1 /* 2 * 3c595.c -- 3COM 3C595 Fast Etherlink III PCI driver for etherboot 3 * 4 * Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp> 5 * All rights reserved. 6 * Mar. 14, 2000 7 * 8 * This software may be used, modified, copied, distributed, and sold, in 9 * both source and binary form provided that the above copyright and these 10 * terms are retained. Under no circumstances are the authors responsible for 11 * the proper functioning of this software, nor do the authors assume any 12 * responsibility for damages incurred with its use. 13 * 14 * This code is based on Martin Renters' etherboot-4.4.3 3c509.c and 15 * Herb Peyerl's FreeBSD 3.4-RELEASE if_vx.c driver. 16 * 17 * Copyright (C) 1993-1994, David Greenman, Martin Renters. 18 * Copyright (C) 1993-1995, Andres Vega Garcia. 19 * Copyright (C) 1995, Serge Babkin. 20 * 21 * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> 22 * 23 * timlegge 08-24-2003 Add Multicast Support 24 */ 25 26 /* #define EDEBUG */ 27 28 #include "etherboot.h" 29 #include "nic.h" 30 #include "pci.h" 31 #include "3c595.h" 32 #include "timer.h" 33 34 static unsigned short eth_nic_base; 35 static unsigned short vx_connector, vx_connectors; 36 37 static struct connector_entry { 38 int bit; 39 char *name; 40 } conn_tab[VX_CONNECTORS] = { 41 #define CONNECTOR_UTP 0 42 { 0x08, "utp"}, 43 #define CONNECTOR_AUI 1 44 { 0x20, "aui"}, 45 /* dummy */ 46 { 0, "???"}, 47 #define CONNECTOR_BNC 3 48 { 0x10, "bnc"}, 49 #define CONNECTOR_TX 4 50 { 0x02, "tx"}, 51 #define CONNECTOR_FX 5 52 { 0x04, "fx"}, 53 #define CONNECTOR_MII 6 54 { 0x40, "mii"}, 55 { 0, "???"} 56 }; 57 58 static void vxgetlink(void); 59 static void vxsetlink(void); 60 61 /************************************************************************** 62 ETH_RESET - Reset adapter 63 ***************************************************************************/ 64 static void t595_reset(struct nic *nic) 65 { 66 int i; 67 68 /*********************************************************** 69 Reset 3Com 595 card 70 *************************************************************/ 71 72 /* stop card */ 73 outw(RX_DISABLE, BASE + VX_COMMAND); 74 outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); 75 VX_BUSY_WAIT; 76 outw(TX_DISABLE, BASE + VX_COMMAND); 77 outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); 78 udelay(8000); 79 outw(RX_RESET, BASE + VX_COMMAND); 80 VX_BUSY_WAIT; 81 outw(TX_RESET, BASE + VX_COMMAND); 82 VX_BUSY_WAIT; 83 outw(C_INTR_LATCH, BASE + VX_COMMAND); 84 outw(SET_RD_0_MASK, BASE + VX_COMMAND); 85 outw(SET_INTR_MASK, BASE + VX_COMMAND); 86 outw(SET_RX_FILTER, BASE + VX_COMMAND); 87 88 /* 89 * initialize card 90 */ 91 VX_BUSY_WAIT; 92 93 GO_WINDOW(0); 94 95 /* Disable the card */ 96 /* outw(0, BASE + VX_W0_CONFIG_CTRL); */ 97 98 /* Configure IRQ to none */ 99 /* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */ 100 101 /* Enable the card */ 102 /* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */ 103 104 GO_WINDOW(2); 105 106 /* Reload the ether_addr. */ 107 for (i = 0; i < ETH_ALEN; i++) 108 outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i); 109 110 outw(RX_RESET, BASE + VX_COMMAND); 111 VX_BUSY_WAIT; 112 outw(TX_RESET, BASE + VX_COMMAND); 113 VX_BUSY_WAIT; 114 115 /* Window 1 is operating window */ 116 GO_WINDOW(1); 117 for (i = 0; i < 31; i++) 118 inb(BASE + VX_W1_TX_STATUS); 119 120 outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | 121 S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); 122 outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | 123 S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); 124 125 /* 126 * Attempt to get rid of any stray interrupts that occured during 127 * configuration. On the i386 this isn't possible because one may 128 * already be queued. However, a single stray interrupt is 129 * unimportant. 130 */ 131 132 outw(ACK_INTR | 0xff, BASE + VX_COMMAND); 133 134 outw(SET_RX_FILTER | FIL_INDIVIDUAL | 135 FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND); 136 137 vxsetlink(); 138 /*{ 139 int i,j; 140 i = CONNECTOR_TX; 141 GO_WINDOW(3); 142 j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; 143 outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS)); 144 GO_WINDOW(4); 145 outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE); 146 GO_WINDOW(1); 147 }*/ 148 149 /* start tranciever and receiver */ 150 outw(RX_ENABLE, BASE + VX_COMMAND); 151 outw(TX_ENABLE, BASE + VX_COMMAND); 152 153 } 154 155 /************************************************************************** 156 ETH_TRANSMIT - Transmit a frame 157 ***************************************************************************/ 158 static char padmap[] = { 159 0, 3, 2, 1}; 160 161 static void t595_transmit( 162 struct nic *nic, 163 const char *d, /* Destination */ 164 unsigned int t, /* Type */ 165 unsigned int s, /* size */ 166 const char *p) /* Packet */ 167 { 168 register int len; 169 int pad; 170 int status; 171 172 #ifdef EDEBUG 173 printf("{l=%d,t=%hX}",s+ETH_HLEN,t); 174 #endif 175 176 /* swap bytes of type */ 177 t= htons(t); 178 179 len=s+ETH_HLEN; /* actual length of packet */ 180 pad = padmap[len & 3]; 181 182 /* 183 * The 3c595 automatically pads short packets to minimum ethernet length, 184 * but we drop packets that are too large. Perhaps we should truncate 185 * them instead? 186 */ 187 if (len + pad > ETH_FRAME_LEN) { 188 return; 189 } 190 191 /* drop acknowledgements */ 192 while(( status=inb(BASE + VX_W1_TX_STATUS) )& TXS_COMPLETE ) { 193 if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { 194 outw(TX_RESET, BASE + VX_COMMAND); 195 outw(TX_ENABLE, BASE + VX_COMMAND); 196 } 197 198 outb(0x0, BASE + VX_W1_TX_STATUS); 199 } 200 201 while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) { 202 /* no room in FIFO */ 203 } 204 205 outw(len, BASE + VX_W1_TX_PIO_WR_1); 206 outw(0x0, BASE + VX_W1_TX_PIO_WR_1); /* Second dword meaningless */ 207 208 /* write packet */ 209 outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2); 210 outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2); 211 outw(t, BASE + VX_W1_TX_PIO_WR_1); 212 outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2); 213 if (s & 1) 214 outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1); 215 216 while (pad--) 217 outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */ 218 219 /* wait for Tx complete */ 220 while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0) 221 ; 222 } 223 224 /************************************************************************** 225 ETH_POLL - Wait for a frame 226 ***************************************************************************/ 227 static int t595_poll(struct nic *nic, int retrieve) 228 { 229 /* common variables */ 230 /* variables for 3C595 */ 231 short status, cst; 232 register short rx_fifo; 233 234 cst=inw(BASE + VX_STATUS); 235 236 #ifdef EDEBUG 237 if(cst & 0x1FFF) 238 printf("-%hX-",cst); 239 #endif 240 241 if( (cst & S_RX_COMPLETE)==0 ) { 242 /* acknowledge everything */ 243 outw(ACK_INTR | cst, BASE + VX_COMMAND); 244 outw(C_INTR_LATCH, BASE + VX_COMMAND); 245 246 return 0; 247 } 248 249 status = inw(BASE + VX_W1_RX_STATUS); 250 #ifdef EDEBUG 251 printf("*%hX*",status); 252 #endif 253 254 if (status & ERR_RX) { 255 outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); 256 return 0; 257 } 258 259 rx_fifo = status & RX_BYTES_MASK; 260 if (rx_fifo==0) 261 return 0; 262 263 if ( ! retrieve ) return 1; 264 265 /* read packet */ 266 #ifdef EDEBUG 267 printf("[l=%d",rx_fifo); 268 #endif 269 insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2); 270 if(rx_fifo & 1) 271 nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1); 272 nic->packetlen=rx_fifo; 273 274 while(1) { 275 status = inw(BASE + VX_W1_RX_STATUS); 276 #ifdef EDEBUG 277 printf("*%hX*",status); 278 #endif 279 rx_fifo = status & RX_BYTES_MASK; 280 281 if(rx_fifo>0) { 282 insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2); 283 if(rx_fifo & 1) 284 nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1); 285 nic->packetlen+=rx_fifo; 286 #ifdef EDEBUG 287 printf("+%d",rx_fifo); 288 #endif 289 } 290 if(( status & RX_INCOMPLETE )==0) { 291 #ifdef EDEBUG 292 printf("=%d",nic->packetlen); 293 #endif 294 break; 295 } 296 udelay(1000); 297 } 298 299 /* acknowledge reception of packet */ 300 outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); 301 while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS); 302 #ifdef EDEBUG 303 { 304 unsigned short type = 0; /* used by EDEBUG */ 305 type = (nic->packet[12]<<8) | nic->packet[13]; 306 if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+ 307 nic->packet[5] == 0xFF*ETH_ALEN) 308 printf(",t=%hX,b]",type); 309 else 310 printf(",t=%hX]",type); 311 } 312 #endif 313 return 1; 314 } 315 316 317 /************************************************************************* 318 3Com 595 - specific routines 319 **************************************************************************/ 320 321 static int 322 eeprom_rdy() 323 { 324 int i; 325 326 for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++) 327 udelay(1000); 328 if (i >= MAX_EEPROMBUSY) { 329 /* printf("3c595: eeprom failed to come ready.\n"); */ 330 printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */ 331 return (0); 332 } 333 return (1); 334 } 335 336 /* 337 * get_e: gets a 16 bits word from the EEPROM. we must have set the window 338 * before 339 */ 340 static int 341 get_e(offset) 342 int offset; 343 { 344 if (!eeprom_rdy()) 345 return (0xffff); 346 outw(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND); 347 if (!eeprom_rdy()) 348 return (0xffff); 349 return (inw(BASE + VX_W0_EEPROM_DATA)); 350 } 351 352 static void 353 vxgetlink(void) 354 { 355 int n, k; 356 357 GO_WINDOW(3); 358 vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f; 359 for (n = 0, k = 0; k < VX_CONNECTORS; k++) { 360 if (vx_connectors & conn_tab[k].bit) { 361 if (n > 0) { 362 printf("/"); 363 } 364 printf(conn_tab[k].name); 365 n++; 366 } 367 } 368 if (vx_connectors == 0) { 369 printf("no connectors!"); 370 return; 371 } 372 GO_WINDOW(3); 373 vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG) 374 & INTERNAL_CONNECTOR_MASK) 375 >> INTERNAL_CONNECTOR_BITS; 376 if (vx_connector & 0x10) { 377 vx_connector &= 0x0f; 378 printf("[*%s*]", conn_tab[vx_connector].name); 379 printf(": disable 'auto select' with DOS util!"); 380 } else { 381 printf("[*%s*]", conn_tab[vx_connector].name); 382 } 383 } 384 385 static void 386 vxsetlink(void) 387 { 388 int i, j; 389 char *reason, *warning; 390 static char prev_conn = -1; 391 392 if (prev_conn == -1) { 393 prev_conn = vx_connector; 394 } 395 396 i = vx_connector; /* default in EEPROM */ 397 reason = "default"; 398 warning = 0; 399 400 if ((vx_connectors & conn_tab[vx_connector].bit) == 0) { 401 warning = "strange connector type in EEPROM."; 402 reason = "forced"; 403 i = CONNECTOR_UTP; 404 } 405 406 if (warning != 0) { 407 printf("warning: %s\n", warning); 408 } 409 printf("selected %s. (%s)\n", conn_tab[i].name, reason); 410 411 /* Set the selected connector. */ 412 GO_WINDOW(3); 413 j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; 414 outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG); 415 416 /* First, disable all. */ 417 outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); 418 udelay(8000); 419 GO_WINDOW(4); 420 outw(0, BASE + VX_W4_MEDIA_TYPE); 421 422 /* Second, enable the selected one. */ 423 switch(i) { 424 case CONNECTOR_UTP: 425 GO_WINDOW(4); 426 outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE); 427 break; 428 case CONNECTOR_BNC: 429 outw(START_TRANSCEIVER,BASE + VX_COMMAND); 430 udelay(8000); 431 break; 432 case CONNECTOR_TX: 433 case CONNECTOR_FX: 434 GO_WINDOW(4); 435 outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE); 436 break; 437 default: /* AUI and MII fall here */ 438 break; 439 } 440 GO_WINDOW(1); 441 } 442 443 static void t595_disable(struct dev *dev) 444 { 445 struct nic *nic = (struct nic *)dev; 446 t595_reset(nic); 447 448 outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); 449 udelay(8000); 450 GO_WINDOW(4); 451 outw(0, BASE + VX_W4_MEDIA_TYPE); 452 GO_WINDOW(1); 453 } 454 455 static void t595_irq(struct nic *nic __unused, irq_action_t action __unused) 456 { 457 switch ( action ) { 458 case DISABLE : 459 break; 460 case ENABLE : 461 break; 462 case FORCE : 463 break; 464 } 465 } 466 467 /************************************************************************** 468 ETH_PROBE - Look for an adapter 469 ***************************************************************************/ 470 static int t595_probe(struct dev *dev, struct pci_device *pci) 471 { 472 struct nic *nic = (struct nic *)dev; 473 int i; 474 unsigned short *p; 475 476 if (pci->ioaddr == 0) 477 return 0; 478 /* eth_nic_base = probeaddrs[0] & ~3; */ 479 eth_nic_base = pci->ioaddr; 480 481 nic->irqno = 0; 482 nic->ioaddr = pci->ioaddr & ~3; 483 484 GO_WINDOW(0); 485 outw(GLOBAL_RESET, BASE + VX_COMMAND); 486 VX_BUSY_WAIT; 487 488 vxgetlink(); 489 490 /* 491 printf("\nEEPROM:"); 492 for (i = 0; i < (EEPROMSIZE/2); i++) { 493 printf("%hX:", get_e(i)); 494 } 495 printf("\n"); 496 */ 497 /* 498 * Read the station address from the eeprom 499 */ 500 p = (unsigned short *) nic->node_addr; 501 for (i = 0; i < 3; i++) { 502 GO_WINDOW(0); 503 p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i)); 504 GO_WINDOW(2); 505 outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2)); 506 } 507 508 printf("Ethernet address: %!\n", nic->node_addr); 509 510 t595_reset(nic); 511 dev->disable = t595_disable; 512 nic->poll = t595_poll; 513 nic->transmit = t595_transmit; 514 nic->irq = t595_irq; 515 return 1; 516 517 } 518 519 static struct pci_id t595_nics[] = { 520 PCI_ROM(0x10b7, 0x5900, "3c590", "3Com590"), /* Vortex 10Mbps */ 521 PCI_ROM(0x10b7, 0x5950, "3c595", "3Com595"), /* Vortex 100baseTx */ 522 PCI_ROM(0x10b7, 0x5951, "3c595-1", "3Com595"), /* Vortex 100baseT4 */ 523 PCI_ROM(0x10b7, 0x5952, "3c595-2", "3Com595"), /* Vortex 100base-MII */ 524 PCI_ROM(0x10b7, 0x9000, "3c900-tpo", "3Com900-TPO"), /* 10 Base TPO */ 525 PCI_ROM(0x10b7, 0x9001, "3c900-t4", "3Com900-Combo"), /* 10/100 T4 */ 526 PCI_ROM(0x10b7, 0x9004, "3c900b-tpo", "3Com900B-TPO"), /* 10 Base TPO */ 527 PCI_ROM(0x10b7, 0x9005, "3c900b-combo", "3Com900B-Combo"), /* 10 Base Combo */ 528 PCI_ROM(0x10b7, 0x9006, "3c900b-tpb2", "3Com900B-2/T"), /* 10 Base TP and Base2 */ 529 PCI_ROM(0x10b7, 0x900a, "3c900b-fl", "3Com900B-FL"), /* 10 Base F */ 530 PCI_ROM(0x10b7, 0x9800, "3c980-cyclone-1", "3Com980-Cyclone"), /* Cyclone */ 531 PCI_ROM(0x10b7, 0x9805, "3c9805-1", "3Com9805"), /* Dual Port Server Cyclone */ 532 PCI_ROM(0x10b7, 0x7646, "3csoho100-tx-1", "3CSOHO100-TX"), /* Hurricane */ 533 PCI_ROM(0x10b7, 0x4500, "3c450-1", "3Com450 HomePNA Tornado"), 534 }; 535 536 struct pci_driver t595_driver = { 537 .type = NIC_DRIVER, 538 .name = "3C595", 539 .probe = t595_probe, 540 .ids = t595_nics, 541 .id_count = sizeof(t595_nics)/sizeof(t595_nics[0]), 542 .class = 0, 543 }; 544 545 /* 546 * Local variables: 547 * c-basic-offset: 8 548 * End: 549 */ 550 551