Using the 8390 Code
The code has been written to reduce the amount of overhead required to
get the code working. The best way to see how easily the code intergrates
into an application is to examine the ETHTEST.ASM code. Below is an overview
of the code, and what the user variables etc are and how they affect the
compilation and execution of the ethernet driver.
REQUIREMENTS
The minimum requirements for using the 8390 code are:
- 8390 chipset compatible network card configured in the XDATA address
space on a page boundary
- 3.5k RAM configured on a page boundary (depends on size of Transmit
and Receive Buffer)
- One spare interrupt, either INT0 or INT1
FUNCTIONS OF THE CODE
While the code is lengthly, there are only five (5) routines that should
be called from the calling program. These routines are explained in greater
detail below. In short, the routines are:
- Int8390 - Interrupt portion of the driver
- Probe8390 - Attempts to locate an 8390 compatible
card at the IOAddr page boundary
- NS8390_Init - Initializes the NIC
- EIGetPacket - Retrieves a packet from the
NIC
- SendPacket - Sends a packet from the TXBUFFER
on to the NIC and triggers a send
IMPLEMENTING THE CODE
To include support for the 8390 driver, Use the INCLUDE or similar directive
to add the 8390.INC file to your source. An example is
INCL "8390.INC" ; Include 8390 Ethernet drivers
This will compile both the 8390.INC file, as well and use the NEEQUATE.TXT
file which is also required for successful compilation.
A skeleton struction to get the code working would look like this:
ORG 0000h
ajmp Begin
ORG INT0 or INT1 address
ljmp Int8390
BEGIN:
<Start of initialization code>
lcall Probe8390
lcall NS8390_Init
<End of Initializtion code>
<Main program loop>
jnb EI_RXD, NoPktWait
lcall ProcessPacket
clr EI_RXD
NoPktWait:
sjmp MainLoop
INCL "8390.inc"
end
<---------- VARIABLES ---------->
This section describes the variables and there purpose. Listed here are
both user variables, and system use variables. User variables determine
run-time configurations. System use variables are used by the code to keep
track of itself and various status flags. The only system user variable
that should be modified by the application program is ei_RXD. Changing
any other System Variable may cause unpredicable behaviour.
Type of variable |
Name |
declared in file: |
Use |
| User Variables |
IOAddr
SAPROM
MultiByte
EIDebug
RXBuffer
TXBuffer |
8390.inc
8390.inc
8390.inc
8390.inc
8390.inc
8390.inc |
Page boundary setting of the NIC. (MSB)
Start of data area for SAPROM data
Byte to enter into Multicast array
TRUE to include debug information in code
Points to start of receive buffer
Points to start of transmit buffer |
| System Variables |
ei_Txing
ei_Rxd
dmaing
Next_Page |
8390.inc
8390.inc
8390.inc
8390.inc |
TRUE is card tranmitting data
TRUE is ReceiveBuffer contains valid data
TRUE is transferring data to NIC
Holds pointer to next page from NIC |
User Variables:
IOAddr: The contains the Most Significant
Byte of the word address of the NIC. For example. If the Address of the
NIC was at 6300h, then IOAddr would contain the value 63h. This value, combined
with the value stored in R1 addresses the correct register within the Network
Card.
SAPROM: This array, which at most will be
32 bytes long, but should only use the first 16 bytes, contains the data
stored on the PROM chip of the NIC. The most important data out of this
PROM area is the MAC address that the card uses. The initialization routine
uses the first 6 bytes at the start of array to program the NIC with the
MAC address programmed on the card. You could, but not recommended is to
program the NIC with your own MAC address. If you have multiple NICs on
the network with the same MAC address, you will create communication problems
- enough said.
Multibyte: Along with receiving normal
packets addressed for the MAC address of the card, you can also program
the card to accept Multicast packets. Normally, the value of this should
be 00h. See the 8390 datasheet for an explanation of this feature. Normally,
leave this value at 00h.
EIDebug: For production code, set this to
FALSE (0). Leaving this active will display some diagnostic messages if
certain conditions are met, i.e. unknown interrupt.
RXBuffer: This is the location of the start
of the receive buffer. If the EI_RXD variable is true, then the data in
this buffer is deemed to be valid and required to be processed. The maximum
length of data in this buffer will not exceed 1540 bytes, which the standard
MTU (Maximum Transmission Unit) used on ethernet. The length of the buffer
can be shorter, but should a packet be received which is longer than the
buffer it will overwrite other areas of memory! The data from the NIC is
entered into the buffer with the following characteristics:
Representation |
Function |
Number of Bytes |
| Frame Status |
Status of the received frame. |
1 |
| Next Packet Pointer |
Pointer to pointer to the next received packet |
1 |
| Length |
Length of the frame |
2, low byte first |
| Source Address |
MAC address of the card that the frame is destined for |
6 |
| Destination Address |
MAC Address of the card that sent the packet |
6 |
| Type of Service |
Type of packet, i.e 0800h = IP, 0806h = ARP |
2 |
| REST OF FRAME |
Remaining data within the frame. Will include other headers, i.e. IP. |
1...1518 bytes |
The length of the actual frame required for processing is calcutated with
the following formula: LENGTH (Bytes 2 and 3) - 18. The Frame Status and
Next Packet Pointer are copied for completeness, but are of no value to
the programmer. The remaining bytes before the REST OF FRAME are required
for transmit data formation and Type Of Service program branching.
TXBuffer: This points to the start of the
transmit buffer. This buffer should be set the size of the largest transmitted
packet + 14 bytes. The format of the transmit packet is as follows:
Description |
Description |
Number of Bytes |
| Destination Address |
MAC Address of the computer to send the packet too |
6 |
| Source Address |
MAC Address of this device, ie. of the NIC |
6 |
| Type of Service |
Type of information the packet contains, i.e. 0806 = ARP, 0800 = IP |
2 |
| REST OF FRAME |
Rest of the frame data, includes IP, ARP etc header and data. Note |
1... |
Note that no range checking of the size of the packet is performed. It is
up to the programmer to make sure that the size of the packet exceeds 50
bytes, and is less than 1518 bytes. Should the packet be less than 50 bytes,
some network cards will reject the packet, and not pass it up to the stack.
This also happens if the length of the packet exceeds 1518 bytes.
System Variables:
ei_Txing: This flag is set to true if the
NIC is sending data onto the network. It is used to prevent sending more
than one packet at a time. This flag is cleared within the interrupt subroutine
when an end of transmit interrupt occurs. If the program is transmitting
multiple packets, it should check the status of this flag before beginning
to assemble the next packet for transmittion and confirm that it is set
to false.
ei_RXD: This flag is set to TRUE if the data
in the Receive buffer should be processed. This is the only system variable
that the programmer should modify. Once the packet has been processed, the
programmer should clear this flag, otherwise no further packets will be
transferred from the NIC to the receive buffer. After this flag is cleared,
the subroutine EIGETPACKET should be called to retreive the next
packet from the NIC should it exist. If you do not call the EIGETPACKET
routine after clearing the flag, any packets waiting in the NIC will not
retrieved until the next interrupt at which time only one packet will be
retreived.
DMAING: This value is set to TRUE if data
is being transferred to or from the NIC. DO NOT change the value of this
variable, otherwise unpredictable results may occur.
Next_Page: Holds the page location of the
next packet to be retreived from the NIC.
DO NOT CHANGE THIS VARIABLE. Doing
so WILL cause packets to be lost within the NIC. It may even cause the NIC
to stop responding. |
<---------- SUBROUTINES ---------->
INT8390
ON EXTRY: NIL
ON EXIT: NIL
DESTROYS: NOTHING
As this code relies on an interrupt from the card to signal various states
of the card, a branch to INT8390 is required either at the INT0 or INT1
interrupt address of the card. This routine contains a RETI instruction,
so an LJMP or AJMP instruction is all that is required. The interrupt routine
performs the following functions:
- Saves the Program status register and changes the Microprocessor to
use register bank 1
- Saves working registers
- Changes P2 to the value of the IOADDR byte
- Get the interrupt value from the NIC
- If the NIC signals that it has received a packet, and the EI_RXD
flag is false, then the interrupt routine will call the EIGETPACKET
subroutine to load a packet from the NIC into the RXBuffer.
- repeats steps 3 and 4 until all interrupts have been serviced
- restore working registers
- Restores PSW thereby returning selected register bank to pre-interrupt
state
NOTE: Do not under any cercumstances atttempt to send a packet while
still in the interrupt routine. This will cause the NIC to stop. The only
way to overcome this is to use the reset button.
PROBE8390
ON ENTRY: NIL
ON EXIT: Carry flag reports status of the operation. if CF set, Accumulator
holds error value, otherwise Accumulator intederminate.
DESTROYS: R1, R2, R3, R4, P2
FUNCTION: To attempt to locate an 8390 compatible chipset NIC card
located on the IOADDR page boundary. If the operation is successful, the
CF is cleared, and the SAPROM contains valid information. If the search
for the card is unsuccessful, the CF bit is set, and the accumulator holds
the error code. Possible error codes are:
- NoCardFound - Unable to locate, or communicate with a NIC. Chances
are the IOADDR equate does not correspond to the page boundary that the
NIC is on.
- NoResetAck - Found a card, but did not get a return an acknowledgement
to the reset function. Same symptons as for NoCardFound.
- NoIRQFound - Found a card, can communicate with it, but no acknowlegement
to an interrupt. Check to make sure that the IRQ number programmed into
the NIC, and the line that you have attached to the microprocessor are
the same. Also, make sure that the interrupt is active and enabled.
NS8390_INIT
ON ENTRY: The first 6 bytes of the SAPROM array MUST contain
a the bytes for the MAC address.
ON EXIT: No status, it is assumed that this will finish with out
error. MAKE SURE THAT PROBE8390 is executed before this for error detection,
as well as to get the MAC address from the NIC.
DESTROYS: P2, R1, R2, Accumulator, DPTR
FUNCTION: Initializes the card, and turns on the Transmit and Receive
buffers. When this call completes, packets can be sent and received. This
routine can be called at any time to reset the NIC.
EIGETPACKET
ON ENTRY: EI_RXD flag set accordingly (see below)
ON EXIT: EI_RXD flag, if cleared upon entry will be set
if a packet has been transferred from the NIC to the Receive buffer.
DESTROYS: P2
FUNCTION: To retrieve a packet from the NIC if one is waiting. If
EI_RXD is set upon entry to this routine, the routine will exit
as the receive buffer is flagged as containing valid data. If the EI_RXD
flag is clear upon entry to this routine and a packet is waiting in the
NIC for retrieval, then the packet is transferred to the ReceiveBuffer and
this flag set. The interrupt to the NIC is switched off during the data
transfer.
SENDPACKET
ON ENTRY: DPTR points to the data to be transmitted. R3/R4 contains
the length of the data to be transferred.
ON EXIT: No exit code. Assume success.
DESTROYS: CF, Accumulator, P2, R1
FUNCTION: To send a packet pointed to by DPTR onto the ethernet network.
No checks are performed on the data to confirm validity. To be a valid ethernet
packet, the minimum size if the packet shall be no less than 60 bytes or
greater than 1518 bytes. The NIC interrupt is turned off during the transmit
to prevent any extraneous errors.
DO NOT call this routine from within
an interrupt routine. Doing so will stop the network card. |
Home |