1 /* 2 * Copyright (c) 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Micom-Interlan Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)if_ix.c 7.8 (Berkeley) 12/16/90 11 */ 12 13 #include "np.h" 14 #if NNP > 0 15 16 /* 17 * Interlan NP100 Ethernet Communications Controller interface 18 */ 19 #include "../include/pte.h" 20 21 #include "sys/param.h" 22 #include "sys/systm.h" 23 #include "sys/mbuf.h" 24 #include "sys/buf.h" 25 #include "sys/protosw.h" 26 #include "sys/socket.h" 27 #include "sys/vmmac.h" 28 #include "sys/ioctl.h" 29 #include "sys/errno.h" 30 31 #include "net/if.h" 32 #include "net/netisr.h" 33 #include "net/route.h" 34 35 #ifdef INET 36 #include "netinet/in.h" 37 #include "netinet/in_systm.h" 38 #include "netinet/in_var.h" 39 #include "netinet/ip.h" 40 #include "netinet/if_ether.h" 41 #endif 42 43 #ifdef NS 44 #include "netns/ns.h" 45 #include "netns/ns_if.h" 46 #endif 47 48 #include "../include/cpu.h" 49 #include "../include/mtpr.h" 50 #include "../if/if_uba.h" 51 #include "../uba/ubareg.h" 52 #include "../uba/ubavar.h" 53 #include "../uba/npreg.h" 54 #include "../if/if_ix.h" 55 56 int ixattach(), ixrint(), ixcint(); 57 #define ILUNIT(x) minor(x) 58 int ixinit(), ixioctl(), ixreset(), ixwatch(), ixstart(); 59 int (*IxAttach)() = ixattach; 60 int (*IxReset)() = ixreset; 61 62 /* 63 * Ethernet software status per interface. 64 * 65 * Each interface is referenced by a network interface structure, 66 * ix_if, which the routing code uses to locate the interface. 67 * This structure contains the output queue for the interface, its address, ... 68 * We also have, for each interface, a UBA interface structure, which 69 * contains information about the UNIBUS resources held by the interface: 70 * map registers, buffered data paths, etc. Information is cached in this 71 * structure for use by the if_uba.c routines in running the interface 72 * efficiently. 73 */ 74 struct ix_softc { 75 struct arpcom ix_ac; /* Ethernet common part */ 76 #define ix_if ix_ac.ac_if /* network-visible interface */ 77 #define ix_addr ix_ac.ac_enaddr /* hardware Ethernet address */ 78 int ix_flags; 79 #define IXF_OACTIVE 0x1 /* output is active */ 80 #define IXF_RCVPENDING 0x2 /* start rcv in ilcint */ 81 #define IXF_GOTUBA 0x4 /* unibus resources mapped */ 82 #define IXF_RUNNING 0x8 /* board is running */ 83 #define IXF_SETADDR 0x10 /* physical address is changed */ 84 #define IXF_STATPENDING 0x20 /* stat cmd pending */ 85 #define IXF_GOTCQE 0x40 /* np resources available */ 86 #define IXF_OWATCH 0x80 /* is output hung? */ 87 #define IXF_RWATCH 0x100 /* is input hung? */ 88 struct ifuba ix_ifuba; /* unibus resources */ 89 u_short ix_aid; /* Access Id returned by open DDL */ 90 u_short ix_badcqe; 91 struct npmaster *ix_mp; /* Board physio request header */ 92 struct npreq *ix_rrp; /* Cached npreq for recv */ 93 struct npreq *ix_wrp; /* Cached npreq for xmit */ 94 short ix_scaninterval; /* interval of stat collection */ 95 #define IXWATCHINTERVAL 60 /* once every 60 seconds */ 96 union ix_stats ix_stats; /* holds on-board statistics */ 97 int ix_ubaddr; /* mapping registers of ix_stats */ 98 } ix_softc[NNP]; 99 extern struct uba_device *npdinfo[]; 100 101 /* 102 * Interface exists: make available by filling in network interface 103 * record. System will initialize the interface when it is ready 104 * to accept packets. We can't even get the ethernet address 105 * or other interesting data until the board has been downloaded. 106 * running ifconfig will attempt to start unit. 107 */ 108 ixattach(ui) 109 struct uba_device *ui; 110 { 111 register struct ix_softc *ix = &ix_softc[ui->ui_unit]; 112 register struct ifnet *ifp = &ix->ix_if; 113 extern struct npmaster npmasters[]; 114 115 ifp->if_unit = ui->ui_unit; 116 ifp->if_name = "ix"; 117 ifp->if_mtu = ETHERMTU; 118 ifp->if_flags = IFF_BROADCAST; 119 120 ifp->if_init = ixinit; 121 ifp->if_output = ether_output; 122 ifp->if_start = ixstart; 123 ifp->if_ioctl = ixioctl; 124 ifp->if_reset = ixreset; 125 126 ix->ix_mp = npmasters + ui->ui_unit; 127 ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; 128 129 if_attach(ifp); 130 } 131 132 struct npreq * 133 ix_GetReq(mp, addr, len) 134 struct npmaster *mp; 135 caddr_t addr; 136 { 137 int unit = mp->unit; 138 register struct npreq *rp; 139 register struct CQE *ep; 140 struct ix_softc *ix = ix_softc + unit; 141 extern struct npreq *NpGetReq(); 142 143 while ((rp = NpGetReq(mp->reqtab)) == NULL) { 144 mp->reqtab->flags |= WANTREQ; 145 sleep((caddr_t)(mp->reqtab), PZERO - 1); 146 } 147 rp->flags = KERNREQ; /* Clear flags */ 148 149 ep = rp->element; /* Associated CQE */ 150 ep->cqe_famid = (unsign32)ix; /* Process ID */ 151 ep->cqe_wind = 0; /* Amount of buffer mapped */ 152 ep->cqe_nbuf = 1; /* Must be 1, no buffer chain */ 153 ep->cqe_char = 1; /* Driver owns this CQE */ 154 ep->cqe_prot = NPDLA; /* Data Link Access protocol */ 155 ep->cqe_bcnt = len; /* Byte count */ 156 rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ 157 ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); 158 ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); 159 return (rp); 160 } 161 162 ix_DoReq(mp, rp, cmd, addr, len, rpb, routine) 163 struct npmaster *mp; 164 register struct npreq *rp; 165 u_short cmd; 166 caddr_t addr; 167 int len; 168 register u_short *rpb; 169 int (*routine)(); 170 { 171 register struct CQE *ep = rp->element; 172 register u_short *p = &ep->rpb1; 173 u_short cnt = *rpb++; 174 extern long NpDebug; 175 int pri; 176 int result = 0; 177 178 ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ 179 ep->cqe_bcnt = len; /* Byte count */ 180 rp->flags = KERNREQ | REQALOC; /* Clear flags */ 181 rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ 182 rp->intr = routine; 183 rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */ 184 ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); 185 ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); 186 ep->cqe_lenrpb = cnt + cnt; 187 for (; cnt > 0; cnt--) *p++ = *rpb++; 188 189 if (NpDebug & DEBCQE) 190 printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid); 191 if (NpDebug & DEBCQE) 192 printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp); 193 if (routine == 0) { 194 NpAddReq(mp->reqtab, rp); /* Queue onto active list */ 195 while (!(rp->flags & REQDONE)) { 196 pri = spl5(); 197 NpAddCQE(ep, &mp->shmemp->devcq, mp); 198 sleep((caddr_t)rp, PZERO - 1); 199 splx(pri); 200 } 201 if (rp->flags & IOABORT || ep->cqe_sts != NPDONE 202 || ep->cqe_ust0 != NPDONE 203 || ep->cqe_ust1 != NPOK) { 204 struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid; 205 printf("ix%d: Req failed, cmd %x, stat %x, flags %x, ", 206 ix->ix_if.if_unit, rp->user, 207 ep->cqe_sts, rp->flags); 208 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); 209 result = 1; 210 } 211 NpRemReq(rp); /* Clear request */ 212 } else { 213 pri = spl5(); 214 NpAddCQE(ep, &mp->shmemp->devcq, mp); 215 splx(pri); 216 } 217 return(result); 218 } 219 /* 220 * Reset of interface after UNIBUS reset. 221 * If interface is on specified uba, reset its state. 222 */ 223 ixreset(unit, uban, softp) 224 int unit, uban; 225 caddr_t softp; 226 { 227 register struct uba_device *ui; 228 int mask = IXF_SETADDR; /* Only remember new physaddr */ 229 230 if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 || 231 ui->ui_ubanum != uban) 232 return; 233 printf(" ix%d reset", unit); 234 if (softp) 235 mask |= IXF_GOTUBA; /* UBA mapping regs still valid; */ 236 ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING; 237 ix_softc[unit].ix_flags &= mask; 238 } 239 240 int ix_MacLoop = 0; 241 242 /* 243 * Initialization of interface; clear recorded pending 244 * operations, and reinitialize UNIBUS usage. 245 */ 246 ixinit(unit) 247 int unit; 248 { 249 register struct ix_softc *ix = &ix_softc[unit]; 250 struct uba_device *ui = npdinfo[unit]; 251 register struct ifnet *ifp = &ix->ix_if; 252 register struct CQE *ep; 253 struct npreq *rp; 254 struct npmaster *mp = ix->ix_mp; 255 register u_short *dpmp = & mp->shmemp->statblock.sb_dpm; 256 u_short rpb[7]; 257 int s; 258 259 /* not yet, if address still unknown */ 260 if ((ifp->if_addrlist == (struct ifaddr *)0) || 261 (ix->ix_flags & IXF_RUNNING)) 262 return; 263 if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) { 264 ifp->if_flags &= ~IFF_UP; 265 return; 266 } 267 if ((ix->ix_flags & IXF_GOTUBA) == 0) { 268 ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; 269 if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum, 270 sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 271 printf("ix%d: can't initialize\n", unit); 272 ix->ix_if.if_flags &= ~IFF_UP; 273 return; 274 } 275 ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats, 276 sizeof (union ix_stats), 0); 277 ix->ix_flags |= IXF_GOTUBA; 278 } 279 if ((ix->ix_flags & IXF_GOTCQE) == 0) { 280 ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info, 281 ETHERMTU); 282 ix->ix_wrp = ix_GetReq(mp, 0, 0); 283 ix->ix_flags |= IXF_GOTCQE; 284 } 285 286 rp = ix->ix_wrp; 287 ep = rp->element; 288 289 /* Changing the ethernet address resets the dla module, 290 so must do it before opening the channel */ 291 if (ix->ix_flags & IXF_SETADDR) { 292 register char *cp = (char *) &ix->ix_stats; 293 int spincount; 294 int x; 295 /* Try Issuing an open channel request before reprogramming 296 the physical address */ 297 rpb[0] = 6; /* RPB length */ 298 rpb[2] = 0x10; /* Share with any smart users */ 299 rpb[3] = 0; /* Take (a copy of) all frames */ 300 rpb[5] = 8; /* On board rcv queue length */ 301 rpb[6] = 0; /* XMT packets as is */ 302 if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0)) 303 return; 304 /* Proceed with LDPA */ 305 *cp++ = 1; 306 bcopy(ix->ix_addr, (caddr_t)cp, 6); 307 rpb[0] = 1; /* RPB length */ 308 if (ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0)) 309 return; 310 #ifndef TheyFinallyFixedTheBoard 311 /* Board requires some time to reinitialize its protocols */ 312 x = spl1(); 313 spincount = 2000000; 314 while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0) 315 spincount--; 316 if (spincount==0) { 317 printf("ix%d: failed to reinitialize DLA module\n", 318 unit); 319 splx(x); 320 } 321 splx(x); 322 #endif 323 } 324 rpb[0] = 6; /* RPB length */ 325 rpb[2] = 0x10; /* Share with any smart users */ 326 if (ix_MacLoop) rpb[2] |= 0x8; 327 /* Enable software loopback on board */ 328 rpb[3] = 0; /* Take (a copy of) all frames */ 329 rpb[5] = 8; /* On board rcv queue length */ 330 rpb[6] = 0; /* XMT packets as is */ 331 if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0)) 332 return; 333 334 ix->ix_aid = ep->rpb1; 335 336 /* Here we request our ethernet address, if we didn't reset it*/ 337 if ((ix->ix_flags & IXF_SETADDR)==0) { 338 rpb[0] = 2; 339 rpb[1] = ix->ix_aid; 340 rpb[2] = 0; /* get all stats */ 341 if (ix_DoReq(mp, rp, IXC_GSTAT, /* Get Stats */ 342 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, 343 rpb, 0)) 344 return; 345 bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6); 346 } 347 ix->ix_if.if_flags |= IFF_RUNNING; 348 ix->ix_flags |= IXF_RUNNING; 349 ifp->if_watchdog = ixwatch; 350 ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL; 351 ixrint(mp, 0); 352 } 353 354 /* 355 * Start output on interface. 356 * Get another datagram to send off of the interface queue, 357 * and map it to the interface before starting the output. 358 */ 359 ixstart(ifp) 360 struct ifnet *ifp; 361 { 362 int len = 0; 363 int unit = ifp->if_unit; 364 register struct ix_softc *ix = &ix_softc[unit]; 365 register struct mbuf *n; 366 struct mbuf *m; 367 int s, error = 0; 368 struct npmaster *mp = ix->ix_mp; 369 struct npreq *rp = ix->ix_wrp; 370 struct CQE *ep; 371 u_short rpb[8]; 372 373 IF_DEQUEUE(&ix->ix_if.if_snd, m); 374 if (m == 0) { 375 if (ix->ix_flags & IXF_STATPENDING) { 376 ix->ix_flags &= ~IXF_STATPENDING; 377 ix->ix_if.if_flags |= IFF_OACTIVE; 378 rpb[0] = 2; 379 rpb[1] = ix->ix_aid; 380 rpb[2] = 0; /* get all stats */ 381 ix_DoReq(mp, rp, IXC_GSTAT, /* general Stats */ 382 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, 383 rpb, ixcint); 384 } 385 return (0); 386 } 387 /* 388 * Ensure minimum packet length. 389 * This makes the safe assumtion that there are no virtual holes 390 * after the data. 391 * For security, it might be wise to zero out the added bytes, 392 * but we're mainly interested in speed at the moment. 393 */ 394 len = if_wubaput(&ix->ix_ifuba, m); 395 if (len - sizeof(struct ether_header) < ETHERMIN) 396 len = ETHERMIN + sizeof(struct ether_header); 397 398 ix->ix_if.if_flags |= IFF_OACTIVE; 399 400 /* Now setup to call np driver */ 401 rpb[0] = 8; 402 rpb[1] = ix->ix_aid; 403 ix_DoReq(mp, rp, IXC_XMIT, /* send frame */ 404 ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint); 405 return (0); 406 } 407 408 /* 409 * Command done interrupt. (almost) 410 */ 411 ixcint(mp, rp) 412 struct npmaster *mp; 413 struct npreq *rp; 414 { 415 struct CQE *ep; 416 register struct ix_softc *ix; 417 int s = splimp(); 418 419 ep = rp->element; 420 ix = (struct ix_softc *)ep->cqe_famid; 421 ix->ix_flags &= ~IXF_OWATCH; 422 if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) { 423 printf("ix%d: stray xmit interrupt, npreq=%x\n", 424 ix->ix_if.if_unit, rp); 425 } 426 ix->ix_if.if_flags &= ~IFF_OACTIVE; 427 if (rp->flags & IOABORT || ep->cqe_sts != NPDONE 428 || ep->cqe_ust0 != NPDONE || ep->cqe_ust1 != NPOK) { 429 if (ep->cqe_ust1 == 0x48) 430 ix->ix_if.if_oerrors++; 431 else { 432 struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid; 433 printf( 434 "ix%d: ixcint failed, cmd %x, stat %x, flags %x, ", 435 ix->ix_if.if_unit, rp->user, 436 ep->cqe_sts, rp->flags); 437 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); 438 if (++ix->ix_badcqe > 65) { 439 ix->ix_badcqe = 0; 440 printf("ixcint: shutting down unix dla\n"); 441 ix->ix_if.if_flags &= ~IFF_UP; 442 } 443 } 444 } 445 else switch (ep->cqe_func) { 446 447 case IXC_XMIT: 448 ix->ix_if.if_opackets++; 449 break; 450 451 case IXC_GSTAT: 452 ix->ix_if.if_collisions += ix->ix_stats.ixg.macg_xrty; 453 } 454 done: 455 if (ix->ix_ifuba.ifu_xtofree) { 456 m_freem(ix->ix_ifuba.ifu_xtofree); 457 ix->ix_ifuba.ifu_xtofree = 0; 458 } 459 if ((ix->ix_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) 460 (void) ixstart(&ix->ix_if); 461 splx(s); 462 } 463 464 /* 465 * Ethernet interface receiver interrupt. 466 * If input error just drop packet. 467 * Otherwise purge input buffered data path and examine 468 * packet to determine type. If can't determine length 469 * from type, then have to drop packet. Othewise decapsulate 470 * packet based on type and pass to type specific higher-level 471 * input routine. 472 */ 473 ixrint(mp, rp) 474 struct npmaster *mp; 475 struct npreq *rp; 476 { 477 struct CQE *ep; 478 register struct ix_softc *ix = ix_softc + mp->unit; 479 register struct ether_header *il; 480 struct mbuf *m; 481 int len, off, resid, s; 482 register struct ifqueue *inq; 483 484 if ((ix->ix_flags & IXF_RUNNING) == 0) 485 return; 486 if (rp == 0) 487 goto setup; 488 ix->ix_flags &= ~(IXF_RCVPENDING|IXF_RWATCH); 489 ep = rp->element; 490 ix->ix_if.if_ipackets++; 491 if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP) 492 UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp); 493 il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr); 494 len = ep->cqe_bcnt - sizeof (struct ether_header); 495 if (ep->cqe_sts != NPDONE || rp->flags & IOABORT 496 || ep->cqe_ust0 != NPDONE 497 || ep->cqe_ust1 != NPOK) { 498 printf("ix%drint: cqe error, cmd %x, stat %x, flags %x, ", 499 ix->ix_if.if_unit, rp->user, ep->cqe_sts, rp->flags); 500 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); 501 if (++ix->ix_badcqe > 50) { 502 ix->ix_badcqe = 0; 503 printf("ixrint: shutting down unix dla\n"); 504 ix->ix_if.if_flags &= ~IFF_UP; 505 return; 506 } 507 goto setup; 508 } 509 510 if ( len < 46 || len > ETHERMTU) { 511 ix->ix_if.if_ierrors++; 512 #ifdef notdef 513 if (ix->ix_if.if_ierrors % 100 == 0) 514 printf("ix%d: += 100 input errors\n", unit); 515 #endif 516 goto setup; 517 } 518 519 /* 520 * Deal with trailer protocol: if type is trailer type 521 * get true type from first 16-bit word past data. 522 * Remember that type was trailer by setting off. 523 */ 524 il->ether_type = ntohs((u_short)il->ether_type); 525 #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) 526 if (il->ether_type >= ETHERTYPE_TRAIL && 527 il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 528 off = (il->ether_type - ETHERTYPE_TRAIL) * 512; 529 if (off >= ETHERMTU) 530 goto setup; /* sanity */ 531 il->ether_type = ntohs(*ildataaddr(il, off, u_short *)); 532 resid = ntohs(*(ildataaddr(il, off+2, u_short *))); 533 if (off + resid > len) 534 goto setup; /* sanity */ 535 len = off + resid; 536 } else 537 off = 0; 538 if (len == 0) 539 goto setup; 540 541 /* 542 * Pull packet off interface. Off is nonzero if packet 543 * has trailing header; ilget will then force this header 544 * information to be at the front, but we still have to drop 545 * the type and length which are at the front of any trailer data. 546 */ 547 m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if); 548 if (m) 549 ether_input(&ix->ix_if, il, m); 550 551 setup: 552 /* 553 * Reset for next packet if possible. 554 * If waiting for transmit command completion, set flag 555 * and wait until command completes. 556 */ 557 if (rp == 0) { 558 rp = ix->ix_rrp; 559 rp->intr = ixrint; 560 ep = rp->element; 561 } 562 len = ETHERMTU + sizeof(struct ether_header); 563 564 /* Now setup to call np driver */ 565 /* Initializations of request structure */ 566 567 ep->cqe_func = IXC_RECV; /* get frame */ 568 ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ 569 ep->cqe_bcnt = len; /* Byte count */ 570 ep->cqe_lenrpb = 10; /* RPB length */ 571 ep->rpb1 = ix->ix_aid; /* which channel */ 572 ep->rpb2 = 65535; /* Timeout */ 573 574 ix->ix_flags |= IXF_RCVPENDING; 575 576 s = spl5(); 577 NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */ 578 splx(s); 579 } 580 581 582 long ixwatchcount; 583 /* 584 * Watchdog routine, request statistics from board. 585 */ 586 ixwatch(unit) 587 int unit; 588 { 589 register struct ix_softc *ix = &ix_softc[unit]; 590 register struct ifnet *ifp = &ix->ix_if; 591 int s; 592 593 ixwatchcount++; 594 if (ix->ix_badcqe > 1) { 595 ix->ix_badcqe--; /* If errors aren't happening too fast, 596 give the board a reprieve */ 597 } 598 s = splimp(); 599 if (ix->ix_flags & IXF_STATPENDING) { 600 ifp->if_timer = ix->ix_scaninterval; 601 ix->ix_flags |= IXF_OWATCH; 602 splx(s); 603 return; 604 } 605 ix->ix_flags |= IXF_STATPENDING; 606 if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) 607 (void) ixstart(ifp); 608 else 609 ix->ix_flags |= IXF_OWATCH; 610 if (ix->ix_flags & IXF_RCVPENDING) 611 ix->ix_flags |= IXF_RWATCH; 612 splx(s); 613 ifp->if_timer = ix->ix_scaninterval; 614 } 615 /* 616 * Process an ioctl request. 617 */ 618 ixioctl(ifp, cmd, data) 619 register struct ifnet *ifp; 620 int cmd; 621 caddr_t data; 622 { 623 register struct ifaddr *ifa = (struct ifaddr *)data; 624 register struct ix_softc *ix = &ix_softc[ifp->if_unit]; 625 int s = splimp(), error = 0; 626 627 switch (cmd) { 628 629 case SIOCSIFADDR: 630 ifp->if_flags |= IFF_UP; 631 ixinit(ifp->if_unit); 632 if ((ifp->if_flags & IFF_UP) == 0) 633 return (EBUSY); 634 635 switch (ifa->ifa_addr->sa_family) { 636 #ifdef INET 637 case AF_INET: 638 ((struct arpcom *)ifp)->ac_ipaddr = 639 IA_SIN(ifa)->sin_addr; 640 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 641 break; 642 #endif 643 #ifdef NS 644 case AF_NS: 645 { 646 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 647 648 if (ns_nullhost(*ina)) { 649 ina->x_host = * (union ns_host *) 650 (ix_softc[ifp->if_unit].ix_addr); 651 } else { 652 return 653 ix_setaddr(ina->x_host.c_host, ifp->if_unit); 654 } 655 break; 656 } 657 #endif 658 } 659 break; 660 661 case SIOCSIFFLAGS: 662 if ((ifp->if_flags & IFF_UP) == 0 && 663 ix->ix_flags & IXF_RUNNING) { 664 ix->ix_flags &= ~IXF_RUNNING; 665 NpReset(ix->ix_mp, 0); 666 } else if (ifp->if_flags & IFF_UP && 667 (ix->ix_flags & IXF_RUNNING) == 0) 668 ixinit(ifp->if_unit); 669 break; 670 671 default: 672 error = EINVAL; 673 } 674 splx(s); 675 return (error); 676 } 677 678 /* 679 * set ethernet address for unit 680 */ 681 ix_setaddr(physaddr, unit) 682 u_char *physaddr; 683 int unit; 684 { 685 register struct ix_softc *ix = &ix_softc[unit]; 686 687 if (! (ix->ix_flags & IXF_RUNNING)) 688 return (EBUSY); 689 690 /* The following is a big cop out due to the fact that 691 Changing the ethernet address resets the dla module, 692 so must re-open the channel, anyway. */ 693 694 695 bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr); 696 ix->ix_flags &= ~IXF_RUNNING; 697 ix->ix_flags |= IXF_SETADDR; 698 ixinit(unit); 699 NpKill(ix->ix_mp, ix->ix_rrp); 700 } 701 static showme() { 702 return ((int) &(ix_softc->ix_badcqe)); 703 } 704 #endif 705