Zynq.XEmac.Mod 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602
  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;
  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 * (on: BOOLEAN);
  391. BEGIN
  392. Finalize^(on)
  393. END Finalize;
  394. END LinkDevice;
  395. (** Ethernet controller driver. *)
  396. Controller = OBJECT
  397. VAR
  398. (** Base of memory-mapped registers *)
  399. iobase: ADDRESS;
  400. dev: LinkDevice;
  401. phy: Phy;
  402. state, isStarted: LONGINT;
  403. speed: LONGINT;
  404. timer: Kernel.Timer;
  405. rxFrames: POINTER TO ARRAY OF Buffer;
  406. txFrame: Buffer;
  407. lastRxQBar, lastTxQBar: ADDRESS;
  408. rxBdBase, txBdBase: ADDRESS;
  409. options: SET;
  410. txBdStartAdr, txBdEndAdr, rxBdStartAdr, rxBdEndAdr: ADDRESS;
  411. kill, start: BOOLEAN;
  412. (* For DMA interaction *)
  413. buffer: POINTER TO ARRAY OF CHAR;
  414. (** Statistics *)
  415. nbrRxFrames, nbrtxFrames, nbrRxErrors, nbrTxErrors: LONGINT;
  416. (** Initializes the controller.
  417. iobase: base address of the registers
  418. *)
  419. PROCEDURE & Init * (iobase: ADDRESS; ld: LinkDevice);
  420. VAR
  421. i: LONGINT;
  422. reg: SET;
  423. (* TEST *)arp: ARRAY 28 OF CHAR;
  424. buf: ARRAY 256 OF Network.Buffer;
  425. BEGIN
  426. NEW(timer);
  427. NEW(rxFrames, RxBdCount);
  428. options := Defaults;
  429. SELF.iobase := iobase;
  430. dev := ld;
  431. dev.calcChecksum := {Network.ChecksumIP, Network.ChecksumTCP, Network.ChecksumUDP};
  432. kill := FALSE;
  433. start := FALSE;
  434. state := IsReady;
  435. Reset;
  436. (* Initialize HW *)
  437. IF Trace THEN KernelLog.String("Zynq.XEmac: Initializing hardware"); KernelLog.Ln END;
  438. SetMacAddress(1, SYSTEM.VAL(Network.LinkAdr, [0X, 0AX, 35X, 0X, 1X, 2X, 0X, 0X]));
  439. SetMdioDivisor(MdcDiv224);
  440. NEW(phy, iobase);
  441. speed := phy.linkSpeed;
  442. IF speed # 1000 THEN
  443. IF Trace THEN KernelLog.String("XEmac: error in speed initialization."); KernelLog.Ln END;
  444. RETURN
  445. END;
  446. SetOperatingSpeed(speed);
  447. SYSTEM.GET(iobase + Dmacr, reg);
  448. INCL(reg, 4);
  449. SYSTEM.PUT(iobase + Dmacr, reg);
  450. SetMdioDivisor(MdcDiv224);
  451. IF Trace THEN KernelLog.String("XEmac: Initializing DMA"); KernelLog.Ln END;
  452. FOR i := 0 TO 6000000 DO END;
  453. InitDMA;
  454. (* preallocate network stack buffers *)
  455. FOR i := 0 TO LEN(buf,0)-1 DO
  456. buf[i] := Network.GetNewBuffer();
  457. END;
  458. FOR i := 0 TO LEN(buf,0)-1 DO
  459. Network.ReturnBuffer(buf[i]);
  460. END;
  461. IF Trace THEN KernelLog.String("XEmac: Starting controller"); KernelLog.Ln END;
  462. Start
  463. END Init;
  464. (* Terminates the process *)
  465. PROCEDURE Kill;
  466. BEGIN {EXCLUSIVE}
  467. kill := TRUE
  468. END Kill;
  469. PROCEDURE Start;
  470. VAR
  471. reg: SET;
  472. BEGIN
  473. IF Trace THEN KernelLog.String("Starting XEmac"); KernelLog.Ln END;
  474. IF isStarted = IsStarted THEN RETURN END;
  475. (* Start DMA *)
  476. SYSTEM.PUT(iobase + Rxqbase, rxBdBase);
  477. SYSTEM.PUT(iobase + Txqbase, txBdBase);
  478. (* Clear any existing interrupt status *)
  479. SYSTEM.PUT(iobase + Isr, IxrAll);
  480. (* Optionally enable TX and RX *)
  481. IF TransmitterEnable IN options THEN
  482. SYSTEM.GET(iobase + Nwctrl, reg);
  483. reg := reg + NwctrlTxEn;
  484. SYSTEM.PUT(iobase + Nwctrl, reg)
  485. END;
  486. IF ReceiverEnable IN options THEN
  487. SYSTEM.GET(iobase + Nwctrl, reg);
  488. reg := reg + NwctrlRxEn;
  489. SYSTEM.PUT(iobase + Nwctrl, reg)
  490. END;
  491. (* Enable TX and RX interrupts *)
  492. SYSTEM.PUT(iobase + Ier, (IxrTxErr + IxrRxErr + {IxrTxCompl, IxrFrameRx}) * IxrAll);
  493. (*BEGIN {EXCLUSIVE}
  494. start := TRUE
  495. END;*)
  496. (*VAR
  497. reg: SET;
  498. BEGIN
  499. SYSTEM.GET(iobase + Nwctrl, reg);
  500. reg := reg + NwctrlStartTx;
  501. SYSTEM.PUT(iobase + Nwctrl, reg)*)
  502. END Start;
  503. PROCEDURE Stop;
  504. VAR
  505. reg: SET;
  506. BEGIN
  507. ASSERT(state = IsReady);
  508. (* Disable all interrupts *)
  509. SYSTEM.PUT32(iobase + Idr, IxrAll);
  510. (* Disable TX and RX *)
  511. SYSTEM.GET(iobase + Nwctrl, reg);
  512. reg := reg - (NwctrlRxEn + NwctrlTxEn);
  513. SYSTEM.PUT(iobase + Nwctrl, reg);
  514. isStarted := 0
  515. END Stop;
  516. PROCEDURE Transmit;
  517. VAR
  518. reg: SET;
  519. BEGIN
  520. IF Trace THEN KernelLog.String("XEmac: transmitting"); KernelLog.Ln END;
  521. SYSTEM.GET(iobase + Nwctrl, reg);
  522. reg := reg + NwctrlStartTx;
  523. SYSTEM.PUT(iobase + Nwctrl, reg)
  524. END Transmit;
  525. (** Stop and restart device *)
  526. PROCEDURE Reset;
  527. VAR
  528. i, tmp: LONGINT;
  529. reg: SET;
  530. BEGIN
  531. IF Trace THEN KernelLog.String("XEmac resetting controller"); KernelLog.Ln END;
  532. ASSERT(state = IsReady);
  533. Stop;
  534. options := Defaults;
  535. reg := (NwctrlStatclr + NwctrlMdEn) * (-NwctrlLoopEn);
  536. SYSTEM.PUT(iobase + Nwctrl, reg);
  537. reg := {};
  538. INCL(reg, Nwcfg100);
  539. INCL(reg, NwcfgFdEn);
  540. INCL(reg, NwcfgUcastHashEn);
  541. SYSTEM.PUT(iobase + Nwcfg, reg);
  542. i := RxBufSize DIV RxBufUnit;
  543. IF RxBufSize MOD RxBufUnit # 0 THEN INC(i) END;
  544. reg := SYSTEM.VAL(SET, LSH(i, DmacrRxBufShift)) * DmacrRxBuf + DmacrRxSize;
  545. INCL(reg, DmacrTxSize);
  546. SYSTEM.PUT(iobase + Dmacr, reg);
  547. SYSTEM.PUT32(iobase + Txsr, 0);
  548. SYSTEM.PUT32(iobase + Rxqbase, 0);
  549. SYSTEM.PUT32(iobase + Txqbase, 0);
  550. SYSTEM.PUT32(iobase + Rxsr, 0);
  551. SYSTEM.PUT32(iobase + Idr, IxrAll);
  552. SYSTEM.GET(iobase + Isr, reg);
  553. SYSTEM.PUT(iobase + Isr, reg);
  554. SYSTEM.PUT32(iobase + PhyMntnc, 0);
  555. ClearHash;
  556. (* Clear all MAC addresses *)
  557. FOR i := 1 TO 4 DO
  558. SetMacAddress(i, ZeroMAC);
  559. tmp := SetTypeIdCheck(i, 0)
  560. END;
  561. (* Clear all counters. *)
  562. FOR i := 0 TO (Last- OctTxL) DIV 4 - 1 DO
  563. SYSTEM.GET(iobase + OctTxL + 4 * i, reg)
  564. END;
  565. (* Disable receiver. *)
  566. SYSTEM.GET(iobase + Nwctrl, reg);
  567. SYSTEM.PUT(iobase + Nwctrl, reg - NwctrlRxEn);
  568. SetOptions(options - {TransmitterEnable, ReceiverEnable});
  569. ClearOptions(-options);
  570. END Reset;
  571. PROCEDURE ResetDevice;
  572. VAR
  573. options: SET;
  574. BEGIN
  575. Stop;
  576. options := SELF.options;
  577. Reset;
  578. SetOptions(options);
  579. ClearOptions(-options)
  580. END ResetDevice;
  581. PROCEDURE SendFrame (CONST dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  582. VAR
  583. txLen, offset: LONGINT;
  584. bufferAdr, txbd: ADDRESS;
  585. intsEnabled: BOOLEAN;
  586. reg: SET;
  587. BEGIN (*{EXCLUSIVE}*)
  588. IF Trace THEN KernelLog.String("XEmac: Sending Frame"); KernelLog.Ln END;
  589. (* Prepare buffer *) (* This part is taken from RTL8169.Mod *)
  590. txLen := 14 + h3len + h4len + dlen;
  591. bufferAdr := ADDRESSOF(txFrame[0]);
  592. (* set destination mac address (first 6 bytes of eth frame) *)
  593. SYSTEM.MOVE(ADDRESSOF(dst[0]), bufferAdr, 6);
  594. (*txFrame[0] := dst[0]; txFrame[1] := dst[1]; txFrame[2] := dst[2]; txFrame[3] := dst[3]; txFrame[4] := dst[4]; txFrame[5] := dst[5];*)
  595. (* set source mac address (6 bytes @ offset 6 of eth frame) *)
  596. SYSTEM.MOVE(ADDRESSOF(dev.local[0]), bufferAdr + 6, 6);
  597. (*txFrame[6]:=000X;txFrame[7]:=00AX;txFrame[8]:=035X;txFrame[9]:=000X;txFrame[10]:=001X;txFrame[11]:=002X;*)
  598. (* set upper layer type, bring type from host to network byte order *)
  599. SYSTEM.PUT16(bufferAdr + 12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
  600. (*IF Trace THEN
  601. KernelLog.Buffer(txFrame, 0, txLen);
  602. KernelLog.Ln
  603. END;*)
  604. offset := 14;
  605. (* move layer 3 and layer 4 headers, data *)
  606. IF h3len > 0 THEN
  607. SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), bufferAdr + offset, h3len);
  608. INC(offset, h3len);
  609. END;
  610. IF h4len > 0 THEN
  611. SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), bufferAdr + offset, h4len);
  612. INC(offset, h4len);
  613. END;
  614. IF offset + dlen < BufSize THEN
  615. SYSTEM.MOVE(ADDRESSOF(data[0]) + dofs, bufferAdr + offset, dlen);
  616. INC(offset, dlen);
  617. END;
  618. (* make the frame at least 64 bytes long *)
  619. WHILE offset < 60 DO
  620. txFrame[offset] := CHR(0);
  621. INC(offset);
  622. INC(txLen)
  623. END;
  624. (*IF Trace THEN
  625. KernelLog.String("Sending frame of length ");
  626. KernelLog.Int(txLen, 0);
  627. KernelLog.Ln;
  628.  KernelLog.Memory(bufferAdr, txLen)
  629. END;*)
  630. (* Send it with DMA *)
  631. intsEnabled := Machine.AreInterruptsEnabled();
  632. Machine.DisableInterrupts;
  633. SYSTEM.GET(iobase + Txqbase, txbd);
  634. IF txbd = 0 THEN txbd := txBdStartAdr END;
  635. Machine.FlushDCacheRange(ADDRESSOF(txFrame[0]), txLen);
  636. SYSTEM.PUT(txbd + BdAdrOffset, ADDRESSOF(txFrame));
  637. IF txbd # txBdEndAdr THEN
  638. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast} + SYSTEM.VAL(SET, txLen));
  639. ELSE
  640. IF Trace THEN KernelLog.String("END OF TXBUFFERS"); KernelLog.Ln END;
  641. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast, TxBufWrap} + SYSTEM.VAL(SET, txLen));
  642. END;
  643. (* no need to flush/invalidate cache for BD memory space
  644. Machine.FlushDCacheRange(txbd, BdSize);
  645. *)
  646. CODE
  647. DSB
  648. END;
  649. (* Transmit *)
  650. Transmit;
  651. IF intsEnabled THEN Machine.EnableInterrupts END;
  652. END SendFrame;
  653. (** Called by the polling body. Signals the new frames to the link device *)
  654. PROCEDURE ReceiveFrame;
  655. VAR
  656. currentBd, adr: ADDRESS;
  657. len, i: LONGINT;
  658. reg: SET;
  659. buf: Network.Buffer;
  660. type: INTEGER;
  661. BEGIN
  662. (*IF Trace THEN KernelLog.String("Receiving frame"); KernelLog.Ln END;*)
  663. currentBd := lastRxQBar;
  664. SYSTEM.GET(currentBd + BdAdrOffset, adr);
  665. adr := adr - (adr MOD 4);
  666. SYSTEM.GET(currentBd, reg);
  667. IF RxBufNew IN reg THEN
  668. (*IF Trace THEN
  669. KernelLog.String("Current BD: "); KernelLog.Address(currentBd); KernelLog.Ln;
  670. KernelLog.String("QBar: "); KernelLog.Address(SYSTEM.GET32(iobase + Rxqbase)); KernelLog.Ln
  671. END;*)
  672. IF SYSTEM.GET32(currentBd + 4) = 0 THEN
  673. SYSTEM.GET(iobase + Nwctrl, reg);
  674. reg := reg * SET(-NwctrlRxEn);
  675. SYSTEM.PUT(iobase + Nwctrl, reg);
  676. SYSTEM.GET(iobase + Nwctrl, reg);
  677. reg := reg + NwctrlRxEn + {18};
  678. SYSTEM.PUT(iobase + Nwctrl, reg)
  679. ELSE
  680. IF Trace THEN KernelLog.String("Receiving frame"); KernelLog.Ln END;
  681. SYSTEM.GET(currentBd + BdStatOffset, reg);
  682. len := SYSTEM.VAL(LONGINT, reg * RxBufLen);
  683. (* Invalidate DCache *)
  684. (* no need to flush/invalidate cache for BD memory space
  685. Machine.InvalidateDCacheRange(currentBd,BdSize);
  686. *)
  687. Machine.InvalidateDCacheRange(adr,len);
  688. (* Construct Frame *)
  689. buf := Network.GetNewBuffer(); ASSERT(buf # NIL);
  690. buf.ofs := 14;
  691. buf.len := len - 14;
  692. buf.next := NIL;
  693. buf.prev := NIL;
  694. buf.calcChecksum := dev.calcChecksum;
  695. SYSTEM.MOVE(adr+6,ADDRESSOF(buf.src[0]),6);
  696. type := INTEGER(SYSTEM.GET8(adr + 12)) * 100H + INTEGER(SYSTEM.GET8(adr + 13));
  697. SYSTEM.MOVE(adr,ADDRESSOF(buf.data[0]),len);
  698. dev.QueueBuffer(buf, type)
  699. END
  700. END;
  701. IF currentBd = rxBdEndAdr THEN
  702. SYSTEM.PUT32(currentBd + BdAdrOffset, adr + 2);
  703. lastRxQBar := rxBdStartAdr
  704. ELSE
  705. SYSTEM.PUT32(currentBd + BdAdrOffset, adr);
  706. INC(lastRxQBar, BdSize)
  707. END;
  708. SYSTEM.PUT32(currentBd + BdStatOffset, 0);
  709. (* no need to flush/invalidate cache for BD memory space
  710. Machine.FlushDCacheRange(currentBd, BdSize);
  711. *)
  712. END ReceiveFrame;
  713. PROCEDURE SetOptions (opts: SET);
  714. VAR
  715. reg, regNetCfg, regNewNetCfg: SET;
  716. BEGIN
  717. IF Trace THEN KernelLog.String("XEmac.SetOptions: "); KernelLog.Hex(SYSTEM.VAL(ADDRESS, opts), -8); KernelLog.Ln END;
  718. ASSERT(state = IsReady);
  719. (* Many of these options will change the NET_CONFIG registers.
  720. * To reduce the amount of IO to the device, group these options here
  721. * and change them all at once.
  722. *)
  723. (* Grab current register contents *)
  724. SYSTEM.GET(iobase + Nwcfg, regNetCfg);
  725. regNewNetCfg := regNetCfg;
  726. IF Trace THEN KernelLog.String("regNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, regNetCfg), -8); KernelLog.Ln END;
  727. (*
  728. * It is configured to max 1536.
  729. *)
  730. IF Frame1536 IN opts THEN
  731. regNewNetCfg := regNewNetCfg + {Nwcfg1536RxEn};
  732. END;
  733. (* Turn on VLAN packet only, only VLAN tagged will be accepted *)
  734. IF Vlan IN opts THEN
  735. regNewNetCfg := regNewNetCfg + {NwcfgNvlanDisc};
  736. END;
  737. (* Turn on FCS stripping on receive packets *)
  738. IF FcsStrip IN opts THEN
  739. regNewNetCfg := regNewNetCfg + {NwcfgFcsRem};
  740. END;
  741. (* Turn on length/type field checking on receive packets *)
  742. IF LenTypeErr IN opts THEN
  743. regNewNetCfg := regNewNetCfg + {NwcfgLengthErrDscrd};
  744. END;
  745. (* Turn on flow control *)
  746. IF FlowControl IN opts THEN
  747. regNewNetCfg := regNewNetCfg + {NwcfgPauseEn};
  748. END;
  749. (* Turn on promiscuous frame filtering (all frames are received) *)
  750. IF Promisc IN opts THEN
  751. regNewNetCfg := regNewNetCfg + {NwcfgCopyAllEn};
  752. END;
  753. (* Allow broadcast address reception *)
  754. IF Broadcast IN opts THEN
  755. regNewNetCfg := regNewNetCfg - {NwcfgBcastDi};
  756. END;
  757. (* Allow multicast address filtering *)
  758. IF Multicast IN opts THEN
  759. regNewNetCfg := regNewNetCfg + {NwcfgMcastHashEn};
  760. END;
  761. (* enable RX checksum offload *)
  762. IF RxChksumEnable IN opts THEN
  763. regNewNetCfg := regNewNetCfg + {NwcfgRxChkSumEn};
  764. END;
  765. (* Officially change the NET_CONFIG registers if it needs to be
  766. * modified.
  767. *)
  768. IF regNetCfg # regNewNetCfg THEN
  769. SYSTEM.PUT(iobase + Nwcfg, regNewNetCfg);
  770. END;
  771. IF Trace THEN KernelLog.String("regNewNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, regNewNetCfg), -8); KernelLog.Ln END;
  772. (* Enable TX checksum offload *)
  773. IF TxChksumEnable IN opts THEN
  774. SYSTEM.GET(iobase + Dmacr, reg);
  775. reg := reg + {DmacrTcpChksum};
  776. SYSTEM.PUT(iobase + Dmacr, reg);
  777. IF Trace THEN KernelLog.String("DMACR_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  778. END;
  779. (* Enable transmitter *)
  780. IF TransmitterEnable IN opts THEN
  781. SYSTEM.GET(iobase + Nwctrl, reg);
  782. reg := reg + NwctrlTxEn;
  783. SYSTEM.PUT(iobase + Nwctrl, reg);
  784. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  785. END;
  786. (* Enable receiver *)
  787. IF ReceiverEnable IN opts THEN
  788. SYSTEM.GET(iobase + Nwctrl, reg);
  789. reg := reg + NwctrlRxEn;
  790. SYSTEM.PUT(iobase + Nwctrl, reg);
  791. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  792. END;
  793. (* The remaining options not handled here are managed elsewhere in the
  794. * driver. No register modifications are needed at this time. Reflecting
  795. * the option in InstancePtr->Options is good enough for now.
  796. *)
  797. (* Set options word to its new value *)
  798. SELF.options := SELF.options + opts;
  799. IF Trace THEN KernelLog.String("SetOptions END "); KernelLog.Address(SYSTEM.VAL(ADDRESS, SELF.options)); KernelLog.Ln END;
  800. END SetOptions;
  801. PROCEDURE ClearOptions (opts: SET);
  802. VAR
  803. reg, old: SET;
  804. BEGIN
  805. IF Trace THEN KernelLog.String("XEmac: Clear Options"); KernelLog.Ln END;
  806. SYSTEM.GET(iobase + Nwcfg, reg);
  807. old := reg;
  808. (*
  809. * It is configured to max 1536.
  810. *)
  811. IF Frame1536 IN opts THEN
  812. EXCL(reg, Nwcfg1536RxEn);
  813. END;
  814. (* Turn off VLAN packet only, only VLAN tagged will be accepted *)
  815. IF Vlan IN opts THEN
  816. EXCL(reg, NwcfgNvlanDisc);
  817. END;
  818. (* Turn off FCS stripping on receive packets *)
  819. IF FcsStrip IN opts THEN
  820. EXCL(reg, NwcfgFcsRem);
  821. END;
  822. (* Turn off length/type field checking on receive packets *)
  823. IF LenTypeErr IN opts THEN
  824. EXCL(reg, NwcfgLengthErrDscrd);
  825. END;
  826. (* Turn off flow control *)
  827. IF FlowControl IN opts THEN
  828. EXCL(reg, NwcfgPauseEn);
  829. END;
  830. (* Turn off promiscuous frame filtering (all frames are received) *)
  831. IF Promisc IN opts THEN
  832. EXCL(reg, NwcfgCopyAllEn);
  833. END;
  834. (* Forbid broadcast address reception *)
  835. IF Broadcast IN opts THEN
  836. EXCL(reg, NwcfgBcastDi);
  837. END;
  838. (* Forbid multicast address filtering *)
  839. IF Multicast IN opts THEN
  840. EXCL(reg, NwcfgMcastHashEn);
  841. END;
  842. (* Disable RX checksum offload *)
  843. IF RxChksumEnable IN opts THEN
  844. EXCL(reg, NwcfgRxChkSumEn);
  845. END;
  846. (* Officially change the NET_CONFIG registers if it needs to be
  847. * modified.
  848. *)
  849. IF reg # old THEN
  850. SYSTEM.PUT(iobase + Nwcfg, reg);
  851. END;
  852. IF Trace THEN KernelLog.String("regNewNetCfg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  853. (* Disable TX checksum offload *)
  854. IF TxChksumEnable IN opts THEN
  855. SYSTEM.GET(iobase + Dmacr, reg);
  856. EXCL(reg, DmacrTcpChksum);
  857. SYSTEM.PUT(iobase + Dmacr, reg);
  858. IF Trace THEN KernelLog.String("DMACR_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  859. END;
  860. (* Disable transmitter *)
  861. IF TransmitterEnable IN opts THEN
  862. SYSTEM.GET(iobase + Nwctrl, reg);
  863. reg := reg * SET(-NwctrlTxEn);
  864. SYSTEM.PUT(iobase + Nwctrl, reg);
  865. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  866. END;
  867. (* Disable receiver *)
  868. IF ReceiverEnable IN opts THEN
  869. SYSTEM.GET(iobase + Nwctrl, reg);
  870. reg := reg * SET(-NwctrlRxEn);
  871. SYSTEM.PUT(iobase + Nwctrl, reg);
  872. IF Trace THEN KernelLog.String("NWCTRL_OFFSET reg="); KernelLog.Hex(SYSTEM.VAL(LONGINT, reg), -8); KernelLog.Ln END;
  873. END;
  874. SELF.options := SELF.options * (-opts);
  875. END ClearOptions;
  876. PROCEDURE ClearHash;
  877. BEGIN
  878. IF Trace THEN KernelLog.String("XEmac: Clear Hash"); KernelLog.Ln END;
  879. ASSERT(state = IsReady);
  880. SYSTEM.PUT32(iobase + HashL, 0);
  881. SYSTEM.PUT32(iobase + HashH, 0)
  882. END ClearHash;
  883. PROCEDURE SetMdioDivisor (divisor: LONGINT);
  884. VAR
  885. reg: SET;
  886. BEGIN
  887. ASSERT(state = IsReady);
  888. (* Only last 3 bits are valid *)
  889. ASSERT(divisor < 8);
  890. SYSTEM.GET(iobase + Nwcfg, reg);
  891. reg := reg * SET(-NwcfgMdcClkDiv);
  892. reg := reg + SYSTEM.VAL(SET, LSH(divisor, NwcfgMdcShift));
  893. SYSTEM.PUT(iobase + Nwcfg, reg);
  894. END SetMdioDivisor;
  895. PROCEDURE SetOperatingSpeed (speed: LONGINT);
  896. VAR
  897. reg: SET;
  898. BEGIN
  899. IF Trace THEN KernelLog.String("XEmac: setting operating speed."); KernelLog.Ln END;
  900. ASSERT(state = IsReady);
  901. ASSERT((speed = 10) OR (speed = 100) OR (speed = 1000));
  902. SYSTEM.GET(iobase + Nwcfg, reg);
  903. reg := reg - {Nwcfg1000, Nwcfg100};
  904. CASE speed OF
  905. 10:
  906. |100:
  907. INCL(reg, Nwcfg100)
  908. |1000:
  909. INCL(reg, Nwcfg1000)
  910. END;
  911. SYSTEM.PUT(iobase + Nwcfg, reg);
  912. IF Trace THEN KernelLog.String("Waiting for operation speed to stabilize"); KernelLog.Ln END;
  913. timer.Sleep(1000);
  914. IF Trace THEN KernelLog.String("XEmac: operating speed set."); KernelLog.Ln END;
  915. END SetOperatingSpeed;
  916. (*! TODO: change parameter interface to a more convenient one *)
  917. PROCEDURE SetMacAddress(index: LONGINT; mac: Network.LinkAdr);
  918. VAR
  919. reg: SET;
  920. BEGIN
  921. ASSERT(index > 0);
  922. DEC(index);
  923. reg := SYSTEM.VAL(SET, ORD(mac[0]) + LSH(ORD(mac[1]), 8) + LSH(ORD(mac[2]), 16) + LSH(ORD(mac[3]), 24));
  924. SYSTEM.PUT(iobase + Laddr1l + (index * 8), reg);
  925. (* There are reserved bits in TOP so don't affect them *)
  926. SYSTEM.GET(iobase + Laddr1h + (index * 8), reg);
  927. reg := reg * SET(-LaddrMach) + SYSTEM.VAL(SET, ORD(mac[4]) + LSH(ORD(mac[5]), 8));
  928. SYSTEM.PUT(iobase + Laddr1h + index * 8, reg);
  929. dev.local := mac;
  930. IF Trace THEN
  931. KernelLog.String("XEmac MAC address set to: ");
  932. KernelLog.Hex(ORD(mac[0]), -2); KernelLog.String(".");
  933. KernelLog.Hex(ORD(mac[1]), -2); KernelLog.String(".");
  934. KernelLog.Hex(ORD(mac[2]), -2); KernelLog.String(".");
  935. KernelLog.Hex(ORD(mac[3]), -2); KernelLog.String(".");
  936. KernelLog.Hex(ORD(mac[4]), -2); KernelLog.String(".");
  937. KernelLog.Hex(ORD(mac[5]), -2); KernelLog.Ln
  938. END
  939. END SetMacAddress;
  940. PROCEDURE SetTypeIdCheck(index, idCheck: LONGINT): LONGINT;
  941. BEGIN
  942. ASSERT(state = IsReady);
  943. ASSERT((index > 0) & (index <= MaxTypeId));
  944. IF isStarted = IsStarted THEN
  945. RETURN IsStarted
  946. END;
  947. SYSTEM.PUT(iobase + Match1 + index * 4, idCheck);
  948. RETURN Success
  949. END SetTypeIdCheck;
  950. PROCEDURE InitDMA;
  951. CONST
  952. MB = 1024*1024;
  953. VAR
  954. beginAdr, endAdr, adr: ADDRESS;
  955. reg: SET;
  956. i: LONGINT;
  957. BEGIN
  958. IF Trace THEN KernelLog.String("XEmac: Starting DMA"); KernelLog.Ln END;
  959. (*
  960. NEW(buffer, (RxBdCount + TxBdCount + 20) * BdSize);
  961. *)
  962. (* allocate 2 pages (each page is 1 MBytes) of memory in Heaps for mapping one full page uncached
  963. without affecting any adjacent data *)
  964. NEW(buffer,2*MB);
  965. ASSERT((RxBdCount + TxBdCount + 20) * BdSize <= MB);
  966. beginAdr := ADDRESSOF(buffer[0]);
  967. beginAdr := beginAdr + (MB - beginAdr MOD MB);
  968. ASSERT(beginAdr MOD MB = 0);
  969. Machine.DisableDCacheRange(beginAdr,MB);
  970. (* setup DMA RX buffer descriptors *)
  971. rxBdStartAdr := beginAdr;
  972. endAdr := beginAdr + (RxBdCount - 1) * BdSize;
  973. rxBdEndAdr := endAdr;
  974. i := 0;
  975. adr := beginAdr;
  976. WHILE adr < endAdr DO
  977. SYSTEM.PUT32(adr + BdAdrOffset, ADDRESSOF(rxFrames[i][0]));
  978. INC(adr, BdSize);
  979. INC(i)
  980. END;
  981. SYSTEM.PUT32(adr + BdAdrOffset, ADDRESSOF(rxFrames[i][0]) + 2);
  982. lastRxQBar := beginAdr;
  983. rxBdBase := beginAdr;
  984. CODE
  985. DSB
  986. END;
  987. (* no need to flush/invalidate cache for BD memory space
  988. (* Flush DCache *)
  989. Machine.FlushDCacheRange(beginAdr, RxBdCount * BdSize);
  990. *)
  991. IF Trace THEN KernelLog.String("XEmac: RX buffers are set up."); KernelLog.Ln END;
  992. (* setup DMA TX buffer descriptors *)
  993. beginAdr := endAdr + BdSize;
  994. txBdStartAdr := beginAdr;
  995. endAdr := beginAdr + (TxBdCount - 1) * BdSize;
  996. txBdEndAdr := endAdr;
  997. adr := beginAdr;
  998. WHILE adr < endAdr DO
  999. SYSTEM.PUT32(adr, 0);
  1000. SYSTEM.PUT32(adr + 4, {TxBufUsed});
  1001. INC(adr, BdSize)
  1002. END;
  1003. SYSTEM.PUT32(adr + 4, {TxBufUsed, TxBufWrap});
  1004. lastTxQBar := beginAdr;
  1005. txBdBase := beginAdr;
  1006. CODE
  1007. DSB
  1008. END;
  1009. (* no need to flush/invalidate cache for BD memory space
  1010. (* Flush DCache *)
  1011. Machine.FlushDCacheRange(txBdBase, TxBdCount * BdSize);
  1012. *)
  1013. IF Trace THEN KernelLog.String("XEmac: TX buffers are set up."); KernelLog.Ln END;
  1014. Objects.InstallHandler(SELF.InterruptHandler, IRQ);
  1015. IF Trace THEN KernelLog.String("DMA Initialized"); KernelLog.Ln END
  1016. END InitDMA;
  1017. (**
  1018. Interrupt handler -- tries to handle the maximum number of IRQs
  1019. at once.
  1020. *)
  1021. PROCEDURE InterruptHandler;
  1022. VAR
  1023. regISR, regSR: SET;
  1024. BEGIN
  1025. ASSERT(state = IsReady);
  1026. (* Get and clear interrupts *)
  1027. SYSTEM.GET(iobase + Isr, regISR);
  1028. SYSTEM.PUT(iobase + Isr, regISR);
  1029. (* Transmit complete interrupt *)
  1030. IF IxrTxCompl IN regISR THEN
  1031. SYSTEM.PUT(iobase + Txsr, {TxsrTxCompl, TxsrUsedRead});
  1032. SendHandler
  1033. END;
  1034. (* Receive complete interrupt *)
  1035. IF IxrFrameRx IN regISR THEN
  1036. SYSTEM.PUT(iobase + Rxsr, {RxsrFrameRx, RxsrBuffna});
  1037. ReceiveHandler
  1038. END;
  1039. (* Receive error conditions interrupt *)
  1040. IF IxrRxErr * regISR # {} THEN
  1041. (* Clear Rx status register *)
  1042. SYSTEM.GET(iobase + Rxsr, regSR);
  1043. SYSTEM.PUT(iobase + Rxsr, regSR);
  1044. IF IxrRxUsed IN regISR THEN
  1045. (* Flush a packet from Rx SRAM *)
  1046. SYSTEM.GET(iobase + Nwctrl, regSR);
  1047. SYSTEM.PUT(iobase + Nwctrl, regSR + {18})
  1048. END;
  1049. ErrorHandler(Recv, regSR)
  1050. END;
  1051. (* Transmit error interrupt
  1052. TxCompl also activates TxUsed when asserted: we have to check for a real error.
  1053. *)
  1054. IF (IxrTxErr * regISR # {}) & (~(IxrTxCompl IN regISR)) THEN
  1055. SYSTEM.GET(iobase + Txsr, regSR);
  1056. SYSTEM.PUT(iobase + Txsr, regSR);
  1057. ErrorHandler(Send, regSR)
  1058. END;
  1059. END InterruptHandler;
  1060. PROCEDURE SendHandler;
  1061. VAR
  1062. reg: SET;
  1063. currBdPtr: ADDRESS;
  1064. BEGIN
  1065. IF Trace THEN KernelLog.String("XEmac.SendHandler"); KernelLog.Ln END;
  1066. SYSTEM.GET(iobase + Txsr, reg);
  1067. SYSTEM.PUT(iobase + Txsr, reg);
  1068. LOOP
  1069. currBdPtr := lastTxQBar;
  1070. IF currBdPtr = SYSTEM.GET32(iobase + Txqbase) THEN EXIT END;
  1071. SYSTEM.PUT32(currBdPtr + BdAdrOffset, 0);
  1072. IF currBdPtr = txBdEndAdr THEN
  1073. SYSTEM.PUT(currBdPtr + BdStatOffset, {TxBufUsed, TxBufWrap});
  1074. lastTxQBar := txBdStartAdr
  1075. ELSE
  1076. SYSTEM.PUT(currBdPtr + BdStatOffset, {TxBufUsed});
  1077. INC(lastTxQBar, BdSize)
  1078. END
  1079. END;
  1080. IF Trace THEN KernelLog.String("XEmac.SendHandler END"); KernelLog.Ln END
  1081. END SendHandler;
  1082. PROCEDURE ReceiveHandler;
  1083. (*VAR
  1084. buf: Network.Buffer;
  1085. type: LONGINT;*)
  1086. VAR
  1087. reg: SET;
  1088. tmp: LONGINT;
  1089. BEGIN
  1090. IF Trace THEN KernelLog.String("XEmac.ReceiveHandler"); KernelLog.Ln END;
  1091. SYSTEM.GET(iobase + Rxsr, reg);
  1092. SYSTEM.PUT(iobase + Rxsr, reg);
  1093. SYSTEM.GET(iobase + Rxcnt, tmp);
  1094. IF tmp = 0 THEN
  1095. SYSTEM.GET(iobase + Nwctrl, reg);
  1096. reg := reg * SET(-NwctrlRxEn);
  1097. SYSTEM.PUT(iobase + Nwctrl, reg);
  1098. SYSTEM.GET(iobase + Nwctrl, reg);
  1099. reg := reg + NwctrlRxEn;
  1100. SYSTEM.PUT(iobase + Nwctrl, reg)
  1101. END
  1102. END ReceiveHandler;
  1103. PROCEDURE ErrorHandler (direction: CHAR; errorWord: SET);
  1104. BEGIN
  1105. IF Trace THEN KernelLog.String("XEmac.ErrorHandler: Error while ") END;
  1106. CASE direction OF
  1107. Send:
  1108. KernelLog.String("sending"); KernelLog.Ln;
  1109. IF TxsrHrespnok IN errorWord THEN
  1110. KernelLog.String("[XEmac ERROR] Transmit DMA error"); KernelLog.Ln
  1111. END;
  1112. IF TxsrUrun IN errorWord THEN
  1113. KernelLog.String("[XEmac ERROR] Transmit underrun"); KernelLog.Ln
  1114. END;
  1115. IF TxsrBufExh IN errorWord THEN
  1116. KernelLog.String("[XEmac ERROR] Transmit buffer exhausted"); KernelLog.Ln
  1117. END;
  1118. IF TxsrRxOvr IN errorWord THEN
  1119. KernelLog.String("[XEmac ERROR] Transmit retry limit exceeded"); KernelLog.Ln
  1120. END;
  1121. IF TxsrFrameRx IN errorWord THEN
  1122. KernelLog.String("[XEmac ERROR] Transmit collision"); KernelLog.Ln
  1123. END;
  1124. IF TxsrUsedRead IN errorWord THEN
  1125. KernelLog.String("[XEmac ERROR] Transmit buffer not available"); KernelLog.Ln;
  1126. KernelLog.String("QBar = "); KernelLog.Address(SYSTEM.GET32(iobase + Txqbase)); KernelLog.Ln
  1127. END;
  1128. |Recv:
  1129. KernelLog.String("receiving"); KernelLog.Ln;
  1130. IF RxsrHrespnok IN errorWord THEN
  1131. KernelLog.String("[XEmac ERROR] Receive DMA error"); KernelLog.Ln
  1132. END;
  1133. IF RxsrRxOvr IN errorWord THEN
  1134. KernelLog.String("[XEmac ERROR] Receive overrun"); KernelLog.Ln
  1135. END;
  1136. IF RxsrBuffna IN errorWord THEN
  1137. KernelLog.String("[XEmac ERROR] Receive buffer not available"); KernelLog.Ln
  1138. END
  1139. END;
  1140. ResetDevice
  1141. END ErrorHandler;
  1142. PROCEDURE SendTestFrame;
  1143. VAR
  1144. txbd: ADDRESS;
  1145. intsEnabled: BOOLEAN;
  1146. BEGIN
  1147. txFrame[0]:=0FFX;txFrame[1]:=0FFX;txFrame[2]:=0FFX;txFrame[3]:=0FFX;txFrame[4]:=0FFX;txFrame[5]:=0FFX;
  1148. txFrame[6]:=000X;txFrame[7]:=00AX;txFrame[8]:=035X;txFrame[9]:=000X;txFrame[10]:=001X;txFrame[11]:=002X;
  1149. txFrame[12]:=008X;txFrame[13]:=006X;txFrame[14]:=000X;txFrame[15]:=001X;
  1150. txFrame[16]:=008X;txFrame[17]:=000X;txFrame[18]:=006X;txFrame[19]:=004X;txFrame[20]:=000X;txFrame[21]:=001X;txFrame[22]:=000X;txFrame[23]:=00AX;
  1151. txFrame[24]:=035X;txFrame[25]:=000X;txFrame[26]:=001X;txFrame[27]:=002X;txFrame[28]:=0C0X;txFrame[29]:=0A8X;txFrame[30]:=001X;txFrame[31]:=00AX;
  1152. txFrame[32]:=000X;txFrame[33]:=000X;txFrame[34]:=000X;txFrame[35]:=000X;txFrame[36]:=000X;txFrame[37]:=000X;txFrame[38]:=0C0X;txFrame[39]:=0A8X;
  1153. txFrame[40]:=001X;txFrame[41]:=00AX;txFrame[42]:=000X;txFrame[43]:=000X;txFrame[44]:=000X;txFrame[45]:=000X;txFrame[46]:=000X;txFrame[47]:=000X;
  1154. txFrame[48]:=001X;txFrame[49]:=00AX;txFrame[50]:=000X;txFrame[51]:=000X;txFrame[52]:=000X;txFrame[53]:=000X;txFrame[54]:=000X;txFrame[55]:=000X;
  1155. txFrame[56]:=001X;txFrame[57]:=00AX;txFrame[58]:=000X;txFrame[59]:=000X;
  1156. KernelLog.String("Sending Test Frame"); KernelLog.Ln;
  1157. KernelLog.Address(ADDRESSOF(txFrame)); KernelLog.Ln;
  1158. KernelLog.Buffer(txFrame, 0, 60);
  1159. (* Send it with DMA *)
  1160. intsEnabled := Machine.AreInterruptsEnabled();
  1161. Machine.DisableInterrupts;
  1162. SYSTEM.GET(iobase + Txqbase, txbd);
  1163. KernelLog.String("SendTestFrame: txbd = "); KernelLog.Address(txbd); KernelLog.Ln;
  1164. IF txbd = 0 THEN txbd := txBdStartAdr END;
  1165. KernelLog.String("SendTestFrame: txbd = "); KernelLog.Address(txbd); KernelLog.Ln;
  1166. Machine.FlushDCacheRange(ADDRESSOF(txFrame), 60);
  1167. SYSTEM.PUT(txbd + BdAdrOffset, ADDRESSOF(txFrame));
  1168. IF txbd # txBdEndAdr THEN
  1169. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast} + SYSTEM.VAL(SET, 60));
  1170. ELSE
  1171. SYSTEM.PUT(txbd + BdStatOffset, {TxBufLast, TxBufWrap} + SYSTEM.VAL(SET, 60));
  1172. END;
  1173. (* no need to flush/invalidate cache for BD memory space
  1174. Machine.FlushDCacheRange(txbd, BdSize);
  1175. *)
  1176. CODE
  1177. DSB
  1178. END;
  1179. (* Transmit *)
  1180. Transmit;
  1181. IF intsEnabled THEN Machine.EnableInterrupts END;
  1182. IF Trace THEN KernelLog.String("Frame sent"); KernelLog.Ln END
  1183. END SendTestFrame;
  1184. PROCEDURE DumpDBMem(start: ADDRESS; count: LONGINT);
  1185. VAR
  1186. i: LONGINT;
  1187. BEGIN
  1188. FOR i := 0 TO count DO
  1189. KernelLog.Address(start); KernelLog.String(": ");
  1190. KernelLog.Address(SYSTEM.GET32(start)); KernelLog.String(" - ");
  1191. INC(start, 4);
  1192. KernelLog.Address(SYSTEM.GET32(start)); KernelLog.Ln;
  1193. INC(start, 4)
  1194. END;
  1195. END DumpDBMem;
  1196. BEGIN {ACTIVE}
  1197. (* Receive is done by polling *)
  1198. (*BEGIN {EXCLUSIVE}
  1199. AWAIT(start)
  1200. END;*)
  1201. LOOP
  1202. (*BEGIN {EXCLUSIVE}
  1203. IF kill THEN EXIT END
  1204. END;*)
  1205. IF lastRxQBar # SYSTEM.GET32(iobase + Rxqbase) THEN
  1206. ReceiveFrame
  1207. END
  1208. END
  1209. END Controller;
  1210. (** Phy subsystem of the controller. *)
  1211. Phy = OBJECT
  1212. VAR
  1213. iobase, phybase: ADDRESS;
  1214. linkSpeed: LONGINT;
  1215. timer: Kernel.Timer;
  1216. PROCEDURE & Setup * (iobase: ADDRESS);
  1217. BEGIN
  1218. SELF.iobase := iobase;
  1219. NEW(timer);
  1220. IF LinkSpeedMode = LinkSpeedAutodetect THEN
  1221. linkSpeed := GetIEEEPhySpeed();
  1222. IF linkSpeed = 1000 THEN
  1223. IF Trace THEN KernelLog.String("Autonegociated speed: 1000 MB/s"); KernelLog.Ln END;
  1224. SetUpSLCRDivisors(1000)
  1225. ELSIF linkSpeed = 100 THEN
  1226. IF Trace THEN KernelLog.String("Autonegociated speed: 100 MB/s"); KernelLog.Ln END;
  1227. SetUpSLCRDivisors(100)
  1228. ELSIF linkSpeed = 10 THEN
  1229. IF Trace THEN KernelLog.String("Autonegociated speed: 10 MB/s"); KernelLog.Ln END;
  1230. SetUpSLCRDivisors(10)
  1231. ELSE
  1232. IF Trace THEN KernelLog.String("Defaulting autonegociated speed to 10 MB/s"); KernelLog.Ln END;
  1233. SetUpSLCRDivisors(10)
  1234. END;
  1235. RETURN
  1236. ELSIF LinkSpeedMode = LinkSpeed1000 THEN
  1237. linkSpeed := 1000;
  1238. ELSIF LinkSpeedMode = LinkSpeed100 THEN
  1239. linkSpeed := 100;
  1240. ELSE
  1241. linkSpeed := 10;
  1242. END;
  1243. SetUpSLCRDivisors(linkSpeed);
  1244. ConfigureIEEEPhySpeed(linkSpeed);
  1245. timer.Sleep(1000)
  1246. END Setup;
  1247. PROCEDURE Detect (): ADDRESS;
  1248. VAR
  1249. status, phyReg: LONGINT;
  1250. phyAdr: ADDRESS;
  1251. BEGIN
  1252. IF Trace THEN KernelLog.String("XEmac: Detecting PHY"); KernelLog.Ln END;
  1253. phyAdr := 31;
  1254. WHILE phyAdr > 0 DO
  1255. status := Read(phyAdr, PhyDetectReg, phyReg);
  1256. IF (phyReg # 0FFFFH) & (SYSTEM.VAL(SET, phyReg) * PhyDetect = PhyDetect) THEN
  1257. IF Trace THEN KernelLog.String("Found PHY at "); KernelLog.Address(phyAdr); KernelLog.Ln END;
  1258. RETURN phyAdr
  1259. END;
  1260. DEC(phyAdr)
  1261. END;
  1262. IF Trace THEN KernelLog.String("PHY not found. Assuming its address is 0"); KernelLog.Ln END;
  1263. RETURN 0
  1264. END Detect;
  1265. PROCEDURE GetIEEEPhySpeed (): LONGINT;
  1266. VAR
  1267. temp, control, res, status, capabilities: LONGINT;
  1268. phyAdr: ADDRESS;
  1269. BEGIN
  1270. phyAdr := Detect();
  1271. IF Trace THEN KernelLog.String("Start PHY autonegociation"); KernelLog.Ln END;
  1272. res := Write(phyAdr, IeeePageAddressRegister, 2);
  1273. res := Read(phyAdr, IeeeControlRegMac, control);
  1274. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeRgmiiTxRxClockDelayed);
  1275. res := Write(phyAdr, IeeeControlRegMac, control);
  1276. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1277. res := Read(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1278. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeAsymmetricPause + IeeePause + Advertise100 + Advertise10);
  1279. res := Write(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1280. res := Read(phyAdr, Ieee1000AdvertiseReg, control);
  1281. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + Advertise1000);
  1282. res := Write(phyAdr, Ieee1000AdvertiseReg, control);
  1283. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1284. res := Read(phyAdr, IeeeCopperSpecificControlReg, control);
  1285. control := control + LSH(7, 12); (* Max number of gigabit attemps *)
  1286. INCL(SYSTEM.VAL(SET, control), 11); (* Enable dowshift *)
  1287. res := Write(phyAdr, IeeeCopperSpecificControlReg, control);
  1288. res := Read(phyAdr, IeeeControlReg, control);
  1289. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlAutonegotiateEnable);
  1290. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeStatAutonegotiateRestart);
  1291. res := Write(phyAdr, IeeeControlReg, control);
  1292. res := Read(phyAdr, IeeeControlReg, control);
  1293. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlReset);
  1294. res := Write(phyAdr, IeeeControlReg, control);
  1295. REPEAT
  1296. IF Trace THEN KernelLog.String("Waiting for PHY reset"); KernelLog.Ln END;
  1297. res := Read(phyAdr, IeeeControlReg, control)
  1298. UNTIL SYSTEM.VAL(SET, control) * IeeeCtrlReset = {};
  1299. IF Trace THEN KernelLog.String("Waiting for PHY to complete autonegotiation"); KernelLog.Ln END;
  1300. res := Read(phyAdr, IeeeStatusReg, status);
  1301. WHILE SYSTEM.VAL(SET, status) * IeeeStatAutonegotiateComplete = {} DO
  1302. timer.Sleep(1000);
  1303. res := Read(phyAdr, IeeeCopperSpecificStatusReg2, temp);
  1304. IF Trace & (SYSTEM.VAL(SET, temp) * IeeeAutonegError # {}) THEN
  1305. KernelLog.String("Autonegotiation error");
  1306. KernelLog.Ln
  1307. END;
  1308. res := Read(phyAdr, IeeeStatusReg, status)
  1309. END;
  1310. IF Trace THEN KernelLog.String("Autonegotiation complete"); KernelLog.Ln END;
  1311. res := Read(phyAdr, IeeeSpecificStatusReg, capabilities);
  1312. IF 15 IN SYSTEM.VAL(SET, capabilities) THEN
  1313. RETURN 1000 (* MB/s *)
  1314. ELSIF 14 IN SYSTEM.VAL(SET, capabilities) THEN
  1315. RETURN 100 (* MB/s *)
  1316. ELSE
  1317. RETURN 10 (* MB/s *)
  1318. END
  1319. END GetIEEEPhySpeed;
  1320. PROCEDURE ConfigureIEEEPhySpeed (speed: LONGINT);
  1321. VAR
  1322. control, res, wait: LONGINT;
  1323. phyAdr: ADDRESS;
  1324. BEGIN
  1325. phyAdr := Detect();
  1326. res := Write(phyAdr, IeeePageAddressRegister, 2);
  1327. res := Read(phyAdr, IeeeControlRegMac, control);
  1328. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeRgmiiTxRxClockDelayed);
  1329. res := Write(phyAdr, IeeeControlRegMac, control);
  1330. res := Write(phyAdr, IeeePageAddressRegister, 0);
  1331. res := Read(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1332. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeAsymmetricPause);
  1333. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeePause);
  1334. res := Write(phyAdr, IeeeAutonegoAdvertiseReg, control);
  1335. res := Read(phyAdr, IeeeControlReg, control);
  1336. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) * (-IeeeCtrlLinkSpeed1000M) * (-IeeeCtrlLinkSpeed100M) * (-IeeeCtrlLinkSpeed10M));
  1337. IF linkSpeed = 1000 THEN
  1338. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed1000M)
  1339. ELSIF linkSpeed = 100 THEN
  1340. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed100M)
  1341. (* Don't advertise PHY speed of 1000 MBPS *)
  1342. ELSIF linkSpeed = 10 THEN
  1343. control := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, control) + IeeeCtrlLinkSpeed10M)
  1344. END;
  1345. END ConfigureIEEEPhySpeed;
  1346. PROCEDURE SetUpSLCRDivisors (div: LONGINT);
  1347. END SetUpSLCRDivisors;
  1348. PROCEDURE Write (address, register: ADDRESS; data: LONGINT): LONGINT;
  1349. VAR
  1350. reg, mgtcr, ipisr: SET;
  1351. BEGIN
  1352. IF Trace THEN KernelLog.String("PHY write"); KernelLog.Ln END;
  1353. SYSTEM.GET(iobase + Nwsr, reg);
  1354. (* Make sure no other PHY operation is currently in progress *)
  1355. IF ~(NwsrMdioIdle IN reg) THEN
  1356. IF Trace THEN KernelLog.String("XEmac Phy write aborted: PHY busy"); KernelLog.Ln END;
  1357. RETURN EmacMiiBusy
  1358. END;
  1359. (* Construct Mgtcr mask for the operation *)
  1360. mgtcr := PhyMntncOp + PhyMntncOpW + SYSTEM.VAL(SET, LSH(phybase, PhyMntncPhyAdShift))
  1361. + SYSTEM.VAL(SET, LSH(address, PhyMntncPhyAdShift))
  1362. + SYSTEM.VAL(SET, LSH(register, PhyMntncPhRegShift)) + SYSTEM.VAL(SET,data);
  1363. SYSTEM.PUT(iobase + PhyMntnc, mgtcr);
  1364. REPEAT
  1365. SYSTEM.GET(iobase + Nwsr, ipisr)
  1366. UNTIL NwsrMdioIdle IN ipisr;
  1367. RETURN Success
  1368. END Write;
  1369. PROCEDURE Read (address, register: ADDRESS; VAR data: LONGINT): LONGINT;
  1370. VAR
  1371. reg, ipisr, mgtcr: SET;
  1372. BEGIN
  1373. SYSTEM.GET(iobase + Nwsr, reg);
  1374. IF ~(NwsrMdioIdle IN reg) THEN
  1375. IF Trace THEN KernelLog.String("XEmac Phy read aborted: PHY busy"); KernelLog.Ln END;
  1376. RETURN EmacMiiBusy
  1377. END;
  1378. mgtcr := PhyMntncOp + PhyMntncOpR
  1379. + SYSTEM.VAL(SET, LSH(address, PhyMntncPhyAdShift))
  1380. + SYSTEM.VAL(SET, LSH(register, PhyMntncPhRegShift));
  1381. SYSTEM.PUT(iobase + PhyMntnc, mgtcr);
  1382. REPEAT
  1383. SYSTEM.GET(iobase + Nwsr, ipisr)
  1384. UNTIL NwsrMdioIdle IN ipisr;
  1385. data := SYSTEM.GET32(iobase + PhyMntnc) MOD 10000H;
  1386. RETURN Success
  1387. END Read;
  1388. END Phy;
  1389. VAR
  1390. ld: LinkDevice;
  1391. res: LONGINT;
  1392. BEGIN
  1393. NEW(ld, Network.TypeEthernet, 1500, 6); (*! What is the correct MTU? *)
  1394. ld.SetName("XEmac");
  1395. Network.registry.Add(ld, res);
  1396. NEW(ld.ctrl, ADDRESS(0E000B000H), ld);
  1397. END XEmac.