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

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