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

1 line
46 KiB
Plaintext

;*******************************************************
;
; SCSI Driver 'Status' filter.
;
; Written by Matt Gulick. Started August 12,1988
;
; Copyright Apple Computer, Inc. 1988-93
; All Rights Reserved
;
;*******************************************************
;*******************************************************
;
; This file contains the 'Status' filter as defined
; in the ERS.
;
;*******************************************************
;*******************************************************
;
; Revision History:
;
;*******************************************************
;
; Aug 12, 1988 File started.
; April 17, 1989 Made changes to accomadate the
; Scanner Driver.
;
; *** System 6.0.1 ***
;
; 16-Feb-93 Jim Murphy added DStatus $4000
; to return SCSI ID (search for
; JCM).
;
;*******************************************************
STRING PASCAL
BLANKS OFF
PAGESIZE 70
PRINT NOGEN
PRINT NOMDIR
MACHINE M65816
IMPORT bitmap
IMPORT rpm_blk_num
IMPORT stat_cont
IMPORT rebuild
IMPORT read_pm_blk
IMPORT call_type
IMPORT main_drvr
IMPORT internal
IMPORT f_partition
IMPORT test_unit_rdy
IMPORT rqst_sense
IMPORT mode_sense
IMPORT read_capacity
IMPORT t_dvc_blocks
IMPORT set_512_mode
IMPORT open_flag
IMPORT set_our_dp
IMPORT disk_switch
IMPORT set_disk_sw
IMPORT rebld_dibs
IMPORT unit_state
IMPORT trash_it
IMPORT uses_dc
IMPORT dib_data_struct
IMPORT lst_rslt_ec ;Status
IMPORT lst_rslt_id ;Status
IMPORT lst_rslt_stat ;Status
IMPORT lst_rslt_skey ;Status
IMPORT lst_rslt_info ;Status
IMPORT lst_rslt_rqlen ;Status
IMPORT lst_rslt_scode ;Status
IMPORT sense_data
IMPORT auto_sense_data
IMPORT internal_buff
IMPORT display_cnt
IMPORT current_fmt
IMPORT opt1_blk_cnt
IMPORT opt1_blk_siz
IMPORT opt1_med_siz
IMPORT opt2_blk_cnt
IMPORT opt2_blk_siz
IMPORT opt2_med_siz
IMPORT opt3_blk_cnt
IMPORT opt3_blk_siz
IMPORT opt3_med_siz
IMPORT format_options
IMPORT check_532_rw
ENTRY dvc_status
ENTRY g_config_parms
ENTRY wait_status
ENTRY fmt_options
ENTRY read_p_map
ENTRY g_last_rslt
ENTRY get_target_priority
PRINT OFF
INCLUDE 'scsihd.equates'
INCLUDE 'M16.MEMORY'
INCLUDE 'M16.UTIL'
PRINT ON
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc THEN
ENTRY gdp
ENTRY gvp
ENDIF
;-------------------------------------------------------------------------------
EJECT
;*******************************************************
;
; Main Entry point to the 'Status' filter. This
; "Filter" is called when a Status Command comes in.
; See the headers of the seperate sections for the
; details of the commands.
;
; 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 status
status PROC
;
; Check to see if this is a Get Last Result
; call. If so, then don't worry yet about
; getting the Unit State.
;
lda <cont_code
cmp #$0005
beq @status
*** Added - 16-Feb-93 JCM
cmp #$4000 ;how about GetSCSITargetPriority?
beq @status
*** End - 16-Feb-93 JCM
;
; Is the device Removable?
;
ldy #dib.dvcchar
lda [dib_ptr],y
and #removable
beq @online ;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
bcc @online
;
; Check to see if this is a Device Status.
; If so, then don't worry yet about returning
; the Error State.
;
tay
lda <cont_code
beq @status
cmp #$0004
blt @status
bpl @tya_out
cmp #$8040
blt @status
; bmi @status
@tya_out tya ;The Carry Bit is still set.
rts
;
; Check to see if this is a Device Specific
; Status call. If so, then don't worry
; about it being Offline
;
@online lda <cont_code
beq @status
bmi @status
;
; Is the device online?
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #dvc_online
bne @status ;Yes.
;
; Device is currently offline.
;
lda #drvr_off_line
sec
@rts_out rts
;
; Zero out the Data Chaining Flag
;
@status stz |uses_dc
;
; Clear transfer count.
;
lda #null
ldy #dib.trx_len
sta [dib_ptr],y
ldy #dib.trx_len+2
sta [dib_ptr],y
;
; Entry to the Status Call Filter.
; This filter acts as a mini driver.
; It examines the Status Code sent
; and calls the appropriate routines.
; If the Command is $8000 or greater,
; then it will be routed to the device
; specific section.
;
lda <stat_code
bmi @do_dvc_spec ;Device Specific Code.
;
; Check the range of the command.
;
*** Added - 16-Feb-93 JCM - This implements a new Apple-defined subcode for returning
*** the SCSI target priority (aka SCSI ID).
cmp #$4000 ;is it GetSCSITargetPriority?
bne @checkStandards
brl get_target_priority
@checkStandards
*** End - 16-Feb-93 JCM
cmp #max_s_cmd+1
bge @error
;
; Convert to an index
;
asl a
tax
jsr (@ncmd_tbl,x)
rts
;
; Bad Command Error.
;
@error lda #drvr_bad_req
sec
rts
;
; Normal Command Table.
;
@ncmd_tbl dc.w dvc_status ;Coded
dc.w g_config_parms ;Coded
dc.w wait_status ;Coded
dc.w fmt_options ;Coded
dc.w read_p_map ;Coded
dc.w g_last_rslt ;Coded
;
; Device Specific Code handling
; starts here.
;
@do_dvc_spec
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc THEN
cmp #$F000
blt @do_scsi_cmd
and #$00ff
cmp #max_config_cmd+1
bge @error
;
; Convert to an index
;
asl a
tax
jsr (@c_cmd_tbl,x)
rts
;
; Config Command Table.
;
@c_cmd_tbl dc.w gdp ;Coded (Get Disk Parms)
dc.w gvp ;Coded (Get Volume Parms)
@do_scsi_cmd
ENDIF
;-------------------------------------------------------------------------------
;
; Check version of data structure
;
stz @chk_zero ;Precondition the flag to no check
lda [buff_ptr]
beq @version_0
cmp #$0001
bne @error
;
; Version 1. Preserve the data pointer
; currently used in the DIB and replace
; it with a pointer to the USER supplied
; Data Chaining instructions.
;
clc
ldy #dib.trx_ptr
lda [dib_ptr],y
sta |dib_data_struct
lda <buff_ptr
adc #ds.DCcode ;Offset to first D.C. Data
sta [dib_ptr],y
ldy #dib.trx_ptr+2
lda [dib_ptr],y
sta |dib_data_struct+2
lda <buff_ptr+2
adc #^ds.DCcode
sta [dib_ptr],y
;
; Set flag to indicate that D.C. Commands
; were used and that we need to restore
; the pointer in the DIB to the normal
; data descriptor. Also set the flag to
; indicate that we need to check the first
; buffer pointer for Zero.
;
dec |uses_dc
dec @chk_zero
;
; Do the rest normally and check the above
; flag later.
;
@version_0 clc
lda <buff_ptr
adc #$0002
sta <scsi_mdrvr
lda <buff_ptr+2
adc #null
sta <scsi_mdrvr+2
;
; Check the buffer pointer for Null.
;
ldy #$000C
lda [scsi_mdrvr],y
sta <buff_ptr
ldy #$000C+2
lda [scsi_mdrvr],y
sta <buff_ptr+2
;
; Check First Buffer for $00000000
;
ora <buff_ptr
bne @DH_Branch
lda @chk_zero
bne @error
;
; Call Main Driver
;
@DH_Branch lda #scsit_stat
sta |call_type
jsr |main_drvr
;-------------------------------------------------------------------------------
IF scsi_dtype = apple_cd\
OR scsi_dtype = changer THEN
bcc @no_cd_error
lda auto_sense_data+\ ;Was it an $82, $84, or $85 Error?
rqst_sens.addnl_sens_code
and #$00ff
cmp #$0082 ;Checking for $82 (End of User Area)
beq @eua
cmp #$0084 ;Checking for $84 (Illegal Mode)
beq @im
cmp #$0085 ;Checking for $85 (Bad Audio Address)
beq @baa
cmp #$00B0 ;Checking for $B0 (No Media)
beq @no_media
;
; None of those. Return I/O Error.
;
lda #$0027
sec
bra @exit
;
; End of User Area.
; Carry is set by CMP being equal
;
@eua lda #$00F0
bra @exit
;
; Illegal Mode.
; Carry is set by CMP being equal
;
@im lda #$00F1
bra @exit
;
; Bad Audio Address.
; Carry is set by CMP being equal
;
@baa lda #$00F2
bra @exit
;
; Bad Audio Address.
; Carry is set by CMP being equal
;
@no_media lda #$002f
bra @exit
ELSE
;-------------------------------------------------------------------------------
bcs @exit
ENDIF
;-------------------------------------------------------------------------------
IF scsi_dtype = apple_cd\
OR scsi_dtype = changer THEN
@no_cd_error
ENDIF
;-------------------------------------------------------------------------------
;
; Save transfer count.
;
ldy #dib.trx_len
lda [dib_ptr],y
sta @call_trns_cnt
ldy #dib.trx_len+2
lda [dib_ptr],y
sta @call_trns_cnt+2
;
; Check to see if we need to handle
; a Disk Switched Event. If not,
; then exit.
;
lda |disk_switch
bpl @exit
;
; Don't Trash the Volumes.
;
jsr rebld_dibs ;Issues a DISK_SW for each rebuilt DIB.
;
; Restore Direct Page Values.
;
@exit pha
php
;
; Check the D.C. Flag
;
lda |uses_dc
beq @set_our_zp
ldy #dib.trx_ptr
lda |dib_data_struct
sta [dib_ptr],y
ldy #dib.trx_ptr+2
lda |dib_data_struct+2
sta [dib_ptr],y
stz |uses_dc ;Reset Flag
@set_our_zp jsr set_our_dp
;
; Set transfer count.
;
lda @call_trns_cnt
sta <trans_cnt
lda @call_trns_cnt+2
sta <trans_cnt+2
;
; Exit.
;
plp
pla
rts
;
; Data Area.
;
@call_trns_cnt dc.l null ;Transfer count before we stepped on it.
@chk_zero dc.w null ;Check first DCMove Flag.
ENDP
EJECT
;*******************************************************
;
;
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: See Spec.
;
;*******************************************************
EXPORT dvc_status
dvc_status PROC
;
; Get Device Status Call
;
lda <rqst_cnt+2
bne @do_max
lda <rqst_cnt
cmp #$0007
blt @no_odds
@do_max lda #$0006
@no_odds lsr a ;0 --> Bit 15, Bit 0 --> Carry
bcs @bad_rqst_cnt ;No odd byte transfers
asl a ;Carry <-- Bit 15, Bit 0 <-- 0
sta <trans_cnt
stz <trans_cnt+2
bne @at_least_2
jmp @clc
;
; Bad Request Count.
;
@bad_rqst_cnt lda #drvr_bad_cnt
rts
;
; Init Status to $0000
;
@at_least_2 stz @dvc_stat
;
; Is the Device Linked?
;
ldy #dib.dvcchar
lda [dib_ptr],y
and #linked_dvc
beq @no_link ;No.
lda #bit_14 ;Yes. Set the bit
tsb @dvc_stat
;
; Is the device busy with a pending call?
;
@no_link ldy #dib.dvcflag
lda [dib_ptr],y
and #int_busy
beq @not_busy ;No.
;-------------------------------------------------------------------------------
IF character_dvc = true THEN
;
; If the device is a character device,
; and it's busy, then also set the Buffer
; Not Empty Flag.
;
lda #bit_13\
++bit_5 ;Yes. Set the bits
tsb @dvc_stat
ENDIF
;-------------------------------------------------------------------------------
IF block_dvc = true THEN
lda #bit_13 ;Yes. Set the bit
tsb @dvc_stat
ENDIF
;-------------------------------------------------------------------------------
;
; Is the Device Online?
;
@not_busy ldy #dib.dvcflag
lda [dib_ptr],y
and #dvc_online
beq @not_online2 ;No. Skip Switch flag.
lda [dib_ptr],y ;Also Check Hard Offline
and #dvc_hardofl ;Is it hard offline?
bne @not_online ;Yes. Do switch flag
lda #bit_4 ;Online, Set the bit
tsb @dvc_stat
lda [dib_ptr],y ;Also Check switch flag
and #dvc_switch ;Is it Switched?
pha
lda [dib_ptr],y ;Clear Switch Flag.
and #dvc_switch--\
$ffff
sta [dib_ptr],y
pla
bne @not_online1 ;Yes. Do switch flag
bra @online ;Skip the following mess.
@not_online
;
; If the device's Online Flag is set
; and it's Hard Offline Flag is also
; set, then we will treat this as a
; disk switch.
;
lda [dib_ptr],y
and #dvc_online++\
dvc_switch--\
$ffff
sta [dib_ptr],y
@not_online1 lda #bit_0
tsb @dvc_stat
@not_online2
@online
;-------------------------------------------------------------------------------
IF block_dvc = true THEN
;
; If the device is a block device, is
; the Device Write Protected?
;
ldy #dib.dvcchar
lda [dib_ptr],y
and #write_allow
bne @writeable ;No.
lda #bit_2 ;Yes. Set the bit
tsb @dvc_stat
ENDIF
;-------------------------------------------------------------------------------
@writeable
;-------------------------------------------------------------------------------
IF block_dvc = true THEN
;
; If the device is a block device, has
; the Device been switched?
;
jsr rqst_sense
bcc @no_error
jmp @switch ;Yes!
;
; The following lines of code commented
; by a '****' were added because of an
; SCSI Device that returned no error when
; there was no media on line. This was
; not the correct thing for the device to
; do. Shame on him. What we needed to do
; to correct this was to get the offline
; flag, then check to see if the device
; returned an error. If an error is
; returned, then we process it normally.
; If no error was returned and the device
; is still ofline, then we treat it as a
; device not ready error. The offline will
; be cleared when the device returns an 06
; in the sense key.
;
@no_error ldy #dib.dvcflag
lda [dib_ptr],y ;****
and #dvc_hardofl ;****
tax ;****
;****
lda |sense_data+\
rqst_sens.sense_key
bne @chk_sense_key ;****
txa ;****
beq @too_far
jmp @opened ;****
@too_far jmp @its_back ;****
@chk_sense_key and #$00ff
cmp #$0002
bne @chk_for_6
jmp @chk_switch
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IF scsi_dtype<>apple_cd\
AND scsi_dtype<>changer THEN
@chk_for_6 cmp #$0006
beq @inserted
ELSE
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@chk_for_6 cmp #$0006
bne @not_a_6
lda sense_data+\ ;Was it a RESET?
rqst_sens.addnl_sens_code
and #$00ff
cmp #$00b0 ;Checking for $B0 (NO MEDIA)
beq @fixit
and #$00fe ;Checking for $28 (INSERTION)
cmp #$0028 ;or $29 (RESET)
beq @inserted ;Yes it was.
@fixit jmp @chk_switch
;
; If the device is a CD_ROM device
; then check to see if the SENSE KEY
; = 5. If so, then treat it as no
; error.
;
@not_a_6 cmp #$0005
bne @its_bs
jmp @its_back
@its_bs
ENDIF
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
stz <trans_cnt
ora #$ff00
sec
rts
;
; Rebuild the DIBs.
;
@inserted
;
; Is this device linked? If it is,
; then we need to mark them all as
; being online.
;
; Start at the headptr if non-zero.
;
ldy #dib.headptr
lda [dib_ptr],y
tax
ldy #dib.headptr+2
lda [dib_ptr],y
bne @set_pointer0 ;Should not be bank 0
;
; Current pointer is the first.
;
lda <dib_ptr+2
ldx <dib_ptr
;
; Set temp Zero Page Pointer
;
@set_pointer0 stx <scsi_zp0
sta <scsi_zp0+2
;
; Set the Flags.
;
ldy #dib.dvcflag
lda [scsi_zp0],y
and #dvc_hardofl--\
$ffff
ora #dvc_switch++\
dvc_online++\
dvc_hard_sw
sta [scsi_zp0],y
;
; If there is a forward device
; pointer than get it.
;
ldy #dib.fdvcptr
lda [scsi_zp0],y
tax
ldy #dib.fdvcptr+2
lda [scsi_zp0],y
bne @set_pointer0
@turdy jsr test_unit_rdy ;Is it ready yet?
bcc @they_r_built ;Yes.
lda auto_sense_data+\ ;Is there media in the drive?
rqst_sens.addnl_sens_code
and #$00ff
cmp #$00b0 ;Checking for $B0 (NO MEDIA)
bne @turdy ;No.
; bcs @turdy ;*************************
@they_r_built
;-------------------------------------------------------------------------------
IF scsi_dtype <> mcd_40 THEN
jsr set_512_mode
ENDIF ;scsi_dtype <> mcd_40
;-------------------------------------------------------------------------------
;
; Issue the READ CAPACITY Command.
;
jsr read_capacity
bcs @no_capacity ;Was there an error?
;
; Get the Block Count (Stored
; High >> Low. Must be switched
; to Low >> High). This is the last
; readable block number. Add 1 to
; it for comparison reasons.
;
lda |block.count\
+internal_buff\
+2
xba
adc #$0001 ;Carry is Clear as a result
sta |t_dvc_blocks ;of the 'READ CAPACITY' Call
lda |block.count\
+internal_buff
xba
adc #null
sta |t_dvc_blocks+2
@no_capacity jsr rebld_dibs ;Rebuild DIBs and Issue a DISK_SW
php ;for each
;
; Restore the origonal Direct Page
; values.
;
jsr set_our_dp
plp
bcc @set_switch
jsr test_unit_rdy
bcc @set_switch
;
; For some reason, we cannot talk to the
; device. It must be offline.
;
@chk_switch ldy #dib.dvcflag
lda [dib_ptr],y
tax
and #dvc_hardofl
bne @opened
txa
and #dvc_online--\
$ffff
ora #dvc_hardofl
sta [dib_ptr],y
lda #bit_4 ;Clear the Online bit
trb @dvc_stat
lda #bit_0 ;Set the Switch bit
tsb @dvc_stat
bra @opened
;
; Set Online Bit. If dvc_hard_sw is
; set, then clear it and return the
; disk switch bit.
;
@its_back lda [dib_ptr],y
pha
and #dvc_hard_sw
tax
pla
and #dvc_hard_sw--\
$ffff
sta [dib_ptr],y
txa
bne @set_switch
bra @opened ;Back in business
@switch ;
; Is this device linked? If it is,
; then we need to mark them all as
; being offline.
;
; Start at the headptr if non-zero.
;
ldy #dib.headptr
lda [dib_ptr],y
tax
ldy #dib.headptr+2
lda [dib_ptr],y
bne @set_pointer2 ;Should not be bank 0
;
; Current pointer is the first.
;
lda <dib_ptr+2
ldx <dib_ptr
;
; Set temp Zero Page Pointer
;
@set_pointer2 stx <scsi_zp0
sta <scsi_zp0+2
;
; Set the Flags.
;
ldy #dib.dvcflag
lda [scsi_zp0],y
ora #dvc_switch++\
dvc_online++\
dvc_hard_sw
and #dvc_online--\
$ffff
sta [scsi_zp0],y
;
; If there is a forward device
; pointer than get it.
;
ldy #dib.fdvcptr
lda [scsi_zp0],y
tax
ldy #dib.fdvcptr+2
lda [scsi_zp0],y
bne @set_pointer2
;
; Set the Switched Bit in Status
;
@set_switch lda #bit_0 ;Yes. Set the bit
tsb @dvc_stat
;
; No forward pointer. Continue on.
;
ENDIF
;-------------------------------------------------------------------------------
@opened
;-------------------------------------------------------------------------------
IF character_dvc = true THEN
;
; If the device is a character device,
; has the Device been opened?
;
lda |open_flag
beq @not_open ;No.
lda #bit_0 ;Yes. Set the bit
tsb @dvc_stat
@not_open
ENDIF
;-------------------------------------------------------------------------------
;
; If it is switched, then call disk switch.
;
lda @dvc_stat
and #bit_0+bit_4 ;If Online Bit is set then
cmp #bit_0 ;don't call disk switch
bne @no_call
jsr set_disk_sw
;
; Return the combined flags.
;
@no_call lda <rqst_cnt+2
bne @its_big
lda <rqst_cnt
beq @clc
cmp #$0007
blt @no_odds_1
@its_big lda #$0006
@no_odds_1 and #$fffe ;No odd byte transfers
sta <trans_cnt
stz <trans_cnt+2
tax
lda @dvc_stat
sta [buff_ptr]
;
; Return the Block Count.
;
dex
dex
beq @clc
ldy #dib.blkcnt
lda [dib_ptr],y
ldy #$0002
sta [buff_ptr],y
dex
dex
beq @clc
ldy #dib.blkcnt+2
lda [dib_ptr],y
ldy #$0004
sta [buff_ptr],y
;
; Exit real nice like.
;
@clc clc
rts
;
; Data for this call.
;
@dvc_stat dc.w null
ENDP
EJECT
;*******************************************************
;
; 'g_config_parms'
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: See Spec.
;
;*******************************************************
EXPORT g_config_parms
g_config_parms PROC
;
; Get Config Parms Call
;
lda #null
sta <trans_cnt
sta <trans_cnt+2
clc
rts
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc THEN
INCLUDE 'SCSI Get Vol/Disk'
ENDIF
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; Get the current Wait/No Wait status of this device.
; If it is a block device then no error will occur and
; a $0000 (Wait Mode) will be returned.
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; [buff_ptr] = Current Mode
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: See Spec.
;
;*******************************************************
EXPORT wait_status
wait_status PROC
;
; Check the parameters list.
; Should contain a WORD
;
lda <rqst_cnt
cmp #$0002
bne @bad_parm
sta <trans_cnt
;-------------------------------------------------------------------------------
IF block_dvc = true THEN
;
; If a Block Device then return Wait Mode.
;
lda #null
ENDIF
;-------------------------------------------------------------------------------
IF character_dvc = true THEN
;
; Check the Current Mode
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #wait_mode
bne @wait
;
; Return No Wait Mode.
;
lda #bit_15
bra @exit
;
; Return Wait Mode.
;
@wait lda #null
ENDIF
;-------------------------------------------------------------------------------
;
; Save it and exit.
;
@exit sta [buff_ptr]
lda #null ;Clear the Acc.
clc
rts
;
; Bad Parm Error
;
@bad_parm lda #drvr_bad_parm
sec
rts
ENDP
EJECT
;*******************************************************
;
; Get Format Options Call
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: See Spec.
;
;*******************************************************
EXPORT fmt_options
fmt_options PROC
;-------------------------------------------------------------------------------
IF block_dvc = true\
AND character_dvc = false THEN
;-------------------------------------------------------------------------------
IF scsi_dtype = apple_cd\
OR scsi_dtype = changer THEN
;
; If the device is a CD_ROM, then there
; are no format options.
stz <trans_cnt
stz <trans_cnt+2
lda #bad_dev_number
sec
rts
ENDIF ;scsi_dtype = apple_cd or changer
;-------------------------------------------------------------------------------
IF scsi_dtype = mcd_40 THEN
;
; If the device is a Tape, then there
; are no format options.
stz <trans_cnt
stz <trans_cnt+2
lda #null
clc
rts
ENDIF ;scsi_dtype = mcd_40
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc THEN
;
; Get Format Options Call
;
; It's a block device. But is
; it partitioned? If it has a
; zero start block then there is
; no partition.
;
ldy #dib.start_blk
lda [dib_ptr],y
ldy #dib.start_blk+2
ora [dib_ptr],y
beq @no_link
;
; Well, it is a partition. But is it
; the only partition. By this, I mean,
; is it a disk with a partition map
; containing only two entries, one for
; the partition map and the other for
; a single volume?
;
; Is it linked? Let's see.
;
ldy #dib.dvcchar
lda [dib_ptr],y
and #linked_dvc
bne @linked ;Linked.
;
; Now check if this is the first or
; second entry in the Partition Map.
;
ldy #dib.part_blk
lda [dib_ptr],y
xba
cmp #$0003
blt @no_link ;Only one partition.
@linked stz <trans_cnt
stz <trans_cnt+2
lda #null
clc
rts
;
; Set display count to 3
;
@no_link lda #$0003
sta |display_cnt-2
sta |display_cnt
;
; Issue MODE SENSE Call
;
jsr mode_sense
;
; Check to see if the device supports
; the page discriptors.
;
lda |mode.blk_disc\
+internal_buff
and #$00ff
beq @do_from_dib
;
; Not all device return the block count
; in this call. Shame on them. If the
; block count is missing, then get it
; from the DIB. This data is 3 bytes
; MSB >> LSB formatted.
;
lda |mode.blocks\ ;High Byte
+internal_buff\
-1
and #$ff00
ora |mode.blocks\ ;.OR.ed with the Low Word
+internal_buff\
+1
beq @do_from_dib
;
; MODE SENSE is legal. Use it.
;
; Set Block Count in format
; option list.
;
lda |mode.blocks\
+internal_buff\
+1
xba
sta |opt1_blk_cnt
sta |opt2_blk_cnt
lda |mode.blocks\
+internal_buff\
-1
xba
sta |opt1_blk_cnt+2
sta |opt2_blk_cnt+2
;
; Set Block Size in format
; option list.
;
lda |mode.blk_size\
+internal_buff\
+1
xba
cmp #$0214 ;is it = 532?
bne @not_532 ;No.
lda #$0200 ;Yes.
@not_532 sta |opt1_blk_siz
sta |opt2_blk_siz
bra @set_med_size
;
; Set Block Count in format
; option list from DIB.
;
@do_from_dib ldy #dib.blkcnt
lda [dib_ptr],y
sta |opt1_blk_cnt
sta |opt2_blk_cnt
ldy #dib.blkcnt+2
lda [dib_ptr],y
sta |opt1_blk_cnt+2
sta |opt2_blk_cnt+2
;
; Set Block Size in format
; option list.
;
ldy #dib.blksize
lda [dib_ptr],y
sta |opt1_blk_siz
sta |opt2_blk_siz
;
; Set Media Size in format
; option list.
;
@set_med_size lda |opt1_blk_cnt+3
and #$00ff
sta @t_blocks
lda |opt1_blk_cnt+1
lsr @t_blocks
lsr a
lsr @t_blocks
lsr a
lsr @t_blocks
lsr a
adc #$0000
sta |opt1_med_siz
sta |opt2_med_siz
;
; Get Read Capacity
;
jsr read_capacity
;
; Set Block Size in format
; option list.
;
lda |block.size\
+internal_buff\
+2
xba
sta |opt3_blk_siz
cmp #$0200
bne @over
;
; Set display count to 2
;
lda #$0002
sta |display_cnt-2
sta |display_cnt
;
; Set Block Count in format
; option list.
;
@over lda |block.count\
+internal_buff\
+2
xba
sta |opt3_blk_cnt
lda |block.count\
+internal_buff
xba
sta |opt3_blk_cnt+2
;
; Set Media Size in format
; option list.
;
lda |block.count\
+internal_buff\
-1
xba
sta @t_blocks
lda |block.count\
+internal_buff\
+1
xba
lsr @t_blocks
lsr a
lsr @t_blocks
lsr a
lsr @t_blocks
lsr a
adc #$0000
sta |opt3_med_siz
;
; Restore Direct Page
;
jsr set_our_dp
;
; Check Count range
;
lda <rqst_cnt+2
bne @do_max
lda <rqst_cnt
cmp #opt3_med_siz-\
format_options+\
2
blt @this_many
@do_max lda #opt3_med_siz-\
format_options+\
2
;
; Send this many bytes of the list.
;
@this_many sta <trans_cnt
stz <trans_cnt+2
tay
dey
bmi @exit
short
@loop lda format_options,y
sta [buff_ptr],y
dey
bpl @loop
longmx
;
; Exit.
;
@exit lda #null
clc
rts
;
; Data Area
;
@t_blocks dc.w null
ENDIF ;scsi_dtype = direct_acc
;-------------------------------------------------------------------------------
ENDIF ;block_dvc = true
;-------------------------------------------------------------------------------
IF block_dvc = false\
AND character_dvc = true THEN
;
; If the device is a Character Device,
; then there are no Format Options to
; return.
;
stz <trans_cnt
stz <trans_cnt+2
lda #null
clc
rts
ENDIF ;character_dvc = true
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; Most be the first device in a link!!!!
;
; Entry point to the 'Read PMap' call. This call
; takes the information given by the caller on direct
; page and builds the equivilent to a Read Status Call
; to read request count bytes starting at physical
; block number 1. This is done by setting the high
; bit of the partition call flag 'f_partition'.
;
; 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 (No Offset)
; This is for partitions.
;
; After calling the Main driver and if no errors were
; encountered, then the Transfer count will be
; updated.
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: See Spec.
;
;*******************************************************
EXPORT read_p_map
read_p_map PROC
;-------------------------------------------------------------------------------
IF block_dvc = true\
AND character_dvc = false THEN
;-------------------------------------------------------------------------------
IF scsi_dtype = apple_cd\
OR scsi_dtype = changer THEN
;
; Exit No Error.
;
lda #drvr_bad_code
sec
rts
ENDIF ;scsi_dtype = apple_cd or changer
;-------------------------------------------------------------------------------
IF scsi_dtype = mcd_40 THEN
;
; Exit No Error.
;
lda #drvr_bad_code
sec
rts
ENDIF ;scsi_dtype = mcd_40
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc THEN
stz @do_532
;
; Set the Block size on Direct Page.
; It is not placed there for this call,
; and we should not rely on it being
; left behind by the last call.
;
lda #block_size
sta <blk_size
;
; Check if first DIB in link if any.
; If it is zero, then we are already
; there. If not then error out.
;
ldy #dib.headptr+2
lda [dib_ptr],y
ldy #dib.headptr
ora [dib_ptr],y
bne @bad_dev_num
;
; Let's check the request count. If
; this is $00000000, then exit clean
; with no data transfered.
;
lda <rqst_cnt
ora <rqst_cnt+2
bne @cnt_non_zero
jmp @out_of_here
;
; 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
;
; Check for 532 byte block size
;
@chk_532 tax
lda <blk_size
cmp #block_size
bne @bad_parm
cpx #$0214
bne @bad_parm
dec @do_532
@blk_size_ok
;
; Build the (Read Data)
; Status Command $8008
;
lda #$0001 ; Sent to me Low >> High.
xba ; I Send it out High >> Low.
sta |c_block_num
;
; Set Main Driver Pointer to
; our data for the command.
;
lda #cmd_$8008
sta <scsi_mdrvr
lda #^cmd_$8008
sta <scsi_mdrvr+2
;
; Set the Partition call flag
;
dec |f_partition
;
; Call Main Driver
;
lda #scsit_stat
sta |call_type
;
; Issue the call.
;
jsr check_532_rw
bcs @rts
;
; Update Transfer Count.
;
@out_of_here lda <rqst_cnt
sta <trans_cnt
lda <rqst_cnt+2
sta <trans_cnt+2
;
; Exit No Error.
;
lda #$0000
clc
rts
@bad_dev_num lda #bad_dev_number
sec
@rts rts
;
; Variables and storage for short call.
;
@do_532 dc.w null ;532 byte block flag
;
; Command Data for this call.
;
cmd_$8008 dc.b $08
dc.b $00
c_block_num dc.w $0000
c_block_cnt dc.b $00
dcb.b 7,$00
ENDIF ;scsi_dtype = direct_acc
;-------------------------------------------------------------------------------
ENDIF ;block_dvc = true
;-------------------------------------------------------------------------------
IF block_dvc = false\
AND character_dvc = true THEN
;
; If the device is a Character Device,
; then there are no Partitions to
; read.
;
stz <trans_cnt
stz <trans_cnt+2
lda #null
clc
rts
ENDIF ;character_dvc = true
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; 'g_last_rslt'
;
; This call returns the Error code result of the last
; call. This used to inquire about the result of a
; call that may have been executed asyncronously. If
; the device is busy with a pending call when this call
; is issued, a DEVICE_BUSY Error will be returned.
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Users Buffer =
; |----------------------------------------|
; WORD +- GS/OS Error Code -+
; |----------------------------------------|
; WORD +- Device ID Number -+
; |----------------------------------------|
; WORD +- SCSI Status Code -+
; |----------------------------------------|
; WORD +- SCSI REQUEST SENSE sense key -+
; |----------------------------------------|
; LONG +- MSB -+
; +- Information Bytes -+
; +- LSB -+
; |----------------------------------------|
; WORD +- REQUEST SENSE data length -+
; |----------------------------------------|
; WORD +- Reserved -+
; |----------------------------------------|
;
; Errors: Device Busy. Only if the target device
; currently has a call pending.
;
;*******************************************************
EXPORT g_last_rslt
g_last_rslt PROC
;
; Is this the same device?
;
lda <dev_num
cmp |lst_rslt_id
bne @bad_dvc_num
;
; Check if the device has a call
; pending.
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #int_busy
bne @device_busy
;
; Update Transfer Count.
;
lda <rqst_cnt+2
bne @rslt_all
lda <rqst_cnt
and #$fffe ;No odd byte transfers
beq @exit
cmp #lst_rslt_scode+2-\
lst_rslt_ec
blt @set_rslt
@rslt_all lda #lst_rslt_scode+2-\
lst_rslt_ec
@set_rslt sta <trans_cnt
tay
lda #null
sta <trans_cnt+2
;
; Move the Data.
;
dey
dey
@loop lda |lst_rslt_ec,y
sta [buff_ptr],y
dey
dey
bpl @loop
;
; Exit No Error.
;
@exit lda #$0000
clc
rts
;
; Errors.
;
@device_busy lda #drvr_busy
sec
@rts rts
@bad_dvc_num lda #bad_dev_number
sec
rts
ENDP
*** Added - 16-Feb-93 JCM
;*******************************************************
;
; 'get_target_priority'
;
; This is skanky, this is skanky, this is skanky. Did
; I mention that this is skanky? - jm3
;
; This call returns the SCSI target priority (known to
; most as the SCSI ID) for a given device. We walk the
; SCSI Manager's internal tables to figure this out,
; since we never need to know the ID otherwise.
; This was added solely for Jim Murphy's convience in
; adding a bit of new information to Finder's Get Info
; window ("Where" card). I've always wanted an easier
; method of getting SCSI ID's, and the Macintosh shows
; it in it's device Icon Info, so why shouldn't we? Now
; we will (at least when this code is done :-).
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB l (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Returns via 'RTS'
;
; Outputs: Acc = 0
; Carry = 0
; or
; Acc = Error
; Carry = 1
;
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; User's Buffer =
; |----------------------------------------|
; WORD +- SCSI Target Priority -+
; |----------------------------------------|
;
; Errors: ACC = drvr_bad_cnt if user did not request
; 2 bytes as the request count
;
;*******************************************************
EXPORT get_target_priority
get_target_priority PROC
lda <rqst_cnt+2
bne @bad_rqst_cnt
lda <rqst_cnt
dec a
dec a
beq @doCall
@bad_rqst_cnt lda #drvr_bad_cnt
sec
rts
; Force the SCSI Manager to update its internal variables so we can be assured that
; <active_sdr points to the SCSI Device Record associated with this dib and, correspondingly,
; this device.
@doCall jsr test_unit_rdy ;basically a dummy call, we don't care about errors
; By taking advantage of the fact that our Direct Page is $100 bytes before the SCSI Manager's,
; (it gave it to us), we can quickly get lots of cool things from it.
tdc ;our DP is active
clc
adc #$100
sta <scsi_zp0 ;we now have the SCSI Manager's direct page. Whooee! :-)
stz <scsi_zp0+2
; Now we will also rely on the fact that the SCSI Manager's direct page is set up
; at $4C on like this:
active_sdr equ $4C ;pointer to currently active SDR
ldy #active_sdr
lda [<scsi_zp0],y
tax
iny
iny
lda [<scsi_zp0],y
sta <scsi_zp0+2
stx <scsi_zp0
; Finally we have a pointer to the SDR for the target SCSI device. At offset $14 in the
; record we have the magic word - the target priority value. A single bit that's set
; within the low order byte indicates the priority.
sdr_targ_priot equ $14 ;Target device priority
ldy #sdr_targ_priot ;offset to the SCSI target priority
lda [<scsi_zp0],y
beq @ouch ;if no bits are set, we're screwed, so exit now
ldx #-1
@getTheID inx
lsr a
bcc @getTheID
txa
@ouch sta [buff_ptr] ;stuff this value in the caller's buffer
lda #2 ;we transferred 2 bytes
sta <trans_cnt
stz <trans_cnt+2
dec a ;no errors possible
dec a ; (was 2 - now 0 - save's a byte)
clc
rts
ENDP
*** End - 16-Feb-93 JCM
EJECT
END