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