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

📄 head.asm

📁 dos下的网卡驱动程序。支持一般通用网卡
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;   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 + -