PowerDOS Programmer's Manual (well, sort of) Revision 1.0 - 08/02/93 (C) 1993 ViewTouch Corp. 344 NE Terry Lane Grants Pass, OR 97526 (503)479-4278 Who's primarily at fault - Chris Latham Lots of chiding and snide remarks - Daniel Hollis Welcome to the first incarnation of the wonderful, furry, spicy (low cholesterol) PowerDOS programmer's Manual (TM)!! Included are all the documents needed to push PowerDOS to (no, make that OVER) its limits. We assume no responsibility for system crashes, loss of data, destruction of hardware (willful or otherwise), loss of limbs, divorces, shattered lives, insanity, paralysis, deaths, or global thermonuclear war resulting from the use, misuse, unuse, abuse or refuse of this program. Do not insert document into ear canal. Keep out of reach of children. May cause dizziness, convulsions, or vomiting. Keep away from open flame. Wear safety gloves when handling. With all that legal mumbo jumbo out of the way, fasten your seat belts and off we go!! Enter at own risk! +----------------------------------------------------------------------+ First, let's discuss what multitasking is... Well, multitasking is...wait, let me digress for a moment. What is a computer....wait, let me digress... Where is the on/off switch? It's in the back. Now that you fully understand multitasking, we'll launch right into the functions that PowerDOS provides. +----------------------------------------------------------------------+ 4B: Program execution PowerDOS supports four new execution modes, as described below: long errcode = Pexec(0x10,prgfile,cmdline,envptr) This mode is just like mode 0, except that the parent continues to operate concurrently with the newly created child task. The error codes only reflect errors that may occurr while trying to create the task, such as file not found or out of memory. The only way for the parent to receive the deathcode from the child task, is if it executes a Wait() before the child terminates. If no error occurrs, (d0.l is not negative), then d0.w will be the process ID of the new task. Also like mode 0, the newly created task gets the largest block of ram for its basepage+text+bss+heap. Since other, concurrently running processes in the system may try to do Mallocs before the new task has shrunk its memory usage, it is advisable that the parent process issues controls as to the amount of memory that the new task will receive for both its TPA and Malloc(-1) calls that it may issue as it executes. Function 0xa3 (Pmaxmem) may be used to set the parents maximum Malloc(-1) return. This max value will be inherited by the child process as its maximum Malloc(-1) value. Also, function 0x9f may be used to set the maximum size of the TPA given to a newly created process. These two variables taken together will give a large amount of control as to how the memory in the system is used. long errcode = Pexec(0x16,0L,_psp basepage,0L) This is just like mode 6, except that the parent again continues to execute concurrently, whith the same problem of receiving the child's deathcode upon its termination. The next two Pexec modes are for support of multiple threads of execution within a single program: long errcode = Pexec(0x17,char *proc_name,char *cmdline,char *envptr, void *code_ptr,long bss_size,long data_size) This mode allows you to execute a code fragment that is within the text segment of the calling process. It creates a basepage, followed by a data segment of the given size (and copies the data from the parents data segment, for the data size given), followed by a BSS of the given size. The user stack pointer is placed at the top of the BSS, so this must be included in the BSS size. At sp+4 will be a pointer to the basepage, the same as Pexec mode 0. Also register a5 will point to the start of the data segment, and register a4 will point to the start of the BSS. proc_name is the name the process will be known by, and must be a null terminated string of no more than 13 characters. The code fragment may directly access or modify variables in its parents data or BSS segments, using pc relative or absolute addresses. Access to the thread's private data and BSS segments, however, may only be accomplished using relative offsets from an address register. long errcode = Pexec(0x18,char *proc_name,char *cmdline,char *envptr, void *code_ptr,long bss_size,long data_size, int var_ints,int *vars[]) This is the same as mode 0x17, except that it allows a number of ints to be placed on the stack of the new task (thus the basepage pointer will not be at sp+4). var_ints is the number of ints to copy onto the stack, and vars is a pointer to the ints to copy. +--------------------------------------------------------------------------+ 7.1 5C: Lock/unlock File Access long Flock(handle, mode, start, length) word handle; word mode; long start; long length; { } +-------------------------------------+ Low memory (parameter | Function Code 0x5c | Word block addr) +-------------------------------------+ | File Handle | Word 1 +-------------------------------------+ | Mode | Word 2 +-------------------------------------+ | | + Start of Lock + Long 1 | | +-------------------------------------+ | | + Length of Lock + Long 2 | | +-------------------------------------+ High memory This is not a function call unique to PowerDOS, since it is defined by Atari as the record locking standard to be used by all networking or multitasking operating systems. However, since this call is not part of regular GemDOS, documentation for it is not readily available. It is documented here for the convienience of PowerDOS developers or just the curious. Word 1 contains the file handle. Word 2 contains a code indicating lock/unlock: 0 = Create a lock of (length) bytes, beginning at (start). 1 = Remove lock that was previously set. Parameters Length and Start MUST match a previous lock call. Long 1 is offset from start of file where the lock will begin. Long 2 is the length of the locked area. Once a lock is set, only the handle that owns the lock may read or write that area of the file. When a handle is closed, any locks left on the file by the handle will automatically be removed. Any handle may have any number of non-overlapping locks on a file. PowerDOS can handle up to 65535 total locks on all open files. Return Parameter: Register D0.L : Contains 0 if the operation was successful (the lock was created or removed, depending on mode), non-zero if an error occurs. New error codes are defined to handle possible error conditions: -58 : Record is locked. This error is returned if the area of the file where a new lock is to be created already has a lock on it, or overlapping it. This error will also be returned during f_read or f_write calls to areas of the file containing locks from other handles. -59 : Matching lock not found for unlock operation. This error will be returned during a lock removal operation if a lock with the proper start/length belonging to the handle was not found as part of the files previously set locks. In assembly language: move.l length,-(sp) move.l start,-(sp) move.w mode,-(sp) move.w handle,-(sp) move.w #$5c,-(sp) trap #1 lea 14(sp),sp +--------------------------------------------------------------------------+ 7.2 80: Get or set Group.User ID of a process long Puserid(process_id,flag,new_group_user) word process_id; word flag; long new_group_user; } { +-------------------------------------+ Low memory (parameter | Function Code 0x80 | Word block addr) +-------------------------------------+ | Process ID | Word 1 +-------------------------------------+ | Get/set flag | Word 2 +-------------------------------------+ | New group.user ID if | + + Long | flag is <>0 (set) | +-------------------------------------+ High memory Note: Only a super user (group.user ID *.0-31) may set a processes group.user ID. All others may only read group.user ID's. Word 1 is ID of process from which to set/get the group.user ID. Zero represents the calling process. Word 2 Get/set flag. Zero means get, else is a set. Long New group.user ID if flag <> 0. Upper word of long is group ID lower word is user ID. Return Parameter: Register D0.L : Contains the group.user ID if a get, or the new group.user if a set. Could also possibly be one of three errors: -62 : Permission violation. Process tried to do a set but was not a super user. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. Note: since the group.user ID can be any number, it is possible to mistake a legitimate group.user ID for an error code. The solution to this is to not allow a group ID to be > 32767. In assembly language: move.l new_group_user,-(sp) move.w flag,-(sp) move.w process_id,-(sp) move.w #$80,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ 7.3 81: Set or get the priority of given process long Ppriority(process_id,new_priority) word process_id; word new_priority; { } +-------------------------------------+ Low memory (parameter | Function Code 0x81 | Word block addr) +-------------------------------------+ | Process ID | Word 1 +-------------------------------------+ | New process priority, or read flag | Word 2 +-------------------------------------+ High memory Note: you may change process priorities only of processes with the same group.user id (your processes) or if you are a superuser. Word 1 Process ID from which priority is to be read or changed. If this value is a zero, then the priority to be read/changed is of the calling process. Word 2 If zero, is a read (zero is not a valid process priority), else is the new priority for the process. Return Parameter: Register D0.L : If D0.l is positive (no error), then the lower word is the current priority of the given process. If D0.l is negative, represents an error: -62 : Permission violation. Process tried to do a set priority but was not a super user or owner. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.w new_priority,-(sp) move.w process_id,-(sp) move.w #$81,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.4 82: Get current process' process ID word Pgetpid() { } +-------------------------------------+ Low memory (parameter | Function Code 0x82 | Word block addr) +-------------------------------------+ High memory Return parameter: Register D0.W : Process ID of calling process. This call never fails. In assembly language: move.w #$82,-(sp) trap #1 addq.l #2,sp +--------------------------------------------------------------------------+ 7.5 83: Get current process' parent's process ID long Pgetppid() { } +-------------------------------------+ Low memory (parameter | Function Code 0x83 | Word block addr) +-------------------------------------+ High memory Return parameter: Register D0.L : If D0.L is not negative, the lower word of D0 is process ID of parent of calling process. If D0.L is negative, then possible error is: -87 : Orphaned process. The parent of the caller no longer exists. In assembly language: move.w #$83,-(sp) trap #1 addq.l #2,sp +--------------------------------------------------------------------------+ 7.6 84: Return pointer to process descriptor of given process void *Pgetpd(process_id) word process_id; { } +-------------------------------------+ Low memory (parameter | Function Code 0x84 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ High memory Note: Only a super user process may directly examine or modify the contents of a process descriptor. Word ID of process whose process descriptor is being sought. If zero, process descriptor of current process is returned. Return Parameter: Register D0.L : Pointer to the process descriptor of the given process ID, or possible error codes (if negative): -62 : Permission violation. Non super user process may not gain access to the process descriptor of any process. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.w process_id,-(sp) move.w #$84,-(sp) trap #1 addq.l #4,sp +--------------------------------------------------------------------------+ 7.7 85: Find the process ID of a process with the given name long Pfindpid(process_name) char *process_name; { } +-------------------------------------+ Low memory (parameter | Function Code 0x85 | Word block addr) +-------------------------------------+ | | + Pointer to process name + Long | | +-------------------------------------+ High memory Long Pointer to name of process whose process ID is to be returned. Name is a zero terminated ASCII string. Call is case independent. If a process was created from a disk file, then its name will be that of the disk file (i.e. WWRITER2.PRG). If this is the case, the extension is not required for a match; The string "wwriter2",0 will match the above example. Return Parameter: Register D0.L : If D0.L is not negative, then lower word is process ID of process with matching name. Possible error: -75 : Process with given name not found. In assembly language: pea process_name move.w #$85,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.8 86: Return information about process typedef struct { int pi_pid; /* Process ID */ int pi_ppid; /* Parents process ID */ int pi_sibling; /* First sibling's process ID (0=none) */ int pi_child; /* First child's process ID (0=none) */ unsigned long pi_gu; /* Group.user ID */ unsigned int pi_priority; /* Process priority */ unsigned int pi_age; /* Process current age if in r-t-r queue */ unsigned char pi_status; /* Various status bits */ unsigned char pi_queueID; /* Queue process resides in */ struct _psp *pi_basepage; /* Pointer to process basepage */ long pi_max_mem; /* Max memory returned for Malloc(-1) */ int pi_ucall; /* Last user state function call */ int pi_scall; /* Last system state function call */ unsigned long pi_ucpu; /* Number of user state milliseconds used */ unsigned long pi_scpu; /* Number of system state milliseconds used */ unsigned long pi_sleep; /* Number of milliseconds left if sleeping */ unsigned long pi_datetime; /* Date/time process started (XBIOS format) */ unsigned long pi_fcalls; /* Number of function calls executed */ unsigned long pi_iocalls; /* Number of i/o calls executed */ unsigned long pi_rbytes; /* Total bytes read from input calls */ unsigned long pi_wbytes; /* Total bytes written from output calls */ void *pi_vector; /* User defined vector */ struct dta *pi_dta; /* Disk transfer address */ char pi_name[14]; /* Process name (zero terminated ASCII) */ char pi_devname[8]; /* Current device name (A:, B:, C: etc) */ long pi_totmem; /* Total memory used by process */ void *pi_stack; /* Current supervisor stack top */ } PROCINFO; long Pprocinf(process_id,buffer) word process_id; struct PROCINFO *buffer; { } +-------------------------------------+ Low memory (parameter | Function Code 0x86 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ | Pointer to buffer which will | + + Long | receive process information | +-------------------------------------+ High memory Word ID of process whose information is being read. If zero, the information is for the calling process. Long Pointer to a buffer into which the information will be copied. The buffer must be sizeof(PROCINFO) bytes in length. Register D0.L : Zero if call was successful, else error: -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: pea buffer move.w process_id,-(sp) move.w #$86,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ 87: Change process priority using a delta long Pnice(process_id,delta) word process_id; word delta; { } +-------------------------------------+ Low memory (parameter | Function Code 0x87 | Word block addr) +-------------------------------------+ | Process ID | Word 1 +-------------------------------------+ | Delta | Word 2 +-------------------------------------+ High memory Word 1 Process ID from which priority is to be read or changed. If this value is a zero, then the priority to be read/changed is of the calling process. Word 2 A delta (+/-) from the current process ID. If this value is zero, no change is made; just returns the current priority. Return Parameter: Register D0.L : If D0.l is positive (no error), then the lower word is the current priority of the given process. If D0.l is negative, represents an error: -62 : Permission violation. Process tried to change the priority but was not a super user or owner. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.w delta,-(sp) move.w process_id,-(sp) move.w #$87,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.9 88: Allocate a block of system memory (top down) char *Smalloc(mem_size) long mem_size; { } +-------------------------------------+ Low memory (parameter | Function Code 0x88 | Word block addr) +-------------------------------------+ | | + Size of memory to allocate + Long | | +-------------------------------------+ High memory This call uses a top down memory allocation technique. Also, the block allocated is NOT owned by the calling process, but belongs to the operating system. This call is normally used to extend structures used by the operating system. Long Size of memory to allocate, or -1 to return size of largest single memory fragment. Return parameter Register D0.L : If input parameter is -1, then is the size of the largest block, or zero if no memory is available for allocation. Else is the start of a memory block of length mem_size, or zero if no block of sufficient size is avaiable. In assembly language: move.l mem_size,-(sp) move.w #$88,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.10 89: Assign a block of memory owned by calling process to process of given process ID long Massign(process_id,mem_start) word process_id; char *mem_start; { } +-------------------------------------+ Low memory (parameter | Function Code 0x89 | Word block addr) +-------------------------------------+ | ID of process to assign memory to | Word +-------------------------------------+ | | + Start address of memory to assign + Long | | +-------------------------------------+ High memory This call is used to assign a block of memory owned by the calling process to another process. The memory block to assign MUST be owned by the caller (it can not have been allocated with Smalloc). Also, the process to assign the memory to must exist and not be the same as the caller. This call is used primarily by the Pexec routines to assign memory allocated by the parent process during the Pexec call, to the new process once it has been created. Word Process ID of process to assign memory to. Long Pointer to start of the memory block. Return parameter Register D0.L : Zero if no error (block was assigned properly), else one of following errors: -40 : Invalid memory block address. The calling process did not own the memory it was trying to assign, or was not the start of a memory block. Also caused by the calling process trying to assign its base memory block (where its basepage is located) to another process, which is illegal. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: pea mem_start move.w process_id,-(sp) move.w #$89,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ 7.11 8B: Perform various status operations on an open file long Fstatus(handle,sub_function, ... ) word handle; word sub_function; { } +-------------------------------------+ Low memory (parameter | Function Code 0x8b | Word block addr) +-------------------------------------+ | File handle | Word 1 +-------------------------------------+ | Status function code | Word 2 +-------------------------------------+ High memory | optional parameters | +.....................................+ This call is primarily used to test for input or output available on an open file, though it performs several other functions as well. Word 1 Handle of an open file from which status information is being sought. Word 2 Status function to perform. Sub function codes: #define st_input 0 /* Test for input data available */ #define st_output 1 /* Test for device output ready */ #define st_size 2 /* Get size of file */ #define st_pos 3 /* Get r/w pointer position */ #define st_eof 4 /* Test for end of file */ #define st_rlock 5 /* Change record lock attributes */ /* Takes extra parameters; ????? */ #define st_extfile 6 /* Extend the files length */ /* Takes extra parameter; length to add to file */ #define st_readopt 7 /* Read options section of path desc */ /* Takes extra parameter; pointer to buffer to read parameters into */ #define st_wrtopt 8 /* Write options section of path desc */ /* Takes extra parameter; pointer to buffer to write parameters from */ #define st_name 9 /* Copy name of open file to buffer */ /* Takes extra parameter; pointer to buffer to read name into */ #define st_type 10 /* Return the file manager type for the file */ Return parameter Register D0.L : The return from the call is dependent on the sub- function desired. Also may return the following errors: -32 : Invalid function number. In this case, the sub-function number was not legal. -37 : Invalid handle. The handle was not for a currently open file. In assembly language: move.w sub_function,-(sp) move.w handle,-(sp) move.w #$8b,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.12 8C: Perform Fsfirst function with index into directory structure long Fsfirstidx(pathname,attributes,index) char *pathname; word attributes; word index; { } +-------------------------------------+ Low memory (parameter | Function Code 0x8c | Word block addr) +-------------------------------------+ | | + Pointer to pathname + Long | | +-------------------------------------+ | Attributes (as in Fsfirst) | Word 1 +-------------------------------------+ | Index of file to start at | Word 2 +-------------------------------------+ High memory The primary purpose of this call is to simplify directory searching over a network. Long Pointer to null terminated pathname Word 1 Attribute to search for (same as for Fsfirst) Word 2 Index into directory of file to start at (0 is first file). Return parameter Register D0.L : Return code and errors are the same as for Fsfirst In assembly language: move.w index,-(sp) move.w attributes,-(sp) pea pathname move #$8c,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ 8D: Wake parent process of current process long Wake_parent( code ) int code; { } +-------------------------------------+ Low memory (parameter | Function Code 0x8D | Word block addr) +-------------------------------------+ | Code | Word +-------------------------------------+ High memory This call is used by the process terminate routine to reactivate the parent of the teminating process. This call will only restart the parent process if it is in the Wait queue. It has no effect otherwise. May be used to reactivate parent process when child process wishes to run concurrently. Also see description of extended Pexec modes at the beginning of this document. Return parameter: Register D0.L : If D0.L is zero, no error occurred. Possible error is: -87 : Orphaned process. The parent of the caller no longer exists. In assembly language: move.w #code,-(sp) move.w #$8D,-(sp) trap #1 addq.l #4,sp +--------------------------------------------------------------------------+ 7.13 8E: Wait for child process to terminate long Wait() { } +-------------------------------------+ Low memory (parameter | Function Code 0x8e | Word block addr) +-------------------------------------+ This allows a process to block itself while awaiting the termination of a child process, though a signal can also be used to unblock the process. It is used by the Pexec function when using modes 0, 4 or 6. Return parameter Register D0.L : The error code of the terminating child process (assuming it used Pterm or Ptermres). These error codes are word in length, so the upper word of D0 will be zero. If upper word of D0 is not zero, then it could be a signal received through the Signal call, or a possible error: -72 : Process has no children to wait for. In assembly language: move.w #$8e,-(sp) trap #1 addq.l #2,sp +--------------------------------------------------------------------------+ 7.14 8F: Sleep (block) for specified time, or indefinately long Sleep(time) long time; { } +-------------------------------------+ Low memory (parameter | Function Code 0x8f | Word block addr) +-------------------------------------+ | | + Milliseconds or ticks to sleep + Long | | +-------------------------------------+ High memory This is a general purpose CPU time management facility. It is also called by several other PowerDOS function calls. Long If zero, will sleep indifinately. A positive value is the number of milliseconds to remain dormant. A negative value is taken as the number of system ticks to remain dormant. A value of -1 causes no sleep, but will cause a task switch if there is a process in the ready-to-run queue with the same or higher priority. Return parameter Register D0.L : The number of ticks left to sleep (if it was a timed sleep and a signal caused a premature activation). In assembly language: move.l time,-(sp) move.w #$8f,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.15 90: Link to queue of processes waiting for access to I/O long Ioqueue(process_id,time) word process_id; long time; { } +-------------------------------------+ Low memory (parameter | Function Code 0x90 | Word block addr) +-------------------------------------+ | ID of process to link to | Word +-------------------------------------+ | | + Milliseconds or ticks to sleep + Long | | +-------------------------------------+ High memory This call is used to block while awaiting access to I/O which is currently controlled by process_id. Word ID of process to link to Long Time to sleep (passed to the Sleep function call) Return parameter Register D0.L : Return parameter from Sleep function call, or possible errors: -76 : The process is trying to link to a process that is already linked to it. This should never happen, but a check is made for it to stop I/O deadlock from occurring. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.l time,-(sp) move.w process_id,-(sp) move.w #$90,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ 7.16 91: Wait (block) until a specified date/time long Wait_dt(date_time) unsigned long date_time; { } +-------------------------------------+ Low memory (parameter | Function Code 0x91 | Word block addr) +-------------------------------------+ | Date/time (in XBIOS format) to | + + Long | reactivate process at | +-------------------------------------+ High memory Long Date and time (in Xbios settime/gettime format) when process is to be reactivated. If the date word is zero, then only the time becomes significant (the date becomes a wildcard). Seconds are not counted; the call will only return on the even minute. If a date is used, but has already occurred, an immediate return results (otherwise the process would never unblock). Return parameter Register D0.L : Always returns zero In assembly language: move.l date_time,-(sp) move.w #$91,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.17 92: Create a new I/O device long Dev_create(dev_name,fm_name,drv_name,path_vars,dev_vars,share) char *dev_name; char *fm_name; char *drv_name; char *path_vars; char *dev_vars; word share; { } +-------------------------------------+ Low memory (parameter | Function Code 0x92 | Word block addr) +-------------------------------------+ | | + Pointer to name device will have + Long 1 | | +-------------------------------------+ | | + Pointer to name of file manager + Long 2 | | +-------------------------------------+ | | + Pointer to name of device driver + Long 3 | | +-------------------------------------+ | | + Pointer to new path init vars + Long 4 | | +-------------------------------------+ | | + Pointer to initial device vars + Long 5 | | +-------------------------------------+ | Device share flag | Word +-------------------------------------+ High memory This function is used to create (add) a new device to PowerDOS. For more information on this call, contact the PowerDOS authors. Long 1 Pointer to name the new device will have. Must be seven characters or less in length, and must be uppercase. String is null terminated. Long 2 Pointer to name of file manager for the device. Long 3 Pointer to name of device driver for the device. Long 4 Pointer to new path initialization vars. First word is number of bytes to copy. Must be 40 or less. Long 5 Pointer to device initialization vars. First word is number of bytes to copy. Must be 40 or less. Word Device share flag. If zero, device is shareable. Return parameter Register D0.L : Zero on success, else possible error codes: -73 : I/O device table is full. No more devices may be added to the system. -74 : File manager or device driver was not found. In assembly language: move.w share-(sp) pea dev_vars pea path_vars pea drv_name pea fm_name pea dev_name move.w #$92,-(sp) trap #1 lea 24(sp),sp +--------------------------------------------------------------------------+ 7.18 93: Add a new file manager to the system long Fm_add(fm_name,subroutine_tab,fm_vars,fm_type) char *fm_name; char *subroutine_tab; char *fm_vars; word fm_type; { } +-------------------------------------+ Low memory (parameter | Function Code 0x93 | Word block addr) +-------------------------------------+ | | + Pointer to file manager name + Long 1 | | +-------------------------------------+ | | + Pointer to subroutine index table + Long 2 | | +-------------------------------------+ | | + Pointer to file manager's variables + Long 3 | | +-------------------------------------+ | File manager type | Word +-------------------------------------+ High memory This function is used to add a new file manager to PowerDOS. For more information, panic and pick up the phone. Long 1 Name by which the file manager will be known to the system. Must be in uppercase, 7 characters max, null terminated. Long 2 Pointer to subroutine index table. Each value in the table is a signed int that is taken as an offset from the start of the table to the service function (a relative offset). Long 3 Pointer to any global variables that the file manager may require. This value has no meaning to the kernal. It is simply loaded into register a6 before calling the file manager service routines. Word File manager type code. Currently defined values are: 0 - Disk File Manager, FAT based storage allocation 1 - Pipe file manager 2 - Sequencial character file manager (CON:, AUX: PRN:, etc.) 3 - Network File Manager (PowerNET) 4 - Null file manager (sends data nowhere) Return parameter Register D0.L : Zero on success, else possible error code: -73 : File manager table is full. No more file managers may be added to the system. In assembly language: move.w fm_type,-(sp) pea fm_vars pea subroutine_tab pea fm_name move.w #$93,-(sp) trap #1 lea 16(sp),sp +--------------------------------------------------------------------------+ 7.19 94: Add a new device driver to the system, or replace an old one long Drv_add(drv_name,subroutine_tab,drv_vars) char *drv_name; char *subroutine_tab; char *drv_vars; { } dev_dd_add macro +-------------------------------------+ Low memory (parameter | Function Code 0x94 | Word block addr) +-------------------------------------+ | | + Pointer to device driver name + Long 1 | | +-------------------------------------+ | | + Pointer to subroutine index table + Long 2 | | +-------------------------------------+ | | + Pointer to driver's variables + Long 3 | | +-------------------------------------+ High memory This function is used to add a new device driver to PowerDOS, or to replace an existing one. The PowerDOS kernal does not use device drivers directly; it merely notes their existance and allows them to be logically tied to a file manager when a device is created with the Dev_create call. For more information, call, but not collect. Long 1 Name by which the driver will be known to the system. Must be in uppercase, 7 characters max, null terminated. Long 2 Pointer to subroutine index table. Each value in the table is a signed int that is taken as an offset from the start of the table to the service function (a relative offset). The meaning of the entries in this table are dependant upon the file manager for which the driver is designed to service. Long 3 Pointer to any global variables that the device driver may require. This value has no meaning to the file manager. It is simply loaded into register a6 before calling the driver's service routines. Return parameter Register D0.L : Zero on success, else possible error code: -73 : Device driver table is full. No more drivers may be added to the system. In assembly language: pea drv_vars pea subroutine_tab pea drv_name move.w #$94,-(sp) trap #1 lea 14(sp),sp +--------------------------------------------------------------------------+ 7.20 95: Return device info for requested device index long Devinfo(idx,buffer) word idx; struct dev_info *buffer; { } +-------------------------------------+ Low memory (parameter | Function Code 0x95 | Word block addr) +-------------------------------------+ | Index of device name to read | Word +-------------------------------------+ | | + Pointer to buffer to receive info + Long | | +-------------------------------------+ High memory This function returns three pieces of information about a device whose device index number is provided. The information is placed into the following structure: struct dev_info { char dev_name[8]; /* 7 char max device name, null terminated */ int fm_type; /* File manager type code */ int share_flag; }; Word Index of device for which information is to be returned. Index numbers start with zero. Long Pointer to structure which will be filled in with information. Return parameter Register D0.L : Zero if no error, else possible error codes: -85 : No device exists for this device number. The only cause for this error is that a logical disk device was created at this index number, but no physical device exists, therefore the device is invalid. -86 : No device exists for this or higher device index numbers, i.e. no more devices exist. In assembly language: pea buffer move.w idx,-(sp) move.w #$95,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ 7.21 96: Send a signal to a process long Send(process_id,signal_code) word process_id; long signal_code; { } +-------------------------------------+ Low memory (parameter | Function Code 0x96 | Word block addr) +-------------------------------------+ | ID of process to send signal to | Word +-------------------------------------+ | | + Signal to send to process + Long | | +-------------------------------------+ High memory The Send function sends a signal to a specified process, and is similar to the F$Send function call of OS-9. It can be used as a general purpose interprocess communication facility, providing the information to be exchanged can be represented in 32 bits or less. Also, there are three predefined and reserved values that are interpreted by the Send function itself. Currently, this call is used extensively by the kernal and file managers to unblock processes that were blocked for I/O. It is not as usefull as the Unix style signals, other than passing a longword between processes. At some future date, a Unix like signalling facility will probably be added to PowerDOS. Word Process ID of the process to send the signal to. A process can send a signal to itself. Long The signal being sent. Three possible values are predefined: 0 - Kill 1 - Wake 2 - Keyboard abort All other codes are user defined. If there is no signal intercept routine installed, an error will be returned, although the receiving process will be unblocked if it was blocked. Return parameter Register D0.L : Zero if no error, else possible error codes: -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. -88 : Process has no signal intercept routine installed. Signal cannot be read by intended process. In assembly language: move.l signal_code,-(sp) move.w process_id,-(sp) move.w #$96,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ 7.22 97: Install signal intercept routine long Sig_intercept(intercept_rtn,var_ptr) int (*intercept_rtn)(long, void *); long *var_ptr; +-------------------------------------+ Low memory (parameter | Function Code 0x97 | Word block addr) +-------------------------------------+ | | + Address of signal intercept routine + Long 1 | | +-------------------------------------+ | Pointer to pass to signal | + + Long 2 | intercept routine | +-------------------------------------+ High memory This routine allows a process to install a handler for signals that it may receive from other processes. The handler must preserve registers a3-a6/d3-d7. It will be executed in supervisor state, and must not move to user state. It must not make any OS calls, just do what it has to do to deal with the signal (like storing it for later processing) and exit with an RTS. Long 1 Address of a service routine. Long 2 Pointer to any variables that the intercept routine may require. When the service routine is called, this pointer will be passed to it, along with the signal itself. Return parameter Register D0.L : Always zero, there is never an error In assembly language: pea var_ptr pea intercept_rtn move.w #$97,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ 98: Suspend a process long Suspend( process_id ) int process_id; { } +-------------------------------------+ Low memory (parameter | Function Code 0x98 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ High memory Note: only a super user process may suspend any process. Non-superuser processes may only suspend processes with the same group.user id. If the process to be suspended is in user state, it will be moved to the event queue. If it is in system state, then it will be moved to the event queue as soon as it reenters user state. Word ID of process to suspend. If zero, the calling process will suspend itself. Return Parameter: Register D0.L : If positive, then lowest byte is current queue of process (if it was a process other than caller). Possible error codes (if negative): -62 : Permission violation. Non super user process may not suspend a process with a different group.user id. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.w process_id,-(sp) move.w #$98,-(sp) trap #1 addq.l #4,sp +--------------------------------------------------------------------------+ 7.23 99: The Message Queue int Q_message(mparams) /* Parameters are passed as a pointer to a structure */ struct mq_params { int cmd; /* Command to execute (0-5) */ union { char *name; /* 0 - Create, 1 - Open message queue */ int handle; /* 2 - Close, 3 - Delete queue */ struct { int handle; struct { long data[4]; } *message; long timeout; } r_w; /* 4 - Read , 5 - Write message */ } cmd_blk; } *mparams; +-------------------------------------+ Low memory (parameter | Function Code 0x99 | Word block addr) +-------------------------------------+ | | + Pointer to parameter structure + Long | | +-------------------------------------+ High memory This function provides access to the message queue. The messages passed are represented by four longwords. A queue may be created, opened (if it already exists), closed, deleted (if there are no other users), read from and written to. Long Pointer to a structure that contains parameters dependant upon the function to perform. /* To open an existing queue, or create it if it doesn't yet exist */ int q_make(name,q_parms) char *name; struct mq_params *q_parms; { int qh; /* Queue handle */ q_parms->cmd_blk.name = name; q_parms->cmd = 1; /* Try to open existing queue */ if(qh = Q_message(q_parms) < 0){ q_parms->cmd = 0; /* If failed, try create */ if(qh = Q_message(q_parms) < 0) return(-1); } return(qh); /* Queue handle back to caller */ } /* Writing a message to a queue */ int q_write(qh,q_parms,q_msg) int qh; struct mq_params *q_parms; struct qmsg { long message[4]; } *q_msg; { q_parms->cmd_blk.r_w.handle = qh; q_parms->cmd_blk.r_w.message = q_msg; q_parms->cmd = 5; return(Q_message(q_parms)); } /* Reading from a queue */ int q_read(qh,q_parms,q_msg,timeout) int qh; struct mq_params *q_parms; struct qmsg *q_msg; long timeout; /* Used as parameter to Sleep function */ { q_parms->cmd_blk.r_w.handle = qh; q_parms->cmd_blk.r_w.message = q_msg; q_parms->cmd_blk.r_w.timeout = timeout; q_parms->cmd = 4; return(Q_message(q_parms)); } /* Closing and possibly deleting the queue */ int q_close(qh,q_parms) int qh; struct mq_params *q_parms; { int rc; q_parms->cmd = 2; q_parms->cmd_blk.handle = qh; if(rc = Q_message(q_parms) == 0){ /* If we are last to close... */ q_parms->cmd = 3; rc = Q_message(q_parms); /* Then delete the queue */ } return(rc); } Return parameter Register D0.W : Dependent upon function. If no errors, will return queue handle (a positive integer) for create and open; zero for delete, read and write; count of queue users remaining for close (when close returns zero, no other users of queue). Possible errors: -52 : Bad name. Queue name passed to create or open was illegal. -61 : Timeout. No message became available for read before timeout expired. Returned on read command. -73 : Table full; no room for another queue or message, and no memory available to allow table expansion. Returned on create and write. -77 : Queue not found. There is no queue using the name passed in queue open command. -78 : Unknown queue. Handle passed in close, delete, read or write does not represent a currently existing queue. -79 : Queue in use. Cannot delete queue, as it is still opened by another (or same) process. -80 : Queue empty. There is no message to read. Returned from read command when timeout is set to -1 (immediate exit if no message available for read). -81 : Queue already exists. Name passed as a parameter to the create command is in use by another queue. In assembly language: pea mparams move.w #$99,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.24 9A: The Semaphore function int Semaphore(sparams) /* Parameters are passed as a pointer to a structure */ struct sparams { int cmd; /* Command to execute (0-5) */ union { char *name; /* Create, Open */ int handle; /* Close, Delete, Release */ struct { int handle; long timeout; } own; /* Semaphore own */ } cmd_blk; } *sparams; +-------------------------------------+ Low memory (parameter | Function Code 0x9a | Word block addr) +-------------------------------------+ | | + Pointer to parameter structure + Long | | +-------------------------------------+ High memory This function is exactly like the message queue, except there is no message involved. Issuing a release command simply increments a count, and issuing an own command decrements the count (a process doing an own will be blocked if the count is less than one, for a time specified in the timeout parameter). Long Pointer to a structure that contains parameters dependant upon the function to perform. Return parameter Register D0.W : Dependent upon function. If no errors, will return semaphore handle (a positive integer) for create and open; zero for delete, own and release; count of semaphore users remaining for close (when close returns zero, no other users of semaphore). Possible errors: -52 : Bad name. Semaphore name passed to create or open was illegal. -61 : Timeout. Count never became greater than zero before timeout expired. Returned on own command. -73 : Table full; no room for another semaphore, and no memory available to allow table expansion. Returned on create. -77 : Semaphore not found. There is no semaphore using the name passed in open command. -78 : Unknown semaphore. Handle passed in close, delete, own or release does not represent a currently existing semaphore. -79 : Semaphore in use. Cannot delete semaphore, as it is still opened by another (or same) process. -80 : Semaphore empty. Returned from own command when timeout is set to -1 (immediate exit if count is less than one). -81 : Semaphore already exists. Name passed as a parameter to the create command is in use by another semaphore. In assembly language: pea sparams move.w #$9a,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.25 9B: Shared memory int Mem_share(msparams) /* Parameters are passed as a pointer to a structure */ struct msparams { int cmd; /* Command to execute (0-3) */ union { struct { char *name; char *start; /* Return: start of block */ long length; /* Input for create, return for open */ } c_o; /* Create, Open */ int handle; /* Close, Delete */ } cmd_blk; } *msparams; +-------------------------------------+ Low memory (parameter | Function Code 0x9b | Word block addr) +-------------------------------------+ | | + Pointer to parameter structure + Long | | +-------------------------------------+ High memory This function provides for a named block of memory. This memory is not owned by any process, but by the operating system; thus if a process using the named memory terminates, the memory won't be freed. Long Pointer to a structure that contains parameters dependant upon the function to perform. Return parameter Register D0.W : Dependent upon function. If no errors, will return shared memory handle (a positive integer) for create and open; zero for delete; count of users remaining for close (when close returns zero, no other users of shared mamory). Possible errors: -52 : Bad name. Shared memory name passed to create or open was illegal. -73 : Table full; no room for another name, and no memory available to allow table expansion (so probably no memory available for the actual shared memory block, either). Returned on create. -77 : Memory name not found. There is no shared memory block using the name passed in open command. -78 : Unknown memory block. Handle passed in close or delete does not represent a currently existing named memory block. -79 : Named memory in use. Cannot delete, as it is still opened by another (or same) process. -81 : Named block already exists. Name passed as a parameter to the create command is in use by another memory block. In assembly language: pea msparams move.w #$9b,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ 7.26 9E: Read or modify a GemDOS, BIOS or XBIOS function vector long Chgvector(trap_num,vector_num,new_vector) int trap_num; int vector_num; char *new_vector; { } +-------------------------------------+ Low memory (parameter | Function Code 0x9e | Word block addr) +-------------------------------------+ | Trap number (1, 13 or 14) | Word +-------------------------------------+ | Vector number to change | Word +-------------------------------------+ | | + New vector or read only if -1 + Long | | +-------------------------------------+ High memory This function allows a single function vector to be read or modified. For instance, the trap #1 Fopen function could be intercepted, and replaced by a whole new Fopen function. Word Part of operating system for which function vector is to be read or written, given as its trap number. Trap 1 is GemDOS, trap 13 is the BIOS (Basic Input/Output System), and trap 14 is the XBIOS (eXtended Basic Input/Output System). Word Function number of the vector to be read or written. Long New vector, or -1 to denote a read only operation. Note: because of the multitasking nature of PowerDOS, it is possible that another running task could use the new function as soon as the vector is modified. Therefore it is necessary to completely initialize the replacement routine before its vector is inserted into the function table. As soon as this call is made to modify the function table, the replacement routine should be able to handle requests made of it. Return parameter Register D0.L : If no errors (noted by a negative), will return the previous contents of the vector. Possible errors: -64 : Range error. Either an incorrect trap number was given (not 1, 13 or 14), or the vector number was too large. In assembly language: pea new_vector move #vector_num,-(sp) move #trap_num,-(sp) move #$9e,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ 7.27 9f: Read or modify a PowerDOS internal variable long Chgsysvar(var_num,flag,new_value) int var_num; int flag; long new_value; { } +-------------------------------------+ Low memory (parameter | Function Code 0x9f | Word block addr) +-------------------------------------+ | Number of variable to read/change | Word +-------------------------------------+ | Read/change flag | Word +-------------------------------------+ | New value if change flag <> 0 | + + Long | (May be only lsb or lsw of long) | +-------------------------------------+ High memory Some of the internal PowerDOS variables may be read; others may be read or written. This function call provides access to these values. In the table below, a 'w' next to the number means it's a writeable value, 'r' means read only. 0 w = G_maxtpa long Max TPA size given to a new process 1 r = G_rsvmem long Artificial top of ram to limit m_alloc(-1) 2 w = G_rsvmaxbl long Max block size returned within topmem area 3 w = G_max_age word Max age to age a process 4 w = G_min_pty word Minimum ageable priority; if below, don't age 5 r = G_timeslice word Number of milliseconds per tick 6 r = G_idlecnt long Idle CPU time. In milliseconds 7 w = G_fastload long Amount of heap to clear on program startup 8 w = G_term long Vector jumped through on process termination 9 w = G_pexec long Vector jumped through on process creation 10 w = G_trace long Vector jumped through during function call trace 11 w = G_alias long Pointer to first in linked list of device aliases 12 w = G_pathcheck long Vector jumped through for path parse routine 13 w = G_extservic long Pointer to first in linked list of extended service function tables 14 r = G_version long GemDOS and PowerDOS version numbers 15 r = G_sysdate long Date/time of PowerDOS system build 16 unused 17 unused 18 unused 19 r = int_eos long Pointer to system interupt end-of-service handler For G_term, G_pexec and G_trace, the vectors are initialized to 0, which signals the kernal not to use the vector. Due to the fact that PowerDOS uses preemptive multitasking, the only reliable way to grab one of these vectors is to go into supervisor mode, set the IPL to 7, issue the call to change (and return the old) vector, save the old vector (which may be 0L) then drop back to the previous IPL. The kernal will JSR through the vector, and each program in the vector chain should do whatever processing it needs to do, then fall through the saved vector, UNLESS IT WAS 0L. In the later case, it should just RTS. When a G_term vector is called, registers d5-d7/a5-a6 must be preserved. a5 points to the process descriptor of the dying process. a6 points to the kernals variables. G_term may be used to clean up a processes environment or some such function. G_pexec is called just before the following instructions, which execute a new task: movem.l (sp)+,d0-a6 Get new processes registers rte Execute it Thus any and all registers may be used. a5 points to the new processes process descriptor, and a6 points to the kernals variables. G_trace is called when a process makes a Trap #1 call, and has its trace bit set (see function 0xa2 below). Register a4 will point to the parameters to the call (thus 0(a4) will always be the function number of the call being executed), a5 points to the process descriptor, and a6 is the kernals variables; register d1 will be a 0 if this is the start of the trace (trace is called before the execution of the function, and again after the function is finished), or a -1 if this is the end of the trace (a4 is undefined at the end of the trace). Registers a4-a6 must be preserved. All others may be used (if d1 is -1, then d0 is the return code from the function). Word Variable that is to be read or possibly written. Numbered from 0 to 19. Currently numbers 16, 17 and 18 are not used, and will return an error if you try to read or change them. Word Read/change flag. Zero means read the variable only. Long New value of variable if flag is not zero. Note that not all of the variables are changeable. If you try to change a variable that is read only, no error will be returned, just the contents of the variable. Also, some of the variables are word, and some are long. For word values, only the lower word of the long will be used. Register D0.L : If no errors (noted by a negative), will return the previous contents of the variable. Possible errors: -32 : Invalid variable number. Note: no range checking is performed on the new value for a variable (if flag is <> 0) so it is up to the caller to insure that the new value is in range, else unpredictable results may occur. In assembly language: move.l new_value,-(sp) move flag,-(sp) move var_num,-(sp) move #$9f,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ A0: Read or modify the name of a process long Pname(proc_id,get_set,name) int proc_id; int get_set; char *name; { } +-------------------------------------+ Low memory (parameter | Function Code 0xA0 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ | Get or set flag | Word +-------------------------------------+ | | + Pointer to character array + Long | | +-------------------------------------+ High memory This function allows you to read or change the name of a process. Note that only the superuser may change the name of any process. Non superusers may only change the name of processes with the same group.user ID. Word Process ID of the process whose name is to be read or written. Zero stands for the current (calling) process. Word Read or write flag. 0 means read. Long Pointer to character buffer at least 14 bytes long for read, (flag = 0), or null terminated string for new name (max string length is 13 characrters). Return parameter Register D0.L : Zero if no errors detected. Possible errors: -62 : Permission violation. Process tried to change the name but was not a super user or did not have same owner ID. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: pea name move #get_set,-(sp) move #proc_id,-(sp) move #$A0,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ A1: Read or modify a process' user vector long Pvector(proc_id,vector) int proc_id; long vector; { } +-------------------------------------+ Low memory (parameter | Function Code 0xA1 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ | | + Vector + Long | | +-------------------------------------+ High memory This function allows you to read or change a user defined vector for any process. Note that the kernal doesn't look at or otherwise use this vector. It is simply a very low level way to pass data between processes. The long value could be a pointer to shared memory, or just a longword value that has meaning to the processes involved. Word Process ID of the process whose vector is to be read or written. Zero stands for the current (calling) process. Long If this is zero, then the call just returns the current value of the user vector; else is the new value of the vector. Thus the value zero cannot be used as a data value. Return parameter Register D0.L : Old vector if no error. Possible errors: -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. Note: it is possible to confuse legitimate values with these two error codes. It is therfore recomended that these values be avoided as potential data. In assembly language: move.l #vector,-(sp) move #proc_id,-(sp) move #$A1,-(sp) trap #1 addq.l #8,sp +--------------------------------------------------------------------------+ A2: Set or clear bits in a process' attribute byte long Pattrib(proc_id,flag,mask) int proc_id; unsigned char flag; unsigned char mask; { } +-------------------------------------+ Low memory (parameter | Function Code 0xA2 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ | Set/Clear flag | Byte +-------------------------------------+ | Bit mask for bits to change | Byte +-------------------------------------+ High memory This function allows you to selectively set or clear bits in the processes attribute byte. Currently, these bits are defined: #define B_redirect 0 /* Have BIOS check for con redirection */ #define N_redirect 1 /* Make negative handles redirect */ #define proc_trace 3 /* If set, jump through trace vector on function call */ Word Process ID of the process whose attribute byte is to be changed. Zero stands for the current (calling) process. byte Set or clear flag. If zero, is a clear bit operation, else is a set bit operation. byte Mask of bits to modify. If a bit is set in this byte, then that particular attribute bit will be changed according to the flag byte. Return parameter Register D0.L : If not negative, lower byte is attribute byte before operation. Possible errors: -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: lsl.w #8,d0 d0 is flag byte or.w d1,d0 d1 is mask move d0,-(sp) move #proc_id,-(sp) move #$A2,-(sp) trap #1 addq.l #6,sp +--------------------------------------------------------------------------+ A3: Set or get the maximum memory returned for Malloc(-1) for a process long Pmaxmem(proc_id,flag,size) int proc_id; int flag; long size; { } +-------------------------------------+ Low memory (parameter | Function Code 0xA3 | Word block addr) +-------------------------------------+ | Process ID | Word +-------------------------------------+ | Set/get flag | Word +-------------------------------------+ | | + New max memory value + Long | | +-------------------------------------+ High memory This function allows you to set a maximum for a Malloc(-1) function call made by a process. Since most programs will do a Malloc(-1) call to determine how much memory is in the system, then malloc all of that memory, this function can keep most memory hogs at bay. If this value is set to zero for a process, then no maximum is in effect and the kernal will return the size of the largest block of ram. Note: a newly forked process will inherit its parent's max_mem setting. Also, only a super user may change this value for all processes, else only processes with the same group.user ID may be changed. Word Process ID of the process whose max memory value is to be read or written. Zero stands for the current (calling) process. Word Set or get flag. If zero, is a get operation, else is a set operation. Long New max memory value for a set call. Return parameter Register D0.L : If not negative, is original setting before a set call. Possible errors: -62 : Permission violation. Process tried to change the max mem value but was not a super user or did not have same owner ID. -70 : Unknown process. Process ID is for a process that has never existed (no process descriptor has been created for that PID). -71 : Dead process. The process ID was for a process that has terminated. In assembly language: move.l #size,-(sp) move #flag,-(sp) move #proc_id,-(sp) move #$A3,-(sp) trap #1 lea 10(sp),sp +--------------------------------------------------------------------------+ Following are listings some important PowerDOS structures. These are shown, not as C structures, but as Hisoft formatted assembly language defines, since PowerDOS was written completely in assembly language. The PowerDOS process descriptor: Num_files equ 32 Number of open files per process RSRESET PD_ID rs.w 1 Process ID PD_parent rs.w 1 Parent's ID PD_sibling rs.w 1 Sibling's ID PD_child rs.w 1 First child's ID PD_group rs.w 1 Group ID PD_user rs.w 1 User ID PD_priority rs.w 1 Process priority PD_age rs.w 1 Process age PD_status rs.b 1 Process execution status PD_queueID rs.b 1 Current queue (sleep, wait or active) PD_basepage rs.l 1 First memory block of process (basepage) PD_max_mem rs.l 1 Max mem size returned for Malloc #-1 PD_ucall rs.w 1 Last user state function call executed PD_scall rs.w 1 Last system state function call executed PD_uticks rs.l 1 Number of user state ticks elapsed PD_sticks rs.l 1 Number of system state ticks elapsed PD_sleep rs.l 1 Count of ticks to remain sleeping PD_datetime rs.l 1 Date and time process started PD_fcalls rs.l 1 Number of function calls executed PD_iocalls rs.l 1 Number of i/o calls executed PD_rbytes rs.l 1 Number of bytes read PD_wbytes rs.l 1 Number of bytes written PD_vector rs.l 1 User defined vector PD_dta rs.l 1 Disk transfer address PD_name rs.b 14 Name of process PD_devname rs.b 8 Process current device name (currently only A, B, C, etc.) PD_files rs.w Num_files Process local path handles PD_reentry rs.b 1 Count of number of levels of reenterancy to kernal PD_attrib rs.b 1 Various attributes PD_memblk rs.w 1 Index of head of procs mdb's PD_pqueue rs.l 1 Previous process queue pointer PD_nqueue rs.l 1 Next process queue pointer PD_pioq rs.w 1 ID of previous process in i/o queue PD_nioq rs.w 1 ID of next process in i/o queue PD_q_ptr rs.l 1 Pointer or flag for queue functions PD_intcpt rs.l 1 Address of signal intercept routine PD_intcptv rs.l 1 Address of vars needed for intercept PD_signal rs.l 1 Signal code that caused death PD_stack rs.l 1 Process stack pointer PD_reg_save rs.l 1 Pointer to current (X)BIOS register save PD_trap1 rs.l 1 Save area for "dirty" trap one vector PD_alias rs.l 1 Pointer to alias being used for current i/o operation PD_defdirs rs.l 26 Default directory of up to 26 drives * Dir's first cluster number, 0 for root. Copied from parent when created * Most file managers that use this feature require only words, but a long * is allocated for future file managers. PD_status2 rs.b 1 Place for new attributes to be stored PD_reserve1 rs.b 1 PD_reserve2 rs.w 18 Space for additions in the future... PD_stackbot rs.b 1000 Process supervisor stack space PD_sstack equ __RS Top of process supervisor stack rs.b 162 Allow for 3 levels of reentrancy to (X)BIOS PD_bios_sav equ __RS PD_size equ __RS Size of process descriptor * Process descriptor block allocation size. First long is pointer to next * block. Ten process descriptors per block allocated PD_alloc equ 4+PD_size*10 * Status flag bits (for PD_status) Sys_state equ 0 Executing in system state Wake_sig equ 1 Process has pending wakeup signal Time_out equ 2 Time slice has expired Subtask equ 3 Process is a subtask (thread) of parent Pexec4 equ 4 Assign base memory to parent on exit Condemn equ 5 Process is condemned Concurrent equ 6 Task is running concurrently with parent Deskthread equ 7 Set if process is Desktop process or decendent * Bit definitions for PD_attrib B_redirect equ 0 Have BIOS check for con redirection N_redirect equ 1 Make negative handles redirect proc_trace equ 3 If set, jump through trace vector on function call * Status flag bits for PD_status2 s2_preempt equ 0 Allow preemption when clear, even if process is in system state s2_suspend equ 1 Suspend process at next entry to user state * Defined signals S_kill equ 0 S_wake equ 1 S_abort equ 2 * (Maybe someday PowerDOS will have a more Unix like signalling system) * Queue ID codes (for PD_queueID) Q_current equ 0 No queue, currently running Q_active equ 1 Active process queue Q_sleep equ 2 Sleeping process queue Q_wait equ 3 Waiting process queue Q_event equ 4 Waiting for an event Q_dead equ 5 No queue, dead process +--------------------------------------------------------------------------+ Error code definitions (some are only used internally) Edskchg equ -14 Disk in drive was changed Einvfn equ -32 Invalid function number Efilnf equ -33 File not found Epthnf equ -34 Pathname not found Enhndl equ -35 No file handles left Eaccdn equ -36 Access denied Eihndl equ -37 Invalid handle number Ensmem equ -39 Not enough memory left Eimba equ -40 Invalid memory block address Edrive equ -46 Invalid drive specification Enmfil equ -49 No more matching files Ebnam equ -52 Bad pathname element Efaterr equ -53 Error with FAT table Edskfull equ -54 Disk is full Elpcl equ -55 Clusters looped Erootful equ -56 Root directory is full Edirex equ -57 Directory already exists Elocked equ -58 Record is locked Enslock equ -59 Can't find requested lock to remove Eeof equ -60 End of file Etime equ -61 Device timed out Epermit equ -62 Permission violation Enovol equ -63 No volume name, can't change attributes Erange equ -64 Range error Eintrn equ -65 Internal error Eplfmt equ -66 Invalid program load format Egsbf equ -67 Setblock failure Eunknp equ -70 Unknown process Edeadpr equ -71 ID is for dead process Enochld equ -72 Process has no children Etabfull equ -73 IO device table is full Efmddne equ -74 File manager or device driver non-existant Eprocnf equ -75 Process with this name not found Eioqs equ -76 Process already part of this ioqueue chain Eqnf equ -77 Queue not found (by name) Eunknq equ -78 Unknown queue (by queue_id) Eqinuse equ -79 Queue in use; can't delete Eqempty equ -80 Queue has no message or count available Eqexist equ -81 Can't create; queue w/ same name exists Epipex equ -82 Can't create; pipe w/ same name exists Epipenf equ -83 Named pipe not found for open Epipewrt equ -84 Pipe write error: written data can't be read Enodev equ -85 No device for given device number Enomdev equ -86 No devices with given number or higher Eorphan equ -87 Process is an orphan; it has no parent Enosighand equ -88 Process has no signal handler installed +--------------------------------------------------------------------------+ Kernal variables: RSRESET G_active rs.l 1 Head of active queue G_sleep rs.l 1 Head of sleeping queue G_wait rs.l 1 Head of waiting queue G_event rs.l 1 Head of event queue G_cur_pd rs.l 1 Process descriptor of current process G_totram rs.l 1 Total ram found in system (TPA size) G_bottpa rs.l 1 Bottom of TPA G_toptpa rs.l 1 Top of TPA G_maxtpa rs.l 1 Maximum tpa size given to process G_rsvmem rs.l 1 High water mark of (S)Malloc(-1) calls G_rsvmaxbl rs.l 1 Max block size returned in G_rsvmem area G_mem_mdb rs.l 1 Points to 1st block of memory descriptor blocks G_hmem_st rs.w 1 Index of head of memory segment list (ST ram) G_tmem_st rs.w 1 Index of tail of memory segment list G_sys_mem rs.w 1 Index of linked system memory blocks G_memblks rs.w 1 Number of free memory block descriptors * Extra ram that may be added to the system is allways considered fastram. * When a block is added for the first time, the index to the head and tail * of the memory (the next two variables) are defined. If any more memory * is added after this, it will be added in to the same structure. (If it * is not contiguous with previous added ram, there will be a gap, but the * memory allocate and free routines deal with this situation properly.) G_hmem_alt rs.w 1 Head of alternate (TT) memory G_tmem_alt rs.w 1 Obviously the tail of said memory G_pd rs.l 1 Points to 1st process descriptor block G_pthd rs.l 1 Points to 1st path descriptor block G_queue_dir rs.l 1 Points to 1st queue directory block G_queue_buf rs.l 1 Points to 1st queue buffer block G_max_age rs.w 1 Max age to age a process G_min_pty rs.w 1 Min priority of ageable process G_timeslice rs.w 1 Number of milliseconds per tick (20) G_ticks rs.w 1 Number of ticks per second (50) G_timeout rs.l 1 Global timeout added to 200 hz clock G_idlecnt rs.l 1 Used to keep track of idle time in 5 ms periods G_idlecntdn rs.w 1 Count till next increment G_fastload rs.l 1 Number of k of heap to clear on prg load G_aes_stack rs.l 1 Current aes stack top G_term rs.l 1 Vector to jump through on proc term G_pexec rs.l 1 Vector to jump through on proc create G_trace rs.l 1 Vector to jump through to trace a process' function calls G_alias rs.l 1 Pointer to any drive/path replacements G_pathcheck rs.l 1 Vector to jump through before path parsing * To allow PowerDOS to be expanded (or to emulate other OS's), a pointer * to another table of vectors is available (zero when not used). The first * long in this table is a pointer to another such table. The third word * is the lowest sevice number in the table, and the fourth word is the * highest service number. Following this is the long word pointers to * the service functions. If a vector in this table is not used (an unused * function) it should be set to zero. G_extservic rs.l 1 Pointer to a table of extended services G_p_run rs.l 1 GemDOS p_run pointer; points to basepage G_version rs.w 1 Version number of GemDOS we are replacing G_sysver rs.w 1 Version of PowerDOS G_sysdate rs.l 1 Date of PowerDOS build (YYYYMMDD) G_flags rs.b 1 Various flags bits that may be needed * Definitions for the bits in G_flags. Gf_cookjar equ 0 Set if PowerDOS installed the cookie jar Gf_server equ 1 Set if system is being used as a network server G_reserve rs.b 1 * When we launch a concurrent task, we give it clean OS vectors so no tsr * programs will also be in the vectors. Such programs tend to fail when * used in a multitasking environment. The following are the original * vectors set when PowerDOS was installed. G_trap1 rs.l 1 Vector for BDOS G_trap13 rs.l 1 Vector for BIOS G_trap14 rs.l 1 Vector for XBIOS * The following is the special reserved block of memory used for video ram. Both * its start address and index are given. This is for the Falcon only, to emulate * the Mrealloc function call. G_videomem rs.l 1 Start address of special videomem block G_videoidx rs.w 1 Index of MDB of video memory +--------------------------------------------------------------------------+