⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ir.asm

📁 dos下的网卡驱动程序。支持一般通用网卡
💻 ASM
📖 第 1 页 / 共 3 页
字号:
get_status_again:
if	CHIP EQ INTEL_82596
    mov     ax, scb_buff.scb_status
else
	LOAD_PORT	SCB_STATUS
	in		ax, dx
endif
    and     ax, SCB_STATUS_MASK
	jz		short check_receiver_status
	mov		temp_ru_status, ax			; Save for later
if	CHIP EQ INTEL_82596
    mov     scb_buff.scb_command, ax 	; ACK the interrupts
	STALL
    C_ATTENTION
	STALL
else
    out     dx, ax 						; ACK the interrupts
endif

	test	temp_ru_status, FR_ST_BIT	; A receive interrupt ?
	jz		short try_no_resources_int	
	to_scrn	2,0,'R'
if	CHIP EQ INTEL_82557
	mov		timer_count, 0				; Receever is not dead - clear watchdog
endif
	call	receive_int
	cmp		rbd_counter, GIANT / SIZE_ONE_DATA_BUFF	; Gone too far ?
	ja		short check_receiver_status	; Yes - restart

try_no_resources_int:	
	test	temp_ru_status, RNR_ST_BIT	; An out of resources interrupt ?
	jz		short get_status_again

check_receiver_status:
	call	start_receive_unit			; This also handles out of resources 
if	CHIP EQ INTEL_82596
	STALL
	call	clear_interrupt_latch
	STALL
endif

	to_scrn	2,0,'i'
	ret


receive_int	PROC NEAR
	to_scrn	2,0,'{'
another_frame:
	mov		ax, cs
	mov		es, ax
	mov		bx, first_rfd			; bx => first RFD

	test	[bx].rfd_status, RFD_DONE_BIT	; Has RFD been used
	jnz		short rfd_used			; Yes - read frame data
	to_scrn	2,0,'}'
	ret								; No - exit

rfd_used:								; First find length of the frame
	test	[bx].rfd_status, RESOURCES_BIT
	jz		short enough_resources
	call	count_in_err
	to_scrn	2,0,'B'
	ret

enough_resources:
	mov		si, first_rbd			; si => buffer descriptor
	xor		dx, dx					; dx holds byte count
	mov		di, [si].rbd_voffset	; Save pointer to data

	mov		rbd_counter, 0			; Guard against no EOF set
continue_count:
	mov		ax, [si].rbd_status		; Status and count word for RBD
	test	ax, EOF_BIT				; Last RBD for this frame
	jne		short got_count
valid_count:
	add		dx, SIZE_ONE_DATA_BUFF	; Add full buffer to count
	mov		si, WORD PTR [si].rbd_link	; Advance to next RBD

	inc		rbd_counter 			; Should eventually find an EOF
	cmp		rbd_counter, GIANT / SIZE_ONE_DATA_BUFF	; Gone too far
	jle		continue_count			; Continue if not
	call	count_in_err
	to_scrn	2,0,'*'
	ret

got_count:
	test	ax, COUNT_VALID			; Is the count valid
	jz		ptrupdate				; No - exit with cleanup
	and		ax, 3FFFh				; Clear status bits in the count
	add		dx, ax					; Add partial buffer to count

; Did we receive our own broadcast?
	add		di, EADDR_LEN			; Point to the source address
	mov		ax, di					; Save pointer to received data
	mov		si, offset cgroup:my_address
	mov		cx, EADDR_LEN/2
	repe	cmpsw
	jne		short not_our_own		; Jump if not

	to_scrn	23,79,'O'
	inc		received_ours			; Remember that we received it.
	jmp		ptrupdate				; Exit with cleanup

not_our_own:
	mov		di, ax					; Recover pointer to received data
	add		di, EADDR_LEN			; Now point to the type/length bytes
; Check to make sure that frame has been received with no errors.
; If errors are found then only return frame if in promiscuous mode.
; In promiscuous mode the frame status is assembled and placed in save_err.
	mov		save_err, 1				; Set default value of no error
	mov		ax, [bx].rfd_status		; Get status of frame
	test	ax, RX_OK				; Check if received without errors
	jnz		short no_frame_errs		; Jump if ok

	call	count_in_err
	to_scrn	23,72,'E'

	cmp	curr_rcv_mode, MATCH_EVERYTHING	; Currently in promiscuous mode ?
	jne		short cleanup_exit		; No - discard bad frame

; Find the error bits in the status of the current frame and save in save_err
	mov		ch, 0
	test	ax, SHORT_FRAME_BIT
	je		short RX_not_short
	or		ch, 02h
RX_not_short:
	test	ax, CRC_BIT
	je		short RX_crc_ok
	or		ch, 04h
RX_crc_ok:
	test	ax, ALIGN_BIT
	je		short RX_align_ok
	or		ch, 08h
RX_align_ok:
	test	ax, OVER_RUN_BIT
	je		short RX_no_over_run
	or		ch, 10h
RX_no_over_run:
	mov		save_err, ch

cleanup_exit:
	jmp		short ptrupdate		; Exit with cleanup

no_frame_errs:
	to_scrn	2,0,'R'
	mov		cx, dx			; Get length of packet in cx
	push	bx
	push	cx
	mov		dl, BLUEBOOK		;assume bluebook Ethernet.
	mov		ax, [di]		; Get the packet type
	xchg	ah, al
	cmp 	ax, 1500
	ja		short BlueBookPacket
	inc		di					;set di to 802.2 header
	inc		di
	mov		dl, IEEE8023
BlueBookPacket:
	mov		dh,	save_err		; Get the error status into dh for Intel
	call	recv_find			; See if type and size are wanted
	pop		cx
	pop		bx
	mov		ax, es				; Did recv_find give us a null pointer?
	or		ax, di				; ..
	je		short ptrupdate		; If null, don't copy the data

	push	cx					; We will want the count and pointer
	push	es					;  to hand to client after copying,
	push	di					;  so save them at this point

	mov		si, first_rbd			; si => buffer descriptor
copybuf:
	mov		dx, si				; Save a copy of the RBD
	mov		cx, [si].rbd_status ; Get count word for RBD
	test	cx, EOF_BIT				; Last RBD for this frame
	jne 	short use_actual_count
	mov		cx, SIZE_ONE_DATA_BUFF	; Add full buffer to count
use_actual_count:
	and		ch, 3Fh				; Clear any status bits in count
	mov		si, [si].rbd_voffset	; Get a pointer to data buffer
								; Memory copy routine
	mov		ax, cx				; Save byte count
	sar		cx, 1				; Convert to a DWORD count
	sar		cx, 1				; Convert to a DWORD count
	rep		movsd				; Copy DWORDS
	mov		cx, ax				; Recover byte count
	and		cx, 0003h			; Obtain count mod 4
	jz		short no_more_1
	rep		movsb				; Copy remaining bytes
no_more_1:

	mov		si, dx				; Recover copy of the RBD
	test	[si].rbd_status, EOF_BIT	; Check EOF bit
	mov		si, WORD PTR [si].rbd_link	; Advance to the next RBD
	jz		copybuf				; If not EOF the contine the copy
	pop		si					; Recover pointer to destination
	pop		ds					; Tell client it's his source
	pop		cx					; And it's this long
	assume	ds:nothing
	call	recv_copy			; Give it to him
	assume	ds:cgroup
	mov		ax, cs				; Recover our DS
	mov		ds, ax

ptrupdate:
	to_scrn	2,0,'-'
	; First update the RBD list
	mov		si, first_rbd			; si => buffer descriptor
do_next_rbd:
	test	[si].rbd_status, EOF_BIT	; Check EOF bit
	mov		[si].rbd_status, 0			; Clear status word
	jnz		short do_last_rbd
	cmp		si, last_rbd				; At the end of list ?
	jz		short do_last_rbd			; Jump if so
	mov		si, WORD PTR [si].rbd_link	; Get to the next rbd
	jmp		do_next_rbd
do_last_rbd:

	mov		di, last_rbd				; Current end of RBD list
	mov		last_rbd, si				; Update with the new end of RBD list
	mov		[si].rbd_size, EL_BIT+SIZE_ONE_DATA_BUFF	; Mark end of the list
	mov		[di].rbd_size, SIZE_ONE_DATA_BUFF	; Remove old end-of-list
	mov		ax, WORD PTR [si].rbd_link	; Get to the next rbd
	mov		first_rbd, ax				; Store as the first rbd for next time

	; Now update the RFD list
	mov		di, last_rfd			; Current end of RFD list
	mov		bx, first_rfd				; bx => first RFD
	mov		last_rfd, bx			; Update with the new end of RFD list
	mov		[bx].rfd_eol, EL_BIT+FLEXIBLE_MODE	; Set new end of RFD list
	mov		[bx].rfd_status, 0		; Clear status word for frame
	mov		[di].rfd_eol, FLEXIBLE_MODE	; Remove old end of RFD list
	mov		si, WORD PTR [bx].rfd_link	; Get address of next RFD
	mov		first_rfd, si			; Store first RFD for next time

	jmp		another_frame
receive_int	ENDP


if	CHIP EQ INTEL_82596
do_tdr	PROC NEAR
; enter with es:di pointing to time int
	push	es
	push	di
	mov		ax, cs					; Get correct segment into es
	mov		es, ax
	mov		cx, 8					; Get buffer will wait for 27ms each call
try_for_tdr_buffer:
	call	get_buffer
	jnc		short got_tdr_buffer
	loop	try_for_tdr_buffer
tdr_problem_exit:
	stc
	pop		di
	pop		es
	ret
	
got_tdr_buffer:
	mov		bx, di				; Save the start of the buffer
	mov		eax, (EL_BIT + S_BIT + TDR_CMD)*10000h
	stosd						; Store the action command word + status word
	mov		ax, -1
	stosw						; Write the address of the next command
	xor		ax, ax
	stosw						; Clear the tdr result
	mov		di, bx				; Recover the start of the buffer
	call	issue_cmd
	
	mov		ax, 40h
	call	set_timeout
wait_tdr_to_complete:
	test	cs:[di], word ptr C_DONE_BIT
	jnz		short tdr_done
	call	do_timeout			; Any more time left ?
	jnz		short wait_tdr_to_complete
	jmp		short tdr_problem_exit

tdr_done:
	pop		di
	pop		es
	test	ax, LNK_OK
	jz		short tdr_bad_cable
	clc
	ret

tdr_bad_cable:
	push	ax
	and	ax, TDR_TIME
	stosw				; store time
	pop	ax

	mov	cl, 12
	shr	ax, cl
	and	ax, 7
	mov	dh, al
	stc
	ret
do_tdr	ENDP
endif

	public	timer_isr
timer_isr:
;if the first instruction is an iret, then the timer is not hooked
if	CHIP EQ INTEL_82596
	iret
else
	; 82557 has a receiver lockup problem
	; requires a multicast setup command to 'unlock' it
	; issued every 2 seconds if necessary
	inc		cs:timer_count
	cmp		cs:timer_count, 25h
	jb		short no_receiver_wakeup
	PUSH_16_32	ax			; save lots of registers
	PUSH_16_32	bx
	PUSH_16_32	cx
	PUSH_16_32	dx
	PUSH_16_32	si
	PUSH_16_32	di
	PUSH_16_32	bp
	push	ds
	push	es
	cld
	assume	ds:cgroup, es:cgroup
	mov		ax, cs
	mov		ds, ax
	mov		es, ax
	mov		timer_count, 0
	mov		si, offset cgroup:our_multicast_list
	mov		ax, MAX_MULTICAST				; Max addresses in multicast data
	mov		cx, MAX_MULTICAST * EADDR_LEN	; Max size of multicast data
	call	set_multicast_list
	to_scrn	2,0,'!'
	assume	ds:nothing, es:nothing
	pop		es			; restore lots of registers
	pop		ds
	POP_16_32	bp
	POP_16_32	di
	POP_16_32	si
	POP_16_32	dx
	POP_16_32	cx
	POP_16_32	bx
	POP_16_32	ax
no_receiver_wakeup:
	jmp		cs:their_timer
endif

	public	enable_board_int
enable_board_int	PROC	NEAR
if	CHIP EQ INTEL_82596
	LOAD_PORT	PLXP_INTERRUPT_CONTROL
    mov     al, LATCHED_INTWRITE_BIT
    out     dx, al
else
	LOAD_PORT	SCB_CMD_INT
	xor		al, al
	out		dx, al
endif
	ret
enable_board_int	ENDP
	
if	CHIP EQ INTEL_82557
	public	disable_board_int
disable_board_int	PROC	NEAR
	LOAD_PORT	SCB_CMD_INT
	mov		al, MASK_INT_BIT
	out		dx, al
	ret
disable_board_int	ENDP
endif

if	CHIP EQ INTEL_82596
	public	clear_interrupt_latch
clear_interrupt_latch	PROC	NEAR
	LOAD_PORT	PLXP_INTERRUPT_CONTROL	; Clear int latch
    in		al, dx
    or		al, BIT_4
	out		dx, al
	ret
clear_interrupt_latch	ENDP
endif

if	CHIP EQ INTEL_82557
our_multicast_list	db	(MAX_MULTICAST * EADDR_LEN) dup (81h)
endif

if	CHIP EQ INTEL_82596
	ALIGN	16
	public	scb_buff
scb_buff	db	size SCB_STRUC dup (0)
endif

	public	first_rfd, last_rfd, first_rbd, last_rbd
first_rfd		dw	?
last_rfd		dw	?
first_rbd		dw	?
last_rbd		dw	?

	public	start_rfd, start_rbd, start_rx_buff
	align	4
start_rfd		db RFD_COUNT * (size RFD_STRUCT) dup (?)
	align	4
start_rbd		db RBD_COUNT * (size RBD_STRUCT) dup (?)
	align	4
start_rx_buff	db RBD_COUNT * SIZE_ONE_DATA_BUFF dup (?)

code	ends

_text	segment para public 'code'
_text	ends

init	segment para public 'code'
init	ends

	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -