DEC21143.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  *
00025  * Parts of this file based upon GXemul, which is Copyright (C) 2004-2007  
00026  * Anders Gavare.  All rights reserved.
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 /*  Internal states during MII data stream decode:  */
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       /*  Normal and Abnormal interrupt summary:  */
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     // Let the thread die...
00209   }
00210 }
00211 
00212 u32             dec21143_cfg_data[64] = {
00213   /*00*/ 0x00191011,  // CFID: vendor + device
00214   /*04*/ 0x02800000,  // CFCS: command + status
00215   /*08*/ 0x02000030,  // CFRV: class + revision   //dth:was 41
00216   /*0c*/ 0x00000000,  // CFLT: latency timer + cache line size
00217   /*10*/ 0x00000001,  // BAR0: CBIO
00218   /*14*/ 0x00000000,  // BAR1: CBMA
00219   /*18*/ 0x00000000,  // BAR2:
00220   /*1c*/ 0x00000000,  // BAR3:
00221   /*20*/ 0x00000000,  // BAR4:
00222   /*24*/ 0x00000000,  // BAR5:
00223   /*28*/ 0x00000000,  // CCIC: CardBus
00224   /*2c*/ 0x500b1011,  // CSID: subsystem + vendor
00225   /*30*/ 0x00000000,  // BAR6: expansion rom base
00226   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00227   /*38*/ 0x00000000,
00228   /*3c*/ 0x281401ff,  // CFIT: interrupt configuration
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   /*00*/ 0x00000000,  // CFID: vendor + device
00236   /*04*/ 0x0000ffff,  // CFCS: command + status
00237   /*08*/ 0x00000000,  // CFRV: class + revision
00238   /*0c*/ 0x0000ffff,  // CFLT: latency timer + cache line size
00239   /*10*/ 0xffffff00,  // BAR0
00240   /*14*/ 0xffffff00,  // BAR1: CBMA
00241   /*18*/ 0x00000000,  // BAR2:
00242   /*1c*/ 0x00000000,  // BAR3:
00243   /*20*/ 0x00000000,  // BAR4:
00244   /*24*/ 0x00000000,  // BAR5:
00245   /*28*/ 0x00000000,  // CCIC: CardBus
00246   /*2c*/ 0x00000000,  // CSID: subsystem + vendor
00247   /*30*/ 0x00000000,  // BAR6: expansion rom base
00248   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00249   /*38*/ 0x00000000,
00250   /*3c*/ 0x000000ff,  // CFIT: interrupt configuration
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     /* Print the list */
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     /* Jump to the selected adapter */
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   // Opening with pcap_open on Windows allows specification of PCAP_OPENFLAG_NOCAPTURE_LOCAL,
00322   // which stops the pcap device from seeing it's own transmitted packets.
00323   //
00324   // This is important because:
00325   //    1. Real ethernet cards don't reflect packets except while in loopback mode(s).
00326   //    2. Reflecting all packets increases inbound packet processing and host load.
00327   //    3. DECNET Phase IV will think a reflected packet is from another node
00328   //            that has the same DECNET Phase IV address (AA-xx-xx-xx-xx-xx),
00329   //            and will panic on startup and abort.
00330   //    4. Libpcap doesn't reflect packets, and we want winpcap/libpcap processing to be identical.
00331   // Loopback packets are handled via direct entry in the receive queue.
00332   if((fp = pcap_open(cfg, 65536 /*snaplen: capture entire packets */,
00333      PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_LOCAL /*promiscuous */,
00334    1 /*read timeout: 1ms. */, 0 /* auth structure */, errbuf)) == NULL) // connect to pcap...
00335 #else
00336     if((fp = pcap_open_live(cfg, 65536 /*snaplen: capture entire packets */,
00337        1 /*promiscuous */, 1 /*read timeout: 1ms. */, errbuf)) == NULL) // connect to pcap...
00338 #endif
00339       FAILURE_1(Runtime, "Error opening adapter %s", cfg);
00340 
00341   // set default mac = Digital ethernet prefix: 08-00-2B + hexified "ES40" + nic number
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   // set assigned mac
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: // CBIO
00460   case 1: // CBMA
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: // CBIO
00473   case 1: // CBMA
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   // if receive process active
00496   if(state.reg[CSR_OPMODE / 8] & OPMODE_SR)
00497   {
00498 
00499     // get packets from host nic if not in internal loopback mode
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;  //set 10bT activity
00507       }
00508     }
00509 
00510     // process a receive descriptor until we run out of
00511     // descriptors or packets to process
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   //printf("21143: rx_queue->name= %s\n", rx_queue->name);
00552   if((address & 7) == 0 && regnr < 32)
00553   {
00554     oldreg = state.reg[regnr];
00555     switch(regnr)
00556     {
00557     case CSR_STATUS / 8:  /*  Zero-on-write  */
00558       state.reg[regnr] &= ~((u32) data & 0x0c01ffff);
00559       break;
00560 
00561     case CSR_MISSED / 8:  /*  Read only  */
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:       /*  csr0  */
00574     if(data & BUSMODE_SWR)
00575     {
00576       ResetNIC();
00577       data &= ~BUSMODE_SWR;
00578     }
00579 
00580     // calculate descriptor skip length in bytes
00581     state.descr_skip = ((data & BUSMODE_DSL) >> 2) * 4;
00582     break;
00583 
00584   case CSR_TXPOLL:        /*  csr1  */
00585     /* CaVa interpretation... */
00586     state.reg[CSR_STATUS / 8] &= ~STATUS_TU;
00587     state.tx.suspend = false;
00588     state.tx.idling = state.tx.idling_threshold;
00589 
00590     //        DoClock();
00591     break;
00592 
00593   case CSR_RXPOLL:        /*  csr2  */
00594     //        DoClock();
00595     break;
00596 
00597   case CSR_RXLIST:        /*  csr3  */
00598     /* debug("[ dec21143: setting RXLIST to 0x%x ]\n", (int)data); */
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:        /*  csr4  */
00606     /* debug("[ dec21143: setting TXLIST to 0x%x ]\n", (int)data); */
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:        /*  csr5  */
00614   case CSR_INTEN:         /*  csr7  */
00615     /*  Recalculate interrupt assertion.  */
00616 
00617     //              DoClock();
00618     break;
00619 
00620   case CSR_OPMODE:        /*  csr6:  */
00621     if(data & 0x02000000)
00622     {
00623 
00624       /*  A must-be-one bit.  */
00625       data &= ~0x02000000;
00626     }
00627 
00628     if(data & OPMODE_ST)
00629     {
00630 
00631       //data &= ~OPMODE_ST;
00632     }
00633     else
00634     {
00635 
00636       /*  Turned off TX? Then idle:  */
00637 
00638       //      state.reg[CSR_STATUS/8] |= STATUS_TPS;
00639     }
00640 
00641     if(data & OPMODE_SR)
00642     {
00643 
00644       //data &= ~OPMODE_SR;
00645     }
00646     else
00647     {
00648 
00649       /*  Turned off RX? Then go to stopped state:  */
00650 
00651       //state.reg[CSR_STATUS/8] &= ~STATUS_RS;
00652     }
00653 
00654     // Did Start/Stop Transmission change state ?
00655     if((data ^ oldreg) & OPMODE_ST)
00656     {
00657       if(data & OPMODE_ST)
00658       { // ST went high
00659         set_tx_state(STATUS_TS_SUSPENDED);
00660       }
00661       else
00662       { // ST went low
00663         set_tx_state(STATUS_TS_STOPPED);
00664       }
00665     }
00666 
00667     // Did Start/Stop Receive change state ?
00668     if((data ^ oldreg) & OPMODE_SR)
00669     {
00670       if(data & OPMODE_SR)
00671       { // SR went high
00672         set_rx_state(STATUS_RS_WAIT);
00673       }
00674       else
00675       { // SR went low
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     //              if (data & OPMODE_PNIC_IT) {
00694     //                      data &= ~OPMODE_PNIC_IT;
00695     //                  state.tx.idling = state.tx.idling_threshold;
00696     //              }
00697     //              if (data != 0) {
00698     //                      printf("[ dec21143: UNIMPLEMENTED OPMODE bits: 0x%08x ]\n", (int)data);
00699     //              }
00700     //              DoClock();
00701     break;
00702 
00703   case CSR_MISSED:  /*  csr8  */
00704     break;
00705 
00706   case CSR_MIIROM:  /*  csr9  */
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: /*  csr12  */
00714     if(((data & SIASTAT_ANS) == SIASTAT_ANS_START)
00715      && (state.reg[CSR_SIATXRX / 8] & SIATXRX_ANE))
00716     {
00717 
00718       // autonegotiation restart... completes immediately in our emulated environment.
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       //          DoClock();
00731     }
00732     else
00733     {
00734       state.reg[CSR_SIASTAT / 8] = oldreg;
00735     }
00736     break;
00737 
00738   case CSR_SIATXRX: /*  csr14  */
00739     break;
00740 
00741   case CSR_SIACONN: /*  csr13  */
00742     if((data & SIACONN_SRL) && (state.reg[CSR_SIATXRX / 8] & SIATXRX_ANE))
00743     {
00744 
00745       // SIA started with autonegotiation... completes immediately in our emulated environment.
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       //          DoClock();
00758     }
00759     break;
00760 
00761   case CSR_SIAGEN:  /*  csr15  */
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   /*  Only care about data during clock cycles:  */
00805   if(!(idata & MIIROM_MDC))
00806     return;
00807 
00808   if(idata & MIIROM_MDC && oldreg & MIIROM_MDC)
00809     return;
00810 
00811   /*  printf("[ mii_access(): 0x%08x ]\n", (int)idata);  */
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     /*  Wait for a starting delimiter (0 followed by 1).  */
00828     if(obit)
00829       return;
00830     if(idata & MIIROM_MIIDIR)
00831       return;
00832 
00833     /*  printf("[ mii_access(): got a 0 delimiter ]\n");  */
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     /*  Wait for a starting delimiter (0 followed by 1).  */
00843     if(!obit)
00844       return;
00845     if(idata & MIIROM_MIIDIR)
00846     {
00847       state.mii.state = MII_STATE_RESET;
00848       return;
00849     }
00850 
00851     /*  printf("[ mii_access(): got a 1 delimiter ]\n");  */
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       /*  printf("[ mii_access(): got first opcode bit (%i) ]\n", obit);  */
00862     }
00863     else
00864     {
00865       state.mii.opcode |= obit;
00866 
00867       /*  printf("[ mii_access(): got opcode = %i ]\n", state.mii.opcode);  */
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     /*  printf("[ mii_access(): got phy/reg addr bit nr %i (%i)"
00877        " ]\n", state.mii.bit - 2, obit);  */
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       /*  printf("[ mii_access(): phyaddr=0x%x regaddr=0x"
00887          "%x ]\n", state.mii.phyaddr, state.mii.regaddr);  */
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         //                              debug("[ mii_access(): WRITE to phyaddr=0x%x regaddr=0x%x: 0x%04x ]\n", state.mii.phyaddr, state.mii.regaddr, tmp);
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       //                      if (state.mii.bit == 13)
00936       //                              debug("[ mii_access(): READ phyaddr=0x%x regaddr=0x%x: 0x%04x ]\n", state.mii.phyaddr, state.mii.regaddr, tmp);
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   /*  debug("CSR9 WRITE! 0x%08x\n", (int)idata);  */
00982 
00983   /*  New selection? Then reset internal state.  */
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   /*  Only care about data during clock cycles:  */
00993   if(!(idata & MIIROM_SROMSK))
00994     return;
00995 
00996   obit = 0;
00997   ibit = idata & MIIROM_SROMDI ? 1 : 0;
00998 
00999   /*  debug("CLOCK CYCLE! (bit %i): ", state.srom.curbit);  */
01000 
01001   /*
01002    *  Linux sends more zeroes before starting the actual opcode, than
01003    *  OpenBSD and NetBSD. Hopefully this is correct. (I'm just guessing
01004    *  that all opcodes should start with a 1, perhaps that's not really
01005    *  the case.)
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     /*  debug("opcode input '%i'\n", ibit);  */
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         //                              if (state.srom.curbit == 6 + 3)
01035         //                                      debug("[ dec21143: ROM read from offset 0x%03x: 0x%04x ]\n", state.srom.addr, romword);
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     /*  debug("input '%i', output '%i'\n", ibit, obit);  */
01054   }
01055 
01056   state.srom.curbit++;
01057 
01058   /*
01059    *  Done opcode + addr + data? Then restart. (At least NetBSD does
01060    *  sequential reads without turning selection off and then on.)
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 bool CDEC21143:acquire_rx_descriptor(u32 status_true, u32 status_false) {
01073         // get current receive descriptor
01074     do_pci_read(state.rx.cur_addr, descr, 4, 4);
01075 
01076         if (rdes0 & TDSTAT_OWN) {       // 21143 owns descriptor
01077                 state.reg[CSR_STATUS/8] &= ~STATUS_RU;  // clear buffers unavailable
01078                 if (state.reg[CSR_OPMODE/8] & OPMODE_SR) {      // if receive start
01079                         state.reg[CSR_STATUS/8] = (state.reg[CSR_STATUS/8] & ~STATUS_RS) | STATUS_RS_WAIT;
01080                 } else {
01081                 }
01082                 return true;            // indicate nothing was processed
01083         } else {
01084                 state.reg[CSR_STATUS/8] = (state.reg[CSR_STATUS/8] & ~(STATUS_RS | STATUS_RU)) | STATUS_R
01085                 return true;
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   //unsigned char descr[16];
01107   //u32 rdes0, rdes1, rdes2, rdes3;
01108   int           bufsize;
01109 
01110   //unsigned char descr[16];
01111   int           buf1_size;
01112 
01113   //unsigned char descr[16];
01114   int           buf2_size;
01115 
01116   //unsigned char descr[16];
01117   int           writeback_len = 4;
01118 
01119   //unsigned char descr[16];
01120   int           to_xfer;
01121 
01122   //struct pcap_pkthdr * packet_header;
01123   //const u_char * packet_data = NULL;
01124 
01125   /*  Is current packet finished? Then check for new ones.  */
01126   if(state.rx.current.used >= state.rx.current.len)
01127   {
01128 
01129     /*  Nothing available? Then abort.  */
01130     if(rx_queue->count() == 0)
01131       return 0;           // indicate nothing was processed
01132 
01133     //      printf("pcap recv: %d bytes (%d captured) for %02x:%02x:%02x:%02x:%02x:%02x  \n",packet_header->len, packet_header->caplen,packet_data[0],packet_data[1],packet_data[2],packet_data[3],packet_data[4],packet_data[5]);
01134     // get next packet from receive queue
01135     rx_queue->get_head(state.rx.current);
01136 
01137     /*  Append a 4 byte CRC:  */
01138 
01139     //state.rx.cur_buf_len += 4;
01140     //CHECK_REALLOCATION(state.rx.cur_buf, realloc(state.rx.cur_buf, state.rx.cur_buf_len), unsigned char);
01141 
01142     /*  Get the next packet into our buffer:  */
01143 
01144     //memcpy(state.rx.cur_buf, packet_data, state.rx.cur_buf_len);
01145 
01146     /*  Well... the CRC is just zeros, for now.  */
01147 
01148     //memset(state.rx.cur_buf + state.rx.cur_buf_len - 4, 0, 4);
01149     //state.rx.cur_offset = 0;
01150   }
01151 
01152   // read current descriptor
01153   do_pci_read(state.rx.cur_addr, descr, 4, 4);
01154 
01155   //rdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
01156   //rdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
01157   //rdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
01158   //rdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
01159 
01160   /*  Only use descriptors owned by the 21143:  */
01161   if(!(rdes0 & TDSTAT_OWN))
01162   {
01163 
01164     // set recive buffers unavailable and receive state to suspended
01165     state.reg[CSR_STATUS / 8] = (state.reg[CSR_STATUS / 8] &~STATUS_RS) |
01166       STATUS_RU |
01167       STATUS_RS_SUSPENDED;
01168     return 0;             // indicate nothing was processed
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   //state.reg[CSR_STATUS/8] &= ~STATUS_RS; // dth: wrong, this is receive state stopped
01177   //  printf("{ dec21143_rx: base = 0x%08x }\n", (int)addr);
01178   //      debug("{ RX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
01179   //          (long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize, (int)bufaddr);
01180   // Turn off all status bits, and give up ownership
01181   rdes0 = 0x00000000;
01182 
01183   //  Is this the first buffer of the frame?
01184   if(state.rx.current.used == 0)
01185     rdes0 |= TDSTAT_Rx_FS;
01186 
01187   // use buffer 1, if length is non-zero
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     // DMA bytes from the packet into buffer 1
01195     do_pci_write(rdes2, &state.rx.current.frame[state.rx.current.used], 1,
01196                  to_xfer);
01197 
01198     // update used
01199     state.rx.current.used += to_xfer;
01200   }
01201 
01202   // use buffer 2, if length is non-zero and not a chain buffer
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     // DMA bytes from the packet into buffer 2
01210     do_pci_write(rdes3, state.rx.current.frame + state.rx.current.used, 1,
01211                  to_xfer);
01212 
01213     // update used
01214     state.rx.current.used += to_xfer;
01215   }
01216 
01217   //  Frame completed?
01218   if(state.rx.current.used >= state.rx.current.len)
01219   {
01220 
01221     //        debug("frame complete.\n");
01222     rdes0 |= TDSTAT_Rx_LS;
01223 
01224     /*  Set the frame length:  */
01225     rdes0 |= (state.rx.current.len << 16) & TDSTAT_Rx_FL;
01226 
01227     /*  Frame too long? (1518 is max ethernet frame length)  */
01228     if(state.rx.current.len > 1518)
01229       rdes0 |= TDSTAT_Rx_TL;
01230 
01231     // set receive interrupt and receive state to waiting-for-packet
01232     state.reg[CSR_STATUS / 8] = (state.reg[CSR_STATUS / 8] &~STATUS_RS) |
01233       STATUS_RI |
01234       STATUS_RS_WAIT;
01235   }
01236 
01237   // Writeback rdes0, others are read-only
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   // move to next descriptor
01242   if(rdes1 & TDCTL_ER)    // end-of-ring, return to base
01243     state.rx.cur_addr = state.reg[CSR_RXLIST / 8];
01244   else
01245   {
01246     if(rdes1 & TDCTL_CH)  // explicit chain, use chain address
01247       state.rx.cur_addr = rdes3;
01248     else
01249       // implicit chain
01250       state.rx.cur_addr += sizeof(descr) + state.descr_skip;
01251   }
01252 
01253   return 1; // indicate processing has occurred
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   /*  printf("{ dec21143_tx: base=0x%08x, tdes0=0x%08x }\n", (int)addr, (int)tdes0);  */
01285 
01286   /*  Only process packets owned by the 21143:  */
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   //state.reg[CSR_STATUS/8] &= ~STATUS_TS;
01306   if(tdes1 & TDCTL_ER)    // end-of-ring, return to base
01307     state.tx.cur_addr = state.reg[CSR_TXLIST / 8];
01308   else
01309   {
01310     if(tdes1 & TDCTL_CH)  // explicit chain, use chain address
01311       state.tx.cur_addr = tdes3;
01312     else
01313       // implicit chain
01314       state.tx.cur_addr += (4 * sizeof(uint32_t)) + state.descr_skip;
01315   }
01316 
01317   /*
01318      printf("{ TX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
01319      (long long)addr, tdes0, tdes1, tdes2, tdes3, bufsize, (int)bufaddr);
01320    */
01321 
01322   /*  Assume no error:  */
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      *  Setup Packet.
01339      *
01340      *  TODO. For now, just ignore it, and pretend it worked.
01341      */
01342 
01343     //              printf("{ TX: setup packet }\n");
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     /*  New descriptor values, according to the docs:  */
01354     tdes0 = 0x7fffffff;
01355     tdes1 = 0xffffffff;
01356     tdes2 = 0xffffffff;
01357     tdes3 = 0xffffffff;
01358   }
01359   else
01360   {
01361 
01362     /*
01363      *  Data Packet.
01364      */
01365 
01366     //              printf("{ TX: data packet: ");
01367     if(tdes1 & TDCTL_Tx_FS)
01368     {
01369 
01370       /*  First segment. Let's allocate a new buffer:  */
01371 
01372       /*  printf("new frame }\n");  */
01373 
01374       //CHECK_ALLOCATION(state.tx.cur_buf = (unsigned char *)malloc(bufsize));
01375       state.tx.cur_buf_len = 0;
01376     }
01377     else
01378     {
01379 
01380       /*  Not first segment. Increase the length of the current buffer:  */
01381 
01382       /*  printf("continuing last frame }\n");  */
01383       if(state.tx.cur_buf == NULL)
01384         printf("[ dec21143: WARNING! tx: middle segment, but no first segment?! ]\n");
01385 
01386       //CHECK_REALLOCATION(state.tx.cur_buf, realloc(state.tx.cur_buf, state.tx.cur_buf_len + bufsize), unsigned char);
01387     }
01388 
01389     /*  "DMA" data from emulated physical memory into the buf:  */
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     /*  Last segment? Then actually transmit it:  */
01395     if(tdes1 & TDCTL_Tx_LS)
01396     {
01397 
01398       /*  printf("{ TX: data frame complete. }\n");  */
01399 
01400       // if not in internal loopback mode, transmit packet to wire
01401       if(!(state.reg[CSR_OPMODE / 8] & OPMODE_OM_INTLOOP))
01402       {
01403 
01404         // printf("pcap send: %d bytes   \n", state.tx.cur_buf_len);
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       // if in internal or external loopback mode, add packet to read queue
01410       if(state.reg[CSR_OPMODE / 8] & OPMODE_OM)
01411       {
01412         bool  crc = !(tdes1 & TDCTL_Tx_AC);
01413 
01414         //printf("21143: %s packet, AC: %d\n", (state.reg[CSR_OPMODE / 8] & OPMODE_OM_INTLOOP) ? "IL" : "EL", !crc);
01415         //printf("21143: TX enabled: %d, RX enabled: %d\n", state.reg[CSR_OPMODE /8] & OPMODE_ST, state.reg[CSR_OPMODE /8] & OPMODE_SR);
01416         //printf("21143: tx(), len=%d, addr=%08x, mode=%s\n", state.tx.cur_buf_len, (int) state.tx.cur_buf, (state.reg[CSR_OPMODE / 8] & OPMODE_OM_INTLOOP) ? "IL" : "EL");
01417         //printf("21143: tx(), data=|");
01418         //unsigned char* aptr = state.tx.cur_buf;
01419         //for(int i=0; i<state.tx.cur_buf_len; i++) {
01420         //      printf("%02x-",*aptr++);
01421         //}
01422         //printf("|\n");
01423         bool  resl = rx_queue->add_tail(state.tx.cur_buf, state.tx.cur_buf_len,
01424                                         calc_crc, crc);
01425       }
01426 
01427       //free(state.tx.cur_buf);
01428       //state.tx.cur_buf = NULL;
01429       state.tx.cur_buf_len = 0;
01430 
01431       /*  Interrupt, if Tx_IC is set:  */
01432       if(tdes1 & TDCTL_Tx_IC)
01433         state.reg[CSR_STATUS / 8] |= STATUS_TI;
01434     }
01435 
01436     /*  We are done with this segment.  */
01437     tdes0 &= ~TDSTAT_OWN;
01438   }
01439 
01440   /*  Error summary:  */
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   /*  Descriptor writeback:  */
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   //strcat(filter,"ether broadcast");
01544   //There must be at least one unique item; at least the mac of the card
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   //  if (state.tx.cur_buf != NULL)
01588   //        free(state.tx.cur_buf);
01589   state.rx.cur_buf = /*state.tx.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   /*  Register values at reset, according to the manual:  */
01596   state.reg[CSR_BUSMODE / 8] = 0xfe000000;  /*  csr0   */
01597   state.reg[CSR_MIIROM / 8] = 0xfff483ff;   /*  csr9   */
01598   state.reg[CSR_SIACONN / 8] = 0xffff0000;  /*  csr13  */
01599   state.reg[CSR_SIATXRX / 8] = 0xffffffff;  /*  csr14  */
01600   state.reg[CSR_SIAGEN / 8] = 0x8ff00000;   /*  csr15  */
01601 
01602   state.tx.idling_threshold = 10;
01603   state.rx.cur_addr = state.tx.cur_addr = 0;
01604 
01605   /*  Version (= 1) and Chip count (= 1):  */
01606   state.srom.data[TULIP_ROM_SROM_FORMAT_VERION] = 1;
01607   state.srom.data[TULIP_ROM_CHIP_COUNT] = 1;
01608 
01609   /*  Set the MAC address:  */
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;  /*  Not used?  */
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;      /*  descriptor length  */
01622   state.srom.data[leaf + 1] = TULIP_ROM_MB_21142_SIA;
01623   state.srom.data[leaf + 2] = TULIP_ROM_MB_MEDIA_100TX;
01624 
01625   /*  here comes 4 bytes of GPIO control/data settings  */
01626   leaf += state.srom.data[leaf];
01627 
01628   state.srom.data[leaf] = 15;     /*  descriptor length  */
01629   state.srom.data[leaf + 1] = TULIP_ROM_MB_21142_MII;
01630   state.srom.data[leaf + 2] = 0;  /*  PHY nr  */
01631   state.srom.data[leaf + 3] = 0;  /*  len of select sequence  */
01632   state.srom.data[leaf + 4] = 0;  /*  len of reset sequence  */
01633 
01634   /*  5,6, 7,8, 9,10, 11,12, 13,14 = unused by GXemul  */
01635   leaf += state.srom.data[leaf];
01636 
01637   /*  MII PHY initial state:  */
01638   state.mii.state = MII_STATE_RESET;
01639 
01640   /*  PHY #0:  */
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   // compute the CRC for the SROM data.  This code is from the
01650   // tu sample driver from HP in if_tu.c, which was apparently
01651   // derived from the 21140 Hardware Specification
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)

SourceForge.net Logo
Project space on SourceForge.net