Zynq.XEmac.Mod 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630
  1. MODULE XEmac; (** AUTHOR "Timothee Martiel"; PURPOSE "Zynq7000 Ethernet Controller Driver"; *)
  2. (** 2014.08.26 Adapted the driver for Minos to A2 *)
  3. IMPORT SYSTEM, Machine, Objects, Kernel, KernelLog, Network, Commands, Modules, Plugins;
  4. CONST
  5. Trace = FALSE;
  6. IRQ = 54;
  7. (* Directions in ErrorHandler *)
  8. Send = 1X;
  9. Recv = 2X;
  10. (* Link speed detect modes *)
  11. LinkSpeedAutodetect = 0;
  12. LinkSpeed10 = 1;
  13. LinkSpeed100 = 2;
  14. LinkSpeed1000 = 3;
  15. LinkSpeedMode = LinkSpeedAutodetect;
  16. (* state *)
  17. IsReady = 11111111H;
  18. IsStarted = 22222222H;
  19. (* Buffer descriptors *)
  20. BdSize = 8;
  21. RxBdCount = 512;
  22. TxBdCount = 512;
  23. BdAdrOffset = 0H;
  24. BdStatOffset = 4H;
  25. BufSize = 1536;
  26. ZeroMAC = SYSTEM.VAL(Network.LinkAdr, [0X, 0X, 0X, 0X, 0X, 0X, 0X, 0X]);
  27. MaxTypeId = 4;
  28. (* Options *)
  29. (**
  30. * Accept all incoming packets.
  31. * This option defaults to disabled (cleared)
  32. *)
  33. Promisc = 0;
  34. (**
  35. * Frame larger than 1516 support for Tx & Rx.
  36. * This option defaults to disabled (cleared)
  37. *)
  38. Frame1536 = 1;(* 00000002H; *)
  39. (**
  40. * VLAN Rx & Tx frame support.
  41. * This option defaults to disabled (cleared)
  42. *)
  43. Vlan = 2;(* 00000004H; *)
  44. (**
  45. * Enable recognition of flow control frames on Rx
  46. * This option defaults to enabled (set)
  47. *)
  48. FlowControl = 4;(* 00000010H; *)
  49. (**
  50. * Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not
  51. * stripped.
  52. * This option defaults to enabled (set)
  53. *)
  54. FcsStrip = 5;(* 00000020H; *)
  55. (**
  56. * Generate FCS field and add PAD automatically for outgoing frames.
  57. * This option defaults to disabled (cleared)
  58. *)
  59. FcsInsert = 6;(* 00000040H; *)
  60. (**
  61. * Enable Length/TYPE error checking for incoming frames. When this option is
  62. * set, the MAC will filter frames that have a mismatched TYPE/length field
  63. * and if REPORT_RXERR is set, the user is notified when these
  64. * TYPEs of frames are encountered. When this option is cleared, the MAC will
  65. * allow these TYPEs of frames to be received.
  66. *
  67. * This option defaults to disabled (cleared)
  68. *)
  69. LenTypeErr = 7;(* 00000080H; *)
  70. (**
  71. * Enable the transmitter.
  72. * This option defaults to enabled (set)
  73. *)
  74. TransmitterEnable = 8;(* 00000100H; *)
  75. (**
  76. * Enable the receiver
  77. * This option defaults to enabled (set)
  78. *)
  79. ReceiverEnable = 9;(*00000200H *);
  80. (**
  81. * Allow reception of the broadcast address
  82. * This option defaults to enabled (set)
  83. *)
  84. Broadcast = 10;(* 00000400H; *)
  85. (**
  86. * Allows reception of multicast addresses programmed into hash
  87. * This option defaults to disabled (clear)
  88. *)
  89. Multicast = 11;(* 00000800H; *)
  90. (**
  91. * Enable the RX checksum offload
  92. * This option defaults to enabled (set)
  93. *)
  94. RxChksumEnable = 12;(* 00001000H; *)
  95. (**
  96. * Enable the TX checksum offload
  97. * This option defaults to enabled (set)
  98. *)
  99. TxChksumEnable = 13;(* 00002000H; *)
  100. Defaults = {Promisc, FlowControl, FcsInsert, FcsStrip, Broadcast, LenTypeErr, TransmitterEnable, ReceiverEnable, RxChksumEnable, TxChksumEnable};
  101. (* Register relative addresses *)
  102. Nwctrl = 0H;
  103. Nwcfg = 4H;
  104. Nwsr = 8H;
  105. Dmacr = 10H;
  106. Txsr = 14H;
  107. Rxqbase = 18H;
  108. Txqbase = 1CH;
  109. Rxsr = 20H;
  110. Isr = 24H;
  111. Ier = 28H;
  112. Idr = 2CH;
  113. Imr = 30H;
  114. PhyMntnc = 34H;
  115. Rxpause = 38H;
  116. Txpause = 3CH;
  117. HashL = 80H;
  118. HashH = 84H;
  119. Last = 1B4H;
  120. Laddr1l = 88H;
  121. Laddr1h = 8CH;
  122. Laddr2l = 90H;
  123. Laddr2h = 94H;
  124. Laddr3l = 98H;
  125. Laddr3h = 9CH;
  126. Laddr4l = 0A0H;
  127. Laddr4h = 0A4H;
  128. Match1 = 0A8H;
  129. Match2 = 0ACH;
  130. Match3 = 0B0H;
  131. Match4 = 0B4H;
  132. Stretch = 0BCH;
  133. OctTxL = 100H;
  134. OctTxH = 104H;
  135. Txcnt = 108H;
  136. Txbccnt = 10CH;
  137. Txmccnt = 110H;
  138. Txpausecnt = 114H;
  139. Tx64cnt = 118H;
  140. Tx65cnt = 11CH;
  141. Tx128cnt = 120H;
  142. Tx256cnt = 124H;
  143. Tx512cnt = 128H;
  144. Tx1024cnt = 12CH;
  145. Tx1519cnt = 130H;
  146. Txuruncnt = 134H;
  147. Snglcollcnt = 138H;
  148. Multicollcnt = 13CH;
  149. Excesscollcnt = 140H;
  150. Latecollcnt = 144H;
  151. Txdefercnt = 148H;
  152. Txcsensecnt = 14CH;
  153. Octrxl = 150H;
  154. Octrxh = 154H;
  155. Rxcnt = 158H;
  156. Rxbroadcnt = 15CH;
  157. Rxmulticnt = 160H;
  158. Rxpausecnt = 164H;
  159. Rx64cnt = 168H;
  160. Rx65cnt = 16CH;
  161. Rx128cnt = 170H;
  162. Rx256cnt = 174H;
  163. Rx512cnt = 178H;
  164. Rx1024cnt = 17CH;
  165. Rx1519cnt = 180H;
  166. Rxundrcnt = 184H;
  167. Rxovrcnt = 188H;
  168. Rxjabcnt = 18CH;
  169. Rxfcscnt = 190H;
  170. Rxlengthcnt = 194H;
  171. Rxsymbcnt = 198H;
  172. Rxaligncnt = 19CH;
  173. Rxreserrcnt = 1A0H;
  174. Rxorcnt = 1A4H;
  175. Rxipccnt = 1A8H;
  176. Rxtcpccnt = 1ACH;
  177. Rxudpccnt = 1B0H;
  178. C1588_sec = 1D0H;
  179. C1588_nanosec = 1D4H;
  180. C1588_adj = 1D8H;
  181. C1588_inc = 1DCH;
  182. Ptp_txsec = 1E0H;
  183. Ptp_txnanosec = 1E4H;
  184. Ptp_rxsec = 1E8H;
  185. Ptp_rxnanosec = 1ECH;
  186. Ptpp_txsec = 1F0H;
  187. Ptpp_txnanosec = 1F4H;
  188. Ptpp_rxsec = 1F8H;
  189. Ptpp_rxnanosec = 1FCH;
  190. (** Masks and bits *)
  191. DmacrRxBuf = {16 .. 23};
  192. DmacrRxBufShift = 16;
  193. DmacrTcpChksum = 11;
  194. DmacrTxSize = 10;
  195. DmacrRxSize = {8, 9};
  196. DmacrEndian = 7;
  197. DmacrBlength = {0 .. 4};
  198. DmacrSingleAhbBurst = 0;
  199. DmacrIncr4AhbBurst = 2;
  200. DmacrIncr8AhbBurst = 3;
  201. DmacrIncr16AhbBurst = 4;
  202. IxrPtppstx = 25;
  203. IxrPtppdrtx = 24;
  204. IxrPtpstx = 23;
  205. IxrPtpdrtx = 22;
  206. IxrPtppsrx = 21;
  207. IxrPtppdrrx = 20;
  208. IxrPtpsrx = 19;
  209. IxrPtpdrrx = 18;
  210. IxrPauseTx = 14;
  211. IxrPauseZero = 13;
  212. IxrPauseNzero = 12;
  213. IxrHrespnOk = 11;
  214. IxrRxOvr = 10;
  215. IxrTxCompl = 7;
  216. IxrTxExh = 6;
  217. IxrRetry = 5;
  218. IxrUrun = 4;
  219. IxrTxUsed = 3;
  220. IxrRxUsed = 2;
  221. IxrFrameRx = 1;
  222. IxrMgmnt = 0;
  223. IxrAll = {0 .. 14};
  224. IxrTxErr = {IxrTxExh, IxrRetry, IxrUrun, IxrTxUsed};
  225. IxrRxErr = {IxrHrespnOk, IxrRxUsed, IxrRxOvr};
  226. LaddrMach = {0 .. 31};
  227. NwcfgBadpreambEn = 29;
  228. NwcfgIpdStretch = 28;
  229. NwcfgFcsIgnore = 26;
  230. NwcfgHdRxEn = 25;
  231. NwcfgRxChkSumEn = 24;
  232. NwcfgPauseCopyDi = 23;
  233. NwcfgMdcShift = 18;
  234. NwcfgMdcClkDiv = {18 .. 20};
  235. NwcfgFcsRem = 17;
  236. NwcfgLengthErrDscrd = 16;
  237. Nwcfg1000 = 10;
  238. Nwcfg100 = 0;
  239. NwcfgUcastHashEn = 7;
  240. NwcfgFdEn = 1;
  241. Nwcfg1536RxEn = 8;
  242. NwcfgNvlanDisc = 2;
  243. NwcfgPauseEn = 13;
  244. NwcfgCopyAllEn = 4;
  245. NwcfgBcastDi = 5;
  246. NwcfgMcastHashEn = 6;
  247. NwctrlZeroPauseTx = {11};
  248. NwctrlPauseTx = {11};
  249. NwctrlHaltTx = {10};
  250. NwctrlStartTx = {9};
  251. NwctrlStatwen = {7};
  252. NwctrlStatinc = {6};
  253. NwctrlStatclr = {5};
  254. NwctrlMdEn = {4};
  255. NwctrlTxEn = {3};
  256. NwctrlRxEn = {2};
  257. NwctrlLoopEn = {1};
  258. NwsrMdio = 1;
  259. NwsrMdioIdle = 2;
  260. PhyMntncOp = {17, 30};
  261. PhyMntncOpR = {29};
  262. PhyMntncOpW = {28};
  263. PhyMntncAddR = {23 .. 27};
  264. PhyMntncReg = {18 .. 22};
  265. PhyMntncData = {0 .. 15};
  266. PhyMntncPhyAdShift = 23;
  267. PhyMntncPhRegShift = 18;
  268. RxsrHrespnok = 3;
  269. RxsrRxOvr = 2;
  270. RxsrFrameRx = 1;
  271. RxsrBuffna = 0;
  272. RxsrError = 13;
  273. RxBufBcast = 31;
  274. RxBufMultiHash = 30;
  275. RxBufUniHash = 29;
  276. RxBufExh = 28;
  277. RxBufAMatch = {25,26};
  278. RxBufIDfound = 24;
  279. RxBufIDmatch = {22,23};
  280. RxBufVlan = 21;
  281. RxBufPri = 20;
  282. RxBufVpri = {17..19};
  283. RxBufCfi = 16;
  284. RxBufEof = 15;
  285. RxBufSof = 14;
  286. RxBufLen = {0 .. 13};
  287. RxBufWrap = 1;
  288. RxBufNew = 0;
  289. RxBufAdd = {2 .. 31};
  290. RxBufSize = 1536;
  291. RxBufUnit = 64;
  292. TxBufUsed = 31;
  293. TxBufWrap = 30;
  294. TxBufRetry = 29;
  295. TxBufUrun = 28;
  296. TxBufExh = 27;
  297. TxBufTcp = 26;
  298. TxBufNocrc = 16;
  299. TxBufLast = 15;
  300. TxBufLen = {0 .. 13};
  301. TxsrHrespnok = 8;
  302. TxsrUrun = 6;
  303. TxsrTxCompl = 5;
  304. TxsrBufExh = 4;
  305. TxsrTxGo = 3;
  306. TxsrRxOvr = 2;
  307. TxsrFrameRx = 1;
  308. TxsrUsedRead = 0;
  309. TxsrError = {TxsrHrespnok, TxsrUrun, TxsrBufExh, TxsrRxOvr, TxsrFrameRx, TxsrUsedRead};
  310. (** Clock divisors *)
  311. MdcDiv8 = 0;
  312. MdcDiv16 = 1;
  313. MdcDiv32 = 2;
  314. MdcDiv48 = 3;
  315. MdcDiv64 = 4;
  316. MdcDiv96 = 5;
  317. MdcDiv128 = 6;
  318. MdcDiv224 = 7;
  319. (* Phy return state *)
  320. EmacMiiReadError = 1003;
  321. EmacMiiBusy = 1004;
  322. Success = 0;
  323. Failure = 1;
  324. DeviceIsStarted = 5;
  325. DeviceIsStopped = 6;
  326. (* Phy registers *)
  327. IeeeControlReg = 0;
  328. IeeeStatusReg = 1;
  329. IeeeAutonegoAdvertiseReg = 4;
  330. IeeePartnerAbilities1Reg = 5;
  331. Ieee1000AdvertiseReg = 9;
  332. IeeePartnerAbilities3Reg = 10;
  333. IeeeCopperSpecificControlReg = 16;
  334. IeeeSpecificStatusReg = 17;
  335. IeeeCopperSpecificStatusReg2 = 19;
  336. IeeeControlRegMac = 21;
  337. IeeePageAddressRegister = 22;
  338. (* Phy bits and masks *)
  339. Advertise10Half = 5;
  340. Advertise10Full = 6;
  341. Advertise100Half = 7;
  342. Advertise100Full = 8;
  343. Advertise100 = {Advertise100Full, Advertise100Half};
  344. Advertise10 = {Advertise10Full, Advertise10Half};
  345. Advertise1000 = {8, 9};
  346. IeeeCtrl1GbpsLinkspeed = 2040H;
  347. IeeeCtrlLinkSpeed = {6};
  348. IeeeCtrlLinkSpeed1000M = {6};
  349. IeeeCtrlLinkSpeed100M = {13};
  350. IeeeCtrlLinkSpeed10M = {};
  351. IeeeCtrlReset = {15};
  352. IeeeCtrlAutonegotiateEnable = {12};
  353. IeeeStatAutonegotiateCapable = {3};
  354. IeeeStatAutonegotiateComplete = {5};
  355. IeeeStatAutonegotiateRestart = {9};
  356. IeeeStat1gbpsExtensions = {8};
  357. IeeeAn1Ability = {5 .. 12};
  358. IeeeAn3Ability1Gbps = {10 .. 11};
  359. IeeeAn1Ability100Mbps = {7 .. 9};
  360. IeeeAn1Ability10Mbps = {5 .. 6};
  361. IeeeRgmiiTxRxClockDelayed = {4 .. 5};
  362. IeeeAsymmetricPause = {11};
  363. IeeePause = {10};
  364. IeeeAutonegError = {15};
  365. PhyDetectReg = 1;
  366. PhyDetect = {3, 11, 12};
  367. TYPE
  368. Buffer = ARRAY BufSize OF CHAR;
  369. (** Implements the Network.LinkDevice abstract class. *)
  370. LinkDevice * = OBJECT (Network.LinkDevice)
  371. VAR
  372. ctrl: Controller;
  373. PROCEDURE & Constr * (type, mtu, adrSize: LONGINT);
  374. VAR
  375. i: LONGINT;
  376. BEGIN
  377. Constr^(type, mtu, adrSize);
  378. FOR i := 0 TO LEN(broadcast) - 1 DO
  379. broadcast[i] := 0FFX
  380. END;
  381. END Constr;
  382. PROCEDURE Linked * (): LONGINT;
  383. BEGIN
  384. RETURN Network.LinkLinked
  385. END Linked;
  386. PROCEDURE DoSend * (dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  387. BEGIN
  388. ctrl.SendFrame(dst, type, l3hdr, l4hdr, data, h3len, h4len, dofs, dlen);
  389. END DoSend;
  390. PROCEDURE Finalize * (connected: BOOLEAN);
  391. BEGIN
  392. ctrl.Finalize;
  393. Finalize^(connected);
  394. END Finalize;
  395. END LinkDevice;
  396. (** Ethernet controller driver. *)
  397. Controller = OBJECT
  398. VAR
  399. (** Base of memory-mapped registers *)
  400. iobase: ADDRESS;
  401. dev: LinkDevice;
  402. phy: Phy;
  403. state, isStarted: LONGINT;
  404. speed: LONGINT;
  405. timer: Kernel.Timer;
  406. rxFrames: POINTER TO ARRAY OF Buffer;
  407. txFrame: Buffer;
  408. lastRxQBar, lastTxQBar: ADDRESS;
  409. rxBdBase, txBdBase: ADDRESS;
  410. options: SET;
  411. txBdStartAdr, txBdEndAdr, rxBdStartAdr, rxBdEndAdr: ADDRESS;
  412. kill, start: BOOLEAN;
  413. (* For DMA interaction *)
  414. buffer: POINTER TO ARRAY OF CHAR;
  415. (** Statistics *)
  416. nbrRxFrames, nbrtxFrames, nbrRxErrors, nbrTxErrors: LONGINT;
  417. (** Initializes the controller.
  418. iobase: base address of the registers
  419. *)
  420. PROCEDURE & Init * (iobase: ADDRESS; ld: LinkDevice);
  421. VAR
  422. i: LONGINT;
  423. reg: SET;
  424. (* TEST *)arp: ARRAY 28 OF CHAR;
  425. buf: ARRAY 256 OF Network.Buffer;
  426. BEGIN
  427. NEW(timer);
  428. NEW(rxFrames, RxBdCount);
  429. options := Defaults;
  430. SELF.iobase := iobase;
  431. dev := ld;
  432. dev.calcChecksum := {Network.ChecksumIP, Network.ChecksumTCP, Network.ChecksumUDP};
  433. kill := FALSE;
  434. start := FALSE;
  435. state := IsReady;
  436. Reset;
  437. (* Initialize HW *)
  438. IF Trace THEN KernelLog.String("Zynq.XEmac: Initializing hardware"); KernelLog.Ln END;
  439. SetMacAddress(1, SYSTEM.VAL(Network.LinkAdr, [0X, 0AX, 35X, 0X, 1X, 2X, 0X, 0X]));
  440. SetMdioDivisor(MdcDiv224);
  441. NEW(phy, iobase);
  442. speed := phy.linkSpeed;
  443. IF speed # 1000 THEN
  444. IF Trace THEN KernelLog.String("XEmac: error in speed initialization."); KernelLog.Ln END;
  445. RETURN
  446. END;
  447. SetOperatingSpeed(speed);
  448. SYSTEM.GET(iobase + Dmacr, reg);
  449. INCL(reg, 4);
  450. SYSTEM.PUT(iobase + Dmacr, reg);
  451. SetMdioDivisor(MdcDiv224);
  452. IF Trace THEN KernelLog.String("XEmac: Initializing DMA"); KernelLog.Ln END;
  453. FOR i := 0 TO 6000000 DO END;
  454. InitDMA;
  455. (* preallocate network stack buffers *)
  456. FOR i := 0 TO LEN(buf,0)-1 DO
  457. buf[i] := Network.GetNewBuffer();
  458. END;
  459. FOR i := 0 TO LEN(buf,0)-1 DO
  460. Network.ReturnBuffer(buf[i]);
  461. END;
  462. IF Trace THEN KernelLog.String("XEmac: Starting controller"); KernelLog.Ln END;
  463. Start
  464. END Init;
  465. (* Terminates the process *)
  466. PROCEDURE Kill;
  467. BEGIN {EXCLUSIVE}
  468. kill := TRUE
  469. END Kill;
  470. PROCEDURE Start;
  471. VAR
  472. reg: SET;
  473. BEGIN
  474. IF Trace THEN KernelLog.String("Starting XEmac"); KernelLog.Ln END;
  475. IF isStarted = IsStarted THEN RETURN END;
  476. (* Start DMA *)
  477. SYSTEM.PUT(iobase + Rxqbase, rxBdBase);
  478. SYSTEM.PUT(iobase + Txqbase, txBdBase);
  479. (* Clear any existing interrupt status *)
  480. SYSTEM.PUT(iobase + Isr, IxrAll);
  481. (* Optionally enable TX and RX *)
  482. IF TransmitterEnable IN options THEN
  483. SYSTEM.GET(iobase + Nwctrl, reg);
  484. reg := reg + NwctrlTxEn;
  485. SYSTEM.PUT(iobase + Nwctrl, reg)
  486. END;
  487. IF ReceiverEnable IN options THEN
  488. SYSTEM.GET(iobase + Nwctrl, reg);
  489. reg := reg + NwctrlRxEn;
  490. SYSTEM.PUT(iobase + Nwctrl, reg)
  491. END;
  492. (* Enable TX and RX interrupts *)
  493. SYSTEM.PUT(iobase + Ier, (IxrTxErr + IxrRxErr + {IxrTxCompl, IxrFrameRx}) * IxrAll);
  494. (*BEGIN {EXCLUSIVE}
  495. start := TRUE
  496. END;*)
  497. (*VAR
  498. reg: SET;
  499. BEGIN
  500. SYSTEM.GET(iobase + Nwctrl, reg);
  501. reg := reg + NwctrlStartTx;
  502. SYSTEM.PUT(iobase + Nwctrl, reg)*)
  503. END Start;
  504. PROCEDURE Stop;
  505. VAR
  506. reg: SET;
  507. BEGIN
  508. ASSERT(state = IsReady);
  509. (* Disable all interrupts *)
  510. SYSTEM.PUT32(iobase + Idr, IxrAll);
  511. (* Disable TX and RX *)
  512. SYSTEM.GET(iobase + Nwctrl, reg);
  513. reg := reg - (NwctrlRxEn + NwctrlTxEn);
  514. SYSTEM.PUT(iobase + Nwctrl, reg);
  515. isStarted := 0
  516. END Stop;
  517. PROCEDURE Transmit;
  518. VAR
  519. reg: SET;
  520. BEGIN
  521. IF Trace THEN KernelLog.String("XEmac: transmitting"); KernelLog.Ln END;
  522. SYSTEM.GET(iobase + Nwctrl, reg);
  523. reg := reg + NwctrlStartTx;
  524. SYSTEM.PUT(iobase + Nwctrl, reg)
  525. END Transmit;
  526. (** Stop and restart device *)
  527. PROCEDURE Reset;
  528. VAR
  529. i, tmp: LONGINT;
  530. reg: SET;
  531. BEGIN
  532. IF Trace THEN KernelLog.String("XEmac resetting controller"); KernelLog.Ln END;
  533. ASSERT(state = IsReady);
  534. Stop;
  535. options := Defaults;
  536. reg := (NwctrlStatclr + NwctrlMdEn) * (-NwctrlLoopEn);
  537. SYSTEM.PUT(iobase + Nwctrl, reg);
  538. reg := {};
  539. INCL(reg, Nwcfg100);
  540. INCL(reg, NwcfgFdEn);
  541. INCL(reg, NwcfgUcastHashEn);
  542. SYSTEM.PUT(iobase + Nwcfg, reg);
  543. i := RxBufSize DIV RxBufUnit;
  544. IF RxBufSize MOD RxBufUnit # 0 THEN INC(i) END;
  545. reg := SYSTEM.VAL(SET, LSH(i, DmacrRxBufShift)) * DmacrRxBuf + DmacrRxSize;
  546. INCL(reg, DmacrTxSize);
  547. SYSTEM.PUT(iobase + Dmacr, reg);
  548. SYSTEM.PUT32(iobase + Txsr, 0);
  549. SYSTEM.PUT32(iobase + Rxqbase, 0);
  550. SYSTEM.PUT32(iobase + Txqbase, 0);
  551. SYSTEM.PUT32(iobase + Rxsr, 0);
  552. SYSTEM.PUT32(iobase + Idr, IxrAll);
  553. SYSTEM.GET(iobase + Isr, reg);
  554. SYSTEM.PUT(iobase + Isr, reg);
  555. SYSTEM.PUT32(iobase + PhyMntnc, 0);
  556. ClearHash;
  557. (* Clear all MAC addresses *)
  558. FOR i := 1 TO 4 DO
  559. SetMacAddress(i, ZeroMAC);
  560. tmp := SetTypeIdCheck(i, 0)
  561. END;
  562. (* Clear all counters. *)
  563. FOR i := 0 TO (Last- OctTxL) DIV 4 - 1 DO
  564. SYSTEM.GET(iobase + OctTxL + 4 * i, reg)
  565. END;
  566. (* Disable receiver. *)
  567. SYSTEM.GET(iobase + Nwctrl, reg);
  568. SYSTEM.PUT(iobase + Nwctrl, reg - NwctrlRxEn);
  569. SetOptions(options - {TransmitterEnable, ReceiverEnable});
  570. ClearOptions(-options);
  571. END Reset;
  572. PROCEDURE ResetDevice;
  573. VAR
  574. options: SET;
  575. BEGIN
  576. Stop;
  577. options := SELF.options;
  578. Reset;
  579. SetOptions(options);
  580. ClearOptions(-options)
  581. END ResetDevice;
  582. PROCEDURE SendFrame (CONST dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  583. VAR
  584. txLen, offset: LONGINT;
  585. bufferAdr, txbd: ADDRESS;
  586. intsEnabled: BOOLEAN;
  587. reg: SET;
  588. BEGIN (*{EXCLUSIVE}*)
  589. IF Trace THEN KernelLog.String("XEmac: Sending Frame"); KernelLog.Ln END;
  590. (* Prepare buffer *) (* This part is taken from RTL8169.Mod *)
  591. txLen := 14 + h3len + h4len + dlen;
  592. bufferAdr := ADDRESSOF(txFrame[0]);
  593. (* set destination mac address (first 6 bytes of eth frame) *)
  594. SYSTEM.MOVE(ADDRESSOF(dst[0]), bufferAdr, 6);
  595. (*txFrame[0] := dst[0]; txFrame[1] := dst[1]; txFrame[2] := dst[2]; txFrame[3] := dst[3]; txFrame[4] := dst[4]; txFrame[5] := dst[5];*)
  596. (* set source mac address (6 bytes @ offset 6 of eth frame) *)
  597. SYSTEM.MOVE(ADDRESSOF(dev.local[0]), bufferAdr + 6, 6);
  598. (*txFrame[6]:=000X;txFrame[7]:=00AX;txFrame[8]:=035X;txFrame[9]:=000X;txFrame[10]:=001X;txFrame[11]:=002X;*)
  599. (* set upper layer type, bring type from host to network byte order *)
  600. SYSTEM.PUT16(bufferAdr + 12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
  601. (*IF Trace THEN
  602. KernelLog.Buffer(txFrame, 0, txLen);
  603. KernelLog.Ln
  604. END;*)
  605. offset := 14;
  606. (* move layer 3 and layer 4 headers, data *)
  607. IF h3len > 0 THEN
  608. SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), bufferAdr + offset, h3len);
  609. INC(offset, h3len);
  610. END;
  611. IF h4len > 0 THEN
  612. SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), bufferAdr + offset, h4len);
  613. INC(offset, h4len);
  614. END;
  615. IF offset + dlen < BufSize THEN
  616. SYSTEM.MOVE(ADDRESSOF(data[0]) + dofs, bufferAdr + offset, dlen);
  617. INC(offset, dlen);
  618. END;
  619. (* make the frame at least 64 bytes long *)
  620. WHILE offset < 60 DO
  621. txFrame[offset] := CHR(0);
  622. INC(offset);
  623. INC(txLen)
  624. END;
  625. (*IF Trace THEN
  626. KernelLog.String("Sending frame of length ");
  627. KernelLog.Int(txLen, 0);
  628. KernelLog.Ln;
  629.  KernelLog.Memory(bufferAdr, txLen)
  630. END;*)
  631. (* Send it with DMA *)
  632. intsEnabled := Machine.AreInterruptsEnabled();
  633. Machine.DisableInterrupts;
  634. SYSTEM.GET(iobase + Txqbase, txbd);
  635. IF txbd = 0 THEN txbd := txBdStartAdr END;
  636. Machine.FlushDCacheRange(ADDRESSOF(txFrame[0]), txLen);
  637. SYSTEM.PUT(txbd + BdAdrOffset, ADDRESSOF(txFrame));
  638. IF txbd # txBdEndAdr THEN
  639. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast} + SYSTEM.VAL(SET, txLen));
  640. ELSE
  641. IF Trace THEN KernelLog.String("END OF TXBUFFERS"); KernelLog.Ln END;
  642. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast, TxBufWrap} + SYSTEM.VAL(SET, txLen));
  643. END;
  644. (* no need to flush/invalidate cache for BD memory space
  645. Machine.FlushDCacheRange(txbd, BdSize);
  646. *)
  647. CODE
  648. DSB
  649. END;
  650. (* Transmit *)
  651. Transmit;
  652. IF intsEnabled THEN Machine.EnableInterrupts END;
  653. END SendFrame;
  654. (** Called by the polling body. Signals the new frames to the link device *)
  655. PROCEDURE ReceiveFrame;
  656. VAR
  657. currentBd, adr: ADDRESS;
  658. len, i: LONGINT;
  659. reg: SET;
  660. buf: Network.Buffer;
  661. type: INTEGER;
  662. BEGIN
  663. (*IF Trace THEN KernelLog.String("Receiving frame"); KernelLog.Ln END;*)
  664. currentBd := lastRxQBar;
  665. SYSTEM.GET(currentBd + BdAdrOffset, adr);
  666. adr := adr - (adr MOD 4);
  667. SYSTEM.GET(currentBd, reg);
  668. IF RxBufNew IN reg THEN
  669. (*IF Trace THEN
  670. KernelLog.String("Current BD: "); KernelLog.Address(currentBd); KernelLog.Ln;
  671. KernelLog.String("QBar: "); KernelLog.Address(SYSTEM.GET32(iobase + Rxqbase)); KernelLog.Ln
  672. END;*)
  673. IF SYSTEM.GET32(currentBd + 4) = 0 THEN
  674. SYSTEM.GET(iobase + Nwctrl, reg);
  675. reg := reg * SET(-NwctrlRxEn);
  676. SYSTEM.PUT(iobase + Nwctrl, reg);
  677. SYSTEM.GET(iobase + Nwctrl, reg);
  678. reg := reg + NwctrlRxEn + {18};
  679. SYSTEM.PUT(iobase + Nwctrl, reg)
  680. ELSE
  681. IF Trace THEN KernelLog.String("Receiving frame"); KernelLog.Ln END;
  682. SYSTEM.GET(currentBd + BdStatOffset, reg);
  683. len := SYSTEM.VAL(LONGINT, reg * RxBufLen);
  684. (* Invalidate DCache *)
  685. (* no need to flush/invalidate cache for BD memory space
  686. Machine.InvalidateDCacheRange(currentBd,BdSize);
  687. *)
  688. Machine.InvalidateDCacheRange(adr,len);
  689. (* Construct Frame *)
  690. buf := Network.GetNewBuffer(); ASSERT(buf # NIL);
  691. buf.ofs := 14;
  692. buf.len := len - 14;
  693. buf.next := NIL;
  694. buf.prev := NIL;
  695. buf.calcChecksum := dev.calcChecksum;
  696. SYSTEM.MOVE(adr+6,ADDRESSOF(buf.src[0]),6);
  697. type := INTEGER(SYSTEM.GET8(adr + 12)) * 100H + INTEGER(SYSTEM.GET8(adr + 13));
  698. SYSTEM.MOVE(adr,ADDRESSOF(buf.data[0]),len);
  699. dev.QueueBuffer(buf, type)
  700. END
  701. END;
  702. IF currentBd = rxBdEndAdr THEN
  703. SYSTEM.PUT32(currentBd + BdAdrOffset, adr + 2);
  704. lastRxQBar := rxBdStartAdr
  705. ELSE
  706. SYSTEM.PUT32(currentBd + BdAdrOffset, adr);
  707. INC(lastRxQBar, BdSize)
  708. END;
  709. SYSTEM.PUT32(currentBd + BdStatOffset, 0);
  710. (* no need to flush/invalidate cache for BD memory space
  711. Machine.FlushDCacheRange(currentBd, BdSize);
  712. *)
  713. END ReceiveFrame;
  714. PROCEDURE SetOptions (opts: SET);
  715. VAR
  716. reg, regNetCfg, regNewNetCfg: SET;
  717. BEGIN
  718. IF Trace THEN KernelLog.String("XEmac.SetOptions: "); KernelLog.Hex(SYSTEM.VAL(ADDRESS, opts), -8); KernelLog.Ln END;
  719. ASSERT(state = IsReady);
  720. (* Many of these options will change the NET_CONFIG registers.
  721. * To reduce the amount of IO to the device, group these options here
  722. * and change them all at once.
  723. *)
  724. (* Grab current register contents *)
  725. SYSTEM.GET(iobase + Nwcfg, regNetCfg);
  726. regNewNetCfg := regNetCfg;
  727. IF Trace THEN KernelLog.String("regNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, regNetCfg), -8); KernelLog.Ln END;
  728. (*
  729. * It is configured to max 1536.
  730. *)
  731. IF Frame1536 IN opts THEN
  732. regNewNetCfg := regNewNetCfg + {Nwcfg1536RxEn};
  733. END;
  734. (* Turn on VLAN packet only, only VLAN tagged will be accepted *)
  735. IF Vlan IN opts THEN
  736. regNewNetCfg := regNewNetCfg + {NwcfgNvlanDisc};
  737. END;
  738. (* Turn on FCS stripping on receive packets *)
  739. IF FcsStrip IN opts THEN
  740. regNewNetCfg := regNewNetCfg + {NwcfgFcsRem};
  741. END;
  742. (* Turn on length/type field checking on receive packets *)
  743. IF LenTypeErr IN opts THEN
  744. regNewNetCfg := regNewNetCfg + {NwcfgLengthErrDscrd};
  745. END;
  746. (* Turn on flow control *)
  747. IF FlowControl IN opts THEN
  748. regNewNetCfg := regNewNetCfg + {NwcfgPauseEn};
  749. END;
  750. (* Turn on promiscuous frame filtering (all frames are received) *)
  751. IF Promisc IN opts THEN
  752. regNewNetCfg := regNewNetCfg + {NwcfgCopyAllEn};
  753. END;
  754. (* Allow broadcast address reception *)
  755. IF Broadcast IN opts THEN
  756. regNewNetCfg := regNewNetCfg - {NwcfgBcastDi};
  757. END;
  758. (* Allow multicast address filtering *)
  759. IF Multicast IN opts THEN
  760. regNewNetCfg := regNewNetCfg + {NwcfgMcastHashEn};
  761. END;
  762. (* enable RX checksum offload *)
  763. IF RxChksumEnable IN opts THEN
  764. regNewNetCfg := regNewNetCfg + {NwcfgRxChkSumEn};
  765. END;
  766. (* Officially change the NET_CONFIG registers if it needs to be
  767. * modified.
  768. *)
  769. IF regNetCfg # regNewNetCfg THEN
  770. SYSTEM.PUT(iobase + Nwcfg, regNewNetCfg);
  771. END;
  772. IF Trace THEN KernelLog.String("regNewNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, regNewNetCfg), -8); KernelLog.Ln END;
  773. (* Enable TX checksum offload *)
  774. IF TxChksumEnable IN opts THEN
  775. SYSTEM.GET(iobase + Dmacr, reg);
  776. reg := reg + {DmacrTcpChksum};
  777. SYSTEM.PUT(iobase + Dmacr, reg);
  778. IF Trace THEN KernelLog.String("DMACR_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  779. END;
  780. (* Enable transmitter *)
  781. IF TransmitterEnable IN opts THEN
  782. SYSTEM.GET(iobase + Nwctrl, reg);
  783. reg := reg + NwctrlTxEn;
  784. SYSTEM.PUT(iobase + Nwctrl, reg);
  785. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  786. END;
  787. (* Enable receiver *)
  788. IF ReceiverEnable IN opts THEN
  789. SYSTEM.GET(iobase + Nwctrl, reg);
  790. reg := reg + NwctrlRxEn;
  791. SYSTEM.PUT(iobase + Nwctrl, reg);
  792. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  793. END;
  794. (* The remaining options not handled here are managed elsewhere in the
  795. * driver. No register modifications are needed at this time. Reflecting
  796. * the option in InstancePtr->Options is good enough for now.
  797. *)
  798. (* Set options word to its new value *)
  799. SELF.options := SELF.options + opts;
  800. IF Trace THEN KernelLog.String("SetOptions END "); KernelLog.Address(SYSTEM.VAL(ADDRESS, SELF.options)); KernelLog.Ln END;
  801. END SetOptions;
  802. PROCEDURE ClearOptions (opts: SET);
  803. VAR
  804. reg, old: SET;
  805. BEGIN
  806. IF Trace THEN KernelLog.String("XEmac: Clear Options"); KernelLog.Ln END;
  807. SYSTEM.GET(iobase + Nwcfg, reg);
  808. old := reg;
  809. (*
  810. * It is configured to max 1536.
  811. *)
  812. IF Frame1536 IN opts THEN
  813. EXCL(reg, Nwcfg1536RxEn);
  814. END;
  815. (* Turn off VLAN packet only, only VLAN tagged will be accepted *)
  816. IF Vlan IN opts THEN
  817. EXCL(reg, NwcfgNvlanDisc);
  818. END;
  819. (* Turn off FCS stripping on receive packets *)
  820. IF FcsStrip IN opts THEN
  821. EXCL(reg, NwcfgFcsRem);
  822. END;
  823. (* Turn off length/type field checking on receive packets *)
  824. IF LenTypeErr IN opts THEN
  825. EXCL(reg, NwcfgLengthErrDscrd);
  826. END;
  827. (* Turn off flow control *)
  828. IF FlowControl IN opts THEN
  829. EXCL(reg, NwcfgPauseEn);
  830. END;
  831. (* Turn off promiscuous frame filtering (all frames are received) *)
  832. IF Promisc IN opts THEN
  833. EXCL(reg, NwcfgCopyAllEn);
  834. END;
  835. (* Forbid broadcast address reception *)
  836. IF Broadcast IN opts THEN
  837. EXCL(reg, NwcfgBcastDi);
  838. END;
  839. (* Forbid multicast address filtering *)
  840. IF Multicast IN opts THEN
  841. EXCL(reg, NwcfgMcastHashEn);
  842. END;
  843. (* Disable RX checksum offload *)
  844. IF RxChksumEnable IN opts THEN
  845. EXCL(reg, NwcfgRxChkSumEn);
  846. END;
  847. (* Officially change the NET_CONFIG registers if it needs to be
  848. * modified.
  849. *)
  850. IF reg # old THEN
  851. SYSTEM.PUT(iobase + Nwcfg, reg);
  852. END;
  853. IF Trace THEN KernelLog.String("regNewNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  854. (* Disable TX checksum offload *)
  855. IF TxChksumEnable IN opts THEN
  856. SYSTEM.GET(iobase + Dmacr, reg);
  857. EXCL(reg, DmacrTcpChksum);
  858. SYSTEM.PUT(iobase + Dmacr, reg);
  859. IF Trace THEN KernelLog.String("DMACR_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  860. END;
  861. (* Disable transmitter *)
  862. IF TransmitterEnable IN opts THEN
  863. SYSTEM.GET(iobase + Nwctrl, reg);
  864. reg := reg * SET(-NwctrlTxEn);
  865. SYSTEM.PUT(iobase + Nwctrl, reg);
  866. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  867. END;
  868. (* Disable receiver *)
  869. IF ReceiverEnable IN opts THEN
  870. SYSTEM.GET(iobase + Nwctrl, reg);
  871. reg := reg * SET(-NwctrlRxEn);
  872. SYSTEM.PUT(iobase + Nwctrl, reg);
  873. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  874. END;
  875. SELF.options := SELF.options * (-opts);
  876. END ClearOptions;
  877. PROCEDURE ClearHash;
  878. BEGIN
  879. IF Trace THEN KernelLog.String("XEmac: Clear Hash"); KernelLog.Ln END;
  880. ASSERT(state = IsReady);
  881. SYSTEM.PUT32(iobase + HashL, 0);
  882. SYSTEM.PUT32(iobase + HashH, 0)
  883. END ClearHash;
  884. PROCEDURE SetMdioDivisor (divisor: LONGINT);
  885. VAR
  886. reg: SET;
  887. BEGIN
  888. ASSERT(state = IsReady);
  889. (* Only last 3 bits are valid *)
  890. ASSERT(divisor < 8);
  891. SYSTEM.GET(iobase + Nwcfg, reg);
  892. reg := reg * SET(-NwcfgMdcClkDiv);
  893. reg := reg + SYSTEM.VAL(SET, LSH(divisor, NwcfgMdcShift));
  894. SYSTEM.PUT(iobase + Nwcfg, reg);
  895. END SetMdioDivisor;
  896. PROCEDURE SetOperatingSpeed (speed: LONGINT);
  897. VAR
  898. reg: SET;
  899. BEGIN
  900. IF Trace THEN KernelLog.String("XEmac: setting operating speed."); KernelLog.Ln END;
  901. ASSERT(state = IsReady);
  902. ASSERT((speed = 10) OR (speed = 100) OR (speed = 1000));
  903. SYSTEM.GET(iobase + Nwcfg, reg);
  904. reg := reg - {Nwcfg1000, Nwcfg100};
  905. CASE speed OF
  906. 10:
  907. |100:
  908. INCL(reg, Nwcfg100)
  909. |1000:
  910. INCL(reg, Nwcfg1000)
  911. END;
  912. SYSTEM.PUT(iobase + Nwcfg, reg);
  913. IF Trace THEN KernelLog.String("Waiting for operation speed to stabilize"); KernelLog.Ln END;
  914. timer.Sleep(1000);
  915. IF Trace THEN KernelLog.String("XEmac: operating speed set."); KernelLog.Ln END;
  916. END SetOperatingSpeed;
  917. (*! TODO: change parameter interface to a more convenient one *)
  918. PROCEDURE SetMacAddress(index: LONGINT; mac: Network.LinkAdr);
  919. VAR
  920. reg: SET;
  921. BEGIN
  922. ASSERT(index > 0);
  923. DEC(index);
  924. reg := SYSTEM.VAL(SET, ORD(mac[0]) + LSH(ORD(mac[1]), 8) + LSH(ORD(mac[2]), 16) + LSH(ORD(mac[3]), 24));
  925. SYSTEM.PUT(iobase + Laddr1l + (index * 8), reg);
  926. (* There are reserved bits in TOP so don't affect them *)
  927. SYSTEM.GET(iobase + Laddr1h + (index * 8), reg);
  928. reg := reg * SET(-LaddrMach) + SYSTEM.VAL(SET, ORD(mac[4]) + LSH(ORD(mac[5]), 8));
  929. SYSTEM.PUT(iobase + Laddr1h + index * 8, reg);
  930. dev.local := mac;
  931. IF Trace THEN
  932. KernelLog.String("XEmac MAC address set to: ");
  933. KernelLog.Hex(ORD(mac[0]), -2); KernelLog.String(".");
  934. KernelLog.Hex(ORD(mac[1]), -2); KernelLog.String(".");
  935. KernelLog.Hex(ORD(mac[2]), -2); KernelLog.String(".");
  936. KernelLog.Hex(ORD(mac[3]), -2); KernelLog.String(".");
  937. KernelLog.Hex(ORD(mac[4]), -2); KernelLog.String(".");
  938. KernelLog.Hex(ORD(mac[5]), -2); KernelLog.Ln
  939. END
  940. END SetMacAddress;
  941. PROCEDURE SetTypeIdCheck(index, idCheck: LONGINT): LONGINT;
  942. BEGIN
  943. ASSERT(state = IsReady);
  944. ASSERT((index > 0) & (index <= MaxTypeId));
  945. IF isStarted = IsStarted THEN
  946. RETURN IsStarted
  947. END;
  948. SYSTEM.PUT(iobase + Match1 + index * 4, idCheck);
  949. RETURN Success
  950. END SetTypeIdCheck;
  951. PROCEDURE InitDMA;
  952. CONST
  953. MB = 1024*1024;
  954. VAR
  955. beginAdr, endAdr, adr: ADDRESS;
  956. reg: SET;
  957. i: LONGINT;
  958. BEGIN
  959. IF Trace THEN KernelLog.String("XEmac: Starting DMA"); KernelLog.Ln END;
  960. (*
  961. NEW(buffer, (RxBdCount + TxBdCount + 20) * BdSize);
  962. *)
  963. (* allocate 2 pages (each page is 1 MBytes) of memory in Heaps for mapping one full page uncached
  964. without affecting any adjacent data *)
  965. NEW(buffer,2*MB);
  966. ASSERT((RxBdCount + TxBdCount + 20) * BdSize <= MB);
  967. beginAdr := ADDRESSOF(buffer[0]);
  968. beginAdr := beginAdr + (MB - beginAdr MOD MB);
  969. ASSERT(beginAdr MOD MB = 0);
  970. Machine.DisableDCacheRange(beginAdr,MB);
  971. (* setup DMA RX buffer descriptors *)
  972. rxBdStartAdr := beginAdr;
  973. endAdr := beginAdr + (RxBdCount - 1) * BdSize;
  974. rxBdEndAdr := endAdr;
  975. i := 0;
  976. adr := beginAdr;
  977. WHILE adr < endAdr DO
  978. SYSTEM.PUT32(adr + BdAdrOffset, ADDRESSOF(rxFrames[i][0]));
  979. INC(adr, BdSize);
  980. INC(i)
  981. END;
  982. SYSTEM.PUT32(adr + BdAdrOffset, ADDRESSOF(rxFrames[i][0]) + 2);
  983. lastRxQBar := beginAdr;
  984. rxBdBase := beginAdr;
  985. CODE
  986. DSB
  987. END;
  988. (* no need to flush/invalidate cache for BD memory space
  989. (* Flush DCache *)
  990. Machine.FlushDCacheRange(beginAdr, RxBdCount * BdSize);
  991. *)
  992. IF Trace THEN KernelLog.String("XEmac: RX buffers are set up."); KernelLog.Ln END;
  993. (* setup DMA TX buffer descriptors *)
  994. beginAdr := endAdr + BdSize;
  995. txBdStartAdr := beginAdr;
  996. endAdr := beginAdr + (TxBdCount - 1) * BdSize;
  997. txBdEndAdr := endAdr;
  998. adr := beginAdr;
  999. WHILE adr < endAdr DO
  1000. SYSTEM.PUT32(adr, 0);
  1001. SYSTEM.PUT32(adr + 4, {TxBufUsed});
  1002. INC(adr, BdSize)
  1003. END;
  1004. SYSTEM.PUT32(adr + 4, {TxBufUsed, TxBufWrap});
  1005. lastTxQBar := beginAdr;
  1006. txBdBase := beginAdr;
  1007. CODE
  1008. DSB
  1009. END;
  1010. (* no need to flush/invalidate cache for BD memory space
  1011. (* Flush DCache *)
  1012. Machine.FlushDCacheRange(txBdBase, TxBdCount * BdSize);
  1013. *)
  1014. IF Trace THEN KernelLog.String("XEmac: TX buffers are set up."); KernelLog.Ln END;
  1015. Objects.InstallHandler(SELF.InterruptHandler, IRQ);
  1016. IF Trace THEN KernelLog.String("DMA Initialized"); KernelLog.Ln END
  1017. END InitDMA;
  1018. (**
  1019. Interrupt handler -- tries to handle the maximum number of IRQs
  1020. at once.
  1021. *)
  1022. PROCEDURE InterruptHandler;
  1023. VAR
  1024. regISR, regSR: SET;
  1025. BEGIN
  1026. ASSERT(state = IsReady);
  1027. (* Get and clear interrupts *)
  1028. SYSTEM.GET(iobase + Isr, regISR);
  1029. SYSTEM.PUT(iobase + Isr, regISR);
  1030. (* Transmit complete interrupt *)
  1031. IF IxrTxCompl IN regISR THEN
  1032. SYSTEM.PUT(iobase + Txsr, {TxsrTxCompl, TxsrUsedRead});
  1033. SendHandler
  1034. END;
  1035. (* Receive complete interrupt *)
  1036. IF IxrFrameRx IN regISR THEN
  1037. SYSTEM.PUT(iobase + Rxsr, {RxsrFrameRx, RxsrBuffna});
  1038. ReceiveHandler
  1039. END;
  1040. (* Receive error conditions interrupt *)
  1041. IF IxrRxErr * regISR # {} THEN
  1042. (* Clear Rx status register *)
  1043. SYSTEM.GET(iobase + Rxsr, regSR);
  1044. SYSTEM.PUT(iobase + Rxsr, regSR);
  1045. IF IxrRxUsed IN regISR THEN
  1046. (* Flush a packet from Rx SRAM *)
  1047. SYSTEM.GET(iobase + Nwctrl, regSR);
  1048. SYSTEM.PUT(iobase + Nwctrl, regSR + {18})
  1049. END;
  1050. ErrorHandler(Recv, regSR)
  1051. END;
  1052. (* Transmit error interrupt
  1053. TxCompl also activates TxUsed when asserted: we have to check for a real error.
  1054. *)
  1055. IF (IxrTxErr * regISR # {}) & (~(IxrTxCompl IN regISR)) THEN
  1056. SYSTEM.GET(iobase + Txsr, regSR);
  1057. SYSTEM.PUT(iobase + Txsr, regSR);
  1058. ErrorHandler(Send, regSR)
  1059. END;
  1060. END InterruptHandler;
  1061. PROCEDURE SendHandler;
  1062. VAR
  1063. reg: SET;
  1064. currBdPtr: ADDRESS;
  1065. BEGIN
  1066. IF Trace THEN KernelLog.String("XEmac.SendHandler"); KernelLog.Ln END;
  1067. SYSTEM.GET(iobase + Txsr, reg);
  1068. SYSTEM.PUT(iobase + Txsr, reg);
  1069. LOOP
  1070. currBdPtr := lastTxQBar;
  1071. IF currBdPtr = SYSTEM.GET32(iobase + Txqbase) THEN EXIT END;
  1072. SYSTEM.PUT32(currBdPtr + BdAdrOffset, 0);
  1073. IF currBdPtr = txBdEndAdr THEN
  1074. SYSTEM.PUT(currBdPtr + BdStatOffset, {TxBufUsed, TxBufWrap});
  1075. lastTxQBar := txBdStartAdr
  1076. ELSE
  1077. SYSTEM.PUT(currBdPtr + BdStatOffset, {TxBufUsed});
  1078. INC(lastTxQBar, BdSize)
  1079. END
  1080. END;
  1081. IF Trace THEN KernelLog.String("XEmac.SendHandler END"); KernelLog.Ln END
  1082. END SendHandler;
  1083. PROCEDURE ReceiveHandler;
  1084. (*VAR
  1085. buf: Network.Buffer;
  1086. type: LONGINT;*)
  1087. VAR
  1088. reg: SET;
  1089. tmp: LONGINT;
  1090. BEGIN
  1091. IF Trace THEN KernelLog.String("XEmac.ReceiveHandler"); KernelLog.Ln END;
  1092. SYSTEM.GET(iobase + Rxsr, reg);
  1093. SYSTEM.PUT(iobase + Rxsr, reg);
  1094. SYSTEM.GET(iobase + Rxcnt, tmp);
  1095. IF tmp = 0 THEN
  1096. SYSTEM.GET(iobase + Nwctrl, reg);
  1097. reg := reg * SET(-NwctrlRxEn);
  1098. SYSTEM.PUT(iobase + Nwctrl, reg);
  1099. SYSTEM.GET(iobase + Nwctrl, reg);
  1100. reg := reg + NwctrlRxEn;
  1101. SYSTEM.PUT(iobase + Nwctrl, reg)
  1102. END
  1103. END ReceiveHandler;
  1104. PROCEDURE ErrorHandler (direction: CHAR; errorWord: SET);
  1105. BEGIN
  1106. IF Trace THEN KernelLog.String("XEmac.ErrorHandler: Error while ") END;
  1107. CASE direction OF
  1108. Send:
  1109. KernelLog.String("sending"); KernelLog.Ln;
  1110. IF TxsrHrespnok IN errorWord THEN
  1111. KernelLog.String("[XEmac ERROR] Transmit DMA error"); KernelLog.Ln
  1112. END;
  1113. IF TxsrUrun IN errorWord THEN
  1114. KernelLog.String("[XEmac ERROR] Transmit underrun"); KernelLog.Ln
  1115. END;
  1116. IF TxsrBufExh IN errorWord THEN
  1117. KernelLog.String("[XEmac ERROR] Transmit buffer exhausted"); KernelLog.Ln
  1118. END;
  1119. IF TxsrRxOvr IN errorWord THEN
  1120. KernelLog.String("[XEmac ERROR] Transmit retry limit exceeded"); KernelLog.Ln
  1121. END;
  1122. IF TxsrFrameRx IN errorWord THEN
  1123. KernelLog.String("[XEmac ERROR] Transmit collision"); KernelLog.Ln
  1124. END;
  1125. IF TxsrUsedRead IN errorWord THEN
  1126. KernelLog.String("[XEmac ERROR] Transmit buffer not available"); KernelLog.Ln;
  1127. KernelLog.String("QBar = "); KernelLog.Address(SYSTEM.GET32(iobase + Txqbase)); KernelLog.Ln
  1128. END;
  1129. |Recv:
  1130. KernelLog.String("receiving"); KernelLog.Ln;
  1131. IF RxsrHrespnok IN errorWord THEN
  1132. KernelLog.String("[XEmac ERROR] Receive DMA error"); KernelLog.Ln
  1133. END;
  1134. IF RxsrRxOvr IN errorWord THEN
  1135. KernelLog.String("[XEmac ERROR] Receive overrun"); KernelLog.Ln
  1136. END;
  1137. IF RxsrBuffna IN errorWord THEN
  1138. KernelLog.String("[XEmac ERROR] Receive buffer not available"); KernelLog.Ln
  1139. END
  1140. END;
  1141. ResetDevice
  1142. END ErrorHandler;
  1143. PROCEDURE SendTestFrame;
  1144. VAR
  1145. txbd: ADDRESS;
  1146. intsEnabled: BOOLEAN;
  1147. BEGIN
  1148. txFrame[0]:=0FFX;txFrame[1]:=0FFX;txFrame[2]:=0FFX;txFrame[3]:=0FFX;txFrame[4]:=0FFX;txFrame[5]:=0FFX;
  1149. txFrame[6]:=000X;txFrame[7]:=00AX;txFrame[8]:=035X;txFrame[9]:=000X;txFrame[10]:=001X;txFrame[11]:=002X;
  1150. txFrame[12]:=008X;txFrame[13]:=006X;txFrame[14]:=000X;txFrame[15]:=001X;
  1151. txFrame[16]:=008X;txFrame[17]:=000X;txFrame[18]:=006X;txFrame[19]:=004X;txFrame[20]:=000X;txFrame[21]:=001X;txFrame[22]:=000X;txFrame[23]:=00AX;
  1152. txFrame[24]:=035X;txFrame[25]:=000X;txFrame[26]:=001X;txFrame[27]:=002X;txFrame[28]:=0C0X;txFrame[29]:=0A8X;txFrame[30]:=001X;txFrame[31]:=00AX;
  1153. txFrame[32]:=000X;txFrame[33]:=000X;txFrame[34]:=000X;txFrame[35]:=000X;txFrame[36]:=000X;txFrame[37]:=000X;txFrame[38]:=0C0X;txFrame[39]:=0A8X;
  1154. txFrame[40]:=001X;txFrame[41]:=00AX;txFrame[42]:=000X;txFrame[43]:=000X;txFrame[44]:=000X;txFrame[45]:=000X;txFrame[46]:=000X;txFrame[47]:=000X;
  1155. txFrame[48]:=001X;txFrame[49]:=00AX;txFrame[50]:=000X;txFrame[51]:=000X;txFrame[52]:=000X;txFrame[53]:=000X;txFrame[54]:=000X;txFrame[55]:=000X;
  1156. txFrame[56]:=001X;txFrame[57]:=00AX;txFrame[58]:=000X;txFrame[59]:=000X;
  1157. KernelLog.String("Sending Test Frame"); KernelLog.Ln;
  1158. KernelLog.Address(ADDRESSOF(txFrame)); KernelLog.Ln;
  1159. KernelLog.Buffer(txFrame, 0, 60);
  1160. (* Send it with DMA *)
  1161. intsEnabled := Machine.AreInterruptsEnabled();
  1162. Machine.DisableInterrupts;
  1163. SYSTEM.GET(iobase + Txqbase, txbd);
  1164. KernelLog.String("SendTestFrame: txbd = "); KernelLog.Address(txbd); KernelLog.Ln;
  1165. IF txbd = 0 THEN txbd := txBdStartAdr END;
  1166. KernelLog.String("SendTestFrame: txbd = "); KernelLog.Address(txbd); KernelLog.Ln;
  1167. Machine.FlushDCacheRange(ADDRESSOF(txFrame), 60);
  1168. SYSTEM.PUT(txbd + BdAdrOffset, ADDRESSOF(txFrame));
  1169. IF txbd # txBdEndAdr THEN
  1170. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast} + SYSTEM.VAL(SET, 60));
  1171. ELSE
  1172. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast, TxBufWrap} + SYSTEM.VAL(SET, 60));
  1173. END;
  1174. (* no need to flush/invalidate cache for BD memory space
  1175. Machine.FlushDCacheRange(txbd, BdSize);
  1176. *)
  1177. CODE
  1178. DSB
  1179. END;
  1180. (* Transmit *)
  1181. Transmit;
  1182. IF intsEnabled THEN Machine.EnableInterrupts END;
  1183. IF Trace THEN KernelLog.String("Frame sent"); KernelLog.Ln END
  1184. END SendTestFrame;
  1185. PROCEDURE DumpDBMem(start: ADDRESS; count: LONGINT);
  1186. VAR
  1187. i: LONGINT;
  1188. BEGIN
  1189. FOR i := 0 TO count DO
  1190. KernelLog.Address(start); KernelLog.String(": ");
  1191. KernelLog.Address(SYSTEM.GET32(start)); KernelLog.String(" - ");
  1192. INC(start, 4);
  1193. KernelLog.Address(SYSTEM.GET32(start)); KernelLog.Ln;
  1194. INC(start, 4)
  1195. END;
  1196. END DumpDBMem;
  1197. PROCEDURE Finalize;
  1198. BEGIN
  1199. Stop;
  1200. Objects.RemoveHandler(SELF.InterruptHandler, IRQ);
  1201. Network.registry.Remove(dev);
  1202. dev.ctrl := NIL;
  1203. dev := NIL;
  1204. END Finalize;
  1205. BEGIN {ACTIVE}
  1206. (* Receive is done by polling *)
  1207. (*BEGIN {EXCLUSIVE}
  1208. AWAIT(start)
  1209. END;*)
  1210. WHILE dev # NIL DO
  1211. (*BEGIN {EXCLUSIVE}
  1212. IF kill THEN EXIT END
  1213. END;*)
  1214. IF lastRxQBar # SYSTEM.GET32(iobase + Rxqbase) THEN
  1215. ReceiveFrame
  1216. END
  1217. END
  1218. END Controller;
  1219. (** Phy subsystem of the controller. *)
  1220. Phy = OBJECT
  1221. VAR
  1222. iobase, phybase: ADDRESS;
  1223. linkSpeed: LONGINT;
  1224. timer: Kernel.Timer;
  1225. PROCEDURE & Setup * (iobase: ADDRESS);
  1226. BEGIN
  1227. SELF.iobase := iobase;
  1228. NEW(timer);
  1229. IF LinkSpeedMode = LinkSpeedAutodetect THEN
  1230. linkSpeed := GetIEEEPhySpeed();
  1231. IF linkSpeed = 1000 THEN
  1232. IF Trace THEN KernelLog.String("Autonegociated speed: 1000 MB/s"); KernelLog.Ln END;
  1233. SetUpSLCRDivisors(1000)
  1234. ELSIF linkSpeed = 100 THEN
  1235. IF Trace THEN KernelLog.String("Autonegociated speed: 100 MB/s"); KernelLog.Ln END;
  1236. SetUpSLCRDivisors(100)
  1237. ELSIF linkSpeed = 10 THEN
  1238. IF Trace THEN KernelLog.String("Autonegociated speed: 10 MB/s"); KernelLog.Ln END;
  1239. SetUpSLCRDivisors(10)
  1240. ELSE
  1241. IF Trace THEN KernelLog.String("Defaulting autonegociated speed to 10 MB/s"); KernelLog.Ln END;
  1242. SetUpSLCRDivisors(10)
  1243. END;
  1244. RETURN
  1245. ELSIF LinkSpeedMode = LinkSpeed1000 THEN
  1246. linkSpeed := 1000;
  1247. ELSIF LinkSpeedMode = LinkSpeed100 THEN
  1248. linkSpeed := 100;
  1249. ELSE
  1250. linkSpeed := 10;
  1251. END;
  1252. SetUpSLCRDivisors(linkSpeed);
  1253. ConfigureIEEEPhySpeed(linkSpeed);
  1254. timer.Sleep(1000)
  1255. END Setup;
  1256. PROCEDURE Detect (): ADDRESS;
  1257. VAR
  1258. status, phyReg: LONGINT;
  1259. phyAdr: ADDRESS;
  1260. BEGIN
  1261. IF Trace THEN KernelLog.String("XEmac: Detecting PHY"); KernelLog.Ln END;
  1262. phyAdr := 31;
  1263. WHILE phyAdr > 0 DO
  1264. status := Read(phyAdr, PhyDetectReg, phyReg);
  1265. IF (phyReg # 0FFFFH) & (SYSTEM.VAL(SET, phyReg) * PhyDetect = PhyDetect) THEN
  1266. IF Trace THEN KernelLog.String("Found PHY at "); KernelLog.Address(phyAdr); KernelLog.Ln END;
  1267. RETURN phyAdr
  1268. END;
  1269. DEC(phyAdr)
  1270. END;
  1271. IF Trace THEN KernelLog.String("PHY not found. Assuming its address is 0"); KernelLog.Ln END;
  1272. RETURN 0
  1273. END Detect;
  1274. PROCEDURE GetIEEEPhySpeed (): LONGINT;
  1275. VAR
  1276. temp, control, res, status, capabilities: LONGINT;
  1277. phyAdr: ADDRESS;
  1278. BEGIN
  1279. phyAdr := Detect();
  1280. IF Trace THEN KernelLog.String("Start PHY autonegociation"); KernelLog.Ln END;
  1281. res := Write(phyAdr, IeeePageAddressRegister, 2);
  1282. res := Read(phyAdr, IeeeControlRegMac, control);
  1283. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeRgmiiTxRxClockDelayed);
  1284. res := Write(phyAdr, IeeeControlRegMac, control);
  1285. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1286. res := Read(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1287. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeAsymmetricPause + IeeePause + Advertise100 + Advertise10);
  1288. res := Write(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1289. res := Read(phyAdr, Ieee1000AdvertiseReg, control);
  1290. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + Advertise1000);
  1291. res := Write(phyAdr, Ieee1000AdvertiseReg, control);
  1292. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1293. res := Read(phyAdr, IeeeCopperSpecificControlReg, control);
  1294. control := control + LSH(7, 12); (* Max number of gigabit attemps *)
  1295. INCL(SYSTEM.VAL(SET, control), 11); (* Enable dowshift *)
  1296. res := Write(phyAdr, IeeeCopperSpecificControlReg, control);
  1297. res := Read(phyAdr, IeeeControlReg, control);
  1298. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlAutonegotiateEnable);
  1299. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeStatAutonegotiateRestart);
  1300. res := Write(phyAdr, IeeeControlReg, control);
  1301. res := Read(phyAdr, IeeeControlReg, control);
  1302. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlReset);
  1303. res := Write(phyAdr, IeeeControlReg, control);
  1304. REPEAT
  1305. IF Trace THEN KernelLog.String("Waiting for PHY reset"); KernelLog.Ln END;
  1306. res := Read(phyAdr, IeeeControlReg, control)
  1307. UNTIL SYSTEM.VAL(SET, control) * IeeeCtrlReset = {};
  1308. IF Trace THEN KernelLog.String("Waiting for PHY to complete autonegotiation"); KernelLog.Ln END;
  1309. res := Read(phyAdr, IeeeStatusReg, status);
  1310. WHILE SYSTEM.VAL(SET, status) * IeeeStatAutonegotiateComplete = {} DO
  1311. timer.Sleep(1000);
  1312. res := Read(phyAdr, IeeeCopperSpecificStatusReg2, temp);
  1313. IF Trace & (SYSTEM.VAL(SET, temp) * IeeeAutonegError # {}) THEN
  1314. KernelLog.String("Autonegotiation error");
  1315. KernelLog.Ln
  1316. END;
  1317. res := Read(phyAdr, IeeeStatusReg, status)
  1318. END;
  1319. IF Trace THEN KernelLog.String("Autonegotiation complete"); KernelLog.Ln END;
  1320. res := Read(phyAdr, IeeeSpecificStatusReg, capabilities);
  1321. IF 15 IN SYSTEM.VAL(SET, capabilities) THEN
  1322. RETURN 1000 (* MB/s *)
  1323. ELSIF 14 IN SYSTEM.VAL(SET, capabilities) THEN
  1324. RETURN 100 (* MB/s *)
  1325. ELSE
  1326. RETURN 10 (* MB/s *)
  1327. END
  1328. END GetIEEEPhySpeed;
  1329. PROCEDURE ConfigureIEEEPhySpeed (speed: LONGINT);
  1330. VAR
  1331. control, res, wait: LONGINT;
  1332. phyAdr: ADDRESS;
  1333. BEGIN
  1334. phyAdr := Detect();
  1335. res := Write(phyAdr, IeeePageAddressRegister, 2);
  1336. res := Read(phyAdr, IeeeControlRegMac, control);
  1337. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeRgmiiTxRxClockDelayed);
  1338. res := Write(phyAdr, IeeeControlRegMac, control);
  1339. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1340. res := Read(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1341. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeAsymmetricPause);
  1342. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeePause);
  1343. res := Write(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1344. res := Read(phyAdr, IeeeControlReg, control);
  1345. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) * (-IeeeCtrlLinkSpeed1000M) * (-IeeeCtrlLinkSpeed100M) * (-IeeeCtrlLinkSpeed10M));
  1346. IF linkSpeed = 1000 THEN
  1347. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed1000M)
  1348. ELSIF linkSpeed = 100 THEN
  1349. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed100M)
  1350. (* Don't advertise PHY speed of 1000 MBPS *)
  1351. ELSIF linkSpeed = 10 THEN
  1352. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed10M)
  1353. END;
  1354. END ConfigureIEEEPhySpeed;
  1355. PROCEDURE SetUpSLCRDivisors (div: LONGINT);
  1356. END SetUpSLCRDivisors;
  1357. PROCEDURE Write (address, register: ADDRESS; data: LONGINT): LONGINT;
  1358. VAR
  1359. reg, mgtcr, ipisr: SET;
  1360. BEGIN
  1361. IF Trace THEN KernelLog.String("PHY write"); KernelLog.Ln END;
  1362. SYSTEM.GET(iobase + Nwsr, reg);
  1363. (* Make sure no other PHY operation is currently in progress *)
  1364. IF ~(NwsrMdioIdle IN reg) THEN
  1365. IF Trace THEN KernelLog.String("XEmac Phy write aborted: PHY busy"); KernelLog.Ln END;
  1366. RETURN EmacMiiBusy
  1367. END;
  1368. (* Construct Mgtcr mask for the operation *)
  1369. mgtcr := PhyMntncOp + PhyMntncOpW + SYSTEM.VAL(SET, LSH(phybase, PhyMntncPhyAdShift))
  1370. + SYSTEM.VAL(SET, LSH(address, PhyMntncPhyAdShift))
  1371. + SYSTEM.VAL(SET, LSH(register, PhyMntncPhRegShift)) + SYSTEM.VAL(SET,data);
  1372. SYSTEM.PUT(iobase + PhyMntnc, mgtcr);
  1373. REPEAT
  1374. SYSTEM.GET(iobase + Nwsr, ipisr)
  1375. UNTIL NwsrMdioIdle IN ipisr;
  1376. RETURN Success
  1377. END Write;
  1378. PROCEDURE Read (address, register: ADDRESS; VAR data: LONGINT): LONGINT;
  1379. VAR
  1380. reg, ipisr, mgtcr: SET;
  1381. BEGIN
  1382. SYSTEM.GET(iobase + Nwsr, reg);
  1383. IF ~(NwsrMdioIdle IN reg) THEN
  1384. IF Trace THEN KernelLog.String("XEmac Phy read aborted: PHY busy"); KernelLog.Ln END;
  1385. RETURN EmacMiiBusy
  1386. END;
  1387. mgtcr := PhyMntncOp + PhyMntncOpR
  1388. + SYSTEM.VAL(SET, LSH(address, PhyMntncPhyAdShift))
  1389. + SYSTEM.VAL(SET, LSH(register, PhyMntncPhRegShift));
  1390. SYSTEM.PUT(iobase + PhyMntnc, mgtcr);
  1391. REPEAT
  1392. SYSTEM.GET(iobase + Nwsr, ipisr)
  1393. UNTIL NwsrMdioIdle IN ipisr;
  1394. data := SYSTEM.GET32(iobase + PhyMntnc) MOD 10000H;
  1395. RETURN Success
  1396. END Read;
  1397. END Phy;
  1398. PROCEDURE Install* (context: Commands.Context);
  1399. VAR ld: LinkDevice; res: WORD;
  1400. BEGIN {EXCLUSIVE}
  1401. NEW(ld, Network.TypeEthernet, 1500, 6); (*! What is the correct MTU? *)
  1402. ld.SetName("XEmac");
  1403. Network.registry.Add(ld, res);
  1404. IF res # 0 THEN
  1405. context.error.String("failed to install"); context.error.Ln;
  1406. context.result := Commands.CommandError; RETURN;
  1407. END;
  1408. NEW(ld.ctrl, ADDRESS(0E000B000H), ld);
  1409. END Install;
  1410. PROCEDURE Remove*;
  1411. VAR table: Plugins.Table; i: SIZE;
  1412. BEGIN {EXCLUSIVE}
  1413. Network.registry.GetAll(table);
  1414. IF table # NIL THEN
  1415. FOR i := 0 TO LEN(table)-1 DO
  1416. IF table[i] IS LinkDevice THEN table[i](LinkDevice).Finalize(TRUE) END
  1417. END
  1418. END;
  1419. END Remove;
  1420. BEGIN
  1421. Modules.InstallTermHandler(Remove);
  1422. END XEmac.