ack/mach/z80/libmon/mon.cpm.s
1987-02-02 12:44:39 +00:00

930 lines
12 KiB
ArmAsm

.define .mon
.define uxfinish
.sect .text
.sect .rom
.sect .data
.sect .bss
.sect .text
! monitor instruction
! a small collection of UNIX system calls implemented under CP/M
! ux_indir=e.mon
! ux_fork=e.mon
! ux_wait=e.mon
! ux_link=e.mon
! ux_exec=e.mon
! ux_chdir=e.mon
! ux_mknod=e.mon
! ux_chmod=e.mon
! ux_chown=e.mon
! ux_break=e.mon
! ux_stat=e.mon
! ux_seek=e.mon
! ux_mount=e.mon
! ux_umount=e.mon
! ux_setuid=e.mon
! ux_getuid=e.mon
! ux_stime=e.mon
! ux_ptrace=e.mon
! ux_alarm=e.mon
! ux_fstat=e.mon
! ux_pause=e.mon
! ux_utime=e.mon
! ux_stty=e.mon
! ux_gtty=e.mon
! ux_access=e.mon
! ux_nice=e.mon
! ux_sync=e.mon
! ux_kill=e.mon
! ux_dup=e.mon
! ux_pipe=e.mon
! ux_times=e.mon
! ux_prof=e.mon
! ux_unused=e.mon
! ux_setgid=e.mon
! ux_getgid=e.mon
! ux_sig=e.mon
! ux_umask=e.mon
! ux_chroot=e.mon
EPERM = 1
ENOENT = 2
ESRCH = 3
EINTR = 4
EIO = 5
ENXIO = 6
E2BIG = 7
ENOEXEC = 8
EBADF = 9
ECHILD = 10
EAGAIN = 11
ENOMEM = 12
EACCES = 13
EFAULT = 14
ENOTBLK = 15
EBUSY = 16
EEXIST = 17
EXDEV = 18
ENODEV = 19
ENOTDIR = 20
EISDIR = 21
EINVAL = 22
ENFILE = 23
EMFILE = 24
ENOTTY = 25
ETXTBSY = 26
EFBIG = 27
ENOSPC = 28
ESPIPE = 29
EROFS = 30
EMLINK = 31
EPIPE = 32
EDOM = 33
! Structure of filearea maintained by this implementation
! First iobuffer of 128 bytes
! Then the fcb area of 36 bytes
! The number of bytes left in the buffer, 1 byte
! The iopointer into the buffer, 2 bytes
! The openflag 0 unused, 1 reading, 2 writing, 1 byte
! The filedescriptor starting at 3, 1 byte
! The number of CTRL-Zs that have been absorbed, 1 byte
! The byte read after a sequence of CTRL-Zs, 1 byte
maxfiles=8
filesize=128+36+1+2+1+1+1+1
filefcb=0 ! pointers point to fcb
position=33
nleft=36
iopointer=37
openflag=39
fildes=40
zcount=41
zsave=42
.assert [ filefcb] <> 0
0: .space maxfiles*filesize
filearea = 0b+128
sibuf:
.data2 0
.space 82
siptr: .space 2
saveargs:
.space 128
argc: .space 2
ttymode:.data1 9,9,8,21;.data2 06310+RAW*040 ! raw = 040
return:
.data2 0,0
uxinit:
xor a
ld c,maxfiles
ld hl,0b
1: ld b,filesize
2: ld (hl),a
inc hl
djnz 2b
dec c
jr nz,1b
ret
uxfinish:
ld a,maxfiles-1
1: push af
call closefil
pop af
dec a
cp 0377
jr nz,1b
ret
.mon:
pop ix
ld (return),ix ! return adres
pop de ! system call number
xor a
or d
jr nz,unimpld ! too big
ld a,e
and 0300 ! only 64 system calls
jr nz,unimpld
sla e
ld hl,systab
add hl,de
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
jp (hl)
systab:
.data2 e.mon ! ux_indir
.data2 ux_exit
.data2 e.mon ! ux_fork
.data2 ux_read
.data2 ux_write
.data2 ux_open
.data2 ux_close
.data2 e.mon ! ux_wait
.data2 ux_creat
.data2 e.mon ! ux_link
.data2 ux_unlink
.data2 e.mon ! ux_exec
.data2 e.mon ! ux_chdir
.data2 ux_time
.data2 e.mon ! ux_mknod
.data2 e.mon ! ux_chmod
.data2 e.mon ! ux_chown
.data2 e.mon ! ux_break
.data2 e.mon ! ux_stat
.data2 e.mon ! ux_seek
.data2 ux_getpid
.data2 e.mon ! ux_mount
.data2 e.mon ! ux_umount
.data2 e.mon ! ux_setuid
.data2 e.mon ! ux_getuid
.data2 e.mon ! ux_stime
.data2 e.mon ! ux_ptrace
.data2 e.mon ! ux_alarm
.data2 e.mon ! ux_fstat
.data2 e.mon ! ux_pause
.data2 e.mon ! ux_utime
.data2 e.mon ! ux_stty
.data2 e.mon ! ux_gtty
.data2 e.mon ! ux_access
.data2 e.mon ! ux_nice
.data2 ux_ftime
.data2 e.mon ! ux_sync
.data2 e.mon ! ux_kill
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 e.mon ! ux_dup
.data2 e.mon ! ux_pipe
.data2 e.mon ! ux_times
.data2 e.mon ! ux_prof
.data2 e.mon ! ux_unused
.data2 e.mon ! ux_setgid
.data2 e.mon ! ux_getgid
.data2 e.mon ! ux_sig
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 ux_ioctl
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 unimpld
.data2 unimpld ! ux_exece
.data2 e.mon ! ux_umask
.data2 e.mon ! ux_chroot
.data2 unimpld
.data2 unimpld
emptyfile:
! searches for a free filestructure
! returns pointer in iy, 0 if not found
ld ix,filearea
ld l,maxfiles
1:
xor a
or (ix+openflag)
jr nz,3f
ld a,maxfiles+3
sub l
ld (ix+fildes),a
! #ifdef CPM1
push iy
push ix
ld de,-128
add ix,de
push ix
pop de
ld c,setdma
call bdos
pop ix
pop iy
or a ! to clear C
! #endif
ret
3:
ld de,filesize
add ix,de
dec l
jr nz,1b
scf
ret
findfile:
ld ix,filearea
ld de,filesize
0:
dec a
ret m
add ix,de
jr 0b
getchar:
push iy
push de
push hl
dec (ix+nleft)
jp p,0f
push ix
pop hl
ld de,-128
add hl,de
ld (ix+iopointer),l
ld (ix+iopointer+1),h
ex de,hl
push ix
ld c,setdma
call bdos
! #ifdef CPM1
ld c,seqread
! #else
! ld c,randomread
! #endif
pop de
call bdos
or a
jr z,1f
ld (ix+zcount),0
pop hl
pop de
pop iy
scf
ret
1:
inc (ix+position)
jr nz,2f
inc (ix+position+1)
2:
ld a,127
ld (ix+nleft),a
0:
ld h,(ix+iopointer+1)
ld l,(ix+iopointer)
ld a,(hl)
inc hl
ld (ix+iopointer),l
ld (ix+iopointer+1),h
pop hl
pop de
pop iy
ret
or a
putchar:
push hl
ld h,(ix+iopointer+1)
ld l,(ix+iopointer)
ld (hl),a
dec (ix+nleft)
jr z,0f
inc hl
ld (ix+iopointer+1),h
ld (ix+iopointer),l
pop hl
ret
0:
pop hl
flsbuf:
push hl
push de
push iy
push ix
pop hl
ld de,-128
add hl,de
ld (ix+iopointer+1),h
ld (ix+iopointer),l
ex de,hl
push ix
ld c,setdma
call bdos
pop de
! #ifdef CPM1
ld c,seqwrite
! #else
! ld c,randomwrite
! #endif
call bdos
or a
jr z,1f
pop iy
pop de
pop hl
scf
ret
1:
inc (ix+position)
jr nz,2f
inc (ix+position+1)
2:
ld a,128
ld (ix+nleft),a
ld b,a
push ix
pop hl
ld de,-128
add hl,de
ld a,26 ! ctrl z
1: ld (hl),a
inc hl
djnz 1b
pop iy
pop de
pop hl
or a
ret
parsename:
! parses file name pointed to by hl and fills in fcb
! of the file pointed to by ix.
! recognizes filenames as complicated as 'b:file.zot'
! and as simple as 'x'
push iy
push ix
pop de
xor a
push de
ld b,36 ! sizeof fcb
0: ld (de),a
inc de
djnz 0b
pop de
inc hl
ld a,(hl)
dec hl
cp ':' ! drive specified ?
jr nz,1f
ld a,(hl)
inc hl
inc hl
dec a
and 15
inc a ! now 1<= a <= 16
ld (de),a
1: inc de
ld b,8 ! filename maximum of 8 characters
1: ld a,(hl)
or a
jr nz,8f
dec hl
ld a,'.'
8:
inc hl
cp '.'
jr z,2f
and 0177 ! no parity
bit 6,a
jr z,9f
and 0337 ! UPPER case
9:
ld (de),a
inc de
djnz 1b
ld a,(hl)
inc hl
cp '.'
jr z,3f
ld a,' '
ld (de),a
inc de
ld (de),a
inc de
ld (de),a
pop iy
ret ! filenames longer than 8 are truncated
2: ld a,' ' ! fill with spaces
0: ld (de),a
inc de
djnz 0b
3: ld b,3 ! length of extension
1: ld a,(hl)
inc hl
or a
jr z,4f
cp 0100
jp m,2f
and 0137
2: ld (de),a
inc de
djnz 1b
pop iy
ret
4: ld a,' '
0: ld (de),a
inc de
djnz 0b
pop iy
ret
! various routines
ux_close:
pop hl
ld a,l
sub 3
jp m,1f
cp maxfiles
call m,closefil
1: ld hl,0
push hl ; jr rtn
closefil:
call findfile
ld a,(ix+openflag)
or a
jr z,3f
ld (ix+openflag),0
cp 1
jr z,2f
ld a,(ix+nleft)
cp 128
jr z,2f
call flsbuf
2:
push iy
push ix
pop de
ld c,close
call bdos
pop iy
3: ret
ux_ioctl:
pop hl
ld a,l
sub 3
jp p,1f
pop hl
ld a,h
cp 't'
jr nz,e.mon
ld a,l
cp 8
jr z,tiocgetp
cp 9
jr z,tiocsetp
jr e.mon
1: pop hl
pop hl
ld hl,-1
push hl ; jr rtn
tiocgetp:
pop de
ld hl,ttymode
2: push bc
ld bc,6
ldir
ld h,b
ld l,c
pop bc
push hl ; jr rtn
tiocsetp:
pop hl
ld de,ttymode
jr 2b
ux_time:
call time4
rtn: ld ix,(return) ; jp (ix)
ux_ftime:
pop hl
ld (retarea+6),hl
call time4
ld hl,(retarea+6)
pop de
ld (hl),e
inc hl
ld (hl),d
inc hl
pop de
ld (hl),e
inc hl
ld (hl),d
inc hl
xor a
ld (hl),a
inc hl
ld (hl),a
inc hl
ld (hl),a
inc hl
ld (hl),a
inc hl
ld (hl),a
inc hl
ld (hl),a
ld ix,(return) ; jp (ix)
time4:
pop hl
ld (retarea),iy
ld (retarea+2),bc
ld (retarea+4),hl
ld hl,(timebuf+2)
push hl
ld hl,(timebuf)
push hl
ld hl,0
push hl
ld hl,50
push hl
call .dvu4
ld iy,(retarea)
ld bc,(retarea+2)
ld hl,(retarea+4)
jp (hl)
ux_exit:
call uxfinish
ld c,reset
call bdos
! no return
ux_creat:
call emptyfile
jr c,openfailed
pop hl
call parsename
pop hl ! file mode, not used under CP/M
push iy
push ix
push ix
pop de
ld c,delete
call bdos
pop de
ld c,makefile
call bdos
pop iy
ld l,1
jr afteropen
ux_open:
call emptyfile
jr nc,1f
openfailed:
pop hl
pop hl ! remove params
ld hl,EMFILE
push hl
push hl ; jr rtn
1:
pop hl ! filename
call parsename
push iy
ld c,open
push ix
pop de
call bdos
pop iy
pop hl
afteropen:
inc a
jr nz,1f
ld hl,ENOENT
push hl
push hl ; jr rtn
1:
inc l
ld (ix+openflag),l
xor a
ld (ix+nleft),a
ld (ix+zcount),a
ld (ix+zsave),26
bit 1,l
jr z,2f
ld (ix+nleft),128
2:
ld (ix+position),a
ld (ix+position+1),a
push ix
pop hl
push bc
ld b,128
3: dec hl
ld (hl),26
djnz 3b
pop bc
ld (ix+iopointer+1),h
ld (ix+iopointer),l
ld h,a
ld l,(ix+fildes)
push hl
ld l,a
push hl ; jr rtn
ux_read:
pop hl
ld a,l
sub 3
jp p,readfile
ld a,(ttymode+4)
bit 5,a
jr z,1f ! not raw
push iy
! #ifdef CPM1
!raw echo interface
ld c,consolein
call bdos
! #else
! !no echo interface
! 4:
! ld c,diconio
! ld e,0xff
! call bdos
! or a
! jr z,4b
!end of no echo interface
! #endif
pop iy
pop hl
ld (hl),a
pop hl
ld hl,1
push hl
ld hl,0
push hl ; jr rtn
1:
ld hl,sibuf+1 ! read from console assumed
dec (hl)
jp p,2f
dec hl ! go read console line
ld (hl),80 ! max line length
push iy
push hl
ld c,readconsole
ex de,hl
call bdos
ld c,writeconsole
ld e,'\n'
call bdos
pop hl
pop iy
inc hl
inc (hl)
ld (siptr),hl ! ready for transfer
push hl
ld e,(hl)
ld d,0
add hl,de
ld (hl),'\r'
inc hl
ld (hl),'\n'
pop hl
2:
push bc
pop ix
ld b,(hl)
inc b ! bytes remaining
pop hl ! copy to
pop de ! bytes wanted (probably 512)
push ix
ld ix,(siptr) ! copy from
xor a ! find out minimum of ramaining and wanted
or d
jr nz,3f ! more than 255 wanted (forget that)
ld a,b
cp e
jp m,3f ! not enough remaining
ld b,e
3:
ld c,b ! keep copy
0:
inc ix
ld a,(ix)
ld (hl),a
inc hl
djnz 0b
ld a,(sibuf+1)
sub c
inc a
ld (sibuf+1),a
ld (siptr),ix
pop hl
push bc
ld c,b
push bc ! load 0
ld b,h
ld c,l
ld ix,(return) ; jp (ix)
readfile:
call findfile
pop de
pop hl ! count
push bc
ld bc,0
0:
xor a
or l
jr z,1f
dec l
3:
! warning: this may not work if zcount overflows
ld a,(ix+zcount)
or a
jr nz,5f
ld a,(ix+zsave)
cp 26
jr z,4f
ld (ix+zsave),26
jr 8f
4:
call getchar
jr c,2f
ld (de),a
sub 26 ! CTRL-Z
jr z,7f
ld a,(ix+zcount)
or a
jr z,6f
ld a,(de)
ld (ix+zsave),a
5:
ld a,26
dec (ix+zcount)
8:
ld (de),a
6:
inc de
inc bc
jr 0b
1:
dec l
dec h
jp p,3b
2:
pop hl
push bc
ld b,h
ld c,l
ld hl,0
push hl ; jr rtn
7:
inc (ix+zcount)
jr 4b
ux_write:
pop hl
ld a,l
sub 3
jp p,writefile
pop hl ! buffer address
pop de ! count
push de
ld ix,0
push ix
push bc
ld b,e ! count now in 'db'
0:
ld a,b
or a
jr nz,1f
ld a,d
or a
jr nz,2f
pop bc
ld ix,(return) ; jp (ix)
2:
dec d
1:
dec b
ld e,(hl)
inc hl
push bc
push de
push hl
ld c,writeconsole
call bdos
pop hl
pop de
pop bc
jr 0b
writefile:
call findfile
pop de
pop hl ! count
push bc
ld bc,0
0:
xor a
or l
jr z,1f
dec l
3:
ld a,(de)
inc de
call putchar
jr c,4f
inc bc
jr 0b
1:
dec l
dec h
jp p,3b
ld ix,0
2:
pop hl
push bc
ld b,h
ld c,l
push ix
ld ix,(return) ; jp (ix)
4:
ld ix,ENOSPC
jr 2b
ux_unlink:
pop hl
ld ix,fcb
call parsename
push bc
ld c,delete
ld de,fcb
call bdos
pop bc
inc a
jr nz,1f
ld hl,ENOENT
push hl ; jr rtn
1:
ld hl,0
push hl ; jr rtn
ux_getpid:
ld hl,12345 ! nice number
push hl ; jr rtn
retarea: .data2 0 ! base of buffer for result values (max 8 bytes)
.data2 0
.data2 0
.data2 0
trapproc:
.data2 0
nextp: .data1 0
header:
ntext: .data2 0
ndata: .data2 0
nproc: .data2 0
entry: .data2 0
nline: .data2 0
hp: .data2 0
pb: .data2 0
pd: .data2 0