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