1 /*------------------------------------------------------------------------ 2 * smc9000.c 3 * This is a Etherboot driver for SMC's 9000 series of Ethernet cards. 4 * 5 * Copyright (C) 1998 Daniel Engstrm <daniel.engstrom (at) riksnett.no> 6 * Based on the Linux SMC9000 driver, smc9194.c by Eric Stahlman 7 * Copyright (C) 1996 by Erik Stahlman <eric (at) vt.edu> 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU Public License, incorporated herein by reference. 11 * 12 * "Features" of the SMC chip: 13 * 4608 byte packet memory. ( for the 91C92/4. Others have more ) 14 * EEPROM for configuration 15 * AUI/TP selection 16 * 17 * Authors 18 * Erik Stahlman <erik (at) vt.edu> 19 * Daniel Engstrm <daniel.engstrom (at) riksnett.no> 20 * 21 * History 22 * 98-09-25 Daniel Engstrm Etherboot driver crated from Eric's 23 * Linux driver. 24 * 25 *---------------------------------------------------------------------------*/ 26 #define LINUX_OUT_MACROS 1 27 #define SMC9000_VERBOSE 1 28 #define SMC9000_DEBUG 0 29 30 #include "etherboot.h" 31 #include "nic.h" 32 #include "cards.h" 33 #include "smc9000.h" 34 35 # define _outb outb 36 # define _outw outw 37 38 static const char smc9000_version[] = "Version 0.99 98-09-30"; 39 static unsigned int smc9000_base=0; 40 static const char *interfaces[ 2 ] = { "TP", "AUI" }; 41 static const char *chip_ids[ 15 ] = { 42 NULL, NULL, NULL, 43 /* 3 */ "SMC91C90/91C92", 44 /* 4 */ "SMC91C94", 45 /* 5 */ "SMC91C95", 46 NULL, 47 /* 7 */ "SMC91C100", 48 /* 8 */ "SMC91C100FD", 49 NULL, NULL, NULL, 50 NULL, NULL, NULL 51 }; 52 static const char smc91c96_id[] = "SMC91C96"; 53 54 /* 55 * Function: smc_reset( int ioaddr ) 56 * Purpose: 57 * This sets the SMC91xx chip to its normal state, hopefully from whatever 58 * mess that any other DOS driver has put it in. 59 * 60 * Maybe I should reset more registers to defaults in here? SOFTRESET should 61 * do that for me. 62 * 63 * Method: 64 * 1. send a SOFT RESET 65 * 2. wait for it to finish 66 * 3. reset the memory management unit 67 * 4. clear all interrupts 68 * 69 */ 70 static void smc_reset(int ioaddr) 71 { 72 /* This resets the registers mostly to defaults, but doesn't 73 * affect EEPROM. That seems unnecessary */ 74 SMC_SELECT_BANK(ioaddr, 0); 75 _outw( RCR_SOFTRESET, ioaddr + RCR ); 76 77 /* this should pause enough for the chip to be happy */ 78 SMC_DELAY(ioaddr); 79 80 /* Set the transmit and receive configuration registers to 81 * default values */ 82 _outw(RCR_CLEAR, ioaddr + RCR); 83 _outw(TCR_CLEAR, ioaddr + TCR); 84 85 /* Reset the MMU */ 86 SMC_SELECT_BANK(ioaddr, 2); 87 _outw( MC_RESET, ioaddr + MMU_CMD ); 88 89 /* Note: It doesn't seem that waiting for the MMU busy is needed here, 90 * but this is a place where future chipsets _COULD_ break. Be wary 91 * of issuing another MMU command right after this */ 92 _outb(0, ioaddr + INT_MASK); 93 } 94 95 96 /*---------------------------------------------------------------------- 97 * Function: smc_probe( int ioaddr ) 98 * 99 * Purpose: 100 * Tests to see if a given ioaddr points to an SMC9xxx chip. 101 * Returns a 0 on success 102 * 103 * Algorithm: 104 * (1) see if the high byte of BANK_SELECT is 0x33 105 * (2) compare the ioaddr with the base register's address 106 * (3) see if I recognize the chip ID in the appropriate register 107 * 108 * --------------------------------------------------------------------- 109 */ 110 static int smc_probe( int ioaddr ) 111 { 112 word bank; 113 word revision_register; 114 word base_address_register; 115 116 /* First, see if the high byte is 0x33 */ 117 bank = inw(ioaddr + BANK_SELECT); 118 if ((bank & 0xFF00) != 0x3300) { 119 return -1; 120 } 121 /* The above MIGHT indicate a device, but I need to write to further 122 * test this. */ 123 _outw(0x0, ioaddr + BANK_SELECT); 124 bank = inw(ioaddr + BANK_SELECT); 125 if ((bank & 0xFF00) != 0x3300) { 126 return -1; 127 } 128 129 /* well, we've already written once, so hopefully another time won't 130 * hurt. This time, I need to switch the bank register to bank 1, 131 * so I can access the base address register */ 132 SMC_SELECT_BANK(ioaddr, 1); 133 base_address_register = inw(ioaddr + BASE); 134 135 if (ioaddr != (base_address_register >> 3 & 0x3E0)) { 136 #ifdef SMC9000_VERBOSE 137 printf("SMC9000: IOADDR %hX doesn't match configuration (%hX)." 138 "Probably not a SMC chip\n", 139 ioaddr, base_address_register >> 3 & 0x3E0); 140 #endif 141 /* well, the base address register didn't match. Must not have 142 * been a SMC chip after all. */ 143 return -1; 144 } 145 146 147 /* check if the revision register is something that I recognize. 148 * These might need to be added to later, as future revisions 149 * could be added. */ 150 SMC_SELECT_BANK(ioaddr, 3); 151 revision_register = inw(ioaddr + REVISION); 152 if (!chip_ids[(revision_register >> 4) & 0xF]) { 153 /* I don't recognize this chip, so... */ 154 #ifdef SMC9000_VERBOSE 155 printf("SMC9000: IO %hX: Unrecognized revision register:" 156 " %hX, Contact author.\n", ioaddr, revision_register); 157 #endif 158 return -1; 159 } 160 161 /* at this point I'll assume that the chip is an SMC9xxx. 162 * It might be prudent to check a listing of MAC addresses 163 * against the hardware address, or do some other tests. */ 164 return 0; 165 } 166 167 168 /************************************************************************** 169 * ETH_RESET - Reset adapter 170 ***************************************************************************/ 171 172 static void smc9000_reset(struct nic *nic) 173 { 174 smc_reset(smc9000_base); 175 } 176 177 /************************************************************************** 178 * ETH_TRANSMIT - Transmit a frame 179 ***************************************************************************/ 180 static void smc9000_transmit( 181 struct nic *nic, 182 const char *d, /* Destination */ 183 unsigned int t, /* Type */ 184 unsigned int s, /* size */ 185 const char *p) /* Packet */ 186 { 187 word length; /* real, length incl. header */ 188 word numPages; 189 unsigned long time_out; 190 byte packet_no; 191 word status; 192 int i; 193 194 /* We dont pad here since we can have the hardware doing it for us */ 195 length = (s + ETH_HLEN + 1)&~1; 196 197 /* convert to MMU pages */ 198 numPages = length / 256; 199 200 if (numPages > 7 ) { 201 #ifdef SMC9000_VERBOSE 202 printf("SMC9000: Far too big packet error. \n"); 203 #endif 204 return; 205 } 206 207 /* dont try more than, say 30 times */ 208 for (i=0;i<30;i++) { 209 /* now, try to allocate the memory */ 210 SMC_SELECT_BANK(smc9000_base, 2); 211 _outw(MC_ALLOC | numPages, smc9000_base + MMU_CMD); 212 213 status = 0; 214 /* wait for the memory allocation to finnish */ 215 for (time_out = currticks() + 5*TICKS_PER_SEC; currticks() < time_out; ) { 216 status = inb(smc9000_base + INTERRUPT); 217 if ( status & IM_ALLOC_INT ) { 218 /* acknowledge the interrupt */ 219 _outb(IM_ALLOC_INT, smc9000_base + INTERRUPT); 220 break; 221 } 222 } 223 224 if ((status & IM_ALLOC_INT) != 0 ) { 225 /* We've got the memory */ 226 break; 227 } else { 228 printf("SMC9000: Memory allocation timed out, resetting MMU.\n"); 229 _outw(MC_RESET, smc9000_base + MMU_CMD); 230 } 231 } 232 233 /* If I get here, I _know_ there is a packet slot waiting for me */ 234 packet_no = inb(smc9000_base + PNR_ARR + 1); 235 if (packet_no & 0x80) { 236 /* or isn't there? BAD CHIP! */ 237 printf("SMC9000: Memory allocation failed. \n"); 238 return; 239 } 240 241 /* we have a packet address, so tell the card to use it */ 242 _outb(packet_no, smc9000_base + PNR_ARR); 243 244 /* point to the beginning of the packet */ 245 _outw(PTR_AUTOINC, smc9000_base + POINTER); 246 247 #if SMC9000_DEBUG > 2 248 printf("Trying to xmit packet of length %hX\n", length ); 249 #endif 250 251 /* send the packet length ( +6 for status, length and ctl byte ) 252 * and the status word ( set to zeros ) */ 253 _outw(0, smc9000_base + DATA_1 ); 254 255 /* send the packet length ( +6 for status words, length, and ctl) */ 256 _outb((length+6) & 0xFF, smc9000_base + DATA_1); 257 _outb((length+6) >> 8 , smc9000_base + DATA_1); 258 259 /* Write the contents of the packet */ 260 261 /* The ethernet header first... */ 262 outsw(smc9000_base + DATA_1, d, ETH_ALEN >> 1); 263 outsw(smc9000_base + DATA_1, nic->node_addr, ETH_ALEN >> 1); 264 _outw(htons(t), smc9000_base + DATA_1); 265 266 /* ... the data ... */ 267 outsw(smc9000_base + DATA_1 , p, s >> 1); 268 269 /* ... and the last byte, if there is one. */ 270 if ((s & 1) == 0) { 271 _outw(0, smc9000_base + DATA_1); 272 } else { 273 _outb(p[s-1], smc9000_base + DATA_1); 274 _outb(0x20, smc9000_base + DATA_1); 275 } 276 277 /* and let the chipset deal with it */ 278 _outw(MC_ENQUEUE , smc9000_base + MMU_CMD); 279 280 status = 0; time_out = currticks() + 5*TICKS_PER_SEC; 281 do { 282 status = inb(smc9000_base + INTERRUPT); 283 284 if ((status & IM_TX_INT ) != 0) { 285 word tx_status; 286 287 /* ack interrupt */ 288 _outb(IM_TX_INT, smc9000_base + INTERRUPT); 289 290 packet_no = inw(smc9000_base + FIFO_PORTS); 291 packet_no &= 0x7F; 292 293 /* select this as the packet to read from */ 294 _outb( packet_no, smc9000_base + PNR_ARR ); 295 296 /* read the first word from this packet */ 297 _outw( PTR_AUTOINC | PTR_READ, smc9000_base + POINTER ); 298 299 tx_status = inw( smc9000_base + DATA_1 ); 300 301 if (0 == (tx_status & TS_SUCCESS)) { 302 #ifdef SMC9000_VERBOSE 303 printf("SMC9000: TX FAIL STATUS: %hX \n", tx_status); 304 #endif 305 /* re-enable transmit */ 306 SMC_SELECT_BANK(smc9000_base, 0); 307 _outw(inw(smc9000_base + TCR ) | TCR_ENABLE, smc9000_base + TCR ); 308 } 309 310 /* kill the packet */ 311 SMC_SELECT_BANK(smc9000_base, 2); 312 _outw(MC_FREEPKT, smc9000_base + MMU_CMD); 313 314 return; 315 } 316 }while(currticks() < time_out); 317 318 printf("SMC9000: Waring TX timed out, resetting board\n"); 319 smc_reset(smc9000_base); 320 return; 321 } 322 323 /************************************************************************** 324 * ETH_POLL - Wait for a frame 325 ***************************************************************************/ 326 static int smc9000_poll(struct nic *nic) 327 { 328 if(!smc9000_base) 329 return 0; 330 331 SMC_SELECT_BANK(smc9000_base, 2); 332 if (inw(smc9000_base + FIFO_PORTS) & FP_RXEMPTY) 333 return 0; 334 335 /* start reading from the start of the packet */ 336 _outw(PTR_READ | PTR_RCV | PTR_AUTOINC, smc9000_base + POINTER); 337 338 /* First read the status and check that we're ok */ 339 if (!(inw(smc9000_base + DATA_1) & RS_ERRORS)) { 340 /* Next: read the packet length and mask off the top bits */ 341 nic->packetlen = (inw(smc9000_base + DATA_1) & 0x07ff); 342 343 /* the packet length includes the 3 extra words */ 344 nic->packetlen -= 6; 345 #if SMC9000_DEBUG > 2 346 printf(" Reading %d words (and %d byte(s))\n", 347 (nic->packetlen >> 1), nic->packetlen & 1); 348 #endif 349 /* read the packet (and the last "extra" word) */ 350 insw(smc9000_base + DATA_1, nic->packet, (nic->packetlen+2) >> 1); 351 /* is there an odd last byte ? */ 352 if (nic->packet[nic->packetlen+1] & 0x20) 353 nic->packetlen++; 354 355 /* error or good, tell the card to get rid of this packet */ 356 _outw(MC_RELEASE, smc9000_base + MMU_CMD); 357 return 1; 358 } 359 360 printf("SMC9000: RX error\n"); 361 /* error or good, tell the card to get rid of this packet */ 362 _outw(MC_RELEASE, smc9000_base + MMU_CMD); 363 return 0; 364 } 365 366 static void smc9000_disable(struct nic *nic) 367 { 368 if(!smc9000_base) 369 return; 370 371 /* no more interrupts for me */ 372 SMC_SELECT_BANK(smc9000_base, 2); 373 _outb( 0, smc9000_base + INT_MASK); 374 375 /* and tell the card to stay away from that nasty outside world */ 376 SMC_SELECT_BANK(smc9000_base, 0); 377 _outb( RCR_CLEAR, smc9000_base + RCR ); 378 _outb( TCR_CLEAR, smc9000_base + TCR ); 379 } 380 381 /************************************************************************** 382 * ETH_PROBE - Look for an adapter 383 ***************************************************************************/ 384 385 struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs) 386 { 387 unsigned short revision; 388 int memory; 389 int media; 390 const char * version_string; 391 const char * if_string; 392 int i; 393 394 /* 395 * the SMC9000 can be at any of the following port addresses. To change, 396 * for a slightly different card, you can add it to the array. Keep in 397 * mind that the array must end in zero. 398 */ 399 static unsigned short portlist[] = { 400 #ifdef SMC9000_SCAN 401 SMC9000_SCAN, 402 #else 403 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 404 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 405 #endif 406 0 }; 407 408 printf("\nSMC9000 %s\n", smc9000_version); 409 #ifdef SMC9000_VERBOSE 410 printf("Copyright (C) 1998 Daniel Engstr\x94m\n"); 411 printf("Copyright (C) 1996 Eric Stahlman\n"); 412 #endif 413 /* if no addresses supplied, fall back on defaults */ 414 if (probe_addrs == 0 || probe_addrs[0] == 0) 415 probe_addrs = portlist; 416 417 /* check every ethernet address */ 418 for (i = 0; probe_addrs[i]; i++) { 419 /* check this specific address */ 420 if (smc_probe(probe_addrs[i]) == 0) 421 smc9000_base = probe_addrs[i]; 422 } 423 424 /* couldn't find anything */ 425 if(0 == smc9000_base) 426 goto out; 427 428 /* 429 * Get the MAC address ( bank 1, regs 4 - 9 ) 430 */ 431 SMC_SELECT_BANK(smc9000_base, 1); 432 for ( i = 0; i < 6; i += 2 ) { 433 word address; 434 435 address = inw(smc9000_base + ADDR0 + i); 436 nic->node_addr[i+1] = address >> 8; 437 nic->node_addr[i] = address & 0xFF; 438 } 439 440 441 /* get the memory information */ 442 SMC_SELECT_BANK(smc9000_base, 0); 443 memory = ( inw(smc9000_base + MCR) >> 9 ) & 0x7; /* multiplier */ 444 memory *= 256 * (inw(smc9000_base + MIR) & 0xFF); 445 446 /* 447 * Now, I want to find out more about the chip. This is sort of 448 * redundant, but it's cleaner to have it in both, rather than having 449 * one VERY long probe procedure. 450 */ 451 SMC_SELECT_BANK(smc9000_base, 3); 452 revision = inw(smc9000_base + REVISION); 453 version_string = chip_ids[(revision >> 4) & 0xF]; 454 455 if (((revision & 0xF0) >> 4 == CHIP_9196) && 456 ((revision & 0x0F) >= REV_9196)) { 457 /* This is a 91c96. 'c96 has the same chip id as 'c94 (4) but 458 * a revision starting at 6 */ 459 version_string = smc91c96_id; 460 } 461 462 if ( !version_string ) { 463 /* I shouldn't get here because this call was done before.... */ 464 goto out; 465 } 466 467 /* is it using AUI or 10BaseT ? */ 468 SMC_SELECT_BANK(smc9000_base, 1); 469 if (inw(smc9000_base + CONFIG) & CFG_AUI_SELECT) 470 media = 2; 471 else 472 media = 1; 473 474 if_string = interfaces[media - 1]; 475 476 /* now, reset the chip, and put it into a known state */ 477 smc_reset(smc9000_base); 478 479 printf("%s rev:%d I/O port:%hX Interface:%s RAM:%d bytes \n", 480 version_string, revision & 0xF, 481 smc9000_base, if_string, memory ); 482 /* 483 * Print the Ethernet address 484 */ 485 printf("Ethernet MAC address: %!\n", nic->node_addr); 486 487 SMC_SELECT_BANK(smc9000_base, 0); 488 489 /* see the header file for options in TCR/RCR NORMAL*/ 490 _outw(TCR_NORMAL, smc9000_base + TCR); 491 _outw(RCR_NORMAL, smc9000_base + RCR); 492 493 /* Select which interface to use */ 494 SMC_SELECT_BANK(smc9000_base, 1); 495 if ( media == 1 ) { 496 _outw( inw( smc9000_base + CONFIG ) & ~CFG_AUI_SELECT, 497 smc9000_base + CONFIG ); 498 } 499 else if ( media == 2 ) { 500 _outw( inw( smc9000_base + CONFIG ) | CFG_AUI_SELECT, 501 smc9000_base + CONFIG ); 502 } 503 504 nic->reset = smc9000_reset; 505 nic->poll = smc9000_poll; 506 nic->transmit = smc9000_transmit; 507 nic->disable = smc9000_disable; 508 509 510 return nic; 511 512 out: 513 #ifdef SMC9000_VERBOSE 514 printf("No SMC9000 adapters found\n"); 515 #endif 516 smc9000_base = 0; 517 518 return (0); 519 } 520 521 522 523