.TITLE PCACP - PAPER TAPE READER/PUNCH ACP  .IDENT /V02/  d;++ ; ,; PCACP - PAPER TAPE READER/PUNCH ACP ; ; THE PAPER TAPE ACP IS INTENDED TO SERVE AS A MODEL FROM X; WHICH MORE USEFUL ACPS CAN BE CONSTRUCTED. THE ACP ONLY ; SERVES THE MOUNT, ACPCONTROL, AND WRITEOF I/O FUNCTION CODES. ; ; PROGRAMMER ; L; VIK MUIZNIEKS JULY -- 1979 ; ;-- x; ; DEFINE SYMBOLS AND OFFSETS (SOME FROM LIB.MLB) @;  $AQBDEF  $JPIDEF l $UCBDEF  $VCBDEF 4 $IODEF  $SSDEF  $IRPDEF ` $IPLDEF $PRDEF ; ( ; DEFINE CONSTANTS USED BY THE ACP ; PC_ACP_TYPE=200 ; PAPER TAPE ACP TYPE T ; ; LOCAL STORAGE  ; AQB_HEAD: .LONG ; AQB HEADER ADDRESS PID: .BLKL 1 ; ACP PROCESS ID H ; ; LIST OF ITEMS FOR $GETJPI TO RETRIEVE ; tGETLIST:.WORD 4 ; LENGTH OF BUFFER  .WORD JPI$_PID ; REQUEST PID < .LONG PID ; ADDR. TO RECEIVE PID  .LONG 0 ; NO LENGTH REQUIRED  .LONG 0 ; END OF GETLIST h; ; ADDRESSES FOR LOCK WORKING SET SYSTEM SERVICE 0; LKWSET: .LONG START_LOCK ; STARTING ADDRESS  .LONG END_LOCK ; ENDING ADDRESS \; ; ENTRY POINT INTO ACP $; START: .WORD 0 ; NULL ENTRY MASK  $CMKRNL_S B^BEGIN ; CHANGE MODE TO KERNEL P RET ; GET HERE ONLY IF ERROR BEGIN: .WORD 0 ; SAVE NO REGISTERS  $GETJPI_S ITMLST=GETLIST ; GET ACP PID  MOVAB G^IOC$GL_AQBLIST,R1 ; GET ACP LIST HEAD  MOVL (R1),R0 ; POINT TO FIRST AQB D10$: CMPL W^PID,AQB$L_ACPPID(R0) ; FOUND RIGHT AQB?  BEQL FOUND ; IF EQL, YES  MOVL AQB$L_LINK(R0),R0 ; GET NEXT LINK p BNEQ 10$ ; AND LOOP 8 MOVL #SS$_NOAQB,R0 ; AQB NOT FOUND  RET FOUND: L MOVL R0,AQB_HEAD ; SAVE AQB ADDRESS  BBSC #AQB$V_CREATING,AQB$B_STATUS(R0),10$ ; FOR SYNCH.  MOVZWL #SS$_WRONGACP,R0 ; RETURN ERROR STATUS  RET ; IF NOT IN SYNCH 10$: $LKWSET_S W^LKWSET ; LOCK IODONE IN W.S.  ;  ;#############################################  ;#############################################  ; THIS IS WHERE YOU WOULD PUT ANY OTHER ONE-  ; TIME INITIALIZATION CODE (E.G., ASSIGNING  ; CHANNELS TO DEVICES, INITIALIZING QUEUES,  ; COUNTERS, POINTERS, ETC.  ;#############################################  ;#############################################  ;  BRW ACP_MAIN ; TRY TO DEQUE IRP l HIBER: $HIBER_S ; WAIT FOR IRP ACP_MAIN: 4! MOVL AQB_HEAD,R2 ; GET AQB ADDRESS ! REMQUE @(R2),R3 ; LOOK FOR IRP ! BVC 10$ ; IF VC, FOUND IRP `"; "; NOTHING IN QUEUE, SEE IF TIME TO DISMOUNT (#; # TSTB AQB$B_MNTCNT(R2) ; ANY VOLUMES MOUNTED? # BNEQ HIBER ; IF NEQ, YES T$ BSBW CHK_ACP_DONE ; TIME TO DISMOUNT? $ BRB ACP_MAIN ; DIDN'T DISMOUNT SINCE % ; AN IRP IN AQB QUEUE %10$: %; H&; THERE WAS AN IRP IN THE AQB QUEUE &; ' MOVL IRP$L_UCB(R3),R5 ; GET UCB ADDRESS t' MOVW IRP$W_FUNC(R3),R7 ; GET I/O FUNC. CODE '; <(; CHECK I/O FUNCTION CODE (; ) CMPZV S^#IO$V_FCODE,S^#IO$S_FCODE,R7,-; CHECK FOR MOUNT h) S^#IO$_MOUNT ; FUNCTION CODE ) BEQL MOUNT ; FOUND MOUNT IF EQL 0* CMPZV S^#IO$V_FCODE,S^#IO$S_FCODE,R7,-; CHECK FOR WRITEOF * S^#IO$_WRITEOF ; FUNCTION CODE * BEQL WRITEOF ; FOUND WRITEOF IF EQL + CMPZV S^#IO$V_FCODE,S^#IO$S_FCODE,R7,-; CHECK FOR ACPCONTROL + S^#IO$_ACPCONTROL ; FUNCTION CODE + BEQL ACPCONTROL ; FOUND IF EQUAL \+ MOVL #SS$_ILLIOFUNC,R0 ; I/O FUNC ILLEGAL + BSBW BAD_IO ; REPORT IT $, BRW ACP_MAIN ; GET NEXT IRP ,MOUNT: MOVL #SS$_WRONGACP,R0 ; ASSUME WRONG ACP , CMPB #PC_ACP_TYPE,AQB$B_ACPTYPE(R2) ; CHECK ACP TYPE P- BNEQ 10$ ; IF NEQ, ERROR - BISL #DEV$M_MNT,UCB$L_DEVCHAR(R5) ; SET MOUNTED BIT . BSBW GOOD_IO ; QUEUE SUC. IRP |. BRW ACP_MAIN ; GET NEXT IRP .10$: BSBW BAD_IO ; ERROR IN IRP D/ BRW ACP_MAIN ; GET NEXT IRP /WRITEOF: 0 MOVW #IO$_WRITEVBLK,IRP$W_FUNC(R3) ; CHANGE FUNCTION CODE 0 ; 0 ;############################################### *0 ;############################################### 40 ; HERE IS WHERE YOU WOULD EXTRACT, MODIFY, OR >0 ; INSERT FIELDS IN THE IRP, AND DO WHATEVER IT H0 ; IS THAT YOUR ACP DOES (MANAGE QUEUES, ISSUE R0 ; QIOS, ETC.). IT IS AT THIS POINT WHERE THE \0 ; "ACP-SPECIFIC" PARTS OF YOUR ACP ARE PLACED. f0 ;############################################### k0 ;############################################### m0 ; p0 JSB G^EXE$INSIOQ ; QUEUE IRP TO DRIVER z0 ; AT START I/O ENTRY PT. 0 ; (MUST HAVE R3=IRP ADDR 81 ; AND R5=UCB ADDRESS) Y1 MOVL UCB$L_VCB(R5),R0 ; GET VCB ADDRESS z1 DECW VCB$W_TRANS(R0) ; ANOTHER TRANS. DONE 1 BSBW DMT_CHK ; CHECK FOR DISMOUNT 2 ; (NOTE IOPOST INVOKED d2 ; BY DRIVER) 2 BRW ACP_MAIN ; GET NEXT IRP 2ACPCONTROL: 2 BSBW GOOD_IO ; COMPLETE IMMEDIATELY 2 ; 2 ; ACPCONTROL QIO USED TO AWAKEN ACP FROM 2 ; HIBERNATION SO THAT ACP WILL DISMOUNT 3 ; ITSELF WHEN DISMOUNT BIT SET IN UCB BY 3 ; DISMOUNT IMAGE (PCDMT). 3 ; '3 BRW ACP_MAIN ; PROCESS NEXT IRP IF )3 ; ACP NOT DISMOUNTING ,3; 3; CHK_ACP_DONE 3; X4; THIS SUBROUTINE CHECKS TO SEE IF THE ACP SHOULD BE 4; DISMOUNTED. IF SO, IT RELEASES SYSTEM RESOURCES, AND 5; DELETES THE ACP PROCESS. IF THE ACP SHOULD NOT BE 5; DISMOUNTED, IT SIMPLY RETURNS. 5; L6; CALLED VIA BSB INSTRUCTION 6; 7; INPUTS: x7; 7; R2 = AQB ADDRESS @8; 8; SIDE EFFECTS: 9; l9; ACP MAY BE DELETED 9; R0 AND R1 DESTROYED 4:; :CHK_ACP_DONE: : CALLS #0,W^LOCKDB ; LOCK I/O DATA BASE `; CMPL AQB$L_ACPQFL(R2),R2 ; ANY I/O IN QUEUE? ; BNEQ 100$ ; IF NEQ, YES (<; <; NO MORE I/O -- DELETE ACP AFTER REMOVING AQB FROM LIST <; T= MOVAB G^IOC$GL_AQBLIST,R1 ; GET LIST ADDRESS = MOVL (R1),R0 ; GET 1ST AQB POINTER > CMPL R2,R0 ; FOUND RIGHT AQB? > BNEQ 20$ ; IF NEQ, NO > MOVL AQB$L_LINK(R2),(R1) ; RELINK H? BRB 40$ ; DEALLOCATE AQB ?20$: CMPL AQB$L_LINK(R0),R2 ; FOUND AQB? @ BEQL 30$ ; IF EQL, YES t@ MOVL AQB$L_LINK(R0),R0 ; GET NEXT AQB @ BRB 20$ ; LOOP ; SAVE REGISTERS \ MOVAL G^IOC$GL_MUTEX,R0 ; GET I/O DATABASE MUTEX \ MOVL G^SCH$GL_CURPCB,R4 ; GET PCB ADDRESS \ JSB G^SCH$LOCKW ; LOCK MUTEX \ RET \UNLOCKDB: .WORD ^M ; SAVE REGISTERS \ MOVAL G^IOC$GL_MUTEX,R0 ; GET I/O DATABASE MUTEX \ MOVL G^SCH$GL_CURPCB,R4 ; GET PCB ADDRESS \ JSB G^SCH$UNLOCK ; UNLOCK MUTEX \ SETIPL #0 ; LOWER IPL \ RET \END_LOCK: ; LABEL FOR LKWSET \ .END START