35/* 36 * Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R 37 * Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda. 38 * 39 * These cards use National Semiconductor DP83934AVQB as Ethernet Controller 40 * and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM. 41 */ 42 43/* 44 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki. 45 */ 46 47#include <sys/param.h> 48#include <sys/systm.h> 49#include <sys/protosw.h> 50#include <sys/socket.h> 51 52#include <net/ethernet.h> 53#include <net/if.h> 54#include <net/if_arp.h> 55#include <net/if_media.h> 56 57#ifdef INET 58#include <netinet/in.h> 59#include <netinet/in_systm.h> 60#include <netinet/in_var.h> 61#include <netinet/ip.h> 62#include <netinet/if_inarp.h> 63#endif 64 65 66#include <sys/bus.h> 67#include <machine/bus.h> 68 69#include <dev/snc/dp83932reg.h> 70#include <dev/snc/dp83932var.h> 71#include <dev/snc/if_sncreg.h> 72#include <dev/snc/dp83932subr.h> 73 74integrate u_int16_t snc_nec16_select_bank 75 (struct snc_softc *, u_int32_t, u_int32_t); 76 77/* 78 * Interface exists: make available by filling in network interface 79 * record. System will initialize the interface when it is ready 80 * to accept packets. 81 */ 82int 83sncsetup(sc, lladdr) 84 struct snc_softc *sc; 85 u_int8_t *lladdr; 86{ 87 u_int32_t p, pp; 88 int i; 89 int offset; 90 91 /* 92 * Put the pup in reset mode (sncinit() will fix it later), 93 * stop the timer, disable all interrupts and clear any interrupts. 94 */ 95 NIC_PUT(sc, SNCR_CR, CR_STP); 96 wbflush(); 97 NIC_PUT(sc, SNCR_CR, CR_RST); 98 wbflush(); 99 NIC_PUT(sc, SNCR_IMR, 0); 100 wbflush(); 101 NIC_PUT(sc, SNCR_ISR, ISR_ALL); 102 wbflush(); 103 104 /* 105 * because the SONIC is basically 16bit device it 'concatenates' 106 * a higher buffer address to a 16 bit offset--this will cause wrap 107 * around problems near the end of 64k !! 108 */ 109 p = pp = 0; 110 111 for (i = 0; i < NRRA; i++) { 112 sc->v_rra[i] = SONIC_GETDMA(p); 113 p += RXRSRC_SIZE(sc); 114 } 115 sc->v_rea = SONIC_GETDMA(p); 116 117 p = SOALIGN(sc, p); 118 119 sc->v_cda = SONIC_GETDMA(p); 120 p += CDA_SIZE(sc); 121 122 p = SOALIGN(sc, p); 123 124 for (i = 0; i < NTDA; i++) { 125 struct mtd *mtdp = &sc->mtda[i]; 126 mtdp->mtd_vtxp = SONIC_GETDMA(p); 127 p += TXP_SIZE(sc); 128 } 129 130 p = SOALIGN(sc, p); 131 132 if ((p - pp) > NBPG) { 133 device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" 134 "TDA (%ld) > NBPG (%d). Punt!\n", 135 (ulong)sc->v_cda - (ulong)sc->v_rra[0], 136 (ulong)sc->mtda[0].mtd_vtxp - (ulong)sc->v_cda, 137 (ulong)p - (ulong)sc->mtda[0].mtd_vtxp, 138 NBPG); 139 return(1); 140 } 141 142 p = pp + NBPG; 143 pp = p; 144 145 sc->sc_nrda = NBPG / RXPKT_SIZE(sc); 146 sc->v_rda = SONIC_GETDMA(p); 147 148 p = pp + NBPG; 149 150 for (i = 0; i < NRBA; i++) { 151 sc->rbuf[i] = p; 152 p += NBPG; 153 } 154 155 pp = p; 156 offset = TXBSIZE; 157 for (i = 0; i < NTDA; i++) { 158 struct mtd *mtdp = &sc->mtda[i]; 159 160 mtdp->mtd_vbuf = SONIC_GETDMA(p); 161 offset += TXBSIZE; 162 if (offset < NBPG) { 163 p += TXBSIZE; 164 } else { 165 p = pp + NBPG; 166 pp = p; 167 offset = TXBSIZE; 168 } 169 } 170 171 return (0); 172} 173 174/* 175 * miscellaneous NEC/SONIC detect functions. 176 */ 177 178/* 179 * check if a specified irq is acceptable. 180 */ 181u_int8_t 182snc_nec16_validate_irq(irq) 183 int irq; 184{ 185 const u_int8_t encoded_irq[16] = { 186 -1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1 187 }; 188 189 return encoded_irq[irq]; 190} 191 192/* 193 * specify irq to board. 194 */ 195int 196snc_nec16_register_irq(sc, irq) 197 struct snc_softc *sc; 198 int irq; 199{ 200 bus_space_tag_t iot = sc->sc_iot; 201 bus_space_handle_t ioh = sc->sc_ioh; 202 u_int8_t encoded_irq; 203 204 encoded_irq = snc_nec16_validate_irq(irq); 205 if (encoded_irq == (u_int8_t) -1) { 206 printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq); 207 return 0; 208 } 209 210 /* select SNECR_IRQSEL register */ 211 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL); 212 /* write encoded irq value */ 213 bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq); 214 215 return 1; 216} 217 218/* 219 * check if a specified memory base address is acceptable. 220 */ 221int 222snc_nec16_validate_mem(maddr) 223 int maddr; 224{ 225 226 /* Check on Normal mode with max range, only */ 227 if ((maddr & ~0x1E000) != 0xC0000) { 228 printf("snc_nec16_validate_mem: " 229 "unsupported window base (0x%x)\n", maddr); 230 return 0; 231 } 232 233 return 1; 234} 235 236/* 237 * specify memory base address to board and map to first bank. 238 */ 239int 240snc_nec16_register_mem(sc, maddr) 241 struct snc_softc *sc; 242 int maddr; 243{ 244 bus_space_tag_t iot = sc->sc_iot; 245 bus_space_handle_t ioh = sc->sc_ioh; 246 247 if (snc_nec16_validate_mem(maddr) == 0) 248 return 0; 249 250 /* select SNECR_MEMSEL register */ 251 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL); 252 /* write encoded memory base select value */ 253 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr)); 254 255 /* 256 * set current bank to 0 (bottom) and map 257 */ 258 /* select SNECR_MEMBS register */ 259 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 260 /* select new bank */ 261 bus_space_write_1(iot, ioh, SNEC_CTRLB, 262 SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN); 263 /* set current bank to 0 */ 264 sc->curbank = 0; 265 266 return 1; 267} 268 269int 270snc_nec16_check_memory(iot, ioh, memt, memh) 271 bus_space_tag_t iot; 272 bus_space_handle_t ioh; 273 bus_space_tag_t memt; 274 bus_space_handle_t memh; 275{ 276 u_int16_t val; 277 int i, j; 278 279 val = 0; 280 for (i = 0; i < SNEC_NBANK; i++) { 281 /* select new bank */ 282 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 283 bus_space_write_1(iot, ioh, SNEC_CTRLB, 284 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 285 286 /* write test pattern */ 287 for (j = 0; j < SNEC_NMEMS / 2; j++) { 288 bus_space_write_2(memt, memh, j * 2, val + j); 289 } 290 val += 0x1000; 291 } 292 293 val = 0; 294 for (i = 0; i < SNEC_NBANK; i++) { 295 /* select new bank */ 296 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 297 bus_space_write_1(iot, ioh, SNEC_CTRLB, 298 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 299 300 /* read test pattern */ 301 for (j = 0; j < SNEC_NMEMS / 2; j++) { 302 if (bus_space_read_2(memt, memh, j * 2) != val + j) 303 break; 304 } 305 306 if (j < SNEC_NMEMS / 2) { 307 printf("snc_nec16_check_memory: " 308 "memory check failed at 0x%04x%04x" 309 "val 0x%04x != expected 0x%04x\n", i, j, 310 bus_space_read_2(memt, memh, j * 2), 311 val + j); 312 return 0; 313 } 314 val += 0x1000; 315 } 316 317 /* zero clear mem */ 318 for (i = 0; i < SNEC_NBANK; i++) { 319 /* select new bank */ 320 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 321 bus_space_write_1(iot, ioh, SNEC_CTRLB, 322 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 323 324 bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2); 325 } 326 327 /* again read test if these are 0 */ 328 for (i = 0; i < SNEC_NBANK; i++) { 329 /* select new bank */ 330 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 331 bus_space_write_1(iot, ioh, SNEC_CTRLB, 332 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 333 334 /* check if cleared */ 335 for (j = 0; j < SNEC_NMEMS; j += 2) { 336 if (bus_space_read_2(memt, memh, j) != 0) 337 break; 338 } 339 340 if (j != SNEC_NMEMS) { 341 printf("snc_nec16_check_memory: " 342 "memory zero clear failed at 0x%04x%04x\n", i, j); 343 return 0; 344 } 345 } 346 347 return 1; 348} 349 350int 351snc_nec16_detectsubr(iot, ioh, memt, memh, irq, maddr, type) 352 bus_space_tag_t iot; 353 bus_space_handle_t ioh; 354 bus_space_tag_t memt; 355 bus_space_handle_t memh; 356 int irq; 357 int maddr; 358 u_int8_t type; 359{ 360 u_int16_t cr; 361 u_int8_t ident; 362 int rv = 0; 363 364 if (snc_nec16_validate_irq(irq) == (u_int8_t) -1) 365 return 0; 366 /* XXX: maddr already checked */ 367 if (snc_nec16_validate_mem(maddr) == 0) 368 return 0; 369 370 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT); 371 ident = bus_space_read_1(iot, ioh, SNEC_CTRLB); 372 if (ident == 0xff || ident == 0x00) { 373 /* not found */ 374 return 0; 375 } 376 377 switch (type) { 378 case SNEC_TYPE_LEGACY: 379 rv = (ident == SNECR_IDENT_LEGACY_CBUS); 380 break; 381 case SNEC_TYPE_PNP: 382 rv = ((ident == SNECR_IDENT_PNP_CBUS) || 383 (ident == SNECR_IDENT_PNP_PCMCIABUS)); 384 break; 385 default: 386 break; 387 } 388 389 if (rv == 0) { 390 printf("snc_nec16_detectsubr: parent bus mismatch\n"); 391 return 0; 392 } 393 394 /* select SONIC register SNCR_CR */ 395 bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR); 396 bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST); 397 delay(400); 398 399 cr = bus_space_read_2(iot, ioh, SNEC_CTRL); 400 if (cr != (CR_RXDIS | CR_STP | CR_RST)) { 401#ifdef DIAGNOSTIC 402 printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n", 403 cr); 404#endif 405 return 0; 406 } 407 408 if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0) 409 return 0; 410 411 return 1; 412} 413 414/* XXX */ 415#define SNC_VENDOR_NEC 0x00004c 416#define SNC_NEC_SERIES_LEGACY_CBUS 0xa5 417#define SNC_NEC_SERIES_PNP_PCMCIA 0xd5 418#define SNC_NEC_SERIES_PNP_PCMCIA2 0x6d /* XXX */ 419#define SNC_NEC_SERIES_PNP_CBUS 0x0d 420#define SNC_NEC_SERIES_PNP_CBUS2 0x3d 421 422u_int8_t * 423snc_nec16_detect_type(myea) 424 u_int8_t *myea; 425{ 426 u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2]; 427 u_int8_t series = myea[3]; 428 u_int8_t type = myea[4] & 0x80; 429 u_int8_t *typestr; 430 431 switch (vendor) { 432 case SNC_VENDOR_NEC: 433 switch (series) { 434 case SNC_NEC_SERIES_LEGACY_CBUS: 435 if (type) 436 typestr = "NEC PC-9801-84"; 437 else 438 typestr = "NEC PC-9801-83"; 439 break; 440 case SNC_NEC_SERIES_PNP_CBUS: 441 case SNC_NEC_SERIES_PNP_CBUS2: 442 if (type) 443 typestr = "NEC PC-9801-104"; 444 else 445 typestr = "NEC PC-9801-103"; 446 break; 447 case SNC_NEC_SERIES_PNP_PCMCIA: 448 case SNC_NEC_SERIES_PNP_PCMCIA2: 449 /* XXX: right ? */ 450 if (type) 451 typestr = "NEC PC-9801N-J02R"; 452 else 453 typestr = "NEC PC-9801N-J02"; 454 break; 455 default: 456 typestr = "NEC unknown (PC-9801N-25?)"; 457 break; 458 } 459 break; 460 default: 461 typestr = "unknown (3rd vendor?)"; 462 break; 463 } 464 465 return typestr; 466} 467 468int 469snc_nec16_get_enaddr(iot, ioh, myea) 470 bus_space_tag_t iot; 471 bus_space_handle_t ioh; 472 u_int8_t *myea; 473{ 474 u_int8_t eeprom[SNEC_EEPROM_SIZE]; 475 u_int8_t rom_sum, sum = 0x00; 476 int i; 477 478 snc_nec16_read_eeprom(iot, ioh, eeprom); 479 480 for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) { 481 sum = sum ^ eeprom[i]; 482 } 483 484 rom_sum = eeprom[SNEC_EEPROM_CKSUM]; 485 486 if (sum != rom_sum) { 487 printf("snc_nec16_get_enaddr: " 488 "checksum mismatch; calculated %02x != read %02x", 489 sum, rom_sum); 490 return 0; 491 } 492 493 for (i = 0; i < ETHER_ADDR_LEN; i++) 494 myea[i] = eeprom[SNEC_EEPROM_SA0 + i]; 495 496 return 1; 497} 498 499/* 500 * read from NEC/SONIC NIC register. 501 */ 502u_int16_t 503snc_nec16_nic_get(sc, reg) 504 struct snc_softc *sc; 505 u_int8_t reg; 506{ 507 u_int16_t val; 508 509 /* select SONIC register */ 510 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg); 511 val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL); 512 513 return val; 514} 515 516/* 517 * write to NEC/SONIC NIC register. 518 */ 519void 520snc_nec16_nic_put(sc, reg, val) 521 struct snc_softc *sc; 522 u_int8_t reg; 523 u_int16_t val; 524{ 525 526 /* select SONIC register */ 527 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg); 528 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val); 529} 530 531 532/* 533 * select memory bank and map 534 * where exists specified (internal buffer memory) offset. 535 */ 536integrate u_int16_t 537snc_nec16_select_bank(sc, base, offset) 538 struct snc_softc *sc; 539 u_int32_t base; 540 u_int32_t offset; 541{ 542 bus_space_tag_t iot = sc->sc_iot; 543 bus_space_handle_t ioh = sc->sc_ioh; 544 u_int8_t bank; 545 u_int16_t noffset; 546 547 /* bitmode is fixed to 16 bit. */ 548 bank = (base + offset * 2) >> 13; 549 noffset = (base + offset * 2) & (SNEC_NMEMS - 1); 550 551#ifdef SNCDEBUG 552 if (noffset % 2) { 553 device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n", 554 noffset); 555 } 556#endif /* SNCDEBUG */ 557 558 if (sc->curbank != bank) { 559 /* select SNECR_MEMBS register */ 560 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 561 /* select new bank */ 562 bus_space_write_1(iot, ioh, SNEC_CTRLB, 563 SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN); 564 /* update current bank */ 565 sc->curbank = bank; 566 } 567 568 return noffset; 569} 570 571/* 572 * write to SONIC descriptors. 573 */ 574void 575snc_nec16_writetodesc(sc, base, offset, val) 576 struct snc_softc *sc; 577 u_int32_t base; 578 u_int32_t offset; 579 u_int16_t val; 580{ 581 bus_space_tag_t memt = sc->sc_memt; 582 bus_space_handle_t memh = sc->sc_memh; 583 u_int16_t noffset; 584 585 noffset = snc_nec16_select_bank(sc, base, offset); 586 587 bus_space_write_2(memt, memh, noffset, val); 588} 589 590/* 591 * read from SONIC descriptors. 592 */ 593u_int16_t 594snc_nec16_readfromdesc(sc, base, offset) 595 struct snc_softc *sc; 596 u_int32_t base; 597 u_int32_t offset; 598{ 599 bus_space_tag_t memt = sc->sc_memt; 600 bus_space_handle_t memh = sc->sc_memh; 601 u_int16_t noffset; 602 603 noffset = snc_nec16_select_bank(sc, base, offset); 604 605 return bus_space_read_2(memt, memh, noffset); 606} 607 608/* 609 * read from SONIC data buffer. 610 */ 611void 612snc_nec16_copyfrombuf(sc, dst, offset, size) 613 struct snc_softc *sc; 614 void *dst; 615 u_int32_t offset; 616 size_t size; 617{ 618 bus_space_tag_t memt = sc->sc_memt; 619 bus_space_handle_t memh = sc->sc_memh; 620 u_int16_t noffset; 621 u_int8_t* bptr = dst; 622 623 noffset = snc_nec16_select_bank(sc, offset, 0); 624 625 /* XXX: should check if offset + size < 0x2000. */ 626 627 bus_space_barrier(memt, memh, noffset, size, 628 BUS_SPACE_BARRIER_READ); 629 630 if (size > 3) { 631 if (noffset & 3) { 632 size_t asize = 4 - (noffset & 3); 633 634 bus_space_read_region_1(memt, memh, noffset, 635 bptr, asize); 636 bptr += asize; 637 noffset += asize; 638 size -= asize; 639 } 640 bus_space_read_region_4(memt, memh, noffset, 641 (u_int32_t *) bptr, size >> 2); 642 bptr += size & ~3; 643 noffset += size & ~3; 644 size &= 3; 645 } 646 if (size) 647 bus_space_read_region_1(memt, memh, noffset, bptr, size); 648} 649 650/* 651 * write to SONIC data buffer. 652 */ 653void 654snc_nec16_copytobuf(sc, src, offset, size) 655 struct snc_softc *sc; 656 void *src; 657 u_int32_t offset; 658 size_t size; 659{ 660 bus_space_tag_t memt = sc->sc_memt; 661 bus_space_handle_t memh = sc->sc_memh; 662 u_int16_t noffset, onoffset; 663 size_t osize = size; 664 u_int8_t* bptr = src; 665 666 noffset = snc_nec16_select_bank(sc, offset, 0); 667 onoffset = noffset; 668 669 /* XXX: should check if offset + size < 0x2000. */ 670 671 if (size > 3) { 672 if (noffset & 3) { 673 size_t asize = 4 - (noffset & 3); 674 675 bus_space_write_region_1(memt, memh, noffset, 676 bptr, asize); 677 bptr += asize; 678 noffset += asize; 679 size -= asize; 680 } 681 bus_space_write_region_4(memt, memh, noffset, 682 (u_int32_t *)bptr, size >> 2); 683 bptr += size & ~3; 684 noffset += size & ~3; 685 size -= size & ~3; 686 } 687 if (size) 688 bus_space_write_region_1(memt, memh, noffset, bptr, size); 689 690 bus_space_barrier(memt, memh, onoffset, osize, 691 BUS_SPACE_BARRIER_WRITE); 692} 693 694/* 695 * write (fill) 0 to SONIC data buffer. 696 */ 697void 698snc_nec16_zerobuf(sc, offset, size) 699 struct snc_softc *sc; 700 u_int32_t offset; 701 size_t size; 702{ 703 bus_space_tag_t memt = sc->sc_memt; 704 bus_space_handle_t memh = sc->sc_memh; 705 u_int16_t noffset, onoffset; 706 size_t osize = size; 707 708 noffset = snc_nec16_select_bank(sc, offset, 0); 709 onoffset = noffset; 710 711 /* XXX: should check if offset + size < 0x2000. */ 712 713 if (size > 3) { 714 if (noffset & 3) { 715 size_t asize = 4 - (noffset & 3); 716 717 bus_space_set_region_1(memt, memh, noffset, 0, asize); 718 noffset += asize; 719 size -= asize; 720 } 721 bus_space_set_region_4(memt, memh, noffset, 0, size >> 2); 722 noffset += size & ~3; 723 size -= size & ~3; 724 } 725 if (size) 726 bus_space_set_region_1(memt, memh, noffset, 0, size); 727 728 bus_space_barrier(memt, memh, onoffset, osize, 729 BUS_SPACE_BARRIER_WRITE); 730} 731 732 733/* 734 * Routines to read bytes sequentially from EEPROM through NEC PC-9801-83, 735 * 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98. 736 * Ported by Kouichi Matsuda. 737 * 738 * This algorism is generic to read data sequentially from 4-Wire 739 * Microwire Serial EEPROM. 740 */ 741 742#define SNEC_EEP_DELAY 1000 743 744void 745snc_nec16_read_eeprom(iot, ioh, data) 746 bus_space_tag_t iot; 747 bus_space_handle_t ioh; 748 u_int8_t *data; 749{ 750 u_int8_t n, val, bit; 751 752 /* Read bytes from EEPROM; two bytes per an iteration. */ 753 for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) { 754 /* select SNECR_EEP */ 755 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP); 756 757 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00); 758 delay(SNEC_EEP_DELAY); 759 760 /* Start EEPROM access. */ 761 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 762 delay(SNEC_EEP_DELAY); 763 764 bus_space_write_1(iot, ioh, SNEC_CTRLB, 765 SNECR_EEP_CS | SNECR_EEP_SK); 766 delay(SNEC_EEP_DELAY); 767 768 bus_space_write_1(iot, ioh, SNEC_CTRLB, 769 SNECR_EEP_CS | SNECR_EEP_DI); 770 delay(SNEC_EEP_DELAY); 771 772 bus_space_write_1(iot, ioh, SNEC_CTRLB, 773 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI); 774 delay(SNEC_EEP_DELAY); 775 776 bus_space_write_1(iot, ioh, SNEC_CTRLB, 777 SNECR_EEP_CS | SNECR_EEP_DI); 778 delay(SNEC_EEP_DELAY); 779 780 bus_space_write_1(iot, ioh, SNEC_CTRLB, 781 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI); 782 delay(SNEC_EEP_DELAY); 783 784 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 785 delay(SNEC_EEP_DELAY); 786 787 bus_space_write_1(iot, ioh, SNEC_CTRLB, 788 SNECR_EEP_CS | SNECR_EEP_SK); 789 delay(SNEC_EEP_DELAY); 790 791 /* Pass the iteration count to the chip. */ 792 for (bit = 0x20; bit != 0x00; bit >>= 1) { 793 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS | 794 ((n & bit) ? SNECR_EEP_DI : 0x00)); 795 delay(SNEC_EEP_DELAY); 796 797 bus_space_write_1(iot, ioh, SNEC_CTRLB, 798 SNECR_EEP_CS | SNECR_EEP_SK | 799 ((n & bit) ? SNECR_EEP_DI : 0x00)); 800 delay(SNEC_EEP_DELAY); 801 } 802 803 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 804 (void) bus_space_read_1(iot, ioh, SNEC_CTRLB); /* ACK */ 805 delay(SNEC_EEP_DELAY); 806 807 /* Read a byte. */ 808 val = 0; 809 for (bit = 0x80; bit != 0x00; bit >>= 1) { 810 bus_space_write_1(iot, ioh, SNEC_CTRLB, 811 SNECR_EEP_CS | SNECR_EEP_SK); 812 delay(SNEC_EEP_DELAY); 813 814 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 815 816 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO) 817 val |= bit; 818 } 819 *data++ = val; 820 821 /* Read one more byte. */ 822 val = 0; 823 for (bit = 0x80; bit != 0x00; bit >>= 1) { 824 bus_space_write_1(iot, ioh, SNEC_CTRLB, 825 SNECR_EEP_CS | SNECR_EEP_SK); 826 delay(SNEC_EEP_DELAY); 827 828 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 829 830 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO) 831 val |= bit; 832 } 833 *data++ = val; 834 835 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00); 836 delay(SNEC_EEP_DELAY); 837 } 838 839#ifdef SNCDEBUG 840 /* Report what we got. */ 841 data -= SNEC_EEPROM_SIZE; 842 log(LOG_INFO, "%s: EEPROM:" 843 " %02x%02x%02x%02x %02x%02x%02x%02x -" 844 " %02x%02x%02x%02x %02x%02x%02x%02x -" 845 " %02x%02x%02x%02x %02x%02x%02x%02x -" 846 " %02x%02x%02x%02x %02x%02x%02x%02x\n", 847 "snc_nec16_read_eeprom", 848 data[ 0], data[ 1], data[ 2], data[ 3], 849 data[ 4], data[ 5], data[ 6], data[ 7], 850 data[ 8], data[ 9], data[10], data[11], 851 data[12], data[13], data[14], data[15], 852 data[16], data[17], data[18], data[19], 853 data[20], data[21], data[22], data[23], 854 data[24], data[25], data[26], data[27], 855 data[28], data[29], data[30], data[31]); 856#endif 857} 858 859#ifdef SNCDEBUG 860void 861snc_nec16_dump_reg(iot, ioh) 862 bus_space_tag_t iot; 863 bus_space_handle_t ioh; 864{ 865 u_int8_t n; 866 u_int16_t val; 867 868 printf("SONIC registers (word):"); 869 for (n = 0; n < SNC_NREGS; n++) { 870 /* select required SONIC register */ 871 bus_space_write_1(iot, ioh, SNEC_ADDR, n); 872 delay(10); 873 val = bus_space_read_2(iot, ioh, SNEC_CTRL); 874 if ((n % 0x10) == 0) 875 printf("\n%04x ", val); 876 else 877 printf("%04x ", val); 878 } 879 printf("\n"); 880 881 printf("NEC/SONIC registers (byte):\n"); 882 for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) { 883 /* select required SONIC register */ 884 bus_space_write_1(iot, ioh, SNEC_ADDR, n); 885 delay(10); 886 val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB); 887 printf("%04x ", val); 888 } 889 printf("\n"); 890} 891 892#endif /* SNCDEBUG */
| 37/* 38 * Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R 39 * Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda. 40 * 41 * These cards use National Semiconductor DP83934AVQB as Ethernet Controller 42 * and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM. 43 */ 44 45/* 46 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki. 47 */ 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/protosw.h> 52#include <sys/socket.h> 53 54#include <net/ethernet.h> 55#include <net/if.h> 56#include <net/if_arp.h> 57#include <net/if_media.h> 58 59#ifdef INET 60#include <netinet/in.h> 61#include <netinet/in_systm.h> 62#include <netinet/in_var.h> 63#include <netinet/ip.h> 64#include <netinet/if_inarp.h> 65#endif 66 67 68#include <sys/bus.h> 69#include <machine/bus.h> 70 71#include <dev/snc/dp83932reg.h> 72#include <dev/snc/dp83932var.h> 73#include <dev/snc/if_sncreg.h> 74#include <dev/snc/dp83932subr.h> 75 76integrate u_int16_t snc_nec16_select_bank 77 (struct snc_softc *, u_int32_t, u_int32_t); 78 79/* 80 * Interface exists: make available by filling in network interface 81 * record. System will initialize the interface when it is ready 82 * to accept packets. 83 */ 84int 85sncsetup(sc, lladdr) 86 struct snc_softc *sc; 87 u_int8_t *lladdr; 88{ 89 u_int32_t p, pp; 90 int i; 91 int offset; 92 93 /* 94 * Put the pup in reset mode (sncinit() will fix it later), 95 * stop the timer, disable all interrupts and clear any interrupts. 96 */ 97 NIC_PUT(sc, SNCR_CR, CR_STP); 98 wbflush(); 99 NIC_PUT(sc, SNCR_CR, CR_RST); 100 wbflush(); 101 NIC_PUT(sc, SNCR_IMR, 0); 102 wbflush(); 103 NIC_PUT(sc, SNCR_ISR, ISR_ALL); 104 wbflush(); 105 106 /* 107 * because the SONIC is basically 16bit device it 'concatenates' 108 * a higher buffer address to a 16 bit offset--this will cause wrap 109 * around problems near the end of 64k !! 110 */ 111 p = pp = 0; 112 113 for (i = 0; i < NRRA; i++) { 114 sc->v_rra[i] = SONIC_GETDMA(p); 115 p += RXRSRC_SIZE(sc); 116 } 117 sc->v_rea = SONIC_GETDMA(p); 118 119 p = SOALIGN(sc, p); 120 121 sc->v_cda = SONIC_GETDMA(p); 122 p += CDA_SIZE(sc); 123 124 p = SOALIGN(sc, p); 125 126 for (i = 0; i < NTDA; i++) { 127 struct mtd *mtdp = &sc->mtda[i]; 128 mtdp->mtd_vtxp = SONIC_GETDMA(p); 129 p += TXP_SIZE(sc); 130 } 131 132 p = SOALIGN(sc, p); 133 134 if ((p - pp) > NBPG) { 135 device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" 136 "TDA (%ld) > NBPG (%d). Punt!\n", 137 (ulong)sc->v_cda - (ulong)sc->v_rra[0], 138 (ulong)sc->mtda[0].mtd_vtxp - (ulong)sc->v_cda, 139 (ulong)p - (ulong)sc->mtda[0].mtd_vtxp, 140 NBPG); 141 return(1); 142 } 143 144 p = pp + NBPG; 145 pp = p; 146 147 sc->sc_nrda = NBPG / RXPKT_SIZE(sc); 148 sc->v_rda = SONIC_GETDMA(p); 149 150 p = pp + NBPG; 151 152 for (i = 0; i < NRBA; i++) { 153 sc->rbuf[i] = p; 154 p += NBPG; 155 } 156 157 pp = p; 158 offset = TXBSIZE; 159 for (i = 0; i < NTDA; i++) { 160 struct mtd *mtdp = &sc->mtda[i]; 161 162 mtdp->mtd_vbuf = SONIC_GETDMA(p); 163 offset += TXBSIZE; 164 if (offset < NBPG) { 165 p += TXBSIZE; 166 } else { 167 p = pp + NBPG; 168 pp = p; 169 offset = TXBSIZE; 170 } 171 } 172 173 return (0); 174} 175 176/* 177 * miscellaneous NEC/SONIC detect functions. 178 */ 179 180/* 181 * check if a specified irq is acceptable. 182 */ 183u_int8_t 184snc_nec16_validate_irq(irq) 185 int irq; 186{ 187 const u_int8_t encoded_irq[16] = { 188 -1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1 189 }; 190 191 return encoded_irq[irq]; 192} 193 194/* 195 * specify irq to board. 196 */ 197int 198snc_nec16_register_irq(sc, irq) 199 struct snc_softc *sc; 200 int irq; 201{ 202 bus_space_tag_t iot = sc->sc_iot; 203 bus_space_handle_t ioh = sc->sc_ioh; 204 u_int8_t encoded_irq; 205 206 encoded_irq = snc_nec16_validate_irq(irq); 207 if (encoded_irq == (u_int8_t) -1) { 208 printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq); 209 return 0; 210 } 211 212 /* select SNECR_IRQSEL register */ 213 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL); 214 /* write encoded irq value */ 215 bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq); 216 217 return 1; 218} 219 220/* 221 * check if a specified memory base address is acceptable. 222 */ 223int 224snc_nec16_validate_mem(maddr) 225 int maddr; 226{ 227 228 /* Check on Normal mode with max range, only */ 229 if ((maddr & ~0x1E000) != 0xC0000) { 230 printf("snc_nec16_validate_mem: " 231 "unsupported window base (0x%x)\n", maddr); 232 return 0; 233 } 234 235 return 1; 236} 237 238/* 239 * specify memory base address to board and map to first bank. 240 */ 241int 242snc_nec16_register_mem(sc, maddr) 243 struct snc_softc *sc; 244 int maddr; 245{ 246 bus_space_tag_t iot = sc->sc_iot; 247 bus_space_handle_t ioh = sc->sc_ioh; 248 249 if (snc_nec16_validate_mem(maddr) == 0) 250 return 0; 251 252 /* select SNECR_MEMSEL register */ 253 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL); 254 /* write encoded memory base select value */ 255 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr)); 256 257 /* 258 * set current bank to 0 (bottom) and map 259 */ 260 /* select SNECR_MEMBS register */ 261 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 262 /* select new bank */ 263 bus_space_write_1(iot, ioh, SNEC_CTRLB, 264 SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN); 265 /* set current bank to 0 */ 266 sc->curbank = 0; 267 268 return 1; 269} 270 271int 272snc_nec16_check_memory(iot, ioh, memt, memh) 273 bus_space_tag_t iot; 274 bus_space_handle_t ioh; 275 bus_space_tag_t memt; 276 bus_space_handle_t memh; 277{ 278 u_int16_t val; 279 int i, j; 280 281 val = 0; 282 for (i = 0; i < SNEC_NBANK; i++) { 283 /* select new bank */ 284 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 285 bus_space_write_1(iot, ioh, SNEC_CTRLB, 286 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 287 288 /* write test pattern */ 289 for (j = 0; j < SNEC_NMEMS / 2; j++) { 290 bus_space_write_2(memt, memh, j * 2, val + j); 291 } 292 val += 0x1000; 293 } 294 295 val = 0; 296 for (i = 0; i < SNEC_NBANK; i++) { 297 /* select new bank */ 298 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 299 bus_space_write_1(iot, ioh, SNEC_CTRLB, 300 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 301 302 /* read test pattern */ 303 for (j = 0; j < SNEC_NMEMS / 2; j++) { 304 if (bus_space_read_2(memt, memh, j * 2) != val + j) 305 break; 306 } 307 308 if (j < SNEC_NMEMS / 2) { 309 printf("snc_nec16_check_memory: " 310 "memory check failed at 0x%04x%04x" 311 "val 0x%04x != expected 0x%04x\n", i, j, 312 bus_space_read_2(memt, memh, j * 2), 313 val + j); 314 return 0; 315 } 316 val += 0x1000; 317 } 318 319 /* zero clear mem */ 320 for (i = 0; i < SNEC_NBANK; i++) { 321 /* select new bank */ 322 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 323 bus_space_write_1(iot, ioh, SNEC_CTRLB, 324 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 325 326 bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2); 327 } 328 329 /* again read test if these are 0 */ 330 for (i = 0; i < SNEC_NBANK; i++) { 331 /* select new bank */ 332 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 333 bus_space_write_1(iot, ioh, SNEC_CTRLB, 334 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN); 335 336 /* check if cleared */ 337 for (j = 0; j < SNEC_NMEMS; j += 2) { 338 if (bus_space_read_2(memt, memh, j) != 0) 339 break; 340 } 341 342 if (j != SNEC_NMEMS) { 343 printf("snc_nec16_check_memory: " 344 "memory zero clear failed at 0x%04x%04x\n", i, j); 345 return 0; 346 } 347 } 348 349 return 1; 350} 351 352int 353snc_nec16_detectsubr(iot, ioh, memt, memh, irq, maddr, type) 354 bus_space_tag_t iot; 355 bus_space_handle_t ioh; 356 bus_space_tag_t memt; 357 bus_space_handle_t memh; 358 int irq; 359 int maddr; 360 u_int8_t type; 361{ 362 u_int16_t cr; 363 u_int8_t ident; 364 int rv = 0; 365 366 if (snc_nec16_validate_irq(irq) == (u_int8_t) -1) 367 return 0; 368 /* XXX: maddr already checked */ 369 if (snc_nec16_validate_mem(maddr) == 0) 370 return 0; 371 372 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT); 373 ident = bus_space_read_1(iot, ioh, SNEC_CTRLB); 374 if (ident == 0xff || ident == 0x00) { 375 /* not found */ 376 return 0; 377 } 378 379 switch (type) { 380 case SNEC_TYPE_LEGACY: 381 rv = (ident == SNECR_IDENT_LEGACY_CBUS); 382 break; 383 case SNEC_TYPE_PNP: 384 rv = ((ident == SNECR_IDENT_PNP_CBUS) || 385 (ident == SNECR_IDENT_PNP_PCMCIABUS)); 386 break; 387 default: 388 break; 389 } 390 391 if (rv == 0) { 392 printf("snc_nec16_detectsubr: parent bus mismatch\n"); 393 return 0; 394 } 395 396 /* select SONIC register SNCR_CR */ 397 bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR); 398 bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST); 399 delay(400); 400 401 cr = bus_space_read_2(iot, ioh, SNEC_CTRL); 402 if (cr != (CR_RXDIS | CR_STP | CR_RST)) { 403#ifdef DIAGNOSTIC 404 printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n", 405 cr); 406#endif 407 return 0; 408 } 409 410 if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0) 411 return 0; 412 413 return 1; 414} 415 416/* XXX */ 417#define SNC_VENDOR_NEC 0x00004c 418#define SNC_NEC_SERIES_LEGACY_CBUS 0xa5 419#define SNC_NEC_SERIES_PNP_PCMCIA 0xd5 420#define SNC_NEC_SERIES_PNP_PCMCIA2 0x6d /* XXX */ 421#define SNC_NEC_SERIES_PNP_CBUS 0x0d 422#define SNC_NEC_SERIES_PNP_CBUS2 0x3d 423 424u_int8_t * 425snc_nec16_detect_type(myea) 426 u_int8_t *myea; 427{ 428 u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2]; 429 u_int8_t series = myea[3]; 430 u_int8_t type = myea[4] & 0x80; 431 u_int8_t *typestr; 432 433 switch (vendor) { 434 case SNC_VENDOR_NEC: 435 switch (series) { 436 case SNC_NEC_SERIES_LEGACY_CBUS: 437 if (type) 438 typestr = "NEC PC-9801-84"; 439 else 440 typestr = "NEC PC-9801-83"; 441 break; 442 case SNC_NEC_SERIES_PNP_CBUS: 443 case SNC_NEC_SERIES_PNP_CBUS2: 444 if (type) 445 typestr = "NEC PC-9801-104"; 446 else 447 typestr = "NEC PC-9801-103"; 448 break; 449 case SNC_NEC_SERIES_PNP_PCMCIA: 450 case SNC_NEC_SERIES_PNP_PCMCIA2: 451 /* XXX: right ? */ 452 if (type) 453 typestr = "NEC PC-9801N-J02R"; 454 else 455 typestr = "NEC PC-9801N-J02"; 456 break; 457 default: 458 typestr = "NEC unknown (PC-9801N-25?)"; 459 break; 460 } 461 break; 462 default: 463 typestr = "unknown (3rd vendor?)"; 464 break; 465 } 466 467 return typestr; 468} 469 470int 471snc_nec16_get_enaddr(iot, ioh, myea) 472 bus_space_tag_t iot; 473 bus_space_handle_t ioh; 474 u_int8_t *myea; 475{ 476 u_int8_t eeprom[SNEC_EEPROM_SIZE]; 477 u_int8_t rom_sum, sum = 0x00; 478 int i; 479 480 snc_nec16_read_eeprom(iot, ioh, eeprom); 481 482 for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) { 483 sum = sum ^ eeprom[i]; 484 } 485 486 rom_sum = eeprom[SNEC_EEPROM_CKSUM]; 487 488 if (sum != rom_sum) { 489 printf("snc_nec16_get_enaddr: " 490 "checksum mismatch; calculated %02x != read %02x", 491 sum, rom_sum); 492 return 0; 493 } 494 495 for (i = 0; i < ETHER_ADDR_LEN; i++) 496 myea[i] = eeprom[SNEC_EEPROM_SA0 + i]; 497 498 return 1; 499} 500 501/* 502 * read from NEC/SONIC NIC register. 503 */ 504u_int16_t 505snc_nec16_nic_get(sc, reg) 506 struct snc_softc *sc; 507 u_int8_t reg; 508{ 509 u_int16_t val; 510 511 /* select SONIC register */ 512 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg); 513 val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL); 514 515 return val; 516} 517 518/* 519 * write to NEC/SONIC NIC register. 520 */ 521void 522snc_nec16_nic_put(sc, reg, val) 523 struct snc_softc *sc; 524 u_int8_t reg; 525 u_int16_t val; 526{ 527 528 /* select SONIC register */ 529 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg); 530 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val); 531} 532 533 534/* 535 * select memory bank and map 536 * where exists specified (internal buffer memory) offset. 537 */ 538integrate u_int16_t 539snc_nec16_select_bank(sc, base, offset) 540 struct snc_softc *sc; 541 u_int32_t base; 542 u_int32_t offset; 543{ 544 bus_space_tag_t iot = sc->sc_iot; 545 bus_space_handle_t ioh = sc->sc_ioh; 546 u_int8_t bank; 547 u_int16_t noffset; 548 549 /* bitmode is fixed to 16 bit. */ 550 bank = (base + offset * 2) >> 13; 551 noffset = (base + offset * 2) & (SNEC_NMEMS - 1); 552 553#ifdef SNCDEBUG 554 if (noffset % 2) { 555 device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n", 556 noffset); 557 } 558#endif /* SNCDEBUG */ 559 560 if (sc->curbank != bank) { 561 /* select SNECR_MEMBS register */ 562 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS); 563 /* select new bank */ 564 bus_space_write_1(iot, ioh, SNEC_CTRLB, 565 SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN); 566 /* update current bank */ 567 sc->curbank = bank; 568 } 569 570 return noffset; 571} 572 573/* 574 * write to SONIC descriptors. 575 */ 576void 577snc_nec16_writetodesc(sc, base, offset, val) 578 struct snc_softc *sc; 579 u_int32_t base; 580 u_int32_t offset; 581 u_int16_t val; 582{ 583 bus_space_tag_t memt = sc->sc_memt; 584 bus_space_handle_t memh = sc->sc_memh; 585 u_int16_t noffset; 586 587 noffset = snc_nec16_select_bank(sc, base, offset); 588 589 bus_space_write_2(memt, memh, noffset, val); 590} 591 592/* 593 * read from SONIC descriptors. 594 */ 595u_int16_t 596snc_nec16_readfromdesc(sc, base, offset) 597 struct snc_softc *sc; 598 u_int32_t base; 599 u_int32_t offset; 600{ 601 bus_space_tag_t memt = sc->sc_memt; 602 bus_space_handle_t memh = sc->sc_memh; 603 u_int16_t noffset; 604 605 noffset = snc_nec16_select_bank(sc, base, offset); 606 607 return bus_space_read_2(memt, memh, noffset); 608} 609 610/* 611 * read from SONIC data buffer. 612 */ 613void 614snc_nec16_copyfrombuf(sc, dst, offset, size) 615 struct snc_softc *sc; 616 void *dst; 617 u_int32_t offset; 618 size_t size; 619{ 620 bus_space_tag_t memt = sc->sc_memt; 621 bus_space_handle_t memh = sc->sc_memh; 622 u_int16_t noffset; 623 u_int8_t* bptr = dst; 624 625 noffset = snc_nec16_select_bank(sc, offset, 0); 626 627 /* XXX: should check if offset + size < 0x2000. */ 628 629 bus_space_barrier(memt, memh, noffset, size, 630 BUS_SPACE_BARRIER_READ); 631 632 if (size > 3) { 633 if (noffset & 3) { 634 size_t asize = 4 - (noffset & 3); 635 636 bus_space_read_region_1(memt, memh, noffset, 637 bptr, asize); 638 bptr += asize; 639 noffset += asize; 640 size -= asize; 641 } 642 bus_space_read_region_4(memt, memh, noffset, 643 (u_int32_t *) bptr, size >> 2); 644 bptr += size & ~3; 645 noffset += size & ~3; 646 size &= 3; 647 } 648 if (size) 649 bus_space_read_region_1(memt, memh, noffset, bptr, size); 650} 651 652/* 653 * write to SONIC data buffer. 654 */ 655void 656snc_nec16_copytobuf(sc, src, offset, size) 657 struct snc_softc *sc; 658 void *src; 659 u_int32_t offset; 660 size_t size; 661{ 662 bus_space_tag_t memt = sc->sc_memt; 663 bus_space_handle_t memh = sc->sc_memh; 664 u_int16_t noffset, onoffset; 665 size_t osize = size; 666 u_int8_t* bptr = src; 667 668 noffset = snc_nec16_select_bank(sc, offset, 0); 669 onoffset = noffset; 670 671 /* XXX: should check if offset + size < 0x2000. */ 672 673 if (size > 3) { 674 if (noffset & 3) { 675 size_t asize = 4 - (noffset & 3); 676 677 bus_space_write_region_1(memt, memh, noffset, 678 bptr, asize); 679 bptr += asize; 680 noffset += asize; 681 size -= asize; 682 } 683 bus_space_write_region_4(memt, memh, noffset, 684 (u_int32_t *)bptr, size >> 2); 685 bptr += size & ~3; 686 noffset += size & ~3; 687 size -= size & ~3; 688 } 689 if (size) 690 bus_space_write_region_1(memt, memh, noffset, bptr, size); 691 692 bus_space_barrier(memt, memh, onoffset, osize, 693 BUS_SPACE_BARRIER_WRITE); 694} 695 696/* 697 * write (fill) 0 to SONIC data buffer. 698 */ 699void 700snc_nec16_zerobuf(sc, offset, size) 701 struct snc_softc *sc; 702 u_int32_t offset; 703 size_t size; 704{ 705 bus_space_tag_t memt = sc->sc_memt; 706 bus_space_handle_t memh = sc->sc_memh; 707 u_int16_t noffset, onoffset; 708 size_t osize = size; 709 710 noffset = snc_nec16_select_bank(sc, offset, 0); 711 onoffset = noffset; 712 713 /* XXX: should check if offset + size < 0x2000. */ 714 715 if (size > 3) { 716 if (noffset & 3) { 717 size_t asize = 4 - (noffset & 3); 718 719 bus_space_set_region_1(memt, memh, noffset, 0, asize); 720 noffset += asize; 721 size -= asize; 722 } 723 bus_space_set_region_4(memt, memh, noffset, 0, size >> 2); 724 noffset += size & ~3; 725 size -= size & ~3; 726 } 727 if (size) 728 bus_space_set_region_1(memt, memh, noffset, 0, size); 729 730 bus_space_barrier(memt, memh, onoffset, osize, 731 BUS_SPACE_BARRIER_WRITE); 732} 733 734 735/* 736 * Routines to read bytes sequentially from EEPROM through NEC PC-9801-83, 737 * 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98. 738 * Ported by Kouichi Matsuda. 739 * 740 * This algorism is generic to read data sequentially from 4-Wire 741 * Microwire Serial EEPROM. 742 */ 743 744#define SNEC_EEP_DELAY 1000 745 746void 747snc_nec16_read_eeprom(iot, ioh, data) 748 bus_space_tag_t iot; 749 bus_space_handle_t ioh; 750 u_int8_t *data; 751{ 752 u_int8_t n, val, bit; 753 754 /* Read bytes from EEPROM; two bytes per an iteration. */ 755 for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) { 756 /* select SNECR_EEP */ 757 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP); 758 759 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00); 760 delay(SNEC_EEP_DELAY); 761 762 /* Start EEPROM access. */ 763 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 764 delay(SNEC_EEP_DELAY); 765 766 bus_space_write_1(iot, ioh, SNEC_CTRLB, 767 SNECR_EEP_CS | SNECR_EEP_SK); 768 delay(SNEC_EEP_DELAY); 769 770 bus_space_write_1(iot, ioh, SNEC_CTRLB, 771 SNECR_EEP_CS | SNECR_EEP_DI); 772 delay(SNEC_EEP_DELAY); 773 774 bus_space_write_1(iot, ioh, SNEC_CTRLB, 775 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI); 776 delay(SNEC_EEP_DELAY); 777 778 bus_space_write_1(iot, ioh, SNEC_CTRLB, 779 SNECR_EEP_CS | SNECR_EEP_DI); 780 delay(SNEC_EEP_DELAY); 781 782 bus_space_write_1(iot, ioh, SNEC_CTRLB, 783 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI); 784 delay(SNEC_EEP_DELAY); 785 786 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 787 delay(SNEC_EEP_DELAY); 788 789 bus_space_write_1(iot, ioh, SNEC_CTRLB, 790 SNECR_EEP_CS | SNECR_EEP_SK); 791 delay(SNEC_EEP_DELAY); 792 793 /* Pass the iteration count to the chip. */ 794 for (bit = 0x20; bit != 0x00; bit >>= 1) { 795 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS | 796 ((n & bit) ? SNECR_EEP_DI : 0x00)); 797 delay(SNEC_EEP_DELAY); 798 799 bus_space_write_1(iot, ioh, SNEC_CTRLB, 800 SNECR_EEP_CS | SNECR_EEP_SK | 801 ((n & bit) ? SNECR_EEP_DI : 0x00)); 802 delay(SNEC_EEP_DELAY); 803 } 804 805 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 806 (void) bus_space_read_1(iot, ioh, SNEC_CTRLB); /* ACK */ 807 delay(SNEC_EEP_DELAY); 808 809 /* Read a byte. */ 810 val = 0; 811 for (bit = 0x80; bit != 0x00; bit >>= 1) { 812 bus_space_write_1(iot, ioh, SNEC_CTRLB, 813 SNECR_EEP_CS | SNECR_EEP_SK); 814 delay(SNEC_EEP_DELAY); 815 816 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 817 818 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO) 819 val |= bit; 820 } 821 *data++ = val; 822 823 /* Read one more byte. */ 824 val = 0; 825 for (bit = 0x80; bit != 0x00; bit >>= 1) { 826 bus_space_write_1(iot, ioh, SNEC_CTRLB, 827 SNECR_EEP_CS | SNECR_EEP_SK); 828 delay(SNEC_EEP_DELAY); 829 830 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS); 831 832 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO) 833 val |= bit; 834 } 835 *data++ = val; 836 837 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00); 838 delay(SNEC_EEP_DELAY); 839 } 840 841#ifdef SNCDEBUG 842 /* Report what we got. */ 843 data -= SNEC_EEPROM_SIZE; 844 log(LOG_INFO, "%s: EEPROM:" 845 " %02x%02x%02x%02x %02x%02x%02x%02x -" 846 " %02x%02x%02x%02x %02x%02x%02x%02x -" 847 " %02x%02x%02x%02x %02x%02x%02x%02x -" 848 " %02x%02x%02x%02x %02x%02x%02x%02x\n", 849 "snc_nec16_read_eeprom", 850 data[ 0], data[ 1], data[ 2], data[ 3], 851 data[ 4], data[ 5], data[ 6], data[ 7], 852 data[ 8], data[ 9], data[10], data[11], 853 data[12], data[13], data[14], data[15], 854 data[16], data[17], data[18], data[19], 855 data[20], data[21], data[22], data[23], 856 data[24], data[25], data[26], data[27], 857 data[28], data[29], data[30], data[31]); 858#endif 859} 860 861#ifdef SNCDEBUG 862void 863snc_nec16_dump_reg(iot, ioh) 864 bus_space_tag_t iot; 865 bus_space_handle_t ioh; 866{ 867 u_int8_t n; 868 u_int16_t val; 869 870 printf("SONIC registers (word):"); 871 for (n = 0; n < SNC_NREGS; n++) { 872 /* select required SONIC register */ 873 bus_space_write_1(iot, ioh, SNEC_ADDR, n); 874 delay(10); 875 val = bus_space_read_2(iot, ioh, SNEC_CTRL); 876 if ((n % 0x10) == 0) 877 printf("\n%04x ", val); 878 else 879 printf("%04x ", val); 880 } 881 printf("\n"); 882 883 printf("NEC/SONIC registers (byte):\n"); 884 for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) { 885 /* select required SONIC register */ 886 bus_space_write_1(iot, ioh, SNEC_ADDR, n); 887 delay(10); 888 val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB); 889 printf("%04x ", val); 890 } 891 printf("\n"); 892} 893 894#endif /* SNCDEBUG */
|