if_temac.c revision 1.2 1 /* $NetBSD: if_temac.c,v 1.2 2007/03/04 05:59:46 christos Exp $ */
2
3 /*
4 * Copyright (c) 2006 Jachym Holecek
5 * All rights reserved.
6 *
7 * Written for DFC Design, s.r.o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Driver for Xilinx LocalLink TEMAC as wired on the GSRD platform.
34 *
35 * TODO:
36 * - Optimize
37 * - Checksum offload
38 * - Address filters
39 * - Support jumbo frames
40 */
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: if_temac.c,v 1.2 2007/03/04 05:59:46 christos Exp $");
44
45 #include "bpfilter.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50 #include <sys/kernel.h>
51 #include <sys/socket.h>
52 #include <sys/ioctl.h>
53 #include <sys/device.h>
54
55 #include <uvm/uvm_extern.h>
56
57 #include <net/if.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_ether.h>
61
62 #if NBPFILTER > 0
63 #include <net/bpf.h>
64 #endif
65
66 #include <machine/bus.h>
67
68 #include <evbppc/virtex/idcr.h>
69 #include <evbppc/virtex/dev/xcvbusvar.h>
70 #include <evbppc/virtex/dev/cdmacreg.h>
71 #include <evbppc/virtex/dev/temacreg.h>
72 #include <evbppc/virtex/dev/temacvar.h>
73
74 #include <dev/mii/miivar.h>
75
76
77 /* This is outside of TEMAC's DCR window, we have to hardcode it... */
78 #define DCR_ETH_BASE 0x0030
79
80 #define TEMAC_REGDEBUG 0
81 #define TEMAC_RXDEBUG 0
82 #define TEMAC_TXDEBUG 0
83
84 #if TEMAC_RXDEBUG > 0 || TEMAC_TXDEBUG > 0
85 #define TEMAC_DEBUG 1
86 #else
87 #define TEMAC_DEBUG 0
88 #endif
89
90 #if TEMAC_REGDEBUG > 0
91 #define TRACEREG(arg) printf arg
92 #else
93 #define TRACEREG(arg) /* nop */
94 #endif
95
96 /* DMA control chains take up one (16KB) page. */
97 #define TEMAC_NTXDESC 256
98 #define TEMAC_NRXDESC 256
99
100 #define TEMAC_TXQLEN 64 /* Software Tx queue length */
101 #define TEMAC_NTXSEG 16 /* Maximum Tx segments per packet */
102
103 #define TEMAC_NRXSEG 1 /* Maximum Rx segments per packet */
104 #define TEMAC_RXPERIOD 1 /* Interrupt every N descriptors. */
105 #define TEMAC_RXTIMO_HZ 100 /* Rx reaper frequency */
106
107 /* Next Tx descriptor and descriptor's offset WRT sc_cdaddr. */
108 #define TEMAC_TXSINC(n, i) (((n) + TEMAC_TXQLEN + (i)) % TEMAC_TXQLEN)
109 #define TEMAC_TXINC(n, i) (((n) + TEMAC_NTXDESC + (i)) % TEMAC_NTXDESC)
110
111 #define TEMAC_TXSNEXT(n) TEMAC_TXSINC((n), 1)
112 #define TEMAC_TXNEXT(n) TEMAC_TXINC((n), 1)
113 #define TEMAC_TXDOFF(n) (offsetof(struct temac_control, cd_txdesc) + \
114 (n) * sizeof(struct cdmac_descr))
115
116 /* Next Rx descriptor and descriptor's offset WRT sc_cdaddr. */
117 #define TEMAC_RXINC(n, i) (((n) + TEMAC_NRXDESC + (i)) % TEMAC_NRXDESC)
118 #define TEMAC_RXNEXT(n) TEMAC_RXINC((n), 1)
119 #define TEMAC_RXDOFF(n) (offsetof(struct temac_control, cd_rxdesc) + \
120 (n) * sizeof(struct cdmac_descr))
121 #define TEMAC_ISINTR(i) (((i) % TEMAC_RXPERIOD) == 0)
122 #define TEMAC_ISLAST(i) ((i) == (TEMAC_NRXDESC - 1))
123
124
125 struct temac_control {
126 struct cdmac_descr cd_txdesc[TEMAC_NTXDESC];
127 struct cdmac_descr cd_rxdesc[TEMAC_NRXDESC];
128 };
129
130 struct temac_txsoft {
131 bus_dmamap_t txs_dmap;
132 struct mbuf *txs_mbuf;
133 int txs_last;
134 };
135
136 struct temac_rxsoft {
137 bus_dmamap_t rxs_dmap;
138 struct mbuf *rxs_mbuf;
139 };
140
141 struct temac_softc {
142 struct device sc_dev;
143 struct ethercom sc_ec;
144 #define sc_if sc_ec.ec_if
145
146 /* Peripheral registers */
147 bus_space_tag_t sc_iot;
148 bus_space_handle_t sc_ioh;
149
150 /* CDMAC channel registers */
151 bus_space_tag_t sc_dma_rxt;
152 bus_space_handle_t sc_dma_rxh; /* Rx channel */
153 bus_space_handle_t sc_dma_rsh; /* Rx status */
154
155 bus_space_tag_t sc_dma_txt;
156 bus_space_handle_t sc_dma_txh; /* Tx channel */
157 bus_space_handle_t sc_dma_tsh; /* Tx status */
158
159 struct temac_txsoft sc_txsoft[TEMAC_TXQLEN];
160 struct temac_rxsoft sc_rxsoft[TEMAC_NRXDESC];
161
162 struct callout sc_rx_timo;
163 struct callout sc_mii_tick;
164 struct mii_data sc_mii;
165
166 bus_dmamap_t sc_control_dmap;
167 #define sc_cdaddr sc_control_dmap->dm_segs[0].ds_addr
168
169 struct temac_control *sc_control_data;
170 #define sc_rxdescs sc_control_data->cd_rxdesc
171 #define sc_txdescs sc_control_data->cd_txdesc
172
173 int sc_txbusy;
174
175 int sc_txfree;
176 int sc_txcur;
177 int sc_txreap;
178
179 int sc_rxreap;
180
181 int sc_txsfree;
182 int sc_txscur;
183 int sc_txsreap;
184
185 int sc_dead; /* Rx/Tx DMA error (fatal) */
186 int sc_rx_drained;
187
188 int sc_rx_chan;
189 int sc_tx_chan;
190
191 void *sc_sdhook;
192 void *sc_rx_ih;
193 void *sc_tx_ih;
194
195 bus_dma_tag_t sc_dmat;
196 };
197
198 /* Device interface. */
199 static void temac_attach(struct device *, struct device *, void *);
200
201 /* Ifnet interface. */
202 static int temac_init(struct ifnet *);
203 static int temac_ioctl(struct ifnet *, u_long, void *);
204 static void temac_start(struct ifnet *);
205 static void temac_stop(struct ifnet *, int);
206
207 /* Media management. */
208 static int temac_mediachange(struct ifnet *);
209 static void temac_mediastatus(struct ifnet *, struct ifmediareq *);
210 static int temac_mii_readreg(struct device *, int, int);
211 static void temac_mii_statchg(struct device *);
212 static void temac_mii_tick(void *);
213 static void temac_mii_writereg(struct device *, int, int, int);
214
215 /* Indirect hooks. */
216 static void temac_shutdown(void *);
217 static void temac_rx_intr(void *);
218 static void temac_tx_intr(void *);
219
220 /* Tools. */
221 static inline void temac_rxcdsync(struct temac_softc *, int, int, int);
222 static inline void temac_txcdsync(struct temac_softc *, int, int, int);
223 static void temac_txreap(struct temac_softc *);
224 static void temac_rxreap(struct temac_softc *);
225 static int temac_rxalloc(struct temac_softc *, int, int);
226 static void temac_rxtimo(void *);
227 static void temac_rxdrain(struct temac_softc *);
228 static void temac_reset(struct temac_softc *);
229 static void temac_txkick(struct temac_softc *);
230
231 /* Register access. */
232 static inline void gmi_write_8(uint32_t, uint32_t, uint32_t);
233 static inline void gmi_write_4(uint32_t, uint32_t);
234 static inline void gmi_read_8(uint32_t, uint32_t *, uint32_t *);
235 static inline uint32_t gmi_read_4(uint32_t);
236 static inline void hif_wait_stat(uint32_t);
237
238 #define cdmac_rx_stat(sc) \
239 bus_space_read_4((sc)->sc_dma_rxt, (sc)->sc_dma_rsh, 0 /* XXX hack */)
240
241 #define cdmac_rx_reset(sc) \
242 bus_space_write_4((sc)->sc_dma_rxt, (sc)->sc_dma_rsh, 0, CDMAC_STAT_RESET)
243
244 #define cdmac_rx_start(sc, val) \
245 bus_space_write_4((sc)->sc_dma_rxt, (sc)->sc_dma_rxh, CDMAC_CURDESC, (val))
246
247 #define cdmac_tx_stat(sc) \
248 bus_space_read_4((sc)->sc_dma_txt, (sc)->sc_dma_tsh, 0 /* XXX hack */)
249
250 #define cdmac_tx_reset(sc) \
251 bus_space_write_4((sc)->sc_dma_txt, (sc)->sc_dma_tsh, 0, CDMAC_STAT_RESET)
252
253 #define cdmac_tx_start(sc, val) \
254 bus_space_write_4((sc)->sc_dma_txt, (sc)->sc_dma_txh, CDMAC_CURDESC, (val))
255
256
257 CFATTACH_DECL(temac, sizeof(struct temac_softc),
258 xcvbus_child_match, temac_attach, NULL, NULL);
259
260
261 /*
262 * Private bus utilities.
263 */
264 static inline void
265 hif_wait_stat(uint32_t mask)
266 {
267 int i = 0;
268
269 while (mask != (mfidcr(IDCR_HIF_STAT) & mask)) {
270 if (i++ > 100) {
271 printf("%s: timeout waiting for 0x%08x\n",
272 __func__, mask);
273 break;
274 }
275 delay(5);
276 }
277
278 TRACEREG(("%s: stat %#08x loops %d\n", __func__, mask, i));
279 }
280
281 static inline void
282 gmi_write_4(uint32_t addr, uint32_t lo)
283 {
284 mtidcr(IDCR_HIF_ARG0, lo);
285 mtidcr(IDCR_HIF_CTRL, (addr & HIF_CTRL_GMIADDR) | HIF_CTRL_WRITE);
286 hif_wait_stat(HIF_STAT_GMIWR);
287
288 TRACEREG(("%s: %#08x <- %#08x\n", __func__, addr, lo));
289 }
290
291 static inline void
292 gmi_write_8(uint32_t addr, uint32_t lo, uint32_t hi)
293 {
294 mtidcr(IDCR_HIF_ARG1, hi);
295 gmi_write_4(addr, lo);
296 }
297
298 static inline void
299 gmi_read_8(uint32_t addr, uint32_t *lo, uint32_t *hi)
300 {
301 *lo = gmi_read_4(addr);
302 *hi = mfidcr(IDCR_HIF_ARG1);
303 }
304
305 static inline uint32_t
306 gmi_read_4(uint32_t addr)
307 {
308 uint32_t res;
309
310 mtidcr(IDCR_HIF_CTRL, addr & HIF_CTRL_GMIADDR);
311 hif_wait_stat(HIF_STAT_GMIRR);
312
313 res = mfidcr(IDCR_HIF_ARG0);
314 TRACEREG(("%s: %#08x -> %#08x\n", __func__, addr, res));
315 return (res);
316 }
317
318 /*
319 * Generic device.
320 */
321 static void
322 temac_attach(struct device *parent, struct device *self, void *aux)
323 {
324 struct xcvbus_attach_args *vaa = aux;
325 struct ll_dmac *rx = vaa->vaa_rx_dmac;
326 struct ll_dmac *tx = vaa->vaa_tx_dmac;
327 struct temac_softc *sc = (struct temac_softc *)self;
328 struct ifnet *ifp = &sc->sc_if;
329 struct mii_data *mii = &sc->sc_mii;
330 uint8_t enaddr[ETHER_ADDR_LEN];
331 bus_dma_segment_t seg;
332 int error, nseg, i;
333
334 printf(": TEMAC\n"); /* XXX will be LL_TEMAC, PLB_TEMAC */
335
336 KASSERT(rx);
337 KASSERT(tx);
338
339 sc->sc_dmat = vaa->vaa_dmat;
340 sc->sc_dead = 0;
341 sc->sc_rx_drained = 1;
342 sc->sc_txbusy = 0;
343 sc->sc_iot = vaa->vaa_iot;
344 sc->sc_dma_rxt = rx->dmac_iot;
345 sc->sc_dma_txt = tx->dmac_iot;
346
347 /*
348 * Map HIF and receive/transmit dmac registers.
349 */
350 if ((error = bus_space_map(vaa->vaa_iot, vaa->vaa_addr, TEMAC_SIZE, 0,
351 &sc->sc_ioh)) != 0) {
352 printf("%s: could not map registers\n", device_xname(self));
353 goto fail_0;
354 }
355
356 if ((error = bus_space_map(sc->sc_dma_rxt, rx->dmac_ctrl_addr,
357 CDMAC_CTRL_SIZE, 0, &sc->sc_dma_rxh)) != 0) {
358 printf("%s: could not map Rx control registers\n",
359 device_xname(self));
360 goto fail_0;
361 }
362 if ((error = bus_space_map(sc->sc_dma_rxt, rx->dmac_stat_addr,
363 CDMAC_STAT_SIZE, 0, &sc->sc_dma_rsh)) != 0) {
364 printf("%s: could not map Rx status register\n",
365 device_xname(self));
366 goto fail_0;
367 }
368
369 if ((error = bus_space_map(sc->sc_dma_txt, tx->dmac_ctrl_addr,
370 CDMAC_CTRL_SIZE, 0, &sc->sc_dma_txh)) != 0) {
371 printf("%s: could not map Tx control registers\n",
372 device_xname(self));
373 goto fail_0;
374 }
375 if ((error = bus_space_map(sc->sc_dma_txt, tx->dmac_stat_addr,
376 CDMAC_STAT_SIZE, 0, &sc->sc_dma_tsh)) != 0) {
377 printf("%s: could not map Tx status register\n",
378 device_xname(self));
379 goto fail_0;
380 }
381
382 /*
383 * Allocate and initialize DMA control chains.
384 */
385 if ((error = bus_dmamem_alloc(sc->sc_dmat,
386 sizeof(struct temac_control), 8, 0, &seg, 1, &nseg, 0)) != 0) {
387 printf("%s: could not allocate control data\n",
388 sc->sc_dev.dv_xname);
389 goto fail_0;
390 }
391
392 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, nseg,
393 sizeof(struct temac_control),
394 (void **)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) {
395 printf("%s: could not map control data\n",
396 sc->sc_dev.dv_xname);
397 goto fail_1;
398 }
399
400 if ((error = bus_dmamap_create(sc->sc_dmat,
401 sizeof(struct temac_control), 1,
402 sizeof(struct temac_control), 0, 0, &sc->sc_control_dmap)) != 0) {
403 printf("%s: could not create control data DMA map\n",
404 sc->sc_dev.dv_xname);
405 goto fail_2;
406 }
407
408 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_control_dmap,
409 sc->sc_control_data, sizeof(struct temac_control), NULL, 0)) != 0) {
410 printf("%s: could not load control data DMA map\n",
411 sc->sc_dev.dv_xname);
412 goto fail_3;
413 }
414
415 /*
416 * Link descriptor chains.
417 */
418 memset(sc->sc_control_data, 0, sizeof(struct temac_control));
419
420 for (i = 0; i < TEMAC_NTXDESC; i++) {
421 sc->sc_txdescs[i].desc_next = sc->sc_cdaddr +
422 TEMAC_TXDOFF(TEMAC_TXNEXT(i));
423 sc->sc_txdescs[i].desc_stat = CDMAC_STAT_DONE;
424 }
425 for (i = 0; i < TEMAC_NRXDESC; i++) {
426 sc->sc_rxdescs[i].desc_next = sc->sc_cdaddr +
427 TEMAC_RXDOFF(TEMAC_RXNEXT(i));
428 sc->sc_txdescs[i].desc_stat = CDMAC_STAT_DONE;
429 }
430
431 bus_dmamap_sync(sc->sc_dmat, sc->sc_control_dmap, 0,
432 sizeof(struct temac_control),
433 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
434
435 /*
436 * Initialize software state for transmit/receive jobs.
437 */
438 for (i = 0; i < TEMAC_TXQLEN; i++) {
439 if ((error = bus_dmamap_create(sc->sc_dmat,
440 ETHER_MAX_LEN_JUMBO, TEMAC_NTXSEG, ETHER_MAX_LEN_JUMBO,
441 0, 0, &sc->sc_txsoft[i].txs_dmap)) != 0) {
442 printf("%s: could not create Tx DMA map %d\n",
443 sc->sc_dev.dv_xname, i);
444 goto fail_4;
445 }
446 sc->sc_txsoft[i].txs_mbuf = NULL;
447 sc->sc_txsoft[i].txs_last = 0;
448 }
449
450 for (i = 0; i < TEMAC_NRXDESC; i++) {
451 if ((error = bus_dmamap_create(sc->sc_dmat,
452 MCLBYTES, TEMAC_NRXSEG, MCLBYTES, 0, 0,
453 &sc->sc_rxsoft[i].rxs_dmap)) != 0) {
454 printf("%s: could not create Rx DMA map %d\n",
455 sc->sc_dev.dv_xname, i);
456 goto fail_5;
457 }
458 sc->sc_rxsoft[i].rxs_mbuf = NULL;
459 }
460
461 /*
462 * Setup transfer interrupt handlers.
463 */
464 error = ENOMEM;
465
466 sc->sc_rx_ih = ll_dmac_intr_establish(rx->dmac_chan,
467 temac_rx_intr, sc);
468 if (sc->sc_rx_ih == NULL) {
469 printf("%s: could not establish Rx interrupt\n",
470 device_xname(self));
471 goto fail_5;
472 }
473
474 sc->sc_tx_ih = ll_dmac_intr_establish(tx->dmac_chan,
475 temac_tx_intr, sc);
476 if (sc->sc_tx_ih == NULL) {
477 printf("%s: could not establish Tx interrupt\n",
478 device_xname(self));
479 goto fail_6;
480 }
481
482 /* XXXFreza: faked, should read unicast address filter. */
483 enaddr[0] = 0x00;
484 enaddr[1] = 0x11;
485 enaddr[2] = 0x17;
486 enaddr[3] = 0xff;
487 enaddr[4] = 0xff;
488 enaddr[5] = 0x01;
489
490 /*
491 * Initialize the TEMAC.
492 */
493 temac_reset(sc);
494
495 /* Configure MDIO link. */
496 gmi_write_4(TEMAC_GMI_MGMTCF, GMI_MGMT_CLKDIV_100MHz | GMI_MGMT_MDIO);
497
498 /* Initialize PHY. */
499 mii->mii_ifp = ifp;
500 mii->mii_readreg = temac_mii_readreg;
501 mii->mii_writereg = temac_mii_writereg;
502 mii->mii_statchg = temac_mii_statchg;
503 ifmedia_init(&mii->mii_media, 0, temac_mediachange,
504 temac_mediastatus);
505
506 mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
507 MII_OFFSET_ANY, 0);
508 if (LIST_FIRST(&mii->mii_phys) == NULL) {
509 ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
510 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE);
511 } else {
512 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
513 }
514
515 /* Hold PHY in reset. */
516 bus_space_write_4(sc->sc_iot, sc->sc_ioh, TEMAC_RESET, TEMAC_RESET_PHY);
517
518 /* Reset EMAC. */
519 bus_space_write_4(sc->sc_iot, sc->sc_ioh, TEMAC_RESET,
520 TEMAC_RESET_EMAC);
521 delay(10000);
522
523 /* Reset peripheral, awakes PHY and EMAC. */
524 bus_space_write_4(sc->sc_iot, sc->sc_ioh, TEMAC_RESET,
525 TEMAC_RESET_PERIPH);
526 delay(40000);
527
528 /* (Re-)Configure MDIO link. */
529 gmi_write_4(TEMAC_GMI_MGMTCF, GMI_MGMT_CLKDIV_100MHz | GMI_MGMT_MDIO);
530
531 /*
532 * Hook up with network stack.
533 */
534 strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
535 ifp->if_softc = sc;
536 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
537 ifp->if_ioctl = temac_ioctl;
538 ifp->if_start = temac_start;
539 ifp->if_init = temac_init;
540 ifp->if_stop = temac_stop;
541 ifp->if_watchdog = NULL;
542 IFQ_SET_READY(&ifp->if_snd);
543 IFQ_SET_MAXLEN(&ifp->if_snd, TEMAC_TXQLEN);
544
545 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
546
547 if_attach(ifp);
548 ether_ifattach(ifp, enaddr);
549
550 sc->sc_sdhook = shutdownhook_establish(temac_shutdown, sc);
551 if (sc->sc_sdhook == NULL)
552 printf("%s: WARNING: unable to establish shutdown hook\n",
553 device_xname(self));
554
555 callout_setfunc(&sc->sc_mii_tick, temac_mii_tick, sc);
556 callout_setfunc(&sc->sc_rx_timo, temac_rxtimo, sc);
557
558 return ;
559
560 fail_6:
561 ll_dmac_intr_disestablish(rx->dmac_chan, sc->sc_rx_ih);
562 i = TEMAC_NRXDESC;
563 fail_5:
564 for (--i; i >= 0; i--)
565 bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].rxs_dmap);
566 i = TEMAC_TXQLEN;
567 fail_4:
568 for (--i; i >= 0; i--)
569 bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmap);
570 fail_3:
571 bus_dmamap_destroy(sc->sc_dmat, sc->sc_control_dmap);
572 fail_2:
573 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,
574 sizeof(struct temac_control));
575 fail_1:
576 bus_dmamem_free(sc->sc_dmat, &seg, nseg);
577 fail_0:
578 printf("%s: error = %d\n", device_xname(self), error);
579 }
580
581 /*
582 * Network device.
583 */
584 static int
585 temac_init(struct ifnet *ifp)
586 {
587 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
588 uint32_t rcr, tcr;
589 int i, error;
590
591 /* Reset DMA channels. */
592 cdmac_tx_reset(sc);
593 cdmac_rx_reset(sc);
594
595 /* Set current media. */
596 mii_mediachg(&sc->sc_mii);
597 callout_schedule(&sc->sc_mii_tick, hz);
598
599 /* Enable EMAC engine. */
600 rcr = (gmi_read_4(TEMAC_GMI_RXCF1) | GMI_RX_ENABLE) &
601 ~(GMI_RX_JUMBO | GMI_RX_FCS);
602 gmi_write_4(TEMAC_GMI_RXCF1, rcr);
603
604 tcr = (gmi_read_4(TEMAC_GMI_TXCF) | GMI_TX_ENABLE) &
605 ~(GMI_TX_JUMBO | GMI_TX_FCS);
606 gmi_write_4(TEMAC_GMI_TXCF, tcr);
607
608 /* XXXFreza: Force promiscuous mode, for now. */
609 gmi_write_4(TEMAC_GMI_AFM, GMI_AFM_PROMISC);
610 ifp->if_flags |= IFF_PROMISC;
611
612 /* Rx/Tx queues are drained -- either from attach() or stop(). */
613 sc->sc_txsfree = TEMAC_TXQLEN;
614 sc->sc_txsreap = 0;
615 sc->sc_txscur = 0;
616
617 sc->sc_txfree = TEMAC_NTXDESC;
618 sc->sc_txreap = 0;
619 sc->sc_txcur = 0;
620
621 sc->sc_rxreap = 0;
622
623 /* Allocate and map receive buffers. */
624 if (sc->sc_rx_drained) {
625 for (i = 0; i < TEMAC_NRXDESC; i++) {
626 if ((error = temac_rxalloc(sc, i, 1)) != 0) {
627 printf("%s: failed to allocate Rx "
628 "descriptor %d\n",
629 sc->sc_dev.dv_xname, i);
630
631 temac_rxdrain(sc);
632 return (error);
633 }
634 }
635 sc->sc_rx_drained = 0;
636
637 temac_rxcdsync(sc, 0, TEMAC_NRXDESC,
638 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
639 cdmac_rx_start(sc, sc->sc_cdaddr + TEMAC_RXDOFF(0));
640 }
641
642 ifp->if_flags |= IFF_RUNNING;
643 ifp->if_flags &= ~IFF_OACTIVE;
644
645 return (0);
646 }
647
648 static int
649 temac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
650 {
651 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
652 struct ifreq *ifr = (struct ifreq *)data;
653 int s, ret;
654
655 s = splnet();
656 if (sc->sc_dead) {
657 ret = EIO;
658 } else
659 switch (cmd) {
660 case SIOCSIFMEDIA:
661 case SIOCGIFMEDIA:
662 ret = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media,
663 cmd);
664 break;
665
666 default:
667 ret = ether_ioctl(ifp, cmd, data);
668 break;
669 }
670
671 splx(s);
672 return (ret);
673 }
674
675 static void
676 temac_start(struct ifnet *ifp)
677 {
678 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
679 struct temac_txsoft *txs;
680 struct mbuf *m;
681 bus_dmamap_t dmap;
682 int error, head, nsegs, i;
683
684 nsegs = 0;
685 head = sc->sc_txcur;
686 txs = NULL; /* gcc */
687
688 if (sc->sc_dead)
689 return;
690
691 KASSERT(sc->sc_txfree >= 0);
692 KASSERT(sc->sc_txsfree >= 0);
693
694 /*
695 * Push mbufs into descriptor chain until we drain the interface
696 * queue or run out of descriptors. We'll mark the first segment
697 * as "done" in hope that we might put CDMAC interrupt above IPL_NET
698 * and have it start jobs & mark packets for GC preemtively for
699 * us -- creativity due to limitations in CDMAC transfer engine
700 * (it really consumes lists, not circular queues, AFAICS).
701 *
702 * We schedule one interrupt per Tx batch.
703 */
704 while (1) {
705 IFQ_POLL(&ifp->if_snd, m);
706 if (m == NULL)
707 break;
708
709 if (sc->sc_txsfree == 0) {
710 ifp->if_flags |= IFF_OACTIVE;
711 break;
712 }
713
714 txs = &sc->sc_txsoft[sc->sc_txscur];
715 dmap = txs->txs_dmap;
716
717 if (txs->txs_mbuf != NULL)
718 printf("FOO\n");
719 if (txs->txs_last)
720 printf("BAR\n");
721
722 if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m,
723 BUS_DMA_WRITE | BUS_DMA_NOWAIT)) != 0) {
724 if (error == EFBIG) {
725 printf("%s: Tx consumes too many segments, "
726 "dropped\n", sc->sc_dev.dv_xname);
727 IFQ_DEQUEUE(&ifp->if_snd, m);
728 m_freem(m);
729 continue;
730 } else {
731 printf("%s: Tx stall due to resource "
732 "shortage\n", sc->sc_dev.dv_xname);
733 break;
734 }
735 }
736
737 /*
738 * If we're short on DMA descriptors, notify upper layers
739 * and leave this packet for later.
740 */
741 if (dmap->dm_nsegs > sc->sc_txfree) {
742 bus_dmamap_unload(sc->sc_dmat, dmap);
743 ifp->if_flags |= IFF_OACTIVE;
744 break;
745 }
746
747 IFQ_DEQUEUE(&ifp->if_snd, m);
748
749 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
750 BUS_DMASYNC_PREWRITE);
751 txs->txs_mbuf = m;
752
753 /*
754 * Map the packet into descriptor chain. XXX We'll want
755 * to fill checksum offload commands here.
756 *
757 * We would be in a race if we weren't blocking CDMAC intr
758 * at this point -- we need to be locked against txreap()
759 * because of dmasync ops.
760 */
761
762 temac_txcdsync(sc, sc->sc_txcur, dmap->dm_nsegs,
763 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
764
765 for (i = 0; i < dmap->dm_nsegs; i++) {
766 sc->sc_txdescs[sc->sc_txcur].desc_addr =
767 dmap->dm_segs[i].ds_addr;
768 sc->sc_txdescs[sc->sc_txcur].desc_size =
769 dmap->dm_segs[i].ds_len;
770 sc->sc_txdescs[sc->sc_txcur].desc_stat =
771 (i == 0 ? CDMAC_STAT_SOP : 0) |
772 (i == (dmap->dm_nsegs - 1) ? CDMAC_STAT_EOP : 0);
773
774 sc->sc_txcur = TEMAC_TXNEXT(sc->sc_txcur);
775 }
776
777 sc->sc_txfree -= dmap->dm_nsegs;
778 nsegs += dmap->dm_nsegs;
779
780 sc->sc_txscur = TEMAC_TXSNEXT(sc->sc_txscur);
781 sc->sc_txsfree--;
782 }
783
784 /* Get data running if we queued any. */
785 if (nsegs > 0) {
786 int tail = TEMAC_TXINC(sc->sc_txcur, -1);
787
788 /* Mark the last packet in this job. */
789 txs->txs_last = 1;
790
791 /* Mark the last descriptor in this job. */
792 sc->sc_txdescs[tail].desc_stat |= CDMAC_STAT_STOP |
793 CDMAC_STAT_INTR;
794 temac_txcdsync(sc, head, nsegs,
795 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
796
797 temac_txkick(sc);
798 #if TEMAC_TXDEBUG > 0
799 printf("%s: start: txcur %03d -> %03d, nseg %03d\n",
800 sc->sc_dev.dv_xname, head, sc->sc_txcur, nsegs);
801 #endif
802 }
803 }
804
805 static void
806 temac_stop(struct ifnet *ifp, int disable)
807 {
808 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
809 struct temac_txsoft *txs;
810 int i;
811
812 #if TEMAC_DEBUG > 0
813 printf("%s: stop\n", device_xname(&sc->sc_dev));
814 #endif
815
816 /* Down the MII. */
817 callout_stop(&sc->sc_mii_tick);
818 mii_down(&sc->sc_mii);
819
820 /* Stop the engine. */
821 temac_reset(sc);
822
823 /* Drain buffers queues (unconditionally). */
824 temac_rxdrain(sc);
825
826 for (i = 0; i < TEMAC_TXQLEN; i++) {
827 txs = &sc->sc_txsoft[i];
828
829 if (txs->txs_mbuf != NULL) {
830 bus_dmamap_unload(sc->sc_dmat, txs->txs_dmap);
831 m_freem(txs->txs_mbuf);
832 txs->txs_mbuf = NULL;
833 txs->txs_last = 0;
834 }
835 }
836 sc->sc_txbusy = 0;
837
838 /* Acknowledge we're down. */
839 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
840 }
841
842 /*
843 * Media management.
844 */
845 static int
846 temac_mediachange(struct ifnet *ifp)
847 {
848 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
849
850 if (ifp->if_flags & IFF_UP)
851 mii_mediachg(&sc->sc_mii);
852 return (0);
853 }
854
855 static void
856 temac_mediastatus(struct ifnet *ifp, struct ifmediareq *imr)
857 {
858 struct temac_softc *sc = (struct temac_softc *)ifp->if_softc;
859
860 mii_pollstat(&sc->sc_mii);
861
862 imr->ifm_status = sc->sc_mii.mii_media_status;
863 imr->ifm_active = sc->sc_mii.mii_media_active;
864 }
865
866 static int
867 temac_mii_readreg(struct device *self, int phy, int reg)
868 {
869 mtidcr(IDCR_HIF_ARG0, (phy << 5) | reg);
870 mtidcr(IDCR_HIF_CTRL, TEMAC_GMI_MII_ADDR);
871 hif_wait_stat(HIF_STAT_MIIRR);
872
873 return (int)mfidcr(IDCR_HIF_ARG0);
874 }
875
876 static void
877 temac_mii_writereg(struct device *self, int phy, int reg, int val)
878 {
879 mtidcr(IDCR_HIF_ARG0, val);
880 mtidcr(IDCR_HIF_CTRL, TEMAC_GMI_MII_WRVAL | HIF_CTRL_WRITE);
881 mtidcr(IDCR_HIF_ARG0, (phy << 5) | reg);
882 mtidcr(IDCR_HIF_CTRL, TEMAC_GMI_MII_ADDR | HIF_CTRL_WRITE);
883 hif_wait_stat(HIF_STAT_MIIWR);
884 }
885
886 static void
887 temac_mii_statchg(struct device *self)
888 {
889 struct temac_softc *sc = (struct temac_softc *)self;
890 uint32_t rcf, tcf, mmc;
891
892 /* Full/half duplex link. */
893 rcf = gmi_read_4(TEMAC_GMI_RXCF1);
894 tcf = gmi_read_4(TEMAC_GMI_TXCF);
895
896 if (sc->sc_mii.mii_media_active & IFM_FDX) {
897 gmi_write_4(TEMAC_GMI_RXCF1, rcf & ~GMI_RX_HDX);
898 gmi_write_4(TEMAC_GMI_TXCF, tcf & ~GMI_TX_HDX);
899 } else {
900 gmi_write_4(TEMAC_GMI_RXCF1, rcf | GMI_RX_HDX);
901 gmi_write_4(TEMAC_GMI_TXCF, tcf | GMI_TX_HDX);
902 }
903
904 /* Link speed. */
905 mmc = gmi_read_4(TEMAC_GMI_MMC) & ~GMI_MMC_SPEED_MASK;
906
907 switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
908 case IFM_10_T:
909 /*
910 * XXXFreza: the GMAC is not happy with 10Mbit ethernet,
911 * although the documentation claims it's supported. Maybe
912 * it's just my equipment...
913 */
914 mmc |= GMI_MMC_SPEED_10;
915 break;
916 case IFM_100_TX:
917 mmc |= GMI_MMC_SPEED_100;
918 break;
919 case IFM_1000_T:
920 mmc |= GMI_MMC_SPEED_1000;
921 break;
922 }
923
924 gmi_write_4(TEMAC_GMI_MMC, mmc);
925 }
926
927 static void
928 temac_mii_tick(void *arg)
929 {
930 struct temac_softc *sc = (struct temac_softc *)arg;
931 int s;
932
933 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
934 return ;
935
936 s = splnet();
937 mii_tick(&sc->sc_mii);
938 splx(s);
939
940 callout_schedule(&sc->sc_mii_tick, hz);
941 }
942
943 /*
944 * External hooks.
945 */
946 static void
947 temac_shutdown(void *arg)
948 {
949 struct temac_softc *sc = (struct temac_softc *)arg;
950
951 temac_reset(sc);
952 }
953
954 static void
955 temac_tx_intr(void *arg)
956 {
957 struct temac_softc *sc = (struct temac_softc *)arg;
958 uint32_t stat;
959
960 /* XXX: We may need to splnet() here if cdmac(4) changes. */
961
962 if ((stat = cdmac_tx_stat(sc)) & CDMAC_STAT_ERROR) {
963 printf("%s: transmit DMA is toast (%#08x), halted!\n",
964 sc->sc_dev.dv_xname, stat);
965
966 /* XXXFreza: how to signal this upstream? */
967 temac_stop(&sc->sc_if, 1);
968 sc->sc_dead = 1;
969 }
970
971 #if TEMAC_DEBUG > 0
972 printf("%s: tx intr 0x%08x\n", device_xname(&sc->sc_dev), stat);
973 #endif
974 temac_txreap(sc);
975 }
976
977 static void
978 temac_rx_intr(void *arg)
979 {
980 struct temac_softc *sc = (struct temac_softc *)arg;
981 uint32_t stat;
982
983 /* XXX: We may need to splnet() here if cdmac(4) changes. */
984
985 if ((stat = cdmac_rx_stat(sc)) & CDMAC_STAT_ERROR) {
986 printf("%s: receive DMA is toast (%#08x), halted!\n",
987 sc->sc_dev.dv_xname, stat);
988
989 /* XXXFreza: how to signal this upstream? */
990 temac_stop(&sc->sc_if, 1);
991 sc->sc_dead = 1;
992 }
993
994 #if TEMAC_DEBUG > 0
995 printf("%s: rx intr 0x%08x\n", device_xname(&sc->sc_dev), stat);
996 #endif
997 temac_rxreap(sc);
998 }
999
1000 /*
1001 * Utils.
1002 */
1003 static inline void
1004 temac_txcdsync(struct temac_softc *sc, int first, int cnt, int flag)
1005 {
1006 if ((first + cnt) > TEMAC_NTXDESC) {
1007 bus_dmamap_sync(sc->sc_dmat, sc->sc_control_dmap,
1008 TEMAC_TXDOFF(first),
1009 sizeof(struct cdmac_descr) * (TEMAC_NTXDESC - first),
1010 flag);
1011 cnt = (first + cnt) % TEMAC_NTXDESC;
1012 first = 0;
1013 }
1014
1015 bus_dmamap_sync(sc->sc_dmat, sc->sc_control_dmap,
1016 TEMAC_TXDOFF(first),
1017 sizeof(struct cdmac_descr) * cnt,
1018 flag);
1019 }
1020
1021 static inline void
1022 temac_rxcdsync(struct temac_softc *sc, int first, int cnt, int flag)
1023 {
1024 if ((first + cnt) > TEMAC_NRXDESC) {
1025 bus_dmamap_sync(sc->sc_dmat, sc->sc_control_dmap,
1026 TEMAC_RXDOFF(first),
1027 sizeof(struct cdmac_descr) * (TEMAC_NRXDESC - first),
1028 flag);
1029 cnt = (first + cnt) % TEMAC_NRXDESC;
1030 first = 0;
1031 }
1032
1033 bus_dmamap_sync(sc->sc_dmat, sc->sc_control_dmap,
1034 TEMAC_RXDOFF(first),
1035 sizeof(struct cdmac_descr) * cnt,
1036 flag);
1037 }
1038
1039 static void
1040 temac_txreap(struct temac_softc *sc)
1041 {
1042 struct temac_txsoft *txs;
1043 bus_dmamap_t dmap;
1044 int sent = 0;
1045
1046 /*
1047 * Transmit interrupts happen on the last descriptor of Tx jobs.
1048 * Hence, every time we're called (and we assume txintr is our
1049 * only caller!), we reap packets upto and including the one
1050 * marked as last-in-batch.
1051 *
1052 * XXX we rely on that we make EXACTLY one batch per intr, no more
1053 */
1054 while (sc->sc_txsfree != TEMAC_TXQLEN) {
1055 txs = &sc->sc_txsoft[sc->sc_txsreap];
1056 dmap = txs->txs_dmap;
1057
1058 sc->sc_txreap = TEMAC_TXINC(sc->sc_txreap, dmap->dm_nsegs);
1059 sc->sc_txfree += dmap->dm_nsegs;
1060
1061 bus_dmamap_unload(sc->sc_dmat, txs->txs_dmap);
1062 m_freem(txs->txs_mbuf);
1063 txs->txs_mbuf = NULL;
1064
1065 sc->sc_if.if_opackets++;
1066 sent = 1;
1067
1068 sc->sc_txsreap = TEMAC_TXSNEXT(sc->sc_txsreap);
1069 sc->sc_txsfree++;
1070
1071 if (txs->txs_last) {
1072 txs->txs_last = 0;
1073 sc->sc_txbusy = 0; /* channel stopped now */
1074
1075 temac_txkick(sc);
1076 break;
1077 }
1078 }
1079
1080 if (sent && (sc->sc_if.if_flags & IFF_OACTIVE))
1081 sc->sc_if.if_flags &= ~IFF_OACTIVE;
1082 }
1083
1084 static int
1085 temac_rxalloc(struct temac_softc *sc, int which, int verbose)
1086 {
1087 struct temac_rxsoft *rxs;
1088 struct mbuf *m;
1089 uint32_t stat;
1090 int error;
1091
1092 rxs = &sc->sc_rxsoft[which];
1093
1094 /* The mbuf itself is not our problem, just clear DMA related stuff. */
1095 if (rxs->rxs_mbuf != NULL) {
1096 bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmap);
1097 rxs->rxs_mbuf = NULL;
1098 }
1099
1100 /*
1101 * We would like to store mbuf and dmap in application specific
1102 * fields of the descriptor, but that doesn't work for Rx. Shame
1103 * on Xilinx for this (and for the useless timer architecture).
1104 *
1105 * Hence each descriptor needs its own soft state. We may want
1106 * to merge multiple rxs's into a monster mbuf when we support
1107 * jumbo frames though. Also, we use single set of indexing
1108 * variables for both sc_rxdescs[] and sc_rxsoft[].
1109 */
1110 MGETHDR(m, M_DONTWAIT, MT_DATA);
1111 if (m == NULL) {
1112 if (verbose)
1113 printf("%s: out of Rx header mbufs\n",
1114 sc->sc_dev.dv_xname);
1115 return (ENOBUFS);
1116 }
1117 MCLAIM(m, &sc->sc_ec.ec_rx_mowner);
1118
1119 MCLGET(m, M_DONTWAIT);
1120 if ((m->m_flags & M_EXT) == 0) {
1121 if (verbose)
1122 printf("%s: out of Rx cluster mbufs\n",
1123 sc->sc_dev.dv_xname);
1124 m_freem(m);
1125 return (ENOBUFS);
1126 }
1127
1128 rxs->rxs_mbuf = m;
1129 m->m_pkthdr.len = m->m_len = MCLBYTES;
1130
1131 /* Make sure the payload after ethernet header is 4-aligned. */
1132 m_adj(m, 2);
1133
1134 error = bus_dmamap_load_mbuf(sc->sc_dmat, rxs->rxs_dmap, m,
1135 BUS_DMA_NOWAIT);
1136 if (error) {
1137 if (verbose)
1138 printf("%s: could not map Rx descriptor %d, "
1139 "error = %d\n", sc->sc_dev.dv_xname, which, error);
1140
1141 rxs->rxs_mbuf = NULL;
1142 m_freem(m);
1143
1144 return (error);
1145 }
1146
1147 stat = \
1148 (TEMAC_ISINTR(which) ? CDMAC_STAT_INTR : 0) |
1149 (TEMAC_ISLAST(which) ? CDMAC_STAT_STOP : 0);
1150
1151 bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmap, 0,
1152 rxs->rxs_dmap->dm_mapsize, BUS_DMASYNC_PREREAD);
1153
1154 /* Descriptor post-sync, if needed, left to the caller. */
1155
1156 sc->sc_rxdescs[which].desc_addr = rxs->rxs_dmap->dm_segs[0].ds_addr;
1157 sc->sc_rxdescs[which].desc_size = rxs->rxs_dmap->dm_segs[0].ds_len;
1158 sc->sc_rxdescs[which].desc_stat = stat;
1159
1160 /* Descriptor pre-sync, if needed, left to the caller. */
1161
1162 return (0);
1163 }
1164
1165 static void
1166 temac_rxreap(struct temac_softc *sc)
1167 {
1168 struct ifnet *ifp = &sc->sc_if;
1169 uint32_t stat, rxstat, rxsize;
1170 struct mbuf *m;
1171 int nseg, head, tail;
1172
1173 head = sc->sc_rxreap;
1174 tail = 0; /* gcc */
1175 nseg = 0;
1176
1177 /*
1178 * Collect finished entries on the Rx list, kick DMA if we hit
1179 * the end. DMA will always stop on the last descriptor in chain,
1180 * so it will never hit a reap-in-progress descriptor.
1181 */
1182 while (1) {
1183 /* Maybe we previously failed to refresh this one? */
1184 if (sc->sc_rxsoft[sc->sc_rxreap].rxs_mbuf == NULL) {
1185 if (temac_rxalloc(sc, sc->sc_rxreap, 0) != 0)
1186 break;
1187
1188 sc->sc_rxreap = TEMAC_RXNEXT(sc->sc_rxreap);
1189 continue;
1190 }
1191 temac_rxcdsync(sc, sc->sc_rxreap, 1,
1192 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1193
1194 stat = sc->sc_rxdescs[sc->sc_rxreap].desc_stat;
1195 m = NULL;
1196
1197 if ((stat & CDMAC_STAT_DONE) == 0)
1198 break;
1199
1200 /* Count any decriptor we've collected, regardless of status. */
1201 nseg ++;
1202
1203 /* XXXFreza: This won't work for jumbo frames. */
1204
1205 if ((stat & (CDMAC_STAT_EOP | CDMAC_STAT_SOP)) !=
1206 (CDMAC_STAT_EOP | CDMAC_STAT_SOP)) {
1207 printf("%s: Rx packet doesn't fit in "
1208 "one descriptor, stat = %#08x\n",
1209 sc->sc_dev.dv_xname, stat);
1210 goto badframe;
1211 }
1212
1213 /* Dissect TEMAC footer if this is end of packet. */
1214 rxstat = sc->sc_rxdescs[sc->sc_rxreap].desc_rxstat;
1215 rxsize = sc->sc_rxdescs[sc->sc_rxreap].desc_rxsize &
1216 RXSIZE_MASK;
1217
1218 if ((rxstat & RXSTAT_GOOD) == 0 ||
1219 (rxstat & RXSTAT_SICK) != 0) {
1220 printf("%s: corrupt Rx packet, rxstat = %#08x\n",
1221 sc->sc_dev.dv_xname, rxstat);
1222 goto badframe;
1223 }
1224
1225 /* We are now bound to succeed. */
1226 bus_dmamap_sync(sc->sc_dmat,
1227 sc->sc_rxsoft[sc->sc_rxreap].rxs_dmap, 0,
1228 sc->sc_rxsoft[sc->sc_rxreap].rxs_dmap->dm_mapsize,
1229 BUS_DMASYNC_POSTREAD);
1230
1231 m = sc->sc_rxsoft[sc->sc_rxreap].rxs_mbuf;
1232 m->m_pkthdr.rcvif = ifp;
1233 m->m_pkthdr.len = m->m_len = rxsize;
1234
1235 badframe:
1236 /* Get ready for more work. */
1237 tail = sc->sc_rxreap;
1238 sc->sc_rxreap = TEMAC_RXNEXT(sc->sc_rxreap);
1239
1240 /* On failures we reuse the descriptor and go ahead. */
1241 if (m == NULL) {
1242 sc->sc_rxdescs[tail].desc_stat =
1243 (TEMAC_ISINTR(tail) ? CDMAC_STAT_INTR : 0) |
1244 (TEMAC_ISLAST(tail) ? CDMAC_STAT_STOP : 0);
1245
1246 ifp->if_ierrors++;
1247 continue;
1248 }
1249
1250 #if NBPFILTER > 0
1251 if (ifp->if_bpf != NULL)
1252 bpf_mtap(ifp->if_bpf, m);
1253 #endif
1254
1255 ifp->if_ipackets++;
1256 (ifp->if_input)(ifp, m);
1257
1258 /* Refresh descriptor, bail out if we're out of buffers. */
1259 if (temac_rxalloc(sc, tail, 1) != 0) {
1260 sc->sc_rxreap = TEMAC_RXINC(sc->sc_rxreap, -1);
1261 printf("%s: Rx give up for now\n", sc->sc_dev.dv_xname);
1262 break;
1263 }
1264 }
1265
1266 /* We may now have a contiguous ready-to-go chunk of descriptors. */
1267 if (nseg > 0) {
1268 #if TEMAC_RXDEBUG > 0
1269 printf("%s: rxreap: rxreap %03d -> %03d, nseg %03d\n",
1270 sc->sc_dev.dv_xname, head, sc->sc_rxreap, nseg);
1271 #endif
1272 temac_rxcdsync(sc, head, nseg,
1273 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1274
1275 if (TEMAC_ISLAST(tail))
1276 cdmac_rx_start(sc, sc->sc_cdaddr + TEMAC_RXDOFF(0));
1277 }
1278
1279 /* Ensure maximum Rx latency is kept under control. */
1280 callout_schedule(&sc->sc_rx_timo, hz / TEMAC_RXTIMO_HZ);
1281 }
1282
1283 static void
1284 temac_rxtimo(void *arg)
1285 {
1286 struct temac_softc *sc = (struct temac_softc *)arg;
1287 int s;
1288
1289 /* We run TEMAC_RXTIMO_HZ times/sec to ensure Rx doesn't stall. */
1290 s = splnet();
1291 temac_rxreap(sc);
1292 splx(s);
1293 }
1294
1295 static void
1296 temac_reset(struct temac_softc *sc)
1297 {
1298 uint32_t rcr, tcr;
1299
1300 /* Kill CDMAC channels. */
1301 cdmac_tx_reset(sc);
1302 cdmac_rx_reset(sc);
1303
1304 /* Disable receiver. */
1305 rcr = gmi_read_4(TEMAC_GMI_RXCF1) & ~GMI_RX_ENABLE;
1306 gmi_write_4(TEMAC_GMI_RXCF1, rcr);
1307
1308 /* Disable transmitter. */
1309 tcr = gmi_read_4(TEMAC_GMI_TXCF) & ~GMI_TX_ENABLE;
1310 gmi_write_4(TEMAC_GMI_TXCF, tcr);
1311 }
1312
1313 static void
1314 temac_rxdrain(struct temac_softc *sc)
1315 {
1316 struct temac_rxsoft *rxs;
1317 int i;
1318
1319 for (i = 0; i < TEMAC_NRXDESC; i++) {
1320 rxs = &sc->sc_rxsoft[i];
1321
1322 if (rxs->rxs_mbuf != NULL) {
1323 bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmap);
1324 m_freem(rxs->rxs_mbuf);
1325 rxs->rxs_mbuf = NULL;
1326 }
1327 }
1328
1329 sc->sc_rx_drained = 1;
1330 }
1331
1332 static void
1333 temac_txkick(struct temac_softc *sc)
1334 {
1335 if (sc->sc_txsoft[sc->sc_txsreap].txs_mbuf != NULL &&
1336 sc->sc_txbusy == 0) {
1337 cdmac_tx_start(sc, sc->sc_cdaddr + TEMAC_TXDOFF(sc->sc_txreap));
1338 sc->sc_txbusy = 1;
1339 }
1340 }
1341