ether79c970.c 11 KB

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