PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ata.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 struct ata_softc Atac;
15
16static void ata_timer_done(acTimerT timer, struct ata_softc *arg)
17{
18 struct ac_ata_h *atah;
19 int thid;
20
21 (void)timer;
22 atah = arg->atah;
23 thid = arg->thid;
24 Kprintf("acata:timer_done\n");
25 atah->a_state = 511;
26 if ( thid )
27 iReleaseWaitThread(thid);
28}
29
30static void ata_thread(void *arg)
31{
32 int thid;
33 acQueueT q_next;
34 struct ac_ata_h *atah;
35 struct ac_ata_h *_next_;
36 acUint32 tmout;
37 acAtaOpsT a_ops;
38 int v10;
39 acSpl state;
40 struct ata_softc *argt;
41
42 argt = (struct ata_softc *)arg;
43 thid = GetThreadId();
44 argt->thid = thid;
45 while ( 1 )
46 {
47 CpuSuspendIntr(&state);
48 q_next = argt->requestq.q_next;
49 atah = 0;
50 if ( q_next )
51 {
52 atah = (struct ac_ata_h *)argt->requestq.q_next;
53 if ( argt == (struct ata_softc *)q_next )
54 {
55 atah = 0;
56 argt->requestq.q_prev = 0;
57 argt->requestq.q_next = 0;
58 }
59 else
60 {
61 _next_ = (struct ac_ata_h *)q_next->q_next;
62 _next_->a_chain.q_prev = q_next->q_prev;
63 argt->requestq.q_next = &_next_->a_chain;
64 }
65 }
66 argt->atah = atah;
67 CpuResumeIntr(state);
68 if ( atah )
69 {
70 tmout = atah->a_tmout;
71 a_ops = atah->a_ops;
72 if ( !tmout )
73 tmout = 5000000;
74 atah->a_state = 3;
75 acTimerAdd(&argt->timer, (acTimerDone)ata_timer_done, argt, tmout);
76 v10 = a_ops->ao_command(atah, 32, 78);
77 acTimerRemove(&argt->timer);
78 if ( v10 < 0 && a_ops->ao_error )
79 {
80 acTimerAdd(&argt->timer, (acTimerDone)ata_timer_done, argt, 0xF4240u);
81 v10 = a_ops->ao_error(atah, v10);
82 acTimerRemove(&argt->timer);
83 }
84 argt->atah = 0;
85 a_ops->ao_done(atah, v10);
86 CancelWakeupThread(0);
87 }
88 else
89 {
90 SleepThread();
91 }
92 if ( thid != argt->thid )
93 ExitThread();
94 }
95}
96
97static int ata_intr(const struct ata_softc *arg)
98{
99 if ( arg )
100 {
101 int thid;
102
103 thid = arg->thid;
104 *((volatile acUint16 *)0xB3000000) = 0;
105 if ( thid )
106 iWakeupThread(thid);
107 }
108 return 1;
109}
110
111int ata_request(struct ac_ata_h *atah, int (*wakeup)(int thid))
112{
113 int unit;
114 int thid;
115 acQueueT q_prev;
116 acSpl state;
117
118 CpuSuspendIntr(&state);
119 unit = 1;
120 if ( (atah->a_flag & 0x10) != 0 )
121 unit = 2;
122 thid = Atac.thid;
123 if ( (Atac.active & unit) == 0 )
124 {
125 thid = 0;
126 }
127 else
128 {
129 if ( Atac.thid == 0 )
130 {
131 wakeup = 0;
132 }
133 else
134 {
135 if ( Atac.requestq.q_next )
136 {
137 wakeup = 0;
138 }
139 else
140 {
141 Atac.requestq.q_prev = (acQueueT)&Atac;
142 Atac.requestq.q_next = (acQueueT)&Atac;
143 }
144 q_prev = Atac.requestq.q_prev;
145 atah->a_chain.q_next = (acQueueT)&Atac;
146 atah->a_chain.q_prev = q_prev;
147 q_prev->q_next = &atah->a_chain;
148 Atac.requestq.q_prev = &atah->a_chain;
149 if ( wakeup )
150 atah->a_state = 3;
151 else
152 atah->a_state = 1;
153 }
154 }
155 CpuResumeIntr(state);
156 if ( thid == 0 )
157 {
158 return -6;
159 }
160 if ( wakeup == 0 )
161 {
162 return 0;
163 }
164 wakeup(thid);
165 return 1;
166}
167
168static int ata_thread_init(struct ata_softc *atac, int priority)
169{
170 int th;
171 iop_thread_t param;
172
173 param.attr = 0x2000000;
174 param.thread = ata_thread;
175 param.priority = priority;
176 param.stacksize = 0x800;
177 param.option = 0;
178 th = CreateThread(&param);
179 if ( th > 0 )
180 StartThread(th, atac);
181 return th;
182}
183
184int ata_probe(acAtaReg atareg)
185{
186 int active;
187 int unit;
188 int count;
189
190 (void)atareg;
191 while ( (*((volatile acUint16 *)0xB6070000) & ATA_STAT_BUSY) != 0 )
192 ;
193 *((volatile acUint16 *)0xB6020000) = 4660;
194 // cppcheck-suppress knownConditionTrueFalse
195 if ( *((volatile acUint16 *)0xB6020000) != 52 )
196 return 0;
197 *((volatile acUint16 *)0xB6030000) = 18;
198 // cppcheck-suppress knownConditionTrueFalse
199 if ( *((volatile acUint16 *)0xB6030000) != 18 )
200 return 0;
201 active = 0;
202 unit = 0;
203 *((volatile acUint16 *)0xB6160000) = 2;
204 *((volatile acUint16 *)0xB6010000) = 0;
205 count = 0;
206 while ( unit < 2 )
207 {
208 *((volatile acUint16 *)0xB6060000) = 16 * (unit != 0);
209 *((volatile acUint16 *)0xB6070000) = 0;
210 *((volatile acUint16 *)0xB6070000) = 0;
211 while ( count <= 1999999 )
212 {
213 // cppcheck-suppress knownConditionTrueFalse
214 if ( (*((volatile acUint16 *)0xB6070000) & ATA_STAT_BUSY) == 0 )
215 break;
216 ++count;
217 }
218 if ( count )
219 active |= 1 << unit;
220 ++unit;
221 count = 0;
222 }
223 return active;
224}
225
226static int ata_module_optarg(const char *str, int default_value)
227{
228 int result;
229 char *next;
230
231 result = strtol(str, &next, 0);
232 if ( next == str )
233 return default_value;
234 return result;
235}
236
237int acAtaModuleStart(int argc, char **argv)
238{
239 int cmdprio;
240 int prio;
241 int delay;
242 int index;
243 char **v11;
244 char *opt;
245 int v13;
246 const char *opt_v10;
247 const char *opt_v11;
248 int index_v12;
249 char *msg;
250
251 if ( acAtaModuleStatus() != 0 )
252 {
253 return -16;
254 }
255 cmdprio = Atac.cprio;
256 prio = Atac.prio;
257 delay = 2000000;
258 if ( !Atac.cprio )
259 cmdprio = 32;
260 index = 1;
261 if ( !Atac.prio )
262 {
263 delay = 1000000;
264 prio = 78;
265 }
266 v11 = argv + 1;
267 while ( index < argc )
268 {
269 opt = *v11;
270 if ( **v11 == 45 )
271 {
272 v13 = opt[1];
273 if ( v13 == 100 )
274 {
275 delay = ata_module_optarg(opt + 2, delay);
276 }
277 else if ( v13 >= 101 )
278 {
279 opt_v11 = opt + 2;
280 if ( v13 == 112 )
281 {
282 prio = ata_module_optarg(opt_v11, prio);
283 }
284 }
285 else
286 {
287 opt_v10 = opt + 2;
288 if ( v13 == 99 )
289 {
290 cmdprio = ata_module_optarg(opt_v10, cmdprio);
291 }
292 }
293 }
294 ++v11;
295 ++index;
296 }
297 if ( prio < cmdprio )
298 cmdprio = prio;
299 Atac.thid = 0;
300 Atac.active = 0;
301 Atac.cprio = cmdprio;
302 Atac.prio = prio;
303 Atac.requestq.q_prev = 0;
304 Atac.requestq.q_next = 0;
305 DelayThread(delay);
306 ChangeThreadPriority(0, 123);
307 index_v12 = ata_probe((acAtaReg)0xB6000000);
308 Atac.active = index_v12;
309 if ( index_v12 == 0 )
310 {
311 msg = "probe device";
312 Atac.active = 0;
313 }
314 else
315 {
316 index_v12 = acIntrRegister(AC_INTR_NUM_ATA, (acIntrHandler)ata_intr, &Atac);
317 if ( index_v12 < 0 && index_v12 != -11 )
318 {
319 msg = "register intr";
320 Atac.active = 0;
321 }
322 else
323 {
324 int v18;
325
326 v18 = ata_thread_init(&Atac, prio);
327 index_v12 = v18;
328 if ( v18 <= 0 )
329 {
330 acIntrRelease(AC_INTR_NUM_ATA);
331 msg = "init thread";
332 Atac.active = 0;
333 }
334 else
335 {
336 Atac.thid = v18;
337 if ( acIntrEnable(AC_INTR_NUM_ATA) < 0 )
338 {
339 int thid;
340
341 thid = Atac.thid;
342 if ( thid > 0 )
343 {
344 int i;
345
346 Atac.thid = 0;
347 WakeupThread(thid);
348 for ( i = 1000;; i = 1000000 )
349 {
350 int ret;
351
352 DelayThread(i);
353 ret = DeleteThread(thid);
354 if ( !ret )
355 break;
356 printf("acata:term_thread: DELETE ret=%d\n", ret);
357 }
358 }
359 acIntrRelease(AC_INTR_NUM_ATA);
360 msg = "enable intr";
361 Atac.active = 0;
362 }
363 else
364 {
365 return 0;
366 }
367 }
368 }
369 }
370 printf("acata: %s: error %d\n", msg, index_v12);
371 return -6;
372}
373
374int acAtaModuleStop()
375{
376 int thid;
377
378 if ( acAtaModuleStatus() == 0 )
379 {
380 return 0;
381 }
382 thid = Atac.thid;
383 if ( Atac.thid > 0 )
384 {
385 int i;
386
387 Atac.thid = 0;
388 WakeupThread(thid);
389 for ( i = 1000;; i = 1000000 )
390 {
391 int ret;
392
393 DelayThread(i);
394 ret = DeleteThread(thid);
395 if ( !ret )
396 break;
397 printf("acata:term_thread: DELETE ret=%d\n", ret);
398 }
399 }
400 acIntrDisable(AC_INTR_NUM_ATA);
401 acIntrRelease(AC_INTR_NUM_ATA);
402 Atac.active = 0;
403 return 0;
404}
405
406int acAtaModuleRestart(int argc, char **argv)
407{
408 (void)argc;
409 (void)argv;
410 return -88;
411}
412
413int acAtaModuleStatus()
414{
415 int ret;
416 int state;
417
418 CpuSuspendIntr(&state);
419 ret = 0;
420 if ( Atac.thid )
421 {
422 ret = 2;
423 if ( !Atac.requestq.q_next )
424 ret = 1;
425 }
426 CpuResumeIntr(state);
427 return ret;
428}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u32 count
start sector of fragmented bd/file