if_cs.c revision 162321
1/*- 2 * Copyright (c) 1997,1998 Maxim Bolotin and Oleg Sharoiko. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/dev/cs/if_cs.c 162321 2006-09-15 15:16:12Z glebius $"); 31 32/* 33 * 34 * Device driver for Crystal Semiconductor CS8920 based ethernet 35 * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997 36 */ 37 38/* 39#define CS_DEBUG 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/malloc.h> 45#include <sys/mbuf.h> 46#include <sys/socket.h> 47#include <sys/sockio.h> 48#include <sys/kernel.h> 49#include <sys/sysctl.h> 50#include <sys/syslog.h> 51 52#include <sys/module.h> 53#include <sys/bus.h> 54#include <machine/bus.h> 55#include <sys/rman.h> 56#include <machine/resource.h> 57 58#include <net/if.h> 59#include <net/if_arp.h> 60#include <net/if_dl.h> 61#include <net/if_media.h> 62#include <net/if_types.h> 63#include <net/ethernet.h> 64#include <net/bpf.h> 65 66#include <dev/cs/if_csvar.h> 67#include <dev/cs/if_csreg.h> 68 69#ifdef CS_USE_64K_DMA 70#define CS_DMA_BUFFER_SIZE 65536 71#else 72#define CS_DMA_BUFFER_SIZE 16384 73#endif 74 75static void cs_init(void *); 76static int cs_ioctl(struct ifnet *, u_long, caddr_t); 77static void cs_start(struct ifnet *); 78static void cs_stop(struct cs_softc *); 79static void cs_reset(struct cs_softc *); 80static void cs_watchdog(struct ifnet *); 81 82static int cs_mediachange(struct ifnet *); 83static void cs_mediastatus(struct ifnet *, struct ifmediareq *); 84static int cs_mediaset(struct cs_softc *, int); 85 86static void cs_write_mbufs(struct cs_softc*, struct mbuf*); 87static void cs_xmit_buf(struct cs_softc*); 88static int cs_get_packet(struct cs_softc*); 89static void cs_setmode(struct cs_softc*); 90 91static int get_eeprom_data(struct cs_softc *sc, int, int, uint16_t *); 92static int get_eeprom_cksum(int, int, uint16_t *); 93static int wait_eeprom_ready( struct cs_softc *); 94static void control_dc_dc( struct cs_softc *, int ); 95static int send_test_pkt( struct cs_softc * ); 96static int enable_tp(struct cs_softc *); 97static int enable_aui(struct cs_softc *); 98static int enable_bnc(struct cs_softc *); 99static int cs_duplex_auto(struct cs_softc *); 100 101devclass_t cs_devclass; 102 103/* sysctl vars */ 104SYSCTL_NODE(_hw, OID_AUTO, cs, CTLFLAG_RD, 0, "cs device parameters"); 105 106int cs_debug = 0; 107TUNABLE_INT("hw.cs.debug", &cs_debug); 108SYSCTL_INT(_hw_cs, OID_AUTO, debug, CTLFLAG_RW, 109 &cs_debug, 0, 110 "cs debug"); 111 112int cs_ignore_cksum_failure = 0; 113TUNABLE_INT("hw.cs.ignore_checksum_failure", &cs_ignore_cksum_failure); 114SYSCTL_INT(_hw_cs, OID_AUTO, ignore_checksum_failure, CTLFLAG_RW, 115 &cs_ignore_cksum_failure, 0, 116 "ignore checksum errors in cs card EEPROM"); 117 118static int cs_recv_delay = 570; 119TUNABLE_INT("hw.cs.recv_delay", &cs_recv_delay); 120SYSCTL_INT(_hw_cs, OID_AUTO, recv_delay, CTLFLAG_RW, &cs_recv_delay, 570, ""); 121 122static int 123get_eeprom_data(struct cs_softc *sc, int off, int len, uint16_t *buffer) 124{ 125 int i; 126 127#ifdef CS_DEBUG 128 printf(CS_NAME":EEPROM data from %x for %x:\n", off, len); 129#endif 130 131 for (i=0; i < len; i++) { 132 if (wait_eeprom_ready(sc) < 0) 133 return (-1); 134 /* Send command to EEPROM to read */ 135 cs_writereg(sc, PP_EECMD, (off + i) | EEPROM_READ_CMD); 136 if (wait_eeprom_ready(sc) < 0) 137 return (-1); 138 buffer[i] = cs_readreg(sc, PP_EEData); 139 140#ifdef CS_DEBUG 141 printf("%02x %02x ",(unsigned char)buffer[i], 142 (unsigned char)buffer[i] >> 8); 143#endif 144 } 145 146#ifdef CS_DEBUG 147 printf("\n"); 148#endif 149 return (0); 150} 151 152static int 153get_eeprom_cksum(int off, int len, uint16_t *buffer) 154{ 155 int i; 156 uint16_t cksum=0; 157 158 for (i = 0; i < len; i++) 159 cksum += buffer[i]; 160 cksum &= 0xffff; 161 if (cksum==0) 162 return (0); 163 if (cs_ignore_cksum_failure) { 164 printf(CS_NAME": checksum mismatch, ignoring\n"); 165 return (0); 166 } 167 return (-1); 168} 169 170static int 171wait_eeprom_ready(struct cs_softc *sc) 172{ 173 DELAY(30000); /* XXX should we do some checks here ? */ 174 return (0); 175} 176 177static void 178control_dc_dc(struct cs_softc *sc, int on_not_off) 179{ 180 unsigned int self_control = HCB1_ENBL; 181 182 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off) 183 self_control |= HCB1; 184 else 185 self_control &= ~HCB1; 186 cs_writereg(sc, PP_SelfCTL, self_control); 187 188 DELAY(500000); 189} 190 191 192static int 193cs_duplex_auto(struct cs_softc *sc) 194{ 195 int i, error=0; 196 197 cs_writereg(sc, PP_AutoNegCTL, 198 RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE); 199 for (i=0; cs_readreg(sc, PP_AutoNegST) & AUTO_NEG_BUSY; i++) { 200 if (i > 40000) { 201 device_printf(sc->dev, 202 "full/half duplex auto negotiation timeout\n"); 203 error = ETIMEDOUT; 204 break; 205 } 206 DELAY(1000); 207 } 208 DELAY(1000000); 209 return (error); 210} 211 212static int 213enable_tp(struct cs_softc *sc) 214{ 215 216 cs_writereg(sc, PP_LineCTL, sc->line_ctl & ~AUI_ONLY); 217 control_dc_dc(sc, 0); 218 DELAY( 150000 ); 219 220 if ((cs_readreg(sc, PP_LineST) & LINK_OK)==0) { 221 device_printf(sc->dev, "failed to enable TP\n"); 222 return (EINVAL); 223 } 224 225 return (0); 226} 227 228/* 229 * XXX This was rewritten from Linux driver without any tests. 230 */ 231static int 232send_test_pkt(struct cs_softc *sc) 233{ 234 char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 235 0, 46, /* A 46 in network order */ 236 0, 0, /* DSAP=0 & SSAP=0 fields */ 237 0xf3, 0 /* Control (Test Req + P bit set) */ }; 238 int i; 239 u_char ether_address_backup[ETHER_ADDR_LEN]; 240 241 for (i = 0; i < ETHER_ADDR_LEN; i++) 242 ether_address_backup[i] = sc->enaddr[i]; 243 244 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_TX_ON); 245 bcopy(test_packet, sc->enaddr, ETHER_ADDR_LEN); 246 bcopy(test_packet+ETHER_ADDR_LEN, 247 sc->enaddr, ETHER_ADDR_LEN); 248 cs_outw(sc, TX_CMD_PORT, sc->send_cmd); 249 cs_outw(sc, TX_LEN_PORT, sizeof(test_packet)); 250 251 /* Wait for chip to allocate memory */ 252 DELAY(50000); 253 if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) { 254 for (i = 0; i < ETHER_ADDR_LEN; i++) 255 sc->enaddr[i] = ether_address_backup[i]; 256 return (0); 257 } 258 259 outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet)); 260 261 DELAY(30000); 262 263 for (i = 0; i < ETHER_ADDR_LEN; i++) 264 sc->enaddr[i] = ether_address_backup[i]; 265 if ((cs_readreg(sc, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) 266 return (1); 267 return (0); 268} 269 270/* 271 * XXX This was rewritten from Linux driver without any tests. 272 */ 273static int 274enable_aui(struct cs_softc *sc) 275{ 276 277 control_dc_dc(sc, 0); 278 cs_writereg(sc, PP_LineCTL, 279 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY); 280 281 if (!send_test_pkt(sc)) { 282 device_printf(sc->dev, "failed to enable AUI\n"); 283 return (EINVAL); 284 } 285 return (0); 286} 287 288/* 289 * XXX This was rewritten from Linux driver without any tests. 290 */ 291static int 292enable_bnc(struct cs_softc *sc) 293{ 294 295 control_dc_dc(sc, 1); 296 cs_writereg(sc, PP_LineCTL, 297 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY); 298 299 if (!send_test_pkt(sc)) { 300 device_printf(sc->dev, "failed to enable BNC\n"); 301 return (EINVAL); 302 } 303 return (0); 304} 305 306int 307cs_cs89x0_probe(device_t dev) 308{ 309 int i; 310 int error; 311 u_long irq, junk; 312 struct cs_softc *sc = device_get_softc(dev); 313 unsigned rev_type = 0; 314 uint16_t id; 315 char chip_revision; 316 uint16_t eeprom_buff[CHKSUM_LEN]; 317 int chip_type, pp_isaint, pp_isadma; 318 319 error = cs_alloc_port(dev, 0, CS_89x0_IO_PORTS); 320 if (error) 321 return (error); 322 323 sc->nic_addr = rman_get_start(sc->port_res); 324 325 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) { 326 /* Chip not detected. Let's try to reset it */ 327 if (bootverbose) 328 device_printf(dev, "trying to reset the chip.\n"); 329 cs_outw(sc, ADD_PORT, PP_SelfCTL); 330 i = cs_inw(sc, DATA_PORT); 331 cs_outw(sc, ADD_PORT, PP_SelfCTL); 332 cs_outw(sc, DATA_PORT, i | POWER_ON_RESET); 333 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) 334 return (ENXIO); 335 } 336 337 for (i = 0; i < 10000; i++) { 338 id = cs_readreg(sc, PP_ChipID); 339 if (id == CHIP_EISA_ID_SIG) 340 break; 341 } 342 if (i == 10000) 343 return (ENXIO); 344 345 rev_type = cs_readreg(sc, PRODUCT_ID_ADD); 346 chip_type = rev_type & ~REVISON_BITS; 347 chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A'; 348 349 sc->chip_type = chip_type; 350 351 if(chip_type==CS8900) { 352 pp_isaint = PP_CS8900_ISAINT; 353 pp_isadma = PP_CS8900_ISADMA; 354 sc->send_cmd = TX_CS8900_AFTER_ALL; 355 } else { 356 pp_isaint = PP_CS8920_ISAINT; 357 pp_isadma = PP_CS8920_ISADMA; 358 sc->send_cmd = TX_CS8920_AFTER_ALL; 359 } 360 361 /* 362 * Clear some fields so that fail of EEPROM will left them clean 363 */ 364 sc->auto_neg_cnf = 0; 365 sc->adapter_cnf = 0; 366 sc->isa_config = 0; 367 368 /* 369 * If no interrupt specified (or "?"), use what the board tells us. 370 */ 371 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk); 372 373 /* 374 * Get data from EEPROM 375 */ 376 if((cs_readreg(sc, PP_SelfST) & EEPROM_PRESENT) == 0) { 377 device_printf(dev, "No EEPROM, assuming defaults.\n"); 378 } else { 379 if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) { 380 device_printf(dev, "EEPROM read failed, " 381 "assuming defaults.\n"); 382 } else { 383 if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) { 384 device_printf(dev, "EEPROM cheksum bad, " 385 "assuming defaults.\n"); 386 } else { 387 sc->auto_neg_cnf = 388 eeprom_buff[AUTO_NEG_CNF_OFFSET/2]; 389 sc->adapter_cnf = 390 eeprom_buff[ADAPTER_CNF_OFFSET/2]; 391 sc->isa_config = 392 eeprom_buff[ISA_CNF_OFFSET/2]; 393 394 for (i=0; i<ETHER_ADDR_LEN/2; i++) { 395 sc->enaddr[i*2]= 396 eeprom_buff[i]; 397 sc->enaddr[i*2+1]= 398 eeprom_buff[i] >> 8; 399 } 400 401 /* 402 * If no interrupt specified, 403 * use what the board tells us. 404 */ 405 if (error) { 406 irq = sc->isa_config & INT_NO_MASK; 407 error = 0; 408 if (chip_type==CS8900) { 409 switch(irq) { 410 case 0: 411 irq=10; 412 break; 413 case 1: 414 irq=11; 415 break; 416 case 2: 417 irq=12; 418 break; 419 case 3: 420 irq=5; 421 break; 422 default: 423 device_printf(dev, "invalid irq in EEPROM.\n"); 424 error=EINVAL; 425 } 426 } else { 427 if (irq>CS8920_NO_INTS) { 428 device_printf(dev, "invalid irq in EEPROM.\n"); 429 error=EINVAL; 430 } 431 } 432 if (!error) 433 bus_set_resource(dev, SYS_RES_IRQ, 0, 434 irq, 1); 435 } 436 } 437 } 438 } 439 440 if (!error) { 441 if (chip_type == CS8900) { 442 switch(irq) { 443 case 5: 444 irq = 3; 445 break; 446 case 10: 447 irq = 0; 448 break; 449 case 11: 450 irq = 1; 451 break; 452 case 12: 453 irq = 2; 454 break; 455 default: 456 error=EINVAL; 457 } 458 } else { 459 if (irq > CS8920_NO_INTS) { 460 error = EINVAL; 461 } 462 } 463 } 464 465 if (!error) { 466 if (!(sc->flags & CS_NO_IRQ)) 467 cs_writereg(sc, pp_isaint, irq); 468 } else { 469 device_printf(dev, "Unknown or invalid irq\n"); 470 return (ENXIO); 471 } 472 473 /* 474 * Temporary disabled 475 * 476 if (drq>0) 477 cs_writereg(sc, pp_isadma, drq); 478 else { 479 device_printf(dev, "incorrect drq\n",); 480 return (0); 481 } 482 */ 483 484 if (bootverbose) 485 device_printf(dev, "CS89%c0%s rev %c media%s%s%s\n", 486 chip_type==CS8900 ? '0' : '2', 487 chip_type==CS8920M ? "M" : "", 488 chip_revision, 489 (sc->adapter_cnf & A_CNF_10B_T) ? " TP" : "", 490 (sc->adapter_cnf & A_CNF_AUI) ? " AUI" : "", 491 (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : ""); 492 493 if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) && 494 (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH)) 495 sc->line_ctl = LOW_RX_SQUELCH; 496 else 497 sc->line_ctl = 0; 498 499 return (0); 500} 501 502/* 503 * Allocate a port resource with the given resource id. 504 */ 505int cs_alloc_port(device_t dev, int rid, int size) 506{ 507 struct cs_softc *sc = device_get_softc(dev); 508 struct resource *res; 509 510 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 511 0ul, ~0ul, size, RF_ACTIVE); 512 if (res == NULL) 513 return (ENOENT); 514 sc->port_rid = rid; 515 sc->port_res = res; 516 sc->port_used = size; 517 return (0); 518} 519 520/* 521 * Allocate a memory resource with the given resource id. 522 */ 523int cs_alloc_memory(device_t dev, int rid, int size) 524{ 525 struct cs_softc *sc = device_get_softc(dev); 526 struct resource *res; 527 528 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 529 0ul, ~0ul, size, RF_ACTIVE); 530 if (res == NULL) 531 return (ENOENT); 532 sc->mem_rid = rid; 533 sc->mem_res = res; 534 sc->mem_used = size; 535 return (0); 536} 537 538/* 539 * Allocate an irq resource with the given resource id. 540 */ 541int cs_alloc_irq(device_t dev, int rid, int flags) 542{ 543 struct cs_softc *sc = device_get_softc(dev); 544 struct resource *res; 545 546 res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 547 (RF_ACTIVE | flags)); 548 if (res == NULL) 549 return (ENOENT); 550 sc->irq_rid = rid; 551 sc->irq_res = res; 552 return (0); 553} 554 555/* 556 * Release all resources 557 */ 558void cs_release_resources(device_t dev) 559{ 560 struct cs_softc *sc = device_get_softc(dev); 561 562 if (sc->port_res) { 563 bus_release_resource(dev, SYS_RES_IOPORT, 564 sc->port_rid, sc->port_res); 565 sc->port_res = 0; 566 } 567 if (sc->mem_res) { 568 bus_release_resource(dev, SYS_RES_MEMORY, 569 sc->mem_rid, sc->mem_res); 570 sc->mem_res = 0; 571 } 572 if (sc->irq_res) { 573 bus_release_resource(dev, SYS_RES_IRQ, 574 sc->irq_rid, sc->irq_res); 575 sc->irq_res = 0; 576 } 577} 578 579/* 580 * Install the interface into kernel networking data structures 581 */ 582int 583cs_attach(device_t dev) 584{ 585 int media=0; 586 struct cs_softc *sc = device_get_softc(dev);; 587 struct ifnet *ifp; 588 589 sc->dev = dev; 590 591 ifp = sc->ifp = if_alloc(IFT_ETHER); 592 if (ifp == NULL) { 593 device_printf(dev, "can not if_alloc()\n"); 594 return (0); 595 } 596 597 cs_stop( sc ); 598 599 ifp->if_softc=sc; 600 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 601 ifp->if_start=cs_start; 602 ifp->if_ioctl=cs_ioctl; 603 ifp->if_watchdog=cs_watchdog; 604 ifp->if_init=cs_init; 605 ifp->if_snd.ifq_maxlen= IFQ_MAXLEN; 606 /* 607 * MIB DATA 608 */ 609 /* 610 ifp->if_linkmib=&sc->mibdata; 611 ifp->if_linkmiblen=sizeof sc->mibdata; 612 */ 613 614 ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | 615 IFF_NEEDSGIANT); 616 617 /* 618 * this code still in progress (DMA support) 619 * 620 621 sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT); 622 if (sc->recv_ring == NULL) { 623 log(LOG_ERR, 624 "%s: Couldn't allocate memory for NIC\n", ifp->if_xname); 625 return(0); 626 } 627 if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF)) 628 < (128*1024-CS_DMA_BUFFER_SIZE)) 629 sc->recv_ring+=16*1024; 630 631 */ 632 633 sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT); 634 if (sc->buffer == NULL) { 635 device_printf(sc->dev, "Couldn't allocate memory for NIC\n"); 636 return(0); 637 } 638 639 /* 640 * Initialize the media structures. 641 */ 642 ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus); 643 644 if (sc->adapter_cnf & A_CNF_10B_T) { 645 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL); 646 if (sc->chip_type != CS8900) { 647 ifmedia_add(&sc->media, 648 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 649 ifmedia_add(&sc->media, 650 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); 651 } 652 } 653 654 if (sc->adapter_cnf & A_CNF_10B_2) 655 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL); 656 657 if (sc->adapter_cnf & A_CNF_AUI) 658 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL); 659 660 if (sc->adapter_cnf & A_CNF_MEDIA) 661 ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL); 662 663 /* Set default media from EEPROM */ 664 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) { 665 case A_CNF_MEDIA_AUTO: media = IFM_ETHER|IFM_AUTO; break; 666 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break; 667 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break; 668 case A_CNF_MEDIA_AUI: media = IFM_ETHER|IFM_10_5; break; 669 default: 670 device_printf(sc->dev, "no media, assuming 10baseT\n"); 671 sc->adapter_cnf |= A_CNF_10B_T; 672 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL); 673 if (sc->chip_type != CS8900) { 674 ifmedia_add(&sc->media, 675 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 676 ifmedia_add(&sc->media, 677 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); 678 } 679 media = IFM_ETHER | IFM_10_T; 680 break; 681 } 682 ifmedia_set(&sc->media, media); 683 cs_mediaset(sc, media); 684 685 ether_ifattach(ifp, sc->enaddr); 686 687 return (0); 688} 689 690int 691cs_detach(device_t dev) 692{ 693 struct cs_softc *sc; 694 struct ifnet *ifp; 695 696 sc = device_get_softc(dev); 697 ifp = sc->ifp; 698 699 cs_stop(sc); 700 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 701 ether_ifdetach(ifp); 702 cs_release_resources(dev); 703 if_free(ifp); 704 return (0); 705} 706 707/* 708 * Initialize the board 709 */ 710static void 711cs_init(void *xsc) 712{ 713 struct cs_softc *sc=(struct cs_softc *)xsc; 714 struct ifnet *ifp = sc->ifp; 715 int i, s, rx_cfg; 716 717 /* 718 * reset whatchdog timer 719 */ 720 ifp->if_timer=0; 721 sc->buf_len = 0; 722 723 s=splimp(); 724 725 /* 726 * Hardware initialization of cs 727 */ 728 729 /* Enable receiver and transmitter */ 730 cs_writereg(sc, PP_LineCTL, 731 cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON); 732 733 /* Configure the receiver mode */ 734 cs_setmode(sc); 735 736 /* 737 * This defines what type of frames will cause interrupts 738 * Bad frames should generate interrupts so that the driver 739 * could track statistics of discarded packets 740 */ 741 rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | 742 RX_EXTRA_DATA_ENBL; 743 if (sc->isa_config & STREAM_TRANSFER) 744 rx_cfg |= RX_STREAM_ENBL; 745 cs_writereg(sc, PP_RxCFG, rx_cfg); 746 cs_writereg(sc, PP_TxCFG, TX_LOST_CRS_ENBL | 747 TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL | 748 TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); 749 cs_writereg(sc, PP_BufCFG, READY_FOR_TX_ENBL | 750 RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL | 751 TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/); 752 753 /* Write MAC address into IA filter */ 754 for (i=0; i<ETHER_ADDR_LEN/2; i++) 755 cs_writereg(sc, PP_IA + i * 2, 756 sc->enaddr[i * 2] | 757 (sc->enaddr[i * 2 + 1] << 8) ); 758 759 /* 760 * Now enable everything 761 */ 762/* 763#ifdef CS_USE_64K_DMA 764 cs_writereg(sc, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K); 765#else 766 cs_writereg(sc, PP_BusCTL, ENABLE_IRQ); 767#endif 768*/ 769 cs_writereg(sc, PP_BusCTL, ENABLE_IRQ); 770 771 /* 772 * Set running and clear output active flags 773 */ 774 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 775 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 776 777 /* 778 * Start sending process 779 */ 780 cs_start(ifp); 781 782 (void) splx(s); 783} 784 785/* 786 * Get the packet from the board and send it to the upper layer. 787 */ 788static int 789cs_get_packet(struct cs_softc *sc) 790{ 791 struct ifnet *ifp = sc->ifp; 792 int iobase = sc->nic_addr, status, length; 793 struct ether_header *eh; 794 struct mbuf *m; 795 796#ifdef CS_DEBUG 797 int i; 798#endif 799 800 status = cs_inw(sc, RX_FRAME_PORT); 801 length = cs_inw(sc, RX_FRAME_PORT); 802 803#ifdef CS_DEBUG 804 device_printf(sc->dev, "rcvd: stat %x, len %d\n", 805 status, length); 806#endif 807 808 if (!(status & RX_OK)) { 809#ifdef CS_DEBUG 810 device_printf(sc->dev, "bad pkt stat %x\n", status); 811#endif 812 ifp->if_ierrors++; 813 return (-1); 814 } 815 816 MGETHDR(m, M_DONTWAIT, MT_DATA); 817 if (m==NULL) 818 return (-1); 819 820 if (length > MHLEN) { 821 MCLGET(m, M_DONTWAIT); 822 if (!(m->m_flags & M_EXT)) { 823 m_freem(m); 824 return (-1); 825 } 826 } 827 828 /* Initialize packet's header info */ 829 m->m_pkthdr.rcvif = ifp; 830 m->m_pkthdr.len = length; 831 m->m_len = length; 832 833 /* Get the data */ 834 insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1); 835 836 eh = mtod(m, struct ether_header *); 837 838#ifdef CS_DEBUG 839 for (i=0;i<length;i++) 840 printf(" %02x",(unsigned char)*((char *)(m->m_data+i))); 841 printf( "\n" ); 842#endif 843 844 if (status & (RX_IA | RX_BROADCAST) || 845 (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) { 846 /* Feed the packet to the upper layer */ 847 (*ifp->if_input)(ifp, m); 848 ifp->if_ipackets++; 849 if (length == ETHER_MAX_LEN-ETHER_CRC_LEN) 850 DELAY(cs_recv_delay); 851 } else { 852 m_freem(m); 853 } 854 855 return (0); 856} 857 858/* 859 * Handle interrupts 860 */ 861void 862csintr(void *arg) 863{ 864 struct cs_softc *sc = (struct cs_softc*) arg; 865 struct ifnet *ifp = sc->ifp; 866 int status; 867 868#ifdef CS_DEBUG 869 device_printf(sc->dev, "Interrupt.\n"); 870#endif 871 872 while ((status=cs_inw(sc, ISQ_PORT))) { 873 874#ifdef CS_DEBUG 875 device_printf(sc->dev, "from ISQ: %04x\n", status); 876#endif 877 878 switch (status & ISQ_EVENT_MASK) { 879 case ISQ_RECEIVER_EVENT: 880 cs_get_packet(sc); 881 break; 882 883 case ISQ_TRANSMITTER_EVENT: 884 if (status & TX_OK) 885 ifp->if_opackets++; 886 else 887 ifp->if_oerrors++; 888 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 889 ifp->if_timer = 0; 890 break; 891 892 case ISQ_BUFFER_EVENT: 893 if (status & READY_FOR_TX) { 894 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 895 ifp->if_timer = 0; 896 } 897 898 if (status & TX_UNDERRUN) { 899 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 900 ifp->if_timer = 0; 901 ifp->if_oerrors++; 902 } 903 break; 904 905 case ISQ_RX_MISS_EVENT: 906 ifp->if_ierrors+=(status>>6); 907 break; 908 909 case ISQ_TX_COL_EVENT: 910 ifp->if_collisions+=(status>>6); 911 break; 912 } 913 } 914 915 if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE)) { 916 cs_start(ifp); 917 } 918} 919 920/* 921 * Save the data in buffer 922 */ 923 924static void 925cs_write_mbufs( struct cs_softc *sc, struct mbuf *m ) 926{ 927 int len; 928 struct mbuf *mp; 929 unsigned char *data, *buf; 930 931 for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) { 932 len = mp->m_len; 933 934 /* 935 * Ignore empty parts 936 */ 937 if (!len) 938 continue; 939 940 /* 941 * Find actual data address 942 */ 943 data = mtod(mp, caddr_t); 944 945 bcopy((caddr_t) data, (caddr_t) buf, len); 946 buf += len; 947 sc->buf_len += len; 948 } 949} 950 951 952static void 953cs_xmit_buf( struct cs_softc *sc ) 954{ 955 outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1); 956 sc->buf_len = 0; 957} 958 959static void 960cs_start(struct ifnet *ifp) 961{ 962 int s, length; 963 struct mbuf *m, *mp; 964 struct cs_softc *sc = ifp->if_softc; 965 966 s = splimp(); 967 968 for (;;) { 969 if (sc->buf_len) 970 length = sc->buf_len; 971 else { 972 IF_DEQUEUE( &ifp->if_snd, m ); 973 974 if (m==NULL) { 975 (void) splx(s); 976 return; 977 } 978 979 for (length=0, mp=m; mp != NULL; mp=mp->m_next) 980 length += mp->m_len; 981 982 /* Skip zero-length packets */ 983 if (length == 0) { 984 m_freem(m); 985 continue; 986 } 987 988 cs_write_mbufs(sc, m); 989 990 BPF_MTAP(ifp, m); 991 992 m_freem(m); 993 } 994 995 /* 996 * Issue a SEND command 997 */ 998 cs_outw(sc, TX_CMD_PORT, sc->send_cmd); 999 cs_outw(sc, TX_LEN_PORT, length ); 1000 1001 /* 1002 * If there's no free space in the buffer then leave 1003 * this packet for the next time: indicate output active 1004 * and return. 1005 */ 1006 if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) { 1007 ifp->if_timer = sc->buf_len; 1008 (void) splx(s); 1009 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1010 return; 1011 } 1012 1013 cs_xmit_buf(sc); 1014 1015 /* 1016 * Set the watchdog timer in case we never hear 1017 * from board again. (I don't know about correct 1018 * value for this timeout) 1019 */ 1020 ifp->if_timer = length; 1021 1022 (void) splx(s); 1023 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1024 return; 1025 } 1026} 1027 1028/* 1029 * Stop everything on the interface 1030 */ 1031static void 1032cs_stop(struct cs_softc *sc) 1033{ 1034 int s = splimp(); 1035 1036 cs_writereg(sc, PP_RxCFG, 0); 1037 cs_writereg(sc, PP_TxCFG, 0); 1038 cs_writereg(sc, PP_BufCFG, 0); 1039 cs_writereg(sc, PP_BusCTL, 0); 1040 1041 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1042 sc->ifp->if_timer = 0; 1043 1044 (void) splx(s); 1045} 1046 1047/* 1048 * Reset the interface 1049 */ 1050static void 1051cs_reset(struct cs_softc *sc) 1052{ 1053 cs_stop(sc); 1054 cs_init(sc); 1055} 1056 1057static uint16_t 1058cs_hash_index(struct sockaddr_dl *addr) 1059{ 1060 uint32_t crc; 1061 uint16_t idx; 1062 caddr_t lla; 1063 1064 lla = LLADDR(addr); 1065 crc = ether_crc32_le(lla, ETHER_ADDR_LEN); 1066 idx = crc >> 26; 1067 1068 return (idx); 1069} 1070 1071static void 1072cs_setmode(struct cs_softc *sc) 1073{ 1074 int rx_ctl; 1075 uint16_t af[4]; 1076 uint16_t port, mask, index; 1077 struct ifnet *ifp = sc->ifp; 1078 struct ifmultiaddr *ifma; 1079 1080 /* Stop the receiver while changing filters */ 1081 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) & ~SERIAL_RX_ON); 1082 1083 if (ifp->if_flags & IFF_PROMISC) { 1084 /* Turn on promiscuous mode. */ 1085 rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT; 1086 } else if (ifp->if_flags & IFF_MULTICAST) { 1087 /* Allow receiving frames with multicast addresses */ 1088 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | 1089 RX_OK_ACCEPT | RX_MULTCAST_ACCEPT; 1090 1091 /* Start with an empty filter */ 1092 af[0] = af[1] = af[2] = af[3] = 0x0000; 1093 1094 if (ifp->if_flags & IFF_ALLMULTI) { 1095 /* Accept all multicast frames */ 1096 af[0] = af[1] = af[2] = af[3] = 0xffff; 1097 } else { 1098 /* 1099 * Set up the filter to only accept multicast 1100 * frames we're interested in. 1101 */ 1102 IF_ADDR_LOCK(ifp); 1103 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1104 struct sockaddr_dl *dl = 1105 (struct sockaddr_dl *)ifma->ifma_addr; 1106 1107 index = cs_hash_index(dl); 1108 port = (u_int16_t) (index >> 4); 1109 mask = (u_int16_t) (1 << (index & 0xf)); 1110 af[port] |= mask; 1111 } 1112 IF_ADDR_UNLOCK(ifp); 1113 } 1114 1115 cs_writereg(sc, PP_LAF + 0, af[0]); 1116 cs_writereg(sc, PP_LAF + 2, af[1]); 1117 cs_writereg(sc, PP_LAF + 4, af[2]); 1118 cs_writereg(sc, PP_LAF + 6, af[3]); 1119 } else { 1120 /* 1121 * Receive only good frames addressed for us and 1122 * good broadcasts. 1123 */ 1124 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | 1125 RX_OK_ACCEPT; 1126 } 1127 1128 /* Set up the filter */ 1129 cs_writereg(sc, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl); 1130 1131 /* Turn on receiver */ 1132 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON); 1133} 1134 1135static int 1136cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data) 1137{ 1138 struct cs_softc *sc=ifp->if_softc; 1139 struct ifreq *ifr = (struct ifreq *)data; 1140 int s,error=0; 1141 1142#ifdef CS_DEBUG 1143 if_printf(ifp, "%s command=%lx\n", __func__, command); 1144#endif 1145 1146 s=splimp(); 1147 1148 switch (command) { 1149 case SIOCSIFFLAGS: 1150 /* 1151 * Switch interface state between "running" and 1152 * "stopped", reflecting the UP flag. 1153 */ 1154 if (sc->ifp->if_flags & IFF_UP) { 1155 if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)==0) { 1156 cs_init(sc); 1157 } 1158 } else { 1159 if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)!=0) { 1160 cs_stop(sc); 1161 } 1162 } 1163 /* 1164 * Promiscuous and/or multicast flags may have changed, 1165 * so reprogram the multicast filter and/or receive mode. 1166 * 1167 * See note about multicasts in cs_setmode 1168 */ 1169 cs_setmode(sc); 1170 break; 1171 1172 case SIOCADDMULTI: 1173 case SIOCDELMULTI: 1174 /* 1175 * Multicast list has changed; set the hardware filter 1176 * accordingly. 1177 * 1178 * See note about multicasts in cs_setmode 1179 */ 1180 cs_setmode(sc); 1181 error = 0; 1182 break; 1183 1184 case SIOCSIFMEDIA: 1185 case SIOCGIFMEDIA: 1186 error = ifmedia_ioctl(ifp, ifr, &sc->media, command); 1187 break; 1188 1189 default: 1190 error = ether_ioctl(ifp, command, data); 1191 break; 1192 } 1193 1194 (void) splx(s); 1195 return (error); 1196} 1197 1198/* 1199 * Device timeout/watchdog routine. Entered if the device neglects to 1200 * generate an interrupt after a transmit has been started on it. 1201 */ 1202static void 1203cs_watchdog(struct ifnet *ifp) 1204{ 1205 struct cs_softc *sc = ifp->if_softc; 1206 1207 ifp->if_oerrors++; 1208 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname); 1209 1210 /* Reset the interface */ 1211 if (ifp->if_flags & IFF_UP) 1212 cs_reset(sc); 1213 else 1214 cs_stop(sc); 1215} 1216 1217static int 1218cs_mediachange(struct ifnet *ifp) 1219{ 1220 struct cs_softc *sc = ifp->if_softc; 1221 struct ifmedia *ifm = &sc->media; 1222 1223 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1224 return (EINVAL); 1225 1226 return (cs_mediaset(sc, ifm->ifm_media)); 1227} 1228 1229static void 1230cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1231{ 1232 int line_status; 1233 struct cs_softc *sc = ifp->if_softc; 1234 1235 ifmr->ifm_active = IFM_ETHER; 1236 line_status = cs_readreg(sc, PP_LineST); 1237 if (line_status & TENBASET_ON) { 1238 ifmr->ifm_active |= IFM_10_T; 1239 if (sc->chip_type != CS8900) { 1240 if (cs_readreg(sc, PP_AutoNegST) & FDX_ACTIVE) 1241 ifmr->ifm_active |= IFM_FDX; 1242 if (cs_readreg(sc, PP_AutoNegST) & HDX_ACTIVE) 1243 ifmr->ifm_active |= IFM_HDX; 1244 } 1245 ifmr->ifm_status = IFM_AVALID; 1246 if (line_status & LINK_OK) 1247 ifmr->ifm_status |= IFM_ACTIVE; 1248 } else { 1249 if (line_status & AUI_ON) { 1250 cs_writereg(sc, PP_SelfCTL, cs_readreg(sc, PP_SelfCTL) | 1251 HCB1_ENBL); 1252 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^ 1253 (cs_readreg(sc, PP_SelfCTL) & HCB1)) 1254 ifmr->ifm_active |= IFM_10_2; 1255 else 1256 ifmr->ifm_active |= IFM_10_5; 1257 } 1258 } 1259} 1260 1261static int 1262cs_mediaset(struct cs_softc *sc, int media) 1263{ 1264 int error; 1265 1266 /* Stop the receiver & transmitter */ 1267 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) & 1268 ~(SERIAL_RX_ON | SERIAL_TX_ON)); 1269 1270#ifdef CS_DEBUG 1271 device_printf(sc->dev, "%s media=%x\n", __func__, media); 1272#endif 1273 1274 switch (IFM_SUBTYPE(media)) { 1275 default: 1276 case IFM_AUTO: 1277 if ((error=enable_tp(sc))==0) 1278 error = cs_duplex_auto(sc); 1279 else if ((error=enable_bnc(sc)) != 0) 1280 error = enable_aui(sc); 1281 break; 1282 case IFM_10_T: 1283 if ((error=enable_tp(sc)) != 0) 1284 break; 1285 if (media & IFM_FDX) 1286 cs_duplex_full(sc); 1287 else if (media & IFM_HDX) 1288 cs_duplex_half(sc); 1289 else 1290 error = cs_duplex_auto(sc); 1291 break; 1292 case IFM_10_2: 1293 error = enable_bnc(sc); 1294 break; 1295 case IFM_10_5: 1296 error = enable_aui(sc); 1297 break; 1298 } 1299 1300 /* 1301 * Turn the transmitter & receiver back on 1302 */ 1303 cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | 1304 SERIAL_RX_ON | SERIAL_TX_ON); 1305 1306 return (error); 1307} 1308