Trap #1 Codes | ||
---|---|---|
D0 | Description | |
$00 | MT_INF / SMS_INFO | Get system information |
$01 | MT_CJOB / SMS_CRJB | Create but do not activate a new job |
$02 | MT_INF / SMS_INJB | Get information for an existing job |
$03 | Not implemented | |
$04 | MT_RJOB / SMS_RMJB | Remove an existing (inactive) job |
$05 | MT_FRJOB / SMS_FRJB | Force remove an existing job |
$06 | MT_FREE / SMS_FRTP | Find the maximum amount of free memory |
$07 | MT_TRAPV / SMS_EXV | Set the TRAP Vector table in RAM |
$08 | MT_SUSJB / SMS_SSJB | Suspend an existing job |
$09 | MT_RELJB / SMS_USJB | Release an existing job from suspension |
$0a | MT_ACTIV / SMS_ACJB | Activate a newly created job |
$0b | MT_PRIOR / SMS_SPJB | Set a job's priority |
$0c | MT_ALLOC / SMS_ALHP | Allocate user heap space |
$0d | MT_LNKFR / SMS_REHP | Free allocated user heap space |
$0e | MT_ALRES / SMS_ARPA | Allocate resident procedure space |
$0f | MT_RERES | Release allocated resident procedure space |
MT_INF / SMS_INFO - Get system information. TRAP #1 D0 = $00 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1 | Unused | D1.L | Current job id |
D2 | Unused | D2.L | QDOS/SMSQ version in ASCII (x.yy) |
D3 | Unused | D3.L | Preserved |
A0 | Unused | A0.L | Pointer to base of system variables |
A1 | Unused | A1.L | Preserved |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
This trap call does not return any errors. | |||
Notes : All registers not shown above are not used on entry and are preserved on exit. |
The following shows the use of this call to get the location of the SuperBasic PROGD$ device :
moveq #mt_inf,d0 ; Trap code trap #1 ; Fetch system information move.l sv_progd(A0),A0 ; A0 now holds the start address of where PROGD$ is stored, or zero : ; And from there, the device name can be extracted. :
MT_CJOB / SMS_CRJB - Create but do not activate a new job TRAP #1 D0 = $01 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | ID of the job which will own the job being created | D1.L | Job id of the created job |
D2.L | Size, in bytes, of the size of the new job's code space | D2.L | Preserved |
D3.L | Size, in bytes, of the new job's data space | D3.L | Preserved |
D7 | Unused | D7.L | Corrupted - set to same value as D1.L |
A0 | Unused | A0.L | Base address of the new job. Points to JB_END within the job header |
A1.L | Start address of the jobs code, or zero | A1.L | Preserved |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : ERR_NJ - No room in the QDOS job table, or D1 was not a valid job id on entry ERR_OM - Not enough memory to create the job. | |||
Notes : All registers not shown above are not used on entry and are preserved on exit. D7 is not documented as being corrupted in any docs that I have, personal experience shows otherwise. If A0.L is zero on entry, then a blank job area will be created ready for you to load some code into, similar to how EXEC works. If you already have some code in memory, and that code is re-entrant, then set A0.L to the start address of the code, and a new job will be created for you, re-using another job's code. |
The following shows the use of this call to create a new job :
moveq #mt_cjob,d0 ; Trap code moveq #-1,d1 ; Current job will be the owner move.l #2048,d2 ; Code size is 2048 bytes move.l #1024,d3 ; Data space and stack takes 1024 bytes suba.l a1,a1 ; Indicate I will load code later trap #1 ; Fetch system information tst.l d0 ; Check for errors bne.s <Error handler> ; Oops, an error occurred <Load job's code from a file etc to the address in A0.L> : :
MT_INF / SMS_INJB - Get information for an existing job TRAP #1 D0 = $02 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of job to get information for | D1.L | Id of next job in tree |
D2.L | Id of job at top of the tree | D2.L | Parent job's id for the job we enquired upon |
D3 | Unused | D3.L | Lowest byte = job's priority Highest 3 bytes = $FF if job suspended, else zero |
A0 | Unused | A0.L | Base address (JB_END) of the job |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : ERR_NJ - Invalid job | |||
Notes : All registers not shown above are not used on entry and are preserved on exit. This call can be used to scan the entire job tree, by calling it in a loop with D1.L = D2.L = zero, then on each subsequent call, setting D1.L to the value just returned in D1.L. Eventually, D1.L will be returned as zero which indicates end of the tree. If D1.L = D2.L <> zero, then only that sub-tree will be scanned, not the entire tree. |
The following shows the use of this call to scan the entire job tree :
moveq #0,d1 ; Zero = SuperBasic move.l d1,d2 ; Job at top of tree also = SuperBasic loop moveq #mt_jinf,d0 ; Trap code trap #1 ; Fetch job information, sets D1.L = next job in tree tst.l d0 ; Check for errors bne.s <Error handler> ; Oops, an error occurred tsl.l d1 ; Are we done yet ? beq.s done ; Yes, no more jobs : <Do stuff here with info returned, but preserve D1.L and D2.L> : bra.s loop ; Using D1 and D2's values from the trap, go and do next job done <Do stuff here when finished> : :
This trap code is not implemented. TRAP #1 D0 = $03 | |
---|---|
Call Parameters | Return Parameters |
Errors returned in D0.L : None, your system will have crashed ! |
MT_RJOB / SMS_RMJB - Remove an existing (inactive) job TRAP #1 D0 = $04 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of job to be removed, or -1 for the current job. | D1.L | Corrupted |
D2 | Unused | D2.L | Corrupted |
D3.L | Error code to return | D3.L | Corrupted |
A0 | Unused | A0.L | Corrupted |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : ERR_NC - Not complete (Job is active) ERR_NJ - Invalid job id | |||
Notes : All registers not mentioned above are unused on entry and preserved on exit. Job 0 (SuperBasic) cannot be removed. This trap is not atomic as it can exit via the scheduler - if the current job is being removed. If the job being removed is active, then ERR_BC (not complete) is returned. If the job has child jobs, they are removed whether or not they are active - (probably) using MT_FRJOB below. The error code in D3.L is passed to any job which is waiting for this job to complete. Any resources - channels, memory etc - owned by the job being removed, or its children, are released. |
The following shows the use of this call to remove the current job :
moveq #mt_rjob,d0 ; Trap code moveq #-1,d1 ; Indicate the current job moveq #0,d3 ; Don't pass any error codes trap #1 ; Kill this job : :
I have a small problem with this, assuming that the current job is removing itself, then it must be active, otherwise, how would it remove itself? This implies that the current job cannot use this call to remove itself. I feel a small delve into the source of QDOS coming on.
MT_FRJOB / SMS_FRJB - Force remove an existing job TRAP #1 D0 = $05 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of job to be removed, or -1 for the current job. | D1.L | Corrupted |
D2 | Unused | D2.L | Corrupted |
D3.L | Error code to return | D3.L | Corrupted |
A0 | Unused | A0.L | Corrupted |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : ERR_NC - Not complete (Job is active) ERR_NJ - Invalid job id | |||
Notes : All registers not mentioned above are unused on entry and preserved on exit. Job 0 (SuperBasic) cannot be removed. This trap is not atomic as it can exit via the scheduler - if the current job is being removed. If the job being removed is active, it is inactivated and removed. If the job has child jobs, they are removed whether or not they are active. The error code in D3.L is passed to any job which is waiting for this job to complete. Any resources - channels, memory etc - owned by the job being removed, or its children, are released. |
The following shows the use of this call to force remove the current job :
moveq #mt_frjob,d0 ; Trap code moveq #-1,d1 ; Indicate the current job moveq #0,d3 ; Don't pass any error codes trap #1 ; Kill this job : :
MT_FREE / SMS_FRTP - Find the maximum amount of free memory TRAP #1 D0 = $06 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1 | Unused | D1.L | Maximum free space in bytes |
D2 | Unused | D2.L | Corrupted |
D3 | Unused | D3.L | Corrupted |
A0 | Unused | A0.L | Corrupted |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : None. | |||
Notes : This trap returns the number of bytes in the biggest free area of Transient Program area or the number of bytes between SV_BASIC and SV_FREE minus 512 - whichever is the biggest. Of course, by the time you have the figure, you might still fail to allocate it all if another job has got there first and allocated some space for itself. |
The following shows the use of this call :
moveq #mt_free,d0 ; Trap code trap #1 ; Kill this job <do stuff here with the number of bytes in D1.L> : :
MT_TRAPV / SMS_EXV - Set the TRAP Vector table in RAM TRAP #1 D0 = $07 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of the job for which the TRAP table is to be redirected | D1.L | Preserved |
D2 | Unused | D2.L | Preserved |
D3 | Unused | D3.L | Preserved |
A0 | Unused | A0.L | Base of job whose id was passed in D1.L |
A1 | Ponter to new TRAP table. | A1.L | Corrupted |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : Err_NJ - Invalid job id. | |||
Notes : This trap allows a job to redirect the TRAP #5 to TRAP #15 calls and exception handlers, but not all of them, which are normally unused by QDOS/SMS. Different jobs can have different tables, but a job is given the same table as its parent when first created. See the example code for full details of the format of the table etc. |
This example code, shows the use of this trap to create an exception handler for an original QL only. Later processors have different stack frames for the Address exception.
MT_SUSJB / SMS_SSJB - Suspend an existing job TRAP #1 D0 = $08 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of the job to be suspended, or -1 for the current job | D1.L | Preserved |
D2 | Unused | D2.L | Preserved |
D3.W | Timout period in frame counts, or -1 for indefinite suspension | D3.L | Preserved |
A0 | Unused | A0.L | Base address of job's header |
A1.L | Address of the flag byte (see below) or zero | A1.L | Documented as Preserved but isn't |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : ERR_NJ - Invalid job | |||
Notes : A1.L is documented as being preserved, but personal experience has shown that it is not always preserved. The value in D3.W is stored in the job's header at JB_STAT. The value in A1.L is stored in the header at JB_HOLD. A frame period is 1/50th in UK/Europe but 1/60th in the USA. The flag byte will be cleared when the job is released again. If the job being suspended is already suspended, then the current suspend period is changed to the new one, and the job is re-suspended for the requested period. This trap always exits via the job scheduler, so it is not atomic. |
The following shows the use of this call :
moveq #mt_susjb,d0 ; Trap code moveq #-1,d1 ; Suspend myself moveq #50,d3 ; Suspend for one European second or 50/60th American seconds suba.l a0,a0 ; No flag byte required trap #1 ; Suspend the job <Do stuff here whan the suspension is over> : :
MT_RELJB / SMS_USJB - Release an existing job from suspension TRAP #1 D0 = $09 | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of the job to be released | D1.L | Preserved |
D2 | Unused | D2.L | Preserved |
D3 | Unused | D3.L | Preserved |
A0 | Unused | A0.L | Base address of job's header |
A1.L | Unused | A1.L | Preserved |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : ERR_NJ - Invalid job | |||
Notes : The flag byte (at JB_HOLD in the job header) will be cleared when the job is released. This trap always exits via the job scheduler, so it is not atomic. |
The following shows the use of this call :
moveq #mt_reljb,d0 ; Trap code moveq #<job_id>,d1 ; <job_id> is a known job id trap #1 ; Suspend the job : :
MT_ACTIV / SMS_ACJB - Activate a newly created job TRAP #1 D0 = $0a | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of the job to be activated | D1.L | Preserved |
D2.B | Priority 0 to 127 but see below | D2.L | Preserved/Corrupted |
D3.W | Timeout 0 or -1 | D3.L | Preserved |
A0 | Unused | A0.L | Base address of job's header |
A1 | Unused | A1.L | Preserved |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved/Corrupted |
Errors returned in D0.L : ERR_NC - Not complete (Job is already active) ERR_NJ - Invalid job | |||
Notes : If the timeout in D3.W is zero, then this equates to EXEC and the job doing the activation will continue to run. Otherwise, it will wait for the job being activated to remove itself using MT_FRJOB before continuing. Also note that A3.L is corrupted if the timeout was not zero on entry. The priority passed in D2.B is documented as being in the range 0 to 127, however, it appears that values from 0 to 255 can be used. Dickens states that D2 is preserved and Pennell says corrupted. Best to assume the worst and consider it corrupted. This trap is not atomic and always exits via the scheduler. |
The following shows the use of this call :
moveq #mt_activ,d0 ; Trap code moveq #<job_id>,d1 ; <job_id> is a known job id moveq #32,d2 ; Standard default priority is 32 moveq #0,d3 ; Continue executing this job, after activating the other one trap #1 ; Suspend the job : :
MT_PRIOR / SMS_SPJB - Set a job's priority TRAP #1 D0 = $0b | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Id of the job | D1.L | Preserved |
D2.B | Priority 0 to 127 but see below | D2.L | Preserved |
D3 | Unused | D3.L | Preserved |
A0 | Unused | A0.L | Base address of job's header |
A1 | Unused | A1.L | Preserved |
A2 | Unused | A2.L | Preserved |
A3 | Unused | A3.L | Preserved |
Errors returned in D0.L : ERR_NJ - Invalid job | |||
Notes : The priority passed in D2.B is documented as being in the range 0 to 127, however, it appears that values from 0 to 255 can be used. This trap is not atomic and always exits via the scheduler. |
The following shows the use of this call :
moveq #mt_prior,d0 ; Trap code moveq #-1,d1 ; Change my own priority moveq #1,d2 ; Set priority very low trap #1 ; Change the priority : :
MT_ALLOC / SMS_ALHP - Allocate user heap space TRAP #1 D0 = $0c | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Number of bytes required in user heap | D1.L | Number of bytes allocated |
D2 | Unused | D2.L | Corrupted |
D3 | Unused | D3.L | Corrupted |
A0 | Pointer to pointer to free space (relative A6) | A0.L | Address of area allocated (relative A6) |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : ERR_OM - Out of memory (in user heap). | |||
Notes : A user heap is an area of memory, maybe in the common heap, set aside for use by a single job. The job can allocate areas of this user heap for its own needs, and deallocate them as required. This stops, or reduces fragmentation of the common heap which is used by every task in the system. Look here for more information on heaps. |
This example show the use of this, and other, heap manipulation traps :
MT_LNKFR / SMS_REHP - Free allocated user heap space TRAP #1 D0 = $0d | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Size of area to be linked (back) in to the user heap | D1.L | Corrupted |
D2 | Unused | D2.L | Corrupted |
D3 | Unused | D3.L | Corrupted |
A0.L | Address of the area of heap/memory to link (back) in to the user heap (Relative A6) | A0.L | Corrupted |
A1.L | Pointer to pointer to free space (Relative A6) or zero. | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
Errors returned in D0.L : None | |||
Notes : This trap is used to create a user heap by setting the memory location (long word) that (A1,A6) points to to zero. Then a chunk of memory, probably previously allocated from the common heap is passed in (A0,A6) and you now have a user heap to play with. If the pointer to the free space is not zero, then you are assumed to be 'freeing' a previously allocated chunk of user heap. See the example file for more details. |
This example show the use of this, and other, heap manipulation traps :
MT_ALRES / SMS_ARPA - Allocate resident procedure space TRAP #1 D0 = $0e | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1.L | Number of bytes required | D1.L | Corrupted |
D2 | Unused | D2.L | Corrupted |
D3 | Unused | D3.L | Corrupted |
A0 | Unused | A0.L | Base address of allocated memory |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : ERR_NC - Not complete (usually means some jobs are executing) ERR_OM - Out of memory | |||
Notes : This trap is how the SuperBasic function RESPR works. It allocates space in the resident procedures area, but only if there are no jobs running. |
The following shows the use of this call :
moveq #mt_alres,d0 ; Trap code move.l #1024,d1 ; 1 Kbyte required in Resident procedure space trap #1 ; Allocate the space tst.l D0 ; Did it work ? bne.s <error handler> ; No, handle errors <Use space allocated from (A0) onwards> : :
MT_RERES (QDOS only) - Release allocated resident procedure space TRAP #1 D0 = $0f | |||
---|---|---|---|
Call Parameters | Return Parameters | ||
D1 | Unused | D1.L | Corrupted |
D2 | Unused | D2.L | Corrupted |
D3 | Unused | D3.L | Corrupted |
A0 | Unused | A0.L | Corrupted |
A1 | Unused | A1.L | Corrupted |
A2 | Unused | A2.L | Corrupted |
A3 | Unused | A3.L | Corrupted |
Errors returned in D0.L : ERR_NC - Not complete (Usually means that some jobs are running) | |||
Notes : This trap has no equivalent under SMS, probably due to the serious danger of crashing the system. The RESPR area is completely removed by this trap - if there are no jobs running - but, as some device drivers allocate RESPR memory, this can cause subsequent system crashes. In addition, some versions of QDOS actually allocate more space, rather than releasing all of it. Best avoided ! |