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