Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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
;


File diff suppressed because it is too large Load Diff

View File

@@ -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
;*************************


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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

View File

@@ -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

View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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

View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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
;*********************************************************************


View File

@@ -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


View File

@@ -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


View File

@@ -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


View File

@@ -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

View File

@@ -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


View File

@@ -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