Nut/OS  4.10.1
API Reference
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 <sys/atom.h>
00089 #include <sys/heap.h>
00090 #include <sys/event.h>
00091 #include <sys/timer.h>
00092 #include <sys/thread.h>
00093 
00094 #include <dev/irqreg.h>
00095 #include <dev/uartavr.h>
00096 #include <dev/ppp.h>
00097 #include <dev/ahdlcavr.h>
00098 
00099 #include <stdint.h>
00100 #include <stdio.h>
00101 #include <string.h>
00102 #include <stdlib.h>
00103 #include <fcntl.h>
00104 
00109 
00115 #ifdef UART0_RTS_BIT
00116 
00117 #if (UART0_RTS_AVRPORT == AVRPORTB)
00118 #define UART0_RTS_PORT  PORTB
00119 #define UART0_RTS_DDR   DDRB
00120 
00121 #elif (UART0_RTS_AVRPORT == AVRPORTD)
00122 #define UART0_RTS_PORT  PORTD
00123 #define UART0_RTS_DDR   DDRD
00124 
00125 #elif (UART0_RTS_AVRPORT == AVRPORTE)
00126 #define UART0_RTS_PORT  PORTE
00127 #define UART0_RTS_DDR   DDRE
00128 
00129 #elif (UART0_RTS_AVRPORT == AVRPORTF)
00130 #define UART0_RTS_PORT  PORTF
00131 #define UART0_RTS_DDR   DDRF
00132 
00133 #elif (UART0_RTS_AVRPORT == AVRPORTG)
00134 #define UART0_RTS_PORT  PORTG
00135 #define UART0_RTS_DDR   DDRG
00136 
00137 #elif (UART0_RTS_AVRPORT == AVRPORTH)
00138 #define UART0_RTS_PORT  PORTH
00139 #define UART0_RTS_DDR   DDRH
00140 
00141 #endif
00142 
00143 #endif /* UART0_RTS_BIT */
00144 
00145 #ifdef UART0_DTR_BIT
00146 
00147 #if (UART0_DTR_AVRPORT == AVRPORTB)
00148 #define UART0_DTR_PORT  PORTB
00149 #define UART0_DTR_DDR   DDRB
00150 
00151 #elif (UART0_DTR_AVRPORT == AVRPORTD)
00152 #define UART0_DTR_PORT  PORTD
00153 #define UART0_DTR_DDR   DDRD
00154 
00155 #elif (UART0_DTR_AVRPORT == AVRPORTE)
00156 #define UART0_DTR_PORT  PORTE
00157 #define UART0_DTR_DDR   DDRE
00158 
00159 #elif (UART0_DTR_AVRPORT == AVRPORTF)
00160 #define UART0_DTR_PORT  PORTF
00161 #define UART0_DTR_DDR   DDRF
00162 
00163 #elif (UART0_DTR_AVRPORT == AVRPORTG)
00164 #define UART0_DTR_PORT  PORTG
00165 #define UART0_DTR_DDR   DDRG
00166 
00167 #elif (UART0_DTR_AVRPORT == AVRPORTH)
00168 #define UART0_DTR_PORT  PORTH
00169 #define UART0_DTR_DDR   DDRH
00170 
00171 #endif
00172 
00173 #endif /* UART0_DTR_BIT */
00174 
00180 #ifdef UART1_RTS_BIT
00181 
00182 #if (UART1_RTS_AVRPORT == AVRPORTB)
00183 #define UART1_RTS_PORT   PORTB
00184 #define UART1_RTS_DDR    DDRB
00185 
00186 #elif (UART1_RTS_AVRPORT == AVRPORTD)
00187 #define UART1_RTS_PORT   PORTD
00188 #define UART1_RTS_DDR    DDRD
00189 
00190 #elif (UART1_RTS_AVRPORT == AVRPORTE)
00191 #define UART1_RTS_PORT   PORTE
00192 #define UART1_RTS_DDR    DDRE
00193 
00194 #elif (UART1_RTS_AVRPORT == AVRPORTF)
00195 #define UART1_RTS_PORT   PORTF
00196 #define UART1_RTS_DDR    DDRF
00197 
00198 #elif (UART1_RTS_AVRPORT == AVRPORTG)
00199 #define UART1_RTS_PORT   PORTG
00200 #define UART1_RTS_DDR    DDRG
00201 
00202 #elif (UART1_RTS_AVRPORT == AVRPORTH)
00203 #define UART1_RTS_PORT   PORTH
00204 #define UART1_RTS_DDR    DDRH
00205 
00206 #endif
00207 
00208 #endif /* UART1_RTS_BIT */
00209 
00210 #ifdef UART1_DTR_BIT
00211 
00212 #if (UART1_DTR_AVRPORT == AVRPORTB)
00213 #define UART1_DTR_PORT  PORTB
00214 #define UART1_DTR_DDR   DDRB
00215 
00216 #elif (UART1_DTR_AVRPORT == AVRPORTD)
00217 #define UART1_DTR_PORT  PORTD
00218 #define UART1_DTR_DDR   DDRD
00219 
00220 #elif (UART1_DTR_AVRPORT == AVRPORTE)
00221 #define UART1_DTR_PORT  PORTE
00222 #define UART1_DTR_DDR   DDRE
00223 
00224 #elif (UART1_DTR_AVRPORT == AVRPORTF)
00225 #define UART1_DTR_PORT  PORTF
00226 #define UART1_DTR_DDR   DDRF
00227 
00228 #elif (UART1_DTR_AVRPORT == AVRPORTG)
00229 #define UART1_DTR_PORT  PORTG
00230 #define UART1_DTR_DDR   DDRG
00231 
00232 #elif (UART1_DTR_AVRPORT == AVRPORTH)
00233 #define UART1_DTR_PORT  PORTH
00234 #define UART1_DTR_DDR   DDRH
00235 
00236 #endif
00237 
00238 #endif /* UART1_DTR_BIT */
00239 
00240 /*
00241  * FCS lookup table located in program memory space.
00242  */
00243 static prog_char fcstab[512] = {
00244     0x00, 0x00, 0x11, 0x89, 0x23, 0x12, 0x32, 0x9b, 0x46, 0x24, 0x57, 0xad, 0x65, 0x36, 0x74, 0xbf,
00245     0x8c, 0x48, 0x9d, 0xc1, 0xaf, 0x5a, 0xbe, 0xd3, 0xca, 0x6c, 0xdb, 0xe5, 0xe9, 0x7e, 0xf8, 0xf7,
00246     0x10, 0x81, 0x01, 0x08, 0x33, 0x93, 0x22, 0x1a, 0x56, 0xa5, 0x47, 0x2c, 0x75, 0xb7, 0x64, 0x3e,
00247     0x9c, 0xc9, 0x8d, 0x40, 0xbf, 0xdb, 0xae, 0x52, 0xda, 0xed, 0xcb, 0x64, 0xf9, 0xff, 0xe8, 0x76,
00248     0x21, 0x02, 0x30, 0x8b, 0x02, 0x10, 0x13, 0x99, 0x67, 0x26, 0x76, 0xaf, 0x44, 0x34, 0x55, 0xbd,
00249     0xad, 0x4a, 0xbc, 0xc3, 0x8e, 0x58, 0x9f, 0xd1, 0xeb, 0x6e, 0xfa, 0xe7, 0xc8, 0x7c, 0xd9, 0xf5,
00250     0x31, 0x83, 0x20, 0x0a, 0x12, 0x91, 0x03, 0x18, 0x77, 0xa7, 0x66, 0x2e, 0x54, 0xb5, 0x45, 0x3c,
00251     0xbd, 0xcb, 0xac, 0x42, 0x9e, 0xd9, 0x8f, 0x50, 0xfb, 0xef, 0xea, 0x66, 0xd8, 0xfd, 0xc9, 0x74,
00252 
00253     0x42, 0x04, 0x53, 0x8d, 0x61, 0x16, 0x70, 0x9f, 0x04, 0x20, 0x15, 0xa9, 0x27, 0x32, 0x36, 0xbb,
00254     0xce, 0x4c, 0xdf, 0xc5, 0xed, 0x5e, 0xfc, 0xd7, 0x88, 0x68, 0x99, 0xe1, 0xab, 0x7a, 0xba, 0xf3,
00255     0x52, 0x85, 0x43, 0x0c, 0x71, 0x97, 0x60, 0x1e, 0x14, 0xa1, 0x05, 0x28, 0x37, 0xb3, 0x26, 0x3a,
00256     0xde, 0xcd, 0xcf, 0x44, 0xfd, 0xdf, 0xec, 0x56, 0x98, 0xe9, 0x89, 0x60, 0xbb, 0xfb, 0xaa, 0x72,
00257     0x63, 0x06, 0x72, 0x8f, 0x40, 0x14, 0x51, 0x9d, 0x25, 0x22, 0x34, 0xab, 0x06, 0x30, 0x17, 0xb9,
00258     0xef, 0x4e, 0xfe, 0xc7, 0xcc, 0x5c, 0xdd, 0xd5, 0xa9, 0x6a, 0xb8, 0xe3, 0x8a, 0x78, 0x9b, 0xf1,
00259     0x73, 0x87, 0x62, 0x0e, 0x50, 0x95, 0x41, 0x1c, 0x35, 0xa3, 0x24, 0x2a, 0x16, 0xb1, 0x07, 0x38,
00260     0xff, 0xcf, 0xee, 0x46, 0xdc, 0xdd, 0xcd, 0x54, 0xb9, 0xeb, 0xa8, 0x62, 0x9a, 0xf9, 0x8b, 0x70,
00261 
00262     0x84, 0x08, 0x95, 0x81, 0xa7, 0x1a, 0xb6, 0x93, 0xc2, 0x2c, 0xd3, 0xa5, 0xe1, 0x3e, 0xf0, 0xb7,
00263     0x08, 0x40, 0x19, 0xc9, 0x2b, 0x52, 0x3a, 0xdb, 0x4e, 0x64, 0x5f, 0xed, 0x6d, 0x76, 0x7c, 0xff,
00264     0x94, 0x89, 0x85, 0x00, 0xb7, 0x9b, 0xa6, 0x12, 0xd2, 0xad, 0xc3, 0x24, 0xf1, 0xbf, 0xe0, 0x36,
00265     0x18, 0xc1, 0x09, 0x48, 0x3b, 0xd3, 0x2a, 0x5a, 0x5e, 0xe5, 0x4f, 0x6c, 0x7d, 0xf7, 0x6c, 0x7e,
00266     0xa5, 0x0a, 0xb4, 0x83, 0x86, 0x18, 0x97, 0x91, 0xe3, 0x2e, 0xf2, 0xa7, 0xc0, 0x3c, 0xd1, 0xb5,
00267     0x29, 0x42, 0x38, 0xcb, 0x0a, 0x50, 0x1b, 0xd9, 0x6f, 0x66, 0x7e, 0xef, 0x4c, 0x74, 0x5d, 0xfd,
00268     0xb5, 0x8b, 0xa4, 0x02, 0x96, 0x99, 0x87, 0x10, 0xf3, 0xaf, 0xe2, 0x26, 0xd0, 0xbd, 0xc1, 0x34,
00269     0x39, 0xc3, 0x28, 0x4a, 0x1a, 0xd1, 0x0b, 0x58, 0x7f, 0xe7, 0x6e, 0x6e, 0x5c, 0xf5, 0x4d, 0x7c,
00270 
00271     0xc6, 0x0c, 0xd7, 0x85, 0xe5, 0x1e, 0xf4, 0x97, 0x80, 0x28, 0x91, 0xa1, 0xa3, 0x3a, 0xb2, 0xb3,
00272     0x4a, 0x44, 0x5b, 0xcd, 0x69, 0x56, 0x78, 0xdf, 0x0c, 0x60, 0x1d, 0xe9, 0x2f, 0x72, 0x3e, 0xfb,
00273     0xd6, 0x8d, 0xc7, 0x04, 0xf5, 0x9f, 0xe4, 0x16, 0x90, 0xa9, 0x81, 0x20, 0xb3, 0xbb, 0xa2, 0x32,
00274     0x5a, 0xc5, 0x4b, 0x4c, 0x79, 0xd7, 0x68, 0x5e, 0x1c, 0xe1, 0x0d, 0x68, 0x3f, 0xf3, 0x2e, 0x7a,
00275     0xe7, 0x0e, 0xf6, 0x87, 0xc4, 0x1c, 0xd5, 0x95, 0xa1, 0x2a, 0xb0, 0xa3, 0x82, 0x38, 0x93, 0xb1,
00276     0x6b, 0x46, 0x7a, 0xcf, 0x48, 0x54, 0x59, 0xdd, 0x2d, 0x62, 0x3c, 0xeb, 0x0e, 0x70, 0x1f, 0xf9,
00277     0xf7, 0x8f, 0xe6, 0x06, 0xd4, 0x9d, 0xc5, 0x14, 0xb1, 0xab, 0xa0, 0x22, 0x92, 0xb9, 0x83, 0x30,
00278     0x7b, 0xc7, 0x6a, 0x4e, 0x58, 0xd5, 0x49, 0x5c, 0x3d, 0xe3, 0x2c, 0x6a, 0x1e, 0xf1, 0x0f, 0x78
00279 };
00280 
00284 #define IN_ACC_MAP(c, m) in_acc_map(c, &(m))
00285 /* Trust me, this is a whole lot smaller when compiled than it looks in C.
00286  * It is written explicitly so that gcc can make good AVR asm out of it. */
00287 static INLINE uint8_t in_acc_map(u_char ch, void * esc_mask) __attribute__((always_inline));  /* gcc specific attribute */
00288 static INLINE uint8_t in_acc_map(u_char ch, void * esc_mask)
00289 {
00290     const uint8_t shift_mask = 0x07;
00291     const uint8_t index_mask = 0x18;
00292     const uint8_t over_mask = ~(shift_mask|index_mask);
00293 
00294     uint8_t shift, index, emask;
00295     uint8_t * emskp = esc_mask;
00296 
00297     if (over_mask & ch) {
00298         return 0;
00299     }
00300 
00301     shift = shift_mask & ch;
00302 
00303     index = ch >> (uint8_t)3;
00304         
00305     /* NOTE:  This assumes that the esc bit field is little endian,
00306      * which it should have been switched to before being set. */
00307 
00308     emask = emskp[index];
00309     return emask & ( ((uint8_t)1) << shift );
00310 }
00311 
00312 #ifndef NUT_THREAD_AHDLCRXSTACK
00313 #define NUT_THREAD_AHDLCRXSTACK     512
00314 #endif
00315 
00316 /*
00317  * Handle AVR UART0 transmit complete interrupts.
00318  */
00319 static void Tx0Complete(void *arg)
00320 {
00321     AHDLCDCB *dcb = arg;
00322 
00323     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00324 #ifdef UART0_CTS_BIT
00325         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT)) {
00326             cbi(UCR, UDRIE);
00327             return;
00328         }
00329 #endif
00330         outb(UDR, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00331         dcb->dcb_tx_idx++;
00332     } else {
00333         cbi(UCR, UDRIE);
00334         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00335     }
00336 }
00337 
00338 #ifdef UART0_CTS_BIT
00339 /*
00340  * Handle AVR UART0 transmit handshake interrupts.
00341  */
00342 static void Cts0Interrupt(void *arg)
00343 {
00344     sbi(UCR, UDRIE);
00345 }
00346 #endif
00347 
00348 #ifdef __AVR_ENHANCED__
00349 /*
00350  * Handle AVR UART1 transmit complete interrupts.
00351  */
00352 static void Tx1Complete(void *arg)
00353 {
00354     register AHDLCDCB *dcb = arg;
00355 
00356     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00357 #ifdef UART1_CTS_BIT
00358         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT)) {
00359             cbi(UCSR1B, UDRIE);
00360             return;
00361         }
00362 #endif
00363         outb(UDR1, dcb->dcb_tx_buf[dcb->dcb_tx_idx]);
00364         dcb->dcb_tx_idx++;
00365     } else {
00366         cbi(UCSR1B, UDRIE);
00367         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00368     }
00369 }
00370 
00371 #ifdef UART1_CTS_BIT
00372 /*
00373  * Handle AVR UART1 transmit handshake interrupts.
00374  */
00375 static void Cts1Interrupt(void *arg)
00376 {
00377     sbi(UCSR1B, UDRIE);
00378 }
00379 #endif
00380 
00381 #endif                          /* __AVR_ENHANCED__ */
00382 
00383 /*
00384  * Handle AVR UART0 receive complete interrupts.
00385  */
00386 static void Rx0Complete(void *arg)
00387 {
00388     AHDLCDCB *dcb = arg;
00389 
00390     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inb(UDR);
00391     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00392         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00393     /* Late increment fixes ICCAVR bug on volatile variables. */
00394     dcb->dcb_rx_idx++;
00395 }
00396 
00397 #ifdef __AVR_ENHANCED__
00398 /*
00399  * Handle AVR UART1 receive complete interrupts.
00400  */
00401 static void Rx1Complete(void *arg)
00402 {
00403     AHDLCDCB *dcb = arg;
00404 
00405     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inb(UDR1);
00406     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00407         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00408     /* Late increment fixes ICCAVR bug on volatile variables. */
00409     dcb->dcb_rx_idx++;
00410 }
00411 #endif                          /* __AVR_ENHANCED__ */
00412 
00413 /*
00414  * \return 0 on success, -1 in case of any errors.
00415  */
00416 static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush)
00417 {
00418     /*
00419      * If transmit buffer is full, wait until interrupt routine
00420      * signals an empty buffer or until a timeout occurs.
00421      */
00422     while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00423         if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
00424             break;
00425     }
00426 
00427     /*
00428      * If transmit buffer is still full, we have a write timeout.
00429      */
00430     if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00431         return -1;
00432     }
00433 
00434     /*
00435      * Buffer has room for more data. Put the byte in the buffer
00436      * and increment the write index.
00437      */
00438     dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
00439     dcb->dcb_wr_idx++;
00440 
00441     /*
00442      * If transmit buffer has become full and the transmitter
00443      * is not active, then activate it.
00444      */
00445     if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00446 
00447         /*
00448          * TODO: Check handshake.
00449          */
00450         NutEnterCritical();
00451 #ifdef __AVR_ENHANCED__
00452         if (dcb->dcb_base)
00453             sbi(UCSR1B, UDRIE);
00454         else
00455 #endif
00456             sbi(UCR, UDRIE);
00457         NutExitCritical();
00458     }
00459     return 0;
00460 }
00461 
00462 /*
00463  * Characters are properly escaped and checksum is updated.
00464  *
00465  * \return 0 on success, -1 in case of any errors.
00466  */
00467 static int SendHdlcData(AHDLCDCB * dcb, CONST uint8_t * data, uint16_t len, uint16_t * txfcs)
00468 {
00469     uint16_t tbx;
00470     register uint16_t fcs;
00471 
00472     if (txfcs)
00473         fcs = *txfcs;
00474     else
00475         fcs = 0;
00476     while (len) {
00477         tbx = (uint16_t) ((uint8_t) fcs ^ *data) << 1;
00478         fcs >>= 8;
00479         fcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00480         if (IN_ACC_MAP(*data, dcb->dcb_tx_accm) || *data == AHDLC_FLAG || *data == AHDLC_ESCAPE) {
00481             if (SendRawByte(dcb, AHDLC_ESCAPE, 0))
00482                 return -1;
00483             if (SendRawByte(dcb, *data ^ AHDLC_TRANS, 0))
00484                 return -1;
00485         } else if (SendRawByte(dcb, *data, 0))
00486             return -1;
00487         data++;
00488         len--;
00489     }
00490     if (txfcs)
00491         *txfcs = fcs;
00492 
00493     return 0;
00494 }
00495 
00506 int AhdlcOutput(NUTDEVICE * dev, NETBUF * nb)
00507 {
00508     uint16_t txfcs;
00509     AHDLCDCB *dcb = dev->dev_dcb;
00510     uint16_t sz;
00511 
00512     /*
00513      * If we are in RAW mode we are not allowed to send AHDLC output.
00514      * We just emulate packet loss behaviour in here.
00515      */
00516     if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00517         return 0;
00518     }
00519 
00520     /*
00521      * Calculate the number of bytes to be send. Do not
00522      * send packets larger than transmit mru.
00523      */
00524     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00525 
00526     if (sz > dcb->dcb_tx_mru) {
00527         return -1;
00528     }
00529 
00530     /*
00531      * TODO: If transmitter is running, we may omit the flag.
00532      */
00533     SendRawByte(dcb, AHDLC_FLAG, 0);
00534 
00535     /* Initialize the checksum and send the NETBUF. */
00536     txfcs = AHDLC_INITFCS;
00537     if (SendHdlcData(dcb, nb->nb_dl.vp, nb->nb_dl.sz, &txfcs))
00538         return -1;
00539     if (SendHdlcData(dcb, nb->nb_nw.vp, nb->nb_nw.sz, &txfcs))
00540         return -1;
00541     if (SendHdlcData(dcb, nb->nb_tp.vp, nb->nb_tp.sz, &txfcs))
00542         return -1;
00543     if (SendHdlcData(dcb, nb->nb_ap.vp, nb->nb_ap.sz, &txfcs))
00544         return -1;
00545 
00546     /* Send the checksum and the final flag. */
00547     txfcs ^= 0xffff;
00548     if (SendHdlcData(dcb, (uint8_t *) & txfcs, 2, 0))
00549         return -1;
00550     SendRawByte(dcb, AHDLC_FLAG, 1);
00551 
00552     return 0;
00553 }
00554 
00561 THREAD(AhdlcRx, arg)
00562 {
00563     NUTDEVICE *dev = arg;
00564     NUTDEVICE *netdev;
00565     AHDLCDCB *dcb = dev->dev_dcb;
00566     IFNET *ifn;
00567     NETBUF *nb;
00568     uint8_t *rxbuf;
00569     uint8_t *rxptr;
00570     uint16_t rxcnt;
00571     uint8_t ch;
00572     uint16_t tbx;
00573     uint8_t inframe;
00574     uint8_t escaped;
00575     uint16_t rxfcs;
00576 
00577     NutThreadSetPriority(9);
00578     for (;;) {
00579         /*
00580          * Reset variables to their initial state
00581          */
00582         rxptr = 0;
00583         rxcnt = 0;
00584         escaped = 0;
00585         rxfcs = AHDLC_INITFCS;
00586         inframe = 0;
00587 
00588         for (;;) {
00589             /*
00590              * Wait until the network interface has been attached.
00591              * This will be initiated by the application calling
00592              * NutNetIfConfig(), which in turn calls a HDLC_SETIFNET
00593              * ioctl() to store the NUTDEVICE pointer of the network
00594              * device in dev_icb and trigger an event on dcb_mf_evt.
00595              */
00596             while ((netdev = dev->dev_icb) == 0) {
00597                 NutEventWait(&dcb->dcb_mf_evt, 1000);
00598             }
00599             ifn = netdev->dev_icb;
00600             dcb->dcb_rtimeout = 1000;
00601             inframe = 0;
00602 
00603             /*
00604              * Allocate the receive buffer, if this fails, we are in a
00605              * low memory situation. Take a nap and see, if the
00606              * situation improved.
00607              */
00608             if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
00609                 break;
00610             }
00611             NutSleep(1000);
00612         }
00613 
00614         /*
00615          * Signal the link driver that we are up.
00616          */
00617         ifn->if_send = AhdlcOutput;
00618         netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00619 
00620         for (;;) {
00621             /*
00622              * If we are still connected to a network, fetch the next
00623              * character from the buffer.
00624              */
00625             while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00626                 if (dev->dev_icb == 0)
00627                     break;
00628                 /* TODO: Check for idle timeout. */
00629                 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00630                     continue;
00631                 }
00632             }
00633 
00634             /*
00635              * Leave loop if network interface is detached
00636              */
00637             if (dev->dev_icb == 0)
00638                 break;
00639 
00640             /*
00641              * If RAW mode is active, we are not allowing any data encapsulation
00642              * processing. So we just sleep for a while.
00643              */
00644             if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00645                 /*
00646                  * It is a must to sleep here, because if we just yield it could create
00647                  * too much processing in here and stall processing elsewhere. This gives
00648                  * opportunity to other threads to process incoming data from USART.
00649                  */
00650                 NutSleep(100);
00651                 continue;
00652             }
00653 
00654             /*
00655              * Read next character from input buffer
00656              */
00657             ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00658 
00659             if (inframe) {
00660                 if (ch != AHDLC_FLAG) {
00661                     if (ch == AHDLC_ESCAPE) {
00662                         escaped = 1;
00663                         continue;
00664                     }
00665                     if (escaped) {
00666                         ch ^= AHDLC_TRANS;
00667                         escaped = 0;
00668                     }
00669 
00670                     /*
00671                      * Unless the peer lied to us about the negotiated MRU,
00672                      * we should never get a frame which is too long. If it
00673                      * happens, toss it away and grab the next incoming one.
00674                      */
00675                     if (rxcnt++ < dcb->dcb_rx_mru) {
00676                         /* Update calculated checksum and store character in buffer. */
00677                         tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
00678                         rxfcs >>= 8;
00679                         rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00680                         *rxptr++ = ch;
00681                     } else
00682                         inframe = 0;
00683                     continue;
00684                 }
00685 
00686                 if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
00687                     /*
00688                      * If the frame checksum is valid, create a NETBUF
00689                      * and pass it to the network specific receive handler.
00690                      */
00691                     rxcnt -= 2;
00692                     if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00693                         memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00694                         (*ifn->if_recv) (netdev, nb);
00695                     }
00696                 }
00697             }
00698 
00699             /*
00700              * If frame flag is received, resync frame processing
00701              */
00702             if (ch == AHDLC_FLAG) {
00703                 inframe = 1;
00704                 escaped = 0;
00705                 rxptr = rxbuf;
00706                 rxcnt = 0;
00707                 rxfcs = AHDLC_INITFCS;
00708             }
00709         }
00710 
00711         /* Signal the link driver that we are down. */
00712         netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00713 
00714         /* Disconnected, clean up. */
00715         if (rxbuf) {
00716             NutHeapFree(rxbuf);
00717             rxbuf = 0;
00718         }
00719     }
00720 }
00721 
00722 /*
00723  * \param dev Indicates the UART device.
00724  *
00725  * \return 0 on success, -1 otherwise.
00726  */
00727 static int AhdlcAvrGetStatus(NUTDEVICE * dev, uint32_t * status)
00728 {
00729     AHDLCDCB *dcb = dev->dev_dcb;
00730     uint8_t us;
00731 
00732     *status = 0;
00733 
00734 #ifdef __AVR_ENHANCED__
00735     if (dev->dev_base) {
00736 #ifdef UART1_CTS_BIT
00737         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00738             *status |= UART_CTSDISABLED;
00739         else
00740             *status |= UART_CTSENABLED;
00741 #endif
00742 #ifdef UART1_RTS_BIT
00743         if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00744             *status |= UART_RTSDISABLED;
00745         else
00746             *status |= UART_RTSENABLED;
00747 #endif
00748 #ifdef UART1_DTR_BIT
00749         if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00750             *status |= UART_DTRDISABLED;
00751         else
00752             *status |= UART_DTRENABLED;
00753 #endif
00754         us = inb(UCSR1A);
00755     } else
00756 #endif                          /* __AVR_ENHANCED__ */
00757     {
00758 #ifdef UART0_CTS_BIT
00759         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00760             *status |= UART_CTSDISABLED;
00761         else
00762             *status |= UART_CTSENABLED;
00763 #endif
00764 #ifdef UART0_RTS_BIT
00765         if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00766             *status |= UART_RTSDISABLED;
00767         else
00768             *status |= UART_RTSENABLED;
00769 #endif
00770 #ifdef UART0_DTR_BIT
00771         if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00772             *status |= UART_DTRDISABLED;
00773         else
00774             *status |= UART_DTRENABLED;
00775 #endif
00776         us = inb(USR);
00777     }
00778     if (us & FE)
00779         *status |= UART_FRAMINGERROR;
00780     if (us & DOR)
00781         *status |= UART_OVERRUNERROR;
00782     if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00783         *status |= UART_TXBUFFEREMPTY;
00784     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00785         *status |= UART_RXBUFFEREMPTY;
00786 
00787     return 0;
00788 }
00789 
00790 /*
00791  * \param dev Indicates the UART device.
00792  *
00793  * \return 0 on success, -1 otherwise.
00794  */
00795 static int AhdlcAvrSetStatus(NUTDEVICE * dev, uint32_t status)
00796 {
00797 #ifdef __AVR_ENHANCED__
00798     if (dev->dev_base) {
00799 #ifdef UART1_RTS_BIT
00800         if (status & UART_RTSDISABLED)
00801             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00802         else if (status & UART_RTSENABLED)
00803             cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00804 #endif
00805 #ifdef UART1_DTR_BIT
00806         if (status & UART_DTRDISABLED)
00807             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00808         else if (status & UART_DTRENABLED)
00809             cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00810 #endif
00811     } else
00812 #endif                          /* __AVR_ENHANCED__ */
00813     {
00814 #ifdef UART0_RTS_BIT
00815         if (status & UART_RTSDISABLED)
00816             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00817         else if (status & UART_RTSENABLED)
00818             cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00819 #endif
00820 #ifdef UART0_DTR_BIT
00821         if (status & UART_DTRDISABLED)
00822             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00823         else if (status & UART_DTRENABLED)
00824             cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00825 #endif
00826     }
00827     return 0;
00828 }
00829 
00830 /*
00831  * Carefully enable UART functions.
00832  */
00833 static void AhdlcAvrEnable(uint16_t base)
00834 {
00835     NutEnterCritical();
00836 
00837 #ifdef __AVR_ENHANCED__
00838     if (base) {
00839 #ifdef UART1_CTS_BIT
00840         sbi(EIMSK, UART1_CTS_BIT);
00841 #endif
00842         outb(UCSR1B, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00843     } else
00844 #endif                          /* __AVR_ENHANCED__ */
00845     {
00846 #ifdef UART0_CTS_BIT
00847         sbi(EIMSK, UART0_CTS_BIT);
00848 #endif
00849         outb(UCR, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00850     }
00851     NutExitCritical();
00852 }
00853 
00854 /*
00855  * Carefully disable UART functions.
00856  */
00857 static void AhdlcAvrDisable(uint16_t base)
00858 {
00859     /*
00860      * Disable UART interrupts.
00861      */
00862     NutEnterCritical();
00863 #ifdef __AVR_ENHANCED__
00864     if (base) {
00865 #ifdef UART1_CTS_BIT
00866         cbi(EIMSK, UART1_CTS_BIT);
00867 #endif
00868         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXCIE) | BV(UDRIE)));
00869     } else
00870 #endif                          /* __AVR_ENHANCED__ */
00871     {
00872 #ifdef UART0_CTS_BIT
00873         cbi(EIMSK, UART0_CTS_BIT);
00874 #endif
00875         outb(UCR, inb(UCR) & ~(BV(RXCIE) | BV(UDRIE)));
00876     }
00877     NutExitCritical();
00878 
00879     /*
00880      * Allow incoming or outgoing character to finish.
00881      */
00882     NutDelay(10);
00883 
00884     /*
00885      * Now disable UART functions.
00886      */
00887 #ifdef __AVR_ENHANCED__
00888     if (base)
00889         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXEN) | BV(TXEN)));
00890     else
00891 #endif                          /* __AVR_ENHANCED__ */
00892         outb(UCR, inb(UCR) & ~(BV(RXEN) | BV(TXEN)));
00893 }
00894 
00940 int AhdlcAvrIOCtl(NUTDEVICE * dev, int req, void *conf)
00941 {
00942     int rc = 0;
00943     AHDLCDCB *dcb;
00944     void **ppv = (void **) conf;
00945     uint32_t *lvp = (uint32_t *) conf;
00946     uint8_t bv;
00947     uint16_t sv;
00948     uint8_t devnum;
00949 
00950     if (dev == 0)
00951         dev = &devUart0;
00952 
00953     devnum = dev->dev_base;
00954     dcb = dev->dev_dcb;
00955 
00956     switch (req) {
00957     case UART_SETSPEED:
00958         AhdlcAvrDisable(devnum);
00959         sv = (uint16_t) ((((2UL * NutGetCpuClock()) / (*lvp * 16UL)) + 1UL) / 2UL) - 1;
00960 #ifdef __AVR_ENHANCED__
00961         if (devnum) {
00962             outb(UBRR1L, (uint8_t) sv);
00963             outb(UBRR1H, (uint8_t) (sv >> 8));
00964         } else {
00965             outb(UBRR0L, (uint8_t) sv);
00966             outb(UBRR0H, (uint8_t) (sv >> 8));
00967         }
00968 #else
00969         outb(UBRR, (uint8_t) sv);
00970 #endif
00971         AhdlcAvrEnable(devnum);
00972         break;
00973 
00974     case UART_GETSPEED:
00975 #ifdef __AVR_ENHANCED__
00976         if (devnum)
00977             sv = (uint16_t) inb(UBRR1H) << 8 | inb(UBRR1L);
00978         else
00979             sv = (uint16_t) inb(UBRR0H) << 8 | inb(UBRR0L);
00980 #else
00981         sv = inb(UBRR);
00982 #endif
00983         *lvp = NutGetCpuClock() / (16UL * (uint32_t) (sv + 1));
00984         break;
00985 
00986     case UART_SETDATABITS:
00987         AhdlcAvrDisable(devnum);
00988         bv = (uint8_t)(*lvp);
00989 #ifdef __AVR_ENHANCED__
00990         if (bv >= 5 && bv <= 8) {
00991             bv = (bv - 5) << 1;
00992             if (devnum) {
00993                 outb(UCSR1C, (inb(UCSR1C) & 0xF9) | bv);
00994                 outb(UCSR1B, inb(UCSR1B) & 0xFB);
00995             } else {
00996                 outb(UCSR0C, (inb(UCSR0C) & 0xF9) | bv);
00997                 outb(UCSR0B, inb(UCSR0B) & 0xFB);
00998             }
00999         } else
01000             rc = -1;
01001 #else
01002         if (bv != 8)
01003             rc = -1;
01004 #endif
01005         AhdlcAvrEnable(devnum);
01006         break;
01007 
01008     case UART_GETDATABITS:
01009 #ifdef __AVR_ENHANCED__
01010         if (devnum)
01011             *lvp = ((inb(UCSR1C) & 0x06) >> 1) + 5;
01012         else
01013             *lvp = ((inb(UCSR0C) & 0x06) >> 1) + 5;
01014 #else
01015         *lvp = 8;
01016 #endif
01017         break;
01018 
01019     case UART_SETPARITY:
01020         AhdlcAvrDisable(devnum);
01021         bv = (uint8_t)(*lvp);
01022 #ifdef __AVR_ENHANCED__
01023         if (bv <= 2) {
01024             if (bv == 1)
01025                 bv = 3;
01026             bv <<= 4;
01027             if (devnum)
01028                 outb(UCSR1C, (inb(UCSR1C) & 0xCF) | bv);
01029             else
01030                 outb(UCSR0C, (inb(UCSR0C) & 0xCF) | bv);
01031         } else
01032             rc = -1;
01033 #endif
01034         if (bv)
01035             rc = -1;
01036         AhdlcAvrEnable(devnum);
01037         break;
01038 
01039     case UART_GETPARITY:
01040 #ifdef __AVR_ENHANCED__
01041         if (devnum)
01042             bv = (inb(UCSR1C) & 0x30) >> 4;
01043         else
01044             bv = (inb(UCSR0C) & 0x30) >> 4;
01045         if (bv == 3)
01046             bv = 1;
01047 #else
01048         bv = 0;
01049 #endif
01050         *lvp = bv;
01051         break;
01052 
01053     case UART_SETSTOPBITS:
01054         AhdlcAvrDisable(devnum);
01055         bv = (uint8_t)(*lvp);
01056 #ifdef __AVR_ENHANCED__
01057         if (bv == 1 || bv == 2) {
01058             bv = (bv - 1) << 3;
01059             if (devnum)
01060                 outb(UCSR1C, (inb(UCSR1C) & 0xF7) | bv);
01061             else
01062                 outb(UCSR0C, (inb(UCSR0C) & 0xF7) | bv);
01063         } else
01064             rc = -1;
01065 #else
01066         if (bv != 1)
01067             rc = -1;
01068 #endif
01069         AhdlcAvrEnable(devnum);
01070         break;
01071 
01072     case UART_GETSTOPBITS:
01073 #ifdef __AVR_ENHANCED__
01074         if (devnum)
01075             *lvp = ((inb(UCSR1C) & 0x08) >> 3) + 1;
01076         else
01077             *lvp = ((inb(UCSR0C) & 0x08) >> 3) + 1;
01078 #else
01079         *lvp = 1;
01080 #endif
01081         break;
01082 
01083     case UART_GETSTATUS:
01084         AhdlcAvrGetStatus(dev, lvp);
01085         break;
01086     case UART_SETSTATUS:
01087         AhdlcAvrSetStatus(dev, *lvp);
01088         break;
01089 
01090     case UART_SETREADTIMEOUT:
01091         dcb->dcb_rtimeout = *lvp;
01092         break;
01093     case UART_GETREADTIMEOUT:
01094         *lvp = dcb->dcb_rtimeout;
01095         break;
01096 
01097     case UART_SETWRITETIMEOUT:
01098         dcb->dcb_wtimeout = *lvp;
01099         break;
01100     case UART_GETWRITETIMEOUT:
01101         *lvp = dcb->dcb_wtimeout;
01102         break;
01103 
01104     case UART_SETLOCALECHO:
01105         bv = (uint8_t)(*lvp);
01106         if (bv)
01107             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01108         else
01109             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01110         break;
01111     case UART_GETLOCALECHO:
01112         if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
01113             *lvp = 1;
01114         else
01115             *lvp = 0;
01116         break;
01117 
01118     case UART_SETFLOWCONTROL:
01119         bv = (uint8_t)(*lvp);
01120         if (bv)
01121             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01122         else
01123             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01124         break;
01125     case UART_GETFLOWCONTROL:
01126         break;
01127 
01128     case UART_SETRAWMODE:
01129         bv = (uint8_t)(*lvp);
01130         if (bv)
01131             dcb->dcb_modeflags |= UART_MF_RAWMODE;
01132         else
01133             dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
01134         break;
01135 
01136     case UART_GETRAWMODE:
01137         if (dcb->dcb_modeflags & UART_MF_RAWMODE)
01138             *lvp = 1;
01139         else
01140             *lvp = 0;
01141         break;
01142 
01143     case HDLC_SETIFNET:
01144         if (ppv && (*ppv != 0)) {
01145             dev->dev_icb = *ppv;
01146             dev->dev_type = IFTYP_NET;
01147             NutEventPost(&dcb->dcb_mf_evt);
01148         } else {
01149             dev->dev_type = IFTYP_CHAR;
01150 
01151             if (dev->dev_icb != 0)
01152             {
01153                 dev->dev_icb = 0;
01154 
01155                 /*
01156                  * Signal AHDLC Thread, so it can change it's state instantly
01157                  */
01158                 NutEventPost(&dcb->dcb_rx_rdy);
01159             }
01160         }
01161         break;
01162     case HDLC_GETIFNET:
01163         *ppv = dev->dev_icb;
01164         break;
01165 
01166     /* AVR host endian is little endian, and the ACCM should have been switched
01167      * to host endian when the value was read in. */
01168     case HDLC_SETTXACCM:
01169         dcb->dcb_tx_accm = (*lvp);
01170         break;
01171 
01172     case HDLC_GETTXACCM:
01173         (*lvp) = dcb->dcb_tx_accm;
01174         break;
01175 
01176     default:
01177         rc = -1;
01178         break;
01179     }
01180     return rc;
01181 }
01182 
01195 int AhdlcAvrInit(NUTDEVICE * dev)
01196 {
01197     int rc = 0;
01198     AHDLCDCB *dcb;
01199     uint32_t baudrate = 9600;
01200 
01201     /* Disable UART. */
01202     AhdlcAvrDisable(dev->dev_base);
01203 
01204     /* Initialize driver control block. */
01205     dcb = dev->dev_dcb;
01206     memset(dcb, 0, sizeof(AHDLCDCB));
01207     dcb->dcb_base = dev->dev_base;
01208     dcb->dcb_rx_buf = NutHeapAlloc(256);
01209     dcb->dcb_tx_buf = NutHeapAlloc(256);
01210     dcb->dcb_rx_mru = 1500;
01211     dcb->dcb_tx_mru = 1500;
01212     dcb->dcb_tx_accm = 0xFFFFFFFF;
01213 
01214     /*
01215      * Initialize UART handshake hardware and register interrupt handlers.
01216      */
01217     if (dev->dev_base) {
01218 #ifdef __AVR_ENHANCED__
01219 
01220 #ifdef UART1_CTS_BIT
01221         sbi(UART1_CTS_PORT, UART1_CTS_BIT);
01222         cbi(UART1_CTS_DDR, UART1_CTS_BIT);
01223         /* Falling edge will generate interrupts. */
01224 #if UART1_CTS_BIT == 4
01225         sbi(EICR, 1);
01226 #elif UART1_CTS_BIT == 5
01227         sbi(EICR, 3);
01228 #elif UART1_CTS_BIT == 6
01229         sbi(EICR, 5);
01230 #elif UART1_CTS_BIT == 7
01231         sbi(EICR, 7);
01232 #endif
01233 #endif
01234 #ifdef UART1_RTS_BIT
01235         sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01236         sbi(UART1_RTS_DDR, UART1_RTS_BIT);
01237 #endif
01238 #ifdef UART1_DTR_BIT
01239         sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01240         sbi(UART1_DTR_DDR, UART1_DTR_BIT);
01241 #endif
01242 
01243         if (NutRegisterIrqHandler(&sig_UART1_RECV, Rx1Complete, dcb))
01244             rc = -1;
01245         else if (NutRegisterIrqHandler(&sig_UART1_DATA, Tx1Complete, dcb))
01246 #ifdef UART1_CTS_BIT
01247             rc = -1;
01248         else if (NutRegisterIrqHandler(&UART1_CTS_SIGNAL, Cts1Interrupt, dev))
01249 #endif
01250 #endif                          /* __AVR_ENHANCED__ */
01251             rc = -1;
01252 
01253     } else {
01254 
01255 #ifdef UART0_CTS_BIT
01256         sbi(UART0_CTS_PORT, UART0_CTS_BIT);
01257         cbi(UART0_CTS_DDR, UART0_CTS_BIT);
01258 #if UART0_CTS_BIT == 4
01259         sbi(EICR, 1);
01260 #elif UART0_CTS_BIT == 5
01261         sbi(EICR, 3);
01262 #elif UART0_CTS_BIT == 6
01263         sbi(EICR, 5);
01264 #elif UART0_CTS_BIT == 7
01265         sbi(EICR, 7);
01266 #endif
01267 #endif
01268 #ifdef UART0_RTS_BIT
01269         sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01270         sbi(UART0_RTS_DDR, UART0_RTS_BIT);
01271 #endif
01272 #ifdef UART0_DTR_BIT
01273         sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01274         sbi(UART0_DTR_DDR, UART0_DTR_BIT);
01275 #endif
01276 
01277         if (NutRegisterIrqHandler(&sig_UART0_RECV, Rx0Complete, dcb))
01278             rc = -1;
01279         else if (NutRegisterIrqHandler(&sig_UART0_DATA, Tx0Complete, dcb))
01280             rc = -1;
01281 #ifdef UART0_CTS_BIT
01282         else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt, dev))
01283             rc = -1;
01284 #endif
01285     }
01286 
01287 
01288     /*
01289      * If we have been successful so far, start the HDLC receiver thread,
01290      * set the initial baudrate and enable the UART.
01291      */
01292     if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, 
01293         (NUT_THREAD_AHDLCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) {
01294         AhdlcAvrIOCtl(dev, UART_SETSPEED, &baudrate);
01295 
01296         return 0;
01297     }
01298 
01299     /* We failed, clean up. */
01300     if (dcb->dcb_rx_buf)
01301         NutHeapFree((void *) dcb->dcb_rx_buf);
01302     if (dcb->dcb_tx_buf)
01303         NutHeapFree((void *) dcb->dcb_tx_buf);
01304 
01305     return -1;
01306 }
01307 
01334 int AhdlcAvrRead(NUTFILE * fp, void *buffer, int size)
01335 {
01336     int rc = 0;
01337     AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
01338     uint8_t *cp = buffer;
01339 
01340     /*
01341      * Get characters from receive buffer.
01342      */
01343     if (buffer) {
01344         while (rc < size) {
01345             if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
01346                 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
01347                 rc++;
01348             } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
01349                 break;
01350         }
01351     }
01352 
01353     /*
01354      * Call without data buffer discards receive buffer.
01355      */
01356     else
01357         dcb->dcb_rd_idx = dcb->dcb_rx_idx;
01358 
01359     return rc;
01360 }
01361 
01374 int AhdlcAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01375 {
01376     int rc = 0;
01377     AHDLCDCB *dcb = dev->dev_dcb;
01378     CONST uint8_t *cp = buffer;
01379 
01380     /*
01381      * Put characters in transmit buffer.
01382      */
01383     if (buffer) {
01384         while (rc < len) {
01385             if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01386                 break;
01387             cp++;
01388             rc++;
01389         }
01390     }
01391 
01392     /*
01393      * Call without data pointer starts transmission.
01394      */
01395     else {
01396         /*
01397          * TODO: Check handshake.
01398          */
01399 #ifdef __AVR_ENHANCED__
01400         if (dev->dev_base)
01401             sbi(UCSR1B, UDRIE);
01402         else
01403 #endif
01404             sbi(UCR, UDRIE);
01405     }
01406     return rc;
01407 }
01408 
01428 int AhdlcAvrWrite(NUTFILE * fp, CONST void *buffer, int len)
01429 {
01430     return AhdlcAvrPut(fp->nf_dev, buffer, len, 0);
01431 }
01432 
01454 int AhdlcAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len)
01455 {
01456     return AhdlcAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);
01457 }
01458 
01475 NUTFILE *AhdlcAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01476 {
01477     NUTFILE *fp;
01478 
01479     if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01480         return NUTFILE_EOF;
01481 
01482     fp->nf_next = 0;
01483     fp->nf_dev = dev;
01484     fp->nf_fcb = 0;
01485 
01486     /* Enable handshake outputs. */
01487 #ifdef __AVR_ENHANCED__
01488     if (dev->dev_base) {
01489 #ifdef UART1_RTS_BIT
01490         cbi(UART1_RTS_PORT, UART1_RTS_BIT);
01491 #endif
01492 #ifdef UART1_DTR_BIT
01493         cbi(UART1_DTR_PORT, UART1_DTR_BIT);
01494 #endif
01495     } else
01496 #endif                          /* __AVR_ENHANCED__ */
01497     {
01498 #ifdef UART0_RTS_BIT
01499         cbi(UART0_RTS_PORT, UART0_RTS_BIT);
01500 #endif
01501 #ifdef UART0_DTR_BIT
01502         cbi(UART0_DTR_PORT, UART0_DTR_BIT);
01503 #endif
01504     }
01505     return fp;
01506 }
01507 
01521 int AhdlcAvrClose(NUTFILE * fp)
01522 {
01523     if (fp && fp != NUTFILE_EOF) {
01524         /* Disable handshake outputs. */
01525 #ifdef __AVR_ENHANCED__
01526         if (fp->nf_dev->dev_base) {
01527 #ifdef UART1_RTS_BIT
01528             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01529 #endif
01530 #ifdef UART1_DTR_BIT
01531             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01532 #endif
01533         } else
01534 #endif                          /* __AVR_ENHANCED__ */
01535         {
01536 #ifdef UART0_RTS_BIT
01537             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01538 #endif
01539 #ifdef UART0_DTR_BIT
01540             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01541 #endif
01542         }
01543         NutHeapFree(fp);
01544         return 0;
01545     }
01546     return -1;
01547 }
01548