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