Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

380 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; **********************************************************************
; initdira - Provides BIOS (XIOS) assembler interface for INITDIR.PLI
; - Also provides examples of how to:
; 1. Call CCP/M-86 XIOS
; 2. Lock up disk system for direct disk I/O
; 3. Lock up console, to prevent a job from being switched out
; **********************************************************************
cseg
public bstdma ; sets DMA segment and offset
public rdsec ; reads a physical sector
public sectrn ; translates a sector
public seldsk ; selects a drive
public setsec ; sets the sector to be read/written
public settrk ; sets the track to be read/written
public wrsec ; writes a physical sector
public openvec ; returns open files vector
public syslock ; locks up the disk system
public sysunlock ; unlocks the disk system
public conlock ; locks the console into foreground mode
public conunlock ; unclocks the console
IO_SELDSK equ 9 ; XIOS function number
IO_READ equ 10 ; XIOS function number
IO_WRITE equ 11 ; XIOS function number
P_PRIORITY equ 145 ; BDOS function: set Process PRIORITY
S_SYSDAT equ 154 ; BDOS function: get SYStem DATa page address
P_PDADR equ 156 ; BDOS function: get Process Descriptor address
Q_OPEN equ 135 ; Open Queue
Q_READC equ 138 ; Read Queue Conditional
Q_WRITEC equ 139 ; Write Queue Conditional
XIOS_ptr equ dword ptr .28h ; loc of XIOS entry in SYSDAT
OPVEC equ word ptr .88h ; loc of Open_Files_on_Drives vector
UDA_seg equ word ptr 10h ; loc of UDA seg in Process Descriptor
;*****************************************************************
;*** PL/I Utility Functions ***
;*****************************************************************
getp1: ; get single byte parameter to register DL
mov bx,[bx] ;BX = .char
mov dl,[bx] ;to register DL
ret
getp2: ; get single word value to DX
getp2i: ; same as getp2
mov bx,[bx]
mov dx,[bx]
ret
getsu: ;get sysdat and uda addrs
;enters: DS=local data seg
;exits: DS=SYSDAT seg, ES=UDA seg (for call to XIOS)
mov cx,udaaddr ;get the saved value
or cx,cx ;set flags
jz getsu1 ;uninitialized, go do the OS call
mov es,cx ;we've been here before, just load regs
mov cx,sysaddr
mov ds,cx
ret
getsu1:
mov cl,P_PDADR ;get Process Descriptor
int 0E0h ;call BDOS
mov cx,es:UDA_seg[bx] ;grab UDA_seg
mov udaaddr,cx ;save for future calls
push cx ;save UDA_seg
mov cl,S_SYSDAT ;get address of SYStem DATa area
int 0E0h ;call BDOS
mov cx,es ;mov ds,es
mov sysaddr,cx ;save for future calls
mov ds,cx
pop es ;restore UDA_seg
ret
;*****************************************************************
;*** Simulate old XIOS style functions ***
;*****************************************************************
bstdma: ; sets DMA segment and offset
call getp2 ;dma address to DX
mov dmaoff,dx ;stuff addr in IOPB's offset field
mov dmaseg,ds ;assume all addresses relative to DS
ret ;no BDOS/XIOS call, just init the IOPB
sectrn: ; translates a sector
call getp2 ;get sector number to DX
mov bx,dx ;no translation: return (unchanged) value
ret
setsec: ; sets the sector to be read/written
call getp2i ;sector number to DX
mov sector,dx ;stuff sector into IOPB
ret
settrk: ; sets the track to be read/written
call getp2i ;track number to DX
mov track,dx ;stuff track into IOPB
ret
;*****************************************************************
;*** Physical I/O calls ***
;*****************************************************************
rdsec: ; reads a physical sector
mov ax,IO_READ
jmp xiosiopb ;jump around this code
wrsec: ; writes a physical sector
mov ax,IO_WRITE ;fall thru to xiosiopb
xiosiopb: ;put the IOPB on the stack, call XIOS
push ds ;ds will contain SYSDAT seg
push es ;es will contain UDA seg
;someday change this to a block move?
mov ch,mscnt
mov cl,drv
push cx ;1st word of IOPB
mov cx,track
push cx ;2nd word
mov cx,sector
push cx ;3rd word
mov cx,dmaseg
push cx ;4th word
mov cx,dmaoff
push cx ;5th word
push ax ;save XIOS_function
call getsu ;set up DS-SYSDAT and ES-UDA
pop ax ;restore XIOS_function
callf XIOS_ptr ;call indirect the XIOS
;bl contains return status
pop cx ;dma offset
pop cx ;dma segment
pop cx ;track
pop cx ;sector
pop cx ;drv & mscnt
pop es ;restore original es
pop ds ;ditto for ds
ret
;*****************************************************************
;*** XIOS Select Disk Routine ***
;*****************************************************************
seldsk: ; selects a drive
; also resets login sequence number of drive to 0,
; to force permanent media to be logged in again on disk reset
call getp1 ;drive to DL
mov drv,dl ;stuff drive into IOPB
push es ! push ds ;save context ************
;do the XIOS SELDSK call
push dx ;save drive
call getsu ;set up DS and ES
pop cx ;restore drive
mov ax,IO_SELDSK
mov dx,0 ;this better not be the first call
callf XIOS_ptr ;call indirect XIOS
;xfer DPH locally
pop es ! push es ;restore & save Data Segment into es
mov di,offset dph ;set up destination
mov si,bx ;ptr to dph returned from XIOS call
mov log_seqn[si],0 ;force disk reset: 0 login sequence number
mov cx,dphsiz
rep movsb ;move copy of DPH into local storage
;xfer DPB locally
mov di,offset dpb ;set up destination
mov si,es:dpbptr ;get this info from DPH
mov cx,dpbsiz
rep movsb ;move copy of DPB into local storage
;cleanup
pop ds ! pop es ;restore context ************
mov dpbptr,offset dpb ;set up local ptr in DPH
mov bx,offset dph ;return address of local copy of DPH
ret
;*****************************************************************
;*** Open Drives Vector ***
;*****************************************************************
openvec: ; returns vector of drives with open files
push es ;save extra seg
push ds ;save data seg
mov cl,S_SYSDAT ;look in the system data page
int 0E0h ;call bdos
mov ax,es:OPVEC ;get the vector of drives containing open files
mov bx,ax ;stuff both regs
pop ds ;restore data seg
pop es ;restore extra seg
ret
;*****************************************************************
;*** System Lock and Unlock Routines ***
;*****************************************************************
syslock: ; locks up the disk system
; returns 0 in ax,bx if everything ok, -1 o.w.
push es ;save extra seg
push ds ;save data seg
mov cl,S_SYSDAT ;look in the system data page
int 0E0h ;call bdos
mov cx,es:OPVEC ;get the vector of drives containing open files
test cx,0FFFFh ;check all drives
jnz syslfail ;fail if any open files
mov cx,Q_OPEN
mov dx,offset qpb ;mxdisk queue parm block
int 0E0h ;call bdos
or ax,ax ;test return
jnz sysltry2 ;if non zero, try kluge
mov cx,Q_READC ;see if we can read the queue
mov dx,offset qpb ;insurance
int 0E0h ;call bdos
or ax,ax ;test retrun
jnz syslfail ;fail if we can't read mxdisk queue
jmp syslokay ;okay, tell 'em so
sysltry2: ;kluge for old systems
mov cx,Q_OPEN
mov dx,offset qpb2 ;mxdisk queue parm block
int 0E0h ;call bdos
or ax,ax ;test return
jnz syslfail ;if non zero
mov cx,Q_READC ;see if we can read the queue
mov dx,offset qpb2 ;insurance
int 0E0h ;call bdos
or ax,ax ;test retrun
jnz syslfail ;fail if we can't read mxdisk queue
syslokay:
mov ax,0 ! jmp syslret ;return code 0, everything okay
syslfail:
mov ax,0FFFFh ;return code -1, failure
syslret:
mov bx,ax ;stuff both regs
pop ds ;restore data seg
pop es ;restore extra seg
ret
sysunlock: ;undoes a 'syslock' function
mov cx,Q_WRITEC ;conditionally write to mxdisk queue
mov dx,offset qpb
int 0E0h
mov cx,Q_WRITEC ;kluge to handle old systems
mov dx,offset qpb2
int 0E0h
ret
;*****************************************************************
;*** Console Lock and Unlock Routines ***
;*****************************************************************
CCB_BACKGRD equ 0002h ;Console in Background mode
CCB_NOSWITCH equ 0008h ;Console not allowed to switch mode
CCB_SIZE equ 2Ch ;size of CCB
CCB_STATE equ word ptr 0Eh ;addr of Console State word in CCB
CON_NUM equ byte ptr 020h ;addr of console number in PD
CCB_PTR equ word ptr .054h ;addr of CCB table in SYSDAT
PD_FLAG equ word ptr 06 ;addr of FLAGs word in PD
PD_KEEP equ 0002h ;Keep Process Flag
TOP_PRIOR equ 151 ;What we set to for Top Priority (arbitrary)
REG_PRIOR equ 200 ;Default Regular Priority
conlock: ;locks the console into the foreground, sets Keep Flag,
; and boosts priority
;returns 0 in ax,dx if everything okay, -1 o.w.
push es ;save extra seg
call concalc ;ES=SYSDAT, bx=CCB offset
test es:CCB_STATE[bx],CCB_BACKGRD ;is console in background?
jnz conlfail ;background operation not allowed!
or es:CCB_STATE[bx],CCB_NOSWITCH ;make sure they don't switch
mov cl,P_PDADR ;get Process Descriptor
int 0E0h ;call BDOS
or es:PD_FLAG[bx],PD_KEEP ;set Keep flag
mov dl,TOP_PRIOR ;let's be quick
mov cl,P_PRIORITY ;set Priority
int 0E0h ;call BDOS
conlokay:
mov ax,0 ! jmp conlret
conlfail:
mov ax,0FFFFh
conlret:
mov bx,ax
pop es ;restore extra seg
ret
conunlock: ;undoes the 'conlock' function
push es ;save extra seg
call concalc ;ES=sysdat, bx=CCB offset
and es:CCB_STATE[bx],NOT CCB_NOSWITCH ;let them switch now
mov cl,P_PDADR ;get Process Descriptor
int 0E0h ;call BDOS
and es:PD_FLAG[bx],NOT PD_KEEP ;reset Keep flag
mov dl,REG_PRIOR ;finished with quick
mov cl,P_PRIORITY ;set Priority
int 0E0h ;call BDOS
pop es ;restore extra seg
ret
concalc: ;put SYSDAT in ES, offset of CCB in bx
mov cx,P_PDADR ;get Process Descriptor Addr
int 0E0h ;call the bdos
xor ax,ax ;clear ax
mov al,es:CON_NUM[bx] ;grab the console number
mov cx,CCB_SIZE ;stuff cx with size
mul cx ;compute ccb address
push ax ;save ccb offset
mov cl,S_SYSDAT ;get the System Data Segment
int 0E0h ;call the bdos
pop bx ;restore ccb offset
add bx,es:CCB_PTR ;compute offset of ccb
ret
;*****************************************************************
;*** Data Segment ***
;*****************************************************************
dseg
sysaddr dw 0 ; save location for sysdat addr
udaaddr dw 0 ; save location for process uda addr
dphsiz equ 014h ; size of Disk Parm Header
dph rb dphsiz ; local save area
log_seqn equ byte ptr 6 ; byte to force reset of permanent media
dpbptr equ word ptr dph+8 ; word of interest: DPB offset
dpbsiz equ 011h ; size of Disk Parameter Buffer
dpb rb dpbsiz ; local save area
iopb rb 0 ; the iopb structure filled in by above rtns
mscnt db 1 ; multi sector count
drv rb 1 ; select drive
track rw 1 ; select track
sector rw 1 ; select sector
dmaseg rw 1 ; set dma address
dmaoff rw 1 ; set dma address
iopbsiz equ (offset $)-(offset iopb)
qpb rb 0 ; queue parameter block
dw 0 ; reserved
dw 0 ; queueid
dw 0 ; nmsgs
dw 0 ; buffer
db 'MXdisk ' ; queue name
qpb2 rb 0 ; queue parameter block number 2: be persistent
dw 0 ; reserved
dw 0 ; queueid
dw 0 ; nmsgs
dw 0 ; buffer
db 'mxdisk ' ; queue name