.page .TITLE COPYIO .IDENT /AV02.2/ ; ; (C) Copyright CERN, Geneva, 1980. ; All rights reserved. ; ; No part of this software may be reproduced, photocopied ; or translated to another program language without written ; permission of the copyright holder, the Director-General ; of CERN. ; However, permission will be freely granted for appropriate ; non-commercial use. ; CERN assumes no responsibility for the use or reliability ; of its software. ; ; Author: A. Vascotto ; ; Revisions: AV01.1 1-JUN-80 original version ; AV02.1 2-SEP-80 new scheme table driven ; AV02.1 18-SEP-80 table changed for new driver ; KE03.0 15-Mar-83 Connected Device Driver version. ; ;+ ; **COPYIO**-COPY I/O STRUCTURE TO A USER BUFFER ; ; PARAMETERS: ; 1- USER BUFFER ADDRESS ; 2- USER BUFFER LENGTH ; 3- ADDRESS OF A LONGWORD TO RECEIVE RETURNED LENGTH ; ; This routine produces a dump of a data base into a user buffer, ; according to the description given in a table. ; Each structure must be declared in the following way: ; ; label: st_type,off_to_first,num_bytes,off_to_link ; ; where ; label is any macro label ; st-type is a positive number identifying the structure ; off_to_first is the offset to the first byte to be dumped ; num_bytes is the number of bytes to be dumped ; it can be 0 if the structure is not to be ; dumped, but its sub-structures are ; off_to_link is the offset of the link to the next structure ; of the same type, if there is a chain ; to be set at -1 if not applicable ; ; Each structure definition may be followed by the list of ; sub-structures linked to it, with this format: ; ; .LONG label,off_to_sub ; ; where ; label is the label of the sub-structure definition ; off_to_sub is the offset to the pointer to the ; sub_structure ; ; Each structure definition (including its sub-structures) MUST ; be terminated by: ; ; .LONG 0 ; ; The first structure to be declared is the one which is pointed to ; by R4 as calculated in the user dependent part of the routine. ; The facility is offered of having many root structures, provided ; their distance (positive or negative) is known. ; This is obtained by declaring a pseudo-structure (not dumped) ; ; .LONG -1,displ ; ; where displ is the quantity added to R4 to calculate the new ; base address of a structure ; ; This declaration is valid only at root level, and must be ; preceded by a terminator and followed by a new declaration. ; ; The last root declaration MUST be followed by a terminator ; (i.e. the last terminator is: .LONG 0,0) ; ; This scheme allows you to generate tree structures attached to ; several roots having the same rank. The tree can have many ; branches originated at each node. ; ; The format of the dump produced for each structure is the following: ; ; .WORD st_type,num_bytes ; .ADDRESS first_word ; .WORD off_to_first,depth ; .BYTE structure ; ..... ; ; where ; st_type, num_bytes, off_to_first are as defined above ; first_word is the first word dumped (the address of it is ; generated) ; depth is the level of subordination of the structure, ; a root being at level 0 ; structure is the dump of the structure (num_bytes is ; the number of bytes following) ; ; The end of the dump is marked by a st_type equal to 0. ; ;- .LIBRARY/SYS$LIBRARY:LIB.MLB/ ; ; INTERNAL STRUCTURE DEFINITION ; $DEFINI STR $DEF STR_TYPE .BLKL 1 $DEF STR_BEG .BLKL 1 $DEF STR_LEN .BLKL 1 $DEF STR_LINK .BLKL 1 $DEF STR_SUB $DEFEND STR ; ; LOCAL STORAGE ; STACK_CNT: .WORD 0 ADDR_STR: .LONG 0 HEADER_STR: .LONG 0 ; START_STR: ; ; HERE BEGINS THE TABLE DRIVING THE DUMP ROUTINE ; ; **** THIS PART IS TO BE MODIFIED TO CHANGE THE DUMP ; DDB_TYPE = 1 TRACE_TYPE = 2 UCB_TYPE = 3 PTCB_TYPE = 4 READQ_TYPE = 5 WRITEQ_TYPE = 6 DONEQ_TYPE = 7 PENDINGQ_TYPE = 8 ; DDB_STR: .LONG DDB_TYPE,0,DDB$K_LENGTH,-1 .LONG TRACE_STR,DDB$L_DDT .LONG UCB_STR,DDB$L_UCB .LONG 0,0 TRACE_STR: .LONG TRACE_TYPE,TRACE$W_LEN-CD$DDT,TRACE$L_MRK+4-TRACE$W_LEN,-1 .LONG 0 UCB_STR: .LONG UCB_TYPE,0,UCB$K_SIZE,UCB$L_LINK .LONG PTCB_STR,UCB$L_PTCBQFL .LONG WRITEQ_STR,UCB$L_WRITEQFL .LONG DONEQ_STR,UCB$L_DONEQFL .LONG PENDINGQ_STR,UCB$L_IOQFL .LONG 0 PTCB_STR: .LONG PTCB_TYPE,0,PTCB$K_LENGTH,0 .LONG READQ_STR,PTCB$L_IOQFL .LONG 0 READQ_STR: .LONG READQ_TYPE,0,IRP$K_LENGTH,0 .LONG 0 WRITEQ_STR: .LONG WRITEQ_TYPE,0,IRP$K_LENGTH,0 .LONG 0 DONEQ_STR: .LONG DONEQ_TYPE,0,IRP$K_LENGTH,0 .LONG 0 PENDINGQ_STR: .LONG PENDINGQ_TYPE,0,IRP$K_LENGTH,0 .LONG 0 ; ; **** END OF CONFIGURATION ; .ENABL LSB .SBTTL COPYIO-COPY I/O STRUCTURE TO USER .ENTRY COPYIO,^M ; ; **** THIS PART DEPEND ON THE FIRST STRUCTURE TO BE DUMPED ; MOVAL G^IOC$GL_DEVLIST,R4 ; DDB POINTER MOVL #10,R0 MOVL 16(AP),R1 ; GET CONTROLLER ADDRESS MOVB (R1),R1 ; GET CHARACTER TSTB R1 ; IF NEGATIVE, FIRST CONTROLLER BLSS 20$ ADDB2 #^A/A/,R1 ; CORRECT 20$: MOVL (R4),R4 ; GET NEXT DDB BNEQ 10$ ; IF NEQ, MORE RET 10$: CMPW DDB$T_NAME+1(R4),#^A/CD/ ; IS A CD DEVICE BNEQ 20$ ; IF NEQ NO TSTB R1 ; IF NEGATIVE, FIRST CONTROLLER FOUND BLSS 15$ CMPB DDB$T_NAME+3(R4),R1 ; IS CORRECT CONTROLLER? BNEQ 20$ ; KEEP SEARCHING IF NOT ; ; HERE WE START WITH R4 SET TO DDB ; ; **** END OF DEPENDENT PART ; 15$: MOVL 4(AP),R2 ; DEST. ADDRESS MOVL 8(AP),R1 ; MAX. BUFFER LENGTH CLRW STACK_CNT ; CLEAR STACK COUNTER MOVL #START_STR,R6 ; ADDRESS OF FIRST ROOT ; LOOP: TSTL STR_TYPE(R6) ; CHECK TYPE BGTR NEXT_STR ; IF GTR THERE IS A NEW ONE BLSS SKIP ; SKIP PRIMARY SPACE BRW EXIT ; NO ROOT LEFT ; SKIP: ADDL2 #4,R6 ; POINT TO SKIP SIZE ADDL2 (R6)+,R4 ; SKIP AND POINT TO NEXT ROOT BRB LOOP ; NEXT_STR: ADDL3 #STR_SUB,R6,R5 ; POINTS TO SUB-STRUC. LIST ADDL3 STR_BEG(R6),R4,ADDR_STR ; GET STARTING ADDR. ; MOVL #2,R0 ; SET LENGTH MOVAB STR_TYPE(R6),R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE TYPE ; MOVL #2,R0 ; SET LENGTH MOVAB STR_LEN(R6),R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE LENGTH ; MOVL #4,R0 ; SET LENGTH MOVAB ADDR_STR,R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE ADDRESS ; MOVL #2,R0 ; SET LENGTH MOVAB STR_BEG(R6),R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE OFFSET ; MOVL #2,R0 ; SET LENGTH MOVAB STACK_CNT,R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE DEPTH LEVEL ; MOVL STR_LEN(R6),R0 ; SET LENGTH BLEQ NEXT_SUB ; IF LEQ DO NOT DUMP MOVL ADDR_STR,R3 ; SET SOURCE ADDRESS BSBW COPY ; COPY THE WHOLE STRUCTURE ; NEXT_SUB: TSTL (R5) ; ANY SUBORDINATE BRANCH ? BLEQ NO_SUB ; IF LEQ NO MORE SUB IN THE LIST ; PUSHR #^M ; YES: SAVE CONTEXT INCW STACK_CNT ; PUSH ONE MOVL (R5)+,R6 ; SET SUB-STR. LIST POINTER ADDL2 (R5),R4 ; GET STRUCT. POINTER ADDR. ; MOVL R4,HEADER_STR MOVL R4,R7 ; ANY_MORE_SUB: MOVL R4,R8 ; SAVE TO CHECK REFLEXIVE LOOP MOVL (R4),R4 ; GET NEW STRUC. POINTER BEQL NO_MORE_SUB CMPL R4,R8 ; REFLEXIVE? BEQL NO_MORE_SUB ; POINTING TO ITSELF. ; CMPL R4,HEADER_STR CMPL R4,R7 BNEQ NEXT_STR ; IF NEQ ANOTHER LINKED ; NO_MORE_SUB: TSTW STACK_CNT ; ROOT LEVEL ? BGTR POP_LEVEL ; IF GTR NO ; ADDL3 #4,R5,R6 ; GET NEXT ROOT BRW LOOP ; POP_LEVEL: POPR #^M ; RESTORE CONTEXT DECW STACK_CNT ; POP ONE ADDL2 #8,R5 ; POINTS TO NEXT SUB-STR. BRB NEXT_SUB ; NO_SUB: TSTL STR_LINK(R6) ; ANY MORE LINKED ? BLSS NO_MORE_SUB ; IF LSS NO ; ADDL2 STR_LINK(R6),R4 ; POINTS TO NEXT STRUC. ; MOVL (R4),R7 BRB ANY_MORE_SUB EXIT: BSBB CLR1 ; MARK END OF DUMP ; SUBL3 R1,8(AP),@12(AP) ; RETURN # OF BYTES MOVL #SS$_NORMAL,R0 RET ; .PAGE .SBTTL COPY-COPY BYTES FROM SOURCE TO DESTINATION ; COPY- ; INPUT: R0= NUMBER OF BYTES TO BE TRANSFERED ; R1= NUMBER OF BYTES LEFT IN OUTPUT BUFFER ; R2= DESTINATION POINTER ; R3= SOURCE POINTER ; ; OUTPUT: BYTES ARE COPIED ; COPY: TSTL R1 ; IS COUNTER DOWN TO 0 ? BEQL 100$ ; IF EQL YES DECL R1 ; ACCOUNT FOR NEXT MOVB (R3)+,(R2)+ ; COPY SOBGTR R0,COPY ; IF GTR, MORE 100$: RSB ; .PAGE .SBTTL CLR1-CLEAR BYTES OF DESTINATION ; CLR1- ; INPUT: R0= NUMBER OF BYTES TO BE CLEARED ; R1= NUMBER OF BYTES LEFT IN OUTPUT BUFFER ; R2= DESTINATION POINTER ; ; OUTPUT: BYTES ARE CLEARED ; CLR1: MOVZWL #4,R0 ; SET FOR ONE LONG WORD CLRN: TSTL R1 ; IS COUNTER DOWN TO 0 ? BEQL 110$ ; IF EQL YES DECL R1 ; ACCOUNT FOR NEXT CLRB (R2)+ ; CLEAR SOBGTR R0,CLRN ; IF GTR, MORE 110$: RSB .END