etherelnk3.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134
  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. ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8);
  407. prev = ctlr->upr;
  408. for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){
  409. pd->np = PADDR(&prev->np);
  410. pd->control = 0;
  411. bp = iallocb(sizeof(Etherpkt));
  412. if(bp == nil)
  413. panic("can't allocate ethernet receive ring");
  414. pd->addr = PADDR(bp->rp);
  415. pd->len = updnLastFrag|sizeof(Etherpkt);
  416. pd->next = prev;
  417. prev = pd;
  418. pd->bp = bp;
  419. }
  420. ctlr->uphead = ctlr->upr;
  421. ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd));
  422. ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8);
  423. prev = ctlr->dnr;
  424. for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){
  425. pd->next = prev;
  426. prev = pd;
  427. }
  428. ctlr->dnhead = ctlr->dnr;
  429. ctlr->dntail = ctlr->dnr;
  430. ctlr->dnq = 0;
  431. }
  432. static Block*
  433. rbpalloc(Block* (*f)(int))
  434. {
  435. Block *bp;
  436. ulong addr;
  437. /*
  438. * The receive buffers must be on a 32-byte
  439. * boundary for EISA busmastering.
  440. */
  441. if(bp = f(ROUNDUP(sizeof(Etherpkt), 4) + 31)){
  442. addr = (ulong)bp->base;
  443. addr = ROUNDUP(addr, 32);
  444. bp->rp = (uchar*)addr;
  445. }
  446. return bp;
  447. }
  448. static uchar*
  449. startdma(Ether* ether, ulong address)
  450. {
  451. int port, status, w;
  452. uchar *wp;
  453. port = ether->port;
  454. w = (STATUS(port)>>13) & 0x07;
  455. COMMAND(port, SelectRegisterWindow, Wmaster);
  456. wp = KADDR(inl(port+MasterAddress));
  457. status = ins(port+MasterStatus);
  458. if(status & (masterInProgress|targetAbort|masterAbort))
  459. print("#l%d: BM status 0x%uX\n", ether->ctlrno, status);
  460. outs(port+MasterStatus, masterMask);
  461. outl(port+MasterAddress, address);
  462. outs(port+MasterLen, sizeof(Etherpkt));
  463. COMMAND(port, StartDma, Upload);
  464. COMMAND(port, SelectRegisterWindow, w);
  465. return wp;
  466. }
  467. static void
  468. promiscuous(void* arg, int on)
  469. {
  470. int filter, port;
  471. Ether *ether;
  472. ether = (Ether*)arg;
  473. port = ether->port;
  474. filter = receiveBroadcast|receiveIndividual;
  475. if(ether->nmaddr)
  476. filter |= receiveMulticast;
  477. if(on)
  478. filter |= receiveAllFrames;
  479. COMMAND(port, SetRxFilter, filter);
  480. }
  481. static void
  482. multicast(void* arg, uchar *addr, int on)
  483. {
  484. int filter, port;
  485. Ether *ether;
  486. USED(addr, on);
  487. ether = (Ether*)arg;
  488. port = ether->port;
  489. filter = receiveBroadcast|receiveIndividual;
  490. if(ether->nmaddr)
  491. filter |= receiveMulticast;
  492. if(ether->prom)
  493. filter |= receiveAllFrames;
  494. COMMAND(port, SetRxFilter, filter);
  495. }
  496. /* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
  497. static void
  498. intrackcb(ulong *cbfn)
  499. {
  500. cbfn[1] = 0x8000;
  501. }
  502. static void
  503. attach(Ether* ether)
  504. {
  505. int port, x;
  506. Ctlr *ctlr;
  507. ctlr = ether->ctlr;
  508. ilock(&ctlr->wlock);
  509. if(ctlr->attached){
  510. iunlock(&ctlr->wlock);
  511. return;
  512. }
  513. port = ether->port;
  514. /*
  515. * Set the receiver packet filter for this and broadcast addresses,
  516. * set the interrupt masks for all interrupts, enable the receiver
  517. * and transmitter.
  518. */
  519. promiscuous(ether, ether->prom);
  520. x = interruptMask;
  521. if(ctlr->busmaster == 1)
  522. x &= ~(rxEarly|rxComplete);
  523. else{
  524. if(ctlr->dnenabled)
  525. x &= ~transferInt;
  526. if(ctlr->upenabled)
  527. x &= ~(rxEarly|rxComplete);
  528. }
  529. COMMAND(port, SetIndicationEnable, x);
  530. COMMAND(port, SetInterruptEnable, x);
  531. COMMAND(port, RxEnable, 0);
  532. COMMAND(port, TxEnable, 0);
  533. /*
  534. * If this is a CardBus card, acknowledge any interrupts.
  535. */
  536. if(ctlr->cbfn != nil)
  537. intrackcb(ctlr->cbfn);
  538. /*
  539. * Prime the busmaster channel for receiving directly into a
  540. * receive packet buffer if necessary.
  541. */
  542. if(ctlr->busmaster == 1)
  543. startdma(ether, PADDR(ctlr->rbp->rp));
  544. else{
  545. if(ctlr->upenabled)
  546. outl(port+UpListPtr, PADDR(&ctlr->uphead->np));
  547. }
  548. ctlr->attached = 1;
  549. iunlock(&ctlr->wlock);
  550. }
  551. static void
  552. statistics(Ether* ether)
  553. {
  554. int port, i, u, w;
  555. Ctlr *ctlr;
  556. port = ether->port;
  557. ctlr = ether->ctlr;
  558. /*
  559. * 3C59[27] require a read between a PIO write and
  560. * reading a statistics register.
  561. */
  562. w = (STATUS(port)>>13) & 0x07;
  563. COMMAND(port, SelectRegisterWindow, Wstatistics);
  564. STATUS(port);
  565. for(i = 0; i < UpperFramesOk; i++)
  566. ctlr->stats[i] += inb(port+i) & 0xFF;
  567. u = inb(port+UpperFramesOk) & 0xFF;
  568. ctlr->stats[FramesXmittedOk] += (u & 0x30)<<4;
  569. ctlr->stats[FramesRcvdOk] += (u & 0x03)<<8;
  570. ctlr->stats[BytesRcvdOk] += ins(port+BytesRcvdOk) & 0xFFFF;
  571. ctlr->stats[BytesRcvdOk+1] += ins(port+BytesXmittedOk) & 0xFFFF;
  572. switch(ctlr->xcvr){
  573. case xcvrMii:
  574. case xcvr100BaseTX:
  575. case xcvr100BaseFX:
  576. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  577. STATUS(port);
  578. ctlr->stats[BytesRcvdOk+2] += inb(port+BadSSD);
  579. break;
  580. }
  581. COMMAND(port, SelectRegisterWindow, w);
  582. }
  583. static void
  584. txstart(Ether* ether)
  585. {
  586. int port, len;
  587. Ctlr *ctlr;
  588. Block *bp;
  589. port = ether->port;
  590. ctlr = ether->ctlr;
  591. /*
  592. * Attempt to top-up the transmit FIFO. If there's room simply
  593. * stuff in the packet length (unpadded to a dword boundary), the
  594. * packet data (padded) and remove the packet from the queue.
  595. * If there's no room post an interrupt for when there is.
  596. * This routine is called both from the top level and from interrupt
  597. * level and expects to be called with ctlr->wlock already locked
  598. * and the correct register window (Wop) in place.
  599. */
  600. for(;;){
  601. if(ctlr->txbp){
  602. bp = ctlr->txbp;
  603. ctlr->txbp = 0;
  604. }
  605. else{
  606. bp = qget(ether->oq);
  607. if(bp == nil)
  608. break;
  609. }
  610. len = ROUNDUP(BLEN(bp), 4);
  611. if(len+4 <= ins(port+TxFree)){
  612. outl(port+Fifo, BLEN(bp));
  613. outsl(port+Fifo, bp->rp, len/4);
  614. freeb(bp);
  615. ether->outpackets++;
  616. }
  617. else{
  618. ctlr->txbp = bp;
  619. if(ctlr->txbusy == 0){
  620. ctlr->txbusy = 1;
  621. COMMAND(port, SetTxAvailableThresh, len>>ctlr->ts);
  622. }
  623. break;
  624. }
  625. }
  626. }
  627. static void
  628. txstart905(Ether* ether)
  629. {
  630. Ctlr *ctlr;
  631. int port, stalled, timeo;
  632. Block *bp;
  633. Pd *pd;
  634. ctlr = ether->ctlr;
  635. port = ether->port;
  636. /*
  637. * Free any completed packets.
  638. */
  639. pd = ctlr->dntail;
  640. while(ctlr->dnq){
  641. if(PADDR(&pd->np) == inl(port+DnListPtr))
  642. break;
  643. if(pd->bp){
  644. freeb(pd->bp);
  645. pd->bp = nil;
  646. }
  647. ctlr->dnq--;
  648. pd = pd->next;
  649. }
  650. ctlr->dntail = pd;
  651. stalled = 0;
  652. while(ctlr->dnq < (ctlr->ndn-1)){
  653. bp = qget(ether->oq);
  654. if(bp == nil)
  655. break;
  656. pd = ctlr->dnhead->next;
  657. pd->np = 0;
  658. pd->control = dnIndicate|BLEN(bp);
  659. pd->addr = PADDR(bp->rp);
  660. pd->len = updnLastFrag|BLEN(bp);
  661. pd->bp = bp;
  662. if(stalled == 0 && ctlr->dnq && inl(port+DnListPtr)){
  663. COMMAND(port, Stall, dnStall);
  664. for(timeo = 100; (STATUS(port) & commandInProgress) && timeo; timeo--)
  665. ;
  666. if(timeo == 0)
  667. print("#l%d: dnstall %d\n", ether->ctlrno, timeo);
  668. stalled = 1;
  669. }
  670. coherence();
  671. ctlr->dnhead->np = PADDR(&pd->np);
  672. ctlr->dnhead->control &= ~dnIndicate;
  673. ctlr->dnhead = pd;
  674. if(ctlr->dnq == 0)
  675. ctlr->dntail = pd;
  676. ctlr->dnq++;
  677. ctlr->dnqueued++;
  678. }
  679. if(ctlr->dnq > ctlr->dnqmax)
  680. ctlr->dnqmax = ctlr->dnq;
  681. /*
  682. * If the adapter is not currently processing anything
  683. * and there is something on the queue, start it processing.
  684. */
  685. if(inl(port+DnListPtr) == 0 && ctlr->dnq)
  686. outl(port+DnListPtr, PADDR(&ctlr->dnhead->np));
  687. if(stalled)
  688. COMMAND(port, Stall, dnUnStall);
  689. }
  690. static void
  691. transmit(Ether* ether)
  692. {
  693. Ctlr *ctlr;
  694. int port, w;
  695. port = ether->port;
  696. ctlr = ether->ctlr;
  697. ilock(&ctlr->wlock);
  698. if(ctlr->dnenabled)
  699. txstart905(ether);
  700. else{
  701. w = (STATUS(port)>>13) & 0x07;
  702. COMMAND(port, SelectRegisterWindow, Wop);
  703. txstart(ether);
  704. COMMAND(port, SelectRegisterWindow, w);
  705. }
  706. iunlock(&ctlr->wlock);
  707. }
  708. static void
  709. receive905(Ether* ether)
  710. {
  711. Ctlr *ctlr;
  712. int len, port, q;
  713. Pd *pd;
  714. Block *bp;
  715. ctlr = ether->ctlr;
  716. port = ether->port;
  717. if(inl(port+UpPktStatus) & upStalled)
  718. ctlr->upstalls++;
  719. q = 0;
  720. for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){
  721. if(pd->control & upError){
  722. if(pd->control & upOverrun)
  723. ether->overflows++;
  724. if(pd->control & (upOversizedFrame|upRuntFrame))
  725. ether->buffs++;
  726. if(pd->control & upAlignmentError)
  727. ether->frames++;
  728. if(pd->control & upCRCError)
  729. ether->crcs++;
  730. }
  731. else if(bp = iallocb(sizeof(Etherpkt)+4)){
  732. len = pd->control & rxBytes;
  733. pd->bp->wp = pd->bp->rp+len;
  734. etheriq(ether, pd->bp, 1);
  735. pd->bp = bp;
  736. pd->addr = PADDR(bp->rp);
  737. coherence();
  738. }
  739. pd->control = 0;
  740. COMMAND(port, Stall, upUnStall);
  741. q++;
  742. }
  743. ctlr->uphead = pd;
  744. ctlr->upqueued += q;
  745. if(q > ctlr->upqmax)
  746. ctlr->upqmax = q;
  747. }
  748. static void
  749. receive(Ether* ether)
  750. {
  751. int len, port, rxerror, rxstatus;
  752. Ctlr *ctlr;
  753. Block *bp;
  754. port = ether->port;
  755. ctlr = ether->ctlr;
  756. while(((rxstatus = ins(port+RxStatus)) & rxIncomplete) == 0){
  757. if(ctlr->busmaster == 1 && (STATUS(port) & busMasterInProgress))
  758. break;
  759. /*
  760. * If there was an error, log it and continue.
  761. * Unfortunately the 3C5[078]9 has the error info in the status register
  762. * and the 3C59[0257] implement a separate RxError register.
  763. */
  764. if(rxstatus & rxError){
  765. if(ctlr->rxstatus9){
  766. switch(rxstatus & rxError9){
  767. case rxOverrun9:
  768. ether->overflows++;
  769. break;
  770. case oversizedFrame9:
  771. case runtFrame9:
  772. ether->buffs++;
  773. break;
  774. case alignmentError9:
  775. ether->frames++;
  776. break;
  777. case crcError9:
  778. ether->crcs++;
  779. break;
  780. }
  781. }
  782. else{
  783. rxerror = inb(port+RxError);
  784. if(rxerror & rxOverrun)
  785. ether->overflows++;
  786. if(rxerror & (oversizedFrame|runtFrame))
  787. ether->buffs++;
  788. if(rxerror & alignmentError)
  789. ether->frames++;
  790. if(rxerror & crcError)
  791. ether->crcs++;
  792. }
  793. }
  794. /*
  795. * If there was an error or a new receive buffer can't be
  796. * allocated, discard the packet and go on to the next.
  797. */
  798. if((rxstatus & rxError) || (bp = rbpalloc(iallocb)) == 0){
  799. COMMAND(port, RxDiscard, 0);
  800. while(STATUS(port) & commandInProgress)
  801. ;
  802. if(ctlr->busmaster == 1)
  803. startdma(ether, PADDR(ctlr->rbp->rp));
  804. continue;
  805. }
  806. /*
  807. * A valid receive packet awaits:
  808. * if using PIO, read it into the buffer;
  809. * discard the packet from the FIFO;
  810. * if using busmastering, start a new transfer for
  811. * the next packet and as a side-effect get the
  812. * end-pointer of the one just received;
  813. * pass the packet on to whoever wants it.
  814. */
  815. if(ctlr->busmaster == 0 || ctlr->busmaster == 2){
  816. len = (rxstatus & rxBytes9);
  817. ctlr->rbp->wp = ctlr->rbp->rp + len;
  818. insl(port+Fifo, ctlr->rbp->rp, HOWMANY(len, 4));
  819. }
  820. COMMAND(port, RxDiscard, 0);
  821. while(STATUS(port) & commandInProgress)
  822. ;
  823. if(ctlr->busmaster == 1)
  824. ctlr->rbp->wp = startdma(ether, PADDR(bp->rp));
  825. etheriq(ether, ctlr->rbp, 1);
  826. ctlr->rbp = bp;
  827. }
  828. }
  829. static int
  830. ejectable(int did)
  831. {
  832. switch (did) {
  833. case 0x5157:
  834. return 1;
  835. default:
  836. return 0;
  837. }
  838. }
  839. static void
  840. interrupt(Ureg*, void* arg)
  841. {
  842. Ether *ether;
  843. int port, status, s, txstatus, w, x;
  844. Ctlr *ctlr;
  845. ether = arg;
  846. port = ether->port;
  847. ctlr = ether->ctlr;
  848. ilock(&ctlr->wlock);
  849. status = STATUS(port);
  850. if(!(status & (interruptMask|interruptLatch))){
  851. ctlr->bogusinterrupts++;
  852. iunlock(&ctlr->wlock);
  853. return;
  854. }
  855. w = (status>>13) & 0x07;
  856. COMMAND(port, SelectRegisterWindow, Wop);
  857. ctlr->interrupts++;
  858. if(ctlr->busmaster == 2)
  859. ctlr->timer[0] += inb(port+TIMER905) & 0xFF;
  860. else
  861. ctlr->timer[0] += inb(port+TIMER) & 0xFF;
  862. do{
  863. if(status & hostError){
  864. /*
  865. * Adapter failure, try to find out why, reset if
  866. * necessary. What happens if Tx is active and a reset
  867. * occurs, need to retransmit? This probably isn't right.
  868. */
  869. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  870. x = ins(port+FifoDiagnostic);
  871. COMMAND(port, SelectRegisterWindow, Wop);
  872. if (status == 0xFFFF && x == 0xFFFF && ejectable(ctlr->did)) {
  873. print("#l%d: Card ejected?\n", ether->ctlrno);
  874. iunlock(&ctlr->wlock);
  875. return;
  876. }
  877. print("#l%d: status 0x%uX, diag 0x%uX\n",
  878. ether->ctlrno, status, x);
  879. if(x & txOverrun){
  880. if(ctlr->busmaster == 0)
  881. COMMAND(port, TxReset, 0);
  882. else
  883. COMMAND(port, TxReset, (updnReset|dmaReset));
  884. COMMAND(port, TxEnable, 0);
  885. }
  886. if(x & rxUnderrun){
  887. /*
  888. * This shouldn't happen...
  889. * Reset the receiver and restore the filter and RxEarly
  890. * threshold before re-enabling.
  891. * Need to restart any busmastering?
  892. */
  893. COMMAND(port, SelectRegisterWindow, Wstate);
  894. s = (port+RxFilter) & 0x000F;
  895. COMMAND(port, SelectRegisterWindow, Wop);
  896. COMMAND(port, RxReset, 0);
  897. while(STATUS(port) & commandInProgress)
  898. ;
  899. COMMAND(port, SetRxFilter, s);
  900. COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
  901. COMMAND(port, RxEnable, 0);
  902. }
  903. status &= ~hostError;
  904. }
  905. if(status & (transferInt|rxComplete)){
  906. receive(ether);
  907. status &= ~(transferInt|rxComplete);
  908. }
  909. if(status & (upComplete)){
  910. COMMAND(port, AcknowledgeInterrupt, upComplete);
  911. receive905(ether);
  912. status &= ~upComplete;
  913. ctlr->upinterrupts++;
  914. }
  915. if(status & txComplete){
  916. /*
  917. * Pop the TxStatus stack, accumulating errors.
  918. * Adjust the TX start threshold if there was an underrun.
  919. * If there was a Jabber or Underrun error, reset
  920. * the transmitter, taking care not to reset the dma logic
  921. * as a busmaster receive may be in progress.
  922. * For all conditions enable the transmitter.
  923. */
  924. if(ctlr->busmaster == 2)
  925. txstatus = port+TxStatus905;
  926. else
  927. txstatus = port+TxStatus;
  928. s = 0;
  929. do{
  930. if(x = inb(txstatus))
  931. outb(txstatus, 0);
  932. s |= x;
  933. }while(STATUS(port) & txComplete);
  934. if(s & txUnderrun){
  935. if(ctlr->dnenabled){
  936. while(inl(port+PktStatus) & dnInProg)
  937. ;
  938. }
  939. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  940. while(ins(port+MediaStatus) & txInProg)
  941. ;
  942. COMMAND(port, SelectRegisterWindow, Wop);
  943. if(ctlr->txthreshold < ETHERMAXTU)
  944. ctlr->txthreshold += ETHERMINTU;
  945. }
  946. /*
  947. * According to the manual, maxCollisions does not require
  948. * a TxReset, merely a TxEnable. However, evidence points to
  949. * it being necessary on the 3C905. The jury is still out.
  950. * On busy or badly configured networks maxCollisions can
  951. * happen frequently enough for messages to be annoying so
  952. * keep quiet about them by popular request.
  953. */
  954. if(s & (txJabber|txUnderrun|maxCollisions)){
  955. if(ctlr->busmaster == 0)
  956. COMMAND(port, TxReset, 0);
  957. else
  958. COMMAND(port, TxReset, (updnReset|dmaReset));
  959. while(STATUS(port) & commandInProgress)
  960. ;
  961. COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
  962. if(ctlr->busmaster == 2)
  963. outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
  964. if(ctlr->dnenabled)
  965. status |= dnComplete;
  966. }
  967. if(s & ~(txStatusComplete|maxCollisions))
  968. print("#l%d: txstatus 0x%uX, threshold %d\n",
  969. ether->ctlrno, s, ctlr->txthreshold);
  970. COMMAND(port, TxEnable, 0);
  971. ether->oerrs++;
  972. status &= ~txComplete;
  973. status |= txAvailable;
  974. }
  975. if(status & txAvailable){
  976. COMMAND(port, AcknowledgeInterrupt, txAvailable);
  977. ctlr->txbusy = 0;
  978. txstart(ether);
  979. status &= ~txAvailable;
  980. }
  981. if(status & dnComplete){
  982. COMMAND(port, AcknowledgeInterrupt, dnComplete);
  983. txstart905(ether);
  984. status &= ~dnComplete;
  985. ctlr->dninterrupts++;
  986. }
  987. if(status & updateStats){
  988. statistics(ether);
  989. status &= ~updateStats;
  990. }
  991. /*
  992. * Currently, this shouldn't happen.
  993. */
  994. if(status & rxEarly){
  995. COMMAND(port, AcknowledgeInterrupt, rxEarly);
  996. status &= ~rxEarly;
  997. }
  998. /*
  999. * Panic if there are any interrupts not dealt with.
  1000. */
  1001. if(status & interruptMask)
  1002. panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
  1003. COMMAND(port, AcknowledgeInterrupt, interruptLatch);
  1004. if(ctlr->cbfn != nil)
  1005. intrackcb(ctlr->cbfn);
  1006. }while((status = STATUS(port)) & (interruptMask|interruptLatch));
  1007. if(ctlr->busmaster == 2)
  1008. ctlr->timer[1] += inb(port+TIMER905) & 0xFF;
  1009. else
  1010. ctlr->timer[1] += inb(port+TIMER) & 0xFF;
  1011. COMMAND(port, SelectRegisterWindow, w);
  1012. iunlock(&ctlr->wlock);
  1013. }
  1014. static long
  1015. ifstat(Ether* ether, void* a, long n, ulong offset)
  1016. {
  1017. char *p;
  1018. int len;
  1019. Ctlr *ctlr;
  1020. if(n == 0)
  1021. return 0;
  1022. ctlr = ether->ctlr;
  1023. ilock(&ctlr->wlock);
  1024. statistics(ether);
  1025. iunlock(&ctlr->wlock);
  1026. p = malloc(READSTR);
  1027. len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts);
  1028. len += snprint(p+len, READSTR-len, "bogusinterrupts: %lud\n", ctlr->bogusinterrupts);
  1029. len += snprint(p+len, READSTR-len, "timer: %lud %lud\n",
  1030. ctlr->timer[0], ctlr->timer[1]);
  1031. len += snprint(p+len, READSTR-len, "carrierlost: %lud\n",
  1032. ctlr->stats[CarrierLost]);
  1033. len += snprint(p+len, READSTR-len, "sqeerrors: %lud\n",
  1034. ctlr->stats[SqeErrors]);
  1035. len += snprint(p+len, READSTR-len, "multiplecolls: %lud\n",
  1036. ctlr->stats[MultipleColls]);
  1037. len += snprint(p+len, READSTR-len, "singlecollframes: %lud\n",
  1038. ctlr->stats[SingleCollFrames]);
  1039. len += snprint(p+len, READSTR-len, "latecollisions: %lud\n",
  1040. ctlr->stats[LateCollisions]);
  1041. len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n",
  1042. ctlr->stats[RxOverruns]);
  1043. len += snprint(p+len, READSTR-len, "framesxmittedok: %lud\n",
  1044. ctlr->stats[FramesXmittedOk]);
  1045. len += snprint(p+len, READSTR-len, "framesrcvdok: %lud\n",
  1046. ctlr->stats[FramesRcvdOk]);
  1047. len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n",
  1048. ctlr->stats[FramesDeferred]);
  1049. len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n",
  1050. ctlr->stats[BytesRcvdOk]);
  1051. len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n",
  1052. ctlr->stats[BytesRcvdOk+1]);
  1053. if(ctlr->upenabled){
  1054. if(ctlr->upqmax > ctlr->upqmaxhw)
  1055. ctlr->upqmaxhw = ctlr->upqmax;
  1056. len += snprint(p+len, READSTR-len, "up: q %lud i %lud m %d h %d s %lud\n",
  1057. ctlr->upqueued, ctlr->upinterrupts,
  1058. ctlr->upqmax, ctlr->upqmaxhw, ctlr->upstalls);
  1059. ctlr->upqmax = 0;
  1060. }
  1061. if(ctlr->dnenabled){
  1062. if(ctlr->dnqmax > ctlr->dnqmaxhw)
  1063. ctlr->dnqmaxhw = ctlr->dnqmax;
  1064. len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d h %d\n",
  1065. ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax, ctlr->dnqmaxhw);
  1066. ctlr->dnqmax = 0;
  1067. }
  1068. snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]);
  1069. n = readstr(offset, a, n, p);
  1070. free(p);
  1071. return n;
  1072. }
  1073. static void
  1074. txrxreset(int port)
  1075. {
  1076. COMMAND(port, TxReset, 0);
  1077. while(STATUS(port) & commandInProgress)
  1078. ;
  1079. COMMAND(port, RxReset, 0);
  1080. while(STATUS(port) & commandInProgress)
  1081. ;
  1082. }
  1083. static Ctlr*
  1084. tcmadapter(int port, int irq, Pcidev* pcidev)
  1085. {
  1086. Ctlr *ctlr;
  1087. ctlr = malloc(sizeof(Ctlr));
  1088. ctlr->port = port;
  1089. ctlr->irq = irq;
  1090. ctlr->pcidev = pcidev;
  1091. ctlr->eepromcmd = EepromReadRegister;
  1092. if(ctlrhead != nil)
  1093. ctlrtail->next = ctlr;
  1094. else
  1095. ctlrhead = ctlr;
  1096. ctlrtail = ctlr;
  1097. return ctlr;
  1098. }
  1099. /*
  1100. * Write two 0 bytes to identify the IDport and then reset the
  1101. * ID sequence. Then send the ID sequence to the card to get
  1102. * the card into command state.
  1103. */
  1104. static void
  1105. idseq(void)
  1106. {
  1107. int i;
  1108. uchar al;
  1109. static int reset, untag;
  1110. /*
  1111. * One time only:
  1112. * reset any adapters listening
  1113. */
  1114. if(reset == 0){
  1115. outb(IDport, 0);
  1116. outb(IDport, 0);
  1117. outb(IDport, 0xC0);
  1118. delay(20);
  1119. reset = 1;
  1120. }
  1121. outb(IDport, 0);
  1122. outb(IDport, 0);
  1123. for(al = 0xFF, i = 0; i < 255; i++){
  1124. outb(IDport, al);
  1125. if(al & 0x80){
  1126. al <<= 1;
  1127. al ^= 0xCF;
  1128. }
  1129. else
  1130. al <<= 1;
  1131. }
  1132. /*
  1133. * One time only:
  1134. * write ID sequence to get the attention of all adapters;
  1135. * untag all adapters.
  1136. * If a global reset is done here on all adapters it will confuse
  1137. * any ISA cards configured for EISA mode.
  1138. */
  1139. if(untag == 0){
  1140. outb(IDport, 0xD0);
  1141. untag = 1;
  1142. }
  1143. }
  1144. static ulong
  1145. activate(void)
  1146. {
  1147. int i;
  1148. ushort x, acr;
  1149. /*
  1150. * Do the little configuration dance:
  1151. *
  1152. * 2. write the ID sequence to get to command state.
  1153. */
  1154. idseq();
  1155. /*
  1156. * 3. Read the Manufacturer ID from the EEPROM.
  1157. * This is done by writing the IDPort with 0x87 (0x80
  1158. * is the 'read EEPROM' command, 0x07 is the offset of
  1159. * the Manufacturer ID field in the EEPROM).
  1160. * The data comes back 1 bit at a time.
  1161. * A delay seems necessary between reading the bits.
  1162. *
  1163. * If the ID doesn't match, there are no more adapters.
  1164. */
  1165. outb(IDport, 0x87);
  1166. delay(20);
  1167. for(x = 0, i = 0; i < 16; i++){
  1168. delay(20);
  1169. x <<= 1;
  1170. x |= inb(IDport) & 0x01;
  1171. }
  1172. if(x != 0x6D50)
  1173. return 0;
  1174. /*
  1175. * 3. Read the Address Configuration from the EEPROM.
  1176. * The Address Configuration field is at offset 0x08 in the EEPROM).
  1177. */
  1178. outb(IDport, 0x88);
  1179. for(acr = 0, i = 0; i < 16; i++){
  1180. delay(20);
  1181. acr <<= 1;
  1182. acr |= inb(IDport) & 0x01;
  1183. }
  1184. return (acr & 0x1F)*0x10 + 0x200;
  1185. }
  1186. static void
  1187. tcm509isa(void)
  1188. {
  1189. int irq, port;
  1190. /*
  1191. * Attempt to activate all adapters. If adapter is set for
  1192. * EISA mode (0x3F0), tag it and ignore. Otherwise, activate
  1193. * it fully.
  1194. */
  1195. while(port = activate()){
  1196. if(ioalloc(port, 0x10, 0, "tcm509isa") < 0){
  1197. print("tcm509isa: port 0x%uX in use\n", port);
  1198. continue;
  1199. }
  1200. /*
  1201. * 6. Tag the adapter so it won't respond in future.
  1202. */
  1203. outb(IDport, 0xD1);
  1204. if(port == 0x3F0){
  1205. iofree(port);
  1206. continue;
  1207. }
  1208. /*
  1209. * 6. Activate the adapter by writing the Activate command
  1210. * (0xFF).
  1211. */
  1212. outb(IDport, 0xFF);
  1213. delay(20);
  1214. /*
  1215. * 8. Can now talk to the adapter's I/O base addresses.
  1216. * Use the I/O base address from the acr just read.
  1217. *
  1218. * Enable the adapter and clear out any lingering status
  1219. * and interrupts.
  1220. */
  1221. while(STATUS(port) & commandInProgress)
  1222. ;
  1223. COMMAND(port, SelectRegisterWindow, Wsetup);
  1224. outs(port+ConfigControl, Ena);
  1225. txrxreset(port);
  1226. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1227. irq = (ins(port+ResourceConfig)>>12) & 0x0F;
  1228. tcmadapter(port, irq, nil);
  1229. }
  1230. }
  1231. static void
  1232. tcm5XXeisa(void)
  1233. {
  1234. ushort x;
  1235. int irq, port, slot;
  1236. /*
  1237. * Check if this is an EISA machine.
  1238. * If not, nothing to do.
  1239. */
  1240. if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4))
  1241. return;
  1242. /*
  1243. * Continue through the EISA slots looking for a match on both
  1244. * 3COM as the manufacturer and 3C579-* or 3C59[27]-* as the product.
  1245. * If an adapter is found, select window 0, enable it and clear
  1246. * out any lingering status and interrupts.
  1247. */
  1248. for(slot = 1; slot < MaxEISA; slot++){
  1249. port = slot*0x1000;
  1250. if(ioalloc(port, 0x1000, 0, "tcm5XXeisa") < 0){
  1251. print("tcm5XXeisa: port 0x%uX in use\n", port);
  1252. continue;
  1253. }
  1254. if(ins(port+0xC80+ManufacturerID) != 0x6D50){
  1255. iofree(port);
  1256. continue;
  1257. }
  1258. x = ins(port+0xC80+ProductID);
  1259. if((x & 0xF0FF) != 0x9050 && (x & 0xFF00) != 0x5900){
  1260. iofree(port);
  1261. continue;
  1262. }
  1263. COMMAND(port, SelectRegisterWindow, Wsetup);
  1264. outs(port+ConfigControl, Ena);
  1265. txrxreset(port);
  1266. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1267. irq = (ins(port+ResourceConfig)>>12) & 0x0F;
  1268. tcmadapter(port, irq, nil);
  1269. }
  1270. }
  1271. static void
  1272. tcm59Xpci(void)
  1273. {
  1274. Pcidev *p;
  1275. Ctlr *ctlr;
  1276. int irq, port;
  1277. p = nil;
  1278. while(p = pcimatch(p, 0x10B7, 0)){
  1279. if(p->ccrb != 0x02 || p->ccru != 0)
  1280. continue;
  1281. /*
  1282. * Not prepared to deal with memory-mapped
  1283. * devices yet.
  1284. */
  1285. if(!(p->mem[0].bar & 0x01))
  1286. continue;
  1287. port = p->mem[0].bar & ~0x01;
  1288. if((port = ioalloc((port == 0)? -1: port, p->mem[0].size,
  1289. 0, "tcm59Xpci")) < 0){
  1290. print("tcm59Xpci: port 0x%uX in use\n", port);
  1291. continue;
  1292. }
  1293. irq = p->intl;
  1294. txrxreset(port);
  1295. COMMAND(port, AcknowledgeInterrupt, 0xFF);
  1296. ctlr = tcmadapter(port, irq, p);
  1297. switch(p->did){
  1298. default:
  1299. break;
  1300. case 0x5157:
  1301. ctlr->eepromcmd = EepromRead8bRegister;
  1302. ctlr->cbfnpa = p->mem[2].bar&~0x0F;
  1303. ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
  1304. break;
  1305. case 0x6056:
  1306. ctlr->eepromcmd = EepromReadOffRegister;
  1307. ctlr->cbfnpa = p->mem[2].bar&~0x0F;
  1308. ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
  1309. break;
  1310. }
  1311. pcisetbme(p);
  1312. }
  1313. }
  1314. static char* tcmpcmcia[] = {
  1315. "3C589", /* 3COM 589[ABCD] */
  1316. "3C562", /* 3COM 562 */
  1317. "589E", /* 3COM Megahertz 589E */
  1318. nil,
  1319. };
  1320. static Ctlr*
  1321. tcm5XXpcmcia(Ether* ether)
  1322. {
  1323. int i;
  1324. Ctlr *ctlr;
  1325. if(ether->type == nil)
  1326. return nil;
  1327. for(i = 0; tcmpcmcia[i] != nil; i++){
  1328. if(cistrcmp(ether->type, tcmpcmcia[i]))
  1329. continue;
  1330. ctlr = tcmadapter(ether->port, ether->irq, nil);
  1331. ctlr->active = 1;
  1332. return ctlr;
  1333. }
  1334. return nil;
  1335. }
  1336. static void
  1337. setxcvr(Ctlr* ctlr, int xcvr)
  1338. {
  1339. int port, x;
  1340. port = ctlr->port;
  1341. if(ctlr->rxstatus9){
  1342. COMMAND(port, SelectRegisterWindow, Wsetup);
  1343. x = ins(port+AddressConfig) & ~xcvrMask9;
  1344. x |= (xcvr>>20)<<14;
  1345. outs(port+AddressConfig, x);
  1346. }
  1347. else{
  1348. COMMAND(port, SelectRegisterWindow, Wfifo);
  1349. x = inl(port+InternalConfig) & ~xcvrMask;
  1350. x |= xcvr;
  1351. outl(port+InternalConfig, x);
  1352. }
  1353. txrxreset(port);
  1354. }
  1355. static void
  1356. setfullduplex(int port)
  1357. {
  1358. int x;
  1359. COMMAND(port, SelectRegisterWindow, Wfifo);
  1360. x = ins(port+MacControl);
  1361. outs(port+MacControl, fullDuplexEnable|x);
  1362. txrxreset(port);
  1363. }
  1364. static int
  1365. miimdi(int port, int n)
  1366. {
  1367. int data, i;
  1368. /*
  1369. * Read n bits from the MII Management Register.
  1370. */
  1371. data = 0;
  1372. for(i = n-1; i >= 0; i--){
  1373. if(ins(port) & mgmtData)
  1374. data |= (1<<i);
  1375. microdelay(1);
  1376. outs(port, mgmtClk);
  1377. microdelay(1);
  1378. outs(port, 0);
  1379. microdelay(1);
  1380. }
  1381. return data;
  1382. }
  1383. static void
  1384. miimdo(int port, int bits, int n)
  1385. {
  1386. int i, mdo;
  1387. /*
  1388. * Write n bits to the MII Management Register.
  1389. */
  1390. for(i = n-1; i >= 0; i--){
  1391. if(bits & (1<<i))
  1392. mdo = mgmtDir|mgmtData;
  1393. else
  1394. mdo = mgmtDir;
  1395. outs(port, mdo);
  1396. microdelay(1);
  1397. outs(port, mdo|mgmtClk);
  1398. microdelay(1);
  1399. outs(port, mdo);
  1400. microdelay(1);
  1401. }
  1402. }
  1403. static int
  1404. miir(int port, int phyad, int regad)
  1405. {
  1406. int data, w;
  1407. w = (STATUS(port)>>13) & 0x07;
  1408. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1409. port += PhysicalMgmt;
  1410. /*
  1411. * Preamble;
  1412. * ST+OP+PHYAD+REGAD;
  1413. * TA + 16 data bits.
  1414. */
  1415. miimdo(port, 0xFFFFFFFF, 32);
  1416. miimdo(port, 0x1800|(phyad<<5)|regad, 14);
  1417. data = miimdi(port, 18);
  1418. port -= PhysicalMgmt;
  1419. COMMAND(port, SelectRegisterWindow, w);
  1420. if(data & 0x10000)
  1421. return -1;
  1422. return data & 0xFFFF;
  1423. }
  1424. static int
  1425. scanphy(int port)
  1426. {
  1427. int i, x;
  1428. for(i = 0; i < 32; i++){
  1429. if((x = miir(port, i, 2)) == -1 || x == 0)
  1430. continue;
  1431. x <<= 6;
  1432. x |= miir(port, i, 3)>>10;
  1433. XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
  1434. USED(x);
  1435. return i;
  1436. }
  1437. return 24;
  1438. }
  1439. static struct {
  1440. char *name;
  1441. int avail;
  1442. int xcvr;
  1443. } media[] = {
  1444. "10BaseT", base10TAvailable, xcvr10BaseT,
  1445. "10Base2", coaxAvailable, xcvr10Base2,
  1446. "100BaseTX", baseTXAvailable, xcvr100BaseTX,
  1447. "100BaseFX", baseFXAvailable, xcvr100BaseFX,
  1448. "aui", auiAvailable, xcvrAui,
  1449. "mii", miiConnector, xcvrMii
  1450. };
  1451. static int
  1452. autoselect(Ctlr* ctlr)
  1453. {
  1454. int media, port, x;
  1455. /*
  1456. * Pathetic attempt at automatic media selection.
  1457. * Really just to get the Fast Etherlink 10BASE-T/100BASE-TX
  1458. * cards operational.
  1459. * It's a bonus if it works for anything else.
  1460. */
  1461. port = ctlr->port;
  1462. if(ctlr->rxstatus9){
  1463. COMMAND(port, SelectRegisterWindow, Wsetup);
  1464. x = ins(port+ConfigControl);
  1465. media = 0;
  1466. if(x & base10TAvailable9)
  1467. media |= base10TAvailable;
  1468. if(x & coaxAvailable9)
  1469. media |= coaxAvailable;
  1470. if(x & auiAvailable9)
  1471. media |= auiAvailable;
  1472. }
  1473. else{
  1474. COMMAND(port, SelectRegisterWindow, Wfifo);
  1475. media = ins(port+ResetOptions);
  1476. }
  1477. XCVRDEBUG("autoselect: media %uX\n", media);
  1478. if(media & miiConnector)
  1479. return xcvrMii;
  1480. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1481. XCVRDEBUG("autoselect: media status %uX\n", ins(port+MediaStatus));
  1482. if(media & baseTXAvailable){
  1483. /*
  1484. * Must have InternalConfig register.
  1485. */
  1486. setxcvr(ctlr, xcvr100BaseTX);
  1487. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1488. x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
  1489. outs(port+MediaStatus, linkBeatEnable|x);
  1490. delay(10);
  1491. if(ins(port+MediaStatus) & linkBeatDetect)
  1492. return xcvr100BaseTX;
  1493. outs(port+MediaStatus, x);
  1494. }
  1495. if(media & base10TAvailable){
  1496. setxcvr(ctlr, xcvr10BaseT);
  1497. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1498. x = ins(port+MediaStatus) & ~dcConverterEnabled;
  1499. outs(port+MediaStatus, linkBeatEnable|jabberGuardEnable|x);
  1500. delay(100);
  1501. XCVRDEBUG("autoselect: 10BaseT media status %uX\n", ins(port+MediaStatus));
  1502. if(ins(port+MediaStatus) & linkBeatDetect)
  1503. return xcvr10BaseT;
  1504. outs(port+MediaStatus, x);
  1505. }
  1506. /*
  1507. * Botch.
  1508. */
  1509. return autoSelect;
  1510. }
  1511. static int
  1512. eepromdata(Ctlr* ctlr, int offset)
  1513. {
  1514. int port;
  1515. port = ctlr->port;
  1516. COMMAND(port, SelectRegisterWindow, Wsetup);
  1517. while(EEPROMBUSY(port))
  1518. ;
  1519. EEPROMCMD(port, ctlr->eepromcmd, offset);
  1520. while(EEPROMBUSY(port))
  1521. ;
  1522. return EEPROMDATA(port);
  1523. }
  1524. static void
  1525. resetctlr(Ctlr *ctlr)
  1526. {
  1527. int x, port = ctlr->port;
  1528. txrxreset(port);
  1529. x = ins(port+ResetOp905B);
  1530. XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
  1531. x &= ~0x4010;
  1532. if(ctlr->did == 0x5157){
  1533. x |= 0x0010; /* Invert LED */
  1534. outs(port+ResetOp905B, x);
  1535. }
  1536. if(ctlr->did == 0x6056){
  1537. x |= 0x4000;
  1538. outs(port+ResetOp905B, x);
  1539. COMMAND(port, SelectRegisterWindow, Wsetup);
  1540. outs(port, 0x0800);
  1541. }
  1542. }
  1543. static void
  1544. shutdown(Ether *ether)
  1545. {
  1546. print("etherelnk3 shutting down\n");
  1547. resetctlr(ether->ctlr);
  1548. }
  1549. int
  1550. etherelnk3reset(Ether* ether)
  1551. {
  1552. char *p;
  1553. Ctlr *ctlr;
  1554. uchar ea[Eaddrlen];
  1555. static int scandone;
  1556. int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
  1557. /*
  1558. * Scan for adapter on PCI, EISA and finally
  1559. * using the little ISA configuration dance.
  1560. */
  1561. if(scandone == 0){
  1562. tcm59Xpci();
  1563. tcm5XXeisa();
  1564. tcm509isa();
  1565. scandone = 1;
  1566. }
  1567. /*
  1568. * Any adapter matches if no ether->port is supplied,
  1569. * otherwise the ports must match.
  1570. */
  1571. for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  1572. if(ctlr->active)
  1573. continue;
  1574. if(ether->port == 0 || ether->port == ctlr->port){
  1575. ctlr->active = 1;
  1576. break;
  1577. }
  1578. }
  1579. if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
  1580. return -1;
  1581. ether->ctlr = ctlr;
  1582. port = ctlr->port;
  1583. ether->port = port;
  1584. ether->irq = ctlr->irq;
  1585. if(ctlr->pcidev != nil)
  1586. ether->tbdf = ctlr->pcidev->tbdf;
  1587. else
  1588. ether->tbdf = BUSUNKNOWN;
  1589. /*
  1590. * Read the DeviceID from the EEPROM, it's at offset 0x03,
  1591. * and do something depending on capabilities.
  1592. */
  1593. switch(ctlr->did = eepromdata(ctlr, 0x03)){
  1594. case 0x5157: /* 3C575 Cyclone */
  1595. case 0x6056:
  1596. /*FALLTHROUGH*/
  1597. case 0x4500: /* 3C450 HomePNA Tornado */
  1598. case 0x7646: /* 3CSOHO100-TX */
  1599. case 0x9055: /* 3C905B-TX */
  1600. case 0x9200: /* 3C905C-TX */
  1601. case 0x9201: /* 3C920 */
  1602. case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
  1603. /*FALLTHROUGH*/
  1604. case 0x9000: /* 3C900-TPO */
  1605. case 0x9001: /* 3C900-COMBO */
  1606. case 0x9005: /* 3C900B-COMBO */
  1607. case 0x9050: /* 3C905-TX */
  1608. case 0x9051: /* 3C905-T4 */
  1609. if(BUSTYPE(ether->tbdf) != BusPCI)
  1610. goto buggery;
  1611. ctlr->busmaster = 2;
  1612. goto vortex;
  1613. case 0x5900: /* 3C590-[TP|COMBO|TPO] */
  1614. case 0x5920: /* 3C592-[TP|COMBO|TPO] */
  1615. case 0x5950: /* 3C595-TX */
  1616. case 0x5951: /* 3C595-T4 */
  1617. case 0x5952: /* 3C595-MII */
  1618. case 0x5970: /* 3C597-TX */
  1619. case 0x5971: /* 3C597-T4 */
  1620. case 0x5972: /* 3C597-MII */
  1621. ctlr->busmaster = 1;
  1622. vortex:
  1623. COMMAND(port, SelectRegisterWindow, Wfifo);
  1624. ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
  1625. ctlr->rxearly = 8188;
  1626. ctlr->rxstatus9 = 0;
  1627. break;
  1628. buggery:
  1629. default:
  1630. ctlr->busmaster = 0;
  1631. COMMAND(port, SelectRegisterWindow, Wsetup);
  1632. x = ins(port+AddressConfig);
  1633. ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
  1634. if(x & autoSelect9)
  1635. ctlr->xcvr |= autoSelect;
  1636. ctlr->rxearly = 2044;
  1637. ctlr->rxstatus9 = 1;
  1638. break;
  1639. }
  1640. if(ctlr->rxearly >= 2048)
  1641. ctlr->ts = 2;
  1642. /*
  1643. * Check if the adapter's station address is to be overridden.
  1644. * If not, read it from the EEPROM and set in ether->ea prior to
  1645. * loading the station address in Wstation.
  1646. * The EEPROM returns 16-bits at a time.
  1647. */
  1648. memset(ea, 0, Eaddrlen);
  1649. if(memcmp(ea, ether->ea, Eaddrlen) == 0){
  1650. for(i = 0; i < Eaddrlen/2; i++){
  1651. x = eepromdata(ctlr, i);
  1652. ether->ea[2*i] = x>>8;
  1653. ether->ea[2*i+1] = x;
  1654. }
  1655. }
  1656. COMMAND(port, SelectRegisterWindow, Wstation);
  1657. for(i = 0; i < Eaddrlen; i++)
  1658. outb(port+i, ether->ea[i]);
  1659. /*
  1660. * Enable the transceiver if necessary and determine whether
  1661. * busmastering can be used. Due to bugs in the first revision
  1662. * of the 3C59[05], don't use busmastering at 10Mbps.
  1663. */
  1664. XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
  1665. /*
  1666. * Allow user to specify desired media in plan9.ini
  1667. */
  1668. for(i = 0; i < ether->nopt; i++){
  1669. if(cistrncmp(ether->opt[i], "media=", 6) != 0)
  1670. continue;
  1671. p = ether->opt[i]+6;
  1672. for(j = 0; j < nelem(media); j++)
  1673. if(cistrcmp(p, media[j].name) == 0)
  1674. ctlr->xcvr = media[j].xcvr;
  1675. }
  1676. /*
  1677. * forgive me, but i am weak
  1678. */
  1679. switch(ctlr->did){
  1680. default:
  1681. if(ctlr->xcvr & autoSelect)
  1682. ctlr->xcvr = autoselect(ctlr);
  1683. break;
  1684. case 0x5157:
  1685. case 0x6056:
  1686. case 0x4500:
  1687. case 0x7646:
  1688. case 0x9055:
  1689. case 0x9200:
  1690. case 0x9201:
  1691. case 0x9805:
  1692. ctlr->xcvr = xcvrMii;
  1693. resetctlr(ctlr);
  1694. break;
  1695. }
  1696. XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
  1697. switch(ctlr->xcvr){
  1698. case xcvrMii:
  1699. /*
  1700. * Quick hack.
  1701. */
  1702. if(ctlr->did == 0x5157)
  1703. phyaddr = 0;
  1704. else if(ctlr->did == 0x6056)
  1705. phyaddr = scanphy(port);
  1706. else
  1707. phyaddr = 24;
  1708. for(i = 0; i < 7; i++)
  1709. XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
  1710. XCVRDEBUG("\n");
  1711. for(timeo = 0; timeo < 30; timeo++){
  1712. phystat = miir(port, phyaddr, 0x01);
  1713. if(phystat & 0x20)
  1714. break;
  1715. XCVRDEBUG(" %2.2uX", phystat);
  1716. delay(100);
  1717. }
  1718. XCVRDEBUG(" %2.2uX", miir(port, phyaddr, 0x01));
  1719. XCVRDEBUG("\n");
  1720. anar = miir(port, phyaddr, 0x04);
  1721. anlpar = miir(port, phyaddr, 0x05) & 0x03E0;
  1722. anar &= anlpar;
  1723. miir(port, phyaddr, 0x00);
  1724. XCVRDEBUG("mii an: %uX anlp: %uX r0:%uX r1:%uX\n",
  1725. anar, anlpar, miir(port, phyaddr, 0x00),
  1726. miir(port, phyaddr, 0x01));
  1727. for(i = 0; i < ether->nopt; i++){
  1728. if(cistrcmp(ether->opt[i], "fullduplex") == 0)
  1729. anar |= 0x0100;
  1730. else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
  1731. anar |= 0x0100;
  1732. else if(cistrcmp(ether->opt[i], "force100") == 0)
  1733. anar |= 0x0080;
  1734. }
  1735. XCVRDEBUG("mii anar: %uX\n", anar);
  1736. if(anar & 0x0100){ /* 100BASE-TXFD */
  1737. ether->mbps = 100;
  1738. setfullduplex(port);
  1739. }
  1740. else if(anar & 0x0200){ /* 100BASE-T4 */
  1741. /* nothing to do */
  1742. }
  1743. else if(anar & 0x0080) /* 100BASE-TX */
  1744. ether->mbps = 100;
  1745. else if(anar & 0x0040) /* 10BASE-TFD */
  1746. setfullduplex(port);
  1747. else{ /* 10BASE-T */
  1748. /* nothing to do */
  1749. }
  1750. break;
  1751. case xcvr100BaseTX:
  1752. case xcvr100BaseFX:
  1753. COMMAND(port, SelectRegisterWindow, Wfifo);
  1754. x = inl(port+InternalConfig) & ~ramPartitionMask;
  1755. outl(port+InternalConfig, x|ramPartition1to1);
  1756. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1757. x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
  1758. x |= linkBeatEnable;
  1759. outs(port+MediaStatus, x);
  1760. if(x & dataRate100)
  1761. ether->mbps = 100;
  1762. break;
  1763. case xcvr10BaseT:
  1764. /*
  1765. * Enable Link Beat and Jabber to start the
  1766. * transceiver.
  1767. */
  1768. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1769. x = ins(port+MediaStatus) & ~dcConverterEnabled;
  1770. x |= linkBeatEnable|jabberGuardEnable;
  1771. outs(port+MediaStatus, x);
  1772. if((ctlr->did & 0xFF00) == 0x5900)
  1773. ctlr->busmaster = 0;
  1774. break;
  1775. case xcvr10Base2:
  1776. COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  1777. x = ins(port+MediaStatus) & ~(linkBeatEnable|jabberGuardEnable);
  1778. outs(port+MediaStatus, x);
  1779. /*
  1780. * Start the DC-DC converter.
  1781. * Wait > 800 microseconds.
  1782. */
  1783. COMMAND(port, EnableDcConverter, 0);
  1784. delay(1);
  1785. break;
  1786. }
  1787. /*
  1788. * Wop is the normal operating register set.
  1789. * The 3C59[0257] adapters allow access to more than one register window
  1790. * at a time, but there are situations where switching still needs to be
  1791. * done, so just do it.
  1792. * Clear out any lingering Tx status.
  1793. */
  1794. COMMAND(port, SelectRegisterWindow, Wop);
  1795. if(ctlr->busmaster == 2)
  1796. x = port+TxStatus905;
  1797. else
  1798. x = port+TxStatus;
  1799. while(inb(x))
  1800. outb(x, 0);
  1801. /*
  1802. * Clear out the
  1803. * adapter statistics, clear the statistics logged into ctlr
  1804. * and enable statistics collection.
  1805. */
  1806. ilock(&ctlr->wlock);
  1807. statistics(ether);
  1808. memset(ctlr->stats, 0, sizeof(ctlr->stats));
  1809. COMMAND(port, StatisticsEnable, 0);
  1810. /*
  1811. * Allocate any receive buffers.
  1812. */
  1813. switch(ctlr->busmaster){
  1814. case 2:
  1815. ctlr->dnenabled = 1;
  1816. /*
  1817. * 10MUpldBug.
  1818. * Disabling is too severe, can use receive busmastering at
  1819. * 100Mbps OK, but how to tell which rate is actually being used -
  1820. * the 3c905 always seems to have dataRate100 set?
  1821. * Believe the bug doesn't apply if upRxEarlyEnable is set
  1822. * and the threshold is set such that uploads won't start
  1823. * until the whole packet has been received.
  1824. */
  1825. ctlr->upenabled = 1;
  1826. x = eepromdata(ctlr, 0x0F);
  1827. if(!(x & 0x01))
  1828. outl(port+PktStatus, upRxEarlyEnable);
  1829. if(ctlr->upenabled || ctlr->dnenabled){
  1830. ctlr->nup = Nup;
  1831. ctlr->ndn = Ndn;
  1832. init905(ctlr);
  1833. }
  1834. else {
  1835. ctlr->rbp = rbpalloc(iallocb);
  1836. if(ctlr->rbp == nil)
  1837. panic("can't reset ethernet: out of memory");
  1838. }
  1839. outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));
  1840. break;
  1841. default:
  1842. ctlr->rbp = rbpalloc(iallocb);
  1843. if(ctlr->rbp == nil)
  1844. panic("can't reset ethernet: out of memory");
  1845. break;
  1846. }
  1847. /*
  1848. * Set a base TxStartThresh which will be incremented
  1849. * if any txUnderrun errors occur and ensure no RxEarly
  1850. * interrupts happen.
  1851. */
  1852. ctlr->txthreshold = ETHERMAXTU/2;
  1853. COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
  1854. COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
  1855. iunlock(&ctlr->wlock);
  1856. /*
  1857. * Linkage to the generic ethernet driver.
  1858. */
  1859. ether->attach = attach;
  1860. ether->transmit = transmit;
  1861. ether->interrupt = interrupt;
  1862. ether->ifstat = ifstat;
  1863. ether->promiscuous = promiscuous;
  1864. ether->multicast = multicast;
  1865. ether->shutdown = shutdown;
  1866. ether->arg = ether;
  1867. return 0;
  1868. }
  1869. void
  1870. etherelnk3link(void)
  1871. {
  1872. addethercard("elnk3", etherelnk3reset);
  1873. addethercard("3C509", etherelnk3reset);
  1874. addethercard("3C575", etherelnk3reset);
  1875. }