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