31 * 32 * Device driver for Crystal Semiconductor CS8920 based ethernet 33 * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997 34 */ 35 36/* 37#define CS_DEBUG 38 */ 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/malloc.h> 43#include <sys/mbuf.h> 44#include <sys/socket.h> 45#include <sys/sockio.h> 46#include <sys/kernel.h> 47#include <sys/sysctl.h> 48#include <sys/syslog.h> 49 50#include <sys/module.h> 51#include <sys/bus.h> 52#include <machine/bus.h> 53#include <sys/rman.h> 54#include <machine/resource.h> 55 56#include <net/if.h> 57#include <net/if_arp.h> 58#include <net/if_media.h> 59#include <net/ethernet.h> 60#include <net/bpf.h> 61 62#include <dev/cs/if_csvar.h> 63#include <dev/cs/if_csreg.h> 64 65#ifdef CS_USE_64K_DMA 66#define CS_DMA_BUFFER_SIZE 65536 67#else 68#define CS_DMA_BUFFER_SIZE 16384 69#endif 70 71static int cs_recv_delay = 570; 72SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, ""); 73 74static void cs_init (void *); 75static int cs_ioctl (struct ifnet *, u_long, caddr_t); 76static void cs_start (struct ifnet *); 77static void cs_stop (struct cs_softc *); 78static void cs_reset (struct cs_softc *); 79static void cs_watchdog (struct ifnet *); 80 81static int cs_mediachange (struct ifnet *); 82static void cs_mediastatus (struct ifnet *, struct ifmediareq *); 83static int cs_mediaset (struct cs_softc *, int); 84 85static void cs_write_mbufs(struct cs_softc*, struct mbuf*); 86static void cs_xmit_buf(struct cs_softc*); 87static int cs_get_packet(struct cs_softc*); 88static void cs_setmode(struct cs_softc*); 89 90static int get_eeprom_data(struct cs_softc *sc, int, int, int *); 91static int get_eeprom_cksum(int, int, int *); 92static int wait_eeprom_ready( struct cs_softc *); 93static void control_dc_dc( struct cs_softc *, int ); 94static int send_test_pkt( struct cs_softc * ); 95static int enable_tp(struct cs_softc *); 96static int enable_aui(struct cs_softc *); 97static int enable_bnc(struct cs_softc *); 98static int cs_duplex_auto(struct cs_softc *); 99 100devclass_t cs_devclass; 101 102static int 103get_eeprom_data( struct cs_softc *sc, int off, int len, int *buffer) 104{ 105 int i; 106 107#ifdef CS_DEBUG 108 printf(CS_NAME":EEPROM data from %x for %x:\n", off,len); 109#endif 110 111 for (i=0;i<len;i++) { 112 if (wait_eeprom_ready(sc) < 0) return -1; 113 /* Send command to EEPROM to read */ 114 cs_writereg(sc, PP_EECMD, (off + i) | EEPROM_READ_CMD); 115 if (wait_eeprom_ready(sc)<0) 116 return (-1); 117 buffer[i] = cs_readreg(sc, PP_EEData); 118 119#ifdef CS_DEBUG 120 printf("%02x %02x ",(unsigned char)buffer[i], 121 (unsigned char)buffer[i+1]); 122#endif 123 } 124 125#ifdef CS_DEBUG 126 printf("\n"); 127#endif 128 return (0); 129} 130 131static int 132get_eeprom_cksum(int off, int len, int *buffer) 133{ 134 int i,cksum=0; 135 136 for (i=0;i<len;i++) 137 cksum+=buffer[i]; 138 cksum &= 0xffff; 139 if (cksum==0) 140 return 0; 141 return -1; 142} 143 144static int 145wait_eeprom_ready(struct cs_softc *sc) 146{ 147 DELAY ( 30000 ); /* XXX should we do some checks here ? */ 148 return 0; 149} 150 151static void 152control_dc_dc(struct cs_softc *sc, int on_not_off) 153{ 154 unsigned int self_control = HCB1_ENBL; 155 156 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off) 157 self_control |= HCB1; 158 else 159 self_control &= ~HCB1; 160 cs_writereg(sc, PP_SelfCTL, self_control); 161 162 DELAY( 500000 ); 163} 164 165 166static int 167cs_duplex_auto(struct cs_softc *sc) 168{ 169 int i, error=0; 170 171 cs_writereg(sc, PP_AutoNegCTL, 172 RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE); 173 for (i=0; cs_readreg(sc, PP_AutoNegST) & AUTO_NEG_BUSY; i++) { 174 if (i > 40000) { 175 if_printf(&sc->arpcom.ac_if, 176 "full/half duplex auto negotiation timeout\n"); 177 error = ETIMEDOUT; 178 break; 179 } 180 DELAY(1000); 181 } 182 DELAY( 1000000 ); 183 return error; 184} 185 186static int 187enable_tp(struct cs_softc *sc) 188{ 189 190 cs_writereg(sc, PP_LineCTL, sc->line_ctl & ~AUI_ONLY); 191 control_dc_dc(sc, 0); 192 DELAY( 150000 ); 193 194 if ((cs_readreg(sc, PP_LineST) & LINK_OK)==0) { 195 if_printf(&sc->arpcom.ac_if, "failed to enable TP\n"); 196 return EINVAL; 197 } 198 199 return 0; 200} 201 202/* 203 * XXX This was rewritten from Linux driver without any tests. 204 */ 205static int 206send_test_pkt(struct cs_softc *sc) 207{ 208 char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 209 0, 46, /* A 46 in network order */ 210 0, 0, /* DSAP=0 & SSAP=0 fields */ 211 0xf3, 0 /* Control (Test Req + P bit set) */ }; 212 int i; 213 u_char ether_address_backup[ETHER_ADDR_LEN]; 214 215 for (i = 0; i < ETHER_ADDR_LEN; i++) { 216 ether_address_backup[i] = sc->arpcom.ac_enaddr[i]; 217 } 218 219 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_TX_ON); 220 bcopy(test_packet, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 221 bcopy(test_packet+ETHER_ADDR_LEN, 222 sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 223 cs_outw(sc, TX_CMD_PORT, sc->send_cmd); 224 cs_outw(sc, TX_LEN_PORT, sizeof(test_packet)); 225 226 /* Wait for chip to allocate memory */ 227 DELAY(50000); 228 if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) { 229 for (i = 0; i < ETHER_ADDR_LEN; i++) { 230 sc->arpcom.ac_enaddr[i] = ether_address_backup[i]; 231 } 232 return 0; 233 } 234 235 outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet)); 236 237 DELAY(30000); 238 239 if ((cs_readreg(sc, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) { 240 for (i = 0; i < ETHER_ADDR_LEN; i++) { 241 sc->arpcom.ac_enaddr[i] = ether_address_backup[i]; 242 } 243 return 1; 244 } 245 for (i = 0; i < ETHER_ADDR_LEN; i++) { 246 sc->arpcom.ac_enaddr[i] = ether_address_backup[i]; 247 } 248 return 0; 249} 250 251/* 252 * XXX This was rewritten from Linux driver without any tests. 253 */ 254static int 255enable_aui(struct cs_softc *sc) 256{ 257 258 control_dc_dc(sc, 0); 259 cs_writereg(sc, PP_LineCTL, 260 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY); 261 262 if (!send_test_pkt(sc)) { 263 if_printf(&sc->arpcom.ac_if, "failed to enable AUI\n"); 264 return EINVAL; 265 } 266 return 0; 267} 268 269/* 270 * XXX This was rewritten from Linux driver without any tests. 271 */ 272static int 273enable_bnc(struct cs_softc *sc) 274{ 275 276 control_dc_dc(sc, 1); 277 cs_writereg(sc, PP_LineCTL, 278 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY); 279 280 if (!send_test_pkt(sc)) { 281 if_printf(&sc->arpcom.ac_if, "failed to enable BNC\n"); 282 return EINVAL; 283 } 284 return 0; 285} 286 287int 288cs_cs89x0_probe(device_t dev) 289{ 290 int i; 291 int error; 292 u_long irq, junk; 293 struct cs_softc *sc = device_get_softc(dev); 294 unsigned rev_type = 0; 295 u_int16_t id; 296 char chip_revision; 297 int eeprom_buff[CHKSUM_LEN]; 298 int chip_type, pp_isaint, pp_isadma; 299 300 error = cs_alloc_port(dev, 0, CS_89x0_IO_PORTS); 301 if (error) 302 return (error); 303 304 sc->nic_addr = rman_get_start(sc->port_res); 305 306 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) { 307 /* Chip not detected. Let's try to reset it */ 308 if (bootverbose) 309 device_printf(dev, "trying to reset the chip.\n"); 310 cs_outw(sc, ADD_PORT, PP_SelfCTL); 311 i = cs_inw(sc, DATA_PORT); 312 cs_outw(sc, ADD_PORT, PP_SelfCTL); 313 cs_outw(sc, DATA_PORT, i | POWER_ON_RESET); 314 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) 315 return (ENXIO); 316 } 317 318 for (i = 0; i < 10000; i++) { 319 id = cs_readreg(sc, PP_ChipID); 320 if (id == CHIP_EISA_ID_SIG) 321 break; 322 } 323 if (i == 10000) 324 return (ENXIO); 325 326 rev_type = cs_readreg(sc, PRODUCT_ID_ADD); 327 chip_type = rev_type & ~REVISON_BITS; 328 chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A'; 329 330 sc->chip_type = chip_type; 331 332 if(chip_type==CS8900) { 333 pp_isaint = PP_CS8900_ISAINT; 334 pp_isadma = PP_CS8900_ISADMA; 335 sc->send_cmd = TX_CS8900_AFTER_ALL; 336 } else { 337 pp_isaint = PP_CS8920_ISAINT; 338 pp_isadma = PP_CS8920_ISADMA; 339 sc->send_cmd = TX_CS8920_AFTER_ALL; 340 } 341 342 /* 343 * Clear some fields so that fail of EEPROM will left them clean 344 */ 345 sc->auto_neg_cnf = 0; 346 sc->adapter_cnf = 0; 347 sc->isa_config = 0; 348 349 /* 350 * If no interrupt specified (or "?"), use what the board tells us. 351 */ 352 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk); 353 354 /* 355 * Get data from EEPROM 356 */ 357 if((cs_readreg(sc, PP_SelfST) & EEPROM_PRESENT) == 0) { 358 device_printf(dev, "No EEPROM, assuming defaults.\n"); 359 } else { 360 if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) { 361 device_printf(dev, "EEPROM read failed, " 362 "assuming defaults.\n"); 363 } else { 364 if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) { 365 device_printf(dev, "EEPROM cheksum bad, " 366 "assuming defaults.\n"); 367 } else { 368 sc->auto_neg_cnf = 369 eeprom_buff[AUTO_NEG_CNF_OFFSET/2]; 370 sc->adapter_cnf = 371 eeprom_buff[ADAPTER_CNF_OFFSET/2]; 372 sc->isa_config = 373 eeprom_buff[ISA_CNF_OFFSET/2]; 374 375 for (i=0; i<ETHER_ADDR_LEN/2; i++) { 376 sc->arpcom.ac_enaddr[i*2]= 377 eeprom_buff[i]; 378 sc->arpcom.ac_enaddr[i*2+1]= 379 eeprom_buff[i] >> 8; 380 } 381 382 /* 383 * If no interrupt specified (or "?"), 384 * use what the board tells us. 385 */ 386 if (error) { 387 irq = sc->isa_config & INT_NO_MASK; 388 if (chip_type==CS8900) { 389 switch(irq) { 390 case 0: 391 irq=10; 392 error=0; 393 break; 394 case 1: 395 irq=11; 396 error=0; 397 break; 398 case 2: 399 irq=12; 400 error=0; 401 break; 402 case 3: 403 irq=5; 404 error=0; 405 break; 406 default: 407 device_printf(dev, "invalid irq in EEPROM.\n"); 408 error=EINVAL; 409 } 410 } else { 411 if (irq>CS8920_NO_INTS) { 412 device_printf(dev, "invalid irq in EEPROM.\n"); 413 error=EINVAL; 414 } else { 415 error=0; 416 } 417 } 418 419 if (!error) 420 bus_set_resource(dev, SYS_RES_IRQ, 0, 421 irq, 1); 422 } 423 } 424 } 425 } 426 427 if (!error) { 428 if (chip_type == CS8900) { 429 switch(irq) { 430 case 5: 431 irq = 3; 432 break; 433 case 10: 434 irq = 0; 435 break; 436 case 11: 437 irq = 1; 438 break; 439 case 12: 440 irq = 2; 441 break; 442 default: 443 error=EINVAL; 444 } 445 } else { 446 if (irq > CS8920_NO_INTS) { 447 error = EINVAL; 448 } 449 } 450 } 451 452 if (!error) { 453 cs_writereg(sc, pp_isaint, irq); 454 } else { 455 device_printf(dev, "Unknown or invalid irq\n"); 456 return (ENXIO); 457 } 458 459 /* 460 * Temporary disabled 461 * 462 if (drq>0) 463 cs_writereg(sc, pp_isadma, drq); 464 else { 465 device_printf(dev, "incorrect drq\n",); 466 return 0; 467 } 468 */ 469 470 if (bootverbose) 471 device_printf(dev, "CS89%c0%s rev %c media%s%s%s\n", 472 chip_type==CS8900 ? '0' : '2', 473 chip_type==CS8920M ? "M" : "", 474 chip_revision, 475 (sc->adapter_cnf & A_CNF_10B_T) ? " TP" : "", 476 (sc->adapter_cnf & A_CNF_AUI) ? " AUI" : "", 477 (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : ""); 478 479 if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) && 480 (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH)) 481 sc->line_ctl = LOW_RX_SQUELCH; 482 else 483 sc->line_ctl = 0; 484 485 486 return 0; 487} 488 489/* 490 * Allocate a port resource with the given resource id. 491 */ 492int cs_alloc_port(device_t dev, int rid, int size) 493{ 494 struct cs_softc *sc = device_get_softc(dev); 495 struct resource *res; 496 497 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 498 0ul, ~0ul, size, RF_ACTIVE); 499 if (res) { 500 sc->port_rid = rid; 501 sc->port_res = res; 502 sc->port_used = size; 503 return (0); 504 } else { 505 return (ENOENT); 506 } 507} 508 509/* 510 * Allocate a memory resource with the given resource id. 511 */ 512int cs_alloc_memory(device_t dev, int rid, int size) 513{ 514 struct cs_softc *sc = device_get_softc(dev); 515 struct resource *res; 516 517 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 518 0ul, ~0ul, size, RF_ACTIVE); 519 if (res) { 520 sc->mem_rid = rid; 521 sc->mem_res = res; 522 sc->mem_used = size; 523 return (0); 524 } else { 525 return (ENOENT); 526 } 527} 528 529/* 530 * Allocate an irq resource with the given resource id. 531 */ 532int cs_alloc_irq(device_t dev, int rid, int flags) 533{ 534 struct cs_softc *sc = device_get_softc(dev); 535 struct resource *res; 536 537 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 538 0ul, ~0ul, 1, (RF_ACTIVE | flags)); 539 if (res) { 540 sc->irq_rid = rid; 541 sc->irq_res = res; 542 return (0); 543 } else { 544 return (ENOENT); 545 } 546} 547 548/* 549 * Release all resources 550 */ 551void cs_release_resources(device_t dev) 552{ 553 struct cs_softc *sc = device_get_softc(dev); 554 555 if (sc->port_res) { 556 bus_release_resource(dev, SYS_RES_IOPORT, 557 sc->port_rid, sc->port_res); 558 sc->port_res = 0; 559 } 560 if (sc->mem_res) { 561 bus_release_resource(dev, SYS_RES_MEMORY, 562 sc->mem_rid, sc->mem_res); 563 sc->mem_res = 0; 564 } 565 if (sc->irq_res) { 566 bus_release_resource(dev, SYS_RES_IRQ, 567 sc->irq_rid, sc->irq_res); 568 sc->irq_res = 0; 569 } 570} 571 572/* 573 * Install the interface into kernel networking data structures 574 */ 575int 576cs_attach(struct cs_softc *sc, int unit, int flags) 577{ 578 int media=0; 579 struct ifnet *ifp = &(sc->arpcom.ac_if); 580 581 cs_stop( sc ); 582 583 if (!ifp->if_name) { 584 ifp->if_softc=sc; 585 ifp->if_unit=unit; 586 ifp->if_name="cs"; 587 ifp->if_output=ether_output; 588 ifp->if_start=cs_start; 589 ifp->if_ioctl=cs_ioctl; 590 ifp->if_watchdog=cs_watchdog; 591 ifp->if_init=cs_init; 592 ifp->if_snd.ifq_maxlen= IFQ_MAXLEN; 593 /* 594 * MIB DATA 595 */ 596 /* 597 ifp->if_linkmib=&sc->mibdata; 598 ifp->if_linkmiblen=sizeof sc->mibdata; 599 */ 600 601 ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST ); 602 603 /* 604 * this code still in progress (DMA support) 605 * 606 607 sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT); 608 if (sc->recv_ring == NULL) { 609 log(LOG_ERR,CS_NAME 610 "%d: Couldn't allocate memory for NIC\n", unit); 611 return(0); 612 } 613 if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF)) 614 < (128*1024-CS_DMA_BUFFER_SIZE)) 615 sc->recv_ring+=16*1024; 616 617 */ 618 619 sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT); 620 if (sc->buffer == NULL) { 621 if_printf(ifp, "Couldn't allocate memory for NIC\n"); 622 return(0); 623 } 624 625 /* 626 * Initialize the media structures. 627 */ 628 ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus); 629 630 if (sc->adapter_cnf & A_CNF_10B_T) { 631 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL); 632 if (sc->chip_type != CS8900) { 633 ifmedia_add(&sc->media, 634 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 635 ifmedia_add(&sc->media, 636 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); 637 } 638 } 639 640 if (sc->adapter_cnf & A_CNF_10B_2) 641 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL); 642 643 if (sc->adapter_cnf & A_CNF_AUI) 644 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL); 645 646 if (sc->adapter_cnf & A_CNF_MEDIA) 647 ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL); 648 649 /* Set default media from EEPROM */ 650 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) { 651 case A_CNF_MEDIA_AUTO: media = IFM_ETHER|IFM_AUTO; break; 652 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break; 653 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break; 654 case A_CNF_MEDIA_AUI: media = IFM_ETHER|IFM_10_5; break; 655 default: if_printf(ifp, "adapter has no media\n"); 656 } 657 ifmedia_set(&sc->media, media); 658 cs_mediaset(sc, media); 659
|