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 + -
显示快捷键?