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

📄 head.asm

📁 dos下的网卡驱动程序。支持一般通用网卡
💻 ASM
📖 第 1 页 / 共 3 页
字号:
	stc
	ret

access_type_type:
	mov	dh,NO_TYPE
	stc
	ret

access_type_number:
	mov	dh,NO_NUMBER
	stc
	ret

access_type_bad:
	mov	dh,BAD_TYPE
	stc
	ret

;register caller of pkt TYPE
f_access_type:
	mov	bx, offset cgroup:driver_class
access_type_9:
	mov	al, [bx]		;get the next class.
	inc	bx
	or	al,al			;end of the list?
	je	access_type_class	;class failed (story of my life)
	cmp	_AL[bp],al		;our class?
	jne	access_type_9		;no, try again
access_type_1:
	cmp	_BX[bp],-1		;generic type?
	je	access_type_2		;yes.
	mov	al,driver_type
	cbw
	cmp	_BX[bp],ax		;our type?
	jne	access_type_type	;no.
access_type_2:
	cmp	_DL[bp],0		;generic number?
	je	access_type_3
	cmp	_DL[bp],1		;our number?
	jne	access_type_number
access_type_3:
	cmp	_CX[bp],MAX_P_LEN	;is the type length too long?
	ja	access_type_bad		;yes - can't be ours.

; now we do two things--look for an open handle, and check the existing
; handles to see if they're replicating a packet type.

	mov	free_handle,0		;remember no free handle yet.
	mov	bx,offset cgroup:handles
access_type_4:
	cmp	[bx].in_use,0		;is this handle in use?
	je	access_type_5		;no - don't check the type.
	mov	al, _AL[bp]		;is this handle the same class as
	cmp	al, [bx].class		;  they're want?
	jne	short access_type_6
	mov	es,_DS[bp]		;get a pointer to their type
	mov	di,_SI[bp]		;  from their ds:si to our es:di
	mov	cx,_CX[bp]		;get the minimum of their length
					;  and our length.  As currently
					;  implemented, only one receiver
					;  gets the packets, so we have to
					;  ensure that the shortest prefix
					;  is unique.
	cmp	cx,[bx].packet_type_len	;Are we less specific than they are?
	jb	access_type_8		;no.
	mov	cx,[bx].packet_type_len	;yes - use their count.
access_type_8:
	lea	si,[bx].packet_type
	or	cx,cx			; pass-all TYPE? (zero TYPE length)
	jne	access_type_7		; ne = no
	mov	bx,offset cgroup:handles+(MAX_HANDLE-1)*(size per_handle)
	jmp	short access_type_5	; put pass-all last
access_type_7:
	repe	cmpsb
	jne	short access_type_6	;go look at the next one.
access_type_inuse:
	mov	dh,TYPE_INUSE		;a handle has been assigned for TYPE
	stc				;and we can't assign another
	ret
access_type_5:				;handle is not in use
	cmp	free_handle,0		;found a free handle yet?
	jne	access_type_6		;yes.
	mov	free_handle,bx		;remember a free handle
access_type_6:
	add	bx,(size per_handle)	;go to the next handle.
	cmp	bx,offset cgroup:end_handles	;examined all handles?
	jb	access_type_4		;no, continue.

	mov	bx,free_handle		;did we find a free handle?
	or	bx,bx
	je	access_type_space	;no - return error.

	mov	ax,_DI[bp]		;remember the receiver type.
	mov	[bx].receiver.offs,ax
	mov	ax,_ES[bp]
	mov	[bx].receiver.segm,ax

	push	ds
	mov	ax,ds
	mov	es,ax
	mov	ds,_DS[bp]		;remember their type.
	mov	si,_SI[bp]
	mov	cx,_CX[bp]
	mov	es:[bx].packet_type_len,cx	; remember the TYPE length
	lea	di,[bx].packet_type
	rep	movsb

	lds	si,es:[bx].receiver	;copy the first 8 bytes
	lea	di,[bx].receiver_sig	; to the receiver signature.
	mov	cx,8/2
	rep	movsw

	pop	ds

	mov	al, _AL[bp]
	mov	[bx].class, al

	mov	[bx].in_use,1		;remember that we're using it.

	mov	_AX[bp],bx		;return the handle to them.

	clc
	ret


access_type_space:
	mov	dh,NO_SPACE
	stc
	ret

f_release_type:
	call	verify_handle		;mark this handle as being unused.
	mov	[bx].in_use,0

	call	count_handles		;All handles gone now?
	cmp	cl,0
	jne	f_release_type_1	;no, don't change the receive mode.

  if 0
	cmp	rcv_modes+2[3*2],0	;does mode 3 exist?
	je	f_release_type_1	;no.
	mov	rcv_mode_num,3		;yes - remember the number and
	call	rcv_modes+2[3*2]	;  call it.
  endif
f_release_type_1:
	clc
	ret


f_send_pkt:
;ds:si -> buffer, cx = length
; XXX Should re-enable interrupts here, but some drivers are broken.
; Possibly re-enable interrupts.
;	test _F[bp], EI		; Were interrupts enabled on pkt driver entry?
;	je	f_send_pkt_1	; No.
;	sti			; Yes, re-enable interrupts now.
;f_send_pkt_1:

;following two instructions not needed because si and cx haven't been changed.
;	mov	si,_SI[bp]
;	mov	cx,_CX[bp]	; count of bytes in the packet.
	add2	packets_out,1
	add2	bytes_out,cx		;add up the received bytes.

	mov	ds,_DS[bp]	; address of buffer from caller's ds.
	assume	ds:nothing, es:nothing

; If -n option take Ethernet encapsulated Novell IPX packets (from BYU's 
; PDSHELL) and change them to be IEEE 802.3 encapsulated.
EPROT_OFF	equ	EADDR_LEN*2
	test	cs:flagbyte,N_OPTION
	jnz	f_send_pkt_2
	call	send_pkt
	ret

f_send_pkt_2:
	cmp	ds:[si].EPROT_OFF,3781h ; if not Novell (prot 8137)
	jne	f_send_pkt_3		;  don't tread on it
	push	ax			; get scratch reg
	mov	ax,[si].EPROT_OFF+4	; get len
	xchg	ah,al
	inc	ax			; make even (rounding up)
	and	al,0feh
	xchg	ah,al
	mov	ds:[si].EPROT_OFF,ax	; save in prot field
	pop	ax			; restore old contents
f_send_pkt_3:
	call	send_pkt
	ret
	assume	ds:cgroup


f_as_send_pkt:
;es:di -> iocb.
	test	driver_function,4	; is this a high-performance driver?
	je	f_as_send_pkt_2		; no.
; Possibly re-enable interrupts.
	test _F[bp], EI			; Were interrupts enabled on pkt driver entry?
	je	f_as_send_pkt_1		; No.
	sti				; Yes, re-enable interrupts now.
f_as_send_pkt_1:
	push	ds			; set up proper ds for the buffer
	lds	si,es:[di].buffer	; ds:si -> buffer
	assume	ds:nothing
	mov	cx,es:[di].len		; cx = length
	add2	packets_out,1
	add2	bytes_out,cx		; add up the received bytes.

;ds:si -> buffer, cx = length, es:di -> iocb.
	call	as_send_pkt
	pop	ds
	assume	ds:cgroup
	ret
f_as_send_pkt_2:
	mov dh,	BAD_COMMAND		; return an error.
	stc
	ret


f_drop_pkt:
; es:di -> iocb.
	test	driver_function,4	; is this a high-performance driver?
	je	f_as_send_pkt_2		; no.
	push	ds			; Preserve ds
	mov	si,offset cgroup:send_head	; Get head offset
dp_loop:
	mov	ax,ds:[si]		; Get offset
	mov	dx,ds:[si+2]		; Get segment
	mov	bx,ax
	or	bx,dx			; End of list?
	je	dp_endlist		; Yes
	cmp	ax,di			; Offsets equal?
	jne	dp_getnext		; No
	mov	bx,es
	cmp	dx,bx			; Segments equal?
	jne	dp_getnext		; No
	call	drop_pkt		; Pass to driver
	les	di,es:[di].next		; Get next segment:offset
	mov	ds:[si],di		; Set next offset
	mov	ds:[si+2],es		; Set next segment
	pop	ds			; Restore ds
	clc
	ret
dp_getnext:
	mov	ds,dx			; Get next segment
	mov	si,ax			; Get next iocb offset
	lea	si,ds:[si].next		; Get next iocb next ptr offset
	jmp	dp_loop			; Try again
dp_endlist:
	pop	ds			; Restore ds
	mov	dh,BAD_IOCB		; Return error
	stc				; Set carry
	ret


f_terminate:
	call	verify_handle		; must have a handle

	mov	[bx].in_use,0		; mark handle as free
	call	count_handles		; all handles gone?
	or	cl,cl
	jne	f_terminate_4		; no, can't exit completely

;
; Now disable interrupts
;
	mov	al,int_no
	or	al,al			;are they using a hardware interrupt?
	je	f_terminate_no_irq	;no.
	cmp	original_mask,0		;was it enabled?
	je	f_terminate_no_mask	;yes, don't mask it now.
	call	maskint
f_terminate_no_mask:

;
; Now return the interrupt to their handler.
;
	mov	ah,25h			;get the old interrupt into es:bx
	mov	al,int_no
	add	al,8
	cmp	al,8+8			;is it a slave 8259 interrupt?
	jb	f_terminate_3		;no.
	add	al,70h - (8+8)		;map it to the real interrupt.
f_terminate_3:
	push	ds
	lds	dx,their_recv_isr
	int	21h
	pop	ds

f_terminate_no_irq:
	cmp	their_timer.segm,0	;did we hook the timer interrupt?
	je	f_terminate_no_timer

	mov	ax,2508h		;restore the timer interrupt.
	push	ds
	lds	dx,their_timer
	int	21h
	pop	ds

f_terminate_no_timer:

	call	terminate		;terminate the hardware.

	mov	al,entry_point	;release our_isr.
	mov	ah,25h
	push	ds
	lds	dx,their_isr
	int	21h
	pop	ds

;
; Now free our memory
;
	movseg	es,cs
	mov	ah,49h
	int	21h
	clc
	ret
f_terminate_4:
	mov	dh, CANT_TERMINATE
	stc
	ret


f_get_address:
;	call	verify_handle
;	mov	es,_ES[bp]		; get new one
;	mov	di,_DI[bp]		; get pointer, es:di is ready
;	mov	cx,_CX[bp]		;Tell them how much room they have.
	cmp	cx,address_len		;is there enough room for our address?
	jb	get_address_space	;no.
	mov	cx,address_len		;yes - get our address length.
	mov	_CX[bp],cx		;Tell them how long our address is.
	mov	si,offset cgroup:my_address	;copy it into their area.
	rep	movsb
	clc
	ret

get_address_space:
	mov	dh,NO_SPACE
	stc
	ret


f_set_address:
	call	count_handles
	cmp	cl,1			;more than one handle in use?
	ja	f_set_address_inuse	;yes - we can't set the address

	mov	cx,_CX[bp]		;get the desired address length.
	cmp	ch,0
	cmp	cl,parameter_list[3]	;is it the right length?
	ja	f_set_address_too_long	;no.

	mov	ds,_ES[bp]		; set new one
	assume	ds:nothing
	mov	si,_DI[bp]		; set pointer, ds:si is ready
	mov	ax,cs
	mov	es,ax
	mov	di,offset cgroup:my_address
	rep	movsb
	mov	ds,ax			;restore ds.
	assume	ds:cgroup

	mov	cx,_CX[bp]		;get the desired address length.
	mov	si,offset cgroup:my_address
	call	set_address
	jc	f_set_address_err	;Did it work?

	mov	cl,parameter_list[3]
	xor	ch,ch
	mov	_CX[bp],cx		;yes - return our address length.

	clc
	ret
f_set_address_inuse:
	mov	dh,CANT_SET
	stc
	ret
f_set_address_too_long:
	mov	dh,NO_SPACE
	stc
	ret
f_set_address_err:
;we get here with cy set - leave it set.
	mov	si,offset cgroup:rom_address	;we can't set the address, restore
	mov	di,offset cgroup:my_address	;  to original.
	mov	cx,MAX_ADDR_LEN/2
	rep	movsw
	ret


f_reset_interface:
	call	verify_handle
	call	reset_interface
	clc
	ret


; Stop the packet driver doing upcalls. Also a following terminate will
; always succed (no in use handles any longer).
f_stop:
	mov	bx,offset cgroup:handles
f_stop_2:
	mov	[bx].in_use,0
	add	bx,(size per_handle)	; next handle
	cmp	bx,offset cgroup:end_handles
	jb	f_stop_2
	clc
	ret


f_get_parameters:
;strictly speaking, this function only works for high-performance drivers.
	test	driver_function,4	;is this a high-performance driver?
	jne	f_get_parameters_1	;yes.
	mov	dh,BAD_COMMAND		;no - return an error.
	stc
	ret
f_get_parameters_1:
	mov	_ES[bp],cs
	mov	_DI[bp],offset cgroup:parameter_list
	clc
	ret


count_handles:
;exit with cl = number of handles currently in use.
	mov	bx,offset cgroup:handles
	mov	cl,0			;number of handles in use.
count_handles_1:
	add	cl,[bx].in_use		;is this handle in use?
	add	bx,(size per_handle)	;go to the next handle.
	cmp	bx,offset cgroup:end_handles
	jb	count_handles_1
	ret


verify_handle:
;Ensure that their handle is real.  If it isn't, we pop off our return
;address, and return to *their* return address with cy set.
	mov	bx,_BX[bp]		;get the handle they gave us
	cmp	bx,offset cgroup:handles
	jb	verify_handle_bad	;no - must be bad.
	cmp	bx,offset cgroup:end_handles
	jae	verify_handle_bad	;no - must be bad.
	cmp	[bx].in_use,1		;if it's not in use, it's bad.
	jne	verify_handle_bad
	ret
verify_handle_bad:
	mov	dh,BAD_HANDLE
	add	sp,2			;pop off our return address.
	stc
	ret


	public	set_recv_isr
set_recv_isr:
	mov	ah,35h			;get the old interrupt into es:bx
	mov	al,int_no		; board's interrupt vector
	or	al,al
	je	set_isr_no_irq
	add	al,8
	cmp	al,8+8			;is it a slave 8259 interrupt?
	jb	set_recv_isr_1		;no.
	add	al,70h - 8 - 8		;map it to the real interrupt.
set_recv_isr_1:
	int	21h
	mov	their_recv_isr.offs,bx	;remember the old seg:off.
	mov	their_recv_isr.segm,es

	mov	ah,25h			;now set our recv interrupt.
	mov	dx,offset cgroup:recv_isr
	int	21h

	cmp	byte ptr timer_isr,0cfh	;is there just an iret at their handler?
	je	set_isr_no_timer	;yes, don't bother hooking the timer.

	mov	ax,3508h		;get the old interrupt into es:bx
	int	21h
	mov	their_timer.offs,bx	;remember the old seg:off.
	mov	their_timer.segm,es

	mov	ah,25h			;now set our recv interrupt.
	mov	dx,offset cgroup:timer_isr
	int	21h

set_isr_no_timer:
	mov	al,int_no		; Now enable interrupts
	call	unmaskint
	mov	original_mask,al

set_isr_no_irq:
	ret

	public	count_in_err

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -