home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / microcrn / issue_48.arc / MTASK.ARC / MTASK.ASM
Encoding:
Assembly Source File  |  1989-05-16  |  13.4 KB  |  402 lines

  1. *  Support code from Micro Cornucopia Magazine Issue #48
  2.  
  3. *  Micro Cornucopia
  4. *  PO Box 223
  5. *  Bend, OR 97709
  6.  
  7.  
  8.  
  9. *
  10. *  MTASK
  11. *
  12. *  This program serves as a cooperative-type multi-task controller
  13. *  for the Mini-Frame.  It provides an appropriate set of I/O routines,
  14. *  until those routines can be installed in ROM.
  15. *
  16.  
  17.  
  18. GETC0    EQU      $800032             GET CHAR FROM CHANNEL 0
  19. GETC1    EQU      $800038             GET CHAR FROM CHANNEL 1
  20. PUTC0    EQU      $800044             WRITE CHAR TO CHANNEL 0
  21. PUTC1    EQU      $80004A             WRITE CHAR TO CHANNEL 1
  22. KEY0     EQU      $800056             CHECK FOR KEY ON CHANNEL 0
  23. KEY1     EQU      $80005C             CHECK FOR KEY ON CHANNEL 1
  24. WARMS    EQU      $80000E             WARM START ENTRY TO MONITOR
  25. PRINTF   EQU      $800020             PRINTF ENTRY POINT
  26.  
  27.  
  28.          ORG      $3D000              PUT SOMEWHERE SAFE FROM SK*DOS
  29.  
  30.  
  31. START    BRA      MTASK               START THE MULTI-TASK SYSTEM
  32.          BRA      PSTAT               PRINT OUT STATS ON ALL TASKS
  33.  
  34. *
  35. *  The following equates are offsets into the task description
  36. *  block.
  37. *
  38.  
  39. STKPTR:   EQU     0                   STACK POINTER (LONG)
  40. VALID:    EQU     4                   VALID FLAG (2 BYTES)
  41. STARTS:   EQU     6                   STARTUP ADDRESS (LONG)
  42. INV:      EQU     10                  VECTOR FOR CHAR IN (LONG)
  43. OUTV:     EQU     14                  VECTOR FOR CHAR OUT (LONG)
  44. KEYPRSDV: EQU     18                  VECTOR FOR KEYPRESSED (LONG)
  45. STATUS:   EQU     22                  STATUS BYTE (1 BYTE)
  46. TEMP1:    EQU     23                  RESERVED (1 BYTE)
  47. COUNT:    EQU     24                  ACTIVATION COUNT
  48. TEMP2:    EQU     28                  RESERVED (LONG)
  49. NAME:     EQU     32                  TASK NAME (8 BYTES)
  50. STKSIZE:  EQU     $200                ROOM FOR EACH TASK'S STACK
  51.  
  52.  
  53. TASK0SP  EQU      $3E000              TASK 0 STACK POINTER
  54. TASK1SP  EQU      TASK0SP+STKSIZE     TASK 1 STACK POINTER
  55. TASK2SP  EQU      TASK1SP+STKSIZE     TASK 2 STACK POINTER
  56.  
  57. *
  58. *  The following equates may need to be adjusted if the ROM routines
  59. *  change.
  60. *
  61.  
  62. GETCRAM2 EQU      $E00+2              RAM VECTOR FOR GETC
  63. PUTCRAM2 EQU      $E06+2              RAM VECTOR FOR PUTC
  64. KEYRAM2  EQU      $E0C+2              RAM VECTOR FOR KEYPRSD
  65.  
  66. INV0:
  67.         BSR       KEYV0               CHECK FOR KEY PRESSED
  68.         BCC       INV0                LOOP UNTIL CHAR AVAILABLE
  69.         JSR       GETC0               GO GET THE CHAR
  70.         RTS                           AND RETURN
  71.  
  72.  
  73. INV1:
  74.         BSR       KEYV1               TEST FOR CHAR
  75.         BCC       INV1                LOOP UNTIL CHAR AVAILABLE
  76.         JSR       GETC1               GO GET THE CHAR
  77.         RTS                           AND RETURN
  78.  
  79.  
  80.  
  81. OUTV0:
  82.         BSR       PAUSE               TIME FOR A SLICE
  83.         MOVE.W    4(A7),-(A7)         PUSH THE CHARACTER AGAIN
  84.         JSR       PUTC0               SEND CHAR TO PORT
  85.         ADDQ.L    #2,A7               POP THE CHARACTER AND RETURN
  86.         RTS
  87.  
  88.  
  89. OUTV1:
  90.         BSR       PAUSE               GUESS WHAT?
  91.         MOVE.W    4(A7),-(A7)         PUSH THE CHARACTER AGAIN  
  92.         JSR       PUTC1               SEND CHAR TO PORT
  93.         ADDQ.L    #2,A7               POP THE CHARACTER AND RETURN
  94.         RTS                          
  95.  
  96.  
  97. KEYV0:
  98.         BSR       PAUSE
  99.         JSR       KEY0                GO LOOK AT KEYBOARD
  100.         RTS
  101.  
  102.  
  103. KEYV1:
  104.         BSR       PAUSE
  105.         JSR       KEY1                GO LOOK AT KEYBOARD
  106.         RTS
  107.  
  108.  
  109. *
  110. *  MTASK
  111. *
  112. *  This routine starts the multi-task kernel:
  113. *
  114. *    It prepares task 0 for activation.
  115. *
  116. *    It jumps to the execution address in the TDB to start task 0.
  117. *
  118.  
  119. MTASK:
  120.         LEA       CURRENT(PC),A0      POINT TO CURRENT TASK
  121.         CLR.W     0(A0)               SHOW TASK 0
  122.         MOVE.L    #TASK0SP,A7         SET UP TASK 0 STACK POINTER
  123.         LEA       INV0(PC),A0         GET INPUT VECTOR
  124.         MOVE.L    A0,GETCRAM2         OVERWRITE MONITOR'S LINK
  125.         LEA       OUTV0(PC),A0        DO OTHER VECTORS
  126.         MOVE.L    A0,PUTCRAM2
  127.         LEA       KEYV0(PC),A0
  128.         MOVE.L    A0,KEYRAM2        
  129.         MOVE.L    #WARMS,-(A7)        PUSH ENTRY TO ROM MONITOR
  130.         RTS                          
  131.  
  132.  
  133.  
  134. *
  135. *  PSTAT
  136. *
  137. *  Print statistics on all tasks to the current I/O device.
  138. *
  139. *  It is designed to be called from the monitor with a GO
  140. *  command.  The RTS at the end of the code will return the
  141. *  user back to the monitor.
  142. *
  143.  
  144. PSTAT:
  145.         PEA       HEADING(PC)         AIM AT HEADING MESSAGE
  146.         JSR       PRINTF
  147.         ADDQ.L    #4,A7
  148.         LEA       RAMTBL(PC),A0       AIM A0 AT RAM TABLE
  149.         CLR.W     D1                  START WITH TASK 0
  150.  
  151. PSTAT1:
  152.         MOVE.W    #BLKSIZE,D0         GET SIZE OF CONFIG BLOCK
  153.         MULS      D1,D0               GET OFFSET INTO ARRAY 
  154.         MOVE.L    INV(A0,D0.W),D2     GET INPUT VECTOR
  155.         CMP.L     #INV0,D2            IS HE USING PORT 0?
  156.         BNE       PSTAT2              BRANCH IF NOT
  157.         PEA       PORT0(PC)           PUSH PORT 0 STRING
  158.         BRA       PSTAT4
  159. PSTAT2:
  160.         CMP.L     #INV1,D2            IS HE USING PORT 1?
  161.         BNE       PSTAT3              BRANCH IF NOT
  162.         PEA       PORT1(PC)           PUSH PORT 1 STRING
  163.         BRA       PSTAT4
  164. PSTAT3:
  165.         PEA       PORTX(PC)           UNKNOWN PORT
  166. PSTAT4:
  167.         MOVE.L    COUNT(A0,D0.L),-(A7)   PUSH ACTIVATION COUNT
  168.         MOVE.L    STKPTR(A0,D0.L),-(A7)  PUSH STACK POINTER
  169.         LEA.L     NAME(A0,D0.L),A1    POINT TO NAME IN BLOCK
  170.         LEA       NAMESTR(PC),A2      POINT TO LOCAL NAME STRING
  171.         MOVEQ     #8,D2               LOAD A COUNTER
  172. PSTAT5:
  173.         MOVE.B    (A1)+,(A2)+         COPY A BYTE
  174.         SUBQ.L    #1,D2               COUNT THIS BYTE
  175.         BNE       PSTAT5              LOOP UNTIL DONE
  176.         CLR.B     (A2)                CLEAR THE TERMINATING BYTE
  177.         PEA       NAMESTR(PC)         PUSH NAME STRING
  178.         PEA       STATMSG(PC)         SHOW THE STAT MESSAGE
  179.         JSR       PRINTF
  180.         ADD.L     #20,A7
  181.         ADDQ.W    #1,D1               GO TO NEXT TASK
  182.         CMP.W     #LASTTASK,D1        SEE IF ALL DONE
  183.         BLE       PSTAT1              KEEP PRINTING UNTIL DONE
  184.         PEA       FINALMSG(PC)        PRINT FINAL MESSAGE
  185.         JSR       PRINTF
  186.         ADDQ.L    #4,A7
  187.         RTS
  188.  
  189.  
  190. HEADING:
  191.         DC.B      $0D,$0A,$0A
  192.         DC.B      '           '
  193.         DC.B      'Stack      '
  194.         DC.B      'Activation '
  195.         DC.B      '           '
  196.         DC.B      '           '
  197.         DC.B      $0D,$0A
  198.         DC.B      'Name       '
  199.         DC.B      'Pointer    '
  200.         DC.B      'Count      '
  201.         DC.B      'I/O device '
  202.         DC.B      '           '
  203.         DC.B      $0D,$0A
  204.         DC.B      '-----------'
  205.         DC.B      '-----------'
  206.         DC.B      '-----------'
  207.         DC.B      '-----------'
  208.         DC.B      '-----------'
  209.         DC.B      $0D,$0A
  210.         DC.B      0
  211.  
  212. STATMSG:
  213.         DC.B      '%-11s%-11X%-11X%-11s'
  214.         DC.B      $0D,$0A
  215.         DC.B      0
  216.  
  217. FINALMSG:
  218.         DC.B      $0D,$0A
  219.         DC.B      0
  220.  
  221. PORT0:
  222.         DC.B      'CHNL 0'
  223.         DC.B      0
  224.  
  225. PORT1:
  226.         DC.B      'CHNL 1'
  227.         DC.B      0
  228.  
  229. PORTX:
  230.         DC.B      'UNKNOWN'
  231.         DC.B      0
  232.  
  233.  
  234.  
  235.  
  236. *
  237. *  PAUSE
  238. *
  239. *  This is the heart of the multi-task controller.  It switches
  240. *  tasks each time it is invoked.  Normally, it is invoked automatically
  241. *  each time an I/O request is made.  Additionally, it may be invoked
  242. *  explicitly by a routine to force a task switch (in the interest
  243. *  of fairness).
  244. *
  245.  
  246. PAUSE:
  247.         MOVEM.L   D0-D7/A0-A7,-(A7)   SAVE ALL REGISTERS
  248.         LEA       CURRENT(PC),A0      POINT TO CURRENT TASK
  249.         MOVE.W    0(A0),D0            PUT IN D0
  250.         MOVE.W    D0,D2               SAVE CURRENT TASK IN D2
  251.         LEA       RAMTBL(PC),A0       POINT TO RAM TABLE
  252.         MULS      #BLKSIZE,D2         MAKE A BLOCK POINTER
  253.         ADD.L     D2,A0               POINT A0 AT THIS TASK'S BLOCK
  254.         MOVE.L    A7,STKPTR(A0)       SAVE CURRENT STACK POINTER
  255.  
  256. PAUSE0:
  257.         CMP.W     #LASTTASK,D0        IS THIS THE LAST TASK?
  258.         BNE       PAUSE1              BRANCH IF NOT
  259.         CLR.W     D0                  GO BACK TO TASK 0
  260.         BRA       PAUSE2
  261. PAUSE1:
  262.         ADDQ.W    #1,D0               GO TO NEXT TASK
  263. PAUSE2:
  264.         LEA       CURRENT(PC),A0      POINT TO CURRENT TASK
  265.         MOVE.W    D0,0(A0)            SAVE CURRENT TASK
  266.         MOVE.W    D0,D2
  267.         MULS      #BLKSIZE,D2         LEAVE D2 AS A BLOCK POINTER
  268.         LEA       RAMTBL(PC),A0       GET ADDRESS OF TASK TABLE
  269.         ADD.L     D2,A0               POINT A0 AT NEW TASK'S TABLE
  270.         CMP.W     #'VL',VALID(A0)     IS THIS A VALID TASK?
  271.         BNE       PAUSE0              IF NOT, GO TRY NEXT ONE
  272.         MOVE.B    STATUS(A0),D1       GET STATUS OF NEW TASK
  273.         BTST.B    #ACTIVE,D1          CHECK THE ACTIVE BIT
  274.         BEQ       PAUSE0              THIS GUY IS INACTIVE, TRY AGAIN
  275.         BTST.B    #STARTUP,D1         HOW ABOUT THE STARTUP BIT?
  276.         BEQ       PAUSE3              NO, MUST BE FULLY ACTIVE
  277.         MOVE.L    STKPTR(A0),A7       PUT NEW STACK POINTER INTO A7
  278.         MOVE.L    STARTS(A0),-(A7)    PUSH THE STARTUP ADDRESS
  279.         MOVEM.L   D0-D7/A0-A7,-(A7)   PUSH ALL REGISTERS (DUMMY)
  280.         BSET.B    #ACTIVE,D1          SHOW THIS TASK AS ACTIVE
  281.         BCLR.B    #STARTUP,D1         SHOW THIS TASK AS STARTED
  282.         MOVE.B    D1,STATUS(A0)       SAVE NEW STATUS
  283.         BRA       PAUSEX              GO GET HIM STARTED
  284.  
  285. PAUSE3:
  286.         MOVE.L    STKPTR(A0),A7       GET THE NEW STACK POINTER
  287.  
  288. PAUSEX:
  289.         ADDQ.L    #1,COUNT(A0)        INCREMENT THE ACTIVATION COUNT
  290.         MOVE.L    INV(A0),GETCRAM2
  291.         MOVE.L    OUTV(A0),PUTCRAM2
  292.         MOVE.L    KEYPRSDV(A0),KEYRAM2
  293.         MOVEM.L   (A7)+,D0-D7/A0-A7   RESTORE ALL REGISTERS
  294.         RTS                           TRANSFER TO NEW TASK
  295.  
  296. *
  297. *  BLINKER
  298. *
  299. *  This is a simple test program to verify that the multi-task
  300. *  activity is taking place.
  301. *
  302.  
  303. BLINKER:
  304.         BSR       PAUSE               GIVE THE OTHER GUY A SHOT
  305.         LEA       RAMTBL(PC),A0       POINT TO RAM TABLE
  306.         MOVE.W    #2,D0               GET OUR TASK NUMBER (KINDA CHEATING)
  307.         MULS      #BLKSIZE,D0         NOW MAKE D0 POINT TO OUR TASK BLOCK
  308.         MOVE.L    COUNT(A0,D0.L),D0   GET CURRENT ACTIVATION COUNT
  309.         BTST.L    #12,D0              LOOK AT A SPECIAL BIT
  310.         BNE       BLNK_ON             IF SET, TURN LIGHT ON
  311.         MOVE.L    #$3F00,$450000      NOT, SO TURN LED OFF
  312.         BRA       BLINKER             LOOP FOREVER
  313. BLNK_ON:
  314.         MOVE.L    #$3E00,$450000
  315.         BRA       BLINKER
  316.  
  317.  
  318.  
  319. *
  320. *  The following equates are bit patterns used in the status byte.
  321. *
  322. ACTIVE:   EQU     0                   BIT 0, TRUE = ACTIVE
  323. STARTUP:  EQU     1                   BIT 1, TRUE = NOT YET STARTED
  324.  
  325. ACTIVE_ST:      EQU   $01             STATE = ACTIVE AND STARTED
  326. UNSTARTED_ST:   EQU   $03             STATE = ACTIVE AND UNSTARTED
  327. SLEEP_ST:       EQU   $00             STATE = NOT ACTIVE AND UNSTARTED
  328.  
  329. *
  330. *  The following table is the initialized version of the task tables.
  331. *
  332.  
  333.  
  334. RAMTBL:
  335.  
  336. *
  337. *  TASK 0
  338. *
  339.         DC.L      TASK0SP             STACK POINTER, TASK 0
  340.         DC.B      'V','L'             VALID FLAGS
  341.         DC.L      WARMS               STARTUP ADDRESS
  342.         DC.L      INV0                INPUT VECTOR
  343.         DC.L      OUTV0               OUTPUT VECTOR
  344.         DC.L      KEYV0               KEYPRESSED VECTOR
  345.         DC.B      ACTIVE_ST           STATUS BYTE (ALREADY ACTIVE)
  346.         DC.B      0                   RESERVED
  347.         DC.L      0                   ACTIVATION COUNT
  348.         DC.L      0                   RESERVED
  349.         DC.B      'TASK_0',0,0
  350.  
  351. BLKSIZE EQU       40                  NUMBER OF BYTES IN BLOCK
  352.  
  353.  
  354. *
  355. *  TASK 1
  356. *
  357.         DC.L      TASK1SP             STACK POINTER, TASK 1
  358.         DC.B      'V','L'             VALID FLAGS
  359.         DC.L      WARMS               STARTUP ADDRESS (ROM MONITOR)
  360.         DC.L      INV1                INPUT VECTOR
  361.         DC.L      OUTV1               OUTPUT VECTOR
  362.         DC.L      KEYV1               KEYPRESSED VECTOR
  363.         DC.B      UNSTARTED_ST        STATUS BYTE (ACTIVE, UNSTARTED)
  364.         DC.B      0                   RESERVED
  365.         DC.L      0                   ACTIVATION COUNT
  366.         DC.L      0                   RESERVED
  367.         DC.B      'TASK_1',0,0
  368.  
  369.  
  370. *
  371. *  TASK 2  (Dummy activity to show multi-task activity)
  372. *
  373.  
  374.         DC.L      TASK2SP             STACK POINTER, TASK 2
  375.         DC.B      'V','L'             VALID FLAGS
  376.         DC.L      BLINKER             STARTUP ADDRESS
  377.         DC.L      0                   INPUT VECTOR
  378.         DC.L      0                   OUTPUT VECTOR
  379.         DC.L      0                   KEYPRESSED VECTOR
  380.         DC.B      UNSTARTED_ST        STATUS BYTE (ACTIVE, UNSTARTED)
  381.         DC.B      0                   RESERVED
  382.         DC.L      0                   ACTIVATION COUNT
  383.         DC.L      0                   RESERVED
  384.         DC.B      'BLINKER',0
  385.  
  386. LASTTASK:   EQU   2                   NUMBER OF LAST LEGAL TASK
  387.  
  388.  
  389. *
  390. *  RAM area used by the multi-user system.
  391. *
  392.  
  393. CURRENT:
  394.         DC.W      0                   NUMBER OF CURRENT TASK
  395. NAMESTR:
  396.         RMB       10                  RESERVED FOR STAT ROUTINE
  397.  
  398.  
  399.         END       START
  400.  
  401.  
  402.