[e16e8f2] | 1 | |
---|
| 2 | /* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */ |
---|
| 3 | |
---|
| 4 | FILE_LICENCE ( GPL2_OR_LATER ); |
---|
| 5 | |
---|
| 6 | /* 05/06/2003 timlegge Fixed relocation and implemented Multicast */ |
---|
| 7 | #define LINUX_OUT_MACROS |
---|
| 8 | |
---|
| 9 | #include "etherboot.h" |
---|
| 10 | #include <gpxe/pci.h> |
---|
| 11 | #include <gpxe/ethernet.h> |
---|
| 12 | #include "nic.h" |
---|
| 13 | #include "console.h" |
---|
| 14 | #include "epic100.h" |
---|
| 15 | |
---|
| 16 | /* Condensed operations for readability */ |
---|
| 17 | #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) |
---|
| 18 | #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) |
---|
| 19 | |
---|
| 20 | #define TX_RING_SIZE 2 /* use at least 2 buffers for TX */ |
---|
| 21 | #define RX_RING_SIZE 2 |
---|
| 22 | |
---|
| 23 | #define PKT_BUF_SZ 1536 /* Size of each temporary Tx/Rx buffer.*/ |
---|
| 24 | |
---|
| 25 | /* |
---|
| 26 | #define DEBUG_RX |
---|
| 27 | #define DEBUG_TX |
---|
| 28 | #define DEBUG_EEPROM |
---|
| 29 | */ |
---|
| 30 | |
---|
| 31 | #define EPIC_DEBUG 0 /* debug level */ |
---|
| 32 | |
---|
| 33 | /* The EPIC100 Rx and Tx buffer descriptors. */ |
---|
| 34 | struct epic_rx_desc { |
---|
| 35 | unsigned long status; |
---|
| 36 | unsigned long bufaddr; |
---|
| 37 | unsigned long buflength; |
---|
| 38 | unsigned long next; |
---|
| 39 | }; |
---|
| 40 | /* description of the tx descriptors control bits commonly used */ |
---|
| 41 | #define TD_STDFLAGS TD_LASTDESC |
---|
| 42 | |
---|
| 43 | struct epic_tx_desc { |
---|
| 44 | unsigned long status; |
---|
| 45 | unsigned long bufaddr; |
---|
| 46 | unsigned long buflength; |
---|
| 47 | unsigned long next; |
---|
| 48 | }; |
---|
| 49 | |
---|
| 50 | #define delay(nanosec) do { int _i = 3; while (--_i > 0) \ |
---|
| 51 | { __SLOW_DOWN_IO; }} while (0) |
---|
| 52 | |
---|
| 53 | static void epic100_open(void); |
---|
| 54 | static void epic100_init_ring(void); |
---|
| 55 | static void epic100_disable(struct nic *nic); |
---|
| 56 | static int epic100_poll(struct nic *nic, int retrieve); |
---|
| 57 | static void epic100_transmit(struct nic *nic, const char *destaddr, |
---|
| 58 | unsigned int type, unsigned int len, const char *data); |
---|
| 59 | #ifdef DEBUG_EEPROM |
---|
| 60 | static int read_eeprom(int location); |
---|
| 61 | #endif |
---|
| 62 | static int mii_read(int phy_id, int location); |
---|
| 63 | static void epic100_irq(struct nic *nic, irq_action_t action); |
---|
| 64 | |
---|
| 65 | static struct nic_operations epic100_operations; |
---|
| 66 | |
---|
| 67 | static int ioaddr; |
---|
| 68 | |
---|
| 69 | static int command; |
---|
| 70 | static int intstat; |
---|
| 71 | static int intmask; |
---|
| 72 | static int genctl ; |
---|
| 73 | static int eectl ; |
---|
| 74 | static int test ; |
---|
| 75 | static int mmctl ; |
---|
| 76 | static int mmdata ; |
---|
| 77 | static int lan0 ; |
---|
| 78 | static int mc0 ; |
---|
| 79 | static int rxcon ; |
---|
| 80 | static int txcon ; |
---|
| 81 | static int prcdar ; |
---|
| 82 | static int ptcdar ; |
---|
| 83 | static int eththr ; |
---|
| 84 | |
---|
| 85 | static unsigned int cur_rx, cur_tx; /* The next free ring entry */ |
---|
| 86 | #ifdef DEBUG_EEPROM |
---|
| 87 | static unsigned short eeprom[64]; |
---|
| 88 | #endif |
---|
| 89 | static signed char phys[4]; /* MII device addresses. */ |
---|
| 90 | struct { |
---|
| 91 | struct epic_rx_desc rx_ring[RX_RING_SIZE] |
---|
| 92 | __attribute__ ((aligned(4))); |
---|
| 93 | struct epic_tx_desc tx_ring[TX_RING_SIZE] |
---|
| 94 | __attribute__ ((aligned(4))); |
---|
| 95 | unsigned char rx_packet[PKT_BUF_SZ * RX_RING_SIZE]; |
---|
| 96 | unsigned char tx_packet[PKT_BUF_SZ * TX_RING_SIZE]; |
---|
| 97 | } epic100_bufs __shared; |
---|
| 98 | #define rx_ring epic100_bufs.rx_ring |
---|
| 99 | #define tx_ring epic100_bufs.tx_ring |
---|
| 100 | #define rx_packet epic100_bufs.rx_packet |
---|
| 101 | #define tx_packet epic100_bufs.tx_packet |
---|
| 102 | |
---|
| 103 | /***********************************************************************/ |
---|
| 104 | /* Externally visible functions */ |
---|
| 105 | /***********************************************************************/ |
---|
| 106 | |
---|
| 107 | |
---|
| 108 | static int |
---|
| 109 | epic100_probe ( struct nic *nic, struct pci_device *pci ) { |
---|
| 110 | |
---|
| 111 | int i; |
---|
| 112 | unsigned short* ap; |
---|
| 113 | unsigned int phy, phy_idx; |
---|
| 114 | |
---|
| 115 | if (pci->ioaddr == 0) |
---|
| 116 | return 0; |
---|
| 117 | |
---|
| 118 | /* Ideally we would detect all network cards in slot order. That would |
---|
| 119 | be best done a central PCI probe dispatch, which wouldn't work |
---|
| 120 | well with the current structure. So instead we detect just the |
---|
| 121 | Epic cards in slot order. */ |
---|
| 122 | |
---|
| 123 | ioaddr = pci->ioaddr; |
---|
| 124 | |
---|
| 125 | nic->irqno = 0; |
---|
| 126 | nic->ioaddr = pci->ioaddr & ~3; |
---|
| 127 | |
---|
| 128 | /* compute all used static epic100 registers address */ |
---|
| 129 | command = ioaddr + COMMAND; /* Control Register */ |
---|
| 130 | intstat = ioaddr + INTSTAT; /* Interrupt Status */ |
---|
| 131 | intmask = ioaddr + INTMASK; /* Interrupt Mask */ |
---|
| 132 | genctl = ioaddr + GENCTL; /* General Control */ |
---|
| 133 | eectl = ioaddr + EECTL; /* EEPROM Control */ |
---|
| 134 | test = ioaddr + TEST; /* Test register (clocks) */ |
---|
| 135 | mmctl = ioaddr + MMCTL; /* MII Management Interface Control */ |
---|
| 136 | mmdata = ioaddr + MMDATA; /* MII Management Interface Data */ |
---|
| 137 | lan0 = ioaddr + LAN0; /* MAC address. (0x40-0x48) */ |
---|
| 138 | mc0 = ioaddr + MC0; /* Multicast Control */ |
---|
| 139 | rxcon = ioaddr + RXCON; /* Receive Control */ |
---|
| 140 | txcon = ioaddr + TXCON; /* Transmit Control */ |
---|
| 141 | prcdar = ioaddr + PRCDAR; /* PCI Receive Current Descr Address */ |
---|
| 142 | ptcdar = ioaddr + PTCDAR; /* PCI Transmit Current Descr Address */ |
---|
| 143 | eththr = ioaddr + ETHTHR; /* Early Transmit Threshold */ |
---|
| 144 | |
---|
| 145 | /* Reset the chip & bring it out of low-power mode. */ |
---|
| 146 | outl(GC_SOFT_RESET, genctl); |
---|
| 147 | |
---|
| 148 | /* Disable ALL interrupts by setting the interrupt mask. */ |
---|
| 149 | outl(INTR_DISABLE, intmask); |
---|
| 150 | |
---|
| 151 | /* |
---|
| 152 | * set the internal clocks: |
---|
| 153 | * Application Note 7.15 says: |
---|
| 154 | * In order to set the CLOCK TEST bit in the TEST register, |
---|
| 155 | * perform the following: |
---|
| 156 | * |
---|
| 157 | * Write 0x0008 to the test register at least sixteen |
---|
| 158 | * consecutive times. |
---|
| 159 | * |
---|
| 160 | * The CLOCK TEST bit is Write-Only. Writing it several times |
---|
| 161 | * consecutively insures a successful write to the bit... |
---|
| 162 | */ |
---|
| 163 | |
---|
| 164 | for (i = 0; i < 16; i++) { |
---|
| 165 | outl(0x00000008, test); |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | #ifdef DEBUG_EEPROM |
---|
| 169 | { |
---|
| 170 | unsigned short sum = 0; |
---|
| 171 | unsigned short value; |
---|
| 172 | for (i = 0; i < 64; i++) { |
---|
| 173 | value = read_eeprom(i); |
---|
| 174 | eeprom[i] = value; |
---|
| 175 | sum += value; |
---|
| 176 | } |
---|
| 177 | } |
---|
| 178 | |
---|
| 179 | #if (EPIC_DEBUG > 1) |
---|
| 180 | printf("EEPROM contents\n"); |
---|
| 181 | for (i = 0; i < 64; i++) { |
---|
| 182 | printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : ""); |
---|
| 183 | } |
---|
| 184 | #endif |
---|
| 185 | #endif |
---|
| 186 | |
---|
| 187 | /* This could also be read from the EEPROM. */ |
---|
| 188 | ap = (unsigned short*)nic->node_addr; |
---|
| 189 | for (i = 0; i < 3; i++) |
---|
| 190 | *ap++ = inw(lan0 + i*4); |
---|
| 191 | |
---|
| 192 | DBG ( " I/O %4.4x %s ", ioaddr, eth_ntoa ( nic->node_addr ) ); |
---|
| 193 | |
---|
| 194 | /* Find the connected MII xcvrs. */ |
---|
| 195 | for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) { |
---|
| 196 | int mii_status = mii_read(phy, 0); |
---|
| 197 | |
---|
| 198 | if (mii_status != 0xffff && mii_status != 0x0000) { |
---|
| 199 | phys[phy_idx++] = phy; |
---|
| 200 | #if (EPIC_DEBUG > 1) |
---|
| 201 | printf("MII transceiver found at address %d.\n", phy); |
---|
| 202 | #endif |
---|
| 203 | } |
---|
| 204 | } |
---|
| 205 | if (phy_idx == 0) { |
---|
| 206 | #if (EPIC_DEBUG > 1) |
---|
| 207 | printf("***WARNING***: No MII transceiver found!\n"); |
---|
| 208 | #endif |
---|
| 209 | /* Use the known PHY address of the EPII. */ |
---|
| 210 | phys[0] = 3; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | epic100_open(); |
---|
| 214 | nic->nic_op = &epic100_operations; |
---|
| 215 | |
---|
| 216 | return 1; |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | static void set_rx_mode(void) |
---|
| 220 | { |
---|
| 221 | unsigned char mc_filter[8]; |
---|
| 222 | int i; |
---|
| 223 | memset(mc_filter, 0xff, sizeof(mc_filter)); |
---|
| 224 | outl(0x0C, rxcon); |
---|
| 225 | for(i = 0; i < 4; i++) |
---|
| 226 | outw(((unsigned short *)mc_filter)[i], mc0 + i*4); |
---|
| 227 | return; |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | static void |
---|
| 231 | epic100_open(void) |
---|
| 232 | { |
---|
| 233 | int mii_reg5; |
---|
| 234 | int full_duplex = 0; |
---|
| 235 | unsigned long tmp; |
---|
| 236 | |
---|
| 237 | epic100_init_ring(); |
---|
| 238 | |
---|
| 239 | /* Pull the chip out of low-power mode, and set for PCI read multiple. */ |
---|
| 240 | outl(GC_RX_FIFO_THR_64 | GC_MRC_READ_MULT | GC_ONE_COPY, genctl); |
---|
| 241 | |
---|
| 242 | outl(TX_FIFO_THRESH, eththr); |
---|
| 243 | |
---|
| 244 | tmp = TC_EARLY_TX_ENABLE | TX_SLOT_TIME; |
---|
| 245 | |
---|
| 246 | mii_reg5 = mii_read(phys[0], 5); |
---|
| 247 | if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) { |
---|
| 248 | full_duplex = 1; |
---|
| 249 | printf(" full-duplex mode"); |
---|
| 250 | tmp |= TC_LM_FULL_DPX; |
---|
| 251 | } else |
---|
| 252 | tmp |= TC_LM_NORMAL; |
---|
| 253 | |
---|
| 254 | outl(tmp, txcon); |
---|
| 255 | |
---|
| 256 | /* Give adress of RX and TX ring to the chip */ |
---|
| 257 | outl(virt_to_le32desc(&rx_ring), prcdar); |
---|
| 258 | outl(virt_to_le32desc(&tx_ring), ptcdar); |
---|
| 259 | |
---|
| 260 | /* Start the chip's Rx process: receive unicast and broadcast */ |
---|
| 261 | set_rx_mode(); |
---|
| 262 | outl(CR_START_RX | CR_QUEUE_RX, command); |
---|
| 263 | |
---|
| 264 | putchar('\n'); |
---|
| 265 | } |
---|
| 266 | |
---|
| 267 | /* Initialize the Rx and Tx rings. */ |
---|
| 268 | static void |
---|
| 269 | epic100_init_ring(void) |
---|
| 270 | { |
---|
| 271 | int i; |
---|
| 272 | |
---|
| 273 | cur_rx = cur_tx = 0; |
---|
| 274 | |
---|
| 275 | for (i = 0; i < RX_RING_SIZE; i++) { |
---|
| 276 | rx_ring[i].status = cpu_to_le32(RRING_OWN); /* Owned by Epic chip */ |
---|
| 277 | rx_ring[i].buflength = cpu_to_le32(PKT_BUF_SZ); |
---|
| 278 | rx_ring[i].bufaddr = virt_to_bus(&rx_packet[i * PKT_BUF_SZ]); |
---|
| 279 | rx_ring[i].next = virt_to_le32desc(&rx_ring[i + 1]) ; |
---|
| 280 | } |
---|
| 281 | /* Mark the last entry as wrapping the ring. */ |
---|
| 282 | rx_ring[i-1].next = virt_to_le32desc(&rx_ring[0]); |
---|
| 283 | |
---|
| 284 | /* |
---|
| 285 | *The Tx buffer descriptor is filled in as needed, |
---|
| 286 | * but we do need to clear the ownership bit. |
---|
| 287 | */ |
---|
| 288 | |
---|
| 289 | for (i = 0; i < TX_RING_SIZE; i++) { |
---|
| 290 | tx_ring[i].status = 0x0000; /* Owned by CPU */ |
---|
| 291 | tx_ring[i].buflength = 0x0000 | cpu_to_le32(TD_STDFLAGS << 16); |
---|
| 292 | tx_ring[i].bufaddr = virt_to_bus(&tx_packet[i * PKT_BUF_SZ]); |
---|
| 293 | tx_ring[i].next = virt_to_le32desc(&tx_ring[i + 1]); |
---|
| 294 | } |
---|
| 295 | tx_ring[i-1].next = virt_to_le32desc(&tx_ring[0]); |
---|
| 296 | } |
---|
| 297 | |
---|
| 298 | /* function: epic100_transmit |
---|
| 299 | * This transmits a packet. |
---|
| 300 | * |
---|
| 301 | * Arguments: char d[6]: destination ethernet address. |
---|
| 302 | * unsigned short t: ethernet protocol type. |
---|
| 303 | * unsigned short s: size of the data-part of the packet. |
---|
| 304 | * char *p: the data for the packet. |
---|
| 305 | * returns: void. |
---|
| 306 | */ |
---|
| 307 | static void |
---|
| 308 | epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type, |
---|
| 309 | unsigned int len, const char *data) |
---|
| 310 | { |
---|
| 311 | unsigned short nstype; |
---|
| 312 | unsigned char *txp; |
---|
| 313 | int entry; |
---|
| 314 | unsigned long ct; |
---|
| 315 | |
---|
| 316 | /* Calculate the next Tx descriptor entry. */ |
---|
| 317 | entry = cur_tx % TX_RING_SIZE; |
---|
| 318 | |
---|
| 319 | if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) { |
---|
| 320 | printf("eth_transmit: Unable to transmit. status=%4.4lx. Resetting...\n", |
---|
| 321 | tx_ring[entry].status); |
---|
| 322 | |
---|
| 323 | epic100_open(); |
---|
| 324 | return; |
---|
| 325 | } |
---|
| 326 | |
---|
| 327 | txp = tx_packet + (entry * PKT_BUF_SZ); |
---|
| 328 | |
---|
| 329 | memcpy(txp, destaddr, ETH_ALEN); |
---|
| 330 | memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN); |
---|
| 331 | nstype = htons(type); |
---|
| 332 | memcpy(txp + 12, (char*)&nstype, 2); |
---|
| 333 | memcpy(txp + ETH_HLEN, data, len); |
---|
| 334 | |
---|
| 335 | len += ETH_HLEN; |
---|
| 336 | len &= 0x0FFF; |
---|
| 337 | while(len < ETH_ZLEN) |
---|
| 338 | txp[len++] = '\0'; |
---|
| 339 | /* |
---|
| 340 | * Caution: the write order is important here, |
---|
| 341 | * set the base address with the "ownership" |
---|
| 342 | * bits last. |
---|
| 343 | */ |
---|
| 344 | |
---|
| 345 | tx_ring[entry].buflength |= cpu_to_le32(len); |
---|
| 346 | tx_ring[entry].status = cpu_to_le32(len << 16) | |
---|
| 347 | cpu_to_le32(TRING_OWN); /* Pass ownership to the chip. */ |
---|
| 348 | |
---|
| 349 | cur_tx++; |
---|
| 350 | |
---|
| 351 | /* Trigger an immediate transmit demand. */ |
---|
| 352 | outl(CR_QUEUE_TX, command); |
---|
| 353 | |
---|
| 354 | ct = currticks(); |
---|
| 355 | /* timeout 10 ms for transmit */ |
---|
| 356 | while ((le32_to_cpu(tx_ring[entry].status) & (TRING_OWN)) && |
---|
| 357 | ct + 10*1000 < currticks()) |
---|
| 358 | /* Wait */; |
---|
| 359 | |
---|
| 360 | if ((le32_to_cpu(tx_ring[entry].status) & TRING_OWN) != 0) |
---|
| 361 | printf("Oops, transmitter timeout, status=%4.4lX\n", |
---|
| 362 | tx_ring[entry].status); |
---|
| 363 | } |
---|
| 364 | |
---|
| 365 | /* function: epic100_poll / eth_poll |
---|
| 366 | * This receives a packet from the network. |
---|
| 367 | * |
---|
| 368 | * Arguments: none |
---|
| 369 | * |
---|
| 370 | * returns: 1 if a packet was received. |
---|
| 371 | * 0 if no pacet was received. |
---|
| 372 | * side effects: |
---|
| 373 | * returns the packet in the array nic->packet. |
---|
| 374 | * returns the length of the packet in nic->packetlen. |
---|
| 375 | */ |
---|
| 376 | |
---|
| 377 | static int |
---|
| 378 | epic100_poll(struct nic *nic, int retrieve) |
---|
| 379 | { |
---|
| 380 | int entry; |
---|
| 381 | int retcode; |
---|
| 382 | int status; |
---|
| 383 | entry = cur_rx % RX_RING_SIZE; |
---|
| 384 | |
---|
| 385 | if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN) |
---|
| 386 | return (0); |
---|
| 387 | |
---|
| 388 | if ( ! retrieve ) return 1; |
---|
| 389 | |
---|
| 390 | status = le32_to_cpu(rx_ring[entry].status); |
---|
| 391 | /* We own the next entry, it's a new packet. Send it up. */ |
---|
| 392 | |
---|
| 393 | #if (EPIC_DEBUG > 4) |
---|
| 394 | printf("epic_poll: entry %d status %hX\n", entry, status); |
---|
| 395 | #endif |
---|
| 396 | |
---|
| 397 | cur_rx++; |
---|
| 398 | if (status & 0x2000) { |
---|
| 399 | printf("epic_poll: Giant packet\n"); |
---|
| 400 | retcode = 0; |
---|
| 401 | } else if (status & 0x0006) { |
---|
| 402 | /* Rx Frame errors are counted in hardware. */ |
---|
| 403 | printf("epic_poll: Frame received with errors\n"); |
---|
| 404 | retcode = 0; |
---|
| 405 | } else { |
---|
| 406 | /* Omit the four octet CRC from the length. */ |
---|
| 407 | nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4; |
---|
| 408 | memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen); |
---|
| 409 | retcode = 1; |
---|
| 410 | } |
---|
| 411 | |
---|
| 412 | /* Clear all error sources. */ |
---|
| 413 | outl(status & INTR_CLEARERRS, intstat); |
---|
| 414 | |
---|
| 415 | /* Give the descriptor back to the chip */ |
---|
| 416 | rx_ring[entry].status = RRING_OWN; |
---|
| 417 | |
---|
| 418 | /* Restart Receiver */ |
---|
| 419 | outl(CR_START_RX | CR_QUEUE_RX, command); |
---|
| 420 | |
---|
| 421 | return retcode; |
---|
| 422 | } |
---|
| 423 | |
---|
| 424 | |
---|
| 425 | static void epic100_disable ( struct nic *nic __unused ) { |
---|
| 426 | /* Soft reset the chip. */ |
---|
| 427 | outl(GC_SOFT_RESET, genctl); |
---|
| 428 | } |
---|
| 429 | |
---|
| 430 | static void epic100_irq(struct nic *nic __unused, irq_action_t action __unused) |
---|
| 431 | { |
---|
| 432 | switch ( action ) { |
---|
| 433 | case DISABLE : |
---|
| 434 | break; |
---|
| 435 | case ENABLE : |
---|
| 436 | break; |
---|
| 437 | case FORCE : |
---|
| 438 | break; |
---|
| 439 | } |
---|
| 440 | } |
---|
| 441 | |
---|
| 442 | #ifdef DEBUG_EEPROM |
---|
| 443 | /* Serial EEPROM section. */ |
---|
| 444 | |
---|
| 445 | /* EEPROM_Ctrl bits. */ |
---|
| 446 | #define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ |
---|
| 447 | #define EE_CS 0x02 /* EEPROM chip select. */ |
---|
| 448 | #define EE_DATA_WRITE 0x08 /* EEPROM chip data in. */ |
---|
| 449 | #define EE_WRITE_0 0x01 |
---|
| 450 | #define EE_WRITE_1 0x09 |
---|
| 451 | #define EE_DATA_READ 0x10 /* EEPROM chip data out. */ |
---|
| 452 | #define EE_ENB (0x0001 | EE_CS) |
---|
| 453 | |
---|
| 454 | /* The EEPROM commands include the alway-set leading bit. */ |
---|
| 455 | #define EE_WRITE_CMD (5 << 6) |
---|
| 456 | #define EE_READ_CMD (6 << 6) |
---|
| 457 | #define EE_ERASE_CMD (7 << 6) |
---|
| 458 | |
---|
| 459 | #define eeprom_delay(n) delay(n) |
---|
| 460 | |
---|
| 461 | static int |
---|
| 462 | read_eeprom(int location) |
---|
| 463 | { |
---|
| 464 | int i; |
---|
| 465 | int retval = 0; |
---|
| 466 | int read_cmd = location | EE_READ_CMD; |
---|
| 467 | |
---|
| 468 | outl(EE_ENB & ~EE_CS, eectl); |
---|
| 469 | outl(EE_ENB, eectl); |
---|
| 470 | |
---|
| 471 | /* Shift the read command bits out. */ |
---|
| 472 | for (i = 10; i >= 0; i--) { |
---|
| 473 | short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; |
---|
| 474 | outl(EE_ENB | dataval, eectl); |
---|
| 475 | eeprom_delay(100); |
---|
| 476 | outl(EE_ENB | dataval | EE_SHIFT_CLK, eectl); |
---|
| 477 | eeprom_delay(150); |
---|
| 478 | outl(EE_ENB | dataval, eectl); /* Finish EEPROM a clock tick. */ |
---|
| 479 | eeprom_delay(250); |
---|
| 480 | } |
---|
| 481 | outl(EE_ENB, eectl); |
---|
| 482 | |
---|
| 483 | for (i = 16; i > 0; i--) { |
---|
| 484 | outl(EE_ENB | EE_SHIFT_CLK, eectl); |
---|
| 485 | eeprom_delay(100); |
---|
| 486 | retval = (retval << 1) | ((inl(eectl) & EE_DATA_READ) ? 1 : 0); |
---|
| 487 | outl(EE_ENB, eectl); |
---|
| 488 | eeprom_delay(100); |
---|
| 489 | } |
---|
| 490 | |
---|
| 491 | /* Terminate the EEPROM access. */ |
---|
| 492 | outl(EE_ENB & ~EE_CS, eectl); |
---|
| 493 | return retval; |
---|
| 494 | } |
---|
| 495 | #endif |
---|
| 496 | |
---|
| 497 | |
---|
| 498 | #define MII_READOP 1 |
---|
| 499 | #define MII_WRITEOP 2 |
---|
| 500 | |
---|
| 501 | static int |
---|
| 502 | mii_read(int phy_id, int location) |
---|
| 503 | { |
---|
| 504 | int i; |
---|
| 505 | |
---|
| 506 | outl((phy_id << 9) | (location << 4) | MII_READOP, mmctl); |
---|
| 507 | /* Typical operation takes < 50 ticks. */ |
---|
| 508 | |
---|
| 509 | for (i = 4000; i > 0; i--) |
---|
| 510 | if ((inl(mmctl) & MII_READOP) == 0) |
---|
| 511 | break; |
---|
| 512 | return inw(mmdata); |
---|
| 513 | } |
---|
| 514 | |
---|
| 515 | static struct nic_operations epic100_operations = { |
---|
| 516 | .connect = dummy_connect, |
---|
| 517 | .poll = epic100_poll, |
---|
| 518 | .transmit = epic100_transmit, |
---|
| 519 | .irq = epic100_irq, |
---|
| 520 | |
---|
| 521 | }; |
---|
| 522 | |
---|
| 523 | static struct pci_device_id epic100_nics[] = { |
---|
| 524 | PCI_ROM(0x10b8, 0x0005, "epic100", "SMC EtherPowerII", 0), /* SMC 83c170 EPIC/100 */ |
---|
| 525 | PCI_ROM(0x10b8, 0x0006, "smc-83c175", "SMC EPIC/C 83c175", 0), |
---|
| 526 | }; |
---|
| 527 | |
---|
| 528 | PCI_DRIVER ( epic100_driver, epic100_nics, PCI_NO_CLASS ); |
---|
| 529 | |
---|
| 530 | DRIVER ( "EPIC100", nic_driver, pci_driver, epic100_driver, |
---|
| 531 | epic100_probe, epic100_disable ); |
---|
| 532 | |
---|
| 533 | /* |
---|
| 534 | * Local variables: |
---|
| 535 | * c-basic-offset: 8 |
---|
| 536 | * c-indent-level: 8 |
---|
| 537 | * tab-width: 8 |
---|
| 538 | * End: |
---|
| 539 | */ |
---|