dm9000.c

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

© 2000-2010 by contributors - visit http://www.ethernut.de/