Input/Output Manager
IOMan provides common processing to all I/O operations.
nam Input/Output Manager
ttl Module Header
* Copyright 1980 by Motorola, Inc., and Microware Systems Corp.,
* Copyright 1982 by Microware Systems Corporation
* Reproduced Under License
* This source code is the proprietary confidential property of
* Microware Systems Corporation, and is provided to licensee
* solely for documentation and educational purposes. Reproduction,
* publication, or distribution in any form to any party other than
* the licensee is strictly prohibited!
* This is a disassembly of the IOMan edition 10 distributed with OS-9 for Dragon 128
* OS-9 Level 2. It contains modifications in some allocation routines.
***************
* I/O Manager
mod IOEnd,IOName,Systm+Objct,ReEnt+1,IOINIT,0
IOName fcs /IOMan/ module name
************************************************************
*
* Edition History
*
* Edition Date Comments
*
* 1 pre-82/08 beginning of history LAC
*
* 2 82/08/24 modifications for MC6829 LAC
*
* 3 82/09/27 conditionals added for LI & LII WGP
*
* 4 82/10/21 I$Deletx system call added WGP
*
* 5 83/01/17 change "F$Load" to set loading process priority
* and to not use the system process descriptor
*
* 6 83/02/18 change "PortBlk" to ignore untranslated
* address bits
* 83/02/24 Moved device termination routines from IODEL
* into DETACH. Minimized ATTACH and DETACH use
* of system's process pointer. Changed SCDIR
* to leave device table use count of old directory
* unchanged.
*
* 7 83/04/06 Removed testing for device being busy(re-entrant).
* This should be taken care of in the link call.
* Removed to take care of problems in using multiple
* devices at the same address. (IO Processor) RES
* 83/04/27 Change F$Load to open file before gobbling up
* it's large memory block.
*
* 8 83/05/04 extensive mods for non-contiguous modules.
* 83/06/16 fixed load bugs - mod dir entry returned must
* be searched for after load, by keeping block
* and offset for reference. Also link count is
* temporarily bumped to keep module around during
* load.
*
* 9 83/07/17 add limit checking for I$Read, I$ReadLn, I$Write,
* and I$WritLn
*
* 10 83/11/01 add error path/module messages, improved error printing
* Vivaway Ltd. PSD
fcb 10 edition number
use defsfile
ttl Initialization
page
**********
* Ioinit
* Entry Point For Start-Up Initialization
*
IOINIT ldx D.Init From configuration table
lda PollCnt,x get polling table entries
ldb #POLSIZ get entry size
mul get polling table size
pshs d save it
lda DEVCNT,X Get device table size
ldb #DEVSIZ
mul get device table size
addd 0,s add polling table size
addd #$FF
clrb round up to nearest page
os9 F$SRqMem allocate required I/O tbl memory
bcs CRASH Death: not enough memory
leax 0,u
IOINI1 clr ,x+ Clear systems I/O tables
subd #1
bhi IOINI1
stu D.PolTbl save addr of Polling tbl
ldd ,s++ polling tbl size
leax d,u allocate room for polling table
stx D.DevTbl Save device tbl addr
ldx D.PthDBT Signal pdbt allocation
os9 F$All64 Allocate/initialize pdbt
bcs CRASH ..can't run without memory
stx D.PthDBT Save path descriptor block tbl addr
os9 F$Ret64 Return unneeded pd
leax IOIRQ,pcr Get interrupt polling routine
stx D.Poll
leay <SVCTBL,pcr Get service initialization
os9 F$SSvc Init service routine entries
rts
**********
CRASH jmp [D$REBOOT] Doom
**********
page
**********
* Service Routine Initialization Table
*
system set $80 system only calls
user set $7F system or user calls
SVCTBL equ *
fcb $FF&user
fdb USERIO-*-2
fcb F$Load&user
fdb LOAD-*-2
ifgt LEVEL-1
fcb F$Load+SysState
fdb SysLoad-*-2
endc
fcb F$PERR&user
fdb PRTERR-*-2
ifne EXTERR
fcb F$InsErr&User
fdb InsErr-*-2
endc
fcb F$IOQu!system
fdb IOQUEU-*-2
fcb $FF!system
fdb SYSIO-*-2
fcb F$IRQ!system
fdb IOPOLL-*-2
fcb F$IODel!system
fdb IODel-*-2
fcb $80 end of table
page
**********
* Iodel
*
* Called When An I/O Module Is Unlinked For The
* Final Time. Error Returned if Module Busy, And
* Module Link Count Should Stay At One.
* Passed: (U)=Register Pack
* R$X,U=Module Addr
* Returns: CC=Set if Error
* Destroys: D
IODEL ldx R$X,u Get module addr
ldu D.Init From configuration module
ldb DevCnt,u Get device table size
ldu D.DevTbl Get device table address
IODEL10 ldy V$DESC,u empty table entry?
beq IODEL20 ..yes; skip it
cmpx V$DESC,u This logical device?
beq IODELErr ..yes; return error
cmpx V$DRIV,u This physical device driver?
beq IODELErr ..yes; return error
cmpx V$FMGR,u This file manager?
beq IODELErr ..yes; return error
IODEL20 leau DEVSIZ,u skip to next entry
decb
bne IODEL10 Loop until end of table
clrb return carry clear
rts
IODELErr comb I/O Delete module error
ldb #E$ModBsy Error: module busy
rts
ifgt LEVEL-1
***************
* Subrouting PortBlk
* Passed: (D)=MS port addr
* Returns: (D)=Port Extended Block number
* CC = Equal if port is in System's I/O Block
* Destroys:
PortBlk lsra
rorb
ifge DAT.BlSz-2048
lsra
rorb
ifge DAT.BlSz-4096
lsra
rorb
endc
endc
lsra
rorb (D)=Extended Block number
anda #DAT.BlMx/256 clear untranslated bits
ifle DAT.BlMx-255
ifeq MappedIO-true
cmpb #IOBlock System's I/O Block?
rts
else
endc
else
endc
endc
ttl File Manager I/O functions
page
UTABLE equ *
TBLBGN set UTABLE
fdb ATTACH-TBLBGN
fdb DETACH-TBLBGN
fdb UDUPE-TBLBGN
fdb UCREAT-TBLBGN
fdb UOPEN-TBLBGN
fdb UMDIR-TBLBGN
fdb UCDIR-TBLBGN
fdb UDELET-TBLBGN
fdb USEEK-TBLBGN
fdb UREAD-TBLBGN
fdb UWRITE-TBLBGN
fdb URDLN-TBLBGN
fdb UWRLN-TBLBGN
fdb UGSTT-TBLBGN
fdb USSTT-TBLBGN
fdb UCLOSE-TBLBGN
fdb UDELETX-TBLBGN
STABLE equ *
TBLBGN set STABLE
fdb ATTACH-TBLBGN Attach (x)=device, (a)=mode
fdb DETACH-TBLBGN Detach (u)=devtbl ptr
fdb SDUPE-TBLBGN (nop) duplicate (a)=pathnumber
* File Manager Name Functions
* (X)=Pathname Ptr
* (A)=Mode
fdb SCREAT-TBLBGN Create file
fdb SOPEN-TBLBGN Open file
fdb SMDIR-TBLBGN Make new directory
fdb SCDIR-TBLBGN Change directory
fdb SDELET-TBLBGN Delete (assumes write mode)
* File Manager Path Functions
* (A)=Path Number
fdb SSEEK-TBLBGN Seek to position (x,u)
fdb SREAD-TBLBGN read (x)=destin, (y)=count
fdb SWRITE-TBLBGN Write (x)=source, (y)=count
fdb SRDLN-TBLBGN readline (x)=destin, (y)=cnt
fdb SWRLN-TBLBGN writeline (x)=source, (y)=cnt
fdb SGSTT-TBLBGN Get status
fdb SSSTT-TBLBGN Set status
fdb SCLOSE-TBLBGN Close path
fdb SDELETX-TBLBGN Delete from execution directory
**********
* I/O Dispatcher
*
USERIO leax <UTABLE,pcr Use user table
bra SYSIO1
SysIO leax <STABLE,pcr Use system table
SYSIO1 cmpb #I$DeletX Function out of range?
bhi SYSIO2 ..yes; error
pshs b Save function code
lslb TIMES Two bytes per entry
ldd b,x Get offset of routine
leax d,x Form absolute entry of routine
puls b Restore function code
jmp 0,x Dispatch
SYSIO2 comb RETURN Carry set
ldb #E$UnkSvc Error: unknown service code
rts
page
**********
* Attach I/O Device
*
* Passed: (A)=R/W/Exec Mode
* (X)=Device Name Ptr
* Returns: (U)=Dev Tbl Ptr
*
org 0 Stack temporary storage
rmb DEVSIZ Temp device table entry
S.MODE rmb 1 R/w mode
S.BUSY rmb 1 Non-zero if device in use
S.PORT rmb 3 Temp port addr
S.DEVT rmb 2 Temp device table ptr
ifgt LEVEL-1
S.LclAdr rmb 2 Local Port Absolute addr
S.Block rmb 2 Port extended Block number
S.Proc rmb 2 user's process ptr
endc
S.STAK rmb 2 User's register stack
S.TMPS equ . Total temp size
ATTACH ldb #S.TMPS-1
ATTA02 clr ,-S Clear out temporary storage
decb
bpl ATTA02
stu S.STAK,S Save user stack ptr
lda R$A,u
sta S.MODE,s Save requested mode
ifgt LEVEL-1
ldx D.Proc get process ptr
stx S.Proc,s save it
leay P$DATImg,x get process dat image ptr
ldx D.SysPRC get syste, process ptr
stx D.Proc make current for link
endc
ldx R$X,u Get device name ptr
lda #DEVIC
ifeq LEVEL-1
OS9 F$Link link to device desc.
else
OS9 F$SLink Link device descriptor module (x)
endc
bcs ATTERR0 ..error; non-existing module
stu V$DESC,s Save addr
ldy S.STAK,s
stx R$X,y Return updated pathname to caller
ifgt LEVEL-1
lda M$PORT,u Port Extended Addr
sta S.PORT,S
endc
ldd M$PORT+1,u Get "base" port addr
std S.PORT+1,s Save it
ldd M$PDEV,u offset of driver module name
leax D,U Get absolute addr of name
lda #DRIVR
os9 F$Link Link device driver module
bcs ATTERR0 ..error; non-existing module
stu V$DRIV,s Save device driver module addr
ldu V$DESC,s get device descriptor addr
ldd M$FMGR,u offset of file mgr name
leax D,U Get absolute addr
lda #FLMGR
OS9 F$LINK Link file manager module
ATTERR0
ifgt LEVEL-1
ldx S.Proc,s get process ptr
stx D.Proc restore it
endc
bcc ATTA15 .. found; continue
ATTERR stb S.TMPS-1,S Save error code
leau 0,S Addr og psuedo device tbl entry
os9 I$Detach ..detach device
leas S.TMPS-1,s
comb
puls pc,b Return error
*
* Device Moudle Components Are All Located
* Search Device Tbl For Device
*
ATTA15 stu V$FMGR,S Save file manager module addr
ldx D.Init From configuration rom addr
ldb DevCnt,x Get device table entry count
lda DevCnt,x Save an extra copy
ldu D.DevTbl Get device tbl addr
ATTA20 ldx V$DESC,u Descriptor ptr
beq ATTA30 ..unused entry; skip
cmpx V$DESC,s Device descriptor module found?
bne ATTA25 ..no; continue
ldx V$STAT,u Is device in TERMINATE routine?
bne ATTA22 ..No; continue
pshs a
lda V$USRS,u TERMINATING PROCESS ID
beq ATTA21 ..ZERO; impossible
os9 F$IOQu Wait for termination
ATTA21 puls a
bra ATTA20 Try again
ATTA22 stu S.DEVT,s Save tbl ptr of found entry
ATTA25 ldx V$DESC,u Descriptor ptr
ldy M$PORT+1,x Get device port addr
cmpy S.PORT+1,s
bne ATTA30
ifgt LEVEL-1
ldy M$PORT,x
cmpy S.PORT,s Same PORT addr?
bne ATTA30 ..No
endc
ldx V$DRIV,u
cmpx V$DRIV,s Save device driver?
bne ATTA30 ..no; skip to next entry
ldx V$STAT,u Don't re-initialize it
stx V$STAT,s Save static memory of found driver
tst V$USRS,u Currently in use?
beq ATTA30 ..no; continue
sta S.BUSY,s Mark it busy (non-zero)
ATTA30 leau DEVSIZ,u Skip to next dev tbl entry
decb
bne ATTA20 Loop until there are no more
ldu S.DEVT,s Device descriptor already in table?
lbne ATTA70 yes; use same entry
*
* Create New Device Table Entry
*
ldu D.DevTbl Get device tbl addr
ATTA35 ldx V$DESC,u Search for a free entry
beq ATTA40 ..found one, exit loop
leau DEVSIZ,u Skip to next entry
deca
bne ATTA35 Loop until end of tbl
ldb #E$DevOvf Error: device table overflow
bra ATTERR
ERMODE ldb #E$BMode Error: illegal mode
bra ATTERR
* this code removed for edition 7
*
*ERBUSY ldb #E$DevBsy Error: device is busy
* bra ATTERR
*
* end of code removed for edition 7
ATTA40 ldx V$STAT,s Is device already initialized?
lbne ATTA60 ..yes; don't need new static
*
* Allocate New Static Storage For Device
*
stu S.DEVT,s save Dev Tbl Entry Ptr
ldx V$DRIV,s Get device driver addr
ldd M$Mem,x Driver Static Storable requirement
addd #$FF
clrb Round up to nearest page
os9 F$SRqMem request Device Static Storage
lbcs ATTERR ..ABORT if error
stu V$STAT,s Save static storage ptr
ATTA57 clr ,U+ Clear out driver static
subd #1
bhi ATTA57
* Map Port into System addr space
ifeq LEVEL-1
ldd S.Port+1,s get port addr off stack
else
ldd S.Port,s Get extended port addr
lbsr PortBlk convert to block addr
std S.Block,s save working block addr
ldu #0 clear DAT entry ptr
tfr u,y clear local address ptr
stu S.LclAdr,s System Local addr=0
ldx D.SysDAT get system DAT image ptr
IOMap20 ldd ,x++ get next DAT Entry
ifne DAT.WrEn+DAT.WrPr
endc
cmpd S.Block,S same as Desirec Block?
beq IOMap40 ..Yes; good
cmpd #DAT.Free Unused Entry?
bne IOMap30 ..No, continue
sty S.LclAdr,s save System Local addr
leau -2,x save DAT Image ptr
IOMap30 leay DAT.BLSz,y update Local Address
bne IOMap20 repeat until Total addr space searched
ldb #E$MemFul prime err: System process mem full
cmpu #0 free table entry found?
lbeq ATTERR ..No; ABORT: System Dat Image Fill
ldd S.Block,s
ifne DAT.WrEn
endc
std 0,u fill in DAT Image with block
ldx D.SysPRC get system process ptr
lda P$State,x
ora #ImgChg indicate DAT image change
sta P$State,x
os9 F$ID Dummy SVC call to update DAT image
ldy S.LclAdr,s get local address
* (D)=System Local addr corresponding to $XX X000 of addr
IOMap40 sty S.LclAdr,s save High order local addr
ldd S.Port+1,S LS 2-bytes of port addr
anda #^DAT.Addr strip off translated bits
addd S.LclAdr,s add to local block addr
endc
ldu V$STAT,s Device Static Storage ptr
clr V.PAGE,u
std V.PORT,u save abs port addr in Static storage
ldy V$DESC,s Pass Descriptor addr to Driver
ldx V$DRIV,s Driver Module addr
ldd M$EXEC,x Get execution addr
jsr D,X Execute dev driver's init routine
lbcs ATTERR ..error; return error code
ldu S.DEVT,s Device table ptr to new entry
ATTA60 ldb #DEVSIZ-1
ATTA65 lda B,S
sta B,U Copy new device table entry
decb
bpl ATTA65
ATTA70 ldx V$DESC,u Dev descriptor module ptr
ldb M$REVS,x Get re-entrant (sharable) bit
lda S.MODE,s Caller's mode specified?
anda M$MODE,x Check with device capabilities
ldx V$DRIV,u Get device driver ptr
anda M$MODE,x Compare with capabilities
cmpa S.MODE,s legal?
lbne ERMODE ..no; error: illegal mode
* this code removed for edition 7
*
* tst S.BUSY,S Device busy?
* beq ATTA90 ..no
* andb M$REVS,X Descriptor re-entrant bit
* bitb #REENT Sharable logical device?
* lbeq ERBUSY ..no; error: device busy
*ATTA90
*
* end of code remove for edition 7
inc V$USRS,u Update user count
bne ATTA91 branch if no overflow
dec V$USRS,u keep high count
ATTA91 ldx S.STAK,S
stu R$U,x Return device tbl ptr
leas S.TMPS,S
clrb RETURN Carry clear
rts
page
**********
* Process Detach Request
*
* Passed: (R$U)=Dev Tbl Entry Ptr
* Destroys: None
*
DETACH ldu R$U,u Get device tbl addr
ldx V$DESC,u (get for DETACH80)
lda #255
cmpa V$USRS,u high count
lbeq DETACH90 ..yes; don't detach
dec V$USRS,u Decrement user count
lbne DETACH80
* Device is not busy, so delete it's device table entry.
* First search for other devices using the same static
* storage, and if none are found, execute TERMINATE routine.
* (U)=device table ptr to delete
ldx D.Init
ldb DevCnt,x get device count
pshs u,b
ldx $02,u
clr $02,u
clr $03,u
ldy D.DevTbl
DETACH10 cmpx $02,y
beq DETACH20
leay DEVSIZ,y
decb
bne DETACH10
* Terminate Physical Device
* (X)-Static Storage Addr
ldy D.Proc
ldb P$ID,y
stb $08,u
ldy $04,u
ldu ,u
exg x,u
ldd $09,x
leax d,x
pshs u
jsr $0F,x
puls u
ldx 1,s
ldx V$Driv,x
ldd M$Mem,x
addd #$FF
clrb
os9 F$SRtMem
* Determine if this was the only active I/O port in it's
* memory block, and release the block if so
ldx 1,s
ldx V$DESC,x
ifgt LEVEL-1
ldd M$PORT,x
beq DETACH20 ..No port
lbsr PortBlk
beq DETACH20
tfr D,X
ldb 0,s Size of DevTbl
pshs x,b
ldu D.DevTbl
UnMap10 cmpu 4,s
beq UnMap20
ldx V$DESC,u
beq UnMap20
ldd M$PORT,x
beq UnMap20
lbsr PortBlk
cmpd 1,s
beq UnMap90
UnMap20 leau DevSiz,u
dec 0,s
bne UnMap10
ldx D.SysPRC
ldu D.SysDAT
ldy #DAT.BlCt number of DAT Blocks per image
UnMap25 ldd ,u++
ifne DAT.WrEn+DAT.WrPr
endc
cmpd 1,s
beq UnMap30
leay -1,y
bne UnMap25
* that's odd, block not found ???
bra UnMap90
UnMap30 ldd #DAT.Free
std -2,u mark DAT block as free
lda P$State,x
ora #ImgChg Inform system of image change
sta P$State,x
UnMap90 leas 3,S discard scratch
endc
DETACH20 puls u,b
ldx V$DESC,u
clr V$DESC,u
clr V$DESC+1,u
clr V$USRS,u
DETACH80
ifgt LEVEL-1
ldd D.Proc get user process ptr
pshs d save it
ldd D.SysPRC get system process ptr
std D.Proc make it current
endc
* (X)=V$DESC, U device descriptor ptr
ldy V$DRIV,u
ldu V$FMGR,u
os9 F$UnLink Unlink file manager
leau 0,y
os9 F$UnLink unlink device driver
leau 0,x
os9 F$UnLink unlink device descriptor
ifgt LEVEL-1
puls d retrieve user process ptr
std D.Proc restore it
endc
DETACH90 lbsr UnQueue Restart any process in I/O queue
clrb
rts
**********
* Dupe
* Process Path Duplication Request
*
UDUPE bsr FNDPTH
bcs SDUP90
pshs x,a
lda R$A,u
lda a,x
bsr SDUP10
bcs SDUPER
puls x,b
stb R$A,u
sta b,x
rts
SDUPER puls pc,x,a
SDUPE lda R$A,u
SDUP10 lbsr FPATH
bcs SDUP90
inc PD.CNT,y
SDUP90 rts
ttl I/O Name function calls
page
**********
* Fndpth
* Find Unused Entry in User'S Local Path Tbl
*
FNDPTH ldx D.Proc
leax P$PATH,x
clra
FNDPD1 tst a,x
beq FNDP90
inca
cmpa #NumPaths
bcs FNDPD1
comb
ldb #E$PthFul
rts
FNDP90 andcc #$FF-CARRY Return carry clear
rts
**********
* Open
* Process Open/Create Request
*
UCREAT equ *
UOPEN bsr FNDPTH
bcs UOPEN9
pshs u,x,a
bsr SOPEN
puls u,x,a
bcs UOPEN9
ldb R$A,u
stb a,x
sta R$A,u
UOPEN9 rts
SCREAT equ *
SOPEN pshs B
ldb R$A,u
bsr PDINIT
bcs SOPENX
puls b
lbsr FMEXEC
bcs SMDIR2
lda PD.PD,y
sta R$A,u
rts
SOPENX puls pc,a
**********
* Makdir
* Process Makdir Request
*
UMDIR equ *
SMDIR pshs b
ldb #DIR.+WRITE.
SMDIR1 bsr PDINIT
bcs SOPENX
puls b
lbsr FMEXEC
SMDIR2 pshs b,cc
ldu PD.DEV,y
os9 I$Detach
lda PD.PD,y
ldx D.PthDBT
os9 F$Ret64
puls pc,b,cc
**********
* Cdir
* Process Change Directory Request
*
UCDIR equ *
SCDIR pshs b
ldb R$A,u
orb #DIR.
bsr PDINIT
bcs SOPENX
puls b
lbsr FMEXEC
bcs SMDIR2
ldu D.Proc
ldb PD.MOD,y
bitb #PREAD.+PWRIT.+READ.+WRITE.
beq SCDIR2
ldx PD.DEV,y
stx P$DIO,u
inc V$USRS,x
bne SCDIR2
dec V$USRS,x
SCDIR2 bitb #PEXEC.+EXEC.
beq SCDIR5
ldx PD.DEV,y
stx P$DIO+6,u
inc V$USRS,x
bne SCDIR5
dec V$USRS,x
SCDIR5 clrb
bra SMDIR2
**********
* Delet
* Process Delete Request
*
UDELET equ *
SDELET pshs b
ldb #$02
bra SMDIR1
**********
* DeletX
* delete from specified directory
*
UDELETX equ *
SDELETX ldb #I$Delete
pshs B
ldb R$A,u
bra SMDIR1
**********
* Pdinit
*
PDINIT
ifeq LEVEL-1
pshs u
else
ldx D.Proc get current process ptr
pshs u,x save process & registers ptr
endc
ldx D.PthDBT Get addr of path descr block tbl
os9 F$All64
bcs PDIN90
inc PD.CNT,y
stb PD.MOD,y
ifeq LEVEL-1
PDIN10 lda ,x+
else
ldx D.Proc get process ptr
ldb P$Task,x get process task number
ldx R$X,u Get caller's pathname ptr
PDIN10 os9 F$LDABX get next character
leax 1,x move ptr
endc
cmpa #$20 Skip spaces
beq PDIN10
leax -1,x
stx R$X,u
ldb PD.MOD,y
cmpa #PDELIM
beq PDIN40
ldx D.Proc
bitb #$24
beq PDIN20
ldx P$DIO+6,x
bra PDIN30
PDIN20 ldx P$DIO,x
PDIN30 beq ERRBPN
ifgt LEVEL-1
ldd D.SysPRC get system process ptr
std D.Proc set current process ptr
endc
ldx V$DESC,x Device descriptor module ptr
ldd M$NAME,x
leax d,x
PDIN40 pshs y
os9 F$PrsNam
puls y
bcs ERRBPN
lda $01,y
os9 I$Attach
stu $03,y
bcs PDIN.ERR
ldx $04,u
leax <$11,x
ldb ,x+
leau <$20,y
cmpb #$20
bls PDIN60
ldb #$1F
PDIN50 lda ,x+
sta ,u+
PDIN60 decb
bpl PDIN50
clrb
PDIN90
ifeq LEVEL-1
puls PC,U
else
puls U,X retrieve current process ptr
stx D.Proc reset current process
rts
endc
ERRBPN ldb #E$BPNam
PDIN.ERR pshs b
lda PD.PD,y
ldx D.PthDBT
os9 F$Ret64
puls b
coma
bra PDIN90
ttl I/O Path function calls
page
**********
* Chkpth
* Validate User Path, And Map Into System Path
*
* Passed: (U)=User Regs, (R$A)=User Path#
* Returns: (A)=System Path#
* (X)=User Path Table Ptr
*
CHKPTH lda R$A,u
cmpa #NumPaths
bcc CHKERR
ldx D.Proc
leax P$PATH,x
andcc #$FF-CARRY
lda a,x
bne CHKP90
CHKERR comb
ldb #E$BPNum
CHKP90 rts
**********
* Seek
* Position File
*
USEEK bsr CHKPTH Validate path number
bcc SSEEK1 ..continue if va
rts
SSEEK lda R$A,u Get (system) path#
SSEEK1 bsr FPATH
lbcc FMEXEC
rts
**********
* Read
* Process Read Or Readln Request
*
UREAD equ *
URDLN bsr CHKPTH get user path #
bcc SRDLN1
rts
SREAD equ *
SRDLN lda R$A,u get user path
SRDLN1 pshs b
ldb #$05
SRDLN2 bsr FPATH
bcs SRDLNX
bitb PD.MOD,y test bits against mode in path desc
beq BADPTH
*
* check limits of read/write buffer
*
ldd R$Y,u else get count from user
beq SRDLN.d
addd R$X,u else update buffer pointer with size
bcs BADBUF
ifge LEVEL-2
subd #1
lsra
lsra
ifge DAT.BlSz-2048
lsra
ifge DAT.BlSz-4096
lsra
endc
endc
ldb R$X,u get address of buffer to hold read data
lsrb
lsrb
ifge DAT.BlSz-2048
lsrb
ifge DAT.BlSz-4096
lsrb
endc
endc
pshs b
suba ,s+
ldx D.Proc
leax P$DATImg,x
aslb
leax b,x
SRDLN.c pshs a
ldd ,x++
cmpd #DAT.Free
puls a
beq BADBUF
deca
bpl SRDLN.c
endc
SRDLN.d puls b
lbra FMEXEC
BADBUF ldb #E$Read
lda 0,s
bita #WRITE.
beq SRDLNX
ldb #E$Write
bra SRDLNX
BADPTH ldb #E$BPNam
SRDLNX com ,S+
rts
**********
* Write
* Process Write or Writeln Request
*
UWRITE equ *
UWRLN bsr CHKPTH
bcc SWRLN1
rts
SWRITE equ *
SWRLN lda R$A,u
SWRLN1 pshs b
ldb #$02
bra SRDLN2
FPath pshs x save x
ldx D.PthDBT
os9 F$Find64 Find (x)=path desc ptr
puls x retrieve x
lbcs CHKERR ..error; return useful error code
FPath9 rts
**********
* Gstt
* Process Getstat Request
*
UGSTT lbsr CHKPTH
ifgt LEVEL-1
ldx D.Proc get process ptr
endc
bcc SGSTT10 ..good
rts
SGSTT lda R$A,u
ifeq LEVEL-1
else
ldx D.SysPRC
SGSTT10 pshs x,b,a
lda R$B,u
sta $01,s
puls a
lbsr SSEEK1
puls x,a
pshs u,y,cc
tsta
beq SGSTT20
cmpa #$0E
beq SGSTT30
puls pc,u,y,cc
SGSTT20 lda D.SysTsk
ldb P$Task,x
leax PD.OPT,y
SGSTT25 ldy #32 Copy 32 Bytes
ldu R$X,u
os9 F$Move
leas 1,s
puls pc,u,y
SGSTT30 lda D.SysTsk
ldb P$Task,x
pshs D
ldx PD.DEV,y
ldx V$DESC,x
ldd M$Name,x
leax D,X
puls D
bra SGSTT25 move 32 bytes
endc
***********
* PSTT
USSTT equ USEEK
SSSTT equ SSEEK
**********
* Close
* Process Close Request
*
UCLOSE lbsr CHKPTH get user path #
bcs FPATH9
pshs b
ldb $01,u
clr b,x
puls b
bra SCLOS1
SCLOSE lda R$A,u
SCLOS1 bsr FPATH
bcs FPATH9
dec $02,y
tst $05,y
bne SCClos2
bsr FMEXEC
SCClos2 tst Pd.Cnt,y
bne FPATH9
lbra SMDIR2
***************
* Subroutine GainPath
* Gain control of Current Path
GainP.zz os9 F$IOQu
comb
ldb <$19,x
bne GainP.9
GainPath ldx D.Proc
ldb ,x
clra
lda $05,y
bne GainP.zz
stb $05,y
GainP.9 rts
***************
* Subroutine FMEXEC
* Dispatch To File MgrS Routine
*
* Passed: (B)=Function Code
* (Y)=Path Descriptor Ptr
* (U)=User'S Register Stack
* Error: B,CC=Set id Error
* Destroys: D
*
FMEXEC pshs u,y,x,b Save regs
bsr GainPath gain control of path
bcc FMEX20 ..gotten; continue
leas 1,S discard function code
bra FMEX30 ..Exit if Signal Error
FMEX20 stu PD.RGS,y Save user register stack
ldx PD.DEV,y Get device tbl entry address
ldx V$FMGR,x Get file manager module address
ldd M$EXEC,X
leax D,X Get file mgr's execution entry addr
ldb ,S+ Restore caller's function byte
subb #I$Create Make it an index
lda #3
mul TIMES 3 bytes per lbra entry
jsr D,X Exec file mgr's routine
FMEX30 pshs B,CC save error status, code
bsr UnQueue Wake Up next in I/O Queue
ldy 4,s path descriptor ptr
ldx D.Proc
lda P$ID,x get current process id
cmpa PD.CPR,y controlling Path Descriptor?
bne FMEX90 ..No
clr PD.CPR,y release path
FMEX90 puls pc,u,y,x,b,cc return
***************
* Subroutine UnQueue
* Wake next process in I/O queue (if any)
UnQueue pshs y,x save regs
ldy D.Proc
bra UnQue80 While not last proc in IO queue
UnQue10 clr P$IOQN,y clear next ptr
ldb #S$Wake
os9 F$Send wake up next process in queue
ifeq LEVEL-1
ldx D.PrcDBT
os9 F$Find64
else
os9 F$GProcP find next process descriptor
endc
clr P$IOQP,y clear previous link in next
UnQue80 lda P$IOQN,y process ID of next process
bne UnQue10 Endwhile
puls pc,y,x
page
***************
* Irq Service Routines
* ====================
************************
* Irq Polling Table Format
*
* Polling Address (2)
* Flip Byte (1)
* Poll Mask (1) Must Be Non-Zero
* Service Address (2)
* Static Storage (2) Must Be Unique To Device
* Priority (1) 0=Lowest, 255=Highest
*
* Irq Polling Table Maintenance Entry Point
*
* (U)=Caller'S Register Save
* R$D,U=Polling Addr
* R$X,U=Ptr To Flip,Mask,Priority
* R$Y,U=Service Addr
* R$U,U=Storage Addr
*
IOPOLL ldx R$X,u Get ptr to flip,mask,priority
ldb 0,x
ldx 1,x
clra default carry clear
pshs cc save Interrupt State
pshs x,b Save flip,mask,priority
ldx D.Init From configuration rom addr
ldb PollCnt,x Get polling table entry count
ldx D.PolTbl Get addr of polling tbl
ldy R$X,u Delete?
beq IOPOL4 ..yes
tst 1,s Mask zero?
beq POLFUL ..yes; error: mask must be non-zero
decb
lda #POLSIZ
mul
leax D,X Compute addr of last tbl entry
lda Q$MASK,x Is the table full (mask not 0)?
bne POLFUL ..yes; error: polling table full
orcc #IntMasks Disable IRQs during Maintenance
IOPOL1 ldb 2,s Get priority of new device
cmpb (Q$PRTY-POLSIZ),X Above the previous entry's?
bcs IOPOL3 ..no; insert it here in the table
ldb #POLSIZ
IOPO11 lda ,-x
sta POLSIZ,x Copy table entry down
decb
bne IOPO11 (move to next higher entry)
cmpx D.PolTbl Is this the top of the table?
bhi IOPOL1 ..no; repeat
IOPOL3 ldd R$D,u Copy parameters into tbl entry
std Q$POLL,x ..polling address
ldd ,s++
sta Q$FLIP,x ..flip
stb Q$MASK,x ..masl
ldb ,s+
stb Q$PRTY,x ..priority
ldd R$Y,u
std Q$SERV,x ..service address
ldd R$U,u
std Q$STAT,x ..static storage address
puls PC,CC return (carry clear)
* Delete An Entry From Polling Tbl
IOPOL4 leas 4,s Clean up stack
ldy R$U,u Caller's static address
IOPOL5 cmpy Q$STAT,x Is this the entry?
beq IOPOL6 ..yes; good
leax POLSIZ,x Skip to next table entry
decb end of table?
bne IOPOL5 ..no; repeat
* Error? - Table Entry Not Found
clrb return Carry clear
IORTS rts
IOPOL6 pshs b,cc Save entry count
orcc #IntMasks Disable IRQs during Maintenance
bra IOPO75
IOPOL7 ldb POLSIZ,x
stb ,x+ Copy next entry up over this one
deca
bne IOPOL7 (move down to next entry)
IOPO75 lda #POLSIZ Get polling table entry size
dec 1,s At last entry yet?
bne IOPOL7 ..no; copy another entry
IOPOL8 clr ,x+ Clear out last entry
deca
bne IOPOL8
puls pc,a,cc return
POLFUL leas 4,S discard temps
POLLERR comb return carry set
ldb #E$Poll Error: polling table entry not found
rts
page
***************
* Irq Polling Routine
* ===================
* Polling Table Format:
* Polling Address (2)
* Flip Byte (1)
* Poll Mask (1)
* Service Address (2)
* Static Storage (2)
* Priority (1)
* Interrupt Request (Irq) Service Entry Point
IOIRQ ldy D.PolTbl Get addr of polling table
ldx D.Init From configuration module
ldb PollCnt,x Get polling table entry count
bra IOIRQ2
IOIRQ1 leay POLSIZ,y Skip to next entry in table
decb end of table?
beq POLLERR ..yes; exit - not found
IOIRQ2 lda [Q$POLL,y] Poll device
eora Q$FLIP,y Flip any inverted hardware bits
bita Q$MASK,y Is device interrupting?
beq IOIRQ1 ..no; go try next device
ldu Q$STAT,y Get storage for device handler
pshs Y,B
jsr [Q$SERV,y] Exec interrupt service routine
puls y,b
bcs IOIRQ1 false interrupt, keep checking
rts
page
ifeq LEVEL-1
jmp NOWHERE
else
************************************************************
*
* Subroutine Load
*
* Load Module service routine
*
Load pshs u save registers ptr
ldx R$X,u get path name ptr
bsr LModule load module
bcs LoadXit
puls y
Load.A pshs y
stx R$X,y save updated pathlist
ldy ,u get DAT image pointer
ldx $04,u get offset within DAT image
ldd #$0006
os9 F$LDDDXY
ldx ,s
std $01,x
leax ,u
os9 F$ELink
bcs LoadXit
ldx ,s
sty $06,x
stu $08,x
LoadXit puls pc,u
page
************************************************************
*
* Subroutine Sysload
*
SysLoad pshs u save registers ptr
ldx R$X,u get name string ptr
bsr LModule load module
bcs SysLXit branch if error
puls y retrieve registers ptr
ldd D.Proc get current process ptr
pshs y,d save registers
ldd R$U,y get process ptr
std D.Proc make it current
bsr Load.A link loaded module
puls x retrieve current process ptr
stx D.Proc reset current process
SysLXit puls pc,u
page
************************************************************
*
* Subroutine Lmodule
*
* Open specified path, read and validate modules until error
realorg set .
org 0
TotRAM rmb 2 total ram acquired for block
TotMod rmb 2 total module size in block
CurrProc rmb 2 current process ptr
Path rmb 1 path number
ErrCode rmb 1 error code
Header rmb M$IDSize module header scratch
locals set .
org realorg
ModPtr set locals+0 Module block offset
PathName set locals+2 Path name string ptr
ProcPtr set locals+4 temporary process ptr
ModBlk set locals+6 Module block number
stacked set 0
LModule os9 F$AllPrc get process descriptor
bcc LMod.1
rts
LMod.1 leay 0,u copy process ptr
ldu #0 clear directory entry ptr
pshs u,y,x,b,a save registers
leas -locals,s make room for scratch
clr ErrCode+stacked,s clear error code
stu TotRAM+stacked,s
stu TotMod+stacked,s
ldu D.Proc
stu CurrProc+stacked,s
clr Path+stacked,s
lda P$Prior,u get priority
sta P$Prior,y save
lda #EXEC. from exec dir
os9 I$Open
bcs LModErr
sta Path+stacked,s
stx PathName+stacked,s
ldx ProcPtr+stacked,s
os9 F$AllTsk
bcs LModErr
stx D.Proc
LMod.J ldd #M$IDSize
ldx TotMod+stacked,s
lbsr GetModul
bcs LModErr
ldu ProcPtr+stacked,s
lda P$Task,u
ldb D.SysTsk
leau Header+stacked,s
pshs x
stacked set stacked+2
ldx ToTMod+stacked,s
os9 F$Move
puls x
stacked set stacked-2
ldd 0,u get module sync bytes
cmpd #M$ID12
bne LModErrA
ldd M$Size,u
subd #M$IDSize
* X already contains old modsiz + new ID
lbsr GetModul
bcs LModErr
ldy <$15,s get proc desc ptr
leay <P$DATImg,y
tfr y,d
ldx $02,s
os9 F$VModul
bcc LMod.K
cmpb #E$KwnMod
beq LMod.L
bra LModErr
LMod.K ldd $02,s
addd $0A,s
std $02,s
LMod.L ldd <$17,s
bne LMod.J
ldd MD$MPtr,u
std <$11,s
ldx MD$MPDAT,u
ldd 0,x
std <$17,s
ldd $06,u
addd #1
beq LMod.J
std MD$Link,u
bra LMod.J
LModErrA ldb #E$BMID
LModErr stb $07,s
ldd $04,s
beq LMod.M
std D.Proc
LMod.M lda $06,s
beq LMod.O
os9 I$Close
LMod.O ldd $02,s
addd #DAT.BlSz-1 round to next block
lsra get block number
lsra
ifge DAT.BlSz-2048
lsra
ifge DAT.BlSz-4096
lsra
endc
endc
sta TotMod+stacked,s save block number
ldb ,s
beq LMod.Q
lsrb make block count
lsrb
ifge DAT.BlSz-2048
lsrb
ifge DAT.BlSz-4096
lsrb
endc
endc
subb $02,s
beq LMod.Q
ldx <$15,s
leax <P$DATImg,x
lsla
leax a,x
clra
tfr d,y
ldu D.BlkMap
LMod.O2 ldd ,x++
clr d,u
leay -$01,y
bne LMod.O2
LMod.Q ldx <$15,s
lda P$ID,x
os9 F$DelPrc
ldd <$17,s
bne LMod.R
ldb $07,s
stb <$12,s
comb
bra LModXit
LMod.R ldu D.ModDir
ldx <$11,s
ldd <$17,s
leau -MD$ESize,u
LMod.S leau MD$ESize,u
cmpu D.ModEnd
bcs LMod.T
comb
ldb #E$MNF
stb <$12,s
bra LModXit
LMod.T cmpx MD$MPtr,u
bne LMod.S
cmpd [MD$MPDAT,u]
bne LMod.S
ldd MD$Link,u
beq LMod.U
subd #1
std MD$Link,u
LMod.U stu <$17,s
clrb
LModXit leas <$11,s
puls pc,u,y,x,b,a
page
stacked set stacked+8
*****************************************************
*
* GetModul routine
*
* Input: D = Size of new section
* X = Present module size in RAM
*
* Output: X = New module size in RAM
*
GetModul pshs y,x,b,a save regs
addd 2,s find new totmod size
std 4,s save it for caller
cmpd TotRAM+stacked,s is there enough RAM?
ifeq CPUType-DRG128
lbls GetM.R yes. skip mem request
else
bls GetM.R yes. skip mem request
endc
addd #DAT.BlSz-1 round to next block
lsra
lsra
ifge DAT.BlSz-2048
lsra
ifge DAT.BlSz-4096
lsra
endc
endc
cmpa #DAT.BlCt-1 check for full map
bhi GetM.Err bra if so
ldb TotRAM+stacked,s get RAM used
lsrb
lsrb get blks RAM used
ifge DAT.BlSz-2048
lsrb
ifge DAT.BlSz-4096
lsrb
endc
endc
pshs b stack it
exg b,a
subb ,s+
lsla
ldu ProcPtr+stacked,s
leau P$DATImg,u
leau a,u
clra
tfr d,x
ldy D.BlkMap
clra
TESTM set 0
ifeq CPUTYPE-DRG128+TESTM
ldb #DAT.GBlk start above graphics blocks
leay b,y
else
clrb
endc
GetM.B tst ,y+ chk if blk free
beq GetM.D bra if so
GetM.C addd #1 update blk number
cmpy D.BlkMap+2
bne GetM.B
ifeq CPUTYPE-DRG128+TESTM
ldy D.BlkMap now try graphics blocks
clra
GetM.F pshs y
leay BlkTrans,pcr
ldb a,y
puls y
tst b,y
beq GetM.H
GetM.G inca
cmpa #DAT.GBlk
bcs GetM.F
endc
GetM.Err comb
ldb #E$MemFul
bra GetM.X exit
ifeq CPUTYPE-DRG128+TESTM
GetM.H inc b,y
clr ,u+
stb ,u+
pshs a
stacked set stacked+1
ldd $09,s
addd #DAT.BlSz
std $09,s
puls a
stacked set stacked-1
leax -1,x
bne GetM.G
bra GetM.I
endc
GetM.D inc -1,y
std ,u++
stacked set stacked+2
pshs d
ldd $0A,s
addd #DAT.BlSz
std $0A,s
puls d
stacked set stacked-2
leax -1,x
bne GetM.C
GetM.I ldx <$1D,s
os9 F$SetTsk
bcs GetM.X
GetM.R lda $0E,s
ldx $02,s
ldy ,s
os9 I$Read
GetM.X leas 4,s return scratch
puls pc,x done
ifeq CPUTYPE-DRG128
*
* Graphics block translation table.
* Optimizes graphics memory allocation
*
BlkTrans fcb $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F
fcb $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F
endc
page
endc
*****
*
* Print Error Routine
*
ifne EXTERR
**********************************************
*
* Subroutine PrtErr
*
* Print error message
*
* Input: U = registers pointer
* R$B,U=error number
*
* Output: U unchanged
* Carry clear
*
* Data: D.Proc, D.SysPrc
*
* Calls: F$Link, F$Unlink, I$Open, I$Close,
* I$ReadLn, I$WritLn
*
* CAUTION: THIS SUBROUTINE TAKES 100+ BYTES OF STACK
*
* The mechanism.
* A 32 byte space in the process descriptor of each process
* is reserved for a name/pathlist of a module or file
* that is assumed to contain the error messages for that
* process. This name is installed by a call to InsErr,
* (F$InsErr). When PrtErr is called, this name is first
* used to try and link to a module, then to a file,
* in the EXEC mode. Both file and module
* have the same structure - i.e., the file is the module
* on disk! The message table in the module/file is then
* searched for the error number, just as in Printerr. If
* it is not found, or no module or file could be found,
* there is a default for the whole system, and a process
* can install a replacement for a subset of error numbers.
* Because of the module structure - the offset
* to the table follows the memory size in the header -
* program modules can contain error message tables that
* they install themselves. Because the structure is that
* of a module, but can also be read from disk, error
* message tables can be left on disk to save memory, or
* loaded into memory for speed.
*
PrtBufSz equ 80
org 0
PrtPath rmb 1
PrtNum rmb 1
PrtProc rmb 2
PrtMod rmb 2
PrtTbl rmb 2
PrtEPath rmb 1
PrtPFlag rmb 1
PrtFlag rmb 1
PrtBuf rmb PrtBufSz
PrtMem equ .
PrtErr ldb R$B,u
beq PrtErr90
ldx D.Proc
lda <P$PATH+2,x get stderr path
beq PrtErr90 return if not there
pshs u
leas -PrtMem,s
leau ,s
std 0,u
stx $02,u
ldy D.SysPRC
sty D.Proc
lbsr PrtErrNm Write label and error number
clr $0A,u
ldx $02,u
PrtErr10 leax P$ErrNam,x
clr $09,u
pshs u,x
clra
os9 F$Link
tfr u,y
puls u,x
sty $04,u
bcc PrtErr20
lda #$05
os9 I$Open
sta $08,u
inc $09,u
bcc PrtErr20
PrtErr15 tst $0A,u
bne PrtErr85
inc $0A,u
ldx D.SysPRC
bra PrtErr10
PrtErr85 lda #C$CR just print CR-LF
pshs a
leax ,s
ldy #1
lbsr PrtLine
leas 1,s
bra PrtErr95
PrtErr80 lbsr PrtUndo
PrtErr95 ldy $02,u
sty D.Proc
leas <$5B,s
puls u
PrtErr90 clrb
rts
PrtErr20 tst $09,u
bne PrtErr30
ldx $04,u
ldd $0D,x
leax d,x
stx $06,u
bra PrtErr40
PrtErr30 ldx #$000D
bsr PrtSeek
bcs PrtErr70
lda $08,u
ldy #$0002
leas -$02,s
leax ,s
os9 I$Read
puls x
bcs PrtErr70
bsr PrtSeek
bcs PrtErr70
PrtErr40 lbsr PrtRdRcd
bcs PrtErr70
lbsr PrtGetNm
beq PrtErr70
cmpb $01,u
bne PrtErr40
pshs x
leax >ErrMsg2,pcr Write hyphen
ldy #$0003
bsr PrtLine
puls x
PrtErr50 ldy #PrtBufSz-1
bsr PrtLine
bsr PrtRdRcd
bcs PrtErr80
lda ,x+
beq PrtErr80
cmpa #$30
bcs PrtErr50
bra PrtErr80
PrtErr70 bsr PrtUndo
lbra PrtErr15
PrtErrNm leax ErrMsg1,pcr
ldy #MsgLen1 string length
bsr PrtLine
ldb PrtNum,u
leax PrtBuf,u
tfr x,y
lda #'0-1
PrtNm1 inca
subb #100
bcc PrtNm1
sta ,y+
lda #'9+1
PrtNm2 deca
addb #10
bcc PrtNm2
sta ,y+
addb #'0
stb ,y+
ldy #3
* Fall through to print it
PrtLine lda ,u
os9 I$WritLn
rts
PrtSeek lda $08,u
pshs u,x
tfr x,u
ldx #0
os9 I$Seek
puls pc,u,x
PrtUndo lda $08,u
tst $09,u
bne PrtUndo1
pshs u
ldu $04,u
os9 F$UnLink
puls pc,u
PrtUndo1 os9 I$Close
rts
PrtRdRcd leax PrtBuf,u point at the buffer
ldy #PrtBufSz max line length
lda PrtEPath,u get path number
tst PrtPFlag,u
beq PrtRd10 ..none; must be a module
os9 I$ReadLn read a line
rts
PrtRd10 tfr y,d put buffer size in B
ldy PrtTbl,u get table ptr
PrtRd20 lda ,y+
sta ,x+ put in buffer
decb end of buffer?
beq PrtRd30 ..yes
cmpa #C$CR end of line?
bne PrtRd20 ..no; get more
PrtRd30 leax PrtBuf,u retrieve buffer ptr
sty PrtTbl,u update table ptr
clrb
rts
PrtGetNm clrb initialise counter
PrtGet10 lda ,x+ get a chr
beq PrtGet20 ..end of table
suba #'0 name numeric
bcs PrtGet30 ..exit if separator
pshs a save digit
lda #10
mul multiply present result by 10
addb ,s+ add new digit
bra PrtGet10 next!
PrtGet20 tstb check answer
PrtGet30 rts
ErrMsg1 fcc 'Error #'
MsgLen1 equ *-ErrMsg1
ErrMsg2 fcc ' - '
MsgLen2 equ *-ErrMsg2
******************************
*
* Subroutine InsErr
*
* Install error message path/module
* name string
*
* Input: U = Registers ptr
* R$X,U=ptr to name string
*
* Output: U unchanged
* Carry set if error, B has error code
*
* Data: D.Proc
*
* Calls: F$Move, F$Link, F$UnLink, I$Open, I$Close
*
* The name string MUST be 32 chrs or less
*
InsErr pshs u
ldx R$X,u
clra
os9 F$Link Is it already loaded?
bcs InsErr1 ..no, then try to open the file
pshs x
os9 F$UnLink
bra InsErr2
InsErr1 ldu ,s
ldx R$X,u
lda #READ.
os9 I$Open
bcs InsErrx
pshs x
os9 I$Close
InsErr2 ldu D.Proc
lda P$Task,u
ldb D.SysTsk
ldy #$0020
leau P$ErrNam,u
ldx $02,s
ldx $04,x
os9 F$Move
ldu $02,s
puls x
stx R$X,u
clrb
InsErrx puls pc,u
else
* Normal error service
********************************
*
* F$PErr System call entry point
*
* Entry: U = Register stack pointer
*
ErrMsg1 fcc "ERROR #"
ErrNum equ *-ErrMsg1
fcb '0-1,'9+1,'0
fcb C$CR
ErrMessL equ *-ErrMsg1
PrtErr ldx D.Proc
lda <P$PATH+2,x get stderr path
beq L08CC
leas -ErrMessL,s make room on stack
leax <ErrMsg1,pcr
leay ,s
L0893 lda ,x+
sta ,y+
cmpa #C$CR done?
bne L0893
ldb R$B,u
* Convert error code to decimal
L089D inc ErrNum+0,s
subb #100
bcc L089D
L08A3 dec ErrNum+1,s
addb #10
bcc L08A3
addb #$30
stb ErrNum+2,s
ldx D.Proc
ldu P$SP,x get the stack pointer
leau -ErrMessL,u put a buffer on it
lda D.SysTsk
ldb P$Task,x get task number of process
leax ,s
ldy #ErrMessL get length of text
L08BD os9 F$Move
leax ,u
ldu D.Proc
lda <P$PATH+2,u get path number
os9 I$WritLn
leas ErrMessL,s purge the buffer
L08CC rts
endc
page
*****
*
* Subroutine Ioqueu
*
* Link Process Into Ioqueue And Go To Sleep
*
IOQueu ldy D.Proc
IOQ.A lda P$IOQN,y
beq IOQ.C
cmpa R$A,u
bne IOQ.B
clr P$IOQN,y
ifeq LEVEL-1
ldx D.PrcDBT
os9 F$Find64
else
os9 F$GProcP get process ptr
endc
bcs IOQuExit
clr P$IOQP,y
ldb #S$Wake
os9 F$Send
bra IOQ.E
IOQ.B
ifeq LEVEL-1
else
os9 F$GProcP get process ptr
endc
bcc IOQ.A
IOQ.C lda R$A,u
IOQ.D
ifeq LEVEL-1
else
os9 F$GProcP get process ptr
endc
bcs IOQuExit
IOQ.E lda P$IOQN,y
bne IOQ.D
ldx D.Proc
lda P$ID,x
sta P$IOQN,y
lda P$ID,y
sta P$IOQP,x
ldx #0
os9 F$Sleep
ldu D.Proc
lda P$IOQP,u
beq IOQ.F
ifeq LEVEL-1
ldx D.PrcDBT
os9 F$Find64
else
os9 F$GProcP get process ptr
endc
bcs IOQ.F branch if dead
lda P$IOQN,y normal queue exit?
beq IOQ.F branch if so
*
* Graceful Abnormal Queue Queue Exit
*
lda P$IOQN,u get next process ID
sta P$IOQN,y put in previous process
beq IOQ.F branch if none
clr P$IOQN,u clear next process link
ifeq LEVEL-1
ldx D.PrcDBT
os9 F$Find64
else
os9 F$GProcP get process ptr
endc
bcs IOQ.F branch if dead
lda P$IOQP,u get previous process ID
sta P$IOQP,y put in next process
IOQ.F clr P$IOQP,u clear predecessor link
IOQuExit rts
emod Module Crc
IOEnd equ *