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