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