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