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 
00087 #include <string.h>
00088 #include <stdlib.h>
00089 
00090 #include <sys/nutconfig.h>
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 
00112 /*
00113  * FCS lookup table located in program memory space.
00114  */
00115 static prog_char fcstab[512] = {
00116     0x00, 0x00, 0x11, 0x89, 0x23, 0x12, 0x32, 0x9b, 0x46, 0x24, 0x57, 0xad, 0x65, 0x36, 0x74, 0xbf,
00117     0x8c, 0x48, 0x9d, 0xc1, 0xaf, 0x5a, 0xbe, 0xd3, 0xca, 0x6c, 0xdb, 0xe5, 0xe9, 0x7e, 0xf8, 0xf7,
00118     0x10, 0x81, 0x01, 0x08, 0x33, 0x93, 0x22, 0x1a, 0x56, 0xa5, 0x47, 0x2c, 0x75, 0xb7, 0x64, 0x3e,
00119     0x9c, 0xc9, 0x8d, 0x40, 0xbf, 0xdb, 0xae, 0x52, 0xda, 0xed, 0xcb, 0x64, 0xf9, 0xff, 0xe8, 0x76,
00120     0x21, 0x02, 0x30, 0x8b, 0x02, 0x10, 0x13, 0x99, 0x67, 0x26, 0x76, 0xaf, 0x44, 0x34, 0x55, 0xbd,
00121     0xad, 0x4a, 0xbc, 0xc3, 0x8e, 0x58, 0x9f, 0xd1, 0xeb, 0x6e, 0xfa, 0xe7, 0xc8, 0x7c, 0xd9, 0xf5,
00122     0x31, 0x83, 0x20, 0x0a, 0x12, 0x91, 0x03, 0x18, 0x77, 0xa7, 0x66, 0x2e, 0x54, 0xb5, 0x45, 0x3c,
00123     0xbd, 0xcb, 0xac, 0x42, 0x9e, 0xd9, 0x8f, 0x50, 0xfb, 0xef, 0xea, 0x66, 0xd8, 0xfd, 0xc9, 0x74,
00124 
00125     0x42, 0x04, 0x53, 0x8d, 0x61, 0x16, 0x70, 0x9f, 0x04, 0x20, 0x15, 0xa9, 0x27, 0x32, 0x36, 0xbb,
00126     0xce, 0x4c, 0xdf, 0xc5, 0xed, 0x5e, 0xfc, 0xd7, 0x88, 0x68, 0x99, 0xe1, 0xab, 0x7a, 0xba, 0xf3,
00127     0x52, 0x85, 0x43, 0x0c, 0x71, 0x97, 0x60, 0x1e, 0x14, 0xa1, 0x05, 0x28, 0x37, 0xb3, 0x26, 0x3a,
00128     0xde, 0xcd, 0xcf, 0x44, 0xfd, 0xdf, 0xec, 0x56, 0x98, 0xe9, 0x89, 0x60, 0xbb, 0xfb, 0xaa, 0x72,
00129     0x63, 0x06, 0x72, 0x8f, 0x40, 0x14, 0x51, 0x9d, 0x25, 0x22, 0x34, 0xab, 0x06, 0x30, 0x17, 0xb9,
00130     0xef, 0x4e, 0xfe, 0xc7, 0xcc, 0x5c, 0xdd, 0xd5, 0xa9, 0x6a, 0xb8, 0xe3, 0x8a, 0x78, 0x9b, 0xf1,
00131     0x73, 0x87, 0x62, 0x0e, 0x50, 0x95, 0x41, 0x1c, 0x35, 0xa3, 0x24, 0x2a, 0x16, 0xb1, 0x07, 0x38,
00132     0xff, 0xcf, 0xee, 0x46, 0xdc, 0xdd, 0xcd, 0x54, 0xb9, 0xeb, 0xa8, 0x62, 0x9a, 0xf9, 0x8b, 0x70,
00133 
00134     0x84, 0x08, 0x95, 0x81, 0xa7, 0x1a, 0xb6, 0x93, 0xc2, 0x2c, 0xd3, 0xa5, 0xe1, 0x3e, 0xf0, 0xb7,
00135     0x08, 0x40, 0x19, 0xc9, 0x2b, 0x52, 0x3a, 0xdb, 0x4e, 0x64, 0x5f, 0xed, 0x6d, 0x76, 0x7c, 0xff,
00136     0x94, 0x89, 0x85, 0x00, 0xb7, 0x9b, 0xa6, 0x12, 0xd2, 0xad, 0xc3, 0x24, 0xf1, 0xbf, 0xe0, 0x36,
00137     0x18, 0xc1, 0x09, 0x48, 0x3b, 0xd3, 0x2a, 0x5a, 0x5e, 0xe5, 0x4f, 0x6c, 0x7d, 0xf7, 0x6c, 0x7e,
00138     0xa5, 0x0a, 0xb4, 0x83, 0x86, 0x18, 0x97, 0x91, 0xe3, 0x2e, 0xf2, 0xa7, 0xc0, 0x3c, 0xd1, 0xb5,
00139     0x29, 0x42, 0x38, 0xcb, 0x0a, 0x50, 0x1b, 0xd9, 0x6f, 0x66, 0x7e, 0xef, 0x4c, 0x74, 0x5d, 0xfd,
00140     0xb5, 0x8b, 0xa4, 0x02, 0x96, 0x99, 0x87, 0x10, 0xf3, 0xaf, 0xe2, 0x26, 0xd0, 0xbd, 0xc1, 0x34,
00141     0x39, 0xc3, 0x28, 0x4a, 0x1a, 0xd1, 0x0b, 0x58, 0x7f, 0xe7, 0x6e, 0x6e, 0x5c, 0xf5, 0x4d, 0x7c,
00142 
00143     0xc6, 0x0c, 0xd7, 0x85, 0xe5, 0x1e, 0xf4, 0x97, 0x80, 0x28, 0x91, 0xa1, 0xa3, 0x3a, 0xb2, 0xb3,
00144     0x4a, 0x44, 0x5b, 0xcd, 0x69, 0x56, 0x78, 0xdf, 0x0c, 0x60, 0x1d, 0xe9, 0x2f, 0x72, 0x3e, 0xfb,
00145     0xd6, 0x8d, 0xc7, 0x04, 0xf5, 0x9f, 0xe4, 0x16, 0x90, 0xa9, 0x81, 0x20, 0xb3, 0xbb, 0xa2, 0x32,
00146     0x5a, 0xc5, 0x4b, 0x4c, 0x79, 0xd7, 0x68, 0x5e, 0x1c, 0xe1, 0x0d, 0x68, 0x3f, 0xf3, 0x2e, 0x7a,
00147     0xe7, 0x0e, 0xf6, 0x87, 0xc4, 0x1c, 0xd5, 0x95, 0xa1, 0x2a, 0xb0, 0xa3, 0x82, 0x38, 0x93, 0xb1,
00148     0x6b, 0x46, 0x7a, 0xcf, 0x48, 0x54, 0x59, 0xdd, 0x2d, 0x62, 0x3c, 0xeb, 0x0e, 0x70, 0x1f, 0xf9,
00149     0xf7, 0x8f, 0xe6, 0x06, 0xd4, 0x9d, 0xc5, 0x14, 0xb1, 0xab, 0xa0, 0x22, 0x92, 0xb9, 0x83, 0x30,
00150     0x7b, 0xc7, 0x6a, 0x4e, 0x58, 0xd5, 0x49, 0x5c, 0x3d, 0xe3, 0x2c, 0x6a, 0x1e, 0xf1, 0x0f, 0x78
00151 };
00152 
00156 #define IN_ACC_MAP(c, m) (( ((uint8_t) (c)) < 0x20)  && ((m) & (1UL << (c))) != 0)
00157 
00158 #ifndef NUT_THREAD_AHDLCRXSTACK
00159 #define NUT_THREAD_AHDLCRXSTACK     512
00160 #endif
00161 
00162 /*
00163  * Handle AVR UART0 transmit complete interrupts.
00164  */
00165 static void Tx0Complete(void *arg)
00166 {
00167     AHDLCDCB *dcb = arg;
00168 
00169     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00170 #ifdef UART0_CTS_BIT
00171         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT)) {
00172             cbi(UCR, UDRIE);
00173             return;
00174         }
00175 #endif
00176         outp(dcb->dcb_tx_buf[dcb->dcb_tx_idx], UDR);
00177         dcb->dcb_tx_idx++;
00178     } else {
00179         cbi(UCR, UDRIE);
00180         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00181     }
00182 }
00183 
00184 #ifdef UART0_CTS_BIT
00185 /*
00186  * Handle AVR UART0 transmit handshake interrupts.
00187  */
00188 static void Cts0Interrupt(void *arg)
00189 {
00190     sbi(UCR, UDRIE);
00191 }
00192 #endif
00193 
00194 #ifdef __AVR_ENHANCED__
00195 /*
00196  * Handle AVR UART1 transmit complete interrupts.
00197  */
00198 static void Tx1Complete(void *arg)
00199 {
00200     register AHDLCDCB *dcb = arg;
00201 
00202     if (dcb->dcb_tx_idx != dcb->dcb_wr_idx) {
00203 #ifdef UART1_CTS_BIT
00204         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT)) {
00205             cbi(UCSR1B, UDRIE);
00206             return;
00207         }
00208 #endif
00209         outp(dcb->dcb_tx_buf[dcb->dcb_tx_idx], UDR1);
00210         dcb->dcb_tx_idx++;
00211     } else {
00212         cbi(UCSR1B, UDRIE);
00213         NutEventPostFromIrq(&dcb->dcb_tx_rdy);
00214     }
00215 }
00216 
00217 #ifdef UART1_CTS_BIT
00218 /*
00219  * Handle AVR UART1 transmit handshake interrupts.
00220  */
00221 static void Cts1Interrupt(void *arg)
00222 {
00223     sbi(UCSR1B, UDRIE);
00224 }
00225 #endif
00226 
00227 #endif                          /* __AVR_ENHANCED__ */
00228 
00229 /*
00230  * Handle AVR UART0 receive complete interrupts.
00231  */
00232 static void Rx0Complete(void *arg)
00233 {
00234     AHDLCDCB *dcb = arg;
00235 
00236     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inp(UDR);
00237     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00238         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00239     /* Late increment fixes ICCAVR bug on volatile variables. */
00240     dcb->dcb_rx_idx++;
00241 }
00242 
00243 #ifdef __AVR_ENHANCED__
00244 /*
00245  * Handle AVR UART1 receive complete interrupts.
00246  */
00247 static void Rx1Complete(void *arg)
00248 {
00249     AHDLCDCB *dcb = arg;
00250 
00251     dcb->dcb_rx_buf[dcb->dcb_rx_idx] = inp(UDR1);
00252     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00253         NutEventPostFromIrq(&dcb->dcb_rx_rdy);
00254     /* Late increment fixes ICCAVR bug on volatile variables. */
00255     dcb->dcb_rx_idx++;
00256 }
00257 #endif                          /* __AVR_ENHANCED__ */
00258 
00259 /*
00260  * \return 0 on success, -1 in case of any errors.
00261  */
00262 static int SendRawByte(AHDLCDCB * dcb, uint8_t ch, uint8_t flush)
00263 {
00264     /*
00265      * If transmit buffer is full, wait until interrupt routine
00266      * signals an empty buffer or until a timeout occurs.
00267      */
00268     while ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00269         if (NutEventWait(&dcb->dcb_tx_rdy, dcb->dcb_wtimeout))
00270             break;
00271     }
00272 
00273     /*
00274      * If transmit buffer is still full, we have a write timeout.
00275      */
00276     if ((uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00277         return -1;
00278     }
00279 
00280     /*
00281      * Buffer has room for more data. Put the byte in the buffer
00282      * and increment the write index.
00283      */
00284     dcb->dcb_tx_buf[dcb->dcb_wr_idx] = ch;
00285     dcb->dcb_wr_idx++;
00286 
00287     /*
00288      * If transmit buffer has become full and the transmitter
00289      * is not active, then activate it.
00290      */
00291     if (flush || (uint8_t) (dcb->dcb_wr_idx + 1) == dcb->dcb_tx_idx) {
00292 
00293         /*
00294          * TODO: Check handshake.
00295          */
00296         NutEnterCritical();
00297 #ifdef __AVR_ENHANCED__
00298         if (dcb->dcb_base)
00299             sbi(UCSR1B, UDRIE);
00300         else
00301 #endif
00302             sbi(UCR, UDRIE);
00303         NutExitCritical();
00304     }
00305     return 0;
00306 }
00307 
00308 /*
00309  * Characters are properly escaped and checksum is updated.
00310  *
00311  * \return 0 on success, -1 in case of any errors.
00312  */
00313 static int SendHdlcData(AHDLCDCB * dcb, CONST uint8_t * data, uint16_t len, uint16_t * txfcs)
00314 {
00315     uint16_t tbx;
00316     register uint16_t fcs;
00317 
00318     if (txfcs)
00319         fcs = *txfcs;
00320     else
00321         fcs = 0;
00322     while (len) {
00323         tbx = (uint16_t) ((uint8_t) fcs ^ *data) << 1;
00324         fcs >>= 8;
00325         fcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00326         if (IN_ACC_MAP(*data, dcb->dcb_tx_accm) || *data == AHDLC_FLAG || *data == AHDLC_ESCAPE) {
00327             if (SendRawByte(dcb, AHDLC_ESCAPE, 0))
00328                 return -1;
00329             if (SendRawByte(dcb, *data ^ AHDLC_TRANS, 0))
00330                 return -1;
00331         } else if (SendRawByte(dcb, *data, 0))
00332             return -1;
00333         data++;
00334         len--;
00335     }
00336     if (txfcs)
00337         *txfcs = fcs;
00338 
00339     return 0;
00340 }
00341 
00352 int AhdlcOutput(NUTDEVICE * dev, NETBUF * nb)
00353 {
00354     uint16_t txfcs;
00355     AHDLCDCB *dcb = dev->dev_dcb;
00356     uint16_t sz;
00357 
00358     /*
00359      * If we are in RAW mode we are not allowed to send AHDLC output.
00360      * We just emulate packet loss behaviour in here.
00361      */
00362     if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00363         return 0;
00364     }
00365 
00366     /*
00367      * Calculate the number of bytes to be send. Do not
00368      * send packets larger than transmit mru.
00369      */
00370     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00371 
00372     if (sz > dcb->dcb_tx_mru) {
00373         return -1;
00374     }
00375 
00376     /*
00377      * TODO: If transmitter is running, we may omit the flag.
00378      */
00379     SendRawByte(dcb, AHDLC_FLAG, 0);
00380 
00381     /* Initialize the checksum and send the NETBUF. */
00382     txfcs = AHDLC_INITFCS;
00383     if (SendHdlcData(dcb, nb->nb_dl.vp, nb->nb_dl.sz, &txfcs))
00384         return -1;
00385     if (SendHdlcData(dcb, nb->nb_nw.vp, nb->nb_nw.sz, &txfcs))
00386         return -1;
00387     if (SendHdlcData(dcb, nb->nb_tp.vp, nb->nb_tp.sz, &txfcs))
00388         return -1;
00389     if (SendHdlcData(dcb, nb->nb_ap.vp, nb->nb_ap.sz, &txfcs))
00390         return -1;
00391 
00392     /* Send the checksum and the final flag. */
00393     txfcs ^= 0xffff;
00394     if (SendHdlcData(dcb, (uint8_t *) & txfcs, 2, 0))
00395         return -1;
00396     SendRawByte(dcb, AHDLC_FLAG, 1);
00397 
00398     return 0;
00399 }
00400 
00407 THREAD(AhdlcRx, arg)
00408 {
00409     NUTDEVICE *dev = arg;
00410     NUTDEVICE *netdev;
00411     AHDLCDCB *dcb = dev->dev_dcb;
00412     IFNET *ifn;
00413     NETBUF *nb;
00414     uint8_t *rxbuf;
00415     uint8_t *rxptr;
00416     uint16_t rxcnt;
00417     uint8_t ch;
00418     uint16_t tbx;
00419     uint8_t inframe;
00420     uint8_t escaped;
00421     uint16_t rxfcs;
00422 
00423     NutThreadSetPriority(9);
00424     for (;;) {
00425         /*
00426          * Reset variables to their initial state
00427          */
00428         rxptr = 0;
00429         rxcnt = 0;
00430         escaped = 0;
00431         rxfcs = AHDLC_INITFCS;
00432         inframe = 0;
00433 
00434         for (;;) {
00435             /*
00436              * Wait until the network interface has been attached.
00437              * This will be initiated by the application calling
00438              * NutNetIfConfig(), which in turn calls a HDLC_SETIFNET
00439              * ioctl() to store the NUTDEVICE pointer of the network
00440              * device in dev_icb and trigger an event on dcb_mf_evt.
00441              */
00442             while ((netdev = dev->dev_icb) == 0) {
00443                 NutEventWait(&dcb->dcb_mf_evt, 1000);
00444             }
00445             ifn = netdev->dev_icb;
00446             dcb->dcb_rtimeout = 1000;
00447             inframe = 0;
00448 
00449             /*
00450              * Allocate the receive buffer, if this fails, we are in a
00451              * low memory situation. Take a nap and see, if the
00452              * situation improved.
00453              */
00454             if ((rxbuf = NutHeapAlloc(dcb->dcb_rx_mru)) != 0) {
00455                 break;
00456             }
00457             NutSleep(1000);
00458         }
00459 
00460         /*
00461          * Signal the link driver that we are up.
00462          */
00463         ifn->if_send = AhdlcOutput;
00464         netdev->dev_ioctl(netdev, LCP_LOWERUP, 0);
00465 
00466         for (;;) {
00467             /*
00468              * If we are still connected to a network, fetch the next
00469              * character from the buffer.
00470              */
00471             while (dcb->dcb_rd_idx == dcb->dcb_rx_idx) {
00472                 if (dev->dev_icb == 0)
00473                     break;
00474                 /* TODO: Check for idle timeout. */
00475                 if (NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout)) {
00476                     continue;
00477                 }
00478             }
00479 
00480             /*
00481              * Leave loop if network interface is detached
00482              */
00483             if (dev->dev_icb == 0)
00484                 break;
00485 
00486             /*
00487              * If RAW mode is active, we are not allowing any data encapsulation
00488              * processing. So we just sleep for a while.
00489              */
00490             if (dcb->dcb_modeflags & UART_MF_RAWMODE) {
00491                 /*
00492                  * It is a must to sleep here, because if we just yield it could create
00493                  * too much processing in here and stall processing elsewhere. This gives
00494                  * opportunity to other threads to process incoming data from USART.
00495                  */
00496                 NutSleep(100);
00497                 continue;
00498             }
00499 
00500             /*
00501              * Read next character from input buffer
00502              */
00503             ch = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
00504 
00505             if (inframe) {
00506                 if (ch != AHDLC_FLAG) {
00507                     if (ch == AHDLC_ESCAPE) {
00508                         escaped = 1;
00509                         continue;
00510                     }
00511                     if (escaped) {
00512                         ch ^= AHDLC_TRANS;
00513                         escaped = 0;
00514                     }
00515 
00516                     /*
00517                      * Unless the peer lied to us about the negotiated MRU,
00518                      * we should never get a frame which is too long. If it
00519                      * happens, toss it away and grab the next incoming one.
00520                      */
00521                     if (rxcnt++ < dcb->dcb_rx_mru) {
00522                         /* Update calculated checksum and store character in buffer. */
00523                         tbx = (uint16_t) ((uint8_t) rxfcs ^ ch) << 1;
00524                         rxfcs >>= 8;
00525                         rxfcs ^= ((uint16_t) PRG_RDB(fcstab + tbx) << 8) | PRG_RDB(fcstab + tbx + 1);
00526                         *rxptr++ = ch;
00527                     } else
00528                         inframe = 0;
00529                     continue;
00530                 }
00531 
00532                 if (rxcnt > 6 && rxfcs == AHDLC_GOODFCS) {
00533                     /*
00534                      * If the frame checksum is valid, create a NETBUF
00535                      * and pass it to the network specific receive handler.
00536                      */
00537                     rxcnt -= 2;
00538                     if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, rxcnt)) != 0) {
00539                         memcpy(nb->nb_dl.vp, rxbuf, rxcnt);
00540                         (*ifn->if_recv) (netdev, nb);
00541                     }
00542                 }
00543             }
00544 
00545             /*
00546              * If frame flag is received, resync frame processing
00547              */
00548             if (ch == AHDLC_FLAG) {
00549                 inframe = 1;
00550                 escaped = 0;
00551                 rxptr = rxbuf;
00552                 rxcnt = 0;
00553                 rxfcs = AHDLC_INITFCS;
00554             }
00555         }
00556 
00557         /* Signal the link driver that we are down. */
00558         netdev->dev_ioctl(netdev, LCP_LOWERDOWN, 0);
00559 
00560         /* Disconnected, clean up. */
00561         if (rxbuf) {
00562             NutHeapFree(rxbuf);
00563             rxbuf = 0;
00564         }
00565     }
00566 }
00567 
00568 /*
00569  * \param dev Indicates the UART device.
00570  *
00571  * \return 0 on success, -1 otherwise.
00572  */
00573 static int AhdlcAvrGetStatus(NUTDEVICE * dev, uint32_t * status)
00574 {
00575     AHDLCDCB *dcb = dev->dev_dcb;
00576     uint8_t us;
00577 
00578     *status = 0;
00579 
00580 #ifdef __AVR_ENHANCED__
00581     if (dev->dev_base) {
00582 #ifdef UART1_CTS_BIT
00583         if (bit_is_set(UART1_CTS_PIN, UART1_CTS_BIT))
00584             *status |= UART_CTSDISABLED;
00585         else
00586             *status |= UART_CTSENABLED;
00587 #endif
00588 #ifdef UART1_RTS_BIT
00589         if (bit_is_set(UART1_RTS_PORT, UART1_RTS_BIT))
00590             *status |= UART_RTSDISABLED;
00591         else
00592             *status |= UART_RTSENABLED;
00593 #endif
00594 #ifdef UART1_DTR_BIT
00595         if (bit_is_set(UART1_DTR_PORT, UART1_DTR_BIT))
00596             *status |= UART_DTRDISABLED;
00597         else
00598             *status |= UART_DTRENABLED;
00599 #endif
00600         us = inp(UCSR1A);
00601     } else
00602 #endif                          /* __AVR_ENHANCED__ */
00603     {
00604 #ifdef UART0_CTS_BIT
00605         if (bit_is_set(UART0_CTS_PIN, UART0_CTS_BIT))
00606             *status |= UART_CTSDISABLED;
00607         else
00608             *status |= UART_CTSENABLED;
00609 #endif
00610 #ifdef UART0_RTS_BIT
00611         if (bit_is_set(UART0_RTS_PORT, UART0_RTS_BIT))
00612             *status |= UART_RTSDISABLED;
00613         else
00614             *status |= UART_RTSENABLED;
00615 #endif
00616 #ifdef UART0_DTR_BIT
00617         if (bit_is_set(UART0_DTR_PORT, UART0_DTR_BIT))
00618             *status |= UART_DTRDISABLED;
00619         else
00620             *status |= UART_DTRENABLED;
00621 #endif
00622         us = inp(USR);
00623     }
00624     if (us & FE)
00625         *status |= UART_FRAMINGERROR;
00626     if (us & DOR)
00627         *status |= UART_OVERRUNERROR;
00628     if (dcb->dcb_tx_idx == dcb->dcb_wr_idx)
00629         *status |= UART_TXBUFFEREMPTY;
00630     if (dcb->dcb_rd_idx == dcb->dcb_rx_idx)
00631         *status |= UART_RXBUFFEREMPTY;
00632 
00633     return 0;
00634 }
00635 
00636 /*
00637  * \param dev Indicates the UART device.
00638  *
00639  * \return 0 on success, -1 otherwise.
00640  */
00641 static int AhdlcAvrSetStatus(NUTDEVICE * dev, uint32_t status)
00642 {
00643 #ifdef __AVR_ENHANCED__
00644     if (dev->dev_base) {
00645 #ifdef UART1_RTS_BIT
00646         if (status & UART_RTSDISABLED)
00647             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
00648         else if (status & UART_RTSENABLED)
00649             cbi(UART1_RTS_PORT, UART1_RTS_BIT);
00650 #endif
00651 #ifdef UART1_DTR_BIT
00652         if (status & UART_DTRDISABLED)
00653             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
00654         else if (status & UART_DTRENABLED)
00655             cbi(UART1_DTR_PORT, UART1_DTR_BIT);
00656 #endif
00657     } else
00658 #endif                          /* __AVR_ENHANCED__ */
00659     {
00660 #ifdef UART0_RTS_BIT
00661         if (status & UART_RTSDISABLED)
00662             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
00663         else if (status & UART_RTSENABLED)
00664             cbi(UART0_RTS_PORT, UART0_RTS_BIT);
00665 #endif
00666 #ifdef UART0_DTR_BIT
00667         if (status & UART_DTRDISABLED)
00668             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
00669         else if (status & UART_DTRENABLED)
00670             cbi(UART0_DTR_PORT, UART0_DTR_BIT);
00671 #endif
00672     }
00673     return 0;
00674 }
00675 
00676 /*
00677  * Carefully enable UART functions.
00678  */
00679 static void AhdlcAvrEnable(uint16_t base)
00680 {
00681     NutEnterCritical();
00682 
00683 #ifdef __AVR_ENHANCED__
00684     if (base) {
00685 #ifdef UART1_CTS_BIT
00686         sbi(EIMSK, UART1_CTS_BIT);
00687 #endif
00688         outp(BV(RXCIE) | BV(RXEN) | BV(TXEN), UCSR1B);
00689     } else
00690 #endif                          /* __AVR_ENHANCED__ */
00691     {
00692 #ifdef UART0_CTS_BIT
00693         sbi(EIMSK, UART0_CTS_BIT);
00694 #endif
00695         outp(BV(RXCIE) | BV(RXEN) | BV(TXEN), UCR);
00696     }
00697     NutExitCritical();
00698 }
00699 
00700 /*
00701  * Carefully disable UART functions.
00702  */
00703 static void AhdlcAvrDisable(uint16_t base)
00704 {
00705     /*
00706      * Disable UART interrupts.
00707      */
00708     NutEnterCritical();
00709 #ifdef __AVR_ENHANCED__
00710     if (base) {
00711 #ifdef UART1_CTS_BIT
00712         cbi(EIMSK, UART1_CTS_BIT);
00713 #endif
00714         outp(inp(UCSR1B) & ~(BV(RXCIE) | BV(UDRIE)), UCSR1B);
00715     } else
00716 #endif                          /* __AVR_ENHANCED__ */
00717     {
00718 #ifdef UART0_CTS_BIT
00719         cbi(EIMSK, UART0_CTS_BIT);
00720 #endif
00721         outp(inp(UCR) & ~(BV(RXCIE) | BV(UDRIE)), UCR);
00722     }
00723     NutExitCritical();
00724 
00725     /*
00726      * Allow incoming or outgoing character to finish.
00727      */
00728     NutDelay(10);
00729 
00730     /*
00731      * Now disable UART functions.
00732      */
00733 #ifdef __AVR_ENHANCED__
00734     if (base)
00735         outp(inp(UCSR1B) & ~(BV(RXEN) | BV(TXEN)), UCSR1B);
00736     else
00737 #endif                          /* __AVR_ENHANCED__ */
00738         outp(inp(UCR) & ~(BV(RXEN) | BV(TXEN)), UCR);
00739 }
00740 
00784 int AhdlcAvrIOCtl(NUTDEVICE * dev, int req, void *conf)
00785 {
00786     int rc = 0;
00787     AHDLCDCB *dcb;
00788     void **ppv = (void **) conf;
00789     uint32_t *lvp = (uint32_t *) conf;
00790     uint8_t bv;
00791     uint16_t sv;
00792     uint8_t devnum;
00793 
00794     if (dev == 0)
00795         dev = &devUart0;
00796 
00797     devnum = dev->dev_base;
00798     dcb = dev->dev_dcb;
00799 
00800     switch (req) {
00801     case UART_SETSPEED:
00802         AhdlcAvrDisable(devnum);
00803         sv = (uint16_t) ((((2UL * NutGetCpuClock()) / (*lvp * 16UL)) + 1UL) / 2UL) - 1;
00804 #ifdef __AVR_ENHANCED__
00805         if (devnum) {
00806             outp((uint8_t) sv, UBRR1L);
00807             outp((uint8_t) (sv >> 8), UBRR1H);
00808         } else {
00809             outp((uint8_t) sv, UBRR0L);
00810             outp((uint8_t) (sv >> 8), UBRR0H);
00811         }
00812 #else
00813         outp((uint8_t) sv, UBRR);
00814 #endif
00815         AhdlcAvrEnable(devnum);
00816         break;
00817 
00818     case UART_GETSPEED:
00819 #ifdef __AVR_ENHANCED__
00820         if (devnum)
00821             sv = (uint16_t) inp(UBRR1H) << 8 | inp(UBRR1L);
00822         else
00823             sv = (uint16_t) inp(UBRR0H) << 8 | inp(UBRR0L);
00824 #else
00825         sv = inp(UBRR);
00826 #endif
00827         *lvp = NutGetCpuClock() / (16UL * (uint32_t) (sv + 1));
00828         break;
00829 
00830     case UART_SETDATABITS:
00831         AhdlcAvrDisable(devnum);
00832         bv = (uint8_t)(*lvp);
00833 #ifdef __AVR_ENHANCED__
00834         if (bv >= 5 && bv <= 8) {
00835             bv = (bv - 5) << 1;
00836             if (devnum) {
00837                 outp((inp(UCSR1C) & 0xF9) | bv, UCSR1C);
00838                 outp(inp(UCSR1B) & 0xFB, UCSR1B);
00839             } else {
00840                 outp((inp(UCSR0C) & 0xF9) | bv, UCSR0C);
00841                 outp(inp(UCSR0B) & 0xFB, UCSR0B);
00842             }
00843         } else
00844             rc = -1;
00845 #else
00846         if (bv != 8)
00847             rc = -1;
00848 #endif
00849         AhdlcAvrEnable(devnum);
00850         break;
00851 
00852     case UART_GETDATABITS:
00853 #ifdef __AVR_ENHANCED__
00854         if (devnum)
00855             *lvp = ((inp(UCSR1C) & 0x06) >> 1) + 5;
00856         else
00857             *lvp = ((inp(UCSR0C) & 0x06) >> 1) + 5;
00858 #else
00859         *lvp = 8;
00860 #endif
00861         break;
00862 
00863     case UART_SETPARITY:
00864         AhdlcAvrDisable(devnum);
00865         bv = (uint8_t)(*lvp);
00866 #ifdef __AVR_ENHANCED__
00867         if (bv <= 2) {
00868             if (bv == 1)
00869                 bv = 3;
00870             bv <<= 4;
00871             if (devnum)
00872                 outp((inp(UCSR1C) & 0xCF) | bv, UCSR1C);
00873             else
00874                 outp((inp(UCSR0C) & 0xCF) | bv, UCSR0C);
00875         } else
00876             rc = -1;
00877 #endif
00878         if (bv)
00879             rc = -1;
00880         AhdlcAvrEnable(devnum);
00881         break;
00882 
00883     case UART_GETPARITY:
00884 #ifdef __AVR_ENHANCED__
00885         if (devnum)
00886             bv = (inp(UCSR1C) & 0x30) >> 4;
00887         else
00888             bv = (inp(UCSR0C) & 0x30) >> 4;
00889         if (bv == 3)
00890             bv = 1;
00891 #else
00892         bv = 0;
00893 #endif
00894         *lvp = bv;
00895         break;
00896 
00897     case UART_SETSTOPBITS:
00898         AhdlcAvrDisable(devnum);
00899         bv = (uint8_t)(*lvp);
00900 #ifdef __AVR_ENHANCED__
00901         if (bv == 1 || bv == 2) {
00902             bv = (bv - 1) << 3;
00903             if (devnum)
00904                 outp((inp(UCSR1C) & 0xF7) | bv, UCSR1C);
00905             else
00906                 outp((inp(UCSR0C) & 0xF7) | bv, UCSR0C);
00907         } else
00908             rc = -1;
00909 #else
00910         if (bv != 1)
00911             rc = -1;
00912 #endif
00913         AhdlcAvrEnable(devnum);
00914         break;
00915 
00916     case UART_GETSTOPBITS:
00917 #ifdef __AVR_ENHANCED__
00918         if (devnum)
00919             *lvp = ((inp(UCSR1C) & 0x08) >> 3) + 1;
00920         else
00921             *lvp = ((inp(UCSR0C) & 0x08) >> 3) + 1;
00922 #else
00923         *lvp = 1;
00924 #endif
00925         break;
00926 
00927     case UART_GETSTATUS:
00928         AhdlcAvrGetStatus(dev, lvp);
00929         break;
00930     case UART_SETSTATUS:
00931         AhdlcAvrSetStatus(dev, *lvp);
00932         break;
00933 
00934     case UART_SETREADTIMEOUT:
00935         dcb->dcb_rtimeout = *lvp;
00936         break;
00937     case UART_GETREADTIMEOUT:
00938         *lvp = dcb->dcb_rtimeout;
00939         break;
00940 
00941     case UART_SETWRITETIMEOUT:
00942         dcb->dcb_wtimeout = *lvp;
00943         break;
00944     case UART_GETWRITETIMEOUT:
00945         *lvp = dcb->dcb_wtimeout;
00946         break;
00947 
00948     case UART_SETLOCALECHO:
00949         bv = (uint8_t)(*lvp);
00950         if (bv)
00951             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00952         else
00953             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00954         break;
00955     case UART_GETLOCALECHO:
00956         if (dcb->dcb_modeflags & UART_MF_LOCALECHO)
00957             *lvp = 1;
00958         else
00959             *lvp = 0;
00960         break;
00961 
00962     case UART_SETFLOWCONTROL:
00963         bv = (uint8_t)(*lvp);
00964         if (bv)
00965             dcb->dcb_modeflags |= UART_MF_LOCALECHO;
00966         else
00967             dcb->dcb_modeflags &= ~UART_MF_LOCALECHO;
00968         break;
00969     case UART_GETFLOWCONTROL:
00970         break;
00971 
00972     case UART_SETRAWMODE:
00973         bv = (uint8_t)(*lvp);
00974         if (bv)
00975             dcb->dcb_modeflags |= UART_MF_RAWMODE;
00976         else
00977             dcb->dcb_modeflags &= ~UART_MF_RAWMODE;
00978         break;
00979 
00980     case UART_GETRAWMODE:
00981         if (dcb->dcb_modeflags & UART_MF_RAWMODE)
00982             *lvp = 1;
00983         else
00984             *lvp = 0;
00985         break;
00986 
00987     case HDLC_SETIFNET:
00988         if (ppv && (*ppv != 0)) {
00989             dev->dev_icb = *ppv;
00990             dev->dev_type = IFTYP_NET;
00991             NutEventPost(&dcb->dcb_mf_evt);
00992         } else {
00993             dev->dev_type = IFTYP_CHAR;
00994 
00995             if (dev->dev_icb != 0)
00996             {
00997                 dev->dev_icb = 0;
00998 
00999                 /*
01000                  * Signal AHDLC Thread, so it can change it's state instantly
01001                  */
01002                 NutEventPost(&dcb->dcb_rx_rdy);
01003             }
01004         }
01005         break;
01006     case HDLC_GETIFNET:
01007         *ppv = dev->dev_icb;
01008         break;
01009 
01010     default:
01011         rc = -1;
01012         break;
01013     }
01014     return rc;
01015 }
01016 
01029 int AhdlcAvrInit(NUTDEVICE * dev)
01030 {
01031     int rc = 0;
01032     AHDLCDCB *dcb;
01033     uint32_t baudrate = 9600;
01034 
01035     /* Disable UART. */
01036     AhdlcAvrDisable(dev->dev_base);
01037 
01038     /* Initialize driver control block. */
01039     dcb = dev->dev_dcb;
01040     memset(dcb, 0, sizeof(AHDLCDCB));
01041     dcb->dcb_base = dev->dev_base;
01042     dcb->dcb_rx_buf = NutHeapAlloc(256);
01043     dcb->dcb_tx_buf = NutHeapAlloc(256);
01044     dcb->dcb_rx_mru = 1500;
01045     dcb->dcb_tx_mru = 1500;
01046     dcb->dcb_tx_accm = 0xFFFFFFFF;
01047 
01048     /*
01049      * Initialize UART handshake hardware and register interrupt handlers.
01050      */
01051     if (dev->dev_base) {
01052 #ifdef __AVR_ENHANCED__
01053 
01054 #ifdef UART1_CTS_BIT
01055         sbi(UART1_CTS_PORT, UART1_CTS_BIT);
01056         cbi(UART1_CTS_DDR, UART1_CTS_BIT);
01057         /* Falling edge will generate interrupts. */
01058 #if UART1_CTS_BIT == 4
01059         sbi(EICR, 1);
01060 #elif UART1_CTS_BIT == 5
01061         sbi(EICR, 3);
01062 #elif UART1_CTS_BIT == 6
01063         sbi(EICR, 5);
01064 #elif UART1_CTS_BIT == 7
01065         sbi(EICR, 7);
01066 #endif
01067 #endif
01068 #ifdef UART1_RTS_BIT
01069         sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01070         sbi(UART1_RTS_DDR, UART1_RTS_BIT);
01071 #endif
01072 #ifdef UART1_DTR_BIT
01073         sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01074         sbi(UART1_DTR_DDR, UART1_DTR_BIT);
01075 #endif
01076 
01077         if (NutRegisterIrqHandler(&sig_UART1_RECV, Rx1Complete, dcb))
01078             rc = -1;
01079         else if (NutRegisterIrqHandler(&sig_UART1_DATA, Tx1Complete, dcb))
01080 #ifdef UART1_CTS_BIT
01081             rc = -1;
01082         else if (NutRegisterIrqHandler(&UART1_CTS_SIGNAL, Cts1Interrupt, dev))
01083 #endif
01084 #endif                          /* __AVR_ENHANCED__ */
01085             rc = -1;
01086 
01087     } else {
01088 
01089 #ifdef UART0_CTS_BIT
01090         sbi(UART0_CTS_PORT, UART0_CTS_BIT);
01091         cbi(UART0_CTS_DDR, UART0_CTS_BIT);
01092 #if UART0_CTS_BIT == 4
01093         sbi(EICR, 1);
01094 #elif UART0_CTS_BIT == 5
01095         sbi(EICR, 3);
01096 #elif UART0_CTS_BIT == 6
01097         sbi(EICR, 5);
01098 #elif UART0_CTS_BIT == 7
01099         sbi(EICR, 7);
01100 #endif
01101 #endif
01102 #ifdef UART0_RTS_BIT
01103         sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01104         sbi(UART0_RTS_DDR, UART0_RTS_BIT);
01105 #endif
01106 #ifdef UART0_DTR_BIT
01107         sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01108         sbi(UART0_DTR_DDR, UART0_DTR_BIT);
01109 #endif
01110 
01111         if (NutRegisterIrqHandler(&sig_UART0_RECV, Rx0Complete, dcb))
01112             rc = -1;
01113         else if (NutRegisterIrqHandler(&sig_UART0_DATA, Tx0Complete, dcb))
01114             rc = -1;
01115 #ifdef UART0_CTS_BIT
01116         else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt, dev))
01117             rc = -1;
01118 #endif
01119     }
01120 
01121 
01122     /*
01123      * If we have been successful so far, start the HDLC receiver thread,
01124      * set the initial baudrate and enable the UART.
01125      */
01126     if (rc == 0 && NutThreadCreate("ahdlcrx", AhdlcRx, dev, 
01127         (NUT_THREAD_AHDLCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD)) {
01128         AhdlcAvrIOCtl(dev, UART_SETSPEED, &baudrate);
01129 
01130         return 0;
01131     }
01132 
01133     /* We failed, clean up. */
01134     if (dcb->dcb_rx_buf)
01135         NutHeapFree((void *) dcb->dcb_rx_buf);
01136     if (dcb->dcb_tx_buf)
01137         NutHeapFree((void *) dcb->dcb_tx_buf);
01138 
01139     return -1;
01140 }
01141 
01168 int AhdlcAvrRead(NUTFILE * fp, void *buffer, int size)
01169 {
01170     int rc = 0;
01171     AHDLCDCB *dcb = fp->nf_dev->dev_dcb;
01172     uint8_t *cp = buffer;
01173 
01174     /*
01175      * Get characters from receive buffer.
01176      */
01177     if (buffer) {
01178         while (rc < size) {
01179             if (dcb->dcb_rd_idx != dcb->dcb_rx_idx) {
01180                 *cp++ = dcb->dcb_rx_buf[dcb->dcb_rd_idx++];
01181                 rc++;
01182             } else if (rc || NutEventWait(&dcb->dcb_rx_rdy, dcb->dcb_rtimeout))
01183                 break;
01184         }
01185     }
01186 
01187     /*
01188      * Call without data buffer discards receive buffer.
01189      */
01190     else
01191         dcb->dcb_rd_idx = dcb->dcb_rx_idx;
01192 
01193     return rc;
01194 }
01195 
01208 int AhdlcAvrPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
01209 {
01210     int rc = 0;
01211     AHDLCDCB *dcb = dev->dev_dcb;
01212     CONST uint8_t *cp = buffer;
01213 
01214     /*
01215      * Put characters in transmit buffer.
01216      */
01217     if (buffer) {
01218         while (rc < len) {
01219             if (SendRawByte(dcb, pflg ? PRG_RDB(cp) : *cp, 0))
01220                 break;
01221             cp++;
01222             rc++;
01223         }
01224     }
01225 
01226     /*
01227      * Call without data pointer starts transmission.
01228      */
01229     else {
01230         /*
01231          * TODO: Check handshake.
01232          */
01233 #ifdef __AVR_ENHANCED__
01234         if (dev->dev_base)
01235             sbi(UCSR1B, UDRIE);
01236         else
01237 #endif
01238             sbi(UCR, UDRIE);
01239     }
01240     return rc;
01241 }
01242 
01262 int AhdlcAvrWrite(NUTFILE * fp, CONST void *buffer, int len)
01263 {
01264     return AhdlcAvrPut(fp->nf_dev, buffer, len, 0);
01265 }
01266 
01288 int AhdlcAvrWrite_P(NUTFILE * fp, PGM_P buffer, int len)
01289 {
01290     return AhdlcAvrPut(fp->nf_dev, (CONST char *) buffer, len, 1);
01291 }
01292 
01309 NUTFILE *AhdlcAvrOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
01310 {
01311     NUTFILE *fp;
01312 
01313     if ((fp = NutHeapAlloc(sizeof(NUTFILE))) == 0)
01314         return NUTFILE_EOF;
01315 
01316     fp->nf_next = 0;
01317     fp->nf_dev = dev;
01318     fp->nf_fcb = 0;
01319 
01320     /* Enable handshake outputs. */
01321 #ifdef __AVR_ENHANCED__
01322     if (dev->dev_base) {
01323 #ifdef UART1_RTS_BIT
01324         cbi(UART1_RTS_PORT, UART1_RTS_BIT);
01325 #endif
01326 #ifdef UART1_DTR_BIT
01327         cbi(UART1_DTR_PORT, UART1_DTR_BIT);
01328 #endif
01329     } else
01330 #endif                          /* __AVR_ENHANCED__ */
01331     {
01332 #ifdef UART0_RTS_BIT
01333         cbi(UART0_RTS_PORT, UART0_RTS_BIT);
01334 #endif
01335 #ifdef UART0_DTR_BIT
01336         cbi(UART0_DTR_PORT, UART0_DTR_BIT);
01337 #endif
01338     }
01339     return fp;
01340 }
01341 
01355 int AhdlcAvrClose(NUTFILE * fp)
01356 {
01357     if (fp && fp != NUTFILE_EOF) {
01358         /* Disable handshake outputs. */
01359 #ifdef __AVR_ENHANCED__
01360         if (fp->nf_dev->dev_base) {
01361 #ifdef UART1_RTS_BIT
01362             sbi(UART1_RTS_PORT, UART1_RTS_BIT);
01363 #endif
01364 #ifdef UART1_DTR_BIT
01365             sbi(UART1_DTR_PORT, UART1_DTR_BIT);
01366 #endif
01367         } else
01368 #endif                          /* __AVR_ENHANCED__ */
01369         {
01370 #ifdef UART0_RTS_BIT
01371             sbi(UART0_RTS_PORT, UART0_RTS_BIT);
01372 #endif
01373 #ifdef UART0_DTR_BIT
01374             sbi(UART0_DTR_PORT, UART0_DTR_BIT);
01375 #endif
01376         }
01377         NutHeapFree(fp);
01378         return 0;
01379     }
01380     return -1;
01381 }
01382 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/