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

📄 8390.asm

📁 RTL8019 Plug-And-Play Packet Driver.
💻 ASM
📖 第 1 页 / 共 4 页
字号:
;History:538,1
; Ian Brabham	28 Apr 1993	Fix problems related to SMC version of 8390

dp8390_version	equ	3	;version number of the generic 8390 driver.

;  Copyright, 1988-1992, Russell Nelson, Crynwr Software

;   This program is free software; you can redistribute it and/or modify
;   it under the terms of the GNU General Public License as published by
;   the Free Software Foundation, version 1.
;
;   This program is distributed in the hope that it will be useful,
;   but WITHOUT ANY WARRANTY; without even the implied warranty of
;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;   GNU General Public License for more details.
;
;   You should have received a copy of the GNU General Public License
;   along with this program; if not, write to the Free Software
;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

; This driver is the work of several people: Bob Clements, Eric Henderson,
; Dave Horne, Glenn Talbott, Russell Nelson, Jan Engvald, Paul Kranenburg,
; and Ian Brabham.

  ife SM_RSTART_PG
	%err	SM_RSTART_PG cannot be zero because of a decrement/unsigned jump.
  endif

;
; The longpause macro was originally written as this:
;
;longpause macro
;	push	cx
;	mov	cx,0
;	loop	$
;	pop	cx
;endm
;
; It was only used to stall while hard resetting the card. On my
; 25Mhz 486 longpause was taking more than 18ms, and almost forever
; on slower machines, much longer than necessary and not predictable.
;
; To be able to utilize longpause elsewhere and make it machine independent and
; predictable, I have re-written it to be a fixed time of 1.6ms, which just
; happens to be the time National recommends waiting for the NIC chip to
; stop sending or receiving after being commanded to stop.
;
; Based on the assumption that ISA specs mandate a 1.0 uS minimum I/O cycle
; Microchannel a 0.5uS minimum I/O cycle, and the NMI Status register (location
; 61h) is readable via I/O cycle on all machines, the longpause macro is now
; defined below. - gft - 901604
; (I realize that on slow machines this may take much longer, but the point
; is that on FAST machines it should never be faster than 1.6ms)

longpause macro
	local lp_not_mc
	push cx
	push ax
	mov  cx,1600	; 1.6ms = 1600*1.0us
	test sys_features,SYS_MCA
	je   lp_not_mc
	shl  cx,1	; twice as many loops for Microchannel
lp_not_mc:
	in al,61h
	loop lp_not_mc
	pop  ax
	pop  cx
endm

	extrn	sys_features: byte

sm_rstop_ptr	db	SM_RSTOP_PG

rxcr_bits       db      ENRXCR_BCST     ; Default to ours plus multicast
  ifdef board_features
is_overrun_690	db	0
  endif


;-> the assigned Ethernet address of the card.
	extrn	rom_address: byte

;-> current address
	extrn	my_address: byte

	public	mcast_list_bits, mcast_all_flag
mcast_list_bits db      0,0,0,0,0,0,0,0 ;Bit mask from last set_multicast_list
mcast_all_flag  db      0               ;Non-zero if hware should have all
					; ones in mask rather than this list.

	public	rcv_modes
rcv_modes	dw	7		;number of receive modes in our table.
		dw	0               ;There is no mode zero
		dw	rcv_mode_1
		dw	rcv_mode_2
		dw	rcv_mode_3
		dw	rcv_mode_4
		dw	rcv_mode_5
		dw	rcv_mode_6

;
;	a temp buffer for the received header
;
RCV_HDR_SIZE	equ	26		; 2 ids @6 + protocol @2+8, + header @4
rcv_hdr		db	RCV_HDR_SIZE dup(0)

;
;	The board data
;
		public	board_data
BOARD_DATA_SIZE equ	32
board_data	db 	BOARD_DATA_SIZE dup(0)


; add public for soft errors (how were these extracted before? - gft - 910604

		public soft_errors
		public soft_tx_errors,soft_tx_err_bits,soft_tx_collisions
		public soft_rx_errors,soft_rx_err_bits
		public soft_rx_overruns,soft_rx_over_nd
;
; Re-arranged the order of these soft_xx_err things so that they can be
; accessed as a data structure (like the statistics structure defined
; in the packet driver spec. I don't know if it's necessary but I've always
; found data structures to be more portable if elements are size aligned.
;  - gft - 910607
; Don't rearrange or insert things between these soft error words because
; they are accessed as a data structure (I don't think I violated my own
; admonition since they wern't public and I could find no references to 
; them and only the NEx000 drivers reference the next previous thing,
; board_data, and they only us 16 bytes of that.)

soft_errors 		label   dword
soft_tx_errors		dw	0,0
soft_tx_collisions	dw	0,0 ; added - gft - 910607 cause who ever heard
				    ; of a CSMA/CD driver not counting
				    ; collisions.
soft_rx_errors		dw	0,0
soft_rx_overruns	dw	0,0 ; added - gft - 910604 cause I just
				    ; gotta track these so I can findout
				    ; just when I'm pushing a driver or
				    ; application to it's limits
soft_rx_over_nd		dw	0,0 ; Also count when theres no data.
hard_tx_errors		dw	0,0
soft_tx_err_bits	db	0
soft_rx_err_bits	db	0

;
; Next Packet Pointer (added  - gft - 910603)
;
;   Initialize to the same value as the current page pointer (start page 1).
;   Update after each reception to be the value of the next packet pointer
;   read from the NIC Header.
;   Copy value -1 to boundry register after each update.
;   Compare value with contents of current page pointer to verify that a
;   packet has been received (don't trust ISR RXE/PRX bits). If !=, one
;   or more packets have been received.

next_packet	db	0
save_curr	db	0

; Added flags and temp storage for new receive overrun processing
;  - gft - 910604

rcv_ovr_resend	db	0,0	; flag to indicate resend needed
defer_upcall	db	0,0	; flag to indicate deferred upcall needed
defer_ds	dw	?	;   deferred upcall parameters
defer_si	dw	?
defer_cx	dw	?


ifdef	deb2screen
; Event to screen debugger. Destroys no registers and requires just 3 bytes at
; each place called. Produces a one-line summary of event types that has ever
; occured and then some trace lines with the sequence of the last events./Jan E LDC

SHOWMIN		equ	'a'
SHOWMAX		equ	'l'
EVENTCOLOR	equ	31h
EVENTLINE	equ	17
TRACECOLOR	equ	2eh

ShowEvent	proc	near
x		=	0
		rept	(SHOWMAX-SHOWMIN+1)
		push	ax
		mov	al,x
		jmp	short ShowEventNum
x		=	x+1
		endm

  ShowEventNum:
		pushf
		push	di
		push	es
		mov	ah,EVENTCOLOR
		mov	di,ax
		shl	di,1
		add	al,SHOWMIN
		mov	es,cs:EventPar
		cld
		stosw

		mov	ah,TRACECOLOR
		mov	es,cs:TracePar
		cli
		mov	di,cs:TraceInd
		stosw
		and	di,01ffh		; (1ff+1)/2 = 256 log entries
		mov	cs:TraceInd,di
		mov	al,01bh
		not	ah
		stosw

		pop	es
		pop	di
		popf
		pop	ax
		ret
ShowEvent	endp

EventPar	dw	0b800h+(EVENTLINE-1)*10-2*EVENTCOLOR*16
TracePar	dw	0b800h+EVENTLINE*10
TraceInd	dw	0

SHOW_EVENT	macro	id
if id gt SHOWMAX or id lt SHOWMIN
		.err
endif
		call	ShowEvent+((id-SHOWMIN)*(ShowEventNum-ShowEvent)/(SHOWMAX-SHOWMIN+1))
		endm

else

SHOW_EVENT	macro	num
		endm

endif ; deb2screen


ifdef	debug			; Include a very useful logging mechanism.  

; The log entry structure.  Log entries include useful data such as
; a type (each place a log entry is made uses a different type), various
; chip status, ring buffer status, log entry dependent data, and optionally
; 8259 interrupt controller status.
logentry	struc
le_type		db	0	; Log entry type
le_ccmd		db	?	; Value of CCMD register
le_isr		db	?	; Value of ISR register
le_tsr		db	?	; Value of TSR register
le_tcur		dw	?	; Value of sm_tcur
le_tboundary	dw	?	; Value of sm_tboundary
le_tnum		dw	?	; Value of sm_tnum
le_dw		dw	?	; Log type specific dw data
ifndef	mkle8259		; Log 8259 status?
le_dd		dd	?	; Log type specific dd data
else
le_irr1		db	?	; Value of 8259-1 IRR register
le_isr1		db	?	; Value of 8259-1 ISR register
le_irr2		db	?	; Value of 8259-2 IRR register
le_isr2		db	?	; Value of 8259-2 ISR register
endif
logentry	ends

; The types of log entries.
LE_SP_E		equ	0	; send_pkt entry
LE_SP_X		equ	1	; send_pkt exit
LE_ASP_E	equ	2	; as_send_pkt entry
LE_ASP_X	equ	3	; as_send_pkt exit
LE_RBALLOC_E	equ	4	; tx_rballoc entry
LE_RBALLOC_X	equ	5	; tx_rballoc exit
LE_COPY_E	equ	6	; sm_copy entry
LE_COPY_X	equ	7	; sm_copy exit
LE_START_E	equ	8	; tx_start entry
LE_START_X	equ	9	; tx_start exit
LE_XMIT_E	equ	0ah	; xmit entry
LE_XMIT_X	equ	0bh	; xmit exit
LE_TXISR_E	equ	0ch	; txisr entry
LE_TXISR_X	equ	0dh	; txisr exit
LE_RECV_E	equ	0eh	; recv entry
LE_RECV_X	equ	0fh	; recv exit
LE_RCVFRM_E	equ	10h	; rcv_frm entry
LE_RCVFRM_X	equ	11h	; rcv_frm exit
LE_COPY_L	equ	12h	; sm_copy loop
LE_TIMER_E	equ	13h	; timer entry
LE_TIMER_X	equ	14h	; timer exit

	public	log, log_index
log		logentry 256 dup (<>) ; The log itself
log_index	db	0	; Index to current log entry

; The macro used to create log entries.
mkle	macro	letype, ledw, ledd, ledd2 ; Make an entry in the log
	pushf			; Save interrupt enable state
	cli			; Disable interrupts
	push	dx		; Save registers
	push	bx
	push	ax
	mov bl,	log_index	; Get current log_index
	xor bh,	bh		; Clear high byte
	shl bx,	1		; Multiply by sixteen
	shl bx,	1
	shl bx,	1
	shl bx,	1
	mov log[bx].le_type, letype ; Store log entry type
	loadport		; Base of device
	setport EN_CCMD	; Point at chip command register
	in al,	dx		; Get chip command state
	mov log[bx].le_ccmd, al	; Store CCMD value
	setport EN0_ISR		; Point at chip command register
	in al,	dx		; Get chip command state
	mov log[bx].le_isr, al	; Store ISR value
	setport EN0_TSR		; Point at chip command register
	in al,	dx		; Get chip command state
	mov log[bx].le_tsr, al	; Store TSR value
	mov ax,	sm_tcur		; Get current sm_tcur
	mov log[bx].le_tcur, ax	; Store sm_tcur value
	mov ax,	sm_tboundary	; Get current sm_tboundary
	mov log[bx].le_tboundary, ax ; Store sm_tboundary value
	mov ax,	sm_tnum		; Get current sm_tnum
	mov log[bx].le_tnum, ax	; Store sm_tnum value
	mov log[bx].le_dw, ledw	; Store log entry dw
ifndef	mkle8259		; Include extra per-type data
	mov word ptr log[bx].le_dd, ledd ; Store low word of log entry dd
	mov word ptr log[bx].le_dd+2, ledd2 ; Store high word of log entry dd
else				; Include 8259 status
	mov	al,0ah		; read request register from
	out	0a0h,al		; secondary 8259
	pause_
	in	al,0a0h		; get it
	mov log[bx].le_irr2, al
	mov	al,0bh		; read in-service register from
	out	0a0h,al		; secondary 8259
	pause_
	in	al,0a0h		; get it
	mov log[bx].le_isr2, al
	mov	al,0ah		; read request register from
	out	020h,al		; primary 8259
	pause_
	in	al,020h		; get it
	mov log[bx].le_irr1, al
	mov	al,0bh		; read in-service register from
	out	020h,al		; primary 8259
	pause_
	in	al,020h		; get it
	mov log[bx].le_isr1, al
endif
ifdef	screenlog		; Log the entry type to the screen too
	push	es
	mov ax,	0b800h		; Color screen only...
	mov es,	ax
	mov bl,	log_index	; Get current log_index
	xor bh,	bh		; Clear high byte
	shl bx,	1		; Multiply by sixteen
	add bx,	3360
	mov byte ptr es:[bx-1], 07h
	mov byte ptr es:[bx], letype+30h
	mov byte ptr es:[bx+1], 70h
	pop	es
endif
	inc	log_index	;
	pop	ax		; Restore registers
	pop	bx
	pop	dx
	popf			; Restore interrupt enable state
	endm

else
mkle	macro	letype, ledw, ledd, ledd2 ; Define an empty macro
	endm
endif

	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.
	mov	dh,BAD_COMMAND
	stc
	ret

	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.
xmit:
	assume	ds:nothing
	ret


; The tx_wait loop had three problems that affected high load throughput.
; Most seriously, while we are waiting for the previous SEND to finnish,
; the chip can actually be RECEIVING one or even many packets! But because
; we were waiting with interrupts disabled, these packets were not emptied
; from the receive ring and we could get an overrun. We could put in code to
; test for pending receive interrupts, but that would not help for the
; third problem, see below. Instead interrupts are now on while waiting.
; Secondly, the wait loop was not long enough to allow for up to 16 collisions.
; Thirdly, for a router there are two or more drivers and the busy waiting
; in one of them prevented interrupt handling for the other(s), giving
; unnecessary low throughput. /Jan E LDC

tx_wait:
	mov	bx,1024*7	; max coll time in Ethernet slot units
tx_wait_l1:
	mov	ah,51		; assume 1 us IO
	test	sys_features,SYS_MCA
	jz	tx_wait_l2
	shl	ah,1		; MCA IO is just 0.5 us
tx_wait_l2:
	sti			; allow receive interrupts while waiting
	loadport		; Point at chip command register
	setport EN_CCMD		; ..
	in al,	dx		; Get chip command state
	test al,ENC_TRANS	; Is transmitter still running?
	cli			; the rest of the code may not work with EI (?)
	jz	tx_idle_0	; Go if free

	dec	ah
	jnz	tx_wait_l2	; wait 51.2 us (one ethernet slot time)

⌨️ 快捷键说明

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