M.MMP=0;THIS IS A MULTIPROCESSOR MONITOR! M.MMP=0;THIS IS A MULTIPROCESSOR MONITOR! UPAR7=177656 ;USER PAR 7 ADDR ;STAND-ALONE MSX ROUTINES, WHEREVER CONDITIONED ;BY BOTH $$DOS AND NODOS DEFINED. .TITLE MXCODE SUPPORT ROUTINES FOR MSX ;--- ; DEFINE REGS R0=%0 R1=%1 R2=%2 R3=%3 R4=%4 R5=%5 SP=%6 PC=%7 ;PS=177776 ; STATUS REG EAEAC=177302 EAEMQ=177304 EAESR=177310 ; GLOBLS DEFINED IN MXTBLS .GLOBL MX.IAC,MX.STK,MX.TCB .IF DF,$$DOS .GLOBL MX.IVT,MX.LUT .ENDC .IF DF,$$DOS .IF DF,NODOS ;STAND-ALONE DUAL MODE MSX ; U.LDR LOAD USER CONTEXT WITH R0 POINTING TO TCB ENTRY .GLOBL U.LDR U.LDR: MOV R0,-(SP) MOV R1,-(SP) MOV R0,R1 ;GET TCB ADDRESS ADD #,R1 ;POINT AT LAST USER APR BIS #30000,@#PS ;ENSURE PREVIOUS USER MODE MOV R2,-(SP) ;NEED ANOTHER REG MOV #,R2 ;TO ADDRESS USER PARS MOV #10,R0 ;R0=COUNTER 1$: MOV -(R1),-(R2) ;SET A USER PAR UP DEC R0 ;DO ALL OF THEM BGT 1$ MOV (SP)+,R2 ;RESTORE THE REGS MOV (SP)+,R1 MOV (SP)+,R0 RTS PC ;SETUP OF USER "SPACE" NOW COMPLETE ; .GLOBL U.RSAV,U.RRES ;REG AND APR SAVE AND RESTORE IN STL ; ; U.RSAV AND U.RRES ; ; THESE ENTRIES ARE CALLED BY JSR PC,U.RSAV OR JSR PC,U.RRES ; TO SAVE AND RESTORE USER REGISTERS IN THE TCB. THE ASSUMPTION IS ; THAT MX.TCB HAS THE TCB ADDRESS OF THE TCB ENTRY TO USE FOR ; REGISTER AND APR SAVING/RESTORING. ALL REGISTERS, ALL 8 USER ; APR'S, AND THE USER STACK ARE SAVED OR RESTORED. ; NOTE THAT THE DYNAMIC STACK IS THE ONE RESTORED. ; THE C BIT WILL BE SET ON RETURN IF THAT STACK WAS 0. ; U.RSAV: TST MX.TCB ;IS A TASK THERE? IF NOT, EXIT NOW. BNE 1$ ;YES, BRANCH 2$: RTS PC ;NO, SCRAM 1$: MOV R0,-(SP) ;NEED A REGISTER SO SAVE R0 BIS #30000,@#PS ;SET PREV USER MODE MOV MX.TCB,R0 ;POINTER STL ENTRY TCBREG=20 ADD #TCBREG,R0 ;POINT AT REG SAVE AREA MOV (SP)+,(R0)+ ;NOW SAVE USER'S R0 MOV R1,(R0)+ ;ALSO HIS R1 MOV R2,(R0)+ ;HIS R2 MOV R3,(R0)+ ;...R3... MOV R4,(R0)+ ;ETC MOV R5,(R0)+ ;ETC ;NOW ALL REGS ARE FREE SO WE CAN SAVE THE APR'S UPAR0=177640 ;ASSUME TASK IS IN USER SPACE ;KERNEL MAPPING WON'T CHANGE MOV #UPAR0,R1 ;SAVE ALL MAPS... ;NOTE THAT TCB IS 32 WORDS LONG, NOT 16, FOR STANDALONE CASE .REPT 8. MOV (R1)+,(R0)+ ;SAVE AN APR .ENDR ;FINALLY SAVE THE USER'S STACK MFPI SP MOV (SP)+,(R0) ;SAVE USER STACK ;NOW SAVE USER'S PC,PS FROM KNL STACK. ASSUME ONLY THE JSR PC WAS THERE ;TO U.RSAV. MOV 2(SP),(R0)+ ;SAVE TASK PC MOV 4(SP),(R0)+ ;SAVE TASK PS ;NOW ALL DONE THE SAVE OF CONTEXT AND MAY GO AWAY NICELY, PLEASE. ;ALLOW SAVE OF F.P. STATUS IN ORIGINAL APR CELL AREA .IIF DF,$FPU, FPPSAV=0 .IF DF,FPPSAV MOV MX.TCB,R0 ;GET THE TCB AGAIN ADD #TCBAP1,R0 ;POINT AT APR TABLE ADDRESS MOV @R0,R0 ;GET THE TABLE ADDRESS INTO R0 NOW ADD #8.+8.+4.+4.,R0 ;PASS SAVED APR'S AND TRAPS STFPS (R0)+ ;SAVE FP STATUS LDFPS #40200 ;SET DOUBLE PREC, NO INTS STF R0,(R0)+ ;SAVE AC0 STF R1,(R0)+ STF R2,(R0)+ STF R3,(R0)+ STF R4,R0 ;AC4 TO AC0 STF R0,(R0)+ STF R5,R0 STF R0,(R0)+ ;SAVE ALL FLOATING AC'S MOV @#244,(R0)+ ;SAVE FLOATING INT VECTOR TOO. MOV @#246,(R0)+ ;(BOTH HALVES...) MOV #2,@#246 ;AND SET IT TO AN RTI MOV #246,@#244 ;TO ITSELF... .ENDC RTS PC ;BYE FOLKS ; U.RRES: ;RESTORE USER REGISTERS FROM TCB POINTED TO BY MX.TCB ;(THIS ROUTINE AND U.RSAV ARE CALLED FROM KERNEL SPACE AND BETTER ; BE RUN THERE OR BAD, BAD THINGS WILL HAPPEN...) MOV MX.TCB,R0 ;POINT AT TCB BNE 1$ ;IF NONE, NO ACTION RTS PC 1$: .IF DF,FPPSAV ADD #TCBAP1,R0 ;POINT AT INIT APR TBL ADDR MOV @R0,R0 ;GET TBL ADD #16.+8.,R0 ;PASS APR AREA AND INT VECTORS MOV R0,R1 ;SAVE ADDRESS HERE TST (R0)+ ;PASS FP STATUS ADDRESS LDFPS #40200 ;FP DOUBLE MODE NOW, INTS OFF LDF (R0)+,R0 LDF (R0)+,R1 LDF (R0)+,R2 LDF (R0)+,R3 STF R0,-(SP) ;NEED AC0 A MOMENT TO LOAD AC4,AC5 LDF (R0)+,R0 ;SAVE AC4 STF R0,R4 LDF (R0)+,R0 STF R0,R5 LDF (SP)+,R0 ;RESTORE AC0 LDFPS (R1) ;RESTORE FPP STATUS NEXT. THEN ALL SET. MOV (R0)+,@#244 ;RESTORE FLOATING INT VECTOR MOV (R0)+,@#246 MOV MX.TCB,R0 .ENDC ADD #TCBREG+40,R0 ;POINT PAST END OF APR SAVE AREA ;THE FIRST THING WE RESTORE IS TASK PS,PC, WHICH WE STORE ON THE ;KERNEL STACK, OVERWRITING WHATEVER WAS THERE. ASSUME JSR PC,U.RRES WAS ;ON TOS AND LEAVE IT ALONE. BIS #30000,@#PS ;SET PREV USER BITS FOR USER ACCESS MOV -(R0),4(SP) ;RESTORE THE PSW MOV -(R0),2(SP) ;RESTORE THE PC MOV #,R1 ;POINT AT USER PARS .REPT 8. ;(THIS CODE IS SIMILAR TO THE SAVE CODE) MOV -(R0),-(R1) ;COPY INTO USER APR'S .ENDR ;NOW RESTORE REGS MOV -(R0),R5 ;RESTORE R5 MOV -(R0),R4 MOV -(R0),R3 MOV -(R0),R2 MOV -(R0),R1 ;DON'T RESTORE R0 UNTIL WE RESTORE USER SP... ;R0 NOW POINTS AT TCBREG+2 CLC ;RESET THE C BIT MOV (R0),-(SP) ;GET OLD USER SP MTPI SP ;SET UP USER MODE STACK BNE 2$ ;IF USER STACK LEGAL, LEAVE C BIT OFF SEC ;IF 0, TELL CALLER SO 2$: MOV -(R0),R0 ;NOW RESTORE R0 RTS PC ;AND GO AWAY QUIETLY .ENDC .ENDC ; ; FOR THE CASE OF STANDALONE SYSTEM, MX.PST PUTS A DUMMY RETURN TO ; MX.RTI ON THE KERNEL STACK. THE USER STACKS NEVER GET THE INTERRUPTS ; SO THERE IS NO NEED TO SWITCH IN SOFTWARE. ; ; MX.PST ROUTINE ;--- ; POST THE CURRENT INTERRUPT. THIS INCLUDES SAVING ALL USER ; REGISTERS, SETTING SP TO INTERNAL STACK IF FIRST ONE AND ; SETTING PRIORITY TO USER SPEC. ; CALLED VIA: ; ; JSR R5,MX.PST ; .WORD XXX ; WHERE XX IS VALUE OF PS TO BE USED ;----- .GLOBL MX.PST,MX.RTI MX.PST: ;---- ENTRY POINT .IIF NDF,$$DOS,MOVB #340,@#PS ;NO INTERRUPTS OF THIS! ;--- COUNT IAC AND SKIP IF NOT FIRST INT .IF DF,$$DOS .IF DF,NODOS ;IF STAND ALONE VERSION SAXCL=0 .ENDC .ENDC INCB MX.IAC ; IAC_ IAC+1 BNE MXPST1 ; IF IAC=0 SKIP STACK RESET ;--- SWITCH STACK HERE .IF NDF,SAXCL MOV R0,MXPST0+2 ; SAVE CURRENT R0 .IFF ; NOTE: DO NOT, IN STANDALONE VERSION, MODIFY STACK EXCEPT FOR ;CASES WHERE SCANNER IS INTERRUPTED. THIS MEANS WE JUMP TO MX.RTI ON ;COMPLETION INTERRUPTS BUT DO NOT CCALL THE SCANNER AT OTHER TIMES. ; SINCE I/O IS HANDLED AS PROCESSES RATHER THAN TASKS NOW, THIS IS THE ;APPROPRIATE PROCEDURE. COMPLETION TASKS CAN ISSUE DECLARE MACROS TO ;OVERRIDE THIS... TST MX.TCB ;SEE IF ANY TASK ACTIVE BNE MXPST0 ;IF SO, NO ACTION JUST HERE. USE COMPL. INT. MOV R0,-(SP) ;STASH R0 ON KNL STACK (WE GET HERE FROM INT) MOV 2(SP),R0 ;GET CURRENT ENTRY R5 MOV R0,-(SP) ;MOVE DOWN ENTRY R5 MOV 2(SP),-(SP) ;MOVE DOWN SAVED R0 FROM ABOVE MOV #MX.RTI,4(SP) ;STASH AN RTI TO MX.RTI ABOVE OLD ONE MOV #30340,6(SP) ;AT PRIO 7 ;FALL THROUGH TO MXPST0 .IFT MOV MX.TCB,R0 ; R0= ADDR OF LAST TCB BEQ MXPST2 ; SKIP IF NONE .ENDC .IF NDF,SAXCL MOV (SP)+,MX.STK-2 ; SAVE OLD 5 ON OUR STACK MOV SP,10(R0) ; SAVE STACK ADDRESS MOV #MX.STK-2,SP ; DO IT .ENDC ;--- SET SP TO INTERNAL STACK MXPST0: .IIF NDF,SAXCL, MOV #0,R0 ; RESTORE R0 .IIF DF,SAXCL, MOV (SP)+,R0 MXPST1: .IIF DF,$$DOS,MOVB (R5),@#PS ; SET USER PRI INC R5 .IIF NDF,$$DOS,CLRB @#PS ;ALLOW INTERRUPTS FOR RSX VERSION TSTB (R5)+ ; SAVE REGS TOO ? BEQ MXPSTX ; NO, SKIP JMP S.RSAV ; YES, DO IT TO IT MXPSTX: RTS R5 ; AND EXIT ; HERE WE HANDLE THE CASE OF THE SCANNER BEING ; INTERRUPTED. IN THIS CASE, MAKE A DUMMY RTI ENTRY ; TO GET US BACK TO MX.RTI, BUT LEAVE CURRENT IN CASE ; THE SCANNER SHOULD NOT RESTART ENTIRELY. MXPST2: MOV (SP),R0 ; SAVE CURRENT TOP .IF DF,$$DOS .IF NDF,NODOS MOV #340,(SP) ; MAKE THE PS WORD .ENDC ;NODOS .IFF CLR @SP .ENDC MOV #MX.RTI,-(SP) ; AND PC MOV R0,-(SP) ; PUT OLD TOP BACK BR MXPST0 ; AND MERGE ; MX.KIL ROUTINE TO BRING US BACK TO DOS. ; WE CLEAN UP THE INTERRUPT VECTORS AND ISSUE AN EXIT TO ; DOS. IF NO DOS PRESENT, EMT VECTOR SHOULD HALT OR SOMETHING. .GLOBL MX.KIL ; ENTRY POINT ;------ MX.KIL: ; HERE IT IS FOLKS .IF DF,$$DOS RESET ; PREVENT ANY BADDY ; NOW LOOP THRU ALL OUR DEVICES, RESETING DDBS AND DRIVERS MOV #MX.LUT,R0 ; R0_ LUT ADR BEQ MXKIL3 MOV (R0)+,R2 ; R2_ # DEVICES BEQ MXKIL3 ;--LOOP OVER EACH DEVICE HERE MXKIL1: MOV (R0)+,R1 ; R1_ LNKBLK ADR BEQ MXKIL2 MOV (R1),R1 ; R1_ DDB ADR BEQ MXKIL2 CLR (R1) ; FREE DDB MOV -(R1),R1 ; R1_ DVR ADR BEQ MXKIL2 CLR (R1) ; FREE DRIVER ; DONE WITH THIS ONE HERE MXKIL2: DEC R2 ; COUNT DOWN BGT MXKIL1 ; MORE LEFT, DO THEM ;-- HERE ALL DRIVERS HAVE HOPEFULLY BEEN FREED MXKIL3: JSR PC,MX.IVR ; RESTORE SAVED INTERRUPT VECTORS .IF NDF,NODOS ; IF DOS IS REALLY REALLY THERE... EMT 60 ; AND GO OFF TO DOS... .IFF ;IF DOS IS NOT REALLY REALLY THERE HALT ;LET USER REALIZE SOMETHING IS WRONG... JMP @#BGNS ;THEN RESTART THE SYSTEM .ENDC .IFF ;FOR RSX VERSION MUST CLOSE ALL FDB'S IN SYSTEM. ;ALLOCATE THEM HERE FOR THE HECK OF IT AND CLOSE ALL OF THEM .MCALL EXIT$S .MCALL FDBDF$,FDOP$A,FDAT$A,FDBK$A .MCALL CLOSE$ JSR PC,CLSALL ;CLOSE ALL FDB'S .GLOBL CLSALL .IIF DF,M$GE,JSR PC,WNDCLR ;IF MAPPED REMOVE ADDR WINDOWS .IIF DF,MX.IV, JSR PC,UNSPRG ;UNSPRING INTERRUPT VECTORS EXIT$S MAXLUN=2 NLUNS=MAXLUN .MCALL CLEF$S,WTSE$S,SPRA$S,ASTX$S,CALL,RETURN .MCALL EXIT$S,WTLO$S,SETF$S,MRKT$,CMKT$,DIR$ ; ;DATA BUFFER .IF NDF,MAXUNI MAXUNI=MAXLUN ;ALLOW 8. UNITS FOR THE PRESENT .ENDC .IF DF,FCSMSX ;CONDITIONALIZE FCS CODE IN MSX -- NORMALLY TOO BIG DATBUF: ; .BLKW 256. ;1 BLOCK PER BUFFER ; ONLY 1 BUFFER NEEDED IN THE HANDLER...ALL ACCESS IS SERIAL ANYHOW. DATCNT: .WORD 0 ;BYTE COUNT FOR CURRENT OPERATION DATBLK: .WORD 0,0 ;VIRTUAL BLOCK NUMBER FOR CURRENT OPERATION ; .SBTTL FDB AREAS FOR FILES .D.D..=1 .MCALL FDBDF$,FDAT$A,FDBK$A,FDOP$A,FDRC$A .MCALL NMBLK$ .MACRO SETFS N,LUNNO FDB'N:: FDBDF$ FDAT$A R.FIX,,1000,-16.,-16. FDRC$A FD.RWM FDBK$A DATBUF,512.,,,IOST'N FDOP$A ,DSD'N,DFNB'N,FO.MFY,FA.DLK DSD'N:: .WORD 4,DEV'N .WORD FL'N,DIR'N .WORD FNL'N,FN'N DFNB'N: NMBLK$ VDDAT'N,DAT,,SY,0 FN'N:: .ASCII /MSXDAT/ .BYTE ''N .ASCII /.DAT/ FNL'N=.-FN'N .EVEN DIR'N:: .ASCII /[003,103]/ FL'N=.-DIR'N .EVEN DEV'N:: .ASCII /TI0:/ .EVEN IOST'N: .WORD 0,0 .ENDM .REPT MAXUNI ;SET UP "MAXUNI" FDB'S SETFS \.D.D..,.D.D.. .D.D..=.D.D..+1 .ENDR .D.D..=1 FDBTBL:: ;TABLE OF FDB ADDRESSES FOR EACH LUN USED .MACRO FDBWRD N .WORD FDB'N .ENDM .REPT MAXUNI ;SET UP "MAXUNI" FDB'S FDBWRD \.D.D.. .D.D..=.D.D..+1 .ENDR ; .ENDC .GLOBL OPNALL,CLSALL OPNALL: .IF DF,FCSMSX JSR R5,S.RSAV ;ALL REGS FREE, SO OPEN ALL FDB'S MOV #MAXUNI,R5 ;NO. UNITS DEFINED FOR THIS HANDLER MOV #FDBTBL,R4 ;AND FDB ADDRESSES 11$: MOV (R4)+,R0 ;POINT R0 AT FDB SET UP NOW .MCALL OPEN$M,CLOSE$ OPEN$M ;R0 ALREADY IS FDB. ;OPEN THE FILE (SET UP ALREADY...) ;NOW SET UP PUD FOR NUMBER OF BLOCKS IN THE NOW-OPEN FILE DEC R5 BGT 11$ ;OPEN MAXUNI FILES JSR R5,S.RRES .ENDC RTS PC CLSALL: .IF DF,FCSMSX JSR R5,S.RSAV ;SAVE REGS MOV #MAXUNI,R5 ;NO. LUNS FOR FILES MOV #FDBTBL,R4 ;TABLE OF FDB ADDRESSES 1$: MOV (R4)+,R0 ;POINT R0 AT FDB CLOSE$ ;CLOSE IT DEC R5 BGT 1$ ;DO ALL OF THEM. JSR R5,S.RRES .ENDC RTS PC ; .ENDC ; INTERRUPT VECTOR SAVE/RESTORE ; IT WORKS OF OF TABLE WHOSE FIRST ENTRY IS THE ; ADDRESS OF THE NEXT FREE WORD. ;-- ; MX.IVS SAVES THE CURRENT INTERRUPT VECTOR IN TABLE THEN SWAPS ; PC VALUE. R1 HAS ADDRESS OF IV, R2 HAS NEW PC VALUE ;--- .IF DF,$$DOS .IF DF,$$DOS .GLOBL MX.IVS .ENDC MX.IVS: ; ENTRY POINT MOV MX.IVT,R3 ; FETCH NEXT WORD ADR MOV R1,(R3)+ ; ADDR OF IV TO TABLE MOV (R1),(R3)+ ; AND OLD PC MOV R2,(R1)+ ; STASH NEW VALUE MOV R3,MX.IVT ; SAVE NEXT ADR ; MOVB (R1)+,(R1) ; SAVE PS IN UPPER BYTE CMPB (R1)+,(R1) MOVB #340,-(R1) ; AND SET TO OURS RTS PC ; AND EXIT ; MX.IVR RESTORES INTERRUPT VECOTRS BASED ON TABLE ; TABLE HAS BEEN BUILT BY MX.IVS .GLOBL MX.IVR MX.IVR: ; ENTRY POINT MOV #MX.IVT,R0 ; TABLE ADR TO 0 MOV (R0)+,R1 ; END ADR TO 1 IVRNXT: CMP R0,R1 ; END ? BHIS IVRXIT ; YES, LEAVE MOV (R0)+,R2 ; IV ADR MOV (R0)+,(R2)+ ; RESTORE PC WORD ; MOVB 1(R2),(R2)+ ; RESTORE STATUS CMPB 1(R2),(R2)+ CLRB (R2) ; AND RESET UPPER BR IVRNXT ; LOOP FOR NEXT ONE IVRXIT: RTS PC ; OF TO CALER HERE .ENDC ; COMMON SAVE/RESTORE CODE ; OUR SYSTEM SAVE/RESTORE SUBROUTINES .GLOBL S.RSAV,S.RRES S.RSAV: MOV R4,-(SP) ; PUSH REGS (R5 ALREADY ON SP) MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) MOV 12(SP),-(SP) ; FIXUP R5 RETURN VALUE RTS R5 ; AND EXIT S.RRES: TST (SP)+ ; POP CALLING R5 MOV (SP)+,R0 ; NOW LOAD THEM UP MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ; AND EXIT TO OUR CALLER ; MINIMAL IOT PROCESSOR ; ; ; NOTE THAT THE DOS CALL FOR DIAGNOSTIC PRINT IS ; ; MOV ,-(SP) ; MOV #CODE,-(SP) ;402 IS A002 ; IOT ; ; CODE HIGH BYTE IS: ; 0 I ERROR ; 1 A ERROR (ACTION) ; 2 W ERROR (WARNING) ; 3 F ERROR (FATAL) ; 4 S ERROR (SYSTEM) (NOT SUPPORTED HERE) ; ; THIS CODE IS MEANT TO PROVIDE THE BAREST SUPPORT FOR ; IO'T S WHIC ARE ISSUED BY DRIVERS, TRAPS, ETC OF THE ; SYSTEM. NO ATTEMPT IS CURRENTLY MADE TO QUEUE ; THEM UP, OR EVEN TO ALLOW NORMAL INTERRUPT PROCESSING. ; SO, WITH THESE CAVEATS, LETS GO TO IT....... ; DEFINE TTY REGISTERS TTICSR=177560 TTIDBR=177562 TTOCSR=177564 TTODBR=177566 .GLOBL MX.IOT ; THIS IS TH ENTRY POINT FOLKS .IF NDF,$$DOS .GLOBL MX.FTL,MX.QUE MX.QUE: CMP -(SP),-(SP) ;GET 2 WORDS ON STACK MOV 4(SP),(SP) MOV 6(SP),2(SP) ;COPY OLD TOP 2 MOV @MX.TCB,6(SP) ;GET TCB ADDR AND THENCE TSK NAME MOV #405,4(SP) ;A005 ERROR (SPMETHING SCREWBALL) BR MX.IOT ;GO TELL GUY .IFTF .GLOBL MX.FTL MX.FTL: ;FATAL ERROR OF SOME KIND CMP -(SP),-(SP) ;GET 2 WORDS ON STACK MOV 4(SP),(SP) MOV 6(SP),2(SP) ;COPY OLD TOP 2 MOV @MX.TCB,6(SP) ;GET TCB ADDR AND THENCE TSK NAME MOV #1400,4(SP) ;FATAL ERROR. F000 .IF DF,$$DOS .IF DF,NODOS BIT #140000,2(SP) ;SEE IF IN KNL MODE BEQ 1$ ;IF SO LEAVE CODE ALONE INC 4(SP) ;ELSE BUMP ERROR CODE 1$: BIC #140000,2(SP) ;THEN AVOID TRYING TO GET INFO OFF USER STK .ENDC .ENDC .ENDC MX.IOT: ;--- SEE!!!!!! ; THE FIRST THING TO DO IS SAVE THE 'CONTEXT', INCLUDING REGS AND ; THE TTY STATUS AND DATA REGS .IF DF,NODOS ;STANDALONE VERSION... BIT #140000,2(SP) ; WAS THE CALLER IN USER MODE? BEQ 1$ ; NO, KERNEL LOGIC IS OK NOW MOV R0,-(SP) ;CALLER WAS IN USER MODE. COPY DATA ;FROM HIS STACK TO OURS MOV 2(SP),-(SP) ;MOVE OLD PC DOWN STACK MFPI SP ;GET USER SP MOV (SP)+,R0 ;COPY TO R0 WHILE NEEDED MFPI (R0)+ ;GET OLD CODE TO OUR STACK MFPI (R0)+ ;GET OLD "HELPFUL INFO" TOO MOV R0,-(SP) ;PREPARE TO "POP" USER STACK BACK MTPI SP ;TO GET RID OF OLD JUNK MOV 6(SP),R0 ;GET BACK CALLER'S R0 MOV 12(SP),6(SP) ;COPY PREVIOUS PSW BACK AGAIN MOV (SP)+,10(SP) ;PUT "HELPFUL INFO" IN PLACE MOV (SP)+,4(SP) ;THEN PUT TRAP CODE IN PLACE AND ALL DONE. 1$: .ENDC MOV SP,SPX ; SAVE STACK ADD #10,SPX ; POINT TO OLD TOP (BEFORE IOT) MOV #SPX,SP ; NOW SAVE REST ON OUR STACK MOV R5,-(SP) MOV R4,-(SP) MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) .IF DF,$$DOS ; OK, NOW SAVE TTY STUFF MOV #TTODBR,R0 ; GET ADDRESS MOV (R0),-(SP) MOV -(R0),-(SP) CLR (R0) ; RESET CSR MOV -(R0),-(SP) MOV -(R0),-(SP) CLR (R0) ; RESET .ENDC ; NOW START IT UP JSR R5,PUTSTP ; PUT OUT CRLF + CRLF ; NOW SET A POINTER TO CODES, ETC MOV SPX,R4 CMP -(R4),-(R4) ; POINT TO CODES. MOVB 1(R4),R0 ; GET CODE VALUE MOVB CODETB(R0),CODE ; MOVE TO MESSAGE JSR R5,PUTSTP ; AND PUT OUT STARTER + ERRHD MOVB (R4),R0 ; GET ERROR NUMBER JSR R5,PUTBYT ; AND ISSUE I JSR R5,PUTSPC ; GIVE ONE SPACE MOV 2(R4),R0 ; GET EXTRA WRD JSR R5,PUTWRD ; AND SEND TO CLOD JSR R5,PUTSPC ; EMIT ANOTHER SPACE MOV -2(R4),R0 ; GET PC AT ERROR JSR R5,PUTWRD ; AND PRINT IT .IF DF,M$GE ; IF DOING MAPPING REPIRT APR1 CONTENT TOO JSR R5,PUTSPC MOV @#177642,R0 ; GET APR1 JSR R5,PUTWRD ; PRINT IT SO MAYBE WE CAN FIND THE TASK .ENDC ; NOW WE DETERMINE THE ACTION, EITHER OFF OR WAIT FOR OPERATORE BITB #1,1(R4); IS THIS REPLY TYPE ? BEQ CONT ; NO, LEAVE THIS WORLD ;---- ; ACTION CODE REQUIRED BY USER, WAIT FOR HIM IOT0: JSR R5,PUTSTP ; ISSUE CRLF + CRLF ; NOW GET ONE CHARACTER .IF DF,$$DOS TST @#TTIDBR ; MAKE SURE READY IS UNSET AT OUTSET .ENDC JSR R5,GETCHR ; GET ONE IN ; NOW DETERMINE ACTION, AN CHECK FOR VALIDITY MOV #ACTNTB,R1 ; TABLE PTR IOT1: TSTB (R1) ; END OF TABLE ? BEQ BADACT ; YES, TELL HIM ABOUT IT CMPB (R1)+,R0 ; THIS IT ? BEQ IOT2 ; YES, LOOK AT IT ADD #3,R1 ; NO, LOOK AT NEXT BR IOT1 ; AND LOOP ;----- ; HERE CODE IS FOUND, BUT FIRST CHECK IF IT IS OK FOR ; THE TYPE OF MESSAGE, EG. CAN'T ALLOW C ON FATAL ERRORS IOT2: BITB (R1)+,1(R4) ; MATCH BITS IN FATAL MESSAGE BNE BADACT ; SHARE COMMON BAD CODE IF NOT VLUD ; ACTION CODE HAS BEEN FOUND VALID, OFF TO ROUTINE MOV (R1),PC ; GO TO IT ;--- ; ILLEGAL CODE OR INVALID PLACEMENT HERE BADACT: JSR R5,PUTSTP ; ISSUE MESSGE + BADMSG BR IOT0 ; AND WAIT AGAIN ;---- ; ACTION CODE PROCESSES FOLLOW ;---- KILL: ;---- KILL THE JOB, USNG OUR STANDARD KILL ROUTINE JSR R5,PUTSTP ; ECHO FULL + KMSG JSR R5,PUTWAT ; WAIT FOR FINAL BHARACTER DONE .IF DF,$$DOS ; RESTORE STUFF HERE MOV #TTICSR,R0 ; GET INITAL ADDRESS MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0) .ENDC .IF DF,M.MMP ;MULTIPROC SYSTEM FLAGS ABORT FOR ERROR MOV MX.TCB,R0 ;GET CURRENT TCBADDR BNE 1$ ;IF ONE EXISTS THAT IS JMP MX.KIL ;IF NONE EXISTS, HAVE TO DIE! SORRY... 1$: MOVB #10,TCBST(R0) ;SAY ABORT QUEUED MOV #-3,TCBSTT(R0) ;ALSO SAY ERROR CAUSED ABORT JMP CONTCM ;THEN GO ON .IFF JMP MX.KIL .ENDC ;---- DUMP: ;-- DUMP CORE FOR CLOWN JSR R5,PUTSTP ; ECHO + DMSG JSR R5,PUTWAT ; WAIT TILL DONE .IF NDF,M.MMP .IF DF,$$DOS HALT ; FOR NOW ONLY BR .-2 .IFF JMP MX.KIL ;EXIT AFTER DUMP .ENDC .IFF .IF DF,SAXCL ;IN STANDALONE, DDT AVAILABLE .IF DF,DODBG ;RESTORE TERMINAL STATUS MOV #TTICSR,R0 ; GET INITAL ADDRESS MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0) JSR R5,S.RRES ;RESTORE TASK REGS OFF STACK JSR PC,U.RSAV ;SAVE CONTEXT CMP @#14,#D.BRK ;DDT SET UP? BEQ 11$ ;YES JMP DDT ;NO 11$: MOV #1,D.S ;SINGLE STEP INT MOV #11,D.CT ;PROCEED COUNT=1 INC D.FFPC ;FLAG HARD INT FLAG BPT ;GO TO DDT TRAP .ENDC .ENDC .ENDC ;---- CONT: ;--- CONTINUE, RESTORE REGS AND EXIT TO CALLER JSR R5,PUTSTP ; ECHO FULL MSG + CMSG JSR R5,PUTWAT ; WAIT FOR DONE .IF DF,$$DOS ; RESTORE STUFF HERE MOV #TTICSR,R0 ; GET INITAL ADDRESS MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0)+ MOV (SP)+,(R0) .ENDC .IF DF,M.MMP ;MULTIPROC SYSTEM FLAGS ABORT FOR ERROR MOV MX.TCB,R0 ;GET CURRENT TCBADDR BNE 1$ ;IF ONE EXISTS THAT IS JMP MX.KIL ;IF NONE EXISTS, HAVE TO DIE! SORRY... 1$: MOVB #10,TCBST(R0) ;SAY ABORT QUEUED MOV #-3,TCBSTT(R0) ;ALSO SAY ERROR CAUSED ABORT CONTCM: .ENDC ; NOW REAL REG MOV (SP)+,R0 MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 MOV (SP)+,R5 ; NOW STACK POINTER AN POP THE TWO WORDS OF PARAMS MOV (SP)+,SP MOV -6(SP),-(SP) ; PLACE RTI PSW IN PROPER SPOT MOV -6(SP),-(SP) ; NOW ISSUE RTI TO EXIT TO CALLER ;NOTE-- IF MULTIPROC VERSION, RETURN VIA SCANNER TO HANDLE TASK ABORT. ;OTHERWISE DO A REAL RTI .IF DF,M.MMP CLRB MX.SEV ;FLAG SIGNIFICANT EVENT HAPPENED... JMP MX.RTI ;CALL SCANNER FOR RTI .IFF RTI .ENDC ; IO SUBROUTINES FOR IOT PROCESSOR ; PUTWRD OUTPUT THE WORD IN R0 IN 6 CHARACTER OCTAL FORMAT PUTWRD: MOV #1,R3 ; SET INITAL BITS MOV #6,R2 ; AND BYTES PWRDC: MOV R0,R1 ; LEAVE R0 FREE FOR PUTCHR PWRD1: CLR R0 ; SET FR NOW BYT PWRD2: ASL R1 ; SHIFT OUT ONE BIT ROL R0 ; AN MOVE TO R0 DEC R3 ; COUNT DOWN BITS BGT PWRD2 ; LOOP OVER BITS/BYTE ADD #'0,R0 ; CONVERT TO ASCII JSR R5,PUTCHR ; AN OUTPUT IT DEC R2 ; COUNT DOWN BYTES BLE PUTXIT ; EXIT IF DONE MOV #3,R3 ; RESET BITS COUN BR PWRD1 ; AND OF FOR NEXT ONE PUTXIT: RTS R5 ; COMMON EXIT (SHARED) ; PUTBYT PUT OUT 3 DIGITS FROM LOW ORDER OF R0 (OCTAL) PUTBYT: SWAB R0 ; FIX UP ORIENTATION MOV #2,R3 ; SET INITAL BIT CUNT MOV #3,R2 ; AN BYTE COUNT BR PWRDC ; AND SHARE CDE ; PUTSTP PUT STRING BY POINTER, PTR IS AT CURRENT (R5) PUTSTP: MOV (R5)+,R1 ; SET STRING POINTER ; PUTSTR PUT A STRING FROM (R1) UNTIL NULL ENCOUNTERED PUTSTR: MOVB (R1)+,R0 ; MOVE NEXT ONE BEQ PUTXIT ; IF NULL, EXIT JSR R5,PUTCHR ; ELSE, OUTPUT IT BR PUTSTR ; AN BACK FOR MORE ; PUTSPC PUT OUT ONE BLANK PUTSPC: MOV #' ,R0 ; LOAD UP REG ; PUTCHR PUT OUT ONE CHRACTE FRM R0 PUTCHR: .IF DF,$$DOS JSR R5,PUTWAT ; WAIT TILL READY MOVB R0,@#TTODBR ; AND ADD NEW ONE .IFF .MCALL QIOW$S MOVB R0,RSX.O ;SAVE CHAR QIOW$S #IO.WVB,#10.,#10.,,#IOSB,,<#RSX.O,#1,#0> .ENDC RTS R5 ; END EI XIT .IF NDF,$$DOS RSX.I: .WORD 0;INPUT BUFFER RSX.O: .WORD 0;OUTPUT BUFFER IOSB: IOST: .WORD 0,0;I/O STATUS BLK .ENDC ; GETCHR GET ONE CHARACTER FROM TTY. GETCHR: .IF DF,$$DOS TSTB @#TTICSR ; WAIT TILL DONE BPL .-4 MOVB @#TTIDBR,R0 ; GET IT TO R0 BIC #177600,R0 ; CLEAR PARITY .IFF QIOW$S #IO.RVB,#10.,#10.,,#IOSB,,<#RSX.I,#1,#0> MOVB RSX.I,R0 BIC #177600,R0 ;READ LUN 10. .ENDC RTS R5 ; AND IEX ; PUTWAT SUSPEND IN LOOP UNTIL KBO IS READY PUTWAT: .IF DF,$$DOS TSTB @#TTOCSR ;READY ? BPL .-4 ; NO, LOP .ENDC RTS R5 ; YES, GO BACK ; TABLES ETC FOR MX.IOT ; ACTION TABLE ACTNTB: .BYTE 'C,2 ; CONTINUE + CONT .BYTE 'D,0 ; DUMP + DUMP .BYTE 'K,0 ; KILL + KILL .BYTE 0,0 ; END OF TABLE CRLF: .BYTE 15,12,'*,0 ; INCLUDES ONE * ERRHD: .ASCII /*** / .BYTE 0 CODE=ERRHD+3 ; TABLE OF VALUES FOR CODE CODETB: .ASCII /IAWF/ ; MESSAGES ETC KMSG: .ASCII /KILL/ .BYTE 15,12,0 DMSG: .ASCII /DUMP/ .BYTE 15,12,0 CMSG: .ASCII /CONT/ .BYTE 15,12,0 BADMSG: .ASCII /?? INVALID RESPONSE/ .BYTE 0 ; STACK SPACE HERE .EVEN .=.+20 ; SPACE FOR LINKAGE .=.+10 ; TTY SAVE AREA .=.+14 ; REGISTERS SPX: + 0 ; INITIAL STACK POINTER .EVEN .END