///////////////////////////////////////////////////////////////////////// // $Id: iodebug.cc,v 1.16 2004-06-19 15:20:12 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// #include "iodev.h" #if BX_IODEBUG_SUPPORT bx_iodebug_c bx_iodebug; bx_iodebug_c *bx_iodebug_ptr; struct bx_iodebug_s_type { bx_bool enabled; unsigned int register_select; Bit32u registers[2]; Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS]; Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS]; } bx_iodebug_s; // Constructor bx_iodebug_c::bx_iodebug_c( void ) { put("IODEBUG"); settype(IODEBUGLOG); } // Destructor bx_iodebug_c::~bx_iodebug_c( void ) { } void bx_iodebug_c::init(void) { int i; DEV_register_ioread_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG", 7); DEV_register_iowrite_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG", 7); DEV_register_iowrite_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG", 7); // fprintf( stderr, "IODEBUG initialized\n"); bx_iodebug_s.enabled = 0; bx_iodebug_s.register_select = 0; for(i=0;iread(addr, io_len) ); } Bit32u bx_iodebug_c::read( Bit32u addr, unsigned io_len ) { if(bx_iodebug_s.enabled) return(0x8A00); return(0); } void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len) { bx_iodebug_c *class_ptr = (bx_iodebug_c *) this_ptr; class_ptr->write( addr, dvalue, io_len ); } void bx_iodebug_c::write( Bit32u addr, Bit32u dvalue, unsigned int io_len ) { // fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned int)addr, (unsigned int)dvalue, io_len); if( addr == 0x8A01 && io_len == 2 ) { bx_iodebug_s.registers[bx_iodebug_s.register_select] = (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) + (dvalue & 0x0000FFFF ); } if( (addr != 0x8A00) || (io_len != 2) ) return; if( !bx_iodebug_s.enabled ) { if( dvalue == 0x8A00 ) { bx_iodebug_s.enabled = 1; // fprintf(stderr, "IODEBUG enabled\n"); bx_iodebug_s.registers[0] = 0; bx_iodebug_s.registers[1] = 0; } return; } switch( dvalue ) { case( 0x8A01 ): bx_iodebug_s.register_select = 0; // fprintf( stderr, "IODEBUG register 0 selected\n"); break; case( 0x8A02 ): bx_iodebug_s.register_select = 1; // fprintf( stderr, "IODEBUG register 1 selected\n"); break; case( 0x8A80 ): bx_iodebug_s.register_select = 0; bx_iodebug_c::add_range( bx_iodebug_s.registers[0], bx_iodebug_s.registers[1]); bx_iodebug_s.registers[0] = 0; bx_iodebug_s.registers[1] = 0; break; #if BX_DEBUGGER case( 0x8AE0 ): fprintf( stderr, "request return to dbg prompt received, 0x8AE0 command (iodebug)\n"); bx_guard.interrupt_requested=1; break; case( 0x8AE2): fprintf( stderr, "request made by the guest os to disable tracing, iodebug port 0x8A00->0x8AE2\n"); BX_CPU(dbg_cpu)->trace = 0; break; case( 0x8AE3 ): fprintf( stderr, "request made by the guest os to enable tracing, iodebug port 0x8A00->0x8AE3\n"); BX_CPU(dbg_cpu)->trace = 1; break; case( 0x8AE4 ): fprintf( stderr, "request made by the guest os to disable register tracing, iodebug port 0x8A00->0x8AE4\n"); BX_CPU(dbg_cpu)->trace_reg = 0; break; case( 0x8AE5 ): fprintf( stderr, "request made by the guest os to enable register tracing, iodebug port 0x8A00->0x8AE5\n"); BX_CPU(dbg_cpu)->trace_reg = 1; break; #endif case( 0x8AFF ): bx_iodebug_s.enabled = 0; // fprintf( stderr, "IODEBUG device deactivated\n"); // break; // default: // fprintf(stderr,"IODEBUG unsupported register code\n"); } } // Static function void bx_iodebug_c::mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) { Bit32u data32; Bit16u data16; Bit8u data8; unsigned int area; if( !bx_iodebug_s.enabled ) return; area = bx_iodebug_c::range_test( addr, len ); // Device is enabled, testing address ranges if( area ) { area--; #if BX_DEBUGGER fprintf( stdout, "%s @ eip: %08X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr); bx_guard.interrupt_requested=1; #else fprintf( stderr, "IODEBUG write to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t", area, cpu->get_EIP(), bx_iodebug_s.monitored_mem_areas_start[area], bx_iodebug_s.monitored_mem_areas_end[area], (unsigned int)addr); data32 = * (Bit32u *)data; data16 = (Bit16u)data32; data8 = (Bit8u)data32; switch(len) { case(1): fprintf(stderr,"%02X\n", (unsigned int)data8); break; case(2): fprintf(stderr,"%04X\n", (unsigned int)data16); break; case(4): fprintf(stderr,"%08X\n", (unsigned int)data32); break; default: fprintf(stderr, "unsupported write size\n"); } #endif } } void bx_iodebug_c::mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) { Bit32u data32; Bit16u data16; Bit8u data8; unsigned int area; if( !bx_iodebug_s.enabled ) return; area = bx_iodebug_c::range_test( addr, len ); // Device is enabled, testing address ranges if( area ) { area--; #if BX_DEBUGGER fprintf( stdout, "%s @ eip: %8X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr); bx_guard.interrupt_requested=1; #else fprintf( stderr, "IODEBUG read to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t", area, cpu->get_EIP(), bx_iodebug_s.monitored_mem_areas_start[area], bx_iodebug_s.monitored_mem_areas_end[area], (unsigned int)addr); data32 = * (Bit32u *)data; data16 = (Bit16u)data32; data8 = (Bit8u)data32; switch(len) { case(1): fprintf(stderr,"%02X\n", (unsigned int)data8); break; case(2): fprintf(stderr,"%04X\n", (unsigned int)data16); break; case(4): fprintf(stderr,"%08X\n", (unsigned int)data32); break; default: fprintf(stderr, "unsupported write size\n"); } #endif } } unsigned int bx_iodebug_c::range_test( Bit32u addr, unsigned int len ) { unsigned int i; for(i=0;i