home *** CD-ROM | disk | FTP | other *** search
- 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
-