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