dm9000e.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00003  * Copyright (C) 2003-2005 by egnite Software GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00022  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00035 /*
00036  * $Log: dm9000e.c,v $
00037  * Revision 1.10  2008/08/11 06:59:07  haraldkipp
00038  * BSD types replaced by stdint types (feature request #1282721).
00039  *
00040  * Revision 1.9  2008/02/15 17:09:44  haraldkipp
00041  * Added support for the Elektor Internet Radio.
00042  *
00043  * Revision 1.8  2007/08/17 11:43:46  haraldkipp
00044  * Enable multicast.
00045  *
00046  * Revision 1.7  2007/05/24 07:26:44  haraldkipp
00047  * Added some delay befor reading the status of the received packet. Fixes
00048  * bug #1672527, thanks to Andreas Helmcke.
00049  *
00050  * Revision 1.6  2007/05/02 11:22:51  haraldkipp
00051  * Added multicast table entry.
00052  *
00053  * Revision 1.5  2006/06/28 17:10:15  haraldkipp
00054  * Include more general header file for ARM.
00055  *
00056  * Revision 1.4  2006/03/16 19:04:48  haraldkipp
00057  * Adding a short delay before reading the status word makes it work with
00058  * compiler optimization. On receiver overflow interrupts the chip is
00059  * declared insane. The output routine will no more enter NutEventWait()
00060  * on insane chips.
00061  *
00062  * Revision 1.3  2006/03/02 19:51:16  haraldkipp
00063  * Replaced GCC specific inline specifications with their portable
00064  * counterparts.
00065  *
00066  * Revision 1.2  2006/01/23 17:33:14  haraldkipp
00067  * Possible memory alignment problem may start network interface too early.
00068  *
00069  * Revision 1.1  2005/10/24 08:49:05  haraldkipp
00070  * Initial check in.
00071  *
00072  */
00073 
00074 #include <cfg/os.h>
00075 #include <arch/arm.h>
00076 
00077 #include <string.h>
00078 
00079 #include <sys/atom.h>
00080 #include <sys/heap.h>
00081 #include <sys/thread.h>
00082 #include <sys/event.h>
00083 #include <sys/timer.h>
00084 #include <sys/confnet.h>
00085 
00086 #include <netinet/if_ether.h>
00087 #include <net/ether.h>
00088 #include <net/if_var.h>
00089 
00090 #include <dev/irqreg.h>
00091 #include <dev/dm9000e.h>
00092 
00093 #ifdef NUTDEBUG
00094 #include <stdio.h>
00095 #endif
00096 
00097 #ifndef NUT_THREAD_NICRXSTACK
00098 #define NUT_THREAD_NICRXSTACK   768
00099 #endif
00100 
00101 /*
00102  * Determine ports, which had not been explicitely configured.
00103  */
00104 #if defined(ETHERNUT3)
00105 
00106 #ifndef NIC_BASE_ADDR
00107 #define NIC_BASE_ADDR   0x20000000
00108 #endif
00109 
00110 #ifndef NIC_SIGNAL_IRQ
00111 #define NIC_SIGNAL_IRQ  INT1
00112 #endif
00113 
00114 #ifndef NIC_SIGNAL_PDR
00115 #define NIC_SIGNAL_PDR  PIO_PDR
00116 #endif
00117 
00118 #ifndef NIC_SIGNAL_BIT
00119 #define NIC_SIGNAL_BIT  10
00120 #endif
00121 
00122 #elif defined(ELEKTOR_IR1)
00123 
00124 #ifndef NIC_BASE_ADDR
00125 #define NIC_BASE_ADDR   0x30000000
00126 #endif
00127 
00128 #ifndef NIC_SIGNAL_IRQ
00129 #define NIC_SIGNAL_IRQ  INT0
00130 #endif
00131 
00132 #ifndef NIC_SIGNAL_PDR
00133 #define NIC_SIGNAL_PDR  PIOB_PDR
00134 #endif
00135 
00136 #ifndef NIC_SIGNAL_XSR
00137 #define NIC_SIGNAL_XSR  PIOB_ASR
00138 #endif
00139 
00140 #ifndef NIC_SIGNAL_BIT
00141 #define NIC_SIGNAL_BIT  PB20_IRQ0_A
00142 #endif
00143 
00144 #endif
00145 
00146 #ifndef NIC_DATA_ADDR
00147 #define NIC_DATA_ADDR   (NIC_BASE_ADDR + 4)
00148 #endif
00149 
00150 #define INT0    0
00151 #define INT1    1
00152 #define INT2    2
00153 #define INT3    3
00154 #define INT4    4
00155 #define INT5    5
00156 #define INT6    6
00157 #define INT7    7
00158 
00159 #ifdef NIC_RESET_BIT
00160 
00161 #if (NIC_RESET_AVRPORT == AVRPORTB)
00162 #define NIC_RESET_PORT   PORTB
00163 #define NIC_RESET_DDR    DDRB
00164 
00165 #elif (NIC_RESET_AVRPORT == AVRPORTD)
00166 #define NIC_RESET_PORT   PORTD
00167 #define NIC_RESET_DDR    DDRD
00168 
00169 #elif (NIC_RESET_AVRPORT == AVRPORTE)
00170 #define NIC_RESET_PORT   PORTE
00171 #define NIC_RESET_DDR    DDRE
00172 
00173 #elif (NIC_RESET_AVRPORT == AVRPORTF)
00174 #define NIC_RESET_PORT   PORTF
00175 #define NIC_RESET_DDR    DDRF
00176 
00177 #endif                          /* NIC_RESET_AVRPORT */
00178 
00179 #endif                          /* NIC_RESET_BIT */
00180 
00181 /*
00182  * Determine interrupt settings.
00183  * DOES NOT WORK
00184  */
00185 #if (NIC_SIGNAL_IRQ == INT0)
00186 #define NIC_SIGNAL          sig_INTERRUPT0
00187 
00188 #elif (NIC_SIGNAL_IRQ == INT2)
00189 #define NIC_SIGNAL          sig_INTERRUPT2
00190 
00191 #elif (NIC_SIGNAL_IRQ == INT3)
00192 #define NIC_SIGNAL          sig_INTERRUPT3
00193 
00194 #elif (NIC_SIGNAL_IRQ == INT4)
00195 #define NIC_SIGNAL          sig_INTERRUPT4
00196 
00197 #elif (NIC_SIGNAL_IRQ == INT5)
00198 #define NIC_SIGNAL          sig_INTERRUPT5
00199 
00200 #elif (NIC_SIGNAL_IRQ == INT6)
00201 #define NIC_SIGNAL          sig_INTERRUPT6
00202 
00203 #elif (NIC_SIGNAL_IRQ == INT7)
00204 #define NIC_SIGNAL          sig_INTERRUPT7
00205 
00206 #else
00207 #define NIC_SIGNAL          sig_INTERRUPT1
00208 
00209 #endif
00210 
00215 
00216 #define NIC_NCR     0x00        /* Network control register (0x00). */
00217 #define NIC_NCR_LBM     0x06    /* Loopback mode. */
00218 #define NIC_NCR_LBNORM  0x00    /* Normal mode. */
00219 #define NIC_NCR_LBMAC   0x02    /* MAC loopback. */
00220 #define NIC_NCR_LBPHY   0x04    /* PHY loopback. */
00221 #define NIC_NCR_RST     0x01    /* Software reset, auto clear. */
00222 
00223 #define NIC_NSR     0x01        /* Network status register (0x00). */
00224 #define NIC_NSR_SPEED   0x80
00225 #define NIC_NSR_LINKST  0x40
00226 #define NIC_NSR_WAKEST  0x20
00227 #define NIC_NSR_TX2END  0x08
00228 #define NIC_NSR_TX1END  0x04
00229 #define NIC_NSR_RXOV    0x02
00230 
00231 #define NIC_TCR     0x02        /* TX control register (0x00). */
00232 #define NIC_TCR_TXREQ    0x01   /* TX request */
00233 
00234 #define NIC_TSR1    0x03        /* TX status register I (0x00). */
00235 
00236 #define NIC_TSR2    0x04        /* TX status register II (0x00). */
00237 
00238 #define NIC_RCR     0x05        /* RX control register (0x00). */
00239 #define NIC_RCR_DIS_LONG 0x20   /* Discard long packets. */
00240 #define NIC_RCR_DIS_CRC 0x10    /* Discard CRC error packets. */
00241 #define NIC_RCR_ALL     0x08    /* Pass all multicast */
00242 #define NIC_RCR_PRMSC   0x02    /* Enable promiscuous mode. */
00243 #define NIC_RCR_RXEN    0x01    /* Enable receiver. */
00244 
00245 #define NIC_RSR     0x06        /* RX status register (0x00). */
00246 #define NIC_RSR_ERRORS  0xBF    /* Error bit mask. */
00247 #define NIC_RSR_RF      0x80    /* Runt frame. */
00248 #define NIC_RSR_MF      0x40    /* Multicast frame. */
00249 #define NIC_RSR_LCS     0x20    /* Late collision. */
00250 #define NIC_RSR_RWTO    0x10    /* Receiver watchdog time out. */
00251 #define NIC_RSR_PLE     0x08    /* Physical layer error. */
00252 #define NIC_RSR_AE      0x04    /* Alignment error. */
00253 #define NIC_RSR_CE      0x02    /* CRC error. */
00254 #define NIC_RSR_FOE     0x01    /* FIFO overflow error. */
00255 
00256 #define NIC_ROCR    0x07        /* Receive overflow counter register (0x00). */
00257 
00258 #define NIC_BPTR    0x08        /* Back pressure threshold register (0x37). */
00259 
00260 #define NIC_FCTR    0x09        /* Flow control threshold register (0x38). */
00261 
00262 #define NIC_FCR     0x0A        /* RX flow control register (0x00). */
00263 
00264 #define NIC_EPCR    0x0B        /* EEPROM and PHY control register. */
00265 
00266 #define NIC_EPAR    0x0C        /* EEPROM and PHY address register. */
00267 
00268 #define NIC_EPDRL   0x0D        /* EEPROM and PHY low byte data register. */
00269 
00270 #define NIC_EPDRH   0x0E        /* EEPROM and PHY high byte data register. */
00271 
00272 #define NIC_WCR     0x0F        /* Wake up control register (0x00). */
00273 
00274 #define NIC_PAR     0x10        /* 6 byte physical address register. */
00275 
00276 #define NIC_MAR     0x16        /* 8 byte multicast address register. */
00277 
00278 #define NIC_GPCR    0x1E        /* General purpose control register (?). */
00279 
00280 #define NIC_GPR     0x1F        /* General purpose register (?). */
00281 
00282 #define NIC_TRPA    0x22        /* 2 byte TX SRAM read pointer address, low/high (0x0000). */
00283 
00284 #define NIC_RWPA    0x24        /* 2 byte RX SRAM write pointer address, low/high (0x0000). */
00285 
00286 #define NIC_VID     0x28        /* 2 byte vendor ID (0x0A46). */
00287 
00288 #define NIC_PID     0x2A        /* 2 byte product ID (0x0900). */
00289 
00290 #define NIC_CHIPR   0x2C        /* Chip revision (0x00). */
00291 
00292 #define NIC_SMCR    0x2F        /* Special mode register (0x00). */
00293 
00294 #define NIC_MRCMDX  0xF0        /* Memory data read command w/o increment (?). */
00295 
00296 #define NIC_MRCMD   0xF2        /* Memory data read command with increment (?). */
00297 
00298 #define NIC_MRR     0xF4        /* 2 byte memory data read register, low/high (?). */
00299 
00300 #define NIC_MWCMDX  0xF6        /* Memory data write command register w/o increment (?). */
00301 
00302 #define NIC_MWCMD   0xF8        /* Memory data write command register with increment (?). */
00303 
00304 #define NIC_MWR     0xFA        /* Memory data write command register with increment (?). */
00305 
00306 #define NIC_TXPL    0xFC        /* 2 byte TX packet length register. (?). */
00307 
00308 #define NIC_ISR     0xFE        /* Interrupt status register (0x00). */
00309 #define NIC_ISR_IOM     0xC0    /* I/O mode mask */
00310 #define NIC_ISR_M16     0x00    /* 16-bit I/O mode */
00311 #define NIC_ISR_M32     0x40    /* 32-bit I/O mode */
00312 #define NIC_ISR_M8      0x80    /* 8-bit I/O mode */
00313 #define NIC_ISR_ROOS    0x08    /* Receiver overflow counter interrupt. */
00314 #define NIC_ISR_ROS     0x04    /* Receiver overflow interrupt. */
00315 #define NIC_ISR_PTS     0x02    /* Transmitter interrupt. */
00316 #define NIC_ISR_PRS     0x01    /* Receiver interrupt. */
00317 
00318 #define NIC_IMR     0xFF        /* Interrupt mask register (0x00). */
00319 #define NIC_IMR_PAR     0x80    /* Enable read/write pointer wrap around. */
00320 #define NIC_IMR_ROOM    0x08    /* Enable receiver overflow counter interrupts. */
00321 #define NIC_IMR_ROM     0x04    /* Enable receiver overflow interrupts. */
00322 #define NIC_IMR_PTM     0x02    /* Enable transmitter interrupts. */
00323 #define NIC_IMR_PRM     0x01    /* Enable receiver interrupts. */
00324 
00325 #define NIC_PHY_BMCR    0x00    /* Basic mode control register. */
00326 
00327 #define NIC_PHY_BMSR    0x01    /* Basic mode status register. */
00328 #define NIC_PHY_BMSR_ANCOMPL    0x0020  /* Auto negotiation complete. */
00329 #define NIC_PHY_BMSR_LINKSTAT   0x0004  /* Link status. */
00330 
00331 #define NIC_PHY_ID1     0x02    /* PHY identifier register 1. */
00332 
00333 #define NIC_PHY_ID2     0x03    /* PHY identifier register 2. */
00334 
00335 #define NIC_PHY_ANAR    0x04    /* Auto negotiation advertisement register. */
00336 
00337 #define NIC_PHY_ANLPAR  0x05    /* Auto negotiation link partner availability register. */
00338 
00339 #define NIC_PHY_ANER    0x06    /* Auto negotiation expansion register. */
00340 
00341 #define NIC_PHY_DSCR    0x10    /* Davicom specified configuration register. */
00342 
00343 #define NIC_PHY_DSCSR   0x11    /* Davicom specified configuration and status register. */
00344 
00345 #define NIC_PHY_10BTCSR 0x12    /* 10BASE-T configuration and status register. */
00346 
00350 struct _NICINFO {
00351 #ifdef NUT_PERFMON
00352     uint32_t ni_rx_packets;       
00353     uint32_t ni_tx_packets;       
00354     uint32_t ni_overruns;         
00355     uint32_t ni_rx_frame_errors;  
00356     uint32_t ni_rx_crc_errors;    
00357     uint32_t ni_rx_missed_errors; 
00358 #endif
00359     HANDLE volatile ni_rx_rdy;  
00360     HANDLE volatile ni_tx_rdy;  
00361     HANDLE ni_mutex;            
00362     volatile int ni_tx_queued;  
00363     volatile int ni_tx_quelen;  
00364     volatile int ni_insane;     
00365     int ni_iomode;              
00366 };
00367 
00371 typedef struct _NICINFO NICINFO;
00372 
00379 
00380 
00381 static INLINE void nic_outb(uint8_t reg, uint8_t val)
00382 {
00383     outb(NIC_BASE_ADDR, reg);
00384     outb(NIC_DATA_ADDR, val);
00385 }
00386 
00387 static INLINE uint8_t nic_inb(uint16_t reg)
00388 {
00389     outb(NIC_BASE_ADDR, reg);
00390     return inb(NIC_DATA_ADDR);
00391 }
00392 
00400 static uint16_t phy_inw(uint8_t reg)
00401 {
00402     /* Select PHY register */
00403     nic_outb(NIC_EPAR, 0x40 | reg);
00404 
00405     /* PHY read command. */
00406     nic_outb(NIC_EPCR, 0x0C);
00407     NutDelay(1);
00408     nic_outb(NIC_EPCR, 0x00);
00409 
00410     /* Get data from PHY data register. */
00411     return ((uint16_t) nic_inb(NIC_EPDRH) << 8) | (uint16_t) nic_inb(NIC_EPDRL);
00412 }
00413 
00422 static void phy_outw(uint8_t reg, uint16_t val)
00423 {
00424     /* Select PHY register */
00425     nic_outb(NIC_EPAR, 0x40 | reg);
00426 
00427     /* Store value in PHY data register. */
00428     nic_outb(NIC_EPDRL, (uint8_t) val);
00429     nic_outb(NIC_EPDRH, (uint8_t) (val >> 8));
00430 
00431     /* PHY write command. */
00432     nic_outb(NIC_EPCR, 0x0A);
00433     NutDelay(1);
00434     nic_outb(NIC_EPCR, 0x00);
00435 }
00436 
00437 static int NicPhyInit(void)
00438 {
00439     /* Restart auto negotiation. */
00440     phy_outw(NIC_PHY_ANAR, 0x01E1);
00441     phy_outw(NIC_PHY_BMCR, 0x1200);
00442 
00443     nic_outb(NIC_GPCR, 1);
00444     nic_outb(NIC_GPR, 0);
00445 
00446     return 0;
00447 }
00448 
00454 static int NicReset(void)
00455 {
00456     /* Hardware reset. */
00457 #ifdef undef_NIC_RESET_BIT
00458     sbi(NIC_RESET_DDR, NIC_RESET_BIT);
00459     sbi(NIC_RESET_PORT, NIC_RESET_BIT);
00460     NutDelay(WAIT100);
00461     cbi(NIC_RESET_PORT, NIC_RESET_BIT);
00462     NutDelay(WAIT250);
00463     NutDelay(WAIT250);
00464 #else
00465     /* Software reset. */
00466     nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00467     NutDelay(1);
00468     /* FIXME: Delay required. */
00469 #endif
00470 
00471     return NicPhyInit();
00472 }
00473 
00474 /*
00475  * NIC interrupt entry.
00476  */
00477 static void NicInterrupt(void *arg)
00478 {
00479     uint8_t isr;
00480     NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
00481 
00482     /* Read interrupt status and disable interrupts. */
00483     isr = nic_inb(NIC_ISR);
00484 
00485     /* Receiver interrupt. */
00486     if (isr & NIC_ISR_PRS) {
00487         nic_outb(NIC_ISR, NIC_ISR_PRS);
00488         NutEventPostFromIrq(&ni->ni_rx_rdy);
00489     }
00490 
00491     /* Transmitter interrupt. */
00492     if (isr & NIC_ISR_PTS) {
00493         if (ni->ni_tx_queued) {
00494             if (ni->ni_tx_quelen) {
00495                 /* Initiate transfer of a queued packet. */
00496                 nic_outb(NIC_TXPL, (uint8_t) ni->ni_tx_quelen);
00497                 nic_outb(NIC_TXPL + 1, (uint8_t) (ni->ni_tx_quelen >> 8));
00498                 ni->ni_tx_quelen = 0;
00499                 nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00500             }
00501             ni->ni_tx_queued--;
00502         }
00503         nic_outb(NIC_ISR, NIC_ISR_PTS);
00504         NutEventPostFromIrq(&ni->ni_tx_rdy);
00505     }
00506 
00507     /* Receiver overflow interrupt. */
00508     if (isr & NIC_ISR_ROS) {
00509         nic_outb(NIC_ISR, NIC_ISR_ROS);
00510         ni->ni_insane = 1;
00511         NutEventPostFromIrq(&ni->ni_rx_rdy);
00512     }
00513 
00514     /* Receiver overflow counter interrupt. */
00515     if (isr & NIC_ISR_ROOS) {
00516         nic_outb(NIC_ISR, NIC_ISR_ROOS);
00517         NutEventPostFromIrq(&ni->ni_rx_rdy);
00518     }
00519 }
00520 
00526 static void NicWrite8(uint8_t * buf, uint16_t len)
00527 {
00528     while (len--) {
00529         outb(NIC_DATA_ADDR, *buf);
00530         buf++;
00531     }
00532 }
00533 
00539 static void NicWrite16(uint8_t * buf, uint16_t len)
00540 {
00541     uint16_t *wp = (uint16_t *) buf;
00542 
00543     len = (len + 1) / 2;
00544     while (len--) {
00545         outw(NIC_DATA_ADDR, *wp);
00546         wp++;
00547     }
00548 }
00549 
00555 static void NicRead8(uint8_t * buf, uint16_t len)
00556 {
00557     while (len--) {
00558         *buf++ = inb(NIC_DATA_ADDR);
00559     }
00560 }
00561 
00567 static void NicRead16(uint8_t * buf, uint16_t len)
00568 {
00569     uint16_t *wp = (uint16_t *) buf;
00570 
00571     len = (len + 1) / 2;
00572     while (len--) {
00573         *wp++ = inw(NIC_DATA_ADDR);
00574     }
00575 }
00576 
00585 static int NicGetPacket(NICINFO * ni, NETBUF ** nbp)
00586 {
00587     int rc = -1;
00588     uint16_t fsw;
00589     uint16_t fbc;
00590 
00591     *nbp = NULL;
00592 
00593     /* Disable NIC interrupts. */
00594     NutIrqDisable(&NIC_SIGNAL);
00595 
00596     /* 
00597      * Read the status word w/o auto increment. If zero, no packet is 
00598      * available. Otherwise it should be set to one. Any other value 
00599      * indicates a weird chip crying for reset.
00600      */
00601     nic_inb(NIC_MRCMDX);
00602     /* Add some delay befor reading the status of the received packet. */
00603     _NOP(); _NOP(); _NOP(); _NOP();
00604     fsw = inb(NIC_DATA_ADDR);
00605     if (fsw > 1) {
00606         ni->ni_insane = 1;
00607     } else if (fsw) {
00608         /* Now read status word and byte count with auto increment. */
00609         outb(NIC_BASE_ADDR, NIC_MRCMD);
00610         if (ni->ni_iomode == NIC_ISR_M16) {
00611             fsw = inw(NIC_DATA_ADDR);
00612             _NOP(); _NOP(); _NOP(); _NOP();
00613             fbc = inw(NIC_DATA_ADDR);
00614         } else {
00615             fsw = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00616             _NOP(); _NOP(); _NOP(); _NOP();
00617             fbc = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
00618         }
00619 
00620         /*
00621          * Receiving long packets is unexpected, because we disabled 
00622          * this during initialization. Let's declare the chip insane.
00623          * Short packets will be handled by the caller.
00624          */
00625         if (fbc > 1536) {
00626             ni->ni_insane = 1;
00627         } else {
00628             /*
00629              * The high byte of the status word contains a copy of the 
00630              * receiver status register.
00631              */
00632             fsw >>= 8;
00633             fsw &= NIC_RSR_ERRORS;
00634 #ifdef NUT_PERMON
00635             /* Update statistics. */
00636             if (fsw) {
00637                 if (RxStatus & NIC_RSR_CE) {
00638                     ni->ni_crc_errors++;
00639                 } else if (RxStatus & NIC_RSR_FOE) {
00640                     ni->ni_overruns++;
00641                 } else {
00642                     ni->ni_rx_missed_errors++;
00643                 }
00644             } else {
00645                 ni->ni_rx_packets++;
00646             }
00647 #endif
00648             /* 
00649              * If we got an error packet or failed to allocated the
00650              * buffer, then silently discard the packet.
00651              */
00652             if (fsw || (*nbp = NutNetBufAlloc(0, NBAF_DATALINK, fbc - 4)) == NULL) {
00653                 if (ni->ni_iomode == NIC_ISR_M16) {
00654                     fbc = (fbc + 1) / 2;
00655                     while (fbc--) {
00656                         fsw = inw(NIC_DATA_ADDR);
00657                     }
00658                 } else {
00659                     while (fbc--) {
00660                         fsw = inb(NIC_DATA_ADDR);
00661                     }
00662                 }
00663             } else {
00664                 if (ni->ni_iomode == NIC_ISR_M16) {
00665                     /* Read packet data from 16 bit bus. */
00666                     NicRead16((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00667                     /* Read packet CRC. */
00668                     fsw = inw(NIC_DATA_ADDR);
00669                     fsw = inw(NIC_DATA_ADDR);
00670                 } else {
00671                     /* Read packet data from 8 bit bus. */
00672                     NicRead8((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
00673                     /* Read packet CRC. */
00674                     fsw = inb(NIC_DATA_ADDR);
00675                     fsw = inb(NIC_DATA_ADDR);
00676                     fsw = inb(NIC_DATA_ADDR);
00677                     fsw = inb(NIC_DATA_ADDR);
00678                 }
00679                 /* Return success. */
00680                 rc = 0;
00681             }
00682         }
00683     }
00684 
00685     /* Enable NIC interrupts if the chip is sane. */
00686     if (ni->ni_insane == 0) {
00687         NutIrqEnable(&NIC_SIGNAL);
00688     }
00689     return rc;
00690 }
00691 
00704 static int NicPutPacket(NICINFO * ni, NETBUF * nb)
00705 {
00706     int rc = -1;
00707     uint16_t sz;
00708 
00709     /*
00710      * Calculate the number of bytes to be send. Do not send packets 
00711      * larger than the Ethernet maximum transfer unit. The MTU
00712      * consist of 1500 data bytes plus the 14 byte Ethernet header
00713      * plus 4 bytes CRC. We check the data bytes only.
00714      */
00715     if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
00716         return -1;
00717     }
00718     sz += nb->nb_dl.sz;
00719     if (sz & 1) {
00720         sz++;
00721     }
00722 
00723     /* Disable interrupts. */
00724     NutIrqDisable(&NIC_SIGNAL);
00725 
00726     /* TODO: Check for link. */
00727     if (ni->ni_insane == 0) {
00728         /* Enable data write. */
00729         outb(NIC_BASE_ADDR, NIC_MWCMD);
00730 
00731         /* Transfer the Ethernet frame. */
00732         if (ni->ni_iomode == NIC_ISR_M16) {
00733             NicWrite16(nb->nb_dl.vp, nb->nb_dl.sz);
00734             NicWrite16(nb->nb_nw.vp, nb->nb_nw.sz);
00735             NicWrite16(nb->nb_tp.vp, nb->nb_tp.sz);
00736             NicWrite16(nb->nb_ap.vp, nb->nb_ap.sz);
00737         } else {
00738             NicWrite8(nb->nb_dl.vp, nb->nb_dl.sz);
00739             NicWrite8(nb->nb_nw.vp, nb->nb_nw.sz);
00740             NicWrite8(nb->nb_tp.vp, nb->nb_tp.sz);
00741             NicWrite8(nb->nb_ap.vp, nb->nb_ap.sz);
00742         }
00743 
00744         /* If no packet is queued, start the transmission. */
00745         if (ni->ni_tx_queued == 0) {
00746             nic_outb(NIC_TXPL, (uint8_t) sz);
00747             nic_outb(NIC_TXPL + 1, (uint8_t) (sz >> 8));
00748             nic_outb(NIC_TCR, NIC_TCR_TXREQ);
00749         }
00750         /* ...otherwise mark this packet queued. */
00751         else {
00752             ni->ni_tx_quelen = sz;
00753         }
00754         ni->ni_tx_queued++;
00755         rc = 0;
00756 #ifdef NUT_PERFMON
00757         ni->ni_tx_packets++;
00758 #endif
00759     }
00760 
00761     /* Enable interrupts. */
00762     NutIrqEnable(&NIC_SIGNAL);
00763 
00764     /* If the controller buffer is filled with two packets, then
00765        wait for the first being sent out. */
00766     if (rc == 0 && ni->ni_tx_queued > 1) {
00767         NutEventWait(&ni->ni_tx_rdy, 500);
00768     }
00769     return rc;
00770 }
00771 
00779 static int NicStart(CONST uint8_t * mac)
00780 {
00781     int i;
00782     int link_wait = 20;
00783 
00784     /* Power up the PHY. */
00785     nic_outb(NIC_GPR, 0);
00786     NutDelay(5);
00787 
00788     /* Software reset with MAC loopback. */
00789     nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00790     NutDelay(5);
00791     nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
00792     NutDelay(5);
00793 
00794     /* 
00795      * PHY power down followed by PHY power up. This should activate 
00796      * the auto sense link.
00797      */
00798     nic_outb(NIC_GPR, 1);
00799     nic_outb(NIC_GPR, 0);
00800 
00801     /* Set MAC address. */
00802     for (i = 0; i < 6; i++) {
00803         nic_outb(NIC_PAR + i, mac[i]);
00804     }
00805 
00806     /* Enable broadcast receive. */
00807     for (i = 0; i < 7; i++) {
00808         nic_outb(NIC_MAR + i, 0);
00809     }
00810     nic_outb(NIC_MAR + 7, 0x80);
00811 
00812     /* Clear interrupts. */
00813     nic_outb(NIC_ISR, NIC_ISR_ROOS | NIC_ISR_ROS | NIC_ISR_PTS | NIC_ISR_PRS);
00814 
00815     /* Enable receiver. */
00816     nic_outb(NIC_RCR, NIC_RCR_DIS_LONG | NIC_RCR_DIS_CRC | NIC_RCR_RXEN | NIC_RCR_ALL);
00817 
00818     /* Wait for link. */
00819     for (link_wait = 20;; link_wait--) {
00820         if (phy_inw(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL) {
00821             break;
00822         }
00823         if (link_wait == 0) {
00824             return -1;
00825         }
00826         NutSleep(200);
00827     }
00828 
00829     /* Enable interrupts. */
00830     nic_outb(NIC_IMR, NIC_IMR_PAR | NIC_IMR_PTM | NIC_IMR_PRM);
00831 
00832     return 0;
00833 }
00834 
00839 THREAD(NicRxLanc, arg)
00840 {
00841     NUTDEVICE *dev;
00842     IFNET *ifn;
00843     NICINFO *ni;
00844     NETBUF *nb;
00845 
00846     dev = arg;
00847     ifn = (IFNET *) dev->dev_icb;
00848     ni = (NICINFO *) dev->dev_dcb;
00849 
00850     /*
00851      * This is a temporary hack. Due to a change in initialization,
00852      * we may not have got a MAC address yet. Wait until one has been
00853      * set.
00854      */
00855     for (;;) {
00856         int i;
00857 
00858         for (i = 0; i < sizeof(ifn->if_mac); i++) {
00859             if (ifn->if_mac[i] && ifn->if_mac[i] != 0xFF) {
00860                 break;
00861             }
00862         }
00863         if (i < sizeof(ifn->if_mac)) {
00864             break;
00865         }
00866         NutSleep(63);
00867     }
00868 
00869     /*
00870      * Do not continue unless we managed to start the NIC. We are
00871      * trapped here if the Ethernet link cannot be established.
00872      * This happens, for example, if no Ethernet cable is plugged
00873      * in.
00874      */
00875     while (NicStart(ifn->if_mac)) {
00876         NutSleep(1000);
00877     }
00878 
00879     /* Initialize the access mutex. */
00880     NutEventPost(&ni->ni_mutex);
00881 
00882     /* Run at high priority. */
00883     NutThreadSetPriority(9);
00884 
00885     /* Enable interrupts. */
00886 #ifdef NIC_SIGNAL_XSR
00887     outr(NIC_SIGNAL_XSR, _BV(NIC_SIGNAL_BIT));
00888 #if defined(ELEKTOR_IR1)
00889     /* Ugly code alarm: Should be configurable. */
00890     outr(PMC_PCER, _BV(IRQ0_ID));
00891 #endif
00892 #endif
00893     outr(NIC_SIGNAL_PDR, _BV(NIC_SIGNAL_BIT));
00894     NutIrqEnable(&NIC_SIGNAL);
00895 #if defined(ELEKTOR_IR1)
00896     /* Ugly code alarm: Should be configurable. */
00897     NutIrqSetMode(&NIC_SIGNAL, NUT_IRQMODE_HIGHLEVEL);
00898 #endif
00899 
00900     for (;;) {
00901         /*
00902          * Wait for the arrival of new packets or poll the receiver 
00903          * every two seconds.
00904          */
00905         NutEventWait(&ni->ni_rx_rdy, 2000);
00906 
00907         /*
00908          * Fetch all packets from the NIC's internal buffer and pass 
00909          * them to the registered handler.
00910          */
00911         while (NicGetPacket(ni, &nb) == 0) {
00912 
00913             /* Discard short packets. */
00914             if (nb->nb_dl.sz < 60) {
00915                 NutNetBufFree(nb);
00916             } else {
00917                 (*ifn->if_recv) (dev, nb);
00918             }
00919         }
00920 
00921         /* We got a weird chip, try to restart it. */
00922         while (ni->ni_insane) {
00923             if (NicStart(ifn->if_mac) == 0) {
00924                 ni->ni_insane = 0;
00925                 ni->ni_tx_queued = 0;
00926                 ni->ni_tx_quelen = 0;
00927                 NutIrqEnable(&NIC_SIGNAL);
00928             } else {
00929                 NutSleep(1000);
00930             }
00931         }
00932     }
00933 }
00934 
00945 int DmOutput(NUTDEVICE * dev, NETBUF * nb)
00946 {
00947     static uint32_t mx_wait = 5000;
00948     int rc = -1;
00949     NICINFO *ni = (NICINFO *) dev->dev_dcb;
00950 
00951     /*
00952      * After initialization we are waiting for a long time to give
00953      * the PHY a chance to establish an Ethernet link.
00954      */
00955     while (rc) {
00956         if (ni->ni_insane) {
00957             break;
00958         }
00959         if (NutEventWait(&ni->ni_mutex, mx_wait)) {
00960             break;
00961         }
00962 
00963         /* Check for packet queue space. */
00964         if (ni->ni_tx_queued > 1) {
00965             if (NutEventWait(&ni->ni_tx_rdy, 500)) {
00966                 /* No queue space. Release the lock and give up. */
00967                 NutEventPost(&ni->ni_mutex);
00968                 break;
00969             }
00970         } else if (NicPutPacket(ni, nb) == 0) {
00971             /* Ethernet works. Set a long waiting time in case we
00972                temporarly lose the link next time. */
00973             rc = 0;
00974             mx_wait = 5000;
00975         }
00976         NutEventPost(&ni->ni_mutex);
00977     }
00978     /*
00979      * Probably no Ethernet link. Significantly reduce the waiting
00980      * time, so following transmission will soon return an error.
00981      */
00982     if (rc) {
00983         mx_wait = 500;
00984     }
00985     return rc;
00986 }
00987 
01005 int DmInit(NUTDEVICE * dev)
01006 {
01007     uint32_t id;
01008     NICINFO *ni = (NICINFO *) dev->dev_dcb;
01009 
01010 #if defined(ELEKTOR_IR1)
01011     outr(PIOA_BSR, _BV(PA20_NCS2_B));
01012     outr(PIOA_PDR, _BV(PA20_NCS2_B));
01013     outr(PIOC_BSR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
01014     outr(PIOC_PDR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
01015 
01016     outr(SMC_CSR(2)
01017         , (1 << SMC_NWS_LSB)
01018         | SMC_WSEN
01019         | (2 << SMC_TDF_LSB)
01020         | SMC_BAT
01021         | SMC_DBW_16
01022         | (1 << SMC_RWSETUP_LSB)
01023         | (1 << SMC_RWHOLD_LSB)
01024         );
01025 #endif
01026 
01027     /* Probe chip by verifying the identifier registers. */
01028     id = (uint32_t) nic_inb(NIC_VID);
01029     id |= (uint32_t) nic_inb(NIC_VID + 1) << 8;
01030     id |= (uint32_t) nic_inb(NIC_PID) << 16;
01031     id |= (uint32_t) nic_inb(NIC_PID + 1) << 24;
01032     if (id != 0x90000A46) {
01033         return -1;
01034     }
01035 
01036     /* Reset chip. */
01037     if (NicReset()) {
01038         return -1;
01039     }
01040 
01041     /* Clear NICINFO structure. */
01042     memset(ni, 0, sizeof(NICINFO));
01043 
01044     /* Determine bus mode. We do not support 32 bit access. */
01045     ni->ni_iomode = nic_inb(NIC_ISR) & NIC_ISR_IOM;
01046     if (ni->ni_iomode == NIC_ISR_M32) {
01047         return -1;
01048     }
01049 
01050     /* Register interrupt handler. */
01051     if (NutRegisterIrqHandler(&NIC_SIGNAL, NicInterrupt, dev)) {
01052         return -1;
01053     }
01054 
01055     /* Start the receiver thread. */
01056     if (NutThreadCreate("rxi1", NicRxLanc, dev, NUT_THREAD_NICRXSTACK) == NULL) {
01057         return -1;
01058     }
01059     return 0;
01060 }
01061 
01062 static NICINFO dcb_eth0;
01063 
01069 static IFNET ifn_eth0 = {
01070     IFT_ETHER,                  
01071     {0, 0, 0, 0, 0, 0},         
01072     0,                          
01073     0,                          
01074     0,                          
01075     ETHERMTU,                   
01076     0,                          
01077     0,                          
01078     0,                          
01079     NutEtherInput,              
01080     DmOutput,                   
01081     NutEtherOutput              
01082 };
01083 
01093 NUTDEVICE devDM9000E = {
01094     0,                          
01095     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
01096     IFTYP_NET,                  
01097     0,                          
01098     0,                          
01099     &ifn_eth0,                  
01100     &dcb_eth0,                  
01101     DmInit,                     
01102     0,                          
01103     0,                          
01104     0,                          
01105 #ifdef __HARVARD_ARCH__
01106     0,                          
01107 #endif
01108     0,                          
01109     0,                          
01110     0                           
01111 };
01112 

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