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