mirror of
https://github.com/antoinevignau/source.git
synced 2025-01-01 15:30:02 +00:00
d29484938c
What we wrote to make audio hearable on a SCSI-2 CD-ROM drive ;-)
1 line
9.5 KiB
Plaintext
1 line
9.5 KiB
Plaintext
|
|
;*******************************************************
|
|
;
|
|
; SCSI Driver 'Shutdown' filter.
|
|
;
|
|
; Written by Matt Gulick. Started August 9,1988
|
|
;
|
|
; Copyright Apple Computer, Inc. 1988,89
|
|
;
|
|
;*******************************************************
|
|
|
|
;*******************************************************
|
|
;
|
|
; This file contains the 'Shutdown' filter as defined
|
|
; in the ERS.
|
|
;
|
|
;*******************************************************
|
|
|
|
;*******************************************************
|
|
;
|
|
; Revision History:
|
|
;
|
|
;*******************************************************
|
|
;
|
|
; Aug 9, 1988 File started.
|
|
; Mar 8, 1989 Modified to support Warm/Cold
|
|
; Shutdown.
|
|
|
|
STRING PASCAL
|
|
BLANKS OFF
|
|
PAGESIZE 70
|
|
PRINT NOGEN
|
|
PRINT NOMDIR
|
|
MACHINE M65816
|
|
|
|
IMPORT direct_page
|
|
IMPORT default_dib
|
|
IMPORT tot_dib_cnt
|
|
IMPORT active_starts
|
|
IMPORT stop_unit
|
|
|
|
PRINT OFF
|
|
|
|
INCLUDE 'scsihd.equates'
|
|
INCLUDE 'M16.MEMORY'
|
|
INCLUDE 'M16.UTIL'
|
|
PRINT ON
|
|
|
|
EJECT
|
|
|
|
;*******************************************************
|
|
;
|
|
; Main Entry point to the 'Shutdown' filter. This
|
|
; "Filter" is called when a Device is no longer
|
|
; desired in the tables. The following code segment
|
|
; first checks to see if the DIB being shut down is
|
|
; the default dib (it will only be shutdown durring
|
|
; startup). If it is the default dib we will do
|
|
; nothing and exit with no error. If on the other
|
|
; hand it is a valid DIB, we will clear some key
|
|
; fields within the dib and then we will alter the
|
|
; links to skip this DIB, then we update a field in the
|
|
; first DIB of this memory segment. This count tells
|
|
; how many active dibs there are in that segment. If
|
|
; this reaches zero we will then dispose this handle
|
|
; because it is unused. If we later need space to
|
|
; bring new devices online and we don't have the space,
|
|
; we'll get it at that time. If on exit there are
|
|
; still any active dibs that use this code segment then
|
|
; a DRVR_BUSY error will be returned. If no DIBs are
|
|
; active then no error will be returned.
|
|
;
|
|
; Inputs: [dib_ptr] = Last DIB built (LONG)
|
|
; Acc = Unspecified
|
|
; Carry = Unspecified
|
|
; Y register = Unspecified
|
|
; X register = Unspecified
|
|
; P register = 0=M=X=e
|
|
; Direct Page = Ours
|
|
; Data Bank = Ours
|
|
;
|
|
; Outputs: Acc = DRVR_BUSY
|
|
; Carry = 1
|
|
; unless we have no more dibs then
|
|
; Acc = 0
|
|
; Carry = 0
|
|
;
|
|
; Y register = Unspecified
|
|
; X register = Unspecified
|
|
; P register = 0=M=X=e
|
|
; Direct Page = GS/OS Direct Page
|
|
; Data Bank = Ours
|
|
;
|
|
; Errors: See Spec.
|
|
;
|
|
;*******************************************************
|
|
|
|
EXPORT shutdown
|
|
shutdown PROC
|
|
;
|
|
; Check to see if this is for the
|
|
; 'default_dib'. If it is, then we
|
|
; need to exit with a DRVR_BUSY Error.
|
|
;
|
|
lda <dib_ptr
|
|
cmp #default_dib
|
|
bne @real_dib
|
|
lda <dib_ptr+2
|
|
cmp #^default_dib
|
|
bne @real_dib
|
|
;
|
|
; Return a DRVR BUSY error and take
|
|
; no action.
|
|
;
|
|
lda #drvr_busy
|
|
sec
|
|
rts
|
|
|
|
@real_dib
|
|
|
|
;-------------------------------------------------------------------------------
|
|
|
|
IF warm_ss_suprt = true THEN
|
|
|
|
;
|
|
; It's a real DIB. Is it a COLD
|
|
; SHUTDOWN?
|
|
;
|
|
lda >warm_cold_flag
|
|
and #$0001
|
|
beq @do_cold ;It's Cold
|
|
;
|
|
; Yeah, so it's a warm shutdown. But
|
|
; does this device know what that
|
|
; means? We'll see!
|
|
;
|
|
ldy #dib.dvcchar
|
|
lda [dib_ptr],y
|
|
and #restartable
|
|
beq @do_cold ;Not restartable.
|
|
;
|
|
; Mark as OFFLINE and Relaxing
|
|
;
|
|
ldy #dib.dvcflag
|
|
lda [dib_ptr],y
|
|
and #dvc_online--\
|
|
$ffff
|
|
ora #relaxing
|
|
sta [dib_ptr],y
|
|
;
|
|
; Is the device removable?
|
|
;
|
|
; ldy #dib.dvcchar
|
|
; lda [dib_ptr],y
|
|
; and #removable
|
|
; beq @continue ;Not removable.
|
|
;
|
|
; Reinitialise DIB Device Number to
|
|
; zero.
|
|
;
|
|
lda #null
|
|
ldy #dib.devnum
|
|
sta [dib_ptr],y
|
|
;
|
|
; Do the Head and Forward links also.
|
|
;
|
|
ldy #dib.headlnk
|
|
sta [dib_ptr],y
|
|
|
|
ldy #dib.fdvclnk
|
|
sta [dib_ptr],y
|
|
;
|
|
; Get out of here updating only
|
|
; the active DIB count not the
|
|
; total DIB Count.
|
|
;
|
|
@continue jmp @update_acnt
|
|
|
|
ENDIF
|
|
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;
|
|
; It's a real DIB. Issue a $1B
|
|
; START/STOP Command. Ignor all
|
|
; errors, not all devices support
|
|
; this optional command.
|
|
;
|
|
@do_cold jsr stop_unit
|
|
;
|
|
; Set Device to Default.
|
|
;
|
|
ldy #dib.dvcflag
|
|
lda #wait_mode++\
|
|
cold_dib
|
|
sta [dib_ptr],y
|
|
;
|
|
; Shut it down. To do this we clear
|
|
; the DIB Device Number.
|
|
;
|
|
ldy #dib.devnum
|
|
lda [dib_ptr],y
|
|
sta @this_device ;Save for a while
|
|
lda #null
|
|
sta [dib_ptr],y
|
|
;
|
|
; Dec Device count for this memory
|
|
; segment.
|
|
;
|
|
ldy #dib.handle ;Set up to deref the handle to find
|
|
lda [dib_ptr],y ;where this memory segment starts.
|
|
sta <scsi_zp0
|
|
sta |@deref_handle ;Save in case we dispose of it.
|
|
ldy #dib.handle+2
|
|
lda [dib_ptr],y
|
|
sta <scsi_zp0+2
|
|
sta |@deref_handle+2
|
|
;
|
|
; Deref the Handle.
|
|
;
|
|
ldy #$0002
|
|
lda [scsi_zp0]
|
|
tax
|
|
lda [scsi_zp0],y
|
|
sta scsi_zp0+2
|
|
stx scsi_zp0
|
|
;
|
|
; Dec the count. If now = zero then
|
|
; dispose of this handle.
|
|
;
|
|
ldy #dib.mem_dib_cnt
|
|
lda [scsi_zp0],y
|
|
dec a
|
|
sta [scsi_zp0],y
|
|
|
|
bne @chk_links ;Not zero. Update link if it exists.
|
|
;
|
|
; We have emptied this memory segment.
|
|
; We now need to deallocate this
|
|
; memory segment.
|
|
;
|
|
ldy #$0002
|
|
pushword |@deref_handle+2
|
|
pushword |@deref_handle
|
|
_disposehandle
|
|
;
|
|
; Find location of previous DIB in
|
|
; linked list.
|
|
;
|
|
; Start at the default DIB.
|
|
;
|
|
lda #default_dib
|
|
sta <prev_dib
|
|
lda #^default_dib
|
|
sta <prev_dib+2
|
|
;
|
|
; Does this DIB point to the
|
|
; requseted DIB?
|
|
;
|
|
ldy #dib.linkptr+2
|
|
|
|
@prev_loop lda [prev_dib],y
|
|
tax ;Save value for later
|
|
|
|
lda [prev_dib] ;Do they match?
|
|
cmp <dib_ptr
|
|
bne @advnc_loop ;No.
|
|
cpx <dib_ptr+2
|
|
beq @set_prev ;Yes. Set new links.
|
|
|
|
@advnc_loop stx <prev_dib+2 ;No. Advance to the next DIB.
|
|
sta <prev_dib
|
|
ora <prev_dib+2
|
|
bne @prev_loop
|
|
bra @chk_links
|
|
;
|
|
; Set previous DIBs link pointer
|
|
; to the DIB that follws the one
|
|
; being shutdown.
|
|
;
|
|
@set_prev lda [dib_ptr]
|
|
sta [prev_dib]
|
|
lda [dib_ptr],y
|
|
sta [prev_dib],y
|
|
;
|
|
; We must now check to see if this DIB
|
|
; that was shutdown is linked to any
|
|
; other DIBs.
|
|
;
|
|
@chk_links ldy #dib.dvcchar
|
|
lda [dib_ptr],y
|
|
and #linked_dvc
|
|
beq @update_tcnt ;No it is not linked.
|
|
;
|
|
; It is linked. First we need to go to
|
|
; the head device if this is not it. If
|
|
; it is the head, then we need to do
|
|
; something completly different.
|
|
;
|
|
clc
|
|
ldy #dib.headptr
|
|
lda [dib_ptr],y
|
|
ldy #dib.headptr+2
|
|
ora [dib_ptr],y
|
|
beq @at_head
|
|
|
|
lda [dib_ptr],y
|
|
sta <scsi_zp0+2
|
|
ldy #dib.headptr
|
|
lda [dib_ptr],y
|
|
sta <scsi_zp0
|
|
bra @chk_lnk_loop
|
|
|
|
@at_head lda <dib_ptr
|
|
sta <scsi_zp0
|
|
lda <dib_ptr+2
|
|
sta <scsi_zp0+2
|
|
|
|
@chk_lnk_loop ldy #dib.fdvclnk
|
|
lda [scsi_zp0],y
|
|
beq @update_tcnt
|
|
|
|
cmp @this_device
|
|
beq @update_link
|
|
|
|
ldy #dib.fdvcptr
|
|
lda [scsi_zp0],y
|
|
tax
|
|
ldy #dib.fdvcptr+2
|
|
lda [scsi_zp0],y
|
|
sta <scsi_zp0+2
|
|
stx <scsi_zp0
|
|
bra @chk_lnk_loop
|
|
|
|
@update_link ldy #dib.headptr
|
|
lda [dib_ptr],y
|
|
sta [scsi_zp0],y
|
|
ldy #dib.headptr+2
|
|
lda [dib_ptr],y
|
|
sta [scsi_zp0],y
|
|
|
|
ldy #dib.fdvcptr
|
|
lda [dib_ptr],y
|
|
sta [scsi_zp0],y
|
|
ldy #dib.fdvcptr+2
|
|
lda [dib_ptr],y
|
|
sta [scsi_zp0],y
|
|
|
|
ldy #dib.fdvclnk
|
|
lda [dib_ptr],y
|
|
sta [scsi_zp0],y
|
|
;
|
|
; Clear the FDVCLNK and HEADLNKs
|
|
; incase this segment is used later.
|
|
;
|
|
lda #null
|
|
sta [dib_ptr],y
|
|
ldy #dib.headlnk
|
|
sta [dib_ptr],y
|
|
;
|
|
; Update the total DIB Count. If
|
|
; there are still some dibs left,
|
|
; then we will return a DRVR_BUSY
|
|
; error. If all done we will return
|
|
; no error. This will cause us to
|
|
; be purged.
|
|
;
|
|
@update_tcnt dec |tot_dib_cnt
|
|
@update_acnt dec |active_starts
|
|
beq @thats_all_folks
|
|
;
|
|
; More left. Return an error.
|
|
;
|
|
lda #DRVR_BUSY
|
|
sec
|
|
rts
|
|
;
|
|
; ThThThThThaaaaattt'ss all folks.
|
|
; I give, go ahead purge me. I
|
|
; LOVE IT when you do that to
|
|
; me!!!!!!
|
|
;
|
|
@thats_all_folks
|
|
;
|
|
; Exit no Error.
|
|
;
|
|
lda #null
|
|
clc
|
|
rts
|
|
;
|
|
; Internal Data Areas.
|
|
;
|
|
@deref_handle dc.l null
|
|
@this_device dc.w null
|
|
|
|
ENDP
|
|
|
|
END
|
|
|
|
EJECT
|