1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if_de.c 7.8 (Berkeley) 04/25/89 18 */ 19 20 #include "de.h" 21 #if NDE > 0 22 23 /* 24 * DEC DEUNA interface 25 * 26 * Lou Salkind 27 * New York University 28 * 29 * TODO: 30 * timeout routine (get statistics) 31 */ 32 #include "machine/pte.h" 33 34 #include "param.h" 35 #include "systm.h" 36 #include "mbuf.h" 37 #include "buf.h" 38 #include "protosw.h" 39 #include "socket.h" 40 #include "vmmac.h" 41 #include "ioctl.h" 42 #include "errno.h" 43 #include "syslog.h" 44 45 #include "../net/if.h" 46 #include "../net/netisr.h" 47 #include "../net/route.h" 48 49 #ifdef INET 50 #include "../netinet/in.h" 51 #include "../netinet/in_systm.h" 52 #include "../netinet/in_var.h" 53 #include "../netinet/ip.h" 54 #include "../netinet/if_ether.h" 55 #endif 56 57 #ifdef NS 58 #include "../netns/ns.h" 59 #include "../netns/ns_if.h" 60 #endif 61 62 #ifdef ISO 63 #include "../netiso/iso.h" 64 #include "../netiso/iso_var.h" 65 #include "../netiso/iso_snpac.h" 66 extern struct snpa_cache all_es, all_is; 67 #endif 68 69 #include "../vax/cpu.h" 70 #include "../vax/mtpr.h" 71 #include "if_dereg.h" 72 #include "if_uba.h" 73 #include "../vaxuba/ubareg.h" 74 #include "../vaxuba/ubavar.h" 75 76 #define NXMT 3 /* number of transmit buffers */ 77 #define NRCV 7 /* number of receive buffers (must be > 1) */ 78 79 int dedebug = 0; 80 81 int deprobe(), deattach(), deintr(); 82 struct uba_device *deinfo[NDE]; 83 u_short destd[] = { 0 }; 84 struct uba_driver dedriver = 85 { deprobe, 0, deattach, 0, destd, "de", deinfo }; 86 int deinit(),ether_output(),deioctl(),dereset(),destart(); 87 88 89 /* 90 * Ethernet software status per interface. 91 * 92 * Each interface is referenced by a network interface structure, 93 * ds_if, which the routing code uses to locate the interface. 94 * This structure contains the output queue for the interface, its address, ... 95 * We also have, for each interface, a UBA interface structure, which 96 * contains information about the UNIBUS resources held by the interface: 97 * map registers, buffered data paths, etc. Information is cached in this 98 * structure for use by the if_uba.c routines in running the interface 99 * efficiently. 100 */ 101 struct de_softc { 102 struct arpcom ds_ac; /* Ethernet common part */ 103 #define ds_if ds_ac.ac_if /* network-visible interface */ 104 #define ds_addr ds_ac.ac_enaddr /* hardware Ethernet address */ 105 int ds_flags; 106 #define DSF_LOCK 1 /* lock out destart */ 107 #define DSF_RUNNING 2 /* board is enabled */ 108 #define DSF_SETADDR 4 /* physical address is changed */ 109 int ds_ubaddr; /* map info for incore structs */ 110 struct ifubinfo ds_deuba; /* unibus resource structure */ 111 struct ifrw ds_ifr[NRCV]; /* unibus receive maps */ 112 struct ifxmt ds_ifw[NXMT]; /* unibus xmt maps */ 113 /* the following structures are always mapped in */ 114 struct de_pcbb ds_pcbb; /* port control block */ 115 struct de_ring ds_xrent[NXMT]; /* transmit ring entrys */ 116 struct de_ring ds_rrent[NRCV]; /* receive ring entrys */ 117 struct de_udbbuf ds_udbbuf; /* UNIBUS data buffer */ 118 /* end mapped area */ 119 #define INCORE_BASE(p) ((char *)&(p)->ds_pcbb) 120 #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0])) 121 #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0])) 122 #define PCBB_OFFSET RVAL_OFF(ds_pcbb) 123 #define XRENT_OFFSET LVAL_OFF(ds_xrent) 124 #define RRENT_OFFSET LVAL_OFF(ds_rrent) 125 #define UDBBUF_OFFSET RVAL_OFF(ds_udbbuf) 126 #define INCORE_SIZE RVAL_OFF(ds_xindex) 127 int ds_xindex; /* UNA index into transmit chain */ 128 int ds_rindex; /* UNA index into receive chain */ 129 int ds_xfree; /* index for next transmit buffer */ 130 int ds_nxmit; /* # of transmits in progress */ 131 } de_softc[NDE]; 132 133 deprobe(reg) 134 caddr_t reg; 135 { 136 register int br, cvec; /* r11, r10 value-result */ 137 register struct dedevice *addr = (struct dedevice *)reg; 138 register i; 139 140 #ifdef lint 141 br = 0; cvec = br; br = cvec; 142 i = 0; derint(i); deintr(i); 143 #endif 144 145 /* 146 * Make sure self-test is finished before we screw with the board. 147 * Self-test on a DELUA can take 15 seconds (argh). 148 */ 149 for (i = 0; 150 i < 160 && 151 (addr->pcsr0 & PCSR0_FATI) == 0 && 152 (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET; 153 ++i) 154 DELAY(100000); 155 if ((addr->pcsr0 & PCSR0_FATI) != 0 || 156 (addr->pcsr1 & PCSR1_STMASK) != STAT_READY) 157 return(0); 158 159 addr->pcsr0 = 0; 160 DELAY(100); 161 addr->pcsr0 = PCSR0_RSET; 162 while ((addr->pcsr0 & PCSR0_INTR) == 0) 163 ; 164 /* make board interrupt by executing a GETPCBB command */ 165 addr->pcsr0 = PCSR0_INTE; 166 addr->pcsr2 = 0; 167 addr->pcsr3 = 0; 168 addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB; 169 DELAY(100000); 170 return(1); 171 } 172 173 /* 174 * Interface exists: make available by filling in network interface 175 * record. System will initialize the interface when it is ready 176 * to accept packets. We get the ethernet address here. 177 */ 178 deattach(ui) 179 struct uba_device *ui; 180 { 181 register struct de_softc *ds = &de_softc[ui->ui_unit]; 182 register struct ifnet *ifp = &ds->ds_if; 183 register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 184 int csr1; 185 186 ifp->if_unit = ui->ui_unit; 187 ifp->if_name = "de"; 188 ifp->if_mtu = ETHERMTU; 189 ifp->if_flags = IFF_BROADCAST; 190 191 /* 192 * What kind of a board is this? 193 * The error bits 4-6 in pcsr1 are a device id as long as 194 * the high byte is zero. 195 */ 196 csr1 = addr->pcsr1; 197 if (csr1 & 0xff60) 198 printf("de%d: broken\n", ui->ui_unit); 199 else if (csr1 & 0x10) 200 printf("de%d: delua\n", ui->ui_unit); 201 else 202 printf("de%d: deuna\n", ui->ui_unit); 203 204 /* 205 * Reset the board and temporarily map 206 * the pcbb buffer onto the Unibus. 207 */ 208 addr->pcsr0 = 0; /* reset INTE */ 209 DELAY(100); 210 addr->pcsr0 = PCSR0_RSET; 211 (void)dewait(ui, "reset"); 212 213 ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb, 214 sizeof (struct de_pcbb), 0); 215 addr->pcsr2 = ds->ds_ubaddr & 0xffff; 216 addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3; 217 addr->pclow = CMD_GETPCBB; 218 (void)dewait(ui, "pcbb"); 219 220 ds->ds_pcbb.pcbb0 = FC_RDPHYAD; 221 addr->pclow = CMD_GETCMD; 222 (void)dewait(ui, "read addr "); 223 224 ubarelse(ui->ui_ubanum, &ds->ds_ubaddr); 225 bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr, 226 sizeof (ds->ds_addr)); 227 printf("de%d: hardware address %s\n", ui->ui_unit, 228 ether_sprintf(ds->ds_addr)); 229 ifp->if_init = deinit; 230 ifp->if_output = ether_output; 231 ifp->if_ioctl = deioctl; 232 ifp->if_reset = dereset; 233 ifp->if_start = destart; 234 ds->ds_deuba.iff_flags = UBA_CANTWAIT; 235 #ifdef notdef 236 /* CAN WE USE BDP's ??? */ 237 ds->ds_deuba.iff_flags |= UBA_NEEDBDP; 238 #endif 239 if_attach(ifp); 240 } 241 242 /* 243 * Reset of interface after UNIBUS reset. 244 * If interface is on specified uba, reset its state. 245 */ 246 dereset(unit, uban) 247 int unit, uban; 248 { 249 register struct uba_device *ui; 250 251 if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 || 252 ui->ui_ubanum != uban) 253 return; 254 printf(" de%d", unit); 255 de_softc[unit].ds_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 256 de_softc[unit].ds_flags &= ~DSF_RUNNING; 257 ((struct dedevice *)ui->ui_addr)->pcsr0 = PCSR0_RSET; 258 (void)dewait(ui, "reset"); 259 deinit(unit); 260 } 261 262 /* 263 * Initialization of interface; clear recorded pending 264 * operations, and reinitialize UNIBUS usage. 265 */ 266 deinit(unit) 267 int unit; 268 { 269 register struct de_softc *ds = &de_softc[unit]; 270 register struct uba_device *ui = deinfo[unit]; 271 register struct dedevice *addr; 272 register struct ifrw *ifrw; 273 register struct ifxmt *ifxp; 274 struct ifnet *ifp = &ds->ds_if; 275 int s; 276 struct de_ring *rp; 277 int incaddr; 278 279 /* not yet, if address still unknown */ 280 if (ifp->if_addrlist == (struct ifaddr *)0) 281 return; 282 283 if (ds->ds_flags & DSF_RUNNING) 284 return; 285 if ((ifp->if_flags & IFF_RUNNING) == 0) { 286 if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum, 287 sizeof (struct ether_header), (int)btoc(ETHERMTU), 288 ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) { 289 printf("de%d: can't initialize\n", unit); 290 ds->ds_if.if_flags &= ~IFF_UP; 291 return; 292 } 293 ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), 294 INCORE_SIZE, 0); 295 } 296 addr = (struct dedevice *)ui->ui_addr; 297 298 /* set the pcbb block address */ 299 incaddr = ds->ds_ubaddr + PCBB_OFFSET; 300 addr->pcsr2 = incaddr & 0xffff; 301 addr->pcsr3 = (incaddr >> 16) & 0x3; 302 addr->pclow = 0; /* reset INTE */ 303 DELAY(100); 304 addr->pclow = CMD_GETPCBB; 305 (void)dewait(ui, "pcbb"); 306 307 /* set the transmit and receive ring header addresses */ 308 incaddr = ds->ds_ubaddr + UDBBUF_OFFSET; 309 ds->ds_pcbb.pcbb0 = FC_WTRING; 310 ds->ds_pcbb.pcbb2 = incaddr & 0xffff; 311 ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3; 312 313 incaddr = ds->ds_ubaddr + XRENT_OFFSET; 314 ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff; 315 ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3; 316 ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short); 317 ds->ds_udbbuf.b_trlen = NXMT; 318 incaddr = ds->ds_ubaddr + RRENT_OFFSET; 319 ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff; 320 ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3; 321 ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short); 322 ds->ds_udbbuf.b_rrlen = NRCV; 323 324 addr->pclow = CMD_GETCMD; 325 (void)dewait(ui, "wtring"); 326 327 /* initialize the mode - enable hardware padding */ 328 ds->ds_pcbb.pcbb0 = FC_WTMODE; 329 /* let hardware do padding - set MTCH bit on broadcast */ 330 ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX; 331 addr->pclow = CMD_GETCMD; 332 (void)dewait(ui, "wtmode"); 333 334 /* set up the receive and transmit ring entries */ 335 ifxp = &ds->ds_ifw[0]; 336 for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) { 337 rp->r_segbl = ifxp->ifw_info & 0xffff; 338 rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3; 339 rp->r_flags = 0; 340 ifxp++; 341 } 342 ifrw = &ds->ds_ifr[0]; 343 for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) { 344 rp->r_slen = sizeof (struct de_buf); 345 rp->r_segbl = ifrw->ifrw_info & 0xffff; 346 rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3; 347 rp->r_flags = RFLG_OWN; /* hang receive */ 348 ifrw++; 349 } 350 351 /* start up the board (rah rah) */ 352 s = splimp(); 353 ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0; 354 ds->ds_if.if_flags |= IFF_RUNNING; 355 addr->pclow = PCSR0_INTE; /* avoid interlock */ 356 (void) destart(&ds->ds_if); /* queue output packets */ 357 ds->ds_flags |= DSF_RUNNING; /* need before de_setaddr */ 358 if (ds->ds_flags & DSF_SETADDR) 359 de_setaddr(ds->ds_addr, unit); 360 addr->pclow = CMD_START | PCSR0_INTE; 361 splx(s); 362 } 363 364 /* 365 * Setup output on interface. 366 * Get another datagram to send off of the interface queue, 367 * and map it to the interface before starting the output. 368 */ 369 destart(ifp) 370 struct ifnet *ifp; 371 { 372 int len; 373 int unit = ifp->if_unit; 374 struct uba_device *ui = deinfo[unit]; 375 struct dedevice *addr = (struct dedevice *)ui->ui_addr; 376 register struct de_softc *ds = &de_softc[unit]; 377 register struct de_ring *rp; 378 struct mbuf *m; 379 register int nxmit; 380 381 /* 382 * the following test is necessary, since 383 * the code is not reentrant and we have 384 * multiple transmission buffers. 385 */ 386 if (ds->ds_if.if_flags & IFF_OACTIVE) 387 return (0); 388 for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) { 389 IF_DEQUEUE(&ds->ds_if.if_snd, m); 390 if (m == 0) 391 break; 392 rp = &ds->ds_xrent[ds->ds_xfree]; 393 if (rp->r_flags & XFLG_OWN) 394 panic("deuna xmit in progress"); 395 len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m); 396 if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 397 UBAPURGE(ds->ds_deuba.iff_uba, 398 ds->ds_ifw[ds->ds_xfree].ifw_bdp); 399 rp->r_slen = len; 400 rp->r_tdrerr = 0; 401 rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN; 402 403 ds->ds_xfree++; 404 if (ds->ds_xfree == NXMT) 405 ds->ds_xfree = 0; 406 } 407 if (ds->ds_nxmit != nxmit) { 408 ds->ds_nxmit = nxmit; 409 if (ds->ds_flags & DSF_RUNNING) 410 addr->pclow = PCSR0_INTE|CMD_PDMD; 411 } 412 return (0); 413 } 414 415 /* 416 * Command done interrupt. 417 */ 418 deintr(unit) 419 int unit; 420 { 421 struct uba_device *ui = deinfo[unit]; 422 register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 423 register struct de_softc *ds = &de_softc[unit]; 424 register struct de_ring *rp; 425 register struct ifxmt *ifxp; 426 short csr0; 427 428 /* save flags right away - clear out interrupt bits */ 429 csr0 = addr->pcsr0; 430 addr->pchigh = csr0 >> 8; 431 432 433 ds->ds_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */ 434 /* 435 * if receive, put receive buffer on mbuf 436 * and hang the request again 437 */ 438 derecv(unit); 439 440 /* 441 * Poll transmit ring and check status. 442 * Be careful about loopback requests. 443 * Then free buffer space and check for 444 * more transmit requests. 445 */ 446 for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) { 447 rp = &ds->ds_xrent[ds->ds_xindex]; 448 if (rp->r_flags & XFLG_OWN) 449 break; 450 ds->ds_if.if_opackets++; 451 ifxp = &ds->ds_ifw[ds->ds_xindex]; 452 /* check for unusual conditions */ 453 if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) { 454 if (rp->r_flags & XFLG_ERRS) { 455 /* output error */ 456 ds->ds_if.if_oerrors++; 457 if (dedebug) 458 printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n", 459 unit, rp->r_flags, XFLG_BITS, 460 rp->r_tdrerr, XERR_BITS, rp->r_slen); 461 } else if (rp->r_flags & XFLG_ONE) { 462 /* one collision */ 463 ds->ds_if.if_collisions++; 464 } else if (rp->r_flags & XFLG_MORE) { 465 /* more than one collision */ 466 ds->ds_if.if_collisions += 2; /* guess */ 467 } else if (rp->r_flags & XFLG_MTCH) { 468 /* received our own packet */ 469 ds->ds_if.if_ipackets++; 470 deread(ds, &ifxp->ifrw, 471 rp->r_slen - sizeof (struct ether_header)); 472 } 473 } 474 if (ifxp->ifw_xtofree) { 475 m_freem(ifxp->ifw_xtofree); 476 ifxp->ifw_xtofree = 0; 477 } 478 /* check if next transmit buffer also finished */ 479 ds->ds_xindex++; 480 if (ds->ds_xindex == NXMT) 481 ds->ds_xindex = 0; 482 } 483 ds->ds_if.if_flags &= ~IFF_OACTIVE; 484 (void) destart(&ds->ds_if); 485 486 if (csr0 & PCSR0_RCBI) { 487 if (dedebug) 488 log(LOG_WARNING, "de%d: buffer unavailable\n", unit); 489 addr->pclow = PCSR0_INTE|CMD_PDMD; 490 } 491 } 492 493 /* 494 * Ethernet interface receiver interface. 495 * If input error just drop packet. 496 * Otherwise purge input buffered data path and examine 497 * packet to determine type. If can't determine length 498 * from type, then have to drop packet. Othewise decapsulate 499 * packet based on type and pass to type specific higher-level 500 * input routine. 501 */ 502 derecv(unit) 503 int unit; 504 { 505 register struct de_softc *ds = &de_softc[unit]; 506 register struct de_ring *rp; 507 int len; 508 509 rp = &ds->ds_rrent[ds->ds_rindex]; 510 while ((rp->r_flags & RFLG_OWN) == 0) { 511 ds->ds_if.if_ipackets++; 512 if (ds->ds_deuba.iff_flags & UBA_NEEDBDP) 513 UBAPURGE(ds->ds_deuba.iff_uba, 514 ds->ds_ifr[ds->ds_rindex].ifrw_bdp); 515 len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header) 516 - 4; /* don't forget checksum! */ 517 /* check for errors */ 518 if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) || 519 (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) || 520 (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) || 521 len < ETHERMIN || len > ETHERMTU) { 522 ds->ds_if.if_ierrors++; 523 if (dedebug) 524 printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n", 525 unit, rp->r_flags, RFLG_BITS, rp->r_lenerr, 526 RERR_BITS, len); 527 } else 528 deread(ds, &ds->ds_ifr[ds->ds_rindex], len); 529 530 /* hang the receive buffer again */ 531 rp->r_lenerr = 0; 532 rp->r_flags = RFLG_OWN; 533 534 /* check next receive buffer */ 535 ds->ds_rindex++; 536 if (ds->ds_rindex == NRCV) 537 ds->ds_rindex = 0; 538 rp = &ds->ds_rrent[ds->ds_rindex]; 539 } 540 } 541 542 /* 543 * Pass a packet to the higher levels. 544 * We deal with the trailer protocol here. 545 */ 546 deread(ds, ifrw, len) 547 register struct de_softc *ds; 548 struct ifrw *ifrw; 549 int len; 550 { 551 struct ether_header *eh; 552 struct mbuf *m; 553 int off, resid; 554 int s; 555 register struct ifqueue *inq; 556 557 /* 558 * Deal with trailer protocol: if type is trailer type 559 * get true type from first 16-bit word past data. 560 * Remember that type was trailer by setting off. 561 */ 562 eh = (struct ether_header *)ifrw->ifrw_addr; 563 eh->ether_type = ntohs((u_short)eh->ether_type); 564 #define dedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) 565 if (eh->ether_type >= ETHERTYPE_TRAIL && 566 eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 567 off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; 568 if (off >= ETHERMTU) 569 return; /* sanity */ 570 eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *)); 571 resid = ntohs(*(dedataaddr(eh, off+2, u_short *))); 572 if (off + resid > len) 573 return; /* sanity */ 574 len = off + resid; 575 } else 576 off = 0; 577 if (len == 0) 578 return; 579 580 /* 581 * Pull packet off interface. Off is nonzero if packet 582 * has trailing header; if_ubaget will then force this header 583 * information to be at the front, but we still have to drop 584 * the type and length which are at the front of any trailer data. 585 */ 586 m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if); 587 if (m == 0) 588 return; 589 ether_input(&ds->ds_if, eh, m); 590 591 s = splimp(); 592 if (IF_QFULL(inq)) { 593 IF_DROP(inq); 594 m_freem(m); 595 } else 596 IF_ENQUEUE(inq, m); 597 splx(s); 598 } 599 /* 600 * Process an ioctl request. 601 */ 602 deioctl(ifp, cmd, data) 603 register struct ifnet *ifp; 604 int cmd; 605 caddr_t data; 606 { 607 register struct ifaddr *ifa = (struct ifaddr *)data; 608 register struct de_softc *ds = &de_softc[ifp->if_unit]; 609 int s = splimp(), error = 0; 610 611 switch (cmd) { 612 613 case SIOCSIFADDR: 614 ifp->if_flags |= IFF_UP; 615 deinit(ifp->if_unit); 616 617 switch (ifa->ifa_addr->sa_family) { 618 #ifdef INET 619 case AF_INET: 620 ((struct arpcom *)ifp)->ac_ipaddr = 621 IA_SIN(ifa)->sin_addr; 622 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 623 break; 624 #endif 625 #ifdef NS 626 case AF_NS: 627 { 628 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 629 630 if (ns_nullhost(*ina)) 631 ina->x_host = *(union ns_host *)(ds->ds_addr); 632 else 633 de_setaddr(ina->x_host.c_host,ifp->if_unit); 634 break; 635 } 636 #endif 637 } 638 break; 639 640 case SIOCSIFFLAGS: 641 if ((ifp->if_flags & IFF_UP) == 0 && 642 ds->ds_flags & DSF_RUNNING) { 643 ((struct dedevice *) 644 (deinfo[ifp->if_unit]->ui_addr))->pclow = 0; 645 DELAY(100); 646 ((struct dedevice *) 647 (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET; 648 ds->ds_flags &= ~DSF_RUNNING; 649 ds->ds_if.if_flags &= ~IFF_OACTIVE; 650 } else if (ifp->if_flags & IFF_UP && 651 (ds->ds_flags & DSF_RUNNING) == 0) 652 deinit(ifp->if_unit); 653 break; 654 655 default: 656 error = EINVAL; 657 } 658 splx(s); 659 return (error); 660 } 661 662 /* 663 * set ethernet address for unit 664 */ 665 de_setaddr(physaddr, unit) 666 u_char *physaddr; 667 int unit; 668 { 669 register struct de_softc *ds = &de_softc[unit]; 670 struct uba_device *ui = deinfo[unit]; 671 register struct dedevice *addr= (struct dedevice *)ui->ui_addr; 672 673 if (! (ds->ds_flags & DSF_RUNNING)) 674 return; 675 676 bcopy((caddr_t) physaddr, (caddr_t) &ds->ds_pcbb.pcbb2, 6); 677 ds->ds_pcbb.pcbb0 = FC_WTPHYAD; 678 addr->pclow = PCSR0_INTE|CMD_GETCMD; 679 if (dewait(ui, "address change") == 0) { 680 ds->ds_flags |= DSF_SETADDR; 681 bcopy((caddr_t) physaddr, (caddr_t) ds->ds_addr, 6); 682 } 683 } 684 685 /* 686 * Await completion of the named function 687 * and check for errors. 688 */ 689 dewait(ui, fn) 690 register struct uba_device *ui; 691 char *fn; 692 { 693 register struct dedevice *addr = (struct dedevice *)ui->ui_addr; 694 register csr0; 695 696 while ((addr->pcsr0 & PCSR0_INTR) == 0) 697 ; 698 csr0 = addr->pcsr0; 699 addr->pchigh = csr0 >> 8; 700 if (csr0 & PCSR0_PCEI) 701 printf("de%d: %s failed, csr0=%b csr1=%b\n", 702 ui->ui_unit, fn, csr0, PCSR0_BITS, 703 addr->pcsr1, PCSR1_BITS); 704 return (csr0 & PCSR0_PCEI); 705 } 706 #endif 707