Intel8255x.Mod 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. MODULE Intel8255x;
  2. (*
  3. Aos driver for Intel 8255x Ethernet Controllers
  4. Reference: Intel, "Intel 8255x 10/100 Mbps Ethernet Controller Family, Open Source Software Developer Manual,
  5. Revision 1.0, January 2003"
  6. *)
  7. IMPORT SYSTEM, Kernel, Machine, PCI, Objects, Modules, Plugins, Network, KernelLog;
  8. CONST
  9. Name = "Intel8255x#";
  10. Desc = "Intel 8255x Ethernet Driver";
  11. K = 1024;
  12. MaxETHFrameSize = 1514;
  13. RxRingSize = 100;
  14. TxRingSize = 100;
  15. MaxTxTrials = 5;
  16. SizeOfConfigCmdHdr = 32;
  17. SizeOfNOPCmdHdr = 8;
  18. SizeOfIASetupCmdHdr = 16;
  19. SizeOfTxCmdHdr = 16;
  20. SizeOfRFDHdr = 16;
  21. keepMasks = TRUE;
  22. (* device registers *)
  23. SCBStatus = 0H;
  24. SCBCommand = 2H;
  25. SCBGenPtr = 4H;
  26. SCBEeprom = 0EH;
  27. PORTReg = 8H;
  28. (* ack bits *)
  29. CX = {15};
  30. FR = {14};
  31. CNA = {13};
  32. RNR = {12};
  33. MDI = {11};
  34. SWI = {10};
  35. (* interrupt masks *)
  36. CXMask = {31};
  37. FRMask = {30};
  38. CNAMask = {29};
  39. RNRMask = {28};
  40. ERMask = {27};
  41. FCPMask = {26};
  42. MaskAllIntr = {24};
  43. UnMaskAllIntr = {};
  44. (* generate software interrupt *)
  45. SI = {25};
  46. (* CU Commands *)
  47. CUNop = {};
  48. CUStart = {20};
  49. CUResume = {21};
  50. CULoadBase = {21, 22};
  51. (* RU Commands *)
  52. RUNop = {};
  53. RUStart = {16};
  54. RUResume = {17};
  55. RUAbort = {18};
  56. RULoadBase = {17, 18};
  57. (* CU States *)
  58. CUIdle = {};
  59. CUSuspended = {6};
  60. (* RU States *)
  61. RUIdle = {};
  62. RUSuspended = {2};
  63. RUReady = {4};
  64. (* PORT Selection Function *)
  65. Reset = {};
  66. SelectiveReset = {1};
  67. (* Action Command Opcodes in Control Block List (CBL) *)
  68. ActionCmdNOP = {};
  69. ActionCmdIASetup = {16};
  70. ActionCmdConfig = {17};
  71. ActionCmdTx = {18};
  72. (* More Command Bits in CBL *)
  73. LastBlock = {31}; (* EL Bit *)
  74. Suspend = {30}; (* S Bit *)
  75. Interrupt = {29}; (* I Bit *)
  76. VAR
  77. nCUWaitActive: LONGINT;
  78. TYPE
  79. ByteField = POINTER TO ARRAY OF CHAR;
  80. DataBlock = POINTER TO RECORD
  81. next: DataBlock;
  82. size: LONGINT;
  83. data: ByteField;
  84. END;
  85. LinkDevice = OBJECT(Network.LinkDevice)
  86. VAR
  87. ctrl: Controller;
  88. txTrials: LONGINT;
  89. (*
  90. send a frame
  91. padding and checksum are inserted directly by the device
  92. *)
  93. PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  94. CONST
  95. DataOfs = 10H; (* data block offset in transmit command block *)
  96. C = 15;
  97. VAR
  98. actAdr, prevAdr: ADDRESS; txLen, i: LONGINT;
  99. byteCount, EOF, TxThreshold, state, cmdHdr, sendStatus: SET;
  100. BEGIN {EXCLUSIVE}
  101. (* if C Bit in next TxCmd Block is not set, the transmit command has not yet finished processing all bytes
  102. => buffer overflow (wait)
  103. *)
  104. ctrl.ExecCmd(MaskAllIntr, ~keepMasks);
  105. REPEAT
  106. sendStatus := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(ctrl.actTxCmd.next.data[0])));
  107. UNTIL (C IN sendStatus);
  108. txLen := 14 + h3len + h4len + dlen; (* number of bytes to transmit *)
  109. prevAdr := ADDRESSOF(ctrl.actTxCmd.data[0]);
  110. ctrl.actTxCmd := ctrl.actTxCmd.next;
  111. actAdr := ADDRESSOF(ctrl.actTxCmd.data[0]);
  112. (* setup cmd hdr *)
  113. SYSTEM.PUT32(actAdr, Suspend + ActionCmdTx);
  114. (* in simplified mode the TBD array address should be set to all ones *)
  115. SYSTEM.PUT32(actAdr + 08H, 0FFFFFFFFH);
  116. (* set TxThreshold, EOF Bit, Tx Command Block Byte Count *)
  117. byteCount := SYSTEM.VAL(SET, txLen) * {0..13};
  118. EOF := {15};
  119. TxThreshold := {16};
  120. SYSTEM.PUT32(actAdr + 0CH, byteCount + EOF + TxThreshold);
  121. (* set data field *)
  122. SYSTEM.MOVE(ADDRESSOF(dst[0]), actAdr + DataOfs, 6); (* the first 6 bytes of data field are dst address *)
  123. SYSTEM.MOVE(ADDRESSOF(local[0]), actAdr + DataOfs + 6, 6);
  124. SYSTEM.PUT16(actAdr + DataOfs + 12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
  125. i := 14;
  126. IF h3len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), actAdr + DataOfs + i, h3len); INC(i, h3len) END;
  127. IF h4len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), actAdr + DataOfs + i, h4len); INC(i, h4len) END;
  128. IF i+dlen < MaxETHFrameSize THEN
  129. SYSTEM.MOVE(ADDRESSOF(data[0])+dofs, actAdr + DataOfs + i, dlen);
  130. INC(i, dlen);
  131. END;
  132. (* delete Suspended Bit from previous TxCmd *)
  133. state := ctrl.GetCUState();
  134. WHILE (state # CUIdle) & (state # CUSuspended) DO
  135. Machine.AtomicInc(nCUWaitActive);
  136. state := ctrl.GetCUState();
  137. END;
  138. cmdHdr := SYSTEM.VAL(SET, SYSTEM.GET32(prevAdr)) - Suspend;
  139. SYSTEM.PUT32(prevAdr, cmdHdr);
  140. state := ctrl.GetCUState();
  141. IF state = CUIdle THEN
  142. actAdr := Machine.PhysicalAdr(actAdr, ctrl.actTxCmd.size);
  143. ctrl.WriteSCBGenPtr(Machine.Ensure32BitAddress (actAdr));
  144. ctrl.ExecCmd(CUStart, keepMasks);
  145. ELSIF state = CUSuspended THEN
  146. ctrl.ExecCmd(CUResume, keepMasks);
  147. END;
  148. INC(sendCount);
  149. ctrl.ExecCmd(UnMaskAllIntr, ~keepMasks);
  150. (* ctrl.ExecCmd(CXMask + CNAMask + ERMask, ~keepMasks); *)
  151. END DoSend;
  152. PROCEDURE ReceiveData(VAR data: ARRAY OF CHAR; ofs, size: LONGINT);
  153. BEGIN
  154. ASSERT(size <= ctrl.rcvSize); (* enough data left *)
  155. ASSERT((size >= 0) & (ofs+size <= LEN(data))); (* index check *)
  156. SYSTEM.MOVE(ctrl.rcvAdr, ADDRESSOF(data[ofs]), size);
  157. INC(ctrl.rcvAdr, size);
  158. DEC(ctrl.rcvSize, size);
  159. END ReceiveData;
  160. PROCEDURE Finalize(connected: BOOLEAN);
  161. BEGIN
  162. ctrl.Finalize;
  163. Finalize^(connected);
  164. END Finalize;
  165. END LinkDevice;
  166. Controller = OBJECT
  167. VAR
  168. next: Controller;
  169. base: ADDRESS; irq: LONGINT;
  170. dev: LinkDevice;
  171. actRFD, lastRFD: DataBlock;
  172. actTxCmd: DataBlock;
  173. rcvAdr, rcvSize: LONGINT;
  174. PROCEDURE &Init*(dev: LinkDevice; base: ADDRESS; irq: LONGINT);
  175. VAR res: WORD; i: LONGINT;
  176. configCmd, iASetupCmd: DataBlock;
  177. BEGIN
  178. SELF.next := installedControllers; installedControllers := SELF;
  179. SELF.base := base;
  180. SELF.irq := irq;
  181. SELF.dev := dev;
  182. dev.ctrl := SELF;
  183. (* set Ethernet Broadcast Address *)
  184. FOR i := 0 TO 5 DO
  185. dev.broadcast[i] := 0FFX;
  186. END;
  187. WritePORT(Reset); Delay(1);
  188. ExecCmd(MaskAllIntr, ~keepMasks); (* mask all interrupts, do not keep any old masks *)
  189. WriteSCBGenPtr(0);
  190. ExecCmd(CULoadBase, keepMasks); (* set CU base, keeping all interrupt masks *)
  191. WriteSCBGenPtr(0);
  192. ExecCmd(RULoadBase, keepMasks); (* set RU base, keeping all interrupt masks *)
  193. (* configure the device *)
  194. MakeBlock(configCmd, SizeOfConfigCmdHdr);
  195. SetCmdHdr(LastBlock + ActionCmdConfig, configCmd);
  196. SetByteMap8255x(configCmd);
  197. StartActionCmd(configCmd);
  198. (* load the device with the individual address (MAC address) *)
  199. MakeBlock(iASetupCmd, SizeOfIASetupCmdHdr);
  200. SetCmdHdr(LastBlock + ActionCmdIASetup, iASetupCmd);
  201. SetMACAddress(iASetupCmd);
  202. StartActionCmd(iASetupCmd);
  203. SetupRxRing();
  204. StartRxUnit();
  205. SetupTxRing();
  206. (* install interrupt handler *)
  207. Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+irq);
  208. (* mask interrupts *)
  209. (* ExecCmd(UnMaskAllIntr, ~keepMasks); *)
  210. ExecCmd(CXMask + CNAMask + ERMask, ~keepMasks);
  211. (* register with Network *)
  212. Network.registry.Add(dev, res); ASSERT(res = Plugins.Ok);
  213. INC(installed);
  214. KernelLog.Enter; KernelLog.String(dev.name); KernelLog.String(" "); Network.OutLinkAdr(dev.local, 6); KernelLog.Exit;
  215. END Init;
  216. (*
  217. setup the IASetup Command and put the MAC in dev.local
  218. if the MAC address is aabbccddeeffH:
  219. dev.local[0] is aa
  220. dev.local[1] is bb
  221. dev.local[2] is cc
  222. etc.
  223. *)
  224. PROCEDURE SetMACAddress(VAR cmd: DataBlock);
  225. CONST
  226. MacAdrBase = 0;
  227. VAR reg, i: INTEGER;
  228. BEGIN
  229. (* read permanent MAC address *)
  230. FOR i := 0 TO 2 DO
  231. ReadEEPROM(MacAdrBase + i, reg); (* EEPROM registers are 2 bytes *)
  232. SYSTEM.PUT16(ADDRESSOF(dev.local[2*i]), reg); (* put MAC in dev.local *)
  233. SYSTEM.PUT16(ADDRESSOF(cmd.data[8 + 2*i]), reg); (* put MAC in Action Command Block *)
  234. END;
  235. END SetMACAddress;
  236. PROCEDURE SetByteMap8255x(VAR cmd: DataBlock);
  237. VAR
  238. byteArray: ARRAY 22 OF CHAR;
  239. PROCEDURE ToChar(s: SET): CHAR;
  240. BEGIN
  241. RETURN SYSTEM.VAL(CHAR, SHORT(SHORT(SYSTEM.VAL(LONGINT, s))));
  242. END ToChar;
  243. BEGIN
  244. byteArray[0] := 16X;
  245. byteArray[1] := 8X;
  246. byteArray[2] := 00X;
  247. byteArray[3] := 00X; (* MWI disable *)
  248. byteArray[4] := 00X;
  249. byteArray[5] := 00X;
  250. byteArray[6] := ToChar({5, 4, 1});
  251. byteArray[7] := ToChar({1, 0}); (* discard short frames (frames < 64 bytes) *)
  252. byteArray[8] := 01X;
  253. byteArray[9] := 00X;
  254. byteArray[10] := ToChar({5, 3, 2, 1}); (* NO src adr insertion (from internal dev IA) *)
  255. byteArray[11] := 00X;
  256. byteArray[12] := ToChar({6, 5, 0});
  257. byteArray[13] := 00X; (* default *)
  258. byteArray[14] := 0F2X; (* default *)
  259. byteArray[15] := ToChar({3});
  260. byteArray[16] := 00X;
  261. byteArray[17] := ToChar({6}); (* for compatibility reason *)
  262. byteArray[18] := ToChar({7, 6, 5, 4, 1}); (* enable padding *)
  263. byteArray[19] := ToChar({7});
  264. byteArray[20] := ToChar({0..5}); (* prio field in byte #31 in flow control frame *)
  265. byteArray[21] := ToChar({2, 0});
  266. SYSTEM.MOVE(ADDRESSOF(byteArray[0]), ADDRESSOF(cmd.data[0]) + 08H, 22);
  267. END SetByteMap8255x;
  268. PROCEDURE SetupTxRing;
  269. VAR
  270. r: LONGINT;
  271. adr, physAdr: ADDRESS;
  272. txCmd, prev: DataBlock;
  273. BEGIN
  274. FOR r := 0 TO TxRingSize - 1 DO
  275. MakeBlock(txCmd, SizeOfTxCmdHdr + MaxETHFrameSize);
  276. adr := ADDRESSOF(txCmd.data[0]);
  277. SYSTEM.PUT32(adr, {15}); (* set C Bit for LinkDevice.Send => no C Bit means Send Buffer Overflow *)
  278. IF prev # NIL THEN
  279. prev.next := txCmd;
  280. physAdr := Machine.PhysicalAdr(adr, txCmd.size); ASSERT(physAdr # Machine.NilAdr);
  281. SYSTEM.PUT32(ADDRESSOF(prev.data[0]) + 04H, physAdr); (* set link address to physical address *)
  282. ELSE
  283. actTxCmd := txCmd; (* set first TxCmd *)
  284. END;
  285. prev := txCmd;
  286. END;
  287. (* link last TxCmd to first TxCmd *)
  288. txCmd.next := actTxCmd;
  289. physAdr := Machine.PhysicalAdr(ADDRESSOF(actTxCmd.data[0]), actTxCmd.size);
  290. ASSERT(physAdr # Machine.NilAdr);
  291. adr := ADDRESSOF(txCmd.data[0]);
  292. SYSTEM.PUT32(adr + 04H, Machine.Ensure32BitAddress (physAdr));
  293. END SetupTxRing;
  294. PROCEDURE SetupRxRing;
  295. VAR
  296. r: LONGINT;
  297. adr, physAdr: ADDRESS;
  298. rxFrame, prev: DataBlock;
  299. BEGIN
  300. FOR r := 0 TO RxRingSize - 1 DO
  301. MakeBlock(rxFrame, SizeOfRFDHdr + MaxETHFrameSize);
  302. (* configure RFD *)
  303. adr := ADDRESSOF(rxFrame.data[0]);
  304. SYSTEM.PUT32(adr, 0);
  305. SYSTEM.PUT32(adr + 0CH, 0);
  306. SYSTEM.PUT16(adr + 0CH + 2H, SHORT(rxFrame.size));
  307. IF prev # NIL THEN
  308. prev.next := rxFrame;
  309. physAdr := Machine.PhysicalAdr(adr, rxFrame.size); ASSERT(physAdr # Machine.NilAdr);
  310. SYSTEM.PUT32(ADDRESSOF(prev.data[0]) + 4H, physAdr); (* set link address to physical address *)
  311. ELSE
  312. actRFD := rxFrame; (* set first RFD *)
  313. END;
  314. prev := rxFrame;
  315. END;
  316. lastRFD := rxFrame;
  317. (* link last RFD TO first RFD *)
  318. lastRFD.next := actRFD;
  319. physAdr := Machine.PhysicalAdr(ADDRESSOF(actRFD.data[0]), actRFD.size); ASSERT(physAdr # Machine.NilAdr);
  320. adr := ADDRESSOF(lastRFD.data[0]);
  321. SYSTEM.PUT32(adr + 4H, Machine.Ensure32BitAddress (physAdr));
  322. SYSTEM.PUT32(adr, Suspend); (* after having received the last block, suspend reception of further frames *)
  323. END SetupRxRing;
  324. PROCEDURE StartRxUnit;
  325. VAR
  326. adr: ADDRESS;
  327. BEGIN
  328. adr := Machine.PhysicalAdr(ADDRESSOF(actRFD.data[0]), actRFD.size); ASSERT(adr # Machine.NilAdr);
  329. WriteSCBGenPtr(Machine.Ensure32BitAddress (adr));
  330. ASSERT(GetRUState() # RUReady);
  331. ExecCmd(RUStart, keepMasks);
  332. END StartRxUnit;
  333. PROCEDURE SetCmdHdr(bits: SET; VAR cmd: DataBlock);
  334. BEGIN
  335. SYSTEM.PUT32(ADDRESSOF(cmd.data[0]), bits * {16..31}); (* set status word bits to 0 *)
  336. END SetCmdHdr;
  337. PROCEDURE MakeBlock(VAR cmd: DataBlock; dataSize: LONGINT);
  338. BEGIN
  339. NEW(cmd);
  340. cmd.size := dataSize;
  341. NEW(cmd.data, cmd.size);
  342. END MakeBlock;
  343. PROCEDURE AckIntr(interrupts: SET);
  344. BEGIN
  345. SYSTEM.PUT16(base + SCBStatus, SHORT(SYSTEM.VAL(LONGINT, interrupts)));
  346. END AckIntr;
  347. PROCEDURE GetStatus():SET;
  348. BEGIN
  349. RETURN SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + SCBStatus)));
  350. END GetStatus;
  351. PROCEDURE GetCUState(): SET;
  352. BEGIN
  353. RETURN GetStatus() * {6, 7};
  354. END GetCUState;
  355. PROCEDURE GetRUState(): SET;
  356. BEGIN
  357. RETURN GetStatus() * {2..5};
  358. END GetRUState;
  359. (*
  360. set the SCB command word
  361. keep indicates if interrupt masks of upper byte are deleted
  362. *)
  363. PROCEDURE ExecCmd(cmd: SET; keep: BOOLEAN);
  364. VAR masks: SET;
  365. BEGIN
  366. cmd := cmd * {16..31}; (* delete status part of cmd *)
  367. IF keep THEN
  368. masks := SYSTEM.VAL(SET, SYSTEM.GET32(base + SCBStatus)); (* get interrupt masks *)
  369. masks := masks * {24..31}; (* delete all but the mask bits *)
  370. cmd := cmd + masks; (* merge cmd with interrupt mask *)
  371. END;
  372. SYSTEM.PUT32(base + SCBStatus, cmd); (* writing zeros to status word has no effect *)
  373. WHILE (SYSTEM.GET8(base + SCBCommand) # 0) DO END; (* wait for command done *)
  374. END ExecCmd;
  375. PROCEDURE WaitForActionCmd(VAR cmd: DataBlock);
  376. CONST
  377. C = 15;
  378. OK = 13;
  379. SecsToWait = 10;
  380. VAR
  381. t: Kernel.MilliTimer;
  382. status: SET;
  383. BEGIN
  384. (* check command completion *)
  385. status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
  386. Kernel.SetTimer(t, SecsToWait * 1000);
  387. WHILE ~(C IN status) & ~Kernel.Expired(t) DO
  388. status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
  389. END;
  390. ASSERT(C IN status);
  391. (* check command ok *)
  392. status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
  393. Kernel.SetTimer(t, SecsToWait * 1000);
  394. WHILE ~(OK IN status) & ~Kernel.Expired(t) DO
  395. status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
  396. END;
  397. ASSERT(OK IN status);
  398. END WaitForActionCmd;
  399. PROCEDURE ContainsRxData(VAR rxFrame: DataBlock): BOOLEAN;
  400. CONST
  401. C = 15;
  402. OK = 13;
  403. EOF = 15;
  404. VAR
  405. adr: ADDRESS;
  406. status: SET;
  407. BEGIN
  408. adr := ADDRESSOF(rxFrame.data[0]);
  409. status := SYSTEM.VAL(SET, SYSTEM.GET32(adr));
  410. IF (C IN status) & (OK IN status) THEN
  411. RETURN EOF IN SYSTEM.VAL(SET, SYSTEM.GET32(adr + 0CH)); (* data placing completed ? *)
  412. END;
  413. RETURN FALSE;
  414. END ContainsRxData;
  415. PROCEDURE StartActionCmd(VAR cmd: DataBlock);
  416. CONST
  417. ActiveState = 7;
  418. VAR
  419. adr: ADDRESS;
  420. BEGIN
  421. adr := Machine.PhysicalAdr(ADDRESSOF(cmd.data[0]), cmd.size); ASSERT(adr # Machine.NilAdr);
  422. WriteSCBGenPtr(Machine.Ensure32BitAddress (adr));
  423. ASSERT(~(ActiveState IN GetStatus())); (* CU must not be in active state *)
  424. ExecCmd(CUStart, keepMasks);
  425. WaitForActionCmd(cmd); (* todo: if we know the last cmd, then check for cmd done BEFORE execCmd *)
  426. END StartActionCmd;
  427. PROCEDURE WritePORT(p: SET);
  428. BEGIN
  429. SYSTEM.PUT32(base + PORTReg, p);
  430. END WritePORT;
  431. PROCEDURE WriteSCBGenPtr(val: LONGINT);
  432. BEGIN
  433. SYSTEM.PUT32(base + SCBGenPtr, val);
  434. END WriteSCBGenPtr;
  435. PROCEDURE ReadEEPROM(reg: INTEGER; VAR res: INTEGER);
  436. CONST
  437. EESK = 0;
  438. EECS = 1;
  439. EEDI = 2;
  440. EEDO = 3;
  441. ReadOpcode = 6;
  442. VAR
  443. x: SET;
  444. bits: INTEGER;
  445. PROCEDURE RaiseClk(VAR x: SET);
  446. VAR dummy: LONGINT;
  447. BEGIN
  448. INCL(x, EESK);
  449. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  450. dummy := SYSTEM.GET16(base + SCBStatus);
  451. Delay(1);
  452. END RaiseClk;
  453. PROCEDURE LowerClk(VAR x: SET);
  454. VAR dummy: LONGINT;
  455. BEGIN
  456. EXCL(x, EESK);
  457. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  458. dummy := SYSTEM.GET16(base + SCBStatus);
  459. Delay(1);
  460. END LowerClk;
  461. PROCEDURE ShiftOutBits(data, count: INTEGER);
  462. VAR
  463. mask: INTEGER;
  464. x: SET;
  465. dummy: LONGINT;
  466. BEGIN
  467. mask := LSH(1, count-1);
  468. x := GetEEPROMReg();
  469. EXCL(x, EEDO); EXCL(x, EEDI);
  470. REPEAT
  471. EXCL(x, EEDI);
  472. IF (SYSTEM.VAL(SET, LONG(data)) * SYSTEM.VAL(SET, LONG(mask)) # {}) THEN
  473. INCL(x, EEDI);
  474. END;
  475. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  476. dummy := SYSTEM.GET16(base + SCBStatus);
  477. Delay(1);
  478. RaiseClk(x);
  479. LowerClk(x);
  480. mask := LSH(mask, -1);
  481. UNTIL mask = 0;
  482. EXCL(x, EEDI);
  483. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  484. END ShiftOutBits;
  485. PROCEDURE ShiftInBits(): INTEGER;
  486. VAR
  487. x: SET;
  488. d, i: INTEGER;
  489. BEGIN
  490. x := GetEEPROMReg();
  491. EXCL(x, EEDO); EXCL(x, EEDI);
  492. d := 0;
  493. FOR i := 0 TO 15 DO
  494. d := LSH(d, 1);
  495. RaiseClk(x);
  496. x := GetEEPROMReg();
  497. EXCL(x, EEDI);
  498. IF (EEDO IN x) & (~ODD(d)) THEN
  499. d := d + 1;
  500. END;
  501. LowerClk(x);
  502. END;
  503. RETURN d;
  504. END ShiftInBits;
  505. PROCEDURE GetEEPROMReg(): SET;
  506. BEGIN
  507. RETURN SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + SCBEeprom)));
  508. END GetEEPROMReg;
  509. (*
  510. returns number of bits in eeprom address
  511. typically 6 or 8 bits according to eeprom size of 64 or 256 registers
  512. *)
  513. PROCEDURE GetEEPROMAdrSize(): INTEGER;
  514. VAR
  515. x: SET;
  516. size: INTEGER;
  517. dummy: LONGINT;
  518. err: BOOLEAN;
  519. BEGIN
  520. err := FALSE;
  521. (* enable eeprom by setting EECS *)
  522. x := GetEEPROMReg();
  523. EXCL(x, EEDI); EXCL(x, EEDO); EXCL(x, EESK);
  524. INCL(x, EECS);
  525. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  526. ShiftOutBits(ReadOpcode, 3); (* opcodes are 3 bits *)
  527. x := GetEEPROMReg();
  528. REPEAT
  529. INC(size);
  530. INCL(x, EEDO);
  531. EXCL(x, EEDI);
  532. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  533. dummy := SYSTEM.GET16(base + SCBStatus);
  534. Delay(1);
  535. RaiseClk(x);
  536. LowerClk(x);
  537. IF size > 8 THEN (* max address size is 8 bits *)
  538. size := 0;
  539. err := TRUE;
  540. END;
  541. x := GetEEPROMReg();
  542. UNTIL ~(EEDO IN x) OR err;
  543. dummy := ShiftInBits();
  544. CleanupEEPROM();
  545. RETURN size;
  546. END GetEEPROMAdrSize;
  547. PROCEDURE CleanupEEPROM;
  548. VAR x: SET;
  549. BEGIN
  550. x := GetEEPROMReg();
  551. EXCL(x, EECS); EXCL(x, EEDI);
  552. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  553. RaiseClk(x);
  554. LowerClk(x);
  555. END CleanupEEPROM;
  556. BEGIN
  557. bits := GetEEPROMAdrSize();
  558. x := GetEEPROMReg();
  559. EXCL(x, EEDI); EXCL(x, EEDO); EXCL(x, EESK);
  560. INCL(x, EECS);
  561. SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
  562. ShiftOutBits(ReadOpcode, 3); (* opcodes are 3 bits *)
  563. ShiftOutBits(reg, bits);
  564. res := ShiftInBits();
  565. CleanupEEPROM();
  566. END ReadEEPROM;
  567. PROCEDURE HandleInterrupt;
  568. VAR
  569. status, ack: SET;
  570. BEGIN
  571. status := GetStatus();
  572. ack := {};
  573. IF IsIn(CX, status) THEN
  574. (* this interrupt indicates that the CU finished executing a command *)
  575. ack := ack + CX;
  576. END;
  577. IF IsIn(FR, status) THEN
  578. (* this interrupt indicates that the RU has finished receiving a frame *)
  579. ack := ack + FR;
  580. ReadFrame();
  581. END;
  582. IF IsIn(CNA, status) THEN
  583. (* this interrupt indicates that the CU has left the active state or has entered the idle state *)
  584. ack := ack + CNA;
  585. END;
  586. IF IsIn(RNR, status) THEN
  587. (* this interrupt indicates that the RU leaves the ready state -> no more place in the RxRing !!! *)
  588. KernelLog.String("Intel8255x: RNR Interrupt: RxRing too small."); KernelLog.Ln;
  589. ack := ack + RNR;
  590. END;
  591. IF IsIn(MDI, status) THEN
  592. (* this interrupt indicates when an MDI read or write cycle has completed *)
  593. ack := ack + MDI;
  594. END;
  595. IF IsIn(SWI, status) THEN
  596. (* used for software generated interrupts *)
  597. ack := ack + SWI;
  598. END;
  599. AckIntr(ack);
  600. END HandleInterrupt;
  601. PROCEDURE IncLastRFD;
  602. VAR
  603. prevStatus: SET;
  604. prevAdr, adr: ADDRESS;
  605. BEGIN
  606. prevAdr := ADDRESSOF(lastRFD.data[0]);
  607. lastRFD := lastRFD.next;
  608. adr := ADDRESSOF(lastRFD.data[0]);
  609. SYSTEM.PUT32(adr, Suspend); (* set Suspend Bit *)
  610. SYSTEM.PUT32(adr + 0CH, 0); (* delete EOF Bit *)
  611. SYSTEM.PUT16(adr + 0CH + 2H, SHORT(lastRFD.size));
  612. prevStatus := SYSTEM.VAL(SET, SYSTEM.GET32(prevAdr));
  613. SYSTEM.PUT32(prevAdr, prevStatus * {0..29, 31}); (* delete Suspend Bit (30) in previous RFD *)
  614. IF GetRUState() = RUSuspended THEN
  615. ExecCmd(RUResume, keepMasks);
  616. END;
  617. END IncLastRFD;
  618. PROCEDURE ReadFrame;
  619. CONST
  620. DataOfs = 10H; (* receive buffer offset *)
  621. VAR
  622. frameAdr: ADDRESS; type, actualCount: LONGINT;
  623. srcAdr (* , dstAdr *) : Network.LinkAdr;
  624. (* handler: Network.Receiver; *)
  625. buf: Network.Buffer;
  626. BEGIN
  627. WHILE ContainsRxData(actRFD) DO
  628. frameAdr := ADDRESSOF(actRFD.data[0]);
  629. actualCount := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.GET32(frameAdr + 0CH)) * {0..13});
  630. (*SYSTEM.MOVE(frameAdr + DataOfs, ADDRESSOF(dstAdr), 6);*)
  631. SYSTEM.MOVE(frameAdr + DataOfs + 6, ADDRESSOF(srcAdr), 6);
  632. type := Network.GetNet2(actRFD.data^, DataOfs + 12); (* Endianess ! *)
  633. (*
  634. dev.GetReceiver(type, handler, hSize);
  635. rcvAdr := frameAdr + DataOfs + 14 + hSize;
  636. rcvSize := actualCount - 14 - hSize;
  637. INC(dev.recvCount);
  638. handler(dev, SYSTEM.VAL(Network.RecvHdr, actRFD.data[DataOfs + 14]), actualCount - 14, type, srcAdr);
  639. *)
  640. buf := Network.GetNewBuffer();
  641. IF buf # NIL THEN
  642. buf.ofs := 0;
  643. buf.len := actualCount - 14;
  644. buf.src := srcAdr;
  645. Network.Copy(actRFD.data^, buf.data, DataOfs + 14, 0, actualCount - 14);
  646. dev.QueueBuffer(buf, type);
  647. END;
  648. (* delete C, OK and EOF Bits in RFD *)
  649. SYSTEM.PUT32(frameAdr, 0);
  650. SYSTEM.PUT16(frameAdr + 0CH, 0);
  651. actRFD := actRFD.next;
  652. IncLastRFD();
  653. END;
  654. END ReadFrame;
  655. PROCEDURE Finalize;
  656. BEGIN
  657. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0 + irq);
  658. Network.registry.Remove(dev);
  659. dev.ctrl := NIL;
  660. dev := NIL;
  661. END Finalize;
  662. END Controller;
  663. VAR
  664. installedControllers: Controller;
  665. installed: LONGINT;
  666. PROCEDURE Install*;
  667. BEGIN {EXCLUSIVE}
  668. IF installed = 0 THEN
  669. ScanPCI(8086H, 2449H);
  670. ScanPCI(8086H, 1029H); (* 82559 Ethernet Controller *)
  671. ScanPCI(8086H, 1031H); (* ICH3 *)
  672. ScanPCI(8086H, 1032H);
  673. ScanPCI(8086H, 1033H);
  674. ScanPCI(8086H, 1034H); (* Reserved *)
  675. ScanPCI(8086H, 1035H);
  676. ScanPCI(8086H, 1036H); (* Reserved *)
  677. ScanPCI(8086H, 1037H); (* Reserved *)
  678. ScanPCI(8086H, 1038H); (* Reserved *)
  679. ScanPCI(8086H, 103DH); (* In VAIO *)
  680. ScanPCI(8086H, 1064H); (* 82562ET/EZ/GT/GZ - Pro/100 VE (LOM) *)
  681. ScanPCI(8086H, 1209H); (* 82559ER *)
  682. ScanPCI(8086H, 1229H); (* Ethernet Pro 100 *)
  683. END;
  684. END Install;
  685. PROCEDURE Remove*;
  686. VAR table: Plugins.Table; i: LONGINT;
  687. BEGIN {EXCLUSIVE}
  688. Network.registry.GetAll(table);
  689. IF table # NIL THEN
  690. FOR i := 0 TO LEN(table)-1 DO
  691. IF table[i] IS LinkDevice THEN table[i](LinkDevice).Finalize(TRUE) END
  692. END
  693. END;
  694. installed := 0;
  695. END Remove;
  696. PROCEDURE ScanPCI(vendor, device: LONGINT);
  697. VAR
  698. index, bus, dev, fct, irq, i: LONGINT; res: WORD;
  699. base: ADDRESS;
  700. d: LinkDevice;
  701. c: Controller;
  702. name: Plugins.Name;
  703. BEGIN
  704. index := 0;
  705. WHILE (PCI.FindPCIDevice(device, vendor, index, bus, dev, fct) = PCI.Done) & (installed < 10) DO
  706. res := PCI.ReadConfigDword(bus, dev, fct, PCI.Adr0Reg, i); ASSERT(res = PCI.Done);
  707. base := i; ASSERT(~ODD(base)); (* memory mapped *)
  708. DEC(base, base MOD 16);
  709. Machine.MapPhysical(base, 4*K, base);
  710. res := PCI.ReadConfigByte(bus, dev, fct, PCI.IntlReg, irq); ASSERT(res = PCI.Done);
  711. NEW(d, Network.TypeEthernet, MaxETHFrameSize - 14, 6);
  712. name := Name;
  713. i := 0; WHILE name[i] # 0X DO INC(i) END;
  714. name[i] := CHR(ORD("0") + installed);
  715. name[i+1] := 0X;
  716. d.SetName(name);
  717. d.desc := Desc;
  718. NEW(c, d, base, irq); (* increments "installed" when successful *)
  719. INC(index)
  720. END
  721. END ScanPCI;
  722. PROCEDURE IsIn(subset, set: SET): BOOLEAN;
  723. BEGIN
  724. RETURN ((subset * set) = subset);
  725. END IsIn;
  726. PROCEDURE Cleanup;
  727. BEGIN
  728. (*WHILE installedControllers # NIL DO installedControllers.Finalize; installedControllers := installedControllers.next END;*)
  729. IF Modules.shutdown = Modules.None THEN (* module is being freed *)
  730. Remove;
  731. END
  732. END Cleanup;
  733. (*
  734. busy wait for ms milliseconds
  735. *)
  736. PROCEDURE Delay(ms: LONGINT);
  737. VAR t: Kernel.MilliTimer;
  738. BEGIN
  739. Kernel.SetTimer(t, ms);
  740. REPEAT UNTIL Kernel.Expired(t);
  741. END Delay;
  742. BEGIN
  743. Modules.InstallTermHandler(Cleanup);
  744. END Intel8255x.
  745. PC.Compile \s Intel8255x.Mod ~
  746. System.OpenKernelLog ~
  747. TestNet.Mod
  748. System.Free TestNet ~
  749. TestNet.SetDevice "Intel8255x#0" ~
  750. TestNet.ShowDevices ~
  751. TestNet.SendBroadcast ~
  752. TestNet.SendBroadcastVar 1499 ~
  753. TestNet.SendTest ^ 1 10 100 1000 ~
  754. Intel8255x.Test
  755. Decoder.Decode Intel8255x.Obx ~
  756. System.Free Intel8255x ~
  757. System.Free TestNet ~
  758. System.State Intel8255x ~
  759. Aos.Call Intel8255x.Install
  760. Aos.Call Intel8255x.Remove