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

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