Annotation of src/sys/arch/playstation2/dev/if_smap.c, Revision 1.17.6.5
1.17.6.5! skrll 1: /* $NetBSD: if_smap.c,v 1.17.6.4 2016/07/09 20:24:55 skrll Exp $ */
1.1 uch 2:
3: /*-
4: * Copyright (c) 2001 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by UCHIYAMA Yasushi.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
1.5 lukem 31:
32: #include <sys/cdefs.h>
1.17.6.5! skrll 33: __KERNEL_RCSID(0, "$NetBSD: if_smap.c,v 1.17.6.4 2016/07/09 20:24:55 skrll Exp $");
1.1 uch 34:
35: #include "debug_playstation2.h"
36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
1.17.6.3 skrll 39: #include <sys/device.h>
1.1 uch 40: #include <sys/syslog.h>
41: #include <sys/mbuf.h>
42: #include <sys/ioctl.h>
1.17.6.3 skrll 43: #include <sys/rndsource.h>
1.1 uch 44: #include <sys/socket.h>
45:
46: #include <playstation2/ee/eevar.h>
47:
48: #include <net/if.h>
49: #include <net/if_dl.h>
50: #include <net/if_types.h>
51:
52: #include <net/if_ether.h>
53: #include <net/if_media.h>
54:
55: #include <dev/mii/miivar.h>
56:
57: #include <netinet/in.h>
58: #include <netinet/in_systm.h>
59: #include <netinet/in_var.h>
60: #include <netinet/ip.h>
61: #include <netinet/if_inarp.h>
62:
63: #include <net/bpf.h>
64: #include <net/bpfdesc.h>
65:
66: #include <playstation2/dev/spdvar.h>
67: #include <playstation2/dev/spdreg.h>
68: #include <playstation2/dev/emac3var.h>
69: #include <playstation2/dev/if_smapreg.h>
70:
71: #ifdef SMAP_DEBUG
72: #include <playstation2/ee/gsvar.h>
73: int smap_debug = 0;
74: #define DPRINTF(fmt, args...) \
75: if (smap_debug) \
1.10 perry 76: printf("%s: " fmt, __func__ , ##args)
1.1 uch 77: #define DPRINTFN(n, arg) \
78: if (smap_debug > (n)) \
1.10 perry 79: printf("%s: " fmt, __func__ , ##args)
1.1 uch 80: #define STATIC
81: struct smap_softc *__sc;
82: void __smap_status(int);
83: void __smap_lock_check(const char *, int);
1.10 perry 84: #define FUNC_ENTER() __smap_lock_check(__func__, 1)
85: #define FUNC_EXIT() __smap_lock_check(__func__, 0)
1.1 uch 86: #else
87: #define DPRINTF(arg...) ((void)0)
88: #define DPRINTFN(n, arg...) ((void)0)
89: #define STATIC static
90: #define FUNC_ENTER() ((void)0)
91: #define FUNC_EXIT() ((void)0)
92: #endif
93:
94: struct smap_softc {
95: struct emac3_softc emac3;
96: struct ethercom ethercom;
97:
98: u_int32_t *tx_buf;
99: u_int32_t *rx_buf;
100: struct smap_desc *tx_desc;
101: struct smap_desc *rx_desc;
102:
103: #define SMAP_FIFO_ALIGN 4
104: int tx_buf_freesize; /* buffer usage */
105: int tx_desc_cnt; /* descriptor usage */
106: u_int16_t tx_fifo_ptr;
107: int tx_done_index, tx_start_index;
108: int rx_done_index;
109:
1.17.6.1 skrll 110: krndsource_t rnd_source;
1.1 uch 111: };
112:
113: #define DEVNAME (sc->emac3.dev.dv_xname)
114: #define ROUND4(x) (((x) + 3) & ~3)
115: #define ROUND16(x) (((x) + 15) & ~15)
116:
117: STATIC int smap_match(struct device *, struct cfdata *, void *);
118: STATIC void smap_attach(struct device *, struct device *, void *);
119:
1.17.6.3 skrll 120: CFATTACH_DECL_NEW(smap, sizeof (struct smap_softc),
1.3 thorpej 121: smap_match, smap_attach, NULL, NULL);
1.1 uch 122:
123: STATIC int smap_intr(void *);
124: STATIC void smap_rxeof(void *);
125: STATIC void smap_txeof(void *);
126: STATIC void smap_start(struct ifnet *);
127: STATIC void smap_watchdog(struct ifnet *);
1.9 christos 128: STATIC int smap_ioctl(struct ifnet *, u_long, void *);
1.1 uch 129: STATIC int smap_init(struct ifnet *);
130: STATIC void smap_stop(struct ifnet *, int);
131:
132: STATIC int smap_get_eaddr(struct smap_softc *, u_int8_t *);
133: STATIC int smap_fifo_init(struct smap_softc *);
134: STATIC int smap_fifo_reset(bus_addr_t);
135: STATIC void smap_desc_init(struct smap_softc *);
136:
137: int
138: smap_match(struct device *parent, struct cfdata *cf, void *aux)
139: {
140: struct spd_attach_args *spa = aux;
141:
142: if (spa->spa_slot != SPD_NIC)
143: return (0);
144:
145: return (1);
146: }
147:
148: void
149: smap_attach(struct device *parent, struct device *self, void *aux)
150: {
151: struct spd_attach_args *spa = aux;
152: struct smap_softc *sc = (void *)self;
153: struct emac3_softc *emac3 = &sc->emac3;
154: struct ifnet *ifp = &sc->ethercom.ec_if;
155: struct mii_data *mii = &emac3->mii;
156: void *txbuf, *rxbuf;
157: u_int16_t r;
158:
159: #ifdef SMAP_DEBUG
160: __sc = sc;
161: #endif
162:
163: printf(": %s\n", spa->spa_product_name);
164:
165: /* SPD EEPROM */
166: if (smap_get_eaddr(sc, emac3->eaddr) != 0)
167: return;
168:
169: printf("%s: Ethernet address %s\n", DEVNAME,
170: ether_sprintf(emac3->eaddr));
171:
172: /* disable interrupts */
173: r = _reg_read_2(SPD_INTR_ENABLE_REG16);
174: r &= ~(SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV |
175: SPD_INTR_EMAC3);
176: _reg_write_2(SPD_INTR_ENABLE_REG16, r);
177: emac3_intr_disable();
178:
179: /* clear pending interrupts */
180: _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
181: SPD_INTR_RXDNV);
182: emac3_intr_clear();
183:
184: /* buffer descriptor mode */
185: _reg_write_1(SMAP_DESC_MODE_REG8, 0);
186:
187: if (smap_fifo_init(sc) != 0)
188: return;
189:
190: if (emac3_init(&sc->emac3) != 0)
191: return;
192: emac3_intr_disable();
193: emac3_disable();
194:
195: smap_desc_init(sc);
196:
197: /* allocate temporary buffer */
198: txbuf = malloc(ETHER_MAX_LEN - ETHER_CRC_LEN + SMAP_FIFO_ALIGN + 16,
199: M_DEVBUF, M_NOWAIT);
200: if (txbuf == NULL) {
201: printf("%s: no memory.\n", DEVNAME);
202: return;
203: }
204:
205: rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16,
206: M_DEVBUF, M_NOWAIT);
207: if (rxbuf == NULL) {
208: printf("%s: no memory.\n", DEVNAME);
209: free(txbuf, M_DEVBUF);
210: return;
211: }
212:
213: sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf);
214: sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf);
215:
216: /*
217: * setup MI layer
218: */
219: strcpy(ifp->if_xname, DEVNAME);
220: ifp->if_softc = sc;
221: ifp->if_start = smap_start;
222: ifp->if_ioctl = smap_ioctl;
223: ifp->if_init = smap_init;
224: ifp->if_stop = smap_stop;
225: ifp->if_watchdog= smap_watchdog;
226: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
227: IFF_MULTICAST;
228: IFQ_SET_READY(&ifp->if_snd);
229:
230: /* ifmedia setup. */
231: mii->mii_ifp = ifp;
232: mii->mii_readreg = emac3_phy_readreg;
233: mii->mii_writereg = emac3_phy_writereg;
234: mii->mii_statchg = emac3_phy_statchg;
1.11 dyoung 235: sc->ethercom.ec_mii = mii;
236: ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
1.1 uch 237: mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY,
238: MII_OFFSET_ANY, 0);
239:
240: /* Choose a default media. */
241: if (LIST_FIRST(&mii->mii_phys) == NULL) {
242: ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
243: ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE);
244: } else {
245: ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
246: }
247:
248: if_attach(ifp);
1.17.6.5! skrll 249: if_deferred_start_init(ifp, NULL);
1.1 uch 250: ether_ifattach(ifp, emac3->eaddr);
251:
252: spd_intr_establish(SPD_NIC, smap_intr, sc);
253:
254: rnd_attach_source(&sc->rnd_source, DEVNAME,
1.17 tls 255: RND_TYPE_NET, RND_FLAG_DEFAULT);
1.1 uch 256: }
257:
258: int
1.9 christos 259: smap_ioctl(struct ifnet *ifp, u_long command, void *data)
1.1 uch 260: {
261: struct smap_softc *sc = ifp->if_softc;
262: int error, s;
263:
264: s = splnet();
265:
1.11 dyoung 266: error = ether_ioctl(ifp, command, data);
267:
268: if (error == ENETRESET) {
269: if (ifp->if_flags & IFF_RUNNING)
270: emac3_setmulti(&sc->emac3, &sc->ethercom);
271: error = 0;
1.1 uch 272: }
273:
274: splx(s);
275:
276: return (error);
277: }
278:
279: int
280: smap_intr(void *arg)
281: {
282: struct smap_softc *sc = arg;
283: struct ifnet *ifp;
284: u_int16_t cause, disable, r;
285:
286: cause = _reg_read_2(SPD_INTR_STATUS_REG16) &
287: _reg_read_2(SPD_INTR_ENABLE_REG16);
288:
289: disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV);
290: if (disable) {
291: r = _reg_read_2(SPD_INTR_ENABLE_REG16);
292: r &= ~disable;
293: _reg_write_2(SPD_INTR_ENABLE_REG16, r);
294:
295: printf("%s: invalid descriptor. (%c%c)\n", DEVNAME,
296: disable & SPD_INTR_RXDNV ? 'R' : '_',
297: disable & SPD_INTR_TXDNV ? 'T' : '_');
298:
299: if (disable & SPD_INTR_RXDNV)
300: smap_rxeof(arg);
301:
302: _reg_write_2(SPD_INTR_CLEAR_REG16, disable);
303: }
304:
305: if (cause & SPD_INTR_TXEND) {
306: _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND);
307: if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0)
308: cause |= SPD_INTR_RXEND;
309: smap_txeof(arg);
310: }
311:
312: if (cause & SPD_INTR_RXEND) {
313: _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND);
314: smap_rxeof(arg);
315: if (sc->tx_desc_cnt > 0 &&
316: sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8))
317: smap_txeof(arg);
318: }
319:
320: if (cause & SPD_INTR_EMAC3)
321: emac3_intr(arg);
322:
1.4 wiz 323: /* if transmission is pending, start here */
1.1 uch 324: ifp = &sc->ethercom.ec_if;
1.17.6.5! skrll 325: if_schedule_deferred_start(ifp);
1.1 uch 326: rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16);
327:
328: return (1);
329: }
330:
331: void
332: smap_rxeof(void *arg)
333: {
334: struct smap_softc *sc = arg;
335: struct smap_desc *d;
336: struct ifnet *ifp = &sc->ethercom.ec_if;
337: struct mbuf *m;
338: u_int16_t r16, stat;
339: u_int32_t *p;
340: int i, j, sz, rxsz, cnt;
341:
342: FUNC_ENTER();
343:
344: i = sc->rx_done_index;
345:
346: for (cnt = 0;; cnt++, i = (i + 1) & 0x3f) {
347: m = NULL;
348: d = &sc->rx_desc[i];
349: stat = d->stat;
350:
351: if ((stat & SMAP_RXDESC_EMPTY) != 0) {
352: break;
353: } else if (stat & 0x7fff) {
354: ifp->if_ierrors++;
355: goto next_packet;
356: }
357:
358: sz = d->sz;
359: rxsz = ROUND4(sz);
360:
361: KDASSERT(sz >= ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN);
362: KDASSERT(sz <= ETHER_MAX_LEN);
363:
364: /* load data from FIFO */
365: _reg_write_2(SMAP_RXFIFO_PTR_REG16, d->ptr & 0x3ffc);
366: p = sc->rx_buf;
367: for (j = 0; j < rxsz; j += sizeof(u_int32_t)) {
368: *p++ = _reg_read_4(SMAP_RXFIFO_DATA_REG);
369: }
370:
371: /* put to mbuf */
372: MGETHDR(m, M_DONTWAIT, MT_DATA);
373: if (m == NULL) {
374: printf("%s: unable to allocate Rx mbuf\n", DEVNAME);
375: ifp->if_ierrors++;
376: goto next_packet;
377: }
378:
379: if (sz > (MHLEN - 2)) {
380: MCLGET(m, M_DONTWAIT);
381: if ((m->m_flags & M_EXT) == 0) {
382: printf("%s: unable to allocate Rx cluster\n",
383: DEVNAME);
384: m_freem(m);
385: m = NULL;
386: ifp->if_ierrors++;
387: goto next_packet;
388: }
389: }
390:
391: m->m_data += 2; /* for alignment */
1.17.6.4 skrll 392: m_set_rcvif(m, ifp);
1.1 uch 393: m->m_pkthdr.len = m->m_len = sz;
1.9 christos 394: memcpy(mtod(m, void *), (void *)sc->rx_buf, sz);
1.1 uch 395:
396: next_packet:
397: _reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1);
398:
399: /* free descriptor */
400: d->sz = 0;
401: d->ptr = 0;
402: d->stat = SMAP_RXDESC_EMPTY;
403: _wbflush();
404:
1.17.6.5! skrll 405: if (m != NULL)
1.17.6.2 skrll 406: if_percpuq_enqueue(ifp->if_percpuq, m);
1.1 uch 407: }
408: sc->rx_done_index = i;
409:
410: r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
411: if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) {
412: r16 |= SPD_INTR_RXDNV;
413: _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
414: }
415:
416: FUNC_EXIT();
417: }
418:
419: void
420: smap_txeof(void *arg)
421: {
422: struct smap_softc *sc = arg;
423: struct ifnet *ifp = &sc->ethercom.ec_if;
424: struct smap_desc *d;
425: int i;
426:
427: FUNC_ENTER();
428:
429: /* clear the timeout timer. */
430: ifp->if_timer = 0;
431:
432: /* garbage collect */
433: for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) {
434: u_int16_t stat;
435:
436: d = &sc->tx_desc[i];
437: stat = d->stat;
438: if (stat & SMAP_TXDESC_READY) {
439: /* all descriptor processed. */
440: break;
441: } else if (stat & 0x7fff) {
442: if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL |
443: SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL))
444: ifp->if_collisions++;
445: else
446: ifp->if_oerrors++;
447: } else {
448: ifp->if_opackets++;
449: }
450:
451: if (sc->tx_desc_cnt == 0)
452: break;
453:
454: sc->tx_buf_freesize += ROUND4(d->sz);
455: sc->tx_desc_cnt--;
456:
457: d->sz = 0;
458: d->ptr = 0;
459: d->stat = 0;
460: _wbflush();
461: }
462: sc->tx_done_index = i;
463:
464: /* OK to start transmit */
465: ifp->if_flags &= ~IFF_OACTIVE;
466:
467: FUNC_EXIT();
468: }
469:
470: void
471: smap_start(struct ifnet *ifp)
472: {
473: struct smap_softc *sc = ifp->if_softc;
474: struct smap_desc *d;
475: struct mbuf *m0, *m;
476: u_int8_t *p, *q;
477: u_int32_t *r;
478: int i, sz, pktsz;
479: u_int16_t fifop;
480: u_int16_t r16;
481:
482: KDASSERT(ifp->if_flags & IFF_RUNNING);
483: FUNC_ENTER();
484:
485: while (1) {
486: IFQ_POLL(&ifp->if_snd, m0);
487: if (m0 == NULL)
488: goto end;
489:
490: pktsz = m0->m_pkthdr.len;
491: KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN);
492: sz = ROUND4(pktsz);
493:
494: if (sz > sc->tx_buf_freesize ||
495: sc->tx_desc_cnt >= SMAP_DESC_MAX ||
496: emac3_tx_done() != 0) {
497: ifp->if_flags |= IFF_OACTIVE;
498: goto end;
499: }
500:
501: IFQ_DEQUEUE(&ifp->if_snd, m0);
502: KDASSERT(m0 != NULL);
503: if (ifp->if_bpf)
1.17.6.3 skrll 504: bpf_mtap(ifp, m0);
1.1 uch 505:
506: p = (u_int8_t *)sc->tx_buf;
507: q = p + sz;
508: /* copy to temporary buffer area */
509: for (m = m0; m != 0; m = m->m_next) {
1.9 christos 510: memcpy(p, mtod(m, void *), m->m_len);
1.1 uch 511: p += m->m_len;
512: }
513: m_freem(m0);
514:
515: /* zero padding area */
516: for (; p < q; p++)
517: *p = 0;
518:
519: /* put to FIFO */
520: fifop = sc->tx_fifo_ptr;
521: KDASSERT((fifop & 3) == 0);
522: _reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop);
523: sc->tx_fifo_ptr = (fifop + sz) & 0xfff;
524:
525: r = sc->tx_buf;
526: for (i = 0; i < sz; i += sizeof(u_int32_t))
1.8 perry 527: *(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++;
1.1 uch 528: _wbflush();
529:
530: /* put FIFO to EMAC3 */
531: d = &sc->tx_desc[sc->tx_start_index];
532: KDASSERT((d->stat & SMAP_TXDESC_READY) == 0);
533:
534: d->sz = pktsz;
535: d->ptr = fifop + SMAP_TXBUF_BASE;
536: d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS |
537: SMAP_TXDESC_GENPAD;
538: _wbflush();
539:
540: sc->tx_buf_freesize -= sz;
541: sc->tx_desc_cnt++;
542: sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f;
543: _reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1);
544:
545: emac3_tx_kick();
546: r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
547: if ((r16 & SPD_INTR_TXDNV) == 0) {
548: r16 |= SPD_INTR_TXDNV;
549: _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
550: }
551: }
552: end:
553: /* set watchdog timer */
554: ifp->if_timer = 5;
555:
556: FUNC_EXIT();
557: }
558:
559: void
560: smap_watchdog(struct ifnet *ifp)
561: {
562: struct smap_softc *sc = ifp->if_softc;
563:
564: printf("%s: watchdog timeout\n",DEVNAME);
565: sc->ethercom.ec_if.if_oerrors++;
566:
567: smap_fifo_init(sc);
568: smap_desc_init(sc);
569: emac3_reset(&sc->emac3);
570: }
571:
572: int
573: smap_init(struct ifnet *ifp)
574: {
575: struct smap_softc *sc = ifp->if_softc;
576: u_int16_t r16;
1.11 dyoung 577: int rc;
1.1 uch 578:
579: smap_fifo_init(sc);
580: emac3_reset(&sc->emac3);
581: smap_desc_init(sc);
582:
583: _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
584: SPD_INTR_RXDNV);
585: emac3_intr_clear();
586:
587: r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
588: r16 |= SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND |
589: SPD_INTR_RXDNV;
590: _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
591: emac3_intr_enable();
592:
593: emac3_enable();
594:
595: /* Program the multicast filter, if necessary. */
596: emac3_setmulti(&sc->emac3, &sc->ethercom);
597:
598: /* Set current media. */
1.11 dyoung 599: if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO)
600: rc = 0;
601: else if (rc != 0)
602: return rc;
1.1 uch 603:
604: ifp->if_flags |= IFF_RUNNING;
605:
606: return (0);
607: }
608:
609: void
610: smap_stop(struct ifnet *ifp, int disable)
611: {
612: struct smap_softc *sc = ifp->if_softc;
613:
614: mii_down(&sc->emac3.mii);
615:
1.12 dyoung 616: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
617:
1.1 uch 618: if (disable)
619: emac3_disable();
620: }
621:
622: /*
623: * FIFO
624: */
625: int
626: smap_fifo_init(struct smap_softc *sc)
627: {
628:
629: if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0)
630: goto error;
631:
632: if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0)
633: goto error;
634:
635: return (0);
636: error:
637: printf("%s: FIFO reset not complete.\n", DEVNAME);
638:
639: return (1);
640: }
641:
642: int
643: smap_fifo_reset(bus_addr_t a)
644: {
645: int retry = 10000;
646:
647: _reg_write_1(a, SMAP_FIFO_RESET);
648:
649: while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0)
650: ;
651:
652: return (retry == 0);
653: }
654:
655: /*
656: * Buffer descriptor
657: */
658: void
659: smap_desc_init(struct smap_softc *sc)
660: {
661: struct smap_desc *d;
662: int i;
663:
664: sc->tx_desc = (void *)SMAP_TXDESC_BASE;
665: sc->rx_desc = (void *)SMAP_RXDESC_BASE;
666:
667: sc->tx_buf_freesize = SMAP_TXBUF_SIZE;
668: sc->tx_fifo_ptr = 0;
669: sc->tx_start_index = 0;
670: sc->tx_done_index = 0;
671: sc->rx_done_index = 0;
672:
673: /* intialize entry */
674: d = sc->tx_desc;
675: for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
676: d->stat = 0;
677: d->__reserved = 0;
678: d->sz = 0;
679: d->ptr = 0;
680: }
681:
682: d = sc->rx_desc;
683: for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
684: d->stat = SMAP_RXDESC_EMPTY;
685: d->__reserved = 0;
686: d->sz = 0;
687: d->ptr = 0;
688: }
689: _wbflush();
690: }
691:
692:
693: /*
694: * EEPROM
695: */
696: int
697: smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr)
698: {
699: u_int16_t checksum, *p = (u_int16_t *)eaddr;
700:
701: spd_eeprom_read(0, p, 3);
702: spd_eeprom_read(3, &checksum, 1);
703:
704: if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) {
705: printf("%s: Ethernet address checksum error.(%s)\n",
706: DEVNAME, ether_sprintf(eaddr));
707: return (1);
708: }
709:
710: return (0);
711: }
712:
713: #ifdef SMAP_DEBUG
714: #include <mips/locore.h>
715: void
716: __smap_lock_check(const char *func, int enter)
717: {
718: static int cnt;
719: static const char *last;
720:
721: cnt += enter ? 1 : -1;
722:
723: if (cnt < 0 || cnt > 1)
724: panic("%s cnt=%d last=%s", func, cnt, last);
725:
726: last = func;
727: }
728:
729: void
730: __smap_status(int msg)
731: {
732: static int cnt;
733: __gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg,
734: _reg_read_1(SMAP_TXFIFO_FRAME_REG8),
735: _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt,
736: __sc->tx_buf_freesize, cnt++);
737: }
738: #endif /* SMAP_DEBUG */
CVSweb <webmaster@jp.NetBSD.org>