xref: /netbsd-src/sys/arch/macppc/dev/if_bm.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: if_bm.c,v 1.34 2007/10/17 19:55:18 garbled Exp $	*/
2 
3 /*-
4  * Copyright (C) 1998, 1999, 2000 Tsubai Masanari.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: if_bm.c,v 1.34 2007/10/17 19:55:18 garbled Exp $");
31 
32 #include "opt_inet.h"
33 #include "bpfilter.h"
34 
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/ioctl.h>
38 #include <sys/kernel.h>
39 #include <sys/mbuf.h>
40 #include <sys/socket.h>
41 #include <sys/systm.h>
42 #include <sys/callout.h>
43 
44 #include <uvm/uvm_extern.h>
45 
46 #include <net/if.h>
47 #include <net/if_dl.h>
48 #include <net/if_ether.h>
49 #include <net/if_media.h>
50 
51 #if NBPFILTER > 0
52 #include <net/bpf.h>
53 #endif
54 
55 #ifdef INET
56 #include <netinet/in.h>
57 #include <netinet/if_inarp.h>
58 #endif
59 
60 
61 #include <dev/ofw/openfirm.h>
62 
63 #include <dev/mii/mii.h>
64 #include <dev/mii/miivar.h>
65 #include <dev/mii/mii_bitbang.h>
66 
67 #include <powerpc/spr.h>
68 
69 #include <machine/autoconf.h>
70 #include <machine/pio.h>
71 
72 #include <macppc/dev/dbdma.h>
73 #include <macppc/dev/if_bmreg.h>
74 
75 #define BMAC_TXBUFS 2
76 #define BMAC_RXBUFS 16
77 #define BMAC_BUFLEN 2048
78 
79 struct bmac_softc {
80 	struct device sc_dev;
81 	struct ethercom sc_ethercom;
82 #define sc_if sc_ethercom.ec_if
83 	struct callout sc_tick_ch;
84 	bus_space_tag_t sc_iot;
85 	bus_space_handle_t sc_ioh;
86 	dbdma_regmap_t *sc_txdma;
87 	dbdma_regmap_t *sc_rxdma;
88 	dbdma_command_t *sc_txcmd;
89 	dbdma_command_t *sc_rxcmd;
90 	void *sc_txbuf;
91 	void *sc_rxbuf;
92 	int sc_rxlast;
93 	int sc_flags;
94 	struct mii_data sc_mii;
95 	u_char sc_enaddr[6];
96 };
97 
98 #define BMAC_BMACPLUS	0x01
99 #define BMAC_DEBUGFLAG	0x02
100 
101 extern volatile uint32_t *heathrow_FCR;
102 
103 int bmac_match __P((struct device *, struct cfdata *, void *));
104 void bmac_attach __P((struct device *, struct device *, void *));
105 void bmac_reset_chip __P((struct bmac_softc *));
106 void bmac_init __P((struct bmac_softc *));
107 void bmac_init_dma __P((struct bmac_softc *));
108 int bmac_intr __P((void *));
109 int bmac_rint __P((void *));
110 void bmac_reset __P((struct bmac_softc *));
111 void bmac_stop __P((struct bmac_softc *));
112 void bmac_start __P((struct ifnet *));
113 void bmac_transmit_packet __P((struct bmac_softc *, void *, int));
114 int bmac_put __P((struct bmac_softc *, void *, struct mbuf *));
115 struct mbuf *bmac_get __P((struct bmac_softc *, void *, int));
116 void bmac_watchdog __P((struct ifnet *));
117 int bmac_ioctl __P((struct ifnet *, u_long, void *));
118 int bmac_mediachange __P((struct ifnet *));
119 void bmac_mediastatus __P((struct ifnet *, struct ifmediareq *));
120 void bmac_setladrf __P((struct bmac_softc *));
121 
122 int bmac_mii_readreg __P((struct device *, int, int));
123 void bmac_mii_writereg __P((struct device *, int, int, int));
124 void bmac_mii_statchg __P((struct device *));
125 void bmac_mii_tick __P((void *));
126 u_int32_t bmac_mbo_read __P((struct device *));
127 void bmac_mbo_write __P((struct device *, u_int32_t));
128 
129 CFATTACH_DECL(bm, sizeof(struct bmac_softc),
130     bmac_match, bmac_attach, NULL, NULL);
131 
132 const struct mii_bitbang_ops bmac_mbo = {
133 	bmac_mbo_read, bmac_mbo_write,
134 	{ MIFDO, MIFDI, MIFDC, MIFDIR, 0 }
135 };
136 
137 static inline uint16_t
138 bmac_read_reg(struct bmac_softc *sc, bus_size_t off)
139 {
140 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
141 }
142 
143 static inline void
144 bmac_write_reg(struct bmac_softc *sc, bus_size_t off, uint16_t val)
145 {
146 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, val);
147 }
148 
149 static inline void
150 bmac_set_bits(struct bmac_softc *sc, bus_size_t off, uint16_t val)
151 {
152 	val |= bmac_read_reg(sc, off);
153 	bmac_write_reg(sc, off, val);
154 }
155 
156 static inline void
157 bmac_reset_bits(struct bmac_softc *sc, bus_size_t off, uint16_t val)
158 {
159 	bmac_write_reg(sc, off, bmac_read_reg(sc, off) & ~val);
160 }
161 
162 int
163 bmac_match(struct device *parent, struct cfdata *cf, void *aux)
164 {
165 	struct confargs *ca = aux;
166 
167 	if (ca->ca_nreg < 24 || ca->ca_nintr < 12)
168 		return 0;
169 
170 	if (strcmp(ca->ca_name, "bmac") == 0)		/* bmac */
171 		return 1;
172 	if (strcmp(ca->ca_name, "ethernet") == 0)	/* bmac+ */
173 		return 1;
174 
175 	return 0;
176 }
177 
178 void
179 bmac_attach(struct device *parent, struct device *self, void *aux)
180 {
181 	struct confargs *ca = aux;
182 	struct bmac_softc *sc = (void *)self;
183 	struct ifnet *ifp = &sc->sc_if;
184 	struct mii_data *mii = &sc->sc_mii;
185 	u_char laddr[6];
186 
187 	callout_init(&sc->sc_tick_ch, 0);
188 
189 	sc->sc_flags =0;
190 	if (strcmp(ca->ca_name, "ethernet") == 0) {
191 		char name[64];
192 
193 		memset(name, 0, 64);
194 		OF_package_to_path(ca->ca_node, name, sizeof(name));
195 		OF_open(name);
196 		sc->sc_flags |= BMAC_BMACPLUS;
197 	}
198 
199 	ca->ca_reg[0] += ca->ca_baseaddr;
200 	ca->ca_reg[2] += ca->ca_baseaddr;
201 	ca->ca_reg[4] += ca->ca_baseaddr;
202 
203 	sc->sc_iot = ca->ca_tag;
204 	if (bus_space_map(sc->sc_iot, ca->ca_reg[0], ca->ca_reg[1], 0,
205 	    &sc->sc_ioh) != 0) {
206 		aprint_error(": couldn't map %#x", ca->ca_reg[0]);
207 		return;
208 	}
209 
210 	bmac_write_reg(sc, INTDISABLE, NoEventsMask);
211 
212 	if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 &&
213 	    OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) {
214 		printf(": cannot get mac-address\n");
215 		return;
216 	}
217 	memcpy(sc->sc_enaddr, laddr, 6);
218 
219 	sc->sc_txdma = mapiodev(ca->ca_reg[2], PAGE_SIZE);
220 	sc->sc_rxdma = mapiodev(ca->ca_reg[4], PAGE_SIZE);
221 	sc->sc_txcmd = dbdma_alloc(BMAC_TXBUFS * sizeof(dbdma_command_t));
222 	sc->sc_rxcmd = dbdma_alloc((BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));
223 	sc->sc_txbuf = malloc(BMAC_BUFLEN * BMAC_TXBUFS, M_DEVBUF, M_NOWAIT);
224 	sc->sc_rxbuf = malloc(BMAC_BUFLEN * BMAC_RXBUFS, M_DEVBUF, M_NOWAIT);
225 	if (sc->sc_txbuf == NULL || sc->sc_rxbuf == NULL ||
226 	    sc->sc_txcmd == NULL || sc->sc_rxcmd == NULL) {
227 		printf("cannot allocate memory\n");
228 		return;
229 	}
230 
231 	printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2],
232 		ether_sprintf(laddr));
233 
234 	intr_establish(ca->ca_intr[0], IST_EDGE, IPL_NET, bmac_intr, sc);
235 	intr_establish(ca->ca_intr[2], IST_EDGE, IPL_NET, bmac_rint, sc);
236 
237 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
238 	ifp->if_softc = sc;
239 	ifp->if_ioctl = bmac_ioctl;
240 	ifp->if_start = bmac_start;
241 	ifp->if_flags =
242 		IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
243 	ifp->if_watchdog = bmac_watchdog;
244 	IFQ_SET_READY(&ifp->if_snd);
245 
246 	mii->mii_ifp = ifp;
247 	mii->mii_readreg = bmac_mii_readreg;
248 	mii->mii_writereg = bmac_mii_writereg;
249 	mii->mii_statchg = bmac_mii_statchg;
250 
251 	ifmedia_init(&mii->mii_media, 0, bmac_mediachange, bmac_mediastatus);
252 	mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
253 		      MII_OFFSET_ANY, 0);
254 
255 	/* Choose a default media. */
256 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
257 		ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL);
258 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T);
259 	} else
260 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
261 
262 	bmac_reset_chip(sc);
263 
264 	if_attach(ifp);
265 	ether_ifattach(ifp, sc->sc_enaddr);
266 }
267 
268 /*
269  * Reset and enable bmac by heathrow FCR.
270  */
271 void
272 bmac_reset_chip(sc)
273 	struct bmac_softc *sc;
274 {
275 	u_int v;
276 
277 	dbdma_reset(sc->sc_txdma);
278 	dbdma_reset(sc->sc_rxdma);
279 
280 	v = in32rb(heathrow_FCR);
281 
282 	v |= EnetEnable;
283 	out32rb(heathrow_FCR, v);
284 	delay(50000);
285 
286 	v |= ResetEnetCell;
287 	out32rb(heathrow_FCR, v);
288 	delay(50000);
289 
290 	v &= ~ResetEnetCell;
291 	out32rb(heathrow_FCR, v);
292 	delay(50000);
293 
294 	out32rb(heathrow_FCR, v);
295 }
296 
297 void
298 bmac_init(sc)
299 	struct bmac_softc *sc;
300 {
301 	struct ifnet *ifp = &sc->sc_if;
302 	struct ether_header *eh;
303 	void *data;
304 	int i, tb, bmcr;
305 	u_short *p;
306 
307 	bmac_reset_chip(sc);
308 
309 	/* XXX */
310 	bmcr = bmac_mii_readreg((struct device *)sc, 0, MII_BMCR);
311 	bmcr &= ~BMCR_ISO;
312 	bmac_mii_writereg((struct device *)sc, 0, MII_BMCR, bmcr);
313 
314 	bmac_write_reg(sc, RXRST, RxResetValue);
315 	bmac_write_reg(sc, TXRST, TxResetBit);
316 
317 	/* Wait for reset completion. */
318 	for (i = 1000; i > 0; i -= 10) {
319 		if ((bmac_read_reg(sc, TXRST) & TxResetBit) == 0)
320 			break;
321 		delay(10);
322 	}
323 	if (i <= 0)
324 		printf("%s: reset timeout\n", ifp->if_xname);
325 
326 	if (! (sc->sc_flags & BMAC_BMACPLUS))
327 		bmac_set_bits(sc, XCVRIF, ClkBit|SerialMode|COLActiveLow);
328 
329 	if ((mfpvr() >> 16) == MPC601)
330 		tb = mfrtcl();
331 	else
332 		tb = mftbl();
333 	bmac_write_reg(sc, RSEED, tb);
334 	bmac_set_bits(sc, XIFC, TxOutputEnable);
335 	bmac_read_reg(sc, PAREG);
336 
337 	/* Reset various counters. */
338 	bmac_write_reg(sc, NCCNT, 0);
339 	bmac_write_reg(sc, NTCNT, 0);
340 	bmac_write_reg(sc, EXCNT, 0);
341 	bmac_write_reg(sc, LTCNT, 0);
342 	bmac_write_reg(sc, FRCNT, 0);
343 	bmac_write_reg(sc, LECNT, 0);
344 	bmac_write_reg(sc, AECNT, 0);
345 	bmac_write_reg(sc, FECNT, 0);
346 	bmac_write_reg(sc, RXCV, 0);
347 
348 	/* Set tx fifo information. */
349 	bmac_write_reg(sc, TXTH, 4);	/* 4 octets before tx starts */
350 
351 	bmac_write_reg(sc, TXFIFOCSR, 0);
352 	bmac_write_reg(sc, TXFIFOCSR, TxFIFOEnable);
353 
354 	/* Set rx fifo information. */
355 	bmac_write_reg(sc, RXFIFOCSR, 0);
356 	bmac_write_reg(sc, RXFIFOCSR, RxFIFOEnable);
357 
358 	/* Clear status register. */
359 	bmac_read_reg(sc, STATUS);
360 
361 	bmac_write_reg(sc, HASH3, 0);
362 	bmac_write_reg(sc, HASH2, 0);
363 	bmac_write_reg(sc, HASH1, 0);
364 	bmac_write_reg(sc, HASH0, 0);
365 
366 	/* Set MAC address. */
367 	p = (u_short *)sc->sc_enaddr;
368 	bmac_write_reg(sc, MADD0, *p++);
369 	bmac_write_reg(sc, MADD1, *p++);
370 	bmac_write_reg(sc, MADD2, *p);
371 
372 	bmac_write_reg(sc, RXCFG,
373 		RxCRCEnable | RxHashFilterEnable | RxRejectOwnPackets);
374 
375 	if (ifp->if_flags & IFF_PROMISC)
376 		bmac_set_bits(sc, RXCFG, RxPromiscEnable);
377 
378 	bmac_init_dma(sc);
379 
380 	/* Enable TX/RX */
381 	bmac_set_bits(sc, RXCFG, RxMACEnable);
382 	bmac_set_bits(sc, TXCFG, TxMACEnable);
383 
384 	bmac_write_reg(sc, INTDISABLE, NormalIntEvents);
385 
386 	ifp->if_flags |= IFF_RUNNING;
387 	ifp->if_flags &= ~IFF_OACTIVE;
388 	ifp->if_timer = 0;
389 
390 	data = sc->sc_txbuf;
391 	eh = (struct ether_header *)data;
392 
393 	memset(data, 0, sizeof(eh) + ETHERMIN);
394 	memcpy(eh->ether_dhost, sc->sc_enaddr, ETHER_ADDR_LEN);
395 	memcpy(eh->ether_shost, sc->sc_enaddr, ETHER_ADDR_LEN);
396 	bmac_transmit_packet(sc, data, sizeof(eh) + ETHERMIN);
397 
398 	bmac_start(ifp);
399 
400 	callout_reset(&sc->sc_tick_ch, hz, bmac_mii_tick, sc);
401 }
402 
403 void
404 bmac_init_dma(sc)
405 	struct bmac_softc *sc;
406 {
407 	dbdma_command_t *cmd = sc->sc_rxcmd;
408 	int i;
409 
410 	dbdma_reset(sc->sc_txdma);
411 	dbdma_reset(sc->sc_rxdma);
412 
413 	memset(sc->sc_txcmd, 0, BMAC_TXBUFS * sizeof(dbdma_command_t));
414 	memset(sc->sc_rxcmd, 0, (BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));
415 
416 	for (i = 0; i < BMAC_RXBUFS; i++) {
417 		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, BMAC_BUFLEN,
418 			vtophys((vaddr_t)sc->sc_rxbuf + BMAC_BUFLEN * i),
419 			DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
420 		cmd++;
421 	}
422 	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
423 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
424 	out32rb(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_rxcmd));
425 
426 	sc->sc_rxlast = 0;
427 
428 	dbdma_start(sc->sc_rxdma, sc->sc_rxcmd);
429 }
430 
431 int
432 bmac_intr(v)
433 	void *v;
434 {
435 	struct bmac_softc *sc = v;
436 	int stat;
437 
438 	stat = bmac_read_reg(sc, STATUS);
439 	if (stat == 0)
440 		return 0;
441 
442 #ifdef BMAC_DEBUG
443 	printf("bmac_intr status = 0x%x\n", stat);
444 #endif
445 
446 	if (stat & IntFrameSent) {
447 		sc->sc_if.if_flags &= ~IFF_OACTIVE;
448 		sc->sc_if.if_timer = 0;
449 		sc->sc_if.if_opackets++;
450 		bmac_start(&sc->sc_if);
451 	}
452 
453 	/* XXX should do more! */
454 
455 	return 1;
456 }
457 
458 int
459 bmac_rint(v)
460 	void *v;
461 {
462 	struct bmac_softc *sc = v;
463 	struct ifnet *ifp = &sc->sc_if;
464 	struct mbuf *m;
465 	dbdma_command_t *cmd;
466 	int status, resid, count, datalen;
467 	int i, n;
468 	void *data;
469 
470 	i = sc->sc_rxlast;
471 	for (n = 0; n < BMAC_RXBUFS; n++, i++) {
472 		if (i == BMAC_RXBUFS)
473 			i = 0;
474 		cmd = &sc->sc_rxcmd[i];
475 		status = in16rb(&cmd->d_status);
476 		resid = in16rb(&cmd->d_resid);
477 
478 #ifdef BMAC_DEBUG
479 		if (status != 0 && status != 0x8440 && status != 0x9440)
480 			printf("bmac_rint status = 0x%x\n", status);
481 #endif
482 
483 		if ((status & DBDMA_CNTRL_ACTIVE) == 0)	/* 0x9440 | 0x8440 */
484 			continue;
485 		count = in16rb(&cmd->d_count);
486 		datalen = count - resid - 2;		/* 2 == framelen */
487 		if (datalen < sizeof(struct ether_header)) {
488 			printf("%s: short packet len = %d\n",
489 				ifp->if_xname, datalen);
490 			goto next;
491 		}
492 		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0);
493 		data = (char *)sc->sc_rxbuf + BMAC_BUFLEN * i;
494 
495 		/* XXX Sometimes bmac reads one extra byte. */
496 		if (datalen == ETHER_MAX_LEN + 1)
497 			datalen--;
498 
499 		/* Trim the CRC. */
500 		datalen -= ETHER_CRC_LEN;
501 
502 		m = bmac_get(sc, data, datalen);
503 		if (m == NULL) {
504 			ifp->if_ierrors++;
505 			goto next;
506 		}
507 
508 #if NBPFILTER > 0
509 		/*
510 		 * Check if there's a BPF listener on this interface.
511 		 * If so, hand off the raw packet to BPF.
512 		 */
513 		if (ifp->if_bpf)
514 			bpf_mtap(ifp->if_bpf, m);
515 #endif
516 		(*ifp->if_input)(ifp, m);
517 		ifp->if_ipackets++;
518 
519 next:
520 		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS,
521 			DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
522 
523 		cmd->d_status = 0;
524 		cmd->d_resid = 0;
525 		sc->sc_rxlast = i + 1;
526 	}
527 	bmac_mediachange(ifp);
528 
529 	dbdma_continue(sc->sc_rxdma);
530 
531 	return 1;
532 }
533 
534 void
535 bmac_reset(sc)
536 	struct bmac_softc *sc;
537 {
538 	int s;
539 
540 	s = splnet();
541 	bmac_init(sc);
542 	splx(s);
543 }
544 
545 void
546 bmac_stop(sc)
547 	struct bmac_softc *sc;
548 {
549 	struct ifnet *ifp = &sc->sc_if;
550 	int s;
551 
552 	s = splnet();
553 
554 	callout_stop(&sc->sc_tick_ch);
555 	mii_down(&sc->sc_mii);
556 
557 	/* Disable TX/RX. */
558 	bmac_reset_bits(sc, TXCFG, TxMACEnable);
559 	bmac_reset_bits(sc, RXCFG, RxMACEnable);
560 
561 	/* Disable all interrupts. */
562 	bmac_write_reg(sc, INTDISABLE, NoEventsMask);
563 
564 	dbdma_stop(sc->sc_txdma);
565 	dbdma_stop(sc->sc_rxdma);
566 
567 	ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
568 	ifp->if_timer = 0;
569 
570 	splx(s);
571 }
572 
573 void
574 bmac_start(ifp)
575 	struct ifnet *ifp;
576 {
577 	struct bmac_softc *sc = ifp->if_softc;
578 	struct mbuf *m;
579 	int tlen;
580 
581 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
582 		return;
583 
584 	while (1) {
585 		if (ifp->if_flags & IFF_OACTIVE)
586 			return;
587 
588 		IFQ_DEQUEUE(&ifp->if_snd, m);
589 		if (m == 0)
590 			break;
591 #if NBPFILTER > 0
592 		/*
593 		 * If BPF is listening on this interface, let it see the
594 		 * packet before we commit it to the wire.
595 		 */
596 		if (ifp->if_bpf)
597 			bpf_mtap(ifp->if_bpf, m);
598 #endif
599 
600 		ifp->if_flags |= IFF_OACTIVE;
601 		tlen = bmac_put(sc, sc->sc_txbuf, m);
602 
603 		/* 5 seconds to watch for failing to transmit */
604 		ifp->if_timer = 5;
605 		ifp->if_opackets++;		/* # of pkts */
606 
607 		bmac_transmit_packet(sc, sc->sc_txbuf, tlen);
608 	}
609 }
610 
611 void
612 bmac_transmit_packet(sc, buff, len)
613 	struct bmac_softc *sc;
614 	void *buff;
615 	int len;
616 {
617 	dbdma_command_t *cmd = sc->sc_txcmd;
618 	vaddr_t va = (vaddr_t)buff;
619 
620 #ifdef BMAC_DEBUG
621 	if (vtophys(va) + len - 1 != vtophys(va + len - 1))
622 		panic("bmac_transmit_packet");
623 #endif
624 
625 	DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, len, vtophys(va),
626 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
627 	cmd++;
628 	DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0,
629 		DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
630 
631 	dbdma_start(sc->sc_txdma, sc->sc_txcmd);
632 }
633 
634 int
635 bmac_put(sc, buff, m)
636 	struct bmac_softc *sc;
637 	void *buff;
638 	struct mbuf *m;
639 {
640 	struct mbuf *n;
641 	int len, tlen = 0;
642 
643 	for (; m; m = n) {
644 		len = m->m_len;
645 		if (len == 0) {
646 			MFREE(m, n);
647 			continue;
648 		}
649 		memcpy(buff, mtod(m, void *), len);
650 		buff = (char *)buff + len;
651 		tlen += len;
652 		MFREE(m, n);
653 	}
654 	if (tlen > PAGE_SIZE)
655 		panic("%s: putpacket packet overflow", sc->sc_dev.dv_xname);
656 
657 	return tlen;
658 }
659 
660 struct mbuf *
661 bmac_get(sc, pkt, totlen)
662 	struct bmac_softc *sc;
663 	void *pkt;
664 	int totlen;
665 {
666 	struct mbuf *m;
667 	struct mbuf *top, **mp;
668 	int len;
669 
670 	MGETHDR(m, M_DONTWAIT, MT_DATA);
671 	if (m == 0)
672 		return 0;
673 	m->m_pkthdr.rcvif = &sc->sc_if;
674 	m->m_pkthdr.len = totlen;
675 	len = MHLEN;
676 	top = 0;
677 	mp = &top;
678 
679 	while (totlen > 0) {
680 		if (top) {
681 			MGET(m, M_DONTWAIT, MT_DATA);
682 			if (m == 0) {
683 				m_freem(top);
684 				return 0;
685 			}
686 			len = MLEN;
687 		}
688 		if (totlen >= MINCLSIZE) {
689 			MCLGET(m, M_DONTWAIT);
690 			if ((m->m_flags & M_EXT) == 0) {
691 				m_free(m);
692 				m_freem(top);
693 				return 0;
694 			}
695 			len = MCLBYTES;
696 		}
697 		m->m_len = len = min(totlen, len);
698 		memcpy(mtod(m, void *), pkt, len);
699 		pkt = (char *)pkt + len;
700 		totlen -= len;
701 		*mp = m;
702 		mp = &m->m_next;
703 	}
704 
705 	return top;
706 }
707 
708 void
709 bmac_watchdog(ifp)
710 	struct ifnet *ifp;
711 {
712 	struct bmac_softc *sc = ifp->if_softc;
713 
714 	bmac_reset_bits(sc, RXCFG, RxMACEnable);
715 	bmac_reset_bits(sc, TXCFG, TxMACEnable);
716 
717 	printf("%s: device timeout\n", ifp->if_xname);
718 	ifp->if_oerrors++;
719 
720 	bmac_reset(sc);
721 }
722 
723 int
724 bmac_ioctl(ifp, cmd, data)
725 	struct ifnet *ifp;
726 	u_long cmd;
727 	void *data;
728 {
729 	struct bmac_softc *sc = ifp->if_softc;
730 	struct ifaddr *ifa = (struct ifaddr *)data;
731 	struct ifreq *ifr = (struct ifreq *)data;
732 	int s, error = 0;
733 
734 	s = splnet();
735 
736 	switch (cmd) {
737 
738 	case SIOCSIFADDR:
739 		ifp->if_flags |= IFF_UP;
740 
741 		switch (ifa->ifa_addr->sa_family) {
742 #ifdef INET
743 		case AF_INET:
744 			bmac_init(sc);
745 			arp_ifinit(ifp, ifa);
746 			break;
747 #endif
748 		default:
749 			bmac_init(sc);
750 			break;
751 		}
752 		break;
753 
754 	case SIOCSIFFLAGS:
755 		if ((ifp->if_flags & IFF_UP) == 0 &&
756 		    (ifp->if_flags & IFF_RUNNING) != 0) {
757 			/*
758 			 * If interface is marked down and it is running, then
759 			 * stop it.
760 			 */
761 			bmac_stop(sc);
762 			ifp->if_flags &= ~IFF_RUNNING;
763 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
764 		    (ifp->if_flags & IFF_RUNNING) == 0) {
765 			/*
766 			 * If interface is marked up and it is stopped, then
767 			 * start it.
768 			 */
769 			bmac_init(sc);
770 		} else {
771 			/*
772 			 * Reset the interface to pick up changes in any other
773 			 * flags that affect hardware registers.
774 			 */
775 			/*bmac_stop(sc);*/
776 			bmac_init(sc);
777 		}
778 #ifdef BMAC_DEBUG
779 		if (ifp->if_flags & IFF_DEBUG)
780 			sc->sc_flags |= BMAC_DEBUGFLAG;
781 #endif
782 		break;
783 
784 	case SIOCADDMULTI:
785 	case SIOCDELMULTI:
786 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
787 			/*
788 			 * Multicast list has changed; set the hardware filter
789 			 * accordingly.
790 			 */
791 			if (ifp->if_flags & IFF_RUNNING) {
792 				bmac_init(sc);
793 				bmac_setladrf(sc);
794 			}
795 			error = 0;
796 		}
797 		break;
798 
799 	case SIOCGIFMEDIA:
800 	case SIOCSIFMEDIA:
801 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
802 		break;
803 
804 	default:
805 		error = EINVAL;
806 	}
807 
808 	splx(s);
809 	return error;
810 }
811 
812 int
813 bmac_mediachange(ifp)
814 	struct ifnet *ifp;
815 {
816 	struct bmac_softc *sc = ifp->if_softc;
817 
818 	return mii_mediachg(&sc->sc_mii);
819 }
820 
821 void
822 bmac_mediastatus(ifp, ifmr)
823 	struct ifnet *ifp;
824 	struct ifmediareq *ifmr;
825 {
826 	struct bmac_softc *sc = ifp->if_softc;
827 
828 	mii_pollstat(&sc->sc_mii);
829 
830 	ifmr->ifm_status = sc->sc_mii.mii_media_status;
831 	ifmr->ifm_active = sc->sc_mii.mii_media_active;
832 }
833 
834 /*
835  * Set up the logical address filter.
836  */
837 void
838 bmac_setladrf(sc)
839 	struct bmac_softc *sc;
840 {
841 	struct ifnet *ifp = &sc->sc_if;
842 	struct ether_multi *enm;
843 	struct ether_multistep step;
844 	u_int32_t crc;
845 	u_int16_t hash[4];
846 	int x;
847 
848 	/*
849 	 * Set up multicast address filter by passing all multicast addresses
850 	 * through a crc generator, and then using the high order 6 bits as an
851 	 * index into the 64 bit logical address filter.  The high order bit
852 	 * selects the word, while the rest of the bits select the bit within
853 	 * the word.
854 	 */
855 
856 	if (ifp->if_flags & IFF_PROMISC) {
857 		bmac_set_bits(sc, RXCFG, RxPromiscEnable);
858 		return;
859 	}
860 
861 	if (ifp->if_flags & IFF_ALLMULTI) {
862 		hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
863 		goto chipit;
864 	}
865 
866 	hash[3] = hash[2] = hash[1] = hash[0] = 0;
867 
868 	ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
869 	while (enm != NULL) {
870 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
871 			/*
872 			 * We must listen to a range of multicast addresses.
873 			 * For now, just accept all multicasts, rather than
874 			 * trying to set only those filter bits needed to match
875 			 * the range.  (At this time, the only use of address
876 			 * ranges is for IP multicast routing, for which the
877 			 * range is big enough to require all bits set.)
878 			 */
879 			hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
880 			ifp->if_flags |= IFF_ALLMULTI;
881 			goto chipit;
882 		}
883 
884 		crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
885 
886 		/* Just want the 6 most significant bits. */
887 		crc >>= 26;
888 
889 		/* Set the corresponding bit in the filter. */
890 		hash[crc >> 4] |= 1 << (crc & 0xf);
891 
892 		ETHER_NEXT_MULTI(step, enm);
893 	}
894 
895 	ifp->if_flags &= ~IFF_ALLMULTI;
896 
897 chipit:
898 	bmac_write_reg(sc, HASH0, hash[0]);
899 	bmac_write_reg(sc, HASH1, hash[1]);
900 	bmac_write_reg(sc, HASH2, hash[2]);
901 	bmac_write_reg(sc, HASH3, hash[3]);
902 	x = bmac_read_reg(sc, RXCFG);
903 	x &= ~RxPromiscEnable;
904 	x |= RxHashFilterEnable;
905 	bmac_write_reg(sc, RXCFG, x);
906 }
907 
908 int
909 bmac_mii_readreg(dev, phy, reg)
910 	struct device *dev;
911 	int phy, reg;
912 {
913 	return mii_bitbang_readreg(dev, &bmac_mbo, phy, reg);
914 }
915 
916 void
917 bmac_mii_writereg(dev, phy, reg, val)
918 	struct device *dev;
919 	int phy, reg, val;
920 {
921 	mii_bitbang_writereg(dev, &bmac_mbo, phy, reg, val);
922 }
923 
924 u_int32_t
925 bmac_mbo_read(dev)
926 	struct device *dev;
927 {
928 	struct bmac_softc *sc = (void *)dev;
929 
930 	return bmac_read_reg(sc, MIFCSR);
931 }
932 
933 void
934 bmac_mbo_write(dev, val)
935 	struct device *dev;
936 	u_int32_t val;
937 {
938 	struct bmac_softc *sc = (void *)dev;
939 
940 	bmac_write_reg(sc, MIFCSR, val);
941 }
942 
943 void
944 bmac_mii_statchg(dev)
945 	struct device *dev;
946 {
947 	struct bmac_softc *sc = (void *)dev;
948 	int x;
949 
950 	/* Update duplex mode in TX configuration */
951 	x = bmac_read_reg(sc, TXCFG);
952 	if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
953 		x |= TxFullDuplex;
954 	else
955 		x &= ~TxFullDuplex;
956 	bmac_write_reg(sc, TXCFG, x);
957 
958 #ifdef BMAC_DEBUG
959 	printf("bmac_mii_statchg 0x%x\n",
960 		IFM_OPTIONS(sc->sc_mii.mii_media_active));
961 #endif
962 }
963 
964 void
965 bmac_mii_tick(v)
966 	void *v;
967 {
968 	struct bmac_softc *sc = v;
969 	int s;
970 
971 	s = splnet();
972 	mii_tick(&sc->sc_mii);
973 	splx(s);
974 
975 	callout_reset(&sc->sc_tick_ch, hz, bmac_mii_tick, sc);
976 }
977