PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
atacmd.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "acata_internal.h"
12
13static int ata_dma_xfer(acDmaT dma, int intr, acDmaOp op);
14static void ata_dma_done(acDmaT dma);
15static void ata_dma_error(acDmaT dma, int intr, acDmaState state, int result);
16static int ata_ops_command(struct ac_ata_h *atah, int cmdpri, int pri);
17static void ata_ops_done(struct ac_ata_h *atah, int result);
18
19static acDmaOpsData ops_8 = {&ata_dma_xfer, &ata_dma_done, &ata_dma_error};
20static struct ac_ata_ops ops_37 = {&ata_ops_command, &ata_ops_done, NULL};
21
22static int ata_dma_xfer(acDmaT dma, int intr, acDmaOp op)
23{
24 struct ata_dma *dmatmp;
25 int thid;
26
27 dmatmp = (struct ata_dma *)dma;
28 if ( dmatmp->ad_state == 31 )
29 {
30 dmatmp->ad_result = dmatmp->ad_ata->ac_h.a_size;
31 return op(dma, (void *)0xB6000000, dmatmp->ad_ata->ac_h.a_buf, dmatmp->ad_ata->ac_h.a_size);
32 }
33 thid = dmatmp->ad_thid;
34 dmatmp->ad_state = 3;
35 if ( intr )
36 iWakeupThread(thid);
37 else
38 WakeupThread(thid);
39 return 0;
40}
41
42static void ata_dma_done(acDmaT dma)
43{
44 struct ata_dma *dmatmp;
45 int thid;
46
47 dmatmp = (struct ata_dma *)dma;
48
49 thid = dmatmp->ad_thid;
50 dmatmp->ad_state = 127;
51 if ( thid )
52 iWakeupThread(thid);
53}
54
55static void ata_dma_error(acDmaT dma, int intr, acDmaState state, int result)
56{
57 struct ata_dma *dmatmp;
58 int thid;
59
60 dmatmp = (struct ata_dma *)dma;
61 thid = dmatmp->ad_thid;
62 dmatmp->ad_state = 1023;
63 dmatmp->ad_result = result;
64 if ( thid )
65 {
66 if ( intr )
67 iWakeupThread(thid);
68 else
69 WakeupThread(thid);
70 }
71 Kprintf("acata:A:dma_error: state=%d ret=%d\n", state, result);
72}
73
74static int ata_ops_command(struct ac_ata_h *atah, int cmdpri, int pri)
75{
76 int flag;
77 int ret;
78 const acAtaCommandData *cmd;
79 int count;
80 int flag_v8;
81 int v16;
82 int ret_v22;
83 int sr_v34;
84 int ret_v35;
85 acAtaCommandData *cmd_v36;
86 int rest_v37;
87 struct ata_dma dma_data;
88 acAtaT ata;
89
90 ata = (acAtaT)atah;
91 flag = atah->a_flag;
92 ret = 0;
93 if ( atah->a_state >= 0x1FFu )
94 {
95 return -116;
96 }
97 atah->a_state = 7;
98 if ( (flag & 1) != 0 )
99 {
100 acDmaT dma;
101 int ret_v3;
102
103 dma = acDmaSetup(&dma_data.ad_dma, &ops_8, 4, 8, flag & 4);
104 dma_data.ad_result = 0;
105 // cppcheck-suppress unreadVariable
106 dma_data.ad_thid = GetThreadId();
107 // cppcheck-suppress unreadVariable
108 dma_data.ad_ata = ata;
109 dma_data.ad_state = 0;
110 ret_v3 = acDmaRequest(dma);
111 if ( ret_v3 < 0 )
112 {
113 printf("acata:A:dma_wait: error %d\n", ret_v3);
114 return ret_v3;
115 }
116 while ( 1 )
117 {
118 int ret_v5;
119
120 ret_v5 = dma_data.ad_state;
121 if ( ret_v5 )
122 {
123 if ( (int)ret_v5 <= 0 )
124 {
125 printf("acata:A:dma_wait: TIMEDOUT %d\n", ret_v5);
126 acDmaCancel(&dma_data.ad_dma, -116);
127 ret = ret_v5;
128 if ( ret_v5 >= 0 )
129 ret = -116;
130 if ( ret < 0 )
131 {
132 return ret;
133 }
134 }
135 break;
136 }
137 if ( SleepThread() )
138 break;
139 }
140 }
141 ChangeThreadPriority(0, cmdpri);
142 cmd = ata->ac_command;
143 count = 5;
144 flag_v8 = atah->a_flag;
145 *((volatile acUint16 *)0xB6060000) = flag_v8 & 0x10;
146 *((volatile acUint16 *)0xB6160000) = (flag_v8 & 2) ^ 2;
147 *((volatile acUint16 *)0xB6010000) = 0;
148 while ( count >= 0 )
149 {
150 int data;
151
152 data = *cmd++;
153 *(acUint16 *)(((2 * ((data >> 8) & 8) + ((data >> 8) & 7)) << 16) + 0xB6000000) = data & 0xFF;
154 --count;
155 if ( ((data >> 8) & 0xF) == 7 )
156 {
157 break;
158 }
159 }
160 ChangeThreadPriority(0, pri);
161 // cppcheck-suppress knownConditionTrueFalse
162 if ( atah->a_state >= 0x1FFu )
163 {
164 return -116;
165 }
166 atah->a_state = 31;
167 if ( atah->a_buf )
168 {
169 if ( (flag_v8 & 1) != 0 )
170 {
171 dma_data.ad_state = 31;
172 acDmaRequest(&dma_data.ad_dma);
173 printf("acata:dma start\n");
174 }
175 else
176 {
177 acUint16 *a_buf;
178
179 a_buf = (acUint16 *)atah->a_buf;
180 if ( (flag_v8 & 4) != 0 )
181 {
182 int a_size;
183
184 a_size = atah->a_size;
185 while ( (*((volatile acUint16 *)0xB6070000) & 0x80) != 0 )
186 ;
187 while ( a_size > 0 )
188 {
189 int xlen;
190 int xlen_v15;
191 int xlen_v16;
192 int sr;
193 int ret_v20;
194
195 xlen = 512;
196 if ( a_size < 513 )
197 xlen = a_size;
198 a_size -= xlen;
199 xlen_v15 = (unsigned int)xlen >> 1;
200 xlen_v16 = xlen_v15 - 1;
201 while ( (*((volatile acUint16 *)0xB6070000) & 8) != 0 )
202 {
203 int ret_v17;
204
205 ret_v17 = 0;
206 if ( xlen_v16 >= 0 )
207 {
208 ret_v17 = *a_buf;
209 a_buf++;
210 }
211 *((volatile acUint16 *)0xB6000000) = ret_v17;
212 --xlen_v16;
213 }
214 if ( (flag_v8 & 2) != 0 )
215 {
216 sr = *((volatile acUint16 *)0xB6160000);
217 ret_v20 = sr & 0xFF;
218 while ( (*((volatile acUint16 *)0xB6160000) & 0x80) != 0 )
219 {
220 ret_v20 = -116;
221 if ( SleepThread() != 0 )
222 break;
223 ret_v20 = *((volatile acUint16 *)0xB6160000);
224 }
225 }
226 else
227 {
228 ret_v20 = *((volatile acUint16 *)0xB6070000);
229 while ( (*((volatile acUint16 *)0xB6070000) & 0x80) != 0 )
230 {
231 sr = *((volatile acUint16 *)0xB6070000);
232 ret_v20 = sr & 0xFF;
233 }
234 }
235 if ( ret_v20 < 0 )
236 break;
237 if ( (ret_v20 & 8) == 0 )
238 break;
239 }
240 }
241 else
242 {
243 acUint16 *buf_v23;
244 int rest;
245
246 buf_v23 = (acUint16 *)atah->a_buf;
247 rest = atah->a_size;
248 while ( rest > 0 )
249 {
250 int sr_v25;
251 int xlen_v27;
252 int xlen_v28;
253 int ret_v29;
254 int xlen_v30;
255
256 if ( (flag_v8 & 2) != 0 )
257 {
258 sr_v25 = *((volatile acUint16 *)0xB6160000);
259 sr_v25 = sr_v25 & 0xFF;
260 while ( (*((volatile acUint16 *)0xB6160000) & 0x80) != 0 )
261 {
262 sr_v25 = -116;
263 if ( SleepThread() )
264 break;
265 sr_v25 = *((volatile acUint16 *)0xB6160000);
266 }
267 }
268 else
269 {
270 sr_v25 = *((volatile acUint16 *)0xB6070000);
271 while ( (*((volatile acUint16 *)0xB6070000) & 0x80) != 0 )
272 {
273 sr_v25 = *((volatile acUint16 *)0xB6070000);
274 sr_v25 = sr_v25 & 0xFF;
275 }
276 }
277 if ( sr_v25 < 0 )
278 break;
279 xlen_v27 = 512;
280 if ( rest < 513 )
281 xlen_v27 = rest;
282 rest -= xlen_v27;
283 xlen_v28 = (unsigned int)xlen_v27 >> 1;
284 if ( (sr_v25 & 1) != 0 )
285 xlen_v28 = 0;
286 (void)(*((volatile acUint16 *)0xB6070000) & 0x80);
287 xlen_v30 = xlen_v28 - 1;
288 while ( (*((volatile acUint16 *)0xB6070000) & 8) != 0 )
289 {
290 if ( xlen_v30 >= 0 )
291 {
292 *buf_v23 = *((volatile acUint16 *)0xB6000000);
293 buf_v23++;
294 }
295 --xlen_v30;
296 }
297 ret_v29 = *((volatile acUint16 *)0xB6070000) & 0x80;
298 if ( !ret_v29 )
299 break;
300 }
301 }
302 }
303 }
304 v16 = flag_v8 & 2;
305 ret_v22 = flag_v8 & 1;
306 if ( ret_v22 )
307 {
308 signed int state;
309
310 state = 63;
311 while ( 1 )
312 {
313 int v38;
314
315 v38 = *((volatile acUint16 *)0xB6160000) & 1;
316 if ( v38 || state >= 511 )
317 {
318 printf(
319 "acata:A:dma_iowait: TIMEDOUT %04x:%02x:%02x\n",
320 state,
321 *((volatile acUint16 *)0xB6160000),
322 *((volatile acUint16 *)0xB6010000));
323 if ( state < 1023 )
324 acDmaCancel(&dma_data.ad_dma, -116);
325 ret = 0;
326 if ( !v38 )
327 ret = -116;
328 break;
329 }
330 state = dma_data.ad_state;
331 if ( (*((volatile acUint16 *)0xB6160000) & 0x80) == 0 && (int)dma_data.ad_state >= 64 )
332 {
333 ret = dma_data.ad_result;
334 break;
335 }
336 if ( SleepThread() )
337 {
338 state = 511;
339 if ( dma_data.ad_state == 31 )
340 state = 1023;
341 }
342 }
343 }
344 else
345 {
346 ret = 0;
347 if ( v16 )
348 {
349 while ( (*((volatile acUint16 *)0xB6160000) & 0x81) == 128 )
350 {
351 if ( SleepThread() )
352 {
353 ret = -116;
354 break;
355 }
356 }
357 }
358 else
359 {
360 int tmout;
361
362 tmout = 99999;
363 while ( (*((volatile acUint16 *)0xB6070000) & 0x81) == 128 )
364 {
365 if ( tmout < 0 )
366 {
367 ret = -116;
368 break;
369 }
370 --tmout;
371 }
372 }
373 if ( ret < 0 )
374 {
375 printf("acata:C:io_done: TIMEDOUT\n");
376 }
377 }
378 if ( ret < 0 )
379 {
380 return ret;
381 }
382 sr_v34 = *((volatile acUint16 *)0xB6070000);
383 if ( (*((volatile acUint16 *)0xB6070000) & 1) != 0 )
384 return -((sr_v34 << 8) + *((volatile acUint16 *)0xB6010000));
385 if ( atah->a_state < 0x1FFu )
386 {
387 atah->a_state = 127;
388 ret_v35 = 0;
389 }
390 else
391 {
392 ret_v35 = -116;
393 }
394 cmd_v36 = ata->ac_command;
395 if ( ret_v35 < 0 )
396 {
397 return -((sr_v34 << 8) + *((volatile acUint16 *)0xB6010000));
398 }
399 for ( rest_v37 = 6; rest_v37 > 0; --rest_v37 )
400 {
401 if ( (((int)*cmd_v36 >> 12) & 0xF) == 0 )
402 break;
403 *cmd_v36 =
404 ((((int)*cmd_v36 >> 12) & 0xF) << 12)
405 | ((*(acUint16 *)(((2 * (((int)*cmd_v36 >> 12) & 8) + (((int)*cmd_v36 >> 12) & 7)) << 16) + 0xB6000000)) & 0xFF);
406 ++cmd_v36;
407 }
408 return 6 - rest_v37;
409}
410
411static void ata_ops_done(struct ac_ata_h *atah, int result)
412{
413 acAtaDone ac_done;
414 acAtaT ata;
415
416 ata = (acAtaT)atah;
417 ac_done = ata->ac_done;
418 if ( ac_done )
419 ac_done(ata, atah->a_arg, result);
420}
421
422acAtaT acAtaSetup(acAtaData *ata, acAtaDone done, void *arg, unsigned int tmout)
423{
424 if ( ata )
425 {
426 ata->ac_h.a_ops = &ops_37;
427 ata->ac_h.a_arg = arg;
428 ata->ac_h.a_tmout = tmout;
429 ata->ac_h.a_state = 0;
430 ata->ac_h.a_flag = 0;
431 ata->ac_done = done;
432 }
433 return ata;
434}
435
436acAtaCommandData *acAtaReply(acAtaT ata)
437{
438 if ( ata == 0 )
439 return 0;
440 return ata->ac_command;
441}
442
443int acAtaRequest(acAtaT ata, int flag, acAtaCommandData *cmd, int item, void *buf, int size)
444{
445 int v7;
446 const acAtaCommandData *v8;
447 char *v9;
448
449 flag = (flag | 8) ^ 8;
450 if ( !ata || !cmd )
451 {
452 return -22;
453 }
454 if ( (unsigned int)item >= 7 )
455 {
456 return -34;
457 }
458 v7 = item - 1;
459 ata->ac_h.a_flag = flag;
460 v8 = &cmd[v7];
461 v9 = (char *)ata + 2 * v7;
462 while ( v7 >= 0 )
463 {
464 --v7;
465 *((acUint16 *)v9 + 18) = *v8--;
466 v9 -= 2;
467 }
468 ata->ac_h.a_buf = buf;
469 ata->ac_h.a_size = size;
470 return ata_request(&ata->ac_h, WakeupThread);
471}
472
473int acAtaRequestI(acAtaT ata, int flag, acAtaCommandData *cmd, int item, void *buf, int size)
474{
475 int v7;
476 const acAtaCommandData *v8;
477 char *v9;
478
479 flag = (flag | 8) ^ 8;
480 if ( !ata || !cmd )
481 {
482 return -22;
483 }
484 if ( (unsigned int)item >= 7 )
485 {
486 return -34;
487 }
488 v7 = item - 1;
489 ata->ac_h.a_flag = flag;
490 v8 = &cmd[v7];
491 v9 = (char *)ata + 2 * v7;
492 while ( v7 >= 0 )
493 {
494 --v7;
495 *((acUint16 *)v9 + 18) = *v8--;
496 v9 -= 2;
497 }
498 ata->ac_h.a_buf = buf;
499 ata->ac_h.a_size = size;
500 return ata_request(&ata->ac_h, iWakeupThread);
501}
502
503int acAtaStatus(acAtaT ata)
504{
505 int state;
506
507 if ( ata == 0 )
508 {
509 return -22;
510 }
511 state = ata->ac_h.a_state;
512 if ( (unsigned int)(state - 1) >= 0x7E )
513 {
514 return 0;
515 }
516 if ( state != 1 )
517 return 2;
518 return 1;
519}
Definition acata.h:46
u32 count
start sector of fragmented bd/file