📄 il.asm
字号:
shl bx, 01h ; Convert to a word count
cmp bx, offset cgroup:unknown_plc-offset cgroup:phy_layer_chip
jb short phy_dev_1_ok
mov bx, offset cgroup:unknown_plc-offset cgroup:phy_layer_chip
phy_dev_1_ok:
mov dx, phy_layer_chip[bx]
print_it
mov si, 0001h ; Setup physical address in si
call setup_routines[bx]
mov cx, supported_plc[bx]
print phys_2_msg
mov bx, eeprom_buff[PHY_DEV_REC_2]
and bx, PHY_DEV_BITS
xchg bl, bh
shl bx, 01h ; Convert to a word count
cmp bx, offset cgroup:unknown_plc-offset cgroup:phy_layer_chip
jb short phy_dev_2_ok
mov bx, offset cgroup:unknown_plc-offset cgroup:phy_layer_chip
phy_dev_2_ok:
mov dx, phy_layer_chip[bx]
print_it
or cx, supported_plc[bx]
cmp cx, SUPPORTED
je short phy_layer_supported
or bx, bx
je short one_phy_dev
mov dx,offset cgroup:no_support_2_phy
jmp short error_get_connector_info
one_phy_dev:
mov dx, offset cgroup:no_support_p_layer
jmp short error_get_connector_info
phy_layer_supported:
cmp duplex, HALF_DUPLEX
je short configed_for_half
mov config_duplex, FDX_PIN_ENBL + FORCE_FDX
configed_for_half:
cmp got_mii_phy, MII_PHY
jne short configed_for_503
mov config_mii_mode, MII_MODE
and config_cdt, NOT CRS_CDT ; Clear CDT for MII interface
configed_for_503:
cmp forced_speed_duplex, 0 ; Check if forced parameters used
je short phy_control_reg_ok
xor bx, bx ; Clear negotiation bit
cmp speed, FAST_100
jne short not_fast
or bx, PHY_CTRL_REG_FAST
not_fast:
cmp duplex, FULL_DUPLEX
jne short not_full
or bx, PHY_CTRL_REG_FULL
not_full:
mov dx,PHY_CONTROL_REG
call write_phy_reg
phy_control_reg_ok:
clc
jmp short exit_get_connector_info
error_get_connector_info:
stc
exit_get_connector_info:
ret
get_connector_info ENDP
write_phy_reg:
; enter with bx = new register contents, dx = register number,
; si = phy number.
; preserves si.
mov ax, si ; Get the physical address
shl ax, 5h ; Move to the correct position
or ax, dx
or ax, PHY_WRITE_OPCODE
shl eax, 10h
mov ax, bx
load_port MDI_CTRL_REG
out dx, eax
STALL
mov ax, 1 ; Wait, if necessary, for about 27ms
call set_timeout
write_phy_reg_1:
in eax, dx ; Get status of MDI command
in eax, dx ; Get status of MDI command
test eax, PHY_READY_BIT ; jump when ready
jne short write_phy_reg_2
call do_timeout ; loop until ready
jnz write_phy_reg_1
stc
write_phy_reg_2:
ret
read_phy_reg:
; enter with bx = register number, si = phy number.
; exit with ax = register value, nc, or cy if we timed out waiting for it.
; preserves bx, si.
mov ax, si ; Get the physical address
shl ax, 5h ; Move to the correct position
or ax, bx
or ax, PHY_READ_OPCODE
shl eax, 10h
load_port MDI_CTRL_REG
out dx, eax
STALL
mov ax, 1 ; Wait, if necessary, for about 27ms
call set_timeout
read_phy_reg_2:
in eax, dx ; Get status of MDI command
in eax, dx ; Get status of MDI command
test eax, PHY_READY_BIT ; Non-zero when ready
jne short read_phy_reg_3 ; Jump if so
call do_timeout ; Any more time left ?
jnz read_phy_reg_2 ; Continue to wait if so
stc
read_phy_reg_3:
ret
else
; Routines for the 82596
init_plx_chip PROC NEAR
;- Program UserPins 0-3 in Write Mode. RCVDIS should default to 1.
LOAD_PORT PLXP_USER_PINS
mov al, 0F0h
or al, BIT_2
out dx, al
LOAD_PORT PLXP_LAN_CONTROL
in ax, dx
or ax, SOFTWARE_RESET_BIT
out dx, ax
and ax, NOT SOFTWARE_RESET_BIT
STALL
STALL
out dx, ax
STALL
STALL
;- Enable LAN 0 interrupt and set it to LATCHED mode
LOAD_PORT PLXP_INTERRUPT_CONTROL
in ax, dx
or ax, LAN_0_INTERRUPT_ENABLE
or ax, LATCHED_INTWRITE_BIT
out dx, ax
STALL
STALL
;- Delay 100msec after PLX reset.
mov ax,0004h
call wait
ret
init_plx_chip ENDP
init_scp PROC NEAR
; Performs the alternate SCP and ISCP initialization for the 82596
mov ax, cs ; Set Up the Alternate SCP Address
mov es, ax
mov si, offset cgroup:scp_buff
call cnvrt_to_phys_add
jc error_init_scp
or al, ALT_SCP_CMD
LOAD_PORT PLXP_PORT_OFFSET
out dx, eax
STALL ; Hold things up - briefly
mov ax, 2
call wait ; Hold things up for 50ms
; Initialize the SYSBUS byte in System Configuration Pointer (SCP)
; Internal Triggering Of Timers, Active High Edge-Triggered Interrupt
mov ax, SYSBUS_CSW OR SYSBUS_LOCK_DIS OR SYSBUS_32_MODE OR SYSBUS_BIT_0
mov scp_buff.scp_sysbus, ax
mov si, offset cgroup:iscp_buff
call cnvrt_to_phys_add
jc error_init_scp
mov scp_buff.scp_iscp_add, eax
mov iscp_buff.iscp_busy, ISCP_BUSY_MARK
mov si, 0
call cnvrt_to_phys_add
jc short error_init_scp
lea si, scb_buff
mov iscp_buff.iscp_scb_offset, si
mov iscp_buff.iscp_scb_lo_add, ax
shr eax, 16
mov iscp_buff.iscp_scb_hi_add, ax
mov scb_buff.scb_status, 0h
C_ATTENTION ; Issue a channel attention to the 82596
mov ax, 1 ; Wait, if necessary, for about 27 mili-
call set_timeout ; seconds (10 should be enough)
iscp_busy_wait:
test iscp_buff.iscp_busy, ISCP_BUSY_MARK
jz short iscp_success
call do_timeout ; Any more time left ?
jnz short iscp_busy_wait ; Continue to wait if so
jmp short iscb_problem
iscp_success:
mov ax, scb_buff.scb_status ;- Acknowledge any interrupts
and ax, SCB_STATUS_MASK
mov scb_buff.scb_command, ax
C_ATTENTION ; Issue a channel attention to the 82596
mov ax, 1 ; Minimum time out value
call wait_scb_non_active
jc short iscb_problem
mov ax, DEFAULT_T_OFF ; Load the Bus Throttle values.
mov scb_buff.scb_off_timer, ax
mov ax, DEFAULT_T_ON
mov scb_buff.scb_on_timer, ax
mov scb_buff.scb_command, CU_LD_B_T_R
C_ATTENTION ; Issue a channel attention to the 82596
mov ax, 1 ; Minimum time out value
call wait_scb_non_active
jnc short exit_init_scp
iscb_problem:
print iscp_init_problem ; Inform the user
stc
exit_init_scp:
ret
error_init_scp:
print problem_in_phys_add
error_init_iscp:
stc
jmp short exit_init_scp
init_scp ENDP
read_ia_pci PROC NEAR
; For the 82596 the Ethernet address is obtained from PCI configuration
mov ah, PCI_FUNCTION_ID ; Get IO base
mov al, READ_PCI_CONFIG_DWORD
mov bx, pci_bus_dev_no ; Recover the bus / device number
mov di, PLXP_NODE_ADDR_REGISTER
int PCI_BIOS_INTERRUPT
cmp ah, PCI_SUCCESSFULL
jne short error_read_ia_pci
mov DWORD PTR rom_address, ecx
mov ah, PCI_FUNCTION_ID ; Get IO base
mov al, READ_PCI_CONFIG_WORD
add di, 4 ; Advance to the next 4 bytes
int PCI_BIOS_INTERRUPT
cmp ah, PCI_SUCCESSFULL
jne short error_read_ia_pci
mov WORD PTR rom_address+4, cx
clc
exit_read_ia_pci:
ret
error_read_ia_pci:
stc
jmp short exit_read_ia_pci
read_ia_pci ENDP
endif
setup_cmd_buffs PROC NEAR
; Setup buffer for commands
mov word ptr cmd_buff1, C_DONE_BIT ; Mark buffer as available
mov word ptr cmd_buff2, C_DONE_BIT ; Mark buffer as available
mov buff_ptrs[0], offset cgroup:cmd_buff1 ; Settup buffer 'array'
mov buff_ptrs[2], offset cgroup:cmd_buff2
mov tx_buff_no, 0 ; Set next buffer # to use
ret
setup_cmd_buffs ENDP
setup_receive PROC NEAR
mov cx, RBD_COUNT ; Setup the receive buffer descriptors
mov ax, cs
mov es, ax
mov si, offset cgroup:start_rx_buff
mov bx, si ; Bx holds a copy of the virtual offset
call cnvrt_to_phys_add
mov esi, eax
mov di, offset cgroup:start_rbd
mov first_rbd, di
mov ax, di
next_rbd:
mov [di].rbd_status, 0
add ax, size rbd_struct ; Pointer to the next RBD
if CHIP EQ INTEL_82596
mov [di].rbd_link, ax
else
movzx eax, ax
mov [di].rbd_link, eax
mov [di].rbd_filler2, 0
endif
mov [di].rbd_ptr, esi ; Store physical address
mov [di].rbd_size, SIZE_ONE_DATA_BUFF
mov [di].rbd_filler1, 0
mov [di].rbd_voffset, bx ; Store the virtual offset
add esi, SIZE_ONE_DATA_BUFF ; Physical address of next buffer
add bx, SIZE_ONE_DATA_BUFF ; Virtual offset of next buffer
mov di, ax ; Advance to the next RBD
loop next_rbd
sub di, size rbd_struct ; Return to previous RBD
mov last_rbd, di
or [di].rbd_size, EL_BIT ; Mark end of chain
mov [di].rbd_link, offset cgroup:start_rbd
mov cx, RFD_COUNT ; Setup the receive buffer descriptors
mov di, offset cgroup:start_rfd
mov first_rfd, di
mov ax, di
next_rfd:
mov [di].rfd_status, 0
mov [di].rfd_eol, FLEXIBLE_MODE
add ax, size rfd_struct ; Pointer to the next RFD
if CHIP EQ INTEL_82596
mov [di].rfd_link, ax
else
movzx eax, ax
mov [di].rfd_link, eax
endif
mov [di].rfd_ptr, -1
mov [di].rfd_cnt, 0
mov [di].rfd_size, 0
mov di, ax ; Advance to the next RFD
loop next_rfd
sub di, size rfd_struct ; Get back to last RFD
mov last_rfd, di
mov [di].rfd_eol, EL_BIT+FLEXIBLE_MODE ; Mark end of chain
if CHIP EQ INTEL_82596
mov [di].rfd_link, offset cgroup:start_rfd ; Wrap around to start
else
mov ax, offset cgroup:start_rfd ; Wrap around to start
movzx eax, ax
mov [di].rfd_link, eax
endif
; Setup the start rdf to point to the start rbd
mov [start_rfd].rfd_ptr, offset cgroup:start_rbd
WAIT_CMD_ACCEPTED ; Wait for acceptance of last command
if CHIP EQ INTEL_82596
mov scb_buff.scb_rfa_add, offset cgroup:start_rfd
mov scb_buff.scb_command, RU_START
C_ATTENTION
else
LOAD_PORT SCB_GEN_PTR
mov ax, offset cgroup:start_rfd
movzx eax, ax
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
ret
setup_receive ENDP
config_chip PROC NEAR
if CHIP EQ INTEL_82557
call load_base_regs
mov dx, offset cgroup:load_base_msg
jc short exit_config_chip ; Exit if there is a problem
endif
call do_config
mov dx, offset cgroup:config_msg
jc short exit_config_chip ; Exit if there is a problem
mov ax, 8 ; Wait for the command
call wait
; Set the Individual address registers with the Ethernet address
mov si, offset cgroup:rom_address
call set_ether
; mov dx, offset cgroup:ether_add_msg
jc short exit_config_chip ; Exit if there is a problem
clc
exit_config_chip:
ret
config_chip ENDP
if CHIP EQ INTEL_82557
load_base_regs PROC NEAR
WAIT_CMD_ACCEPTED ; Wait for acceptance of last command
LOAD_PORT SCB_GEN_PTR ; Load port address for SCB general pointer
xor eax, eax
mov ax, cs
shl eax, 4
out dx, eax ; Load the port with the segment address
LOAD_PORT SCB_CMD ; Load port address for SCB command
mov al, CU_LD_BASE ; Command to set the CU base register
out dx, al ; Issue the command
WAIT_CMD_ACCEPTED ; Wait for acceptance of last command
LOAD_PORT SCB_STATUS ; Load port address for SCB status
mov ax, 1 ; Use minimum time-out in the wait routine
call wait_scb_non_active ; Can't issue a command if chip is active
jc short exit_load_base_regs ; Exit if there is a problem
LOAD_PORT SCB_GEN_PTR ; Load port address for SCB general pointer
xor eax, eax
mov ax, cs
shl eax, 4
out dx, eax ; Load the port with the segment address
LOAD_PORT SCB_CMD ; Load port address for SCB command
mov al, RU_LD_BASE ; Command to set the RU base register
out dx, al ; Issue the command
exit_load_base_regs:
ret
load_base_regs ENDP
endif
do_select_media PROC NEAR
; First check to see if connector type has been specified
if CHIP EQ INTEL_82557
cmp temp_connector, TPE_CONNECTOR ; Found 100Mbs capability
clc
je short using_tpe ; Jump if so
print auto_detect_nr_msg
jmp short using_tpe
endif
cmp temp_connector, TPE_CONNECTOR
je short test_TPE
cmp temp_connector, BNC_CONNECTOR
je short test_BNC
cmp temp_connector, AUI_CONNECTOR
je short test_AUI
print using_auto_msg ; Auto detecting media
call setup_test_packet
test_AUI: ; Try the AUI connector first
mov connector, AUI
if CHIP EQ INTEL_82596
LOAD_PORT PLXP_USER_PINS
in al, dx
or al, PLXP_USER_1
and al, NOT PLXP_USER_0
out dx, al
else
; debug 82557 code required from Intel to select AUI connector
endif
mov ax,0016h ; Delay about 600 msec for front_end setup
call wait
cmp temp_connector, AUI_CONNECTOR
je short using_aui
call send_on_connector
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -