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