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