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

📄 il.asm

📁 dos下的网卡驱动程序。支持一般通用网卡
💻 ASM
📖 第 1 页 / 共 4 页
字号:


check_virtual_mem_services	PROC	NEAR
	; Check to see if virtual DMA service is being provided.
	; Bit 5 of the Bios Flags at 40:7Bh is set if virtual services present
	; Sets the appropriate routine to use for conversion to physical addresses
    mov     ax, 40h
	mov		es, ax
	test	BYTE PTR es:[007bh], 20h
	jz		short no_virtual_services_found
	print 	virtual_services	; Announce virtual DMA services present
	mov		cnvrt_to_phys_add, offset cgroup:virtual_address_convert
	jmp		short exit_check_virtual_mem_services
no_virtual_services_found:
	print 	no_virtual_services	; Announce no virtual DMA services
	mov		cnvrt_to_phys_add, offset cgroup:linear_address_convert
exit_check_virtual_mem_services:
	ret
check_virtual_mem_services	ENDP


linear_address_convert	PROC	NEAR
	; Address to be converted is in es:si
	; Converted physical address is returned in eax
	xor		eax, eax
	mov		ax, es
	shl		eax, 4
	movzx	esi, si			; Make certain that top part of SI is clear
	add		eax, esi
	ret
linear_address_convert	ENDP

virtual_address_convert	PROC	NEAR
	mov     di, offset cgroup:virtual_mem_struct
	; Lock the memory,
	; which in turn returns the physical address in the DMA descriptor
	mov     word ptr [di], 200h
	mov     word ptr [di+2], 0
	mov     word ptr [di+4], si
	mov     word ptr [di+6], 0
	mov     [di+8], es

    mov     ax, 8103h		; Lock DMA region
    mov     dx, 0ch			; No alloc, no remap
    push    ds
    pop     es
    int     4Bh
	jc		short exit_virtual_address_convert

							; Now unlock the DMA region
    mov     ax, 8104h		; Unlock DMA region
    mov     dx, 0			; No copy
    int     4Bh
no_unlock:
    mov     eax, [di+0ch]
	clc
exit_virtual_address_convert:
	ret
virtual_address_convert	ENDP

etopen_chip	PROC	NEAR
	call	find_base			; Go and find the chip
	jc		short exit_etopen_chip
	call	reset_chip
	call	test_chip
	jc		short exit_etopen_chip
if	CHIP EQ INTEL_82557
	; test_chip clears the interrupt mask bit that is set in reset_chip
	call	disable_board_int	; Mask the board interrupts
	print	reading_eeprom_chksum
	call	dump_eeprom			; Copy eeprom contents to RAM

	cmp		checksum, CHKSUM_VAL	; Does it sum to correct signature?
	je		short chksum_ok

	print	eeprom_chksum_bad
	stc						; set flag for chksum bad
	jmp		short exit_etopen_chip
chksum_ok:
	print	self_test_ok_msg
; Copy over the ethernet address
	mov		ax, ds				; ES needs to be correct
	mov		es, ax
	mov		cx, EADDR_LEN/2		; Number of word to move/byte swap
	mov		si, offset cgroup:eeprom_buff
	mov		di, offset cgroup:rom_address	; Where to write ethernet address
	rep		movsw

	call	get_connector_info	; Get info about media
	jc		short exit_etopen_chip
else
	call	init_plx_chip		; Initialize the pci interface chip
    call    init_scp			; Initialize the SCP, ISCP, SCB
	jc		short exit_etopen_chip
scp_int_ok:
	call	read_ia_pci			; Get Ethernet address from PCI Config space
	jc		short exit_etopen_chip
endif

	call	setup_cmd_buffs		; Setup buffer for commands
	call	config_chip			; Configure chip
	jc		short exit_etopen_chip_1
	call	do_select_media
exit_etopen_chip_1:
	ret
configure:
	call	setup_cmd_buffs		; Setup buffer for commands
	call	config_chip			; Configure chip
	jc		short exit_etopen_chip
	call	do_select_media
exit_etopen_chip:
	ret
etopen_failed:
	stc							; Give up.
	ret
etopen_chip	ENDP

test_chip	PROC	NEAR
	print	self_test_msg			; Announce the start of the self test
	mov		ax, cs
	mov		es, ax
	mov		si, offset cgroup:self_test_buff
	call	cnvrt_to_phys_add
	jnc		short cnvrt_ok
	print	problem_in_phys_add
	stc
	jmp		short exit_test_chip
cnvrt_ok:
	or		al, SELF_TEST_CMD
if	CHIP EQ INTEL_82596
	LOAD_PORT	PLXP_PORT_OFFSET
else
	LOAD_PORT	PORT
endif
	out		dx, eax
	STALL							; Hold things up - briefly
	mov		ax, 1					; Wait, if necessary, for about 27 mili-
	call	set_timeout				;    seconds (5 should be enough)
check_test_buff:
	cmp		self_test_buff, 0h	; Test both DWORDS in the buffer
	je		short not_passed		; Need to pass both tests
	cmp		self_test_buff+4, 0h
	jne		short not_passed
	print	self_test_ok_msg
	; 82557 self test resets the chip, need time to recover - 48h too small
	mov		ax, 50h					
	call	wait
	clc
	jmp		short exit_test_chip
not_passed:
	call	do_timeout				; Any more time left ?
	jnz		check_test_buff			; Continue to wait if so
	mov	dx,offset self_test_no_msg		; No - announce failure
	stc
exit_test_chip:
	ret
test_chip	ENDP

if	CHIP EQ INTEL_82557
disable_chip_int	PROC NEAR
	LOAD_PORT	SCB_CMD
	mov		ax, MASK_INT_BIT
	out		dx, ax
	ret
disable_chip_int	ENDP

endif

if	CHIP EQ INTEL_82557

one_mil	EQU	02387

;	readtickcounter
;
;	Read the 16 bit timer tick count register (system board timer 0).
;	The count register decrements by 2 (even numbers) every 838ns.
;
;	Assumes:	Interrupts disabled
;
;	Returns:	AX with the current count
;			Interrupts disabled

readtickcounter:
	xor	al, al			;Command 8254 timer to latch
	out	43h, al			; T0's current count

	in	al, 40h			;read the latched count
	mov	ah, al			; LSB first
	in	al, 40h			; MSB next
	xchg	al, ah			;put count in proper order
	ret


eeprom_delay_1ms:
	push	ax
	push	cx
	call	readtickcounter
	mov	cx, ax
eeprom_delay_1ms_1:
	call	readtickcounter
	neg	ax
	add	ax, cx
	cmp	ax, one_mil
	jb	eeprom_delay_1ms_1
	pop	cx
	pop	ax
	ret

write_eeprom_bit:
	out	dx, al
	call	eeprom_delay_1ms	; wait for the clock to rise
 	or	al, EESK		; Set the eeprom strobe
	out	dx,	al		; Write rising edge of strobe to eeprom
	and	al, NOT EESK		; Clear the eeprom strobe
	out	dx,	al		; Write falling edge of strobe to eeprom
	ret

read_eeprom_bit:
	mov	al, EECS OR EESK
	out	dx, al			; Write rising edge of strobe to eeprom
	call	eeprom_delay_1ms	; wait for the clock to rise
	in	al, dx			; Get the data bit
	mov	bl, al			; Place the result in bl
	mov	al, EECS		; Clear the eeprom strobe
	out	dx, al			; Write falling edge of strobe to eeprom
	ret

;output the READ opcode
write_read_opcode:
	mov	al, EEDI OR EECS	; Set a 1 in the data bit
	call	write_eeprom_bit	; Write a 1
	call	write_eeprom_bit	; Write a 1
	mov	al, EECS		; Set a 0 in the data bit
	call	write_eeprom_bit	; Write a 1
	ret

dump_eeprom	PROC	NEAR
	push	bx
	push	cx
	push	di

	xor	bx, bx			; Offset into eeprom for start of address
	mov	di, offset cgroup:eeprom_buff; Where to write the data
					; Called with :
					; bx = starting offset address in the EEPROM
					; cx = number of bytes to read
					; ds:di = buffer to place the data
					; si is use for temporary storage

	LOAD_PORT	EEPROM_REG	; Set the eeprom port

; now read location zero by clocking out bits until the eeprom reads.
	call	write_read_opcode
	mov	cx,1
get_eeprom_size:
	mov	al, EEDO OR EECS	; set DO to see when eeprom writes a zero
	call	write_eeprom_bit
	shl	cx,1
	in	al,dx
	test	al,EEDO			; when we clock in a zero, the eeprom
	jz	short get_eeprom_size_1	; has gotten it's whole address.
	cmp	cx,EEPROM_MAX
	jb	get_eeprom_size
get_eeprom_size_1:
	mov	address_bitmask,cx
	mov	al, 0			; Disable the EEPROM
	out	dx, al			; Perform the operation

	xor	bx,bx			; start with word zero.
get_next_eeprom_word:
	push	cx			; Number of words left to read
	push	bx			; Address of next word in eeprom

	call	write_read_opcode
	mov	cx, address_bitmask	; Number of bits in each address
next_add_bit:
	shr	cx,1
	mov	al, EECS		; get the chip select bit
	test	bl,cl
	je	short next_add_bit_1
	or	al,EEDI			; if the bit was a one, bring it in.
next_add_bit_1:
	call	write_eeprom_bit	; Write the address bit
	cmp	cx,1
	jne	next_add_bit		; Write out all bits

eeprom_address_done:			; Now ready to read the EEPROM data
	xor	si, si			; Byte will be assembled in si
	mov	cx, 10h			; Number of bits to fetch
get_next_bit:
	call	read_eeprom_bit		; Value of eeprom bit returned in bl
	and	bx, EEDO		; Clear all but the eeprom data output bit
	or	si, bx			; Add the bit to the assembled byte
	rol	si, 1			; Advance byte ready for next bit
	loop	get_next_bit		; Continue until all 16 bits have been read

	mov	cl, 4h			; Final rotate for SI gets the word aligned
	ror	si, cl			;  correctly

	mov	[di], si		; Store the word
  if 0
	mov	ax,si
	call	wordout
	mov	al,' '
	call	chrout
  endif
	add	checksum, si		; add it into the checksum.
	add	di, 2			; Advance the buffer pointer

	pop	bx			; Next EEPROM address to read from
	inc	bx
	pop	cx			; Remaining bytes to read
 	mov	al, 0			; Disable the EEPROM
	out	dx, al			; Perform the operation
	loop	get_next_eeprom_word

	; Now check if the eeprom buffer contains only 0xFFFF (expect MAC address and checksum).
	; In that case, make the checksum invalid.
	; This has to be done, because the Intel EEPROM tool will NOT program the eeprom expect
	; the MAC address and checksum when the eeprom file is write protected.
	; But as long as the checksum is valid, the chip functions will in most cases not work
	; cause they have wrong informations taken from the eeprom.

	cmp	checksum, CHKSUM_VAL
	jne	short check_all_ff_done	; special handling not neccessary if checksum is already invalid

	mov	cx, address_bitmask
	sub	cx, 3+1			; 3 for the MAC address and 1 for the checksum
	jc	short check_all_ff_done	; skip function if cx was too low
	mov	di, offset cgroup:eeprom_buff
	add	di, 3*2			; skip the MAC address
check_all_ff_loop:
	mov	ax, [di]
	cmp	ax, 0FFFFh
	jne	short check_all_ff_done
	add	di, 2
	loop	check_all_ff_loop

ifdef SPECIAL_FFFF_HANDLING_82559ER
	;
	; Fill the buffer with valid values for the 82559ER.
	; This can be done, because the 82559ER has the PHY device built-in and all the
	; values describing the PHY device are known.
	;

	; check if it is a 82559ER
	mov	ax, vendorid
	cmp	ax, 8086h
	jne	short make_checksum_bad		; not a intel part
	mov	ax, deviceid
	cmp	ax, 1209h			; 1209h=82559ER
	jne	short make_checksum_bad		; not the 82559ER

	;
	; now, store valid values for words 3, 5-7
	;
	mov	di, offset cgroup:eeprom_buff

	mov	ax, 0203h			; xx03h:10MB + 100MB
	mov	[di+3*2], ax

	mov	ax, 0201h			; xx01h: connectors=RJ-45
	mov	[di+5*2], ax

	mov	ax, 4701h			; PHY1=82555
	mov	[di+6*2], ax

	mov	ax, 0000h			; PHY2=none
	mov	[di+7*2], ax

	jmp	short check_all_ff_done
endif

make_checksum_bad:
	; make the checksum invalid, cause eeprom is partially unprogrammed
	mov	ax, CHKSUM_VAL
	not	ax
	mov	checksum, ax		; make the checksum invalid

check_all_ff_done:

	pop		di
	pop		cx
	pop		bx
	ret
dump_eeprom	ENDP

get_connector_info	PROC	NEAR
	cmp		WORD PTR eeprom_buff[PHY_DEV_REC_2], 0FFFFh
	jne	short get_connector_info_1
	; the EEPROM may have non-set words equal to all zeroes or all ones.
	mov		WORD PTR eeprom_buff[PHY_DEV_REC_2], 0
get_connector_info_1:

	mov		cx,	eeprom_buff[COMPATIBILITY]
	and		cx,  MC_100_OK + MC_10_OK
	mov		multicast_fix, cx
	jne		short no_fix_required
	print	fix_root_msg
	or		cx, cx
	jne		short not_fix_both
	print	fix_both
	jmp		short no_fix_required
not_fix_both:
	test	cx, MC_10_OK
	jne		short not_fix_10
	print	fix_10bits
not_fix_10:
	test	cx, MC_100_OK
	jne		short no_fix_required
	print	fix_100bits
no_fix_required:

; Prefer to use a 100Mbps phy.
	cmp		WORD PTR eeprom_buff[PHY_DEV_REC_1], 0000h
	je		short no_ph1_device
	test	eeprom_buff[PHY_DEV_REC_1], TEN_MB_ONLY
	je		short support_100

no_ph1_device:
; If they're both 10, go for it.
	cmp		WORD PTR eeprom_buff[PHY_DEV_REC_2], 0000h
	je		short support_10
; if phy2 is 100, use it.
	test	eeprom_buff[PHY_DEV_REC_2], TEN_MB_ONLY
	je		short support_100

support_10:
	mov		speed, SLOW_10
	mov		duplex, HALF_DUPLEX
	print	support_10_msg
	jmp		short done_support

support_100:
	mov		temp_connector, TPE_CONNECTOR	; Must have TP connector
	mov		got_mii_phy, MII_PHY
	print	support_100_msg
	jmp		short done_support

done_support:
	print	phys_1_msg
	mov		bx, eeprom_buff[PHY_DEV_REC_1]
	and		bx, PHY_DEV_BITS
	xchg	bl, bh

⌨️ 快捷键说明

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