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