Files
Shawn Quick dfcaae62dd Add qlink, the disk tools, and a bootable ProDOS 8 image.
Move the assembler to src/qasm. qlink links OMF 1.0 and 2.0 from a script. makeBin flattens a load file, qomf dumps OMF, and qpro builds ProDOS volumes. APW and MPW assemble through the ORCA front end. Relocatable modules emit OMF objects. Listings stay off unless -l is set.

make boot assembles the GS/OS 6.0.1 ProDOS 8 kernel and BASIC.SYSTEM into an 800K volume. BASIC.SYSTEM accepts ls and pfx, and its splash reports PRODOS BASIC 2.0, copyright 1983-2026. IIGS.601.SRC is the source and the BASIC.SYSTEM oracle that image is built from.
2026-10-16 14:41:55 -07:00

1 line
69 KiB
Plaintext

string asis
;-----------------------------------------------
;
; Forward addresses and entries
;
;-----------------------------------------------
ENTRY add2bktlist
ENTRY add_to_free
ENTRY addme2lru
ENTRY bucket_vp
ENTRY c_bytes_free
ENTRY c_marker
ENTRY c_request_size
ENTRY c_temp_1
ENTRY c_temp_2
ENTRY c_temp_bwd
ENTRY c_temp_element
ENTRY c_temp_fwd
ENTRY c_temp_nvp
ENTRY cache_error
ENTRY cache_search
ENTRY cashseg_end
ENTRY current_vp
ENTRY d_from_tail
ENTRY enuf_room
ENTRY getlinks
ENTRY head_vp
ENTRY is_there_room
ENTRY look_in_array
ENTRY message_shown
ENTRY next_vp
ENTRY no_find
ENTRY prev_vp
ENTRY search_vol_id
ENTRY set_cache_ptr
ENTRY set_flink_2nil
ENTRY show_message
ENTRY start_of_data
ENTRY tail_vp
ENTRY unlink
ENTRY unlink_bwd
ENTRY update_free
ENTRY write_to_disk
include 'common.equ.src'
;===============================================================================
; cashseg.s
;
; Framework for building load segment cashseg.s
;
;===============================================================================
longa on
longi on
header_length equ $30
cashseg_org equ $00a280
cashseg_start equ cashseg_org
cashseg_header proc org cashseg_org-header_length
msb on
dc.w cashseg_end-cashseg_start
dc.l cashseg_org
dc.w $0000
dc.b 'Caching Manager v03.00 '
dc.b 00
msb off
endp
cashseg_dummy proc org cashseg_org
endp
;------------------------------------------------------------------------------
; internal notes for gs/os caching routines. these notes should never be
; separated from the source code, they're listed here in no particular order.
;
; -- entry to each routine is via the system service table, the recognized
; entry points are: cash_init, cash_add, cash_find, cash_delete, cash_del_vol,
; cash_flsh_def and cash_shutdown. all other routines are used by the
; caching routines and are not known to anyone else.
;
; -- at the start of each entry point are comments describing briefly what
; the routine does, what the inputs are and what the outputs are. entry and
; exit to each routine is always with full native mode and direct page equal
; to gs/os direct page.
;
; -- cash_init and cash_shutdown are only used by gs/os, applications are
; not allowed to make these calls.
;
; -- the cache size, (always in bytes) is determined by reading battery ram.
; each tick is equal to 32K, if minus then the cache manager will assume 32K.
; if 0 then the cache manager will assume 8K. 8K is about enough to boot the
; system and not much else.
;
; -- the cache manager does not allocate to itself an amount of memory equal
; to the cache size as specified by the user. instead, the cache manager
; keeps a running byte count of the remaining amount of memory that can be
; used for the cache. as the cache grows and shrinks, the cache manager updates
; the remaining bytes left in the cache.
;
; -- the cache manager makes no assumptions about the size of the block that
; wants to be cached. it doesn't even have to be a power of 2. i'm not sure
; what the behavior of the mike memory manager is when the request for memory
; is greater than his nominal memory size unit.
;
; -- the cache manager obtains memory from the mike memory manager. (the
; mike memory manager is a custom memory manager for gs/os.) communications
; to the mike memory manager is by virtual pointers. vps are sort of like
; handles, pointers are derived from vps by de-referencing them.
;
; -- depending on the state of the system, there can be cases where the cache
; manager cannot get memory even though it's own running byte count says
; there's room. this usually happens when the system has no more free memory.
;
; -- in front of each cached block is a cache header. in it are the vital
; pieces of information that is needed to maintain the cache links.
;
; -- there are 2 classes of cached blocks, those that can be automatically
; deleted from the cache list by LRU and those that can't. the privileged
; cached blocks are also known as deferred blocks.
;
; -- the cache list is doubly linked with a head virtual pointer and a tail
; virtual pointer. the head_vp always points to the most recently added or
; requested block. the tail_vp always points to the block that is least
; recently used and that can be deleted because of LRU. things get a little
; complicated if the tail_vp points to a deferred block.
;
; -- incoming blocks are 'hashed' by 'and'ing away the block number and only
; keeping the low 7 bits. this will yield a max value of 127. without looking
; at disk structure, and assuming a fair amount of randomness in block number,
; 'hashing' to one of 128 different values will generally yield a somewhat
; even distribution. these values are known here as buckets and the cache
; list is also linked by bucket virtual pointers. there are 128 different
; bucket vps, there are no tail bucket vps. also maintaining a linked list by
; bucket vps gives the cache manager a very fast scheme of finding or deleting
; a block. (faster schemes were avoided because of the complexity implementing
; and maintaining it.)
;
; -- when cash_flsh_def (flush deferred blocks) is called, the deferred blocks
; are written to disk in the order they are found in the cache. no, it doesn't
; meet interleave and it maybe could if the deferred blocks were ordered
; sequentially but it isn't that important here. the cost in code, time and
; maintaining it isn't worth one pass through the disk. this call isn't used
; that much and when it is used, no big deal if the heads move back and forth
; a few times.
;
; -- the cache header contains a 2 byte reserved field that is currently used
; to number the incoming block. it can be used for other things if you want.
;
; -- there is some amount of memory that is used by the cache manager so the
; user won't get 32K worth of cached blocks if he specified a 32K cache. he'll
; get about 29K depending on block size. this is rather obscure but worth
; mentioning and rather difficult to notice by the user.
;
; -- Jan 25, 1988 R.T.
;
; Changed CASH_DEV_VOL. The routine did not delete deferred blocks. The
; routine now will delete both reqular blocks as well as deferred blocks.
; files changed: 'caching/scache1'
;
; -- Jan 26, 1988 R.T.
;
; Changed CASH_DEV_VOL. The routine will now tell the user that the volume
; may be damaged if a deferred block is deleted.
; files changed: 'caching/scache1' -> added a routine called 'show_message'
; 'caching/scache2' -> added 'message_shown' to data area
;
; -- Mar 22, 1988 R.T.
;
; Changed CASH_DEL_VOL. The routine will now delete ALL non-deferred
; blocks if both the device number and fst number are set to zero.
; The routine will now check the deferred bit when removing blocks by
; fst number.
; files changed: 'caching/scache1'
;
; -- Jan 30, 1989 R.T.
;
; added auto_flush_handler:
; This routine will check to see if sessions are enabled. If
; they are then I will issue a stop session call and then
; re-enable them.
;
; -- Feb 28, 1989 B.P.A
;
; Changed cashseg_org from $a200 to $a280 to give SCM some more room to
; grow. Added cache_overflow proc at end of code to check for code
; overflowing its space (will generate an error at link time).
;
; -- Mar 08, 1989 G.R.T
;
; The Cache Manager now adds itself to the OutOfMemory Queue. If I am
; called, I will do a reset_cache to the OS then return with the
; new bytes free count.
;
; -- Jun 05, 1989 G.R.T and B.P.A. and M.S.A
;
; Fixed a bug in Cash_Del_Vol. The routine was not doing a deref call
; for the bucket table. This caused a problem if compact memory was
; called Vault.
;
; -- 9/14/89 Mensch and B.P.A.
;
; Added a deref_bucket to the start of shutdown_cache in case the only cache
; block is that. This is to fix a reset_cache system death bug.
;
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;------------------------------------------------------------------------------
;Revisions
EXPORT cash_notes
cash_notes PROC
ENDP
;-----------------------------------------------------------------------------
; Deref_bucket:
; This routine will deref the bucket table VP and setup
; cache_bkt_ptr
;
;
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; Copyright (c) 1987,1988,1989 Apple Computer Inc. All rights reserved.
; author: Rob Turner
;-----------------------------------------------------------------------------
Deref_bucket proc
php
phx
phy
ldx bucket_vp
ldy bucket_vp+2
jsl deref ;deref this for real pointing
stx <cache_bkt_ptr
sty <cache_bkt_ptr+2
ply
plx
plp
rts
endp
;-----------------------------------------------------------------------------
; curr_vp_to_ptr:
; This routine will set current_vp then deref current VP
; and store the result in cache_cur_ptr
;
;
;
; inputs: A = don't care outputs: A = trashed
; X = vp low X = trashed
; Y = vp high Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; Copyright (c) 1987,1988,1989 Apple Computer Inc. All rights reserved.
; author: Rob Turner
;-----------------------------------------------------------------------------
curr_vp_to_ptr proc
stx current_vp
sty current_vp+2
export XY_to_cur_ptr
XY_to_cur_ptr
jsl deref
stx <cache_cur_ptr
sty <cache_cur_ptr+2
rts
endp
;-----------------------------------------------------------------------------
; auto_flush_handler:
; This routine will check to see if sessions are enabled. If
; they are then I will issue a stop session call and then
; re-enable them.
;
;
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; Copyright (c) 1987,1988,1989 Apple Computer Inc. All rights reserved.
; author: Rob Turner
;-----------------------------------------------------------------------------
auto_flush_handler proc
import in_queue
phk
plb
jsl $e100a8
dc.w $201f ;get the current sessions flag
dc.l get_session
lda session_state
and #$0001 ;clear all other bits
beq @no_sessions
jsl $e100a8 ;now do a stop session call please
dc.w $201E
dc.l session_list
jsl $e100a8
dc.w $201d ;turn the session back on please
dc.l session_list
@no_sessions
stz in_queue ;indicate that we have ran
rtl
get_session dc.w $01 ;PCount
session_state dc.w 00
session_list dc.w $0000
endp
;-----------------------------------------------------------------------------
; CASH_INIT -- initializes the cache
;
; This routine will try to initialize the cache. Memory as needed by the
; cache is obtained from the Mike Memory Manager. The size of the cache is
; determined by looking at battery ram. Once this is read, changing the
; value in battery ram will not change the size of the cache. The cache size
; cannot be changed on the fly unless you're SSSPECIAL !!!
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the block is cached
; c = 1 means something screwed up, the block's not cached
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_init
cash_init PROC
import c_data_len
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
ldx #c_data_len ;number of bytes to zero
cash_i00 stz start_of_data,x
dex
dex
bpl cash_i00
;-----------------------------------------------------------------------------
; we need a segment of memory for holding the bucket vps. since there will be
; 128 buckets and each bucket will contain a bucket vp, the memory request
; will be 512 bytes.
;-----------------------------------------------------------------------------
lda #$0200 ;size of request, in bytes
sta c_request_size ;save this for later
sec ;we want it zeroed
jsl alloc_seg ;try to get it from mr. mike
bcc cash_i01 ;skip if no problem
jmp cache_error ;damn, couldn't get memory
cash_i01 stx bucket_vp
sty bucket_vp+2 ;save vp to bucket array
;-----------------------------------------------------------------------------
; read battery ram to find the user selected cache size. each tick equals
; 32K. (max size = 4M - 32K) normal battery ram is $ff, if the value read
; is $ff then we'll pretend it's a 1. if the value read is 0, then the
; ram cache size will be about 16K, enough to boot, not much more.
;-----------------------------------------------------------------------------
pea $0000 ;push space for result
pea ram_cache_size ;location of cache size
ldx #$0c03 ;read battery parameter
jsl $e10000 ;ain't no error possible
pla ;get cache size, low only
and #$00ff ;make sure to only keep low byte
beq cash_i02 ;skip if 0, user wants no cache
cmp #$00ff
beq cash_i03 ;skip if $ff, pretend it's 1
clc
ror a
bcc cash_i01a ;skip if c = 0, even number of 32Ks
ldx #$0080 ;32K
stx c_bytes_free+1 ;take care of odd
cash_i01a sta c_bytes_free+2 ;take care of even
bra cash_i05
cash_i02 lda #default_cache_size
bra cash_i04
cash_i03 lda #$0080 ;32K
cash_i04 sta c_bytes_free+1 ;size of total cache in bytes
; subtract bucket array size from total bytes free
cash_i05 jmp update_free
ENDP
;-----------------------------------------------------------------------------
; CASH_ADD -- adds a block to the cache
;
; This routine will try to add the requested block into the cache. It's
; position within the LRU and bucket chain will be at the start of the list.
; In the event there is not enough room in the cache, the last recently used
; block(s) will be purged until there is enough room for the requested block.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the block is cached
; c = 1 means something screwed up, the block's not cached
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_add
cash_add PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
jsr deref_bucket ;Deref the bucket table and setup cache_bkt_ptr
; always assume it ain't there, but see if there's enough room first
cash_a00 clc
lda <drvr_blk_size ;get requested block size
adc #c_headerlen ;add to size of cache header
sta c_request_size ;save this for later
jsr enuf_room ;check for space free
bcc cash_a01 ;skip if there's room for it
bra cash_a02 ;something's wrong
cash_a01 lda c_request_size ;get the size we want
; clc ;we don't want it zeroed
jsl alloc_seg ;ask for this amount from mike
bcc cash_a03 ;skip if we got it
cash_a02 jmp cache_error ;damn! couldn't get the memory
; add this cache cell to the start of the LRU chain
cash_a03 jsr addme2lru
; add this cache cell to the start of the bucket chain
jsr add2bktlist
bcs cash_a02 ;error from mike
; now fill in the rest of the cache header information
ldy #c_blknum ;point to block number, lo
lda <drvr_blk_num
sta [<cache_cur_ptr],y
iny
iny ;point to block number, hi
lda <drvr_blk_num+2
sta [<cache_cur_ptr],y
iny
iny ;point to block size
lda <drvr_blk_size
sta [<cache_cur_ptr],y
iny
iny ;point to FST number
lda <drvr_fst_num
sta [<cache_cur_ptr],y
iny
iny ;point to volume id
lda <drvr_vol_id
sta [<cache_cur_ptr],y
iny
iny ;point to device number
lda <drvr_dev_num
sta [<cache_cur_ptr],y
iny
iny ;point to cache priority
lda <drvr_cache
sta [<cache_cur_ptr],y
iny
iny ;point to cell size
lda c_request_size
sta [<cache_cur_ptr],y
; the following is only for debugging purposes . . .
iny
iny ;point to reserved field
inc c_marker
lda c_marker
sta [<cache_cur_ptr],y
iny
iny
sta [<cache_cur_ptr],y
jsr set_cache_ptr ;set drvr_cach_ptr before returning
; update bytes free and we're done.
EXPORT update_free
update_free ;
sec
lda c_bytes_free
sbc c_request_size
sta c_bytes_free
lda c_bytes_free+2
sbc #$0000
sta c_bytes_free+2 ;4 byte subtract
plb
clc
rtl
ENDP
;-----------------------------------------------------------------------------
; CASH_FIND -- finds a block in the cache
;
; This routine will try to find the requested block in the cache. If it's
; found, it'll be moved to the start of the LRU chain and a 4 byte pointer will
; be returned pointing to the start of the requested block. The bucket links
; will not be moved.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; on input: c = 0 means look for the block
; c = 1 means look for vol_id and deferred bit
;
; inputs: A = vol_id if c=1 outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the block is in the cache or vol_id found
; c = 1 means something screwed up or the block's not in the cache
; or vol_id not found
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_find
cash_find PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
bcc cash_fff ;skip if we're looking for a block
jsr search_vol_id ;we're looking for vol_id
plb ;pull to balance the stack
rtl ;result in c
; if we came from cash_flsh_def then we want to skip this
cash_fff ldx no_find ;non 0 means we want to skip this
bne cash_fff0
jsr cache_search ;locate the requested block
bcc cash_fm00 ;skip if we found it
cash_fff0 jmp cache_error ;error, no can find
; if we're in deferred mode and the block ain't, then correct for this
cash_fm00 ldy #c_priority ;offset to priority field
lda [<cache_cur_ptr],y
tax ;save for later
bmi cash_f00 ;skip if deferred bit set
lda <drvr_cache ;are we deferred mode now ?
bpl cash_f00 ;skip if no
txa ;bring a back
ora #$8000 ;make this block deferred
sta [<cache_cur_ptr],y ;this guy's deferred
lda <drvr_vol_id
ldy #c_volumeid
sta [<cache_cur_ptr],y
; pull out both LRU links into next_vp and prev_vp
cash_f00 ldx #c_lru_bwd
ldy #c_lru_fwd
jsr getlinks ;prev_vp in x and y
tya
bne cash_f01 ;skip if hi backlink <> 0
txa
bne cash_f01 ;skip if lo backlink <> 0
; backlink = 0, cache cell is at the start of list, ain't much left to do
bra cash_f04
; backlink <> 0, check forward link to see if cache cell is at the end
cash_f01 lda next_vp
bne cash_f02 ;skip if hi forward link <> 0
lda next_vp+2
bne cash_f02 ;skip if hi forward link <> 0
; forward link = 0, cache cell is at end of list, update tail_vp
; prev_vp is still in x and y
stx tail_vp
sty tail_vp+2
lda #c_lru_fwd
jsr set_flink_2nil ;set forward link to nil
bra cash_f03
; backlink and forward link are both <> 0, the cache cell is somewhere in
; the middle of the list. the head_vp and tail_vp aren't used here. unlink
; the LRU links of the current cell by joining the previous and next cells
; together.
cash_f02 ldx #c_lru_bwd
ldy #c_lru_fwd
jsr unlink
; the current cache cell has been LRU unlinked. reattach the LRU links at
; the start of the LRU chain.
cash_f03 ldx current_vp
ldy current_vp+2
jsr addme2lru
; last thing to do is return the pointer to the cached block
cash_f04 jsr set_cache_ptr ;set drvr_cach_ptr before returning
cash_f05 plb ;restore caller's data bank
clc ;indicate no error
rtl
ENDP
;-----------------------------------------------------------------------------
; CASH_DELETE -- deletes (purges) a block from the cache
;
; This routine will try to delete the requested block from the cache. If
; entry to this routine is via cache_xdelete then we don't have to look for
; the block before deleting it, the block is pointed to by current_vp.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the block has been deleted from the cache
; c = 1 means something screwed up or the block's not in the cache
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_delete
cash_delete PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
bra cash_dxxx ;skip over other entry point
EXPORT cache_xdelete
cache_xdelete ;
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
bra cash_d00 ;jump into it
cash_dxxx jsr cache_search ;locate the requested block
bcc cash_d00 ;skip if we found it
jmp cache_error ;error, no can find
;-----------------------------------------------------------------------------
; remove this cache cell from the LRU chain
;-----------------------------------------------------------------------------
; pull out both LRU links into next_vp and prev_vp, we'll need them later
cash_d00 ldx #c_lru_bwd
ldy #c_lru_fwd
jsr getlinks ;prev_vp in x and y
; if we happen to come in from xdelete, then we need to keep around the value
; of next_vp. removing by bucket will destroy this.
lda next_vp
sta c_temp_nvp
lda next_vp+2
sta c_temp_nvp+2
tya
bne cash_d02 ;skip if hi backlink <> 0
txa
bne cash_d02 ;skip if lo backlink <> 0
; backlink = 0, cache cell is at the start of list. if forward link = 0 then
; we have a single cell cache. x is still 0.
cpx next_vp
bne cash_d01 ;skip if lo forward link <> 0
cpx next_vp+2
bne cash_d01 ;skip if hi forward link <> 0
; forward link is also = 0, we have a single cell cache.
stz head_vp ;x is 0 from above
stz head_vp+2
stz tail_vp
stz tail_vp+2
jmp cash_dd00a
; forward link is not = 0, but the backlink is still = 0
cash_d01 ldx next_vp
stx head_vp
ldx next_vp+2
stx head_vp+2 ;head_vp now points to 2nd cell
ldx #c_lru_bwd
stx c_temp_bwd
jsr unlink_bwd ;unlink backward link
bra cash_dd00
; backlink <> 0, check forward link to see if cache cell is at the end
cash_d02 lda next_vp
bne cash_d03 ;skip if lo forward link <> 0
lda next_vp+2
bne cash_d03 ;skip if hi forward link <> 0
; forward link = 0, cache cell is at end of list. prev_vp is still in x and y
stx tail_vp
sty tail_vp+2 ;tail_vp now points to 2nd from last
lda #c_lru_fwd
jsr set_flink_2nil ;set forward link to nil
bra cash_dd00
; backlink and forward link are both <> 0, the cache cell is somewhere in
; the middle of the list. the head_vp and tail_vp aren't used here. unlink
; the LRU links of the current cell by joining the previous and next cells
; together.
cash_d03 ldx #c_lru_bwd
ldy #c_lru_fwd
jsr unlink
; the current cache cell has been LRU unlinked.
;-----------------------------------------------------------------------------
; remove this cache cell from the bucket chain
;-----------------------------------------------------------------------------
; pull out both bucket links into next_vp and prev_vp, we'll need them later
cash_dd00 ldx #c_bkt_bwd
ldy #c_bkt_fwd
jsr getlinks ;prev_vp in x and y
tya
bne cash_dd01 ;skip if hi backlink <> 0
txa
bne cash_dd01 ;skip if lo backlink <> 0
; backlink = 0, cache cell is at the start of list. if forward link = 0 then
; we have a single cell cache. x is still 0.
cpx next_vp
bne cash_dd00b ;skip if lo forward link <> 0
cpx next_vp+2
bne cash_dd00b ;skip if hi forward link <> 0
; forward link is also = 0, we have a single cell bucket list
cash_dd00a ldy #c_blknum
lda [<cache_cur_ptr],y ;get block number, lo
and #$007f ;keep low 7 bits
asl a
asl a ;multiply by 4 to make into index
tay
txa ;set acc to 0
sta [<cache_bkt_ptr],y
iny
iny
sta [<cache_bkt_ptr],y
bra cash_dd03 ;we done
; forward link is not = 0, but backlink is still = 0
cash_dd00b ldy #c_blknum
lda [<cache_cur_ptr],y ;get block number, lo
and #$007f ;keep low 7 bits
asl a
asl a ;multiply by 4 to make into index
tay
lda next_vp
sta [<cache_bkt_ptr],y
iny
iny
lda next_vp+2
sta [<cache_bkt_ptr],y
ldx #c_bkt_bwd
stx c_temp_bwd
jsr unlink_bwd ;unlink backward link
bra cash_dd03
; backlink <> 0, check forward link to see if cache cell is at the end
cash_dd01 lda next_vp
bne cash_dd02 ;skip if hi forward link <> 0
lda next_vp+2
bne cash_dd02 ;skip if hi forward link <> 0
; forward link = 0, cache cell is at end of list. prev_vp is still in x and y
lda #c_bkt_fwd
jsr set_flink_2nil ;set forward link to nil
bra cash_dd03
; backlink and forward link are both <> 0, the cache cell is somewhere in
; the middle of the list. unlink the bucket links of the current cell by
; joining the previous and next cells together.
cash_dd02 ldx #c_bkt_bwd
ldy #c_bkt_fwd
jsr unlink
; the current cache cell has been bucket unlinked. now give it back to mike.
; also, update the free byte count
cash_dd03 jsr add_to_free ;add this amount to free byte count
ldx current_vp
ldy current_vp+2
jsl release_seg ;try to give it back to mike
bcc cash_dd04 ;skip if no problem
jmp cache_error ;damn, couldn't give it back
cash_dd04 plb ;restore caller's data bank
clc ;indicate no error
rtl
ENDP
;-----------------------------------------------------------------------------
; CASH_DEL_VOL -- deletes (purges) a volume's block(s) from the cache
;
; This routine will try to delete all blocks belonging to the requested
; device number from the cache. If the device number = 0 then all blocks
; of all device numbers of the specified FST will be deleted. If both
; device number and fst number are zero all blocks that are not deferred
; will be deleted.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the volume's block(s) are deleted
; c = 1 means something screwed up, the blocks may still be cached
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_del_vol
cash_del_vol PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
jsr deref_bucket ;Deref the bucket table and setup cache_bkt_ptr
stz message_shown ;reset flag. Flag used to tell user
;that a deferred block has been flushed
ldy <drvr_dev_num
sty c_temp_2 ;assume we're deleting by device number
ldy <drvr_fst_num
ldx #c_devnum
lda <drvr_dev_num
bne cash_dv00 ;skip if we're deleting by device #
sty c_temp_2 ; we're deleting by FST
ldx #c_fstnum
cash_dv00 stx c_temp_1
ldy head_vp+2
sty next_vp+2
ldx head_vp
stx next_vp ;start this mess from the head
bra cash_dv03 ;check for 0 first
cash_dv01 stx current_vp
ldy next_vp+2
sty current_vp+2
jsr curr_vp_to_ptr ;convert the current VP to a real pointer
lda c_temp_2 ;delete all non-deferred blocks?
beq do_all_please
ldy c_temp_1
lda [<cache_cur_ptr],y
cmp c_temp_2 ;equal ?
bne cash_dv04 ;nope
; only pick out the non-deferred blocks
; ldx c_temp_1
; cpx #c_fstnum ;are we deleting by fst number ?
; beq cash_dv01a ;yes, don't worry about deferred stuff
;===========================================================================
;
; We no longer skip deferred blocks. They get kicked out along with
; other blocks on the device. By Rob Turner 1/25/88
;
;===========================================================================
do_all_please ;
ldy #c_priority
lda [<cache_cur_ptr],y
bpl cash_dv01a ;Block is not deferred
lda c_temp_2 ;removing all non-deferred blocks?
beq cash_dv04 ;yes, so skip this block
bit message_shown ;have we told the user about damage?
bmi cash_dv01a ;Yes!
jsr show_message ;tell the user
dec message_shown
;
; we've located a block for deletion
;
cash_dv01a jsl cache_xdelete ;delete this guy
bcc cash_dv02 ;skip if no error
jmp cache_error ;i don't know why
cash_dv02 lda c_temp_nvp ;restore next_vp
sta next_vp
lda c_temp_nvp+2
sta next_vp+2
cash_dv03 ldx next_vp
bne cash_dv01 ;skip if <> 0
ldy next_vp+2
bne cash_dv01 ;skip if <> 0
bra cash_dv05 ;it's 0, we done deleting
; it's not this cell, follow forward link and try again.
cash_dv04 ldy #c_lru_fwd
lda [<cache_cur_ptr],y
tax ;low link in x
iny
iny
lda [<cache_cur_ptr],y
sta next_vp+2
tay ;hi link in y
bne cash_dv01 ;y <> 0, loop
txa
bne cash_dv01 ;x <> 0, loop
; the forward link is 0, we're all done here.
cash_dv05 plb ;restore caller's data bank
clc ;indicate no error
rtl
ENDP
;-----------------------------------------------------------------------------
;Show_Message: This routine will tell the user that the volume is
; possible damaged.
;-----------------------------------------------------------------------------
EXPORT show_message
show_message PROC
;using common_equ
;using cache_data
lda <cache_cur_ptr+2
pha ;save the zeropage pointer
lda <cache_cur_ptr
pha
ldy #c_volumeid ;get the volume id please
lda [<cache_cur_ptr],y
beq end_show ;major problem
jsl find_vcr ;go and get the vcr ptr
bcs end_show ;major problem
jsr XY_to_cur_ptr ;deref X and Y & setup cache_cur_ptr with real address.
ldy #vcr_name ;index to volume name
lda [<cache_cur_ptr],y
tax
iny
iny
lda [<cache_cur_ptr],y
tay
jsr XY_to_cur_ptr ;deref X and Y & setup cache_cur_ptr with real address.
lda [<cache_cur_ptr]
xba ;convert length word to length byte
sta [<cache_cur_ptr]
pea $0010 ;error message number
ldx <cache_cur_ptr+2
lda <cache_cur_ptr ;low word of address
inc a ;point to length byte
bne high_ok
inx ;advance the bank address
high_ok ;
phx ;high word
pha ;low word
pha ;garbage
pha
jsl report_error
lda [<cache_cur_ptr]
xba ;convert length byte to length word
sta [<cache_cur_ptr]
end_show ;
pla
sta <cache_cur_ptr
pla
sta <cache_cur_ptr+2
rts
ENDP
;-----------------------------------------------------------------------------
; CASH_FLSH_DEF -- write to disk the deferred cache block(s)
;
; This routine will try to write to disk the deferred cache blocks belonging
; to a specific volume id. After being written to disk, these deferred cache
; blocks will be downgraded to regular cache blocks.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the volume ids deferred blocks have been
; written to disk
; c = 1 means something screwed up, couldn't write to disk all
; deferred blocks of the given volume id
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_flsh_def
cash_flsh_def PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
jsr deref_bucket ;Deref the bucket table and setup cache_bkt_ptr
ldx <drvr_cache ;get this
phx ;save this for later
stz <drvr_cache
;-----------------------------------------------------------------------------
;
;-----------------------------------------------------------------------------
ldx head_vp ;start this mess from the head
ldy head_vp+2
cfd_00
jsr curr_vp_to_ptr ;convert the current VP to a real pointer
;-----------------------------------------------------------------------------
; we can only write out cell(s) that are deferred. we may have to walk the
; entire list to find it but we know it's there.
;-----------------------------------------------------------------------------
ldy #c_priority
lda [<cache_cur_ptr],y ;get this cell's priority
bmi cfd_02 ;skip if deferred
cfd_00a ldy #c_lru_fwd
lda [<cache_cur_ptr],y
iny
iny
tax ;save backward vp link, lo
bne cfd_01 ;skip if not 0
lda [<cache_cur_ptr],y
beq cash_fd09 ;we found a vp of $0000
cfd_01 lda [<cache_cur_ptr],y
tay ;save backward vp link, hi
bra cfd_00 ;loop for next cell
; if we get here then we found a deferred block, check for volume id
cfd_02 ldy #c_volumeid
lda [<cache_cur_ptr],y ;get volume id
cmp <drvr_vol_id ;same ?
bne cfd_00a ;no, check next cell
; if we get here then we found a match, write this puppy out
inc no_find ;disable find routine
jsr write_to_disk ;write this block to disk
bcs cash_fd09 ;this wasn't expected
; if we get here then the writes okay and now turn off deferred status
ldy #c_priority
lda [<cache_cur_ptr],y
and #$7fff ;turn off bit 15
sta [<cache_cur_ptr],y
bra cfd_00a ;loop to find next one if any
cash_fd09 stz no_find ;re-enable find routine
plx ;restore drvr_cache
stx <drvr_cache
plb ;restore caller's data bank
clc ;indicate no error
rtl
ENDP
;-----------------------------------------------------------------------------
; CASH_SHUTDOWN -- shutdown the cache
;
; This routine will try to shutdown the cache by deleting each entry one at a
; time. The LRU list will be used for deletion, the bucket lists will not be
; used nor updated. The state of the cache is unknown if there's an error.
;
; Input and output is passed to this routine by GS/OS direct page and full
; native mode is always assumed.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the cache has been shutdown
; c = 1 means something screwed up, the cache is unreliable now
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cash_shutdown
cash_shutdown PROC
;using common_equ
;using cache_data
phb ;save caller's data bank
phk
plb ;set data bank to ourspace
jsr deref_bucket ;Deref the bucket table and setup cache_bkt_ptr
bra cash_sd01
cash_sd00 jsr d_from_tail ;delete one from the tail
bcc cash_sd01 ;skip if no problem
jmp cache_error ;not suppose to happen
cash_sd01 ldx tail_vp
bne cash_sd00 ;head <> 0, at least 1 cell left
ldy tail_vp+2
bne cash_sd00 ;head <> 0, at least 1 cell left
; lastly, get rid of the bucket array
ldx bucket_vp
ldy bucket_vp+2
jsl release_seg
bcc cash_sd02 ;skip if no problem
jmp cache_error ;mike's got a problem
cash_sd02
Import Cache_out_of_Queue
jsr Cache_out_of_Queue
plb ;restore caller's data bank
clc ;indicate no error
rtl
ENDP
;-----------------------------------------------------------------------------
EXPORT cache_misc
cache_misc PROC
;using common_equ
;using cache_data
;-----------------------------------------------------------------------------
; ENUF_ROOM -- checks for space remaining in cache
;
; This routine will check the cache free space to see if there's enough room
; for adding another cell into the chain. If there's not enough room then
; LRU will be invoked and cells will be deleted until there's enough room for
; the requested block.
;
; inputs: A = cell size outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, there's enough room for the request size
; c = 1 means something screwed up, it's probably mike's fault
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT enuf_room
enuf_room ;
import in_queue
jsr is_there_room ;is there room for something ?
bcs enuf_02 ;there's enough room
lda tail_vp
bne enuf_00 ;skip if not 0
lda tail_vp+2
bne enuf_00 ;skip if not 0
; there isn't enough room yet, the tail_vp is 0, something is all screwed up.
; Or sessions are enabled and the cache is full. If this is the case
; then I will do an end session and flush the word.
;
put_in_queue lda in_queue ;lets see if we have queued up to check for sessions
bmi @already_in
lda #$FFFF
sta in_queue ;do not add to the queue until I have ran once
lda #$0001 ;priority 1
ldx #auto_flush_handler
ldy #^auto_flush_handler
jsl signal ;add in our signal handler
@already_in
sec ;this should never happen
rts
; there ain't enough room to cache the requested cell. enforce LRU until
; there's enough room or error whichever is first.
enuf_00 jsr d_from_tail ;delete one from the tail
bcc enuf_room ;skip if no problem
bcs put_in_queue ;let error migrate up
enuf_02 clc
rts
;-----------------------------------------------------------------------------
; ADDME2LRU -- adds a block to the LRU chain
;
; This routine will take the cache cell pointed to by x and y and add it to
; the start of the LRU chain.
;
; inputs: A = don't care outputs: A = trashed
; X = vp to cache cell, lo X = trashed
; Y = vp to cache cell, hi Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT addme2lru
addme2lru ;
lda head_vp
sta next_vp
lda head_vp+2
sta next_vp+2
stx head_vp
sty head_vp+2 ;this is the new LRU head
jsr XY_to_cur_ptr ;deref X and Y & setup cache_cur_ptr with real address.
ldy #c_lru_fwd ;offset to forward vp link
lda next_vp
sta [<cache_cur_ptr],y
iny
iny
lda next_vp+2
sta [<cache_cur_ptr],y
ldy #c_lru_bwd ;offset to backward vp link
lda #$0000
sta [<cache_cur_ptr],y
iny
iny
sta [<cache_cur_ptr],y
lda next_vp
bne addme00
lda next_vp+2
bne addme00
lda head_vp
sta tail_vp
lda head_vp+2
sta tail_vp+2
rts
addme00 ldx next_vp
ldy next_vp+2
jsl deref
stx <cache_nxt_ptr
sty <cache_nxt_ptr+2
ldy #c_lru_bwd ;offset to backward vp link
lda head_vp
sta [<cache_nxt_ptr],y
iny
iny
lda head_vp+2
sta [<cache_nxt_ptr],y
rts
;-----------------------------------------------------------------------------
; add2bktlist -- adds a block to the bucket chain
;
; This routine will take the cache cell pointed to by head_vp and add it to
; the head of the bucket chain.
;
; inputs: A = bucket number outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the cache cell has been added to the head
; of the bucket chain
; c = 1 means something screwed up, the operation was not completed
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT add2bktlist
add2bktlist ;
jsr look_in_array ;look in bucket array for it
bcc add2d00 ;skip if there's something there
stz next_vp ;set forward link to nil
stz next_vp+2
bra add2d01
add2d00 stx next_vp
sty next_vp+2
jsl deref
stx <cache_nxt_ptr
sty <cache_nxt_ptr+2
ldy #c_bkt_bwd ;offset to backward vp link
lda head_vp
sta [<cache_nxt_ptr],y
iny
iny
lda head_vp+2
sta [<cache_nxt_ptr],y
add2d01 lda c_temp_element
asl a
asl a ;multiply by 4 to make into index
tay
lda head_vp
sta [<cache_bkt_ptr],y
iny
iny
lda head_vp+2
sta [<cache_bkt_ptr],y
ldy #c_bkt_fwd ;offset to forward vp link
lda next_vp
sta [<cache_cur_ptr],y
iny
iny
lda next_vp+2
sta [<cache_cur_ptr],y
ldy #c_bkt_bwd ;offset to backward vp link
lda #$0000
sta [<cache_cur_ptr],y
iny
iny
sta [<cache_cur_ptr],y
clc
rts
;-----------------------------------------------------------------------------
; CACHE_SEARCH -- searches the cache for the requested block
;
; This routine will search the bucket list to locate the requested block. If
; it's found, cache_cur_ptr will be pointing to that block.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the requested block has been found
; c = 1 means something screwed up or the block's not in the cache
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cache_search
cache_search ;
jsr look_in_array ;look in bucket array for it
bcc cash_s00 ;skip if maybe
rts ;error, it ain't there
; the block should be somewhere in this bucket list, look for it
cash_s00
jsr curr_vp_to_ptr ;convert the current VP to a real pointer
ldy #c_blknum ;point to block number, lo
lda [<cache_cur_ptr],y
cmp <drvr_blk_num ;equal ?
bne cash_s01 ;nope
iny
iny ;point to block number, hi
lda [<cache_cur_ptr],y
cmp <drvr_blk_num+2 ;equal ?
bne cash_s01 ;nope
ldy #c_blksize ;point to block size
lda [<cache_cur_ptr],y
cmp <drvr_blk_size ;equal ?
bne cash_s02 ;nope ----------> L O O K !!!
ldy #c_devnum ;point to device number
lda [<cache_cur_ptr],y
cmp <drvr_dev_num ;equal ?
bne cash_s01 ;nope
clc ;we've located the requested cell
rts
; it's not this cell, follow forward link and try again.
cash_s01 ldy #c_bkt_fwd
lda [<cache_cur_ptr],y
tax ;low link in x
iny
iny
lda [<cache_cur_ptr],y
tay ;high link in y
bne cash_s00 ;y <> 0, loop
txa
bne cash_s00 ;x <> 0, loop
; the forward link is 0, seems like we didn't find it
sec
rts
;-----------------------------------------------------------------------------
; if we get here then we found a block in the cache that's a different size
; than the requested size. this could be caused by different FSTs asking for
; it. in any case, to be safe and not sorry, this found block will be deleted
; from the cache and the find_block routine will return with carry set. the
; requestor will have to get that block off the disk.
;-----------------------------------------------------------------------------
cash_s02 jsl cache_xdelete ;current_vp still valid here
sec ;pretend we didn't find the block
rts
;-----------------------------------------------------------------------------
; SEARCH_VOL_ID -- searches the cache for a volume ids deferred block
;
; This routine will search the cache list for a volume ids deferred block.
; If we find any, then we'll return carry clear otherwise carry set.
;
; inputs: A = volume id outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means no error, the requested volume id has deferred blocks
; c = 1 means something screwed up or no deferred blocks found
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT search_vol_id
search_vol_id ;
lda tail_vp
ora tail_vp+2
bne svi_0010
sec ;no blocks
rts
svi_0010 ;
ldx tail_vp
ldy tail_vp+2
svi_00
jsr curr_vp_to_ptr ;convert the current VP to a real pointer
ldy #c_priority
lda [<cache_cur_ptr],y ;get this cell's priority
bpl svi_01 ;skip if not deferred
ldy #c_volumeid
lda [<cache_cur_ptr],y
cmp <drvr_vol_id
bne svi_01 ;skip if not this volume id
clc ;we found at least one.
rts
svi_01 ldy #c_lru_bwd
lda [<cache_cur_ptr],y
iny
iny
tax ;save backward vp link, lo
bne svi_03 ;skip if not 0
lda [<cache_cur_ptr],y
bne svi_03a ;skip if not 0
;-----------------------------------------------------------------------------
; if we get here then we're at the head of the list and still haven't been
; able to find any blocks that match volume id and deferred bit set.
;-----------------------------------------------------------------------------
sec ;we're at the end
rts
svi_03 lda [<cache_cur_ptr],y
svi_03a tay ;save backward vp link, hi
bra svi_00 ;loop for next cell
;-----------------------------------------------------------------------------
; GETLINKS -- fetches the forward and backward vp links
;
; This routine will fetch the forward and backward vp links of either the LRU
; or bucket chain and return them into next_vp and prev_vp. Additionally, x
; and y will contain prev_vp and prev_vp+2.
;
; inputs: A = don't care outputs: A = trashed
; X = offset to backward link X = prev_vp
; Y = offset to forward link Y = prev_vp+2
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT getlinks
getlinks ;
lda [<cache_cur_ptr],y
sta next_vp
iny
iny
lda [<cache_cur_ptr],y
sta next_vp+2
txy ;offset to backward vp link
lda [<cache_cur_ptr],y
sta prev_vp
tax
iny
iny
lda [<cache_cur_ptr],y
sta prev_vp+2
tay
rts
;-----------------------------------------------------------------------------
; SET_FLINK_2NIL -- sets forward vp link to nil
;
; This routine will set the forward vp link of the cache cell pointed to by
; prev_vp to nil.
;
; inputs: A = offset to forward link outputs: A = trashed
; X = prev_vp X = trashed
; Y = prev_vp+2 Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT set_flink_2nil
set_flink_2nil ;
sta c_temp_fwd
jsl deref
stx <cache_pre_ptr
sty <cache_pre_ptr+2
ldy c_temp_fwd ;offset to forward vp link
lda #$0000
sta [<cache_pre_ptr],y
iny
iny
sta [<cache_pre_ptr],y
rts
;-----------------------------------------------------------------------------
; UNLINK -- unlinks the current cache cell
;
; This routine will link together the cache cells pointed to by next_vp and
; prev_vp. By doing this, the current cache cell will be 'unlink'ed from
; either the LRU or bucket chains.
;
; inputs: A = don't care outputs: A = trashed
; X = offset to backward link X = trashed
; Y = offset to forward link Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT unlink
unlink ;
stx c_temp_bwd
sty c_temp_fwd
ldx prev_vp
ldy prev_vp+2
jsl deref
stx <cache_pre_ptr
sty <cache_pre_ptr+2
ldy c_temp_fwd ;offset to forward vp link
lda next_vp
sta [<cache_pre_ptr],y
iny
iny
lda next_vp+2
sta [<cache_pre_ptr],y
EXPORT unlink_bwd
unlink_bwd ;
ldx next_vp
ldy next_vp+2
jsl deref
stx <cache_nxt_ptr
sty <cache_nxt_ptr+2
ldy c_temp_bwd ;offset to backward vp link
lda prev_vp
sta [<cache_nxt_ptr],y
iny
iny
lda prev_vp+2
sta [<cache_nxt_ptr],y
rts
;-----------------------------------------------------------------------------
; D_FROM_TAIL -- deletes a cache cell from the LRU tail
;
; This routine will try to delete the last recently used cache cell that's
; not deferred from the cache list.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means a cache cell was deleted
; c = 1 means it's mike's fault or they're all deferred blocks
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT d_from_tail
d_from_tail ;
ldx tail_vp
ldy tail_vp+2
dft_00
jsr curr_vp_to_ptr ;convert the current VP to a real pointer
;-----------------------------------------------------------------------------
; we can only delete cell(s) that are not deferred. we may have to walk the
; entire list to find somebody who's not deferred.
;-----------------------------------------------------------------------------
ldy #c_priority
lda [<cache_cur_ptr],y ;get this cell's priority
bpl dft_02 ;skip if not deferred
ldy #c_lru_bwd
lda [<cache_cur_ptr],y
iny
iny
tax ;save backward vp link, lo
bne dft_01 ;skip if not 0
lda [<cache_cur_ptr],y
bne dft_01a ;skip if not 0
;-----------------------------------------------------------------------------
; if we get here then we're at the head of the list and still haven't been
; able to delete anybody.
;-----------------------------------------------------------------------------
sec ;we're at the end
rts
dft_01 lda [<cache_cur_ptr],y
dft_01a tay ;save backward vp link, hi
bra dft_00 ;loop for next cell
;-----------------------------------------------------------------------------
; if we get here then we found a non deferred block, delete this puppy. The
; tail_vp may be updated by the delete routine, we don't mess with it here.
;-----------------------------------------------------------------------------
dft_02 ;
dft_03 jsl cache_xdelete ;delete this block
rts ;result in c
;-----------------------------------------------------------------------------
; IS_THERE_ROOM -- checks to if there is enough room for the next cache cell
;
; It's just a simple 4 byte compare.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means there's not enough room
; c = 1 means there's enough room
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT is_there_room
is_there_room ;
sec
lda c_bytes_free
sbc c_request_size
lda c_bytes_free+2
sbc #$0000
rts
;-----------------------------------------------------------------------------
; ADD_TO_FREE -- add freed bytes back to free byte count
;
; This routine will add the number of bytes about to be released, back to
; Mike. It's just a simple 4 byte addition.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT add_to_free
add_to_free ;
ldy #c_cellsize
clc
lda c_bytes_free
adc [<cache_cur_ptr],y
sta c_bytes_free
bcc atf_00
inc c_bytes_free+2 ;bump this for carry
atf_00 rts
;-----------------------------------------------------------------------------
; SET_CACHE_PTR -- sets drvr_cach_ptr
;
; This routine will set drvr_cach_ptr, that's all.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = trashed
; Y = don't care Y = trashed
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = don't care
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT set_cache_ptr
set_cache_ptr ;
clc
lda <cache_cur_ptr ;get pointer to current cache cell
adc #c_headerlen ;add to it the cache header length
sta <drvr_cach_ptr ;pointer to cached block, lo
lda <cache_cur_ptr+2
adc #$0000
sta <drvr_cach_ptr+2 ;pointer to cached block, hi
rts
;-----------------------------------------------------------------------------
; LOOK_IN_ARRAY -- looks in bucket array for an entry
;
; This routine will index into the bucket array for an entry. If the entry is
; not 0, then the block we're looking for is somewhere in that particular
; bucket list. If the entry is 0, then the bucket array has no knowledge of
; the requested block.
;
; inputs: A = don't care outputs: A = trashed
; X = don't care X = vp to cached block, lo
; Y = don't care Y = vp to cached block, hi
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means there's something here, still have to traverse links
; c = 1 means there's no entry for this bucket index
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT look_in_array
look_in_array
jsr deref_bucket ;Deref the bucket table and setup cache_bkt_ptr
lda <drvr_blk_num ;get block number
and #$007f ;keep low 7 bits
sta c_temp_element ;save this for later
asl a
asl a ;multiply by 4 and make into index
tay
lda [<cache_bkt_ptr],y ;get lo part
tax ;save in x
iny
iny
lda [<cache_bkt_ptr],y ;get hi part
bne lia_00 ;skip if <> 0
tay
txa
bne lia_01 ;skip if <> 0
sec ;no entry for this block
rts
lia_00 tay ;move hi part into y
lia_01 clc ;indicate an entry found
rts
;-----------------------------------------------------------------------------
; WRITE_TO_DISK -- writes a block to a disk
;
; This routine will write a block from the cache to a block device. The
; blocks to be written will most likely be deferred blocks. The block to be
; written is pointed to by cache_cur_ptr
;
; inputs: A = don't care outputs: A = don't care
; X = don't care X = don't care
; Y = don't care Y = don't care
; D = gs/os direct page D = i didn't change it
; B = don't care B = preserved
; K = don't care K = preserved
; LCbank = don't care LCbank = i didn't change it
;
; on output: c = 0 means the write's successful
; c = 1 means the write went wrong
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT write_to_disk
write_to_disk ;
lda #drvr_write ;driver write command
sta <drvr_call_num
ldy #c_blknum ;offset to block number, lo
lda [<cache_cur_ptr],y
sta <drvr_blk_num
iny
iny ;offset to block number, hi
lda [<cache_cur_ptr],y
sta <drvr_blk_num+2
sec
ldy #c_cellsize ;offset to size of cache cell
lda [<cache_cur_ptr],y
sbc #c_headerlen ;subtract away the cache header
sta <drvr_req_cnt ;want to write this many bytes
clc
lda <cache_cur_ptr
adc #c_headerlen ;point past the cacher header
sta <drvr_buf_ptr ;data starts here, lo
lda <cache_cur_ptr+2
adc #$0000
sta <drvr_buf_ptr+2 ;data starts here, hi
; i think we got everything ready for a write, let's do it
jsl dev_dispatcher
rts ;result in a and c
;-----------------------------------------------------------------------------
; CACHE_ERROR -- exits to the caller
;
; This routine will exit back to the caller because of some sort of error.
; The error usually results from fiddling with the mike memory manager or
; the LRU or bucket links are trashed. This shouldn't happen though . . .
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cache_error
cache_error ;
plb ;restore caller's data bank
sec ;indicate an error
rtl ;go back with bad news
ENDP
;-----------------------------------------------------------------------------
; Cache_In_Queue --
;
; This routine will add a task in the OutOfMemory queue routine. If the
; memory manager runs out of memory then I will purge the cache.
;
;-----------------------------------------------------------------------------
EXPORT Cache_In_Queue
Cache_In_Queue Proc
lda >InQueueAlready ;See if I am already in the queue
bmi @skip_add ;I am already in the queue thank you very much.
pea MyOutOfMemRoutine>>16
pea MyOutOfMemRoutine
ldx #$0C02 ;AddToOOMQueue
jsl $e10000
lda #$FFFF
sta >InQueueAlready
@skip_add rtl ;return to the caller
Export Cache_out_of_Queue
Cache_out_of_Queue
lda call_number ;is this a Reset_Cache Call?
cmp #$2026
beq @skip_remove ;It sure is so don't do anything
lda InQueueAlready ;Am I in the queue?
beq @skip_remove
pea MyOutOfMemRoutine>>16
pea MyOutOfMemRoutine
ldx #$0D02 ;DeleteFromOOMQueue
jsl $e10000
lda #$0000 ;zero the InQueue Flag
sta InQueueAlready
@skip_remove rts
MyOutOfMemRoutine
dc.l 000000 ;Used by the Queue Manager?
cache_reset_list ;zero PCount for reset cache call
dc.w 0000 ;Doubles as ResetCacheList and Queue Header
dc.w $A55A
RTLAddr equ 1
stage equ RTLAddr+3 ;First or second stage of calls
BytesNeeded equ stage+2 ;Number of bytes the memory manager needs
Result equ BytesNeeded+4 ;Number of bytes I have freed up!
active_flag equ $e100Be ;OS active flag: BIT 15 set to 1 = busy
;
;Lets zap the results please
;
lda #$0000
sta Result,s
sta Result+2,s ;tell Memory Manger Nothing yet.
;
;See if the OS busy first. If it is then we let the OS deal with the situation.
;
lda >active_flag ;is the OS Busy???
bmi @end_mem ;Yep it sure is.
;
;See if we are being called before or after purging data.
;
lda stage,s
beq @do_free ;only free before purging....
@end_mem
longa off
sep #$20 ;8 bit mode please
;
;Get return address
;
pla
ply
;
;Remove size bytes of parameters
;
plx
plx
plx
phy
pha
longa on
rep #$20 ;back to caller
rtl
@do_free
phb
phk
plb
jsr GetFreeMem ;go get the count please A=Low, Y=High
sta curr_free_mem ;the current state of memory
sty curr_free_mem+2
;
;Now what we do is issue a Reset Cache Call to GS/OS
;
jsl $e100a8
dc.w $2026 ;reset cache call
dc.l cache_reset_list
jsr GetFreeMem ;A=Low, Y=High
sec
sbc curr_free_mem ;get the new memory count please
tax
tya
sbc curr_free_mem+2
plb ;reset the bank register please
sta result+2,s ;save the high word of newly freed memory
txa
sta result,s
bra @end_mem ;return to the caller
GetFreeMem
pha
pha ;lets see how much memory is free right now.
ldx #$1b02 ;Get FREEMEM call
jsl $e10000
pla ;get the low word
ply
rts
curr_free_mem dc.l 00
InQueueAlready dc.w 00 ;indicates if I am installed in the Queue.
endp
;-----------------------------------------------------------------------------
; DATA
;
; Note: every variable better be an even number of bytes.
;
; cache_cur_ptr, cache_nxt_ptr, cache_pre_ptr and cache_bkt_ptr are in
; GS/OS direct page
;
; Copyright (c) 1987 Apple Computer Inc. All rights reserved.
; author: Ray (Rowdy Yates) Chiang
;-----------------------------------------------------------------------------
EXPORT cache_data
cache_data PROC
EXPORT start_of_data
start_of_data ;
EXPORT head_vp
head_vp DS.B 4 ;vp to head of LRU list
EXPORT tail_vp
tail_vp DS.B 4 ;vp to tail of LRU list
EXPORT current_vp
current_vp DS.B 4 ;vp to current cache cell
EXPORT next_vp
next_vp DS.B 4 ;vp to next cache cell
EXPORT prev_vp
prev_vp DS.B 4 ;vp to previous cache cell
EXPORT bucket_vp
bucket_vp DS.B 4 ;vp to bucket vps
EXPORT c_bytes_free
c_bytes_free DS.B 4 ;number of bytes free in cache
EXPORT c_request_size
c_request_size DS.B 2 ;current request size
EXPORT c_temp_element
c_temp_element DS.B 2 ;temp for bucket element
EXPORT c_temp_fwd
c_temp_fwd DS.B 2 ;temp for forward vp link
EXPORT c_temp_bwd
c_temp_bwd DS.B 2 ;temp for backward vp link
EXPORT c_temp_1
c_temp_1 DS.B 2 ;temp for device number or FST offset
EXPORT c_temp_2
c_temp_2 DS.B 2 ;temp for device number or FST value
EXPORT c_temp_nvp
c_temp_nvp DS.B 4 ;temp for next_vp
EXPORT c_marker
c_marker DS.B 2 ;temp for debugging
EXPORT no_find
no_find DS.B 2 ;flag for enable/disable find routine
EXPORT message_shown
message_shown DS.B 2 ;flag to indicate deferred blocks
; ;have been flushed and user was told
export in_queue
in_queue dc.w $0000
EXPORT end_of_data
end_of_data
export c_data_len:equ
c_data_len equ end_of_data-start_of_data-1
ENDP
;===============================================================================
; cashseg
;
; Framework for building load segment cashseg.
;
;===============================================================================
cashseg_end PROC
ENDP
cache_overflow proc org $00AA00, skip ;This will generate an error if
endp ;the code overflows its space.
END