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