libdragon
Loading...
Searching...
No Matches
rspq.h
Go to the documentation of this file.
1
168#ifndef __LIBDRAGON_RSPQ_H
169#define __LIBDRAGON_RSPQ_H
170
171#include <stdint.h>
172#include "rsp.h"
173#include "debug.h"
174#include "n64sys.h"
175#include "pputils.h"
176
177#ifdef __cplusplus
178extern "C" {
179#endif
180
182#define RSPQ_MAX_COMMAND_SIZE 62
183
189#define RSPQ_MAX_SHORT_COMMAND_SIZE 16
190
202typedef struct rspq_block_s rspq_block_t;
203
223
234void rspq_init(void);
235
241void rspq_close(void);
242
243
276uint32_t rspq_overlay_register(rsp_ucode_t *overlay_ucode);
277
294void rspq_overlay_register_static(rsp_ucode_t *overlay_ucode, uint32_t overlay_id);
295
311void rspq_overlay_unregister(uint32_t overlay_id);
312
333void* rspq_overlay_get_state(rsp_ucode_t *overlay_ucode);
334
399#define rspq_write(ovl_id, cmd_id, ...) \
400 __PPCAT(_rspq_write, __HAS_VARARGS(__VA_ARGS__)) (ovl_id, cmd_id, ##__VA_ARGS__)
401
403
404// Extern references, not part of rspq public API
405extern volatile uint32_t *rspq_cur_pointer, *rspq_cur_sentinel;
406extern void rspq_next_buffer(void);
407
408// Helpers used to implement rspq_write
409#define _rspq_write_prolog() \
410 volatile uint32_t *ptr = rspq_cur_pointer+1; \
411 (void)ptr;
412
413#define _rspq_write_epilog() ({ \
414 if (__builtin_expect(rspq_cur_pointer > rspq_cur_sentinel, 0)) \
415 rspq_next_buffer(); \
416})
417
418#define _rspq_write_arg(arg) \
419 *ptr++ = (arg);
420
421#define _rspq_write0(ovl_id, cmd_id) ({ \
422 _rspq_write_prolog(); \
423 rspq_cur_pointer[0] = (ovl_id) + ((cmd_id)<<24); \
424 rspq_cur_pointer += 1; \
425 _rspq_write_epilog(); \
426})
427
428#define _rspq_write1(ovl_id, cmd_id, arg0, ...) ({ \
429 _Static_assert(__COUNT_VARARGS(__VA_ARGS__) <= RSPQ_MAX_SHORT_COMMAND_SIZE, "too many arguments to rspq_write, please use rspq_write_begin/arg/end instead"); \
430 _rspq_write_prolog(); \
431 __CALL_FOREACH(_rspq_write_arg, ##__VA_ARGS__); \
432 rspq_cur_pointer[0] = ((ovl_id) + ((cmd_id)<<24)) | (arg0); \
433 rspq_cur_pointer += 1 + __COUNT_VARARGS(__VA_ARGS__); \
434 _rspq_write_epilog(); \
435})
436
438
440typedef struct {
441 uint32_t first_word;
442 volatile uint32_t *pointer;
443 volatile uint32_t *first;
444 bool is_first;
446
479inline rspq_write_t rspq_write_begin(uint32_t ovl_id, uint32_t cmd_id, int size) {
480 extern volatile uint32_t *rspq_cur_pointer, *rspq_cur_sentinel;
481 extern void rspq_next_buffer(void);
482
483 assertf(size <= RSPQ_MAX_COMMAND_SIZE, "The maximum command size is %d!", RSPQ_MAX_COMMAND_SIZE);
484
485 if (__builtin_expect(rspq_cur_pointer > rspq_cur_sentinel - size, 0))
487
488 volatile uint32_t *cur = rspq_cur_pointer;
489 rspq_cur_pointer += size;
490
491 return (rspq_write_t){
492 .first_word = ovl_id + (cmd_id<<24),
493 .pointer = cur + 1,
494 .first = cur,
495 .is_first = 1
496 };
497}
498
520inline void rspq_write_arg(rspq_write_t *w, uint32_t value) {
521 if (w->is_first) {
522 w->first_word |= value;
523 w->is_first = 0;
524 } else {
525 *w->pointer++ = value;
526 }
527}
528
544 *w->first = w->first_word;
545 w->first = 0;
546 w->pointer = 0;
547}
548
605void rspq_flush(void);
606
620void rspq_wait(void);
621
642
657
670
671
689void rspq_block_begin(void);
690
707
725void rspq_block_run(rspq_block_t *block);
726
739void rspq_block_free(rspq_block_t *block);
740
777void rspq_highpri_begin(void);
778
789void rspq_highpri_end(void);
790
799void rspq_highpri_sync(void);
800
807void rspq_noop(void);
808
824void rspq_dma_to_rdram(void *rdram_addr, uint32_t dmem_addr, uint32_t len, bool is_async);
825
841void rspq_dma_to_dmem(uint32_t dmem_addr, void *rdram_addr, uint32_t len, bool is_async);
842
844__attribute__((deprecated("may not work anymore. use rspq_syncpoint_new/rspq_syncpoint_check instead")))
845void rspq_signal(uint32_t signal);
848#ifdef __cplusplus
849}
850#endif
851
852#endif
Debugging Support.
#define assertf(expr, msg,...)
assertf() is like assert() with an attached printf().
Definition debug.h:196
N64 System Interface.
Low-level RSP hardware library.
void rspq_next_buffer(void)
Switch to the next write buffer for the current RSP queue.
Definition rspq.c:920
volatile uint32_t * rspq_cur_pointer
Copy of the current write pointer (see rspq_ctx_t)
Definition rspq.c:325
volatile uint32_t * rspq_cur_sentinel
Copy of the current write sentinel (see rspq_ctx_t)
Definition rspq.c:326
uint32_t rspq_overlay_register(rsp_ucode_t *overlay_ucode)
Register a rspq overlay into the RSP queue engine.
Definition rspq.c:869
void rspq_write_end(rspq_write_t *w)
Finish enqueuing a command into the queue.
Definition rspq.h:543
volatile uint32_t * first
pointer to the first word of the command
Definition rspq.h:443
void rspq_flush(void)
Make sure that RSP starts executing up to the last written command.
Definition rspq.c:1000
uint32_t first_word
value that will be written as first word
Definition rspq.h:441
volatile uint32_t * pointer
current pointer into the RSP queue
Definition rspq.h:442
void rspq_overlay_unregister(uint32_t overlay_id)
Unregister a ucode overlay from the RSP queue engine.
Definition rspq.c:881
void * rspq_overlay_get_state(rsp_ucode_t *overlay_ucode)
Return a pointer to the overlay state (in RDRAM)
Definition rspq.c:707
void rspq_block_begin(void)
Begin creating a new block.
Definition rspq.c:1091
rspq_syncpoint_t rspq_syncpoint_new(void)
Create a syncpoint in the queue.
Definition rspq.c:1208
void rspq_highpri_sync(void)
Wait for the RSP to finish processing all high-priority queues.
Definition rspq.c:1073
#define RSPQ_MAX_COMMAND_SIZE
Maximum size of a command (in 32-bit words).
Definition rspq.h:182
rspq_write_t rspq_write_begin(uint32_t ovl_id, uint32_t cmd_id, int size)
Begin writing a new command into the RSP queue.
Definition rspq.h:479
void rspq_overlay_register_static(rsp_ucode_t *overlay_ucode, uint32_t overlay_id)
Register an overlay into the RSP queue engine assigning a static ID to it.
Definition rspq.c:874
int rspq_syncpoint_t
A syncpoint in the queue.
Definition rspq.h:222
rspq_block_t * rspq_block_end(void)
Finish creating a block.
Definition rspq.c:1110
bool is_first
true if we are waiting for the first argument word
Definition rspq.h:444
bool rspq_syncpoint_check(rspq_syncpoint_t sync_id)
Check whether a syncpoint was reached by RSP or not.
Definition rspq.c:1230
void rspq_block_free(rspq_block_t *block)
Free a block that is not needed any more.
Definition rspq.c:1130
void rspq_write_arg(rspq_write_t *w, uint32_t value)
Add one argument to the command being enqueued.
Definition rspq.h:520
void rspq_syncpoint_wait(rspq_syncpoint_t sync_id)
Wait until a syncpoint is reached by RSP.
Definition rspq.c:1236
void rspq_dma_to_dmem(uint32_t dmem_addr, void *rdram_addr, uint32_t len, bool is_async)
Enqueue a command to do a DMA transfer from RDRAM to DMEM.
Definition rspq.c:1287
void rspq_block_run(rspq_block_t *block)
Add to the RSP queue a command that runs a block.
Definition rspq.c:1166
void rspq_close(void)
Shut down the RSPQ library.
Definition rspq.c:672
void rspq_highpri_end(void)
Finish building the high-priority queue and close it.
Definition rspq.c:1057
void rspq_highpri_begin(void)
Start building a high-priority queue.
Definition rspq.c:1009
void rspq_noop(void)
Enqueue a no-op command in the queue.
Definition rspq.c:1203
void rspq_init(void)
Initialize the RSPQ library.
Definition rspq.c:586
void rspq_wait(void)
Wait until all commands in the queue have been executed by RSP.
Definition rspq.c:1256
void rspq_dma_to_rdram(void *rdram_addr, uint32_t dmem_addr, uint32_t len, bool is_async)
Enqueue a command to do a DMA transfer from DMEM to RDRAM.
Definition rspq.c:1282
A write cursor, returned by rspq_write_begin.
Definition rspq.h:440
A rspq block: pre-recorded array of commands.
Definition rspq_internal.h:162
RSP ucode definition.
Definition rsp.h:282