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

1 line
38 KiB
Plaintext

;*******************************************************
;
; SCSI Driver 'Startup' filter.
;
; Written by Matt Gulick. Started July 1,1988
;
; Copyright Apple Computer, Inc. 1988,89
;
;*******************************************************
;*******************************************************
;
; This file contains the 'Startup' filter as defined
; in the ERS.
;
;*******************************************************
;*******************************************************
;
; Revision History:
;
;*******************************************************
;
; July 1, 1988 File started.
; July 21, 1988 reworked logic and added
; a few new subroutines.
; April 10, 1989 Started to add code for
; character devices for the
; Scanner.
STRING PASCAL
BLANKS OFF
PAGESIZE 70
PRINT NOGEN
PRINT NOMDIR
MACHINE M65816
IMPORT wake_me_up
IMPORT get_mm_id
IMPORT get_dvc_ram
IMPORT set_512_mode
IMPORT select_page_num
IMPORT test_unit_rdy
IMPORT start_unit
IMPORT mode_sense
IMPORT read_capacity
IMPORT default_dib
IMPORT rebld_dibs
IMPORT dpi_overide
IMPORT set_our_dp
IMPORT direct_page
IMPORT gsos_dpage
IMPORT main_drvr
IMPORT internal
IMPORT internal_buff
IMPORT get_scsimgr
IMPORT call_type
IMPORT fre_dvc_ram
IMPORT dvc_count
IMPORT rpm_blk_num
IMPORT rebuild
IMPORT part_num
IMPORT do_part_dib
IMPORT first_time
IMPORT part_cnt
IMPORT chk_ram
IMPORT dibicise_new_ram
IMPORT dibicise_new_dib
IMPORT main_caller
IMPORT active_starts
IMPORT tot_dib_cnt
IMPORT t_dvc_blocks
IMPORT auto_sense_data
ENTRY do_inq_parms
ENTRY do_mode_parms
ENTRY do_read_cap
ENTRY do_partition
ENTRY get_nxt_dvc
PRINT OFF
INCLUDE 'scsihd.equates'
INCLUDE 'M16.MEMORY'
INCLUDE 'M16.UTIL'
PRINT ON
EJECT
;*******************************************************
;
; Main Entry point to the 'Startup' filter. This
; 'Filter' is called after the driver is loaded. The
; code that follows sets up the drivers environment,
; then calls 'get_dvc_ram'. On return from the
; 'get_dvc_ram' call, the following structure are in
; place if no error ocured.
;
; dvc_list = Long Pointer to device List
; next_dib = Long Pointer to First DIB
; first_dib = Long Pointer to the beginning
; of the RAM Allocated for the
; new DIBs.
;
; This contains enough RAM for one DIB for
; each device in the device list. If more
; space is needed due to partitioning, then
; the startup filter will be responsible for
; getting that space from the memory manager.
;
; From this point, we need to build the DIB for each
; device.
;
; 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 startup
startup PROC
;-------------------------------------------------------------------------------
IF warm_ss_suprt = true THEN
;
; Check to see if this is a WARM STARTUP
; Call. If it is, we will need to handle
; this a lot differently than a normal
; startup. First of all our DIBs are, for
; the most part, already built. The only
; possible changes might be in respect to
; removable media. In any case we will
; call the warm start routine in the Driver
; Mgmt file to take care of this for us.
;
; Is it a COLD STARTUP?
;
lda >warm_cold_flag
and #$0001
bne @do_warm ;It's Warm
@no_warm_start jmp @chk_dflt ;It's Cold
;
; Check to see if this is for the
; 'default_dib'. If it is, then we need
; to exit with an error. The error is so
; that our default DIB is purged from the
; startup list.
;
@do_warm lda <dib_ptr
cmp #default_dib
bne @not_dflt
lda <dib_ptr+2
cmp #^default_dib
bne @not_dflt
lda #drvr_io ;Error Out.
sec
rts
;
; Yeah, so it's a WARM STARTUP. But
; does this device know what that
; means? We'll see!
;
@not_dflt ldy #dib.dvcchar
lda [dib_ptr],y
and #restartable
beq @no_warm_start ;Not restartable.
;
; Yeah, so it knows what that means!
; But first let's see if it is a new
; DIB.
;
ldy #dib.dvcflag
lda [dib_ptr],y
tax
;
; Compare to default value.
;
cmp #wait_mode++\
cold_dib
beq @in_valid_dib ;Unused DIB. Reject it.
;
; One last check. Is it partitioned
; and if so, does it also have a valid
; block offset?
;
ldy #dib.dvcchar
lda [dib_ptr],y
and #linked_dvc
beq @valid_dib ;Used DIB. Start it.
ldy #dib.start_blk
lda [dib_ptr],y
ldy #dib.start_blk+2
ora [dib_ptr],y
bne @valid_dib ;Used DIB. Start it.
;
; Zero out the Device Number and
; remove link.
;
@in_valid_dib lda #null
ldy #dib.devnum
sta [dib_ptr],y
ldy #dib.dvcchar
lda [dib_ptr],y
and #linked_dvc--\
$ffff
sta [dib_ptr],y
lda #drvr_no_dev ;Error Out.
sec
rts
;
;
@valid_dib txa
and #cold_dib
bne @no_warm_start ;New DIB and Awake. Do Cold Start
;
; Old DIB. But is it asleep?
;
txa
and #relaxing
beq @over_wake_up ;Not asleep.
;
; Call the Warm Restart Routine.
;
jsr wake_me_up
;
; The device is now awake. If it is
; removable we need to see if the
; disk has been changed.
;
@over_wake_up ldy #dib.dvcchar
lda [dib_ptr],y
and #removable
beq @bra_been_had ;Not removable.
;
; Rebuild the DIBs for this device if
; this is the first partition for this
; device.
;
ldy #dib.unitnum
lda [dib_ptr],y
and #max_p_mask
bne @bra_been_had ;Not the head. They've been done already
;
; Current pointer is the first.
;
lda <dib_ptr+2
ldx <dib_ptr
@set_pointer 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
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_pointer
jsr set_512_mode
lda #$ffff ;Don't Do Post Driver Installs
sta |dpi_overide
jsr rebld_dibs ;Rebuild DIBs and Issue a DISK_SW for each
php
stz |dpi_overide ;Clear the Overide
;
; Restore the origonal Direct Page values.
;
jsr set_our_dp
plp
bcc @bra_been_had
jsr test_unit_rdy
bcc @bra_been_had
;
; For some reason, we cannot talk to the
; device. It must be offline.
;
@chk_switch ldy #dib.dvcflag
lda [dib_ptr],y
and #dvc_online--\
$ffff
sta [dib_ptr],y
;@bra_been_had jmp @links_done
@bra_been_had bra @ive_been_had
ENDIF
;-------------------------------------------------------------------------------
;
; Check to see if this is for the
; 'default_dib'. If it is, then we need
; to build all the devices that we can and
; exit with an error. The error is so that
; our default DIB is purged from the startup
; list. The device dispatcher will then
; call us for the DIB pointed to in the
; 'default_dib's link pointer. This and any
; further 'STARTUP' calls will exit with no
; error, except that no action will be taken
; other than to increment the startup call
; count to be used as a balance for the
; shutdown calls that will eventually be
; issued.
;
@chk_dflt lda <dib_ptr
cmp #default_dib
bne @ive_been_had
lda <dib_ptr+2
cmp #^default_dib
;-------------------------------------------------------------------------------
IF part_suprt = false Then
beq @im_a_virgin
@ive_been_had ;
; Mark the device as started and
; as online.
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #cold_dib--\
$ffff
;===============================================================================
IF character_dvc = true Then
ora #dvc_online
ENDIF
;===============================================================================
sta [dib_ptr],y
ELSE
;-------------------------------------------------------------------------------
bne @ive_been_had
jmp @im_a_virgin
@ive_been_had
;
; Clear the Cold Start Flag.
;
ldy #dib.dvcflag
lda [dib_ptr],y
and #cold_dib--\
$ffff
sta [dib_ptr],y
;
; Check the Partition Bits. If they
; are all clear, then we will set the
; head device link to this device.
;
ldy #dib.unitnum
lda [dib_ptr],y
cmp #$0001
beq @jmp_links_done
and #max_p_mask
bne @not_head
;
; Too far to branch to.
;
@jmp_links_done jmp @links_done
;
; This is not the first or boot device,
; nor is it the first or only logical
; device on this physical device. That
; means that it is probably partitioned.
; This means we need to set the head and
; forward links. The following code will
; do this for us.
;
; Get the Device Number for setting as
; a forward link. Also save the unit
; number (less the partition bits) to
; match the other DIBs from this device.
;
@not_head ldy #dib.devnum
lda [dib_ptr],y
sta @current_dev
ldy #dib.unitnum
lda [dib_ptr],y
and #max_p_mask\
--$ffff
sta @our_unit
ldy #dib.slotnum
lda [dib_ptr],y
sta @our_slot
;
; Start pointer out at the default DIB.
;
lda #default_dib
sta <scsi_zp4
lda #^default_dib
sta <scsi_zp4+2
;
; Main Search loop.
;
; Advance pointer to the next DIB. If
; link is = to zero, then exit loop.
;
@links_loop ldy #dib.linkptr+2
lda [scsi_zp4]
tax
ora [scsi_zp4],y
bne @non_zero
jmp @links_done
@non_zero lda [scsi_zp4],y
@advance sta <scsi_zp4+2
stx <scsi_zp4
;
; Check unit number to see if it is the same.
;
ldy #dib.unitnum
lda [scsi_zp4],y
and #max_p_mask\
--$ffff
cmp @our_unit ;Is it ours?
bne @links_loop ;No. Check the next one.
;
; Check Slot number to see if it is the same.
;
ldy #dib.slotnum
lda [scsi_zp4],y
cmp @our_slot ;Is it ours?
bne @links_loop ;No. Check the next one.
;
; They are equal. Is the forward link = zero?
;
ldy #dib.fdvclnk
lda [scsi_zp4],y
; beq @found_end
; cmp @current_dev
bne @links_loop ;No. Check the next one.
;
; Yes. This DIB has no forward device link.
; We will volunteer the users DIB for the Job.
; Set the head Link in the DIB called and the
; forward link in ours.
;
@found_end lda @current_dev
sta [scsi_zp4],y
ldy #dib.headlnk
lda [scsi_zp4],y
beq @stuff_head
;
; Set Head Pointer to scsi_zp4
;
pha
ldy #dib.headptr
lda [scsi_zp4],y
sta [dib_ptr],y
ldy #dib.headptr+2
lda [scsi_zp4],y
sta [dib_ptr],y
pla
bra @do_head
;
; Set head Pointer to the same as
; in scsi_zp4
;
@stuff_head ldy #dib.headptr
lda <scsi_zp4
sta [dib_ptr],y
ldy #dib.headptr+2
lda <scsi_zp4+2
sta [dib_ptr],y
ldy #dib.devnum
lda [scsi_zp4],y
@do_head ldy #dib.headlnk
sta [dib_ptr],y
;
; Also set the Forward Device Ptr.
;
ldy #dib.fdvcptr
lda <dib_ptr
sta [scsi_zp4],y
ldy #dib.fdvcptr+2
lda <dib_ptr+2
sta [scsi_zp4],y
;
; And the forward link.
;
ldy #dib.devnum
lda [dib_ptr],y
ldy #dib.fdvclnk
sta [scsi_zp4],y
;
; Is it a COLD STARTUP?
;
lda >warm_cold_flag
and #$0001
bne @links_done ;It's Warm. Skip the links
;
; Set the linked bit in both DIBs.
;
ldy #dib.dvcchar
lda [scsi_zp4],y
ora #linked_dvc
sta [scsi_zp4],y
lda [dib_ptr],y
ora #linked_dvc
sta [dib_ptr],y
ENDIF
;-------------------------------------------------------------------------------
;
; Not the first one, so increment the counter
; if we are not beyond what we have for an
; active dib count.
;
@links_done lda |active_starts
cmp |tot_dib_cnt
beq @over_inc
inc |active_starts
@over_inc clc
rts
;
; Local Data storage here.
;
@current_dev dc.w null ;Device Number for this DIB
@our_unit dc.w null ;His unit number less the partition bits.
@our_slot dc.w null ;His slot number
;
; Check to see if we've been called before.
; If not then we need to get the gs/os
; direct page address.
;
@im_a_virgin lda |direct_page
bne @we_have_it
;
; Where is GS/OS Direct Page?
;
tdc
sta |gsos_dpage
;
; We also need to get the SCSI Managers
; ID for the S_DISPATCHER.
;
jsr get_scsimgr
bcs @rts
;
; Get ID from the memory manager. All that
; this does is request a new ID.
;
@we_have_it jsr get_mm_id
;
; Call the get_dvc_ram subroutine.
; This will allocate the space
; that we need for the device list
; returned by the SCSI Manager.
; It then calculates a DIB count
; (Max 256) and allocates RAM for
; those structures. This can be
; increased later if it is needed.
; This can occur if some of the
; devices contain more than one
; partition.
;
jsr get_dvc_ram
bcc @do_dflt_dib ;Check for errors.
jsr fre_dvc_ram ;Dump Get Devices Ram
lda #drvr_no_dev ;Exit
sec
@rts rts
;
; Now we need to build the DIBs for
; these devices. The first one will
; not be built in the default_dib
; area. The default_dib will be
; copied first to the new memory that
; has been allocated. It is here
; that the first DIB will be built.
; After this the last DIB built will
; be copied into the space for the
; next DIB to be built and then
; updated accordingly. We do not use
; the default_dib because this will
; serve to keep this driver active
; even if no devices are present at
; boot time. Just in case a drive
; does come online later.
;
@do_dflt_dib lda <dvc_list ;Advance pointer to the first entry.
adc #$0004 ;Pass Direct page pointer and
sta <dvc_list ;device count. Carry was CLEAR!!!!
lda <dvc_list+2
adc #$0000
sta <dvc_list+2
lda #default_dib
sta <last_dib
lda #^default_dib
sta <last_dib+2
stz |main_caller ;tell the link setter that he was called
clc ;Do Links Also
jsr dibicise_new_ram ;by the main loop
bra @over
@over jsr do_mode_parms ;Do MODE SENSE supplied parms
jsr do_inq_parms ;Do INQUIRY supplied parms
;-------------------------------------------------------------------------------
IF block_dvc = true Then
jsr do_read_cap ;Do READ CAPACITY supplied parms
ENDIF
;-------------------------------------------------------------------------------
IF part_suprt = true Then
jsr do_partition ;Do partition DIBs
ENDIF
;-------------------------------------------------------------------------------
jsr get_nxt_dvc ;Go to the next physical device
bne @over ;But only if they exist.
;
; This SEC is extremely important. At
; this point the startup call was issued
; to the default DIB. We took this
; opertunity to build all of our DIBs
; and we have a count of how many we did
; build. We do not want the device manager
; to keep the default DIB as an active
; device and so we exit with the carry
; set. He will then check the link
; pointer and if it is not zero, he will
; call the startup routine for that dib.
; At that time we will exit with the carry
; clear.
;
; Free Get Devices Ram first.
;
jsr fre_dvc_ram
lda #drvr_io
sec
rts
ENDP
EJECT
;*******************************************************
;
; 'do_inq_parms'
;
; This routine issues an INQUIRY call to the device and
; then uses the data returned to fill in some of the blank
; holes in the DIB.
;
; Inputs: <next_dib = Next DIB start (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Outputs: <next_dib = unchanged (LONG)
; [next_dib] = INQUIRY values set (PTR)
; Removable bit
; Command bitmap
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: None.
;
;*******************************************************
EXPORT do_inq_parms
do_inq_parms PROC
;
; Set internal command flag
;
dec |internal
;
; Tell the Main Driver where
; our command structure resides.
;
lda #@start_inq
sta <scsi_mdrvr
lda #^@start_inq
sta <scsi_mdrvr+2
;
; And our buffer
;
lda #internal_buff
sta <buff_ptr
lda #^internal_buff
sta <buff_ptr+2
;
; And our length 0f $40 Bytes
;
lda #$0040
sta <rqst_cnt
stz <rqst_cnt+2
;
; Stuff the pointer to the dib
; that we are building into the
; Direct Page locations. The
; main driver will use this to
; build the SCSI INQUIRY Command
; that we will issue.
;
lda <next_dib
sta <dib_ptr
lda <next_dib+2
sta <dib_ptr+2
;
; Set the Call Type and Issue the
; INQUIRY Command.
;
lda #scsit_stat
sta |call_type
jsr |main_drvr
bcc @over_0 ;Was there an error?
rts ;Yes.
;
; Is the device removable?
;
@over_0 lda |inq.removable\
+internal_buff
and #bit_7
beq @non_remove
;
; Yes. Set the bit in the
; characteristics field.
;
ldy #dib.dvcchar
lda [next_dib],y
ora #removable
sta [next_dib],y
bra @over_1
;
; No. Clear the bit in the
; characteristics field.
;
@non_remove ldy #dib.dvcchar
lda [next_dib],y
and #removable--\
$ffff
sta [next_dib],y
;
; Set a ZP pointer to where the
; command bitmap information will
; be placed.
;
@over_1 clc
lda <next_dib
adc #dib.group0
sta <scsi_zp0
lda <next_dib+2
adc #^dib.group0
sta <scsi_zp0+2
;
; Not all devices conform to the
; Apple Command Command Set. We
; need to check if the Command
; Bitmap is available. If not
; then we will stuff the default
; bitmap and then clear bits as
; the device indicates. This will
; be done elsewhere in response to
; a command not supported error.
;
; First check the return length.
;
ldy #dib.trx_len
lda [dib_ptr],y
cmp #inq.group+5-1 ;End of first group - 1
blt @do_default
;
; We got those bytes. Are they 0?
;
short ;5 Bytes to check. Best done 8 bit
sec ;The Carry will be our flag
lda |inq.group\
+internal_buff
bne @chk_carry ;Must Start w/ Group Zero.
clc ;The Carry will be our flag
ldx #$0005
@chk_bm_loop lda |inq.group\
+internal_buff,x
bne @chk_carry
dex
bpl @chk_bm_loop
sec
@chk_carry longmx
bcs @do_default
;
; There are some devices out there
; that return bogus bitmaps. They
; look correct, but are not. We will
; check the first 4 bytes of the
; Bitmap to see if they support the
; Mandatory Commands. If not, then
; we will use our default bitmap.
;
lda |inq.group\
+internal_buff+1
and @min_cmnds
cmp @min_cmnds
bne @do_default
lda |inq.group\
+internal_buff+3
and @min_cmnds+2
cmp @min_cmnds+2
bne @do_default
;
; Zero out the current data in the
; dib. If there are any holes in
; the information then we are sure
; that those holes are null.
;
ldy #dib.group7\
-dib.group0\
+2
lda #null
@loop_0 sta [scsi_zp0],y
dey
dey
bpl @loop_0
;
; Get the group number for the next
; four bytes of bitmap.
;
; Group x (BYTE)
; Bitmap (LONG)
; Group y (BYTE)
; Bitmap (LONG)
; Group z (BYTE)
; Bitmap (LONG)
; Group '$FF (BYTE)
;
ldx #null
@loop_1 lda |inq.group\
+internal_buff,x
and #$00ff ;Real Code
cmp #$00ff
beq @over_2
cmp #$0007+1
bge @do_default
;
; Convert group number into an
; index into the group table in
; the dib.
;
asl a
asl a
tay
inx
;
; Transfer the bitmap.
;
lda |inq.group\
+internal_buff,x
sta [scsi_zp0],y
inx
inx
iny
iny
lda |inq.group\
+internal_buff,x
sta [scsi_zp0],y
inx
inx
bra @loop_1
;
; The device did not support
; the Command Bitmap in the
; INQUIRY Parms. We need to
; put the default bitmap in
; place.
;
@do_default ldy #dib.group7\
-dib.group0\
+2
@dflt_loop lda default_dib\
+dib.group0,y
sta [scsi_zp0],y
dey
dey
bpl @dflt_loop
;
; Clean exit when done.
;
@over_2 clc
rts
;
; Data Area.
;
; Inquiry Command Packet.
;
@start_inq dc.b $12
dcb.b 11,$00
;
; Data of Minimum Command set that
; must be supported.
;
@min_cmnds
;-------------------------------------------------------------------------------
IF scsi_dtype = direct_acc Then
;
; It is a Direct-Access Device.
;
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = direct_acc
;-------------------------------------------------------------------------------
IF scsi_dtype = seq_acc THEN
;
; It is a Sequential-Access Device.
;
arl ;Cause error if used. Force definition
dc.B $D0,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = seq_acc
;-------------------------------------------------------------------------------
IF scsi_dtype = appl_laser THEN
;
; It is an Apple LaserWriter Device.
;
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = appl_laser
;-------------------------------------------------------------------------------
IF scsi_dtype = proc_dvc THEN
;
; It is a Processor Device.
;
arl ;Cause error if used. Force definition
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = proc_dvc
;-------------------------------------------------------------------------------
IF scsi_dtype = worm_dvc THEN
;
; It is a Write-once Read-multiple Device.
;
arl ;Cause error if used. Force definition
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = worm_dvc
;-------------------------------------------------------------------------------
IF scsi_dtype = read_dacc THEN
;
; It is a Read-only Direct-Access Device.
;
dc.B $90,$00,$23,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = read_dacc
;-------------------------------------------------------------------------------
IF scsi_dtype = scanner THEN
;
; It is a Scanner Device.
;
dc.B $90,$00,$23,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = scanner
;-------------------------------------------------------------------------------
IF scsi_dtype = optic_mem THEN
;
; It is a Optical Memory Device.
;
arl ;Cause error if used. Force definition
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = optic_mem
;-------------------------------------------------------------------------------
IF scsi_dtype = changer THEN
;
; It is a Changer Device.
;
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = changer
;-------------------------------------------------------------------------------
IF scsi_dtype = comm_dvc THEN
;
; It is a Communication Device.
;
arl ;Cause error if used. Force definition
dc.B $98,$A0,$20,$00 ; Group 0 Commands
ENDIF ;scsi_dtype = comm_dvc
;-------------------------------------------------------------------------------
IF scsi_dtype = mcd_40 THEN
;
; It is a Direct Access Magnetic
; Tape Device.
;
dc.B $DF,$77,$FF,$7C ; Group 0 Commands
ENDIF ;scsi_dtype = mcd_40
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; 'do_mode_parms'
;
; This routine issues an MODE SENSE call to the device and
; then uses the data returned to fill in some of the blank
; holes in the DIB.
;
; Inputs: <next_dib = Next DIB start (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Outputs: <next_dib = unchanged (LONG)
; [next_dib] = MODE SENSE vals set (PTR)
; Write Protect bit
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: None.
;
;*******************************************************
EXPORT do_mode_parms
do_mode_parms PROC
;
; Stuff the pointer to the dib
; that we are building into the
; Direct Page locations. The
; main driver will use this to
; build the SCSI MODE SENSE
; Command that we will issue.
;
lda <next_dib
sta <dib_ptr
lda <next_dib+2
sta <dib_ptr+2
;
; Start the Unit
;
;-------------------------------------------------------------------------------
IF scsi_dtype <> scanner THEN
jsr start_unit
ENDIF
;-------------------------------------------------------------------------------
IF scsi_dtype = mcd_40\
OR scsi_dtype = apple_cd\
OR scsi_dtype = changer THEN
;
; Check for no-media
;
bcc @cd_tape_ok
;
; Check for No Media Error
;
lda |auto_sense_data+\
rqst_sens.sense_key
beq @cd_tape_ok
and #$00ff
cmp #$0002 ;Is there Media?
bne @cd_tape_ok ;Yes.
;
; No Media. Mark the DIB Hard Ofline also.
;
ldy #dib.dvcflag
lda [dib_ptr],y
ora #dvc_hardofl
sta [dib_ptr],y
@cd_tape_ok
ENDIF
;-------------------------------------------------------------------------------
;
; Check if unit Ready
;
jsr test_unit_rdy
;
; Issue MODE SENSE Call
;
jsr mode_sense
bcs @rts ;Was there an error?
;-------------------------------------------------------------------------------
IF scsi_dtype <> apple_cd\
AND scsi_dtype <> changer\
AND scsi_dtype <> scanner THEN
;
; Is the device writable? If CD-ROM
; then don't even bother with this
; code.
;
lda |mode.w_protect\
+internal_buff
and #bit_7
beq @over_1 ;No.
;
; Yes. Set the bit in the
; characteristics field.
;
ldy #dib.dvcchar
lda #write_allow
ora [next_dib],y
sta [next_dib],y
ENDIF
;-------------------------------------------------------------------------------
@over_1 ;Label must always be available.
;-------------------------------------------------------------------------------
IF scsi_dtype <> mcd_40\
AND scsi_dtype <> scanner\
AND scsi_dtype <> appl_laser THEN
;
; Check to see if the device supports
; the page discriptors.
;
lda |mode.blk_disc\
+internal_buff
and #$00ff
beq @clc
;
; Ensure that the device is in
; 512 mode if possible and send
; data from page 1 back to the
; device.
;
lda |mode.page_number\
+internal_buff
and #$ff3f ;Clear the invalid bits.
sta |select_page_num
lda |mode.page_number\
+internal_buff+2
ora #bit_6++\ ;Set AWRE and ARRE bits.
bit_7
sta |select_page_num+2
lda |mode.page_number\
+internal_buff+4
sta |select_page_num+4
lda |mode.page_number\
+internal_buff+6
sta |select_page_num+6
jsr set_512_mode
bcs @rts
@clc
ENDIF
;-------------------------------------------------------------------------------
;
; Exit
;
clc
@rts rts
;
; Data for the MODE SENSE Command
;
@start_mode dc.b $1a
dc.b $00
dc.b $01
dcb.b 9,$00
ENDP
EJECT
;*******************************************************
;
; 'do_read_cap'
;
; This routine issues an READ CAPACITY call to the
; device and then uses the data returned to fill in
; some of the blank holes in the DIB.
;
; Inputs: <next_dib = Next DIB start (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Outputs: <next_dib = unchanged (LONG)
; [next_dib] = READ CAP.. vals set (PTR)
; Block Count
; Block Size
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: None.
;
;*******************************************************
EXPORT do_read_cap
do_read_cap PROC
;-------------------------------------------------------------------------------
IF scsi_dtype <> scanner THEN
;
; Stuff the pointer to the dib
; that we are building into the
; Direct Page locations. The
; main driver will use this to
; build the SCSI READ CAPACITY
; Command that we will issue.
;
lda <next_dib
sta <dib_ptr
lda <next_dib+2
sta <dib_ptr+2
;
; Issue the READ CAPACITY Command.
;
jsr read_capacity
bcc @over_0 ;Was there an error?
rts ;Yes.
;
; 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.
;
@over_0 lda |block.count\
+internal_buff\
+2
xba
adc #$0001
sta |t_dvc_blocks
lda |block.count\
+internal_buff
xba
adc #null
sta |t_dvc_blocks+2
;-------------------------------------------------------------------------------
IF block_dvc = true THEN
beq @over_mo
;
; Some devices do not return a bitmap
; of the commands that they support.
; For these devices we use a default
; minimum command set. If the Block
; Count is > $ffff, then we need to
; update this to support the exrended
; read and write commands.
;
ldy #dib.group1
lda [next_dib],y
ora #$b000 ;Bit 15 = Extended Read
;Bit 13 = Extended Write
;Bit 12 = Extended Seek
sta [next_dib],y
@over_mo
ENDIF
;-------------------------------------------------------------------------------
;
; Get the devices block size (This
; also needs to be switched from
; High >> Low to Low >> High) and
; place it in the dib.
;
lda |block.size\
+internal_buff\
+2
xba
ldy #dib.blksize
sta [next_dib],y
sta <blk_size ;Place on direct page.
lda |block.size\
+internal_buff
xba
ldy #dib.blksize+2
sta [next_dib],y
sta <blk_size+2 ;Place on direct page.
;
; Clean exit.
;
clc
rts
ELSE
;-------------------------------------------------------------------------------
clc
rts
ENDIF
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; 'do_partition'
;
; This routine issues a READ call to the device and
; then uses the data returned to check for any
; partitions on the media.
;
; Inputs: <next_dib = Next DIB start (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Outputs: <next_dib = 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
;
; Errors: None.
;
;*******************************************************
;
; Start of the code segment for this.
;
EXPORT do_partition
do_partition PROC
;-------------------------------------------------------------------------------
IF part_suprt = true Then
;
; Initialize a few values.
;
lda #$ffff ;The following values will be incrimented
sta |first_time ;with zero indication special action.
sta |part_num ;This is set to $ffff so that it will only
;occur on the first pass through.
stz |part_cnt
stz |rpm_blk_num
stz |rebuild
;
; MAIN LOOP OF CODE SEGMENT.
;
jsr do_part_dib
rts
ELSE
;-------------------------------------------------------------------------------
clc
rts
ENDIF
;-------------------------------------------------------------------------------
ENDP
EJECT
;*******************************************************
;
; 'get_nxt_dvc'
;
; This routine checks to see if there are any
; remaining devices in the list handed to us by the
; GET_DEVICES Call to the SCSI Manager. If there are
; devices, then we advance our pointers and exit with
; the Z flag set. The caller can the do a BNE to
; continue his loop ( Z(ero) indicates that there are
; no devices left ).
;
; Inputs: <next_dib = Next DIB start (LONG)
; Acc = Unspecified
; Carry = Unspecified
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Direct Page = Ours
; Data Bank = Ours
;
; Outputs: <next_dib = last DIB Built (LONG)
; Carry = 1
; Acc = Error
; Carry = 0
; Acc = ram_page_cnt
; = 0 no more devices
; Y register = Unspecified
; X register = Unspecified
; P register = 0=M=X=e
; Z=1 if more devices
; Z=0 if no more devices
; Direct Page = Ours
; Data Bank = Ours
;
; Errors: None.
;
;*******************************************************
EXPORT get_nxt_dvc
get_nxt_dvc PROC
;
; Are there any more devices?
;
dec |dvc_count
bne @we_have_more
clc
rts ;Z Flag set here.
;
; Advance the Device Data Pointer
; in the device list from the SCSI
; Manager
;
@we_have_more clc
lda <dvc_list
adc #$0004
sta <dvc_list
lda <dvc_list+2
adc #null
sta <dvc_list+2
;
; Call Check Ram routine. This will
; check to see if there is room for an
; additional DIB. If not then room
; will be made for enough DIBs to cover
; the remaining partitions and devices.
; From this caller, there should be no
; partitions to account for.
;
stz |main_caller
jmp chk_ram
ENDP
END
EJECT