home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Serving the Web
/
ServingTheWeb1995.disc1of1.iso
/
connect
/
tcpip
/
crynwr
/
pktd11a
/
exos205.asm
< prev
next >
Wrap
Assembly Source File
|
1993-11-13
|
13KB
|
495 lines
version equ 1
include defs.asm
; a driver for the EXOS 205 Ethernet controller by Dirk Koeppen (dirk@incom.de)
; 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.
public int_no
public driver_class, driver_type, driver_name, driver_function
public parameter_list
public usage_msg
public copyright_msg
public parse_args
public print_parameters
; inform 82586.asm that we have a larger amount of memory
SEG586 equ 0fh
; equates for controlling EXOS 205 i/o ports
P_INTR EQU 0 ; interrupt EXOS 205
P_CTRL1 EQU 2 ; control port 1
P1_186 EQU 00000001b ; enable 80186
P1_586 EQU 00000010b ; enable 82586
P1_A12 EQU 00000100b ; address bit 12 of EXOS memory
P1_NET EQU 00001000b ; enable net (disable loopback)
P1_A13 EQU 00010000b ; address bit 13 of EXOS memory
P1_CA EQU 00100000b ; do a channel attention by host
P1_A14 EQU 01000000b ; address bit 14 of EXOS memory
P1_A15 EQU 10000000b ; address bit 15 of EXOS memory
P_CTRL2 EQU 3 ; control port 2
P2_A16 EQU 00000001b ; address bit 16 of EXOS memory
P2_SHM EQU 01111110b ; EXOS shared memory address on host
P2_ACC EQU 10000000b ; enable access to EXOS memory
P_ACK EQU 4 ; acknowledge interrupt
; here are some equates to syncronise the i186 and the host via a semaphore
S_INST EQU 0aah ; a fancy value to flag installed code
S_EXEC EQU 0a5h ; .. code is executing
S_FAILED EQU 05ah ; .. i186 has failed to execute code
S_STOP EQU 055h ; .. code was successfully executed
code segment word public
assume cs:code, ds:code
int_no db 2, 0, 0, 0 ; interrupt number
io_addr dw 310h, 0 ; I/O address for card
base_addr dw 0cc00h, 0 ; base segment for board
ex_eaddr db 6 dup (0) ; boards Ethernet address
ex_ctrl1 db 0 ; copy of control port 1
ex_ctrl2 db 0 ; .. port2
driver_class db BLUEBOOK, IEEE8023, 0 ; from the packet spec
driver_type db 13 ; from the packet spec
driver_name db "EXOS205", 0 ; name of the driver
driver_function db 2
parameter_list label byte
db 1 ; major rev of packet driver
db 9 ; minor rev of packet driver
db 14 ; length of parameter list
db EADDR_LEN ; length of MAC-layer address
dw GIANT ; MTU, including MAC headers
dw MAX_MULTICAST * EADDR_LEN ; buffer size of multicast addrs
dw 0 ; (# of back-to-back MTU rcvs) - 1
dw 0 ; (# of successive xmits) - 1
int_num dw 0 ; interrupt # to hook for post-EOI
; processing, 0 == none
usage_msg db "usage: exos205 [options] <packet_int_no> [int_no] [io_addr] [base_addr]",CR,LF,'$'
copyright_msg db "Packet driver for the EXOS 205, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,".",'0'+i82586_version,CR,LF
db "Portions Copyright 1988 The Board of Trustees of the University of Illinois.",CR,LF
db "Portions Copyright 1992 Dirk Koeppen (dirk@incom.de).",CR,LF,'$'
no_exos205 db "Unable to initialize the EXOS 205 adapter.",CR,LF,'$'
int_no_name db "Interrupt number ",'$'
io_addr_name db "I/O port ",'$'
base_addr_name db "Shared memory address ",'$'
; ENABLE_NETWORK - switch on the transceiver
enable_network:
ret ; is on all the time
; RESET_586 - reset the network controller
reset_586:
push ds ; could be called from different segment
push ax
mov ax, cs
mov ds, ax
loadport
setport P_CTRL1 ; load the i/o control register
mov al, ex_ctrl1
or al, P1_CA ; set CA
and al, NOT P1_586 ; disable i82586
out dx, al ; trigger the port
jmp $+2 ; let the signal dry
or al, NOT P1_586 ; enable i82586
out dx, al
mov ex_ctrl1, al ; save a copy
pop ax
pop ds
ret
; DOCA - do a channel attention
doca:
push ds ; could be called from different segment
push ax
mov ax, cs
mov ds, ax
loadport
setport P_CTRL1 ; load the i/o control register
mov al, ex_ctrl1
and al, NOT P1_CA ; clear CA
or al, P1_586 ; enable i82586 if not already enabled
out dx, al ; trigger the port
jmp $+2 ; let the signal dry
jmp $+2
or al, P1_CA ; set CA
out dx, al
mov ex_ctrl1, al ; save a copy
setport P_ACK ; acknowledge intr (placed here because
out dx, ax ; .. recv_isr calls doca each time)
pop ax
pop ds
ret
; EX_INIT - initialize the EXOS205
ex_init:
loadport ; base of device
mov ex_ctrl1, P1_NET+P1_A12+P1_A13+P1_A14+P1_A15 ; highest mem page
mov ax, base_addr ; where the shared memory should get to
shr ah, 1 ; shift it to the right place
and ah, P2_SHM ; zero all other bits
or ah, P2_A16 ; set address bit 16
mov ex_ctrl2, ah
setport P_CTRL1 ; set the EXOS memory address
mov al, ex_ctrl1
out dx, al
setport P_CTRL2
mov al, ex_ctrl2
out dx, al
jmp $+2 ; let it dry
jmp $+2
or ex_ctrl2, P2_ACC ; enable the memory
mov al, ex_ctrl2
out dx, al
init_i186:
push es ; save 'C' register type loop-counters
push si
push di
push ds
mov es, base_addr ; ES:DI -> EXOS205 memory (end of last 16K page)
mov di, 03fffh
mov ax, cs ; DS:SI -> code to be downloaded (end of code)
mov ds, ax
mov si, offset i186_end
mov cx, (offset i186_end-offset i186_code) ; amount to be downloaded
inc cx ; one more because loops end at 0
std ; copy backwards
rep movsb ; copy the code
cld
pop ds ; restore original DS
mov di, 03fffh ; where the semaphore is located
sub di, (offset i186_end-offset i186_sema)
mov al, es:[di] ; get semaphore
cmp al, S_INST ; check if code is installed
jne init_failed ; failed to init board
setport P_CTRL1
mov al, ex_ctrl1 ; release the i186, let it execute the code
or al, P1_186
mov ex_ctrl1, al ; .. and let it run forever
out dx, al
mov ax, (36*2) ; give it 2 seconds to start execution
call set_timeout
init_loop1:
mov al, es:[di] ; get semaphore
cmp al, S_EXEC ; does it execute ?
je init_i186exec
call do_timeout ; loop until timeout
jne init_loop1
jmp init_failed ; failed to init board
init_i186exec:
mov ax, (36*5) ; give it 5 seconds to initialize
call set_timeout
init_loop2:
mov al, es:[di] ; get semaphore
cmp al, S_STOP ; did it stop ?
je init_i186stop
call do_timeout ; loop until timeout
jne init_loop2
jmp init_failed ; failed to init board
init_i186stop:
xor ax, ax ; flag that everything worked all right
push ax
mov di, 03fffh ; where the Ethernet address is located
sub di, (offset i186_end-offset i186_addr)
mov bx, offset ex_eaddr
mov cx, 6 ; 6 bytes to move
init_acpy:
mov al, es:[di] ; copy address
mov ds:[bx], al
inc di ; next byte
inc bx
loop init_acpy ; loop for all byte
init_end:
pop ax
setport P_ACK ; acknowledge intr to reset hardware logic
out dx, ax
pop di ; restore saved registers
pop si
pop es
or ax, ax ; setup zero flag
ret
init_failed:
setport P_CTRL1 ; stop the i186
mov al, ex_ctrl1
and al, NOT P1_186 ; .. forever
mov ex_ctrl1, al
out dx, al
mov ax, -1 ; failed to init board
push ax
jmp init_end
; I186_CODE - this code is downloaded to the EXOS205 to be executed by the i186
i186_code:
i186_addr:
db 08h, 00h, 14h ; unique EXOS Ethernet address (byte 5-3)
db 0, 0, 0 ; .. byte 2-0 of the boards Ethernet address
i186_sema:
db S_INST ; semaphore will be S_STOP if code was executed
i186_ipl: ; i186 bootstrap
cli ; disable interrupts
xor ax, ax ; zero relocation register
mov dx, 0fffeh
out dx, ax
mov ax, 0fff8h ; setup UMCS register
out 0a0h, ax
mov ax, 0007ch ; .. PACS register
out 0a4h, ax
mov ax, 080bch ; .. MPCS register
out 0a8h, ax
mov ax, cs ; DS -> CS
mov ds, ax
; flag code execution
mov bx, 00fffh - (offset i186_end-offset i186_sema)
mov byte ptr ds:[bx], S_EXEC
xor cx, cx
i186_wait: ; spend some time to let host read the semaphore
jmp $+2
jmp $+2
jmp $+2
loop i186_wait
; where to write the boards Ethernet addr to (starts 3 bytes after code)
mov si, 00fffh - (offset i186_end-offset i186_addr) + 3
mov dx, 0502h ; low order nibble of byte 2 Ethernet address
xor bx, bx ; zero checksum
mov cx, 3 ; 3 bytes of Ethernet address are to be read
i186_acpy:
in al, dx ; read one nibble
and al, 00001111b ; .. mask valid bits (just to get shure !)
mov ah, al ; .. store it
add bl, al ; .. add to checksum
inc dx ; go to high order nibble
inc dx
in al, dx ; .. read it
add bl, al ; .. add to checksum
shl al, 1 ; .. shift it to be high order nibble
shl al, 1
shl al, 1
shl al, 1
or al, ah ; pack those two nibbles into one byte
mov ds:[si], al ; .. and store the byte
inc dx ; go to next nibble of Ethernet address
inc dx
inc si
loop i186_acpy ; loop until all 3 bytes are read
mov ah, bl ; add bottom to top nibble
shr ah, 1 ; top nibble
shr ah, 1
shr ah, 1
shr ah, 1
and bl, 00001111b ; bottom nibble
add ah, bl ; add them
xor ah, 5 ; is x-ored by 5 to avoid 0x00 or 0xff problem
in al, dx ; DX -> checksum
cmp ah, al
je i186_ok
mov byte ptr ds:[si], S_FAILED; flag that checksum failed
jmp $ ; stop execution (i186 will be stopped by host)
i186_ok:
mov byte ptr ds:[si], S_STOP ; flag that we have stopped execution
xor ax, ax ; set the interrupt vector
mov ds, ax ; .. i82586 is connected to INT2
mov si, 4*14 ; INT2 has vector type 14
mov word ptr ds:[si], 00fffh - (offset i186_end-offset i186_intr)
inc si
inc si
mov word ptr ds:[si], 0ff00h
sti ; enable interrupts
mov dx, 3ch ; INT2 control register
mov ax, 3 ; level triggered, unmasked and prio 3
out dx, ax
xor bx, bx ; zero counters
xor cx, cx
mov bp, 00fffh - (offset i186_end-offset i186_lcnt)
i186_loop: ; endless loop to keep i186 doing something
nop
nop
nop
nop
loop i186_loop
inc bx ; count
mov cs:[bp], bx ; .. and store for debugging
jmp i186_loop ; cycle endless while waiting for interrupts
i186_intr: ; interrupt routine called by 82586 intr
push dx
mov dx, 00600h ; interrupt host first
out dx, ax
push ax
push bx
push bp
mov bp, 00fffh - (offset i186_end-offset i186_icnt)
mov bx, cs:[bp]
inc bx ; increment interrupt counter
mov cs:[bp], bx ; .. and store for debugging
mov dx, 22h ; acknowledge interrupt
mov ax, 8000h
out dx, ax
pop bp
pop bx
pop ax
pop dx
iret
db 'INTR cnt->' ; some debugging variables
i186_icnt:
dw 0 ; counts 82586 interrupts
db 'LOOP cnt->'
i186_lcnt:
dw 0 ; loops to flag execution
i586_reset_vector:
db 0eah dup (0) ; reserved for the i82586 reset vector
i186_reset_vector:
db 0eah ; opcode 'jmp far'
dw 00fffh - (offset i186_end-offset i186_ipl)
dw 0ff00h
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fill patterns
i186_end:
db 0 ; one more fill pattern
; here we include the code that is common between 82586 implementations.
; everything above this is resident.
include 82586.asm
; everything below this is discarded upon installation.
; CHECK_BOARD - check if there really is a EXOS 205 installed
check_board:
mov SCP, 0 ; 16 bit bus type in scb.
call ex_init ; setup the board
je check_ok
mov dx, offset no_exos205 ; failed to init board
jmp error
check_ok:
xor ax, ax ; have a return value
ret
; PARSE_ARGS - read the command line option and overwrite defaults
parse_args:
mov di, offset int_no
call get_number
mov di, offset io_addr
call get_number
mov di, offset base_addr
call get_number
clc
ret
; PRINT_PARAMETERS - print out the boards configuration parameters
print_parameters:
mov di, offset int_no
mov dx, offset int_no_name
call print_number
mov di, offset io_addr
mov dx, offset io_addr_name
call print_number
mov ax, memory_begin
mov cl, 4
shr ax, cl
add base_addr, ax
push ax
mov di, offset base_addr
mov dx, offset base_addr_name
call print_number
pop ax
sub base_addr, ax
ret
; GET_ADDRESS - get boards Ethernet address
; enter with es:di -> place to get the address,
; cx = size of address buffer.
; exit with nc, cx = actual size of address,
; or cy if buffer not big enough.
get_address:
assume ds: code
mov bx, offset ex_eaddr ; where to copy is located
get_address_1:
mov al, ds:[bx] ; copy a byte of the address
stosb ; put it away
inc bx ; next address byte
loop get_address_1 ; go back for rest
ret
include memtest.asm
code ends
end