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
14 KiB
Plaintext
1 line
14 KiB
Plaintext
|
||
;*******************************************************
|
||
;
|
||
; SCSI Driver 'Write' filter.
|
||
;
|
||
; Written by Matt Gulick. Started June 14,1988
|
||
;
|
||
; Copyright Apple Computer, Inc. 1988,89
|
||
;
|
||
;*******************************************************
|
||
|
||
;*******************************************************
|
||
;
|
||
; This file contains the 'Write' filter as defined in
|
||
; the ERS.
|
||
;
|
||
;*******************************************************
|
||
|
||
;*******************************************************
|
||
;
|
||
; Revision History:
|
||
;
|
||
;*******************************************************
|
||
|
||
; June 14, 1988 File started.
|
||
; June 21, 1988 Modified to mach the results of
|
||
; the Code Review and added
|
||
; register comments.
|
||
|
||
STRING PASCAL
|
||
BLANKS OFF
|
||
PAGESIZE 70
|
||
PRINT NOGEN
|
||
PRINT NOMDIR
|
||
MACHINE M65816
|
||
|
||
IMPORT unit_state
|
||
IMPORT test_unit_rdy
|
||
IMPORT auto_sense_data
|
||
IMPORT main_drvr
|
||
IMPORT call_type
|
||
IMPORT w_update_cache
|
||
IMPORT divend
|
||
IMPORT divsor
|
||
IMPORT result
|
||
IMPORT max_blk_cnt
|
||
IMPORT divide
|
||
IMPORT check_532_rw
|
||
|
||
PRINT OFF
|
||
|
||
INCLUDE 'scsihd.equates'
|
||
INCLUDE 'M16.MEMORY'
|
||
INCLUDE 'M16.UTIL'
|
||
PRINT ON
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Main Entry point to the 'Write' filter. This
|
||
; "Filter" takes the information given by the caller
|
||
; on direct page and builds the equivilent to a Write
|
||
; Extended Control Call. In order of appearence:
|
||
;
|
||
; Verify that Device # $0000
|
||
; Call Number = $0003
|
||
; Block Size = dib.blksize
|
||
;
|
||
; We now Build the SCSI Main Driver Command and send
|
||
; it.
|
||
;
|
||
; The following will be validated by the Main Driver
|
||
; when it builds the command.
|
||
;
|
||
; Request Count = Block Size * i
|
||
; Block Number = Blk Num + Offset
|
||
; This is for partitions.
|
||
;
|
||
; After calling the Main driver and if no errors were
|
||
; encountered, then the Transfer count will be
|
||
; updated.
|
||
;
|
||
; Inputs: None.
|
||
;
|
||
; Outputs: 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 Write
|
||
Write PROC
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
IF scsi_dtype = scanner THEN
|
||
;
|
||
; Device is not writable.
|
||
;
|
||
lda #drvr_bad_req
|
||
sec
|
||
rts
|
||
|
||
ENDIF
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
IF scsi_dtype = apple_cd\
|
||
OR scsi_dtype = changer THEN
|
||
;
|
||
; Device is not writable.
|
||
;
|
||
lda #drvr_wrt_prot
|
||
sec
|
||
rts
|
||
|
||
ENDIF
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
IF scsi_dtype <> apple_cd\
|
||
AND scsi_dtype <> changer\
|
||
AND scsi_dtype <> scanner THEN
|
||
|
||
stz @cache
|
||
;
|
||
; Is the device Removable?
|
||
;
|
||
ldy #dib.dvcchar
|
||
|
||
lda [dib_ptr],y
|
||
and #removable
|
||
beq @write ;No.
|
||
;
|
||
; This device is removable. Now we
|
||
; need to check to see if the unit
|
||
; has gone offline, (then we need to
|
||
; report that to the OS) or if the
|
||
; unit has come back online (Rebuild
|
||
; the DIBs).
|
||
;
|
||
jsr unit_state
|
||
bcs @rts_out
|
||
;
|
||
; Is the device online?
|
||
;
|
||
ldy #dib.dvcflag
|
||
|
||
lda [dib_ptr],y
|
||
and #dvc_hardofl
|
||
bne @off_line ;Yes.
|
||
|
||
lda [dib_ptr],y
|
||
and #dvc_online
|
||
bne @write ;Yes.
|
||
;
|
||
; Device is currently offline.
|
||
;
|
||
@off_line lda #drvr_off_line
|
||
sec
|
||
@rts_out rts
|
||
;
|
||
; Let's check the request count. If
|
||
; this is $00000000, then exit clean
|
||
; with no data transfered.
|
||
;
|
||
@write lda <rqst_cnt
|
||
and #$01ff ;Cheap Check for multiple of 512
|
||
bne @bad_rqst_cnt
|
||
lda <rqst_cnt
|
||
ora <rqst_cnt+2
|
||
bne @chk_max
|
||
jmp @completed
|
||
;
|
||
; Block Number is beyond the range for this disk.
|
||
;
|
||
@out_of_range lda #drvr_bad_blk
|
||
sec
|
||
rts
|
||
;
|
||
; Requested Byte Count not a multiple of 512
|
||
;
|
||
@bad_rqst_cnt lda #drvr_bad_cnt
|
||
sec
|
||
rts
|
||
;
|
||
; Check to see if more is being
|
||
; requested then we can give him.
|
||
;
|
||
@chk_max lda <rqst_cnt
|
||
sta |divend
|
||
lda <rqst_cnt+2
|
||
sta |divend+2
|
||
|
||
lda #block_size
|
||
sta |divsor
|
||
|
||
sec
|
||
ldy #dib.blkcnt
|
||
lda [dib_ptr],y
|
||
sbc <block_num
|
||
sta |max_blk_cnt
|
||
|
||
ldy #dib.blkcnt+2
|
||
lda [dib_ptr],y
|
||
sbc <block_num+2
|
||
sta |max_blk_cnt+2
|
||
|
||
bcc @out_of_range
|
||
ora |max_blk_cnt
|
||
beq @out_of_range
|
||
|
||
jsr divide
|
||
bcs @rts_now
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
IF scsi_dtype = direct_acc THEN
|
||
|
||
;
|
||
; Verify Block Size.
|
||
;
|
||
@cnt_non_zero ldy #dib.blksize
|
||
lda [dib_ptr],y ;Block Size
|
||
cmp <blk_size
|
||
bne @chk_532
|
||
|
||
ldy #dib.blksize+2
|
||
lda [dib_ptr],y
|
||
beq @blk_size_ok
|
||
|
||
@bad_parm lda #drvr_bad_parm
|
||
sec
|
||
@rts_now rts
|
||
;
|
||
; Check for 532 byte block size
|
||
;
|
||
@chk_532 tax
|
||
|
||
lda <blk_size
|
||
cmp #block_size
|
||
bne @bad_parm
|
||
|
||
cpx #$0214
|
||
beq @no_cache
|
||
bra @bad_parm
|
||
|
||
ELSE
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
;
|
||
; Verify Block Size.
|
||
;
|
||
@cnt_non_zero ldy #dib.blksize
|
||
lda [dib_ptr],y ;Block Size
|
||
cmp <blk_size
|
||
bne @bad_parm
|
||
|
||
ldy #dib.blksize+2
|
||
lda [dib_ptr],y
|
||
beq @blk_size_ok
|
||
|
||
@bad_parm lda #drvr_bad_parm
|
||
sec
|
||
@rts_now rts
|
||
|
||
ENDIF
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
@blk_size_ok
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
IF cache_blks = true THEN
|
||
;
|
||
; Regardless of the Cache Priority,
|
||
; we need to see if it is in the cache.
|
||
;
|
||
; Set flag to cache the block only if
|
||
; it is already there.
|
||
;
|
||
dec @cache
|
||
|
||
lda <cache_prio ;Deferred Mode?
|
||
bmi @deferred ;Yes.
|
||
|
||
ENDIF
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
@no_cache
|
||
;
|
||
; Build the (Write Data) Status
|
||
; Command $802A, and just in case
|
||
; it is not accepted, we will also
|
||
; build $800A.
|
||
;
|
||
lda <block_num ; Sent to me Low >> High.
|
||
xba ; I Send it out High >> Low.
|
||
sta |c_block_num_l+2
|
||
sta |c_block_num_s
|
||
lda <block_num+2
|
||
xba
|
||
sta |c_block_num_l
|
||
;
|
||
; Set Main Driver Pointer to
|
||
; our data for the command.
|
||
;
|
||
lda #cmd_$802A
|
||
sta <scsi_mdrvr
|
||
lda #^cmd_$802A
|
||
sta <scsi_mdrvr+2
|
||
;
|
||
; Call Main Driver
|
||
;
|
||
lda #scsit_cont
|
||
sta |call_type
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
IF scsi_dtype = direct_acc THEN
|
||
;
|
||
; Issue the call.
|
||
;
|
||
jsr check_532_rw
|
||
bcc @deferred ;Everything went ok.
|
||
cmp #drvr_bad_code ;Was it a Bad Command?
|
||
beq @munge ;Yes. Do the Munging
|
||
brl @crapped_out2 ;No. Then get out of here.
|
||
|
||
@deferred jmp @completed
|
||
;
|
||
; At this point the extended call was not
|
||
; excepted. We must now issue the normal
|
||
; version of this command. First, we must
|
||
; check to see if the request is within the
|
||
; one byte block count range. If not, we
|
||
; will need to special process this request.
|
||
;
|
||
; Setup Divide routine while preserving the
|
||
; origonal count for later.
|
||
;
|
||
@munge lda <rqst_cnt
|
||
sta @orig_rqst
|
||
sta @rem_rqst
|
||
sta |divend
|
||
lda <rqst_cnt+2
|
||
sta @orig_rqst+2
|
||
sta @rem_rqst+2
|
||
sta |divend+2
|
||
|
||
lda <blk_size
|
||
sta |divsor
|
||
|
||
jsr divide
|
||
bcc @do_it
|
||
rts
|
||
;
|
||
; Preserve Buffer pointer. We will need to
|
||
; bump it a few times.
|
||
;
|
||
@do_it lda <buff_ptr
|
||
sta @orig_buff
|
||
lda <buff_ptr+2
|
||
sta @orig_buff+2
|
||
;
|
||
; Get result in block count. If > $80,
|
||
; then we need to break it into multiple
|
||
; calls. If not, then send it as is.
|
||
;
|
||
lda |result+1
|
||
bne @gr8er_80
|
||
lda |result
|
||
dec a
|
||
cmp #$0080
|
||
blt @issue_call
|
||
;
|
||
; Set the max count for a single byte block
|
||
; count (Block size * $80).
|
||
;
|
||
@gr8er_80 lda <blk_size+1
|
||
and #$00ff
|
||
lsr a
|
||
sta <rqst_cnt+2
|
||
lda <blk_size-1
|
||
and #$ff00
|
||
ror a
|
||
sta <rqst_cnt
|
||
;
|
||
; Set Main Driver Pointer to
|
||
; our data for the command.
|
||
;
|
||
@issue_call lda #cmd_$800A
|
||
sta <scsi_mdrvr
|
||
lda #^cmd_$800A
|
||
sta <scsi_mdrvr+2
|
||
;
|
||
; Call Main Driver
|
||
;
|
||
lda #scsit_cont
|
||
sta |call_type
|
||
;
|
||
; Issue the call.
|
||
;
|
||
jsr check_532_rw
|
||
bcc @did_munge
|
||
sta @error_loc
|
||
lda auto_sense_data+\
|
||
rqst_sens.sense_key
|
||
and #$00ff ;Checking for $03
|
||
cmp #$0003 ;This covers $03
|
||
bne @craped_out
|
||
;
|
||
; Some kind of I/O Error.
|
||
;
|
||
@io_error lda #drvr_io
|
||
sec
|
||
rts
|
||
|
||
@craped_out lda @error_loc
|
||
@crapped_out2 and #$7FFF
|
||
cmp #$7E00
|
||
bge @io_error
|
||
sec
|
||
@rts_0 rts
|
||
|
||
@error_loc dc.w null
|
||
;
|
||
; Check for special processing.
|
||
;
|
||
@did_munge ;
|
||
; Get Transfer Result and bump values
|
||
; for the next call.
|
||
;
|
||
clc
|
||
ldy #dib.trx_rqst
|
||
lda [dib_ptr],y
|
||
sta @trans_cnt
|
||
adc <buff_ptr
|
||
sta <buff_ptr
|
||
ldy #dib.trx_rqst+2
|
||
lda [dib_ptr],y
|
||
sta @trans_cnt+2
|
||
adc <buff_ptr+2
|
||
sta <buff_ptr+2
|
||
;
|
||
; Get remaining bytes to be transfered.
|
||
;
|
||
sec
|
||
lda @rem_rqst
|
||
sbc @trans_cnt
|
||
sta @rem_rqst
|
||
lda @rem_rqst+2
|
||
sbc @trans_cnt+2
|
||
sta @rem_rqst+2
|
||
ora @rem_rqst
|
||
beq @done
|
||
|
||
clc ;Cause = values to result in Negative
|
||
lda @rem_rqst
|
||
sbc <rqst_cnt
|
||
lda @rem_rqst+2
|
||
sbc <rqst_cnt+2
|
||
bpl @over
|
||
|
||
lda @rem_rqst
|
||
sta <rqst_cnt
|
||
lda @rem_rqst+2
|
||
sta <rqst_cnt+2
|
||
|
||
;
|
||
;*****************************************
|
||
;* Bump Block number. Pay close *
|
||
;* attention to what this comment says. *
|
||
;* If you don't and you change the code *
|
||
;* then your on your own. This word is *
|
||
;* in MSB >> LSB order. We need to add *
|
||
;* $80 to it. This is done by a simple *
|
||
;* increment. *
|
||
;*****************************************
|
||
;
|
||
@over lda |c_block_num_s
|
||
clc
|
||
xba
|
||
adc #$0080
|
||
xba
|
||
sta |c_block_num_s
|
||
|
||
brl @issue_call
|
||
;
|
||
; Restore the environment.
|
||
;
|
||
@done lda @orig_rqst
|
||
sta <rqst_cnt
|
||
lda @orig_rqst+2
|
||
sta <rqst_cnt+2
|
||
|
||
lda @orig_buff
|
||
sta <buff_ptr
|
||
lda @orig_buff+2
|
||
sta <buff_ptr+2
|
||
|
||
|
||
ELSE
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
jsr |main_drvr
|
||
bcc @completed
|
||
|
||
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
IF scsi_dtype = mcd_40 THEN
|
||
|
||
lda auto_sense_data+\
|
||
rqst_sens.addnl_sens_code
|
||
and #$00ff ;Checking for $04, $A7, $A8, or $B0
|
||
cmp #$0004 ;This cover $04
|
||
beq @not_ready
|
||
cmp #$0027 ;This cover $27 Write Protected
|
||
beq @write_protect
|
||
cmp #$00A7 ;This cover $A7
|
||
beq @not_ready
|
||
cmp #$00A8 ;This cover $A8
|
||
beq @not_ready
|
||
cmp #$00B0 ;This cover $B0
|
||
beq @not_ready
|
||
|
||
lda #drvr_io
|
||
sec
|
||
rts ;There was an error!
|
||
|
||
@write_protect ldy #dib.dvcchar
|
||
lda [dib_ptr],y
|
||
and #write_allow--\
|
||
$ffff
|
||
sta [dib_ptr],y
|
||
|
||
lda #drvr_wrt_prot
|
||
sec
|
||
rts
|
||
|
||
@not_ready lda #drvr_off_line
|
||
sec
|
||
rts
|
||
|
||
ENDIF
|
||
|
||
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
lda #drvr_io
|
||
rts ;There was an error!
|
||
|
||
@deferred
|
||
|
||
ENDIF
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
;
|
||
; Update Transfer Count.
|
||
;
|
||
@completed lda <rqst_cnt
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
IF block_dvc = true\
|
||
AND character_dvc = false THEN
|
||
|
||
and #%1111111111111110
|
||
|
||
ENDIF ;block_dvc = true
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
sta <trans_cnt
|
||
lda <rqst_cnt+2
|
||
sta <trans_cnt+2
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
IF cache_blks = true THEN
|
||
;
|
||
; Check if cache bypassed.
|
||
;
|
||
bit @cache
|
||
bpl @out_of_here ;Yes.
|
||
|
||
clc
|
||
lda <cache_prio ;Deferred Mode?
|
||
bmi @chk_cache ;Yes.
|
||
|
||
bne @chk_cache ;No.
|
||
|
||
sec ;Update only
|
||
@chk_cache jsr w_update_cache
|
||
bcc @out_of_here
|
||
lda <cache_prio ;Deferred Mode?
|
||
bpl @out_of_here ;No
|
||
stz @cache ;Yes. Force write skipping the cache
|
||
jmp @no_cache ;logic this time around.
|
||
|
||
ENDIF
|
||
|
||
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
|
||
;
|
||
; Exit No Error.
|
||
;
|
||
@out_of_here lda #$0000
|
||
clc
|
||
@rts rts
|
||
|
||
;
|
||
; Variables and storage for short call.
|
||
;
|
||
@cache dc.w null ;Cache flag
|
||
@do_532 dc.w null ;532 byte block flag
|
||
|
||
@orig_buff dc.l null ;Origonal Buffer Pointer
|
||
@orig_rqst dc.l null ;Origonal Request Count
|
||
@rem_rqst dc.l null ;Number of bytes remaining
|
||
@trans_cnt dc.l null ;number of bytes transfered by device
|
||
;this time
|
||
;
|
||
; Command Data for this call.
|
||
;
|
||
cmd_$800A dc.b $0A
|
||
dc.b $00
|
||
c_block_num_s dc.w $0000
|
||
c_block_cnt_s dc.b $00
|
||
dcb.b 7,$00
|
||
;
|
||
; Command Data for this call.
|
||
;
|
||
cmd_$802A dc.b $2A
|
||
dc.b $00
|
||
c_block_num_l dc.l $00000000
|
||
c_block_cnt_l dcb.b 3,$00
|
||
dcb.b 7,$00
|
||
|
||
ENDIF
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
ENDP
|
||
|
||
EJECT
|
||
|
||
END
|