mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 09:54:20 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
;************************************************
|
||||
;* Common equates for the serial system *
|
||||
;* File name: CHRCOMM.EQU *
|
||||
;* Last Update: 10/10/83 *
|
||||
;************************************************
|
||||
|
||||
cr equ 0dh ;carriage return
|
||||
lf equ 0ah ;line feed
|
||||
esc equ 01bh ;escape
|
||||
|
||||
; These equates are for the control characters
|
||||
|
||||
ctrlc equ 003h
|
||||
ctrld equ 004h
|
||||
ctrlq equ 011h
|
||||
ctrls equ 013h
|
||||
|
||||
XOFF EQU CTRLS
|
||||
XON EQU CTRLQ
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
|
||||
title 'Software Console Input Handler'
|
||||
|
||||
;*******************************************
|
||||
; *
|
||||
; CONIN MODULE *
|
||||
; Last changed : 2/11/84 *
|
||||
; *
|
||||
;*******************************************
|
||||
|
||||
include flags.equ
|
||||
include serdata.equ
|
||||
include chrcomm.equ
|
||||
include system.lib
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
extrn icdesctbl:word
|
||||
extrn vccb_tbl:word
|
||||
|
||||
cseg
|
||||
|
||||
public io_conin
|
||||
public io_const
|
||||
public conin_0 ; default routine for Q ctl structure's C_STATE
|
||||
|
||||
extrn supif:near ; in header module
|
||||
extrn serial_in:near ; in serin.a86
|
||||
extrn set_up_bx:near
|
||||
|
||||
;========
|
||||
io_conin:
|
||||
;========
|
||||
;
|
||||
; ENTRY: dl = physical console number
|
||||
; EXIT: al = character
|
||||
; ah = 000H if al contains a character
|
||||
; 0ffH if al contains a virtual console number
|
||||
|
||||
call io_const ; bx -> Q control structure.
|
||||
call C_STATE[bx] ; C_STATE = address of next routine in state
|
||||
; machine. Default is conin0 (see below).
|
||||
ret
|
||||
|
||||
|
||||
;========
|
||||
io_const:
|
||||
;========
|
||||
;
|
||||
; ENTRY: dl = physical console number
|
||||
; EXIT: al = 0FFH if a character is available
|
||||
; = 000H if NO character is available
|
||||
; bx -> Recv Queue control structure
|
||||
|
||||
|
||||
xor dh,dh ; clear the upper byte
|
||||
cst1:
|
||||
shl dx, 1 ; word table
|
||||
mov bx, dx
|
||||
mov bx, icdesctbl[bx] ; bx -> Receive Q control
|
||||
cst2:
|
||||
pushf ! cli ; Check for chars in buffer
|
||||
xor al,al
|
||||
test Q_STATE[bx], CHAR_AVAIL
|
||||
jz cst3 ; char not available
|
||||
dec al ; character ready signal
|
||||
cst3:
|
||||
popf
|
||||
ret
|
||||
|
||||
|
||||
conin_0:
|
||||
;------
|
||||
; ENTRY: bx = addr of the Q control block
|
||||
; EXIT: ah = 0 if characters are being returned.
|
||||
; ah = 0FFH if this is a screen switch code being returned
|
||||
|
||||
|
||||
push bx ; save the Q control addr
|
||||
call serial_in ; get the character
|
||||
pop bx ; restore the Q control addr
|
||||
cmp al, ESC
|
||||
je esc_now
|
||||
mov ah, 0 ; set ah as a character code
|
||||
ret
|
||||
esc_now: ; delay for 16 ms, check for another character
|
||||
push bx ; save the Q control addr
|
||||
mov dx, DELAY_16MS ; delay for 16 ms
|
||||
mov cl, P_DELAY
|
||||
call supif
|
||||
pop bx ; restore the Q control addr
|
||||
test Q_STATE[bx], CHAR_AVAIL
|
||||
jnz esc_seq
|
||||
; it must be a lone escape character
|
||||
mov al, ESC ; al = the return character ( ESC )
|
||||
mov ah, 0 ; ah = character being returned code
|
||||
ret
|
||||
esc_seq:
|
||||
push bx ; save the Q ctl addr
|
||||
call serial_in ; get the next char
|
||||
pop bx ; restore the Q ctl addr
|
||||
cmp al, '?'
|
||||
je exit_st ; ignore alt keypad
|
||||
cmp al, 'S'
|
||||
jb exit_st ; check for screen switch
|
||||
cmp al, 'V'
|
||||
ja exit_st ; ignore out-of-range function keys
|
||||
|
||||
; this is a screen switch command
|
||||
sub al, 'S' ; normalize the screen number to 0
|
||||
mov ah, 0FFH ; set the screen switch return code
|
||||
mov dh, P_CON[bx] ; Check if we're in the middle of an
|
||||
mov dl, dh ; escape sequence.
|
||||
push bx ; If so, don't allow screen switch key to
|
||||
call set_up_bx ; return to PIN until sequence is finished.
|
||||
cmp OESC_CNT[bx],0
|
||||
pop bx
|
||||
je exit_st
|
||||
|
||||
or Q_STATE[bx], SWITCH_PEND
|
||||
xor dh,dh
|
||||
add dl, SWITCH_BIAS
|
||||
mov cl, f_flagwait
|
||||
push ax
|
||||
call supif
|
||||
pop ax
|
||||
|
||||
exit_st:
|
||||
ret
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
title ' Console Output Entry Module'
|
||||
|
||||
;*******************************************
|
||||
; *
|
||||
; CONOUT MODULE *
|
||||
; Last changed : 2/11/84 *
|
||||
; *
|
||||
;*******************************************
|
||||
|
||||
include chrcomm.equ
|
||||
include serdata.equ
|
||||
include vscreen.equ
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
extrn ocdesctbl:word
|
||||
extrn vccb_tbl:word ; in vs_screen.a86
|
||||
extrn oq0desc:byte
|
||||
extrn stoppoll:word ; in headentr.a86
|
||||
|
||||
cseg
|
||||
|
||||
public io_conout
|
||||
public pmsg
|
||||
public conout1
|
||||
|
||||
extrn serial_out:near ; in serout.a86
|
||||
extrn supif:near ; in headentr.a86
|
||||
extrn vs_conout:near ; in vs_screen.a86
|
||||
|
||||
;====
|
||||
pmsg:
|
||||
;====
|
||||
; print message on current console until 0ffh
|
||||
; input: BX = address of message
|
||||
|
||||
push stoppoll
|
||||
mov stoppoll,0ffffh
|
||||
mov dl, 0 ; signon to console 0
|
||||
ploop:
|
||||
mov cl,[bx] ; get next char
|
||||
cmp cl,0ffh
|
||||
je pmsg_ret ; return if 0ffh
|
||||
; CL = character
|
||||
push dx ;save device number
|
||||
push bx ;save string ptr
|
||||
call io_conout ;display it
|
||||
pop bx ;regain <BX>
|
||||
pop dx ;console
|
||||
inc bx ;bump to next char
|
||||
jmps ploop ;loop till done
|
||||
pmsg_ret:
|
||||
pop stoppoll
|
||||
ret ; end of message
|
||||
|
||||
|
||||
;=========
|
||||
io_conout: ; Function 2: Console Output
|
||||
;=========
|
||||
;
|
||||
; input: CL = character
|
||||
; DL = virtual console number
|
||||
;
|
||||
; output: None
|
||||
;
|
||||
|
||||
xor dh,dh
|
||||
jmp vs_conout ; for virtual screen buffering
|
||||
; omit this jump to disable buffering
|
||||
conout1:
|
||||
push dx ; save the Virtual con
|
||||
mov bx, dx
|
||||
shl bx, 1
|
||||
mov bx, vccb_tbl[bx] ; bx -> VCCB
|
||||
mov bl, vccb_pcon[bx] ; get the Physical console #
|
||||
xor bh, bh
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ; bx -> Xmit Q control structure
|
||||
|
||||
pop dx ; get the Vcon back
|
||||
cmp dl, CUR_VCON[bx]
|
||||
je co1 ; if background and dynamic,
|
||||
ret ; bit bucket the char
|
||||
co1:
|
||||
cmp cl, ESC ; Check for an escape character.
|
||||
jne co2 ; Worst case (VT-52) is 4 char's.
|
||||
mov OESC_CNT[bx], 4 ; init escape count
|
||||
co2:
|
||||
call serial_out
|
||||
ret
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
;
|
||||
;
|
||||
; THIS SUBMIT FILE WILL BUILD AN XIOS.CON MODULE
|
||||
; FOR THE SAMPLE CONCURRENT CP/M 3.1 COMPUPRO XIOS.
|
||||
; 2/17/84
|
||||
;
|
||||
;
|
||||
rasm86 headentr $lo
|
||||
;
|
||||
rasm86 ctc $lo
|
||||
rasm86 pic $lo
|
||||
rasm86 intvec $lo
|
||||
rasm86 np_8087 $lo
|
||||
rasm86 tick $lo
|
||||
;
|
||||
rasm86 conin $lo
|
||||
rasm86 serin $lo
|
||||
rasm86 conout $lo
|
||||
rasm86 serout $lo
|
||||
rasm86 servar $lo
|
||||
;
|
||||
rasm86 i3int $lo
|
||||
rasm86 ssint $lo
|
||||
;
|
||||
rasm86 vscreen $lo
|
||||
rasm86 switch $lo
|
||||
;
|
||||
rasm86 pcmode $lo
|
||||
rasm86 statlin $lo
|
||||
rasm86 list $lo
|
||||
;
|
||||
rasm86 vccb $lo
|
||||
rasm86 serdata $lo
|
||||
;
|
||||
rasm86 dentry $lo
|
||||
rasm86 fd $lo
|
||||
rasm86 hdisk $lo
|
||||
rasm86 reskew $lo
|
||||
rasm86 mdisk $lo
|
||||
rasm86 dpbs $lo
|
||||
;
|
||||
era *.lst
|
||||
;
|
||||
; LINK86 LOOKS FOR AN INPUT FILE "XIOS.INP"
|
||||
; (SEE HEADENTR.A86)
|
||||
;
|
||||
link86 xios[i
|
||||
;
|
||||
ren xios.con=xios.cmd
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
title 'Intel 8253 CTC module'
|
||||
|
||||
;************************************************
|
||||
; *
|
||||
; COUNTER TIMER CHIP MODULE *
|
||||
; Last changed : 12/15/83 *
|
||||
; *
|
||||
;************************************************
|
||||
|
||||
include system.lib
|
||||
|
||||
LATENCY equ false ; if the CTC is programmed for modes
|
||||
; 2 or 3 then set this to true.
|
||||
|
||||
|
||||
; COUNTER TIMER EQUATES
|
||||
|
||||
TIMER0_CTL_WORD EQU 30H ; timer 0, two byte rl, mode 0
|
||||
TIMER0_LB EQU 3CH
|
||||
TIMER0_HB EQU 82H
|
||||
|
||||
TIMER0_LATCH EQU 0
|
||||
TIMER0_RESET_COUNT EQU 823CH
|
||||
|
||||
;
|
||||
; these are the compupro CTC PORT ADDRESSES
|
||||
|
||||
CTC_PORT_BASE equ 50H
|
||||
|
||||
CTC_CTL_PORT equ ctc_port_base + 7
|
||||
Timer_0 equ ctc_port_base + 4
|
||||
|
||||
cseg
|
||||
|
||||
public ctc_init
|
||||
public reset_tick_ctc ; called by the tick module
|
||||
public int_latency ; called by the tick module
|
||||
|
||||
|
||||
;
|
||||
; now set up the timer for 16.67 milliseconds
|
||||
; timer 0, two byte rl, mode 0
|
||||
|
||||
;========
|
||||
ctc_init:
|
||||
;==============
|
||||
reset_tick_ctc:
|
||||
;==============
|
||||
;
|
||||
; At this time the CTC is only used to generate the real time tick
|
||||
; for CCP/M. Therefore initing and reseting the tick do the same thing.
|
||||
;
|
||||
|
||||
mov al, TIMER0_CTL_WORD ; select timer 0 mode 0
|
||||
out CTC_CTL_PORT, al ; two byte count
|
||||
|
||||
mov al,TIMER0_LB ; load the LSB
|
||||
out timer_0, al
|
||||
|
||||
mov al, TIMER0_HB ; load the MSB
|
||||
out timer_0, al
|
||||
|
||||
; at this point the CTC starts counting
|
||||
|
||||
ret
|
||||
|
||||
;===========
|
||||
int_latency:
|
||||
;===========
|
||||
; Interrupt latency measurement entry point.
|
||||
;
|
||||
; ENTRY: from the tick interrupt service routine
|
||||
;
|
||||
; EXIT: max_latency is updated if the current latency is
|
||||
; greater than any previous latency since cold boot.
|
||||
;
|
||||
; NOTE: all registers are preserved, two levels ( 4 bytes )
|
||||
; of stack are used.
|
||||
|
||||
|
||||
if not LATENCY
|
||||
|
||||
ret
|
||||
|
||||
endif
|
||||
|
||||
if LATENCY
|
||||
|
||||
push ax ; save the CPU environment we're
|
||||
push dx ; going to use
|
||||
|
||||
mov al, TIMER0_LATCH ; latch the timer's count
|
||||
out CTC_CTL_PORT, al
|
||||
|
||||
in al, TIMER_0 ; get the timers lsb
|
||||
mov ah, al ; store it
|
||||
in al, TIMER_0 ; get the timers msb
|
||||
|
||||
xchg ah, al ; arrange the CTC's latched count
|
||||
; as a 16 bit word
|
||||
|
||||
mov dx, TIMER0_RESET_COUNT ; subtract the initialization count
|
||||
sub dx, ax ; from the count just read
|
||||
cmp dx, max_latency
|
||||
jbe no_latency_update
|
||||
; the latency just measure is the
|
||||
; worst case
|
||||
mov max_latency, dx ; update maximum latency read so far
|
||||
no_latency_update:
|
||||
|
||||
pop dx ; restore the CPU environment
|
||||
pop ax
|
||||
|
||||
ret
|
||||
|
||||
endif
|
||||
|
||||
dseg
|
||||
|
||||
max_latency dw 0
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
|
||||
title 'CCP/M disk entry'
|
||||
|
||||
include exerror.equ
|
||||
include diskhdr.equ
|
||||
include system.lib
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* DISK I/O EQUATES
|
||||
;*
|
||||
;*****************************************************
|
||||
;
|
||||
max_retries equ 02 ;retries on disk i/o
|
||||
;before perm error
|
||||
|
||||
eject ! include dskcomn.equ
|
||||
|
||||
FIRST_CALL_FLAG EQU 01H
|
||||
|
||||
eject
|
||||
|
||||
cgroup group code, data
|
||||
|
||||
cseg
|
||||
|
||||
public io_seldsk, io_read, io_write, io_flushbuf
|
||||
public io_select
|
||||
|
||||
extrn sysdat:word
|
||||
extrn supif:near, intdisp:near
|
||||
|
||||
extrn f_dsk_sel:near
|
||||
extrn h_dsk_sel:near
|
||||
|
||||
extrn read:near, h_read:near, read_m_dsk:near
|
||||
extrn write:near, h_write:near, write_M_dsk:near
|
||||
|
||||
dseg
|
||||
|
||||
|
||||
public disk_modes, log_phy, phy_log
|
||||
public idrive, itrack, isector, idmaoff, idmaseg
|
||||
|
||||
|
||||
eject ! include sysdat.lib
|
||||
|
||||
cseg
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* DISK IO CODE AREA
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
;=========
|
||||
io_seldsk: ; Function 9: Select Disk
|
||||
;=========
|
||||
; input: CL = disk to be selected
|
||||
; DL = 00h if disk has not been previously selected
|
||||
; = 01h if disk has been previously selected
|
||||
; output: AX = 0 if illegal disk
|
||||
; = offset of DPH relative from
|
||||
; XIOS Data Segment
|
||||
cseg
|
||||
|
||||
cmp cl,16
|
||||
jb sel_ok ;check for valid drive
|
||||
mov ax,0 ;return error if not
|
||||
ret
|
||||
|
||||
sel_ok:
|
||||
xor bx,bx
|
||||
mov bl,cl
|
||||
mov cl,con_tab[bx] ; allows easy modification of logical to
|
||||
; physical representation of drives
|
||||
|
||||
io_select: ; RESKEW entry point
|
||||
mov idrive,cl
|
||||
|
||||
xor bx, bx
|
||||
mov bl,cl
|
||||
shl bx, 1
|
||||
call select_tbl[bx]
|
||||
|
||||
io_sd_exit:
|
||||
|
||||
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
;=======
|
||||
io_read: ; Function 10: Read sector
|
||||
;=======
|
||||
; Reads the sector on the current disk, track and
|
||||
; sector into the current dma buffer.
|
||||
; input: parameters on stack
|
||||
; output: AL = 000h if no error occured
|
||||
; AL = 001h if an error occured
|
||||
; = 0ffh if media density has changed
|
||||
|
||||
|
||||
mov bp,sp
|
||||
|
||||
mov al,drive
|
||||
cmp al,16! jb rdsk_ok ;check for valid drive
|
||||
mov al,1 ;return error if not
|
||||
mov ah,ATTA_FAILED
|
||||
ret
|
||||
rdsk_ok:
|
||||
|
||||
xor bx,bx
|
||||
mov bl,drive
|
||||
mov al,con_tab[bx]
|
||||
mov drive,al
|
||||
|
||||
mov idrive,al ;save DPH index in local variable
|
||||
|
||||
;*** xor bx,bx ; stores drive mode (0=CCP/M other=PC_MODE)
|
||||
;*** mov bl,al
|
||||
;*** mov bl,disk_modes[bx]
|
||||
;*** mov c_mode,bl
|
||||
|
||||
xor ah,ah ;Index into the physical driver
|
||||
mov si,ax
|
||||
shl si,1
|
||||
jmp read_tbl[si] ;jump to physical driver read routine
|
||||
|
||||
eject
|
||||
|
||||
;========
|
||||
io_write: ; Function 11: Write disk
|
||||
;========
|
||||
; Write the sector in the current Dma buffer
|
||||
; to the current disk on the current
|
||||
; track in the current sector.
|
||||
; input: CL = 0 - Defered Writes
|
||||
; 1 - non-defered writes
|
||||
; 2 - def-wrt 1st sect unalloc blk
|
||||
; output: AL = 000h if no error occured
|
||||
; = 001h if error occured
|
||||
; = 002h if read only disk
|
||||
; = 0ffh if media density has changed
|
||||
|
||||
mov bp,sp ;set BP for indexing into IOPB
|
||||
mov al,drive
|
||||
cmp al,16! jb wdsk_ok ;check if valid drive
|
||||
mov al,1 ;return error if not
|
||||
mov ah,ATTA_FAILED
|
||||
ret
|
||||
wdsk_ok:
|
||||
|
||||
xor bx,bx
|
||||
mov bl,drive
|
||||
mov al,con_tab[bx]
|
||||
mov drive,al
|
||||
|
||||
mov idrive,al ;save DPH index in local variable
|
||||
|
||||
;*** xor bx,bx ; stores drive mode (0=CCP/M other=PC_MODE)
|
||||
;*** mov bl,al
|
||||
;*** mov bl,disk_modes[bx]
|
||||
;*** mov c_mode,bl
|
||||
|
||||
xor ah,ah ;Index into the physical driver
|
||||
mov si,ax
|
||||
shl si,1
|
||||
jmp write_tbl[si] ;jump to physical driver write routine
|
||||
|
||||
;===========
|
||||
io_flushbuf: ; Function 12: Flush Buffer
|
||||
;===========
|
||||
; input: None
|
||||
; output: AL = 00h if no error occurs
|
||||
; = 01h if error occurs
|
||||
; = 02h if read/only disk
|
||||
|
||||
xor al,al ;no need to flush buffer with
|
||||
ret ; no blocking/deblocking in XIOS
|
||||
|
||||
|
||||
ret_error:
|
||||
;--------
|
||||
|
||||
mov al, 01
|
||||
mov ah,ATTA_FAILED
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
read_error_type db 0
|
||||
write_error_type db 0
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* IOPB for disk I/O
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
; iopb dd loczero ;pointer for 8089
|
||||
opcode db 0 ;operation code
|
||||
idrive db 0 ;disk drive id
|
||||
itrack dw 0 ;track for I/O
|
||||
head db 0 ;head for I/O
|
||||
isector db 0 ;sector for I/O
|
||||
count db 0 ;number of sectors for I/O
|
||||
retcode db 0 ;return code from operation
|
||||
retmask db 0 ;return code mask
|
||||
retries db 0 ;number of error retries
|
||||
idmaoff dw 0 ;DMA offset address
|
||||
idmaseg dw 0 ;DMA segment address
|
||||
seclen dw 0 ;sector length
|
||||
dw 0,0,0 ;work area
|
||||
|
||||
eject
|
||||
|
||||
;
|
||||
; Disk Parameter block header table
|
||||
; Currently set up for
|
||||
; A hard disk
|
||||
; B hard disk
|
||||
; C hard disk
|
||||
; D floppy
|
||||
; E floppy
|
||||
; M Memory disk
|
||||
|
||||
select_tbl:
|
||||
dw offset h_dsk_sel ; first hard disk
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset f_dsk_sel ; first floppy
|
||||
dw offset f_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
dw offset h_dsk_sel
|
||||
|
||||
read_tbl dw offset h_read
|
||||
dw offset h_read
|
||||
dw offset h_read
|
||||
dw offset read
|
||||
dw offset read
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset read_m_dsk
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
|
||||
write_tbl dw offset h_write
|
||||
dw offset h_write
|
||||
dw offset h_write
|
||||
dw offset write
|
||||
dw offset write
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset write_m_dsk
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
dw offset ret_error
|
||||
|
||||
; used to allow easy modification of logical to physical drives
|
||||
|
||||
con_tab db 0
|
||||
db 1
|
||||
db 2
|
||||
db 3
|
||||
db 4
|
||||
db 5
|
||||
db 6
|
||||
db 7
|
||||
db 8
|
||||
db 9
|
||||
db 10
|
||||
db 11
|
||||
db 12
|
||||
db 13
|
||||
db 14
|
||||
db 15
|
||||
|
||||
; used to store operating modes for disk drivers
|
||||
; if 0 then CP/M else DOS
|
||||
|
||||
disk_modes db 0,0,0,0
|
||||
db 0,0,0,0
|
||||
db 0,0,0,0
|
||||
db 0,0,0,0
|
||||
|
||||
; Floppy code uses to get correct physical floppy
|
||||
|
||||
log_phy db 255 ; A
|
||||
db 255 ; B
|
||||
db 255 ; C
|
||||
db 0 ; D physical floppy 0
|
||||
db 1 ; E physical floppy 1
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
db 255 ; M
|
||||
db 255
|
||||
db 255
|
||||
db 255
|
||||
|
||||
; For Floppy routines to determine what logical drive is currently
|
||||
; using the physical drive.
|
||||
|
||||
phy_log db 0
|
||||
db 0
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
;************************************************
|
||||
;* Disk System Header Equate File *
|
||||
;* File name: diskhdr.equ *
|
||||
;* Last update: 11/10/83 *
|
||||
;************************************************
|
||||
|
||||
;
|
||||
; Read and Write disk parameter equates
|
||||
;
|
||||
; At the disk read and write function entrys
|
||||
; all disk I/O parameters are on the stack
|
||||
; and the stack at these entrys appears as
|
||||
; follows:
|
||||
;
|
||||
; +-------+-------+
|
||||
; +14 | DRV | MCNT | Drive and Multi sector count
|
||||
; +-------+-------+
|
||||
; +12 | TRACK | Track number
|
||||
; +-------+-------+
|
||||
; +10 | SECTOR | Physical sector number
|
||||
; +-------+-------+
|
||||
; +8 | DMA_SEG | DMA segment
|
||||
; +-------+-------+
|
||||
; +6 | DMA_OFF | DMA offset
|
||||
; +-------+-------+
|
||||
; +4 | RET_SEG | BDOS return segment
|
||||
; +-------+-------+
|
||||
; +2 | RET_OFF | BDOS return offset
|
||||
; +-------+-------+
|
||||
; SP+0 | RET_ADR | Local entry return address
|
||||
; +-------+-------+
|
||||
;
|
||||
; These parameters may be indexed and modifide
|
||||
; directly on the stack and will be removed
|
||||
; by the BDOS after the function is complete
|
||||
|
||||
|
||||
; These are the euates for the above pictured data structure
|
||||
|
||||
DRIVE equ byte ptr 14[bp]
|
||||
MCNT equ byte ptr 15[bp]
|
||||
TRACK equ word ptr 12[bp]
|
||||
SECTOR equ word ptr 10[bp]
|
||||
DMASEG equ word ptr 8[bp]
|
||||
DMAOFF equ word ptr 6[bp]
|
||||
|
||||
; These equates are for the DPH's
|
||||
|
||||
xlt equ word ptr 0 ; tranalation table offset in dph
|
||||
dpb equ word ptr 8 ; disk parameter block offset in dph
|
||||
mf equ byte ptr 5 ; disk specific media flag
|
||||
|
||||
; These equates are for the DPB's
|
||||
|
||||
spt equ 0 ; sectors per track offset in dpb
|
||||
psh equ 15 ; physical shift factor offset in dpb
|
||||
|
||||
|
||||
; Retry equates
|
||||
|
||||
RW_RECAL_COUNT EQU 5 ; Max number of recals
|
||||
RETRY_COUNT EQU 10 ; Max number retries
|
||||
|
||||
; Path tracer equates
|
||||
|
||||
PATH_ENTRY EQU word ptr 0 ; Path counter when routine entered
|
||||
PATH_EXIT EQU word ptr 2 ; Path counter when routine exited
|
||||
|
||||
LAST_RETRY EQU word ptr 4 ; Retry counter at last exit
|
||||
LAST_RETURN EQU word ptr 6 ; Last returned value
|
||||
|
||||
USE EQU word ptr 8 ; number of time routine called
|
||||
RETRY_SUM EQU word ptr 10 ; sum of all retry attempts
|
||||
RETRY1_SUM EQU word ptr 12 ; sum of all retry attempts
|
||||
RECAL_SUM EQU word ptr 14 ; sum of all retry attempts
|
||||
|
||||
PATH_RETRY_HIST EQU 16 ; length of above data structure
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
|
||||
|
||||
|
||||
title 'Compupro CCP/M DPHs & DPBs'
|
||||
|
||||
|
||||
;****************************************
|
||||
; *
|
||||
; DISK PARAMTER HEADERS & BLOCKS *
|
||||
; Last changed: 2/6/84 *
|
||||
; *
|
||||
;****************************************
|
||||
|
||||
include dpbs.equ
|
||||
|
||||
dseg
|
||||
|
||||
public dph1,dpe5,dph2,dph3,dph4,dph5
|
||||
|
||||
public xlts, xltd1, xltd2, xltd3
|
||||
public current_reskew
|
||||
public re_skew_26_3, re_skew_26_2, re_skew_15_2, re_skew_8_2
|
||||
public dpbs1, dpbs2, dpbd1, dpbd2, dpbd3, dpbd4, dpbd5, dpbd6
|
||||
public dpbpc1
|
||||
|
||||
;== floppy disk 0
|
||||
dph1 dw xltd3, 0000h ; translate table
|
||||
dw 0000h, 0000h ; scratch area
|
||||
dw dpbpc1 ; disk paramater table
|
||||
dw 0ffffh, 0ffffh ; check, alloc vectors
|
||||
dw 0ffffh ; dir buf control block
|
||||
dw 0ffffh ; data buff cntrl block
|
||||
dw 0ffffh ; hash table segment
|
||||
|
||||
;== floppy disk 1
|
||||
dph2 dw xltd3, 0000h ; translate table
|
||||
dw 0000h, 0000h ; scratch area
|
||||
dw dpbpc1 ; disk paramater table
|
||||
dw offset dph1_csv ; check sum vector
|
||||
dw 0ffffh ; alloc vectors
|
||||
dw 0ffffh ; dir buf control block
|
||||
dw 0ffffh ; data buff cntrl block
|
||||
dw 0ffffh ; hash table segment
|
||||
|
||||
; hard disk outter edge
|
||||
dph3 dw 0000h, 0000h ; translate table
|
||||
dw 0000h, 0000h ; scratch area
|
||||
dw dpbh1 ; disk paramater table
|
||||
dw 0ffffh ; check sum vector
|
||||
dw 0ffffh ; alloc vectors
|
||||
dw 0ffffh ; dir buf control block
|
||||
dw 0ffffh ; data buff cntrl block
|
||||
dw 0ffffh ; hash table segment
|
||||
|
||||
; hard disk middle
|
||||
dph4 dw 0000h, 0000h ; translate table
|
||||
dw 0000h, 0000h ; scratch area
|
||||
dw dpbh2 ; disk paramater table
|
||||
dw 0ffffh ; check sum vector
|
||||
dw 0ffffh ; alloc vectors
|
||||
dw 0ffffh ; dir buf control block
|
||||
dw 0ffffh ; data buff cntrl block
|
||||
dw 0ffffh ; hash table segment
|
||||
|
||||
; hard disk near spindle
|
||||
dph5 dw 0000h, 0000h ; translate table
|
||||
dw 0000h, 0000h ; scratch area
|
||||
dw dpbh3 ; disk paramater table
|
||||
dw 0ffffh ; check sum vector
|
||||
dw 0ffffh ; alloc vectors
|
||||
dw 0ffffh ; dir buf control block
|
||||
dw 0ffffh ; data buff cntrl block
|
||||
dw 0ffffh ; hash table segment
|
||||
|
||||
; mdisk
|
||||
dpe5 dw xlt5,0000h ;Translate Table
|
||||
dw 0000h,0000h ;Scratch Area
|
||||
dw dpb5 ;Dsk Parm Block
|
||||
dw offset dph2_csv ; check sum vector
|
||||
dw 0ffffh ; Alloc Vectors
|
||||
dw 0ffffh ;Dir Buff Cntrl Blk
|
||||
dw 0 ;Data Buff Cntrl Blk
|
||||
dw 0 ;Hash Table Segment
|
||||
|
||||
dph1_csv rb 256 / 4 + 1 ; ( drm/4 ) + 2
|
||||
dph2_csv rb 256 / 4 + 1 ; ( drm/4 ) + 2
|
||||
|
||||
|
||||
eject
|
||||
|
||||
; THESE ARE THE SKEW TABLES
|
||||
; sector translation tables (for floppy disks)
|
||||
|
||||
|
||||
xlts DB 0,6,12,18,24,4,10,16,22,2,8,14,20 ; physical skew = 6
|
||||
DB 1,7,13,19,25,5,11,17,23,3,9,15,21 ; 26 sectors/track
|
||||
; 128 byte sectors
|
||||
|
||||
xltd1 db 0,9,18,1,10,19,2,11,20,3,12,21 ; physical skew = 9
|
||||
db 4,13,22,5,14,23,6,15,24,7,16,25 ; 26 sectors/track
|
||||
db 8,17 ; 256 byte sectors
|
||||
|
||||
xltd2 db 0,4,8,12,1,5,9,13 ; physical skew = 4
|
||||
db 2,6,10,14,3,7,11 ; 15 sectors/track
|
||||
; 512 byte sectors
|
||||
|
||||
xltd3 DB 0,3,6,1,4,7,2,5 ; physical skew = 3
|
||||
; 8 sectors per track
|
||||
; 1024 byte sectors
|
||||
|
||||
; THESE ARE THE RE-SKEW TABLES
|
||||
|
||||
current_reskew dw 0
|
||||
|
||||
re_skew_26_3 db 0,3,6,9,12,15,18,21,24,1,4,7,10
|
||||
db 13,16,19,22,25,2,5,8,11,14,17,20,23
|
||||
|
||||
re_skew_26_2 db 0,2,4,6,8,10,12,14,16,18,20,22,24
|
||||
db 1,3,5,7,9,11,13,15,17,19,21,23,25
|
||||
|
||||
re_skew_15_2 db 0,2,4,6,8,10,12,14
|
||||
db 1,3,5,7,9,11,13
|
||||
|
||||
re_skew_8_2 db 0,2,4,6
|
||||
db 1,3,5,7
|
||||
|
||||
|
||||
eject
|
||||
|
||||
; disk type definition blocks for each particular mode.
|
||||
|
||||
dpbpc1: ; 8" single sided and density for PC_MODE
|
||||
|
||||
DW 0ffffH ; EXTFLAG
|
||||
DW 2 ; NFATS
|
||||
DW 6 ; NFATRECS
|
||||
DW 495 ; NCLSTRS
|
||||
DW 128*4 ; CLSIZE
|
||||
DW 1 ; FATADD
|
||||
DW 26 ; SPT
|
||||
DB 0 ; BSH
|
||||
DB 0 ; BLM
|
||||
DB 0 ; EXM
|
||||
DW 1221 ; DSM --- will be 495 at run time
|
||||
DW 255 ; DRM --- will be 67 at run time
|
||||
DB 0 ; AL0
|
||||
DB 0 ; AL1
|
||||
DW 8040H ; CKS --- will be 801a at run time
|
||||
DW 0 ; OFF
|
||||
DB 0 ; PSH
|
||||
DB 0 ; PHM
|
||||
|
||||
dpbs1: ;single density, single sided.
|
||||
DW 26 ;sectors per track
|
||||
DB 3,7,0 ;block size=1k, exm=0
|
||||
DW s1dsm-1,64-1 ;dsm,drm
|
||||
DB 11000000b,00000000b ;2 blocks for directory
|
||||
DW 8010H ;64/4 cks
|
||||
DW 2 ;offset by 2 tracks
|
||||
db 0 ; physical sector shift
|
||||
db 0 ; physical sector mask
|
||||
|
||||
dpbs2: ;single density, double sided.
|
||||
DW 26 ;sectors per track
|
||||
DB 4,15,1 ;block size=2k, exm=1
|
||||
DW s2dsm-1,128-1 ;dsm, drm
|
||||
DB 11000000b,00000000b ;2 blocks for directory
|
||||
DW 8020H ;128/4 cks
|
||||
DW 2*2 ;offset by 4 tracks
|
||||
db 0 ; physical sector shift
|
||||
db 0 ; physical sector mask
|
||||
|
||||
|
||||
dpbd1: ;double density, single sided. (256 byte sectors)
|
||||
DW 26 ;physical sectors per track
|
||||
DB 4,15,0 ;block size = 2k, exm=0 (should be 1)
|
||||
DW d1dsm-1,128-1 ;dsm, drm
|
||||
DB 11000000b,00000000b ;2 blocks for directory
|
||||
DW 8020H ;128/4 cks
|
||||
DW 2 ;offset 2 tracks
|
||||
db 1 ; physical sector shift
|
||||
db 1 ; physical sector mask
|
||||
|
||||
|
||||
dpbd2: ;double density, double sided. (256 byte sectors)
|
||||
DW 26 ; physical sectors per track
|
||||
DB 4,15,0 ;2k block size, exm=0
|
||||
DW d2dsm-1,256-1 ;dsm, drm
|
||||
DB 11110000b,00000000b ;4 directory blocks
|
||||
DW 8040H ;256/4 cks
|
||||
DW 2*2 ;offset 4 tracks
|
||||
db 1 ; physical sector shift
|
||||
db 1 ; physical sector mask
|
||||
|
||||
|
||||
dpbd3: ;double density, single sided. (512 byte sectors)
|
||||
DW 15 ;physical sectors per track
|
||||
DB 4,15,0 ;2k block size, exm=0
|
||||
DW d3dsm-1,128-1 ;dsm, drm
|
||||
DB 11000000b,00000000b ;2 directory blocks
|
||||
DW 8020H ;128/4 cks
|
||||
DW 2 ;offset 2 tracks
|
||||
db 2 ; physical sector shift
|
||||
db 3 ; physical sector mask
|
||||
|
||||
|
||||
dpbd4: ;double density, double sided. (512-byte sectors)
|
||||
DW 15 ;physical sectors per track
|
||||
DB 4,15,0 ;2k block size, exm=0
|
||||
DW d4dsm-1,256-1 ;dsm, drm
|
||||
DB 11110000b,00000000b ;4 directory blocks
|
||||
DW 8040 ;256/4 cks
|
||||
DW 2*2 ;offset 4 tracks
|
||||
db 2 ; physical sector shift
|
||||
db 3 ; physical sector mask
|
||||
|
||||
|
||||
dpbd5: ;double density, single sided. (1024-byte sectors)
|
||||
DW 8 ;physical sectors per track
|
||||
DB 4,15,0 ;2k block size, exm=0
|
||||
DW d5dsm-1,128-1 ;dsm, drm
|
||||
DB 11000000b,00000000b ;2 directory blocks
|
||||
DW 8020H ;128/4 cks, semi-permanent
|
||||
DW 2 ;offset 2 tracks
|
||||
db 3 ; physical sector shift
|
||||
db 7 ; physical sector mask
|
||||
|
||||
|
||||
dpbd6: ;double density, double sided. (1024-byte sectors)
|
||||
DW 8 ;physical sectors per track
|
||||
DB 4,15,0 ;2k block size, exm=0
|
||||
DW d6dsm-1,256-1 ;dsm, drm
|
||||
DB 11110000b,00000000b ;4 directory blocks
|
||||
DW 8040H ; 256/4 cks, semi-permanent
|
||||
DW 2*2 ;offset 4 tracks
|
||||
db 3 ; physical sector shift
|
||||
db 7 ; physical sector mask
|
||||
|
||||
|
||||
|
||||
dpbh1: ; hard disk near outtter edge
|
||||
DW 11 ;physical sectors per track
|
||||
DB 5,31,1 ; 4k block size, exm=1
|
||||
DW 7FDh,3FFH ;dsm, drm
|
||||
DB 0ffh,0ffh ; 16 directory blocks
|
||||
DW 8000h ; 0 cks, semi-permanent
|
||||
DW 8 ;offset 8 tracks
|
||||
db 3 ; physical sector shift
|
||||
db 7 ; physical sector mask
|
||||
|
||||
dpbh2: ; hard disk near middle
|
||||
DW 11 ;physical sectors per track
|
||||
DB 5,31,1 ; 4k block size, exm=1
|
||||
DW 7FDh,3FFH ;dsm, drm
|
||||
DB 0ffh,0ffh ; 16 directory blocks
|
||||
DW 8000h ; 0 cks, semi-permanent
|
||||
DW 2F0h ;offset 2F0h tracks
|
||||
db 3 ; physical sector shift
|
||||
db 7 ; physical sector mask
|
||||
|
||||
dpbh3: ; hard disk near spindle
|
||||
DW 11 ;physical sectors per track
|
||||
DB 5,31,1 ; 4k block size, exm=1
|
||||
DW 4E5h,3FFH ;dsm, drm
|
||||
DB 0ffh,0ffh ; 16 directory blocks
|
||||
DW 8000h ; 0 cks, semi-permanent
|
||||
DW 5D8h ;offset 5D8h tracks
|
||||
db 3 ; physical sector shift
|
||||
db 7 ; physical sector mask
|
||||
|
||||
|
||||
; DISKDEF 5,0,7,,1024,127,32,0,0
|
||||
;
|
||||
; 1016: 128 Byte Record Capacity
|
||||
; 127: Kilobyte Drive Capacity
|
||||
; 32: 32 Byte Directory Entries
|
||||
; 0: Checked Directory Entries
|
||||
; 128: Records / Extent
|
||||
; 8: Records / Block
|
||||
; 8: Sectors / Track
|
||||
; 0: Reserved Tracks
|
||||
;
|
||||
dpb5 equ offset $ ;Disk Parameter Block
|
||||
dw 8 ;Sectors Per Track
|
||||
db 3 ;Block Shift
|
||||
db 7 ;Block Mask
|
||||
db 0 ;Extnt Mask
|
||||
dw 126 ;Disk Size - 1
|
||||
dw 31 ;Directory Max
|
||||
db 128 ;Alloc0
|
||||
db 0 ;Alloc1
|
||||
dw 0 ;Check Size
|
||||
dw 0 ;Offset
|
||||
db 0 ;Phys Sec Shift
|
||||
db 0 ;Phys Sec Mask
|
||||
|
||||
xlt5 equ 0 ;No Translate Table
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
; CP/M disk control block equates which define the
|
||||
; disk types and maximum storage capability of each
|
||||
; disk type.
|
||||
|
||||
; CP/M to host disk constants
|
||||
|
||||
hstsiz EQU 1024 ;blocking/deblocking buffer size
|
||||
cpmsib EQU 1024/128 ;standard sectors in block
|
||||
fpysib EQU 2048/128 ;sectors in floppy disk block
|
||||
hblksiz EQU 4*1024 ;M20 block size
|
||||
hhstsiz EQU 512 ;M20 bytes per sector
|
||||
hdspt EQU 21 ;M20 physical sectors per head/track
|
||||
hhstspt EQU hdspt*8 ;M20 physical sectors per track
|
||||
hhstblk EQU hhstsiz/128 ;M20 CP/M records per physical sector
|
||||
hcpmspt EQU hhstblk*hhstspt ;M20 CP/M records per track
|
||||
hardsib EQU hblksiz/128 ;standard records in hard disk data block
|
||||
|
||||
|
||||
dskhd EQU 8 ;hard drive, 512-byte sectors
|
||||
s1dsm EQU ((77-2)*26)/cpmsib
|
||||
s2dsm EQU ((77-2)*2*26)/fpysib
|
||||
d1dsm EQU ((77-2)*2*26)/fpysib
|
||||
d2dsm EQU ((77-2)*2*2*26)/fpysib
|
||||
d3dsm EQU ((77-2)*4*15)/fpysib
|
||||
d4dsm EQU ((77-2)*2*4*15)/fpysib
|
||||
d5dsm EQU ((77-2)*8*8)/fpysib
|
||||
d6dsm EQU ((77-2)*2*8*8)/fpysib
|
||||
h0dsm EQU 97*hcpmspt/hardsib ;1st 97 tracks of M20
|
||||
h1dsm EQU h0dsm ;2nd 97 tracks of M20
|
||||
h2dsm EQU 49*hcpmspt/hardsib ;last 49 tracks of M20
|
||||
|
||||
ndsk EQU 5 ;number of logical disk drives
|
||||
csvflen equ 256/4 ;csv length for floppies
|
||||
alvflen equ (d6dsm+7)/8 ;alloc vector length for floppies
|
||||
alvh0ln EQU (h0dsm+7)/8 ;alv length for logical hard drive 0
|
||||
alvh1ln EQU (h1dsm+7)/8 ;alv length for logical hard drive 1
|
||||
alvh2ln EQU (h2dsm+7)/8 ;alv length for logical hard drive 2
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
HD_FORK EQU TRUE
|
||||
FLPY_FORK EQU TRUE
|
||||
|
||||
FDC_FLAG EQU 7
|
||||
H_DISK_FLAG EQU 8
|
||||
|
||||
HD_EOI EQU 61H
|
||||
FLPY_EOI EQU 64H
|
||||
|
||||
MASTER_PIC_PORT EQU 50H
|
||||
F_DMA EQU 0C2H
|
||||
|
||||
FS_READ_ID EQU 0AH
|
||||
FD_READ_ID EQU 4AH
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
;
|
||||
; Extented Error Codes
|
||||
;
|
||||
ATTA_FAILED equ 80H
|
||||
SEEK_FAILED equ 40H
|
||||
CONT_FAILED equ 20H
|
||||
BAD_CRC_ERR equ 10H
|
||||
DMA_OVERRUN equ 08H
|
||||
SEC_NOT_FND equ 04H
|
||||
WRT_PRO_DSK equ 03H
|
||||
ADR_NOT_FND equ 02H
|
||||
BAD_COMMAND equ 01H
|
||||
NO_EXTD_ERR equ 00H
|
||||
;
|
||||
|
||||
2232
CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 3.1 SOURCE/D5/FD.A86
Normal file
2232
CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 3.1 SOURCE/D5/FD.A86
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
||||
|
||||
;****************************************************************
|
||||
;* FLAG DEFINITION MODULE *
|
||||
;* File name: FLAGS.EQU *
|
||||
;* Last Update: 10/10/83 *
|
||||
;* *
|
||||
;* All the flags used in CCP/M's I/O system should be *
|
||||
;* defined in this module. *
|
||||
;****************************************************************
|
||||
|
||||
; Flags 0, 1, and 2 are defined and reserved by DRI
|
||||
|
||||
TICK_FLAG equ 1 ; system tick
|
||||
|
||||
SEC_FLAG equ 2 ; used by clock
|
||||
|
||||
; OEM defined flags
|
||||
|
||||
NMI_FLAG equ 6 ; Non Maskable Interrupt
|
||||
FDC_FLAG equ 7 ; Floppy Interrupt
|
||||
H_DISK_FLAG equ 8 ; Hard Disk Interrupt
|
||||
|
||||
; Serial port flags
|
||||
|
||||
C0IN_F equ 4 ; Physical console 0
|
||||
C0OUT_F equ 5
|
||||
|
||||
C1IN_F equ 9 ; Physical console 1
|
||||
C1OUT_F equ 10
|
||||
|
||||
C2IN_F equ 11 ; Physical console 2
|
||||
C2OUT_F equ 12
|
||||
|
||||
C3IN_F equ 13 ; Physical console 3
|
||||
C3OUT_F equ 14
|
||||
|
||||
C4IN_F equ 15 ; Physical console 4
|
||||
C4OUT_F equ 16
|
||||
|
||||
C5IN_F equ 17 ; Physical console 5
|
||||
C5OUT_F equ 18
|
||||
|
||||
C6IN_F equ 19 ; Physical console 6
|
||||
C6OUT_F equ 20
|
||||
|
||||
C7IN_F equ 21 ; Physical console 7
|
||||
C7OUT_F equ 22
|
||||
|
||||
C8IN_F equ 23 ; Physical console 8
|
||||
C8OUT_F equ 24
|
||||
|
||||
|
||||
;*************************
|
||||
;* END OF FLAG DEFINITIONS
|
||||
;*************************
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,857 @@
|
||||
|
||||
title 'Disk 2 Hard Disk Driver'
|
||||
|
||||
;************************************************
|
||||
; *
|
||||
; HARD DISK DRIVER MODULE *
|
||||
; Last changed : 2/13/84 *
|
||||
; *
|
||||
;************************************************
|
||||
|
||||
include system.lib
|
||||
eject !
|
||||
include diskhdr.equ
|
||||
include exerror.equ
|
||||
|
||||
HD_IRL equ 02H ; hard disk interrupt request line
|
||||
|
||||
MASTER_PIC_PORT EQU 50H
|
||||
RW_ERROR EQU 01
|
||||
SUCCESS EQU 0
|
||||
RET_ADDR EQU 04
|
||||
|
||||
; FOR HARD DISK WITH A DISK 2 CONTROLLER
|
||||
H_READ_F EQU 1
|
||||
H_WRITE_F EQU 2
|
||||
|
||||
; disk 2 ports
|
||||
STAT_CONTROL equ 0C8H
|
||||
DISK_2_DATA equ STAT_CONTROL + 1
|
||||
DISK_2_SELECT equ 0F0H
|
||||
|
||||
ROUTINE_USE equ 2
|
||||
|
||||
phys_drvs equ 1 ; # physical hard drive(s) supported
|
||||
track_0 equ 0 ; this is track 0
|
||||
drive_sel_op equ 0 ; disk 2 drive select op code
|
||||
drive_0 equ 10h ; this is the first and only drive
|
||||
; in the system
|
||||
seek_outer equ false
|
||||
seek_inner equ true
|
||||
|
||||
home_count equ 512
|
||||
; status equates
|
||||
ATTN_NOT equ 80h
|
||||
TIME_OUT equ 40h
|
||||
CRC_ERROR equ 20h
|
||||
OVER_RUN equ 10h
|
||||
READY_NOT equ 08h
|
||||
SEEK_COMPLETE_NOT equ 04h
|
||||
WRITE_FAULT_NOT equ 02h
|
||||
TRACK0_NOT equ 01h
|
||||
|
||||
; control equates
|
||||
RUN EQU 40H
|
||||
OP2 EQU 20H
|
||||
OP1 EQU 10H
|
||||
OP0 EQU 08H
|
||||
FAULT_CLR EQU 04H
|
||||
USR1 EQU 02H
|
||||
USR2 EQU 01H
|
||||
|
||||
; command equates
|
||||
NULL_F equ 0C0H
|
||||
CLEAR_INT equ 080H
|
||||
READ_DATA_F equ 0C8H
|
||||
WRITE_DATA_F equ 0D0H
|
||||
WRITE_HEADER_F equ 091H
|
||||
READ_HEADER_F equ 0E0H
|
||||
|
||||
; seek direction, op2(bit 5) of the
|
||||
; command word sets the direction
|
||||
; signal to the disk drive.
|
||||
INNER EQU 20H
|
||||
OUTTER EQU 00H
|
||||
; offsets for read header command buffer
|
||||
TEST_CYLINDER EQU 0H
|
||||
TEST_HEAD EQU 1H
|
||||
TEST_SECTOR EQU 2H
|
||||
|
||||
eject
|
||||
|
||||
; For the DISK2 selector card
|
||||
; See page 28 of the DISK2 manual
|
||||
; the patterns given are for:
|
||||
; d7 = write/read
|
||||
; d6 = memory (vs io port operations)
|
||||
; d5 = increment the memory address
|
||||
; d4 = no wait states
|
||||
; d3 - d0 = complement of the dma dev
|
||||
; the selector channel will work with
|
||||
DISK_2_INT_PRIORITY equ 10
|
||||
DISK_2_DMA_PRIORITY equ not DISK_2_INT_PRIORITY
|
||||
WRITE_TO_DISK equ 00100000b or ( DISK_2_DMA_PRIORITY and 0fh )
|
||||
READ_FROM_DISK equ 10100000b or ( DISK_2_DMA_PRIORITY and 0fh )
|
||||
|
||||
; For the read/write routines
|
||||
TRACK_OFFSET EQU 0
|
||||
HEAD_OFFSET EQU 2
|
||||
SECTOR_OFFSET EQU 4
|
||||
DMA_OFFSET equ 6
|
||||
|
||||
; these are the op codes for the DISK2
|
||||
OP_DRIVE equ 080H
|
||||
OP_TRACK equ 088H
|
||||
OP_HEAD equ 090h
|
||||
OP_SECTOR equ 098h
|
||||
|
||||
eject
|
||||
|
||||
H_DISK_FLAG EQU 8
|
||||
HD_EOI EQU 61H
|
||||
|
||||
cseg
|
||||
|
||||
public h_read, h_write, h_dsk_sel
|
||||
public h_init, h_disk_int
|
||||
|
||||
extrn intdisp:near
|
||||
extrn supif:near, sysdat:word
|
||||
extrn read_write:near
|
||||
|
||||
dseg
|
||||
|
||||
extrn dph_tbl:word
|
||||
extrn dph1:byte, dph2:byte, dph3:byte
|
||||
|
||||
extrn current_reskew:word
|
||||
|
||||
extrn itrack:word, isector:byte, idmaoff:word, idmaseg:word
|
||||
|
||||
hd_stat db 0 ; Interrupt handler will put status
|
||||
; from the DISK2 controller here before
|
||||
; it resets the PIC.
|
||||
eject ! include sysdat.lib
|
||||
|
||||
eject
|
||||
|
||||
cseg
|
||||
|
||||
;==========
|
||||
h_disk_int: ; hard disk interrupt handler
|
||||
;==========
|
||||
;
|
||||
|
||||
push ds
|
||||
mov ds,sysdat
|
||||
|
||||
mov h_disk_ssreg,ss ; may need to check for
|
||||
mov h_disk_spreg,sp ; re-entrant interrupt since
|
||||
mov ss,sysdat ; nmi's can't be disabled
|
||||
mov sp,offset h_disk_tos
|
||||
|
||||
push ax ! push bx
|
||||
push cx ! push dx
|
||||
push di ! push si
|
||||
push bp ! push es
|
||||
|
||||
in al, ( MASTER_PIC_PORT + 1 ) ; get the PIC's mask
|
||||
or al, HD_IRL ; mask out the Disk 2
|
||||
out ( MASTER_PIC_PORT + 1 ), al ; write the mask back to the PIC
|
||||
|
||||
mov dx, H_DISK_FLAG
|
||||
mov cl,F_FLAGSET
|
||||
call supif
|
||||
|
||||
mov al, HD_EOI ; just reset the PIC's
|
||||
out MASTER_PIC_PORT,al
|
||||
|
||||
pop es ! pop bp
|
||||
pop si ! pop di
|
||||
pop dx ! pop cx
|
||||
pop bx ! pop ax
|
||||
|
||||
mov ss, h_disk_ssreg
|
||||
mov sp, h_disk_spreg
|
||||
|
||||
pop ds
|
||||
|
||||
jmp intdisp ; iret from dispatcher
|
||||
|
||||
|
||||
eject
|
||||
|
||||
;=========
|
||||
h_dsk_sel:
|
||||
;=========
|
||||
;
|
||||
; Translates cpm logical drive to a controller specific drive
|
||||
;
|
||||
; ENTRY: cl = cpm logical drive
|
||||
; bx = offset into a dph table
|
||||
; dl[bit 0] = select code
|
||||
;
|
||||
; EXIT: ax = bx = &dph if every thing went ok
|
||||
; ax = bx = 0 if there is no DPH for this drive
|
||||
;
|
||||
; NOTE: this routine just indexes into the dph table
|
||||
; and returns whatever is there. There is no protection.
|
||||
|
||||
mov ax, dph_tbl[bx]
|
||||
mov bx, ax
|
||||
mov current_reskew, 0
|
||||
ret
|
||||
|
||||
|
||||
;====
|
||||
h_init:
|
||||
;====
|
||||
; Initialzation of the hard disk sub-system.
|
||||
; Initializes the memory structures, homes the head,
|
||||
; and puts the disk2 and its selector in a safe state.
|
||||
; See microdisk drives C/E Manual (lsi version) by FUJITSU
|
||||
; and page 6 of the disk 2 manual
|
||||
|
||||
; init the last physical sector to 0
|
||||
mov last_cyl,track_0
|
||||
|
||||
; do the initial read of the selector channel
|
||||
; pages 27 and 28 of the disk 2 guide
|
||||
in al, DISK_2_SELECT
|
||||
|
||||
; init the header buffer d word
|
||||
mov ( header_buffer_addr + 2 ), ds
|
||||
|
||||
; we only are supporting one drive
|
||||
; wait for the drive to be come ready
|
||||
mov al, OP_DRIVE ; select drive command
|
||||
call send_command
|
||||
mov al, DRIVE_0 ; for this drive
|
||||
call send_data
|
||||
|
||||
init_drv_rdy_lp: ; wait for the drive
|
||||
mov al, NULL_F
|
||||
call send_command
|
||||
call stat_return
|
||||
test al, READY_NOT
|
||||
jnz init_drv_rdy_lp
|
||||
|
||||
call h_home
|
||||
jz init_exit
|
||||
or al, ERROR ; extended from h_home
|
||||
init_exit:
|
||||
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
;======
|
||||
h_read:
|
||||
;======
|
||||
; this routine is called by the bdos
|
||||
;
|
||||
; ENTRY: bp = &(IOPB on the stack)
|
||||
;
|
||||
; EXIT: OK if the read happened ok
|
||||
; RW_ERROR if there was a read error
|
||||
;
|
||||
|
||||
mov hard_op, H_READ_F
|
||||
mov si, offset h_rd_wt
|
||||
jmp read_write
|
||||
|
||||
|
||||
|
||||
;======
|
||||
h_write:
|
||||
;======
|
||||
; this routine is called by the bdos
|
||||
;
|
||||
; ENTRY: bp = &(IOPB on the stack)
|
||||
;
|
||||
; EXIT: OK if the read happened ok
|
||||
; RW_ERROR if there was a read error
|
||||
;
|
||||
|
||||
mov hard_op, H_WRITE_F
|
||||
mov si, offset h_rd_wt
|
||||
jmp read_write
|
||||
|
||||
|
||||
|
||||
;=======
|
||||
h_rd_wt:
|
||||
;=======
|
||||
;
|
||||
; This is the main sector read routine for concurrent
|
||||
; It does everything possible to make the read.
|
||||
; The drive is assumed to be 0 and selected befor this operation.
|
||||
;
|
||||
; ENTRY: hd_op = READ if we want a read, WRITE if we want a write
|
||||
; itrack = the track we want to read
|
||||
; isector = the sector we want to read
|
||||
; idmaoff = where to get or put the data
|
||||
; idmaseg = where to get or put the data
|
||||
;
|
||||
; EXIT: al = OK if every thing went OK
|
||||
; al = RW_ERROR (01) if there was a fatal error
|
||||
;
|
||||
|
||||
mov bx, offset rw_track
|
||||
mov h_rd_wt_param_add, bx ; save the param pointer
|
||||
|
||||
; translate the track from concurrent to the track and
|
||||
; sector for the hard disk
|
||||
; this assumes 8 heads [ 0 - 7 ]
|
||||
|
||||
mov ax, itrack
|
||||
and ax, 07
|
||||
mov HEAD_OFFSET[bx], al
|
||||
mov ax, itrack
|
||||
mov cl, 3
|
||||
shr ax, cl
|
||||
mov TRACK_OFFSET[bx], ax
|
||||
|
||||
; move the remaining params passed in from read_write to
|
||||
; our local copies
|
||||
xor ax, ax
|
||||
mov al, isector
|
||||
mov SECTOR_OFFSET[bx], ax
|
||||
mov ax, idmaoff
|
||||
mov DMA_OFFSET[bx], ax
|
||||
mov ax, idmaseg
|
||||
mov DMA_OFFSET + 2 [bx], ax
|
||||
|
||||
; select the drive and
|
||||
; check for the drive being ready.
|
||||
mov al, OP_DRIVE
|
||||
call send_command
|
||||
mov al, DRIVE_0
|
||||
call send_data
|
||||
call stat_return
|
||||
and al, READY_NOT! jz rd_drv_rdy
|
||||
mov ah,ATTA_FAILED ; drive was not ready
|
||||
or al, RW_ERROR
|
||||
ret
|
||||
rd_drv_rdy:
|
||||
|
||||
mov re_homes, RETRY_COUNT / 2
|
||||
re_home_lp:
|
||||
mov h_rd_wt_retries, RETRY_COUNT
|
||||
h_rd_wt_retry_lp:
|
||||
|
||||
mov bx, h_rd_wt_param_add ; set up the parameter pointer
|
||||
|
||||
; seek to the proper track
|
||||
mov ax, TRACK_OFFSET[bx]
|
||||
mov cyl,ax
|
||||
call seek
|
||||
|
||||
mov bx, h_rd_wt_param_add ; set up the parameter pointer
|
||||
|
||||
; set up the drive register
|
||||
mov al, OP_DRIVE ; select the drive/head register for
|
||||
call send_command ; for the subsequent out instruction
|
||||
xor ax,ax ; only drive 0 is valid
|
||||
mov ax, HEAD_OFFSET[bx]
|
||||
and ax, 0fH ; THE lower nibble in al is head
|
||||
or al, DRIVE_0 ; the upper nibble is the drive
|
||||
call send_data
|
||||
|
||||
; set up the track register
|
||||
mov al, OP_TRACK
|
||||
call send_command
|
||||
mov ax, TRACK_OFFSET[bx] ; select the track
|
||||
call send_data
|
||||
|
||||
; set up the head register
|
||||
mov al, OP_HEAD
|
||||
call send_command
|
||||
mov ax, HEAD_OFFSET[bx] ; select the head
|
||||
and ax,0fh
|
||||
call send_data
|
||||
|
||||
; set up the sector register
|
||||
mov al, OP_SECTOR
|
||||
call send_command
|
||||
mov ax, SECTOR_OFFSET[bx] ;select the sector
|
||||
and al, 0ffh
|
||||
call send_data
|
||||
|
||||
; set up the dma base and direction
|
||||
lea bx, DMA_OFFSET[bx]
|
||||
cmp hard_op, H_READ_F
|
||||
jne h_wrt_now
|
||||
mov al, READ_FROM_DISK
|
||||
jmps set_h_dma
|
||||
h_wrt_now:
|
||||
mov al, WRITE_TO_DISK
|
||||
set_h_dma:
|
||||
call set_disk_2_dma
|
||||
|
||||
; do the read or write
|
||||
cmp hard_op, H_READ_F
|
||||
jne h_wrt_now_1
|
||||
mov al, READ_DATA_F
|
||||
jmps h_do_rd_wt
|
||||
h_wrt_now_1:
|
||||
mov al, WRITE_DATA_F
|
||||
h_do_rd_wt:
|
||||
call send_command
|
||||
|
||||
; get the status byte and deal with any errors
|
||||
|
||||
call h_int_wait
|
||||
call stat_return
|
||||
test al, TIME_OUT or CRC_ERROR or OVER_RUN
|
||||
jnz h_rd_wt_err_1
|
||||
and al, SUCCESS
|
||||
jmp h_rd_wt_exit
|
||||
h_rd_wt_err_1:
|
||||
; stash the last return error code from the controller
|
||||
mov h_rd_wt_error_type, al
|
||||
; check the number of retries
|
||||
dec h_rd_wt_retries ! jnz rd_wt_retry_1
|
||||
; re-home the head after 5 retries
|
||||
dec re_homes ! jz re_home_1
|
||||
call h_home
|
||||
jmp re_home_lp
|
||||
re_home_1:
|
||||
mov ah,ATTA_FAILED
|
||||
mov al, RW_ERROR
|
||||
jmp h_rd_wt_exit
|
||||
rd_wt_retry_1:
|
||||
; if it's a crc_error or a data_over_run error just retry it
|
||||
test al, TIME_OUT! jnz rd_wt_retry_2
|
||||
jmp h_rd_wt_retry_lp
|
||||
rd_wt_retry_2:
|
||||
; must be a time out error, so check for the proper track
|
||||
mov bx, offset header_buffer_addr
|
||||
call read_header
|
||||
cmp al, SUCCESS! je check_track
|
||||
or al, RW_ERROR ; extented error set in read_header
|
||||
jmps h_rd_wt_exit
|
||||
check_track:
|
||||
; we h_rd_wt the header so check the track
|
||||
mov bx, h_rd_wt_param_add
|
||||
mov ax, TRACK_OFFSET[bx]
|
||||
mov bx, offset header_buffer
|
||||
; if the head is over the proper cyinder/track just retry
|
||||
cmp ax, TEST_CYLINDER[bx]! jne wrong_track
|
||||
jmp h_rd_wt_retry_lp
|
||||
wrong_track:
|
||||
; must have been over a wrong track.
|
||||
; so update last track and re-seek
|
||||
mov ax, TEST_CYLINDER[bx]
|
||||
mov last_cyl,ax
|
||||
mov bx, h_rd_wt_param_add
|
||||
mov ax, TRACK_OFFSET[bx]
|
||||
mov cyl,ax
|
||||
call seek
|
||||
jmp h_rd_wt_retry_lp
|
||||
h_rd_wt_exit:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
|
||||
|
||||
;=====
|
||||
h_home:
|
||||
;=====
|
||||
;
|
||||
; this routine will home the drive.
|
||||
; If the track 0 not signal is true we do nothing.
|
||||
; If it's false we try to home the heads.
|
||||
;
|
||||
; ENTRY: none
|
||||
;
|
||||
; EXIT: al = 0ffh on error
|
||||
; al = 000h if things went OK.
|
||||
; the zero flag refects al
|
||||
|
||||
|
||||
; if were on track 0 we don't have to home
|
||||
mov al, OP_DRIVE
|
||||
call send_command
|
||||
mov al, DRIVE_0
|
||||
call send_data
|
||||
call stat_return
|
||||
test al, TRACK0_NOT
|
||||
jz home_exit
|
||||
; we have do the home
|
||||
mov home_retries,RETRY_COUNT
|
||||
home_retry_lp:
|
||||
; first find out what track we're over
|
||||
mov bx, offset header_buffer_addr
|
||||
call read_header
|
||||
cmp al, SUCCESS ! je h_home_1
|
||||
dec home_retries
|
||||
jnz home_retry_lp
|
||||
or al, ERROR ; extended error set in read_header
|
||||
jmp home_exit
|
||||
h_home_1:
|
||||
; get the current cylinder
|
||||
xor ax,ax
|
||||
mov bx, offset header_buffer
|
||||
mov al, TEST_CYLINDER[bx]
|
||||
mov last_cyl, ax
|
||||
|
||||
; seek to cylinder 0
|
||||
mov cyl, 0
|
||||
call seek
|
||||
|
||||
call stat_return
|
||||
test al, TRACK0_NOT ! jz end_home_lp
|
||||
; try to issue the home command
|
||||
pushf! cli
|
||||
mov al, SEEK_OUTER ; set direction
|
||||
call send_command
|
||||
mov cx, HOME_COUNT ; and bang the port
|
||||
home_lp:
|
||||
in al, DISK_2_DATA ; over 256 reads from the data port
|
||||
loop home_lp ; at a rate between 3K and 3 Meg
|
||||
popf
|
||||
|
||||
mov dl, ( 15 * DELAY_16_MS ) ; wait for the hard disk to recover
|
||||
mov cl, DELAY_F ; about 250 ms
|
||||
call supif
|
||||
|
||||
call stat_return
|
||||
|
||||
test al,TRACK0_NOT ! jz end_home_lp
|
||||
; if we're still not over track 0
|
||||
; get away from the stop and try again
|
||||
mov cyl, 30
|
||||
call seek
|
||||
dec home_retries
|
||||
jnz home_retry_lp
|
||||
mov ah,SEEK_FAILED
|
||||
or al, ERROR
|
||||
end_home_lp:
|
||||
mov last_cyl, TRACK_0
|
||||
home_exit:
|
||||
|
||||
ret
|
||||
eject
|
||||
|
||||
read_header:
|
||||
;-----------
|
||||
;
|
||||
; This routine reads the three header bytes from the first sector
|
||||
; encountered on the track the head is over. In essence it just
|
||||
; drops the head and tells you the current cylinder, head, and sector.
|
||||
;
|
||||
; ENTRY: bx = &dma_add (dword)
|
||||
;
|
||||
; EXIT:
|
||||
; al = ERROR if the drive was not ready.
|
||||
; or if the header couldn't be ready with in
|
||||
; RETRY_COUNT attempts.
|
||||
; al = OK if every thing worked OK,
|
||||
; the address pointed to by bx on the way in
|
||||
; will contain the cylinder, head, and sector
|
||||
; for the currently selected drive.
|
||||
|
||||
mov rd_hdr_retries, RETRY_COUNT
|
||||
rd_hdr_retry_lp:
|
||||
|
||||
; set up the dma base and direction
|
||||
mov al, READ_FROM_DISK
|
||||
call set_disk_2_dma
|
||||
|
||||
rd_hdr_drv_rdy:
|
||||
mov al, READ_HEADER_F
|
||||
call send_command
|
||||
|
||||
call h_int_wait
|
||||
call stat_return
|
||||
|
||||
; check for no errors
|
||||
and al, TIME_OUT or CRC_ERROR or OVER_RUN
|
||||
test al,SUCCESS! jz exit_read_header
|
||||
; must have some sort of error
|
||||
dec rd_hdr_retries! jnz rd_hdr_retry_lp
|
||||
mov ah,al
|
||||
or al, ERROR
|
||||
test ah,TIME_OUT
|
||||
jz not_time_out
|
||||
mov ah,ATTA_FAILED
|
||||
jmps exit_read_header
|
||||
not_time_out:
|
||||
shr ah,1 ; convert to extended error
|
||||
exit_read_header:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
|
||||
seek:
|
||||
;----
|
||||
;
|
||||
; This routine seeks to the track passed in.
|
||||
; It does no error recovery. It expects the READ or Write routine
|
||||
; to take care of errors.
|
||||
;
|
||||
; ENTRY: cyl the cylinder we want to seek to.
|
||||
; last_cyl the last cylinder we were on.
|
||||
; The one the head should be over when we
|
||||
; enter this routine.
|
||||
; EXIT: there is no error code returned.
|
||||
; if there is an error in the seek operation, the corresponing
|
||||
; read or write will fail. When the corresponding read
|
||||
; or write tries to recover it will do the seeks again.
|
||||
|
||||
; Is the current cylinder the one we want.
|
||||
mov ax, cyl
|
||||
cmp ax, last_cyl! je exit_seek
|
||||
jg requested_cyl_greater
|
||||
sub last_cyl,ax ; the last cylinder was greater
|
||||
mov al, OUTTER ; set the direction twords the edge
|
||||
call send_command
|
||||
jmps seek_1
|
||||
requested_cyl_greater:
|
||||
xchg ax, last_cyl ; the cylinder we want is greater
|
||||
sub last_cyl,ax
|
||||
mov al, inner ; set the direction twords the spindle
|
||||
call send_command
|
||||
seek_1:
|
||||
mov cx, last_cyl ; last_cyl = abs( cyl - last_cyl )
|
||||
pushf! cli ; critical region
|
||||
seek_2:
|
||||
in al, DISK_2_DATA ; bang the step port
|
||||
loop seek_2
|
||||
popf
|
||||
|
||||
; set the null command and do a flag wait
|
||||
mov al, NULL_F
|
||||
call send_command
|
||||
|
||||
call h_int_wait
|
||||
call stat_return
|
||||
|
||||
mov ax,cyl ; update the cylinder register
|
||||
mov last_cyl,ax
|
||||
|
||||
; just to get back to here the seek must have happened.
|
||||
; the only action I can take at this time would be a sample
|
||||
; of the track field on the disk. This has to be done
|
||||
; by the read or write any way. So return.
|
||||
|
||||
exit_seek:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
|
||||
set_disk_2_dma:
|
||||
;--------------
|
||||
;
|
||||
; This routine sets the 24 bit dma from the dword
|
||||
; pointed to by Bx.
|
||||
;
|
||||
; ENTRY: al = mode byte for the selector channel
|
||||
; bx = &dma_add (dword)
|
||||
;
|
||||
; EXIT: the selector channel will have it's dma
|
||||
; set to the value passed in.
|
||||
|
||||
push ax
|
||||
|
||||
; just do a read of the selector channel to make it
|
||||
; ready for the subsequent writes
|
||||
in al, DISK_2_SELECT
|
||||
|
||||
; calculate the segment and offset into a 20 bit dma value
|
||||
mov dx, 2[bx]! mov ax,dx
|
||||
mov cl,4! shl ax,cl
|
||||
shr dh,cl
|
||||
add ax,[bx]
|
||||
adc dh,0
|
||||
|
||||
; send this three (3) byte dma value to the disk 2 selector channel
|
||||
mov dl, al
|
||||
in al, DISK_2_SELECT
|
||||
mov al,dh! out DISK_2_SELECT,al
|
||||
mov al,ah! out DISK_2_SELECT,al
|
||||
mov al,dl! out DISK_2_SELECT,al
|
||||
|
||||
; send the mode control byte to the selector channel
|
||||
pop ax
|
||||
out DISK_2_SELECT,al
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
|
||||
h_int_wait:
|
||||
;----------
|
||||
;
|
||||
; This routine waits for the interrupt
|
||||
;
|
||||
; ENTRY: none
|
||||
;
|
||||
; EXIT: none
|
||||
|
||||
jmps real_h_int
|
||||
|
||||
int_wait_lp:
|
||||
call stat_return
|
||||
test al, ATTN_NOT
|
||||
jnz int_wait_lp
|
||||
|
||||
jmp h_int_wait_exit
|
||||
|
||||
real_h_int:
|
||||
push ax! push bx! push cx! push dx
|
||||
push di! push si! push bp
|
||||
push es! push ds!
|
||||
|
||||
; turn on the disk 2's interrupt line
|
||||
|
||||
in al, ( MASTER_PIC_PORT + 1 ) ; read the PIC's int mask
|
||||
and al, not HD_IRL ; turn on the disk 2
|
||||
out ( MASTER_PIC_PORT + 1 ), al ; write the mask back out
|
||||
|
||||
mov dl, H_DISK_FLAG
|
||||
mov cl, F_FLAGWAIT
|
||||
call supif
|
||||
|
||||
pop ds! pop es
|
||||
pop bp! pop si! pop di
|
||||
pop dx! pop cx! pop bx! pop ax
|
||||
|
||||
h_int_wait_exit:
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
send_command:
|
||||
;------------
|
||||
;
|
||||
; this routine sends a command to the DISK2 controller
|
||||
;
|
||||
; ENTRY: al = command
|
||||
;
|
||||
; EXIT: none
|
||||
;
|
||||
; bx must be preserved
|
||||
|
||||
out STAT_CONTROL, al
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
send_data:
|
||||
;---------
|
||||
;
|
||||
; this routine sends a data byte to the DISK2 controller
|
||||
;
|
||||
; ENTRY: al = data byte
|
||||
;
|
||||
; EXIT: none
|
||||
;
|
||||
; NOTE: bx must be preserved
|
||||
|
||||
out DISK_2_DATA, al
|
||||
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
stat_return:
|
||||
;-----------
|
||||
;
|
||||
; this routine just returns the status from the disk controler
|
||||
;
|
||||
; ENTRY: none
|
||||
;
|
||||
; EXIT: al = current status from the disk controller
|
||||
|
||||
in al, STAT_CONTROL ; get the controler status
|
||||
|
||||
ret
|
||||
|
||||
rw 48
|
||||
h_disk_tos rw 0
|
||||
h_disk_ssreg rw 1
|
||||
h_disk_spreg rw 1
|
||||
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
h_rd_wt_error_type db 0
|
||||
|
||||
header_buffer_addr dw offset header_buffer
|
||||
dw 0
|
||||
|
||||
header_buffer db 0,0,0,0,0 ; should only need three
|
||||
|
||||
|
||||
eject
|
||||
|
||||
;
|
||||
; params for h_rd_wt
|
||||
|
||||
hard_op db 0
|
||||
|
||||
rw_track dw 0
|
||||
rw_head dw 0
|
||||
rw_sector dw 0
|
||||
rw_dma_off dw 0
|
||||
rw_dma_seg dw 0
|
||||
|
||||
;
|
||||
; these are the current retry counters
|
||||
|
||||
h_rd_wt_retries db 0
|
||||
re_homes db 0
|
||||
write_retries db 0
|
||||
rd_hdr_retries db 0
|
||||
home_retries db 0
|
||||
|
||||
;
|
||||
; The disk 2 controler wants a control word and delivers a status
|
||||
; word for each operation
|
||||
|
||||
disk2_control db 0
|
||||
disk2_status db 0
|
||||
|
||||
; BIT CTL STATUS
|
||||
; (write) (read)
|
||||
;--------------------------------------------------------
|
||||
; 7 attn_not attn_not
|
||||
; 6 run time out
|
||||
; 5 op2 crc error
|
||||
; 4 op1 over run
|
||||
; 3 op0 ready_not
|
||||
; 2 fault clr seek complete_not
|
||||
; 1 usr1 write fault_not
|
||||
; 0 usr0 track0_not
|
||||
;
|
||||
; where: _not indicates an active low signal
|
||||
|
||||
;
|
||||
; used by init and seek
|
||||
|
||||
last_cyl dw 0 ; the last cylinder we were on
|
||||
cyl dw 0 ; the current cylinder we want
|
||||
|
||||
h_rd_wt_param_add dw 0
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,456 @@
|
||||
title 'Xios Header and Entry'
|
||||
|
||||
|
||||
;********************************************************
|
||||
;********************************************************
|
||||
; *
|
||||
; CONCURRENT CP/M 3.1 *
|
||||
; *
|
||||
; SAMPLE XIOS FOR THE *
|
||||
; *
|
||||
; COMPUPRO 86/87. *
|
||||
; *
|
||||
; 2/17/84 *
|
||||
; *
|
||||
; *
|
||||
; Copyright (c) 1984 *
|
||||
; Digital Research, Inc. *
|
||||
; Box 579, Pacific Grove *
|
||||
; California, 93950 *
|
||||
; *
|
||||
; *
|
||||
; BY : *
|
||||
; JEFF NEWMAN *
|
||||
; FRAN BORDA *
|
||||
; GREG PACHNER *
|
||||
; *
|
||||
; This XIOS (Extended I/O System) was *
|
||||
; written as a sample . Whenever a choice *
|
||||
; had to be made between clarity and *
|
||||
; efficiency, clarity was chosen. Many of *
|
||||
; the modules could be made more efficient. *
|
||||
; *
|
||||
; *
|
||||
; To assemble and link the relocatable modules, *
|
||||
; refer to the CPROXIOS.SUB file. The format of *
|
||||
; XIOS.INP is as follows : *
|
||||
; *
|
||||
; *
|
||||
; xios = headentr[data[o[0]],m], *
|
||||
; intvec, pic, np_8087, ctc, tick, *
|
||||
; conout, serout, vscreen, conin, serin, *
|
||||
; ssint, i3int, servar, pcmode, *
|
||||
; statlin, list, switch, vccb, serdata, *
|
||||
; dentry, reskew, mdisk, dpbs, fd, hdisk *
|
||||
; *
|
||||
; *
|
||||
; *
|
||||
;********************************************************
|
||||
|
||||
|
||||
include system.lib
|
||||
include sysdat.lib
|
||||
|
||||
eject
|
||||
|
||||
cgroup group code, data ; this group definition forces an 8080
|
||||
; model when used with a link command
|
||||
; of xios = mod[data[o[0]]],mod2,mod3,...
|
||||
|
||||
dseg
|
||||
|
||||
public sysdat, dispatch
|
||||
|
||||
public dph_tbl
|
||||
public doorop
|
||||
public supervisor
|
||||
public debugflag
|
||||
public stoppoll
|
||||
public mem_alloc
|
||||
|
||||
extrn vccb0:byte, lcb0:byte
|
||||
|
||||
extrn dph1:byte, dph2:byte, dph3:byte
|
||||
extrn dph4:byte, dph5:byte, dpe5:byte
|
||||
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
; CONDITIONAL ASSEMBLY SWITCHES
|
||||
;---------------------------------------------------------------------
|
||||
|
||||
NP_8087 equ 1 ; does xios handle 8087
|
||||
; 1 = yes, 0 = no
|
||||
DEBUG equ 3 ; debug switch
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; END CONDITIONAL SWITCHES
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
|
||||
cseg
|
||||
|
||||
public supif
|
||||
public intdisp
|
||||
|
||||
extrn io_const:near ; public in char
|
||||
extrn io_conin:near ; public in char
|
||||
extrn io_conout:near ; public in char
|
||||
extrn io_listst:near ; public in char
|
||||
extrn io_list:near ; public in char
|
||||
;extrn io_auxin:near ; public in char
|
||||
;extrn io_auxout:near ; public in char
|
||||
extrn io_switch:near ; public in char
|
||||
extrn io_statline:near ; public in char
|
||||
|
||||
extrn io_seldsk:near ; public in dskrn
|
||||
extrn io_read:near ; public in dskrn
|
||||
extrn io_write:near ; public in dskrn
|
||||
extrn io_flushbuf:near ; public in dskrn
|
||||
|
||||
|
||||
;*******
|
||||
; PC_MODE SUPPORT
|
||||
;
|
||||
extrn io_screen:near ; public in pcmode
|
||||
extrn io_video:near ; public in pcmode
|
||||
extrn io_keybd:near ; public in pcmode
|
||||
extrn io_shft:near ; public in pcmode
|
||||
extrn io_eqck:near ; public in pcmode
|
||||
extrn io_int13_read:near ; public in pcmode
|
||||
extrn io_int13_write:near ; public in pcmode
|
||||
|
||||
;*******
|
||||
; INIT SUPPORT
|
||||
;
|
||||
extrn int_init:near ; in intvec
|
||||
extrn pic_init:near ; in pic
|
||||
extrn hard_int_vec:near ; in pic
|
||||
extrn int_enable:near ; in pic
|
||||
extrn ctc_init:near ; in ctc
|
||||
extrn char_init:near ; in chrinit
|
||||
extrn vs_init:near ; in vscreen
|
||||
extrn fdc_init:near ; in fd
|
||||
extrn h_init:near ; in hdisk
|
||||
extrn np_8087_test:near ; in np_8087
|
||||
|
||||
extrn pmsg:near ; in conout
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; XIOS ORIGIN AT C00
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
org 0c00h ; This org forces the XIOS to start at
|
||||
; offset 0C00H in the system data area.
|
||||
|
||||
jmp init ; Hardware and I/O system initialization
|
||||
jmp entry ; xios entry point
|
||||
|
||||
sysdat dw 0 ; Sysdat Segment
|
||||
supervisor rw 2
|
||||
|
||||
eject
|
||||
;------------------------------------------------------------------------
|
||||
; BEGIN XIOS HEADER
|
||||
;------------------------------------------------------------------------
|
||||
|
||||
; Location specific data structures defined by DRI
|
||||
|
||||
org 0c0ch
|
||||
|
||||
tick db false ; tick enable flag
|
||||
ticks_sec db 60 ; # of ticks per second
|
||||
doorop db 0 ; global door open interrupt flag
|
||||
db 0 ; reserved
|
||||
npcns db NPCONS ; number of physical consoles
|
||||
nvcns db NVCONS ; number of virtual consoles
|
||||
nccb db 8 ; total number of ccbs
|
||||
nlcb db 2 ; number of list devices
|
||||
ccb dw offset vccb0 ; offset of the first ccb
|
||||
lcb dw offset lcb0 ; offset of first lcb
|
||||
|
||||
; disk parameter header offset table. Location defined by DRI.
|
||||
|
||||
dph_tbl dw offset dph3 ;A: hard #0
|
||||
dw offset dph4 ;B: 1
|
||||
dw offset dph5 ;C: 2
|
||||
dw offset dph1 ;D: floppy #0
|
||||
dw offset dph2 ;E: 1
|
||||
dw 0,0,0 ;F:,G:,H:
|
||||
dw 0,0,0 ;I:,J:,K:
|
||||
dw 0 ;L:
|
||||
dw offset dpe5 ;M:
|
||||
dw 0,0,0 ;N:,O:,P:
|
||||
|
||||
mem_alloc dw 0800H ; buffer space for 8 virtual consoles
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; END XIOS HEADER
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; BEGIN MISC DEFINITIONS
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
dispatch rw 2 ; used by the I/O system as the entry
|
||||
; into the dispatcher.Intialized by
|
||||
; the XIOS init code.
|
||||
|
||||
debugflag db DEBUG ; 001h = clock tick not enabled
|
||||
; 002h = interrupt 3 not set to
|
||||
; the interrupt trap code.
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; END MISC DEFINITIONS
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
eject
|
||||
|
||||
;------------------------------------------------------------------------
|
||||
; BEGIN XIOS ENTRY POINT
|
||||
;------------------------------------------------------------------------
|
||||
|
||||
entry:
|
||||
|
||||
; All calls to the XIOS routines enter through here
|
||||
; with a CALLF. Must return with a RETF
|
||||
;
|
||||
; ENTRY: AL = function number
|
||||
; CX = parameter
|
||||
; DX = 2nd parameter
|
||||
; DS = system data
|
||||
; ES = user data area
|
||||
;
|
||||
; EXIT: AX = BX = return
|
||||
;
|
||||
cld
|
||||
xor ah,ah
|
||||
|
||||
cmp al,37
|
||||
jb ok
|
||||
|
||||
illegal:
|
||||
mov ax,0ffffh
|
||||
jmp exit
|
||||
|
||||
ok:
|
||||
shl ax,1 ;call routine
|
||||
mov bx,ax
|
||||
call functab[bx]
|
||||
|
||||
exit:
|
||||
mov bx, rlr
|
||||
mov es, P_UDA[bx]
|
||||
|
||||
mov bx,ax ;BX=AX
|
||||
retf ;All Done
|
||||
|
||||
reserved:
|
||||
mov ax,0ffffh
|
||||
ret
|
||||
|
||||
;----------------------------------------------------------------------
|
||||
; END XIOS ENTRY POINT
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
eject
|
||||
;----------------------------------------------------------------------
|
||||
; XIOS FUNCTION TABLE
|
||||
;----------------------------------------------------------------------
|
||||
|
||||
dseg
|
||||
|
||||
functab dw io_const ; 0 - console status
|
||||
dw io_conin ; 1 - console input
|
||||
dw io_conout ; 2 - console output
|
||||
dw io_listst ; 3 - list status
|
||||
dw io_list ; 4 - list output
|
||||
dw reserved ; 5 -
|
||||
dw reserved ; 6 -
|
||||
dw io_switch ; 7 - switch screen
|
||||
dw io_statline ; 8 - display status line
|
||||
dw io_seldsk ; 9 - select disk
|
||||
dw io_read ;10 - read
|
||||
dw io_write ;11 - write
|
||||
dw io_flushbuf ;12 - flush buffer
|
||||
dw io_polldev ;13 - poll device
|
||||
dw reserved ;14 - not presently used
|
||||
dw reserved ;15 - not presently used
|
||||
dw reserved ;16 - not presently used
|
||||
dw reserved ;17 - not presently used
|
||||
dw reserved ;18 - not presently used
|
||||
dw reserved ;19 - not presently used
|
||||
dw reserved ;20 - not presently used
|
||||
dw reserved ;21 - not presently used
|
||||
dw reserved ;22 - not presently used
|
||||
dw reserved ;23 - not presently used
|
||||
dw reserved ;24 - not presently used
|
||||
dw reserved ;25 - not presently used
|
||||
dw reserved ;26 - not presently used
|
||||
dw reserved ;27 - not presently used
|
||||
dw reserved ;28 - not presently used
|
||||
dw reserved ;29 - not presently used
|
||||
dw io_screen ;30 - get/set screen mode
|
||||
dw io_video ;31 - video i/o
|
||||
dw io_keybd ;32 - keyboard info
|
||||
dw io_shft ;33 - shift status
|
||||
dw io_eqck ;34 - equipment check
|
||||
dw io_int13_read ;35 - read DOS disk
|
||||
dw io_int13_write ;36 - write DOS disk
|
||||
|
||||
|
||||
stoppoll db 0
|
||||
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
; BEGIN SUPERVISOR INTERFACE
|
||||
;--------------------------------------------------------------------------
|
||||
cseg
|
||||
|
||||
supif: ; Supervisor Interface
|
||||
;
|
||||
; ENTRY: CX = function #
|
||||
; DX = parameter
|
||||
; DS = parameter segment if address
|
||||
; ES = user data area
|
||||
; EXIT: BX = AX = return
|
||||
; CX = error code for RTM functions
|
||||
; ES = return segment if address
|
||||
|
||||
push es
|
||||
mov bx,rlr
|
||||
mov es,p_uda[bx]
|
||||
xor ch,ch
|
||||
callf cs:dword ptr supervisor
|
||||
pop es
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; END SUPERVISOR INTERFACE
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; BEGIN XIOS INITIALIZATION
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
cseg
|
||||
|
||||
;====
|
||||
init: ; CCP/M's XIOS initialization entry point
|
||||
;====
|
||||
;
|
||||
cli ;disable interrupts
|
||||
mov sysdat,ds ; save sysdat for sysdat access
|
||||
mov ax,supmod ; place copy of SUPMOD in data segment
|
||||
mov supervisor,ax ; into Code Segment (supervisor)
|
||||
mov ax,supmod+2
|
||||
mov supervisor+2,ax
|
||||
|
||||
mov ax,dispatcher ; Make copy of Interrupt Routines' access
|
||||
mov dispatch,ax ; point to dispatcher
|
||||
mov ax,dispatcher+2
|
||||
mov dispatch+2,ax
|
||||
|
||||
mov int_ssreg,ss ; establish the stack
|
||||
mov int_spreg,sp
|
||||
cld ; set forward direction
|
||||
mov ax, ds ; ES = SS = DS
|
||||
mov es, ax
|
||||
mov ss, ax ; establish a stack for init
|
||||
mov sp,offset int_tos
|
||||
|
||||
call int_init ; paint all the interrupt vectors
|
||||
; and poke the NMI and BREAK vectors
|
||||
; ( int 2 and int 3 )
|
||||
|
||||
call hard_int_vec ; initialize the hardware interrupt vectors
|
||||
|
||||
call char_init ; initialize the char I/O system
|
||||
|
||||
call pic_init ; initialize the interrupt system hardware
|
||||
|
||||
call ctc_init ; initialize the counter timer
|
||||
|
||||
call vs_init ; initialize the virtual screens
|
||||
|
||||
call int_enable ; turn on the interrupt system masks in the PIC's
|
||||
|
||||
sti ; turn on the CPU's interrupt system
|
||||
|
||||
call fdc_init ; initialize the floppy disk system
|
||||
|
||||
call h_init ; initialize the hard disk system
|
||||
|
||||
if NP_8087
|
||||
call np_8087_test ; checks if 8087 is present
|
||||
endif
|
||||
|
||||
call signon
|
||||
mov ss,int_ssreg ; restore stack for the far return
|
||||
mov sp,int_spreg
|
||||
mov bx, rlr ; restore ES
|
||||
mov es, P_UDA[bx]
|
||||
retf ; back to CCP/M's init process
|
||||
|
||||
dseg
|
||||
|
||||
|
||||
rw 48 ; initialzation stack
|
||||
int_tos rw 0
|
||||
int_ssreg rw 1
|
||||
int_spreg rw 1
|
||||
|
||||
;-----------------------------------------------------------------------
|
||||
; END XIOS INITIALIZATION
|
||||
;-----------------------------------------------------------------------
|
||||
|
||||
;-----------------------------------------------------------------------
|
||||
; BEGIN MISC ROUTINES
|
||||
;-----------------------------------------------------------------------
|
||||
|
||||
cseg
|
||||
|
||||
;-------
|
||||
intdisp:
|
||||
;-------
|
||||
jmpf cs:dword ptr dispatch
|
||||
|
||||
;==========
|
||||
io_polldev: ; Function 13: Poll Device
|
||||
;==========
|
||||
;
|
||||
; ENTRY: DL = device number
|
||||
;
|
||||
; EXIT: AL = 000h if not ready
|
||||
; = 0ffh if ready
|
||||
|
||||
ret
|
||||
|
||||
ptch:
|
||||
;-----
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
nop ! nop ! nop ! nop ! nop ! nop
|
||||
|
||||
|
||||
signon:
|
||||
mov bx, offset signon_m
|
||||
call pmsg
|
||||
ret
|
||||
|
||||
dseg
|
||||
|
||||
signon_m db 0ah,0dh
|
||||
db 'CompuPro XIOS of 2/14/84',0ah,0dh,0ffh
|
||||
|
||||
;-----------------------------------------------------------------------
|
||||
; END MISC ROUTINES
|
||||
;-----------------------------------------------------------------------
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
;************************************************
|
||||
;* Interfacer 3 board euqate module *
|
||||
;* File Name: I3BOARD.EQU *
|
||||
;* Last Update: 10/11/83 *
|
||||
;************************************************
|
||||
|
||||
; Interfacer 3 board port definitions
|
||||
|
||||
i3_base equ 10h ; base addr of board
|
||||
i3_uart_data equ i3_base ; usart data port
|
||||
i3_uart_status equ i3_base + 1 ; usart status port
|
||||
i3_uart_mode equ i3_base + 2 ; usart mode port
|
||||
i3_uart_cmd equ i3_base + 3 ; usart command port
|
||||
i3_xmit_int_stat equ i3_base + 4 ; I3 Xmit Interrupt status
|
||||
i3_xmit_int_mask equ i3_base + 4 ; I3 Xmit Interrupt mask
|
||||
i3_rcv_int_stat equ i3_base + 5 ; I3 Recv Interrupt status
|
||||
i3_rcv_int_mask equ i3_base + 5 ; I3 Recv Interrupt mask
|
||||
i3_select_reg equ i3_base + 7 ; I3 Usart Select register
|
||||
|
||||
|
||||
; The I3 board has two Interrupt mask registers to control which
|
||||
; usarts (0-7) interrupt systems are enabled.
|
||||
; One mask register is for Xmit the other for Recv.
|
||||
; When the interrupt mask ports are read, they act as status ports.
|
||||
; A Usart that has its interrupt disabled will have a 0 in its
|
||||
; corresponding bit position. Usart 0 = bit 0, Usart 7 = bit 7.
|
||||
; The quiescent state is: All receiver interrupts are enabled. An
|
||||
; Xmit interrupt is only enabled when the Xmitter is in use.
|
||||
|
||||
I3_INT_ENABLE equ 0ffH ; receive interrupt mask
|
||||
|
||||
; The following equates are for the Xmit Q control stuctures.
|
||||
|
||||
OFLAG equ byte ptr 1 ; Queue control flags
|
||||
OUSART equ byte ptr 8 ; Usart number
|
||||
O_BIT_MASK equ byte ptr 10 ; Usarts Int register mask bit
|
||||
|
||||
; Flag bit(s) for OFLAG field in Xmit Q control structure
|
||||
|
||||
XOFF_PENDING equ 10H ; set = Xoff received from the guy
|
||||
; were sending data to.
|
||||
|
||||
; The following equates are for the Recv Q control stucture
|
||||
|
||||
U_NUMB equ byte ptr 10 ; Usarts number
|
||||
CMD_REG equ byte ptr 3 ; Usart command register image
|
||||
U_PORTC equ byte ptr 11 ; Usart Command port
|
||||
XINT_MASK equ byte ptr 14 ; Bit(s) used as the Xmit ready mask
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
|
||||
title 'I3 interrupt entry'
|
||||
|
||||
;************************************************
|
||||
; *
|
||||
; INTERFACER 3 BOARD MODULE *
|
||||
; Last changed : 2/10/84 *
|
||||
; *
|
||||
;************************************************
|
||||
|
||||
include i3board.equ
|
||||
|
||||
dseg
|
||||
|
||||
extrn icdesctbl:word
|
||||
extrn ocdesctbl:word
|
||||
extrn i3_xmit_int_vec:byte
|
||||
extrn bit_mask_tbl:byte
|
||||
|
||||
cseg
|
||||
|
||||
public i3r_int
|
||||
public i3t_int
|
||||
extrn sysdat:word
|
||||
extrn reset_i3iint_pic:near
|
||||
extrn reset_i3tint_pic:near
|
||||
extrn store_char:near
|
||||
extrn xmit_on:near
|
||||
extrn xmit_off:near
|
||||
extrn intco:near
|
||||
|
||||
;;=======
|
||||
i3t_int: ; Interfacer 3 transmit interrupt entry
|
||||
;;=======
|
||||
;;
|
||||
;; ENTRY: from the interfacer 3's transmit ready interrupt line.
|
||||
;; The interfacer 3's interrupt status register has
|
||||
;; a bit set for each USART whose transmit buffer is empty.
|
||||
;;
|
||||
;; I3_xmit_int_vec contains a bit vector of the USARTS on
|
||||
;; Interfacer 3 that we have characters for.
|
||||
;;
|
||||
;; EXIT: back to the process we interrupted
|
||||
;;
|
||||
;; NOTE: All the USART's Xmit interrupts are wire ORed together
|
||||
;;
|
||||
push ds
|
||||
mov ds,sysdat
|
||||
|
||||
mov i3_out_int_ss,ss
|
||||
mov i3_out_int_sp,sp
|
||||
mov ss,sysdat
|
||||
mov sp,offset i3_out_int_tos
|
||||
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
|
||||
co_test_lp:
|
||||
mov al, 0 ;; We have to select a usart before
|
||||
out I3_SELECT_REG, al ;; we can query the board, see page 9
|
||||
;; of the interfacer 3 manual
|
||||
mov ah, i3_xmit_int_vec ;; bit vector of expected interrupts
|
||||
mov bx, offset bit_mask_tbl ;; byte mask for each Xmit interrupt
|
||||
mov cx, 8 ;; length of bit mask table
|
||||
co_lp:
|
||||
test ah, [bx]
|
||||
jz co_lp_1
|
||||
in al, I3_XMIT_INT_STAT ;; Get the board's interrupt status
|
||||
test al, [bx] ;; Is this the interrupt we expect ?
|
||||
jnz co_found_it
|
||||
co_lp_1:
|
||||
inc bx ;; point to the next mask
|
||||
loop co_lp ;; check all the USARTS
|
||||
jmp co_exit
|
||||
|
||||
co_found_it: ;; cx = the USART number that interrupted us
|
||||
mov bx, offset ocdesctbl ;; base of Xmit Q table
|
||||
shl cx, 1
|
||||
add bx, cx ;; index into the table
|
||||
mov bx, [bx] ;; bx -> Xmit Q ctl Structure
|
||||
call intco ;; send the character
|
||||
|
||||
jmps co_test_lp ;; In case another interrupt came in
|
||||
;; while we were doing this one, check
|
||||
;; the interrupt status again.
|
||||
|
||||
co_exit:
|
||||
call reset_i3tint_pic
|
||||
pop dx ;; restore the environment
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
mov ss, i3_out_int_ss ;; restore the stack
|
||||
mov sp, i3_out_int_sp
|
||||
|
||||
pop ds ;; restore the data segment
|
||||
|
||||
iret ;; back to the process we interrupted
|
||||
|
||||
|
||||
;
|
||||
;interfacer 3 output interrupt stack area
|
||||
|
||||
rw 32
|
||||
i3_out_int_tos:
|
||||
rw 0
|
||||
i3_out_int_ss rw 1
|
||||
i3_out_int_sp rw 1
|
||||
|
||||
|
||||
;;-----------
|
||||
i3r_int: ;; Interfacer 3 receive interrupt entry
|
||||
;;---------
|
||||
;;
|
||||
;; ENTRY: from an interrupt
|
||||
|
||||
push ds ;; establish a local data segment
|
||||
mov ds, sysdat
|
||||
|
||||
mov i3r_sss, ss ;; save the stack we came in on
|
||||
mov i3r_sps, sp
|
||||
mov ss, sysdat ;; and establish our own local stack
|
||||
mov sp, offset i3r_tos
|
||||
|
||||
push ax ;; save the reg's we need for
|
||||
push bx ;; the interrupt handler
|
||||
|
||||
mov al, 0 ;; We have to select a USART on the
|
||||
out I3_SELECT_REG, al ;; interfacer 3 before we can query
|
||||
;; the interrupt status register.
|
||||
;; see page 9 of the interfacer 3
|
||||
;; manual
|
||||
|
||||
in al, I3_RCV_INT_STAT ;; read the interfacer 3's
|
||||
;; interrupt status
|
||||
call res_usart ;; find which USART interrupted us
|
||||
mov bx, ax ;; save the usart's number
|
||||
|
||||
out I3_SELECT_REG, al ;; select the USART
|
||||
in al, I3_UART_STATUS ;; get the status
|
||||
mov ah, al
|
||||
in al, I3_UART_DATA ;; and the data
|
||||
push ax ;; store the status and data
|
||||
|
||||
call reset_i3iint_pic
|
||||
|
||||
xor bh, bh ;; clear the high byte of the index
|
||||
inc bx ;; usart 0 in table is the SS board
|
||||
shl bx, 1 ;; word table
|
||||
mov bx, icdesctbl[bx] ;; bx -> USART q
|
||||
|
||||
pop ax ;; retrieve the usart's status and data
|
||||
call store_char ;; process the character
|
||||
pop bx ;; restore the cpu registers
|
||||
pop ax
|
||||
|
||||
cli ;; entering a critical region
|
||||
mov ss, i3r_sss ;; restore the stack
|
||||
mov sp, i3r_sps
|
||||
|
||||
pop ds ;; restore the data segment
|
||||
|
||||
iret
|
||||
|
||||
|
||||
res_usart:
|
||||
;;---------
|
||||
;;
|
||||
;; This routine does a binary search for the bit representing the USART
|
||||
;; that interrupted us.
|
||||
;;
|
||||
;; ENTRY: al = the interfacer 3's receive interrupt status byte
|
||||
;;
|
||||
;; EXIT: al = the number of usart whose bit is set
|
||||
;;
|
||||
;; NOTE: This routine only uses ax and the flags
|
||||
|
||||
test al, 0FH
|
||||
jnz low_nibble
|
||||
test al, 30H ;; one of the bits in the upper nibble
|
||||
jz u_half
|
||||
test al,10H ;; in the lower half of the upper nibble
|
||||
jnz u_4
|
||||
mov al, 5 ;; USART 5
|
||||
jmps ux
|
||||
u_4:
|
||||
mov al,4 ;; USART 4
|
||||
jmps ux
|
||||
u_half:
|
||||
test al, 40H ;; it's either bit 6 or 7
|
||||
jnz u_6
|
||||
mov al, 7 ;; USART 7
|
||||
jmps ux
|
||||
u_6:
|
||||
mov al, 6 ;; USART 6
|
||||
jmps ux
|
||||
low_nibble:
|
||||
test al, 03H ;; one of the bits in the lower nibble
|
||||
jz u_half1
|
||||
test al, 01H ;; in the lower half of the lower nibble
|
||||
jnz u_0
|
||||
mov al, 1 ;; USART 1
|
||||
jmps ux
|
||||
u_0:
|
||||
mov al,0 ;; USART 0
|
||||
jmps ux
|
||||
u_half1:
|
||||
test al, 04H ;; it's either usart 2 or 3
|
||||
jnz u_2
|
||||
mov al, 3 ;; USART 3
|
||||
jmps ux
|
||||
u_2:
|
||||
mov al,2 ;; USART 2
|
||||
ux:
|
||||
ret
|
||||
|
||||
|
||||
i3r_sss dw 0 ; interfacer 3 receive stack segment save
|
||||
i3r_sps dw 0 ; interfacer 3 receive stack offset save
|
||||
rw 40
|
||||
i3r_tos:
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
title 'Software Interrupt Init & Handlers'
|
||||
|
||||
include system.lib
|
||||
include sysdat.lib
|
||||
|
||||
include flags.equ
|
||||
|
||||
OVEC1 equ 1 * 4 ;; Equates for SID's interrupt vector.
|
||||
SVEC1 equ OVEC1 + 2 ;; They are used during initialization.
|
||||
|
||||
OVEC3 equ 3 * 4
|
||||
SVEC3 equ OVEC3 + 2
|
||||
|
||||
OVECE1 equ 0E1H * 4
|
||||
SVECE1 equ OVECE1 + 2
|
||||
|
||||
LOW_NIBBLE EQU 0FH ;; used by outbyte
|
||||
|
||||
dseg
|
||||
|
||||
extrn debugflag:byte
|
||||
|
||||
cseg
|
||||
|
||||
public nmiint, int_init
|
||||
|
||||
extrn sysdat:word
|
||||
extrn supif:near
|
||||
extrn dispatch:dword
|
||||
extrn pmsg:near
|
||||
|
||||
;;======
|
||||
nmiint:
|
||||
;;======
|
||||
;;
|
||||
;; Non-maskable interrupt handler
|
||||
;;
|
||||
;; This handler sets a flag when an NMI is executed.
|
||||
;; A process is expected to be sleeping on this flag.
|
||||
|
||||
push ds ;; establish a data segment
|
||||
mov ds, sysdat
|
||||
|
||||
mov nmi_ssreg,ss ;; establish a stack
|
||||
mov nmi_spreg,sp
|
||||
mov ss,sysdat
|
||||
mov sp,offset nmi_tos
|
||||
|
||||
push ax ! push bx ;; save the environment
|
||||
push cx ! push dx
|
||||
push di ! push si
|
||||
push bp ! push es
|
||||
|
||||
mov dx, nmi_flag ;; wake up the sleeping NMI
|
||||
mov cl, f_flagset ;; process
|
||||
call supif
|
||||
|
||||
pop es ! pop bp ;; restore the environment
|
||||
pop si ! pop di
|
||||
pop dx ! pop cx
|
||||
pop bx ! pop ax
|
||||
|
||||
mov ss,nmi_ssreg ;; restore the stack
|
||||
mov sp,nmi_spreg
|
||||
|
||||
pop ds ;; restore the data segment
|
||||
|
||||
jmpf cs:dispatch ;; exit through the dispatcher
|
||||
|
||||
eject
|
||||
|
||||
|
||||
int_trap: ;;unknown interrupts go here ...
|
||||
;;-------
|
||||
;;
|
||||
;; We will terminate the process that caused this
|
||||
;; after writing a message to the process's default
|
||||
;; console. If the process is in KEEP mode, we will
|
||||
;; force it to terminate anyway...
|
||||
;;
|
||||
;; We don't need to save any registers since we are
|
||||
;; not going to return to the process.
|
||||
|
||||
mov ds,sysdat
|
||||
;; print first 6 chars of PD Name
|
||||
mov bx,rlr ;; get the PD
|
||||
add bx,p_name ;; get the process name
|
||||
mov byte ptr 6[bx],':' ;; step on the process name
|
||||
mov byte ptr 7[bx],0ffh
|
||||
call pmsg ;; print the first 6 letters
|
||||
|
||||
;; calculate and print the
|
||||
;; Illegal Interrupt message
|
||||
pop ax ;; get the addr of the int 3
|
||||
sub ax,offset int_work + 1 ;; subtract from this addr
|
||||
;; the base of the INT 3 table
|
||||
mov bx,offset int_trpcode ;; point to where the ascii will go
|
||||
call outbyte ;; convert the int number to ascii
|
||||
mov bx,offset int_trp ;; print the message
|
||||
call pmsg
|
||||
;; terminate process
|
||||
mov bx,rlr ;; get the PD
|
||||
and p_flag[bx], not pf_keep ;; turn off the process's keep flag
|
||||
mov cx,f_terminate ;; set the terminate code
|
||||
mov dx,0ffffh ;; free its memory
|
||||
int 224 ;; go to the system
|
||||
|
||||
hlt ;; this instruction should
|
||||
;; never execute
|
||||
|
||||
|
||||
outbyte:
|
||||
;;-------
|
||||
;; ENTRY: al = binary of an unsigned byte
|
||||
;; bx = where to put the ascii
|
||||
;;
|
||||
;; EXIT: [bx] = ascii of high nibble of byte
|
||||
;; [bx+1] = ascii of low nibble of byte
|
||||
|
||||
push ax ;; save the byte
|
||||
mov di, bx ;; save where to put the ascii
|
||||
mov bx, offset xlate_tbl
|
||||
mov cl, 4
|
||||
|
||||
shr al, cl ;; move the high nibble into place
|
||||
xlat xlate_tbl ;; translate the highest nibble
|
||||
mov [di], al ;; stash it, di -> destination
|
||||
inc di ;; next ascii position
|
||||
|
||||
pop ax ;; get the byte back
|
||||
and al, LOW_NIBBLE ;; mask out the upper nibble
|
||||
xlat xlate_tbl ;; tanslate the lower nibble
|
||||
mov [di], al ;; di -> destination
|
||||
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
;;========
|
||||
int_init:
|
||||
;;========
|
||||
;;
|
||||
;; Un-initialized interrupt initialization
|
||||
;;
|
||||
|
||||
cli ;; interrupts should be off on entry,but...
|
||||
;; setup an INT 3 for each possible interrupt
|
||||
|
||||
mov cx,256 ;; # of interrupt vectors
|
||||
mov di,offset int_work ;; base of the INT 3 table
|
||||
mov al,0cch ;; opcode for INT 3
|
||||
rep stosb ;; store INT 3 in interrupt table
|
||||
|
||||
push ds ;; Setup all interrupt vectors in low
|
||||
xor ax,ax ;; memory to their respective INT 3 in the INT 3 table
|
||||
mov ds,ax ;; set DS to zero
|
||||
;; save SID's interrupt vectors
|
||||
mov ax, word ptr .OVEC1 ;; vector 1
|
||||
mov es:vec1_off, ax
|
||||
mov ax, word ptr.SVEC1
|
||||
mov es:vec1_seg, ax
|
||||
|
||||
mov ax, word ptr.OVEC3 ;; vector 3
|
||||
mov es:vec3_off, ax
|
||||
mov ax, word ptr.SVEC3
|
||||
mov es:vec3_seg, ax
|
||||
|
||||
mov ax, word ptr.OVECE1 ;; vector E1
|
||||
mov es:vece1_off, ax
|
||||
mov ax, word ptr.SVECE1
|
||||
mov es:vece1_seg, ax
|
||||
|
||||
xor di,di ;; start with vector 0
|
||||
mov bx,offset int_work ;; bx -> base of interrupt 3 table
|
||||
mov cx,256 ;; cx = # of interrupt vectors
|
||||
setint:
|
||||
mov word ptr [di],bx ;; interrupt vector offset
|
||||
mov word ptr 2[di],cs ;; interrupt vector segment (INT 3 table)
|
||||
|
||||
add di,004H ;; next vector
|
||||
inc bx ;; next table entry
|
||||
loop setint ;; initialize all the int vectors ...
|
||||
|
||||
mov word ptr .0008h,offset nmiint
|
||||
mov word ptr .000ah,cs ;; initialize the NMI
|
||||
|
||||
;; if we're in a debugging environment put sids interrupt vectors
|
||||
;; back. If we're not in an interrupt environment then make
|
||||
;; the interrupt 3 vector point to the un-initialized interrupt
|
||||
;; handler.
|
||||
|
||||
test es:debugflag, 002H ;; do we want to put SID'S vector back ?
|
||||
jz set_int_trap ;; no ...
|
||||
|
||||
mov ax, es:vec1_off ;; yes, do vector 1
|
||||
mov word ptr .OVEC1, ax
|
||||
mov ax, es:vec1_seg
|
||||
mov word ptr .SVEC1, ax
|
||||
|
||||
mov ax, es:vec3_off ;; vector 3
|
||||
mov word ptr .OVEC3, ax
|
||||
mov ax, es:vec3_seg
|
||||
mov word ptr .SVEC3, ax
|
||||
|
||||
mov ax, es:vece1_off ;; vector E1
|
||||
mov word ptr .OVECE1, ax
|
||||
mov ax, es:vece1_seg
|
||||
mov word ptr .SVECE1, ax
|
||||
|
||||
jmps intie
|
||||
|
||||
set_int_trap:
|
||||
;; point to our trap.
|
||||
mov word ptr .OVEC3, offset int_trap ;; setup INT 3's offset
|
||||
mov word ptr .SVEC3, cs ;; and segment
|
||||
intie:
|
||||
pop ds ;; restore the data segment
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
nmi_tos rw 80
|
||||
nmi_ssreg rw 1 ;; nonmaskable interrupt stack
|
||||
nmi_spreg rw 1
|
||||
nmi_instk rb 1
|
||||
|
||||
rw 48 ;; tick's interrupt stack
|
||||
tick_tos rw 0
|
||||
tick_ssreg rw 1
|
||||
tick_spreg rw 1
|
||||
|
||||
;; this translate table is used by outbyte
|
||||
;; to translate from binary to ascii
|
||||
xlate_tbl db '0123456789ABCDEF'
|
||||
|
||||
;; this message is printed by the uninitialized interrupt
|
||||
;; routine.
|
||||
int_trp db ' Uninitialized interrupt, code = 0'
|
||||
int_trpcode db 'xxH',0dh,0ah,0ffh
|
||||
|
||||
|
||||
;; SID's interrupt vectors are stored
|
||||
;; here during initialization.
|
||||
vec1_off dw 0 ;; interrupt vector 1
|
||||
vec1_seg dw 0
|
||||
|
||||
vec3_off dw 0 ;; interrupt vector 3
|
||||
vec3_seg dw 0
|
||||
|
||||
vece1_off dw 0 ;; interrupt vector E1
|
||||
vece1_seg dw 0
|
||||
|
||||
;; scratch area
|
||||
;;
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
dw 0cccch,0cccch,0cccch
|
||||
|
||||
;; Int 3 table for the unintialized interrupts
|
||||
int_work rb 256 ;;interrupt vector routines
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
title 'List Device module'
|
||||
|
||||
;******************************************
|
||||
; *
|
||||
; LIST DEVICE MODULE *
|
||||
; Last changed : 1/30/84 *
|
||||
; *
|
||||
;******************************************
|
||||
|
||||
dseg
|
||||
|
||||
public lcb0
|
||||
|
||||
extrn oq7desc:byte
|
||||
extrn oq8desc:byte
|
||||
|
||||
cseg
|
||||
|
||||
public io_listst, io_list
|
||||
|
||||
extrn serial_out:near
|
||||
|
||||
;=========
|
||||
io_listst: ; Function 3: List Status
|
||||
;=========
|
||||
; input: DL = list device number
|
||||
; output: AL = 0ffh if ready
|
||||
; = 000h if not ready
|
||||
|
||||
xor al,al
|
||||
ret ;back to caller
|
||||
|
||||
;=======
|
||||
io_list: ; Function 4: List Output
|
||||
;=======
|
||||
; input: CL = character
|
||||
; dl = list device number
|
||||
; output: None
|
||||
|
||||
cmp dl, 0 ! je list0
|
||||
mov bx, offset oq7desc
|
||||
jmps list1
|
||||
list0:
|
||||
mov bx, offset oq8desc
|
||||
list1:
|
||||
call serial_out
|
||||
|
||||
ret
|
||||
|
||||
dseg
|
||||
|
||||
lcb0 dw 0,0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
|
||||
lcb1 dw 0,0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
title 'M disk module'
|
||||
include diskhdr.equ
|
||||
|
||||
MDISKBASE EQU 6000H
|
||||
|
||||
cseg
|
||||
|
||||
public read_m_dsk, write_m_dsk
|
||||
|
||||
read_m_dsk:
|
||||
;----------
|
||||
call mdisk_calc ;calculate byte address
|
||||
push es ;save UDA
|
||||
les di,dword ptr dmaoff ;load destination DMA address
|
||||
xor si,si ;setup source DMA address
|
||||
push ds ;save current DS
|
||||
mov ds,bx ;load pointer to sector in memory
|
||||
rep movsw ;execute move of 128 bytes....
|
||||
pop ds ;then restore user DS register
|
||||
pop es ;restore UDA
|
||||
xor ax,ax ;return with good return code
|
||||
ret
|
||||
|
||||
write_m_dsk:
|
||||
;-----------
|
||||
call mdisk_calc ;calculate byte address
|
||||
push es ;save UDA
|
||||
mov es,bx ;setup destination DMA address
|
||||
xor di,di
|
||||
push ds ;save user segment register
|
||||
lds si,dword ptr dmaoff ;load source DMA address
|
||||
rep movsw ;move from user to disk in memory
|
||||
pop ds ;restore user segment pointer
|
||||
pop es ;restore UDA
|
||||
xor ax,ax ;return no error
|
||||
ret
|
||||
|
||||
|
||||
mdisk_calc:
|
||||
;----------
|
||||
; output: BX = sector paragraph address
|
||||
; CX = length in words to transfer
|
||||
|
||||
mov bx,track ;pickup track number
|
||||
mov cl,3 ;times eight for relative sector number
|
||||
shl bx,cl
|
||||
mov cx,sector ;plus sector
|
||||
add bx,cx ;gives relative sector number
|
||||
mov cl,3 ;times eight for paragraph of sector start
|
||||
shl bx,cl
|
||||
add bx,mdiskbase+1 ;plus base address of disk in memory
|
||||
mov cx,64 ;length for move of 1 sector
|
||||
mov al,mcnt
|
||||
xor ah,ah
|
||||
mul cx ;length * multi sector count
|
||||
mov cx,ax
|
||||
cld
|
||||
ret
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
title '8087 module'
|
||||
|
||||
;******************************************
|
||||
; *
|
||||
; 8087 MODULE *
|
||||
; Last changed : 1/30/84 *
|
||||
; *
|
||||
;******************************************
|
||||
|
||||
|
||||
cseg
|
||||
|
||||
public np_8087_int ; extrn in pic.a86
|
||||
public np_8087_test
|
||||
|
||||
extrn sysdat:word ; public in header.a86
|
||||
extrn reset_8087_pic:near ; public in pic.a86
|
||||
|
||||
|
||||
NP_8087_OFF equ 0120H ; interrupt vector offset (COMPUPRO)
|
||||
|
||||
NP_8087_OWNER equ 08cH ; 8087 owner(SYSDAT)
|
||||
|
||||
IV_SEG_8087 equ 0a2H ; address of Interrupt Vector for
|
||||
IV_OFF_8087 equ 0a0H ; interupt handler (SYSDAT)
|
||||
|
||||
IH_SEG_8087 equ 0a6H ; address of system's interrupt
|
||||
IH_OFF_8087 equ 0a4H ; handler (SYSDAT)
|
||||
|
||||
status equ byte ptr 02H ; status word location in 8087
|
||||
; environment
|
||||
p_flag equ word ptr 06H ; PD flag field
|
||||
|
||||
pf_keep equ 02H ; KEEP bit in p_flag
|
||||
pf_term equ 80H ; TERMINATE bit in p_flag
|
||||
|
||||
severe equ 05H ; Zero divide and invalid operation
|
||||
|
||||
;========
|
||||
np_8087_int:
|
||||
;========
|
||||
;
|
||||
push ds ; setup the system's date segment
|
||||
mov ds, sysdat
|
||||
|
||||
mov np_8087_ss, ss ; establish a stack
|
||||
mov np_8087_sp, sp
|
||||
mov ss, sysdat
|
||||
mov sp, offset np_8087_tos
|
||||
|
||||
push ax ; save registers that we
|
||||
push bx ; will be using
|
||||
push si
|
||||
|
||||
|
||||
FNSTENV np_8087_env ; save 8087 environment
|
||||
FCLEX
|
||||
FDISI
|
||||
call reset_8087_pic ; COMPUPRO specific
|
||||
|
||||
; We can now check what 8087 exception caused the interrupt
|
||||
|
||||
mov bx, word ptr .NP_8087_OWNER
|
||||
test bx,bx ; has owner already terminated
|
||||
jz exit1 ; yes
|
||||
mov si, offset np_8087_env
|
||||
mov al, status[si]
|
||||
test al, not severe ; Is it a severe error
|
||||
jnz exit1 ; no
|
||||
and p_flag[bx],not pf_keep ; terminate user even if
|
||||
or p_flag[bx],pf_term ; keep flag was on
|
||||
|
||||
exit1:
|
||||
|
||||
;
|
||||
|
||||
mov status[si],0H ; Clear status word for env. restore
|
||||
|
||||
pop si
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
mov ss, np_8087_ss
|
||||
mov sp, np_8087_sp
|
||||
|
||||
FLDENV np_8087_env ; restore 8087
|
||||
FWAIT
|
||||
|
||||
pop ds
|
||||
iret
|
||||
|
||||
|
||||
;========
|
||||
np_8087_test:
|
||||
;========
|
||||
;
|
||||
; Checks for presence of 8087 and place a zero in np_8087_owner
|
||||
; location of SYSDAT if 8087 is present. The SUP init routine
|
||||
; has placed 0ffffH there as the default of no 8087.
|
||||
;
|
||||
|
||||
FNINIT ; init to see if 8087 is present
|
||||
FSTCW control ; get 8087 control word
|
||||
mov bx, NP_8087_OWNER
|
||||
xor ax,ax
|
||||
FWAIT ; let 8087 finish
|
||||
or ax,control ; is 8087 present
|
||||
jz exit2 ; no
|
||||
|
||||
mov word ptr [bx],0 ; record that 8087 is present
|
||||
|
||||
mov bx, IV_SEG_8087 ; init SYSDAT with segment and
|
||||
mov word ptr [bx],0 ; offset of interrupt vector for
|
||||
mov bx, IV_OFF_8087 ; 8087 exception handler
|
||||
mov word ptr [bx], NP_8087_OFF
|
||||
|
||||
mov bx, IH_SEG_8087 ; init SYSDAT with segment and
|
||||
mov word ptr [bx],ds ; offset of system's execption handler
|
||||
mov bx, IH_OFF_8087
|
||||
mov word ptr [bx], offset np_8087_int
|
||||
exit2:
|
||||
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
rw 18H ; Local stack
|
||||
np_8087_tos:
|
||||
np_8087_ss rw 1
|
||||
np_8087_sp rw 1
|
||||
|
||||
np_8087_env rw 7 ; 8087 environment stored here
|
||||
control rw 1 ; control word for test stored here
|
||||
|
||||
end
|
||||
@@ -0,0 +1,213 @@
|
||||
;
|
||||
; PC_MODE SUPPORT
|
||||
;
|
||||
|
||||
include system.lib
|
||||
include flags.equ
|
||||
include serdata.equ
|
||||
|
||||
;DOS_HEAD equ byte ptr 13[BP]
|
||||
;DOS_TRACK equ byte ptr 12[BP]
|
||||
;DOS_SECTOR equ byte ptr 10[BP]
|
||||
|
||||
;TRACK equ word ptr 12[BP]
|
||||
;SECTOR equ word ptr 10[BP]
|
||||
|
||||
|
||||
CSEG
|
||||
|
||||
public io_screen
|
||||
public io_video
|
||||
public io_keybd
|
||||
public io_shft
|
||||
public io_eqck
|
||||
public io_int13_read
|
||||
public io_int13_write
|
||||
|
||||
extrn io_read:near, io_write:near
|
||||
extrn supif:near
|
||||
|
||||
DSEG
|
||||
|
||||
public f30_tbl
|
||||
|
||||
extrn ocdesctbl:word
|
||||
extrn vrtl_phy:byte
|
||||
|
||||
CSEG
|
||||
|
||||
;=========
|
||||
io_screen: ;FUNCTION 30 -- get/set screen mode
|
||||
;=========
|
||||
;
|
||||
; ENTRY: CH -- 0 = set, 1 = get
|
||||
; CL -- Mode if CH = 0
|
||||
; DL -- Virtual console number
|
||||
;
|
||||
; EXIT: AX -- Mode if CH = 1. If CH = 0, then 0000H for success.
|
||||
;
|
||||
|
||||
xor bx,bx
|
||||
mov bl,dl ; Vcon index
|
||||
|
||||
cmp ch,0 ; check mode
|
||||
jz set
|
||||
|
||||
;
|
||||
; Get the screen mode
|
||||
;
|
||||
shl bx,1
|
||||
mov ax,f30_tbl[bx]
|
||||
;
|
||||
ret
|
||||
|
||||
set:
|
||||
;
|
||||
; Set the screen mode
|
||||
;
|
||||
mov dx,cx ; save mode
|
||||
and cx,000fH ; get alphanumeric mode
|
||||
cmp cx,0
|
||||
jz set_grphc
|
||||
|
||||
mov dx,cx
|
||||
call set_mode
|
||||
ret
|
||||
|
||||
set_grphc:
|
||||
and dx,00f0H
|
||||
call set_mode
|
||||
cmp dx,10H
|
||||
jne set_exit
|
||||
|
||||
; Handle GSX with care
|
||||
|
||||
shr bx,1
|
||||
mov dx,bx ; Vcon number
|
||||
mov bl,vrtl_phy[bx] ; Pcon number
|
||||
shl bx,1
|
||||
mov bx,ocdesctbl[bx] ; bx -> Xmit Queue control
|
||||
|
||||
pushf
|
||||
cli
|
||||
|
||||
cmp dl,CUR_VCON[bx] ; are we in foreground
|
||||
je int_exit ; no need to do flagwait
|
||||
|
||||
; F L A G W A I T until we get put into foreground
|
||||
|
||||
add dl,v_flag
|
||||
mov cl,f_flagwait
|
||||
call supif
|
||||
|
||||
int_exit:
|
||||
popf
|
||||
|
||||
set_exit:
|
||||
mov ax,0
|
||||
ret
|
||||
|
||||
set_mode:
|
||||
; entry: BX has Vcon number, DL new mode
|
||||
;
|
||||
;
|
||||
|
||||
shl bx,1
|
||||
mov cx,word ptr f30_tbl[bx]
|
||||
mov cl,dl
|
||||
mov word ptr f30_tbl[bx],cx ; update f30_tbl
|
||||
|
||||
;
|
||||
ret
|
||||
|
||||
;========
|
||||
io_video: ;FUNCTION 31 -- video i/o
|
||||
;========
|
||||
;========
|
||||
io_keybd: ;FUNCTION 32 -- keyboard information
|
||||
;========
|
||||
;=======
|
||||
io_shft: ;FUNCTION 33 -- shift status
|
||||
;=======
|
||||
;=======
|
||||
io_eqck: ;FUNCTION 34 -- equipment check
|
||||
;=======
|
||||
mov ax,0ffffh
|
||||
ret
|
||||
|
||||
|
||||
;=============
|
||||
io_int13_read: ;FUNCTION 35 -- read DOS disk
|
||||
;=============
|
||||
;
|
||||
; ENTRY: DOS IOPB on stack
|
||||
;
|
||||
; EXIT: CCP/M IOPB on stack
|
||||
;
|
||||
|
||||
; Since 5 and 1/4" dependent programs would only use this routine,
|
||||
; and we have 8" drives, we will return an error.
|
||||
|
||||
mov ax,0ffffH
|
||||
ret
|
||||
|
||||
; mov bp,sp
|
||||
;
|
||||
; xor ah,ah
|
||||
; mov al,DOS_SECTOR
|
||||
; dec ax ; DOS field 1 relative CCP/M 0 relative
|
||||
; mov SECTOR,ax
|
||||
;
|
||||
; mov al,DOS_TRACK
|
||||
; shl ax,1 ; CCP/M TRACK = DOS_TRACK*2 + DOS_HEAD
|
||||
; xor bh,bh
|
||||
; mov bl,DOS_HEAD
|
||||
; add ax,bx
|
||||
; mov TRACK,ax
|
||||
;
|
||||
; jmp io_read
|
||||
|
||||
|
||||
;==============
|
||||
io_int13_write: ;FUNCTION 36 -- write DOS disk
|
||||
;==============
|
||||
;
|
||||
; ENTRY: DOS IOPB on stack
|
||||
;
|
||||
; EXIT: CCP/M IOPB on stack
|
||||
;
|
||||
|
||||
; Since 5 and 1/4" dependent programs would only use this routine,
|
||||
; and we have 8" drives, we will return an error.
|
||||
|
||||
mov ax,0ffffH
|
||||
ret
|
||||
|
||||
; mov bp,sp
|
||||
;
|
||||
; xor ah,ah
|
||||
; mov al,DOS_SECTOR
|
||||
; dec ax ; DOS field 1 relative CCP/M 0 relative
|
||||
; mov SECTOR,ax
|
||||
;
|
||||
; mov al,DOS_TRACK
|
||||
; shl ax,1 ; CCP/M TRACK = DOS_TRACK*2 + DOS_HEAD
|
||||
; xor bh,bh
|
||||
; mov bl,DOS_HEAD
|
||||
; add ax,bx
|
||||
; mov TRACK,ax
|
||||
;
|
||||
; jmp io_write
|
||||
|
||||
DSEG
|
||||
|
||||
f30_tbl dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
dw 1801h
|
||||
|
||||
end
|
||||
@@ -0,0 +1,354 @@
|
||||
title 'Hardware Interrupts'
|
||||
|
||||
;****************************************
|
||||
; *
|
||||
; HARDWARE INTERRUPTS *
|
||||
; Last changed : 2/16/84 *
|
||||
; *
|
||||
;****************************************
|
||||
|
||||
NP_8087 equ 1 ; will xios support 8087
|
||||
; 1 -- yes
|
||||
; 0 -- no
|
||||
CPMDEBUG equ 1 ; 1 = turn off I3 int's for debug envir.
|
||||
; 0 = I3 int's are on - normal envir.
|
||||
MASTER_PIC_PORT equ 50H
|
||||
SLAVE_PIC_PORT equ 52H
|
||||
|
||||
; Specific End Of Interrupt Commands
|
||||
|
||||
CI0_EOI EQU 67H ; Specific EOI master/slave
|
||||
CO0_EOI EQU 66H ; Specific EOI master/slave
|
||||
I3_CI_EOI EQU 62H ; Specific EOI master only
|
||||
I3_CO_EOI EQU 63H ; Specific EOI master only
|
||||
|
||||
HD_EOI EQU 61H ; specific eoi master only
|
||||
FLPY_EOI EQU 64H ; Specific EOI master only
|
||||
TICK_EOI EQU 61H ; Specific EOI master/slave
|
||||
NP_8087_EOI EQU 60H ; Specific EOI master/slave
|
||||
|
||||
SLAVE_EOI EQU 67H ; Specific EOI master only
|
||||
|
||||
DISABLE_INTS EQU 0FFH ; mask to turn off all interrupts
|
||||
|
||||
MASTER_INT_MASK EQU 063H ; floppies, transmit and
|
||||
; receive for interfacer 3,
|
||||
; and slave pic
|
||||
|
||||
SLAVE_INT_MASK EQU 07CH ; receive interrupts, 8087
|
||||
; and the timer tick
|
||||
|
||||
NS_EOI EQU 20H ; Non specific end of interrupt
|
||||
|
||||
|
||||
MASTER_ICW_1 EQU 1DH ; basic operational mode of chip
|
||||
|
||||
MASTER_ICW_2 EQU 40H ; base of chips interrupt vectors
|
||||
|
||||
MASTER_ICW_3 EQU 80H ; master/slave map
|
||||
|
||||
MASTER_ICW_4 EQU 01H ; interrupt response mode
|
||||
|
||||
|
||||
SLAVE_ICW_1 EQU MASTER_ICW_1
|
||||
|
||||
SLAVE_ICW_2 EQU MASTER_ICW_2 + 8
|
||||
|
||||
SLAVE_ICW_3 EQU 07H ; slave I.D. number
|
||||
|
||||
SLAVE_ICW_4 EQU MASTER_ICW_4
|
||||
|
||||
I3_INT_ENABLE EQU 0FFH
|
||||
|
||||
|
||||
; Character interrupt vectors
|
||||
;
|
||||
|
||||
MASTER_INT_BASE equ 40H
|
||||
|
||||
SLAVE_INT_BASE equ 48H
|
||||
|
||||
CONIN_IR equ 7 ; on the slave
|
||||
CONOUT_IR equ 6 ; on the slave
|
||||
|
||||
I3_IN_IR equ 2 ; on the master
|
||||
I3_OUT_IR equ 3 ; on the master
|
||||
|
||||
HD_IR equ 1 ; on the master
|
||||
FLPY_IR equ 4 ; on the master
|
||||
TICK_IR equ 1 ; on the slave
|
||||
NP_8087_IR equ 0 ; on the slave
|
||||
|
||||
|
||||
CON_IN_OFF EQU ( SLAVE_INT_BASE + CONIN_IR ) * 4
|
||||
CON_IN_SEG EQU CON_IN_OFF + 2
|
||||
|
||||
CON_OUT_OFF EQU ( SLAVE_INT_BASE + CONOUT_IR ) * 4
|
||||
CON_OUT_SEG EQU CON_OUT_OFF + 2
|
||||
|
||||
I3_IN_OFF EQU ( MASTER_INT_BASE + I3_IN_IR ) * 4
|
||||
I3_IN_SEG EQU I3_IN_OFF + 2
|
||||
|
||||
I3_OUT_OFF EQU ( MASTER_INT_BASE + I3_OUT_IR ) * 4
|
||||
I3_OUT_SEG EQU I3_OUT_OFF + 2
|
||||
|
||||
FLPY_OFF EQU ( MASTER_INT_BASE + FLPY_IR ) * 4
|
||||
FLPY_SEG EQU FLPY_OFF + 2
|
||||
|
||||
H_DISK_OFF EQU ( MASTER_INT_BASE + HD_IR ) * 4
|
||||
H_DISK_SEG EQU H_DISK_OFF + 2
|
||||
|
||||
TICK_OFF EQU ( SLAVE_INT_BASE + TICK_IR ) * 4
|
||||
TICK_SEG EQU TICK_OFF + 2
|
||||
|
||||
NP_8087_OFF EQU ( SLAVE_INT_BASE + NP_8087_IR ) * 4
|
||||
NP_8087_SEG EQU NP_8087_OFF + 2
|
||||
|
||||
|
||||
cseg
|
||||
|
||||
public hard_int_vec
|
||||
public pic_init
|
||||
public int_enable
|
||||
public reset_tick_pic
|
||||
public reset_sstint_pic
|
||||
public reset_i3tint_pic
|
||||
public reset_ssiint_pic
|
||||
public reset_i3iint_pic
|
||||
|
||||
extrn conin_int:near
|
||||
extrn sst_int:near ; public in ssint.a86
|
||||
extrn i3r_int:near
|
||||
extrn i3t_int:near ; public in i3int.a86
|
||||
extrn h_disk_int:near ; public in hdisk.a86
|
||||
extrn flint:near ; public in fd.a86
|
||||
extrn tick_int:near ; public in tick.a86
|
||||
|
||||
if NP_8087
|
||||
|
||||
extrn np_8087_int:near
|
||||
public reset_8087_pic
|
||||
|
||||
endif
|
||||
|
||||
;==============
|
||||
reset_tick_pic:
|
||||
;==============
|
||||
;
|
||||
; reset the PIC for the tick.
|
||||
|
||||
mov al, SLAVE_EOI
|
||||
out MASTER_PIC_PORT, al
|
||||
mov al, TICK_EOI
|
||||
out SLAVE_PIC_PORT, al
|
||||
ret
|
||||
|
||||
if NP_8087
|
||||
|
||||
;=============
|
||||
reset_8087_pic:
|
||||
;=============
|
||||
;
|
||||
; reset the PIC for the 8087
|
||||
|
||||
mov al, SLAVE_EOI
|
||||
out MASTER_PIC_PORT, al
|
||||
mov al, NP_8087_EOI
|
||||
out SLAVE_PIC_PORT, al
|
||||
ret
|
||||
|
||||
endif
|
||||
|
||||
;=============
|
||||
reset_ssiint_pic:
|
||||
;=============
|
||||
; Reset System Support Board's PIC for receive
|
||||
;
|
||||
mov al, SLAVE_EOI ;; clear the PICS for this interrupt
|
||||
out MASTER_PIC_PORT, al ;; request channel
|
||||
mov al, CI0_EOI
|
||||
out SLAVE_PIC_PORT, al
|
||||
ret
|
||||
|
||||
|
||||
;===============
|
||||
reset_sstint_pic:
|
||||
;===============
|
||||
;
|
||||
; Reset System support board USART's PIC for transmit
|
||||
|
||||
mov al, SLAVE_EOI ;; reset the PIC's
|
||||
out MASTER_PIC_PORT,al
|
||||
mov al, CO0_EOI
|
||||
out SLAVE_PIC_PORT,al
|
||||
ret
|
||||
|
||||
|
||||
;================
|
||||
reset_i3tint_pic:
|
||||
;================
|
||||
;
|
||||
; Reset the interfacer 3's PIC IR line
|
||||
|
||||
mov al, I3_CO_EOI ;; reset the PIC
|
||||
out MASTER_PIC_PORT,al
|
||||
ret
|
||||
|
||||
;================
|
||||
reset_i3iint_pic:
|
||||
;================
|
||||
; Reset Interfacer 3's PIC
|
||||
|
||||
mov al, I3_CI_EOI ;; reset the interfacer 3's PIC
|
||||
out MASTER_PIC_PORT, al ;; interrupt line
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;========
|
||||
pic_init:
|
||||
;========
|
||||
;
|
||||
; PIC initialization entry point
|
||||
;
|
||||
; interrupt structure
|
||||
;
|
||||
; MASTER PIC :
|
||||
; IRQ0 =
|
||||
; IRQ1 = DISK 2
|
||||
; IRQ2 = interfacer 3 receive ready
|
||||
; IRQ3 = interfacer 3 transmit ready
|
||||
; IRQ4 = DISK 1
|
||||
; IRQ5 =
|
||||
; IRQ6 =
|
||||
; IRQ7 = Slave input
|
||||
;
|
||||
; SLAVE PIC :
|
||||
; IRQ0 = 8087
|
||||
; IRQ1 = Timer 0 ( mpm's tick )
|
||||
; IRQ2 = Timer 1 ( free )
|
||||
; IRQ3 = Timer 2 ( free )
|
||||
; IRQ4 = 9511 svrq
|
||||
; IRQ5 = 9511 end
|
||||
; IRQ6 = SS Tx int
|
||||
; IRQ7 = SS Rx int
|
||||
;
|
||||
; DETAILS about the interrupt structure
|
||||
;
|
||||
; For both the master and the slave:
|
||||
; 1] 8086 mode
|
||||
; 2] the interrupt system is level-triggered
|
||||
; 3] all interrupts are masked off after the PICs are initialized
|
||||
;
|
||||
; The Master PIC:
|
||||
; 1] pic interrupt base is 40H
|
||||
; 2] IR 7 is a slave input
|
||||
;
|
||||
; The Slave PIC:
|
||||
; 1] pic interrupt base is at 48H
|
||||
|
||||
mov al,MASTER_ICW_1 ;set up the master PIC
|
||||
out MASTER_PIC_PORT, al
|
||||
|
||||
mov al,MASTER_ICW_2
|
||||
out MASTER_PIC_PORT + 1,al
|
||||
|
||||
mov al,MASTER_ICW_3
|
||||
out MASTER_PIC_PORT + 1, al
|
||||
|
||||
mov al,MASTER_ICW_4
|
||||
out MASTER_PIC_PORT + 1, al
|
||||
|
||||
mov al,DISABLE_INTS
|
||||
out MASTER_PIC_PORT + 1, al
|
||||
|
||||
mov al,SLAVE_ICW_1 ; set up the slave PIC
|
||||
out SLAVE_PIC_PORT, al
|
||||
|
||||
mov al,SLAVE_ICW_2
|
||||
out SLAVE_PIC_PORT + 1,al
|
||||
|
||||
mov al,SLAVE_ICW_3
|
||||
out SLAVE_PIC_PORT + 1, al
|
||||
|
||||
mov al,SLAVE_ICW_4
|
||||
out SLAVE_PIC_PORT + 1, al
|
||||
|
||||
mov al, DISABLE_INTS
|
||||
out SLAVE_PIC_PORT + 1, al
|
||||
|
||||
ret
|
||||
|
||||
;==========
|
||||
int_enable:
|
||||
;==========
|
||||
;
|
||||
; Interrupt enable entry point
|
||||
;
|
||||
; The hard disk, and all usart transmitters are not
|
||||
; enabled until they are needed.
|
||||
|
||||
mov al, MASTER_INT_MASK
|
||||
out MASTER_PIC_PORT + 1, al
|
||||
|
||||
mov al,SLAVE_INT_MASK
|
||||
out SLAVE_PIC_PORT + 1, al
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;============
|
||||
hard_int_vec:
|
||||
;============
|
||||
;
|
||||
; Hardware interrupt vector initialization entry point
|
||||
;
|
||||
|
||||
; set DS to the interrupt vector area
|
||||
push ds ; save incoming DS
|
||||
xor ax,ax ; point to the vectors
|
||||
mov ds, ax
|
||||
; setup character i/o interrupt addr
|
||||
; console input slave irq 7 ( int 4fh )
|
||||
mov word ptr .CON_IN_OFF, offset conin_int
|
||||
mov word ptr .CON_IN_SEG, cs
|
||||
|
||||
; console output slave irq 6 ( int 4eh )
|
||||
mov word ptr .CON_OUT_OFF, offset sst_int
|
||||
mov word ptr .CON_OUT_SEG, cs
|
||||
|
||||
; interfacer 3 input master irq 2 ( int 42h )
|
||||
mov word ptr .I3_IN_OFF, offset i3r_int
|
||||
mov word ptr .I3_IN_SEG, cs
|
||||
|
||||
; interfacer 3 output master irq 3 ( int 43h )
|
||||
mov word ptr .I3_OUT_OFF, offset i3t_int
|
||||
mov word ptr .I3_OUT_SEG, cs
|
||||
|
||||
; setup hard disk i/o interrupt addr
|
||||
mov word ptr .H_DISK_OFF, offset h_disk_int
|
||||
mov word ptr .H_DISK_SEG, cs
|
||||
|
||||
; setup floppy disk i/o interrupt addr (VI5)
|
||||
mov word ptr .FLPY_OFF, offset flint
|
||||
mov word ptr .FLPY_SEG, cs
|
||||
|
||||
; setup tick interrupt addr
|
||||
mov word ptr .TICK_OFF, offset tick_int
|
||||
mov word ptr .TICK_SEG, cs
|
||||
|
||||
if NP_8087
|
||||
|
||||
; setup 8087 interrupt addr
|
||||
mov word ptr .NP_8087_OFF, offset NP_8087_int
|
||||
mov word ptr .NP_8087_SEG, cs
|
||||
|
||||
endif
|
||||
pop ds ; restore the data segment
|
||||
|
||||
ret
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
title 'Unskew / Reskew'
|
||||
|
||||
include exerror.equ
|
||||
include system.lib
|
||||
include diskhdr.equ
|
||||
|
||||
FIRST_CALL_FLAG equ 01H
|
||||
|
||||
dseg
|
||||
|
||||
extrn disk_modes:byte
|
||||
|
||||
cseg
|
||||
|
||||
public read_write
|
||||
|
||||
extrn current_reskew:word
|
||||
extrn io_select:near
|
||||
extrn idrive:byte, itrack:word, isector:byte,idmaoff:word, idmaseg:word
|
||||
|
||||
;----------
|
||||
read_write: ;unskews and reads or writes multi sectors
|
||||
;----------
|
||||
;
|
||||
; input: SI = read or write routine address
|
||||
;
|
||||
; output: AX = return code
|
||||
|
||||
|
||||
mov cl, idrive
|
||||
mov dl, FIRST_CALL_FLAG ; this is not the first select
|
||||
call io_select ;get DPH address
|
||||
or bx,bx! jnz dsk_ok ;check if valid
|
||||
ret_error:
|
||||
mov ah,ATTA_FAILED
|
||||
mov al,1 ; return error if not
|
||||
ret
|
||||
dsk_ok:
|
||||
mov ax,xlt[bx]
|
||||
mov xltbl,ax ;save translation table address
|
||||
mov bx,dpb[bx]
|
||||
push bx
|
||||
xor bx,bx
|
||||
mov bl,idrive
|
||||
mov bl,disk_modes[bx]
|
||||
cmp bl,0 ; Is this a CCP/M DPB?
|
||||
pop bx
|
||||
jz yes1
|
||||
add bx,12 ; add offset to make DOS DPB look like CCP/M
|
||||
yes1:
|
||||
mov ax,spt[bx]
|
||||
mov maxsec,ax ;save maximum sector per track
|
||||
mov cl,psh[bx]
|
||||
mov ax,128
|
||||
shl ax,cl ;compute physical record size
|
||||
mov secsiz,ax ; and save it
|
||||
call initdmatbl ;initialize dma offset table
|
||||
cmp mcnt,0
|
||||
je rw_sects
|
||||
rw_1:
|
||||
mov ax,sector ;is sector < max sector/track
|
||||
cmp ax,maxsec! jb same_trk
|
||||
call rw_sects ; no - read/write sectors on track
|
||||
call initdmatbl ; reinitialize dma offset table
|
||||
inc track ; next track
|
||||
xor ax,ax
|
||||
mov sector,ax ; initialize sector to 0
|
||||
same_trk:
|
||||
mov bx,xltbl ;get translation table address
|
||||
or bx,bx! jz no_trans ;if xlt <> 0
|
||||
xlat al ; translate sector number
|
||||
no_trans:
|
||||
xor bh,bh
|
||||
mov bl,al ;sector # is used as the index
|
||||
shl bx,1 ; into the dma offset table
|
||||
mov ax,dmaoff
|
||||
mov dmatbl[bx],ax ;save dma offset in table
|
||||
add ax,secsiz ;increment dma offset by the
|
||||
mov dmaoff,ax ; physical sector size
|
||||
inc sector ;next sector
|
||||
dec mcnt ;decrement multi sector count
|
||||
jnz rw_1 ;if mcnt <> 0 store next sector dma
|
||||
rw_sects: ;read/write sectors in dma table
|
||||
mov ah,DMA_OVERRUN
|
||||
mov al,1 ;preset error code
|
||||
xor bx,bx ;initialize sector index
|
||||
rw_s1:
|
||||
cmp current_reskew, 0
|
||||
je no_reskew
|
||||
push bx! push ax
|
||||
mov ax, bx
|
||||
mov bx, current_reskew
|
||||
mov ah, 0
|
||||
xlat al
|
||||
mov di, ax
|
||||
pop ax! pop bx
|
||||
jmps re_skew_1
|
||||
no_reskew:
|
||||
mov di,bx
|
||||
re_skew_1:
|
||||
shl di,1 ;compute index into dma table
|
||||
cmp word ptr dmatbl[di],0ffffh
|
||||
je no_rw ;nop if invalid entry
|
||||
push bx! push si ;save index and routine address
|
||||
mov ax,track ;get track # from IOPB
|
||||
mov itrack,ax
|
||||
mov ax,di ;sector # is index value
|
||||
shr ax, 1
|
||||
mov isector,al
|
||||
mov ax,dmatbl[di] ;get dma offset from table
|
||||
mov idmaoff,ax
|
||||
mov ax,dmaseg ;get dma segment from IOPB
|
||||
mov idmaseg,ax
|
||||
call si ;call read/write routine
|
||||
pop si! pop bx ;restore routine address and index
|
||||
or al,al! jnz err_ret ;if error occured return
|
||||
no_rw:
|
||||
inc bx ;next sector index
|
||||
cmp bx,maxsec ;if not end of table
|
||||
jb rw_s1 ; go read/write next sector
|
||||
err_ret:
|
||||
|
||||
ret ;return with error code in AL
|
||||
|
||||
eject
|
||||
|
||||
initdmatbl: ;initialize DMA offset table
|
||||
;----------
|
||||
mov di,offset dmatbl
|
||||
mov cx,maxsec ;length = maxsec + 1 sectors may
|
||||
inc cx ; index relative to 0 or 1
|
||||
mov ax,0ffffh
|
||||
push es ;save UDA
|
||||
push ds! pop es
|
||||
rep stosw ;initialize table to 0ffffh
|
||||
pop es ;restore UDA
|
||||
ret
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* DISK DATA AREA
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
xltbl dw 0 ;translation table address
|
||||
maxsec dw 0 ;max sectors per track
|
||||
secsiz dw 0 ;sector size
|
||||
dmatbl rw 50 ;dma address table
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
|
||||
title 'Serial Data Structures'
|
||||
|
||||
;***************************************************
|
||||
; *
|
||||
; SERIAL IO DATA STRUCTURES MODULE *
|
||||
; Last changed : 2/15/84 *
|
||||
; *
|
||||
;***************************************************
|
||||
|
||||
include serdata.equ
|
||||
include flags.equ
|
||||
include chrcomm.equ
|
||||
|
||||
eject
|
||||
|
||||
public ciqctl
|
||||
public icdesctbl
|
||||
public ocdesctbl
|
||||
public oq0desc
|
||||
public oq7desc
|
||||
public oq8desc
|
||||
|
||||
cgroup group code, data, siq_seg
|
||||
|
||||
cseg
|
||||
|
||||
extrn conin_0:near
|
||||
|
||||
dseg
|
||||
|
||||
icdesctbl dw ciqctl ; 0 system support usart
|
||||
dw ci1qctl ; 1 interfacer 3 usart 0
|
||||
dw 0 ; 2 interfacer 3 usart 1
|
||||
dw 0 ; 3 interfacer 3 usart 2
|
||||
dw 0 ; 4 interfacer 3 usart 3
|
||||
dw 0 ; 5 interfacer 3 usart 4
|
||||
dw 0 ; 6 interfacer 3 usart 5
|
||||
dw ci7qctl ; 7 interfacer 3 usart 6
|
||||
dw ci8qctl ; 8 interfacer 3 usart 7
|
||||
|
||||
eject
|
||||
|
||||
siq_seg dseg para
|
||||
|
||||
; Q control structure for main system console
|
||||
|
||||
ciqctl db C0IN_F ; System flag
|
||||
dw 0 ; Q status
|
||||
db 27H ; Command register image
|
||||
dw 0 ; un-processed characters
|
||||
dw 0 ; interrupt side input Q index
|
||||
dw 0 ; processes side output Q index
|
||||
db SS_U ; Usart number ( System support board code )
|
||||
db 05fH ; Usart command port
|
||||
db 05dH ; Usart status port
|
||||
db 05cH ; Usart data port
|
||||
db SS_U ; transmitter interrupt mask
|
||||
dw 0 ; input escape Q index
|
||||
dw 0 ; output escape Q index
|
||||
db 0 ; last char read from Q
|
||||
db 0 ; last status byte read from Q
|
||||
dw conin_0 ; current state for this console
|
||||
db 0 ; physical console number
|
||||
db 0 ; virtual console number
|
||||
db 0 ; error reset count
|
||||
rb 06H ; pad
|
||||
rb 10H ; the state machines escape Q
|
||||
rb 80H ; the usarts data Q
|
||||
rb 80H ; the usarts status Q
|
||||
|
||||
; Q control structure for 2nd physical console
|
||||
; It is USART 0 on the Interfacer 3 board.
|
||||
|
||||
ci1qctl db C1IN_F ; system flag
|
||||
dw 0 ; Q status
|
||||
db 27H ; Command register image
|
||||
dw 0 ; un-processed characters
|
||||
dw 0 ; interrupt side input Q index
|
||||
dw 0 ; processes side output Q index
|
||||
db 00H ; Usart number ( System support board code )
|
||||
db 013H ; Usart command port
|
||||
db 011H ; Usart status port
|
||||
db 010H ; Usart data port
|
||||
db US_0 ; transmitter interrupt mask
|
||||
dw 0 ; input escape Q index
|
||||
dw 0 ; output escape Q index
|
||||
db 0 ; last char read from Q
|
||||
db 0 ; last status byte read from Q
|
||||
dw conin_0 ; current state for this console
|
||||
db 0 ; physical console number
|
||||
db 0 ; virtual console number
|
||||
db 0 ; error reset count
|
||||
rb 06H ; pad
|
||||
rb 10H ; the state machines escape Q
|
||||
rb 80H ; the usarts data Q
|
||||
rb 80H ; the usarts status Q
|
||||
|
||||
; Q control structure for printer 1.
|
||||
; 6th USART on the system support board.
|
||||
; 8th bit in data byte is masked off.
|
||||
|
||||
ci7qctl db c7IN_F
|
||||
dw 0014H ; Q status
|
||||
db 27H ; Command register image
|
||||
dw 0 ; un-processed characters
|
||||
dw 0 ; last char read from Q
|
||||
db 0 ; Last status byte read from Q
|
||||
dw conin_0 ; current state for this console
|
||||
db 0 ; physical cons #
|
||||
db 0 ; virtual console #
|
||||
db 0 ; error reset count
|
||||
rb 6h ; pad
|
||||
rb 10h ; state machine escape Q
|
||||
rb 80h ; usart data q
|
||||
rb 80h ; usart status q
|
||||
|
||||
; Q control structure for printer 0.
|
||||
; 7th USART on the system support board.
|
||||
; This Q is set up for Xon Xoff protocol.
|
||||
; 8th bit in data byte is masked off.
|
||||
|
||||
ci8qctl db C8IN_F ; system flag
|
||||
dw 0014H ; Q status
|
||||
db 27H ; Command register image
|
||||
dw 0 ; un-processed characters
|
||||
dw 0 ; interrupt side input Q index
|
||||
dw 0 ; processes side output Q index
|
||||
db 07H ; Usart number ( System support board code )
|
||||
db 013H ; Usart command port
|
||||
db 011H ; Usart status port
|
||||
db 010H ; Usart data port
|
||||
db US_7 ; transmitter interrupt mask
|
||||
dw 0 ; input escape Q index
|
||||
dw 0 ; output escape Q index
|
||||
db 0 ; last char read from Q
|
||||
db 0 ; last status byte read from Q
|
||||
dw conin_0 ; current state for this console
|
||||
db 0 ; physical console number
|
||||
db 0 ; virtual console number
|
||||
db 0 ; error reset count
|
||||
rb 06H ; pad
|
||||
rb 10H ; the state machines escape Q
|
||||
rb 80H ; the usarts data Q
|
||||
rb 80H ; the usarts status Q
|
||||
|
||||
|
||||
;***********************************************************
|
||||
; *
|
||||
; OUTPUT DATA CONTROL STRUCTURES *
|
||||
; *
|
||||
;***********************************************************
|
||||
|
||||
cgroup group soq_seg
|
||||
|
||||
dseg
|
||||
|
||||
ocdesctbl dw offset oq0desc ; system support
|
||||
dw offset oq1desc ; interfacer 3 from here on down
|
||||
dw 0 ; offset oq2desc
|
||||
dw 0 ; offset oq3desc
|
||||
dw 0 ; offset oq4desc
|
||||
dw 0 ; offset oq5desc
|
||||
dw 0 ; offset oq6desc
|
||||
dw offset oq7desc ; printer 1
|
||||
dw offset oq8desc ; printer 0
|
||||
|
||||
soq_seg dseg para
|
||||
|
||||
|
||||
oq0desc db c0out_f ; Concurrents flag #
|
||||
db 0 ; local flag byte, bit vector
|
||||
rb 4 ; char count & position
|
||||
db 5CH ; IO PORT
|
||||
db 5DH ; STATUS PORT
|
||||
db NO_SELECT ; Usart number
|
||||
db 0 ; escape count
|
||||
db 0 ; output bit mask
|
||||
db 0 ; current Vcon
|
||||
db 0 ; pad
|
||||
db TXRDY, DSR, 0
|
||||
rb onmsgs
|
||||
|
||||
|
||||
oq1desc db c1out_f
|
||||
db 0
|
||||
rb 4
|
||||
db 10H
|
||||
db 11H
|
||||
db 0
|
||||
db 0
|
||||
db 01
|
||||
db 4
|
||||
db 0
|
||||
db TXRDY, DSR, 0
|
||||
rb onmsgs
|
||||
; printer 1
|
||||
oq7desc db c7out_f
|
||||
db 0A0H
|
||||
rb 4
|
||||
db 10H
|
||||
db 11H
|
||||
db 6
|
||||
db 0
|
||||
db 40h
|
||||
dw 0
|
||||
db TXRDY, DSR, 0
|
||||
rb onmsgs
|
||||
|
||||
; printer 0
|
||||
; set for xon xoff mode
|
||||
|
||||
oq8desc db c8out_f
|
||||
db 20H
|
||||
rb 4
|
||||
db 10H
|
||||
db 11H
|
||||
db 7
|
||||
db 0
|
||||
db 80h
|
||||
dw 0
|
||||
db TXRDY, DSR, 0
|
||||
rb onmsgs
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
|
||||
;*****************************************************
|
||||
; *
|
||||
; Serial Equates *
|
||||
; Last Update: 2/6/84 *
|
||||
;*****************************************************
|
||||
|
||||
|
||||
INMSGS equ 80H ; Input queue buffer size
|
||||
UPPER_LIM equ INMSGS - 10
|
||||
|
||||
NULL equ 0
|
||||
|
||||
V_FLAG equ 020H ; Flag bias for GSX
|
||||
SWITCH_BIAS equ 028H ; Flag bias for Screen Switch
|
||||
|
||||
P_DELAY equ 141 ; used in Tick
|
||||
DELAY_16MS equ 1 ; each system tick is 16 ms
|
||||
|
||||
; used by Send_Xon, Send_Xoff in Serin
|
||||
SLAVE_PIC_MASK equ 53H ; slave pic's irq mask port
|
||||
CONIN_IRQ equ 40H ; console input irq bit
|
||||
|
||||
|
||||
; usart's command registers bit equates
|
||||
X_CTL equ 01H
|
||||
DTR equ 02H
|
||||
R_CTL equ 04H
|
||||
ERROR_RESET equ 10H
|
||||
RTS equ 20H
|
||||
|
||||
;usart's status register bit equates
|
||||
TXRDY equ 01H ;Transmit buffer is empty
|
||||
RXRDY equ 02H ;Receive buffer has data
|
||||
PARITY_ERR equ 08H
|
||||
OVERRUN_ERR equ 10H
|
||||
FRAME_ERR equ 20H
|
||||
DCD equ 40H ;Set = DCD is low
|
||||
DSR equ 80H ;Set = DSR is low
|
||||
|
||||
eject
|
||||
|
||||
;**************************************************
|
||||
; *
|
||||
; INPUT QUEUE CONTROL STRUCTURE *
|
||||
; *
|
||||
;**************************************************
|
||||
|
||||
SYS_FLAG equ byte ptr 0 ; Q's CCP/M flag number
|
||||
Q_STATE equ word ptr (SYS_FLAG +1) ; current state of this Q
|
||||
CMD_REG equ byte ptr (Q_STATE + 2) ; usarts command reg image
|
||||
UN_PC equ word ptr (CMD_REG +1) ; unprocessed characters
|
||||
INT_IN equ word ptr (UN_PC + 2) ; interrupt side index
|
||||
PROC_OUT equ word ptr (INT_IN + 2) ; process side index
|
||||
U_NUMB equ byte ptr (PROC_OUT + 2) ; usart,s number
|
||||
U_PORTC equ byte ptr (U_NUMB + 1) ; usart's command port
|
||||
U_PORTS equ byte ptr (U_PORTC + 1) ; usart's status port
|
||||
U_PORTD equ byte ptr (U_PORTS + 1) ; usart's data port
|
||||
XINT_MASK equ byte ptr (U_PORTD +1) ; xmitters interrupt mask
|
||||
IESC_IN equ word ptr (XINT_MASK +1) ; input esc buff index
|
||||
OESC_IN equ word ptr (IESC_IN +2) ; output esc buff index
|
||||
LAST_CHAR equ byte ptr (OESC_IN +2) ; last char read from Q
|
||||
LAST_STAT equ byte ptr (LAST_CHAR +1) ; last status read from Q
|
||||
C_STATE equ word ptr (LAST_STAT +1) ; conin current routine/state
|
||||
P_CON equ byte ptr (C_STATE +2) ; physical console number
|
||||
V_CON equ byte ptr (P_CON +1) ; virtual console number
|
||||
ERR_CNT equ byte ptr (V_CON +1) ; Error reset counter
|
||||
|
||||
ESC_BUFF equ byte ptr 32 ; the escape buffer
|
||||
D_BUFF equ byte ptr 48 ; the data buffer
|
||||
S_BUFF equ byte ptr (D_BUFF + INMSGS) ; the status buffer
|
||||
|
||||
; bit definitions for Q_state
|
||||
IPROC_WAITING equ 0001H
|
||||
CHAR_AVAIL equ 0002H
|
||||
BIT8_MASK equ 0004H
|
||||
XX_MODE equ 0010H
|
||||
DTR_MODE equ 0020H
|
||||
RTS_MODE equ 0040H
|
||||
SENDER_STOPPED equ 0080H
|
||||
SWITCH_PEND equ 0100H
|
||||
|
||||
eject
|
||||
|
||||
;************************************************
|
||||
; *
|
||||
; OUTPUT QUEUE CONTROL STRUCTURE *
|
||||
; *
|
||||
;************************************************
|
||||
|
||||
|
||||
OFLAGN equ byte ptr 0 ; CCP/M's flag number
|
||||
OFLAG equ byte ptr 1 ; I/O system bit flags
|
||||
OMSGCNT equ word ptr 2 ; Number of chars in Q
|
||||
OMSGOUT equ word ptr 4 ; current output position in Q
|
||||
OIOPORT equ byte ptr 6 ; Output data port address
|
||||
OSTPORT equ byte ptr 7 ; Output Status port address
|
||||
OUSART equ byte ptr 8 ; Output Usart number
|
||||
OESC_CNT equ byte ptr 9 ; chars since last escape
|
||||
O_BIT_MASK equ byte ptr 10 ; USART's interrupt bit position
|
||||
CUR_VCON equ byte ptr 11 ; Current Vcon on this Pcon
|
||||
XMIT_MASK equ byte ptr 13 ; bit(s) used as a Xmit ready mask
|
||||
DSR_BIT equ byte ptr 14 ; bit used by usart to reflect the
|
||||
; status of the USARTs DSR pin.
|
||||
OBUFFER equ byte ptr 16 ; the Q starts here
|
||||
|
||||
ONMSGS equ 0080h ; size of the output Q buffer
|
||||
OESC_MAX equ 4 ; maximum # char's in esc sequence
|
||||
; (for VT-52)
|
||||
|
||||
|
||||
; Bit definitions for Queue State field
|
||||
XON_XOFF_MODE EQU 20H ; If set, the Queue system will respect
|
||||
; Xon/Xoff protocol.
|
||||
XOFF_PENDING EQU 10H ; If set,the USART we're sending chars
|
||||
; to wants us to stop.
|
||||
RTS_PROT EQU 80H ; If set, the Queue system will recognize
|
||||
; the DSR pin on the USART.
|
||||
PROC_WAITING equ 01H ; If set,a process is waiting for
|
||||
; room in this Queue.
|
||||
|
||||
NO_SELECT equ 0ffH ; Put into the USART NUMBER field of
|
||||
; the Q Control structure (OUSART) when:
|
||||
; we do not want a usart select call
|
||||
; made before a usart is accessed for
|
||||
; command, status, or data.
|
||||
|
||||
|
||||
|
||||
|
||||
; IN_XMT_MASK values for each of the USARTS
|
||||
SS_U equ 0FFH ; system support boards USART
|
||||
US_0 equ 01H ; Interfacer 3 USART 0
|
||||
US_1 equ 02H ; Interfacer 3 USART 1
|
||||
US_2 equ 04H ; Interfacer 3 USART 2
|
||||
US_3 equ 08H ; Interfacer 3 USART 3
|
||||
US_4 equ 10H ; Interfacer 3 USART 4
|
||||
US_5 equ 20H ; Interfacer 3 USART 5
|
||||
US_6 equ 40H ; Interfacer 3 USART 6
|
||||
US_7 equ 80H ; Interfacer 3 USART 7
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
|
||||
title 'Serial Input module'
|
||||
|
||||
;*****************************************
|
||||
; *
|
||||
; SERIAL INPUT MODULE *
|
||||
; Last change : 2/13/84 *
|
||||
; *
|
||||
;*****************************************
|
||||
|
||||
include system.lib
|
||||
include chrcomm.equ
|
||||
include serdata.equ
|
||||
|
||||
cseg
|
||||
|
||||
public serial_in
|
||||
public store_char
|
||||
|
||||
extrn supif:near ;; headentr.a86
|
||||
extrn ocdesctbl:word ;; serdata.a86
|
||||
extrn usart_on:near
|
||||
extrn xmit_on:near ;; servar.a86
|
||||
extrn xmit_off:near ;; servar.a86
|
||||
extrn set_bit:near ;; servar.a86
|
||||
extrn clear_bit:near ;; servar.a86
|
||||
|
||||
serial_in:
|
||||
;-----
|
||||
; ENTRY: bx = addr of the input Q control block
|
||||
;
|
||||
; EXIT: al = data from the usart's Q
|
||||
; ah = the usarts status byte
|
||||
|
||||
pushf ! cli
|
||||
|
||||
cin2: ;; if char is available, get it
|
||||
test Q_STATE[bx], CHAR_AVAIL ;; else flagwait until it's available
|
||||
jnz cin1
|
||||
or Q_STATE[bx], IPROC_WAITING ;; set a loacal proc waiting flag
|
||||
push bx ;; save the address of Q control struc
|
||||
mov dl, SYS_FLAG[bx] ;; do the flag wait
|
||||
mov cl, F_FLAGWAIT
|
||||
call supif
|
||||
cmp ax, 0ffffh ! jne cin3 ;; was there an error ?
|
||||
mov cl, P_DISPATCH ;; dispatch the process, let it try
|
||||
call supif ;; again later
|
||||
cin3:
|
||||
pop bx ;; get back the Q control structure
|
||||
jmps cin2 ;; just in case the flagset shouldn't
|
||||
;; have happened.
|
||||
cin1:
|
||||
push bx ;; save the Q control structure
|
||||
call conin_fc ;; call the console read routine
|
||||
pop bx ;; restore the Q control addr
|
||||
mov al, LAST_CHAR[bx] ;; al = char from Q
|
||||
mov ah, LAST_STAT[bx] ;; ah = status from Q
|
||||
popf ;; turn the interrupts back on
|
||||
ret
|
||||
|
||||
|
||||
|
||||
conin_fc:
|
||||
;;--------
|
||||
;; This routine reads a character from the console input Q
|
||||
;;
|
||||
;; ENTRY: bx -> the Q control structure
|
||||
;;
|
||||
;; EXIT: LAST_CHAR[bx] = the character that was read in
|
||||
;; LAST_STAT[bx] = the usart's status that corresponded to the
|
||||
;; char in LAST_CHAR[bx]
|
||||
|
||||
push si ;; we need an index register
|
||||
mov si, PROC_OUT[bx] ;; get the Q's output index
|
||||
mov al, D_BUFF[bx+si] ;; get the character
|
||||
mov LAST_CHAR[bx], al
|
||||
mov al, S_BUFF[bx+si] ;; get the status byte
|
||||
mov LAST_STAT[bx], al
|
||||
inc si ;; inc the processes output index
|
||||
and si, (INMSGS -1) ;; mod the size of the Q
|
||||
mov PROC_OUT[bx], si ;; restore the index register
|
||||
pop si ;; restore the extra index register
|
||||
dec UN_PC[bx] ;; dec un-processed char count
|
||||
cmp UN_PC[bx], 0 ;; was this the last char in the Q ?
|
||||
jne cinf2 ;; no ...
|
||||
cinf1:
|
||||
and Q_STATE[bx], not CHAR_AVAIL
|
||||
cinf2: ;; if sender was stopped check the receive buffer
|
||||
;; for being half empty. When the receive buffer is half
|
||||
test Q_STATE[bx], SENDER_STOPPED ;; empty restart the sender
|
||||
jz cinf3
|
||||
cmp UN_PC[bx], ( INMSGS / 2 )
|
||||
ja cinf3
|
||||
call start_sender ;; the Q is half empty
|
||||
cinf3:
|
||||
ret
|
||||
|
||||
|
||||
store_char:
|
||||
;;----------
|
||||
;;
|
||||
;; This routine stores the status and data bytes from a usart in their Q's.
|
||||
;; It also handles the interrupt level Xon Xoff protocol.
|
||||
;; If an error is detected in the status byte returned from the USART
|
||||
;; a reset error command is sent to the usart.
|
||||
;;
|
||||
;; ENTRY: bx -> receive Q control structure
|
||||
;; al = the data read from the USART
|
||||
;; ah = the status read from the USART
|
||||
;;
|
||||
;; EXIT: the status and data are put in the status and data Q's.
|
||||
;;
|
||||
|
||||
test Q_STATE[bx], BIT8_MASK ;; are we masking off the 8th bit
|
||||
jz try_xon
|
||||
and al, 7FH
|
||||
try_xon:
|
||||
test Q_STATE[bx], XX_MODE ;; is this Q in Xon Xoff mode ?
|
||||
jz store_now
|
||||
cmp al, XON ! jne try_xoff ;; is the char an Xon
|
||||
call xmit_on ;; char was an Xon, start transmitter
|
||||
ret
|
||||
try_xoff:
|
||||
cmp al, XOFF ! jne store_now
|
||||
call xmit_off ;; char was an Xoff, stop transmitter
|
||||
ret
|
||||
store_now:
|
||||
push si ;; use SI as an index register
|
||||
mov si, INT_IN[bx]
|
||||
mov D_BUFF[bx+si], al ;; store the data
|
||||
mov S_BUFF[bx+si], ah ;; store the status
|
||||
inc si
|
||||
and si, (INMSGS - 1)
|
||||
mov INT_IN[bx], si
|
||||
pop si
|
||||
|
||||
or Q_STATE[bx], CHAR_AVAIL ;; set char avail flag
|
||||
test ah, PARITY_ERR or OVERRUN_ERR or FRAME_ERR;; check for usart errs
|
||||
jz no_err ;; if err, send error reset to usart
|
||||
inc ERR_CNT[bx] ;; inc the error reset counter
|
||||
mov ah, ERROR_RESET ;; set up the error reset bit
|
||||
call set_bit ;; now set it in the usarts command register
|
||||
and CMD_REG[bx], not ERROR_RESET ;; this is one time command
|
||||
;; we have to reset the command
|
||||
;; register image, so we don't
|
||||
;; keep doing an error reset
|
||||
no_err:
|
||||
inc UN_PC[bx]
|
||||
cmp UN_PC[bx], UPPER_LIM ;; is # chars in buff >= limit ?
|
||||
jb check_proc_waiting ;; no
|
||||
call stop_sender ;; yes, stop transmitter
|
||||
check_proc_waiting:
|
||||
test Q_STATE[bx], IPROC_WAITING ;; only do flagset if proc is waiting
|
||||
jz no_proc_waiting ;; for a character
|
||||
and Q_STATE[bx], not IPROC_WAITING ;; clear the process waiting flag
|
||||
push ax ! push bx ! push cx ;; this is an interrupt context
|
||||
push dx ! push bp ! push si ;; save the environment
|
||||
push di ! push es ! push ds
|
||||
sc2:
|
||||
mov dl, SYS_FLAG[bx] ;; get the flag number
|
||||
mov cl, F_FLAGSET ;; set the system function
|
||||
push bx ;; save the Q ptr in case of a retry
|
||||
call supif
|
||||
pop bx ;; restore the Q ptr
|
||||
cmp ax, 0ffffh ;; check for an error
|
||||
jne sc3
|
||||
cmp cx, 2aH ;; was it a flag ignore ?
|
||||
jne sc3 ;; if it was not an ignore just exit
|
||||
jmps sc2 ;; else, try again
|
||||
|
||||
sc3:
|
||||
pop ds ! pop es ! pop di ;; restore environment
|
||||
pop si ! pop bp ! pop dx
|
||||
pop cx ! pop bx ! pop ax
|
||||
no_proc_waiting:
|
||||
ret
|
||||
|
||||
|
||||
start_sender:
|
||||
;;------------
|
||||
;;
|
||||
;; This routine tries to restart the sender.
|
||||
;;
|
||||
;; ENTRY: bx = addr Q control structure
|
||||
;;
|
||||
;; EXIT: none
|
||||
;;
|
||||
;; NOTE: I have assumed + 12 volts on the DSR or RTS lines means
|
||||
;; send data. Conversely - 12 volts means stop
|
||||
;; sending data.
|
||||
;; The DTR* pin (#24) on the 2651 is wired
|
||||
;; to the DSR pin on the DB-25 connector ( pin 6 ),
|
||||
;; through an inverting driver. This requires setting
|
||||
;; the DTR bit in the command register to start the sender.
|
||||
;;
|
||||
;; For the RTS protocol, the RTS* pin (23) on the 2651
|
||||
;; is wired to the Ready for Send pin on the DB-25
|
||||
;; connector ( pin 5 ) through an inverting driver. This
|
||||
;; requires setting the RTS bit in the command register
|
||||
;; to start the sender.
|
||||
|
||||
test Q_STATE[bx], DTR_MODE ;; check dtr protocol
|
||||
jz try_rts1
|
||||
mov ah, DTR ;; force DTR* (dtr not) pin low
|
||||
call set_bit
|
||||
and Q_STATE[bx], not SENDER_STOPPED
|
||||
try_rts1:
|
||||
test Q_STATE[bx], RTS_MODE ;; check for RTS protocol,
|
||||
jz try_xx1
|
||||
mov ah, RTS ;; force the RTS* (rts not) pin low
|
||||
call set_bit
|
||||
and Q_STATE[bx], not SENDER_STOPPED
|
||||
try_xx1:
|
||||
test Q_STATE[bx], XX_MODE ;; check for Xon/Xoff protocol
|
||||
jz no_prot
|
||||
call send_xon
|
||||
and Q_STATE[bx], not SENDER_STOPPED
|
||||
no_prot:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
stop_sender:
|
||||
;;-----------
|
||||
;; This routine tries to stop the transmitter.
|
||||
;;
|
||||
;; ENTRY: bx = addr( Q control )
|
||||
;;
|
||||
;; EXIT: none
|
||||
;;
|
||||
|
||||
test Q_STATE[bx], DTR_MODE
|
||||
jz try_rts
|
||||
mov ah, DTR ;; force DTR* (dtr not) pin high
|
||||
call clear_bit
|
||||
or Q_STATE[bx], SENDER_STOPPED
|
||||
try_rts:
|
||||
test Q_STATE[bx], RTS_MODE ;; check for RTS protocol,
|
||||
jz try_xx
|
||||
mov ah, RTS ;; force the RTS* (rts not) pin high
|
||||
call clear_bit
|
||||
or Q_STATE[bx], SENDER_STOPPED
|
||||
try_xx:
|
||||
test Q_STATE[bx], XX_MODE ;; check for Xon/Xoff protocol
|
||||
jz no_protocol
|
||||
call send_xoff
|
||||
or Q_STATE[bx], SENDER_STOPPED
|
||||
no_protocol:
|
||||
cmp UN_PC[bx], INMSGS ;; If at lim of buffer, adjust char
|
||||
jb ss_2
|
||||
ss_0:
|
||||
dec UN_PC[bx]
|
||||
cmp INT_IN[bx], 0
|
||||
je ss_1
|
||||
dec INT_IN[bx]
|
||||
jmps ss_2
|
||||
ss_1:
|
||||
mov INT_IN[bx], (INMSGS - 1) ;; force index to end of buffer
|
||||
ss_2:
|
||||
ret
|
||||
|
||||
send_xon:
|
||||
;;--------
|
||||
;; This routine sends an Xon to the sender
|
||||
;;
|
||||
;; ENTRY: bx = addr of Q control sturcture
|
||||
;;
|
||||
;; EXIT: An Xon ( ctl q ) is sent to the sender
|
||||
;;
|
||||
test XINT_MASK[bx], SS_U ;; is this the system support board?
|
||||
je sxn
|
||||
mov ah, XON ;; it's interfacer 3 board
|
||||
call send_char
|
||||
sxn:
|
||||
ret
|
||||
|
||||
|
||||
send_xoff:
|
||||
;;---------
|
||||
;; This routine sends an Xoff to the sender.
|
||||
;;
|
||||
;; ENTRY: bx = addr of Q control sturcture
|
||||
;;
|
||||
;; EXIT: An Xoff ( ctl s ) is sent to the sender
|
||||
;;
|
||||
test XINT_MASK[bx], SS_U ;; is this the system support board?
|
||||
je sxf
|
||||
mov ah, XOFF ;; it's the interfacer 3 board
|
||||
call send_char
|
||||
sxf:
|
||||
ret
|
||||
|
||||
|
||||
send_char:
|
||||
;;---------
|
||||
;; This routine sends a single character to the USART in the Q ctl struct.
|
||||
;;
|
||||
;; ENTRY: bx = addr Q control structure
|
||||
;; ah = char to send
|
||||
;;
|
||||
;; EXIT: none
|
||||
|
||||
push bx ;; save the input Q control addr
|
||||
mov bl, U_NUMB[bx] ;; get the usart's i3 number
|
||||
xor bh, bh ;; clear the upper byte
|
||||
inc bx ;; index above the SS usart
|
||||
shl bx, 1 ;; indexing into a word table
|
||||
mov bx, ocdesctbl[bx] ;; bx -> Output Q control
|
||||
|
||||
push cx
|
||||
push si
|
||||
|
||||
mov cx, OMSGCNT[bx] ;; get the number of chars in Q
|
||||
mov si, omsgout[bx] ;; get the output index
|
||||
add si, cx ;; add to it the number of chars
|
||||
and si,onmsgs-1 ;; in the buffer, mod( buff size )
|
||||
|
||||
mov obuffer[bx+si],ah ;; put the char in the Q
|
||||
inc cx ;; inc the chars in Q count
|
||||
mov omsgcnt[bx],cx ;; update
|
||||
|
||||
dec cx ;; if 1st char in Q, start Xmit int's
|
||||
jnz sc1 ;; cx = chars in Q - 1
|
||||
call usart_on ;; start the Xmitter
|
||||
sc1:
|
||||
pop si
|
||||
pop cx
|
||||
|
||||
pop bx ;; restore the input Q control addr
|
||||
|
||||
ret
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
|
||||
title 'Interrupt Serial Output'
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* This module is the invariant part of an interrupt *
|
||||
;* driven serial output system. *
|
||||
;* Last Update: 2/14/84 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
include flags.equ
|
||||
include system.lib
|
||||
include chrcomm.equ
|
||||
include serdata.equ
|
||||
|
||||
dseg
|
||||
|
||||
public dsr_check
|
||||
public dsr_vec
|
||||
|
||||
extrn bit_mask_tbl:byte
|
||||
extrn ocdesctbl:word
|
||||
extrn icdesctbl:word
|
||||
extrn vrtl_phy:byte
|
||||
|
||||
cseg
|
||||
|
||||
public serial_out
|
||||
public intco
|
||||
public dsr_start
|
||||
|
||||
extrn supif:near
|
||||
|
||||
extrn usart_on:near
|
||||
extrn usart_off:near
|
||||
extrn usart_select:near
|
||||
|
||||
;;=====
|
||||
intco: ;; called from ssint.a86,i3int.a86
|
||||
;;=====
|
||||
;;
|
||||
;; ENTRY: bx -> Xmit Q ctl structure
|
||||
;;
|
||||
;; OFLAG: 01h - process flag waiting (buf empty)
|
||||
;; 02h - status ready
|
||||
;; 10h - Xoff pending
|
||||
;; 20H - Xon/Xoff mode
|
||||
;; 80H - RTS protocol support
|
||||
;;
|
||||
;; EXIT : AX,BX used.
|
||||
;; All other registers preserved.
|
||||
;;
|
||||
;; Handles the interrupt side of writing a char to the console.
|
||||
;; It runs in an interrupt context.
|
||||
|
||||
push dx ;; port select register
|
||||
xor dh,dh ;; clear the high byte
|
||||
mov al, OUSART[bx] ;; get the usart number
|
||||
cmp al, NO_SELECT ;; does it need a select ?
|
||||
je no_sel
|
||||
call usart_select
|
||||
no_sel:
|
||||
test OFLAG[bx], XON_XOFF_MODE ;; Is this USART supporting Xon/Xoff protocol ?
|
||||
jz intco1
|
||||
test OFLAG[bx], XOFF_PENDING ;; Have we received a stop request?
|
||||
jnz icoexit ;; yes
|
||||
intco1:
|
||||
test OFLAG[bx], RTS_PROT ;; Is this USART supporting RTS protocol
|
||||
jz intco2
|
||||
xor dh, dh ;; yes,...
|
||||
mov dl, OSTPORT[bx] ;; get the status port
|
||||
in al, dx ;; get the status
|
||||
mov ah, DSR_BIT[bx] ;; get the DSR bit
|
||||
test al, ah ;; test the DSR bit of the USART
|
||||
jnz intco2 ;; bit(7) = 1 if DSR* = 0 volts
|
||||
call dsr_stop ;; we've gotten a request to stop
|
||||
jmp icoexit
|
||||
intco2:
|
||||
mov dl, OSTPORT[bx] ;; get the status port addr
|
||||
in al,dx ;; get the USARTS status
|
||||
mov ah, XMIT_MASK[bx] ;; get the Xmit empty mask
|
||||
test al, ah ;; is the Xmit buffer empty ?
|
||||
jz icoexit
|
||||
;; yes, are there any characters to send ?
|
||||
push cx ;; save the regs we're going to use
|
||||
push si
|
||||
mov cx, OMSGCNT[bx]
|
||||
cmp cx,0 ;; is there a char to send ?
|
||||
je icodone
|
||||
mov si, OMSGOUT[bx] ;; yes, get the output index
|
||||
mov al, OBUFFER[bx+si] ;; al = char to send
|
||||
mov dl, OIOPORT[bx] ;; get the USARTS data port
|
||||
out dx, al ;; send the char
|
||||
inc si ;; inc the output index
|
||||
and si, ONMSGS - 1 ;; mod the Queue size
|
||||
mov OMSGOUT[bx], si ;; save the output index
|
||||
dec cx ;; dec the chars-to-send count
|
||||
mov OMSGCNT[bx], cx ;; If there is a proccess waiting for
|
||||
;; room in this Q, do a flag set for
|
||||
;; the process when the Q is half empty.
|
||||
cmp cx, ( ONMSGS / 2 ) ;; is the Q at least half empty ?
|
||||
ja icodone
|
||||
test OFLAG[bx], PROC_WAITING ;; yes, is there a process waiting?
|
||||
jz icodone ;; no,...
|
||||
push bx ;; save the remaining environment
|
||||
push bp ;; for the flag set call
|
||||
push di
|
||||
push es
|
||||
intco3:
|
||||
mov dl, OFLAGN[bx] ;; Get the flag for this Q
|
||||
mov cl, F_FLAGSET ;; do the flag set
|
||||
push bx ;; save the Q ptr in case of a retry
|
||||
call supif
|
||||
pop bx
|
||||
cmp ax, ERROR ;; was there an error ?
|
||||
jne intco4
|
||||
cmp cx, FLAG_IGNORE ;; yes, was the flag ignored ?
|
||||
je intco3 ;; yes, try again
|
||||
intco4:
|
||||
pop es ;; restore the environment
|
||||
pop di ;; that was saved for the flag set
|
||||
pop bp
|
||||
pop bx
|
||||
and OFLAG[bx], not PROC_WAITING ;; clear the proc waiting flag
|
||||
icodone:
|
||||
pop si ;; restore the context
|
||||
pop cx
|
||||
cmp OMSGCNT[bx], 0 ;; More char's to send ?
|
||||
jne icoexit ;; yes, just return
|
||||
mov al, OUSART[bx] ;; no, get the usart number
|
||||
call usart_off ;; turn off usart's transmit system
|
||||
icoexit:
|
||||
pop dx
|
||||
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
;===========
|
||||
serial_out:
|
||||
;===========
|
||||
;
|
||||
; ENTRY: cl = character to send out
|
||||
; bx -> Queue control struct
|
||||
;
|
||||
; EXIT: the character is :
|
||||
; 1] either sent to the USART,
|
||||
; 2] or put in the output buffer,
|
||||
; 3] or, the process is flagwaited until there is room
|
||||
; in the output buffer .
|
||||
|
||||
pushf
|
||||
push bx
|
||||
cli
|
||||
push cx ;; save the character
|
||||
mov cx, OMSGCNT[bx] ;; cx = number of chars in the Q
|
||||
cmp cx, ONMSGS ;; is there room in the Q ?
|
||||
jb con1
|
||||
or OFLAG[bx], PROC_WAITING ;; no, set a local process-waiting flag
|
||||
pop cx
|
||||
pop bx
|
||||
popf ;; turn interrupts back on
|
||||
push cx ;; save the character
|
||||
push bx ;; save the Q ctl structure
|
||||
|
||||
mov dl,OFLAGN[bx] ;; do the global flagwait
|
||||
mov cl,F_FLAGWAIT
|
||||
call supif
|
||||
cmp ax, ERROR ;; was there an error ?
|
||||
jne con0
|
||||
;; It might have been a flag overrun.
|
||||
mov cl, P_DISPATCH ;; Dispatch the process, and try again.
|
||||
call supif
|
||||
|
||||
con0:
|
||||
pop bx ;; BX -> Q ctl structure
|
||||
pop cx ;; restore the char
|
||||
jmps serial_out
|
||||
|
||||
con1: ;; There's room in the Xmit Q.
|
||||
cmp OESC_CNT[bx], 0 ;; Check the esc count
|
||||
jz not_esc
|
||||
push bx
|
||||
cmp OESC_CNT[bx], 1 ;; Are we at the end of the sequence?
|
||||
je check_switch ;; Yes, see if PIN is waiting.
|
||||
|
||||
check_xy:
|
||||
cmp OESC_CNT[bx], 3 ;; See if this is a 4-char sequence.
|
||||
jne dec_esc ;; We're at first or third char.
|
||||
pop bx ! pop ax
|
||||
push ax ! push bx ;; AX -> char , BX -> Output Q ctl
|
||||
cmp ax, 'Y' ;; ESC Y is only 4-char sequence.
|
||||
je dec_esc
|
||||
|
||||
check_switch:
|
||||
pop bx ! pop ax
|
||||
mov OESC_CNT[bx], 0 ;; Clear escape count.
|
||||
call con2 ;; Send the last char in the sequence
|
||||
xor ah,ah ;; before doing the flag set, if any.
|
||||
mov al, CUR_VCON[bx]
|
||||
mov bx,ax
|
||||
mov bl, vrtl_phy[bx] ;; get the physical console #
|
||||
xor bh,bh
|
||||
shl bx, 1
|
||||
mov bx, icdesctbl[bx] ;; get the Input Q control structure
|
||||
test Q_STATE[bx],SWITCH_PEND ;; Is PIN waiting for an escape
|
||||
jz exit ;; sequence to end ?
|
||||
|
||||
flag_set:
|
||||
push bx ! push cx ! push si
|
||||
xor dh, dh
|
||||
mov dl, P_CON[bx]
|
||||
add dl, SWITCH_BIAS ;; Flag # = virtual console + bias
|
||||
mov cl, f_flagset ;; Wake up the PIN waiting to do
|
||||
call supif ;; a screen switch.
|
||||
pop si ! pop cx ! pop bx
|
||||
and Q_STATE[bx], not SWITCH_PEND
|
||||
jmps exit
|
||||
not_esc:
|
||||
pop ax
|
||||
call con2
|
||||
jmps exit
|
||||
dec_esc:
|
||||
pop bx ! pop ax
|
||||
dec OESC_CNT[bx]
|
||||
call con2
|
||||
|
||||
exit:
|
||||
pop bx
|
||||
popf
|
||||
ret
|
||||
|
||||
con2: ;; put the character in the Xmit Q
|
||||
mov si, OMSGOUT[bx] ;; get the output index
|
||||
add si, cx ;; add to it the number of chars
|
||||
and si,ONMSGS - 1 ;; in the buffer, mod( buff size )
|
||||
mov OBUFFER[bx+si],al ;; put it in the Q
|
||||
inc cx ;; inc Q char count
|
||||
mov OMSGCNT[bx],cx
|
||||
;; if 1st char in Q, start USART Xmit
|
||||
dec cx ;; cx = chars in Q -1
|
||||
jnz con4
|
||||
test OFLAG[bx], XON_XOFF_MODE ;; Is it supporting Xon/Xoff protocol ?
|
||||
jz con3
|
||||
test OFLAG[bx], XOFF_PENDING ;; Is there an Xoff pending ?
|
||||
jnz con4
|
||||
;; The character is in the buffer and
|
||||
con3: ;; the usart int system is turned off.
|
||||
call usart_on ;; Start the Usart's Xmitter.
|
||||
con4:
|
||||
ret
|
||||
|
||||
eject
|
||||
|
||||
|
||||
;===========
|
||||
dsr_stop:
|
||||
;===========
|
||||
; This routine is called when the USART is set to acknowledge the DSR pin
|
||||
; and the DSR line is high (i.e.,stop sending data).
|
||||
;
|
||||
; ENTRY: bx -> Output Q control structure for the USART
|
||||
; EXIT: The dsr_vec has a bit set for this usart.
|
||||
; The usart transmitter interrupt system is shut down.
|
||||
; The dsr_check flag is posted for the tick routine.
|
||||
|
||||
; To post this usart in the dsr_vec
|
||||
mov al, O_BIT_MASK[bx] ; get the bit corresponding to this USART
|
||||
or dsr_vec, al ; OR it into the DSR vector
|
||||
mov al, OUSART[bx] ; get the usart number
|
||||
call usart_off ; and stop the transmitter
|
||||
mov dsr_check, TRUE ; signal the tick routine to check the
|
||||
; state of the DSR pin for this usart
|
||||
ret
|
||||
|
||||
;=========
|
||||
dsr_start:
|
||||
;=========
|
||||
; Called by the tick routine when the dsr_check flag = true.
|
||||
; It looks at the dsr vector to figure out which usart has had its
|
||||
; transmitter turned off (due to the DSR pin). It then reads the usart's
|
||||
; status and tests the state of the DSR bit in the status word (bit(7)).
|
||||
; When this bit is on ,the port we're sending to wants more data. We
|
||||
; start the transmitter and remove its bit from the dsr_vector. If the
|
||||
; dsr vector has all its bits cleared, we clear the dsr check flag.
|
||||
|
||||
push ax ;; save the environment
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
|
||||
dsr_test_lp:
|
||||
mov al, 0
|
||||
call usart_select ;; select the usart
|
||||
mov ah, dsr_vec ;; bit vector of the off Xmitters
|
||||
dsr_lp_0:
|
||||
mov bx, offset bit_mask_tbl ;; byte mask for each Xmit interrupt
|
||||
mov cx, 8 ;; length of bit mask table
|
||||
dsr_lp:
|
||||
test ah, [bx]
|
||||
jz dsr_lp_2
|
||||
mov al, [bx] ;; found the usart, AND off the bit in
|
||||
not al ;; dsr_vec
|
||||
and ah, al
|
||||
;; CX = USART
|
||||
mov bx, offset ocdesctbl ;; get base of Xmit Q table
|
||||
shl cx, 1 ;; times 2 ( word table )
|
||||
add bx, cx ;; index into the table
|
||||
mov bx, [bx] ;; bx -> Xmit Q ctl Structure
|
||||
mov al, OUSART[bx] ;; select the USART
|
||||
call usart_select
|
||||
xor dh, dh
|
||||
mov dl, OSTPORT[bx] ;; get USART's status port
|
||||
in al, dx ;; read the status
|
||||
test al, DSR_BIT[bx] ;; check DSR pin - should we turn on
|
||||
jz dsr_lp_1 ;; the transmitter ?
|
||||
call usart_on ;; yes, turn on the Usart
|
||||
mov al, O_BIT_MASK[bx] ;; get the bit
|
||||
not al ;; make it an AND mask
|
||||
and dsr_vec, al ;; remove from bit vector
|
||||
dsr_lp_1:
|
||||
jmps dsr_lp_0 ;; in case another usart has it's
|
||||
;; xmitter turned off
|
||||
dsr_lp_2:
|
||||
inc bx ;; point to the next mask
|
||||
loop dsr_lp ;; check all the USARTS
|
||||
|
||||
cmp dsr_vec, 0 ;; if dsr_vec is empty, clear dsr_check
|
||||
jne dsr_st1 ;; flag
|
||||
mov dsr_check, FALSE
|
||||
dsr_st1:
|
||||
pop dx ;; restore the environment
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
|
||||
dsr_check db 0 ; This flag = true when a USART has had its
|
||||
; transmitter shut down due to the state of
|
||||
; the dsr pin.
|
||||
|
||||
dsr_vec db 0 ; This is a bit vector of the usarts that
|
||||
; have had their transmitter(s) shut down by
|
||||
; a reqest from the port they're sending data
|
||||
; to.
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
title 'Interrupt Driven Serial Variant'
|
||||
|
||||
;****************************************
|
||||
; *
|
||||
; SERIAL VARIANT MODULE *
|
||||
; Last changed: 2/10/84 *
|
||||
; *
|
||||
;****************************************
|
||||
|
||||
include ssboard.equ
|
||||
include i3board.equ
|
||||
include u2651.equ
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
public i3_xmit_int_vec
|
||||
public bit_mask_tbl
|
||||
extrn ocdesctbl:word
|
||||
|
||||
cseg
|
||||
|
||||
public char_init
|
||||
public usart_on
|
||||
public usart_off
|
||||
public usart_select
|
||||
public xmit_on
|
||||
public xmit_off
|
||||
public set_bit
|
||||
public clear_bit
|
||||
|
||||
|
||||
;=========
|
||||
char_init: ;; Init consoles on the System Support
|
||||
;========= and the Interfacer 3 board.
|
||||
|
||||
;; do the System Support board
|
||||
MOV AL,01101110b ;; async, 16x, 8 bits, no parity,
|
||||
;; even, 1 stop
|
||||
OUT ssmode,AL ;; set up mode register 1
|
||||
MOV AL,01111110b ;; 9600 baud
|
||||
OUT ssmode,AL ;; set up mode register 2
|
||||
MOV AL,00100111b ;; trans. on, dtr low, rec. on,
|
||||
;; no break, no reset, rts low
|
||||
OUT sscmd,AL ;; set up command port
|
||||
|
||||
mov dl, 0 ;; Do the Interfacer 3 board
|
||||
mov cx, 8
|
||||
i3_init_loop:
|
||||
mov al, dl
|
||||
inc dl
|
||||
call i3_init
|
||||
loop i3_init_loop
|
||||
|
||||
mov al, i3_int_enable ;; turn on all I3 recv interrupts
|
||||
out I3_RCV_INT_MASK, al
|
||||
|
||||
not al ;; turn off all I3 Xmit interrupts
|
||||
out I3_XMIT_INT_MASK, al
|
||||
|
||||
mov i3_xmit_int_vec, al ;; initialize the bit vector
|
||||
|
||||
i3_init: ;; al = uart on I3 board to init
|
||||
;; async, 16x, 8 bits, no parity,
|
||||
;; even, 1 stop, 9600 baud.
|
||||
out i3_select_reg, al
|
||||
MOV AL,01101110b
|
||||
OUT i3_uart_mode,AL ;; set up mode register 1
|
||||
MOV AL,01111110b ;; 9600 baud
|
||||
OUT i3_uart_mode,AL ;; set up mode register 2
|
||||
MOV AL,00100111b ;; Xmit on, dtr low, recv on,
|
||||
;; no break, no reset, rts low
|
||||
OUT i3_uart_cmd,AL ;; set up command port
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;========
|
||||
usart_on:
|
||||
;========
|
||||
;
|
||||
; ENTRY: bx -> Xmit Q control structure
|
||||
;
|
||||
|
||||
mov al, OUSART[bx] ;; Is the usart on the i3 board ?
|
||||
cmp al, NO_SELECT
|
||||
je usrt_on1 ;; No, must be on system support board.
|
||||
mov al, 0 ;; Yes, we must first select one of the
|
||||
out I3_SELECT_REG, al ;; USARTS to get to int mask register.
|
||||
mov al, O_BIT_MASK[bx] ;; Get the USART'S mask bit
|
||||
or i3_xmit_int_vec, al ;; set our bit vector
|
||||
mov al, i3_xmit_int_vec ;; set the interfacer 3's
|
||||
out I3_XMIT_INT_MASK, al ;; interrupt mask register
|
||||
jmps usrt_on2
|
||||
|
||||
usrt_on1: ;; usart is on the SS board
|
||||
in al, SLAVE_PIC_PORT + 1 ;; get the PIC mask
|
||||
and al, 0bfh ;; turn on the SS USART Xmit IR line
|
||||
out SLAVE_PIC_PORT + 1, al ;; write to the PIC
|
||||
usrt_on2:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;=========
|
||||
usart_off:
|
||||
;=========
|
||||
;
|
||||
; ENTRY: bx -> Xmit Q control structure
|
||||
;
|
||||
|
||||
cmp OUSART[bx], NO_SELECT ;; Is this the System Support board ?
|
||||
jne usrt_off1 ;; no, must be interfacer 3
|
||||
;; Turn off the Xmit interrupt at the PIC
|
||||
in al, SLAVE_PIC_PORT + 1 ;; read the PIC's mask
|
||||
or al, 40h ;; turn off the SS USART Xmit int
|
||||
out SLAVE_PIC_PORT + 1, al ;; write the mask back to the PIC
|
||||
jmps usrt_off2 ;; and exit
|
||||
|
||||
usrt_off1: ;; the Xmit Q is empty and the USART
|
||||
;; is on the interfacer 3.
|
||||
mov ah, O_BIT_MASK[bx] ;; get the interfacer 3's interrupt
|
||||
;; mask register bit for this USART
|
||||
not ah ;; we need to AND off the bit
|
||||
mov al, i3_xmit_int_vec ;; get the interfacer 3's Xmit bit vector
|
||||
and al,ah ;; turn off this USART in our bit vector
|
||||
out I3_XMIT_INT_MASK, al ;; turn off the USART on the I3
|
||||
mov i3_xmit_int_vec, al ;; save our new bit vector
|
||||
usrt_off2:
|
||||
ret
|
||||
|
||||
|
||||
eject
|
||||
|
||||
;============
|
||||
usart_select:
|
||||
;============
|
||||
;
|
||||
; ENTRY: al = usart number
|
||||
;
|
||||
|
||||
out I3_SELECT_REG, al
|
||||
ret
|
||||
|
||||
|
||||
;============
|
||||
xmit_on:
|
||||
;============
|
||||
;;
|
||||
;; ENTRY: bx -> Recv Q control structure
|
||||
;;
|
||||
;; EXIT: The Interfacer 3's USART transmit intvec is enabled.
|
||||
;; The USART number (U_NUMB) in the Q control structure is set.
|
||||
|
||||
pushf ! cli ;; interrupts off
|
||||
|
||||
mov al, 0 ;; We have to select a USART on the
|
||||
out I3_SELECT_REG, al ;; interfacer 3 before we can query
|
||||
;; the interrupt status register.
|
||||
mov al, i3_xmit_int_vec ;; get the Xmit interrupt vector
|
||||
or al, XINT_MASK[bx] ;; set this Usart's interrupt bit
|
||||
mov i3_xmit_int_vec, al ;; in the Xmit interrupt vector
|
||||
out I3_XMIT_INT_MASK, al ;; and the interfacer 3's
|
||||
;; interrupt mask port
|
||||
|
||||
push bx ;; save the input Q control addr
|
||||
mov bl, U_NUMB[bx] ;; get the usarts i3 number
|
||||
xor bh, bh ;; clear the upper byte
|
||||
inc bx ;; index above the SS usart
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ;; get the output Q control addr
|
||||
and OFLAG[bx], not XOFF_PENDING ;; turn off the Xoff pending flag
|
||||
pop bx ;; restore the input Q control addr
|
||||
popf ;; turn the interrrupts back on
|
||||
|
||||
ret
|
||||
|
||||
;============
|
||||
xmit_off:
|
||||
;============
|
||||
;;
|
||||
;; ENTRY: bx -> Recv Q control structure
|
||||
;;
|
||||
;; EXIT: The Interfacer 3's USART transmit intvec is disabled.
|
||||
;; The USART number (U_NUMB) in the Q control structure is reset.
|
||||
;; The Xoff pending flag is set in the output Q control
|
||||
;; structure.
|
||||
|
||||
pushf ! cli ;; interrupts off
|
||||
|
||||
mov al, 0 ;; We have to select a USART on the
|
||||
out I3_SELECT_REG, al ;; interfacer 3 before we can query
|
||||
;; the interrupt status register.
|
||||
mov al, i3_xmit_int_vec ;; get the Xmit interrupt vector
|
||||
mov ah, XINT_MASK[bx] ;; get the Usarts interrupt bit
|
||||
not ah ;; reset this Usart's interrupt bit
|
||||
and al, ah ;; in the Xmit interrupt vector
|
||||
mov i3_xmit_int_vec, al ;; and the interfacer 3's
|
||||
out I3_XMIT_INT_MASK, al ;; interrupt mask port
|
||||
|
||||
push bx ;; save the input Q control addr
|
||||
mov bl, U_NUMB[bx] ;; get the usarts i3 number
|
||||
xor bh, bh ;; clear the upper byte
|
||||
inc bx ;; index above the SS usart
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ;; get the output Q control addr
|
||||
or OFLAG[bx], XOFF_PENDING ;; turn on the Xoff pending flag
|
||||
pop bx ;; restore the input Q control addr
|
||||
popf ;; turn the interrrupts back on
|
||||
|
||||
ret
|
||||
|
||||
|
||||
;============
|
||||
set_bit:
|
||||
;============
|
||||
;; ENTRY: ah = Bit to set in the Q state word
|
||||
;; bx -> Recv Q control structure
|
||||
;;
|
||||
;; EXIT: CMD_REG[bx] and the Usart's command register
|
||||
;; have the bits specified in ah set
|
||||
|
||||
push dx
|
||||
pushf ! cli ;; synchronize command register images
|
||||
mov al, U_NUMB[bx] ;; get the USART's number on the I3 bd
|
||||
cmp al, SS_U ;; select the usart if it's on the
|
||||
je set_bit1 ;; interfacer 3 board
|
||||
out I3_SELECT_REG, al ;; do the select
|
||||
set_bit1:
|
||||
mov al, CMD_REG[bx] ;; get the command resgisters image
|
||||
or al, ah ;; or in the bit(s)
|
||||
mov CMD_REG[bx], al ;; put back the new image
|
||||
xor dh,dh
|
||||
mov dl, U_PORTC[bx] ;; get the command port address
|
||||
out dx, al ;; send this image to the usart
|
||||
popf
|
||||
pop dx
|
||||
ret
|
||||
|
||||
|
||||
;=========
|
||||
clear_bit:
|
||||
;;========
|
||||
;;
|
||||
;; ENTRY: ah = Bit to clear in the Q state word
|
||||
;; bx -> Recv Q control structure
|
||||
;;
|
||||
;; EXIT: Q_STATE[bx] and the Usart's command register
|
||||
;; have the bits specified in ah cleared.
|
||||
|
||||
push dx
|
||||
pushf ! cli ;; synchronize command register images
|
||||
mov al, U_NUMB[bx] ;; get the USART's number on the I3 bd
|
||||
cmp al, SS_U ;; select the usart if it's on the
|
||||
je clr_bit1 ;; interfacer 3 board
|
||||
out I3_SELECT_REG, al ;; do the select
|
||||
clr_bit1:
|
||||
mov al, CMD_REG[bx] ;; get the command resgisters image
|
||||
not ah ;; create the AND mask
|
||||
and al, ah ;; AND off the bits specfied
|
||||
mov CMD_REG[bx], al ;; put back the new image
|
||||
xor dh,dh
|
||||
mov dl, U_PORTC[bx] ;; get the command port address
|
||||
out dx, al ;; send this image to the usart
|
||||
popf
|
||||
pop dx
|
||||
ret
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
i3_xmit_int_vec db 0
|
||||
|
||||
bit_mask_tbl db 80h, 40h, 20h, 10h, 08h, 04h, 02h, 01h
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
;************************************************
|
||||
;* Compupro System Support Board Equates *
|
||||
;* File Name: SSBOARD.EQU *
|
||||
;* Last Update: 2/10/84 *
|
||||
;************************************************
|
||||
|
||||
; Compupro system support board Usart definitions
|
||||
|
||||
ssdatav EQU 00000010b ;system support data available
|
||||
ssxmit EQU 00000001b ;system support transmit buffer empty
|
||||
ssdatset EQU 10000000b ;system support data set ready
|
||||
|
||||
; Compupro system support board port definitions
|
||||
|
||||
PORT_BASE EQU 50H
|
||||
|
||||
ssmode equ port_base + 0eh ; compupro system support mode
|
||||
sscmd equ port_base + 0fh ; compupro system support command
|
||||
ssstat equ port_base + 0dh ; compupro system support status
|
||||
ssdata equ port_base + 0ch ; compupro system support data
|
||||
|
||||
|
||||
SYS_SUP_USART equ 0ffh ; Usart number. When the OUSART
|
||||
; field is set to 0ffH it means
|
||||
; do not select this usart before
|
||||
; status, command, or read/write
|
||||
; operations.
|
||||
|
||||
NO_SELECT equ 0ffH ; Same as sys_sup_usart
|
||||
|
||||
SS_U equ NO_SELECT
|
||||
|
||||
SLAVE_PIC_PORT equ 52H ; used to turn off the SS usart
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
title 'System Support Board interrupt entry'
|
||||
|
||||
;*************************************************
|
||||
; *
|
||||
; SYSTEM SUPPORT BOARD MODULE *
|
||||
; Last changed: 2/10/84 *
|
||||
; *
|
||||
;*************************************************
|
||||
|
||||
include ssboard.equ
|
||||
|
||||
dseg
|
||||
|
||||
extrn ciqctl:byte
|
||||
extrn oq0desc:byte
|
||||
|
||||
cseg
|
||||
|
||||
public conin_int
|
||||
public sst_int
|
||||
extrn sysdat:word
|
||||
extrn reset_ssiint_pic:near
|
||||
extrn store_char:near
|
||||
extrn intco:near
|
||||
extrn reset_sstint_pic:near
|
||||
|
||||
;;-------
|
||||
sst_int: ;; System Support's Transmit Int Entry
|
||||
;;-------
|
||||
;;
|
||||
;; ENTRY: hardware interrupt from System Support's USART transmit ready.
|
||||
;;
|
||||
;; EXIT: back to the interrupted process
|
||||
|
||||
push ds ;; establish a data segment
|
||||
mov ds,sysdat
|
||||
mov conout_int_ss,ss ;; establish a stack
|
||||
mov conout_int_sp,sp
|
||||
mov ss,sysdat
|
||||
mov sp,offset conout_int_tos
|
||||
push ax ;; establish an environment
|
||||
push bx
|
||||
push dx
|
||||
|
||||
mov bx,offset oq0desc ;; bx -> system supports Xmit Q ctl
|
||||
call intco ;; send the character
|
||||
call reset_sstint_pic ;; set the PIC's IR line
|
||||
|
||||
pop dx ;; restore the environment
|
||||
pop bx
|
||||
pop ax
|
||||
mov ss,conout_int_ss ;; restore the stack
|
||||
mov sp,conout_int_sp
|
||||
pop ds ;; restore the Data Segment
|
||||
|
||||
iret ;; back to the process we interrupted
|
||||
|
||||
|
||||
|
||||
;
|
||||
; console output interrupt stack area
|
||||
|
||||
rw 32
|
||||
conout_int_tos rw 0
|
||||
conout_int_ss rw 1
|
||||
conout_int_sp rw 1
|
||||
|
||||
;;-------
|
||||
conin_int: ;; System Support's Conin Interrupt Entry
|
||||
;;---------
|
||||
;;
|
||||
|
||||
push ds ;; establish a local data segment
|
||||
mov ds, sysdat
|
||||
mov ss_save, ss ;; we need to establish a stack
|
||||
mov sp_save, sp ;; save the stask segment and offset
|
||||
mov ss, sysdat ;; new stack in our data segment
|
||||
mov sp, offset int_tos
|
||||
|
||||
push ax ;; save the environment
|
||||
push bx
|
||||
|
||||
in al, ssstat ;; get the system supports Usart status
|
||||
mov bh, al
|
||||
in al, ssdata ;; now get its data
|
||||
mov bl, al
|
||||
call reset_ssiint_pic
|
||||
mov ax, bx
|
||||
mov bx, offset ciQctl ;; get the Q control structure
|
||||
call store_char ;; store usart's status and data
|
||||
|
||||
pop bx ;; restore the environment
|
||||
pop ax
|
||||
mov ss, ss_save ;; restore the stack
|
||||
mov sp, sp_save
|
||||
pop ds ;; restore the data segment
|
||||
|
||||
iret
|
||||
|
||||
|
||||
ss_save dw 0 ; system support boards stack segment save
|
||||
sp_save dw 0 ; system support boards stack offset save
|
||||
rw 40
|
||||
int_tos:
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
|
||||
title 'Status Line module'
|
||||
|
||||
include system.lib
|
||||
include sysdat.lib
|
||||
include chrcomm.equ
|
||||
include serdata.equ
|
||||
|
||||
dseg
|
||||
|
||||
extrn vccb_tbl:word
|
||||
extrn ocdesctbl:word
|
||||
extrn f30_tbl:word
|
||||
|
||||
cseg
|
||||
|
||||
public io_statline
|
||||
;public update_stl
|
||||
|
||||
extrn usart_on:near
|
||||
|
||||
;===========
|
||||
io_statline:
|
||||
;===========
|
||||
;
|
||||
; CCP/M's entry point for status line updates
|
||||
;
|
||||
; ENTRY: DL = physical console
|
||||
;
|
||||
|
||||
xor bx,bx
|
||||
mov bl,dl ; physical console number
|
||||
|
||||
;fill in status line info here !!
|
||||
|
||||
push es ; save the UDA
|
||||
push dx ; save the Pcon
|
||||
|
||||
mov ax,ds ; set up for subsequent string
|
||||
mov es,ax ; moves
|
||||
|
||||
|
||||
|
||||
xor bx, bx ; get the Xmit Q control stucture
|
||||
mov bl, dl
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ; bx -> Xmit Q control Structure
|
||||
|
||||
mov bl, CUR_VCON[bx] ; al = current Vcon for this Pcon
|
||||
xor bh,bh
|
||||
shl bx,1
|
||||
; and al, 0fh
|
||||
|
||||
mov ax,f30_tbl[bx]
|
||||
test ax,0010H ; no update if in gen. graphic mode
|
||||
jz update
|
||||
;
|
||||
pop dx
|
||||
pop es
|
||||
ret
|
||||
|
||||
; Going to update status line
|
||||
|
||||
update: ;*** fill in console owner name
|
||||
mov si, vccb_tbl[bx] ; si -> VCCB for this Pcon's
|
||||
; current Vcon
|
||||
|
||||
mov si, [si] ; get pd addr from ccb
|
||||
add si, P_NAME ; move console owners
|
||||
mov di, offset st_name ; name into status line
|
||||
|
||||
mov cx,4
|
||||
cld
|
||||
rep movsw
|
||||
|
||||
;*** update Vcon field
|
||||
shr bx,1 ; get back Vcon number
|
||||
add bl,'0'
|
||||
mov vcon_numb,bl
|
||||
|
||||
|
||||
|
||||
mov al, dl ;*** fill in the physical console
|
||||
; and al, 0fh
|
||||
add al, '0'
|
||||
mov pcon_numb, al
|
||||
|
||||
|
||||
|
||||
mov di,offset st_open ;*** fill in open file drive letters
|
||||
mov cx, 6 ; 6 drives
|
||||
mov al,' ' ; clear open file string
|
||||
rep stosb
|
||||
|
||||
mov dx,open_vector
|
||||
mov di,offset st_open
|
||||
update0:
|
||||
shr dx,1! jnc update1
|
||||
mov al,cl
|
||||
add al,'A'
|
||||
stosb ;store drive letter
|
||||
update1:
|
||||
inc cx
|
||||
or dx,dx
|
||||
jnz update0 ;any more drives?
|
||||
|
||||
;
|
||||
; Send the status line to the console
|
||||
;
|
||||
|
||||
pop dx ; get the Pcon back
|
||||
pushf
|
||||
cli
|
||||
|
||||
; check for room in the con-out circular buffer
|
||||
; if ( omsgs - omsgcnt > st_len ) display the status line
|
||||
; also check for not being in the middle of an escape sequence
|
||||
|
||||
; get the physical Q control structure
|
||||
|
||||
xor dh, dh ; clear the high byte
|
||||
mov bx, dx
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ; bx -> Xmit Queue control
|
||||
|
||||
mov ax, ONMSGS
|
||||
sub ax, OMSGCNT[bx]
|
||||
cmp ax, ST_LEN ! jb stl_ret
|
||||
cmp OESC_CNT[bx], 0 ! jne stl_ret
|
||||
|
||||
stl_now:
|
||||
mov cx, ST_LEN - 1 ; length of the status line
|
||||
mov si, offset st_line ; addr of the status line
|
||||
mov dx, OMSGCNT[bx] ; the chars in Q
|
||||
mov bp, OMSGOUT[bx] ; current output pointer
|
||||
|
||||
st_line_lp:
|
||||
mov di, bp ; current char ptr => index reg
|
||||
add di, dx ; add in the number of chars waiting
|
||||
and di, (ONMSGS - 1) ; circular buffer...
|
||||
lodsb ; get a char from the st line
|
||||
mov OBUFFER[di+bx], al ; stuff the character
|
||||
inc dx ; bump char waiting count
|
||||
loop st_line_lp ; do it until the entire status line
|
||||
; is moved into the con out buffer
|
||||
|
||||
mov OMSGCNT[bx], dx ; put the updated number of chars
|
||||
; waiting to go out into the Q
|
||||
; control structure.
|
||||
|
||||
call usart_on ; start the engine ( if necessary )
|
||||
|
||||
stl_ret:
|
||||
popf
|
||||
pop es ; es = UDA
|
||||
|
||||
exit:
|
||||
ret
|
||||
|
||||
dseg
|
||||
|
||||
st_line db esc,'j' ;save cursor position
|
||||
db 0,0,0,0 ; wait for the Z 19
|
||||
|
||||
db esc,'x1' ;enable status line
|
||||
db esc,'Y' ;direct cursor address
|
||||
db 31+25,31+1 ; line 25, column 1
|
||||
|
||||
db 'Pcon='
|
||||
pcon_numb db '0' ;ascii Pcon number
|
||||
db ' ' ; visual delimiter
|
||||
|
||||
db 'Vcon='
|
||||
vcon_numb db '0' ; ascii Vcon number
|
||||
db ' ' ; visual delimiter
|
||||
|
||||
st_name db ' ' ;console owner process name
|
||||
db ' ' ; visual delimiter
|
||||
|
||||
st_open db 'xxxxxx' ;drives with open files
|
||||
|
||||
; db ;additional bytes for status line
|
||||
|
||||
db esc,'k' ;restore cursor position
|
||||
db 0,0,0,0
|
||||
db 0ffh
|
||||
st_len equ (offset $-1) - (offset st_line)
|
||||
|
||||
; table to indicate if special status line is being displayed currently
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
title 'Screen Switch module'
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* This module is the entry point for a screen switch *
|
||||
;* FILE NAME: switch.a86 *
|
||||
;* LAST UPDATE: 2/13/84 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
include system.lib
|
||||
include flags.equ
|
||||
include serdata.equ
|
||||
|
||||
eject
|
||||
|
||||
dseg
|
||||
|
||||
extrn ocdesctbl:word
|
||||
extrn f30_tbl: word
|
||||
|
||||
cseg
|
||||
|
||||
public io_switch
|
||||
extrn io_statline:near ;; in statlin.a86
|
||||
extrn vs_switch:near ;; in vscreen.a86
|
||||
extrn supif:near ;; in headentr.a86
|
||||
|
||||
;=========
|
||||
io_switch: ; Function 7: Switch Screen
|
||||
;=========
|
||||
;
|
||||
; input: dl = Vcon to switch to
|
||||
; dh = Pcon to do the switch on
|
||||
;
|
||||
|
||||
push dx ;; save the Pcon and Vcon
|
||||
|
||||
call vs_switch ;; does fully buffered screen
|
||||
;; switch.
|
||||
|
||||
pop dx ;; DH -> pcon, DL -> vcon
|
||||
call set_up_bx ;; BX -> output Q ctl structure
|
||||
|
||||
check_graph:
|
||||
mov CUR_VCON[bx],dl
|
||||
push dx ! push bx ;; and check for a graphics
|
||||
xor bh,bh ;; process that was flagwaited
|
||||
mov bl,dl
|
||||
shl bx,1
|
||||
mov bx, f30_tbl[bx]
|
||||
test bx, 010H ;; 010h = graphics is on
|
||||
jz go_stat
|
||||
xor dh,dh
|
||||
add dl, V_FLAG ;; Flag # = virt cons + bias
|
||||
mov cl, f_flagset ;; Do the system flag set.
|
||||
call supif
|
||||
go_stat:
|
||||
pop bx ! pop dx ;; DL -> phys cons #
|
||||
mov CUR_VCON[bx],dl
|
||||
mov dl, dh ;; get pcon
|
||||
jmp io_statline ;; update status line
|
||||
|
||||
|
||||
;-----------
|
||||
set_up_bx:
|
||||
;-----------
|
||||
|
||||
xor bx, bx
|
||||
mov bl, dh ;; use Pcon to index into the Xmit Q's
|
||||
shl bx, 1
|
||||
mov bx, ocdesctbl[bx] ;; bx -> Xmit Q control
|
||||
ret
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
;*********************************************************************
|
||||
;* sysdat for a RASM86 system.
|
||||
;*********************************************************************
|
||||
|
||||
supmod equ ds: word ptr .0H
|
||||
dispatcher equ ds: word ptr .38H
|
||||
mpmseg equ ds: word ptr .40H
|
||||
endseg equ ds: word ptr .44H
|
||||
rlr equ ds: word ptr .68H
|
||||
thrdrt equ ds: word ptr .72H
|
||||
qlr equ ds: word ptr .74H
|
||||
|
||||
version equ ds: word ptr .78H
|
||||
vernum equ ds: word ptr .7AH
|
||||
mpmvernum equ ds: word ptr .7CH
|
||||
tod equ ds: byte ptr .7EH
|
||||
|
||||
open_vector equ ds: word ptr .88H
|
||||
|
||||
;*********************************************************************
|
||||
;* end of system data area definition
|
||||
;*********************************************************************
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
|
||||
true equ 0ffffh ; value of TRUE
|
||||
false equ 0 ; value of FALSE
|
||||
|
||||
unknown equ 0 ; value to be filled in
|
||||
dskrecl equ 128 ; log. disk record len
|
||||
|
||||
fcblen equ 32 ; size of file control block
|
||||
pnamsiz equ 8 ; size of process name
|
||||
qnamsiz equ pnamsiz ; size of queue name
|
||||
fnamsiz equ pnamsiz ; size of file name
|
||||
ftypsiz equ 3 ; size of file type
|
||||
|
||||
ccpmint equ 224 ; int vec for ccpm ent.
|
||||
debugint equ ccpmint+1 ; int vec for debuggers
|
||||
|
||||
ulen equ 0100h ; size of uda
|
||||
pdlen equ 030h ; size of Process Descriptor
|
||||
|
||||
todlen equ 5 ; size of Time of Day struct
|
||||
flag_tick equ 1 ; flag 0 = tick flag
|
||||
flag_sec equ 2 ; flag 1 = second flag
|
||||
flag_min equ 3 ; flag 2 = minute flag
|
||||
|
||||
ldtabsiz equ 0aah ; ldtablen=11, 10 entries
|
||||
|
||||
npcons equ 2 ; total # physical consoles
|
||||
nvcons equ 8 ; total # virtual consoles
|
||||
|
||||
|
||||
;**********************
|
||||
;* SUP/RTM EQUATES
|
||||
;**********************
|
||||
|
||||
tracebit equ 0100H
|
||||
|
||||
P_DISPATCH equ 142
|
||||
f_dispatch equ 142 ; CCP/M dispatch func #
|
||||
f_terminate equ 143 ; CCP/M terminate func #
|
||||
f_polldev equ 131 ; CCP/M polldevice func #
|
||||
f_flagwait equ 132 ; CCP/M flagwait func #
|
||||
f_flagset equ 133 ; CCP/M flagset func #
|
||||
|
||||
p_flag equ word ptr 06H ; PD flag field
|
||||
p_name equ byte ptr 08H ; PD Name field
|
||||
p_uda equ word ptr 010H ; PD UDA Segment Addr
|
||||
p_cns equ byte ptr 020H ; PD console field
|
||||
|
||||
pf_keep equ 02H ; KEEP bit in p_flag
|
||||
|
||||
DELAY_F EQU 08DH
|
||||
DELAY_16_MS EQU 1 ; number of ticks to wait
|
||||
|
||||
ERROR EQU 0FFFFH
|
||||
|
||||
flag_ignore equ 02ah ; error code returned on flag ignore
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
|
||||
title 'Tick Module'
|
||||
|
||||
dseg
|
||||
|
||||
extrn dsr_check:byte
|
||||
|
||||
cseg
|
||||
|
||||
nolist
|
||||
include system.lib
|
||||
list
|
||||
|
||||
public tick_int
|
||||
|
||||
extrn int_latency:near ; public in ctc.a86
|
||||
extrn reset_tick_ctc:near ; public in pic.a86
|
||||
extrn reset_tick_pic:near ; public in ctc.a86
|
||||
|
||||
extrn sysdat:word ; public in headentr.a86
|
||||
extrn supif:near
|
||||
extrn dispatch:dword ; public in headentr.a86
|
||||
|
||||
extrn dsr_start:near
|
||||
|
||||
;========
|
||||
tick_int: ; tick interrupt entry
|
||||
;========
|
||||
; The responsibilities of this handler are:
|
||||
; 1] reset the tick hardware - the CTC and the PIC
|
||||
; 2] set the tick flag on every tick
|
||||
; 3] set the second flag once a second
|
||||
; 4] do a dispatch
|
||||
;
|
||||
; ENTRY: from the tick interrupt
|
||||
;
|
||||
; EXIT: system dispatch
|
||||
|
||||
push ds ; setup the system's data segment
|
||||
mov ds, sysdat
|
||||
|
||||
mov tick_ssreg, ss ; establish a stack for the tick
|
||||
mov tick_spreg, sp ; interrupt service routine
|
||||
mov ss, sysdat
|
||||
mov sp, offset tick_tos
|
||||
|
||||
push ax ; save the entire CPU context,
|
||||
push bx ; for the flag set calls
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
push si
|
||||
push bp
|
||||
push es
|
||||
|
||||
call int_latency ; measure how long it took to service
|
||||
; this interrupt
|
||||
call reset_tick_ctc ; reset the CTC for the next tick
|
||||
call reset_tick_pic ; reset the PIC for the next tick
|
||||
|
||||
mov dx, FLAG_TICK ; the tick flag is used when a
|
||||
mov cl, F_FLAGSET ; process is on the delay list.
|
||||
call supif
|
||||
|
||||
dec tick_count ; every second we have to set the
|
||||
jnz sec_done ; second flag
|
||||
mov tick_count, 60
|
||||
mov dx, FLAG_SEC
|
||||
mov cl, F_FLAGSET
|
||||
call supif
|
||||
sec_done:
|
||||
; this is specific to the compupro
|
||||
cmp dsr_check, TRUE ! jne dsr_done
|
||||
; we must need to check the dsr
|
||||
call dsr_start ; status of the USARTS on the interfacer 3
|
||||
dsr_done:
|
||||
pop es ; restore the CPU environment to
|
||||
pop bp ; what it was before the interrupt
|
||||
pop si
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
mov ss, tick_ssreg ; restore the pre-interrupt stack
|
||||
mov sp, tick_spreg
|
||||
|
||||
pop ds ; restore the pre-interrupt data seg
|
||||
|
||||
jmpf cs:dword ptr dispatch ; iret through the dispatcher.
|
||||
|
||||
|
||||
dseg
|
||||
|
||||
tick_bos rw 20H ; label the bottom of the stack
|
||||
; for debugging
|
||||
tick_tos:
|
||||
tick_ssreg dw 0 ; pre-interrupt SS stored here
|
||||
tick_spreg dw 0 ; pre-interrupt SP stored here
|
||||
|
||||
tick_count db 60 ; this tick count is used to
|
||||
; generate the second flag set call.
|
||||
; It is initialized to the number of
|
||||
; ticks per second.
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
|
||||
;********************************************************
|
||||
;* 2651 Usart Commmand And Status port equates *
|
||||
;* File Name: U2651.EQU *
|
||||
;* Last Update: 2/10/83 *
|
||||
;********************************************************
|
||||
|
||||
; usart's command registers bit equates
|
||||
|
||||
X_CTL equ 01H ; Set enables Xmitter
|
||||
DTR equ 02H ; 1 forces the DTR pin low
|
||||
R_CTL equ 04H ; Set enables the Receiver
|
||||
ERROR_RESET equ 10H ; Setting this resets the error flags
|
||||
RTS equ 20H ; 1 forces the RTS pin low
|
||||
|
||||
; usart's status register bit equates
|
||||
|
||||
TXRDY equ 01H ; Set = the Xmit buffer is empty
|
||||
RXRDY equ 02H ; Set = the Recv buffer has data
|
||||
PARITY_ERR equ 08H ; Set = parity error
|
||||
OVERRUN_ERR equ 10H ; Set = overrun error
|
||||
FRAME_ERR equ 20H ; Set = framing error
|
||||
DCD equ 40H ; Set means DCD is low
|
||||
DSR equ 80H ; Set means DSR is low
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
|
||||
title 'VCCBs for CCP/M'
|
||||
|
||||
;****************************************
|
||||
; *
|
||||
; VIRTUAL CONSOLE CONTROL BLOCKS *
|
||||
; Last changed: 2/13/84 *
|
||||
; *
|
||||
;****************************************
|
||||
|
||||
include system.lib
|
||||
|
||||
public vccb0
|
||||
public vccb_tbl,vrtl_phy
|
||||
|
||||
cgroup group vccb_seg
|
||||
|
||||
dseg
|
||||
|
||||
vccb_tbl dw offset vccb0 ; Pcon 0
|
||||
dw offset vccb1
|
||||
dw offset vccb2
|
||||
dw offset vccb3
|
||||
|
||||
dw offset vccb4 ; Pcon 1
|
||||
dw offset vccb5
|
||||
dw offset vccb6
|
||||
dw offset vccb7
|
||||
|
||||
vrtl_phy db 0
|
||||
db 0
|
||||
db 0
|
||||
db 0
|
||||
db 1
|
||||
db 1
|
||||
db 1
|
||||
db 1
|
||||
|
||||
vccb_seg dseg para
|
||||
|
||||
vccb0 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 0 ;physical console number
|
||||
db 0 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0000h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb1 ; virtual console link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb1 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 0 ;physical console number
|
||||
db 1 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb2 ; virtual console link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb2 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 0 ;physical console number
|
||||
db 2 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb3 ; virtual console link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb3 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 0 ;physical console number
|
||||
db 3 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw 0 ; last Vcon on Pcon 1
|
||||
dw 0 ;reserved
|
||||
|
||||
eject
|
||||
|
||||
vccb4 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 1 ;physical console number
|
||||
db 4 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0000h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb5 ; link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb5 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 1 ; physical console number
|
||||
db 5 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb6 ; link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb6 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 1 ;physical console number
|
||||
db 6 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw offset vccb7 ; link
|
||||
dw 0 ;reserved
|
||||
|
||||
vccb7 dw 0 ;owner
|
||||
dw 0,0,0 ;reserved
|
||||
db 0ffh,0ffh ;mimic, msource
|
||||
db 1 ; physical console number
|
||||
db 7 ;virtual console number
|
||||
dw 0 ;reserved
|
||||
dw 0002h ;state flags
|
||||
dw 10 ;max buffer size K bytes
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0,0 ;reserved
|
||||
dw 0,0 ;reserved
|
||||
dw 0 ; link, last vcon on pcon 1
|
||||
dw 0 ;reserved
|
||||
|
||||
end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
;*****************************************************************
|
||||
; *
|
||||
; VIRTUAL SCREEN STRUCTURES AND EQUATES *
|
||||
; *
|
||||
;*****************************************************************
|
||||
|
||||
|
||||
backsp equ 08H
|
||||
escape equ 01bH
|
||||
blank equ ' '
|
||||
|
||||
crt_col equ 80 ; screen sizings
|
||||
crt_row equ 24
|
||||
crt_size equ crt_col * crt_row
|
||||
crtfull equ 0
|
||||
|
||||
; Screen Structure
|
||||
vs_cursor equ word ptr 0[bx] ; cursor pts to attrib and char
|
||||
vs_oldcursor equ word ptr 2[bx]
|
||||
vs_column equ byte ptr 4[bx]
|
||||
vs_row equ byte ptr 5[bx]
|
||||
vs_mode equ byte ptr 6[bx] ; screen mode - see vsm values
|
||||
vs_attrib equ byte ptr 7[bx]
|
||||
vs_xy equ word ptr 8[bx] ; x-y coordinates for direct
|
||||
vs_old_xy equ word ptr 0aH[bx] ; cursor positioning
|
||||
vs_screen_seg equ word ptr 0cH[bx] ; for screen image buffer
|
||||
vs_escape_rt equ word ptr 0eH[bx] ; escape routine to ret to
|
||||
vs_struc_len equ 010h ; edge up to pp. boundary
|
||||
|
||||
; attribute bit values
|
||||
vsa_reverse equ 01110000B ; IBM PC compatible
|
||||
vsa_normal equ 00000111B
|
||||
vsa_blink equ 10000000B
|
||||
vsa_bright equ 00001000B
|
||||
|
||||
; mode bit values
|
||||
vsm_no_wrap equ 00000010B ; CCP/M only
|
||||
vsm_nocursor equ 00000100B
|
||||
|
||||
vccb_pcon equ 0ah
|
||||
vccb_vcon equ 0bh
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
xios = headentr[data[o[0]],m],
|
||||
intvec, pic, np_8087, ctc, tick,
|
||||
conout, serout, vscreen, conin, serin,
|
||||
ssint, i3int, servar, pcmode,
|
||||
statlin, list, switch, vccb, serdata,
|
||||
dentry, reskew, mdisk, dpbs, fd, hdisk
|
||||
|
||||
|
||||
Reference in New Issue
Block a user