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