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 |
| + | } |