PS2SDK
PS2 Homebrew Libraries
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 
13 static struct uart_softc Uartc;
14 
15 static 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 
31 static 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 
98 int 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 
196 int 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 
282 static unsigned int uart_timedout(void *arg)
283 {
284  iReleaseWaitThread((int)arg);
285  return 0;
286 }
287 
288 int 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 
342 static 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 
396 static 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 
435 int 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 
473 int 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 
489 int 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 
500 static 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 
511 int 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 
622 int 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 
639 int acUartModuleRestart(int argc, char **argv)
640 {
641  (void)argc;
642  (void)argv;
643  return -88;
644 }
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
event
Definition: thcommon.h:71
uart_softc
Definition: acuart_internal.h:27
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
ac_uart_attr
Definition: acuart.h:23
uart_buf
Definition: acuart_internal.h:19
iop_event_t
Definition: thevent.h:37
_iop_sys_clock
Definition: thbase.h:87