etherdp83820.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. /*
  2. * National Semiconductor DP83820
  3. * 10/100/1000 Mb/s Ethernet Network Interface Controller
  4. * (Gig-NIC).
  5. * Driver assumes little-endian and 32-bit host throughout.
  6. */
  7. #include "u.h"
  8. #include "../port/lib.h"
  9. #include "mem.h"
  10. #include "dat.h"
  11. #include "fns.h"
  12. #include "io.h"
  13. #include "../port/error.h"
  14. #include "../port/netif.h"
  15. #include "etherif.h"
  16. #include "ethermii.h"
  17. enum { /* Registers */
  18. Cr = 0x00, /* Command */
  19. Cfg = 0x04, /* Configuration and Media Status */
  20. Mear = 0x08, /* MII/EEPROM Access */
  21. Ptscr = 0x0C, /* PCI Test Control */
  22. Isr = 0x10, /* Interrupt Status */
  23. Imr = 0x14, /* Interrupt Mask */
  24. Ier = 0x18, /* Interrupt Enable */
  25. Ihr = 0x1C, /* Interrupt Holdoff */
  26. Txdp = 0x20, /* Transmit Descriptor Pointer */
  27. Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
  28. Txcfg = 0x28, /* Transmit Configuration */
  29. Gpior = 0x2C, /* General Purpose I/O Control */
  30. Rxdp = 0x30, /* Receive Descriptor Pointer */
  31. Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
  32. Rxcfg = 0x38, /* Receive Configuration */
  33. Pqcr = 0x3C, /* Priority Queueing Control */
  34. Wcsr = 0x40, /* Wake on LAN Control/Status */
  35. Pcr = 0x44, /* Pause Control/Status */
  36. Rfcr = 0x48, /* Receive Filter/Match Control */
  37. Rfdr = 0x4C, /* Receive Filter/Match Data */
  38. Brar = 0x50, /* Boot ROM Address */
  39. Brdr = 0x54, /* Boot ROM Data */
  40. Srr = 0x58, /* Silicon Revision */
  41. Mibc = 0x5C, /* MIB Control */
  42. Mibd = 0x60, /* MIB Data */
  43. Txdp1 = 0xA0, /* Txdp Priority 1 */
  44. Txdp2 = 0xA4, /* Txdp Priority 2 */
  45. Txdp3 = 0xA8, /* Txdp Priority 3 */
  46. Rxdp1 = 0xB0, /* Rxdp Priority 1 */
  47. Rxdp2 = 0xB4, /* Rxdp Priority 2 */
  48. Rxdp3 = 0xB8, /* Rxdp Priority 3 */
  49. Vrcr = 0xBC, /* VLAN/IP Receive Control */
  50. Vtcr = 0xC0, /* VLAN/IP Transmit Control */
  51. Vdr = 0xC4, /* VLAN Data */
  52. Ccsr = 0xCC, /* Clockrun Control/Status */
  53. Tbicr = 0xE0, /* TBI Control */
  54. Tbisr = 0xE4, /* TBI Status */
  55. Tanar = 0xE8, /* TBI ANAR */
  56. Tanlpar = 0xEC, /* TBI ANLPAR */
  57. Taner = 0xF0, /* TBI ANER */
  58. Tesr = 0xF4, /* TBI ESR */
  59. };
  60. enum { /* Cr */
  61. Txe = 0x00000001, /* Transmit Enable */
  62. Txd = 0x00000002, /* Transmit Disable */
  63. Rxe = 0x00000004, /* Receiver Enable */
  64. Rxd = 0x00000008, /* Receiver Disable */
  65. Txr = 0x00000010, /* Transmitter Reset */
  66. Rxr = 0x00000020, /* Receiver Reset */
  67. Swien = 0x00000080, /* Software Interrupt Enable */
  68. Rst = 0x00000100, /* Reset */
  69. TxpriSHFT = 9, /* Tx Priority Queue Select */
  70. TxpriMASK = 0x00001E00,
  71. RxpriSHFT = 13, /* Rx Priority Queue Select */
  72. RxpriMASK = 0x0001E000,
  73. };
  74. enum { /* Configuration and Media Status */
  75. Bem = 0x00000001, /* Big Endian Mode */
  76. Ext125 = 0x00000002, /* External 125MHz reference Select */
  77. Bromdis = 0x00000004, /* Disable Boot ROM interface */
  78. Pesel = 0x00000008, /* Parity Error Detection Action */
  79. Exd = 0x00000010, /* Excessive Deferral Abort */
  80. Pow = 0x00000020, /* Program Out of Window Timer */
  81. Sb = 0x00000040, /* Single Back-off */
  82. Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
  83. Extstsen = 0x00000100, /* Extended Status Enable */
  84. Phydis = 0x00000200, /* Disable PHY */
  85. Phyrst = 0x00000400, /* Reset PHY */
  86. M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
  87. Data64en = 0x00001000, /* 64-bit Data Enable */
  88. Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
  89. T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
  90. Mwidis = 0x00008000, /* MWI Disable */
  91. Mrmdis = 0x00010000, /* MRM Disable */
  92. Tmrtest = 0x00020000, /* Timer Test Mode */
  93. Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
  94. Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
  95. Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
  96. Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
  97. Tbien = 0x01000000, /* Ten-Bit Interface Enable */
  98. Dupsts = 0x10000000, /* Full Duplex Status */
  99. Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
  100. Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
  101. Lnksts = 0x80000000, /* Link Status */
  102. };
  103. enum { /* MII/EEPROM Access */
  104. Eedi = 0x00000001, /* EEPROM Data In */
  105. Eedo = 0x00000002, /* EEPROM Data Out */
  106. Eeclk = 0x00000004, /* EEPROM Serial Clock */
  107. Eesel = 0x00000008, /* EEPROM Chip Select */
  108. Mdio = 0x00000010, /* MII Management Data */
  109. Mddir = 0x00000020, /* MII Management Direction */
  110. Mdc = 0x00000040, /* MII Management Clock */
  111. };
  112. enum { /* Interrupts */
  113. Rxok = 0x00000001, /* Rx OK */
  114. Rxdesc = 0x00000002, /* Rx Descriptor */
  115. Rxerr = 0x00000004, /* Rx Packet Error */
  116. Rxearly = 0x00000008, /* Rx Early Threshold */
  117. Rxidle = 0x00000010, /* Rx Idle */
  118. Rxorn = 0x00000020, /* Rx Overrun */
  119. Txok = 0x00000040, /* Tx Packet OK */
  120. Txdesc = 0x00000080, /* Tx Descriptor */
  121. Txerr = 0x00000100, /* Tx Packet Error */
  122. Txidle = 0x00000200, /* Tx Idle */
  123. Txurn = 0x00000400, /* Tx Underrun */
  124. Mib = 0x00000800, /* MIB Service */
  125. Swi = 0x00001000, /* Software Interrupt */
  126. Pme = 0x00002000, /* Power Management Event */
  127. Phy = 0x00004000, /* PHY Interrupt */
  128. Hibint = 0x00008000, /* High Bits Interrupt Set */
  129. Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
  130. Rtabt = 0x00020000, /* Received Target Abort */
  131. Rmabt = 0x00040000, /* Received Master Abort */
  132. Sserr = 0x00080000, /* Signalled System Error */
  133. Dperr = 0x00100000, /* Detected Parity Error */
  134. Rxrcmp = 0x00200000, /* Receive Reset Complete */
  135. Txrcmp = 0x00400000, /* Transmit Reset Complete */
  136. Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
  137. Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
  138. Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
  139. Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
  140. Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
  141. Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
  142. Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
  143. Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
  144. };
  145. enum { /* Interrupt Enable */
  146. Ien = 0x00000001, /* Interrupt Enable */
  147. };
  148. enum { /* Interrupt Holdoff */
  149. IhSHFT = 0, /* Interrupt Holdoff */
  150. IhMASK = 0x000000FF,
  151. Ihctl = 0x00000100, /* Interrupt Holdoff Control */
  152. };
  153. enum { /* Transmit Configuration */
  154. TxdrthSHFT = 0, /* Tx Drain Threshold */
  155. TxdrthMASK = 0x000000FF,
  156. FlthSHFT = 16, /* Tx Fill Threshold */
  157. FlthMASK = 0x0000FF00,
  158. Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
  159. MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
  160. MxdmaMASK = 0x00700000,
  161. Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
  162. Atp = 0x10000000, /* Automatic Transmit Padding */
  163. Mlb = 0x20000000, /* MAC Loopback */
  164. Hbi = 0x40000000, /* Heartbeat Ignore */
  165. Csi = 0x80000000, /* Carrier Sense Ignore */
  166. };
  167. enum { /* Receive Configuration */
  168. RxdrthSHFT = 1, /* Rx Drain Threshold */
  169. RxdrthMASK = 0x0000003E,
  170. Airl = 0x04000000, /* Accept In-Range Length Errored */
  171. Alp = 0x08000000, /* Accept Long Packets */
  172. Rxfd = 0x10000000, /* Receive Full Duplex */
  173. Stripcrc = 0x20000000, /* Strip CRC */
  174. Arp = 0x40000000, /* Accept Runt Packets */
  175. Aep = 0x80000000, /* Accept Errored Packets */
  176. };
  177. enum { /* Priority Queueing Control */
  178. Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
  179. Txfairen = 0x00000002, /* Transmit Fairness Enable */
  180. RxpqenSHFT = 2, /* Receive Priority Queue Enable */
  181. RxpqenMASK = 0x0000000C,
  182. };
  183. enum { /* Pause Control/Status */
  184. PscntSHFT = 0, /* Pause Counter Value */
  185. PscntMASK = 0x0000FFFF,
  186. Pstx = 0x00020000, /* Transmit Pause Frame */
  187. PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
  188. PsffloMASK = 0x000C0000,
  189. PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
  190. PsffhiMASK = 0x00300000,
  191. PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
  192. PsstloMASK = 0x00C00000,
  193. PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
  194. PssthiMASK = 0x03000000,
  195. Psrcvd = 0x08000000, /* Pause Frame Received */
  196. Psact = 0x10000000, /* Pause Active */
  197. Psda = 0x20000000, /* Pause on Destination Address */
  198. Psmcast = 0x40000000, /* Pause on Multicast */
  199. Psen = 0x80000000, /* Pause Enable */
  200. };
  201. enum { /* Receive Filter/Match Control */
  202. RfaddrSHFT = 0, /* Extended Register Address */
  203. RfaddrMASK = 0x000003FF,
  204. Ulm = 0x00080000, /* U/L bit mask */
  205. Uhen = 0x00100000, /* Unicast Hash Enable */
  206. Mhen = 0x00200000, /* Multicast Hash Enable */
  207. Aarp = 0x00400000, /* Accept ARP Packets */
  208. ApatSHFT = 23, /* Accept on Pattern Match */
  209. ApatMASK = 0x07800000,
  210. Apm = 0x08000000, /* Accept on Perfect Match */
  211. Aau = 0x10000000, /* Accept All Unicast */
  212. Aam = 0x20000000, /* Accept All Multicast */
  213. Aab = 0x40000000, /* Accept All Broadcast */
  214. Rfen = 0x80000000, /* Rx Filter Enable */
  215. };
  216. enum { /* Receive Filter/Match Data */
  217. RfdataSHFT = 0, /* Receive Filter Data */
  218. RfdataMASK = 0x0000FFFF,
  219. BmaskSHFT = 16, /* Byte Mask */
  220. BmaskMASK = 0x00030000,
  221. };
  222. enum { /* MIB Control */
  223. Wrn = 0x00000001, /* Warning Test Indicator */
  224. Frz = 0x00000002, /* Freeze All Counters */
  225. Aclr = 0x00000004, /* Clear All Counters */
  226. Mibs = 0x00000008, /* MIB Counter Strobe */
  227. };
  228. enum { /* MIB Data */
  229. Nmibd = 11, /* Number of MIB Data Registers */
  230. };
  231. enum { /* VLAN/IP Receive Control */
  232. Vtden = 0x00000001, /* VLAN Tag Detection Enable */
  233. Vtren = 0x00000002, /* VLAN Tag Removal Enable */
  234. Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
  235. Dutf = 0x00000008, /* Discard Untagged Frames */
  236. Ipen = 0x00000010, /* IP Checksum Enable */
  237. Ripe = 0x00000020, /* Reject IP Checksum Errors */
  238. Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
  239. Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
  240. };
  241. enum { /* VLAN/IP Transmit Control */
  242. Vgti = 0x00000001, /* VLAN Global Tag Insertion */
  243. Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
  244. Gchk = 0x00000004, /* Global Checksum Generation */
  245. Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
  246. };
  247. enum { /* VLAN Data */
  248. VtypeSHFT = 0, /* VLAN Type Field */
  249. VtypeMASK = 0x0000FFFF,
  250. VtciSHFT = 16, /* VLAN Tag Control Information */
  251. VtciMASK = 0xFFFF0000,
  252. };
  253. enum { /* Clockrun Control/Status */
  254. Clkrunen = 0x00000001, /* CLKRUN Enable */
  255. Pmeen = 0x00000100, /* PME Enable */
  256. Pmests = 0x00008000, /* PME Status */
  257. };
  258. typedef struct {
  259. u32int link; /* Link to the next descriptor */
  260. u32int bufptr; /* pointer to data Buffer */
  261. int cmdsts; /* Command/Status */
  262. int extsts; /* optional Extended Status */
  263. Block* bp; /* Block containing bufptr */
  264. u32int unused; /* pad to 64-bit */
  265. } Desc;
  266. enum { /* Common cmdsts bits */
  267. SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
  268. SizeSHFT = 0,
  269. Ok = 0x08000000, /* Packet OK */
  270. Crc = 0x10000000, /* Suppress/Include CRC */
  271. Intr = 0x20000000, /* Interrupt on ownership transfer */
  272. More = 0x40000000, /* not last descriptor in a packet */
  273. Own = 0x80000000, /* Descriptor Ownership */
  274. };
  275. enum { /* Transmit cmdsts bits */
  276. CcntMASK = 0x000F0000, /* Collision Count */
  277. CcntSHFT = 16,
  278. Ec = 0x00100000, /* Excessive Collisions */
  279. Owc = 0x00200000, /* Out of Window Collision */
  280. Ed = 0x00400000, /* Excessive Deferral */
  281. Td = 0x00800000, /* Transmit Deferred */
  282. Crs = 0x01000000, /* Carrier Sense Lost */
  283. Tfu = 0x02000000, /* Transmit FIFO Underrun */
  284. Txa = 0x04000000, /* Transmit Abort */
  285. };
  286. enum { /* Receive cmdsts bits */
  287. Irl = 0x00010000, /* In-Range Length Error */
  288. Lbp = 0x00020000, /* Loopback Packet */
  289. Fae = 0x00040000, /* Frame Alignment Error */
  290. Crce = 0x00080000, /* CRC Error */
  291. Ise = 0x00100000, /* Invalid Symbol Error */
  292. Runt = 0x00200000, /* Runt Packet Received */
  293. Long = 0x00400000, /* Too Long Packet Received */
  294. DestMASK = 0x01800000, /* Destination Class */
  295. DestSHFT = 23,
  296. Rxo = 0x02000000, /* Receive Overrun */
  297. Rxa = 0x04000000, /* Receive Aborted */
  298. };
  299. enum { /* extsts bits */
  300. EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
  301. EvtciSHFT = 0,
  302. Vpkt = 0x00010000, /* VLAN Packet */
  303. Ippkt = 0x00020000, /* IP Packet */
  304. Iperr = 0x00040000, /* IP Checksum Error */
  305. Tcppkt = 0x00080000, /* TCP Packet */
  306. Tcperr = 0x00100000, /* TCP Checksum Error */
  307. Udppkt = 0x00200000, /* UDP Packet */
  308. Udperr = 0x00400000, /* UDP Checksum Error */
  309. };
  310. enum {
  311. Nrd = 256,
  312. Nrb = 4*Nrd,
  313. Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
  314. Ntd = 128,
  315. };
  316. typedef struct Ctlr Ctlr;
  317. typedef struct Ctlr {
  318. int port;
  319. Pcidev* pcidev;
  320. Ctlr* next;
  321. int active;
  322. int id;
  323. int eepromsz; /* address size in bits */
  324. ushort* eeprom;
  325. int* nic;
  326. int cfg;
  327. int imr;
  328. QLock alock; /* attach */
  329. Lock ilock; /* init */
  330. void* alloc; /* base of per-Ctlr allocated data */
  331. Mii* mii;
  332. Lock rdlock; /* receive */
  333. Desc* rd;
  334. int nrd;
  335. int nrb;
  336. int rdx;
  337. int rxcfg;
  338. Lock tlock; /* transmit */
  339. Desc* td;
  340. int ntd;
  341. int tdh;
  342. int tdt;
  343. int ntq;
  344. int txcfg;
  345. int rxidle;
  346. uint mibd[Nmibd];
  347. int ec;
  348. int owc;
  349. int ed;
  350. int crs;
  351. int tfu;
  352. int txa;
  353. } Ctlr;
  354. #define csr32r(c, r) (*((c)->nic+((r)/4)))
  355. #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
  356. static Ctlr* dp83820ctlrhead;
  357. static Ctlr* dp83820ctlrtail;
  358. static Lock dp83820rblock; /* free receive Blocks */
  359. static Block* dp83820rbpool;
  360. static char* dp83820mibs[Nmibd] = {
  361. "RXErroredPkts",
  362. "RXFCSErrors",
  363. "RXMsdPktErrors",
  364. "RXFAErrors",
  365. "RXSymbolErrors",
  366. "RXFrameToLong",
  367. "RXIRLErrors",
  368. "RXBadOpcodes",
  369. "RXPauseFrames",
  370. "TXPauseFrames",
  371. "TXSQEErrors",
  372. };
  373. static int
  374. mdior(Ctlr* ctlr, int n)
  375. {
  376. int data, i, mear, r;
  377. mear = csr32r(ctlr, Mear);
  378. r = ~(Mdc|Mddir) & mear;
  379. data = 0;
  380. for(i = n-1; i >= 0; i--){
  381. if(csr32r(ctlr, Mear) & Mdio)
  382. data |= (1<<i);
  383. csr32w(ctlr, Mear, Mdc|r);
  384. csr32w(ctlr, Mear, r);
  385. }
  386. csr32w(ctlr, Mear, mear);
  387. return data;
  388. }
  389. static void
  390. mdiow(Ctlr* ctlr, int bits, int n)
  391. {
  392. int i, mear, r;
  393. mear = csr32r(ctlr, Mear);
  394. r = Mddir|(~Mdc & mear);
  395. for(i = n-1; i >= 0; i--){
  396. if(bits & (1<<i))
  397. r |= Mdio;
  398. else
  399. r &= ~Mdio;
  400. csr32w(ctlr, Mear, r);
  401. csr32w(ctlr, Mear, Mdc|r);
  402. }
  403. csr32w(ctlr, Mear, mear);
  404. }
  405. static int
  406. dp83820miimir(Mii* mii, int pa, int ra)
  407. {
  408. int data;
  409. Ctlr *ctlr;
  410. ctlr = mii->ctlr;
  411. /*
  412. * MII Management Interface Read.
  413. *
  414. * Preamble;
  415. * ST+OP+PA+RA;
  416. * LT + 16 data bits.
  417. */
  418. mdiow(ctlr, 0xFFFFFFFF, 32);
  419. mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
  420. data = mdior(ctlr, 18);
  421. if(data & 0x10000)
  422. return -1;
  423. return data & 0xFFFF;
  424. }
  425. static int
  426. dp83820miimiw(Mii* mii, int pa, int ra, int data)
  427. {
  428. Ctlr *ctlr;
  429. ctlr = mii->ctlr;
  430. /*
  431. * MII Management Interface Write.
  432. *
  433. * Preamble;
  434. * ST+OP+PA+RA+LT + 16 data bits;
  435. * Z.
  436. */
  437. mdiow(ctlr, 0xFFFFFFFF, 32);
  438. data &= 0xFFFF;
  439. data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
  440. mdiow(ctlr, data, 32);
  441. return 0;
  442. }
  443. static Block *
  444. dp83820rballoc(Desc* desc)
  445. {
  446. Block *bp;
  447. if(desc->bp == nil){
  448. ilock(&dp83820rblock);
  449. if((bp = dp83820rbpool) == nil){
  450. iunlock(&dp83820rblock);
  451. desc->bp = nil;
  452. desc->cmdsts = Own;
  453. return nil;
  454. }
  455. dp83820rbpool = bp->next;
  456. bp->next = nil;
  457. iunlock(&dp83820rblock);
  458. desc->bufptr = PCIWADDR(bp->rp);
  459. desc->bp = bp;
  460. }
  461. else{
  462. bp = desc->bp;
  463. bp->rp = bp->lim - Rbsz;
  464. bp->wp = bp->rp;
  465. }
  466. coherence();
  467. desc->cmdsts = Intr|Rbsz;
  468. return bp;
  469. }
  470. static void
  471. dp83820rbfree(Block *bp)
  472. {
  473. bp->rp = bp->lim - Rbsz;
  474. bp->wp = bp->rp;
  475. ilock(&dp83820rblock);
  476. bp->next = dp83820rbpool;
  477. dp83820rbpool = bp;
  478. iunlock(&dp83820rblock);
  479. }
  480. static void
  481. dp83820halt(Ctlr* ctlr)
  482. {
  483. int i, timeo;
  484. ilock(&ctlr->ilock);
  485. csr32w(ctlr, Imr, 0);
  486. csr32w(ctlr, Ier, 0);
  487. csr32w(ctlr, Cr, Rxd|Txd);
  488. for(timeo = 0; timeo < 1000; timeo++){
  489. if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
  490. break;
  491. microdelay(1);
  492. }
  493. csr32w(ctlr, Mibc, Frz);
  494. iunlock(&ctlr->ilock);
  495. if(ctlr->rd != nil){
  496. for(i = 0; i < ctlr->nrd; i++){
  497. if(ctlr->rd[i].bp == nil)
  498. continue;
  499. freeb(ctlr->rd[i].bp);
  500. ctlr->rd[i].bp = nil;
  501. }
  502. }
  503. if(ctlr->td != nil){
  504. for(i = 0; i < ctlr->ntd; i++){
  505. if(ctlr->td[i].bp == nil)
  506. continue;
  507. freeb(ctlr->td[i].bp);
  508. ctlr->td[i].bp = nil;
  509. }
  510. }
  511. }
  512. static void
  513. dp83820cfg(Ctlr* ctlr)
  514. {
  515. int cfg;
  516. /*
  517. * Don't know how to deal with a TBI yet.
  518. */
  519. if(ctlr->mii == nil)
  520. return;
  521. /*
  522. * The polarity of these bits is at the mercy
  523. * of the board designer.
  524. * The correct answer for all speed and duplex questions
  525. * should be to query the phy.
  526. */
  527. cfg = csr32r(ctlr, Cfg);
  528. if(!(cfg & Dupsts)){
  529. ctlr->rxcfg |= Rxfd;
  530. ctlr->txcfg |= Csi|Hbi;
  531. iprint("83820: full duplex, ");
  532. }
  533. else{
  534. ctlr->rxcfg &= ~Rxfd;
  535. ctlr->txcfg &= ~(Csi|Hbi);
  536. iprint("83820: half duplex, ");
  537. }
  538. csr32w(ctlr, Rxcfg, ctlr->rxcfg);
  539. csr32w(ctlr, Txcfg, ctlr->txcfg);
  540. switch(cfg & (Spdsts1000|Spdsts100)){
  541. case Spdsts1000: /* 100Mbps */
  542. default: /* 10Mbps */
  543. ctlr->cfg &= ~Mode1000;
  544. if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
  545. iprint("100Mb/s\n");
  546. else
  547. iprint("10Mb/s\n");
  548. break;
  549. case Spdsts100: /* 1Gbps */
  550. ctlr->cfg |= Mode1000;
  551. iprint("1Gb/s\n");
  552. break;
  553. }
  554. csr32w(ctlr, Cfg, ctlr->cfg);
  555. }
  556. static void
  557. dp83820init(Ether* edev)
  558. {
  559. int i;
  560. Ctlr *ctlr;
  561. Desc *desc;
  562. uchar *alloc;
  563. ctlr = edev->ctlr;
  564. dp83820halt(ctlr);
  565. /*
  566. * Receiver
  567. */
  568. alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
  569. ctlr->rd = (Desc*)alloc;
  570. alloc += ctlr->nrd*sizeof(Desc);
  571. memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
  572. ctlr->rdx = 0;
  573. for(i = 0; i < ctlr->nrd; i++){
  574. desc = &ctlr->rd[i];
  575. desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
  576. if(dp83820rballoc(desc) == nil)
  577. continue;
  578. }
  579. csr32w(ctlr, Rxdphi, 0);
  580. csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
  581. for(i = 0; i < Eaddrlen; i += 2){
  582. csr32w(ctlr, Rfcr, i);
  583. csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
  584. }
  585. csr32w(ctlr, Rfcr, Rfen|Aab|Apm);
  586. ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
  587. ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
  588. /*
  589. * Transmitter.
  590. */
  591. ctlr->td = (Desc*)alloc;
  592. memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
  593. ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
  594. for(i = 0; i < ctlr->ntd; i++){
  595. desc = &ctlr->td[i];
  596. desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
  597. }
  598. csr32w(ctlr, Txdphi, 0);
  599. csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
  600. ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
  601. ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
  602. ilock(&ctlr->ilock);
  603. dp83820cfg(ctlr);
  604. csr32w(ctlr, Mibc, Aclr);
  605. ctlr->imr |= Mib;
  606. csr32w(ctlr, Imr, ctlr->imr);
  607. /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
  608. csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
  609. csr32w(ctlr, Ier, Ien);
  610. csr32w(ctlr, Cr, Rxe|Txe);
  611. iunlock(&ctlr->ilock);
  612. }
  613. static void
  614. dp83820attach(Ether* edev)
  615. {
  616. Block *bp;
  617. Ctlr *ctlr;
  618. ctlr = edev->ctlr;
  619. qlock(&ctlr->alock);
  620. if(ctlr->alloc != nil){
  621. qunlock(&ctlr->alock);
  622. return;
  623. }
  624. if(waserror()){
  625. if(ctlr->mii != nil){
  626. free(ctlr->mii);
  627. ctlr->mii = nil;
  628. }
  629. if(ctlr->alloc != nil){
  630. free(ctlr->alloc);
  631. ctlr->alloc = nil;
  632. }
  633. qunlock(&ctlr->alock);
  634. nexterror();
  635. }
  636. if(!(ctlr->cfg & Tbien)){
  637. if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  638. error(Enomem);
  639. ctlr->mii->ctlr = ctlr;
  640. ctlr->mii->mir = dp83820miimir;
  641. ctlr->mii->miw = dp83820miimiw;
  642. if(mii(ctlr->mii, ~0) == 0)
  643. error("no PHY");
  644. ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
  645. ctlr->imr |= Phy;
  646. }
  647. ctlr->nrd = Nrd;
  648. ctlr->nrb = Nrb;
  649. ctlr->ntd = Ntd;
  650. ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
  651. if(ctlr->alloc == nil)
  652. error(Enomem);
  653. for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
  654. if((bp = allocb(Rbsz)) == nil)
  655. break;
  656. bp->free = dp83820rbfree;
  657. dp83820rbfree(bp);
  658. }
  659. dp83820init(edev);
  660. qunlock(&ctlr->alock);
  661. poperror();
  662. }
  663. static void
  664. dp83820transmit(Ether* edev)
  665. {
  666. Block *bp;
  667. Ctlr *ctlr;
  668. Desc *desc;
  669. int cmdsts, r, x;
  670. ctlr = edev->ctlr;
  671. ilock(&ctlr->tlock);
  672. bp = nil;
  673. for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
  674. desc = &ctlr->td[x];
  675. if((cmdsts = desc->cmdsts) & Own)
  676. break;
  677. if(!(cmdsts & Ok)){
  678. if(cmdsts & Ec)
  679. ctlr->ec++;
  680. if(cmdsts & Owc)
  681. ctlr->owc++;
  682. if(cmdsts & Ed)
  683. ctlr->ed++;
  684. if(cmdsts & Crs)
  685. ctlr->crs++;
  686. if(cmdsts & Tfu)
  687. ctlr->tfu++;
  688. if(cmdsts & Txa)
  689. ctlr->txa++;
  690. edev->oerrs++;
  691. }
  692. desc->bp->next = bp;
  693. bp = desc->bp;
  694. desc->bp = nil;
  695. ctlr->ntq--;
  696. }
  697. ctlr->tdh = x;
  698. if(bp != nil)
  699. freeblist(bp);
  700. x = ctlr->tdt;
  701. while(ctlr->ntq < (ctlr->ntd-1)){
  702. if((bp = qget(edev->oq)) == nil)
  703. break;
  704. desc = &ctlr->td[x];
  705. desc->bufptr = PCIWADDR(bp->rp);
  706. desc->bp = bp;
  707. ctlr->ntq++;
  708. coherence();
  709. desc->cmdsts = Own|Intr|BLEN(bp);
  710. x = NEXT(x, ctlr->ntd);
  711. }
  712. if(x != ctlr->tdt){
  713. ctlr->tdt = x;
  714. r = csr32r(ctlr, Cr);
  715. csr32w(ctlr, Cr, Txe|r);
  716. }
  717. iunlock(&ctlr->tlock);
  718. }
  719. static void
  720. dp83820interrupt(Ureg*, void* arg)
  721. {
  722. Block *bp;
  723. Ctlr *ctlr;
  724. Desc *desc;
  725. Ether *edev;
  726. int cmdsts, i, isr, r, x;
  727. edev = arg;
  728. ctlr = edev->ctlr;
  729. for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
  730. if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
  731. x = ctlr->rdx;
  732. desc = &ctlr->rd[x];
  733. while((cmdsts = desc->cmdsts) & Own){
  734. if((cmdsts & Ok) && desc->bp != nil){
  735. bp = desc->bp;
  736. desc->bp = nil;
  737. bp->wp += cmdsts & SizeMASK;
  738. etheriq(edev, bp, 1);
  739. }
  740. //else if(!(cmdsts & Ok)){
  741. // iprint("dp83820: rx %8.8uX:", cmdsts);
  742. // bp = desc->bp;
  743. // for(i = 0; i < 20; i++)
  744. // iprint(" %2.2uX", bp->rp[i]);
  745. // iprint("\n");
  746. //}
  747. dp83820rballoc(desc);
  748. x = NEXT(x, ctlr->nrd);
  749. desc = &ctlr->rd[x];
  750. }
  751. ctlr->rdx = x;
  752. if(isr & Rxidle){
  753. r = csr32r(ctlr, Cr);
  754. csr32w(ctlr, Cr, Rxe|r);
  755. ctlr->rxidle++;
  756. }
  757. isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
  758. }
  759. if(isr & Txurn){
  760. x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
  761. r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
  762. if(x < ((TxdrthMASK)>>TxdrthSHFT)
  763. && x < (2048/32 - r)){
  764. ctlr->txcfg &= ~TxdrthMASK;
  765. x++;
  766. ctlr->txcfg |= x<<TxdrthSHFT;
  767. csr32w(ctlr, Txcfg, ctlr->txcfg);
  768. }
  769. }
  770. if(isr & (Txurn|Txidle|Txdesc|Txok)){
  771. dp83820transmit(edev);
  772. isr &= ~(Txurn|Txidle|Txdesc|Txok);
  773. }
  774. if(isr & Mib){
  775. for(i = 0; i < Nmibd; i++){
  776. r = csr32r(ctlr, Mibd+(i*sizeof(int)));
  777. ctlr->mibd[i] += r & 0xFFFF;
  778. }
  779. isr &= ~Mib;
  780. }
  781. if((isr & Phy) && ctlr->mii != nil){
  782. ctlr->mii->mir(ctlr->mii, 1, Bmsr);
  783. print("phy: cfg %8.8uX bmsr %4.4uX\n",
  784. csr32r(ctlr, Cfg),
  785. ctlr->mii->mir(ctlr->mii, 1, Bmsr));
  786. dp83820cfg(ctlr);
  787. isr &= ~Phy;
  788. }
  789. if(isr)
  790. iprint("dp83820: isr %8.8uX\n", isr);
  791. }
  792. }
  793. static long
  794. dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
  795. {
  796. char *p;
  797. Ctlr *ctlr;
  798. int i, l, r;
  799. ctlr = edev->ctlr;
  800. edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
  801. edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
  802. edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
  803. edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
  804. if(n == 0)
  805. return 0;
  806. p = malloc(READSTR);
  807. l = 0;
  808. for(i = 0; i < Nmibd; i++){
  809. r = csr32r(ctlr, Mibd+(i*sizeof(int)));
  810. ctlr->mibd[i] += r & 0xFFFF;
  811. if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
  812. l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
  813. dp83820mibs[i], ctlr->mibd[i], r);
  814. }
  815. l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
  816. l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
  817. l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
  818. l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
  819. l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
  820. l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
  821. l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
  822. l += snprint(p+l, READSTR, "rom:");
  823. for(i = 0; i < 0x10; i++){
  824. if(i && ((i & 0x07) == 0))
  825. l += snprint(p+l, READSTR-l, "\n ");
  826. l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
  827. }
  828. l += snprint(p+l, READSTR-l, "\n");
  829. if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  830. l += snprint(p+l, READSTR, "phy:");
  831. for(i = 0; i < NMiiPhyr; i++){
  832. if(i && ((i & 0x07) == 0))
  833. l += snprint(p+l, READSTR-l, "\n ");
  834. r = miimir(ctlr->mii, i);
  835. l += snprint(p+l, READSTR-l, " %4.4uX", r);
  836. }
  837. snprint(p+l, READSTR-l, "\n");
  838. }
  839. n = readstr(offset, a, n, p);
  840. free(p);
  841. return n;
  842. }
  843. static void
  844. dp83820promiscuous(void* arg, int on)
  845. {
  846. USED(arg, on);
  847. }
  848. static int
  849. atc93c46r(Ctlr* ctlr, int address)
  850. {
  851. int data, i, mear, r, size;
  852. /*
  853. * Analog Technology, Inc. ATC93C46
  854. * or equivalent serial EEPROM.
  855. */
  856. mear = csr32r(ctlr, Mear);
  857. mear &= ~(Eesel|Eeclk|Eedo|Eedi);
  858. r = Eesel|mear;
  859. reread:
  860. csr32w(ctlr, Mear, r);
  861. data = 0x06;
  862. for(i = 3-1; i >= 0; i--){
  863. if(data & (1<<i))
  864. r |= Eedi;
  865. else
  866. r &= ~Eedi;
  867. csr32w(ctlr, Mear, r);
  868. csr32w(ctlr, Mear, Eeclk|r);
  869. microdelay(1);
  870. csr32w(ctlr, Mear, r);
  871. microdelay(1);
  872. }
  873. /*
  874. * First time through must work out the EEPROM size.
  875. */
  876. if((size = ctlr->eepromsz) == 0)
  877. size = 8;
  878. for(size = size-1; size >= 0; size--){
  879. if(address & (1<<size))
  880. r |= Eedi;
  881. else
  882. r &= ~Eedi;
  883. csr32w(ctlr, Mear, r);
  884. microdelay(1);
  885. csr32w(ctlr, Mear, Eeclk|r);
  886. microdelay(1);
  887. csr32w(ctlr, Mear, r);
  888. microdelay(1);
  889. if(!(csr32r(ctlr, Mear) & Eedo))
  890. break;
  891. }
  892. r &= ~Eedi;
  893. data = 0;
  894. for(i = 16-1; i >= 0; i--){
  895. csr32w(ctlr, Mear, Eeclk|r);
  896. microdelay(1);
  897. if(csr32r(ctlr, Mear) & Eedo)
  898. data |= (1<<i);
  899. csr32w(ctlr, Mear, r);
  900. microdelay(1);
  901. }
  902. csr32w(ctlr, Mear, mear);
  903. if(ctlr->eepromsz == 0){
  904. ctlr->eepromsz = 8-size;
  905. ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
  906. goto reread;
  907. }
  908. return data;
  909. }
  910. static int
  911. dp83820reset(Ctlr* ctlr)
  912. {
  913. int i, r;
  914. unsigned char sum;
  915. /*
  916. * Soft reset the controller;
  917. * read the EEPROM to get the initial settings
  918. * of the Cfg and Gpior bits which should be cleared by
  919. * the reset.
  920. */
  921. csr32w(ctlr, Cr, Rst);
  922. delay(1);
  923. while(csr32r(ctlr, Cr) & Rst)
  924. delay(1);
  925. atc93c46r(ctlr, 0);
  926. if(ctlr->eeprom == nil)
  927. return -1;
  928. sum = 0;
  929. for(i = 0; i < 0x0E; i++){
  930. r = atc93c46r(ctlr, i);
  931. ctlr->eeprom[i] = r;
  932. sum += r;
  933. sum += r>>8;
  934. }
  935. if(sum != 0){
  936. print("dp83820reset: bad EEPROM checksum\n");
  937. return -1;
  938. }
  939. #ifdef notdef
  940. csr32w(ctlr, Gpior, ctlr->eeprom[4]);
  941. cfg = Extstsen|Exd;
  942. r = csr32r(ctlr, Cfg);
  943. if(ctlr->eeprom[5] & 0x0001)
  944. cfg |= Ext125;
  945. if(ctlr->eeprom[5] & 0x0002)
  946. cfg |= M64addren;
  947. if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
  948. cfg |= Data64en;
  949. if(ctlr->eeprom[5] & 0x0008)
  950. cfg |= T64addren;
  951. if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
  952. cfg |= Mwidis;
  953. if(ctlr->eeprom[5] & 0x0020)
  954. cfg |= Mrmdis;
  955. if(ctlr->eeprom[5] & 0x0080)
  956. cfg |= Mode1000;
  957. if(ctlr->eeprom[5] & 0x0200)
  958. cfg |= Tbien|Mode1000;
  959. /*
  960. * What about RO bits we might have destroyed with Rst?
  961. * What about Exd, Tmrtest, Extstsen, Pintctl?
  962. * Why does it think it has detected a 64-bit bus when
  963. * it hasn't?
  964. */
  965. #else
  966. //r = csr32r(ctlr, Cfg);
  967. //r &= ~(Mode1000|T64addren|Data64en|M64addren);
  968. //csr32w(ctlr, Cfg, r);
  969. //csr32w(ctlr, Cfg, 0x2000);
  970. #endif /* notdef */
  971. ctlr->cfg = csr32r(ctlr, Cfg);
  972. print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
  973. ctlr->cfg &= ~(T64addren|Data64en|M64addren);
  974. csr32w(ctlr, Cfg, ctlr->cfg);
  975. csr32w(ctlr, Mibc, Aclr|Frz);
  976. return 0;
  977. }
  978. static void
  979. dp83820pci(void)
  980. {
  981. void *mem;
  982. Pcidev *p;
  983. Ctlr *ctlr;
  984. p = nil;
  985. while(p = pcimatch(p, 0, 0)){
  986. if(p->ccrb != 0x02 || p->ccru != 0)
  987. continue;
  988. switch((p->did<<16)|p->vid){
  989. default:
  990. continue;
  991. case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
  992. break;
  993. }
  994. mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
  995. if(mem == 0){
  996. print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
  997. continue;
  998. }
  999. ctlr = malloc(sizeof(Ctlr));
  1000. ctlr->port = p->mem[1].bar & ~0x0F;
  1001. ctlr->pcidev = p;
  1002. ctlr->id = (p->did<<16)|p->vid;
  1003. ctlr->nic = mem;
  1004. if(dp83820reset(ctlr)){
  1005. free(ctlr);
  1006. continue;
  1007. }
  1008. pcisetbme(p);
  1009. if(dp83820ctlrhead != nil)
  1010. dp83820ctlrtail->next = ctlr;
  1011. else
  1012. dp83820ctlrhead = ctlr;
  1013. dp83820ctlrtail = ctlr;
  1014. }
  1015. }
  1016. static int
  1017. dp83820pnp(Ether* edev)
  1018. {
  1019. int i;
  1020. Ctlr *ctlr;
  1021. uchar ea[Eaddrlen];
  1022. if(dp83820ctlrhead == nil)
  1023. dp83820pci();
  1024. /*
  1025. * Any adapter matches if no edev->port is supplied,
  1026. * otherwise the ports must match.
  1027. */
  1028. for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
  1029. if(ctlr->active)
  1030. continue;
  1031. if(edev->port == 0 || edev->port == ctlr->port){
  1032. ctlr->active = 1;
  1033. break;
  1034. }
  1035. }
  1036. if(ctlr == nil)
  1037. return -1;
  1038. edev->ctlr = ctlr;
  1039. edev->port = ctlr->port;
  1040. edev->irq = ctlr->pcidev->intl;
  1041. edev->tbdf = ctlr->pcidev->tbdf;
  1042. edev->mbps = 1000;
  1043. /*
  1044. * Check if the adapter's station address is to be overridden.
  1045. * If not, read it from the EEPROM and set in ether->ea prior to
  1046. * loading the station address in the hardware.
  1047. */
  1048. memset(ea, 0, Eaddrlen);
  1049. if(memcmp(ea, edev->ea, Eaddrlen) == 0){
  1050. for(i = 0; i < Eaddrlen/2; i++){
  1051. edev->ea[2*i] = ctlr->eeprom[0x0C-i];
  1052. edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
  1053. }
  1054. }
  1055. edev->attach = dp83820attach;
  1056. edev->transmit = dp83820transmit;
  1057. edev->interrupt = dp83820interrupt;
  1058. edev->ifstat = dp83820ifstat;
  1059. edev->arg = edev;
  1060. edev->promiscuous = dp83820promiscuous;
  1061. return 0;
  1062. }
  1063. void
  1064. etherdp83820link(void)
  1065. {
  1066. addethercard("DP83820", dp83820pnp);
  1067. }