otulip.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. Etherboot DEC Tulip driver
  3. adapted by Ken Yap from
  4. FreeBSD netboot DEC 21143 driver
  5. Author: David Sharp
  6. date: Nov/98
  7. Known to work on DEC DE500 using 21143-PC chipset.
  8. Even on cards with the same chipset there can be
  9. incompatablity problems with the way media selection
  10. and status LED settings are done. See comments below.
  11. Some code fragments were taken from verious places,
  12. Ken Yap's etherboot, FreeBSD's if_de.c, and various
  13. Linux related files. DEC's manuals for the 21143 and
  14. SROM format were very helpful. The Linux de driver
  15. development page has a number of links to useful
  16. related information. Have a look at:
  17. ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
  18. */
  19. #include "etherboot.h"
  20. #include "nic.h"
  21. #include "pci.h"
  22. #include "cards.h"
  23. #include "otulip.h"
  24. static unsigned short vendor, dev_id;
  25. static unsigned short ioaddr;
  26. static unsigned int *membase;
  27. static unsigned char srom[1024];
  28. #define BUFLEN 1536 /* must be longword divisable */
  29. /* buffers must be longword aligned */
  30. /* transmit descriptor and buffer */
  31. static struct txdesc txd;
  32. /* receive descriptor(s) and buffer(s) */
  33. #define NRXD 4
  34. static struct rxdesc rxd[NRXD];
  35. static int rxd_tail = 0;
  36. #ifdef USE_LOWMEM_BUFFER
  37. #define rxb ((char *)0x10000 - NRXD * BUFLEN)
  38. #define txb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)
  39. #else
  40. static unsigned char rxb[NRXD * BUFLEN];
  41. static unsigned char txb[BUFLEN];
  42. #endif
  43. static unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */
  44. enum tulip_offsets {
  45. CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
  46. CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
  47. CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 };
  48. /***************************************************************************/
  49. /* 21143 specific stuff */
  50. /***************************************************************************/
  51. /* XXX assume 33MHz PCI bus, this is not very accurate and should be
  52. used only with gross over estimations of required delay times unless
  53. you tune UADJUST to your specific processor and I/O subsystem */
  54. #define UADJUST 870
  55. static void udelay(unsigned long usec) {
  56. unsigned long i;
  57. for (i=((usec*UADJUST)/33)+1; i>0; i--) (void) TULIP_CSR_READ(csr_0);
  58. }
  59. /* The following srom related code was taken from FreeBSD's if_de.c */
  60. /* with minor alterations to make it work here. the Linux code is */
  61. /* better but this was easier to use */
  62. static void delay_300ns(void)
  63. {
  64. int idx;
  65. for (idx = (300 / 33) + 1; idx > 0; idx--)
  66. (void) TULIP_CSR_READ(csr_busmode);
  67. }
  68. #define EMIT do { TULIP_CSR_WRITE(csr_srom_mii, csr); delay_300ns(); } while (0)
  69. static void srom_idle(void)
  70. {
  71. unsigned bit, csr;
  72. csr = SROMSEL ; EMIT;
  73. csr = SROMSEL | SROMRD; EMIT;
  74. csr ^= SROMCS; EMIT;
  75. csr ^= SROMCLKON; EMIT;
  76. /*
  77. * Write 25 cycles of 0 which will force the SROM to be idle.
  78. */
  79. for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
  80. csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
  81. csr ^= SROMCLKON; EMIT; /* clock high; data valid */
  82. }
  83. csr ^= SROMCLKOFF; EMIT;
  84. csr ^= SROMCS; EMIT;
  85. csr = 0; EMIT;
  86. }
  87. static void srom_read(void)
  88. {
  89. unsigned idx;
  90. const unsigned bitwidth = SROM_BITWIDTH;
  91. const unsigned cmdmask = (SROMCMD_RD << bitwidth);
  92. const unsigned msb = 1 << (bitwidth + 3 - 1);
  93. unsigned lastidx = (1 << bitwidth) - 1;
  94. srom_idle();
  95. for (idx = 0; idx <= lastidx; idx++) {
  96. unsigned lastbit, data, bits, bit, csr;
  97. csr = SROMSEL ; EMIT;
  98. csr = SROMSEL | SROMRD; EMIT;
  99. csr ^= SROMCSON; EMIT;
  100. csr ^= SROMCLKON; EMIT;
  101. lastbit = 0;
  102. for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1)
  103. {
  104. const unsigned thisbit = bits & msb;
  105. csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
  106. if (thisbit != lastbit) {
  107. csr ^= SROMDOUT; EMIT; /* clock low; invert data */
  108. } else {
  109. EMIT;
  110. }
  111. csr ^= SROMCLKON; EMIT; /* clock high; data valid */
  112. lastbit = thisbit;
  113. }
  114. csr ^= SROMCLKOFF; EMIT;
  115. for (data = 0, bits = 0; bits < 16; bits++) {
  116. data <<= 1;
  117. csr ^= SROMCLKON; EMIT; /* clock high; data valid */
  118. data |= TULIP_CSR_READ(csr_srom_mii) & SROMDIN ? 1 : 0;
  119. csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
  120. }
  121. srom[idx*2] = data & 0xFF;
  122. srom[idx*2+1] = data >> 8;
  123. csr = SROMSEL | SROMRD; EMIT;
  124. csr = 0; EMIT;
  125. }
  126. srom_idle();
  127. }
  128. /**************************************************************************
  129. ETH_RESET - Reset adapter
  130. ***************************************************************************/
  131. static void tulip_reset(struct nic *nic)
  132. {
  133. int x,cnt=2;
  134. outl(0x00000001, ioaddr + CSR0);
  135. udelay(1000);
  136. /* turn off reset and set cache align=16lword, burst=unlimit */
  137. outl(0x01A08000, ioaddr + CSR0);
  138. /* for some reason the media selection does not take
  139. the first time se it is repeated. */
  140. while(cnt--) {
  141. /* stop TX,RX processes */
  142. if (cnt == 1)
  143. outl(0x32404000, ioaddr + CSR6);
  144. else
  145. outl(0x32000040, ioaddr + CSR6);
  146. /* XXX - media selection is vendor specific and hard coded right
  147. here. This should be fixed to use the hints in the SROM and
  148. allow media selection by the user at runtime. MII support
  149. should also be added. Support for chips other than the
  150. 21143 should be added here as well */
  151. /* start set to 10Mbps half-duplex */
  152. /* setup SIA */
  153. outl(0x0, ioaddr + CSR13); /* reset SIA */
  154. outl(0x7f3f, ioaddr + CSR14);
  155. outl(0x8000008, ioaddr + CSR15);
  156. outl(0x0, ioaddr + CSR13);
  157. outl(0x1, ioaddr + CSR13);
  158. outl(0x2404000, ioaddr + CSR6);
  159. /* initalize GP */
  160. outl(0x8af0008, ioaddr + CSR15);
  161. outl(0x50008, ioaddr + CSR15);
  162. /* end set to 10Mbps half-duplex */
  163. if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
  164. /* do stuff for MX98715 */
  165. outl(0x01a80000, ioaddr + CSR6);
  166. outl(0xFFFFFFFF, ioaddr + CSR14);
  167. outl(0x00001000, ioaddr + CSR12);
  168. }
  169. outl(0x0, ioaddr + CSR7); /* disable interrupts */
  170. /* construct setup packet which is used by the 21143 to
  171. program its CAM to recognize interesting MAC addresses */
  172. memset(&txd, 0, sizeof(struct txdesc));
  173. txd.buf1addr = &txb[0];
  174. txd.buf2addr = &txb[0]; /* just in case */
  175. txd.buf1sz = 192; /* setup packet must be 192 bytes */
  176. txd.buf2sz = 0;
  177. txd.control = 0x020; /* setup packet */
  178. txd.status = 0x80000000; /* give ownership to 21143 */
  179. /* construct perfect filter frame */
  180. /* with mac address as first match */
  181. /* and broadcast address for all others */
  182. for(x=0;x<192;x++) txb[x] = 0xff;
  183. txb[0] = nic->node_addr[0];
  184. txb[1] = nic->node_addr[1];
  185. txb[4] = nic->node_addr[2];
  186. txb[5] = nic->node_addr[3];
  187. txb[8] = nic->node_addr[4];
  188. txb[9] = nic->node_addr[5];
  189. outl((unsigned long)&txd, ioaddr + CSR4); /* set xmit buf */
  190. outl(0x2406000, ioaddr + CSR6); /* start transmiter */
  191. udelay(50000); /* wait for the setup packet to be processed */
  192. }
  193. /* setup receive descriptor */
  194. {
  195. int x;
  196. for(x=0;x<NRXD;x++) {
  197. memset(&rxd[x], 0, sizeof(struct rxdesc));
  198. rxd[x].buf1addr = &rxb[x * BUFLEN];
  199. rxd[x].buf2addr = 0; /* not used */
  200. rxd[x].buf1sz = BUFLEN;
  201. rxd[x].buf2sz = 0; /* not used */
  202. rxd[x].control = 0x0;
  203. rxd[x].status = 0x80000000; /* give ownership it to 21143 */
  204. }
  205. rxd[NRXD - 1].control = 0x008; /* Set Receive end of ring on la
  206. st descriptor */
  207. rxd_tail = 0;
  208. }
  209. /* tell DC211XX where to find rx descriptor list */
  210. outl((unsigned long)&rxd[0], ioaddr + CSR3);
  211. /* start the receiver */
  212. outl(0x2406002, ioaddr + CSR6);
  213. }
  214. /**************************************************************************
  215. ETH_TRANSMIT - Transmit a frame
  216. ***************************************************************************/
  217. static const char padmap[] = {
  218. 0, 3, 2, 1};
  219. static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
  220. {
  221. unsigned long time;
  222. /* setup ethernet header */
  223. memcpy(ehdr, d, ETH_ALEN);
  224. memcpy(&ehdr[ETH_ALEN], nic->node_addr, ETH_ALEN);
  225. ehdr[ETH_ALEN*2] = (t >> 8) & 0xff;
  226. ehdr[ETH_ALEN*2+1] = t & 0xff;
  227. /* setup the transmit descriptor */
  228. memset(&txd, 0, sizeof(struct txdesc));
  229. txd.buf1addr = &ehdr[0]; /* ethernet header */
  230. txd.buf1sz = ETH_HLEN;
  231. txd.buf2addr = p; /* packet to transmit */
  232. txd.buf2sz = s;
  233. txd.control = 0x188; /* LS+FS+TER */
  234. txd.status = 0x80000000; /* give it to 21143 */
  235. outl(inl(ioaddr + CSR6) & ~0x00004000, ioaddr + CSR6);
  236. outl((unsigned long)&txd, ioaddr + CSR4);
  237. outl(inl(ioaddr + CSR6) | 0x00004000, ioaddr + CSR6);
  238. /* Wait for transmit to complete before returning. not well tested.
  239. time = currticks();
  240. while(txd.status & 0x80000000) {
  241. if (currticks() - time > 20) {
  242. printf("transmit timeout.\n");
  243. break;
  244. }
  245. }
  246. */
  247. }
  248. /**************************************************************************
  249. ETH_POLL - Wait for a frame
  250. ***************************************************************************/
  251. static int tulip_poll(struct nic *nic)
  252. {
  253. if (rxd[rxd_tail].status & 0x80000000) return 0;
  254. nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
  255. /* copy packet to working buffer */
  256. /* XXX - this copy could be avoided with a little more work
  257. but for now we are content with it because the optimised
  258. memcpy(, , ) is quite fast */
  259. memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen);
  260. /* return the descriptor and buffer to recieve ring */
  261. rxd[rxd_tail].status = 0x80000000;
  262. rxd_tail++;
  263. if (rxd_tail == NRXD) rxd_tail = 0;
  264. return 1;
  265. }
  266. static void tulip_disable(struct nic *nic)
  267. {
  268. /* nothing for the moment */
  269. }
  270. /**************************************************************************
  271. ETH_PROBE - Look for an adapter
  272. ***************************************************************************/
  273. struct nic *otulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
  274. {
  275. int i;
  276. if (io_addrs == 0 || *io_addrs == 0)
  277. return (0);
  278. vendor = pci->vendor;
  279. dev_id = pci->dev_id;
  280. ioaddr = *io_addrs;
  281. membase = (unsigned int *)pci->membase;
  282. /* wakeup chip */
  283. pcibios_write_config_dword(pci->bus,pci->devfn,0x40,0x00000000);
  284. /* Stop the chip's Tx and Rx processes. */
  285. /* outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); */
  286. /* Clear the missed-packet counter. */
  287. /* (volatile int)inl(ioaddr + CSR8); */
  288. srom_read();
  289. for (i=0; i < ETH_ALEN; i++)
  290. nic->node_addr[i] = srom[20+i];
  291. printf("Tulip %! at ioaddr %#hX\n", nic->node_addr, ioaddr);
  292. tulip_reset(nic);
  293. nic->reset = tulip_reset;
  294. nic->poll = tulip_poll;
  295. nic->transmit = tulip_transmit;
  296. nic->disable = tulip_disable;
  297. return nic;
  298. }