📄 etherdrv.inc
字号:
;==============================================================================
; @(#)ne2000.inc
;
;
;
; Module Name: ne2000.inc
; Module Desc: include file (as hwequ.inc) for board.src
; Created: Nov. 1996
;
;
; Revision: 1.0
; --------------------------------------------------------------------
; General Information:
;
;==============================================================================
;==============================================================================
; ETHERNET INITIALIZATION ROUTINE.
;==============================================================================
public IO_INIT
extrn set_isr_offs:near ;a xmasprt routine to set interrupts
; ;INITIALIZE UART
; Initialization items picked up from "hwequ.inc".
;
mon_et_addr label BYTE ; Board's ethernet address
public mon_et_addr
db ETH_ADDR0
db ETH_ADDR1
db ETH_ADDR2
db ETH_ADDR3
db ETH_ADDR4
db ETH_ADDR5
mon_ip_addr label BYTE ; Board's IP address
public mon_ip_addr
db IP_ADDR0
db IP_ADDR1
db IP_ADDR2
db IP_ADDR3
mon_udp_port dw MON_UDP_PORT ; UDP port for XRAY monitor
public mon_udp_port
eth_ioaddr dw NIC_IOADDR ; Adapter I/O base address
eth_irq db NIC_IRQ ; Adapter's IRQ
eth_cable db NIC_CABLE_T ; Ethernet cable type
public eth_ioaddr
public eth_irq
public eth_cable
%IF ((%CONIO AND %INITIO) ne 0) THEN
(
extrn init_ethernet:NEAR
extrn get_char:NEAR
extrn ether_rx_interrupt:NEAR
extrn tx_char:NEAR
extrn ether_irq_get:NEAR
extrn ether_int_enable:NEAR
IO_INIT proc near
cmp ax,0
jnz INIT_RESET ;not first init
;****************** INSTALL AND INIT ETHERNET CONTROLLER *********************
mov ether_int_active, 0
call init_ethernet ; Initialize NIC
or eax,eax
jz SHORT ether_init_ok
ret
ether_init_ok:
; if interrupt driven, set them up
%IF ((%CONIO AND %INTRPT) ne 0) THEN
(
;************************************************************************
;
; :SETUP 8259 CONTROLLER
;
; SET (NUM_8259, 2) ;set the number of 8259's 1 or 2
; MASTER_8259 EQU 020H
; SLAVE_8259 EQU 0A0H
; MASTER_8259_BASE EQU 038H ;base for interrupts from the 1st 8259
; SLAVE_8259_BASE EQU 040H ;base of interrupts for the 2nd 8259 lwr 3 bits
;must be 0
%IF (%NUM_8259 EQ 2) THEN
(
mov al, 11h ;ICW 1, bit 0 = for ICW4 used,
; bit 4 = ICW1
)
ELSE
(
mov al, 13h ;ICW 1, no slaves, bit 1= 1
; for no slaves
) FI
push esi ; ESI used below
pushfd
cli ;*********** INTS OFF *********
out MASTER_8259, al ;Write ICW 1
mov al, MASTER_8259_BASE ;ICW 2 set the base of vectors
; from this 8259
out MASTER_8259+1,al ;Write ICW 2
mov al, 04H ;ICW 3 the other 8259 is
; cascaded to this unit
out MASTER_8259+1,al ;Write ICW 3
mov al, 01h ;ICW 4 NO EOI, NO SPECIAL
; NESTED MODE
out MASTER_8259+1,al ;Write ICW 4
;OCW 1 ENABLE interrupts in
; controller
call ether_irq_get ; Get ethernet IRQ #
mov ether_int_number, eax
mov edx, eax ; IRQ in DL
mov eax, 0FFH ; Assume Ether IRQ on master
cmp edx, 07H ; Ether IRQ on SLAVE?
jbe SHORT cascade_n ; No, don't cascade
mov eax, 0FBH ; Yes, get mask with cascade
jmp SHORT master_enable_n ; and don't enable in MASTER
cascade_n:
btr eax, edx ; Enable requested IRQ
add edx, MASTER_8259_BASE ; Compute vector number
mov esi, edx ; and remember it
master_enable_n:
out MASTER_8259+1, al ;Write OCW 1 (Mask)
mov al, 20h ;OCW2 NON SPECIFIC EOI
out MASTER_8259, al ;Write OCW 2 with non sp EOI
mov al, 08H ;OCW3 Operation command word
; no action
out MASTER_8259, al; ;Write OCW 3
%IF (%NUM_8259 EQ 2) THEN
(
;initialize the second 8259
mov al, 11h ;ICW 1, this is the slave unit
out SLAVE_8259,al
mov al, SLAVE_8259_BASE ;ICW 2 set the base of vectors
; from this 8259
out SLAVE_8259+1,al
mov al, 02H ;ICW 3 the other 8259 is
; cascaded to this unit
out SLAVE_8259+1,al
mov al, 01h ;ICW 4 NO EOI, NO SPECIAL
; NESTED MODE
out SLAVE_8259+1,al
;OCW 1 ENABLE interrupts in
; controller
mov edx, ether_int_number ; IRQ in DL
mov eax, 0FFH ; Get SLAVE int mask
sub edx, 8
cmp dl, 07H ; IRQ > 15?
ja SHORT slave_enable_n ; Yes, don't enable in SLAVE
mov esi, edx ; ESI = IRQ - 8
add esi, SLAVE_8259_BASE ; Compute vector number
btr eax, edx ; Enable requested IRQ
slave_enable_n:
out SLAVE_8259+1,al ; OCW1
mov al, 20h ;OCW2 NON SPECIFIC EOI
out SLAVE_8259,al;
mov al, 08H ;OCW2 Operation command word
; no action
out SLAVE_8259,al;
) FI
; setup the IDT descriptor to point at the desired ISR
; entry point to handle an ethernet interrupt
push OFFSET RX_INT
push esi ;this is the interrupt taken
; by ethernet IRQ
call set_isr_offs ;and set the interrupt in the
; IVT table
add esp,8 ;pop the two long words
; off the esp
call ether_int_enable ; Enable NIC interrupts
popfd ;******* RESTORE INTS *********
pop esi
xor eax, eax
ret
) FI
INIT_RESET: ;reset port from aux-mon
; (interrupt, etc)
xor eax, eax
ret
IO_TERM: ;reset port to aux-mon
; (disable int, etc)
xor eax, eax
ret
IO_INIT endp
) FI ; INITIO
ether_in_int_mode proc near
public ether_in_int_mode
%IF ((%CONIO AND %INTRPT) ne 0) THEN
(
mov eax, 1
ret
)
else
(
xor eax,eax
ret
) FI
ether_in_int_mode endp
;==============================================================================
;
; Polled (OR Interrupt driven) output
;
; -> DL = character to transmit
; EAX = Control Code: 0 = Normal char, 1 = Last char
; <- EAX = RET_OK (transmitted ok)
; ER_TBF (transmit buffer full)
;
;==============================================================================
CON_OUT proc near
push ebx
push ecx
push edx
;************************ PROCESS OUTPUT CHARACTER **************************
and edx, 0FFH
and eax, 0FFH
push eax ; Pass control code
push edx ; Pass character
; push eax
; push edx
; push ecx
; mov cl, dl
;OUT_CHAR('O')
;OUT_CHAR( cl )
; pop ecx
; pop edx
; pop eax
call tx_char ; Transmit character
add esp, 2*4 ; Flush args
;*********************************** EXIT ************************************
pop edx
pop ecx
pop ebx
ret ;return to caller
con_out40:
mov ax,ER_TBF
ret
CON_OUT endp
;******************************* END CON_OUT *********************************
;==============================================================================
;
; Polled input
;
; <- DL = received character
; -> EAX = RET_OK (received ok)
; ER_NCA (no character available)
; ER_REC (receive error)
;
;==============================================================================
%IF ((%CONIO AND %POLLED) ne 0) THEN
(
;******************************* CON_IN ENTRY ********************************
CON_IN proc near
push ebx
push ecx
;******************************* CON_IN CODE *********************************
push 0 ; Make room for return char
mov eax, esp ; Set ptr to return value
; (safer than pushing ESP)
push eax ; Push char ptr
call get_char ; Get ethernet character
pop edx ; Flush pointer
pop edx ; Pickup charater
; or eax, eax
; jnz SHORT ichar_print_n
; push eax
; push edx
; push ecx
; mov cl, dl
;OUT_CHAR('I')
;OUT_CHAR( cl )
; pop ecx
; pop edx
; pop eax
;ichar_print_n:
;******************************* CON_IN EXIT *********************************
pop ecx
pop ebx
ret
CON_IN endp
) FI
;==============================================================================
;
; Interrupt input
;
;==============================================================================
%IF ((%CONIO AND %INTRPT) ne 0) THEN
(
public RX_INT
RX_INT proc near ; Receive interrupt
cli ;******** INTS OFF ************
pushad ; Save all data registers
mov ether_int_active, 1 ; Remember INT active
;************************ GET CHARACTER(S) FROM NIC **************************
call ether_rx_interrupt ; Execute NIC interrupt
;*************************** CHARECTER INPUT LOOP ****************************
rx_loop: push 0 ; Make room in local stack
mov eax, esp ; Create character pointer
push eax ; Pass pointer of char buff
call get_char ; Get character from rx packet
pop edx ; Flush pointer
pop edx ; Get charater from stack
cmp eax, ER_NCA ; Buffer empty?
je SHORT rx_int_done ; Yes, quit
; EDX = input character
; EAX = receive code
or eax, eax
jnz SHORT intchar_print_n
push eax
push edx
push ecx
mov cl, dl
;OUT_CHAR('X')
;OUT_CHAR( cl )
pop ecx
pop edx
pop eax
intchar_print_n:
call NEAR PTR mo_start + MORXCHR ;Send char to monitor
cmp eax, ER_HLT ;should we stop?
jne SHORT rx_loop ;no, check for next char
;************************* MONITOR TELLS US TO STOP **************************
; if have interrupt controller would do an EOI here
;*************************** SEND EOI TO 8259(S) *****************************
mov al,20h ;OCW2 output a non specific
; EOI
cmp ether_int_number, 8
jb SHORT rx_i1_slave_n
out SLAVE_8259, al
rx_i1_slave_n:
out MASTER_8259,al
mov ether_int_active, 0 ; Exiting INT
popad
jmp mo_start + MOHALT ; Enter monitor HALT state
;**************************** RX_INT NORMAL EXIT *****************************
rx_int_done:
;*************************** SEND EOI TO 8259(S) *****************************
mov al,20h ;OCW2 output a non specific
; EOI
cmp ether_int_number, 8
jb SHORT rx_i2_slave_n
out SLAVE_8259, al
rx_i2_slave_n:
out MASTER_8259,al
mov ether_int_active, 0 ; Exiting INT
popad ; Restore all data registers
iretd ; Return from interrupt
RX_INT endp
)
ELSE
(
RX_INT proc near
public RX_INT
push eax
mov al,20h ;OCW2 output a non specific
; EOI
out MASTER_8259, al
pop eax
iretd ; Return from interrupt
RX_INT endp
) FI
;*****************************************************************************
;
; int in_ether_interrupt( void )
;
;*****************************************************************************
public in_ether_interrupt
in_ether_interrupt proc NEAR
mov eax, ether_int_active
ret
in_ether_interrupt endp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -