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