00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 #include <cfg/os.h>
00109 #include <cfg/arch/avr.h>
00110 
00111 #include <string.h>
00112 
00113 #include <sys/atom.h>
00114 #include <sys/heap.h>
00115 #include <sys/thread.h>
00116 #include <sys/event.h>
00117 #include <sys/timer.h>
00118 #include <sys/confnet.h>
00119 
00120 #include <netinet/if_ether.h>
00121 #include <net/ether.h>
00122 #include <net/if_var.h>
00123 
00124 #include <dev/irqreg.h>
00125 #include <dev/cs8900a.h>
00126 
00127 #ifdef NUTDEBUG
00128 #include <stdio.h>
00129 #endif
00130 
00131 
00132 
00133 
00134 #include <arch/arm/lpc2xxx.h>
00135 #include <__armlib.h>
00136 #define cli()   __ARMLIB_disableIRQ()
00137 #define sei()   __ARMLIB_enableIRQ()   
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 #define CS_DATA_P0    (cs_base + 0x0000UL)
00147 #define CS_DATA_P1              (cs_base + 0x0002UL)
00148 #define CS_TX_CMD_I             (cs_base + 0x0004UL)
00149 #define CS_TX_LEN_I             (cs_base + 0x0006UL)
00150 #define CS_INT_STAT   (cs_base + 0x0008UL)
00151 #define CS_PP_PTR                 (cs_base + 0x000AUL)
00152 #define CS_PP_DATA0             (cs_base + 0x000CUL)
00153 #define CS_PP_DATA1             (cs_base + 0x000EUL)
00154 
00155 
00156 
00157 #define CS_PROD_ID              0x0000
00158 #define CS_IO_BASE              0x0020
00159 #define CS_INT_NUM              0x0022
00160 #define CS_DMA_CHAN             0x0024
00161 #define CS_DMA_SOF              0x0026
00162 #define CS_DMA_FCNT             0x0028
00163 #define CS_DMA_RXCNT    0x002A
00164 #define CS_MEM_BASE             0x002C
00165 #define CS_BOOT_BASE    0x0030
00166 #define CS_BOOT_MASK    0x0034
00167 #define CS_EE_CMD                 0x0040
00168 #define CS_EE_DATA              0x0042
00169 #define CS_RX_FRM_CNT   0x0050
00170 
00171 #define CS_ISQ                    0x0120
00172 #define CS_RX_CFG                 0x0102
00173 #define CS_RX_EVENT             0x0124
00174 #define CS_RX_CTL                 0x0104
00175 #define CS_TX_CFG                 0x0106
00176 #define CS_TX_EVENT             0x0128
00177 #define CS_TX_CMD_P             0x0108
00178 #define CS_BUF_CFG              0x010A
00179 #define CS_BUF_EVENT    0x012C
00180 #define CS_RX_MISS              0x0130
00181 #define CS_TX_COLL              0x0132
00182 #define CS_LINE_CTRL    0x0112
00183 #define CS_LINE_STAT    0x0134
00184 #define CS_SELF_CTRL    0x0114
00185 #define CS_SELF_STAT    0x0136
00186 #define CS_BUS_CTRL             0x0116
00187 #define CS_BUS_STAT             0x0138
00188 #define CS_TEST_CTRL    0x0118
00189 #define CS_AUI_TDR              0x013C
00190 
00191 #define CS_PP_TX_CMD    0x0144
00192 #define CS_PP_TX_LEN    0x0146
00193 
00194 #define CS_IEEE_ADDR    0x0158
00195 
00200 
00205 struct _NICINFO {
00206     uint32_t ni_rx_packets;       
00207     uint32_t ni_tx_packets;       
00208 };
00209 
00213 typedef struct _NICINFO NICINFO;
00214 
00215 
00216 
00217 
00218 
00219 
00220 static   uint8_t cs_flags = 0;
00221 volatile uint32_t cs_base  = 0x82000000UL;
00222 
00223 
00224 
00225 
00226 
00227 void CSWrite16(uint32_t addr, uint16_t data)
00228 {
00229     uint8_t *p;
00230 
00231     p = (uint8_t *) addr;
00232     cli();
00233     *p = data;
00234     p++;
00235     *p = data >> 8;    
00236     sei();
00237 }
00238 
00239 void CSWritePP16(uint16_t addr, uint16_t data)
00240 {
00241     uint8_t *p;
00242 
00243     cli();
00244     p = (uint8_t *) CS_PP_PTR;
00245     *p = addr;
00246     p++;
00247     *p = addr >> 8;
00248 
00249     CSWrite16(CS_PP_DATA0, data);
00250 
00251     return;
00252 }
00253 
00254 uint16_t CSRead16(uint32_t addr)
00255 {
00256     uint8_t *p;
00257     uint16_t d;
00258 
00259     cli();
00260     p  = (uint8_t *) addr;
00261     d  = *p;
00262     p++;
00263     d |= (*p << 8); 
00264     sei();
00265 
00266     return d;
00267 }
00268 
00269 uint16_t CSReadPP16(uint16_t addr)
00270 {
00271     uint8_t *p;
00272 
00273     cli();
00274     p = (uint8_t *) CS_PP_PTR;
00275     *p = addr;
00276     p++;
00277     *p = addr >> 8;
00278 
00279     return CSRead16(CS_PP_DATA0);
00280 }
00281 
00282 void CSBeginFrame(void)
00283 {
00284     cs_flags &= ~1;
00285 }
00286 
00287 void CSEndFrame(void)
00288 {
00289     uint8_t *p;
00290 
00291     cli();
00292     p = (uint8_t *) CS_DATA_P0 + 1;
00293     sei();
00294 
00295     
00296     if (cs_flags & 1)
00297         p = 0;
00298 }
00299 
00300 void CSWriteFrameByte(uint8_t data)
00301 {
00302     uint8_t *p;
00303 
00304     if (cs_flags & 1)
00305         p = (uint8_t *) CS_DATA_P0 + 1;
00306     else
00307         p = (uint8_t *) CS_DATA_P0;
00308 
00309     *p = data;
00310     cs_flags ^= 1;
00311 }
00312 
00313 static int CSEthPutPacket(NUTDEVICE * dev, NETBUF * nb)
00314 {
00315     uint16_t i;
00316     uint16_t sz;
00317     uint8_t *p;
00318     NICINFO *ni;
00319 
00320     ni = (NICINFO *) dev->dev_dcb;
00321 
00322     
00323     
00324     
00325     
00326     sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
00327     if (sz >= 0x600) {
00328         NutNetBufFree(nb);
00329         return -1;
00330     }
00331 #if 0
00332     if (tcp_trace) {
00333         NutPrintFormat_P(dev_debug, PSTR("[ETHTX-%u]\r\n"), sz);
00334         NutPrintFlush(dev_debug);
00335     }
00336 #endif
00337 
00338     
00339     CSWrite16(CS_TX_CMD_I, 0xC0);
00340     
00341     CSWrite16(CS_TX_LEN_I, sz);
00342 
00343     
00344     
00345     
00346     
00347     
00348     
00349     i = 0;
00350     while ((CSReadPP16(CS_BUS_STAT) & 0x0100) == 0) {
00351         i++;
00352         if (i > 20)
00353             return 0;
00354         NutSleep(10);
00355     }
00356 
00357     
00358     
00359     
00360     CSBeginFrame();
00361 
00362     p = nb->nb_dl.vp;
00363     for (i = 0; i < nb->nb_dl.sz; i++) {
00364         CSWriteFrameByte(*p++);
00365     }
00366 
00367 
00368     p = nb->nb_nw.vp;
00369     for (i = 0; i < nb->nb_nw.sz; i++) {
00370         CSWriteFrameByte(*p++);
00371     }
00372 
00373     p = nb->nb_tp.vp;
00374     for (i = 0; i < nb->nb_tp.sz; i++) {
00375         CSWriteFrameByte(*p++);
00376     }
00377 
00378     p = nb->nb_ap.vp;
00379     for (i = 0; i < nb->nb_ap.sz; i++) {
00380         CSWriteFrameByte(*p++);
00381     }
00382 
00383     CSEndFrame();
00384 
00385     return 0;
00386 }
00387 
00388 void CSSoftwareWakeup(void)
00389 {
00390     volatile uint8_t *p;
00391     uint16_t          data = CS_SELF_CTRL;
00392 
00393     p = (uint8_t *) CS_PP_PTR;
00394     *p = data;
00395     p++;
00396     *p = data >> 8;
00397 
00398     NutDelay(10);
00399 }
00400 
00401 
00402 void CSSoftwareReset(void)
00403 {
00404     volatile uint8_t *p;
00405     uint16_t          data;
00406 
00407     data = CS_SELF_CTRL;
00408     p  = (uint8_t *) CS_PP_PTR;    
00409     *p = data;
00410     p++;
00411     *p = data >> 8;
00412         
00413     data = 0x0040;
00414     p  = (uint8_t *) CS_DATA_P0;
00415     *p = data;
00416     p++;
00417     *p = data >> 8;
00418 }
00419 
00420 
00421 THREAD(CSNICrx, arg)
00422 {
00423     NUTDEVICE *dev;
00424     IFNET *ifn;
00425     NICINFO *ni;
00426     NETBUF *nb;
00427     uint8_t *p;
00428     uint8_t *q;
00429     uint16_t i, m;
00430     volatile uint16_t l;
00431 
00432     dev = arg;
00433     ifn = (IFNET *) dev->dev_icb;
00434     ni = (NICINFO *) dev->dev_dcb;
00435 
00436 #if 0
00437     if (tcp_trace) {
00438         NutPrintFormat_P(dev_debug, PSTR("Enter ETHReceive\r\n"));
00439         NutPrintFlush(dev_debug);
00440     }
00441 #endif
00442 
00443     l = 0;
00444 
00445     NutThreadSetPriority(8);
00446     for (;;) {
00447         while ((CSReadPP16(CS_RX_EVENT) & 0x0100) == 0) {
00448             NutSleep(10);
00449         }
00450 
00451         l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0);
00452         l = *(uint8_t *) (CS_DATA_P0 + 1) << 8 | *(uint8_t *) (CS_DATA_P0);
00453         
00454         
00455         
00456 
00457         
00458         if (l & 1)
00459             m = l - 1;
00460         else
00461             m = l;
00462 
00463 
00464         nb = NutNetBufAlloc(0, NBAF_DATALINK, l);
00465         if (nb) {
00466             q = nb->nb_dl.vp;
00467             for (i = 0; i < m; i += 2) {
00468                 p = (uint8_t *) CS_DATA_P0;
00469                 *q++ = *p;
00470                 p = (uint8_t *) CS_DATA_P0 + 1;
00471                 *q++ = *p;
00472             }
00473 
00474             
00475             if (m != l) {
00476                 p = (uint8_t *) CS_DATA_P0;
00477                 *q++ = *p;
00478 
00479                 p = (uint8_t *) CS_DATA_P0 + 1;
00480                 m = *p;
00481             }
00482             ni->ni_rx_packets++;
00483             (*ifn->if_recv) (dev, nb);
00484         }
00485     }
00486 }
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00504 int cs8900Output(NUTDEVICE * dev, NETBUF * nb)
00505 {
00506     int rc = -1;
00507     NICINFO *ni;
00508 
00509     ni = (NICINFO *) dev->dev_dcb;
00510 
00511 #if 0
00512     if (tcp_trace) {
00513         NutPrintFormat_P(dev_debug, PSTR("Enter EthOutput\r\n"));
00514         NutPrintFlush(dev_debug);
00515     }
00516 #endif
00517 
00518     if ((rc = CSEthPutPacket(dev, nb)) == 0)
00519         ni->ni_tx_packets++;
00520 
00521     return rc;
00522 }
00523 
00541 int cs8900Init(NUTDEVICE * dev)
00542 {
00543     uint16_t  i;
00544     uint16_t  j;
00545     IFNET   *ifn;
00546     NICINFO *ni;
00547     
00548 #if 0
00549     if (tcp_trace) {
00550         NutPrintFormat_P(dev_debug, PSTR("Enter NicInit  \r\n"));
00551         NutPrintFlush(dev_debug);
00552     }
00553 #endif
00554 
00555     cs_base = dev->dev_base;
00556     
00557 #if defined(OLIMEX_LPCE2294)
00558     if (cs_base == 0)
00559     {
00560       cs_base = 0x82000000UL;
00561     }
00562 #endif    
00563 
00564 
00565     if (confnet.cd_size == 0)
00566         NutNetLoadConfig(dev->dev_name);
00567 
00568     ifn = dev->dev_icb;
00569 #if 0 
00570     memcpy(ifn->if_mac, confnet.cdn_mac, 6);
00571 #else
00572     ifn->if_mac[0] = 0x00;
00573     ifn->if_mac[1] = 0x06;
00574     ifn->if_mac[2] = 0x98;
00575     ifn->if_mac[3] = 0x00;
00576     ifn->if_mac[4] = 0x00;
00577     ifn->if_mac[5] = 0x00;
00578 #endif    
00579     memset(dev->dev_dcb, 0, sizeof(NICINFO));
00580     ni = (NICINFO *) dev->dev_dcb;
00581 
00582     
00583     CSSoftwareWakeup();
00584     CSSoftwareReset();
00585 
00586     NutDelay(100);
00587 
00588     
00589     if (CSReadPP16(CS_PROD_ID) != 0x630E)
00590         return -1;
00591 
00592     
00593     
00594     
00595     for (i = 0; i < 6; i += 2) {
00596         j = ifn->if_mac[i] << 8;
00597         j |= ifn->if_mac[i + 1];
00598         CSWritePP16(CS_IEEE_ADDR + i, j);
00599         j = CSReadPP16(CS_IEEE_ADDR + i);
00600 #if 0
00601         if (tcp_trace) {
00602             NutPrintFormat_P(dev_debug, PSTR("ADDR = %x\r\n"), j);
00603             NutPrintFlush(dev_debug);
00604         }
00605 #endif
00606     }
00607 
00608     
00609     
00610     
00611     CSWritePP16(CS_LINE_CTRL, 0x00C0);
00612     
00613     
00614 
00615     CSWritePP16(CS_RX_CTL, 0x0F40);
00616     
00617     
00618 
00619     
00620     
00621     
00622     NutThreadCreate("csnicrx", CSNICrx, dev, 768);
00623 
00624     return 0;
00625 }
00626 
00627 static NICINFO dcb_eth0;
00628 
00634 static IFNET ifn_eth0 = {
00635     IFT_ETHER,                  
00636     0,                          
00637     {0, 0, 0, 0, 0, 0},         
00638     0,                          
00639     0,                          
00640     0,                          
00641     ETHERMTU,                   
00642     0,                          
00643     0,                          
00644     0,                          
00645     NutEtherInput,              
00646     cs8900Output,               
00647     NutEtherOutput              
00648 };
00649 
00659 NUTDEVICE devCS8900A = {
00660     0,                          
00661     {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        
00662     IFTYP_NET,                  
00663     0,                          
00664     0,                          
00665     &ifn_eth0,                  
00666     &dcb_eth0,                  
00667     cs8900Init,                 
00668     0,                          
00669     0,                          
00670     0,                          
00671     0,                          
00672     0,                          
00673     0                           
00674 };
00675