nicrtl.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log: nicrtl.c,v $
00036  * Revision 1.5  2008/08/11 06:59:17  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.4  2006/06/27 01:42:56  hwmaier
00040  * Fixed bug related to edge triggered interrupt mode (RTL_IRQ_RISING_EDGE) in ISR.
00041  *
00042  * Revision 1.3  2006/03/02 23:57:12  hwmaier
00043  * Include cfg/dev.h added
00044  *
00045  * Revision 1.2  2006/01/11 08:33:30  hwmaier
00046  * Changes to make receiver thread's stack size configurable and honour
00047  * the NUT_THREAD_NICRXSTACK configuration setting
00048  *
00049  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00050  * Moved from dev.
00051  *
00052  * Revision 1.15  2005/04/30 16:42:41  chaac
00053  * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG
00054  * is defined in NutConf, it will make effect where it is used.
00055  *
00056  * Revision 1.14  2005/02/10 07:06:18  hwmaier
00057  * Changes to incorporate support for AT90CAN128 CPU
00058  *
00059  * Revision 1.13  2005/02/05 20:42:38  haraldkipp
00060  * Force compiler error for leftover debug prints.
00061  *
00062  * Revision 1.12  2005/01/24 21:11:50  freckle
00063  * renamed NutEventPostFromIRQ into NutEventPostFromIrq
00064  *
00065  * Revision 1.11  2005/01/22 19:24:46  haraldkipp
00066  * Changed AVR port configuration names from PORTx to AVRPORTx.
00067  *
00068  * Revision 1.10  2005/01/21 16:49:46  freckle
00069  * Seperated calls to NutEventPostAsync between Threads and IRQs
00070  *
00071  * Revision 1.9  2004/12/17 15:31:28  haraldkipp
00072  * Support of rising edge interrupts for hardware w/o inverter gate.
00073  * Fixed compilation issue for hardware with RTL reset port.
00074  * Thanks to FOCUS Software Engineering Pty Ltd.
00075  *
00076  * Revision 1.8  2004/09/10 10:36:01  haraldkipp
00077  * ICCAVR compile problems fixed
00078  *
00079  * Revision 1.7  2004/08/25 10:41:00  haraldkipp
00080  * Hardware dependent definitions are configurable. For performance reasons the
00081  * base address is not kept in a variable any longer. It is now a preprocessor
00082  * macro and the parameters during device registration are ignored. The speed
00083  * improvements provided by Kolja Waschk for the LAN91C111 had been implemented
00084  * here too. The driver will not touch a port anymore unless a reset port bit
00085  * had been configured. For Ethernut 1.1 bit 4 PORTE must be specified in the
00086  * configuration. Finally, an EEPROM emulation had been added, which can use
00087  * address bus bits instead of wasting additional port pins. The required
00088  * hardware has been implemented on Rev.-G Ethernut 1.3 boards. This fixes the
00089  * Realtek full duplex problem.
00090  *
00091  * Revision 1.6  2004/05/17 19:14:53  haraldkipp
00092  * Added Bengt Florin's RTL8019 driver mods
00093  *
00094  * Revision 1.5  2004/03/16 16:48:27  haraldkipp
00095  * Added Jan Dubiec's H8/300 port.
00096  *
00097  * Revision 1.4  2003/08/05 20:05:59  haraldkipp
00098  * Bugfix. Empty MAC address is FF, not 00
00099  *
00100  * Revision 1.3  2003/07/17 09:39:56  haraldkipp
00101  * Optimized controller feeding.
00102  * Ignore LSB of packet status.
00103  *
00104  * Revision 1.2  2003/05/15 14:09:16  haraldkipp
00105  * Much better performance under heavy traffic.
00106  *
00107  * Revision 1.1.1.1  2003/05/09 14:40:48  haraldkipp
00108  * Initial using 3.2.1
00109  *
00110  */
00111 
00112 #include <cfg/os.h>
00113 #include <cfg/arch/avr.h>
00114 #include <cfg/dev.h>
00115 
00116 #include <string.h>
00117 
00118 #include <sys/atom.h>
00119 #include <sys/heap.h>
00120 #include <sys/thread.h>
00121 #include <sys/event.h>
00122 #include <sys/timer.h>
00123 #include <sys/confnet.h>
00124 
00125 #include <net/ether.h>
00126 #include <net/if_var.h>
00127 
00128 #include <dev/irqreg.h>
00129 #include <dev/nicrtl.h>
00130 #include "rtlregs.h"
00131 
00132 #ifdef NUTDEBUG
00133 #include <sys/osdebug.h>
00134 #include <net/netdebug.h>
00135 #endif
00136 
00137 #ifndef NUT_THREAD_NICRXSTACK
00138 #define NUT_THREAD_NICRXSTACK   640
00139 #endif
00140 
00141 /*
00142  * Determine ports, which had not been explicitely configured.
00143  */
00144 #if (RTL_EESK_AVRPORT == AVRPORTB)
00145 #define RTL_EESK_PIN    PINB
00146 #define RTL_EESK_DDR    DDRB
00147 
00148 #elif (RTL_EESK_AVRPORT == AVRPORTC)
00149 #define RTL_EE_MEMBUS
00150 #define RTL_EESK_PIN    PINC
00151 #define RTL_EESK_DDR    DDRC
00152 
00153 #elif (RTL_EESK_AVRPORT == AVRPORTD)
00154 #define RTL_EESK_PIN    PIND
00155 #define RTL_EESK_DDR    DDRD
00156 
00157 #elif (RTL_EESK_AVRPORT == AVRPORTE)
00158 #define RTL_EESK_PIN    PINE
00159 #define RTL_EESK_DDR    DDRE
00160 
00161 #elif (RTL_EESK_AVRPORT == AVRPORTF)
00162 #define RTL_EESK_PIN    PINF
00163 #define RTL_EESK_DDR    DDRF
00164 
00165 #endif /* RTL_EESK_AVRPORT */
00166 
00167 #if (RTL_EEDO_AVRPORT == AVRPORTB)
00168 #define RTL_EEDO_PORT   PORTB
00169 #define RTL_EEDO_DDR    DDRB
00170 
00171 #elif (RTL_EEDO_AVRPORT == AVRPORTC)
00172 #define RTL_EE_MEMBUS
00173 #define RTL_EEDO_PORT   PORTC
00174 #define RTL_EEDO_DDR    DDRC
00175 
00176 #elif (RTL_EEDO_AVRPORT == AVRPORTD)
00177 #define RTL_EEDO_PORT   PORTD
00178 #define RTL_EEDO_DDR    DDRD
00179 
00180 #elif (RTL_EEDO_AVRPORT == AVRPORTE)
00181 #define RTL_EEDO_PORT   PORTE
00182 #define RTL_EEDO_DDR    DDRE
00183 
00184 #elif (RTL_EEDO_AVRPORT == AVRPORTF)
00185 #define RTL_EEDO_PORT   PORTF
00186 #define RTL_EEDO_DDR    DDRF
00187 
00188 #endif /* RTL_EEDO_AVRPORT */
00189 
00190 #if (RTL_EEMU_AVRPORT == AVRPORTB)
00191 #define RTL_EEMU_PORT   PORTB
00192 #define RTL_EEMU_DDR    DDRB
00193 
00194 #elif (RTL_EEMU_AVRPORT == AVRPORTC)
00195 #define RTL_EE_MEMBUS
00196 #define RTL_EEMU_PORT   PORTC
00197 #define RTL_EEMU_DDR    DDRC
00198 
00199 #elif (RTL_EEMU_AVRPORT == AVRPORTD)
00200 #define RTL_EEMU_PORT   PORTD
00201 #define RTL_EEMU_DDR    DDRD
00202 
00203 #elif (RTL_EEMU_AVRPORT == AVRPORTE)
00204 #define RTL_EEMU_PORT   PORTE
00205 #define RTL_EEMU_DDR    DDRE
00206 
00207 #elif (RTL_EEMU_AVRPORT == AVRPORTF)
00208 #define RTL_EEMU_PORT   PORTF
00209 #define RTL_EEMU_DDR    DDRF
00210 
00211 #endif /* RTL_EEMU_AVRPORT */
00212 
00213 #if (RTL_RESET_AVRPORT == AVRPORTB)
00214 #define RTL_RESET_PORT   PORTB
00215 #define RTL_RESET_DDR    DDRB
00216 
00217 #elif (RTL_RESET_AVRPORT == AVRPORTD)
00218 #define RTL_RESET_PORT   PORTD
00219 #define RTL_RESET_DDR    DDRD
00220 
00221 #elif (RTL_RESET_AVRPORT == AVRPORTE)
00222 #define RTL_RESET_PORT   PORTE
00223 #define RTL_RESET_DDR    DDRE
00224 
00225 #elif (RTL_RESET_AVRPORT == AVRPORTF)
00226 #define RTL_RESET_PORT   PORTF
00227 #define RTL_RESET_DDR    DDRF
00228 
00229 #endif /* RTL_RESET_AVRPORT */
00230 
00231 
00235 #if (RTL_SIGNAL_IRQ == INT0)
00236 #define RTL_SIGNAL sig_INTERRUPT0
00237 #ifdef __AVR_ENHANCED__
00238 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC00); sbi(EICRA, ISC01)
00239 #endif
00240 
00241 #elif (RTL_SIGNAL_IRQ == INT1)
00242 #define RTL_SIGNAL sig_INTERRUPT1
00243 #ifdef __AVR_ENHANCED__
00244 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC10); sbi(EICRA, ISC11)
00245 #endif
00246 
00247 #elif (RTL_SIGNAL_IRQ == INT2)
00248 #define RTL_SIGNAL sig_INTERRUPT2
00249 #ifdef __AVR_ENHANCED__
00250 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC20); sbi(EICRA, ISC21)
00251 #endif
00252 
00253 #elif (RTL_SIGNAL_IRQ == INT3)
00254 #define RTL_SIGNAL sig_INTERRUPT3
00255 #ifdef __AVR_ENHANCED__
00256 #define RTL_RISING_EDGE_MODE()   sbi(EICRA, ISC30); sbi(EICRA, ISC31)
00257 #endif
00258 
00259 #elif (RTL_SIGNAL_IRQ == INT4)
00260 #define RTL_SIGNAL sig_INTERRUPT4
00261 #ifdef __AVR_ENHANCED__
00262 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC40); sbi(EICRB, ISC41)
00263 #endif
00264 
00265 #elif (RTL_SIGNAL_IRQ == INT6)
00266 #define RTL_SIGNAL sig_INTERRUPT6
00267 #ifdef __AVR_ENHANCED__
00268 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC60); sbi(EICRB, ISC61)
00269 #endif
00270 
00271 #elif (RTL_SIGNAL_IRQ == INT7)
00272 #define RTL_SIGNAL sig_INTERRUPT7
00273 #ifdef __AVR_ENHANCED__
00274 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC70); sbi(EICRB, ISC71)
00275 #endif
00276 
00277 #else
00278 #define RTL_SIGNAL sig_INTERRUPT5
00279 #ifdef __AVR_ENHANCED__
00280 #define RTL_RISING_EDGE_MODE()   sbi(EICRB, ISC50); sbi(EICRB, ISC51)
00281 #endif
00282 
00283 #endif /* RTL_SIGNAL_IRQ */
00284 
00285 
00289 #define NIC_PAGE_SIZE   0x100
00290 
00294 #define NIC_START_PAGE  0x40
00295 
00299 #define NIC_STOP_PAGE   0x60
00300 
00306 #define NIC_TX_PAGES    6
00307 
00328 #define NIC_TX_BUFFERS      1
00329 
00330 #define NIC_FIRST_TX_PAGE   NIC_START_PAGE
00331 #define NIC_FIRST_RX_PAGE   (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)
00332 
00333 #define NIC_CR_PAGE0 (0)
00334 #define NIC_CR_PAGE1 (NIC_CR_PS0)
00335 #define NIC_CR_PAGE2 (NIC_CR_PS1)
00336 #define NIC_CR_PAGE3 (NIC_CR_PS1 | NIC_CR_PS0)
00337 
00338 /*
00339  * This delay has been added by Bengt Florin and is used to minimize
00340  * the effect of the IORDY line during reads. Bengt contributed a
00341  * more versatile loop, which unfortunately wasn't portable to the
00342  * ImageCraft compiler.
00343  *
00344  * Both versions depend on the CPU clock and had been tested with
00345  * 14.7456 MHz.
00346  */
00347 static INLINE void Delay16Cycles(void)
00348 {
00349     _NOP();
00350     _NOP();
00351     _NOP();
00352     _NOP();
00353     _NOP();
00354     _NOP();
00355     _NOP();
00356     _NOP();
00357     _NOP();
00358     _NOP();
00359     _NOP();
00360     _NOP();
00361     _NOP();
00362     _NOP();
00363     _NOP();
00364     _NOP();
00365 }
00366 
00371 
00375 struct nic_pkt_header {
00376     uint8_t ph_status;           
00377     uint8_t ph_nextpg;           
00378     uint16_t ph_size;            
00379 };
00380 
00381 #define NICINB(reg)         (*((volatile uint8_t *)RTL_BASE_ADDR + reg))
00382 #define NICOUTB(reg, val)   (*((volatile uint8_t *)RTL_BASE_ADDR + reg) = val)
00383 
00388 static int NicReset(void)
00389 {
00390     uint8_t i;
00391     uint8_t j;
00392 
00393 /*
00394  * Toggle the hardware reset line. Since Ethernut version 1.3 the
00395  * hardware reset pin of the nic is no longer connected to bit 4
00396  * on port E, but wired to the board reset line.
00397  */
00398 #ifdef RTL_RESET_BIT
00399     sbi(RTL_RESET_DDR, RTL_RESET_BIT);
00400     sbi(RTL_RESET_PORT, RTL_RESET_BIT);
00401     NutDelay(WAIT100);
00402     cbi(RTL_RESET_PORT, RTL_RESET_BIT);
00403     NutDelay(WAIT250);
00404     NutDelay(WAIT250);
00405 #endif
00406 
00407     /*
00408      * Do the software reset by reading from the reset register followed
00409      * by writing to the reset register. Wait until the controller enters
00410      * the reset state.
00411      */
00412     for (j = 0; j < 20; j++) {
00413         i = NICINB(NIC_RESET);
00414         NutDelay(WAIT5);
00415         NICOUTB(NIC_RESET, i);
00416         for (i = 0; i < 20; i++) {
00417             NutDelay(WAIT50);
00418             /*
00419              * We got the reset bit. However, Ethernut 1.1 may
00420              * still fail because the NIC hasn't got it's hardware
00421              * reset and the data lines remain in tristate. So we
00422              * read noise instead of the register. To solve this
00423              * problem, we will verify the NIC's id.
00424              */
00425             if ((NICINB(NIC_PG0_ISR) & NIC_ISR_RST) != 0 &&     /* */
00426                 NICINB(NIC_PG0_RBCR0) == 0x50 &&        /* */
00427                 NICINB(NIC_PG0_RBCR1) == 0x70)
00428                 return 0;
00429         }
00430     }
00431     return -1;
00432 }
00433 
00434 static int DetectNicEeprom(void)
00435 {
00436 #ifdef RTL_EESK_BIT
00437     register u_int cnt = 0;
00438 
00439     NutEnterCritical();
00440 
00441     /*
00442      * Prepare the EEPROM emulation port bits. Configure the EEDO
00443      * and the EEMU lines as outputs and set both lines to high.
00444      */
00445     sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00446     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00447 #ifdef RTL_EEMU_BIT
00448     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00449     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00450 #endif
00451     NutDelay(20);
00452 
00453     /*
00454      * Force the chip to re-read the EEPROM contents.
00455      */
00456     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00457     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);
00458 
00459     /*
00460      * No external memory access beyond this point.
00461      */
00462 #ifdef RTL_EE_MEMBUS
00463     /*
00464      * No external memory access beyond this point.
00465      */
00466 #ifdef __AVR_ENHANCED__
00467     /* On the ATmega 128 we release bits 5-7 as normal port pins. */
00468     outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));
00469 #else
00470     /* On the ATmega 103 we have to disable the external memory interface. */
00471     cbi(MCUCR, SRE);
00472 #endif
00473 #endif
00474 
00475     /*
00476      * Check, if the chip toggles our EESK input. If not, we do not
00477      * have EEPROM emulation hardware.
00478      */
00479     if (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT)) {
00480         while (++cnt && bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00481     } else {
00482         while (++cnt && bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00483     }
00484 
00485 #ifdef RTL_EE_MEMBUS
00486     /*
00487      * Enable memory interface.
00488      */
00489 #ifdef __AVR_ENHANCED__
00490     /* On the ATmega 128 we release bits 5-7 as normal port pins. */
00491     outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));
00492 #else
00493     /* On the ATmega 103 we have to disable the external memory interface. */
00494     sbi(MCUCR, SRE);
00495 #endif
00496 #endif
00497 
00498     /* Reset port outputs to default. */
00499     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00500     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00501 #ifdef RTL_EEMU_BIT
00502     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00503     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00504 #endif
00505 
00506     /* Restore previous interrupt enable state. */
00507     NutExitCritical();
00508 
00509     /* Wait until controller ready. */
00510     while (NICINB(NIC_CR) != (NIC_CR_STP | NIC_CR_RD2));
00511 
00512     return cnt ? 0 : -1;
00513 #else
00514     return -1;
00515 #endif
00516 }
00517 
00518 #ifdef RTL_EESK_BIT
00519 /*
00520  * Emulated EEPROM contents.
00521  *
00522  * In jumper mode our influence is quite limited, only CONFIG3 and CONFIG4
00523  * can be modified.
00524  */
00525 static prog_char nic_eeprom[18] = {
00526     0xFF,                       /* CONFIG2: jPL1 jPL0   0      jBS4   jBS3   jBS2  jBS1  jBS0  */
00527     0xFF,                       /* CONFIG1: 1    jIRQS2 jIRQS1 jIRQS0 jIOS3  jIOS2 jIOS1 jIOS0 */
00528 
00529     0xFF,                       /* CONFIG4: -    -      -      -      -      -     -     IOMS  */
00530     0x30,                       /* CONFIG3  PNP  FUDUP  LEDS1  LEDS0  -      0     PWRDN ACTB  */
00531 
00532     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* MAC */
00533     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF      /* ID */
00534 };
00535 #endif
00536 
00546 static void EmulateNicEeprom(void)
00547 {
00548 #ifdef RTL_EESK_BIT
00549     register uint8_t clk;
00550     register uint8_t cnt;
00551     register uint8_t val;
00552 
00553     /*
00554      * Disable all interrupts. This routine requires critical timing
00555      * and optionally may disable the memory interface.
00556      */
00557     NutEnterCritical();
00558 
00559     /*
00560      * Prepare the EEPROM emulation port bits. Configure the EEDO and
00561      * the EEMU lines as outputs and set EEDO to low and EEMU to high.
00562      */
00563     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00564     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00565 #ifdef RTL_EEMU_BIT
00566     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00567     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00568 #endif
00569     NutDelay(20);
00570 
00571     /*
00572      * Start EEPROM configuration. Stop/abort any activity and select
00573      * configuration page 3. Setting bit EEM0 will force the controller
00574      * to read the EEPROM contents.
00575      */
00576 
00577     /* Select page 3, stop and abort/complete. */
00578     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00579     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);
00580 
00581     /*
00582      * We can avoid wasting port pins for EEPROM emulation by using the
00583      * upper bits of the address bus.
00584      */
00585 #ifdef RTL_EE_MEMBUS
00586     /*
00587      * No external memory access beyond this point.
00588      */
00589 #ifdef __AVR_ENHANCED__
00590     /* On the ATmega 128 we release bits 5-7 as normal port pins. */
00591     outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));
00592 #else
00593     /* On the ATmega 103 we have to disable the external memory interface. */
00594     cbi(MCUCR, SRE);
00595 #endif
00596 #endif
00597 
00598     /*
00599      * Loop for all EEPROM words.
00600      */
00601     for (cnt = 0; cnt < sizeof(nic_eeprom);) {
00602 
00603         /*
00604          *
00605          * 1 start bit, always high
00606          * 2 op-code bits
00607          * 7 address bits
00608          * 1 dir change bit, always low
00609          */
00610         for (clk = 0; clk < 11; clk++) {
00611             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00612             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00613         }
00614 
00615         /*
00616          * Shift out the high byte, MSB first. Our data changes at the EESK
00617          * rising edge. Data is sampled by the Realtek at the falling edge.
00618          */
00619         val = PRG_RDB(nic_eeprom + cnt);
00620         cnt++;
00621         for (clk = 0x80; clk; clk >>= 1) {
00622             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00623             if (val & clk)
00624                 sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00625             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00626             cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00627         }
00628 
00629         /*
00630          * Shift out the low byte.
00631          */
00632         val = PRG_RDB(nic_eeprom + cnt);
00633         cnt++;
00634         for (clk = 0x80; clk; clk >>= 1) {
00635             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00636             if (val & clk)
00637                 sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00638             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00639             cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00640         }
00641 
00642 
00643         /* 5 remaining clock cycles. */
00644         for (clk = 0; clk < 5; clk++) {
00645             while (bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));
00646             while (bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));
00647         }
00648     }
00649 
00650 #ifdef RTL_EE_MEMBUS
00651     /*
00652      * Enable memory interface.
00653      */
00654 #ifdef __AVR_ENHANCED__
00655     /* On the ATmega 128 we release bits 5-7 as normal port pins. */
00656     outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));
00657 #else
00658     /* On the ATmega 103 we have to disable the external memory interface. */
00659     sbi(MCUCR, SRE);
00660 #endif
00661 #endif
00662 
00663     /* Reset port outputs to default. */
00664     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00665 #ifdef RTL_EEMU_BIT
00666     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00667     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00668 #endif
00669 
00670     /* Restore previous interrupt enable state. */
00671     NutExitCritical();
00672 #endif
00673 }
00674 
00675 /*
00676  * Fires up the network interface. NIC interrupts
00677  * should have been disabled when calling this
00678  * function.
00679  */
00680 static int NicStart(CONST uint8_t * mac)
00681 {
00682     uint8_t i;
00683 
00684     if (NicReset()) {
00685         return -1;
00686     }
00687     if (DetectNicEeprom() == 0) {
00688         EmulateNicEeprom();
00689     }
00690 
00691     /*
00692      * Mask all interrupts and clear any interrupt status flag to set the
00693      * INT pin back to low.
00694      */
00695     NICOUTB(NIC_PG0_IMR, 0);
00696     NICOUTB(NIC_PG0_ISR, 0xff);
00697 
00698     /*
00699      * During reset the nic loaded its initial configuration from an
00700      * external eeprom. On the ethernut board we do not have any
00701      * configuration eeprom, but simply tied the eeprom data line to
00702      * high level. So we have to clear some bits in the configuration
00703      * register. Switch to register page 3.
00704      */
00705     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);
00706 
00707     /*
00708      * The nic configuration registers are write protected unless both
00709      * EEM bits are set to 1.
00710      */
00711     NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);
00712 
00713     /*
00714      * Network media had been set to 10Base2 by the virtual EEPROM and
00715      * will be set now to auto detect. This will initiate a link test.
00716      * We don't force 10BaseT, because this would disable the link test.
00717      */
00718     NICOUTB(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);
00719 
00720     /*
00721      * Disable sleep and power down.
00722      *
00723      * The virtual EEPROM (resistor tight to VCC) will set all bits of
00724      * CONFIG3 to 1. Unfortunately we are not able to modify the full
00725      * duplex bit. The only solution is to use a real EEPROM or emulate
00726      * one.
00727      */
00728     NICOUTB(NIC_PG3_CONFIG3, NIC_CONFIG3_LEDS1 | NIC_CONFIG3_LEDS1);
00729 
00730     /*
00731      * Reenable write protection of the nic configuration registers
00732      * and wait for link test to complete.
00733      */
00734     NICOUTB(NIC_PG3_EECR, 0);
00735     NutDelay(255);
00736 
00737     /*
00738      * Switch to register page 0 and set data configuration register
00739      * to byte-wide DMA transfers, normal operation (no loopback),
00740      * send command not executed and 8 byte fifo threshold.
00741      */
00742     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
00743     NICOUTB(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);
00744 
00745     /*
00746      * Clear remote dma byte count register.
00747      */
00748     NICOUTB(NIC_PG0_RBCR0, 0);
00749     NICOUTB(NIC_PG0_RBCR1, 0);
00750 
00751     /*
00752      * Temporarily set receiver to monitor mode and transmitter to
00753      * internal loopback mode. Incoming packets will not be stored
00754      * in the nic ring buffer and no data will be send to the network.
00755      */
00756     NICOUTB(NIC_PG0_RCR, NIC_RCR_MON);
00757     NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
00758 
00759     /*
00760      * Configure the nic's ring buffer page layout.
00761      * NIC_PG0_BNRY: Last page read.
00762      * NIC_PG0_PSTART: First page of receiver buffer.
00763      * NIC_PG0_PSTOP: Last page of receiver buffer.
00764      */
00765     NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
00766     NICOUTB(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);
00767     NICOUTB(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);
00768     NICOUTB(NIC_PG0_PSTOP, NIC_STOP_PAGE);
00769 
00770     /*
00771      * Once again clear interrupt status register.
00772      */
00773     NICOUTB(NIC_PG0_ISR, 0xff);
00774 
00775     /*
00776      * Switch to register page 1 and copy our MAC address into the nic.
00777      * We are still in stop mode.
00778      */
00779     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
00780     for (i = 0; i < 6; i++)
00781         NICOUTB(NIC_PG1_PAR0 + i, mac[i]);
00782 
00783     /*
00784      * Clear multicast filter bits to disable all packets.
00785      */
00786     for (i = 0; i < 8; i++)
00787         NICOUTB(NIC_PG1_MAR0 + i, 0);
00788 
00789     /*
00790      * Set current page pointer to one page after the boundary pointer.
00791      */
00792     NICOUTB(NIC_PG1_CURR, NIC_FIRST_RX_PAGE);
00793 
00794     /*
00795      * Switch back to register page 0, remaining in stop mode.
00796      */
00797     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
00798 
00799     /*
00800      * Take receiver out of monitor mode and enable it for accepting
00801      * broadcasts.
00802      */
00803     NICOUTB(NIC_PG0_RCR, NIC_RCR_AB);
00804 
00805     /*
00806      * Clear all interrupt status flags and enable interrupts.
00807      */
00808     NICOUTB(NIC_PG0_ISR, 0xff);
00809     /* Note: transmitter if polled, thus no NIC_IMR_PTXE */
00810     NICOUTB(NIC_PG0_IMR, NIC_IMR_PRXE | NIC_IMR_RXEE | NIC_IMR_TXEE | NIC_IMR_OVWE);
00811 
00812     /*
00813      * Fire up the nic by clearing the stop bit and setting the start bit.
00814      * To activate the local receive dma we must also take the nic out of
00815      * the local loopback mode.
00816      */
00817     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
00818     NICOUTB(NIC_PG0_TCR, 0);
00819 
00820     NutDelay(255);
00821 
00822     return 0;
00823 }
00824 
00828 static void NicCompleteDma(void)
00829 {
00830     uint8_t i;
00831 
00832     /*
00833      * Complete remote dma.
00834      */
00835     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
00836 
00837     /*
00838      * Check that we have a DMA complete flag.
00839      */
00840     for (i = 0; i <= 20; i++)
00841         if (NICINB(NIC_PG0_ISR) & NIC_ISR_RDC)
00842             break;
00843 
00844     /*
00845      * Reset remote dma complete flag.
00846      */
00847     NICOUTB(NIC_PG0_ISR, NIC_ISR_RDC);
00848 }
00849 
00850 /*
00851  * Write data block to the NIC.
00852  */
00853 static void NicWrite(uint8_t * buf, uint16_t len)
00854 {
00855     register uint16_t l = len - 1;
00856     register uint8_t ih = (uint16_t) l >> 8;
00857     register uint8_t il = (uint8_t) l;
00858 
00859     if (!len)
00860         return;
00861 
00862     do {
00863         do {
00864             NICOUTB(NIC_IOPORT, *buf++);
00865         } while (il-- != 0);
00866     } while (ih-- != 0);
00867 }
00868 
00869 /*
00870  * Read data block from the NIC.
00871  */
00872 static void NicRead(uint8_t * buf, uint16_t len)
00873 {
00874     register uint16_t l = len - 1;
00875     register uint8_t ih = (uint16_t) l >> 8;
00876     register uint8_t il = (uint8_t) l;
00877 
00878     if (!len)
00879         return;
00880 
00881     do {
00882         do {
00883             *buf++ = NICINB(NIC_IOPORT);
00884         } while (il-- != 0);
00885     } while (ih-- != 0);
00886 }
00887 
00888 
00902 static int NicPutPacket(NETBUF * nb)
00903 {
00904     uint16_t sz;
00905     uint16_t i;
00906     uint8_t padding = 0;
00907 
00908     /*
00909      * Calculate the number of bytes to be send. Do not
00910      * send packets larger than 1514 bytes.
00911      *
00912      * The previous version was wrong by specifying a maximum
00913      * of 1518, because it didn't take the CRC into account,
00914      * which is generated by the hardware and automatically
00915      * appended. Thanks to Bengt Florin, who discovered this.
00916      */
00917     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00918     if (sz > 1514)
00919         return -1;
00920 
00921     /*
00922      * The controller will not append pad bytes,
00923      * so we have to do this.
00924      */
00925     if (sz < 60) {
00926         padding = (uint8_t) (60 - sz);
00927         sz = 60;
00928     }
00929 
00930     /*
00931      * Bengt Florin introduces polling mode for the transmitter. Be
00932      * aware, that this may introduce other problems. If a high
00933      * priority thread is waiting for the transmitter, it may hold
00934      * the CPU for more than 1.2 milliseconds in worst cases.
00935      */
00936     while (NICINB(NIC_CR) & NIC_CR_TXP)
00937         NutThreadYield();
00938 
00939     /* we don't want to be interrupted by NIC owerflow */
00940     cbi(EIMSK, RTL_SIGNAL_IRQ);
00941 
00942     /*
00943      * Set remote dma byte count
00944      * and start address.
00945      */
00946     NICOUTB(NIC_PG0_RBCR0, sz);
00947     NICOUTB(NIC_PG0_RBCR1, sz >> 8);
00948     NICOUTB(NIC_PG0_RSAR0, 0);
00949     NICOUTB(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);
00950 
00951     /*
00952      * Peform the write.
00953      */
00954     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD1);
00955 
00956     /*
00957      * Transfer the Ethernet frame.
00958      */
00959     NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
00960     NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
00961     NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
00962     NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
00963 
00964     /*
00965      * Add pad bytes.
00966      */
00967     for (i = 0; i < padding; i++)
00968         NICOUTB(NIC_IOPORT, 0);
00969 
00970     /*
00971      * Complete remote dma.
00972      */
00973     NicCompleteDma();
00974 
00975     /*
00976      * Number of bytes to be transmitted.
00977      */
00978     NICOUTB(NIC_PG0_TBCR0, (sz & 0xff));
00979     NICOUTB(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));
00980 
00981     /*
00982      * First page of packet to be transmitted.
00983      */
00984     NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);
00985 
00986     /*
00987      * Start transmission.
00988      */
00989     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
00990 
00991     sbi(EIMSK, RTL_SIGNAL_IRQ);
00992 
00993     return 0;
00994 }
00995 
01006 static NETBUF *NicGetPacket(void)
01007 {
01008     NETBUF *nb = 0;
01009     struct nic_pkt_header hdr;
01010     uint16_t count;
01011     uint8_t *buf;
01012     uint8_t nextpg;
01013     uint8_t bnry;
01014     uint8_t curr;
01015     uint16_t i;
01016     uint8_t drop = 0;
01017 
01018     /* we don't want to be interrupted by NIC owerflow */
01019     cbi(EIMSK, RTL_SIGNAL_IRQ);
01020     /*
01021      * Get the current page pointer. It points to the page where the NIC
01022      * will start saving the next incoming packet.
01023      */
01024     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0);
01025     Delay16Cycles();
01026     curr = NICINB(NIC_PG1_CURR);
01027     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
01028 
01029     /*
01030      * Get the pointer to the last page we read from. The following page
01031      * is the one where we start reading. If it's equal to the current
01032      * page pointer, then there's nothing to read. In this case we return
01033      * a null pointer.
01034      */
01035     if ((bnry = NICINB(NIC_PG0_BNRY) + 1) >= NIC_STOP_PAGE)
01036         bnry = NIC_FIRST_RX_PAGE;
01037 
01038     if (bnry == curr) {
01039         sbi(EIMSK, RTL_SIGNAL_IRQ);
01040         return 0;
01041     }
01042 
01043     /*
01044      * Read the NIC specific packet header.
01045      */
01046     NICOUTB(NIC_PG0_RBCR0, sizeof(struct nic_pkt_header));
01047     NICOUTB(NIC_PG0_RBCR1, 0);
01048     NICOUTB(NIC_PG0_RSAR0, 0);
01049     NICOUTB(NIC_PG0_RSAR1, bnry);
01050     buf = (uint8_t *) & hdr;
01051     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
01052     Delay16Cycles();
01053     for (i = 0; i < sizeof(struct nic_pkt_header); i++)
01054         *buf++ = NICINB(NIC_IOPORT);
01055     NicCompleteDma();
01056 
01057     /*
01058      *  Check packet length. Silently discard packets of illegal size.
01059      */
01060     if (hdr.ph_size < 60 + sizeof(struct nic_pkt_header) ||     /* */
01061         hdr.ph_size > 1514 + sizeof(struct nic_pkt_header)) {
01062         drop = 1;
01063     }
01064 
01065     /*
01066      * Calculate the page of the next packet. If it differs from the
01067      * pointer in the packet header, we return with errorcode.
01068      */
01069     nextpg = bnry + (hdr.ph_size >> 8) + ((hdr.ph_size & 0xFF) != 0);
01070     if (nextpg >= NIC_STOP_PAGE) {
01071         nextpg -= NIC_STOP_PAGE;
01072         nextpg += NIC_FIRST_RX_PAGE;
01073     }
01074     if (nextpg != hdr.ph_nextpg) {
01075         uint8_t nextpg1 = nextpg + 1;
01076         if (nextpg1 >= NIC_STOP_PAGE) {
01077             nextpg1 -= NIC_STOP_PAGE;
01078             nextpg1 += NIC_FIRST_RX_PAGE;
01079         }
01080         if (nextpg1 != hdr.ph_nextpg) {
01081             sbi(EIMSK, RTL_SIGNAL_IRQ);
01082             return (NETBUF *) 0xFFFF;
01083         }
01084         nextpg = nextpg1;
01085     }
01086 
01087     /*
01088      * Check packet status. It should have set bit 0, but
01089      * even without this bit packets seem to be OK.
01090      */
01091     if (!drop && ((hdr.ph_status & 0x0E) == 0)) {
01092         /*
01093          * Allocate a NETBUF.
01094          * Omit the fcs.
01095          */
01096         count = hdr.ph_size - 4;
01097         if ((nb = NutNetBufAlloc(0, NBAF_DATALINK, count))) {
01098             /*
01099              * Set remote dma byte count and
01100              * start address. Don't read the
01101              * header again.
01102              */
01103             NICOUTB(NIC_PG0_RBCR0, count);
01104             NICOUTB(NIC_PG0_RBCR1, count >> 8);
01105             NICOUTB(NIC_PG0_RSAR0, sizeof(struct nic_pkt_header));
01106             NICOUTB(NIC_PG0_RSAR1, bnry);
01107 
01108             /*
01109              * Perform the read.
01110              */
01111             NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD0);
01112             Delay16Cycles();
01113             NicRead(nb->nb_dl.vp, count);
01114             NicCompleteDma();
01115         }
01116     }
01117 
01118     /*
01119      * Set boundary register to the last page we read.
01120      * This also drops packets with errors
01121      */
01122     if (--nextpg < NIC_FIRST_RX_PAGE)
01123         nextpg = NIC_STOP_PAGE - 1;
01124     NICOUTB(NIC_PG0_BNRY, nextpg);
01125 
01126     sbi(EIMSK, RTL_SIGNAL_IRQ);
01127     return nb;
01128 }
01129 
01130 /*
01131  * \brief Handle NIC overflows.
01132  *
01133  * When a receiver buffer overflow occurs, the NIC will defer any subsequent
01134  * action until properly restarted.
01135  *
01136  * This routine is called within interrupt context, which introduces a big
01137  * problem. It waits for the last transmission to finish, which may take
01138  * several milliseconds. Since Nut/OS 3.5, we do not support nested interrupts
01139  * on AVR systems anymore. So this routine may now increase interrupt
01140  * latency in an unacceptable way. The solution might be to handle overflows
01141  * in the receiver thread.
01142  *
01143  * In any case, this routines needs a major redesign. But it has been
01144  * tested in its current form to gracefully withstand ping floods. Thanks
01145  * to Bengt Florin for contributing his code, which provides much more
01146  * stability than its predecessor.
01147  */
01148 static uint8_t NicOverflow(void)
01149 {
01150     uint8_t cr;
01151     uint8_t resend = 0;
01152     uint8_t curr;
01153 
01154     /*
01155      * Wait for any transmission in progress. Save the command register,
01156      * so we can later determine, if NIC transmitter has been interrupted.
01157      * or reception in progress.
01158      */
01159     while (NICINB(NIC_CR) & NIC_CR_TXP);
01160     cr = NICINB(NIC_CR);
01161 
01162     /*
01163      * Get the current page pointer. It points to the page where the NIC
01164      * will start saving the next incoming packet.
01165      */
01166     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);
01167     curr = NICINB(NIC_PG1_CURR);
01168     NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);
01169 
01170     /* Clear remote byte count register. */
01171     NICOUTB(NIC_PG0_RBCR0, 0);
01172     NICOUTB(NIC_PG0_RBCR1, 0);
01173 
01174     /* Check for any incomplete transmission. */
01175     if ((cr & NIC_CR_TXP) && ((NICINB(NIC_PG0_ISR) & (NIC_ISR_PTX | NIC_ISR_TXE)) == 0)) {
01176         resend = 1;
01177     }
01178 
01179     /* Enter loopback mode and restart the NIC. */
01180     NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);
01181     NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);
01182 
01183     /*
01184      * Discard all packets from the receiver buffer. Set boundary
01185      * register to the last page we read.
01186      */
01187     if (--curr < NIC_FIRST_RX_PAGE) {
01188         curr = NIC_STOP_PAGE - 1;
01189     }
01190     NICOUTB(NIC_PG0_BNRY, curr);
01191 
01192     /* Switch from loopback to normal mode mode. */
01193     NICOUTB(NIC_PG0_TCR, 0);
01194 
01195     /* Re-invoke any interrupted transmission. */
01196     if (resend) {
01197         NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);
01198     }
01199 
01200     /* Finally clear the overflow flag */
01201     NICOUTB(NIC_PG0_ISR, NIC_ISR_OVW);
01202     return resend;
01203 }
01204 
01205 
01206 /*
01207  * \brief NIC interrupt entry.
01208  */
01209 static void NicInterrupt(void *arg)
01210 {
01211     uint8_t isr;
01212     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
01213 
01214     ni->ni_interrupts++;
01215 
01216 #ifdef RTL_IRQ_RISING_EDGE
01217     do
01218     {
01219 #endif 
01220     isr = NICINB(NIC_PG0_ISR);
01221     NICOUTB(NIC_PG0_ISR, isr);
01222 
01223     /*
01224      * Recover from receive buffer overflow. This may take some
01225      * time, so we enable global interrupts but keep NIC
01226      * interrupts disabled.
01227      */
01228     if (isr & NIC_ISR_OVW) {
01229         /* The AVR platform uses a dedicated interrupt stack, which
01230          * forbids interrupt nesting. */
01231 #if !defined(__AVR__)
01232         cbi(EIMSK, RTL_SIGNAL_IRQ);
01233         sei();
01234 #endif
01235         NicOverflow();
01236 #if !defined(__AVR__)
01237         cli();
01238         sbi(EIMSK, RTL_SIGNAL_IRQ);
01239 #endif
01240         ni->ni_rx_overruns++;
01241     } else {
01242         /*
01243          * If this is a transmit interrupt, then a packet has been sent.
01244          * So we can clear the transmitter busy flag and wake up the
01245          * transmitter thread.
01246          */
01247         if (isr & NIC_ISR_TXE)
01248             ni->ni_tx_errors++;
01249 
01250         /*
01251          * If this is a receive interrupt, then wake up the receiver
01252          * thread.
01253          */
01254         if (isr & NIC_ISR_PRX)
01255             NutEventPostFromIrq(&ni->ni_rx_rdy);
01256 
01257         if (isr & NIC_ISR_RXE) {
01258             ni->ni_rx_frame_errors += NICINB(NIC_PG0_CNTR0);
01259             ni->ni_rx_crc_errors += NICINB(NIC_PG0_CNTR1);
01260             ni->ni_rx_missed_errors += NICINB(NIC_PG0_CNTR2);
01261         }
01262     }
01263 #ifdef RTL_IRQ_RISING_EDGE
01264     /* Check that all unmasked interrupts are cleared before we
01265     * leave the ISR to assert the INT line goes back to low
01266     * and a new interrupt edge will be generated for following
01267     * interrupts.
01268     */
01269     }
01270     while (bit_is_set(PINE, RTL_SIGNAL_IRQ));
01271 #endif
01272 }
01273 
01280 THREAD(NicRx, arg)
01281 {
01282     NUTDEVICE *dev;
01283     IFNET *ifn;
01284     NICINFO *ni;
01285     NETBUF *nb;
01286 
01287     dev = arg;
01288     ifn = (IFNET *) dev->dev_icb;
01289     ni = (NICINFO *) dev->dev_dcb;
01290 
01291     NutThreadSetPriority(9);
01292     /*
01293      * This is a temporary hack. Due to a change in initialization,
01294      * we may not have got a MAC address yet. Wait until one has been
01295      * set.
01296      */
01297     if ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF) {
01298         while ((ifn->if_mac[0] & ifn->if_mac[1] & ifn->if_mac[2]) == 0xFF)
01299             NutSleep(125);
01300         cbi(EIMSK, RTL_SIGNAL_IRQ);
01301         NicStart(ifn->if_mac);
01302         sbi(EIMSK, RTL_SIGNAL_IRQ);
01303     }
01304 
01305     while (1) {
01306         NutEventWait(&ni->ni_rx_rdy, 0);
01307         /*
01308          * Fetch all packets from the NIC's internal
01309          * buffer and pass them to the registered handler.
01310          */
01311         do {
01312             nb = NicGetPacket();
01313 
01314             /* The sanity check may fail because the controller is too busy.
01315                restart the NIC. */
01316             if ((uint16_t) nb == 0xFFFF) {
01317                 NicStart(ifn->if_mac);
01318                 ni->ni_rx_size_errors++;
01319             } else if (nb) {
01320                 ni->ni_rx_packets++;
01321                 (*ifn->if_recv) (dev, nb);
01322             }
01323         } while (nb);
01324     }
01325 }
01326 
01337 int NicOutput(NUTDEVICE * dev, NETBUF * nb)
01338 {
01339     int rc = -1;
01340     NICINFO *ni = (NICINFO *) dev->dev_dcb;
01341 
01342     if (NicPutPacket(nb) == 0) {
01343         ni->ni_tx_packets++;
01344         rc = 0;
01345     }
01346     return rc;
01347 }
01348 
01369 int NicInit(NUTDEVICE * dev)
01370 {
01371     IFNET *ifn;
01372     NICINFO *ni;
01373 
01374     /*
01375      * We need to know our MAC address. If no configuration is
01376      * available, load it now.
01377      */
01378     if (confnet.cd_size == 0)
01379         NutNetLoadConfig(dev->dev_name);
01380 
01381     ifn = dev->dev_icb;
01382     memcpy(ifn->if_mac, confnet.cdn_mac, 6);
01383     ni = (NICINFO *) dev->dev_dcb;
01384     memset(ni, 0, sizeof(NICINFO));
01385 
01386     /*
01387      * Start the receiver thread.
01388      */
01389     NutThreadCreate("rxi5", NicRx, dev, NUT_THREAD_NICRXSTACK);
01390     NutSleep(WAIT500);
01391 
01392     /*
01393      * Register interrupt handler and enable interrupts.
01394      */
01395     if (NutRegisterIrqHandler(&RTL_SIGNAL, NicInterrupt, dev))
01396         return -1;
01397 
01398     cbi(EIMSK, RTL_SIGNAL_IRQ);
01399 #ifdef RTL_IRQ_RISING_EDGE
01400     /* Support of rising edge interrupts for HW w/o inverter gate */
01401     RTL_RISING_EDGE_MODE();
01402 #endif
01403 
01404     if (ifn->if_mac[0] | ifn->if_mac[1] | ifn->if_mac[2])
01405         if (NicStart(ifn->if_mac))
01406             return -1;
01407 
01408     sbi(EIMSK, RTL_SIGNAL_IRQ);
01409 
01410     return 0;
01411 }
01412 
01413 

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