📄 head.asm
字号:
; Copyright 1988-1995 Russell Nelson.
;Licensed by Intel for distribution without complete source.
;History:1137,1
;Tue Sep 03 14:17:57 2002 Don't chain to default interrupt handler if we handled.
;Fri Aug 11 15:59:38 2000 Change the way xmit works so we can abort interrupt processing
include defs.asm
cgroup group code,init,_text
code segment para public 'code'
assume cs:cgroup, ds:cgroup
public phd_environ
org 2ch
phd_environ dw ?
public phd_dioa
org 80h
phd_dioa label byte
org 100h
start:
jmp start_1
extrn start_1: near
db "PK"
extrn branding_msg: byte
dw branding_msg
even ;put the stack on a word boundary.
dw 128 dup(?) ;128 words of stack.
our_stack label byte
extrn int_no: byte
public entry_point, sys_features, flagbyte, is_186, is_286, is_386
entry_point db ?,?,?,? ; interrupt to communicate.
sys_features db 0 ; 2h = MC 40h = 2nd 8259
is_186 db 0 ;=0 if 808[68], =1 if 80[123]86.
is_286 db 0 ;=0 if 80[1]8[68], =1 if 80[234]86.
is_386 db 0 ;=0 if 80[12]8[68], =1 if 80[34]86.
flagbyte db 0
original_mask db 0 ;=0 if interrupt was originally on.
even
functions label word
dw f_not_implemented ;0
dw f_driver_info ;1
dw f_access_type ;2
dw f_release_type ;3
dw f_send_pkt ;4
dw f_terminate ;5
dw f_get_address ;6
dw f_reset_interface ;7
dw f_stop ;8
dw f_not_implemented ;9
dw f_get_parameters ;10
dw f_not_implemented ;11
dw f_as_send_pkt ;12
dw f_drop_pkt ;13
dw f_not_implemented ;14
dw f_not_implemented ;15
dw f_not_implemented ;16
dw f_not_implemented ;17
dw f_not_implemented ;18
dw f_not_implemented ;19
dw f_set_rcv_mode ;20
dw f_get_rcv_mode ;21
dw f_set_multicast_list ;22
dw f_get_multicast_list ;23
dw f_get_statistics ;24
dw f_set_address ;25
;external data supplied by device-dependent module:
extrn driver_class: byte
extrn driver_type: byte
extrn driver_name: byte
extrn driver_function: byte
extrn parameter_list: byte
extrn rcv_modes: word ;count of modes followed by mode handles.
;external code supplied by device-dependent module:
extrn send_pkt: near
extrn as_send_pkt: near
extrn drop_pkt: near
extrn set_address: near
extrn terminate: near
extrn reset_interface: near
extrn xmit: near
extrn recv: near
extrn etopen: near
extrn set_multicast_list: near
extrn timer_isr: near
per_handle struc
in_use db 0 ;non-zero if this handle is in use.
packet_type db MAX_P_LEN dup(0);associated packet type.
packet_type_len dw 0 ;associated packet type length.
receiver dd 0 ;receiver handler.
receiver_sig db 8 dup(?) ;signature at the receiver handler.
class db ? ;interface class
per_handle ends
handles per_handle MAX_HANDLE dup(<>)
end_handles label byte
public multicast_count, multicast_addrs, multicast_broad
multicast_count dw 0 ;count of stored multicast addresses.
multicast_broad db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh ; entry for broadcast
multicast_addrs db MAX_MULTICAST*EADDR_LEN dup(?)
;the device-dependent code reads the board's address from ROM in the
;initialization code.
public address_len, rom_address, my_address
address_len dw EADDR_LEN ;default to Ethernet.
rom_address db MAX_ADDR_LEN dup(?) ;our address in ROM.
my_address db MAX_ADDR_LEN dup(?) ;our current address.
rcv_mode_num dw 3
free_handle dw 0 ; temp, a handle not in use
found_handle dw 0 ; temp, handle for our packet
receive_ptr dd 0 ; the pkt receive service routine
public send_head, send_tail
send_head dd 0 ; head of transmit queue
send_tail dd 0 ; tail of transmit queue
statistics_list label dword
packets_in dw ?,?
packets_out dw ?,?
bytes_in dw ?,?
bytes_out dw ?,?
errors_in dw ?,?
errors_out dw ?,?
packets_dropped dw ?,? ;dropped due to no type handler.
REGS_R_32_BIT EQU 1
REG_16 MACRO param
param dw ?
ifdef REGS_R_32_BIT
dw ?
endif
ENDM
REG_8 MACRO param1, param2
param1 db ?
param2 db ?
ifdef REGS_R_32_BIT
dw ?
endif
ENDM
ifdef REGS_R_32_BIT
REG_WORD_SIZE equ 2
else
REG_WORD_SIZE equ 1
endif
savespss label dword
savesp dw (?) ;saved during the stack swap.
savess dw ?
their_recv_isr dd 0 ; original owner of board int
public their_timer
their_timer dd 0
;
; The following structure is used to access the registers pushed by the
; packet driver interrupt handler. Don't change this structure without also
; changing the "bytes" structure given below.
;
regs struc ; stack offsets of incoming regs
_ES dw ?
_DS dw ?
REG_16 _BP
REG_16 _DI
REG_16 _SI
REG_16 _DX
REG_16 _CX
REG_16 _BX
REG_16 _AX
_IP dw ?
_CS dw ?
_F dw ? ; flags, Carry flag is bit 0
regs ends
;
; bits in the _F register.
;
CY equ 0001h
EI equ 0200h
;
; This structure is a bytewise version of the "regs" structure above.
;
bytes struc ; stack offsets of incoming regs
dw ? ; es, ds, are 16 bits
dw ?
dw REG_WORD_SIZE dup (?) ; bp, di, si are 16 (or 32) bits
dw REG_WORD_SIZE dup (?)
dw REG_WORD_SIZE dup (?)
REG_8 _DL, _DH
REG_8 _CL, _CH
REG_8 _BL, _BH
REG_8 _AL, _AH
bytes ends
public their_isr
their_isr dd 0 ; original owner of pkt driver int
public our_isr
our_isr:
jmp short our_isr_0 ;the required signature.
nop
db 'PKT DRVR',0
our_isr_open:
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
call etopen ; init the card
jc our_isr_no_init
mov si,offset cgroup:rom_address ;copy their original address to
movseg es,ds
mov di,offset cgroup:my_address ; their current address.
mov cx,MAX_ADDR_LEN/2
rep movsw
cmp rcv_modes+2[3*2],0 ;does mode 3 exist?
stc ;make sure we generate an error!
je our_isr_no_init ;no.
call rcv_modes+2[3*2] ; call it.
clc
our_isr_no_init:
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
mov dh,CANT_RESET ; (actually can't initialize)
; jc our_isr_error
jnc qqq
jmp our_isr_error
qqq:
or flagbyte,CALLED_ETOPEN ; remember this fact
jmp short our_isr_cont
our_isr_0:
assume ds:nothing
PUSH_16_32 ax
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
mov bx,cs ;set up ds.
mov ds,bx
assume ds:cgroup
mov bp,sp ;we use bp to access the original regs.
and _F[bp],not CY ;start by clearing the carry flag.
if 0
test _F[bp],EI ;were interrupt on?
jz our_isr_ei ;no, don't turn them back on.
sti ;yes, turn them back on.
our_isr_ei:
endif
test flagbyte,CALLED_ETOPEN ; have we initialized the card?
; jz our_isr_open ; no
jnz our_isr_cont
jmp our_isr_open ; no
our_isr_cont:
mov bl,ah ;jump to the correct function.
xor bh,bh
cmp bx,25 ;only twenty five functions right now.
ja f_bad_command
add bx,bx ;*2
;
; The functions are called with all the original registers except
; BX, DH, and BP. They do not need to preserve any of them. If the
; function returns with cy clear, all is well. Otherwise dh=error number.
;
call functions[bx]
assume ds:nothing
jc our_isr_error
our_isr_return:
pop es
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
iret
our_isr_error:
assume ds:nothing
mov bp,sp ;we use bp to access the original regs.
mov _DH[bp],dh
or _F[bp],CY ;return their carry flag.
jmp short our_isr_return
f_bad_command:
assume ds:cgroup
extrn bad_command_intercept: near
mov bx,_BX[bp]
call bad_command_intercept
mov _BX[bp],bx
mov _DX[bp],dx
jnc our_isr_return
jmp our_isr_error
public re_enable_interrupts
re_enable_interrupts:
; Possibly re-enable interrupts. We put this here so that other routines
; don't need to know how we put things on the stack.
test _F[bp], EI ; Were interrupts enabled on pkt driver entry?
je re_enable_interrupts_1 ; No.
sti ; Yes, re-enable interrupts now.
re_enable_interrupts_1:
ret
f_not_implemented:
mov dh,BAD_COMMAND
stc
ret
f_driver_info:
; As of 1.08, the handle is optional, so we no longer verify it.
; call verify_handle
cmp _AL[bp],0ffh ; correct calling convention?
jne f_driver_info_1 ; ne = incorrect, fail
;For enhanced PD, if they call
cmp _BX[bp],offset cgroup:handles ;with a handle, give them the
;class they think it is
jb default_handle
cmp _BX[bp],offset cgroup:end_handles ;otherwise default to first class
jae default_handle
mov bx, _BX[bp]
cmp [bx].in_use,0 ;if it's not in use, it's bad.
je default_handle
mov al, [bx].class
mov _CH[bp], al
jmp short got_handle
default_handle:
mov al,driver_class
mov _CH[bp],al
got_handle:
mov _BX[bp],majver ;version
mov al,driver_type
cbw
mov _DX[bp],ax
mov _CL[bp],0 ;number zero.
mov _DS[bp],ds ; point to our name in their ds:si
mov _SI[bp],offset cgroup:driver_name
mov al,driver_function
mov _AL[bp],al
clc
ret
f_driver_info_1:
stc
ret
f_set_rcv_mode:
call verify_handle
cmp cx,rcv_mode_num ;are we already using that mode?
je f_set_rcv_mode_4 ;yes, no need to check anything.
mov dx,bx ;remember our handle.
call count_handles ;is ours the only open handle?
cmp cl,1
jne f_set_rcv_mode_1 ;no, don't change the receive mode.
mov cx,_CX[bp] ;get the desired receive mode.
cmp cx,rcv_modes ;do they have this many modes?
jae f_set_rcv_mode_1 ;no - must be a bad mode for us.
mov bx,cx
add bx,bx ;we're accessing words, not bytes.
mov ax,rcv_modes[bx]+2 ;get the handler for this mode.
or ax,ax ;do they have one?
je f_set_rcv_mode_1 ;no - must be a bad mode for us.
mov rcv_mode_num,cx ;yes - remember the number and
call ax ; call it.
f_set_rcv_mode_4:
clc
ret
f_set_rcv_mode_1:
mov dh,BAD_MODE
stc
ret
f_get_rcv_mode:
call verify_handle
mov ax,rcv_mode_num ;return the current receive mode.
mov _AX[bp],ax
clc
ret
f_set_multicast_list:
;following instruction not needed because cx hasn't been changed.
; mov cx,_CX[bp] ;Tell them how much room they have.
;verify that they supplied an even number of EADDR's.
mov ax,cx
xor dx,dx
mov bx,EADDR_LEN
div bx
or dx,dx ;zero remainder?
jne f_set_multicast_list_2 ;no, we don't have an even number of
; addresses.
cmp ax,MAX_MULTICAST ;is this too many?
ja f_set_multicast_list_3 ;yes - return NO_SPACE
f_set_multicast_list_1:
mov multicast_count,ax ;remember the number of addresses.
movseg es,cs
mov di,offset cgroup:multicast_addrs
push ds
mov ds,_ES[bp] ; get ds:si -> new list.
mov si,_DI[bp]
push cx
rep movsb
pop cx
pop ds
mov si,offset cgroup:multicast_addrs
call set_multicast_list
ret
f_set_multicast_list_2:
mov dh,BAD_ADDRESS
stc
ret
f_set_multicast_list_3:
mov dh,NO_SPACE
stc
ret
f_get_multicast_list:
mov _ES[bp],ds ;return what we have remembered.
mov _DI[bp],offset cgroup:multicast_addrs
mov ax,EADDR_LEN ;multiply the count by the length.
mul multicast_count
mov _CX[bp],ax ;because they want total bytes.
clc
ret
f_get_statistics:
call verify_handle ;just in case.
mov _DS[bp],ds
mov _SI[bp],offset cgroup:statistics_list
clc
ret
access_type_class:
mov dh,NO_CLASS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -