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