;******************************************************* ; ; 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 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 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: 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 > 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