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

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