catch up with upsteam
[libogc.git] / libogc / dvd.c
blobb50ee4be7c5192952ad774ae990c1c72fd46d841
1 /*-------------------------------------------------------------
3 dvd.h -- DVD subsystem
5 Copyright (C) 2004
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 Additionally following copyrights apply for the patching system:
10 * Copyright (C) 2005 The GameCube Linux Team
11 * Copyright (C) 2005 Albert Herranz
13 Thanks alot guys for that incredible patch!!
15 This software is provided 'as-is', without any express or implied
16 warranty. In no event will the authors be held liable for any
17 damages arising from the use of this software.
19 Permission is granted to anyone to use this software for any
20 purpose, including commercial applications, and to alter it and
21 redistribute it freely, subject to the following restrictions:
23 1. The origin of this software must not be misrepresented; you
24 must not claim that you wrote the original software. If you use
25 this software in a product, an acknowledgment in the product
26 documentation would be appreciated but is not required.
28 2. Altered source versions must be plainly marked as such, and
29 must not be misrepresented as being the original software.
31 3. This notice may not be removed or altered from any source
32 distribution.
35 -------------------------------------------------------------*/
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include "asm.h"
41 #include "processor.h"
42 #include "cache.h"
43 #include "lwp.h"
44 #include "irq.h"
45 #include "ogcsys.h"
46 #include "system.h"
47 #include "dvd.h"
49 //#define _DVD_DEBUG
51 #define DVD_BRK (1<<0)
52 #define DVD_DE_MSK (1<<1)
53 #define DVD_DE_INT (1<<2)
54 #define DVD_TC_MSK (1<<3)
55 #define DVD_TC_INT (1<<4)
56 #define DVD_BRK_MSK (1<<5)
57 #define DVD_BRK_INT (1<<6)
59 #define DVD_CVR_INT (1<<2)
60 #define DVD_CVR_MSK (1<<1)
61 #define DVD_CVR_STATE (1<<0)
63 #define DVD_DI_MODE (1<<2)
64 #define DVD_DI_DMA (1<<1)
65 #define DVD_DI_START (1<<0)
67 #define DVD_DISKIDSIZE 0x20
68 #define DVD_DRVINFSIZE 0x20
69 #define DVD_MAXCOMMANDS 0x12
71 #define DVD_DVDINQUIRY 0x12000000
72 #define DVD_FWSETOFFSET 0x32000000
73 #define DVD_FWENABLEEXT 0x55000000
74 #define DVD_READSECTOR 0xA8000000
75 #define DVD_READDISKID 0xA8000040
76 #define DVD_SEEKSECTOR 0xAB000000
77 #define DVD_REQUESTERROR 0xE0000000
78 #define DVD_AUDIOSTREAM 0xE1000000
79 #define DVD_AUDIOSTATUS 0xE2000000
80 #define DVD_STOPMOTOR 0xE3000000
81 #define DVD_AUDIOCONFIG 0xE4000000
82 #define DVD_FWSETSTATUS 0xEE000000
83 #define DVD_FWWRITEMEM 0xFE010100
84 #define DVD_FWREADMEM 0xFE010000
85 #define DVD_FWCTRLMOTOR 0xFE110000
86 #define DVD_FWFUNCCALL 0xFE120000
88 #define DVD_MODEL04 0x20020402
89 #define DVD_MODEL06 0x20010608
90 #define DVD_MODEL08 0x20020823
91 #define DVD_MODEL08Q 0x20010831
93 #define DVD_FWIRQVECTOR 0x00804c
95 #define DVD_DRIVERESET 0x00000001
96 #define DVD_CHIPPRESENT 0x00000002
97 #define DVD_INTEROPER 0x00000004
99 /* drive status, status */
100 #define DVD_STATUS(s) ((u8)((s)>>24))
102 #define DVD_STATUS_READY 0x00
103 #define DVD_STATUS_COVER_OPENED 0x01
104 #define DVD_STATUS_DISK_CHANGE 0x02
105 #define DVD_STATUS_NO_DISK 0x03
106 #define DVD_STATUS_MOTOR_STOP 0x04
107 #define DVD_STATUS_DISK_ID_NOT_READ 0x05
109 /* drive status, error */
110 #define DVD_ERROR(s) ((u32)((s)&0x00ffffff))
112 #define DVD_ERROR_NO_ERROR 0x000000
113 #define DVD_ERROR_MOTOR_STOPPED 0x020400
114 #define DVD_ERROR_DISK_ID_NOT_READ 0x020401
115 #define DVD_ERROR_MEDIUM_NOT_PRESENT 0x023a00
116 #define DVD_ERROR_SEEK_INCOMPLETE 0x030200
117 #define DVD_ERROR_UNRECOVERABLE_READ 0x031100
118 #define DVD_ERROR_TRANSFER_PROTOCOL 0x040800
119 #define DVD_ERROR_INVALID_COMMAND 0x052000
120 #define DVD_ERROR_AUDIOBUFFER_NOTSET 0x052001
121 #define DVD_ERROR_BLOCK_OUT_OF_RANGE 0x052100
122 #define DVD_ERROR_INVALID_FIELD 0x052400
123 #define DVD_ERROR_INVALID_AUDIO_CMD 0x052401
124 #define DVD_ERROR_INVALID_CONF_PERIOD 0x052402
125 #define DVD_ERROR_END_OF_USER_AREA 0x056300
126 #define DVD_ERROR_MEDIUM_CHANGED 0x062800
127 #define DVD_ERROR_MEDIUM_CHANGE_REQ 0x0B5A01
129 #define DVD_SPINMOTOR_MASK 0x0000ff00
131 #define cpu_to_le32(x) (((x>>24)&0x000000ff) | ((x>>8)&0x0000ff00) | ((x<<8)&0x00ff0000) | ((x<<24)&0xff000000))
132 #define dvd_may_retry(s) (DVD_STATUS(s) == DVD_STATUS_READY || DVD_STATUS(s) == DVD_STATUS_DISK_ID_NOT_READ)
134 #define _SHIFTL(v, s, w) \
135 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
136 #define _SHIFTR(v, s, w) \
137 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
139 typedef void (*dvdcallbacklow)(s32);
140 typedef void (*dvdstatecb)(dvdcmdblk *);
142 typedef struct _dvdcmdl {
143 s32 cmd;
144 void *buf;
145 u32 len;
146 s64 offset;
147 dvdcallbacklow cb;
148 } dvdcmdl;
150 typedef struct _dvdcmds {
151 void *buf;
152 u32 len;
153 s64 offset;
154 } dvdcmds;
156 static u32 __dvd_initflag = 0;
157 static u32 __dvd_stopnextint = 0;
158 static vu32 __dvd_resetoccured = 0;
159 static u32 __dvd_waitcoverclose = 0;
160 static u32 __dvd_breaking = 0;
161 static vu32 __dvd_resetrequired = 0;
162 static u32 __dvd_canceling = 0;
163 static u32 __dvd_pauseflag = 0;
164 static u32 __dvd_pausingflag = 0;
165 static u64 __dvd_lastresetend = 0;
166 static u32 __dvd_ready = 0;
167 static u32 __dvd_resumefromhere = 0;
168 static u32 __dvd_fatalerror = 0;
169 static u32 __dvd_lasterror = 0;
170 static u32 __dvd_internalretries = 0;
171 static u32 __dvd_autofinishing = 0;
172 static u32 __dvd_autoinvalidation = 1;
173 static u32 __dvd_cancellasterror = 0;
174 static u32 __dvd_drivechecked = 0;
175 static u32 __dvd_drivestate = 0;
176 static u32 __dvd_extensionsenabled = TRUE;
177 static u32 __dvd_lastlen;
178 static u32 __dvd_nextcmdnum;
179 static u32 __dvd_workaround;
180 static u32 __dvd_workaroundseek;
181 static u32 __dvd_lastcmdwasread;
182 static u32 __dvd_currcmd;
183 static u32 __dvd_motorcntrl;
184 static lwpq_t __dvd_wait_queue;
185 static syswd_t __dvd_timeoutalarm;
186 static dvdcmdblk __dvd_block$15;
187 static dvdcmdblk __dvd_dummycmdblk;
188 static dvddiskid __dvd_tmpid0 ATTRIBUTE_ALIGN(32);
189 static dvddrvinfo __dvd_driveinfo ATTRIBUTE_ALIGN(32);
190 static dvdcallbacklow __dvd_callback = NULL;
191 static dvdcallbacklow __dvd_resetcovercb = NULL;
192 static dvdcallbacklow __dvd_finalunlockcb = NULL;
193 static dvdcallbacklow __dvd_finalreadmemcb = NULL;
194 static dvdcallbacklow __dvd_finalsudcb = NULL;
195 static dvdcallbacklow __dvd_finalstatuscb = NULL;
196 static dvdcallbacklow __dvd_finaladdoncb = NULL;
197 static dvdcallbacklow __dvd_finalpatchcb = NULL;
198 static dvdcallbacklow __dvd_finaloffsetcb = NULL;
199 static dvdcbcallback __dvd_cancelcallback = NULL;
200 static dvdcbcallback __dvd_mountusrcb = NULL;
201 static dvdstatecb __dvd_laststate = NULL;
202 static dvdcmdblk *__dvd_executing = NULL;
203 static void *__dvd_usrdata = NULL;
204 static dvddiskid *__dvd_diskID = (dvddiskid*)0x80000000;
206 static lwp_queue __dvd_waitingqueue[4];
207 static dvdcmdl __dvd_cmdlist[4];
208 static dvdcmds __dvd_cmd_curr,__dvd_cmd_prev;
210 static u32 __dvdpatchcode_size = 0;
211 static const u8 *__dvdpatchcode = NULL;
213 static const u32 __dvd_patchcode04_size = 448;
214 static const u8 __dvd_patchcode04[] =
216 0xf7,0x10,0xff,0xf7,0xf4,0x74,0x25,0xd0,0x40,0xf7,0x20,0x4c,0x80,0xf4,0x74,0xd6,
217 0x9c,0x08,0xf7,0x20,0xd6,0xfc,0xf4,0x74,0x28,0xae,0x08,0xf7,0x20,0xd2,0xfc,0x80,
218 0x0c,0xc4,0xda,0xfc,0xfe,0xc8,0xda,0xfc,0xf5,0x00,0x01,0xe8,0x03,0xfc,0xc1,0x00,
219 0xa0,0xf4,0x74,0x09,0xec,0x40,0x10,0xc8,0xda,0xfc,0xf5,0x00,0x02,0xe8,0x03,0xfc,
220 0xbc,0x00,0xf4,0x74,0xf9,0xec,0x40,0x80,0x02,0xf0,0x20,0xc8,0x84,0x80,0xc0,0x9c,
221 0x81,0xdc,0xb4,0x80,0xf5,0x30,0x00,0xf4,0x44,0xa1,0xd1,0x40,0xf8,0xaa,0x00,0x10,
222 0xf4,0xd0,0x9c,0xd1,0x40,0xf0,0x01,0xdc,0xb4,0x80,0xf5,0x30,0x00,0xf7,0x48,0xaa,
223 0x00,0xe9,0x07,0xf4,0xc4,0xa1,0xd1,0x40,0x10,0xfe,0xd8,0x32,0xe8,0x1d,0xf7,0x48,
224 0xa8,0x00,0xe8,0x28,0xf7,0x48,0xab,0x00,0xe8,0x22,0xf7,0x48,0xe1,0x00,0xe8,0x1c,
225 0xf7,0x48,0xee,0x00,0xe8,0x3d,0xd8,0x55,0xe8,0x31,0xfe,0x71,0x04,0xfd,0x22,0x00,
226 0xf4,0x51,0xb0,0xd1,0x40,0xa0,0x40,0x04,0x40,0x06,0xea,0x33,0xf2,0xf9,0xf4,0xd2,
227 0xb0,0xd1,0x40,0x71,0x04,0xfd,0x0a,0x00,0xf2,0x49,0xfd,0x05,0x00,0x51,0x04,0xf2,
228 0x36,0xfe,0xf7,0x21,0xbc,0xff,0xf7,0x31,0xbc,0xff,0xfe,0xf5,0x30,0x01,0xfd,0x7e,
229 0x00,0xea,0x0c,0xf5,0x30,0x01,0xc4,0xb0,0x81,0xf5,0x30,0x02,0xc4,0x94,0x81,0xdc,
230 0xb4,0x80,0xf8,0xe0,0x00,0x10,0xa0,0xf5,0x10,0x01,0xf5,0x10,0x02,0xf5,0x10,0x03,
231 0xfe,0xc8,0xda,0xfc,0xf7,0x00,0xfe,0xff,0xf7,0x31,0xd2,0xfc,0xea,0x0b,0xc8,0xda,
232 0xfc,0xf7,0x00,0xfd,0xff,0xf7,0x31,0xd6,0xfc,0xc4,0xda,0xfc,0xcc,0x44,0xfc,0xf7,
233 0x00,0xfe,0xff,0xc4,0x44,0xfc,0xf4,0x7d,0x28,0xae,0x08,0xe9,0x07,0xf4,0x75,0x60,
234 0xd1,0x40,0xea,0x0c,0xf4,0x7d,0xd6,0x9c,0x08,0xe9,0x05,0xf4,0x75,0x94,0xd1,0x40,
235 0xf2,0x7c,0xd0,0x04,0xcc,0x5b,0x80,0xd8,0x01,0xe9,0x02,0x7c,0x04,0x51,0x20,0x71,
236 0x34,0xf4,0x7d,0xc1,0x85,0x08,0xe8,0x05,0xfe,0x80,0x01,0xea,0x02,0x80,0x00,0xa5,
237 0xd8,0x00,0xe8,0x02,0x85,0x0c,0xc5,0xda,0xfc,0xf4,0x75,0xa0,0xd1,0x40,0x14,0xfe,
238 0xf7,0x10,0xff,0xf7,0xf4,0xc9,0xa0,0xd1,0x40,0xd9,0x00,0xe8,0x22,0x21,0xf7,0x49,
239 0x08,0x06,0xe9,0x05,0x85,0x02,0xf5,0x10,0x01,0xf4,0x79,0x00,0xf0,0x00,0xe9,0x05,
240 0x80,0x00,0xf5,0x10,0x09,0xd9,0x06,0xe9,0x06,0x61,0x06,0xd5,0x06,0x41,0x06,0xf4,
241 0xe0,0x9f,0xdc,0xc7,0xf4,0xe0,0xb5,0xcb,0xc7,0x00,0x00,0x00,0x74,0x0a,0x08,0x00,
242 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
243 0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
246 static const u32 __dvd_patchcode06_size = 448;
247 static const u8 __dvd_patchcode06[] =
249 0xf7,0x10,0xff,0xf7,0xf4,0x74,0x25,0xd0,0x40,0xf7,0x20,0x4c,0x80,0xf4,0x74,0x42,
250 0x9d,0x08,0xf7,0x20,0xd6,0xfc,0xf4,0x74,0x45,0xb1,0x08,0xf7,0x20,0xd2,0xfc,0x80,
251 0x0c,0xc4,0xda,0xfc,0xfe,0xc8,0xda,0xfc,0xf5,0x00,0x01,0xe8,0x03,0xfc,0xc1,0x00,
252 0xa0,0xf4,0x74,0x09,0xec,0x40,0x10,0xc8,0xda,0xfc,0xf5,0x00,0x02,0xe8,0x03,0xfc,
253 0xbc,0x00,0xf4,0x74,0x02,0xed,0x40,0x80,0x02,0xf0,0x20,0xc8,0x78,0x80,0xc0,0x90,
254 0x81,0xdc,0xa8,0x80,0xf5,0x30,0x00,0xf4,0x44,0xa1,0xd1,0x40,0xf8,0xaa,0x00,0x10,
255 0xf4,0xd0,0x9c,0xd1,0x40,0xf0,0x01,0xdc,0xa8,0x80,0xf5,0x30,0x00,0xf7,0x48,0xaa,
256 0x00,0xe9,0x07,0xf4,0xc4,0xa1,0xd1,0x40,0x10,0xfe,0xd8,0x32,0xe8,0x1d,0xf7,0x48,
257 0xa8,0x00,0xe8,0x28,0xf7,0x48,0xab,0x00,0xe8,0x22,0xf7,0x48,0xe1,0x00,0xe8,0x1c,
258 0xf7,0x48,0xee,0x00,0xe8,0x3d,0xd8,0x55,0xe8,0x31,0xfe,0x71,0x04,0xfd,0x22,0x00,
259 0xf4,0x51,0xb0,0xd1,0x40,0xa0,0x40,0x04,0x40,0x06,0xea,0x33,0xf2,0xf9,0xf4,0xd2,
260 0xb0,0xd1,0x40,0x71,0x04,0xfd,0x0a,0x00,0xf2,0x49,0xfd,0x05,0x00,0x51,0x04,0xf2,
261 0x36,0xfe,0xf7,0x21,0xbc,0xff,0xf7,0x31,0xbc,0xff,0xfe,0xf5,0x30,0x01,0xfd,0x7e,
262 0x00,0xea,0x0c,0xf5,0x30,0x01,0xc4,0xa4,0x81,0xf5,0x30,0x02,0xc4,0x88,0x81,0xdc,
263 0xa8,0x80,0xf8,0xe0,0x00,0x10,0xa0,0xf5,0x10,0x01,0xf5,0x10,0x02,0xf5,0x10,0x03,
264 0xfe,0xc8,0xda,0xfc,0xf7,0x00,0xfe,0xff,0xf7,0x31,0xd2,0xfc,0xea,0x0b,0xc8,0xda,
265 0xfc,0xf7,0x00,0xfd,0xff,0xf7,0x31,0xd6,0xfc,0xc4,0xda,0xfc,0xcc,0x44,0xfc,0xf7,
266 0x00,0xfe,0xff,0xc4,0x44,0xfc,0xf4,0x7d,0x45,0xb1,0x08,0xe9,0x07,0xf4,0x75,0x60,
267 0xd1,0x40,0xea,0x0c,0xf4,0x7d,0x42,0x9d,0x08,0xe9,0x05,0xf4,0x75,0x94,0xd1,0x40,
268 0xf2,0x7c,0xd0,0x04,0xcc,0x5b,0x80,0xd8,0x01,0xe9,0x02,0x7c,0x04,0x51,0x20,0x71,
269 0x34,0xf4,0x7d,0xb9,0x85,0x08,0xe8,0x05,0xfe,0x80,0x01,0xea,0x02,0x80,0x00,0xa5,
270 0xd8,0x00,0xe8,0x02,0x85,0x0c,0xc5,0xda,0xfc,0xf4,0x75,0xa0,0xd1,0x40,0x14,0xfe,
271 0xf7,0x10,0xff,0xf7,0xf4,0xc9,0xa0,0xd1,0x40,0xd9,0x00,0xe8,0x22,0x21,0xf7,0x49,
272 0x08,0x06,0xe9,0x05,0x85,0x02,0xf5,0x10,0x01,0xf4,0x79,0x00,0xf0,0x00,0xe9,0x05,
273 0x80,0x00,0xf5,0x10,0x09,0xd9,0x06,0xe9,0x06,0x61,0x06,0xd5,0x06,0x41,0x06,0xf4,
274 0xe0,0xbc,0xdf,0xc7,0xf4,0xe0,0x37,0xcc,0xc7,0x00,0x00,0x00,0x74,0x0a,0x08,0x00,
275 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
276 0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
279 static const u32 __dvd_patchcode08_size = 448;
280 static const u8 __dvd_patchcode08[] =
282 0xf7,0x10,0xff,0xf7,0xf4,0x74,0x25,0xd0,0x40,0xf7,0x20,0x4c,0x80,0xf4,0x74,0x32,
283 0x9d,0x08,0xf7,0x20,0xd6,0xfc,0xf4,0x74,0x75,0xae,0x08,0xf7,0x20,0xd2,0xfc,0x80,
284 0x0c,0xc4,0xda,0xfc,0xfe,0xc8,0xda,0xfc,0xf5,0x00,0x01,0xe8,0x03,0xfc,0xc1,0x00,
285 0xa0,0xf4,0x74,0x09,0xec,0x40,0x10,0xc8,0xda,0xfc,0xf5,0x00,0x02,0xe8,0x03,0xfc,
286 0xbc,0x00,0xf4,0x74,0xf5,0xec,0x40,0x80,0x02,0xf0,0x20,0xc8,0x80,0x80,0xc0,0x98,
287 0x81,0xdc,0xb0,0x80,0xf5,0x30,0x00,0xf4,0x44,0xa1,0xd1,0x40,0xf8,0xaa,0x00,0x10,
288 0xf4,0xd0,0x9c,0xd1,0x40,0xf0,0x01,0xdc,0xb0,0x80,0xf5,0x30,0x00,0xf7,0x48,0xaa,
289 0x00,0xe9,0x07,0xf4,0xc4,0xa1,0xd1,0x40,0x10,0xfe,0xd8,0x32,0xe8,0x1d,0xf7,0x48,
290 0xa8,0x00,0xe8,0x28,0xf7,0x48,0xab,0x00,0xe8,0x22,0xf7,0x48,0xe1,0x00,0xe8,0x1c,
291 0xf7,0x48,0xee,0x00,0xe8,0x3d,0xd8,0x55,0xe8,0x31,0xfe,0x71,0x04,0xfd,0x22,0x00,
292 0xf4,0x51,0xb0,0xd1,0x40,0xa0,0x40,0x04,0x40,0x06,0xea,0x33,0xf2,0xf9,0xf4,0xd2,
293 0xb0,0xd1,0x40,0x71,0x04,0xfd,0x0a,0x00,0xf2,0x49,0xfd,0x05,0x00,0x51,0x04,0xf2,
294 0x36,0xfe,0xf7,0x21,0xbc,0xff,0xf7,0x31,0xbc,0xff,0xfe,0xf5,0x30,0x01,0xfd,0x7e,
295 0x00,0xea,0x0c,0xf5,0x30,0x01,0xc4,0xac,0x81,0xf5,0x30,0x02,0xc4,0x90,0x81,0xdc,
296 0xb0,0x80,0xf8,0xe0,0x00,0x10,0xa0,0xf5,0x10,0x01,0xf5,0x10,0x02,0xf5,0x10,0x03,
297 0xfe,0xc8,0xda,0xfc,0xf7,0x00,0xfe,0xff,0xf7,0x31,0xd2,0xfc,0xea,0x0b,0xc8,0xda,
298 0xfc,0xf7,0x00,0xfd,0xff,0xf7,0x31,0xd6,0xfc,0xc4,0xda,0xfc,0xcc,0x44,0xfc,0xf7,
299 0x00,0xfe,0xff,0xc4,0x44,0xfc,0xf4,0x7d,0x75,0xae,0x08,0xe9,0x07,0xf4,0x75,0x60,
300 0xd1,0x40,0xea,0x0c,0xf4,0x7d,0x32,0x9d,0x08,0xe9,0x05,0xf4,0x75,0x94,0xd1,0x40,
301 0xf2,0x7c,0xd0,0x04,0xcc,0x5b,0x80,0xd8,0x01,0xe9,0x02,0x7c,0x04,0x51,0x20,0x71,
302 0x34,0xf4,0x7d,0xc1,0x85,0x08,0xe8,0x05,0xfe,0x80,0x01,0xea,0x02,0x80,0x00,0xa5,
303 0xd8,0x00,0xe8,0x02,0x85,0x0c,0xc5,0xda,0xfc,0xf4,0x75,0xa0,0xd1,0x40,0x14,0xfe,
304 0xf7,0x10,0xff,0xf7,0xf4,0xc9,0xa0,0xd1,0x40,0xd9,0x00,0xe8,0x22,0x21,0xf7,0x49,
305 0x08,0x06,0xe9,0x05,0x85,0x02,0xf5,0x10,0x01,0xf4,0x79,0x00,0xf0,0x00,0xe9,0x05,
306 0x80,0x00,0xf5,0x10,0x09,0xd9,0x06,0xe9,0x06,0x61,0x06,0xd5,0x06,0x41,0x06,0xf4,
307 0xe0,0xec,0xdc,0xc7,0xf4,0xe0,0x0e,0xcc,0xc7,0x00,0x00,0x00,0x74,0x0a,0x08,0x00,
308 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
309 0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
312 static const u32 __dvd_patchcodeQ08_size = 448;
313 static const u8 __dvd_patchcodeQ08[] =
315 0xf7,0x10,0xff,0xf7,0xf4,0x74,0x25,0xd0,0x40,0xf7,0x20,0x4c,0x80,0xf4,0x74,0x39,
316 0x9e,0x08,0xf7,0x20,0xd6,0xfc,0xf4,0x74,0x02,0xb3,0x08,0xf7,0x20,0xd2,0xfc,0x80,
317 0x0c,0xc4,0xda,0xfc,0xfe,0xc8,0xda,0xfc,0xf5,0x00,0x01,0xe8,0x03,0xfc,0xc1,0x00,
318 0xa0,0xf4,0x74,0x09,0xec,0x40,0x10,0xc8,0xda,0xfc,0xf5,0x00,0x02,0xe8,0x03,0xfc,
319 0xbc,0x00,0xf4,0x74,0x02,0xed,0x40,0x80,0x02,0xf0,0x20,0xc8,0x78,0x80,0xc0,0x92,
320 0x81,0xdc,0xaa,0x80,0xf5,0x30,0x00,0xf4,0x44,0xa1,0xd1,0x40,0xf8,0xaa,0x00,0x10,
321 0xf4,0xd0,0x9c,0xd1,0x40,0xf0,0x01,0xdc,0xaa,0x80,0xf5,0x30,0x00,0xf7,0x48,0xaa,
322 0x00,0xe9,0x07,0xf4,0xc4,0xa1,0xd1,0x40,0x10,0xfe,0xd8,0x32,0xe8,0x1d,0xf7,0x48,
323 0xa8,0x00,0xe8,0x28,0xf7,0x48,0xab,0x00,0xe8,0x22,0xf7,0x48,0xe1,0x00,0xe8,0x1c,
324 0xf7,0x48,0xee,0x00,0xe8,0x3d,0xd8,0x55,0xe8,0x31,0xfe,0x71,0x04,0xfd,0x22,0x00,
325 0xf4,0x51,0xb0,0xd1,0x40,0xa0,0x40,0x04,0x40,0x06,0xea,0x33,0xf2,0xf9,0xf4,0xd2,
326 0xb0,0xd1,0x40,0x71,0x04,0xfd,0x0a,0x00,0xf2,0x49,0xfd,0x05,0x00,0x51,0x04,0xf2,
327 0x36,0xfe,0xf7,0x21,0xbc,0xff,0xf7,0x31,0xbc,0xff,0xfe,0xf5,0x30,0x01,0xfd,0x7e,
328 0x00,0xea,0x0c,0xf5,0x30,0x01,0xc4,0xa6,0x81,0xf5,0x30,0x02,0xc4,0x8a,0x81,0xdc,
329 0xaa,0x80,0xf8,0xe0,0x00,0x10,0xa0,0xf5,0x10,0x01,0xf5,0x10,0x02,0xf5,0x10,0x03,
330 0xfe,0xc8,0xda,0xfc,0xf7,0x00,0xfe,0xff,0xf7,0x31,0xd2,0xfc,0xea,0x0b,0xc8,0xda,
331 0xfc,0xf7,0x00,0xfd,0xff,0xf7,0x31,0xd6,0xfc,0xc4,0xda,0xfc,0xcc,0x44,0xfc,0xf7,
332 0x00,0xfe,0xff,0xc4,0x44,0xfc,0xf4,0x7d,0x02,0xb3,0x08,0xe9,0x07,0xf4,0x75,0x60,
333 0xd1,0x40,0xea,0x0c,0xf4,0x7d,0x39,0x9e,0x08,0xe9,0x05,0xf4,0x75,0x94,0xd1,0x40,
334 0xf2,0x7c,0xd0,0x04,0xcc,0x5b,0x80,0xd8,0x01,0xe9,0x02,0x7c,0x04,0x51,0x20,0x71,
335 0x34,0xf4,0x7d,0x7f,0x86,0x08,0xe8,0x05,0xfe,0x80,0x01,0xea,0x02,0x80,0x00,0xa5,
336 0xd8,0x00,0xe8,0x02,0x85,0x0c,0xc5,0xda,0xfc,0xf4,0x75,0xa0,0xd1,0x40,0x14,0xfe,
337 0xf7,0x10,0xff,0xf7,0xf4,0xc9,0xa0,0xd1,0x40,0xd9,0x00,0xe8,0x22,0x21,0xf7,0x49,
338 0x08,0x06,0xe9,0x05,0x85,0x02,0xf5,0x10,0x01,0xf4,0x79,0x00,0xf0,0x00,0xe9,0x05,
339 0x80,0x00,0xf5,0x10,0x09,0xd9,0x06,0xe9,0x06,0x61,0x06,0xd5,0x06,0x41,0x06,0xf4,
340 0xe0,0x79,0xe1,0xc7,0xf4,0xe0,0xeb,0xcd,0xc7,0x00,0x00,0x00,0xa4,0x0a,0x08,0x00,
341 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
342 0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
345 static vu32* const _piReg = (u32*)0xCC003000;
347 #if defined(HW_RVL)
348 static vu32* const _diReg = (u32*)0xCD006000;
349 #elif defined(HW_DOL)
350 static vu32* const _diReg = (u32*)0xCC006000;
351 #endif
353 static u8 __dvd_unlockcmd$221[12] = {0xff,0x01,'M','A','T','S','H','I','T','A',0x02,0x00};
354 static u8 __dvd_unlockcmd$222[12] = {0xff,0x00,'D','V','D','-','G','A','M','E',0x03,0x00};
355 static u32 __dvd_errortable[] = {
356 0x00000000, 0x00023a00, 0x00062800, 0x00030200,
357 0x00031100, 0x00052000, 0x00052001, 0x00052100,
358 0x00052400, 0x00052401, 0x00052402, 0x000B5A01,
359 0x00056300, 0x00020401, 0x00020400, 0x00040800,
360 0x00100007, 0x00000000
363 void __dvd_statecheckid(void);
364 void __dvd_stategettingerror(void);
365 void __dvd_statecoverclosed(void);
366 void __dvd_stateready(void);
367 void __dvd_statemotorstopped(void);
368 void __dvd_statetimeout(void);
369 void __dvd_stategotoretry(void);
370 void __dvd_stateerror(s32 result);
371 void __dvd_statecoverclosed_cmd(dvdcmdblk *block);
372 void __dvd_statebusy(dvdcmdblk *block);
373 void DVD_LowReset(u32 reset_mode);
374 s32 DVD_LowSeek(s64 offset,dvdcallbacklow cb);
375 s32 DVD_LowRead(void *buf,u32 len,s64 offset,dvdcallbacklow cb);
376 s32 DVD_LowReadId(dvddiskid *diskID,dvdcallbacklow cb);
377 s32 DVD_LowRequestError(dvdcallbacklow cb);
378 s32 DVD_LowStopMotor(dvdcallbacklow cb);
379 s32 DVD_LowInquiry(dvddrvinfo *info,dvdcallbacklow cb);
380 s32 DVD_LowWaitCoverClose(dvdcallbacklow cb);
381 s32 DVD_LowAudioStream(u32 subcmd,u32 len,s64 offset,dvdcallbacklow cb);
382 s32 DVD_LowAudioBufferConfig(s32 enable,u32 size,dvdcallbacklow cb);
383 s32 DVD_LowRequestAudioStatus(u32 subcmd,dvdcallbacklow cb);
384 s32 DVD_LowEnableExtensions(u8 enable,dvdcallbacklow cb);
385 s32 DVD_LowSpinMotor(u32 mode,dvdcallbacklow cb);
386 s32 DVD_LowSetStatus(u32 status,dvdcallbacklow cb);
387 s32 DVD_LowUnlockDrive(dvdcallbacklow cb);
388 s32 DVD_LowPatchDriveCode(dvdcallbacklow cb);
389 s32 DVD_LowSpinUpDrive(dvdcallbacklow cb);
390 s32 DVD_LowControlMotor(u32 mode,dvdcallbacklow cb);
391 s32 DVD_LowFuncCall(u32 address,dvdcallbacklow cb);
392 s32 DVD_LowReadmem(u32 address,void *buffer,dvdcallbacklow cb);
393 s32 DVD_LowSetGCMOffset(s64 offset,dvdcallbacklow cb);
394 s32 DVD_LowSetOffset(s64 offset,dvdcallbacklow cb);
395 s32 DVD_ReadAbsAsyncPrio(dvdcmdblk *block,void *buf,u32 len,s64 offset,dvdcbcallback cb,s32 prio);
396 s32 DVD_ReadDiskID(dvdcmdblk *block,dvddiskid *id,dvdcbcallback cb);
397 s32 __issuecommand(s32 prio,dvdcmdblk *block);
399 extern void udelay(int us);
400 extern u32 diff_msec(unsigned long long start,unsigned long long end);
401 extern long long gettime(void);
402 extern void __MaskIrq(u32);
403 extern void __UnmaskIrq(u32);
404 extern syssramex* __SYS_LockSramEx(void);
405 extern u32 __SYS_UnlockSramEx(u32 write);
407 static u8 err2num(u32 errorcode)
409 u32 i;
411 i=0;
412 while(i<18) {
413 if(errorcode==__dvd_errortable[i]) return i;
414 i++;
416 if(errorcode<0x00100000 || errorcode>0x00100008) return 29;
418 return 17;
421 static u8 convert(u32 errorcode)
423 u8 err,err_num;
425 if((errorcode-0x01230000)==0x4567) return 255;
426 else if((errorcode-0x01230000)==0x4568) return 254;
428 err = _SHIFTR(errorcode,24,8);
429 err_num = err2num((errorcode&0x00ffffff));
430 if(err>0x06) err = 0x06;
432 return err_num+(err*30);
435 static void __dvd_clearwaitingqueue()
437 u32 i;
439 for(i=0;i<4;i++)
440 __lwp_queue_init_empty(&__dvd_waitingqueue[i]);
443 static s32 __dvd_checkwaitingqueue()
445 u32 i;
446 u32 level;
448 _CPU_ISR_Disable(level);
449 for(i=0;i<4;i++) {
450 if(!__lwp_queue_isempty(&__dvd_waitingqueue[i])) break;
452 _CPU_ISR_Restore(level);
453 return (i<4);
456 static s32 __dvd_pushwaitingqueue(s32 prio,dvdcmdblk *block)
458 u32 level;
459 #ifdef _DVD_DEBUG
460 printf("__dvd_pushwaitingqueue(%d,%p,%p)\n",prio,block,block->cb);
461 #endif
462 _CPU_ISR_Disable(level);
463 __lwp_queue_appendI(&__dvd_waitingqueue[prio],&block->node);
464 _CPU_ISR_Restore(level);
465 return 1;
468 static dvdcmdblk* __dvd_popwaitingqueueprio(s32 prio)
470 u32 level;
471 dvdcmdblk *ret = NULL;
472 #ifdef _DVD_DEBUG
473 printf("__dvd_popwaitingqueueprio(%d)\n",prio);
474 #endif
475 _CPU_ISR_Disable(level);
476 ret = (dvdcmdblk*)__lwp_queue_firstnodeI(&__dvd_waitingqueue[prio]);
477 _CPU_ISR_Restore(level);
478 #ifdef _DVD_DEBUG
479 printf("__dvd_popwaitingqueueprio(%p,%p)\n",ret,ret->cb);
480 #endif
481 return ret;
484 static dvdcmdblk* __dvd_popwaitingqueue()
486 u32 i,level;
487 dvdcmdblk *ret = NULL;
488 #ifdef _DVD_DEBUG
489 printf("__dvd_popwaitingqueue()\n");
490 #endif
491 _CPU_ISR_Disable(level);
492 for(i=0;i<4;i++) {
493 if(!__lwp_queue_isempty(&__dvd_waitingqueue[i])) {
494 _CPU_ISR_Restore(level);
495 ret = __dvd_popwaitingqueueprio(i);
496 return ret;
499 _CPU_ISR_Restore(level);
500 return NULL;
503 static void __dvd_timeouthandler(syswd_t alarm,void *cbarg)
505 dvdcallbacklow cb;
507 __MaskIrq(IRQMASK(IRQ_PI_DI));
508 cb = __dvd_callback;
509 if(cb) cb(0x10);
512 static void __dvd_storeerror(u32 errorcode)
514 u8 err;
515 syssramex *ptr;
517 err = convert(errorcode);
518 ptr = __SYS_LockSramEx();
519 ptr->dvderr_code = err;
520 __SYS_UnlockSramEx(1);
523 static u32 __dvd_categorizeerror(u32 errorcode)
525 #ifdef _DVD_DEBUG
526 printf("__dvd_categorizeerror(%08x)\n",errorcode);
527 #endif
528 if((errorcode-0x20000)==0x0400) {
529 __dvd_lasterror = errorcode;
530 return 1;
533 if(DVD_ERROR(errorcode)==DVD_ERROR_MEDIUM_CHANGED
534 || DVD_ERROR(errorcode)==DVD_ERROR_MEDIUM_NOT_PRESENT
535 || DVD_ERROR(errorcode)==DVD_ERROR_MEDIUM_CHANGE_REQ
536 || (DVD_ERROR(errorcode)-0x40000)==0x3100) return 0;
538 __dvd_internalretries++;
539 if(__dvd_internalretries==2) {
540 if(__dvd_lasterror==DVD_ERROR(errorcode)) {
541 __dvd_lasterror = DVD_ERROR(errorcode);
542 return 1;
544 __dvd_lasterror = DVD_ERROR(errorcode);
545 return 2;
548 __dvd_lasterror = DVD_ERROR(errorcode);
549 if(DVD_ERROR(errorcode)!=DVD_ERROR_UNRECOVERABLE_READ) {
550 if(__dvd_executing->cmd!=0x0005) return 3;
552 return 2;
555 static void __SetupTimeoutAlarm(const struct timespec *tp)
557 SYS_SetAlarm(__dvd_timeoutalarm,tp,__dvd_timeouthandler,NULL);
560 static void __Read(void *buffer,u32 len,s64 offset,dvdcallbacklow cb)
562 u32 val;
563 struct timespec tb;
564 #ifdef _DVD_DEBUG
565 printf("__Read(%p,%d,%d)\n",buffer,len,offset);
566 #endif
567 __dvd_callback = cb;
568 __dvd_stopnextint = 0;
569 __dvd_lastcmdwasread = 1;
571 _diReg[2] = DVD_READSECTOR;
572 _diReg[3] = (u32)(offset>>2);
573 _diReg[4] = len;
574 _diReg[5] = (u32)buffer;
575 _diReg[6] = len;
577 __dvd_lastlen = len;
579 _diReg[7] = (DVD_DI_DMA|DVD_DI_START);
580 val = _diReg[7];
581 if(val>0x00a00000) {
582 tb.tv_sec = 20;
583 tb.tv_nsec = 0;
584 __SetupTimeoutAlarm(&tb);
585 } else {
586 tb.tv_sec = 10;
587 tb.tv_nsec = 0;
588 __SetupTimeoutAlarm(&tb);
592 static void __DoRead(void *buffer,u32 len,s64 offset,dvdcallbacklow cb)
594 #ifdef _DVD_DEBUG
595 printf("__DoRead(%p,%d,%d)\n",buffer,len,offset);
596 #endif
597 __dvd_nextcmdnum = 0;
598 __dvd_cmdlist[0].cmd = -1;
599 __Read(buffer,len,offset,cb);
602 static u32 __ProcessNextCmd()
604 u32 cmd_num;
605 #ifdef _DVD_DEBUG
606 printf("__ProcessNextCmd(%d)\n",__dvd_nextcmdnum);
607 #endif
608 cmd_num = __dvd_nextcmdnum;
609 if(__dvd_cmdlist[cmd_num].cmd==0x0001) {
610 __dvd_nextcmdnum++;
611 __Read(__dvd_cmdlist[cmd_num].buf,__dvd_cmdlist[cmd_num].len,__dvd_cmdlist[cmd_num].offset,__dvd_cmdlist[cmd_num].cb);
612 return 1;
615 if(__dvd_cmdlist[cmd_num].cmd==0x0002) {
616 __dvd_nextcmdnum++;
617 DVD_LowSeek(__dvd_cmdlist[cmd_num].offset,__dvd_cmdlist[cmd_num].cb);
618 return 1;
620 return 0;
623 static void __DVDLowWATypeSet(u32 workaround,u32 workaroundseek)
625 u32 level;
627 _CPU_ISR_Disable(level);
628 __dvd_workaround = workaround;
629 __dvd_workaroundseek = workaroundseek;
630 _CPU_ISR_Restore(level);
633 static void __DVDInitWA()
635 __dvd_nextcmdnum = 0;
636 __DVDLowWATypeSet(0,0);
639 static s32 __dvd_checkcancel(u32 cancelpt)
641 dvdcmdblk *block;
643 if(__dvd_canceling) {
644 __dvd_resumefromhere = cancelpt;
645 __dvd_canceling = 0;
647 block = __dvd_executing;
648 __dvd_executing = &__dvd_dummycmdblk;
650 block->state = 10;
651 if(block->cb) block->cb(-3,block);
652 if(__dvd_cancelcallback) __dvd_cancelcallback(0,block);
654 __dvd_stateready();
655 return 1;
657 return 0;
660 static void __dvd_stateretrycb(s32 result)
662 #ifdef _DVD_DEBUG
663 printf("__dvd_stateretrycb(%08x)\n",result);
664 #endif
665 if(result==0x0010) {
666 __dvd_executing->state = -1;
667 __dvd_statetimeout();
668 return;
671 if(result&0x0002) __dvd_stateerror(0x01234567);
672 if(result==0x0001) {
673 __dvd_statebusy(__dvd_executing);
674 return;
678 static void __dvd_unrecoverederrorretrycb(s32 result)
680 u32 val;
682 if(result==0x0010) {
683 __dvd_executing->state = -1;
684 __dvd_statetimeout();
685 return;
688 __dvd_executing->state = -1;
689 if(result&0x0002) __dvd_stateerror(0x01234567);
690 else {
691 val = _diReg[8];
692 __dvd_stateerror(val);
696 static void __dvd_unrecoverederrorcb(s32 result)
698 if(result==0x0010) {
699 __dvd_executing->state = -1;
700 __dvd_statetimeout();
701 return;
703 if(result&0x0001) {
704 __dvd_stategotoretry();
705 return;
707 if(!(result==0x0002)) DVD_LowRequestError(__dvd_unrecoverederrorretrycb);
710 static void __dvd_stateerrorcb(s32 result)
712 dvdcmdblk *block;
713 #ifdef _DVD_DEBUG
714 printf("__dvd_stateerrorcb(%d)\n",result);
715 #endif
716 if(result==0x0010) {
717 __dvd_executing->state = -1;
718 __dvd_statetimeout();
719 return;
722 __dvd_fatalerror = 1;
723 block = __dvd_executing;
724 __dvd_executing = &__dvd_dummycmdblk;
725 if(block->cb) block->cb(-1,block);
726 if(__dvd_canceling) {
727 __dvd_canceling = 0;
728 if(__dvd_cancelcallback) __dvd_cancelcallback(0,block);
730 __dvd_stateready();
733 static void __dvd_stategettingerrorcb(s32 result)
735 s32 ret;
736 u32 val,cnclpt;
737 #ifdef _DVD_DEBUG
738 printf("__dvd_stategettingerrorcb(%d)\n",result);
739 #endif
740 if(result==0x0010) {
741 __dvd_executing->state = -1;
742 __dvd_statetimeout();
743 return;
745 if(result&0x0002) {
746 __dvd_executing->state = -1;
747 __dvd_stateerror(0x01234567);
748 return;
750 if(result==0x0001) {
751 val = _diReg[8];
752 ret = __dvd_categorizeerror(val);
753 #ifdef _DVD_DEBUG
754 printf("__dvd_stategettingerrorcb(status = %02x, err = %08x, category = %d)\n",DVD_STATUS(val),DVD_ERROR(val),ret);
755 #endif
756 if(ret==1) {
757 __dvd_executing->state = -1;
758 __dvd_stateerror(val);
759 return;
760 } else if(ret==2 || ret==3) cnclpt = 0;
761 else {
762 if(DVD_STATUS(val)==DVD_STATUS_COVER_OPENED) cnclpt = 4;
763 else if(DVD_STATUS(val)==DVD_STATUS_DISK_CHANGE) cnclpt = 6;
764 else if(DVD_STATUS(val)==DVD_STATUS_NO_DISK) cnclpt = 3;
765 else cnclpt = 5;
767 if(__dvd_checkcancel(cnclpt)) return;
769 if(ret==2) {
770 if(dvd_may_retry(val)) {
771 // disable the extensions iff they're enabled and we were trying to read the disc ID
772 if(__dvd_executing->cmd==0x05) {
773 __dvd_lasterror = 0;
774 __dvd_extensionsenabled = FALSE;
775 DVD_LowSpinUpDrive(__dvd_stateretrycb);
776 return;
778 __dvd_statebusy(__dvd_executing);
779 } else {
780 __dvd_storeerror(val);
781 __dvd_stategotoretry();
783 return;
784 } else if(ret==3) {
785 if(DVD_ERROR(val)==DVD_ERROR_UNRECOVERABLE_READ) {
786 DVD_LowSeek(__dvd_executing->offset,__dvd_unrecoverederrorcb);
787 return;
788 } else {
789 __dvd_laststate(__dvd_executing);
790 return;
792 } else if(DVD_STATUS(val)==DVD_STATUS_COVER_OPENED) {
793 __dvd_executing->state = 5;
794 __dvd_statemotorstopped();
795 return;
796 } else if(DVD_STATUS(val)==DVD_STATUS_DISK_CHANGE) {
797 __dvd_executing->state = 3;
798 __dvd_statecoverclosed();
799 return;
800 } else if(DVD_STATUS(val)==DVD_STATUS_NO_DISK) {
801 __dvd_executing->state = 4;
802 __dvd_statemotorstopped();
803 return;
805 __dvd_executing->state = -1;
806 __dvd_stateerror(0x01234567);
807 return;
811 static void __dvd_statebusycb(s32 result)
813 u32 val;
814 dvdcmdblk *block;
815 #ifdef _DVD_DEBUG
816 printf("__dvd_statebusycb(%04x)\n",result);
817 #endif
818 if(result==0x0010) {
819 __dvd_executing->state = -1;
820 __dvd_statetimeout();
821 return;
823 if(__dvd_currcmd==0x0003 || __dvd_currcmd==0x000f) {
824 if(result&0x0002) {
825 __dvd_executing->state = -1;
826 __dvd_stateerror(0x01234567);
827 return;
829 if(result==0x0001) {
830 __dvd_internalretries = 0;
831 if(__dvd_currcmd==0x000f) __dvd_resetrequired = 1;
832 if(__dvd_checkcancel(7)) return;
834 __dvd_executing->state = 7;
835 __dvd_statemotorstopped();
836 return;
839 if(result&0x0004) {
842 if(__dvd_currcmd==0x0001 || __dvd_currcmd==0x0004
843 || __dvd_currcmd==0x0005 || __dvd_currcmd==0x000e) {
844 __dvd_executing->txdsize += (__dvd_executing->currtxsize-_diReg[6]);
846 if(result&0x0008) {
847 __dvd_canceling = 0;
848 block = __dvd_executing;
849 __dvd_executing = &__dvd_dummycmdblk;
850 __dvd_executing->state = 10;
851 if(block->cb) block->cb(-3,block);
852 if(__dvd_cancelcallback) __dvd_cancelcallback(0,block);
853 __dvd_stateready();
854 return;
856 if(result&0x0001) {
857 __dvd_internalretries = 0;
858 if(__dvd_checkcancel(0)) return;
860 if(__dvd_currcmd==0x0001 || __dvd_currcmd==0x0004
861 || __dvd_currcmd==0x0005 || __dvd_currcmd==0x000e) {
862 #ifdef _DVD_DEBUG
863 printf("__dvd_statebusycb(%p,%p)\n",__dvd_executing,__dvd_executing->cb);
864 #endif
865 if(__dvd_executing->txdsize!=__dvd_executing->len) {
866 __dvd_statebusy(__dvd_executing);
867 return;
869 block = __dvd_executing;
870 __dvd_executing = &__dvd_dummycmdblk;
871 block->state = 0;
872 if(block->cb) block->cb(block->txdsize,block);
873 __dvd_stateready();
874 return;
876 if(__dvd_currcmd==0x0009 || __dvd_currcmd==0x000a
877 || __dvd_currcmd==0x000b || __dvd_currcmd==0x000c) {
879 val = _diReg[8];
880 if(__dvd_currcmd==0x000a || __dvd_currcmd==0x000b) val <<= 2;
882 block = __dvd_executing;
883 __dvd_executing = &__dvd_dummycmdblk;
884 block->state = 0;
885 if(block->cb) block->cb(val,block);
886 __dvd_stateready();
887 return;
889 if(__dvd_currcmd==0x0006) {
890 if(!__dvd_executing->currtxsize) {
891 if(_diReg[8]&0x0001) {
892 block = __dvd_executing;
893 __dvd_executing = &__dvd_dummycmdblk;
894 block->state = 9;
895 if(block->cb) block->cb(-2,block);
896 __dvd_stateready();
897 return;
899 __dvd_autofinishing = 0;
900 __dvd_executing->currtxsize = 1;
901 DVD_LowAudioStream(0,__dvd_executing->len,__dvd_executing->offset,__dvd_statebusycb);
902 return;
905 block = __dvd_executing;
906 __dvd_executing = &__dvd_dummycmdblk;
907 block->state = 0;
908 if(block->cb) block->cb(0,block);
909 __dvd_stateready();
910 return;
912 if(__dvd_currcmd==0x0010) {
913 if(__dvd_drivestate&DVD_CHIPPRESENT) {
914 block = __dvd_executing;
915 __dvd_executing = &__dvd_dummycmdblk;
916 block->state = 0;
917 if(block->cb) block->cb(DVD_DISKIDSIZE,block);
918 __dvd_stateready();
919 return;
923 block = __dvd_executing;
924 __dvd_executing = &__dvd_dummycmdblk;
925 block->state = 0;
926 if(block->cb) block->cb(0,block);
927 __dvd_stateready();
928 return;
930 if(result==0x0002) {
931 #ifdef _DVD_DEBUG
932 printf("__dvd_statebusycb(%d,%d)\n",__dvd_executing->txdsize,__dvd_executing->len);
933 #endif
934 if(__dvd_currcmd==0x000e) {
935 __dvd_executing->state = -1;
936 __dvd_stateerror(0x01234567);
937 return;
939 if((__dvd_currcmd==0x0001 || __dvd_currcmd==0x0004
940 || __dvd_currcmd==0x0005 || __dvd_currcmd==0x000e)
941 && __dvd_executing->txdsize==__dvd_executing->len) {
942 if(__dvd_checkcancel(0)) return;
944 block = __dvd_executing;
945 __dvd_executing = &__dvd_dummycmdblk;
946 block->state = 0;
947 if(block->cb) block->cb(block->txdsize,block);
948 __dvd_stateready();
949 return;
952 __dvd_stategettingerror();
955 static void __dvd_mountsynccb(s32 result,dvdcmdblk *block)
957 LWP_ThreadBroadcast(__dvd_wait_queue);
960 static void __dvd_inquirysynccb(s32 result,dvdcmdblk *block)
962 LWP_ThreadBroadcast(__dvd_wait_queue);
965 static void __dvd_readsynccb(s32 result,dvdcmdblk *block)
967 LWP_ThreadBroadcast(__dvd_wait_queue);
970 static void __dvd_streamatendsynccb(s32 result,dvdcmdblk *block)
972 LWP_ThreadBroadcast(__dvd_wait_queue);
975 static void __dvd_seeksynccb(s32 result,dvdcmdblk *block)
977 LWP_ThreadBroadcast(__dvd_wait_queue);
980 static void __dvd_spinupdrivesynccb(s32 result,dvdcmdblk *block)
982 LWP_ThreadBroadcast(__dvd_wait_queue);
985 static void __dvd_motorcntrlsynccb(s32 result,dvdcmdblk *block)
987 LWP_ThreadBroadcast(__dvd_wait_queue);
990 static void __dvd_setgcmsynccb(s32 result,dvdcmdblk *block)
992 LWP_ThreadBroadcast(__dvd_wait_queue);
995 static void __dvd_statemotorstoppedcb(s32 result)
997 #ifdef _DVD_DEBUG
998 printf("__dvd_statemotorstoppedcb(%08x)\n",result);
999 #endif
1000 _diReg[1] = 0;
1001 __dvd_executing->state = 3;
1002 __dvd_statecoverclosed();
1005 static void __dvd_statecoverclosedcb(s32 result)
1007 #ifdef _DVD_DEBUG
1008 printf("__dvd_statecoverclosedcb(%08x)\n",result);
1009 #endif
1010 if(result==0x0010) {
1011 __dvd_executing->state = -1;
1012 __dvd_statetimeout();
1013 return;
1016 if(!(result&0x0006)) {
1017 __dvd_internalretries = 0;
1018 __dvd_statecheckid();
1019 return;
1022 if(result==0x0002) __dvd_stategettingerror();
1025 static void __dvd_statecheckid1cb(s32 result)
1027 #ifdef _DVD_DEBUG
1028 printf("__dvd_statecheckid1cb(%08x)\n",result);
1029 #endif
1030 __dvd_ready = 1;
1031 if(memcmp(__dvd_diskID,&__dvd_tmpid0,DVD_DISKIDSIZE)) memcpy(__dvd_diskID,&__dvd_tmpid0,DVD_DISKIDSIZE);
1032 LWP_ThreadBroadcast(__dvd_wait_queue);
1035 static void __dvd_stategotoretrycb(s32 result)
1037 if(result==0x0010) {
1038 __dvd_executing->state = -1;
1039 __dvd_statetimeout();
1040 return;
1042 if(result&0x0002) {
1043 __dvd_executing->state = -1;
1044 __dvd_stateerror(0x01234567);
1045 return;
1047 if(result==0x0001) {
1048 __dvd_internalretries = 0;
1049 if(__dvd_currcmd==0x0004 || __dvd_currcmd==0x0005
1050 || __dvd_currcmd==0x000d || __dvd_currcmd==0x000f) {
1051 __dvd_resetrequired = 1;
1052 if(__dvd_checkcancel(2)) return;
1054 __dvd_executing->state = 11;
1055 __dvd_statemotorstopped();
1060 static void __dvd_getstatuscb(s32 result)
1062 u32 val,*pn_data;
1063 dvdcallbacklow cb;
1064 #ifdef _DVD_DEBUG
1065 printf("__dvd_getstatuscb(%d)\n",result);
1066 #endif
1067 if(result==0x0010) {
1068 __dvd_statetimeout();
1069 return;
1071 if(result==0x0001) {
1072 val = _diReg[8];
1074 pn_data = __dvd_usrdata;
1075 __dvd_usrdata = NULL;
1076 if(pn_data) pn_data[0] = val;
1078 cb = __dvd_finalstatuscb;
1079 __dvd_finalstatuscb = NULL;
1080 if(cb) cb(result);
1081 return;
1083 __dvd_stategettingerror();
1086 static void __dvd_readmemcb(s32 result)
1088 u32 val,*pn_data;
1089 dvdcallbacklow cb;
1090 #ifdef _DVD_DEBUG
1091 printf("__dvd_readmemcb(%d)\n",result);
1092 #endif
1093 if(result==0x0010) {
1094 __dvd_statetimeout();
1095 return;
1097 if(result==0x0001) {
1098 val = _diReg[8];
1100 pn_data = __dvd_usrdata;
1101 __dvd_usrdata = NULL;
1102 if(pn_data) pn_data[0] = val;
1104 cb = __dvd_finalreadmemcb;
1105 __dvd_finalreadmemcb = NULL;
1106 if(cb) cb(result);
1107 return;
1109 __dvd_stategettingerror();
1112 static void __dvd_cntrldrivecb(s32 result)
1114 #ifdef _DVD_DEBUG
1115 printf("__dvd_cntrldrivecb(%d)\n",result);
1116 #endif
1117 if(result==0x0010) {
1118 __dvd_statetimeout();
1119 return;
1121 if(result==0x0001) {
1122 DVD_LowSpinMotor(__dvd_motorcntrl,__dvd_finalsudcb);
1123 return;
1125 __dvd_stategettingerror();
1128 static void __dvd_setgcmoffsetcb(s32 result)
1130 s64 *pn_data,offset;
1131 #ifdef _DVD_DEBUG
1132 printf("__dvd_setgcmoffsetcb(%d)\n",result);
1133 #endif
1134 if(result==0x0010) {
1135 __dvd_statetimeout();
1136 return;
1138 if(result==0x0001) {
1139 pn_data = (s64*)__dvd_usrdata;
1140 __dvd_usrdata = NULL;
1142 offset = 0;
1143 if(pn_data) offset = *pn_data;
1144 DVD_LowSetOffset(offset,__dvd_finaloffsetcb);
1145 return;
1147 __dvd_stategettingerror();
1150 static void __dvd_handlespinupcb(s32 result)
1152 static u32 step = 0;
1153 #ifdef _DVD_DEBUG
1154 printf("__dvd_handlespinupcb(%d,%d)\n",result,step);
1155 #endif
1156 if(result==0x0010) {
1157 __dvd_statetimeout();
1158 return;
1160 if(result==0x0001) {
1161 if(step==0x0000) {
1162 step++;
1163 _diReg[1] = _diReg[1];
1164 DVD_LowEnableExtensions(__dvd_extensionsenabled,__dvd_handlespinupcb);
1165 return;
1167 if(step==0x0001) {
1168 step++;
1169 _diReg[1] = _diReg[1];
1170 DVD_LowSpinMotor((DVD_SPINMOTOR_ACCEPT|DVD_SPINMOTOR_UP),__dvd_handlespinupcb);
1171 return;
1173 if(step==0x0002) {
1174 step = 0;
1175 if(!__dvd_lasterror) {
1176 _diReg[1] = _diReg[1];
1177 DVD_LowSetStatus((_SHIFTL((DVD_STATUS_DISK_ID_NOT_READ+1),16,8)|0x00000300),__dvd_finalsudcb);
1178 return;
1180 __dvd_finalsudcb(result);
1181 return;
1185 step = 0;
1186 __dvd_stategettingerror();
1189 static void __dvd_fwpatchcb(s32 result)
1191 static u32 step = 0;
1192 #ifdef _DVD_DEBUG
1193 printf("__dvd_fwpatchcb(%d,%d)\n",result,step);
1194 #endif
1195 if(result==0x0010) {
1196 __dvd_statetimeout();
1197 return;
1199 if(result==0x0001) {
1200 if(step==0x0000) {
1201 step++;
1202 _diReg[1] = _diReg[1];
1203 DVD_LowUnlockDrive(__dvd_fwpatchcb);
1204 return;
1206 if(step==0x0001) {
1207 step = 0;
1208 DVD_LowPatchDriveCode(__dvd_finalpatchcb);
1209 return;
1213 step = 0;
1214 __dvd_stategettingerror();
1217 static void __dvd_checkaddonscb(s32 result)
1219 u32 txdsize;
1220 dvdcallbacklow cb;
1221 #ifdef _DVD_DEBUG
1222 printf("__dvd_checkaddonscb(%d)\n",result);
1223 #endif
1224 __dvd_drivechecked = 1;
1225 txdsize = (DVD_DISKIDSIZE-_diReg[6]);
1226 if(result&0x0001) {
1227 // if the read was successful but was interrupted by a break we issue the read again.
1228 if(txdsize!=DVD_DISKIDSIZE) {
1229 _diReg[1] = _diReg[1];
1230 DCInvalidateRange(&__dvd_tmpid0,DVD_DISKIDSIZE);
1231 DVD_LowReadId(&__dvd_tmpid0,__dvd_checkaddonscb);
1232 return;
1234 __dvd_drivestate |= DVD_CHIPPRESENT;
1237 cb = __dvd_finaladdoncb;
1238 __dvd_finaladdoncb = NULL;
1239 if(cb) cb(0x01);
1242 static void __dvd_checkaddons(dvdcallbacklow cb)
1244 #ifdef _DVD_DEBUG
1245 printf("__dvd_checkaddons()\n");
1246 #endif
1247 __dvd_finaladdoncb = cb;
1249 // try to read disc ID.
1250 _diReg[1] = _diReg[1];
1251 DCInvalidateRange(&__dvd_tmpid0,DVD_DISKIDSIZE);
1252 DVD_LowReadId(&__dvd_tmpid0,__dvd_checkaddonscb);
1253 return;
1256 static void __dvd_fwpatchmem(dvdcallbacklow cb)
1258 #ifdef _DVD_DEBUG
1259 printf("__dvd_fwpatchmem()\n");
1260 #endif
1261 __dvd_finalpatchcb = cb;
1263 _diReg[1] = _diReg[1];
1264 DCInvalidateRange(&__dvd_driveinfo,DVD_DRVINFSIZE);
1265 DVD_LowInquiry(&__dvd_driveinfo,__dvd_fwpatchcb);
1266 return;
1269 static void __dvd_handlespinup()
1271 #ifdef _DVD_DEBUG
1272 printf("__dvd_handlespinup()\n");
1273 #endif
1274 _diReg[1] = _diReg[1];
1275 DVD_LowUnlockDrive(__dvd_handlespinupcb);
1276 return;
1279 static void __dvd_spinupdrivecb(s32 result)
1281 #ifdef _DVD_DEBUG
1282 printf("__dvd_spinupdrivecb(%d,%02x,%02x)\n",result,__dvd_resetoccured,__dvd_drivestate);
1283 #endif
1284 if(result==0x0010) {
1285 __dvd_statetimeout();
1286 return;
1288 if(result==0x0001) {
1289 if(!__dvd_drivechecked) {
1290 __dvd_checkaddons(__dvd_spinupdrivecb);
1291 return;
1293 if(!(__dvd_drivestate&DVD_CHIPPRESENT)) {
1294 if(!(__dvd_drivestate&DVD_INTEROPER)) {
1295 if(!(__dvd_drivestate&DVD_DRIVERESET)) {
1296 DVD_Reset(DVD_RESETHARD);
1297 udelay(1150*1000);
1299 __dvd_fwpatchmem(__dvd_spinupdrivecb);
1300 return;
1302 __dvd_handlespinup();
1303 return;
1306 __dvd_finalsudcb(result);
1307 return;
1309 __dvd_stategettingerror();
1312 static void __dvd_statecoverclosed_spinupcb(s32 result)
1314 DCInvalidateRange(&__dvd_tmpid0,DVD_DISKIDSIZE);
1315 __dvd_laststate = __dvd_statecoverclosed_cmd;
1316 __dvd_statecoverclosed_cmd(__dvd_executing);
1319 static void __DVDInterruptHandler(u32 nIrq,void *pCtx)
1321 s64 now;
1322 u32 status,ir,irm,irmm,diff;
1323 dvdcallbacklow cb;
1325 SYS_CancelAlarm(__dvd_timeoutalarm);
1327 irmm = 0;
1328 if(__dvd_lastcmdwasread) {
1329 __dvd_cmd_prev.buf = __dvd_cmd_curr.buf;
1330 __dvd_cmd_prev.len = __dvd_cmd_curr.len;
1331 __dvd_cmd_prev.offset = __dvd_cmd_curr.offset;
1332 if(__dvd_stopnextint) irmm |= 0x0008;
1334 __dvd_lastcmdwasread = 0;
1335 __dvd_stopnextint = 0;
1337 status = _diReg[0];
1338 irm = (status&(DVD_DE_MSK|DVD_TC_MSK|DVD_BRK_MSK));
1339 ir = ((status&(DVD_DE_INT|DVD_TC_INT|DVD_BRK_INT))&(irm<<1));
1340 #ifdef _DVD_DEBUG
1341 printf("__DVDInterruptHandler(status: %08x,irm: %08x,ir: %08x (%d))\n",status,irm,ir,__dvd_resetoccured);
1342 #endif
1343 if(ir&DVD_BRK_INT) irmm |= 0x0008;
1344 if(ir&DVD_TC_INT) irmm |= 0x0001;
1345 if(ir&DVD_DE_INT) irmm |= 0x0002;
1347 if(irmm) __dvd_resetoccured = 0;
1349 _diReg[0] = (ir|irm);
1351 now = gettime();
1352 diff = diff_msec(__dvd_lastresetend,now);
1353 if(__dvd_resetoccured && diff>200) {
1354 status = _diReg[1];
1355 irm = status&DVD_CVR_MSK;
1356 ir = (status&DVD_CVR_INT)&(irm<<1);
1357 if(ir&0x0004) {
1358 cb = __dvd_resetcovercb;
1359 __dvd_resetcovercb = NULL;
1360 if(cb) {
1361 cb(0x0004);
1364 _diReg[1] = _diReg[1];
1365 } else {
1366 if(__dvd_waitcoverclose) {
1367 status = _diReg[1];
1368 irm = status&DVD_CVR_MSK;
1369 ir = (status&DVD_CVR_INT)&(irm<<1);
1370 if(ir&DVD_CVR_INT) irmm |= 0x0004;
1371 _diReg[1] = (ir|irm);
1372 __dvd_waitcoverclose = 0;
1373 } else
1374 _diReg[1] = 0;
1377 if(irmm&0x0008) {
1378 if(!__dvd_breaking) irmm &= ~0x0008;
1381 if(irmm&0x0001) {
1382 if(__ProcessNextCmd()) return;
1383 } else {
1384 __dvd_cmdlist[0].cmd = -1;
1385 __dvd_nextcmdnum = 0;
1388 cb = __dvd_callback;
1389 __dvd_callback = NULL;
1390 if(cb) cb(irmm);
1392 __dvd_breaking = 0;
1395 static void __dvd_patchdrivecb(s32 result)
1397 u32 cnt = 0;
1398 static u32 cmd_buf[3];
1399 static u32 stage = 0;
1400 static u32 nPos = 0;
1401 static u32 drv_address = 0x0040d000;
1402 const u32 chunk_size = 3*sizeof(u32);
1404 #ifdef _DVD_DEBUG
1405 printf("__DVDPatchDriveCode()\n");
1406 #endif
1407 if(__dvdpatchcode==NULL || __dvdpatchcode_size<=0) return;
1409 while(stage!=0x0003) {
1410 __dvd_callback = __dvd_patchdrivecb;
1411 if(stage==0x0000) {
1412 #ifdef _DVD_DEBUG
1413 printf("__DVDPatchDriveCode(0x%08x,%02x,%d)\n",drv_address,stage,nPos);
1414 #endif
1415 for(cnt=0;cnt<chunk_size && nPos<__dvdpatchcode_size;cnt++,nPos++) ((u8*)cmd_buf)[cnt] = __dvdpatchcode[nPos];
1417 if(nPos>=__dvdpatchcode_size) stage = 0x0002;
1418 else stage = 0x0001;
1420 _diReg[1] = _diReg[1];
1421 _diReg[2] = DVD_FWWRITEMEM;
1422 _diReg[3] = drv_address;
1423 _diReg[4] = _SHIFTL(cnt,16,16);
1424 _diReg[7] = (DVD_DI_DMA|DVD_DI_START);
1426 drv_address += cnt;
1427 return;
1430 if(stage>=0x0001) {
1431 #ifdef _DVD_DEBUG
1432 printf("__DVDPatchDriveCode(%02x)\n",stage);
1433 #endif
1434 if(stage>0x0001) stage = 0x0003;
1435 else stage = 0;
1437 _diReg[1] = _diReg[1];
1438 _diReg[2] = cmd_buf[0];
1439 _diReg[3] = cmd_buf[1];
1440 _diReg[4] = cmd_buf[2];
1441 _diReg[7] = DVD_DI_START;
1442 return;
1445 __dvd_callback = NULL;
1446 __dvdpatchcode = NULL;
1447 __dvd_drivestate |= DVD_INTEROPER;
1448 DVD_LowFuncCall(0x0040d000,__dvd_finalpatchcb);
1452 static void __dvd_unlockdrivecb(s32 result)
1454 u32 i;
1455 #ifdef _DVD_DEBUG
1456 printf("__DVDUnlockDrive(%d)\n",result);
1457 #endif
1458 __dvd_callback = __dvd_finalunlockcb;
1459 _diReg[1] = _diReg[1];
1460 for(i=0;i<3;i++) _diReg[2+i] = ((u32*)__dvd_unlockcmd$222)[i];
1461 _diReg[7] = DVD_DI_START;
1464 void __dvd_resetasync(dvdcbcallback cb)
1466 u32 level;
1468 _CPU_ISR_Disable(level);
1469 __dvd_clearwaitingqueue();
1470 if(__dvd_canceling) __dvd_cancelcallback = cb;
1471 else {
1472 if(__dvd_executing) __dvd_executing->cb = NULL;
1473 DVD_CancelAllAsync(cb);
1475 _CPU_ISR_Restore(level);
1478 void __dvd_statebusy(dvdcmdblk *block)
1480 u32 len;
1481 #ifdef _DVD_DEBUG
1482 printf("__dvd_statebusy(%p)\n",block);
1483 #endif
1484 __dvd_laststate = __dvd_statebusy;
1485 if(block->cmd>DVD_MAXCOMMANDS) return;
1487 switch(block->cmd) {
1488 case 1: //Read(Sector)
1489 case 4:
1490 _diReg[1] = _diReg[1];
1491 len = block->len-block->txdsize;
1492 if(len<0x80000) block->currtxsize = len;
1493 else block->currtxsize = 0x80000;
1494 DVD_LowRead(block->buf+block->txdsize,block->currtxsize,(block->offset+block->txdsize),__dvd_statebusycb);
1495 return;
1496 case 2: //Seek(Sector)
1497 _diReg[1] = _diReg[1];
1498 DVD_LowSeek(block->offset,__dvd_statebusycb);
1499 return;
1500 case 3:
1501 case 15:
1502 DVD_LowStopMotor(__dvd_statebusycb);
1503 return;
1504 case 5: //ReadDiskID
1505 _diReg[1] = _diReg[1];
1506 block->currtxsize = DVD_DISKIDSIZE;
1507 DVD_LowReadId(block->buf,__dvd_statebusycb);
1508 return;
1509 case 6:
1510 _diReg[1] = _diReg[1];
1511 if(__dvd_autofinishing) {
1512 __dvd_executing->currtxsize = 0;
1513 DVD_LowRequestAudioStatus(0,__dvd_statebusycb);
1514 } else {
1515 __dvd_executing->currtxsize = 1;
1516 DVD_LowAudioStream(0,__dvd_executing->len,__dvd_executing->offset,__dvd_statebusycb);
1518 return;
1519 case 7:
1520 _diReg[1] = _diReg[1];
1521 DVD_LowAudioStream(0x00010000,0,0,__dvd_statebusycb);
1522 return;
1523 case 8:
1524 _diReg[1] = _diReg[1];
1525 __dvd_autofinishing = 1;
1526 DVD_LowAudioStream(0,0,0,__dvd_statebusycb);
1527 return;
1528 case 9:
1529 _diReg[1] = _diReg[1];
1530 DVD_LowRequestAudioStatus(0,__dvd_statebusycb);
1531 return;
1532 case 10:
1533 _diReg[1] = _diReg[1];
1534 DVD_LowRequestAudioStatus(0x00010000,__dvd_statebusycb);
1535 return;
1536 case 11:
1537 _diReg[1] = _diReg[1];
1538 DVD_LowRequestAudioStatus(0x00020000,__dvd_statebusycb);
1539 return;
1540 case 12:
1541 _diReg[1] = _diReg[1];
1542 DVD_LowRequestAudioStatus(0x00030000,__dvd_statebusycb);
1543 return;
1544 case 13:
1545 _diReg[1] = _diReg[1];
1546 DVD_LowAudioBufferConfig(__dvd_executing->offset,__dvd_executing->len,__dvd_statebusycb);
1547 return;
1548 case 14: //Inquiry
1549 _diReg[1] = _diReg[1];
1550 block->currtxsize = 0x20;
1551 DVD_LowInquiry(block->buf,__dvd_statebusycb);
1552 return;
1553 case 16:
1554 __dvd_lasterror = 0;
1555 __dvd_extensionsenabled = TRUE;
1556 DVD_LowSpinUpDrive(__dvd_statebusycb);
1557 return;
1558 case 17:
1559 _diReg[1] = _diReg[1];
1560 DVD_LowControlMotor(block->offset,__dvd_statebusycb);
1561 return;
1562 case 18:
1563 _diReg[1] = _diReg[1];
1564 DVD_LowSetGCMOffset(block->offset,__dvd_statebusycb);
1565 return;
1566 default:
1567 return;
1571 void __dvd_stateready()
1573 dvdcmdblk *block;
1574 #ifdef _DVD_DEBUG
1575 printf("__dvd_stateready()\n");
1576 #endif
1577 if(!__dvd_checkwaitingqueue()) {
1578 __dvd_executing = NULL;
1579 return;
1582 __dvd_executing = __dvd_popwaitingqueue();
1584 if(__dvd_fatalerror) {
1585 __dvd_executing->state = -1;
1586 block = __dvd_executing;
1587 __dvd_executing = &__dvd_dummycmdblk;
1588 if(block->cb) block->cb(-1,block);
1589 __dvd_stateready();
1590 return;
1593 __dvd_currcmd = __dvd_executing->cmd;
1595 if(__dvd_resumefromhere) {
1596 if(__dvd_resumefromhere<=7) {
1597 switch(__dvd_resumefromhere) {
1598 case 1:
1599 __dvd_executing->state = 6;
1600 __dvd_statemotorstopped();
1601 break;
1602 case 2:
1603 __dvd_executing->state = 11;
1604 __dvd_statemotorstopped();
1605 break;
1606 case 3:
1607 __dvd_executing->state = 4;
1608 __dvd_statemotorstopped();
1609 break;
1610 case 4:
1611 __dvd_executing->state = 5;
1612 __dvd_statemotorstopped();
1613 break;
1614 case 5:
1615 __dvd_executing->state = -1;
1616 __dvd_stateerror(__dvd_cancellasterror);
1617 break;
1618 case 6:
1619 __dvd_executing->state = 3;
1620 __dvd_statecoverclosed();
1621 break;
1622 case 7:
1623 __dvd_executing->state = 7;
1624 __dvd_statemotorstopped();
1625 break;
1626 default:
1627 break;
1631 __dvd_resumefromhere = 0;
1632 return;
1634 __dvd_executing->state = 1;
1635 __dvd_statebusy(__dvd_executing);
1638 void __dvd_statecoverclosed()
1640 dvdcmdblk *blk;
1641 #ifdef _DVD_DEBUG
1642 printf("__dvd_statecoverclosed(%d)\n",__dvd_currcmd);
1643 #endif
1644 if(__dvd_currcmd==0x0004 || __dvd_currcmd==0x0005
1645 || __dvd_currcmd==0x000d || __dvd_currcmd==0x000f
1646 || __dvd_currcmd==0x0010) {
1647 __dvd_clearwaitingqueue();
1648 blk = __dvd_executing;
1649 __dvd_executing = &__dvd_dummycmdblk;
1650 if(blk->cb) blk->cb(-4,blk);
1651 __dvd_stateready();
1652 } else {
1653 __dvd_extensionsenabled = TRUE;
1654 DVD_LowSpinUpDrive(__dvd_statecoverclosed_spinupcb);
1658 void __dvd_statecoverclosed_cmd(dvdcmdblk *block)
1660 #ifdef _DVD_DEBUG
1661 printf("__dvd_statecoverclosed_cmd(%d)\n",__dvd_currcmd);
1662 #endif
1663 DVD_LowReadId(&__dvd_tmpid0,__dvd_statecoverclosedcb);
1666 void __dvd_statemotorstopped()
1668 #ifdef _DVD_DEBUG
1669 printf("__dvd_statemotorstopped(%d)\n",__dvd_executing->state);
1670 #endif
1671 DVD_LowWaitCoverClose(__dvd_statemotorstoppedcb);
1674 void __dvd_stateerror(s32 result)
1676 #ifdef _DVD_DEBUG
1677 printf("__dvd_stateerror(%08x)\n",result);
1678 #endif
1679 __dvd_storeerror(result);
1680 DVD_LowStopMotor(__dvd_stateerrorcb);
1683 void __dvd_stategettingerror()
1685 #ifdef _DVD_DEBUG
1686 printf("__dvd_stategettingerror()\n");
1687 #endif
1688 DVD_LowRequestError(__dvd_stategettingerrorcb);
1691 void __dvd_statecheckid2(dvdcmdblk *block)
1696 void __dvd_statecheckid()
1698 dvdcmdblk *blk;
1699 #ifdef _DVD_DEBUG
1700 printf("__dvd_statecheckid(%02x)\n",__dvd_currcmd);
1701 #endif
1702 if(__dvd_currcmd==0x0003) {
1703 if(memcmp(&__dvd_dummycmdblk,&__dvd_executing,sizeof(dvdcmdblk))) {
1704 DVD_LowStopMotor(__dvd_statecheckid1cb);
1705 return;
1707 memcpy(__dvd_diskID,&__dvd_tmpid0,DVD_DISKIDSIZE);
1709 __dvd_executing->state = 1;
1710 DCInvalidateRange(&__dvd_tmpid0,DVD_DISKIDSIZE);
1711 __dvd_laststate = __dvd_statecheckid2;
1712 __dvd_statecheckid2(__dvd_executing);
1713 return;
1715 if(__dvd_currcmd==0x0010) {
1716 blk = __dvd_executing;
1717 blk->state = 0;
1718 __dvd_executing = &__dvd_dummycmdblk;
1719 if(blk->cb) blk->cb(0,blk);
1720 __dvd_stateready();
1721 return;
1723 if(__dvd_currcmd!=0x0005 && memcmp(__dvd_diskID,&__dvd_tmpid0,DVD_DISKIDSIZE)) {
1724 blk = __dvd_executing;
1725 blk->state = -1;
1726 __dvd_executing = &__dvd_dummycmdblk;
1727 if(blk->cb) blk->cb(-1,blk); //terminate current operation
1728 if(__dvd_mountusrcb) __dvd_mountusrcb(DVD_DISKIDSIZE,blk); //if we came across here, notify user callback of successful remount
1729 __dvd_stateready();
1730 return;
1732 __dvd_statebusy(__dvd_executing);
1735 void __dvd_statetimeout()
1737 __dvd_storeerror(0x01234568);
1738 DVD_Reset(DVD_RESETSOFT);
1739 __dvd_stateerrorcb(0);
1742 void __dvd_stategotoretry()
1744 DVD_LowStopMotor(__dvd_stategotoretrycb);
1747 s32 __issuecommand(s32 prio,dvdcmdblk *block)
1749 s32 ret;
1750 u32 level;
1751 #ifdef _DVD_DEBUG
1752 printf("__issuecommand(%d,%p,%p)\n",prio,block,block->cb);
1753 printf("__issuecommand(%p)\n",__dvd_waitingqueue[prio].first);
1754 #endif
1755 if(__dvd_autoinvalidation &&
1756 (block->cmd==0x0001 || block->cmd==0x00004
1757 || block->cmd==0x0005 || block->cmd==0x000e)) DCInvalidateRange(block->buf,block->len);
1759 _CPU_ISR_Disable(level);
1760 block->state = 0x0002;
1761 ret = __dvd_pushwaitingqueue(prio,block);
1762 if(!__dvd_executing) __dvd_stateready();
1763 _CPU_ISR_Restore(level);
1764 return ret;
1767 s32 DVD_LowUnlockDrive(dvdcallbacklow cb)
1769 #ifdef _DVD_DEBUG
1770 printf("DVD_LowUnlockDrive()\n");
1771 #endif
1772 u32 i;
1774 __dvd_callback = __dvd_unlockdrivecb;
1775 __dvd_finalunlockcb = cb;
1776 __dvd_stopnextint = 0;
1778 for(i=0;i<3;i++) _diReg[2+i] = ((u32*)__dvd_unlockcmd$221)[i];
1779 _diReg[7] = DVD_DI_START;
1781 return 1;
1784 s32 DVD_LowPatchDriveCode(dvdcallbacklow cb)
1786 #ifdef _DVD_DEBUG
1787 printf("DVD_LowPatchDriveCode(%08x)\n",__dvd_driveinfo.rel_date);
1788 #endif
1789 __dvd_finalpatchcb = cb;
1790 __dvd_stopnextint = 0;
1792 if(__dvd_driveinfo.rel_date==DVD_MODEL04) {
1793 __dvdpatchcode = __dvd_patchcode04;
1794 __dvdpatchcode_size = __dvd_patchcode04_size;
1795 } else if((__dvd_driveinfo.rel_date&0x0000ff00)==0x00000500) { // for wii: since i don't know the real date i have to mask & compare.
1796 } else if(__dvd_driveinfo.rel_date==DVD_MODEL06) {
1797 __dvdpatchcode = __dvd_patchcode06;
1798 __dvdpatchcode_size = __dvd_patchcode06_size;
1799 } else if(__dvd_driveinfo.rel_date==DVD_MODEL08) {
1800 __dvdpatchcode = __dvd_patchcode08;
1801 __dvdpatchcode_size = __dvd_patchcode08_size;
1802 } else if(__dvd_driveinfo.rel_date==DVD_MODEL08Q) {
1803 __dvdpatchcode = __dvd_patchcodeQ08;
1804 __dvdpatchcode_size = __dvd_patchcodeQ08_size;
1805 } else if((__dvd_driveinfo.rel_date&0x0000ff00)==0x00000900) { // for wii: since i don't know the real date i have to mask & compare.
1806 } else {
1807 __dvdpatchcode = NULL;
1808 __dvdpatchcode_size = 0;
1811 __dvd_patchdrivecb(0);
1812 return 1;
1815 s32 DVD_LowSetOffset(s64 offset,dvdcallbacklow cb)
1817 #ifdef _DVD_DEBUG
1818 printf("DVD_LowSetOffset(%08x)\n",offset);
1819 #endif
1820 __dvd_stopnextint = 0;
1821 __dvd_callback = cb;
1823 _diReg[2] = DVD_FWSETOFFSET;
1824 _diReg[3] = (u32)(offset>>2);
1825 _diReg[4] = 0;
1826 _diReg[7] = DVD_DI_START;
1828 return 1;
1831 s32 DVD_LowSetGCMOffset(s64 offset,dvdcallbacklow cb)
1833 static s64 loc_offset = 0;
1834 #ifdef _DVD_DEBUG
1835 printf("DVD_LowSetGCMOffset(%08x)\n",offset);
1836 #endif
1837 loc_offset = offset;
1839 __dvd_finaloffsetcb = cb;
1840 __dvd_stopnextint = 0;
1841 __dvd_usrdata = &loc_offset;
1843 DVD_LowUnlockDrive(__dvd_setgcmoffsetcb);
1844 return 1;
1847 s32 DVD_LowReadmem(u32 address,void *buffer,dvdcallbacklow cb)
1849 #ifdef _DVD_DEBUG
1850 printf("DVD_LowReadmem(0x%08x,%p)\n",address,buffer);
1851 #endif
1852 __dvd_finalreadmemcb = cb;
1853 __dvd_usrdata = buffer;
1854 __dvd_callback = __dvd_readmemcb;
1855 __dvd_stopnextint = 0;
1857 _diReg[2] = DVD_FWREADMEM;
1858 _diReg[3] = address;
1859 _diReg[4] = 0x00010000;
1860 _diReg[7] = DVD_DI_START;
1862 return 1;
1865 s32 DVD_LowFuncCall(u32 address,dvdcallbacklow cb)
1867 #ifdef _DVD_DEBUG
1868 printf("DVD_LowFuncCall(0x%08x)\n",address);
1869 #endif
1870 __dvd_callback = cb;
1871 __dvd_stopnextint = 0;
1873 _diReg[2] = DVD_FWFUNCCALL;
1874 _diReg[3] = address;
1875 _diReg[4] = 0x66756E63;
1876 _diReg[7] = DVD_DI_START;
1878 return 1;
1881 s32 DVD_LowSpinMotor(u32 mode,dvdcallbacklow cb)
1883 #ifdef _DVD_DEBUG
1884 printf("DVD_LowSpinMotor(%08x)\n",mode);
1885 #endif
1886 __dvd_callback = cb;
1887 __dvd_stopnextint = 0;
1889 _diReg[2] = DVD_FWCTRLMOTOR|(mode&0x0000ff00);
1890 _diReg[3] = 0;
1891 _diReg[4] = 0;
1892 _diReg[7] = DVD_DI_START;
1894 return 1;
1897 s32 DVD_LowEnableExtensions(u8 enable,dvdcallbacklow cb)
1899 #ifdef _DVD_DEBUG
1900 printf("DVD_LowEnableExtensions(%02x)\n",enable);
1901 #endif
1902 __dvd_callback = cb;
1903 __dvd_stopnextint = 0;
1905 _diReg[2] = (DVD_FWENABLEEXT|_SHIFTL(enable,16,8));
1906 _diReg[3] = 0;
1907 _diReg[4] = 0;
1908 _diReg[7] = DVD_DI_START;
1910 return 1;
1913 s32 DVD_LowSetStatus(u32 status,dvdcallbacklow cb)
1915 #ifdef _DVD_DEBUG
1916 printf("DVD_LowSetStatus(%08x)\n",status);
1917 #endif
1918 __dvd_callback = cb;
1919 __dvd_stopnextint = 0;
1921 _diReg[2] = (DVD_FWSETSTATUS|(status&0x00ffffff));
1922 _diReg[3] = 0;
1923 _diReg[4] = 0;
1924 _diReg[7] = DVD_DI_START;
1926 return 1;
1929 s32 DVD_LowGetStatus(u32 *status,dvdcallbacklow cb)
1931 #ifdef _DVD_DEBUG
1932 printf("DVD_LowSetStatus(%08x)\n",status);
1933 #endif
1934 __dvd_finalstatuscb = cb;
1935 __dvd_usrdata = status;
1937 DVD_LowRequestError(__dvd_getstatuscb);
1938 return 1;
1941 s32 DVD_LowControlMotor(u32 mode,dvdcallbacklow cb)
1943 #ifdef _DVD_DEBUG
1944 printf("DVD_LowControlMotor(%08x)\n",mode);
1945 #endif
1946 __dvd_stopnextint = 0;
1947 __dvd_motorcntrl = mode;
1948 __dvd_finalsudcb = cb;
1949 DVD_LowUnlockDrive(__dvd_cntrldrivecb);
1951 return 1;
1955 s32 DVD_LowSpinUpDrive(dvdcallbacklow cb)
1957 #ifdef _DVD_DEBUG
1958 printf("DVD_LowSpinUpDrive()\n");
1959 #endif
1960 __dvd_finalsudcb = cb;
1961 __dvd_spinupdrivecb(1);
1963 return 1;
1966 s32 DVD_LowRead(void *buf,u32 len,s64 offset,dvdcallbacklow cb)
1968 #ifdef _DVD_DEBUG
1969 printf("DVD_LowRead(%p,%d,%d)\n",buf,len,offset);
1970 #endif
1971 _diReg[6] = len;
1973 __dvd_cmd_curr.buf = buf;
1974 __dvd_cmd_curr.len = len;
1975 __dvd_cmd_curr.offset = offset;
1976 __DoRead(buf,len,offset,cb);
1977 return 1;
1980 s32 DVD_LowSeek(s64 offset,dvdcallbacklow cb)
1982 #ifdef _DVD_DEBUG
1983 printf("DVD_LowSeek(%d)\n",offset);
1984 #endif
1985 struct timespec tb;
1987 __dvd_callback = cb;
1988 __dvd_stopnextint = 0;
1990 _diReg[2] = DVD_SEEKSECTOR;
1991 _diReg[3] = (u32)(offset>>2);
1992 _diReg[7] = DVD_DI_START;
1994 tb.tv_sec = 10;
1995 tb.tv_nsec = 0;
1996 __SetupTimeoutAlarm(&tb);
1998 return 1;
2001 s32 DVD_LowReadId(dvddiskid *diskID,dvdcallbacklow cb)
2003 #ifdef _DVD_DEBUG
2004 printf("DVD_LowReadId(%p)\n",diskID);
2005 #endif
2006 struct timespec tb;
2008 __dvd_callback = cb;
2009 __dvd_stopnextint = 0;
2011 _diReg[2] = DVD_READDISKID;
2012 _diReg[3] = 0;
2013 _diReg[4] = DVD_DISKIDSIZE;
2014 _diReg[5] = (u32)diskID;
2015 _diReg[6] = DVD_DISKIDSIZE;
2016 _diReg[7] = (DVD_DI_DMA|DVD_DI_START);
2018 tb.tv_sec = 10;
2019 tb.tv_nsec = 0;
2020 __SetupTimeoutAlarm(&tb);
2022 return 1;
2025 s32 DVD_LowRequestError(dvdcallbacklow cb)
2027 #ifdef _DVD_DEBUG
2028 printf("DVD_LowRequestError()\n");
2029 #endif
2030 struct timespec tb;
2032 __dvd_callback = cb;
2033 __dvd_stopnextint = 0;
2035 _diReg[2] = DVD_REQUESTERROR;
2036 _diReg[7] = DVD_DI_START;
2038 tb.tv_sec = 10;
2039 tb.tv_nsec = 0;
2040 __SetupTimeoutAlarm(&tb);
2042 return 1;
2045 s32 DVD_LowStopMotor(dvdcallbacklow cb)
2047 #ifdef _DVD_DEBUG
2048 printf("DVD_LowStopMotor()\n");
2049 #endif
2050 struct timespec tb;
2052 __dvd_callback = cb;
2053 __dvd_stopnextint = 0;
2055 _diReg[2] = DVD_STOPMOTOR;
2056 _diReg[7] = DVD_DI_START;
2058 tb.tv_sec = 10;
2059 tb.tv_nsec = 0;
2060 __SetupTimeoutAlarm(&tb);
2062 return 1;
2065 s32 DVD_LowInquiry(dvddrvinfo *info,dvdcallbacklow cb)
2067 #ifdef _DVD_DEBUG
2068 printf("DVD_LowInquiry(%p)\n",info);
2069 #endif
2070 struct timespec tb;
2072 __dvd_callback = cb;
2073 __dvd_stopnextint = 0;
2075 _diReg[2] = DVD_DVDINQUIRY;
2076 _diReg[4] = 0x20;
2077 _diReg[5] = (u32)info;
2078 _diReg[6] = 0x20;
2079 _diReg[7] = (DVD_DI_DMA|DVD_DI_START);
2081 tb.tv_sec = 10;
2082 tb.tv_nsec = 0;
2083 __SetupTimeoutAlarm(&tb);
2085 return 1;
2088 s32 DVD_LowWaitCoverClose(dvdcallbacklow cb)
2090 #ifdef _DVD_DEBUG
2091 printf("DVD_LowWaitCoverClose()\n");
2092 #endif
2093 __dvd_callback = cb;
2094 __dvd_waitcoverclose = 1;
2095 __dvd_stopnextint = 0;
2096 _diReg[1] = DVD_CVR_MSK;
2097 return 1;
2100 void DVD_LowReset(u32 reset_mode)
2102 u32 val;
2104 _diReg[1] = DVD_CVR_MSK;
2105 val = _piReg[9];
2106 _piReg[9] = ((val&~0x0004)|0x0001);
2108 udelay(12);
2110 if(reset_mode==DVD_RESETHARD) val |= 0x0004;
2111 val |= 0x0001;
2112 _piReg[9] = val;
2114 __dvd_resetoccured = 1;
2115 __dvd_lastresetend = gettime();
2116 __dvd_drivestate |= DVD_DRIVERESET;
2119 s32 DVD_LowAudioStream(u32 subcmd,u32 len,s64 offset,dvdcallbacklow cb)
2121 #ifdef _DVD_DEBUG
2122 printf("DVD_LowAudioStream(%08x,%d,%08x,%p)\n",subcmd,len,offset,cb);
2123 #endif
2124 struct timespec tb;
2126 __dvd_callback = cb;
2127 __dvd_stopnextint = 0;
2129 _diReg[2] = DVD_AUDIOSTREAM|subcmd;
2130 _diReg[3] = (u32)(offset>>2);
2131 _diReg[4] = len;
2132 _diReg[7] = DVD_DI_START;
2134 tb.tv_sec = 10;
2135 tb.tv_nsec = 0;
2136 __SetupTimeoutAlarm(&tb);
2138 return 1;
2141 s32 DVD_LowAudioBufferConfig(s32 enable,u32 size,dvdcallbacklow cb)
2143 #ifdef _DVD_DEBUG
2144 printf("DVD_LowAudioBufferConfig(%02x,%d,%p)\n",enable,size,cb);
2145 #endif
2146 u32 val;
2147 struct timespec tb;
2149 __dvd_callback = cb;
2150 __dvd_stopnextint = 0;
2152 val = 0;
2153 if(enable) {
2154 val |= 0x00010000;
2155 if(!size) val |= 0x0000000a;
2158 _diReg[2] = DVD_AUDIOCONFIG|val;
2159 _diReg[7] = DVD_DI_START;
2161 tb.tv_sec = 10;
2162 tb.tv_nsec = 0;
2163 __SetupTimeoutAlarm(&tb);
2165 return 1;
2168 s32 DVD_LowRequestAudioStatus(u32 subcmd,dvdcallbacklow cb)
2170 #ifdef _DVD_DEBUG
2171 printf("DVD_LowRequestAudioStatus(%08x,%p)\n",subcmd,cb);
2172 #endif
2173 struct timespec tb;
2175 __dvd_callback = cb;
2176 __dvd_stopnextint = 0;
2178 _diReg[2] = DVD_AUDIOSTATUS|subcmd;
2179 _diReg[7] = DVD_DI_START;
2181 tb.tv_sec = 10;
2182 tb.tv_nsec = 0;
2183 __SetupTimeoutAlarm(&tb);
2185 return 1;
2188 //special, only used in bios replacement. therefor only there extern'd
2189 s32 __DVDAudioBufferConfig(dvdcmdblk *block,u32 enable,u32 size,dvdcbcallback cb)
2191 if(!block) return 0;
2193 block->cmd = 0x000d;
2194 block->offset = enable;
2195 block->len = size;
2196 block->cb = cb;
2198 return __issuecommand(2,block);
2201 s32 DVD_ReadDiskID(dvdcmdblk *block,dvddiskid *id,dvdcbcallback cb)
2203 #ifdef _DVD_DEBUG
2204 printf("DVD_ReadDiskID(%p,%p)\n",block,id);
2205 #endif
2206 if(!block || !id) return 0;
2208 block->cmd = 0x0005;
2209 block->buf = id;
2210 block->len = DVD_DISKIDSIZE;
2211 block->offset = 0;
2212 block->txdsize = 0;
2213 block->cb = cb;
2215 return __issuecommand(2,block);
2218 s32 DVD_ReadAbsAsyncPrio(dvdcmdblk *block,void *buf,u32 len,s64 offset,dvdcbcallback cb,s32 prio)
2220 #ifdef _DVD_DEBUG
2221 printf("DVD_ReadAbsAsyncPrio(%p,%p,%d,%d,%d)\n",block,buf,len,offset,prio);
2222 #endif
2223 block->cmd = 0x0001;
2224 block->buf = buf;
2225 block->len = len;
2226 block->offset = offset;
2227 block->txdsize = 0;
2228 block->cb = cb;
2230 return __issuecommand(prio,block);
2233 s32 DVD_ReadAbsAsyncForBS(dvdcmdblk *block,void *buf,u32 len,s64 offset,dvdcbcallback cb)
2235 #ifdef _DVD_DEBUG
2236 printf("DVD_ReadAbsAsyncForBS(%p,%p,%d,%d)\n",block,buf,len,offset);
2237 #endif
2238 block->cmd = 0x0004;
2239 block->buf = buf;
2240 block->len = len;
2241 block->offset = offset;
2242 block->txdsize = 0;
2243 block->cb = cb;
2245 return __issuecommand(2,block);
2248 s32 DVD_SeekAbsAsyncPrio(dvdcmdblk *block,s64 offset,dvdcbcallback cb,s32 prio)
2250 block->cmd = 0x0002;
2251 block->offset = offset;
2252 block->cb = cb;
2254 return __issuecommand(prio,block);
2257 s32 DVD_InquiryAsync(dvdcmdblk *block,dvddrvinfo *info,dvdcbcallback cb)
2259 #ifdef _DVD_DEBUG
2260 printf("DVD_InquiryAsync(%p,%p,%p)\n",block,info,cb);
2261 #endif
2262 block->cmd = 0x000e;
2263 block->buf = info;
2264 block->len = 0x20;
2265 block->txdsize = 0;
2266 block->cb = cb;
2267 #ifdef _DVD_DEBUG
2268 printf("DVD_InquiryAsync(%p,%p)\n",block,block->cb);
2269 #endif
2270 return __issuecommand(2,block);
2273 s32 DVD_Inquiry(dvdcmdblk *block,dvddrvinfo *info)
2275 u32 level;
2276 s32 state,ret;
2277 #ifdef _DVD_DEBUG
2278 printf("DVD_Inquiry(%p,%p)\n",block,info);
2279 #endif
2280 ret = DVD_InquiryAsync(block,info,__dvd_inquirysynccb);
2281 if(!ret) return -1;
2283 _CPU_ISR_Disable(level);
2284 do {
2285 state = block->state;
2286 if(state==0) ret = block->txdsize;
2287 else if(state==-1) ret = -1;
2288 else if(state==10) ret = -3;
2289 else LWP_ThreadSleep(__dvd_wait_queue);
2290 } while(state!=0 && state!=-1 && state!=10);
2291 _CPU_ISR_Restore(level);
2292 return ret;
2295 s32 DVD_ReadPrio(dvdcmdblk *block,void *buf,u32 len,s64 offset,s32 prio)
2297 u32 level;
2298 s32 state,ret;
2299 #ifdef _DVD_DEBUG
2300 printf("DVD_ReadPrio(%p,%p,%d,%d,%d)\n",block,buf,len,offset,prio);
2301 #endif
2302 if(offset>=0 && offset<8511160320LL) {
2303 ret = DVD_ReadAbsAsyncPrio(block,buf,len,offset,__dvd_readsynccb,prio);
2304 if(!ret) return -1;
2306 _CPU_ISR_Disable(level);
2307 do {
2308 state = block->state;
2309 if(state==0) ret = block->txdsize;
2310 else if(state==-1) ret = -1;
2311 else if(state==10) ret = -3;
2312 else LWP_ThreadSleep(__dvd_wait_queue);
2313 } while(state!=0 && state!=-1 && state!=10);
2314 _CPU_ISR_Restore(level);
2315 return ret;
2317 return -1;
2320 s32 DVD_SeekPrio(dvdcmdblk *block,s64 offset,s32 prio)
2322 u32 level;
2323 s32 state,ret;
2324 #ifdef _DVD_DEBUG
2325 printf("DVD_SeekPrio(%p,%d,%d)\n",block,offset,prio);
2326 #endif
2327 if(offset>0 && offset<8511160320LL) {
2328 ret = DVD_SeekAbsAsyncPrio(block,offset,__dvd_seeksynccb,prio);
2329 if(!ret) return -1;
2331 _CPU_ISR_Disable(level);
2332 do {
2333 state = block->state;
2334 if(state==0) ret = 0;
2335 else if(state==-1) ret = -1;
2336 else if(state==10) ret = -3;
2337 else LWP_ThreadSleep(__dvd_wait_queue);
2338 } while(state!=0 && state!=-1 && state!=10);
2339 _CPU_ISR_Restore(level);
2341 return ret;
2343 return -1;
2346 s32 DVD_CancelAllAsync(dvdcbcallback cb)
2348 u32 level;
2349 #ifdef _DVD_DEBUG
2350 printf("DVD_CancelAllAsync(%p)\n",cb);
2351 #endif
2352 _CPU_ISR_Disable(level);
2353 DVD_Pause();
2354 _CPU_ISR_Restore(level);
2355 return 1;
2358 s32 DVD_StopStreamAtEndAsync(dvdcmdblk *block,dvdcbcallback cb)
2360 #ifdef _DVD_DEBUG
2361 printf("DVD_StopStreamAtEndAsync(%p,%p)\n",block,cb);
2362 #endif
2363 block->cmd = 0x08;
2364 block->cb = cb;
2365 return __issuecommand(1,block);
2368 s32 DVD_StopStreamAtEnd(dvdcmdblk *block)
2370 s32 ret,state;
2371 u32 level;
2372 #ifdef _DVD_DEBUG
2373 printf("DVD_StopStreamAtEnd(%p)\n",block);
2374 #endif
2375 ret = DVD_StopStreamAtEndAsync(block,__dvd_streamatendsynccb);
2376 if(!ret) return -1;
2378 _CPU_ISR_Disable(level);
2379 do {
2380 state = block->state;
2381 if(state==0 || state==-1) ret = -1;
2382 else if(state==10) ret = block->txdsize;
2383 else LWP_ThreadSleep(__dvd_wait_queue);
2384 } while(state!=0 && state!=-1 && state!=10);
2385 _CPU_ISR_Restore(level);
2387 return ret;
2390 s32 DVD_SpinUpDriveAsync(dvdcmdblk *block,dvdcbcallback cb)
2392 #ifdef _DVD_DEBUG
2393 printf("DVD_SpinUpDriveAsync(%p,%p)\n",block,cb);
2394 #endif
2395 DVD_Reset(DVD_RESETNONE);
2397 block->cmd = 0x10;
2398 block->cb = cb;
2399 return __issuecommand(1,block);
2402 s32 DVD_SpinUpDrive(dvdcmdblk *block)
2404 s32 ret,state;
2405 u32 level;
2406 #ifdef _DVD_DEBUG
2407 printf("DVD_SpinUpDrive(%p)\n",block);
2408 #endif
2409 ret = DVD_SpinUpDriveAsync(block,__dvd_spinupdrivesynccb);
2410 if(!ret) return -1;
2412 _CPU_ISR_Disable(level);
2413 do {
2414 state = block->state;
2415 if(state==0 || state==-1) ret = -1;
2416 else if(state==10) ret = block->txdsize;
2417 else LWP_ThreadSleep(__dvd_wait_queue);
2418 } while(state!=0 && state!=-1 && state!=10);
2419 _CPU_ISR_Restore(level);
2421 return ret;
2424 s32 DVD_ControlDriveAsync(dvdcmdblk *block,u32 cmd,dvdcbcallback cb)
2426 #ifdef _DVD_DEBUG
2427 printf("DVD_ControlMotorAsync(%p,%d,%p)\n",block,cmd,cb);
2428 #endif
2429 block->cmd = 0x11;
2430 block->cb = cb;
2431 block->offset = cmd;
2432 return __issuecommand(1,block);
2435 s32 DVD_ControlDrive(dvdcmdblk *block,u32 cmd)
2437 s32 ret,state;
2438 u32 level;
2439 #ifdef _DVD_DEBUG
2440 printf("DVD_ControlMotor(%p,%d)\n",block,cmd);
2441 #endif
2442 ret = DVD_ControlDriveAsync(block,cmd,__dvd_motorcntrlsynccb);
2444 _CPU_ISR_Disable(level);
2445 do {
2446 state = block->state;
2447 if(state==0 || state==-1) ret = -1;
2448 else if(state==10) ret = block->txdsize;
2449 else LWP_ThreadSleep(__dvd_wait_queue);
2450 } while(state!=0 && state!=-1 && state!=10);
2451 _CPU_ISR_Restore(level);
2453 return ret;
2456 s32 DVD_SetGCMOffsetAsync(dvdcmdblk *block,s64 offset,dvdcbcallback cb)
2458 #ifdef _DVD_DEBUG
2459 printf("DVD_SetGCMOffsetAsync(%p,%08x,%p)\n",block,offset,cb);
2460 #endif
2461 block->cmd = 0x12;
2462 block->cb = cb;
2463 block->offset = offset;
2464 return __issuecommand(1,block);
2467 s32 DVD_SetGCMOffset(dvdcmdblk *block,s64 offset)
2469 s32 ret,state;
2470 u32 level;
2471 #ifdef _DVD_DEBUG
2472 printf("DVD_SetGCMOffset(%p,%08x)\n",block,offset);
2473 #endif
2474 ret = DVD_SetGCMOffsetAsync(block,offset,__dvd_setgcmsynccb);
2476 _CPU_ISR_Disable(level);
2477 do {
2478 state = block->state;
2479 if(state==0 || state==-1) ret = -1;
2480 else if(state==10) ret = block->txdsize;
2481 else LWP_ThreadSleep(__dvd_wait_queue);
2482 } while(state!=0 && state!=-1 && state!=10);
2483 _CPU_ISR_Restore(level);
2485 return ret;
2488 s32 DVD_GetCmdBlockStatus(dvdcmdblk *block)
2490 u32 level;
2491 s32 ret = -1;
2493 _CPU_ISR_Disable(level);
2494 if(block) {
2495 if((ret=block->state)==0x0003) ret = 1;
2497 _CPU_ISR_Restore(level);
2498 return ret;
2501 s32 DVD_GetDriveStatus()
2503 s32 ret;
2504 u32 level;
2506 _CPU_ISR_Disable(level);
2507 if(__dvd_fatalerror) ret = -1;
2508 else {
2509 if(__dvd_pausingflag) ret = 8;
2510 else {
2511 if(!__dvd_executing || __dvd_executing==&__dvd_dummycmdblk) ret = 0;
2512 else ret = DVD_GetCmdBlockStatus(__dvd_executing);
2515 _CPU_ISR_Restore(level);
2516 return ret;
2519 void DVD_Pause()
2521 u32 level;
2523 _CPU_ISR_Disable(level);
2524 __dvd_pauseflag = 1;
2525 if(__dvd_executing==NULL) __dvd_pausingflag = 1;
2526 _CPU_ISR_Restore(level);
2529 void DVD_Reset(u32 reset_mode)
2531 #ifdef _DVD_DEBUG
2532 printf("DVD_Reset(%d)\n",reset_mode);
2533 #endif
2534 __dvd_drivestate &= ~(DVD_INTEROPER|DVD_CHIPPRESENT|DVD_DRIVERESET);
2536 if(reset_mode!=DVD_RESETNONE)
2537 DVD_LowReset(reset_mode);
2539 _diReg[0] = (DVD_DE_MSK|DVD_TC_MSK|DVD_BRK_MSK);
2540 _diReg[1] = _diReg[1];
2542 __dvd_resetrequired = 0;
2543 __dvd_internalretries = 0;
2546 void callback(s32 result,dvdcmdblk *block)
2548 #ifdef _DVD_DEBUG
2549 printf("callback(%d)\n",result);
2550 #endif
2551 if(result==0x00) {
2552 DVD_ReadDiskID(block,&__dvd_tmpid0,callback);
2553 return;
2555 else if(result>=DVD_DISKIDSIZE) {
2556 memcpy(__dvd_diskID,&__dvd_tmpid0,DVD_DISKIDSIZE);
2557 } else if(result==-4) {
2558 DVD_SpinUpDriveAsync(block,callback);
2559 return;
2561 if(__dvd_mountusrcb) __dvd_mountusrcb(result,block);
2564 s32 DVD_MountAsync(dvdcmdblk *block,dvdcbcallback cb)
2566 #ifdef _DVD_DEBUG
2567 printf("DVD_MountAsync()\n");
2568 #endif
2569 __dvd_mountusrcb = cb;
2570 DVD_Reset(DVD_RESETHARD);
2571 udelay(1150*1000);
2572 return DVD_SpinUpDriveAsync(block,callback);
2575 s32 DVD_Mount()
2577 s32 ret = 0;
2578 s32 state;
2579 u32 level;
2580 #ifdef _DVD_DEBUG
2581 printf("DVD_Mount()\n");
2582 #endif
2584 ret = DVD_MountAsync(&__dvd_block$15,__dvd_mountsynccb);
2585 if(!ret) return -1;
2587 _CPU_ISR_Disable(level);
2588 do {
2589 state = __dvd_block$15.state;
2590 if(state==0) ret = 0;
2591 else if(state==-1) ret = -1;
2592 else if(state==10) ret = -3;
2593 else LWP_ThreadSleep(__dvd_wait_queue);
2594 } while(state!=0 && state!=-1 && state!=10);
2595 __dvd_mountusrcb = NULL; //set to zero coz this is only used to sync for this function.
2596 _CPU_ISR_Restore(level);
2598 return ret;
2601 dvddiskid* DVD_GetCurrentDiskID()
2603 return __dvd_diskID;
2606 dvddrvinfo* DVD_GetDriveInfo()
2608 return &__dvd_driveinfo;
2611 void DVD_Init()
2613 #ifdef _DVD_DEBUG
2614 printf("DVD_Init()\n");
2615 #endif
2616 if(!__dvd_initflag) {
2617 __dvd_initflag = 1;
2618 __dvd_clearwaitingqueue();
2619 __DVDInitWA();
2621 IRQ_Request(IRQ_PI_DI,__DVDInterruptHandler,NULL);
2622 __UnmaskIrq(IRQMASK(IRQ_PI_DI));
2624 SYS_CreateAlarm(&__dvd_timeoutalarm);
2625 LWP_InitQueue(&__dvd_wait_queue);
2629 u32 DVD_SetAutoInvalidation(u32 auto_inv)
2631 u32 ret = __dvd_autoinvalidation;
2632 __dvd_autoinvalidation= auto_inv;
2633 return ret;
2636 static bool dvdio_Startup()
2638 DVD_Init();
2640 if (mfpvr() == 0x00083214) // GameCube
2642 DVD_Mount();
2644 else
2646 DVD_Reset(DVD_RESETHARD);
2647 DVD_ReadDiskID(&__dvd_block$15, &__dvd_tmpid0, callback);
2649 return true;
2652 static bool dvdio_IsInserted()
2654 u32 status = 0;
2655 DVD_LowGetStatus(&status, NULL);
2657 if(DVD_STATUS(status) == DVD_STATUS_READY)
2658 return true;
2660 return false;
2663 static bool dvdio_ReadSectors(sec_t sector,sec_t numSectors,void *buffer)
2665 dvdcmdblk blk;
2667 if(DVD_ReadPrio(&blk, buffer, numSectors<<11, sector << 11, 2) <= 0)
2668 return false;
2670 return true;
2673 static bool dvdio_WriteSectors(sec_t sector,sec_t numSectors,const void *buffer)
2675 return true;
2678 static bool dvdio_ClearStatus()
2680 return true;
2683 static bool dvdio_Shutdown()
2685 return true;
2688 const DISC_INTERFACE __io_gcdvd = {
2689 DEVICE_TYPE_GAMECUBE_DVD,
2690 FEATURE_MEDIUM_CANREAD | FEATURE_GAMECUBE_DVD,
2691 (FN_MEDIUM_STARTUP)&dvdio_Startup,
2692 (FN_MEDIUM_ISINSERTED)&dvdio_IsInserted,
2693 (FN_MEDIUM_READSECTORS)&dvdio_ReadSectors,
2694 (FN_MEDIUM_WRITESECTORS)&dvdio_WriteSectors,
2695 (FN_MEDIUM_CLEARSTATUS)&dvdio_ClearStatus,
2696 (FN_MEDIUM_SHUTDOWN)&dvdio_Shutdown