1 /* $OpenBSD: if_we.c,v 1.5 1998/12/23 00:33:29 aaron Exp $ */ 2 /* $NetBSD: if_we.c,v 1.11 1998/07/05 06:49:14 jonathan Exp $ */ 3 4 /*- 5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 43 * adapters. 44 * 45 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 46 * 47 * Copyright (C) 1993, David Greenman. This software may be used, modified, 48 * copied, distributed, and sold, in both source and binary form provided that 49 * the above copyright and these terms are retained. Under no circumstances is 50 * the author responsible for the proper functioning of this software, nor does 51 * the author assume any responsibility for damages incurred with its use. 52 */ 53 54 /* 55 * Device driver for the Western Digital/SMC 8003 and 8013 series, 56 * and the SMC Elite Ultra (8216). 57 */ 58 59 #include "bpfilter.h" 60 #include "we.h" 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/device.h> 65 #include <sys/socket.h> 66 #include <sys/mbuf.h> 67 #include <sys/syslog.h> 68 69 #include <net/if.h> 70 #include <net/if_dl.h> 71 #include <net/if_types.h> 72 #include <net/if_media.h> 73 74 #ifdef __NetBSD__ 75 #include <net/if_ether.h> 76 #endif 77 78 #ifdef INET 79 #include <netinet/in.h> 80 #include <netinet/in_systm.h> 81 #include <netinet/in_var.h> 82 #include <netinet/ip.h> 83 #ifdef __NetBSD__ 84 #include <netinet/if_inarp.h> 85 #else 86 #include <netinet/if_ether.h> 87 #endif 88 #endif 89 90 #ifdef NS 91 #include <netns/ns.h> 92 #include <netns/ns_if.h> 93 #endif 94 95 #if NBPFILTER > 0 96 #include <net/bpf.h> 97 #include <net/bpfdesc.h> 98 #endif 99 100 #include <machine/bus.h> 101 #include <machine/intr.h> 102 103 #include <dev/isa/isareg.h> 104 #include <dev/isa/isavar.h> 105 106 #include <dev/ic/dp8390reg.h> 107 #include <dev/ic/dp8390var.h> 108 109 #include <dev/isa/if_wereg.h> 110 111 #ifndef __BUS_SPACE_HAS_STREAM_METHODS 112 #define bus_space_read_region_stream_2 bus_space_read_region_2 113 #define bus_space_write_stream_2 bus_space_write_2 114 #define bus_space_write_region_stream_2 bus_space_write_region_2 115 #endif 116 117 struct we_softc { 118 struct dp8390_softc sc_dp8390; 119 120 bus_space_tag_t sc_asict; /* space tag for ASIC */ 121 bus_space_handle_t sc_asich; /* space handle for ASIC */ 122 123 u_int8_t sc_laar_proto; 124 u_int8_t sc_msr_proto; 125 126 u_int8_t sc_type; /* our type */ 127 128 int sc_16bitp; /* are we 16 bit? */ 129 130 void *sc_ih; /* interrupt handle */ 131 }; 132 133 int we_probe __P((struct device *, void *, void *)); 134 void we_attach __P((struct device *, struct device *, void *)); 135 136 struct cfattach we_isa_ca = { 137 sizeof(struct we_softc), we_probe, we_attach 138 }; 139 140 #if NWE_ISAPNP 141 struct cfattach we_isapnp_ca = { 142 sizeof(struct we_softc), we_probe, we_attach 143 }; 144 #endif /* NWE_ISAPNP */ 145 146 #ifdef __NetBSD__ 147 extern struct cfdriver we_cd; 148 #else 149 struct cfdriver we_cd = { 150 NULL, "we", DV_IFNET 151 }; 152 #endif 153 154 const char *we_params __P((bus_space_tag_t, bus_space_handle_t, u_int8_t *, 155 bus_size_t *, int *, int *)); 156 void we_set_media __P((struct we_softc *, int)); 157 158 int we_mediachange __P((struct dp8390_softc *)); 159 void we_mediastatus __P((struct dp8390_softc *, struct ifmediareq *)); 160 161 void we_recv_int __P((struct dp8390_softc *)); 162 void we_init_card __P((struct dp8390_softc *)); 163 int we_write_mbuf __P((struct dp8390_softc *, struct mbuf *, int)); 164 int we_ring_copy __P((struct dp8390_softc *, int, caddr_t, u_short)); 165 void we_read_hdr __P((struct dp8390_softc *, int, struct dp8390_ring *)); 166 int we_test_mem __P((struct dp8390_softc *)); 167 168 __inline void we_readmem __P((struct we_softc *, int, u_int8_t *, int)); 169 170 static const int we_584_irq[] = { 171 9, 3, 5, 7, 10, 11, 15, 4, 172 }; 173 #define NWE_584_IRQ (sizeof(we_584_irq) / sizeof(we_584_irq[0])) 174 175 static const int we_790_irq[] = { 176 IRQUNK, 9, 3, 5, 7, 10, 11, 15, 177 }; 178 #define NWE_790_IRQ (sizeof(we_790_irq) / sizeof(we_790_irq[0])) 179 180 int we_media[] = { 181 IFM_ETHER|IFM_10_2, 182 IFM_ETHER|IFM_10_5, 183 }; 184 #define NWE_MEDIA (sizeof(we_media) / sizeof(we_media[0])) 185 186 /* 187 * Delay needed when switching 16-bit access to shared memory. 188 */ 189 #define WE_DELAY(wsc) delay(3) 190 191 /* 192 * Enable card RAM, and 16-bit access. 193 */ 194 #define WE_MEM_ENABLE(wsc) \ 195 do { \ 196 if ((wsc)->sc_16bitp) \ 197 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 198 WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \ 199 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 200 WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \ 201 WE_DELAY((wsc)); \ 202 } while (0) 203 204 /* 205 * Disable card RAM, and 16-bit access. 206 */ 207 #define WE_MEM_DISABLE(wsc) \ 208 do { \ 209 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 210 WE_MSR, (wsc)->sc_msr_proto); \ 211 if ((wsc)->sc_16bitp) \ 212 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \ 213 WE_LAAR, (wsc)->sc_laar_proto); \ 214 WE_DELAY((wsc)); \ 215 } while (0) 216 217 int 218 we_probe(parent, match, aux) 219 struct device *parent; 220 void *match, *aux; 221 { 222 struct isa_attach_args *ia = aux; 223 struct cfdata *cf = match; 224 bus_space_tag_t asict, memt; 225 bus_space_handle_t asich, memh; 226 bus_size_t memsize; 227 int asich_valid, memh_valid; 228 int i, is790, rv = 0; 229 u_int8_t x, type; 230 231 asict = ia->ia_iot; 232 memt = ia->ia_memt; 233 234 asich_valid = memh_valid = 0; 235 236 /* Disallow wildcarded i/o addresses. */ 237 if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */) 238 return (0); 239 240 /* Disallow wildcarded mem address. */ 241 if (ia->ia_maddr == -1 /* ISACF_IOMEM_DEFAULT */) 242 return (0); 243 244 /* Attempt to map the device. */ 245 if (ia->ia_ioh) 246 asich = ia->ia_ioh; 247 else { 248 if (bus_space_map(asict, ia->ia_iobase, WE_NPORTS, 0, &asich)) 249 goto out; 250 } 251 asich_valid = 1; 252 253 #ifdef TOSH_ETHER 254 bus_space_write_1(asict, asich, WE_MSR, WE_MSR_POW); 255 #endif 256 257 /* 258 * Attempt to do a checksum over the station address PROM. 259 * If it fails, it's probably not a WD/SMC board. There is 260 * a problem with this, though. Some clone WD8003E boards 261 * (e.g. Danpex) won't pass the checksum. In this case, 262 * the checksum byte always seems to be 0. 263 */ 264 for (x = 0, i = 0; i < 8; i++) 265 x += bus_space_read_1(asict, asich, WE_PROM + i); 266 267 if (x != WE_ROM_CHECKSUM_TOTAL) { 268 /* Make sure it's an 8003E clone... */ 269 if (bus_space_read_1(asict, asich, WE_CARD_ID) != 270 WE_TYPE_WD8003E) 271 goto out; 272 273 /* Check the checksum byte. */ 274 if (bus_space_read_1(asict, asich, WE_PROM + 7) != 0) 275 goto out; 276 } 277 278 /* 279 * Reset the card to force it into a known state. 280 */ 281 #ifdef TOSH_ETHER 282 bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST | WE_MSR_POW); 283 #else 284 bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST); 285 #endif 286 delay(100); 287 288 bus_space_write_1(asict, asich, WE_MSR, 289 bus_space_read_1(asict, asich, WE_MSR) & ~WE_MSR_RST); 290 291 /* Wait in case the card is reading it's EEPROM. */ 292 delay(5000); 293 294 /* 295 * Get parameters. 296 */ 297 if (we_params(asict, asich, &type, &memsize, NULL, &is790) == NULL) 298 goto out; 299 300 /* Allow user to override probed value. */ 301 if (ia->ia_msize) 302 memsize = ia->ia_msize; 303 304 /* Attempt to map the memory space. */ 305 if (ia->ia_memh) 306 memh = ia->ia_memh; 307 else { 308 if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh)) 309 goto out; 310 } 311 memh_valid = 1; 312 313 /* 314 * If possible, get the assigned interrupt number from the card 315 * and use it. 316 */ 317 if (is790) { 318 u_int8_t hwr; 319 320 /* Assemble together the encoded interrupt number. */ 321 hwr = bus_space_read_1(asict, asich, WE790_HWR); 322 bus_space_write_1(asict, asich, WE790_HWR, 323 hwr | WE790_HWR_SWH); 324 325 x = bus_space_read_1(asict, asich, WE790_GCR); 326 i = ((x & WE790_GCR_IR2) >> 4) | 327 ((x & (WE790_GCR_IR1|WE790_GCR_IR0)) >> 2); 328 bus_space_write_1(asict, asich, WE790_HWR, 329 hwr & ~WE790_HWR_SWH); 330 331 if (ia->ia_irq != IRQUNK && ia->ia_irq != we_790_irq[i]) 332 printf("%s%d: overriding IRQ %d to %d\n", 333 we_cd.cd_name, cf->cf_unit, ia->ia_irq, 334 we_790_irq[i]); 335 ia->ia_irq = we_790_irq[i]; 336 } else if (type & WE_SOFTCONFIG) { 337 /* Assemble together the encoded interrupt number. */ 338 i = (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_IR2) | 339 ((bus_space_read_1(asict, asich, WE_IRR) & 340 (WE_IRR_IR0 | WE_IRR_IR1)) >> 5); 341 342 if (ia->ia_irq != IRQUNK && ia->ia_irq != we_584_irq[i]) 343 printf("%s%d: overriding IRQ %d to %d\n", 344 we_cd.cd_name, cf->cf_unit, ia->ia_irq, 345 we_584_irq[i]); 346 ia->ia_irq = we_584_irq[i]; 347 } 348 349 /* So, we say we've found it! */ 350 ia->ia_iosize = WE_NPORTS; 351 ia->ia_msize = memsize; 352 rv = 1; 353 354 out: 355 if (asich_valid) 356 bus_space_unmap(asict, asich, WE_NPORTS); 357 if (memh_valid) 358 bus_space_unmap(memt, memh, memsize); 359 return (rv); 360 } 361 362 void 363 we_attach(parent, self, aux) 364 struct device *parent, *self; 365 void *aux; 366 { 367 struct we_softc *wsc = (struct we_softc *)self; 368 struct dp8390_softc *sc = &wsc->sc_dp8390; 369 struct isa_attach_args *ia = aux; 370 bus_space_tag_t nict, asict, memt; 371 bus_space_handle_t nich, asich, memh; 372 const char *typestr; 373 u_int8_t x; 374 int i; 375 376 nict = asict = ia->ia_iot; 377 memt = ia->ia_memt; 378 379 /* Map the device. */ 380 if (ia->ia_ioh) 381 asich = ia->ia_ioh; 382 else if (bus_space_map(asict, ia->ia_iobase, WE_NPORTS, 0, &asich)) { 383 printf(": can't map nic i/o space\n"); 384 return; 385 } 386 387 if (bus_space_subregion(asict, asich, WE_NIC_OFFSET, WE_NIC_NPORTS, 388 &nich)) { 389 printf(": can't subregion i/o space\n"); 390 return; 391 } 392 393 typestr = we_params(asict, asich, &wsc->sc_type, NULL, 394 &wsc->sc_16bitp, &sc->is790); 395 if (typestr == NULL) { 396 printf(": where did the card go?\n"); 397 return; 398 } 399 400 /* 401 * Map memory space. Note we use the size that might have 402 * been overridden by the user. 403 */ 404 if (ia->ia_memh) 405 memh = ia->ia_memh; 406 else if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) { 407 printf(": can't map shared memory\n"); 408 return; 409 } 410 411 /* 412 * Allow user to override 16-bit mode. 8-bit takes precedence. 413 */ 414 if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_16BIT_MODE) 415 wsc->sc_16bitp = 1; 416 if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_8BIT_MODE) 417 wsc->sc_16bitp = 0; 418 419 wsc->sc_asict = asict; 420 wsc->sc_asich = asich; 421 422 sc->sc_regt = nict; 423 sc->sc_regh = nich; 424 425 sc->sc_buft = memt; 426 sc->sc_bufh = memh; 427 428 /* Interface is always enabled. */ 429 sc->sc_enabled = 1; 430 431 /* Registers are linear. */ 432 for (i = 0; i < 16; i++) 433 sc->sc_reg_map[i] = i; 434 435 /* Now we can use the NIC_{GET,PUT}() macros. */ 436 437 printf(": %s (%s-bit)\n", typestr, wsc->sc_16bitp ? "16" : "8"); 438 439 /* Get station address from EEPROM. */ 440 for (i = 0; i < ETHER_ADDR_LEN; i++) 441 #ifdef __NetBSD__ 442 sc->sc_enaddr[i] = bus_space_read_1(asict, asich, WE_PROM + i); 443 #else 444 sc->sc_arpcom.ac_enaddr[i] = 445 bus_space_read_1(asict, asich, WE_PROM + i); 446 #endif 447 448 /* 449 * Set upper address bits and 8/16 bit access to shared memory. 450 */ 451 if (sc->is790) { 452 wsc->sc_laar_proto = 453 bus_space_read_1(asict, asich, WE_LAAR) & 454 ~WE_LAAR_M16EN; 455 bus_space_write_1(asict, asich, WE_LAAR, 456 wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0)); 457 } else if ((wsc->sc_type & WE_SOFTCONFIG) || 458 #ifdef TOSH_ETHER 459 (wsc->sc_type == WE_TYPE_TOSHIBA1) || 460 (wsc->sc_type == WE_TYPE_TOSHIBA4) || 461 #endif 462 (wsc->sc_type == WE_TYPE_WD8013EBT)) { 463 wsc->sc_laar_proto = (ia->ia_maddr >> 19) & WE_LAAR_ADDRHI; 464 if (wsc->sc_16bitp) 465 wsc->sc_laar_proto |= WE_LAAR_L16EN; 466 bus_space_write_1(asict, asich, WE_LAAR, 467 wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0)); 468 } 469 470 /* 471 * Set address and enable interface shared memory. 472 */ 473 if (sc->is790) { 474 /* XXX MAGIC CONSTANTS XXX */ 475 x = bus_space_read_1(asict, asich, 0x04); 476 bus_space_write_1(asict, asich, 0x04, x | 0x80); 477 bus_space_write_1(asict, asich, 0x0b, 478 ((ia->ia_maddr >> 13) & 0x0f) | 479 ((ia->ia_maddr >> 11) & 0x40) | 480 (bus_space_read_1(asict, asich, 0x0b) & 0xb0)); 481 bus_space_write_1(asict, asich, 0x04, x); 482 wsc->sc_msr_proto = 0x00; 483 sc->cr_proto = 0x00; 484 } else { 485 #ifdef TOSH_ETHER 486 if (wsc->sc_type == WE_TYPE_TOSHIBA1 || 487 wsc->sc_type == WE_TYPE_TOSHIBA4) { 488 bus_space_write_1(asict, asich, WE_MSR + 1, 489 ((ia->ia_maddr >> 8) & 0xe0) | 0x04); 490 bus_space_write_1(asict, asich, WE_MSR + 2, 491 ((ia->ia_maddr >> 16) & 0x0f)); 492 wsc->sc_msr_proto = WE_MSR_POW; 493 } else 494 #endif 495 wsc->sc_msr_proto = (ia->ia_maddr >> 13) & 496 WE_MSR_ADDR; 497 498 sc->cr_proto = ED_CR_RD2; 499 } 500 501 bus_space_write_1(asict, asich, WE_MSR, 502 wsc->sc_msr_proto | WE_MSR_MENB); 503 WE_DELAY(wsc); 504 505 /* 506 * DCR gets: 507 * 508 * FIFO threshold to 8, No auto-init Remote DMA, 509 * byte order=80x86. 510 * 511 * 16-bit cards also get word-wide DMA transfers. 512 */ 513 sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | 514 (wsc->sc_16bitp ? ED_DCR_WTS : 0); 515 516 sc->test_mem = we_test_mem; 517 sc->ring_copy = we_ring_copy; 518 sc->write_mbuf = we_write_mbuf; 519 sc->read_hdr = we_read_hdr; 520 sc->recv_int = we_recv_int; 521 522 sc->sc_mediachange = we_mediachange; 523 sc->sc_mediastatus = we_mediastatus; 524 525 sc->mem_start = 0; 526 sc->mem_size = ia->ia_msize; 527 528 sc->sc_flags = self->dv_cfdata->cf_flags; 529 530 /* Do generic parts of attach. */ 531 if (wsc->sc_type & WE_SOFTCONFIG) { 532 int defmedia = IFM_ETHER; 533 534 if (sc->is790) { 535 x = bus_space_read_1(asict, asich, WE790_HWR); 536 bus_space_write_1(asict, asich, WE790_HWR, 537 x | WE790_HWR_SWH); 538 if (bus_space_read_1(asict, asich, WE790_GCR) & 539 WE790_GCR_GPOUT) 540 defmedia |= IFM_10_2; 541 else 542 defmedia |= IFM_10_5; 543 bus_space_write_1(asict, asich, WE790_HWR, 544 x & ~WE790_HWR_SWH); 545 } else { 546 x = bus_space_read_1(asict, asich, WE_IRR); 547 if (x & WE_IRR_OUT2) 548 defmedia |= IFM_10_2; 549 else 550 defmedia |= IFM_10_5; 551 } 552 i = dp8390_config(sc, we_media, NWE_MEDIA, defmedia); 553 } else 554 i = dp8390_config(sc, NULL, 0, 0); 555 if (i) { 556 printf("%s: configuration failed\n", sc->sc_dev.dv_xname); 557 return; 558 } 559 560 /* 561 * Disable 16-bit access to shared memory - we leave it disabled 562 * so that: 563 * 564 * (1) machines reboot properly when the board is set to 565 * 16-bit mode and there are conflicting 8-bit devices 566 * within the same 128k address space as this board's 567 * shared memory, and 568 * 569 * (2) so that other 8-bit devices with shared memory 570 * in this same 128k address space will work. 571 */ 572 WE_MEM_DISABLE(wsc); 573 574 /* 575 * Enable the configured interrupt. 576 */ 577 if (sc->is790) 578 bus_space_write_1(asict, asich, WE790_ICR, 579 bus_space_read_1(asict, asich, WE790_ICR) | 580 WE790_ICR_EIL); 581 else if (wsc->sc_type & WE_SOFTCONFIG) 582 bus_space_write_1(asict, asich, WE_IRR, 583 bus_space_read_1(asict, asich, WE_IRR) | WE_IRR_IEN); 584 else if (ia->ia_irq == IRQUNK) { 585 printf("%s: can't wildcard IRQ on a %s\n", 586 sc->sc_dev.dv_xname, typestr); 587 return; 588 } 589 590 /* Establish interrupt handler. */ 591 wsc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 592 IPL_NET, dp8390_intr, sc, sc->sc_dev.dv_xname); 593 if (wsc->sc_ih == NULL) 594 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname); 595 } 596 597 int 598 we_test_mem(sc) 599 struct dp8390_softc *sc; 600 { 601 struct we_softc *wsc = (struct we_softc *)sc; 602 bus_space_tag_t memt = sc->sc_buft; 603 bus_space_handle_t memh = sc->sc_bufh; 604 bus_size_t memsize = sc->mem_size; 605 int i; 606 607 if (wsc->sc_16bitp) 608 bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1); 609 else 610 bus_space_set_region_1(memt, memh, 0, 0, memsize); 611 612 if (wsc->sc_16bitp) { 613 for (i = 0; i < memsize; i += 2) { 614 if (bus_space_read_2(memt, memh, i) != 0) 615 goto fail; 616 } 617 } else { 618 for (i = 0; i < memsize; i++) { 619 if (bus_space_read_1(memt, memh, i) != 0) 620 goto fail; 621 } 622 } 623 624 return (0); 625 626 fail: 627 printf("%s: failed to clear shared memory at offset 0x%x\n", 628 sc->sc_dev.dv_xname, i); 629 WE_MEM_DISABLE(wsc); 630 return (1); 631 } 632 633 /* 634 * Given a NIC memory source address and a host memory destination address, 635 * copy 'len' from NIC to host using shared memory. The 'len' is rounded 636 * up to a word - ok as long as mbufs are word-sized. 637 */ 638 __inline void 639 we_readmem(wsc, from, to, len) 640 struct we_softc *wsc; 641 int from; 642 u_int8_t *to; 643 int len; 644 { 645 bus_space_tag_t memt = wsc->sc_dp8390.sc_buft; 646 bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh; 647 648 if (len & 1) 649 ++len; 650 651 if (wsc->sc_16bitp) 652 bus_space_read_region_stream_2(memt, memh, from, 653 (u_int16_t *)to, len >> 1); 654 else 655 bus_space_read_region_1(memt, memh, from, 656 to, len); 657 } 658 659 int 660 we_write_mbuf(sc, m, buf) 661 struct dp8390_softc *sc; 662 struct mbuf *m; 663 int buf; 664 { 665 struct we_softc *wsc = (struct we_softc *)sc; 666 bus_space_tag_t memt = wsc->sc_dp8390.sc_buft; 667 bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh; 668 u_int8_t *data, savebyte[2]; 669 int savelen, len, leftover; 670 #ifdef DIAGNOSTIC 671 u_int8_t *lim; 672 #endif 673 674 savelen = m->m_pkthdr.len; 675 676 WE_MEM_ENABLE(wsc); 677 678 /* 679 * 8-bit boards are simple; no alignment tricks are necessary. 680 */ 681 if (wsc->sc_16bitp == 0) { 682 for (; m != NULL; buf += m->m_len, m = m->m_next) 683 bus_space_write_region_1(memt, memh, 684 buf, mtod(m, u_int8_t *), m->m_len); 685 goto out; 686 } 687 688 /* Start out with no leftover data. */ 689 leftover = 0; 690 savebyte[0] = savebyte[1] = 0; 691 692 for (; m != NULL; m = m->m_next) { 693 len = m->m_len; 694 if (len == 0) 695 continue; 696 data = mtod(m, u_int8_t *); 697 #ifdef DIAGNOSTIC 698 lim = data + len; 699 #endif 700 while (len > 0) { 701 if (leftover) { 702 /* 703 * Data left over (from mbuf or realignment). 704 * Buffer the next byte, and write it and 705 * the leftover data out. 706 */ 707 savebyte[1] = *data++; 708 len--; 709 bus_space_write_stream_2(memt, memh, buf, 710 *(u_int16_t *)savebyte); 711 buf += 2; 712 leftover = 0; 713 #ifdef i386 714 #define ALIGNED_POINTER(p,t) 1 715 #endif 716 #ifdef alpha 717 #define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) 718 #endif 719 } else if (ALIGNED_POINTER(data, u_int16_t) == 0) { 720 /* 721 * Unaligned dta; buffer the next byte. 722 */ 723 savebyte[0] = *data++; 724 len--; 725 leftover = 1; 726 } else { 727 /* 728 * Aligned data; output contiguous words as 729 * much as we can, then buffer the remaining 730 * byte, if any. 731 */ 732 leftover = len & 1; 733 len &= ~1; 734 bus_space_write_region_stream_2(memt, memh, 735 buf, (u_int16_t *)data, len >> 1); 736 data += len; 737 buf += len; 738 if (leftover) 739 savebyte[0] = *data++; 740 len = 0; 741 } 742 } 743 if (len < 0) 744 panic("we_write_mbuf: negative len"); 745 #ifdef DIAGNOSTIC 746 if (data != lim) 747 panic("we_write_mbuf: data != lim"); 748 #endif 749 } 750 if (leftover) { 751 savebyte[1] = 0; 752 bus_space_write_stream_2(memt, memh, buf, 753 *(u_int16_t *)savebyte); 754 } 755 756 out: 757 WE_MEM_DISABLE(wsc); 758 759 return (savelen); 760 } 761 762 int 763 we_ring_copy(sc, src, dst, amount) 764 struct dp8390_softc *sc; 765 int src; 766 caddr_t dst; 767 u_short amount; 768 { 769 struct we_softc *wsc = (struct we_softc *)sc; 770 u_short tmp_amount; 771 772 /* Does copy wrap to lower addr in ring buffer? */ 773 if (src + amount > sc->mem_end) { 774 tmp_amount = sc->mem_end - src; 775 776 /* Copy amount up to end of NIC memory. */ 777 we_readmem(wsc, src, dst, tmp_amount); 778 779 amount -= tmp_amount; 780 src = sc->mem_ring; 781 dst += tmp_amount; 782 } 783 784 we_readmem(wsc, src, dst, amount); 785 786 return (src + amount); 787 } 788 789 void 790 we_read_hdr(sc, packet_ptr, packet_hdrp) 791 struct dp8390_softc *sc; 792 int packet_ptr; 793 struct dp8390_ring *packet_hdrp; 794 { 795 struct we_softc *wsc = (struct we_softc *)sc; 796 797 we_readmem(wsc, packet_ptr, (u_int8_t *)packet_hdrp, 798 sizeof(struct dp8390_ring)); 799 #if BYTE_ORDER == BIG_ENDIAN 800 packet_hdrp->count = swap16(packet_hdrp->count); 801 #endif 802 } 803 804 void 805 we_recv_int(sc) 806 struct dp8390_softc *sc; 807 { 808 struct we_softc *wsc = (struct we_softc *)sc; 809 810 WE_MEM_ENABLE(wsc); 811 dp8390_rint(sc); 812 WE_MEM_DISABLE(wsc); 813 } 814 815 int 816 we_mediachange(sc) 817 struct dp8390_softc *sc; 818 { 819 820 /* 821 * Current media is already set up. Just reset the interface 822 * to let the new value take hold. The new media will be 823 * set up in we_init_card() called via dp8390_init(). 824 */ 825 dp8390_reset(sc); 826 return (0); 827 } 828 829 void 830 we_mediastatus(sc, ifmr) 831 struct dp8390_softc *sc; 832 struct ifmediareq *ifmr; 833 { 834 struct ifmedia *ifm = &sc->sc_media; 835 836 /* 837 * The currently selected media is always the active media. 838 */ 839 ifmr->ifm_active = ifm->ifm_cur->ifm_media; 840 } 841 842 void 843 we_init_card(sc) 844 struct dp8390_softc *sc; 845 { 846 struct we_softc *wsc = (struct we_softc *)sc; 847 struct ifmedia *ifm = &sc->sc_media; 848 849 we_set_media(wsc, ifm->ifm_cur->ifm_media); 850 } 851 852 void 853 we_set_media(wsc, media) 854 struct we_softc *wsc; 855 int media; 856 { 857 struct dp8390_softc *sc = &wsc->sc_dp8390; 858 bus_space_tag_t asict = wsc->sc_asict; 859 bus_space_handle_t asich = wsc->sc_asich; 860 u_int8_t hwr, gcr, irr; 861 862 if (sc->is790) { 863 hwr = bus_space_read_1(asict, asich, WE790_HWR); 864 bus_space_write_1(asict, asich, WE790_HWR, 865 hwr | WE790_HWR_SWH); 866 gcr = bus_space_read_1(asict, asich, WE790_GCR); 867 if (IFM_SUBTYPE(media) == IFM_10_2) 868 gcr |= WE790_GCR_GPOUT; 869 else 870 gcr &= ~WE790_GCR_GPOUT; 871 bus_space_write_1(asict, asich, WE790_GCR, 872 gcr | WE790_GCR_LIT); 873 bus_space_write_1(asict, asich, WE790_HWR, 874 hwr & ~WE790_HWR_SWH); 875 return; 876 } 877 878 irr = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR); 879 if (IFM_SUBTYPE(media) == IFM_10_2) 880 irr |= WE_IRR_OUT2; 881 else 882 irr &= ~WE_IRR_OUT2; 883 bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE_IRR, irr); 884 } 885 886 const char * 887 we_params(asict, asich, typep, memsizep, is16bitp, is790p) 888 bus_space_tag_t asict; 889 bus_space_handle_t asich; 890 u_int8_t *typep; 891 bus_size_t *memsizep; 892 int *is16bitp, *is790p; 893 { 894 const char *typestr; 895 bus_size_t memsize; 896 int is16bit, is790; 897 u_int8_t type; 898 899 memsize = 8192; 900 is16bit = is790 = 0; 901 902 type = bus_space_read_1(asict, asich, WE_CARD_ID); 903 switch (type) { 904 case WE_TYPE_WD8003S: 905 typestr = "WD8003S"; 906 break; 907 case WE_TYPE_WD8003E: 908 typestr = "WD8003E"; 909 break; 910 case WE_TYPE_WD8003EB: 911 typestr = "WD8003EB"; 912 break; 913 case WE_TYPE_WD8003W: 914 typestr = "WD8003W"; 915 break; 916 case WE_TYPE_WD8013EBT: 917 typestr = "WD8013EBT"; 918 memsize = 16384; 919 is16bit = 1; 920 break; 921 case WE_TYPE_WD8013W: 922 typestr = "WD8013W"; 923 memsize = 16384; 924 is16bit = 1; 925 break; 926 case WE_TYPE_WD8013EP: /* also WD8003EP */ 927 if (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) { 928 is16bit = 1; 929 memsize = 16384; 930 typestr = "WD8013EP"; 931 } else 932 typestr = "WD8003EP"; 933 break; 934 case WE_TYPE_WD8013WC: 935 typestr = "WD8013WC"; 936 memsize = 16384; 937 is16bit = 1; 938 break; 939 case WE_TYPE_WD8013EBP: 940 typestr = "WD8013EBP"; 941 memsize = 16384; 942 is16bit = 1; 943 break; 944 case WE_TYPE_WD8013EPC: 945 typestr = "WD8013EPC"; 946 memsize = 16384; 947 is16bit = 1; 948 break; 949 case WE_TYPE_SMC8216C: 950 case WE_TYPE_SMC8216T: 951 { 952 u_int8_t hwr; 953 954 typestr = (type == WE_TYPE_SMC8216C) ? 955 "SMC8216/SMC8216C" : "SMC8216T"; 956 957 hwr = bus_space_read_1(asict, asich, WE790_HWR); 958 bus_space_write_1(asict, asich, WE790_HWR, 959 hwr | WE790_HWR_SWH); 960 switch (bus_space_read_1(asict, asich, WE790_RAR) & 961 WE790_RAR_SZ64) { 962 case WE790_RAR_SZ64: 963 memsize = 65536; 964 break; 965 case WE790_RAR_SZ32: 966 memsize = 32768; 967 break; 968 case WE790_RAR_SZ16: 969 memsize = 16384; 970 break; 971 case WE790_RAR_SZ8: 972 /* 8216 has 16K shared mem -- 8416 has 8K */ 973 typestr = (type == WE_TYPE_SMC8216C) ? 974 "SMC8416C/SMC8416BT" : "SMC8416T"; 975 memsize = 8192; 976 break; 977 } 978 bus_space_write_1(asict, asich, WE790_HWR, hwr); 979 980 is16bit = 1; 981 is790 = 1; 982 break; 983 } 984 #ifdef TOSH_ETHER 985 case WE_TYPE_TOSHIBA1: 986 typestr = "Toshiba1"; 987 memsize = 32768; 988 is16bit = 1; 989 break; 990 case WE_TYPE_TOSHIBA4: 991 typestr = "Toshiba4"; 992 memsize = 32768; 993 is16bit = 1; 994 break; 995 #endif 996 default: 997 /* Not one we recognize. */ 998 return (NULL); 999 } 1000 1001 /* 1002 * Make some adjustments to initial values depending on what is 1003 * found in the ICR. 1004 */ 1005 if (is16bit && (type != WE_TYPE_WD8013EBT) && 1006 #ifdef TOSH_ETHER 1007 (type != WE_TYPE_TOSHIBA1 && type != WE_TYPE_TOSHIBA4) && 1008 #endif 1009 (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) == 0) { 1010 is16bit = 0; 1011 memsize = 8192; 1012 } 1013 1014 #ifdef WE_DEBUG 1015 { 1016 int i; 1017 1018 printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, " 1019 "memsize = %d\n", type, typestr, is16bit, memsize); 1020 for (i = 0; i < 8; i++) 1021 printf(" %d -> 0x%x\n", i, 1022 bus_space_read_1(asict, asich, i)); 1023 } 1024 #endif 1025 1026 if (typep != NULL) 1027 *typep = type; 1028 if (memsizep != NULL) 1029 *memsizep = memsize; 1030 if (is16bitp != NULL) 1031 *is16bitp = is16bit; 1032 if (is790p != NULL) 1033 *is790p = is790; 1034 return (typestr); 1035 } 1036