antoine-source/scsi2/SCSI.Drivers/SCSI Set Vol:Disk

1 line
20 KiB
Plaintext

;*******************************************************
;
; SCSI Driver Set Volume/Disk Parms code.
;
; Written by Matt Gulick. Started April 17,1991
;
; Copyright Apple Computer, Inc. 1990
;
;*******************************************************
;*******************************************************
;
; This file contains the Set Volume/Disk Parms as
; defined in the ERS.
;
;*******************************************************
;*******************************************************
;
; Revision History:
;
;*******************************************************
; April 17, 1991 File started.
IMPORT chk_count
IMPORT length
IMPORT rqst
IMPORT gc_buff_ptr
IMPORT count
IMPORT temp
IMPORT error
IMPORT ddm_index
IMPORT pre_load_ddm
IMPORT pdata_block
IMPORT find_drvr_part
IMPORT set_drvr_ndex
EJECT
;*******************************************************
;
; 's_vol_parms'
;
; This routine is used to set information about the
; volume. Calls should have the DIB Pointer set to
; the volume for which the information is being
; requested.
;
; The structure of the parameter list is defined in the
; SCSI Driver ERS. The parameters are going to depend
; greatly on the type of device that this driver is
; written for. That means that the info for the Scanner
; will not be the same in any form as that for a Hard
; Disk, or a Tape drive. These calls will be particular
; for the device type supported.
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB (LONG)
; [buff_ptr] = Data Buffer Pointer (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 svp
svp
;
; Check the Request Count. Volume calls
; need 2 bytes.
;
lda <rqst_cnt+2
bne @rqst_cnt_ok
lda <rqst_cnt
cmp #$0002
blt @bad_cnt
;
; Check Bitmap.
;
@rqst_cnt_ok lda [buff_ptr]
;
; Do the Volume Parms Here.
; Acc = Bitmap on entry.
;
sta |bitmap
and #vconf_resv2++\
vconf_resv3++\ ;Check Bits that are not supported
vconf_resv4++\ ;at this time.
vconf_resv5++\
vconf_resv6
bne @exit_parm ;If unsupported bit set then error out.
;
; Check for Remount Bit
;
lda |bitmap
and #vconf_remount
beq @next_0
jsr remount_vol
;
; Check Status Bits Flag. If set, then we
; use the low byte of this word to set the
; status bits in the Partition Map and in
; the DIB Status.
;
@next_0 lda |bitmap
and #vconf_set_stat
beq @next_1
jsr set_stat_bits
@next_1 bcs @rts
lda #$0002
sta <trans_cnt
lda #null
sta <trans_cnt+2
clc
@rts rts
;
; Error exit point.
;
@bad_cnt lda #drvr_bad_cnt
brl exit_none
;
; Drive is Offline.
;
@not_online lda #drvr_off_line
sec
rts
;
; Not from a partition.
;
@exit_parm brl exit_parm
;
; Routines used by the above code to
; perform the requested task.
;
remount_vol
;
; Mark this DIB as Switched and Hard
; Offline.
;
ldy #dib.dvcflag
lda [dib_ptr],y
ora #dvc_online++\
dvc_switch
and #dvc_hardofl--\
$ffff
sta [dib_ptr],y
;
; Generate a Disk Switched Event
;
jsr set_disk_sw
;
; Clean Exit.
;
rts
set_stat_bits
;
; Set the Status Bits in the Partition
; Map entry to mach those supplied by
; this call.
;
; Check to see if this Volume is Online.
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #dvc_online
beq @not_online
;
; Validate that this DIB is from
; a Partition Map Entry.
;
ldy #dib.start_blk
lda [dib_ptr],y
ldy #dib.start_blk+2
ora [dib_ptr],y
bne @over
;
; Not from a partition.
;
lda #drvr_bad_parm
sec
rts
;
; Get block that contains this
; DIB's Partition Map Entry.
;
@over ldy #dib.part_blk
lda [dib_ptr],y
sta |rpm_blk_num
sta |wpm_blk_num
;
; Tell the code that we have already
; set the Block Number and that this
; is not a startup call.
;
dec |stat_cont ;This is from a Status or Control Call
dec |rebuild ;And not from a startup Call
;
; Issue the Read PM Block Call.
;
jsr |read_pm_blk
bcs @bad_exit ;There was an error.
;
; Is what we read a Partition Map?
;
lda |pm.Sig\
+internal_buff
cmp #Part_sig
bne @bad_exit ;Bad Data Read.
;
; Set the Status Byte
;
lda |bitmap
and #$00ff
sta @temp
lda |pm.PartStatus+2\
+internal_buff
xba
and #$ff00
ora @temp
xba
sta |pm.PartStatus+2\
+internal_buff
;
; Issue the Write PM Block Call.
;
jsr |write_pm_blk
bcs @bad_exit ;There was no error.
;
; Clean Exit
;
@all_done jsr set_our_dp
lda @temp ;Update the DIB.
and #vconf_wr_enable++\
vconf_rd_enable
asl a
sta @temp
ldy #dib.dvcchar
lda [dib_ptr],y
and #write_allow++\
read_allow--\
$ffff
ora @temp
sta [dib_ptr],y
;
; Generate a Disk Switched Event
;
jsr set_disk_sw
lda #no_error
clc
rts
;
; Data Area.
;
@temp dc.w null
;
; Not from a partition.
;
@not_online lda #drvr_off_line
bra exit_none
;
; Error exit point.
;
@bad_exit jsr set_our_dp
lda #drvr_io
bra exit_none
;
; Error exit point.
;
@bad_cnt lda #drvr_bad_cnt
bra exit_none
;
; Use this code to exit when no data is
; being returned.
;
exit_parm lda #drvr_bad_parm
exit_none stz <trans_cnt
stz <trans_cnt+2
cmp #$0001
rts
EJECT
;*******************************************************
;
; 's_disk_parms'
;
; This routine is used to set information about the
; disk in question. The DIB Pointer must point to
; the head DIB if this is a linked device.
;
; The structure of the parameter list is defined in the
; SCSI Driver ERS. The parameters are going to depend
; greatly on the type of device that this driver is
; written for. That means that the info for the Scanner
; will not be the same in any form as that for a Hard
; Disk, or a Tape drive. These calls will be particular
; for the device type supported.
;
; Called via 'JSR'
;
; Inputs: [dib_ptr] = Target DIB (LONG)
; [buff_ptr] = Data Buffer Pointer (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 sdp
sdp
;
; Check the Request Count. Volume calls
; need at least 4 bytes. Disk calls need
; more and that will be verified there.
;
lda <rqst_cnt+2
bne @rqst_cnt_ok
lda <rqst_cnt
cmp #$001A
blt @bad_cnt
;
; Check to see if this Volume is Online.
;
@rqst_cnt_ok ldy #dib.dvcflag
lda [dib_ptr],y
and #dvc_online
beq @not_online
;
; Validate that this DIB is from
; a Partition Map Entry.
;
ldy #dib.start_blk
lda [dib_ptr],y
ldy #dib.start_blk+2
ora [dib_ptr],y
bne do_sdisk
;
; Not from a partition.
;
lda #drvr_bad_parm
brl exit_none
;
; Not from a partition.
;
@not_online lda #drvr_off_line
brl exit_none
;
; Error exit point.
;
@bad_exit jsr set_our_dp
lda #drvr_io
brl exit_none
;
; Error exit point.
;
@bad_cnt lda #drvr_bad_cnt
brl exit_none
;
; Set Disk Calls are handled here.
;
do_sdisk stz |error
;
; Preserve the Users Buffer Pointer.
;
lda <buff_ptr
sta gc_buff_ptr
lda <buff_ptr+2
sta gc_buff_ptr+2
;
; If a call is unacceptable an error will
; be returned and the transfer length
; will reflect the buffer size that is
; needed if the current one is too small.
;
; Check Set DDM Info
;
ldy #disk_pl.ddm_buff_len
lda [buff_ptr],y
bne @chk_ddm_len
ldy #disk_pl.ddm_buff_ptr
ora [buff_ptr],y
ldy #disk_pl.ddm_buff_ptr+2
ora [buff_ptr],y
bne @bad_ddm_len
bra @pre_load_ddm
;
; Is the DDM Buffer Long enough?
;
@chk_ddm_len cmp #$0200
beq @do_ddm
;
; Bad request length for the DDM
;
@bad_ddm_len lda #$0200
ldy #disk_pl.ddm_trns_len
sta [buff_ptr],y
lda #drvr_bad_cnt
sta |error
bra @pre_load_ddm
;
; Set DDM.
;
@do_ddm jsr set_ddm
bcc @chk_vol
brl @disk_done
;
; If called, the user is not
; setting the DDM and we need
; to load it into our own buffer.
;
@pre_load_ddm jsr pre_load_ddm
bcc @chk_vol
brl @disk_done
;
; Check Set Volume Info
;
@chk_vol ldy #disk_pl.vol_buff_len
lda [buff_ptr],y
bne @chk_vol_len
ldy #disk_pl.vol_buff_ptr
ora [buff_ptr],y
ldy #disk_pl.vol_buff_ptr+2
ora [buff_ptr],y
bne @bad_vol_len
bra @chk_drvr
;
; Is the DDM Buffer Long enough?
;
@chk_vol_len cmp #$0200
beq @do_vol
;
; Bad request length for the DDM
;
@bad_vol_len lda #$0200
ldy #disk_pl.vol_trns_len
sta [buff_ptr],y
lda #drvr_bad_cnt
sta |error
bra @chk_drvr
;
; Set Volume Info.
;
@do_vol jsr set_vol
bcs @disk_done
;
; Check Set Driver Info
;
@chk_drvr clc
lda |ddm_index
adc #$0004
tay
lda [ddm_buff],y
xba
asl a ;Convert Blocks to Bytes
stz |drvr_size
stz |drvr_size+2
sta |drvr_size+1
;
; Check Set Driver Data
;
ldy #disk_pl.drvr_buff_len
lda [buff_ptr],y
bne @chk_drvr_len
ldy #disk_pl.drvr_buff_ptr
ora [buff_ptr],y
ldy #disk_pl.drvr_buff_ptr+2
ora [buff_ptr],y
bne @bad_drvr_len
bra @disk_done1
;
; Is the DDM Buffer Long enough?
;
@chk_drvr_len cmp |drvr_size
blt @do_drvr
beq @do_drvr
;
; Bad request length for the DDM
;
@bad_drvr_len lda |drvr_size
ldy #disk_pl.drvr_trns_len
sta [buff_ptr],y
lda #drvr_bad_cnt
bra @disk_done
;
; Get Volume Info.
;
@do_drvr jsr set_drvr
;
; All done. Return the transfer
; length and any error codes that
; were encountered
;
@disk_done sta |error
@disk_done1 lda #$001A
sta <trans_cnt
stz <trans_cnt+2
;
; Replace the Buffer Pointer.
;
lda gc_buff_ptr
sta <buff_ptr
lda gc_buff_ptr+2
sta <buff_ptr+2
lda |error
cmp #$0001
rts
;
; Subroutines for this code.
;
; The first Routine is used to Write
; the DDM from the callers buffer.
;
set_ddm jsr set_drvr_ndex
;
; Tell the Main Driver where
; our command structure resides.
;
lda #@write_ddm
sta <scsi_mdrvr
lda #^@write_ddm
sta <scsi_mdrvr+2
;
; Set the user's buffer
;
ldy #disk_pl.ddm_buff_ptr
lda [buff_ptr],y
tax
ldy #disk_pl.ddm_buff_ptr+2
lda [buff_ptr],y
sta <buff_ptr+2
sta <ddm_buff+2 ;Incase we need it for the Driver Code
stx <buff_ptr
stx <ddm_buff ;Incase we need it for the Driver Code
;
; Is what we are writing a Driver
; Descriptor Map?
;
lda [ddm_buff]
cmp #DDM_sig
bne @bad_exit1 ;Bad Data.
lda #block_size
sta <rqst_cnt
lda #^block_size
sta <rqst_cnt+2
;
; Set internal command flag
;
dec |internal
;
; Set the Partition call flag
;
dec |f_partition
;
; Set the Call Type and Issue the
; READ BLOCK Command.
;
lda #scsit_cont
sta |call_type
;
; Issue the call.
;
jsr check_532_rw
php
;
; Replace the Buffer Pointer.
;
lda gc_buff_ptr
sta <buff_ptr
lda gc_buff_ptr+2
sta <buff_ptr+2
;
; Check for Call Errors
;
plp
bcs @bad_exit1
;
; Add in the Length
;
lda #block_size
ldy #disk_pl.ddm_trns_len
sta [buff_ptr],y
;
; Clean Exit.
;
lda #$0000
clc
rts
;
; Error exit point.
;
@bad_exit1 jsr set_our_dp
lda #drvr_io
sec
rts
;
; Data for the WRITE BLOCK Command
;
@write_ddm dc.b $0A
dc.b null
dc.w null
dcb.b 10,null
;
; This Routine is used to set the
; Volume Info from the callers buffer.
;
set_vol
;
; Find the Partition Map Entry that matches
; the data blocks used in the DDM.
;
ldy ddm_index
lda [ddm_buff],y
sta |pdata_block
iny
iny
lda [ddm_buff],y
sta |pdata_block+2
lda #$0001 ;Start looking here.
ldx #internal_buff
ldy #^internal_buff
jsr find_drvr_part
bcs @rts
;
; Set the Partition Map Block Number
; that we need to Write.
;
sta @write_vol_num
;
; Tell the Main Driver where
; our command structure resides.
;
lda #@write_vol
sta <scsi_mdrvr
lda #^@write_vol
sta <scsi_mdrvr+2
;
; Set the user's buffer
;
ldy #disk_pl.vol_buff_ptr
lda [buff_ptr],y
tax
ldy #disk_pl.vol_buff_ptr+2
lda [buff_ptr],y
sta <buff_ptr+2
sta <config_buff+2
stx <buff_ptr
stx <config_buff
;
; Is what we are writing a Driver
; Descriptor Map?
;
lda [config_buff]
cmp #Part_sig
bne @bad_exit1 ;Bad Data Read.
lda #block_size
sta <rqst_cnt
lda #^block_size
sta <rqst_cnt+2
;
; Set internal command flag
;
dec |internal
;
; Set the Partition call flag
;
dec |f_partition
;
; Set the Call Type and Issue the
; READ BLOCK Command.
;
lda #scsit_cont
sta |call_type
;
; Issue the call.
;
jsr check_532_rw
php
;
; Replace the Buffer Pointer.
;
lda gc_buff_ptr
sta <buff_ptr
lda gc_buff_ptr+2
sta <buff_ptr+2
;
; Check for Call Errors
;
plp
bcs @bad_exit1
;
; Add in the Length
;
lda #block_size
ldy #disk_pl.vol_trns_len
sta [buff_ptr],y
;
; Clean Exit.
;
lda #$0000
clc
@rts rts
;
; Error exit point.
;
@bad_exit1 jsr set_our_dp
lda #drvr_io
sec
rts
;
; Data for the WRITE BLOCK Command
;
@write_vol dc.b $0A
dc.b null
@write_vol_num dc.w null
dcb.b 10,null
;
; This Routine is used to set the
; Driver Data into the callers buffer.
;
set_drvr
;
; At this point the DDM is in Memory
; and the Zero Page Pointer 'DDM_BUFF'
; points to it.
;
ldy ddm_index
lda [ddm_buff],y
and #%0001111100000000 ;Allow Byte 1, bits 0-4 to pass
ora #$000A ;OR in the command number
sta @write_drvr
iny
iny
lda [ddm_buff],y
sta @block_num
iny
iny
lda [ddm_buff],y
xba
asl a ;Cheap Multiply by $200
stz <rqst_cnt
stz <rqst_cnt+2
sta <rqst_cnt+1
;
; Set the user's buffer
;
ldy #disk_pl.drvr_buff_ptr
lda [buff_ptr],y
tax
ldy #disk_pl.drvr_buff_ptr+2
lda [buff_ptr],y
sta <buff_ptr+2
sta <config_buff+2
stx <buff_ptr
stx <config_buff
;
; Tell the Main Driver where
; our command structure resides.
;
lda #@write_drvr
sta <scsi_mdrvr
lda #^@write_drvr
sta <scsi_mdrvr+2
;
; Set internal command flag
;
dec |internal
;
; Set the Partition call flag
;
dec |f_partition
;
; Set the Call Type and Issue the
; WRITE BLOCK Command.
;
lda #scsit_cont
sta |call_type
;
; Issue the call.
;
jsr check_532_rw
php
;
; Replace the Buffer Pointer.
;
lda gc_buff_ptr
sta <buff_ptr
lda gc_buff_ptr+2
sta <buff_ptr+2
;
; Check for Call Errors
;
plp
bcs @bad_exit1
;
; Add in the Length
;
lda <rqst_cnt
ldy #disk_pl.drvr_trns_len
sta [buff_ptr],y
;
; Clean Exit.
;
lda #$0000
rts
;
; Error exit point.
;
@bad_exit1 jsr set_our_dp
lda #drvr_io
sec
rts
;
; Command to Write the Driver Data
;
@write_drvr dc.b $0A
dc.b null
@block_num dc.w null
dcb.b 10,null
;
; Other Data Storage areas.
;
EXPORT drvr_size
drvr_size dc.l null ;Driver Size in Bytes
EXPORT gc_buff_ptr
gc_buff_ptr dc.l null ;Their buffer pointer
EXPORT error
error dc.w null
EXPORT ddm_index
ddm_index dc.w null ;Index Into the DDM for the rqsted DRVR
bitmap dc.w null ;Bitmap supplied by user.
EJECT