.TITLE AK -- ARK LOGICAL DISK HANDLER .SBTTL DEFINITIONS .MCALL .DRDEF,.ADDR,.ASSUME .ENABL LC ; DEVICE SPECIFICATIONS AK.ID = 277 ;DEVICE IDENTIFIER AK.SIZ = 0 ;DEVICE SIZE ; SPFUN DEFINITIONS FN$ATT = 277 ;ATTATCH AK TO DEVICE SPECIFIED IN BUF ; RMON OFFSETS $SYNCH = 324 ;ADDRESS OF SYNCH ROUTINE $$MTPS = 360 ;.MTPS ROUTINE $$MFPS = 362 ;.MFPS ROUTINE $PNPTR = 404 ;OFFSET TO PNAME TABLE .IIF NDF,TSX$P TSX$P=0 ;NE,TSX$P ==> TSX+ .IF NE,TSX$P ; TSX+ DEFINITIONS .IIF NDF,TX$32J TX$32J=0 ;NE,TX$32J ==> ONLY 32 JOB SYSTEM Q$DEVX = 26-Q.BLKN ;QEL OFFSET TO DEVICE PNAME INDEX Q$FLAG = 27-Q.BLKN ;QEL OFFSET TO DEVICE CONTROL FLAGS Q$JOBX = 30-Q.BLKN ;QEL OFFSET TO EXTENDED JOB NUMBER DX$NCA = 10 ;DO NOT DO CACHING FOR THIS DEVICE V$REQ = 14 ;[14(-2(54))] = ADR. OF ROUTINE TO REQUEUE A REQUEST .IF NDF,MAXJOB .IF NE,TX$32J MAXJOB = 31. ;CURRENT MAXIMUM ALLOWED JOB# .IFF ; MAXJOB = 63. ;CURRENT MAXIMUM ALLOWED JOB# .ENDC ; TX$32J .ENDC ; MAXJOB .ENDC ; TSX$P ; MACROS .MACRO PUSH ARG MOV ARG,-(SP) .ENDM .MACRO POP ARG MOV (SP)+,ARG .ENDM .SBTTL EDIT HISTORY AND DESCRIPTION ; EDIT HISTORY: ; ; 6-Apr-85 Creation ; 7-Aug-85 Added .SYNCH code to TSX+ portion to avoid SOF for cached devs ; 20-Sep-86 Added code to handle TSX+ extended job numbers ; DESCRIPTION: ; ; The purpose of this handler is to allow ARK to do directory I/O to logical ;subset disks located on any physical device without requiring the user to do ;anything at monitor command level. It works by changing the appropriate ;entries in the queue element and handing it to the handler for the physical ;device that AK: has been attatched to. The attatchment is made by an SPFUN, ;and cleared either by an SPFUN or by calling the abort entry point to this ;handler. ; Since the handler may be running under RT-11, TSX+ V4, or TSX+ V5, there ;are several different mechanisms for re-queueing the request. Under RT-11 and ;TSX+ V4, handlers are loaded into the first 64K bytes, so the entry point in ;the $ENTRY table in the monitor can be called. Under TSX+ V5.1, some handlers ;may be loaded into virtual overlays in PAR5, so just calling the handler may ;not work. Fortunately, under 5.1 and later there is a table in the monitor ;that has pointers to several routines, one of which (IOSTRT) is a routine to ;re-queue an I/O request. Since this routine is normally called in user state, ;and handlers run in system state, a .SYNCH would normally have to be done ;first. It turns out, however, that the only case in which failing to do a ;.SYNCH could cause a problem is if the device we want to requeue to has data ;caching enabled. Therefore, to avoid the overhead of the .SYNCH whenever ;possible, we check the device status flag for caching (DX$NCA) and only do the ;.SYNCH if the device has caching enabled (DX$NCA=0). .SBTTL HANDLER PROPER .DRDEF AK, AK.ID, FILST$!HNDLR$!SPFUN$!ABTIO$, AK.SIZ, 0, 0 .DRBEG AK AKENT:: MOV AKCQE,R4 ;GET POINTER TO QEL MOV @#54,R5 ;GET POINTER TO BASE OF RMON .ADDR #AKBUF,R2 ;GET POINTER TO DATA BLOCK .IF NE,TSX$P ;\\\\\\ IF TSX+, .ASSUME AKB$L EQ 10 ; " .IF NE,TX$32J ;;; IF ONLY 31 JOB SYSTEM MOVB Q$JNUM(R4),R0 ;GET JOB# BIC #177407,R0 ; " BEQ AKERR ; BUT DIE IF SYSTEM ADD R0,R2 ;INDEX TO TABLE FOR JOB ASR R0 ;AND SAVE JOB# FOR .SYNCH ASR R0 ; " ASR R0 ; " MOV R0,SYNBLK+2 ; " .IFF ;;; ELSE IF 32+ JOB SYSTEM MOVB Q$JOBX(R4),R0 ;GET JOB# BLE AKERR ; BUT DIE IF SYSTEM JOB CMP R0,#MAXJOB ; OR OUT OF RANGE BHI AKERR ; " MOV R0,SYNBLK+2 ;SAVE JOB# FOR .SYNCH ASL R0 ;AND INDEX INTO TABLE FOR JOB ASL R0 ; " ASL R0 ; " ADD R0,R2 ; " .ENDC ;;; TX$32J .ENDC ;////// TSX$P MOVB Q$FUNC(R4),R0 ;GET FUNTION# BNE AKFUN ;IF NOT READ,WRITE,SEEK, DECODE MOV (R2)+,R3 ;ELSE GET HANDLER ADDRESS BEQ AKERR ; AND DIE IF NOT SET MOV Q$WCNT(R4),R0 ;COMPUTE END BLOCK# OF REQUEST BPL 1$ ; " NEG R0 ; " 1$: ADD #377,R0 ; " CLRB R0 ; " SWAB R0 ; " ADD @R4,R0 ;IF IT OVERFLOWED, DIE BCS AKERR ; " CMP R0,(R2)+ ;IF BLOCK# TOO LARGE, DIE BHI AKERR ; " BICB #7,Q$UNIT(R4) ;REPLACE UNIT# WITH PHYSICAL UNIT# BISB (R2)+,Q$UNIT(R4); " .IF NE,TSX$P ;\\\\\\ IF TSX+, MOVB (R2)+,R1 ;REPLACE AK PNAME INDEX WITH PHYSICAL INDEX MOVB R1,Q$DEVX(R4) ; " .IFF ;====== ELSE NOT TSX+ TSTB (R2)+ ;SKIP PNAME INDEX .ENDC ;////// TSX$P ADD @R2,@R4 ;ADD OFFSET TO LOGICAL DISK FILE .IF NE,TSX$P ;\\\\\\ IF TSX+, ADD (PC)+,R1 ;OFFSET TO DVFLAG TABLE DVFLAG: .BLKW 1 ; " MOV -2(R5),R0 ;LOOK FOR POINTER TO VECTOR TABLE BEQ BYHAND ;IF NOT THERE, JUST CALL HANDLER BY HAND MOV V$REQ(R0),IOSJ ;ELSE SAVE IOSTRT ADDRESS BITB #DX$NCA,-(R1) ;IF CACHED, SYNCH TO USER BNE DOIOS ; " .ADDR #SYNBLK,R4 ; " JSR R5,@$SYNCH(R5) ; " BR AKERR ; " DOIOS: MOV AKCQE,R1 ;POINT TO QEL CMP -(R1),-(R1) ; " MOV @R1,AKCQE ;REMOVE FROM LIST BNE 1$ ; " CLR AKLQE ; " 1$: JMP @(PC)+ ;AND CALL IOSTRT TO REQUEUE REQUEST IOSJ: .BLKW 1 ; " .ENDC ;////// TSX$P BYHAND: CALL $$MFPS(R5) ;*** DISABLE INTERRUPTS *** PUSH #340 ; " CALL $$MTPS(R5) ; " CLR AKLQE ;REMOVE QEL FROM OUR QUEUE CLR AKCQE ; " MOV @R3,R0 ;GET POINTER TO LAST QEL FOR REAL HANDLER BNE 1$ ;IF QUEUE IS EMPTY, MOV R4,(R3)+ ; MAKE THIS BE ONE AND ONLY ELEMENT MOV R4,(R3)+ ; " CALL $$MTPS(R5) ; RESTORE PSW JMP @R3 ; AND INVOKE REAL HANDLER 1$: MOV R4,Q$LINK(R0) ;ELSE LINK QEL TO END OF LIST MOV R4,@R3 ; " JMP $$MTPS(R5) ; RE-ENABLE INTERRUPTS AND RETURN ; HERE TO DIE WITH I/O ERROR AKERR:: MOV AKCQE,R4 ;GET POINTER TO QEL BIS #HDERR$,@-(R4) ;SET HARD ERROR BIT IN CHANNEL STATUS AKFIN:: .DRFIN AK ;AND RETURN WITH .DRFIN .SBTTL SPFUNS ; HERE FOR ATTACH SPFUN WITH TABLE POINTER IN R2, FUNCTION CODE IN R0, POINTER ; TO QUEUE ELEMENT IN R4, AND BASE OF RMON IN R5 IF TSX+. AKFUN:: CMPB R0,#FN$ATT ;IF WRONG FUNCTION, DIE BNE AKERR ; " MOV #AKB$L,R0 ;COPY TABLE INTO HANDLER .IF EQ,MMG$T ;\\\\\\ IF MEMORY MANAGEMENT MOV Q$BUFF(R4),R1 ; " 1$: MOVB (R1)+,(R2)+ ; " .IFF ;====== ELSE SJ 1$: CALL @$GTBYT ; " MOVB (SP)+,(R2)+ ; " .ENDC ;////// MMG$T SOB R0,1$ ; " .IF NE,TSX$P ;\\\\\\ IF TSX+, ADD $PNPTR(R5),R5 ;GET POINTER TO PNAME TABLE MOV R5,R1 ; AND SAVE A COPY 2$: CMP (R5)+,#-1 ;SEARCH THROUGH TABLE FOR -1 BNE 2$ ; " ADD R5,R1 ;COMPUTE ADDRESS OF DVFLAG TABLE ROR R1 ; " MOV R1,DVFLAG ; AND SAVE IT (DVFLAG+1, ACTUALLY) .ENDC ;////// TSX$P BR AKFIN ;AND RETURN ; ABORT ENTRY POINT AKABT:: NOP ; DUMMY INTERRUPT ENTRY POINT, SO AKINT WILL BE DEFINED AKINT:: PUSH R5 ;SAVE REGISTERS, JUST IN CASE PUSH R4 ; " .ADDR #AKBUF,R5 ;GET POINTER TO DATA BLOCK .IF NE,TSX$P ;\\\\\\ IF TSX+, INDEX BY JOB# .ASSUME AKB$L EQ 10 ; " .ASSUME <^C & > EQ BIC #^C,R4 ; " ASL R4 ; " ASL R4 ; " ASL R4 ; " ADD R4,R5 ; " .ENDC ;////// TSX$P CLR @R5 ;CLEAR HANDLER ADDRESS POP R4 ;RESTORE REGISTERS AND RETURN POP R5 ; " RETURN .SBTTL DATA AREAS ; AK ATTATCHMENT BLOCK AKADR:: .BLKW 1 ;ADDRESS OF PHYSICAL HANDLER AKSIZ:: .BLKW 1 ;SIZE OF DEVICE UNIT OR SUB-DEVICE FILE AKUNT:: .BLKB 1 ;UNIT# OF PHYSICAL DEVICE AKPNM:: .BLKB 1 ;$PNAME OFFSET OF PHYSICAL DEVICE AKOFS:: .BLKW 1 ;STARTING BLOCK# OF FILE ON PHYSICAL DEVICE AKB$L = .-AKADR ;LENGTH OF DATA BLOCK .IF NE,TSX$P ;\\\\\\ IF TSX+, AKBUF = AKADR-AKB$L ;DEFINE BASE ADDRESS OF TABLE .REPT MAXJOB ; AND ALLOCATE A BLOCK FOR EACH JOB (PLUS 1 EXTRA) .BLKB AKB$L ; " .ENDR SYNBLK::.WORD 0,0,0,0,0,-1,0 ;SYNCH ARG BLOCK .IFF ;====== ELSE NOT TSX+ AKBUF = AKADR ;DEFINE BASE ADDRESS OF TABLE .ENDC ;////// TSX$P .DREND AK .END