antoine-source/scsi2/SCSI.Drivers/SCSI Filter write

1 line
14 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;*******************************************************
;
; 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