mb86960.c revision 1.35 1 1.35 itojun /* $NetBSD: mb86960.c,v 1.35 1999/09/13 10:31:35 itojun Exp $ */
2 1.19 perry
3 1.1 mycroft /*
4 1.1 mycroft * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
5 1.1 mycroft *
6 1.1 mycroft * This software may be used, modified, copied, distributed, and sold, in
7 1.1 mycroft * both source and binary form provided that the above copyright, these
8 1.1 mycroft * terms and the following disclaimer are retained. The name of the author
9 1.1 mycroft * and/or the contributor may not be used to endorse or promote products
10 1.1 mycroft * derived from this software without specific prior written permission.
11 1.1 mycroft *
12 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
13 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
16 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
19 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22 1.1 mycroft * SUCH DAMAGE.
23 1.1 mycroft */
24 1.1 mycroft
25 1.1 mycroft /*
26 1.1 mycroft * Portions copyright (C) 1993, David Greenman. This software may be used,
27 1.1 mycroft * modified, copied, distributed, and sold, in both source and binary form
28 1.1 mycroft * provided that the above copyright and these terms are retained. Under no
29 1.1 mycroft * circumstances is the author responsible for the proper functioning of this
30 1.1 mycroft * software, nor does the author assume any responsibility for damages
31 1.1 mycroft * incurred with its use.
32 1.1 mycroft */
33 1.1 mycroft
34 1.1 mycroft #define FE_VERSION "if_fe.c ver. 0.8"
35 1.1 mycroft
36 1.1 mycroft /*
37 1.1 mycroft * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards.
38 1.1 mycroft * Contributed by M.S. <seki (at) sysrap.cs.fujitsu.co.jp>
39 1.1 mycroft *
40 1.1 mycroft * This version is intended to be a generic template for various
41 1.1 mycroft * MB86960A/MB86965A based Ethernet cards. It currently supports
42 1.1 mycroft * Fujitsu FMV-180 series (i.e., FMV-181 and FMV-182) and Allied-
43 1.1 mycroft * Telesis AT1700 series and RE2000 series. There are some
44 1.1 mycroft * unnecessary hooks embedded, which are primarily intended to support
45 1.1 mycroft * other types of Ethernet cards, but the author is not sure whether
46 1.1 mycroft * they are useful.
47 1.1 mycroft */
48 1.1 mycroft
49 1.25 jonathan #include "opt_inet.h"
50 1.26 jonathan #include "opt_ns.h"
51 1.1 mycroft #include "bpfilter.h"
52 1.18 explorer #include "rnd.h"
53 1.1 mycroft
54 1.1 mycroft #include <sys/param.h>
55 1.1 mycroft #include <sys/systm.h>
56 1.1 mycroft #include <sys/errno.h>
57 1.1 mycroft #include <sys/ioctl.h>
58 1.1 mycroft #include <sys/mbuf.h>
59 1.1 mycroft #include <sys/socket.h>
60 1.1 mycroft #include <sys/syslog.h>
61 1.1 mycroft #include <sys/device.h>
62 1.18 explorer #if NRND > 0
63 1.18 explorer #include <sys/rnd.h>
64 1.18 explorer #endif
65 1.1 mycroft
66 1.1 mycroft #include <net/if.h>
67 1.1 mycroft #include <net/if_dl.h>
68 1.1 mycroft #include <net/if_types.h>
69 1.21 enami #include <net/if_media.h>
70 1.17 is #include <net/if_ether.h>
71 1.1 mycroft
72 1.1 mycroft #ifdef INET
73 1.1 mycroft #include <netinet/in.h>
74 1.1 mycroft #include <netinet/in_systm.h>
75 1.1 mycroft #include <netinet/in_var.h>
76 1.1 mycroft #include <netinet/ip.h>
77 1.17 is #include <netinet/if_inarp.h>
78 1.1 mycroft #endif
79 1.1 mycroft
80 1.1 mycroft #ifdef NS
81 1.1 mycroft #include <netns/ns.h>
82 1.1 mycroft #include <netns/ns_if.h>
83 1.1 mycroft #endif
84 1.1 mycroft
85 1.1 mycroft #if NBPFILTER > 0
86 1.1 mycroft #include <net/bpf.h>
87 1.1 mycroft #include <net/bpfdesc.h>
88 1.1 mycroft #endif
89 1.1 mycroft
90 1.21 enami #include <machine/bus.h>
91 1.1 mycroft
92 1.3 cgd #include <dev/ic/mb86960reg.h>
93 1.21 enami #include <dev/ic/mb86960var.h>
94 1.1 mycroft
95 1.35 itojun #ifndef __BUS_SPACE_HAS_STREAM_METHODS
96 1.35 itojun #define bus_space_write_multi_stream_2 bus_space_write_multi_2
97 1.35 itojun #define bus_space_read_multi_stream_2 bus_space_read_multi_2
98 1.35 itojun #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
99 1.35 itojun
100 1.1 mycroft /* Standard driver entry points. These can be static. */
101 1.21 enami void mb86960_init __P((struct mb86960_softc *));
102 1.21 enami int mb86960_ioctl __P((struct ifnet *, u_long, caddr_t));
103 1.21 enami void mb86960_start __P((struct ifnet *));
104 1.21 enami void mb86960_reset __P((struct mb86960_softc *));
105 1.21 enami void mb86960_watchdog __P((struct ifnet *));
106 1.1 mycroft
107 1.1 mycroft /* Local functions. Order of declaration is confused. FIXME. */
108 1.21 enami int mb86960_get_packet __P((struct mb86960_softc *, int));
109 1.21 enami void mb86960_stop __P((struct mb86960_softc *));
110 1.21 enami void mb86960_tint __P((struct mb86960_softc *, u_char));
111 1.21 enami void mb86960_rint __P((struct mb86960_softc *, u_char));
112 1.21 enami static __inline__
113 1.21 enami void mb86960_xmit __P((struct mb86960_softc *));
114 1.21 enami void mb86960_write_mbufs __P((struct mb86960_softc *, struct mbuf *));
115 1.21 enami static __inline__
116 1.21 enami void mb86960_droppacket __P((struct mb86960_softc *));
117 1.21 enami void mb86960_getmcaf __P((struct ethercom *, u_char *));
118 1.21 enami void mb86960_setmode __P((struct mb86960_softc *));
119 1.21 enami void mb86960_loadmar __P((struct mb86960_softc *));
120 1.1 mycroft
121 1.21 enami int mb86960_mediachange __P((struct ifnet *));
122 1.21 enami void mb86960_mediastatus __P((struct ifnet *, struct ifmediareq *));
123 1.1 mycroft
124 1.21 enami #if FE_DEBUG >= 1
125 1.21 enami void mb86960_dump __P((int, struct mb86960_softc *));
126 1.1 mycroft #endif
127 1.1 mycroft
128 1.1 mycroft void
129 1.21 enami mb86960_attach(sc, type, myea)
130 1.21 enami struct mb86960_softc *sc;
131 1.21 enami enum mb86960_type type;
132 1.21 enami u_int8_t *myea;
133 1.1 mycroft {
134 1.21 enami bus_space_tag_t bst = sc->sc_bst;
135 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
136 1.1 mycroft
137 1.21 enami sc->type = type;
138 1.1 mycroft
139 1.21 enami /* Register values which depend on board design. */
140 1.21 enami sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL;
141 1.21 enami sc->proto_dlcr5 = 0;
142 1.21 enami sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO;
143 1.1 mycroft
144 1.21 enami switch (sc->type) {
145 1.21 enami case MB86960_TYPE_86960:
146 1.21 enami sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC;
147 1.1 mycroft break;
148 1.21 enami case MB86960_TYPE_86965:
149 1.21 enami sc->proto_dlcr7 = FE_D7_BYTSWP_LH;
150 1.1 mycroft break;
151 1.1 mycroft }
152 1.1 mycroft
153 1.1 mycroft /*
154 1.1 mycroft * Program the 86960 as follows:
155 1.1 mycroft * SRAM: 32KB, 100ns, byte-wide access.
156 1.1 mycroft * Transmission buffer: 4KB x 2.
157 1.1 mycroft * System bus interface: 16 bits.
158 1.1 mycroft * We cannot change these values but TXBSIZE, because they
159 1.1 mycroft * are hard-wired on the board. Modifying TXBSIZE will affect
160 1.1 mycroft * the driver performance.
161 1.1 mycroft */
162 1.21 enami sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB |
163 1.21 enami FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;
164 1.1 mycroft
165 1.1 mycroft /*
166 1.1 mycroft * Minimum initialization of the hardware.
167 1.1 mycroft * We write into registers; hope I/O ports have no
168 1.1 mycroft * overlap with other boards.
169 1.1 mycroft */
170 1.1 mycroft
171 1.1 mycroft /* Initialize 86960. */
172 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
173 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
174 1.1 mycroft delay(200);
175 1.1 mycroft
176 1.21 enami #ifdef DIAGNOSTIC
177 1.21 enami if (myea == NULL) {
178 1.21 enami printf("%s: ethernet address shouldn't be NULL\n",
179 1.21 enami sc->sc_dev.dv_xname);
180 1.21 enami panic("NULL ethernet address");
181 1.1 mycroft }
182 1.1 mycroft #endif
183 1.21 enami bcopy(myea, sc->sc_enaddr, sizeof(sc->sc_enaddr));
184 1.1 mycroft
185 1.1 mycroft /* Disable all interrupts. */
186 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR2, 0);
187 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR3, 0);
188 1.1 mycroft }
189 1.1 mycroft
190 1.1 mycroft /*
191 1.1 mycroft * Install interface into kernel networking data structures
192 1.1 mycroft */
193 1.1 mycroft void
194 1.21 enami mb86960_config(sc, media, nmedia, defmedia)
195 1.21 enami struct mb86960_softc *sc;
196 1.21 enami int *media, nmedia, defmedia;
197 1.1 mycroft {
198 1.1 mycroft struct cfdata *cf = sc->sc_dev.dv_cfdata;
199 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
200 1.21 enami int i;
201 1.1 mycroft
202 1.1 mycroft /* Stop the 86960. */
203 1.21 enami mb86960_stop(sc);
204 1.1 mycroft
205 1.1 mycroft /* Initialize ifnet structure. */
206 1.12 thorpej bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
207 1.12 thorpej ifp->if_softc = sc;
208 1.21 enami ifp->if_start = mb86960_start;
209 1.21 enami ifp->if_ioctl = mb86960_ioctl;
210 1.21 enami ifp->if_watchdog = mb86960_watchdog;
211 1.6 mycroft ifp->if_flags =
212 1.6 mycroft IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
213 1.1 mycroft
214 1.1 mycroft #if FE_DEBUG >= 3
215 1.21 enami log(LOG_INFO, "%s: mb86960_config()\n", sc->sc_dev.dv_xname);
216 1.21 enami mb86960_dump(LOG_INFO, sc);
217 1.1 mycroft #endif
218 1.1 mycroft
219 1.1 mycroft #if FE_SINGLE_TRANSMISSION
220 1.1 mycroft /* Override txb config to allocate minimum. */
221 1.1 mycroft sc->proto_dlcr6 &= ~FE_D6_TXBSIZ
222 1.1 mycroft sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB;
223 1.1 mycroft #endif
224 1.1 mycroft
225 1.1 mycroft /* Modify hardware config if it is requested. */
226 1.1 mycroft if ((cf->cf_flags & FE_FLAGS_OVERRIDE_DLCR6) != 0)
227 1.1 mycroft sc->proto_dlcr6 = cf->cf_flags & FE_FLAGS_DLCR6_VALUE;
228 1.1 mycroft
229 1.1 mycroft /* Find TX buffer size, based on the hardware dependent proto. */
230 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) {
231 1.1 mycroft case FE_D6_TXBSIZ_2x2KB:
232 1.1 mycroft sc->txb_size = 2048;
233 1.1 mycroft break;
234 1.1 mycroft case FE_D6_TXBSIZ_2x4KB:
235 1.1 mycroft sc->txb_size = 4096;
236 1.1 mycroft break;
237 1.1 mycroft case FE_D6_TXBSIZ_2x8KB:
238 1.1 mycroft sc->txb_size = 8192;
239 1.1 mycroft break;
240 1.1 mycroft default:
241 1.1 mycroft /* Oops, we can't work with single buffer configuration. */
242 1.1 mycroft #if FE_DEBUG >= 2
243 1.1 mycroft log(LOG_WARNING, "%s: strange TXBSIZ config; fixing\n",
244 1.1 mycroft sc->sc_dev.dv_xname);
245 1.1 mycroft #endif
246 1.1 mycroft sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;
247 1.1 mycroft sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB;
248 1.1 mycroft sc->txb_size = 2048;
249 1.1 mycroft break;
250 1.1 mycroft }
251 1.1 mycroft
252 1.21 enami /* Initialize media goo. */
253 1.21 enami ifmedia_init(&sc->sc_media, 0, mb86960_mediachange,
254 1.21 enami mb86960_mediastatus);
255 1.21 enami if (media != NULL) {
256 1.21 enami for (i = 0; i < nmedia; i++)
257 1.21 enami ifmedia_add(&sc->sc_media, media[i], 0, NULL);
258 1.21 enami ifmedia_set(&sc->sc_media, defmedia);
259 1.21 enami } else {
260 1.21 enami ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
261 1.21 enami ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
262 1.21 enami }
263 1.21 enami
264 1.1 mycroft /* Attach the interface. */
265 1.1 mycroft if_attach(ifp);
266 1.17 is ether_ifattach(ifp, sc->sc_enaddr);
267 1.1 mycroft
268 1.21 enami #if NBPFILTER > 0
269 1.21 enami /* If BPF is in the kernel, call the attach for it. */
270 1.21 enami bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
271 1.21 enami #endif
272 1.21 enami #if NRND > 0
273 1.21 enami rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
274 1.31 explorer RND_TYPE_NET, 0);
275 1.21 enami #endif
276 1.1 mycroft /* Print additional info when attached. */
277 1.21 enami printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
278 1.21 enami ether_sprintf(sc->sc_enaddr));
279 1.21 enami
280 1.1 mycroft #if FE_DEBUG >= 3
281 1.1 mycroft {
282 1.1 mycroft int buf, txb, bbw, sbw, ram;
283 1.1 mycroft
284 1.1 mycroft buf = txb = bbw = sbw = ram = -1;
285 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_BUFSIZ) {
286 1.1 mycroft case FE_D6_BUFSIZ_8KB:
287 1.1 mycroft buf = 8;
288 1.1 mycroft break;
289 1.1 mycroft case FE_D6_BUFSIZ_16KB:
290 1.1 mycroft buf = 16;
291 1.1 mycroft break;
292 1.1 mycroft case FE_D6_BUFSIZ_32KB:
293 1.1 mycroft buf = 32;
294 1.1 mycroft break;
295 1.1 mycroft case FE_D6_BUFSIZ_64KB:
296 1.1 mycroft buf = 64;
297 1.1 mycroft break;
298 1.1 mycroft }
299 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) {
300 1.1 mycroft case FE_D6_TXBSIZ_2x2KB:
301 1.1 mycroft txb = 2;
302 1.1 mycroft break;
303 1.1 mycroft case FE_D6_TXBSIZ_2x4KB:
304 1.1 mycroft txb = 4;
305 1.1 mycroft break;
306 1.1 mycroft case FE_D6_TXBSIZ_2x8KB:
307 1.1 mycroft txb = 8;
308 1.1 mycroft break;
309 1.1 mycroft }
310 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_BBW) {
311 1.1 mycroft case FE_D6_BBW_BYTE:
312 1.1 mycroft bbw = 8;
313 1.1 mycroft break;
314 1.1 mycroft case FE_D6_BBW_WORD:
315 1.1 mycroft bbw = 16;
316 1.1 mycroft break;
317 1.1 mycroft }
318 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_SBW) {
319 1.1 mycroft case FE_D6_SBW_BYTE:
320 1.1 mycroft sbw = 8;
321 1.1 mycroft break;
322 1.1 mycroft case FE_D6_SBW_WORD:
323 1.1 mycroft sbw = 16;
324 1.1 mycroft break;
325 1.1 mycroft }
326 1.1 mycroft switch (sc->proto_dlcr6 & FE_D6_SRAM) {
327 1.1 mycroft case FE_D6_SRAM_100ns:
328 1.1 mycroft ram = 100;
329 1.1 mycroft break;
330 1.1 mycroft case FE_D6_SRAM_150ns:
331 1.1 mycroft ram = 150;
332 1.1 mycroft break;
333 1.1 mycroft }
334 1.15 christos printf("%s: SRAM %dKB %dbit %dns, TXB %dKBx2, %dbit I/O\n",
335 1.1 mycroft sc->sc_dev.dv_xname, buf, bbw, ram, txb, sbw);
336 1.1 mycroft }
337 1.1 mycroft #endif
338 1.21 enami }
339 1.21 enami
340 1.21 enami /*
341 1.21 enami * Media change callback.
342 1.21 enami */
343 1.21 enami int
344 1.21 enami mb86960_mediachange(ifp)
345 1.21 enami struct ifnet *ifp;
346 1.21 enami {
347 1.21 enami struct mb86960_softc *sc = ifp->if_softc;
348 1.1 mycroft
349 1.21 enami if (sc->sc_mediachange)
350 1.21 enami return ((*sc->sc_mediachange)(sc));
351 1.34 abs return (0);
352 1.21 enami }
353 1.1 mycroft
354 1.21 enami /*
355 1.21 enami * Media status callback.
356 1.21 enami */
357 1.21 enami void
358 1.21 enami mb86960_mediastatus(ifp, ifmr)
359 1.21 enami struct ifnet *ifp;
360 1.21 enami struct ifmediareq *ifmr;
361 1.21 enami {
362 1.21 enami struct mb86960_softc *sc = ifp->if_softc;
363 1.18 explorer
364 1.21 enami if (sc->sc_enabled == 0) {
365 1.21 enami ifmr->ifm_active = IFM_ETHER | IFM_NONE;
366 1.21 enami ifmr->ifm_status = 0;
367 1.21 enami return;
368 1.21 enami }
369 1.21 enami
370 1.21 enami if (sc->sc_mediastatus)
371 1.21 enami (*sc->sc_mediastatus)(sc, ifmr);
372 1.1 mycroft }
373 1.1 mycroft
374 1.1 mycroft /*
375 1.1 mycroft * Reset interface.
376 1.1 mycroft */
377 1.1 mycroft void
378 1.21 enami mb86960_reset(sc)
379 1.21 enami struct mb86960_softc *sc;
380 1.1 mycroft {
381 1.1 mycroft int s;
382 1.1 mycroft
383 1.8 mycroft s = splnet();
384 1.21 enami mb86960_stop(sc);
385 1.21 enami mb86960_init(sc);
386 1.1 mycroft splx(s);
387 1.1 mycroft }
388 1.1 mycroft
389 1.1 mycroft /*
390 1.1 mycroft * Stop everything on the interface.
391 1.1 mycroft *
392 1.1 mycroft * All buffered packets, both transmitting and receiving,
393 1.1 mycroft * if any, will be lost by stopping the interface.
394 1.1 mycroft */
395 1.1 mycroft void
396 1.21 enami mb86960_stop(sc)
397 1.21 enami struct mb86960_softc *sc;
398 1.1 mycroft {
399 1.21 enami bus_space_tag_t bst = sc->sc_bst;
400 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
401 1.1 mycroft
402 1.1 mycroft #if FE_DEBUG >= 3
403 1.21 enami log(LOG_INFO, "%s: top of mb86960_stop()\n", sc->sc_dev.dv_xname);
404 1.21 enami mb86960_dump(LOG_INFO, sc);
405 1.1 mycroft #endif
406 1.1 mycroft
407 1.1 mycroft /* Disable interrupts. */
408 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR2, 0x00);
409 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR3, 0x00);
410 1.1 mycroft
411 1.1 mycroft /* Stop interface hardware. */
412 1.1 mycroft delay(200);
413 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
414 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
415 1.1 mycroft delay(200);
416 1.1 mycroft
417 1.1 mycroft /* Clear all interrupt status. */
418 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, 0xFF);
419 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR1, 0xFF);
420 1.1 mycroft
421 1.1 mycroft /* Put the chip in stand-by mode. */
422 1.1 mycroft delay(200);
423 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
424 1.21 enami sc->proto_dlcr7 | FE_D7_POWER_DOWN);
425 1.1 mycroft delay(200);
426 1.1 mycroft
427 1.1 mycroft /* MAR loading can be delayed. */
428 1.1 mycroft sc->filter_change = 0;
429 1.1 mycroft
430 1.1 mycroft /* Call a hook. */
431 1.21 enami if (sc->stop_card)
432 1.21 enami (*sc->stop_card)(sc);
433 1.1 mycroft
434 1.1 mycroft #if DEBUG >= 3
435 1.21 enami log(LOG_INFO, "%s: end of mb86960_stop()\n", sc->sc_dev.dv_xname);
436 1.21 enami mb86960_dump(LOG_INFO, sc);
437 1.1 mycroft #endif
438 1.1 mycroft }
439 1.1 mycroft
440 1.1 mycroft /*
441 1.1 mycroft * Device timeout/watchdog routine. Entered if the device neglects to
442 1.1 mycroft * generate an interrupt after a transmit has been started on it.
443 1.1 mycroft */
444 1.1 mycroft void
445 1.21 enami mb86960_watchdog(ifp)
446 1.12 thorpej struct ifnet *ifp;
447 1.1 mycroft {
448 1.21 enami struct mb86960_softc *sc = ifp->if_softc;
449 1.1 mycroft
450 1.1 mycroft log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
451 1.1 mycroft #if FE_DEBUG >= 3
452 1.21 enami mb86960_dump(LOG_INFO, sc);
453 1.1 mycroft #endif
454 1.1 mycroft
455 1.1 mycroft /* Record how many packets are lost by this accident. */
456 1.21 enami sc->sc_ec.ec_if.if_oerrors += sc->txb_sched + sc->txb_count;
457 1.1 mycroft
458 1.21 enami mb86960_reset(sc);
459 1.1 mycroft }
460 1.1 mycroft
461 1.1 mycroft /*
462 1.6 mycroft * Drop (skip) a packet from receive buffer in 86960 memory.
463 1.6 mycroft */
464 1.21 enami static __inline__ void
465 1.21 enami mb86960_droppacket(sc)
466 1.21 enami struct mb86960_softc *sc;
467 1.6 mycroft {
468 1.21 enami bus_space_tag_t bst = sc->sc_bst;
469 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
470 1.6 mycroft
471 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR14, FE_B14_FILTER | FE_B14_SKIP);
472 1.6 mycroft }
473 1.6 mycroft
474 1.6 mycroft /*
475 1.1 mycroft * Initialize device.
476 1.1 mycroft */
477 1.1 mycroft void
478 1.21 enami mb86960_init(sc)
479 1.21 enami struct mb86960_softc *sc;
480 1.1 mycroft {
481 1.21 enami bus_space_tag_t bst = sc->sc_bst;
482 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
483 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
484 1.5 mycroft int i;
485 1.1 mycroft
486 1.1 mycroft #if FE_DEBUG >= 3
487 1.21 enami log(LOG_INFO, "%s: top of mb86960_init()\n", sc->sc_dev.dv_xname);
488 1.21 enami mb86960_dump(LOG_INFO, sc);
489 1.1 mycroft #endif
490 1.1 mycroft
491 1.1 mycroft /* Reset transmitter flags. */
492 1.1 mycroft ifp->if_flags &= ~IFF_OACTIVE;
493 1.1 mycroft ifp->if_timer = 0;
494 1.1 mycroft
495 1.1 mycroft sc->txb_free = sc->txb_size;
496 1.1 mycroft sc->txb_count = 0;
497 1.1 mycroft sc->txb_sched = 0;
498 1.1 mycroft
499 1.21 enami /* Do any card-specific initialization, if applicable. */
500 1.21 enami if (sc->init_card)
501 1.21 enami (*sc->init_card)(sc);
502 1.1 mycroft
503 1.1 mycroft #if FE_DEBUG >= 3
504 1.1 mycroft log(LOG_INFO, "%s: after init hook\n", sc->sc_dev.dv_xname);
505 1.21 enami mb86960_dump(LOG_INFO, sc);
506 1.1 mycroft #endif
507 1.1 mycroft
508 1.1 mycroft /*
509 1.1 mycroft * Make sure to disable the chip, also.
510 1.1 mycroft * This may also help re-programming the chip after
511 1.1 mycroft * hot insertion of PCMCIAs.
512 1.1 mycroft */
513 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
514 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
515 1.21 enami delay(200);
516 1.1 mycroft
517 1.1 mycroft /* Power up the chip and select register bank for DLCRs. */
518 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
519 1.1 mycroft sc->proto_dlcr7 | FE_D7_RBS_DLCR | FE_D7_POWER_UP);
520 1.1 mycroft delay(200);
521 1.1 mycroft
522 1.1 mycroft /* Feed the station address. */
523 1.21 enami bus_space_write_region_1(bst, bsh, FE_DLCR8,
524 1.21 enami sc->sc_enaddr, ETHER_ADDR_LEN);
525 1.1 mycroft
526 1.1 mycroft /* Select the BMPR bank for runtime register access. */
527 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
528 1.1 mycroft sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
529 1.1 mycroft
530 1.1 mycroft /* Initialize registers. */
531 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, 0xFF); /* Clear all bits. */
532 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR1, 0xFF); /* ditto. */
533 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR2, 0x00);
534 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR3, 0x00);
535 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR4, sc->proto_dlcr4);
536 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR5, sc->proto_dlcr5);
537 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR10, 0x00);
538 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR11, FE_B11_CTRL_SKIP);
539 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR12, 0x00);
540 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR13, sc->proto_bmpr13);
541 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR14, FE_B14_FILTER);
542 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR15, 0x00);
543 1.1 mycroft
544 1.1 mycroft #if FE_DEBUG >= 3
545 1.1 mycroft log(LOG_INFO, "%s: just before enabling DLC\n", sc->sc_dev.dv_xname);
546 1.21 enami mb86960_dump(LOG_INFO, sc);
547 1.1 mycroft #endif
548 1.1 mycroft
549 1.1 mycroft /* Enable interrupts. */
550 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR2, FE_TMASK);
551 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR3, FE_RMASK);
552 1.1 mycroft
553 1.1 mycroft /* Enable transmitter and receiver. */
554 1.1 mycroft delay(200);
555 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
556 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_ENABLE);
557 1.1 mycroft delay(200);
558 1.1 mycroft
559 1.1 mycroft #if FE_DEBUG >= 3
560 1.1 mycroft log(LOG_INFO, "%s: just after enabling DLC\n", sc->sc_dev.dv_xname);
561 1.21 enami mb86960_dump(LOG_INFO, sc);
562 1.1 mycroft #endif
563 1.1 mycroft
564 1.1 mycroft /*
565 1.1 mycroft * Make sure to empty the receive buffer.
566 1.1 mycroft *
567 1.1 mycroft * This may be redundant, but *if* the receive buffer were full
568 1.1 mycroft * at this point, the driver would hang. I have experienced
569 1.1 mycroft * some strange hangups just after UP. I hope the following
570 1.1 mycroft * code solve the problem.
571 1.1 mycroft *
572 1.1 mycroft * I have changed the order of hardware initialization.
573 1.1 mycroft * I think the receive buffer cannot have any packets at this
574 1.1 mycroft * point in this version. The following code *must* be
575 1.1 mycroft * redundant now. FIXME.
576 1.1 mycroft */
577 1.1 mycroft for (i = 0; i < FE_MAX_RECV_COUNT; i++) {
578 1.21 enami if (bus_space_read_1(bst, bsh, FE_DLCR5) & FE_D5_BUFEMP)
579 1.1 mycroft break;
580 1.21 enami mb86960_droppacket(sc);
581 1.1 mycroft }
582 1.1 mycroft #if FE_DEBUG >= 1
583 1.21 enami if (i >= FE_MAX_RECV_COUNT)
584 1.1 mycroft log(LOG_ERR, "%s: cannot empty receive buffer\n",
585 1.1 mycroft sc->sc_dev.dv_xname);
586 1.1 mycroft #endif
587 1.1 mycroft #if FE_DEBUG >= 3
588 1.21 enami if (i < FE_MAX_RECV_COUNT)
589 1.1 mycroft log(LOG_INFO, "%s: receive buffer emptied (%d)\n",
590 1.1 mycroft sc->sc_dev.dv_xname, i);
591 1.1 mycroft #endif
592 1.1 mycroft
593 1.1 mycroft #if FE_DEBUG >= 3
594 1.1 mycroft log(LOG_INFO, "%s: after ERB loop\n", sc->sc_dev.dv_xname);
595 1.21 enami mb86960_dump(LOG_INFO, sc);
596 1.1 mycroft #endif
597 1.1 mycroft
598 1.1 mycroft /* Do we need this here? */
599 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, 0xFF); /* Clear all bits. */
600 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR1, 0xFF); /* ditto. */
601 1.1 mycroft
602 1.1 mycroft #if FE_DEBUG >= 3
603 1.1 mycroft log(LOG_INFO, "%s: after FIXME\n", sc->sc_dev.dv_xname);
604 1.21 enami mb86960_dump(LOG_INFO, sc);
605 1.1 mycroft #endif
606 1.1 mycroft
607 1.1 mycroft /* Set 'running' flag. */
608 1.1 mycroft ifp->if_flags |= IFF_RUNNING;
609 1.1 mycroft
610 1.1 mycroft /*
611 1.1 mycroft * At this point, the interface is runnung properly,
612 1.1 mycroft * except that it receives *no* packets. we then call
613 1.21 enami * mb86960_setmode() to tell the chip what packets to be
614 1.1 mycroft * received, based on the if_flags and multicast group
615 1.1 mycroft * list. It completes the initialization process.
616 1.1 mycroft */
617 1.21 enami mb86960_setmode(sc);
618 1.1 mycroft
619 1.1 mycroft #if FE_DEBUG >= 3
620 1.1 mycroft log(LOG_INFO, "%s: after setmode\n", sc->sc_dev.dv_xname);
621 1.21 enami mb86960_dump(LOG_INFO, sc);
622 1.1 mycroft #endif
623 1.1 mycroft
624 1.1 mycroft /* ...and attempt to start output. */
625 1.21 enami mb86960_start(ifp);
626 1.1 mycroft
627 1.1 mycroft #if FE_DEBUG >= 3
628 1.21 enami log(LOG_INFO, "%s: end of mb86960_init()\n", sc->sc_dev.dv_xname);
629 1.21 enami mb86960_dump(LOG_INFO, sc);
630 1.1 mycroft #endif
631 1.1 mycroft }
632 1.1 mycroft
633 1.1 mycroft /*
634 1.1 mycroft * This routine actually starts the transmission on the interface
635 1.1 mycroft */
636 1.21 enami static __inline__ void
637 1.21 enami mb86960_xmit(sc)
638 1.21 enami struct mb86960_softc *sc;
639 1.1 mycroft {
640 1.21 enami bus_space_tag_t bst = sc->sc_bst;
641 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
642 1.1 mycroft
643 1.1 mycroft /*
644 1.1 mycroft * Set a timer just in case we never hear from the board again.
645 1.1 mycroft * We use longer timeout for multiple packet transmission.
646 1.1 mycroft * I'm not sure this timer value is appropriate. FIXME.
647 1.1 mycroft */
648 1.21 enami sc->sc_ec.ec_if.if_timer = 1 + sc->txb_count;
649 1.1 mycroft
650 1.1 mycroft /* Update txb variables. */
651 1.1 mycroft sc->txb_sched = sc->txb_count;
652 1.1 mycroft sc->txb_count = 0;
653 1.1 mycroft sc->txb_free = sc->txb_size;
654 1.1 mycroft
655 1.1 mycroft #if FE_DELAYED_PADDING
656 1.1 mycroft /* Omit the postponed padding process. */
657 1.1 mycroft sc->txb_padding = 0;
658 1.1 mycroft #endif
659 1.1 mycroft
660 1.1 mycroft /* Start transmitter, passing packets in TX buffer. */
661 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR10, sc->txb_sched | FE_B10_START);
662 1.1 mycroft }
663 1.1 mycroft
664 1.1 mycroft /*
665 1.1 mycroft * Start output on interface.
666 1.1 mycroft * We make two assumptions here:
667 1.8 mycroft * 1) that the current priority is set to splnet _before_ this code
668 1.1 mycroft * is called *and* is returned to the appropriate priority after
669 1.1 mycroft * return
670 1.1 mycroft * 2) that the IFF_OACTIVE flag is checked before this code is called
671 1.1 mycroft * (i.e. that the output part of the interface is idle)
672 1.1 mycroft */
673 1.1 mycroft void
674 1.21 enami mb86960_start(ifp)
675 1.1 mycroft struct ifnet *ifp;
676 1.1 mycroft {
677 1.21 enami struct mb86960_softc *sc = ifp->if_softc;
678 1.1 mycroft struct mbuf *m;
679 1.1 mycroft
680 1.1 mycroft #if FE_DEBUG >= 1
681 1.1 mycroft /* Just a sanity check. */
682 1.1 mycroft if ((sc->txb_count == 0) != (sc->txb_free == sc->txb_size)) {
683 1.1 mycroft /*
684 1.1 mycroft * Txb_count and txb_free co-works to manage the
685 1.1 mycroft * transmission buffer. Txb_count keeps track of the
686 1.1 mycroft * used potion of the buffer, while txb_free does unused
687 1.1 mycroft * potion. So, as long as the driver runs properly,
688 1.1 mycroft * txb_count is zero if and only if txb_free is same
689 1.1 mycroft * as txb_size (which represents whole buffer.)
690 1.1 mycroft */
691 1.1 mycroft log(LOG_ERR, "%s: inconsistent txb variables (%d, %d)\n",
692 1.1 mycroft sc->sc_dev.dv_xname, sc->txb_count, sc->txb_free);
693 1.1 mycroft /*
694 1.1 mycroft * So, what should I do, then?
695 1.1 mycroft *
696 1.1 mycroft * We now know txb_count and txb_free contradicts. We
697 1.1 mycroft * cannot, however, tell which is wrong. More
698 1.1 mycroft * over, we cannot peek 86960 transmission buffer or
699 1.1 mycroft * reset the transmission buffer. (In fact, we can
700 1.1 mycroft * reset the entire interface. I don't want to do it.)
701 1.1 mycroft *
702 1.1 mycroft * If txb_count is incorrect, leaving it as is will cause
703 1.1 mycroft * sending of gabages after next interrupt. We have to
704 1.1 mycroft * avoid it. Hence, we reset the txb_count here. If
705 1.1 mycroft * txb_free was incorrect, resetting txb_count just loose
706 1.1 mycroft * some packets. We can live with it.
707 1.1 mycroft */
708 1.1 mycroft sc->txb_count = 0;
709 1.1 mycroft }
710 1.1 mycroft #endif
711 1.1 mycroft
712 1.1 mycroft #if FE_DEBUG >= 1
713 1.1 mycroft /*
714 1.1 mycroft * First, see if there are buffered packets and an idle
715 1.1 mycroft * transmitter - should never happen at this point.
716 1.1 mycroft */
717 1.1 mycroft if ((sc->txb_count > 0) && (sc->txb_sched == 0)) {
718 1.1 mycroft log(LOG_ERR, "%s: transmitter idle with %d buffered packets\n",
719 1.1 mycroft sc->sc_dev.dv_xname, sc->txb_count);
720 1.21 enami mb86960_xmit(sc);
721 1.1 mycroft }
722 1.1 mycroft #endif
723 1.1 mycroft
724 1.1 mycroft /*
725 1.1 mycroft * Stop accepting more transmission packets temporarily, when
726 1.1 mycroft * a filter change request is delayed. Updating the MARs on
727 1.1 mycroft * 86960 flushes the transmisstion buffer, so it is delayed
728 1.1 mycroft * until all buffered transmission packets have been sent
729 1.1 mycroft * out.
730 1.1 mycroft */
731 1.1 mycroft if (sc->filter_change) {
732 1.1 mycroft /*
733 1.1 mycroft * Filter change requst is delayed only when the DLC is
734 1.1 mycroft * working. DLC soon raise an interrupt after finishing
735 1.1 mycroft * the work.
736 1.1 mycroft */
737 1.1 mycroft goto indicate_active;
738 1.1 mycroft }
739 1.1 mycroft
740 1.1 mycroft for (;;) {
741 1.1 mycroft /*
742 1.1 mycroft * See if there is room to put another packet in the buffer.
743 1.1 mycroft * We *could* do better job by peeking the send queue to
744 1.1 mycroft * know the length of the next packet. Current version just
745 1.1 mycroft * tests against the worst case (i.e., longest packet). FIXME.
746 1.1 mycroft *
747 1.1 mycroft * When adding the packet-peek feature, don't forget adding a
748 1.1 mycroft * test on txb_count against QUEUEING_MAX.
749 1.1 mycroft * There is a little chance the packet count exceeds
750 1.1 mycroft * the limit. Assume transmission buffer is 8KB (2x8KB
751 1.1 mycroft * configuration) and an application sends a bunch of small
752 1.1 mycroft * (i.e., minimum packet sized) packets rapidly. An 8KB
753 1.1 mycroft * buffer can hold 130 blocks of 62 bytes long...
754 1.1 mycroft */
755 1.32 thorpej if (sc->txb_free <
756 1.32 thorpej (ETHER_MAX_LEN - ETHER_CRC_LEN) + FE_DATA_LEN_LEN) {
757 1.1 mycroft /* No room. */
758 1.1 mycroft goto indicate_active;
759 1.1 mycroft }
760 1.1 mycroft
761 1.1 mycroft #if FE_SINGLE_TRANSMISSION
762 1.1 mycroft if (sc->txb_count > 0) {
763 1.1 mycroft /* Just one packet per a transmission buffer. */
764 1.1 mycroft goto indicate_active;
765 1.1 mycroft }
766 1.1 mycroft #endif
767 1.1 mycroft
768 1.1 mycroft /*
769 1.1 mycroft * Get the next mbuf chain for a packet to send.
770 1.1 mycroft */
771 1.1 mycroft IF_DEQUEUE(&ifp->if_snd, m);
772 1.1 mycroft if (m == 0) {
773 1.1 mycroft /* No more packets to send. */
774 1.1 mycroft goto indicate_inactive;
775 1.1 mycroft }
776 1.1 mycroft
777 1.6 mycroft #if NBPFILTER > 0
778 1.6 mycroft /* Tap off here if there is a BPF listener. */
779 1.6 mycroft if (ifp->if_bpf)
780 1.6 mycroft bpf_mtap(ifp->if_bpf, m);
781 1.6 mycroft #endif
782 1.6 mycroft
783 1.1 mycroft /*
784 1.1 mycroft * Copy the mbuf chain into the transmission buffer.
785 1.1 mycroft * txb_* variables are updated as necessary.
786 1.1 mycroft */
787 1.21 enami mb86960_write_mbufs(sc, m);
788 1.1 mycroft
789 1.6 mycroft m_freem(m);
790 1.6 mycroft
791 1.1 mycroft /* Start transmitter if it's idle. */
792 1.1 mycroft if (sc->txb_sched == 0)
793 1.21 enami mb86960_xmit(sc);
794 1.1 mycroft }
795 1.1 mycroft
796 1.1 mycroft indicate_inactive:
797 1.1 mycroft /*
798 1.1 mycroft * We are using the !OACTIVE flag to indicate to
799 1.1 mycroft * the outside world that we can accept an
800 1.1 mycroft * additional packet rather than that the
801 1.1 mycroft * transmitter is _actually_ active. Indeed, the
802 1.1 mycroft * transmitter may be active, but if we haven't
803 1.1 mycroft * filled all the buffers with data then we still
804 1.1 mycroft * want to accept more.
805 1.1 mycroft */
806 1.1 mycroft ifp->if_flags &= ~IFF_OACTIVE;
807 1.1 mycroft return;
808 1.1 mycroft
809 1.1 mycroft indicate_active:
810 1.1 mycroft /*
811 1.1 mycroft * The transmitter is active, and there are no room for
812 1.1 mycroft * more outgoing packets in the transmission buffer.
813 1.1 mycroft */
814 1.1 mycroft ifp->if_flags |= IFF_OACTIVE;
815 1.1 mycroft return;
816 1.1 mycroft }
817 1.1 mycroft
818 1.1 mycroft /*
819 1.1 mycroft * Transmission interrupt handler
820 1.1 mycroft * The control flow of this function looks silly. FIXME.
821 1.1 mycroft */
822 1.1 mycroft void
823 1.21 enami mb86960_tint(sc, tstat)
824 1.21 enami struct mb86960_softc *sc;
825 1.1 mycroft u_char tstat;
826 1.1 mycroft {
827 1.21 enami bus_space_tag_t bst = sc->sc_bst;
828 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
829 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
830 1.1 mycroft int left;
831 1.1 mycroft int col;
832 1.1 mycroft
833 1.1 mycroft /*
834 1.1 mycroft * Handle "excessive collision" interrupt.
835 1.1 mycroft */
836 1.1 mycroft if (tstat & FE_D0_COLL16) {
837 1.1 mycroft /*
838 1.1 mycroft * Find how many packets (including this collided one)
839 1.1 mycroft * are left unsent in transmission buffer.
840 1.1 mycroft */
841 1.21 enami left = bus_space_read_1(bst, bsh, FE_BMPR10);
842 1.1 mycroft
843 1.1 mycroft #if FE_DEBUG >= 2
844 1.1 mycroft log(LOG_WARNING, "%s: excessive collision (%d/%d)\n",
845 1.1 mycroft sc->sc_dev.dv_xname, left, sc->txb_sched);
846 1.1 mycroft #endif
847 1.1 mycroft #if FE_DEBUG >= 3
848 1.21 enami mb86960_dump(LOG_INFO, sc);
849 1.1 mycroft #endif
850 1.1 mycroft
851 1.1 mycroft /*
852 1.1 mycroft * Update statistics.
853 1.1 mycroft */
854 1.1 mycroft ifp->if_collisions += 16;
855 1.1 mycroft ifp->if_oerrors++;
856 1.1 mycroft ifp->if_opackets += sc->txb_sched - left;
857 1.1 mycroft
858 1.1 mycroft /*
859 1.1 mycroft * Collision statistics has been updated.
860 1.1 mycroft * Clear the collision flag on 86960 now to avoid confusion.
861 1.1 mycroft */
862 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, FE_D0_COLLID);
863 1.1 mycroft
864 1.1 mycroft /*
865 1.1 mycroft * Restart transmitter, skipping the
866 1.1 mycroft * collided packet.
867 1.1 mycroft *
868 1.1 mycroft * We *must* skip the packet to keep network running
869 1.1 mycroft * properly. Excessive collision error is an
870 1.1 mycroft * indication of the network overload. If we
871 1.1 mycroft * tried sending the same packet after excessive
872 1.1 mycroft * collision, the network would be filled with
873 1.1 mycroft * out-of-time packets. Packets belonging
874 1.1 mycroft * to reliable transport (such as TCP) are resent
875 1.1 mycroft * by some upper layer.
876 1.1 mycroft */
877 1.21 enami bus_space_write_1(bst, bsh, FE_BMPR11,
878 1.1 mycroft FE_B11_CTRL_SKIP | FE_B11_MODE1);
879 1.1 mycroft sc->txb_sched = left - 1;
880 1.1 mycroft }
881 1.1 mycroft
882 1.1 mycroft /*
883 1.1 mycroft * Handle "transmission complete" interrupt.
884 1.1 mycroft */
885 1.1 mycroft if (tstat & FE_D0_TXDONE) {
886 1.1 mycroft /*
887 1.1 mycroft * Add in total number of collisions on last
888 1.1 mycroft * transmission. We also clear "collision occurred" flag
889 1.1 mycroft * here.
890 1.1 mycroft *
891 1.1 mycroft * 86960 has a design flow on collision count on multiple
892 1.1 mycroft * packet transmission. When we send two or more packets
893 1.1 mycroft * with one start command (that's what we do when the
894 1.1 mycroft * transmission queue is clauded), 86960 informs us number
895 1.1 mycroft * of collisions occured on the last packet on the
896 1.1 mycroft * transmission only. Number of collisions on previous
897 1.1 mycroft * packets are lost. I have told that the fact is clearly
898 1.1 mycroft * stated in the Fujitsu document.
899 1.1 mycroft *
900 1.1 mycroft * I considered not to mind it seriously. Collision
901 1.1 mycroft * count is not so important, anyway. Any comments? FIXME.
902 1.1 mycroft */
903 1.1 mycroft
904 1.21 enami if (bus_space_read_1(bst, bsh, FE_DLCR0) & FE_D0_COLLID) {
905 1.1 mycroft /* Clear collision flag. */
906 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, FE_D0_COLLID);
907 1.1 mycroft
908 1.1 mycroft /* Extract collision count from 86960. */
909 1.21 enami col = bus_space_read_1(bst, bsh, FE_DLCR4) & FE_D4_COL;
910 1.1 mycroft if (col == 0) {
911 1.1 mycroft /*
912 1.1 mycroft * Status register indicates collisions,
913 1.1 mycroft * while the collision count is zero.
914 1.1 mycroft * This can happen after multiple packet
915 1.1 mycroft * transmission, indicating that one or more
916 1.1 mycroft * previous packet(s) had been collided.
917 1.1 mycroft *
918 1.1 mycroft * Since the accurate number of collisions
919 1.1 mycroft * has been lost, we just guess it as 1;
920 1.1 mycroft * Am I too optimistic? FIXME.
921 1.1 mycroft */
922 1.1 mycroft col = 1;
923 1.1 mycroft } else
924 1.1 mycroft col >>= FE_D4_COL_SHIFT;
925 1.1 mycroft ifp->if_collisions += col;
926 1.1 mycroft #if FE_DEBUG >= 4
927 1.1 mycroft log(LOG_WARNING, "%s: %d collision%s (%d)\n",
928 1.1 mycroft sc->sc_dev.dv_xname, col, col == 1 ? "" : "s",
929 1.1 mycroft sc->txb_sched);
930 1.1 mycroft #endif
931 1.1 mycroft }
932 1.1 mycroft
933 1.1 mycroft /*
934 1.1 mycroft * Update total number of successfully
935 1.1 mycroft * transmitted packets.
936 1.1 mycroft */
937 1.1 mycroft ifp->if_opackets += sc->txb_sched;
938 1.1 mycroft sc->txb_sched = 0;
939 1.10 mycroft }
940 1.1 mycroft
941 1.10 mycroft if (sc->txb_sched == 0) {
942 1.1 mycroft /*
943 1.1 mycroft * The transmitter is no more active.
944 1.1 mycroft * Reset output active flag and watchdog timer.
945 1.1 mycroft */
946 1.1 mycroft ifp->if_flags &= ~IFF_OACTIVE;
947 1.1 mycroft ifp->if_timer = 0;
948 1.1 mycroft
949 1.1 mycroft /*
950 1.1 mycroft * If more data is ready to transmit in the buffer, start
951 1.1 mycroft * transmitting them. Otherwise keep transmitter idle,
952 1.1 mycroft * even if more data is queued. This gives receive
953 1.1 mycroft * process a slight priority.
954 1.1 mycroft */
955 1.1 mycroft if (sc->txb_count > 0)
956 1.21 enami mb86960_xmit(sc);
957 1.1 mycroft }
958 1.1 mycroft }
959 1.1 mycroft
960 1.1 mycroft /*
961 1.1 mycroft * Ethernet interface receiver interrupt.
962 1.1 mycroft */
963 1.1 mycroft void
964 1.21 enami mb86960_rint(sc, rstat)
965 1.21 enami struct mb86960_softc *sc;
966 1.1 mycroft u_char rstat;
967 1.1 mycroft {
968 1.21 enami bus_space_tag_t bst = sc->sc_bst;
969 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
970 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
971 1.1 mycroft int len;
972 1.1 mycroft u_char status;
973 1.1 mycroft int i;
974 1.1 mycroft
975 1.1 mycroft /*
976 1.1 mycroft * Update statistics if this interrupt is caused by an error.
977 1.1 mycroft */
978 1.21 enami if (rstat & (FE_D1_OVRFLO | FE_D1_CRCERR | FE_D1_ALGERR |
979 1.21 enami FE_D1_SRTPKT)) {
980 1.1 mycroft #if FE_DEBUG >= 3
981 1.1 mycroft log(LOG_WARNING, "%s: receive error: %b\n",
982 1.1 mycroft sc->sc_dev.dv_xname, rstat, FE_D1_ERRBITS);
983 1.1 mycroft #endif
984 1.1 mycroft ifp->if_ierrors++;
985 1.1 mycroft }
986 1.1 mycroft
987 1.1 mycroft /*
988 1.1 mycroft * MB86960 has a flag indicating "receive queue empty."
989 1.1 mycroft * We just loop cheking the flag to pull out all received
990 1.1 mycroft * packets.
991 1.1 mycroft *
992 1.1 mycroft * We limit the number of iterrations to avoid infinite loop.
993 1.1 mycroft * It can be caused by a very slow CPU (some broken
994 1.1 mycroft * peripheral may insert incredible number of wait cycles)
995 1.1 mycroft * or, worse, by a broken MB86960 chip.
996 1.1 mycroft */
997 1.1 mycroft for (i = 0; i < FE_MAX_RECV_COUNT; i++) {
998 1.1 mycroft /* Stop the iterration if 86960 indicates no packets. */
999 1.21 enami if (bus_space_read_1(bst, bsh, FE_DLCR5) & FE_D5_BUFEMP)
1000 1.1 mycroft break;
1001 1.1 mycroft
1002 1.1 mycroft /*
1003 1.1 mycroft * Extract A receive status byte.
1004 1.1 mycroft * As our 86960 is in 16 bit bus access mode, we have to
1005 1.1 mycroft * use inw() to get the status byte. The significant
1006 1.1 mycroft * value is returned in lower 8 bits.
1007 1.1 mycroft */
1008 1.21 enami status = (u_char)bus_space_read_2(bst, bsh, FE_BMPR8);
1009 1.1 mycroft #if FE_DEBUG >= 4
1010 1.1 mycroft log(LOG_INFO, "%s: receive status = %02x\n",
1011 1.1 mycroft sc->sc_dev.dv_xname, status);
1012 1.1 mycroft #endif
1013 1.1 mycroft
1014 1.1 mycroft /*
1015 1.1 mycroft * If there was an error, update statistics and drop
1016 1.1 mycroft * the packet, unless the interface is in promiscuous
1017 1.1 mycroft * mode.
1018 1.1 mycroft */
1019 1.1 mycroft if ((status & 0xF0) != 0x20) { /* XXXX ? */
1020 1.1 mycroft if ((ifp->if_flags & IFF_PROMISC) == 0) {
1021 1.1 mycroft ifp->if_ierrors++;
1022 1.21 enami mb86960_droppacket(sc);
1023 1.1 mycroft continue;
1024 1.1 mycroft }
1025 1.1 mycroft }
1026 1.1 mycroft
1027 1.1 mycroft /*
1028 1.1 mycroft * Extract the packet length.
1029 1.1 mycroft * It is a sum of a header (14 bytes) and a payload.
1030 1.1 mycroft * CRC has been stripped off by the 86960.
1031 1.1 mycroft */
1032 1.21 enami len = bus_space_read_2(bst, bsh, FE_BMPR8);
1033 1.1 mycroft
1034 1.1 mycroft /*
1035 1.1 mycroft * MB86965 checks the packet length and drop big packet
1036 1.1 mycroft * before passing it to us. There are no chance we can
1037 1.1 mycroft * get [crufty] packets. Hence, if the length exceeds
1038 1.1 mycroft * the specified limit, it means some serious failure,
1039 1.1 mycroft * such as out-of-sync on receive buffer management.
1040 1.1 mycroft *
1041 1.1 mycroft * Is this statement true? FIXME.
1042 1.1 mycroft */
1043 1.32 thorpej if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) ||
1044 1.32 thorpej len < ETHER_HDR_LEN) {
1045 1.1 mycroft #if FE_DEBUG >= 2
1046 1.1 mycroft log(LOG_WARNING,
1047 1.1 mycroft "%s: received a %s packet? (%u bytes)\n",
1048 1.1 mycroft sc->sc_dev.dv_xname,
1049 1.32 thorpej len < ETHER_HDR_LEN ? "partial" : "big", len);
1050 1.1 mycroft #endif
1051 1.1 mycroft ifp->if_ierrors++;
1052 1.21 enami mb86960_droppacket(sc);
1053 1.1 mycroft continue;
1054 1.1 mycroft }
1055 1.1 mycroft
1056 1.1 mycroft /*
1057 1.1 mycroft * Check for a short (RUNT) packet. We *do* check
1058 1.1 mycroft * but do nothing other than print a message.
1059 1.1 mycroft * Short packets are illegal, but does nothing bad
1060 1.1 mycroft * if it carries data for upper layer.
1061 1.1 mycroft */
1062 1.1 mycroft #if FE_DEBUG >= 2
1063 1.32 thorpej if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
1064 1.1 mycroft log(LOG_WARNING,
1065 1.21 enami "%s: received a short packet? (%u bytes)\n",
1066 1.21 enami sc->sc_dev.dv_xname, len);
1067 1.1 mycroft }
1068 1.1 mycroft #endif
1069 1.1 mycroft
1070 1.1 mycroft /*
1071 1.1 mycroft * Go get a packet.
1072 1.1 mycroft */
1073 1.21 enami if (!mb86960_get_packet(sc, len)) {
1074 1.1 mycroft /* Skip a packet, updating statistics. */
1075 1.1 mycroft #if FE_DEBUG >= 2
1076 1.1 mycroft log(LOG_WARNING,
1077 1.1 mycroft "%s: out of mbufs; dropping packet (%u bytes)\n",
1078 1.1 mycroft sc->sc_dev.dv_xname, len);
1079 1.1 mycroft #endif
1080 1.1 mycroft ifp->if_ierrors++;
1081 1.21 enami mb86960_droppacket(sc);
1082 1.1 mycroft
1083 1.1 mycroft /*
1084 1.1 mycroft * We stop receiving packets, even if there are
1085 1.1 mycroft * more in the buffer. We hope we can get more
1086 1.1 mycroft * mbufs next time.
1087 1.1 mycroft */
1088 1.1 mycroft return;
1089 1.1 mycroft }
1090 1.1 mycroft
1091 1.1 mycroft /* Successfully received a packet. Update stat. */
1092 1.1 mycroft ifp->if_ipackets++;
1093 1.1 mycroft }
1094 1.1 mycroft }
1095 1.1 mycroft
1096 1.1 mycroft /*
1097 1.1 mycroft * Ethernet interface interrupt processor
1098 1.1 mycroft */
1099 1.1 mycroft int
1100 1.21 enami mb86960_intr(arg)
1101 1.1 mycroft void *arg;
1102 1.1 mycroft {
1103 1.21 enami struct mb86960_softc *sc = arg;
1104 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1105 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1106 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
1107 1.1 mycroft u_char tstat, rstat;
1108 1.1 mycroft
1109 1.21 enami if (sc->sc_enabled == 0)
1110 1.21 enami return (0);
1111 1.21 enami
1112 1.1 mycroft #if FE_DEBUG >= 4
1113 1.21 enami log(LOG_INFO, "%s: mb86960_intr()\n", sc->sc_dev.dv_xname);
1114 1.21 enami mb86960_dump(LOG_INFO, sc);
1115 1.1 mycroft #endif
1116 1.1 mycroft
1117 1.1 mycroft /*
1118 1.1 mycroft * Get interrupt conditions, masking unneeded flags.
1119 1.1 mycroft */
1120 1.21 enami tstat = bus_space_read_1(bst, bsh, FE_DLCR0) & FE_TMASK;
1121 1.21 enami rstat = bus_space_read_1(bst, bsh, FE_DLCR1) & FE_RMASK;
1122 1.1 mycroft if (tstat == 0 && rstat == 0)
1123 1.1 mycroft return (0);
1124 1.1 mycroft
1125 1.1 mycroft /*
1126 1.1 mycroft * Loop until there are no more new interrupt conditions.
1127 1.1 mycroft */
1128 1.1 mycroft for (;;) {
1129 1.1 mycroft /*
1130 1.1 mycroft * Reset the conditions we are acknowledging.
1131 1.1 mycroft */
1132 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR0, tstat);
1133 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR1, rstat);
1134 1.1 mycroft
1135 1.1 mycroft /*
1136 1.1 mycroft * Handle transmitter interrupts. Handle these first because
1137 1.1 mycroft * the receiver will reset the board under some conditions.
1138 1.1 mycroft */
1139 1.1 mycroft if (tstat != 0)
1140 1.21 enami mb86960_tint(sc, tstat);
1141 1.1 mycroft
1142 1.1 mycroft /*
1143 1.1 mycroft * Handle receiver interrupts.
1144 1.1 mycroft */
1145 1.1 mycroft if (rstat != 0)
1146 1.21 enami mb86960_rint(sc, rstat);
1147 1.1 mycroft
1148 1.1 mycroft /*
1149 1.1 mycroft * Update the multicast address filter if it is
1150 1.1 mycroft * needed and possible. We do it now, because
1151 1.1 mycroft * we can make sure the transmission buffer is empty,
1152 1.1 mycroft * and there is a good chance that the receive queue
1153 1.1 mycroft * is empty. It will minimize the possibility of
1154 1.1 mycroft * packet lossage.
1155 1.1 mycroft */
1156 1.1 mycroft if (sc->filter_change &&
1157 1.1 mycroft sc->txb_count == 0 && sc->txb_sched == 0) {
1158 1.21 enami mb86960_loadmar(sc);
1159 1.21 enami ifp->if_flags &= ~IFF_OACTIVE;
1160 1.1 mycroft }
1161 1.1 mycroft
1162 1.1 mycroft /*
1163 1.1 mycroft * If it looks like the transmitter can take more data,
1164 1.1 mycroft * attempt to start output on the interface. This is done
1165 1.1 mycroft * after handling the receiver interrupt to give the
1166 1.1 mycroft * receive operation priority.
1167 1.1 mycroft */
1168 1.21 enami if ((ifp->if_flags & IFF_OACTIVE) == 0)
1169 1.21 enami mb86960_start(ifp);
1170 1.18 explorer
1171 1.18 explorer #if NRND > 0
1172 1.18 explorer if (rstat != 0 || tstat != 0)
1173 1.18 explorer rnd_add_uint32(&sc->rnd_source, rstat + tstat);
1174 1.18 explorer #endif
1175 1.1 mycroft
1176 1.1 mycroft /*
1177 1.1 mycroft * Get interrupt conditions, masking unneeded flags.
1178 1.1 mycroft */
1179 1.21 enami tstat = bus_space_read_1(bst, bsh, FE_DLCR0) & FE_TMASK;
1180 1.21 enami rstat = bus_space_read_1(bst, bsh, FE_DLCR1) & FE_RMASK;
1181 1.1 mycroft if (tstat == 0 && rstat == 0)
1182 1.1 mycroft return (1);
1183 1.1 mycroft }
1184 1.1 mycroft }
1185 1.1 mycroft
1186 1.1 mycroft /*
1187 1.1 mycroft * Process an ioctl request. This code needs some work - it looks pretty ugly.
1188 1.1 mycroft */
1189 1.1 mycroft int
1190 1.21 enami mb86960_ioctl(ifp, cmd, data)
1191 1.21 enami struct ifnet *ifp;
1192 1.21 enami u_long cmd;
1193 1.1 mycroft caddr_t data;
1194 1.1 mycroft {
1195 1.21 enami struct mb86960_softc *sc = ifp->if_softc;
1196 1.21 enami struct ifaddr *ifa = (struct ifaddr *)data;
1197 1.1 mycroft struct ifreq *ifr = (struct ifreq *)data;
1198 1.1 mycroft int s, error = 0;
1199 1.1 mycroft
1200 1.1 mycroft #if FE_DEBUG >= 3
1201 1.21 enami log(LOG_INFO, "%s: ioctl(%lx)\n", sc->sc_dev.dv_xname, cmd);
1202 1.1 mycroft #endif
1203 1.1 mycroft
1204 1.8 mycroft s = splnet();
1205 1.1 mycroft
1206 1.21 enami switch (cmd) {
1207 1.1 mycroft case SIOCSIFADDR:
1208 1.21 enami if ((error = mb86960_enable(sc)) != 0)
1209 1.21 enami break;
1210 1.1 mycroft ifp->if_flags |= IFF_UP;
1211 1.1 mycroft
1212 1.1 mycroft switch (ifa->ifa_addr->sa_family) {
1213 1.1 mycroft #ifdef INET
1214 1.1 mycroft case AF_INET:
1215 1.21 enami mb86960_init(sc);
1216 1.17 is arp_ifinit(ifp, ifa);
1217 1.1 mycroft break;
1218 1.1 mycroft #endif
1219 1.1 mycroft #ifdef NS
1220 1.1 mycroft case AF_NS:
1221 1.1 mycroft {
1222 1.21 enami struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1223 1.1 mycroft
1224 1.1 mycroft if (ns_nullhost(*ina))
1225 1.1 mycroft ina->x_host =
1226 1.21 enami *(union ns_host *)LLADDR(ifp->if_sadl);
1227 1.17 is else {
1228 1.17 is bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
1229 1.17 is ETHER_ADDR_LEN);
1230 1.17 is }
1231 1.1 mycroft /* Set new address. */
1232 1.21 enami mb86960_init(sc);
1233 1.1 mycroft break;
1234 1.1 mycroft }
1235 1.1 mycroft #endif
1236 1.1 mycroft default:
1237 1.21 enami mb86960_init(sc);
1238 1.1 mycroft break;
1239 1.1 mycroft }
1240 1.1 mycroft break;
1241 1.1 mycroft
1242 1.1 mycroft case SIOCSIFFLAGS:
1243 1.1 mycroft if ((ifp->if_flags & IFF_UP) == 0 &&
1244 1.1 mycroft (ifp->if_flags & IFF_RUNNING) != 0) {
1245 1.1 mycroft /*
1246 1.1 mycroft * If interface is marked down and it is running, then
1247 1.1 mycroft * stop it.
1248 1.1 mycroft */
1249 1.21 enami mb86960_stop(sc);
1250 1.1 mycroft ifp->if_flags &= ~IFF_RUNNING;
1251 1.21 enami mb86960_disable(sc);
1252 1.1 mycroft } else if ((ifp->if_flags & IFF_UP) != 0 &&
1253 1.21 enami (ifp->if_flags & IFF_RUNNING) == 0) {
1254 1.1 mycroft /*
1255 1.1 mycroft * If interface is marked up and it is stopped, then
1256 1.1 mycroft * start it.
1257 1.1 mycroft */
1258 1.21 enami if ((error = mb86960_enable(sc)) != 0)
1259 1.21 enami break;
1260 1.21 enami mb86960_init(sc);
1261 1.30 thorpej } else if ((ifp->if_flags & IFF_UP) != 0) {
1262 1.1 mycroft /*
1263 1.1 mycroft * Reset the interface to pick up changes in any other
1264 1.1 mycroft * flags that affect hardware registers.
1265 1.1 mycroft */
1266 1.21 enami mb86960_setmode(sc);
1267 1.1 mycroft }
1268 1.1 mycroft #if DEBUG >= 1
1269 1.1 mycroft /* "ifconfig fe0 debug" to print register dump. */
1270 1.1 mycroft if (ifp->if_flags & IFF_DEBUG) {
1271 1.21 enami log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n",
1272 1.21 enami sc->sc_dev.dv_xname);
1273 1.21 enami mb86960_dump(LOG_DEBUG, sc);
1274 1.1 mycroft }
1275 1.1 mycroft #endif
1276 1.1 mycroft break;
1277 1.1 mycroft
1278 1.1 mycroft case SIOCADDMULTI:
1279 1.1 mycroft case SIOCDELMULTI:
1280 1.21 enami if (sc->sc_enabled == 0) {
1281 1.21 enami error = EIO;
1282 1.21 enami break;
1283 1.21 enami }
1284 1.21 enami
1285 1.1 mycroft /* Update our multicast list. */
1286 1.21 enami error = (cmd == SIOCADDMULTI) ?
1287 1.21 enami ether_addmulti(ifr, &sc->sc_ec) :
1288 1.21 enami ether_delmulti(ifr, &sc->sc_ec);
1289 1.1 mycroft
1290 1.1 mycroft if (error == ENETRESET) {
1291 1.1 mycroft /*
1292 1.1 mycroft * Multicast list has changed; set the hardware filter
1293 1.1 mycroft * accordingly.
1294 1.1 mycroft */
1295 1.21 enami mb86960_setmode(sc);
1296 1.1 mycroft error = 0;
1297 1.1 mycroft }
1298 1.1 mycroft break;
1299 1.1 mycroft
1300 1.21 enami case SIOCGIFMEDIA:
1301 1.21 enami case SIOCSIFMEDIA:
1302 1.21 enami error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1303 1.21 enami break;
1304 1.21 enami
1305 1.1 mycroft default:
1306 1.1 mycroft error = EINVAL;
1307 1.21 enami break;
1308 1.1 mycroft }
1309 1.1 mycroft
1310 1.1 mycroft splx(s);
1311 1.1 mycroft return (error);
1312 1.1 mycroft }
1313 1.1 mycroft
1314 1.1 mycroft /*
1315 1.1 mycroft * Retreive packet from receive buffer and send to the next level up via
1316 1.1 mycroft * ether_input(). If there is a BPF listener, give a copy to BPF, too.
1317 1.1 mycroft * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
1318 1.1 mycroft */
1319 1.1 mycroft int
1320 1.21 enami mb86960_get_packet(sc, len)
1321 1.21 enami struct mb86960_softc *sc;
1322 1.1 mycroft int len;
1323 1.1 mycroft {
1324 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1325 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1326 1.21 enami struct ifnet *ifp = &sc->sc_ec.ec_if;
1327 1.1 mycroft struct ether_header *eh;
1328 1.1 mycroft struct mbuf *m;
1329 1.1 mycroft
1330 1.1 mycroft /* Allocate a header mbuf. */
1331 1.1 mycroft MGETHDR(m, M_DONTWAIT, MT_DATA);
1332 1.1 mycroft if (m == 0)
1333 1.1 mycroft return (0);
1334 1.1 mycroft m->m_pkthdr.rcvif = ifp;
1335 1.1 mycroft m->m_pkthdr.len = len;
1336 1.1 mycroft
1337 1.1 mycroft /* The following silliness is to make NFS happy. */
1338 1.1 mycroft #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
1339 1.1 mycroft #define EOFF (EROUND - sizeof(struct ether_header))
1340 1.1 mycroft
1341 1.1 mycroft /*
1342 1.1 mycroft * Our strategy has one more problem. There is a policy on
1343 1.1 mycroft * mbuf cluster allocation. It says that we must have at
1344 1.6 mycroft * least MINCLSIZE (208 bytes) to allocate a cluster. For a
1345 1.6 mycroft * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
1346 1.6 mycroft * our code violates the rule...
1347 1.1 mycroft * On the other hand, the current code is short, simle,
1348 1.1 mycroft * and fast, however. It does no harmful thing, just waists
1349 1.1 mycroft * some memory. Any comments? FIXME.
1350 1.1 mycroft */
1351 1.1 mycroft
1352 1.1 mycroft /* Attach a cluster if this packet doesn't fit in a normal mbuf. */
1353 1.1 mycroft if (len > MHLEN - EOFF) {
1354 1.1 mycroft MCLGET(m, M_DONTWAIT);
1355 1.1 mycroft if ((m->m_flags & M_EXT) == 0) {
1356 1.1 mycroft m_freem(m);
1357 1.1 mycroft return (0);
1358 1.1 mycroft }
1359 1.1 mycroft }
1360 1.1 mycroft
1361 1.1 mycroft /*
1362 1.1 mycroft * The following assumes there is room for the ether header in the
1363 1.1 mycroft * header mbuf.
1364 1.1 mycroft */
1365 1.1 mycroft m->m_data += EOFF;
1366 1.1 mycroft eh = mtod(m, struct ether_header *);
1367 1.1 mycroft
1368 1.1 mycroft /* Set the length of this packet. */
1369 1.1 mycroft m->m_len = len;
1370 1.1 mycroft
1371 1.1 mycroft /* Get a packet. */
1372 1.35 itojun bus_space_read_multi_stream_2(bst, bsh, FE_BMPR8, mtod(m, u_int16_t *),
1373 1.29 pk (len + 1) >> 1);
1374 1.1 mycroft
1375 1.1 mycroft #if NBPFILTER > 0
1376 1.1 mycroft /*
1377 1.1 mycroft * Check if there's a BPF listener on this interface. If so, hand off
1378 1.1 mycroft * the raw packet to bpf.
1379 1.1 mycroft */
1380 1.1 mycroft if (ifp->if_bpf) {
1381 1.1 mycroft bpf_mtap(ifp->if_bpf, m);
1382 1.1 mycroft
1383 1.1 mycroft /*
1384 1.1 mycroft * Note that the interface cannot be in promiscuous mode if
1385 1.1 mycroft * there are no BPF listeners. And if we are in promiscuous
1386 1.1 mycroft * mode, we have to check if this packet is really ours.
1387 1.1 mycroft */
1388 1.1 mycroft if ((ifp->if_flags & IFF_PROMISC) != 0 &&
1389 1.1 mycroft (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1390 1.17 is bcmp(eh->ether_dhost, sc->sc_enaddr,
1391 1.21 enami sizeof(eh->ether_dhost)) != 0) {
1392 1.1 mycroft m_freem(m);
1393 1.1 mycroft return (1);
1394 1.1 mycroft }
1395 1.1 mycroft }
1396 1.1 mycroft #endif
1397 1.1 mycroft
1398 1.33 thorpej (*ifp->if_input)(ifp, m);
1399 1.1 mycroft return (1);
1400 1.1 mycroft }
1401 1.1 mycroft
1402 1.1 mycroft /*
1403 1.1 mycroft * Write an mbuf chain to the transmission buffer memory using 16 bit PIO.
1404 1.1 mycroft * Returns number of bytes actually written, including length word.
1405 1.1 mycroft *
1406 1.1 mycroft * If an mbuf chain is too long for an Ethernet frame, it is not sent.
1407 1.1 mycroft * Packets shorter than Ethernet minimum are legal, and we pad them
1408 1.1 mycroft * before sending out. An exception is "partial" packets which are
1409 1.1 mycroft * shorter than mandatory Ethernet header.
1410 1.1 mycroft *
1411 1.1 mycroft * I wrote a code for an experimental "delayed padding" technique.
1412 1.1 mycroft * When employed, it postpones the padding process for short packets.
1413 1.1 mycroft * If xmit() occured at the moment, the padding process is omitted, and
1414 1.1 mycroft * garbages are sent as pad data. If next packet is stored in the
1415 1.1 mycroft * transmission buffer before xmit(), write_mbuf() pads the previous
1416 1.1 mycroft * packet before transmitting new packet. This *may* gain the
1417 1.1 mycroft * system performance (slightly).
1418 1.1 mycroft */
1419 1.1 mycroft void
1420 1.21 enami mb86960_write_mbufs(sc, m)
1421 1.21 enami struct mb86960_softc *sc;
1422 1.1 mycroft struct mbuf *m;
1423 1.1 mycroft {
1424 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1425 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1426 1.1 mycroft u_char *data;
1427 1.1 mycroft u_short savebyte; /* WARNING: Architecture dependent! */
1428 1.1 mycroft int totlen, len, wantbyte;
1429 1.21 enami #if FE_DEBUG >= 2
1430 1.21 enami struct mbuf *mp;
1431 1.21 enami #endif
1432 1.16 thorpej
1433 1.16 thorpej /* XXX thorpej 960116 - quiet bogus compiler warning. */
1434 1.16 thorpej savebyte = 0;
1435 1.1 mycroft
1436 1.1 mycroft #if FE_DELAYED_PADDING
1437 1.1 mycroft /* Do the "delayed padding." */
1438 1.1 mycroft len = sc->txb_padding >> 1;
1439 1.1 mycroft if (len > 0) {
1440 1.1 mycroft while (--len >= 0)
1441 1.21 enami bus_space_write_2(bst, bsh, FE_BMPR8, 0);
1442 1.1 mycroft sc->txb_padding = 0;
1443 1.1 mycroft }
1444 1.1 mycroft #endif
1445 1.1 mycroft
1446 1.4 mycroft /* We need to use m->m_pkthdr.len, so require the header */
1447 1.4 mycroft if ((m->m_flags & M_PKTHDR) == 0)
1448 1.21 enami panic("mb86960_write_mbufs: no header mbuf");
1449 1.4 mycroft
1450 1.1 mycroft #if FE_DEBUG >= 2
1451 1.1 mycroft /* First, count up the total number of bytes to copy. */
1452 1.1 mycroft for (totlen = 0, mp = m; mp != 0; mp = mp->m_next)
1453 1.1 mycroft totlen += mp->m_len;
1454 1.1 mycroft /* Check if this matches the one in the packet header. */
1455 1.1 mycroft if (totlen != m->m_pkthdr.len)
1456 1.1 mycroft log(LOG_WARNING, "%s: packet length mismatch? (%d/%d)\n",
1457 1.1 mycroft sc->sc_dev.dv_xname, totlen, m->m_pkthdr.len);
1458 1.1 mycroft #else
1459 1.1 mycroft /* Just use the length value in the packet header. */
1460 1.1 mycroft totlen = m->m_pkthdr.len;
1461 1.1 mycroft #endif
1462 1.1 mycroft
1463 1.1 mycroft #if FE_DEBUG >= 1
1464 1.1 mycroft /*
1465 1.1 mycroft * Should never send big packets. If such a packet is passed,
1466 1.1 mycroft * it should be a bug of upper layer. We just ignore it.
1467 1.1 mycroft * ... Partial (too short) packets, neither.
1468 1.1 mycroft */
1469 1.32 thorpej if (totlen > (ETHER_MAX_LEN - ETHER_CRC_LEN) ||
1470 1.32 thorpej totlen < ETHER_HDR_LEN) {
1471 1.1 mycroft log(LOG_ERR, "%s: got a %s packet (%u bytes) to send\n",
1472 1.1 mycroft sc->sc_dev.dv_xname,
1473 1.32 thorpej totlen < ETHER_HDR_LEN ? "partial" : "big", totlen);
1474 1.21 enami sc->sc_ec.ec_if.if_oerrors++;
1475 1.1 mycroft return;
1476 1.1 mycroft }
1477 1.1 mycroft #endif
1478 1.1 mycroft
1479 1.1 mycroft /*
1480 1.1 mycroft * Put the length word for this frame.
1481 1.1 mycroft * Does 86960 accept odd length? -- Yes.
1482 1.1 mycroft * Do we need to pad the length to minimum size by ourselves?
1483 1.1 mycroft * -- Generally yes. But for (or will be) the last
1484 1.1 mycroft * packet in the transmission buffer, we can skip the
1485 1.1 mycroft * padding process. It may gain performance slightly. FIXME.
1486 1.1 mycroft */
1487 1.32 thorpej bus_space_write_2(bst, bsh, FE_BMPR8,
1488 1.32 thorpej max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN)));
1489 1.1 mycroft
1490 1.1 mycroft /*
1491 1.1 mycroft * Update buffer status now.
1492 1.1 mycroft * Truncate the length up to an even number, since we use outw().
1493 1.1 mycroft */
1494 1.1 mycroft totlen = (totlen + 1) & ~1;
1495 1.32 thorpej sc->txb_free -= FE_DATA_LEN_LEN +
1496 1.32 thorpej max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN));
1497 1.1 mycroft sc->txb_count++;
1498 1.1 mycroft
1499 1.1 mycroft #if FE_DELAYED_PADDING
1500 1.1 mycroft /* Postpone the packet padding if necessary. */
1501 1.32 thorpej if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN))
1502 1.32 thorpej sc->txb_padding = (ETHER_MIN_LEN - ETHER_CRC_LEN) - totlen;
1503 1.1 mycroft #endif
1504 1.1 mycroft
1505 1.1 mycroft /*
1506 1.1 mycroft * Transfer the data from mbuf chain to the transmission buffer.
1507 1.1 mycroft * MB86960 seems to require that data be transferred as words, and
1508 1.1 mycroft * only words. So that we require some extra code to patch
1509 1.1 mycroft * over odd-length mbufs.
1510 1.1 mycroft */
1511 1.1 mycroft wantbyte = 0;
1512 1.1 mycroft for (; m != 0; m = m->m_next) {
1513 1.1 mycroft /* Ignore empty mbuf. */
1514 1.1 mycroft len = m->m_len;
1515 1.1 mycroft if (len == 0)
1516 1.1 mycroft continue;
1517 1.1 mycroft
1518 1.1 mycroft /* Find the actual data to send. */
1519 1.1 mycroft data = mtod(m, caddr_t);
1520 1.1 mycroft
1521 1.1 mycroft /* Finish the last byte. */
1522 1.1 mycroft if (wantbyte) {
1523 1.21 enami bus_space_write_2(bst, bsh, FE_BMPR8,
1524 1.21 enami savebyte | (*data << 8));
1525 1.1 mycroft data++;
1526 1.1 mycroft len--;
1527 1.1 mycroft wantbyte = 0;
1528 1.1 mycroft }
1529 1.1 mycroft
1530 1.1 mycroft /* Output contiguous words. */
1531 1.1 mycroft if (len > 1)
1532 1.35 itojun bus_space_write_multi_stream_2(bst, bsh, FE_BMPR8,
1533 1.29 pk (u_int16_t *)data, len >> 1);
1534 1.1 mycroft
1535 1.1 mycroft /* Save remaining byte, if there is one. */
1536 1.1 mycroft if (len & 1) {
1537 1.1 mycroft data += len & ~1;
1538 1.1 mycroft savebyte = *data;
1539 1.1 mycroft wantbyte = 1;
1540 1.1 mycroft }
1541 1.1 mycroft }
1542 1.1 mycroft
1543 1.1 mycroft /* Spit the last byte, if the length is odd. */
1544 1.1 mycroft if (wantbyte)
1545 1.21 enami bus_space_write_2(bst, bsh, FE_BMPR8, savebyte);
1546 1.1 mycroft
1547 1.1 mycroft #if ! FE_DELAYED_PADDING
1548 1.1 mycroft /*
1549 1.1 mycroft * Pad the packet to the minimum length if necessary.
1550 1.1 mycroft */
1551 1.32 thorpej len = ((ETHER_MIN_LEN - ETHER_CRC_LEN) >> 1) - (totlen >> 1);
1552 1.1 mycroft while (--len >= 0)
1553 1.21 enami bus_space_write_2(bst, bsh, FE_BMPR8, 0);
1554 1.1 mycroft #endif
1555 1.1 mycroft }
1556 1.1 mycroft
1557 1.1 mycroft /*
1558 1.1 mycroft * Compute the multicast address filter from the
1559 1.1 mycroft * list of multicast addresses we need to listen to.
1560 1.1 mycroft */
1561 1.1 mycroft void
1562 1.21 enami mb86960_getmcaf(ec, af)
1563 1.17 is struct ethercom *ec;
1564 1.1 mycroft u_char *af;
1565 1.1 mycroft {
1566 1.17 is struct ifnet *ifp = &ec->ec_if;
1567 1.1 mycroft struct ether_multi *enm;
1568 1.22 mycroft register u_char *cp;
1569 1.23 mycroft register u_int32_t crc;
1570 1.24 mycroft static const u_int32_t crctab[] = {
1571 1.23 mycroft 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1572 1.23 mycroft 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1573 1.23 mycroft 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1574 1.23 mycroft 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1575 1.23 mycroft };
1576 1.23 mycroft register int len;
1577 1.1 mycroft struct ether_multistep step;
1578 1.1 mycroft
1579 1.1 mycroft /*
1580 1.1 mycroft * Set up multicast address filter by passing all multicast addresses
1581 1.1 mycroft * through a crc generator, and then using the high order 6 bits as an
1582 1.1 mycroft * index into the 64 bit logical address filter. The high order bit
1583 1.1 mycroft * selects the word, while the rest of the bits select the bit within
1584 1.1 mycroft * the word.
1585 1.1 mycroft */
1586 1.1 mycroft
1587 1.1 mycroft if ((ifp->if_flags & IFF_PROMISC) != 0)
1588 1.1 mycroft goto allmulti;
1589 1.1 mycroft
1590 1.1 mycroft af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0x00;
1591 1.17 is ETHER_FIRST_MULTI(step, ec, enm);
1592 1.1 mycroft while (enm != NULL) {
1593 1.1 mycroft if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1594 1.1 mycroft sizeof(enm->enm_addrlo)) != 0) {
1595 1.1 mycroft /*
1596 1.1 mycroft * We must listen to a range of multicast addresses.
1597 1.1 mycroft * For now, just accept all multicasts, rather than
1598 1.1 mycroft * trying to set only those filter bits needed to match
1599 1.1 mycroft * the range. (At this time, the only use of address
1600 1.1 mycroft * ranges is for IP multicast routing, for which the
1601 1.1 mycroft * range is big enough to require all bits set.)
1602 1.1 mycroft */
1603 1.1 mycroft goto allmulti;
1604 1.1 mycroft }
1605 1.1 mycroft
1606 1.1 mycroft cp = enm->enm_addrlo;
1607 1.1 mycroft crc = 0xffffffff;
1608 1.1 mycroft for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1609 1.23 mycroft crc ^= *cp++;
1610 1.23 mycroft crc = (crc >> 4) ^ crctab[crc & 0xf];
1611 1.23 mycroft crc = (crc >> 4) ^ crctab[crc & 0xf];
1612 1.1 mycroft }
1613 1.1 mycroft /* Just want the 6 most significant bits. */
1614 1.1 mycroft crc >>= 26;
1615 1.1 mycroft
1616 1.1 mycroft /* Turn on the corresponding bit in the filter. */
1617 1.1 mycroft af[crc >> 3] |= 1 << (crc & 7);
1618 1.1 mycroft
1619 1.1 mycroft ETHER_NEXT_MULTI(step, enm);
1620 1.1 mycroft }
1621 1.1 mycroft ifp->if_flags &= ~IFF_ALLMULTI;
1622 1.1 mycroft return;
1623 1.1 mycroft
1624 1.1 mycroft allmulti:
1625 1.1 mycroft ifp->if_flags |= IFF_ALLMULTI;
1626 1.1 mycroft af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0xff;
1627 1.1 mycroft }
1628 1.1 mycroft
1629 1.1 mycroft /*
1630 1.1 mycroft * Calculate a new "multicast packet filter" and put the 86960
1631 1.1 mycroft * receiver in appropriate mode.
1632 1.1 mycroft */
1633 1.1 mycroft void
1634 1.21 enami mb86960_setmode(sc)
1635 1.21 enami struct mb86960_softc *sc;
1636 1.1 mycroft {
1637 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1638 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1639 1.21 enami int flags = sc->sc_ec.ec_if.if_flags;
1640 1.1 mycroft
1641 1.1 mycroft /*
1642 1.1 mycroft * If the interface is not running, we postpone the update
1643 1.1 mycroft * process for receive modes and multicast address filter
1644 1.1 mycroft * until the interface is restarted. It reduces some
1645 1.1 mycroft * complicated job on maintaining chip states. (Earlier versions
1646 1.1 mycroft * of this driver had a bug on that point...)
1647 1.1 mycroft *
1648 1.21 enami * To complete the trick, mb86960_init() calls mb86960_setmode() after
1649 1.1 mycroft * restarting the interface.
1650 1.1 mycroft */
1651 1.1 mycroft if ((flags & IFF_RUNNING) == 0)
1652 1.1 mycroft return;
1653 1.1 mycroft
1654 1.1 mycroft /*
1655 1.1 mycroft * Promiscuous mode is handled separately.
1656 1.1 mycroft */
1657 1.1 mycroft if ((flags & IFF_PROMISC) != 0) {
1658 1.1 mycroft /*
1659 1.1 mycroft * Program 86960 to receive all packets on the segment
1660 1.1 mycroft * including those directed to other stations.
1661 1.1 mycroft * Multicast filter stored in MARs are ignored
1662 1.1 mycroft * under this setting, so we don't need to update it.
1663 1.1 mycroft *
1664 1.6 mycroft * Promiscuous mode is used solely by BPF, and BPF only
1665 1.6 mycroft * listens to valid (no error) packets. So, we ignore
1666 1.6 mycroft * errornous ones even in this mode.
1667 1.1 mycroft */
1668 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR5,
1669 1.1 mycroft sc->proto_dlcr5 | FE_D5_AFM0 | FE_D5_AFM1);
1670 1.1 mycroft sc->filter_change = 0;
1671 1.1 mycroft
1672 1.1 mycroft #if FE_DEBUG >= 3
1673 1.1 mycroft log(LOG_INFO, "%s: promiscuous mode\n", sc->sc_dev.dv_xname);
1674 1.1 mycroft #endif
1675 1.1 mycroft return;
1676 1.1 mycroft }
1677 1.1 mycroft
1678 1.1 mycroft /*
1679 1.1 mycroft * Turn the chip to the normal (non-promiscuous) mode.
1680 1.1 mycroft */
1681 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR5, sc->proto_dlcr5 | FE_D5_AFM1);
1682 1.1 mycroft
1683 1.1 mycroft /*
1684 1.1 mycroft * Find the new multicast filter value.
1685 1.1 mycroft */
1686 1.21 enami mb86960_getmcaf(&sc->sc_ec, sc->filter);
1687 1.1 mycroft sc->filter_change = 1;
1688 1.1 mycroft
1689 1.1 mycroft #if FE_DEBUG >= 3
1690 1.1 mycroft log(LOG_INFO,
1691 1.1 mycroft "%s: address filter: [%02x %02x %02x %02x %02x %02x %02x %02x]\n",
1692 1.1 mycroft sc->sc_dev.dv_xname,
1693 1.1 mycroft sc->filter[0], sc->filter[1], sc->filter[2], sc->filter[3],
1694 1.1 mycroft sc->filter[4], sc->filter[5], sc->filter[6], sc->filter[7]);
1695 1.1 mycroft #endif
1696 1.1 mycroft
1697 1.1 mycroft /*
1698 1.1 mycroft * We have to update the multicast filter in the 86960, A.S.A.P.
1699 1.1 mycroft *
1700 1.1 mycroft * Note that the DLC (Data Linc Control unit, i.e. transmitter
1701 1.1 mycroft * and receiver) must be stopped when feeding the filter, and
1702 1.1 mycroft * DLC trushes all packets in both transmission and receive
1703 1.1 mycroft * buffers when stopped.
1704 1.1 mycroft *
1705 1.1 mycroft * ... Are the above sentenses correct? I have to check the
1706 1.1 mycroft * manual of the MB86960A. FIXME.
1707 1.1 mycroft *
1708 1.1 mycroft * To reduce the packet lossage, we delay the filter update
1709 1.1 mycroft * process until buffers are empty.
1710 1.1 mycroft */
1711 1.1 mycroft if (sc->txb_sched == 0 && sc->txb_count == 0 &&
1712 1.21 enami (bus_space_read_1(bst, bsh, FE_DLCR1) & FE_D1_PKTRDY) == 0) {
1713 1.1 mycroft /*
1714 1.1 mycroft * Buffers are (apparently) empty. Load
1715 1.1 mycroft * the new filter value into MARs now.
1716 1.1 mycroft */
1717 1.21 enami mb86960_loadmar(sc);
1718 1.1 mycroft } else {
1719 1.1 mycroft /*
1720 1.1 mycroft * Buffers are not empty. Mark that we have to update
1721 1.21 enami * the MARs. The new filter will be loaded by mb86960_intr()
1722 1.1 mycroft * later.
1723 1.1 mycroft */
1724 1.1 mycroft #if FE_DEBUG >= 4
1725 1.21 enami log(LOG_INFO, "%s: filter change delayed\n",
1726 1.21 enami sc->sc_dev.dv_xname);
1727 1.1 mycroft #endif
1728 1.1 mycroft }
1729 1.1 mycroft }
1730 1.1 mycroft
1731 1.1 mycroft /*
1732 1.1 mycroft * Load a new multicast address filter into MARs.
1733 1.1 mycroft *
1734 1.21 enami * The caller must have splnet'ed befor mb86960_loadmar.
1735 1.1 mycroft * This function starts the DLC upon return. So it can be called only
1736 1.1 mycroft * when the chip is working, i.e., from the driver's point of view, when
1737 1.1 mycroft * a device is RUNNING. (I mistook the point in previous versions.)
1738 1.1 mycroft */
1739 1.1 mycroft void
1740 1.21 enami mb86960_loadmar(sc)
1741 1.21 enami struct mb86960_softc *sc;
1742 1.1 mycroft {
1743 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1744 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1745 1.1 mycroft
1746 1.1 mycroft /* Stop the DLC (transmitter and receiver). */
1747 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
1748 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
1749 1.1 mycroft
1750 1.1 mycroft /* Select register bank 1 for MARs. */
1751 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
1752 1.1 mycroft sc->proto_dlcr7 | FE_D7_RBS_MAR | FE_D7_POWER_UP);
1753 1.1 mycroft
1754 1.1 mycroft /* Copy filter value into the registers. */
1755 1.21 enami bus_space_write_region_1(bst, bsh, FE_MAR8, sc->filter, FE_FILTER_LEN);
1756 1.1 mycroft
1757 1.1 mycroft /* Restore the bank selection for BMPRs (i.e., runtime registers). */
1758 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
1759 1.1 mycroft sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
1760 1.1 mycroft
1761 1.1 mycroft /* Restart the DLC. */
1762 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR6,
1763 1.21 enami sc->proto_dlcr6 | FE_D6_DLC_ENABLE);
1764 1.1 mycroft
1765 1.1 mycroft /* We have just updated the filter. */
1766 1.1 mycroft sc->filter_change = 0;
1767 1.1 mycroft
1768 1.1 mycroft #if FE_DEBUG >= 3
1769 1.1 mycroft log(LOG_INFO, "%s: address filter changed\n", sc->sc_dev.dv_xname);
1770 1.1 mycroft #endif
1771 1.1 mycroft }
1772 1.1 mycroft
1773 1.21 enami /*
1774 1.21 enami * Enable power on the interface.
1775 1.21 enami */
1776 1.21 enami int
1777 1.21 enami mb86960_enable(sc)
1778 1.21 enami struct mb86960_softc *sc;
1779 1.21 enami {
1780 1.21 enami
1781 1.21 enami #if FE_DEBUG >= 3
1782 1.21 enami log(LOG_INFO, "%s: mb86960_enable()\n", sc->sc_dev.dv_xname);
1783 1.21 enami #endif
1784 1.21 enami
1785 1.21 enami if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
1786 1.21 enami if ((*sc->sc_enable)(sc) != 0) {
1787 1.21 enami printf("%s: device enable failed\n",
1788 1.21 enami sc->sc_dev.dv_xname);
1789 1.21 enami return (EIO);
1790 1.21 enami }
1791 1.21 enami }
1792 1.21 enami
1793 1.21 enami sc->sc_enabled = 1;
1794 1.21 enami return (0);
1795 1.21 enami }
1796 1.21 enami
1797 1.21 enami /*
1798 1.21 enami * Disable power on the interface.
1799 1.21 enami */
1800 1.21 enami void
1801 1.21 enami mb86960_disable(sc)
1802 1.21 enami struct mb86960_softc *sc;
1803 1.21 enami {
1804 1.21 enami
1805 1.21 enami #if FE_DEBUG >= 3
1806 1.21 enami log(LOG_INFO, "%s: mb86960_disable()\n", sc->sc_dev.dv_xname);
1807 1.21 enami #endif
1808 1.21 enami
1809 1.21 enami if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
1810 1.21 enami (*sc->sc_disable)(sc);
1811 1.21 enami sc->sc_enabled = 0;
1812 1.21 enami }
1813 1.28 thorpej }
1814 1.28 thorpej
1815 1.28 thorpej int
1816 1.28 thorpej mb86960_activate(self, act)
1817 1.28 thorpej struct device *self;
1818 1.28 thorpej enum devact act;
1819 1.28 thorpej {
1820 1.28 thorpej struct mb86960_softc *sc = (struct mb86960_softc *)self;
1821 1.28 thorpej int rv = 0, s;
1822 1.28 thorpej
1823 1.28 thorpej s = splnet();
1824 1.28 thorpej switch (act) {
1825 1.28 thorpej case DVACT_ACTIVATE:
1826 1.28 thorpej rv = EOPNOTSUPP;
1827 1.28 thorpej break;
1828 1.28 thorpej
1829 1.28 thorpej case DVACT_DEACTIVATE:
1830 1.28 thorpej #ifdef notyet
1831 1.28 thorpej /* First, kill off the interface. */
1832 1.28 thorpej if_detach(sc->sc_ec.ec_if);
1833 1.28 thorpej #endif
1834 1.28 thorpej
1835 1.28 thorpej /* Now disable the interface. */
1836 1.28 thorpej mb86960_disable(sc);
1837 1.28 thorpej break;
1838 1.28 thorpej }
1839 1.28 thorpej splx(s);
1840 1.28 thorpej return (rv);
1841 1.21 enami }
1842 1.21 enami
1843 1.1 mycroft #if FE_DEBUG >= 1
1844 1.1 mycroft void
1845 1.21 enami mb86960_dump(level, sc)
1846 1.1 mycroft int level;
1847 1.21 enami struct mb86960_softc *sc;
1848 1.1 mycroft {
1849 1.21 enami bus_space_tag_t bst = sc->sc_bst;
1850 1.21 enami bus_space_handle_t bsh = sc->sc_bsh;
1851 1.1 mycroft u_char save_dlcr7;
1852 1.1 mycroft
1853 1.21 enami save_dlcr7 = bus_space_read_1(bst, bsh, FE_DLCR7);
1854 1.1 mycroft
1855 1.21 enami log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x %02x\n",
1856 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR0),
1857 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR1),
1858 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR2),
1859 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR3),
1860 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR4),
1861 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR5),
1862 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR6),
1863 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR7));
1864 1.21 enami
1865 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
1866 1.21 enami (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_DLCR);
1867 1.21 enami log(level, "\t %02x %02x %02x %02x %02x %02x %02x %02x\n",
1868 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR8),
1869 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR9),
1870 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR10),
1871 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR11),
1872 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR12),
1873 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR13),
1874 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR14),
1875 1.21 enami bus_space_read_1(bst, bsh, FE_DLCR15));
1876 1.21 enami
1877 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
1878 1.21 enami (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_MAR);
1879 1.21 enami log(level, "\tMAR = %02x %02x %02x %02x %02x %02x %02x %02x\n",
1880 1.21 enami bus_space_read_1(bst, bsh, FE_MAR8),
1881 1.21 enami bus_space_read_1(bst, bsh, FE_MAR9),
1882 1.21 enami bus_space_read_1(bst, bsh, FE_MAR10),
1883 1.21 enami bus_space_read_1(bst, bsh, FE_MAR11),
1884 1.21 enami bus_space_read_1(bst, bsh, FE_MAR12),
1885 1.21 enami bus_space_read_1(bst, bsh, FE_MAR13),
1886 1.21 enami bus_space_read_1(bst, bsh, FE_MAR14),
1887 1.21 enami bus_space_read_1(bst, bsh, FE_MAR15));
1888 1.21 enami
1889 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7,
1890 1.21 enami (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_BMPR);
1891 1.21 enami log(level,
1892 1.21 enami "\tBMPR = xx xx %02x %02x %02x %02x %02x %02x %02x %02x xx %02x\n",
1893 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR10),
1894 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR11),
1895 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR12),
1896 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR13),
1897 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR14),
1898 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR15),
1899 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR16),
1900 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR17),
1901 1.21 enami bus_space_read_1(bst, bsh, FE_BMPR19));
1902 1.1 mycroft
1903 1.21 enami bus_space_write_1(bst, bsh, FE_DLCR7, save_dlcr7);
1904 1.1 mycroft }
1905 1.1 mycroft #endif
1906