PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
uart.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 "acuart_internal.h"
12
13static struct uart_softc Uartc;
14
15static int uart_eve_alloc()
16{
17 int ret;
18 iop_event_t param;
19
20 param.attr = 2;
21 param.bits = 0;
22 param.option = 0;
23 ret = CreateEventFlag(&param);
24 if ( ret <= 0 )
25 {
26 printf("acuart:eve_alloc: error %d\n", ret);
27 }
28 return ret;
29}
30
31static int uart_xmit(struct uart_buf *xmit, acUartReg uartreg)
32{
33 int head;
34 int tail;
35 acUint8 *buf;
36 int count;
37
38 head = xmit->ub_head;
39 tail = xmit->ub_tail;
40 if ( head == tail )
41 return 0;
42 buf = xmit->ub_buf;
43 count = 16;
44 if ( head < tail )
45 {
46 signed int size;
47 const acUint8 *src;
48 int size_v6;
49
50 size = xmit->ub_size - tail;
51 src = &buf[tail];
52 if ( size > 16 )
53 {
54 size = 16;
55 tail += 16;
56 }
57 else
58 {
59 tail = 0;
60 }
61 count = 16 - size;
62 for ( size_v6 = size - 1; size_v6 >= 0; --size_v6 )
63 {
64 *uartreg = *src++;
65 }
66 }
67 if ( count )
68 {
69 int size_v8;
70
71 size_v8 = head - tail;
72 if ( tail < head )
73 {
74 const acUint8 *src_v9;
75 int size_v10;
76
77 src_v9 = &buf[tail];
78 if ( count < size_v8 )
79 {
80 size_v8 = count;
81 tail += count;
82 }
83 else
84 {
85 tail = head;
86 }
87 count -= size_v8;
88 for ( size_v10 = size_v8 - 1; size_v10 >= 0; --size_v10 )
89 {
90 *uartreg = *src_v9++;
91 }
92 }
93 }
94 xmit->ub_tail = tail;
95 return 2 * (count < 16);
96}
97
98int acUartWrite(void *buf, int count)
99{
100 const acUint8 *src;
101 int eve;
102 int v6;
103 int head;
104 int tail;
105 acUint8 *ub_buf;
106 int bufsize;
107 int size;
108 acSpl state;
109
110 if ( !buf || count < 0 )
111 return -22;
112 if ( !count )
113 return 0;
114 src = (acUint8 *)buf;
115 if ( !Uartc.eve )
116 return -6;
117 eve = Uartc.eve;
118 CpuSuspendIntr(&state);
119 v6 = count;
120 head = Uartc.xmit.ub_head;
121 tail = Uartc.xmit.ub_tail;
122 CpuResumeIntr(state);
123 ub_buf = Uartc.xmit.ub_buf;
124 bufsize = Uartc.xmit.ub_size;
125 if ( head >= tail )
126 {
127 int xlen;
128 acUint8 *dst;
129 int xlen_v9;
130
131 xlen = Uartc.xmit.ub_size - head;
132 dst = &Uartc.xmit.ub_buf[head];
133 if ( count < (signed int)(Uartc.xmit.ub_size - head) )
134 {
135 xlen = count;
136 head += count;
137 }
138 else
139 {
140 head = 0;
141 }
142 v6 = count - xlen;
143 for ( xlen_v9 = xlen - 1; xlen_v9 >= 0; ++dst )
144 {
145 --xlen_v9;
146 *dst = *src++;
147 }
148 }
149 if ( v6 && head < tail )
150 {
151 int xlen_v11;
152 acUint8 *dst_v12;
153 int xlen_v13;
154
155 xlen_v11 = tail - head;
156 dst_v12 = &ub_buf[head];
157 if ( v6 < tail - head )
158 {
159 xlen_v11 = v6;
160 head += v6;
161 }
162 else
163 {
164 head = tail;
165 }
166 v6 -= xlen_v11;
167 for ( xlen_v13 = xlen_v11 - 1; xlen_v13 >= 0; ++dst_v12 )
168 {
169 --xlen_v13;
170 *dst_v12 = *src++;
171 }
172 }
173 if ( head == tail )
174 {
175 if ( --head < 0 )
176 head = bufsize - 1;
177 ++v6;
178 }
179 else
180 {
181 SetEventFlag(eve, 2u);
182 }
183 Uartc.xmit.ub_head = head;
184 size = count - v6;
185 if ( size )
186 {
187 if ( (*((volatile acUint16 *)0xB241800A) /* originally 8 bit access */ & 0x20) != 0 )
188 {
189 uart_xmit(&Uartc.xmit, (acUartReg)0xB2418000);
190 *((volatile acUint16 *)0xB2418002) = *((volatile acUint16 *)0xB2418002) | 2;
191 }
192 }
193 return size;
194}
195
196int acUartRead(void *buf, int count)
197{
198 acUint8 *dst;
199 int eve;
200 int head;
201 int tail;
202 acUint8 *ub_buf;
203 int v9;
204 acSpl state;
205
206 if ( !buf || count < 0 )
207 return -22;
208 if ( count == 0 )
209 {
210 return 0;
211 }
212 dst = (acUint8 *)buf;
213 if ( Uartc.eve == 0 )
214 {
215 return -6;
216 }
217 eve = Uartc.eve;
218 CpuSuspendIntr(&state);
219 head = Uartc.recv.ub_head;
220 tail = Uartc.recv.ub_tail;
221 CpuResumeIntr(state);
222 if ( head == tail )
223 {
224 return 0;
225 }
226 ub_buf = Uartc.recv.ub_buf;
227 v9 = count;
228 if ( head < tail )
229 {
230 int bufsize;
231 const acUint8 *src;
232 int bufsize_v9;
233
234 bufsize = Uartc.recv.ub_size - tail;
235 src = &Uartc.recv.ub_buf[tail];
236 if ( count < (signed int)(Uartc.recv.ub_size - tail) )
237 {
238 bufsize = count;
239 tail += count;
240 }
241 else
242 {
243 tail = 0;
244 }
245 v9 = count - bufsize;
246 for ( bufsize_v9 = bufsize - 1; bufsize_v9 >= 0; ++dst )
247 {
248 --bufsize_v9;
249 *dst = *src++;
250 }
251 }
252 if ( v9 && tail < head )
253 {
254 int bufsize_v11;
255 const acUint8 *src_v12;
256 int bufsize_v13;
257
258 bufsize_v11 = head - tail;
259 src_v12 = &ub_buf[tail];
260 if ( v9 < head - tail )
261 {
262 bufsize_v11 = v9;
263 tail += v9;
264 }
265 else
266 {
267 tail = head;
268 }
269 v9 -= bufsize_v11;
270 for ( bufsize_v13 = bufsize_v11 - 1; bufsize_v13 >= 0; ++dst )
271 {
272 --bufsize_v13;
273 *dst = *src_v12++;
274 }
275 }
276 Uartc.recv.ub_tail = tail;
277 if ( head != tail )
278 SetEventFlag(eve, 1u);
279 return count - v9;
280}
281
282static unsigned int uart_timedout(void *arg)
283{
284 iReleaseWaitThread((int)arg);
285 return 0;
286}
287
288int acUartWait(acUartFlag rw, int usec)
289{
290 int thid;
291 int v7;
292 int ret;
293 iop_sys_clock_t tmout;
294 u32 result_v7;
295
296 if ( rw == 0 )
297 {
298 return -22;
299 }
300 if ( Uartc.eve == 0 )
301 {
302 return -6;
303 }
304 thid = GetThreadId();
305 if ( usec > 0 )
306 {
307 USec2SysClock(usec, &tmout);
308 SetAlarm(&tmout, uart_timedout, (void *)thid);
309 }
310 result_v7 = 0;
311 v7 = (usec > 0 ? WaitEventFlag : PollEventFlag)(Uartc.eve, rw, 17, &result_v7);
312 if ( v7 == -418 )
313 {
314 ret = -116;
315 }
316 else if ( v7 >= -417 )
317 {
318 ret = -5;
319 if ( !v7 )
320 ret = 0;
321 }
322 else
323 {
324 ret = -5;
325 if ( v7 == -425 )
326 ret = -6;
327 }
328 CancelAlarm(uart_timedout, (void *)thid);
329 if ( !ret )
330 {
331 int ret_v5;
332
333 ret_v5 = result_v7 & rw;
334 result_v7 &= ~rw;
335 if ( result_v7 )
336 SetEventFlag(Uartc.eve, result_v7);
337 return ret_v5;
338 }
339 return ret;
340}
341
342static int uart_intr(struct uart_softc *arg)
343{
344 struct uart_buf *p_recv;
345 int v3;
346 signed int event;
347 acUint32 ub_tail;
348 acUint8 *buf;
349 signed int bufsize;
350 int sr;
351 int event_v9;
352
353 p_recv = &arg->recv;
354 v3 = 0;
355 *((volatile acUint16 *)0xB3100000) = 0;
356 event = arg->recv.ub_head;
357 ub_tail = arg->recv.ub_tail;
358 buf = arg->recv.ub_buf;
359 bufsize = arg->recv.ub_size;
360 sr = *((volatile acUint16 *)0xB241800A) /* originally 8 bit access */ & 0xFF;
361 while ( (sr & 0x1F) != 0 )
362 {
363 if ( (sr & 0x10) != 0 )
364 {
365 Kprintf("acuart:intr: BREAK\n");
366 }
367 else
368 {
369 if ( sr & 1 )
370 {
371 buf[event] = *((volatile acUint16 *)0xB2418000);
372 ++event;
373 if ( event >= bufsize )
374 event = 0;
375 if ( (acUint32)event == ub_tail && (int)++ub_tail >= bufsize )
376 ub_tail = 0;
377 }
378 }
379 v3 = 1;
380 sr = *((volatile acUint16 *)0xB241800A) /* originally 8 bit access */ & 0xFF;
381 }
382 p_recv->ub_head = event;
383 p_recv->ub_tail = ub_tail;
384 event_v9 = v3;
385 if ( (*((volatile acUint16 *)0xB241800A) /* originally 8 bit access */ & 0x20) != 0 )
386 {
387 if ( !uart_xmit(&arg->xmit, (acUartReg)0xB2418000) )
388 *((volatile acUint16 *)0xB2418002) = *((volatile acUint16 *)0xB2418002) & 0xFD;
389 event_v9 |= 2u;
390 }
391 if ( event_v9 )
392 iSetEventFlag(arg->eve, event_v9);
393 return 1;
394}
395
396static void uart_attr_set(struct uart_softc *uartc, acUartReg uartreg)
397{
398 int v3;
399 int trigger;
400 int v6;
401 int v7;
402 int state;
403
404 v3 = 36864000 / (signed int)(16 * uartc->speed);
405 trigger = uartc->fifo;
406 if ( trigger < 14 )
407 {
408 if ( trigger < 8 )
409 v6 = ((trigger >= 4) << 6 & 0xFFFF);
410 else
411 v6 = 128;
412 }
413 else
414 {
415 v6 = 192;
416 }
417 v7 = 16 * (uartc->loopback != 0);
418 uartreg[1] = 0;
419 uartreg[2] = 6;
420 uartreg[3] = 131;
421 *uartreg = (v3 + 1) >> 1;
422 uartreg[1] = (v3 + 1) >> 9;
423 uartreg[3] = 3;
424 uartreg[4] = v7 | 0xF;
425 uartreg[2] = v6 | 1;
426 CpuSuspendIntr(&state);
427 uartc->xmit.ub_tail = 0;
428 uartc->xmit.ub_head = uartc->xmit.ub_tail;
429 uartc->recv.ub_tail = 0;
430 uartc->recv.ub_head = uartc->recv.ub_tail;
431 CpuResumeIntr(state);
432 uartreg[1] = 1;
433}
434
435int acUartSetAttr(const acUartAttrData *attr)
436{
437 int fifo;
438 int fifo_v2;
439
440 if ( attr == 0 )
441 {
442 return -22;
443 }
444 if ( Uartc.eve == 0 )
445 {
446 return -6;
447 }
448 fifo = attr->ua_fifo;
449 Uartc.speed = attr->ua_speed;
450 Uartc.loopback = attr->ua_loopback != 0;
451 if ( fifo < 14 )
452 {
453 if ( fifo < 8 )
454 {
455 fifo_v2 = 4;
456 if ( fifo < 4 )
457 fifo_v2 = 1;
458 }
459 else
460 {
461 fifo_v2 = 8;
462 }
463 }
464 else
465 {
466 fifo_v2 = 14;
467 }
468 Uartc.fifo = fifo_v2;
469 uart_attr_set(&Uartc, (acUartReg)0xB2418000);
470 return 0;
471}
472
473int acUartGetAttr(acUartAttrData *attr)
474{
475 if ( attr == 0 )
476 {
477 return -22;
478 }
479 if ( Uartc.eve == 0 )
480 {
481 return -6;
482 }
483 attr->ua_speed = Uartc.speed;
484 attr->ua_fifo = Uartc.fifo;
485 attr->ua_loopback = Uartc.loopback;
486 return 0;
487}
488
489int acUartModuleStatus()
490{
491 int v0;
492 int state;
493
494 CpuSuspendIntr(&state);
495 v0 = Uartc.eve != 0;
496 CpuResumeIntr(state);
497 return v0;
498}
499
500static int uart_optarg(const char *str, int default_value)
501{
502 int result;
503 char *next;
504
505 result = strtol(str, &next, 0);
506 if ( next == str )
507 return default_value;
508 return result;
509}
510
511int acUartModuleStart(int argc, char **argv)
512{
513 int index;
514 char **v7;
515 int v9;
516 int uartc;
517 int eve;
518 acUint8 *buf;
519 char *msg;
520 int size;
521
522 if ( acUartModuleStatus() != 0 )
523 {
524 return -16;
525 }
526 Uartc.loopback = 0;
527 if ( !Uartc.speed )
528 Uartc.speed = 9600;
529 if ( !Uartc.fifo )
530 Uartc.fifo = 1;
531 if ( !Uartc.xmit.ub_size )
532 Uartc.xmit.ub_size = 256;
533 index = 1;
534 if ( !Uartc.recv.ub_size )
535 Uartc.recv.ub_size = 512;
536 v7 = argv + 1;
537 while ( index < argc )
538 {
539 const char *opt;
540
541 opt = *v7;
542 if ( **v7 == 45 )
543 {
544 switch ( opt[1] )
545 {
546 case 'b':
547 Uartc.speed = uart_optarg(opt + 2, Uartc.speed);
548 break;
549 case 'f':
550 Uartc.fifo = uart_optarg(opt + 2, Uartc.fifo);
551 break;
552 case 'l':
553 Uartc.loopback = 1;
554 break;
555 case 'r':
556 Uartc.recv.ub_size = uart_optarg(opt + 2, Uartc.recv.ub_size);
557 break;
558 case 'x':
559 Uartc.xmit.ub_size = uart_optarg(opt + 2, Uartc.xmit.ub_size);
560 break;
561 default:
562 break;
563 }
564 }
565 ++index;
566 ++v7;
567 }
568 Uartc.xmit.ub_buf = 0;
569 uartc = Uartc.recv.ub_size + Uartc.xmit.ub_size;
570 v9 = uart_eve_alloc();
571 eve = v9;
572 if ( v9 <= 0 )
573 {
574 buf = 0;
575 msg = "eve_alloc";
576 size = v9;
577 }
578 else
579 {
580 buf = (acUint8 *)AllocSysMemory(0, uartc, 0);
581 if ( buf == 0 )
582 {
583 msg = "mem_alloc";
584 size = -12;
585 }
586 else
587 {
588 size = acIntrRegister(AC_INTR_NUM_UART, (acIntrHandler)uart_intr, &Uartc);
589 if ( size < 0 )
590 {
591 msg = "intr_register";
592 }
593 else
594 {
595 size = acIntrEnable(AC_INTR_NUM_UART);
596 if ( size < 0 )
597 {
598 acIntrRelease(AC_INTR_NUM_UART);
599 msg = "intr_enable";
600 }
601 else
602 {
603 Uartc.xmit.ub_buf = buf;
604 Uartc.recv.ub_buf = &buf[Uartc.xmit.ub_size];
605 uart_attr_set(&Uartc, (acUartReg)0xB2418000);
606 Uartc.eve = eve;
607 return 0;
608 }
609 }
610 }
611 }
612 printf("acuart:init:%s: error %d\n", msg, size);
613 if ( buf )
614 FreeSysMemory(buf);
615 if ( eve > 0 )
616 {
617 DeleteEventFlag(eve);
618 }
619 return -6;
620}
621
622int acUartModuleStop()
623{
624 if ( !acUartModuleStatus() )
625 return 0;
626 *((volatile acUint16 *)0xB2418002) = 0;
627 *((volatile acUint16 *)0xB2418004) = 7;
628 acIntrDisable(AC_INTR_NUM_UART);
629 acIntrRelease(AC_INTR_NUM_UART);
630 if ( Uartc.xmit.ub_buf )
631 FreeSysMemory(Uartc.xmit.ub_buf);
632 if ( Uartc.eve > 0 )
633 {
634 DeleteEventFlag(Uartc.eve);
635 }
636 return 0;
637}
638
639int acUartModuleRestart(int argc, char **argv)
640{
641 (void)argc;
642 (void)argv;
643 return -88;
644}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
u32 count
start sector of fragmented bd/file