DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/ne2000.cpp
00001 #include "config.h"
00002 
00003 #if C_NE2000
00004 
00005 #if defined(WIN32)
00006   #define HAVE_REMOTE
00007 #endif
00008 
00009 #include "dosbox.h"
00010 #include <string.h>
00011 #include <stdio.h>
00012 #include "support.h"
00013 #include "inout.h"
00014 #include "setup.h"
00015 #include "callback.h"
00016 #include "timer.h"
00017 #include "pic.h"
00018 #include "cpu.h"
00019 #include "setup.h"
00020 #include "control.h"
00021 
00022 /* Couldn't find a real spec for the NE2000 out there, hence this is adapted heavily from Bochs */
00023 
00024 
00026 // $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $
00028 //
00029 //  Copyright (C) 2002  MandrakeSoft S.A.
00030 //
00031 //    MandrakeSoft S.A.
00032 //    43, rue d'Aboukir
00033 //    75002 Paris - France
00034 //    http://www.linux-mandrake.com/
00035 //    http://www.mandrakesoft.com/
00036 //
00037 //  This library is free software; you can redistribute it and/or
00038 //  modify it under the terms of the GNU Lesser General Public
00039 //  License as published by the Free Software Foundation; either
00040 //  version 2 of the License, or (at your option) any later version.
00041 //
00042 //  This library is distributed in the hope that it will be useful,
00043 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00044 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00045 //  Lesser General Public License for more details.
00046 //
00047 //  You should have received a copy of the GNU General Public License along
00048 //  with this program; if not, write to the Free Software Foundation, Inc.,
00049 //  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00050 
00051 // Peter Grehan (grehan@iprg.nokia.com) coded all of this
00052 // NE2000/ether stuff.
00053 
00054 #include "ne2000.h"
00055 
00056 #include "pcap.h"
00057 // Handle to WinPCap device
00058 pcap_t *adhandle = 0;
00059 static void NE2000_TX_Event(Bitu val);
00060 
00061 #ifdef WIN32
00062 // DLL loading
00063 #define pcap_sendpacket(A,B,C)                  PacketSendPacket(A,B,C)
00064 #define pcap_close(A)                                   PacketClose(A)
00065 #define pcap_freealldevs(A)                             PacketFreealldevs(A)
00066 #define pcap_open(A,B,C,D,E,F)                  PacketOpen(A,B,C,D,E,F)
00067 #define pcap_next_ex(A,B,C)                             PacketNextEx(A,B,C)
00068 #define pcap_findalldevs_ex(A,B,C,D)    PacketFindALlDevsEx(A,B,C,D)
00069 
00070 int (*PacketSendPacket)(pcap_t *, const u_char *, int) = 0;
00071 void (*PacketClose)(pcap_t *) = 0;
00072 void (*PacketFreealldevs)(pcap_if_t *) = 0;
00073 pcap_t* (*PacketOpen)(char const *,int,int,int,struct pcap_rmtauth *,char *) = 0;
00074 int (*PacketNextEx)(pcap_t *, struct pcap_pkthdr **, const u_char **) = 0;
00075 int (*PacketFindALlDevsEx)(char *, struct pcap_rmtauth *, pcap_if_t **, char *) = 0;
00076 
00077 #endif
00078 
00079 //Never completely fill the ne2k ring so that we never
00080 // hit the unclear completely full buffer condition.
00081 #define BX_NE2K_NEVER_FULL_RING (1)
00082 
00083 #define LOG_THIS theNE2kDevice->
00084 //#define BX_DEBUG 
00085 //#define BX_INFO 
00086 #define BX_NULL_TIMER_HANDLE 0
00087 //#define BX_PANIC 
00088 //#define BX_ERROR 
00089 #define BX_RESET_HARDWARE 0
00090 #define BX_RESET_SOFTWARE 1
00091 
00092 static char bxtmp[1024];
00093 
00094 static inline void BX_INFO(const char *msg,...) {
00095     va_list va;
00096 
00097     va_start(va,msg);
00098     vsnprintf(bxtmp,sizeof(bxtmp)-1,msg,va);
00099     va_end(va);
00100 
00101     LOG(LOG_MISC,LOG_NORMAL)("BX_INFO: %s",bxtmp);
00102 }
00103 
00104 static inline void BX_DEBUG(const char *msg,...) {
00105     if (false/*TOO MUCH DEBUG INFO*/) {
00106         va_list va;
00107 
00108         va_start(va,msg);
00109         vsnprintf(bxtmp,sizeof(bxtmp)-1,msg,va);
00110         va_end(va);
00111 
00112         LOG(LOG_MISC,LOG_DEBUG)("BX_DEBUG: %s",bxtmp);
00113     }
00114 }
00115 
00116 static inline void BX_ERROR(const char *msg,...) {
00117     va_list va;
00118 
00119     va_start(va,msg);
00120     vsnprintf(bxtmp,sizeof(bxtmp)-1,msg,va);
00121     va_end(va);
00122 
00123     LOG_MSG("BX_ERROR: %s",bxtmp);
00124 }
00125 
00126 static inline void BX_PANIC(const char *msg,...) {
00127     va_list va;
00128 
00129     va_start(va,msg);
00130     vsnprintf(bxtmp,sizeof(bxtmp)-1,msg,va);
00131     va_end(va);
00132 
00133     LOG_MSG("BX_PANIC: %s",bxtmp);
00134     E_Exit("BX_PANIC condition");
00135 }
00136 
00137 bx_ne2k_c* theNE2kDevice = NULL;
00138 
00139   
00140 bx_ne2k_c::bx_ne2k_c(void)
00141 {
00142   s.tx_timer_index = BX_NULL_TIMER_HANDLE;
00143 }
00144 
00145 
00146 bx_ne2k_c::~bx_ne2k_c(void)
00147 {
00148   // nothing for now
00149 }
00150 
00151 //
00152 // reset - restore state to power-up, cancelling all i/o
00153 //
00154 void
00155 bx_ne2k_c::reset(unsigned type)
00156 {
00157     (void)type;//UNUSED
00158   BX_DEBUG ("reset");
00159   // Zero out registers and memory
00160   memset( & BX_NE2K_THIS s.CR,  0, sizeof(BX_NE2K_THIS s.CR) );
00161   memset( & BX_NE2K_THIS s.ISR, 0, sizeof(BX_NE2K_THIS s.ISR));
00162   memset( & BX_NE2K_THIS s.IMR, 0, sizeof(BX_NE2K_THIS s.IMR));
00163   memset( & BX_NE2K_THIS s.DCR, 0, sizeof(BX_NE2K_THIS s.DCR));
00164   memset( & BX_NE2K_THIS s.TCR, 0, sizeof(BX_NE2K_THIS s.TCR));
00165   memset( & BX_NE2K_THIS s.TSR, 0, sizeof(BX_NE2K_THIS s.TSR));
00166   //memset( & BX_NE2K_THIS s.RCR, 0, sizeof(BX_NE2K_THIS s.RCR));
00167   memset( & BX_NE2K_THIS s.RSR, 0, sizeof(BX_NE2K_THIS s.RSR));
00168   BX_NE2K_THIS s.tx_timer_active = 0;
00169   BX_NE2K_THIS s.local_dma  = 0;
00170   BX_NE2K_THIS s.page_start = 0;
00171   BX_NE2K_THIS s.page_stop  = 0;
00172   BX_NE2K_THIS s.bound_ptr  = 0;
00173   BX_NE2K_THIS s.tx_page_start = 0;
00174   BX_NE2K_THIS s.num_coll   = 0;
00175   BX_NE2K_THIS s.tx_bytes   = 0;
00176   BX_NE2K_THIS s.fifo       = 0;
00177   BX_NE2K_THIS s.remote_dma = 0;
00178   BX_NE2K_THIS s.remote_start = 0;
00179   BX_NE2K_THIS s.remote_bytes = 0;
00180   BX_NE2K_THIS s.tallycnt_0 = 0;
00181   BX_NE2K_THIS s.tallycnt_1 = 0;
00182   BX_NE2K_THIS s.tallycnt_2 = 0;
00183 
00184   //memset( & BX_NE2K_THIS s.physaddr, 0, sizeof(BX_NE2K_THIS s.physaddr));
00185   //memset( & BX_NE2K_THIS s.mchash, 0, sizeof(BX_NE2K_THIS s.mchash));
00186   BX_NE2K_THIS s.curr_page = 0;
00187 
00188   BX_NE2K_THIS s.rempkt_ptr   = 0;
00189   BX_NE2K_THIS s.localpkt_ptr = 0;
00190   BX_NE2K_THIS s.address_cnt  = 0;
00191 
00192   memset( & BX_NE2K_THIS s.mem, 0, sizeof(BX_NE2K_THIS s.mem));
00193   
00194   // Set power-up conditions
00195   BX_NE2K_THIS s.CR.stop      = 1;
00196     BX_NE2K_THIS s.CR.rdma_cmd  = 4;
00197   BX_NE2K_THIS s.ISR.reset    = 1;
00198   BX_NE2K_THIS s.DCR.longaddr = 1;
00199   PIC_DeActivateIRQ((unsigned int)s.base_irq);
00200   //DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq);
00201 }
00202 
00203 //
00204 // read_cr/write_cr - utility routines for handling reads/writes to
00205 // the Command Register
00206 //
00207 Bit32u
00208 bx_ne2k_c::read_cr(void)
00209 {
00210   Bit32u val = 
00211     (((unsigned int)(BX_NE2K_THIS s.CR.pgsel    & 0x03u) << 6u) |
00212          ((unsigned int)(BX_NE2K_THIS s.CR.rdma_cmd & 0x07u) << 3u) |
00213           (unsigned int)(BX_NE2K_THIS s.CR.tx_packet << 2u) |
00214           (unsigned int)(BX_NE2K_THIS s.CR.start     << 1u) |
00215           (unsigned int)(BX_NE2K_THIS s.CR.stop));
00216   BX_DEBUG("read CR returns 0x%08x", val);
00217   return val;
00218 }
00219 
00220 void
00221 bx_ne2k_c::write_cr(Bit32u value)
00222 {
00223   BX_DEBUG ("wrote 0x%02x to CR", value);
00224 
00225   // Validate remote-DMA
00226   if ((value & 0x38) == 0x00) {
00227     BX_DEBUG("CR write - invalid rDMA value 0");
00228     value |= 0x20; /* dma_cmd == 4 is a safe default */
00229         //value = 0x22; /* dma_cmd == 4 is a safe default */
00230   }
00231 
00232   // Check for s/w reset
00233   if (value & 0x01) {
00234     BX_NE2K_THIS s.ISR.reset = 1;
00235     BX_NE2K_THIS s.CR.stop   = 1;
00236   } else {
00237     BX_NE2K_THIS s.CR.stop = 0;
00238   }
00239 
00240   BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3;
00241   
00242   // If start command issued, the RST bit in the ISR
00243   // must be cleared
00244   if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) {
00245     BX_NE2K_THIS s.ISR.reset = 0;
00246   }
00247 
00248   BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02);
00249   BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6;
00250 
00251     // Check for send-packet command
00252     if (BX_NE2K_THIS s.CR.rdma_cmd == 3) {
00253         // Set up DMA read from receive ring
00254                 BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma =
00255                         BX_NE2K_THIS s.bound_ptr * 256;
00256                 BX_NE2K_THIS s.remote_bytes = *((Bit16u*) &
00257                         BX_NE2K_THIS s.mem[BX_NE2K_THIS s.bound_ptr * 256 + 2 - BX_NE2K_MEMSTART]);
00258                 BX_INFO("Sending buffer #x%x length %d",
00259                         BX_NE2K_THIS s.remote_start,
00260                         BX_NE2K_THIS s.remote_bytes);
00261     }
00262 
00263   // Check for start-tx
00264     if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) {
00265                 // loopback mode
00266                 if (BX_NE2K_THIS s.TCR.loop_cntl != 1) {
00267                         BX_INFO("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl);
00268                 } else {
00269                         rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 -
00270                                 BX_NE2K_MEMSTART],
00271                                 BX_NE2K_THIS s.tx_bytes);
00272 
00273                         // do a TX interrupt
00274                         // Generate an interrupt if not masked and not one in progress
00275                         if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) {
00276                                 //LOG_MSG("tx complete interrupt");
00277                                 PIC_ActivateIRQ((unsigned int)s.base_irq);
00278                         }
00279                         BX_NE2K_THIS s.ISR.pkt_tx = 1;
00280                 }
00281     } else if (value & 0x04) {
00282                 // start-tx and no loopback
00283                 if (BX_NE2K_THIS s.CR.stop || !BX_NE2K_THIS s.CR.start)
00284                         BX_PANIC(("CR write - tx start, dev in reset"));
00285             
00286                 if (BX_NE2K_THIS s.tx_bytes == 0)
00287                         BX_PANIC(("CR write - tx start, tx bytes == 0"));
00288 
00289 #ifdef notdef    
00290     // XXX debug stuff
00291     printf("packet tx (%d bytes):\t", BX_NE2K_THIS s.tx_bytes);
00292     for (int i = 0; i < BX_NE2K_THIS s.tx_bytes; i++) {
00293       printf("%02x ", BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - 
00294                                 BX_NE2K_MEMSTART + i]);
00295       if (i && (((i+1) % 16) == 0)) 
00296         printf("\t");
00297     }
00298     printf("");
00299 #endif    
00300 
00301     // Send the packet to the system driver
00302         /* TODO: Transmit packet */
00303     //BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes);
00304         pcap_sendpacket(adhandle,&s.mem[s.tx_page_start*256 - BX_NE2K_MEMSTART], s.tx_bytes);
00305         // some more debug
00306         if (BX_NE2K_THIS s.tx_timer_active) {
00307       BX_PANIC(("CR write, tx timer still active"));
00308           PIC_RemoveEvents(NE2000_TX_Event);
00309         }
00310         //LOG_MSG("send packet command");
00311         //s.tx_timer_index = (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10;
00312         s.tx_timer_active = 1;
00313         PIC_AddEvent(NE2000_TX_Event,(float)((64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10000.0),0);
00314     // Schedule a timer to trigger a tx-complete interrupt
00315     // The number of microseconds is the bit-time / 10.
00316     // The bit-time is the preamble+sfd (64 bits), the
00317     // inter-frame gap (96 bits), the CRC (4 bytes), and the
00318     // the number of bits in the frame (s.tx_bytes * 8).
00319     //
00320 
00321         /* TODO: Code transmit timer */
00322         /*
00323     bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index,
00324                                 (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10,
00325                                 0); // not continuous
00326         */
00327   } // end transmit-start branch
00328 
00329   // Linux probes for an interrupt by setting up a remote-DMA read
00330   // of 0 bytes with remote-DMA completion interrupts enabled.
00331   // Detect this here
00332   if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 &&
00333       BX_NE2K_THIS s.CR.start &&
00334       BX_NE2K_THIS s.remote_bytes == 0) {
00335     BX_NE2K_THIS s.ISR.rdma_done = 1;
00336     if (BX_NE2K_THIS s.IMR.rdma_inte) {
00337                 PIC_ActivateIRQ((unsigned int)s.base_irq);
00338       //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
00339     }
00340   }
00341 }
00342 
00343 //
00344 // chipmem_read/chipmem_write - access the 64K private RAM.
00345 // The ne2000 memory is accessed through the data port of
00346 // the asic (offset 0) after setting up a remote-DMA transfer.
00347 // Both byte and word accesses are allowed.
00348 // The first 16 bytes contains the MAC address at even locations,
00349 // and there is 16K of buffer memory starting at 16K
00350 //
00351 Bit32u bx_ne2k_c::chipmem_read(Bit32u address, unsigned int io_len)
00352 {
00353   Bit32u retval = 0;
00354 
00355   if ((io_len == 2) && (address & 0x1)) 
00356     BX_PANIC(("unaligned chipmem word read"));
00357 
00358   // ROM'd MAC address
00359   if (/*(address >=0) && */address <= 31) {
00360     retval = BX_NE2K_THIS s.macaddr[address];
00361     if ((io_len == 2u) || (io_len == 4u)) {
00362       retval |= (unsigned int)(BX_NE2K_THIS s.macaddr[address + 1u] << 8u);
00363           if (io_len == 4u) {
00364                         retval |= (unsigned int)(BX_NE2K_THIS s.macaddr[address + 2u] << 16u);
00365                         retval |= (unsigned int)(BX_NE2K_THIS s.macaddr[address + 3u] << 24u);
00366           }
00367     }
00368     return (retval);
00369   }
00370 
00371   if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) {
00372     retval = BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART];
00373     if ((io_len == 2u) || (io_len == 4u)) {
00374       retval |= (unsigned int)(BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] << 8u);
00375     }
00376         if (io_len == 4u) {
00377        retval |= (unsigned int)(BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 2] << 16u);
00378        retval |= (unsigned int)(BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 3] << 24u);
00379     }
00380     return (retval);
00381   }
00382 
00383   BX_DEBUG("out-of-bounds chipmem read, %04X", address);
00384 
00385   return (0xff);
00386 }
00387 
00388 void 
00389 bx_ne2k_c::chipmem_write(Bit32u address, Bit32u value, unsigned io_len)
00390 {
00391   if ((io_len == 2) && (address & 0x1)) 
00392     BX_PANIC(("unaligned chipmem word write"));
00393 
00394   if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) {
00395     BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART] = value & 0xff;
00396     if (io_len == 2)
00397       BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] = value >> 8;
00398   } else
00399     BX_DEBUG("out-of-bounds chipmem write, %04X", address);
00400 }
00401 
00402 //
00403 // asic_read/asic_write - This is the high 16 bytes of i/o space
00404 // (the lower 16 bytes is for the DS8390). Only two locations
00405 // are used: offset 0, which is used for data transfer, and
00406 // offset 0xf, which is used to reset the device.
00407 // The data transfer port is used to as 'external' DMA to the
00408 // DS8390. The chip has to have the DMA registers set up, and
00409 // after that, insw/outsw instructions can be used to move
00410 // the appropriate number of bytes to/from the device.
00411 //
00412 Bit32u 
00413 bx_ne2k_c::asic_read(Bit32u offset, unsigned int io_len)
00414 {
00415   Bit32u retval = 0;
00416 
00417   switch (offset) {
00418   case 0x0:  // Data register
00419     //
00420     // A read remote-DMA command must have been issued,
00421     // and the source-address and length registers must  
00422     // have been initialised.
00423     //
00424     if (io_len > BX_NE2K_THIS s.remote_bytes)
00425       {
00426        BX_ERROR("ne2K: dma read underrun iolen=%d remote_bytes=%d",io_len,BX_NE2K_THIS s.remote_bytes);
00427        //return 0;
00428       }
00429 
00430     //BX_INFO(("ne2k read DMA: addr=%4x remote_bytes=%d",BX_NE2K_THIS s.remote_dma,BX_NE2K_THIS s.remote_bytes));
00431     retval = chipmem_read(BX_NE2K_THIS s.remote_dma, io_len);
00432     //
00433     // The 8390 bumps the address and decreases the byte count
00434     // by the selected word size after every access, not by
00435     // the amount of data requested by the host (io_len).
00436     //
00437     BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1);
00438     if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) {
00439       BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8;
00440     }
00441     // keep s.remote_bytes from underflowing
00442     if (BX_NE2K_THIS s.remote_bytes > 1)
00443       BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1);
00444     else
00445       BX_NE2K_THIS s.remote_bytes = 0;
00446 
00447         // If all bytes have been written, signal remote-DMA complete
00448         if (BX_NE2K_THIS s.remote_bytes == 0) {
00449             BX_NE2K_THIS s.ISR.rdma_done = 1;
00450             if (BX_NE2K_THIS s.IMR.rdma_inte) {
00451                         PIC_ActivateIRQ((unsigned int)s.base_irq);
00452                 //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
00453                 }
00454         }
00455     break;
00456 
00457   case 0xf:  // Reset register
00458     theNE2kDevice->reset(BX_RESET_SOFTWARE);
00459         //retval=0x1;
00460     break;
00461 
00462   default:
00463     BX_INFO("asic read invalid address %04x", (unsigned) offset);
00464     break;
00465   }
00466 
00467   return (retval);
00468 }
00469 
00470 void
00471 bx_ne2k_c::asic_write(Bit32u offset, Bit32u value, unsigned io_len)
00472 {
00473   BX_DEBUG("asic write addr=0x%02x, value=0x%04x", (unsigned) offset, (unsigned) value);
00474   switch (offset) {
00475   case 0x0:  // Data register - see asic_read for a description
00476 
00477     if ((io_len == 2) && (BX_NE2K_THIS s.DCR.wdsize == 0)) {
00478       BX_PANIC(("dma write length 2 on byte mode operation"));
00479       break;
00480     }
00481 
00482     if (BX_NE2K_THIS s.remote_bytes == 0)
00483       BX_PANIC(("ne2K: dma write, byte count 0"));
00484 
00485     chipmem_write(BX_NE2K_THIS s.remote_dma, value, io_len);
00486     // is this right ??? asic_read uses DCR.wordsize
00487     BX_NE2K_THIS s.remote_dma   += io_len;
00488     if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) {
00489       BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8;
00490     }
00491 
00492     BX_NE2K_THIS s.remote_bytes -= io_len;
00493     if (BX_NE2K_THIS s.remote_bytes > BX_NE2K_MEMSIZ)
00494       BX_NE2K_THIS s.remote_bytes = 0;
00495 
00496     // If all bytes have been written, signal remote-DMA complete
00497     if (BX_NE2K_THIS s.remote_bytes == 0) {
00498       BX_NE2K_THIS s.ISR.rdma_done = 1;
00499       if (BX_NE2K_THIS s.IMR.rdma_inte) {
00500           PIC_ActivateIRQ((unsigned int)s.base_irq);
00501           //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
00502       }
00503     }
00504     break;
00505 
00506   case 0xf:  // Reset register
00507     theNE2kDevice->reset(BX_RESET_SOFTWARE);
00508     break;
00509 
00510   default: // this is invalid, but happens under win95 device detection
00511     BX_INFO("asic write invalid address %04x, ignoring", (unsigned) offset);
00512     break ;
00513   }
00514 }
00515 
00516 //
00517 // page0_read/page0_write - These routines handle reads/writes to
00518 // the 'zeroth' page of the DS8390 register file
00519 //
00520 Bit32u
00521 bx_ne2k_c::page0_read(Bit32u offset, unsigned int io_len)
00522 {
00523   BX_DEBUG("page 0 read from port %04x, len=%u", (unsigned) offset,
00524            (unsigned) io_len);
00525   if (io_len > 1) {
00526     BX_ERROR("bad length! page 0 read from port %04x, len=%u", (unsigned) offset,
00527              (unsigned) io_len); /* encountered with win98 hardware probe */
00528         return 0;
00529   }
00530 
00531 
00532   switch (offset) {
00533   case 0x1:  // CLDA0
00534     return (BX_NE2K_THIS s.local_dma & 0xff);
00535     break;
00536 
00537   case 0x2:  // CLDA1
00538     return (unsigned int)(BX_NE2K_THIS s.local_dma >> 8u);
00539     break;
00540 
00541   case 0x3:  // BNRY
00542     return (BX_NE2K_THIS s.bound_ptr);
00543     break;
00544 
00545   case 0x4:  // TSR
00546     return
00547        ((unsigned int)(BX_NE2K_THIS s.TSR.ow_coll    << 7u) |
00548             (unsigned int)(BX_NE2K_THIS s.TSR.cd_hbeat   << 6u) |
00549             (unsigned int)(BX_NE2K_THIS s.TSR.fifo_ur    << 5u) |
00550             (unsigned int)(BX_NE2K_THIS s.TSR.no_carrier << 4u) |
00551             (unsigned int)(BX_NE2K_THIS s.TSR.aborted    << 3u) |
00552             (unsigned int)(BX_NE2K_THIS s.TSR.collided   << 2u) |
00553             (unsigned int)(BX_NE2K_THIS s.TSR.tx_ok));
00554     break;
00555 
00556   case 0x5:  // NCR
00557     return (BX_NE2K_THIS s.num_coll);
00558     break;
00559     
00560   case 0x6:  // FIFO
00561     // reading FIFO is only valid in loopback mode
00562     BX_ERROR(("reading FIFO not supported yet"));
00563     return (BX_NE2K_THIS s.fifo);
00564     break;
00565 
00566   case 0x7:  // ISR
00567     return
00568        ((unsigned int)(BX_NE2K_THIS s.ISR.reset     << 7u) |
00569             (unsigned int)(BX_NE2K_THIS s.ISR.rdma_done << 6u) |
00570             (unsigned int)(BX_NE2K_THIS s.ISR.cnt_oflow << 5u) |
00571             (unsigned int)(BX_NE2K_THIS s.ISR.overwrite << 4u) |
00572             (unsigned int)(BX_NE2K_THIS s.ISR.tx_err    << 3u) |
00573             (unsigned int)(BX_NE2K_THIS s.ISR.rx_err    << 2u) |
00574             (unsigned int)(BX_NE2K_THIS s.ISR.pkt_tx    << 1u) |
00575             (unsigned int)(BX_NE2K_THIS s.ISR.pkt_rx));
00576     break;
00577     
00578   case 0x8:  // CRDA0
00579     return (BX_NE2K_THIS s.remote_dma & 0xff);
00580     break;
00581 
00582   case 0x9:  // CRDA1
00583     return (unsigned int)(BX_NE2K_THIS s.remote_dma >> 8u);
00584     break;
00585 
00586   case 0xa:  // reserved
00587     BX_INFO(("reserved read - page 0, 0xa"));
00588     return (0xff);
00589     break;
00590 
00591   case 0xb:  // reserved
00592     BX_INFO(("reserved read - page 0, 0xb"));
00593     return (0xff);
00594     break;
00595     
00596   case 0xc:  // RSR
00597     return
00598        ((unsigned int)(BX_NE2K_THIS s.RSR.deferred    << 7u) |
00599             (unsigned int)(BX_NE2K_THIS s.RSR.rx_disabled << 6u) |
00600             (unsigned int)(BX_NE2K_THIS s.RSR.rx_mbit     << 5u) |
00601             (unsigned int)(BX_NE2K_THIS s.RSR.rx_missed   << 4u) |
00602             (unsigned int)(BX_NE2K_THIS s.RSR.fifo_or     << 3u) |
00603             (unsigned int)(BX_NE2K_THIS s.RSR.bad_falign  << 2u) |
00604             (unsigned int)(BX_NE2K_THIS s.RSR.bad_crc     << 1u) |
00605             (unsigned int)(BX_NE2K_THIS s.RSR.rx_ok));
00606     break;
00607     
00608   case 0xd:  // CNTR0
00609     return (BX_NE2K_THIS s.tallycnt_0);
00610     break;
00611 
00612   case 0xe:  // CNTR1
00613     return (BX_NE2K_THIS s.tallycnt_1);
00614     break;
00615 
00616   case 0xf:  // CNTR2
00617     return (BX_NE2K_THIS s.tallycnt_2);
00618     break;
00619 
00620   default:
00621     BX_PANIC("page 0 offset %04x out of range", (unsigned) offset);
00622   }
00623 
00624   return(0);
00625 }
00626 
00627 void
00628 bx_ne2k_c::page0_write(Bit32u offset, Bit32u value, unsigned io_len)
00629 {
00630   BX_DEBUG("page 0 write to port %04x, len=%u", (unsigned) offset,
00631            (unsigned) io_len);
00632 
00633   // It appears to be a common practice to use outw on page0 regs...
00634 
00635   // break up outw into two outb's
00636   if (io_len == 2) {
00637     page0_write(offset, (value & 0xff), 1);
00638     page0_write(offset + 1, ((value >> 8) & 0xff), 1);
00639     return;
00640   }
00641 
00642   switch (offset) {
00643   case 0x1:  // PSTART
00644     BX_NE2K_THIS s.page_start = value;
00645     break;
00646 
00647   case 0x2:  // PSTOP
00648         // BX_INFO(("Writing to PSTOP: %02x", value));
00649     BX_NE2K_THIS s.page_stop = value;
00650     break;
00651 
00652   case 0x3:  // BNRY
00653     BX_NE2K_THIS s.bound_ptr = value;
00654     break;
00655 
00656   case 0x4:  // TPSR
00657     BX_NE2K_THIS s.tx_page_start = value;
00658     break;
00659 
00660   case 0x5:  // TBCR0
00661     // Clear out low byte and re-insert
00662     BX_NE2K_THIS s.tx_bytes &= 0xff00;
00663     BX_NE2K_THIS s.tx_bytes |= (value & 0xff);
00664     break;
00665 
00666   case 0x6:  // TBCR1
00667     // Clear out high byte and re-insert
00668     BX_NE2K_THIS s.tx_bytes &= 0x00ff;
00669     BX_NE2K_THIS s.tx_bytes |= ((value & 0xff) << 8);
00670     break;
00671 
00672   case 0x7:  // ISR
00673     value &= 0x7f;  // clear RST bit - status-only bit
00674     // All other values are cleared iff the ISR bit is 1
00675     BX_NE2K_THIS s.ISR.pkt_rx    &= ~((bx_bool)((value & 0x01) == 0x01));
00676         BX_NE2K_THIS s.ISR.pkt_tx    &= ~((bx_bool)((value & 0x02) == 0x02));
00677     BX_NE2K_THIS s.ISR.rx_err    &= ~((bx_bool)((value & 0x04) == 0x04));
00678     BX_NE2K_THIS s.ISR.tx_err    &= ~((bx_bool)((value & 0x08) == 0x08));
00679     BX_NE2K_THIS s.ISR.overwrite &= ~((bx_bool)((value & 0x10) == 0x10));
00680     BX_NE2K_THIS s.ISR.cnt_oflow &= ~((bx_bool)((value & 0x20) == 0x20));
00681     BX_NE2K_THIS s.ISR.rdma_done &= ~((bx_bool)((value & 0x40) == 0x40));
00682     value = ((unsigned int)(BX_NE2K_THIS s.ISR.rdma_done << 6u) |
00683              (unsigned int)(BX_NE2K_THIS s.ISR.cnt_oflow << 5u) |
00684              (unsigned int)(BX_NE2K_THIS s.ISR.overwrite << 4u) |
00685              (unsigned int)(BX_NE2K_THIS s.ISR.tx_err    << 3u) |
00686              (unsigned int)(BX_NE2K_THIS s.ISR.rx_err    << 2u) |
00687              (unsigned int)(BX_NE2K_THIS s.ISR.pkt_tx    << 1u) |
00688              (unsigned int)(BX_NE2K_THIS s.ISR.pkt_rx));
00689     value &= ((unsigned int)(BX_NE2K_THIS s.IMR.rdma_inte  << 6u) |
00690               (unsigned int)(BX_NE2K_THIS s.IMR.cofl_inte  << 5u) |
00691               (unsigned int)(BX_NE2K_THIS s.IMR.overw_inte << 4u) |
00692               (unsigned int)(BX_NE2K_THIS s.IMR.txerr_inte << 3u) |
00693               (unsigned int)(BX_NE2K_THIS s.IMR.rxerr_inte << 2u) |
00694               (unsigned int)(BX_NE2K_THIS s.IMR.tx_inte    << 1u) |
00695               (unsigned int)(BX_NE2K_THIS s.IMR.rx_inte));
00696     if (value == 0)
00697           PIC_DeActivateIRQ((unsigned int)s.base_irq);
00698       //DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq);
00699     break;
00700 
00701   case 0x8:  // RSAR0
00702     // Clear out low byte and re-insert
00703     BX_NE2K_THIS s.remote_start &= 0xff00u;
00704     BX_NE2K_THIS s.remote_start |= (value & 0xffu);
00705     BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start;
00706     break;
00707 
00708   case 0x9:  // RSAR1
00709     // Clear out high byte and re-insert
00710     BX_NE2K_THIS s.remote_start &= 0x00ffu;
00711     BX_NE2K_THIS s.remote_start |= ((value & 0xffu) << 8u);
00712     BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start;
00713     break;
00714 
00715   case 0xa:  // RBCR0
00716     // Clear out low byte and re-insert
00717     BX_NE2K_THIS s.remote_bytes &= 0xff00u;
00718     BX_NE2K_THIS s.remote_bytes |= (value & 0xffu);
00719     break;
00720 
00721   case 0xb:  // RBCR1
00722     // Clear out high byte and re-insert
00723     BX_NE2K_THIS s.remote_bytes &= 0x00ffu;
00724     BX_NE2K_THIS s.remote_bytes |= ((value & 0xffu) << 8u);
00725     break;
00726 
00727   case 0xc:  // RCR
00728     // Check if the reserved bits are set
00729     if (value & 0xc0)
00730       BX_INFO(("RCR write, reserved bits set"));
00731 
00732     // Set all other bit-fields
00733     BX_NE2K_THIS s.RCR.errors_ok = ((value & 0x01u) == 0x01u);
00734     BX_NE2K_THIS s.RCR.runts_ok  = ((value & 0x02u) == 0x02u);
00735     BX_NE2K_THIS s.RCR.broadcast = ((value & 0x04u) == 0x04u);
00736     BX_NE2K_THIS s.RCR.multicast = ((value & 0x08u) == 0x08u);
00737     BX_NE2K_THIS s.RCR.promisc   = ((value & 0x10u) == 0x10u);
00738     BX_NE2K_THIS s.RCR.monitor   = ((value & 0x20u) == 0x20u);
00739 
00740     // Monitor bit is a little suspicious...
00741     if (value & 0x20)
00742       BX_INFO(("RCR write, monitor bit set!"));
00743     break;
00744 
00745   case 0xd:  // TCR
00746     // Check reserved bits
00747     if (value & 0xe0)
00748       BX_ERROR(("TCR write, reserved bits set"));
00749 
00750     // Test loop mode (not supported)
00751     if (value & 0x06) {
00752       BX_NE2K_THIS s.TCR.loop_cntl = (value & 0x6) >> 1;
00753       BX_INFO("TCR write, loop mode %d not supported", BX_NE2K_THIS s.TCR.loop_cntl);
00754     } else {
00755       BX_NE2K_THIS s.TCR.loop_cntl = 0;
00756     }
00757 
00758     // Inhibit-CRC not supported.
00759     if (value & 0x01)
00760       BX_PANIC(("TCR write, inhibit-CRC not supported"));
00761 
00762     // Auto-transmit disable very suspicious
00763     if (value & 0x08)
00764       BX_PANIC(("TCR write, auto transmit disable not supported"));
00765 
00766     // Allow collision-offset to be set, although not used
00767     BX_NE2K_THIS s.TCR.coll_prio = ((value & 0x08) == 0x08);
00768     break;
00769 
00770   case 0xe:  // DCR
00771     // the loopback mode is not suppported yet
00772     if (!(value & 0x08)) {
00773       BX_ERROR(("DCR write, loopback mode selected"));
00774     }
00775     // It is questionable to set longaddr and auto_rx, since they
00776     // aren't supported on the ne2000. Print a warning and continue
00777     if (value & 0x04)
00778       BX_INFO(("DCR write - LAS set ???"));
00779     if (value & 0x10)
00780       BX_INFO(("DCR write - AR set ???"));
00781 
00782     // Set other values.
00783     BX_NE2K_THIS s.DCR.wdsize   = ((value & 0x01) == 0x01);
00784     BX_NE2K_THIS s.DCR.endian   = ((value & 0x02) == 0x02);
00785     BX_NE2K_THIS s.DCR.longaddr = ((value & 0x04) == 0x04); // illegal ?
00786     BX_NE2K_THIS s.DCR.loop     = ((value & 0x08) == 0x08);
00787     BX_NE2K_THIS s.DCR.auto_rx  = ((value & 0x10) == 0x10); // also illegal ?
00788     BX_NE2K_THIS s.DCR.fifo_size = (value & 0x50) >> 5;
00789     break;
00790 
00791   case 0xf:  // IMR
00792     // Check for reserved bit
00793         if (value & 0x80)
00794       BX_PANIC(("IMR write, reserved bit set"));
00795 
00796     // Set other values
00797     BX_NE2K_THIS s.IMR.rx_inte    = ((value & 0x01) == 0x01);
00798     BX_NE2K_THIS s.IMR.tx_inte    = ((value & 0x02) == 0x02);
00799     BX_NE2K_THIS s.IMR.rxerr_inte = ((value & 0x04) == 0x04);
00800     BX_NE2K_THIS s.IMR.txerr_inte = ((value & 0x08) == 0x08);
00801     BX_NE2K_THIS s.IMR.overw_inte = ((value & 0x10) == 0x10);
00802     BX_NE2K_THIS s.IMR.cofl_inte  = ((value & 0x20) == 0x20);
00803     BX_NE2K_THIS s.IMR.rdma_inte  = ((value & 0x40) == 0x40);
00804         if(BX_NE2K_THIS s.ISR.pkt_tx && BX_NE2K_THIS s.IMR.tx_inte) {
00805           LOG_MSG("tx irq retrigger");
00806           PIC_ActivateIRQ((unsigned int)s.base_irq);
00807         }
00808     break;
00809   default:
00810     BX_PANIC("page 0 write, bad offset %0x", offset);
00811   }
00812 }
00813 
00814 
00815 //
00816 // page1_read/page1_write - These routines handle reads/writes to
00817 // the first page of the DS8390 register file
00818 //
00819 Bit32u
00820 bx_ne2k_c::page1_read(Bit32u offset, unsigned int io_len)
00821 {
00822   BX_DEBUG("page 1 read from port %04x, len=%u", (unsigned) offset,
00823            (unsigned) io_len);
00824   if (io_len > 1)
00825     BX_PANIC("bad length! page 1 read from port %04x, len=%u", (unsigned) offset,
00826              (unsigned) io_len);
00827 
00828   switch (offset) {
00829   case 0x1:  // PAR0-5
00830   case 0x2:
00831   case 0x3:
00832   case 0x4:
00833   case 0x5:
00834   case 0x6:
00835     return (BX_NE2K_THIS s.physaddr[offset - 1]);
00836     break;
00837 
00838   case 0x7:  // CURR
00839       BX_DEBUG("returning current page: %02x", (BX_NE2K_THIS s.curr_page));
00840     return (BX_NE2K_THIS s.curr_page);
00841 
00842   case 0x8:  // MAR0-7
00843   case 0x9:
00844   case 0xa:
00845   case 0xb:
00846   case 0xc:
00847   case 0xd:
00848   case 0xe:
00849   case 0xf:
00850     return (BX_NE2K_THIS s.mchash[offset - 8]);
00851     break;
00852 
00853   default:
00854     BX_PANIC("page 1 r offset %04x out of range", (unsigned) offset);
00855   }
00856 
00857   return (0);
00858 }
00859 
00860 void
00861 bx_ne2k_c::page1_write(Bit32u offset, Bit32u value, unsigned io_len)
00862 {
00863     (void)io_len;//UNUSED
00864   BX_DEBUG("page 1 w offset %04x", (unsigned) offset);
00865   switch (offset) {
00866   case 0x1:  // PAR0-5
00867   case 0x2:
00868   case 0x3:
00869   case 0x4:
00870   case 0x5:
00871   case 0x6:
00872     BX_NE2K_THIS s.physaddr[offset - 1] = value;
00873     break;
00874     
00875   case 0x7:  // CURR
00876     BX_NE2K_THIS s.curr_page = value;
00877     break;
00878 
00879   case 0x8:  // MAR0-7
00880   case 0x9:
00881   case 0xa:
00882   case 0xb:
00883   case 0xc:
00884   case 0xd:
00885   case 0xe:
00886   case 0xf:
00887     BX_NE2K_THIS s.mchash[offset - 8] = value;
00888     break;
00889 
00890   default:
00891     BX_PANIC("page 1 w offset %04x out of range", (unsigned) offset);
00892   }  
00893 }
00894 
00895 
00896 //
00897 // page2_read/page2_write - These routines handle reads/writes to
00898 // the second page of the DS8390 register file
00899 //
00900 Bit32u
00901 bx_ne2k_c::page2_read(Bit32u offset, unsigned int io_len)
00902 {
00903   BX_DEBUG("page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len);
00904 
00905   if (io_len > 1)
00906     BX_PANIC("bad length!  page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len);
00907 
00908   switch (offset) {
00909   case 0x1:  // PSTART
00910     return (BX_NE2K_THIS s.page_start);
00911     break;
00912 
00913   case 0x2:  // PSTOP
00914     return (BX_NE2K_THIS s.page_stop);
00915     break;
00916 
00917   case 0x3:  // Remote Next-packet pointer
00918     return (BX_NE2K_THIS s.rempkt_ptr);
00919     break;
00920 
00921   case 0x4:  // TPSR
00922     return (BX_NE2K_THIS s.tx_page_start);
00923     break;
00924 
00925   case 0x5:  // Local Next-packet pointer
00926     return (BX_NE2K_THIS s.localpkt_ptr);
00927     break;
00928 
00929   case 0x6:  // Address counter (upper)
00930     return (unsigned int)(BX_NE2K_THIS s.address_cnt >> 8u);
00931     break;
00932 
00933   case 0x7:  // Address counter (lower)
00934     return (unsigned int)(BX_NE2K_THIS s.address_cnt & 0xff);
00935     break;
00936 
00937   case 0x8:  // Reserved
00938   case 0x9:
00939   case 0xa:
00940   case 0xb:
00941     BX_ERROR("reserved read - page 2, 0x%02x", (unsigned) offset);
00942     return (0xff);
00943     break;
00944 
00945   case 0xc:  // RCR
00946     return
00947        ((unsigned int)(BX_NE2K_THIS s.RCR.monitor   << 5u) |
00948             (unsigned int)(BX_NE2K_THIS s.RCR.promisc   << 4u) |
00949             (unsigned int)(BX_NE2K_THIS s.RCR.multicast << 3u) |
00950             (unsigned int)(BX_NE2K_THIS s.RCR.broadcast << 2u) |
00951             (unsigned int)(BX_NE2K_THIS s.RCR.runts_ok  << 1u) |
00952             (unsigned int)(BX_NE2K_THIS s.RCR.errors_ok));
00953     break;
00954 
00955   case 0xd:  // TCR
00956     return
00957        ((unsigned int)(BX_NE2K_THIS s.TCR.coll_prio         << 4u) |
00958             (unsigned int)(BX_NE2K_THIS s.TCR.ext_stoptx        << 3u) |
00959            ((unsigned int)(BX_NE2K_THIS s.TCR.loop_cntl & 0x3u) << 1u) |
00960             (unsigned int)(BX_NE2K_THIS s.TCR.crc_disable));
00961     break;
00962 
00963   case 0xe:  // DCR
00964     return
00965       (((unsigned int)(BX_NE2K_THIS s.DCR.fifo_size & 0x3) << 5u) |
00966             (unsigned int)(BX_NE2K_THIS s.DCR.auto_rx          << 4u) |
00967             (unsigned int)(BX_NE2K_THIS s.DCR.loop             << 3u) |
00968             (unsigned int)(BX_NE2K_THIS s.DCR.longaddr         << 2u) |
00969             (unsigned int)(BX_NE2K_THIS s.DCR.endian           << 1u) |
00970             (unsigned int)(BX_NE2K_THIS s.DCR.wdsize));
00971     break;
00972 
00973   case 0xf:  // IMR
00974     return
00975        ((unsigned int)(BX_NE2K_THIS s.IMR.rdma_inte  << 6u) |
00976             (unsigned int)(BX_NE2K_THIS s.IMR.cofl_inte  << 5u) |
00977             (unsigned int)(BX_NE2K_THIS s.IMR.overw_inte << 4u) |
00978             (unsigned int)(BX_NE2K_THIS s.IMR.txerr_inte << 3u) |
00979             (unsigned int)(BX_NE2K_THIS s.IMR.rxerr_inte << 2u) |
00980             (unsigned int)(BX_NE2K_THIS s.IMR.tx_inte    << 1u) |
00981            (unsigned int) (BX_NE2K_THIS s.IMR.rx_inte));
00982     break;
00983 
00984   default:
00985     BX_PANIC("page 2 offset %04x out of range", (unsigned) offset);
00986   }
00987 
00988   return (0);
00989 }
00990 
00991 void
00992 bx_ne2k_c::page2_write(Bit32u offset, Bit32u value, unsigned io_len)
00993 {
00994     (void)io_len;//UNUSED
00995   // Maybe all writes here should be BX_PANIC()'d, since they
00996   // affect internal operation, but let them through for now
00997   // and print a warning.
00998   if (offset != 0)
00999     BX_ERROR(("page 2 write ?"));
01000 
01001   switch (offset) {
01002   case 0x1:  // CLDA0
01003     // Clear out low byte and re-insert
01004     BX_NE2K_THIS s.local_dma &= 0xff00;
01005     BX_NE2K_THIS s.local_dma |= (value & 0xff);
01006     break;
01007 
01008   case 0x2:  // CLDA1
01009     // Clear out high byte and re-insert
01010     BX_NE2K_THIS s.local_dma &= 0x00ff;
01011     BX_NE2K_THIS s.local_dma |= ((value & 0xff) << 8u);
01012     break;
01013 
01014   case 0x3:  // Remote Next-pkt pointer
01015     BX_NE2K_THIS s.rempkt_ptr = value;
01016     break;
01017 
01018   case 0x4:
01019     BX_PANIC(("page 2 write to reserved offset 4"));
01020     break;
01021 
01022   case 0x5:  // Local Next-packet pointer
01023     BX_NE2K_THIS s.localpkt_ptr = value;
01024     break;
01025 
01026   case 0x6:  // Address counter (upper)
01027     // Clear out high byte and re-insert
01028     BX_NE2K_THIS s.address_cnt &= 0x00ff;
01029     BX_NE2K_THIS s.address_cnt |= ((value & 0xff) << 8);
01030     break;
01031 
01032   case 0x7:  // Address counter (lower)
01033     // Clear out low byte and re-insert
01034     BX_NE2K_THIS s.address_cnt &= 0xff00;
01035     BX_NE2K_THIS s.address_cnt |= (value & 0xff);
01036     break;
01037 
01038   case 0x8:
01039   case 0x9:
01040   case 0xa:
01041   case 0xb:
01042   case 0xc:
01043   case 0xd:
01044   case 0xe:
01045   case 0xf:
01046     BX_PANIC("page 2 write to reserved offset %0x", offset);
01047     break;
01048    
01049   default:
01050     BX_PANIC("page 2 write, illegal offset %0x", offset);
01051     break;
01052   }
01053 }
01054   
01055 //
01056 // page3_read/page3_write - writes to this page are illegal
01057 //
01058 Bit32u
01059 bx_ne2k_c::page3_read(Bit32u offset, unsigned int io_len)
01060 {
01061     (void)offset;//UNUSED
01062     (void)io_len;//UNUSED
01063   BX_PANIC(("page 3 read attempted"));
01064   return (0);
01065 }
01066 
01067 void
01068 bx_ne2k_c::page3_write(Bit32u offset, Bit32u value, unsigned io_len)
01069 {
01070     (void)value;//UNUSED
01071     (void)offset;//UNUSED
01072     (void)io_len;//UNUSED
01073   BX_PANIC(("page 3 write attempted"));
01074 }
01075 
01076 //
01077 // tx_timer_handler/tx_timer
01078 //
01079 void
01080 bx_ne2k_c::tx_timer_handler(void *this_ptr)
01081 {
01082   bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
01083 
01084   class_ptr->tx_timer();
01085 }
01086 
01087 void
01088 bx_ne2k_c::tx_timer(void)
01089 {
01090   BX_DEBUG(("tx_timer"));
01091   BX_NE2K_THIS s.TSR.tx_ok = 1;
01092   // Generate an interrupt if not masked and not one in progress
01093   if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) {
01094                 //LOG_MSG("tx complete interrupt");
01095           PIC_ActivateIRQ((unsigned int)s.base_irq);
01096     //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
01097   } //else        LOG_MSG("no tx complete interrupt");
01098   BX_NE2K_THIS s.ISR.pkt_tx = 1;
01099   BX_NE2K_THIS s.tx_timer_active = 0;
01100 }
01101 
01102 
01103 //
01104 // read_handler/read - i/o 'catcher' function called from BOCHS
01105 // mainline when the CPU attempts a read in the i/o space registered
01106 // by this ne2000 instance
01107 //
01108 Bit32u bx_ne2k_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
01109 {
01110 #if !BX_USE_NE2K_SMF
01111   bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
01112 
01113   return( class_ptr->read(address, io_len) );
01114 }
01115 
01116 Bit32u bx_ne2k_c::read(Bit32u address, unsigned io_len)
01117 {
01118 #else
01119   UNUSED(this_ptr);
01120 #endif  // !BX_USE_NE2K_SMF
01121   BX_DEBUG("read addr %x, len %d", address, io_len);
01122   Bit32u retval = 0;
01123   unsigned int offset = (unsigned int)address - (unsigned int)(BX_NE2K_THIS s.base_address);
01124 
01125   if (offset >= 0x10) {
01126     retval = asic_read(offset - 0x10, io_len);
01127   } else if (offset == 0x00) {
01128     retval = read_cr();
01129   } else {
01130     switch (BX_NE2K_THIS s.CR.pgsel) {
01131     case 0x00:
01132       retval = page0_read(offset, io_len);
01133       break;
01134 
01135     case 0x01:
01136       retval = page1_read(offset, io_len);
01137       break;
01138 
01139     case 0x02:
01140       retval = page2_read(offset, io_len);
01141       break;
01142 
01143     case 0x03:
01144       retval = page3_read(offset, io_len);
01145       break;
01146 
01147     default:
01148       BX_PANIC("ne2K: unknown value of pgsel in read - %d",
01149                BX_NE2K_THIS s.CR.pgsel);
01150     }
01151   }
01152 
01153   return (retval);
01154 }
01155 
01156 //
01157 // write_handler/write - i/o 'catcher' function called from BOCHS
01158 // mainline when the CPU attempts a write in the i/o space registered
01159 // by this ne2000 instance
01160 //
01161 void
01162 bx_ne2k_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, 
01163                          unsigned io_len)
01164 {
01165 #if !BX_USE_NE2K_SMF
01166   bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
01167   
01168   class_ptr->write(address, value, io_len);
01169 }
01170 
01171 void
01172 bx_ne2k_c::write(Bit32u address, Bit32u value, unsigned io_len)
01173 {
01174 #else
01175   UNUSED(this_ptr);
01176 #endif  // !BX_USE_NE2K_SMF
01177   BX_DEBUG("write with length %d", io_len);
01178   unsigned int offset = (unsigned int)address - (unsigned int)(BX_NE2K_THIS s.base_address);
01179 
01180   //
01181   // The high 16 bytes of i/o space are for the ne2000 asic -
01182   //  the low 16 bytes are for the DS8390, with the current
01183   //  page being selected by the PS0,PS1 registers in the
01184   //  command register
01185   //
01186   if (offset >= 0x10) {
01187     asic_write(offset - 0x10, value, io_len);
01188         } else if (offset == 0x00) {
01189     write_cr(value);
01190   } else {
01191     switch (BX_NE2K_THIS s.CR.pgsel) {
01192     case 0x00:
01193       page0_write(offset, value, io_len);
01194       break;
01195 
01196     case 0x01:
01197       page1_write(offset, value, io_len);
01198       break;
01199 
01200     case 0x02:
01201       page2_write(offset, value, io_len);
01202       break;
01203 
01204     case 0x03:
01205       page3_write(offset, value, io_len);
01206       break;
01207 
01208     default:
01209       BX_PANIC("ne2K: unknown value of pgsel in write - %d",
01210                BX_NE2K_THIS s.CR.pgsel);
01211     }
01212   }
01213 }
01214 
01215 
01216 /*
01217  * mcast_index() - return the 6-bit index into the multicast
01218  * table. Stolen unashamedly from FreeBSD's if_ed.c
01219  */
01220 unsigned
01221 bx_ne2k_c::mcast_index(const void *dst)
01222 {
01223 #define POLYNOMIAL 0x04c11db6
01224   unsigned long crc = 0xffffffffL;
01225   int carry, i, j;
01226   unsigned char b;
01227   unsigned char *ep = (unsigned char *) dst;
01228 
01229   for (i = 6; --i >= 0;) {
01230       b = *ep++;
01231       for (j = 8; --j >= 0;) {
01232           carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
01233           crc <<= 1;
01234           b >>= 1;
01235           if (carry)
01236               crc = ((crc ^ POLYNOMIAL) | (unsigned int)carry);
01237       }
01238   }
01239 
01240   return (uint32_t)((crc & 0xfffffffful) >> 26ul); /* WARNING: Caller directly uses our 6-bit return as index. If not truncated, will cause a segfault */
01241 #undef POLYNOMIAL
01242 }
01243 
01244 /*
01245  * Callback from the eth system driver when a frame has arrived
01246  */
01247 /*
01248 void
01249 bx_ne2k_c::rx_handler(void *arg, const void *buf, unsigned len)
01250 {
01251     // BX_DEBUG(("rx_handler with length %d", len));
01252   bx_ne2k_c *class_ptr = (bx_ne2k_c *) arg;
01253   if(
01254   class_ptr->rx_frame(buf, len);
01255 }
01256 */
01257 /*
01258  * rx_frame() - called by the platform-specific code when an
01259  * ethernet frame has been received. The destination address
01260  * is tested to see if it should be accepted, and if the
01261  * rx ring has enough room, it is copied into it and
01262  * the receive process is updated
01263  */
01264 void
01265 bx_ne2k_c::rx_frame(const void *buf, unsigned io_len)
01266 {
01267   int pages;
01268   int avail;
01269   unsigned idx;
01270 //  int wrapped;
01271   int nextpage;
01272   unsigned char pkthdr[4];
01273   unsigned char *pktbuf = (unsigned char *) buf;
01274   unsigned char *startptr;
01275   static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
01276 
01277   if(io_len != 60) {
01278         BX_DEBUG("rx_frame with length %d", io_len);
01279   }
01280 
01281         //LOG_MSG("stop=%d, pagestart=%x, dcr_loop=%x, tcr_loopcntl=%x",
01282         //      BX_NE2K_THIS s.CR.stop, BX_NE2K_THIS s.page_start,
01283         //      BX_NE2K_THIS s.DCR.loop, BX_NE2K_THIS s.TCR.loop_cntl);
01284   if ((BX_NE2K_THIS s.CR.stop != 0) ||
01285       (BX_NE2K_THIS s.page_start == 0) /*||
01286       ((BX_NE2K_THIS s.DCR.loop == 0) &&
01287        (BX_NE2K_THIS s.TCR.loop_cntl != 0))*/) {
01288     return;
01289   }
01290 
01291   // Add the pkt header + CRC to the length, and work
01292   // out how many 256-byte pages the frame would occupy
01293   pages = (int)((io_len + 4u + 4u + 255u)/256u);
01294 
01295   if (BX_NE2K_THIS s.curr_page < BX_NE2K_THIS s.bound_ptr) {
01296     avail = BX_NE2K_THIS s.bound_ptr - BX_NE2K_THIS s.curr_page;    
01297   } else {
01298     avail = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start) -
01299       (BX_NE2K_THIS s.curr_page - BX_NE2K_THIS s.bound_ptr);
01300 //    wrapped = 1;
01301   }
01302 
01303   // Avoid getting into a buffer overflow condition by not attempting
01304   // to do partial receives. The emulation to handle this condition
01305   // seems particularly painful.
01306   if ((avail < pages) 
01307 #if BX_NE2K_NEVER_FULL_RING
01308       || (avail == pages)
01309 #endif
01310       ) {
01311         BX_DEBUG("no space");
01312     return;
01313   }
01314 
01315   if ((io_len < 40/*60*/) && !BX_NE2K_THIS s.RCR.runts_ok) {
01316     BX_DEBUG("rejected small packet, length %d", io_len);
01317     return;
01318   }
01319   // some computers don't care...
01320   if (io_len < 60) io_len=60;
01321 
01322   // Do address filtering if not in promiscuous mode
01323   if (! BX_NE2K_THIS s.RCR.promisc) {
01324     if (!memcmp(buf, bcast_addr, 6)) {
01325       if (!BX_NE2K_THIS s.RCR.broadcast) {
01326         return;
01327       }
01328     } else if (pktbuf[0] & 0x01) {
01329         if (! BX_NE2K_THIS s.RCR.multicast) {
01330             return;
01331         }
01332       idx = mcast_index(buf);
01333       if (!(BX_NE2K_THIS s.mchash[idx >> 3] & (1 << (idx & 0x7)))) {
01334         return;
01335       }
01336     } else if (0 != memcmp(buf, BX_NE2K_THIS s.physaddr, 6)) {
01337       return;
01338     }
01339   } else {
01340       BX_DEBUG(("rx_frame promiscuous receive"));
01341   }
01342 
01343     BX_INFO("rx_frame %d to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x",
01344            io_len,
01345            pktbuf[0], pktbuf[1], pktbuf[2], pktbuf[3], pktbuf[4], pktbuf[5],
01346            pktbuf[6], pktbuf[7], pktbuf[8], pktbuf[9], pktbuf[10], pktbuf[11]);
01347 
01348   nextpage = BX_NE2K_THIS s.curr_page + pages;
01349   if (nextpage >= BX_NE2K_THIS s.page_stop) {
01350     nextpage -= BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start;
01351   }
01352 
01353   // Setup packet header
01354   pkthdr[0] = 0;        // rx status - old behavior
01355   pkthdr[0] = 1;        // Probably better to set it all the time
01356                         // rather than set it to 0, which is clearly wrong.
01357   if (pktbuf[0] & 0x01) {
01358     pkthdr[0] |= 0x20;  // rx status += multicast packet
01359   }
01360   pkthdr[1] = nextpage; // ptr to next packet
01361   pkthdr[2] = (io_len + 4) & 0xff;      // length-low
01362   pkthdr[3] = (io_len + 4) >> 8;        // length-hi
01363 
01364   // copy into buffer, update curpage, and signal interrupt if config'd
01365   startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.curr_page * 256 -
01366                                BX_NE2K_MEMSTART];
01367   if ((nextpage > BX_NE2K_THIS s.curr_page) ||
01368       ((BX_NE2K_THIS s.curr_page + pages) == BX_NE2K_THIS s.page_stop)) {
01369     memcpy(startptr, pkthdr, 4);
01370     memcpy(startptr + 4, buf, io_len);
01371     BX_NE2K_THIS s.curr_page = nextpage;
01372   } else {
01373     unsigned int endbytes = (unsigned int)(BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.curr_page) 
01374       * 256u;
01375     memcpy(startptr, pkthdr, 4);
01376     memcpy(startptr + 4, buf, (size_t)(endbytes - 4u));
01377     startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.page_start * 256u -
01378                                  BX_NE2K_MEMSTART];
01379     memcpy(startptr, (void *)(pktbuf + endbytes - 4u),
01380            (size_t)(io_len - endbytes + 8u));
01381     BX_NE2K_THIS s.curr_page = nextpage;
01382   }
01383   
01384   BX_NE2K_THIS s.RSR.rx_ok = 1;
01385   if (pktbuf[0] & 0x80) {
01386     BX_NE2K_THIS s.RSR.rx_mbit = 1;
01387   }
01388 
01389   BX_NE2K_THIS s.ISR.pkt_rx = 1;
01390 
01391   if (BX_NE2K_THIS s.IMR.rx_inte) {
01392         //LOG_MSG("packet rx interrupt");
01393           PIC_ActivateIRQ((unsigned int)s.base_irq);
01394     //DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
01395   } //else LOG_MSG("no packet rx interrupt");
01396 
01397 }
01398 
01399 //Bit8u macaddr[6] = { 0xAC, 0xDE, 0x48, 0x8E, 0x89, 0x19 };
01400 
01401 Bitu dosbox_read(Bitu port, Bitu len) {
01402         Bitu retval = theNE2kDevice->read((Bit32u)port,(unsigned int)len);
01403         //LOG_MSG("ne2k rd port %x val %4x len %d page %d, CS:IP %8x:%8x",
01404         //      port, retval, len, theNE2kDevice->s.CR.pgsel,SegValue(cs),reg_eip);
01405         return retval;
01406 }
01407 void dosbox_write(Bitu port, Bitu val, Bitu len) {
01408         //LOG_MSG("ne2k wr port %x val %4x len %d page %d, CS:IP %8x:%8x",
01409         //      port, val, len,theNE2kDevice->s.CR.pgsel,SegValue(cs),reg_eip);
01410         theNE2kDevice->write((Bit32u)port, (Bit32u)val, (unsigned int)len);
01411 }
01412 
01413 void bx_ne2k_c::init()
01414 {
01415   //BX_DEBUG(("Init $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $"));
01416 
01417   // Read in values from config file
01418   //BX_NE2K_THIS s.base_address = 0x300;
01419   //BX_NE2K_THIS s.base_irq     = 3;
01420   /*
01421   if (BX_NE2K_THIS s.tx_timer_index == BX_NULL_TIMER_HANDLE) {
01422     BX_NE2K_THIS s.tx_timer_index =
01423       bx_pc_system.register_timer(this, tx_timer_handler, 0,
01424                                   0,0, "ne2k"); // one-shot, inactive
01425   }*/
01426   // Register the IRQ and i/o port addresses
01427   //DEV_register_irq(BX_NE2K_THIS s.base_irq, "NE2000 ethernet NIC");
01428 
01429    //DEV_register_ioread_handler(this, read_handler, addr, "ne2000 NIC", 3);
01430    //DEV_register_iowrite_handler(this, write_handler, addr, "ne2000 NIC", 3);
01431 
01432 
01433   BX_INFO("port 0x%x/32 irq %d mac %02x:%02x:%02x:%02x:%02x:%02x",
01434            (unsigned int)(BX_NE2K_THIS s.base_address),
01435            (int)(BX_NE2K_THIS s.base_irq),
01436            BX_NE2K_THIS s.physaddr[0],
01437            BX_NE2K_THIS s.physaddr[1],
01438            BX_NE2K_THIS s.physaddr[2],
01439            BX_NE2K_THIS s.physaddr[3],
01440            BX_NE2K_THIS s.physaddr[4],
01441            BX_NE2K_THIS s.physaddr[5]);
01442 
01443   // Initialise the mac address area by doubling the physical address
01444   BX_NE2K_THIS s.macaddr[0]  = BX_NE2K_THIS s.physaddr[0];
01445   BX_NE2K_THIS s.macaddr[1]  = BX_NE2K_THIS s.physaddr[0];
01446   BX_NE2K_THIS s.macaddr[2]  = BX_NE2K_THIS s.physaddr[1];
01447   BX_NE2K_THIS s.macaddr[3]  = BX_NE2K_THIS s.physaddr[1];
01448   BX_NE2K_THIS s.macaddr[4]  = BX_NE2K_THIS s.physaddr[2];
01449   BX_NE2K_THIS s.macaddr[5]  = BX_NE2K_THIS s.physaddr[2];
01450   BX_NE2K_THIS s.macaddr[6]  = BX_NE2K_THIS s.physaddr[3];
01451   BX_NE2K_THIS s.macaddr[7]  = BX_NE2K_THIS s.physaddr[3];
01452   BX_NE2K_THIS s.macaddr[8]  = BX_NE2K_THIS s.physaddr[4];
01453   BX_NE2K_THIS s.macaddr[9]  = BX_NE2K_THIS s.physaddr[4];
01454   BX_NE2K_THIS s.macaddr[10] = BX_NE2K_THIS s.physaddr[5];
01455   BX_NE2K_THIS s.macaddr[11] = BX_NE2K_THIS s.physaddr[5];
01456     
01457   // ne2k signature
01458   for (Bitu i = 12; i < 32; i++) 
01459     BX_NE2K_THIS s.macaddr[i] = 0x57;
01460     
01461   // Bring the register state into power-up state
01462   reset(BX_RESET_HARDWARE);
01463 }
01464 
01465 static void NE2000_TX_Event(Bitu val) {
01466     (void)val;//UNUSED
01467         theNE2kDevice->tx_timer();
01468 }
01469 
01470 static void NE2000_Poller(void) {
01471         int res;
01472         struct pcap_pkthdr *header;
01473         u_char *pkt_data;
01474 //#if 0
01475         while((res = pcap_next_ex( adhandle, &header, (const u_char **)&pkt_data)) > 0) {
01476                 //LOG_MSG("NE2000: Received %d bytes", header->len);
01477                 
01478                 // don't receive in loopback modes
01479                 if((theNE2kDevice->s.DCR.loop == 0) || (theNE2kDevice->s.TCR.loop_cntl != 0))
01480                         return;
01481                 theNE2kDevice->rx_frame(pkt_data, header->len);
01482         }
01483 //#endif
01484 }
01485 #ifdef WIN32
01486 #include <windows.h>
01487 #endif
01488 
01489 class NE2K: public Module_base {
01490 private:
01491         // Data
01492         IO_ReadHandleObject ReadHandler8[0x20];
01493         IO_WriteHandleObject WriteHandler8[0x20];
01494         IO_ReadHandleObject ReadHandler16[0x10];
01495         IO_WriteHandleObject WriteHandler16[0x10];
01496 
01497 public:
01498         bool load_success;
01499         NE2K(Section* configuration):Module_base(configuration) {
01500                 Section_prop * section=static_cast<Section_prop *>(configuration);
01501 
01502                 load_success = true;
01503                 // enabled?
01504 
01505                 if(!section->Get_bool("ne2000")) {
01506                         load_success = false;
01507                         return;
01508                 }
01509 
01510 #ifdef WIN32
01511 /*              
01512                 int (*PacketSendPacket)(pcap_t *, const u_char *, int);
01513                 void (*PacketClose)(pcap_t *);
01514                 void (*PacketFreealldevs)(pcap_if_t *);
01515                 pcap_t* (*PacketOpen)(char const *,int,int,int,struct pcap_rmtauth *,char *);
01516                 int (*PacketNextEx)(pcap_t *, struct pcap_pkthdr **, const u_char **);
01517                 int (*PacketFindALlDevsEx)(char *, struct pcap_rmtauth *, pcap_if_t **, char *);
01518 */
01519                 // init the library
01520                 HINSTANCE pcapinst;
01521                 pcapinst = LoadLibrary("WPCAP.DLL");
01522                 if(pcapinst==NULL) {
01523                         LOG_MSG("WinPcap has to be installed for the NE2000 to work.");
01524                         load_success = false;
01525                         return;
01526                 }
01527                 FARPROC psp;
01528                 
01529                 psp = GetProcAddress(pcapinst,"pcap_sendpacket");
01530                 if(!PacketSendPacket) PacketSendPacket =
01531                         (int (__cdecl *)(pcap_t *,const u_char *,int))psp;
01532                 
01533                 psp = GetProcAddress(pcapinst,"pcap_close");
01534                 if(!PacketClose) PacketClose =
01535                         (void (__cdecl *)(pcap_t *)) psp;
01536                 
01537                 psp = GetProcAddress(pcapinst,"pcap_freealldevs");
01538                 if(!PacketFreealldevs) PacketFreealldevs =
01539                         (void (__cdecl *)(pcap_if_t *)) psp;
01540 
01541                 psp = GetProcAddress(pcapinst,"pcap_open");
01542                 if(!PacketOpen) PacketOpen =
01543                         (pcap_t* (__cdecl *)(char const *,int,int,int,struct pcap_rmtauth *,char *)) psp;
01544 
01545                 psp = GetProcAddress(pcapinst,"pcap_next_ex");
01546                 if(!PacketNextEx) PacketNextEx = 
01547                         (int (__cdecl *)(pcap_t *, struct pcap_pkthdr **, const u_char **)) psp;
01548 
01549                 psp = GetProcAddress(pcapinst,"pcap_findalldevs_ex");
01550                 if(!PacketFindALlDevsEx) PacketFindALlDevsEx =
01551                         (int (__cdecl *)(char *, struct pcap_rmtauth *, pcap_if_t **, char *)) psp;
01552 
01553                 if(PacketFindALlDevsEx==0 || PacketNextEx==0 || PacketOpen==0 || 
01554                         PacketFreealldevs==0 || PacketClose==0 || PacketSendPacket==0) {
01555                         LOG_MSG("Wrong WinPcap version or something");
01556                         load_success = false;
01557                         return;
01558                 }
01559 
01560 #endif
01561 
01562                 // get irq and base
01563                 Bitu irq = (Bitu)section->Get_int("nicirq");
01564                 if(!(irq==3 || irq==4  || irq==5  || irq==6 ||irq==7 ||
01565                         irq==9 || irq==10 || irq==11 || irq==12 ||irq==14 ||irq==15)) {
01566                         irq=3;
01567                 }
01568                 Bitu base = (Bitu)section->Get_hex("nicbase");
01569                 if(!(base==0x260||base==0x280||base==0x300||base==0x320||base==0x340||base==0x380)) {
01570                         base=0x300;
01571                 }
01572 
01573         LOG_MSG("NE2000: Base=0x%x irq=%u",(unsigned int)base,(unsigned int)irq);
01574 
01575                 // mac address
01576                 const char* macstring=section->Get_string("macaddr");
01577                 unsigned int macint[6];
01578                 Bit8u mac[6];
01579                 if(sscanf(macstring,"%02x:%02x:%02x:%02x:%02x:%02x",
01580                         &macint[0],&macint[1],&macint[2],&macint[3],&macint[4],&macint[5]) != 6) {
01581                         mac[0]=0xac;mac[1]=0xde;mac[2]=0x48;
01582                         mac[3]=0x88;mac[4]=0xbb;mac[5]=0xaa;
01583                 } else {
01584                         mac[0]=macint[0]; mac[1]=macint[1];
01585                         mac[2]=macint[2]; mac[3]=macint[3];
01586                         mac[4]=macint[4]; mac[5]=macint[5];
01587                 }
01588 
01589                 // find out which pcap device to use
01590                 const char* realnicstring=section->Get_string("realnic");
01591                 pcap_if_t *alldevs;
01592                 pcap_if_t *currentdev = NULL;
01593                 char errbuf[PCAP_ERRBUF_SIZE];
01594                 unsigned int userdev;
01595 #ifdef WIN32
01596                 if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
01597 #else
01598                 if (pcap_findalldevs(&alldevs, errbuf) == -1)
01599 #endif
01600                 {
01601                         LOG_MSG("Cannot enumerate network interfaces: %s\n", errbuf);
01602                         load_success = false;
01603                         return;
01604                 }
01605                 if (!strcasecmp(realnicstring,"list")) {
01606                         // print list and quit
01607                         Bitu i = 0;
01608                         LOG_MSG("\nNetwork Interface List \n-----------------------------------");
01609                         for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
01610                                 const char* desc = "no description"; 
01611                                 if(currentdev->description) desc=currentdev->description;
01612                                 i++;
01613                                 LOG_MSG("%2d. %s\n    (%s)\n",(int)i,currentdev->name,desc);
01614                         }
01615                         pcap_freealldevs(alldevs);
01616                         load_success = false;
01617                         return;
01618                 } else if(1==sscanf(realnicstring,"%u",&userdev)) {
01619                         // user passed us a number
01620                         Bitu i = 0;
01621                         currentdev=alldevs;
01622                         while(currentdev!=NULL) {
01623                                 i++;
01624                                 if(i==userdev) break;
01625                                 else currentdev=currentdev->next;
01626                         }
01627                 } else {
01628                         // user might have passed a piece of name
01629                         for(currentdev=alldevs; currentdev!=NULL; currentdev=currentdev->next) {
01630                                 if(strstr(currentdev->name,realnicstring)) {
01631                                         break;
01632                                 }else if(currentdev->description!=NULL &&
01633                                         strstr(currentdev->description,realnicstring)) {
01634                                         break;
01635                                 }
01636                         }
01637                 }
01638 
01639                 if(currentdev==NULL) {
01640                         LOG_MSG("Unable to find network interface - check realnic parameter\n");
01641                         load_success = false;
01642                         pcap_freealldevs(alldevs);
01643                         return;
01644                 }
01645                 // print out which interface we are going to use
01646         const char* desc = "no description"; 
01647                 if(currentdev->description) desc=currentdev->description;
01648                 LOG_MSG("Using Network interface:\n%s\n(%s)\n",currentdev->name,desc);
01649                 
01650                 // attempt to open it
01651 #ifdef WIN32
01652                 if ( (adhandle= pcap_open(
01653                         currentdev->name, // name of the device
01654             65536,            // portion of the packet to capture
01655                               // 65536 = whole packet 
01656             PCAP_OPENFLAG_PROMISCUOUS,    // promiscuous mode
01657             -1,             // read timeout
01658             NULL,             // authentication on the remote machine
01659             errbuf            // error buffer
01660             ) ) == NULL)
01661 #else
01662                 /*pcap_t *pcap_open_live(const char *device, int snaplen,
01663                int promisc, int to_ms, char *errbuf)*/
01664                 if ( (adhandle= pcap_open_live(
01665                         currentdev->name, // name of the device
01666             65536,            // portion of the packet to capture
01667                               // 65536 = whole packet 
01668             true,    // promiscuous mode
01669             -1,             // read timeout
01670             errbuf            // error buffer
01671             ) ) == NULL)
01672 
01673 #endif        
01674         {
01675                                 LOG_MSG("\nUnable to open the interface: %s.", errbuf);
01676                 pcap_freealldevs(alldevs);
01677                         load_success = false;
01678                         return;
01679                 }
01680                 pcap_freealldevs(alldevs);
01681 #ifndef WIN32
01682                 pcap_setnonblock(adhandle,1,errbuf);
01683 #endif
01684                 // create the bochs NIC class
01685                 theNE2kDevice = new bx_ne2k_c ();
01686                 memcpy(theNE2kDevice->s.physaddr, mac, 6);
01687 
01688                 theNE2kDevice->s.base_address=(Bit32u)base;
01689                 theNE2kDevice->s.base_irq=(int)irq;
01690 
01691                 theNE2kDevice->init();
01692 
01693                 // install I/O-handlers and timer
01694                 for(Bitu i = 0; i < 0x20; i++) {
01695                         ReadHandler8[i].Install((i+theNE2kDevice->s.base_address),
01696                                 dosbox_read,IO_MB|IO_MW);
01697                         WriteHandler8[i].Install((i+theNE2kDevice->s.base_address),
01698                                 dosbox_write,IO_MB|IO_MW);
01699                 }
01700                 TIMER_AddTickHandler(NE2000_Poller);
01701         }       
01702         
01703         ~NE2K() {
01704                 if(adhandle) pcap_close(adhandle);
01705                 adhandle=0;
01706                 if(theNE2kDevice != 0) delete theNE2kDevice;
01707                 theNE2kDevice=0;
01708                 TIMER_DelTickHandler(NE2000_Poller);
01709                 PIC_RemoveEvents(NE2000_TX_Event);
01710         }       
01711 };
01712 
01713 static NE2K* test = NULL;
01714 
01715 void NE2K_ShutDown(Section* sec) {
01716     (void)sec;//UNUSED
01717         if (test) {
01718         delete test;    
01719         test = NULL;
01720     }
01721 }
01722 
01723 void NE2K_OnReset(Section* sec) {
01724     (void)sec;//UNUSED
01725         if (test == NULL && !IS_PC98_ARCH) {
01726                 LOG(LOG_MISC,LOG_DEBUG)("Allocating NE2000 emulation");
01727                 test = new NE2K(control->GetSection("ne2000"));
01728 
01729                 if (!test->load_success) {
01730                         LOG(LOG_MISC,LOG_DEBUG)("Sorry, NE2000 allocation failed to load");
01731                         delete test;
01732                         test = NULL;
01733                 }
01734         }
01735 }
01736 
01737 void NE2K_Init() {
01738         LOG(LOG_MISC,LOG_DEBUG)("Initializing NE2000 network card emulation");
01739 
01740         AddExitFunction(AddExitFunctionFuncPair(NE2K_ShutDown),true);
01741         AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(NE2K_OnReset));
01742 }
01743 
01744 #endif // C_NE2000