etherelnk3.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144
  1. /*
  2. * Etherlink III, Fast EtherLink and Fast EtherLink XL adapters.
  3. * To do:
  4. * check robustness in the face of errors (e.g. busmaster & rxUnderrun);
  5. * RxEarly and busmaster;
  6. * autoSelect;
  7. * PCI latency timer and master enable;
  8. * errata list;
  9. * rewrite all initialisation.
  10. */
  11. #include "u.h"
  12. #include "../port/lib.h"
  13. #include "mem.h"
  14. #include "dat.h"
  15. #include "fns.h"
  16. #include "io.h"
  17. #include "../port/error.h"
  18. #include "../port/netif.h"
  19. #include "etherif.h"
  20. #define XCVRDEBUG if(0)print
  21. enum {
  22. IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
  23. };
  24. enum { /* all windows */
  25. CommandR = 0x000E,
  26. IntStatusR = 0x000E,
  27. };
  28. enum { /* Commands */
  29. GlobalReset = 0x0000,
  30. SelectRegisterWindow = 0x0001,
  31. EnableDcConverter = 0x0002,
  32. RxDisable = 0x0003,
  33. RxEnable = 0x0004,
  34. RxReset = 0x0005,
  35. Stall = 0x0006, /* 3C90x */
  36. TxDone = 0x0007,
  37. RxDiscard = 0x0008,
  38. TxEnable = 0x0009,
  39. TxDisable = 0x000A,
  40. TxReset = 0x000B,
  41. RequestInterrupt = 0x000C,
  42. AcknowledgeInterrupt = 0x000D,
  43. SetInterruptEnable = 0x000E,
  44. SetIndicationEnable = 0x000F, /* SetReadZeroMask */
  45. SetRxFilter = 0x0010,
  46. SetRxEarlyThresh = 0x0011,
  47. SetTxAvailableThresh = 0x0012,
  48. SetTxStartThresh = 0x0013,
  49. StartDma = 0x0014, /* initiate busmaster operation */
  50. StatisticsEnable = 0x0015,
  51. StatisticsDisable = 0x0016,
  52. DisableDcConverter = 0x0017,
  53. SetTxReclaimThresh = 0x0018, /* PIO-only adapters */
  54. PowerUp = 0x001B, /* not all adapters */
  55. PowerDownFull = 0x001C, /* not all adapters */
  56. PowerAuto = 0x001D, /* not all adapters */
  57. };
  58. enum { /* (Global|Rx|Tx)Reset command bits */
  59. tpAuiReset = 0x0001, /* 10BaseT and AUI transceivers */
  60. endecReset = 0x0002, /* internal Ethernet encoder/decoder */
  61. networkReset = 0x0004, /* network interface logic */
  62. fifoReset = 0x0008, /* FIFO control logic */
  63. aismReset = 0x0010, /* autoinitialise state-machine logic */
  64. hostReset = 0x0020, /* bus interface logic */
  65. dmaReset = 0x0040, /* bus master logic */
  66. vcoReset = 0x0080, /* on-board 10Mbps VCO */
  67. updnReset = 0x0100, /* upload/download (Rx/TX) logic */
  68. resetMask = 0x01FF,
  69. };
  70. enum { /* Stall command bits */
  71. upStall = 0x0000,
  72. upUnStall = 0x0001,
  73. dnStall = 0x0002,
  74. dnUnStall = 0x0003,
  75. };
  76. enum { /* SetRxFilter command bits */
  77. receiveIndividual = 0x0001, /* match station address */
  78. receiveMulticast = 0x0002,
  79. receiveBroadcast = 0x0004,
  80. receiveAllFrames = 0x0008, /* promiscuous */
  81. };
  82. enum { /* StartDma command bits */
  83. Upload = 0x0000, /* transfer data from adapter to memory */
  84. Download = 0x0001, /* transfer data from memory to adapter */
  85. };
  86. enum { /* IntStatus bits */
  87. interruptLatch = 0x0001,
  88. hostError = 0x0002, /* Adapter Failure */
  89. txComplete = 0x0004,
  90. txAvailable = 0x0008,
  91. rxComplete = 0x0010,
  92. rxEarly = 0x0020,
  93. intRequested = 0x0040,
  94. updateStats = 0x0080,
  95. transferInt = 0x0100, /* Bus Master Transfer Complete */
  96. dnComplete = 0x0200,
  97. upComplete = 0x0400,
  98. busMasterInProgress = 0x0800,
  99. commandInProgress = 0x1000,
  100. interruptMask = 0x07FE,
  101. };
  102. #define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a))
  103. #define STATUS(port) ins((port)+IntStatusR)
  104. enum { /* Window 0 - setup */
  105. Wsetup = 0x0000,
  106. /* registers */
  107. ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */
  108. ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */
  109. ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */
  110. AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */
  111. ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */
  112. EepromCommand = 0x000A,
  113. EepromData = 0x000C,
  114. /* AddressConfig Bits */
  115. autoSelect9 = 0x0080,
  116. xcvrMask9 = 0xC000,
  117. /* ConfigControl bits */
  118. Ena = 0x0001,
  119. base10TAvailable9 = 0x0200,
  120. coaxAvailable9 = 0x1000,
  121. auiAvailable9 = 0x2000,
  122. /* EepromCommand bits */
  123. EepromReadRegister = 0x0080,
  124. EepromReadOffRegister = 0x00B0,
  125. EepromRead8bRegister = 0x0230,
  126. EepromBusy = 0x8000,
  127. };
  128. #define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
  129. #define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
  130. #define EEPROMDATA(port) ins((port)+EepromData)
  131. enum { /* Window 1 - operating set */
  132. Wop = 0x0001,
  133. /* registers */
  134. Fifo = 0x0000,
  135. RxError = 0x0004, /* 3C59[0257] only */
  136. RxStatus = 0x0008,
  137. TIMER = 0x000A,
  138. TxStatus = 0x000B,
  139. TxFree = 0x000C,
  140. /* RxError bits */
  141. rxOverrun = 0x0001,
  142. runtFrame = 0x0002,
  143. alignmentError = 0x0004, /* Framing */
  144. crcError = 0x0008,
  145. oversizedFrame = 0x0010,
  146. dribbleBits = 0x0080,
  147. /* RxStatus bits */
  148. rxBytes = 0x1FFF, /* 3C59[0257] mask */
  149. rxBytes9 = 0x07FF, /* 3C5[078]9 mask */
  150. rxError9 = 0x3800, /* 3C5[078]9 error mask */
  151. rxOverrun9 = 0x0000,
  152. oversizedFrame9 = 0x0800,
  153. dribbleBits9 = 0x1000,
  154. runtFrame9 = 0x1800,
  155. alignmentError9 = 0x2000, /* Framing */
  156. crcError9 = 0x2800,
  157. rxError = 0x4000,
  158. rxIncomplete = 0x8000,
  159. /* TxStatus Bits */
  160. txStatusOverflow = 0x0004,
  161. maxCollisions = 0x0008,
  162. txUnderrun = 0x0010,
  163. txJabber = 0x0020,
  164. interruptRequested = 0x0040,
  165. txStatusComplete = 0x0080,
  166. };
  167. enum { /* Window 2 - station address */
  168. Wstation = 0x0002,
  169. ResetOp905B = 0x000C,
  170. };
  171. enum { /* Window 3 - FIFO management */
  172. Wfifo = 0x0003,
  173. /* registers */
  174. InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */
  175. OtherInt = 0x0004, /* 3C59[0257] */
  176. RomControl = 0x0006, /* 3C509B, 3C59[27] */
  177. MacControl = 0x0006, /* 3C59[0257] */
  178. ResetOptions = 0x0008, /* 3C59[0257] */
  179. MediaOptions = 0x0008, /* 3C905B */
  180. RxFree = 0x000A,
  181. /* InternalConfig bits */
  182. disableBadSsdDetect = 0x00000100,
  183. ramLocation = 0x00000200, /* 0 external, 1 internal */
  184. ramPartition5to3 = 0x00000000,
  185. ramPartition3to1 = 0x00010000,
  186. ramPartition1to1 = 0x00020000,
  187. ramPartition3to5 = 0x00030000,
  188. ramPartitionMask = 0x00030000,
  189. xcvr10BaseT = 0x00000000,
  190. xcvrAui = 0x00100000, /* 10BASE5 */
  191. xcvr10Base2 = 0x00300000,
  192. xcvr100BaseTX = 0x00400000,
  193. xcvr100BaseFX = 0x00500000,
  194. xcvrMii = 0x00600000,
  195. xcvrMask = 0x00700000,
  196. autoSelect = 0x01000000,
  197. /* MacControl bits */
  198. deferExtendEnable = 0x0001,
  199. deferTIMERSelect = 0x001E, /* mask */
  200. fullDuplexEnable = 0x0020,
  201. allowLargePackets = 0x0040,
  202. extendAfterCollision = 0x0080, /* 3C90xB */
  203. flowControlEnable = 0x0100, /* 3C90xB */
  204. vltEnable = 0x0200, /* 3C90xB */
  205. /* ResetOptions bits */
  206. baseT4Available = 0x0001,
  207. baseTXAvailable = 0x0002,
  208. baseFXAvailable = 0x0004,
  209. base10TAvailable = 0x0008,
  210. coaxAvailable = 0x0010,
  211. auiAvailable = 0x0020,
  212. miiConnector = 0x0040,
  213. };
  214. enum { /* Window 4 - diagnostic */
  215. Wdiagnostic = 0x0004,
  216. /* registers */
  217. VcoDiagnostic = 0x0002,
  218. FifoDiagnostic = 0x0004,
  219. NetworkDiagnostic = 0x0006,
  220. PhysicalMgmt = 0x0008,
  221. MediaStatus = 0x000A,
  222. BadSSD = 0x000C,
  223. UpperBytesOk = 0x000D,
  224. /* FifoDiagnostic bits */
  225. txOverrun = 0x0400,
  226. rxUnderrun = 0x2000,
  227. receiving = 0x8000,
  228. /* PhysicalMgmt bits */
  229. mgmtClk = 0x0001,
  230. mgmtData = 0x0002,
  231. mgmtDir = 0x0004,
  232. cat5LinkTestDefeat = 0x8000,
  233. /* MediaStatus bits */
  234. dataRate100 = 0x0002,
  235. crcStripDisable = 0x0004,
  236. enableSqeStats = 0x0008,
  237. collisionDetect = 0x0010,
  238. carrierSense = 0x0020,
  239. jabberGuardEnable = 0x0040,
  240. linkBeatEnable = 0x0080,
  241. jabberDetect = 0x0200,
  242. polarityReversed = 0x0400,
  243. linkBeatDetect = 0x0800,
  244. txInProg = 0x1000,
  245. dcConverterEnabled = 0x4000,
  246. auiDisable = 0x8000, /* 10BaseT transceiver selected */
  247. };
  248. enum { /* Window 5 - internal state */
  249. Wstate = 0x0005,
  250. /* registers */
  251. TxStartThresh = 0x0000,
  252. TxAvailableThresh = 0x0002,
  253. RxEarlyThresh = 0x0006,
  254. RxFilter = 0x0008,
  255. InterruptEnable = 0x000A,
  256. IndicationEnable = 0x000C,
  257. };
  258. enum { /* Window 6 - statistics */
  259. Wstatistics = 0x0006,
  260. /* registers */
  261. CarrierLost = 0x0000,
  262. SqeErrors = 0x0001,
  263. MultipleColls = 0x0002,
  264. SingleCollFrames = 0x0003,
  265. LateCollisions = 0x0004,
  266. RxOverruns = 0x0005,
  267. FramesXmittedOk = 0x0006,
  268. FramesRcvdOk = 0x0007,
  269. FramesDeferred = 0x0008,
  270. UpperFramesOk = 0x0009,
  271. BytesRcvdOk = 0x000A,
  272. BytesXmittedOk = 0x000C,
  273. };
  274. enum { /* Window 7 - bus master operations */
  275. Wmaster = 0x0007,
  276. /* registers */
  277. MasterAddress = 0x0000,
  278. MasterLen = 0x0006,
  279. MasterStatus = 0x000C,
  280. /* MasterStatus bits */
  281. masterAbort = 0x0001,
  282. targetAbort = 0x0002,
  283. targetRetry = 0x0004,
  284. targetDisc = 0x0008,
  285. masterDownload = 0x1000,
  286. masterUpload = 0x4000,
  287. masterInProgress = 0x8000,
  288. masterMask = 0xD00F,
  289. };
  290. enum { /* 3C90x extended register set */
  291. TIMER905 = 0x001A, /* 8-bits */
  292. TxStatus905 = 0x001B, /* 8-bits */
  293. PktStatus = 0x0020, /* 32-bits */
  294. DnListPtr = 0x0024, /* 32-bits, 8-byte aligned */
  295. FragAddr = 0x0028, /* 32-bits */
  296. FragLen = 0x002C, /* 16-bits */
  297. ListOffset = 0x002E, /* 8-bits */
  298. TxFreeThresh = 0x002F, /* 8-bits */
  299. UpPktStatus = 0x0030, /* 32-bits */
  300. FreeTIMER = 0x0034, /* 16-bits */
  301. UpListPtr = 0x0038, /* 32-bits, 8-byte aligned */
  302. /* PktStatus bits */
  303. fragLast = 0x00000001,
  304. dnCmplReq = 0x00000002,
  305. dnStalled = 0x00000004,
  306. upCompleteX = 0x00000008,
  307. dnCompleteX = 0x00000010,
  308. upRxEarlyEnable = 0x00000020,
  309. armCountdown = 0x00000040,
  310. dnInProg = 0x00000080,
  311. counterSpeed = 0x00000010, /* 0 3.2uS, 1 320nS */
  312. countdownMode = 0x00000020,
  313. /* UpPktStatus bits (dpd->control) */
  314. upPktLenMask = 0x00001FFF,
  315. upStalled = 0x00002000,
  316. upError = 0x00004000,
  317. upPktComplete = 0x00008000,
  318. upOverrun = 0x00010000, /* RxError<<16 */
  319. upRuntFrame = 0x00020000,
  320. upAlignmentError = 0x00040000,
  321. upCRCError = 0x00080000,
  322. upOversizedFrame = 0x00100000,
  323. upDribbleBits = 0x00800000,
  324. upOverflow = 0x01000000,
  325. dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */
  326. updnLastFrag = 0x80000000, /* (dpd->len) */
  327. Nup = 32,
  328. Ndn = 64,
  329. };
  330. /*
  331. * Up/Dn Packet Descriptors.
  332. * The hardware info (np, control, addr, len) must be 8-byte aligned
  333. * and this structure size must be a multiple of 8.
  334. */
  335. typedef struct Pd Pd;
  336. typedef struct Pd {
  337. ulong np; /* next pointer */
  338. ulong control; /* FSH or UpPktStatus */
  339. ulong addr;
  340. ulong len;
  341. Pd* next;
  342. Block* bp;
  343. } Pd;
  344. typedef struct Ctlr Ctlr;
  345. typedef struct Ctlr {
  346. int port;
  347. Pcidev* pcidev;
  348. int irq;
  349. Ctlr* next;
  350. int active;
  351. int did;
  352. Lock wlock; /* window access */
  353. int attached;
  354. int busmaster;
  355. Block* rbp; /* receive buffer */
  356. Block* txbp; /* FIFO -based transmission */
  357. int txthreshold;
  358. int txbusy;
  359. int nup; /* full-busmaster -based reception */
  360. void* upbase;
  361. Pd* upr;
  362. Pd* uphead;
  363. int ndn; /* full-busmaster -based transmission */
  364. void* dnbase;
  365. Pd* dnr;
  366. Pd* dnhead;
  367. Pd* dntail;
  368. int dnq;
  369. long interrupts; /* statistics */
  370. long bogusinterrupts;
  371. long timer[2];
  372. long stats[BytesRcvdOk+3];
  373. int upqmax;
  374. int upqmaxhw;
  375. ulong upinterrupts;
  376. ulong upqueued;
  377. ulong upstalls;
  378. int dnqmax;
  379. int dnqmaxhw;
  380. ulong dninterrupts;
  381. ulong dnqueued;
  382. int xcvr; /* transceiver type */
  383. int eepromcmd; /* EEPROM read command */
  384. int rxstatus9; /* old-style RxStatus register */
  385. int rxearly; /* RxEarlyThreshold */
  386. int ts; /* threshold shift */
  387. int upenabled;
  388. int dnenabled;
  389. ulong cbfnpa; /* CardBus functions */
  390. ulong* cbfn;
  391. } Ctlr;
  392. static Ctlr* ctlrhead;
  393. static Ctlr* ctlrtail;
  394. static void
  395. init905(Ctlr* ctlr)
  396. {
  397. Block *bp;
  398. Pd *pd, *prev;
  399. /*
  400. * Create rings for the receive and transmit sides.
  401. * Take care with alignment:
  402. * make sure ring base is 8-byte aligned;
  403. * make sure each entry is 8-byte aligned.
  404. */
  405. ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd));
  406. if(ctlr->upbase == nil)
  407. error(Enomem);
  408. ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
  409. prev = ctlr->upr;
  410. for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
  411. pd->np = PADDR(&prev->np);
  412. pd->control = 0;
  413. bp = iallocb(sizeof(Etherpkt));
  414. if(bp == nil)
  415. panic("can't allocate ethernet receive ring");
  416. pd->addr = PADDR(bp->rp);
  417. pd->len = updnLastFrag|sizeof(Etherpkt);
  418. pd->next = prev;
  419. prev = pd;
  420. pd->bp = bp;
  421. }
  422. ctlr->uphead = ctlr->upr;
  423. ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
  424. if(ctlr->dnbase == nil) {
  425. free(ctlr->upbase);
  426. error(Enomem);
  427. }
  428. ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
  429. prev = ctlr->dnr;
  430. for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
  431. pd->next = prev;
  432. prev = pd;
  433. }
  434. ctlr->dnhead = ctlr->dnr;
  435. ctlr->dntail = ctlr->dnr;
  436. ctlr->dnq = 0;
  437. }
  438. static Block*
  439. rbpalloc(Block* (*f)(int))
  440. {
  441. Block *bp;
  442. ulong addr;
  443. /*
  444. * The receive buffers must be on a 32-byte
  445. * boundary for EISA busmastering.
  446. */
  447. if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
  448. addr = (ulong)bp->base;
  449. addr = ROUNDUP(addr, 32);
  450. bp->rp = (uchar*)addr;
  451. }
  452. return bp;
  453. }
  454. static uchar*
  455. startdma(Ether* ether, ulong address)
  456. {
  457. int port, status, w;
  458. uchar *wp;
  459. port = ether->port;
  460. w = (STATUS(port)>>13) & 0x07;
  461. COMMAND(port, SelectRegisterWindow, Wmaster);
  462. wp = KADDR(inl(port+MasterAddress));
  463. status = ins(port+MasterStatus);
  464. if(status & (masterInProgress|targetAbort|masterAbort))
  465. print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
  466. outs(port+MasterStatus, masterMask);
  467. outl(port+MasterAddress, address);
  468. outs(port+MasterLen, sizeof(Etherpkt));
  469. COMMAND(port, StartDma, Upload);
  470. COMMAND(port, SelectRegisterWindow, w);
  471. return wp;
  472. }
  473. static void
  474. promiscuous(void* arg, int on)
  475. {
  476. int filter, port;
  477. Ether *ether;
  478. ether = (Ether*)arg;
  479. port = ether->port;
  480. filter = receiveBroadcast|receiveIndividual;
  481. if(ether->nmaddr)
  482. filter |= receiveMulticast;
  483. if(on)
  484. filter |= receiveAllFrames;
  485. COMMAND(port, SetRxFilter, filter);
  486. }
  487. static void
  488. multicast(void* arg, uchar *addr, int on)
  489. {
  490. int filter, port;
  491. Ether *ether;
  492. USED(addr, on);
  493. ether = (Ether*)arg;
  494. port = ether->port;
  495. filter = receiveBroadcast|receiveIndividual;
  496. if(ether->nmaddr)
  497. filter |= receiveMulticast;
  498. if(ether->prom)
  499. filter |= receiveAllFrames;
  500. COMMAND(port, SetRxFilter, filter);
  501. }
  502. /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
  503. static void
  504. intrackcb(ulong *cbfn)
  505. {
  506. cbfn[1] = 0x8000;
  507. }
  508. static void
  509. attach(Ether* ether)
  510. {
  511. int port, x;
  512. Ctlr *ctlr;
  513. ctlr = ether->ctlr;
  514. ilock(&ctlr->wlock);
  515. if(ctlr->attached){
  516. iunlock(&ctlr->wlock);
  517. return;
  518. }
  519. port = ether->port;
  520. /*
  521. * Set the receiver packet filter for this and broadcast addresses,
  522. * set the interrupt masks for all interrupts, enable the receiver
  523. * and transmitter.
  524. */
  525. promiscuous(ether, ether->prom);
  526. x = interruptMask;
  527. if(ctlr->busmaster == 1)
  528. x &= ~(rxEarly|rxComplete);
  529. else{
  530. if(ctlr->dnenabled)
  531. x &= ~transferInt;
  532. if(ctlr->upenabled)
  533. x &= ~(rxEarly|rxComplete);
  534. }
  535. COMMAND(port, SetIndicationEnable, x);
  536. COMMAND(port, SetInterruptEnable, x);
  537. COMMAND(port, RxEnable, 0);
  538. COMMAND(port, TxEnable, 0);
  539. /*
  540. * If this is a CardBus card, acknowledge any interrupts.
  541. */
  542. if(ctlr->cbfn != nil)
  543. intrackcb(ctlr->cbfn);
  544. /*
  545. * Prime the busmaster channel for receiving directly into a
  546. * receive packet buffer if necessary.
  547. */
  548. if(ctlr->busmaster == 1)
  549. startdma(ether, PADDR(ctlr->rbp->rp));
  550. else{
  551. if(ctlr->upenabled)
  552. outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
  553. }
  554. ctlr->attached = 1;
  555. iunlock(&ctlr->wlock);
  556. }
  557. static void
  558. statistics(Ether* ether)
  559. {
  560. int port, i, u, w;
  561. Ctlr *ctlr;
  562. port = ether->port;
  563. ctlr = ether->ctlr;
  564. /*
  565. * 3C59[27] require a read between a PIO write and
  566. * reading a statistics register.
  567. */
  568. w = (STATUS(port)>>13) & 0x07;
  569. COMMAND(port, SelectRegisterWindow, Wstatistics);
  570. STATUS(port);
  571. for(i = 0; i < UpperFramesOk; i++)
  572. ctlr->stats[i] += inb(port+i) & 0xFF;
  573. u = inb(port+UpperFramesOk) & 0xFF;
  574. ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
  575. ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
  576. ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
  577. ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
  578. switch(ctlr->xcvr){
  579. case xcvrMii:
  580. case xcvr100BaseTX:
  581. case xcvr100BaseFX:
  582. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  583. STATUS(port);
  584. ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
  585. break;
  586. }
  587. COMMAND(port, SelectRegisterWindow, w);
  588. }
  589. static void
  590. txstart(Ether* ether)
  591. {
  592. int port, len;
  593. Ctlr *ctlr;
  594. Block *bp;
  595. port = ether->port;
  596. ctlr = ether->ctlr;
  597. /*
  598. * Attempt to top-up the transmit FIFO. If there's room simply
  599. * stuff in the packet length (unpadded to a dword boundary), the
  600. * packet data (padded) and remove the packet from the queue.
  601. * If there's no room post an interrupt for when there is.
  602. * This routine is called both from the top level and from interrupt
  603. * level and expects to be called with ctlr->wlock already locked
  604. * and the correct register window (Wop) in place.
  605. */
  606. for(;;){
  607. if(ctlr->txbp){
  608. bp = ctlr->txbp;
  609. ctlr->txbp = 0;
  610. }
  611. else{
  612. bp = qget(ether->oq);
  613. if(bp == nil)
  614. break;
  615. }
  616. len = ROUNDUP(BLEN(bp), 4);
  617. if(len+4 <= ins(port+TxFree)){
  618. outl(port+Fifo, BLEN(bp));
  619. outsl(port+Fifo, bp->rp, len/4);
  620. freeb(bp);
  621. ether->outpackets++;
  622. }
  623. else{
  624. ctlr->txbp = bp;
  625. if(ctlr->txbusy == 0){
  626. ctlr->txbusy = 1;
  627. COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
  628. }
  629. break;
  630. }
  631. }
  632. }
  633. static void
  634. txstart905(Ether* ether)
  635. {
  636. Ctlr *ctlr;
  637. int port, stalled, timeo;
  638. Block *bp;
  639. Pd *pd;
  640. ctlr = ether->ctlr;
  641. port = ether->port;
  642. /*
  643. * Free any completed packets.
  644. */
  645. pd = ctlr->dntail;
  646. while(ctlr->dnq){
  647. if(PADDR(&pd->np) == inl(port+DnListPtr))
  648. break;
  649. if(pd->bp){
  650. freeb(pd->bp);
  651. pd->bp = nil;
  652. }
  653. ctlr->dnq--;
  654. pd = pd->next;
  655. }
  656. ctlr->dntail = pd;
  657. stalled = 0;
  658. while(ctlr->dnq < (ctlr->ndn-1)){
  659. bp = qget(ether->oq);
  660. if(bp == nil)
  661. break;
  662. pd = ctlr->dnhead->next;
  663. pd->np = 0;
  664. pd->control = dnIndicate|BLEN(bp);
  665. pd->addr = PADDR(bp->rp);
  666. pd->len = updnLastFrag|BLEN(bp);
  667. pd->bp = bp;
  668. if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
  669. COMMAND(port, Stall, dnStall);
  670. for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
  671. ;
  672. if(timeo == 0)
  673. print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
  674. stalled = 1;
  675. }
  676. coherence();
  677. ctlr->dnhead->np = PADDR(&pd->np);
  678. ctlr->dnhead->control &= ~dnIndicate;
  679. ctlr->dnhead = pd;
  680. if(ctlr->dnq == 0)
  681. ctlr->dntail = pd;
  682. ctlr->dnq++;
  683. ctlr->dnqueued++;
  684. }
  685. if(ctlr->dnq > ctlr->dnqmax)
  686. ctlr->dnqmax = ctlr->dnq;
  687. /*
  688. * If the adapter is not currently processing anything
  689. * and there is something on the queue, start it processing.
  690. */
  691. if(inl(port+DnListPtr) == 0 && ctlr->dnq)
  692. outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
  693. if(stalled)
  694. COMMAND(port, Stall, dnUnStall);
  695. }
  696. static void
  697. transmit(Ether* ether)
  698. {
  699. Ctlr *ctlr;
  700. int port, w;
  701. port = ether->port;
  702. ctlr = ether->ctlr;
  703. ilock(&ctlr->wlock);
  704. if(ctlr->dnenabled)
  705. txstart905(ether);
  706. else{
  707. w = (STATUS(port)>>13) & 0x07;
  708. COMMAND(port, SelectRegisterWindow, Wop);
  709. txstart(ether);
  710. COMMAND(port, SelectRegisterWindow, w);
  711. }
  712. iunlock(&ctlr->wlock);
  713. }
  714. static void
  715. receive905(Ether* ether)
  716. {
  717. Ctlr *ctlr;
  718. int len, port, q;
  719. Pd *pd;
  720. Block *bp;
  721. ctlr = ether->ctlr;
  722. port = ether->port;
  723. if(inl(port+UpPktStatus) & upStalled)
  724. ctlr->upstalls++;
  725. q = 0;
  726. for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
  727. if(pd->control & upError){
  728. if(pd->control & upOverrun)
  729. ether->overflows++;
  730. if(pd->control & (upOversizedFrame|upRuntFrame))
  731. ether->buffs++;
  732. if(pd->control & upAlignmentError)
  733. ether->frames++;
  734. if(pd->control & upCRCError)
  735. ether->crcs++;
  736. }
  737. else if(bp = iallocb(sizeof(Etherpkt)+4)){
  738. len = pd->control & rxBytes;
  739. pd->bp->wp = pd->bp->rp+len;
  740. etheriq(ether, pd->bp, 1);
  741. pd->bp = bp;
  742. pd->addr = PADDR(bp->rp);
  743. coherence();
  744. }
  745. pd->control = 0;
  746. COMMAND(port, Stall, upUnStall);
  747. q++;
  748. }
  749. ctlr->uphead = pd;
  750. ctlr->upqueued += q;
  751. if(q > ctlr->upqmax)
  752. ctlr->upqmax = q;
  753. }
  754. static void
  755. receive(Ether* ether)
  756. {
  757. int len, port, rxerror, rxstatus;
  758. Ctlr *ctlr;
  759. Block *bp;
  760. port = ether->port;
  761. ctlr = ether->ctlr;
  762. while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
  763. if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
  764. break;
  765. /*
  766. * If there was an error, log it and continue.
  767. * Unfortunately the 3C5[078]9 has the error info in the status register
  768. * and the 3C59[0257] implement a separate RxError register.
  769. */
  770. if(rxstatus & rxError){
  771. if(ctlr->rxstatus9){
  772. switch(rxstatus & rxError9){
  773. case rxOverrun9:
  774. ether->overflows++;
  775. break;
  776. case oversizedFrame9:
  777. case runtFrame9:
  778. ether->buffs++;
  779. break;
  780. case alignmentError9:
  781. ether->frames++;
  782. break;
  783. case crcError9:
  784. ether->crcs++;
  785. break;
  786. }
  787. }
  788. else{
  789. rxerror = inb(port+RxError);
  790. if(rxerror & rxOverrun)
  791. ether->overflows++;
  792. if(rxerror & (oversizedFrame|runtFrame))
  793. ether->buffs++;
  794. if(rxerror & alignmentError)
  795. ether->frames++;
  796. if(rxerror & crcError)
  797. ether->crcs++;
  798. }
  799. }
  800. /*
  801. * If there was an error or a new receive buffer can't be
  802. * allocated, discard the packet and go on to the next.
  803. */
  804. if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
  805. COMMAND(port, RxDiscard, 0);
  806. while(STATUS(port) & commandInProgress)
  807. ;
  808. if(ctlr->busmaster == 1)
  809. startdma(ether, PADDR(ctlr->rbp->rp));
  810. continue;
  811. }
  812. /*
  813. * A valid receive packet awaits:
  814. * if using PIO, read it into the buffer;
  815. * discard the packet from the FIFO;
  816. * if using busmastering, start a new transfer for
  817. * the next packet and as a side-effect get the
  818. * end-pointer of the one just received;
  819. * pass the packet on to whoever wants it.
  820. */
  821. if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
  822. len = (rxstatus & rxBytes9);
  823. ctlr->rbp->wp = ctlr->rbp->rp + len;
  824. insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
  825. }
  826. COMMAND(port, RxDiscard, 0);
  827. while(STATUS(port) & commandInProgress)
  828. ;
  829. if(ctlr->busmaster == 1)
  830. ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
  831. etheriq(ether, ctlr->rbp, 1);
  832. ctlr->rbp = bp;
  833. }
  834. }
  835. static int
  836. ejectable(int did)
  837. {
  838. switch (did) {
  839. case 0x5157:
  840. return 1;
  841. default:
  842. return 0;
  843. }
  844. }
  845. static void
  846. interrupt(Ureg*, void* arg)
  847. {
  848. Ether *ether;
  849. int port, status, s, txstatus, w, x;
  850. Ctlr *ctlr;
  851. ether = arg;
  852. port = ether->port;
  853. ctlr = ether->ctlr;
  854. ilock(&ctlr->wlock);
  855. status = STATUS(port);
  856. if(!(status & (interruptMask|interruptLatch))){
  857. ctlr->bogusinterrupts++;
  858. iunlock(&ctlr->wlock);
  859. return;
  860. }
  861. w = (status>>13) & 0x07;
  862. COMMAND(port, SelectRegisterWindow, Wop);
  863. ctlr->interrupts++;
  864. if(ctlr->busmaster == 2)
  865. ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
  866. else
  867. ctlr->timer[0] += inb(port+TIMER) & 0xFF;
  868. do{
  869. if(status & hostError){
  870. /*
  871. * Adapter failure, try to find out why, reset if
  872. * necessary. What happens if Tx is active and a reset
  873. * occurs, need to retransmit? This probably isn't right.
  874. */
  875. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  876. x = ins(port+FifoDiagnostic);
  877. COMMAND(port, SelectRegisterWindow, Wop);
  878. if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
  879. print("#l%d: Card ejected?\n", ether->ctlrno);
  880. iunlock(&ctlr->wlock);
  881. return;
  882. }
  883. print("#l%d: status 0x%uX, diag 0x%uX\n",
  884. ether->ctlrno, status, x);
  885. if(x & txOverrun){
  886. if(ctlr->busmaster == 0)
  887. COMMAND(port, TxReset, 0);
  888. else
  889. COMMAND(port, TxReset, (updnReset|dmaReset));
  890. COMMAND(port, TxEnable, 0);
  891. }
  892. if(x & rxUnderrun){
  893. /*
  894. * This shouldn't happen...
  895. * Reset the receiver and restore the filter and RxEarly
  896. * threshold before re-enabling.
  897. * Need to restart any busmastering?
  898. */
  899. COMMAND(port, SelectRegisterWindow, Wstate);
  900. s = (port+RxFilter) & 0x000F;
  901. COMMAND(port, SelectRegisterWindow, Wop);
  902. COMMAND(port, RxReset, 0);
  903. while(STATUS(port) & commandInProgress)
  904. ;
  905. COMMAND(port, SetRxFilter, s);
  906. COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
  907. COMMAND(port, RxEnable, 0);
  908. }
  909. status &= ~hostError;
  910. }
  911. if(status & (transferInt|rxComplete)){
  912. receive(ether);
  913. status &= ~(transferInt|rxComplete);
  914. }
  915. if(status & (upComplete)){
  916. COMMAND(port, AcknowledgeInterrupt, upComplete);
  917. receive905(ether);
  918. status &= ~upComplete;
  919. ctlr->upinterrupts++;
  920. }
  921. if(status & txComplete){
  922. /*
  923. * Pop the TxStatus stack, accumulating errors.
  924. * Adjust the TX start threshold if there was an underrun.
  925. * If there was a Jabber or Underrun error, reset
  926. * the transmitter, taking care not to reset the dma logic
  927. * as a busmaster receive may be in progress.
  928. * For all conditions enable the transmitter.
  929. */
  930. if(ctlr->busmaster == 2)
  931. txstatus = port+TxStatus905;
  932. else
  933. txstatus = port+TxStatus;
  934. s = 0;
  935. do{
  936. if(x = inb(txstatus))
  937. outb(txstatus, 0);
  938. s |= x;
  939. }while(STATUS(port) & txComplete);
  940. if(s & txUnderrun){
  941. if(ctlr->dnenabled){
  942. while(inl(port+PktStatus) & dnInProg)
  943. ;
  944. }
  945. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  946. while(ins(port+MediaStatus) & txInProg)
  947. ;
  948. COMMAND(port, SelectRegisterWindow, Wop);
  949. if(ctlr->txthreshold < ETHERMAXTU)
  950. ctlr->txthreshold += ETHERMINTU;
  951. }
  952. /*
  953. * According to the manual, maxCollisions does not require
  954. * a TxReset, merely a TxEnable. However, evidence points to
  955. * it being necessary on the 3C905. The jury is still out.
  956. * On busy or badly configured networks maxCollisions can
  957. * happen frequently enough for messages to be annoying so
  958. * keep quiet about them by popular request.
  959. */
  960. if(s & (txJabber|txUnderrun|maxCollisions)){
  961. if(ctlr->busmaster == 0)
  962. COMMAND(port, TxReset, 0);
  963. else
  964. COMMAND(port, TxReset, (updnReset|dmaReset));
  965. while(STATUS(port) & commandInProgress)
  966. ;
  967. COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
  968. if(ctlr->busmaster == 2)
  969. outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
  970. if(ctlr->dnenabled)
  971. status |= dnComplete;
  972. }
  973. if(s & ~(txStatusComplete|maxCollisions))
  974. print("#l%d: txstatus 0x%uX, threshold %d\n",
  975. ether->ctlrno, s, ctlr->txthreshold);
  976. COMMAND(port, TxEnable, 0);
  977. ether->oerrs++;
  978. status &= ~txComplete;
  979. status |= txAvailable;
  980. }
  981. if(status & txAvailable){
  982. COMMAND(port, AcknowledgeInterrupt, txAvailable);
  983. ctlr->txbusy = 0;
  984. txstart(ether);
  985. status &= ~txAvailable;
  986. }
  987. if(status & dnComplete){
  988. COMMAND(port, AcknowledgeInterrupt, dnComplete);
  989. txstart905(ether);
  990. status &= ~dnComplete;
  991. ctlr->dninterrupts++;
  992. }
  993. if(status & updateStats){
  994. statistics(ether);
  995. status &= ~updateStats;
  996. }
  997. /*
  998. * Currently, this shouldn't happen.
  999. */
  1000. if(status & rxEarly){
  1001. COMMAND(port, AcknowledgeInterrupt, rxEarly);
  1002. status &= ~rxEarly;
  1003. }
  1004. /*
  1005. * Panic if there are any interrupts not dealt with.
  1006. */
  1007. if(status & interruptMask)
  1008. panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
  1009. COMMAND(port, AcknowledgeInterrupt, interruptLatch);
  1010. if(ctlr->cbfn != nil)
  1011. intrackcb(ctlr->cbfn);
  1012. }while((status = STATUS(port)) & (interruptMask|interruptLatch));
  1013. if(ctlr->busmaster == 2)
  1014. ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
  1015. else
  1016. ctlr->timer[1] += inb(port+TIMER) & 0xFF;
  1017. COMMAND(port, SelectRegisterWindow, w);
  1018. iunlock(&ctlr->wlock);
  1019. }
  1020. static long
  1021. ifstat(Ether* ether, void* a, long n, ulong offset)
  1022. {
  1023. char *p;
  1024. int len;
  1025. Ctlr *ctlr;
  1026. if(n == 0)
  1027. return 0;
  1028. ctlr = ether->ctlr;
  1029. ilock(&ctlr->wlock);
  1030. statistics(ether);
  1031. iunlock(&ctlr->wlock);
  1032. p = malloc(READSTR);
  1033. if(p == nil)
  1034. error(Enomem);
  1035. len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
  1036. len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
  1037. len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
  1038. ctlr->timer[0], ctlr->timer[1]);
  1039. len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
  1040. ctlr->stats[CarrierLost]);
  1041. len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
  1042. ctlr->stats[SqeErrors]);
  1043. len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
  1044. ctlr->stats[MultipleColls]);
  1045. len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
  1046. ctlr->stats[SingleCollFrames]);
  1047. len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
  1048. ctlr->stats[LateCollisions]);
  1049. len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
  1050. ctlr->stats[RxOverruns]);
  1051. len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
  1052. ctlr->stats[FramesXmittedOk]);
  1053. len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
  1054. ctlr->stats[FramesRcvdOk]);
  1055. len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
  1056. ctlr->stats[FramesDeferred]);
  1057. len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
  1058. ctlr->stats[BytesRcvdOk]);
  1059. len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
  1060. ctlr->stats[BytesRcvdOk+1]);
  1061. if(ctlr->upenabled){
  1062. if(ctlr->upqmax > ctlr->upqmaxhw)
  1063. ctlr->upqmaxhw = ctlr->upqmax;
  1064. len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
  1065. ctlr->upqueued, ctlr->upinterrupts,
  1066. ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
  1067. ctlr->upqmax = 0;
  1068. }
  1069. if(ctlr->dnenabled){
  1070. if(ctlr->dnqmax > ctlr->dnqmaxhw)
  1071. ctlr->dnqmaxhw = ctlr->dnqmax;
  1072. len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
  1073. ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
  1074. ctlr->dnqmax = 0;
  1075. }
  1076. snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
  1077. n = readstr(offset, a, n, p);
  1078. free(p);
  1079. return n;
  1080. }
  1081. static void
  1082. txrxreset(int port)
  1083. {
  1084. COMMAND(port, TxReset, 0);
  1085. while(STATUS(port) & commandInProgress)
  1086. ;
  1087. COMMAND(port, RxReset, 0);
  1088. while(STATUS(port) & commandInProgress)
  1089. ;
  1090. }
  1091. static Ctlr*
  1092. tcmadapter(int port, int irq, Pcidev* pcidev)
  1093. {
  1094. Ctlr *ctlr;
  1095. ctlr = malloc(sizeof(Ctlr));
  1096. if(ctlr == nil)
  1097. error(Enomem);
  1098. ctlr->port = port;
  1099. ctlr->irq = irq;
  1100. ctlr->pcidev = pcidev;
  1101. ctlr->eepromcmd = EepromReadRegister;
  1102. if(ctlrhead != nil)
  1103. ctlrtail->next = ctlr;
  1104. else
  1105. ctlrhead = ctlr;
  1106. ctlrtail = ctlr;
  1107. return ctlr;
  1108. }
  1109. /*
  1110. * Write two 0 bytes to identify the IDport and then reset the
  1111. * ID sequence. Then send the ID sequence to the card to get
  1112. * the card into command state.
  1113. */
  1114. static void
  1115. idseq(void)
  1116. {
  1117. int i;
  1118. uchar al;
  1119. static int reset, untag;
  1120. /*
  1121. * One time only:
  1122. * reset any adapters listening
  1123. */
  1124. if(reset == 0){
  1125. outb(IDport, 0);
  1126. outb(IDport, 0);
  1127. outb(IDport, 0xC0);
  1128. delay(20);
  1129. reset = 1;
  1130. }
  1131. outb(IDport, 0);
  1132. outb(IDport, 0);
  1133. for(al = 0xFF, i = 0; i < 255; i++){
  1134. outb(IDport, al);
  1135. if(al & 0x80){
  1136. al <<= 1;
  1137. al ^= 0xCF;
  1138. }
  1139. else
  1140. al <<= 1;
  1141. }
  1142. /*
  1143. * One time only:
  1144. * write ID sequence to get the attention of all adapters;
  1145. * untag all adapters.
  1146. * If a global reset is done here on all adapters it will confuse
  1147. * any ISA cards configured for EISA mode.
  1148. */
  1149. if(untag == 0){
  1150. outb(IDport, 0xD0);
  1151. untag = 1;
  1152. }
  1153. }
  1154. static ulong
  1155. activate(void)
  1156. {
  1157. int i;
  1158. ushort x, acr;
  1159. /*
  1160. * Do the little configuration dance:
  1161. *
  1162. * 2. write the ID sequence to get to command state.
  1163. */
  1164. idseq();
  1165. /*
  1166. * 3. Read the Manufacturer ID from the EEPROM.
  1167. * This is done by writing the IDPort with 0x87 (0x80
  1168. * is the 'read EEPROM' command, 0x07 is the offset of
  1169. * the Manufacturer ID field in the EEPROM).
  1170. * The data comes back 1 bit at a time.
  1171. * A delay seems necessary between reading the bits.
  1172. *
  1173. * If the ID doesn't match, there are no more adapters.
  1174. */
  1175. outb(IDport, 0x87);
  1176. delay(20);
  1177. for(x = 0, i = 0; i < 16; i++){
  1178. delay(20);
  1179. x <<= 1;
  1180. x |= inb(IDport) & 0x01;
  1181. }
  1182. if(x != 0x6D50)
  1183. return 0;
  1184. /*
  1185. * 3. Read the Address Configuration from the EEPROM.
  1186. * The Address Configuration field is at offset 0x08 in the EEPROM).
  1187. */
  1188. outb(IDport, 0x88);
  1189. for(acr = 0, i = 0; i < 16; i++){
  1190. delay(20);
  1191. acr <<= 1;
  1192. acr |= inb(IDport) & 0x01;
  1193. }
  1194. return (acr & 0x1F)*0x10 + 0x200;
  1195. }
  1196. static void
  1197. tcm509isa(void)
  1198. {
  1199. int irq, port;
  1200. /*
  1201. * Attempt to activate all adapters. If adapter is set for
  1202. * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
  1203. * it fully.
  1204. */
  1205. while(port = activate()){
  1206. if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
  1207. print("tcm509isa: port 0x%uX in use\n", port);
  1208. continue;
  1209. }
  1210. /*
  1211. * 6. Tag the adapter so it won't respond in future.
  1212. */
  1213. outb(IDport, 0xD1);
  1214. if(port == 0x3F0){
  1215. iofree(port);
  1216. continue;
  1217. }
  1218. /*
  1219. * 6. Activate the adapter by writing the Activate command
  1220. * (0xFF).
  1221. */
  1222. outb(IDport, 0xFF);
  1223. delay(20);
  1224. /*
  1225. * 8. Can now talk to the adapter's I/O base addresses.
  1226. * Use the I/O base address from the acr just read.
  1227. *
  1228. * Enable the adapter and clear out any lingering status
  1229. * and interrupts.
  1230. */
  1231. while(STATUS(port) & commandInProgress)
  1232. ;
  1233. COMMAND(port, SelectRegisterWindow, Wsetup);
  1234. outs(port+ConfigControl, Ena);
  1235. txrxreset(port);
  1236. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1237. irq = (ins(port+ResourceConfig)>>12) & 0x0F;
  1238. tcmadapter(port, irq, nil);
  1239. }
  1240. }
  1241. static void
  1242. tcm5XXeisa(void)
  1243. {
  1244. ushort x;
  1245. int irq, port, slot;
  1246. /*
  1247. * Check if this is an EISA machine.
  1248. * If not, nothing to do.
  1249. */
  1250. if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
  1251. return;
  1252. /*
  1253. * Continue through the EISA slots looking for a match on both
  1254. * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
  1255. * If an adapter is found, select window 0, enable it and clear
  1256. * out any lingering status and interrupts.
  1257. */
  1258. for(slot = 1; slot < MaxEISA; slot++){
  1259. port = slot*0x1000;
  1260. if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
  1261. print("tcm5XXeisa: port 0x%uX in use\n", port);
  1262. continue;
  1263. }
  1264. if(ins(port+0xC80+ManufacturerID) != 0x6D50){
  1265. iofree(port);
  1266. continue;
  1267. }
  1268. x = ins(port+0xC80+ProductID);
  1269. if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
  1270. iofree(port);
  1271. continue;
  1272. }
  1273. COMMAND(port, SelectRegisterWindow, Wsetup);
  1274. outs(port+ConfigControl, Ena);
  1275. txrxreset(port);
  1276. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1277. irq = (ins(port+ResourceConfig)>>12) & 0x0F;
  1278. tcmadapter(port, irq, nil);
  1279. }
  1280. }
  1281. static void
  1282. tcm59Xpci(void)
  1283. {
  1284. Pcidev *p;
  1285. Ctlr *ctlr;
  1286. int irq, port;
  1287. p = nil;
  1288. while(p = pcimatch(p, 0x10B7, 0)){
  1289. if(p->ccrb != 0x02 || p->ccru != 0)
  1290. continue;
  1291. /*
  1292. * Not prepared to deal with memory-mapped
  1293. * devices yet.
  1294. */
  1295. if(!(p->mem[0].bar & 0x01))
  1296. continue;
  1297. port = p->mem[0].bar & ~0x01;
  1298. if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
  1299. 0, "tcm59Xpci")) < 0){
  1300. print("tcm59Xpci: port 0x%uX in use\n", port);
  1301. continue;
  1302. }
  1303. irq = p->intl;
  1304. txrxreset(port);
  1305. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1306. ctlr = tcmadapter(port, irq, p);
  1307. switch(p->did){
  1308. default:
  1309. break;
  1310. case 0x5157:
  1311. ctlr->eepromcmd = EepromRead8bRegister;
  1312. ctlr->cbfnpa = p->mem[2].bar&~0x0F;
  1313. ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
  1314. break;
  1315. case 0x6056:
  1316. ctlr->eepromcmd = EepromReadOffRegister;
  1317. ctlr->cbfnpa = p->mem[2].bar&~0x0F;
  1318. ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
  1319. break;
  1320. }
  1321. pcisetbme(p);
  1322. }
  1323. }
  1324. static char* tcmpcmcia[] = {
  1325. "3C589", /* 3COM 589[ABCD] */
  1326. "3C562", /* 3COM 562 */
  1327. "589E", /* 3COM Megahertz 589E */
  1328. nil,
  1329. };
  1330. static Ctlr*
  1331. tcm5XXpcmcia(Ether* ether)
  1332. {
  1333. int i;
  1334. Ctlr *ctlr;
  1335. if(ether->type == nil)
  1336. return nil;
  1337. for(i = 0; tcmpcmcia[i] != nil; i++){
  1338. if(cistrcmp(ether->type, tcmpcmcia[i]))
  1339. continue;
  1340. ctlr = tcmadapter(ether->port, ether->irq, nil);
  1341. ctlr->active = 1;
  1342. return ctlr;
  1343. }
  1344. return nil;
  1345. }
  1346. static void
  1347. setxcvr(Ctlr* ctlr, int xcvr)
  1348. {
  1349. int port, x;
  1350. port = ctlr->port;
  1351. if(ctlr->rxstatus9){
  1352. COMMAND(port, SelectRegisterWindow, Wsetup);
  1353. x = ins(port+AddressConfig) & ~xcvrMask9;
  1354. x |= (xcvr>>20)<<14;
  1355. outs(port+AddressConfig, x);
  1356. }
  1357. else{
  1358. COMMAND(port, SelectRegisterWindow, Wfifo);
  1359. x = inl(port+InternalConfig) & ~xcvrMask;
  1360. x |= xcvr;
  1361. outl(port+InternalConfig, x);
  1362. }
  1363. txrxreset(port);
  1364. }
  1365. static void
  1366. setfullduplex(int port)
  1367. {
  1368. int x;
  1369. COMMAND(port, SelectRegisterWindow, Wfifo);
  1370. x = ins(port+MacControl);
  1371. outs(port+MacControl, fullDuplexEnable|x);
  1372. txrxreset(port);
  1373. }
  1374. static int
  1375. miimdi(int port, int n)
  1376. {
  1377. int data, i;
  1378. /*
  1379. * Read n bits from the MII Management Register.
  1380. */
  1381. data = 0;
  1382. for(i = n-1; i >= 0; i--){
  1383. if(ins(port) & mgmtData)
  1384. data |= (1<<i);
  1385. microdelay(1);
  1386. outs(port, mgmtClk);
  1387. microdelay(1);
  1388. outs(port, 0);
  1389. microdelay(1);
  1390. }
  1391. return data;
  1392. }
  1393. static void
  1394. miimdo(int port, int bits, int n)
  1395. {
  1396. int i, mdo;
  1397. /*
  1398. * Write n bits to the MII Management Register.
  1399. */
  1400. for(i = n-1; i >= 0; i--){
  1401. if(bits & (1<<i))
  1402. mdo = mgmtDir|mgmtData;
  1403. else
  1404. mdo = mgmtDir;
  1405. outs(port, mdo);
  1406. microdelay(1);
  1407. outs(port, mdo|mgmtClk);
  1408. microdelay(1);
  1409. outs(port, mdo);
  1410. microdelay(1);
  1411. }
  1412. }
  1413. static int
  1414. miir(int port, int phyad, int regad)
  1415. {
  1416. int data, w;
  1417. w = (STATUS(port)>>13) & 0x07;
  1418. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1419. port += PhysicalMgmt;
  1420. /*
  1421. * Preamble;
  1422. * ST+OP+PHYAD+REGAD;
  1423. * TA + 16 data bits.
  1424. */
  1425. miimdo(port, 0xFFFFFFFF, 32);
  1426. miimdo(port, 0x1800|(phyad<<5)|regad, 14);
  1427. data = miimdi(port, 18);
  1428. port -= PhysicalMgmt;
  1429. COMMAND(port, SelectRegisterWindow, w);
  1430. if(data & 0x10000)
  1431. return -1;
  1432. return data & 0xFFFF;
  1433. }
  1434. static int
  1435. scanphy(int port)
  1436. {
  1437. int i, x;
  1438. for(i = 0; i < 32; i++){
  1439. if((x = miir(port, i, 2)) == -1 || x == 0)
  1440. continue;
  1441. x <<= 6;
  1442. x |= miir(port, i, 3)>>10;
  1443. XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
  1444. USED(x);
  1445. return i;
  1446. }
  1447. return 24;
  1448. }
  1449. static struct {
  1450. char *name;
  1451. int avail;
  1452. int xcvr;
  1453. } media[] = {
  1454. "10BaseT", base10TAvailable, xcvr10BaseT,
  1455. "10Base2", coaxAvailable, xcvr10Base2,
  1456. "100BaseTX", baseTXAvailable, xcvr100BaseTX,
  1457. "100BaseFX", baseFXAvailable, xcvr100BaseFX,
  1458. "aui", auiAvailable, xcvrAui,
  1459. "mii", miiConnector, xcvrMii
  1460. };
  1461. static int
  1462. autoselect(Ctlr* ctlr)
  1463. {
  1464. int media, port, x;
  1465. /*
  1466. * Pathetic attempt at automatic media selection.
  1467. * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
  1468. * cards operational.
  1469. * It's a bonus if it works for anything else.
  1470. */
  1471. port = ctlr->port;
  1472. if(ctlr->rxstatus9){
  1473. COMMAND(port, SelectRegisterWindow, Wsetup);
  1474. x = ins(port+ConfigControl);
  1475. media = 0;
  1476. if(x & base10TAvailable9)
  1477. media |= base10TAvailable;
  1478. if(x & coaxAvailable9)
  1479. media |= coaxAvailable;
  1480. if(x & auiAvailable9)
  1481. media |= auiAvailable;
  1482. }
  1483. else{
  1484. COMMAND(port, SelectRegisterWindow, Wfifo);
  1485. media = ins(port+ResetOptions);
  1486. }
  1487. XCVRDEBUG("autoselect: media %uX\n", media);
  1488. if(media & miiConnector)
  1489. return xcvrMii;
  1490. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1491. XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
  1492. if(media & baseTXAvailable){
  1493. /*
  1494. * Must have InternalConfig register.
  1495. */
  1496. setxcvr(ctlr, xcvr100BaseTX);
  1497. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1498. x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
  1499. outs(port+MediaStatus, linkBeatEnable|x);
  1500. delay(10);
  1501. if(ins(port+MediaStatus) & linkBeatDetect)
  1502. return xcvr100BaseTX;
  1503. outs(port+MediaStatus, x);
  1504. }
  1505. if(media & base10TAvailable){
  1506. setxcvr(ctlr, xcvr10BaseT);
  1507. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1508. x = ins(port+MediaStatus) & ~dcConverterEnabled;
  1509. outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
  1510. delay(100);
  1511. XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
  1512. if(ins(port+MediaStatus) & linkBeatDetect)
  1513. return xcvr10BaseT;
  1514. outs(port+MediaStatus, x);
  1515. }
  1516. /*
  1517. * Botch.
  1518. */
  1519. return autoSelect;
  1520. }
  1521. static int
  1522. eepromdata(Ctlr* ctlr, int offset)
  1523. {
  1524. int port;
  1525. port = ctlr->port;
  1526. COMMAND(port, SelectRegisterWindow, Wsetup);
  1527. while(EEPROMBUSY(port))
  1528. ;
  1529. EEPROMCMD(port, ctlr->eepromcmd, offset);
  1530. while(EEPROMBUSY(port))
  1531. ;
  1532. return EEPROMDATA(port);
  1533. }
  1534. static void
  1535. resetctlr(Ctlr *ctlr)
  1536. {
  1537. int x, port = ctlr->port;
  1538. txrxreset(port);
  1539. x = ins(port+ResetOp905B);
  1540. XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
  1541. x &= ~0x4010;
  1542. if(ctlr->did == 0x5157){
  1543. x |= 0x0010; /* Invert LED */
  1544. outs(port+ResetOp905B, x);
  1545. }
  1546. if(ctlr->did == 0x6056){
  1547. x |= 0x4000;
  1548. outs(port+ResetOp905B, x);
  1549. COMMAND(port, SelectRegisterWindow, Wsetup);
  1550. outs(port, 0x0800);
  1551. }
  1552. }
  1553. static void
  1554. shutdown(Ether *ether)
  1555. {
  1556. print("etherelnk3 shutting down\n");
  1557. resetctlr(ether->ctlr);
  1558. }
  1559. int
  1560. etherelnk3reset(Ether* ether)
  1561. {
  1562. char *p;
  1563. Ctlr *ctlr;
  1564. uchar ea[Eaddrlen];
  1565. static int scandone;
  1566. int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
  1567. /*
  1568. * Scan for adapter on PCI, EISA and finally
  1569. * using the little ISA configuration dance.
  1570. */
  1571. if(scandone == 0){
  1572. tcm59Xpci();
  1573. tcm5XXeisa();
  1574. tcm509isa();
  1575. scandone = 1;
  1576. }
  1577. /*
  1578. * Any adapter matches if no ether->port is supplied,
  1579. * otherwise the ports must match.
  1580. */
  1581. for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  1582. if(ctlr->active)
  1583. continue;
  1584. if(ether->port == 0 || ether->port == ctlr->port){
  1585. ctlr->active = 1;
  1586. break;
  1587. }
  1588. }
  1589. if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
  1590. return -1;
  1591. ether->ctlr = ctlr;
  1592. port = ctlr->port;
  1593. ether->port = port;
  1594. ether->irq = ctlr->irq;
  1595. if(ctlr->pcidev != nil)
  1596. ether->tbdf = ctlr->pcidev->tbdf;
  1597. else
  1598. ether->tbdf = BUSUNKNOWN;
  1599. /*
  1600. * Read the DeviceID from the EEPROM, it's at offset 0x03,
  1601. * and do something depending on capabilities.
  1602. */
  1603. switch(ctlr->did = eepromdata(ctlr, 0x03)){
  1604. case 0x5157: /* 3C575 Cyclone */
  1605. case 0x6056:
  1606. /*FALLTHROUGH*/
  1607. case 0x4500: /* 3C450 HomePNA Tornado */
  1608. case 0x7646: /* 3CSOHO100-TX */
  1609. case 0x9055: /* 3C905B-TX */
  1610. case 0x9200: /* 3C905C-TX */
  1611. case 0x9201: /* 3C920 */
  1612. case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
  1613. /*FALLTHROUGH*/
  1614. case 0x9000: /* 3C900-TPO */
  1615. case 0x9001: /* 3C900-COMBO */
  1616. case 0x9005: /* 3C900B-COMBO */
  1617. case 0x9050: /* 3C905-TX */
  1618. case 0x9051: /* 3C905-T4 */
  1619. if(BUSTYPE(ether->tbdf) != BusPCI)
  1620. goto buggery;
  1621. ctlr->busmaster = 2;
  1622. goto vortex;
  1623. case 0x5900: /* 3C590-[TP|COMBO|TPO] */
  1624. case 0x5920: /* 3C592-[TP|COMBO|TPO] */
  1625. case 0x5950: /* 3C595-TX */
  1626. case 0x5951: /* 3C595-T4 */
  1627. case 0x5952: /* 3C595-MII */
  1628. case 0x5970: /* 3C597-TX */
  1629. case 0x5971: /* 3C597-T4 */
  1630. case 0x5972: /* 3C597-MII */
  1631. ctlr->busmaster = 1;
  1632. vortex:
  1633. COMMAND(port, SelectRegisterWindow, Wfifo);
  1634. ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
  1635. ctlr->rxearly = 8188;
  1636. ctlr->rxstatus9 = 0;
  1637. break;
  1638. buggery:
  1639. default:
  1640. ctlr->busmaster = 0;
  1641. COMMAND(port, SelectRegisterWindow, Wsetup);
  1642. x = ins(port+AddressConfig);
  1643. ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
  1644. if(x & autoSelect9)
  1645. ctlr->xcvr |= autoSelect;
  1646. ctlr->rxearly = 2044;
  1647. ctlr->rxstatus9 = 1;
  1648. break;
  1649. }
  1650. if(ctlr->rxearly >= 2048)
  1651. ctlr->ts = 2;
  1652. /*
  1653. * Check if the adapter's station address is to be overridden.
  1654. * If not, read it from the EEPROM and set in ether->ea prior to
  1655. * loading the station address in Wstation.
  1656. * The EEPROM returns 16-bits at a time.
  1657. */
  1658. memset(ea, 0, Eaddrlen);
  1659. if(memcmp(ea, ether->ea, Eaddrlen) == 0){
  1660. for(i = 0; i < Eaddrlen/2; i++){
  1661. x = eepromdata(ctlr, i);
  1662. ether->ea[2*i] = x>>8;
  1663. ether->ea[2*i+1] = x;
  1664. }
  1665. }
  1666. COMMAND(port, SelectRegisterWindow, Wstation);
  1667. for(i = 0; i < Eaddrlen; i++)
  1668. outb(port+i, ether->ea[i]);
  1669. /*
  1670. * Enable the transceiver if necessary and determine whether
  1671. * busmastering can be used. Due to bugs in the first revision
  1672. * of the 3C59[05], don't use busmastering at 10Mbps.
  1673. */
  1674. XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
  1675. /*
  1676. * Allow user to specify desired media in plan9.ini
  1677. */
  1678. for(i = 0; i < ether->nopt; i++){
  1679. if(cistrncmp(ether->opt[i], "media=", 6) != 0)
  1680. continue;
  1681. p = ether->opt[i]+6;
  1682. for(j = 0; j < nelem(media); j++)
  1683. if(cistrcmp(p, media[j].name) == 0)
  1684. ctlr->xcvr = media[j].xcvr;
  1685. }
  1686. /*
  1687. * forgive me, but i am weak
  1688. */
  1689. switch(ctlr->did){
  1690. default:
  1691. if(ctlr->xcvr & autoSelect)
  1692. ctlr->xcvr = autoselect(ctlr);
  1693. break;
  1694. case 0x5157:
  1695. case 0x6056:
  1696. case 0x4500:
  1697. case 0x7646:
  1698. case 0x9055:
  1699. case 0x9200:
  1700. case 0x9201:
  1701. case 0x9805:
  1702. ctlr->xcvr = xcvrMii;
  1703. resetctlr(ctlr);
  1704. break;
  1705. }
  1706. XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
  1707. switch(ctlr->xcvr){
  1708. case xcvrMii:
  1709. /*
  1710. * Quick hack.
  1711. */
  1712. if(ctlr->did == 0x5157)
  1713. phyaddr = 0;
  1714. else if(ctlr->did == 0x6056)
  1715. phyaddr = scanphy(port);
  1716. else
  1717. phyaddr = 24;
  1718. for(i = 0; i < 7; i++)
  1719. XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
  1720. XCVRDEBUG("\n");
  1721. for(timeo = 0; timeo < 30; timeo++){
  1722. phystat = miir(port, phyaddr, 0x01);
  1723. if(phystat & 0x20)
  1724. break;
  1725. XCVRDEBUG(" %2.2uX", phystat);
  1726. delay(100);
  1727. }
  1728. XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
  1729. XCVRDEBUG("\n");
  1730. anar = miir(port, phyaddr, 0x04);
  1731. anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
  1732. anar &= anlpar;
  1733. miir(port, phyaddr, 0x00);
  1734. XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
  1735. anar, anlpar, miir(port, phyaddr, 0x00),
  1736. miir(port, phyaddr, 0x01));
  1737. for(i = 0; i < ether->nopt; i++){
  1738. if(cistrcmp(ether->opt[i], "fullduplex") == 0)
  1739. anar |= 0x0100;
  1740. else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
  1741. anar |= 0x0100;
  1742. else if(cistrcmp(ether->opt[i], "force100") == 0)
  1743. anar |= 0x0080;
  1744. }
  1745. XCVRDEBUG("mii anar: %uX\n", anar);
  1746. if(anar & 0x0100){ /* 100BASE-TXFD */
  1747. ether->mbps = 100;
  1748. setfullduplex(port);
  1749. }
  1750. else if(anar & 0x0200){ /* 100BASE-T4 */
  1751. /* nothing to do */
  1752. }
  1753. else if(anar & 0x0080) /* 100BASE-TX */
  1754. ether->mbps = 100;
  1755. else if(anar & 0x0040) /* 10BASE-TFD */
  1756. setfullduplex(port);
  1757. else{ /* 10BASE-T */
  1758. /* nothing to do */
  1759. }
  1760. break;
  1761. case xcvr100BaseTX:
  1762. case xcvr100BaseFX:
  1763. COMMAND(port, SelectRegisterWindow, Wfifo);
  1764. x = inl(port+InternalConfig) & ~ramPartitionMask;
  1765. outl(port+InternalConfig, x|ramPartition1to1);
  1766. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1767. x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
  1768. x |= linkBeatEnable;
  1769. outs(port+MediaStatus, x);
  1770. if(x & dataRate100)
  1771. ether->mbps = 100;
  1772. break;
  1773. case xcvr10BaseT:
  1774. /*
  1775. * Enable Link Beat and Jabber to start the
  1776. * transceiver.
  1777. */
  1778. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1779. x = ins(port+MediaStatus) & ~dcConverterEnabled;
  1780. x |= linkBeatEnable|jabberGuardEnable;
  1781. outs(port+MediaStatus, x);
  1782. if((ctlr->did & 0xFF00) == 0x5900)
  1783. ctlr->busmaster = 0;
  1784. break;
  1785. case xcvr10Base2:
  1786. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1787. x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
  1788. outs(port+MediaStatus, x);
  1789. /*
  1790. * Start the DC-DC converter.
  1791. * Wait > 800 microseconds.
  1792. */
  1793. COMMAND(port, EnableDcConverter, 0);
  1794. delay(1);
  1795. break;
  1796. }
  1797. /*
  1798. * Wop is the normal operating register set.
  1799. * The 3C59[0257] adapters allow access to more than one register window
  1800. * at a time, but there are situations where switching still needs to be
  1801. * done, so just do it.
  1802. * Clear out any lingering Tx status.
  1803. */
  1804. COMMAND(port, SelectRegisterWindow, Wop);
  1805. if(ctlr->busmaster == 2)
  1806. x = port+TxStatus905;
  1807. else
  1808. x = port+TxStatus;
  1809. while(inb(x))
  1810. outb(x, 0);
  1811. /*
  1812. * Clear out the
  1813. * adapter statistics, clear the statistics logged into ctlr
  1814. * and enable statistics collection.
  1815. */
  1816. ilock(&ctlr->wlock);
  1817. statistics(ether);
  1818. memset(ctlr->stats, 0, sizeof(ctlr->stats));
  1819. COMMAND(port, StatisticsEnable, 0);
  1820. /*
  1821. * Allocate any receive buffers.
  1822. */
  1823. switch(ctlr->busmaster){
  1824. case 2:
  1825. ctlr->dnenabled = 1;
  1826. /*
  1827. * 10MUpldBug.
  1828. * Disabling is too severe, can use receive busmastering at
  1829. * 100Mbps OK, but how to tell which rate is actually being used -
  1830. * the 3c905 always seems to have dataRate100 set?
  1831. * Believe the bug doesn't apply if upRxEarlyEnable is set
  1832. * and the threshold is set such that uploads won't start
  1833. * until the whole packet has been received.
  1834. */
  1835. ctlr->upenabled = 1;
  1836. x = eepromdata(ctlr, 0x0F);
  1837. if(!(x & 0x01))
  1838. outl(port+PktStatus, upRxEarlyEnable);
  1839. if(ctlr->upenabled || ctlr->dnenabled){
  1840. ctlr->nup = Nup;
  1841. ctlr->ndn = Ndn;
  1842. init905(ctlr);
  1843. }
  1844. else {
  1845. ctlr->rbp = rbpalloc(iallocb);
  1846. if(ctlr->rbp == nil)
  1847. panic("can't reset ethernet: out of memory");
  1848. }
  1849. outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
  1850. break;
  1851. default:
  1852. ctlr->rbp = rbpalloc(iallocb);
  1853. if(ctlr->rbp == nil)
  1854. panic("can't reset ethernet: out of memory");
  1855. break;
  1856. }
  1857. /*
  1858. * Set a base TxStartThresh which will be incremented
  1859. * if any txUnderrun errors occur and ensure no RxEarly
  1860. * interrupts happen.
  1861. */
  1862. ctlr->txthreshold = ETHERMAXTU/2;
  1863. COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
  1864. COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
  1865. iunlock(&ctlr->wlock);
  1866. /*
  1867. * Linkage to the generic ethernet driver.
  1868. */
  1869. ether->attach = attach;
  1870. ether->transmit = transmit;
  1871. ether->interrupt = interrupt;
  1872. ether->ifstat = ifstat;
  1873. ether->promiscuous = promiscuous;
  1874. ether->multicast = multicast;
  1875. ether->shutdown = shutdown;
  1876. ether->arg = ether;
  1877. return 0;
  1878. }
  1879. void
  1880. etherelnk3link(void)
  1881. {
  1882. addethercard("elnk3", etherelnk3reset);
  1883. addethercard("3C509", etherelnk3reset);
  1884. addethercard("3C575", etherelnk3reset);
  1885. }