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