Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "AmigaDOS Packets"
Steven Solie (talk | contribs) |
Steven Solie (talk | contribs) |
||
Line 1: | Line 1: | ||
+ | {{WIP}} |
||
= Introduction = |
= Introduction = |
||
Revision as of 17:11, 2 May 2012
This page is currently being updated to AmigaOS 4.x. Some of the information contained here may not yet be applicable in part or totally. |
Contents
Introduction
Packet passing handles all communication performed by AmigaDOS between processes. The function diagram below shows how packets fit in with the other components of the Amiga operating system.
+--------------+ | User Process +-----------------------+ +-------+------+ | | | | | Function Calls | | | \|/ | +---------+--------+ | | AmigaDOS Open(), | | | Close(), etc. | | +---------+--------+ | | | | | +-Packets---+--------+ +-----Packets--------+ | | | | | | \|/ \|/ \|/ \|/ \|/ \|/ +----+----+ +----+----+ +-+--+--+-+ +----+----+ +----+----+ | FFS/OFS | | FFS/OFS | | FFS/OFS | | CON: | | CON: | | DH0: | | DF0: | | DF1: | | Window1 | | Window2 | | Handler | | Handler | | Handler | | Handler | | Handler | | Process | | Process | | Process | | Process | | Process | +----+----+ +-------+-+ +----+----+ +----+----+ +----+----+ | | | | | \|/ \|/ \|/ \|/ \|/ +----+--------+ +--+--------+----+ +----+-----------+----+ |Hddisk.device| |Trackdisk.device| | Console.device | +-------------+ +----------------+ +---------------------+
A StandardPacket (defined in <dos/dosextens.h>) is used to send packet commands to a process's MsgPort. The StandardPacket structure contains an Exec Message structure and an AmigaDOS DOSPacket structure:
struct StandardPacket { struct Message sp_Msg; struct DOSPacket sp_Pkt; };
This structure must be longword-aligned, and initialized to link the Message and DOSPacket sections to each other:
packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
Packets must also be initialized with a ReplyPort which can be created with the amiga.lib function CreatePort():
if (replyport = (struct MsgPort *) CreatePort(NULL, 0)) packet->sp_Pkt.dp_Port = replyport;
The DOSPacket portion of the StandardPacket structure is used to pass the packet type and arguments, and to receive the results of the packet. The argument types, number of arguments, and results vary for different packet types and are documented with each packet description. A DOSPacket must be longword-aligned and has the following general structure:
Type | Name | Description |
---|---|---|
struct Message* | dp_Link | Pointer back to Exec message structure |
struct Message* | dp_Port | Reply port for the packet. Must be filled in each send |
LONG | dp_Type | Packet type |
LONG | dp_Res1 | For filesystem calls this is the result that would have been returned by the function; eg. Write("W") returns actual length written. |
LONG | dp_Res2 | For filesystem calls this is what would have been returned by IoErr() |
LONG | dp_Arg1 | Argument 1 (depends on packet type) |
LONG | dp_Arg2 | Argument 2 (depends on packet type) |
LONG | dp_Arg3 | Argument 3 (depends on packet type) |
LONG | dp_Arg4 | Argument 4 (depends on packet type) |
LONG | dp_Arg5 | Argument 5 (depends on packet type) |
LONG | dp_Arg6 | Argument 6 (depends on packet type) |
LONG | dp_Arg7 | Argument 7 (depends on packet type) |
The format of a specific packet depends on its type; but in all cases it contains a back-pointer to the Message structure, the MsgPort for the reply, and two result fields. When AmigaDOS sends a packet, the reply port is overwritten with the process ID of the sender so that the packet can be returned. Thus, when sending a packet to an AmigaDOS handler process, you must fill in the reply MsgPort each time; otherwise when the packet returns, AmigaDOS has overwritten the original port. AmigaDOS maintains all other fields except the result fields.
All AmigaDOS packets are sent to the message port created as part of a process; this message port is initialized so that arriving messages cause signal bit 8 to be set. An AmigaDOS process that is waiting for a message waits for signal 8 to be set. When the process wakes up because this event has occurred, GetMsg() takes the message from the message port and extracts the packet address. If the process is an AmigaDOS handler process, then the packet contains a value in the PktType field that indicates an action to be performed, such as reading some data. The argument fields contain specific information such as the size of the buffer where the characters go.
When the handler process has completed the work required to satisfy this request, the packet returns to the sender, using the same message structure. Both the message structure and the packet structure must be allocated by the client and not deallocated before the reply has been received. Normally AmigaDOS is called by the client to send the packet, such as when a call to Read() is made. However, there are cases where asynchronous I/O is required, and in this case the client may send packets to the handler process as required. The packet and message structures must be allocated, and the process ID field filled in with the message port where this packet must return. A call to PutMsg() then sends the message to the destination. Note that many packets may be sent out, returning to either the same or different message ports.
Packet Types
Packets sent to a filesystem or handler can be divided into several basic categories:
- Basic Input/Output.
- These actions deal with transferring data to and from objects controlled by the handler.
- File/Directory Manipulation/Information.
- These actions are used to gain access to and manipulate the high-level structures of the filesystem.
- Volume Manipulation/Information.
- These actions allow access to the specific volume controlled by the filesystem.
- Handler Maintenance and Control.
- These actions allow control over the handler/filesystem itself, independent of the actual volume or structure underneath.
- Handler Internal.
- These actions are never sent to the handler directly. Instead they are generally responses to I/O requests made by the handler. The handler makes these responses look like packets to simplify processing.
- Obsolete Packets.
- These packets are no longer valid for use by handlers and filesystems.
- Console Only Packets.
- These packets are specific to console handlers. Filesystems can ignore these packets.
Each packet type documented in this section is listed with its action name, its corresponding number, any AmigaDOS routines that use this packet, and the list of parameters that the packet uses. The C variable types for the packet parameters are one of the following types:
Type | Description |
---|---|
BPTR | This is a BCPL pointer (the address of the given object shifted right by 2). Note: This means that the object must be aligned on a longword boundary. |
LOCK | This is a BPTR to a FileLock structure returned by a previous ACTION_LOCATE_OBJECT. A lock of 0 is legal, indicating the root of the volume for the handler. |
BSTR | This is a BPTR to a string where the first byte indicates the number of characters in the string. A byte of this length is unsigned but because the information is stored in a byte, the strings are limited to 255 characters in length. |
BOOL | A 32-bit boolean value either containing DOSTRUE (-1) or DOSFALSE (0). Note: Equality comparisons with DOSTRUE should be avoided. |
CODE | A 32-bit error code as defined in the <dos/dos.h> include file. Handlers should not return error codes besides those defined in <dos/dos.h>. |
ARG1 | The FileHandle->fh_Arg1 field. |
LONG | A 32-bit integer value. |
Basic Input/Output
Directory/File Manipulation/Information
Volume Manipulation/Information
Handler Maintenance and Control
Handler Internal
Obsolete Packets
Console Only Packets
Summary of Defined Packet Numbers
Using Packets Directly
AmigaDOS contains many features that can only be accessed by sending a packet directly to a process. For example, the ACTION_DISK_INFO packet may be used to find the Intuition window pointer of a CON: or RAW: window. This is useful for redirecting system requesters so that they appear where the user can see them (see "Redirecting System Requesters" above). The Window pointer will be returned in the ID_VolumeNode field, and a pointer to the console's I/O request will be returned in the ID_InUse field. Note that auxilary consoles (AUX:) can return a NULL Window pointer, and also may have no ConUnit (io_Unit) associated with their I/O request block. Be careful to check for these possibilities when you use this packet. If your application runs in a CLI window, a user may be running you in an auxilary (AUX:) CLI.
Another example is the ACTION_SCREENMODE_MODE packet which can be sent to the handler process of a CON: window to put the console into raw or cooked mode.
By default, CON: provides mapped keyboard input which is filtered, buffered, and automatically echoed. Many of the special key escape sequences (such as those generated by the function, cursor, and help keys) are filtered out; all strokes are buffered and held back from the reader until the user hits the RETURN key; and the nonfiltered keypresses (such as alphanumeric keys and backspace) are automatically echoed to the CON: window. This "cooked" mode is perfect for general line input from a user because it provides automatic line editing features (same as in the Shell command line).
Sometimes, however, an application needs to get individual keys immediately from a CON: window, or control its own echoing, or receive the escape strings that the keymap generates for special keys such as the Help key or cursor keys.
In this case, an ACTION_SCREEN_MODE packet with the argument DOSTRUE (-1) may be sent to the MsgPort of a CON: window to put the CON: into "raw" mode. In raw mode, a CON: behaves much like a RAW: window. Keyboard console input is not automatically filtered, buffered, or echoed. When reading a CON: which has been set to "raw" mode, each keypress can be read immediately as the ASCII value or string to which the key is mapped by the keymap.
For some applications, it may be convenient to toggle a CON: window between cooked and raw modes, to use cooked mode for use line input, and raw mode when keypresses should cause immediate actions.
ACTION_SCREEN_MODE with the argument DOSFALSE (0L) will place a CON: window in cooked mode. Note that the ACTION_SCREEN_MODE packet may also be used on auxilary (AUX:) consoles.
The handler MsgPort of most named AmigaDOS devices (like DF0:) can be found with the DeviceProc() function. Note that DeviceProc() cannot be used to find a CON: or RAW: handler because there may be many handlers for each of these. The handler MsgPort (ProcessID) of a CON: or RAW: window is in its FileHandle structure (fh_Type). The MsgPort of a CLI process's "*" window is process->pr_ConsoleTask.
Here's how to find the MsgPort of a handler process (in all cases make sure that port is non-NULL before using it):
Finding the MsgPort of a unique named handler process such as "DF0:":
port = (struct MsgPort *) DeviceProc("DF1:");
Finding the MsgPort of the handler process for an open file:
fh = Open("CON:0/40/640/140/Test", MODE_NEWFILE); if ((fh) && (fh->Type)) { /* if Open() succeeded and fh_Type is non-NULL */ port = (struct MsgPort *) (((struct FileHandle *) (fh << 2))->fh_Type); }
Finding the MsgPort of your process's console handler:
struct Task* task = FindTask(NULL); if (task->tc_Node.ln_Type == NT_PROCESS) { /* port may be NULL - check before using! */ port = ((struct Process *) task)->pr_ConsoleTask; }
Packets are sent by initializing a longword-aligned StandardPacket structure and sending the packet to the MsgPort of a handler process.
The dos.library provides new simple functions for sending and replying to packets:
SendPkt() - asynchronously send your initialized packet WaitPkt() - wait for asynchronous packet to complete ReplyPkt() - reply a packet which has been sent to you DoPkt() - creates and sends a packet, and waits for completion