i8255x: Improved interrupt handling.
git-svn-id: svn://kolibrios.org@9232 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
14beceb157
commit
3bd9001d45
@ -1,6 +1,6 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Copyright (C) KolibriOS team 2004-2017. All rights reserved. ;;
|
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; i8255x (Intel eepro 100) driver for KolibriOS ;;
|
;; i8255x (Intel eepro 100) driver for KolibriOS ;;
|
||||||
@ -27,14 +27,18 @@ entry START
|
|||||||
COMPATIBLE_API = 0x0100
|
COMPATIBLE_API = 0x0100
|
||||||
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
|
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
|
||||||
|
|
||||||
MAX_DEVICES = 16
|
; configureable area
|
||||||
|
|
||||||
TX_RING_SIZE = 16
|
MAX_DEVICES = 16 ; Maximum number of devices this driver may handle
|
||||||
|
|
||||||
DEBUG = 1
|
TX_RING_SIZE = 16 ; Number of packets in send ring buffer
|
||||||
__DEBUG__ = 1
|
RX_RING_SIZE = 1 ; Number of packets in receive ring buffer
|
||||||
|
|
||||||
|
__DEBUG__ = 1 ; 1 = on, 0 = off
|
||||||
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
|
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
|
||||||
|
|
||||||
|
; end configureable area
|
||||||
|
|
||||||
section '.flat' readable writable executable
|
section '.flat' readable writable executable
|
||||||
|
|
||||||
include '../proc32.inc'
|
include '../proc32.inc'
|
||||||
@ -43,6 +47,16 @@ include '../macros.inc'
|
|||||||
include '../fdo.inc'
|
include '../fdo.inc'
|
||||||
include '../netdrv.inc'
|
include '../netdrv.inc'
|
||||||
|
|
||||||
|
if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
|
||||||
|
display 'TX_RING_SIZE must be a power of two'
|
||||||
|
err
|
||||||
|
end if
|
||||||
|
|
||||||
|
if (RX_RING_SIZE)<>(1)
|
||||||
|
display 'RX_RING_SIZE must be 1'
|
||||||
|
err
|
||||||
|
end if
|
||||||
|
|
||||||
; I/O registers
|
; I/O registers
|
||||||
REG_SCB_STATUS = 0
|
REG_SCB_STATUS = 0
|
||||||
REG_SCB_CMD = 2
|
REG_SCB_CMD = 2
|
||||||
@ -64,7 +78,7 @@ EE_SK = 1 shl 0 ; serial clock
|
|||||||
EE_CS = 1 shl 1 ; chip select
|
EE_CS = 1 shl 1 ; chip select
|
||||||
EE_DI = 1 shl 2 ; data in
|
EE_DI = 1 shl 2 ; data in
|
||||||
EE_DO = 1 shl 3 ; data out
|
EE_DO = 1 shl 3 ; data out
|
||||||
EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO
|
EE_MASK = EE_SK or EE_CS or EE_DI or EE_DO
|
||||||
; opcodes, first bit is start bit and must be 1
|
; opcodes, first bit is start bit and must be 1
|
||||||
EE_READ = 110b
|
EE_READ = 110b
|
||||||
EE_WRITE = 101b
|
EE_WRITE = 101b
|
||||||
@ -581,7 +595,7 @@ reset:
|
|||||||
;-------------------------
|
;-------------------------
|
||||||
; Individual address setup
|
; Individual address setup
|
||||||
|
|
||||||
mov [ebx + device.confcmd.command], TXFD_CMD_IA + TXFD_CMD_SUSPEND
|
mov [ebx + device.confcmd.command], TXFD_CMD_IA or TXFD_CMD_SUSPEND
|
||||||
mov [ebx + device.confcmd.status], 0
|
mov [ebx + device.confcmd.status], 0
|
||||||
lea eax, [ebx + device.tx_ring]
|
lea eax, [ebx + device.tx_ring]
|
||||||
invoke GetPhysAddr
|
invoke GetPhysAddr
|
||||||
@ -604,7 +618,7 @@ reset:
|
|||||||
;-------------
|
;-------------
|
||||||
; Configure CU
|
; Configure CU
|
||||||
|
|
||||||
mov [ebx + device.confcmd.command], TXFD_CMD_CFG + TXFD_CMD_SUSPEND
|
mov [ebx + device.confcmd.command], TXFD_CMD_CFG or TXFD_CMD_SUSPEND
|
||||||
mov [ebx + device.confcmd.status], 0
|
mov [ebx + device.confcmd.status], 0
|
||||||
lea eax, [ebx + device.confcmd.status]
|
lea eax, [ebx + device.confcmd.status]
|
||||||
invoke GetPhysAddr
|
invoke GetPhysAddr
|
||||||
@ -704,13 +718,13 @@ init_tx_ring:
|
|||||||
;; Transmit ;;
|
;; Transmit ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; In: pointer to device structure in ebx ;;
|
;; In: pointer to device structure in ebx ;;
|
||||||
|
;; Out: eax = 0 on success ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
align 16
|
||||||
proc transmit stdcall bufferptr
|
proc transmit stdcall bufferptr
|
||||||
|
|
||||||
pushf
|
spin_lock_irqsave
|
||||||
cli
|
|
||||||
|
|
||||||
mov esi, [bufferptr]
|
mov esi, [bufferptr]
|
||||||
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
|
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
|
||||||
@ -721,9 +735,9 @@ proc transmit stdcall bufferptr
|
|||||||
[eax+13]:2,[eax+12]:2
|
[eax+13]:2,[eax+12]:2
|
||||||
|
|
||||||
cmp [esi + NET_BUFF.length], 1514
|
cmp [esi + NET_BUFF.length], 1514
|
||||||
ja .fail
|
ja .error
|
||||||
cmp [esi + NET_BUFF.length], 60
|
cmp [esi + NET_BUFF.length], 60
|
||||||
jb .fail
|
jb .error
|
||||||
|
|
||||||
; Get current TX descriptor
|
; Get current TX descriptor
|
||||||
mov edi, [ebx + device.cur_tx]
|
mov edi, [ebx + device.cur_tx]
|
||||||
@ -733,11 +747,11 @@ proc transmit stdcall bufferptr
|
|||||||
|
|
||||||
; Check if current descriptor is free or still in use
|
; Check if current descriptor is free or still in use
|
||||||
cmp [edi + txfd.status], 0
|
cmp [edi + txfd.status], 0
|
||||||
jne .fail
|
jne .overrun
|
||||||
|
|
||||||
; Fill in status and command values
|
; Fill in status and command values
|
||||||
mov [edi + txfd.status], 0
|
mov [edi + txfd.status], 0
|
||||||
mov [edi + txfd.command], TXFD_CMD_SUSPEND + TXFD_CMD_TX + TXFD_CMD_TX_FLEX
|
mov [edi + txfd.command], TXFD_CMD_SUSPEND or TXFD_CMD_TX or TXFD_CMD_TX_FLEX
|
||||||
mov [edi + txfd.count], 0x01208000
|
mov [edi + txfd.count], 0x01208000
|
||||||
|
|
||||||
; Fill in buffer address and size
|
; Fill in buffer address and size
|
||||||
@ -768,21 +782,31 @@ proc transmit stdcall bufferptr
|
|||||||
add dword[ebx + device.bytes_tx], ecx
|
add dword[ebx + device.bytes_tx], ecx
|
||||||
adc dword[ebx + device.bytes_tx + 4], 0
|
adc dword[ebx + device.bytes_tx + 4], 0
|
||||||
|
|
||||||
; Wait for command to complete
|
|
||||||
call cmd_wait
|
|
||||||
|
|
||||||
inc [ebx + device.cur_tx]
|
inc [ebx + device.cur_tx]
|
||||||
and [ebx + device.cur_tx], TX_RING_SIZE - 1
|
and [ebx + device.cur_tx], TX_RING_SIZE - 1
|
||||||
|
|
||||||
DEBUGF 1,"Transmit OK\n"
|
; Wait for command to complete
|
||||||
popf
|
call cmd_wait
|
||||||
|
|
||||||
|
spin_unlock_irqrestore
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail:
|
.error:
|
||||||
DEBUGF 2,"Transmit failed!\n"
|
DEBUGF 2, "TX packet error\n"
|
||||||
|
inc [ebx + device.packets_tx_err]
|
||||||
invoke NetFree, [bufferptr]
|
invoke NetFree, [bufferptr]
|
||||||
popf
|
|
||||||
|
spin_unlock_irqrestore
|
||||||
|
or eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.overrun:
|
||||||
|
DEBUGF 2, "TX overrun\n"
|
||||||
|
inc [ebx + device.packets_tx_ovr]
|
||||||
|
invoke NetFree, [bufferptr]
|
||||||
|
|
||||||
|
spin_unlock_irqrestore
|
||||||
or eax, -1
|
or eax, -1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -794,42 +818,24 @@ endp
|
|||||||
;; Interrupt handler ;;
|
;; Interrupt handler ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
align 16
|
||||||
align 4
|
|
||||||
int_handler:
|
int_handler:
|
||||||
|
|
||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,"INT\n"
|
mov ebx, [esp+4*4]
|
||||||
|
DEBUGF 1,"INT for 0x%x\n", ebx
|
||||||
|
|
||||||
; find pointer of device wich made IRQ occur
|
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
|
||||||
|
|
||||||
mov ecx, [devices]
|
|
||||||
test ecx, ecx
|
|
||||||
jz .nothing
|
|
||||||
mov esi, device_list
|
|
||||||
.nextdevice:
|
|
||||||
mov ebx, [esi]
|
|
||||||
|
|
||||||
; set_io [ebx + device.io_addr], 0 ; REG_SCB_STATUS = 0
|
; set_io [ebx + device.io_addr], 0 ; REG_SCB_STATUS = 0
|
||||||
set_io [ebx + device.io_addr], REG_SCB_STATUS
|
set_io [ebx + device.io_addr], REG_SCB_STATUS
|
||||||
in ax, dx
|
in ax, dx
|
||||||
out dx, ax ; send it back to ACK
|
|
||||||
test ax, ax
|
test ax, ax
|
||||||
jnz .got_it
|
jz .nothing
|
||||||
.continue:
|
out dx, ax ; send it back to ACK
|
||||||
add esi, 4
|
|
||||||
dec ecx
|
|
||||||
jnz .nextdevice
|
|
||||||
.nothing:
|
|
||||||
pop edi esi ebx
|
|
||||||
xor eax, eax
|
|
||||||
|
|
||||||
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
|
DEBUGF 1,"Status: %x\n", ax
|
||||||
|
|
||||||
.got_it:
|
|
||||||
|
|
||||||
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax
|
|
||||||
|
|
||||||
test ax, SCB_STATUS_FR ; did we receive a frame?
|
test ax, SCB_STATUS_FR ; did we receive a frame?
|
||||||
jz .no_rx
|
jz .no_rx
|
||||||
@ -958,18 +964,22 @@ int_handler:
|
|||||||
.no_tx:
|
.no_tx:
|
||||||
|
|
||||||
test ax, RU_STATUS_NO_RESOURCES
|
test ax, RU_STATUS_NO_RESOURCES
|
||||||
jne .fail
|
jz .not_out_of_resources
|
||||||
|
|
||||||
DEBUGF 2, "Out of resources!\n"
|
DEBUGF 2, "Out of resources!\n"
|
||||||
|
|
||||||
.fail:
|
.not_out_of_resources:
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
inc eax
|
inc eax
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.nothing:
|
||||||
|
pop edi esi ebx
|
||||||
|
xor eax, eax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
@ -983,9 +993,6 @@ cmd_wait:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
ee_read: ; esi = address to read
|
ee_read: ; esi = address to read
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user