mirror of
https://github.com/antoinevignau/source.git
synced 2024-11-04 18:05:25 +00:00
d29484938c
What we wrote to make audio hearable on a SCSI-2 CD-ROM drive ;-)
1 line
26 KiB
Plaintext
1 line
26 KiB
Plaintext
|
||
;*******************************************************
|
||
;
|
||
; SCSI Driver 'Main Driver'.
|
||
;
|
||
; Written by Matt Gulick. Started May 25,1988
|
||
;
|
||
; Copyright Apple Computer, Inc. 1988,89
|
||
;
|
||
;*******************************************************
|
||
|
||
;*******************************************************
|
||
;
|
||
; This file contains the 'Main Driver' as defined in
|
||
; the ERS.
|
||
;
|
||
;*******************************************************
|
||
|
||
;*******************************************************
|
||
;
|
||
; Revision History:
|
||
;
|
||
;*******************************************************
|
||
|
||
; May 25, 1988 File started.
|
||
; June 6, 1988 Turned sections into subroutines
|
||
; and wrote the Main Driver Proper.
|
||
; June 20, 1988 Added Register Input and Output.
|
||
; Also included the changes from
|
||
; the code review.
|
||
; Oct 25, 1988 Made changes in code to reflect the
|
||
; redesign of the SCSI Manager interface.
|
||
;
|
||
|
||
STRING PASCAL
|
||
BLANKS OFF
|
||
PAGESIZE 70
|
||
PRINT NOGEN
|
||
PRINT NOMDIR
|
||
MACHINE M65816
|
||
|
||
IMPORT cmd_t_tbl
|
||
IMPORT call_type
|
||
IMPORT scratch0
|
||
IMPORT cmd_ps_tbl
|
||
IMPORT c_len_len
|
||
IMPORT c_blk_len
|
||
IMPORT divide
|
||
IMPORT result
|
||
IMPORT divend
|
||
IMPORT divsor
|
||
IMPORT time_cnt
|
||
IMPORT rout2_s_disp
|
||
IMPORT gsos_dpage
|
||
IMPORT f_partition
|
||
IMPORT internal
|
||
IMPORT disk_switch
|
||
IMPORT scsi_mgrnum
|
||
IMPORT manager_cmd
|
||
IMPORT cur_cmd
|
||
IMPORT cur_cmd2
|
||
IMPORT cur_group
|
||
IMPORT trans_dest
|
||
IMPORT p_block_num
|
||
IMPORT killer_blk
|
||
IMPORT trans_flag
|
||
IMPORT temp_x
|
||
IMPORT temp_y
|
||
IMPORT timeout_flag
|
||
IMPORT auto_sense_data
|
||
IMPORT lst_rslt_ec
|
||
IMPORT lst_rslt_stat
|
||
IMPORT lst_rslt_skey
|
||
IMPORT lst_rslt_info
|
||
IMPORT lst_rslt_rqlen
|
||
IMPORT lst_rslt_scode
|
||
|
||
PRINT OFF
|
||
|
||
INCLUDE 'scsihd.equates'
|
||
INCLUDE 'M16.MEMORY'
|
||
INCLUDE 'M16.UTIL'
|
||
|
||
PRINT ON
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Main Entry point to the 'Main Driver'.
|
||
;
|
||
; The function of this code is to take the callers
|
||
; command data and build a SCSI Command Packet. This
|
||
; is done using the conversion tables in the file
|
||
; 'SCSI Command Table'. The command and other data
|
||
; is actually built in the space that has been added
|
||
; to the DIB and then routed to the SCSI Manager.
|
||
;
|
||
; The routine is called with the LONG pointer to the
|
||
; callers command data in the Direct Page location
|
||
; 'scsi_mdrvr'. This, in conjunction with the DIB Ptr
|
||
; at direct page location 'dib_ptr' as the address
|
||
; for the template overlay, will be used to do the
|
||
; following:
|
||
;
|
||
; Transfer the callers command data to the command
|
||
; packet.
|
||
; Zero all 12 bytes first.
|
||
; Validate Internal Command flag if set.
|
||
; .OR. in all values durring translation.
|
||
; Adjust Transfer length if needed.
|
||
; Convert Block Number from Logical to Actual
|
||
; If partition Flag is <20> zero then leave
|
||
; block number unmodified.
|
||
; Check for command errors.
|
||
;
|
||
; Stuff SCSI Manager Flags
|
||
;
|
||
; Stuff data in the TRX buffer data structure
|
||
;
|
||
; Ship the call out to the SCSI Manager.
|
||
;
|
||
; Clear Partition Call Flag.
|
||
;
|
||
; Clear the Internal Command Flag.
|
||
;
|
||
; Translate any SCSI errors into GS/OS errors.
|
||
;
|
||
; Inputs: Acc = Unspecified
|
||
; Y register = Unspecified
|
||
; X register = Unspecified
|
||
; P register = 0=M=X=e
|
||
; Direct Page = Ours
|
||
; Data Bank = Ours
|
||
;
|
||
; Outputs: Acc = Unspecified
|
||
; Y register = Unspecified
|
||
; X register = Unspecified
|
||
; P register = 0=M=X=e
|
||
; Direct Page = Ours
|
||
; Data Bank = Ours
|
||
;
|
||
; Errors: Carry set if Error.
|
||
;
|
||
;*******************************************************
|
||
|
||
EXPORT main_drvr
|
||
main_drvr PROC
|
||
;
|
||
; Clear the Timeout flag
|
||
;
|
||
stz |timeout_flag
|
||
;
|
||
; Clear the last error stuff
|
||
;
|
||
stz |lst_rslt_ec
|
||
stz |lst_rslt_stat
|
||
stz |lst_rslt_skey
|
||
stz |lst_rslt_info
|
||
stz |lst_rslt_rqlen
|
||
stz |lst_rslt_scode
|
||
;
|
||
; Clear the Command Buffer
|
||
;
|
||
ldx #max_cmd_len*2\
|
||
-2
|
||
ldy #max_cmd_len*2\
|
||
+dib.scsicmd\
|
||
-2
|
||
lda #$0000
|
||
@loop sta [dib_ptr],y
|
||
dey
|
||
dey
|
||
dex
|
||
dex
|
||
bpl @loop
|
||
;
|
||
; Get the Curren CoMmanD and GRouP
|
||
;
|
||
lda [scsi_mdrvr]
|
||
and #$0fff
|
||
sta |cur_cmd2 ;Preserve Current Command Number
|
||
and #$00ff
|
||
sta |cur_cmd ;Preserve Current Command Number
|
||
pha
|
||
;
|
||
; Get Offsets to Validate Command
|
||
; Support by the device.
|
||
;
|
||
tax
|
||
and #bit_4\
|
||
+bit_5\
|
||
+bit_6\
|
||
+bit_7
|
||
lsr a
|
||
lsr a
|
||
lsr a
|
||
tay
|
||
lda |bm_cmd_offset,y
|
||
tay
|
||
txa
|
||
and #bit_0\
|
||
+bit_1\
|
||
+bit_2\
|
||
+bit_3
|
||
asl a
|
||
tax
|
||
lda [dib_ptr],y
|
||
and |bm_cmd_mask,x
|
||
bne @cmd_support
|
||
;
|
||
; Command Not Supported
|
||
; by this device.
|
||
;
|
||
pla ;Fix Stack
|
||
lda #drvr_bad_code
|
||
sec
|
||
@exit rts
|
||
;
|
||
; Get the SCSI Group Number.
|
||
;
|
||
@cmd_support pla
|
||
and #bit_5\
|
||
+bit_6\
|
||
+bit_7
|
||
lsr a
|
||
lsr a
|
||
lsr a
|
||
lsr a
|
||
lsr a
|
||
sta |cur_group
|
||
;
|
||
; Set TRANSlation PoiNTer
|
||
;
|
||
jsr s_trans_ptr
|
||
bcs @exit
|
||
;
|
||
; VALidate the CoMmanD TYPe
|
||
;
|
||
jsr val_cmd_typ
|
||
bcs @exit ;Bad Command
|
||
;
|
||
; Set 'scsi_zp4' to scsi Command
|
||
; in DIB
|
||
;
|
||
clc
|
||
lda <dib_ptr
|
||
adc #dib.scsicmd
|
||
sta <scsi_zp4
|
||
lda <dib_ptr+2
|
||
adc #$0000
|
||
sta <scsi_zp4+2
|
||
;
|
||
; TRANSLATE user's command data
|
||
; into SCSI Command Packet
|
||
;
|
||
jsr translate
|
||
;
|
||
; FINALIZE the SCSI Command Packet.
|
||
; This includes updating the
|
||
; requested block number to account
|
||
; for partitioning, and the request
|
||
; length from bytes to blocks.
|
||
;
|
||
jsr finalize
|
||
bcs @exit
|
||
bvs @no_data
|
||
;
|
||
; Stuff SCSI Manager flags.
|
||
;
|
||
jsr stuff_flag
|
||
;
|
||
; Build the Transmit/Receive
|
||
; structure.
|
||
;
|
||
lda #scsi_io_call ;set SCSI Manager Command to
|
||
sta |manager_cmd ;I/O Call.
|
||
|
||
ldy #dib.trx_buff ;Stuff the Buffer Pointer
|
||
lda <buff_ptr
|
||
sta [dib_ptr],y
|
||
|
||
ldy #dib.trx_buff+2
|
||
lda <buff_ptr+2
|
||
sta [dib_ptr],y
|
||
;
|
||
; Stuff the request count in both the
|
||
; Total length and in the DCMove command.
|
||
;
|
||
lda <rqst_cnt
|
||
|
||
ldy #dib.trx_length ;Stuff the DCMove transfer count
|
||
sta [dib_ptr],y
|
||
|
||
ldy #dib.trx_rqst ;Stuff the Requested transfer count
|
||
sta [dib_ptr],y
|
||
|
||
lda <rqst_cnt+2
|
||
|
||
ldy #dib.trx_length+2
|
||
sta [dib_ptr],y
|
||
|
||
ldy #dib.trx_rqst+2
|
||
sta [dib_ptr],y
|
||
;
|
||
; Mark auto sense buffer as trashed.
|
||
;
|
||
lda #$ffff
|
||
sta |auto_sense_data
|
||
sta |auto_sense_data+2
|
||
;
|
||
; Send command to the SCSI Manager
|
||
;
|
||
jsr issue_cmd
|
||
;
|
||
; Place Info in for Get Last Result
|
||
; Status Call.
|
||
;
|
||
php
|
||
pha
|
||
|
||
sta |lst_rslt_stat
|
||
;
|
||
; Did we get auto sense data?
|
||
;
|
||
lda |auto_sense_data
|
||
and |auto_sense_data+2
|
||
cmp #$ffff
|
||
beq @no_sense ;No.
|
||
;
|
||
; Yes we did. Setup last result
|
||
; info incase it is needed.
|
||
;
|
||
lda |auto_sense_data+\
|
||
rqst_sens.sense_key
|
||
and #$00ff
|
||
sta |lst_rslt_skey
|
||
|
||
lda |auto_sense_data+\
|
||
rqst_sens.info_bytes
|
||
sta |lst_rslt_info
|
||
lda |auto_sense_data+\
|
||
rqst_sens.info_bytes+2
|
||
sta |lst_rslt_info+2
|
||
|
||
clc
|
||
lda |auto_sense_data+\
|
||
rqst_sens.addnl_sens_len
|
||
and #$00ff
|
||
adc #$0008
|
||
sta |lst_rslt_rqlen
|
||
|
||
lda |auto_sense_data+\
|
||
rqst_sens.addnl_sens_code
|
||
and #$00ff
|
||
sta |lst_rslt_scode
|
||
;
|
||
; Restore Acc. Carry and Stack.
|
||
;
|
||
@no_sense pla
|
||
plp
|
||
;
|
||
; Clear partiton call and internal
|
||
; command flags.
|
||
;
|
||
@no_data stz |f_partition
|
||
stz |internal
|
||
;
|
||
; return to Driver front end.
|
||
;
|
||
rts
|
||
|
||
;*******************************************************
|
||
;
|
||
; Transfer the callers command data to the command
|
||
; packet.
|
||
;
|
||
;*******************************************************
|
||
|
||
;*******************************************************
|
||
;*******************************************************
|
||
;
|
||
; Subroutines from the Main Driver.
|
||
;
|
||
;*******************************************************
|
||
;*******************************************************
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Point to Command Translation Table
|
||
; 'trans_flag' = Translation Flags
|
||
; 'scsi_zp2' = Translation Data.
|
||
;
|
||
;*******************************************************
|
||
|
||
|
||
s_trans_ptr lda #cmd_t_tbl
|
||
sta <scsi_zp2
|
||
;
|
||
; Find Command Translation Table for conversion
|
||
;
|
||
@find_cmd lda (scsi_zp2)
|
||
bmi @chk_end
|
||
cmp |cur_cmd ;Check for 8 bits of 16 match
|
||
beq @got_r_cmd
|
||
cmp |cur_cmd2 ;Check for 12 bits of 16 match
|
||
beq @got_r_cmd
|
||
;
|
||
; Goto next entry.
|
||
;
|
||
clc
|
||
lda <scsi_zp2
|
||
adc #$0004
|
||
sta <scsi_zp2
|
||
bra @find_cmd
|
||
;
|
||
; Is it really the end of the table?
|
||
;
|
||
@chk_end cmp #$ffff
|
||
beq @no_cmd_fnd
|
||
;
|
||
; The Command was not found.
|
||
; Return a Bad Command error
|
||
;
|
||
@no_cmd_fnd lda #drvr_bad_code
|
||
sec
|
||
rts
|
||
;
|
||
; We found our command. Now
|
||
; point to the translation data.
|
||
;
|
||
@got_r_cmd ldy #$0002
|
||
lda (scsi_zp2),y
|
||
sta <scsi_zp2
|
||
;
|
||
; Now get the Translation Flags.
|
||
;
|
||
lda (scsi_zp2)
|
||
sta |trans_flag
|
||
;
|
||
; Set Timeout Factor.
|
||
;
|
||
@check_timer and #scsic_tout
|
||
beq @not_by_block
|
||
|
||
dec |timeout_flag
|
||
|
||
@not_by_block ldy #$0002
|
||
lda (scsi_zp2),y
|
||
ldy #dib.time_out
|
||
sta [dib_ptr],y
|
||
;
|
||
; Advance pointer to translation data
|
||
;
|
||
clc
|
||
lda <scsi_zp2
|
||
adc #$0004 ;Setup Pointer to translation data
|
||
sta <scsi_zp2
|
||
rts
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Check to see if this is an internal command. If it
|
||
; is, then the high of 'internal' must be set.
|
||
;
|
||
; Validate that this command is a Staus Command if we
|
||
; were called with a Status type call. Or is it a
|
||
; Control call with a Control Command?
|
||
;
|
||
;*******************************************************
|
||
|
||
|
||
val_cmd_typ stz |disk_switch ;Ensure that this flag is clear.
|
||
|
||
lda |trans_flag
|
||
tay
|
||
and #scsic_int
|
||
beq @non_int ;If = then Internal Command flag = 0
|
||
bit |internal ;non-0. Is it an internal command?
|
||
bpl @no_cmd_fnd
|
||
;
|
||
; Is the command a Status if entry
|
||
; was via status, or is it a Control
|
||
; vial control entry. If neither
|
||
; then error out.
|
||
;
|
||
@non_int tya
|
||
and |call_type
|
||
beq @no_cmd_fnd ;No match. Error.
|
||
;
|
||
; Must this command be issued to the
|
||
; first DIB of a linked device?
|
||
;
|
||
tya
|
||
and #scsic_1st
|
||
beq @chk_dsksw
|
||
;
|
||
; Check Headlink Pointer.
|
||
;
|
||
phy
|
||
ldy #dib.headlnk
|
||
lda [dib_ptr],y
|
||
beq @ply
|
||
ldy #dib.devnum
|
||
cmp [dib_ptr],y
|
||
beq @ply
|
||
;
|
||
; The Command was invalid.
|
||
; Return a Bad Command error
|
||
;
|
||
ply ;Restore the stack.
|
||
@bad_dev_num lda #bad_dev_number
|
||
sec
|
||
rts
|
||
;
|
||
; Check to see if we need to do a
|
||
; DISK SWITCH after this command.
|
||
;
|
||
@ply ply
|
||
|
||
@chk_dsksw tya
|
||
and #scsic_dsw
|
||
beq @clc
|
||
|
||
dec disk_switch
|
||
|
||
@clc clc
|
||
rts
|
||
;
|
||
; The Command was invalid.
|
||
; Return a Bad Command error
|
||
;
|
||
@no_cmd_fnd lda #drvr_bad_code
|
||
sec
|
||
@rts rts
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Is it an ASIS Command, or does it need to be
|
||
; translated? What ever the case, when this command
|
||
; returns, the command data will be in it's place
|
||
; ready for the length and block fields to be updated
|
||
; in needed.
|
||
;
|
||
;*******************************************************
|
||
|
||
|
||
translate lda |trans_flag
|
||
and #scsid_asis
|
||
beq @translate
|
||
;
|
||
; Yes. It is as is. Move the Command
|
||
; bytes over.
|
||
;
|
||
ldy #max_cmd_len-2
|
||
@move_cmd lda [scsi_mdrvr],y
|
||
sta [scsi_zp4],y
|
||
dey
|
||
dey
|
||
bpl @move_cmd
|
||
@rts rts ;Return to caller.
|
||
;
|
||
;
|
||
; We have gotten to this piece of code
|
||
; because the user data is not in the
|
||
; form accepted by the SCSI Target.
|
||
; We need to translate the data using
|
||
; the translation data pointed to by
|
||
; the direct page value 'scsi_zp2' It
|
||
; is extremely important that we .OR.
|
||
; in all values during translation.
|
||
;
|
||
@translate lda #null ;Always do the Command Byte
|
||
bra @over
|
||
|
||
@loop lda (scsi_zp2) ;Get translation Data.
|
||
beq @rts ;we are at the end if value = $0000
|
||
;
|
||
; Place High Byte in Source Offset and
|
||
; the Low Byte in Destination Offset.
|
||
;
|
||
@over tay
|
||
and #bit_0\
|
||
+bit_1\
|
||
+bit_2\
|
||
+bit_3
|
||
sta |trans_dest
|
||
tya
|
||
xba ;Move High Byte to Low Byte
|
||
and #bit_0\
|
||
+bit_1\
|
||
+bit_2\
|
||
+bit_3
|
||
tay
|
||
;
|
||
; Move Command Data.
|
||
;
|
||
shortm ;We only want the byte from this
|
||
lda [scsi_mdrvr],y
|
||
ldy |trans_dest ;offset.
|
||
ora [scsi_zp4],y
|
||
sta [scsi_zp4],y
|
||
longm
|
||
;
|
||
; Point to next Translation Byte
|
||
;
|
||
clc
|
||
lda <scsi_zp2
|
||
adc #$0002
|
||
sta <scsi_zp2
|
||
bra @loop
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; The command Packet is now built except for some
|
||
; minor cosmetic work.
|
||
;
|
||
;*******************************************************
|
||
;
|
||
; Stuff the SCSI Device ID (Our unit
|
||
; number) and our Slot Number into the
|
||
; commad area for the SCSI Manager.
|
||
;
|
||
finalize
|
||
ldy #dib.slotnum ;***** Temp Change *****
|
||
lda [dib_ptr],y ;***** Temp Change *****
|
||
ldy #dib.scsi_slot ;***** Temp Change *****
|
||
sta [dib_ptr],y ;***** Temp Change *****
|
||
|
||
ldy #dib.unitnum
|
||
lda [dib_ptr],y
|
||
and #max_p_mask\
|
||
--$ffff
|
||
ldy #dib.scsiid
|
||
sta [dib_ptr],y
|
||
;
|
||
; Set ZP3 to point to the Command
|
||
; Packet information. This will be
|
||
; used to place the length and
|
||
; block number as well as the
|
||
; command length for the SCSI
|
||
; Manager.
|
||
;
|
||
lda |cur_group
|
||
asl a ;Multiply by 6
|
||
sta |scratch0
|
||
asl a
|
||
adc |scratch0 ;Carry Clear by asl and adc.
|
||
adc #cmd_ps_tbl ;Carry still Clear.
|
||
sta <scsi_zp3
|
||
;
|
||
; Adjust Transfer length if needed.
|
||
;
|
||
lda trans_flag
|
||
and #scsid_blk++\ ;Convert Trans Count to Blocks
|
||
scsid_byte++\ ;Leave Trans Count in Bytes
|
||
scsid_none ;Transfer count does not go in CMD
|
||
|
||
cmp #scsid_none ;Is the Request length in the command?
|
||
beq @blknum_jmp ;No.
|
||
cmp #scsid_byte ;Yes. Is it in Byte form?
|
||
beq @move_byte ;Yes.
|
||
cmp #scsid_blk ;No. Is it in Block form?
|
||
beq @move_blk ;Yes.
|
||
sec ;No. Return Bad Byte Count Error.
|
||
@bad_rqst lda #drvr_bad_cnt
|
||
@clv clv ;Clear Overflow Flag
|
||
rts
|
||
|
||
@blknum_jmp jmp @block_num ;No.
|
||
;
|
||
; If the request count = 0 then exit with
|
||
; the overflow flag set. This will indicate
|
||
; that no data is to tbe transfered. It
|
||
; also indicates that this is not an error
|
||
; condition.
|
||
;
|
||
@zero_cnt bit @overflow
|
||
clc
|
||
rts
|
||
|
||
@overflow dc.w $4000
|
||
;
|
||
; Convert Request Count to Blocks.
|
||
;
|
||
@move_blk lda <rqst_cnt ;Setup Divide Routine.
|
||
sta |divend
|
||
|
||
ora <rqst_cnt+2 ;Check for zero request from block device.
|
||
beq @zero_cnt
|
||
|
||
lda <rqst_cnt+2
|
||
sta |divend+2
|
||
|
||
ldy #dib.blksize
|
||
lda [dib_ptr],y
|
||
sta |divsor
|
||
|
||
jsr divide
|
||
bcs @clv
|
||
;
|
||
; Get requested Length in blocks and
|
||
; goto stuff routine. Also stuff for
|
||
; timeout calculation if needed.
|
||
;
|
||
ldx |result
|
||
stx |time_cnt
|
||
ldy |result+2
|
||
sty |time_cnt+2
|
||
|
||
bra @stuff_len
|
||
;
|
||
; Get requested length in bytes and goto
|
||
; stuff routine.
|
||
;
|
||
@move_byte ldx <rqst_cnt
|
||
ldy <rqst_cnt+2
|
||
;
|
||
; Clear timeout Values.
|
||
;
|
||
stz |time_cnt
|
||
stz |time_cnt+2
|
||
|
||
;*******************************************************
|
||
;
|
||
; Transfer request length to command packet.
|
||
;
|
||
;*******************************************************
|
||
|
||
@stuff_len sty |temp_y ;Save 32 bit transfer length for later
|
||
stx |temp_x
|
||
short ;Goto 8 bit Acc
|
||
ldy #<c_len_len ;Get offset into command packet description
|
||
lda (scsi_zp3),y ;table and get Length of length field
|
||
tax
|
||
;
|
||
; Check byte count so that any value greater
|
||
; than the max will be represented by the
|
||
; max.
|
||
;
|
||
lda |temp_y+1
|
||
beq @byte_3_ok
|
||
lda #$ff
|
||
stz |temp_y+1
|
||
sta |temp_y
|
||
sta |temp_x+1
|
||
sta |temp_x
|
||
@byte_3_ok cpx #$03
|
||
bge @count_ok
|
||
|
||
lda |temp_y
|
||
beq @byte_2_ok
|
||
lda #$ff
|
||
stz |temp_y
|
||
sta |temp_x+1
|
||
sta |temp_x
|
||
@byte_2_ok cpx #$02
|
||
beq @count_ok
|
||
|
||
lda |temp_x+1
|
||
beq @byte_1_ok
|
||
lda #$ff
|
||
stz |temp_x+1
|
||
sta |temp_x
|
||
@byte_1_ok cpx #$01
|
||
beq @count_ok
|
||
|
||
stz |temp_x
|
||
|
||
@count_ok dey
|
||
lda (scsi_zp3),y ;and the offset to the end of the length
|
||
tay ;field
|
||
lda |temp_x ;Stuff the Low byte of the length
|
||
ora [scsi_zp4],y
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_len ;Do Block Number.
|
||
dey
|
||
lda |temp_x+1 ;Stuff the Mid-Low byte of the
|
||
ora [scsi_zp4],y ;length if used.
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_len ;Do Block Number.
|
||
dey
|
||
lda |temp_y ;Stuff the Mid-High byte of the
|
||
ora [scsi_zp4],y ;length if used.
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_len ;Do Block Number.
|
||
dey
|
||
lda |temp_y+1 ;Stuff the High byte of the
|
||
ora [scsi_zp4],y ;length if used.
|
||
sta [scsi_zp4],y
|
||
;
|
||
; Clean up Processor.
|
||
;
|
||
@exit_len longmx
|
||
|
||
;*******************************************************
|
||
;
|
||
; Convert Block Number from Logical to Actual If
|
||
; partition Flag is <20> zero then leave block number
|
||
; unmodified.
|
||
;
|
||
;*******************************************************
|
||
|
||
@block_num lda |trans_flag ;Does it have a block number in the
|
||
and #scsit_blk ;command packet?
|
||
beq @exit_blk1 ;No.
|
||
;
|
||
; Is this a partition Map call?
|
||
;
|
||
bit |f_partition ;Get the partition call flag.
|
||
bmi @exit_blk1 ;It's a partition map call.
|
||
;
|
||
; It has a block number and is not a
|
||
; partition map command. Translate
|
||
; that logical block number to a
|
||
; physical number.
|
||
;
|
||
ldy #dib.start_blk+2
|
||
lda [dib_ptr],y
|
||
sta |p_block_num\ ;Stored High <20> Low
|
||
-dib.start_blk,y
|
||
ldy #dib.start_blk
|
||
lda [dib_ptr],y
|
||
sta |p_block_num\ ;Stored High <20> Low
|
||
-dib.start_blk,y
|
||
;
|
||
; Zero out starting block number space.
|
||
; This space is used to retrieve the
|
||
; starting block number for a call incase
|
||
; it is needed. An example of this is a
|
||
; device specific write type call that is
|
||
; going to update blocks that might be in
|
||
; the cache. If this happens, then this
|
||
; will be used as a starting point from
|
||
; whence to kill those blocks that are in
|
||
; the cache.
|
||
;
|
||
stz |killer_blk
|
||
stz |killer_blk+2
|
||
;
|
||
; We now have the block offset where we
|
||
; need it.
|
||
;
|
||
short ;Goto 8 bit Acc
|
||
ldy #<c_blk_len ;Get offset into command packet description
|
||
lda (scsi_zp3),y ;table and get Length of block field
|
||
tax
|
||
dey
|
||
lda (scsi_zp3),y ;and the offset to the end of the block
|
||
tay ;field
|
||
clc
|
||
lda [scsi_zp4],y ;adjust the Low byte of block num.
|
||
sta |killer_blk
|
||
adc |p_block_num+3 ;add the physical block offset.
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_blk ;Do Block Number.
|
||
dey
|
||
lda [scsi_zp4],y ;adjust the Mid-Low byte of block num.
|
||
sta |killer_blk+1
|
||
adc |p_block_num+2 ;add the physical block offset.
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_blk ;Do Block Number.
|
||
dey
|
||
lda [scsi_zp4],y ;adjust the Mid-High byte of block num.
|
||
sta |killer_blk+2
|
||
adc |p_block_num+1 ;add the physical block offset.
|
||
sta [scsi_zp4],y
|
||
dex
|
||
beq @exit_blk ;Do Block Number.
|
||
dey
|
||
lda [scsi_zp4],y ;adjust the High byte of block num.
|
||
sta |killer_blk+3
|
||
adc |p_block_num ;add the physical block offset.
|
||
sta [scsi_zp4],y
|
||
;
|
||
; Clean up Processor.
|
||
;
|
||
@exit_blk longmx
|
||
;
|
||
; Check for Block Number overflow
|
||
; (Carry Set)
|
||
;
|
||
bcc @exit_blk2
|
||
lda #drvr_bad_req
|
||
rts
|
||
|
||
@exit_blk1 clc
|
||
@exit_blk2 clv ;Clear no data flag
|
||
rts
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Stuff Flags for SCSI Manager
|
||
;
|
||
;*******************************************************
|
||
|
||
stuff_flag
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
IF scsi_dtype = mcd_40 THEN
|
||
;
|
||
; It is a Direct Access Magnetic
|
||
; Tape Device.
|
||
;
|
||
lda #$8000
|
||
|
||
ELSE
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
;
|
||
; It is not a Direct Access Magnetic
|
||
; Tape Device.
|
||
;
|
||
lda #$0000
|
||
|
||
ENDIF
|
||
|
||
;-------------------------------------------------------------------------------
|
||
|
||
ldy #dib.scsic_flgs
|
||
sta [dib_ptr],y
|
||
rts
|
||
|
||
EJECT
|
||
|
||
;*******************************************************
|
||
;
|
||
; Call the SCSI Manager VIA the Supervisory Dispatcher.
|
||
;
|
||
;*******************************************************
|
||
issue_cmd
|
||
;
|
||
; Set Timeout Factor.
|
||
;
|
||
lda |timeout_flag
|
||
beq @over
|
||
;
|
||
; Adjust Time Out Value.
|
||
;
|
||
ldy #dib.time_out
|
||
lda [dib_ptr],y
|
||
sta @time_mult
|
||
|
||
lda |time_cnt+2
|
||
bne @do_max_time
|
||
lda |time_cnt
|
||
stz |time_cnt
|
||
beq @do_max_time
|
||
|
||
@mult_loop lsr @time_mult
|
||
bcc @shift
|
||
|
||
php
|
||
clc
|
||
adc |time_cnt
|
||
sta |time_cnt
|
||
bcs @fix
|
||
cmp #max_timeout
|
||
bge @fix
|
||
plp
|
||
|
||
@shift beq @save
|
||
asl a
|
||
bcc @mult_loop
|
||
bra @do_max_time
|
||
|
||
@time_mult dc.w null
|
||
|
||
@fix plp
|
||
|
||
@do_max_time lda #max_timeout
|
||
@save ldy #dib.time_out
|
||
sta [dib_ptr],y
|
||
;
|
||
; Setup the pointer to our Command
|
||
; list within the DIB on GS/OS Direct
|
||
; Page
|
||
;
|
||
@over ldx |gsos_dpage
|
||
clc
|
||
lda <dib_ptr
|
||
|
||
; adc #dib.scsiid
|
||
adc #dib.scsi_slot
|
||
|
||
sta >smgr_pl_ptr,x
|
||
lda <dib_ptr+2
|
||
|
||
; adc #^dib.scsiid
|
||
adc #^dib.scsi_slot
|
||
|
||
sta >smgr_pl_ptr+2,x
|
||
;
|
||
; Call the SCSI Manager via the
|
||
; S_DISPATCHER
|
||
;
|
||
lda |scsi_mgrnum ;Get the Managers ID
|
||
ldx |manager_cmd ;Get Manager Command Number
|
||
jmp rout2_s_disp
|
||
|
||
EJECT
|
||
;
|
||
; Bitmaps used to check
|
||
; for command errors.
|
||
;
|
||
; Offset into DIB to where
|
||
; the WORD is that holds the
|
||
; bit for this group.
|
||
;
|
||
bm_cmd_offset dc.w dib.group0 ;group0 Low WORD
|
||
dc.w dib.group0+2 ; High WORD
|
||
dc.w dib.group1 ;group1 Low WORD
|
||
dc.w dib.group1+2 ; High WORD
|
||
dc.w dib.group2 ;group2 Low WORD
|
||
dc.w dib.group2+2 ; High WORD
|
||
dc.w dib.group3 ;group3 Low WORD
|
||
dc.w dib.group3+2 ; High WORD
|
||
dc.w dib.group4 ;group4 Low WORD
|
||
dc.w dib.group4+2 ; High WORD
|
||
dc.w dib.group5 ;group5 Low WORD
|
||
dc.w dib.group5+2 ; High WORD
|
||
dc.w dib.group6 ;group6 Low WORD
|
||
dc.w dib.group6+2 ; High WORD
|
||
dc.w dib.group7 ;group7 Low WORD
|
||
dc.w dib.group7+2 ; High WORD
|
||
;
|
||
; Mask for commands $00 - $0F
|
||
; in the low word and commands
|
||
; $10 - $1F in the high word.
|
||
;
|
||
bm_cmd_mask dc.w bit_7 ;CMD $x0 Bit 7 Low Byte
|
||
dc.w bit_6 ;CMD $x1 Bit 6 Low Byte
|
||
dc.w bit_5 ;CMD $x2 Bit 5 Low Byte
|
||
dc.w bit_4 ;CMD $x3 Bit 4 Low Byte
|
||
dc.w bit_3 ;CMD $x4 Bit 3 Low Byte
|
||
dc.w bit_2 ;CMD $x5 Bit 2 Low Byte
|
||
dc.w bit_1 ;CMD $x6 Bit 1 Low Byte
|
||
dc.w bit_0 ;CMD $x7 Bit 0 Low Byte
|
||
dc.w bit_15 ;CMD $x8 Bit 7 High Byte
|
||
dc.w bit_14 ;CMD $x9 Bit 6 High Byte
|
||
dc.w bit_13 ;CMD $xA Bit 5 High Byte
|
||
dc.w bit_12 ;CMD $xB Bit 4 High Byte
|
||
dc.w bit_11 ;CMD $xC Bit 3 High Byte
|
||
dc.w bit_10 ;CMD $xD Bit 2 High Byte
|
||
dc.w bit_9 ;CMD $xE Bit 1 High Byte
|
||
dc.w bit_8 ;CMD $xF Bit 0 High Byte
|
||
|
||
ENDP
|
||
|
||
EJECT
|
||
|
||
END
|