home *** CD-ROM | disk | FTP | other *** search
- ;History:152,1
- ;Sun Jan 05 22:13:40 1992 increased RST_IVAL to 7.
- ;Tue Feb 27 10:56:15 1990 send_pkt wasn't timing out properly.
- version equ 0
-
- include defs.asm
-
- ;Ported from Philip Prindeville's arcnet driver for PCIP
- ;by Russell Nelson. Any bugs are due to Russell Nelson.
-
- ; Copyright, 1988-1992, Russell Nelson
-
- ; 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.
-
- code segment word public
- assume cs:code, ds:code
-
-
- ;Registers:
-
- ;the following I/O addresses are mapped to the COM 9026
- IMASK equ 0 ; writeable
- STATUS equ 0 ; readable
- COMMAND equ 1
- ;the following I/O addresses are mapped to the 8253 counter/timer
- CNTR0 equ 4
- CNTR1 equ 5
- CNTR2 equ 6
- MODE equ 7
- ;reading the following I/O addresse performs a software reset.
- SW_RST equ 8
-
- ; time needed to do various things (in clock ticks)
- RST_IVAL equ 7 ;reset
- SEND_IVAL equ 4 ;send
-
- ; ARP type for ARCnet
- ARP_ARC equ 007h
-
- ; broadcast address is nid 0
- ARC_BCAST equ 0
-
- ; packet sizes
- ARC_MTU equ 253
- ARC_MnTU equ 257
- ARC_XMTU equ 508
- ;
- ;status/interrupt mask bit fields
- ;
- ST_TA equ 001h ; transmitter available
- ST_TMA equ 002h ; transmitted msg. ackd
- ST_RECON equ 004h ; system reconfigured
- ST_TEST equ 008h ; test flag
- ST_POR equ 010h ; power-on-reset
- ST_ETS1 equ 020h ; unused
- ST_ETS2 equ 040h ; unused
- ST_RI equ 080h ; receiver inhibited
-
- ;
- ;in the command register, the following bits have these meanings:
- ; 0-2 command
- ; 3-4 page number (enable rvc/xmt)
- ; 7 rcv b'casts
-
-
- DSBL_XMT equ 001h ; disable transmitter
- DSBL_RCV equ 002h ; disable receiver
- ENBL_XMT equ 003h ; enable transmitter
- ENBL_RCV equ 004h ; enable receiver
- DFN_CONF equ 005h ; define configuration
- CLR_FLGS equ 006h ; clear flags
- LD_TST_FLG equ 007h ; load test flags
-
- ; flags for clear flags operation
-
- FL_POR equ 008h ; power-on-reset
- FL_RECON equ 010h ; system reconfigured
-
- ; flags for load test flags operation
-
- FL_TST equ 008h ; test flag (diagnostic)
-
- ; byte deposited into first address of buffers when POR
- TSTWRD equ 0321Q
-
- ; handy macros for enable receiver/transmitter
-
- BCAST equ 080h ; receiver only
- ;PAGE equ(nn) ((nn)<<3)
-
- ; flags for define configuration
-
- CONF_NORM equ 000h ; 1-253 byte packets
- CONF_XTND equ 008h ; 256-508 byte packets
-
- ; macros to access buffers
- ;BUF equ(page) (((custom.c_basemem) + 512 * (page)))
-
- ; ARCnet pseudo header -- note that syscode must occupy last byte...
-
- arc_hdr struc
- arc_sid db ? ; source, valid on rcv
- arc_did db ? ; destination, 0 = b'cast
- arc_cp db ? ; continuation pointer. zero
- ; for extended packets
- arc_xcp db ? ; extended cp, see above
- arc_syscode db ? ; system code/pkt type
- arc_hdr ends
-
- ; designations for receiver/transmitter buffers. sorry, no cleverness here
- RCVPAGE equ 2
- XMTPAGE equ 3
-
- public int_no
- int_no db 5,0,0,0 ; interrupt number.
- io_addr dw 02e0h,0 ; I/O address for card (jumpers)
- mem_base dw 0d800h,0
-
- public driver_class, driver_type, driver_name, driver_function, parameter_list
- driver_class db 8,0 ;ARCnet (from the packet spec)
- driver_type db 1 ;Datapoint RIM (from the packet spec)
- driver_name db 'ARCnet',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 1 ;length of MAC-layer address
- dw 507 ;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
-
- include popf.asm
- include movemem.asm
-
- 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
-
-
- 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.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
-
- ;Wait for transmitter ready.
- loadport
- setport STATUS
-
- mov ax,SEND_IVAL ;only wait this long for it.
- call set_timeout ; otherwise we can't send.
- send_pkt_3:
- in al,dx ;if not busy, exit.
- and al,ST_TA
- jne send_pkt_2
- call do_timeout ;did we time out yet?
- jne send_pkt_3 ;no, not yet.
-
- setport COMMAND ;stop the transmit.
- mov al,DSBL_XMT
- out dx,al
- mov dh,CANT_SEND ;timed out, can't send.
- stc
- ret
-
- send_pkt_toobig:
- mov dh,NO_SPACE
- stc
- ret
-
- send_pkt_2:
- ;store the packet on the board.
- mov es,mem_base
- mov di,XMTPAGE * 512
- movsw ;move the SID and DID to the board.
- sub cx,2 ;leave them out of the count.
-
- cmp cx,ARC_XMTU ;is this one too big?
- ja send_pkt_toobig ;yes, can't store it.
- cmp cx,ARC_MTU ;is this one small enough
- jbe send_pkt_1 ;yes, just move it in.
- cmp cx,ARC_MnTU ;is it *too* large AND *too* small?
- jae send_pkt_5 ;no.
- mov cx,ARC_MnTU ;yes - use the larger size.
- send_pkt_5:
- xor al,al ;use a zero cp to indicate xcp.
- mov ah,cl ;store the length in xcp.
- neg ah
- stosw
- jmp short send_pkt_4
- send_pkt_1:
- mov al,cl ;store the length in cp.
- neg al
- stosb
- send_pkt_4:
- mov ax,di ;continue the put.
- mov al,cl ; advance the cp to its proper place.
- neg al
- mov di,ax
- call movemem
-
- ;start the transmit.
- mov al,ENBL_XMT or (XMTPAGE shl 3)
- loadport
- setport COMMAND
- out dx,al
-
- clc
- ret
-
- ;Set address on controller
- public set_address
- set_address:
- assume ds:nothing
- ;enter with ds:si -> address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- mov dh,CANT_SET
- stc
- 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:
- assume ds:code
- loadport
- setport IMASK
- mov al,0
- out dx,al
-
- setport COMMAND
- mov al,DSBL_RCV
- out dx,al
- mov al,DSBL_XMT
- out dx,al
-
- setport STATUS ;do we need to do this [rnn]?
- in al,dx
-
- ret
-
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- ;we don't do anything.
- ret
-
-
- include timeout.asm
-
- ;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
-
- recv_1:
- loadport ;get the status to see if we got
- setport STATUS ; a false alarm.
- in al,dx
- test al,ST_RI
- je recv_2 ;yup, exit now.
-
- mov es,mem_base
- mov bx,RCVPAGE * 512
-
- ;decode data size.
-
- mov cx,256 ;compute the actual length.
- mov al,es:[bx].arc_cp
- or al,al ;is this a normal or continuation pkt?
- jne recv_3 ;go if normal.
- mov cx,512 ;extended packets have 512 max.
- mov al,es:[bx].arc_xcp
- recv_3:
- xor ah,ah
- sub cx,ax
- add cx,2 ;add in SID and DID.
- mov bl,al ;use al as the low byte of the address.
- mov di,bx
- mov dl,driver_class
- call recv_find ;look up our type.
-
- mov ax,es ;is this pointer null?
- or ax,di
- je recv_isr_9 ;yes - just free the frame.
-
- push es ;remember where the buffer pointer is.
- push di
-
- mov ds,mem_base ;copy the packet into their buffer.
- assume ds:nothing
- mov si,RCVPAGE * 512 ; (don't worry about ds.
- movsw ;move SID and DID.
- mov ax,si
- lodsb ;get arc_cp.
- or al,al ;extended?
- jne recv_5 ;no.
- lodsb ;yes - get arc_xcp.
- recv_5:
- mov si,ax ;set the new pointer.
- push cx ;move the data part of the packet.
- sub cx,2 ;don't move the two we've already
- call movemem ; moved.
- pop cx
-
- pop si
- pop ds
- assume ds:nothing
- call recv_copy ;tell them that we copied it.
-
- mov ax,cs ;restore our ds.
- mov ds,ax
- assume ds:code
-
- recv_isr_9:
-
- loadport ;enable reception again.
- setport COMMAND
- mov al,ENBL_RCV or (RCVPAGE shl 3) or BCAST
- out dx,al
-
- jmp recv_1
- recv_2:
- 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. 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: arcnet [options] <packet_int_no> <hardware_irq> <io_addr> <mem_base>",CR,LF,'$'
-
- public copyright_msg
- copyright_msg db "Packet driver for the DataPoint RIM (ARCnet), version ",'0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
- db "Portions Copyright 1988 Philip Prindeville",CR,LF,'$'
-
- no_arcnet_msg db "No ARCnet found at that address.",CR,LF,'$'
- failed_test_msg db "Failed self test.",CR,LF,'$'
-
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- mem_base_name db "Memory address ",'$'
-
- extrn set_recv_isr: near
-
- ;enter with si -> argument string, di -> word to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with dx -> name of word, di -> dword to print.
- extrn print_number: near
-
- ;=length of our address.
- extrn address_len: word
-
- ;-> the assigned address of the card.
- extrn rom_address: byte
-
- public parse_args
- parse_args:
- ;exit with nc if all went well, cy otherwise.
- mov di,offset int_no
- call get_number
- mov di,offset io_addr
- call get_number
- mov di,offset mem_base
- call get_number
- clc
- ret
-
-
- no_arcnet_error:
- mov dx,offset no_arcnet_msg
- stc
- ret
- failed_test_error:
- mov dx,offset failed_test_msg
- stc
- ret
-
-
- public etopen
- etopen:
- ;reset the board via the I/O reset port, then wait for it to become sane again.
-
- mov ax,mem_base ;test the memory first.
- mov cx,2048
- call memory_test
- jne no_arcnet_error
-
- mov es,mem_base
-
- loadport
- setport SW_RST
- in al,dx
-
- mov ax,RST_IVAL
- call set_timeout
- etopen_1:
- call do_timeout
- jne etopen_1
-
- setport STATUS
- in al,dx
-
- ;since we've just reset:
- ; reset the POR flag,
- ; check the diagnostic byte in the buffer,
- ; grab the node ID, and assign it to the host number.
-
- test al,ST_POR
- je etopen_2
-
- setport COMMAND
- mov al,CLR_FLGS or FL_POR or FL_RECON
- out dx,al
-
- mov al,es:[0]
- cmp byte ptr es:[0],TSTWRD
- je etopen_3
- jmp failed_test_error ;failed power on self-test.
- etopen_3:
- mov al,es:[1]
- mov rom_address,al
- mov address_len,ARCADDR_LEN
- etopen_2:
-
- ;another simple diagnostic:
- ; force test flag on in RIM,
- ; check to see that it is set,
- ; reset it.
-
- loadport
- setport COMMAND
- mov al,LD_TST_FLG or FL_TST
- out dx,al
-
- setport STATUS
- in al,dx
-
- test al,FL_TST
- jne etopen_4
- jmp failed_test_error ;failed forced self-test.
- etopen_4:
- setport COMMAND
- mov al,LD_TST_FLG
- out dx,al
- setport STATUS
- in al,dx
-
- pushf
- cli
-
- call set_recv_isr
-
- ;now we enable the board to interrupt
- ;us on packet received. Not transmiter available
- ;(i.e. transmission complete). We don't have
- ;any control over POR, since it is NMI...
- ;RECON seems useless.
-
- loadport
- setport IMASK
- mov al,ST_RI
- out dx,al
-
- ; we should allow extended packets
- setport COMMAND
- mov al,DFN_CONF or CONF_XTND
- out dx,al
-
- mov al,ENBL_RCV or (RCVPAGE shl 3) or BCAST;
- out dx,al
-
- popf
-
- 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:
- 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 di,offset mem_base
- mov dx,offset mem_base_name
- call print_number
- ret
-
- include memtest.asm
-
- code ends
-
- end
-