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