PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
atapicmd.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 atapi_dma_xfer(acDmaT dma, int intr, acDmaOp op);
14static void atapi_dma_done(acDmaT dma);
15static void atapi_dma_error(acDmaT dma, int intr, acDmaState state, int result);
16static int atapi_ops_command(struct ac_ata_h *atah, int cmdpri, int pri);
17static void atapi_ops_done(struct ac_ata_h *atah, int result);
18static int atapi_ops_error(struct ac_ata_h *atah, int ret);
19
20static acDmaOpsData ops_8_0 = {&atapi_dma_xfer, &atapi_dma_done, &atapi_dma_error};
21static struct ac_ata_ops ops_48 = {&atapi_ops_command, &atapi_ops_done, &atapi_ops_error};
22
23static int atapi_dma_xfer(acDmaT dma, int intr, acDmaOp op)
24{
25 struct atapi_dma *dmatmp;
26 int thid;
27
28 dmatmp = (struct atapi_dma *)dma;
29 if ( dmatmp->ad_state == 31 )
30 {
31 dmatmp->ad_result = dmatmp->ad_atapi->ap_h.a_size;
32 return op(dma, (void *)0xB6000000, dmatmp->ad_atapi->ap_h.a_buf, dmatmp->ad_atapi->ap_h.a_size);
33 }
34 thid = dmatmp->ad_thid;
35 dmatmp->ad_state = 3;
36 if ( intr )
37 iWakeupThread(thid);
38 else
39 WakeupThread(thid);
40 return 0;
41}
42
43static void atapi_dma_done(acDmaT dma)
44{
45 struct atapi_dma *dmatmp;
46 int thid;
47
48 dmatmp = (struct atapi_dma *)dma;
49 thid = dmatmp->ad_thid;
50 dmatmp->ad_state = 127;
51 if ( thid )
52 iWakeupThread(thid);
53}
54
55static void atapi_dma_error(acDmaT dma, int intr, acDmaState state, int result)
56{
57 struct atapi_dma *dmatmp;
58 int thid;
59
60 dmatmp = (struct atapi_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:P:dma_error: state=%d ret=%d\n", state, result);
72}
73
74static int atapi_packet_send(acAtaReg atareg, acAtapiPacketData *pkt, int flag)
75{
76 int count;
77 int tmout;
78 int v6;
79
80 (void)atareg;
81 count = 6;
82 *((volatile acUint16 *)0xB6050000) = 0;
83 *((volatile acUint16 *)0xB6040000) = 64;
84 *((volatile acUint16 *)0xB6060000) = flag & 0x10;
85 *((volatile acUint16 *)0xB6160000) = (flag & 2) ^ 2;
86 *((volatile acUint16 *)0xB6010000) = flag & 1;
87 *((volatile acUint16 *)0xB6070000) = 160;
88 tmout = 999;
89 v6 = 1000;
90 // cppcheck-suppress knownConditionTrueFalse
91 while ( (*((volatile acUint16 *)0xB6070000) & 0x80) != 0 )
92 {
93 if ( tmout < 0 )
94 {
95 printf("acata:P:wait: TIMEDOUT\n");
96 v6 = -116;
97 break;
98 }
99 --tmout;
100 v6 = tmout + 1;
101 }
102 if ( v6 < 0 )
103 {
104 printf("acata:P:packet_send: TIMEDOUT\n");
105 return -116;
106 }
107 // cppcheck-suppress knownConditionTrueFalse
108 while ( (*((volatile acUint16 *)0xB6070000) & 8) != 0 )
109 {
110 --count;
111 if ( count < 0 )
112 break;
113 *((volatile acUint16 *)0xB6000000) = pkt->u_h[0];
114 pkt = (acAtapiPacketData *)((char *)pkt + 2);
115 }
116 return 0;
117}
118
119static int atapi_pio_read(acAtaReg atareg, acUint16 *buf, int count, int flag)
120{
121 char v6;
122 int rest;
123 int sr;
124 int xlen;
125 int sr_v5;
126 int drop_v10;
127
128 (void)atareg;
129 v6 = flag;
130 rest = count;
131 sr = flag & 2;
132 while ( 1 )
133 {
134 int xlen_v6;
135 int drop;
136 int xlen_v8;
137 int sr_v9;
138
139 if ( !sr )
140 {
141 sr_v5 = *((volatile acUint16 *)0xB6070000);
142 while ( (sr_v5 & 0x80) != 0 )
143 {
144 xlen = *((volatile acUint16 *)0xB6070000);
145 sr_v5 = xlen & 0xFF;
146 }
147 }
148 else
149 {
150 xlen = *((volatile acUint16 *)0xB6160000);
151 sr_v5 = xlen & 0xFF;
152 while ( (sr_v5 & 0x80) != 0 )
153 {
154 sr_v5 = -116;
155 if ( SleepThread() != 0 )
156 break;
157 sr_v5 = *((volatile acUint16 *)0xB6160000);
158 }
159 }
160 if ( sr_v5 < 0 )
161 return sr_v5;
162 if ( (sr_v5 & 8) == 0 )
163 break;
164 xlen_v6 = (*((volatile acUint16 *)0xB6050000) << 8) + *((volatile acUint16 *)0xB6040000);
165 drop = xlen_v6 - rest;
166 if ( rest >= xlen_v6 )
167 drop = 0;
168 else
169 xlen_v6 = rest;
170 rest -= xlen_v6;
171 xlen_v8 = (xlen_v6 + 1) / 2 - 1;
172 while ( xlen_v8 >= 0 )
173 {
174 --xlen_v8;
175 *buf++ = *((volatile acUint16 *)0xB6000000);
176 }
177 sr_v9 = drop + 1;
178 for ( drop_v10 = sr_v9 / 2 - 1; drop_v10 >= 0; --drop_v10 )
179 ;
180 sr = v6 & 2;
181 if ( (*((volatile acUint16 *)0xB6070000) & 0x80) == 0 )
182 {
183 break;
184 }
185 }
186 return count - rest;
187}
188
189static int atapi_ops_command(struct ac_ata_h *atah, int cmdpri, int pri)
190{
191 int flag;
192 int ret_v5;
193 int v28;
194 struct atapi_dma dma_data;
195 acAtapiT atapi;
196
197 atapi = (acAtapiT)atah;
198 flag = atah->a_flag;
199 if ( (flag & 1) == 0 )
200 {
201 ret_v5 = 0;
202 }
203 else
204 {
205 acDmaT dma;
206 int v8;
207 int ret;
208
209 dma = acDmaSetup(&dma_data.ad_dma, &ops_8_0, 4, 64, flag & 4);
210 dma_data.ad_result = 0;
211 // cppcheck-suppress unreadVariable
212 dma_data.ad_thid = GetThreadId();
213 // cppcheck-suppress unreadVariable
214 dma_data.ad_atapi = atapi;
215 dma_data.ad_state = 0;
216 v8 = acDmaRequest(dma);
217 ret = v8;
218 if ( v8 < 0 )
219 {
220 printf("acata:P:dma_wait: error %d\n", v8);
221 ret_v5 = ret;
222 }
223 else
224 {
225 while ( 1 )
226 {
227 int flg;
228
229 flg = 0;
230 ret_v5 = dma_data.ad_state;
231 if ( ret_v5 )
232 {
233 if ( (int)ret_v5 > 0 )
234 {
235 ret_v5 = 0;
236 break;
237 }
238 flg = 1;
239 }
240 if ( flg == 0 && SleepThread() )
241 flg = 1;
242 if ( flg != 0 )
243 {
244 printf("acata:P:dma_wait: TIMEDOUT %d\n", ret_v5);
245 acDmaCancel(&dma_data.ad_dma, -116);
246 if ( ret_v5 >= 0 )
247 {
248 ret_v5 = -116;
249 }
250 break;
251 }
252 }
253 }
254 }
255 if ( ret_v5 < 0 )
256 return ret_v5;
257 ChangeThreadPriority(0, cmdpri);
258 ret_v5 = atapi_packet_send((acAtaReg)0xB6000000, &atapi->ap_packet, flag);
259 if ( ret_v5 >= 0 )
260 {
261 int v12;
262 if ( atah->a_state < 0x1FFu )
263 {
264 atah->a_state = 31;
265 v12 = 0;
266 }
267 else
268 {
269 v12 = -116;
270 }
271 ret_v5 = -116;
272 if ( v12 >= 0 )
273 {
274 acUint16 *a_buf;
275
276 a_buf = (acUint16 *)atah->a_buf;
277 if ( !a_buf )
278 {
279 ret_v5 = 0;
280 }
281 else if ( (flag & 1) != 0 )
282 {
283 dma_data.ad_state = 31;
284 ret_v5 = acDmaRequest(&dma_data.ad_dma);
285 }
286 else
287 {
288 int size;
289 acUint16 *v15;
290
291 size = atah->a_size;
292 v15 = (acUint16 *)atah->a_buf;
293 if ( (flag & 4) == 0 )
294 {
295 ret_v5 = atapi_pio_read((acAtaReg)0xB6000000, a_buf, atah->a_size, flag);
296 }
297 else
298 {
299 signed int a_size;
300 int sr;
301
302 a_size = atah->a_size;
303 sr = flag & 2;
304 while ( 1 )
305 {
306 int xlen;
307 int sr_v14;
308 int xlen_v15;
309 int drop;
310 int xlen_v17;
311 int sr_v18;
312 int drop_v20;
313
314 if ( sr )
315 {
316 xlen = *((volatile acUint16 *)0xB6160000);
317 sr_v14 = xlen & 0xFF;
318 while ( (sr_v14 & 0x80) != 0 )
319 {
320 sr_v14 = -116;
321 if ( SleepThread() != 0 )
322 break;
323 sr_v14 = *((volatile acUint16 *)0xB6160000);
324 }
325 }
326 else
327 {
328 sr_v14 = *((volatile acUint16 *)0xB6070000);
329 while ( (sr_v14 & 0x80) != 0 )
330 {
331 xlen = *((volatile acUint16 *)0xB6070000);
332 sr_v14 = xlen & 0xFF;
333 }
334 }
335 ret_v5 = sr_v14;
336 if ( sr_v14 < 0 )
337 break;
338 if ( (sr_v14 & 8) == 0 )
339 {
340 ret_v5 = size - a_size;
341 break;
342 }
343 xlen_v15 = (*((volatile acUint16 *)0xB6050000) << 8) + *((volatile acUint16 *)0xB6040000);
344 drop = xlen_v15 - a_size;
345 if ( a_size >= xlen_v15 )
346 drop = 0;
347 else
348 xlen_v15 = a_size;
349 a_size -= xlen_v15;
350 xlen_v17 = (xlen_v15 + 1) / 2 - 1;
351 for ( sr_v18 = drop + 1; xlen_v17 >= 0; sr_v18 = drop + 1 )
352 {
353 *((volatile acUint16 *)0xB6000000) = *v15;
354 v15++;
355 --xlen_v17;
356 }
357 for ( drop_v20 = sr_v18 / 2 - 1; drop_v20 >= 0; --drop_v20 )
358 *((volatile acUint16 *)0xB6000000) = 0;
359 sr = flag & 2;
360 if ( (*((volatile acUint16 *)0xB6070000) & 0x80) == 0 )
361 {
362 ret_v5 = size - a_size;
363 break;
364 }
365 }
366 }
367 }
368 }
369 }
370 ChangeThreadPriority(0, pri);
371 if ( ret_v5 < 0 )
372 return ret_v5;
373 if ( atah->a_state < 0x1FFu )
374 {
375 atah->a_state = 63;
376 v28 = 0;
377 }
378 else
379 {
380 v28 = -116;
381 }
382 if ( v28 < 0 )
383 return -116;
384 if ( (flag & 1) == 0 )
385 {
386 int v32;
387
388 v32 = 0;
389 if ( (flag & 2) != 0 )
390 {
391 while ( (*((volatile acUint16 *)0xB6160000) & 0x81) == 128 )
392 {
393 if ( SleepThread() )
394 {
395 v32 = -116;
396 break;
397 }
398 }
399 }
400 else
401 {
402 int tmout;
403
404 tmout = 99999;
405 while ( (*((volatile acUint16 *)0xB6070000) & 0x81) == 128 )
406 {
407 if ( tmout < 0 )
408 {
409 v32 = -116;
410 break;
411 }
412 --tmout;
413 }
414 }
415 if ( v32 < 0 )
416 {
417 printf("acata:C:io_done: TIMEDOUT\n");
418 ret_v5 = -116;
419 }
420 }
421 else
422 {
423 signed int ret_v23;
424 acInt32 ad_result;
425
426 ret_v23 = 63;
427 while ( 1 )
428 {
429 int v30;
430
431 v30 = *((volatile acUint16 *)0xB6160000) & 1;
432 if ( v30 || ret_v23 >= 511 )
433 {
434 printf(
435 "acata:P:dma_iowait: TIMEDOUT %04x:%02x:%02x\n",
436 ret_v23,
437 *((volatile acUint16 *)0xB6160000),
438 *((volatile acUint16 *)0xB6010000));
439 if ( ret_v23 < 1023 )
440 acDmaCancel(&dma_data.ad_dma, -116);
441 ad_result = 0;
442 if ( !v30 )
443 ad_result = -116;
444 break;
445 }
446 ret_v23 = dma_data.ad_state;
447 if ( (*((volatile acUint16 *)0xB6160000) & 0x80) == 0 && (int)dma_data.ad_state >= 64 )
448 {
449 ad_result = dma_data.ad_result;
450 break;
451 }
452 if ( SleepThread() )
453 {
454 ret_v23 = 511;
455 if ( dma_data.ad_state == 31 )
456 ret_v23 = 1023;
457 }
458 }
459 ret_v5 = ad_result;
460 }
461 if ( ret_v5 < 0 )
462 return ret_v5;
463 if ( (*((volatile acUint16 *)0xB6070000) & 1) != 0 )
464 return -((*((volatile acUint16 *)0xB6070000) << 8) + *((volatile acUint16 *)0xB6010000));
465 if ( atah->a_state >= 0x1FFu )
466 {
467 return -116;
468 }
469 atah->a_state = 127;
470 return ret_v5;
471}
472
473static void atapi_ops_done(struct ac_ata_h *atah, int result)
474{
475 acAtapiDone ap_done;
476 acAtapiT atapi;
477
478 atapi = (acAtapiT)atah;
479 ap_done = atapi->ap_done;
480 if ( ap_done )
481 ap_done(atapi, atah->a_arg, result);
482}
483
484static int atapi_ops_error(struct ac_ata_h *atah, int ret)
485{
486 int flag;
487 int v3;
488 struct atapi_sense sense;
489 union
490 {
491 struct
492 {
493 acUint8 opcode;
494 acUint8 lun;
495 // cppcheck-suppress unusedStructMember
496 acUint8 padding[2];
497 acUint8 len;
498 // cppcheck-suppress unusedStructMember
499 acUint8 padding2[7];
500 };
502 } u;
503 acAtapiT atapi;
504
505 atapi = (acAtapiT)atah;
506 if ( (*((volatile acUint16 *)0xB6070000) & 1) == 0 )
507 return ret;
508 memset(&sense, 0, sizeof(sense));
509 memset(&u, 0, sizeof(u));
510 flag = atah->a_flag;
511 u.opcode = 0x03;
512 u.len = 0x12;
513 u.lun = atapi->ap_packet.u_b[1];
514 *((volatile acUint16 *)0xB6160000) = (flag & 2) ^ 2;
515 *((volatile acUint16 *)0xB6010000) = 0;
516 v3 = atapi_packet_send((acAtaReg)0xB6000000, &u.pkt, flag);
517 if ( v3 < 0 )
518 {
519 ret = v3;
520 }
521 else
522 {
523 int v4;
524 int v5;
525
526 v4 = atapi_pio_read((acAtaReg)0xB6000000, (acUint16 *)&sense, sizeof(sense), flag);
527 v5 = v4;
528 if ( v4 > 0 )
529 {
530 int v6;
531
532 v6 = 0;
533 if ( (flag & 2) != 0 )
534 {
535 while ( (*((volatile acUint16 *)0xB6160000) & 0x81) == 128 )
536 {
537 if ( SleepThread() )
538 {
539 v6 = -116;
540 break;
541 }
542 }
543 }
544 else
545 {
546 int tmout;
547
548 tmout = 99999;
549 while ( (*((volatile acUint16 *)0xB6070000) & 0x81) == 128 )
550 {
551 if ( tmout < 0 )
552 {
553 v6 = -116;
554 break;
555 }
556 --tmout;
557 }
558 }
559 if ( v6 < 0 )
560 {
561 printf("acata:C:io_done: TIMEDOUT\n");
562 v6 = -116;
563 }
564 v3 = v5;
565 if ( v6 < 0 )
566 v3 = -116;
567 ret = v3;
568 }
569 else
570 {
571 ret = v4;
572 if ( !v4 )
573 {
574 v3 = -5;
575 ret = v3;
576 }
577 }
578 }
579 if ( ret > 0 )
580 return -((sense.s_key << 16) | (sense.s_asc << 8) | sense.s_ascq);
581 if ( !ret )
582 return -5;
583 return ret;
584}
585
586acAtapiT acAtapiSetup(acAtapiData *atapi, acAtapiDone done, void *arg, unsigned int tmout)
587{
588 if ( atapi )
589 {
590 atapi->ap_h.a_ops = &ops_48;
591 atapi->ap_h.a_arg = arg;
592 atapi->ap_h.a_tmout = tmout;
593 atapi->ap_h.a_state = 0;
594 atapi->ap_h.a_flag = 0;
595 atapi->ap_done = done;
596 }
597 return atapi;
598}
599
600int acAtapiRequest(acAtapiT atapi, int flag, acAtapiPacketData *pkt, void *buf, int size)
601{
602 flag = flag | 8;
603 if ( !atapi || !pkt )
604 {
605 return -22;
606 }
607 atapi->ap_h.a_flag = flag;
608 atapi->ap_packet.u_w[0] = pkt->u_w[0];
609 atapi->ap_packet.u_w[1] = pkt->u_w[1];
610 atapi->ap_packet.u_w[2] = pkt->u_w[2];
611 atapi->ap_h.a_buf = buf;
612 atapi->ap_h.a_size = size;
613 return ata_request(&atapi->ap_h, WakeupThread);
614}
615
616int acAtapiRequestI(acAtapiT atapi, int flag, acAtapiPacketData *pkt, void *buf, int size)
617{
618 flag = flag | 8;
619 if ( !atapi || !pkt )
620 {
621 return -22;
622 }
623 atapi->ap_h.a_flag = flag;
624 atapi->ap_packet.u_w[0] = pkt->u_w[0];
625 atapi->ap_packet.u_w[1] = pkt->u_w[1];
626 atapi->ap_packet.u_w[2] = pkt->u_w[2];
627 atapi->ap_h.a_buf = buf;
628 atapi->ap_h.a_size = size;
629 return ata_request(&atapi->ap_h, iWakeupThread);
630}
631
632int acAtapiStatus(acAtapiT atapi)
633{
634 int state;
635
636 if ( atapi == 0 )
637 {
638 return -22;
639 }
640 state = atapi->ap_h.a_state;
641 if ( (unsigned int)(state - 1) >= 0x7E )
642 {
643 return 0;
644 }
645 if ( state != 1 )
646 return 2;
647 return 1;
648}
u32 count
start sector of fragmented bd/file