BIOS.AM79C970.Mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. MODULE AM79C970;
  2. (* Aos Driver for AMD 79C970 (simulated by VMware) *)
  3. IMPORT
  4. SYSTEM, Machine, PCI, Objects, Modules, Plugins, Network, KernelLog;
  5. CONST
  6. Name = "AM79C970#";
  7. Description = "AMD Network Driver, Chipversion AM79C970A";
  8. MaxETHFrameSize = 1514;
  9. TxBufSize = 1600; (* Max size of tx buffers *)
  10. RxBufSize =1536; (* Max size for received frames *)
  11. RxRingSize = 32;
  12. TxRingSize = 16;
  13. ModeDRX = 0; (* disable rx *)
  14. ModeDTX = 1; (* disable tx *)
  15. ModePROM = 15; (* promiscuous mode *)
  16. (* 16 bit resources *)
  17. RAP=12H;
  18. RDP=10H;
  19. BDP=16H;
  20. RESET=14H;
  21. CSR0 = 0; (* control and status register *)
  22. OWN = 31;
  23. VAR
  24. installed: LONGINT; (* number of installed devices *)
  25. installFinished: BOOLEAN;
  26. outPackets, inPackets, missedFrames: LONGINT;
  27. TYPE
  28. (* 32bit Initializationblock, p. 989*)
  29. InitializationBlock = RECORD
  30. modeTlenRlen : SET;
  31. padr : ARRAY 3 OF INTEGER;
  32. reserved : INTEGER;
  33. ladr : ARRAY 2 OF SET;
  34. rdra : Machine.Address32;
  35. tdra : Machine.Address32;
  36. END;
  37. (* buffer for transmission*)
  38. TxBuffer = POINTER TO ARRAY TxBufSize OF CHAR;
  39. (* LinkDevice: interface to Bluebottle *)
  40. LinkDevice = OBJECT (Network.LinkDevice)
  41. VAR
  42. ctrl: Controller;
  43. hw: LONGINT;
  44. PROCEDURE Linked*(): LONGINT;
  45. BEGIN
  46. IF ctrl.Linked() THEN
  47. RETURN Network.LinkLinked;
  48. ELSE
  49. RETURN Network.LinkNotLinked;
  50. END;
  51. END Linked;
  52. PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  53. VAR
  54. i, pos: LONGINT;
  55. tBuf: TxBuffer;
  56. flags1: SET;
  57. BEGIN
  58. INC(outPackets);
  59. tBuf := ctrl.txBufRing[ctrl.txIndex];
  60. ctrl.DisableInterrupts();
  61. pos := 0;
  62. (* set up ethernet header *)
  63. FOR i := 0 TO 6 - 1 DO tBuf[pos + i] := dst[i] END;
  64. INC(pos, 6);
  65. FOR i := 0 TO 6 - 1 DO tBuf[pos + i] := local[i] END;
  66. INC(pos, 6);
  67. tBuf[pos] := CHR(type DIV 100H);
  68. INC(pos);
  69. tBuf[pos] := CHR(type MOD 100H);
  70. INC(pos);
  71. (* insert l3hdr into buffer data field *)
  72. FOR i := 0 TO h3len - 1 DO
  73. tBuf[pos+i] := l3hdr[i]
  74. END;
  75. INC(pos, h3len);
  76. (* insert l4hdr into buffer data field *)
  77. FOR i := 0 TO h4len - 1 DO
  78. tBuf[pos + i] := l4hdr[i]
  79. END;
  80. INC(pos, h4len);
  81. (* insert data into buffer data field *)
  82. FOR i := 0 TO dlen - 1 DO
  83. tBuf[pos + i] := data[i + dofs];
  84. END;
  85. INC(pos, dlen);
  86. flags1 := SYSTEM.VAL(SET, -pos) - {16..31} + {OWN} + {25, 24};
  87. SYSTEM.PUT32(ctrl.txRingAdr + ctrl.txIndex * 16 + 4, flags1);
  88. ctrl.txIndex:=(ctrl.txIndex+1) MOD TxRingSize;
  89. (* trigger immediate send poll *)
  90. ctrl.WriteCSR(0,58);
  91. ctrl.EnableInterrupts();
  92. END DoSend;
  93. PROCEDURE Finalize(connected: BOOLEAN);
  94. BEGIN
  95. ctrl.Finalize;
  96. Finalize^(connected);
  97. END Finalize;
  98. END LinkDevice;
  99. (* Controller: interface to the AM79C970 hardware *)
  100. Controller = OBJECT
  101. VAR
  102. next: Controller; (* next controller in list *)
  103. base, irq: LONGINT;
  104. dev: LinkDevice;
  105. initBlock: InitializationBlock;
  106. rxAlignDescriptorRing: POINTER TO ARRAY (RxRingSize+1)*16 OF CHAR;
  107. txAlignDescriptorRing: POINTER TO ARRAY (TxRingSize+1)*16 OF CHAR;
  108. (* actual ring starting address (16 byte aligned!) *)
  109. rxRingAdr: ADDRESS;
  110. txRingAdr: ADDRESS;
  111. (* buffer rings (parallel to descriptors..) *)
  112. txBufRing: ARRAY TxRingSize OF TxBuffer;
  113. rxBufRing: ARRAY RxRingSize OF Network.Buffer;
  114. (* index to point to current descriptor entry/ current buffer *)
  115. rxIndex, txIndex : LONGINT;
  116. PROCEDURE &Init*(dev: LinkDevice; base, irq: LONGINT);
  117. VAR
  118. res: WORD;
  119. s: SET;
  120. i,x: INTEGER;
  121. BEGIN
  122. outPackets:=0;
  123. inPackets:=0;
  124. missedFrames:= 0;
  125. (* set ethernet broadcast address: FF-FF-FF-FF-FF-FF *)
  126. FOR i := 0 TO 5 DO dev.broadcast[i] := 0FFX END;
  127. (* update list of installed controllers, insert at head *)
  128. SELF.next := installedControllers;
  129. installedControllers := SELF;
  130. SELF.base := base;
  131. SELF.dev := dev;
  132. SELF.irq := irq;
  133. dev.ctrl := SELF;
  134. (* install Interrupthandler *)
  135. IF (irq >= 1) & (irq <= 15) THEN
  136. Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+irq);
  137. END;
  138. (* 16 Bit Software Reset *)
  139. Machine.Portin16(base + RESET, x);
  140. (* make sure S-Reset has set STOP (2) to initialize registers *)
  141. ASSERT(ReadCSR(0)=4);
  142. (* this Chip needs 16 Bit IO-Resources *)
  143. ASSERT(DeviceOk());
  144. (* Setup Init Block *)
  145. (* Rx/Tx disabled *)
  146. initBlock.modeTlenRlen := {ModePROM, ModeDTX, ModeDRX};
  147. (* TLEN 16, RLEN 32 *)
  148. initBlock.modeTlenRlen := initBlock.modeTlenRlen + {30} + {22} + {20};
  149. (* PADR - read the MAC address and set to the init block *)
  150. Machine.Portin16(base, x);
  151. dev.local[0] := CHR(x MOD 100H);
  152. dev.local[1] := CHR(x DIV 100H);
  153. initBlock.padr[0] := x;
  154. Machine.Portin16(base + 2, x);
  155. dev.local[2] := CHR(x MOD 100H);
  156. dev.local[3] := CHR(x DIV 100H);
  157. initBlock.padr[1] := x;
  158. Machine.Portin16(base + 4, x);
  159. dev.local[4] := CHR(x MOD 100H);
  160. dev.local[5] := CHR(x DIV 100H);
  161. initBlock.padr[2] := x;
  162. (* Logical Address Filter *)
  163. initBlock.ladr[0] := SYSTEM.VAL(SET, 0H);
  164. initBlock.ladr[1] := SYSTEM.VAL(SET, 0H);
  165. (* Descriptor Ring Addresses *)
  166. NEW(rxAlignDescriptorRing);
  167. rxRingAdr := ADDRESSOF(rxAlignDescriptorRing[0]);
  168. IF rxRingAdr MOD 16 # 0 THEN
  169. INC(rxRingAdr, 16 - rxRingAdr MOD 16);
  170. END;
  171. initBlock.rdra := Machine.Ensure32BitAddress (rxRingAdr);
  172. NEW(txAlignDescriptorRing);
  173. txRingAdr := ADDRESSOF(txAlignDescriptorRing[0]);
  174. IF txRingAdr MOD 16 # 0 THEN
  175. INC(txRingAdr, 16 - txRingAdr MOD 16);
  176. END;
  177. initBlock.tdra := Machine.Ensure32BitAddress (txRingAdr);
  178. (*Switch to 32bit mode. SSIZE32=1 *)
  179. WriteBCR(20, 2);
  180. (*write CSR1 (InitBlock Lower Address) *)
  181. s := SYSTEM.VAL(SET, ADDRESSOF(initBlock));
  182. x := SYSTEM.VAL(INTEGER, ADDRESSOF(initBlock) MOD 10000H);
  183. WriteCSR(1, x);
  184. (*write CSR2 (InitBlock Upper Address) *)
  185. x:= SYSTEM.VAL(INTEGER, ADDRESSOF(initBlock) DIV 10000H);
  186. WriteCSR(2, x);
  187. (* Set INIT bit (0) in CSR0 in order to start initialization*)
  188. WriteCSR(CSR0, 1);
  189. (* wait for IDON bit (8) in CSR0 *)
  190. i := 0;
  191. REPEAT
  192. INC(i)
  193. UNTIL (8 IN SYSTEM.VAL(SET, ReadCSR(CSR0))) OR (i > 1000);
  194. ASSERT( i < 1000) ; (* check for timeout *)
  195. WriteCSR(CSR0, 42H);
  196. SetupRxTxRings();
  197. (* register device with Network (res gets set) *)
  198. Network.registry.Add(dev, res);
  199. ASSERT(res = Plugins.Ok);
  200. INC(installed);
  201. END Init;
  202. PROCEDURE ReadCSR(nr:INTEGER) : INTEGER;
  203. VAR x: INTEGER;
  204. BEGIN
  205. Machine.Portout16(base + RAP, nr); (* write address *)
  206. Machine.Portin16(base + RDP, x); (* read value *)
  207. RETURN x;
  208. END ReadCSR;
  209. PROCEDURE WriteCSR(nr, val : INTEGER);
  210. BEGIN
  211. Machine.Portout16(base + RAP, nr); (* write address *)
  212. Machine.Portout16(base + RDP, val); (* read value *)
  213. END WriteCSR;
  214. PROCEDURE ReadBCR(nr: INTEGER) : INTEGER;
  215. VAR x : INTEGER;
  216. BEGIN
  217. Machine.Portout16(base + RAP, nr);
  218. Machine.Portin16(base + BDP, x);
  219. RETURN x;
  220. END ReadBCR;
  221. PROCEDURE WriteBCR(nr, val : INTEGER);
  222. BEGIN
  223. Machine.Portout16(base + RAP, nr);
  224. Machine.Portout16(base + BDP, val);
  225. END WriteBCR;
  226. PROCEDURE DeviceOk() : BOOLEAN;
  227. VAR x : INTEGER;
  228. BEGIN
  229. x := 88;
  230. Machine.Portout16(base + RAP, x);
  231. Machine.Portin16(base + RAP, x);
  232. RETURN x = 88
  233. END DeviceOk;
  234. PROCEDURE SetupRxTxRings;
  235. VAR
  236. i: LONGINT;
  237. adr: ADDRESS;
  238. t: SET;
  239. rBuf: Network.Buffer;
  240. tBuf: TxBuffer;
  241. BEGIN
  242. rxIndex := 0;
  243. txIndex := 0;
  244. (* Rx/Tx descriptor see p. 991-996*)
  245. adr := rxRingAdr;
  246. FOR i:=0 TO RxRingSize-1 DO
  247. rBuf:=Network.GetNewBuffer();
  248. rxBufRing[i] := rBuf;
  249. SYSTEM.PUT32(adr, ADDRESSOF(rBuf.data[0])); INC(adr, 4);
  250. SYSTEM.PUT16(adr, -RxBufSize); INC(adr, 2);
  251. SYSTEM.PUT16(adr, 8000H); INC(adr, 2);
  252. SYSTEM.PUT32(adr, 0); INC(adr, 4);
  253. SYSTEM.PUT32(adr, 0); INC(adr, 4)
  254. END;
  255. t:= SYSTEM.VAL(SET, 0FFFH-TxBufSize+1)+{12..15};
  256. adr := txRingAdr;
  257. FOR i:=0 TO TxRingSize-1 DO
  258. NEW(tBuf);
  259. txBufRing[i] := tBuf;
  260. SYSTEM.PUT32(adr, ADDRESSOF(tBuf[0])); INC(adr, 4);
  261. SYSTEM.PUT32(adr, t); INC(adr, 4);
  262. SYSTEM.PUT32(adr, 0); INC(adr, 4);
  263. SYSTEM.PUT32(adr, 0); INC(adr, 4)
  264. END;
  265. (* stop chip and write some BMU related registers bit.*)
  266. HWStop();
  267. (* enable Rx/Tx, clear bits 0 and 1. This will automatically set TXON and RXON bits in CSR0*)
  268. WriteCSR(15, 0);
  269. (* enable polling (and some other stuff) *)
  270. WriteCSR(4, 915H);
  271. HWStart();
  272. END SetupRxTxRings;
  273. PROCEDURE UpdateTxRing;
  274. VAR
  275. i:LONGINT;
  276. flags1, flags2: SET;
  277. BEGIN
  278. i := 0;
  279. WHILE i < TxRingSize DO
  280. flags1 := SYSTEM.VAL(SET, SYSTEM.GET32(txRingAdr + i * 16 + 4));
  281. flags2 := SYSTEM.VAL(SET, SYSTEM.GET32(txRingAdr + i * 16 + 8));
  282. IF ~(31 IN flags1) THEN
  283. SYSTEM.PUT32(txRingAdr+ i * 16+4,SYSTEM.VAL(SET, 0FFFH-TxBufSize+1)+{12..15});
  284. SYSTEM.PUT32(txRingAdr+i*16+8, 0);
  285. END;
  286. INC(i);
  287. END;
  288. END UpdateTxRing;
  289. (* read all frames that are marked with OWN = 0*)
  290. PROCEDURE ReceivePacket;
  291. VAR
  292. type, size: LONGINT;
  293. rBuf, buf: Network.Buffer;
  294. flags1, flags2:SET;
  295. BEGIN
  296. DisableInterrupts();
  297. flags1 := SYSTEM.VAL(SET,SYSTEM.GET32(rxRingAdr + rxIndex * 16 + 4));
  298. flags2 := SYSTEM.VAL(SET,SYSTEM.GET32(rxRingAdr + rxIndex * 16 + 8));
  299. WHILE ~(31 IN flags1) DO
  300. INC(inPackets);
  301. buf := Network.GetNewBuffer();
  302. IF buf # NIL THEN
  303. rBuf:=rxBufRing[rxIndex];
  304. size:= SYSTEM.VAL(INTEGER,flags2);
  305. type := Network.GetNet2(rBuf.data, 6 + 6);
  306. rBuf.ofs:= 14;
  307. rBuf.len:= size;
  308. rBuf.src:= SYSTEM.VAL(Network.LinkAdr, rBuf.data[6]);
  309. rBuf.calcChecksum:= {};
  310. dev.QueueBuffer(rBuf, type);
  311. rxBufRing[rxIndex]:=buf;
  312. SYSTEM.PUT32(rxRingAdr+ rxIndex * 16, ADDRESSOF(buf.data[0]));
  313. SYSTEM.PUT32(rxRingAdr+ rxIndex * 16+4,SYSTEM.VAL(SET, 0FFFH-RxBufSize+1)+{12..15}+{31});
  314. SYSTEM.PUT32(rxRingAdr+ rxIndex * 16+8, 0);
  315. ELSE
  316. (* no more upcall buffers available, so do not queue the old one *)
  317. KernelLog.String("NO MORE BUFFERS!!!!!!!"); KernelLog.Ln;
  318. END;
  319. rxIndex:=(rxIndex+1) MOD RxRingSize;
  320. flags1 := SYSTEM.VAL(SET,SYSTEM.GET32(rxRingAdr + rxIndex * 16 + 4));
  321. flags2 := SYSTEM.VAL(SET,SYSTEM.GET32(rxRingAdr + rxIndex * 16 + 8));
  322. END;
  323. EnableInterrupts();
  324. END ReceivePacket;
  325. PROCEDURE HWStop;
  326. BEGIN
  327. WriteCSR(CSR0, 4);
  328. END HWStop;
  329. PROCEDURE HWStart;
  330. BEGIN
  331. WriteCSR(15, SYSTEM.VAL(INTEGER, {ModePROM}));
  332. WriteCSR(CSR0, SYSTEM.VAL(INTEGER, {1, 6}))
  333. END HWStart;
  334. PROCEDURE DisableInterrupts;
  335. VAR
  336. x: INTEGER;
  337. BEGIN
  338. x:=ReadCSR(0);
  339. WriteCSR(0, SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET, x)-{6}-{14}-{13}-{12}-{11}-{10}-{9})); (* do not clear the interrupt bits *)
  340. END DisableInterrupts;
  341. PROCEDURE EnableInterrupts;
  342. VAR
  343. x: INTEGER;
  344. BEGIN
  345. x:=ReadCSR(0);
  346. WriteCSR(0, SYSTEM.VAL(INTEGER, SYSTEM.VAL(SET, x)+{6}-{14}-{13}-{12}-{11}-{10}-{9}));
  347. END EnableInterrupts;
  348. PROCEDURE HandleInterrupt;
  349. VAR
  350. status : INTEGER;
  351. BEGIN
  352. status:=ReadCSR( 0);
  353. (* TINT *)
  354. IF (9 IN SYSTEM.VAL(SET,status)) THEN
  355. UpdateTxRing();
  356. END;
  357. (* RINT *)
  358. IF (10 IN SYSTEM.VAL(SET,status)) THEN
  359. ReceivePacket();
  360. END;
  361. (* MISS - if a frame got lost, increment counter *)
  362. IF (12 IN SYSTEM.VAL(SET,status)) THEN
  363. INC(missedFrames);
  364. END;
  365. (* to clear interrupts write 1 to according bits *)
  366. status:=ReadCSR(0);
  367. WriteCSR(0, status);
  368. END HandleInterrupt;
  369. PROCEDURE Linked():BOOLEAN;
  370. BEGIN
  371. RETURN TRUE;
  372. END Linked;
  373. PROCEDURE Finalize;
  374. BEGIN
  375. (* cleanup Network registry and remove interrupthandler*)
  376. Network.registry.Remove(dev);
  377. DEC(installed);
  378. Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0 + irq);
  379. END Finalize;
  380. END Controller;
  381. VAR
  382. installedControllers: Controller;
  383. (* Scan the PCI bus for the specified card. *)
  384. PROCEDURE ScanPCI(vendor, device: LONGINT);
  385. VAR
  386. index, bus, dev, fct, res, base, irq, i: LONGINT;
  387. d: LinkDevice;
  388. c: Controller;
  389. name: Plugins.Name;
  390. BEGIN
  391. index := 0; (*returns the first card found. If index was 1, it would return the second one.. *)
  392. WHILE (PCI.FindPCIDevice(device, vendor, index, bus, dev, fct) = PCI.Done) & (installed < 16) DO
  393. res := PCI.ReadConfigDword(bus, dev, fct, PCI.Adr0Reg, base); (* read offset 10H (PCI.Adr0Reg) from PCI Registers *)
  394. ASSERT (res = PCI.Done);
  395. ASSERT(ODD(base)); (* I/O mapped *)
  396. DEC(base, base MOD 4); (* strip lower 2 bits *)
  397. res := PCI.ReadConfigByte(bus, dev, fct, PCI.IntlReg, irq);
  398. ASSERT(res = PCI.Done);
  399. NEW(d, Network.TypeEthernet, MaxETHFrameSize - 14, 6);
  400. name := Name;
  401. i := 0;
  402. WHILE name[i] # 0X DO INC(i) END;
  403. IF installed > 9 THEN
  404. name[i] := CHR(ORD("A") + installed - 10);
  405. ELSE
  406. name[i] := CHR(ORD("0") + installed);
  407. END;
  408. name[i+1] := 0X;
  409. KernelLog.String("Found device: "); KernelLog.String(name); KernelLog.String("; IRQ = "); KernelLog.Int(irq, 0); KernelLog.Ln;
  410. res:=PCI.WriteConfigDword(bus, dev, fct, PCI.CmdReg, 5); (* enable bus master and IO Space access *)
  411. d.SetName(name);
  412. d.desc := Description;
  413. NEW(c, d, base, irq); (* increments "installed" when successful *)
  414. INC(index);
  415. END
  416. END ScanPCI;
  417. PROCEDURE Install*;
  418. BEGIN {EXCLUSIVE}
  419. IF installed = 0 THEN
  420. ScanPCI(1022H, 2000H); (* Vendor = AMD, Device = 79C970 *)
  421. END;
  422. END Install;
  423. PROCEDURE Cleanup; (*(par : ANY) :ANY;*)
  424. BEGIN
  425. WHILE installedControllers # NIL DO
  426. KernelLog.String("Removing "); KernelLog.String(installedControllers.dev.name); KernelLog.Ln;
  427. installedControllers.Finalize;
  428. installedControllers := installedControllers.next;
  429. KernelLog.String("Outgoing packets: "); KernelLog.Int(outPackets,0); KernelLog.Ln;
  430. KernelLog.String("Incoming packets: "); KernelLog.Int(inPackets,0); KernelLog.Ln;
  431. KernelLog.String("Missed packets: "); KernelLog.Int(missedFrames,0); KernelLog.Ln;
  432. KernelLog.String("Success!"); KernelLog.Ln;
  433. END;
  434. installedControllers := NIL;
  435. END Cleanup;
  436. (* executed at module load *)
  437. BEGIN
  438. installFinished:=FALSE;
  439. Modules.InstallTermHandler(Cleanup);
  440. END AM79C970.
  441. (*
  442. SystemTools.Free AM79C970~
  443. AM79C970.Install ~
  444. *)