PS2SDK
PS2 Homebrew Libraries
spduart.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 <ctype.h>
12 #include <irx_imports.h>
13 #include <speedregs.h>
14 
15 #define MODNAME "INET_SPEED_UART_driver"
16 
17 // Based off of the module from SDK 3.1.0
18 IRX_ID(MODNAME, 0x2, 0x1A);
19 
20 extern struct irx_export_table _exp_spduart;
21 
22 // 16550 compatible UART interface.
23 // Reference: https://www.freebsd.org/doc/en_US.ISO8859-1/articles/serial-uart/index.html
24 typedef struct uart16550_regs_
25 {
27  u8 pad01;
29  u8 pad03;
30  u8 r_lcr;
31  u8 pad05;
32  u8 r_mcr;
33  u8 pad07;
34  u8 r_lsr;
35  u8 pad09;
36  u8 r_msr;
37  u8 pad0B;
38  u8 r_scr;
39  u8 pad0D;
40  u8 pad0E;
41  u8 pad0F;
42  u8 r_cr1;
43  u8 pad11;
44  u8 r_cr2;
45  u8 pad13;
47 
48 typedef struct spduart_buffer_struct_
49 {
50  int m_offset1;
51  int m_offset2;
52  int m_cur_xfer_len;
53  void *m_ptr;
55 
56 typedef struct spduart_internals_
57 {
58  int spduart_thread;
59  int spduart_ef;
60  uart16550_regs_t *dev9_uart_reg_area;
61  int spduart_thpri_;
62  int spduart_thstack_;
63  int spduart_overrun_error_count;
64  int spduart_parity_error_count;
65  int spduart_framing_error_count;
66  int spduart_break_interrupt_count;
67  int spduart_buffer_overflow_count;
68  int spduart_rx_count;
69  int spduart_tx_count;
70  char spduart_fcr_cached;
71  char spduart_msr_cached;
72  char spduart_signal_pin;
73  char spduart_mcr_cached;
74  int spduart_baud_;
75  int spduart_trig_;
76  iop_sys_clock_t spduart_clock_1e4;
77  iop_sys_clock_t spduart_clock_1e6;
78  int spduart_alarm_1e4_flag;
79  int spduart_alarm_1e6_flag;
80  int spduart_start_flag;
81  int spduart_stop_flag;
82  int shutdown_flag;
83  int spduart_data_set_ready_flag;
84  int spduart_nogci_;
85  char spduart_gci_[2];
86  // cppcheck-suppress unusedStructMember
87  char unused6a;
88  // cppcheck-suppress unusedStructMember
89  char unused6b;
90  spduart_buffer_struct_t recv_buf_struct;
91  spduart_buffer_struct_t send_buf_struct;
92  sceModemOps_t spduart_modem_ops;
93  char spduart_dial_[1024];
94  char buf1data[1024];
95  char buf2data[1024];
97 
98 // The modem used in SCPH-10281 network adapter is Conexant SMARTSCM/56 CX88168-11
99 // Datasheet: https://archive.org/download/ps2_modem_ref/DSA-140092.pdf
100 // AT command reference: https://archive.org/download/ps2_modem_ref/IML56_modem_AT_commands.pdf
101 
102 // The following is formatted in Motorola s37 format (aka S-Record, SRECORD, S-Rec, SREC)
103 static const char *modem_firmware_s37[54] = {
104  "S3100000A000B20269A9008DBC044C0EE101\r",
105  "S31500009DA560606060606060606B606B606060606092\r",
106  "S31500009DB56B60606B60606060606060606060606082\r",
107  "S31500009DC56060606060606B606B60606B6060606067\r",
108  "S31500009DD5606060606060606B6B6060606B60606B4C\r",
109  "S31500009DE560606B606060606060606060606B606052\r",
110  "S31500009EB000000600000000004E0003000000000045\r",
111  "S31500009EC09300002A000000000000000000000000CF\r",
112  "S31500009ED00000000000006E006100006E000000003F\r",
113  "S31500009EE0000000000000004B7100000074000098A4\r",
114  "S31500009EF000009B000000000000000000005E000063\r",
115  "S30600009F00005A\r",
116  "S31500009F019A284C5F86A9608DA79DADA102D019A99B\r",
117  "S31500009F11048DEC02A973CD0D01B0038D0D01A9418C\r",
118  "S31500009F21CD110190038D110160C2016001FF4C1931\r",
119  "S31500009F31AD6487D014D2105D01A9328D1D87A900A9\r",
120  "S31500009F418D1E8748C2105D0168604CC686A9603FB8\r",
121  "S31500009F516B02A96B8DE49DA96B8DA79D604C008159\r",
122  "S31500009F61A21820445A0DEB02A2184CF5584C6986EA\r",
123  "S31500009F714C449EAE59048A2902F0168A29FD8D5950\r",
124  "S31500009F8104A9528D1C06A9807B09208D1806A9A05B\r",
125  "S31200009F917B60D2083906604CEF864C548682\r",
126  "S31500009DF9AD4B878540AD4C878541A541C900D00447\r",
127  "S31500009E09A540C996B033AD43878540AD44878541A2\r",
128  "S31500009E1938A540E98C8540A541E9008541A540ED75\r",
129  "S31500009E2952878540A541ED53878541B26444207820\r",
130  "S30F00009E3969A5408D439E4C708660BB\r",
131  "S31500009E447F4C04D21060016087FFAD9602C971F0A1\r",
132  "S31500009E542C206067A540E9588540A541E902854163\r",
133  "S31500009E64900BAD588789018D58874C4575AD960280\r",
134  "S31500009E74C971F009ADA89E8DA79E4CAE77ADA89E7C\r",
135  "S31500009E8438EDA79E9004C902B00160A900854085FB\r",
136  "S31500009E9441A5408D5887A5418D598707FF20DD7759\r",
137  "S30800009EA44C1361F5\r",
138  "S31500008654A950CD0286B0038D028660E2750102043C\r",
139  "S3150000866497FF27FF60A203A9004C9BE4AD478785CB\r",
140  "S3150000867440AD48878541B26444207869AD439E8500\r",
141  "S3150000868442208B69A541C907D004A540C9089012A8\r",
142  "S31500008694A9758D3F87A9778D4087B200AEB248B1E0\r",
143  "S315000086A4B759601FFF1BAFFF09A7FFC2027501B2CE\r",
144  "S315000086B414FEE25D01100AC6FED00617FFD202754B\r",
145  "S315000086C40160AD5702C93CD021BF6B1EB20747B249\r",
146  "S315000086D45046B20A45B2B9442096E3B20747B250AF\r",
147  "S315000086E446B20B45B2B9442096E360E21106100681\r",
148  "S30C000086F47F5C032095026084\r",
149  "S3150000810020A786E25D0110374F63342073E7AD96F2\r",
150  "S3150000811002C971D00FF24E01100AAD0404C960B055\r",
151  "S31500008120034CF960AD3F87C9B1F00FAD4D87C9006B\r",
152  "S31500008130F00DE2600110094C7E9EA9008D4D87600E\r",
153  "S3150000814020F99DADEC02C903D0F5AD3F87C9DBD060\r",
154  "S31500008150EEE25E0101E920C466A5406D45878540D3\r",
155  "S31500008160A5416D46878541B26444207869A5408D56\r",
156  "S31500008170A89E38E92890C8A54038E93290060FFF36\r",
157  "S30C00008180BE4C719E4C4C9EA3\r"};
158 
159 static spduart_internals_t spduart_internals;
160 
161 #define sceInetPrintf(...) printf(__VA_ARGS__)
162 
163 static int module_start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi);
164 static int module_stop(int ac, char *av[], void *startaddr, ModuleInfo_t *mi);
165 
166 int _start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
167 {
168  if ( argc >= 0 )
169  return module_start(argc, argv, startaddr, mi);
170  else
171  return module_stop(argc, argv, startaddr, mi);
172 }
173 
174 static void spduart_dump_msr(u8 msr)
175 {
176  sceInetPrintf(
177  "spduart: MSR=%02x (DCTS=%d DDSR=%d TERI=%d DDCD=%d\n",
178  msr,
179  msr & 1,
180  (msr >> 1) & 1,
181  (msr >> 2) & 1,
182  (msr >> 3) & 1);
183  sceInetPrintf(
184  "spduart: CTS=%d DSR=%d RI=%d DCD=%d)\n", (msr >> 4) & 1, (msr >> 5) & 1, (msr >> 6) & 1, msr >> 7);
185 }
186 
187 static unsigned int alarm_cb_1e4(void *userdata)
188 {
189  struct spduart_internals_ *priv;
190 
191  priv = (struct spduart_internals_ *)userdata;
192  priv->spduart_modem_ops.rcv_len = priv->recv_buf_struct.m_cur_xfer_len;
193  iSetEventFlag(priv->spduart_modem_ops.evfid, sceModemEFP_Recv);
194  return 0;
195 }
196 
197 static unsigned int alarm_cb_1e6(void *userdata)
198 {
199  struct spduart_internals_ *priv;
200 
201  priv = (struct spduart_internals_ *)userdata;
202  iSetEventFlag(priv->spduart_ef, 4u);
203  return priv->spduart_clock_1e6.lo;
204 }
205 
206 static int spduart_send(struct spduart_internals_ *priv)
207 {
208  int m_cur_xfer_len;
209  int v4;
210  u8 v7;
211  int state;
212 
213  CpuSuspendIntr(&state);
214  priv->spduart_fcr_cached &= ~2;
215  m_cur_xfer_len = priv->send_buf_struct.m_cur_xfer_len;
216  v4 = 0;
217  if ( m_cur_xfer_len > 0 )
218  {
219  if ( m_cur_xfer_len > 16 )
220  m_cur_xfer_len = 16;
221  if ( ((priv->spduart_msr_cached >> 4) & sceModemLINE_CTS) != 0 )
222  {
223  if ( (spduart_internals.dev9_uart_reg_area->r_msr & 0x20) != 0 )
224  {
225  int v6;
226 
227  v6 = m_cur_xfer_len - 1;
228  do
229  {
230  v7 = *((u8 *)priv->send_buf_struct.m_ptr + (priv->send_buf_struct.m_offset2 & 0x3FF));
231  ++priv->send_buf_struct.m_offset2;
232  priv->send_buf_struct.m_cur_xfer_len -= 1;
233  --v6;
234  spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr = v7;
235  ++v4;
236  } while ( v6 > 0 );
237  if ( priv->send_buf_struct.m_cur_xfer_len > 0 )
238  {
239  priv->spduart_fcr_cached |= 2;
240  }
241  }
242  else
243  {
244  priv->spduart_fcr_cached |= 2;
245  }
246  priv->spduart_tx_count += v4;
247  }
248  }
249  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = priv->spduart_fcr_cached;
250  CpuResumeIntr(state);
251  return v4;
252 }
253 
254 static int spduart_dev9_intr_cb(int flag)
255 {
256  int v1;
257  u32 v2;
258  u8 r_msr;
259  int m_offset1;
260  char r_scr;
261 
262  (void)flag;
263 
264  v1 = 0;
265  v2 = 0;
266  while ( 1 )
267  {
268  switch ( spduart_internals.dev9_uart_reg_area->r_lcr & 0xF )
269  {
270  case 0:
271  r_scr = spduart_internals.dev9_uart_reg_area->r_scr;
272  if ( spduart_internals.spduart_start_flag )
273  {
274  spduart_internals.spduart_msr_cached = spduart_internals.dev9_uart_reg_area->r_scr;
275  continue;
276  }
277  if ( (spduart_internals.dev9_uart_reg_area->r_scr & 1) != 0 )
278  {
279  if ( ((spduart_internals.dev9_uart_reg_area->r_scr >> 4) & sceModemLINE_CTS) != 0 )
280  {
281  v2 |= 4u;
282  }
283  }
284  if ( r_scr & 2 )
285  {
286  if ( ((spduart_internals.dev9_uart_reg_area->r_scr >> 4) & sceModemLINE_DSR) == 0 )
287  {
288  spduart_internals.shutdown_flag = 1;
289  iSetEventFlag(spduart_internals.spduart_modem_ops.evfid, sceModemEFP_PlugOut);
290  }
291  else
292  {
293  if ( !spduart_internals.spduart_data_set_ready_flag )
294  {
295  v2 |= 4u;
296  spduart_internals.spduart_data_set_ready_flag = 1;
297  iSetEventFlag(spduart_internals.spduart_modem_ops.evfid, sceModemEFP_StartDone | sceModemEFP_Send);
298  }
299  }
300  }
301  if ( r_scr & 4 )
302  {
303  iSetEventFlag(spduart_internals.spduart_modem_ops.evfid, sceModemEFP_Ring);
304  }
305  if ( (r_scr & 8) && (((spduart_internals.spduart_msr_cached ^ (u8)r_scr) >> 4) & sceModemLINE_DCD) != 0 )
306  {
307  iSetEventFlag(spduart_internals.spduart_modem_ops.evfid, ( ((r_scr >> 4) & sceModemLINE_DCD) != 0 ) ? sceModemEFP_Connect : sceModemEFP_Disconnect);
308  }
309  spduart_internals.spduart_msr_cached = r_scr;
310  break;
311  case 1:
312  if ( v1 > 0 )
313  {
314  v2 |= 8u;
315  spduart_internals.spduart_rx_count += v1;
316  if ( spduart_internals.recv_buf_struct.m_cur_xfer_len < 257 )
317  {
318  if ( (spduart_internals.spduart_signal_pin & 2) == 0 )
319  {
320  spduart_internals.spduart_signal_pin |= 2u;
321  spduart_internals.dev9_uart_reg_area->r_lsr = spduart_internals.spduart_signal_pin;
322  }
323  }
324  if ( spduart_internals.recv_buf_struct.m_cur_xfer_len >= 768 )
325  {
326  if ( (spduart_internals.spduart_signal_pin & 2) != 0 )
327  {
328  spduart_internals.spduart_signal_pin &= ~2u;
329  spduart_internals.dev9_uart_reg_area->r_lsr = spduart_internals.spduart_signal_pin;
330  }
331  }
332  }
333  if ( v2 )
334  iSetEventFlag(spduart_internals.spduart_ef, v2);
335  return 0;
336  case 2:
337  spduart_internals.spduart_fcr_cached &= ~2u;
338  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = spduart_internals.spduart_fcr_cached;
339  v2 |= 4u;
340  continue;
341  case 4:
342  case 0xC:
343  while ( (spduart_internals.dev9_uart_reg_area->r_msr & 1) != 0 && !spduart_internals.spduart_start_flag )
344  {
345  if ( spduart_internals.recv_buf_struct.m_cur_xfer_len >= 1024 )
346  {
347  ++spduart_internals.spduart_buffer_overflow_count;
348  }
349  else
350  {
351  ++v1;
352  m_offset1 = spduart_internals.recv_buf_struct.m_offset1;
353  *((u8 *)spduart_internals.recv_buf_struct.m_ptr + (spduart_internals.recv_buf_struct.m_offset1 & 0x3FF)) =
354  spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr;
355  spduart_internals.recv_buf_struct.m_offset1 = m_offset1 + 1;
356  ++spduart_internals.recv_buf_struct.m_cur_xfer_len;
357  }
358  }
359  continue;
360  case 6:
361  r_msr = spduart_internals.dev9_uart_reg_area->r_msr;
362  if ( r_msr & 2 )
363  {
364  ++spduart_internals.spduart_overrun_error_count;
365  }
366  if ( r_msr & 4 )
367  {
368  ++spduart_internals.spduart_parity_error_count;
369  }
370  if ( r_msr & 8 )
371  {
372  ++spduart_internals.spduart_framing_error_count;
373  }
374  if ( r_msr & 0x10 )
375  {
376  ++spduart_internals.spduart_break_interrupt_count;
377  }
378  continue;
379  default:
380  continue;
381  }
382  }
383 }
384 
385 static int spduart_set_baud(int baud)
386 {
387  switch ( baud )
388  {
389  case 115200:
390  return 1;
391  case 57600:
392  return 2;
393  case 38400:
394  return 3;
395  case 28800:
396  return 4;
397  case 19200:
398  return 6;
399  case 9600:
400  return 12;
401  default:
402  return 0;
403  }
404 }
405 
406 static void spduart_do_init_dev9(struct spduart_internals_ *priv)
407 {
408  int v2;
409 
410  spduart_internals.dev9_uart_reg_area->r_cr1 = 27;
411  spduart_internals.dev9_uart_reg_area->r_cr2 = 4;
412  DelayThread(10000);
413  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = 0;
414  priv->spduart_mcr_cached = -125;
415  spduart_internals.dev9_uart_reg_area->r_mcr = priv->spduart_mcr_cached;
416  v2 = spduart_set_baud(priv->spduart_baud_);
417  spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr = v2;
418  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = (v2 >> 8) & 0xFF;
419  priv->spduart_mcr_cached = 3;
420  spduart_internals.dev9_uart_reg_area->r_mcr = priv->spduart_mcr_cached;
421  priv->spduart_signal_pin = 3;
422  spduart_internals.dev9_uart_reg_area->r_lsr = priv->spduart_signal_pin;
423  switch ( priv->spduart_trig_ )
424  {
425  case 1:
426  {
427  spduart_internals.dev9_uart_reg_area->r_lcr = 1;
428  break;
429  }
430  case 4:
431  {
432  spduart_internals.dev9_uart_reg_area->r_lcr = 65;
433  break;
434  }
435  case 8:
436  default:
437  {
438  spduart_internals.dev9_uart_reg_area->r_lcr = -127;
439  break;
440  }
441  case 14:
442  {
443  spduart_internals.dev9_uart_reg_area->r_lcr = -63;
444  break;
445  }
446  }
447 }
448 
449 static void spduart_deinit()
450 {
451  spduart_internals.dev9_uart_reg_area->r_cr2 = -124;
452 }
453 
454 static void fail_sleep(const char *fmt)
455 {
456  sceInetPrintf(fmt);
457  while ( 1 )
458  SleepThread();
459 }
460 
461 static void sleep_on_shutdown(const struct spduart_internals_ *priv)
462 {
463  if ( priv->shutdown_flag )
464  {
465  fail_sleep("spduart: plug-out\n");
466  }
467 }
468 
469 static int spduart_send_now(struct spduart_internals_ *priv, const char *in_buf, char *expected_buf)
470 {
471  char *v6;
472  int v7;
473  char r_scr;
474  int v11;
475  char v12;
476  int v13;
477  int v14;
478 
479  v6 = expected_buf;
480  v7 = 0;
481  while ( 1 )
482  {
483  int v8;
484  int v9;
485 
486  v8 = 0;
487  v9 = 0;
488  sleep_on_shutdown(priv);
489  if ( *in_buf )
490  {
491  r_scr = spduart_internals.dev9_uart_reg_area->r_scr;
492  priv->spduart_msr_cached = r_scr;
493  if ( ((r_scr >> 4) & sceModemLINE_CTS) != 0 && ((spduart_internals.dev9_uart_reg_area->r_msr >> 4) & sceModemLINE_DSR) != 0 )
494  {
495  v11 = 15;
496  do
497  {
498  v12 = *in_buf;
499  v13 = v11;
500  if ( !v12 )
501  break;
502  ++in_buf;
503  ++v9;
504  --v11;
505  spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr = v12;
506  } while ( v13 > 0 );
507  }
508  }
509  if ( (spduart_internals.dev9_uart_reg_area->r_msr & 1) != 0 )
510  {
511  v8 = 1;
512  v14 = *v6;
513  if ( *v6 )
514  {
515  ++v6;
516  if ( v14 != spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr )
517  v6 = expected_buf;
518  }
519  }
520  if ( !*in_buf )
521  {
522  if ( !*v6 )
523  break;
524  }
525  if ( !v9 && !v8 )
526  {
527  if ( v7 >= 300 )
528  return -1;
529  v7 += 1;
530  DelayThread(10000);
531  }
532  }
533  return 0;
534 }
535 
536 static void spduart_init_hw(struct spduart_internals_ *priv)
537 {
538  int i;
539  int v5;
540  char *buf1data;
541 
542  while ( 1 )
543  {
544  int v7;
545  int v10;
546  const char *v11;
547 
548  while ( 1 )
549  {
550  while ( 1 )
551  {
552  do
553  {
554  spduart_deinit();
555  DelayThread(200000);
556  sleep_on_shutdown(priv);
557  spduart_do_init_dev9(priv);
558  for ( i = 0; i < 300; ++i )
559  {
560  sleep_on_shutdown(priv);
561  DelayThread(10000);
562  }
563  while ( 1 )
564  {
565  sleep_on_shutdown(priv);
566  priv->spduart_msr_cached = spduart_internals.dev9_uart_reg_area->r_scr;
567  if ( ((priv->spduart_msr_cached >> 4) & sceModemLINE_DSR) != 0 )
568  break;
569  DelayThread(100000);
570  }
571  } while ( spduart_send_now(priv, "AT\r", "OK") < 0 && spduart_send_now(priv, "AT\r", "OK") < 0 );
572  if ( spduart_send_now(priv, "ATI3\r", "P2109-V90") < 0 )
573  break;
574  sceInetPrintf("spduart: P2109-V90 detected\n");
575  spduart_send_now(priv, "AT**\r", "Download initiated ..");
576  sceInetPrintf("spduart: downloading (9A-40)\n");
577  v5 = 0;
578  i = 0;
579  while ( modem_firmware_s37[i] )
580  {
581  v5 = spduart_send_now(priv, modem_firmware_s37[i], ".");
582  if ( v5 < 0 )
583  {
584  sceInetPrintf("spduart: failed to download (1)\n");
585  break;
586  }
587  i += 1;
588  }
589  if ( v5 >= 0 && spduart_send_now(priv, "S70500000000FA\r", "OK") >= 0 )
590  {
591  sceInetPrintf("spduart: download completed\n");
592  break;
593  }
594  sceInetPrintf("spduart: failed to download (2)\n");
595  }
596  if ( priv->spduart_nogci_ )
597  return;
598  if ( !priv->spduart_gci_[0] )
599  break;
600  sprintf(priv->buf2data, "AT+GCI=%c%c\r", priv->spduart_gci_[0], priv->spduart_gci_[1]);
601  sceInetPrintf("spduart: sending \"%S\"\n", priv->buf2data);
602  if ( spduart_send_now(priv, priv->buf2data, "OK") >= 0 )
603  return;
604  sceInetPrintf("spduart: failed to set GCI (1)\n");
605  }
606  if ( !priv->spduart_dial_[0] )
607  {
608  fail_sleep("spduart: no dial_cnf\n");
609  }
610  sceInetPrintf("spduart: scanning GCI setting in \"%s\"\n", priv->spduart_dial_);
611  v7 = open(priv->spduart_dial_, 1);
612  if ( v7 < 0 )
613  {
614  fail_sleep("spduart: can't open\n");
615  }
616  buf1data = priv->buf1data;
617  v10 = read(v7, buf1data, 1024);
618  if ( v10 < 0 )
619  {
620  fail_sleep("spduart: read error\n");
621  }
622  close(v7);
623  if ( (unsigned int)v10 >= 0x400 )
624  {
625  fail_sleep("spduart: file too big\n");
626  }
627  v11 = &buf1data[v10];
628  while ( 1 )
629  {
630  if ( buf1data >= v11 )
631  {
632  fail_sleep("spduart: no GCI setting\n");
633  }
634  while ( buf1data < v11 )
635  {
636  if ( (isspace(*buf1data)) == 0 )
637  break;
638  buf1data += 1;
639  }
640  if ( *buf1data != '#' )
641  {
642  while ( buf1data < v11 && *buf1data != '+' )
643  {
644  buf1data += 1;
645  }
646  if ( (*buf1data == '+') && (strncmp("+GCI=", buf1data, 5) == 0) )
647  {
648  buf1data += 5;
649  if ( ((isxdigit(buf1data[0])) != 0) && ((isxdigit(buf1data[1])) != 0) )
650  {
651  break;
652  }
653  }
654  }
655  while ( buf1data < v11 && *buf1data != '\n' )
656  {
657  buf1data += 1;
658  }
659  if ( *buf1data == '\n' )
660  buf1data += 1;
661  }
662  sprintf(priv->buf2data, "AT+GCI=%c%c\r", (u8)*buf1data, (u8)buf1data[1]);
663  sceInetPrintf("spduart: sending \"%S\"\n", priv->buf2data);
664  if ( spduart_send_now(priv, priv->buf2data, "OK") < 0 )
665  {
666  sceInetPrintf("spduart: failed to set GCI (2)\n");
667  continue;
668  }
669  break;
670  }
671 }
672 
673 static void spduart_thread_proc(void *arg)
674 {
675  struct spduart_internals_ *priv = arg;
676  int i;
677  int m_cur_xfer_len;
678  int v10;
679  u32 v12;
680 
681  spduart_init_hw(priv);
682  priv->spduart_fcr_cached = 13;
683  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = priv->spduart_fcr_cached;
684  while ( !WaitEventFlag(priv->spduart_ef, 0xFu, 17, &v12) )
685  {
686  if ( (v12 & 2) != 0 && !priv->spduart_start_flag )
687  {
688  SpdIntrDisable(4096);
689  if ( priv->spduart_alarm_1e4_flag )
690  {
691  CancelAlarm(alarm_cb_1e4, priv);
692  priv->spduart_alarm_1e4_flag = 0;
693  }
694  if ( priv->spduart_alarm_1e6_flag )
695  {
696  CancelAlarm(alarm_cb_1e6, priv);
697  priv->spduart_alarm_1e6_flag = 0;
698  }
699  priv->spduart_signal_pin = 0;
700  spduart_internals.dev9_uart_reg_area->r_lsr = 0;
701  spduart_internals.dev9_uart_reg_area->r_lcr = -121;
702  priv->recv_buf_struct.m_cur_xfer_len = 0;
703  priv->recv_buf_struct.m_offset1 = 0;
704  priv->recv_buf_struct.m_offset2 = 0;
705  priv->send_buf_struct.m_cur_xfer_len = 0;
706  priv->send_buf_struct.m_offset1 = 0;
707  priv->send_buf_struct.m_offset2 = 0;
708  // cppcheck-suppress redundantAssignment
709  spduart_internals.dev9_uart_reg_area->r_lcr = -127;
710  priv->spduart_start_flag = 1;
711  priv->spduart_stop_flag = 0;
712  if ( !priv->shutdown_flag )
713  {
714  priv->spduart_mcr_cached = 67;
715  spduart_internals.dev9_uart_reg_area->r_mcr = priv->spduart_mcr_cached;
716  for ( i = 0; i < 20; i += 1 )
717  {
718  if ( priv->shutdown_flag )
719  break;
720  if ( ((priv->spduart_msr_cached >> 4) & sceModemLINE_DCD) == 0 )
721  {
722  priv->spduart_mcr_cached = 3;
723  spduart_internals.dev9_uart_reg_area->r_mcr = 3;
724  for ( i = 0; i < 300; i += 1 )
725  {
726  if ( priv->shutdown_flag )
727  break;
728  DelayThread(10000);
729  }
730  break;
731  }
732  DelayThread(100000);
733  }
734  }
735  }
736  if ( !priv->spduart_start_flag )
737  {
738  if ( (v12 & 4) != 0 )
739  {
740  if ( priv->spduart_data_set_ready_flag )
741  {
742  if ( spduart_send(priv) > 0 )
743  {
744  m_cur_xfer_len = priv->send_buf_struct.m_cur_xfer_len;
745  if ( m_cur_xfer_len >= 257 )
746  {
747  priv->spduart_modem_ops.snd_len = 1024 - m_cur_xfer_len;
748  SetEventFlag(priv->spduart_modem_ops.evfid, sceModemEFP_Send);
749  }
750  }
751  }
752  }
753  if ( (v12 & 8) != 0 )
754  {
755  if ( priv->spduart_alarm_1e4_flag )
756  {
757  CancelAlarm(alarm_cb_1e4, priv);
758  priv->spduart_alarm_1e4_flag = 0;
759  }
760  v10 = priv->recv_buf_struct.m_cur_xfer_len;
761  if ( v10 >= 257 )
762  {
763  priv->spduart_modem_ops.rcv_len = v10;
764  SetEventFlag(priv->spduart_modem_ops.evfid, sceModemEFP_Recv);
765  }
766  else
767  {
768  SetAlarm(&priv->spduart_clock_1e4, alarm_cb_1e4, priv);
769  priv->spduart_alarm_1e4_flag = 1;
770  }
771  }
772  }
773  else if ( (v12 & 1) != 0 )
774  {
775  priv->shutdown_flag = 0;
776  priv->spduart_data_set_ready_flag = 0;
777  priv->spduart_modem_ops.snd_len = 1024;
778  priv->spduart_signal_pin = 3;
779  spduart_internals.dev9_uart_reg_area->r_lsr = 3;
780  priv->spduart_msr_cached = spduart_internals.dev9_uart_reg_area->r_scr;
781  spduart_dump_msr(priv->spduart_msr_cached);
782  if ( ((priv->spduart_msr_cached >> 4) & sceModemLINE_DSR) != 0 )
783  {
784  SetEventFlag(priv->spduart_modem_ops.evfid, sceModemEFP_StartDone | sceModemEFP_Send);
785  priv->spduart_data_set_ready_flag = 1;
786  }
787  if ( ((priv->spduart_msr_cached >> 4) & sceModemLINE_DCD) != 0 )
788  {
789  SetEventFlag(priv->spduart_modem_ops.evfid, sceModemEFP_Connect);
790  }
791  priv->spduart_start_flag = 0;
792  SetAlarm(&priv->spduart_clock_1e6, alarm_cb_1e6, priv);
793  priv->spduart_alarm_1e6_flag = 1;
794  SpdIntrEnable(4096);
795  }
796  }
797 }
798 
799 static int spduart_op_start(void *userdata, int flags)
800 {
801  struct spduart_internals_ *priv;
802 
803  (void)flags;
804  priv = (struct spduart_internals_ *)userdata;
805  priv->spduart_stop_flag = 0;
806  SetEventFlag(priv->spduart_ef, 1u);
807  return 0;
808 }
809 
810 static int spduart_op_stop(void *userdata, int flags)
811 {
812  struct spduart_internals_ *priv;
813 
814  (void)flags;
815  priv = (struct spduart_internals_ *)userdata;
816  priv->spduart_stop_flag = 1;
817  SetEventFlag(priv->spduart_ef, 2u);
818  return 0;
819 }
820 
821 static int spduart_op_recv(void *userdata, void *ptr, int len)
822 {
823  int m_cur_xfer_len;
824  size_t v7;
825  int v8;
826  size_t v9;
827  int state;
828  struct spduart_internals_ *priv;
829 
830  priv = (struct spduart_internals_ *)userdata;
831  m_cur_xfer_len = len;
832  v7 = 0;
833  if ( priv->recv_buf_struct.m_cur_xfer_len < len )
834  m_cur_xfer_len = priv->recv_buf_struct.m_cur_xfer_len;
835  v8 = priv->recv_buf_struct.m_offset2 & 0x3FF;
836  v9 = 1024 - v8;
837  if ( m_cur_xfer_len < 1024 - v8 )
838  v9 = m_cur_xfer_len;
839  if ( v9 > 0 )
840  {
841  size_t v10;
842 
843  v7 = v9;
844  bcopy((char *)priv->recv_buf_struct.m_ptr + v8, ptr, v9);
845  v10 = m_cur_xfer_len - v9;
846  if ( v10 > 0 )
847  {
848  bcopy(priv->recv_buf_struct.m_ptr, (char *)ptr + v9, v10);
849  v7 += v10;
850  }
851  CpuSuspendIntr(&state);
852  priv->recv_buf_struct.m_cur_xfer_len -= v7;
853  priv->recv_buf_struct.m_offset2 += v7;
854  priv->spduart_modem_ops.rcv_len = priv->recv_buf_struct.m_cur_xfer_len;
855  if ( priv->recv_buf_struct.m_cur_xfer_len < 257 )
856  {
857  if ( (priv->spduart_signal_pin & 2) == 0 )
858  {
859  priv->spduart_signal_pin |= 2;
860  spduart_internals.dev9_uart_reg_area->r_lsr = priv->spduart_signal_pin;
861  }
862  }
863  CpuResumeIntr(state);
864  }
865  return v7;
866 }
867 
868 static int spduart_op_send(void *userdata, void *ptr, int len)
869 {
870  int v4;
871  int v7;
872  int v8;
873  size_t v9;
874  int state;
875  struct spduart_internals_ *priv;
876 
877  priv = (struct spduart_internals_ *)userdata;
878  v4 = len;
879  v7 = 0;
880  if ( 1024 - priv->send_buf_struct.m_cur_xfer_len < len )
881  v4 = 1024 - priv->send_buf_struct.m_cur_xfer_len;
882  v8 = priv->send_buf_struct.m_offset1 & 0x3FF;
883  v9 = 1024 - v8;
884  if ( (unsigned int)v4 < v9 )
885  v9 = v4;
886  if ( v9 > 0 )
887  {
888  size_t v10;
889 
890  v7 = v9;
891  bcopy(ptr, (char *)priv->send_buf_struct.m_ptr + v8, v9);
892  v10 = v4 - v9;
893  if ( v10 > 0 )
894  {
895  bcopy((char *)ptr + v9, priv->send_buf_struct.m_ptr, v10);
896  v7 += v10;
897  }
898  CpuSuspendIntr(&state);
899  priv->send_buf_struct.m_cur_xfer_len += v7;
900  priv->send_buf_struct.m_offset1 += v7;
901  priv->spduart_modem_ops.snd_len = 1024 - priv->send_buf_struct.m_cur_xfer_len;
902  CpuResumeIntr(state);
903  }
904  if ( v7 > 0 )
905  SetEventFlag(priv->spduart_ef, 4u);
906  return v7;
907 }
908 
909 static int spduart_op_control(void *userdata, int code, void *ptr, int len)
910 {
911  int v22;
912  int state;
913  int priority;
914  unsigned int v25;
915  int v26;
916  struct spduart_internals_ *priv;
917 
918  priv = (struct spduart_internals_ *)userdata;
919  switch ( code )
920  {
921  case sceModemCC_FLUSH_RXBUF:
922  case sceModemCC_FLUSH_TXBUF:
923  case sceModemCC_GET_DIALCONF:
924  break;
925  default:
926  {
927  if ( len != 4 )
928  return -512;
929  }
930  }
931  switch ( code )
932  {
933  case sceModemCC_GET_THPRI:
934  {
935  bcopy(&priv->spduart_thpri_, ptr, 4);
936  return 0;
937  }
938  case sceModemCC_GET_IF_TYPE:
939  {
940  v22 = sceModemIFT_SERIAL;
941  bcopy(&v22, ptr, 4);
942  return 0;
943  }
944  case sceModemCC_FLUSH_RXBUF:
945  {
946  CpuSuspendIntr(&state);
947  priv->recv_buf_struct.m_offset1 = 0;
948  priv->recv_buf_struct.m_offset2 = 0;
949  priv->recv_buf_struct.m_cur_xfer_len = 0;
950  priv->spduart_modem_ops.rcv_len = 0;
951  CpuResumeIntr(state);
952  return 0;
953  }
954  case sceModemCC_FLUSH_TXBUF:
955  {
956  CpuSuspendIntr(&state);
957  priv->send_buf_struct.m_offset1 = 0;
958  priv->send_buf_struct.m_offset2 = 0;
959  priv->send_buf_struct.m_cur_xfer_len = 0;
960  priv->spduart_modem_ops.snd_len = 1024;
961  CpuResumeIntr(state);
962  return 0;
963  }
964  case sceModemCC_GET_DIALCONF:
965  {
966  int v13;
967 
968  v13 = strlen(priv->spduart_dial_) + 1;
969  if ( len < v13 )
970  {
971  return -512;
972  }
973  bcopy(priv->spduart_dial_, ptr, v13);
974  return 0;
975  }
976  case sceModemCC_GET_RX_COUNT:
977  {
978  bcopy(&priv->spduart_rx_count, ptr, 4);
979  return 0;
980  }
981  case sceModemCC_GET_TX_COUNT:
982  {
983  bcopy(&priv->spduart_tx_count, ptr, 4);
984  return 0;
985  }
986  case sceModemCC_GET_OE_COUNT:
987  {
988  bcopy(&priv->spduart_overrun_error_count, ptr, 4);
989  return 0;
990  }
991  case sceModemCC_GET_PE_COUNT:
992  {
993  bcopy(&priv->spduart_parity_error_count, ptr, 4);
994  return 0;
995  }
996  case sceModemCC_GET_FE_COUNT:
997  {
998  bcopy(&priv->spduart_framing_error_count, ptr, 4);
999  return 0;
1000  }
1001  case sceModemCC_GET_BO_COUNT:
1002  {
1003  bcopy(&priv->spduart_buffer_overflow_count, ptr, 4);
1004  return 0;
1005  }
1006  case sceModemCC_GET_PARAM:
1007  {
1008  v25 = sceModemPARAM_RTSCTS;
1009  v25 |= ((priv->spduart_mcr_cached << 30) & (sceModemPARAM_PARODD | sceModemPARAM_PARENB));
1010  v25 |= ((priv->spduart_mcr_cached << 28) & sceModemPARAM_CSIZE);
1011  v25 |= priv->spduart_baud_;
1012  v25 |= ( (priv->spduart_mcr_cached & 4) != 0 ) ? sceModemPARAM_STOP2 : sceModemPARAM_STOP1;
1013  bcopy((int *)&v25, ptr, 4);
1014  return 0;
1015  }
1016  case sceModemCC_GET_LINE:
1017  {
1018  v26 = ((priv->spduart_signal_pin << 4) & (sceModemLINE_DTR | sceModemLINE_RTS)) | (((u8)priv->spduart_msr_cached >> 4) & (sceModemLINE_CTS | sceModemLINE_DSR | sceModemLINE_RI | sceModemLINE_DCD));
1019  bcopy(&v26, ptr, 4);
1020  return 0;
1021  }
1022  case sceModemCC_SET_THPRI:
1023  {
1024  int v6;
1025 
1026  bcopy(ptr, &priority, 4);
1027  v6 = 0;
1028  if ( priv->spduart_thread > 0 )
1029  {
1030  v6 = ChangeThreadPriority(priv->spduart_thread, priority);
1031  if ( !v6 )
1032  priv->spduart_thpri_ = priority;
1033  }
1034  if ( priv->spduart_thread <= 0 || v6 == -413 )
1035  {
1036  if ( (unsigned int)(priority - 9) < 0x73 )
1037  priv->spduart_thpri_ = priority;
1038  }
1039  return v6;
1040  }
1041  case sceModemCC_SET_PARAM:
1042  {
1043  int v17;
1044 
1045  bcopy(ptr, &v25, 4);
1046  v17 = spduart_set_baud(v25 & sceModemPARAM_SPEED);
1047  if ( !v17 )
1048  return -512;
1049  if ( (v25 & sceModemPARAM_STOP1) == 0 || (v25 & (sceModemPARAM_XON | sceModemPARAM_XOFF)) != 0 )
1050  return -512;
1051  if ( (v25 & sceModemPARAM_PARODD) != 0 || (v25 & sceModemPARAM_RTSCTS) == 0 )
1052  return -512;
1053  priv->spduart_mcr_cached &= 0x40;
1054  priv->spduart_mcr_cached |= ((v25 & (sceModemPARAM_PARODD | sceModemPARAM_PARENB)) >> 30);
1055  priv->spduart_mcr_cached |= ((v25 & sceModemPARAM_CSIZE) >> 28);
1056  priv->spduart_mcr_cached |= ((v25 & sceModemPARAM_STOPS) >> 27);
1057  priv->spduart_mcr_cached |= 0x80;
1058  spduart_internals.dev9_uart_reg_area->r_mcr = priv->spduart_mcr_cached;
1059  spduart_internals.dev9_uart_reg_area->r_wrthr_rdrbr = v17;
1060  spduart_internals.dev9_uart_reg_area->r_wrfcr_rdiir = (v17 >> 8) & 0xFF;
1061  priv->spduart_mcr_cached &= ~0x80;
1062  // cppcheck-suppress redundantAssignment
1063  spduart_internals.dev9_uart_reg_area->r_mcr = priv->spduart_mcr_cached;
1064  return 0;
1065  }
1066  case sceModemCC_SET_LINE:
1067  {
1068  bcopy(ptr, &v26, 4);
1069  if ( (v26 & ~(sceModemLINE_DTR | sceModemLINE_RTS)) != 0 )
1070  return -512;
1071  priv->spduart_signal_pin &= ~3;
1072  priv->spduart_signal_pin |= ((unsigned int)(v26 & (sceModemLINE_DTR | sceModemLINE_RTS)) >> 4);
1073  spduart_internals.dev9_uart_reg_area->r_lsr = priv->spduart_signal_pin;
1074  return 0;
1075  }
1076  default:
1077  return -513;
1078  }
1079 }
1080 
1081 static void shutdown_cb(void)
1082 {
1083  spduart_internals.shutdown_flag = 1;
1084 }
1085 
1086 static int print_version(void)
1087 {
1088  printf("SPDUART (%s)%s\n", "Version 2.26.0", "");
1089  return MODULE_NO_RESIDENT_END;
1090 }
1091 
1092 static int print_usage(void)
1093 {
1094  printf("Usage: spduart [-probe] [-nogci] [baud=<baud>] [trig=<trig>] [gci=<gci>] [thpri=<prio>] [thstack=<stack>] "
1095  "[dial=<dial>]\n");
1096  return MODULE_NO_RESIDENT_END;
1097 }
1098 
1099 // cppcheck-suppress unusedFunction
1100 void spduart_2_deinit(int a1)
1101 {
1102  USE_SPD_REGS;
1103 
1104  if ( !a1 && (SPD_REG16(SPD_R_REV_3) & 8) != 0 )
1105  spduart_internals.dev9_uart_reg_area->r_cr2 = -124;
1106 }
1107 
1108 // cppcheck-suppress constParameter
1109 static int module_start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
1110 {
1111  int v2;
1112  int v3;
1113  int v5;
1114  char *v7;
1115  int v11;
1116  int v14;
1117  int v16;
1118  iop_event_t v17;
1119  iop_thread_t v18;
1120  USE_SPD_REGS;
1121 
1122  (void)startaddr;
1123 
1124  v2 = 0;
1125  v3 = 0;
1126  spduart_internals.spduart_thpri_ = 40;
1127  spduart_internals.spduart_thstack_ = 0x2000;
1128  spduart_internals.spduart_dial_[0] = 0;
1129  spduart_internals.spduart_baud_ = 115200;
1130  spduart_internals.spduart_trig_ = 8;
1131  for ( v5 = 1; v5 < ac; v5 += 1 )
1132  {
1133  if ( !strcmp("-help", av[v5]) )
1134  {
1135  return print_usage();
1136  }
1137  else if ( !strcmp("-version", av[v5]) )
1138  {
1139  return print_version();
1140  }
1141  else if ( !strcmp("-probe", av[v5]) )
1142  {
1143  v3 = 1;
1144  continue;
1145  }
1146  else if ( !strcmp("-nogci", av[v5]) )
1147  {
1148  spduart_internals.spduart_nogci_ = 1;
1149  continue;
1150  }
1151  else if ( !strncmp("dial=", av[v5], 5) )
1152  {
1153  strcpy(spduart_internals.spduart_dial_, av[v5] + 5);
1154  continue;
1155  }
1156  else if ( !strncmp("gci=", av[v5], 4) )
1157  {
1158  v7 = (char *)(av[v5] + 4);
1159  if ( (isxdigit(*v7)) == 0 || (isxdigit(v7[1])) == 0 )
1160  return print_usage();
1161  spduart_internals.spduart_gci_[0] = v7[0];
1162  spduart_internals.spduart_gci_[1] = v7[1];
1163  continue;
1164  }
1165  else if ( !strncmp("thpri=", av[v5], 6) )
1166  {
1167  v7 = (char *)(av[v5] + 6);
1168  if ( (isdigit(*v7)) == 0 )
1169  return print_usage();
1170  v11 = strtol(v7, 0, 10);
1171  if ( (unsigned int)(v11 - 9) >= 0x73 )
1172  return print_usage();
1173  spduart_internals.spduart_thpri_ = v11;
1174  }
1175  else if ( !strncmp("thstack=", av[v5], 8) )
1176  {
1177  v7 = (char *)(av[v5] + 8);
1178  if ( (isdigit(*v7)) == 0 )
1179  return print_usage();
1180  spduart_internals.spduart_thstack_ = strtol(v7, 0, 10);
1181  while ( *v7 )
1182  {
1183  if ( (isdigit(*v7)) == 0 )
1184  break;
1185  ++v7;
1186  }
1187  if ( !strcmp(v7, "KB") )
1188  {
1189  spduart_internals.spduart_thstack_ <<= 10;
1190  continue;
1191  }
1192  }
1193  else if ( !strncmp("baud=", av[v5], 5) )
1194  {
1195  v7 = (char *)(av[v5] + 5);
1196  if ( (isdigit(*v7)) == 0 )
1197  return print_usage();
1198  spduart_internals.spduart_baud_ = strtol(v7, 0, 10);
1199  if ( !spduart_set_baud(spduart_internals.spduart_baud_) )
1200  return print_usage();
1201  }
1202  else if ( !strncmp("trig=", av[v5], 5) )
1203  {
1204  v7 = (char *)(av[v5] + 5);
1205  if ( (isdigit(*v7)) == 0 )
1206  return print_usage();
1207  v11 = strtol(v7, 0, 10);
1208  switch ( v11 )
1209  {
1210  case 1:
1211  case 4:
1212  case 8:
1213  case 14:
1214  {
1215  spduart_internals.spduart_trig_ = v11;
1216  break;
1217  }
1218  default:
1219  {
1220  return print_usage();
1221  }
1222  }
1223  }
1224  else
1225  {
1226  return print_usage();
1227  }
1228  while ( *v7 )
1229  {
1230  if ( (isdigit(*v7)) == 0 )
1231  break;
1232  ++v7;
1233  }
1234  if ( *v7 )
1235  return print_usage();
1236  }
1237  if ( (SPD_REG16(SPD_R_REV_3) & 8) == 0 )
1238  {
1239  sceInetPrintf("spduart: SPEED-UART not found\n");
1240  return 1;
1241  }
1242  sceInetPrintf("spduart: SPEED-UART detected\n");
1243  if ( v3 )
1244  {
1245  return 5;
1246  }
1247  if ( RegisterLibraryEntries(&_exp_spduart) )
1248  {
1249  sceInetPrintf("spduart: module already loaded\n");
1250  }
1251  else
1252  {
1253  v14 = 0;
1254  sceInetPrintf(
1255  "spduart: thpri=%d baud=%d trig=%d\n",
1256  spduart_internals.spduart_thpri_,
1257  spduart_internals.spduart_baud_,
1258  spduart_internals.spduart_trig_);
1259  spduart_internals.dev9_uart_reg_area = (uart16550_regs_t *)0xB0000080;
1260  spduart_internals.recv_buf_struct.m_ptr = spduart_internals.buf1data;
1261  spduart_internals.send_buf_struct.m_ptr = spduart_internals.buf2data;
1262  spduart_internals.spduart_start_flag = 1;
1263  spduart_internals.spduart_stop_flag = 0;
1264  spduart_do_init_dev9(&spduart_internals);
1265  for ( v14 = 0; v14 < 30; v14 += 1 )
1266  {
1267  spduart_internals.spduart_msr_cached = spduart_internals.dev9_uart_reg_area->r_scr;
1268  if ( ((spduart_internals.spduart_msr_cached >> 4) & sceModemLINE_DSR) != 0 )
1269  {
1270  sceInetPrintf("spduart: Modem module detected\n");
1271  Dev9RegisterPowerOffHandler(1, shutdown_cb);
1272  memset(&v17, 0, sizeof(v17));
1273  spduart_internals.spduart_ef = CreateEventFlag(&v17);
1274  if ( spduart_internals.spduart_ef > 0 )
1275  {
1276  v18.attr = 0x2000000;
1277  v18.thread = spduart_thread_proc;
1278  v18.option = 0;
1279  v18.priority = spduart_internals.spduart_thpri_;
1280  v18.stacksize = spduart_internals.spduart_thstack_;
1281  v16 = CreateThread(&v18);
1282  if ( v16 > 0 )
1283  {
1284  spduart_internals.spduart_thread = v16;
1285  if ( !StartThread(v16, &spduart_internals) )
1286  {
1287  SpdIntrDisable(4096);
1288  SpdRegisterIntrHandler(12, (dev9_intr_cb_t)spduart_dev9_intr_cb);
1289  USec2SysClock(10000u, &spduart_internals.spduart_clock_1e4);
1290  USec2SysClock(1000000u, &spduart_internals.spduart_clock_1e6);
1291  bzero(&spduart_internals.spduart_modem_ops, 108);
1292  spduart_internals.spduart_modem_ops.module_name = "spduart";
1293  spduart_internals.spduart_modem_ops.vendor_name = "SCE";
1294  spduart_internals.spduart_modem_ops.device_name = "Modem (Network Adaptor)";
1295  spduart_internals.spduart_modem_ops.bus_type = sceModemBus_NIC;
1296  spduart_internals.spduart_modem_ops.start = spduart_op_start;
1297  spduart_internals.spduart_modem_ops.stop = spduart_op_stop;
1298  spduart_internals.spduart_modem_ops.recv = spduart_op_recv;
1299  spduart_internals.spduart_modem_ops.send = spduart_op_send;
1300  spduart_internals.spduart_modem_ops.prot_ver = sceModemProtVer;
1301  spduart_internals.spduart_modem_ops.impl_ver = 0;
1302  spduart_internals.spduart_modem_ops.priv = &spduart_internals;
1303  spduart_internals.spduart_modem_ops.control = spduart_op_control;
1304  if ( sceModemRegisterDevice(&spduart_internals.spduart_modem_ops) >= 0 )
1305  {
1306 #if 0
1307  return MODULE_REMOVABLE_END;
1308 #else
1309  if ( mi && ((mi->newflags & 2) != 0) )
1310  mi->newflags |= 0x10;
1311  return MODULE_RESIDENT_END;
1312 #endif
1313  }
1314  v2 += 1;
1315  TerminateThread(spduart_internals.spduart_thread);
1316  }
1317  v2 += 1;
1318  DeleteThread(spduart_internals.spduart_thread);
1319  }
1320  v2 += 1;
1321  DeleteEventFlag(spduart_internals.spduart_ef);
1322  }
1323  }
1324  DelayThread(100000);
1325  }
1326  sceInetPrintf("spduart: Modem module NOT detected\n");
1327  spduart_deinit();
1328  ReleaseLibraryEntries(&_exp_spduart);
1329  }
1330  sceInetPrintf("spduart: not resident end (fail%d)\n", v2);
1331  return MODULE_NO_RESIDENT_END;
1332 }
1333 
1334 static int module_stop(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
1335 {
1336  (void)ac;
1337  (void)av;
1338  (void)startaddr;
1339  (void)mi;
1340 
1341  if ( !spduart_internals.spduart_start_flag && !spduart_internals.spduart_stop_flag )
1342  {
1343  sceInetPrintf("spduart: can't unload (busy)\n");
1344  return MODULE_REMOVABLE_END;
1345  }
1346  sceModemUnregisterDevice(&spduart_internals.spduart_modem_ops);
1347  TerminateThread(spduart_internals.spduart_thread);
1348  DeleteThread(spduart_internals.spduart_thread);
1349  DeleteEventFlag(spduart_internals.spduart_ef);
1350  if ( spduart_internals.spduart_alarm_1e4_flag )
1351  CancelAlarm(alarm_cb_1e4, &spduart_internals);
1352  if ( spduart_internals.spduart_alarm_1e6_flag )
1353  CancelAlarm(alarm_cb_1e6, &spduart_internals);
1354  Dev9RegisterPowerOffHandler(1, 0);
1355  ReleaseLibraryEntries(&_exp_spduart);
1356  SpdIntrDisable(4096);
1357  spduart_deinit();
1358  return MODULE_NO_RESIDENT_END;
1359 }
_ModuleInfo::newflags
u16 newflags
Definition: loadcore.h:36
speedregs.h
uart16550_regs_::r_lcr
u8 r_lcr
Definition: spduart.c:30
uart16550_regs_::r_lsr
u8 r_lsr
Definition: spduart.c:34
uart16550_regs_::r_mcr
u8 r_mcr
Definition: spduart.c:32
uart16550_regs_::r_cr1
u8 r_cr1
Definition: spduart.c:42
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
ctype.h
irx_export_table
Definition: irx.h:90
uart16550_regs_::r_msr
u8 r_msr
Definition: spduart.c:36
sceModemOps
Definition: modem.h:95
_iop_thread
Definition: thbase.h:39
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
spduart_buffer_struct_
Definition: spduart.c:48
uart16550_regs_::r_wrfcr_rdiir
u8 r_wrfcr_rdiir
Definition: spduart.c:28
uart16550_regs_::r_scr
u8 r_scr
Definition: spduart.c:38
uart16550_regs_::r_cr2
u8 r_cr2
Definition: spduart.c:44
uart16550_regs_
Definition: spduart.c:24
_ModuleInfo
Definition: loadcore.h:31
iop_event_t
Definition: thevent.h:37
_iop_sys_clock
Definition: thbase.h:87
uart16550_regs_::r_wrthr_rdrbr
u8 r_wrthr_rdrbr
Definition: spduart.c:26
spduart_internals_
Definition: spduart.c:56