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 #include <cfg/ahdlc.h>
00051
00052 #include <string.h>
00053 #include <stdlib.h>
00054 #include <fcntl.h>
00055
00056 #include <sys/nutconfig.h>
00057 #include <sys/atom.h>
00058 #include <sys/heap.h>
00059 #include <sys/event.h>
00060 #include <sys/timer.h>
00061 #include <sys/thread.h>
00062
00063 #include <dev/irqreg.h>
00064 #include <dev/ppp.h>
00065
00066 #include <netinet/if_ppp.h>
00067 #include <net/ppp.h>
00068 #include <net/if_var.h>
00069
00070 #include <dev/usartat91.h>
00071 #include <dev/at91_ahdlc.h>
00072
00073
00074 #ifndef NUT_AHDLC_RECV_DMA_SIZE
00075 #define NUT_AHDLC_RECV_DMA_SIZE 64
00076 #endif
00077
00078
00079 static unsigned char DMA_RxBuf0[NUT_AHDLC_RECV_DMA_SIZE];
00080
00081 #define UART_RECEIVER_TIMEOUT 32
00082
00083 #define SIG_UART sig_UART1
00084 #define US_ID US1_ID
00085 #define US_GPIO_PINS 0x00000360
00086
00087
00088
00093
00094 static AHDLCDCB dcb_ahdlc;
00095
00102 NUTDEVICE devAhdlc1 = {
00103 0,
00104 {'u', 'a', 'r', 't', '1', 0, 0, 0, 0},
00105 IFTYP_CHAR,
00106 1,
00107 0,
00108 0,
00109 &dcb_ahdlc,
00110 AhdlcAt91Init,
00111 AhdlcAt91IOCtl,
00112 AhdlcAt91Read,
00113 AhdlcAt91Write,
00114 AhdlcAt91Open,
00115 AhdlcAt91Close,
00116 0
00117 };
00118
00119
00120
00121
00122
00123 static prog_char fcstab[512] = {
00124 0x00, 0x00, 0x11, 0x89, 0x23, 0x12, 0x32, 0x9b, 0x46, 0x24, 0x57, 0xad, 0x65, 0x36, 0x74, 0xbf,
00125 0x8c, 0x48, 0x9d, 0xc1, 0xaf, 0x5a, 0xbe, 0xd3, 0xca, 0x6c, 0xdb, 0xe5, 0xe9, 0x7e, 0xf8, 0xf7,
00126 0x10, 0x81, 0x01, 0x08, 0x33, 0x93, 0x22, 0x1a, 0x56, 0xa5, 0x47, 0x2c, 0x75, 0xb7, 0x64, 0x3e,
00127 0x9c, 0xc9, 0x8d, 0x40, 0xbf, 0xdb, 0xae, 0x52, 0xda, 0xed, 0xcb, 0x64, 0xf9, 0xff, 0xe8, 0x76,
00128 0x21, 0x02, 0x30, 0x8b, 0x02, 0x10, 0x13, 0x99, 0x67, 0x26, 0x76, 0xaf, 0x44, 0x34, 0x55, 0xbd,
00129 0xad, 0x4a, 0xbc, 0xc3, 0x8e, 0x58, 0x9f, 0xd1, 0xeb, 0x6e, 0xfa, 0xe7, 0xc8, 0x7c, 0xd9, 0xf5,
00130 0x31, 0x83, 0x20, 0x0a, 0x12, 0x91, 0x03, 0x18, 0x77, 0xa7, 0x66, 0x2e, 0x54, 0xb5, 0x45, 0x3c,
00131 0xbd, 0xcb, 0xac, 0x42, 0x9e, 0xd9, 0x8f, 0x50, 0xfb, 0xef, 0xea, 0x66, 0xd8, 0xfd, 0xc9, 0x74,
00132
00133 0x42, 0x04, 0x53, 0x8d, 0x61, 0x16, 0x70, 0x9f, 0x04, 0x20, 0x15, 0xa9, 0x27, 0x32, 0x36, 0xbb,
00134 0xce, 0x4c, 0xdf, 0xc5, 0xed, 0x5e, 0xfc, 0xd7, 0x88, 0x68, 0x99, 0xe1, 0xab, 0x7a, 0xba, 0xf3,
00135 0x52, 0x85, 0x43, 0x0c, 0x71, 0x97, 0x60, 0x1e, 0x14, 0xa1, 0x05, 0x28, 0x37, 0xb3, 0x26, 0x3a,
00136 0xde, 0xcd, 0xcf, 0x44, 0xfd, 0xdf, 0xec, 0x56, 0x98, 0xe9, 0x89, 0x60, 0xbb, 0xfb, 0xaa, 0x72,
00137 0x63, 0x06, 0x72, 0x8f, 0x40, 0x14, 0x51, 0x9d, 0x25, 0x22, 0x34, 0xab, 0x06, 0x30, 0x17, 0xb9,
00138 0xef, 0x4e, 0xfe, 0xc7, 0xcc, 0x5c, 0xdd, 0xd5, 0xa9, 0x6a, 0xb8, 0xe3, 0x8a, 0x78, 0x9b, 0xf1,
00139 0x73, 0x87, 0x62, 0x0e, 0x50, 0x95, 0x41, 0x1c, 0x35, 0xa3, 0x24, 0x2a, 0x16, 0xb1, 0x07, 0x38,
00140 0xff, 0xcf, 0xee, 0x46, 0xdc, 0xdd, 0xcd, 0x54, 0xb9, 0xeb, 0xa8, 0x62, 0x9a, 0xf9, 0x8b, 0x70,
00141
00142 0x84, 0x08, 0x95, 0x81, 0xa7, 0x1a, 0xb6, 0x93, 0xc2, 0x2c, 0xd3, 0xa5, 0xe1, 0x3e, 0xf0, 0xb7,
00143 0x08, 0x40, 0x19, 0xc9, 0x2b, 0x52, 0x3a, 0xdb, 0x4e, 0x64, 0x5f, 0xed, 0x6d, 0x76, 0x7c, 0xff,
00144 0x94, 0x89, 0x85, 0x00, 0xb7, 0x9b, 0xa6, 0x12, 0xd2, 0xad, 0xc3, 0x24, 0xf1, 0xbf, 0xe0, 0x36,
00145 0x18, 0xc1, 0x09, 0x48, 0x3b, 0xd3, 0x2a, 0x5a, 0x5e, 0xe5, 0x4f, 0x6c, 0x7d, 0xf7, 0x6c, 0x7e,
00146 0xa5, 0x0a, 0xb4, 0x83, 0x86, 0x18, 0x97, 0x91, 0xe3, 0x2e, 0xf2, 0xa7, 0xc0, 0x3c, 0xd1, 0xb5,
00147 0x29, 0x42, 0x38, 0xcb, 0x0a, 0x50, 0x1b, 0xd9, 0x6f, 0x66, 0x7e, 0xef, 0x4c, 0x74, 0x5d, 0xfd,
00148 0xb5, 0x8b, 0xa4, 0x02, 0x96, 0x99, 0x87, 0x10, 0xf3, 0xaf, 0xe2, 0x26, 0xd0, 0xbd, 0xc1, 0x34,
00149 0x39, 0xc3, 0x28, 0x4a, 0x1a, 0xd1, 0x0b, 0x58, 0x7f, 0xe7, 0x6e, 0x6e, 0x5c, 0xf5, 0x4d, 0x7c,
00150
00151 0xc6, 0x0c, 0xd7, 0x85, 0xe5, 0x1e, 0xf4, 0x97, 0x80, 0x28, 0x91, 0xa1, 0xa3, 0x3a, 0xb2, 0xb3,
00152 0x4a, 0x44, 0x5b, 0xcd, 0x69, 0x56, 0x78, 0xdf, 0x0c, 0x60, 0x1d, 0xe9, 0x2f, 0x72, 0x3e, 0xfb,
00153 0xd6, 0x8d, 0xc7, 0x04, 0xf5, 0x9f, 0xe4, 0x16, 0x90, 0xa9, 0x81, 0x20, 0xb3, 0xbb, 0xa2, 0x32,
00154 0x5a, 0xc5, 0x4b, 0x4c, 0x79, 0xd7, 0x68, 0x5e, 0x1c, 0xe1, 0x0d, 0x68, 0x3f, 0xf3, 0x2e, 0x7a,
00155 0xe7, 0x0e, 0xf6, 0x87, 0xc4, 0x1c, 0xd5, 0x95, 0xa1, 0x2a, 0xb0, 0xa3, 0x82, 0x38, 0x93, 0xb1,
00156 0x6b, 0x46, 0x7a, 0xcf, 0x48, 0x54, 0x59, 0xdd, 0x2d, 0x62, 0x3c, 0xeb, 0x0e, 0x70, 0x1f, 0xf9,
00157 0xf7, 0x8f, 0xe6, 0x06, 0xd4, 0x9d, 0xc5, 0x14, 0xb1, 0xab, 0xa0, 0x22, 0x92, 0xb9, 0x83, 0x30,
00158 0x7b, 0xc7, 0x6a, 0x4e, 0x58, 0xd5, 0x49, 0x5c, 0x3d, 0xe3, 0x2c, 0x6a, 0x1e, 0xf1, 0x0f, 0x78
00159 };
00160
00164 #define IN_ACC_MAP(c, m) (( ((u_char) (c)) < 0x20) && ((m) & (1UL << (c))) != 0)
00165
00166 #ifndef NUT_THREAD_AHDLCRXSTACK
00167 #define NUT_THREAD_AHDLCRXSTACK 2048
00168 #endif
00169
00170
00171
00177 static void At91UsartInterrupt(void *arg)
00178 {
00179 AHDLCDCB *dcb = arg;
00180 u_short count, i;
00181 ureg_t csr = inr(US1_CSR);
00182
00183 if (csr & (US_ENDRX | US_RXBUFF | US_TIMEOUT)) {
00184
00185
00186 if (csr & US_TIMEOUT) {
00187 count = NUT_AHDLC_RECV_DMA_SIZE - inr(USART1_BASE + PERIPH_RCR_OFF);
00188 } else {
00189 count = NUT_AHDLC_RECV_DMA_SIZE;
00190 }
00191
00192 for (i = 0; i < count; i++) {
00193 dcb->dcb_rx_buf[dcb->dcb_rx_idx] = DMA_RxBuf0[i];
00194 dcb->dcb_rx_idx++;
00195 }
00196
00197 outr(USART1_BASE + PERIPH_RPR_OFF, (unsigned int) DMA_RxBuf0);
00198 outr(USART1_BASE + PERIPH_RCR_OFF, NUT_AHDLC_RECV_DMA_SIZE);
00199 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
00200 outr(US1_CR, inr(US1_CR) | US_STTTO);
00201 NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00202 }
00203
00204 if (csr & US_TXRDY) {
00205 if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00206 outr(US1_THR, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00207 dcb->dcb_tx_idx++;
00208 } else {
00209 outr(US1_IDR, US_TXRDY);
00210 NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00211 }
00212 }
00213
00214 }
00215
00216
00217
00218
00219
00220
00221 static int SendRawByte(AHDLCDCB * dcb, u_char ch, u_char flush)
00222 {
00223
00224
00225
00226
00227 while ((u_char) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00228 if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
00229 break;
00230 }
00231
00232
00233
00234
00235 if ((u_char) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00236 return -1;
00237 }
00238
00239
00240
00241
00242
00243 dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
00244 dcb->dcb_wr_idx++;
00245
00246
00247
00248
00249
00250 if (flush || (u_char) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00251
00252 NutEnterCritical();
00253
00254 outr(US1_IER, US_TXRDY);
00255
00256 NutExitCritical();
00257 }
00258 return 0;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 static int SendHdlcData(AHDLCDCB * dcb, CONST u_char * data, u_short len, u_short * txfcs)
00268 {
00269 u_short tbx;
00270 u_short fcs;
00271
00272 if (txfcs)
00273 fcs = *txfcs;
00274 else
00275 fcs = 0;
00276
00277 while (len) {
00278 tbx = (u_short) ((u_char) fcs ^ *data) << 1;
00279 fcs >>= 8;
00280 fcs ^= ((u_short) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00281
00282 if (IN_ACC_MAP(*data, dcb->dcb_tx_accm) || *data == AHDLC_FLAG || *data == AHDLC_ESCAPE) {
00283 if (SendRawByte(dcb, AHDLC_ESCAPE, 0)) {
00284 return -1;
00285 }
00286 if (SendRawByte(dcb, *data ^ AHDLC_TRANS, 0)) {
00287 return -1;
00288 }
00289 } else if (SendRawByte(dcb, *data, 0)) {
00290 return -1;
00291 }
00292 data++;
00293 len--;
00294 }
00295 if (txfcs)
00296 *txfcs = fcs;
00297
00298 return 0;
00299 }
00300
00311 int AhdlcOutput(NUTDEVICE * dev, NETBUF * nb)
00312 {
00313 u_short txfcs;
00314 AHDLCDCB *dcb = dev->dev_dcb;
00315 u_short sz;
00316
00317
00318
00319
00320
00321 if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00322 return 0;
00323 }
00324
00325
00326
00327
00328
00329 sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00330
00331 if (sz > dcb->dcb_tx_mru) {
00332 return -1;
00333 }
00334
00335
00336
00337
00338 SendRawByte(dcb, AHDLC_FLAG, 0);
00339
00340
00341 txfcs = AHDLC_INITFCS;
00342 if (SendHdlcData(dcb, nb->nb_dl.vp, nb->nb_dl.sz, &txfcs))
00343 return -1;
00344 if (SendHdlcData(dcb, nb->nb_nw.vp, nb->nb_nw.sz, &txfcs))
00345 return -1;
00346 if (SendHdlcData(dcb, nb->nb_tp.vp, nb->nb_tp.sz, &txfcs))
00347 return -1;
00348 if (SendHdlcData(dcb, nb->nb_ap.vp, nb->nb_ap.sz, &txfcs))
00349 return -1;
00350
00351
00352 txfcs ^= 0xffff;
00353 if (SendHdlcData(dcb, (u_char *) & txfcs, 2, 0))
00354 return -1;
00355
00356 SendRawByte(dcb, AHDLC_FLAG, 1);
00357
00358 return 0;
00359 }
00360
00367 THREAD(AhdlcRx, arg)
00368 {
00369 NUTDEVICE *dev = arg;
00370 NUTDEVICE *netdev;
00371 AHDLCDCB *dcb = dev->dev_dcb;
00372 IFNET *ifn;
00373 NETBUF *nb;
00374 u_char *rxbuf;
00375 u_char *rxptr;
00376 u_short rxcnt;
00377 u_char ch;
00378 u_short tbx;
00379 u_char inframe;
00380 u_char escaped;
00381 u_short rxfcs;
00382
00383 NutThreadSetPriority(9);
00384 for (;;) {
00385
00386
00387
00388 rxptr = 0;
00389 rxcnt = 0;
00390 escaped = 0;
00391 rxfcs = AHDLC_INITFCS;
00392 inframe = 0;
00393
00394 for (;;) {
00395
00396
00397
00398
00399
00400
00401
00402 while ((netdev = dev->dev_icb) == 0) {
00403 if (NutEventWait(&dcb->dcb_mf_evt, 1000) == 0) {
00404 NutSleep(100);
00405 }
00406 }
00407 ifn = netdev->dev_icb;
00408 dcb->dcb_rtimeout = 1000;
00409 inframe = 0;
00410
00411
00412
00413
00414
00415
00416 if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
00417 break;
00418 }
00419 NutSleep(1000);
00420 }
00421
00422
00423
00424
00425 ifn->if_send = AhdlcOutput;
00426 netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00427
00428 for (;;) {
00429
00430
00431
00432
00433 while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00434 if (dev->dev_icb == 0)
00435 break;
00436
00437 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00438 continue;
00439 }
00440 }
00441
00442
00443
00444
00445 if (dev->dev_icb == 0)
00446 break;
00447
00448
00449
00450
00451
00452 if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00453
00454
00455
00456
00457
00458 NutSleep(100);
00459 continue;
00460 }
00461
00462
00463
00464
00465 ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00466
00467 if (inframe) {
00468 if (ch != AHDLC_FLAG) {
00469 if (ch == AHDLC_ESCAPE) {
00470 escaped = 1;
00471 continue;
00472 }
00473 if (escaped) {
00474 ch ^= AHDLC_TRANS;
00475 escaped = 0;
00476 }
00477
00478
00479
00480
00481
00482
00483 if (rxcnt++ < dcb->dcb_rx_mru) {
00484
00485 tbx = (u_short) ((u_char) rxfcs ^ ch) << 1;
00486 rxfcs >>= 8;
00487 rxfcs ^= ((u_short) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00488 *rxptr++ = ch;
00489 } else
00490 inframe = 0;
00491 continue;
00492 }
00493
00494 if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
00495
00496
00497
00498
00499 rxcnt -= 2;
00500 if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00501 memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00502 (*ifn->if_recv) (netdev, nb);
00503 }
00504 }
00505 }
00506
00507
00508
00509
00510 if (ch == AHDLC_FLAG) {
00511 inframe = 1;
00512 escaped = 0;
00513 rxptr = rxbuf;
00514 rxcnt = 0;
00515 rxfcs = AHDLC_INITFCS;
00516 }
00517 }
00518
00519
00520
00521 netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00522
00523
00524 if (rxbuf) {
00525 NutHeapFree(rxbuf);
00526 rxbuf = 0;
00527 }
00528 }
00529 }
00530
00531
00532
00533
00534
00535
00536 static int AhdlcAt91GetStatus(NUTDEVICE * dev, u_long * status)
00537 {
00538 AHDLCDCB *dcb = dev->dev_dcb;
00539
00540
00541 *status = 0;
00542
00543 #ifdef __AVR_ENHANCED__
00544 if (dev->dev_base) {
00545 #ifdef UART1_CTS_BIT
00546 if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00547 *status |= UART_CTSDISABLED;
00548 else
00549 *status |= UART_CTSENABLED;
00550 #endif
00551 #ifdef UART1_RTS_BIT
00552 if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00553 *status |= UART_RTSDISABLED;
00554 else
00555 *status |= UART_RTSENABLED;
00556 #endif
00557 #ifdef UART1_DTR_BIT
00558 if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00559 *status |= UART_DTRDISABLED;
00560 else
00561 *status |= UART_DTRENABLED;
00562 #endif
00563 us = inp(UCSR1A);
00564 } else
00565 #endif
00566 {
00567 #ifdef UART0_CTS_BIT
00568 if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00569 *status |= UART_CTSDISABLED;
00570 else
00571 *status |= UART_CTSENABLED;
00572 #endif
00573 #ifdef UART0_RTS_BIT
00574 if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00575 *status |= UART_RTSDISABLED;
00576 else
00577 *status |= UART_RTSENABLED;
00578 #endif
00579 #ifdef UART0_DTR_BIT
00580 if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00581 *status |= UART_DTRDISABLED;
00582 else
00583 *status |= UART_DTRENABLED;
00584 #endif
00585
00586 }
00587
00588
00589
00590
00591 if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00592 *status |= UART_TXBUFFEREMPTY;
00593 if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00594 *status |= UART_RXBUFFEREMPTY;
00595
00596 return 0;
00597 }
00598
00599
00600
00601
00602
00603
00604 static int AhdlcAt91SetStatus(NUTDEVICE * dev, u_long status)
00605 {
00606
00607 #ifdef __AVR_ENHANCED__
00608 if (dev->dev_base) {
00609 #ifdef UART1_RTS_BIT
00610 if (status & UART_RTSDISABLED)
00611 sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00612 else if (status & UART_RTSENABLED)
00613 cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00614 #endif
00615 #ifdef UART1_DTR_BIT
00616 if (status & UART_DTRDISABLED)
00617 sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00618 else if (status & UART_DTRENABLED)
00619 cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00620 #endif
00621 } else
00622 #endif
00623 {
00624 #ifdef UART0_RTS_BIT
00625 if (status & UART_RTSDISABLED)
00626 sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00627 else if (status & UART_RTSENABLED)
00628 cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00629 #endif
00630 #ifdef UART0_DTR_BIT
00631 if (status & UART_DTRDISABLED)
00632 sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00633 else if (status & UART_DTRENABLED)
00634 cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00635 #endif
00636 }
00637 return 0;
00638 }
00639
00640
00641
00642
00643 static void AhdlcAt91Enable(u_short base)
00644 {
00645
00646 NutEnterCritical();
00647
00648 outr(US1_RTOR, UART_RECEIVER_TIMEOUT);
00649 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
00650 outr(US1_CR, US_TXEN | US_RXEN | US_STTTO);
00651
00652
00653 outr(US1_IER, US_ENDRX | US_RXBUFF | US_TIMEOUT);
00654
00655 NutIrqEnable(&SIG_UART);
00656
00657 NutExitCritical();
00658 }
00659
00660
00661
00662
00663
00664 static void AhdlcAt91Disable(u_short base)
00665 {
00666
00667 NutEnterCritical();
00668
00669 NutIrqDisable(&SIG_UART);
00670
00671 outr(US1_IDR, -1);
00672 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTDIS);
00673
00674 NutExitCritical();
00675
00676
00677
00678 NutDelay(10);
00679
00680
00681
00682
00683 outr(US1_CR, US_RXDIS | US_TXDIS);
00684 }
00685
00723 int AhdlcAt91IOCtl(NUTDEVICE * dev, int req, void *conf)
00724 {
00725 int rc = 0;
00726 AHDLCDCB *dcb;
00727 void **ppv = (void **) conf;
00728 u_long *lvp = (u_long *) conf;
00729 u_char bv;
00730 u_char devnum;
00731 ureg_t cs;
00732
00733 if (dev == 0) {
00734 dev = &devUsartAt910;
00735 }
00736
00737 devnum = dev->dev_base;
00738 dcb = dev->dev_dcb;
00739
00740 switch (req) {
00741
00742 case UART_SETSPEED:
00743
00744 AhdlcAt91Disable(dcb->dcb_base);
00745 #if defined(AT91_PLL_MAINCK)
00746 outr(USART1_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (*lvp)) + 1) / 2);
00747 #else
00748 outr(USART1_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (*lvp)) + 1) / 2);
00749 #endif
00750 AhdlcAt91Enable(dcb->dcb_base);
00751 break;
00752
00753 case UART_GETSPEED:
00754 cs = inr(USART1_BASE + US_MR_OFF);
00755 u_long clk;
00756 #if defined(AT91_PLL_MAINCK)
00757 clk = At91GetMasterClock();
00758 #else
00759 clk = NutGetCpuClock();
00760 #endif
00761 if ((cs & US_CLKS) == US_CLKS_MCK8) {
00762 clk /= 8;
00763 } else if ((cs & US_CLKS) != US_CLKS_MCK) {
00764 clk = 0;
00765 }
00766 *lvp = (clk / (16UL * (inr(USART1_BASE + US_BRGR_OFF) & 0xFFFF)));
00767 break;
00768
00769 case UART_GETSTATUS:
00770 AhdlcAt91GetStatus(dev, lvp);
00771 break;
00772 case UART_SETSTATUS:
00773 AhdlcAt91SetStatus(dev, *lvp);
00774 break;
00775
00776 case UART_SETREADTIMEOUT:
00777 dcb->dcb_rtimeout = *lvp;
00778 break;
00779 case UART_GETREADTIMEOUT:
00780 *lvp = dcb->dcb_rtimeout;
00781 break;
00782
00783 case UART_SETWRITETIMEOUT:
00784 dcb->dcb_wtimeout = *lvp;
00785 break;
00786 case UART_GETWRITETIMEOUT:
00787 *lvp = dcb->dcb_wtimeout;
00788 break;
00789
00790 case UART_SETLOCALECHO:
00791 bv = (u_char) (*lvp);
00792 if (bv)
00793 dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00794 else
00795 dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00796 break;
00797 case UART_GETLOCALECHO:
00798 if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
00799 *lvp = 1;
00800 else
00801 *lvp = 0;
00802 break;
00803
00804 case UART_SETFLOWCONTROL:
00805 bv = (u_char) (*lvp);
00806 if (bv)
00807 dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00808 else
00809 dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00810 break;
00811 case UART_GETFLOWCONTROL:
00812 break;
00813
00814 case UART_SETRAWMODE:
00815 bv = (u_char) (*lvp);
00816 if (bv)
00817 dcb->dcb_modeflags |= UART_MF_RAWMODE;
00818 else
00819 dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
00820 break;
00821
00822 case UART_GETRAWMODE:
00823 if (dcb->dcb_modeflags & UART_MF_RAWMODE)
00824 *lvp = 1;
00825 else
00826 *lvp = 0;
00827 break;
00828
00829 case HDLC_SETIFNET:
00830 if (ppv && (*ppv != 0)) {
00831 dev->dev_icb = *ppv;
00832 dev->dev_type = IFTYP_NET;
00833 NutEventPost(&dcb->dcb_mf_evt);
00834 } else {
00835
00836 dev->dev_type = IFTYP_CHAR;
00837
00838 if (dev->dev_icb != 0) {
00839 dev->dev_icb = 0;
00840
00841
00842
00843
00844 NutEventPost(&dcb->dcb_rx_rdy);
00845 }
00846 }
00847 break;
00848
00849 case HDLC_GETIFNET:
00850 *ppv = dev->dev_icb;
00851 break;
00852
00853 default:
00854 rc = -1;
00855 break;
00856 }
00857 return rc;
00858 }
00859
00860
00873 int AhdlcAt91Init(NUTDEVICE * dev)
00874 {
00875 int rc = 0;
00876 AHDLCDCB *dcb;
00877
00878
00879
00880 AhdlcAt91Disable(dev->dev_base);
00881
00882
00883 dcb = dev->dev_dcb;
00884 memset(dcb, 0, sizeof(AHDLCDCB));
00885 dcb->dcb_base = dev->dev_base;
00886 dcb->dcb_rx_buf = NutHeapAlloc(256);
00887 dcb->dcb_tx_buf = NutHeapAlloc(256);
00888 dcb->dcb_rx_mru = 1500;
00889 dcb->dcb_tx_mru = 1500;
00890 dcb->dcb_tx_accm = 0xFFFFFFFF;
00891
00892
00893 if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, dcb)) {
00894 return -1;
00895 }
00896
00897 outr(PMC_PCER, _BV(US1_ID));
00898
00899 outr(PIOA_PDR, US_GPIO_PINS);
00900
00901
00902 outr(US1_CR, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
00903
00904 outr(US1_IDR, 0xFFFFFFFF);
00905
00906 #if defined (US_RCR_OFF)
00907 outr(US1_RCR, 0);
00908 #endif
00909 #if defined (US_TCR_OFF)
00910 outr(US1_TCR, 0);
00911 #endif
00912
00913 #if defined(AT91_PLL_MAINCK)
00914 outr(US1_BRGR, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
00915 #else
00916 outr(US1_BRGR, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
00917 #endif
00918
00919 outr(US1_MR, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1 | US_MODE_HWHANDSHAKE);
00920
00921
00922 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTDIS);
00923 outr(USART1_BASE + PERIPH_RPR_OFF, (unsigned int) DMA_RxBuf0);
00924 outr(USART1_BASE + PERIPH_RCR_OFF, NUT_AHDLC_RECV_DMA_SIZE);
00925 outr(USART1_BASE + PERIPH_RNPR_OFF, 0);
00926 outr(USART1_BASE + PERIPH_RNCR_OFF, 0);
00927
00928
00929
00930
00931
00932 if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, NUT_THREAD_AHDLCRXSTACK)) {
00933
00934 return 0;
00935 }
00936
00937
00938 if (dcb->dcb_rx_buf)
00939 NutHeapFree((void *) dcb->dcb_rx_buf);
00940 if (dcb->dcb_tx_buf)
00941 NutHeapFree((void *) dcb->dcb_tx_buf);
00942
00943 return -1;
00944 }
00945
00946
00947
00948
00975 int AhdlcAt91Read(NUTFILE * fp, void *buffer, int size)
00976 {
00977 int rc = 0;
00978 AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
00979 u_char *cp = buffer;
00980
00981
00982
00983
00984 if (buffer) {
00985 while (rc < size) {
00986 if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
00987 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00988 rc++;
00989 } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
00990 break;
00991 }
00992 }
00993
00994
00995
00996
00997 else
00998 dcb->dcb_rd_idx = dcb->dcb_rx_idx;
00999
01000 return rc;
01001 }
01002
01015 int AhdlcAt91Put(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01016 {
01017 int rc = 0;
01018 AHDLCDCB *dcb = dev->dev_dcb;
01019 CONST u_char *cp = buffer;
01020
01021
01022
01023
01024 if (buffer) {
01025 while (rc < len) {
01026 if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01027 break;
01028 cp++;
01029 rc++;
01030 }
01031 }
01032
01033
01034
01035
01036 else {
01037
01038 NutEnterCritical();
01039
01040 outr(US1_IER, US_TXRDY);
01041
01042 NutExitCritical();
01043 }
01044 return rc;
01045 }
01046
01066 int AhdlcAt91Write(NUTFILE * fp, CONST void *buffer, int len)
01067 {
01068 return AhdlcAt91Put(fp->nf_dev, buffer, len, 0);
01069 }
01070
01092 int AhdlcAt91Write_P(NUTFILE * fp, PGM_P buffer, int len)
01093 {
01094 return AhdlcAt91Put(fp->nf_dev, (CONST char *) buffer, len, 1);
01095 }
01096
01113 NUTFILE *AhdlcAt91Open(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01114 {
01115 NUTFILE *fp;
01116
01117 if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01118 return NUTFILE_EOF;
01119
01120 fp->nf_next = 0;
01121 fp->nf_dev = dev;
01122 fp->nf_fcb = 0;
01123
01124 outr(US1_RTOR, UART_RECEIVER_TIMEOUT);
01125 outr(USART1_BASE + PERIPH_PTCR_OFF, PDC_RXTEN);
01126 outr(US1_CR, US_TXEN | US_RXEN | US_STTTO);
01127
01128
01129 outr(US1_IER, US_ENDRX | US_RXBUFF | US_TIMEOUT);
01130
01131 NutEnterCritical();
01132
01133 NutIrqEnable(&SIG_UART);
01134
01135 NutExitCritical();
01136
01137 return fp;
01138 }
01139
01153 int AhdlcAt91Close(NUTFILE * fp)
01154 {
01155 if (fp && fp != NUTFILE_EOF) {
01156 NutHeapFree(fp);
01157 return 0;
01158 }
01159 return -1;
01160 }
01161