RTL8139.Mod 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. MODULE RTL8139; (** AUTHOR "TF"; PURPOSE "Driver for RealTek RTL8139 Ethernet Controllers"; *)
  2. (* references :
  3. RTL 8139C(L) Preliminary, REALTEK Semiconductor Corp., Rev 1.1 1999/11/4
  4. RTL 8139(a/B) Programming guide (V0.1) 1999/1/15
  5. This driver is not optimized for speed. It has been tested on Chipset8139 and Chipset8139C. Please report success / failure with
  6. other 8139 compatible chipsets.
  7. *)
  8. IMPORT
  9. SYSTEM, Kernel, Machine, PCI, Objects, Modules, Plugins, Network, KernelLog
  10. , Files;
  11. CONST
  12. Name = "RTL8139#";
  13. Desc = "RealTek 8139 ethernet driver";
  14. Model8139 = 0; Model8139CB = 1; ModelSMC1211TX = 2; ModelDELTA8139 = 3; ModelADDTRON8139 = 4; ModelDFE528TX = 5;
  15. Model8129 = 7; MaxModel = 8;
  16. Chipset8139 = 0; Chipset8139K = 1; Chipset8139A = 2; Chipset8139B = 3; Chipset8130 = 4; Chipset8139C = 5;
  17. NofChipsets = 6;
  18. HasPwrDn = 0; HasLWake = 1;
  19. DebugFind = TRUE; DebugInit = TRUE; DebugCleanup = TRUE; DebugTransmit = FALSE; DebugReceive = FALSE;
  20. RegisterInNetwork = TRUE; CallNetworkReceiver = TRUE; Min60BytePacket = TRUE;
  21. ReceiveAll = FALSE;
  22. RxBufLenIdx = 2;
  23. RxBufLen = ASH(8192, RxBufLenIdx) ;
  24. RxBufPad = 16;
  25. RxBufWrapPad = 2048;
  26. RxBufSize = RxBufLen + RxBufPad + RxBufWrapPad;
  27. MaxETHFrameSize = 1514;
  28. MaxPacketsPerIRQ = 10;
  29. VAR
  30. installed: LONGINT; (* number of installed devices *)
  31. logtime: Kernel.MilliTimer;
  32. TYPE
  33. ChipsetSpecific = RECORD
  34. name: ARRAY 32 OF CHAR;
  35. version: LONGINT;
  36. configSet, flags: SET;
  37. END;
  38. VAR
  39. chipsetInfo: ARRAY MaxModel OF ChipsetSpecific;
  40. (* Interrupt statistics (only with one adapter) *)
  41. nPCIError, nTimeOut, nCableLengthChg, nFifoOverflow, nPUnOrLnkChg,
  42. nRxBufferOverflow, nTxError, nTxOk, nRxError, nRxOk :LONGINT;
  43. logging : BOOLEAN;
  44. log :Files.Rider;
  45. TYPE
  46. LinkDevice = OBJECT (Network.LinkDevice)
  47. VAR ctrl: Controller;
  48. PROCEDURE Linked*(): LONGINT;
  49. BEGIN
  50. IF ctrl.Linked() THEN
  51. RETURN Network.LinkLinked;
  52. ELSE
  53. RETURN Network.LinkNotLinked;
  54. END;
  55. END Linked;
  56. PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  57. VAR i: LONGINT; bufAdr: ADDRESS; txState:LONGINT; txs:SET; t, totlen:LONGINT;
  58. BEGIN {EXCLUSIVE}
  59. (* Disable IRQ *)
  60. SYSTEM.PUT16(ctrl.base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(ctrl.base + 3CH)))-{0..6, 13..15}));
  61. bufAdr:=ADDRESSOF(ctrl.txBuffers[ctrl.nextTxBuffer]^[0]);
  62. SYSTEM.MOVE(ADDRESSOF(dst[0]), bufAdr, 6);
  63. SYSTEM.MOVE(ADDRESSOF(local[0]), bufAdr+6, 6);
  64. SYSTEM.PUT16(bufAdr+12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
  65. i:=14;
  66. IF h3len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), bufAdr+i, h3len); INC(i, h3len) END;
  67. IF h4len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), bufAdr+i, h4len); INC(i, h4len) END;
  68. IF i + dlen < MaxETHFrameSize THEN
  69. SYSTEM.MOVE(ADDRESSOF(data[0]) + dofs, bufAdr + i, dlen); INC(i, dlen);
  70. END;
  71. IF Min60BytePacket THEN WHILE i<60 DO ctrl.txBuffers[ctrl.nextTxBuffer]^[i] := CHR(0); INC(i) END END;
  72. totlen := i;
  73. IF DebugTransmit THEN
  74. KernelLog.Enter; KernelLog.String("[TRANSMIT] Packet length:"); KernelLog.Int(i, 5); KernelLog.String(" data ..."); KernelLog.Ln;
  75. KernelLog.Buffer(ctrl.txBuffers[ctrl.nextTxBuffer]^, 0, i);
  76. KernelLog.Exit;
  77. END;
  78. IF i <= MaxETHFrameSize THEN
  79. SYSTEM.PUT32(ctrl.base + 20H+4*ctrl.nextTxBuffer, bufAdr); (* set Transmit Start Address *)
  80. txState:=8*32*2048; (* threshold 256 *)
  81. txState:=txState+i;
  82. SYSTEM.PUT32(ctrl.base + 10H+4*ctrl.nextTxBuffer, txState); (* send *)
  83. i:=0; WHILE (i<10000000) & (SYSTEM.VAL(SET, SYSTEM.GET32(ctrl.base+10H+4*ctrl.nextTxBuffer)) * {14, 15, 30} = {}) DO
  84. INC(i)
  85. END;
  86. IF i=10000000 THEN KernelLog.Enter; KernelLog.String("MegaError !!!"); KernelLog.Exit; ctrl.Reset END;
  87. IF DebugTransmit THEN
  88. KernelLog.Enter;
  89. IF i<10000000 THEN
  90. txs:=SYSTEM.VAL(SET, SYSTEM.GET32(ctrl.base+10H+4*ctrl.nextTxBuffer));
  91. IF 13 IN txs THEN KernelLog.String(" DMA Completed ") END;
  92. IF 14 IN txs THEN KernelLog.String(" Fifo underrun ") END;
  93. IF 15 IN txs THEN KernelLog.String(" Transmit OK ") END;
  94. IF 30 IN txs THEN KernelLog.String(" Transmit ABORTED ") END
  95. ELSE KernelLog.String("Transmit timed out ");
  96. KernelLog.Bits(SYSTEM.VAL(SET, SYSTEM.GET32(ctrl.base+10H+4*ctrl.nextTxBuffer)), 0, 32)
  97. END;
  98. KernelLog.Exit
  99. END;
  100. INC(sendCount);
  101. ctrl.nextTxBuffer := (ctrl.nextTxBuffer + 1) MOD 4
  102. END
  103. ;
  104. (* Enable IRQ *)
  105. SYSTEM.PUT16(ctrl.base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(ctrl.base + 3CH)))+{0..6, 13..15}));
  106. IF logging THEN
  107. t := Kernel.Elapsed(logtime);
  108. Files.WriteLInt(log, t DIV 1000);
  109. Files.WriteLInt(log, (t MOD 1000)*1000+1);
  110. Files.WriteLInt(log, totlen); Files.WriteLInt(log, totlen);
  111. log.file.WriteBytes(log, ctrl.txBuffers[ctrl.nextTxBuffer]^, 0, totlen)
  112. END
  113. END DoSend;
  114. PROCEDURE Finalize(connected: BOOLEAN);
  115. BEGIN
  116. ctrl.Finalize;
  117. Finalize^(connected);
  118. END Finalize;
  119. END LinkDevice;
  120. Controller = OBJECT
  121. VAR
  122. next: Controller;
  123. base: ADDRESS; irq: LONGINT;
  124. dev: LinkDevice;
  125. model, chipset: LONGINT;
  126. media: SET;
  127. rxBufPos: LONGINT;
  128. timer: Kernel.Timer;
  129. eepromAdrLen:LONGINT;
  130. devAdr:ARRAY 3 OF LONGINT;
  131. rxBuffer: POINTER TO ARRAY OF CHAR; (* ring buffer *)
  132. rxAdr: LONGINT; (* ring buffer physical adr *)
  133. nextTxBuffer: LONGINT;
  134. txBuffers: ARRAY 4 OF POINTER TO ARRAY OF CHAR;
  135. rcvAdr, rcvSize:LONGINT;
  136. PROCEDURE FlushWrite8(reg, val:LONGINT);
  137. BEGIN
  138. SYSTEM.PUT8(base + reg, val); (* force flush *) val := SYSTEM.GET8(base + reg)
  139. END FlushWrite8;
  140. PROCEDURE Reset;
  141. VAR dp, dummy:LONGINT; val:SET;
  142. BEGIN nextTxBuffer:=0;
  143. KernelLog.Enter; KernelLog.String("Softreset"); KernelLog.Exit;
  144. (* soft reset *)
  145. SYSTEM.PUT8(base + 37H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H)))) + {4})); (* command register: 4 soft reset *)
  146. dp:=0;
  147. LOOP INC(dp); timer.Sleep(1); IF (SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H)))) * {4} = {}) OR (dp=100) THEN EXIT END END;
  148. (* assert PIO and MMIO enabled *)
  149. val := SYSTEM.VAL(SET, SYSTEM.GET8(base + 52H));
  150. IF val * {3} = {} THEN KernelLog.String("MMIO is disabled."); HALT(1000) END;
  151. IF val * {2} = {} THEN KernelLog.String("IO mapping is disabled."); HALT(1000) END;
  152. (* enable Tx / Rx *)
  153. FlushWrite8(37H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H))))* {1, 5, 6, 7} + {2 , 3}));
  154. (* initialize the rxBuffer *)
  155. SYSTEM.PUT32(base + 30H, ADDRESSOF(rxBuffer[0]));
  156. rxBufPos:=0; SYSTEM.PUT16(base+38H, rxBufPos-16); dummy:=SYSTEM.GET16(base + 38H);
  157. (* initialize packet types *)
  158. (* IF ReceiveAll THEN SYSTEM.PUT32(base + 44H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) - {24..27, 13..15} + {24(*..27, 13..15*), 12, 8..10, 7, 0..4})
  159. ELSE SYSTEM.PUT32(base + 44H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) - {24..27, 13..15} + {24(*..27, 13..15*), 12, 8..10, 7, 1..4})
  160. END; *)
  161. IF ReceiveAll THEN
  162. SYSTEM.PUT32(base + 44H,
  163. SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) * chipsetInfo[chipset].configSet + {24(*..27, 13..15*), 12, 8..10, 7, 0..4})
  164. ELSE
  165. SYSTEM.PUT32(base + 44H,
  166. SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) * chipsetInfo[chipset].configSet + {24(*..27, 13..15*), 12, 8..10, 7, 1..4})
  167. END;
  168. dummy:=SYSTEM.GET32(base + 44H); (* flush *)
  169. (* Set MAC address *)
  170. SYSTEM.PUT32(base, Network.Get4(dev.local, 0)); dummy:=SYSTEM.GET32(base);
  171. SYSTEM.PUT32(base + 4, Network.Get4(dev.local, 4));dummy:=SYSTEM.GET32(base + 4);
  172. (* enable Tx interrupt for testing *)
  173. (* SYSTEM.PUT16(base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + 3CH)))+{2, 0, 4}));*)
  174. SYSTEM.PUT16(base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + 3CH)))+{0..6, 13..15}));
  175. (* Set Max DMA Burst Size*)
  176. SYSTEM.PUT32(base + 40H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 40H))+{9, 10});
  177. END Reset;
  178. PROCEDURE &Init*(dev: LinkDevice; base: ADDRESS; irq, model: LONGINT);
  179. VAR res: WORD; dp, ver, i, dummy: LONGINT; val, nval: SET;
  180. BEGIN
  181. SELF.next:=installedControllers; installedControllers:=SELF;
  182. NEW(timer);
  183. SELF.base := base; SELF.dev := dev; SELF.model := model; SELF.media := media; SELF.irq := irq;
  184. dev.ctrl := SELF;
  185. (* chipset:=Chipset8139; (*uncomment this line if the driver does not work. Maybe it will then still not work ;-) *) *)
  186. (* enable high power mode *)
  187. IF HasPwrDn IN chipsetInfo[chipset].flags THEN
  188. FlushWrite8(50H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 50H)))) + {7, 6})); (* config write enable *)
  189. SYSTEM.PUT8(base + 52H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 52H)))) - {0, 1})); (* config 1: 0 pwrdn, 1 sleep *)
  190. FlushWrite8(50H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 50H)))) - {7, 6})); (* config write disable *)
  191. ELSE
  192. val := SYSTEM.VAL(SET, SYSTEM.GET8(base + 52H)); nval := val;
  193. IF (HasLWake IN chipsetInfo[chipset].flags) & (1 IN val) THEN nval:=nval - {1} END;
  194. nval := nval + {0}; (* cfg1 pm enable *)
  195. IF nval # val THEN
  196. FlushWrite8(50H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 50H)))) + {7, 6})); (* config write enable *)
  197. SYSTEM.PUT8(base + 52H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 52H)))) - {0, 1})); (* config 1: 0 pwrdn, 1 sleep *)
  198. FlushWrite8(50H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 50H)))) - {7, 6})) (* config write disable *)
  199. END;
  200. IF (HasLWake IN chipsetInfo[chipset].flags) THEN
  201. SYSTEM.PUT8(base + 5AH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 5AH)))) - {2})) (* config 4: 2 lwptn *)
  202. END
  203. END;
  204. (* soft reset *)
  205. SYSTEM.PUT8(base + 37H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H)))) + {4})); (* command register: 4 soft reset *)
  206. dp:=0;
  207. LOOP INC(dp); timer.Sleep(1); IF (SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H)))) * {4} = {}) OR (dp=100) THEN EXIT END END;
  208. (* assert PIO and MMIO enabled *)
  209. val := SYSTEM.VAL(SET, SYSTEM.GET8(base + 52H));
  210. IF val * {3} = {} THEN KernelLog.String("MMIO is disabled."); HALT(1000) END;
  211. IF val * {2} = {} THEN KernelLog.String("IO mapping is disabled."); HALT(1000) END;
  212. (* get version *)
  213. chipset:=-1;
  214. ver := SYSTEM.GET8(base + 43H);
  215. i := 0; WHILE i < NofChipsets DO IF chipsetInfo[i].version = ver THEN chipset := i; i:=NofChipsets ELSE INC(i) END END;
  216. IF chipset = -1 THEN chipset:=Chipset8139; KernelLog.Enter; KernelLog.String("chipset version unknown... assuming RTL-8139"); KernelLog.Exit END;
  217. IF DebugInit THEN KernelLog.String("Chip version is: "); KernelLog.Hex(ver, 2); KernelLog.String(" "); KernelLog.String(chipsetInfo[chipset].name); KernelLog.Ln END;
  218. (* Install Interrupt handler *)
  219. IF DebugInit THEN KernelLog.String("Install IRQ Handler: "); KernelLog.Int(irq, 5); KernelLog.Ln END;
  220. IF (irq >= 1) & (irq <= 15) THEN Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+irq) END;
  221. NEW(rxBuffer, RxBufSize);
  222. (* enable Tx / Rx *)
  223. FlushWrite8(37H, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 37H))))* {1, 5, 6, 7} + {2 , 3}));
  224. (* initialize the rxBuffer *)
  225. SYSTEM.PUT32(base + 30H, ADDRESSOF(rxBuffer[0]));
  226. rxBufPos:=0; SYSTEM.PUT16(base+38H, rxBufPos-16); dummy:=SYSTEM.GET16(base + 38H);
  227. (* initialize packet types *)
  228. (* IF ReceiveAll THEN SYSTEM.PUT32(base + 44H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) - {24..27, 13..15} + {24(*..27, 13..15*), 12, 8..10, 7, 0..4})
  229. ELSE SYSTEM.PUT32(base + 44H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) - {24..27, 13..15} + {24(*..27, 13..15*), 12, 8..10, 7, 1..4})
  230. END; *)
  231. IF ReceiveAll THEN
  232. SYSTEM.PUT32(base + 44H,
  233. SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) * chipsetInfo[chipset].configSet + {24(*..27, 13..15*), 12, 8..10, 7, 0..4})
  234. ELSE
  235. SYSTEM.PUT32(base + 44H,
  236. SYSTEM.VAL(SET, SYSTEM.GET32(base + 44H)) * chipsetInfo[chipset].configSet + {24(*..27, 13..15*), 12, 8..10, 7, 1..4})
  237. END;
  238. dummy:=SYSTEM.GET32(base + 44H); (* flush *)
  239. FOR i:=0 TO 3 DO NEW(txBuffers[i], MaxETHFrameSize) END;
  240. FOR i := 0 TO 5 DO dev.broadcast[i] := 0FFX END;
  241. eepromAdrLen:=8; IF ReadEEPROM(0)#8129H THEN eepromAdrLen:=6 END;
  242. FOR i:=0 TO 2 DO devAdr[i]:=ReadEEPROM(7+i);
  243. dev.local[i*2]:=CHR(devAdr[i] MOD 256);dev.local[i*2+1]:=CHR(devAdr[i] DIV 256 MOD 256)
  244. END;
  245. dev.adrSize := 6;
  246. (* Set MAC address *)
  247. SYSTEM.PUT32(base, Network.Get4(dev.local, 0)); dummy:=SYSTEM.GET32(base);
  248. SYSTEM.PUT32(base + 4, Network.Get4(dev.local, 4));dummy:=SYSTEM.GET32(base + 4);
  249. (* MAR Multicast Filter Setup (33 33 xx xx xx xx) *)
  250. SYSTEM.PUT32(base + 8H, 0FFFF3333H);
  251. SYSTEM.PUT32(base + 0CH, 0FFFFFFFFH);
  252. (* enable Tx interrupt for testing *)
  253. (* SYSTEM.PUT16(base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + 3CH)))+{2, 0, 4}));*)
  254. SYSTEM.PUT16(base + 3CH, SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + 3CH)))+{1..6, 13..15}));
  255. (* Set Max DMA Burst Size*)
  256. SYSTEM.PUT32(base + 40H, SYSTEM.VAL(SET, SYSTEM.GET32(base + 40H))+{9, 10});
  257. (* Register with Network *)
  258. IF RegisterInNetwork THEN
  259. Network.registry.Add(dev, res);
  260. ASSERT(res = Plugins.Ok);
  261. INC(installed)
  262. END
  263. END Init;
  264. PROCEDURE ReadEEPROM(loc:LONGINT):LONGINT;
  265. VAR readCMD, data:SET; dummy, i:LONGINT;
  266. BEGIN
  267. readCMD := SYSTEM.VAL(SET, loc);
  268. IF eepromAdrLen = 6 THEN readCMD:=readCMD+{1+6, 2+6} ELSE readCMD:=readCMD+{1+8, 2+8} END;
  269. (* base+50H bit 3: EEPROM chip select; bit 2 EEPROM clock shift *)
  270. (* enable EEPROM access *)
  271. SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, {7})); SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, {7, 3}));
  272. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  273. (* setup read adress *)
  274. i := 4 + eepromAdrLen;
  275. WHILE i >= 0 DO
  276. IF i IN readCMD THEN SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, {7, 3, 1})) ELSE SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR,{7, 3})) END;
  277. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  278. IF i IN readCMD THEN SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR,{7, 3, 2, 1})) ELSE SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR,{7, 3, 2})) END; (* clock shift *)
  279. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  280. DEC(i)
  281. END;
  282. (* enb, chip select *)
  283. SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, {7, 3}));
  284. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  285. (* read 16 bit *)
  286. data:={};
  287. FOR i:=15 TO 0 BY -1 DO
  288. SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR,{7, 3, 2})); (* shift clock *)
  289. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  290. IF SYSTEM.VAL(SET, LONG(LONG(SYSTEM.GET8(base + 50H)))) * {0} = {0} THEN INCL(data, i) END;
  291. SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, {7, 3})); (* ~shift clock *)
  292. dummy:=SYSTEM.GET32(base+50H) (* delay *)
  293. END;
  294. (* disable EEPROM *)
  295. SYSTEM.PUT8(base+50H, SYSTEM.VAL(CHAR, -{3}));
  296. dummy:=SYSTEM.GET32(base+50H); (* delay *)
  297. RETURN SYSTEM.VAL(LONGINT, data)
  298. END ReadEEPROM;
  299. PROCEDURE ReadPacket;
  300. VAR rxInfo, pSize, pStart, dummy, i, type: LONGINT; t: LONGINT;
  301. buf : Network.Buffer;
  302. BEGIN
  303. i:=0;
  304. WHILE (i<MaxPacketsPerIRQ) & ~(0 IN SYSTEM.VAL(SET, SYSTEM.GET8(base + 37H))) DO
  305. rxInfo := Network.Get4(rxBuffer^, rxBufPos);
  306. pSize := (rxInfo DIV 65536) MOD 65536 - 4;
  307. pStart := rxBufPos + 4;
  308. IF DebugReceive THEN KernelLog.Enter; KernelLog.String("[RECEIVE] PSize is:"); KernelLog.Int(pSize, 4); KernelLog.Exit END;
  309. IF pSize # 0FFF0H THEN
  310. IF pSize < MaxETHFrameSize THEN
  311. IF DebugReceive THEN
  312. KernelLog.Enter;
  313. KernelLog.String("Read Packet ("); KernelLog.Int(pSize, 4); KernelLog.String(")"); KernelLog.Ln;
  314. KernelLog.Buffer(rxBuffer^, rxBufPos + 4, pSize);
  315. KernelLog.Exit
  316. END;
  317. IF logging THEN
  318. t := Kernel.Elapsed(logtime);
  319. Files.WriteLInt(log, t DIV 1000);
  320. Files.WriteLInt(log, (t MOD 1000)*1000+1);
  321. Files.WriteLInt(log, pSize); Files.WriteLInt(log, pSize);
  322. log.file.WriteBytes(log, rxBuffer^, rxBufPos + 4, pSize);
  323. END;
  324. type := Network.GetNet2(rxBuffer^, pStart + 6 + 6);
  325. IF DebugReceive THEN KernelLog.Enter; KernelLog.String("packet type:"); KernelLog.Hex(type, 2); KernelLog.Exit END;
  326. (* IF CallNetworkReceiver THEN
  327. dev.GetReceiver(type, handler, hSize); (* base method call *)
  328. IF hSize > pSize THEN hSize := pSize END;
  329. rcvAdr := ADDRESSOF(rxBuffer[pStart + 14 + hSize]);
  330. rcvSize := pSize - hSize - 14;
  331. INC(dev.recvCount);
  332. handler(dev, SYSTEM.VAL(Network.RecvHdr, rxBuffer[pStart+14]), pSize-14, type,
  333. SYSTEM.VAL(Network.LinkAdr, rxBuffer[pStart+6]));
  334. END; *)
  335. buf := Network.GetNewBuffer();
  336. IF buf # NIL THEN
  337. buf.ofs := 0;
  338. buf.len := pSize - 14;
  339. buf.src := SYSTEM.VAL(Network.LinkAdr, rxBuffer[pStart + 6]);
  340. buf.calcChecksum := {};
  341. Network.Copy(rxBuffer^, buf.data, pStart + 14, 0, pSize - 14);
  342. dev.QueueBuffer(buf, type);
  343. ELSE
  344. (* no more upcall buffers available *)
  345. END
  346. (* write buffer pos was here *)
  347. END
  348. END; (* ELSE DMA is still in action for this packet (Info: BSD-driver) *)
  349. (* write buffer *)
  350. rxBufPos:=(rxBufPos+pSize+8+3); rxBufPos:=(rxBufPos - (rxBufPos MOD 4)) MOD RxBufLen;
  351. SYSTEM.PUT16(base+38H, rxBufPos-16); dummy:=SYSTEM.GET16(base + 38H);
  352. INC(i)
  353. END;
  354. END ReadPacket;
  355. PROCEDURE HandleInterrupt;
  356. VAR status, ack:SET; dummy:LONGINT;
  357. BEGIN
  358. ack:={0};
  359. status:=SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + 3EH)));
  360. (* System Error: PCI bus error *)
  361. IF 15 IN status THEN
  362. Machine.AtomicInc(nPCIError)
  363. END;
  364. (* TimeOut: TCTR reaches value of TimerInt register *)
  365. IF 14 IN status THEN
  366. Machine.AtomicInc(nTimeOut); INCL(ack, 14);
  367. END;
  368. (* Cable length changed *)
  369. IF 13 IN status THEN
  370. Machine.AtomicInc(nCableLengthChg); INCL(ack, 13)
  371. END;
  372. (* Rx FIFO overflow *)
  373. IF 6 IN status THEN
  374. INCL(ack, 4); INCL(ack, 6); INCL(ack, 0);
  375. Machine.AtomicInc(nFifoOverflow);
  376. END;
  377. (* Packet underrun or link changed *)
  378. IF 5 IN status THEN Reset;
  379. Machine.AtomicInc(nPUnOrLnkChg); INCL(ack, 5)
  380. END;
  381. (* Rx buffer overflow *)
  382. IF 4 IN status THEN (* Reset; *)
  383. Machine.AtomicInc(nRxBufferOverflow);
  384. INCL(ack, 0); INCL(ack, 4);
  385. END;
  386. (* Transmit error: packet transmission aborted (too many collisions) *)
  387. IF 3 IN status THEN
  388. Machine.AtomicInc(nTxError); INCL(ack, 3)
  389. END;
  390. (* Transmit ok *)
  391. IF 2 IN status THEN
  392. Machine.AtomicInc(nTxOk);
  393. INCL(ack, 2)
  394. END;
  395. (* Receive Error: CRC error or alignment error *)
  396. IF 1 IN status THEN
  397. Machine.AtomicInc(nRxError); INCL(ack, 1)
  398. END;
  399. (* receive ok *)
  400. IF 0 IN status THEN
  401. Machine.AtomicInc(nRxOk);
  402. ReadPacket;
  403. INCL(ack, 0);
  404. END;
  405. SYSTEM.PUT16(base + 3EH, SYSTEM.VAL(LONGINT, ack));
  406. dummy:=SYSTEM.GET16(base + 3EH);
  407. END HandleInterrupt;
  408. PROCEDURE Finalize;
  409. BEGIN
  410. (* disable all interrupts *)
  411. SYSTEM.PUT16(base + 3CH, 0);
  412. timer.Sleep(1000); (* hope the interrupt will be over, then *)
  413. IF DebugCleanup THEN KernelLog.String("Remove IRQ Handler."); KernelLog.Ln END;
  414. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0+irq);
  415. IF RegisterInNetwork THEN Network.registry.Remove(dev) END
  416. END Finalize;
  417. PROCEDURE Linked(): BOOLEAN;
  418. BEGIN
  419. RETURN ~(2 IN SYSTEM.VAL(SET, SYSTEM.GET8(base + 58H)));
  420. END Linked;
  421. END Controller;
  422. VAR
  423. installedControllers: Controller;
  424. (* Scan the PCI bus for the specified card. *)
  425. PROCEDURE ScanPCI(vendor, device, model: LONGINT);
  426. VAR index, bus, dev, fct, irq, i: LONGINT; res: WORD; base: ADDRESS; d: LinkDevice; c: Controller; name: Plugins.Name;
  427. BEGIN
  428. index := 0;
  429. WHILE (PCI.FindPCIDevice(device, vendor, index, bus, dev, fct) = PCI.Done) & (installed < 10) DO
  430. res := PCI.ReadConfigDword(bus, dev, fct, PCI.Adr1Reg, i); ASSERT(res = PCI.Done);
  431. base := i; ASSERT(~ODD(base)); (* memory mapped *)
  432. DEC(base, base MOD 16);
  433. Machine.MapPhysical(base, 0FFH, base);
  434. res := PCI.ReadConfigByte(bus, dev, fct, PCI.IntlReg, irq); ASSERT(res = PCI.Done);
  435. NEW(d, Network.TypeEthernet, MaxETHFrameSize - 14, 6);
  436. name := Name;
  437. i := 0; WHILE name[i] # 0X DO INC(i) END;
  438. name[i] := CHR(ORD("0") + installed);
  439. name[i+1] := 0X;
  440. d.SetName(name);
  441. d.desc := Desc;
  442. IF DebugFind THEN KernelLog.String("Found model nr :"); KernelLog.Int(model, 4); KernelLog.Ln END;
  443. NEW(c, d, base, irq, model); (* increments "installed" when successful *)
  444. INC(index)
  445. END
  446. END ScanPCI;
  447. PROCEDURE Install*;
  448. BEGIN {EXCLUSIVE}
  449. IF installed = 0 THEN
  450. IF DebugFind THEN KernelLog.String("Searching devices..."); KernelLog.Ln END;
  451. ScanPCI(10ECH, 8139H, Model8139);
  452. ScanPCI(10ECH, 8138H, Model8139CB);
  453. ScanPCI(1113H, 1211H, ModelSMC1211TX);
  454. ScanPCI(1500H, 1360H, ModelDELTA8139);
  455. ScanPCI(4033H, 1360H, ModelADDTRON8139);
  456. ScanPCI(1186H, 1300H, ModelDFE528TX);
  457. ScanPCI(10ECH, 8129H, Model8129);
  458. IF DebugFind THEN KernelLog.String("Find finished."); KernelLog.Ln END;
  459. END;
  460. END Install;
  461. PROCEDURE StartLog*;
  462. VAR f: Files.File;
  463. BEGIN
  464. Kernel.SetTimer(logtime, 0);
  465. f := Files.New("EtherNet.Log"); f.Set(log, 0); Files.Register(f); (* tcpdump compatible log file *)
  466. Files.WriteLInt(log, LONGINT(0A1B2C3D4H)); Files.WriteInt(log, 2);
  467. Files.WriteInt(log, 4); Files.WriteLInt(log, 0); Files.WriteLInt(log, 0);
  468. Files.WriteLInt(log, 1514); Files.WriteLInt(log, 1);
  469. logging := TRUE;
  470. KernelLog.Enter; KernelLog.String("EtherNet log started --> dumping to EtherNet.Log."); KernelLog.Exit
  471. END StartLog;
  472. PROCEDURE StopLog*;
  473. BEGIN
  474. logging:=FALSE;
  475. KernelLog.Enter; KernelLog.String("EtherNet log stopped."); KernelLog.Exit
  476. END StopLog;
  477. PROCEDURE Cleanup;
  478. BEGIN
  479. WHILE installedControllers # NIL DO installedControllers.Finalize; installedControllers:=installedControllers.next END
  480. END Cleanup;
  481. BEGIN
  482. Modules.InstallTermHandler(Cleanup);
  483. chipsetInfo[Chipset8139].name := "RTL-8139"; chipsetInfo[Chipset8139].version := 40H;
  484. chipsetInfo[Chipset8139].flags := {HasPwrDn}; chipsetInfo[Chipset8139].configSet:={28..31, 17..23, 6};
  485. chipsetInfo[Chipset8139B].name := "RTL-8139B"; chipsetInfo[Chipset8139B].version := 78H;
  486. chipsetInfo[Chipset8139B].flags := {HasLWake}; chipsetInfo[Chipset8139B].configSet:={28..31, 17..22, 6};
  487. chipsetInfo[Chipset8139A].name := "RTL-8139A"; chipsetInfo[Chipset8139A].version := 70H;
  488. chipsetInfo[Chipset8139A].flags := {}; chipsetInfo[Chipset8139A].configSet:={28..31, 17..26, 6};
  489. chipsetInfo[Chipset8139C].name := "RTL-8139C"; chipsetInfo[Chipset8139C].version := 74H;
  490. chipsetInfo[Chipset8139C].flags := {HasLWake}; chipsetInfo[Chipset8139C].configSet:={28..31, 17..22, 6};
  491. END RTL8139.
  492. System.Free RTL8139 ~
  493. RTL8139.Install
  494. System.OpenKernelLog
  495. TestNet.Mod
  496. TestNet.SetDevice "RTL8139#0"