Contiki 2.6
|
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