Nut/OS  4.10.3
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              * Note that we also put the FCS into the receive buffer.
00608              */
00609             if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru + 2)) != 0) {
00610                 break;
00611             }
00612             NutSleep(1000);
00613         }
00614 
00615         /*
00616          * Signal the link driver that we are up.
00617          */
00618         ifn->if_send = AhdlcOutput;
00619         netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00620 
00621         for (;;) {
00622             /*
00623              * If we are still connected to a network, fetch the next
00624              * character from the buffer.
00625              */
00626             while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00627                 if (dev->dev_icb == 0)
00628                     break;
00629                 /* TODO: Check for idle timeout. */
00630                 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00631                     continue;
00632                 }
00633             }
00634 
00635             /*
00636              * Leave loop if network interface is detached
00637              */
00638             if (dev->dev_icb == 0)
00639                 break;
00640 
00641             /*
00642              * If RAW mode is active, we are not allowing any data encapsulation
00643              * processing. So we just sleep for a while.
00644              */
00645             if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00646                 /*
00647                  * It is a must to sleep here, because if we just yield it could create
00648                  * too much processing in here and stall processing elsewhere. This gives
00649                  * opportunity to other threads to process incoming data from USART.
00650                  */
00651                 NutSleep(100);
00652                 continue;
00653             }
00654 
00655             /*
00656              * Read next character from input buffer
00657              */
00658             ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00659 
00660             if (inframe) {
00661                 if (ch != AHDLC_FLAG) {
00662                     if (ch == AHDLC_ESCAPE) {
00663                         escaped = 1;
00664                         continue;
00665                     }
00666                     if (escaped) {
00667                         ch ^= AHDLC_TRANS;
00668                         escaped = 0;
00669                     }
00670 
00671                     /*
00672                      * Unless the peer lied to us about the negotiated MRU,
00673                      * we should never get a frame which is too long. If it
00674                      * happens, toss it away and grab the next incoming one.
00675                      */
00676                     if (rxcnt++ < dcb->dcb_rx_mru + 2) {
00677                         /* Update calculated checksum and store character in buffer. */
00678                         tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
00679                         rxfcs >>= 8;
00680                         rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00681                         *rxptr++ = ch;
00682                     } else
00683                         inframe = 0;
00684                     continue;
00685                 }
00686 
00687                 if (rxcnt >= 2 && rxfcs == AHDLC_GOODFCS) {
00688                     /*
00689                      * If the frame checksum is valid, create a NETBUF
00690                      * and pass it to the network specific receive handler.
00691                      */
00692                     rxcnt -= 2;
00693                     if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00694                         memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00695                         (*ifn->if_recv) (netdev, nb);
00696                     }
00697                 }
00698             }
00699 
00700             /*
00701              * If frame flag is received, resync frame processing
00702              */
00703             if (ch == AHDLC_FLAG) {
00704                 inframe = 1;
00705                 escaped = 0;
00706                 rxptr = rxbuf;
00707                 rxcnt = 0;
00708                 rxfcs = AHDLC_INITFCS;
00709             }
00710         }
00711 
00712         /* Signal the link driver that we are down. */
00713         netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00714 
00715         /* Disconnected, clean up. */
00716         if (rxbuf) {
00717             NutHeapFree(rxbuf);
00718             rxbuf = 0;
00719         }
00720     }
00721 }
00722 
00723 /*
00724  * \param dev Indicates the UART device.
00725  *
00726  * \return 0 on success, -1 otherwise.
00727  */
00728 static int AhdlcAvrGetStatus(NUTDEVICE * dev, uint32_t * status)
00729 {
00730     AHDLCDCB *dcb = dev->dev_dcb;
00731     uint8_t us;
00732 
00733     *status = 0;
00734 
00735 #ifdef __AVR_ENHANCED__
00736     if (dev->dev_base) {
00737 #ifdef UART1_CTS_BIT
00738         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00739             *status |= UART_CTSDISABLED;
00740         else
00741             *status |= UART_CTSENABLED;
00742 #endif
00743 #ifdef UART1_RTS_BIT
00744         if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00745             *status |= UART_RTSDISABLED;
00746         else
00747             *status |= UART_RTSENABLED;
00748 #endif
00749 #ifdef UART1_DTR_BIT
00750         if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00751             *status |= UART_DTRDISABLED;
00752         else
00753             *status |= UART_DTRENABLED;
00754 #endif
00755         us = inb(UCSR1A);
00756     } else
00757 #endif                          /* __AVR_ENHANCED__ */
00758     {
00759 #ifdef UART0_CTS_BIT
00760         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00761             *status |= UART_CTSDISABLED;
00762         else
00763             *status |= UART_CTSENABLED;
00764 #endif
00765 #ifdef UART0_RTS_BIT
00766         if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00767             *status |= UART_RTSDISABLED;
00768         else
00769             *status |= UART_RTSENABLED;
00770 #endif
00771 #ifdef UART0_DTR_BIT
00772         if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00773             *status |= UART_DTRDISABLED;
00774         else
00775             *status |= UART_DTRENABLED;
00776 #endif
00777         us = inb(USR);
00778     }
00779     if (us & FE)
00780         *status |= UART_FRAMINGERROR;
00781     if (us & DOR)
00782         *status |= UART_OVERRUNERROR;
00783     if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00784         *status |= UART_TXBUFFEREMPTY;
00785     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00786         *status |= UART_RXBUFFEREMPTY;
00787 
00788     return 0;
00789 }
00790 
00791 /*
00792  * \param dev Indicates the UART device.
00793  *
00794  * \return 0 on success, -1 otherwise.
00795  */
00796 static int AhdlcAvrSetStatus(NUTDEVICE * dev, uint32_t status)
00797 {
00798 #ifdef __AVR_ENHANCED__
00799     if (dev->dev_base) {
00800 #ifdef UART1_RTS_BIT
00801         if (status & UART_RTSDISABLED)
00802             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00803         else if (status & UART_RTSENABLED)
00804             cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00805 #endif
00806 #ifdef UART1_DTR_BIT
00807         if (status & UART_DTRDISABLED)
00808             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00809         else if (status & UART_DTRENABLED)
00810             cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00811 #endif
00812     } else
00813 #endif                          /* __AVR_ENHANCED__ */
00814     {
00815 #ifdef UART0_RTS_BIT
00816         if (status & UART_RTSDISABLED)
00817             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00818         else if (status & UART_RTSENABLED)
00819             cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00820 #endif
00821 #ifdef UART0_DTR_BIT
00822         if (status & UART_DTRDISABLED)
00823             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00824         else if (status & UART_DTRENABLED)
00825             cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00826 #endif
00827     }
00828     return 0;
00829 }
00830 
00831 /*
00832  * Carefully enable UART functions.
00833  */
00834 static void AhdlcAvrEnable(uint16_t base)
00835 {
00836     NutEnterCritical();
00837 
00838 #ifdef __AVR_ENHANCED__
00839     if (base) {
00840 #ifdef UART1_CTS_BIT
00841         sbi(EIMSK, UART1_CTS_BIT);
00842 #endif
00843         outb(UCSR1B, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00844     } else
00845 #endif                          /* __AVR_ENHANCED__ */
00846     {
00847 #ifdef UART0_CTS_BIT
00848         sbi(EIMSK, UART0_CTS_BIT);
00849 #endif
00850         outb(UCR, BV(RXCIE) | BV(RXEN) | BV(TXEN));
00851     }
00852     NutExitCritical();
00853 }
00854 
00855 /*
00856  * Carefully disable UART functions.
00857  */
00858 static void AhdlcAvrDisable(uint16_t base)
00859 {
00860     /*
00861      * Disable UART interrupts.
00862      */
00863     NutEnterCritical();
00864 #ifdef __AVR_ENHANCED__
00865     if (base) {
00866 #ifdef UART1_CTS_BIT
00867         cbi(EIMSK, UART1_CTS_BIT);
00868 #endif
00869         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXCIE) | BV(UDRIE)));
00870     } else
00871 #endif                          /* __AVR_ENHANCED__ */
00872     {
00873 #ifdef UART0_CTS_BIT
00874         cbi(EIMSK, UART0_CTS_BIT);
00875 #endif
00876         outb(UCR, inb(UCR) & ~(BV(RXCIE) | BV(UDRIE)));
00877     }
00878     NutExitCritical();
00879 
00880     /*
00881      * Allow incoming or outgoing character to finish.
00882      */
00883     NutDelay(10);
00884 
00885     /*
00886      * Now disable UART functions.
00887      */
00888 #ifdef __AVR_ENHANCED__
00889     if (base)
00890         outb(UCSR1B, inb(UCSR1B) & ~(BV(RXEN) | BV(TXEN)));
00891     else
00892 #endif                          /* __AVR_ENHANCED__ */
00893         outb(UCR, inb(UCR) & ~(BV(RXEN) | BV(TXEN)));
00894 }
00895 
00941 int AhdlcAvrIOCtl(NUTDEVICE * dev, int req, void *conf)
00942 {
00943     int rc = 0;
00944     AHDLCDCB *dcb;
00945     void **ppv = (void **) conf;
00946     uint32_t *lvp = (uint32_t *) conf;
00947     uint8_t bv;
00948     uint16_t sv;
00949     uint8_t devnum;
00950 
00951     if (dev == 0)
00952         dev = &devUart0;
00953 
00954     devnum = dev->dev_base;
00955     dcb = dev->dev_dcb;
00956 
00957     switch (req) {
00958     case UART_SETSPEED:
00959         AhdlcAvrDisable(devnum);
00960         sv = (uint16_t) ((((2UL * NutGetCpuClock()) / (*lvp * 16UL)) + 1UL) / 2UL) - 1;
00961 #ifdef __AVR_ENHANCED__
00962         if (devnum) {
00963             outb(UBRR1L, (uint8_t) sv);
00964             outb(UBRR1H, (uint8_t) (sv >> 8));
00965         } else {
00966             outb(UBRR0L, (uint8_t) sv);
00967             outb(UBRR0H, (uint8_t) (sv >> 8));
00968         }
00969 #else
00970         outb(UBRR, (uint8_t) sv);
00971 #endif
00972         AhdlcAvrEnable(devnum);
00973         break;
00974 
00975     case UART_GETSPEED:
00976 #ifdef __AVR_ENHANCED__
00977         if (devnum)
00978             sv = (uint16_t) inb(UBRR1H) << 8 | inb(UBRR1L);
00979         else
00980             sv = (uint16_t) inb(UBRR0H) << 8 | inb(UBRR0L);
00981 #else
00982         sv = inb(UBRR);
00983 #endif
00984         *lvp = NutGetCpuClock() / (16UL * (uint32_t) (sv + 1));
00985         break;
00986 
00987     case UART_SETDATABITS:
00988         AhdlcAvrDisable(devnum);
00989         bv = (uint8_t)(*lvp);
00990 #ifdef __AVR_ENHANCED__
00991         if (bv >= 5 && bv <= 8) {
00992             bv = (bv - 5) << 1;
00993             if (devnum) {
00994                 outb(UCSR1C, (inb(UCSR1C) & 0xF9) | bv);
00995                 outb(UCSR1B, inb(UCSR1B) & 0xFB);
00996             } else {
00997                 outb(UCSR0C, (inb(UCSR0C) & 0xF9) | bv);
00998                 outb(UCSR0B, inb(UCSR0B) & 0xFB);
00999             }
01000         } else
01001             rc = -1;
01002 #else
01003         if (bv != 8)
01004             rc = -1;
01005 #endif
01006         AhdlcAvrEnable(devnum);
01007         break;
01008 
01009     case UART_GETDATABITS:
01010 #ifdef __AVR_ENHANCED__
01011         if (devnum)
01012             *lvp = ((inb(UCSR1C) & 0x06) >> 1) + 5;
01013         else
01014             *lvp = ((inb(UCSR0C) & 0x06) >> 1) + 5;
01015 #else
01016         *lvp = 8;
01017 #endif
01018         break;
01019 
01020     case UART_SETPARITY:
01021         AhdlcAvrDisable(devnum);
01022         bv = (uint8_t)(*lvp);
01023 #ifdef __AVR_ENHANCED__
01024         if (bv <= 2) {
01025             if (bv == 1)
01026                 bv = 3;
01027             bv <<= 4;
01028             if (devnum)
01029                 outb(UCSR1C, (inb(UCSR1C) & 0xCF) | bv);
01030             else
01031                 outb(UCSR0C, (inb(UCSR0C) & 0xCF) | bv);
01032         } else
01033             rc = -1;
01034 #endif
01035         if (bv)
01036             rc = -1;
01037         AhdlcAvrEnable(devnum);
01038         break;
01039 
01040     case UART_GETPARITY:
01041 #ifdef __AVR_ENHANCED__
01042         if (devnum)
01043             bv = (inb(UCSR1C) & 0x30) >> 4;
01044         else
01045             bv = (inb(UCSR0C) & 0x30) >> 4;
01046         if (bv == 3)
01047             bv = 1;
01048 #else
01049         bv = 0;
01050 #endif
01051         *lvp = bv;
01052         break;
01053 
01054     case UART_SETSTOPBITS:
01055         AhdlcAvrDisable(devnum);
01056         bv = (uint8_t)(*lvp);
01057 #ifdef __AVR_ENHANCED__
01058         if (bv == 1 || bv == 2) {
01059             bv = (bv - 1) << 3;
01060             if (devnum)
01061                 outb(UCSR1C, (inb(UCSR1C) & 0xF7) | bv);
01062             else
01063                 outb(UCSR0C, (inb(UCSR0C) & 0xF7) | bv);
01064         } else
01065             rc = -1;
01066 #else
01067         if (bv != 1)
01068             rc = -1;
01069 #endif
01070         AhdlcAvrEnable(devnum);
01071         break;
01072 
01073     case UART_GETSTOPBITS:
01074 #ifdef __AVR_ENHANCED__
01075         if (devnum)
01076             *lvp = ((inb(UCSR1C) & 0x08) >> 3) + 1;
01077         else
01078             *lvp = ((inb(UCSR0C) & 0x08) >> 3) + 1;
01079 #else
01080         *lvp = 1;
01081 #endif
01082         break;
01083 
01084     case UART_GETSTATUS:
01085         AhdlcAvrGetStatus(dev, lvp);
01086         break;
01087     case UART_SETSTATUS:
01088         AhdlcAvrSetStatus(dev, *lvp);
01089         break;
01090 
01091     case UART_SETREADTIMEOUT:
01092         dcb->dcb_rtimeout = *lvp;
01093         break;
01094     case UART_GETREADTIMEOUT:
01095         *lvp = dcb->dcb_rtimeout;
01096         break;
01097 
01098     case UART_SETWRITETIMEOUT:
01099         dcb->dcb_wtimeout = *lvp;
01100         break;
01101     case UART_GETWRITETIMEOUT:
01102         *lvp = dcb->dcb_wtimeout;
01103         break;
01104 
01105     case UART_SETLOCALECHO:
01106         bv = (uint8_t)(*lvp);
01107         if (bv)
01108             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01109         else
01110             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01111         break;
01112     case UART_GETLOCALECHO:
01113         if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
01114             *lvp = 1;
01115         else
01116             *lvp = 0;
01117         break;
01118 
01119     case UART_SETFLOWCONTROL:
01120         bv = (uint8_t)(*lvp);
01121         if (bv)
01122             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
01123         else
01124             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
01125         break;
01126     case UART_GETFLOWCONTROL:
01127         break;
01128 
01129     case UART_SETRAWMODE:
01130         bv = (uint8_t)(*lvp);
01131         if (bv)
01132             dcb->dcb_modeflags |= UART_MF_RAWMODE;
01133         else
01134             dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
01135         break;
01136 
01137     case UART_GETRAWMODE:
01138         if (dcb->dcb_modeflags & UART_MF_RAWMODE)
01139             *lvp = 1;
01140         else
01141             *lvp = 0;
01142         break;
01143 
01144     case HDLC_SETIFNET:
01145         if (ppv && (*ppv != 0)) {
01146             dev->dev_icb = *ppv;
01147             dev->dev_type = IFTYP_NET;
01148             dcb->dcb_rx_mru = dcb->dcb_tx_mru = ((IFNET *)(((NUTDEVICE *)ppv)->dev_icb))->if_mtu;
01149             NutEventPost(&dcb->dcb_mf_evt);
01150         } else {
01151             dev->dev_type = IFTYP_CHAR;
01152 
01153             if (dev->dev_icb != 0)
01154             {
01155                 dev->dev_icb = 0;
01156 
01157                 /*
01158                  * Signal AHDLC Thread, so it can change it's state instantly
01159                  */
01160                 NutEventPost(&dcb->dcb_rx_rdy);
01161             }
01162         }
01163         break;
01164     case HDLC_GETIFNET:
01165         *ppv = dev->dev_icb;
01166         break;
01167 
01168     /* AVR host endian is little endian, and the ACCM should have been switched
01169      * to host endian when the value was read in. */
01170     case HDLC_SETTXACCM:
01171         dcb->dcb_tx_accm = (*lvp);
01172         break;
01173 
01174     case HDLC_GETTXACCM:
01175         (*lvp) = dcb->dcb_tx_accm;
01176         break;
01177 
01178     default:
01179         rc = -1;
01180         break;
01181     }
01182     return rc;
01183 }
01184 
01197 int AhdlcAvrInit(NUTDEVICE * dev)
01198 {
01199     int rc = 0;
01200     AHDLCDCB *dcb;
01201     uint32_t baudrate = 9600;
01202 
01203     /* Disable UART. */
01204     AhdlcAvrDisable(dev->dev_base);
01205 
01206     /* Initialize driver control block. */
01207     dcb = dev->dev_dcb;
01208     memset(dcb, 0, sizeof(AHDLCDCB));
01209     dcb->dcb_base = dev->dev_base;
01210     dcb->dcb_rx_buf = NutHeapAlloc(256);
01211     dcb->dcb_tx_buf = NutHeapAlloc(256);
01212     dcb->dcb_rx_mru = dcb->dcb_tx_mru = ((IFNET *)dev->dev_icb)->if_mtu;
01213     dcb->dcb_tx_accm = 0xFFFFFFFF;
01214 
01215     /*
01216      * Initialize UART handshake hardware and register interrupt handlers.
01217      */
01218     if (dev->dev_base) {
01219 #ifdef __AVR_ENHANCED__
01220 
01221 #ifdef UART1_CTS_BIT
01222         sbi(UART1_CTS_PORT, UART1_CTS_BIT);
01223         cbi(UART1_CTS_DDR, UART1_CTS_BIT);
01224         /* Falling edge will generate interrupts. */
01225 #if UART1_CTS_BIT == 4
01226         sbi(EICR, 1);
01227 #elif UART1_CTS_BIT == 5
01228         sbi(EICR, 3);
01229 #elif UART1_CTS_BIT == 6
01230         sbi(EICR, 5);
01231 #elif UART1_CTS_BIT == 7
01232         sbi(EICR, 7);
01233 #endif
01234 #endif
01235 #ifdef UART1_RTS_BIT
01236         sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01237         sbi(UART1_RTS_DDR, UART1_RTS_BIT);
01238 #endif
01239 #ifdef UART1_DTR_BIT
01240         sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01241         sbi(UART1_DTR_DDR, UART1_DTR_BIT);
01242 #endif
01243 
01244         if (NutRegisterIrqHandler(&sig_UART1_RECV, Rx1Complete, dcb))
01245             rc = -1;
01246         else if (NutRegisterIrqHandler(&sig_UART1_DATA, Tx1Complete, dcb))
01247 #ifdef UART1_CTS_BIT
01248             rc = -1;
01249         else if (NutRegisterIrqHandler(&UART1_CTS_SIGNAL, Cts1Interrupt, dev))
01250 #endif
01251 #endif                          /* __AVR_ENHANCED__ */
01252             rc = -1;
01253 
01254     } else {
01255 
01256 #ifdef UART0_CTS_BIT
01257         sbi(UART0_CTS_PORT, UART0_CTS_BIT);
01258         cbi(UART0_CTS_DDR, UART0_CTS_BIT);
01259 #if UART0_CTS_BIT == 4
01260         sbi(EICR, 1);
01261 #elif UART0_CTS_BIT == 5
01262         sbi(EICR, 3);
01263 #elif UART0_CTS_BIT == 6
01264         sbi(EICR, 5);
01265 #elif UART0_CTS_BIT == 7
01266         sbi(EICR, 7);
01267 #endif
01268 #endif
01269 #ifdef UART0_RTS_BIT
01270         sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01271         sbi(UART0_RTS_DDR, UART0_RTS_BIT);
01272 #endif
01273 #ifdef UART0_DTR_BIT
01274         sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01275         sbi(UART0_DTR_DDR, UART0_DTR_BIT);
01276 #endif
01277 
01278         if (NutRegisterIrqHandler(&sig_UART0_RECV, Rx0Complete, dcb))
01279             rc = -1;
01280         else if (NutRegisterIrqHandler(&sig_UART0_DATA, Tx0Complete, dcb))
01281             rc = -1;
01282 #ifdef UART0_CTS_BIT
01283         else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt, dev))
01284             rc = -1;
01285 #endif
01286     }
01287 
01288 
01289     /*
01290      * If we have been successful so far, start the HDLC receiver thread,
01291      * set the initial baudrate and enable the UART.
01292      */
01293     if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, 
01294         (NUT_THREAD_AHDLCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) {
01295         AhdlcAvrIOCtl(dev, UART_SETSPEED, &baudrate);
01296 
01297         return 0;
01298     }
01299 
01300     /* We failed, clean up. */
01301     if (dcb->dcb_rx_buf)
01302         NutHeapFree((void *) dcb->dcb_rx_buf);
01303     if (dcb->dcb_tx_buf)
01304         NutHeapFree((void *) dcb->dcb_tx_buf);
01305 
01306     return -1;
01307 }
01308 
01335 int AhdlcAvrRead(NUTFILE * fp, void *buffer, int size)
01336 {
01337     int rc = 0;
01338     AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
01339     uint8_t *cp = buffer;
01340 
01341     /*
01342      * Get characters from receive buffer.
01343      */
01344     if (buffer) {
01345         while (rc < size) {
01346             if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
01347                 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
01348                 rc++;
01349             } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
01350                 break;
01351         }
01352     }
01353 
01354     /*
01355      * Call without data buffer discards receive buffer.
01356      */
01357     else
01358         dcb->dcb_rd_idx = dcb->dcb_rx_idx;
01359 
01360     return rc;
01361 }
01362 
01375 int AhdlcAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01376 {
01377     int rc = 0;
01378     AHDLCDCB *dcb = dev->dev_dcb;
01379     CONST uint8_t *cp = buffer;
01380 
01381     /*
01382      * Put characters in transmit buffer.
01383      */
01384     if (buffer) {
01385         while (rc < len) {
01386             if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01387                 break;
01388             cp++;
01389             rc++;
01390         }
01391     }
01392 
01393     /*
01394      * Call without data pointer starts transmission.
01395      */
01396     else {
01397         /*
01398          * TODO: Check handshake.
01399          */
01400 #ifdef __AVR_ENHANCED__
01401         if (dev->dev_base)
01402             sbi(UCSR1B, UDRIE);
01403         else
01404 #endif
01405             sbi(UCR, UDRIE);
01406     }
01407     return rc;
01408 }
01409 
01429 int AhdlcAvrWrite(NUTFILE * fp, CONST void *buffer, int len)
01430 {
01431     return AhdlcAvrPut(fp->nf_dev, buffer, len, 0);
01432 }
01433 
01455 int AhdlcAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len)
01456 {
01457     return AhdlcAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);
01458 }
01459 
01476 NUTFILE *AhdlcAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01477 {
01478     NUTFILE *fp;
01479 
01480     if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01481         return NUTFILE_EOF;
01482 
01483     fp->nf_next = 0;
01484     fp->nf_dev = dev;
01485     fp->nf_fcb = 0;
01486 
01487     /* Enable handshake outputs. */
01488 #ifdef __AVR_ENHANCED__
01489     if (dev->dev_base) {
01490 #ifdef UART1_RTS_BIT
01491         cbi(UART1_RTS_PORT, UART1_RTS_BIT);
01492 #endif
01493 #ifdef UART1_DTR_BIT
01494         cbi(UART1_DTR_PORT, UART1_DTR_BIT);
01495 #endif
01496     } else
01497 #endif                          /* __AVR_ENHANCED__ */
01498     {
01499 #ifdef UART0_RTS_BIT
01500         cbi(UART0_RTS_PORT, UART0_RTS_BIT);
01501 #endif
01502 #ifdef UART0_DTR_BIT
01503         cbi(UART0_DTR_PORT, UART0_DTR_BIT);
01504 #endif
01505     }
01506     return fp;
01507 }
01508 
01522 int AhdlcAvrClose(NUTFILE * fp)
01523 {
01524     if (fp && fp != NUTFILE_EOF) {
01525         /* Disable handshake outputs. */
01526 #ifdef __AVR_ENHANCED__
01527         if (fp->nf_dev->dev_base) {
01528 #ifdef UART1_RTS_BIT
01529             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01530 #endif
01531 #ifdef UART1_DTR_BIT
01532             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01533 #endif
01534         } else
01535 #endif                          /* __AVR_ENHANCED__ */
01536         {
01537 #ifdef UART0_RTS_BIT
01538             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01539 #endif
01540 #ifdef UART0_DTR_BIT
01541             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01542 #endif
01543         }
01544         NutHeapFree(fp);
01545         return 0;
01546     }
01547     return -1;
01548 }
01549