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