.TITLE MXTST ;MSX TEST TASKS. CONSOLE TASK WILL NORMALLY BE ACTIVE ;INITIALLY ON A SYSTEM. IT WILL ALLOW A USER TO ;SEND MESSAGES TO THE OTHER TASKS NAMED "A","B","C","D", OR "E" ; (INTERNALLY CONVERTED TO RAD50 AAA,BBB,CCT,DDD,EEE, ETC.) ;THESE TASKS WILL TYPE A MESSAGE SHOWING THEY ARE ACTIVE ;ON STARTUP, THEN AWAIT INPUT MESSAGES AND PRINT THEM. ; THE CONSOLE TASK WILL PROMPT AND MAY BE GIVEN COMMANDS: ;1. SP A SPAWN TASK A (OR B,C,D,E) ;2. RQ A REQUEST TASK A (OR B,C,D,E) ;3. SE A "MESSAGE" SEND MESSAGE INSIDE QUOTES TO TASK A ;4. AB A ABORT TASK A. WILL PRINT MESSAGE IF ANY EXIT ; AST IS SEEN FROM THE TASK (SHOULD BE ONE ; WHERE THE TASK WAS SPAWNED). ;5. EX A EXITS TO RSX/IAS ;6. AC A DISPLAYS ALL ACTIVE TASKS AND LOCATIONS .GLOBL AAA,BBB,CCT,DDD,EEE,KBT NAMS: .RAD50 /AAABBBCCTDDDEEEFFFGGGHHHIIIJJJ/ .WORD 0 KBMSG: .BLKW 60. ;BUFFER FOR KB INPUT MESSAGE PRPT: .ASCII <15><12>/MSX CONSOLE>/ .EVEN PRPTSZ=.-PRPT CMDS: .ASCII /SP/ .ASCII /RQ/ .ASCII /SE/ .ASCII /AB/ .ASCII /EX/ ;EXIT TO RSX .ASCII /AC/ ;ACTIVE TASK LIST LISTING .WORD 0 ;END FLAG ACTS: .WORD SPWN,RQST,SNDMSG,ABRT,BEGONE,ATLLST,0 .MCALL EXIT$S BEGONE: EXIT$S ;TABLE-DRIVEN STUFF! ATLMSG: .BYTE 15,12 .ASCII /TASK NAME=/ TSKNM: .BYTE 40,40,40 ;TASK NAME (RAD50) TRANSLATION .ASCII / ACTIVE IN CPU NO. / TSKCP: .BYTE 40 .ASCII / IN STATE (OCTAL)=/ TKST: .BYTE 40,40 ;TASK STATE .BYTE 15,12 MSZ=.-ATLMSG .EVEN ATLLST: MOV #MX.TBL,R5 ;FIND ALL ACTIVE TASKS AND LIST WHERE ;THEY ARE. 2$: MOV @R5,R1 ;GET TASK NAME MOV #TSKNM,R0 ;WHERE TO PUT IT CALL $C5TA ;CONVERT THE RAD50 TO ASCII MOVB TCBCPU(R5),R0 ;GET CPU NO. ADD #60,R0 ;MAKE IT ASCII MOVB R0,TSKCP ;SAVE IN THE MESSAGE MOVB TCBST(R5),R0 ;GET TASK STATUS TCBST=3 BIC #^C77,R0 ;MASK TO 6 BITS (IGNORE SUSPENDED BIT) MOV R0,R1 ;COPY ASH #-3,R1 ;ZOT OFF LOW DIGIT BIC #^C7,R1 BIC #^C7,R0 ;MASK DIGITS ADD #60,R0 ADD #60,R1 ;MAKE ASCII MOVB R1,TKST ;SAVE IN MSG MOVB R0,TKST+1 TST TCBDSP(R5) ;SEE IF TASK IS GOING BEQ 1$ ;IF NOT, SKIP THE MESSAGE QIOW.S WRITE,#1,#KPEV,#ATLMSG,#MSZ,#0 ;WRITE THE MESSAGE 1$: ADD #MX.TBS,R5 ;POINT AT NEXT TCB TST @R5 ;IF AT END, DONE BNE 2$ ;OTHERWISE DO THE NEXT JMP KBT KBTPOL: .BLKW 16.*16. ;MESSAGE POOL SPACE. AAAPOL: .BLKW 16.*16. BBBPOL: .BLKW 256. CCTPOL: .BLKW 256. DDDPOL: .BLKW 256. EEEPOL: .BLKW 256. .GLOBL KBTPOL,AAAPOL,BBBPOL,CCTPOL,DDDPOL,EEEPOL KBPUT: GENDPB WRITE,1,KPEV,PRPT,PRPTSZ,0 .WORD 0 KPEV: .WORD 0,0 KBGET: GENDPB READ,2,KGEV,KBMSG,80.,0 .WORD 0 KGEV: .WORD 0,0 KERRMG: .ASCII <15><12>/ERROR SEEN. CODE= / KERR: .BYTE 60 .BYTE 15,12 KEMSZ=.-KERRMG .EVEN KEDPB: GENDPB WRITE,1,KPEV,KERRMG,KEMSZ,0 ; ; KBT: ; ;ZERO TEXT IN BUFFER FOR POSSIBLE USE LATER MOV #KBMSG,R0 MOV #44.,R1 30$: CLR (R0)+ ;ZERO CHARS MEAN NOT READ SOB R1,30$ ;SO CLEAR 88. CHARS (MORE THAN WE READ) ;FIRST CHECK FOR NONZERO XITEV (SPAWN TSK EXIT) AND REPORT VIA SPECIAL ASCII ;CHARACTER IF ANY SPAWNED TSK EXITED MOV #XITEV,R0 ;POINT AT EV'S FOR EXITEED TASKS MOV #'A,R1 ;CODE=A,B,C,D,E... MOV #5,R2 ;5 TO TRY XASLP: TST (R0)+ ;WAS EV NONZERO? BEQ 32$ ;IF EV WAS 0, NO MSG CLR -2(R0) ;IF NOT, ZERO IT. JSR PC,MERR ;THEN TYPE THE MESSAGE IT WAS EXITED 32$: INC R1 ;NOW BUMP THE CODE SOB R2,XASLP ;AND TRY THE NEXT ONE ; ;AT THIS POINT, ALL EXITS OF SPAWNED TASKS ARE REPORTED AND EV'S ARE ;AGAIN ALL 0. CLR KPEV TRAN. #KPEV,#KBPUT,#1 ;EMIT PROMPT WAIT. #KPEV ;WAIT FOR IT TO FINISH CLR KGEV TRAN. #KGEV,#KBGET,#2 ;GET REPLY WAIT. #KGEV ;WAITING FOR HIM TO TYPE IT ; ;NOW ANALYZE REPLY. THE EV IS THE SAME AS THE RSX I/O STATUS BLOCK ;SO WORD 2 OF IT IS THE BYTE COUNT FOR RSX-BASED SYSTEMS. CMP KGEV+2,#2 ;AT LEAST 2 CHARACTERS THERE? BLE KBT ;NO, HAVE TO ASK AGAIN...ERROR MOV #CMDS,R0 ;YES, GET INDEX OF COMMAND LIST CMDFND: CMP (R0)+,KBMSG ;SEE IF WE HAVE THE COMMAND BEQ CMDGOT ;IF WE DO, ALL IS WELL TST (R0) ;SEE IF THIS IS END OF LIST BEQ KBT ;IF SO, RETRY READ WITH PROMPT BR CMDFND ;ELSE KEEP LOOKING CMDGOT: SUB #,R0 ;GET COMMAND INDEX (WORD INDEX...) MOVB KBMSG+3,R1 ;GET TASK LETTER NOW... SUB #'A,R1 ;AND MAKE OFFSET FROM IT CMP R1,#5 ;BE SURE RANGE IS OK BLO TSKOK JSR PC,ERR BR KBT ERR: MOVB R1,KERR ;SAVE R1=ERROR CODE ADD #60,KERR ;MAKE NUMERIC (OR OTHER ASCII) TRAN. #KPEV,#KEDPB,#1 ;WRITE OUT THE ERROR MESSAGE WAIT. #KPEV RTS PC MERR: MOVB R1,KERR ;SAVE R1=ERROR CODE TRAN. #KPEV,#KEDPB,#1 ;WRITE OUT THE ERROR MESSAGE WAIT. #KPEV RTS PC TSKOK: ASL R1 ;FORM TASK NAME INDEX MOV R1,R5 ;SAVE OFFSET TO TASK IN R5 FOR SUBS MOV NAMS(R1),R1 ;R1=TASK NAME NOW. ;NOW DISPATCH TO THE COMMAND HANDLERS JMP @ACTS(R0) ;GO TO APPROPRIATE HANDLERS WITH ;R1=TASK NAME (RAD50). ;R0=TASK OFFSET (WORD OFFSET) XITEV: .WORD 0,0,0,0,0,0 ;EXIT EV'S FOR TASKS CALEV: .WORD 0,0,0,0,0,0 ;CALLING EV'S FOR TASKS MSGLEN: .WORD 0,0,0,0,0,0 MSGADR: .WORD 0,0,0,0,0,0 MSGSTT: .WORD 0,0,0,0,0,0 ;MSG STATUS MSGHDR: .WORD 0,0,2 HDRNAM: .WORD 0 ;RAD50 TASK NAME SENT TO HDRSIZ: .WORD 0 ;MESSAGE LENGTH HDREVA: .WORD 0 ;EV TO BUMP ON TASK MSG RECEIPT HDRDAT: .BLKW 200. ;DATA AREA (400 CHARS MAX...MORE THAN NEEDED.) MSGEV: .WORD 0,0,0,0,0,0 ;MESSAGE EV'S SPWN: ;SPAWN COMMAND. SPAWN A TASK... MOV R5,R2 ;GET EXIT EVA ADD #XITEV,R2 ;IN R2 MOV R5,R3 ;FORM CALL EVA ADD #CALEV,R3 SPAWN R1,R2,R3 ;SPAWN THE TASK WAIT. R3 ;WAIT FOR DIRECTIVE DONE TST @R3 ;SEE IF R3 WAS + (OK) BMI 1$ 2$: CLR @R3 ;ZERO EV FOR NEXT TIME JMP KBT 1$: MOV @R3,R1 CLR @R3 ;ZERO EV FOR NEXT TIME NEG R1 ;MAKE CODE IN R1 JSR PC,ERR BR 2$ ;THEN BACK... RQST: ;REQUEST TASK... MOV R5,R2 ADD #CALEV,R2 ;GET AN EV ADDRESS FOR THIS TASK RQST. R1,R2 WAIT. R2 TST @R2 BMI 1$ 2$: CLR @R2 JMP KBT ;OK, GET NEXT CMD 1$: MOV @R2,R1 ;EV IS ERR CODE CLR @R2 NEG R1 ;MAKE SMALL + NO. JSR PC,ERR ;COMPLAIN BR 2$ ;THEN GO ON ABRT: ;ABORT TASK ABORT R1 ;GO ABORT IT...NO MESSAGE DIRECTLY XITJ: JMP KBT SNDMSG: ;SEND MESSAGE TO TASK (ASSUME OR HOPE TASK ACTIVE...) ;FIRST MUST LOCATE THE MESSAGE (LOOK FOR DOUBLE QUOTE (") CHARACTER) MOV R1,HDRNAM ;FIRST SAVE TASK NAME AS WHERE TO SEND MSG MOV #KBMSG+3,R1 ;START IN BUFFER P1LP: CMPB (R1)+,#'" ;SEE IF WE FOUND A QUOTES MARK BEQ P1LGOT ;IF SO, SCAN FOR DATA CMP R1,#KBMSG+80. ;BE SURE NOT PAST END TEXT BLO P1LP ;IF NOT, ALL SEEMS WELL LPER: SUB #KBMSG,R1 ;ELSE SET COLUMN JSR PC,ERR BR XITJ ;THEN BACK TO MAIN LOOP P1LGOT: CLR R2 ;R2 = MESSAGE COUNTER NOW... MOV #HDRDAT,R3 ;R3=DATA AREA P2LP: CMPB @R1,#'" ;BE SURE NOT AT 2ND QUOTES MARK BEQ P2LPGT ;IF SO, DONE MOVB (R1)+,(R3)+ ;ELSE COPY A BYTE BEQ LPER ;;NULLS ARE ERRORS INC R2 ;AND COUNT IT CMP R1,#KBMSG+80. ;BE SURE NOT TOO FAR BLO P2LP BR LPER ;IF TOO FAR, REPORT ERROR P2LPGT: MOV R2,HDRSIZ ;SAVE SIZE OF MESSAGE MOV R5,R3 ;NOW GET EV TO BUMP ON RECEIPT ADD #MSGEV,R3 ;ADDR NOW IN R3 MOV R3,HDREVA ;SAVE IN HEADER CLR @R3 ;ZERO THE EV INITIALLY MSGOUT #MSGHDR ;NOW SEND THE MESSAGE ;AWAIT ITS RECEIPT AND COMPLAIN ON ERROR WAIT. R3 ;WAIT TILL HE RETURNS MY EV TST @R3 ;WAS IT OK (POSITIVE?) BPL 1$ ;YES, SEEMS THAT WAY MOV @R3,R1 ;NO, GET VALUE NEG R1 ;AND NEGATE FOR HIM ADD #5,R1 ;FORM "UNIQUE" CODE JSR PC,ERR ;PRINT IT 1$: CLR @R3 ;ZERO EV FOR NEXT TIME AROUND JMP KBT ;FINALLY BACK TO WORK! ;SUBORDINATE TASKS... THESE REPORT TO LUN 1 THEY ARE ACTIVE, ;THEN AWAIT MESSAGES. INAMS: .ASCII <15><12>/AAA ACTIVE/<15><12> NMSZ=.-INAMS ;NOTE EVEN .EVEN .ASCII <15><12>/BBB ACTIVE/<15><12> .ASCII <15><12>/CCT ACTIVE/<15><12> .ASCII <15><12>/DDD ACTIVE/<15><12> .ASCII <15><12>/EEE ACTIVE/<15><12> ; .EVEN MINAMS: .ASCII <15><12>/AAA MSG IN/<15><12> .EVEN .ASCII <15><12>/BBB MSG IN/<15><12> .ASCII <15><12>/CCT MSG IN/<15><12> .ASCII <15><12>/DDD MSG IN/<15><12> .ASCII <15><12>/EEE MSG IN/<15><12> ; .EVEN ;MESSAGE OUTPUT DPB'S TO ECHO MESSAGES .MACRO GENEV LABEL .WORD 0 LABEL: .WORD 0 .WORD 0 .ENDM ;EVENT VARIABLES FOR QTRANS GENEV AEV GENEV BEV GENEV CEV GENEV DEV GENEV EEV ; EVVR: .WORD AEV,BEV,CEV,DEV,EEV EVSS: .WORD 0,0,0,0,0,0 EVWR: .WORD EVSS,EVSS+2,EVSS+4,EVSS+6,EVSS+10 ;EV FOR WAIT ON MSGIN MGLNS: .WORD 0,0,0,0,0,0 MLNT: .WORD MGLNS,MGLNS+2,MGLNS+4,MGLNS+6,MGLNS+10 MGADS: .WORD 0,0,0,0,0,0 MADT: .WORD MGADS,MGADS+2,MGADS+4,MGADS+6,MGADS+10 MSTTS: .WORD 0,0,0,0,0 MSTB: .WORD MSTTS,MSTTS+2,MSTTS+4,MSTTS+6,MSTTS+10 AAA: CLR R2 ;TSK=AAA BR ABCDE BBB: MOV #2,R2 BR ABCDE CCT: MOV #4,R2 BR ABCDE DDD: MOV #6,R2 BR ABCDE EEE: MOV #10,R2 BR ABCDE ABCDE: ;DISPLAY TASK NAME AS ACTIVE... MOV R2,R3 MUL #,R3 ;GET OFFSET TO BUFFER ADD #INAMS,R3 QIOW.S WRITE,#1,EVVR(R2),R3,#NMSZ,#0 ;ABOVE STASHES MESSAGE ON LUN 1 AND WAITS FOR DONE ;NOW SET UP TO RECEIVE MESSAGES... MOV R3,-(SP) MOV #EVWR,R3 ADD R2,R3 ;ADDRESS OF RCV COUNT EV. MODSTT #1,R3,#14,#24 ;SET RCV COUNT IN EVSS AREA MOV (SP)+,R3 ;NOW WE CAN AWAIT MESSAGES IN ADD #,R3 ;POINT AT "MSG IN" MESSAGES ;RATHER THAN INITIAL "ACTIVE" LPP: WAIT. EVWR(R2) CLR @EVWR(R2) ;ZERO THE EV ON WAIT DONE MSGIN MLNT(R2),MADT(R2),MSTB(R2) ;READ MESSAGE QIOW.S WRITE,#1,EVVR(R2),R3,#NMSZ,#0 QIOW.S WRITE,#1,EVVR(R2),@MADT(R2),@MLNT(R2),#0 ;WRITE MSG TOO MSGFRE @MLNT(R2),@MADT(R2) ;FREE MSG AREA JMP LPP ;GO GET NEXT MSG IF ANY EXIT. .END