ether79c970.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * AMD79C970
  11. * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus
  12. * To do:
  13. * finish this rewrite
  14. */
  15. #include "u.h"
  16. #include "lib.h"
  17. #include "mem.h"
  18. #include "dat.h"
  19. #include "fns.h"
  20. #include "io.h"
  21. #include "etherif.h"
  22. enum {
  23. Lognrdre = 6,
  24. Nrdre = (1<<Lognrdre),/* receive descriptor ring entries */
  25. Logntdre = 4,
  26. Ntdre = (1<<Logntdre),/* transmit descriptor ring entries */
  27. Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
  28. };
  29. enum { /* DWIO I/O resource map */
  30. Aprom = 0x0000, /* physical address */
  31. Rdp = 0x0010, /* register data port */
  32. Rap = 0x0014, /* register address port */
  33. Sreset = 0x0018, /* software reset */
  34. Bdp = 0x001C, /* bus configuration register data port */
  35. };
  36. enum { /* CSR0 */
  37. Init = 0x0001, /* begin initialisation */
  38. Strt = 0x0002, /* enable chip */
  39. Stop = 0x0004, /* disable chip */
  40. Tdmd = 0x0008, /* transmit demand */
  41. Txon = 0x0010, /* transmitter on */
  42. Rxon = 0x0020, /* receiver on */
  43. Iena = 0x0040, /* interrupt enable */
  44. Intr = 0x0080, /* interrupt flag */
  45. Idon = 0x0100, /* initialisation done */
  46. Tint = 0x0200, /* transmit interrupt */
  47. Rint = 0x0400, /* receive interrupt */
  48. Merr = 0x0800, /* memory error */
  49. Miss = 0x1000, /* missed frame */
  50. Cerr = 0x2000, /* collision */
  51. Babl = 0x4000, /* transmitter timeout */
  52. Err = 0x8000, /* Babl|Cerr|Miss|Merr */
  53. };
  54. enum { /* CSR3 */
  55. Bswp = 0x0004, /* byte swap */
  56. Emba = 0x0008, /* enable modified back-off algorithm */
  57. Dxmt2pd = 0x0010, /* disable transmit two part deferral */
  58. Lappen = 0x0020, /* look-ahead packet processing enable */
  59. };
  60. enum { /* CSR4 */
  61. ApadXmt = 0x0800, /* auto pad transmit */
  62. };
  63. enum { /* CSR15 */
  64. Prom = 0x8000, /* promiscuous mode */
  65. };
  66. typedef struct { /* Initialisation Block */
  67. uint16_t mode;
  68. uint8_t rlen; /* upper 4 bits */
  69. uint8_t tlen; /* upper 4 bits */
  70. uint8_t padr[6];
  71. uint8_t res[2];
  72. uint8_t ladr[8];
  73. uint32_t rdra;
  74. uint32_t tdra;
  75. } Iblock;
  76. typedef struct { /* descriptor ring entry */
  77. uint32_t addr;
  78. uint32_t md1; /* status|bcnt */
  79. uint32_t md2; /* rcc|rpc|mcnt */
  80. void* data;
  81. } Dre;
  82. enum { /* md1 */
  83. Enp = 0x01000000, /* end of packet */
  84. Stp = 0x02000000, /* start of packet */
  85. RxBuff = 0x04000000, /* buffer error */
  86. Def = 0x04000000, /* deferred */
  87. Crc = 0x08000000, /* CRC error */
  88. One = 0x08000000, /* one retry needed */
  89. Oflo = 0x10000000, /* overflow error */
  90. More = 0x10000000, /* more than one retry needed */
  91. Fram = 0x20000000, /* framing error */
  92. RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */
  93. TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */
  94. Own = 0x80000000,
  95. };
  96. enum { /* md2 */
  97. Rtry = 0x04000000, /* failed after repeated retries */
  98. Lcar = 0x08000000, /* loss of carrier */
  99. Lcol = 0x10000000, /* late collision */
  100. Uflo = 0x40000000, /* underflow error */
  101. TxBuff = 0x80000000, /* buffer error */
  102. };
  103. typedef struct Ctlr Ctlr;
  104. struct Ctlr {
  105. Lock;
  106. int port;
  107. Pcidev* pcidev;
  108. Ctlr* next;
  109. int active;
  110. int init; /* initialisation in progress */
  111. Iblock iblock;
  112. Dre* rdr; /* receive descriptor ring */
  113. int rdrx;
  114. Dre* tdr; /* transmit descriptor ring */
  115. int tdrh; /* host index into tdr */
  116. int tdri; /* interface index into tdr */
  117. int ntq; /* descriptors active */
  118. ulong rxbuff; /* receive statistics */
  119. ulong crc;
  120. ulong oflo;
  121. ulong fram;
  122. ulong rtry; /* transmit statistics */
  123. ulong lcar;
  124. ulong lcol;
  125. ulong uflo;
  126. ulong txbuff;
  127. ulong merr; /* bobf is such a whiner */
  128. ulong miss;
  129. ulong babl;
  130. int (*ior)(Ctlr*, int);
  131. void (*iow)(Ctlr*, int, int);
  132. };
  133. static Ctlr* ctlrhead;
  134. static Ctlr* ctlrtail;
  135. /*
  136. * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above.
  137. * To get to 16-bit offsets, scale down with 0x10 staying the same.
  138. */
  139. static int
  140. io16r(Ctlr* c, int r)
  141. {
  142. if(r >= Rdp)
  143. r = (r-Rdp)/2+Rdp;
  144. return ins(c->port+r);
  145. }
  146. static void
  147. io16w(Ctlr* c, int r, int v)
  148. {
  149. if(r >= Rdp)
  150. r = (r-Rdp)/2+Rdp;
  151. outs(c->port+r, v);
  152. }
  153. static int
  154. io32r(Ctlr* c, int r)
  155. {
  156. return inl(c->port+r);
  157. }
  158. static void
  159. io32w(Ctlr* c, int r, int v)
  160. {
  161. outl(c->port+r, v);
  162. }
  163. static void
  164. attach(Ether*)
  165. {
  166. }
  167. static void
  168. detach(Ether* ether)
  169. {
  170. Ctlr *ctlr;
  171. ctlr = ether->ctlr;
  172. ctlr->iow(ctlr, Rdp, Iena|Stop);
  173. }
  174. static void
  175. ringinit(Ctlr* ctlr)
  176. {
  177. Dre *dre;
  178. /*
  179. * Initialise the receive and transmit buffer rings.
  180. * The ring entries must be aligned on 16-byte boundaries.
  181. *
  182. * This routine is protected by ctlr->init.
  183. */
  184. if(ctlr->rdr == 0){
  185. ctlr->rdr = ialloc(Nrdre*sizeof(Dre), 0x10);
  186. for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
  187. dre->data = malloc(Rbsize);
  188. dre->addr = PADDR(dre->data);
  189. dre->md2 = 0;
  190. dre->md1 = Own|(-Rbsize & 0xFFFF);
  191. }
  192. }
  193. ctlr->rdrx = 0;
  194. if(ctlr->tdr == 0)
  195. ctlr->tdr = ialloc(Ntdre*sizeof(Dre), 0x10);
  196. memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
  197. ctlr->tdrh = ctlr->tdri = 0;
  198. }
  199. static void
  200. transmit(Ether* ether)
  201. {
  202. Ctlr *ctlr;
  203. Block *bp;
  204. Dre *dre;
  205. RingBuf *tb;
  206. ctlr = ether->ctlr;
  207. if(ctlr->init)
  208. return;
  209. while(ctlr->ntq < (Ntdre-1)){
  210. tb = &ether->tb[ether->ti];
  211. if(tb->owner != Interface)
  212. break;
  213. bp = allocb(tb->len);
  214. memmove(bp->wp, tb->pkt, tb->len);
  215. memmove(bp->wp+Eaddrlen, ether->ea, Eaddrlen);
  216. bp->wp += tb->len;
  217. /*
  218. * Give ownership of the descriptor to the chip,
  219. * increment the software ring descriptor pointer
  220. * and tell the chip to poll.
  221. * There's no need to pad to ETHERMINTU
  222. * here as ApadXmt is set in CSR4.
  223. */
  224. dre = &ctlr->tdr[ctlr->tdrh];
  225. dre->data = bp;
  226. dre->addr = PADDR(bp->rp);
  227. dre->md2 = 0;
  228. dre->md1 = Own|Stp|Enp|Oflo|(-BLEN(bp) & 0xFFFF);
  229. ctlr->ntq++;
  230. ctlr->iow(ctlr, Rap, 0);
  231. ctlr->iow(ctlr, Rdp, Iena|Tdmd);
  232. ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
  233. tb->owner = Host;
  234. ether->ti = NEXT(ether->ti, ether->ntb);
  235. }
  236. }
  237. static void
  238. interrupt(Ureg*, void* arg)
  239. {
  240. Ctlr *ctlr;
  241. Ether *ether;
  242. int csr0;
  243. Dre *dre;
  244. RingBuf *rb;
  245. ether = arg;
  246. ctlr = ether->ctlr;
  247. /*
  248. * Acknowledge all interrupts and whine about those that shouldn't
  249. * happen.
  250. */
  251. intrloop:
  252. csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF;
  253. ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena);
  254. if(csr0 & Merr)
  255. ctlr->merr++;
  256. if(csr0 & Miss)
  257. ctlr->miss++;
  258. if(csr0 & Babl)
  259. ctlr->babl++;
  260. //if(csr0 & (Babl|Miss|Merr))
  261. // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0);
  262. if(!(csr0 & (Rint|Tint)))
  263. return;
  264. /*
  265. * Receiver interrupt: run round the descriptor ring logging
  266. * errors and passing valid receive data up to the higher levels
  267. * until a descriptor is encountered still owned by the chip.
  268. */
  269. if(csr0 & Rint){
  270. dre = &ctlr->rdr[ctlr->rdrx];
  271. while(!(dre->md1 & Own)){
  272. rb = &ether->rb[ether->ri];
  273. if(dre->md1 & RxErr){
  274. if(dre->md1 & RxBuff)
  275. ctlr->rxbuff++;
  276. if(dre->md1 & Crc)
  277. ctlr->crc++;
  278. if(dre->md1 & Oflo)
  279. ctlr->oflo++;
  280. if(dre->md1 & Fram)
  281. ctlr->fram++;
  282. }
  283. else if(rb->owner == Interface){
  284. rb->owner = Host;
  285. rb->len = (dre->md2 & 0x0FFF)-4;
  286. memmove(rb->pkt, dre->data, rb->len);
  287. ether->ri = NEXT(ether->ri, ether->nrb);
  288. }
  289. /*
  290. * Finished with this descriptor, reinitialise it,
  291. * give it back to the chip, then on to the next...
  292. */
  293. dre->md2 = 0;
  294. dre->md1 = Own|(-Rbsize & 0xFFFF);
  295. ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
  296. dre = &ctlr->rdr[ctlr->rdrx];
  297. }
  298. }
  299. /*
  300. * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
  301. */
  302. if(csr0 & Tint){
  303. lock(ctlr);
  304. while(ctlr->ntq){
  305. dre = &ctlr->tdr[ctlr->tdri];
  306. if(dre->md1 & Own)
  307. break;
  308. if(dre->md1 & TxErr){
  309. if(dre->md2 & Rtry)
  310. ctlr->rtry++;
  311. if(dre->md2 & Lcar)
  312. ctlr->lcar++;
  313. if(dre->md2 & Lcol)
  314. ctlr->lcol++;
  315. if(dre->md2 & Uflo)
  316. ctlr->uflo++;
  317. if(dre->md2 & TxBuff)
  318. ctlr->txbuff++;
  319. }
  320. freeb(dre->data);
  321. ctlr->ntq--;
  322. ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
  323. }
  324. transmit(ether);
  325. unlock(ctlr);
  326. }
  327. goto intrloop;
  328. }
  329. static void
  330. amd79c970pci(void)
  331. {
  332. Ctlr *ctlr;
  333. Pcidev *p;
  334. p = nil;
  335. while(p = pcimatch(p, 0x1022, 0x2000)){
  336. ctlr = malloc(sizeof(Ctlr));
  337. ctlr->port = p->mem[0].bar & ~0x01;
  338. ctlr->pcidev = p;
  339. if(ctlrhead != nil)
  340. ctlrtail->next = ctlr;
  341. else
  342. ctlrhead = ctlr;
  343. ctlrtail = ctlr;
  344. }
  345. }
  346. int
  347. amd79c970reset(Ether* ether)
  348. {
  349. int x;
  350. uint8_t ea[Eaddrlen];
  351. Ctlr *ctlr;
  352. if(ctlrhead == nil)
  353. amd79c970pci();
  354. /*
  355. * Any adapter matches if no port is supplied,
  356. * otherwise the ports must match.
  357. */
  358. for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  359. if(ctlr->active)
  360. continue;
  361. if(ether->port == 0 || ether->port == ctlr->port){
  362. ctlr->active = 1;
  363. break;
  364. }
  365. }
  366. if(ctlr == nil)
  367. return -1;
  368. /*
  369. * Allocate a controller structure and start to initialise it.
  370. */
  371. ether->ctlr = ctlr;
  372. ether->port = ctlr->port;
  373. ether->irq = ctlr->pcidev->intl;
  374. ether->tbdf = ctlr->pcidev->tbdf;
  375. pcisetbme(ctlr->pcidev);
  376. ilock(ctlr);
  377. ctlr->init = 1;
  378. io32r(ctlr, Sreset);
  379. io16r(ctlr, Sreset);
  380. if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){
  381. ctlr->ior = io16r;
  382. ctlr->iow = io16w;
  383. }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){
  384. ctlr->ior = io32r;
  385. ctlr->iow = io32w;
  386. }else{
  387. print("#l%d: card doesn't talk right\n", ether->ctlrno);
  388. iunlock(ctlr);
  389. return -1;
  390. }
  391. ctlr->iow(ctlr, Rap, 88);
  392. x = ctlr->ior(ctlr, Rdp);
  393. ctlr->iow(ctlr, Rap, 89);
  394. x |= ctlr->ior(ctlr, Rdp)<<16;
  395. switch(x&0xFFFFFFF){
  396. case 0x2420003: /* PCnet/PCI 79C970 */
  397. case 0x2621003: /* PCnet/PCI II 79C970A */
  398. break;
  399. default:
  400. print("unknown PCnet card version %.7ux\n", x&0xFFFFFFF);
  401. iunlock(ctlr);
  402. return -1;
  403. }
  404. /*
  405. * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access.
  406. * Set the auto pad transmit in CSR4.
  407. */
  408. ctlr->iow(ctlr, Rap, 20);
  409. ctlr->iow(ctlr, Bdp, 0x0002);
  410. ctlr->iow(ctlr, Rap, 4);
  411. x = ctlr->ior(ctlr, Rdp) & 0xFFFF;
  412. ctlr->iow(ctlr, Rdp, ApadXmt|x);
  413. ctlr->iow(ctlr, Rap, 0);
  414. /*
  415. * Check if the adapter's station address is to be overridden.
  416. * If not, read it from the I/O-space and set in ether->ea prior to
  417. * loading the station address in the initialisation block.
  418. */
  419. memset(ea, 0, Eaddrlen);
  420. if(!memcmp(ea, ether->ea, Eaddrlen)){
  421. x = ctlr->ior(ctlr, Aprom);
  422. ether->ea[0] = x;
  423. ether->ea[1] = x>>8;
  424. if(ctlr->ior == io16r)
  425. x = ctlr->ior(ctlr, Aprom+2);
  426. else
  427. x >>= 16;
  428. ether->ea[2] = x;
  429. ether->ea[3] = x>>8;
  430. x = ctlr->ior(ctlr, Aprom+4);
  431. ether->ea[4] = x;
  432. ether->ea[5] = x>>8;
  433. }
  434. /*
  435. * Start to fill in the initialisation block
  436. * (must be DWORD aligned).
  437. */
  438. ctlr->iblock.rlen = Lognrdre<<4;
  439. ctlr->iblock.tlen = Logntdre<<4;
  440. memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr));
  441. ringinit(ctlr);
  442. ctlr->iblock.rdra = PADDR(ctlr->rdr);
  443. ctlr->iblock.tdra = PADDR(ctlr->tdr);
  444. /*
  445. * Point the chip at the initialisation block and tell it to go.
  446. * Mask the Idon interrupt and poll for completion. Strt and interrupt
  447. * enables will be set later when attaching to the network.
  448. */
  449. x = PADDR(&ctlr->iblock);
  450. ctlr->iow(ctlr, Rap, 1);
  451. ctlr->iow(ctlr, Rdp, x & 0xFFFF);
  452. ctlr->iow(ctlr, Rap, 2);
  453. ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF);
  454. ctlr->iow(ctlr, Rap, 3);
  455. ctlr->iow(ctlr, Rdp, Idon);
  456. ctlr->iow(ctlr, Rap, 0);
  457. ctlr->iow(ctlr, Rdp, Init);
  458. while(!(ctlr->ior(ctlr, Rdp) & Idon))
  459. ;
  460. /*
  461. * We used to set CSR0 to Idon|Stop here, and then
  462. * in attach change it to Iena|Strt. Apparently the simulated
  463. * 79C970 in VMware never enables after a write of Idon|Stop,
  464. * so we enable the device here now.
  465. */
  466. ctlr->iow(ctlr, Rdp, Iena|Strt);
  467. ctlr->init = 0;
  468. iunlock(ctlr);
  469. /*
  470. * Linkage to the generic ethernet driver.
  471. */
  472. ether->attach = attach;
  473. ether->transmit = transmit;
  474. ether->interrupt = interrupt;
  475. ether->detach = detach;
  476. return 0;
  477. }