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.

ns8390.c 31KB

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