        IFUND   IODRIVERBODY
IODRIVERBODY    EQU     0
IODRIVERPOLL    EQU     0
IODRIVERRAM     EQU     0
ROMONLY         EQU     1
TEMPX           EQU     0
TIMEOUT:FUSE    EQU     2
        TITLE   COPYRIGHT (C) 1982 PSITECH
        NAME    PSITECH SDOS/MT TIME SHARE PRIMITIVE ROUTINES
        psr     1
        pcc     1
        ifund   m6800
m6800   equ     1
m6809   equ     0
m6801   equ     0
        fin     m6800
        FIN     IODRIVERBODY
        ifund   romonly
romonly equ     0
        fin     romonly
        IF      IODRIVERBODY!ROMONLY
        PAGE    DEFINITIONS
*
*******************************************************************
*
*       SCRATCHPAD ALLOCATION
*
WUBYTES EQU     2
WUJMPX  EQU     3
LIMIT   EQU     4
*
*       SDOS SACRED AREA ALLOCATION
*
USERSPSAVE      EQU     $F1
*
BANKSELECT      EQU     $FFE0          STORE HERE TO SELECT RAM BANK
SYSTEMBANK      EQU     0
INTVECTOR       EQU     $F3F8
ASSIGNPAGETOMAPCONTINUE EQU            $FFEC
USERMAXPAGE     EQU     119            END OF THE WORLD FOR USER MEMORY
IOQUANTUM       EQU     60/20          = 50 MS.
CPUQUANTUM      EQU     60*2           = 2 SECONDS
        PAGE
*               LOCAL SCRATCH PAD
::              SET     *
                ORG     $F000          RAM STORAGE
MTCRASHINFO                            ; SAVE SOME ROOM FOR MT TO TELL
                FDB     0,0,0,0        US HOW HE DIED
NEXTAVAILABLEPAGE                      ; NEXT PHYSICAL PAGE AVAILABLE FOR USER
                FCB     15-1
CONFIGUREDPAGES FCB     15,0,0,0,0,0,0,0 THIS TELLS US NUMBER OF PAGES/USER
USERBANK        RMB     1              WHERE WE KEEP THE USER NUMBER
*SYSTEMSPACEINTPTR                     ; SAVES CONTENTS OF INTVECTOR FOR
*               RMB     2              SYSTEM SPACE
QUANTUM                                ; NUMBER TO 60HZ TICKS LEFT BEFORE
                FCB     0              THIS USER GETS BUMPED
QUANTUMTHRESHOLD
                FCB     0              MINIMUM ABORTABLE TIMESLICE QUANTUM
REMAININGQUANTUM                       ; AMOUNT OF TIMESLICE REMAINING WHEN
                FCB     0              ABORTED

UNSWITCHEDBYTES                        ; 2 BYTES THAT DON'T GET SWITCHED
                RMB     2              (SEE COPYTO...)
SYSTEMSPSAVE    FDB     0              where to save ths system stack pointer
TIMESLICEUP     FDB     0              where to go on quantum done
********* WARNING:
********* IF STACK SPACE HERE IS NOT SUFFICIENT, THE SYSTEM WILL BLOW UP!
********* NEEDS ENOUGH STACK FOR CONTEXT BLOCK, SCRATCH PAD, THE 16 BYTES
********* THAT COPYTO... WILL PUSH, AND A FEW SPARES
*
*       STACK SPACE REQD FOR CTU/S (16+ A FEW)
*       + IRQ CONTEXT (12)
*       + AMMOUNT THAT THE INTERRUPT LEVEL CODE IS ALLOWED TO PUSH
*         ON A TASK LEVEL STACK (8)
*       + NMI (12)
*
        RMB     28+16+10               SPACE FOR INTERRUPT SYSTEM TO PLAY IN
CONTINUESTACK
        if      m6800!m6801
        FCB     $FF     this takes care of the 6800's funny stack pointer
        FCB     $FF     DUMMY CC WITH INTERRUPTS DISABLED
        FCB     0,0     DUMMY B,A REGISTERS
        FDB     0       DUMMY X
        ELSE    (6809)
        FCB     $FF     CC WITH IRQ AND FIRQ MASKED AND THE ENTIRE FLAG SET
        FCB     $AA     A
        FCB     $BB     B
        FCB     $00     Z              MUST BE ZERO FOR USERRTI
        FDB     $1234   X
        FDB     $2345   Y
        FDB     $3456   U
        FIN
        FDB     USERRTI         WHERE TO RETURN TO AFTER SERVICING INTERRUPT
*
        PAGE    INTERRUPT HANDLING LOGIC
        IF      M6800!M6801
        ORG     $F000   WHERE TO PUT THE PRIMITIVE ROUTINES
        FIN
USERSPACESYSCALL ; USER SYSCALL TRANSFERS CONTROL HERE
        IF      M6800!M6801
        STX     TEMPX   PUSH REST OF CONTEXT BLOCK
        LDAA    TEMPX
        LDAB    TEMPX+1
        PSHB            PUSH (X)
        PSHA
        PSHA            PUSH TRASHED (A)
        PSHA            PUSH TRASHED (B)
        CLRA            MAKE AN INTERRUPT-ENABLED CC AND CARRY CLEAR
        ELSE    (6809)
        PSHS    A,B,DP,U,X,Y
        LDAA    #$80                   CARRY CLEAR AND ENTIRE SET
        FIN     M6800...
        PSHA                           PUSH (CC)
        IF      M6800
        NOP                            NO SURPRISES, PLEEZ...
        FIN
        SEI
        IF      M6809
        CLRA
        TFR     A,DP
        FIN
        STS     USERSPSAVE             SAVE USER STACK IN HIS SPACE
        CLR     BANKSELECT
        LDX     #IRQINT                TELL THE INTERRUPT SYSTEM
        STX     INTVECTOR
        LDS     SYSTEMSPSAVE           SWITCH TO SYSTEM TASK'S STACK POINTER
        CLI                            LET THE SUN SHINE AGAIN
        LDAA    QUANTUM
        ADDA    REMAININGQUANTUM
        RTS                            RETURN CONTROL TO SYSTEM TASK

USERSPACEINTERRUPT ; AN INTERRUPT OCCURRING WHILE USER IS RUNNING COMES HERE
        STS     >USERSPSAVE            CONTEXT BLOCK IS PUSHED, SAVE USER SP
        CLR     BANKSELECT             SELECT SYSTEM SPACE
        LDS     #CONTINUESTACK         GIVE INTERRUPT SYSTEM A STACK TO PLAY IN
        LDX     #IRQINT                TELL THE INTERRUPT SYSTEM
        STX     INTVECTOR
        JMP     0,X                    GO TO SYSTEM SPACE INTERRUPT ROUTINE
        PAGE
RETURNTOUSER ; SYSTEM TASK PASSES CONTROL HERE TO LET USER CONTINUE EXECUTION
        STS     SYSTEMSPSAVE            SAVE SYSTEM TASK'S STACK POINTER
        IF      M6800
        NOP             NO SURPRISES, PLEEZ...
        FIN
        SEI
USERRTI ; CONTROL PASSES HERE TO SWITCH ON USER SPACE AND CONTINUE USER
        LDAA    QUANTUM         ANY TIME LEFT FOR THIS USER ?
        BLE     TIMESLICEEXPIRED        B/ NO, KILL HIM!
        LDAA    USERBANK        GET THE USER
        STAA    BANKSELECT
        LDX     #USERSPACEINTERRUPT LET THE INTERRUPT SYSTEM KNOW
        STX     INTVECTOR
        LDS     USERSPSAVE      PICK UP USER'S STACK POINTER
        RTI

TIMESLICEEXPIRED ; USERRTI OCCURRED, BUT QUANTUM IS EXPIRED
        LDS     SYSTEMSPSAVE
        CLI                     ALLOW THE SUNSHINE IN AGAIN
        LDX     TIMESLICEUP     GET WHERE TO GO
        ADDA    REMAININGQUANTUM        TELL /MT HOW MUCH TIME THIS GUY HAD LEFT
        JMP     0,X             AND GO THERE!
*
*       ASSIGN PAGE NUMBER IN (B) TO MAP NUMBER (USERBANK) SLOT (A)
*       RESTORES MAP TO SYSTEM SPACE WHEN FINISHED
*
ASSIGNPAGETOMAP
        LDX     #$FFF0                 SELECT THE RIGHT MAP SLOT
        LEAX    A,X
        LDA     USERBANK
        SEI
*       CONTINUE WHERE WE WON'T SHOOT OURSELVES IN THE FOOT
        JMP     ASSIGNPAGETOMAPCONTINUE
*ASSIGNPAGETOMAPCONTINUE
*       STA     BANKSELECT
*       STB     ,X
*       CLR     BANKSELECT
*       CLI
*       RTS
        PAGE    COPY ACCUMULATORS TO USER/SYSTEM SPACE
copyatouser
         ldb   userbank                    get selected user
         if    m6800
         nop                           traditionally needed to make sei work
         fin
         sei                           no surprises!
         stb   BANKSELECT                  change banks
         sta   0,x                     do dirtywork
         clr   BANKSELECT                  change banks,system bank is zero
         cli
         rts                           finis

copyusertoa
         lda   userbank                    get selected user
         if    m6800
         nop                           traditionally needed to make sei work
         fin
         sei                           no surprises!
         sta   BANKSELECT                  change banks
         lda   0,x                     do dirtywork
         CLR   BANKSELECT                  change banks
         cli
         rts                           finis

copydtouser
         if    m6800!m6801
         pshb
         ldb   userbank                    get selected user
         nop                           traditionally needed to make sei work
         sei                           no surprises!
         stb   BANKSELECT                  change banks
         sta   0,x                     do dirtywork
        CLR     BANKSELECT             change banks
         pula                          get saved b
         stb   BANKSELECT                  change banks
         sta   1,x                     do dirtywork, again
        CLR     BANKSELECT             change banks
         cli
         rts                           finis
         else  (m6809)
         tfr   d,u
         lda   userbank                    get selected user
         sei                           no surprises!
         sta   BANKSELECT                  change banks
         stu   0,x                     do dirtywork
         CLR   BANKSELECT             change banks
         cli
         rts                           finis
         fin

copyusertodx
         lda   userbank                    get selected user
         if    m6800
         nop                           traditionally needed to make sei work
         fin
         sei                           no surprises!
         sta   BANKSELECT                  change banks
         LDD   0,X
         ldx   0,x                     do dirtywork, fast
         CLR   BANKSELECT                  change banks back
         cli
         rts                           finis
       PAGE    COPY TO SYSTEM
        IF      M6800
*       Copy to System space from User Space
*       Entry: (Y) = Destination (Y = memory location TEMPX)
*               (X) = Source address
*               (D) = # bytes to copy
*       Destroys all scratchpad locations
*
CopytoSystem
        STS     SYSTEMSPSAVE    CHANGE TO UNSWITCHABLE STACK POINTER
        LDS     #CONTINUESTACK  LEAVING INTERRUPTS ENABLED!
        STX     FROM    = WHERE TO COPY FROM
        PSHB            SAVE # BYTES TO COPY
        PSHA
        ANDB    #%1111  = NUMBER OF BYTES TO COPY BEFORE REACHING A MULTIPLE OF 16
        BNE     CTSWarmup
        JMP     CTSMAIN
        PAGE
*       CTSWarmup -- Quickly copies blocks of less than 16 bytes in length
*
CTSWarmup
        STAB    WUBYTES         number of bytes for warm-up copy
        EORB    #%1111  COMPUTE 15-# BYTES TO COPY
        STAB    WUFROM+1
        TBA             MULTIPLY # BYTES TO MOVE BY LENGTH OF (LDAA n,X;PSHA) SEQUENCE
        ASLB            = *2
        ABA             = *3
        STAA    WUJMPX  save warm-up jump index
        CLRB
        ADDA    #CTSWarmup1&$FF (D) = ADDRESS OF FIRST INSTRUCTION TO EXECUTE
        ADCB    #CTSWarmup1/256
        PSHA
        PSHB
        LDAA    FROM    GET WHERE TO COPY FROM
        LDAB    FROM+1
        SUBB    WUFROM+1        BECAUSE 6800 CAN'T INDEX BACKWARD
        SBCA    #0
        STAA    WUFROM
        STAB    WUFROM+1
        LDX     WUFROM
        IF      M6800
        NOP             SHUT DOWN THE INTERRUPT SYSTEM,
        FIN
        SEI             CAUSE IT'LL KILL US HERE!
        LDAA    USERBANK
        STAA    BANKSELECT
        RTS             GO TO FIRST INSTRUCTION IN LOOP TO EXECUTE
        PAGE
CTSWarmup1
        LDAA    0,X     FETCH AND PUSH A BYTE
        PSHA
        LDAA    1,X
        PSHA
        LDAA    2,X
        PSHA
        LDAA    3,X
        PSHA
        LDAA    4,X
        PSHA
        LDAA    5,X
        PSHA
        LDAA    6,X
        PSHA
        LDAA    7,X
        PSHA
        LDAA    8,X
        PSHA
        LDAA    9,X
        PSHA
        LDAA    10,X
        PSHA
        LDAA    11,X
        PSHA
        LDAA    12,X
        PSHA
        LDAA    13,X
        PSHA
        LDAA    14,X
        PSHA
        PAGE
        CLR     BANKSELECT
        CLI             RE-ENABLE THE INTERRUPTS HERE!
        LDX     TEMPX   GET WHERE TO COPY TO
        LDAA    WUJMPX  get the previously-computed jump index
        CLRB
        ADDA    #CTSWarmup2&$FF (D) = ADDRESS OF FIRST INSTRUCTION TO EXECUTE
        ADCB    #CTSWarmup2/256
        PSHA
        PSHB
        RTS
        PAGE
CTSWarmup2
        PULA
        STAA    14,X
        PULA
        STAA    13,X
        PULA
        STAA    12,X
        PULA
        STAA    11,X
        PULA
        STAA    10,X
        PULA
        STAA    9,X
        PULA
        STAA    8,X
        PULA
        STAA    7,X
        PULA
        STAA    6,X
        PULA
        STAA    5,X
        PULA
        STAA    4,X
        PULA
        STAA    3,X
        PULA
        STAA    2,X
        PULA
        STAA    1,X
        PULA
        STAA    0,X
        PAGE
        LDAB    WUBYTES adjust from and to pointers due to warm-up operation
        ADDB    FROM+1  UPDATE FROM POINTER
        STAB    FROM+1
        BCC     CTSWarmup2a
        INC     FROM
CTSWarmup2a
        LDAB    WUBYTES
        ADDB    TEMPX+1 ADJUST "TO" POINTER"
        STAB    TEMPX+1
        BCC     CTSWarmup2b
        INC     TEMPX
CTSWarmup2b
*
*       CTS MAIN: COPIES BLOCKS OF 16 BYTES FROM USER TO SYSTEM
*               ASSERT: SYSTEM SPACE IS ENABLED HERE!
*
CTSMAIN PULA
        PULB
*       NOW COMPUTE LIMIT ADDRESS
        ANDB    #%11110000      SUBTRACT OFF # BYTES MOVED BY CTSWARMUP
        ADDB    FROM+1
        ADCA    FROM
        STAA    LIMIT
        STAB    LIMIT+1
CTSGO   LDX     FROM    NOW, GET 16 BYTES
        CPX     LIMIT   DONE?
        BNE     CTSGO2
        LDS     SYSTEMSPSAVE    SWITCH BACK TO THE ORIGINAL STACK POINTER
        RTS
        PAGE
*       COPY A BLOCK OF 16 BYTES
*
CTSGO2
        IF      M6800
        NOP             SHUT DOWN THE INTERRUPT SYSTEM
        FIN
        SEI             (IT'LL ONLY BE OFF FOR ROUGHLY 30 INSTRUCTIONS)
        LDAA    USERBANK
        STAA    BANKSELECT
        LDAA    0,X
        PSHA
        LDAA    1,X
        PSHA
        LDAA    2,X
        PSHA
        LDAA    3,X
        PSHA
        LDAA    4,X
        PSHA
        LDAA    5,X
        PSHA
        LDAA    6,X
        PSHA
        LDAA    7,X
        PSHA
        LDAA    8,X
        PSHA
        LDAA    9,X
        PSHA
        LDAA    $A,X
        PSHA
        LDAA    $B,X
        PSHA
        LDAA    $C,X
        PSHA
        LDAA    $D,X
        PSHA
        LDAA    $E,X
        PSHA
        LDAA    $F,X
        PSHA
        PAGE
        LDAA    #SYSTEMBANK
        STAA    bankselect
        CLI             RE-ENABLE THE INTERRUPT SYSTEM
        LDX     TEMPX   NOW, STORE THE 16 BYTES
        PULA
        STAA    $F,X
        PULA
        STAA    $E,X
        PULA
        STAA    $D,X
        PULA
        STAA    $C,X
        PULA
        STAA    $B,X
        PULA
        STAA    $A,X
        PULA
        STAA    9,X
        PULA
        STAA    8,X
        PULA
        STAA    7,X
        PULA
        STAA    6,X
        PULA
        STAA    5,X
        PULA
        STAA    4,X
        PULA
        STAA    3,X
        PULA
        STAA    2,X
        PULA
        STAA    1,X
        PULA
        STAA    0,X
        PAGE
*       NOW, ADD 16 TO BOTH TO AND FROM
        LDAB    TEMPX+1
        ADDB    #$10
        BCC     ADD16TOTO2S
        INC     TEMPX
ADD16TOTO2S     STAB    TEMPX+1

        LDAB    FROM+1
        ADDB    #$10
        BCC     ADD16TOFROM2S
        INC     FROM
ADD16TOFROM2S   STAB    FROM+1
        JMP     CTSGO
        PAGE    COPY TO USER
*       Copy to User space from System Space
*       Entry: (Y) = Destination (Y = memory location TEMPX)
*               (X) = Source address
*               (D) = # bytes to copy
*       Destroys all scratchpad locations
*
CopytoUser
        STS     SYSTEMSPSAVE    CHANGE TO UNSWITCHABLE STACK POINTER
        LDS     #CONTINUESTACK  LEAVING INTERRUPTS ENABLED!
        STX     FROM    = WHERE TO COPY FROM
        PSHB            SAVE # BYTES TO COPY
        PSHA
        ANDB    #%1111  = NUMBER OF BYTES TO COPY BEFORE REACHING A MULTIPLE OF 16
        BNE     CTUWarmup
        JMP     CTUMAIN
        PAGE
*       CTUWarmup -- Quickly copies blocks of less than 16 bytes in length
*
CTUWarmup
        STAB    WUBYTES         number of bytes for warm-up copy
        EORB    #%1111  COMPUTE 15-# BYTES TO COPY
        STAB    WUFROM+1
        TBA             MULTIPLY # BYTES TO MOVE BY LENGTH OF (LDAA n,X;PSHA) SEQUENCE
        ASLB            = *2
        ABA             = *3
        STAA    WUJMPX  save warm-up jump index
        CLRB
        ADDA    #CTUWarmup1&$FF (D) = ADDRESS OF FIRST INSTRUCTION TO EXECUTE
        ADCB    #CTUWarmup1/256
        PSHA
        PSHB
        LDAA    FROM    GET WHERE TO COPY FROM
        LDAB    FROM+1
        SUBB    WUFROM+1        BECAUSE 6800 CAN'T INDEX BACKWARD
        SBCA    #0
        STAA    WUFROM
        STAB    WUFROM+1
        LDX     WUFROM
        RTS             GO TO FIRST INSTRUCTION IN LOOP TO EXECUTE
        PAGE
CTUWarmup1
        LDAA    0,X     FETCH AND PUSH A BYTE
        PSHA
        LDAA    1,X
        PSHA
        LDAA    2,X
        PSHA
        LDAA    3,X
        PSHA
        LDAA    4,X
        PSHA
        LDAA    5,X
        PSHA
        LDAA    6,X
        PSHA
        LDAA    7,X
        PSHA
        LDAA    8,X
        PSHA
        LDAA    9,X
        PSHA
        LDAA    10,X
        PSHA
        LDAA    11,X
        PSHA
        LDAA    12,X
        PSHA
        LDAA    13,X
        PSHA
        LDAA    14,X
        PSHA
        PAGE
        LDX     TEMPX   GET WHERE TO COPY TO
        LDAA    WUJMPX  get the previously-computed jump index
        CLRB
        ADDA    #CTUWarmup2&$FF (D) = ADDRESS OF FIRST INSTRUCTION TO EXECUTE
        ADCB    #CTUWarmup2/256
        PSHA
        PSHB
        IF      M6800
        NOP             SHUT DOWN THE INTERRUPT SYSTEM,
        FIN
        SEI             CAUSE IT'LL KILL US HERE!
        LDAA    USERBANK
        STAA    BANKSELECT
        RTS
        PAGE
CTUWarmup2
        PULA
        STAA    14,X
        PULA
        STAA    13,X
        PULA
        STAA    12,X
        PULA
        STAA    11,X
        PULA
        STAA    10,X
        PULA
        STAA    9,X
        PULA
        STAA    8,X
        PULA
        STAA    7,X
        PULA
        STAA    6,X
        PULA
        STAA    5,X
        PULA
        STAA    4,X
        PULA
        STAA    3,X
        PULA
        STAA    2,X
        PULA
        STAA    1,X
        PULA
        STAA    0,X
        PAGE
        CLR     BANKSELECT
        CLI             RE-ENABLE THE INTERRUPTS HERE!
        LDAB    WUBYTES adjust from and to pointers due to warm-up operation
        ADDB    FROM+1  UPDATE FROM POINTER
        STAB    FROM+1
        BCC     CTUWarmup2a
        INC     FROM
CTUWarmup2a
        LDAB    WUBYTES
        ADDB    TEMPX+1 ADJUST "TO" POINTER"
        STAB    TEMPX+1
        BCC     CTUWarmup2b
        INC     TEMPX
CTUWarmup2b
*
*       CTU MAIN: COPIES BLOCKS OF 16 BYTES FROM SYSTEM TO USER
*               ASSERT: SYSTEM SPACE IS ENABLED HERE!
*
CTUMAIN PULA
        PULB
*       NOW COMPUTE LIMIT ADDRESS
        ANDB    #%11110000      SUBTRACT OFF # BYTES MOVED BY CTUWARMUP
        ADDB    FROM+1
        ADCA    FROM
        STAA    LIMIT
        STAB    LIMIT+1
CTUGO   LDX     FROM    NOW, GET 16 BYTES
        CPX     LIMIT   DONE?
        BNE     CTUGO2
        LDS     SYSTEMSPSAVE    SWITCH BACK TO THE ORIGINAL STACK POINTER
        RTS
        PAGE
*       COPY A BLOCK OF 16 BYTES
*
CTUGO2
        LDAA    0,X
        PSHA
        LDAA    1,X
        PSHA
        LDAA    2,X
        PSHA
        LDAA    3,X
        PSHA
        LDAA    4,X
        PSHA
        LDAA    5,X
        PSHA
        LDAA    6,X
        PSHA
        LDAA    7,X
        PSHA
        LDAA    8,X
        PSHA
        LDAA    9,X
        PSHA
        LDAA    $A,X
        PSHA
        LDAA    $B,X
        PSHA
        LDAA    $C,X
        PSHA
        LDAA    $D,X
        PSHA
        LDAA    $E,X
        PSHA
        LDAA    $F,X
        PSHA
        PAGE
        LDX     TEMPX   NOW, STORE THE 16 BYTES
        IF      M6800
        NOP             SHUT DOWN THE INTERRUPT SYSTEM
        FIN
        SEI             (IT'LL ONLY BE OFF FOR ROUGHLY 30 INSTRUCTIONS)
        LDAA    USERBANK
        STAA    BANKSELECT
        PULA
        STAA    $F,X
        PULA
        STAA    $E,X
        PULA
        STAA    $D,X
        PULA
        STAA    $C,X
        PULA
        STAA    $B,X
        PULA
        STAA    $A,X
        PULA
        STAA    9,X
        PULA
        STAA    8,X
        PULA
        STAA    7,X
        PULA
        STAA    6,X
        PULA
        STAA    5,X
        PULA
        STAA    4,X
        PULA
        STAA    3,X
        PULA
        STAA    2,X
        PULA
        STAA    1,X
        PULA
        STAA    0,X
        PAGE
        CLR     BANKSELECT
        CLI             RE-ENABLE THE INTERRUPT SYSTEM
*       NOW, ADD 16 TO BOTH TO AND FROM
        LDAB    TEMPX+1
        ADDB    #$10
        BCC     ADD16TOTO2U
        INC     TEMPX
ADD16TOTO2U     STAB    TEMPX+1

        LDAB    FROM+1
        ADDB    #$10
        BCC     ADD16TOFROM2U
        INC     FROM
ADD16TOFROM2U   STAB    FROM+1
        JMP     CTUGO
        ELSE    (6809)
        PAGE    COPY TO SYSTEM
        tabs    9,17
*       Copy to System space from User Space
*       Entry:  (Y) = Destination
*               (X) = Source address
*               (D) = # bytes to copy
*       Destroys all scratchpad locations
*
CopytoSystem
        STS     SYSTEMSPSAVE    CHANGE TO UNSWITCHABLE STACK POINTER
        LDS     #CONTINUESTACK  LEAVING INTERRUPTS ENABLED!
        LEAU    D,X
        STU     LIMIT           = FIRST BYTE NOT COPIED
        BITB    #1              COPYING AN ODD NUMBER OF BYTES ?
        BEQ     CTS.Even        B/ NO
        PSHB                    SAVE LSB OF # BYTES TO COPY...
        LDB     userbank            COPY 1 BYTE TO SYSTEM SPACE
        SEI                     (DISABLE WHILE IN WRONG SPACE)
        STB     BANKSELECT          TO ENSURE BYTE COUNT TO COPY IS EVEN
        LDA     ,X+             FETCH THE BYTE, ADVANCE SOURCE POINTER
        CLR     BANKSELECT             STORE THE BYTE INTO THE SYSTEM SPACE
        CLI                     (SAFE TO RE-ENABLE THE WORLD AGAIN)
        STA     ,Y+             STORE THE BYTE AND ADVANCE THE TARGET POINTER
        PULB                    RESTORE LSB OF BYTE COUNT
CTS.Even ; Number of bytes left to transfer is even
        LEAS    -16,S           MAKE WORK AREA ON STACK
        ANDB    #%1110          = NUMBER OF BYTES TO COPY BEFORE REACHING A MULTIPLE OF 16
        BEQ     CTSMAIN         B/ BLOCK SIZE TO COPY IS ALREADY MULTIPLE OF 16
CTSWarmup ; Quickly copies even blocks of 14 or less bytes in length
        STB     WUBYTES         number of bytes for warm-up copy
        EORB    #%1110          COMPUTE 14-# BYTES TO COPY
        ASLB            = *2
        STB     WUJMPX  save warm-up jump index
        LDU     #CTSWARMUP1
        lda     userbank
        SEI             TURN OFF INTERRUPTS, CAUSE IT'LL KILL US HERE!
        sta     BANKSELECT
        JMP     B,U
        PAGE
CTSWarmup1
        LDD     12,X            start here to copy 14 bytes
        STD     12,S
        LDD     10,X
        STD     10,S
        LDD     8,X
        STD     8,S
        LDD     6,X
        STD     6,S
        LDD     4,X
        STD     4,S
        LDD     2,X
        STD     2,S
        LDD     0,X             start here to copy 2 bytes
        STD     0,S
        CLR     BANKSELECT             switch back to system space
        CLI                     SAFE TO RE-ENABLE THE INTERRUPTS HERE!
        LDB     WUJMPX  get the previously-computed jump index
        LDU     #CTSWARMUP2
        JMP     B,U

CTSWarmup2
        LDD     12,S
        STD     12,Y
        LDD     10,S
        STD     10,Y
        LDD     8,S
        STD     8,Y
        LDD     6,S
        STD     6,Y
        LDD     4,S
        STD     4,Y
        LDD     2,S
        STD     2,Y
        LDD     0,S
        STD     0,Y
        LDB     WUBYTES adjust from and to pointers due to warm-up operation
        LEAX    B,X     UPDATE "FROM" POINTER
        LEAY    B,Y     UPDATE "TO" POINTER
        PAGE
*       CTS MAIN: COPIES BLOCKS OF 16 BYTES FROM USER TO SYSTEM
*               ASSERT: SYSTEM SPACE IS ENABLED HERE!

CTSMAIN CPX     LIMIT           DONE?
        BNE     CTSGO2
        LDS     SYSTEMSPSAVE    SWITCH BACK TO THE ORIGINAL STACK POINTER
        RTS

*       COPY A BLOCK OF 16 BYTES

CTSGO2                          ; SHUT DOWN THE INTERRUPT SYSTEM
        SEI                     ; (IT'LL ONLY BE OFF FOR ROUGHLY 16 INSTRUCTIONS)
        lda     userbank
        sta     BANKSELECT
        LDD     14,X
        STD     14,S
        LDD     12,X
        STD     12,S
        LDD     10,X
        STD     10,S
        LDD     8,X
        STD     8,S
        LDD     6,X
        STD     6,S
        LDD     4,X
        STD     4,S
        LDD     2,X
        STD     2,S
        LDD     0,X
        STD     0,S
        PAGE
        CLR     BANKSELECT
        CLI             RE-ENABLE THE INTERRUPT SYSTEM
        LDD     14,S
        STD     14,Y
        LDD     12,S
        STD     12,Y
        LDD     10,S
        STD     10,Y
        LDD     8,S
        STD     8,Y
        LDD     6,S
        STD     6,Y
        LDD     4,S
        STD     4,Y
        LDD     2,S
        STD     2,Y
        LDD     0,S
        STD     0,Y

*       NOW, ADD 16 TO BOTH "TO" AND "FROM"

        LEAX    16,X
        LEAY    16,Y
        JMP     CTSMAIN
        PAGE    COPY TO USER
*       Copy to User space from System Space
*       Entry:  (Y) = Destination
*               (X) = Source address
*               (D) = # bytes to copy
*       Destroys all scratchpad locations

CopytoUser
        STS     SYSTEMSPSAVE    CHANGE TO UNSWITCHABLE STACK POINTER
        LDS     #CONTINUESTACK  LEAVING INTERRUPTS ENABLED!
        LEAU    D,X
        STU     LIMIT           = FIRST BYTE NOT COPIED
        BITB    #1              COPYING AN ODD NUMBER OF BYTES ?
        BEQ     CTU.Even        B/ NO
        LDA     ,X+             FETCH ONE BYTE, ADVANCE SOURCE POINTER
        PSHB                    SAVE LSB OF # BYTES TO COPY...
        LDB     userbank            MOVE BYTE TO USER SPACE
        SEI                     (DISABLE WHILE IN WRONG SPACE)
        STB     BANKSELECT          TO ENSURE BYTE COUNT TO COPY IS EVEN
        STA     ,Y+             STORE THE BYTE AND ADVANCE THE TARGET POINTER
        CLR     BANKSELECT             STORE THE BYTE INTO THE SYSTEM SPACE
        CLI                     (SAFE TO RE-ENABLE THE WORLD AGAIN)
        PULB                    RESTORE LSB OF BYTE COUNT
CTU.Even ; Number of bytes left to transfer is even
        LEAS    -16,S           MAKE WORK AREA ON STACK
        ANDB    #%1110          = NUMBER OF BYTES TO COPY BEFORE REACHING A MULTIPLE OF 16
        BEQ     CTUMAIN         B/ multiple of 16, go copy!
CTUWarmup ; Quickly copies even blocks of 14 or less bytes in length
        STB     WUBYTES         number of bytes for warm-up copy
        EORB    #%1110          COMPUTE 14-# BYTES TO COPY
        ASLB                    = *2
        STB     WUJMPX          save warm-up jump index
        LDU     #CTUWARMUP1
        JMP     B,U
        PAGE
CTUWarmup1
        LDD     12,X            start here to copy 14 bytes
        STD     12,S
        LDD     10,X
        STD     10,S
        LDD     8,X
        STD     8,S
        LDD     6,X
        STD     6,S
        LDD     4,X
        STD     4,S
        LDD     2,X
        STD     2,S
        LDD     0,X             start here to copy 2 bytes
        STD     0,S
        LDU     #CTUWARMUP2
        LDB     WUJMPX  get the previously-computed jump index (stored in system space)
        lda     userbank    switch in the user space
        SEI             TURN OFF INTERRUPTS, CAUSE IT'LL KILL US HERE!
        sta     BANKSELECT
        JMP     B,U

CTUWarmup2
        LDD     12,S
        STD     12,Y
        LDD     10,S
        STD     10,Y
        LDD     8,S
        STD     8,Y
        LDD     6,S
        STD     6,Y
        LDD     4,S
        STD     4,Y
        LDD     2,S
        STD     2,Y
        LDD     0,S
        STD     0,Y
        CLR     BANKSELECT
        CLI             RE-ENABLE THE INTERRUPTS HERE!
        LDB     WUBYTES adjust from and to pointers due to warm-up operation
        LEAX    B,X     UPDATE "FROM" POINTER
        LEAY    B,Y     UPDATE "TO" POINTER
        PAGE
*       CTU MAIN: COPIES BLOCKS OF 16 BYTES FROM SYSTEM TO USER
*               ASSERT: SYSTEM SPACE IS ENABLED HERE!

CTUMAIN CPX     LIMIT           DONE?
        BNE     CTUGO2
        LDS     SYSTEMSPSAVE    SWITCH BACK TO THE ORIGINAL STACK POINTER
        RTS

*       COPY A BLOCK OF 16 BYTES

CTUGO2  LDD     14,X
        STD     14,S
        LDD     12,X
        STD     12,S
        LDD     10,X
        STD     10,S
        LDD     8,X
        STD     8,S
        LDD     6,X
        STD     6,S
        LDD     4,X
        STD     4,S
        LDD     2,X
        STD     2,S
        LDD     0,X
        STD     0,S
        PAGE
                                ; SHUT DOWN THE INTERRUPT SYSTEM
        SEI                     ; (IT'LL ONLY BE OFF FOR ROUGHLY 16 INSTRUCTIONS)
        lda     userbank
        sta     BANKSELECT
        LDD     14,S
        STD     14,Y
        LDD     12,S
        STD     12,Y
        LDD     10,S
        STD     10,Y
        LDD     8,S
        STD     8,Y
        LDD     6,S
        STD     6,Y
        LDD     4,S
        STD     4,Y
        LDD     2,S
        STD     2,Y
        LDD     0,S
        STD     0,Y
        clr     BANKSELECT      system bank is zero
        CLI             RE-ENABLE THE INTERRUPT SYSTEM

*       NOW, ADD 16 TO BOTH "TO" AND "FROM"

        LEAX    16,X
        LEAY    16,Y
        JMP     CTUMAIN
        FIN     M6800
        PAGE    NOW FOR THE STUFF THAT GOES IN THE IOPACK
        ORG     ::
        FIN     IODRIVERBODY!ROMONLY
        IF      IODRIVERBODY

*       TS PRIMITIVE JUMP TABLE
*
        JMP     ABORTQUANTUM            CALLED BY VT DRIVER TO ABORT A ....
PRIMITIVETABLE
        FDB     LENPRIMITIVETABLE       TELL HOW LONG THE TABLE IS
        JMP     USERSPACESYSCALL
        JMP     USERSELECT
        JMP     USERCURRENTSIZE
        JMP     RETURNTOUSER
        JMP     SETQUANTUM
        JMP     COPYTOSYSTEM
        JMP     COPYTOUSER
        JMP     COPYUSERTODX
        JMP     COPYATOUSER
        JMP     COPYDTOUSER
        JMP     COPYUSERTOA
        JMP     SETFUSE
        JMP     TESTFUSE
        FDB     MTCRASHINFO
        FCB     IOQUANTUM,CPUQUANTUM
LENPRIMITIVETABLE       EQU     *-PRIMITIVETABLE-2
        PAGE
SETQUANTUM ; (A) = REMAINING USER TIME SLICE; (X) = QUANTUM-END ROUTINE
; (B) = MINIMUM ABORTABLE REMAINING QUANTUM
        STAA    QUANTUM SAVE REMAINING TIME SLICE
        STAB    QUANTUMTHRESHOLD        SAVE MIN TIME SLICE
        STX     TIMESLICEUP
        CLR     REMAININGQUANTUM        REMEMBER 'QUANTUM NOT ABORTED'
        RTS

ABORTQUANTUM ; ABORT USER QUANTUM IF GREATER THAN QUANTUMTHRESHOLD
        LDAA    QUANTUM         HOW MUCH WAMPUM LEFT ?
        CMPA    QUANTUMTHRESHOLD
        BLE     ABORTQUANTUM.RTS        B/ NOT ENOUGH, DON'T ABORT
        STAA    REMAININGQUANTUM        REMEMBER REMAINING FOR TIMESLICEEXPIRED
        CLR     QUANTUM         FORCE USERRTI TO DO TIMESLICEEXPIRED
ABORTQUANTUM.RTS
        RTS

mt:CLOCKTICKED ; SDOS:CLOCKTICKED RE-AIMED HERE
        TFR     A,B                    = # TICKS PASSED
        LDAA    QUANTUM = TICKS REMAINING
        SBA            = # LEFT
        BVC     mt:CLOCKTICKED2 B/ SOME LEFT
        LDAA    #-128            QUANTUM UNDERFLOWED
mt:CLOCKTICKED2
        STAA    QUANTUM SAVE REMAINING QUANTUM
        TFR     B,A            RESTORE (A)
        JMP     SDOS+SDOS:CLOCKTICKED

SETFUSE STX     mt:FUSE+TIMEOUT:FUSE
        RTS

TESTFUSE        LDX     mt:FUSE+TIMEOUT:FUSE
        RTS

mt:FUSE FDB     nexttimeout    POINTER TO NEXT TIMEOUTBLOCK
        FDB     0       TIMEOUT:FUSE
        FDB     FUSEBURNEDUP   WHERE TO GO IF FUSE EXPIRES
nexttimeout     set     mt:fuse

FUSEBURNEDUP
        BSR     ABORTQUANTUM
        JMP     SDOS+SDOS:RTI
        PAGE
USERCURRENTSIZE
        LDY     #CONFIGUREDPAGES       GET LIST OF PAGES FOR EACH USER
        LDA     USERBANK               GET USER NUMBER
        LEAY    A,Y                    FIND OUT HOW MANY PAGES FOR THIS USER
        LDA     ,Y
        BNE     USERCURSIZE2           B/ HIS MAP IS ALREADY SETUP, D HAS SIZE
        LDD     #$0FFF                 SET UP THE I/O PAGE
        JSR     ASSIGNPAGETOMAP
USERCURSIZE1
        INC     NEXTAVAILABLEPAGE
        LDB     NEXTAVAILABLEPAGE      GO GRAB A PAGE
        CMPB    #USERMAXPAGE+1         0..254 IS RAM, 255 IS I/O PAGE
        BEQ     USERCURSIZE2           B/ NONE LEFT
        LDA     #$E                    ASSIGN PAGE (B) TO USERBANK, SLOT $E
        JSR     ASSIGNPAGETOMAP
        LDX     #$E000                 GO TEST MEMORY ASSIGNED TO SLOT $E
        JSR     COPYUSERTOA            READ WHATS OUT THERE
        COMA
        PSHS    A
        JSR     COPYATOUSER
        JSR     COPYUSERTOA
        CMPA    ,S+                    SMELL LIKE MEMORY?
        BNE     USERCURSIZE1           B/ NO, THIS PAGE IS NOT RAM
        LDB     NEXTAVAILABLEPAGE      GET PAGE NUMBER
        LDA     ,Y                     GET SLOT NUMBER
        JSR     ASSIGNPAGETOMAP        ASSIGN PAGE (B) TO USERBANK, SLOT (A)
        INC     ,Y                     COUNT IT
        LDA     ,Y
        CMPA    #15
        BNE     USERCURSIZE1           B/ NO
USERCURSIZE2
        CLRB
        LDA     ,Y                     GET NUMBER OF PAGES OF RAM
        ASLA
        ASLA
        ASLA
        ASLA
        RTS
        PAGE
*       USERSELECT -- FOCUSES ADDRESS SPACE SWITCHING LOGIC ON USER (A)
*
USERSELECT
        CMPA    #7      this is as high as this configuration goes
        BHI     USERSELECT.ERROR
        STAA    USERBANK
*       LDX     INTVECTOR       SAVE COPY OF SYSTEM SPACE INTERRUPT VECTOR
*       STX     SYSTEMSPACEINTPTR       (AFTER 1ST CALL THIS IS REDUNDANT BUT CHEAP)
        CLC
        RTS

USERSELECT.ERROR
        SEC
        RTS
        FIN     IODRIVERBODY
        END
