Nut/OS  4.10.3
API Reference
cs8900.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002-2003 by Call Direct Cellular Solutions Pty. Ltd. 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. All advertising materials mentioning features or use of this
00014  *    software must display the following acknowledgement:
00015  *
00016  *    This product includes software developed by Call Direct Cellular Solutions Pty. Ltd.
00017  *    and its contributors.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY CALL DIRECT CELLULAR SOLUTIONS AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CALL DIRECT
00023  * CELLULAR SOLUTIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.calldirect.com.au/
00033  *
00034  * -
00035  * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
00036  *
00037  * Redistribution and use in source and binary forms, with or without
00038  * modification, are permitted provided that the following conditions
00039  * are met:
00040  *
00041  * 1. Redistributions of source code must retain the above copyright
00042  *    notice, this list of conditions and the following disclaimer.
00043  * 2. Redistributions in binary form must reproduce the above copyright
00044  *    notice, this list of conditions and the following disclaimer in the
00045  *    documentation and/or other materials provided with the distribution.
00046  * 3. All advertising materials mentioning features or use of this
00047  *    software must display the following acknowledgement:
00048  *
00049  *    This product includes software developed by egnite Software GmbH
00050  *    and its contributors.
00051  *
00052  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00053  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00054  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00055  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00056  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00057  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00058  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00059  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00060  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00061  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00062  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00063  * SUCH DAMAGE.
00064  *
00065  * For additional information see http://www.ethernut.de/
00066  *
00067  * -
00068  * Portions Copyright (C) 2000 David J. Hudson <dave@humbug.demon.co.uk>
00069  *
00070  * This file is distributed in the hope that it will be useful, but WITHOUT
00071  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00072  * FITNESS FOR A PARTICULAR PURPOSE.
00073  *
00074  * You can redistribute this file and/or modify it under the terms of the GNU
00075  * General Public License (GPL) as published by the Free Software Foundation;
00076  * either version 2 of the License, or (at your discretion) any later version.
00077  * See the accompanying file "copying-gpl.txt" for more details.
00078  *
00079  * As a special exception to the GPL, permission is granted for additional
00080  * uses of the text contained in this file.  See the accompanying file
00081  * "copying-liquorice.txt" for details.
00082  * -
00083  * Portions Copyright (c) 1983, 1993 by
00084  *      The Regents of the University of California.  All rights reserved.
00085  *
00086  * Redistribution and use in source and binary forms, with or without
00087  * modification, are permitted provided that the following conditions
00088  * are met:
00089  * 1. Redistributions of source code must retain the above copyright
00090  *    notice, this list of conditions and the following disclaimer.
00091  * 2. Redistributions in binary form must reproduce the above copyright
00092  *    notice, this list of conditions and the following disclaimer in the
00093  *    documentation and/or other materials provided with the distribution.
00094  * 3. All advertising materials mentioning features or use of this software
00095  *    must display the following acknowledgement:
00096  *      This product includes software developed by the University of
00097  *      California, Berkeley and its contributors.
00098  * 4. Neither the name of the University nor the names of its contributors
00099  *    may be used to endorse or promote products derived from this software
00100  *    without specific prior written permission.
00101  *
00102  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00103  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00104  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00105  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00106  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00107  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00108  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00109  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00110  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00111  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00112  * SUCH DAMAGE.
00113  * -
00114  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
00115  *
00116  * Permission to use, copy, modify, and distribute this software for any
00117  * purpose with or without fee is hereby granted, provided that the above
00118  * copyright notice and this permission notice appear in all copies, and that
00119  * the name of Digital Equipment Corporation not be used in advertising or
00120  * publicity pertaining to distribution of the document or software without
00121  * specific, written prior permission.
00122  * 
00123  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
00124  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
00125  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
00126  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00127  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00128  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00129  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00130  * SOFTWARE.
00131  */
00132 
00133 /*
00134  * $Log$
00135  * Revision 1.4  2009/01/17 11:26:37  haraldkipp
00136  * Getting rid of two remaining BSD types in favor of stdint.
00137  * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
00138  *
00139  * Revision 1.3  2008/08/11 06:59:14  haraldkipp
00140  * BSD types replaced by stdint types (feature request #1282721).
00141  *
00142  * Revision 1.2  2006/10/08 16:48:07  haraldkipp
00143  * Documentation fixed
00144  *
00145  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00146  * Moved from dev.
00147  *
00148  * Revision 1.9  2005/04/30 16:42:41  chaac
00149  * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
00150  * is defined in NutConf, it will make effect where it is used.
00151  *
00152  * Revision 1.8  2004/05/26 09:40:30  olereinhardt
00153  * Changed reading of packet length / receive status to be compatible with
00154  * newer AVRGCC versions. (Need to read high byte first!)
00155  *
00156  * Added software reset / wakeup routine to init code. (only avalilable in new code)
00157  *
00158  * Revision 1.7  2004/05/25 11:39:47  olereinhardt
00159  * Define NUT_CS8900_OLD to get the old functionality back again
00160  *
00161  * Revision 1.6  2004/05/24 17:09:17  olereinhardt
00162  * Changed base address handling in cs8900.c and moved cs8900.h to /include/dev
00163  * Base address can now be passed to the nic driver by NutRegisterDevice.
00164  * Removed some Assembler code in cs8900.c
00165  *
00166  * Added some databus waitstate settings for the upper half of the address space in os/arch/avr_nutinit.c. Now three waitstates are default for 0x8000-0xFFFF
00167  *
00168  * Added terminal device driver for hd44780 compatible LCD displays directly
00169  * connected to the memory bus (memory mapped). See hd44780.c for more information.
00170  * Therefore some minor changed in include/dev/term.h and dev/term.c are needet to
00171  * pass a base address to the lcd driver.
00172  *
00173  * Revision 1.5  2004/03/18 14:06:52  haraldkipp
00174  * Deprecated header file replaced
00175  *
00176  * Revision 1.4  2003/10/13 10:13:49  haraldkipp
00177  * First release
00178  *
00179  * Revision 1.3  2003/08/05 20:11:30  haraldkipp
00180  * Removed from ICCAVR compilation
00181  *
00182  * Revision 1.2  2003/07/20 20:07:38  haraldkipp
00183  * Conflicting Ethernet driver routine names solved.
00184  *
00185  * Revision 1.1  2003/07/20 16:37:21  haraldkipp
00186  * CrystalTek 8900A driver added.
00187  *
00188  *
00189  * Revision 1.0  2002/03/28 MJC CDCS
00190  * Created
00191  *
00192  * Revision 1.1  2003/03/25 MJC CDCS
00193  * Modified behaviour when transmit buffer space unavailable
00194  *
00195  */
00196 
00197 /* Not ported. */
00198 #ifdef __GNUC__
00199 
00200 #include <cfg/os.h>
00201 #include <string.h>
00202 #include <avr/interrupt.h>
00203 
00204 #include <sys/heap.h>
00205 #include <sys/thread.h>
00206 #include <sys/event.h>
00207 #include <sys/timer.h>
00208 #include <sys/confnet.h>
00209 
00210 #include <dev/nicrtl.h>
00211 #include <netinet/if_ether.h>
00212 #include <net/ether.h>
00213 #include <net/if_var.h>
00214 #include <netinet/ip.h>
00215 
00216 #include <dev/irqreg.h>
00217 #include "cs8900.h"
00218 
00219 #ifdef NUTDEBUG
00220 #include <sys/osdebug.h>
00221 #include <net/netdebug.h>
00222 #endif
00223 
00228 
00229 
00230 // Ethernet flags byte
00231 // Bit 0 = transmit byte flag
00232 uint8_t cs_flags;
00233 volatile uint16_t cs_base = 0x0000;
00234 
00235 
00236 void CSWrite16(uint16_t addr, uint16_t data)
00237 {
00238     uint16_t *p;
00239 
00240     p = (uint16_t *) addr;
00241     cli();
00242     *p = data;
00243     sei();
00244 }
00245 
00246 void CSWritePP16(uint16_t addr, uint16_t data)
00247 {
00248     uint16_t *p;
00249 
00250     cli();
00251     p = (uint16_t *) CS_PP_PTR;
00252     *p = addr;
00253 
00254     CSWrite16(CS_PP_DATA0, data);
00255 
00256     return;
00257 }
00258 
00259 uint16_t CSRead16(uint16_t addr)
00260 {
00261     uint16_t *p;
00262     uint16_t d;
00263 
00264     cli();
00265     p = (uint16_t *) addr;
00266     d = *p;
00267     sei();
00268 
00269     return d;
00270 }
00271 
00272 uint16_t CSReadPP16(uint16_t addr)
00273 {
00274     uint16_t *p;
00275 
00276     cli();
00277     p = (uint16_t *) CS_PP_PTR;
00278     *p = addr;
00279 
00280     return CSRead16(CS_PP_DATA0);
00281 }
00282 
00283 uint32_t CSReadPP32(unsigned int addr)
00284 {
00285     uint32_t l;
00286     uint32_t *p;
00287 
00288     cli();
00289     p = (uint32_t *) CS_PP_PTR;
00290     *p = addr;
00291     p = (uint32_t *) CS_PP_DATA0;
00292     l = *p;
00293     sei();
00294 
00295     return l;
00296 }
00297 
00298 
00299 
00300 void CSBeginFrame(void)
00301 {
00302     cs_flags &= ~1;
00303 }
00304 
00305 void CSEndFrame(void)
00306 {
00307     uint8_t *p;
00308 
00309     cli();
00310     p = (uint8_t *) CS_DATA_P0 + 1;
00311     sei();
00312 
00313     // If odd number of bytes in packet pad it out
00314     if (cs_flags & 1)
00315         p = 0;
00316 }
00317 
00318 void CSWriteFrameByte(uint8_t data)
00319 {
00320     uint8_t *p;
00321 
00322     if (cs_flags & 1)
00323         p = (uint8_t *) CS_DATA_P0 + 1;
00324     else
00325         p = (uint8_t *) CS_DATA_P0;
00326 
00327     *p = data;
00328     cs_flags ^= 1;
00329 }
00330 
00331 static int CSEthPutPacket(NUTDEVICE * dev, NETBUF * nb)
00332 {
00333     uint16_t i;
00334     uint16_t sz;
00335     uint8_t *p;
00336     NICINFO *ni;
00337 
00338     ni = (NICINFO *) dev->dev_dcb;
00339 
00340     //
00341     // Calculate the number of bytes to be send. Do not
00342     // send packets larger than 1536 bytes.
00343     //
00344     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00345     if (sz >= 0x600) {
00346         NutNetBufFree(nb);
00347         return -1;
00348     }
00349 #if 0
00350     if (tcp_trace) {
00351         NutPrintFormat_P(dev_debug, PSTR("[ETHTX-%u]\r\n"), sz);
00352         NutPrintFlush(dev_debug);
00353     }
00354 #endif
00355 
00356     // Start transmission after entire frame is loaded into CS8900
00357     CSWrite16(CS_TX_CMD_I, 0xC0);
00358     // Set frame size
00359     CSWrite16(CS_TX_LEN_I, sz);
00360 
00361     // Wait for buffer space, but only for a while (200ms)
00362     // If the cable is disconnected this will never become true
00363     // If we don't get the go ahead within 200ms return 0 (Sucess)
00364     // And let the upper layers deal with re-transmission 
00365     // If we return failure TCP sockets will close straight away which probably
00366     // isn't the correct behaviour
00367     i = 0;
00368     while ((CSReadPP16(CS_BUS_STAT) & 0x0100) == 0) {
00369         i++;
00370         if (i > 20)
00371             return 0;
00372         NutSleep(10);
00373     }
00374 
00375     //
00376     // Transfer ethernet physical header.
00377     //
00378     CSBeginFrame();
00379 
00380     p = nb->nb_dl.vp;
00381     for (i = 0; i < nb->nb_dl.sz; i++) {
00382         CSWriteFrameByte(*p++);
00383     }
00384 
00385 
00386     p = nb->nb_nw.vp;
00387     for (i = 0; i < nb->nb_nw.sz; i++) {
00388         CSWriteFrameByte(*p++);
00389     }
00390 
00391     p = nb->nb_tp.vp;
00392     for (i = 0; i < nb->nb_tp.sz; i++) {
00393         CSWriteFrameByte(*p++);
00394     }
00395 
00396     p = nb->nb_ap.vp;
00397     for (i = 0; i < nb->nb_ap.sz; i++) {
00398         CSWriteFrameByte(*p++);
00399     }
00400 
00401     CSEndFrame();
00402 
00403     return 0;
00404 }
00405 
00420 int CSNicOutput(NUTDEVICE * dev, NETBUF * nb)
00421 {
00422     int rc = -1;
00423     NICINFO *ni;
00424 
00425     ni = (NICINFO *) dev->dev_dcb;
00426 
00427 #if 0
00428     if (tcp_trace) {
00429         NutPrintFormat_P(dev_debug, PSTR("Enter EthOutput\r\n"));
00430         NutPrintFlush(dev_debug);
00431     }
00432 #endif
00433 
00434     if ((rc = CSEthPutPacket(dev, nb)) == 0)
00435         ni->ni_tx_packets++;
00436 
00437     return rc;
00438 }
00439 
00440 
00441 
00442 
00443 
00451 THREAD(CSNICrx, arg)
00452 {
00453     NUTDEVICE *dev;
00454     IFNET *ifn;
00455     NICINFO *ni;
00456     NETBUF *nb;
00457     uint8_t *p;
00458     uint8_t *q;
00459     uint16_t i, m;
00460     volatile uint16_t l;
00461 
00462     dev = arg;
00463     ifn = (IFNET *) dev->dev_icb;
00464     ni = (NICINFO *) dev->dev_dcb;
00465 
00466 #if 0
00467     if (tcp_trace) {
00468         NutPrintFormat_P(dev_debug, PSTR("Enter ETHReceive\r\n"));
00469         NutPrintFlush(dev_debug);
00470     }
00471 #endif
00472 
00473     l = 0;
00474 
00475     NutThreadSetPriority(8);
00476     for (;;) {
00477         while ((CSReadPP16(CS_RX_EVENT) & 0x0100) == 0) {
00478             NutSleep(10);
00479         }
00480 
00481 #ifdef NUT_CS8900_OLD
00482         // Get the RxStatus But don't let the compiler do any optomisation
00483         asm volatile ("lds __tmp_reg__, %3" "\n\t"
00484                       "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l)
00485                       :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1))
00486             );
00487 
00488         // Get the Packet Length But don't let the compiler do any optomisation
00489         asm volatile ("lds __tmp_reg__, %3" "\n\t"
00490                       "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l)
00491                       :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1))
00492             );
00493 #else
00494 
00495         l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0);
00496         l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0);
00497 #endif
00498         //NutPrintFormat_P(dev_debug,PSTR("RxLength = %x \r\n"), l);
00499         //NutPrintFlush(dev_debug);
00500 
00501         // Account for odd length packets
00502         if (l & 1)
00503             m = l - 1;
00504         else
00505             m = l;
00506 
00507 
00508         nb = NutNetBufAlloc(0, NBAF_DATALINK, l);
00509         if (nb) {
00510             q = nb->nb_dl.vp;
00511             for (i = 0; i < m; i += 2) {
00512                 p = (uint8_t *) CS_DATA_P0;
00513                 *q++ = *p;
00514                 p = (uint8_t *) CS_DATA_P0 + 1;
00515                 *q++ = *p;
00516             }
00517 
00518             // Odd length packets
00519             if (m != l) {
00520                 p = (uint8_t *) CS_DATA_P0;
00521                 *q++ = *p;
00522 
00523                 p = (uint8_t *) CS_DATA_P0 + 1;
00524                 m = *p;
00525             }
00526             ni->ni_rx_packets++;
00527             (*ifn->if_recv) (dev, nb);
00528         }
00529     }
00530 }
00531 
00532 void CSSoftwareWakeup(void)
00533 {
00534     volatile uint16_t *p;
00535 
00536     p = (uint16_t *) CS_PP_PTR;
00537     *p = CS_SELF_CTRL;
00538 
00539     NutDelay(10);
00540 }
00541 
00542 
00543 void CSSoftwareReset(void)
00544 {
00545     volatile uint16_t *p;
00546 
00547     p = (uint16_t *) CS_PP_PTR;
00548     *p = CS_SELF_CTRL;
00549     p = (uint16_t *) CS_DATA_P0;
00550     *p = 0x0040;
00551 }
00552 
00553 
00564 int CSNicInit(NUTDEVICE * dev)
00565 {
00566     uint16_t i;
00567     uint16_t j;
00568     IFNET *ifn;
00569     NICINFO *ni;
00570 
00571 #if 0
00572     if (tcp_trace) {
00573         NutPrintFormat_P(dev_debug, PSTR("Enter NicInit  \r\n"));
00574         NutPrintFlush(dev_debug);
00575     }
00576 #endif
00577     cs_base = dev->dev_base;
00578 
00579     if (confnet.cd_size == 0)
00580         NutNetLoadConfig(dev->dev_name);
00581 
00582     ifn = dev->dev_icb;
00583     memcpy(ifn->if_mac, confnet.cdn_mac, 6);
00584     memset(dev->dev_dcb, 0, sizeof(NICINFO));
00585     ni = (NICINFO *) dev->dev_dcb;
00586 
00587     // Take CS8900 out of reset and wait for internal reset to complete
00588 #ifdef NUT_CS8900_OLD
00589     outb(PORTD, inb(PORTD) & ~RESETE);
00590 #else
00591     CSSoftwareWakeup();
00592     CSSoftwareReset();
00593 #endif
00594 
00595     NutDelay(100);
00596 
00597     // Check for presence
00598     if (CSReadPP16(CS_PROD_ID) != 0x630E)
00599         return -1;
00600 
00601     //
00602     //  Copy our MAC address to the NIC
00603     // 
00604     for (i = 0; i < 6; i += 2) {
00605         j = ifn->if_mac[i] << 8;
00606         j |= ifn->if_mac[i + 1];
00607         CSWritePP16(CS_IEEE_ADDR + i, j);
00608         j = CSReadPP16(CS_IEEE_ADDR + i);
00609 #if 0
00610         if (tcp_trace) {
00611             NutPrintFormat_P(dev_debug, PSTR("ADDR = %x\r\n"), j);
00612             NutPrintFlush(dev_debug);
00613         }
00614 #endif
00615     }
00616 
00617     //
00618     // Enable the Transmitter and Receiver
00619     //
00620     CSWritePP16(CS_LINE_CTRL, 0x00C0);
00621     //i = CSReadPP16(CS_LINE_CTRL);
00622     //NutPrintFormat_P(dev_debug,PSTR("CS_LINE_CTRL = %x\r\n"), i);
00623 
00624     CSWritePP16(CS_RX_CTL, 0x0F40);
00625     //i = CSReadPP16(CS_RX_CTL);
00626     //NutPrintFormat_P(dev_debug,PSTR("CS_RX_CTL = %x\r\n"), i);
00627 
00628     // 
00629     // Start receiver thread
00630     //
00631     NutThreadCreate("csnicrx", CSNICrx, dev, 500);
00632 
00633     return 0;
00634 }
00635 
00637 #else
00638 void keep_icc_happy(void)
00639 {
00640 }
00641 
00642 #endif