ethervt6105m.c 26 KB

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