1 /* $NetBSD: if_bm.c,v 1.39 2009/03/14 15:36:09 dsl Exp $ */
4 * Copyright (C) 1998, 1999, 2000 Tsubai Masanari. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: if_bm.c,v 1.39 2009/03/14 15:36:09 dsl Exp $");
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/ioctl.h>
38 #include <sys/kernel.h>
40 #include <sys/socket.h>
41 #include <sys/systm.h>
42 #include <sys/callout.h>
44 #include <uvm/uvm_extern.h>
47 #include <net/if_dl.h>
48 #include <net/if_ether.h>
49 #include <net/if_media.h>
56 #include <netinet/in.h>
57 #include <netinet/if_inarp.h>
61 #include <dev/ofw/openfirm.h>
63 #include <dev/mii/mii.h>
64 #include <dev/mii/miivar.h>
65 #include <dev/mii/mii_bitbang.h>
67 #include <powerpc/spr.h>
69 #include <machine/autoconf.h>
70 #include <machine/pio.h>
72 #include <macppc/dev/dbdma.h>
73 #include <macppc/dev/if_bmreg.h>
74 #include <macppc/dev/obiovar.h>
77 #define BMAC_RXBUFS 16
78 #define BMAC_BUFLEN 2048
82 struct ethercom sc_ethercom
;
83 #define sc_if sc_ethercom.ec_if
84 struct callout sc_tick_ch
;
85 bus_space_tag_t sc_iot
;
86 bus_space_handle_t sc_ioh
;
87 dbdma_regmap_t
*sc_txdma
;
88 dbdma_regmap_t
*sc_rxdma
;
89 dbdma_command_t
*sc_txcmd
;
90 dbdma_command_t
*sc_rxcmd
;
95 struct mii_data sc_mii
;
99 #define BMAC_BMACPLUS 0x01
100 #define BMAC_DEBUGFLAG 0x02
102 int bmac_match(struct device
*, struct cfdata
*, void *);
103 void bmac_attach(struct device
*, struct device
*, void *);
104 void bmac_reset_chip(struct bmac_softc
*);
105 void bmac_init(struct bmac_softc
*);
106 void bmac_init_dma(struct bmac_softc
*);
107 int bmac_intr(void *);
108 int bmac_rint(void *);
109 void bmac_reset(struct bmac_softc
*);
110 void bmac_stop(struct bmac_softc
*);
111 void bmac_start(struct ifnet
*);
112 void bmac_transmit_packet(struct bmac_softc
*, void *, int);
113 int bmac_put(struct bmac_softc
*, void *, struct mbuf
*);
114 struct mbuf
*bmac_get(struct bmac_softc
*, void *, int);
115 void bmac_watchdog(struct ifnet
*);
116 int bmac_ioctl(struct ifnet
*, u_long
, void *);
117 void bmac_setladrf(struct bmac_softc
*);
119 int bmac_mii_readreg(struct device
*, int, int);
120 void bmac_mii_writereg(struct device
*, int, int, int);
121 void bmac_mii_statchg(struct device
*);
122 void bmac_mii_tick(void *);
123 u_int32_t
bmac_mbo_read(struct device
*);
124 void bmac_mbo_write(struct device
*, u_int32_t
);
126 CFATTACH_DECL(bm
, sizeof(struct bmac_softc
),
127 bmac_match
, bmac_attach
, NULL
, NULL
);
129 const struct mii_bitbang_ops bmac_mbo
= {
130 bmac_mbo_read
, bmac_mbo_write
,
131 { MIFDO
, MIFDI
, MIFDC
, MIFDIR
, 0 }
134 static inline uint16_t
135 bmac_read_reg(struct bmac_softc
*sc
, bus_size_t off
)
137 return bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, off
);
141 bmac_write_reg(struct bmac_softc
*sc
, bus_size_t off
, uint16_t val
)
143 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, off
, val
);
147 bmac_set_bits(struct bmac_softc
*sc
, bus_size_t off
, uint16_t val
)
149 val
|= bmac_read_reg(sc
, off
);
150 bmac_write_reg(sc
, off
, val
);
154 bmac_reset_bits(struct bmac_softc
*sc
, bus_size_t off
, uint16_t val
)
156 bmac_write_reg(sc
, off
, bmac_read_reg(sc
, off
) & ~val
);
160 bmac_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
162 struct confargs
*ca
= aux
;
164 if (ca
->ca_nreg
< 24 || ca
->ca_nintr
< 12)
167 if (strcmp(ca
->ca_name
, "bmac") == 0) /* bmac */
169 if (strcmp(ca
->ca_name
, "ethernet") == 0) /* bmac+ */
176 bmac_attach(struct device
*parent
, struct device
*self
, void *aux
)
178 struct confargs
*ca
= aux
;
179 struct bmac_softc
*sc
= (void *)self
;
180 struct ifnet
*ifp
= &sc
->sc_if
;
181 struct mii_data
*mii
= &sc
->sc_mii
;
184 callout_init(&sc
->sc_tick_ch
, 0);
187 if (strcmp(ca
->ca_name
, "ethernet") == 0) {
191 OF_package_to_path(ca
->ca_node
, name
, sizeof(name
));
193 sc
->sc_flags
|= BMAC_BMACPLUS
;
196 ca
->ca_reg
[0] += ca
->ca_baseaddr
;
197 ca
->ca_reg
[2] += ca
->ca_baseaddr
;
198 ca
->ca_reg
[4] += ca
->ca_baseaddr
;
200 sc
->sc_iot
= ca
->ca_tag
;
201 if (bus_space_map(sc
->sc_iot
, ca
->ca_reg
[0], ca
->ca_reg
[1], 0,
203 aprint_error(": couldn't map %#x", ca
->ca_reg
[0]);
207 bmac_write_reg(sc
, INTDISABLE
, NoEventsMask
);
209 if (OF_getprop(ca
->ca_node
, "local-mac-address", laddr
, 6) == -1 &&
210 OF_getprop(ca
->ca_node
, "mac-address", laddr
, 6) == -1) {
211 printf(": cannot get mac-address\n");
214 memcpy(sc
->sc_enaddr
, laddr
, 6);
216 sc
->sc_txdma
= mapiodev(ca
->ca_reg
[2], PAGE_SIZE
);
217 sc
->sc_rxdma
= mapiodev(ca
->ca_reg
[4], PAGE_SIZE
);
218 sc
->sc_txcmd
= dbdma_alloc(BMAC_TXBUFS
* sizeof(dbdma_command_t
));
219 sc
->sc_rxcmd
= dbdma_alloc((BMAC_RXBUFS
+ 1) * sizeof(dbdma_command_t
));
220 sc
->sc_txbuf
= malloc(BMAC_BUFLEN
* BMAC_TXBUFS
, M_DEVBUF
, M_NOWAIT
);
221 sc
->sc_rxbuf
= malloc(BMAC_BUFLEN
* BMAC_RXBUFS
, M_DEVBUF
, M_NOWAIT
);
222 if (sc
->sc_txbuf
== NULL
|| sc
->sc_rxbuf
== NULL
||
223 sc
->sc_txcmd
== NULL
|| sc
->sc_rxcmd
== NULL
) {
224 printf("cannot allocate memory\n");
228 printf(" irq %d,%d: address %s\n", ca
->ca_intr
[0], ca
->ca_intr
[2],
229 ether_sprintf(laddr
));
231 intr_establish(ca
->ca_intr
[0], IST_EDGE
, IPL_NET
, bmac_intr
, sc
);
232 intr_establish(ca
->ca_intr
[2], IST_EDGE
, IPL_NET
, bmac_rint
, sc
);
234 memcpy(ifp
->if_xname
, sc
->sc_dev
.dv_xname
, IFNAMSIZ
);
236 ifp
->if_ioctl
= bmac_ioctl
;
237 ifp
->if_start
= bmac_start
;
239 IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
| IFF_MULTICAST
;
240 ifp
->if_watchdog
= bmac_watchdog
;
241 IFQ_SET_READY(&ifp
->if_snd
);
244 mii
->mii_readreg
= bmac_mii_readreg
;
245 mii
->mii_writereg
= bmac_mii_writereg
;
246 mii
->mii_statchg
= bmac_mii_statchg
;
248 sc
->sc_ethercom
.ec_mii
= mii
;
249 ifmedia_init(&mii
->mii_media
, 0, ether_mediachange
, ether_mediastatus
);
250 mii_attach(&sc
->sc_dev
, mii
, 0xffffffff, MII_PHY_ANY
,
253 /* Choose a default media. */
254 if (LIST_FIRST(&mii
->mii_phys
) == NULL
) {
255 ifmedia_add(&mii
->mii_media
, IFM_ETHER
|IFM_10_T
, 0, NULL
);
256 ifmedia_set(&mii
->mii_media
, IFM_ETHER
|IFM_10_T
);
258 ifmedia_set(&mii
->mii_media
, IFM_ETHER
|IFM_AUTO
);
263 ether_ifattach(ifp
, sc
->sc_enaddr
);
267 * Reset and enable bmac by heathrow FCR.
270 bmac_reset_chip(struct bmac_softc
*sc
)
274 dbdma_reset(sc
->sc_txdma
);
275 dbdma_reset(sc
->sc_rxdma
);
277 v
= obio_read_4(HEATHROW_FCR
);
280 obio_write_4(HEATHROW_FCR
, v
);
284 obio_write_4(HEATHROW_FCR
, v
);
288 obio_write_4(HEATHROW_FCR
, v
);
291 obio_write_4(HEATHROW_FCR
, v
);
295 bmac_init(struct bmac_softc
*sc
)
297 struct ifnet
*ifp
= &sc
->sc_if
;
298 struct ether_header
*eh
;
306 bmcr
= bmac_mii_readreg((struct device
*)sc
, 0, MII_BMCR
);
308 bmac_mii_writereg((struct device
*)sc
, 0, MII_BMCR
, bmcr
);
310 bmac_write_reg(sc
, RXRST
, RxResetValue
);
311 bmac_write_reg(sc
, TXRST
, TxResetBit
);
313 /* Wait for reset completion. */
314 for (i
= 1000; i
> 0; i
-= 10) {
315 if ((bmac_read_reg(sc
, TXRST
) & TxResetBit
) == 0)
320 printf("%s: reset timeout\n", ifp
->if_xname
);
322 if (! (sc
->sc_flags
& BMAC_BMACPLUS
))
323 bmac_set_bits(sc
, XCVRIF
, ClkBit
|SerialMode
|COLActiveLow
);
325 if ((mfpvr() >> 16) == MPC601
)
329 bmac_write_reg(sc
, RSEED
, tb
);
330 bmac_set_bits(sc
, XIFC
, TxOutputEnable
);
331 bmac_read_reg(sc
, PAREG
);
333 /* Reset various counters. */
334 bmac_write_reg(sc
, NCCNT
, 0);
335 bmac_write_reg(sc
, NTCNT
, 0);
336 bmac_write_reg(sc
, EXCNT
, 0);
337 bmac_write_reg(sc
, LTCNT
, 0);
338 bmac_write_reg(sc
, FRCNT
, 0);
339 bmac_write_reg(sc
, LECNT
, 0);
340 bmac_write_reg(sc
, AECNT
, 0);
341 bmac_write_reg(sc
, FECNT
, 0);
342 bmac_write_reg(sc
, RXCV
, 0);
344 /* Set tx fifo information. */
345 bmac_write_reg(sc
, TXTH
, 4); /* 4 octets before tx starts */
347 bmac_write_reg(sc
, TXFIFOCSR
, 0);
348 bmac_write_reg(sc
, TXFIFOCSR
, TxFIFOEnable
);
350 /* Set rx fifo information. */
351 bmac_write_reg(sc
, RXFIFOCSR
, 0);
352 bmac_write_reg(sc
, RXFIFOCSR
, RxFIFOEnable
);
354 /* Clear status register. */
355 bmac_read_reg(sc
, STATUS
);
357 bmac_write_reg(sc
, HASH3
, 0);
358 bmac_write_reg(sc
, HASH2
, 0);
359 bmac_write_reg(sc
, HASH1
, 0);
360 bmac_write_reg(sc
, HASH0
, 0);
362 /* Set MAC address. */
363 p
= (u_short
*)sc
->sc_enaddr
;
364 bmac_write_reg(sc
, MADD0
, *p
++);
365 bmac_write_reg(sc
, MADD1
, *p
++);
366 bmac_write_reg(sc
, MADD2
, *p
);
368 bmac_write_reg(sc
, RXCFG
,
369 RxCRCEnable
| RxHashFilterEnable
| RxRejectOwnPackets
);
371 if (ifp
->if_flags
& IFF_PROMISC
)
372 bmac_set_bits(sc
, RXCFG
, RxPromiscEnable
);
377 bmac_set_bits(sc
, RXCFG
, RxMACEnable
);
378 bmac_set_bits(sc
, TXCFG
, TxMACEnable
);
380 bmac_write_reg(sc
, INTDISABLE
, NormalIntEvents
);
382 ifp
->if_flags
|= IFF_RUNNING
;
383 ifp
->if_flags
&= ~IFF_OACTIVE
;
387 eh
= (struct ether_header
*)data
;
389 memset(data
, 0, sizeof(eh
) + ETHERMIN
);
390 memcpy(eh
->ether_dhost
, sc
->sc_enaddr
, ETHER_ADDR_LEN
);
391 memcpy(eh
->ether_shost
, sc
->sc_enaddr
, ETHER_ADDR_LEN
);
392 bmac_transmit_packet(sc
, data
, sizeof(eh
) + ETHERMIN
);
396 callout_reset(&sc
->sc_tick_ch
, hz
, bmac_mii_tick
, sc
);
400 bmac_init_dma(struct bmac_softc
*sc
)
402 dbdma_command_t
*cmd
= sc
->sc_rxcmd
;
405 dbdma_reset(sc
->sc_txdma
);
406 dbdma_reset(sc
->sc_rxdma
);
408 memset(sc
->sc_txcmd
, 0, BMAC_TXBUFS
* sizeof(dbdma_command_t
));
409 memset(sc
->sc_rxcmd
, 0, (BMAC_RXBUFS
+ 1) * sizeof(dbdma_command_t
));
411 for (i
= 0; i
< BMAC_RXBUFS
; i
++) {
412 DBDMA_BUILD(cmd
, DBDMA_CMD_IN_LAST
, 0, BMAC_BUFLEN
,
413 vtophys((vaddr_t
)sc
->sc_rxbuf
+ BMAC_BUFLEN
* i
),
414 DBDMA_INT_ALWAYS
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
417 DBDMA_BUILD(cmd
, DBDMA_CMD_NOP
, 0, 0, 0,
418 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_ALWAYS
);
419 out32rb(&cmd
->d_cmddep
, vtophys((vaddr_t
)sc
->sc_rxcmd
));
423 dbdma_start(sc
->sc_rxdma
, sc
->sc_rxcmd
);
429 struct bmac_softc
*sc
= v
;
432 stat
= bmac_read_reg(sc
, STATUS
);
437 printf("bmac_intr status = 0x%x\n", stat
);
440 if (stat
& IntFrameSent
) {
441 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
442 sc
->sc_if
.if_timer
= 0;
443 sc
->sc_if
.if_opackets
++;
444 bmac_start(&sc
->sc_if
);
447 /* XXX should do more! */
455 struct bmac_softc
*sc
= v
;
456 struct ifnet
*ifp
= &sc
->sc_if
;
458 dbdma_command_t
*cmd
;
459 int status
, resid
, count
, datalen
;
464 for (n
= 0; n
< BMAC_RXBUFS
; n
++, i
++) {
465 if (i
== BMAC_RXBUFS
)
467 cmd
= &sc
->sc_rxcmd
[i
];
468 status
= in16rb(&cmd
->d_status
);
469 resid
= in16rb(&cmd
->d_resid
);
472 if (status
!= 0 && status
!= 0x8440 && status
!= 0x9440)
473 printf("bmac_rint status = 0x%x\n", status
);
476 if ((status
& DBDMA_CNTRL_ACTIVE
) == 0) /* 0x9440 | 0x8440 */
478 count
= in16rb(&cmd
->d_count
);
479 datalen
= count
- resid
- 2; /* 2 == framelen */
480 if (datalen
< sizeof(struct ether_header
)) {
481 printf("%s: short packet len = %d\n",
482 ifp
->if_xname
, datalen
);
485 DBDMA_BUILD_CMD(cmd
, DBDMA_CMD_STOP
, 0, 0, 0, 0);
486 data
= (char *)sc
->sc_rxbuf
+ BMAC_BUFLEN
* i
;
488 /* XXX Sometimes bmac reads one extra byte. */
489 if (datalen
== ETHER_MAX_LEN
+ 1)
493 datalen
-= ETHER_CRC_LEN
;
495 m
= bmac_get(sc
, data
, datalen
);
503 * Check if there's a BPF listener on this interface.
504 * If so, hand off the raw packet to BPF.
507 bpf_mtap(ifp
->if_bpf
, m
);
509 (*ifp
->if_input
)(ifp
, m
);
513 DBDMA_BUILD_CMD(cmd
, DBDMA_CMD_IN_LAST
, 0, DBDMA_INT_ALWAYS
,
514 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
518 sc
->sc_rxlast
= i
+ 1;
520 ether_mediachange(ifp
);
522 dbdma_continue(sc
->sc_rxdma
);
528 bmac_reset(struct bmac_softc
*sc
)
538 bmac_stop(struct bmac_softc
*sc
)
540 struct ifnet
*ifp
= &sc
->sc_if
;
545 callout_stop(&sc
->sc_tick_ch
);
546 mii_down(&sc
->sc_mii
);
549 bmac_reset_bits(sc
, TXCFG
, TxMACEnable
);
550 bmac_reset_bits(sc
, RXCFG
, RxMACEnable
);
552 /* Disable all interrupts. */
553 bmac_write_reg(sc
, INTDISABLE
, NoEventsMask
);
555 dbdma_stop(sc
->sc_txdma
);
556 dbdma_stop(sc
->sc_rxdma
);
558 ifp
->if_flags
&= ~(IFF_UP
| IFF_RUNNING
);
565 bmac_start(struct ifnet
*ifp
)
567 struct bmac_softc
*sc
= ifp
->if_softc
;
571 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
575 if (ifp
->if_flags
& IFF_OACTIVE
)
578 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
583 * If BPF is listening on this interface, let it see the
584 * packet before we commit it to the wire.
587 bpf_mtap(ifp
->if_bpf
, m
);
590 ifp
->if_flags
|= IFF_OACTIVE
;
591 tlen
= bmac_put(sc
, sc
->sc_txbuf
, m
);
593 /* 5 seconds to watch for failing to transmit */
595 ifp
->if_opackets
++; /* # of pkts */
597 bmac_transmit_packet(sc
, sc
->sc_txbuf
, tlen
);
602 bmac_transmit_packet(struct bmac_softc
*sc
, void *buff
, int len
)
604 dbdma_command_t
*cmd
= sc
->sc_txcmd
;
605 vaddr_t va
= (vaddr_t
)buff
;
608 if (vtophys(va
) + len
- 1 != vtophys(va
+ len
- 1))
609 panic("bmac_transmit_packet");
612 DBDMA_BUILD(cmd
, DBDMA_CMD_OUT_LAST
, 0, len
, vtophys(va
),
613 DBDMA_INT_NEVER
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
615 DBDMA_BUILD(cmd
, DBDMA_CMD_STOP
, 0, 0, 0,
616 DBDMA_INT_ALWAYS
, DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
618 dbdma_start(sc
->sc_txdma
, sc
->sc_txcmd
);
622 bmac_put(struct bmac_softc
*sc
, void *buff
, struct mbuf
*m
)
633 memcpy(buff
, mtod(m
, void *), len
);
634 buff
= (char *)buff
+ len
;
638 if (tlen
> PAGE_SIZE
)
639 panic("%s: putpacket packet overflow", sc
->sc_dev
.dv_xname
);
645 bmac_get(struct bmac_softc
*sc
, void *pkt
, int totlen
)
648 struct mbuf
*top
, **mp
;
651 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
654 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
655 m
->m_pkthdr
.len
= totlen
;
662 MGET(m
, M_DONTWAIT
, MT_DATA
);
669 if (totlen
>= MINCLSIZE
) {
670 MCLGET(m
, M_DONTWAIT
);
671 if ((m
->m_flags
& M_EXT
) == 0) {
678 m
->m_len
= len
= min(totlen
, len
);
679 memcpy(mtod(m
, void *), pkt
, len
);
680 pkt
= (char *)pkt
+ len
;
690 bmac_watchdog(struct ifnet
*ifp
)
692 struct bmac_softc
*sc
= ifp
->if_softc
;
694 bmac_reset_bits(sc
, RXCFG
, RxMACEnable
);
695 bmac_reset_bits(sc
, TXCFG
, TxMACEnable
);
697 printf("%s: device timeout\n", ifp
->if_xname
);
704 bmac_ioctl(struct ifnet
*ifp
, unsigned long cmd
, void *data
)
706 struct bmac_softc
*sc
= ifp
->if_softc
;
707 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
715 ifp
->if_flags
|= IFF_UP
;
718 switch (ifa
->ifa_addr
->sa_family
) {
721 arp_ifinit(ifp
, ifa
);
730 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
732 /* XXX see the comment in ed_ioctl() about code re-use */
733 if ((ifp
->if_flags
& IFF_UP
) == 0 &&
734 (ifp
->if_flags
& IFF_RUNNING
) != 0) {
736 * If interface is marked down and it is running, then
740 ifp
->if_flags
&= ~IFF_RUNNING
;
741 } else if ((ifp
->if_flags
& IFF_UP
) != 0 &&
742 (ifp
->if_flags
& IFF_RUNNING
) == 0) {
744 * If interface is marked up and it is stopped, then
750 * Reset the interface to pick up changes in any other
751 * flags that affect hardware registers.
757 if (ifp
->if_flags
& IFF_DEBUG
)
758 sc
->sc_flags
|= BMAC_DEBUGFLAG
;
766 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
768 * Multicast list has changed; set the hardware filter
771 if (ifp
->if_flags
& IFF_RUNNING
) {
779 error
= ether_ioctl(ifp
, cmd
, data
);
788 * Set up the logical address filter.
791 bmac_setladrf(struct bmac_softc
*sc
)
793 struct ifnet
*ifp
= &sc
->sc_if
;
794 struct ether_multi
*enm
;
795 struct ether_multistep step
;
801 * Set up multicast address filter by passing all multicast addresses
802 * through a crc generator, and then using the high order 6 bits as an
803 * index into the 64 bit logical address filter. The high order bit
804 * selects the word, while the rest of the bits select the bit within
808 if (ifp
->if_flags
& IFF_PROMISC
) {
809 bmac_set_bits(sc
, RXCFG
, RxPromiscEnable
);
813 if (ifp
->if_flags
& IFF_ALLMULTI
) {
814 hash
[3] = hash
[2] = hash
[1] = hash
[0] = 0xffff;
818 hash
[3] = hash
[2] = hash
[1] = hash
[0] = 0;
820 ETHER_FIRST_MULTI(step
, &sc
->sc_ethercom
, enm
);
821 while (enm
!= NULL
) {
822 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
, ETHER_ADDR_LEN
)) {
824 * We must listen to a range of multicast addresses.
825 * For now, just accept all multicasts, rather than
826 * trying to set only those filter bits needed to match
827 * the range. (At this time, the only use of address
828 * ranges is for IP multicast routing, for which the
829 * range is big enough to require all bits set.)
831 hash
[3] = hash
[2] = hash
[1] = hash
[0] = 0xffff;
832 ifp
->if_flags
|= IFF_ALLMULTI
;
836 crc
= ether_crc32_le(enm
->enm_addrlo
, ETHER_ADDR_LEN
);
838 /* Just want the 6 most significant bits. */
841 /* Set the corresponding bit in the filter. */
842 hash
[crc
>> 4] |= 1 << (crc
& 0xf);
844 ETHER_NEXT_MULTI(step
, enm
);
847 ifp
->if_flags
&= ~IFF_ALLMULTI
;
850 bmac_write_reg(sc
, HASH0
, hash
[0]);
851 bmac_write_reg(sc
, HASH1
, hash
[1]);
852 bmac_write_reg(sc
, HASH2
, hash
[2]);
853 bmac_write_reg(sc
, HASH3
, hash
[3]);
854 x
= bmac_read_reg(sc
, RXCFG
);
855 x
&= ~RxPromiscEnable
;
856 x
|= RxHashFilterEnable
;
857 bmac_write_reg(sc
, RXCFG
, x
);
861 bmac_mii_readreg(struct device
*dev
, int phy
, int reg
)
863 return mii_bitbang_readreg(dev
, &bmac_mbo
, phy
, reg
);
867 bmac_mii_writereg(struct device
*dev
, int phy
, int reg
, int val
)
869 mii_bitbang_writereg(dev
, &bmac_mbo
, phy
, reg
, val
);
873 bmac_mbo_read(struct device
*dev
)
875 struct bmac_softc
*sc
= (void *)dev
;
877 return bmac_read_reg(sc
, MIFCSR
);
881 bmac_mbo_write(struct device
*dev
, u_int32_t val
)
883 struct bmac_softc
*sc
= (void *)dev
;
885 bmac_write_reg(sc
, MIFCSR
, val
);
889 bmac_mii_statchg(struct device
*dev
)
891 struct bmac_softc
*sc
= (void *)dev
;
894 /* Update duplex mode in TX configuration */
895 x
= bmac_read_reg(sc
, TXCFG
);
896 if ((IFM_OPTIONS(sc
->sc_mii
.mii_media_active
) & IFM_FDX
) != 0)
900 bmac_write_reg(sc
, TXCFG
, x
);
903 printf("bmac_mii_statchg 0x%x\n",
904 IFM_OPTIONS(sc
->sc_mii
.mii_media_active
));
909 bmac_mii_tick(void *v
)
911 struct bmac_softc
*sc
= v
;
915 mii_tick(&sc
->sc_mii
);
918 callout_reset(&sc
->sc_tick_ch
, hz
, bmac_mii_tick
, sc
);