ethervt6102.c 23 KB

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