libdragon
rspq.h
Go to the documentation of this file.
1
142#ifndef __LIBDRAGON_RSPQ_H
143#define __LIBDRAGON_RSPQ_H
144
145#include <stdint.h>
146#include <rsp.h>
147#include <pputils.h>
148
149#ifdef __cplusplus
150extern "C" {
151#endif
152
154#define RSPQ_MAX_COMMAND_SIZE 63
155
161#define RSPQ_MAX_SHORT_COMMAND_SIZE 16
162
174typedef struct rspq_block_s rspq_block_t;
175
195
206void rspq_init(void);
207
213void rspq_close(void);
214
215
248uint32_t rspq_overlay_register(rsp_ucode_t *overlay_ucode);
249
266void rspq_overlay_register_static(rsp_ucode_t *overlay_ucode, uint32_t overlay_id);
267
283void rspq_overlay_unregister(uint32_t overlay_id);
284
300void* rspq_overlay_get_state(rsp_ucode_t *overlay_ucode);
301
366#define rspq_write(ovl_id, cmd_id, ...) \
367 __PPCAT(_rspq_write, __HAS_VARARGS(__VA_ARGS__)) (ovl_id, cmd_id, ##__VA_ARGS__)
368
370
371// Helpers used to implement rspq_write
372#define _rspq_write_prolog() \
373 extern volatile uint32_t *rspq_cur_pointer, *rspq_cur_sentinel; \
374 extern void rspq_next_buffer(void); \
375 volatile uint32_t *ptr = rspq_cur_pointer+1; \
376 (void)ptr;
377
378#define _rspq_write_epilog() ({ \
379 if (__builtin_expect(rspq_cur_pointer > rspq_cur_sentinel, 0)) \
380 rspq_next_buffer(); \
381})
382
383#define _rspq_write_arg(arg) \
384 *ptr++ = (arg);
385
386#define _rspq_write0(ovl_id, cmd_id) ({ \
387 _rspq_write_prolog(); \
388 rspq_cur_pointer[0] = (ovl_id) + ((cmd_id)<<24); \
389 rspq_cur_pointer += 1; \
390 _rspq_write_epilog(); \
391})
392
393#define _rspq_write1(ovl_id, cmd_id, arg0, ...) ({ \
394 _Static_assert(__COUNT_VARARGS(__VA_ARGS__) < RSPQ_MAX_SHORT_COMMAND_SIZE); \
395 _rspq_write_prolog(); \
396 __CALL_FOREACH(_rspq_write_arg, ##__VA_ARGS__); \
397 rspq_cur_pointer[0] = ((ovl_id) + ((cmd_id)<<24)) | (arg0); \
398 rspq_cur_pointer += 1 + __COUNT_VARARGS(__VA_ARGS__); \
399 _rspq_write_epilog(); \
400})
401
403
405typedef struct {
406 uint32_t first_word;
407 volatile uint32_t *pointer;
408 volatile uint32_t *first;
409 bool is_first;
411
444inline rspq_write_t rspq_write_begin(uint32_t ovl_id, uint32_t cmd_id, int size) {
445 extern volatile uint32_t *rspq_cur_pointer, *rspq_cur_sentinel;
446 extern void rspq_next_buffer(void);
447
448 if (__builtin_expect(rspq_cur_pointer > rspq_cur_sentinel - size, 0))
450
451 volatile uint32_t *cur = rspq_cur_pointer;
452 rspq_cur_pointer += size;
453
454 return (rspq_write_t){
455 .first_word = ovl_id + (cmd_id<<24),
456 .pointer = cur + 1,
457 .first = cur,
458 .is_first = 1
459 };
460}
461
483inline void rspq_write_arg(rspq_write_t *w, uint32_t value) {
484 if (w->is_first) {
485 w->first_word |= value;
486 w->is_first = 0;
487 } else {
488 *w->pointer++ = value;
489 }
490}
491
507 *w->first = w->first_word;
508 w->first = 0;
509 w->pointer = 0;
510}
511
568void rspq_flush(void);
569
582#define rspq_wait() ({ \
583 rspq_syncpoint_wait(rspq_syncpoint_new()); \
584})
585
606
621
634
635
653void rspq_block_begin(void);
654
671
689void rspq_block_run(rspq_block_t *block);
690
703void rspq_block_free(rspq_block_t *block);
704
741void rspq_highpri_begin(void);
742
753void rspq_highpri_end(void);
754
763void rspq_highpri_sync(void);
764
771void rspq_noop(void);
772
793void rspq_signal(uint32_t signal);
794
810void rspq_dma_to_rdram(void *rdram_addr, uint32_t dmem_addr, uint32_t len, bool is_async);
811
827void rspq_dma_to_dmem(uint32_t dmem_addr, void *rdram_addr, uint32_t len, bool is_async);
828
829#ifdef __cplusplus
830}
831#endif
832
833#endif
Low-level RSP hardware library.
void rspq_next_buffer(void)
Switch to the next write buffer for the current RSP queue.
Definition: rspq.c:992
volatile uint32_t * rspq_cur_pointer
Copy of the current write pointer (see rspq_ctx_t)
Definition: rspq.c:434
volatile uint32_t * rspq_cur_sentinel
Copy of the current write sentinel (see rspq_ctx_t)
Definition: rspq.c:435
A pre-built block of commands.
Definition: rspq.c:337
uint32_t rspq_overlay_register(rsp_ucode_t *overlay_ucode)
Register a rspq overlay into the RSP queue engine.
Definition: rspq.c:932
void rspq_write_end(rspq_write_t *w)
Finish enqueuing a command into the queue.
Definition: rspq.h:506
volatile uint32_t * first
pointer to the first word of the command
Definition: rspq.h:408
void rspq_flush(void)
Make sure that RSP starts executing up to the last written command.
Definition: rspq.c:1066
uint32_t first_word
value that will be written as first word
Definition: rspq.h:406
volatile uint32_t * pointer
current pointer into the RSP queue
Definition: rspq.h:407
void rspq_overlay_unregister(uint32_t overlay_id)
Unregister a ucode overlay from the RSP queue engine.
Definition: rspq.c:944
void * rspq_overlay_get_state(rsp_ucode_t *overlay_ucode)
Return a pointer to the overlay state (in RDRAM)
Definition: rspq.c:753
void rspq_block_begin(void)
Begin creating a new block.
Definition: rspq.c:1143
rspq_syncpoint_t rspq_syncpoint_new(void)
Create a syncpoint in the queue.
Definition: rspq.c:1238
void rspq_highpri_sync(void)
Wait for the RSP to finish processing all high-priority queues.
Definition: rspq.c:1133
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:444
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:937
int rspq_syncpoint_t
A syncpoint in the queue.
Definition: rspq.h:194
rspq_block_t * rspq_block_end(void)
Finish creating a block.
Definition: rspq.c:1159
bool is_first
true if we are waiting for the first argument word
Definition: rspq.h:409
bool rspq_syncpoint_check(rspq_syncpoint_t sync_id)
Check whether a syncpoint was reached by RSP or not.
Definition: rspq.c:1248
void rspq_block_free(rspq_block_t *block)
Free a block that is not needed any more.
Definition: rspq.c:1176
void rspq_write_arg(rspq_write_t *w, uint32_t value)
Add one argument to the command being enqueued.
Definition: rspq.h:483
void rspq_syncpoint_wait(rspq_syncpoint_t sync_id)
Wait until a syncpoint is reached by RSP.
Definition: rspq.c:1254
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:1292
void rspq_block_run(rspq_block_t *block)
Add to the RSP queue a command that runs a block.
Definition: rspq.c:1209
void rspq_close(void)
Shut down the RSPQ library.
Definition: rspq.c:740
void rspq_signal(uint32_t signal)
Enqueue a command that sets a signal in SP status.
Definition: rspq.c:1274
void rspq_highpri_end(void)
Finish building the high-priority queue and close it.
Definition: rspq.c:1117
void rspq_highpri_begin(void)
Start building a high-priority queue.
Definition: rspq.c:1074
void rspq_noop(void)
Enqueue a no-op command in the queue.
Definition: rspq.c:1233
void rspq_init(void)
Initialize the RSPQ library.
Definition: rspq.c:675
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:1287
A write cursor, returned by rspq_write_begin.
Definition: rspq.h:405
RSP ucode definition.
Definition: rsp.h:270