Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
cester-hw.c
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2022 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27// This file isn't to be compiled directly. It's to be included in every
28// sub test .c file that wants to do hardware measurements.
29
30// clang-format off
31
32#include <stdint.h>
33
35 static void hexdump(const void* data_, unsigned size) {
36 const uint8_t* data = (const uint8_t*)data_;
37 char ascii[17];
38 ascii[16] = 0;
39 for (unsigned i = 0; i < size; i++) {
40 if (i % 16 == 0) ramsyscall_printf("%08x |", i);
41 ramsyscall_printf("%02X ", data[i]);
42 ascii[i % 16] = data[i] >= ' ' && data[i] <= '~' ? data[i] : '.';
43 unsigned j = i + 1;
44 if ((j % 8 == 0) || (j == size)) {
46 if (j % 16 == 0) {
47 ramsyscall_printf("| %s \n", ascii);
48 } else if (j == size) {
49 ascii[j % 16] = 0;
50 if (j % 16 <= 8) ramsyscall_printf(" ");
51 for (j %= 16; j < 16; j++) ramsyscall_printf(" ");
52 ramsyscall_printf("| %s \n", ascii);
53 }
54 }
55 }
56 }
57
58 static int s_interruptsWereEnabled = 0;
59 static uint16_t s_oldMode = 0;
60 static uint32_t s_lastHSyncCounter = 0;
61 static uint32_t s_currentTime = 0;
62 static uint32_t s_oldIMASK = 0;
63 static const unsigned US_PER_HBLANK = 64;
64
65 struct LocPResult {
66 uint8_t track, index, m, s, f, am, as, af;
67 uint8_t padding[8];
68 };
69
70 static uint8_t btoi(uint8_t b) {
71 return (b >> 4) * 10 + (b & 0xf);
72 }
73
74 static uint8_t itob(uint8_t i) {
75 return (i / 10) * 16 + (i % 10);
76 }
77
78 static int isValidBCD(uint8_t b) {
79 return (b & 0xf) < 10 && (b >> 4) < 10;
80 }
81
82 static uint32_t MSF2LBA(uint8_t m, uint8_t s, uint8_t f) {
83 return (m * 60 + s) * 75 + f;
84 }
85
86 static uint8_t readResponse(uint8_t response[16]) {
87 uint8_t responseSize = 0;
88 while ((CDROM_REG0 & 0x20) && (responseSize < 16)) {
90 }
91 return responseSize;
92 }
93
94 static uint8_t discardResponse() {
95 uint8_t response[16];
96 return readResponse(response);
97 }
98
99 static inline void initializeTime() {
100 while (1) {
101 uint32_t init = COUNTERS[1].value;
102 uint32_t counter;
103 while ((counter = COUNTERS[1].value) == init);
104 if (counter != COUNTERS[1].value) continue;
105 s_lastHSyncCounter = counter;
106 break;
107 }
108 s_currentTime = 0;
109 }
110
111 static inline uint32_t updateTime() {
112 uint32_t lastHSyncCounter = s_lastHSyncCounter;
113 uint32_t hsyncCounter;
114 while (1) {
115 hsyncCounter = COUNTERS[1].value;
116 if (hsyncCounter != COUNTERS[1].value) continue;
117 break;
118 }
119 if (hsyncCounter < lastHSyncCounter) {
120 hsyncCounter += 0x10000;
121 }
122 uint32_t currentTime = s_currentTime = s_currentTime + (hsyncCounter - lastHSyncCounter) * US_PER_HBLANK;
123 s_lastHSyncCounter = hsyncCounter;
124 return currentTime;
125 }
126
127 static inline uint32_t waitCDRomIRQ() {
128 uint32_t time;
129 do {
130 time = updateTime();
131 } while ((IREG & IRQ_CDROM) == 0);
132 IREG &= ~IRQ_CDROM;
133 return time;
134 }
135
136 static inline int waitCDRomIRQWithTimeout(uint32_t* timeoutp) {
137 uint32_t time = updateTime();
138 uint32_t timeout = *timeoutp + time;
139 do {
140 time = updateTime();
141 } while (((IREG & IRQ_CDROM) == 0) && (time <= timeout));
142 int ret = (IREG & IRQ_CDROM) != 0;
143 *timeoutp = time;
144 IREG &= ~IRQ_CDROM;
145 return ret;
146 }
147
148 static inline uint8_t ackCDRomCause() {
149 CDROM_REG0 = 1;
150 uint8_t cause = CDROM_REG3_UC;
151 if (cause & 7) {
152 CDROM_REG0 = 1;
153 CDROM_REG3 = 7;
154 }
155 if (cause & 0x18) {
156 CDROM_REG0 = 1;
157 CDROM_REG3 = cause & 0x18;
158 }
159 return cause & 7;
160 }
161
162 int setMode(uint8_t mode) {
163 uint8_t cause;
164 CDROM_REG0 = 0;
167 waitCDRomIRQ();
170 if (cause != 3) return 0;
171 return 1;
172 }
173
174 static inline int resetCDRom() {
175 uint8_t cause;
176
177 CDROM_REG0 = 1;
178 CDROM_REG3 = 0x1f;
179 CDROM_REG0 = 1;
180 CDROM_REG2 = 0x1f;
181 CDROM_REG0 = 0;
183 waitCDRomIRQ();
186 if (cause != 3) return 0;
187 waitCDRomIRQ();
190 if (cause != 2) return 0;
191
193 // wait 10ms for things to settle
194 while (updateTime() < 10000);
195 return setMode(0);
196 }
197
198 static int setLoc(uint8_t minute, uint8_t second, uint8_t frame) {
199 uint8_t cause;
200
201 CDROM_REG0 = 0;
202 CDROM_REG2 = minute;
203 CDROM_REG2 = second;
204 CDROM_REG2 = frame;
206 waitCDRomIRQ();
209 if (cause != 3) return 0;
210
211 return 1;
212 }
213
214 static int seekPTo(uint8_t minute, uint8_t second, uint8_t frame) {
215 uint8_t cause;
216
217 CDROM_REG0 = 0;
218 CDROM_REG2 = minute;
219 CDROM_REG2 = second;
220 CDROM_REG2 = frame;
222 waitCDRomIRQ();
225 if (cause != 3) return 0;
226
227 CDROM_REG0 = 0;
229 waitCDRomIRQ();
232 if (cause != 3) return 0;
233 waitCDRomIRQ();
236 if (cause != 2) return 0;
237 return 1;
238 }
239
240 static int seekLTo(uint8_t minute, uint8_t second, uint8_t frame) {
241 uint8_t cause;
242
243 CDROM_REG0 = 0;
244 CDROM_REG2 = minute;
245 CDROM_REG2 = second;
246 CDROM_REG2 = frame;
248 waitCDRomIRQ();
251 if (cause != 3) return 0;
252
253 CDROM_REG0 = 0;
255 waitCDRomIRQ();
258 if (cause != 3) return 0;
259 waitCDRomIRQ();
262 if (cause != 2) return 0;
263
264 return 1;
265 }
266
267 uint8_t getCtrl() {
268 uint8_t cause;
269
270 CDROM_REG0 = 0;
272 waitCDRomIRQ();
274 uint8_t ctrl = CDROM_REG1;
275
276 return ctrl;
277 }
278)
279
281 s_interruptsWereEnabled = enterCriticalSection();
283 COUNTERS[1].mode = 0x0100;
284 SBUS_DEV5_CTRL = 0x20943;
288)
289
290CESTER_AFTER_ALL(cpu_tests,
292 COUNTERS[1].mode = s_oldMode;
293 if (s_interruptsWereEnabled) leaveCriticalSection();
294)
uint8_t response[16]
Definition cdlgetlocl.c:84
uint8_t responseSize
Definition cdlgetlocl.c:85
initializeTime()
waitCDRomIRQ()
CESTER_BODY(static void hexdump(const void *data_, unsigned size) { const uint8_t *data=(const uint8_t *) data_;char ascii[17];ascii[16]=0;for(unsigned i=0;i< size;i++) { if(i % 16==0) ramsyscall_printf("%08x |", i);ramsyscall_printf("%02X ", data[i]);ascii[i % 16]=data[i] >=' ' &&data[i]<='~' ? data[i] :'.';unsigned j=i+1;if((j % 8==0)||(j==size)) { ramsyscall_printf(" ");if(j % 16==0) { ramsyscall_printf("| %s \n", ascii);} else if(j==size) { ascii[j % 16]=0;if(j % 16<=8) ramsyscall_printf(" ");for(j %=16;j< 16;j++) ramsyscall_printf(" ");ramsyscall_printf("| %s \n", ascii);} } } } static int s_interruptsWereEnabled=0;static uint16_t s_oldMode=0;static uint32_t s_lastHSyncCounter=0;static uint32_t s_currentTime=0;static uint32_t s_oldIMASK=0;static const unsigned US_PER_HBLANK=64;struct LocPResult { uint8_t track, index, m, s, f, am, as, af;uint8_t padding[8];};static uint8_t btoi(uint8_t b) { return(b > > 4) *10+(b &0xf);} static uint8_t itob(uint8_t i) { return(i/10) *16+(i % 10);} static int isValidBCD(uint8_t b) { return(b &0xf)< 10 &&(b > > 4)< 10;} static uint32_t MSF2LBA(uint8_t m, uint8_t s, uint8_t f) { return(m *60+s) *75+f;} static uint8_t readResponse(uint8_t response[16]) { uint8_t responseSize=0;while((CDROM_REG0 &0x20) &&(responseSize< 16)) { response[responseSize++]=CDROM_REG1;} return responseSize;} static uint8_t discardResponse() { uint8_t response[16];return readResponse(response);} static inline void initializeTime() { while(1) { uint32_t init=COUNTERS[1].value;uint32_t counter;while((counter=COUNTERS[1].value)==init);if(counter !=COUNTERS[1].value) continue;s_lastHSyncCounter=counter;break;} s_currentTime=0;} static inline uint32_t updateTime() { uint32_t lastHSyncCounter=s_lastHSyncCounter;uint32_t hsyncCounter;while(1) { hsyncCounter=COUNTERS[1].value;if(hsyncCounter !=COUNTERS[1].value) continue;break;} if(hsyncCounter< lastHSyncCounter) { hsyncCounter+=0x10000;} uint32_t currentTime=s_currentTime=s_currentTime+(hsyncCounter - lastHSyncCounter) *US_PER_HBLANK;s_lastHSyncCounter=hsyncCounter;return currentTime;} static inline uint32_t waitCDRomIRQ() { uint32_t time;do { time=updateTime();} while((IREG &IRQ_CDROM)==0);IREG &=~IRQ_CDROM;return time;} static inline int waitCDRomIRQWithTimeout(uint32_t *timeoutp) { uint32_t time=updateTime();uint32_t timeout= *timeoutp+time;do { time=updateTime();} while(((IREG &IRQ_CDROM)==0) &&(time<=timeout));int ret=(IREG &IRQ_CDROM) !=0; *timeoutp=time;IREG &=~IRQ_CDROM;return ret;} static inline uint8_t ackCDRomCause() { CDROM_REG0=1;uint8_t cause=CDROM_REG3_UC;if(cause &7) { CDROM_REG0=1;CDROM_REG3=7;} if(cause &0x18) { CDROM_REG0=1;CDROM_REG3=cause &0x18;} return cause &7;} int setMode(uint8_t mode) { uint8_t cause;CDROM_REG0=0;CDROM_REG2=mode;CDROM_REG1=CDL_SETMODE;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;return 1;} static inline int resetCDRom() { uint8_t cause;CDROM_REG0=1;CDROM_REG3=0x1f;CDROM_REG0=1;CDROM_REG2=0x1f;CDROM_REG0=0;CDROM_REG1=CDL_INIT;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=2) return 0;initializeTime();while(updateTime()< 10000);return setMode(0);} static int setLoc(uint8_t minute, uint8_t second, uint8_t frame) { uint8_t cause;CDROM_REG0=0;CDROM_REG2=minute;CDROM_REG2=second;CDROM_REG2=frame;CDROM_REG1=CDL_SETLOC;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;return 1;} static int seekPTo(uint8_t minute, uint8_t second, uint8_t frame) { uint8_t cause;CDROM_REG0=0;CDROM_REG2=minute;CDROM_REG2=second;CDROM_REG2=frame;CDROM_REG1=CDL_SETLOC;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;CDROM_REG0=0;CDROM_REG1=CDL_SEEKP;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=2) return 0;return 1;} static int seekLTo(uint8_t minute, uint8_t second, uint8_t frame) { uint8_t cause;CDROM_REG0=0;CDROM_REG2=minute;CDROM_REG2=second;CDROM_REG2=frame;CDROM_REG1=CDL_SETLOC;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;CDROM_REG0=0;CDROM_REG1=CDL_SEEKL;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=3) return 0;waitCDRomIRQ();cause=ackCDRomCause();CDROM_REG1;if(cause !=2) return 0;return 1;} uint8_t getCtrl() { uint8_t cause;CDROM_REG0=0;CDROM_REG1=CDL_NOP;waitCDRomIRQ();ackCDRomCause();uint8_t ctrl=CDROM_REG1;return ctrl;}) CESTER_BEFORE_ALL(cpu_tests
COUNTERS[1] mode
Definition cester-hw.c:283
s_oldMode
Definition cester-hw.c:282
s_interruptsWereEnabled
Definition cester-hw.c:281
SBUS_COM_CTRL
Definition cester-hw.c:285
IMASK
Definition cester-hw.c:287
SBUS_DEV5_CTRL
Definition cester-hw.c:284
s_oldIMASK
Definition cester-hw.c:286
@ CDL_SETMODE
Definition cdrom.h:56
@ CDL_NOP
Definition cdrom.h:43
@ CDL_SEEKL
Definition cdrom.h:63
@ CDL_SEEKP
Definition cdrom.h:64
@ CDL_SETLOC
Definition cdrom.h:44
@ CDL_INIT
Definition cdrom.h:52
#define CDROM_REG3_UC
Definition cdrom.h:39
#define CDROM_REG0
Definition cdrom.h:31
#define CDROM_REG3
Definition cdrom.h:34
#define CDROM_REG1
Definition cdrom.h:32
#define CDROM_REG2
Definition cdrom.h:33
static int size
Definition string.h:142
cpu_tests
Definition cop0.c:78
#define COUNTERS
Definition counters.h:40
ramsyscall_printf("=== e01_kseg1_reads_no_fill ===\n")
uint8_t b
Definition gte-depthcue.c:39
CESTER_BEFORE_ALL(CESTER_TEST(gte_latency_tests, gte_enable();)
Definition gte-latency.c:115
int i
Definition gte-regio.c:297
#define IREG
Definition hwregs.h:46
@ IRQ_CDROM
Definition irq.h:37
m
Definition gentable.py:52
constexpr uint8_t itob(uint8_t i)
Definition msf.hh:36
constexpr uint8_t btoi(uint8_t b)
Definition msf.hh:35
uint32_t timeout
Definition race.c:103
ackCDRomCause()
uint8_t cause
Definition reading.c:707
readResponse(response)
char * s
Definition string.c:48
static int value
Definition syscalls.h:535
static int ret
Definition syscalls.h:73
void uint32_t(classId, spec)