home *** CD-ROM | disk | FTP | other *** search
- * Support code from Micro Cornucopia Magazine Issue #48
-
- * Micro Cornucopia
- * PO Box 223
- * Bend, OR 97709
-
-
-
- *
- * MTASK
- *
- * This program serves as a cooperative-type multi-task controller
- * for the Mini-Frame. It provides an appropriate set of I/O routines,
- * until those routines can be installed in ROM.
- *
-
-
- GETC0 EQU $800032 GET CHAR FROM CHANNEL 0
- GETC1 EQU $800038 GET CHAR FROM CHANNEL 1
- PUTC0 EQU $800044 WRITE CHAR TO CHANNEL 0
- PUTC1 EQU $80004A WRITE CHAR TO CHANNEL 1
- KEY0 EQU $800056 CHECK FOR KEY ON CHANNEL 0
- KEY1 EQU $80005C CHECK FOR KEY ON CHANNEL 1
- WARMS EQU $80000E WARM START ENTRY TO MONITOR
- PRINTF EQU $800020 PRINTF ENTRY POINT
-
-
- ORG $3D000 PUT SOMEWHERE SAFE FROM SK*DOS
-
-
- START BRA MTASK START THE MULTI-TASK SYSTEM
- BRA PSTAT PRINT OUT STATS ON ALL TASKS
-
- *
- * The following equates are offsets into the task description
- * block.
- *
-
- STKPTR: EQU 0 STACK POINTER (LONG)
- VALID: EQU 4 VALID FLAG (2 BYTES)
- STARTS: EQU 6 STARTUP ADDRESS (LONG)
- INV: EQU 10 VECTOR FOR CHAR IN (LONG)
- OUTV: EQU 14 VECTOR FOR CHAR OUT (LONG)
- KEYPRSDV: EQU 18 VECTOR FOR KEYPRESSED (LONG)
- STATUS: EQU 22 STATUS BYTE (1 BYTE)
- TEMP1: EQU 23 RESERVED (1 BYTE)
- COUNT: EQU 24 ACTIVATION COUNT
- TEMP2: EQU 28 RESERVED (LONG)
- NAME: EQU 32 TASK NAME (8 BYTES)
- STKSIZE: EQU $200 ROOM FOR EACH TASK'S STACK
-
-
- TASK0SP EQU $3E000 TASK 0 STACK POINTER
- TASK1SP EQU TASK0SP+STKSIZE TASK 1 STACK POINTER
- TASK2SP EQU TASK1SP+STKSIZE TASK 2 STACK POINTER
-
- *
- * The following equates may need to be adjusted if the ROM routines
- * change.
- *
-
- GETCRAM2 EQU $E00+2 RAM VECTOR FOR GETC
- PUTCRAM2 EQU $E06+2 RAM VECTOR FOR PUTC
- KEYRAM2 EQU $E0C+2 RAM VECTOR FOR KEYPRSD
-
- INV0:
- BSR KEYV0 CHECK FOR KEY PRESSED
- BCC INV0 LOOP UNTIL CHAR AVAILABLE
- JSR GETC0 GO GET THE CHAR
- RTS AND RETURN
-
-
- INV1:
- BSR KEYV1 TEST FOR CHAR
- BCC INV1 LOOP UNTIL CHAR AVAILABLE
- JSR GETC1 GO GET THE CHAR
- RTS AND RETURN
-
-
-
- OUTV0:
- BSR PAUSE TIME FOR A SLICE
- MOVE.W 4(A7),-(A7) PUSH THE CHARACTER AGAIN
- JSR PUTC0 SEND CHAR TO PORT
- ADDQ.L #2,A7 POP THE CHARACTER AND RETURN
- RTS
-
-
- OUTV1:
- BSR PAUSE GUESS WHAT?
- MOVE.W 4(A7),-(A7) PUSH THE CHARACTER AGAIN
- JSR PUTC1 SEND CHAR TO PORT
- ADDQ.L #2,A7 POP THE CHARACTER AND RETURN
- RTS
-
-
- KEYV0:
- BSR PAUSE
- JSR KEY0 GO LOOK AT KEYBOARD
- RTS
-
-
- KEYV1:
- BSR PAUSE
- JSR KEY1 GO LOOK AT KEYBOARD
- RTS
-
-
- *
- * MTASK
- *
- * This routine starts the multi-task kernel:
- *
- * It prepares task 0 for activation.
- *
- * It jumps to the execution address in the TDB to start task 0.
- *
-
- MTASK:
- LEA CURRENT(PC),A0 POINT TO CURRENT TASK
- CLR.W 0(A0) SHOW TASK 0
- MOVE.L #TASK0SP,A7 SET UP TASK 0 STACK POINTER
- LEA INV0(PC),A0 GET INPUT VECTOR
- MOVE.L A0,GETCRAM2 OVERWRITE MONITOR'S LINK
- LEA OUTV0(PC),A0 DO OTHER VECTORS
- MOVE.L A0,PUTCRAM2
- LEA KEYV0(PC),A0
- MOVE.L A0,KEYRAM2
- MOVE.L #WARMS,-(A7) PUSH ENTRY TO ROM MONITOR
- RTS
-
-
-
- *
- * PSTAT
- *
- * Print statistics on all tasks to the current I/O device.
- *
- * It is designed to be called from the monitor with a GO
- * command. The RTS at the end of the code will return the
- * user back to the monitor.
- *
-
- PSTAT:
- PEA HEADING(PC) AIM AT HEADING MESSAGE
- JSR PRINTF
- ADDQ.L #4,A7
- LEA RAMTBL(PC),A0 AIM A0 AT RAM TABLE
- CLR.W D1 START WITH TASK 0
-
- PSTAT1:
- MOVE.W #BLKSIZE,D0 GET SIZE OF CONFIG BLOCK
- MULS D1,D0 GET OFFSET INTO ARRAY
- MOVE.L INV(A0,D0.W),D2 GET INPUT VECTOR
- CMP.L #INV0,D2 IS HE USING PORT 0?
- BNE PSTAT2 BRANCH IF NOT
- PEA PORT0(PC) PUSH PORT 0 STRING
- BRA PSTAT4
- PSTAT2:
- CMP.L #INV1,D2 IS HE USING PORT 1?
- BNE PSTAT3 BRANCH IF NOT
- PEA PORT1(PC) PUSH PORT 1 STRING
- BRA PSTAT4
- PSTAT3:
- PEA PORTX(PC) UNKNOWN PORT
- PSTAT4:
- MOVE.L COUNT(A0,D0.L),-(A7) PUSH ACTIVATION COUNT
- MOVE.L STKPTR(A0,D0.L),-(A7) PUSH STACK POINTER
- LEA.L NAME(A0,D0.L),A1 POINT TO NAME IN BLOCK
- LEA NAMESTR(PC),A2 POINT TO LOCAL NAME STRING
- MOVEQ #8,D2 LOAD A COUNTER
- PSTAT5:
- MOVE.B (A1)+,(A2)+ COPY A BYTE
- SUBQ.L #1,D2 COUNT THIS BYTE
- BNE PSTAT5 LOOP UNTIL DONE
- CLR.B (A2) CLEAR THE TERMINATING BYTE
- PEA NAMESTR(PC) PUSH NAME STRING
- PEA STATMSG(PC) SHOW THE STAT MESSAGE
- JSR PRINTF
- ADD.L #20,A7
- ADDQ.W #1,D1 GO TO NEXT TASK
- CMP.W #LASTTASK,D1 SEE IF ALL DONE
- BLE PSTAT1 KEEP PRINTING UNTIL DONE
- PEA FINALMSG(PC) PRINT FINAL MESSAGE
- JSR PRINTF
- ADDQ.L #4,A7
- RTS
-
-
- HEADING:
- DC.B $0D,$0A,$0A
- DC.B ' '
- DC.B 'Stack '
- DC.B 'Activation '
- DC.B ' '
- DC.B ' '
- DC.B $0D,$0A
- DC.B 'Name '
- DC.B 'Pointer '
- DC.B 'Count '
- DC.B 'I/O device '
- DC.B ' '
- DC.B $0D,$0A
- DC.B '-----------'
- DC.B '-----------'
- DC.B '-----------'
- DC.B '-----------'
- DC.B '-----------'
- DC.B $0D,$0A
- DC.B 0
-
- STATMSG:
- DC.B '%-11s%-11X%-11X%-11s'
- DC.B $0D,$0A
- DC.B 0
-
- FINALMSG:
- DC.B $0D,$0A
- DC.B 0
-
- PORT0:
- DC.B 'CHNL 0'
- DC.B 0
-
- PORT1:
- DC.B 'CHNL 1'
- DC.B 0
-
- PORTX:
- DC.B 'UNKNOWN'
- DC.B 0
-
-
-
-
- *
- * PAUSE
- *
- * This is the heart of the multi-task controller. It switches
- * tasks each time it is invoked. Normally, it is invoked automatically
- * each time an I/O request is made. Additionally, it may be invoked
- * explicitly by a routine to force a task switch (in the interest
- * of fairness).
- *
-
- PAUSE:
- MOVEM.L D0-D7/A0-A7,-(A7) SAVE ALL REGISTERS
- LEA CURRENT(PC),A0 POINT TO CURRENT TASK
- MOVE.W 0(A0),D0 PUT IN D0
- MOVE.W D0,D2 SAVE CURRENT TASK IN D2
- LEA RAMTBL(PC),A0 POINT TO RAM TABLE
- MULS #BLKSIZE,D2 MAKE A BLOCK POINTER
- ADD.L D2,A0 POINT A0 AT THIS TASK'S BLOCK
- MOVE.L A7,STKPTR(A0) SAVE CURRENT STACK POINTER
-
- PAUSE0:
- CMP.W #LASTTASK,D0 IS THIS THE LAST TASK?
- BNE PAUSE1 BRANCH IF NOT
- CLR.W D0 GO BACK TO TASK 0
- BRA PAUSE2
- PAUSE1:
- ADDQ.W #1,D0 GO TO NEXT TASK
- PAUSE2:
- LEA CURRENT(PC),A0 POINT TO CURRENT TASK
- MOVE.W D0,0(A0) SAVE CURRENT TASK
- MOVE.W D0,D2
- MULS #BLKSIZE,D2 LEAVE D2 AS A BLOCK POINTER
- LEA RAMTBL(PC),A0 GET ADDRESS OF TASK TABLE
- ADD.L D2,A0 POINT A0 AT NEW TASK'S TABLE
- CMP.W #'VL',VALID(A0) IS THIS A VALID TASK?
- BNE PAUSE0 IF NOT, GO TRY NEXT ONE
- MOVE.B STATUS(A0),D1 GET STATUS OF NEW TASK
- BTST.B #ACTIVE,D1 CHECK THE ACTIVE BIT
- BEQ PAUSE0 THIS GUY IS INACTIVE, TRY AGAIN
- BTST.B #STARTUP,D1 HOW ABOUT THE STARTUP BIT?
- BEQ PAUSE3 NO, MUST BE FULLY ACTIVE
- MOVE.L STKPTR(A0),A7 PUT NEW STACK POINTER INTO A7
- MOVE.L STARTS(A0),-(A7) PUSH THE STARTUP ADDRESS
- MOVEM.L D0-D7/A0-A7,-(A7) PUSH ALL REGISTERS (DUMMY)
- BSET.B #ACTIVE,D1 SHOW THIS TASK AS ACTIVE
- BCLR.B #STARTUP,D1 SHOW THIS TASK AS STARTED
- MOVE.B D1,STATUS(A0) SAVE NEW STATUS
- BRA PAUSEX GO GET HIM STARTED
-
- PAUSE3:
- MOVE.L STKPTR(A0),A7 GET THE NEW STACK POINTER
-
- PAUSEX:
- ADDQ.L #1,COUNT(A0) INCREMENT THE ACTIVATION COUNT
- MOVE.L INV(A0),GETCRAM2
- MOVE.L OUTV(A0),PUTCRAM2
- MOVE.L KEYPRSDV(A0),KEYRAM2
- MOVEM.L (A7)+,D0-D7/A0-A7 RESTORE ALL REGISTERS
- RTS TRANSFER TO NEW TASK
-
- *
- * BLINKER
- *
- * This is a simple test program to verify that the multi-task
- * activity is taking place.
- *
-
- BLINKER:
- BSR PAUSE GIVE THE OTHER GUY A SHOT
- LEA RAMTBL(PC),A0 POINT TO RAM TABLE
- MOVE.W #2,D0 GET OUR TASK NUMBER (KINDA CHEATING)
- MULS #BLKSIZE,D0 NOW MAKE D0 POINT TO OUR TASK BLOCK
- MOVE.L COUNT(A0,D0.L),D0 GET CURRENT ACTIVATION COUNT
- BTST.L #12,D0 LOOK AT A SPECIAL BIT
- BNE BLNK_ON IF SET, TURN LIGHT ON
- MOVE.L #$3F00,$450000 NOT, SO TURN LED OFF
- BRA BLINKER LOOP FOREVER
- BLNK_ON:
- MOVE.L #$3E00,$450000
- BRA BLINKER
-
-
-
- *
- * The following equates are bit patterns used in the status byte.
- *
- ACTIVE: EQU 0 BIT 0, TRUE = ACTIVE
- STARTUP: EQU 1 BIT 1, TRUE = NOT YET STARTED
-
- ACTIVE_ST: EQU $01 STATE = ACTIVE AND STARTED
- UNSTARTED_ST: EQU $03 STATE = ACTIVE AND UNSTARTED
- SLEEP_ST: EQU $00 STATE = NOT ACTIVE AND UNSTARTED
-
- *
- * The following table is the initialized version of the task tables.
- *
-
-
- RAMTBL:
-
- *
- * TASK 0
- *
- DC.L TASK0SP STACK POINTER, TASK 0
- DC.B 'V','L' VALID FLAGS
- DC.L WARMS STARTUP ADDRESS
- DC.L INV0 INPUT VECTOR
- DC.L OUTV0 OUTPUT VECTOR
- DC.L KEYV0 KEYPRESSED VECTOR
- DC.B ACTIVE_ST STATUS BYTE (ALREADY ACTIVE)
- DC.B 0 RESERVED
- DC.L 0 ACTIVATION COUNT
- DC.L 0 RESERVED
- DC.B 'TASK_0',0,0
-
- BLKSIZE EQU 40 NUMBER OF BYTES IN BLOCK
-
-
- *
- * TASK 1
- *
- DC.L TASK1SP STACK POINTER, TASK 1
- DC.B 'V','L' VALID FLAGS
- DC.L WARMS STARTUP ADDRESS (ROM MONITOR)
- DC.L INV1 INPUT VECTOR
- DC.L OUTV1 OUTPUT VECTOR
- DC.L KEYV1 KEYPRESSED VECTOR
- DC.B UNSTARTED_ST STATUS BYTE (ACTIVE, UNSTARTED)
- DC.B 0 RESERVED
- DC.L 0 ACTIVATION COUNT
- DC.L 0 RESERVED
- DC.B 'TASK_1',0,0
-
-
- *
- * TASK 2 (Dummy activity to show multi-task activity)
- *
-
- DC.L TASK2SP STACK POINTER, TASK 2
- DC.B 'V','L' VALID FLAGS
- DC.L BLINKER STARTUP ADDRESS
- DC.L 0 INPUT VECTOR
- DC.L 0 OUTPUT VECTOR
- DC.L 0 KEYPRESSED VECTOR
- DC.B UNSTARTED_ST STATUS BYTE (ACTIVE, UNSTARTED)
- DC.B 0 RESERVED
- DC.L 0 ACTIVATION COUNT
- DC.L 0 RESERVED
- DC.B 'BLINKER',0
-
- LASTTASK: EQU 2 NUMBER OF LAST LEGAL TASK
-
-
- *
- * RAM area used by the multi-user system.
- *
-
- CURRENT:
- DC.W 0 NUMBER OF CURRENT TASK
- NAMESTR:
- RMB 10 RESERVED FOR STAT ROUTINE
-
-
- END START
-
-