1 /* $NetBSD: if_gm.c,v 1.35 2009/03/14 15:36:09 dsl Exp $ */
4 * Copyright (c) 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_gm.c,v 1.35 2009/03/14 15:36:09 dsl Exp $");
36 #include <sys/param.h>
37 #include <sys/device.h>
38 #include <sys/ioctl.h>
39 #include <sys/kernel.h>
41 #include <sys/socket.h>
42 #include <sys/systm.h>
43 #include <sys/callout.h>
49 #include <uvm/uvm_extern.h>
52 #include <net/if_ether.h>
53 #include <net/if_media.h>
60 #include <netinet/in.h>
61 #include <netinet/if_inarp.h>
64 #include <dev/mii/mii.h>
65 #include <dev/mii/miivar.h>
67 #include <dev/pci/pcivar.h>
68 #include <dev/pci/pcireg.h>
69 #include <dev/pci/pcidevs.h>
71 #include <dev/ofw/openfirm.h>
72 #include <macppc/dev/if_gmreg.h>
73 #include <machine/pio.h>
80 struct ethercom sc_ethercom
;
82 struct gmac_dma
*sc_txlist
;
83 struct gmac_dma
*sc_rxlist
;
86 void *sc_txbuf
[NTXBUF
];
87 void *sc_rxbuf
[NRXBUF
];
88 struct mii_data sc_mii
;
89 struct callout sc_tick_ch
;
93 rndsource_element_t sc_rnd_source
; /* random source */
97 #define sc_if sc_ethercom.ec_if
99 int gmac_match(struct device
*, struct cfdata
*, void *);
100 void gmac_attach(struct device
*, struct device
*, void *);
102 static inline u_int
gmac_read_reg(struct gmac_softc
*, int);
103 static inline void gmac_write_reg(struct gmac_softc
*, int, u_int
);
105 static inline void gmac_start_txdma(struct gmac_softc
*);
106 static inline void gmac_start_rxdma(struct gmac_softc
*);
107 static inline void gmac_stop_txdma(struct gmac_softc
*);
108 static inline void gmac_stop_rxdma(struct gmac_softc
*);
110 int gmac_intr(void *);
111 void gmac_tint(struct gmac_softc
*);
112 void gmac_rint(struct gmac_softc
*);
113 struct mbuf
* gmac_get(struct gmac_softc
*, void *, int);
114 void gmac_start(struct ifnet
*);
115 int gmac_put(struct gmac_softc
*, void *, struct mbuf
*);
117 void gmac_stop(struct gmac_softc
*);
118 void gmac_reset(struct gmac_softc
*);
119 void gmac_init(struct gmac_softc
*);
120 void gmac_init_mac(struct gmac_softc
*);
121 void gmac_setladrf(struct gmac_softc
*);
123 int gmac_ioctl(struct ifnet
*, u_long
, void *);
124 void gmac_watchdog(struct ifnet
*);
126 int gmac_mii_readreg(struct device
*, int, int);
127 void gmac_mii_writereg(struct device
*, int, int, int);
128 void gmac_mii_statchg(struct device
*);
129 void gmac_mii_tick(void *);
131 CFATTACH_DECL(gm
, sizeof(struct gmac_softc
),
132 gmac_match
, gmac_attach
, NULL
, NULL
);
135 gmac_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
137 struct pci_attach_args
*pa
= aux
;
139 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_APPLE
&&
140 (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_APPLE_GMAC
||
141 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_APPLE_GMAC2
||
142 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_APPLE_GMAC3
))
149 gmac_attach(struct device
*parent
, struct device
*self
, void *aux
)
151 struct gmac_softc
*sc
= (void *)self
;
152 struct pci_attach_args
*pa
= aux
;
153 struct ifnet
*ifp
= &sc
->sc_if
;
154 struct mii_data
*mii
= &sc
->sc_mii
;
155 pci_intr_handle_t ih
;
156 const char *intrstr
= NULL
;
163 node
= pcidev_to_ofdev(pa
->pa_pc
, pa
->pa_tag
);
165 printf(": cannot find gmac node\n");
169 OF_getprop(node
, "local-mac-address", laddr
, sizeof laddr
);
170 OF_getprop(node
, "assigned-addresses", reg
, sizeof reg
);
172 memcpy(sc
->sc_laddr
, laddr
, sizeof laddr
);
175 if (pci_intr_map(pa
, &ih
)) {
176 printf(": unable to map interrupt\n");
179 intrstr
= pci_intr_string(pa
->pa_pc
, ih
);
181 if (pci_intr_establish(pa
->pa_pc
, ih
, IPL_NET
, gmac_intr
, sc
) == NULL
) {
182 printf(": unable to establish interrupt");
184 printf(" at %s", intrstr
);
189 /* Setup packet buffers and DMA descriptors. */
190 p
= malloc((NRXBUF
+ NTXBUF
) * 2048 + 3 * 0x800, M_DEVBUF
, M_NOWAIT
);
192 printf(": cannot malloc buffers\n");
195 p
= (void *)roundup((vaddr_t
)p
, 0x800);
196 memset(p
, 0, 2048 * (NRXBUF
+ NTXBUF
) + 2 * 0x800);
198 sc
->sc_rxlist
= (void *)p
;
200 sc
->sc_txlist
= (void *)p
;
204 for (i
= 0; i
< NRXBUF
; i
++) {
206 dp
->address
= htole32(vtophys((vaddr_t
)p
));
207 dp
->cmd
= htole32(GMAC_OWN
);
213 for (i
= 0; i
< NTXBUF
; i
++) {
215 dp
->address
= htole32(vtophys((vaddr_t
)p
));
220 printf(": Ethernet address %s\n", ether_sprintf(laddr
));
221 printf("%s: interrupting at %s\n", sc
->sc_dev
.dv_xname
, intrstr
);
223 callout_init(&sc
->sc_tick_ch
, 0);
228 memcpy(ifp
->if_xname
, sc
->sc_dev
.dv_xname
, IFNAMSIZ
);
230 ifp
->if_ioctl
= gmac_ioctl
;
231 ifp
->if_start
= gmac_start
;
232 ifp
->if_watchdog
= gmac_watchdog
;
234 IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
| IFF_MULTICAST
;
235 IFQ_SET_READY(&ifp
->if_snd
);
238 mii
->mii_readreg
= gmac_mii_readreg
;
239 mii
->mii_writereg
= gmac_mii_writereg
;
240 mii
->mii_statchg
= gmac_mii_statchg
;
242 sc
->sc_ethercom
.ec_mii
= mii
;
243 ifmedia_init(&mii
->mii_media
, 0, ether_mediachange
, ether_mediastatus
);
244 mii_attach(self
, mii
, 0xffffffff, MII_PHY_ANY
, MII_OFFSET_ANY
, 0);
246 /* Choose a default media. */
247 if (LIST_FIRST(&mii
->mii_phys
) == NULL
) {
248 ifmedia_add(&mii
->mii_media
, IFM_ETHER
|IFM_NONE
, 0, NULL
);
249 ifmedia_set(&mii
->mii_media
, IFM_ETHER
|IFM_NONE
);
251 ifmedia_set(&mii
->mii_media
, IFM_ETHER
|IFM_AUTO
);
254 ether_ifattach(ifp
, laddr
);
256 rnd_attach_source(&sc
->sc_rnd_source
, sc
->sc_dev
.dv_xname
,
262 gmac_read_reg(struct gmac_softc
*sc
, int reg
)
264 return in32rb(sc
->sc_reg
+ reg
);
268 gmac_write_reg(struct gmac_softc
*sc
, int reg
, u_int val
)
270 out32rb(sc
->sc_reg
+ reg
, val
);
274 gmac_start_txdma(struct gmac_softc
*sc
)
278 x
= gmac_read_reg(sc
, GMAC_TXDMACONFIG
);
280 gmac_write_reg(sc
, GMAC_TXDMACONFIG
, x
);
281 x
= gmac_read_reg(sc
, GMAC_TXMACCONFIG
);
283 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, x
);
287 gmac_start_rxdma(struct gmac_softc
*sc
)
291 x
= gmac_read_reg(sc
, GMAC_RXDMACONFIG
);
293 gmac_write_reg(sc
, GMAC_RXDMACONFIG
, x
);
294 x
= gmac_read_reg(sc
, GMAC_RXMACCONFIG
);
296 gmac_write_reg(sc
, GMAC_RXMACCONFIG
, x
);
300 gmac_stop_txdma(struct gmac_softc
*sc
)
304 x
= gmac_read_reg(sc
, GMAC_TXDMACONFIG
);
306 gmac_write_reg(sc
, GMAC_TXDMACONFIG
, x
);
307 x
= gmac_read_reg(sc
, GMAC_TXMACCONFIG
);
309 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, x
);
313 gmac_stop_rxdma(struct gmac_softc
*sc
)
317 x
= gmac_read_reg(sc
, GMAC_RXDMACONFIG
);
319 gmac_write_reg(sc
, GMAC_RXDMACONFIG
, x
);
320 x
= gmac_read_reg(sc
, GMAC_RXMACCONFIG
);
322 gmac_write_reg(sc
, GMAC_RXMACCONFIG
, x
);
328 struct gmac_softc
*sc
= v
;
331 status
= gmac_read_reg(sc
, GMAC_STATUS
) & 0xff;
335 if (status
& GMAC_INT_RXDONE
)
338 if (status
& GMAC_INT_TXEMPTY
)
342 rnd_add_uint32(&sc
->sc_rnd_source
, status
);
348 gmac_tint(struct gmac_softc
*sc
)
350 struct ifnet
*ifp
= &sc
->sc_if
;
352 ifp
->if_flags
&= ~IFF_OACTIVE
;
358 gmac_rint(struct gmac_softc
*sc
)
360 struct ifnet
*ifp
= &sc
->sc_if
;
361 volatile struct gmac_dma
*dp
;
366 for (i
= sc
->sc_rxlast
;; i
++) {
370 dp
= &sc
->sc_rxlist
[i
];
371 cmd
= le32toh(dp
->cmd
);
374 len
= (cmd
>> 16) & GMAC_LEN_MASK
;
377 if (le32toh(dp
->cmd_hi
) & 0x40000000) {
382 m
= gmac_get(sc
, sc
->sc_rxbuf
[i
], len
);
390 * Check if there's a BPF listener on this interface.
391 * If so, hand off the raw packet to BPF.
394 bpf_mtap(ifp
->if_bpf
, m
);
396 (*ifp
->if_input
)(ifp
, m
);
401 __asm
volatile ("sync");
402 dp
->cmd
= htole32(GMAC_OWN
);
406 /* XXX Make sure free buffers have GMAC_OWN. */
408 for (j
= 1; j
< NRXBUF
; j
++) {
411 dp
= &sc
->sc_rxlist
[i
++];
412 dp
->cmd
= htole32(GMAC_OWN
);
417 gmac_get(struct gmac_softc
*sc
, void *pkt
, int totlen
)
420 struct mbuf
*top
, **mp
;
423 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
426 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
427 m
->m_pkthdr
.len
= totlen
;
434 MGET(m
, M_DONTWAIT
, MT_DATA
);
441 if (totlen
>= MINCLSIZE
) {
442 MCLGET(m
, M_DONTWAIT
);
443 if ((m
->m_flags
& M_EXT
) == 0) {
450 m
->m_len
= len
= min(totlen
, len
);
451 memcpy(mtod(m
, void *), pkt
, len
);
462 gmac_start(struct ifnet
*ifp
)
464 struct gmac_softc
*sc
= ifp
->if_softc
;
468 volatile struct gmac_dma
*dp
;
470 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
474 if (ifp
->if_flags
& IFF_OACTIVE
)
477 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
481 /* 5 seconds to watch for failing to transmit */
483 ifp
->if_opackets
++; /* # of pkts */
486 buff
= sc
->sc_txbuf
[i
];
487 tlen
= gmac_put(sc
, buff
, m
);
489 dp
= &sc
->sc_txlist
[i
];
492 dp
->cmd
= htole32(tlen
| GMAC_OWN
| GMAC_SOP
);
497 __asm
volatile ("sync");
499 gmac_write_reg(sc
, GMAC_TXDMAKICK
, i
);
504 * If BPF is listening on this interface, let it see the
505 * packet before we commit it to the wire.
508 bpf_mtap(ifp
->if_bpf
, m
);
515 if (i
== gmac_read_reg(sc
, GMAC_TXDMACOMPLETE
)) {
516 ifp
->if_flags
|= IFF_OACTIVE
;
523 gmac_put(struct gmac_softc
*sc
, void *buff
, struct mbuf
*m
)
527 for (; m
; m
= m
->m_next
) {
531 memcpy(buff
, mtod(m
, void *), len
);
536 panic("%s: gmac_put packet overflow", sc
->sc_dev
.dv_xname
);
542 gmac_reset(struct gmac_softc
*sc
)
551 gmac_write_reg(sc
, GMAC_SOFTWARERESET
, 3);
552 for (i
= 10; i
> 0; i
--) {
553 delay(300000); /* XXX long delay */
554 if ((gmac_read_reg(sc
, GMAC_SOFTWARERESET
) & 3) == 0)
558 printf("%s: reset timeout\n", sc
->sc_dev
.dv_xname
);
562 for (i
= 0; i
< NRXBUF
; i
++)
563 sc
->sc_rxlist
[i
].cmd
= htole32(GMAC_OWN
);
564 __asm
volatile ("sync");
566 gmac_write_reg(sc
, GMAC_TXDMADESCBASEHI
, 0);
567 gmac_write_reg(sc
, GMAC_TXDMADESCBASELO
,
568 vtophys((vaddr_t
)sc
->sc_txlist
));
569 gmac_write_reg(sc
, GMAC_RXDMADESCBASEHI
, 0);
570 gmac_write_reg(sc
, GMAC_RXDMADESCBASELO
,
571 vtophys((vaddr_t
)sc
->sc_rxlist
));
572 gmac_write_reg(sc
, GMAC_RXDMAKICK
, NRXBUF
);
578 gmac_stop(struct gmac_softc
*sc
)
580 struct ifnet
*ifp
= &sc
->sc_if
;
585 callout_stop(&sc
->sc_tick_ch
);
586 mii_down(&sc
->sc_mii
);
591 gmac_write_reg(sc
, GMAC_INTMASK
, 0xffffffff);
593 ifp
->if_flags
&= ~(IFF_UP
| IFF_RUNNING
);
600 gmac_init_mac(struct gmac_softc
*sc
)
603 char *laddr
= sc
->sc_laddr
;
605 if ((mfpvr() >> 16) == MPC601
)
609 gmac_write_reg(sc
, GMAC_RANDOMSEED
, tb
);
612 gmac_write_reg(sc
, GMAC_DATAPATHMODE
, 4);
613 gmac_mii_writereg(&sc
->sc_dev
, 0, 0, 0x1000);
615 gmac_write_reg(sc
, GMAC_TXDMACONFIG
, 0xffc00);
616 gmac_write_reg(sc
, GMAC_RXDMACONFIG
, 0);
617 gmac_write_reg(sc
, GMAC_MACPAUSE
, 0x1bf0);
618 gmac_write_reg(sc
, GMAC_INTERPACKETGAP0
, 0);
619 gmac_write_reg(sc
, GMAC_INTERPACKETGAP1
, 8);
620 gmac_write_reg(sc
, GMAC_INTERPACKETGAP2
, 4);
621 gmac_write_reg(sc
, GMAC_MINFRAMESIZE
, ETHER_MIN_LEN
);
622 gmac_write_reg(sc
, GMAC_MAXFRAMESIZE
, ETHER_MAX_LEN
);
623 gmac_write_reg(sc
, GMAC_PASIZE
, 7);
624 gmac_write_reg(sc
, GMAC_JAMSIZE
, 4);
625 gmac_write_reg(sc
, GMAC_ATTEMPTLIMIT
,0x10);
626 gmac_write_reg(sc
, GMAC_MACCNTLTYPE
, 0x8808);
628 gmac_write_reg(sc
, GMAC_MACADDRESS0
, (laddr
[4] << 8) | laddr
[5]);
629 gmac_write_reg(sc
, GMAC_MACADDRESS1
, (laddr
[2] << 8) | laddr
[3]);
630 gmac_write_reg(sc
, GMAC_MACADDRESS2
, (laddr
[0] << 8) | laddr
[1]);
631 gmac_write_reg(sc
, GMAC_MACADDRESS3
, 0);
632 gmac_write_reg(sc
, GMAC_MACADDRESS4
, 0);
633 gmac_write_reg(sc
, GMAC_MACADDRESS5
, 0);
634 gmac_write_reg(sc
, GMAC_MACADDRESS6
, 1);
635 gmac_write_reg(sc
, GMAC_MACADDRESS7
, 0xc200);
636 gmac_write_reg(sc
, GMAC_MACADDRESS8
, 0x0180);
637 gmac_write_reg(sc
, GMAC_MACADDRFILT0
, 0);
638 gmac_write_reg(sc
, GMAC_MACADDRFILT1
, 0);
639 gmac_write_reg(sc
, GMAC_MACADDRFILT2
, 0);
640 gmac_write_reg(sc
, GMAC_MACADDRFILT2_1MASK
, 0);
641 gmac_write_reg(sc
, GMAC_MACADDRFILT0MASK
, 0);
643 for (i
= 0; i
< 0x6c; i
+= 4)
644 gmac_write_reg(sc
, GMAC_HASHTABLE0
+ i
, 0);
646 gmac_write_reg(sc
, GMAC_SLOTTIME
, 0x40);
648 if (IFM_OPTIONS(sc
->sc_mii
.mii_media_active
) & IFM_FDX
) {
649 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, 6);
650 gmac_write_reg(sc
, GMAC_XIFCONFIG
, 1);
652 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, 0);
653 gmac_write_reg(sc
, GMAC_XIFCONFIG
, 5);
657 gmac_write_reg(sc
, GMAC_MACCTRLCONFIG
, 3);
659 gmac_write_reg(sc
, GMAC_MACCTRLCONFIG
, 0);
663 gmac_setladrf(struct gmac_softc
*sc
)
665 struct ifnet
*ifp
= &sc
->sc_if
;
666 struct ether_multi
*enm
;
667 struct ether_multistep step
;
668 struct ethercom
*ec
= &sc
->sc_ethercom
;
674 /* Clear hash table */
675 for (i
= 0; i
< 16; i
++)
678 /* Get current RX configuration */
679 v
= gmac_read_reg(sc
, GMAC_RXMACCONFIG
);
681 if ((ifp
->if_flags
& IFF_PROMISC
) != 0) {
682 /* Turn on promiscuous mode; turn off the hash filter */
684 v
&= ~GMAC_RXMAC_HEN
;
685 ifp
->if_flags
|= IFF_ALLMULTI
;
689 /* Turn off promiscuous mode; turn on the hash filter */
694 * Set up multicast address filter by passing all multicast addresses
695 * through a crc generator, and then using the high order 8 bits as an
696 * index into the 256 bit logical address filter. The high order bit
697 * selects the word, while the rest of the bits select the bit within
701 ETHER_FIRST_MULTI(step
, ec
, enm
);
702 while (enm
!= NULL
) {
703 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
, 6)) {
705 * We must listen to a range of multicast addresses.
706 * For now, just accept all multicasts, rather than
707 * trying to set only those filter bits needed to match
708 * the range. (At this time, the only use of address
709 * ranges is for IP multicast routing, for which the
710 * range is big enough to require all bits set.)
712 for (i
= 0; i
< 16; i
++)
714 ifp
->if_flags
|= IFF_ALLMULTI
;
718 crc
= ether_crc32_le(enm
->enm_addrlo
, ETHER_ADDR_LEN
);
720 /* Just want the 8 most significant bits. */
723 /* Set the corresponding bit in the filter. */
724 hash
[crc
>> 4] |= 1 << (crc
& 0xf);
726 ETHER_NEXT_MULTI(step
, enm
);
729 ifp
->if_flags
&= ~IFF_ALLMULTI
;
732 /* Now load the hash table into the chip */
733 for (i
= 0; i
< 16; i
++)
734 gmac_write_reg(sc
, GMAC_HASHTABLE0
+ i
* 4, hash
[i
]);
736 gmac_write_reg(sc
, GMAC_RXMACCONFIG
, v
);
740 gmac_init(struct gmac_softc
*sc
)
742 struct ifnet
*ifp
= &sc
->sc_if
;
750 gmac_start_txdma(sc
);
751 gmac_start_rxdma(sc
);
753 gmac_write_reg(sc
, GMAC_INTMASK
, ~(GMAC_INT_TXEMPTY
| GMAC_INT_RXDONE
));
755 ifp
->if_flags
|= IFF_RUNNING
;
756 ifp
->if_flags
&= ~IFF_OACTIVE
;
759 callout_reset(&sc
->sc_tick_ch
, 1, gmac_mii_tick
, sc
);
765 gmac_ioctl(struct ifnet
*ifp
, unsigned long cmd
, void *data
)
767 struct gmac_softc
*sc
= ifp
->if_softc
;
768 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
769 struct ifreq
*ifr
= (struct ifreq
*)data
;
777 ifp
->if_flags
|= IFF_UP
;
780 switch (ifa
->ifa_addr
->sa_family
) {
783 arp_ifinit(ifp
, ifa
);
792 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
794 /* XXX see the comment in ed_ioctl() about code re-use */
795 if ((ifp
->if_flags
& IFF_UP
) == 0 &&
796 (ifp
->if_flags
& IFF_RUNNING
) != 0) {
798 * If interface is marked down and it is running, then
802 ifp
->if_flags
&= ~IFF_RUNNING
;
803 } else if ((ifp
->if_flags
& IFF_UP
) != 0 &&
804 (ifp
->if_flags
& IFF_RUNNING
) == 0) {
806 * If interface is marked up and it is stopped, then
812 * Reset the interface to pick up changes in any other
813 * flags that affect hardware registers.
819 if (ifp
->if_flags
& IFF_DEBUG
)
820 sc
->sc_flags
|= GMAC_DEBUGFLAG
;
828 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
830 * Multicast list has changed; set the hardware filter
833 if (ifp
->if_flags
& IFF_RUNNING
) {
835 /* gmac_setladrf(sc); */
841 error
= ether_ioctl(ifp
, cmd
, data
);
850 gmac_watchdog(struct ifnet
*ifp
)
852 struct gmac_softc
*sc
= ifp
->if_softc
;
854 printf("%s: device timeout\n", ifp
->if_xname
);
862 gmac_mii_readreg(struct device
*dev
, int phy
, int reg
)
864 struct gmac_softc
*sc
= (void *)dev
;
867 gmac_write_reg(sc
, GMAC_MIFFRAMEOUTPUT
,
868 0x60020000 | (phy
<< 23) | (reg
<< 18));
870 for (i
= 1000; i
>= 0; i
-= 10) {
871 if (gmac_read_reg(sc
, GMAC_MIFFRAMEOUTPUT
) & 0x10000)
876 printf("%s: gmac_mii_readreg: timeout\n", sc
->sc_dev
.dv_xname
);
880 return gmac_read_reg(sc
, GMAC_MIFFRAMEOUTPUT
) & 0xffff;
884 gmac_mii_writereg(struct device
*dev
, int phy
, int reg
, int val
)
886 struct gmac_softc
*sc
= (void *)dev
;
889 gmac_write_reg(sc
, GMAC_MIFFRAMEOUTPUT
,
890 0x50020000 | (phy
<< 23) | (reg
<< 18) | (val
& 0xffff));
892 for (i
= 1000; i
>= 0; i
-= 10) {
893 if (gmac_read_reg(sc
, GMAC_MIFFRAMEOUTPUT
) & 0x10000)
898 printf("%s: gmac_mii_writereg: timeout\n", sc
->sc_dev
.dv_xname
);
902 gmac_mii_statchg(struct device
*dev
)
904 struct gmac_softc
*sc
= (void *)dev
;
909 if (IFM_OPTIONS(sc
->sc_mii
.mii_media_active
) & IFM_FDX
) {
910 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, 6);
911 gmac_write_reg(sc
, GMAC_XIFCONFIG
, 1);
913 gmac_write_reg(sc
, GMAC_TXMACCONFIG
, 0);
914 gmac_write_reg(sc
, GMAC_XIFCONFIG
, 5);
918 gmac_write_reg(sc
, GMAC_MACCTRLCONFIG
, 3);
920 gmac_write_reg(sc
, GMAC_MACCTRLCONFIG
, 0);
922 gmac_start_txdma(sc
);
923 gmac_start_rxdma(sc
);
927 gmac_mii_tick(void *v
)
929 struct gmac_softc
*sc
= v
;
933 mii_tick(&sc
->sc_mii
);
936 callout_reset(&sc
->sc_tick_ch
, hz
, gmac_mii_tick
, sc
);