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 *((volatile acUint16 *)0xB6030000) = 18;
194 active = 0;
195 unit = 0;
196 *((volatile acUint16 *)0xB6160000) = 2;
197 *((volatile acUint16 *)0xB6010000) = 0;
198 count = 0;
199 while ( unit < 2 )
200 {
201 *((volatile acUint16 *)0xB6060000) = 16 * (unit != 0);
202 *((volatile acUint16 *)0xB6070000) = 0;
203 while ( count <= 1999999 )
204 {
205 // cppcheck-suppress knownConditionTrueFalse
206 if ( (*((volatile acUint16 *)0xB6070000) & 0x80) == 0 )
207 break;
208 ++count;
209 }
210 if ( count )
211 active |= 1 << unit;
212 ++unit;
213 count = 0;
214 }
215 return active;
216}
217
218static int ata_module_optarg(const char *str, int default_value)
219{
220 int result;
221 char *next;
222
223 result = strtol(str, &next, 0);
224 if ( next == str )
225 return default_value;
226 return result;
227}
228
229int acAtaModuleStart(int argc, char **argv)
230{
231 int cmdprio;
232 int prio;
233 int delay;
234 int index;
235 char **v11;
236 char *opt;
237 int v13;
238 const char *opt_v10;
239 const char *opt_v11;
240 int index_v12;
241 char *msg;
242
243 if ( acAtaModuleStatus() != 0 )
244 {
245 return -16;
246 }
247 cmdprio = Atac.cprio;
248 prio = Atac.prio;
249 delay = 2000000;
250 if ( !Atac.cprio )
251 cmdprio = 32;
252 index = 1;
253 if ( !Atac.prio )
254 {
255 delay = 1000000;
256 prio = 78;
257 }
258 v11 = argv + 1;
259 while ( index < argc )
260 {
261 opt = *v11;
262 if ( **v11 == 45 )
263 {
264 v13 = opt[1];
265 if ( v13 == 100 )
266 {
267 delay = ata_module_optarg(opt + 2, delay);
268 }
269 else if ( v13 >= 101 )
270 {
271 opt_v11 = opt + 2;
272 if ( v13 == 112 )
273 {
274 prio = ata_module_optarg(opt_v11, prio);
275 }
276 }
277 else
278 {
279 opt_v10 = opt + 2;
280 if ( v13 == 99 )
281 {
282 cmdprio = ata_module_optarg(opt_v10, cmdprio);
283 }
284 }
285 }
286 ++v11;
287 ++index;
288 }
289 if ( prio < cmdprio )
290 cmdprio = prio;
291 Atac.thid = 0;
292 Atac.active = 0;
293 Atac.cprio = cmdprio;
294 Atac.prio = prio;
295 Atac.requestq.q_prev = 0;
296 Atac.requestq.q_next = 0;
297 DelayThread(delay);
298 ChangeThreadPriority(0, 123);
299 index_v12 = ata_probe((acAtaReg)0xB6000000);
300 Atac.active = index_v12;
301 if ( index_v12 == 0 )
302 {
303 msg = "probe device";
304 Atac.active = 0;
305 }
306 else
307 {
308 index_v12 = acIntrRegister(AC_INTR_NUM_ATA, (acIntrHandler)ata_intr, &Atac);
309 if ( index_v12 < 0 && index_v12 != -11 )
310 {
311 msg = "register intr";
312 Atac.active = 0;
313 }
314 else
315 {
316 int v18;
317
318 v18 = ata_thread_init(&Atac, prio);
319 index_v12 = v18;
320 if ( v18 <= 0 )
321 {
322 acIntrRelease(AC_INTR_NUM_ATA);
323 msg = "init thread";
324 Atac.active = 0;
325 }
326 else
327 {
328 Atac.thid = v18;
329 if ( acIntrEnable(AC_INTR_NUM_ATA) < 0 )
330 {
331 int thid;
332
333 thid = Atac.thid;
334 if ( thid > 0 )
335 {
336 int i;
337
338 Atac.thid = 0;
339 WakeupThread(thid);
340 for ( i = 1000;; i = 1000000 )
341 {
342 int ret;
343
344 DelayThread(i);
345 ret = DeleteThread(thid);
346 if ( !ret )
347 break;
348 printf("acata:term_thread: DELETE ret=%d\n", ret);
349 }
350 }
351 acIntrRelease(AC_INTR_NUM_ATA);
352 msg = "enable intr";
353 Atac.active = 0;
354 }
355 else
356 {
357 return 0;
358 }
359 }
360 }
361 }
362 printf("acata: %s: error %d\n", msg, index_v12);
363 return -6;
364}
365
366int acAtaModuleStop()
367{
368 int thid;
369
370 if ( acAtaModuleStatus() == 0 )
371 {
372 return 0;
373 }
374 thid = Atac.thid;
375 if ( Atac.thid > 0 )
376 {
377 int i;
378
379 Atac.thid = 0;
380 WakeupThread(thid);
381 for ( i = 1000;; i = 1000000 )
382 {
383 int ret;
384
385 DelayThread(i);
386 ret = DeleteThread(thid);
387 if ( !ret )
388 break;
389 printf("acata:term_thread: DELETE ret=%d\n", ret);
390 }
391 }
392 acIntrDisable(AC_INTR_NUM_ATA);
393 acIntrRelease(AC_INTR_NUM_ATA);
394 Atac.active = 0;
395 return 0;
396}
397
398int acAtaModuleRestart(int argc, char **argv)
399{
400 (void)argc;
401 (void)argv;
402 return -88;
403}
404
405int acAtaModuleStatus()
406{
407 int ret;
408 int state;
409
410 CpuSuspendIntr(&state);
411 ret = 0;
412 if ( Atac.thid )
413 {
414 ret = 2;
415 if ( !Atac.requestq.q_next )
416 ret = 1;
417 }
418 CpuResumeIntr(state);
419 return ret;
420}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u32 count
start sector of fragmented bd/file