ethervt6102.c 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /*
  2. * VIA VT6102 Fast Ethernet Controller (Rhine II).
  3. * To do:
  4. * cache-line size alignments - done
  5. * reduce tx interrupts
  6. * use 2 descriptors on tx for alignment - done
  7. * reorganise initialisation/shutdown/reset
  8. * adjust Tx FIFO threshold on underflow - untested
  9. * why does the link status never cause an interrupt?
  10. * use the lproc as a periodic timer for stalls, etc.
  11. */
  12. #include "u.h"
  13. #include "../port/lib.h"
  14. #include "mem.h"
  15. #include "dat.h"
  16. #include "fns.h"
  17. #include "io.h"
  18. #include "../port/error.h"
  19. #include "../port/netif.h"
  20. #include "etherif.h"
  21. #include "ethermii.h"
  22. enum {
  23. Par0 = 0x00, /* Ethernet Address */
  24. Rcr = 0x06, /* Receive Configuration */
  25. Tcr = 0x07, /* Transmit Configuration */
  26. Cr = 0x08, /* Control */
  27. Isr = 0x0C, /* Interrupt Status */
  28. Imr = 0x0E, /* Interrupt Mask */
  29. Rxdaddr = 0x18, /* Current Rx Descriptor Address */
  30. Txdaddr = 0x1C, /* Current Tx Descriptor Address */
  31. Phyadr = 0x6C, /* Phy Address */
  32. Miisr = 0x6D, /* MII Status */
  33. Bcr0 = 0x6E, /* Bus Control */
  34. Bcr1 = 0x6F,
  35. Miicr = 0x70, /* MII Control */
  36. Miiadr = 0x71, /* MII Address */
  37. Miidata = 0x72, /* MII Data */
  38. Eecsr = 0x74, /* EEPROM Control and Status */
  39. };
  40. enum { /* Rcr */
  41. Sep = 0x01, /* Accept Error Packets */
  42. Ar = 0x02, /* Accept Small Packets */
  43. Am = 0x04, /* Accept Multicast */
  44. Ab = 0x08, /* Accept Broadcast */
  45. Prom = 0x10, /* Accept Physical Address Packets */
  46. RrftMASK = 0xE0, /* Receive FIFO Threshold */
  47. RrftSHIFT = 5,
  48. Rrft64 = 0<<RrftSHIFT,
  49. Rrft32 = 1<<RrftSHIFT,
  50. Rrft128 = 2<<RrftSHIFT,
  51. Rrft256 = 3<<RrftSHIFT,
  52. Rrft512 = 4<<RrftSHIFT,
  53. Rrft768 = 5<<RrftSHIFT,
  54. Rrft1024 = 6<<RrftSHIFT,
  55. RrftSAF = 7<<RrftSHIFT,
  56. };
  57. enum { /* Tcr */
  58. Lb0 = 0x02, /* Loopback Mode */
  59. Lb1 = 0x04,
  60. Ofset = 0x08, /* Back-off Priority Selection */
  61. RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
  62. RtsfSHIFT = 5,
  63. Rtsf128 = 0<<RtsfSHIFT,
  64. Rtsf256 = 1<<RtsfSHIFT,
  65. Rtsf512 = 2<<RtsfSHIFT,
  66. Rtsf1024 = 3<<RtsfSHIFT,
  67. RtsfSAF = 7<<RtsfSHIFT,
  68. };
  69. enum { /* Cr */
  70. Init = 0x0001, /* INIT Process Begin */
  71. Strt = 0x0002, /* Start NIC */
  72. Stop = 0x0004, /* Stop NIC */
  73. Rxon = 0x0008, /* Turn on Receive Process */
  74. Txon = 0x0010, /* Turn on Transmit Process */
  75. Tdmd = 0x0020, /* Transmit Poll Demand */
  76. Rdmd = 0x0040, /* Receive Poll Demand */
  77. Eren = 0x0100, /* Early Receive Enable */
  78. Fdx = 0x0400, /* Set MAC to Full Duplex Mode */
  79. Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */
  80. Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */
  81. Rdmd1 = 0x4000, /* Receive Poll Demand 1 */
  82. Sfrst = 0x8000, /* Software Reset */
  83. };
  84. enum { /* Isr/Imr */
  85. Prx = 0x0001, /* Received Packet Successfully */
  86. Ptx = 0x0002, /* Transmitted Packet Successfully */
  87. Rxe = 0x0004, /* Receive Error */
  88. Txe = 0x0008, /* Transmit Error */
  89. Tu = 0x0010, /* Transmit Buffer Underflow */
  90. Ru = 0x0020, /* Receive Buffer Link Error */
  91. Be = 0x0040, /* PCI Bus Error */
  92. Cnt = 0x0080, /* Counter Overflow */
  93. Eri = 0x0100, /* Early Receive Interrupt */
  94. Udfi = 0x0200, /* Tx FIFO Underflow */
  95. Ovfi = 0x0400, /* Receive FIFO Overflow */
  96. Pktrace = 0x0800, /* Hmmm... */
  97. Norbf = 0x1000, /* No Receive Buffers */
  98. Abti = 0x2000, /* Transmission Abort */
  99. Srci = 0x4000, /* Port State Change */
  100. Geni = 0x8000, /* General Purpose Interrupt */
  101. };
  102. enum { /* Phyadr */
  103. PhyadMASK = 0x1F, /* PHY Address */
  104. PhyadSHIFT = 0,
  105. Mfdc = 0x20, /* Accelerate MDC Speed */
  106. Mpo0 = 0x40, /* MII Polling Timer Interval */
  107. Mpo1 = 0x80,
  108. };
  109. enum { /* Bcr0 */
  110. DmaMASK = 0x07, /* DMA Length */
  111. DmaSHIFT = 0,
  112. Dma32 = 0<<DmaSHIFT,
  113. Dma64 = 1<<DmaSHIFT,
  114. Dma128 = 2<<DmaSHIFT,
  115. Dma256 = 3<<DmaSHIFT,
  116. Dma512 = 4<<DmaSHIFT,
  117. Dma1024 = 5<<DmaSHIFT,
  118. DmaSAF = 7<<DmaSHIFT,
  119. CrftMASK = 0x38, /* Rx FIFO Threshold */
  120. CrftSHIFT = 3,
  121. Crft64 = 1<<CrftSHIFT,
  122. Crft128 = 2<<CrftSHIFT,
  123. Crft256 = 3<<CrftSHIFT,
  124. Crft512 = 4<<CrftSHIFT,
  125. Crft1024 = 5<<CrftSHIFT,
  126. CrftSAF = 7<<CrftSHIFT,
  127. Extled = 0x40, /* Extra LED Support Control */
  128. Med2 = 0x80, /* Medium Select Control */
  129. };
  130. enum { /* Bcr1 */
  131. PotMASK = 0x07, /* Polling Timer Interval */
  132. PotSHIFT = 0,
  133. CtftMASK = 0x38, /* Tx FIFO Threshold */
  134. CtftSHIFT = 3,
  135. Ctft64 = 1<<CtftSHIFT,
  136. Ctft128 = 2<<CtftSHIFT,
  137. Ctft256 = 3<<CtftSHIFT,
  138. Ctft512 = 4<<CtftSHIFT,
  139. Ctft1024 = 5<<CtftSHIFT,
  140. CtftSAF = 7<<CtftSHIFT,
  141. };
  142. enum { /* Miicr */
  143. Mdc = 0x01, /* Clock */
  144. Mdi = 0x02, /* Data In */
  145. Mdo = 0x04, /* Data Out */
  146. Mout = 0x08, /* Output Enable */
  147. Mdpm = 0x10, /* Direct Program Mode Enable */
  148. Wcmd = 0x20, /* Write Enable */
  149. Rcmd = 0x40, /* Read Enable */
  150. Mauto = 0x80, /* Auto Polling Enable */
  151. };
  152. enum { /* Miiadr */
  153. MadMASK = 0x1F, /* MII Port Address */
  154. MadSHIFT = 0,
  155. Mdone = 0x20, /* Accelerate MDC Speed */
  156. Msrcen = 0x40, /* MII Polling Timer Interval */
  157. Midle = 0x80,
  158. };
  159. enum { /* Eecsr */
  160. Edo = 0x01, /* Data Out */
  161. Edi = 0x02, /* Data In */
  162. Eck = 0x04, /* Clock */
  163. Ecs = 0x08, /* Chip Select */
  164. Dpm = 0x10, /* Direct Program Mode Enable */
  165. Autold = 0x20, /* Dynamic Reload */
  166. Embp = 0x40, /* Embedded Program Enable */
  167. Eepr = 0x80, /* Programmed */
  168. };
  169. /*
  170. * Ring descriptor. The space allocated for each
  171. * of these will be rounded up to a cache-line boundary.
  172. * The first 4 elements are known to the hardware.
  173. */
  174. typedef struct Ds Ds;
  175. typedef struct Ds {
  176. uint status;
  177. uint control;
  178. uint addr;
  179. uint branch;
  180. Block* bp;
  181. void* bounce;
  182. Ds* next;
  183. Ds* prev;
  184. } Ds;
  185. enum { /* Rx Ds status */
  186. Rerr = 0x00000001, /* Receiver Error */
  187. Crc = 0x00000002, /* CRC Error */
  188. Fae = 0x00000004, /* Frame Alignment Error */
  189. Fov = 0x00000008, /* FIFO Overflow */
  190. Long = 0x00000010, /* A Long Packet */
  191. Runt = 0x00000020, /* A Runt Packet */
  192. Rxserr = 0x00000040, /* System Error */
  193. Buff = 0x00000080, /* Buffer Underflow Error */
  194. Rxedp = 0x00000100, /* End of Packet Buffer */
  195. Rxstp = 0x00000200, /* Packet Start */
  196. Chn = 0x00000400, /* Chain Buffer */
  197. Phy = 0x00000800, /* Physical Address Packet */
  198. Bar = 0x00001000, /* Broadcast Packet */
  199. Mar = 0x00002000, /* Multicast Packet */
  200. Rxok = 0x00008000, /* Packet Received Successfully */
  201. LengthMASK = 0x07FF0000, /* Received Packet Length */
  202. LengthSHIFT = 16,
  203. Own = 0x80000000, /* Descriptor Owned by NIC */
  204. };
  205. enum { /* Tx Ds status */
  206. NcrMASK = 0x0000000F, /* Collision Retry Count */
  207. NcrSHIFT = 0,
  208. Cols = 0x00000010, /* Experienced Collisions */
  209. Cdh = 0x00000080, /* CD Heartbeat */
  210. Abt = 0x00000100, /* Aborted after Excessive Collisions */
  211. Owc = 0x00000200, /* Out of Window Collision Seen */
  212. Crs = 0x00000400, /* Carrier Sense Lost */
  213. Udf = 0x00000800, /* FIFO Underflow */
  214. Tbuff = 0x00001000, /* Invalid Td */
  215. Txserr = 0x00002000, /* System Error */
  216. Terr = 0x00008000, /* Excessive Collisions */
  217. };
  218. enum { /* Tx Ds control */
  219. TbsMASK = 0x000007FF, /* Tx Buffer Size */
  220. TbsSHIFT = 0,
  221. Chain = 0x00008000, /* Chain Buffer */
  222. Crcdisable = 0x00010000, /* Disable CRC generation */
  223. Stp = 0x00200000, /* Start of Packet */
  224. Edp = 0x00400000, /* End of Packet */
  225. Ic = 0x00800000, /* Assert Interrupt Immediately */
  226. };
  227. enum {
  228. Nrd = 64,
  229. Ntd = 64,
  230. Rdbsz = ROUNDUP(ETHERMAXTU+4, 4),
  231. Nrxstats = 8,
  232. Ntxstats = 9,
  233. Txcopy = 128,
  234. };
  235. typedef struct Ctlr Ctlr;
  236. typedef struct Ctlr {
  237. int port;
  238. Pcidev* pcidev;
  239. Ctlr* next;
  240. int active;
  241. int id;
  242. uchar par[Eaddrlen];
  243. QLock alock; /* attach */
  244. void* alloc; /* receive/transmit descriptors */
  245. int cls; /* alignment */
  246. int nrd;
  247. int ntd;
  248. Ds* rd;
  249. Ds* rdh;
  250. Lock tlock;
  251. Ds* td;
  252. Ds* tdh;
  253. Ds* tdt;
  254. int tdused;
  255. Lock clock; /* */
  256. int cr;
  257. int imr;
  258. int tft; /* Tx threshold */
  259. Mii* mii;
  260. Rendez lrendez;
  261. int lwakeup;
  262. uint rxstats[Nrxstats]; /* statistics */
  263. uint txstats[Ntxstats];
  264. uint intr;
  265. uint lintr;
  266. uint lsleep;
  267. uint rintr;
  268. uint tintr;
  269. uint taligned;
  270. uint tsplit;
  271. uint tcopied;
  272. uint txdw;
  273. } Ctlr;
  274. static Ctlr* vt6102ctlrhead;
  275. static Ctlr* vt6102ctlrtail;
  276. #define csr8r(c, r) (inb((c)->port+(r)))
  277. #define csr16r(c, r) (ins((c)->port+(r)))
  278. #define csr32r(c, r) (inl((c)->port+(r)))
  279. #define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
  280. #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
  281. #define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
  282. static char* rxstats[Nrxstats] = {
  283. "Receiver Error",
  284. "CRC Error",
  285. "Frame Alignment Error",
  286. "FIFO Overflow",
  287. "Long Packet",
  288. "Runt Packet",
  289. "System Error",
  290. "Buffer Underflow Error",
  291. };
  292. static char* txstats[Ntxstats] = {
  293. "Aborted after Excessive Collisions",
  294. "Out of Window Collision Seen",
  295. "Carrier Sense Lost",
  296. "FIFO Underflow",
  297. "Invalid Td",
  298. "System Error",
  299. nil,
  300. "Excessive Collisions",
  301. };
  302. //extern void cgapost(char[2]);
  303. //extern char* cgapostlo;
  304. //extern char* cgaposthi;
  305. static long
  306. vt6102ifstat(Ether* edev, void* a, long n, ulong offset)
  307. {
  308. char *p;
  309. Ctlr *ctlr;
  310. int i, l, r;
  311. ctlr = edev->ctlr;
  312. p = malloc(2*READSTR);
  313. l = 0;
  314. for(i = 0; i < Nrxstats; i++){
  315. l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
  316. rxstats[i], ctlr->rxstats[i]);
  317. }
  318. for(i = 0; i < Ntxstats; i++){
  319. if(txstats[i] == nil)
  320. continue;
  321. l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
  322. txstats[i], ctlr->txstats[i]);
  323. }
  324. l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls);
  325. l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr);
  326. l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr);
  327. l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep);
  328. l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr);
  329. l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr);
  330. l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned);
  331. l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit);
  332. l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied);
  333. l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw);
  334. l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft);
  335. if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  336. l += snprint(p+l, 2*READSTR, "phy: ");
  337. for(i = 0; i < NMiiPhyr; i++){
  338. if(i && ((i & 0x07) == 0))
  339. l += snprint(p+l, 2*READSTR-l, "\n ");
  340. r = miimir(ctlr->mii, i);
  341. l += snprint(p+l, 2*READSTR-l, " %4.4uX", r);
  342. }
  343. snprint(p+l, 2*READSTR-l, "\n");
  344. }
  345. snprint(p+l, 2*READSTR-l, "\n");
  346. n = readstr(offset, a, n, p);
  347. free(p);
  348. return n;
  349. }
  350. static void
  351. vt6102promiscuous(void* arg, int on)
  352. {
  353. int rcr;
  354. Ctlr *ctlr;
  355. Ether *edev;
  356. edev = arg;
  357. ctlr = edev->ctlr;
  358. rcr = csr8r(ctlr, Rcr);
  359. if(on)
  360. rcr |= Prom;
  361. else
  362. rcr &= ~Prom;
  363. csr8w(ctlr, Rcr, rcr);
  364. }
  365. static void
  366. vt6102multicast(void* arg, uchar* addr, int on)
  367. {
  368. /*
  369. * For now Am is set in Rcr.
  370. * Will need to interlock with promiscuous
  371. * when this gets filled in.
  372. */
  373. USED(arg, addr, on);
  374. }
  375. static int
  376. vt6102wakeup(void* v)
  377. {
  378. return *((int*)v) != 0;
  379. }
  380. static void
  381. vt6102imr(Ctlr* ctlr, int imr)
  382. {
  383. ilock(&ctlr->clock);
  384. ctlr->imr |= imr;
  385. csr16w(ctlr, Imr, ctlr->imr);
  386. iunlock(&ctlr->clock);
  387. }
  388. static void
  389. vt6102lproc(void* arg)
  390. {
  391. Ctlr *ctlr;
  392. Ether *edev;
  393. MiiPhy *phy;
  394. edev = arg;
  395. ctlr = edev->ctlr;
  396. for(;;){
  397. if(ctlr->mii == nil || ctlr->mii->curphy == nil)
  398. break;
  399. if(miistatus(ctlr->mii) < 0)
  400. goto enable;
  401. phy = ctlr->mii->curphy;
  402. ilock(&ctlr->clock);
  403. if(phy->fd)
  404. ctlr->cr |= Fdx;
  405. else
  406. ctlr->cr &= ~Fdx;
  407. csr16w(ctlr, Cr, ctlr->cr);
  408. iunlock(&ctlr->clock);
  409. enable:
  410. ctlr->lwakeup = 0;
  411. vt6102imr(ctlr, Srci);
  412. ctlr->lsleep++;
  413. sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);
  414. }
  415. pexit("vt6102lproc: done", 1);
  416. }
  417. static void
  418. vt6102attach(Ether* edev)
  419. {
  420. int i;
  421. Ctlr *ctlr;
  422. Ds *ds, *prev;
  423. uchar *alloc, *bounce;
  424. char name[KNAMELEN];
  425. ctlr = edev->ctlr;
  426. qlock(&ctlr->alock);
  427. if(ctlr->alloc != nil){
  428. qunlock(&ctlr->alock);
  429. return;
  430. }
  431. /*
  432. * Descriptor and bounce-buffer space.
  433. * Must all be aligned on a 4-byte boundary,
  434. * but try to align on cache-lines.
  435. */
  436. ctlr->nrd = Nrd;
  437. ctlr->ntd = Ntd;
  438. alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1);
  439. if(alloc == nil){
  440. qunlock(&ctlr->alock);
  441. return;
  442. }
  443. ctlr->alloc = alloc;
  444. alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls);
  445. ctlr->rd = (Ds*)alloc;
  446. if(waserror()){
  447. ds = ctlr->rd;
  448. for(i = 0; i < ctlr->nrd; i++){
  449. if(ds->bp != nil){
  450. freeb(ds->bp);
  451. ds->bp = nil;
  452. }
  453. if((ds = ds->next) == nil)
  454. break;
  455. }
  456. free(ctlr->alloc);
  457. ctlr->alloc = nil;
  458. qunlock(&ctlr->alock);
  459. nexterror();
  460. }
  461. prev = ctlr->rd + ctlr->nrd-1;
  462. for(i = 0; i < ctlr->nrd; i++){
  463. ds = (Ds*)alloc;
  464. alloc += ctlr->cls;
  465. ds->control = Rdbsz;
  466. ds->branch = PCIWADDR(alloc);
  467. ds->bp = iallocb(Rdbsz+3);
  468. if(ds->bp == nil)
  469. error("vt6102: can't allocate receive ring\n");
  470. ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
  471. ds->addr = PCIWADDR(ds->bp->rp);
  472. ds->next = (Ds*)alloc;
  473. ds->prev = prev;
  474. prev = ds;
  475. ds->status = Own;
  476. }
  477. prev->branch = 0;
  478. prev->next = ctlr->rd;
  479. prev->status = 0;
  480. ctlr->rdh = ctlr->rd;
  481. ctlr->td = (Ds*)alloc;
  482. prev = ctlr->td + ctlr->ntd-1;
  483. bounce = alloc + ctlr->ntd*ctlr->cls;
  484. for(i = 0; i < ctlr->ntd; i++){
  485. ds = (Ds*)alloc;
  486. alloc += ctlr->cls;
  487. ds->bounce = bounce;
  488. bounce += Txcopy;
  489. ds->next = (Ds*)alloc;
  490. ds->prev = prev;
  491. prev = ds;
  492. }
  493. prev->next = ctlr->td;
  494. ctlr->tdh = ctlr->tdt = ctlr->td;
  495. ctlr->tdused = 0;
  496. ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;
  497. /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
  498. ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
  499. ilock(&ctlr->clock);
  500. csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
  501. csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
  502. csr16w(ctlr, Isr, ~0);
  503. csr16w(ctlr, Imr, ctlr->imr);
  504. csr16w(ctlr, Cr, ctlr->cr);
  505. iunlock(&ctlr->clock);
  506. snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
  507. kproc(name, vt6102lproc, edev);
  508. qunlock(&ctlr->alock);
  509. poperror();
  510. }
  511. static void
  512. vt6102transmit(Ether* edev)
  513. {
  514. Block *bp;
  515. Ctlr *ctlr;
  516. Ds *ds, *next;
  517. int control, i, o, prefix, size, tdused, timeo;
  518. ctlr = edev->ctlr;
  519. ilock(&ctlr->tlock);
  520. /*
  521. * Free any completed packets
  522. */
  523. ds = ctlr->tdh;
  524. for(tdused = ctlr->tdused; tdused > 0; tdused--){
  525. /*
  526. * For some errors the chip will turn the Tx engine
  527. * off. Wait for that to happen.
  528. * Could reset and re-init the chip here if it doesn't
  529. * play fair.
  530. * To do: adjust Tx FIFO threshold on underflow.
  531. */
  532. if(ds->status & (Abt|Tbuff|Udf)){
  533. //*cgaposthi = 'A';
  534. for(timeo = 0; timeo < 1000; timeo++){
  535. if(!(csr16r(ctlr, Cr) & Txon))
  536. break;
  537. microdelay(1);
  538. }
  539. // if(timeo >= 1000)
  540. // *cgaposthi = 'T';
  541. ds->status = Own;
  542. csr32w(ctlr, Txdaddr, PCIWADDR(ds));
  543. //*cgaposthi = 'B';
  544. }
  545. if(ds->status & Own)
  546. break;
  547. ds->addr = 0;
  548. ds->branch = 0;
  549. if(ds->bp != nil){
  550. freeb(ds->bp);
  551. ds->bp = nil;
  552. }
  553. for(i = 0; i < Ntxstats-1; i++){
  554. if(ds->status & (1<<i))
  555. ctlr->txstats[i]++;
  556. }
  557. ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
  558. ds = ds->next;
  559. }
  560. ctlr->tdh = ds;
  561. /*
  562. * Try to fill the ring back up.
  563. */
  564. ds = ctlr->tdt;
  565. while(tdused < ctlr->ntd-2){
  566. if((bp = qget(edev->oq)) == nil)
  567. break;
  568. tdused++;
  569. size = BLEN(bp);
  570. prefix = 0;
  571. if(o = (((int)bp->rp) & 0x03)){
  572. prefix = Txcopy-o;
  573. if(prefix > size)
  574. prefix = size;
  575. memmove(ds->bounce, bp->rp, prefix);
  576. ds->addr = PCIWADDR(ds->bounce);
  577. bp->rp += prefix;
  578. size -= prefix;
  579. }
  580. next = ds->next;
  581. ds->branch = PCIWADDR(ds->next);
  582. if(size){
  583. if(prefix){
  584. next->bp = bp;
  585. next->addr = PCIWADDR(bp->rp);
  586. next->branch = PCIWADDR(next->next);
  587. next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);
  588. control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);
  589. next = next->next;
  590. tdused++;
  591. ctlr->tsplit++;
  592. }
  593. else{
  594. ds->bp = bp;
  595. ds->addr = PCIWADDR(bp->rp);
  596. control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
  597. ctlr->taligned++;
  598. }
  599. }
  600. else{
  601. freeb(bp);
  602. control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
  603. ctlr->tcopied++;
  604. }
  605. ds->control = control;
  606. if(tdused >= ctlr->ntd-2){
  607. ds->control |= Ic;
  608. ctlr->txdw++;
  609. }
  610. coherence();
  611. ds->status = Own;
  612. ds = next;
  613. }
  614. ctlr->tdt = ds;
  615. ctlr->tdused = tdused;
  616. if(ctlr->tdused)
  617. csr16w(ctlr, Cr, Tdmd|ctlr->cr);
  618. iunlock(&ctlr->tlock);
  619. }
  620. static void
  621. vt6102receive(Ether* edev)
  622. {
  623. Ds *ds;
  624. Block *bp;
  625. Ctlr *ctlr;
  626. int i, len;
  627. ctlr = edev->ctlr;
  628. ds = ctlr->rdh;
  629. while(!(ds->status & Own) && ds->status != 0){
  630. if(ds->status & Rerr){
  631. //*cgaposthi = 'R';
  632. for(i = 0; i < Nrxstats; i++){
  633. if(ds->status & (1<<i))
  634. ctlr->rxstats[i]++;
  635. }
  636. //*cgaposthi = 'r';
  637. }
  638. else if(bp = iallocb(Rdbsz+3)){
  639. len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
  640. ds->bp->wp = ds->bp->rp+len;
  641. etheriq(edev, ds->bp, 1);
  642. bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
  643. ds->addr = PCIWADDR(bp->rp);
  644. ds->bp = bp;
  645. }
  646. ds->control = Rdbsz;
  647. ds->branch = 0;
  648. ds->status = 0;
  649. ds->prev->branch = PCIWADDR(ds);
  650. coherence();
  651. ds->prev->status = Own;
  652. ds = ds->next;
  653. }
  654. ctlr->rdh = ds;
  655. csr16w(ctlr, Cr, ctlr->cr);
  656. }
  657. static void
  658. vt6102interrupt(Ureg*, void* arg)
  659. {
  660. Ctlr *ctlr;
  661. Ether *edev;
  662. int imr, isr, r, timeo;
  663. edev = arg;
  664. ctlr = edev->ctlr;
  665. ilock(&ctlr->clock);
  666. csr16w(ctlr, Imr, 0);
  667. imr = ctlr->imr;
  668. ctlr->intr++;
  669. for(;;){
  670. if((isr = csr16r(ctlr, Isr)) != 0)
  671. csr16w(ctlr, Isr, isr);
  672. if((isr & ctlr->imr) == 0)
  673. break;
  674. if(isr & Srci){
  675. imr &= ~Srci;
  676. ctlr->lwakeup = isr & Srci;
  677. wakeup(&ctlr->lrendez);
  678. isr &= ~Srci;
  679. ctlr->lintr++;
  680. }
  681. if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
  682. vt6102receive(edev);
  683. isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
  684. ctlr->rintr++;
  685. }
  686. if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
  687. if(isr & (Abti|Udfi|Tu)){
  688. //*cgaposthi = 'a';
  689. for(timeo = 0; timeo < 1000; timeo++){
  690. if(!(csr16r(ctlr, Cr) & Txon))
  691. break;
  692. microdelay(1);
  693. }
  694. // if(timeo >= 1000)
  695. // *cgapostlo = 't';
  696. // else
  697. // *cgapostlo = 'b';
  698. if((isr & Udfi) && ctlr->tft < CtftSAF){
  699. ctlr->tft += 1<<CtftSHIFT;
  700. r = csr8r(ctlr, Bcr1) & ~CtftMASK;
  701. csr8w(ctlr, Bcr1, r|ctlr->tft);
  702. }
  703. }
  704. vt6102transmit(edev);
  705. isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
  706. ctlr->tintr++;
  707. }
  708. if(isr){
  709. //*cgaposthi = 'X';
  710. panic("vt6102: isr %4.4uX\n", isr);
  711. }
  712. }
  713. ctlr->imr = imr;
  714. csr16w(ctlr, Imr, ctlr->imr);
  715. iunlock(&ctlr->clock);
  716. }
  717. static int
  718. vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data)
  719. {
  720. Ctlr *ctlr;
  721. int r, timeo;
  722. ctlr = mii->ctlr;
  723. csr8w(ctlr, Miicr, 0);
  724. r = csr8r(ctlr, Phyadr);
  725. csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
  726. csr8w(ctlr, Phyadr, pa);
  727. csr8w(ctlr, Miiadr, ra);
  728. if(cmd == Wcmd)
  729. csr16w(ctlr, Miidata, data);
  730. csr8w(ctlr, Miicr, cmd);
  731. for(timeo = 0; timeo < 10000; timeo++){
  732. if(!(csr8r(ctlr, Miicr) & cmd))
  733. break;
  734. microdelay(1);
  735. }
  736. if(timeo >= 10000)
  737. return -1;
  738. if(cmd == Wcmd)
  739. return 0;
  740. return csr16r(ctlr, Miidata);
  741. }
  742. static int
  743. vt6102miimir(Mii* mii, int pa, int ra)
  744. {
  745. return vt6102miimicmd(mii, pa, ra, Rcmd, 0);
  746. }
  747. static int
  748. vt6102miimiw(Mii* mii, int pa, int ra, int data)
  749. {
  750. return vt6102miimicmd(mii, pa, ra, Wcmd, data);
  751. }
  752. static int
  753. vt6102detach(Ctlr* ctlr)
  754. {
  755. int timeo;
  756. /*
  757. * Soft reset the controller.
  758. */
  759. csr16w(ctlr, Cr, Sfrst);
  760. for(timeo = 0; timeo < 10000; timeo++){
  761. if(!(csr16r(ctlr, Cr) & Sfrst))
  762. break;
  763. microdelay(1);
  764. }
  765. if(timeo >= 1000)
  766. return -1;
  767. return 0;
  768. }
  769. static int
  770. vt6102reset(Ctlr* ctlr)
  771. {
  772. MiiPhy *phy;
  773. int i, r, timeo;
  774. if(vt6102detach(ctlr) < 0)
  775. return -1;
  776. /*
  777. * Load the MAC address into the PAR[01]
  778. * registers.
  779. */
  780. r = csr8r(ctlr, Eecsr);
  781. csr8w(ctlr, Eecsr, Autold|r);
  782. for(timeo = 0; timeo < 100; timeo++){
  783. if(!(csr8r(ctlr, Cr) & Autold))
  784. break;
  785. microdelay(1);
  786. }
  787. if(timeo >= 100)
  788. return -1;
  789. for(i = 0; i < Eaddrlen; i++)
  790. ctlr->par[i] = csr8r(ctlr, Par0+i);
  791. /*
  792. * Configure DMA and Rx/Tx thresholds.
  793. * If the Rx/Tx threshold bits in Bcr[01] are 0 then
  794. * the thresholds are determined by Rcr/Tcr.
  795. */
  796. r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
  797. csr8w(ctlr, Bcr0, r|Crft64|Dma64);
  798. r = csr8r(ctlr, Bcr1) & ~CtftMASK;
  799. csr8w(ctlr, Bcr1, r|ctlr->tft);
  800. r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
  801. csr8w(ctlr, Rcr, r|Ab|Am);
  802. r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
  803. csr8w(ctlr, Tcr, r);
  804. /*
  805. * Link management.
  806. */
  807. if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  808. return -1;
  809. ctlr->mii->mir = vt6102miimir;
  810. ctlr->mii->miw = vt6102miimiw;
  811. ctlr->mii->ctlr = ctlr;
  812. if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
  813. free(ctlr->mii);
  814. ctlr->mii = nil;
  815. return -1;
  816. }
  817. // print("oui %X phyno %d\n", phy->oui, phy->phyno);
  818. //miiane(ctlr->mii, ~0, ~0, ~0);
  819. return 0;
  820. }
  821. static void
  822. vt6102pci(void)
  823. {
  824. Pcidev *p;
  825. Ctlr *ctlr;
  826. int cls, port;
  827. p = nil;
  828. while(p = pcimatch(p, 0, 0)){
  829. if(p->ccrb != 0x02 || p->ccru != 0)
  830. continue;
  831. switch((p->did<<16)|p->vid){
  832. default:
  833. continue;
  834. case (0x3065<<16)|0x1106: /* Rhine II */
  835. case (0x3106<<16)|0x1106: /* Rhine III */
  836. break;
  837. }
  838. port = p->mem[0].bar & ~0x01;
  839. if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
  840. print("vt6102: port 0x%uX in use\n", port);
  841. continue;
  842. }
  843. ctlr = malloc(sizeof(Ctlr));
  844. ctlr->port = port;
  845. ctlr->pcidev = p;
  846. ctlr->id = (p->did<<16)|p->vid;
  847. if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
  848. cls = 0x10;
  849. ctlr->cls = cls*4;
  850. if(ctlr->cls < sizeof(Ds)){
  851. print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);
  852. free(ctlr);
  853. continue;
  854. }
  855. ctlr->tft = Ctft64;
  856. if(vt6102reset(ctlr)){
  857. free(ctlr);
  858. continue;
  859. }
  860. pcisetbme(p);
  861. if(vt6102ctlrhead != nil)
  862. vt6102ctlrtail->next = ctlr;
  863. else
  864. vt6102ctlrhead = ctlr;
  865. vt6102ctlrtail = ctlr;
  866. }
  867. }
  868. static int
  869. vt6102pnp(Ether* edev)
  870. {
  871. Ctlr *ctlr;
  872. if(vt6102ctlrhead == nil)
  873. vt6102pci();
  874. /*
  875. * Any adapter matches if no edev->port is supplied,
  876. * otherwise the ports must match.
  877. */
  878. for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){
  879. if(ctlr->active)
  880. continue;
  881. if(edev->port == 0 || edev->port == ctlr->port){
  882. ctlr->active = 1;
  883. break;
  884. }
  885. }
  886. if(ctlr == nil)
  887. return -1;
  888. edev->ctlr = ctlr;
  889. edev->port = ctlr->port;
  890. edev->irq = ctlr->pcidev->intl;
  891. edev->tbdf = ctlr->pcidev->tbdf;
  892. edev->mbps = 100;
  893. memmove(edev->ea, ctlr->par, Eaddrlen);
  894. /*
  895. * Linkage to the generic ethernet driver.
  896. */
  897. edev->attach = vt6102attach;
  898. edev->transmit = vt6102transmit;
  899. edev->interrupt = vt6102interrupt;
  900. edev->ifstat = vt6102ifstat;
  901. edev->ctl = nil;
  902. edev->arg = edev;
  903. edev->promiscuous = vt6102promiscuous;
  904. edev->multicast = vt6102multicast;
  905. return 0;
  906. }
  907. void
  908. ethervt6102link(void)
  909. {
  910. addethercard("vt6102", vt6102pnp);
  911. addethercard("rhine", vt6102pnp);
  912. }