
;*******************************************************
;
;	SCSI Driver Get Configuration Parms code.
;
;	Written by Matt Gulick.		Started June 22,1990
;
;	Copyright Apple Computer, Inc. 1990
;
;*******************************************************

;*******************************************************
;
;	This file contains the Get Configuration Parms as
;	defined in the ERS.
;
;*******************************************************

;*******************************************************
;
;	Revision History:
;
;*******************************************************

;	June 22,	1988	File started.

				IMPORT		chk_count
				IMPORT		bitmap
				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

				EJECT
			
;*******************************************************
;
;	'g_config_parms'
;
;	This routine is used to get information about the
;	volume or disk in question.  If this call is issued
;	to get disk info, then the DIB Pointer must point to
;	the head DIB if this is a linked device.  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.
;
;*******************************************************

gcp
											;
											; 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		#$0004
				blt		@bad_cnt
											;
											; Do a mini check of the parameter list
											; to see if it is correct.
											;
@rqst_cnt_ok	lda		[buff_ptr]			;Is the Request Count = 0?
				beq		@exit_none			;Yes.  Get Zero

				cmp		#$0002				;Is the count bigger than the min
				blt		@exit_parm			;Overhead Structure? No?  Parm Error.
											;
											; 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
				beq		@exit_parm
											;
											; Check Bitmap.
											;
				ldy		#config_pl.bitmap
				lda		[buff_ptr],y
				bmi		@do_volume
				brl		do_disk
											;
											; 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
											;
											; Do the Volume Parms Here.
											; Acc = Bitmap on entry.
											;
@do_volume		cmp		#$8000				;All other bits must be zero or
				bne		@exit_parm			;we have a parm error.
				sta		|bitmap
											;
											; Get block that contains this
											; DIB's Partition Map Entry.
											;
				ldy		#dib.part_blk
				lda		[dib_ptr],y
				sta		|rpm_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.
				jsr		set_our_dp
											;
											; Is what we read a Partition Map?
											;
				lda		|pm.Sig\
						+internal_buff
				cmp		#Part_sig
				bne		@bad_exit			;Bad Data Read.
											;
											; GTet the Status Byte
											;
				ldy		#config_pl.bitmap
				lda		|pm.PartStatus+2\
						+internal_buff
				xba
				and		#$00ff
				ora		|bitmap
				sta		[buff_ptr],y
											;
											; Clean Exit
											;
				lda		#$0004
				sta		<trans_cnt
				lda		#no_error
				sta		<trans_cnt+2
				clc
				rts
											;
											; Get Config Disk Calls are handled
											; here.
											;
											; Init Transfer Count to Null.  Then
											; check to be sure that this is a get
											; Config ParmList and not a Set Config
											; List.
											;
do_disk			stz		length
				stz		length+2
											;
											; Get the Request Count.We will set this
											; aside and subtract from that as data
											; is transfered.  This way we will not
											; over run their buffers.
											;
				ldy		<rqst_cnt
				sty		rqst
				ldy		<rqst_cnt+2
				sty		rqst+2

				sta		temp
				and		#$4000
				bne		@exit_parm
											;
											; Check Count. Must have a count that
											; is at least big enough to cover the
											; count and bitmap fields plus the first
											; DDM_Info field.  If not then there is
											; an error.
											;
				ldy		#config_pl.count
				sec
				lda		[buff_ptr],y
				sbc		#config_pl.vol_info\
						-config_pl.count
				sta		count
				blt		@exit_parm
											;
											; Put the first flag bit in Bit 15.
											;%00xxx00000000000
				asl		temp				;%0xxx000000000000
				asl		temp				;%xxx0000000000000
											;
											; Preserve the Users Buffer Pointer.
											;
				lda		<buff_ptr
				sta		gc_buff_ptr
				lda		<buff_ptr+2
				sta		gc_buff_ptr+2
											;
											; Pre_load the DDM if needed.
											;
				jsr		pre_load_ddm
				bcc		@ddm_loaded
				rts
											;
											; Use this code to exit when no data is
											; being returned.
											;
@exit_parm		lda		#drvr_bad_parm
				sec
				rts
											;
											; Check Set DDM Bit
											;
@ddm_loaded		asl		temp
				bcc		@chk_vol
				jsr		get_ddm
				bcs		@disk_done
											;
											; Check Get Volume Info Bit
											;
@chk_vol		jsr		|chk_count
				bcs		@disk_done
				asl		temp
				bcc		@chk_drvr
				jsr		get_vol
				bcs		@disk_done
											;
											; Check Get Driver Bit
											;
@chk_drvr		jsr		|chk_count
				bcs		@disk_done
				asl		temp
				bcc		@disk_done
				jsr		get_drvr
											;
											; All done.  Return the transfer
											; length and any error codes that
											; were encountered
											;
@disk_done		sta		error
				lda		length
				sta		<trans_cnt
				lda		length+2
				sta		<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 Read
											; the DDM into the callers buffer.
											;
get_ddm
											;
											; Tell the Main Driver where
											; our command structure resides.
											;
				lda		#@read_ddm
				sta		<scsi_mdrvr
				lda		#^@read_ddm
				sta		<scsi_mdrvr+2
											;
											; Set the user's buffer
											;
				ldy		#config_pl.ddm_info
				clc

				lda		[buff_ptr],y
				sta		<config_tcnt
				adc		#$0004
				tax

				ldy		#config_pl.ddm_info+2

				lda		[buff_ptr],y
				sta		<config_tcnt+2
				adc		#$0000
				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
											;
											; And our length from the DIB's
											; Block Size value
											;
				lda		[config_tcnt]
				cmp		#block_size+4
				beq		@over_0

@over_0			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_stat
				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
											;
											; Is what we read a Driver
											; Descriptor Map?
											;
				lda		[ddm_buff]
				cmp		#DDM_sig
				bne		@bad_exit1			;Bad Data Read.
											;
											; Add in the Length
											;
				clc
				lda		#block_size
				ldy		#$0002
				sta		[config_tcnt],y

				adc		length
				sta		length

				lda		length+2
				adc		#^block_size
				sta		length+2
											;
											; Clean Exit.
											;
				lda		#$0000
				clc
				rts
											;
											; Error exit point.
											;
@bad_exit1		jsr		set_our_dp
				lda		#drvr_io
				sec
				rts
											;
											; Data for the READ BLOCK Command
											;
@read_ddm		dc.b		$08
				dc.b		null
				dc.w		null
				dcb.b		10,null
											;
											; This Routine is used to get the
											; Volume Info into the callers buffer.
											;
get_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
											;
											; Set the user's buffer
											;
				ldy		#config_pl.vol_info
				clc

				lda		[buff_ptr],y
				sta		<config_tcnt
				adc		#$0004
				tax

				ldy		#config_pl.vol_info+2

				lda		[buff_ptr],y
				sta		<config_tcnt+2
				adc		#$0000
				sta		<buff_ptr+2
				sta		<config_buff+2
				tay
				stx		<buff_ptr
				stx		<config_buff
											;
											; And our length from the DIB's
											; Block Size value
											;
				lda		[config_tcnt]
				cmp		#block_size+4
				beq		@over_0
											;
											; Use this code to exit when no data is
											; being sent.
											;
@exit_parm1		lda		#drvr_bad_parm
				sec
				rts

@over_0			lda		#$0001				;Start looking here.
				jsr		find_drvr_part
				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
											;
											; Is what we read a Driver
											; Descriptor Map?
											;
				lda		[config_buff]
				cmp		#Part_sig
				bne		@bad_exit1			;Bad Data Read.
											;
											; Add in the Length
											;
				clc
				lda		#block_size
				ldy		#$0002
				sta		[config_tcnt],y

				adc		length
				sta		length

				lda		length+2
				adc		#^block_size
				sta		length+2
											;
											; Clean Exit.
											;
				lda		#$0000
				clc
@rts			rts
											;
											; Error exit point.
											;
@bad_exit1		jsr		set_our_dp
				lda		#drvr_io
				sec
				rts
											;
											; Data for the READ BLOCK Command
											;
@read_vol		dc.b		$08
				dc.b		null
@read_vol_num	dc.w		null
				dcb.b		10,null
											;
											; This Routine is used to get the
											; Driver Data into the callers buffer.
											;
get_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		#$0008				;OR in the command number
				sta		@read_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		#config_pl.driver_info
				clc

				lda		[buff_ptr],y
				sta		<config_tcnt
				adc		#$0004
				tax

				ldy		#config_pl.driver_info+2

				lda		[buff_ptr],y
				sta		<config_tcnt+2
				adc		#$0000
				sta		<buff_ptr+2
				sta		<config_buff+2
				stx		<buff_ptr
				stx		<config_buff
											;
											; And our length from the DIB's
											; Block Size value
											;
				lda		<rqst_cnt+2
				bne		@too_big
				lda		[config_tcnt]
				cmp		<rqst_cnt
				bge		@length_ok

@too_big		sec
				stz		<rqst_cnt+2
				lda		[config_tcnt]
				sbc		#$0004
				sta		<rqst_cnt
											;
											; Tell the Main Driver where
											; our command structure resides.
											;
@length_ok		lda		#@read_drvr
				sta		<scsi_mdrvr
				lda		#^@read_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
											; READ BLOCK Command.
											;
				lda		#scsit_stat
				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
											;
				clc
				lda		<rqst_cnt
				ldy		#$0002
				sta		[config_tcnt],y

				adc		length
				sta		length

				lda		length+2
				adc		<rqst_cnt+2
				sta		length+2
											;
											; Clean Exit.
											;
				lda		#$0000
				rts
											;
											; Error exit point.
											;
@bad_exit1		jsr		set_our_dp
				lda		#drvr_io
				sec
				rts
											;
											; Data for the READ BLOCK Command
											;
@temp			dc.w		null
											;
											; Command to Read the Driver Data
											;
@read_drvr		dc.b		$08
				dc.b		null
@block_num		dc.w		null
				dcb.b		10,null

				EJECT



