1 /* $NetBSD: epe.c,v 1.21 2009/03/18 16:00:09 cegger Exp $ */
4 * Copyright (c) 2004 Jesse Off
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: epe.c,v 1.21 2009/03/18 16:00:09 cegger Exp $");
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/ioctl.h>
36 #include <sys/kernel.h>
38 #include <sys/malloc.h>
40 #include <sys/device.h>
41 #include <uvm/uvm_extern.h>
43 #include <machine/bus.h>
44 #include <machine/intr.h>
46 #include <arm/cpufunc.h>
48 #include <arm/ep93xx/epsocvar.h>
49 #include <arm/ep93xx/ep93xxvar.h>
52 #include <net/if_dl.h>
53 #include <net/if_types.h>
54 #include <net/if_media.h>
55 #include <net/if_ether.h>
57 #include <dev/mii/mii.h>
58 #include <dev/mii/miivar.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip.h>
65 #include <netinet/if_inarp.h>
70 #include <netns/ns_if.h>
76 #include <net/bpfdesc.h>
79 #include <arm/ep93xx/ep93xxreg.h>
80 #include <arm/ep93xx/epereg.h>
81 #include <arm/ep93xx/epevar.h>
83 #define DEFAULT_MDCDIV 32
91 bus_space_read_4(sc->sc_iot, sc->sc_ioh, (EPE_ ## x))
92 #define EPE_WRITE(x, y) \
93 bus_space_write_4(sc->sc_iot, sc->sc_ioh, (EPE_ ## x), (y))
94 #define CTRLPAGE_DMASYNC(x, y, z) \
95 bus_dmamap_sync(sc->sc_dmat, sc->ctrlpage_dmamap, (x), (y), (z))
97 #define EPE_READ(x) *(volatile u_int32_t *) \
98 (EP93XX_AHB_VBASE + EP93XX_AHB_EPE + (EPE_ ## x))
99 #define EPE_WRITE(x, y) *(volatile u_int32_t *) \
100 (EP93XX_AHB_VBASE + EP93XX_AHB_EPE + (EPE_ ## x)) = y
101 #define CTRLPAGE_DMASYNC(x, y, z)
102 #endif /* ! EPE_FAST */
104 static int epe_match(struct device
*, struct cfdata
*, void *);
105 static void epe_attach(struct device
*, struct device
*, void *);
106 static void epe_init(struct epe_softc
*);
107 static int epe_intr(void* arg
);
108 static int epe_gctx(struct epe_softc
*);
109 static int epe_mediachange(struct ifnet
*);
110 int epe_mii_readreg (struct device
*, int, int);
111 void epe_mii_writereg (struct device
*, int, int, int);
112 void epe_statchg (struct device
*);
113 void epe_tick (void *);
114 static int epe_ifioctl (struct ifnet
*, u_long
, void *);
115 static void epe_ifstart (struct ifnet
*);
116 static void epe_ifwatchdog (struct ifnet
*);
117 static int epe_ifinit (struct ifnet
*);
118 static void epe_ifstop (struct ifnet
*, int);
119 static void epe_setaddr (struct ifnet
*);
121 CFATTACH_DECL(epe
, sizeof(struct epe_softc
),
122 epe_match
, epe_attach
, NULL
, NULL
);
125 epe_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
131 epe_attach(struct device
*parent
, struct device
*self
, void *aux
)
133 struct epe_softc
*sc
;
134 struct epsoc_attach_args
*sa
;
138 sc
= (struct epe_softc
*) self
;
140 sc
->sc_iot
= sa
->sa_iot
;
141 sc
->sc_intr
= sa
->sa_intr
;
142 sc
->sc_dmat
= sa
->sa_dmat
;
144 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
, sa
->sa_size
,
146 panic("%s: Cannot map registers", self
->dv_xname
);
148 /* Fetch the Ethernet address from property if set. */
149 enaddr
= prop_dictionary_get(device_properties(self
), "mac-addr");
150 if (enaddr
!= NULL
) {
151 KASSERT(prop_object_type(enaddr
) == PROP_TYPE_DATA
);
152 KASSERT(prop_data_size(enaddr
) == ETHER_ADDR_LEN
);
153 memcpy(sc
->sc_enaddr
, prop_data_data_nocopy(enaddr
),
155 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, EPE_AFP
, 0);
156 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, EPE_IndAd
,
157 sc
->sc_enaddr
, ETHER_ADDR_LEN
);
160 ep93xx_intr_establish(sc
->sc_intr
, IPL_NET
, epe_intr
, sc
);
165 epe_gctx(struct epe_softc
*sc
)
167 struct ifnet
* ifp
= &sc
->sc_ec
.ec_if
;
168 u_int32_t
*cur
, ndq
= 0;
170 /* Handle transmit completions */
171 cur
= (u_int32_t
*)(EPE_READ(TXStsQCurAdd
) -
172 sc
->ctrlpage_dsaddr
+ (char*)sc
->ctrlpage
);
174 if (sc
->TXStsQ_cur
!= cur
) {
175 CTRLPAGE_DMASYNC(TX_QLEN
* 2 * sizeof(u_int32_t
),
176 TX_QLEN
* sizeof(u_int32_t
), BUS_DMASYNC_PREREAD
);
182 u_int32_t tbi
= *sc
->TXStsQ_cur
& 0x7fff;
183 struct mbuf
*m
= sc
->txq
[tbi
].m
;
185 if ((*sc
->TXStsQ_cur
& TXStsQ_TxWE
) == 0) {
188 bus_dmamap_unload(sc
->sc_dmat
, sc
->txq
[tbi
].m_dmamap
);
191 sc
->txq
[tbi
].m
= NULL
;
193 tbi
= (tbi
+ 1) % TX_QLEN
;
194 } while (sc
->txq
[tbi
].m
== m
);
198 if (sc
->TXStsQ_cur
>= sc
->TXStsQ
+ TX_QLEN
) {
199 sc
->TXStsQ_cur
= sc
->TXStsQ
;
201 } while (sc
->TXStsQ_cur
!= cur
);
203 sc
->TXDQ_avail
+= ndq
;
204 if (ifp
->if_flags
& IFF_OACTIVE
) {
205 ifp
->if_flags
&= ~IFF_OACTIVE
;
206 /* Disable end-of-tx-chain interrupt */
207 EPE_WRITE(IntEn
, IntEn_REOFIE
);
215 struct epe_softc
*sc
= (struct epe_softc
*)arg
;
216 struct ifnet
* ifp
= &sc
->sc_ec
.ec_if
;
217 u_int32_t ndq
= 0, irq
, *cur
;
219 irq
= EPE_READ(IntStsC
);
221 cur
= (u_int32_t
*)(EPE_READ(RXStsQCurAdd
) -
222 sc
->ctrlpage_dsaddr
+ (char*)sc
->ctrlpage
);
223 CTRLPAGE_DMASYNC(TX_QLEN
* 3 * sizeof(u_int32_t
),
224 RX_QLEN
* 4 * sizeof(u_int32_t
),
225 BUS_DMASYNC_PREREAD
);
226 while (sc
->RXStsQ_cur
!= cur
) {
227 if ((sc
->RXStsQ_cur
[0] & (RXStsQ_RWE
|RXStsQ_RFP
|RXStsQ_EOB
)) ==
228 (RXStsQ_RWE
|RXStsQ_RFP
|RXStsQ_EOB
)) {
229 u_int32_t bi
= (sc
->RXStsQ_cur
[1] >> 16) & 0x7fff;
230 u_int32_t fl
= sc
->RXStsQ_cur
[1] & 0xffff;
233 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
234 if (m
!= NULL
) MCLGET(m
, M_DONTWAIT
);
235 if (m
!= NULL
&& (m
->m_flags
& M_EXT
)) {
236 bus_dmamap_unload(sc
->sc_dmat
,
237 sc
->rxq
[bi
].m_dmamap
);
238 sc
->rxq
[bi
].m
->m_pkthdr
.rcvif
= ifp
;
239 sc
->rxq
[bi
].m
->m_pkthdr
.len
=
240 sc
->rxq
[bi
].m
->m_len
= fl
;
243 bpf_mtap(ifp
->if_bpf
, sc
->rxq
[bi
].m
);
244 #endif /* NBPFILTER > 0 */
245 (*ifp
->if_input
)(ifp
, sc
->rxq
[bi
].m
);
247 bus_dmamap_load(sc
->sc_dmat
,
248 sc
->rxq
[bi
].m_dmamap
,
249 m
->m_ext
.ext_buf
, MCLBYTES
,
250 NULL
, BUS_DMA_NOWAIT
);
252 sc
->rxq
[bi
].m_dmamap
->dm_segs
[0].ds_addr
;
254 /* Drop packets until we can get replacement
255 * empty mbufs for the RXDQ.
269 if (sc
->RXStsQ_cur
>= sc
->RXStsQ
+ (RX_QLEN
* 2)) {
270 sc
->RXStsQ_cur
= sc
->RXStsQ
;
275 ifp
->if_ipackets
+= ndq
;
276 CTRLPAGE_DMASYNC(TX_QLEN
* 3 * sizeof(u_int32_t
),
277 RX_QLEN
* 4 * sizeof(u_int32_t
),
278 BUS_DMASYNC_PREWRITE
|BUS_DMASYNC_PREREAD
);
279 EPE_WRITE(RXStsEnq
, ndq
);
280 EPE_WRITE(RXDEnq
, ndq
);
284 if (epe_gctx(sc
) > 0 && IFQ_IS_EMPTY(&ifp
->if_snd
) == 0) {
288 irq
= EPE_READ(IntStsC
);
289 if ((irq
& (IntSts_RxSQ
|IntSts_ECI
)) != 0)
297 epe_init(struct epe_softc
*sc
)
299 bus_dma_segment_t segs
;
302 struct ifnet
* ifp
= &sc
->sc_ec
.ec_if
;
303 int mdcdiv
= DEFAULT_MDCDIV
;
305 callout_init(&sc
->epe_tick_ch
, 0);
307 /* Select primary Individual Address in Address Filter Pointer */
309 /* Read ethernet MAC, should already be set by bootrom */
310 bus_space_read_region_1(sc
->sc_iot
, sc
->sc_ioh
, EPE_IndAd
,
311 sc
->sc_enaddr
, ETHER_ADDR_LEN
);
312 printf("%s: MAC address %s\n", sc
->sc_dev
.dv_xname
,
313 ether_sprintf(sc
->sc_enaddr
));
315 /* Soft Reset the MAC */
316 EPE_WRITE(SelfCtl
, SelfCtl_RESET
);
317 while(EPE_READ(SelfCtl
) & SelfCtl_RESET
);
319 /* suggested magic initialization values from datasheet */
320 EPE_WRITE(RXBufThrshld
, 0x800040);
321 EPE_WRITE(TXBufThrshld
, 0x200010);
322 EPE_WRITE(RXStsThrshld
, 0x40002);
323 EPE_WRITE(TXStsThrshld
, 0x40002);
324 EPE_WRITE(RXDThrshld
, 0x40002);
325 EPE_WRITE(TXDThrshld
, 0x40002);
327 /* Allocate a page of memory for descriptor and status queues */
328 err
= bus_dmamem_alloc(sc
->sc_dmat
, PAGE_SIZE
, 0, PAGE_SIZE
,
329 &segs
, 1, &rsegs
, BUS_DMA_WAITOK
);
331 err
= bus_dmamem_map(sc
->sc_dmat
, &segs
, 1, PAGE_SIZE
,
332 &sc
->ctrlpage
, (BUS_DMA_WAITOK
|BUS_DMA_COHERENT
));
335 err
= bus_dmamap_create(sc
->sc_dmat
, PAGE_SIZE
, 1, PAGE_SIZE
,
336 0, BUS_DMA_WAITOK
, &sc
->ctrlpage_dmamap
);
339 err
= bus_dmamap_load(sc
->sc_dmat
, sc
->ctrlpage_dmamap
,
340 sc
->ctrlpage
, PAGE_SIZE
, NULL
, BUS_DMA_WAITOK
);
343 panic("%s: Cannot get DMA memory", sc
->sc_dev
.dv_xname
);
345 sc
->ctrlpage_dsaddr
= sc
->ctrlpage_dmamap
->dm_segs
[0].ds_addr
;
346 memset(sc
->ctrlpage
, 0, PAGE_SIZE
);
348 /* Set up pointers to start of each queue in kernel addr space.
349 * Each descriptor queue or status queue entry uses 2 words
351 sc
->TXDQ
= (u_int32_t
*)sc
->ctrlpage
;
352 sc
->TXDQ_cur
= sc
->TXDQ
;
353 sc
->TXDQ_avail
= TX_QLEN
- 1;
354 sc
->TXStsQ
= &sc
->TXDQ
[TX_QLEN
* 2];
355 sc
->TXStsQ_cur
= sc
->TXStsQ
;
356 sc
->RXDQ
= &sc
->TXStsQ
[TX_QLEN
];
357 sc
->RXStsQ
= &sc
->RXDQ
[RX_QLEN
* 2];
358 sc
->RXStsQ_cur
= sc
->RXStsQ
;
360 /* Program each queue's start addr, cur addr, and len registers
361 * with the physical addresses.
363 addr
= (char *)sc
->ctrlpage_dmamap
->dm_segs
[0].ds_addr
;
364 EPE_WRITE(TXDQBAdd
, (u_int32_t
)addr
);
365 EPE_WRITE(TXDQCurAdd
, (u_int32_t
)addr
);
366 EPE_WRITE(TXDQBLen
, TX_QLEN
* 2 * sizeof(u_int32_t
));
368 addr
+= (sc
->TXStsQ
- sc
->TXDQ
) * sizeof(u_int32_t
);
369 EPE_WRITE(TXStsQBAdd
, (u_int32_t
)addr
);
370 EPE_WRITE(TXStsQCurAdd
, (u_int32_t
)addr
);
371 EPE_WRITE(TXStsQBLen
, TX_QLEN
* sizeof(u_int32_t
));
373 addr
+= (sc
->RXDQ
- sc
->TXStsQ
) * sizeof(u_int32_t
);
374 EPE_WRITE(RXDQBAdd
, (u_int32_t
)addr
);
375 EPE_WRITE(RXDCurAdd
, (u_int32_t
)addr
);
376 EPE_WRITE(RXDQBLen
, RX_QLEN
* 2 * sizeof(u_int32_t
));
378 addr
+= (sc
->RXStsQ
- sc
->RXDQ
) * sizeof(u_int32_t
);
379 EPE_WRITE(RXStsQBAdd
, (u_int32_t
)addr
);
380 EPE_WRITE(RXStsQCurAdd
, (u_int32_t
)addr
);
381 EPE_WRITE(RXStsQBLen
, RX_QLEN
* 2 * sizeof(u_int32_t
));
383 /* Populate the RXDQ with mbufs */
384 for(i
= 0; i
< RX_QLEN
; i
++) {
387 bus_dmamap_create(sc
->sc_dmat
, MCLBYTES
, TX_QLEN
/4, MCLBYTES
, 0,
388 BUS_DMA_WAITOK
, &sc
->rxq
[i
].m_dmamap
);
389 MGETHDR(m
, M_WAIT
, MT_DATA
);
392 bus_dmamap_load(sc
->sc_dmat
, sc
->rxq
[i
].m_dmamap
,
393 m
->m_ext
.ext_buf
, MCLBYTES
, NULL
,
396 sc
->RXDQ
[i
* 2] = sc
->rxq
[i
].m_dmamap
->dm_segs
[0].ds_addr
;
397 sc
->RXDQ
[i
* 2 + 1] = (i
<< 16) | MCLBYTES
;
398 bus_dmamap_sync(sc
->sc_dmat
, sc
->rxq
[i
].m_dmamap
, 0,
399 MCLBYTES
, BUS_DMASYNC_PREREAD
);
402 for(i
= 0; i
< TX_QLEN
; i
++) {
403 bus_dmamap_create(sc
->sc_dmat
, MCLBYTES
, 1, MCLBYTES
, 0,
404 (BUS_DMA_WAITOK
|BUS_DMA_ALLOCNOW
),
405 &sc
->txq
[i
].m_dmamap
);
407 sc
->TXDQ
[i
* 2 + 1] = (i
<< 16);
410 /* Divide HCLK by 32 for MDC clock */
411 if (device_cfdata(&sc
->sc_dev
)->cf_flags
)
412 mdcdiv
= device_cfdata(&sc
->sc_dev
)->cf_flags
;
413 EPE_WRITE(SelfCtl
, (SelfCtl_MDCDIV(mdcdiv
)|SelfCtl_PSPRS
));
415 sc
->sc_mii
.mii_ifp
= ifp
;
416 sc
->sc_mii
.mii_readreg
= epe_mii_readreg
;
417 sc
->sc_mii
.mii_writereg
= epe_mii_writereg
;
418 sc
->sc_mii
.mii_statchg
= epe_statchg
;
419 sc
->sc_ec
.ec_mii
= &sc
->sc_mii
;
420 ifmedia_init(&sc
->sc_mii
.mii_media
, IFM_IMASK
, epe_mediachange
,
422 mii_attach((struct device
*)sc
, &sc
->sc_mii
, 0xffffffff, MII_PHY_ANY
,
424 ifmedia_set(&sc
->sc_mii
.mii_media
, IFM_ETHER
|IFM_AUTO
);
426 EPE_WRITE(BMCtl
, BMCtl_RxEn
|BMCtl_TxEn
);
427 EPE_WRITE(IntEn
, IntEn_REOFIE
);
428 /* maximum valid max frame length */
429 EPE_WRITE(MaxFrmLen
, (0x7ff << 16)|MHLEN
);
430 /* wait for receiver ready */
431 while((EPE_READ(BMSts
) & BMSts_RxAct
) == 0);
432 /* enqueue the entries in RXStsQ and RXDQ */
433 CTRLPAGE_DMASYNC(0, sc
->ctrlpage_dmamap
->dm_mapsize
,
434 BUS_DMASYNC_PREWRITE
|BUS_DMASYNC_PREREAD
);
435 EPE_WRITE(RXDEnq
, RX_QLEN
- 1);
436 EPE_WRITE(RXStsEnq
, RX_QLEN
- 1);
439 * We can support 802.1Q VLAN-sized frames.
441 sc
->sc_ec
.ec_capabilities
|= ETHERCAP_VLAN_MTU
;
443 strcpy(ifp
->if_xname
, sc
->sc_dev
.dv_xname
);
444 ifp
->if_flags
= IFF_BROADCAST
|IFF_SIMPLEX
|IFF_NOTRAILERS
|IFF_MULTICAST
;
445 ifp
->if_ioctl
= epe_ifioctl
;
446 ifp
->if_start
= epe_ifstart
;
447 ifp
->if_watchdog
= epe_ifwatchdog
;
448 ifp
->if_init
= epe_ifinit
;
449 ifp
->if_stop
= epe_ifstop
;
452 IFQ_SET_READY(&ifp
->if_snd
);
454 ether_ifattach(ifp
, (sc
)->sc_enaddr
);
458 epe_mediachange(struct ifnet
*ifp
)
460 if (ifp
->if_flags
& IFF_UP
)
466 epe_mii_readreg(struct device
*self
, int phy
, int reg
)
469 struct epe_softc
*sc
;
471 sc
= (struct epe_softc
*)self
;
472 d
= EPE_READ(SelfCtl
);
473 EPE_WRITE(SelfCtl
, d
& ~SelfCtl_PSPRS
); /* no preamble suppress */
474 EPE_WRITE(MIICmd
, (MIICmd_READ
| (phy
<< 5) | reg
));
475 while(EPE_READ(MIISts
) & MIISts_BUSY
);
476 v
= EPE_READ(MIIData
);
477 EPE_WRITE(SelfCtl
, d
); /* restore old value */
482 epe_mii_writereg(struct device
*self
, int phy
, int reg
, int val
)
484 struct epe_softc
*sc
;
487 sc
= (struct epe_softc
*)self
;
488 d
= EPE_READ(SelfCtl
);
489 EPE_WRITE(SelfCtl
, d
& ~SelfCtl_PSPRS
); /* no preamble suppress */
490 EPE_WRITE(MIIData
, val
);
491 EPE_WRITE(MIICmd
, (MIICmd_WRITE
| (phy
<< 5) | reg
));
492 while(EPE_READ(MIISts
) & MIISts_BUSY
);
493 EPE_WRITE(SelfCtl
, d
); /* restore old value */
498 epe_statchg(struct device
*self
)
500 struct epe_softc
*sc
= (struct epe_softc
*)self
;
504 * We must keep the MAC and the PHY in sync as
505 * to the status of full-duplex!
507 reg
= EPE_READ(TestCtl
);
508 if (sc
->sc_mii
.mii_media_active
& IFM_FDX
)
511 reg
&= ~TestCtl_MFDX
;
512 EPE_WRITE(TestCtl
, reg
);
518 struct epe_softc
* sc
= (struct epe_softc
*)arg
;
519 struct ifnet
* ifp
= &sc
->sc_ec
.ec_if
;
523 ifp
->if_collisions
+= EPE_READ(TXCollCnt
);
524 /* These misses are ok, they will happen if the RAM/CPU can't keep up */
525 misses
= EPE_READ(RXMissCnt
);
527 printf("%s: %d rx misses\n", sc
->sc_dev
.dv_xname
, misses
);
530 if (epe_gctx(sc
) > 0 && IFQ_IS_EMPTY(&ifp
->if_snd
) == 0) {
535 mii_tick(&sc
->sc_mii
);
536 callout_reset(&sc
->epe_tick_ch
, hz
, epe_tick
, sc
);
541 epe_ifioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
546 error
= ether_ioctl(ifp
, cmd
, data
);
547 if (error
== ENETRESET
) {
548 if (ifp
->if_flags
& IFF_RUNNING
)
557 epe_ifstart(struct ifnet
*ifp
)
559 struct epe_softc
*sc
= (struct epe_softc
*)ifp
->if_softc
;
561 bus_dma_segment_t
*segs
;
562 int s
, bi
, err
, nsegs
, ndq
;
567 if (sc
->TXDQ_avail
== 0) {
568 if (epe_gctx(sc
) == 0) {
569 /* Enable End-Of-TX-Chain interrupt */
570 EPE_WRITE(IntEn
, IntEn_REOFIE
|IntEn_ECIE
);
571 ifp
->if_flags
|= IFF_OACTIVE
;
578 bi
= sc
->TXDQ_cur
- sc
->TXDQ
;
580 IFQ_POLL(&ifp
->if_snd
, m
);
586 if ((err
= bus_dmamap_load_mbuf(sc
->sc_dmat
, sc
->txq
[bi
].m_dmamap
, m
,
588 sc
->txq
[bi
].m_dmamap
->dm_segs
[0].ds_addr
& 0x3 ||
589 sc
->txq
[bi
].m_dmamap
->dm_nsegs
> (sc
->TXDQ_avail
- ndq
)) {
590 /* Copy entire mbuf chain to new and 32-bit aligned storage */
594 bus_dmamap_unload(sc
->sc_dmat
, sc
->txq
[bi
].m_dmamap
);
596 MGETHDR(mn
, M_DONTWAIT
, MT_DATA
);
597 if (mn
== NULL
) goto stop
;
598 if (m
->m_pkthdr
.len
> (MHLEN
& (~0x3))) {
599 MCLGET(mn
, M_DONTWAIT
);
600 if ((mn
->m_flags
& M_EXT
) == 0) {
605 mn
->m_data
= (void *)(((u_int32_t
)mn
->m_data
+ 0x3) & (~0x3));
606 m_copydata(m
, 0, m
->m_pkthdr
.len
, mtod(mn
, void *));
607 mn
->m_pkthdr
.len
= mn
->m_len
= m
->m_pkthdr
.len
;
608 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
611 bus_dmamap_load_mbuf(sc
->sc_dmat
, sc
->txq
[bi
].m_dmamap
, m
,
614 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
619 bpf_mtap(ifp
->if_bpf
, m
);
620 #endif /* NBPFILTER > 0 */
622 nsegs
= sc
->txq
[bi
].m_dmamap
->dm_nsegs
;
623 segs
= sc
->txq
[bi
].m_dmamap
->dm_segs
;
624 bus_dmamap_sync(sc
->sc_dmat
, sc
->txq
[bi
].m_dmamap
, 0,
625 sc
->txq
[bi
].m_dmamap
->dm_mapsize
,
626 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
628 /* XXX: This driver hasn't been tested w/nsegs > 1 */
632 sc
->TXDQ
[bi
* 2] = segs
->ds_addr
;
634 sc
->TXDQ
[bi
* 2 + 1] = segs
->ds_len
| (bi
<< 16) |
637 sc
->TXDQ
[bi
* 2 + 1] = segs
->ds_len
| (bi
<< 16);
639 bi
= (bi
+ 1) % TX_QLEN
;
645 * Enqueue another. Don't do more than half the available
646 * descriptors before telling the MAC about them
648 if ((sc
->TXDQ_avail
- ndq
) > 0 && ndq
< TX_QLEN
/ 2) {
649 IFQ_POLL(&ifp
->if_snd
, m
);
656 sc
->TXDQ_avail
-= ndq
;
657 sc
->TXDQ_cur
= &sc
->TXDQ
[bi
];
658 CTRLPAGE_DMASYNC(0, TX_QLEN
* 2 * sizeof(u_int32_t
),
659 BUS_DMASYNC_PREWRITE
|BUS_DMASYNC_PREREAD
);
660 EPE_WRITE(TXDEnq
, ndq
);
663 if (IFQ_IS_EMPTY(&ifp
->if_snd
) == 0)
671 epe_ifwatchdog(struct ifnet
*ifp
)
673 struct epe_softc
*sc
= (struct epe_softc
*)ifp
->if_softc
;
675 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
677 printf("%s: device timeout, BMCtl = 0x%08x, BMSts = 0x%08x\n",
678 sc
->sc_dev
.dv_xname
, EPE_READ(BMCtl
), EPE_READ(BMSts
));
682 epe_ifinit(struct ifnet
*ifp
)
684 struct epe_softc
*sc
= ifp
->if_softc
;
685 int rc
, s
= splnet();
687 callout_stop(&sc
->epe_tick_ch
);
688 EPE_WRITE(RXCtl
, RXCtl_IA0
|RXCtl_BA
|RXCtl_RCRCA
|RXCtl_SRxON
);
689 EPE_WRITE(TXCtl
, TXCtl_STxON
);
690 EPE_WRITE(GIIntMsk
, GIIntMsk_INT
); /* start interrupting */
692 if ((rc
= mii_mediachg(&sc
->sc_mii
)) == ENXIO
)
697 callout_reset(&sc
->epe_tick_ch
, hz
, epe_tick
, sc
);
698 ifp
->if_flags
|= IFF_RUNNING
;
705 epe_ifstop(struct ifnet
*ifp
, int disable
)
707 struct epe_softc
*sc
= ifp
->if_softc
;
712 EPE_WRITE(GIIntMsk
, 0);
713 callout_stop(&sc
->epe_tick_ch
);
716 mii_down(&sc
->sc_mii
);
718 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
720 sc
->sc_mii
.mii_media_status
&= ~IFM_ACTIVE
;
724 epe_setaddr(struct ifnet
*ifp
)
726 struct epe_softc
*sc
= ifp
->if_softc
;
727 struct ethercom
*ac
= &sc
->sc_ec
;
728 struct ether_multi
*enm
;
729 struct ether_multistep step
;
730 u_int8_t ias
[2][ETHER_ADDR_LEN
];
731 u_int32_t h
, nma
= 0, hashes
[2] = { 0, 0 };
732 u_int32_t rxctl
= EPE_READ(RXCtl
);
734 /* disable receiver temporarily */
735 EPE_WRITE(RXCtl
, rxctl
& ~RXCtl_SRxON
);
737 rxctl
&= ~(RXCtl_MA
|RXCtl_PA
|RXCtl_IA2
|RXCtl_IA3
);
739 if (ifp
->if_flags
& IFF_PROMISC
) {
743 ifp
->if_flags
&= ~IFF_ALLMULTI
;
745 ETHER_FIRST_MULTI(step
, ac
, enm
);
746 while (enm
!= NULL
) {
747 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
, ETHER_ADDR_LEN
)) {
749 * We must listen to a range of multicast addresses.
750 * For now, just accept all multicasts, rather than
751 * trying to set only those filter bits needed to match
752 * the range. (At this time, the only use of address
753 * ranges is for IP multicast routing, for which the
754 * range is big enough to require all bits set.)
756 rxctl
&= ~(RXCtl_IA2
|RXCtl_IA3
);
758 hashes
[0] = 0xffffffffUL
;
759 hashes
[1] = 0xffffffffUL
;
760 ifp
->if_flags
|= IFF_ALLMULTI
;
765 /* We can program 2 perfect address filters for mcast */
766 memcpy(ias
[nma
], enm
->enm_addrlo
, ETHER_ADDR_LEN
);
767 rxctl
|= (1 << (nma
+ 2));
770 * XXX: Datasheet is not very clear here, I'm not sure
771 * if I'm doing this right. --joff
773 h
= ether_crc32_le(enm
->enm_addrlo
, ETHER_ADDR_LEN
);
775 /* Just want the 6 most-significant bits. */
778 hashes
[ h
/ 32 ] |= (1 << (h
% 32));
781 ETHER_NEXT_MULTI(step
, enm
);
786 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, EPE_IndAd
,
787 sc
->sc_enaddr
, ETHER_ADDR_LEN
);
788 if (rxctl
& RXCtl_IA2
) {
790 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, EPE_IndAd
,
791 ias
[0], ETHER_ADDR_LEN
);
793 if (rxctl
& RXCtl_IA3
) {
795 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, EPE_IndAd
,
796 ias
[1], ETHER_ADDR_LEN
);
798 if (hashes
[0] != 0 && hashes
[1] != 0) {
800 EPE_WRITE(HashTbl
, hashes
[0]);
801 EPE_WRITE(HashTbl
+ 4, hashes
[1]);
803 EPE_WRITE(RXCtl
, rxctl
);