ethervt6102.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  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. static long
  303. vt6102ifstat(Ether* edev, void* a, long n, ulong offset)
  304. {
  305. char *p;
  306. Ctlr *ctlr;
  307. int i, l, r;
  308. ctlr = edev->ctlr;
  309. p = malloc(2*READSTR);
  310. l = 0;
  311. for(i = 0; i < Nrxstats; i++){
  312. l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
  313. rxstats[i], ctlr->rxstats[i]);
  314. }
  315. for(i = 0; i < Ntxstats; i++){
  316. if(txstats[i] == nil)
  317. continue;
  318. l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
  319. txstats[i], ctlr->txstats[i]);
  320. }
  321. l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls);
  322. l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr);
  323. l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr);
  324. l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep);
  325. l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr);
  326. l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr);
  327. l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned);
  328. l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit);
  329. l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied);
  330. l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw);
  331. l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft);
  332. if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  333. l += snprint(p+l, 2*READSTR, "phy: ");
  334. for(i = 0; i < NMiiPhyr; i++){
  335. if(i && ((i & 0x07) == 0))
  336. l += snprint(p+l, 2*READSTR-l, "\n ");
  337. r = miimir(ctlr->mii, i);
  338. l += snprint(p+l, 2*READSTR-l, " %4.4uX", r);
  339. }
  340. snprint(p+l, 2*READSTR-l, "\n");
  341. }
  342. snprint(p+l, 2*READSTR-l, "\n");
  343. n = readstr(offset, a, n, p);
  344. free(p);
  345. return n;
  346. }
  347. static void
  348. vt6102promiscuous(void* arg, int on)
  349. {
  350. int rcr;
  351. Ctlr *ctlr;
  352. Ether *edev;
  353. edev = arg;
  354. ctlr = edev->ctlr;
  355. rcr = csr8r(ctlr, Rcr);
  356. if(on)
  357. rcr |= Prom;
  358. else
  359. rcr &= ~Prom;
  360. csr8w(ctlr, Rcr, rcr);
  361. }
  362. static void
  363. vt6102multicast(void* arg, uchar* addr, int on)
  364. {
  365. /*
  366. * For now Am is set in Rcr.
  367. * Will need to interlock with promiscuous
  368. * when this gets filled in.
  369. */
  370. USED(arg, addr, on);
  371. }
  372. static int
  373. vt6102wakeup(void* v)
  374. {
  375. return *((int*)v) != 0;
  376. }
  377. static void
  378. vt6102imr(Ctlr* ctlr, int imr)
  379. {
  380. ilock(&ctlr->clock);
  381. ctlr->imr |= imr;
  382. csr16w(ctlr, Imr, ctlr->imr);
  383. iunlock(&ctlr->clock);
  384. }
  385. static void
  386. vt6102lproc(void* arg)
  387. {
  388. Ctlr *ctlr;
  389. Ether *edev;
  390. MiiPhy *phy;
  391. edev = arg;
  392. ctlr = edev->ctlr;
  393. for(;;){
  394. if(ctlr->mii == nil || ctlr->mii->curphy == nil)
  395. break;
  396. if(miistatus(ctlr->mii) < 0)
  397. goto enable;
  398. phy = ctlr->mii->curphy;
  399. ilock(&ctlr->clock);
  400. if(phy->fd)
  401. ctlr->cr |= Fdx;
  402. else
  403. ctlr->cr &= ~Fdx;
  404. csr16w(ctlr, Cr, ctlr->cr);
  405. iunlock(&ctlr->clock);
  406. enable:
  407. ctlr->lwakeup = 0;
  408. vt6102imr(ctlr, Srci);
  409. ctlr->lsleep++;
  410. sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);
  411. }
  412. pexit("vt6102lproc: done", 1);
  413. }
  414. static void
  415. vt6102attach(Ether* edev)
  416. {
  417. int i;
  418. Ctlr *ctlr;
  419. Ds *ds, *prev;
  420. uchar *alloc, *bounce;
  421. char name[KNAMELEN];
  422. ctlr = edev->ctlr;
  423. qlock(&ctlr->alock);
  424. if(ctlr->alloc != nil){
  425. qunlock(&ctlr->alock);
  426. return;
  427. }
  428. /*
  429. * Descriptor and bounce-buffer space.
  430. * Must all be aligned on a 4-byte boundary,
  431. * but try to align on cache-lines.
  432. */
  433. ctlr->nrd = Nrd;
  434. ctlr->ntd = Ntd;
  435. alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1);
  436. if(alloc == nil){
  437. qunlock(&ctlr->alock);
  438. return;
  439. }
  440. ctlr->alloc = alloc;
  441. alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls);
  442. ctlr->rd = (Ds*)alloc;
  443. if(waserror()){
  444. ds = ctlr->rd;
  445. for(i = 0; i < ctlr->nrd; i++){
  446. if(ds->bp != nil){
  447. freeb(ds->bp);
  448. ds->bp = nil;
  449. }
  450. if((ds = ds->next) == nil)
  451. break;
  452. }
  453. free(ctlr->alloc);
  454. ctlr->alloc = nil;
  455. qunlock(&ctlr->alock);
  456. nexterror();
  457. }
  458. prev = ctlr->rd + ctlr->nrd-1;
  459. for(i = 0; i < ctlr->nrd; i++){
  460. ds = (Ds*)alloc;
  461. alloc += ctlr->cls;
  462. ds->control = Rdbsz;
  463. ds->branch = PCIWADDR(alloc);
  464. ds->bp = iallocb(Rdbsz+3);
  465. if(ds->bp == nil)
  466. error("vt6102: can't allocate receive ring\n");
  467. ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
  468. ds->addr = PCIWADDR(ds->bp->rp);
  469. ds->next = (Ds*)alloc;
  470. ds->prev = prev;
  471. prev = ds;
  472. ds->status = Own;
  473. }
  474. prev->branch = 0;
  475. prev->next = ctlr->rd;
  476. prev->status = 0;
  477. ctlr->rdh = ctlr->rd;
  478. ctlr->td = (Ds*)alloc;
  479. prev = ctlr->td + ctlr->ntd-1;
  480. bounce = alloc + ctlr->ntd*ctlr->cls;
  481. for(i = 0; i < ctlr->ntd; i++){
  482. ds = (Ds*)alloc;
  483. alloc += ctlr->cls;
  484. ds->bounce = bounce;
  485. bounce += Txcopy;
  486. ds->next = (Ds*)alloc;
  487. ds->prev = prev;
  488. prev = ds;
  489. }
  490. prev->next = ctlr->td;
  491. ctlr->tdh = ctlr->tdt = ctlr->td;
  492. ctlr->tdused = 0;
  493. ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;
  494. /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
  495. ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
  496. ilock(&ctlr->clock);
  497. csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
  498. csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
  499. csr16w(ctlr, Isr, ~0);
  500. csr16w(ctlr, Imr, ctlr->imr);
  501. csr16w(ctlr, Cr, ctlr->cr);
  502. iunlock(&ctlr->clock);
  503. snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
  504. kproc(name, vt6102lproc, edev);
  505. qunlock(&ctlr->alock);
  506. poperror();
  507. }
  508. static void
  509. vt6102transmit(Ether* edev)
  510. {
  511. Block *bp;
  512. Ctlr *ctlr;
  513. Ds *ds, *next;
  514. int control, i, o, prefix, size, tdused, timeo;
  515. ctlr = edev->ctlr;
  516. ilock(&ctlr->tlock);
  517. /*
  518. * Free any completed packets
  519. */
  520. ds = ctlr->tdh;
  521. for(tdused = ctlr->tdused; tdused > 0; tdused--){
  522. /*
  523. * For some errors the chip will turn the Tx engine
  524. * off. Wait for that to happen.
  525. * Could reset and re-init the chip here if it doesn't
  526. * play fair.
  527. * To do: adjust Tx FIFO threshold on underflow.
  528. */
  529. if(ds->status & (Abt|Tbuff|Udf)){
  530. for(timeo = 0; timeo < 1000; timeo++){
  531. if(!(csr16r(ctlr, Cr) & Txon))
  532. break;
  533. microdelay(1);
  534. }
  535. ds->status = Own;
  536. csr32w(ctlr, Txdaddr, PCIWADDR(ds));
  537. }
  538. if(ds->status & Own)
  539. break;
  540. ds->addr = 0;
  541. ds->branch = 0;
  542. if(ds->bp != nil){
  543. freeb(ds->bp);
  544. ds->bp = nil;
  545. }
  546. for(i = 0; i < Ntxstats-1; i++){
  547. if(ds->status & (1<<i))
  548. ctlr->txstats[i]++;
  549. }
  550. ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
  551. ds = ds->next;
  552. }
  553. ctlr->tdh = ds;
  554. /*
  555. * Try to fill the ring back up.
  556. */
  557. ds = ctlr->tdt;
  558. while(tdused < ctlr->ntd-2){
  559. if((bp = qget(edev->oq)) == nil)
  560. break;
  561. tdused++;
  562. size = BLEN(bp);
  563. prefix = 0;
  564. if(o = (((int)bp->rp) & 0x03)){
  565. prefix = Txcopy-o;
  566. if(prefix > size)
  567. prefix = size;
  568. memmove(ds->bounce, bp->rp, prefix);
  569. ds->addr = PCIWADDR(ds->bounce);
  570. bp->rp += prefix;
  571. size -= prefix;
  572. }
  573. next = ds->next;
  574. ds->branch = PCIWADDR(ds->next);
  575. if(size){
  576. if(prefix){
  577. next->bp = bp;
  578. next->addr = PCIWADDR(bp->rp);
  579. next->branch = PCIWADDR(next->next);
  580. next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);
  581. control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);
  582. next = next->next;
  583. tdused++;
  584. ctlr->tsplit++;
  585. }
  586. else{
  587. ds->bp = bp;
  588. ds->addr = PCIWADDR(bp->rp);
  589. control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
  590. ctlr->taligned++;
  591. }
  592. }
  593. else{
  594. freeb(bp);
  595. control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
  596. ctlr->tcopied++;
  597. }
  598. ds->control = control;
  599. if(tdused >= ctlr->ntd-2){
  600. ds->control |= Ic;
  601. ctlr->txdw++;
  602. }
  603. coherence();
  604. ds->status = Own;
  605. ds = next;
  606. }
  607. ctlr->tdt = ds;
  608. ctlr->tdused = tdused;
  609. if(ctlr->tdused)
  610. csr16w(ctlr, Cr, Tdmd|ctlr->cr);
  611. iunlock(&ctlr->tlock);
  612. }
  613. static void
  614. vt6102receive(Ether* edev)
  615. {
  616. Ds *ds;
  617. Block *bp;
  618. Ctlr *ctlr;
  619. int i, len;
  620. ctlr = edev->ctlr;
  621. ds = ctlr->rdh;
  622. while(!(ds->status & Own) && ds->status != 0){
  623. if(ds->status & Rerr){
  624. for(i = 0; i < Nrxstats; i++){
  625. if(ds->status & (1<<i))
  626. ctlr->rxstats[i]++;
  627. }
  628. }
  629. else if(bp = iallocb(Rdbsz+3)){
  630. len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
  631. ds->bp->wp = ds->bp->rp+len;
  632. etheriq(edev, ds->bp, 1);
  633. bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
  634. ds->addr = PCIWADDR(bp->rp);
  635. ds->bp = bp;
  636. }
  637. ds->control = Rdbsz;
  638. ds->branch = 0;
  639. ds->status = 0;
  640. ds->prev->branch = PCIWADDR(ds);
  641. coherence();
  642. ds->prev->status = Own;
  643. ds = ds->next;
  644. }
  645. ctlr->rdh = ds;
  646. csr16w(ctlr, Cr, ctlr->cr);
  647. }
  648. static void
  649. vt6102interrupt(Ureg*, void* arg)
  650. {
  651. Ctlr *ctlr;
  652. Ether *edev;
  653. int imr, isr, r, timeo;
  654. edev = arg;
  655. ctlr = edev->ctlr;
  656. ilock(&ctlr->clock);
  657. csr16w(ctlr, Imr, 0);
  658. imr = ctlr->imr;
  659. ctlr->intr++;
  660. for(;;){
  661. if((isr = csr16r(ctlr, Isr)) != 0)
  662. csr16w(ctlr, Isr, isr);
  663. if((isr & ctlr->imr) == 0)
  664. break;
  665. if(isr & Srci){
  666. imr &= ~Srci;
  667. ctlr->lwakeup = isr & Srci;
  668. wakeup(&ctlr->lrendez);
  669. isr &= ~Srci;
  670. ctlr->lintr++;
  671. }
  672. if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
  673. vt6102receive(edev);
  674. isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
  675. ctlr->rintr++;
  676. }
  677. if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
  678. if(isr & (Abti|Udfi|Tu)){
  679. for(timeo = 0; timeo < 1000; timeo++){
  680. if(!(csr16r(ctlr, Cr) & Txon))
  681. break;
  682. microdelay(1);
  683. }
  684. if((isr & Udfi) && ctlr->tft < CtftSAF){
  685. ctlr->tft += 1<<CtftSHIFT;
  686. r = csr8r(ctlr, Bcr1) & ~CtftMASK;
  687. csr8w(ctlr, Bcr1, r|ctlr->tft);
  688. }
  689. }
  690. vt6102transmit(edev);
  691. isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
  692. ctlr->tintr++;
  693. }
  694. if(isr)
  695. panic("vt6102: isr %4.4uX\n", isr);
  696. }
  697. ctlr->imr = imr;
  698. csr16w(ctlr, Imr, ctlr->imr);
  699. iunlock(&ctlr->clock);
  700. }
  701. static int
  702. vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data)
  703. {
  704. Ctlr *ctlr;
  705. int r, timeo;
  706. ctlr = mii->ctlr;
  707. csr8w(ctlr, Miicr, 0);
  708. r = csr8r(ctlr, Phyadr);
  709. csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
  710. csr8w(ctlr, Phyadr, pa);
  711. csr8w(ctlr, Miiadr, ra);
  712. if(cmd == Wcmd)
  713. csr16w(ctlr, Miidata, data);
  714. csr8w(ctlr, Miicr, cmd);
  715. for(timeo = 0; timeo < 10000; timeo++){
  716. if(!(csr8r(ctlr, Miicr) & cmd))
  717. break;
  718. microdelay(1);
  719. }
  720. if(timeo >= 10000)
  721. return -1;
  722. if(cmd == Wcmd)
  723. return 0;
  724. return csr16r(ctlr, Miidata);
  725. }
  726. static int
  727. vt6102miimir(Mii* mii, int pa, int ra)
  728. {
  729. return vt6102miimicmd(mii, pa, ra, Rcmd, 0);
  730. }
  731. static int
  732. vt6102miimiw(Mii* mii, int pa, int ra, int data)
  733. {
  734. return vt6102miimicmd(mii, pa, ra, Wcmd, data);
  735. }
  736. static int
  737. vt6102detach(Ctlr* ctlr)
  738. {
  739. int timeo;
  740. /*
  741. * Soft reset the controller.
  742. */
  743. csr16w(ctlr, Cr, Sfrst);
  744. for(timeo = 0; timeo < 10000; timeo++){
  745. if(!(csr16r(ctlr, Cr) & Sfrst))
  746. break;
  747. microdelay(1);
  748. }
  749. if(timeo >= 1000)
  750. return -1;
  751. return 0;
  752. }
  753. static int
  754. vt6102reset(Ctlr* ctlr)
  755. {
  756. MiiPhy *phy;
  757. int i, r, timeo;
  758. if(vt6102detach(ctlr) < 0)
  759. return -1;
  760. /*
  761. * Load the MAC address into the PAR[01]
  762. * registers.
  763. */
  764. r = csr8r(ctlr, Eecsr);
  765. csr8w(ctlr, Eecsr, Autold|r);
  766. for(timeo = 0; timeo < 100; timeo++){
  767. if(!(csr8r(ctlr, Cr) & Autold))
  768. break;
  769. microdelay(1);
  770. }
  771. if(timeo >= 100)
  772. return -1;
  773. for(i = 0; i < Eaddrlen; i++)
  774. ctlr->par[i] = csr8r(ctlr, Par0+i);
  775. /*
  776. * Configure DMA and Rx/Tx thresholds.
  777. * If the Rx/Tx threshold bits in Bcr[01] are 0 then
  778. * the thresholds are determined by Rcr/Tcr.
  779. */
  780. r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
  781. csr8w(ctlr, Bcr0, r|Crft64|Dma64);
  782. r = csr8r(ctlr, Bcr1) & ~CtftMASK;
  783. csr8w(ctlr, Bcr1, r|ctlr->tft);
  784. r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
  785. csr8w(ctlr, Rcr, r|Ab|Am);
  786. r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
  787. csr8w(ctlr, Tcr, r);
  788. /*
  789. * Link management.
  790. */
  791. if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  792. return -1;
  793. ctlr->mii->mir = vt6102miimir;
  794. ctlr->mii->miw = vt6102miimiw;
  795. ctlr->mii->ctlr = ctlr;
  796. if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
  797. free(ctlr->mii);
  798. ctlr->mii = nil;
  799. return -1;
  800. }
  801. // print("oui %X phyno %d\n", phy->oui, phy->phyno);
  802. USED(phy);
  803. //miiane(ctlr->mii, ~0, ~0, ~0);
  804. return 0;
  805. }
  806. static void
  807. vt6102pci(void)
  808. {
  809. Pcidev *p;
  810. Ctlr *ctlr;
  811. int cls, port;
  812. p = nil;
  813. while(p = pcimatch(p, 0, 0)){
  814. if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
  815. continue;
  816. switch((p->did<<16)|p->vid){
  817. default:
  818. continue;
  819. case (0x3065<<16)|0x1106: /* Rhine II */
  820. case (0x3106<<16)|0x1106: /* Rhine III */
  821. break;
  822. }
  823. port = p->mem[0].bar & ~0x01;
  824. if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
  825. print("vt6102: port 0x%uX in use\n", port);
  826. continue;
  827. }
  828. ctlr = malloc(sizeof(Ctlr));
  829. ctlr->port = port;
  830. ctlr->pcidev = p;
  831. ctlr->id = (p->did<<16)|p->vid;
  832. if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
  833. cls = 0x10;
  834. ctlr->cls = cls*4;
  835. if(ctlr->cls < sizeof(Ds)){
  836. print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);
  837. iofree(port);
  838. free(ctlr);
  839. continue;
  840. }
  841. ctlr->tft = Ctft64;
  842. if(vt6102reset(ctlr)){
  843. iofree(port);
  844. free(ctlr);
  845. continue;
  846. }
  847. pcisetbme(p);
  848. if(vt6102ctlrhead != nil)
  849. vt6102ctlrtail->next = ctlr;
  850. else
  851. vt6102ctlrhead = ctlr;
  852. vt6102ctlrtail = ctlr;
  853. }
  854. }
  855. static int
  856. vt6102pnp(Ether* edev)
  857. {
  858. Ctlr *ctlr;
  859. if(vt6102ctlrhead == nil)
  860. vt6102pci();
  861. /*
  862. * Any adapter matches if no edev->port is supplied,
  863. * otherwise the ports must match.
  864. */
  865. for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){
  866. if(ctlr->active)
  867. continue;
  868. if(edev->port == 0 || edev->port == ctlr->port){
  869. ctlr->active = 1;
  870. break;
  871. }
  872. }
  873. if(ctlr == nil)
  874. return -1;
  875. edev->ctlr = ctlr;
  876. edev->port = ctlr->port;
  877. edev->irq = ctlr->pcidev->intl;
  878. edev->tbdf = ctlr->pcidev->tbdf;
  879. edev->mbps = 100;
  880. memmove(edev->ea, ctlr->par, Eaddrlen);
  881. /*
  882. * Linkage to the generic ethernet driver.
  883. */
  884. edev->attach = vt6102attach;
  885. edev->transmit = vt6102transmit;
  886. edev->interrupt = vt6102interrupt;
  887. edev->ifstat = vt6102ifstat;
  888. edev->ctl = nil;
  889. edev->arg = edev;
  890. edev->promiscuous = vt6102promiscuous;
  891. edev->multicast = vt6102multicast;
  892. return 0;
  893. }
  894. void
  895. ethervt6102link(void)
  896. {
  897. addethercard("vt6102", vt6102pnp);
  898. addethercard("rhine", vt6102pnp);
  899. }