initial check-in. device driver works [?]

This commit is contained in:
Kelvin Sherlock 2016-10-14 23:03:00 -04:00
commit 0c4092d779
9 changed files with 1903 additions and 0 deletions

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
LD=mpw linkIIgs
ASM=mpw asmIIgs
#ASMFLAGS=-d DEBUG_S16 -d DebugSymbols
ASMFLAGS=-case on
LDFLAGS=
all : host.driver host.fst
host.fst : host.fst.o
$(LD) -t \$$BD -at \$$0000 $< -o $@
# aux type (-at)
# $8000 = inactive
# $0100 = gs/os driver
# $00xx = number of devices supported (should match dib)
host.driver : host.driver.o
$(LD) -t \$$BB -at \$$0101 $< -o $@
host.driver.o : host.driver.aii gsos.equ
host.fst.o : host.fst.aii gsos.equ fst.equ
%.o : %.aii
$(ASM) $(ASMFLAGS) $< -o $@

54
fst.equ Normal file
View File

@ -0,0 +1,54 @@
; my direct page.
dp record $0080
ptr ds.l 1 ; misc ptr
my_vcr ds.l 1
my_fcr ds.l 1
cookie ds.w 1
__end equ *
IF *>=$d4 THEN
AERROR 'dp -- too large.'
ENDIF
endr
fcr record 0
id ds.w 1 ; ref num
path_name ds.l 1
fst_id ds.w 1
vcr_id ds.w 1
level ds.w 1
newline ds.l 1
newline_length ds.w 1
mask ds.w 1
access ds.w 1
; fst-specific items
cookie ds.w 1
__sizeof equ *
endr
vcr record 0
id ds.w 1
name ds.l 1
status ds.w 1
open_count ds.w 1
fst_id ds.w 1
device ds.w 1
fst_ptr ds.l 1
; fst-specific items
__sizeof equ *
endr
; 5 = mfs, we're stealing it for now.
fst_id equ 5

274
fst.macros Normal file
View File

@ -0,0 +1,274 @@
; dispatch table for variable-pcount structures.
MACRO
&lab dispatch &table
&lab
@loop
ldy &table,x
jsr (&table+2,x)
dex
dex
dex
dex
bpl @loop
MEND
MACRO
str.&size ; &arg, ...
lclc &str
lcla &i, &l
&str setc &setting('string')
STRING asis
if &size<>'' THEN
dc.&size @end-@start
ENDIF
@start
&i seta 1
&l seta &nbr(&syslist)
WHILE &i<=&l DO
dc.b &syslist[&i]
&i seta &i+1
ENDWHILE
@end
STRING &str
MEND
MACRO
long &p1,&p2
lcla &bits
&bits seta %00000000
;&p1 setc &lc(&p1)
;&p2 setc &lc(&p2)
if &p1='m' OR &p2='m' THEN
&bits seta &bits+%00100000
longa on
ENDIF
if &p1='x' OR &p2='x' THEN
&bits seta &bits+%00010000
longi on
ENDIF
IF &bits<>0 THEN
rep #&bits
ENDIF
MEND
MACRO
short &p1,&p2
lcla &bits
&bits seta %00000000
;&p1 setc &lc(&p1)
;&p2 setc &lc(&p2)
if &p1='m' OR &p2='m' THEN
&bits seta &bits+%00100000
longa off
ENDIF
if &p1='x' OR &p2='x' THEN
&bits seta &bits+%00010000
longi off
ENDIF
IF &bits<>0 THEN
sep #&bits
ENDIF
MEND
macro
&l ~ConvSeconds &p1,&p2,&p3
&l ph2 &p1
ph4 &p2
ph4 &p3
ldx #$3703
jsl $E10000
mend
macro
&l ~Long2Hex &p1,&p2,&p3
&l ph4 &p1
ph4 &p2
ph2 &p3
ldx #$230B
jsl $E10000
mend
macro
&l ~Int2Hex &p1,&p2,&p3
&l ph2 &p1
ph4 &p2
ph2 &p3
ldx #$220B
jsl $E10000
mend
macro
&l _DebugHexDump
&l ldx #$0fff
jsl $e10000
mend
macro
&l ~DebugHexDump &p1,&p2
&l ph4 &p1
ph2 &p2
ldx #$0fff
jsl $e10000
mend
macro
&l _DebugGetTrace
&l ldx #$10ff
jsl $e10000
mend
macro
&l ~DebugGetTrace
&l ldx #$10ff
jsl $e10000
mend
macro
&l _DebugSetTrace
&l ldx #$11ff
jsl $e10000
mend
macro
&l ~DebugSetTrace &p1
&l ph2 &p1
ldx #$11ff
jsl $e10000
mend
; borrowed from orca/m
; mpw's pushword/pushlong have bugs and generally sucks
MACRO
ph2 &n1
IF &n1='*' THEN
MEXIT
ENDIF
IF &n1[1:1]='#' THEN
pea &n1[2:255]
MEXIT
ENDIF
IF &n1[1:1]='<' THEN
pei &n1
MEXIT
ENDIF
lda &n1
pha
MEND
MACRO
ph4 &n1
IF &n1='*' THEN
MEXIT
ENDIF
IF &n1[1:1]='#' THEN
pea |(&n1[2:255])>>16
pea |&n1[2:255]
MEXIT
ENDIF
IF &n1[1:1]='<' THEN
pei &n1+2
pei &n1
MEXIT
ENDIF
lda &n1+2
pha
lda &n1
pha
MEND
; _rts.cc -> return iff carry clear
macro
&l _rts.&cond
if &cond='cc' THEN
bcs @ok
ENDIF
if &cond='cs' THEN
bcc @ok
ENDIF
if &cond='eq' THEN
bne @ok
ENDIF
if &cond='ne' THEN
beq @ok
ENDIF
if &cond='mi' THEN
bpl @ok
ENDIF
if &cond='pl' THEN
bmi @ok
ENDIF
if &cond='vs' THEN
bvc @ok
ENDIF
if &cond='vc' THEN
bvs @ok
ENDIF
rts
@ok
mend
; reverse subtract.
macro
&l rsb &target
eor #$ffff
sec
adc &target
mend

113
fst_open.aii Normal file
View File

@ -0,0 +1,113 @@
include 'gsos.equ'
include 'fst.equ'
include 'fst.macros'
include 'records.equ'
open proc
with fst_parms
jsr check_path
bcs exit
jsr build_vcr
bcs exit
lda #invalid_fst_op
ldx call_number
sec
wdm #$ff
bcs exit
stx cookie
sty scratch ; actual read/write access
; build the fcr.
lda #fcr.__sizeof
ldx #host
ldy #^host
jsl alloc_fcr
bcs close
jsl deref
stx my_fcr
sty my_fcr+2
; need to re-deref the vcr?
ldy #vcr.open_count
lda [my_vcr],y
inc a
sta [my_vcr],y
lda scratch
ldy #fcr.access
sta [my_fcr],y
lda #fst_id
ldy #fcr.fst_id
sta [my_fcr],y
ldy #vcr.id
lda [my_vcr],y
ldy #fcr.vcr_id
sta [my_fcr],y
exit_ok
lda #0
clc
exit
rtl
close
;; oops! close it!
lda #0
ldx #$2014
ldy cookie
wdm #$ff
sec
lda #out_of_mem
rtl
host str.w ":Host"
endp
path_op proc
create entry
destroy entry
get_file_info entry
set_file_info entry
clear_backup entry
with fst_parms
jsr check_path
bcs exit
; hmmm - don't really need a vcr for this...
;jsr build_vcr
;bcs exit
lda #invalid_fst_op
ldx call_number
sec
wdm #$ff
exit
rtl
endp
change_path proc
; special since there are two pathnames.
lda #invalid_fst_op
sec
rtl
endp
judge_name proc
lda #0
clc
rtl
endp
end

263
gsos.equ Normal file
View File

@ -0,0 +1,263 @@
MACRO
DEFAULT &var,&value
IF &FINDSYM(&SYSGLOBAL,&var)=0 THEN
&var EQU &value
ENDIF
MEND
; ` prevents expansion during macro processing.
DEFAULT `DEBUG_S16,0
DEFAULT `DebugSymbols,0
****************************************************************
*
* The following are equates for GS/OS error codes.
*
****************************************************************
no_error equ $00 ; no error has occured
bad_system_call equ $01 ; bad system call number
fst_load_fail equ $02 ; couldn't load FST
invalid_pcount equ $04 ; invalid parameter count
gsos_active equ $07 ; gsos already active
dev_not_found equ $10 ; device not found
invalid_dev_num equ $11 ; invalid device number
drvr_bad_req equ $20 ; bad request or command
drvr_bad_code equ $21 ; bad control or status code
drvr_bad_parm equ $22 ; bad call parameter
drvr_not_open equ $23 ; character device not open
drvr_prior_open equ $24 ; character device already open
irq_table_full equ $25 ; interrupt table full
drvr_no_resrc equ $26 ; resources not available
drvr_io_error equ $27 ; I/O error
drvr_no_dev equ $28 ; device not connected
drvr_busy equ $29 ; driver is busy & not available
drvr_wr_prot equ $2B ; device is write protected
drvr_bad_count equ $2C ; invalid byte count
drvr_bad_block equ $2D ; invalid block number
drvr_disk_sw equ $2E ; disk has been switched
drvr_off_line equ $2F ; device off line / no media present
bad_path_syntax equ $40 ; invalid pathname syntax
invalid_ref_num equ $43 ; invalid reference number
path_not_found equ $44 ; subdirectory does not exist
vol_not_found equ $45 ; volume not found
file_not_found equ $46 ;
dup_pathname equ $47 ; create or rename with existing name
volume_full equ $48 ;
vol_dir_full equ $49 ; volume directory full
version_error equ $4A ;
bad_store_type equ $4B ; bad storage type
end_of_file equ $4C ;
out_of_range equ $4D ; position out of range
invalid_access equ $4E ; access not allowed
buff_too_small equ $4F ; buffer too small
softerrorlow equ $50 ; errors from $50 to $6f are soft errors
file_busy equ $50 ; file is already open
dir_error equ $51 ; directory error
unknown_vol equ $52 ; unknown volume type
parm_range_err equ $53 ; parameter out of range
out_of_mem equ $54 ; out of memory
dup_volume equ $57 ; duplicate volume name
not_block_dev equ $58 ; not a block device
invalid_level equ $59 ; specified level outside legal range
damaged_bitmap equ $5A ; block number too large
bad_path_names equ $5B ; invalid pathnames for change_path
not_system_file equ $5C ; not an executable file
os_unsupported equ $5D ; operating system not supported
stack_overflow equ $5F ; too many applications on stack
data_unavail equ $60 ; data unavailable
end_of_dir equ $61 ; end of directory has been reached
invalid_class equ $62 ; invalid FST call class
res_not_found equ $63 ; file does not contain req. resource
invalid_fst_id equ $64 ; specified FST is not present in system
invalid_fst_op equ $65 ; FST does not handle this type of call
fst_caution equ $66 ; FST handled call, but result is weird
dup_device equ $67 ; used internally only!!!
dev_list_full equ $68 ; device list is full
sup_list_full equ $69 ; supervisor list is full
fst_error equ $6A ;generic FST error
softerrorhigh equ $6f ; maximum soft error number allowed
resource_exist equ $70 ;Cannot expand file, resource already exist
res_add_err equ $71 ;cannot add resource fork to this type file.
network_error equ $88 ;Generic network error.
****************************************************************
*
* System Service Table Equates:
*
****************************************************************
dev_dispatcher equ $01FC00 ;dev_dispatch (initialized by new dev dispatcher)
cache_find_blk equ $01FC04 ;cash_find
cache_add_blk equ $01FC08 ;cash_add
cache_init equ $01FC0C ;cache initialization
cache_shutdn equ $01FC10 ;cash_shutdown
cache_del_blk equ $01FC14 ;cash_delete
cache_del_vol equ $01FC18 ;cash_del_vol
alloc_seg equ $01FC1C ;alloc_zero
release_seg equ $01FC20 ;deallocate
alloc_vcr equ $01FC24 ;allocvcr
release_vcr equ $01FC28 ;releasevcr
alloc_fcr equ $01FC2C ;allocfcr
release_fcr equ $01FC30 ;releasefcr
swap_out equ $01FC34 ;swapout
deref equ $01FC38 ;deref2
get_sys_gbuf equ $01FC3C ;s_get_sys_gbuf
sys_exit equ $01FC40 ;s_sys_exit
sys_death equ $01FC44 ;s_sys_death
find_vcr equ $01FC48 ;findvcr
find_fcr equ $01FC4C ;findfcr
set_sys_speed equ $01FC50 ;set system speed (initialized by new dev dispatcher)
cache_flsh_def equ $01FC54 ;flush deferred blocks from cache
rename_vcr equ $01FC58 ;renamevcr
rename_fcr equ $01FC5C ;renamefcr
get_vcr equ $01FC60 ;getvcr
get_fcr equ $01FC64 ;getfcr
lock_mem equ $01FC68 ;lockmem
unlock_mem equ $01FC6C ;unlockmem
move_info equ $01FC70 ;block move routines
cvt_0to1 equ $01FC74 ;cvt0to1
cvt_1to0 equ $01FC78 ;cvt1to0
replace_80 equ $01FC7C ;replace80
to_b0_core equ $01FC80 ;to_bank0_core
gen_dispatch equ $01FC84 ;g_dispatch
signal equ $01FC88 ;signal_event
get_sys_buf equ $01FC8C ;get_b0_buf
set_disksw equ $01FC90 ;set_disk_sw (initialized by new dev dispatcher)
report_error equ $01FC94 ;s_report_error
mount_message equ $01FC98 ;s_mount_msg
full_error equ $01FC9C ;s_full_error
report_fatal equ $01FCA0 ;s_report_fatal
sup_drvr_disp equ $01FCA4 ;supervisory dispatcher
install_driver equ $01FCA8 ;install device driver
get_boot_pfx equ $01FCAC ;s_get_boot_pfx
set_boot_pfx equ $01FCB0 ;s_set_boot_pfx
alloc_cache_seg equ $01FCB4 ;low_allocate
get_stked_id equ $01FCB8 ;get id of prog at top of GQUIT stack
dyn_slot_arbiter equ $01FCBC ;slot arbitration routine (initialized by new dev dispatcher)
parse_pathname equ $01FCC0 ;parse a pathname
post_os_event equ $01FCC4 ;notify external code about os event.
dynamic_install equ $01FCC8 ;install drivers (new init by SCM to JML INSERT_DRIVER)
dev_mgr_svc equ $01FCCC ;device manager entry (initialized by new dev dispatcher)
old_dev_disp equ $01FCD0 ;old device dispatcher (new init by SCM to JML DEV_DISPATCH)
init_parse_path equ $01FCD4 ;initialize for parse_path.
;
; Event codes for os_event
;
volmod_event equ $0040 ; event code for volume modified
disk_in_event equ $0008 ; disk inserted event
;
; Driver command codes
;
drvr_startup equ 0
drvr_open equ 1
drvr_read equ 2
drvr_write equ 3
drvr_close equ 4
drvr_status equ 5
drvr_control equ 6
drvr_flush equ 7
drvr_shutdown equ 8
drvr_get_dib equ 1
;
; Driver control and status call codes
;
stat_status equ 0
stat_config equ 1
*
* System Death error codes
*
vcr_unusable equ $000A ; VCR is unusable/inconsistent
fcr_unusable equ $000B ; FCR is unusable/inconsistent
vcr_swapped equ $4000 ;FLAG:Volume is swapped out (1 = true)
vcr_swapped_in equ $BFFF ;FLAG:Volume is swapped in
vcr_wr_enable equ $2000 ;FLAG:Volume has been seen write enabled
vcr_wr_unknown equ $DFFF ;FLAG:Volume has not been seen wrenbld
*
* access bits.
*
read_enabled equ $0001 ;1=Read Enabled
write_enabled equ $0002 ;1=Write Enabled
backup_enabled equ $0020 ;1=Needs to be backed up
rename_enabled equ $0040 ;1=Rename allowed
destroy_enabled equ $0080 ;1=Destroy is enabled
read_access equ $01
write_access equ $02
invis_bit equ $04
read_write_acc equ $03
; used by ProDOS
in_cache equ $8002
; records
dev_parms record 0
;--------------------------------------------------
; Here are the device driver fields
;--------------------------------------------------
dev_num ds.w 1 ; device number being called
dev_callnum ds.w 1 ; call number
dev_dev_id ; device ID (get_dib_ptr)
dev_buff ; I/O buffer address
ds.l 1
dev_req_cnt ds.l 1 ; request count
dev_xfer_cnt ds.l 1 ; transfer count
dev_blk_num ds.l 1 ; block number
dev_blk_size ds.w 1 ; block size
dev_fst_num ; FST number
dev_stat_code ; status code
dev_ctrl_code ; control code
ds.w 1
dev_vol_id ds.w 1 ; volume ID (???)
dev_cache_pr ds.w 1 ; cache priority
dev_cache_ptr ds.l 1 ; cache pointer
dev_dib_ptr ds.l 1 ; pointer to DIB
endr
; gs/os direct page.
fst_parms record $0030
call_number ds.w 1 ; FST call number
param_blk_ptr ds.l 1 ; pointer to user's parameter block
;dev_num ; device number from parameter block
dev1_num ds.w 1 ; alias name for dev_num
dev2_num ds.w 1 ; second device number
path1_ptr ; ptr to 1st partial/entire pathname
fcr_ptr ds.l 1 ; pointer to file control record
path2_ptr ; ptr to 2nd partial/entire pathname
vcr_ptr ds.l 1 ; pointer to volume control record
path_flag ds.w 1 ; flag for path information
span1 ds.w 1 ; largest distance between path1 term.
span2 ds.w 1 ; max dist. between separators for path2
endr

279
host.driver.aii Normal file
View File

@ -0,0 +1,279 @@
include 'gsos.equ'
include 'fst.macros'
entry entry, startup, open, close, read, write, flush, status, control, shutdown
;entry open_flag, ss_count, status_word
string asis
header proc
dc.w dib-header
dc.w 1 ; 1 device
dc.w 0 ; no config list
dib dc.l 0 ;Link pointer to next DIB
dc.l entry ;Entry pointer
dc.w %0000111100000000 ;Characteristics
dc.l 0 ;Block count
str.b 'HOST' ;Device name with length
dcb.b 32-5,$20
dc.w $8007 ;Slot number
dc.w 1 ;Unit number
dc.w $1000 ;Version number
dc.w $0010 ;ID # file server
dc.w 0 ;No header link
dc.w 0 ;No forward link
dc.l 0 ;extended dib ptr
dc.w 0 ;Device number
endp
entry proc
longa on
longi on
phb ;Save the GS/OS bank register
phk
plb
cmp #8+1 ;Max command number
bcc @dispatch
lda #drvr_bad_req
bra exit
@dispatch
asl a
tax
jsr (table,x)
exit
plb
cmp #1
rtl
table
dc.w startup
dc.w open
dc.w read
dc.w write
dc.w close
dc.w status
dc.w control
dc.w flush
dc.w shutdown
endp
data record
export ss_count, open_flag, status_word
ss_count dc.w 0
open_flag dc.w 0
; copied via get_device_status
status_word dc.w $0010
blocks dc.l 0
endr
flush proc
lda #no_error
rts
endp
read proc
lda #no_error
rts
endp
write proc
lda #no_error
rts
endp
startup proc
stz open_flag
inc ss_count
lda #no_error
rts
endp
shutdown proc
stz ss_count
lda #no_error
rts
endp
open proc
lda open_flag
bne oops
inc open_flag
lda #1
tsb status_word
lda #no_error
rts
oops
lda #drvr_prior_open
rts
endp
close proc
lda open_flag
beq oops
stz open_flag
lda #1
trb status_word
lda #no_error
rts
oops
lda #drvr_not_open
rts
endp
status proc
with dev_parms
lda <dev_stat_code
cmp #4+1
bcc @dispatch
lda #drvr_bad_code
rts
@dispatch
asl a
tax
; pre-zero transfer count
stz <dev_xfer_cnt
stz <dev_xfer_cnt+2
lda dev_req_cnt
; check for 0-sized request...
ora dev_req_cnt+2
beq exit
jmp (table,x)
table
dc.w get_device_status
dc.w get_config_params
dc.w get_wait_status
dc.w get_format_options
dc.w get_partition_map
get_device_status
lda dev_req_cnt+2
bne bad_parm
lda dev_req_cnt
cmp #2
bcc bad_parm
cmp #6+1
bcs bad_parm
sta <dev_xfer_cnt
tay
dey
sep #$30
longa off
@loop
lda status_word,y
sta [dev_buff],y
dey
bpl @loop
rep #$30
longa on
exit
lda #no_error
rts
bad_parm lda #drvr_bad_parm
rts
get_partition_map
get_format_options
lda #no_error
rts
get_config_params
get_wait_status
lda dev_req_cnt+2
bne bad_parm
lda dev_req_cnt
cmp #2
bne bad_parm
sta <dev_xfer_cnt
lda #0
sta [dev_buff]
lda #no_error
rts
endp
control proc
with dev_parms
lda <dev_ctrl_code
cmp #9+1
bcc @dispatch
lda #drvr_bad_code
rts
@dispatch
asl a
tax
jmp (table,x)
entry null, set_wait
table
dc.w null ; reset
dc.w null ; format
dc.w null ; eject
dc.w null ; set ctrl
dc.w set_wait ; set wait
dc.w null ; set format
dc.w null ; set partition
dc.w null ; arm signal
dc.w null ; disarm signal
dc.w null ; set partition map
null lda #no_error
rts
set_wait
; verify wait status is 0.
lda dev_req_cnt+2
bne @bad_parm
lda dev_req_cnt
cmp #2
bne @bad_parm
lda [dev_buff]
beq @exit
@bad_parm
lda #drvr_bad_parm
@exit
rts
endp
end

598
host.fst.aii Normal file
View File

@ -0,0 +1,598 @@
include 'gsos.equ'
include 'fst.equ'
include 'fst.macros'
include 'records.equ'
longa on
longi on
string asis
entry app_entry, sys_entry
header proc
str 'FST '
dc.l app_entry
dc.l sys_entry
dc.w fst_id
dc.w $0000 ; attributes
dc.w $0100 ; version
dc.w $0200 ; block size
dc.l $007FFFFF ; maximum volume size
dc.l 1 ; min volume size
dc.l $FFFFFFFF ; max file size
dc.l 0 ; reserved
str.b 'Host' ; name
str.b 'Host FST v01.00' ; comment
dc.w 0 ; reserved
; credits
str.b 'Host FST written by Kelvin W Sherlock.'
endp
data record
export dev_id
; device id of the .host driver.
dev_id ds.w 0
endr
sys_entry proc
phk
plb
rep #$30
cpx #max_sys_call+1
bge rtl_no_error
jmp (@sys_table,x)
@sys_table
dc.w rtl_no_error
dc.w sys_startup
dc.w sys_shutdown
dc.w rtl_no_error ; remove vcr
dc.w rtl_no_error ; deferred flush
max_sys_call equ *-@sys_table-2
endp
sys_startup proc
with dev_parms
; 1. find the .host device.
lda #1
sta dev_dev_id
stz dev_num
loop
lda #drvr_get_dib
sta dev_callnum
jsl dev_dispatcher
bcs no
; appletalk puts up a dialog box....
ldy #$34 ; dib device id
lda [dev_dib_ptr],y
cmp #$10 ; file server
bne next
short m
ldy #$0e ; name $04 H O S T
lda [dev_dib_ptr],y
cmp #$04
bne next
iny
lda [dev_dib_ptr],y
cmp #'H'
bne next
iny
lda [dev_dib_ptr],y
cmp #'O'
bne next
iny
lda [dev_dib_ptr],y
cmp #'S'
bne next
iny
lda [dev_dib_ptr],y
cmp #'T'
bne next
lon m
lda dev_dev_id
sta dev_id
bra got_device
next
long m
; try the next one.
inc dev_dev_id
bra loop
got_device
; sanity check that the global buffer location
; is where I expect it.
jsl get_sys_gbuf
cpy #$0000
bne no
cpx #$9a00
bne no
; check if host wdm active.
lda #0
sec
ldx #$8001
wdm #$ff
; wdm will clear carry if active.
rtl
no
sec ; unload me!
lda #0
rtl
endp
sys_shutdown proc
lda #0
clc
ldx #$8002
wdm #$ff
rtl
endp
rtl_no_error proc
lda #0
clc
rtl
endp
rtl_invalid_fst_op proc
lda #invalid_fst_op
sec
rtl
endp
rtl_bad_system_call proc
lda #bad_system_call
sec
rtl
endp
rtl_invalid_pcount proc
lda #invalid_pcount
sec
rtl
endp
app_entry proc
with dp
with fst_parms
import max_pcount
import want_fcr
import want_vcr
phk
plb
rep #$30
;brk $42
sty <call_class
; debug saves all registers.
IF DEBUG_S16 THEN
jsr debug
ENDIF
; check the class 0 or 1 only.
cpy #2+1
bge @bad_system_call
cpx #max_app_call+1 ; 66+1
bge @bad_system_call
; class 1 -- check the pcount maximum.
cpy #2
bne @ok
lda [param_blk_ptr]
; gs/os already checks the minimum and verifies non-null names, etc.
;cmp min_pcount,x
;blt @invalid_pcount
cmp max_pcount,x
bge @invalid_pcount
@ok
stz my_fcr
stz my_fcr+2
stz my_vcr
stz my_vcr+2
stz cookie
phx ; save...
lda want_fcr,x
beq @fcr
ldx fcr_ptr
ldy fcr_ptr+2
jsl deref
stx my_fcr
sty my_fcr+2
ldy #fcr.cookie
lda [my_fcr],y
sta cookie
@fcr
plx ; restore
phx ; save
lda want_vcr,x
beq @vcr
ldx vcr_ptr
ldy vcr_ptr+2
jsl deref
stx my_vcr
sty my_vcr+2
@vcr
plx ; restore
; check for dev num / :Host: path?
; fake an rtl address for sys_exit
; otherwise, would need to jml sys_exit from functions.
pea |(sys_exit-1)>>8
phb
lda #<sys_exit-1
sta 1,s
; call it...
jmp (@app_table,x)
@bad_system_call
lda #bad_system_call
sec
jml sys_exit
@invalid_pcount
lda #invalid_pcount
sec
jml sys_exit
endp
close proc
with dp
lda #invalid_fst_op
ldx call_number
ldy cookie
sec
wdm #$ff
bcc @ok
rtl
@ok
; destroy the fcr
lda [my_fcr]
jsl release_fcr
; decrement vcr
ldx vcr_ptr
ldy vcr_ptr+2
jsl deref
stx my_vcr
sty my_vcr+2
ldy #vcr.open_count
lda [my_vcr],y
beq fatal
dec a
sta [my_vcr],y
lda #0
clc
rtl
fatal
lda #vcr_unusable
jml sys_death
endp
read proc
; slightly special since newline mode may be in effect.
ldy #fcr.mask
lda [my_fcr],y
sta >$009a00 ; hardcoded...
beq fd_op
; zero-out the table.
ldx #256-2
lda #0
@zloop
sta >$009a00+2,x
dex
dex
bpl @zloop
; newline list is a virtual pointer.
ldy #fcr.newline
lda [my_fcr],y
tax
iny
iny
lda [my_fcr],y
tay
jsl deref
stx ptr
sty ptr+2
ldy #fcr.newline_length
lda [my_fcr],y
tay
dey
ldx #0
lda #0
short m
nloop
lda [ptr],y
tax
lda #$ff
sta >$009a00+2,x
dey
bpl nloop
long m
bra fd_op
endp
fd_op proc
; read, write, truncate, etc.
; everything (except close) that uses an fcr.
lda #invalid_fst_op
ldx call_number
ldy cookie
sec
wdm #$ff
rtl
endp
volume proc
; check if a volume is ours, create vcr if necessary.
lda fst_parms.dev1_num
beq no
cmp dev_id
bne no
; yes!
lda #unknown_vol
ldx call_number
sec
wdm #$ff
bcc @ok
rtl
@ok
; name is hardcoded to Host.
jsr build_vcr
rtl
no
lda #unknown_vol
sec
rtl
endp
build_vcr procname
; for now, volume hard coded as 'Host'.
with dp
ldx #default_name
ldy #^default_name
lda #0
jsl find_vcr
bcs create_vcr
jsl deref
stx my_vcr
sty my_vcr+2
ldy #vcr.fst_id
lda [my_vcr],y
cmp #fst_id
bne dump_vcr
ldy #vcr.status
lda [my_vcr],y
and #vcr_swapped
beq @exit
and #vcr_swapped_in
sta [my_vcr],y
;lda device
lda dev_id
ldy #vcr.device
sta [my_vcr],y
@exit
lda #0
clc
rts
dump_vcr
; vcr exists for the filename but it's not mine.
; if inactive, kick it out. otherwise, return dup error.
;
; todo -- prodos fst has kludge for change path which
; allows duplicates if using a device name or something...
;
ldy #vcr.open_count
lda [my_vcr],y
beq @dump
lda #dup_volume
sec
rts
@dump
ldy #vcr.id
lda [my_vcr],y
jsl release_vcr
; drop through.
create_vcr
lda #vcr.__sizeof
ldx #default_name
ldy #^default_name
jsl alloc_vcr
lda #out_of_mem
bcs exit
jsl deref
stx my_vcr
sty my_vcr+2
lda #0
ldy #vcr.status
sta [my_vcr],y
ldy #vcr.open_count
sta [my_vcr],y
lda #fst_id
ldy #vcr.fst_id
sta [my_vcr],y
lda dev_id
ldy #vcr.device
sta [my_vcr],y
lda #0
clc
exit
rts
default_name_colon
str.w ':Host'
default_name
str.w 'Host'
endp
get_dev_num proc
path equ path1_ptr
lda dev1_num
bne store
jsr check_path
bcs exit
jsr build_vcr
bcs exit
lda dev_id
store
ldx call_class
ldy table,x
sta [param_blk_ptr],y
lda #0
clc
exit
rtl
table
dc.w DevNumRec.devNum, DevNumRecGS.devNum
endp
;
; verify this path is for us
; (via dev number or :Host:)
;
check_path proc
lda dev1_num
beq path
cmp dev_id
beq ok
vnf
lda #vol_not_found
sec
rts
ok
lda #0
clc
rts
path
ldy #2
ldx #0
lda #0
short m
loop
lda [path1_ptr],y
cmp lower,y
beq @next
cmp upper,y
beq @next
long m
bra vnf
@next
iny
cpy #5+2
bne loop
; check for trailing null / :
lda [path1_ptr],y
beq @ok
cmp #':'
beq @ok
long m
bra vnf
@ok
long m
bra ok
lower str.w ':host'
upper str.w ':HOST'
end

239
records.equ Normal file
View File

@ -0,0 +1,239 @@
;
; n.b. -- __sizeof only works for the record. It does not
; work when actually instantiated. MPW sucks for some reason.
; perhaps it blindly adds the current * to all relative equates....
;
macro
&n begin_struct
&n record 0
__begin equ *
mend
macro
&n end_struct
&n
__end equ *
__sizeof equ __end - __begin
endr
mend
GSString255 begin_struct
length DS.W 1 ; Word - Number of Chars in text field
text DS.B 255 ; char[255] -
end_struct
GSString32 begin_struct
length DS.W 1 ; Word - Number of characters in text field
text DS.B 32 ; char[32] -
end_struct
ResultBuf255 begin_struct
bufSize DS.W 1
bufString DS GSString255
end_struct
ResultBuf32 begin_struct
bufSize DS.W 1
bufString DS GSString32
end_struct
TimeRec begin_struct
second DS.B 1
minute DS.B 1
hour DS.B 1
year DS.B 1
day DS.B 1
month DS.B 1
extra DS.B 1
weekDay DS.B 1
end_struct
DirEntryRecGS begin_struct
pCount DS.W 1
refNum DS.W 1
flags DS.W 1
base DS.W 1
displacement DS.W 1
name DS.L 1
entryNum DS.W 1
fileType DS.W 1
eof DS.L 1
blockCount DS.L 1
createDateTime DS TimeRec
modDateTime DS TimeRec
access DS.W 1
auxType DS.L 1
fileSysID DS.W 1
optionList DS.L 1
resourceEOF DS.L 1
resourceBlocks DS.L 1
end_struct
DirEntryRec begin_struct
refNum DS.B 2
flags DS.B 2
base DS.B 2
displacement DS.B 2
nameBuffer DS.B 4
entryNum DS.B 2
fileType DS.B 2
endOfFile DS.B 4
blockCount DS.B 4
createTime DS TimeRec
modTime DS TimeRec
access DS.B 2
auxType DS.B 4
fileSysID DS.B 2
end_struct
FileInfoRecGS begin_struct
pCount DS.W 1
pathname DS.L 1
access DS.W 1
fileType DS.W 1
auxType DS.L 1
storageType DS.W 1
createDateTime DS TimeRec
modDateTime DS TimeRec
optionList DS.L 1
eof DS.L 1
blocksUsed DS.L 1
resourceEOF DS.L 1
resourceBlocks DS.L 1
end_struct
FileRec begin_struct
pathname DS.B 4
fAccess DS.B 2
fileType DS.B 2
auxType DS.B 4
storageType DS.B 2
createDate DS.B 2
createTime DS.B 2
modDate DS.B 2
modTime DS.B 2
blocksUsed DS.B 4
end_struct
OpenRecGS begin_struct
pCount DS.W 1
refNum DS.W 1
pathname DS.L 1
requestAccess DS.W 1
resourceNumber DS.W 1
access DS.W 1
fileType DS.W 1
auxType DS.L 1
storageType DS.W 1
createDateTime DS TimeRec
modDateTime DS TimeRec
optionList DS.L 1
eof DS.L 1
blocksUsed DS.L 1
resourceEOF DS.L 1
resourceBlocks DS.L 1
end_struct
OpenRec begin_struct
openRefNum DS.B 2
openPathname DS.B 4
ioBuffer DS.B 4
end_struct
VolumeRecGS begin_struct
pCount DS.W 1
devName DS.L 1
volName DS.L 1
totalBlocks DS.L 1
freeBlocks DS.L 1
fileSysID DS.W 1
blockSize DS.W 1
characteristics ds.w 1
deviceID ds.w 1
end_struct
VolumeRec begin_struct
deviceName DS.B 4
volName DS.B 4
totalBlocks DS.B 4
freeBlocks DS.B 4
fileSysID DS.B 2
end_struct
JudgeNameRecGS begin_struct
pCount ds.w 1
fileSysID ds.w 1
nameType ds.w 1
syntax ds.l 1
maxLen ds.w 1
name ds.l 1
nameFlags ds.w 1
end_struct
PositionRecGS begin_struct
pCount DS.W 1
refNum DS.W 1
position DS.L 1
end_struct
MarkRec begin_struct
markRefNum DS.B 2
position DS.B 4
end_struct
EOFRecGS begin_struct
pCount DS.W 1
refNum DS.W 1
eof DS.L 1
end_struct
EOFRec begin_struct
eofRefNum DS.B 2
eofPosition DS.B 4
end_struct
IORecGS begin_struct
pCount DS.W 1
refNum DS.W 1
dataBuffer DS.L 1
requestCount DS.L 1
transferCount DS.L 1
cachePriority DS.W 1
end_struct
FileIORec begin_struct
fileRefNum DS.B 2
dataBuffer DS.B 4
requestCount DS.B 4
transferCount DS.B 4
end_struct
SetPositionRecGS begin_struct
pCount DS.W 1
refNum DS.W 1
base DS.W 1
displacement DS.L 1
end_struct
DevNumRecGS begin_struct
pCount DS.W 1
devName DS.L 1
devNum DS.W 1
end_struct
DevNumRec begin_struct
devName DS.B 4
devNum DS.B 2
end_struct

55
records.rb Normal file
View File

@ -0,0 +1,55 @@
#!/usr/bin/env ruby -w
offset = 0
record = nil
records = {}
puts "/* generated on #{Time.now.ctime} */"
puts ""
ARGF.each_line {|x|
x.chomp!
x.gsub!(/(;.*)$/,'')
x = x.rstrip
next if x.empty?
if record.nil?
record = $1 if /^(\w+\d*)\s+begin_struct$/.match x
next
end
case x
when /^\s+end_struct$/
puts ""
records[record] = offset
record = nil
offset = 0
when /^(\w+\d*)?\s+ds\s+(\w+\d*)$/i
# bleh ds timerec
puts "#define #{record}_#{$1} #{offset}" if $1
raise "unknown record #{$2}" unless records.include? $2
offset += records[$2]
when /^(\w+\d*)?\s+ds\.b\s+(\d+)$/i
puts "#define #{record}_#{$1} #{offset}" if $1
offset += $2.to_i
when /^(\w+\d*)?\s+ds\.w\s+(\d+)$/i
puts "#define #{record}_#{$1} #{offset}" if $1
offset += $2.to_i * 2
when /^(\w+\d*)?\s+ds\.l\s+(\d+)$/i
puts "#define #{record}_#{$1} #{offset}" if $1
offset += $2.to_i * 4
else
raise "bad line #{x}"
end
}
exit 0