RTL8169.Mod 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. MODULE RTL8169; (** AUTHOR "Roger Keller"; PURPOSE "Driver for RealTek RTL8169 Ethernet Controllers"; *)
  2. (*
  3. Reference: RealTek, "RealTek Gigabit Ethernet Media Access Controller
  4. with Power Management RTL8169S/RTL8110S Registers"
  5. Revision 1.0, March 2003
  6. *)
  7. IMPORT
  8. SYSTEM, Kernel, Machine, PCI,
  9. Objects, Modules, Plugins, Network, KernelLog;
  10. CONST
  11. Name = "RTL8169#";
  12. Description = "RealTek 8169 Gigabit ethernet driver";
  13. MaxETHFrameSize = 1514;
  14. TxMaxSize = 1600; (* Max size of tx buffers *)
  15. RxMaxSize = 600H; (* Max size for received frames = 1536 bytes *)
  16. RxRingSize = 1024; (* Rx Ring of 116 buffers *)
  17. TxRingSize = 1024; (* Tx Ring of 116 buffers *)
  18. SizeOfRxTxFDHdr = 16; (* size of Rx / Tx Descriptor Header *)
  19. InterruptMask = {0, 1, 2, 3, 4, 5, 6, 7, 15}; (* interrupts to handle *)
  20. Promisc = FALSE; (* enable Promiscuous mode *)
  21. UnknownHW = 0;
  22. RTL8169 = 1;
  23. RTL8169S = 2;
  24. DebugFind = 0;
  25. DebugInit = 1;
  26. DebugConfigs = 2;
  27. DebugHWVer = 3;
  28. DebugMAC = 4;
  29. DebugStatus = 5;
  30. DebugRxRing = 6;
  31. DebugTxRing = 7;
  32. DebugReceive = 8;
  33. DebugTransmit = 9;
  34. DebugInterrupt = 10;
  35. DebugCleanup = 31;
  36. Debug = {DebugFind, DebugInit, DebugTxRing, DebugCleanup};
  37. VAR
  38. installed: LONGINT; (* number of installed devices *)
  39. TYPE
  40. (* base Rx/Tx descriptor, as described in RTL8169 specs *)
  41. RxTxDescriptor = RECORD
  42. flags: SET;
  43. vLanTag: LONGINT;
  44. bufAdrLo, bufAdrHi: LONGINT;
  45. END;
  46. (* buffer for transmission *)
  47. TxBuffer = POINTER TO RECORD
  48. data: ARRAY TxMaxSize OF CHAR;
  49. next: TxBuffer;
  50. END;
  51. (* wrapper for Network.Buffer to be able to form rings *)
  52. RxBuffer = POINTER TO RECORD
  53. buf: Network.Buffer;
  54. next: RxBuffer;
  55. END;
  56. (* LinkDevice: interface to Bluebottle *)
  57. LinkDevice = OBJECT (Network.LinkDevice)
  58. VAR
  59. ctrl: Controller;
  60. hw: LONGINT;
  61. PROCEDURE Linked*(): LONGINT;
  62. BEGIN
  63. RETURN ctrl.linkStatus;
  64. END Linked;
  65. PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  66. BEGIN
  67. ctrl.SendFrame(dst, type, l3hdr, l4hdr, data, h3len, h4len, dofs, dlen);
  68. END DoSend;
  69. PROCEDURE Finalize(connected: BOOLEAN);
  70. BEGIN
  71. ctrl.Finalize;
  72. Finalize^(connected);
  73. END Finalize;
  74. END LinkDevice;
  75. (* Controller: interface to the RTL8169 hardware *)
  76. Controller = OBJECT
  77. VAR
  78. next: Controller; (* next controller in list *)
  79. base: ADDRESS; irq: LONGINT;
  80. dev: LinkDevice;
  81. rds: ARRAY RxRingSize OF RxTxDescriptor;
  82. tds: ARRAY TxRingSize OF RxTxDescriptor;
  83. curRD, curTD: LONGINT;
  84. firstRD, firstTD: LONGINT;
  85. lastRD, lastTD: LONGINT;
  86. (*rxBuffer, rxLast: TxBuffer;*)
  87. rxBuffer, rxLast: RxBuffer;
  88. txBuffer, txLast: TxBuffer;
  89. nofFreeTx: LONGINT; (* number of free tx descriptors *)
  90. nRxOverflow: HUGEINT;
  91. nTxOverflow: HUGEINT;
  92. nRxFrames, nTxFrames: LONGINT;
  93. nRxErrorFrames: LONGINT;
  94. nTxErrorFrames: LONGINT;
  95. linkStatus: LONGINT;
  96. PROCEDURE &Init*(dev: LinkDevice; base: ADDRESS; irq: LONGINT);
  97. VAR
  98. res: WORD; i: LONGINT;
  99. s: SET;
  100. BEGIN
  101. (* update list of installed controllers, insert at head *)
  102. SELF.next := installedControllers;
  103. installedControllers := SELF;
  104. SELF.base := base;
  105. SELF.dev := dev;
  106. SELF.irq := irq;
  107. dev.ctrl := SELF;
  108. nRxOverflow := 0;
  109. nTxOverflow := 0;
  110. nRxFrames := 0;
  111. nTxFrames := 0;
  112. nRxErrorFrames := 0;
  113. nTxErrorFrames := 0;
  114. (* tell the system that the nic calculates the checksums for tcp, udp and ip packets *)
  115. dev.calcChecksum := {Network.ChecksumIP, Network.ChecksumTCP, Network.ChecksumUDP};
  116. (* set ethernet broadcast address: FF-FF-FF-FF-FF-FF *)
  117. FOR i := 0 TO 5 DO
  118. dev.broadcast[i] := 0FFX
  119. END;
  120. (* make sure PIO and MMIO are enabled*)
  121. s := SYSTEM.VAL(SET, Read8(52H));
  122. IF ~ (2 IN s) THEN
  123. KernelLog.String("I/O Mapping is disabled!");
  124. HALT(1000);
  125. END;
  126. IF ~ (3 IN s) THEN
  127. KernelLog.String("MMIO is disabled!");
  128. HALT(1000);
  129. END;
  130. (* find out if we're on 1GBps *)
  131. s := SYSTEM.VAL(SET, Read8(6CH));
  132. (* if not, try to enable 1GBps ... *)
  133. IF ~ (4 IN s) THEN
  134. (* reset the hardware and enable 1000baseTx *)
  135. HwReset;
  136. EnableTBI;
  137. END;
  138. (* read and store MAC address *)
  139. ReadMACAddress;
  140. (* find out hardware version *)
  141. GetHardwareVersion;
  142. (* soft reset the chip *)
  143. ResetNIC;
  144. (* enable Tx and Rx *)
  145. EnableTxRx(TRUE, TRUE);
  146. (* set Max Transmit Packet Size (MTPS):
  147. register counts in 32 byte units -> 32H * 32 bytes = 1600 bytes *)
  148. Write8(0ECH, 32H);
  149. (* set Receive Packet Maximum Size (RMS) *)
  150. Write16(0DAH, RxMaxSize);
  151. (* set Tx config register:
  152. let the nic compute CRCs of frames in Tx *)
  153. s := SYSTEM.VAL(SET, Read32(40H));
  154. s := (s - {17..18, 19}) + {8..10, 25};
  155. Write32(40H, SYSTEM.VAL(LONGINT, s));
  156. (* config c+ command register:
  157. PCI multiple read/write enable;
  158. Receive Checksum Offload enable *)
  159. s := SYSTEM.VAL(SET, Read16(0E0H));
  160. s := s + {3, 5};
  161. Write16(0E0H, SYSTEM.VAL(LONGINT, s));
  162. (* setup Tx (normal priority) ring *)
  163. res := SetupTxRing();
  164. (* set Transmit Normal Priority Descriptor Start Address (TNPDS) *)
  165. Write32(20H, res);
  166. Write32(20H + 4, 0);
  167. (* setup Rx ring *)
  168. res := SetupRxRing();
  169. (* set Receive Descriptor Start Address (RDSAR) *)
  170. Write32(0E4H, res);
  171. Write32(0E4H + 4, 0);
  172. (* reset Rx missed packet counter *)
  173. Write32(04CH, 0);
  174. (* configure receiver *)
  175. ConfigRx;
  176. (* install interrupt handler *)
  177. IF (irq >= 1) & (irq <= 15) THEN
  178. Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0 + irq)
  179. END;
  180. (* enable interrupts *)
  181. Write16(3CH, SYSTEM.VAL(LONGINT, InterruptMask));
  182. UpdateLinkStatus;
  183. (* register device with Network *)
  184. Network.registry.Add(dev, res);
  185. ASSERT(res = Plugins.Ok);
  186. INC(installed);
  187. IF DebugConfigs IN Debug THEN
  188. DebugConfig;
  189. END;
  190. END Init;
  191. PROCEDURE SendFrame(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  192. VAR
  193. txLen, offset, type4: LONGINT;
  194. bufBase: ADDRESS;
  195. chksums: SET;
  196. BEGIN {EXCLUSIVE}
  197. IF nofFreeTx <= 0 THEN
  198. KernelLog.String("no tx buffers"); KernelLog.Ln;
  199. INC(nTxOverflow);
  200. END;
  201. AWAIT(nofFreeTx > 0);
  202. txLen := 14 + h3len + h4len + dlen;
  203. bufBase := ADDRESSOF(txBuffer.data);
  204. (* generate ethernet frame: setup eth header, move data *)
  205. (* set destination mac address (first 6 bytes of eth frame) *)
  206. SYSTEM.MOVE(ADDRESSOF(dst[0]), bufBase, 6);
  207. (* set source mac address (6 bytes @ offset 6 of eth frame) *)
  208. SYSTEM.MOVE(ADDRESSOF(dev.local[0]), bufBase + 6, 6);
  209. (* set upper layer type, bring type from host to network byte order *)
  210. SYSTEM.PUT16(bufBase + 12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
  211. offset := 14; (* eth header has 14 bytes *)
  212. (* move layer 3 and layer 4 headers, data *)
  213. IF h3len > 0 THEN
  214. SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), bufBase + offset, h3len);
  215. INC(offset, h3len);
  216. END;
  217. IF h4len > 0 THEN
  218. SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), bufBase + offset, h4len);
  219. INC(offset, h4len);
  220. END;
  221. IF offset + dlen < MaxETHFrameSize THEN
  222. SYSTEM.MOVE(ADDRESSOF(data[0]) + dofs, bufBase + offset, dlen);
  223. INC(offset, dlen);
  224. END;
  225. (* make the frame at least 64 bytes long *)
  226. WHILE offset < 60 DO
  227. txBuffer.data[offset] := CHR(0);
  228. INC(offset);
  229. INC(txLen);
  230. END;
  231. IF DebugTransmit IN Debug THEN
  232. KernelLog.String("Sending frame of length ");
  233. KernelLog.Int(txLen, 0);
  234. KernelLog.Ln;
  235.  (*KernelLog.Memory(bufBase, txLen);*)
  236. END;
  237. (* find out which protocols are used;
  238. let the NIC calc the checksums for IP, TCP and UCP headers *)
  239. chksums := {};
  240. IF type = 0800H THEN
  241. INCL(chksums, 18); (* offload IP checksum *)
  242. type4 := SYSTEM.VAL(SHORTINT, l3hdr[9]); (* get type if IP data *)
  243. IF type4 = 6 THEN (* TCP/IP *)
  244. INCL(chksums, 16); (* offload TCP checksum *)
  245. ELSIF type4 = 17 THEN
  246. INCL(chksums, 17); (* offload UDP checksum *)
  247. END;
  248. END;
  249. (* update Tx Descriptor:
  250. set OWN=1, FS=1, LS=1, checksum offloads;
  251. set size of packet to be transmitted *)
  252. tds[curTD].flags := tds[curTD].flags * {30}; (* only keep EOR bit *)
  253. tds[curTD].flags := tds[curTD].flags + {31, 29, 28} + chksums;
  254. tds[curTD].flags := tds[curTD].flags + (SYSTEM.VAL(SET, txLen) * {0..15});
  255. (* move to next Tx Descriptor, Tx Buffer *)
  256. INC(curTD);
  257. IF curTD = TxRingSize THEN
  258. curTD := firstTD;
  259. END;
  260. txBuffer := txBuffer.next;
  261. DEC(nofFreeTx);
  262. (* tell the nic that there's some eth frame waiting to be transmitted (set NPQ=1) *)
  263. Write8(38H, SYSTEM.VAL(LONGINT, {6}));
  264. END SendFrame;
  265. PROCEDURE ConfigRx;
  266. VAR s: SET;
  267. BEGIN
  268. (* set Rx config register:
  269. let the nic check CRCs of frames in Rx;
  270. accept broadcast, multicast, phys match, all packets with dest addr (IFF Promiscuos mode enabled)
  271. set no Rx FIFO threshold, set unlimited DMA burst size*)
  272. s := SYSTEM.VAL(SET, Read32(44H));
  273. s := (s * {7, 11..12, 17..31}) + {1..3, 9, 14..15, 16};
  274. IF Promisc THEN
  275. INCL(s, 0);
  276. END;
  277. Write32(44H, SYSTEM.VAL(LONGINT, s));
  278. (* set multicast filter: receive everything *)
  279. Write32(08H, LONGINT(0FFFFFFFFH));
  280. Write32(08H + 4, LONGINT(0FFFFFFFFH));
  281. END ConfigRx;
  282. PROCEDURE SetTimer(val: LONGINT);
  283. BEGIN
  284. Write32(58H, val);
  285. END SetTimer;
  286. PROCEDURE GetHardwareVersion;
  287. VAR s: SET;
  288. BEGIN
  289. s := SYSTEM.VAL(SET, Read32(40H));
  290. s := s * {23, 26..30};
  291. IF DebugHWVer IN Debug THEN
  292. KernelLog.String("Hardware Version: ");
  293. END;
  294. IF s = {} THEN
  295. dev.hw := RTL8169;
  296. IF DebugHWVer IN Debug THEN
  297. KernelLog.String("RTL8169");
  298. END;
  299. ELSIF ((s * {23, 26}) # {}) & ((s * {27..30}) = {}) THEN
  300. dev.hw := RTL8169S;
  301. IF DebugHWVer IN Debug THEN
  302. KernelLog.String("RTL8169S/RTL8110S");
  303. END;
  304. ELSE
  305. dev.hw := UnknownHW;
  306. IF DebugHWVer IN Debug THEN
  307. KernelLog.String("Hardware Version is unknown");
  308. END;
  309. END;
  310. IF DebugHWVer IN Debug THEN
  311. KernelLog.Ln;
  312. END;
  313. END GetHardwareVersion;
  314. PROCEDURE ResetNIC;
  315. VAR s: SET;
  316. BEGIN
  317. Write8(37H, SYSTEM.VAL(LONGINT, {4}));
  318. (* wait until reset has finished *)
  319. REPEAT
  320. Delay(10);
  321. s := SYSTEM.VAL(SET, Read8(37H));
  322. UNTIL ~(4 IN s);
  323. END ResetNIC;
  324. PROCEDURE EnableTxRx(tx, rx: BOOLEAN);
  325. VAR s: SET;
  326. BEGIN
  327. s := SYSTEM.VAL(SET, Read8(37H));
  328. s := s * {0..1, 5..7};
  329. IF tx THEN
  330. INCL(s, 2);
  331. END;
  332. IF rx THEN
  333. INCL(s, 3);
  334. END;
  335. Write8(37H, SYSTEM.VAL(LONGINT, s));
  336. END EnableTxRx;
  337. PROCEDURE ReadMACAddress;
  338. VAR
  339. i: INTEGER;
  340. res: WORD;
  341. BEGIN
  342. (* MAC address is in registers 00H - 05H *)
  343. IF DebugMAC IN Debug THEN
  344. KernelLog.String("MAC address is: ");
  345. END;
  346. FOR i := 0 TO 5 DO
  347. res := Read8(i);
  348. SYSTEM.PUT8(ADDRESSOF(dev.local[i]), res);
  349. IF DebugMAC IN Debug THEN
  350. IF i > 0 THEN
  351. KernelLog.String("-");
  352. END;
  353. KernelLog.Hex(ORD(dev.local[i]), -2);
  354. END;
  355. END;
  356. IF DebugMAC IN Debug THEN
  357. KernelLog.Ln;
  358. END;
  359. dev.adrSize := 6;
  360. END ReadMACAddress;
  361. PROCEDURE Read8(reg: LONGINT): SHORTINT;
  362. BEGIN
  363. RETURN SYSTEM.GET8(base + reg);
  364. END Read8;
  365. PROCEDURE Write8(reg: LONGINT; val: LONGINT);
  366. BEGIN
  367. SYSTEM.PUT8(base + reg, SHORT(SHORT(val)));
  368. END Write8;
  369. PROCEDURE Read16(reg: LONGINT): INTEGER;
  370. BEGIN
  371. RETURN SYSTEM.GET16(base + reg);
  372. END Read16;
  373. PROCEDURE Write16(reg: LONGINT; val: LONGINT);
  374. BEGIN
  375. SYSTEM.PUT16(base + reg, SHORT(val));
  376. END Write16;
  377. PROCEDURE Read32(reg: LONGINT): LONGINT;
  378. BEGIN
  379. RETURN SYSTEM.GET32(base + reg);
  380. END Read32;
  381. PROCEDURE Write32(reg: LONGINT; val: LONGINT);
  382. BEGIN
  383. SYSTEM.PUT32(base + reg, val);
  384. END Write32;
  385. PROCEDURE EnableTBI;
  386. VAR
  387. s: SET;
  388. i: LONGINT;
  389. BEGIN
  390. IF 7 IN SYSTEM.VAL(SET, Read8(6CH)) THEN RETURN END;
  391. s := PHYRead(04H) + {5..8}; (* advertise 10 full/half, 100 full/half *)
  392. PHYWrite(04H, s);
  393. PHYWrite(09H, {9}); (* advertise 1000 full *)
  394. (* enable and restart auto negotiation *)
  395. PHYWrite(00H, {9, 12});
  396. Delay(100);
  397. FOR i := 1 TO 1000 DO
  398. s := PHYRead(01H);
  399. IF 5 IN s THEN (* auto negotiation complete *)
  400. Delay(100);
  401. IF DebugStatus IN Debug THEN
  402. PrintStatus;
  403. END;
  404. RETURN;
  405. ELSE
  406. Delay(100);
  407. END;
  408. END;
  409. END EnableTBI;
  410. PROCEDURE HwReset;
  411. VAR
  412. s: SET;
  413. i: LONGINT;
  414. BEGIN
  415. s := PHYRead(00H) + {15};
  416. PHYWrite(00H, s);
  417. (* wait until reset has been completet *)
  418. FOR i := 1 TO 50 DO
  419. IF ~(15 IN PHYRead(00H)) THEN
  420. RETURN;
  421. END;
  422. END;
  423. END HwReset;
  424. PROCEDURE PHYWrite(regAdr: LONGINT; data: SET);
  425. VAR
  426. s: SET;
  427. i: LONGINT;
  428. BEGIN
  429. s := {31};
  430. s := s + (SYSTEM.VAL(SET, regAdr * 010000H) * {16..20});
  431. s := s + (data * {0..15});
  432. Write32(60H, SYSTEM.VAL(LONGINT, s));
  433. Delay(100);
  434. (* wait until write has been completet *)
  435. FOR i := 1 TO 2000 DO
  436. IF SYSTEM.VAL(SET, Read32(60H)) * {31} = {} THEN
  437. RETURN;
  438. END;
  439. Delay(100);
  440. END;
  441. END PHYWrite;
  442. PROCEDURE PHYRead(regAdr: LONGINT): SET;
  443. VAR
  444. s: SET;
  445. i: LONGINT;
  446. BEGIN
  447. s := SYSTEM.VAL(SET, regAdr * 010000H) * {16..20};
  448. Write32(60H, SYSTEM.VAL(LONGINT, s));
  449. Delay(100);
  450. (* wait until read has been completed *)
  451. FOR i := 1 TO 2000 DO
  452. s := SYSTEM.VAL(SET, Read32(60H));
  453. IF 31 IN s THEN
  454. RETURN (s * {0..15});
  455. END;
  456. Delay(100);
  457. END;
  458. RETURN {};
  459. END PHYRead;
  460. PROCEDURE AllocBuffer(VAR buf: TxBuffer);
  461. BEGIN
  462. NEW(buf); (* edit: no more alignment necessary, since PTR TO RECORD is already 32 byte aligned *)
  463. END AllocBuffer;
  464. PROCEDURE SetupRxRing(): Machine.Address32;
  465. VAR
  466. r: LONGINT;
  467. adr, physAdr: ADDRESS;
  468. buf, prev: RxBuffer;
  469. BEGIN
  470. (* make sure the descriptor ring is 256 byte aligned in physical memory *)
  471. adr := ADDRESSOF(rds[0]);
  472. adr := Machine.PhysicalAdr(adr, SizeOfRxTxFDHdr);
  473. IF adr MOD 256 = 0 THEN
  474. firstRD := 0;
  475. ELSE
  476. firstRD := 16 - (LONGINT (adr MOD 256) DIV 16);
  477. END;
  478. IF DebugRxRing IN Debug THEN
  479. KernelLog.String("Rx descriptor start = ");
  480. KernelLog.Hex(adr, 8);
  481. KernelLog.Ln;
  482. KernelLog.String("first Rx descriptor id = ");
  483. KernelLog.Int(firstRD, 0);
  484. KernelLog.Ln;
  485. END;
  486. FOR r := firstRD TO RxRingSize - 1 DO
  487. NEW(buf);
  488. buf.buf := Network.GetNewBuffer();
  489. ASSERT(buf.buf # NIL);
  490. adr := ADDRESSOF(buf.buf.data[0]);
  491. physAdr := Machine.PhysicalAdr(adr, Network.MaxPacketSize);
  492. ASSERT(physAdr # Machine.NilAdr);
  493. rds[r].flags := {31};
  494. rds[r].flags := rds[r].flags + (SYSTEM.VAL(SET, Network.MaxPacketSize) * {0..13});
  495. rds[r].vLanTag := 0;
  496. rds[r].bufAdrLo := Machine.Ensure32BitAddress (physAdr);
  497. rds[r].bufAdrHi := 0;
  498. IF prev # NIL THEN
  499. prev.next := buf;
  500. ELSE
  501. (* set first Rx Buffer *)
  502. rxBuffer := buf;
  503. END;
  504. prev := buf;
  505. END;
  506. rxLast := buf;
  507. rxLast.next := rxBuffer;
  508. (* mark last descriptor as EOR (end of descriptor ring) *)
  509. INCL(rds[RxRingSize - 1].flags, 30);
  510. curRD := firstRD;
  511. adr := ADDRESSOF(rds[firstRD]);
  512. (* return physical address of first rx descriptor *)
  513. RETURN Machine.Ensure32BitAddress (Machine.PhysicalAdr(adr, SizeOfRxTxFDHdr));
  514. END SetupRxRing;
  515. PROCEDURE SetupTxRing(): Machine.Address32;
  516. VAR
  517. r: LONGINT;
  518. adr, physAdr: ADDRESS;
  519. buf, prev: TxBuffer;
  520. BEGIN
  521. (* make sure the descriptor ring is 256 byte aligned in physical memory *)
  522. adr := ADDRESSOF(tds[0]);
  523. adr := Machine.PhysicalAdr(adr, SizeOfRxTxFDHdr);
  524. IF adr MOD 256 = 0 THEN
  525. firstTD := 0;
  526. ELSE
  527. firstTD := 16 - (LONGINT (adr MOD 256) DIV 16);
  528. END;
  529. lastTD := firstTD;
  530. nofFreeTx := TxRingSize - firstTD;
  531. IF DebugTxRing IN Debug THEN
  532. KernelLog.String("Tx descriptor start = ");
  533. KernelLog.Hex(adr, -8);
  534. KernelLog.Ln;
  535. KernelLog.String("first Tx descriptor id = ");
  536. KernelLog.Int(firstTD, 0);
  537. KernelLog.Ln;
  538. KernelLog.String("nofFreeTx = ");
  539. KernelLog.Int(nofFreeTx, 0);
  540. KernelLog.Ln;
  541. END;
  542. FOR r := firstTD TO TxRingSize - 1 DO
  543. AllocBuffer(buf);
  544. (* configure TFD *)
  545. adr := ADDRESSOF(buf.data[0]);
  546. physAdr := Machine.PhysicalAdr(adr, TxMaxSize);
  547. ASSERT(physAdr # Machine.NilAdr);
  548. tds[r].flags := {};
  549. tds[r].vLanTag := 0;
  550. tds[r].bufAdrLo := Machine.Ensure32BitAddress (physAdr);
  551. tds[r].bufAdrHi := 0;
  552. IF prev # NIL THEN
  553. prev.next := buf;
  554. ELSE
  555. (* set first Tx Buffer *)
  556. txBuffer := buf;
  557. END;
  558. prev := buf;
  559. END;
  560. txLast := buf;
  561. txLast.next := txBuffer;
  562. (* mark last descriptor as EOR (end of descriptor ring) *)
  563. INCL(tds[TxRingSize - 1].flags, 30);
  564. curTD := firstTD;
  565. adr := ADDRESSOF(tds[firstTD]);
  566. (* return physical address of first tx descriptor *)
  567. RETURN Machine.Ensure32BitAddress (Machine.PhysicalAdr(adr, SizeOfRxTxFDHdr));
  568. END SetupTxRing;
  569. PROCEDURE ReadFrames;
  570. VAR
  571. adr: ADDRESS; type, size: LONGINT;
  572. dstAdr: Network.LinkAdr;
  573. buf: Network.Buffer;
  574. s: SET;
  575. BEGIN
  576. (* read all frames that are marked with OWN = 0*)
  577. WHILE ~(31 IN rds[curRD].flags) DO
  578. (* skip error frames *)
  579. IF (21 IN rds[curRD].flags) THEN
  580. INC(nRxErrorFrames);
  581. ELSIF CheckChecksumErrors(rds[curRD]) THEN
  582. (* find out how many bytes have been received, including CRC *)
  583. size := SYSTEM.VAL(LONGINT, rds[curRD].flags * {0..13});
  584. IF DebugReceive IN Debug THEN
  585. KernelLog.String("Received a frame of length ");
  586. KernelLog.Int(size, 0);
  587. KernelLog.Ln;
  588. END;
  589. adr := ADDRESSOF(rxBuffer.buf.data[0]);
  590. (* copy destination and source addresses, type of packet *)
  591. dstAdr := SYSTEM.VAL(Network.LinkAdr, rxBuffer.buf.data[0]);
  592. rxBuffer.buf.src := SYSTEM.VAL(Network.LinkAdr, rxBuffer.buf.data[6]);
  593. type := Network.GetNet2(rxBuffer.buf.data, 12);
  594. buf := rxBuffer.buf;
  595. buf.ofs := 14;
  596. buf.len := size - 14;
  597. buf.calcChecksum := { Network.ChecksumIP, Network.ChecksumUDP, Network.ChecksumTCP };
  598. buf.next := NIL;
  599. buf.prev := NIL;
  600. IF type = 0DEADH THEN
  601. (* make sure the frame doesn't bounce between the two cards by adding 1 to the type *)
  602. SendFrame(buf.src, type + 1, buf.data, buf.data, buf.data, 0, 0, 0, buf.len);
  603. ELSIF type = 0DEADH + 1 THEN
  604. (* discard this frame *)
  605. ELSE
  606. dev.QueueBuffer(buf, type);
  607. END;
  608. INC(nRxFrames);
  609. IF (type # 0DEADH) & (type # 0DEADH + 1) THEN
  610. rxBuffer.buf := Network.GetNewBuffer();
  611. buf := rxBuffer.buf;
  612. ASSERT(rxBuffer.buf # NIL);
  613. IF buf # NIL THEN
  614. rds[curRD].bufAdrLo := Machine.Ensure32BitAddress (Machine.PhysicalAdr(ADDRESSOF(rxBuffer.buf.data[0]), Network.MaxPacketSize));
  615. END;
  616. END;
  617. ELSE
  618. IF DebugReceive IN Debug THEN
  619. KernelLog.String("Checksum error detected!"); KernelLog.Ln;
  620. END;
  621. INC(nRxErrorFrames);
  622. END;
  623. (* mark the buffer to be able to receive again *)
  624. rds[curRD].flags := {31} + (rds[curRD].flags * {30}) + (SYSTEM.VAL(SET, Network.MaxPacketSize) * {0..13});
  625. rds[curRD].vLanTag := 0;
  626. s := rds[curRD].flags;
  627. (* advance Rx descriptor, Rx buffer *)
  628. rxBuffer := rxBuffer.next;
  629. INC(curRD);
  630. IF curRD = RxRingSize THEN
  631. curRD := firstRD;
  632. END;
  633. END;
  634. END ReadFrames;
  635. PROCEDURE CheckChecksumErrors(d: RxTxDescriptor): BOOLEAN;
  636. VAR proto: SET;
  637. BEGIN
  638. proto := d.flags * {17..18};
  639. IF proto = {} THEN
  640. RETURN TRUE; (* no checksum errors since non-ip packet *)
  641. ELSIF proto = {17} THEN
  642. (* protocol is TCP/IP so check IP and TCP checksum failures *)
  643. RETURN d.flags * {14, 16} = {};
  644. ELSIF proto = {18} THEN
  645. (* protocol is UDP/IP so check IP and UDP checksum failures *)
  646. RETURN d.flags * {15, 16} = {};
  647. ELSE
  648. (* protocol is IP so check IP checksum failures *)
  649. RETURN d.flags * {16} = {};
  650. END;
  651. END CheckChecksumErrors;
  652. PROCEDURE HandleInterrupt;
  653. VAR
  654. status, ack: SET;
  655. BEGIN
  656. (* get current interrupt mask, disable all interrupts *)
  657. Write16(3CH, 0);
  658. ack := {0};
  659. (* read interrupt status, @ offset 3EH - 3FH *)
  660. status := SYSTEM.VAL(SET, Read16(3EH));
  661. (* System Error (SERR) *)
  662. IF (15 IN InterruptMask) & (15 IN status) THEN
  663. IF DebugInterrupt IN Debug THEN
  664. KernelLog.String("System Error Interrupt"); KernelLog.Ln;
  665. END;
  666. INCL(ack, 15);
  667. END;
  668. (* Time Out (TimeOut) *)
  669. IF (14 IN InterruptMask) & (14 IN status) THEN
  670. IF DebugInterrupt IN Debug THEN
  671. KernelLog.String("Timeout Interrupt"); KernelLog.Ln;
  672. END;
  673. INCL(ack, 14);
  674. END;
  675. IF (8 IN InterruptMask) & (8 IN status) THEN
  676. IF DebugInterrupt IN Debug THEN
  677. KernelLog.String("Software Interrupt"); KernelLog.Ln;
  678. END;
  679. INCL(ack, 8);
  680. END;
  681. IF (7 IN InterruptMask) & (7 IN status) THEN
  682. IF DebugInterrupt IN Debug THEN
  683. KernelLog.String("Tx Descriptor Unavailable Interrupt"); KernelLog.Ln;
  684. END;
  685. INCL(ack, 7);
  686. (*UpdateTxRing;*)
  687. (*INCL(status, 2); (* let the tx ring be updated *)*)
  688. END;
  689. (* Rx FIFO Overflow (FOVW) *)
  690. IF (6 IN InterruptMask) & (6 IN status) THEN
  691. IF DebugInterrupt IN Debug THEN
  692. KernelLog.String("Rx FIFO Overflow Interrupt"); KernelLog.Ln;
  693. END;
  694. INC(nRxOverflow);
  695. INCL(ack, 6);
  696. (*INCL(ack, 4);*)
  697. (*INCL(status, 0); (* read the frames *)*)
  698. END;
  699. (* Link Change (LinkChg) *)
  700. IF (5 IN InterruptMask) & (5 IN status) THEN
  701. IF DebugInterrupt IN Debug THEN
  702. KernelLog.String("Link Change Interrupt"); KernelLog.Ln;
  703. END;
  704. UpdateLinkStatus;
  705. INCL(ack, 5);
  706. END;
  707. (* Rx Descriptor Unavailable (RDU) *)
  708. IF (4 IN InterruptMask) & (4 IN status) THEN
  709. IF DebugInterrupt IN Debug THEN
  710. (* CAREFUL: UN-COMMENTING THE NEXT LINE CAN CRASH THE OS *)
  711. (*KernelLog.String("Rx Descriptor Unavailable Interrupt"); KernelLog.Ln;*)
  712. END;
  713. INCL(ack, 4);
  714. (*INCL(status, 0); (* read the frames *)*)
  715. END;
  716. (* Transmit (Tx) Error (TER) *)
  717. IF (3 IN InterruptMask) & (3 IN status) THEN
  718. IF DebugInterrupt IN Debug THEN
  719. KernelLog.String("Transmit Error Interrupt"); KernelLog.Ln;
  720. END;
  721. INCL(ack, 3);
  722. INC(nTxErrorFrames);
  723. INCL(status, 2); (* let the tx ring be updated *)
  724. END;
  725. (* Transmit (Tx) OK (TOK) *)
  726. IF (2 IN InterruptMask) & (2 IN status) THEN
  727. IF DebugInterrupt IN Debug THEN
  728. KernelLog.String("Transmit OK Interrupt"); KernelLog.Ln;
  729. END;
  730. UpdateTxRing;
  731. INCL(ack, 2);
  732. END;
  733. (* Receive (Rx) Error (RER) *)
  734. IF (1 IN InterruptMask) & (1 IN status) THEN
  735. IF DebugInterrupt IN Debug THEN
  736. KernelLog.String("Receive Error Interrupt"); KernelLog.Ln;
  737. END;
  738. INCL(ack, 1);
  739. (*ReadFrames;*)
  740. INCL(status, 0); (* let the rx ring be updated *)
  741. END;
  742. (* Receive (Rx) OK (ROK) *)
  743. IF (0 IN InterruptMask) & (0 IN status) THEN
  744. IF DebugInterrupt IN Debug THEN
  745. (* CAREFUL: UN-COMMENTING THE NEXT LINE CAN CRASH THE OS *)
  746. (*KernelLog.String("Receive Ok Interrupt"); KernelLog.Ln;*)
  747. END;
  748. ReadFrames;
  749. INCL(ack, 0); (* read the frames *)
  750. END;
  751. ack := status;
  752. (* reset interrupt status *)
  753. Write16(3EH, SYSTEM.VAL(LONGINT, ack));
  754. (* re-enable interrupts *)
  755. Write16(3CH, SYSTEM.VAL(LONGINT, InterruptMask));
  756. END HandleInterrupt;
  757. PROCEDURE UpdateLinkStatus;
  758. BEGIN
  759. IF 1 IN SYSTEM.VAL(SET, Read8(6CH)) THEN
  760. linkStatus := Network.LinkLinked;
  761. ELSE
  762. linkStatus := Network.LinkNotLinked;
  763. END;
  764. END UpdateLinkStatus;
  765. PROCEDURE UpdateTxRing;
  766. VAR i: LONGINT;
  767. BEGIN { EXCLUSIVE }
  768. i := lastTD;
  769. WHILE (i # curTD) DO
  770. IF DebugTransmit IN Debug THEN
  771. KernelLog.String("*** Tx OK ***"); KernelLog.Ln;
  772. END;
  773. INC(i);
  774. INC(nTxFrames);
  775. INC(nofFreeTx);
  776. IF i = TxRingSize THEN
  777. i := firstTD;
  778. END;
  779. txLast := txLast.next;
  780. END;
  781. lastTD := i;
  782. END UpdateTxRing;
  783. PROCEDURE Finalize;
  784. VAR
  785. s: SET;
  786. BEGIN
  787. (* cleanup Network registry *)
  788. Network.registry.Remove(dev);
  789. (* disable Tx and Rx *)
  790. s := SYSTEM.VAL(SET, Read8(37H));
  791. Write8(37H, SYSTEM.VAL(SHORTINT, s - {2, 3}));
  792. (* soft reset *)
  793. Write8(37H, SYSTEM.VAL(SHORTINT, {4}));
  794. (* disable all interrupts *)
  795. Write16(3CH, 0);
  796. WHILE (rxBuffer # NIL) & (rxBuffer.buf # NIL) DO
  797. Network.ReturnBuffer(rxBuffer.buf);
  798. rxBuffer.buf := NIL;
  799. rxBuffer := rxBuffer.next;
  800. END;
  801. IF DebugCleanup IN Debug THEN
  802. KernelLog.String("Removing IRQ Handler.");
  803. KernelLog.Ln
  804. END;
  805. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0 + irq);
  806. END Finalize;
  807. PROCEDURE DebugConfig;
  808. VAR
  809. s: SET;
  810. res: WORD;
  811. BEGIN
  812. KernelLog.String("*** BEGIN OF NIC CONFIGURATION ***"); KernelLog.Ln;
  813. s := SYSTEM.VAL(SET, Read16(0E0H));
  814. KernelLog.String("C+ Command:"); KernelLog.Ln;
  815. KernelLog.String(" "); KernelLog.Bits(s, 0, 16); KernelLog.Ln;
  816. KernelLog.String("Rx Descriptor base address:"); KernelLog.Ln;
  817. KernelLog.String(" ");
  818. res := Read32(0E4H + 4H);
  819. KernelLog.Hex(res, 8);
  820. res := Read32(0E4H);
  821. KernelLog.Hex(res, 8);
  822. KernelLog.Ln;
  823. KernelLog.String("Tx Normal Priority Descriptor base address:"); KernelLog.Ln;
  824. KernelLog.String(" ");
  825. res := Read32(020H + 4H);
  826. KernelLog.Hex(res, 8);
  827. res := Read32(020H);
  828. KernelLog.Hex(res, 8);
  829. KernelLog.Ln;
  830. res := Read16(0DAH);
  831. KernelLog.String("Receive Packet Max Size:"); KernelLog.Ln;
  832. KernelLog.String(" "); KernelLog.Int(res, 0); KernelLog.Ln;
  833. res := Read8(0ECH);
  834. KernelLog.String("Max Transmit Packet Size:"); KernelLog.Ln;
  835. KernelLog.String(" "); KernelLog.Int(res * 32, 0); KernelLog.Ln;
  836. s := SYSTEM.VAL(SET, Read32(40H));
  837. KernelLog.String("Transmit Configuration:"); KernelLog.Ln;
  838. KernelLog.String(" "); KernelLog.Bits(s, 0, 32); KernelLog.Ln;
  839. s := SYSTEM.VAL(SET, Read32(44H));
  840. KernelLog.String("Receive Configuration:"); KernelLog.Ln;
  841. KernelLog.String(" "); KernelLog.Bits(s, 0, 32); KernelLog.Ln;
  842. s := SYSTEM.VAL(SET, Read16(3CH));
  843. KernelLog.String("interrupt mask:"); KernelLog.Ln;
  844. KernelLog.String(" "); KernelLog.Bits(s, 0, 16); KernelLog.Ln;
  845. s := SYSTEM.VAL(SET, Read8(37H));
  846. KernelLog.String("command bits:"); KernelLog.Ln;
  847. KernelLog.String(" "); KernelLog.Bits(s, 0, 8); KernelLog.Ln;
  848. KernelLog.String("*** END OF NIC CONFIGURATION ***"); KernelLog.Ln;
  849. END DebugConfig;
  850. PROCEDURE PrintStatus;
  851. VAR
  852. phyStatus: SET;
  853. BEGIN
  854. phyStatus := SYSTEM.VAL(SET, Read8(6CH));
  855. IF 1 IN phyStatus THEN
  856. KernelLog.String(" Device is linked");
  857. KernelLog.Ln;
  858. ELSE
  859. KernelLog.String(" Device is NOT linked");
  860. KernelLog.Ln;
  861. END;
  862. IF 4 IN phyStatus THEN
  863. KernelLog.String(" Linkspeed is 1GBps Full-Duplex");
  864. KernelLog.Ln;
  865. ELSE
  866. IF 3 IN phyStatus THEN
  867. KernelLog.String(" Linkspeed is 100MBps");
  868. KernelLog.Ln;
  869. ELSIF 2 IN phyStatus THEN
  870. KernelLog.String(" Linkspeed is 10MBps");
  871. KernelLog.Ln;
  872. END;
  873. IF 0 IN phyStatus THEN
  874. KernelLog.String(" Device is in FULL-DUPLEX MODE");
  875. KernelLog.Ln;
  876. ELSE
  877. KernelLog.String(" Device is in Half-Duplex Mode");
  878. KernelLog.Ln;
  879. END;
  880. END;
  881. IF 6 IN phyStatus THEN
  882. KernelLog.String(" Transmit Flow Control enabled");
  883. KernelLog.Ln;
  884. END;
  885. IF 5 IN phyStatus THEN
  886. KernelLog.String(" Receive Flow Control enabled");
  887. KernelLog.Ln;
  888. END;
  889. KernelLog.String(" nRxOverflow = ");
  890. KernelLog.HIntHex(nRxOverflow, 16);
  891. KernelLog.Ln;
  892. KernelLog.String(" nTxOverflow = ");
  893. KernelLog.HIntHex(nTxOverflow, 16);
  894. KernelLog.Ln;
  895. KernelLog.String(" Rx Missed Packet Counter = ");
  896. KernelLog.Int(Read32(4CH), 0);
  897. KernelLog.Ln;
  898. KernelLog.String(" nRxFrames = ");
  899. KernelLog.Int(nRxFrames, 0);
  900. KernelLog.Ln;
  901. KernelLog.String(" nTxFrames = ");
  902. KernelLog.Int(nTxFrames, 0);
  903. KernelLog.Ln;
  904. KernelLog.String(" nRxErrorFrames = ");
  905. KernelLog.Int(nRxErrorFrames, 0);
  906. KernelLog.Ln;
  907. KernelLog.String(" nTxErrorFrames = ");
  908. KernelLog.Int(nTxErrorFrames, 0);
  909. KernelLog.Ln;
  910. END PrintStatus;
  911. END Controller;
  912. VAR
  913. installedControllers: Controller;
  914. (* Scan the PCI bus for the specified card. *)
  915. PROCEDURE ScanPCI(vendor, device: LONGINT);
  916. VAR index, bus, dev, fct, irq, i: LONGINT; res: WORD; base: ADDRESS; d: LinkDevice; c: Controller; name: Plugins.Name;
  917. BEGIN
  918. index := 0;
  919. WHILE (PCI.FindPCIDevice(device, vendor, index, bus, dev, fct) = PCI.Done) & (installed < 16) DO
  920. res := PCI.ReadConfigDword(bus, dev, fct, PCI.Adr1Reg, i); ASSERT(res = PCI.Done);
  921. base := i; ASSERT(~ODD(base)); (* memory mapped *)
  922. DEC(base, base MOD 16);
  923. Machine.MapPhysical(base, 0FFH, base);
  924. res := PCI.ReadConfigByte(bus, dev, fct, PCI.IntlReg, irq); ASSERT(res = PCI.Done);
  925. NEW(d, Network.TypeEthernet, MaxETHFrameSize - 14, 6);
  926. name := Name;
  927. i := 0; WHILE name[i] # 0X DO INC(i) END;
  928. IF installed > 9 THEN
  929. name[i] := CHR(ORD("A") + installed - 10);
  930. ELSE
  931. name[i] := CHR(ORD("0") + installed);
  932. END;
  933. name[i+1] := 0X;
  934. IF DebugFind IN Debug THEN
  935. KernelLog.String("Found device: ");
  936. KernelLog.String(name);
  937. KernelLog.String("; IRQ = ");
  938. KernelLog.Int(irq, 0);
  939. KernelLog.Ln;
  940. END;
  941. d.SetName(name);
  942. d.desc := Description;
  943. NEW(c, d, base, irq); (* increments "installed" when successful *)
  944. IF DebugStatus IN Debug THEN
  945. c.PrintStatus;
  946. END;
  947. INC(index)
  948. END
  949. END ScanPCI;
  950. PROCEDURE Install*;
  951. BEGIN {EXCLUSIVE}
  952. IF DebugFind IN Debug THEN
  953. KernelLog.String("Searching devices...");
  954. KernelLog.Ln
  955. END;
  956. IF installed = 0 THEN
  957. ScanPCI(10ECH, 8169H); (* Vendor = RealTek, Device = RTL8169 *)
  958. END;
  959. IF DebugFind IN Debug THEN
  960. KernelLog.String("Find finished.");
  961. KernelLog.Ln
  962. END;
  963. END Install;
  964. PROCEDURE DebugStati*;
  965. VAR c: Controller;
  966. BEGIN
  967. c := installedControllers;
  968. WHILE c # NIL DO
  969. c.PrintStatus;
  970. c := c.next;
  971. END;
  972. END DebugStati;
  973. PROCEDURE TestDevices*;
  974. VAR c: Controller;
  975. BEGIN
  976. c := installedControllers;
  977. WHILE c # NIL DO
  978. TestDevice(c);
  979. c := c.next;
  980. END;
  981. END TestDevices;
  982. PROCEDURE TestDevice(ctrl: Controller);
  983. VAR
  984. i, diff, bytes, times: LONGINT;
  985. milliTimer : Kernel.MilliTimer;
  986. data: ARRAY 1024 OF CHAR;
  987. bw: REAL;
  988. dst: Network.LinkAdr;
  989. BEGIN
  990. dst[0] := 000X;
  991. dst[1] := 030X;
  992. dst[2] := 04FX;
  993. dst[3] := 025X;
  994. dst[4] := 0BBX;
  995. dst[5] := 0DBX;
  996. IF ctrl # NIL THEN
  997. ctrl.nRxFrames := 0;
  998. ctrl.nTxFrames := 0;
  999. (* fill the buffer *)
  1000. FOR i := 0 TO LEN(data)-1 DO
  1001. data[i] := CHR(i MOD 100H)
  1002. END;
  1003. Kernel.SetTimer(milliTimer, 0);
  1004. times := 1024 * 1024 * 2;
  1005. FOR i := 1 TO times DO
  1006. ctrl.SendFrame(dst, 0DEADH, data, data, data, 0, 0, 0, LEN(data));
  1007. IF i MOD 1024 = 0 THEN
  1008. Delay(1);
  1009. END;
  1010. END;
  1011. diff := Kernel.Elapsed(milliTimer);
  1012. times := ctrl.nRxFrames * 2;
  1013. bytes := (LEN(data));
  1014. KernelLog.String("stats:"); KernelLog.Ln;
  1015. KernelLog.String("frame size = ");
  1016. KernelLog.Int(bytes, 0);
  1017. KernelLog.String("; num frames = ");
  1018. KernelLog.Int(times, 0);
  1019. KernelLog.String("; time = ");
  1020. KernelLog.Int(diff, 0); KernelLog.String("ms");
  1021. KernelLog.String("; bandwidth = ");
  1022. bw := bytes * 1.0 * times / (diff / 1000.0);
  1023. KernelLog.Int(ENTIER(bw / 1024), 0); KernelLog.String("KB/s, ");
  1024. KernelLog.Int(ENTIER(bw * 8 / 1000 / 1000), 0); KernelLog.String("Mbps"); KernelLog.Ln;
  1025. END
  1026. END TestDevice;
  1027. PROCEDURE Cleanup;
  1028. BEGIN
  1029. WHILE installedControllers # NIL DO
  1030. IF DebugCleanup IN Debug THEN
  1031. KernelLog.Ln;
  1032. KernelLog.String("Removing ");
  1033. KernelLog.String(installedControllers.dev.name);
  1034. KernelLog.Ln;
  1035. installedControllers.PrintStatus;
  1036. END;
  1037. installedControllers.Finalize;
  1038. installedControllers := installedControllers.next;
  1039. IF DebugCleanup IN Debug THEN
  1040. KernelLog.String("Success!");
  1041. KernelLog.Ln;
  1042. END;
  1043. END;
  1044. installedControllers := NIL;
  1045. END Cleanup;
  1046. PROCEDURE Delay(ms: LONGINT);
  1047. VAR
  1048. t: Kernel.MilliTimer;
  1049. BEGIN
  1050. Kernel.SetTimer(t, ms);
  1051. REPEAT UNTIL Kernel.Expired(t);
  1052. END Delay;
  1053. BEGIN
  1054. Modules.InstallTermHandler(Cleanup);
  1055. END RTL8169.
  1056. (*
  1057. MAC address 00-30-4F-25-BB-DB
  1058. MAC address 00-08-A1-3C-06-CB
  1059. local IP 129.132.134.209
  1060. System.Free RTL8169 ~
  1061. RTL8169.Install ~
  1062. WMPerfMon.Open ~
  1063. RTL8169.DebugStati ~
  1064. IP.IPConfig ~
  1065. RTL8169.TestDevices~
  1066. OFSTools.Mount RAM RamFS 300000 4096 ~
  1067. TestNet.SetDevice "RTL8169#0" ~
  1068. TestNet.ShowDevices ~
  1069. TestNet.SendBroadcast ~
  1070. TestNet.SendBroadcastVar 1499 ~
  1071. TestNet.SendTest ^ 1 10 100 1000 ~
  1072. *)