.TITLE SCH .IDENT /4.0/ ;+ ; SCH -- MODIFY RSX11M V4.0 TIME SHARING PARAMETERS (ROUND ROBIN/SWAP ; TIMES, PRIORITIES) AND SHUFFLER CONTROL PARAMETER. ; WRITTEN BY: ; JAMES G. DOWNWARD ; KMS FUSION,INC ; 3941 RESEARCH PARK DR. ; ANN ARBOR, MICH. 48104 ; (313)-769-8500 ; ; ; The task SCH (for schedule) is used to display and modify RSX11M'S ; timesharing parameters, ie the Round Robin interval and the swap interval, ; the round robin priority range, the low level for the swap priority range, ; and the time delay (in tics) befor SHF can run again. ; ; RSX11M V4.0 now has locations where the time delay between SHF requests, ; the round robin interval, and the swap interval are stored, so this task ; can display and modify those values without having to SLP the executive. ; ; Minor sanity checks are performed, ie, a swap time less than the round robin ; interval is not allowed. However all other reasonable combinations will be ; accepted even if they would not realy be suitable. One reason for this is ; that 'suitable' for one system would be unsuitable for another. The ; situation is goverened by core size, the speed and size of disks, and the ; amount of swapping going on (ie how heavily loaded the system is). ; ; In order for this program to work, in all its glory, TDSCH.SLP must ; have been applied to TDSCH.MAC, and a SYSGEN done to incorporate the ; EXEC modification. However, an assembly conditional allows SCH to be ; assembled to use just the symbols defined in an unmodified EXEC. The ; exec mod will work with any system regardless of whether or not this program ; is used. It is as harmless as any EXEC mod can be since it involves no new ; code. Rather is forces the assembly time paramters for round robin schedul- ; ing and executive level disk swapping to appear in locations which are ; global symbols. ; ; COMMAND SYNTAX: ; SCH /SW1[/SW2/SW3] ; WHERE THE SWITCHES ARE ; ; /DSP - Display the scheduling parameters ; /RBN:N - Set the round robin interval to N tics ; * /RBH:n - Set the high priority level for Round Robining ; * /RBL:n - Set the low priority level for Round Robining ; /SWP:N - Set the swap interval to N tics. ; * /SWL:N Set the lower limit to decrement swap priority to ; /MSF:N - Set the minimum # of tics between SHF requests ; ; * - Requires the SLP patch to TDSCH.MAC ; ; If /DSP is seen, it displays the value of the other switches after their ; value is placed in the EXEC. ; ; As mentioned, a small exec mod may be made (TDSCH.SLP may be used ; to do this). Because of the way the locations to SLP are found, this file ; should be relatively immune to any changes DEC makes to TDSCH. If SLP ; patch is not made, SCH will not be able to display or set the Round Robin ; priority range or the lower limit for decrementing swapping priorities. ; ; If the target system has incorporated the KMS SYSTEM accounting package, ; this task will also display the various system performance parameters (# SHF ; runs, # checkpoints, # loader requests, # tasks run , etc.) ; ; THIS TASK MAY BE BUILT ; ; MAC SCH.OBJ;1=LB:[1,1]EXEMC/ML,[11,10]RSXCM/PA:1,SY:[UIC]SCH ; TKB SCH.TSK;1/PR/CP=SCH.OBJ;1 ; / ; TASK=...SCH ; PRI=50 ; // ;- ;+ ; ASSEMBLY PARAMETERS ; ; If one wishes to use this task without applying a SLP patch to ; TDSCH.MAC, comment out the symbol KMS. SCH will then display EXEC TIME ; sharing parameters but one will not be able to change the high/low ; Round Robin priority range or the low Swap priority level ; KMS=1 ; IF DEFINED, REQUIRE the TDSCH PATCH ; ;- .MCALL UCBDF$,TCBDF$,HWDDF$,EXIT$S,SDAT$,RQST$,QIOW$,DIR$,USTP$ .MCALL EXST$S,RCST$,STOP$S .MCALL GMCR$ TCBDF$ ; DEFINE TCB OFFSETS HWDDF$ ; DEFINE HARDWARE OFFSETS UCBDF$ ; DEFINE UCB OFFSETS .IF NDF R$$NDC .ERROR ; ROUND ROBIN SCHEDULING NOT BUILT IN .ENDC .IF NDF S$$WPC ; .ERROR ; EXECUTIVE LEVEL DISK SWAPING NOT SUPPORTED .ENDC ; ; ; LOCAL MACROS ; .MACRO PRINT STRING MOV #STRING,R0 CALL PNTLIN .ENDM PRINT ; ; ERROR MESSAGES ; .ENABL LC .EVEN M1: .ASCIZ <15><12>/SCH -- Fatal, not a privleged terminal./ M2: .ASCIZ <15><12>/SCH -- Fatal, command switches are missing./ M3: .ASCIZ <15><12>/SCH -- Fatal, command error./ M4: .ASCIZ <15><12>/SCH -- Fatal, syntax error./ M5: .ASCIZ <15><12>/SCH -- Fatal, illegal switch./ M6: .ASCIZ <15><12>/SCH -- Fatal, illegal schedule interval./ M7: .ASCIZ <15><12>/SCH -- Fatal, illegal Round Robin priority range./ M8: .ASCIZ <15><12>/SCH -- Fatal, illegal Swap range./ M9: .ASCII <15><12>/SCH -- Fatal, Priorities may not be modified./ .ASCIZ <15><12>/ TDSCH must be SLPed/ .EVEN ; ; SCHEDULE DISPLAY MESSAGES ; SCHHDR: .ASCII <15><12>/RSX11M Timesharing Scheduling Parameters/ RBNTIM: .ASCII <15><12>/ Round Robin Interval (tics) = / RBNTM: .ASCIZ / / RBNPRH: .ASCII <15><12>/ Round Robin Priority (high) = / RBNHI: .ASCIZ / / RBNPRL: .ASCII <15><12>/ Round Robin Priority (low) = / RBNLO: .ASCIZ / / SWPTIM: .ASCII <15><12>/ Exec Swaping Interval (tics) = / SWPTM: .ASCIZ / / SWPPRH: .ASCII <15><12>/ Swaping Priority (high) = / SWPHI: .ASCIZ / / SWPPRL: .ASCII <15><12>/ Swaping Priority (low) = / SWPLO: .ASCIZ / / SHFDLY: .ASCII <15><12>% SHF request delay (tics) = % DLYSHF: .ASCIZ / / .IFDF S$$ACC ; IF KMS ACCOUNTING USED PERFRM: .ASCIZ <15><12><12>/RSX11M Global Performance Statistics/ RUNCNT: .ASCII <15><12>/ # RUN Requests = / RUNVL: .ASCIZ / / SHFCNT: .ASCII <15><12>/ # SHF Requests = / SHFVL: .ASCIZ / / CKPCNT: .ASCII <15><12>/ # Checkpoints = / CKPVL: .ASCIZ / / LDRCNT: .ASCII <15><12>/ # LDR Requests = / LDRVL: .ASCIZ / / .ENDC TICVAL: .ASCII / / ; 6 BLANK SPACES ; ; FLAGS TO INDICATE SWITCHES FOUND AND LOCAL DATA STORAGE .EVEN DSPFLG: .WORD 0 ; IF =1 DISPLAY VALUES ON EXIT NEGFLG: .WORD 0 ; IF <>0, NEGATIVE VALUE IS OK RBNVAL: .WORD 0 ; HOLD VALUE RBHVAL: .WORD R$$NDH ; HOLD VALUE OF HIGH LEVEL ROUND ROBIN PRI RBLVAL: .WORD R$$NDL ; HOLD VALUDE OF LOW LEVEL ROUND ROBIN PRI SWPVAL: .WORD 0 ; HOLD VALUE OF SWAP INTERVAL SWHVAL: .WORD S$$WPR ; HOLD VALUE OF SWAP HIGH PRIORITY SWLVAL: .WORD -S$$WPR ; HOLD VALUE OF SWAP LOW PRIORITY MINVAL: .WORD S$$HFC ; HOLD VALUE OF SHFDLY (IN TICS) ; DIRECTIVE PARAMETER BLOCKS ; QIODPB: QIOW$ IO.WVB,2,2,,,,<0,0,0> ; WRITE TO TERMINAL GMCR: GMCR$ ; GET COMMANDLINE DPB BUF: .BLKW 40 ; BUFFER FOR TERMINAL OUTPUT .WORD 0 ; SENTINAL ; ; SWITCH TABLE ; SWTAB: .RAD50 /DSP/ .RAD50 /RBN/ .RAD50 /RBL/ .RAD50 /RBH/ .RAD50 /SWP/ .RAD50 /SWL/ .RAD50 /MSF/ ENDTAB: ; ; ; JUMP TABLE TO PROCESSING ROUTINES ; JMPTAB: .WORD DSPLAY ; DISPLAY TIME SHARING PARAMETERS .WORD ROBIN ; SET NEW ROUND ROBIN INTERVAL .WORD RPRILO ; SET NEW ROUND ROBIN LOW PRIORITY .WORD RPRIHI ; SET NEW ROUND ROBIN HIGH PRIORITY .WORD SWAP ; SET NEW SWAP INTERVAL .WORD SPRILO ; SET NEW LOW SWAP PRIORITY .WORD SHFTIM ; SET MAX NUMBER SHF RUNS .SBTTL START OF PROGRAM SCH: ; REF LABLE MOV $RNDCT,RBNVAL ; STORE VALUES FOR LATER COMPARISON .IFDF KMS ; IF KMS MODS IN MOV RNDH,RBHVAL ; MOV RNDL,RBLVAL ; .ENDC MOV $SWPCT,SWPVAL ; SINCE USER MAY WISH TO SET ONLY ONE .IFDF KMS MOV $SWPRL,SWLVAL ; .ENDC MOV $SHFCT,MINVAL ; MOV $TKTCB,R0 ; FIRST GET OUR TCB MOV T.UCB(R0),R0 ; THEN OUR UCB ADDRESS BIT #U2.PRV,U.CW2(R0) ; IS TERMINAL PRIVLEGED BNE 2$ ; IF NE, YES PRINT M1 ; WARN THAT TERMINAL IS NOT PRIVLEGED 1$: JMP ERRXIT ; AND EXIT WITH SEVERE ERROR 2$: ; REF LABLE DIR$ #GMCR ; GET MCR COMMAND LINE BCC 10$ ; NO ERROR, SO PROCEED PRINT M3 ; COMMAND ERROR BR 1$ ; AND EXIT 10$: MOV #GMCR+G.MCRB,R5 ; GET ADDRESS OF MCR COMMAND LINE CMP $DSW,#7. ; SEE IF ANY COMMANDS PRESENT BGE 20$ ; MUST HAVE AT LEAST 7 CHARACTERS IN LINE PRINT M2 ; OR ELSE NO VALID COMMAND PRESENT BR 1$ ; AND EXIT 20$: ADD #1,R5 ; POINT TO WHERE WE EXPECT A SPACE 25$: INC R5 ; BUMP COUNTER CMPB (R5),#15 ; IS IT A BNE 27$ ; IF NE , NO, CONTINUE SCAN JMP ENDUP ; IF EQ, YES, ENDUP AS APPROPRIATE 27$: CMPB (R5),#33 ; IS IT AN BNE 28$ ; IF NE,NO, CONTINUE JMP ENDUP ; IF EQ, YES, ENDUP AS APPROPRIATE 28$: CMPB (R5),#'/ ; IS IT A SWITCH BNE 25$ ; IF NE, NO IT ISN'T, CONTINUE SCAN INC R5 ; BUMP PAST / CALL KEYWRD ; SCAN FOR KEYWORD BR 25$ ; AND SCAN LINE FOR MORE ;+ ; KEYWRD -- SCAN THROUGH THE SWITCH TABLE LOOKING FOR A MATCH ; IF A MATCH IS FOUND, EXECUTE AN @CALL VIA THE ; JMP TABLE TO THE PROCESSING ROUTINE. ; IF NO MATCH IS FOUND , DECLARE AN ILLEGAL KEYWORD ERROR ; AND EXIT WITH GRACE. ;- KEYWRD: ; MOV R5,R0 ; POINTER TO THE NEXT THREE BYTES CLR R1 ; CONTROL FOR $CAT5(DO NOT CONTROL DOTS) CALL $CAT5 ; CONVERT 3 BYTES TO ONE RAD50 WORD IN R1 MOV #SWTAB,R4 ; NOW WE WILL SEARCH COMMAND TABLE FOR MATCH 10$: CMP R1,(R4)+ ; DO WE HAVE A MATCH BEQ 20$ ; YES WE DO CMP R4,#ENDTAB ; ARE WE AT END BLO 10$ ; IF LO, NO, LOOK SOME MORE PRINT M5 ; ILLEGAL COMMAND SWITCH JMP ERRXIT ; EXIT WITH ERROR STATUS 20$: ; CALL @JMPTAB-SWTAB-2(R4) ; JUST LIKE IN CCL RETURN ROBIN: CALL GETVAL ; PARSE COMMAND AND GET VALUE FOR INTERVAL MOV R1,RBNVAL ; KEEP VALUE RETURN ; BACK FOR MORE RPRILO: .IFDF KMS ; IF TDSCH/SYSCM PATCHES INSTALLED CALL GETVAL ; PARS COMMAND AND GET VALUE MOV R1,RBLVAL ; SAVE VALUE RETURN ; BACK FOR MORE .IFF ; IF TDSCH/SYSCM PATCHES NOT MADE PRINT M9 ; WARN USER JMP ERRXIT ; AND EXIT .ENDC RPRIHI: .IFDF KMS ; IF TDSCH/SYSCM PATCHES INSTALLED CALL GETVAL ; PARSE COMMAND AND GET VALUE MOV R1,RBHVAL ; SAVE VALUE RETURN ; BACK FOR MORE .IFF ; IF TDSCH/SYSCM PATCHES NOT MADE PRINT M9 ; WARN USER JMP ERRXIT ; AND EXIT .ENDC SWAP: CALL GETVAL ; GET INTERVAL VALUE MOV R1,SWPVAL ; KEEP VALUE RETURN ; BACK FOR MORE SPRILO: .IFDF KMS ; IF TDSCH/SYSCM PATCHES INSTALLED INC NEGFLG ; SHOW NEGATIVE VALUE OK CALL GETVAL ; GET INTERNAL VALUE CLR NEGFLG ; NEG VALUE NOT OK NEXT TIME MOV R1,SWLVAL ; KEEP VALUE RETURN ; .IFF ; IF TDSCH/SYSCM PATCHES NOT MADE PRINT M9 ; WARN USER JMP ERRXIT ; AND EXIT .ENDC SHFTIM: CALL GETVAL ; PARSE COMMAND AND GET VALUE FOR INTERVAL MOV R1,MINVAL ; KEEP VALUE RETURN ; BACK FOR MORE DSPLAY: INC DSPFLG ; SET DISPLAY FLAG RETURN ; AND LOOK FOR MORE GETVAL: ; REF LABLE CLR R3 ; CLEAR COUNTER MOV #TICVAL,R0 ; WHERE WE WILL PUT NUMBER 1$: CMPB (R5),#15 ; CR IS ILLEGAL HERE BNE 10$ ; IF NE, OK 5$: PRINT M4 ; A CR HERE IS SYNTAX ERROR JMP ERRXIT ; EXIT WITH ERROR STATUS 10$: CMPB (R5),#33 ; AN ESC IS ALSO ILLEGAL BEQ 5$ ; SO EXIT WITH ERROR CMPB (R5),#'/ ; A '/' HERE UNTIL AFTER NUMBER IS ILLEGAL BEQ 5$ ; SO EXIT WITH ERROR IF FOUND CMPB (R5)+,#': ; HAVE WE GOT ':' BEQ 20$ ; IF EQ, YES, LOOK FOR NUMBER BR 1$ ; AND LOOK SOME MORE 20$: ; CMPB (R5),#15 ; IS A RIGHT AFTER ':' BEQ 5$ ; IF EQ, YES, SYNTAX ERROR CMPB (R5),#33 ; PERHAPS ITS AN ESC RIGHT AFTER ':' BEQ 5$ ; IF EQ, YES, ITS A FATAL SYNTAX ERROR 25$: TST NEGFLG ; ARE NEGATIVE VALUES OK BEQ 40$ ; IF EQ, NO, SKIP TEST CMPB (R5),#'- ; IS IT A MINUS SIGN BNE 40$ ; IF NE, NO INC NEGFLG ; YES, LEAVE A CANDEL LIT INC R5 ; POINT PAST MINUS SIGN 40$: CMPB (R5),#'0 ; IS IT >=0 BLT 50$ ; IF LT, ASSUME NUMBER DONE, TRY TO CONVERT IT CMPB (R5),#'9 ; IS IT <=9 BGT 5$ ; IF GT 9 BEFORE ENCOUNTERING A '/', ; ITS A SYNTAX ERROR INC R3 ; KEEP TRACK OF THE NUMBER OF CHARACTERS CMP R3,#5 ; IS IT GREATER THAN 5 BGT 5$ ; IF YES, SYNTAX ERROR MOVB (R5)+,(R0)+ ; IF NO, MOVE INTO TICVAL BR 40$ ; GET ANOTHER NUMBER 50$: ; CMPB (R5),#'/ ; IS IT A '/' BEQ 60$ ; A '/' IS OK CMPB (R5),#15 ; IS IT EOL BEQ 60$ ; EOL IS OK ALSO CMPB (R5),#33 ; IS IT ESC BEQ 60$ ; AN ESC FOR EOL OK ALSO BR 5$ ; ANYTHING ELSE IS FATAL SYNTAX ERROR 60$: ; MOVB #'*,(R0) ; SET A NON NUMERIC CHARACTER TO TERMINATE ; CONVERSION MOV #TICVAL,R0 ; GET ADDRESS OF ASCII STRING CALL $CDTB ; CONVERT TO DECIMAL TST R1 ; IS IT >0 BNE 65$ ; IF NE,YES TST NEGFLG ; # IS 0, THIS IS ONLY OK IF NEGFLG SET BNE 65$ ; IF NE, SET SO IS OK 63$: PRINT M6 ; WARN USER, DELTA VALUE IS ILLEGAL JMP ERRXIT ; AND EXIT WITH ERROR 65$: DEC R5 ; BACK UP POINTER TO BEFORE /(IF ANY) CMP NEGFLG,#2 ; SHOULD WE NEGATE VALUE BNE 70$ ; IF NE, NO NEG R1 ; MAKE IT A NEGATIVE VALUE 70$: RETURN ; ;+ ; DSP DISPLAY THE DATA ON THE RSX11M TIME SHARING PARAMETERS ; ;- DSP: MOV $RNDCT,R1 ; GET THE SAMPLE INTERVAL VALUE MOV #RBNTM,R0 ; ADDRESS OF WHERE TO PLACE TIME NUMBER CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT SCHHDR ; PRINT OUT HEADER AND ROUND ROBIN TIME MOV RBHVAL,R1 ; GET HIGH PRIORITY RANGE MOV #RBNHI,R0 ; ADDRESS OF WHERE TO PLACE HIGH PRIORITY CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT RBNPRH ; PRINT OUT HIGH PRIORITY MOV RBLVAL,R1 ; GET LOW PRIORITY RANGE MOV #RBNLO,R0 ; ADDRESS OF WHERE TO PLACE LOW PRIORITY CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT RBNPRL ; PRINT OUT LOW PRIORITY MOV $SWPCT,R1 ; GET SWAPING INTERVAL MOV #SWPTM,R0 ; GET OUTPUT STRING ADDRESS CLR R2 ; SUPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT SWPTIM ; WRITE IT OUT MOV SWHVAL,R1 ; GET HIGH SWAP PRIORITY MOV #SWPHI,R0 ; ADDRESS OF WHERE TO PLACE VALUE CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT SWPPRH ; WRITE IT OUT MOV SWLVAL,R1 ; GET LOW SWAP PRIORITY MOV #SWPLO,R0 ; ADDRESS OF WHERE TO PLACE VALUE CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDSG ; CONVERT TO DECIMAL ASCII PRINT SWPPRL ; WRITE IT OUT MOV $SHFCT,R1 ; GET SWAPING INTERVAL MOV #DLYSHF,R0 ; GET OUTPUT STRING ADDRESS CLR R2 ; SUPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT SHFDLY ; WRITE IT OUT .IFDF S$$ACC ; IF KMS ACCOUNTING USED PRINT PERFRM ; Print out header MOV $RUNRQ,R1 ; Get # of run requests MOV #RUNVL,R0 ; Get where to place output string CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII PRINT RUNCNT ; MOV $SHFRQ,R1 ; Get # of SHF requests MOV #SHFVL,R0 ; Get where to place output string CLR R2 ; Suppress leading zeros CALL $CBDMG ; Convert to Decimal ASCII PRINT SHFCNT ; Print it out MOV $CKPRQ,R1 ; Get # of CKP requests MOV #CKPVL,R0 ; Get where to place output string CLR R2 ; Suppress leading zeros CALL $CBDMG ; Convert to Decimal ASCII PRINT CKPCNT ; Print it out MOV $LDRQ,R1 ; Get # of LDR requests MOV #LDRVL,R0 ; Get where to place results CLR R2 ; Suppress leading Zeros CALL $CBDMG ; convert to Decimal ASCII PRINT LDRCNT ; .ENDC RETURN ; AND RETURN TO MAINLINE .SBTTL ENDUP PROCES THE COMMANDS AND EXIT ;+ ; ENDUP -- PROCESS THE VARIOUS COMMANDS ISSUED ON THE COMMAND LINE ; AND EXIT ; ;- ENDUP: ; CMP SWPVAL,RBNVAL ; THE SWAPING TIME MUST BE > ROBIN INTERVAL BGT 1$ ; IF GT OK PRINT M6 ; IF LE, ERROR BR ERRXIT ; FATAL ERROR 1$: ; CMP RBHVAL,RBLVAL ; High priority must be > low priority BLE PRIERR ; IF LE, PRIORITY ERROR CMP RBHVAL,#1 ; PRIORITY MUST BE >1 BLT PRIERR ; ELSE CMP RBLVAL,#1 ; BAD BLT PRIERR ; PRIORITY CMP RBHVAL,#255. ; PRIORITY MUST BE LE 255. BGT PRIERR ; ELSE CMP RBLVAL,#255. ; BAD BGT PRIERR ; PRIORITY CMP SWLVAL,SWHVAL ; LOWER MUST BE SMALLER BGE SWPERR ; ELSE ERROR CMP SWLVAL,#-50. ; DON'T LET VALUE BE TOO LOW BLE SWPERR ; ELSE ERROR CALL $SWSTK,10$ ; SWITCH TO SYSTEM STATE MOV SWPVAL,$SWPCT ; SET SWAP TIME MOV RBNVAL,$RNDCT ; SET ROUND ROBIN INTERVAL .IFDF KMS ; MOV SWLVAL,$SWPRL ; SET LOWER SWAP PRIORITY RANGE MOV RBHVAL,RNDH ; SET ROUND ROBIN HIGH PRIORITY MOV RBLVAL,RNDL ; SET ROUND ROBIN LOW PRIORITY .ENDC MOV MINVAL,$SHFCT ; SET DELAY BETWEEN SHF RUNS RETURN ; BACK TO USER STATE 10$: TST DSPFLG ; SHOULD WE DISPLAY CURRENT STATUS BEQ XIT ; IF EQ, NO CALL DSP ; YES XIT: EXST$S #1 ; PRIERR: PRINT M7 ; SAY ITS A BAD PRIORITY RANGE BR ERRXIT ; SWPERR: PRINT M8 ; SAY ITS A BAD SWAP VALUE ERRXIT: EXST$S #4 ; ;+ ; PNTLIN ; ; THIS ROUTINE WILL PRINT AN ASCIZ LINE ;- PNTLIN: MOV #-1,R1 ; GET COUNT INITIALIZED MOV R0,QIODPB+Q.IOPL ; STORE BUFFER ADDRESS 170$: INC R1 ; INCREMENT COUNTER TSTB (R0)+ ; IS THIS THE LAST BYTE? BNE 170$ ; NO. KEEP GOING MOV R1,QIODPB+Q.IOPL+2 ; STORE BYTE COUNT DIR$ #QIODPB RETURN .END SCH