Contiki 2.6

lanc111.c

00001 #define INLINE
00002 #define CONST const
00003 #define NETBUF char
00004 /*
00005  * Copyright (C) 2003-2005 by egnite Software GmbH. All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00024  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  *
00035  */
00036 
00037 /*
00038  * $Log: lanc111.c,v $
00039  * Revision 1.1  2006/06/17 22:41:21  adamdunkels
00040  * Import of the contiki-2.x development code from the SICS internal CVS server
00041  *
00042  * Revision 1.1  2005/09/19 23:05:34  adam
00043  * AVR device drivers
00044  *
00045  * Revision 1.1  2005/05/19 09:06:25  adam
00046  * Very initial version of the LANC111 Ethernet driver, imported from Nut/OS code - does not work yet
00047  *
00048  * Revision 1.12  2005/02/02 19:55:34  haraldkipp
00049  * If no Ethernet link was available on the LAN91C111, each outgoing packet
00050  * took 15 seconds and, even worse, the ouput routine doesn't return an error.
00051  * Now the first attempt to send a packet without Ethernet link will wait for
00052  * 5 seconds and subsequent attempts take 0.5 seconds only, always returning
00053  * an error.
00054  *
00055  * Revision 1.11  2005/01/24 21:11:49  freckle
00056  * renamed NutEventPostFromIRQ into NutEventPostFromIrq
00057  *
00058  * Revision 1.10  2005/01/22 19:24:11  haraldkipp
00059  * Changed AVR port configuration names from PORTx to AVRPORTx.
00060  *
00061  * Revision 1.9  2005/01/21 16:49:45  freckle
00062  * Seperated calls to NutEventPostAsync between Threads and IRQs
00063  *
00064  * Revision 1.8  2004/09/22 08:14:48  haraldkipp
00065  * Made configurable
00066  *
00067  * Revision 1.7  2004/03/08 11:14:17  haraldkipp
00068  * Added quick hack for fixed mode.
00069  *
00070  * Revision 1.6  2004/02/25 16:22:33  haraldkipp
00071  * Do not initialize MAC with all zeros
00072  *
00073  * Revision 1.5  2004/01/14 19:31:43  drsung
00074  * Speed improvement to NicWrite applied. Thanks to Kolja Waschk
00075  *
00076  * Revision 1.4  2003/11/06 09:26:50  haraldkipp
00077  * Removed silly line with hardcoded MAC, left over from testing
00078  *
00079  * Revision 1.3  2003/11/04 17:54:47  haraldkipp
00080  * PHY configuration timing changed again for reliable linking
00081  *
00082  * Revision 1.2  2003/11/03 17:12:53  haraldkipp
00083  * Allow linking with RTL8019 driver.
00084  * Links more reliable to 10 MBit networks now.
00085  * Reset MMU on allocation failures.
00086  * Some optimizations.
00087  *
00088  * Revision 1.1  2003/10/13 10:13:49  haraldkipp
00089  * First release
00090  *
00091  */
00092 
00093 #include "contiki.h"
00094 
00095 #include <string.h>
00096 
00097 #include <avr/io.h>
00098 
00099 /*
00100  * Determine ports, which had not been explicitely configured.
00101  */
00102 #ifndef LANC111_BASE_ADDR
00103 #define LANC111_BASE_ADDR   0xC000
00104 #endif
00105 
00106 #ifndef LANC111_SIGNAL_IRQ
00107 #define LANC111_SIGNAL_IRQ  INT5
00108 #endif
00109 
00110 #ifdef LANC111_RESET_BIT
00111 
00112 #if (LANC111_RESET_AVRPORT == AVRPORTB)
00113 #define LANC111_RESET_PORT   PORTB
00114 #define LANC111_RESET_DDR    DDRB
00115 
00116 #elif (LANC111_RESET_AVRPORT == AVRPORTD)
00117 #define LANC111_RESET_PORT   PORTD
00118 #define LANC111_RESET_DDR    DDRD
00119 
00120 #elif (LANC111_RESET_AVRPORT == AVRPORTE)
00121 #define LANC111_RESET_PORT   PORTE
00122 #define LANC111_RESET_DDR    DDRE
00123 
00124 #elif (LANC111_RESET_AVRPORT == AVRPORTF)
00125 #define LANC111_RESET_PORT   PORTF
00126 #define LANC111_RESET_DDR    DDRF
00127 
00128 #endif /* LANC111_RESET_AVRPORT */
00129 
00130 #endif /* LANC111_RESET_BIT */
00131 
00132 /*
00133  * Determine interrupt settings.
00134  */
00135 #if (LANC111_SIGNAL_IRQ == INT0)
00136 #define LANC111_SIGNAL          sig_INTERRUPT0
00137 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00138 
00139 #elif (LANC111_SIGNAL_IRQ == INT1)
00140 #define LANC111_SIGNAL          sig_INTERRUPT1
00141 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00142 
00143 #elif (LANC111_SIGNAL_IRQ == INT2)
00144 #define LANC111_SIGNAL          sig_INTERRUPT2
00145 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00146 
00147 #elif (LANC111_SIGNAL_IRQ == INT3)
00148 #define LANC111_SIGNAL          sig_INTERRUPT3
00149 #define LANC111_SIGNAL_MODE()   sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00150 
00151 #elif (LANC111_SIGNAL_IRQ == INT4)
00152 #define LANC111_SIGNAL          sig_INTERRUPT4
00153 #define LANC111_SIGNAL_MODE()   sbi(EICRB, ISC40); sbi(EICRB, ISC41)
00154 
00155 #elif (LANC111_SIGNAL_IRQ == INT6)
00156 #define LANC111_SIGNAL          sig_INTERRUPT6
00157 #define LANC111_SIGNAL_MODE()   sbi(EICRB, ISC60); sbi(EICRB, ISC61)
00158 
00159 #elif (LANC111_SIGNAL_IRQ == INT7)
00160 #define LANC111_SIGNAL          sig_INTERRUPT7
00161 #define LANC111_SIGNAL_MODE()   sbi(EICRB, ISC70); sbi(EICRB, ISC71)
00162 
00163 #else
00164 #define LANC111_SIGNAL          sig_INTERRUPT5
00165 #define LANC111_SIGNAL_MODE()   sbi(EICRB, ISC50); sbi(EICRB, ISC51)
00166 
00167 #endif
00168 
00169 /*!
00170  * \addtogroup xgSmscRegs
00171  */
00172 /*@{*/
00173 
00174 /*! 
00175  * \brief Bank select register. 
00176  */
00177 #define NIC_BSR         (LANC111_BASE_ADDR + 0x0E)
00178 
00179 /*! 
00180  * \brief Bank 0 - Transmit control register. 
00181  */
00182 #define NIC_TCR         (LANC111_BASE_ADDR + 0x00)
00183 
00184 #define TCR_SWFDUP      0x8000  /*!< \ref NIC_TCR bit mask, enables full duplex.  */
00185 #define TCR_EPH_LOOP    0x2000  /*!< \ref NIC_TCR bit mask, enables internal loopback. */
00186 #define TCR_STP_SQET    0x1000  /*!< \ref NIC_TCR bit mask, enables transmission stop on SQET error. */
00187 #define TCR_FDUPLX      0x0800  /*!< \ref NIC_TCR bit mask, enables receiving own frames. */
00188 #define TCR_MON_CSN     0x0400  /*!< \ref NIC_TCR bit mask, enables carrier monitoring. */
00189 #define TCR_NOCRC       0x0100  /*!< \ref NIC_TCR bit mask, disables CRC transmission. */
00190 #define TCR_PAD_EN      0x0080  /*!< \ref NIC_TCR bit mask, enables automatic padding. */
00191 #define TCR_FORCOL      0x0004  /*!< \ref NIC_TCR bit mask, forces collision. */
00192 #define TCR_LOOP        0x0002  /*!< \ref NIC_TCR bit mask, enables PHY loopback. */
00193 #define TCR_TXENA       0x0001  /*!< \ref NIC_TCR bit mask, enables transmitter. */
00194 
00195 
00196 /*! 
00197  * \brief Bank 0 - EPH status register. 
00198  */
00199 #define NIC_EPHSR       (LANC111_BASE_ADDR + 0x02)
00200 
00201 /*! 
00202  * \brief Bank 0 - Receive control register. 
00203  */
00204 #define NIC_RCR         (LANC111_BASE_ADDR + 0x04)
00205 
00206 #define RCR_SOFT_RST    0x8000  /*!< \ref NIC_RCR bit mask, activates software reset. */
00207 #define RCR_FILT_CAR    0x4000  /*!< \ref NIC_RCR bit mask, enables carrier filter. */
00208 #define RCR_ABORT_ENB   0x2000  /*!< \ref NIC_RCR bit mask, enables receive abort on collision. */
00209 #define RCR_STRIP_CRC   0x0200  /*!< \ref NIC_RCR bit mask, strips CRC. */
00210 #define RCR_RXEN        0x0100  /*!< \ref NIC_RCR bit mask, enables receiver. */
00211 #define RCR_ALMUL       0x0004  /*!< \ref NIC_RCR bit mask, multicast frames accepted when set. */
00212 #define RCR_PRMS        0x0002  /*!< \ref NIC_RCR bit mask, enables promiscuous mode. */
00213 #define RCR_RX_ABORT    0x0001  /*!< \ref NIC_RCR bit mask, set when receive was aborted. */
00214 
00215 /*! 
00216  * \brief Bank 0 - Counter register.
00217  */
00218 #define NIC_ECR         (LANC111_BASE_ADDR + 0x06)
00219 
00220 /*! 
00221  * \brief Bank 0 - Memory information register.
00222  */
00223 #define NIC_MIR         (LANC111_BASE_ADDR + 0x08)
00224 
00225 /*! 
00226  * \brief Bank 0 - Receive / PHY control register.
00227  */
00228 #define NIC_RPCR        (LANC111_BASE_ADDR + 0x0A)
00229 
00230 #define RPCR_SPEED      0x2000  /*!< \ref NIC_RPCR bit mask, PHY operates at 100 Mbps. */
00231 #define RPCR_DPLX       0x1000  /*!< \ref NIC_RPCR bit mask, PHY operates at full duplex mode. */
00232 #define RPCR_ANEG       0x0800  /*!< \ref NIC_RPCR bit mask, sets PHY in auto-negotiation mode. */
00233 #define RPCR_LEDA_PAT   0x0000  /*!< \ref NIC_RPCR bit mask for LEDA mode. */
00234 #define RPCR_LEDB_PAT   0x0010  /*!< \ref NIC_RPCR bit mask for LEDB mode. */
00235 
00236 /*! 
00237  * \brief Bank 1 - Configuration register.
00238  */
00239 #define NIC_CR          (LANC111_BASE_ADDR + 0x00)
00240 
00241 #define CR_EPH_EN       0x8000  /*!< \ref NIC_CR bit mask, . */
00242 
00243 /*! 
00244  * \brief Bank 1 - Base address register.
00245  */
00246 #define NIC_BAR         (LANC111_BASE_ADDR + 0x02)
00247 
00248 /*! 
00249  * \brief Bank 1 - Individual address register.
00250  */
00251 #define NIC_IAR         (LANC111_BASE_ADDR + 0x04)
00252 
00253 /*! 
00254  * \brief Bank 1 - General purpose register.
00255  */
00256 #define NIC_GPR         (LANC111_BASE_ADDR + 0x0A)
00257 
00258 /*! 
00259  * \brief Bank 1 - Control register.
00260  */
00261 #define NIC_CTR         (LANC111_BASE_ADDR + 0x0C)
00262 
00263 #define CTR_RCV_BAD     0x4000  /*!< \ref NIC_CTR bit mask. */
00264 #define CTR_AUTO_RELEASE 0x0800 /*!< \ref NIC_CTR bit mask, transmit packets automatically released. */
00265 
00266 /*!
00267  * \brief Bank 2 - MMU command register.
00268  */
00269 #define NIC_MMUCR       (LANC111_BASE_ADDR + 0x00)
00270 
00271 #define MMUCR_BUSY      0x0001
00272 
00273 #define MMU_NOP         0
00274 #define MMU_ALO         (1<<5)
00275 #define MMU_RST         (2<<5)
00276 #define MMU_REM         (3<<5)
00277 #define MMU_TOP         (4<<5)
00278 #define MMU_PKT         (5<<5)
00279 #define MMU_ENQ         (6<<5)
00280 #define MMU_RTX         (7<<5)
00281 
00282 /*!
00283  * \brief Bank 2 - Packet number register.
00284  *
00285  * This byte register specifies the accessible transmit packet number.
00286  */
00287 #define NIC_PNR         (LANC111_BASE_ADDR + 0x02)
00288 
00289 /*!
00290  * \brief Bank 2 - Allocation result register.
00291  *
00292  * This byte register is updated upon a \ref MMU_ALO command.
00293  */
00294 #define NIC_ARR         (LANC111_BASE_ADDR + 0x03)
00295 
00296 #define ARR_FAILED      0x80
00297 
00298 /*!
00299  * \brief Bank 2 - FIFO ports register.
00300  */
00301 #define NIC_FIFO        (LANC111_BASE_ADDR + 0x04)
00302 
00303 /*!
00304  * \brief Bank 2 - Pointer register.
00305  */
00306 #define NIC_PTR         (LANC111_BASE_ADDR + 0x06)
00307 
00308 #define PTR_RCV         0x8000  /*! \ref NIC_PTR bit mask, specifies receive or transmit buffer. */
00309 #define PTR_AUTO_INCR   0x4000  /*! \ref NIC_PTR bit mask, enables automatic pointer increment. */
00310 #define PTR_READ        0x2000  /*! \ref NIC_PTR bit mask, indicates type of access. */
00311 #define PTR_ETEN        0x1000  /*! \ref NIC_PTR bit mask, enables early transmit underrun detection. */
00312 #define PTR_NOT_EMPTY   0x0800  /*! \ref NIC_PTR bit mask, set when write data fifo is not empty. */
00313 
00314 /*!
00315  * \brief Bank 2 - Data register.
00316  */
00317 #define NIC_DATA        (LANC111_BASE_ADDR + 0x08)
00318 
00319 /*!
00320  * \brief Bank 2 - Interrupt status register.
00321  */
00322 #define NIC_IST         (LANC111_BASE_ADDR + 0x0C)
00323 
00324 /*!
00325  * \brief Bank 2 - Interrupt acknowledge register.
00326  */
00327 #define NIC_ACK         (LANC111_BASE_ADDR + 0x0C)
00328 
00329 /*!
00330  * \brief Bank 2 - Interrupt mask register.
00331  */
00332 #define NIC_MSK         (LANC111_BASE_ADDR + 0x0D)
00333 
00334 #define INT_MD          0x80    /*!< \ref PHY state change interrupt bit mask. */
00335 #define INT_ERCV        0x40    /*!< \ref Early receive interrupt bit mask. */
00336 #define INT_EPH         0x20    /*!< \ref Ethernet protocol interrupt bit mask. */
00337 #define INT_RX_OVRN     0x10    /*!< \ref Receive overrun interrupt bit mask. */
00338 #define INT_ALLOC       0x08    /*!< \ref Transmit allocation interrupt bit mask. */
00339 #define INT_TX_EMPTY    0x04    /*!< \ref Transmitter empty interrupt bit mask. */
00340 #define INT_TX          0x02    /*!< \ref Transmit complete interrupt bit mask. */
00341 #define INT_RCV         0x01    /*!< \ref Receive interrupt bit mask. */
00342 
00343 /*!
00344  * \brief Bank 3 - Multicast table register.
00345  */
00346 #define NIC_MT          (LANC111_BASE_ADDR + 0x00)
00347 
00348 /*!
00349  * \brief Bank 3 - Management interface register.
00350  */
00351 #define NIC_MGMT        (LANC111_BASE_ADDR + 0x08)
00352 
00353 #define MGMT_MDOE       0x08    /*!< \ref NIC_MGMT bit mask, enables MDO pin. */
00354 #define MGMT_MCLK       0x04    /*!< \ref NIC_MGMT bit mask, drives MDCLK pin. */
00355 #define MGMT_MDI        0x02    /*!< \ref NIC_MGMT bit mask, reflects MDI pin status. */
00356 #define MGMT_MDO        0x01    /*!< \ref NIC_MGMT bit mask, drives MDO pin. */
00357 
00358 /*!
00359  * \brief Bank 3 - Revision register.
00360  */
00361 #define NIC_REV         (LANC111_BASE_ADDR + 0x0A)
00362 
00363 /*!
00364  * \brief Bank 3 - Early RCV register.
00365  */
00366 #define NIC_ERCV        (LANC111_BASE_ADDR + 0x0C)
00367 
00368 /*!
00369  * \brief PHY control register.
00370  */
00371 #define NIC_PHYCR       0
00372 
00373 #define PHYCR_RST       0x8000  /*!< \ref NIC_PHYCR bit mask, resets PHY. */
00374 #define PHYCR_LPBK      0x4000  /*!< \ref NIC_PHYCR bit mask, . */
00375 #define PHYCR_SPEED     0x2000  /*!< \ref NIC_PHYCR bit mask, . */
00376 #define PHYCR_ANEG_EN   0x1000  /*!< \ref NIC_PHYCR bit mask, . */
00377 #define PHYCR_PDN       0x0800  /*!< \ref NIC_PHYCR bit mask, . */
00378 #define PHYCR_MII_DIS   0x0400  /*!< \ref NIC_PHYCR bit mask, . */
00379 #define PHYCR_ANEG_RST  0x0200  /*!< \ref NIC_PHYCR bit mask, . */
00380 #define PHYCR_DPLX      0x0100  /*!< \ref NIC_PHYCR bit mask, . */
00381 #define PHYCR_COLST     0x0080  /*!< \ref NIC_PHYCR bit mask, . */
00382 
00383 
00384 /*!
00385  * \brief PHY status register.
00386  */
00387 #define NIC_PHYSR       1
00388 
00389 #define PHYSR_CAP_T4    0x8000  /*!< \ref NIC_PHYSR bit mask, indicates 100BASE-T4 capability. */
00390 #define PHYSR_CAP_TXF   0x4000  /*!< \ref NIC_PHYSR bit mask, indicates 100BASE-TX full duplex capability. */
00391 #define PHYSR_CAP_TXH   0x2000  /*!< \ref NIC_PHYSR bit mask, indicates 100BASE-TX half duplex capability. */
00392 #define PHYSR_CAP_TF    0x1000  /*!< \ref NIC_PHYSR bit mask, indicates 10BASE-T full duplex capability. */
00393 #define PHYSR_CAP_TH    0x0800  /*!< \ref NIC_PHYSR bit mask, indicates 10BASE-T half duplex capability. */
00394 #define PHYSR_CAP_SUPR  0x0040  /*!< \ref NIC_PHYSR bit mask, indicates preamble suppression capability. */
00395 #define PHYSR_ANEG_ACK  0x0020  /*!< \ref NIC_PHYSR bit mask, auto-negotiation completed. */
00396 #define PHYSR_REM_FLT   0x0010  /*!< \ref NIC_PHYSR bit mask, remote fault detected. */
00397 #define PHYSR_CAP_ANEG  0x0008  /*!< \ref NIC_PHYSR bit mask, indicates auto-negotiation capability. */
00398 #define PHYSR_LINK      0x0004  /*!< \ref NIC_PHYSR bit mask, valid link status. */
00399 #define PHYSR_JAB       0x0002  /*!< \ref NIC_PHYSR bit mask, jabber collision detected. */
00400 #define PHYSR_EXREG     0x0001  /*!< \ref NIC_PHYSR bit mask, extended capabilities available. */
00401 
00402 
00403 /*!
00404  * \brief PHY identifier register 1.
00405  */
00406 #define NIC_PHYID1      2
00407 
00408 /*!
00409  * \brief PHY identifier register 1.
00410  */
00411 #define NIC_PHYID2      3
00412 
00413 /*!
00414  * \brief PHY auto-negotiation advertisement register.
00415  */
00416 #define NIC_PHYANAD     4
00417 
00418 #define PHYANAD_NP      0x8000  /*!< \ref NIC_PHYANAD bit mask, exchanging next page information. */
00419 #define PHYANAD_ACK     0x4000  /*!< \ref NIC_PHYANAD bit mask, acknowledged. */
00420 #define PHYANAD_RF      0x2000  /*!< \ref NIC_PHYANAD bit mask, remote fault. */
00421 #define PHYANAD_T4      0x0200  /*!< \ref NIC_PHYANAD bit mask, indicates 100BASE-T4 capability. */
00422 #define PHYANAD_TX_FDX  0x0100  /*!< \ref NIC_PHYANAD bit mask, indicates 100BASE-TX full duplex capability. */
00423 #define PHYANAD_TX_HDX  0x0080  /*!< \ref NIC_PHYANAD bit mask, indicates 100BASE-TX half duplex capability. */
00424 #define PHYANAD_10FDX   0x0040  /*!< \ref NIC_PHYANAD bit mask, indicates 10BASE-T full duplex capability. */
00425 #define PHYANAD_10_HDX  0x0020  /*!< \ref NIC_PHYANAD bit mask, indicates 10BASE-T half duplex capability. */
00426 #define PHYANAD_CSMA    0x0001  /*!< \ref NIC_PHYANAD bit mask, indicates 802.3 CSMA capability. */
00427 
00428 /*!
00429  * \brief PHY auto-negotiation remote end capability register.
00430  */
00431 #define NIC_PHYANRC     5
00432 
00433 /*!
00434  * \brief PHY configuration register 1.
00435  */
00436 #define NIC_PHYCFR1     16
00437 
00438 /*!
00439  * \brief PHY configuration register 2.
00440  */
00441 #define NIC_PHYCFR2     17
00442 
00443 /*!
00444  * \brief PHY status output register.
00445  */
00446 #define NIC_PHYSOR      18
00447 
00448 #define PHYSOR_INT      0x8000  /*!< \ref NIC_PHYSOR bit mask, interrupt bits changed. */
00449 #define PHYSOR_LNKFAIL  0x4000  /*!< \ref NIC_PHYSOR bit mask, link failure detected. */
00450 #define PHYSOR_LOSSSYNC 0x2000  /*!< \ref NIC_PHYSOR bit mask, descrambler sync lost detected. */
00451 #define PHYSOR_CWRD     0x1000  /*!< \ref NIC_PHYSOR bit mask, code word error detected. */
00452 #define PHYSOR_SSD      0x0800  /*!< \ref NIC_PHYSOR bit mask, start of stream error detected. */
00453 #define PHYSOR_ESD      0x0400  /*!< \ref NIC_PHYSOR bit mask, end of stream error detected. */
00454 #define PHYSOR_RPOL     0x0200  /*!< \ref NIC_PHYSOR bit mask, reverse polarity detected. */
00455 #define PHYSOR_JAB      0x0100  /*!< \ref NIC_PHYSOR bit mask, jabber detected. */
00456 #define PHYSOR_SPDDET   0x0080  /*!< \ref NIC_PHYSOR bit mask, 100/10 speed detected. */
00457 #define PHYSOR_DPLXDET  0x0040  /*!< \ref NIC_PHYSOR bit mask, duplex detected. */
00458 
00459 /*!
00460  * \brief PHY mask register.
00461  */
00462 #define NIC_PHYMSK      19
00463 
00464 #define PHYMSK_MINT     0x8000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_INT interrupt. */
00465 #define PHYMSK_MLNKFAIL 0x4000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_LNKFAIL interrupt. */
00466 #define PHYMSK_MLOSSSYN 0x2000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_LOSSSYNC interrupt. */
00467 #define PHYMSK_MCWRD    0x1000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_CWRD interrupt. */
00468 #define PHYMSK_MSSD     0x0800  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_SSD interrupt. */
00469 #define PHYMSK_MESD     0x0400  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_ESD interrupt. */
00470 #define PHYMSK_MRPOL    0x0200  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_RPOL interrupt. */
00471 #define PHYMSK_MJAB     0x0100  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_JAB interrupt. */
00472 #define PHYMSK_MSPDDT   0x0080  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_SPDDET interrupt. */
00473 #define PHYMSK_MDPLDT   0x0040  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_DPLXDET interrupt. */
00474 
00475 
00476 
00477 #define MSBV(bit)       (1 << ((bit) - 8))
00478 
00479 #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
00480 #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
00481 #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
00482 #define nic_outw(addr, val) { \
00483     *(volatile uint8_t *)(addr) = (uint8_t)(val); \
00484     *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
00485 }
00486 
00487 #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
00488 #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
00489 #define nic_inw(addr) (*(volatile uint16_t *)(addr))
00490 
00491 #define nic_bs(bank)    nic_outlb(NIC_BSR, bank)
00492 
00493 /*!
00494  * \struct _NICINFO lanc111.h dev/lanc111.h
00495  * \brief Network interface controller information structure.
00496  */
00497 /*@}*/
00498 
00499 /*!
00500  * \addtogroup xgNicLanc111
00501  */
00502 /*@{*/
00503 
00504 
00505 
00506 /*!
00507  * \brief Select specified PHY register for reading or writing.
00508  *
00509  * \note NIC interrupts must have been disabled before calling this routine.
00510  *
00511  * \param reg PHY register number.
00512  * \param we  Indicates type of access, 1 for write and 0 for read.
00513  *
00514  * \return Contents of the PHY interface rgister.
00515  */
00516 static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
00517 {
00518     uint8_t rs;
00519     uint8_t msk;
00520     uint8_t i;
00521 
00522     nic_bs(3);
00523     rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;
00524 
00525     /* Send idle pattern. */
00526     for (i = 0; i < 33; i++) {
00527         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00528         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00529     }
00530 
00531     /* Send start sequence. */
00532     nic_outlb(NIC_MGMT, rs);
00533     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00534     nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00535     nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00536 
00537     /* Write or read mode. */
00538     if (we) {
00539         nic_outlb(NIC_MGMT, rs);
00540         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00541         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00542         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00543     } else {
00544         nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00545         nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00546         nic_outlb(NIC_MGMT, rs);
00547         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00548     }
00549 
00550     /* Send PHY address. Zero is used for the internal PHY. */
00551     for (i = 0; i < 5; i++) {
00552         nic_outlb(NIC_MGMT, rs);
00553         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00554     }
00555 
00556     /* Send PHY register number. */
00557     for (msk = 0x10; msk; msk >>= 1) {
00558         if (reg & msk) {
00559             nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00560             nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00561         } else {
00562             nic_outlb(NIC_MGMT, rs);
00563             nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00564         }
00565     }
00566     nic_outlb(NIC_MGMT, rs);
00567 
00568     return rs;
00569 }
00570 
00571 /*!
00572  * \brief Read contents of PHY register.
00573  *
00574  * \note NIC interrupts must have been disabled before calling this routine.
00575  *
00576  * \param reg PHY register number.
00577  *
00578  * \return Contents of the specified register.
00579  */
00580 static uint16_t NicPhyRead(uint8_t reg)
00581 {
00582     uint16_t rc = 0;
00583     uint8_t rs;
00584     uint8_t i;
00585 
00586     /* Select register for reading. */
00587     rs = NicPhyRegSelect(reg, 0);
00588 
00589     /* Switch data direction. */
00590     rs &= ~MGMT_MDOE;
00591     nic_outlb(NIC_MGMT, rs);
00592     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00593 
00594     /* Clock data in. */
00595     for (i = 0; i < 16; i++) {
00596         nic_outlb(NIC_MGMT, rs);
00597         nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00598         rc <<= 1;
00599         rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;
00600     }
00601 
00602     /* This will set the clock line to low. */
00603     nic_outlb(NIC_MGMT, rs);
00604 
00605     return rc;
00606 }
00607 
00608 /*!
00609  * \brief Write value to PHY register.
00610  *
00611  * \note NIC interrupts must have been disabled before calling this routine.
00612  *
00613  * \param reg PHY register number.
00614  * \param val Value to write.
00615  */
00616 static void NicPhyWrite(uint8_t reg, uint16_t val)
00617 {
00618     uint16_t msk;
00619     uint8_t rs;
00620 
00621     /* Select register for writing. */
00622     rs = NicPhyRegSelect(reg, 1);
00623 
00624     /* Switch data direction dummy. */
00625     nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00626     nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00627     nic_outlb(NIC_MGMT, rs);
00628     nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00629 
00630     /* Clock data out. */
00631     for (msk = 0x8000; msk; msk >>= 1) {
00632         if (val & msk) {
00633             nic_outlb(NIC_MGMT, rs | MGMT_MDO);
00634             nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);
00635         } else {
00636             nic_outlb(NIC_MGMT, rs);
00637             nic_outlb(NIC_MGMT, rs | MGMT_MCLK);
00638         }
00639     }
00640 
00641     /* Set clock line low and output line int z-state. */
00642     nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);
00643 }
00644 
00645 /*!
00646  * \brief Configure the internal PHY.
00647  *
00648  * Reset the PHY and initiate auto-negotiation.
00649  */
00650 static int NicPhyConfig(void)
00651 {
00652     uint16_t phy_sor;
00653     uint16_t phy_sr;
00654     uint16_t phy_to;
00655     uint16_t mode;
00656 
00657     /* 
00658      * Reset the PHY and wait until this self clearing bit
00659      * becomes zero. We sleep 63 ms before each poll and
00660      * give up after 3 retries. 
00661      */
00662     //printf("Reset PHY..");
00663     NicPhyWrite(NIC_PHYCR, PHYCR_RST);
00664     for (phy_to = 0;; phy_to++) {
00665         NutSleep(63);
00666         if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
00667             break;
00668         if (phy_to > 3)
00669             return -1;
00670     }
00671     //printf("OK\n");
00672 
00673     /* Store PHY status output. */
00674     phy_sor = NicPhyRead(NIC_PHYSOR);
00675 
00676     /* Enable PHY interrupts. */
00677     NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
00678                 PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);
00679 
00680     /* Set RPC register. */
00681     mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
00682     nic_bs(0);
00683     nic_outw(NIC_RPCR, mode);
00684 
00685 #ifdef NIC_FIXED
00686     /* Disable link. */
00687     phy_sr = NicPhyRead(NIC_PHYCFR1);
00688     NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
00689     NutSleep(63);
00690 
00691     /* Set fixed capabilities. */
00692     NicPhyWrite(NIC_PHYCR, NIC_FIXED);
00693     nic_bs(0);
00694     nic_outw(NIC_RPCR, mode);
00695 
00696     /* Enable link. */
00697     phy_sr = NicPhyRead(NIC_PHYCFR1);
00698     NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
00699     phy_sr = NicPhyRead(NIC_PHYCFR1);
00700 
00701 #else
00702     /*
00703      * Advertise our capabilities, initiate auto negotiation
00704      * and wait until this has been completed.
00705      */
00706     //printf("Negotiate..");
00707     NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
00708     NutSleep(63);
00709     for (phy_to = 0, phy_sr = 0;; phy_to++) {
00710         /* Give up after 10 seconds. */
00711         if (phy_to >= 1024)
00712             return -1;
00713         /* Restart auto negotiation every 4 seconds or on failures. */
00714         if ((phy_to & 127) == 0 /* || (phy_sr & PHYSR_REM_FLT) != 0 */ ) {
00715             NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
00716             //printf("Restart..");
00717             NutSleep(63);
00718         }
00719         /* Check if we are done. */
00720         phy_sr = NicPhyRead(NIC_PHYSR);
00721         //printf("[SR %04X]", phy_sr);
00722         if (phy_sr & PHYSR_ANEG_ACK)
00723             break;
00724         NutSleep(63);
00725     }
00726     //printf("OK\n");
00727 #endif
00728 
00729     return 0;
00730 }
00731 
00732 /*!
00733  * \brief Wait until MMU is ready.
00734  *
00735  * Poll the MMU command register until \ref MMUCR_BUSY
00736  * is cleared.
00737  *
00738  * \param tmo Timeout in milliseconds.
00739  *
00740  * \return 0 on success or -1 on timeout.
00741  */
00742 static INLINE int NicMmuWait(uint16_t tmo)
00743 {
00744     while (tmo--) {
00745         if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)
00746             break;
00747         NutDelay(1);
00748     }
00749     return tmo ? 0 : -1;
00750 }
00751 
00752 /*!
00753  * \brief Reset the Ethernet controller.
00754  *
00755  * \return 0 on success, -1 otherwise.
00756  */
00757 static int NicReset(void)
00758 {
00759 #ifdef LANC111_RESET_BIT
00760     sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);
00761     sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00762     NutDelay(WAIT100);
00763     cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);
00764     NutDelay(WAIT250);
00765     NutDelay(WAIT250);
00766 #endif
00767 
00768     /* Disable all interrupts. */
00769     nic_outlb(NIC_MSK, 0);
00770 
00771     /* MAC and PHY software reset. */
00772     nic_bs(0);
00773     nic_outw(NIC_RCR, RCR_SOFT_RST);
00774 
00775     /* Enable Ethernet protocol handler. */
00776     nic_bs(1);
00777     nic_outw(NIC_CR, CR_EPH_EN);
00778 
00779     NutDelay(10);
00780 
00781     /* Disable transmit and receive. */
00782     nic_bs(0);
00783     nic_outw(NIC_RCR, 0);
00784     nic_outw(NIC_TCR, 0);
00785 
00786     /* Enable auto release. */
00787     nic_bs(1);
00788     nic_outw(NIC_CTR, CTR_AUTO_RELEASE);
00789 
00790     /* Reset MMU. */
00791     nic_bs(2);
00792     nic_outlb(NIC_MMUCR, MMU_RST);
00793     if (NicMmuWait(1000))
00794         return -1;
00795 
00796     return 0;
00797 }
00798 
00799 /*
00800  * Fires up the network interface. NIC interrupts
00801  * should have been disabled when calling this
00802  * function.
00803  *
00804  * \param mac Six byte unique MAC address.
00805  */
00806 static int NicStart(CONST uint8_t * mac)
00807 {
00808     uint8_t i;
00809 
00810     if (NicReset())
00811         return -1;
00812 
00813     /* Enable receiver. */
00814     nic_bs(3);
00815     nic_outlb(NIC_ERCV, 7);
00816     nic_bs(0);
00817     nic_outw(NIC_RCR, RCR_RXEN);
00818 
00819     /* Enable transmitter and padding. */
00820     nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);
00821 
00822     /* Configure the PHY. */
00823     if (NicPhyConfig())
00824         return -1;
00825 
00826     /* Set MAC address. */
00827     //printf("Set MAC %02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00828     nic_bs(1);
00829     for (i = 0; i < 6; i++)
00830         nic_outlb(NIC_IAR + i, mac[i]);
00831     //printf("OK\n");
00832 
00833     /* Enable interrupts. */
00834     nic_bs(2);
00835     nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);
00836 
00837     return 0;
00838 }
00839 
00840 /*
00841  * NIC interrupt entry.
00842  */
00843 #if 0
00844 static void NicInterrupt(void *arg)
00845 {
00846     uint8_t isr;
00847     uint8_t imr;
00848     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00849 
00850     ni->ni_interrupts++;
00851 
00852     /* Read the interrupt mask and disable all interrupts. */
00853     nic_bs(2);
00854     imr = nic_inlb(NIC_MSK);
00855     nic_outlb(NIC_MSK, 0);
00856 
00857     /* Read the interrupt status and acknowledge all interrupts. */
00858     isr = nic_inlb(NIC_IST);
00859     //printf("\n!%02X-%02X ", isr, imr);
00860     isr &= imr;
00861 
00862     /*
00863      * If this is a transmit interrupt, then a packet has been sent. 
00864      * So we can clear the transmitter busy flag and wake up the 
00865      * transmitter thread.
00866      */
00867     if (isr & INT_TX_EMPTY) {
00868         nic_outlb(NIC_ACK, INT_TX_EMPTY);
00869         imr &= ~INT_TX_EMPTY;
00870         NutEventPostFromIrq(&ni->ni_tx_rdy);
00871     }
00872     /* Transmit error. */
00873     else if (isr & INT_TX) {
00874         /* re-enable transmit */
00875         nic_bs(0);
00876         nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);
00877         nic_bs(2);
00878         nic_outlb(NIC_ACK, INT_TX);
00879         /* kill the packet */
00880         nic_outlb(NIC_MMUCR, MMU_PKT);
00881 
00882         NutEventPostFromIrq(&ni->ni_tx_rdy);
00883     }
00884 
00885 
00886     /*
00887      * If this is a receive interrupt, then wake up the receiver 
00888      * thread.
00889      */
00890     if (isr & INT_RX_OVRN) {
00891         nic_outlb(NIC_ACK, INT_RX_OVRN);
00892         //nic_outlb(NIC_MMUCR, MMU_TOP);
00893     }
00894     if (isr & INT_ERCV) {
00895         nic_outlb(NIC_ACK, INT_ERCV);
00896         NutEventPostFromIrq(&ni->ni_rx_rdy);
00897     }
00898     if (isr & INT_RCV) {
00899         nic_outlb(NIC_ACK, INT_RCV);
00900         imr &= ~INT_RCV;
00901         NutEventPostFromIrq(&ni->ni_rx_rdy);
00902     }
00903 
00904     if (isr & INT_ALLOC) {
00905         imr &= ~INT_ALLOC;
00906         NutEventPostFromIrq(&maq);
00907     }
00908     //printf(" -%02X-%02X- ", nic_inlb(NIC_IST), inb(PINE) & 0x20);
00909     nic_outlb(NIC_MSK, imr);
00910 }
00911 #endif /* 0 */
00912 /*
00913  * Write data block to the NIC.
00914  */
00915 static void NicWrite(uint8_t * buf, uint16_t len)
00916 {
00917     register uint16_t l = len - 1;
00918     register uint8_t ih = (uint16_t) l >> 8;
00919     register uint8_t il = (uint8_t) l;
00920 
00921     if (!len)
00922         return;
00923 
00924     do {
00925         do {
00926             nic_outlb(NIC_DATA, *buf++);
00927         } while (il-- != 0);
00928     } while (ih-- != 0);
00929 }
00930 
00931 /*
00932  * Read data block from the NIC.
00933  */
00934 static void NicRead(uint8_t * buf, uint16_t len)
00935 {
00936     register uint16_t l = len - 1;
00937     register uint8_t ih = (uint16_t) l >> 8;
00938     register uint8_t il = (uint8_t) l;
00939 
00940     if (!len)
00941         return;
00942 
00943     do {
00944         do {
00945             *buf++ = nic_inlb(NIC_DATA);
00946         } while (il-- != 0);
00947     } while (ih-- != 0);
00948 }
00949 
00950 /*!
00951  * \brief Fetch the next packet out of the receive ring buffer.
00952  *
00953  * Nic interrupts must be disabled when calling this funtion.
00954  *
00955  * \return Pointer to an allocated ::NETBUF. If there is no
00956  *         no data available, then the function returns a
00957  *         null pointer. If the NIC's buffer seems to be
00958  *         corrupted, a pointer to 0xFFFF is returned.
00959  */
00960 static NETBUF *NicGetPacket(void)
00961 {
00962     NETBUF *nb = 0;
00963     //uint8_t *buf;
00964     uint16_t fsw;
00965     uint16_t fbc;
00966 
00967     /* Check the fifo empty bit. If it is set, then there is 
00968        nothing in the receiver fifo. */
00969     nic_bs(2);
00970     if (nic_inw(NIC_FIFO) & 0x8000) {
00971         return 0;
00972     }
00973 
00974     /* Inialize pointer register. */
00975     nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);
00976     _NOP();
00977     _NOP();
00978     _NOP();
00979     _NOP();
00980 
00981     /* Read status word and byte count. */
00982     fsw = nic_inw(NIC_DATA);
00983     fbc = nic_inw(NIC_DATA);
00984     //printf("[SW=%04X,BC=%04X]", fsw, fbc);
00985 
00986     /* Check for frame errors. */
00987     if (fsw & 0xAC00) {
00988         nb = (NETBUF *) 0xFFFF;
00989     }
00990     /* Check the byte count. */
00991     else if (fbc < 66 || fbc > 1524) {
00992         nb = (NETBUF *) 0xFFFF;
00993     }
00994 
00995     else {
00996         /* 
00997          * Allocate a NETBUF. 
00998          * Hack alert: Rev A chips never set the odd frame indicator.
00999          */
01000         fbc -= 3;
01001         /*        nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);*/
01002 
01003         /* Perform the read. */
01004 /*              if (nb)
01005                 NicRead(nb->nb_dl.vp, fbc);*/
01006     }
01007 
01008     /* Release the packet. */
01009     nic_outlb(NIC_MMUCR, MMU_TOP);
01010 
01011     return nb;
01012 }
01013 
01014 /*!
01015  * \brief Load a packet into the nic's transmit ring buffer.
01016  *
01017  * Interupts must have been disabled when calling this function.
01018  *
01019  * \param nb Network buffer structure containing the packet to be sent.
01020  *           The structure must have been allocated by a previous
01021  *           call NutNetBufAlloc(). This routine will automatically
01022  *           release the buffer in case of an error.
01023  *
01024  * \return 0 on success, -1 in case of any errors. Errors
01025  *         will automatically release the network buffer 
01026  *         structure.
01027  */
01028 #if 0
01029 static int NicPutPacket(NETBUF * nb)
01030 {
01031     uint16_t sz;
01032     uint8_t odd = 0;
01033     uint8_t imsk;
01034 
01035     //printf("[P]");
01036     /*
01037      * Calculate the number of bytes to be send. Do not send packets 
01038      * larger than the Ethernet maximum transfer unit. The MTU
01039      * consist of 1500 data bytes plus the 14 byte Ethernet header
01040      * plus 4 bytes CRC. We check the data bytes only.
01041      */
01042     if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
01043         return -1;
01044 
01045     /* Disable all interrupts. */
01046     imsk = nic_inlb(NIC_MSK);
01047     nic_outlb(NIC_MSK, 0);
01048 
01049     /* Allocate packet buffer space. */
01050     nic_bs(2);
01051     nic_outlb(NIC_MMUCR, MMU_ALO);
01052     if (NicMmuWait(100))
01053         return -1;
01054 
01055     /* Enable interrupts including allocation success. */
01056     nic_outlb(NIC_MSK, imsk | INT_ALLOC);
01057 
01058     /* The MMU needs some time. Use it to calculate the byte count. */
01059     sz += nb->nb_dl.sz;
01060     sz += 6;
01061     if (sz & 1) {
01062         sz++;
01063         odd++;
01064     }
01065 
01066     /* Wait for allocation success. */
01067     while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01068         if (NutEventWait(&maq, 125)) {
01069             nic_outlb(NIC_MMUCR, MMU_RST);
01070             NicMmuWait(1000);
01071             nic_outlb(NIC_MMUCR, MMU_ALO);
01072             if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {
01073                 if (NutEventWait(&maq, 125)) {
01074                     return -1;
01075                 }
01076             }
01077         }
01078     }
01079 
01080     /* Disable interrupts. */
01081     imsk = nic_inlb(NIC_MSK);
01082     nic_outlb(NIC_MSK, 0);
01083 
01084 
01085     nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));
01086 
01087     nic_outw(NIC_PTR, 0x4000);
01088 
01089     /* Transfer control word. */
01090     nic_outlb(NIC_DATA, 0);
01091     nic_outlb(NIC_DATA, 0);
01092 
01093     /* Transfer the byte count. */
01094     nic_outw(NIC_DATA, sz);
01095 
01096     /* Transfer the Ethernet frame. */
01097     NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
01098     NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
01099     NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
01100     NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
01101 
01102     if (odd)
01103         nic_outlb(NIC_DATA, 0);
01104 
01105     /* Transfer the control word. */
01106     nic_outw(NIC_DATA, 0);
01107 
01108     /* Enqueue packet. */
01109     if (NicMmuWait(100))
01110         return -1;
01111     nic_outlb(NIC_MMUCR, MMU_ENQ);
01112 
01113     /* Enable interrupts. */
01114     imsk |= INT_TX | INT_TX_EMPTY;
01115     nic_outlb(NIC_MSK, imsk);
01116 
01117     return 0;
01118 }
01119 #endif
01120 
01121 /*! \fn NicRxLanc(void *arg)
01122  * \brief NIC receiver thread.
01123  *
01124  */
01125 #if 1
01126 PROCESS_THREAD(lanc111_process, ev, data)
01127      /*THREAD(NicRxLanc, arg)*/
01128 {
01129   /*    NUTDEVICE *dev;
01130     IFNET *ifn;
01131     NICINFO *ni;
01132     NETBUF *nb;*/
01133   uint8_t imsk;
01134   static struct etimer et;
01135   
01136     /*    dev = arg;
01137     ifn = (IFNET *) dev->dev_icb;
01138     ni = (NICINFO *) dev->dev_dcb;*/
01139 
01140     /*
01141      * This is a temporary hack. Due to a change in initialization,
01142      * we may not have got a MAC address yet. Wait until one has been
01143      * set.
01144      */
01145 
01146   PROCESS_BEGIN();
01147   
01148   /*    while(*((u_long *) (ifn->if_mac)) &&
01149    *((u_long *) (ifn->if_mac)) != 0xFFFFFFFFUL) {*/
01150   while(0) {
01151       etimer_set(&et, CLOCK_SECOND / 8);
01152       PROCESS_WAIT_UNTIL(etimer_expired(&et));
01153     }
01154 
01155     /*
01156      * Do not continue unless we managed to start the NIC. We are
01157      * trapped here if the Ethernet link cannot be established.
01158      * This happens, for example, if no Ethernet cable is plugged
01159      * in.
01160      */
01161   /*    while(NicStart(ifn->if_mac)) {*/
01162   while(0) {
01163       /*NutSleep(1000);*/
01164       etimer_set(&et, CLOCK_SECOND);
01165       PROCESS_WAIT_UNTIL(etimer_expired(&et));
01166     }
01167 
01168     LANC111_SIGNAL_MODE();
01169     sbi(EIMSK, LANC111_SIGNAL_IRQ);
01170 
01171     /*    NutEventPost(&mutex);*/
01172 
01173     /* Run at high priority. */
01174     /*    NutThreadSetPriority(9);*/
01175 
01176     for (;;) {
01177 
01178         /*
01179          * Wait for the arrival of new packets or
01180          * check the receiver every two second.
01181          */
01182       /*        NutEventWait(&ni->ni_rx_rdy, 2000);*/
01183       PROCESS_WAIT_EVENT();
01184 
01185         /*
01186          * Fetch all packets from the NIC's internal
01187          * buffer and pass them to the registered handler.
01188          */
01189         imsk = nic_inlb(NIC_MSK);
01190         nic_outlb(NIC_MSK, 0);
01191         /*      while ((nb = NicGetPacket()) != 0) {
01192             if (nb != (NETBUF *) 0xFFFF) {
01193               ni->ni_rx_packets++;
01194               (*ifn->if_recv) (dev, nb);              
01195             }
01196             }*/
01197         nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);
01198     }
01199 
01200     PROCESS_END();
01201 }
01202 #endif  /* 0 */
01203 /*!
01204  * \brief Send Ethernet packet.
01205  *
01206  * \param dev   Identifies the device to use.
01207  * \param nb    Network buffer structure containing the packet to be sent.
01208  *              The structure must have been allocated by a previous
01209  *              call NutNetBufAlloc().
01210  *
01211  * \return 0 on success, -1 in case of any errors.
01212  */
01213 #if 0
01214 int LancOutput(NUTDEVICE * dev, NETBUF * nb)
01215 {
01216     static u_long mx_wait = 5000;
01217     int rc = -1;
01218     NICINFO *ni;
01219 
01220     /*
01221      * After initialization we are waiting for a long time to give
01222      * the PHY a chance to establish an Ethernet link.
01223      */
01224     if (NutEventWait(&mutex, mx_wait) == 0) {
01225         ni = (NICINFO *) dev->dev_dcb;
01226 
01227         if (NicPutPacket(nb) == 0) {
01228             ni->ni_tx_packets++;
01229             rc = 0;
01230             /* Ethernet works. Set a long waiting time in case we
01231                temporarly lose the link next time. */
01232             mx_wait = 5000;
01233         }
01234         NutEventPost(&mutex);
01235     }
01236     /*
01237      * Probably no Ethernet link. Significantly reduce the waiting
01238      * time, so following transmission will soon return an error.
01239      */
01240     else {
01241         mx_wait = 500;
01242     }
01243     return rc;
01244 }
01245 #endif
01246 #if 0
01247 /*!
01248  * \brief Initialize Ethernet hardware.
01249  *
01250  * Resets the LAN91C111 Ethernet controller, initializes all required 
01251  * hardware registers and starts a background thread for incoming 
01252  * Ethernet traffic.
01253  *
01254  * Applications should do not directly call this function. It is 
01255  * automatically executed during during device registration by 
01256  * NutRegisterDevice().
01257  *
01258  * If the network configuration hasn't been set by the application
01259  * before registering the specified device, this function will
01260  * call NutNetLoadConfig() to get the MAC address.
01261  *
01262  * \param dev Identifies the device to initialize.
01263  */
01264 int LancInit(NUTDEVICE * dev)
01265 {
01266     /* Disable NIC interrupt and clear NICINFO structure. */
01267     cbi(EIMSK, LANC111_SIGNAL_IRQ);
01268     memset(dev->dev_dcb, 0, sizeof(NICINFO));
01269 
01270     /* Register interrupt handler and enable interrupts. */
01271     if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01272         return -1;
01273 
01274     /*
01275      * Start the receiver thread.
01276      */
01277     NutThreadCreate("rxi5", NicRxLanc, dev, 640);
01278 
01279     //NutSleep(500);
01280 
01281     return 0;
01282 }
01283 
01284 /*@}*/
01285 
01286 /*!
01287  * \addtogroup xgSmscDev
01288  */
01289 /*@{*/
01290 
01291 static NICINFO dcb_eth0;
01292 
01293 /*!
01294  * \brief Network interface information structure.
01295  *
01296  * Used to call.
01297  */
01298 static IFNET ifn_eth0 = {
01299     IFT_ETHER,                  /*!< \brief Interface type. */
01300     {0, 0, 0, 0, 0, 0},         /*!< \brief Hardware net address. */
01301     0,                          /*!< \brief IP address. */
01302     0,                          /*!< \brief Remote IP address for point to point. */
01303     0,                          /*!< \brief IP network mask. */
01304     ETHERMTU,                   /*!< \brief Maximum size of a transmission unit. */
01305     0,                          /*!< \brief Packet identifier. */
01306     0,                          /*!< \brief Linked list of arp entries. */
01307     NutEtherInput,              /*!< \brief Routine to pass received data to, if_recv(). */
01308     LancOutput,                 /*!< \brief Driver output routine, if_send(). */
01309     NutEtherOutput              /*!< \brief Media output routine, if_output(). */
01310 };
01311 
01312 /*!
01313  * \brief Device information structure.
01314  *
01315  * A pointer to this structure must be passed to NutRegisterDevice() 
01316  * to bind this Ethernet device driver to the Nut/OS kernel.
01317  * An application may then call NutNetIfConfig() with the name \em eth0 
01318  * of this driver to initialize the network interface.
01319  * 
01320  */
01321 NUTDEVICE devSmsc111 = {
01322     0,                          /* Pointer to next device. */
01323     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        /* Unique device name. */
01324     IFTYP_NET,                  /* Type of device. */
01325     0,                          /* Base address. */
01326     0,                          /* First interrupt number. */
01327     &ifn_eth0,                  /* Interface control block. */
01328     &dcb_eth0,                  /* Driver control block. */
01329     LancInit,                   /* Driver initialization routine. */
01330     0,                          /* Driver specific control function. */
01331     0,                          /* Read from device. */
01332     0,                          /* Write to device. */
01333     0,                          /* Write from program space data to device. */
01334     0,                          /* Open a device or file. */
01335     0,                          /* Close a device or file. */
01336     0                           /* Request file size. */
01337 };
01338 
01339 /*@}*/
01340 #endif
01341 
01342 
01343 int
01344 lanc111_init(void)
01345 {
01346     /* Disable NIC interrupt and clear NICINFO structure. */
01347     cbi(EIMSK, LANC111_SIGNAL_IRQ);
01348 
01349     /* Register interrupt handler and enable interrupts. */
01350     /*    if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))
01351           return -1;*/
01352 
01353     /*
01354      * Start the receiver thread.
01355      */
01356     /*    NutThreadCreate("rxi5", NicRxLanc, dev, 640);*/
01357 
01358     //NutSleep(500);
01359 
01360     return 0;
01361 }
01362