MODULE Intel8255x;
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;
SCBStatus = 0H;
SCBCommand = 2H;
SCBGenPtr = 4H;
SCBEeprom = 0EH;
PORTReg = 8H;
CX = {15};
FR = {14};
CNA = {13};
RNR = {12};
MDI = {11};
SWI = {10};
CXMask = {31};
FRMask = {30};
CNAMask = {29};
RNRMask = {28};
ERMask = {27};
FCPMask = {26};
MaskAllIntr = {24};
UnMaskAllIntr = {};
SI = {25};
CUNop = {};
CUStart = {20};
CUResume = {21};
CULoadBase = {21, 22};
RUNop = {};
RUStart = {16};
RUResume = {17};
RUAbort = {18};
RULoadBase = {17, 18};
CUIdle = {};
CUSuspended = {6};
RUIdle = {};
RUSuspended = {2};
RUReady = {4};
Reset = {};
SelectiveReset = {1};
ActionCmdNOP = {};
ActionCmdIASetup = {16};
ActionCmdConfig = {17};
ActionCmdTx = {18};
LastBlock = {31};
Suspend = {30};
Interrupt = {29};
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;
PROCEDURE DoSend*(dst: Network.LinkAdr; type: LONGINT; VAR l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
CONST
DataOfs = 10H;
C = 15;
VAR
actAdr, prevAdr: SYSTEM.ADDRESS; txLen, i: LONGINT;
byteCount, EOF, TxThreshold, state, cmdHdr, sendStatus: SET;
BEGIN {EXCLUSIVE}
ctrl.ExecCmd(MaskAllIntr, ~keepMasks);
REPEAT
sendStatus := SYSTEM.VAL(SET, SYSTEM.GET32(SYSTEM.ADR(ctrl.actTxCmd.next.data[0])));
UNTIL (C IN sendStatus);
txLen := 14 + h3len + h4len + dlen;
prevAdr := SYSTEM.ADR(ctrl.actTxCmd.data[0]);
ctrl.actTxCmd := ctrl.actTxCmd.next;
actAdr := SYSTEM.ADR(ctrl.actTxCmd.data[0]);
SYSTEM.PUT32(actAdr, Suspend + ActionCmdTx);
SYSTEM.PUT32(actAdr + 08H, 0FFFFFFFFH);
byteCount := SYSTEM.VAL(SET, txLen) * {0..13};
EOF := {15};
TxThreshold := {16};
SYSTEM.PUT32(actAdr + 0CH, byteCount + EOF + TxThreshold);
SYSTEM.MOVE(SYSTEM.ADR(dst[0]), actAdr + DataOfs, 6);
SYSTEM.MOVE(SYSTEM.ADR(local[0]), actAdr + DataOfs + 6, 6);
SYSTEM.PUT16(actAdr + DataOfs + 12, SYSTEM.ROT(SYSTEM.VAL(INTEGER, SHORT(type)), 8));
i := 14;
IF h3len > 0 THEN SYSTEM.MOVE(SYSTEM.ADR(l3hdr[0]), actAdr + DataOfs + i, h3len); INC(i, h3len) END;
IF h4len > 0 THEN SYSTEM.MOVE(SYSTEM.ADR(l4hdr[0]), actAdr + DataOfs + i, h4len); INC(i, h4len) END;
IF i+dlen < MaxETHFrameSize THEN
SYSTEM.MOVE(SYSTEM.ADR(data[0])+dofs, actAdr + DataOfs + i, dlen);
INC(i, dlen);
END;
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);
END DoSend;
PROCEDURE ReceiveData(VAR data: ARRAY OF CHAR; ofs, size: LONGINT);
BEGIN
ASSERT(size <= ctrl.rcvSize);
ASSERT((size >= 0) & (ofs+size <= LEN(data)));
SYSTEM.MOVE(ctrl.rcvAdr, SYSTEM.ADR(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: SYSTEM.ADDRESS; irq: LONGINT;
dev: LinkDevice;
actRFD, lastRFD: DataBlock;
actTxCmd: DataBlock;
rcvAdr, rcvSize: LONGINT;
PROCEDURE &Init*(dev: LinkDevice; base: SYSTEM.ADDRESS; irq: LONGINT);
VAR res, i: LONGINT;
configCmd, iASetupCmd: DataBlock;
BEGIN
SELF.next := installedControllers; installedControllers := SELF;
SELF.base := base;
SELF.irq := irq;
SELF.dev := dev;
dev.ctrl := SELF;
FOR i := 0 TO 5 DO
dev.broadcast[i] := 0FFX;
END;
WritePORT(Reset); Delay(1);
ExecCmd(MaskAllIntr, ~keepMasks);
WriteSCBGenPtr(0);
ExecCmd(CULoadBase, keepMasks);
WriteSCBGenPtr(0);
ExecCmd(RULoadBase, keepMasks);
MakeBlock(configCmd, SizeOfConfigCmdHdr);
SetCmdHdr(LastBlock + ActionCmdConfig, configCmd);
SetByteMap8255x(configCmd);
StartActionCmd(configCmd);
MakeBlock(iASetupCmd, SizeOfIASetupCmdHdr);
SetCmdHdr(LastBlock + ActionCmdIASetup, iASetupCmd);
SetMACAddress(iASetupCmd);
StartActionCmd(iASetupCmd);
SetupRxRing();
StartRxUnit();
SetupTxRing();
Objects.InstallHandler(SELF.HandleInterrupt, Machine.IRQ0+irq);
ExecCmd(CXMask + CNAMask + ERMask, ~keepMasks);
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;
PROCEDURE SetMACAddress(VAR cmd: DataBlock);
CONST
MacAdrBase = 0;
VAR reg, i: INTEGER;
BEGIN
FOR i := 0 TO 2 DO
ReadEEPROM(MacAdrBase + i, reg);
SYSTEM.PUT16(SYSTEM.ADR(dev.local[2*i]), reg);
SYSTEM.PUT16(SYSTEM.ADR(cmd.data[8 + 2*i]), reg);
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;
byteArray[4] := 00X;
byteArray[5] := 00X;
byteArray[6] := ToChar({5, 4, 1});
byteArray[7] := ToChar({1, 0});
byteArray[8] := 01X;
byteArray[9] := 00X;
byteArray[10] := ToChar({5, 3, 2, 1});
byteArray[11] := 00X;
byteArray[12] := ToChar({6, 5, 0});
byteArray[13] := 00X;
byteArray[14] := 0F2X;
byteArray[15] := ToChar({3});
byteArray[16] := 00X;
byteArray[17] := ToChar({6});
byteArray[18] := ToChar({7, 6, 5, 4, 1});
byteArray[19] := ToChar({7});
byteArray[20] := ToChar({0..5});
byteArray[21] := ToChar({2, 0});
SYSTEM.MOVE(SYSTEM.ADR(byteArray[0]), SYSTEM.ADR(cmd.data[0]) + 08H, 22);
END SetByteMap8255x;
PROCEDURE SetupTxRing;
VAR
r: LONGINT;
adr, physAdr: SYSTEM.ADDRESS;
txCmd, prev: DataBlock;
BEGIN
FOR r := 0 TO TxRingSize - 1 DO
MakeBlock(txCmd, SizeOfTxCmdHdr + MaxETHFrameSize);
adr := SYSTEM.ADR(txCmd.data[0]);
SYSTEM.PUT32(adr, {15});
IF prev # NIL THEN
prev.next := txCmd;
physAdr := Machine.PhysicalAdr(adr, txCmd.size); ASSERT(physAdr # Machine.NilAdr);
SYSTEM.PUT32(SYSTEM.ADR(prev.data[0]) + 04H, physAdr);
ELSE
actTxCmd := txCmd;
END;
prev := txCmd;
END;
txCmd.next := actTxCmd;
physAdr := Machine.PhysicalAdr(SYSTEM.ADR(actTxCmd.data[0]), actTxCmd.size);
ASSERT(physAdr # Machine.NilAdr);
adr := SYSTEM.ADR(txCmd.data[0]);
SYSTEM.PUT32(adr + 04H, Machine.Ensure32BitAddress (physAdr));
END SetupTxRing;
PROCEDURE SetupRxRing;
VAR
r: LONGINT;
adr, physAdr: SYSTEM.ADDRESS;
rxFrame, prev: DataBlock;
BEGIN
FOR r := 0 TO RxRingSize - 1 DO
MakeBlock(rxFrame, SizeOfRFDHdr + MaxETHFrameSize);
adr := SYSTEM.ADR(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(SYSTEM.ADR(prev.data[0]) + 4H, physAdr);
ELSE
actRFD := rxFrame;
END;
prev := rxFrame;
END;
lastRFD := rxFrame;
lastRFD.next := actRFD;
physAdr := Machine.PhysicalAdr(SYSTEM.ADR(actRFD.data[0]), actRFD.size); ASSERT(physAdr # Machine.NilAdr);
adr := SYSTEM.ADR(lastRFD.data[0]);
SYSTEM.PUT32(adr + 4H, Machine.Ensure32BitAddress (physAdr));
SYSTEM.PUT32(adr, Suspend);
END SetupRxRing;
PROCEDURE StartRxUnit;
VAR
adr: SYSTEM.ADDRESS;
BEGIN
adr := Machine.PhysicalAdr(SYSTEM.ADR(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(SYSTEM.ADR(cmd.data[0]), bits * {16..31});
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;
PROCEDURE ExecCmd(cmd: SET; keep: BOOLEAN);
VAR masks: SET;
BEGIN
cmd := cmd * {16..31};
IF keep THEN
masks := SYSTEM.VAL(SET, SYSTEM.GET32(base + SCBStatus));
masks := masks * {24..31};
cmd := cmd + masks;
END;
SYSTEM.PUT32(base + SCBStatus, cmd);
WHILE (SYSTEM.GET8(base + SCBCommand) # 0) DO END;
END ExecCmd;
PROCEDURE WaitForActionCmd(VAR cmd: DataBlock);
CONST
C = 15;
OK = 13;
SecsToWait = 10;
VAR
t: Kernel.MilliTimer;
status: SET;
BEGIN
status := SYSTEM.VAL(SET, SYSTEM.GET32(SYSTEM.ADR(cmd.data[0])));
Kernel.SetTimer(t, SecsToWait * 1000);
WHILE ~(C IN status) & ~Kernel.Expired(t) DO
status := SYSTEM.VAL(SET, SYSTEM.GET32(SYSTEM.ADR(cmd.data[0])));
END;
ASSERT(C IN status);
status := SYSTEM.VAL(SET, SYSTEM.GET32(SYSTEM.ADR(cmd.data[0])));
Kernel.SetTimer(t, SecsToWait * 1000);
WHILE ~(OK IN status) & ~Kernel.Expired(t) DO
status := SYSTEM.VAL(SET, SYSTEM.GET32(SYSTEM.ADR(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: SYSTEM.ADDRESS;
status: SET;
BEGIN
adr := SYSTEM.ADR(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));
END;
RETURN FALSE;
END ContainsRxData;
PROCEDURE StartActionCmd(VAR cmd: DataBlock);
CONST
ActiveState = 7;
VAR
adr: SYSTEM.ADDRESS;
BEGIN
adr := Machine.PhysicalAdr(SYSTEM.ADR(cmd.data[0]), cmd.size); ASSERT(adr # Machine.NilAdr);
WriteSCBGenPtr(Machine.Ensure32BitAddress (adr));
ASSERT(~(ActiveState IN GetStatus()));
ExecCmd(CUStart, keepMasks);
WaitForActionCmd(cmd);
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 := SYSTEM.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 := SYSTEM.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 := SYSTEM.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;
PROCEDURE GetEEPROMAdrSize(): INTEGER;
VAR
x: SET;
size: INTEGER;
dummy: LONGINT;
err: BOOLEAN;
BEGIN
err := FALSE;
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);
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
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);
ShiftOutBits(reg, bits);
res := ShiftInBits();
CleanupEEPROM();
END ReadEEPROM;
PROCEDURE HandleInterrupt;
VAR
status, ack: SET;
BEGIN
status := GetStatus();
ack := {};
IF IsIn(CX, status) THEN
ack := ack + CX;
END;
IF IsIn(FR, status) THEN
ack := ack + FR;
ReadFrame();
END;
IF IsIn(CNA, status) THEN
ack := ack + CNA;
END;
IF IsIn(RNR, status) THEN
KernelLog.String("Intel8255x: RNR Interrupt: RxRing too small."); KernelLog.Ln;
ack := ack + RNR;
END;
IF IsIn(MDI, status) THEN
ack := ack + MDI;
END;
IF IsIn(SWI, status) THEN
ack := ack + SWI;
END;
AckIntr(ack);
END HandleInterrupt;
PROCEDURE IncLastRFD;
VAR
prevStatus: SET;
prevAdr, adr: SYSTEM.ADDRESS;
BEGIN
prevAdr := SYSTEM.ADR(lastRFD.data[0]);
lastRFD := lastRFD.next;
adr := SYSTEM.ADR(lastRFD.data[0]);
SYSTEM.PUT32(adr, Suspend);
SYSTEM.PUT32(adr + 0CH, 0);
SYSTEM.PUT16(adr + 0CH + 2H, SHORT(lastRFD.size));
prevStatus := SYSTEM.VAL(SET, SYSTEM.GET32(prevAdr));
SYSTEM.PUT32(prevAdr, prevStatus * {0..29, 31});
IF GetRUState() = RUSuspended THEN
ExecCmd(RUResume, keepMasks);
END;
END IncLastRFD;
PROCEDURE ReadFrame;
CONST
DataOfs = 10H;
VAR
frameAdr: SYSTEM.ADDRESS; type, actualCount: LONGINT;
srcAdr : Network.LinkAdr;
buf: Network.Buffer;
BEGIN
WHILE ContainsRxData(actRFD) DO
frameAdr := SYSTEM.ADR(actRFD.data[0]);
actualCount := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, SYSTEM.GET32(frameAdr + 0CH)) * {0..13});
SYSTEM.MOVE(frameAdr + DataOfs + 6, SYSTEM.ADR(srcAdr), 6);
type := Network.GetNet2(actRFD.data^, DataOfs + 12);
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;
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);
ScanPCI(8086H, 1031H);
ScanPCI(8086H, 1032H);
ScanPCI(8086H, 1033H);
ScanPCI(8086H, 1034H);
ScanPCI(8086H, 1035H);
ScanPCI(8086H, 1036H);
ScanPCI(8086H, 1037H);
ScanPCI(8086H, 1038H);
ScanPCI(8086H, 103DH);
ScanPCI(8086H, 1064H);
ScanPCI(8086H, 1209H);
ScanPCI(8086H, 1229H);
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, res, irq, i: LONGINT;
base: SYSTEM.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));
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);
INC(index)
END
END ScanPCI;
PROCEDURE IsIn(subset, set: SET): BOOLEAN;
BEGIN
RETURN ((subset * set) = subset);
END IsIn;
PROCEDURE Cleanup;
BEGIN
IF Modules.shutdown = Modules.None THEN
Remove;
END
END Cleanup;
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