📄 il.asm
字号:
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 + -