36,6 → 36,22 |
; |
;******************************************************************** |
|
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel |
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel |
ETHER_RARP equ 0x3580 |
|
struc ETH_FRAME |
{ .DstMAC dp ? ;destination MAC-address [6 bytes] |
.SrcMAC dp ? ;source MAC-address [6 bytes] |
.Type dw ? ;type of the upper-layer protocol [2 bytes] |
.Data db ? ;data [46-1500 bytes] |
} |
|
virtual at Ether_buffer |
ETH_FRAME ETH_FRAME |
end virtual |
|
|
; Some useful information on data structures |
|
; Ethernet Packet - ARP Request example |
75,19 → 91,15 |
; Include individual drivers source files at this point. |
; If you create a new driver, include it below. |
|
include "rtl8029.inc" |
include "i8255x.inc" |
include "rtl8139.inc" |
include "3c59x.inc" |
include "sis900.inc" |
include "pcnet32.inc" |
include "drivers/rtl8029.inc" |
include "drivers/i8255x.inc" |
include "drivers/rtl8139.inc" |
include "drivers/3c59x.inc" |
include "drivers/sis900.inc" |
include "drivers/pcnet32.inc" |
;include "drivers/mtd80x.inc" |
include "drivers/rtl8169.inc" |
|
; DEBUGGING_STATE enables or disables output of received and transmitted |
; data over the serial port |
DEBUGGING_ENABLED equ 1 |
DEBUGGING_DISABLED equ 0 |
DEBUGGING_STATE equ DEBUGGING_ENABLED |
|
; PCICards |
; ======== |
; PCI vendor and hardware types for hardware supported by the above drivers |
100,99 → 112,98 |
; be several lines which refer to the same functions. |
; The first driver found on the PCI bus will be the one used. |
|
PCICARDS_ENTRY_SIZE equ 20 ; Size of each PCICARDS entry |
PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry |
|
iglobal |
PCICards: |
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit |
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit |
dd 0x12111113, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit |
dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
; /+/ Íîâûå âåíäîðû ñåòåâûõ êàðò íà áàçå rtl8139 |
dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit |
; /-/ |
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit |
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit |
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit |
; following card is untested |
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit |
dd 0,0,0,0,0 ; end of list marker, do not remove |
endg |
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 |
dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 |
dd 0x12111113, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 |
|
; PCI Bus defines |
PCI_HEADER_TYPE equ 0x0e ;8 bit |
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit |
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits |
PCI_BASE_ADDRESS_SPACE_IO equ 0x01 |
PCI_VENDOR_ID equ 0x00 ;16 bit |
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC |
dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable |
|
ETHER_IP equ 0x0008 ; Reversed from 0800 for intel |
ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel |
ETHER_RARP equ 0x3580 |
ARP_REQ_OPCODE equ 0x0100 |
ARP_REP_OPCODE equ 0x0200 |
dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 |
|
dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 |
|
dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
|
dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 |
|
;dd 0x08031516, mtd80x_probe, mtd80x_reset, mtd80x_poll, mtd80x_transmit, mtd80x_cable |
|
; following cards are untested |
dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 |
;dd 0x08001516, mtd80x_probe, mtd80x_reset, mtd80x_poll, mtd80x_transmit, mtd80x_cable |
;dd 0x08911516, mtd80x_probe, mtd80x_reset, mtd80x_poll, mtd80x_transmit, mtd80x_cable |
|
rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove |
endg |
|
uglobal |
arp_rx_count: dd 0 |
ip_rx_count: dd 0 |
dumped_rx_count: dd 0 |
ip_tx_count: dd 0 |
;Net-stack's interface's settings |
node_addr: db 0,0,0,0,0,0 |
gateway_ip: dd 0 |
dns_ip: dd 0 |
|
eth_rx_data_len: dw 0 |
eth_status: dd 0 |
io_addr: dd 0 |
207,190 → 218,21 |
drvr_reset: dd 0 |
drvr_poll: dd 0 |
drvr_transmit: dd 0 |
drvr_cable: dd 0 |
|
; These hold the destination Host identity for ARP responses |
remote_ip_add: dd 0 |
remote_hw_add: db 0, 0, 0, 0, 0, 0 |
endg |
|
iglobal |
broadcast_add: db 0xff,0xff,0xff,0xff,0xff,0xff |
subnet_mask: dd 0x00ffffff |
subnet_mask: dd 0x00ffffff ; 255.255.255.0 |
endg |
|
uglobal |
; This is used by getMACfromIP |
MACAddress: db 0,0,0,0,0,0 |
gateway_ip: db 0, 0, 0, 0 |
dns_ip: dd 0 |
endg |
include "arp.inc" ;arp-protocol functions |
include "pci.inc" ;PCI bus access functions |
|
; The follow is the ARP Table. |
; This table must be manually updated and the kernel recompilied if |
; changes are made to it. |
; ARP_TABLE_SIZE defines the size of the table |
; ARP_TABLE_ENTRIES defines the number of entries in the table |
; Each entry is 10 bytes: 4 Byte IP address, 6 byte MAC Address, |
; 2 bytes status, 2 bytes TTL ( in seconds ) |
; Empty entries are filled with zeros |
; The TTL field is decremented every second, and is deleted when it |
; reaches 0. It is refreshed every time a packet is received |
; If the TTL field is 0xFFFF it is a permanent entry and is never deleted |
; The status field can be the following values |
; 0x0000 entry not used |
; 0x0001 entry holds a valid mapping |
; 0x0002 entry contains an IP address, awaiting ARP response |
; 0x0003 No response received to ARP request. |
; The last status value is provided to allow the network layer to delete |
; a packet that is queued awaiting an ARP response |
|
ARP_NO_ENTRY equ 0 |
ARP_VALID_MAPPING equ 1 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
|
ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry |
ARP_TABLE_SIZE equ 20 ; Size of table |
ARP_TABLE_ENTRIES equ 0 ; Inital, hardcoded entries |
|
uglobal |
ARPTable: |
times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 |
endg |
|
iglobal |
NumARP: db ARP_TABLE_ENTRIES |
endg |
|
;*************************************************************************** |
; Function |
; eth_probe |
; Description |
; Searches for an ethernet card. If found, the card is enabled and |
; the ethernet -> IP link established |
; |
; This function scans the PCI bus looking for a supported device. |
; ISA bus is currently not supported. |
; |
; eax is 0 if no hardware found |
;*************************************************************************** |
eth_probe: |
; Find a card on the PCI bus, and get it's address |
call scan_bus ; Find the ethernet cards PIC address |
xor eax, eax |
cmp [io_addr], eax |
je ep_00x ; Return 0 in eax if no cards found |
|
call dword [drvr_probe] ; Call the drivers probe function |
|
mov eax, [io_addr] ; return a non zero value |
|
ep_00x: |
ret |
|
;*************************************************************************** |
; Function |
; ethernet_driver |
; |
; Description |
; The ethernet RX and TX handler |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
ethernet_driver: |
; Do nothing if the driver is inactive |
cmp [ethernet_active], byte 0 |
je eth_exit |
|
call eth_rx |
call eth_tx |
|
eth_exit: |
ret |
|
;*************************************************************************** |
; Function |
; eth_rx |
; |
; Description |
; Polls the ethernet card for received data. Extracts if present |
; Depending on the Protocol within the packet: |
; ARP : Pass to ARP_handler. This may result in an ARP reply |
; being tx'ed |
; IP : Store in an IP buffer |
; |
;*************************************************************************** |
eth_rx: |
xor ax, ax |
mov [eth_rx_data_len], ax |
call dword [drvr_poll] ; Call the drivers poll function |
|
mov ax, [eth_rx_data_len] |
cmp ax, 0 |
je erx_exit |
|
if DEBUGGING_STATE = DEBUGGING_ENABLED |
pusha |
mov eax, 0 ;Indicate that this is a received packet |
mov cx, [eth_rx_data_len] |
mov esi, Ether_buffer |
cmp word [esi + 12], ETHER_IP |
jnz erxd_done |
; cmp byte [esi + 14 + 9], 0x06 ; TCP |
; jnz erxd_done |
call eth_dump |
erxd_done: |
popa |
end if |
|
; Check the protocol. Call appropriate handler |
mov eax, Ether_buffer |
add eax, 12 ; The address of the protocol word |
|
mov ax, [eax] |
|
cmp ax, ETHER_ARP |
je erx_001 ; It is ARP |
|
cmp ax, ETHER_IP |
je erx_002 ; It's IP |
|
; inc dword [dumped_rx_count] |
|
jmp erx_exit ; If not IP or ARP, ignore |
|
erx_001: |
mov eax, [arp_rx_count] |
inc eax |
mov [arp_rx_count], eax |
|
; At this point, the packet is still in the Ether_buffer |
call arp_handler |
|
jmp erx_exit |
|
erx_002: |
mov eax, [ip_rx_count] |
inc eax |
mov [ip_rx_count], eax |
|
; Check to see if the MAC address is in our arp table |
; refresh the arp ttl if so |
|
mov esi, Ether_buffer |
add esi, 6 |
|
call refreshARP |
|
call ether_IP_handler |
|
jmp erx_exit |
|
erx_exit: |
ret |
|
;*************************************************************************** |
; Function |
; eth_tx |
; |
; Description |
403,18 → 245,19 |
; Places buffer on empty queue when the tx routine finished |
; |
;*************************************************************************** |
eth_tx: |
proc eth_tx stdcall uses ebx esi edi |
local MACAddress dp ? ;allocate 6 bytes in the stack |
|
; Look for a buffer to tx |
mov eax, NET1OUT_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je eth_exit ; Exit if no buffer available |
je .exit ; Exit if no buffer available |
|
push eax |
push eax ;save buffer number |
|
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
imul eax, IPBUFFSIZE |
add eax, IPbuffs |
|
; Extract the destination IP |
425,94 → 268,37 |
|
; If the destination address is 255.255.255.255, |
; set the MACAddress to all ones ( broadcast ) |
mov [MACAddress], dword 0xffffffff |
mov [MACAddress + 4], word 0xffff |
cld |
mov esi, broadcast_add |
lea edi, [MACAddress] |
movsd |
movsw |
cmp edx, 0xffffffff |
je etx_send ; If it is broadcast, just send |
je .send ; If it is broadcast, just send |
|
call getMACfromIP ; Get the MAC address. |
lea eax, [MACAddress] ;cause this is local variable |
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax ;opcode,IP,MAC_ptr - Get the MAC address. |
|
cmp eax, ARP_VALID_MAPPING |
jz etx_send |
je .send |
|
; No valid entry. Are we waiting for a response? |
cmp eax, ARP_AWAITING_RESPONSE |
jne etx_001 |
; No valid entry. Has the request been sent, but timed out? |
cmp eax, ARP_RESPONSE_TIMEOUT |
je .freebuf |
|
.wait_response: ;we wait arp-response |
; Re-queue the packet, and exit |
pop ebx |
mov eax, NET1OUT_QUEUE |
call queue |
jmp etx_exit |
call queue ; Get the buffer back |
jmp .exit |
|
etx_001: |
; HAs the request been sent, but timed out? |
cmp eax, ARP_RESPONSE_TIMEOUT |
jne etx_002 |
|
pop eax |
call freeBuff |
jmp etx_exit |
|
etx_002: |
; There is no entry. Re queue the request, and ask ARP to send a request |
|
; IP address is in edx |
push edx |
call arp_request |
pop ebx |
|
; Add an entry in the ARP table, awaiting response |
|
cmp byte [NumARP], ARP_TABLE_SIZE |
je etx_003 ; We cannot add a new entry in the table |
|
inc byte [NumARP] |
|
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
sub eax, ARP_ENTRY_SIZE |
|
mov [eax + ARPTable], ebx |
xor ebx, ebx |
mov [eax + ARPTable + 4], ebx |
mov [eax + ARPTable + 8], bx |
|
; set the status field up - awaiting response |
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x02 |
mov [eax + ARPTable + 11], cl |
|
; Initialise the time to live field - 10s |
mov cx, 0x000A |
mov [eax + ARPTable + 12], cx |
|
etx_003: |
pop ebx ; Get the buffer back |
mov eax, NET1OUT_QUEUE |
call queue |
jmp etx_exit |
|
etx_send: |
xor ecx, ecx |
mov ch, [ebx+2] |
mov cl, [ebx+3] ; ; Size of IP packet to send |
|
mov esi, ebx |
|
mov edi, MACAddress |
|
if DEBUGGING_STATE = DEBUGGING_ENABLED |
pusha |
mov cx, 42 |
mov eax, 1 ; Indicate that this is a tx packet |
call eth_dump |
popa |
end if |
|
mov bx, ETHER_IP |
.send: ;if ARP_VALID_MAPPING then send the packet |
lea edi, [MACAddress] ; Pointer to 48 bit destination address |
movzx ecx, word[ebx+2] ; Size of IP packet to send |
xchg ch, cl ; because mirror byte-order |
mov esi, ebx ; Pointer to packet data |
mov bx, ETHER_IP ; Type of packet |
call dword [drvr_transmit] ; Call the drivers transmit function |
|
; OK, we have sent a packet, so increment the count |
519,11 → 305,13 |
inc dword [ip_tx_count] |
|
; And finally, return the buffer to the free queue |
.freebuf: |
pop eax |
call freeBuff |
|
etx_exit: |
.exit: |
ret |
endp |
|
;*************************************************************************** |
; Function |
554,7 → 342,7 |
mov edi, eax |
|
; get a pointer to the start of the DATA |
mov esi, Ether_buffer + 14 |
mov esi, ETH_FRAME.Data |
|
; Now store it all away |
mov ecx, IPBUFFSIZE / 4 ; Copy all of the available |
571,1131 → 359,95 |
ret |
|
;*************************************************************************** |
; |
; ARP CODE FOLLOWS |
; |
; The ARP code is used by ethernet drivers to translate an destination |
; IP address into an ethernet hardware address. Functions to broadcast |
; requests and handle response are (or will be) here. |
; The IP layer has no knowledge of ARP, as this is a network interface |
; issue |
; |
;*************************************************************************** |
|
;*************************************************************************** |
; Function |
; arp_timer |
; |
; eth_probe |
; Description |
; Called every 1s |
; It is responsible for removing expired routes |
; All registers may be destroyed |
; Searches for an ethernet card. If found, the card is enabled and |
; the ethernet -> IP link established |
; |
;*************************************************************************** |
arp_timer: |
; loop through all the ARP entries, decrementing each one |
; that doesn't have a TTL of 0xFFFF |
movzx eax, byte [NumARP] |
|
arp_001: |
cmp eax, 0 |
je arp_003 |
|
push eax |
dec eax |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
cmp word [ eax + ARPTable + 12], 0xFFFF |
je arp_002 |
|
cmp word [ eax + ARPTable + 12], 0 |
je arp_002 |
|
dec word [eax + ARPTable + 12] |
|
arp_002: |
pop eax |
dec eax |
jmp arp_001 |
|
; Now, look for entries with a TTL of 0 |
; Valid entries and response timeout entries get removed |
; awaiting response gets converted into a response timeout, with a |
; short life time - this allows queued packets to be flushed |
arp_003: |
movzx edx, byte [NumARP] |
cmp edx, 0 |
je arp_exit |
|
; EDX holds the # of entries to search through |
mov eax, 0 |
|
arp_005: |
cmp word [ eax + ARPTable + 12], 0 |
jne arp_004 |
|
; If it's status code is 0001 or 0003, delete the entry |
cmp word [eax + ARPTable + 10], 0x0100 |
je arp_007 |
cmp word [eax + ARPTable + 10], 0x0300 |
je arp_007 |
|
; The only other valid code is 0002 - indicating a |
; timeout while waiting for a response. Change the |
; entry to response timed out |
|
mov [eax + ARPTable + 10], word 0x0300 |
mov [eax + ARPTable + 12], word 0x000A |
jmp arp_004 |
|
arp_007: |
; Delete this entry |
mov edi, ARPTable |
add edi, eax |
mov esi, edi |
add esi, ARP_ENTRY_SIZE |
|
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE |
sub ecx, eax |
|
rep movsb |
|
dec byte [NumARP] |
jmp arp_006 |
|
arp_004: |
add eax, ARP_ENTRY_SIZE |
arp_006: |
dec edx |
cmp edx, 0 |
jne arp_005 |
|
arp_exit: |
ret |
|
;*************************************************************************** |
; Function |
; arp_request |
; This function scans the PCI bus looking for a supported device. |
; ISA bus is currently not supported. |
; |
; Description |
; Sends an ARP request on the ethernet |
; The requested IP address is in edx |
; All registers may be destroyed |
; |
; eax is 0 if no hardware found |
;*************************************************************************** |
arp_request: |
mov ebx, Ether_buffer |
mov ax, 0x0100 |
mov [ebx], ax |
add ebx, 2 |
|
mov ax, 0x0008 |
mov [ebx], ax |
add ebx, 2 |
|
mov ax, 0x0406 |
mov [ebx], ax |
add ebx, 2 |
|
mov ax, 0x0100 |
mov [ebx], ax |
add ebx, 2 |
|
mov ecx, node_addr |
mov eax, [ecx] |
mov [ebx], eax |
add ecx, 4 |
add ebx, 4 |
mov ax, [ecx] |
mov [ebx], ax |
add ebx, 2 |
mov eax, [stack_ip] |
mov [ebx], eax |
add ebx, 4 |
|
eth_probe: |
; Find a card on the PCI bus, and get it's address |
call scan_bus ; Find the ethernet cards PIC address |
xor eax, eax |
mov [ebx], eax |
add ebx, 4 |
mov [ebx], ax |
cmp [io_addr], eax |
je ep_00x ; Return 0 in eax if no cards found |
|
add ebx, 2 |
mov [ebx], edx |
call dword [drvr_probe] ; Call the drivers probe function |
|
; Now, send it! |
mov eax, [io_addr] ; return a non zero value |
|
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
mov edi, broadcast_add |
|
;if DEBUGGING_STATE = DEBUGGING_ENABLED |
; pusha |
; mov eax, 1 ; Indicate that this is a tx packet |
; mov ecx, 28 |
; mov esi, Ether_buffer |
; call eth_dump |
; popa |
;end if |
|
mov bx, ETHER_ARP |
mov ecx, 28 |
mov esi, Ether_buffer |
call dword [drvr_transmit] ; Call the drivers transmit function |
ep_00x: |
ret |
|
;*************************************************************************** |
; Function |
; arp_handler |
; ethernet_driver |
; |
; Description |
; Called when an ARP packet is received on the ethernet |
; Header + Data is in Ether_buffer[] |
; It looks to see if the packet is a request to resolve this Hosts |
; IP address. If it is, send the ARP reply packet. |
; This Hosts IP address is in dword [stack_ip] ( in network format ) |
; This Hosts MAC address is in node_addr[6] |
; All registers may be destroyed |
; The ethernet RX and TX handler |
; This is a kernel function, called by stack_handler |
; |
;*************************************************************************** |
arp_handler: |
; Is this a REQUEST? |
; Is this a request for My Host IP |
; Yes - So construct a response message. |
; Send this message to the ethernet card for transmission |
ethernet_driver: |
; Do nothing if the driver is inactive |
cmp [ethernet_active], byte 0 |
je eth_exit |
|
mov ebx, Ether_buffer |
call eth_rx |
call eth_tx |
|
mov edx, ebx |
add edx, 20 |
mov ax, [edx] |
cmp ax, ARP_REQ_OPCODE ; Is this a request packet? |
jne arph_resp ; No - so test for response |
|
mov edx, ebx |
add edx, 38 |
mov eax, [edx] |
|
cmp eax, [stack_ip] ; Is it looking for my IP address? |
jne arph_exit ; No - so quit now |
|
; OK, it is a request for my MAC address. Build the frame and send it |
|
; Save the important data from the original packet |
; remote MAC address first |
mov ecx, remote_hw_add |
mov edx, ebx |
add edx, 22 ; edx points to Source h/w address |
mov eax, [edx] |
mov [ecx], eax |
add edx, 4 |
add ecx, 4 |
mov ax, [edx] |
mov [ecx],ax |
|
; and also the remote IP address |
add edx, 2 |
mov eax,[edx] |
mov [remote_ip_add], eax |
|
; So now we can reuse the packet. ebx still holds the address of |
; the header + packet |
; We dont need the header ( first 14 bytes ) |
|
mov edx, ebx |
add edx, 20 |
mov ax, ARP_REP_OPCODE |
mov [edx], ax |
add edx, 2 |
|
mov ecx, node_addr |
mov eax, [ecx] |
mov [edx], eax |
add ecx, 4 |
add edx, 4 |
mov ax, [ecx] |
mov [edx], ax |
add edx, 2 |
mov eax, [stack_ip] |
mov [edx], eax |
add edx, 4 |
mov ecx, remote_hw_add |
mov eax, [ecx] |
mov [edx], eax |
add ecx, 4 |
add edx, 4 |
mov ax, [ecx] |
mov [edx], ax |
|
add edx, 2 |
mov eax, [remote_ip_add] |
mov [edx], eax |
|
; Now, send it! |
|
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
mov edi, remote_hw_add |
|
;if DEBUGGING_STATE = DEBUGGING_ENABLED |
; pusha |
; mov eax, 1 ; Indicate that this is a tx packet |
; mov ecx, 28 |
; mov esi, Ether_buffer + 14 |
; call eth_dump |
; popa |
;end if |
|
mov bx, ETHER_ARP |
mov ecx, 28 |
mov esi, Ether_buffer + 14 |
call dword [drvr_transmit] ; Call the drivers transmit function |
jmp arph_exit |
|
arph_resp: |
cmp ax, ARP_REP_OPCODE ; Is this a replypacket? |
jne arph_resp ; No - so quit |
|
; This was a reply, probably directed at me. |
; save the remotes MAC & IP |
mov ecx, remote_hw_add |
mov edx, ebx |
add edx, 22 ; edx points to Source h/w address |
mov eax, [edx] |
mov [ecx], eax |
add edx, 4 |
add ecx, 4 |
mov ax, [edx] |
mov [ecx],ax |
|
; and also the remote IP address |
add edx, 2 |
mov eax,[edx] |
mov [remote_ip_add], eax |
|
; Now, add an entry in the table for this IP address if it doesn't exist |
|
push eax |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
pop edx |
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je arph_002 |
|
arph_001: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable], edx |
loopnz arph_001 ; Return back if non match |
|
jnz arph_002 ; None found, add to end |
|
mov ecx, [remote_hw_add] |
mov [eax + ARPTable + 4], ecx |
mov cx, [remote_hw_add+4] |
mov [eax + ARPTable + 8], cx |
|
; specify the type - a valid entry |
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x01 |
mov [eax + ARPTable + 11], cl |
|
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
jmp arph_exit |
|
arph_002: |
|
cmp byte [NumARP], ARP_TABLE_SIZE |
je arph_exit |
|
inc byte [NumARP] |
|
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
sub eax, ARP_ENTRY_SIZE |
|
mov ecx, [remote_ip_add] |
mov [eax + ARPTable], ecx |
mov ecx, [remote_hw_add] |
mov [eax + ARPTable + 4], ecx |
mov cx, [remote_hw_add+4] |
mov [eax + ARPTable + 8], cx |
|
mov cl, 0x00 |
mov [eax + ARPTable + 10], cl |
mov cl, 0x01 |
mov [eax + ARPTable + 11], cl |
|
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
|
arph_exit: |
eth_exit: |
ret |
|
; pointer to MAC in esi |
refreshARP: |
mov ebx, [esi] |
mov dx, [esi+4] |
push edx |
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
pop edx |
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je rf_exit |
|
rf_001: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable+4], ebx |
|
je rf_002 |
loop rf_001 |
jmp rf_exit |
|
rf_002: |
cmp [eax + ARPTable+8], dx |
je rf_gotone |
loop rf_001 |
jmp rf_exit |
|
rf_gotone: |
; Initialise the time to live field - 1 hour |
mov cx, 0x0E10 |
mov [eax + ARPTable + 12], cx |
|
rf_exit: |
ret |
|
;*************************************************************************** |
; Function |
; getMACfromIP |
; eth_rx |
; |
; Description |
; Takes an IP address in edx and scans the ARP table for |
; a matching entry |
; If a match is found, it's MAC address is stored in MACAddress. |
; Otherwise the value 0 is writen to MACAddress |
; eax holds ARP table entry status code ( ARP_ ) |
; ebx unchanged |
; Polls the ethernet card for received data. Extracts if present |
; Depending on the Protocol within the packet: |
; ARP : Pass to ARP_handler. This may result in an ARP reply |
; being tx'ed |
; IP : Store in an IP buffer |
; |
;*************************************************************************** |
getMACfromIP: |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
; desitnation is local |
; else |
; destination is remote, so pass to gateway |
eth_rx: |
xor ax, ax |
mov [eth_rx_data_len], ax |
call dword [drvr_poll] ; Call the drivers poll function |
|
mov eax, edx |
and eax, [subnet_mask] |
mov ecx, [stack_ip] |
and ecx, [subnet_mask] |
cmp eax, ecx |
je gm0 |
mov ax, [eth_rx_data_len] |
cmp ax, 0 |
je .exit |
|
mov edx, [gateway_ip] |
gm0: |
push edx |
xor eax, eax |
mov [MACAddress], eax |
mov [MACAddress + 4], ax |
|
movzx eax, byte [NumARP] |
mov ecx, ARP_ENTRY_SIZE |
mul ecx |
; Check the protocol. Call appropriate handler |
|
pop edx |
mov ax, [ETH_FRAME.Type] ; The address of the protocol word |
|
movzx ecx, byte [NumARP] |
cmp ecx, 0 |
je gm_none |
gm1: |
sub eax, ARP_ENTRY_SIZE |
cmp [eax + ARPTable], edx |
loopnz gm1 ; Return back if non match |
jnz gm_none ; Quit if none found |
cmp ax, ETHER_IP |
je .is_ip ; It's IP |
|
; eax holds index |
mov ecx, [eax + ARPTable + 4] |
mov [MACAddress], ecx |
mov cx, [eax + ARPTable + 8] |
mov [MACAddress+4], cx |
cmp ax, ETHER_ARP |
je .is_arp ; It is ARP |
|
; Return the entry status in eax |
mov ch, [eax + ARPTable + 10] |
mov cl, [eax + ARPTable + 11] |
movzx eax, cx |
jmp gm_exit |
jmp .exit ; If not IP or ARP, ignore |
|
gm_none: |
mov eax, ARP_NO_ENTRY |
.is_ip: |
DEBUGF 1,"K : eth_rx - IP packet\n" |
inc dword [ip_rx_count] |
call ether_IP_handler |
jmp .exit |
|
gm_exit: |
ret |
.is_arp: |
DEBUGF 1,"K : eth_rx - ARP packet\n" |
; At this point, the packet is still in the Ether_buffer |
call arp_handler |
|
;*************************************************************************** |
; |
; PCI CODE FOLLOWS |
; |
; the following functions provide access to the PCI interface. |
; These functions are used by scan_bus, and also some ethernet drivers |
; |
;*************************************************************************** |
|
;*************************************************************************** |
; Function |
; config_cmd |
; |
; Description |
; creates a command dword for use with the PCI bus |
; bus # in ebx |
; devfn in ecx |
; where in edx |
; |
; command dword returned in eax |
; Only eax destroyed |
;*************************************************************************** |
config_cmd: |
push ecx |
mov eax, ebx |
shl eax, 16 |
or eax, 0x80000000 |
shl ecx, 8 |
or eax, ecx |
pop ecx |
or eax, edx |
and eax, 0xFFFFFFFC |
.exit: |
ret |
|
;*************************************************************************** |
; Function |
; pcibios_read_config_byte |
; |
; Description |
; reads a byte from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; byte returned in al ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_byte: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
|
xor eax, eax |
and dx, 0x03 |
add dx, 0xCFC |
; and dx, 0xFFC |
in al, dx |
ret |
|
;*************************************************************************** |
; Function |
; pcibios_read_config_word |
; |
; Description |
; reads a word from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; word returned in ax ( rest of eax zero ) |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_word: |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
|
xor eax, eax |
and dx, 0x02 |
add dx, 0xCFC |
; and dx, 0xFFC |
in ax, dx |
ret |
|
;*************************************************************************** |
; Function |
; pcibios_read_config_dword |
; |
; Description |
; reads a dword from the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; dword returned in eax |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_read_config_dword: |
push edx |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
xor eax, eax |
mov dx, 0xCFC |
in eax, dx |
pop edx |
ret |
|
;*************************************************************************** |
; Function |
; pcibios_write_config_byte |
; |
; Description |
; write a byte in al to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_byte: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
|
and dx, 0x03 |
add dx, 0xCFC |
out dx, al |
ret |
|
;*************************************************************************** |
; Function |
; pcibios_write_config_word |
; |
; Description |
; write a word in ax to the PCI config space |
; bus # in ebx |
; devfn in ecx |
; where in edx ( ls 16 bits significant ) |
; |
; Only eax/edx destroyed |
;*************************************************************************** |
pcibios_write_config_word: |
push ax |
call config_cmd |
push dx |
mov dx, 0xCF8 |
out dx, eax |
pop dx |
pop ax |
|
and dx, 0x02 |
add dx, 0xCFC |
out dx, ax |
ret |
|
;*************************************************************************** |
; Function |
; delay_us |
; |
; Description |
; delays for 30 to 60 us |
; |
; I would prefer this routine to be able to delay for |
; a selectable number of microseconds, but this works for now. |
; |
; If you know a better way to do 2us delay, pleae tell me! |
;*************************************************************************** |
delay_us: |
push eax |
push ecx |
|
mov ecx,2 |
|
in al,0x61 |
and al,0x10 |
mov ah,al |
cld |
|
dcnt1: |
in al,0x61 |
and al,0x10 |
cmp al,ah |
jz dcnt1 |
|
mov ah,al |
loop dcnt1 |
|
pop ecx |
pop eax |
|
ret |
|
;*************************************************************************** |
; Function |
; scan_bus |
; |
; Description |
; Scans the PCI bus for a supported device |
; If a supported device is found, the drvr_ variables are initialised |
; to that drivers functions ( as defined in the PCICards table) |
; |
; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid |
; pci_data holds the PCI vendor + device code |
; pci_dev holds PCI bus dev # |
; pci_bus holds PCI bus # |
; |
; io_addr will be zero if no card found |
; |
;*************************************************************************** |
scan_bus: |
xor eax, eax |
mov [hdrtype], al |
mov [pci_data], eax |
|
xor ebx, ebx ; ebx = bus# 0 .. 255 |
|
sb_bus_loop: |
xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) |
|
sb_devf_loop: |
mov eax, ecx |
and eax, 0x07 |
|
cmp eax, 0 |
jne sb_001 |
|
mov edx, PCI_HEADER_TYPE |
call pcibios_read_config_byte |
mov [hdrtype], al |
jmp sb_002 |
|
sb_001: |
mov al, [hdrtype] |
and al, 0x80 |
cmp al, 0x80 |
jne sb_inc_devf |
|
sb_002: |
mov edx, PCI_VENDOR_ID |
call pcibios_read_config_dword |
mov [vendor_device], eax |
cmp eax, 0xffffffff |
je sb_empty |
cmp eax, 0 |
jne sb_check_vendor |
|
sb_empty: |
mov [hdrtype], byte 0 |
jmp sb_inc_devf |
|
sb_check_vendor: |
; iterate though PCICards until end or match found |
mov esi, PCICards |
|
sb_check: |
cmp [esi], dword 0 |
je sb_inc_devf ; Quit if at last entry |
cmp eax, [esi] |
je sb_got_card |
add esi, PCICARDS_ENTRY_SIZE |
jmp sb_check |
|
sb_got_card: |
; indicate that we have found the card |
mov [pci_data], eax |
mov [pci_dev], ecx |
mov [pci_bus], ebx |
|
; Define the driver functions |
push eax |
mov eax, [esi+4] |
mov [drvr_probe], eax |
mov eax, [esi+8] |
mov [drvr_reset], eax |
mov eax, [esi+12] |
mov [drvr_poll], eax |
mov eax, [esi+16] |
mov [drvr_transmit], eax |
pop eax |
|
mov edx, PCI_BASE_ADDRESS_0 |
|
sb_reg_check: |
call pcibios_read_config_dword |
mov [io_addr], eax |
and eax, PCI_BASE_ADDRESS_IO_MASK |
cmp eax, 0 |
je sb_inc_reg |
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_SPACE_IO |
cmp eax, 0 |
je sb_inc_reg |
|
mov eax, [io_addr] |
and eax, PCI_BASE_ADDRESS_IO_MASK |
mov [io_addr], eax |
|
sb_exit1: |
ret |
|
sb_inc_reg: |
add edx, 4 |
cmp edx, PCI_BASE_ADDRESS_5 |
jbe sb_reg_check |
|
sb_inc_devf: |
inc ecx |
cmp ecx, 255 |
jb sb_devf_loop |
inc ebx |
cmp ebx, 256 |
jb sb_bus_loop |
|
; We get here if we didn't find our card |
; set io_addr to 0 as an indication |
xor eax, eax |
mov [io_addr], eax |
|
sb_exit2: |
ret |
|
;*************************************************************************** |
; |
; DEBUGGING CODE FOLLOWS |
; |
; If debugging data output is not required, ALL code & data below may |
; be removed. |
; |
;*************************************************************************** |
|
if DEBUGGING_STATE = DEBUGGING_ENABLED |
|
;*************************************************************************** |
; Function |
; eth_dump |
; |
; Description |
; Dumps a tx or rx ethernet packet over the rs232 link |
; This is a debugging routine that seriously slows down the stack. |
; Use with caution. |
; |
; Baud rate is 57600, 8n1 com1 |
; eax : type (0 == rx, 1 == tx ) |
; cx : # of bytes in buffer |
; esi : address of buffer start |
; edi : pointer to MACAddress ( tx only ) |
; |
;*************************************************************************** |
eth_dump: |
pusha |
|
; Set the port to the desired speed |
mov ebx, 0x3f8 ; combase |
|
mov edx, ebx |
add edx, 3 ; data format register |
mov al, 0x80 ; enable access to divisor latch |
out dx, al |
|
mov edx, ebx |
add edx, 1 ; interrupt enable register |
mov al, 0x00 ; No interruts enabled |
out dx, al |
|
mov edx, ebx |
mov al, 0x20 / 16 ; set baud rate to 57600 0x10 =115200 |
out dx, al |
|
mov edx, ebx |
add edx, 3 ; data format register |
mov al, 0x03 ; 8 data bits |
out dx, al |
|
mov edx, ebx |
add edx, 4 ; Modem control register |
mov al, 0x08 ; out2 enabled. No handshaking. |
out dx, al |
|
mov edx, ebx |
add edx, 1 ; interrupt enable register |
mov al, 0x01 ; Receive data interrupt enabled, |
out dx, al |
|
popa |
|
; First, display the type of the buffer. |
; If it is a tx buffer, display the macaddress |
|
pusha |
|
cmp eax, 0 |
jne dd001 |
|
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
|
; Output "RX:" |
mov bl, 'R' |
call tx_byted |
mov bl, 'X' |
call tx_byted |
mov bl, ':' |
call tx_byted |
jmp dump_data |
|
dd001: |
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
|
; Output TX: xxxxxxxxxxxx |
mov bl, 'T' |
call tx_byted |
mov bl, 'X' |
call tx_byted |
mov bl, ':' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
|
; Display MAC address |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
inc edi |
xor eax, eax |
mov al, [edi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [edi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
dump_data: |
popa |
|
; OK, we come in here with |
; cx == number of byte to send |
; esi == buffer start |
; |
dd_000: |
mov bl, 0x0a |
call tx_byted |
mov bl, 0x0d |
call tx_byted |
|
mov eax, 16 ; Number of characters on the line |
mov edi, esi ; Save first byte position for later |
|
push ecx |
|
dd_001: |
push eax |
|
; Print a byte, and a space |
xor eax, eax |
mov al, [esi] |
shr al, 4 |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
xor eax, eax |
mov al, [esi] |
and al, 0x0f |
mov bl, [eax + hexchars] |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
mov bl, ' ' |
call tx_byted |
|
pop eax |
|
inc esi |
dec ecx |
cmp ecx, 0 |
je dd_0011 ; Print the ASCII format |
|
dec eax |
|
cmp eax, 0 |
je dd_002 ; Print the ASCII format |
jmp dd_001 ; Print rest of line |
|
dd_0011: |
; First, complete the 16 bytes of data, by printing spaces |
dec eax |
cmp eax, 0 |
je dd_002 |
|
push eax |
mov bl, ' ' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
mov bl, ' ' |
call tx_byted |
pop eax |
jmp dd_0011 |
|
dd_002: |
pop ecx |
mov esi, edi ; Go back to the start of the line data |
|
mov eax, 16 |
|
outLineAscii: |
push eax |
|
xor eax, eax |
mov al, [esi] |
mov bl, '.' |
|
cmp al, 0x1F |
jle outAscii |
cmp al, 0x7e |
jge outAscii |
|
mov bl, al |
|
outAscii: |
call tx_byted ; byte in bl eax ebx edx destroyed |
|
pop eax |
dec ecx |
inc esi |
cmp ecx, 0 |
je dd_003 |
|
dec eax |
cmp eax, 0 |
je dd_003 |
jmp outLineAscii |
|
dd_003: |
cmp ecx, 0 |
je dd_004 |
jmp dd_000 |
|
dd_004: |
ret |
|
;*************************************************************************** |
; Function |
; tx_byte |
; |
; Description |
; Send a byte in bl out of the com port 1 |
; destroys eax, edx |
; |
;*************************************************************************** |
tx_byted: |
push ebx ; Save the byte |
|
mov ebx, 0x3f8 ; get the com port address |
|
; Wait for transmit buffer to empty. This could take 1ms @ 9600baud |
|
mov edx, ebx |
add edx, 5 |
|
wait_txd: |
in al, dx ; read uart serialisation status |
and al, 0x40 |
cmp al, 0 |
jz wait_txd ; loop until free |
|
mov edx, ebx |
pop eax ; restore the byte to send |
out dx, al |
ret |
|
iglobal |
; This is used for translating hex to ASCII for display or output |
hexchars db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' |
endg |
end if |
|