ni5010.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /**************************************************************************
  2. Etherboot - BOOTP/TFTP Bootstrap Program
  3. Driver for NI5010.
  4. Code freely taken from Jan-Pascal van Best and Andreas Mohr's
  5. Linux NI5010 driver.
  6. ***************************************************************************/
  7. /*
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2, or (at
  11. * your option) any later version.
  12. */
  13. /* to get some global routines like printf */
  14. #include "etherboot.h"
  15. /* to get the interface to the body of the program */
  16. #include "nic.h"
  17. /* to get our own prototype */
  18. #include "cards.h"
  19. /* ni5010.h file included verbatim */
  20. /*
  21. * Racal-Interlan ni5010 Ethernet definitions
  22. *
  23. * This is an extension to the Linux operating system, and is covered by the
  24. * same Gnu Public License that covers that work.
  25. *
  26. * copyrights (c) 1996 by Jan-Pascal van Best (jvbest@wi.leidenuniv.nl)
  27. *
  28. * I have done a look in the following sources:
  29. * crynwr-packet-driver by Russ Nelson
  30. */
  31. #define NI5010_BUFSIZE 2048 /* number of bytes in a buffer */
  32. #define NI5010_MAGICVAL0 0x00 /* magic-values for ni5010 card */
  33. #define NI5010_MAGICVAL1 0x55
  34. #define NI5010_MAGICVAL2 0xAA
  35. #define SA_ADDR0 0x02
  36. #define SA_ADDR1 0x07
  37. #define SA_ADDR2 0x01
  38. /* The number of low I/O ports used by the ni5010 ethercard. */
  39. #define NI5010_IO_EXTENT 32
  40. #define PRINTK(x) if (NI5010_DEBUG) printk x
  41. #define PRINTK2(x) if (NI5010_DEBUG>=2) printk x
  42. #define PRINTK3(x) if (NI5010_DEBUG>=3) printk x
  43. /* The various IE command registers */
  44. #define EDLC_XSTAT (ioaddr + 0x00) /* EDLC transmit csr */
  45. #define EDLC_XCLR (ioaddr + 0x00) /* EDLC transmit "Clear IRQ" */
  46. #define EDLC_XMASK (ioaddr + 0x01) /* EDLC transmit "IRQ Masks" */
  47. #define EDLC_RSTAT (ioaddr + 0x02) /* EDLC receive csr */
  48. #define EDLC_RCLR (ioaddr + 0x02) /* EDLC receive "Clear IRQ" */
  49. #define EDLC_RMASK (ioaddr + 0x03) /* EDLC receive "IRQ Masks" */
  50. #define EDLC_XMODE (ioaddr + 0x04) /* EDLC transmit Mode */
  51. #define EDLC_RMODE (ioaddr + 0x05) /* EDLC receive Mode */
  52. #define EDLC_RESET (ioaddr + 0x06) /* EDLC RESET register */
  53. #define EDLC_TDR1 (ioaddr + 0x07) /* "Time Domain Reflectometry" reg1 */
  54. #define EDLC_ADDR (ioaddr + 0x08) /* EDLC station address, 6 bytes */
  55. /* 0x0E doesn't exist for r/w */
  56. #define EDLC_TDR2 (ioaddr + 0x0f) /* "Time Domain Reflectometry" reg2 */
  57. #define IE_GP (ioaddr + 0x10) /* GP pointer (word register) */
  58. /* 0x11 is 2nd byte of GP Pointer */
  59. #define IE_RCNT (ioaddr + 0x10) /* Count of bytes in rcv'd packet */
  60. /* 0x11 is 2nd byte of "Byte Count" */
  61. #define IE_MMODE (ioaddr + 0x12) /* Memory Mode register */
  62. #define IE_DMA_RST (ioaddr + 0x13) /* IE DMA Reset. write only */
  63. #define IE_ISTAT (ioaddr + 0x13) /* IE Interrupt Status. read only */
  64. #define IE_RBUF (ioaddr + 0x14) /* IE Receive Buffer port */
  65. #define IE_XBUF (ioaddr + 0x15) /* IE Transmit Buffer port */
  66. #define IE_SAPROM (ioaddr + 0x16) /* window on station addr prom */
  67. #define IE_RESET (ioaddr + 0x17) /* any write causes Board Reset */
  68. /* bits in EDLC_XSTAT, interrupt clear on write, status when read */
  69. #define XS_TPOK 0x80 /* transmit packet successful */
  70. #define XS_CS 0x40 /* carrier sense */
  71. #define XS_RCVD 0x20 /* transmitted packet received */
  72. #define XS_SHORT 0x10 /* transmission media is shorted */
  73. #define XS_UFLW 0x08 /* underflow. iff failed board */
  74. #define XS_COLL 0x04 /* collision occurred */
  75. #define XS_16COLL 0x02 /* 16th collision occurred */
  76. #define XS_PERR 0x01 /* parity error */
  77. #define XS_CLR_UFLW 0x08 /* clear underflow */
  78. #define XS_CLR_COLL 0x04 /* clear collision */
  79. #define XS_CLR_16COLL 0x02 /* clear 16th collision */
  80. #define XS_CLR_PERR 0x01 /* clear parity error */
  81. /* bits in EDLC_XMASK, mask/enable transmit interrupts. register is r/w */
  82. #define XM_TPOK 0x80 /* =1 to enable Xmt Pkt OK interrupts */
  83. #define XM_RCVD 0x20 /* =1 to enable Xmt Pkt Rcvd ints */
  84. #define XM_UFLW 0x08 /* =1 to enable Xmt Underflow ints */
  85. #define XM_COLL 0x04 /* =1 to enable Xmt Collision ints */
  86. #define XM_COLL16 0x02 /* =1 to enable Xmt 16th Coll ints */
  87. #define XM_PERR 0x01 /* =1 to enable Xmt Parity Error ints */
  88. /* note: always clear this bit */
  89. #define XM_ALL (XM_TPOK | XM_RCVD | XM_UFLW | XM_COLL | XM_COLL16)
  90. /* bits in EDLC_RSTAT, interrupt clear on write, status when read */
  91. #define RS_PKT_OK 0x80 /* received good packet */
  92. #define RS_RST_PKT 0x10 /* RESET packet received */
  93. #define RS_RUNT 0x08 /* Runt Pkt rcvd. Len < 64 Bytes */
  94. #define RS_ALIGN 0x04 /* Alignment error. not 8 bit aligned */
  95. #define RS_CRC_ERR 0x02 /* Bad CRC on rcvd pkt */
  96. #define RS_OFLW 0x01 /* overflow for rcv FIFO */
  97. #define RS_VALID_BITS ( RS_PKT_OK | RS_RST_PKT | RS_RUNT | RS_ALIGN | RS_CRC_ERR | RS_OFLW )
  98. /* all valid RSTAT bits */
  99. #define RS_CLR_PKT_OK 0x80 /* clear rcvd packet interrupt */
  100. #define RS_CLR_RST_PKT 0x10 /* clear RESET packet received */
  101. #define RS_CLR_RUNT 0x08 /* clear Runt Pckt received */
  102. #define RS_CLR_ALIGN 0x04 /* clear Alignment error */
  103. #define RS_CLR_CRC_ERR 0x02 /* clear CRC error */
  104. #define RS_CLR_OFLW 0x01 /* clear rcv FIFO Overflow */
  105. /* bits in EDLC_RMASK, mask/enable receive interrupts. register is r/w */
  106. #define RM_PKT_OK 0x80 /* =1 to enable rcvd good packet ints */
  107. #define RM_RST_PKT 0x10 /* =1 to enable RESET packet ints */
  108. #define RM_RUNT 0x08 /* =1 to enable Runt Pkt rcvd ints */
  109. #define RM_ALIGN 0x04 /* =1 to enable Alignment error ints */
  110. #define RM_CRC_ERR 0x02 /* =1 to enable Bad CRC error ints */
  111. #define RM_OFLW 0x01 /* =1 to enable overflow error ints */
  112. /* bits in EDLC_RMODE, set Receive Packet mode. register is r/w */
  113. #define RMD_TEST 0x80 /* =1 for Chip testing. normally 0 */
  114. #define RMD_ADD_SIZ 0x10 /* =1 5-byte addr match. normally 0 */
  115. #define RMD_EN_RUNT 0x08 /* =1 enable runt rcv. normally 0 */
  116. #define RMD_EN_RST 0x04 /* =1 to rcv RESET pkt. normally 0 */
  117. #define RMD_PROMISC 0x03 /* receive *all* packets. unusual */
  118. #define RMD_MULTICAST 0x02 /* receive multicasts too. unusual */
  119. #define RMD_BROADCAST 0x01 /* receive broadcasts & normal. usual */
  120. #define RMD_NO_PACKETS 0x00 /* don't receive any packets. unusual */
  121. /* bits in EDLC_XMODE, set Transmit Packet mode. register is r/w */
  122. #define XMD_COLL_CNT 0xf0 /* coll's since success. read-only */
  123. #define XMD_IG_PAR 0x08 /* =1 to ignore parity. ALWAYS set */
  124. #define XMD_T_MODE 0x04 /* =1 to power xcvr. ALWAYS set this */
  125. #define XMD_LBC 0x02 /* =1 for loopback. normally set */
  126. #define XMD_DIS_C 0x01 /* =1 disables contention. normally 0 */
  127. /* bits in EDLC_RESET, write only */
  128. #define RS_RESET 0x80 /* =1 to hold EDLC in reset state */
  129. /* bits in IE_MMODE, write only */
  130. #define MM_EN_DMA 0x80 /* =1 begin DMA xfer, Cplt clrs it */
  131. #define MM_EN_RCV 0x40 /* =1 allows Pkt rcv. clr'd by rcv */
  132. #define MM_EN_XMT 0x20 /* =1 begin Xmt pkt. Cplt clrs it */
  133. #define MM_BUS_PAGE 0x18 /* =00 ALWAYS. Used when MUX=1 */
  134. #define MM_NET_PAGE 0x06 /* =00 ALWAYS. Used when MUX=0 */
  135. #define MM_MUX 0x01 /* =1 means Rcv Buff on system bus */
  136. /* =0 means Xmt Buff on system bus */
  137. /* bits in IE_ISTAT, read only */
  138. #define IS_TDIAG 0x80 /* =1 if Diagnostic problem */
  139. #define IS_EN_RCV 0x20 /* =1 until frame is rcv'd cplt */
  140. #define IS_EN_XMT 0x10 /* =1 until frame is xmt'd cplt */
  141. #define IS_EN_DMA 0x08 /* =1 until DMA is cplt or aborted */
  142. #define IS_DMA_INT 0x04 /* =0 iff DMA done interrupt. */
  143. #define IS_R_INT 0x02 /* =0 iff unmasked Rcv interrupt */
  144. #define IS_X_INT 0x01 /* =0 iff unmasked Xmt interrupt */
  145. /* NIC specific static variables go here */
  146. static unsigned short ioaddr = 0;
  147. static unsigned int bufsize_rcv = 0;
  148. #if 0
  149. static void show_registers(void)
  150. {
  151. printf("XSTAT %hhX ", inb(EDLC_XSTAT));
  152. printf("XMASK %hhX ", inb(EDLC_XMASK));
  153. printf("RSTAT %hhX ", inb(EDLC_RSTAT));
  154. printf("RMASK %hhX ", inb(EDLC_RMASK));
  155. printf("RMODE %hhX ", inb(EDLC_RMODE));
  156. printf("XMODE %hhX ", inb(EDLC_XMODE));
  157. printf("ISTAT %hhX\n", inb(IE_ISTAT));
  158. }
  159. #endif
  160. static void reset_receiver(void)
  161. {
  162. outw(0, IE_GP); /* Receive packet at start of buffer */
  163. outb(RS_VALID_BITS, EDLC_RCLR); /* Clear all pending Rcv interrupts */
  164. outb(MM_EN_RCV, IE_MMODE); /* Enable rcv */
  165. }
  166. /**************************************************************************
  167. RESET - Reset adapter
  168. ***************************************************************************/
  169. static void ni5010_reset(struct nic *nic)
  170. {
  171. int i;
  172. /* Reset the hardware here. Don't forget to set the station address. */
  173. outb(RS_RESET, EDLC_RESET); /* Hold up EDLC_RESET while configing board */
  174. outb(0, IE_RESET); /* Hardware reset of ni5010 board */
  175. outb(0, EDLC_XMASK); /* Disable all Xmt interrupts */
  176. outb(0, EDLC_RMASK); /* Disable all Rcv interrupt */
  177. outb(0xFF, EDLC_XCLR); /* Clear all pending Xmt interrupts */
  178. outb(0xFF, EDLC_RCLR); /* Clear all pending Rcv interrupts */
  179. outb(XMD_LBC, EDLC_XMODE); /* Only loopback xmits */
  180. /* Set the station address */
  181. for(i = 0; i < ETH_ALEN; i++)
  182. outb(nic->node_addr[i], EDLC_ADDR + i);
  183. outb(XMD_IG_PAR | XMD_T_MODE | XMD_LBC, EDLC_XMODE);
  184. /* Normal packet xmit mode */
  185. outb(RMD_BROADCAST, EDLC_RMODE);
  186. /* Receive broadcast and normal packets */
  187. reset_receiver();
  188. outb(0x00, EDLC_RESET); /* Un-reset the ni5010 */
  189. }
  190. /**************************************************************************
  191. POLL - Wait for a frame
  192. ***************************************************************************/
  193. static int ni5010_poll(struct nic *nic)
  194. {
  195. int rcv_stat;
  196. if (((rcv_stat = inb(EDLC_RSTAT)) & RS_VALID_BITS) != RS_PKT_OK) {
  197. outb(rcv_stat, EDLC_RSTAT); /* Clear the status */
  198. return (0);
  199. }
  200. outb(rcv_stat, EDLC_RCLR); /* Clear the status */
  201. nic->packetlen = inw(IE_RCNT);
  202. /* Read packet into buffer */
  203. outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */
  204. outw(0, IE_GP); /* Seek to beginning of packet */
  205. insb(IE_RBUF, nic->packet, nic->packetlen);
  206. return (1);
  207. }
  208. /**************************************************************************
  209. TRANSMIT - Transmit a frame
  210. ***************************************************************************/
  211. static void ni5010_transmit(struct nic *nic,
  212. const char *d, /* Destination */
  213. unsigned int t, /* Type */
  214. unsigned int s, /* size */
  215. const char *p) /* Packet */
  216. {
  217. unsigned int len;
  218. int buf_offs, xmt_stat;
  219. unsigned long time;
  220. len = s + ETH_HLEN;
  221. if (len < ETH_ZLEN)
  222. len = ETH_ZLEN;
  223. buf_offs = NI5010_BUFSIZE - len;
  224. outb(0, EDLC_RMASK); /* Mask all receive interrupts */
  225. outb(0, IE_MMODE); /* Put Xmit buffer on system bus */
  226. outb(0xFF, EDLC_RCLR); /* Clear out pending rcv interrupts */
  227. outw(buf_offs, IE_GP); /* Point GP at start of packet */
  228. outsb(IE_XBUF, d, ETH_ALEN); /* Put dst in buffer */
  229. outsb(IE_XBUF, nic->node_addr, ETH_ALEN);/* Put src in buffer */
  230. outb(t >> 8, IE_XBUF);
  231. outb(t, IE_XBUF);
  232. outsb(IE_XBUF, p, s); /* Put data in buffer */
  233. while (s++ < ETH_ZLEN - ETH_HLEN) /* Pad to min size */
  234. outb(0, IE_XBUF);
  235. outw(buf_offs, IE_GP); /* Rewrite where packet starts */
  236. /* should work without that outb() (Crynwr used it) */
  237. /*outb(MM_MUX, IE_MMODE);*/
  238. /* Xmt buffer to EDLC bus */
  239. outb(MM_EN_XMT | MM_MUX, IE_MMODE); /* Begin transmission */
  240. /* wait for transmit complete */
  241. while (((xmt_stat = inb(IE_ISTAT)) & IS_EN_XMT) != 0)
  242. ;
  243. reset_receiver(); /* Immediately switch to receive */
  244. }
  245. /**************************************************************************
  246. DISABLE - Turn off ethernet interface
  247. ***************************************************************************/
  248. static void ni5010_disable(struct nic *nic)
  249. {
  250. outb(0, IE_MMODE);
  251. outb(RS_RESET, EDLC_RESET);
  252. }
  253. static inline int rd_port(void)
  254. {
  255. inb(IE_RBUF);
  256. return inb(IE_SAPROM);
  257. }
  258. static int ni5010_probe1(struct nic *nic)
  259. {
  260. int i, boguscount = 40, data;
  261. /* The tests are from the Linux NI5010 driver
  262. I don't understand it all, but if it works for them... */
  263. if (inb(ioaddr) == 0xFF)
  264. return (0);
  265. while ((rd_port() & rd_port() & rd_port()
  266. & rd_port() & rd_port() & rd_port()) != 0xFF)
  267. {
  268. if (boguscount-- <= 0)
  269. return (0);
  270. }
  271. for (i = 0; i < 32; i++)
  272. if ((data = rd_port()) != 0xFF)
  273. break;
  274. if (data == 0xFF)
  275. return (0);
  276. if (data == SA_ADDR0 && rd_port() == SA_ADDR1 && rd_port() == SA_ADDR2) {
  277. for (i = 0; i < 4; i++)
  278. rd_port();
  279. if (rd_port() != NI5010_MAGICVAL1 || rd_port() != NI5010_MAGICVAL2)
  280. return (0);
  281. } else
  282. return (0);
  283. for (i = 0; i < ETH_ALEN; i++) {
  284. outw(i, IE_GP);
  285. nic->node_addr[i] = inb(IE_SAPROM);
  286. }
  287. printf("\nNI5010 ioaddr %#hX, addr %!\n", ioaddr, nic->node_addr);
  288. /* get the size of the onboard receive buffer
  289. * higher addresses than bufsize are wrapped into real buffer
  290. * i.e. data for offs. 0x801 is written to 0x1 with a 2K onboard buffer
  291. */
  292. if (bufsize_rcv == 0) {
  293. outb(1, IE_MMODE); /* Put Rcv buffer on system bus */
  294. outw(0, IE_GP); /* Point GP at start of packet */
  295. outb(0, IE_RBUF); /* set buffer byte 0 to 0 */
  296. for (i = 1; i < 0xFF; i++) {
  297. outw(i << 8, IE_GP); /* Point GP at packet size to be tested */
  298. outb(i, IE_RBUF);
  299. outw(0x0, IE_GP); /* Point GP at start of packet */
  300. data = inb(IE_RBUF);
  301. if (data == i) break;
  302. }
  303. bufsize_rcv = i << 8;
  304. outw(0, IE_GP); /* Point GP at start of packet */
  305. outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */
  306. }
  307. printf("Bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
  308. return (1);
  309. }
  310. /**************************************************************************
  311. PROBE - Look for an adapter, this routine's visible to the outside
  312. ***************************************************************************/
  313. struct nic *ni5010_probe(struct nic *nic, unsigned short *probe_addrs)
  314. {
  315. static unsigned short io_addrs[] = {
  316. 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0 };
  317. unsigned short *p;
  318. /* if probe_addrs is 0, then use list above */
  319. if (probe_addrs == 0 || *probe_addrs == 0)
  320. probe_addrs = io_addrs;
  321. for (p = probe_addrs; (ioaddr = *p) != 0; p++) {
  322. if (ni5010_probe1(nic))
  323. break;
  324. }
  325. if (ioaddr == 0)
  326. return (0);
  327. ni5010_reset(nic);
  328. /* point to NIC specific routines */
  329. nic->reset = ni5010_reset;
  330. nic->poll = ni5010_poll;
  331. nic->transmit = ni5010_transmit;
  332. nic->disable = ni5010_disable;
  333. return (nic);
  334. }