Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
Macros | Functions | Variables
gpu-dma-ring.c File Reference
#include <stdint.h>
#include "common/hardware/hwregs.h"
#include "common/syscalls/syscalls.h"
#include "texture-fixtures.h"
#include "exotic/cester.h"
Include dependency graph for gpu-dma-ring.c:

Macros

#define PCSX_TESTS   0
 
#define CESTER_MAYBE_TEST   CESTER_TEST
 
#define CESTER_NO_SIGNAL
 
#define CESTER_NO_TIME
 
#define EXIT_SUCCESS   0
 
#define EXIT_FAILURE   1
 
#define R32(a)   (*(volatile uint32_t *)(a))
 
#define D2_MADR   R32(0xbf8010a0)
 
#define D2_BCR   R32(0xbf8010a4)
 
#define D2_CHCR   R32(0xbf8010a8)
 
#define D_DPCR   R32(0xbf8010f0)
 
#define D_DICR   R32(0xbf8010f4)
 
#define RING   16
 
#define SLOT_WORDS   16
 
#define VBLANKS   10
 
#define EXIT_LIMIT   2000000
 
#define QUAD_WORDS   12
 
#define QUAD_TPAGE   (TEX15_TX | (2u << 7))
 

Functions

 CESTER_BODY (#define R32(a) #define D2_MADR #define D2_BCR #define D2_CHCR #define D_DPCR #define D_DICR #define RING #define SLOT_WORDS #define VBLANKS #define EXIT_LIMIT static uint32_t s_ring[RING *SLOT_WORDS] __attribute__((aligned(64)));struct Arm { uint32_t madr[VBLANKS+1];uint32_t chcr[VBLANKS+1];uint32_t dicr[VBLANKS+1];uint16_t written[VBLANKS+1];uint16_t laps[VBLANKS+1];uint32_t exitPolls;uint32_t exitChcr, exitMadr, exitDicr, exitIstat;};static struct Arm s_high, s_mid;static int s_interruptsWereEnabled;static uint32_t slotAddr(unsigned k) { return(uint32_t)&s_ring[k *SLOT_WORDS] &0xffffff;} #define QUAD_WORDS #define QUAD_TPAGE static void writeQuad(unsigned k, uint32_t seq) { uint32_t *p=&s_ring[k *SLOT_WORDS+1];uint32_t c=(seq *0x0f0b07u) &0x007f7f7fu;p[0]=0x3e000000|c;p[1]=0;p[2]=0;p[3]=c ^ 0x003f003f;p[4]=319;p[5]=(QUAD_TPAGE<< 16)|63;p[6]=c ^ 0x00003f3f;p[7]=239<< 16;p[8]=15<< 8;p[9]=c ^ 0x003f3f00;p[10]=(239<< 16)|319;p[11]=(15<< 8)|63;} static void buildRing(void) { for(unsigned k=0;k< RING;k++) { s_ring[k *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|slotAddr((k+1) % RING);writeQuad(k, k);} } static int slotOf(uint32_t madr) { uint32_t base=slotAddr(0);madr &=0xffffff;if(madr< base) return -1;uint32_t off=(madr - base)/(SLOT_WORDS *4);return off< RING ?(int) off :-1;} static void setupGpu(void) { GPU_STATUS=0x00000000;GPU_STATUS=0x06000000|0x260|(0xc60<< 12);GPU_STATUS=0x07000000|0x010|(0x100<< 10);GPU_STATUS=0x05000000;GPU_STATUS=0x08000001;GPU_DATA=0xe1000600;GPU_DATA=0xe3000000;GPU_DATA=0xe4000000|319|(239<< 10);GPU_DATA=0xe5000000;GPU_STATUS=0x03000000;GPU_STATUS=0x04000002;} static void run(struct Arm *a, unsigned trail, const char *name) { setupGpu();uploadTex15Masked();waitGPU();buildRing();D_DPCR|=0x00000800;D_DICR=0x00840000|0x7f000000;IREG=~0x8u;D2_MADR=slotAddr(0);D2_BCR=0;D2_CHCR=0x01000401;unsigned prod=(RING - trail) % RING;int last=0;uint32_t seq=RING;unsigned written=0, laps=0;a->madr[0]=D2_MADR;a->chcr[0]=D2_CHCR;a->dicr[0]=D_DICR;a->written[0]=0;a->laps[0]=0;for(int v=1;v<=VBLANKS;v++) { IREG=~1u;while(!(IREG &1)) { int d=slotOf(D2_MADR);if(d< 0) continue;if(d< last) laps++;last=d;unsigned target=(d+RING - trail) % RING;while(prod !=target) { writeQuad(prod, seq++);prod=(prod+1) % RING;written++;} } a->madr[v]=D2_MADR;a->chcr[v]=D2_CHCR;a->dicr[v]=D_DICR;a->written[v]=written;a->laps[v]=laps;written=0;laps=0;} int d=slotOf(D2_MADR);unsigned e=((d< 0 ? 0 :d)+RING/2) % RING;s_ring[e *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|0xffffff;uint32_t polls=0;while((D2_CHCR &0x01000000) &&polls< EXIT_LIMIT) polls++;a->exitPolls=polls;a->exitChcr=D2_CHCR;a->exitMadr=D2_MADR;a->exitDicr=D_DICR;a->exitIstat=IREG;if(a->exitChcr &0x01000000) D2_CHCR=0x00000401;for(int v=0;v<=VBLANKS;v++) { ramsyscall_printf("%s v=%d madr=%08x slot=%d chcr=%08x dicr=%08x written=%d laps=%d\n", name, v, a->madr[v], slotOf(a->madr[v]), a->chcr[v], a->dicr[v], a->written[v], a->laps[v]);} ramsyscall_printf("%s exit polls=%d chcr=%08x madr=%08x dicr=%08x istat=%08x\n", name, a->exitPolls, a->exitChcr, a->exitMadr, a->exitDicr, a->exitIstat);} static int allBusy(const struct Arm *a) { for(int v=0;v<=VBLANKS;v++) if(!(a->chcr[v] &0x01000000)) return 0;return 1;} static unsigned minWritten(const struct Arm *a) { unsigned m=0xffff;for(int v=2;v<=VBLANKS;v++) if(a->written[v]< m) m=a->written[v];return m;} static unsigned totalLaps(const struct Arm *a) { unsigned n=0;for(int v=1;v<=VBLANKS;v++) n+=a->laps[v];return n;}) CESTER_BEFORE_ALL(gpudmaring
 
 CESTER_AFTER_ALL (CESTER_MAYBE_TEST(gpudmaring, D2_CHCR=0x00000401;GPU_STATUS=0x00000000;if(s_interruptsWereEnabled) leaveCriticalSection();)
 

Variables

 s_interruptsWereEnabled = enterCriticalSection()
 
 IMASK = 0
 
run & s_high
 
run & s_mid
 

Macro Definition Documentation

◆ CESTER_MAYBE_TEST

#define CESTER_MAYBE_TEST   CESTER_TEST

◆ CESTER_NO_SIGNAL

#define CESTER_NO_SIGNAL

◆ CESTER_NO_TIME

#define CESTER_NO_TIME

◆ D2_BCR

#define D2_BCR   R32(0xbf8010a4)

◆ D2_CHCR

#define D2_CHCR   R32(0xbf8010a8)

◆ D2_MADR

#define D2_MADR   R32(0xbf8010a0)

◆ D_DICR

#define D_DICR   R32(0xbf8010f4)

◆ D_DPCR

#define D_DPCR   R32(0xbf8010f0)

◆ EXIT_FAILURE

#define EXIT_FAILURE   1

◆ EXIT_LIMIT

#define EXIT_LIMIT   2000000

◆ EXIT_SUCCESS

#define EXIT_SUCCESS   0

◆ PCSX_TESTS

#define PCSX_TESTS   0

◆ QUAD_TPAGE

#define QUAD_TPAGE   (TEX15_TX | (2u << 7))

◆ QUAD_WORDS

#define QUAD_WORDS   12

◆ R32

#define R32 (   a)    (*(volatile uint32_t *)(a))

◆ RING

#define RING   16

◆ SLOT_WORDS

#define SLOT_WORDS   16

◆ VBLANKS

#define VBLANKS   10

Function Documentation

◆ CESTER_AFTER_ALL()

CESTER_AFTER_ALL ( CESTER_MAYBE_TEST(  gpudmaring,
D2_CHCR  = 0x00000401; GPU_STATUS = 0x00000000; if (s_interruptsWereEnabled) leaveCriticalSection(); 
)

◆ CESTER_BODY()

CESTER_BODY ( #define R32(a) #define D2_MADR #define D2_BCR #define D2_CHCR #define D_DPCR #define D_DICR #define RING #define SLOT_WORDS #define VBLANKS #define EXIT_LIMIT static uint32_t s_ring __attribute__((aligned(64)));struct Arm { uint32_t madr[VBLANKS+1];uint32_t chcr[VBLANKS+1];uint32_t dicr[VBLANKS+1];uint16_t written[VBLANKS+1];uint16_t laps[VBLANKS+1];uint32_t exitPolls;uint32_t exitChcr, exitMadr, exitDicr, exitIstat;};static struct Arm  s_high[RING *SLOT_WORDS],
s_mid;static int s_interruptsWereEnabled;static uint32_t slotAddr(unsigned k) { return(uint32_t)&s_ring[k *SLOT_WORDS] &0xffffff;} #define QUAD_WORDS #define QUAD_TPAGE static void writeQuad(unsigned k, uint32_t seq) { uint32_t *p=&s_ring[k *SLOT_WORDS+1];uint32_t c=(seq *0x0f0b07u) &0x007f7f7fu;p[0]=0x3e000000|c;p[1]=0;p[2]=0;p[3]=c ^ 0x003f003f;p[4]=319;p[5]=(QUAD_TPAGE<< 16)|63;p[6]=c ^ 0x00003f3f;p[7]=239<< 16;p[8]=15<< 8;p[9]=c ^ 0x003f3f00;p[10]=(239<< 16)|319;p[11]=(15<< 8)|63;} static void buildRing(void) { for(unsigned k=0;k< RING;k++) { s_ring[k *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|slotAddr((k+1) % RING);writeQuad(k, k);} } static int slotOf(uint32_t madr) { uint32_t base=slotAddr(0);madr &=0xffffff;if(madr< base) return -1;uint32_t off=(madr - base)/(SLOT_WORDS *4);return off< RING ?(int) off :-1;} static void setupGpu(void) { GPU_STATUS=0x00000000;GPU_STATUS=0x06000000|0x260|(0xc60<< 12);GPU_STATUS=0x07000000|0x010|(0x100<< 10);GPU_STATUS=0x05000000;GPU_STATUS=0x08000001;GPU_DATA=0xe1000600;GPU_DATA=0xe3000000;GPU_DATA=0xe4000000|319|(239<< 10);GPU_DATA=0xe5000000;GPU_STATUS=0x03000000;GPU_STATUS=0x04000002;} static void run(struct Arm *a, unsigned trail, const char *name) { setupGpu();uploadTex15Masked();waitGPU();buildRing();D_DPCR|=0x00000800;D_DICR=0x00840000|0x7f000000;IREG=~0x8u;D2_MADR=slotAddr(0);D2_BCR=0;D2_CHCR=0x01000401;unsigned prod=(RING - trail) % RING;int last=0;uint32_t seq=RING;unsigned written=0, laps=0;a->madr[0]=D2_MADR;a->chcr[0]=D2_CHCR;a->dicr[0]=D_DICR;a->written[0]=0;a->laps[0]=0;for(int v=1;v<=VBLANKS;v++) { IREG=~1u;while(!(IREG &1)) { int d=slotOf(D2_MADR);if(d< 0) continue;if(d< last) laps++;last=d;unsigned target=(d+RING - trail) % RING;while(prod !=target) { writeQuad(prod, seq++);prod=(prod+1) % RING;written++;} } a->madr[v]=D2_MADR;a->chcr[v]=D2_CHCR;a->dicr[v]=D_DICR;a->written[v]=written;a->laps[v]=laps;written=0;laps=0;} int d=slotOf(D2_MADR);unsigned e=((d< 0 ? 0 :d)+RING/2) % RING;s_ring[e *SLOT_WORDS]=((uint32_t) QUAD_WORDS<< 24)|0xffffff;uint32_t polls=0;while((D2_CHCR &0x01000000) &&polls< EXIT_LIMIT) polls++;a->exitPolls=polls;a->exitChcr=D2_CHCR;a->exitMadr=D2_MADR;a->exitDicr=D_DICR;a->exitIstat=IREG;if(a->exitChcr &0x01000000) D2_CHCR=0x00000401;for(int v=0;v<=VBLANKS;v++) { ramsyscall_printf("%s v=%d madr=%08x slot=%d chcr=%08x dicr=%08x written=%d laps=%d\n", name, v, a->madr[v], slotOf(a->madr[v]), a->chcr[v], a->dicr[v], a->written[v], a->laps[v]);} ramsyscall_printf("%s exit polls=%d chcr=%08x madr=%08x dicr=%08x istat=%08x\n", name, a->exitPolls, a->exitChcr, a->exitMadr, a->exitDicr, a->exitIstat);} static int allBusy(const struct Arm *a) { for(int v=0;v<=VBLANKS;v++) if(!(a->chcr[v] &0x01000000)) return 0;return 1;} static unsigned minWritten(const struct Arm *a) { unsigned m=0xffff;for(int v=2;v<=VBLANKS;v++) if(a->written[v]< m) m=a->written[v];return m;} static unsigned totalLaps(const struct Arm *a) { unsigned n=0;for(int v=1;v<=VBLANKS;v++) n+=a->laps[v];return n;}   
)

Variable Documentation

◆ IMASK

IMASK = 0

◆ s_high

run& s_high

◆ s_interruptsWereEnabled

s_interruptsWereEnabled = enterCriticalSection()

◆ s_mid

run& s_mid