ir.asm
来自「dos下的网卡驱动程序。支持一般通用网卡」· 汇编 代码 · 共 1,244 行 · 第 1/3 页
ASM
1,244 行
;exit with nc if okay, or cy, dh=error if any errors.
assume ds:nothing
call set_ether
jnc short exit_set_address
mov dh, CANT_SET
exit_set_address:
ret
assume ds:cgroup
if CHIP EQ INTEL_82596
rcv_mode_2:
and byte ptr config_start[02h], NOT CB_CFIG_SAVE_BAD_FRAMES
and byte ptr config_start[08h], NOT CB_CFIG_PROMISCUOUS
or byte ptr config_start[08h], CB_CFIG_BROADCAST_DIS
or byte ptr config_start[0Bh], CB_CFIG_MCAST_DISABLE
and byte ptr config_start[0Dh], NOT CB_CFIG_MULTIIA_ENABLE
mov al, MATCH_IA
jmp short set_rcv_mode
rcv_mode_3:
and byte ptr config_start[02h], NOT CB_CFIG_SAVE_BAD_FRAMES
and byte ptr config_start[08h], NOT CB_CFIG_PROMISCUOUS
and byte ptr config_start[08h], NOT CB_CFIG_BROADCAST_DIS
or byte ptr config_start[0Bh], CB_CFIG_MCAST_DISABLE
and byte ptr config_start[0Dh], NOT CB_CFIG_MULTIIA_ENABLE
mov al, MATCH_BRDCAST
jmp short set_rcv_mode
rcv_mode_4:
and byte ptr config_start[02h], NOT CB_CFIG_SAVE_BAD_FRAMES
and byte ptr config_start[08h], NOT CB_CFIG_PROMISCUOUS
and byte ptr config_start[08h], NOT CB_CFIG_BROADCAST_DIS
or byte ptr config_start[0Bh], CB_CFIG_MCAST_DISABLE
or byte ptr config_start[0Dh], CB_CFIG_MULTIIA_ENABLE
mov al, MATCH_SOME_MULTICAST
jmp short set_rcv_mode
rcv_mode_5:
and byte ptr config_start[02h], NOT CB_CFIG_SAVE_BAD_FRAMES
and byte ptr config_start[08h], NOT CB_CFIG_PROMISCUOUS
and byte ptr config_start[08h], NOT CB_CFIG_BROADCAST_DIS
and byte ptr config_start[0Bh], NOT CB_CFIG_MCAST_DISABLE
and byte ptr config_start[0Dh], NOT CB_CFIG_MULTIIA_ENABLE
mov al, MATCH_ALL_MULTICAST
jmp short set_rcv_mode
rcv_mode_6:
or byte ptr config_start[02h], CB_CFIG_SAVE_BAD_FRAMES
or byte ptr config_start[08h], CB_CFIG_PROMISCUOUS
and byte ptr config_start[08h], NOT CB_CFIG_BROADCAST_DIS
and byte ptr config_start[0Bh], NOT CB_CFIG_MCAST_DISABLE
and byte ptr config_start[0Dh], NOT CB_CFIG_MULTIIA_ENABLE
mov al, MATCH_EVERYTHING
else
rcv_mode_2:
and byte ptr config_start[06h], NOT SAVE_BF
or byte ptr config_start[07h], DISC_SHORT
and byte ptr config_start[0Fh], NOT PROMISC_MODE
or byte ptr config_start[0Fh], BROADCAST_DIS
and byte ptr config_start[14h], NOT MULTI_IA_ENBL
and byte ptr config_start[15h], NOT MULTICAST_ALL
mov al, MATCH_IA
jmp set_rcv_mode
rcv_mode_3:
and byte ptr config_start[06h], NOT SAVE_BF
or byte ptr config_start[07h], DISC_SHORT
and byte ptr config_start[0fh], NOT PROMISC_MODE
and byte ptr config_start[0fh], NOT BROADCAST_DIS
and byte ptr config_start[14h], NOT MULTI_IA_ENBL
and byte ptr config_start[15h], NOT MULTICAST_ALL
mov al, MATCH_BRDCAST
jmp short set_rcv_mode
rcv_mode_4:
and byte ptr config_start[06h], NOT SAVE_BF
or byte ptr config_start[07h], DISC_SHORT
and byte ptr config_start[0fh], NOT PROMISC_MODE
and byte ptr config_start[0fh], NOT BROADCAST_DIS
or byte ptr config_start[14h], MULTI_IA_ENBL
and byte ptr config_start[15h], NOT MULTICAST_ALL
mov al, MATCH_SOME_MULTICAST
jmp short set_rcv_mode
rcv_mode_5:
and byte ptr config_start[06h], NOT SAVE_BF
or byte ptr config_start[07h], DISC_SHORT
and byte ptr config_start[0fh], NOT PROMISC_MODE
and byte ptr config_start[0fh], NOT BROADCAST_DIS
and byte ptr config_start[14h], NOT MULTI_IA_ENBL
or byte ptr config_start[15h], MULTICAST_ALL
mov al, MATCH_ALL_MULTICAST
jmp short set_rcv_mode
rcv_mode_6:
or byte ptr config_start[06h], SAVE_BF
and byte ptr config_start[07h], NOT DISC_SHORT
or byte ptr config_start[0fh], PROMISC_MODE
and byte ptr config_start[0fh], NOT BROADCAST_DIS
and byte ptr config_start[14h], NOT MULTI_IA_ENBL
or byte ptr config_start[15h], MULTICAST_ALL
mov al, MATCH_EVERYTHING
endif
set_rcv_mode:
mov curr_rcv_mode, al
call do_config
ret
public set_multicast_list
assume ds:nothing
set_multicast_list:
to_scrn 2,0,'M'
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
; cx = number of bytes.
;return nc if we set all of them, or cy,dh=error if we didn't.
; wait until the previous command has finished executing
set_multicast_list_1:
cmp cx, MAX_MULTICAST * EADDR_LEN ; Max size of multicast data
stc
ja short error_set_multicast_list
if CHIP EQ INTEL_82557
mov ax, cs
mov es, ax
push cx ; Copy for the multicast fix
push si
mov di, offset cgroup:our_multicast_list
mov ax, cx ; Copy byte count
sar cx, 2 ; Convert to a DWORD count
rep movsd ; Copy DWORDS
mov cx, ax ; Recover byte count
and cx, 0003h ; Obtain count mod 4
jz short copied_all_bytes
rep movsb ; Copy remaining bytes
copied_all_bytes:
pop si
pop ax ; Recover size of the multicast data
push ax ; Store again for later
mov cx, MAX_MULTICAST * EADDR_LEN ; Max size of multicast data
sub cx, ax ; cx = size of filler data
je short no_filler
mov ax, 81h ; Default multicast data
rep stosb
no_filler:
pop cx
endif
call get_buffer
jc short error_set_multicast_list
mov bx, di ; Save the start of the buffer
mov eax, (EL_BIT + S_BIT + MULTI_ADD)*10000h
stosd ; Store the action command word + status word
if CHIP EQ INTEL_82596
mov ax, -1
stosw ; Write the address of the next command
else
mov eax, -1 ; Write the address of the next command
stosd ; Store the link address - next command
endif
mov ax, cx ; Write byte count
stosw
; Memory copy of the MC/IA data
sar cx, 2 ; Convert to a DWORD count
rep movsd ; Copy DWORDS
mov cx, ax ; Recover byte count
and cx, 0003h ; Obtain count mod 4
jz short done_all
rep movsb ; Copy remaining bytes
done_all:
mov di, bx ; Recover the start of the buffer
call issue_cmd
error_set_multicast_list:
jnc short exit_set_multicast_list
mov dh, CANT_SET
exit_set_multicast_list:
ret
public terminate
terminate:
call reset_chip
ret
public set_ether
set_ether PROC NEAR
; Set the Individual address registers with the Ethernet address => si
mov ax, cs ; Get correct segment into es
mov es, ax
mov cx, 4 ; Get buffer will wait for 27ms each call
try_for_ether_buffer:
call get_buffer
jnc short got_ether_buffer
loop try_for_ether_buffer
mov dx, offset cgroup:ether_add_msg1
stc
jmp short exit_set_ether ; Exit if buffer not available
got_ether_buffer:
mov cx, EADDR_LEN
mov bx, di ; Save the start of the buffer
mov eax, (EL_BIT + IA_SETUP)*10000h
stosd ; Store the action command word + status word
if CHIP EQ INTEL_82596
mov ax, -1 ; Get the address (16 bit) of next command
stosw ; Store the link address - next command
else
mov eax, -1 ; Get the address (32 bit) of the next command
stosd ; Store the link address - next command
endif
mov cx, EADDR_LEN/2 ; Now copy over the ethernet address
rep movsw
if CHIP EQ INTEL_82557
add di, 02h ; Increase to the address of the next command
endif
mov di, bx ; Recover the start of the buffer
call issue_cmd
mov dx, offset cgroup:ether_add_msg2
exit_set_ether:
ret
set_ether ENDP
public do_config
do_config PROC NEAR
; Set the configuration information
mov cx, 4 ; Get buffer will wait for 27ms each call
try_for_config_buffer:
call get_buffer
jnc short got_config_buffer
loop try_for_config_buffer
stc
jmp short exit_do_config ; Exit if buffer not available
got_config_buffer:
mov cx, offset cgroup:config_end - offset cgroup:config_start
mov bx, di ; Save the start of the buffer
mov si, offset cgroup:config_start
mov eax, (EL_BIT + S_BIT + CONFIG_CMD)*10000h
stosd ; Store the action command word + status word
if CHIP EQ INTEL_82596
mov ax, -1 ; Set the address (16 bits) of next command
stosw ; Store the link address - next command
else
mov eax, -1 ; Set the address (32 bits) of next command
stosd ; Store the link address - next command
endif
sar cx, 2h ; Convert to a DWORD count
rep movsd
mov di, bx ; Recover the start of the buffer
call issue_cmd
exit_do_config:
; debug - No documentation on the correct delay for the config command
mov ax, 10h ; Wait for the command
call wait
clc
ret
do_config ENDP
public reset_chip
reset_chip PROC NEAR
if CHIP EQ INTEL_82596
xor ax, ax
LOAD_PORT PLXP_CA_OFFSET ; Writing a 0 here will reset the chip
out dx, ax
STALL
call wait_27ms ; Only really need a 5ms delay
call clear_interrupt_latch
else
call disable_board_int
LOAD_PORT PORT ; Issue a selective reset before full reset
mov eax, SELECTIVE_RESET
out dx, eax
STALL ; Cannot acces chip for 10 micro seconds
mov ax, 4 ; Wait, if necessary, for about
call set_timeout ; 100 mili-seconds
check_test_buff:
in eax, dx ; Has selective reset completed
or eax, 0h
je short done_selective_reset ; Jump if so
call do_timeout ; Any more time left ?
jnz check_test_buff ; Continue to wait if so
done_selective_reset:
mov eax, SOFTWARE_RESET ; Now issue full software reset
out dx, eax
endif
mov ax,02h ; Wait about 50ms
call wait
ret
reset_chip ENDP
public wait_27ms, wait
wait_27ms:
mov ax, 1
NOWARN
wait:
WARN
call set_timeout
wait_27ms_1:
call do_timeout
jne wait_27ms_1
ret
public reset_interface
reset_interface:
;reset the interface.
assume ds:cgroup
ret
;called when we want to determine what to do with a received packet.
;enter with cx = packet length, es:di -> packet type, dl = packet class.
extrn recv_find: near
;called after we have copied the packet into the buffer.
;enter with ds:si ->the packet, cx = length of the packet.
extrn recv_copy: near
;call this routine to schedule a subroutine that gets run after the
;recv_isr. This is done by stuffing routine's address in place
;of the recv_isr iret's address. This routine should push the flags when it
;is entered, and should jump to recv_exiting_exit to leave.
;enter with ax = address of routine to run.
extrn schedule_exiting: near
;recv_exiting jumps here to exit, after pushing the flags.
extrn recv_exiting_exit: near
extrn count_in_err: near
extrn count_out_err: near
extrn count_handles : near
start_receive_unit PROC NEAR
; First check if reciever is ready
if CHIP EQ INTEL_82596
mov ax, scb_buff.scb_status ; Get the status bits
else
LOAD_PORT SCB_STATUS
in ax, dx ; Get the status bits
endif
and ax, RU_STATUS_BITS ; Mask non receive status bits
cmp ax, RU_READY ; Is the receiver ready
jne short do_restart ; No - restart the receiver
cmp rbd_counter, GIANT / SIZE_ONE_DATA_BUFF ; Gone too far ?
jbe short ru_is_ready ; Yes - restart
mov rbd_counter, 0
do_restart:
to_scrn 2,0,'@'
if CHIP EQ INTEL_82557
add dx, SCB_CMD - SCB_STATUS ; Get to the command register
mov al, RU_ABORT
out dx, al
STALL
STALL
add dx, SCB_STATUS - SCB_CMD ; Get back to the status register
mov ax, SCB_STATUS_MASK
out dx, ax ; ACK the interrupts
endif
if 1
; Code to reset the rbd and rfd descriptors
mov cx, RBD_COUNT ; Setup the receive buffer descriptors
mov si, first_rbd
next_rbd:
mov [si].rbd_status, 0
mov si, WORD PTR [si].rbd_link
loop next_rbd
mov cx, RFD_COUNT ; Setup the receive buffer descriptors
mov di, first_rfd
if CHIP EQ INTEL_82596
mov [di].rfd_ptr, si ; Setup the start rfd to point to the start rbd
else
movzx esi, si
mov [di].rfd_ptr, esi ; Setup the start rfd to point to the start rbd
endif
next_rfd:
mov [di].rfd_status, 0h
mov di, WORD PTR [di].rfd_link
loop next_rfd
endif
; re-start receive unit and setup the intial RFD
if CHIP EQ INTEL_82596
mov scb_buff.scb_rfa_add, di ; Set SCB for the START RU command
mov scb_buff.scb_command, RU_START
STALL
C_ATTENTION
STALL
else
add dx, SCB_GEN_PTR - SCB_STATUS; Get back to the general pointer
movzx eax, di
out dx, eax ; Issue the address - upper word is low
add dx, SCB_CMD - SCB_GEN_PTR ; Get back to cmd port
mov al, RU_START
out dx, al ; Issue the command
endif
ru_is_ready:
ret
start_receive_unit ENDP
public recv
recv:
;called from the recv isr. All registers have been saved, and ds=cs.
;Upon exit, the interrupt will be acknowledged.
assume ds:cgroup
if CHIP EQ INTEL_82596
LOAD_PORT PLXP_INTERRUPT_CONTROL
in al, dx
test al, BIT_4
jz short check_receiver_status
endif
to_scrn 2,0,'I'
look_again:
WAIT_CMD_ACCEPTED
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?