;******************************************************* ; ; SCSI Driver Main Driver. ; ; Written by Matt Gulick. Started May 16,1988 ; ; Copyright Apple Computer, Inc. 1988-90 ; ;******************************************************* ;******************************************************* ; ; This file contains the code segment that is called ; when a Device call comes in. This code is ; responsible for checking the validity of the ; command, setting the environment and parsing the ; call to the desired filter. ; ;******************************************************* ;******************************************************* ; ; Revision History: ; ;******************************************************* ; May 16, 1988 File started. ; May 17, 1988 DIB Record defined. ; June 6, 1988 Main Driver Written. ; Jun 10, 1988 Broke down files into links. ; Jun 20, 1988 Add comments concerning Registers to the ; routine headers. Also incorporate ; changes from code review. ; July 8, 1988 Added code to allocate Directpage area ; of $100 bytes. ; Oct 25, 1988 Modified the default DIB to reflect the ; changes in the SCSI Manager Interface. ; Also made changes in the code to account ; for this. ; ; Apr 10, 1989 Started code for character devices. ; STRING PASCAL BLANKS OFF PAGESIZE 70 PRINT NOGEN PRINT NOMDIR MACHINE M65816 IMPORT startup IMPORT Open IMPORT Read IMPORT Write IMPORT Close IMPORT Status IMPORT Control IMPORT Flush IMPORT Shutdown IMPORT g_dib_ptr ENTRY default_dib ENTRY direct_page ;Driver Mgmt ENTRY exit_dpage ;Driver Mgmt ENTRY gsos_dpage ;Driver Mgmt ENTRY lst_rslt_ec ;Status ENTRY lst_rslt_id ENTRY lst_rslt_stat ENTRY lst_rslt_skey ENTRY lst_rslt_info ENTRY lst_rslt_rqlen ENTRY lst_rslt_scode ENTRY auto_sense_data ;Main Driver EJECT INCLUDE 'scsihd.equates' PRINT OFF INCLUDE 'M16.MEMORY' INCLUDE 'M16.UTIL' PRINT ON ;******************************************************* ; ; This dummy Procedure is used to inform the loader. ; Drivers start with data but are not data segments. ; The loader may load what it thinks to be a data ; segment accross bank boundries. This is not good ; for code. ; ;******************************************************* EXPORT dummy dummy PROC ENDP ;******************************************************* ; ; Header as required by the device dispatcher for ; drivers. ; ;******************************************************* EXPORT start start PROC dc.w default_dib-start dc.w $0001 dc.w ctrl_list-start ctrl_list dc.l null dc.l null ENDP ;******************************************************* ; ; Main entry to the SCSI Driver code segment. The ; state of the machine at this point is: ; ; Acc = Call Number ; $0000 = Startup ; $0001 = Open ; $0002 = Read ; $0003 = Write ; $0004 = Close ; $0005 = Status ; $0006 = Control ; $0007 = Flush ; $0008 = Shutdown ; Y register = Unspecified ; X register = Unspecified ; P register = 0=M=X=e ; Direct Page = GS/OS Direct Page ; Data Bank = Unspecified ; Stack Pointer = GS/OS Stack ; System Speed = Fast ; ;******************************************************* EXPORT drvr_main drvr_main PROC ; ; Preserve Callers Data Bank ; and set ours. ; phb phk plb ; ; Check to see if we have our own ; Direct Page. If so then copy first ; 'x' bytes to our temp, switch DP and ; copy it back to ours. ; ldx |direct_page beq @chk_startup ;No DP. This must be a startup call. ; ; Set our Direct Page with the first ; 'x' Bytes equal to the GS/OS DP ; settings. ; pha ; clc ; Calculate Source Address of GS/OS tdc ; Direct Page that we want. sta |gsos_dpage ; Preserving GS/OS DP for later use. adc #dev_num pea $0000 pha ; clc ; Calculate Destination Address of lda |direct_page ; our Direct Page that we want. adc #dev_num pea $0000 pha pushlong #dib_ptr+4 ;Length of the move pushword #move_sinc_dinc jsl move_info ;Move the data ; ; Set our Direct Page. ; lda |direct_page tcd ; ; Continue with call. ; pla bra @do_command ; ; Validate for Startup Command. ; @chk_startup cmp #cmd_start bne @error1 ; ; Convert call number in Acc ; to an index into our jmp table ; @do_command cmp #max_d_cmd+1 bge @error @do_cmd1 asl a tax ; ; If this is a status call $0005 ; then don't clear these values. ; That's what they are trying to ; get. ; cmp #cmd_status*2 ;Account for the ASL bne @clear ;Not a status call lda >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF warm_ss_suprt = true THEN dc.w restartable++\ ;Restartable from ram if Set (WORD) speed_ind++\ ;Device is speed ind if Set blk_device++\ ;Block Device if Set write_allow++\ ;Write is Allowed if Set read_allow++\ ;Read is Allowed if Set format_allow ;Format is Allowed if Set ELSE ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dc.w speed_ind++\ ;Device is speed ind if Set (WORD) blk_device++\ ;Block Device if Set write_allow++\ ;Write is Allowed if Set read_allow++\ ;Read is Allowed if Set format_allow ;Format is Allowed if Set ENDIF ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ENDIF ;------------------------------------------------------------------------------- ; ; Is it a Write-once Read-multiple Device. ; IF scsi_dtype = apple_cd THEN ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF warm_ss_suprt = true THEN dc.w restartable++\ ;Restartable from ram if Set (WORD) speed_ind++\ ;Device is speed ind if Set blk_device++\ ;Block Device if Set read_allow ;Read is Allowed if Set ELSE ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dc.w speed_ind++\ ;Device is speed ind if Set (WORD) blk_device++\ ;Block Device if Set read_allow ;Read is Allowed if Set ENDIF ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ENDIF ;------------------------------------------------------------------------------- ; ; Is it an MCD 40 Tape Drive ; IF scsi_dtype = mcd_40 THEN ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IF warm_ss_suprt = true THEN dc.w restartable++\ ;Restartable from ram if Set (WORD) speed_ind++\ ;Device is speed ind if Set blk_device++\ ;Block Device if Set write_allow++\ ;Write is Allowed if Set read_allow++\ ;Read is Allowed if Set format_allow ;Format is Allowed if Set ELSE ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dc.w speed_ind++\ ;Device is speed ind if Set (WORD) blk_device++\ ;Block Device if Set write_allow++\ ;Write is Allowed if Set read_allow++\ ;Read is Allowed if Set format_allow ;Format is Allowed if Set ENDIF ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = scanner THEN ; ; Is it a Scanner Device? ; dc.w speed_ind++\ ;Device is speed ind if Set read_allow ;Read is Allowed if Set ENDIF ;------------------------------------------------------------------------------- dc.l $00000000 ; Block Count for this device (LONG) ; Set to default. This can change ; ; Length of Descriptive Name (PSTR) ; Followed by the Descriptive ; Name for the device. This ; is a conditional Assembly. ; ;------------------------------------------------------------------------------- IF scsi_dtype = direct_acc THEN ; ; Is it a Direct-Access Device. ; dc.b 'SCSIHD.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = seq_acc THEN ; ; Is it a Sequential-Access Device. ; dc.b 'SCSITAPE.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = print_dvc THEN ; ; Is it a Printer Device. ; dc.b 'SCSIPRINTER.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = proc_dvc THEN ; ; Is it a Processor Device. ; dc.b 'SCSIPROC.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = worm_dvc THEN ; ; Is it a Write-once Read-multiple Device. ; dc.b 'SCSIWORM.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = read_dacc THEN ; ; Is it a Read-only Direct-Access Device. ; dc.b 'SCSICDROM.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = scanner THEN ; ; Is it a Scanner Device. ; dc.b 'SCSISCANNER.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = optic_mem THEN ; ; Is it a Optical Memory Device. ; dc.b 'SCSIOPTICAL.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = changer THEN ; ; Is it a Changer Device. ; dc.b 'SCSICHANGER.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = comm_dvc THEN ; ; Is it a Communication Device. ; dc.b 'SCSICOM.00.00' ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = mcd_40 THEN ; ; Is it a Direct Access Magnetic ; Tape Device. ; dc.b 'SCSITAPE.00.00' ENDIF ;------------------------------------------------------------------------------- ; ; Pad space to fill gap to next field. ; dcb.b dib.slotnum+default_dib-*,$20 dc.w $8000 ; Device Slot Number from MGR. (WORD) ; By setting bit 15 in the slot ; number we can force the device ; dispatcher to keep it around. ; We will save this as a default ; dib. This will also allow us ; to remain loaded if there are ; no devices available at boot ; time. ; dc.w $0000 ; Device Unit Number from MGR. (WORD) dc.w drvr_vers ; Version Number for our Driver (WORD) ;------------------------------------------------------------------------------- IF scsi_dtype = direct_acc THEN dc.w $0005 ; ID of Device we talk to (WORD) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = apple_cd THEN dc.w $0007 ; ID of Device we talk to (WORD) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = mcd_40 THEN dc.w $0006 ; ID of Device we talk to (WORD) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = scanner THEN dc.w $001A ; ID of Device we talk to (WORD) ENDIF ;------------------------------------------------------------------------------- dc.w $0000 ; Head Device Link (WORD) dc.w $0000 ; Forward Device Link (WORD) ; ; Pointer to DIB Extension (LONG) ; dc.l dib.start_blk+default_dib dc.w $0000 ; DIB Device Number (WORD) ; ; The Starting Block Number for this device ; is maintained here. This is used to ; modify the requested block number from ; a logical to a physical number. ; dc.l $00000000 ; Starting Physical Block Num. (LONG) ; ; These two pointers are the compliment ; to the links in the standard DIB and ; will point to the actual DIB referenced ; in the Head and Forward Device Links. ; dc.l null ; Head Dvc Pointer (LONG) dc.l null ; Forward Dvc Pointer (LONG) dc.w null ; Number of active dibs in mem (WORD) dc.w null ; Reserved (WORD) ; ; Memory Manager Handle ; dc.l $00000000 ; (LONG) ; ; Block Size ; dc.l block_size ; (LONG) ; ; Maximum SCSI Command supported by ; the device for this DIB. ; dc.w $00FF ; (WORD) ; ; SCSI Command Group Bitmaps used as defaults ; when device does not return this info in the ; INQUIRY Command. ; ;------------------------------------------------------------------------------- IF scsi_dtype = direct_acc THEN ; ; It is a Direct-Access Device. ; dc.B $D9,$B0,$27,$BE ; Group 0 (LONG) dc.B $04,$03,$1E,$FB ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = seq_acc THEN ; ; It is a Sequential-Access Device. ; dc.B $D4,$B1,$FF,$FF ; Group 0 (LONG) dc.B $00,$10,$08,$78 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = print_dvc THEN ; ; It is a Printer Device. ; dc.B $98,$30,$AF,$9C ; Group 0 (LONG) dc.B $00,$00,$00,$00 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = proc_dvc THEN ; ; It is a Processor Device. ; dc.B $90,$A0,$20,$8C ; Group 0 (LONG) dc.B $00,$00,$00,$00 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = worm_dvc THEN ; ; It is a Write-once Read-multiple Device. ; dc.B $D1,$90,$27,$BE ; Group 0 (LONG) dc.B $04,$03,$10,$60 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = read_dacc THEN ; ; It is a Read-only Direct-Access Device. ; dc.B $D0,$90,$27,$BE ; Group 0 (LONG) dc.B $04,$01,$10,$60 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = scanner THEN ; ; It is a Scanner Device. ; dc.B $90,$00,$27,$BC ; Group 0 (LONG) dc.B $0C,$A0,$48,$78 ; Group 1 (LONG) dc.B $00,$0C,$04,$20 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = optic_mem THEN ; ; It is a Optical Memory Device. ; dc.B $D9,$B0,$27,$BE ; Group 0 (LONG) dc.B $04,$0F,$1E,$FC ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$AF,$11,$04 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = changer THEN ; ; It is a Changer Device. ; dc.B $90,$00,$20,$8C ; Group 0 (LONG) dc.B $00,$00,$00,$80 ; Group 1 (LONG) dc.B $00,$00,$04,$21 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $06,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = comm_dvc THEN ; ; It is a Communication Device. ; dc.B $90,$A0,$24,$2C ; Group 0 (LONG) dc.B $00,$00,$00,$18 ; Group 1 (LONG) dc.B $00,$00,$00,$00 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = mcd_40 THEN ; ; It is a Direct Access Magnetic ; Tape Device. ; dc.B $DF,$77,$FF,$7C ; Group 0 (LONG) dc.B $04,$00,$01,$18 ; Group 1 (LONG) dc.B $00,$00,$00,$00 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- IF scsi_dtype = appl_laser THEN ; ; It is an Apple LaserWriter Device. ; dc.B $FE,$20,$27,$20 ; Group 0 (LONG) dc.B $00,$00,$00,$00 ; Group 1 (LONG) dc.B $00,$00,$00,$00 ; Group 2 (LONG) dc.B $00,$00,$00,$00 ; Group 3 (LONG) dc.B $00,$00,$00,$00 ; Group 4 (LONG) dc.B $00,$00,$00,$00 ; Group 5 (LONG) dc.B $00,$00,$00,$00 ; Group 6 (LONG) dc.B $00,$00,$00,$00 ; Group 7 (LONG) ENDIF ;------------------------------------------------------------------------------- ; ; SCSI Manager Call PList ; dc.w $0000 ; Same as our Slot Number (WORD) dc.w scsi_dtype ; Same as our Unit Number (WORD) dc.w $0000 ; Version of call issued (WORD) dc.w $0000 ; Flags from Command Table (WORD) dc.w $0000 ; Time Out Factor * xxx ms (WORD) ; Completion Routine Pointer (LONG) dc.l dib.complet\ +default_dib ; Pointer to Command Packet (LONG) dc.l dib.scsicmd\ +default_dib ; Ptr to Send/R'cv Structure (LONG) dc.l dib.trx_buff\ +default_dib dc.l $00000000 ; Users Send/R'cv Length (LONG) ; Pointer to Status Structure (LONG) dc.l auto_sense_data dc.l $00000000 ; Reserved space 1 (LONG) dc.l $00000000 ; Reserved space 2 (LONG) ; ; SCSI Command Packet ; dcb.b 12,$00 ; Room for any SCSI Command (BYTES) ; ; SCSI Manager Device Send/R'cv Buffers List ; dc.l $00000000 ; Users Send Buffer (LONG) dc.l $00000000 ; Request cnt for this buffer (LONG) dc.l $00000000 ; Offset for next pass (LONG) dc.l $00000000 ; Null (LONG) dc.l $00000000 ; Null (LONG) dc.l $00000000 ; Null (LONG) dc.l $00000000 ; Null (LONG) dc.l $00000000 ; Null (LONG) dcb.l 4,$00000000 ; Reserved Space * 4 for future (LONG) ; ; Device Busy and other Flags (WORD) ; dc.w wait_mode++\ ; Wait Mode is default cold_dib ; and they start cold. ; ; Completion Routine for this DIB. ; This takes the remaining space in ; the allocated RAM. Any routine can ; be placed here but must never go ; beyond offset $FF ; jsl g_dib_ptr pei scsi_zp0 pei scsi_zp1 stx dib_size THEN ; ; It's too long. Force an error ; bad dib length ENDIF ;------------------------------------------------------------------------------- IF @end-default_dib