Category : Network Files
Archive   : PKTD11A.ZIP
Filename : AR450.ASM

 
Output of file : AR450.ASM contained in archive : PKTD11A.ZIP
;History:508,1
version equ 0

include defs.asm

; Copyright, 1991-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.

arlan_segment segment at 0

org 000h
ar_signature db ?

org 030h
ar_reset db ?

org 031h
ar_diagnostics db ?

org 040h
ar_node_id db EADDR_LEN dup(?) ;6 byte node address field.

org 046h
ar_node_bcast db EADDR_LEN dup(?) ;6 byte broadcast address.

org 04ch
ar_type db ? ;1 byte hardware type
ar_type_A450 equ 00h
ar_type_A650 equ 01h
ar_type_A670 equ 0bh
ar_type_A670E equ 0ch
ar_type_A650E equ 0dh
ar_type_A440LT equ 0eh

org 04dh
ar_version label word ;Version number.
ar_version_maj db ?
ar_version_min db ?

org 080h
ar_interrupt db ? ;not used by LANCPU

org 081h
ar_control_i db ? ;image of the control register.

org 090h
ar_command db ?

COM_CONF equ 1
COM_RX_ENABLE equ 3
COM_RX_ABORT equ 4
COM_TX_ENABLE equ 5
COM_TX_ABORT equ 6
COM_NOP equ 7
COM_INT equ 80h

org 0a0h
ar_rx_status db ?

org 0a2h
ar_rx_offset dw ? ;start of received datagram

org 0a4h
ar_rx_length dw ? ;length of received datagram

org 0a6h
ar_rx_src db EADDR_LEN dup(?) ;RX source address.

org 0ach
ar_rx_bcast db ? ;<>0 if received frame was bcast.

org 0adh
ar_rx_quality db ? ;indicates quality of received packet.

org 0b0h
ar_tx_status db ?

org 0b1h
ar_tx_quality db ?

org 100h
ar_sys_params label byte

org 108h
ar_irq_level db ? ;IRQ level

org 109h
ar_spreading db 3 dup(?) ;Spread spectrum code ID.

org 10ch
ar_NID dw ? ;Radio address of LAN card.

org 11dh
ar_tx_atten db ? ;attenuation of radio transmitter in db.

org 11eh
ar_system_id dd ? ;system ID.

org 128h
ar_MDS dw ? ;Maximum Datagram Size.

org 12ah
ar_MFS dw ? ;Maximum Frame Size.

org 12ch
ar_max_retry db ?

org 162h
ar_register db ? ;indicates if card must register w/ router.

org 164h
ar_poll_rate dw ? ;<>0 if power saving is used.

org 166h
ar_refresh_rate dw ? ;tens of msecs between registration
;refreshes.
org 168h
ar_name db 16 dup(?)

org 400h
ar_tx_buffer label byte

org 0c00h
ar_rx_buffer label byte

org 1fffh
ar_control db ?
CONTROL_RESET equ 1
CONTROL_CA equ 2
CONTROL_IE equ 4
CONTROL_CLRI equ 8


arlan_segment ends

code segment word public
assume cs:code, ds:code

public int_no
int_no db 0,0,0,0 ;must be four bytes long for get_number.

base_addr dw ? ;The base address of the board.

xmit_bdcast db ?

public driver_class, driver_type, driver_name, driver_function, parameter_list
driver_class db BLUEBOOK,0 ;from the packet spec
driver_type db 99 ;from the packet spec
driver_name db 'ARLAN 450',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,

public rcv_modes
rcv_modes dw 4 ;number of receive modes in our table.
dw 0,0,0,rcv_mode_3

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


include popf.asm
include timeout.asm
include movemem.asm

public send_pkt
send_pkt:
;enter with es:di->upcall routine, (0:0) if no upcall is desired.
; (only if the high-performance bit is set in driver_function)
;enter with ds:si -> packet, cx = packet length.
;if we're a high-performance driver, es:di -> upcall.
;exit with nc if ok, or else cy if error, dh set to error number.
assume ds:nothing

mov es,base_addr
assume es:arlan_segment

cmp cx,ar_MDS ;Is this packet too large?
mov dh,NO_SPACE
ja send_pkt_toobig ;yes, don't bother sending it.

if 0
mov bx,2 ;count the number of times around...
wait_again:
mov ax,10 ;don't wait too long...
call set_timeout
wait_for_xmit:
sti
cmp ar_tx_status,0 ;is the transmit done?
jne xmit_done ;yes, exit now.
call do_timeout
jne wait_for_xmit ;no, wait for it to finish.
cli

inc ar_interrupt ;note that we had to crap out.

mov ar_command,COM_TX_ABORT
call doca
mov ar_tx_status,1
else
sti
wait_for_xmit:
cmp ar_tx_status,0 ;is the transmit done?
jne xmit_done ;yes, exit now.
jmp wait_for_xmit ;no, wait for it to finish.
endif
clc ;pretend we actually sent it.
ret
send_pkt_toobig:
stc
ret
xmit_done:
cli

mov di,offset ar_command + 5

mov xmit_bdcast,0

;check to see if it's an Ethernet broadcast (all ones).
push ds
push si
push cx
mov cx,EADDR_LEN
send_pkt_1:
lodsb
cmp al,0ffh
loope send_pkt_1
jne send_pkt_2 ;not Ethernet broadcast.

inc xmit_bdcast ;remember that it was a broadcast.

mov si,offset ar_node_bcast ;use our broadcast address.
mov ds,base_addr

movsw ;move the broadcast address over.
movsw
movsw

pop cx
pop si
pop ds

add si,EADDR_LEN ;skip the addresses.
jmp short send_pkt_3
send_pkt_2:
pop cx
pop si
pop ds

movsw ;move the destination address over.
movsw
movsw

send_pkt_3:
add si,EADDR_LEN ;skip the addresses.
sub cx,EADDR_LEN+EADDR_LEN ;. .

mov di,offset ar_tx_buffer
mov al,xmit_bdcast
stosb
push cx
call movemem
pop cx

inc cx ;include the broadcast byte.

mov ar_command,COM_TX_ENABLE
mov word ptr ar_command[1],offset ar_tx_buffer
mov word ptr ar_command[3],cx

mov ar_tx_status,0 ;let the board fill it in.

call doca

clc
ret


public set_address
set_address:
;enter with ds:si -> Ethernet address, CX = length of address.
;exit with nc if okay, or cy, dh=error if any errors.
assume ds:nothing
ret


rcv_mode_3:
;receive mode 3 is the only one we support, so we don't have to do anything.
ret


public set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
; cx = number of bytes.
;return nc if we set all of them, or cy,dh=error if we didn't.
mov dh,NO_MULTICAST
stc
ret


public terminate
terminate:
clc
ret

public reset_interface
reset_interface:
;reset the interface.
assume ds:code
ret


;called when we want to determine what to do with a received packet.
;enter with cx = packet length, es:di -> packet type, dl = packet class.
extrn recv_find: near

;called after we have copied the packet into the buffer.
;enter with ds:si ->the packet, cx = length of the packet.
extrn recv_copy: near

;call this routine to schedule a subroutine that gets run after the
;recv_isr. This is done by stuffing routine's address in place
;of the recv_isr iret's address. This routine should push the flags when it
;is entered, and should jump to recv_exiting_exit to leave.
;enter with ax = address of routine to run.
extrn schedule_exiting: near

;recv_exiting jumps here to exit, after pushing the flags.
extrn recv_exiting_exit: near

extrn count_in_err: near
extrn count_out_err: near

public recv
recv:
;called from the recv isr. All registers have been saved, and ds=cs.
;Upon exit, the interrupt will be acknowledged.
assume ds:code, es:arlan_segment
mov es,base_addr

;clear the interrupt request.

mov al,ar_control_i ;drop the clear interrupt bit.
and al,not CONTROL_CLRI
mov ar_control,al
or al,CONTROL_CLRI ;raise the clear interrupt bit.
mov ar_control,al

cmp ar_rx_status,0 ;was this our receive interrupt?
jne recv_recv
cmp ar_tx_status,0 ;was this our transmit interrupt?
jne recv_xmit
jmp recv_exit
recv_xmit:
jmp recv_exit

recv_recv:
mov di,ar_rx_offset ;get a pointer to the packet.
mov cx,ar_rx_length ;get the length.
dec cx ;omit the "was broadcast" flag.
inc di ;. .
add cx,EADDR_LEN+EADDR_LEN ;add the two headers in.
push es
push di
push cx
mov dl, BLUEBOOK ;assume bluebook Ethernet.
call recv_find
pop cx
pop si
pop ds
assume ds:arlan_segment, es:nothing

mov ax,es ;is this pointer null?
or ax,di
je recv_free ;yes - just free the frame.

push es
push di
push cx
sub cx,EADDR_LEN+EADDR_LEN
mov al,ds:[si-1] ;get the "was broadcast" flag.
cmp al,0 ;was it a broadcast?
je recv_us ;no.
mov ax,0ffffh ;yes, stuff an Ethernet broadcast in.
stosw
stosw
stosw
jmp short recv_source
recv_us:
mov si,offset ar_node_id
movsw
movsw
movsw
recv_source:
mov si,offset ar_rx_src ;move the source address over.
movsw
movsw
movsw
mov si,ar_rx_offset ;get a pointer to the packet.
inc si
rep movsb
pop cx
pop si
pop ds
assume ds:nothing

call recv_copy

recv_free:

movseg ds,cs
assume ds:code
mov es,base_addr
assume es:arlan_segment

enable_receive:

mov ar_rx_status,0 ;clear the current status.
mov ar_command,COM_RX_ENABLE+COM_INT
mov ar_command+1,1 ;receive broadcasts.
call doca

cmp ar_rx_status,0 ;is there another packet?
jne recv_recv ;yes, receive it now.

recv_exit:
ret


doca:
;toggle the CA bit in the control register.
;must be executed with interrupts off to protect ar_control_i.
;return cy if we had a horrible failure.
assume es:arlan_segment
pushf ;make up a fake iret stack frame.
cli
mov al,ar_control_i ;toggle the bit in the image
xor al,CONTROL_CA
mov ar_control_i,al ;and store them both.
mov ar_control,al
popf

mov ax,5 ;wait about 1/7th of a second.
call set_timeout
doca_2:
cmp ar_command,0 ;wait for the command to finish.
je doca_1 ;it did.
call do_timeout
jne doca_2
stc
ret
doca_1:
clc
ret


public timer_isr
timer_isr:
;if the first instruction is an iret, then the timer is not hooked
iret

;any code after this will not be kept after initialization. Buffers
;used by the program, if any, are allocated from the memory between
;end_resident and end_free_mem.
public end_resident,end_free_mem
end_resident label byte
end_free_mem label byte


public usage_msg
usage_msg db "usage: ar450 [options] ",CR,LF,'$'

public copyright_msg
copyright_msg db "Packet driver for an ARLAN 450, version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
db "Portions Copyright 1990, Russell Nelson",CR,LF,'$'

extrn set_recv_isr: near

;enter with si -> argument string, di -> wword to store.
;if there is no number, don't change the number.
extrn get_number: near

;enter with dx -> argument string, di -> wword to print.
extrn print_number: near

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

public parse_args
parse_args:
;exit with nc if all went well, cy otherwise.
clc
ret


signature db "TELESYSTEM"
signature_len equ $-signature

no_board_msg db "Cannot locate an ARLAN board.",'$'
self_test_msg db "ARLAN board self-tests bad.",'$'
bad_mem_msg db "The on-card memory tests as bad.",'$'
file_not_found db "File not found",'$'
read_trouble db "Trouble reading the file",'$'
timeout_msg_xx db "x"
timeout_msg_x db "x"
timeout_msg db "Timed out waiting for the board",'$'
configure_bad db "The configure attempt failed",'$'

arlan_cfg db "arlan.cfg",0
handle dw ?

int_no_name db "Interrupt number ",'$'

public etopen
etopen:
assume ds:code, es:arlan_segment

;look for the arlan card in memory
mov dx,0c000h
etopen_1:
mov si,offset signature
mov es,dx
mov di,offset ar_signature
mov cx,signature_len
repe cmpsb
je etopen_2

add dx,200h
cmp dx,0de00h
jb etopen_1
mov dx,offset no_board_msg
stc
ret
etopen_2:
mov base_addr,dx

mov ar_control,1 ;reset the board.

mov ax,base_addr ;test the memory.
mov cx,2000h-3
call memory_test
je memory_ok
mov dx,offset bad_mem_msg
stc
ret
memory_ok:

xor di,di ;zero all the memory.
mov cx,2000h-1
xor al,al
rep stosb

mov ar_reset,1 ;set the reset flag.
mov ar_control,0 ;remove the reset.

mov ax,36
call set_timeout
wait_for_reset:
cmp ar_reset,0 ;did it finish resetting yet?
je wait_for_reset_1 ;yes, exit.
call do_timeout
jne wait_for_reset
mov dx,offset timeout_msg
stc
ret
wait_for_reset_1:

;set the reset flag again, so that we can detect if we somehow got reset.

mov ar_reset,1

cmp ar_diagnostics,0ffh ;Did it self-check okay?
je self_test_ok
mov dx,offset self_test_msg
stc
ret
self_test_ok:

mov ar_command,COM_NOP ;do a NOP.
call doca
jnc wait_for_first_nop_1
mov dx,offset self_test_msg
stc
ret
wait_for_first_nop_1:

;;; They say to do another with with COM_INT set...

mov al,ar_irq_level ;copy the interrupt number out of
mov int_no,al ; the configuration file.

mov ax,3d00h ;open for reading.
mov dx,offset arlan_cfg
int 21h
jnc file_found
mov dx,offset file_not_found
stc
ret

file_found:
mov handle,ax

mov ax,4200h
mov bx,handle
xor cx,cx
mov dx,100h ;skip past the first 100h bytes.
int 21h

mov ah,3fh ;read the system parameters.
mov bx,handle
mov cx,100h
mov dx,offset ar_sys_params
push ds
mov ds,base_addr
int 21h
pop ds
jnc no_trouble
mov dx,offset read_trouble
stc
ret

no_trouble:

mov ah,3eh ;close the file.
mov bx,handle
int 21h

cmp int_no,0 ;Does the board know its interrupt
jne set_int_no ; number? go if it does.
mov al,ar_irq_level ;No, so use the one
mov int_no,al ; in the configuration file.
set_int_no:

; do the configure.

mov ar_command,COM_CONF
call doca
jnc wait_for_configure_1 ;it did.
mov dx,offset timeout_msg_x
stc
ret
wait_for_configure_1:

cmp ar_diagnostics,0ffh ;did the configure succeed?
je configure_ok
mov dx,offset configure_bad
stc
ret
configure_ok:


;wait a short while for the AR450. For the AR440, wait up to 15 seconds.

mov ax,36
call set_timeout
wait_for_address:
mov cx,EADDR_LEN ;see if our address is still zeroes.
mov si,offset ar_node_id
xor al,al
wait_for_address_2:
or al,es:[si]
inc si
loop wait_for_address_2
or al,al ;do we have an address yet?
jne wait_for_address_1 ;yes.
call do_timeout
jne wait_for_address
mov dx,offset timeout_msg_xx
stc
ret
wait_for_address_1:

;say that the max we'll send is an Ethernet GIANT packet, less the two
; Ethernet addresses that we don't include in the datagram, plus the one
; broadcast byte that we *do* include.

mov ax,GIANT - EADDR_LEN*2 + 1
mov ax,1023
mov ar_MDS,ax
mov ar_MFS,ax

; reduce the number of retries

mov ar_max_retry,16

;enable reception

call enable_receive

;mark transmission as done

mov ar_tx_status,1

;enable our interrupts.

mov al,ar_control_i
or al,CONTROL_IE or CONTROL_CLRI
mov ar_control_i,al
mov ar_control,al


;get our address

movseg es,cs
mov di,offset rom_address
mov cx,EADDR_LEN ; Move one ethernet address from our copy
mov si,offset ar_node_id ; Copy from the board.
push ds
mov ds,base_addr
rep movsb
pop ds

; Now hook in our interrupt

call set_recv_isr

sti

mov al, int_no ; Get board's interrupt vector
add al, 8
cmp al, 8+8 ; Is it a slave 8259 interrupt?
jb set_int_num ; No.
add al, 70h - 8 - 8 ; Map it to the real interrupt.
set_int_num:
xor ah, ah ; Clear high byte
mov int_num, ax ; Set parameter_list int num.

clc
ret


public print_parameters
print_parameters:
;echo our command-line parameters
mov dx,offset int_no_name
mov di,offset int_no
call print_number

ret

include memtest.asm

code ends

end


  3 Responses to “Category : Network Files
Archive   : PKTD11A.ZIP
Filename : AR450.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/