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
00147 #include "StdAfx.h"
00148
00149 #if defined(HAVE_PCAP)
00150 #include "DEC21143.h"
00151 #include "System.h"
00152
00153 #if defined(DEBUG_NIC)
00154 #define DEBUG_NIC_FILTER
00155 #define DEBUG_NIC_SROM
00156 #endif
00157
00158
00159 #define MII_STATE_RESET 0
00160 #define MII_STATE_START_WAIT 1
00161 #define MII_STATE_READ_OP 2
00162 #define MII_STATE_READ_PHYADDR_REGADDR 3
00163 #define MII_STATE_A 4
00164 #define MII_STATE_D 5
00165 #define MII_STATE_IDLE 6
00166
00170 void CDEC21143::run()
00171 {
00172 try
00173 {
00174 for(;;)
00175 {
00176 if(StopThread)
00177 return;
00178 receive_process();
00179
00180 bool asserted;
00181
00182 if((state.reg[CSR_OPMODE / 8] & OPMODE_ST))
00183 while(dec21143_tx());
00184
00185
00186 state.reg[CSR_STATUS / 8] &= ~(STATUS_NIS | STATUS_AIS);
00187 if(state.reg[CSR_STATUS / 8] & state.reg[CSR_INTEN / 8] & 0x00004845)
00188 state.reg[CSR_STATUS / 8] |= STATUS_NIS;
00189 if(state.reg[CSR_STATUS / 8] & state.reg[CSR_INTEN / 8] & 0x0c0037ba)
00190 state.reg[CSR_STATUS / 8] |= STATUS_AIS;
00191
00192 asserted = (state.reg[CSR_STATUS / 8] & state.reg[CSR_INTEN / 8] & 0x0c01ffff) ? true : false;
00193
00194 if(asserted != state.irq_was_asserted)
00195 {
00196 if(do_pci_interrupt(0, asserted))
00197 state.irq_was_asserted = asserted;
00198 }
00199
00200 Poco::Thread::sleep(10);
00201 }
00202 }
00203
00204 catch(Poco::Exception & e)
00205 {
00206 printf("Exception in NIC thread: %s.\n", e.displayText().c_str());
00207
00208
00209 }
00210 }
00211
00212 u32 dec21143_cfg_data[64] = {
00213 0x00191011,
00214 0x02800000,
00215 0x02000030,
00216 0x00000000,
00217 0x00000001,
00218 0x00000000,
00219 0x00000000,
00220 0x00000000,
00221 0x00000000,
00222 0x00000000,
00223 0x00000000,
00224 0x500b1011,
00225 0x00000000,
00226 0x00000000,
00227 0x00000000,
00228 0x281401ff,
00229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00231 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00232 };
00233
00234 u32 dec21143_cfg_mask[64] = {
00235 0x00000000,
00236 0x0000ffff,
00237 0x00000000,
00238 0x0000ffff,
00239 0xffffff00,
00240 0xffffff00,
00241 0x00000000,
00242 0x00000000,
00243 0x00000000,
00244 0x00000000,
00245 0x00000000,
00246 0x00000000,
00247 0x00000000,
00248 0x00000000,
00249 0x00000000,
00250 0x000000ff,
00251 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00254 };
00255
00256 int CDEC21143:: nic_num = 0;
00257
00261 CDEC21143::CDEC21143(CConfigurator* confg, CSystem* c, int pcibus, int pcidev) : CPCIDevice(confg, c, pcibus, pcidev)
00262 { }
00263
00267 void CDEC21143::init()
00268 {
00269 pcap_if_t* alldevs;
00270
00271 pcap_if_t *d;
00272 u_int inum;
00273 u_int i = 0;
00274 char errbuf[PCAP_ERRBUF_SIZE];
00275 char* cfg;
00276
00277 add_function(0, dec21143_cfg_data, dec21143_cfg_mask);
00278
00279 cfg = myCfg->get_text_value("adapter");
00280 if(!cfg)
00281 {
00282 printf("\n%s: Choose a network adapter to connect to:\n", devid_string);
00283 if(pcap_findalldevs(&alldevs, errbuf) == -1)
00284 {
00285 FAILURE_1(Runtime, "Error in pcap_findalldevs_ex: %s", errbuf);
00286 }
00287
00288
00289 for(d = alldevs; d; d = d->next)
00290 {
00291 printf("%d. %s\n ", ++i, d->name);
00292 if(d->description)
00293 printf(" (%s)\n", d->description);
00294 else
00295 printf(" (No description available)\n");
00296 }
00297
00298 if(i == 0)
00299 FAILURE(Runtime, "No network interfaces found");
00300
00301 if(i == 1)
00302 inum = 1;
00303 else
00304 {
00305 inum = 0;
00306 while(inum < 1 || inum > i)
00307 {
00308 printf("%%NIC-Q-NICNO: Enter the interface number (1-%d):", i);
00309 scanf("%d", &inum);
00310 }
00311 }
00312
00313
00314 for(d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
00315
00316 cfg = d->name;
00317 }
00318
00319 #if defined(WIN32)
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 if((fp = pcap_open(cfg, 65536 ,
00333 PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_LOCAL ,
00334 1 , 0 , errbuf)) == NULL)
00335 #else
00336 if((fp = pcap_open_live(cfg, 65536 ,
00337 1 , 1 , errbuf)) == NULL)
00338 #endif
00339 FAILURE_1(Runtime, "Error opening adapter %s", cfg);
00340
00341
00342 state.mac[0] = 0x08;
00343 state.mac[1] = 0x00;
00344 state.mac[2] = 0x2B;
00345 state.mac[3] = 0xE5;
00346 state.mac[4] = 0x40;
00347 state.mac[5] = nic_num++;
00348
00349
00350 cfg = myCfg->get_text_value("mac");
00351 if(cfg)
00352 {
00353 const char* mac_chars = "0123456789abcdefABCDEF-.:";
00354 const char* hex_chars = "0123456789abcdefABCDEF";
00355 const char* hex_scanf = "%hx";
00356 bool mac_replaced = false;
00357 if((strlen(cfg) == 17) && (strspn(cfg, mac_chars) == 17))
00358 {
00359 char newmac[18];
00360 strcpy(newmac, cfg);
00361 newmac[2] = newmac[5] = newmac[8] = newmac[11] = newmac[14] = 0;
00362 if((strspn(&newmac[0], hex_chars) == 2)
00363 && (strspn(&newmac[3], hex_chars) == 2)
00364 && (strspn(&newmac[6], hex_chars) == 2)
00365 && (strspn(&newmac[9], hex_chars) == 2)
00366 && (strspn(&newmac[12], hex_chars) == 2)
00367 && (strspn(&newmac[15], hex_chars) == 2))
00368 {
00369 short unsigned int num;
00370 sscanf(&newmac[0], hex_scanf, &num);
00371 state.mac[0] = num & 0xff;
00372 sscanf(&newmac[3], hex_scanf, &num);
00373 state.mac[1] = num & 0xff;
00374 sscanf(&newmac[6], hex_scanf, &num);
00375 state.mac[2] = num & 0xff;
00376 sscanf(&newmac[9], hex_scanf, &num);
00377 state.mac[3] = num & 0xff;
00378 sscanf(&newmac[12], hex_scanf, &num);
00379 state.mac[4] = num & 0xff;
00380 sscanf(&newmac[15], hex_scanf, &num);
00381 state.mac[5] = num & 0xff;
00382 mac_replaced = true;
00383 }
00384 }
00385
00386 if(mac_replaced)
00387 {
00388 printf("%s: MAC set to %s\n", devid_string, cfg);
00389 }
00390 else
00391 {
00392 FAILURE_1(Configuration,
00393 "MAC address (%s) should have xx-xx-xx-xx-xx-xx format", cfg);
00394 }
00395 }
00396 else
00397 {
00398 char mac[18];
00399 sprintf(mac, "%02X-%02X-%02X-%02X-%02X-%02X", state.mac[0], state.mac[1],
00400 state.mac[2], state.mac[3], state.mac[4], state.mac[5]);
00401 printf("%s: MAC defaulted to %s\n", devid_string, mac);
00402 }
00403
00404 rx_queue = new CPacketQueue("rx_queue",
00405 (int) myCfg->get_num_value("queue", false, 100));
00406 calc_crc = myCfg->get_bool_value("crc", false);
00407
00408 state.rx.cur_buf = NULL;
00409 state.tx.cur_buf = (unsigned char*) malloc(1514);
00410 state.irq_was_asserted = false;
00411 state.tx.idling = 0;
00412
00413 ResetPCI();
00414
00415 myThread = 0;
00416
00417 printf("%s: $Id: DEC21143.cpp,v 1.35 2008/03/26 19:11:01 iamcamiel Exp $\n",
00418 devid_string);
00419 }
00420
00421 void CDEC21143::start_threads()
00422 {
00423 if(!myThread)
00424 {
00425 myThread = new Poco::Thread("nic");
00426 printf(" %s", myThread->getName().c_str());
00427 StopThread = false;
00428 myThread->start(*this);
00429 }
00430 }
00431
00432 void CDEC21143::stop_threads()
00433 {
00434 StopThread = true;
00435 if(myThread)
00436 {
00437 printf(" %s", myThread->getName().c_str());
00438 myThread->join();
00439 delete myThread;
00440 myThread = 0;
00441 }
00442 }
00443
00447 CDEC21143::~CDEC21143()
00448 {
00449 stop_threads();
00450
00451 pcap_close(fp);
00452 delete rx_queue;
00453 }
00454
00455 u32 CDEC21143::ReadMem_Bar(int func, int bar, u32 address, int dsize)
00456 {
00457 switch(bar)
00458 {
00459 case 0:
00460 case 1:
00461 return nic_read(address, dsize);
00462 }
00463
00464 printf("21143: ReadMem_Bar: unsupported bar %d\n", bar);
00465 return 0;
00466 }
00467
00468 void CDEC21143::WriteMem_Bar(int func, int bar, u32 address, int dsize, u32 data)
00469 {
00470 switch(bar)
00471 {
00472 case 0:
00473 case 1:
00474 nic_write(address, dsize, (u32) endian_bits(data, dsize));
00475 return;
00476 }
00477
00478 printf("21143: WriteMem_Bar: unsupported bar %d\n", bar);
00479 }
00480
00484 void CDEC21143::check_state()
00485 {
00486 if(myThread && !myThread->isRunning())
00487 FAILURE(Thread, "NIC thread has died");
00488 }
00489
00490 void CDEC21143::receive_process()
00491 {
00492 struct pcap_pkthdr* packet_header;
00493 const u_char* packet_data = NULL;
00494
00495
00496 if(state.reg[CSR_OPMODE / 8] & OPMODE_SR)
00497 {
00498
00499
00500 if(!(state.reg[CSR_OPMODE / 8] & OPMODE_OM_INTLOOP))
00501 {
00502 while(pcap_next_ex(fp, &packet_header, &packet_data) > 0)
00503 {
00504 bool resl = rx_queue->add_tail(packet_data, packet_header->caplen,
00505 calc_crc, true);
00506 state.reg[CSR_SIASTAT / 8] |= SIASTAT_TRA;
00507 }
00508 }
00509
00510
00511
00512 while(dec21143_rx());
00513 }
00514 }
00515
00519 u32 CDEC21143::nic_read(u32 address, int dsize)
00520 {
00521 u32 data = 0;
00522
00523 u32 oldreg = 0;
00524 int regnr = (int) (address >> 3);
00525
00526 if((address & 7) == 0 && regnr < 32)
00527 {
00528 data = state.reg[regnr];
00529 }
00530 else
00531 printf("dec21143: WARNING! unaligned access (0x%x) \n", (int) address);
00532 #if defined(DEBUG_NIC)
00533 printf("21143: nic_read - CSR(%d), value: %08x\n", regnr, data);
00534 #endif
00535 return data;
00536 }
00537
00541 void CDEC21143::nic_write(u32 address, int dsize, u32 data)
00542 {
00543 uint32_t oldreg = 0;
00544
00545 int regnr = (int) (address >> 3);
00546
00547 #if defined(DEBUG_NIC)
00548 printf("21143: nic_write - CSR(%d), value: %08x\n", regnr, data);
00549 #endif
00550
00551
00552 if((address & 7) == 0 && regnr < 32)
00553 {
00554 oldreg = state.reg[regnr];
00555 switch(regnr)
00556 {
00557 case CSR_STATUS / 8:
00558 state.reg[regnr] &= ~((u32) data & 0x0c01ffff);
00559 break;
00560
00561 case CSR_MISSED / 8:
00562 break;
00563
00564 default:
00565 state.reg[regnr] = (u32) data;
00566 }
00567 }
00568 else
00569 printf("[ dec21143: WARNING! unaligned access (0x%x) ]\n", (int) address);
00570
00571 switch(address)
00572 {
00573 case CSR_BUSMODE:
00574 if(data & BUSMODE_SWR)
00575 {
00576 ResetNIC();
00577 data &= ~BUSMODE_SWR;
00578 }
00579
00580
00581 state.descr_skip = ((data & BUSMODE_DSL) >> 2) * 4;
00582 break;
00583
00584 case CSR_TXPOLL:
00585
00586 state.reg[CSR_STATUS / 8] &= ~STATUS_TU;
00587 state.tx.suspend = false;
00588 state.tx.idling = state.tx.idling_threshold;
00589
00590
00591 break;
00592
00593 case CSR_RXPOLL:
00594
00595 break;
00596
00597 case CSR_RXLIST:
00598
00599 if(data & 0x3)
00600 printf("[ dec21143: WARNING! RXLIST not aligned? (0x%x) ]\n", data);
00601 data &= ~0x3;
00602 state.rx.cur_addr = data;
00603 break;
00604
00605 case CSR_TXLIST:
00606
00607 if(data & 0x3)
00608 printf("[ dec21143: WARNING! TXLIST not aligned? (0x%x) ]\n", data);
00609 data &= ~0x3;
00610 state.tx.cur_addr = data;
00611 break;
00612
00613 case CSR_STATUS:
00614 case CSR_INTEN:
00615
00616
00617
00618 break;
00619
00620 case CSR_OPMODE:
00621 if(data & 0x02000000)
00622 {
00623
00624
00625 data &= ~0x02000000;
00626 }
00627
00628 if(data & OPMODE_ST)
00629 {
00630
00631
00632 }
00633 else
00634 {
00635
00636
00637
00638
00639 }
00640
00641 if(data & OPMODE_SR)
00642 {
00643
00644
00645 }
00646 else
00647 {
00648
00649
00650
00651
00652 }
00653
00654
00655 if((data ^ oldreg) & OPMODE_ST)
00656 {
00657 if(data & OPMODE_ST)
00658 {
00659 set_tx_state(STATUS_TS_SUSPENDED);
00660 }
00661 else
00662 {
00663 set_tx_state(STATUS_TS_STOPPED);
00664 }
00665 }
00666
00667
00668 if((data ^ oldreg) & OPMODE_SR)
00669 {
00670 if(data & OPMODE_SR)
00671 {
00672 set_rx_state(STATUS_RS_WAIT);
00673 }
00674 else
00675 {
00676 set_tx_state(STATUS_RS_STOPPED);
00677 }
00678 }
00679
00680 data &= ~
00681 (
00682 OPMODE_HBD |
00683 OPMODE_SCR |
00684 OPMODE_PCS |
00685 OPMODE_PS |
00686 OPMODE_SF |
00687 OPMODE_TTM |
00688 OPMODE_FD |
00689 OPMODE_TR |
00690 OPMODE_OM
00691 );
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 break;
00702
00703 case CSR_MISSED:
00704 break;
00705
00706 case CSR_MIIROM:
00707 if(data & MIIROM_MDC)
00708 mii_access(oldreg, (u32) data);
00709 else
00710 srom_access(oldreg, (u32) data);
00711 break;
00712
00713 case CSR_SIASTAT:
00714 if(((data & SIASTAT_ANS) == SIASTAT_ANS_START)
00715 && (state.reg[CSR_SIATXRX / 8] & SIATXRX_ANE))
00716 {
00717
00718
00719 state.reg[CSR_SIASTAT / 8] &= ~SIASTAT_ANS;
00720 state.reg[CSR_SIASTAT / 8] |=
00721 (
00722 SIASTAT_ANS_FLPGOOD |
00723 SIASTAT_LPN |
00724 SIASTAT_LPC
00725 );
00726 state.reg[CSR_STATUS / 8] |= STATUS_LNPANC;
00727 state.reg[CSR_SIATXRX / 8] &= ~(SIATXRX_TH | SIATXRX_THX | SIATXRX_T4);
00728 state.reg[CSR_SIATXRX / 8] |= SIATXRX_TXF;
00729
00730
00731 }
00732 else
00733 {
00734 state.reg[CSR_SIASTAT / 8] = oldreg;
00735 }
00736 break;
00737
00738 case CSR_SIATXRX:
00739 break;
00740
00741 case CSR_SIACONN:
00742 if((data & SIACONN_SRL) && (state.reg[CSR_SIATXRX / 8] & SIATXRX_ANE))
00743 {
00744
00745
00746 state.reg[CSR_SIASTAT / 8] &= ~SIASTAT_ANS;
00747 state.reg[CSR_SIASTAT / 8] |=
00748 (
00749 SIASTAT_ANS_FLPGOOD |
00750 SIASTAT_LPN |
00751 SIASTAT_LPC
00752 );
00753 state.reg[CSR_STATUS / 8] |= STATUS_LNPANC;
00754 state.reg[CSR_SIATXRX / 8] &= ~(SIATXRX_TH | SIATXRX_THX | SIATXRX_T4);
00755 state.reg[CSR_SIATXRX / 8] |= SIATXRX_TXF;
00756
00757
00758 }
00759 break;
00760
00761 case CSR_SIAGEN:
00762 break;
00763
00764 default:
00765 printf("[ dec21143: write to unimplemented 0x%02x: 0x%02x ]\n", (int) address,
00766 (int) data);
00767 }
00768 }
00769
00770 void CDEC21143::set_tx_state(int tx_state)
00771 {
00772 state.reg[CSR_STATUS / 8] &= ~STATUS_TS;
00773 state.reg[CSR_STATUS / 8] |= (tx_state & STATUS_TS);
00774 }
00775
00776 void CDEC21143::set_rx_state(int rx_state)
00777 {
00778 state.reg[CSR_STATUS / 8] &= ~STATUS_RS;
00779 state.reg[CSR_STATUS / 8] |= (rx_state & STATUS_RS);
00780 }
00781
00797 void CDEC21143::mii_access(uint32_t oldreg, uint32_t idata)
00798 {
00799 int obit;
00800
00801 int ibit = 0;
00802 uint16_t tmp;
00803
00804
00805 if(!(idata & MIIROM_MDC))
00806 return;
00807
00808 if(idata & MIIROM_MDC && oldreg & MIIROM_MDC)
00809 return;
00810
00811
00812 if(idata & MIIROM_BR)
00813 {
00814 printf("[ mii_access(): MIIROM_BR: TODO ]\n");
00815 return;
00816 }
00817
00818 obit = idata & MIIROM_MDO ? 1 : 0;
00819
00820 if(state.mii.state >= MII_STATE_START_WAIT
00821 && state.mii.state <= MII_STATE_READ_PHYADDR_REGADDR && idata & MIIROM_MIIDIR) printf("[ mii_access(): bad dir? ]\n");
00822
00823 switch(state.mii.state)
00824 {
00825 case MII_STATE_RESET:
00826
00827
00828 if(obit)
00829 return;
00830 if(idata & MIIROM_MIIDIR)
00831 return;
00832
00833
00834 state.mii.state = MII_STATE_START_WAIT;
00835 state.mii.opcode = 0;
00836 state.mii.phyaddr = 0;
00837 state.mii.regaddr = 0;
00838 break;
00839
00840 case MII_STATE_START_WAIT:
00841
00842
00843 if(!obit)
00844 return;
00845 if(idata & MIIROM_MIIDIR)
00846 {
00847 state.mii.state = MII_STATE_RESET;
00848 return;
00849 }
00850
00851
00852 state.mii.state = MII_STATE_READ_OP;
00853 state.mii.bit = 0;
00854 break;
00855
00856 case MII_STATE_READ_OP:
00857 if(state.mii.bit == 0)
00858 {
00859 state.mii.opcode = obit << 1;
00860
00861
00862 }
00863 else
00864 {
00865 state.mii.opcode |= obit;
00866
00867
00868 state.mii.state = MII_STATE_READ_PHYADDR_REGADDR;
00869 }
00870
00871 state.mii.bit++;
00872 break;
00873
00874 case MII_STATE_READ_PHYADDR_REGADDR:
00875
00876
00877
00878 if(state.mii.bit <= 6)
00879 state.mii.phyaddr |= obit << (6 - state.mii.bit);
00880 else
00881 state.mii.regaddr |= obit << (11 - state.mii.bit);
00882 state.mii.bit++;
00883 if(state.mii.bit >= 12)
00884 {
00885
00886
00887
00888 state.mii.state = MII_STATE_A;
00889 }
00890 break;
00891
00892 case MII_STATE_A:
00893 switch(state.mii.opcode)
00894 {
00895 case MII_COMMAND_WRITE:
00896 if(state.mii.bit >= 13)
00897 state.mii.state = MII_STATE_D;
00898 break;
00899
00900 case MII_COMMAND_READ:
00901 ibit = 0;
00902 state.mii.state = MII_STATE_D;
00903 break;
00904
00905 default:
00906 printf("[ mii_access(): UNIMPLEMENTED MII opcode %i (probably just a bug in GXemul's MII data stream handling) ]\n",
00907 state.mii.opcode);
00908 state.mii.state = MII_STATE_RESET;
00909 }
00910
00911 state.mii.bit++;
00912 break;
00913
00914 case MII_STATE_D:
00915 switch(state.mii.opcode)
00916 {
00917 case MII_COMMAND_WRITE:
00918 if(idata & MIIROM_MIIDIR)
00919 printf("[ mii_access(): write: bad dir? ]\n");
00920 obit = obit ? (0x8000 >> (state.mii.bit - 14)) : 0;
00921 tmp = state.mii.phy_reg[(state.mii.phyaddr << 5) + state.mii.regaddr] | obit;
00922 if(state.mii.bit >= 29)
00923 {
00924 state.mii.state = MII_STATE_IDLE;
00925
00926
00927 }
00928 break;
00929
00930 case MII_COMMAND_READ:
00931 if(!(idata & MIIROM_MIIDIR))
00932 break;
00933 tmp = state.mii.phy_reg[(state.mii.phyaddr << 5) + state.mii.regaddr];
00934
00935
00936
00937 ibit = tmp & (0x8000 >> (state.mii.bit - 13));
00938 if(state.mii.bit >= 28)
00939 state.mii.state = MII_STATE_IDLE;
00940 break;
00941 }
00942
00943 state.mii.bit++;
00944 break;
00945
00946 case MII_STATE_IDLE:
00947 state.mii.bit++;
00948 if(state.mii.bit >= 31)
00949 state.mii.state = MII_STATE_RESET;
00950 break;
00951 }
00952
00953 state.reg[CSR_MIIROM / 8] &= ~MIIROM_MDI;
00954 if(ibit)
00955 state.reg[CSR_MIIROM / 8] |= MIIROM_MDI;
00956 }
00957
00975 void CDEC21143::srom_access(uint32_t oldreg, uint32_t idata)
00976 {
00977 int obit;
00978
00979 int ibit;
00980
00981
00982
00983
00984 if(idata & MIIROM_SR && !(oldreg & MIIROM_SR))
00985 {
00986 state.srom.curbit = 0;
00987 state.srom.opcode = 0;
00988 state.srom.opcode_has_started = 0;
00989 state.srom.addr = 0;
00990 }
00991
00992
00993 if(!(idata & MIIROM_SROMSK))
00994 return;
00995
00996 obit = 0;
00997 ibit = idata & MIIROM_SROMDI ? 1 : 0;
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 if(!ibit && !state.srom.opcode_has_started)
01008 return;
01009
01010 if(state.srom.curbit < 3)
01011 {
01012 state.srom.opcode_has_started = 1;
01013 state.srom.opcode <<= 1;
01014 state.srom.opcode |= ibit;
01015
01016
01017 }
01018 else
01019 {
01020 switch(state.srom.opcode)
01021 {
01022 case TULIP_SROM_OPC_READ:
01023 if(state.srom.curbit < 6 + 3)
01024 {
01025 obit = state.srom.curbit < 6 + 2;
01026 state.srom.addr <<= 1;
01027 state.srom.addr |= ibit;
01028 }
01029 else
01030 {
01031 uint16_t romword = state.srom.data[state.srom.addr * 2] +
01032 (state.srom.data[state.srom.addr * 2 + 1] << 8);
01033
01034
01035
01036 obit = romword & (0x8000 >> (state.srom.curbit - 6 - 3)) ? 1 : 0;
01037 #if defined(DEBUG_NIC_SROM)
01038 printf("%%NIC-I-SROMREAD: Read %04x from %04x\n", romword,
01039 state.srom.addr);
01040 #endif
01041 }
01042 break;
01043
01044 default:
01045 printf("[ dec21243: unimplemented SROM/EEPROM opcode %i ]\n",
01046 state.srom.opcode);
01047 }
01048
01049 state.reg[CSR_MIIROM / 8] &= ~MIIROM_SROMDO;
01050 if(obit)
01051 state.reg[CSR_MIIROM / 8] |= MIIROM_SROMDO;
01052
01053
01054 }
01055
01056 state.srom.curbit++;
01057
01058
01059
01060
01061
01062 if(state.srom.curbit >= 3 + 6 + 16)
01063 {
01064 state.srom.curbit = 0;
01065 state.srom.opcode = 0;
01066 state.srom.opcode_has_started = 0;
01067 state.srom.addr = 0;
01068 }
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01095 int CDEC21143::dec21143_rx()
01096 {
01097 static u32 descr[4];
01098 static u32& rdes0 = descr[0];
01099 static u32& rdes1 = descr[1];
01100 static u32& rdes2 = descr[2];
01101 static u32& rdes3 = descr[3];
01102
01103 u32 addr = state.rx.cur_addr;
01104 u32 bufaddr;
01105
01106
01107
01108 int bufsize;
01109
01110
01111 int buf1_size;
01112
01113
01114 int buf2_size;
01115
01116
01117 int writeback_len = 4;
01118
01119
01120 int to_xfer;
01121
01122
01123
01124
01125
01126 if(state.rx.current.used >= state.rx.current.len)
01127 {
01128
01129
01130 if(rx_queue->count() == 0)
01131 return 0;
01132
01133
01134
01135 rx_queue->get_head(state.rx.current);
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150 }
01151
01152
01153 do_pci_read(state.rx.cur_addr, descr, 4, 4);
01154
01155
01156
01157
01158
01159
01160
01161 if(!(rdes0 & TDSTAT_OWN))
01162 {
01163
01164
01165 state.reg[CSR_STATUS / 8] = (state.reg[CSR_STATUS / 8] &~STATUS_RS) |
01166 STATUS_RU |
01167 STATUS_RS_SUSPENDED;
01168 return 0;
01169 }
01170
01171 buf1_size = rdes1 & TDCTL_SIZE1;
01172 buf2_size = (rdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
01173 bufaddr = buf1_size ? rdes2 : rdes3;
01174 bufsize = buf1_size ? buf1_size : buf2_size;
01175
01176
01177
01178
01179
01180
01181 rdes0 = 0x00000000;
01182
01183
01184 if(state.rx.current.used == 0)
01185 rdes0 |= TDSTAT_Rx_FS;
01186
01187
01188 if(buf1_size > 0)
01189 {
01190 to_xfer = state.rx.current.len - state.rx.current.used;
01191 if(to_xfer > buf1_size)
01192 to_xfer = buf1_size;
01193
01194
01195 do_pci_write(rdes2, &state.rx.current.frame[state.rx.current.used], 1,
01196 to_xfer);
01197
01198
01199 state.rx.current.used += to_xfer;
01200 }
01201
01202
01203 if((buf2_size > 0) && (!(rdes1 & TDCTL_CH)))
01204 {
01205 to_xfer = state.rx.current.len - state.rx.current.used;
01206 if(to_xfer > buf2_size)
01207 to_xfer = buf2_size;
01208
01209
01210 do_pci_write(rdes3, state.rx.current.frame + state.rx.current.used, 1,
01211 to_xfer);
01212
01213
01214 state.rx.current.used += to_xfer;
01215 }
01216
01217
01218 if(state.rx.current.used >= state.rx.current.len)
01219 {
01220
01221
01222 rdes0 |= TDSTAT_Rx_LS;
01223
01224
01225 rdes0 |= (state.rx.current.len << 16) & TDSTAT_Rx_FL;
01226
01227
01228 if(state.rx.current.len > 1518)
01229 rdes0 |= TDSTAT_Rx_TL;
01230
01231
01232 state.reg[CSR_STATUS / 8] = (state.reg[CSR_STATUS / 8] &~STATUS_RS) |
01233 STATUS_RI |
01234 STATUS_RS_WAIT;
01235 }
01236
01237
01238 state.reg[CSR_STATUS / 8] = (state.reg[CSR_STATUS / 8] &~STATUS_RS) | STATUS_RS_CLOSE;
01239 do_pci_write(state.rx.cur_addr, descr, 4, 1);
01240
01241
01242 if(rdes1 & TDCTL_ER)
01243 state.rx.cur_addr = state.reg[CSR_RXLIST / 8];
01244 else
01245 {
01246 if(rdes1 & TDCTL_CH)
01247 state.rx.cur_addr = rdes3;
01248 else
01249
01250 state.rx.cur_addr += sizeof(descr) + state.descr_skip;
01251 }
01252
01253 return 1;
01254 }
01255
01260 int CDEC21143::dec21143_tx()
01261 {
01262 u32 addr = state.tx.cur_addr;
01263
01264 u32 bufaddr;
01265 unsigned char descr[16];
01266 u32 tdes0;
01267 u32 tdes1;
01268 u32 tdes2;
01269 u32 tdes3;
01270 int bufsize;
01271 int buf1_size;
01272 int buf2_size;
01273
01274 if(state.tx.suspend)
01275 return 0;
01276
01277 do_pci_read(addr, descr, 1, 16);
01278
01279 tdes0 = descr[0] + (descr[1] << 8) + (descr[2] << 16) + (descr[3] << 24);
01280 tdes1 = descr[4] + (descr[5] << 8) + (descr[6] << 16) + (descr[7] << 24);
01281 tdes2 = descr[8] + (descr[9] << 8) + (descr[10] << 16) + (descr[11] << 24);
01282 tdes3 = descr[12] + (descr[13] << 8) + (descr[14] << 16) + (descr[15] << 24);
01283
01284
01285
01286
01287 if(!(tdes0 & TDSTAT_OWN))
01288 {
01289 if(state.tx.idling > state.tx.idling_threshold)
01290 {
01291 state.reg[CSR_STATUS / 8] |= STATUS_TU;
01292 state.tx.suspend = true;
01293 state.tx.idling = 0;
01294 }
01295 else
01296 state.tx.idling++;
01297 return 0;
01298 }
01299
01300 buf1_size = tdes1 & TDCTL_SIZE1;
01301 buf2_size = (tdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
01302 bufaddr = buf1_size ? tdes2 : tdes3;
01303 bufsize = buf1_size ? buf1_size : buf2_size;
01304
01305
01306 if(tdes1 & TDCTL_ER)
01307 state.tx.cur_addr = state.reg[CSR_TXLIST / 8];
01308 else
01309 {
01310 if(tdes1 & TDCTL_CH)
01311 state.tx.cur_addr = tdes3;
01312 else
01313
01314 state.tx.cur_addr += (4 * sizeof(uint32_t)) + state.descr_skip;
01315 }
01316
01317
01318
01319
01320
01321
01322
01323 tdes0 &= ~
01324 (
01325 TDSTAT_Tx_UF |
01326 TDSTAT_Tx_EC |
01327 TDSTAT_Tx_LC |
01328 TDSTAT_Tx_NC |
01329 TDSTAT_Tx_LO |
01330 TDSTAT_Tx_TO |
01331 TDSTAT_ES
01332 );
01333
01334 if(tdes1 & TDCTL_Tx_SET)
01335 {
01336
01337
01338
01339
01340
01341
01342
01343
01344 if(bufsize != 192)
01345 printf("[ dec21143: setup packet len = %i, should be 192! ]\n",
01346 (int) bufsize);
01347 do_pci_read(bufaddr, state.setup_filter, 1, 192);
01348 SetupFilter();
01349
01350 if(tdes1 & TDCTL_Tx_IC)
01351 state.reg[CSR_STATUS / 8] |= STATUS_TI;
01352
01353
01354 tdes0 = 0x7fffffff;
01355 tdes1 = 0xffffffff;
01356 tdes2 = 0xffffffff;
01357 tdes3 = 0xffffffff;
01358 }
01359 else
01360 {
01361
01362
01363
01364
01365
01366
01367 if(tdes1 & TDCTL_Tx_FS)
01368 {
01369
01370
01371
01372
01373
01374
01375 state.tx.cur_buf_len = 0;
01376 }
01377 else
01378 {
01379
01380
01381
01382
01383 if(state.tx.cur_buf == NULL)
01384 printf("[ dec21143: WARNING! tx: middle segment, but no first segment?! ]\n");
01385
01386
01387 }
01388
01389
01390 do_pci_read(bufaddr, state.tx.cur_buf + state.tx.cur_buf_len, 1, bufsize);
01391
01392 state.tx.cur_buf_len += bufsize;
01393
01394
01395 if(tdes1 & TDCTL_Tx_LS)
01396 {
01397
01398
01399
01400
01401 if(!(state.reg[CSR_OPMODE / 8] & OPMODE_OM_INTLOOP))
01402 {
01403
01404
01405 if(pcap_sendpacket(fp, state.tx.cur_buf, state.tx.cur_buf_len))
01406 printf("Error sending the packet: %s\n", pcap_geterr);
01407 }
01408
01409
01410 if(state.reg[CSR_OPMODE / 8] & OPMODE_OM)
01411 {
01412 bool crc = !(tdes1 & TDCTL_Tx_AC);
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 bool resl = rx_queue->add_tail(state.tx.cur_buf, state.tx.cur_buf_len,
01424 calc_crc, crc);
01425 }
01426
01427
01428
01429 state.tx.cur_buf_len = 0;
01430
01431
01432 if(tdes1 & TDCTL_Tx_IC)
01433 state.reg[CSR_STATUS / 8] |= STATUS_TI;
01434 }
01435
01436
01437 tdes0 &= ~TDSTAT_OWN;
01438 }
01439
01440
01441 if(tdes0 & (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC | TDSTAT_Tx_NC |
01442 TDSTAT_Tx_LO | TDSTAT_Tx_TO))
01443 tdes0 |= TDSTAT_ES;
01444
01445
01446 descr[0] = (u8) tdes0;
01447 descr[1] = (u8) (tdes0 >> 8);
01448 descr[2] = (u8) (tdes0 >> 16);
01449 descr[3] = (u8) (tdes0 >> 24);
01450 descr[4] = (u8) tdes1;
01451 descr[5] = (u8) (tdes1 >> 8);
01452 descr[6] = (u8) (tdes1 >> 16);
01453 descr[7] = (u8) (tdes1 >> 24);
01454 descr[8] = (u8) tdes2;
01455 descr[9] = (u8) (tdes2 >> 8);
01456 descr[10] = (u8) (tdes2 >> 16);
01457 descr[11] = (u8) (tdes2 >> 24);
01458 descr[12] = (u8) tdes3;
01459 descr[13] = (u8) (tdes3 >> 8);
01460 descr[14] = (u8) (tdes3 >> 16);
01461 descr[15] = (u8) (tdes3 >> 24);
01462
01463 do_pci_write(addr, descr, 1, 16);
01464
01465 return 1;
01466 }
01467
01468 void CDEC21143::SetupFilter()
01469 {
01470 u8 mac[16][6];
01471 char mac_txt[16][20];
01472 char filter[1000];
01473 int i;
01474 int j;
01475 int numUnique;
01476 int unique[16];
01477 bool u;
01478 #if defined(DEBUG_NIC_FILTER)
01479 printf("Building a filter...\n");
01480 #endif
01481 for(i = 0; i < 16; i++)
01482 {
01483 mac[i][0] = state.setup_filter[i * 12];
01484 mac[i][1] = state.setup_filter[i * 12 + 1];
01485 mac[i][2] = state.setup_filter[i * 12 + 4];
01486 mac[i][3] = state.setup_filter[i * 12 + 5];
01487 mac[i][4] = state.setup_filter[i * 12 + 8];
01488 mac[i][5] = state.setup_filter[i * 12 + 9];
01489 sprintf(mac_txt[i], "%02x:%02x:%02x:%02x:%02x:%02x", mac[i][0], mac[i][1],
01490 mac[i][2], mac[i][3], mac[i][4], mac[i][5]);
01491 #if defined(DEBUG_NIC_FILTER)
01492 printf("MAC[%d] = %s. \n", i, mac_txt[i]);
01493 #endif
01494 }
01495
01496 #if defined(DEBUG_NIC_FILTER)
01497 printf("Filter mode: ");
01498 if(state.reg[CSR_OPMODE / 8] & OPMODE_PR)
01499 printf("promiscuous.\n");
01500 else
01501 {
01502 if(state.reg[CSR_OPMODE / 8] & OPMODE_IF)
01503 printf("inverse ");
01504 if(state.reg[CSR_OPMODE / 8] & OPMODE_HP)
01505 {
01506 printf("hash ");
01507 if(state.reg[CSR_OPMODE / 8] & OPMODE_HO)
01508 printf("only ");
01509 }
01510 else
01511 printf("perfect ");
01512 printf("filtering.\n");
01513 }
01514 #endif
01515 numUnique = 0;
01516 for(i = 0; i < 16; i++)
01517 {
01518 u = true;
01519 for(j = 0; j < numUnique; j++)
01520 {
01521 if(mac[i][0] == mac[unique[j]][0] && mac[i][1] == mac[unique[j]][1]
01522 && mac[i][2] == mac[unique[j]][2] && mac[i][3] == mac[unique[j]][3]
01523 && mac[i][4] == mac[unique[j]][4] && mac[i][5] == mac[unique[j]][5])
01524 {
01525 u = false;
01526 break;
01527 }
01528 }
01529
01530 if(u)
01531 {
01532 unique[numUnique] = i;
01533 numUnique++;
01534 }
01535 }
01536
01537 #if defined(DEBUG_NIC_FILTER)
01538 for(i = 0; i < numUnique; i++)
01539 printf("Unique MAC[%d] = %s. \n", i, mac_txt[unique[i]]);
01540 #endif
01541 filter[0] = '\0';
01542
01543
01544
01545 strcat(filter, "ether dst ");
01546 strcat(filter, mac_txt[unique[0]]);
01547 for(i = 1; i < numUnique; i++)
01548 {
01549 strcat(filter, " or ether dst ");
01550 strcat(filter, mac_txt[unique[i]]);
01551 }
01552
01553 #if defined(DEBUG_NIC_FILTER)
01554 printf("FILTER = %s. \n", filter);
01555 #endif
01556 if(pcap_compile(fp, &fcode, filter, 1, 0xffffffff) < 0)
01557 FAILURE_1(Logic, "Unable to compile the packet filter (%s)", filter);
01558
01559 if(pcap_setfilter(fp, &fcode) < 0)
01560 FAILURE(Runtime, "Error setting the filter.");
01561 }
01562
01567 void CDEC21143::ResetPCI()
01568 {
01569 CPCIDevice::ResetPCI();
01570
01571 ResetNIC();
01572 }
01573
01580 void CDEC21143::ResetNIC()
01581 {
01582 int leaf;
01583
01584 if(state.rx.cur_buf != NULL)
01585 free(state.rx.cur_buf);
01586
01587
01588
01589 state.rx.cur_buf = NULL;
01590
01591 memset(state.reg, 0, sizeof(uint32_t) * 32);
01592 memset(state.srom.data, 0, sizeof(state.srom.data));
01593 memset(state.mii.phy_reg, 0, sizeof(state.mii.phy_reg));
01594
01595
01596 state.reg[CSR_BUSMODE / 8] = 0xfe000000;
01597 state.reg[CSR_MIIROM / 8] = 0xfff483ff;
01598 state.reg[CSR_SIACONN / 8] = 0xffff0000;
01599 state.reg[CSR_SIATXRX / 8] = 0xffffffff;
01600 state.reg[CSR_SIAGEN / 8] = 0x8ff00000;
01601
01602 state.tx.idling_threshold = 10;
01603 state.rx.cur_addr = state.tx.cur_addr = 0;
01604
01605
01606 state.srom.data[TULIP_ROM_SROM_FORMAT_VERION] = 1;
01607 state.srom.data[TULIP_ROM_CHIP_COUNT] = 1;
01608
01609
01610 memcpy(state.srom.data + TULIP_ROM_IEEE_NETWORK_ADDRESS, state.mac, 6);
01611
01612 leaf = 30;
01613 state.srom.data[TULIP_ROM_CHIPn_DEVICE_NUMBER(0)] = 0;
01614 state.srom.data[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)] = leaf & 255;
01615 state.srom.data[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0) + 1] = leaf >> 8;
01616
01617 state.srom.data[leaf + TULIP_ROM_IL_SELECT_CONN_TYPE] = 0;
01618 state.srom.data[leaf + TULIP_ROM_IL_MEDIA_COUNT] = 2;
01619 leaf += TULIP_ROM_IL_MEDIAn_BLOCK_BASE;
01620
01621 state.srom.data[leaf] = 7;
01622 state.srom.data[leaf + 1] = TULIP_ROM_MB_21142_SIA;
01623 state.srom.data[leaf + 2] = TULIP_ROM_MB_MEDIA_100TX;
01624
01625
01626 leaf += state.srom.data[leaf];
01627
01628 state.srom.data[leaf] = 15;
01629 state.srom.data[leaf + 1] = TULIP_ROM_MB_21142_MII;
01630 state.srom.data[leaf + 2] = 0;
01631 state.srom.data[leaf + 3] = 0;
01632 state.srom.data[leaf + 4] = 0;
01633
01634
01635 leaf += state.srom.data[leaf];
01636
01637
01638 state.mii.state = MII_STATE_RESET;
01639
01640
01641 state.mii.phy_reg[MII_BMSR] = BMSR_100TXFDX |
01642 BMSR_10TFDX |
01643 BMSR_ACOMP |
01644 BMSR_ANEG |
01645 BMSR_LINK;
01646
01647 state.tx.suspend = false;
01648
01649
01650
01651
01652 unsigned int POLY = 0x04c11db6;
01653 unsigned int FlippedCrc = 0;
01654 unsigned int Crc = 0xffffffff;
01655 unsigned char i;
01656 unsigned char CurrentByte;
01657 unsigned char Bit;
01658 unsigned char Msb;
01659 unsigned char chksm_1;
01660 unsigned char chksm_2;
01661
01662 for(i = 0; i < 126; i++)
01663 {
01664 CurrentByte = state.srom.data[i];
01665
01666 for(Bit = 0; Bit < 8; Bit++)
01667 {
01668 Msb = (Crc >> 31) & 1;
01669 Crc <<= 1;
01670
01671 if(Msb ^ (CurrentByte & 1))
01672 {
01673 Crc ^= POLY;
01674 Crc |= 1;
01675 }
01676
01677 CurrentByte >>= 1;
01678 }
01679 }
01680
01681 for(i = 0; i < 32; i++)
01682 {
01683 FlippedCrc <<= 1;
01684 Bit = Crc & 1;
01685 Crc >>= 1;
01686 FlippedCrc += Bit;
01687 }
01688
01689 Crc = FlippedCrc ^ 0xffffffff;
01690
01691 chksm_1 = Crc & 0xff;
01692 chksm_2 = Crc >> 8;
01693
01694 state.srom.data[126] = chksm_1;
01695 state.srom.data[127] = chksm_2;
01696 #if defined(DEBUG_NIC_SROM)
01697 printf("%%NIC-I-CKSUM: SROM checksum bytes are %02x, %02x\n",
01698 state.srom.data[126], state.srom.data[127]);
01699 #endif
01700 }
01701
01702 static u32 nic_magic1 = 0xDEC21143;
01703 static u32 nic_magic2 = 0x21143DEC;
01704
01708 int CDEC21143::SaveState(FILE* f)
01709 {
01710 long ss = sizeof(state);
01711 int res;
01712
01713 if(res = CPCIDevice::SaveState(f))
01714 return res;
01715
01716 fwrite(&nic_magic1, sizeof(u32), 1, f);
01717 fwrite(&ss, sizeof(long), 1, f);
01718 fwrite(&state, sizeof(state), 1, f);
01719 fwrite(&nic_magic2, sizeof(u32), 1, f);
01720 printf("%s: %d bytes saved.\n", devid_string, ss);
01721 return 0;
01722 }
01723
01727 int CDEC21143::RestoreState(FILE* f)
01728 {
01729 long ss;
01730 u32 m1;
01731 u32 m2;
01732 int res;
01733 size_t r;
01734
01735 if(res = CPCIDevice::RestoreState(f))
01736 return res;
01737
01738 r = fread(&m1, sizeof(u32), 1, f);
01739 if(r != 1)
01740 {
01741 printf("%s: unexpected end of file!\n", devid_string);
01742 return -1;
01743 }
01744
01745 if(m1 != nic_magic1)
01746 {
01747 printf("%s: MAGIC 1 does not match!\n", devid_string);
01748 return -1;
01749 }
01750
01751 fread(&ss, sizeof(long), 1, f);
01752 if(r != 1)
01753 {
01754 printf("%s: unexpected end of file!\n", devid_string);
01755 return -1;
01756 }
01757
01758 if(ss != sizeof(state))
01759 {
01760 printf("%s: STRUCT SIZE does not match!\n", devid_string);
01761 return -1;
01762 }
01763
01764 fread(&state, sizeof(state), 1, f);
01765 if(r != 1)
01766 {
01767 printf("%s: unexpected end of file!\n", devid_string);
01768 return -1;
01769 }
01770
01771 r = fread(&m2, sizeof(u32), 1, f);
01772 if(r != 1)
01773 {
01774 printf("%s: unexpected end of file!\n", devid_string);
01775 return -1;
01776 }
01777
01778 if(m2 != nic_magic2)
01779 {
01780 printf("%s: MAGIC 1 does not match!\n", devid_string);
01781 return -1;
01782 }
01783
01784 printf("%s: %d bytes restored.\n", devid_string, ss);
01785 return 0;
01786 }
01787 #endif //defined(HAVE_PCAP)