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