home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
cpm86
/
c86xfj.a86
< prev
next >
Wrap
Text File
|
2011-08-09
|
15KB
|
607 lines
; * * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * *
; [30e] Add support for Fujitsu Micro 16s
; Chris Barker, 01/04/85
; [30d] Add SET PORT command, currently unimplemented.
; [30c] Isolate all machine dependencies in KERIO.
; [30a] Add keyboard DEL key alteration for APC
; RonB, 04/18/84
; * * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * *
; [28e] Switch to local stack on interrupts.
; RonB, 03/28/84
; * * * * * * * * * * * * * * * version 2.4 * * * * * * * * * * * * * * *
; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
; RonB,03/02/84
; [19a] Add XON/XOFF type flow control
; [19b] Clear screen and beginning and end of program.
; [19e] Add PRTBRK to send break to port (Rainbow only)
; [19g] Put in EQU for clock rate for timing loops.
; Rg, 2/84 <Oc.Garland%CU20B@Columbia-20>
; * * * * * * * * * * * * * * * version 2.3 * * * * * * * * * * * * * * *
; [par] Added calls to set parity, strip parity on input if
; other than none parity is called for.
; JD, 2/84
; * * * * * * * * * * * * * * * version 2.2 * * * * * * * * * * * * * * *
; [2] Add a de-initialization routine for the serial port, to restore
; changed interrupt vectors, etc.
; RonB,12/23/83
; [1] Add I/O support for the NEC Advanced Personal Computer
; RonB,12/23/83
; * * * * * * * * * * * * * * * version 2.0 * * * * * * * * * * * * * * *
; This module contains all the low level communications port I/O
; routines.
; Here are the I/O routines for the Fujitsu Micro 16s
CSEG $
; Clock rate *10 for timing loops ;[19g]
clckrt equ 80 ;[19g] 8.0 Mhz ;[30e]
; Interrupt vector locations, in data segment 0
mnioff equ 30h ;sio interrupt offset
mniseg equ 32h ;sio interrupt segment
; 8259 Interrupt controller (master)
iccmd equ 00h ;interrupt command register
icmask equ 02h ;interrupt mask register
; 8259 commands and masks
icEOI equ 20h ;end of interrupt (command)
;ictmof equ 08h ;disable timer (mask)
icmnof equ 04h ;disable RS232 (mask)
; Baud Rate controller (MB 14417)
bdport equ 0FD59h ;baud rate select (read/write)
; 8251A USART controller
mndata equ 0FD06h ; data port
mnsts1 equ 0FD07h ;in status port
mncmd equ 0FD07h ;out command port
; 8251 status port 1 bits
mninp equ 02h ;receive ready value
mnout equ 01h ;send ready value
mndsr equ 80h ;data set ready
; 8251 initialization instructions
; command instructions
ctxe equ 01h ;transmit enable
cdtr equ 02h ;dtr signal high
crxe equ 04h ;receive enable
cbrk equ 08h ;send break
cerr equ 10h ;error reset
crts equ 20h ;rts signal high
cmode equ 40h ;reset - go to mode instruction format
chunt equ 80h ;hunt for sync characters
; mode instructions
m1x equ 01h ;baud rate factor: 1x
m16x equ 02h ; 16x
m64x equ 03h ; 64x
m5d equ 00h ;data bits: 5
m6d equ 04h ; 6
m7d equ 08h ; 7
m8d equ 0Ch ; 8
mpn equ 00h ;parity: none
mpo equ 10h ; odd
mpe equ 30h ; even
m1s equ 40h ;stop bits: 1
m15s equ 80h ; 1.5
m2s equ 0C0h ; 2
outlmt equ 1000h ;Number of times to check output status
; before giving up on send. ;[20d]
; Test if port is ready to send next char. Returns RSKP if ready.
; Trashes dx.
outwt: cmp floctl, floxon ;are we doing flow-control? [19a] start
jne outwta ;no - go on
cmp xofrcv, true ;are we being held?
jne outwta ;no - ok go on
ret ;held - say we're busy. [19a] end
outwta: push ax
mov dx,mnsts1
in al,dx
and al,mndsr+mnout
sub al,mndsr+mnout
jz outwt2
outwt1: pop ax
ret
outwt2: pop ax
jmp rskp
; Output data to port. Trashes DX and prints char in AL.
outchr: mov dx,mndata
out dx,al
ret
; Output the character in AL, checking first to make sure the port is clear.
prtout: call dopar ;[par] set parity
push dx
push cx ;[20d] begin
mov cx,outlmt
prtou2: call outwt ;Wait until the port is ready
loop prtou2 ; or too much time has passed.
nop
call outchr ;Output it.
pop cx ;[20d] end
pop dx
ret
; Test if data is available from port.
instat: cmp mnchrn,0 ;Any chars in the buffer?
jnz inst2
ret
inst2: jmp rskp
; Input data from port. Preserves all registers and returns char in
; AL. Gets the char from the ring buffer. Assumes a char is
; already there.
inchr: push bx
cli ;Disable interrupts while were are playing.
dec mnchrn ;Decrement the number of chars in the buffer.
mov bx,mnchop ;Get the pointer into the buffer.
inc bx ;Increment to the next char.
cmp bx,offset mnchrs+mnchnd ;Past the end?
jb inchr2
lea bx,mnchrs ;If so wrap around to the start.
inchr2: mov mnchop,bx ;Save the updated pointer.
mov al,[bx] ;Get the character.
sti ;All done, we can restore interrupts.
pop bx
cmp parflg,parnon ;[par] no parity?
je inchr3 ;[par] yup, don't bother stripping
and al,7fh ;[par] checking parity, strip off
inchr3: cmp floctl, floxon ;do flow-control? [19a] start
je inchr4 ;If yes jump
ret
inchr4: cmp xofsnt, true ;Have we sent an XOFF
je inchr5 ;Jump if yes
ret
inchr5: cmp mnchrn, mntrg1 ;Under the low trigger point?
jb inchr6 ;yes - jump
ret
inchr6: push ax ;save current character
mov al, xon
call prtout ;send an XON
mov xofsnt, false ;turn off the flag
pop ax ;get back character
ret ; [19a] end
mnax dw 0 ;Storage in CSEG ;[28e] begin
mnsp dw 0 ; for use by interrupt handler
mnsseg dw 0
mndseg dw 0
; This routine handles the interrupts on input.
mnint: cli
mov cs:mnax, ax ;Save interrupt stack location.
mov ax, sp
mov cs:mnsp, ax
mov ax, ss
mov cs:mnsseg, ax
mov ax, cs:mndseg ;Switch to our internal stack.
mov ss, ax
lea sp, mnstk
push ds ;Save all registers.
push es
push bp
push di
push si
push dx
push cx
push bx
mov ds, ax ;Get our data segment address.
call mnproc ;Process the character.
mov dx, iccmd
mov al, icEOI ;signal end of interrupt to 8259A
out dx, al
pop bx ;Restore all registers.
pop cx
pop dx
pop si
pop di
pop bp
pop es
pop ds
mov ax, cs:mnsp ;Restore the original stack.
mov sp, ax
mov ax, cs:mnsseg
mov ss, ax
mov ax, cs:mnax
iret ;Return from the interrupt. ;[28e] end
; This routine (called by MNINT) gets a char from the serial port
; and puts it in the ring buffer.
mnproc: mov dx,mnsts1
in al,dx ;Get the port status.
and al,mninp ;Is a character waiting?
jnz mnpro2 ; Yes, go take care of it.
ret ; No, just a false alarm.
mnpro2: mov dx,mndata
in al,dx ;Read the char.
cmp floctl, floxon ;are we doing flow-control ? [19a] start
jne mnpr2b ;no - go on
cmp al, xoff ;is it an XOFF?
jne mnpr2a ;no - go on
mov xofrcv, true ;set the flag
ret
mnpr2a: cmp al, xon ;an XON?
jne mnpr2b ;no
mov xofrcv, false ;clear the flag
ret ; [19a] end
mnpr2b: cmp mnchrn,mnchnd ;Is the buffer full?
je mnperr ;If so, take care of the error.
inc mnchrn ;Increment the character count.
mov bx,mnchip ;Get the buffer input pointer.
inc bx ;Increment it.
cmp bx,offset mnchrs+mnchnd ;Past the end?
jb mnpro3
lea bx,mnchrs ;Yes, point to the start again.
mnpro3: mov mnchip,bx ;Save the pointer.
mov [bx],al ;Put the character in the buffer.
cmp floctl, floxon ;do flow-control? [19a] start
je mnpro4 ;If yes jump
ret
mnpro4: cmp xofsnt, true ;Have we sent an XOFF
jnz mnpro5
ret ;return if we have
mnpro5: cmp mnchrn, mntrg2 ;Past the High trigger point?
ja mnpro6 ;yes - jump
ret
mnpro6: mov al, xoff
call prtout ;send an XOFF
mov xofsnt, true ;set the flag
ret ; [19a] End
mnperr: ret ;Just return on an error for now.
; prtbrk - send a break ; [20b] start
prtbrk:
mov dx,mncmd ;break goes to command port
mov al,cbrk+crts+cerr+crxe+cdtr+ctxe ;add break to normal command
out dx,al
mov cx, 25000 ;sit for a while
prtbk1: loop prtbk1
mov al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
out dx,al ;return to normal setting
ret ; [20b] end
; serini - This routine initializes all devices that need it.
; Called at the start of the program.
serini: cmp mninit,0FFh ; must only do this initialization once
je serin2
mov mninit,0FFh
push es
mov dx,icmask
in al,dx ;get current interrupt mask
mov mnxmsk,al ;save it for restore
; or al,ictmof+icmnof;mask off timer and sio interrupts
or al,icmnof ;mask off sio interrupt
out dx,al
mov ax,ds ;save data segment in cseg
mov cs:mndseg,ax ; for use by the interrupt handler
mov ax,0 ;point to zero page to replace
mov es,ax ;the sio interrupt vector
mov ax,es:.mniseg ;after first saving the current vector
mov mnxseg,ax
mov ax,es:.mnioff
mov mnxoff,ax
cli
mov ax,cs
mov es:.mniseg,ax
mov ax,offset mnint
mov es:.mnioff,ax
sti
; call stmode ;set mode & baud to defaults
call stbaud
mov dx,mndata ;dummy read to clear buffer
in al,dx
mov dx,icmask
in al,dx ;enable sio interrupts
and al,not icmnof
out dx,al
pop es
serin2: ret
; serfin - this routine is used to "undo" what serini has done, called
; just before exiting back to cp/m.
serfin:
call clrscr ;[19b] clear screen ;[30c]
cmp mninit,0FFh ;check if initialization has been done
jne serfn2 ;if not, don't de-initialize
mov mninit,0
push es
cli
mov dx,icmask
mov al,mnxmsk ;restore the old interrupt mask
out dx,al
mov ax,0
mov es,ax
mov ax,mnxseg ;restore sio interrupt vector
mov es:.mniseg,ax
mov ax,mnxoff
mov es:.mnioff,ax
sti
pop es
serfn2: ret
; This routine clears the serial port input buffer. It is called to
; clear out excess NAKs that can result from server mode operation.
cfibf: mov mnchrn, 0 ;Say no characters in the buffer.
mov mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
mov mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
ret
; set the parity, number of data bits, and number of stop bits
stmode: ;do this all in stbaud for micro16s
; set the baud rate
stbaud: mov al,mnbaud ;get the baud rate information
cmp al,6 ;check for valid range (0-6)
ja stb03 ;j/ out of valid range
mov bx,offset baudtb;get address of baud rate table
mov ah,0
add bx,ax
mov dx,bdport
mov al,[bx] ;get value
out dx,al ;output byte
mov al,m64x
jne stb02 ;
mov al,m16x ;for 19200 bd
stb02: push ax
mov dx,mncmd
mov al,0 ;recommended reset procedure:
out dx,al ;three 0's followed by a cmode
mov al,0
out dx,al
mov al,0
out dx,al
mov al,cmode ;enable mode setting
out dx,al
pop ax
add al,m1s ;1 stop, no parity, 8 data, 16x baud
add al,mpn ;Note: these adds are distinct to
add al,m8d ; allow the 8251 time to reset
out dx,al
mov al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
out dx,al
stb03: ret
dseg $
; Serial port default parameters
mnbaud db 5 ;9600 baud
; Interval Timer values (assumes 64x baud rate mode)
baudtb db 00h ;300 baud 0
db 11h ;600 baud 1
db 22h ;1200 baud 2
db 33h ;2400 baud 3
db 44h ;4800 baud 4
db 55h ;9600 baud 5
db 44h ;19200 baud 6 - requires 16x rate mode
mninit db 0 ;set to 0FFh if initialization has been done
mnxmsk db 0 ;8259 interrupt mask storage
mnxseg dw 0 ;system sio interrupt vector
mnxoff dw 0
mnchnd equ 512 ;Size of circular buffer.
mnchrs rb mnchnd ;Circular character buffer for input.
mnchip dw mnchrs-1+mnchnd ;Input pointer into character buffer.
mnchop dw mnchrs-1+mnchnd ;Output pointer into character buffer.
mnchrn dw 0 ;Number of chars in the buffer.
mntrg1 equ 128 ;[19a] Low trigger point for Auto XON/XOFF
mntrg2 equ 384 ;[19a] High trigger point for Auto XON/XOFF
floctl db 1 ;[19a] If floctl=floxon do Auto XON/XOFF logic
xofsnt db 0 ;[19a] set if XOFF was sent
xofrcv db 0 ;[19a] set if XOFF was recieved
rw 32 ;Interrupt stack ;[28e]
mnstk dw 0 ;bottom of stack ;[28e]
CSEG $
; The following routines do the SET and SHOW for the machine dependent
; features of Kermit. At present there are only two: baud rate setting
; and port selection.
; This is the SET BAUD rate subcommand
bdset: lea dx, bdtab
lea bx, bdhlp
mov ah, cmkey
call comnd
jmp r
mov temp1, bx
mov ah, cmcfm
call comnd ;Get a confirm.
jmp r ; Didn't get a confirm.
mov bx, temp1
mov mnbaud, bl ;Set the baud rate table index.
call stbaud
jmp rskp
; This is the SET PORT subcommand (not implemented in APC)
prtset: mov ah, cmcfm
call comnd ;Get a confirm.
jmp $+3 ; Didn't get a confirm.
lea dx, infms6 ;Tell user it's not implemented
call tcrmsg
jmp rskp
; The following procedures implement the SHOW command for the system
; dependent features of baud rate and port selection.
shobd: lea dx, bdst ;Baud rate string.
call tcrmsg
mov al, mnbaud ;Print the keyword corresponding to the
lea bx, bdtab ; current value of mnbaud.
call tabprt
ret
shoprt: ret ;Port selection not implemented.
DSEG $
bdtab db 7 ;Thirteen entries ;[6] begin
db 4,'1200$'
dw 0002h
db 5,'19200$'
dw 0006h
db 4,'2400$'
dw 0003h
db 3,'300$'
dw 0000h
db 4,'4800$'
dw 0004h
db 3,'600$'
dw 0001h
db 4,'9600$'
dw 0006h ;[6] end
bdhlp db cr,lf,' 300 600 1200 2400'
db cr,lf,' 4800 9600 19200$'
; The following routines do screen control. These are isolated here because
; the screen control sequences are likely to vary from system to system, even
; though the Rainbow and APC (the only systems implemented to date) both use
; ANSI sequences for this purpose.
CSEG $
; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
poscur: mov bx, dx ;Do ANSI cursor positioning.
mov ax, [bx] ;
add ax, ' ' ;Add 20h to both row and column
mov word ptr anspos+2, ax
lea dx, anspos ;Print cursor positioning string.
call tmsg
ret
; CLRSCR - homes cursor and clears screen.
clrscr: lea dx, fujcls
call tmsg
ret
; CLRLIN - clears from cursor to end of line.
clrlin: mov dl, cr ;Go to beginning of line
call bout
clreol: lea dx, ansclr ;Clear from cursor to end of line
call tmsg
ret
; REVON - turns on reverse video display
revon: lea dx, ansron
call tmsg
ret
; REVOFF - turns off reverse video display
revoff: lea dx, ansrof
call tmsg
ret
; BLDON - turns on bold (highlighted) display
bldon: lea dx, ansbon ;
call tmsg ;
ret
; BLDOFF - turns off bold (highlighted) display
bldoff: lea dx, ansbof ;
call tmsg ;
ret
DSEG $
anspos db esc,'=00$' ;Position cursor to row and column
fujcls db 1Eh,1Ah,'$' ;Home cursor and clear screen
ansclr db esc,'T$' ;Clear from cursor to end of line
ansron db esc,'G',0Ch,'$' ;Turn on reverse video (green)
ansrof db esc,'G',04h,'$' ;Turn off reverse video (green)
ansbon db esc,'G',05h,'$' ;Turn on bold (uses blue)
ansbof db esc,'G',04h,'$' ;Turn off bold (back to green)
; Here tab expansion is done if necessary. If not, just return retskp.
cseg $
dotab: jmp rskp ;No, just proceed.
dseg $
curbuf db 2,0,0 ;command, row, column of cursor position
delstr db 10O, 10O, '$' ;Delete string.
system db ' FUJITSU Micro 16s $' ;[1][20a]