Changes

2,132 bytes added ,  11:33, 21 October 2023
Fix source code missing
Line 231: Line 231:  
|-
 
|-
 
| 2
 
| 2
| 0x00000004 <nowiki>|</nowiki> (size<<14) <nowiki>|</nowiki> (static_buffer_id<<4)
+
| 0x00000004 <nowiki>|</nowiki> (size<<8) <nowiki>|</nowiki> (static_buffer_id<<4)
 
<ptr>
 
<ptr>
 
| This is typically used for RW buffers over PXI, but any process can use this. The address written to the destination cmd-buf is a phys-addr for a table located in the corresponding static buffer of the receiving process (which must be provided by the latter, otherwise the kernel dereferences NULL). Each static buffer needs to be page-aligned and musn't exceed a page's length (kernelpanic otherwise). This table contains the phys-addrs for the actual data, the array entries have the following format: {u32 *datachunk_physaddr, u32 datachunk_bytesize}.
 
| This is typically used for RW buffers over PXI, but any process can use this. The address written to the destination cmd-buf is a phys-addr for a table located in the corresponding static buffer of the receiving process (which must be provided by the latter, otherwise the kernel dereferences NULL). Each static buffer needs to be page-aligned and musn't exceed a page's length (kernelpanic otherwise). This table contains the phys-addrs for the actual data, the array entries have the following format: {u32 *datachunk_physaddr, u32 datachunk_bytesize}.
 
|-
 
|-
 
| 3
 
| 3
| 0x00000006 <nowiki>|</nowiki> (size<<14) <nowiki>|</nowiki> (static_buffer_id<<4)
+
| 0x00000006 <nowiki>|</nowiki> (size<<8) <nowiki>|</nowiki> (static_buffer_id<<4)
 
<ptr>
 
<ptr>
 
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
 
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
 
|}
 
|}
 +
 +
 +
== SVCs ==
 +
 +
=== svcReplyAndReceive ===
 +
 +
'''Signature:'''
 +
Result ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)
 +
 +
In a single operation, sends a IPC reply and waits for a new request. <code>handles</code> should be a pointer to an array of <code>handleCount</code> handles.<sup>TODO: Are only port/session handles supported?</sup>
 +
<code>replyTarget</code> should contain a handle to the session to send the reply to. (This is usually the session from which we received the previous request.)
 +
If <code>replyTarget</code> is 0, no reply and the call will simply wait for an incoming event.<sup>TODO: It doesn't seem like the 0xFFFF0000 command id mentioned in the above sections is necessary, but needs confirmation.</sup>
 +
 +
Upon returning, <code>index</code> will contain an index into <code>handles</code> specifying which object changed state.
 +
If it's a server port endpoint, it means that there is a new incoming connection on that port which should be accepted using svcAcceptSession.
 +
If it's a server session endpoint it means that we received a request from that session and should process and then reply to it by calling svcReplyAndReceive again with <code>replyTarget</code> set to that session's handle.
 +
 +
An example of a server svcReplyAndReceive loop is:
 +
 +
#define MAX_CLIENTS 4
 +
Handle server_port = ...;
 +
s32 requesting_index;
 +
Handle handles[1 + MAX_CLIENTS] = { server_port };
 +
s32 connected_clients = 0;
 +
Handle reply_target = 0;
 +
 +
while (true) {
 +
    Result res = svcReplyAndReceive(&requesting_index, handles, 1 + connected_clients, reply_target);
 +
 +
    if (res == 0xC920181A) {
 +
        // Session was closed by remote
 +
        // TODO: Handle disconnects
 +
        reply_target = 0;
 +
        continue;
 +
    }
 +
 +
    if (requesting_index == 0) {
 +
        // New connection in server_port
 +
        ASSERT(connected_client < MAX_CLIENTS);
 +
        svcAcceptSession(&handles[1 + connected_clients++], server_port);
 +
        reply_target = 0;
 +
        continue;
 +
    }
 +
 +
    reply_target = handles[requesting_index];
 +
 +
    // Handle command here and write reply to command buffer
 +
}
2

edits