23,22 → 23,21 |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
format MS COFF |
format PE DLL native |
entry START |
|
CURRENT_API = 0x0200 |
COMPATIBLE_API = 0x0100 |
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
|
NUM_RX_DESC = 4 ; Number of RX descriptors |
NUM_TX_DESC = 4 ; Number of TX descriptors |
RX_BUFF_SZ = 1520 ; Buffer size for each Rx buffer |
TX_BUFF_SZ = 1516 ; Buffer size for each Tx buffer |
MAX_ETH_FRAME_SIZE = 1516 |
|
API_VERSION = 0x01000100 |
DRIVER_VERSION = 5 |
|
MAX_DEVICES = 16 |
|
DEBUG = 1 |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 2 |
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
|
DSIZE = 0x00000fff |
CRC_SIZE = 4 |
197,40 → 196,33 |
EEDONE = 0x00000200 |
EEGNT = 0x00000100 |
|
section '.flat' readable writable executable |
|
include '../proc32.inc' |
include '../struct.inc' |
include '../macros.inc' |
include '../proc32.inc' |
include '../imports.inc' |
include '../fdo.inc' |
include '../netdrv.inc' |
include '../netdrv_pe.inc' |
|
public START |
public version |
|
struct device ETH_DEVICE |
|
virtual at ebx |
device: |
io_addr dd ? |
pci_bus dd ? |
pci_dev dd ? |
irq_line db ? |
cur_rx db ? |
cur_tx db ? |
last_tx db ? |
pci_revision db ? |
table_entries db ? |
|
ETH_DEVICE |
rb 0x100 - ($ and 0xff) ; align 256 |
txd rd (4 * NUM_TX_DESC) |
rxd rd (4 * NUM_RX_DESC) |
|
.io_addr dd ? |
.pci_bus dd ? |
.pci_dev dd ? |
.irq_line db ? |
.cur_rx db ? |
.cur_tx db ? |
.last_tx db ? |
.pci_revision db ? |
.table_entries db ? |
rb 2 ; alignment |
ends |
|
.txd rd (4 * NUM_TX_DESC) |
.rxd rd (4 * NUM_RX_DESC) |
|
.size = $ - device |
|
end virtual |
|
macro ee_delay { |
push eax |
in eax, dx |
246,20 → 238,39 |
pop eax |
} |
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; proc START ;; |
;; ;; |
;; (standard driver proc) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
section '.flat' code readable align 16 |
|
; Driver entry point - register our service when the driver is loading. |
; TODO: add needed operations when unloading |
START: |
cmp dword [esp+4], 1 |
jne .exit |
stdcall RegService, my_service, service_proc |
ret 4 |
.exit: |
|
proc START c, reason:dword, cmdline:dword |
|
cmp [reason], DRV_ENTRY |
jne .fail |
|
DEBUGF 2,"Loading driver\n" |
invoke RegService, my_service, service_proc |
ret |
|
.fail: |
xor eax, eax |
ret 4 |
ret |
|
endp |
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; proc SERVICE_PROC ;; |
;; ;; |
;; (standard driver proc) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
; Service procedure for the driver - handle all I/O requests for the driver. |
; Currently handled requests are: SRV_GETVERSION = 0 and SRV_HOOK = 1. |
service_proc: |
307,9 → 318,9 |
mov ax, [eax+1] ; |
.nextdevice: |
mov ebx, [esi] |
cmp al, byte[device.pci_bus] |
cmp al, byte[ebx + device.pci_bus] |
jne @f |
cmp ah, byte[device.pci_dev] |
cmp ah, byte[ebx + device.pci_dev] |
je .find_devicenum ; Device is already loaded, let's find it's device number |
@@: |
add esi, 4 |
321,28 → 332,31 |
jae .fail |
; 4g. Allocate memory for device descriptor and receive+transmit buffers. |
; 4h. Zero the structure. |
allocate_and_clear ebx, device.size, .fail |
allocate_and_clear ebx, sizeof.device, .fail |
; 4i. Save PCI coordinates |
mov eax, [edx + IOCTL.input] |
movzx ecx, byte[eax+1] |
mov [device.pci_bus], ecx |
mov [ebx + device.pci_bus], ecx |
movzx ecx, byte[eax+2] |
mov [device.pci_dev], ecx |
mov [ebx + device.pci_dev], ecx |
; 4j. Fill in the direct call addresses into the struct. |
mov [device.reset], reset |
mov [device.transmit], transmit |
mov [device.unload], unload |
mov [device.name], my_service |
mov [ebx + device.reset], reset |
mov [ebx + device.transmit], transmit |
mov [ebx + device.unload], unload |
mov [ebx + device.name], my_service |
|
; 4k. Now, it's time to find the base io addres of the PCI device |
; TODO: implement check if bus and dev exist on this machine |
|
; Now, it's time to find the base io addres of the PCI device |
PCI_find_io |
stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev] |
mov [ebx + device.io_addr], eax |
|
; We've found the io address, find IRQ now |
PCI_find_irq |
|
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line |
mov [ebx + device.irq_line], al |
|
; 4m. Add new device to the list (required for int_handler). |
mov eax, [devices] |
mov [device_list+4*eax], ebx |
354,8 → 368,8 |
jnz .destroy |
; 4n. If device was successfully initialized, register it for the kernel. |
|
mov [device.type], NET_TYPE_ETH |
call NetRegDev |
mov [ebx + device.type], NET_TYPE_ETH |
invoke NetRegDev |
|
cmp eax, -1 |
je .destroy |
365,7 → 379,7 |
; 5. If the device was already loaded, find the device number and return it in eax |
|
.find_devicenum: |
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx |
; into a device number in edi |
mov eax, edi ; Application wants it in eax instead |
ret 4 |
377,7 → 391,7 |
; todo: reset device into virgin state |
|
.err: |
stdcall KernelFree, ebx |
invoke KernelFree, ebx |
|
.fail: |
xor eax, eax |
416,16 → 430,26 |
probe: |
DEBUGF 1, "Probe\n" |
|
; wake up device CHECKME |
stdcall PciWrite8, [device.pci_bus], [device.pci_dev], 0x40, 0 |
; wake up device |
; TODO: check capabilities pointer instead of using hardcoded offset. |
invoke PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x40, 0 |
|
PCI_make_bus_master |
; Make the device a bus master |
invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command |
or al, PCI_CMD_MASTER |
invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax |
|
PCI_adjust_latency 64 |
; Adjust PCI latency to be at least 64 |
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency |
cmp al, 64 |
jae @f |
mov al, 64 |
invoke PciWrite8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.max_latency, eax |
@@: |
|
; Get Card Revision |
stdcall PciRead8, [device.pci_bus], [device.pci_dev], 0x08 |
mov [device.pci_revision], al ; save the revision for later use |
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], 0x08 |
mov [ebx + device.pci_revision], al ; save the revision for later use |
|
; Look up through the specific_table |
mov esi, specific_table |
436,26 → 460,23 |
je .ok |
add esi, 12 ; Advance to next entry |
jmp .tableloop |
|
.ok: |
|
call dword[esi + 4] ; "get MAC" function |
|
; Set table entries |
mov [device.table_entries], 16 |
cmp [device.pci_revision], SIS635A_900_REV |
mov [ebx + device.table_entries], 16 |
cmp [ebx + device.pci_revision], SIS635A_900_REV |
jae @f |
cmp [device.pci_revision], SIS900B_900_REV |
cmp [ebx + device.pci_revision], SIS900B_900_REV |
je @f |
mov [device.table_entries], 8 |
mov [ebx + device.table_entries], 8 |
@@: |
|
; TODO: Probe for mii transceiver |
|
jmp reset |
|
.notsupported: |
DEBUGF 1, "Device not supported\n" |
DEBUGF 2, "Device not supported\n" |
or eax, -1 |
|
ret |
464,27 → 485,33 |
|
DEBUGF 1, "reset\n" |
|
movzx eax, [device.irq_line] |
stdcall AttachIntHandler, eax, int_handler, 0 |
movzx eax, [ebx + device.irq_line] |
invoke AttachIntHandler, eax, int_handler, ebx |
test eax, eax |
jnz @f |
DEBUGF 2,"Could not attach int handler!\n" |
or eax, -1 |
ret |
@@: |
|
;-------------------------------------------- |
; Disable Interrupts and reset Receive Filter |
|
set_io 0 |
set_io ier |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], ier |
xor eax, eax |
out dx, eax |
|
set_io imr |
set_io [ebx + device.io_addr], imr |
out dx, eax |
|
set_io rfcr |
set_io [ebx + device.io_addr], rfcr |
out dx, eax |
|
;----------- |
; Reset Card |
|
set_io cr |
set_io [ebx + device.io_addr], cr |
in eax, dx ; Get current Command Register |
or eax, RESET + RxRESET + TxRESET ; set flags |
out dx, eax ; Write new Command Register |
492,7 → 519,7 |
;---------- |
; Wait loop |
|
set_io isr |
set_io [ebx + device.io_addr], isr |
mov ecx, 1000 |
.loop: |
dec ecx |
505,11 → 532,11 |
;------------------------------------------------------ |
; Set Configuration Register depending on Card Revision |
|
set_io cfg |
set_io [ebx + device.io_addr], cfg |
mov eax, PESEL ; Configuration Register Bit |
cmp [device.pci_revision], SIS635A_900_REV |
cmp [ebx + device.pci_revision], SIS635A_900_REV |
je .match |
cmp [device.pci_revision], SIS900B_900_REV ; Check card revision |
cmp [ebx + device.pci_revision], SIS900B_900_REV ; Check card revision |
jne .done |
.match: ; Revision match |
or eax, RND_CNT ; Configuration Register Bit |
519,7 → 546,7 |
DEBUGF 1, "Initialising RX Filter\n" |
|
; Get Receive Filter Control Register |
set_io rfcr |
set_io [ebx + device.io_addr], rfcr |
in eax, dx |
push eax |
|
531,12 → 558,12 |
xor ecx, ecx |
.macloop: |
mov eax, ecx |
set_io 0 |
set_io rfcr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], rfcr |
shl eax, 16 ; high word of eax tells card which mac byte to write |
out dx, eax ; |
set_io rfdr |
mov ax, word [device.mac + ecx*2] ; Get Mac ID word |
set_io [ebx + device.io_addr], rfdr |
mov ax, word [ebx + device.mac + ecx*2] ; Get Mac ID word |
out dx, ax ; Send Mac ID |
inc cl ; send next word |
cmp cl, 3 ; more to send? |
544,7 → 571,7 |
|
; enable packet filtering |
pop eax ; old register value |
set_io rfcr |
set_io [ebx + device.io_addr], rfcr |
or eax, RFEN ; enable filtering |
out dx, eax ; set register |
|
551,10 → 578,10 |
DEBUGF 1, "Initialising TX Descriptors\n" |
|
mov ecx, NUM_TX_DESC |
lea esi, [device.txd] |
lea esi, [ebx + device.txd] |
.txdescloop: |
lea eax, [esi + 16] ; next ptr |
GetRealAddr |
invoke GetPhysAddr |
mov dword [esi], eax ; link to next desc |
mov dword [esi + 4], 0 ; status field |
mov dword [esi + 8], 0 ; ptr to buffer |
562,112 → 589,111 |
dec ecx |
jnz .txdescloop |
|
lea eax, [device.txd] |
GetRealAddr |
lea eax, [ebx + device.txd] |
invoke GetPhysAddr |
mov dword [esi - 16], eax ; correct last descriptor link ptr |
|
set_io txdp ; TX Descriptor Pointer |
; lea eax, [device.txd] |
; GetRealAddr |
set_io [ebx + device.io_addr], txdp ; TX Descriptor Pointer |
; lea eax, [ebx + device.txd] |
; invoke GetPhysAddr |
out dx, eax |
|
mov [device.cur_tx], 0 ; Set current tx descriptor to 0 |
mov [device.last_tx], 0 |
mov [ebx + device.cur_tx], 0 ; Set current tx descriptor to 0 |
mov [ebx + device.last_tx], 0 |
|
DEBUGF 1, "Initialising RX Descriptors\n" |
|
mov ecx, NUM_RX_DESC |
lea esi, [device.rxd] |
lea esi, [ebx + device.rxd] |
.rxdescloop: |
lea eax, [esi + 16] ; next ptr |
GetRealAddr |
invoke GetPhysAddr |
mov dword [esi], eax |
mov dword [esi + 4], RX_BUFF_SZ ; size |
|
push ecx esi |
stdcall KernelAlloc, RX_BUFF_SZ |
invoke KernelAlloc, RX_BUFF_SZ |
pop esi ecx |
test eax, eax |
jz .fail |
mov dword [esi + 12], eax ; address |
GetRealAddr |
invoke GetPhysAddr |
mov dword [esi + 8], eax ; real address |
add esi, 16 |
dec ecx |
jnz .rxdescloop |
|
lea eax, [device.rxd] |
GetRealAddr |
lea eax, [ebx + device.rxd] |
invoke GetPhysAddr |
mov dword [esi - 16], eax ; correct last descriptor link ptr |
|
set_io 0 |
set_io rxdp |
; lea eax, [device.rxd] |
; GetRealAddr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], rxdp |
; lea eax, [ebx + device.rxd] |
; invoke GetPhysAddr |
out dx, eax |
|
mov [device.cur_rx], 0 ; Set current rx descriptor to 0 |
mov [ebx + device.cur_rx], 0 ; Set current rx descriptor to 0 |
|
DEBUGF 1, "setting RX mode\n" |
|
xor cl, cl |
.rxfilterloop: |
set_io 0 |
set_io rfcr ; Receive Filter Control Reg offset |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], rfcr ; Receive Filter Control Reg offset |
mov eax, 4 ; determine table entry |
add al, cl |
shl eax, 16 |
out dx, eax ; tell card which entry to modify |
|
set_io rfdr ; Receive Filter Control Reg offset |
set_io [ebx + device.io_addr], rfdr ; Receive Filter Control Reg offset |
mov eax, 0xffff ; entry value |
out dx, ax ; write value to table in card |
|
inc cl ; next entry |
cmp cl, [device.table_entries] |
cmp cl, [ebx + device.table_entries] |
jb .rxfilterloop |
|
set_io rfcr ; Receive Filter Control Register offset |
set_io [ebx + device.io_addr], rfcr ; Receive Filter Control Register offset |
mov eax, RFAAB + RFAAM + RFAAP + RFEN |
out dx, eax |
|
set_io rxcfg ; Receive Config Register offset |
set_io [ebx + device.io_addr], rxcfg ; Receive Config Register offset |
mov eax, ATX + RX_DMA + 2 ; 0x2 : RX Drain Threshold = 8*8=64 bytes |
out dx, eax |
|
DEBUGF 1, "setting TX mode\n" |
|
set_io txcfg ; Transmit config Register offset |
mov eax, ATP + HBI + CSI + TX_DMA + 0x120 |
; TX Fill threshold = 0x100 |
set_io [ebx + device.io_addr], txcfg ; Transmit config Register offset |
mov eax, ATP + HBI + CSI + TX_DMA + 0x120 ; TX Fill threshold = 0x100 |
; TX Drain Threshold = 0x20 |
out dx, eax |
|
DEBUGF 1, "Enabling interrupts\n" |
|
set_io imr |
set_io [ebx + device.io_addr], imr |
mov eax, IE ; Interrupt enable mask |
out dx, eax |
|
set_io cr |
set_io [ebx + device.io_addr], cr |
in eax, dx |
or eax, RxENA ; Enable Receive |
out dx, eax |
|
set_io ier ; Interrupt enable |
set_io [ebx + device.io_addr], ier ; Interrupt enable |
mov eax, 1 |
out dx, eax |
|
mov [device.mtu], 1514 |
mov [ebx + device.mtu], 1514 |
|
; Set link state to unknown |
mov [device.state], ETH_LINK_UNKOWN |
mov [ebx + device.state], ETH_LINK_UNKNOWN |
|
xor eax, eax |
ret |
|
.fail: |
DEBUGF 1, "Resetting device failed\n" |
DEBUGF 2, "Resetting device failed\n" |
or eax, -1 |
|
ret |
691,13 → 717,13 |
;*************************************************************************** |
align 4 |
SIS960_get_mac_addr: |
DEBUGF 1, "SIS960 - get mac: " |
DEBUGF 1, "SIS960 - get mac:\n" |
|
;------------------------------- |
; Send Request for eeprom access |
|
set_io 0 |
set_io mear ; Eeprom access register |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], mear ; Eeprom access register |
mov eax, EEREQ ; Request access to eeprom |
out dx, eax ; Send request |
|
711,9 → 737,9 |
jnz .got_access ; if it is, go access the eeprom |
loop .loop ; else keep waiting |
|
DEBUGF 1, "Access to EEprom failed!\n", 0 |
DEBUGF 2, "Access to EEprom failed!\n", 0 |
|
set_io mear ; Eeprom access register |
set_io [ebx + device.io_addr], mear ; Eeprom access register |
mov eax, EEDONE ; tell eeprom we are done |
out dx, eax |
|
734,19 → 760,20 |
push ecx |
call read_eeprom ; try to read 16 bits |
pop ecx |
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID varible |
mov word [ebx + device.mac+ecx*2], ax ; save 16 bits to the MAC ID varible |
dec ecx ; one less word to read |
jns .read_loop ; if more read more |
mov eax, 1 ; return non-zero indicating success |
|
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2 |
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",\ |
[ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
|
;------------------------------------- |
; Tell EEPROM We are Done Accessing It |
|
.done: |
set_io 0 |
set_io mear ; Eeprom access register |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], mear ; Eeprom access register |
mov eax, EEDONE ; tell eeprom we are done |
out dx, eax |
|
765,7 → 792,7 |
;*************************************************************************** |
align 4 |
SIS900_get_mac_addr: |
DEBUGF 1, "SIS900 - get mac: " |
DEBUGF 1, "SIS900 - get mac:\n" |
|
;------------------------------------ |
; check to see if we have sane EEPROM |
789,11 → 816,12 |
push ecx |
call read_eeprom ; try to read 16 bits |
pop ecx |
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID storage |
mov word [ebx + device.mac+ecx*2], ax ; save 16 bits to the MAC ID storage |
dec ecx ; one less word to read |
jns .loop ; if more read more |
|
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2 |
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",\ |
[ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
|
xor eax, eax |
ret |
813,14 → 841,14 |
;*************************************************************************** |
align 4 |
Get_Mac_SIS635_900_REV: |
DEBUGF 1, "SIS635 - get mac: " |
DEBUGF 1, "SIS635 - get mac:\n" |
|
set_io 0 |
set_io rfcr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], rfcr |
in eax, dx |
mov esi, eax |
|
set_io cr |
set_io [ebx + device.io_addr], cr |
or eax, RELOAD |
out dx, eax |
|
830,7 → 858,7 |
;----------------------------------------------- |
; Disable packet filtering before setting filter |
|
set_io rfcr |
set_io [ebx + device.io_addr], rfcr |
mov eax, esi |
and eax, not RFEN |
out dx, eax |
839,15 → 867,15 |
; Load MAC to filter data register |
|
xor ecx, ecx |
lea edi, [device.mac] |
lea edi, [ebx + device.mac] |
.loop: |
set_io 0 |
set_io rfcr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], rfcr |
mov eax, ecx |
shl eax, RFADDR_shift |
out dx, eax |
|
set_io rfdr |
set_io [ebx + device.io_addr], rfdr |
in ax, dx |
stosw |
inc ecx |
857,12 → 885,13 |
;------------------------ |
; Enable packet filtering |
|
set_io rfcr |
set_io [ebx + device.io_addr], rfcr |
mov eax, esi |
or eax, RFEN |
out dx, eax |
|
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2 |
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",\ |
[ebx + device.mac]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2 |
|
xor eax, eax |
ret |
880,8 → 909,8 |
align 4 |
read_eeprom: |
|
set_io 0 |
set_io mear |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], mear |
|
xor eax, eax ; start send |
out dx, eax |
958,7 → 987,7 |
|
align 4 |
write_mac: |
DEBUGF 1,'Setting MAC is not supported for SIS900 card.\n' |
DEBUGF 2,'Setting MAC is not supported for SIS900 card.\n' |
add esp, 6 |
ret |
|
976,63 → 1005,71 |
; |
;*************************************************************************** |
align 4 |
transmit: |
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8] |
mov eax, [esp+4] |
|
proc transmit stdcall bufferptr, buffersize |
|
pushf |
cli |
|
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize] |
mov eax, [bufferptr] |
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ |
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
[eax+13]:2,[eax+12]:2 |
|
cmp dword [esp + 8], MAX_ETH_FRAME_SIZE |
ja .error |
cmp dword [esp + 8], 60 |
jb .error |
cmp [buffersize], 1514 |
ja .fail |
cmp [buffersize], 60 |
jb .fail |
|
movzx ecx, [device.cur_tx] |
movzx ecx, [ebx + device.cur_tx] |
shl ecx, 4 ; *16 |
lea ecx, [device.txd + ecx] |
lea ecx, [ebx + device.txd + ecx] |
|
test dword [ecx + 4], 0x80000000 ; card owns descriptor ? |
jnz .error |
jnz .fail |
|
mov eax, [esp + 4] |
mov eax, [bufferptr] |
mov dword [ecx + 12], eax |
GetRealAddr |
invoke GetPhysAddr |
mov dword [ecx + 8], eax ; buffer address |
|
mov eax, [esp + 8] |
mov eax, [buffersize] |
and eax, DSIZE |
or eax, 0x80000000 ; card owns descriptor |
mov dword [ecx + 4], eax ; status field |
|
set_io 0 |
set_io cr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], cr |
in eax, dx |
or eax, TxENA ; Enable the transmit state machine |
out dx, eax |
|
inc [device.cur_tx] |
and [device.cur_tx], NUM_TX_DESC-1 |
inc [ebx + device.cur_tx] |
and [ebx + device.cur_tx], NUM_TX_DESC-1 |
|
; update stats |
mov ecx, [esp + 8] |
inc [device.packets_tx] |
add dword [device.bytes_tx], ecx |
adc dword [device.bytes_tx + 4], 0 |
mov ecx, [buffersize] |
inc [ebx + device.packets_tx] |
add dword [ebx + device.bytes_tx], ecx |
adc dword [ebx + device.bytes_tx + 4], 0 |
|
.finish: |
DEBUGF 1,"Packet sent!\n" |
DEBUGF 1,"Transmit OK\n" |
popf |
xor eax, eax |
ret 8 |
ret |
|
.error: |
DEBUGF 1,"ERROR!\n" |
stdcall KernelFree, [esp+4] |
.fail: |
DEBUGF 2,"Transmit failed\n" |
invoke KernelFree, [bufferptr] |
popf |
or eax, -1 |
ret 8 |
ret |
|
endp |
|
|
;*************************************************************************** |
; |
; int_handler |
1049,7 → 1086,7 |
|
push ebx esi edi |
|
DEBUGF 1,"\n%s int\n", my_service |
DEBUGF 1,"INT\n" |
|
; find pointer of device which made IRQ occur |
|
1060,8 → 1097,8 |
.nextdevice: |
mov ebx, [esi] |
|
set_io 0 |
set_io isr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], isr |
in eax, dx ; note that this clears all interrupts |
test ax, IE |
jnz .got_it |
1077,7 → 1114,7 |
|
.got_it: |
|
DEBUGF 1,"Device: %x Status: %x ", ebx, ax |
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax |
|
test ax, RxOK |
jz .no_rx_ |
1088,9 → 1125,9 |
|
;----------- |
; Get Status |
movzx eax, [device.cur_rx] ; find current descriptor |
movzx eax, [ebx + device.cur_rx] ; find current descriptor |
shl eax, 4 ; * 16 |
mov ecx, dword[device.rxd + eax + 4] ; get receive status |
mov ecx, dword[ebx + device.rxd + eax + 4] ; get receive status |
|
;------------------------------------------- |
; Check RX_Status to see if packet is waiting |
1109,39 → 1146,39 |
jbe .error_size |
|
; update statistics |
inc dword [device.packets_rx] |
add dword [device.bytes_rx], ecx |
adc dword [device.bytes_rx + 4], 0 |
inc dword [ebx + device.packets_rx] |
add dword [ebx + device.bytes_rx], ecx |
adc dword [ebx + device.bytes_rx + 4], 0 |
|
push ebx |
push .return |
push ecx ; packet size |
pushd [device.rxd + eax + 12] ; packet ptr |
pushd [ebx + device.rxd + eax + 12] ; packet ptr |
DEBUGF 1, "Packet received OK\n" |
jmp Eth_input |
jmp [Eth_input] |
.return: |
pop ebx |
|
; Reset status, allow ethernet card access to descriptor |
stdcall KernelAlloc, RX_BUFF_SZ |
invoke KernelAlloc, RX_BUFF_SZ |
test eax, eax |
jz .fail |
movzx ecx, [device.cur_rx] |
movzx ecx, [ebx + device.cur_rx] |
shl ecx, 4 ; *16 |
lea ecx, [device.rxd + ecx] |
lea ecx, [ebx + device.rxd + ecx] |
mov dword [ecx + 12], eax |
GetRealAddr |
invoke GetPhysAddr |
mov dword [ecx + 8], eax |
mov dword [ecx + 4], RX_BUFF_SZ |
|
inc [device.cur_rx] ; get next descriptor |
and [device.cur_rx], NUM_RX_DESC-1 ; only 4 descriptors 0-3 |
inc [ebx + device.cur_rx] ; get next descriptor |
and [ebx + device.cur_rx], NUM_RX_DESC-1 ; only 4 descriptors 0-3 |
|
jmp .rx_loop |
|
.no_rx: |
set_io 0 |
set_io cr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], cr |
in eax, dx |
or eax, RxENA ; Re-Enable the Receive state machine |
out dx, eax |
1155,9 → 1192,9 |
DEBUGF 1, "TX ok!\n" |
|
.tx_loop: |
movzx ecx, [device.last_tx] |
movzx ecx, [ebx + device.last_tx] |
shl ecx, 4 ; *16 |
lea ecx, [device.txd + ecx] |
lea ecx, [ebx + device.txd + ecx] |
|
test dword [ecx + 4], 0x80000000 ; card owns descr |
jnz .no_tx |
1167,10 → 1204,10 |
DEBUGF 1, "Freeing packet = %x\n", [ecx + 12]:8 |
push dword [ecx + 12] |
mov dword [ecx + 12], 0 |
call KernelFree |
invoke KernelFree |
|
inc [device.last_tx] |
and [device.last_tx], NUM_TX_DESC-1 |
inc [ebx + device.last_tx] |
and [ebx + device.last_tx], NUM_TX_DESC-1 |
jmp .tx_loop |
|
.no_tx: |
1184,11 → 1221,11 |
ret |
|
.error_status: |
DEBUGF 1, "Packet error: %x\n", ecx |
DEBUGF 2, "Packet error: %x\n", ecx |
jmp .fail |
|
.error_size: |
DEBUGF 1, "Packet too large/small\n" |
DEBUGF 2, "Packet too large/small\n" |
jmp .fail |
|
|
1197,10 → 1234,13 |
|
; End of code |
|
align 4 ; Place all initialised data here |
data fixups |
end data |
|
devices dd 0 |
include '../peimport.inc' |
|
my_service db 'SIS900',0 ; max 16 chars include zero |
|
specific_table: |
; dd SIS630A_900_REV, Get_Mac_SIS630A_900_REV, 0 |
; dd SIS630E_900_REV, Get_Mac_SIS630E_900_REV, 0 |
1212,12 → 1252,9 |
dd SIS900B_900_REV, SIS900_get_mac_addr, 0 |
dd 0 ; end of list |
|
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF) |
my_service db 'SIS900',0 ; max 16 chars include zero |
|
include_debug_strings ; All data wich FDO uses will be included here |
|
section '.data' data readable writable align 16; place all uninitialized data place here |
|
align 4 |
devices dd 0 |
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling |
|