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