You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /**************************************************************************
  2. ETHERBOOT - BOOTP/TFTP Bootstrap Program
  3. Author: Martin Renters
  4. Date: May/94
  5. This code is based heavily on David Greenman's if_ed.c driver
  6. Copyright (C) 1993-1994, David Greenman, Martin Renters.
  7. This software may be used, modified, copied, distributed, and sold, in
  8. both source and binary form provided that the above copyright and these
  9. terms are retained. Under no circumstances are the authors responsible for
  10. the proper functioning of this software, nor do the authors assume any
  11. responsibility for damages incurred with its use.
  12. Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003
  13. Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/02
  14. 3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
  15. SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
  16. 3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
  17. RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
  18. parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
  19. SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02
  20. based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
  21. **************************************************************************/
  22. FILE_LICENCE ( BSD2 );
  23. /* #warning "ns8390.c: FIXME: split ISA and PCI, clean up" */
  24. #if 1
  25. #if !defined(INCLUDE_NS8390) && !defined(INCLUDE_WD) && \
  26. !defined(INCLUDE_NE) && !defined(INCLUDE_3C503)
  27. /* The driver named ns8390 is the PCI driver, often called
  28. "PCI ne2000 clones". */
  29. # define INCLUDE_NS8390 1
  30. #endif
  31. #include "etherboot.h"
  32. #include "nic.h"
  33. #include "ns8390.h"
  34. #include <ipxe/ethernet.h>
  35. #ifdef INCLUDE_NS8390
  36. #include <ipxe/pci.h>
  37. #else
  38. #include <ipxe/isa.h>
  39. #endif
  40. static unsigned char eth_vendor, eth_flags;
  41. #ifdef INCLUDE_WD
  42. static unsigned char eth_laar;
  43. #endif
  44. static unsigned short eth_nic_base, eth_asic_base;
  45. static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
  46. static Address eth_bmem, eth_rmem;
  47. static unsigned char eth_drain_receiver;
  48. #ifdef INCLUDE_WD
  49. static struct wd_board {
  50. const char *name;
  51. char id;
  52. char flags;
  53. char memsize;
  54. } wd_boards[] = {
  55. {"WD8003S", TYPE_WD8003S, 0, MEM_8192},
  56. {"WD8003E", TYPE_WD8003E, 0, MEM_8192},
  57. {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
  58. {"WD8003W", TYPE_WD8003W, 0, MEM_8192},
  59. {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
  60. {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
  61. {"WD8003EP/WD8013EP",
  62. TYPE_WD8013EP, 0, MEM_8192},
  63. {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
  64. {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
  65. {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
  66. {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
  67. {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
  68. {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
  69. {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
  70. {NULL, 0, 0, 0}
  71. };
  72. #endif
  73. #ifdef INCLUDE_3C503
  74. static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
  75. #endif
  76. #if defined(INCLUDE_WD)
  77. #define ASIC_PIO WD_IAR
  78. #define eth_probe wd_probe
  79. #if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
  80. Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
  81. #endif
  82. #endif
  83. #if defined(INCLUDE_3C503)
  84. #define eth_probe t503_probe
  85. #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
  86. Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
  87. #endif
  88. #endif
  89. #if defined(INCLUDE_NE)
  90. #define eth_probe ne_probe
  91. #if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
  92. Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
  93. #endif
  94. #endif
  95. #if defined(INCLUDE_NS8390)
  96. #define eth_probe nepci_probe
  97. #if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
  98. Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
  99. #endif
  100. #endif
  101. #if defined(INCLUDE_3C503)
  102. #define ASIC_PIO _3COM_RFMSB
  103. #else
  104. #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
  105. #define ASIC_PIO NE_DATA
  106. #endif
  107. #endif
  108. #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
  109. /**************************************************************************
  110. ETH_PIO_READ - Read a frame via Programmed I/O
  111. **************************************************************************/
  112. static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
  113. {
  114. #ifdef INCLUDE_WD
  115. outb(src & 0xff, eth_asic_base + WD_GP2);
  116. outb(src >> 8, eth_asic_base + WD_GP2);
  117. #else
  118. outb(D8390_COMMAND_RD2 |
  119. D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
  120. outb(cnt, eth_nic_base + D8390_P0_RBCR0);
  121. outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
  122. outb(src, eth_nic_base + D8390_P0_RSAR0);
  123. outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
  124. outb(D8390_COMMAND_RD0 |
  125. D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
  126. #ifdef INCLUDE_3C503
  127. outb(src & 0xff, eth_asic_base + _3COM_DALSB);
  128. outb(src >> 8, eth_asic_base + _3COM_DAMSB);
  129. outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
  130. #endif
  131. #endif
  132. if (eth_flags & FLAG_16BIT)
  133. cnt = (cnt + 1) >> 1;
  134. while(cnt--) {
  135. #ifdef INCLUDE_3C503
  136. while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
  137. ;
  138. #endif
  139. if (eth_flags & FLAG_16BIT) {
  140. *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
  141. dst += 2;
  142. }
  143. else
  144. *(dst++) = inb(eth_asic_base + ASIC_PIO);
  145. }
  146. #ifdef INCLUDE_3C503
  147. outb(t503_output, eth_asic_base + _3COM_CR);
  148. #endif
  149. }
  150. /**************************************************************************
  151. ETH_PIO_WRITE - Write a frame via Programmed I/O
  152. **************************************************************************/
  153. static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
  154. {
  155. #ifdef COMPEX_RL2000_FIX
  156. unsigned int x;
  157. #endif /* COMPEX_RL2000_FIX */
  158. #ifdef INCLUDE_WD
  159. outb(dst & 0xff, eth_asic_base + WD_GP2);
  160. outb(dst >> 8, eth_asic_base + WD_GP2);
  161. #else
  162. outb(D8390_COMMAND_RD2 |
  163. D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
  164. outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
  165. outb(cnt, eth_nic_base + D8390_P0_RBCR0);
  166. outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
  167. outb(dst, eth_nic_base + D8390_P0_RSAR0);
  168. outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
  169. outb(D8390_COMMAND_RD1 |
  170. D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
  171. #ifdef INCLUDE_3C503
  172. outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
  173. outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
  174. outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
  175. #endif
  176. #endif
  177. if (eth_flags & FLAG_16BIT)
  178. cnt = (cnt + 1) >> 1;
  179. while(cnt--)
  180. {
  181. #ifdef INCLUDE_3C503
  182. while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
  183. ;
  184. #endif
  185. if (eth_flags & FLAG_16BIT) {
  186. outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
  187. src += 2;
  188. }
  189. else
  190. outb(*(src++), eth_asic_base + ASIC_PIO);
  191. }
  192. #ifdef INCLUDE_3C503
  193. outb(t503_output, eth_asic_base + _3COM_CR);
  194. #else
  195. #ifdef COMPEX_RL2000_FIX
  196. for (x = 0;
  197. x < COMPEX_RL2000_TRIES &&
  198. (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
  199. != D8390_ISR_RDC;
  200. ++x);
  201. if (x >= COMPEX_RL2000_TRIES)
  202. printf("Warning: Compex RL2000 aborted wait!\n");
  203. #endif /* COMPEX_RL2000_FIX */
  204. #ifndef INCLUDE_WD
  205. while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
  206. != D8390_ISR_RDC);
  207. #endif
  208. #endif
  209. }
  210. #else
  211. /**************************************************************************
  212. ETH_PIO_READ - Dummy routine when NE2000 not compiled in
  213. **************************************************************************/
  214. static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}
  215. #endif
  216. /**************************************************************************
  217. enable_multycast - Enable Multicast
  218. **************************************************************************/
  219. static void enable_multicast(unsigned short eth_nic_base)
  220. {
  221. unsigned char mcfilter[8];
  222. int i;
  223. memset(mcfilter, 0xFF, 8);
  224. outb(4, eth_nic_base+D8390_P0_RCR);
  225. outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND);
  226. for(i=0;i<8;i++)
  227. {
  228. outb(mcfilter[i], eth_nic_base + 8 + i);
  229. if(inb(eth_nic_base + 8 + i)!=mcfilter[i])
  230. printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i);
  231. }
  232. outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND);
  233. outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);
  234. }
  235. /**************************************************************************
  236. NS8390_RESET - Reset adapter
  237. **************************************************************************/
  238. static void ns8390_reset(struct nic *nic)
  239. {
  240. int i;
  241. eth_drain_receiver = 0;
  242. #ifdef INCLUDE_WD
  243. if (eth_flags & FLAG_790)
  244. outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  245. else
  246. #endif
  247. outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
  248. D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  249. if (eth_flags & FLAG_16BIT)
  250. outb(0x49, eth_nic_base+D8390_P0_DCR);
  251. else
  252. outb(0x48, eth_nic_base+D8390_P0_DCR);
  253. outb(0, eth_nic_base+D8390_P0_RBCR0);
  254. outb(0, eth_nic_base+D8390_P0_RBCR1);
  255. outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */
  256. outb(2, eth_nic_base+D8390_P0_TCR);
  257. outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
  258. outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
  259. #ifdef INCLUDE_WD
  260. if (eth_flags & FLAG_790) {
  261. #ifdef WD_790_PIO
  262. outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */
  263. outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */
  264. #else
  265. outb(0, eth_nic_base + 0x09);
  266. #endif
  267. }
  268. #endif
  269. outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
  270. outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
  271. outb(0xFF, eth_nic_base+D8390_P0_ISR);
  272. outb(0, eth_nic_base+D8390_P0_IMR);
  273. #ifdef INCLUDE_WD
  274. if (eth_flags & FLAG_790)
  275. outb(D8390_COMMAND_PS1 |
  276. D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  277. else
  278. #endif
  279. outb(D8390_COMMAND_PS1 |
  280. D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  281. for (i=0; i<ETH_ALEN; i++)
  282. outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
  283. for (i=0; i<ETH_ALEN; i++)
  284. outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
  285. outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
  286. #ifdef INCLUDE_WD
  287. if (eth_flags & FLAG_790)
  288. outb(D8390_COMMAND_PS0 |
  289. D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  290. else
  291. #endif
  292. outb(D8390_COMMAND_PS0 |
  293. D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  294. outb(0xFF, eth_nic_base+D8390_P0_ISR);
  295. outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */
  296. outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */
  297. enable_multicast(eth_nic_base);
  298. #ifdef INCLUDE_3C503
  299. /*
  300. * No way to tell whether or not we're supposed to use
  301. * the 3Com's transceiver unless the user tells us.
  302. * 'flags' should have some compile time default value
  303. * which can be changed from the command menu.
  304. */
  305. t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
  306. outb(t503_output, eth_asic_base + _3COM_CR);
  307. #endif
  308. }
  309. static int ns8390_poll(struct nic *nic, int retrieve);
  310. #ifndef INCLUDE_3C503
  311. /**************************************************************************
  312. ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
  313. **************************************************************************/
  314. static void eth_rx_overrun(struct nic *nic)
  315. {
  316. int start_time;
  317. #ifdef INCLUDE_WD
  318. if (eth_flags & FLAG_790)
  319. outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  320. else
  321. #endif
  322. outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
  323. D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
  324. /* wait for at least 1.6ms - we wait one timer tick */
  325. start_time = currticks();
  326. while (currticks() - start_time <= 1)
  327. /* Nothing */;
  328. outb(0, eth_nic_base+D8390_P0_RBCR0); /* reset byte counter */
  329. outb(0, eth_nic_base+D8390_P0_RBCR1);
  330. /*
  331. * Linux driver checks for interrupted TX here. This is not necessary,
  332. * because the transmit routine waits until the frame is sent.
  333. */
  334. /* enter loopback mode and restart NIC */
  335. outb(2, eth_nic_base+D8390_P0_TCR);
  336. #ifdef INCLUDE_WD
  337. if (eth_flags & FLAG_790)
  338. outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  339. else
  340. #endif
  341. outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
  342. D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  343. /* clear the RX ring, acknowledge overrun interrupt */
  344. eth_drain_receiver = 1;
  345. while (ns8390_poll(nic, 1))
  346. /* Nothing */;
  347. eth_drain_receiver = 0;
  348. outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
  349. /* leave loopback mode - no packets to be resent (see Linux driver) */
  350. outb(0, eth_nic_base+D8390_P0_TCR);
  351. }
  352. #endif /* INCLUDE_3C503 */
  353. /**************************************************************************
  354. NS8390_TRANSMIT - Transmit a frame
  355. **************************************************************************/
  356. static void ns8390_transmit(
  357. struct nic *nic,
  358. const char *d, /* Destination */
  359. unsigned int t, /* Type */
  360. unsigned int s, /* size */
  361. const char *p) /* Packet */
  362. {
  363. #if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))
  364. Address eth_vmem = bus_to_virt(eth_bmem);
  365. #endif
  366. #ifdef INCLUDE_3C503
  367. if (!(eth_flags & FLAG_PIO)) {
  368. memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
  369. memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
  370. *((char *)eth_vmem+12) = t>>8; /* type */
  371. *((char *)eth_vmem+13) = t;
  372. memcpy((char *)eth_vmem+ETH_HLEN, p, s);
  373. s += ETH_HLEN;
  374. while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
  375. }
  376. #endif
  377. #ifdef INCLUDE_WD
  378. if (eth_flags & FLAG_16BIT) {
  379. outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
  380. inb(0x84);
  381. }
  382. #ifndef WD_790_PIO
  383. /* Memory interface */
  384. if (eth_flags & FLAG_790) {
  385. outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
  386. inb(0x84);
  387. }
  388. inb(0x84);
  389. memcpy((char *)eth_vmem, d, ETH_ALEN); /* dst */
  390. memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
  391. *((char *)eth_vmem+12) = t>>8; /* type */
  392. *((char *)eth_vmem+13) = t;
  393. memcpy((char *)eth_vmem+ETH_HLEN, p, s);
  394. s += ETH_HLEN;
  395. while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;
  396. if (eth_flags & FLAG_790) {
  397. outb(0, eth_asic_base + WD_MSR);
  398. inb(0x84);
  399. }
  400. #else
  401. inb(0x84);
  402. #endif
  403. #endif
  404. #if defined(INCLUDE_3C503)
  405. if (eth_flags & FLAG_PIO)
  406. #endif
  407. #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))
  408. {
  409. /* Programmed I/O */
  410. unsigned short type;
  411. type = (t >> 8) | (t << 8);
  412. eth_pio_write( (unsigned char *) d, eth_tx_start<<8, ETH_ALEN);
  413. eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
  414. /* bcc generates worse code without (const+const) below */
  415. eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
  416. eth_pio_write( (unsigned char *) p, (eth_tx_start<<8)+ETH_HLEN, s);
  417. s += ETH_HLEN;
  418. if (s < ETH_ZLEN) s = ETH_ZLEN;
  419. }
  420. #endif
  421. #if defined(INCLUDE_3C503)
  422. #endif
  423. #ifdef INCLUDE_WD
  424. if (eth_flags & FLAG_16BIT) {
  425. outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
  426. inb(0x84);
  427. }
  428. if (eth_flags & FLAG_790)
  429. outb(D8390_COMMAND_PS0 |
  430. D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  431. else
  432. #endif
  433. outb(D8390_COMMAND_PS0 |
  434. D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  435. outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
  436. outb(s, eth_nic_base+D8390_P0_TBCR0);
  437. outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
  438. #ifdef INCLUDE_WD
  439. if (eth_flags & FLAG_790)
  440. outb(D8390_COMMAND_PS0 |
  441. D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  442. else
  443. #endif
  444. outb(D8390_COMMAND_PS0 |
  445. D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
  446. D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
  447. }
  448. /**************************************************************************
  449. NS8390_POLL - Wait for a frame
  450. **************************************************************************/
  451. static int ns8390_poll(struct nic *nic, int retrieve)
  452. {
  453. int ret = 0;
  454. unsigned char rstat, curr, next;
  455. unsigned short len, frag;
  456. unsigned short pktoff;
  457. unsigned char *p;
  458. struct ringbuffer pkthdr;
  459. #ifndef INCLUDE_3C503
  460. /* avoid infinite recursion: see eth_rx_overrun() */
  461. if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
  462. eth_rx_overrun(nic);
  463. return(0);
  464. }
  465. #endif /* INCLUDE_3C503 */
  466. rstat = inb(eth_nic_base+D8390_P0_RSR);
  467. if (!(rstat & D8390_RSTAT_PRX)) return(0);
  468. next = inb(eth_nic_base+D8390_P0_BOUND)+1;
  469. if (next >= eth_memsize) next = eth_rx_start;
  470. outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
  471. curr = inb(eth_nic_base+D8390_P1_CURR);
  472. outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
  473. if (curr >= eth_memsize) curr=eth_rx_start;
  474. if (curr == next) return(0);
  475. if ( ! retrieve ) return 1;
  476. #ifdef INCLUDE_WD
  477. if (eth_flags & FLAG_16BIT) {
  478. outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
  479. inb(0x84);
  480. }
  481. #ifndef WD_790_PIO
  482. if (eth_flags & FLAG_790) {
  483. outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
  484. inb(0x84);
  485. }
  486. #endif
  487. inb(0x84);
  488. #endif
  489. pktoff = next << 8;
  490. if (eth_flags & FLAG_PIO)
  491. eth_pio_read(pktoff, (unsigned char *)&pkthdr, 4);
  492. else
  493. memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);
  494. pktoff += sizeof(pkthdr);
  495. /* incoming length includes FCS so must sub 4 */
  496. len = pkthdr.len - 4;
  497. if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
  498. || len > ETH_FRAME_LEN) {
  499. printf("Bogus packet, ignoring\n");
  500. return (0);
  501. }
  502. else {
  503. p = nic->packet;
  504. nic->packetlen = len; /* available to caller */
  505. frag = (eth_memsize << 8) - pktoff;
  506. if (len > frag) { /* We have a wrap-around */
  507. /* read first part */
  508. if (eth_flags & FLAG_PIO)
  509. eth_pio_read(pktoff, p, frag);
  510. else
  511. memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);
  512. pktoff = eth_rx_start << 8;
  513. p += frag;
  514. len -= frag;
  515. }
  516. /* read second part */
  517. if (eth_flags & FLAG_PIO)
  518. eth_pio_read(pktoff, p, len);
  519. else
  520. memcpy(p, bus_to_virt(eth_rmem + pktoff), len);
  521. ret = 1;
  522. }
  523. #ifdef INCLUDE_WD
  524. #ifndef WD_790_PIO
  525. if (eth_flags & FLAG_790) {
  526. outb(0, eth_asic_base + WD_MSR);
  527. inb(0x84);
  528. }
  529. #endif
  530. if (eth_flags & FLAG_16BIT) {
  531. outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
  532. inb(0x84);
  533. }
  534. inb(0x84);
  535. #endif
  536. next = pkthdr.next; /* frame number of next packet */
  537. if (next == eth_rx_start)
  538. next = eth_memsize;
  539. outb(next-1, eth_nic_base+D8390_P0_BOUND);
  540. return(ret);
  541. }
  542. /**************************************************************************
  543. NS8390_DISABLE - Turn off adapter
  544. **************************************************************************/
  545. static void ns8390_disable ( struct nic *nic ) {
  546. ns8390_reset(nic);
  547. }
  548. /**************************************************************************
  549. NS8390_IRQ - Enable, Disable, or Force interrupts
  550. **************************************************************************/
  551. static void ns8390_irq(struct nic *nic __unused, irq_action_t action __unused)
  552. {
  553. switch ( action ) {
  554. case DISABLE :
  555. break;
  556. case ENABLE :
  557. break;
  558. case FORCE :
  559. break;
  560. }
  561. }
  562. static struct nic_operations ns8390_operations;
  563. static struct nic_operations ns8390_operations = {
  564. .connect = dummy_connect,
  565. .poll = ns8390_poll,
  566. .transmit = ns8390_transmit,
  567. .irq = ns8390_irq,
  568. };
  569. /**************************************************************************
  570. ETH_PROBE - Look for an adapter
  571. **************************************************************************/
  572. #ifdef INCLUDE_NS8390
  573. static int eth_probe (struct nic *nic, struct pci_device *pci)
  574. #else
  575. static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)
  576. #endif
  577. {
  578. int i;
  579. #ifdef INCLUDE_NS8390
  580. unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };
  581. unsigned short *probe_addrs = pci_probe_addrs;
  582. #endif
  583. eth_vendor = VENDOR_NONE;
  584. eth_drain_receiver = 0;
  585. nic->irqno = 0;
  586. #ifdef INCLUDE_WD
  587. {
  588. /******************************************************************
  589. Search for WD/SMC cards
  590. ******************************************************************/
  591. struct wd_board *brd;
  592. unsigned short chksum;
  593. unsigned char c;
  594. for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
  595. eth_asic_base += 0x20) {
  596. chksum = 0;
  597. for (i=8; i<16; i++)
  598. chksum += inb(eth_asic_base+i);
  599. /* Extra checks to avoid soundcard */
  600. if ((chksum & 0xFF) == 0xFF &&
  601. inb(eth_asic_base+8) != 0xFF &&
  602. inb(eth_asic_base+9) != 0xFF)
  603. break;
  604. }
  605. if (eth_asic_base > WD_HIGH_BASE)
  606. return (0);
  607. /* We've found a board */
  608. eth_vendor = VENDOR_WD;
  609. eth_nic_base = eth_asic_base + WD_NIC_ADDR;
  610. nic->ioaddr = eth_nic_base;
  611. c = inb(eth_asic_base+WD_BID); /* Get board id */
  612. for (brd = wd_boards; brd->name; brd++)
  613. if (brd->id == c) break;
  614. if (!brd->name) {
  615. printf("Unknown WD/SMC NIC type %hhX\n", c);
  616. return (0); /* Unknown type */
  617. }
  618. eth_flags = brd->flags;
  619. eth_memsize = brd->memsize;
  620. eth_tx_start = 0;
  621. eth_rx_start = D8390_TXBUF_SIZE;
  622. if ((c == TYPE_WD8013EP) &&
  623. (inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
  624. eth_flags = FLAG_16BIT;
  625. eth_memsize = MEM_16384;
  626. }
  627. if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
  628. eth_bmem = (0x80000 |
  629. ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
  630. } else
  631. eth_bmem = WD_DEFAULT_MEM;
  632. if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
  633. /* from Linux driver, 8416BT detects as 8216 sometimes */
  634. unsigned int addr = inb(eth_asic_base + 0xb);
  635. if (((addr >> 4) & 3) == 0) {
  636. brd += 2;
  637. eth_memsize = brd->memsize;
  638. }
  639. }
  640. outb(0x80, eth_asic_base + WD_MSR); /* Reset */
  641. for (i=0; i<ETH_ALEN; i++) {
  642. nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
  643. }
  644. DBG ( "\n%s base %4.4x", brd->name, eth_asic_base );
  645. if (eth_flags & FLAG_790) {
  646. #ifdef WD_790_PIO
  647. DBG ( ", PIO mode, addr %s\n", eth_ntoa ( nic->node_addr ) );
  648. eth_bmem = 0;
  649. eth_flags |= FLAG_PIO; /* force PIO mode */
  650. outb(0, eth_asic_base+WD_MSR);
  651. #else
  652. DBG ( ", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
  653. outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
  654. outb((inb(eth_asic_base+0x04) |
  655. 0x80), eth_asic_base+0x04);
  656. outb(((unsigned)(eth_bmem >> 13) & 0x0F) |
  657. ((unsigned)(eth_bmem >> 11) & 0x40) |
  658. (inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
  659. outb((inb(eth_asic_base+0x04) &
  660. ~0x80), eth_asic_base+0x04);
  661. #endif
  662. } else {
  663. DBG (", Memory %x, MAC Addr %s\n", eth_bmem, eth_ntoa ( nic->node_addr) );
  664. outb(((unsigned)(eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
  665. }
  666. if (eth_flags & FLAG_16BIT) {
  667. if (eth_flags & FLAG_790) {
  668. eth_laar = inb(eth_asic_base + WD_LAAR);
  669. outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
  670. } else {
  671. outb((eth_laar =
  672. WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
  673. /*
  674. The previous line used to be
  675. WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
  676. jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
  677. it work for WD8013s. This seems to work for my 8013 boards. I
  678. don't know what is really happening. I wish I had data sheets
  679. or more time to decode the Linux driver. - Ken
  680. */
  681. }
  682. inb(0x84);
  683. }
  684. }
  685. #endif
  686. #ifdef INCLUDE_3C503
  687. #ifdef T503_AUI
  688. nic->flags = 1; /* aui */
  689. #else
  690. nic->flags = 0; /* no aui */
  691. #endif
  692. /******************************************************************
  693. Search for 3Com 3c503 if no WD/SMC cards
  694. ******************************************************************/
  695. if (eth_vendor == VENDOR_NONE) {
  696. int idx;
  697. int iobase_reg, membase_reg;
  698. static unsigned short base[] = {
  699. 0x300, 0x310, 0x330, 0x350,
  700. 0x250, 0x280, 0x2A0, 0x2E0, 0 };
  701. /* Loop through possible addresses checking each one */
  702. for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
  703. eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
  704. /*
  705. * Note that we use the same settings for both 8 and 16 bit cards:
  706. * both have an 8K bank of memory at page 1 while only the 16 bit
  707. * cards have a bank at page 0.
  708. */
  709. eth_memsize = MEM_16384;
  710. eth_tx_start = 32;
  711. eth_rx_start = 32 + D8390_TXBUF_SIZE;
  712. /* Check our base address. iobase and membase should */
  713. /* both have a maximum of 1 bit set or be 0. */
  714. iobase_reg = inb(eth_asic_base + _3COM_BCFR);
  715. membase_reg = inb(eth_asic_base + _3COM_PCFR);
  716. if ((iobase_reg & (iobase_reg - 1)) ||
  717. (membase_reg & (membase_reg - 1)))
  718. continue; /* nope */
  719. /* Now get the shared memory address */
  720. eth_flags = 0;
  721. switch (membase_reg) {
  722. case _3COM_PCFR_DC000:
  723. eth_bmem = 0xdc000;
  724. break;
  725. case _3COM_PCFR_D8000:
  726. eth_bmem = 0xd8000;
  727. break;
  728. case _3COM_PCFR_CC000:
  729. eth_bmem = 0xcc000;
  730. break;
  731. case _3COM_PCFR_C8000:
  732. eth_bmem = 0xc8000;
  733. break;
  734. case _3COM_PCFR_PIO:
  735. eth_flags |= FLAG_PIO;
  736. eth_bmem = 0;
  737. break;
  738. default:
  739. continue; /* nope */
  740. }
  741. break;
  742. }
  743. if (base[idx] == 0) /* not found */
  744. return (0);
  745. #ifndef T503_SHMEM
  746. eth_flags |= FLAG_PIO; /* force PIO mode */
  747. eth_bmem = 0;
  748. #endif
  749. eth_vendor = VENDOR_3COM;
  750. /* Need this to make ns8390_poll() happy. */
  751. eth_rmem = eth_bmem - 0x2000;
  752. /* Reset NIC and ASIC */
  753. outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
  754. outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
  755. /* Get our ethernet address */
  756. outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
  757. nic->ioaddr = eth_nic_base;
  758. DBG ( "\n3Com 3c503 base %4.4x, ", eth_nic_base );
  759. if (eth_flags & FLAG_PIO)
  760. DBG ( "PIO mode" );
  761. else
  762. DBG ( "memory %4.4x", eth_bmem );
  763. for (i=0; i<ETH_ALEN; i++) {
  764. nic->node_addr[i] = inb(eth_nic_base+i);
  765. }
  766. DBG ( ", %s, MAC Addr %s\n", nic->flags ? "AUI" : "internal xcvr",
  767. eth_ntoa ( nic->node_addr ) );
  768. outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
  769. /*
  770. * Initialize GA configuration register. Set bank and enable shared
  771. * mem. We always use bank 1. Disable interrupts.
  772. */
  773. outb(_3COM_GACFR_RSEL |
  774. _3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
  775. outb(0xff, eth_asic_base + _3COM_VPTR2);
  776. outb(0xff, eth_asic_base + _3COM_VPTR1);
  777. outb(0x00, eth_asic_base + _3COM_VPTR0);
  778. /*
  779. * Clear memory and verify that it worked (we use only 8K)
  780. */
  781. if (!(eth_flags & FLAG_PIO)) {
  782. memset(bus_to_virt(eth_bmem), 0, 0x2000);
  783. for(i = 0; i < 0x2000; ++i)
  784. if (*((char *)(bus_to_virt(eth_bmem+i)))) {
  785. printf ("Failed to clear 3c503 shared mem.\n");
  786. return (0);
  787. }
  788. }
  789. /*
  790. * Initialize GA page/start/stop registers.
  791. */
  792. outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
  793. outb(eth_memsize, eth_asic_base + _3COM_PSPR);
  794. }
  795. #endif
  796. #if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
  797. {
  798. /******************************************************************
  799. Search for NE1000/2000 if no WD/SMC or 3com cards
  800. ******************************************************************/
  801. unsigned char c;
  802. if (eth_vendor == VENDOR_NONE) {
  803. unsigned char romdata[16];
  804. unsigned char testbuf[32];
  805. int idx;
  806. static unsigned char test[] = "NE*000 memory";
  807. static unsigned short base[] = {
  808. #ifdef NE_SCAN
  809. NE_SCAN,
  810. #endif
  811. 0 };
  812. /* if no addresses supplied, fall back on defaults */
  813. if (probe_addrs == NULL || probe_addrs[0] == 0)
  814. probe_addrs = base;
  815. eth_bmem = 0; /* No shared memory */
  816. for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
  817. eth_flags = FLAG_PIO;
  818. eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
  819. eth_memsize = MEM_16384;
  820. eth_tx_start = 32;
  821. eth_rx_start = 32 + D8390_TXBUF_SIZE;
  822. c = inb(eth_asic_base + NE_RESET);
  823. outb(c, eth_asic_base + NE_RESET);
  824. (void) inb(0x84);
  825. outb(D8390_COMMAND_STP |
  826. D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
  827. outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
  828. outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
  829. outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
  830. outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
  831. #ifdef NS8390_FORCE_16BIT
  832. eth_flags |= FLAG_16BIT; /* force 16-bit mode */
  833. #endif
  834. eth_pio_write( (unsigned char *) test, 8192, sizeof(test));
  835. eth_pio_read(8192, testbuf, sizeof(test));
  836. if (!memcmp(test, testbuf, sizeof(test)))
  837. break;
  838. eth_flags |= FLAG_16BIT;
  839. eth_memsize = MEM_32768;
  840. eth_tx_start = 64;
  841. eth_rx_start = 64 + D8390_TXBUF_SIZE;
  842. outb(D8390_DCR_WTS |
  843. D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
  844. outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
  845. outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
  846. eth_pio_write( (unsigned char *) test, 16384, sizeof(test));
  847. eth_pio_read(16384, testbuf, sizeof(test));
  848. if (!memcmp(testbuf, test, sizeof(test)))
  849. break;
  850. }
  851. if (eth_nic_base == 0)
  852. return (0);
  853. if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
  854. eth_flags |= FLAG_16BIT;
  855. eth_vendor = VENDOR_NOVELL;
  856. eth_pio_read(0, romdata, sizeof(romdata));
  857. for (i=0; i<ETH_ALEN; i++) {
  858. nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
  859. }
  860. nic->ioaddr = eth_nic_base;
  861. DBG ( "\nNE%c000 base %4.4x, MAC Addr %s\n",
  862. (eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
  863. eth_ntoa ( nic->node_addr ) );
  864. }
  865. }
  866. #endif
  867. if (eth_vendor == VENDOR_NONE)
  868. return(0);
  869. if (eth_vendor != VENDOR_3COM)
  870. eth_rmem = eth_bmem;
  871. ns8390_reset(nic);
  872. nic->nic_op = &ns8390_operations;
  873. /* Based on PnP ISA map */
  874. #ifdef INCLUDE_WD
  875. dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
  876. dev->devid.device_id = htons(0x812a);
  877. #endif
  878. #ifdef INCLUDE_3C503
  879. dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
  880. dev->devid.device_id = htons(0x80f3);
  881. #endif
  882. #ifdef INCLUDE_NE
  883. dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
  884. dev->devid.device_id = htons(0x80d6);
  885. #endif
  886. return 1;
  887. }
  888. #ifdef INCLUDE_WD
  889. struct isa_driver wd_driver __isa_driver = {
  890. .type = NIC_DRIVER,
  891. .name = "WD",
  892. .probe = wd_probe,
  893. .ioaddrs = 0,
  894. };
  895. ISA_ROM("wd","WD8003/8013, SMC8216/8416, SMC 83c790 (EtherEZ)");
  896. #endif
  897. #ifdef INCLUDE_3C503
  898. struct isa_driver t503_driver __isa_driver = {
  899. .type = NIC_DRIVER,
  900. .name = "3C503",
  901. .probe = t503_probe,
  902. .ioaddrs = 0,
  903. };
  904. ISA_ROM("3c503","3Com503, Etherlink II[/16]");
  905. #endif
  906. #ifdef INCLUDE_NE
  907. struct isa_driver ne_driver __isa_driver = {
  908. .type = NIC_DRIVER,
  909. .name = "NE*000",
  910. .probe = ne_probe,
  911. .ioaddrs = 0,
  912. };
  913. ISA_ROM("ne","NE1000/2000 and clones");
  914. #endif
  915. #ifdef INCLUDE_NS8390
  916. static struct pci_device_id nepci_nics[] = {
  917. /* A few NE2000 PCI clones, list not exhaustive */
  918. PCI_ROM(0x10ec, 0x8029, "rtl8029", "Realtek 8029", 0),
  919. PCI_ROM(0x1186, 0x0300, "dlink-528", "D-Link DE-528", 0),
  920. PCI_ROM(0x1050, 0x0940, "winbond940", "Winbond NE2000-PCI", 0), /* Winbond 86C940 / 89C940 */
  921. PCI_ROM(0x1050, 0x5a5a, "winbond940f", "Winbond W89c940F", 0), /* Winbond 89C940F */
  922. PCI_ROM(0x11f6, 0x1401, "compexrl2000", "Compex ReadyLink 2000", 0),
  923. PCI_ROM(0x8e2e, 0x3000, "ktiet32p2", "KTI ET32P2", 0),
  924. PCI_ROM(0x4a14, 0x5000, "nv5000sc", "NetVin NV5000SC", 0),
  925. PCI_ROM(0x12c3, 0x0058, "holtek80232", "Holtek HT80232", 0),
  926. PCI_ROM(0x12c3, 0x5598, "holtek80229", "Holtek HT80229", 0),
  927. PCI_ROM(0x10bd, 0x0e34, "surecom-ne34", "Surecom NE34", 0),
  928. PCI_ROM(0x1106, 0x0926, "via86c926", "Via 86c926", 0),
  929. };
  930. PCI_DRIVER ( nepci_driver, nepci_nics, PCI_NO_CLASS );
  931. DRIVER ( "NE2000/PCI", nic_driver, pci_driver, nepci_driver,
  932. nepci_probe, ns8390_disable );
  933. #endif /* INCLUDE_NS8390 */
  934. #endif
  935. /*
  936. * Local variables:
  937. * c-basic-offset: 8
  938. * c-indent-level: 8
  939. * tab-width: 8
  940. * End:
  941. */