00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <sys/atom.h>
00053 #include <sys/event.h>
00054 #include <sys/timer.h>
00055
00056 #include <dev/irqreg.h>
00057
00058 #include <arch/arm.h>
00059 #include <dev/usart.h>
00060
00061 #include <stdio.h>
00066
00067
00068 #define ASCII_XON 0x11
00069
00070 #define ASCII_XOFF 0x13
00071
00072
00073 #define XON_PENDING 0x10
00074
00075 #define XOFF_PENDING 0x20
00076
00077 #define XOFF_SENT 0x40
00078
00079 #define XOFF_RCVD 0x80
00080
00081
00085
00086
00090 static ureg_t flow_control;
00091
00092 static volatile ureg_t tx_stop = 1;
00093
00094 static USARTDCB dcb_uart;
00095
00096
00097
00098
00099
00100
00101 static void GbaUartTxEmpty(RINGBUF * rbf)
00102 {
00103 register u_char *cp = rbf->rbf_tail;
00104
00105
00106
00107
00108 if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00109 if (flow_control & XON_PENDING) {
00110 outw(REG_SIODATA8, ASCII_XOFF);
00111 flow_control |= XOFF_SENT;
00112 } else {
00113 outw(REG_SIODATA8, ASCII_XON);
00114 flow_control &= ~XOFF_SENT;
00115 }
00116 flow_control &= ~(XON_PENDING | XOFF_PENDING);
00117 return;
00118 }
00119
00120 if (flow_control & XOFF_RCVD) {
00121
00122
00123
00124
00125 tx_stop = 1;
00126 outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);
00127 return;
00128 }
00129
00130 if (rbf->rbf_cnt) {
00131
00132 rbf->rbf_cnt--;
00133
00134
00135
00136
00137 outw(REG_SIODATA8, *cp);
00138
00139
00140
00141
00142 if (++cp == rbf->rbf_last) {
00143 cp = rbf->rbf_start;
00144 }
00145 rbf->rbf_tail = cp;
00146 if (rbf->rbf_cnt == rbf->rbf_lwm) {
00147 NutEventPostFromIrq(&rbf->rbf_que);
00148 }
00149 }
00150
00151
00152
00153
00154 else {
00155 tx_stop = 1;
00156 outw(REG_SIOCNT, (inw(REG_SIOCNT) & ~SIO_SEND_ENA) | SIO_TX_FULL);
00157 rbf->rbf_cnt = 0;
00158 NutEventPostFromIrq(&rbf->rbf_que);
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167
00168 static void GbaUartRxFull(RINGBUF * rbf)
00169 {
00170 register size_t cnt;
00171 register u_char ch;
00172
00173
00174
00175
00176
00177
00178
00179 ch = (u_char) inw(REG_SIODATA8);
00180
00181
00182
00183
00184
00185
00186 if (flow_control) {
00187
00188 if (ch == ASCII_XOFF) {
00189 tx_stop = 1;
00190 outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);
00191 flow_control |= XOFF_RCVD;
00192 return;
00193 }
00194
00195 else if (ch == ASCII_XON) {
00196 tx_stop = 0;
00197 outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_SEND_ENA);
00198 flow_control &= ~XOFF_RCVD;
00199 return;
00200 }
00201 }
00202
00203
00204
00205
00206 cnt = rbf->rbf_cnt;
00207 if (cnt >= rbf->rbf_siz) {
00208
00209 return;
00210 }
00211
00212
00213 if (cnt++ == 0) {
00214 NutEventPostFromIrq(&rbf->rbf_que);
00215 }
00216
00217
00218
00219
00220
00221 else if (flow_control) {
00222 if (cnt >= rbf->rbf_hwm) {
00223 if ((flow_control & XOFF_SENT) == 0) {
00224 if (inw(REG_SIOCNT) & SIO_TX_FULL) {
00225 flow_control |= XOFF_PENDING;
00226 } else {
00227 outw(REG_SIODATA8, ASCII_XOFF);
00228 flow_control |= XOFF_SENT;
00229 flow_control &= ~XOFF_PENDING;
00230 }
00231 }
00232 }
00233 }
00234
00235
00236
00237
00238 *rbf->rbf_head++ = ch;
00239 if (rbf->rbf_head == rbf->rbf_last) {
00240 rbf->rbf_head = rbf->rbf_start;
00241 }
00242
00243
00244 rbf->rbf_cnt = cnt;
00245 }
00246
00247 static void GbaUartIsr(void *arg)
00248 {
00249
00250 outw(REG_IF, INT_SIO);
00251
00252 if ((inw(REG_SIOCNT) & SIO_RX_EMPTY) == 0) {
00253 GbaUartRxFull(&((USARTDCB *) arg)->dcb_rx_rbf);
00254 }
00255 if ((inw(REG_SIOCNT) & SIO_TX_FULL) == 0) {
00256 GbaUartTxEmpty(&((USARTDCB *) arg)->dcb_tx_rbf);
00257 }
00258 }
00259
00266 static void GbaUartEnable(void)
00267 {
00268 NutEnterCritical();
00269
00270
00271
00272 NutExitCritical();
00273 }
00274
00278 static void GbaUartDisable(void)
00279 {
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 }
00300
00309 static u_long GbaUartGetSpeed(void)
00310 {
00311 u_short sv = inw(REG_SIOCNT);
00312
00313 if ((sv & SIO_BAUD_115200) == SIO_BAUD_115200) {
00314 return 115200UL;
00315 }
00316 if ((sv & SIO_BAUD_57600) == SIO_BAUD_57600) {
00317 return 57600UL;
00318 }
00319 if ((sv & SIO_BAUD_38400) == SIO_BAUD_38400) {
00320 return 38400L;
00321 }
00322 return 9600UL;
00323 }
00324
00335 static int GbaUartSetSpeed(u_long rate)
00336 {
00337 u_short sv;
00338
00339 GbaUartDisable();
00340 sv = inw(REG_SIOCNT) & ~SIO_BAUD_115200;
00341 if (rate == 115200) {
00342 sv |= SIO_BAUD_115200;
00343 } else {
00344 if (rate == 57600) {
00345 sv |= SIO_BAUD_57600;
00346 } else if (rate == 38400) {
00347 sv |= SIO_BAUD_38400;
00348 }
00349 }
00350 outw(REG_SIOCNT, sv);
00351 GbaUartEnable();
00352
00353 return 0;
00354 }
00355
00364 static u_char GbaUartGetDataBits(void)
00365 {
00366 return 8;
00367 }
00368
00377 static int GbaUartSetDataBits(u_char bits)
00378 {
00379 GbaUartDisable();
00380 GbaUartEnable();
00381
00382
00383
00384
00385 if (GbaUartGetDataBits() != bits) {
00386 return -1;
00387 }
00388 return 0;
00389 }
00390
00399 static u_char GbaUartGetParity(void)
00400 {
00401 return 0;
00402 }
00403
00414 static int GbaUartSetParity(u_char mode)
00415 {
00416 GbaUartDisable();
00417 GbaUartEnable();
00418
00419
00420
00421
00422 if (GbaUartGetParity() != mode) {
00423 return -1;
00424 }
00425 return 0;
00426 }
00427
00436 static u_char GbaUartGetStopBits(void)
00437 {
00438 return 1;
00439 }
00440
00449 static int GbaUartSetStopBits(u_char bits)
00450 {
00451 GbaUartDisable();
00452 GbaUartEnable();
00453
00454
00455
00456
00457 if (GbaUartGetStopBits() != bits) {
00458 return -1;
00459 }
00460 return 0;
00461 }
00462
00468 static u_long GbaUartGetStatus(void)
00469 {
00470 u_long rc = 0;
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 if (flow_control) {
00481 if (flow_control & XOFF_SENT) {
00482 rc |= UART_RXDISABLED;
00483 }
00484 if (flow_control & XOFF_RCVD) {
00485 rc |= UART_TXDISABLED;
00486 }
00487 }
00488
00489
00490
00491
00492
00493 if ((rc & UART_RXDISABLED) == 0) {
00494 rc |= UART_RXENABLED;
00495 }
00496 if ((rc & UART_TXDISABLED) == 0) {
00497 rc |= UART_TXENABLED;
00498 }
00499 return rc;
00500 }
00501
00509 static int GbaUartSetStatus(u_long flags)
00510 {
00511
00512
00513
00514 if (flow_control) {
00515
00516
00517 NutEnterCritical();
00518
00519
00520
00521
00522
00523 if (flags & UART_RXENABLED) {
00524 flow_control &= ~XOFF_SENT;
00525 } else if (flags & UART_RXDISABLED) {
00526 flow_control |= XOFF_SENT;
00527 }
00528
00529
00530
00531
00532
00533 if (flags & UART_TXENABLED) {
00534 flow_control &= ~XOFF_RCVD;
00535 } else if (flags & UART_TXDISABLED) {
00536 flow_control |= XOFF_RCVD;
00537 }
00538 NutExitCritical();
00539 }
00540
00541
00542
00543
00544 if ((GbaUartGetStatus() & ~UART_ERRORS) != flags) {
00545 return -1;
00546 }
00547 return 0;
00548 }
00549
00559 static u_char GbaUartGetClockMode(void)
00560 {
00561 return 0;
00562 }
00563
00575 static int GbaUartSetClockMode(u_char mode)
00576 {
00577
00578
00579
00580 if (GbaUartGetClockMode() != mode) {
00581 return -1;
00582 }
00583 return 0;
00584 }
00585
00594 static u_long GbaUartGetFlowControl(void)
00595 {
00596 u_long rc = 0;
00597
00598 if (flow_control) {
00599 rc |= USART_MF_XONXOFF;
00600 } else {
00601 rc &= ~USART_MF_XONXOFF;
00602 }
00603
00604 return rc;
00605 }
00606
00617 static int GbaUartSetFlowControl(u_long flags)
00618 {
00619
00620
00621
00622 if (flags & USART_MF_XONXOFF) {
00623 if (flow_control == 0) {
00624 NutEnterCritical();
00625 flow_control = 1 | XOFF_SENT;
00626 NutExitCritical();
00627 }
00628 } else {
00629 NutEnterCritical();
00630 flow_control = 0;
00631 NutExitCritical();
00632 }
00633
00634
00635
00636
00637 if (GbaUartGetFlowControl() != flags) {
00638 return -1;
00639 }
00640 return 0;
00641 }
00642
00650 static void GbaUartTxStart(void)
00651 {
00652 RINGBUF *rbf = &dcb_uart.dcb_tx_rbf;
00653 register u_char *cp = rbf->rbf_tail;
00654
00655 NutEnterCritical();
00656 if(tx_stop) {
00657 if (rbf->rbf_cnt) {
00658 rbf->rbf_cnt--;
00659 outw(REG_SIODATA8, *cp);
00660 if (++cp == rbf->rbf_last) {
00661 cp = rbf->rbf_start;
00662 }
00663 rbf->rbf_tail = cp;
00664 tx_stop = 0;
00665 }
00666 }
00667 outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_SEND_ENA);
00668 NutExitCritical();
00669 }
00670
00679 static void GbaUartRxStart(void)
00680 {
00681
00682
00683
00684 NutEnterCritical();
00685 if (flow_control && (flow_control & XOFF_SENT) != 0) {
00686 if (inw(REG_SIOCNT) & SIO_TX_FULL) {
00687 flow_control |= XON_PENDING;
00688 } else {
00689 outw(REG_SIODATA8, ASCII_XON);
00690 flow_control &= ~XON_PENDING;
00691 }
00692 flow_control &= ~(XOFF_SENT | XOFF_PENDING);
00693 }
00694 outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_RECV_ENA);
00695 NutExitCritical();
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static int GbaUartInit(void)
00707 {
00708 int rc;
00709
00710
00711
00712
00713
00714 outw(REG_RCNT, 0x8032);
00715 NutSleep(100);
00716
00717
00718 outw(REG_IME, 0);
00719
00720
00721 if((rc = NutRegisterIrqHandler(&sig_SIO, GbaUartIsr, &dcb_uart)) == 0) {
00722
00723
00724 outw(REG_RCNT, 0x0000);
00725
00726
00727 outw(REG_SIOCNT, SIO_IRQ_ENA | SIO_MODE_UART | SIO_DATA_8BIT | SIO_BAUD_38400);
00728
00729
00730 outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_RX_EMPTY | SIO_TX_FULL);
00731
00732
00733
00734
00735
00736 outw(REG_IE, inw(REG_IE) | INT_SIO);
00737 }
00738
00739 printf("I[%04X]", inw(REG_SIOCNT));
00740
00741
00742 outw(REG_IME, 1);
00743
00744 return rc;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 static int GbaUartDeinit(void)
00756 {
00757
00758 NutRegisterIrqHandler(&sig_SIO, 0, 0);
00759
00760 return 0;
00761 }
00762
00763 #if 1
00764
00767 static USARTDCB dcb_uart = {
00768 0,
00769 0,
00770 0,
00771 0,
00772 {0, 0, 0, 0, 0, 0, 0, 0},
00773 {0, 0, 0, 0, 0, 0, 0, 0},
00774 0,
00775 GbaUartInit,
00776 GbaUartDeinit,
00777 GbaUartTxStart,
00778 GbaUartRxStart,
00779 GbaUartSetFlowControl,
00780 GbaUartGetFlowControl,
00781 GbaUartSetSpeed,
00782 GbaUartGetSpeed,
00783 GbaUartSetDataBits,
00784 GbaUartGetDataBits,
00785 GbaUartSetParity,
00786 GbaUartGetParity,
00787 GbaUartSetStopBits,
00788 GbaUartGetStopBits,
00789 GbaUartSetStatus,
00790 GbaUartGetStatus,
00791 GbaUartSetClockMode,
00792 GbaUartGetClockMode,
00793 };
00794
00810 NUTDEVICE devUartGba = {
00811 0,
00812 {'u', 'a', 'r', 't', '0', 0, 0, 0, 0},
00813 IFTYP_CHAR,
00814 0,
00815 0,
00816 0,
00817 &dcb_uart,
00818 UsartInit,
00819 UsartIOCtl,
00820 UsartRead,
00821 UsartWrite,
00822 UsartOpen,
00823 UsartClose,
00824 UsartSize
00825 };
00826 #endif
00827