#include <gpxe/ethernet.h>#include <errno.h>#include "etherboot.h"#include "nic.h"#include <gpxe/isa.h>#include "smc9000.h"Go to the source code of this file.
Defines | |
| #define | LINUX_OUT_MACROS 1 |
| #define | SMC9000_DEBUG 0 |
| #define | PRINTK2(args...) |
| #define | _outb outb |
| #define | _outw outw |
Functions | |
| FILE_LICENCE (GPL_ANY) | |
| static word | smc_read_phy_register (int ioaddr, byte phyaddr, byte phyreg) |
| static void | smc_write_phy_register (int ioaddr, byte phyaddr, byte phyreg, word phydata) |
| static int | smc_detect_phy (int ioaddr, byte *pphyaddr) |
| static void | smc_phy_configure (int ioaddr) |
| static void | smc_reset (int ioaddr) |
| static int | smc9000_probe_addr (isa_probe_addr_t ioaddr) |
| static void | smc9000_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) |
| static int | smc9000_poll (struct nic *nic, int retrieve) |
| static void | smc9000_disable (struct nic *nic, struct isa_device *isa __unused) |
| static void | smc9000_irq (struct nic *nic __unused, irq_action_t action __unused) |
| static int | smc9000_probe (struct nic *nic, struct isa_device *isa) |
| ISA_DRIVER (smc9000_driver, smc9000_probe_addrs, smc9000_probe_addr, GENERIC_ISAPNP_VENDOR, 0x8228) | |
| DRIVER ("SMC9000", nic_driver, isa_driver, smc9000_driver, smc9000_probe, smc9000_disable) | |
| ISA_ROM ("smc9000","SMC9000") | |
Variables | |
| static const char | smc9000_version [] = "Version 0.99 98-09-30" |
| static const char * | interfaces [2] = { "TP", "AUI" } |
| static const char * | chip_ids [15] |
| static const char | smc91c96_id [] = "SMC91C96" |
| static struct nic_operations | smc9000_operations |
| static isa_probe_addr_t | smc9000_probe_addrs [] |
| #define PRINTK2 | ( | args... | ) |
| #define _outb outb |
Definition at line 48 of file smc9000.c.
Referenced by smc9000_disable(), smc9000_transmit(), and smc_reset().
| #define _outw outw |
Definition at line 49 of file smc9000.c.
Referenced by smc9000_poll(), smc9000_probe(), smc9000_probe_addr(), smc9000_transmit(), and smc_reset().
| FILE_LICENCE | ( | GPL_ANY | ) |
Definition at line 70 of file smc9000.c.
References BANK_SELECT, inw, MII_MCLK, MII_MDI, MII_MDO, MII_MDOE, MII_REG, outw, printf(), SMC_SELECT_BANK, and udelay().
Referenced by smc_detect_phy(), and smc_phy_configure().
00071 { 00072 int oldBank; 00073 unsigned int i; 00074 byte mask; 00075 word mii_reg; 00076 byte bits[64]; 00077 int clk_idx = 0; 00078 int input_idx; 00079 word phydata; 00080 00081 // 32 consecutive ones on MDO to establish sync 00082 for (i = 0; i < 32; ++i) 00083 bits[clk_idx++] = MII_MDOE | MII_MDO; 00084 00085 // Start code <01> 00086 bits[clk_idx++] = MII_MDOE; 00087 bits[clk_idx++] = MII_MDOE | MII_MDO; 00088 00089 // Read command <10> 00090 bits[clk_idx++] = MII_MDOE | MII_MDO; 00091 bits[clk_idx++] = MII_MDOE; 00092 00093 // Output the PHY address, msb first 00094 mask = (byte)0x10; 00095 for (i = 0; i < 5; ++i) 00096 { 00097 if (phyaddr & mask) 00098 bits[clk_idx++] = MII_MDOE | MII_MDO; 00099 else 00100 bits[clk_idx++] = MII_MDOE; 00101 00102 // Shift to next lowest bit 00103 mask >>= 1; 00104 } 00105 00106 // Output the phy register number, msb first 00107 mask = (byte)0x10; 00108 for (i = 0; i < 5; ++i) 00109 { 00110 if (phyreg & mask) 00111 bits[clk_idx++] = MII_MDOE | MII_MDO; 00112 else 00113 bits[clk_idx++] = MII_MDOE; 00114 00115 // Shift to next lowest bit 00116 mask >>= 1; 00117 } 00118 00119 // Tristate and turnaround (2 bit times) 00120 bits[clk_idx++] = 0; 00121 //bits[clk_idx++] = 0; 00122 00123 // Input starts at this bit time 00124 input_idx = clk_idx; 00125 00126 // Will input 16 bits 00127 for (i = 0; i < 16; ++i) 00128 bits[clk_idx++] = 0; 00129 00130 // Final clock bit 00131 bits[clk_idx++] = 0; 00132 00133 // Save the current bank 00134 oldBank = inw( ioaddr+BANK_SELECT ); 00135 00136 // Select bank 3 00137 SMC_SELECT_BANK(ioaddr, 3); 00138 00139 // Get the current MII register value 00140 mii_reg = inw( ioaddr+MII_REG ); 00141 00142 // Turn off all MII Interface bits 00143 mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); 00144 00145 // Clock all 64 cycles 00146 for (i = 0; i < sizeof(bits); ++i) 00147 { 00148 // Clock Low - output data 00149 outw( mii_reg | bits[i], ioaddr+MII_REG ); 00150 udelay(50); 00151 00152 00153 // Clock Hi - input data 00154 outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG ); 00155 udelay(50); 00156 bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI; 00157 } 00158 00159 // Return to idle state 00160 // Set clock to low, data to low, and output tristated 00161 outw( mii_reg, ioaddr+MII_REG ); 00162 udelay(50); 00163 00164 // Restore original bank select 00165 SMC_SELECT_BANK(ioaddr, oldBank); 00166 00167 // Recover input data 00168 phydata = 0; 00169 for (i = 0; i < 16; ++i) 00170 { 00171 phydata <<= 1; 00172 00173 if (bits[input_idx++] & MII_MDI) 00174 phydata |= 0x0001; 00175 } 00176 00177 #if (SMC_DEBUG > 2 ) 00178 printf("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", 00179 phyaddr, phyreg, phydata); 00180 #endif 00181 00182 return(phydata); 00183 }
Definition at line 189 of file smc9000.c.
References BANK_SELECT, inw, MII_MCLK, MII_MDI, MII_MDO, MII_MDOE, MII_REG, outw, printf(), SMC_SELECT_BANK, and udelay().
Referenced by smc_phy_configure().
00191 { 00192 int oldBank; 00193 unsigned int i; 00194 word mask; 00195 word mii_reg; 00196 byte bits[65]; 00197 int clk_idx = 0; 00198 00199 // 32 consecutive ones on MDO to establish sync 00200 for (i = 0; i < 32; ++i) 00201 bits[clk_idx++] = MII_MDOE | MII_MDO; 00202 00203 // Start code <01> 00204 bits[clk_idx++] = MII_MDOE; 00205 bits[clk_idx++] = MII_MDOE | MII_MDO; 00206 00207 // Write command <01> 00208 bits[clk_idx++] = MII_MDOE; 00209 bits[clk_idx++] = MII_MDOE | MII_MDO; 00210 00211 // Output the PHY address, msb first 00212 mask = (byte)0x10; 00213 for (i = 0; i < 5; ++i) 00214 { 00215 if (phyaddr & mask) 00216 bits[clk_idx++] = MII_MDOE | MII_MDO; 00217 else 00218 bits[clk_idx++] = MII_MDOE; 00219 00220 // Shift to next lowest bit 00221 mask >>= 1; 00222 } 00223 00224 // Output the phy register number, msb first 00225 mask = (byte)0x10; 00226 for (i = 0; i < 5; ++i) 00227 { 00228 if (phyreg & mask) 00229 bits[clk_idx++] = MII_MDOE | MII_MDO; 00230 else 00231 bits[clk_idx++] = MII_MDOE; 00232 00233 // Shift to next lowest bit 00234 mask >>= 1; 00235 } 00236 00237 // Tristate and turnaround (2 bit times) 00238 bits[clk_idx++] = 0; 00239 bits[clk_idx++] = 0; 00240 00241 // Write out 16 bits of data, msb first 00242 mask = 0x8000; 00243 for (i = 0; i < 16; ++i) 00244 { 00245 if (phydata & mask) 00246 bits[clk_idx++] = MII_MDOE | MII_MDO; 00247 else 00248 bits[clk_idx++] = MII_MDOE; 00249 00250 // Shift to next lowest bit 00251 mask >>= 1; 00252 } 00253 00254 // Final clock bit (tristate) 00255 bits[clk_idx++] = 0; 00256 00257 // Save the current bank 00258 oldBank = inw( ioaddr+BANK_SELECT ); 00259 00260 // Select bank 3 00261 SMC_SELECT_BANK(ioaddr, 3); 00262 00263 // Get the current MII register value 00264 mii_reg = inw( ioaddr+MII_REG ); 00265 00266 // Turn off all MII Interface bits 00267 mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO); 00268 00269 // Clock all cycles 00270 for (i = 0; i < sizeof(bits); ++i) 00271 { 00272 // Clock Low - output data 00273 outw( mii_reg | bits[i], ioaddr+MII_REG ); 00274 udelay(50); 00275 00276 00277 // Clock Hi - input data 00278 outw( mii_reg | bits[i] | MII_MCLK, ioaddr+MII_REG ); 00279 udelay(50); 00280 bits[i] |= inw( ioaddr+MII_REG ) & MII_MDI; 00281 } 00282 00283 // Return to idle state 00284 // Set clock to low, data to low, and output tristated 00285 outw( mii_reg, ioaddr+MII_REG ); 00286 udelay(50); 00287 00288 // Restore original bank select 00289 SMC_SELECT_BANK(ioaddr, oldBank); 00290 00291 #if (SMC_DEBUG > 2 ) 00292 printf("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n", 00293 phyaddr, phyreg, phydata); 00294 #endif 00295 }
| static int smc_detect_phy | ( | int | ioaddr, | |
| byte * | pphyaddr | |||
| ) | [static] |
Definition at line 301 of file smc9000.c.
References PHY_ID1_REG, PHY_ID2_REG, printf(), and smc_read_phy_register().
Referenced by smc_phy_configure().
00302 { 00303 word phy_id1; 00304 word phy_id2; 00305 int phyaddr; 00306 int found = 0; 00307 00308 // Scan all 32 PHY addresses if necessary 00309 for (phyaddr = 0; phyaddr < 32; ++phyaddr) 00310 { 00311 // Read the PHY identifiers 00312 phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG); 00313 phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG); 00314 00315 // Make sure it is a valid identifier 00316 if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) && 00317 (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) 00318 { 00319 if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) 00320 { 00321 // Save the PHY's address 00322 *pphyaddr = phyaddr; 00323 found = 1; 00324 break; 00325 } 00326 } 00327 } 00328 00329 if (!found) 00330 { 00331 printf("No PHY found\n"); 00332 return(0); 00333 } 00334 00335 // Set the PHY type 00336 if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) 00337 { 00338 printf("PHY=LAN83C183 (LAN91C111 Internal)\n"); 00339 } 00340 00341 if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) 00342 { 00343 printf("PHY=LAN83C180\n"); 00344 } 00345 00346 return(1); 00347 }
| static void smc_phy_configure | ( | int | ioaddr | ) | [static] |
Definition at line 353 of file smc9000.c.
References mdelay(), outw, PHY_AD_10_FDX, PHY_AD_10_HDX, PHY_AD_CSMA, PHY_AD_REG, PHY_AD_T4, PHY_AD_TX_FDX, PHY_AD_TX_HDX, PHY_CNTL_ANEG_EN, PHY_CNTL_ANEG_RST, PHY_CNTL_DPLX, PHY_CNTL_REG, PHY_CNTL_RST, PHY_CNTL_SPEED, PHY_INT_CWRD, PHY_INT_DPLXDET, PHY_INT_ESD, PHY_INT_JAB, PHY_INT_LOSSSYNC, PHY_INT_REG, PHY_INT_RPOL, PHY_INT_SPDDET, PHY_INT_SSD, PHY_MASK_REG, PHY_STAT_ANEG_ACK, PHY_STAT_CAP_T4, PHY_STAT_CAP_TF, PHY_STAT_CAP_TH, PHY_STAT_CAP_TXF, PHY_STAT_CAP_TXH, PHY_STAT_REG, PHY_STAT_REM_FLT, PRINTK2, RPC_DEFAULT, RPC_DPLX, RPC_REG, RPC_SPEED, smc_detect_phy(), smc_read_phy_register(), SMC_SELECT_BANK, smc_write_phy_register(), sky2_status_le::status, and timeout().
Referenced by smc9000_probe().
00354 { 00355 int timeout; 00356 byte phyaddr; 00357 word my_phy_caps; // My PHY capabilities 00358 word my_ad_caps; // My Advertised capabilities 00359 word status; 00360 int failed = 0; 00361 int rpc_cur_mode = RPC_DEFAULT; 00362 int lastPhy18; 00363 00364 // Find the address and type of our phy 00365 if (!smc_detect_phy(ioaddr, &phyaddr)) 00366 { 00367 return; 00368 } 00369 00370 // Reset the PHY, setting all other bits to zero 00371 smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST); 00372 00373 // Wait for the reset to complete, or time out 00374 timeout = 6; // Wait up to 3 seconds 00375 while (timeout--) 00376 { 00377 if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG) 00378 & PHY_CNTL_RST)) 00379 { 00380 // reset complete 00381 break; 00382 } 00383 00384 mdelay(500); // wait 500 millisecs 00385 } 00386 00387 if (timeout < 1) 00388 { 00389 PRINTK2("PHY reset timed out\n"); 00390 return; 00391 } 00392 00393 // Read PHY Register 18, Status Output 00394 lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG); 00395 00396 // Enable PHY Interrupts (for register 18) 00397 // Interrupts listed here are disabled 00398 smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG, 00399 PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD | 00400 PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB | 00401 PHY_INT_SPDDET | PHY_INT_DPLXDET); 00402 00403 /* Configure the Receive/Phy Control register */ 00404 SMC_SELECT_BANK(ioaddr, 0); 00405 outw( rpc_cur_mode, ioaddr + RPC_REG ); 00406 00407 // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG 00408 my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); 00409 my_ad_caps = PHY_AD_CSMA; // I am CSMA capable 00410 00411 if (my_phy_caps & PHY_STAT_CAP_T4) 00412 my_ad_caps |= PHY_AD_T4; 00413 00414 if (my_phy_caps & PHY_STAT_CAP_TXF) 00415 my_ad_caps |= PHY_AD_TX_FDX; 00416 00417 if (my_phy_caps & PHY_STAT_CAP_TXH) 00418 my_ad_caps |= PHY_AD_TX_HDX; 00419 00420 if (my_phy_caps & PHY_STAT_CAP_TF) 00421 my_ad_caps |= PHY_AD_10_FDX; 00422 00423 if (my_phy_caps & PHY_STAT_CAP_TH) 00424 my_ad_caps |= PHY_AD_10_HDX; 00425 00426 // Update our Auto-Neg Advertisement Register 00427 smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps); 00428 00429 PRINTK2("phy caps=%x\n", my_phy_caps); 00430 PRINTK2("phy advertised caps=%x\n", my_ad_caps); 00431 00432 // Restart auto-negotiation process in order to advertise my caps 00433 smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG, 00434 PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST ); 00435 00436 // Wait for the auto-negotiation to complete. This may take from 00437 // 2 to 3 seconds. 00438 // Wait for the reset to complete, or time out 00439 timeout = 20; // Wait up to 10 seconds 00440 while (timeout--) 00441 { 00442 status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG); 00443 if (status & PHY_STAT_ANEG_ACK) 00444 { 00445 // auto-negotiate complete 00446 break; 00447 } 00448 00449 mdelay(500); // wait 500 millisecs 00450 00451 // Restart auto-negotiation if remote fault 00452 if (status & PHY_STAT_REM_FLT) 00453 { 00454 PRINTK2("PHY remote fault detected\n"); 00455 00456 // Restart auto-negotiation 00457 PRINTK2("PHY restarting auto-negotiation\n"); 00458 smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG, 00459 PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST | 00460 PHY_CNTL_SPEED | PHY_CNTL_DPLX); 00461 } 00462 } 00463 00464 if (timeout < 1) 00465 { 00466 PRINTK2("PHY auto-negotiate timed out\n"); 00467 failed = 1; 00468 } 00469 00470 // Fail if we detected an auto-negotiate remote fault 00471 if (status & PHY_STAT_REM_FLT) 00472 { 00473 PRINTK2("PHY remote fault detected\n"); 00474 failed = 1; 00475 } 00476 00477 // Set our sysctl parameters to match auto-negotiation results 00478 if ( lastPhy18 & PHY_INT_SPDDET ) 00479 { 00480 PRINTK2("PHY 100BaseT\n"); 00481 rpc_cur_mode |= RPC_SPEED; 00482 } 00483 else 00484 { 00485 PRINTK2("PHY 10BaseT\n"); 00486 rpc_cur_mode &= ~RPC_SPEED; 00487 } 00488 00489 if ( lastPhy18 & PHY_INT_DPLXDET ) 00490 { 00491 PRINTK2("PHY Full Duplex\n"); 00492 rpc_cur_mode |= RPC_DPLX; 00493 } 00494 else 00495 { 00496 PRINTK2("PHY Half Duplex\n"); 00497 rpc_cur_mode &= ~RPC_DPLX; 00498 } 00499 00500 // Re-Configure the Receive/Phy Control register 00501 outw( rpc_cur_mode, ioaddr + RPC_REG ); 00502 }
| static void smc_reset | ( | int | ioaddr | ) | [static] |
Definition at line 520 of file smc9000.c.
References _outb, _outw, INT_MASK, MC_RESET, MMU_CMD, RCR, RCR_CLEAR, RCR_SOFTRESET, SMC_DELAY, SMC_SELECT_BANK, TCR, and TCR_CLEAR.
Referenced by smc9000_disable(), smc9000_probe(), and smc9000_transmit().
00521 { 00522 /* This resets the registers mostly to defaults, but doesn't 00523 * affect EEPROM. That seems unnecessary */ 00524 SMC_SELECT_BANK(ioaddr, 0); 00525 _outw( RCR_SOFTRESET, ioaddr + RCR ); 00526 00527 /* this should pause enough for the chip to be happy */ 00528 SMC_DELAY(ioaddr); 00529 00530 /* Set the transmit and receive configuration registers to 00531 * default values */ 00532 _outw(RCR_CLEAR, ioaddr + RCR); 00533 _outw(TCR_CLEAR, ioaddr + TCR); 00534 00535 /* Reset the MMU */ 00536 SMC_SELECT_BANK(ioaddr, 2); 00537 _outw( MC_RESET, ioaddr + MMU_CMD ); 00538 00539 /* Note: It doesn't seem that waiting for the MMU busy is needed here, 00540 * but this is a place where future chipsets _COULD_ break. Be wary 00541 * of issuing another MMU command right after this */ 00542 _outb(0, ioaddr + INT_MASK); 00543 }
| static int smc9000_probe_addr | ( | isa_probe_addr_t | ioaddr | ) | [static] |
Definition at line 560 of file smc9000.c.
References _outw, BANK_SELECT, BASE, chip_ids, DBG, inw, REVISION, and SMC_SELECT_BANK.
00561 { 00562 word bank; 00563 word revision_register; 00564 word base_address_register; 00565 00566 /* First, see if the high byte is 0x33 */ 00567 bank = inw(ioaddr + BANK_SELECT); 00568 if ((bank & 0xFF00) != 0x3300) { 00569 return 0; 00570 } 00571 /* The above MIGHT indicate a device, but I need to write to further 00572 * test this. */ 00573 _outw(0x0, ioaddr + BANK_SELECT); 00574 bank = inw(ioaddr + BANK_SELECT); 00575 if ((bank & 0xFF00) != 0x3300) { 00576 return 0; 00577 } 00578 00579 /* well, we've already written once, so hopefully another time won't 00580 * hurt. This time, I need to switch the bank register to bank 1, 00581 * so I can access the base address register */ 00582 SMC_SELECT_BANK(ioaddr, 1); 00583 base_address_register = inw(ioaddr + BASE); 00584 00585 if (ioaddr != (base_address_register >> 3 & 0x3E0)) { 00586 DBG("SMC9000: IOADDR %hX doesn't match configuration (%hX)." 00587 "Probably not a SMC chip\n", 00588 ioaddr, base_address_register >> 3 & 0x3E0); 00589 /* well, the base address register didn't match. Must not have 00590 * been a SMC chip after all. */ 00591 return 0; 00592 } 00593 00594 00595 /* check if the revision register is something that I recognize. 00596 * These might need to be added to later, as future revisions 00597 * could be added. */ 00598 SMC_SELECT_BANK(ioaddr, 3); 00599 revision_register = inw(ioaddr + REVISION); 00600 if (!chip_ids[(revision_register >> 4) & 0xF]) { 00601 /* I don't recognize this chip, so... */ 00602 DBG( "SMC9000: IO %hX: Unrecognized revision register:" 00603 " %hX, Contact author.\n", ioaddr, revision_register ); 00604 return 0; 00605 } 00606 00607 /* at this point I'll assume that the chip is an SMC9xxx. 00608 * It might be prudent to check a listing of MAC addresses 00609 * against the hardware address, or do some other tests. */ 00610 return 1; 00611 }
| static void smc9000_transmit | ( | struct nic * | nic, | |
| const char * | d, | |||
| unsigned int | t, | |||
| unsigned int | s, | |||
| const char * | p | |||
| ) | [static] |
Definition at line 617 of file smc9000.c.
References _outb, _outw, currticks(), DATA_1, DBG, ETH_ALEN, ETH_HLEN, FIFO_PORTS, htons, IM_ALLOC_INT, IM_TX_INT, inb, INTERRUPT, inw, nic::ioaddr, sky2_status_le::length, MC_ALLOC, MC_ENQUEUE, MC_FREEPKT, MC_RESET, MMU_CMD, nic::node_addr, outsw, PNR_ARR, POINTER, printf(), PTR_AUTOINC, PTR_READ, smc_reset(), SMC_SELECT_BANK, sky2_status_le::status, TCR, TCR_ENABLE, TICKS_PER_SEC, and TS_SUCCESS.
00623 { 00624 word length; /* real, length incl. header */ 00625 word numPages; 00626 unsigned long time_out; 00627 byte packet_no; 00628 word status; 00629 int i; 00630 00631 /* We dont pad here since we can have the hardware doing it for us */ 00632 length = (s + ETH_HLEN + 1)&~1; 00633 00634 /* convert to MMU pages */ 00635 numPages = length / 256; 00636 00637 if (numPages > 7 ) { 00638 DBG("SMC9000: Far too big packet error. \n"); 00639 return; 00640 } 00641 00642 /* dont try more than, say 30 times */ 00643 for (i=0;i<30;i++) { 00644 /* now, try to allocate the memory */ 00645 SMC_SELECT_BANK(nic->ioaddr, 2); 00646 _outw(MC_ALLOC | numPages, nic->ioaddr + MMU_CMD); 00647 00648 status = 0; 00649 /* wait for the memory allocation to finnish */ 00650 for (time_out = currticks() + 5*TICKS_PER_SEC; currticks() < time_out; ) { 00651 status = inb(nic->ioaddr + INTERRUPT); 00652 if ( status & IM_ALLOC_INT ) { 00653 /* acknowledge the interrupt */ 00654 _outb(IM_ALLOC_INT, nic->ioaddr + INTERRUPT); 00655 break; 00656 } 00657 } 00658 00659 if ((status & IM_ALLOC_INT) != 0 ) { 00660 /* We've got the memory */ 00661 break; 00662 } else { 00663 printf("SMC9000: Memory allocation timed out, resetting MMU.\n"); 00664 _outw(MC_RESET, nic->ioaddr + MMU_CMD); 00665 } 00666 } 00667 00668 /* If I get here, I _know_ there is a packet slot waiting for me */ 00669 packet_no = inb(nic->ioaddr + PNR_ARR + 1); 00670 if (packet_no & 0x80) { 00671 /* or isn't there? BAD CHIP! */ 00672 printf("SMC9000: Memory allocation failed. \n"); 00673 return; 00674 } 00675 00676 /* we have a packet address, so tell the card to use it */ 00677 _outb(packet_no, nic->ioaddr + PNR_ARR); 00678 00679 /* point to the beginning of the packet */ 00680 _outw(PTR_AUTOINC, nic->ioaddr + POINTER); 00681 00682 #if SMC9000_DEBUG > 2 00683 printf("Trying to xmit packet of length %hX\n", length ); 00684 #endif 00685 00686 /* send the packet length ( +6 for status, length and ctl byte ) 00687 * and the status word ( set to zeros ) */ 00688 _outw(0, nic->ioaddr + DATA_1 ); 00689 00690 /* send the packet length ( +6 for status words, length, and ctl) */ 00691 _outb((length+6) & 0xFF, nic->ioaddr + DATA_1); 00692 _outb((length+6) >> 8 , nic->ioaddr + DATA_1); 00693 00694 /* Write the contents of the packet */ 00695 00696 /* The ethernet header first... */ 00697 outsw(nic->ioaddr + DATA_1, d, ETH_ALEN >> 1); 00698 outsw(nic->ioaddr + DATA_1, nic->node_addr, ETH_ALEN >> 1); 00699 _outw(htons(t), nic->ioaddr + DATA_1); 00700 00701 /* ... the data ... */ 00702 outsw(nic->ioaddr + DATA_1 , p, s >> 1); 00703 00704 /* ... and the last byte, if there is one. */ 00705 if ((s & 1) == 0) { 00706 _outw(0, nic->ioaddr + DATA_1); 00707 } else { 00708 _outb(p[s-1], nic->ioaddr + DATA_1); 00709 _outb(0x20, nic->ioaddr + DATA_1); 00710 } 00711 00712 /* and let the chipset deal with it */ 00713 _outw(MC_ENQUEUE , nic->ioaddr + MMU_CMD); 00714 00715 status = 0; time_out = currticks() + 5*TICKS_PER_SEC; 00716 do { 00717 status = inb(nic->ioaddr + INTERRUPT); 00718 00719 if ((status & IM_TX_INT ) != 0) { 00720 word tx_status; 00721 00722 /* ack interrupt */ 00723 _outb(IM_TX_INT, nic->ioaddr + INTERRUPT); 00724 00725 packet_no = inw(nic->ioaddr + FIFO_PORTS); 00726 packet_no &= 0x7F; 00727 00728 /* select this as the packet to read from */ 00729 _outb( packet_no, nic->ioaddr + PNR_ARR ); 00730 00731 /* read the first word from this packet */ 00732 _outw( PTR_AUTOINC | PTR_READ, nic->ioaddr + POINTER ); 00733 00734 tx_status = inw( nic->ioaddr + DATA_1 ); 00735 00736 if (0 == (tx_status & TS_SUCCESS)) { 00737 DBG("SMC9000: TX FAIL STATUS: %hX \n", tx_status); 00738 /* re-enable transmit */ 00739 SMC_SELECT_BANK(nic->ioaddr, 0); 00740 _outw(inw(nic->ioaddr + TCR ) | TCR_ENABLE, nic->ioaddr + TCR ); 00741 } 00742 00743 /* kill the packet */ 00744 SMC_SELECT_BANK(nic->ioaddr, 2); 00745 _outw(MC_FREEPKT, nic->ioaddr + MMU_CMD); 00746 00747 return; 00748 } 00749 }while(currticks() < time_out); 00750 00751 printf("SMC9000: TX timed out, resetting board\n"); 00752 smc_reset(nic->ioaddr); 00753 return; 00754 }
| static int smc9000_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 759 of file smc9000.c.
References _outw, DATA_1, FIFO_PORTS, FP_RXEMPTY, insw, inw, nic::ioaddr, MC_RELEASE, MMU_CMD, nic::packet, nic::packetlen, POINTER, printf(), PTR_AUTOINC, PTR_RCV, PTR_READ, RS_ERRORS, and SMC_SELECT_BANK.
00760 { 00761 SMC_SELECT_BANK(nic->ioaddr, 2); 00762 if (inw(nic->ioaddr + FIFO_PORTS) & FP_RXEMPTY) 00763 return 0; 00764 00765 if ( ! retrieve ) return 1; 00766 00767 /* start reading from the start of the packet */ 00768 _outw(PTR_READ | PTR_RCV | PTR_AUTOINC, nic->ioaddr + POINTER); 00769 00770 /* First read the status and check that we're ok */ 00771 if (!(inw(nic->ioaddr + DATA_1) & RS_ERRORS)) { 00772 /* Next: read the packet length and mask off the top bits */ 00773 nic->packetlen = (inw(nic->ioaddr + DATA_1) & 0x07ff); 00774 00775 /* the packet length includes the 3 extra words */ 00776 nic->packetlen -= 6; 00777 #if SMC9000_DEBUG > 2 00778 printf(" Reading %d words (and %d byte(s))\n", 00779 (nic->packetlen >> 1), nic->packetlen & 1); 00780 #endif 00781 /* read the packet (and the last "extra" word) */ 00782 insw(nic->ioaddr + DATA_1, nic->packet, (nic->packetlen+2) >> 1); 00783 /* is there an odd last byte ? */ 00784 if (nic->packet[nic->packetlen+1] & 0x20) 00785 nic->packetlen++; 00786 00787 /* error or good, tell the card to get rid of this packet */ 00788 _outw(MC_RELEASE, nic->ioaddr + MMU_CMD); 00789 return 1; 00790 } 00791 00792 printf("SMC9000: RX error\n"); 00793 /* error or good, tell the card to get rid of this packet */ 00794 _outw(MC_RELEASE, nic->ioaddr + MMU_CMD); 00795 return 0; 00796 }
| static void smc9000_disable | ( | struct nic * | nic, | |
| struct isa_device *isa | __unused | |||
| ) | [static] |
Definition at line 798 of file smc9000.c.
References _outb, INT_MASK, nic::ioaddr, RCR, RCR_CLEAR, smc_reset(), SMC_SELECT_BANK, TCR, and TCR_CLEAR.
00798 { 00799 00800 smc_reset(nic->ioaddr); 00801 00802 /* no more interrupts for me */ 00803 SMC_SELECT_BANK(nic->ioaddr, 2); 00804 _outb( 0, nic->ioaddr + INT_MASK); 00805 00806 /* and tell the card to stay away from that nasty outside world */ 00807 SMC_SELECT_BANK(nic->ioaddr, 0); 00808 _outb( RCR_CLEAR, nic->ioaddr + RCR ); 00809 _outb( TCR_CLEAR, nic->ioaddr + TCR ); 00810 }
| static void smc9000_irq | ( | struct nic *nic | __unused, | |
| irq_action_t action | __unused | |||
| ) | [static] |
| static int smc9000_probe | ( | struct nic * | nic, | |
| struct isa_device * | isa | |||
| ) | [static] |
Definition at line 836 of file smc9000.c.
References _outw, ADDR0, CFG_AUI_SELECT, CHIP_9196, chip_ids, CONFIG, DBG, eth_ntoa(), interfaces, inw, isa_device::ioaddr, nic::ioaddr, nic::irqno, MCR, media, MIR, nic::nic_op, nic::node_addr, printf(), RCR, RCR_NORMAL, REV_9196, REVISION, smc9000_version, smc91c96_id, smc_phy_configure(), smc_reset(), SMC_SELECT_BANK, TCR, and TCR_NORMAL.
00836 { 00837 00838 unsigned short revision; 00839 int memory; 00840 int media; 00841 const char * version_string; 00842 const char * if_string; 00843 int i; 00844 00845 nic->irqno = 0; 00846 nic->ioaddr = isa->ioaddr; 00847 00848 /* 00849 * Get the MAC address ( bank 1, regs 4 - 9 ) 00850 */ 00851 SMC_SELECT_BANK(nic->ioaddr, 1); 00852 for ( i = 0; i < 6; i += 2 ) { 00853 word address; 00854 00855 address = inw(nic->ioaddr + ADDR0 + i); 00856 nic->node_addr[i+1] = address >> 8; 00857 nic->node_addr[i] = address & 0xFF; 00858 } 00859 00860 /* get the memory information */ 00861 SMC_SELECT_BANK(nic->ioaddr, 0); 00862 memory = ( inw(nic->ioaddr + MCR) >> 9 ) & 0x7; /* multiplier */ 00863 memory *= 256 * (inw(nic->ioaddr + MIR) & 0xFF); 00864 00865 /* 00866 * Now, I want to find out more about the chip. This is sort of 00867 * redundant, but it's cleaner to have it in both, rather than having 00868 * one VERY long probe procedure. 00869 */ 00870 SMC_SELECT_BANK(nic->ioaddr, 3); 00871 revision = inw(nic->ioaddr + REVISION); 00872 version_string = chip_ids[(revision >> 4) & 0xF]; 00873 00874 if (((revision & 0xF0) >> 4 == CHIP_9196) && 00875 ((revision & 0x0F) >= REV_9196)) { 00876 /* This is a 91c96. 'c96 has the same chip id as 'c94 (4) but 00877 * a revision starting at 6 */ 00878 version_string = smc91c96_id; 00879 } 00880 00881 if ( !version_string ) { 00882 /* I shouldn't get here because this call was done before.... */ 00883 return 0; 00884 } 00885 00886 /* is it using AUI or 10BaseT ? */ 00887 SMC_SELECT_BANK(nic->ioaddr, 1); 00888 if (inw(nic->ioaddr + CONFIG) & CFG_AUI_SELECT) 00889 media = 2; 00890 else 00891 media = 1; 00892 00893 if_string = interfaces[media - 1]; 00894 00895 /* now, reset the chip, and put it into a known state */ 00896 smc_reset(nic->ioaddr); 00897 00898 printf("SMC9000 %s\n", smc9000_version); 00899 DBG("Copyright (C) 1998 Daniel Engstr\x94m\n"); 00900 DBG("Copyright (C) 1996 Eric Stahlman\n"); 00901 00902 printf("%s rev:%d I/O port:%hX Interface:%s RAM:%d bytes \n", 00903 version_string, revision & 0xF, 00904 nic->ioaddr, if_string, memory ); 00905 00906 DBG ( "Ethernet MAC address: %s\n", eth_ntoa ( nic->node_addr ) ); 00907 00908 SMC_SELECT_BANK(nic->ioaddr, 0); 00909 00910 /* see the header file for options in TCR/RCR NORMAL*/ 00911 _outw(TCR_NORMAL, nic->ioaddr + TCR); 00912 _outw(RCR_NORMAL, nic->ioaddr + RCR); 00913 00914 /* Select which interface to use */ 00915 SMC_SELECT_BANK(nic->ioaddr, 1); 00916 if ( media == 1 ) { 00917 _outw( inw( nic->ioaddr + CONFIG ) & ~CFG_AUI_SELECT, 00918 nic->ioaddr + CONFIG ); 00919 } 00920 else if ( media == 2 ) { 00921 _outw( inw( nic->ioaddr + CONFIG ) | CFG_AUI_SELECT, 00922 nic->ioaddr + CONFIG ); 00923 } 00924 00925 smc_phy_configure(nic->ioaddr); 00926 00927 nic->nic_op = &smc9000_operations; 00928 return 1; 00929 }
| ISA_DRIVER | ( | smc9000_driver | , | |
| smc9000_probe_addrs | , | |||
| smc9000_probe_addr | , | |||
| GENERIC_ISAPNP_VENDOR | , | |||
| 0x8228 | ||||
| ) |
| DRIVER | ( | "SMC9000" | , | |
| nic_driver | , | |||
| isa_driver | , | |||
| smc9000_driver | , | |||
| smc9000_probe | , | |||
| smc9000_disable | ||||
| ) |
| ISA_ROM | ( | "smc9000" | , | |
| "SMC9000" | ||||
| ) |
const char smc9000_version[] = "Version 0.99 98-09-30" [static] |
const char* interfaces[2] = { "TP", "AUI" } [static] |
const char* chip_ids[15] [static] |
Initial value:
{
NULL, NULL, NULL,
"SMC91C90/91C92",
"SMC91C94",
"SMC91C95",
NULL,
"SMC91C100",
"SMC91C100FD",
"SMC91C11xFD",
NULL, NULL,
NULL, NULL, NULL
}
Definition at line 53 of file smc9000.c.
Referenced by smc9000_probe(), and smc9000_probe_addr().
const char smc91c96_id[] = "SMC91C96" [static] |
struct nic_operations smc9000_operations [static] |
Initial value:
{
.connect = dummy_connect,
.poll = smc9000_poll,
.transmit = smc9000_transmit,
.irq = smc9000_irq,
}
isa_probe_addr_t smc9000_probe_addrs[] [static] |
1.5.7.1