.SBTTL AUXIO entry and dispatch .TITLE AUXIO DPACP auxiliary task process packet .PSECT AUXIO .IDENT /M002/ .SBTTL Common I/O routine ; ;+ ; ; AUXIO ; Process packet for DPACP auxiliary program. ; Moves the parameters from the recieved packet ; to a QIO DPB. ; The correct Lun must be used for each function, ; some use a general lun, others need a saved lun. ; This is accomplished through a table, each entry in ; the table corresponding to one lun, the entry being zero ; if not accessed or equal to the file number if accessed. ; The function code is used as an offset into a dispatch table ; to allow the proper lun usage for each function. ; ; The FID and FNB offsets are turned into addresses and ; the pointers stored in the QIO DPB. ; After the QIO the actual FID or FNB block is moved to ; the return packet. ; The QIO status block address already points to the ; return packet. ; ; INPUT ; R5 Points to recieved packet ; R4 Points to return packet ; ; OUTPUT ; R0-R3 destroyed, R5,R4 preserved ; Outputs I/O return packet @R4 ; ; EXTERNAL REFERENCES ; ; AUTHOR ; Daniel McCoy Informatics Inc. Palo Alto, Ca. ; ; REVISIONS LAST CHANGE ; DATE PERSON STATEMENT OF CHANGES ; 5 mar 80 dsm Added multi device support ; 19 feb 80 dsm Minor restructuring ; 26 sep 79 DSM Version two ; 1/2/79 DSM First coding ; ; NOTES ; ;- ; .PAGE .MCALL DIR$ ; AUXIO:: ; Get function code and convert to dispatch offset MOVB X.FCN+1(R5),R0 ; Get function code, high byte SUB #LOWFCN-1,R0 ; Make it from 0 to ... BLE 2$ ; Dont use if below LOWFCN CMP #HIFCN-LOWFCN+1,R0 ; Check for too high BLT 2$ ; Dont use if higher than HIFCN ASL R0 ; Double to word index ; ; Call the routine corresponding to the function, ; according to the dispatch table below. ; Received packet address in R5 ; Return packet address in R4 CALL @FCNDSP-2(R0) BR 10$ 2$: CALL ILLCOD ; Function out of range 10$: ; DEBUG !!! Return lun used in extra packet position MOV QLUN,Y.YYY(R4) ; DEBUG !!! RETURN ; .PAGE .SBTTL Function dispatch table ; ; Dispatch table for QI/O function code. ; Offset from fuction code using formula below: ; ((function code, high byte)-(LOWFCN-1))*2 + FCNDSP - 2 FCNDSP: .WORD ILLCOD ; 5=mount volume .WORD ILLCOD ; 6=dismount volume .WORD DODAC ; 7=close out unit ; Find marked lun, free lun on success .WORD ILLCOD ; 10=unused .WORD DOGEN ; 11=find file in directory ; Use IOLUN .WORD ILLCOD ; 12=unused .WORD DOGEN ; 13=remove file from directory ; Use IOLUN .WORD DOGEN ; 14=enter file in directory ; Use IOLUN .WORD DOACC ; 15=access for read .WORD DOACC ; 16=access for read, write .WORD DOACC ; 17=access for read, write, ext. ; Find free lun, mark lun on success .WORD DODAC ; 20=deaccess file ; Find marked lun, free lun on success .WORD ILLCOD ; 21=read, virtual block .WORD ILLCOD ; 22=write virtual block .WORD DOEXDL ; 23=extend file ; Try to use marked lun, else use IOLUN .WORD DOGEN ; 24=create file ; Use IOLUN .WORD DOEXDL ; 25=mark file for delete ; Try to use marked lun, else use IOLUN .WORD ILLCOD ; 26=read attributes .WORD ILLCOD ; 27=write attributes .PAGE .SBTTL DOIO Common I/O routine ;+ ; DOIO ; Individual I/O routines come here for actual I/O ; Lun has been set up. ; Here we set up the rest of the parameters and do the QIO. ; Then the results are moved to the return packet. ; ; R3,R4,R5 preserved ; R0,R1,R2 destroyed ;- DOIO: MOV R5,R0 ; Save packet address in R5, use R0 MOV X.FCN(R0),QFUN ; Move function code ; ADD #X.FIDP,R0 ; Offset to FID MOV #QPARAM,R1 ; Point to QIO parameter list MOV (R0)+,(R1)+ ; Move FID pointer (X.FIDP) BEQ 10$ ; Skip if no FID ADD R5,-2(R1) ; Turn FID offset into an address 10$: MOV (R0)+,(R1)+ ; Move attribute parameter (X.RWAT) MOV (R0)+,(R1)+ ; Move extend parameter (X.EXTD) MOV (R0)+,(R1)+ ; Move second word of extend MOV (R0)+,(R1)+ ; Move access control (X.RTRV) MOV (R0),(R1) ; Move FNB pointer (X.FNBP) BEQ 20$ ; Skip if no FNB ADD R5,(R1) ; Turn FNB offset into an address 20$: ; Actual I/O, ; Parameters, function, and lun all set up. DIR$ #QIO ; Send the I/O request BCC 30$ ; Skip if no directive error MOV #BADQ,R0 ; Point to error message JMP BADMSG ; Report bad directive and quit 30$: ; ; Return parameters and status, R4 points to return packet MOV QPARAM,Y.FIDP(R4) ; FID pointer BEQ 40$ ; Skip if no FID ; FID processing MOV R4,R1 ; Save pointer to return packet ADD #Y.FBLK,R1 ; Point return space for FID MOV QPARAM,R0 ; Point to FID MOV (R0)+,(R1)+ ; Move file number MOV (R0)+,(R1)+ ; Move file sequence MOV (R0),(R1) ; Move volume number (not used) MOV #Y.FBLK,Y.FIDP(R4) ; Store offset CLR Y.FNBP(R4) ; No FNB, only one at a time BR 60$ ; Skip FNB stuff 40$: ; FNB processing TST QPARAM+10. ; Check for FNB pointer BEQ 60$ ; Skip if no FNB MOV R4,R1 ; Save pointer to return packet ADD #Y.FBLK,R1 ; Point to destination MOV QPARAM+10.,R0 ; Point to FNB MOV #/2,R2 ; Words to move 50$: MOV (R0)+,(R1)+ ; Move FNB to return packet SOB R2,50$ ; Loop ; MOV #Y.FBLK,Y.FNBP(R4) ; Store offset 60$: RETURN .PAGE .SBTTL Individual function setup routines ;+ ; DOGEN ; Entry for I/O that doesn't need previous access, ; uses the general I/O lun. ;- DOGEN: MOV #IOLUN,QLUN ; Use normal I/O lun CALL ASN ; Assign lun BCS 10$ ; Check for error CALL DOIO ; Do the QIO, and return 10$: RETURN ;+ ; DOACC ; Entry to do accesses, ; finds a free lun to use for access, ; returns an error if none free, ; if the access was successful marks the lun in use ; for this file. ;- DOACC: CLR R0 ; Set search for free lun CALL FIND ; Look for it MOV R2,QLUN ; Put logical unit number into QIO DPB BMI 30$ ; Error if no lun found CALL ASN ; Assign lun BCS 20$ ; Check for error CALL DOIO ; Do the QIO TSTB QSTAT ; Successful access? BMI 20$ ; Skip if not MOV X.ID(R5),LUNLST(R3) ; Mark lun in use for this file ADD #2,FFLUN ; Bump free lun to look past here 20$: RETURN ; Normal return 30$: MOV #IE.TMM,R0 ; Report too many messages ; Close enough when all the luns are used BR ERROR ; Report error ;+ ; DOEXDL ; Entry to do extends and deletes, ; if file is accessed, uses lun on which it is accessed ; else uses the general I/O lun. ;- DOEXDL: MOV X.ID(R5),R0 ; Set search for the ID CALL FIND ; Look for it MOV R2,QLUN ; Use allocated lun BPL 20$ ; Skip if one was found MOV #IOLUN,QLUN ; Else use regular lun CALL ASN ; Assign lun BCS 30$ ; Check for error 20$: CALL DOIO ; Do the QIO, and return 30$: RETURN ;+ ; DODAC ; Entry to do deaccesses ; Uses the lun on which the file was previously accessed ; and returns an error if it wasn't accessed. ; If the deaccess was successful, marks the lun free. ;- DODAC: MOV X.ID(R5),R0 ; Set search for the ID CALL FIND ; Look for it MOV R2,QLUN ; Use allocated lun BMI 30$ ; Error if no lun found CALL DOIO ; Do the QIO TSTB QSTAT ; Successful deaccess BMI 20$ ; Dont free lun if not deaccessed CLR LUNLST(R3) ; Deaccess complete, free lun CMP R3,FFLUN ; Is this lowest free one? BHI 20$ ; If hi, no MOV R3,FFLUN ; Yes, save it as first 20$: RETURN ; Normal return 30$: MOV #IE.NLN,R0 ; Report file no accessed BR ERROR ; Return with error ;+ ; ILLCOD ; entry for function codes not supported by this program ; returns with "illegal function code" specified in ; the return packet status block ;- ILLCOD: MOV #IE.IFC,R0 ; Report bad function ERROR: MOV R0,QSTAT ; Set error code CLRB QSTAT+1 ; Clear hi byte CLR QSTAT+2 ; Clear second word of status SEC ; Signal error return RETURN .PAGE .SBTTL Utility routines ;+ ; FIND ; searches LUNLST for the value specified in R0 ; returns: ; R2 = LUN corresponding to entry found ; or -1 if not found ; R3 = Pointer into LUNLST for entry found ; ; R1 destroyed ; R0, R4, R5 preserved ;- FIND: TST R0 ; Looking for available lun? BNE 5$ ; If ne, no MOV FFLUN,R3 ; Point at first free one TST LUNLST(R3) ; Is it really free? BEQ 20$ ; Yes use it BR 6$ ; No, just start there 5$: CLR R3 ; Start at beginning 6$: MOV #NACLNS,R1 ; Get number of luns ASL R1 ; Convert to end of LUNLST ; 10$: CMP R3,R1 ; End of list? BGE 30$ ; Get out if past end of list CMP R0,LUNLST(R3) ; entry match? BEQ 20$ ; get out of loop if we found it TST (R3)+ ; Bump to next word BR 10$ ; Loop 20$: ; Found it MOV R3,R2 ; Fix up Lun ASR R2 ; Convert from bytes to words ADD #ACLUN1,R2 ; Bump past the other luns RETURN 30$: ; Went to end of list MOV #-1,R2 ; Set not found RETURN .PAGE ;+ ; ASN Checks to see that the device requested in the packet ; is in DEVLST, if not returns a negative error code in ; R0, if device is there, it assigns the lun in the ; current QIO DPB to the device. ; If assign lun is unsuccessful, again returns a negative R0 ; If all goes well R0 = 0 ; ; R1,R2 destroyed ; R3-R5 preserved ;- .MCALL ALUN$S ASN: MOV #DEVLST,R0 ; Point to device list MOV X.NAME(R5),R1 ; Get device name MOV X.UNIT(R5),R2 ; Get device unit 10$: CMP (R0),R1 ; Device name match? BNE 20$ ; Skip if no CMP 2(R0),R2 ; Unit match? BEQ 30$ ; If yes, we found it 20$: ADD #4,R0 ; Next device CMP R0,#DEVEND ; Any more? BLO 10$ ; Check next one if yes ; Device not there BR 40$ ; Go return error 30$: ; We found a valid device ; Assign the lun to it ; ALUN$S QLUN,R1,R2 BCS 40$ ; If directive error return with error ; The device is all assigned and set up CLR R0 ; Show success, (clears carry too) RETURN ; 40$: MOV #IE.NFW,R0 ; Return some error code BR ERROR ; Returns the same to slave .END