ethervt6102.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  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. break;
  836. }
  837. port = p->mem[0].bar & ~0x01;
  838. if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
  839. print("vt6102: port 0x%uX in use\n", port);
  840. continue;
  841. }
  842. ctlr = malloc(sizeof(Ctlr));
  843. ctlr->port = port;
  844. ctlr->pcidev = p;
  845. ctlr->id = (p->did<<16)|p->vid;
  846. if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
  847. cls = 0x10;
  848. ctlr->cls = cls*4;
  849. if(ctlr->cls < sizeof(Ds)){
  850. print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);
  851. free(ctlr);
  852. continue;
  853. }
  854. ctlr->tft = Ctft64;
  855. if(vt6102reset(ctlr)){
  856. free(ctlr);
  857. continue;
  858. }
  859. pcisetbme(p);
  860. if(vt6102ctlrhead != nil)
  861. vt6102ctlrtail->next = ctlr;
  862. else
  863. vt6102ctlrhead = ctlr;
  864. vt6102ctlrtail = ctlr;
  865. }
  866. }
  867. static int
  868. vt6102pnp(Ether* edev)
  869. {
  870. Ctlr *ctlr;
  871. if(vt6102ctlrhead == nil)
  872. vt6102pci();
  873. /*
  874. * Any adapter matches if no edev->port is supplied,
  875. * otherwise the ports must match.
  876. */
  877. for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){
  878. if(ctlr->active)
  879. continue;
  880. if(edev->port == 0 || edev->port == ctlr->port){
  881. ctlr->active = 1;
  882. break;
  883. }
  884. }
  885. if(ctlr == nil)
  886. return -1;
  887. edev->ctlr = ctlr;
  888. edev->port = ctlr->port;
  889. edev->irq = ctlr->pcidev->intl;
  890. edev->tbdf = ctlr->pcidev->tbdf;
  891. edev->mbps = 100;
  892. memmove(edev->ea, ctlr->par, Eaddrlen);
  893. /*
  894. * Linkage to the generic ethernet driver.
  895. */
  896. edev->attach = vt6102attach;
  897. edev->transmit = vt6102transmit;
  898. edev->interrupt = vt6102interrupt;
  899. edev->ifstat = vt6102ifstat;
  900. edev->ctl = nil;
  901. edev->arg = edev;
  902. edev->promiscuous = vt6102promiscuous;
  903. edev->multicast = vt6102multicast;
  904. return 0;
  905. }
  906. void
  907. ethervt6102link(void)
  908. {
  909. addethercard("vt6102", vt6102pnp);
  910. addethercard("rhine", vt6102pnp);
  911. }