DOSBox-X
|
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