📄 ir.asm
字号:
;Licensed by Intel for distribution without complete source.
;History:1,1
;Tue Aug 21 12:54:06 2001 call setup_53040 on an 82555 as well.
;Wed Aug 01 22:00:25 2001 Add some calls to count_in_err
;Fri Aug 11 15:58:39 2000 Change the way the xmit routine works so we can implement IRQ chaining "right"
include options.inc
include chip.inc
include defs.asm
if CHIP EQ INTEL_82596
include 82596.inc
else
include 82557.inc
endif
cgroup group code, _text, init
code segment para public 'code'
assume cs:cgroup, ds:cgroup
include timeout.asm
extrn ether_add_msg1 : word
extrn ether_add_msg2 : word
extrn their_timer : dword
public mem_map_io
mem_map_io dw 0,0 ; Memory mapped I/O address from the command line
public tx_buff_no, buff_ptrs
tx_buff_no dw ?
old_buff_no dw ?
buff_ptrs dw offset cgroup:cmd_buff1
dw offset cgroup:cmd_buff2
rbd_counter db 0 ; Used to guard against no EOF set
align 4
public cmd_buff1, cmd_buff2
cmd_buff1 db GIANT + 10h dup (?)
align 4
cmd_buff2 db GIANT + 10h dup (?)
if CHIP EQ INTEL_82557
timer_count dw 0h ; Watchdog timer for the receiver lockup
endif
public base_addr, int_no
base_addr dw 0,0 ; I/O address as located via the I/O scan
int_no db 0,0,0,0 ; must be four bytes long for get_number.
public driver_class, driver_type, driver_name
driver_class db BLUEBOOK,IEEE8023,0 ;null terminated list of classes.
driver_type db 255 ;from the packet spec
driver_name db short_name, 0 ;name of the driver.
public driver_function, parameter_list
driver_function db 8 + 2 ; Mix capability + packet status returned in DH
parameter_list label byte
db 1 ;major rev of packet driver
db 9 ;minor rev of packet driver
db 14 ;length of parameter list
db EADDR_LEN ;length of MAC-layer address
dw GIANT ;MTU, including MAC headers
dw MAX_MULTICAST * EADDR_LEN ;buffer size of multicast addrs
dw 0 ;(# of back-to-back MTU rcvs) - 1
dw 0 ;(# of successive xmits) - 1
public int_num
int_num dw 0 ;Interrupt # to hook for post-EOI
;processing, 0 == none,
;-> current address
extrn my_address: byte
received_ours db 0
public rcv_modes
;number of receive modes in our table.
rcv_modes dw (offset cgroup:end_rcv_modes - offset cgroup:mode_zero)/2
mode_zero dw 0 ;There is no mode zero
dw 0
dw rcv_mode_2 ; Individual address only
dw rcv_mode_3 ; Mode 2 + Broadcast address
dw rcv_mode_4 ; Mode 3 + Limited Multi-Cast addresses
dw rcv_mode_5 ; Mode 4 + all Multi_Cast addresses
dw rcv_mode_6 ; All packets - promiscuous mode
end_rcv_modes:
curr_rcv_mode db MATCH_BRDCAST ; The current receive mode
save_err db 0 ; Errors in last frame received (promiscuous mode only)
ALIGN 4
config_start:
if CHIP EQ INTEL_82596
; This structure needs to be 14 bytes long but is rounded up to 16 bytes in
; order to make use of DWORD transfers
db CB_CFIG_PREFETCH_BIT + (offset cgroup:true_config_end - offset cgroup:config_start)
db CB_CFIG_NO_MONITOR_MODE + DEFAULT_FIFO
db 40h
db CB_CFIG_PREAMBLE_LEN + CB_CFIG_NO_SRCADR + CB_CFIG_ADDRESS_LEN
db 0h
db CB_CFIG_IFS
db CB_CFIG_SLOTTIME_LOW
db CB_CFIG_MAX_RETRIES + CB_CFIG_SLOTTIME_HIGH
db 0h
db 0h
db RUNT
db CB_CFIG_NO_MONITOR_MODE + CB_CFIG_MCAST_DISABLE + CB_CFIG_NO_CDT_SAC + CB_CFIG_AUTO_RETX + CB_CFIG_NO_CRC_IN_MEM + CB_CFIG_LENGTH_DISABLE + CB_CFIG_PRECRS_DISABLE
db 0h
db NOT (CB_CFIG_BACKOFF_DISABLE + CB_CFIG_MULTIIA_ENABLE)
else
public config_mii_mode, config_cdt, config_duplex
; This structure needs to be 22 bytes long but is rounded up to 24 bytes in
; order to make use of DWORD transfers
db offset cgroup:true_config_end - offset cgroup:config_start
db TX_FIFO_LMT + RX_FIFO_LMT
db ADPATIVE_IFS
db 0h
db RX_DMA_MAX
db DMBC_EN + TX_DMA_MAX
db CI_INT + LATE_SCB + 32h
db UNDR_RTRY_1 + DISC_SHORT
config_mii_mode:
db 0h ; For MII interface - db MII_MODE
db 0h
db PREAMBLE_LEN_7 + NSAI + 6h
db NRML_LINR_PRTY
; debug
; db DEF_IFS_SPACING
db 0f0h ;- works 0a0h too small
db 0h
db 0f2h
config_cdt:
db CRS_CDT + 48h ; For MII interface - db 48h
db 0h
db 40h
db PADDING_ENBL + STRIPPING_ENBL + 0F0h
config_duplex:
db 0h ; For full duplex set to FDX_PIN_ENBL
db 3fh
db 05h
endif
true_config_end:
db 0 ; 2 extra bytes to make config data
db 0 ; size be a a multiple of DWORDS
config_end:
temp_ru_status dw ?
curs dw 0
if CHIP EQ INTEL_82557
public multicast_fix
multicast_fix dw ? ; All drivers currently need fix - so this is ignored
endif
;this macro writes the given character to the given row and column on a CGA.
to_scrn macro r, c, ch
local di_ok,black,done,one_more
if 0
jumps
.8086
push bx
push es
push di
mov di, cs:curs
cmp di, 3200
jb short di_ok
mov di, 0
di_ok:
mov bx,0b800h
mov es,bx
mov bx,es:[di+r*160+c*2]
test bh,1
jne short black
mov bh,07h
jmp short done
black:
mov bh,70h
done:
mov bl,ch
mov es:[di+r*160+c*2],bx
add di, 2
mov cs:curs, di
pop di
pop es
pop bx
.386
endif
endm
.386 ; Must have >= 386 for these routines to be called
public bad_command_intercept
bad_command_intercept:
;called with ah=command, unknown to the skeleton.
;exit with nc if okay, cy, dh=error if not.
cmp ah, 26
jne short bad_command_intercept_1
if CHIP EQ INTEL_82596
jmp do_tdr
else
; no tdr capability for the 82557
endif
bad_command_intercept_1:
mov dh, BAD_COMMAND
stc
ret
get_buffer PROC NEAR
; Get the next buffer address from the buff_ptr array
mov ax, cs
mov es, ax
mov ax, cs:tx_buff_no ; Get next buffer # to use
mov di, ax ; Save into di
mov cs:old_buff_no, ax ; Save buffer #
inc ax ; Advance the buffer #
cmp ax, 2 ; Advanced too far ?
jl short count_ok ; No - the next count is ok
xor ax, ax ; Next count will be zero
count_ok:
mov cs:tx_buff_no, ax ; Store the updated buffer #
sal di, 1 ; Make bx a word count
mov di, cs:buff_ptrs[di] ; Get the buffer address
mov ax, 1
call set_timeout
wait_cmd_to_complete:
test word ptr cs:[di], C_DONE_BIT
jnz short buff_finished_with
to_scrn 2,0,'W'
call do_timeout ; Any more time left ?
jnz short wait_cmd_to_complete
mov ax, cs:old_buff_no ; Recover the original buffer #
mov cs:tx_buff_no, ax ; Store for next time
stc
ret
buff_finished_with:
clc
ret
get_buffer ENDP
public as_send_pkt
; The Asynchronous Transmit Packet routine.
; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
; interrupts possibly enabled.
; Exit with nc if ok, or else cy if error, dh set to error number.
; es:di and interrupt enable flag preserved on exit.
as_send_pkt:
ret
public drop_pkt
; Drop a packet from the queue.
; Enter with es:di -> iocb.
drop_pkt:
assume ds:nothing
ret
public xmit
; Process a transmit interrupt with the least possible latency to achieve
; back-to-back packet transmissions.
; May only use ax and dx.
; Return cy if we should abort the interrupt reception.
xmit:
assume ds:nothing
WAIT_CMD_ACCEPTED
LOAD_PORT SCB_STATUS
in ax, dx
and ax, SCB_STATUS_MASK
clc
jnz short xmit_1
stc
xmit_1:
ret
public wait_scb_non_active
wait_scb_non_active PROC NEAR
call set_timeout ; AX previously set with the timeout
check_scb_again:
if CHIP EQ INTEL_82596
mov ax, cs:scb_buff.scb_status ; Get the status bits
else
in ax, dx ; Get the status bits
endif
and ax, CU_STATUS_BITS ; Mask all but the cu status
cmp ax, CU_ACTIVE ; Is the cu active
clc ; Clear carry for exit
jne short exit_wait_scb_non_active ; Jump if so
call do_timeout ; No - any more time left ?
jnz check_scb_again ; Continue to wait if so
stc ; Otherwise exit with carry set
exit_wait_scb_non_active:
ret
wait_scb_non_active ENDP
public issue_cmd
issue_cmd PROC NEAR
; di holds the start of the buffer for the command
cmd_accept_wait:
WAIT_CMD_ACCEPTED ; Wait for acceptance of last command
; Now wait for that command to be completed
mov ax, 40h ; Wait, if necessary, for about 1 s
if CHIP EQ INTEL_82557
add dx, SCB_STATUS - SCB_CMD ; Get to the status port
endif
call wait_scb_non_active ; Can't issue a command if chip is active
jc short exit_issue_cmd ; Exit if still active
pushf ; Save interrupt status
cli ; Prevent the receiver from interrupting
if CHIP EQ INTEL_82596
cmp cs:scb_buff.scb_command, 0 ; Did the receiver interrupt earlier
else
add dx, SCB_CMD - SCB_STATUS ; Get to the command port
in al, dx
cmp al, 0 ; Did the receiver interrupt earlier
endif
jz short cmd_accepted ; No - safe to issue command
popf ; Recover flags
jmp short cmd_accept_wait ; Need to wait again
cmd_accepted:
if CHIP EQ INTEL_82596
mov cs:scb_buff.scb_command, CU_START
mov cs:scb_buff.scb_cbl_add, di
STALL
C_ATTENTION
STALL
else
add dx, SCB_GEN_PTR - SCB_CMD ; Get to the general pointer port
xor eax, eax
mov ax, 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, CU_START
out dx, al ; Issue the command
endif
popf ; Restore interrupt status
exit_issue_cmd_ok:
clc
exit_issue_cmd:
ret
issue_cmd ENDP
send_problem:
to_scrn 2,0,'P'
mov dh, CANT_SEND ; Indicate an error.
stc
ret
send_pkt_toobig:
mov dh,NO_SPACE
stc
ret
public send_pkt
send_pkt:
;enter with es:di->upcall routine, (0:0) if no upcall is desired.
; (only if the high-performance bit is set in driver_function)
;enter with ds:si -> packet, cx = packet length.
;if we're a high-performance driver, es:di -> upcall.
;exit with nc if ok, or else cy if error, dh set to error number.
assume ds:nothing
cmp cx,GIANT ; Is this packet too large?
ja send_pkt_toobig
cmp cx, RUNT ; Minimum length for Ether
jae short oklen
mov cx, RUNT ; Make sure size at least RUNT
oklen:
to_scrn 2,0,'T'
mov ax, cs
mov es, ax
call get_buffer
jc send_problem
mov bx, di ; Save the start of the buffer
mov eax, (EL_BIT + S_BIT + TRANSMIT)*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
stosw ; Store the TBD array null pointer
mov eax, TX_EOF_BIT
else
mov eax, -1 ; Write the address of the next command
stosd ; Store the link address - next command
stosd ; Store the TBD array null pointer
mov eax, TX_THRESHOLD*10000h + TX_EOF_BIT
endif
or ax, cx ; Include the length of the packet
stosd
; Memory copy routine
mov ax, cx ; Save 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 no_more
rep movsb ; Copy remaining bytes
no_more:
mov di, bx ; Recover the start of the buffer
call issue_cmd
jc send_problem
ret
public set_address
set_address:
;enter with ds:si -> Ethernet address, CX = length of address.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -