1 /*-------------------------------------------------------------
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
35 -------------------------------------------------------------*/
41 #include "processor.h"
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
{
150 typedef struct _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;
348 static vu32
* const _diReg
= (u32
*)0xCD006000;
349 #elif defined(HW_DOL)
350 static vu32
* const _diReg
= (u32
*)0xCC006000;
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
)
413 if(errorcode
==__dvd_errortable
[i
]) return i
;
416 if(errorcode
<0x00100000 || errorcode
>0x00100008) return 29;
421 static u8
convert(u32 errorcode
)
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()
440 __lwp_queue_init_empty(&__dvd_waitingqueue
[i
]);
443 static s32
__dvd_checkwaitingqueue()
448 _CPU_ISR_Disable(level
);
450 if(!__lwp_queue_isempty(&__dvd_waitingqueue
[i
])) break;
452 _CPU_ISR_Restore(level
);
456 static s32
__dvd_pushwaitingqueue(s32 prio
,dvdcmdblk
*block
)
460 printf("__dvd_pushwaitingqueue(%d,%p,%p)\n",prio
,block
,block
->cb
);
462 _CPU_ISR_Disable(level
);
463 __lwp_queue_appendI(&__dvd_waitingqueue
[prio
],&block
->node
);
464 _CPU_ISR_Restore(level
);
468 static dvdcmdblk
* __dvd_popwaitingqueueprio(s32 prio
)
471 dvdcmdblk
*ret
= NULL
;
473 printf("__dvd_popwaitingqueueprio(%d)\n",prio
);
475 _CPU_ISR_Disable(level
);
476 ret
= (dvdcmdblk
*)__lwp_queue_firstnodeI(&__dvd_waitingqueue
[prio
]);
477 _CPU_ISR_Restore(level
);
479 printf("__dvd_popwaitingqueueprio(%p,%p)\n",ret
,ret
->cb
);
484 static dvdcmdblk
* __dvd_popwaitingqueue()
487 dvdcmdblk
*ret
= NULL
;
489 printf("__dvd_popwaitingqueue()\n");
491 _CPU_ISR_Disable(level
);
493 if(!__lwp_queue_isempty(&__dvd_waitingqueue
[i
])) {
494 _CPU_ISR_Restore(level
);
495 ret
= __dvd_popwaitingqueueprio(i
);
499 _CPU_ISR_Restore(level
);
503 static void __dvd_timeouthandler(syswd_t alarm
,void *cbarg
)
507 __MaskIrq(IRQMASK(IRQ_PI_DI
));
512 static void __dvd_storeerror(u32 errorcode
)
517 err
= convert(errorcode
);
518 ptr
= __SYS_LockSramEx();
519 ptr
->dvderr_code
= err
;
520 __SYS_UnlockSramEx(1);
523 static u32
__dvd_categorizeerror(u32 errorcode
)
526 printf("__dvd_categorizeerror(%08x)\n",errorcode
);
528 if((errorcode
-0x20000)==0x0400) {
529 __dvd_lasterror
= errorcode
;
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
);
544 __dvd_lasterror
= DVD_ERROR(errorcode
);
548 __dvd_lasterror
= DVD_ERROR(errorcode
);
549 if(DVD_ERROR(errorcode
)!=DVD_ERROR_UNRECOVERABLE_READ
) {
550 if(__dvd_executing
->cmd
!=0x0005) return 3;
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
)
565 printf("__Read(%p,%d,%d)\n",buffer
,len
,offset
);
568 __dvd_stopnextint
= 0;
569 __dvd_lastcmdwasread
= 1;
571 _diReg
[2] = DVD_READSECTOR
;
572 _diReg
[3] = (u32
)(offset
>>2);
574 _diReg
[5] = (u32
)buffer
;
579 _diReg
[7] = (DVD_DI_DMA
|DVD_DI_START
);
584 __SetupTimeoutAlarm(&tb
);
588 __SetupTimeoutAlarm(&tb
);
592 static void __DoRead(void *buffer
,u32 len
,s64 offset
,dvdcallbacklow cb
)
595 printf("__DoRead(%p,%d,%d)\n",buffer
,len
,offset
);
597 __dvd_nextcmdnum
= 0;
598 __dvd_cmdlist
[0].cmd
= -1;
599 __Read(buffer
,len
,offset
,cb
);
602 static u32
__ProcessNextCmd()
606 printf("__ProcessNextCmd(%d)\n",__dvd_nextcmdnum
);
608 cmd_num
= __dvd_nextcmdnum
;
609 if(__dvd_cmdlist
[cmd_num
].cmd
==0x0001) {
611 __Read(__dvd_cmdlist
[cmd_num
].buf
,__dvd_cmdlist
[cmd_num
].len
,__dvd_cmdlist
[cmd_num
].offset
,__dvd_cmdlist
[cmd_num
].cb
);
615 if(__dvd_cmdlist
[cmd_num
].cmd
==0x0002) {
617 DVD_LowSeek(__dvd_cmdlist
[cmd_num
].offset
,__dvd_cmdlist
[cmd_num
].cb
);
623 static void __DVDLowWATypeSet(u32 workaround
,u32 workaroundseek
)
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
)
643 if(__dvd_canceling
) {
644 __dvd_resumefromhere
= cancelpt
;
647 block
= __dvd_executing
;
648 __dvd_executing
= &__dvd_dummycmdblk
;
651 if(block
->cb
) block
->cb(-3,block
);
652 if(__dvd_cancelcallback
) __dvd_cancelcallback(0,block
);
660 static void __dvd_stateretrycb(s32 result
)
663 printf("__dvd_stateretrycb(%08x)\n",result
);
666 __dvd_executing
->state
= -1;
667 __dvd_statetimeout();
671 if(result
&0x0002) __dvd_stateerror(0x01234567);
673 __dvd_statebusy(__dvd_executing
);
678 static void __dvd_unrecoverederrorretrycb(s32 result
)
683 __dvd_executing
->state
= -1;
684 __dvd_statetimeout();
688 __dvd_executing
->state
= -1;
689 if(result
&0x0002) __dvd_stateerror(0x01234567);
692 __dvd_stateerror(val
);
696 static void __dvd_unrecoverederrorcb(s32 result
)
699 __dvd_executing
->state
= -1;
700 __dvd_statetimeout();
704 __dvd_stategotoretry();
707 if(!(result
==0x0002)) DVD_LowRequestError(__dvd_unrecoverederrorretrycb
);
710 static void __dvd_stateerrorcb(s32 result
)
714 printf("__dvd_stateerrorcb(%d)\n",result
);
717 __dvd_executing
->state
= -1;
718 __dvd_statetimeout();
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
) {
728 if(__dvd_cancelcallback
) __dvd_cancelcallback(0,block
);
733 static void __dvd_stategettingerrorcb(s32 result
)
738 printf("__dvd_stategettingerrorcb(%d)\n",result
);
741 __dvd_executing
->state
= -1;
742 __dvd_statetimeout();
746 __dvd_executing
->state
= -1;
747 __dvd_stateerror(0x01234567);
752 ret
= __dvd_categorizeerror(val
);
754 printf("__dvd_stategettingerrorcb(status = %02x, err = %08x, category = %d)\n",DVD_STATUS(val
),DVD_ERROR(val
),ret
);
757 __dvd_executing
->state
= -1;
758 __dvd_stateerror(val
);
760 } else if(ret
==2 || ret
==3) cnclpt
= 0;
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;
767 if(__dvd_checkcancel(cnclpt
)) return;
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) {
774 __dvd_extensionsenabled
= FALSE
;
775 DVD_LowSpinUpDrive(__dvd_stateretrycb
);
778 __dvd_statebusy(__dvd_executing
);
780 __dvd_storeerror(val
);
781 __dvd_stategotoretry();
785 if(DVD_ERROR(val
)==DVD_ERROR_UNRECOVERABLE_READ
) {
786 DVD_LowSeek(__dvd_executing
->offset
,__dvd_unrecoverederrorcb
);
789 __dvd_laststate(__dvd_executing
);
792 } else if(DVD_STATUS(val
)==DVD_STATUS_COVER_OPENED
) {
793 __dvd_executing
->state
= 5;
794 __dvd_statemotorstopped();
796 } else if(DVD_STATUS(val
)==DVD_STATUS_DISK_CHANGE
) {
797 __dvd_executing
->state
= 3;
798 __dvd_statecoverclosed();
800 } else if(DVD_STATUS(val
)==DVD_STATUS_NO_DISK
) {
801 __dvd_executing
->state
= 4;
802 __dvd_statemotorstopped();
805 __dvd_executing
->state
= -1;
806 __dvd_stateerror(0x01234567);
811 static void __dvd_statebusycb(s32 result
)
816 printf("__dvd_statebusycb(%04x)\n",result
);
819 __dvd_executing
->state
= -1;
820 __dvd_statetimeout();
823 if(__dvd_currcmd
==0x0003 || __dvd_currcmd
==0x000f) {
825 __dvd_executing
->state
= -1;
826 __dvd_stateerror(0x01234567);
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();
842 if(__dvd_currcmd
==0x0001 || __dvd_currcmd
==0x0004
843 || __dvd_currcmd
==0x0005 || __dvd_currcmd
==0x000e) {
844 __dvd_executing
->txdsize
+= (__dvd_executing
->currtxsize
-_diReg
[6]);
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
);
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) {
863 printf("__dvd_statebusycb(%p,%p)\n",__dvd_executing
,__dvd_executing
->cb
);
865 if(__dvd_executing
->txdsize
!=__dvd_executing
->len
) {
866 __dvd_statebusy(__dvd_executing
);
869 block
= __dvd_executing
;
870 __dvd_executing
= &__dvd_dummycmdblk
;
872 if(block
->cb
) block
->cb(block
->txdsize
,block
);
876 if(__dvd_currcmd
==0x0009 || __dvd_currcmd
==0x000a
877 || __dvd_currcmd
==0x000b || __dvd_currcmd
==0x000c) {
880 if(__dvd_currcmd
==0x000a || __dvd_currcmd
==0x000b) val
<<= 2;
882 block
= __dvd_executing
;
883 __dvd_executing
= &__dvd_dummycmdblk
;
885 if(block
->cb
) block
->cb(val
,block
);
889 if(__dvd_currcmd
==0x0006) {
890 if(!__dvd_executing
->currtxsize
) {
891 if(_diReg
[8]&0x0001) {
892 block
= __dvd_executing
;
893 __dvd_executing
= &__dvd_dummycmdblk
;
895 if(block
->cb
) block
->cb(-2,block
);
899 __dvd_autofinishing
= 0;
900 __dvd_executing
->currtxsize
= 1;
901 DVD_LowAudioStream(0,__dvd_executing
->len
,__dvd_executing
->offset
,__dvd_statebusycb
);
905 block
= __dvd_executing
;
906 __dvd_executing
= &__dvd_dummycmdblk
;
908 if(block
->cb
) block
->cb(0,block
);
912 if(__dvd_currcmd
==0x0010) {
913 if(__dvd_drivestate
&DVD_CHIPPRESENT
) {
914 block
= __dvd_executing
;
915 __dvd_executing
= &__dvd_dummycmdblk
;
917 if(block
->cb
) block
->cb(DVD_DISKIDSIZE
,block
);
923 block
= __dvd_executing
;
924 __dvd_executing
= &__dvd_dummycmdblk
;
926 if(block
->cb
) block
->cb(0,block
);
932 printf("__dvd_statebusycb(%d,%d)\n",__dvd_executing
->txdsize
,__dvd_executing
->len
);
934 if(__dvd_currcmd
==0x000e) {
935 __dvd_executing
->state
= -1;
936 __dvd_stateerror(0x01234567);
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
;
947 if(block
->cb
) block
->cb(block
->txdsize
,block
);
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
)
998 printf("__dvd_statemotorstoppedcb(%08x)\n",result
);
1001 __dvd_executing
->state
= 3;
1002 __dvd_statecoverclosed();
1005 static void __dvd_statecoverclosedcb(s32 result
)
1008 printf("__dvd_statecoverclosedcb(%08x)\n",result
);
1010 if(result
==0x0010) {
1011 __dvd_executing
->state
= -1;
1012 __dvd_statetimeout();
1016 if(!(result
&0x0006)) {
1017 __dvd_internalretries
= 0;
1018 __dvd_statecheckid();
1022 if(result
==0x0002) __dvd_stategettingerror();
1025 static void __dvd_statecheckid1cb(s32 result
)
1028 printf("__dvd_statecheckid1cb(%08x)\n",result
);
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();
1043 __dvd_executing
->state
= -1;
1044 __dvd_stateerror(0x01234567);
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
)
1065 printf("__dvd_getstatuscb(%d)\n",result
);
1067 if(result
==0x0010) {
1068 __dvd_statetimeout();
1071 if(result
==0x0001) {
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
;
1083 __dvd_stategettingerror();
1086 static void __dvd_readmemcb(s32 result
)
1091 printf("__dvd_readmemcb(%d)\n",result
);
1093 if(result
==0x0010) {
1094 __dvd_statetimeout();
1097 if(result
==0x0001) {
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
;
1109 __dvd_stategettingerror();
1112 static void __dvd_cntrldrivecb(s32 result
)
1115 printf("__dvd_cntrldrivecb(%d)\n",result
);
1117 if(result
==0x0010) {
1118 __dvd_statetimeout();
1121 if(result
==0x0001) {
1122 DVD_LowSpinMotor(__dvd_motorcntrl
,__dvd_finalsudcb
);
1125 __dvd_stategettingerror();
1128 static void __dvd_setgcmoffsetcb(s32 result
)
1130 s64
*pn_data
,offset
;
1132 printf("__dvd_setgcmoffsetcb(%d)\n",result
);
1134 if(result
==0x0010) {
1135 __dvd_statetimeout();
1138 if(result
==0x0001) {
1139 pn_data
= (s64
*)__dvd_usrdata
;
1140 __dvd_usrdata
= NULL
;
1143 if(pn_data
) offset
= *pn_data
;
1144 DVD_LowSetOffset(offset
,__dvd_finaloffsetcb
);
1147 __dvd_stategettingerror();
1150 static void __dvd_handlespinupcb(s32 result
)
1152 static u32 step
= 0;
1154 printf("__dvd_handlespinupcb(%d,%d)\n",result
,step
);
1156 if(result
==0x0010) {
1157 __dvd_statetimeout();
1160 if(result
==0x0001) {
1163 _diReg
[1] = _diReg
[1];
1164 DVD_LowEnableExtensions(__dvd_extensionsenabled
,__dvd_handlespinupcb
);
1169 _diReg
[1] = _diReg
[1];
1170 DVD_LowSpinMotor((DVD_SPINMOTOR_ACCEPT
|DVD_SPINMOTOR_UP
),__dvd_handlespinupcb
);
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
);
1180 __dvd_finalsudcb(result
);
1186 __dvd_stategettingerror();
1189 static void __dvd_fwpatchcb(s32 result
)
1191 static u32 step
= 0;
1193 printf("__dvd_fwpatchcb(%d,%d)\n",result
,step
);
1195 if(result
==0x0010) {
1196 __dvd_statetimeout();
1199 if(result
==0x0001) {
1202 _diReg
[1] = _diReg
[1];
1203 DVD_LowUnlockDrive(__dvd_fwpatchcb
);
1208 DVD_LowPatchDriveCode(__dvd_finalpatchcb
);
1214 __dvd_stategettingerror();
1217 static void __dvd_checkaddonscb(s32 result
)
1222 printf("__dvd_checkaddonscb(%d)\n",result
);
1224 __dvd_drivechecked
= 1;
1225 txdsize
= (DVD_DISKIDSIZE
-_diReg
[6]);
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
);
1234 __dvd_drivestate
|= DVD_CHIPPRESENT
;
1237 cb
= __dvd_finaladdoncb
;
1238 __dvd_finaladdoncb
= NULL
;
1242 static void __dvd_checkaddons(dvdcallbacklow cb
)
1245 printf("__dvd_checkaddons()\n");
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
);
1256 static void __dvd_fwpatchmem(dvdcallbacklow cb
)
1259 printf("__dvd_fwpatchmem()\n");
1261 __dvd_finalpatchcb
= cb
;
1263 _diReg
[1] = _diReg
[1];
1264 DCInvalidateRange(&__dvd_driveinfo
,DVD_DRVINFSIZE
);
1265 DVD_LowInquiry(&__dvd_driveinfo
,__dvd_fwpatchcb
);
1269 static void __dvd_handlespinup()
1272 printf("__dvd_handlespinup()\n");
1274 _diReg
[1] = _diReg
[1];
1275 DVD_LowUnlockDrive(__dvd_handlespinupcb
);
1279 static void __dvd_spinupdrivecb(s32 result
)
1282 printf("__dvd_spinupdrivecb(%d,%02x,%02x)\n",result
,__dvd_resetoccured
,__dvd_drivestate
);
1284 if(result
==0x0010) {
1285 __dvd_statetimeout();
1288 if(result
==0x0001) {
1289 if(!__dvd_drivechecked
) {
1290 __dvd_checkaddons(__dvd_spinupdrivecb
);
1293 if(!(__dvd_drivestate
&DVD_CHIPPRESENT
)) {
1294 if(!(__dvd_drivestate
&DVD_INTEROPER
)) {
1295 if(!(__dvd_drivestate
&DVD_DRIVERESET
)) {
1296 DVD_Reset(DVD_RESETHARD
);
1299 __dvd_fwpatchmem(__dvd_spinupdrivecb
);
1302 __dvd_handlespinup();
1306 __dvd_finalsudcb(result
);
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
)
1322 u32 status
,ir
,irm
,irmm
,diff
;
1325 SYS_CancelAlarm(__dvd_timeoutalarm
);
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;
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));
1341 printf("__DVDInterruptHandler(status: %08x,irm: %08x,ir: %08x (%d))\n",status
,irm
,ir
,__dvd_resetoccured
);
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
);
1352 diff
= diff_msec(__dvd_lastresetend
,now
);
1353 if(__dvd_resetoccured
&& diff
>200) {
1355 irm
= status
&DVD_CVR_MSK
;
1356 ir
= (status
&DVD_CVR_INT
)&(irm
<<1);
1358 cb
= __dvd_resetcovercb
;
1359 __dvd_resetcovercb
= NULL
;
1364 _diReg
[1] = _diReg
[1];
1366 if(__dvd_waitcoverclose
) {
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;
1378 if(!__dvd_breaking
) irmm
&= ~0x0008;
1382 if(__ProcessNextCmd()) return;
1384 __dvd_cmdlist
[0].cmd
= -1;
1385 __dvd_nextcmdnum
= 0;
1388 cb
= __dvd_callback
;
1389 __dvd_callback
= NULL
;
1395 static void __dvd_patchdrivecb(s32 result
)
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
);
1405 printf("__DVDPatchDriveCode()\n");
1407 if(__dvdpatchcode
==NULL
|| __dvdpatchcode_size
<=0) return;
1409 while(stage
!=0x0003) {
1410 __dvd_callback
= __dvd_patchdrivecb
;
1413 printf("__DVDPatchDriveCode(0x%08x,%02x,%d)\n",drv_address
,stage
,nPos
);
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
);
1432 printf("__DVDPatchDriveCode(%02x)\n",stage
);
1434 if(stage
>0x0001) stage
= 0x0003;
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
;
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
)
1456 printf("__DVDUnlockDrive(%d)\n",result
);
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
)
1468 _CPU_ISR_Disable(level
);
1469 __dvd_clearwaitingqueue();
1470 if(__dvd_canceling
) __dvd_cancelcallback
= cb
;
1472 if(__dvd_executing
) __dvd_executing
->cb
= NULL
;
1473 DVD_CancelAllAsync(cb
);
1475 _CPU_ISR_Restore(level
);
1478 void __dvd_statebusy(dvdcmdblk
*block
)
1482 printf("__dvd_statebusy(%p)\n",block
);
1484 __dvd_laststate
= __dvd_statebusy
;
1485 if(block
->cmd
>DVD_MAXCOMMANDS
) return;
1487 switch(block
->cmd
) {
1488 case 1: //Read(Sector)
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
);
1496 case 2: //Seek(Sector)
1497 _diReg
[1] = _diReg
[1];
1498 DVD_LowSeek(block
->offset
,__dvd_statebusycb
);
1502 DVD_LowStopMotor(__dvd_statebusycb
);
1504 case 5: //ReadDiskID
1505 _diReg
[1] = _diReg
[1];
1506 block
->currtxsize
= DVD_DISKIDSIZE
;
1507 DVD_LowReadId(block
->buf
,__dvd_statebusycb
);
1510 _diReg
[1] = _diReg
[1];
1511 if(__dvd_autofinishing
) {
1512 __dvd_executing
->currtxsize
= 0;
1513 DVD_LowRequestAudioStatus(0,__dvd_statebusycb
);
1515 __dvd_executing
->currtxsize
= 1;
1516 DVD_LowAudioStream(0,__dvd_executing
->len
,__dvd_executing
->offset
,__dvd_statebusycb
);
1520 _diReg
[1] = _diReg
[1];
1521 DVD_LowAudioStream(0x00010000,0,0,__dvd_statebusycb
);
1524 _diReg
[1] = _diReg
[1];
1525 __dvd_autofinishing
= 1;
1526 DVD_LowAudioStream(0,0,0,__dvd_statebusycb
);
1529 _diReg
[1] = _diReg
[1];
1530 DVD_LowRequestAudioStatus(0,__dvd_statebusycb
);
1533 _diReg
[1] = _diReg
[1];
1534 DVD_LowRequestAudioStatus(0x00010000,__dvd_statebusycb
);
1537 _diReg
[1] = _diReg
[1];
1538 DVD_LowRequestAudioStatus(0x00020000,__dvd_statebusycb
);
1541 _diReg
[1] = _diReg
[1];
1542 DVD_LowRequestAudioStatus(0x00030000,__dvd_statebusycb
);
1545 _diReg
[1] = _diReg
[1];
1546 DVD_LowAudioBufferConfig(__dvd_executing
->offset
,__dvd_executing
->len
,__dvd_statebusycb
);
1549 _diReg
[1] = _diReg
[1];
1550 block
->currtxsize
= 0x20;
1551 DVD_LowInquiry(block
->buf
,__dvd_statebusycb
);
1554 __dvd_lasterror
= 0;
1555 __dvd_extensionsenabled
= TRUE
;
1556 DVD_LowSpinUpDrive(__dvd_statebusycb
);
1559 _diReg
[1] = _diReg
[1];
1560 DVD_LowControlMotor(block
->offset
,__dvd_statebusycb
);
1563 _diReg
[1] = _diReg
[1];
1564 DVD_LowSetGCMOffset(block
->offset
,__dvd_statebusycb
);
1571 void __dvd_stateready()
1575 printf("__dvd_stateready()\n");
1577 if(!__dvd_checkwaitingqueue()) {
1578 __dvd_executing
= NULL
;
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
);
1593 __dvd_currcmd
= __dvd_executing
->cmd
;
1595 if(__dvd_resumefromhere
) {
1596 if(__dvd_resumefromhere
<=7) {
1597 switch(__dvd_resumefromhere
) {
1599 __dvd_executing
->state
= 6;
1600 __dvd_statemotorstopped();
1603 __dvd_executing
->state
= 11;
1604 __dvd_statemotorstopped();
1607 __dvd_executing
->state
= 4;
1608 __dvd_statemotorstopped();
1611 __dvd_executing
->state
= 5;
1612 __dvd_statemotorstopped();
1615 __dvd_executing
->state
= -1;
1616 __dvd_stateerror(__dvd_cancellasterror
);
1619 __dvd_executing
->state
= 3;
1620 __dvd_statecoverclosed();
1623 __dvd_executing
->state
= 7;
1624 __dvd_statemotorstopped();
1631 __dvd_resumefromhere
= 0;
1634 __dvd_executing
->state
= 1;
1635 __dvd_statebusy(__dvd_executing
);
1638 void __dvd_statecoverclosed()
1642 printf("__dvd_statecoverclosed(%d)\n",__dvd_currcmd
);
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
);
1653 __dvd_extensionsenabled
= TRUE
;
1654 DVD_LowSpinUpDrive(__dvd_statecoverclosed_spinupcb
);
1658 void __dvd_statecoverclosed_cmd(dvdcmdblk
*block
)
1661 printf("__dvd_statecoverclosed_cmd(%d)\n",__dvd_currcmd
);
1663 DVD_LowReadId(&__dvd_tmpid0
,__dvd_statecoverclosedcb
);
1666 void __dvd_statemotorstopped()
1669 printf("__dvd_statemotorstopped(%d)\n",__dvd_executing
->state
);
1671 DVD_LowWaitCoverClose(__dvd_statemotorstoppedcb
);
1674 void __dvd_stateerror(s32 result
)
1677 printf("__dvd_stateerror(%08x)\n",result
);
1679 __dvd_storeerror(result
);
1680 DVD_LowStopMotor(__dvd_stateerrorcb
);
1683 void __dvd_stategettingerror()
1686 printf("__dvd_stategettingerror()\n");
1688 DVD_LowRequestError(__dvd_stategettingerrorcb
);
1691 void __dvd_statecheckid2(dvdcmdblk
*block
)
1696 void __dvd_statecheckid()
1700 printf("__dvd_statecheckid(%02x)\n",__dvd_currcmd
);
1702 if(__dvd_currcmd
==0x0003) {
1703 if(memcmp(&__dvd_dummycmdblk
,&__dvd_executing
,sizeof(dvdcmdblk
))) {
1704 DVD_LowStopMotor(__dvd_statecheckid1cb
);
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
);
1715 if(__dvd_currcmd
==0x0010) {
1716 blk
= __dvd_executing
;
1718 __dvd_executing
= &__dvd_dummycmdblk
;
1719 if(blk
->cb
) blk
->cb(0,blk
);
1723 if(__dvd_currcmd
!=0x0005 && memcmp(__dvd_diskID
,&__dvd_tmpid0
,DVD_DISKIDSIZE
)) {
1724 blk
= __dvd_executing
;
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
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
)
1752 printf("__issuecommand(%d,%p,%p)\n",prio
,block
,block
->cb
);
1753 printf("__issuecommand(%p)\n",__dvd_waitingqueue
[prio
].first
);
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
);
1767 s32
DVD_LowUnlockDrive(dvdcallbacklow cb
)
1770 printf("DVD_LowUnlockDrive()\n");
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
;
1784 s32
DVD_LowPatchDriveCode(dvdcallbacklow cb
)
1787 printf("DVD_LowPatchDriveCode(%08x)\n",__dvd_driveinfo
.rel_date
);
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.
1807 __dvdpatchcode
= NULL
;
1808 __dvdpatchcode_size
= 0;
1811 __dvd_patchdrivecb(0);
1815 s32
DVD_LowSetOffset(s64 offset
,dvdcallbacklow cb
)
1818 printf("DVD_LowSetOffset(%08x)\n",offset
);
1820 __dvd_stopnextint
= 0;
1821 __dvd_callback
= cb
;
1823 _diReg
[2] = DVD_FWSETOFFSET
;
1824 _diReg
[3] = (u32
)(offset
>>2);
1826 _diReg
[7] = DVD_DI_START
;
1831 s32
DVD_LowSetGCMOffset(s64 offset
,dvdcallbacklow cb
)
1833 static s64 loc_offset
= 0;
1835 printf("DVD_LowSetGCMOffset(%08x)\n",offset
);
1837 loc_offset
= offset
;
1839 __dvd_finaloffsetcb
= cb
;
1840 __dvd_stopnextint
= 0;
1841 __dvd_usrdata
= &loc_offset
;
1843 DVD_LowUnlockDrive(__dvd_setgcmoffsetcb
);
1847 s32
DVD_LowReadmem(u32 address
,void *buffer
,dvdcallbacklow cb
)
1850 printf("DVD_LowReadmem(0x%08x,%p)\n",address
,buffer
);
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
;
1865 s32
DVD_LowFuncCall(u32 address
,dvdcallbacklow cb
)
1868 printf("DVD_LowFuncCall(0x%08x)\n",address
);
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
;
1881 s32
DVD_LowSpinMotor(u32 mode
,dvdcallbacklow cb
)
1884 printf("DVD_LowSpinMotor(%08x)\n",mode
);
1886 __dvd_callback
= cb
;
1887 __dvd_stopnextint
= 0;
1889 _diReg
[2] = DVD_FWCTRLMOTOR
|(mode
&0x0000ff00);
1892 _diReg
[7] = DVD_DI_START
;
1897 s32
DVD_LowEnableExtensions(u8 enable
,dvdcallbacklow cb
)
1900 printf("DVD_LowEnableExtensions(%02x)\n",enable
);
1902 __dvd_callback
= cb
;
1903 __dvd_stopnextint
= 0;
1905 _diReg
[2] = (DVD_FWENABLEEXT
|_SHIFTL(enable
,16,8));
1908 _diReg
[7] = DVD_DI_START
;
1913 s32
DVD_LowSetStatus(u32 status
,dvdcallbacklow cb
)
1916 printf("DVD_LowSetStatus(%08x)\n",status
);
1918 __dvd_callback
= cb
;
1919 __dvd_stopnextint
= 0;
1921 _diReg
[2] = (DVD_FWSETSTATUS
|(status
&0x00ffffff));
1924 _diReg
[7] = DVD_DI_START
;
1929 s32
DVD_LowGetStatus(u32
*status
,dvdcallbacklow cb
)
1932 printf("DVD_LowSetStatus(%08x)\n",status
);
1934 __dvd_finalstatuscb
= cb
;
1935 __dvd_usrdata
= status
;
1937 DVD_LowRequestError(__dvd_getstatuscb
);
1941 s32
DVD_LowControlMotor(u32 mode
,dvdcallbacklow cb
)
1944 printf("DVD_LowControlMotor(%08x)\n",mode
);
1946 __dvd_stopnextint
= 0;
1947 __dvd_motorcntrl
= mode
;
1948 __dvd_finalsudcb
= cb
;
1949 DVD_LowUnlockDrive(__dvd_cntrldrivecb
);
1955 s32
DVD_LowSpinUpDrive(dvdcallbacklow cb
)
1958 printf("DVD_LowSpinUpDrive()\n");
1960 __dvd_finalsudcb
= cb
;
1961 __dvd_spinupdrivecb(1);
1966 s32
DVD_LowRead(void *buf
,u32 len
,s64 offset
,dvdcallbacklow cb
)
1969 printf("DVD_LowRead(%p,%d,%d)\n",buf
,len
,offset
);
1973 __dvd_cmd_curr
.buf
= buf
;
1974 __dvd_cmd_curr
.len
= len
;
1975 __dvd_cmd_curr
.offset
= offset
;
1976 __DoRead(buf
,len
,offset
,cb
);
1980 s32
DVD_LowSeek(s64 offset
,dvdcallbacklow cb
)
1983 printf("DVD_LowSeek(%d)\n",offset
);
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
;
1996 __SetupTimeoutAlarm(&tb
);
2001 s32
DVD_LowReadId(dvddiskid
*diskID
,dvdcallbacklow cb
)
2004 printf("DVD_LowReadId(%p)\n",diskID
);
2008 __dvd_callback
= cb
;
2009 __dvd_stopnextint
= 0;
2011 _diReg
[2] = DVD_READDISKID
;
2013 _diReg
[4] = DVD_DISKIDSIZE
;
2014 _diReg
[5] = (u32
)diskID
;
2015 _diReg
[6] = DVD_DISKIDSIZE
;
2016 _diReg
[7] = (DVD_DI_DMA
|DVD_DI_START
);
2020 __SetupTimeoutAlarm(&tb
);
2025 s32
DVD_LowRequestError(dvdcallbacklow cb
)
2028 printf("DVD_LowRequestError()\n");
2032 __dvd_callback
= cb
;
2033 __dvd_stopnextint
= 0;
2035 _diReg
[2] = DVD_REQUESTERROR
;
2036 _diReg
[7] = DVD_DI_START
;
2040 __SetupTimeoutAlarm(&tb
);
2045 s32
DVD_LowStopMotor(dvdcallbacklow cb
)
2048 printf("DVD_LowStopMotor()\n");
2052 __dvd_callback
= cb
;
2053 __dvd_stopnextint
= 0;
2055 _diReg
[2] = DVD_STOPMOTOR
;
2056 _diReg
[7] = DVD_DI_START
;
2060 __SetupTimeoutAlarm(&tb
);
2065 s32
DVD_LowInquiry(dvddrvinfo
*info
,dvdcallbacklow cb
)
2068 printf("DVD_LowInquiry(%p)\n",info
);
2072 __dvd_callback
= cb
;
2073 __dvd_stopnextint
= 0;
2075 _diReg
[2] = DVD_DVDINQUIRY
;
2077 _diReg
[5] = (u32
)info
;
2079 _diReg
[7] = (DVD_DI_DMA
|DVD_DI_START
);
2083 __SetupTimeoutAlarm(&tb
);
2088 s32
DVD_LowWaitCoverClose(dvdcallbacklow cb
)
2091 printf("DVD_LowWaitCoverClose()\n");
2093 __dvd_callback
= cb
;
2094 __dvd_waitcoverclose
= 1;
2095 __dvd_stopnextint
= 0;
2096 _diReg
[1] = DVD_CVR_MSK
;
2100 void DVD_LowReset(u32 reset_mode
)
2104 _diReg
[1] = DVD_CVR_MSK
;
2106 _piReg
[9] = ((val
&~0x0004)|0x0001);
2110 if(reset_mode
==DVD_RESETHARD
) val
|= 0x0004;
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
)
2122 printf("DVD_LowAudioStream(%08x,%d,%08x,%p)\n",subcmd
,len
,offset
,cb
);
2126 __dvd_callback
= cb
;
2127 __dvd_stopnextint
= 0;
2129 _diReg
[2] = DVD_AUDIOSTREAM
|subcmd
;
2130 _diReg
[3] = (u32
)(offset
>>2);
2132 _diReg
[7] = DVD_DI_START
;
2136 __SetupTimeoutAlarm(&tb
);
2141 s32
DVD_LowAudioBufferConfig(s32 enable
,u32 size
,dvdcallbacklow cb
)
2144 printf("DVD_LowAudioBufferConfig(%02x,%d,%p)\n",enable
,size
,cb
);
2149 __dvd_callback
= cb
;
2150 __dvd_stopnextint
= 0;
2155 if(!size
) val
|= 0x0000000a;
2158 _diReg
[2] = DVD_AUDIOCONFIG
|val
;
2159 _diReg
[7] = DVD_DI_START
;
2163 __SetupTimeoutAlarm(&tb
);
2168 s32
DVD_LowRequestAudioStatus(u32 subcmd
,dvdcallbacklow cb
)
2171 printf("DVD_LowRequestAudioStatus(%08x,%p)\n",subcmd
,cb
);
2175 __dvd_callback
= cb
;
2176 __dvd_stopnextint
= 0;
2178 _diReg
[2] = DVD_AUDIOSTATUS
|subcmd
;
2179 _diReg
[7] = DVD_DI_START
;
2183 __SetupTimeoutAlarm(&tb
);
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
;
2198 return __issuecommand(2,block
);
2201 s32
DVD_ReadDiskID(dvdcmdblk
*block
,dvddiskid
*id
,dvdcbcallback cb
)
2204 printf("DVD_ReadDiskID(%p,%p)\n",block
,id
);
2206 if(!block
|| !id
) return 0;
2208 block
->cmd
= 0x0005;
2210 block
->len
= DVD_DISKIDSIZE
;
2215 return __issuecommand(2,block
);
2218 s32
DVD_ReadAbsAsyncPrio(dvdcmdblk
*block
,void *buf
,u32 len
,s64 offset
,dvdcbcallback cb
,s32 prio
)
2221 printf("DVD_ReadAbsAsyncPrio(%p,%p,%d,%d,%d)\n",block
,buf
,len
,offset
,prio
);
2223 block
->cmd
= 0x0001;
2226 block
->offset
= offset
;
2230 return __issuecommand(prio
,block
);
2233 s32
DVD_ReadAbsAsyncForBS(dvdcmdblk
*block
,void *buf
,u32 len
,s64 offset
,dvdcbcallback cb
)
2236 printf("DVD_ReadAbsAsyncForBS(%p,%p,%d,%d)\n",block
,buf
,len
,offset
);
2238 block
->cmd
= 0x0004;
2241 block
->offset
= offset
;
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
;
2254 return __issuecommand(prio
,block
);
2257 s32
DVD_InquiryAsync(dvdcmdblk
*block
,dvddrvinfo
*info
,dvdcbcallback cb
)
2260 printf("DVD_InquiryAsync(%p,%p,%p)\n",block
,info
,cb
);
2262 block
->cmd
= 0x000e;
2268 printf("DVD_InquiryAsync(%p,%p)\n",block
,block
->cb
);
2270 return __issuecommand(2,block
);
2273 s32
DVD_Inquiry(dvdcmdblk
*block
,dvddrvinfo
*info
)
2278 printf("DVD_Inquiry(%p,%p)\n",block
,info
);
2280 ret
= DVD_InquiryAsync(block
,info
,__dvd_inquirysynccb
);
2283 _CPU_ISR_Disable(level
);
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
);
2295 s32
DVD_ReadPrio(dvdcmdblk
*block
,void *buf
,u32 len
,s64 offset
,s32 prio
)
2300 printf("DVD_ReadPrio(%p,%p,%d,%d,%d)\n",block
,buf
,len
,offset
,prio
);
2302 if(offset
>=0 && offset
<8511160320LL) {
2303 ret
= DVD_ReadAbsAsyncPrio(block
,buf
,len
,offset
,__dvd_readsynccb
,prio
);
2306 _CPU_ISR_Disable(level
);
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
);
2320 s32
DVD_SeekPrio(dvdcmdblk
*block
,s64 offset
,s32 prio
)
2325 printf("DVD_SeekPrio(%p,%d,%d)\n",block
,offset
,prio
);
2327 if(offset
>0 && offset
<8511160320LL) {
2328 ret
= DVD_SeekAbsAsyncPrio(block
,offset
,__dvd_seeksynccb
,prio
);
2331 _CPU_ISR_Disable(level
);
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
);
2346 s32
DVD_CancelAllAsync(dvdcbcallback cb
)
2350 printf("DVD_CancelAllAsync(%p)\n",cb
);
2352 _CPU_ISR_Disable(level
);
2354 _CPU_ISR_Restore(level
);
2358 s32
DVD_StopStreamAtEndAsync(dvdcmdblk
*block
,dvdcbcallback cb
)
2361 printf("DVD_StopStreamAtEndAsync(%p,%p)\n",block
,cb
);
2365 return __issuecommand(1,block
);
2368 s32
DVD_StopStreamAtEnd(dvdcmdblk
*block
)
2373 printf("DVD_StopStreamAtEnd(%p)\n",block
);
2375 ret
= DVD_StopStreamAtEndAsync(block
,__dvd_streamatendsynccb
);
2378 _CPU_ISR_Disable(level
);
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
);
2390 s32
DVD_SpinUpDriveAsync(dvdcmdblk
*block
,dvdcbcallback cb
)
2393 printf("DVD_SpinUpDriveAsync(%p,%p)\n",block
,cb
);
2395 DVD_Reset(DVD_RESETNONE
);
2399 return __issuecommand(1,block
);
2402 s32
DVD_SpinUpDrive(dvdcmdblk
*block
)
2407 printf("DVD_SpinUpDrive(%p)\n",block
);
2409 ret
= DVD_SpinUpDriveAsync(block
,__dvd_spinupdrivesynccb
);
2412 _CPU_ISR_Disable(level
);
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
);
2424 s32
DVD_ControlDriveAsync(dvdcmdblk
*block
,u32 cmd
,dvdcbcallback cb
)
2427 printf("DVD_ControlMotorAsync(%p,%d,%p)\n",block
,cmd
,cb
);
2431 block
->offset
= cmd
;
2432 return __issuecommand(1,block
);
2435 s32
DVD_ControlDrive(dvdcmdblk
*block
,u32 cmd
)
2440 printf("DVD_ControlMotor(%p,%d)\n",block
,cmd
);
2442 ret
= DVD_ControlDriveAsync(block
,cmd
,__dvd_motorcntrlsynccb
);
2444 _CPU_ISR_Disable(level
);
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
);
2456 s32
DVD_SetGCMOffsetAsync(dvdcmdblk
*block
,s64 offset
,dvdcbcallback cb
)
2459 printf("DVD_SetGCMOffsetAsync(%p,%08x,%p)\n",block
,offset
,cb
);
2463 block
->offset
= offset
;
2464 return __issuecommand(1,block
);
2467 s32
DVD_SetGCMOffset(dvdcmdblk
*block
,s64 offset
)
2472 printf("DVD_SetGCMOffset(%p,%08x)\n",block
,offset
);
2474 ret
= DVD_SetGCMOffsetAsync(block
,offset
,__dvd_setgcmsynccb
);
2476 _CPU_ISR_Disable(level
);
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
);
2488 s32
DVD_GetCmdBlockStatus(dvdcmdblk
*block
)
2493 _CPU_ISR_Disable(level
);
2495 if((ret
=block
->state
)==0x0003) ret
= 1;
2497 _CPU_ISR_Restore(level
);
2501 s32
DVD_GetDriveStatus()
2506 _CPU_ISR_Disable(level
);
2507 if(__dvd_fatalerror
) ret
= -1;
2509 if(__dvd_pausingflag
) ret
= 8;
2511 if(!__dvd_executing
|| __dvd_executing
==&__dvd_dummycmdblk
) ret
= 0;
2512 else ret
= DVD_GetCmdBlockStatus(__dvd_executing
);
2515 _CPU_ISR_Restore(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
)
2532 printf("DVD_Reset(%d)\n",reset_mode
);
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
)
2549 printf("callback(%d)\n",result
);
2552 DVD_ReadDiskID(block
,&__dvd_tmpid0
,callback
);
2555 else if(result
>=DVD_DISKIDSIZE
) {
2556 memcpy(__dvd_diskID
,&__dvd_tmpid0
,DVD_DISKIDSIZE
);
2557 } else if(result
==-4) {
2558 DVD_SpinUpDriveAsync(block
,callback
);
2561 if(__dvd_mountusrcb
) __dvd_mountusrcb(result
,block
);
2564 s32
DVD_MountAsync(dvdcmdblk
*block
,dvdcbcallback cb
)
2567 printf("DVD_MountAsync()\n");
2569 __dvd_mountusrcb
= cb
;
2570 DVD_Reset(DVD_RESETHARD
);
2572 return DVD_SpinUpDriveAsync(block
,callback
);
2581 printf("DVD_Mount()\n");
2584 ret
= DVD_MountAsync(&__dvd_block$
15,__dvd_mountsynccb
);
2587 _CPU_ISR_Disable(level
);
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
);
2601 dvddiskid
* DVD_GetCurrentDiskID()
2603 return __dvd_diskID
;
2606 dvddrvinfo
* DVD_GetDriveInfo()
2608 return &__dvd_driveinfo
;
2614 printf("DVD_Init()\n");
2616 if(!__dvd_initflag
) {
2618 __dvd_clearwaitingqueue();
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
;
2636 static bool dvdio_Startup()
2640 if (mfpvr() == 0x00083214) // GameCube
2646 DVD_Reset(DVD_RESETHARD
);
2647 DVD_ReadDiskID(&__dvd_block$
15, &__dvd_tmpid0
, callback
);
2652 static bool dvdio_IsInserted()
2655 DVD_LowGetStatus(&status
, NULL
);
2657 if(DVD_STATUS(status
) == DVD_STATUS_READY
)
2663 static bool dvdio_ReadSectors(sec_t sector
,sec_t numSectors
,void *buffer
)
2667 if(DVD_ReadPrio(&blk
, buffer
, numSectors
<<11, sector
<< 11, 2) <= 0)
2673 static bool dvdio_WriteSectors(sec_t sector
,sec_t numSectors
,const void *buffer
)
2678 static bool dvdio_ClearStatus()
2683 static bool dvdio_Shutdown()
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