123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893 |
- MODULE Intel8255x;
- (*
- Aos driver for Intel 8255x Ethernet Controllers
- Reference: Intel, "Intel 8255x 10/100 Mbps Ethernet Controller Family, Open Source Software Developer Manual,
- Revision 1.0, January 2003"
- *)
- IMPORT SYSTEM, Kernel, Machine, PCI, Objects, Modules, Plugins, Network, KernelLog;
- CONST
- Name = "Intel8255x#";
- Desc = "Intel 8255x Ethernet Driver";
- K = 1024;
- MaxETHFrameSize = 1514;
- RxRingSize = 100;
- TxRingSize = 100;
- MaxTxTrials = 5;
- SizeOfConfigCmdHdr = 32;
- SizeOfNOPCmdHdr = 8;
- SizeOfIASetupCmdHdr = 16;
- SizeOfTxCmdHdr = 16;
- SizeOfRFDHdr = 16;
- keepMasks = TRUE;
- (* device registers *)
- SCBStatus = 0H;
- SCBCommand = 2H;
- SCBGenPtr = 4H;
- SCBEeprom = 0EH;
- PORTReg = 8H;
- (* ack bits *)
- CX = {15};
- FR = {14};
- CNA = {13};
- RNR = {12};
- MDI = {11};
- SWI = {10};
- (* interrupt masks *)
- CXMask = {31};
- FRMask = {30};
- CNAMask = {29};
- RNRMask = {28};
- ERMask = {27};
- FCPMask = {26};
- MaskAllIntr = {24};
- UnMaskAllIntr = {};
- (* generate software interrupt *)
- SI = {25};
- (* CU Commands *)
- CUNop = {};
- CUStart = {20};
- CUResume = {21};
- CULoadBase = {21, 22};
- (* RU Commands *)
- RUNop = {};
- RUStart = {16};
- RUResume = {17};
- RUAbort = {18};
- RULoadBase = {17, 18};
- (* CU States *)
- CUIdle = {};
- CUSuspended = {6};
- (* RU States *)
- RUIdle = {};
- RUSuspended = {2};
- RUReady = {4};
- (* PORT Selection Function *)
- Reset = {};
- SelectiveReset = {1};
- (* Action Command Opcodes in Control Block List (CBL) *)
- ActionCmdNOP = {};
- ActionCmdIASetup = {16};
- ActionCmdConfig = {17};
- ActionCmdTx = {18};
- (* More Command Bits in CBL *)
- LastBlock = {31}; (* EL Bit *)
- Suspend = {30}; (* S Bit *)
- Interrupt = {29}; (* I Bit *)
- VAR
- nCUWaitActive: LONGINT;
- TYPE
- ByteField = POINTER TO ARRAY OF CHAR;
- DataBlock = POINTER TO RECORD
- next: DataBlock;
- size: LONGINT;
- data: ByteField;
- END;
- LinkDevice = OBJECT(Network.LinkDevice)
- VAR
- ctrl: Controller;
- txTrials: LONGINT;
- (*
- send a frame
- padding and checksum are inserted directly by the device
- *)
- PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
- CONST
- DataOfs = 10H; (* data block offset in transmit command block *)
- C = 15;
- VAR
- actAdr, prevAdr: ADDRESS; txLen, i: LONGINT;
- byteCount, EOF, TxThreshold, state, cmdHdr, sendStatus: SET;
- BEGIN {EXCLUSIVE}
- (* if C Bit in next TxCmd Block is not set, the transmit command has not yet finished processing all bytes
- => buffer overflow (wait)
- *)
- ctrl.ExecCmd(MaskAllIntr, ~keepMasks);
- REPEAT
- sendStatus := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(ctrl.actTxCmd.next.data[0])));
- UNTIL (C IN sendStatus);
- txLen := 14 + h3len + h4len + dlen; (* number of bytes to transmit *)
- prevAdr := ADDRESSOF(ctrl.actTxCmd.data[0]);
- ctrl.actTxCmd := ctrl.actTxCmd.next;
- actAdr := ADDRESSOF(ctrl.actTxCmd.data[0]);
- (* setup cmd hdr *)
- SYSTEM.PUT32(actAdr, Suspend + ActionCmdTx);
- (* in simplified mode the TBD array address should be set to all ones *)
- SYSTEM.PUT32(actAdr + 08H, 0FFFFFFFFH);
- (* set TxThreshold, EOF Bit, Tx Command Block Byte Count *)
- byteCount := SYSTEM.VAL(SET, txLen) * {0..13};
- EOF := {15};
- TxThreshold := {16};
- SYSTEM.PUT32(actAdr + 0CH, byteCount + EOF + TxThreshold);
- (* set data field *)
- SYSTEM.MOVE(ADDRESSOF(dst[0]), actAdr + DataOfs, 6); (* the first 6 bytes of data field are dst address *)
- SYSTEM.MOVE(ADDRESSOF(local[0]), actAdr + DataOfs + 6, 6);
- SYSTEM.PUT16(actAdr + DataOfs + 12, ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
- i := 14;
- IF h3len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l3hdr[0]), actAdr + DataOfs + i, h3len); INC(i, h3len) END;
- IF h4len > 0 THEN SYSTEM.MOVE(ADDRESSOF(l4hdr[0]), actAdr + DataOfs + i, h4len); INC(i, h4len) END;
- IF i+dlen < MaxETHFrameSize THEN
- SYSTEM.MOVE(ADDRESSOF(data[0])+dofs, actAdr + DataOfs + i, dlen);
- INC(i, dlen);
- END;
- (* delete Suspended Bit from previous TxCmd *)
- state := ctrl.GetCUState();
- WHILE (state # CUIdle) & (state # CUSuspended) DO
- Machine.AtomicInc(nCUWaitActive);
- state := ctrl.GetCUState();
- END;
- cmdHdr := SYSTEM.VAL(SET, SYSTEM.GET32(prevAdr)) - Suspend;
- SYSTEM.PUT32(prevAdr, cmdHdr);
- state := ctrl.GetCUState();
- IF state = CUIdle THEN
- actAdr := Machine.PhysicalAdr(actAdr, ctrl.actTxCmd.size);
- ctrl.WriteSCBGenPtr(Machine.Ensure32BitAddress (actAdr));
- ctrl.ExecCmd(CUStart, keepMasks);
- ELSIF state = CUSuspended THEN
- ctrl.ExecCmd(CUResume, keepMasks);
- END;
- INC(sendCount);
- ctrl.ExecCmd(UnMaskAllIntr, ~keepMasks);
- (* ctrl.ExecCmd(CXMask + CNAMask + ERMask, ~keepMasks); *)
- END DoSend;
- PROCEDURE ReceiveData(VAR data: ARRAY OF CHAR; ofs, size: LONGINT);
- BEGIN
- ASSERT(size <= ctrl.rcvSize); (* enough data left *)
- ASSERT((size >= 0) & (ofs+size <= LEN(data))); (* index check *)
- SYSTEM.MOVE(ctrl.rcvAdr, ADDRESSOF(data[ofs]), size);
- INC(ctrl.rcvAdr, size);
- DEC(ctrl.rcvSize, size);
- END ReceiveData;
- PROCEDURE Finalize(connected: BOOLEAN);
- BEGIN
- ctrl.Finalize;
- Finalize^(connected);
- END Finalize;
- END LinkDevice;
- Controller = OBJECT
- VAR
- next: Controller;
- base: ADDRESS; irq: LONGINT;
- dev: LinkDevice;
- actRFD, lastRFD: DataBlock;
- actTxCmd: DataBlock;
- rcvAdr, rcvSize: LONGINT;
- PROCEDURE &Init*(dev: LinkDevice; base: ADDRESS; irq: LONGINT);
- VAR res: WORD; i: LONGINT;
- configCmd, iASetupCmd: DataBlock;
- BEGIN
- SELF.next := installedControllers; installedControllers := SELF;
- SELF.base := base;
- SELF.irq := irq;
- SELF.dev := dev;
- dev.ctrl := SELF;
- (* set Ethernet Broadcast Address *)
- FOR i := 0 TO 5 DO
- dev.broadcast[i] := 0FFX;
- END;
- WritePORT(Reset); Delay(1);
- ExecCmd(MaskAllIntr, ~keepMasks); (* mask all interrupts, do not keep any old masks *)
- WriteSCBGenPtr(0);
- ExecCmd(CULoadBase, keepMasks); (* set CU base, keeping all interrupt masks *)
- WriteSCBGenPtr(0);
- ExecCmd(RULoadBase, keepMasks); (* set RU base, keeping all interrupt masks *)
- (* configure the device *)
- MakeBlock(configCmd, SizeOfConfigCmdHdr);
- SetCmdHdr(LastBlock + ActionCmdConfig, configCmd);
- SetByteMap8255x(configCmd);
- StartActionCmd(configCmd);
- (* load the device with the individual address (MAC address) *)
- MakeBlock(iASetupCmd, SizeOfIASetupCmdHdr);
- SetCmdHdr(LastBlock + ActionCmdIASetup, iASetupCmd);
- SetMACAddress(iASetupCmd);
- StartActionCmd(iASetupCmd);
- SetupRxRing();
- StartRxUnit();
- SetupTxRing();
- (* install interrupt handler *)
- Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+irq);
- (* mask interrupts *)
- (* ExecCmd(UnMaskAllIntr, ~keepMasks); *)
- ExecCmd(CXMask + CNAMask + ERMask, ~keepMasks);
- (* register with Network *)
- Network.registry.Add(dev, res); ASSERT(res = Plugins.Ok);
- INC(installed);
- KernelLog.Enter; KernelLog.String(dev.name); KernelLog.String(" "); Network.OutLinkAdr(dev.local, 6); KernelLog.Exit;
- END Init;
- (*
- setup the IASetup Command and put the MAC in dev.local
- if the MAC address is aabbccddeeffH:
- dev.local[0] is aa
- dev.local[1] is bb
- dev.local[2] is cc
- etc.
- *)
- PROCEDURE SetMACAddress(VAR cmd: DataBlock);
- CONST
- MacAdrBase = 0;
- VAR reg, i: INTEGER;
- BEGIN
- (* read permanent MAC address *)
- FOR i := 0 TO 2 DO
- ReadEEPROM(MacAdrBase + i, reg); (* EEPROM registers are 2 bytes *)
- SYSTEM.PUT16(ADDRESSOF(dev.local[2*i]), reg); (* put MAC in dev.local *)
- SYSTEM.PUT16(ADDRESSOF(cmd.data[8 + 2*i]), reg); (* put MAC in Action Command Block *)
- END;
- END SetMACAddress;
- PROCEDURE SetByteMap8255x(VAR cmd: DataBlock);
- VAR
- byteArray: ARRAY 22 OF CHAR;
- PROCEDURE ToChar(s: SET): CHAR;
- BEGIN
- RETURN SYSTEM.VAL(CHAR, SHORT(SHORT(SYSTEM.VAL(LONGINT, s))));
- END ToChar;
- BEGIN
- byteArray[0] := 16X;
- byteArray[1] := 8X;
- byteArray[2] := 00X;
- byteArray[3] := 00X; (* MWI disable *)
- byteArray[4] := 00X;
- byteArray[5] := 00X;
- byteArray[6] := ToChar({5, 4, 1});
- byteArray[7] := ToChar({1, 0}); (* discard short frames (frames < 64 bytes) *)
- byteArray[8] := 01X;
- byteArray[9] := 00X;
- byteArray[10] := ToChar({5, 3, 2, 1}); (* NO src adr insertion (from internal dev IA) *)
- byteArray[11] := 00X;
- byteArray[12] := ToChar({6, 5, 0});
- byteArray[13] := 00X; (* default *)
- byteArray[14] := 0F2X; (* default *)
- byteArray[15] := ToChar({3});
- byteArray[16] := 00X;
- byteArray[17] := ToChar({6}); (* for compatibility reason *)
- byteArray[18] := ToChar({7, 6, 5, 4, 1}); (* enable padding *)
- byteArray[19] := ToChar({7});
- byteArray[20] := ToChar({0..5}); (* prio field in byte #31 in flow control frame *)
- byteArray[21] := ToChar({2, 0});
- SYSTEM.MOVE(ADDRESSOF(byteArray[0]), ADDRESSOF(cmd.data[0]) + 08H, 22);
- END SetByteMap8255x;
- PROCEDURE SetupTxRing;
- VAR
- r: LONGINT;
- adr, physAdr: ADDRESS;
- txCmd, prev: DataBlock;
- BEGIN
- FOR r := 0 TO TxRingSize - 1 DO
- MakeBlock(txCmd, SizeOfTxCmdHdr + MaxETHFrameSize);
- adr := ADDRESSOF(txCmd.data[0]);
- SYSTEM.PUT32(adr, {15}); (* set C Bit for LinkDevice.Send => no C Bit means Send Buffer Overflow *)
- IF prev # NIL THEN
- prev.next := txCmd;
- physAdr := Machine.PhysicalAdr(adr, txCmd.size); ASSERT(physAdr # Machine.NilAdr);
- SYSTEM.PUT32(ADDRESSOF(prev.data[0]) + 04H, physAdr); (* set link address to physical address *)
- ELSE
- actTxCmd := txCmd; (* set first TxCmd *)
- END;
- prev := txCmd;
- END;
- (* link last TxCmd to first TxCmd *)
- txCmd.next := actTxCmd;
- physAdr := Machine.PhysicalAdr(ADDRESSOF(actTxCmd.data[0]), actTxCmd.size);
- ASSERT(physAdr # Machine.NilAdr);
- adr := ADDRESSOF(txCmd.data[0]);
- SYSTEM.PUT32(adr + 04H, Machine.Ensure32BitAddress (physAdr));
- END SetupTxRing;
- PROCEDURE SetupRxRing;
- VAR
- r: LONGINT;
- adr, physAdr: ADDRESS;
- rxFrame, prev: DataBlock;
- BEGIN
- FOR r := 0 TO RxRingSize - 1 DO
- MakeBlock(rxFrame, SizeOfRFDHdr + MaxETHFrameSize);
- (* configure RFD *)
- adr := ADDRESSOF(rxFrame.data[0]);
- SYSTEM.PUT32(adr, 0);
- SYSTEM.PUT32(adr + 0CH, 0);
- SYSTEM.PUT16(adr + 0CH + 2H, SHORT(rxFrame.size));
- IF prev # NIL THEN
- prev.next := rxFrame;
- physAdr := Machine.PhysicalAdr(adr, rxFrame.size); ASSERT(physAdr # Machine.NilAdr);
- SYSTEM.PUT32(ADDRESSOF(prev.data[0]) + 4H, physAdr); (* set link address to physical address *)
- ELSE
- actRFD := rxFrame; (* set first RFD *)
- END;
- prev := rxFrame;
- END;
- lastRFD := rxFrame;
- (* link last RFD TO first RFD *)
- lastRFD.next := actRFD;
- physAdr := Machine.PhysicalAdr(ADDRESSOF(actRFD.data[0]), actRFD.size); ASSERT(physAdr # Machine.NilAdr);
- adr := ADDRESSOF(lastRFD.data[0]);
- SYSTEM.PUT32(adr + 4H, Machine.Ensure32BitAddress (physAdr));
- SYSTEM.PUT32(adr, Suspend); (* after having received the last block, suspend reception of further frames *)
- END SetupRxRing;
- PROCEDURE StartRxUnit;
- VAR
- adr: ADDRESS;
- BEGIN
- adr := Machine.PhysicalAdr(ADDRESSOF(actRFD.data[0]), actRFD.size); ASSERT(adr # Machine.NilAdr);
- WriteSCBGenPtr(Machine.Ensure32BitAddress (adr));
- ASSERT(GetRUState() # RUReady);
- ExecCmd(RUStart, keepMasks);
- END StartRxUnit;
- PROCEDURE SetCmdHdr(bits: SET; VAR cmd: DataBlock);
- BEGIN
- SYSTEM.PUT32(ADDRESSOF(cmd.data[0]), bits * {16..31}); (* set status word bits to 0 *)
- END SetCmdHdr;
- PROCEDURE MakeBlock(VAR cmd: DataBlock; dataSize: LONGINT);
- BEGIN
- NEW(cmd);
- cmd.size := dataSize;
- NEW(cmd.data, cmd.size);
- END MakeBlock;
- PROCEDURE AckIntr(interrupts: SET);
- BEGIN
- SYSTEM.PUT16(base + SCBStatus, SHORT(SYSTEM.VAL(LONGINT, interrupts)));
- END AckIntr;
- PROCEDURE GetStatus():SET;
- BEGIN
- RETURN SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + SCBStatus)));
- END GetStatus;
- PROCEDURE GetCUState(): SET;
- BEGIN
- RETURN GetStatus() * {6, 7};
- END GetCUState;
- PROCEDURE GetRUState(): SET;
- BEGIN
- RETURN GetStatus() * {2..5};
- END GetRUState;
- (*
- set the SCB command word
- keep indicates if interrupt masks of upper byte are deleted
- *)
- PROCEDURE ExecCmd(cmd: SET; keep: BOOLEAN);
- VAR masks: SET;
- BEGIN
- cmd := cmd * {16..31}; (* delete status part of cmd *)
- IF keep THEN
- masks := SYSTEM.VAL(SET, SYSTEM.GET32(base + SCBStatus)); (* get interrupt masks *)
- masks := masks * {24..31}; (* delete all but the mask bits *)
- cmd := cmd + masks; (* merge cmd with interrupt mask *)
- END;
- SYSTEM.PUT32(base + SCBStatus, cmd); (* writing zeros to status word has no effect *)
- WHILE (SYSTEM.GET8(base + SCBCommand) # 0) DO END; (* wait for command done *)
- END ExecCmd;
- PROCEDURE WaitForActionCmd(VAR cmd: DataBlock);
- CONST
- C = 15;
- OK = 13;
- SecsToWait = 10;
- VAR
- t: Kernel.MilliTimer;
- status: SET;
- BEGIN
- (* check command completion *)
- status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
- Kernel.SetTimer(t, SecsToWait * 1000);
- WHILE ~(C IN status) & ~Kernel.Expired(t) DO
- status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
- END;
- ASSERT(C IN status);
- (* check command ok *)
- status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
- Kernel.SetTimer(t, SecsToWait * 1000);
- WHILE ~(OK IN status) & ~Kernel.Expired(t) DO
- status := SYSTEM.VAL(SET, SYSTEM.GET32(ADDRESSOF(cmd.data[0])));
- END;
- ASSERT(OK IN status);
- END WaitForActionCmd;
- PROCEDURE ContainsRxData(VAR rxFrame: DataBlock): BOOLEAN;
- CONST
- C = 15;
- OK = 13;
- EOF = 15;
- VAR
- adr: ADDRESS;
- status: SET;
- BEGIN
- adr := ADDRESSOF(rxFrame.data[0]);
- status := SYSTEM.VAL(SET, SYSTEM.GET32(adr));
- IF (C IN status) & (OK IN status) THEN
- RETURN EOF IN SYSTEM.VAL(SET, SYSTEM.GET32(adr + 0CH)); (* data placing completed ? *)
- END;
- RETURN FALSE;
- END ContainsRxData;
- PROCEDURE StartActionCmd(VAR cmd: DataBlock);
- CONST
- ActiveState = 7;
- VAR
- adr: ADDRESS;
- BEGIN
- adr := Machine.PhysicalAdr(ADDRESSOF(cmd.data[0]), cmd.size); ASSERT(adr # Machine.NilAdr);
- WriteSCBGenPtr(Machine.Ensure32BitAddress (adr));
- ASSERT(~(ActiveState IN GetStatus())); (* CU must not be in active state *)
- ExecCmd(CUStart, keepMasks);
- WaitForActionCmd(cmd); (* todo: if we know the last cmd, then check for cmd done BEFORE execCmd *)
- END StartActionCmd;
- PROCEDURE WritePORT(p: SET);
- BEGIN
- SYSTEM.PUT32(base + PORTReg, p);
- END WritePORT;
- PROCEDURE WriteSCBGenPtr(val: LONGINT);
- BEGIN
- SYSTEM.PUT32(base + SCBGenPtr, val);
- END WriteSCBGenPtr;
- PROCEDURE ReadEEPROM(reg: INTEGER; VAR res: INTEGER);
- CONST
- EESK = 0;
- EECS = 1;
- EEDI = 2;
- EEDO = 3;
- ReadOpcode = 6;
- VAR
- x: SET;
- bits: INTEGER;
- PROCEDURE RaiseClk(VAR x: SET);
- VAR dummy: LONGINT;
- BEGIN
- INCL(x, EESK);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- dummy := SYSTEM.GET16(base + SCBStatus);
- Delay(1);
- END RaiseClk;
- PROCEDURE LowerClk(VAR x: SET);
- VAR dummy: LONGINT;
- BEGIN
- EXCL(x, EESK);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- dummy := SYSTEM.GET16(base + SCBStatus);
- Delay(1);
- END LowerClk;
- PROCEDURE ShiftOutBits(data, count: INTEGER);
- VAR
- mask: INTEGER;
- x: SET;
- dummy: LONGINT;
- BEGIN
- mask := LSH(1, count-1);
- x := GetEEPROMReg();
- EXCL(x, EEDO); EXCL(x, EEDI);
- REPEAT
- EXCL(x, EEDI);
- IF (SYSTEM.VAL(SET, LONG(data)) * SYSTEM.VAL(SET, LONG(mask)) # {}) THEN
- INCL(x, EEDI);
- END;
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- dummy := SYSTEM.GET16(base + SCBStatus);
- Delay(1);
- RaiseClk(x);
- LowerClk(x);
- mask := LSH(mask, -1);
- UNTIL mask = 0;
- EXCL(x, EEDI);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- END ShiftOutBits;
- PROCEDURE ShiftInBits(): INTEGER;
- VAR
- x: SET;
- d, i: INTEGER;
- BEGIN
- x := GetEEPROMReg();
- EXCL(x, EEDO); EXCL(x, EEDI);
- d := 0;
- FOR i := 0 TO 15 DO
- d := LSH(d, 1);
- RaiseClk(x);
- x := GetEEPROMReg();
- EXCL(x, EEDI);
- IF (EEDO IN x) & (~ODD(d)) THEN
- d := d + 1;
- END;
- LowerClk(x);
- END;
- RETURN d;
- END ShiftInBits;
- PROCEDURE GetEEPROMReg(): SET;
- BEGIN
- RETURN SYSTEM.VAL(SET, LONG(SYSTEM.GET16(base + SCBEeprom)));
- END GetEEPROMReg;
- (*
- returns number of bits in eeprom address
- typically 6 or 8 bits according to eeprom size of 64 or 256 registers
- *)
- PROCEDURE GetEEPROMAdrSize(): INTEGER;
- VAR
- x: SET;
- size: INTEGER;
- dummy: LONGINT;
- err: BOOLEAN;
- BEGIN
- err := FALSE;
- (* enable eeprom by setting EECS *)
- x := GetEEPROMReg();
- EXCL(x, EEDI); EXCL(x, EEDO); EXCL(x, EESK);
- INCL(x, EECS);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- ShiftOutBits(ReadOpcode, 3); (* opcodes are 3 bits *)
- x := GetEEPROMReg();
- REPEAT
- INC(size);
- INCL(x, EEDO);
- EXCL(x, EEDI);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- dummy := SYSTEM.GET16(base + SCBStatus);
- Delay(1);
- RaiseClk(x);
- LowerClk(x);
- IF size > 8 THEN (* max address size is 8 bits *)
- size := 0;
- err := TRUE;
- END;
- x := GetEEPROMReg();
- UNTIL ~(EEDO IN x) OR err;
- dummy := ShiftInBits();
- CleanupEEPROM();
- RETURN size;
- END GetEEPROMAdrSize;
- PROCEDURE CleanupEEPROM;
- VAR x: SET;
- BEGIN
- x := GetEEPROMReg();
- EXCL(x, EECS); EXCL(x, EEDI);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- RaiseClk(x);
- LowerClk(x);
- END CleanupEEPROM;
- BEGIN
- bits := GetEEPROMAdrSize();
- x := GetEEPROMReg();
- EXCL(x, EEDI); EXCL(x, EEDO); EXCL(x, EESK);
- INCL(x, EECS);
- SYSTEM.PUT16(base + SCBEeprom, SHORT(SYSTEM.VAL(LONGINT, x)));
- ShiftOutBits(ReadOpcode, 3); (* opcodes are 3 bits *)
- ShiftOutBits(reg, bits);
- res := ShiftInBits();
- CleanupEEPROM();
- END ReadEEPROM;
- PROCEDURE HandleInterrupt;
- VAR
- status, ack: SET;
- BEGIN
- status := GetStatus();
- ack := {};
- IF IsIn(CX, status) THEN
- (* this interrupt indicates that the CU finished executing a command *)
- ack := ack + CX;
- END;
- IF IsIn(FR, status) THEN
- (* this interrupt indicates that the RU has finished receiving a frame *)
- ack := ack + FR;
- ReadFrame();
- END;
- IF IsIn(CNA, status) THEN
- (* this interrupt indicates that the CU has left the active state or has entered the idle state *)
- ack := ack + CNA;
- END;
- IF IsIn(RNR, status) THEN
- (* this interrupt indicates that the RU leaves the ready state -> no more place in the RxRing !!! *)
- KernelLog.String("Intel8255x: RNR Interrupt: RxRing too small."); KernelLog.Ln;
- ack := ack + RNR;
- END;
- IF IsIn(MDI, status) THEN
- (* this interrupt indicates when an MDI read or write cycle has completed *)
- ack := ack + MDI;
- END;
- IF IsIn(SWI, status) THEN
- (* used for software generated interrupts *)
- ack := ack + SWI;
- END;
- AckIntr(ack);
- END HandleInterrupt;
- PROCEDURE IncLastRFD;
- VAR
- prevStatus: SET;
- prevAdr, adr: ADDRESS;
- BEGIN
- prevAdr := ADDRESSOF(lastRFD.data[0]);
- lastRFD := lastRFD.next;
- adr := ADDRESSOF(lastRFD.data[0]);
- SYSTEM.PUT32(adr, Suspend); (* set Suspend Bit *)
- SYSTEM.PUT32(adr + 0CH, 0); (* delete EOF Bit *)
- SYSTEM.PUT16(adr + 0CH + 2H, SHORT(lastRFD.size));
- prevStatus := SYSTEM.VAL(SET, SYSTEM.GET32(prevAdr));
- SYSTEM.PUT32(prevAdr, prevStatus * {0..29, 31}); (* delete Suspend Bit (30) in previous RFD *)
- IF GetRUState() = RUSuspended THEN
- ExecCmd(RUResume, keepMasks);
- END;
- END IncLastRFD;
- PROCEDURE ReadFrame;
- CONST
- DataOfs = 10H; (* receive buffer offset *)
- VAR
- frameAdr: ADDRESS; type, actualCount: LONGINT;
- srcAdr (* , dstAdr *) : Network.LinkAdr;
- (* handler: Network.Receiver; *)
- buf: Network.Buffer;
- BEGIN
- WHILE ContainsRxData(actRFD) DO
- frameAdr := ADDRESSOF(actRFD.data[0]);
- actualCount := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.GET32(frameAdr + 0CH)) * {0..13});
- (*SYSTEM.MOVE(frameAdr + DataOfs, ADDRESSOF(dstAdr), 6);*)
- SYSTEM.MOVE(frameAdr + DataOfs + 6, ADDRESSOF(srcAdr), 6);
- type := Network.GetNet2(actRFD.data^, DataOfs + 12); (* Endianess ! *)
- (*
- dev.GetReceiver(type, handler, hSize);
- rcvAdr := frameAdr + DataOfs + 14 + hSize;
- rcvSize := actualCount - 14 - hSize;
- INC(dev.recvCount);
- handler(dev, SYSTEM.VAL(Network.RecvHdr, actRFD.data[DataOfs + 14]), actualCount - 14, type, srcAdr);
- *)
- buf := Network.GetNewBuffer();
- IF buf # NIL THEN
- buf.ofs := 0;
- buf.len := actualCount - 14;
- buf.src := srcAdr;
- Network.Copy(actRFD.data^, buf.data, DataOfs + 14, 0, actualCount - 14);
- dev.QueueBuffer(buf, type);
- END;
- (* delete C, OK and EOF Bits in RFD *)
- SYSTEM.PUT32(frameAdr, 0);
- SYSTEM.PUT16(frameAdr + 0CH, 0);
- actRFD := actRFD.next;
- IncLastRFD();
- END;
- END ReadFrame;
- PROCEDURE Finalize;
- BEGIN
- Objects.RemoveHandler(SELF.HandleInterrupt, Machine.IRQ0 + irq);
- Network.registry.Remove(dev);
- dev.ctrl := NIL;
- dev := NIL;
- END Finalize;
- END Controller;
- VAR
- installedControllers: Controller;
- installed: LONGINT;
- PROCEDURE Install*;
- BEGIN {EXCLUSIVE}
- IF installed = 0 THEN
- ScanPCI(8086H, 2449H);
- ScanPCI(8086H, 1029H); (* 82559 Ethernet Controller *)
- ScanPCI(8086H, 1031H); (* ICH3 *)
- ScanPCI(8086H, 1032H);
- ScanPCI(8086H, 1033H);
- ScanPCI(8086H, 1034H); (* Reserved *)
- ScanPCI(8086H, 1035H);
- ScanPCI(8086H, 1036H); (* Reserved *)
- ScanPCI(8086H, 1037H); (* Reserved *)
- ScanPCI(8086H, 1038H); (* Reserved *)
- ScanPCI(8086H, 103DH); (* In VAIO *)
- ScanPCI(8086H, 1064H); (* 82562ET/EZ/GT/GZ - Pro/100 VE (LOM) *)
- ScanPCI(8086H, 1209H); (* 82559ER *)
- ScanPCI(8086H, 1229H); (* Ethernet Pro 100 *)
- END;
- END Install;
- PROCEDURE Remove*;
- VAR table: Plugins.Table; i: LONGINT;
- BEGIN {EXCLUSIVE}
- Network.registry.GetAll(table);
- IF table # NIL THEN
- FOR i := 0 TO LEN(table)-1 DO
- IF table[i] IS LinkDevice THEN table[i](LinkDevice).Finalize(TRUE) END
- END
- END;
- installed := 0;
- END Remove;
- PROCEDURE ScanPCI(vendor, device: LONGINT);
- VAR
- index, bus, dev, fct, irq, i: LONGINT; res: WORD;
- base: ADDRESS;
- d: LinkDevice;
- c: Controller;
- name: Plugins.Name;
- BEGIN
- index := 0;
- WHILE (PCI.FindPCIDevice(device, vendor, index, bus, dev, fct) = PCI.Done) & (installed < 10) DO
- res := PCI.ReadConfigDword(bus, dev, fct, PCI.Adr0Reg, i); ASSERT(res = PCI.Done);
- base := i; ASSERT(~ODD(base)); (* memory mapped *)
- DEC(base, base MOD 16);
- Machine.MapPhysical(base, 4*K, base);
- res := PCI.ReadConfigByte(bus, dev, fct, PCI.IntlReg, irq); ASSERT(res = PCI.Done);
- NEW(d, Network.TypeEthernet, MaxETHFrameSize - 14, 6);
- name := Name;
- i := 0; WHILE name[i] # 0X DO INC(i) END;
- name[i] := CHR(ORD("0") + installed);
- name[i+1] := 0X;
- d.SetName(name);
- d.desc := Desc;
- NEW(c, d, base, irq); (* increments "installed" when successful *)
- INC(index)
- END
- END ScanPCI;
- PROCEDURE IsIn(subset, set: SET): BOOLEAN;
- BEGIN
- RETURN ((subset * set) = subset);
- END IsIn;
- PROCEDURE Cleanup;
- BEGIN
- (*WHILE installedControllers # NIL DO installedControllers.Finalize; installedControllers := installedControllers.next END;*)
- IF Modules.shutdown = Modules.None THEN (* module is being freed *)
- Remove;
- END
- END Cleanup;
- (*
- busy wait for ms milliseconds
- *)
- PROCEDURE Delay(ms: LONGINT);
- VAR t: Kernel.MilliTimer;
- BEGIN
- Kernel.SetTimer(t, ms);
- REPEAT UNTIL Kernel.Expired(t);
- END Delay;
- BEGIN
- Modules.InstallTermHandler(Cleanup);
- END Intel8255x.
- PC.Compile \s Intel8255x.Mod ~
- System.OpenKernelLog ~
- TestNet.Mod
- System.Free TestNet ~
- TestNet.SetDevice "Intel8255x#0" ~
- TestNet.ShowDevices ~
- TestNet.SendBroadcast ~
- TestNet.SendBroadcastVar 1499 ~
- TestNet.SendTest ^ 1 10 100 1000 ~
- Intel8255x.Test
- Decoder.Decode Intel8255x.Obx ~
- System.Free Intel8255x ~
- System.Free TestNet ~
- System.State Intel8255x ~
- Aos.Call Intel8255x.Install
- Aos.Call Intel8255x.Remove
|