ahdlcavr.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2004 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.5  2009/02/06 15:37:39  haraldkipp
00037  * Added stack space multiplier and addend. Adjusted stack space.
00038  *
00039  * Revision 1.4  2008/08/11 06:59:14  haraldkipp
00040  * BSD types replaced by stdint types (feature request #1282721).
00041  *
00042  * Revision 1.3  2006/10/08 16:48:07  haraldkipp
00043  * Documentation fixed
00044  *
00045  * Revision 1.2  2005/08/02 17:46:45  haraldkipp
00046  * Major API documentation update.
00047  *
00048  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00049  * Moved from dev.
00050  *
00051  * Revision 1.10  2005/06/26 12:40:59  chaac
00052  * Added support for raw mode to AHDLC driver.
00053  *
00054  * Revision 1.9  2005/05/27 14:43:28  chaac
00055  * Fixed bugs on closing AHDLC sessions. Fixed AHDLC ioctl handling. Not all
00056  * messages were handled correctly  and fixed possible problem of reading memory
00057  * from address zero.
00058  *
00059  * Revision 1.8  2005/04/05 17:44:56  haraldkipp
00060  * Made stack space configurable.
00061  *
00062  * Revision 1.7  2005/02/10 07:06:17  hwmaier
00063  * Changes to incorporate support for AT90CAN128 CPU
00064  *
00065  * Revision 1.6  2005/01/24 21:11:48  freckle
00066  * renamed NutEventPostFromIRQ into NutEventPostFromIrq
00067  *
00068  * Revision 1.5  2005/01/21 16:49:45  freckle
00069  * Seperated calls to NutEventPostAsync between Threads and IRQs
00070  *
00071  * Revision 1.4  2004/12/16 08:40:35  haraldkipp
00072  * Late increment fixes ICCAVR bug.
00073  *
00074  * Revision 1.3  2004/03/18 14:05:20  haraldkipp
00075  * Comments updated
00076  *
00077  * Revision 1.2  2004/03/16 16:48:27  haraldkipp
00078  * Added Jan Dubiec's H8/300 port.
00079  *
00080  * Revision 1.1  2004/03/08 11:16:54  haraldkipp
00081  * Asynchronous HDLC driver added
00082  *
00083  */
00084 
00085 #include <cfg/ahdlc.h>
00086 #include <cfg/arch/avr.h>
00087 
00088 #include <string.h>
00089 #include <stdlib.h>
00090 
00091 #include <sys/atom.h>
00092 #include <sys/heap.h>
00093 #include <sys/event.h>
00094 #include <sys/timer.h>
00095 #include <sys/thread.h>
00096 
00097 #include <dev/irqreg.h>
00098 #include <dev/uartavr.h>
00099 
00100 #include <fcntl.h>
00101 
00102 #include <dev/ppp.h>
00103 #include <dev/ahdlcavr.h>
00104 
00105 #include <stdio.h>
00106 
00111 
00117 #ifdef UART0_RTS_BIT
00118 
00119 #if (UART0_RTS_AVRPORT == AVRPORTB)
00120 #define UART0_RTS_PORT  PORTB
00121 #define UART0_RTS_DDR   DDRB
00122 
00123 #elif (UART0_RTS_AVRPORT == AVRPORTD)
00124 #define UART0_RTS_PORT  PORTD
00125 #define UART0_RTS_DDR   DDRD
00126 
00127 #elif (UART0_RTS_AVRPORT == AVRPORTE)
00128 #define UART0_RTS_PORT  PORTE
00129 #define UART0_RTS_DDR   DDRE
00130 
00131 #elif (UART0_RTS_AVRPORT == AVRPORTF)
00132 #define UART0_RTS_PORT  PORTF
00133 #define UART0_RTS_DDR   DDRF
00134 
00135 #elif (UART0_RTS_AVRPORT == AVRPORTG)
00136 #define UART0_RTS_PORT  PORTG
00137 #define UART0_RTS_DDR   DDRG
00138 
00139 #elif (UART0_RTS_AVRPORT == AVRPORTH)
00140 #define UART0_RTS_PORT  PORTH
00141 #define UART0_RTS_DDR   DDRH
00142 
00143 #endif
00144 
00145 #endif /* UART0_RTS_BIT */
00146 
00147 #ifdef UART0_DTR_BIT
00148 
00149 #if (UART0_DTR_AVRPORT == AVRPORTB)
00150 #define UART0_DTR_PORT  PORTB
00151 #define UART0_DTR_DDR   DDRB
00152 
00153 #elif (UART0_DTR_AVRPORT == AVRPORTD)
00154 #define UART0_DTR_PORT  PORTD
00155 #define UART0_DTR_DDR   DDRD
00156 
00157 #elif (UART0_DTR_AVRPORT == AVRPORTE)
00158 #define UART0_DTR_PORT  PORTE
00159 #define UART0_DTR_DDR   DDRE
00160 
00161 #elif (UART0_DTR_AVRPORT == AVRPORTF)
00162 #define UART0_DTR_PORT  PORTF
00163 #define UART0_DTR_DDR   DDRF
00164 
00165 #elif (UART0_DTR_AVRPORT == AVRPORTG)
00166 #define UART0_DTR_PORT  PORTG
00167 #define UART0_DTR_DDR   DDRG
00168 
00169 #elif (UART0_DTR_AVRPORT == AVRPORTH)
00170 #define UART0_DTR_PORT  PORTH
00171 #define UART0_DTR_DDR   DDRH
00172 
00173 #endif
00174 
00175 #endif /* UART0_DTR_BIT */
00176 
00182 #ifdef UART1_RTS_BIT
00183 
00184 #if (UART1_RTS_AVRPORT == AVRPORTB)
00185 #define UART1_RTS_PORT   PORTB
00186 #define UART1_RTS_DDR    DDRB
00187 
00188 #elif (UART1_RTS_AVRPORT == AVRPORTD)
00189 #define UART1_RTS_PORT   PORTD
00190 #define UART1_RTS_DDR    DDRD
00191 
00192 #elif (UART1_RTS_AVRPORT == AVRPORTE)
00193 #define UART1_RTS_PORT   PORTE
00194 #define UART1_RTS_DDR    DDRE
00195 
00196 #elif (UART1_RTS_AVRPORT == AVRPORTF)
00197 #define UART1_RTS_PORT   PORTF
00198 #define UART1_RTS_DDR    DDRF
00199 
00200 #elif (UART1_RTS_AVRPORT == AVRPORTG)
00201 #define UART1_RTS_PORT   PORTG
00202 #define UART1_RTS_DDR    DDRG
00203 
00204 #elif (UART1_RTS_AVRPORT == AVRPORTH)
00205 #define UART1_RTS_PORT   PORTH
00206 #define UART1_RTS_DDR    DDRH
00207 
00208 #endif
00209 
00210 #endif /* UART1_RTS_BIT */
00211 
00212 #ifdef UART1_DTR_BIT
00213 
00214 #if (UART1_DTR_AVRPORT == AVRPORTB)
00215 #define UART1_DTR_PORT  PORTB
00216 #define UART1_DTR_DDR   DDRB
00217 
00218 #elif (UART1_DTR_AVRPORT == AVRPORTD)
00219 #define UART1_DTR_PORT  PORTD
00220 #define UART1_DTR_DDR   DDRD
00221 
00222 #elif (UART1_DTR_AVRPORT == AVRPORTE)
00223 #define UART1_DTR_PORT  PORTE
00224 #define UART1_DTR_DDR   DDRE
00225 
00226 #elif (UART1_DTR_AVRPORT == AVRPORTF)
00227 #define UART1_DTR_PORT  PORTF
00228 #define UART1_DTR_DDR   DDRF
00229 
00230 #elif (UART1_DTR_AVRPORT == AVRPORTG)
00231 #define UART1_DTR_PORT  PORTG
00232 #define UART1_DTR_DDR   DDRG
00233 
00234 #elif (UART1_DTR_AVRPORT == AVRPORTH)
00235 #define UART1_DTR_PORT  PORTH
00236 #define UART1_DTR_DDR   DDRH
00237 
00238 #endif
00239 
00240 #endif /* UART1_DTR_BIT */
00241 
00242 /*
00243  * FCS lookup table located in program memory space.
00244  */
00245 static prog_char fcstab[512] = {
00246     0x00, 0x00, 0x11, 0x89, 0x23, 0x12, 0x32, 0x9b, 0x46, 0x24, 0x57, 0xad, 0x65, 0x36, 0x74, 0xbf,
00247     0x8c, 0x48, 0x9d, 0xc1, 0xaf, 0x5a, 0xbe, 0xd3, 0xca, 0x6c, 0xdb, 0xe5, 0xe9, 0x7e, 0xf8, 0xf7,
00248     0x10, 0x81, 0x01, 0x08, 0x33, 0x93, 0x22, 0x1a, 0x56, 0xa5, 0x47, 0x2c, 0x75, 0xb7, 0x64, 0x3e,
00249     0x9c, 0xc9, 0x8d, 0x40, 0xbf, 0xdb, 0xae, 0x52, 0xda, 0xed, 0xcb, 0x64, 0xf9, 0xff, 0xe8, 0x76,
00250     0x21, 0x02, 0x30, 0x8b, 0x02, 0x10, 0x13, 0x99, 0x67, 0x26, 0x76, 0xaf, 0x44, 0x34, 0x55, 0xbd,
00251     0xad, 0x4a, 0xbc, 0xc3, 0x8e, 0x58, 0x9f, 0xd1, 0xeb, 0x6e, 0xfa, 0xe7, 0xc8, 0x7c, 0xd9, 0xf5,
00252     0x31, 0x83, 0x20, 0x0a, 0x12, 0x91, 0x03, 0x18, 0x77, 0xa7, 0x66, 0x2e, 0x54, 0xb5, 0x45, 0x3c,
00253     0xbd, 0xcb, 0xac, 0x42, 0x9e, 0xd9, 0x8f, 0x50, 0xfb, 0xef, 0xea, 0x66, 0xd8, 0xfd, 0xc9, 0x74,
00254 
00255     0x42, 0x04, 0x53, 0x8d, 0x61, 0x16, 0x70, 0x9f, 0x04, 0x20, 0x15, 0xa9, 0x27, 0x32, 0x36, 0xbb,
00256     0xce, 0x4c, 0xdf, 0xc5, 0xed, 0x5e, 0xfc, 0xd7, 0x88, 0x68, 0x99, 0xe1, 0xab, 0x7a, 0xba, 0xf3,
00257     0x52, 0x85, 0x43, 0x0c, 0x71, 0x97, 0x60, 0x1e, 0x14, 0xa1, 0x05, 0x28, 0x37, 0xb3, 0x26, 0x3a,
00258     0xde, 0xcd, 0xcf, 0x44, 0xfd, 0xdf, 0xec, 0x56, 0x98, 0xe9, 0x89, 0x60, 0xbb, 0xfb, 0xaa, 0x72,
00259     0x63, 0x06, 0x72, 0x8f, 0x40, 0x14, 0x51, 0x9d, 0x25, 0x22, 0x34, 0xab, 0x06, 0x30, 0x17, 0xb9,
00260     0xef, 0x4e, 0xfe, 0xc7, 0xcc, 0x5c, 0xdd, 0xd5, 0xa9, 0x6a, 0xb8, 0xe3, 0x8a, 0x78, 0x9b, 0xf1,
00261     0x73, 0x87, 0x62, 0x0e, 0x50, 0x95, 0x41, 0x1c, 0x35, 0xa3, 0x24, 0x2a, 0x16, 0xb1, 0x07, 0x38,
00262     0xff, 0xcf, 0xee, 0x46, 0xdc, 0xdd, 0xcd, 0x54, 0xb9, 0xeb, 0xa8, 0x62, 0x9a, 0xf9, 0x8b, 0x70,
00263 
00264     0x84, 0x08, 0x95, 0x81, 0xa7, 0x1a, 0xb6, 0x93, 0xc2, 0x2c, 0xd3, 0xa5, 0xe1, 0x3e, 0xf0, 0xb7,
00265     0x08, 0x40, 0x19, 0xc9, 0x2b, 0x52, 0x3a, 0xdb, 0x4e, 0x64, 0x5f, 0xed, 0x6d, 0x76, 0x7c, 0xff,
00266     0x94, 0x89, 0x85, 0x00, 0xb7, 0x9b, 0xa6, 0x12, 0xd2, 0xad, 0xc3, 0x24, 0xf1, 0xbf, 0xe0, 0x36,
00267     0x18, 0xc1, 0x09, 0x48, 0x3b, 0xd3, 0x2a, 0x5a, 0x5e, 0xe5, 0x4f, 0x6c, 0x7d, 0xf7, 0x6c, 0x7e,
00268     0xa5, 0x0a, 0xb4, 0x83, 0x86, 0x18, 0x97, 0x91, 0xe3, 0x2e, 0xf2, 0xa7, 0xc0, 0x3c, 0xd1, 0xb5,
00269     0x29, 0x42, 0x38, 0xcb, 0x0a, 0x50, 0x1b, 0xd9, 0x6f, 0x66, 0x7e, 0xef, 0x4c, 0x74, 0x5d, 0xfd,
00270     0xb5, 0x8b, 0xa4, 0x02, 0x96, 0x99, 0x87, 0x10, 0xf3, 0xaf, 0xe2, 0x26, 0xd0, 0xbd, 0xc1, 0x34,
00271     0x39, 0xc3, 0x28, 0x4a, 0x1a, 0xd1, 0x0b, 0x58, 0x7f, 0xe7, 0x6e, 0x6e, 0x5c, 0xf5, 0x4d, 0x7c,
00272 
00273     0xc6, 0x0c, 0xd7, 0x85, 0xe5, 0x1e, 0xf4, 0x97, 0x80, 0x28, 0x91, 0xa1, 0xa3, 0x3a, 0xb2, 0xb3,
00274     0x4a, 0x44, 0x5b, 0xcd, 0x69, 0x56, 0x78, 0xdf, 0x0c, 0x60, 0x1d, 0xe9, 0x2f, 0x72, 0x3e, 0xfb,
00275     0xd6, 0x8d, 0xc7, 0x04, 0xf5, 0x9f, 0xe4, 0x16, 0x90, 0xa9, 0x81, 0x20, 0xb3, 0xbb, 0xa2, 0x32,
00276     0x5a, 0xc5, 0x4b, 0x4c, 0x79, 0xd7, 0x68, 0x5e, 0x1c, 0xe1, 0x0d, 0x68, 0x3f, 0xf3, 0x2e, 0x7a,
00277     0xe7, 0x0e, 0xf6, 0x87, 0xc4, 0x1c, 0xd5, 0x95, 0xa1, 0x2a, 0xb0, 0xa3, 0x82, 0x38, 0x93, 0xb1,
00278     0x6b, 0x46, 0x7a, 0xcf, 0x48, 0x54, 0x59, 0xdd, 0x2d, 0x62, 0x3c, 0xeb, 0x0e, 0x70, 0x1f, 0xf9,
00279     0xf7, 0x8f, 0xe6, 0x06, 0xd4, 0x9d, 0xc5, 0x14, 0xb1, 0xab, 0xa0, 0x22, 0x92, 0xb9, 0x83, 0x30,
00280     0x7b, 0xc7, 0x6a, 0x4e, 0x58, 0xd5, 0x49, 0x5c, 0x3d, 0xe3, 0x2c, 0x6a, 0x1e, 0xf1, 0x0f, 0x78
00281 };
00282 
00286 #define IN_ACC_MAP(c, m) (( ((uint8_t) (c)) < 0x20)  && ((m) & (1UL << (c))) != 0)
00287 
00288 #ifndef NUT_THREAD_AHDLCRXSTACK
00289 #define NUT_THREAD_AHDLCRXSTACK     512
00290 #endif
00291 
00292 /*
00293  * Handle AVR UART0 transmit complete interrupts.
00294  */
00295 static void Tx0Complete(void *arg)
00296 {
00297     AHDLCDCB *dcb = arg;
00298 
00299     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00300 #ifdef UART0_CTS_BIT
00301         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT)) {
00302             cbi(UCR, UDRIE);
00303             return;
00304         }
00305 #endif
00306         outb(UDR, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00307         dcb->dcb_tx_idx++;
00308     } else {
00309         cbi(UCR, UDRIE);
00310         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00311     }
00312 }
00313 
00314 #ifdef UART0_CTS_BIT
00315 /*
00316  * Handle AVR UART0 transmit handshake interrupts.
00317  */
00318 static void Cts0Interrupt(void *arg)
00319 {
00320     sbi(UCR, UDRIE);
00321 }
00322 #endif
00323 
00324 #ifdef __AVR_ENHANCED__
00325 /*
00326  * Handle AVR UART1 transmit complete interrupts.
00327  */
00328 static void Tx1Complete(void *arg)
00329 {
00330     register AHDLCDCB *dcb = arg;
00331 
00332     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00333 #ifdef UART1_CTS_BIT
00334         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT)) {
00335             cbi(UCSR1B, UDRIE);
00336             return;
00337         }
00338 #endif
00339         outb(UDR1, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00340         dcb->dcb_tx_idx++;
00341     } else {
00342         cbi(UCSR1B, UDRIE);
00343         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00344     }
00345 }
00346 
00347 #ifdef UART1_CTS_BIT
00348 /*
00349  * Handle AVR UART1 transmit handshake interrupts.
00350  */
00351 static void Cts1Interrupt(void *arg)
00352 {
00353     sbi(UCSR1B, UDRIE);
00354 }
00355 #endif
00356 
00357 #endif                          /* __AVR_ENHANCED__ */
00358 
00359 /*
00360  * Handle AVR UART0 receive complete interrupts.
00361  */
00362 static void Rx0Complete(void *arg)
00363 {
00364     AHDLCDCB *dcb = arg;
00365 
00366     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inb(UDR);
00367     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00368         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00369     /* Late increment fixes ICCAVR bug on volatile variables. */
00370     dcb->dcb_rx_idx++;
00371 }
00372 
00373 #ifdef __AVR_ENHANCED__
00374 /*
00375  * Handle AVR UART1 receive complete interrupts.
00376  */
00377 static void Rx1Complete(void *arg)
00378 {
00379     AHDLCDCB *dcb = arg;
00380 
00381     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inb(UDR1);
00382     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00383         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00384     /* Late increment fixes ICCAVR bug on volatile variables. */
00385     dcb->dcb_rx_idx++;
00386 }
00387 #endif                          /* __AVR_ENHANCED__ */
00388 
00389 /*
00390  * \return 0 on success, -1 in case of any errors.
00391  */
00392 static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush)
00393 {
00394     /*
00395      * If transmit buffer is full, wait until interrupt routine
00396      * signals an empty buffer or until a timeout occurs.
00397      */
00398     while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00399         if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
00400             break;
00401     }
00402 
00403     /*
00404      * If transmit buffer is still full, we have a write timeout.
00405      */
00406     if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00407         return -1;
00408     }
00409 
00410     /*
00411      * Buffer has room for more data. Put the byte in the buffer
00412      * and increment the write index.
00413      */
00414     dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
00415     dcb->dcb_wr_idx++;
00416 
00417     /*
00418      * If transmit buffer has become full and the transmitter
00419      * is not active, then activate it.
00420      */
00421     if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00422 
00423         /*
00424          * TODO: Check handshake.
00425          */
00426         NutEnterCritical();
00427 #ifdef __AVR_ENHANCED__
00428         if (dcb->dcb_base)
00429             sbi(UCSR1B, UDRIE);
00430         else
00431 #endif
00432             sbi(UCR, UDRIE);
00433         NutExitCritical();
00434     }
00435     return 0;
00436 }
00437 
00438 /*
00439  * Characters are properly escaped and checksum is updated.
00440  *
00441  * \return 0 on success, -1 in case of any errors.
00442  */
00443 static int SendHdlcData(AHDLCDCB * dcb, CONST uint8_t * data, uint16_t len, uint16_t * txfcs)
00444 {
00445     uint16_t tbx;
00446     register uint16_t fcs;
00447 
00448     if (txfcs)
00449         fcs = *txfcs;
00450     else
00451         fcs = 0;
00452     while (len) {
00453         tbx = (uint16_t) ((uint8_t) fcs ^ *data) << 1;
00454         fcs >>= 8;
00455         fcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00456         if (IN_ACC_MAP(*data, dcb->dcb_tx_accm) || *data == AHDLC_FLAG || *data == AHDLC_ESCAPE) {
00457             if (SendRawByte(dcb, AHDLC_ESCAPE, 0))
00458                 return -1;
00459             if (SendRawByte(dcb, *data ^ AHDLC_TRANS, 0))
00460                 return -1;
00461         } else if (SendRawByte(dcb, *data, 0))
00462             return -1;
00463         data++;
00464         len--;
00465     }
00466     if (txfcs)
00467         *txfcs = fcs;
00468 
00469     return 0;
00470 }
00471 
00482 int AhdlcOutput(NUTDEVICE * dev, NETBUF * nb)
00483 {
00484     uint16_t txfcs;
00485     AHDLCDCB *dcb = dev->dev_dcb;
00486     uint16_t sz;
00487 
00488     /*
00489      * If we are in RAW mode we are not allowed to send AHDLC output.
00490      * We just emulate packet loss behaviour in here.
00491      */
00492     if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00493         return 0;
00494     }
00495 
00496     /*
00497      * Calculate the number of bytes to be send. Do not
00498      * send packets larger than transmit mru.
00499      */
00500     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00501 
00502     if (sz > dcb->dcb_tx_mru) {
00503         return -1;
00504     }
00505 
00506     /*
00507      * TODO: If transmitter is running, we may omit the flag.
00508      */
00509     SendRawByte(dcb, AHDLC_FLAG, 0);
00510 
00511     /* Initialize the checksum and send the NETBUF. */
00512     txfcs = AHDLC_INITFCS;
00513     if (SendHdlcData(dcb, nb->nb_dl.vp, nb->nb_dl.sz, &txfcs))
00514         return -1;
00515     if (SendHdlcData(dcb, nb->nb_nw.vp, nb->nb_nw.sz, &txfcs))
00516         return -1;
00517     if (SendHdlcData(dcb, nb->nb_tp.vp, nb->nb_tp.sz, &txfcs))
00518         return -1;
00519     if (SendHdlcData(dcb, nb->nb_ap.vp, nb->nb_ap.sz, &txfcs))
00520         return -1;
00521 
00522     /* Send the checksum and the final flag. */
00523     txfcs ^= 0xffff;
00524     if (SendHdlcData(dcb, (uint8_t *) & txfcs, 2, 0))
00525         return -1;
00526     SendRawByte(dcb, AHDLC_FLAG, 1);
00527 
00528     return 0;
00529 }
00530 
00537 THREAD(AhdlcRx, arg)
00538 {
00539     NUTDEVICE *dev = arg;
00540     NUTDEVICE *netdev;
00541     AHDLCDCB *dcb = dev->dev_dcb;
00542     IFNET *ifn;
00543     NETBUF *nb;
00544     uint8_t *rxbuf;
00545     uint8_t *rxptr;
00546     uint16_t rxcnt;
00547     uint8_t ch;
00548     uint16_t tbx;
00549     uint8_t inframe;
00550     uint8_t escaped;
00551     uint16_t rxfcs;
00552 
00553     NutThreadSetPriority(9);
00554     for (;;) {
00555         /*
00556          * Reset variables to their initial state
00557          */
00558         rxptr = 0;
00559         rxcnt = 0;
00560         escaped = 0;
00561         rxfcs = AHDLC_INITFCS;
00562         inframe = 0;
00563 
00564         for (;;) {
00565             /*
00566              * Wait until the network interface has been attached.
00567              * This will be initiated by the application calling
00568              * NutNetIfConfig(), which in turn calls a HDLC_SETIFNET
00569              * ioctl() to store the NUTDEVICE pointer of the network
00570              * device in dev_icb and trigger an event on dcb_mf_evt.
00571              */
00572             while ((netdev = dev->dev_icb) == 0) {
00573                 NutEventWait(&dcb->dcb_mf_evt, 1000);
00574             }
00575             ifn = netdev->dev_icb;
00576             dcb->dcb_rtimeout = 1000;
00577             inframe = 0;
00578 
00579             /*
00580              * Allocate the receive buffer, if this fails, we are in a
00581              * low memory situation. Take a nap and see, if the
00582              * situation improved.
00583              */
00584             if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
00585                 break;
00586             }
00587             NutSleep(1000);
00588         }
00589 
00590         /*
00591          * Signal the link driver that we are up.
00592          */
00593         ifn->if_send = AhdlcOutput;
00594         netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00595 
00596         for (;;) {
00597             /*
00598              * If we are still connected to a network, fetch the next
00599              * character from the buffer.
00600              */
00601             while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00602                 if (dev->dev_icb == 0)
00603                     break;
00604                 /* TODO: Check for idle timeout. */
00605                 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00606                     continue;
00607                 }
00608             }
00609 
00610             /*
00611              * Leave loop if network interface is detached
00612              */
00613             if (dev->dev_icb == 0)
00614                 break;
00615 
00616             /*
00617              * If RAW mode is active, we are not allowing any data encapsulation
00618              * processing. So we just sleep for a while.
00619              */
00620             if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00621                 /*
00622                  * It is a must to sleep here, because if we just yield it could create
00623                  * too much processing in here and stall processing elsewhere. This gives
00624                  * opportunity to other threads to process incoming data from USART.
00625                  */
00626                 NutSleep(100);
00627                 continue;
00628             }
00629 
00630             /*
00631              * Read next character from input buffer
00632              */
00633             ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00634 
00635             if (inframe) {
00636                 if (ch != AHDLC_FLAG) {
00637                     if (ch == AHDLC_ESCAPE) {
00638                         escaped = 1;
00639                         continue;
00640                     }
00641                     if (escaped) {
00642                         ch ^= AHDLC_TRANS;
00643                         escaped = 0;
00644                     }
00645 
00646                     /*
00647                      * Unless the peer lied to us about the negotiated MRU,
00648                      * we should never get a frame which is too long. If it
00649                      * happens, toss it away and grab the next incoming one.
00650                      */
00651                     if (rxcnt++ < dcb->dcb_rx_mru) {
00652                         /* Update calculated checksum and store character in buffer. */
00653                         tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
00654                         rxfcs >>= 8;
00655                         rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00656                         *rxptr++ = ch;
00657                     } else
00658                         inframe = 0;
00659                     continue;
00660                 }
00661 
00662                 if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
00663                     /*
00664                      * If the frame checksum is valid, create a NETBUF
00665                      * and pass it to the network specific receive handler.
00666                      */
00667                     rxcnt -= 2;
00668                     if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00669                         memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00670                         (*ifn->if_recv) (netdev, nb);
00671                     }
00672                 }
00673             }
00674 
00675             /*
00676              * If frame flag is received, resync frame processing
00677              */
00678             if (ch == AHDLC_FLAG) {
00679                 inframe = 1;
00680                 escaped = 0;
00681                 rxptr = rxbuf;
00682                 rxcnt = 0;
00683                 rxfcs = AHDLC_INITFCS;
00684             }
00685         }
00686 
00687         /* Signal the link driver that we are down. */
00688         netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00689 
00690         /* Disconnected, clean up. */
00691         if (rxbuf) {
00692             NutHeapFree(rxbuf);
00693             rxbuf = 0;
00694         }
00695     }
00696 }
00697 
00698 /*
00699  * \param dev Indicates the UART device.
00700  *
00701  * \return 0 on success, -1 otherwise.
00702  */
00703 static int AhdlcAvrGetStatus(NUTDEVICE * dev, uint32_t * status)
00704 {
00705     AHDLCDCB *dcb = dev->dev_dcb;
00706     uint8_t us;
00707 
00708     *status = 0;
00709 
00710 #ifdef __AVR_ENHANCED__
00711     if (dev->dev_base) {
00712 #ifdef UART1_CTS_BIT
00713         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00714             *status |= UART_CTSDISABLED;
00715         else
00716             *status |= UART_CTSENABLED;
00717 #endif
00718 #ifdef UART1_RTS_BIT
00719         if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00720             *status |= UART_RTSDISABLED;
00721         else
00722             *status |= UART_RTSENABLED;
00723 #endif
00724 #ifdef UART1_DTR_BIT
00725         if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00726             *status |= UART_DTRDISABLED;
00727         else
00728             *status |= UART_DTRENABLED;
00729 #endif
00730         us = inb(UCSR1A);
00731     } else
00732 #endif                          /* __AVR_ENHANCED__ */
00733     {
00734 #ifdef UART0_CTS_BIT
00735         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00736             *status |= UART_CTSDISABLED;
00737         else
00738             *status |= UART_CTSENABLED;
00739 #endif
00740 #ifdef UART0_RTS_BIT
00741         if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00742             *status |= UART_RTSDISABLED;
00743         else
00744             *status |= UART_RTSENABLED;
00745 #endif
00746 #ifdef UART0_DTR_BIT
00747         if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00748             *status |= UART_DTRDISABLED;
00749         else
00750             *status |= UART_DTRENABLED;
00751 #endif
00752         us = inb(USR);
00753     }
00754     if (us & FE)
00755         *status |= UART_FRAMINGERROR;
00756     if (us & DOR)
00757         *status |= UART_OVERRUNERROR;
00758     if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00759         *status |= UART_TXBUFFEREMPTY;
00760     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00761         *status |= UART_RXBUFFEREMPTY;
00762 
00763     return 0;
00764 }
00765 
00766 /*
00767  * \param dev Indicates the UART device.
00768  *
00769  * \return 0 on success, -1 otherwise.
00770  */
00771 static int AhdlcAvrSetStatus(NUTDEVICE * dev, uint32_t status)
00772 {
00773 #ifdef __AVR_ENHANCED__
00774     if (dev->dev_base) {
00775 #ifdef UART1_RTS_BIT
00776         if (status & UART_RTSDISABLED)
00777             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00778         else if (status & UART_RTSENABLED)
00779             cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00780 #endif
00781 #ifdef UART1_DTR_BIT
00782         if (status & UART_DTRDISABLED)
00783             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00784         else if (status & UART_DTRENABLED)
00785             cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00786 #endif
00787     } else
00788 #endif                          /* __AVR_ENHANCED__ */
00789     {
00790 #ifdef UART0_RTS_BIT
00791         if (status & UART_RTSDISABLED)
00792             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00793         else if (status & UART_RTSENABLED)
00794             cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00795 #endif
00796 #ifdef UART0_DTR_BIT
00797         if (status & UART_DTRDISABLED)
00798             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00799         else if (status & UART_DTRENABLED)
00800             cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00801 #endif
00802     }
00803     return 0;
00804 }
00805 
00806 /*
00807  * Carefully enable UART functions.
00808  */
00809 static void AhdlcAvrEnable(uint16_t base)
00810 {
00811     NutEnterCritical();
00812 
00813 #ifdef __AVR_ENHANCED__
00814     if (base) {
00815 #ifdef UART1_CTS_BIT
00816         sbi(EIMSK, UART1_CTS_BIT);
00817 #endif
00818         outb(UCSR1B, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00819     } else
00820 #endif                          /* __AVR_ENHANCED__ */
00821     {
00822 #ifdef UART0_CTS_BIT
00823         sbi(EIMSK, UART0_CTS_BIT);
00824 #endif
00825         outb(UCR, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00826     }
00827     NutExitCritical();
00828 }
00829 
00830 /*
00831  * Carefully disable UART functions.
00832  */
00833 static void AhdlcAvrDisable(uint16_t base)
00834 {
00835     /*
00836      * Disable UART interrupts.
00837      */
00838     NutEnterCritical();
00839 #ifdef __AVR_ENHANCED__
00840     if (base) {
00841 #ifdef UART1_CTS_BIT
00842         cbi(EIMSK, UART1_CTS_BIT);
00843 #endif
00844         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXCIE) | BV(UDRIE)));
00845     } else
00846 #endif                          /* __AVR_ENHANCED__ */
00847     {
00848 #ifdef UART0_CTS_BIT
00849         cbi(EIMSK, UART0_CTS_BIT);
00850 #endif
00851         outb(UCR, inb(UCR) & ~(BV(RXCIE) | BV(UDRIE)));
00852     }
00853     NutExitCritical();
00854 
00855     /*
00856      * Allow incoming or outgoing character to finish.
00857      */
00858     NutDelay(10);
00859 
00860     /*
00861      * Now disable UART functions.
00862      */
00863 #ifdef __AVR_ENHANCED__
00864     if (base)
00865         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXEN) | BV(TXEN)));
00866     else
00867 #endif                          /* __AVR_ENHANCED__ */
00868         outb(UCR, inb(UCR) & ~(BV(RXEN) | BV(TXEN)));
00869 }
00870 
00914 int AhdlcAvrIOCtl(NUTDEVICE * dev, int req, void *conf)
00915 {
00916     int rc = 0;
00917     AHDLCDCB *dcb;
00918     void **ppv = (void **) conf;
00919     uint32_t *lvp = (uint32_t *) conf;
00920     uint8_t bv;
00921     uint16_t sv;
00922     uint8_t devnum;
00923 
00924     if (dev == 0)
00925         dev = &devUart0;
00926 
00927     devnum = dev->dev_base;
00928     dcb = dev->dev_dcb;
00929 
00930     switch (req) {
00931     case UART_SETSPEED:
00932         AhdlcAvrDisable(devnum);
00933         sv = (uint16_t) ((((2UL * NutGetCpuClock()) / (*lvp * 16UL)) + 1UL) / 2UL) - 1;
00934 #ifdef __AVR_ENHANCED__
00935         if (devnum) {
00936             outb(UBRR1L, (uint8_t) sv);
00937             outb(UBRR1H, (uint8_t) (sv >> 8));
00938         } else {
00939             outb(UBRR0L, (uint8_t) sv);
00940             outb(UBRR0H, (uint8_t) (sv >> 8));
00941         }
00942 #else
00943         outb(UBRR, (uint8_t) sv);
00944 #endif
00945         AhdlcAvrEnable(devnum);
00946         break;
00947 
00948     case UART_GETSPEED:
00949 #ifdef __AVR_ENHANCED__
00950         if (devnum)
00951             sv = (uint16_t) inb(UBRR1H) << 8 | inb(UBRR1L);
00952         else
00953             sv = (uint16_t) inb(UBRR0H) << 8 | inb(UBRR0L);
00954 #else
00955         sv = inb(UBRR);
00956 #endif
00957         *lvp = NutGetCpuClock() / (16UL * (uint32_t) (sv + 1));
00958         break;
00959 
00960     case UART_SETDATABITS:
00961         AhdlcAvrDisable(devnum);
00962         bv = (uint8_t)(*lvp);
00963 #ifdef __AVR_ENHANCED__
00964         if (bv >= 5 && bv <= 8) {
00965             bv = (bv - 5) << 1;
00966             if (devnum) {
00967                 outb(UCSR1C, (inb(UCSR1C) & 0xF9) | bv);
00968                 outb(UCSR1B, inb(UCSR1B) & 0xFB);
00969             } else {
00970                 outb(UCSR0C, (inb(UCSR0C) & 0xF9) | bv);
00971                 outb(UCSR0B, inb(UCSR0B) & 0xFB);
00972             }
00973         } else
00974             rc = -1;
00975 #else
00976         if (bv != 8)
00977             rc = -1;
00978 #endif
00979         AhdlcAvrEnable(devnum);
00980         break;
00981 
00982     case UART_GETDATABITS:
00983 #ifdef __AVR_ENHANCED__
00984         if (devnum)
00985             *lvp = ((inb(UCSR1C) & 0x06) >> 1) + 5;
00986         else
00987             *lvp = ((inb(UCSR0C) & 0x06) >> 1) + 5;
00988 #else
00989         *lvp = 8;
00990 #endif
00991         break;
00992 
00993     case UART_SETPARITY:
00994         AhdlcAvrDisable(devnum);
00995         bv = (uint8_t)(*lvp);
00996 #ifdef __AVR_ENHANCED__
00997         if (bv <= 2) {
00998             if (bv == 1)
00999                 bv = 3;
01000             bv <<= 4;
01001             if (devnum)
01002                 outb(UCSR1C, (inb(UCSR1C) & 0xCF) | bv);
01003             else
01004                 outb(UCSR0C, (inb(UCSR0C) & 0xCF) | bv);
01005         } else
01006             rc = -1;
01007 #endif
01008         if (bv)
01009             rc = -1;
01010         AhdlcAvrEnable(devnum);
01011         break;
01012 
01013     case UART_GETPARITY:
01014 #ifdef __AVR_ENHANCED__
01015         if (devnum)
01016             bv = (inb(UCSR1C) & 0x30) >> 4;
01017         else
01018             bv = (inb(UCSR0C) & 0x30) >> 4;
01019         if (bv == 3)
01020             bv = 1;
01021 #else
01022         bv = 0;
01023 #endif
01024         *lvp = bv;
01025         break;
01026 
01027     case UART_SETSTOPBITS:
01028         AhdlcAvrDisable(devnum);
01029         bv = (uint8_t)(*lvp);
01030 #ifdef __AVR_ENHANCED__
01031         if (bv == 1 || bv == 2) {
01032             bv = (bv - 1) << 3;
01033             if (devnum)
01034                 outb(UCSR1C, (inb(UCSR1C) & 0xF7) | bv);
01035             else
01036                 outb(UCSR0C, (inb(UCSR0C) & 0xF7) | bv);
01037         } else
01038             rc = -1;
01039 #else
01040         if (bv != 1)
01041             rc = -1;
01042 #endif
01043         AhdlcAvrEnable(devnum);
01044         break;
01045 
01046     case UART_GETSTOPBITS:
01047 #ifdef __AVR_ENHANCED__
01048         if (devnum)
01049             *lvp = ((inb(UCSR1C) & 0x08) >> 3) + 1;
01050         else
01051             *lvp = ((inb(UCSR0C) & 0x08) >> 3) + 1;
01052 #else
01053         *lvp = 1;
01054 #endif
01055         break;
01056 
01057     case UART_GETSTATUS:
01058         AhdlcAvrGetStatus(dev, lvp);
01059         break;
01060     case UART_SETSTATUS:
01061         AhdlcAvrSetStatus(dev, *lvp);
01062         break;
01063 
01064     case UART_SETREADTIMEOUT:
01065         dcb->dcb_rtimeout = *lvp;
01066         break;
01067     case UART_GETREADTIMEOUT:
01068         *lvp = dcb->dcb_rtimeout;
01069         break;
01070 
01071     case UART_SETWRITETIMEOUT:
01072         dcb->dcb_wtimeout = *lvp;
01073         break;
01074     case UART_GETWRITETIMEOUT:
01075         *lvp = dcb->dcb_wtimeout;
01076         break;
01077 
01078     case UART_SETLOCALECHO:
01079         bv = (uint8_t)(*lvp);
01080         if (bv)
01081             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01082         else
01083             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01084         break;
01085     case UART_GETLOCALECHO:
01086         if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
01087             *lvp = 1;
01088         else
01089             *lvp = 0;
01090         break;
01091 
01092     case UART_SETFLOWCONTROL:
01093         bv = (uint8_t)(*lvp);
01094         if (bv)
01095             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01096         else
01097             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01098         break;
01099     case UART_GETFLOWCONTROL:
01100         break;
01101 
01102     case UART_SETRAWMODE:
01103         bv = (uint8_t)(*lvp);
01104         if (bv)
01105             dcb->dcb_modeflags |= UART_MF_RAWMODE;
01106         else
01107             dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
01108         break;
01109 
01110     case UART_GETRAWMODE:
01111         if (dcb->dcb_modeflags & UART_MF_RAWMODE)
01112             *lvp = 1;
01113         else
01114             *lvp = 0;
01115         break;
01116 
01117     case HDLC_SETIFNET:
01118         if (ppv && (*ppv != 0)) {
01119             dev->dev_icb = *ppv;
01120             dev->dev_type = IFTYP_NET;
01121             NutEventPost(&dcb->dcb_mf_evt);
01122         } else {
01123             dev->dev_type = IFTYP_CHAR;
01124 
01125             if (dev->dev_icb != 0)
01126             {
01127                 dev->dev_icb = 0;
01128 
01129                 /*
01130                  * Signal AHDLC Thread, so it can change it's state instantly
01131                  */
01132                 NutEventPost(&dcb->dcb_rx_rdy);
01133             }
01134         }
01135         break;
01136     case HDLC_GETIFNET:
01137         *ppv = dev->dev_icb;
01138         break;
01139 
01140     default:
01141         rc = -1;
01142         break;
01143     }
01144     return rc;
01145 }
01146 
01159 int AhdlcAvrInit(NUTDEVICE * dev)
01160 {
01161     int rc = 0;
01162     AHDLCDCB *dcb;
01163     uint32_t baudrate = 9600;
01164 
01165     /* Disable UART. */
01166     AhdlcAvrDisable(dev->dev_base);
01167 
01168     /* Initialize driver control block. */
01169     dcb = dev->dev_dcb;
01170     memset(dcb, 0, sizeof(AHDLCDCB));
01171     dcb->dcb_base = dev->dev_base;
01172     dcb->dcb_rx_buf = NutHeapAlloc(256);
01173     dcb->dcb_tx_buf = NutHeapAlloc(256);
01174     dcb->dcb_rx_mru = 1500;
01175     dcb->dcb_tx_mru = 1500;
01176     dcb->dcb_tx_accm = 0xFFFFFFFF;
01177 
01178     /*
01179      * Initialize UART handshake hardware and register interrupt handlers.
01180      */
01181     if (dev->dev_base) {
01182 #ifdef __AVR_ENHANCED__
01183 
01184 #ifdef UART1_CTS_BIT
01185         sbi(UART1_CTS_PORT, UART1_CTS_BIT);
01186         cbi(UART1_CTS_DDR, UART1_CTS_BIT);
01187         /* Falling edge will generate interrupts. */
01188 #if UART1_CTS_BIT == 4
01189         sbi(EICR, 1);
01190 #elif UART1_CTS_BIT == 5
01191         sbi(EICR, 3);
01192 #elif UART1_CTS_BIT == 6
01193         sbi(EICR, 5);
01194 #elif UART1_CTS_BIT == 7
01195         sbi(EICR, 7);
01196 #endif
01197 #endif
01198 #ifdef UART1_RTS_BIT
01199         sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01200         sbi(UART1_RTS_DDR, UART1_RTS_BIT);
01201 #endif
01202 #ifdef UART1_DTR_BIT
01203         sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01204         sbi(UART1_DTR_DDR, UART1_DTR_BIT);
01205 #endif
01206 
01207         if (NutRegisterIrqHandler(&sig_UART1_RECV, Rx1Complete, dcb))
01208             rc = -1;
01209         else if (NutRegisterIrqHandler(&sig_UART1_DATA, Tx1Complete, dcb))
01210 #ifdef UART1_CTS_BIT
01211             rc = -1;
01212         else if (NutRegisterIrqHandler(&UART1_CTS_SIGNAL, Cts1Interrupt, dev))
01213 #endif
01214 #endif                          /* __AVR_ENHANCED__ */
01215             rc = -1;
01216 
01217     } else {
01218 
01219 #ifdef UART0_CTS_BIT
01220         sbi(UART0_CTS_PORT, UART0_CTS_BIT);
01221         cbi(UART0_CTS_DDR, UART0_CTS_BIT);
01222 #if UART0_CTS_BIT == 4
01223         sbi(EICR, 1);
01224 #elif UART0_CTS_BIT == 5
01225         sbi(EICR, 3);
01226 #elif UART0_CTS_BIT == 6
01227         sbi(EICR, 5);
01228 #elif UART0_CTS_BIT == 7
01229         sbi(EICR, 7);
01230 #endif
01231 #endif
01232 #ifdef UART0_RTS_BIT
01233         sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01234         sbi(UART0_RTS_DDR, UART0_RTS_BIT);
01235 #endif
01236 #ifdef UART0_DTR_BIT
01237         sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01238         sbi(UART0_DTR_DDR, UART0_DTR_BIT);
01239 #endif
01240 
01241         if (NutRegisterIrqHandler(&sig_UART0_RECV, Rx0Complete, dcb))
01242             rc = -1;
01243         else if (NutRegisterIrqHandler(&sig_UART0_DATA, Tx0Complete, dcb))
01244             rc = -1;
01245 #ifdef UART0_CTS_BIT
01246         else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt, dev))
01247             rc = -1;
01248 #endif
01249     }
01250 
01251 
01252     /*
01253      * If we have been successful so far, start the HDLC receiver thread,
01254      * set the initial baudrate and enable the UART.
01255      */
01256     if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, 
01257         (NUT_THREAD_AHDLCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) {
01258         AhdlcAvrIOCtl(dev, UART_SETSPEED, &baudrate);
01259 
01260         return 0;
01261     }
01262 
01263     /* We failed, clean up. */
01264     if (dcb->dcb_rx_buf)
01265         NutHeapFree((void *) dcb->dcb_rx_buf);
01266     if (dcb->dcb_tx_buf)
01267         NutHeapFree((void *) dcb->dcb_tx_buf);
01268 
01269     return -1;
01270 }
01271 
01298 int AhdlcAvrRead(NUTFILE * fp, void *buffer, int size)
01299 {
01300     int rc = 0;
01301     AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
01302     uint8_t *cp = buffer;
01303 
01304     /*
01305      * Get characters from receive buffer.
01306      */
01307     if (buffer) {
01308         while (rc < size) {
01309             if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
01310                 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
01311                 rc++;
01312             } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
01313                 break;
01314         }
01315     }
01316 
01317     /*
01318      * Call without data buffer discards receive buffer.
01319      */
01320     else
01321         dcb->dcb_rd_idx = dcb->dcb_rx_idx;
01322 
01323     return rc;
01324 }
01325 
01338 int AhdlcAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01339 {
01340     int rc = 0;
01341     AHDLCDCB *dcb = dev->dev_dcb;
01342     CONST uint8_t *cp = buffer;
01343 
01344     /*
01345      * Put characters in transmit buffer.
01346      */
01347     if (buffer) {
01348         while (rc < len) {
01349             if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01350                 break;
01351             cp++;
01352             rc++;
01353         }
01354     }
01355 
01356     /*
01357      * Call without data pointer starts transmission.
01358      */
01359     else {
01360         /*
01361          * TODO: Check handshake.
01362          */
01363 #ifdef __AVR_ENHANCED__
01364         if (dev->dev_base)
01365             sbi(UCSR1B, UDRIE);
01366         else
01367 #endif
01368             sbi(UCR, UDRIE);
01369     }
01370     return rc;
01371 }
01372 
01392 int AhdlcAvrWrite(NUTFILE * fp, CONST void *buffer, int len)
01393 {
01394     return AhdlcAvrPut(fp->nf_dev, buffer, len, 0);
01395 }
01396 
01418 int AhdlcAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len)
01419 {
01420     return AhdlcAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);
01421 }
01422 
01439 NUTFILE *AhdlcAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01440 {
01441     NUTFILE *fp;
01442 
01443     if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01444         return NUTFILE_EOF;
01445 
01446     fp->nf_next = 0;
01447     fp->nf_dev = dev;
01448     fp->nf_fcb = 0;
01449 
01450     /* Enable handshake outputs. */
01451 #ifdef __AVR_ENHANCED__
01452     if (dev->dev_base) {
01453 #ifdef UART1_RTS_BIT
01454         cbi(UART1_RTS_PORT, UART1_RTS_BIT);
01455 #endif
01456 #ifdef UART1_DTR_BIT
01457         cbi(UART1_DTR_PORT, UART1_DTR_BIT);
01458 #endif
01459     } else
01460 #endif                          /* __AVR_ENHANCED__ */
01461     {
01462 #ifdef UART0_RTS_BIT
01463         cbi(UART0_RTS_PORT, UART0_RTS_BIT);
01464 #endif
01465 #ifdef UART0_DTR_BIT
01466         cbi(UART0_DTR_PORT, UART0_DTR_BIT);
01467 #endif
01468     }
01469     return fp;
01470 }
01471 
01485 int AhdlcAvrClose(NUTFILE * fp)
01486 {
01487     if (fp && fp != NUTFILE_EOF) {
01488         /* Disable handshake outputs. */
01489 #ifdef __AVR_ENHANCED__
01490         if (fp->nf_dev->dev_base) {
01491 #ifdef UART1_RTS_BIT
01492             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01493 #endif
01494 #ifdef UART1_DTR_BIT
01495             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01496 #endif
01497         } else
01498 #endif                          /* __AVR_ENHANCED__ */
01499         {
01500 #ifdef UART0_RTS_BIT
01501             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01502 #endif
01503 #ifdef UART0_DTR_BIT
01504             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01505 #endif
01506         }
01507         NutHeapFree(fp);
01508         return 0;
01509     }
01510     return -1;
01511 }
01512 

© 2000-2010 by contributors - visit http://www.ethernut.de/