PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
dvripl.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2021-2021, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <stdbool.h>
12#include "iomanX.h"
13#include "loadcore.h"
14#include "pvrdrv.h"
15#include "stdio.h"
16#include "thbase.h"
17#include "thsemap.h"
18#include "speedregs.h"
19#include "errno.h"
20#include "timrman.h"
21#include "sysmem.h"
22
23#define MODNAME "DVRIPL"
24#ifdef DEBUG
25#define DPRINTF(x...) printf(MODNAME ": " x)
26#else
27#define DPRINTF(x...)
28#endif
29
30extern int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
31extern int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
32extern int dvripl_df_init(iomanX_iop_device_t *dev);
33extern int dvripl_df_exit(iomanX_iop_device_t *dev);
34extern int dvripl_df_ioctl(iomanX_iop_file_t *f, int cmd, void *param);
35extern int dvripl_df_devctl(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
36extern int dvripl_df_ioctl2(iomanX_iop_file_t *f, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
37extern int iplioctl2_update(iomanX_iop_file_t *a1, int cmd, void *arg);
38extern void dvr_ready(int a1, void *a2);
39
40IOMANX_RETURN_VALUE_IMPL(EUNSUP);
41
42static iomanX_iop_device_ops_t DvrFuncTbl =
43 {
44 &dvripl_df_init, // init
45 &dvripl_df_exit, // deinit
46 IOMANX_RETURN_VALUE(EUNSUP), // format
47 IOMANX_RETURN_VALUE(EUNSUP), // open
48 IOMANX_RETURN_VALUE(EUNSUP), // close
49 IOMANX_RETURN_VALUE(EUNSUP), // read
50 IOMANX_RETURN_VALUE(EUNSUP), // write
51 IOMANX_RETURN_VALUE(EUNSUP), // lseek
52 &dvripl_df_ioctl, // ioctl
53 IOMANX_RETURN_VALUE(EUNSUP), // remove
54 IOMANX_RETURN_VALUE(EUNSUP), // mkdir
55 IOMANX_RETURN_VALUE(EUNSUP), // rmdir
56 IOMANX_RETURN_VALUE(EUNSUP), // dopen
57 IOMANX_RETURN_VALUE(EUNSUP), // dclose
58 IOMANX_RETURN_VALUE(EUNSUP), // dread
59 IOMANX_RETURN_VALUE(EUNSUP), // getstat
60 IOMANX_RETURN_VALUE(EUNSUP), // chstat
61 IOMANX_RETURN_VALUE(EUNSUP), // rename
62 IOMANX_RETURN_VALUE(EUNSUP), // chdir
63 IOMANX_RETURN_VALUE(EUNSUP), // sync
64 IOMANX_RETURN_VALUE(EUNSUP), // mount
65 IOMANX_RETURN_VALUE(EUNSUP), // umount
66 IOMANX_RETURN_VALUE_S64(EUNSUP), // lseek64
67 &dvripl_df_devctl, // devctl
68 IOMANX_RETURN_VALUE(EUNSUP), // symlink
69 IOMANX_RETURN_VALUE(EUNSUP), // readlink
70 &dvripl_df_ioctl2, // ioctl2
71 };
72s32 dvr_ready_flag;
73static iomanX_iop_device_t DVRMAN = {
74 .name = "dvr_ipl",
75 .desc = "Digital Video Recorder",
76 .ops = &DvrFuncTbl,
77 .type = (IOP_DT_FS | IOP_DT_FSEXT),
78};
79s32 sema_id;
80char SBUF[32768];
81
82// Based off of DESR / PSX DVR system software version 1.31.
83IRX_ID(MODNAME, 1, 1);
84
85int _start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
86{
87 if (argc >= 0)
88 return module_start(argc, argv, startaddr, mi);
89 else
90 return module_stop(argc, argv, startaddr, mi);
91}
92
93int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
94{
95 (void)argc;
96 (void)argv;
97 (void)startaddr;
98
99 if (iomanX_AddDrv(&DVRMAN) != 0)
100 return MODULE_NO_RESIDENT_END;
101#if 0
102 return MODULE_REMOVABLE_END;
103#else
104 if (mi && ((mi->newflags & 2) != 0))
105 mi->newflags |= 0x10;
106 return MODULE_RESIDENT_END;
107#endif
108}
109
110int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
111{
112 (void)argc;
113 (void)argv;
114 (void)startaddr;
115 (void)mi;
116
117 if (iomanX_DelDrv(DVRMAN.name) != 0)
118 return MODULE_REMOVABLE_END;
119 return MODULE_NO_RESIDENT_END;
120}
121
122int dvripl_df_init(iomanX_iop_device_t *dev)
123{
124 int v1;
125 iop_sema_t v3;
126
127 (void)dev;
128
129 DPRINTF("dvripl_df_init\n");
130 v3.attr = 0;
131 v3.initial = 1;
132 v3.max = 1;
133 v3.option = 0;
134 v1 = CreateSema(&v3);
135 if (v1 < 0)
136 return -1;
137 sema_id = v1;
138 return 0;
139}
140
141int dvripl_df_exit(iomanX_iop_device_t *dev)
142{
143 (void)dev;
144
145 DPRINTF("dvripl_df_exit\n");
146 if (DeleteSema(sema_id) != 0)
147 return -1;
148 return 0;
149}
150
151int dvripl_df_ioctl(iomanX_iop_file_t *f, int cmd, void *param)
152{
153 (void)f;
154 (void)cmd;
155 (void)param;
156
157 DPRINTF("dvripl_df_ioctl\n");
158 WaitSema(sema_id);
159 SignalSema(sema_id);
160 return -EINVAL;
161}
162
163int dvripl_df_devctl(
165 const char *name,
166 int cmd,
167 void *arg,
168 unsigned int arglen,
169 void *buf,
170 unsigned int buflen)
171{
172 int v11;
173
174 (void)name;
175 (void)arglen;
176 (void)buf;
177 (void)buflen;
178
179 DPRINTF("dvripl_df_devctl\n");
180 WaitSema(sema_id);
181 v11 = -EINVAL;
182 if (cmd == 0x5602)
183 v11 = iplioctl2_update(a1, 0x5602, arg);
184 SignalSema(sema_id);
185 return v11;
186}
187
188int dvripl_df_ioctl2(iomanX_iop_file_t *f, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
189{
190 (void)f;
191 (void)cmd;
192 (void)arg;
193 (void)arglen;
194 (void)buf;
195 (void)buflen;
196
197 DPRINTF("dvripl_df_ioctl2\n");
198 WaitSema(sema_id);
199 SignalSema(sema_id);
200 return -EINVAL;
201}
202
203int iplioctl2_update(iomanX_iop_file_t *a1, int cmd, void *arg)
204{
205 int total_size;
206 int retval;
207 int csum;
208 int cmdackerr1;
209 int cmdackerr2;
210 int cmdackerr3;
211 int update_fd;
212#if 0
213 int hard_timer;
214 u32 system_clock;
215#endif
216 int cmdackerr4;
217 drvdrv_exec_cmd_ack cmdack;
218
219 (void)a1;
220 (void)cmd;
221
222 total_size = 0;
223 retval = 0;
224 csum = 0;
225 DPRINTF("iplioctl2_update\n");
226 DPRINTF("NOP\n");
227 cmdack.command = 0x101;
228 cmdack.input_word_count = 0;
229 cmdackerr1 = DvrdrvExecCmdAck(&cmdack);
230 DPRINTF("dvrcmd.ack_p[0]:%x\n", cmdack.ack_status_ack);
231 if (cmdackerr1)
232 goto LABEL_2;
233 if (cmdack.ack_status_ack) {
234 DPRINTF("NOP -> Status error!\n");
235 return -EIO;
236 }
237 DPRINTF("VERSION\n");
238 cmdack.command = 0x102;
239 cmdack.input_word_count = 0;
240 cmdackerr2 = DvrdrvExecCmdAck(&cmdack);
241 DPRINTF("dvrcmd.ack_p[0]:%x\n", cmdack.ack_status_ack);
242 if (cmdackerr2) {
243 LABEL_2:
244 DPRINTF("NOP -> Handshake error!\n");
245 return -EIO;
246 }
247 if (cmdack.ack_status_ack) {
248 DPRINTF("NOP -> Status error!\n");
249 return -EIO;
250 }
251 DPRINTF("major : %04x\n", cmdack.output_word[0]);
252 DPRINTF("minor : %04x\n", cmdack.output_word[1]);
253 DPRINTF("CONFIG\n");
254 cmdack.command = 0x106;
255 cmdack.input_word[0] = 1;
256 cmdack.input_word[1] = 6;
257 cmdack.input_word[2] = 0x1000;
258 cmdack.input_word[3] = 0x8968;
259 cmdack.input_word[4] = 0x115A;
260 cmdack.input_word[5] = 0x6048;
261 cmdack.input_word[6] = 0xF;
262 cmdack.input_word[7] = 0x5353;
263 cmdack.input_word_count = 8;
264 cmdackerr3 = DvrdrvExecCmdAck(&cmdack);
265 DPRINTF("dvrcmd.ack_p[0]:%x\n", cmdack.ack_status_ack);
266 if (cmdackerr3) {
267 DPRINTF("CONFIG -> Handshake error!(%d)\n", cmdackerr3);
268 return -EIO;
269 }
270 if (cmdack.ack_status_ack) {
271 DPRINTF("CONFIG -> Status error!\n");
272 return -EIO;
273 }
274 update_fd = iomanX_open((const char *)arg, 1, 0x124);
275 if (update_fd >= 0) {
276 int chunk_offset;
277 chunk_offset = 0x10000000;
278 DPRINTF("Opened \"%s\"\n", (const char *)arg);
279 DPRINTF("Downloading \"%s\"\n", (const char *)arg);
280#if 0
281 hard_timer = AllocHardTimer(1, 32, 1);
282 SetupHardTimer(hard_timer, 1, 0, 1);
283 StartHardTimer(hard_timer);
284#endif
285 while (1) {
286 int read_buf_offs;
287 int *read_buf;
288 s32 chunk_size;
289 int read_size;
290 DPRINTF("%08X\n", chunk_offset);
291 read_size = iomanX_read(update_fd, SBUF, 0x8000);
292 chunk_size = read_size;
293 if (read_size < 0) {
294 retval = -EIO;
295 DPRINTF("Cannot read \"%s\"\n", (const char *)arg);
296 goto LABEL_30;
297 }
298 read_buf = (int *)SBUF;
299 if (!read_size)
300 break;
301 read_buf_offs = 0;
302 while (read_buf_offs++ < chunk_size / 4) {
303 unsigned int read_buf_tmp;
304 read_buf_tmp = *read_buf++;
305 csum += (read_buf_tmp << 24) + ((read_buf_tmp & 0xFF00) << 8) + ((read_buf_tmp & 0xFF0000) >> 8) + ((read_buf_tmp & 0xff000000) >> 24);
306 }
307 cmdack.command = 0x103;
308 cmdack.input_word[0] = chunk_offset >> 16;
309 cmdack.input_word[1] = chunk_offset;
310 cmdack.input_word_count = 2;
311 cmdack.input_buffer = SBUF;
312 cmdack.input_buffer_length = chunk_size;
313 if (DvrdrvExecCmdAckDmaSendComp(&cmdack)) {
314 retval = -EIO;
315 DPRINTF("Handshake error! (phase:%d)\n", cmdack.phase);
316 goto LABEL_30;
317 }
318 chunk_offset += chunk_size;
319 if (cmdack.ack_status_ack)
320 goto LABEL_29;
321 total_size += chunk_size;
322 }
323#if 0
324 system_clock = GetTimerCounter(hard_timer);
325 DPRINTF("System Clock : %ld\n", system_clock);
326 StopHardTimer(hard_timer);
327 FreeHardTimer(hard_timer);
328#endif
329 DPRINTF("CHECK SUM\n");
330 DPRINTF("total_size:%d\n", total_size);
331 DPRINTF("csum : %x\n", csum);
332 cmdack.command = 0x105;
333 cmdack.input_word[0] = 0x1000;
334 cmdack.input_word[2] = total_size >> 16;
335 cmdack.input_word[4] = csum >> 16;
336 cmdack.input_word[1] = 0;
337 cmdack.input_word[3] = total_size;
338 cmdack.input_word[5] = csum;
339 cmdack.input_word_count = 6;
340 cmdackerr4 = DvrdrvExecCmdAck(&cmdack);
341 DPRINTF("result: %d\n", cmdackerr4);
342 DPRINTF("dvrcmd.ack_p[0]:%x\n", cmdack.ack_status_ack);
343 DPRINTF("dvrcmd.ack_p[1]:%x\n", cmdack.output_word[0]);
344 DPRINTF("dvrcmd.ack_p[2]:%x\n", cmdack.output_word[1]);
345 if (cmdackerr4) {
346 retval = -EIO;
347 goto LABEL_30;
348 }
349 if (cmdack.ack_status_ack)
350 LABEL_29:
351 retval = -EIO;
352 } else {
353 retval = -ENMFILE;
354 }
355LABEL_30:
356 iomanX_close(update_fd);
357 DvrdrvUnregisterIntrHandler(dvr_ready);
358 DPRINTF("done.\n");
359 return retval;
360}
361
362void dvr_ready(int a1, void *a2)
363{
364 (void)a1;
365
366 Kprintf("DVRRDY INTERRUPT\n");
367 dvr_ready_flag = 1;
368 iWakeupThread(*(u32 *)a2);
369}
#define EINVAL
Definition errno.h:63
#define EUNSUP
Definition errno.h:117
#define ENMFILE
Definition errno.h:187
#define EIO
Definition errno.h:29
#define IOP_DT_FSEXT
Definition iomanX.h:66
u16 newflags
Definition loadcore.h:36