Annotation of sys/arch/vax/bi/if_ni.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ni.c,v 1.10 2007/05/11 10:06:55 pedro Exp $ */
2: /* $NetBSD: if_ni.c,v 1.15 2002/05/22 16:03:14 wiz Exp $ */
3: /*
4: * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed at Ludd, University of
17: * Lule}, Sweden and its contributors.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * Driver for DEBNA/DEBNT/DEBNK ethernet cards.
35: * Things that is still to do:
36: * Collect statistics.
37: */
38:
39: #include "bpfilter.h"
40:
41: #include <sys/param.h>
42: #include <sys/mbuf.h>
43: #include <sys/socket.h>
44: #include <sys/device.h>
45: #include <sys/systm.h>
46: #include <sys/sockio.h>
47: #include <sys/sched.h>
48:
49: #include <net/if.h>
50: #include <net/if_ether.h>
51: #include <net/if_dl.h>
52:
53: #include <netinet/in.h>
54: #include <netinet/if_inarp.h>
55:
56: #if NBPFILTER > 0
57: #include <net/bpf.h>
58: #include <net/bpfdesc.h>
59: #endif
60:
61: #include <machine/bus.h>
62: #ifdef __vax__
63: #include <machine/mtpr.h>
64: #include <machine/pte.h>
65: #endif
66:
67: #include <dev/bi/bireg.h>
68: #include <dev/bi/bivar.h>
69:
70: /*
71: * Tunable buffer parameters. Good idea to have them as power of 8; then
72: * they will fit into a logical VAX page.
73: */
74: #define NMSGBUF 8 /* Message queue entries */
75: #define NTXBUF 16 /* Transmit queue entries */
76: #define NTXFRAGS 8 /* Number of transmit buffer fragments */
77: #define NRXBUF 24 /* Receive queue entries */
78: #define NBDESCS (NTXBUF * NTXFRAGS + NRXBUF)
79: #define NQUEUES 3 /* RX + TX + MSG */
80: #define PKTHDR 18 /* Length of (control) packet header */
81: #define RXADD 18 /* Additional length of receive datagram */
82: #define TXADD (10+NTXFRAGS*8) /* "" transmit "" */
83: #define MSGADD 134 /* "" message "" */
84:
85: #include <dev/bi/if_nireg.h> /* XXX include earlier */
86:
87: /*
88: * Macros for (most cases of) insqti/remqhi.
89: * Retry NRETRIES times to do the operation, if it still fails assume
90: * a lost lock and panic.
91: */
92: #define NRETRIES 100
93: #define INSQTI(e, h) ({ \
94: int ret, i; \
95: for (i = 0; i < NRETRIES; i++) { \
96: if ((ret = insqti(e, h)) != ILCK_FAILED) \
97: break; \
98: } \
99: if (i == NRETRIES) \
100: panic("ni: insqti failed at %d", __LINE__); \
101: ret; \
102: })
103: #define REMQHI(h) ({ \
104: int i;void *ret; \
105: for (i = 0; i < NRETRIES; i++) { \
106: if ((ret = remqhi(h)) != (void *)ILCK_FAILED) \
107: break; \
108: } \
109: if (i == NRETRIES) \
110: panic("ni: remqhi failed at %d", __LINE__); \
111: ret; \
112: })
113:
114:
115: #define nipqb (&sc->sc_gvppqb->nc_pqb)
116: #define gvp sc->sc_gvppqb
117: #define fqb sc->sc_fqb
118: #define bbd sc->sc_bbd
119:
120: struct ni_softc {
121: struct device sc_dev; /* Configuration common part */
122: struct ethercom sc_ec; /* Ethernet common part */
123: #define sc_if sc_ec.ec_if /* network-visible interface */
124: bus_space_tag_t sc_iot;
125: bus_addr_t sc_ioh;
126: bus_dma_tag_t sc_dmat;
127: struct ni_gvppqb *sc_gvppqb; /* Port queue block */
128: struct ni_gvppqb *sc_pgvppqb; /* Phys address of PQB */
129: struct ni_fqb *sc_fqb; /* Free Queue block */
130: struct ni_bbd *sc_bbd; /* Buffer descriptors */
131: u_int8_t sc_enaddr[ETHER_ADDR_LEN];
132: };
133:
134: static int nimatch(struct device *, struct cfdata *, void *);
135: static void niattach(struct device *, struct device *, void *);
136: static void niinit(struct ni_softc *);
137: static void nistart(struct ifnet *);
138: static void niintr(void *);
139: static int niioctl(struct ifnet *, u_long, caddr_t);
140: static int ni_add_rxbuf(struct ni_softc *, struct ni_dg *, int);
141: static void ni_setup(struct ni_softc *);
142: static void nitimeout(struct ifnet *);
143: static void ni_shutdown(void *);
144: static void ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p);
145: static int failtest(struct ni_softc *, int, int, int, char *);
146:
147: volatile int endwait, retry; /* Used during autoconfig */
148:
149: struct cfattach ni_ca = {
150: sizeof(struct ni_softc), nimatch, niattach
151: };
152:
153: #define NI_WREG(csr, val) \
154: bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
155: #define NI_RREG(csr) \
156: bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
157:
158: #define WAITREG(csr,val) while (NI_RREG(csr) & val);
159: /*
160: * Check for present device.
161: */
162: int
163: nimatch(parent, cf, aux)
164: struct device *parent;
165: struct cfdata *cf;
166: void *aux;
167: {
168: struct bi_attach_args *ba = aux;
169: u_short type;
170:
171: type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE);
172: if (type != BIDT_DEBNA && type != BIDT_DEBNT && type != BIDT_DEBNK)
173: return 0;
174:
175: if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT &&
176: cf->cf_loc[BICF_NODE] != ba->ba_nodenr)
177: return 0;
178:
179: return 1;
180: }
181:
182: /*
183: * Allocate a bunch of descriptor-safe memory.
184: * We need to get the structures from the beginning of its own pages.
185: */
186: static void
187: ni_getpgs(struct ni_softc *sc, int size, caddr_t *v, paddr_t *p)
188: {
189: bus_dma_segment_t seg;
190: int nsegs, error;
191:
192: if ((error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &seg, 1,
193: &nsegs, BUS_DMA_NOWAIT)) != 0)
194: panic(" unable to allocate memory: error %d", error);
195:
196: if ((error = bus_dmamem_map(sc->sc_dmat, &seg, nsegs, size, v,
197: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0)
198: panic(" unable to map memory: error %d", error);
199:
200: if (p)
201: *p = seg.ds_addr;
202: memset(*v, 0, size);
203: }
204:
205: static int
206: failtest(struct ni_softc *sc, int reg, int mask, int test, char *str)
207: {
208: int i = 100;
209:
210: do {
211: DELAY(100000);
212: } while (((NI_RREG(reg) & mask) != test) && --i);
213:
214: if (i == 0) {
215: printf("%s: %s\n", sc->sc_dev.dv_xname, str);
216: return 1;
217: }
218: return 0;
219: }
220:
221:
222: /*
223: * Interface exists: make available by filling in network interface
224: * record. System will initialize the interface when it is ready
225: * to accept packets.
226: */
227: void
228: niattach(parent, self, aux)
229: struct device *parent, *self;
230: void *aux;
231: {
232: struct bi_attach_args *ba = aux;
233: struct ni_softc *sc = (struct ni_softc *)self;
234: struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
235: struct ni_msg *msg;
236: struct ni_ptdb *ptdb;
237: caddr_t va;
238: int i, j, s, res;
239: u_short type;
240:
241: type = bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE);
242: printf(": DEBN%c\n", type == BIDT_DEBNA ? 'A' : type == BIDT_DEBNT ?
243: 'T' : 'K');
244: sc->sc_iot = ba->ba_iot;
245: sc->sc_ioh = ba->ba_ioh;
246: sc->sc_dmat = ba->ba_dmat;
247:
248: bi_intr_establish(ba->ba_icookie, ba->ba_ivec, niintr, sc);
249:
250: ni_getpgs(sc, sizeof(struct ni_gvppqb), (caddr_t *)&sc->sc_gvppqb,
251: (paddr_t *)&sc->sc_pgvppqb);
252: ni_getpgs(sc, sizeof(struct ni_fqb), (caddr_t *)&sc->sc_fqb, 0);
253: ni_getpgs(sc, NBDESCS * sizeof(struct ni_bbd),
254: (caddr_t *)&sc->sc_bbd, 0);
255: /*
256: * Zero the newly allocated memory.
257: */
258:
259: nipqb->np_veclvl = (ba->ba_ivec << 2) + 2;
260: nipqb->np_node = ba->ba_intcpu;
261: nipqb->np_vpqb = (u_int32_t)gvp;
262: #ifdef __vax__
263: nipqb->np_spt = nipqb->np_gpt = mfpr(PR_SBR);
264: nipqb->np_sptlen = nipqb->np_gptlen = mfpr(PR_SLR);
265: #else
266: #error Must fix support for non-vax.
267: #endif
268: nipqb->np_bvplvl = 1;
269: nipqb->np_vfqb = (u_int32_t)fqb;
270: nipqb->np_vbdt = (u_int32_t)bbd;
271: nipqb->np_nbdr = NBDESCS;
272:
273: /* Free queue block */
274: nipqb->np_freeq = NQUEUES;
275: fqb->nf_mlen = PKTHDR+MSGADD;
276: fqb->nf_dlen = PKTHDR+TXADD;
277: fqb->nf_rlen = PKTHDR+RXADD;
278:
279: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
280: ifp->if_softc = sc;
281: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
282: ifp->if_start = nistart;
283: ifp->if_ioctl = niioctl;
284: ifp->if_watchdog = nitimeout;
285: IFQ_SET_READY(&ifp->if_snd);
286:
287: /*
288: * Start init sequence.
289: */
290:
291: /* Reset the node */
292: NI_WREG(BIREG_VAXBICSR, NI_RREG(BIREG_VAXBICSR) | BICSR_NRST);
293: DELAY(500000);
294: i = 20;
295: while ((NI_RREG(BIREG_VAXBICSR) & BICSR_BROKE) && --i)
296: DELAY(500000);
297: if (i == 0) {
298: printf("%s: BROKE bit set after reset\n", sc->sc_dev.dv_xname);
299: return;
300: }
301:
302: /* Check state */
303: if (failtest(sc, NI_PSR, PSR_STATE, PSR_UNDEF, "not undefined state"))
304: return;
305:
306: /* Clear owner bits */
307: NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
308: NI_WREG(NI_PCR, NI_RREG(NI_PCR) & ~PCR_OWN);
309:
310: /* kick off init */
311: NI_WREG(NI_PCR, (u_int32_t)sc->sc_pgvppqb | PCR_INIT | PCR_OWN);
312: while (NI_RREG(NI_PCR) & PCR_OWN)
313: DELAY(100000);
314:
315: /* Check state */
316: if (failtest(sc, NI_PSR, PSR_INITED, PSR_INITED, "failed initialize"))
317: return;
318:
319: NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
320:
321: WAITREG(NI_PCR, PCR_OWN);
322: NI_WREG(NI_PCR, PCR_OWN|PCR_ENABLE);
323: WAITREG(NI_PCR, PCR_OWN);
324: WAITREG(NI_PSR, PSR_OWN);
325:
326: /* Check state */
327: if (failtest(sc, NI_PSR, PSR_STATE, PSR_ENABLED, "failed enable"))
328: return;
329:
330: NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~PSR_OWN);
331:
332: /*
333: * The message queue packets must be located on the beginning
334: * of a page. A VAX page is 512 bytes, but it clusters 8 pages.
335: * This knowledge is used here when allocating pages.
336: * !!! How should this be done on MIPS and Alpha??? !!!
337: */
338: #if NBPG < 4096
339: #error pagesize too small
340: #endif
341: s = splvm();
342: /* Set up message free queue */
343: ni_getpgs(sc, NMSGBUF * 512, &va, 0);
344: for (i = 0; i < NMSGBUF; i++) {
345: struct ni_msg *msg;
346:
347: msg = (void *)(va + i * 512);
348:
349: res = INSQTI(msg, &fqb->nf_mforw);
350: }
351: WAITREG(NI_PCR, PCR_OWN);
352: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
353: WAITREG(NI_PCR, PCR_OWN);
354:
355: /* Set up xmit queue */
356: ni_getpgs(sc, NTXBUF * 512, &va, 0);
357: for (i = 0; i < NTXBUF; i++) {
358: struct ni_dg *data;
359:
360: data = (void *)(va + i * 512);
361: data->nd_status = 0;
362: data->nd_len = TXADD;
363: data->nd_ptdbidx = 1;
364: data->nd_opcode = BVP_DGRAM;
365: for (j = 0; j < NTXFRAGS; j++) {
366: data->bufs[j]._offset = 0;
367: data->bufs[j]._key = 1;
368: bbd[i * NTXFRAGS + j].nb_key = 1;
369: bbd[i * NTXFRAGS + j].nb_status = 0;
370: data->bufs[j]._index = i * NTXFRAGS + j;
371: }
372: res = INSQTI(data, &fqb->nf_dforw);
373: }
374: WAITREG(NI_PCR, PCR_OWN);
375: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_DFREEQ|PCR_OWN);
376: WAITREG(NI_PCR, PCR_OWN);
377:
378: /* recv buffers */
379: ni_getpgs(sc, NRXBUF * 512, &va, 0);
380: for (i = 0; i < NRXBUF; i++) {
381: struct ni_dg *data;
382: int idx;
383:
384: data = (void *)(va + i * 512);
385: data->nd_len = RXADD;
386: data->nd_opcode = BVP_DGRAMRX;
387: data->nd_ptdbidx = 2;
388: data->bufs[0]._key = 1;
389:
390: idx = NTXBUF * NTXFRAGS + i;
391: if (ni_add_rxbuf(sc, data, idx))
392: panic("niattach: ni_add_rxbuf: out of mbufs");
393:
394: res = INSQTI(data, &fqb->nf_rforw);
395: }
396: WAITREG(NI_PCR, PCR_OWN);
397: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
398: WAITREG(NI_PCR, PCR_OWN);
399:
400: splx(s);
401:
402: /* Set initial parameters */
403: msg = REMQHI(&fqb->nf_mforw);
404:
405: msg->nm_opcode = BVP_MSG;
406: msg->nm_status = 0;
407: msg->nm_len = sizeof(struct ni_param) + 6;
408: msg->nm_opcode2 = NI_WPARAM;
409: ((struct ni_param *)&msg->nm_text[0])->np_flags = NP_PAD;
410:
411: endwait = retry = 0;
412: res = INSQTI(msg, &gvp->nc_forw0);
413:
414: retry: WAITREG(NI_PCR, PCR_OWN);
415: NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
416: WAITREG(NI_PCR, PCR_OWN);
417: i = 1000;
418: while (endwait == 0 && --i)
419: DELAY(10000);
420:
421: if (endwait == 0) {
422: if (++retry < 3)
423: goto retry;
424: printf("%s: no response to set params\n", sc->sc_dev.dv_xname);
425: return;
426: }
427:
428: /* Clear counters */
429: msg = REMQHI(&fqb->nf_mforw);
430: msg->nm_opcode = BVP_MSG;
431: msg->nm_status = 0;
432: msg->nm_len = sizeof(struct ni_param) + 6;
433: msg->nm_opcode2 = NI_RCCNTR;
434:
435: res = INSQTI(msg, &gvp->nc_forw0);
436:
437: WAITREG(NI_PCR, PCR_OWN);
438: NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
439: WAITREG(NI_PCR, PCR_OWN);
440:
441: /* Enable transmit logic */
442: msg = REMQHI(&fqb->nf_mforw);
443:
444: msg->nm_opcode = BVP_MSG;
445: msg->nm_status = 0;
446: msg->nm_len = 18;
447: msg->nm_opcode2 = NI_STPTDB;
448: ptdb = (struct ni_ptdb *)&msg->nm_text[0];
449: memset(ptdb, 0, sizeof(struct ni_ptdb));
450: ptdb->np_index = 1;
451: ptdb->np_fque = 1;
452:
453: res = INSQTI(msg, &gvp->nc_forw0);
454:
455: WAITREG(NI_PCR, PCR_OWN);
456: NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
457: WAITREG(NI_PCR, PCR_OWN);
458:
459: /* Wait for everything to finish */
460: WAITREG(NI_PSR, PSR_OWN);
461:
462: printf("%s: address %s\n", sc->sc_dev.dv_xname,
463: ether_sprintf(sc->sc_enaddr));
464:
465: /*
466: * Attach the interface.
467: */
468: if_attach(ifp);
469: ether_ifattach(ifp, sc->sc_enaddr);
470: if (shutdownhook_establish(ni_shutdown, sc) == 0)
471: printf("%s: WARNING: unable to establish shutdown hook\n",
472: sc->sc_dev.dv_xname);
473: }
474:
475: /*
476: * Initialization of interface.
477: */
478: void
479: niinit(sc)
480: struct ni_softc *sc;
481: {
482: struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
483:
484: /*
485: * Set flags (so ni_setup() do the right thing).
486: */
487: ifp->if_flags |= IFF_RUNNING;
488: ifp->if_flags &= ~IFF_OACTIVE;
489:
490: /*
491: * Send setup messages so that the rx/tx locic starts.
492: */
493: ni_setup(sc);
494:
495: }
496:
497: /*
498: * Start output on interface.
499: */
500: void
501: nistart(ifp)
502: struct ifnet *ifp;
503: {
504: struct ni_softc *sc = ifp->if_softc;
505: struct ni_dg *data;
506: struct ni_bbd *bdp;
507: struct mbuf *m, *m0;
508: int i, cnt, res, mlen;
509:
510: if (ifp->if_flags & IFF_OACTIVE)
511: return;
512: #ifdef DEBUG
513: if (ifp->if_flags & IFF_DEBUG)
514: printf("%s: nistart\n", sc->sc_dev.dv_xname);
515: #endif
516:
517: while (fqb->nf_dforw) {
518: IFQ_POLL(&ifp->if_snd, m);
519: if (m == 0)
520: break;
521:
522: data = REMQHI(&fqb->nf_dforw);
523: if ((int)data == Q_EMPTY) {
524: ifp->if_flags |= IFF_OACTIVE;
525: break;
526: }
527:
528: IFQ_DEQUEUE(&ifp->if_snd, m);
529:
530: /*
531: * Count number of mbufs in chain.
532: * Always do DMA directly from mbufs, therefore the transmit
533: * ring is really big.
534: */
535: for (m0 = m, cnt = 0; m0; m0 = m0->m_next)
536: if (m0->m_len)
537: cnt++;
538: if (cnt > NTXFRAGS)
539: panic("nistart"); /* XXX */
540:
541: #if NBPFILTER > 0
542: if (ifp->if_bpf)
543: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
544: #endif
545: bdp = &bbd[(data->bufs[0]._index & 0x7fff)];
546: for (m0 = m, i = 0, mlen = 0; m0; m0 = m0->m_next) {
547: if (m0->m_len == 0)
548: continue;
549: bdp->nb_status = (mtod(m0, u_int32_t) & NIBD_OFFSET) |
550: NIBD_VALID;
551: bdp->nb_pte = (u_int32_t)kvtopte(mtod(m0, void *));
552: bdp->nb_len = m0->m_len;
553: data->bufs[i]._offset = 0;
554: data->bufs[i]._len = bdp->nb_len;
555: data->bufs[i]._index |= NIDG_CHAIN;
556: mlen += bdp->nb_len;
557: bdp++;
558: i++;
559: }
560: data->nd_opcode = BVP_DGRAM;
561: data->nd_pad3 = 1;
562: data->nd_ptdbidx = 1;
563: data->nd_len = 10 + i * 8;
564: data->bufs[i - 1]._index &= ~NIDG_CHAIN;
565: if (mlen < 64)
566: data->bufs[i - 1]._len = bdp[-1].nb_len += (64 - mlen);
567: data->nd_cmdref = (u_int32_t)m;
568: #ifdef DEBUG
569: if (ifp->if_flags & IFF_DEBUG)
570: printf("%s: sending %d bytes (%d segments)\n",
571: sc->sc_dev.dv_xname, mlen, i);
572: #endif
573:
574: res = INSQTI(data, &gvp->nc_forw0);
575: if (res == Q_EMPTY) {
576: WAITREG(NI_PCR, PCR_OWN);
577: NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
578: }
579: }
580: }
581:
582: void
583: niintr(void *arg)
584: {
585: struct ni_softc *sc = arg;
586: struct ni_dg *data;
587: struct ni_msg *msg;
588: struct ifnet *ifp = &sc->sc_if;
589: struct ni_bbd *bd;
590: struct mbuf *m;
591: int idx, res;
592:
593: if ((NI_RREG(NI_PSR) & PSR_STATE) != PSR_ENABLED)
594: return;
595:
596: if ((NI_RREG(NI_PSR) & PSR_ERR))
597: printf("%s: PSR %x\n", sc->sc_dev.dv_xname, NI_RREG(NI_PSR));
598:
599: KERNEL_LOCK();
600: /* Got any response packets? */
601: while ((NI_RREG(NI_PSR) & PSR_RSQ) && (data = REMQHI(&gvp->nc_forwr))) {
602:
603: switch (data->nd_opcode) {
604: case BVP_DGRAMRX: /* Receive datagram */
605: idx = data->bufs[0]._index;
606: bd = &bbd[idx];
607: m = (void *)data->nd_cmdref;
608: m->m_pkthdr.len = m->m_len =
609: data->bufs[0]._len - ETHER_CRC_LEN;
610: m->m_pkthdr.rcvif = ifp;
611: if (ni_add_rxbuf(sc, data, idx)) {
612: bd->nb_len = (m->m_ext.ext_size - 2);
613: bd->nb_pte =
614: (long)kvtopte(m->m_ext.ext_buf);
615: bd->nb_status = 2 | NIBD_VALID;
616: bd->nb_key = 1;
617: }
618: data->nd_len = RXADD;
619: data->nd_status = 0;
620: res = INSQTI(data, &fqb->nf_rforw);
621: if (res == Q_EMPTY) {
622: WAITREG(NI_PCR, PCR_OWN);
623: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_RFREEQ|PCR_OWN);
624: }
625: if (m == (void *)data->nd_cmdref)
626: break; /* Out of mbufs */
627:
628: #if NBPFILTER > 0
629: if (ifp->if_bpf)
630: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
631: #endif
632: (*ifp->if_input)(ifp, m);
633: break;
634:
635: case BVP_DGRAM:
636: m = (struct mbuf *)data->nd_cmdref;
637: ifp->if_flags &= ~IFF_OACTIVE;
638: m_freem(m);
639: res = INSQTI(data, &fqb->nf_dforw);
640: if (res == Q_EMPTY) {
641: WAITREG(NI_PCR, PCR_OWN);
642: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_DFREEQ|PCR_OWN);
643: }
644: break;
645:
646: case BVP_MSGRX:
647: msg = (struct ni_msg *)data;
648: switch (msg->nm_opcode2) {
649: case NI_WPARAM:
650: memcpy(sc->sc_enaddr, ((struct ni_param *)&msg->nm_text[0])->np_dpa, ETHER_ADDR_LEN);
651: endwait = 1;
652: break;
653:
654: case NI_RCCNTR:
655: case NI_CLPTDB:
656: case NI_STPTDB:
657: break;
658:
659: default:
660: printf("Unkn resp %d\n",
661: msg->nm_opcode2);
662: break;
663: }
664: res = INSQTI(data, &fqb->nf_mforw);
665: if (res == Q_EMPTY) {
666: WAITREG(NI_PCR, PCR_OWN);
667: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
668: }
669: break;
670:
671: default:
672: printf("Unknown opcode %d\n", data->nd_opcode);
673: res = INSQTI(data, &fqb->nf_mforw);
674: if (res == Q_EMPTY) {
675: WAITREG(NI_PCR, PCR_OWN);
676: NI_WREG(NI_PCR, PCR_FREEQNE|PCR_MFREEQ|PCR_OWN);
677: }
678: }
679: }
680:
681: /* Try to kick on the start routine again */
682: nistart(ifp);
683:
684: NI_WREG(NI_PSR, NI_RREG(NI_PSR) & ~(PSR_OWN|PSR_RSQ));
685: KERNEL_UNLOCK();
686: }
687:
688: /*
689: * Process an ioctl request.
690: */
691: int
692: niioctl(ifp, cmd, data)
693: register struct ifnet *ifp;
694: u_long cmd;
695: caddr_t data;
696: {
697: struct ni_softc *sc = ifp->if_softc;
698: struct ifreq *ifr = (struct ifreq *)data;
699: struct ifaddr *ifa = (struct ifaddr *)data;
700: int s = splnet(), error = 0;
701:
702: switch (cmd) {
703:
704: case SIOCSIFADDR:
705: ifp->if_flags |= IFF_UP;
706: switch(ifa->ifa_addr->sa_family) {
707: #ifdef INET
708: case AF_INET:
709: niinit(sc);
710: arp_ifinit(ifp, ifa);
711: break;
712: #endif
713: }
714: break;
715:
716: case SIOCSIFFLAGS:
717: if ((ifp->if_flags & IFF_UP) == 0 &&
718: (ifp->if_flags & IFF_RUNNING) != 0) {
719: /*
720: * If interface is marked down and it is running,
721: * stop it.
722: */
723: ifp->if_flags &= ~IFF_RUNNING;
724: ni_setup(sc);
725: } else if ((ifp->if_flags & IFF_UP) != 0 &&
726: (ifp->if_flags & IFF_RUNNING) == 0) {
727: /*
728: * If interface it marked up and it is stopped, then
729: * start it.
730: */
731: niinit(sc);
732: } else if ((ifp->if_flags & IFF_UP) != 0) {
733: /*
734: * Send a new setup packet to match any new changes.
735: * (Like IFF_PROMISC etc)
736: */
737: ni_setup(sc);
738: }
739: break;
740:
741: case SIOCADDMULTI:
742: case SIOCDELMULTI:
743: /*
744: * Update our multicast list.
745: */
746: error = (cmd == SIOCADDMULTI) ?
747: ether_addmulti(ifr, &sc->sc_ec):
748: ether_delmulti(ifr, &sc->sc_ec);
749:
750: if (error == ENETRESET) {
751: /*
752: * Multicast list has changed; set the hardware filter
753: * accordingly.
754: */
755: if (ifp->if_flags & IFF_RUNNING)
756: ni_setup(sc);
757: error = 0;
758: }
759: break;
760:
761: default:
762: error = EINVAL;
763:
764: }
765: splx(s);
766: return (error);
767: }
768:
769: /*
770: * Add a receive buffer to the indicated descriptor.
771: */
772: int
773: ni_add_rxbuf(struct ni_softc *sc, struct ni_dg *data, int idx)
774: {
775: struct ni_bbd *bd = &bbd[idx];
776: struct mbuf *m;
777:
778: MGETHDR(m, M_DONTWAIT, MT_DATA);
779: if (m == NULL)
780: return (ENOBUFS);
781:
782: MCLGET(m, M_DONTWAIT);
783: if ((m->m_flags & M_EXT) == 0) {
784: m_freem(m);
785: return (ENOBUFS);
786: }
787:
788: m->m_data += 2;
789: bd->nb_len = (m->m_ext.ext_size - 2);
790: bd->nb_pte = (long)kvtopte(m->m_ext.ext_buf);
791: bd->nb_status = 2 | NIBD_VALID;
792: bd->nb_key = 1;
793:
794: data->bufs[0]._offset = 0;
795: data->bufs[0]._len = bd->nb_len;
796: data->bufs[0]._index = idx;
797: data->nd_cmdref = (long)m;
798:
799: return (0);
800: }
801:
802: /*
803: * Create setup packet and put in queue for sending.
804: */
805: void
806: ni_setup(struct ni_softc *sc)
807: {
808: struct ifnet *ifp = &sc->sc_if;
809: struct ni_msg *msg;
810: struct ni_ptdb *ptdb;
811: struct ether_multi *enm;
812: struct ether_multistep step;
813: int i, res;
814:
815: msg = REMQHI(&fqb->nf_mforw);
816: if ((int)msg == Q_EMPTY)
817: return; /* What to do? */
818:
819: ptdb = (struct ni_ptdb *)&msg->nm_text[0];
820: memset(ptdb, 0, sizeof(struct ni_ptdb));
821:
822: msg->nm_opcode = BVP_MSG;
823: msg->nm_len = 18;
824: ptdb->np_index = 2; /* definition type index */
825: ptdb->np_fque = 2; /* Free queue */
826: if (ifp->if_flags & IFF_RUNNING) {
827: msg->nm_opcode2 = NI_STPTDB;
828: ptdb->np_type = ETHERTYPE_IP;
829: ptdb->np_flags = PTDB_UNKN|PTDB_BDC;
830: if (ifp->if_flags & IFF_PROMISC)
831: ptdb->np_flags |= PTDB_PROMISC;
832: memset(ptdb->np_mcast[0], 0xff, ETHER_ADDR_LEN); /* Broadcast */
833: ptdb->np_adrlen = 1;
834: msg->nm_len += 8;
835: ifp->if_flags &= ~IFF_ALLMULTI;
836: if ((ifp->if_flags & IFF_PROMISC) == 0) {
837: ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
838: i = 1;
839: while (enm != NULL) {
840: if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
841: ifp->if_flags |= IFF_ALLMULTI;
842: ptdb->np_flags |= PTDB_AMC;
843: break;
844: }
845: msg->nm_len += 8;
846: ptdb->np_adrlen++;
847: memcpy(ptdb->np_mcast[i++], enm->enm_addrlo,
848: ETHER_ADDR_LEN);
849: ETHER_NEXT_MULTI(step, enm);
850: }
851: }
852: } else
853: msg->nm_opcode2 = NI_CLPTDB;
854:
855: res = INSQTI(msg, &gvp->nc_forw0);
856: if (res == Q_EMPTY) {
857: WAITREG(NI_PCR, PCR_OWN);
858: NI_WREG(NI_PCR, PCR_CMDQNE|PCR_CMDQ0|PCR_OWN);
859: }
860: }
861:
862: /*
863: * Check for dead transmit logic. Not uncommon.
864: */
865: void
866: nitimeout(ifp)
867: struct ifnet *ifp;
868: {
869: #if 0
870: struct ni_softc *sc = ifp->if_softc;
871:
872: if (sc->sc_inq == 0)
873: return;
874:
875: printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
876: /*
877: * Do a reset of interface, to get it going again.
878: * Will it work by just restart the transmit logic?
879: */
880: niinit(sc);
881: #endif
882: }
883:
884: /*
885: * Shutdown hook. Make sure the interface is stopped at reboot.
886: */
887: void
888: ni_shutdown(arg)
889: void *arg;
890: {
891: struct ni_softc *sc = arg;
892:
893: WAITREG(NI_PCR, PCR_OWN);
894: NI_WREG(NI_PCR, PCR_OWN|PCR_SHUTDOWN);
895: WAITREG(NI_PCR, PCR_OWN);
896: WAITREG(NI_PSR, PSR_OWN);
897:
898: }
899:
CVSweb