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 | */ |
---|