' ---------------------------------------------------------------------------- ' ' NetPing - ICMP request/response processing for the BX-24/EE-100 ' Author: Matthew Daughtrey ' Last Modified Feb 18 2001 ' ' This code demonstrates ICMP (ping) functionality. Hardware details are at ' http://www.embeddedether.net. ' This code is public domain, although I'd appreciate a credit and a copy of ' improvements you might make to it. ' ' - 2/18/2001 mattd Added ARP handling ' ' ---------------------------------------------------------------------------- ' ' BX-24 pin numbers ' const Pin_IOR as byte = 16 const Pin_IOW as byte = 15 const Pin_AEN as byte = 14 const Pin_RST as byte = 13 const Bit_IOR as byte = 4 const Bit_IOW as byte = 5 const Bit_AEN as byte = 6 const Bit_RST as byte = 7 ' ' I/O Register indices ' const IO_RxTx0 as byte = &H0 const IO_RxTx1 as byte = &H2 const IO_TxCmd as byte = &H4 const IO_TxLength as byte = &H6 const IO_IntStatusQ as byte = &H8 const IO_PPPtr as byte = &H0A const IO_PPData0 as byte = &H0C const IO_PPData1 as byte = &H0E ' ' PacketPage register indices ' const Reg_EISAID as Integer = &H0000 const Reg_PID as Integer = &H0002 const Reg_IOBase as Integer = &H0020 ' ' Receiver Configuration ' const Reg_RxConfig as Integer = &H0102 const Bit_Skip_1 as Integer = &H0040 const Bit_BufferCRC as Integer = &H0800 ' ' Receiver Control Register ' const Reg_RxControl as Integer = &H0104 const Bit_IAHashA as Integer = &H0040 ' Accept frames that pass the hash filter const Bit_PromiscuousA as Integer = &H0080 ' Accept frames with any address const Bit_RxOKA as Integer = &H0100 ' Accept frames with good CRC and length const Bit_MulticastA as Integer = &H0200 ' Accept frames with multicast addresses const Bit_IndividualA as Integer = &H0400 ' Accept frames with our address const Bit_BroadcastA as Integer = &H0800 ' Accept broadcast frames const Bit_RuntA as Integer = &H2000 ' Accept runt frames const Reg_TxCmdStatus as Integer = &H0108 ' ' Line Control Register ' const Reg_LineControl as Integer = &H0112 const Bit_SerTxOn as Integer = &H0080 ' Enable transmitter const Bit_SerRxOn as Integer = &H0040 ' Enable receiver const Reg_SelfControl as Integer = &H0114 const Reg_TestControl as Integer = &H0118 const Reg_RxEvent as Integer = &H0124 const Reg_LineStatus as Integer = &H0134 const Reg_SelfStatus as Integer = &H0136 ' ' Bus Status ' const Reg_BusStatus as Integer = &H0138 const Bit_TxBidErr as Integer = &H0080 ' Error bidding for tx memory const Bit_Rdy4TxNow as Integer = &H0100 ' Ready to accept frame ' ' Transmit Command Request ' const Reg_TxCmdReq as Integer = &H0144 const Bit_TxStartAt5 as Integer = &H0000 ' Start transmission after 5 bytes are in the queue const Bit_TxStartAt381 as Integer = &H0040 ' Start transmission after 381 bytes are in the queue const Bit_TxStartAt1021 as Integer = &H0080 ' Start transmission after 1021 bytes are in the queue const Bit_TxStartAtAll as Integer = &H00c0 ' Start transmission after all bytes are in the queue const Bit_Force as Integer = &H0100 ' Abort any tx in progress const Bit_Onecoll as Integer = &H0200 ' Abort tx after one collision const Bit_InhibitCRC as Integer = &H1000 ' Don't append CRC to tx const Bit_TxPadDis as Integer = &H2000 ' Disable padding to allow runt frames (<64 bytes w/CRC) const Reg_TxLength as Integer = &H0146 const Reg_IEEEAddrBase as Integer = &H0158 ' ' Transmitter Event ' const Reg_TxEvent as Integer = &H0218 const Bit_LossOfCRS as Integer = &H0040 const Bit_SQError as Integer = &H0080 const Bit_TxOK as Integer = &H0100 const Bit_OutOfWindow as Integer = &H0200 const Bit_Jabber as Integer = &H0400 const Bit_16Coll as Integer = &H8000 ' ' Protocol types ' const Major_IP as Integer = &H0008 const Major_X25 as Integer = &H0508 const Major_ARP as Integer = &H0608 const Major_RARP as Integer = &H3580 const Major_IPXSPX as Integer = &H3781 const Minor_ICMP as Byte = &H01 const ICMP_EchoRequest as Byte = &H08 const ARP_Ethernet as Integer = &H0100 const ARP_IP as Integer = &H0008 const ARP_Request as Integer = &H0100 const ARP_Reply as Integer = &H0200 const RARP_Request as Integer = &H0300 const RARP_Reply as Integer = &H0400 ' ' EEPROM data ' dim PersistentIEEE as new ByteVectorData dim PersistentIP as new ByteVectorData Dim PortAValue as byte Dim HexString as String * 10 Dim HexTable as String * 17 Dim Data as Integer Dim Bytes(1 to 2) as byte Dim LEDFlag as Boolean Dim RxChecksum as new UnsignedLong Dim TxChecksum as new UnsignedLong Dim EthernetLength as new UnsignedInteger Dim MyIEEEAddress(1 to 3) as Integer Dim OtherIEEEAddress(1 to 3) as Integer dim MyIPAddress(1 to 2) as Integer dim OtherIPAddress(1 to 2) as Integer Dim MajorProtocol as Integer dim MinorProtocol as Integer ' ' Converts Value into a hex string stored in HexString ' Public Sub CHexStr(ByVal Value As Integer) Dim NewValue as new UnsignedInteger NewValue = CUInt(Value) Call BlockMove(2, MemAddress(NewValue), MemAddress(Bytes)) Mid(HexString, 1, 1) = Mid(HexTable, CInt(Bytes(2)\16+1), 1) Mid(HexString, 2, 1) = Mid(HexTable, CInt(Bytes(2) mod 16)+1, 1) Mid(HexString, 3, 1) = Mid(HexTable, CInt(Bytes(1)\16+1), 1) Mid(HexString, 4, 1) = Mid(HexTable, CInt(Bytes(1) mod 16)+1, 1) End Sub Public Sub CHexStrLng(ByVal Value As UnsignedLong) Dim NewValue as new UnsignedLong NewValue = Value Call BlockMove(4, MemAddress(NewValue), MemAddress(Bytes)) Mid(HexString, 1, 1) = Mid(HexTable, CInt(Bytes(1)\16+1), 1) Mid(HexString, 2, 1) = Mid(HexTable, CInt(Bytes(1) mod 16)+1, 1) Mid(HexString, 3, 1) = Mid(HexTable, CInt(Bytes(2)\16+1), 1) Mid(HexString, 4, 1) = Mid(HexTable, CInt(Bytes(2) mod 16)+1, 1) Mid(HexString, 5, 1) = Mid(HexTable, CInt(Bytes(3)\16+1), 1) Mid(HexString, 6, 1) = Mid(HexTable, CInt(Bytes(3) mod 16)+1, 1) Mid(HexString, 7, 1) = Mid(HexTable, CInt(Bytes(4)\16+1), 1) Mid(HexString, 8, 1) = Mid(HexTable, CInt(Bytes(4) mod 16)+1, 1) End Sub ' ' Write to one of the 16-bit I/O registers ' sub IOWriteWord(ByVal Address as Byte, ByVal Data as Integer) Dim RawData(1 to 2) as Byte Dim Count as Integer Count = Data Call BlockMove(2, MemAddress(Count), MemAddress(RawData)) PortAValue = PortAValue and bx01110000 ' mask off address lines, RST low Address = Address and bx00001110 ' address bounds mask PortAValue = PortAValue or Address ' set new address lines Register.DDRC = &Hff ' set data pins to output for Count = 1 to 2 Register.PORTC = RawData(Count) ' write to the data bus Register.PORTA = PortAValue ' set I/O pins Call PutPin(Pin_IOW, bxOutputLow) ' set IOR active Call PutPin(Pin_IOW, bxOutputHigh) ' IOR inactive PortAValue = PortAValue or 1 ' set up for MSB address next Register.DDRC = &H00 ' set data pins to input TxChecksum = TxChecksum + CuLng(Data) end sub ' ' Read from one of the 16-bit I/O registers. This routine also updates ' Checksum for header checksum calculations elsewhere in the program. ' This routine reads LSB/MSB. ' function IOReadWord(ByVal Address as Byte) as Integer Dim UData as new UnsignedInteger Dim RawData(1 to 2) as Byte Dim Count as Integer PortAValue = PortAValue and bx01110000 ' mask off address lines, RST low Address = Address and bx00001110 ' address bounds mask PortAValue = PortAValue or Address ' set new address lines for Count = 1 to 2 Register.PORTA = PortAValue ' set pins Call PutPin(Pin_IOR, bxOutputLow) ' set IOR active RawData(Count) = Register.PINC ' read the data bus Call PutPin(Pin_IOR, bxOutputHigh) ' IOR inactive PortAValue = PortAValue or 1 ' set MSB address next ' ' Copy the 2 captured bytes to the returned unsigned int ' Call BlockMove(2, MemAddress(RawData), MemAddress(UData)) RxChecksum = RxChecksum + CuLng(UData) IOReadWord = CInt(UData) end function ' ' Read from one of the 16-bit I/O registers, MSB/LSB. ' function IOReadWordHL(ByVal Address as Byte) as Integer ' Set IOReadWordHL = new UnsignedInteger ' dim UData as new UnsignedInteger Dim RawData(1 to 2) as Byte Dim Count as Integer PortAValue = PortAValue and bx01110000 ' mask off address lines, RST low Address = Address and bx00001110 ' address bounds mask PortAValue = PortAValue or Address ' set new address lines PortAValue = PortAValue or 1 for Count = 2 to 1 step -1 Register.PORTA = PortAValue ' set pins Call PutPin(Pin_IOR, bxOutputLow) ' set IOR active RawData(Count) = Register.PINC ' read the data bus Call PutPin(Pin_IOR, bxOutputHigh) ' IOR inactive PortAValue = PortAValue and bx11111110 ' set MSB address next ' ' Copy the 2 captured bytes to the returned unsigned int ' Call BlockMove(2, MemAddress(RawData), MemAddress(IOReadWordHL)) end function ' ' Write a word to a PacketPage register. ' sub RegWriteWord(ByVal Address as Integer, ByVal Data as Integer) Call IOWriteWord(IO_PPPtr, Address) Call IOWriteWord(IO_PPData0, Data) end sub ' ' Read a word from a PacketPage register. ' function RegReadWord(ByVal Address as Integer) as Integer ' Set RegReadWord = new UnsignedInteger Call IOWriteWord(IO_PPPtr, Address) RegReadWord = IOReadWord(IO_PPData0) end function ' ' Initialize the CS8900A. Returns a 1 if init succeeded, else 0 ' function Init() as Integer Dim Count as Integer Init = 0 PortAValue = bx00110000 ' RST/AEN low, IOW/IOR high, address 0 Register.DDRA = &Hff ' set ctl pins to output Register.PORTC = &hff ' enable data pullups Register.PORTA = PortAValue Call PutPin(Pin_RST, bxOutputHigh) ' assert Reset Delay(0.05) Call PutPin(Pin_RST, bxOutputLow) ' deassert Reset ' ' Test for a signature and init if found ' if (IOReadWord(IO_PPPtr) = &H3000) then Init = 1 ' ' Reset the chip ' call RegWriteWord(Reg_SelfControl, &H0040) ' ' Wait for init to complete ' do while (IOReadWord(IO_PPData0) and &H0040 <> 0) loop ' ' Line Control Register ' call RegWriteWord(Reg_LineControl, Bit_SerRxOn or Bit_SerTxOn) ' ' Receiver Control Register ' call RegWriteWord(Reg_RxControl, Bit_IAHashA or Bit_RxOKA or Bit_BroadcastA or Bit_IndividualA or Bit_RuntA) end if end function ' ' Program the ethernet address into the CS8900A. Shows up as 'EE100' on the ' network sniffer. Also store ethernet address and IP address into EEPROM. ' sub SetIEEEAddress() call GetEEPROM(PersistentIEEE.DataAddress, MyIEEEAddress, 6) call GetEEPROM(PersistentIP.DataAddress, MyIPAddress, 4) call RegWriteWord(Reg_IEEEAddrBase, MyIEEEAddress(1)) call RegWriteWord(Reg_IEEEAddrBase + 2, MyIEEEAddress(2)) call RegWriteWord(Reg_IEEEAddrBase + 4, MyIEEEAddress(3)) end sub ' ' Check header checksum ' function RxChecksumOK() as Boolean Dim HiWord as new UnsignedInteger Dim LoWord as new UnsignedInteger do call BlockMove(2, MemAddress(RxChecksum), MemAddress(LoWord)) call BlockMove(2, MemAddress(RxChecksum)+2, MemAddress(HiWord)) if (HiWord > 0) then RxChecksum = CuLng(LoWord) + CuLng(HiWord) else exit do end if loop if (LoWord <> CuInt(&Hffff)) then RxChecksumOK = false else RxChecksumOK = true end if end function function GetTxChecksum() as UnsignedInteger Set GetTxChecksum = New UnsignedInteger Dim HiWord as new UnsignedInteger Dim LoWord as new UnsignedInteger do call BlockMove(2, MemAddress(TxChecksum), MemAddress(LoWord)) call BlockMove(2, MemAddress(TxChecksum)+2, MemAddress(HiWord)) if (HiWord > 0) then TxChecksum = CuLng(LoWord) + CuLng(HiWord) else GetTxChecksum = Not LoWord exit do end if loop end function ' ' Flush the current receive buffer ' sub AbortRx() Call IOWriteWord(IO_PPPtr, Reg_RxConfig) Data = IOReadWord(IO_PPData0) Call PutBit(Data, 6, 1) Call IOWriteWord(IO_PPData0, CInt(Data)) end sub ' ' Bid for tx memory and initialize tx ' sub PrepareTx(ByVal Length as Integer, ByVal Protocol as Integer) if Length = 0 then Length = CInt(EthernetLength) end if ' call IOWriteWord(IO_TxCmd, Bit_TxStartAtAll or Bit_TxPadDis) call IOWriteWord(IO_TxCmd, Bit_TxStartAtAll) call IOWriteWord(IO_TxLength, CInt(Length)) call IOWriteWord(IO_PPPtr, Reg_BusStatus) do data = IOReadWord(IO_PPData0) if (Data and Bit_TxBidErr = 1) then Debug.Print "Invalid TxLength" exit sub end if loop until (Data and Bit_Rdy4TxNow <> 0) call IOWriteWord(IO_RxTx0, OtherIEEEAddress(1)) call IOWriteWord(IO_RxTx0, OtherIEEEAddress(2)) call IOWriteWord(IO_RxTx0, OtherIEEEAddress(3)) call IOWriteWord(IO_RxTx0, MyIEEEAddress(1)) call IOWriteWord(IO_RxTx0, MyIEEEAddress(2)) call IOWriteWord(IO_RxTx0, MyIEEEAddress(3)) call IOWriteWord(IO_RxTx0, Protocol) TxChecksum = CULng(0) end sub ' ' Process the IP Packet. Right now we're interested only in ICMP (ping). ' sub ProcessIP() Dim Count as Integer dim PacketParms(1 to 9) as Integer dim Payload(1 to 50) as Integer dim DataLength as Integer Dim HeaderLength as new UnsignedInteger Dim RxPayloadLength as new UnsignedInteger dim TxPayloadLength as new UnsignedInteger RxChecksum = CULng(0) ' ' Reading from IO_RxTx0 retrieves a byte from received frame, ' ' Read version(4 bits), header length(4), type (8), total length(16) ' and store it ' Data = IOReadWord(IO_RxTx0) PacketParms(1) = Data call BlockMove(2, MemAddress(Data), MemAddress(Bytes)) HeaderLength = CuInt(Bytes(1) and &h0f) * 4 PacketParms(2) = IOReadWord(IO_RxTx0) RxPayloadLength = EthernetLength - HeaderLength - 14 TxPayLoadLength = RxPayloadLength ' ' Identification(16), flags(4), fragment offset(12) ' PacketParms(3) = IOReadWord(IO_RxTx0) PacketParms(4) = IOReadWord(IO_RxTx0) ' ' Eat TTL, Parse Protocol ' Data = IOReadWord(IO_RxTx0) PacketParms(5) = Data Call BlockMove(2, MemAddress(Data), MemAddress(Bytes)) ' Debug.Print "Minor Protocol ";CStr(CInt(Bytes(2))) if (Bytes(2) <> Minor_ICMP) then ' ' Flush the Rx buffer ' Call AbortRx() exit sub end if Debug.Print "ICMP "; Data = IOReadWord(IO_RxTx0) ' read in received checksum ' ' Read in source IP address ' OtherIPAddress(1) = IOReadWord(IO_RxTx0) OtherIPAddress(2) = IOReadWord(IO_RxTx0) ' ' Read in Dest IP address (that would be us, hopefully) ' Data = IOReadWord(IO_RxTx0) Data = IOReadWord(IO_RxTx0) ' ' RxChecksum OK? ' if (RxChecksumOK() <> True) then Debug.Print " Bad RxChecksum " exit sub end if ' ' So the IP checksum checked out OK. This is ICMP so now we have to check the IP header ' checksum. ' RxChecksum = CuLng(0) Data = IOReadWord(IO_RxTx0) ' read in ICMP type and code RxPayloadLength = RxPayloadLength - 2 call BlockMove(2, MemAddress(Data), MemAddress(Bytes)) ' ' We're only interested in Echo Request ' if (Bytes(1) <> ICMP_EchoRequest) then exit sub end if Bytes(1) = 0 ' set to echo reply call BlockMove(2, MemAddress(Bytes), MemAddress(Data)) PacketParms(6) = Data Data = IOReadWord(IO_RxTx0) ' read in checksum PacketParms(7) = IOReadWord(IO_RxTx0) ' identification PacketParms(8) = IOReadWord(IO_RxTx0) ' sequence number RxPayloadLength = RxPayloadLength - 6 ' ' Save the payload for later ' Count = 1 RxPayloadLength = RxPayloadLength \ 2 DataLength = CInt(RxPayloadLength) do while ((Count <= DataLength) and (Count < 50)) Payload(Count) = IOReadWord(IO_RxTx0) Count = Count + 1 loop if (RxChecksumOK() <> True) then Debug.Print "Bad ICMP checksum" exit sub end if ' ' So, it's a good ICMP Echo Request. Flash the LED. ' if LEDFlag = false then Call PutPin(25, bxOutputLow) Call PutPin(26, bxOutputHigh) LEDFlag = true else Call PutPin(25, bxOutputHigh) Call PutPin(26, bxOutputLow) LEDFlag = false end if ' ' Build the Echo Reply ' Initialize tx ' Call PrepareTx(0, Major_IP) ' use EthernetLength for Count = 1 to 5 call IOWriteWord(IO_RxTx0, PacketParms(Count)) next ' ' Add IP addresses into header checksum and send it ' TxChecksum = TxChecksum + CuLng(MyIPAddress(1)) TxChecksum = TxChecksum + CuLng(MyIPAddress(2)) TxChecksum = TxChecksum + CuLng(OtherIPAddress(1)) TxChecksum = TxChecksum + CuLng(OtherIPAddress(2)) call IOWriteWord(IO_RxTx0, CInt(GetTxChecksum())) ' ' Source IP = dest and vice versa ' call IOWriteWord(IO_RxTx0, MyIPAddress(1)) call IOWriteWord(IO_RxTx0, MyIPAddress(2)) call IOWriteWord(IO_RxTx0, OtherIPAddress(1)) call IOWriteWord(IO_RxTx0, OtherIPAddress(2)) ' ' Write out ICMP header ' TxChecksum = CuLng(0) call IOWriteWord(IO_RxTx0, PacketParms(6)) ' type/code TxPayloadLength = TxPayloadLength - 2 ' ' Calculate and send ICMP checksum ' TxChecksum = TxChecksum + CuLng(PacketParms(7)) TxChecksum = TxChecksum + CuLng(PacketParms(8)) for Count = 1 to DataLength TxChecksum = TxChecksum + CuLng(Payload(Count)) next call IOWriteWord(IO_RxTx0, CInt(GetTxChecksum())) call IOWriteWord(IO_RxTx0, PacketParms(7)) ' identification call IOWriteWord(IO_RxTx0, PacketParms(8)) ' sequence number TxPayloadLength = TxPayloadLength - 6 for Count = 1 to DataLength call IOWriteWord(IO_RxTx0, Payload(Count)) next end sub ' ' Process Address Resolution Protocol ' sub ProcessARP() dim Count as Integer Dim Bytes(1 to 2) as Byte ' ' Read hardware type ' if IOReadWord(IO_RxTx0) <> ARP_Ethernet then Debug.Print "Bad hardware type" call AbortRx() exit sub end if ' ' Read protocol ' if IOReadWord(IO_RxTx0) <> ARP_IP then Debug.Print "Bad protocol" call AbortRx() exit sub end if ' ' Read hardware address length, protocol address length ' Data = IOReadWord(IO_RxTx0) ' ' Read opcode ' Data = IOReadWord(IO_RxTx0) if Data <> ARP_Request then CHexStr(Data) Debug.Print "Bad opcode ";Mid(HexString,1,4) end if ' ' Store source hardware address for reply ' OtherIEEEAddress(1) = IOReadWord(IO_RxTx0) OtherIEEEAddress(2) = IOReadWord(IO_RxTx0) OtherIEEEAddress(3) = IOReadWord(IO_RxTx0) ' ' Store source protocol address ' OtherIPAddress(1) = IOReadWord(IO_RxTx0) OtherIPAddress(2) = IOReadWord(IO_RxTx0) ' ' Destination hardware address is zeroes so we don't care ' data = IOReadWord(IO_RxTx0) data = IOReadWord(IO_RxTx0) data = IOReadWord(IO_RxTx0) ' ' See if the destination protocol address is ours ' if ((IOReadWord(IO_RxTx0) <> MyIPAddress(1)) or _ (IOReadWord(IO_RxTx0) <> MyIPAddress(2))) then Debug.Print "Not our IP address" call AbortRx() exit sub end if ' ' It's ours, build the reply ' Debug.Print "ARP "; Call PrepareTx(42, Major_ARP) call IOWriteWord(IO_RxTx0, ARP_Ethernet) ' hardware type call IOWriteWord(IO_RxTx0, ARP_IP) ' protocol type ' call IOWriteWord(IO_RxTx0, &H0604) ' hardware and protocol length call IOWriteWord(IO_RxTx0, &H0406) ' hardware and protocol length call IOWriteWord(IO_RxTx0, ARP_Reply) ' opcode call IOWriteWord(IO_RxTx0, MyIEEEAddress(1)) ' source hardware address call IOWriteWord(IO_RxTx0, MyIEEEAddress(2)) ' ... call IOWriteWord(IO_RxTx0, MyIEEEAddress(3)) ' ... call IOWriteWord(IO_RxTx0, MyIPAddress(1)) ' source protocol address call IOWriteWord(IO_RxTx0, MyIPAddress(2)) ' ... call IOWriteWord(IO_RxTx0, OtherIEEEAddress(1)) ' source hardware address call IOWriteWord(IO_RxTx0, OtherIEEEAddress(2)) ' ... call IOWriteWord(IO_RxTx0, OtherIEEEAddress(3)) ' ... call IOWriteWord(IO_RxTx0, OtherIPAddress(1)) ' source protocol address call IOWriteWord(IO_RxTx0, OtherIPAddress(2)) ' ... end sub ' ' RxEthernetPacket process incoming packet ' function RxEthernetPacket() as Boolean Dim Count as Integer Call IOWriteWord(IO_PPPtr, Reg_RxEvent) if (IOReadWord(IO_PPData0) and &H0100 <> 0) then Data = IOReadWordHL(IO_RxTx0) ' read status EthernetLength = CUInt(IOReadWordHL(IO_RxTx0)) ' read length ' ' Discard the destination IEEE address ' for Count = 1 to 3 Data = IOReadWord(IO_RxTx0) next ' ' Source IEEE address ' for Count = 1 to 3 OtherIEEEAddress(Count) = IOReadWord(IO_RxTx0) next ' ' Packet type ' MajorProtocol = IOReadWord(IO_RxTx0) ' EthernetLength = EthernetLength - 14 RxEthernetPacket = True else RxEthernetPacket = False end if end function sub main() Dim Count as Integer HexTable = "0123456789abcdef" LEDFlag = false Delay(5.0) ' sleep for 5 secs so NetMedia's flaky download can work ' ' Init the EEPROM data ' Call PersistentIEEE.Source("IEEE.TXT") Call PersistentIP.Source("IP.TXT") ' ' Try to ID the chip ' if (Init() = 1) then Debug.Print "Init OK" else Debug.Print "Init Failed" End if ' ' Show chip status ' Debug.Print "--------------------------- INIT 1 -------------------------------" Call IOWriteWord(IO_PPPtr, Reg_EISAID) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "EISA Reg ID = "; Mid(HexString, 1, 4) Call IOWriteWord(IO_PPPtr, Reg_PID) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "PID = "; Mid(HexString, 1, 4) Call IOWriteWord(IO_PPPtr, Reg_IOBase) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "I/O Base = "; Mid(HexString, 1, 4) Call IOWriteWord(IO_PPPtr, Reg_SelfStatus) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "Chip Status = "; Mid(HexString, 1, 4) Call IOWriteWord(IO_PPPtr, Reg_LineStatus) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "Line Status = "; Mid(HexString, 1, 4) Call IOWriteWord(IO_PPPtr, Reg_SelfControl) CHexStr(IOReadWord(IO_PPData0)) Debug.Print "Chip Control = "; Mid(HexString, 1, 4) Debug.Print "------------------------ END INIT -------------------------------" Call SetIEEEAddress() do do while RxEthernetPacket() = False loop Select Case MajorProtocol case Major_IP Call ProcessIP() ' case Major_X25 ' Debug.Print "X.25"; case Major_ARP call ProcessARP() ' case Major_RARP ' Debug.Print "RARP"; ' case Major_IPXSPX ' Debug.Print "IPX/SPX"; ' Case else ' CHexStr(MajorProtocol) ' Debug.Print "Unknown Protocol ";Mid(HexString, 1, 4) end select loop end sub