00001 #include "openem.h"
00002
00003 #include "arch/ibmpc/ibmpc.h"
00004
00005 #include "arch/ibmpc/dma.h"
00006 #include "arch/ibmpc/sys_ppi_8255A.h"
00007
00008 #include <stdio.h>
00009
00010 namespace IBMPC
00011 {
00012
00013 Memory::Memory()
00014 :m_pages(NULL), m_pages_count_pow(0), m_page_size_pow(0),
00015 m_addr_page_shift(0), m_addr_page_mask(0), m_addr_clamp_mask(0),
00016 m_state(0)
00017 {
00018 }
00019
00020 Memory::~Memory()
00021 {
00022 if (m_pages) {
00023 unsigned int total_pages = 1 << m_pages_count_pow;
00024 for (unsigned int page_index=0; page_index < total_pages; ++page_index)
00025 page_free(page_index);
00026 delete[] m_pages;
00027 }
00028 }
00029
00030 bool Memory::alloc_pagetable(unsigned int pages_count_pow, unsigned int page_size_pow)
00031 {
00032
00033
00034 OE_ASSERT(pages_count_pow <= sizeof(unsigned int)*8);
00035 OE_ASSERT(page_size_pow <= sizeof(unsigned int)*8);
00036
00037 unsigned int page_size = 1 << page_size_pow;
00038 unsigned int pages_count = 1 << pages_count_pow;
00039
00040
00041 page_t *new_page_table = new page_t[pages_count];
00042 if (new_page_table == NULL)
00043 return false;
00044
00045 m_pages_count_pow = pages_count_pow;
00046 m_page_size_pow = page_size_pow;
00047
00048 m_addr_page_shift = page_size_pow;
00049 m_addr_page_mask = page_size-1;
00050 m_addr_clamp_mask = (pages_count * page_size) - 1;
00051
00052
00053 if (m_pages) {
00054 for (unsigned int page_index=0; page_index < pages_count; ++page_index)
00055 page_free(page_index);
00056 delete[] m_pages;
00057 }
00058
00059
00060 m_pages = new_page_table;
00061
00062
00063 for (unsigned int page_index=0; page_index < pages_count; ++page_index) {
00064 page_t &page = m_pages[page_index];
00065 page.flags = 0;
00066 page.mem = NULL;
00067 }
00068
00069 return true;
00070 }
00071
00072 void Memory::page_set_perm(unsigned int page_index, uint32 perm)
00073 {
00074 OE_ASSERT(page_index < (unsigned int)(1 << m_pages_count_pow));
00075 OE_ASSERT(perm & PAGE_ALLOCATED);
00076 OE_ASSERT(m_pages);
00077 perm &= ~PAGE_ALLOCATED;
00078 page_t &page = m_pages[page_index];
00079 page.flags = (page.flags & PAGE_ALLOCATED) | perm;
00080 }
00081
00082 uint32 Memory::page_get_perm(unsigned int page_index)
00083 {
00084 OE_ASSERT(page_index < (unsigned int)(1 << m_pages_count_pow));
00085 OE_ASSERT(m_pages);
00086 page_t &page = m_pages[page_index];
00087 return page.flags;
00088 }
00089
00090 bool Memory::page_alloc(unsigned int page_index)
00091 {
00092 OE_ASSERT(page_index < (unsigned int)(1 << m_pages_count_pow));
00093 OE_ASSERT(m_pages);
00094 uint8 *new_page_mem = new uint8[1 << m_page_size_pow];
00095 if (new_page_mem == NULL) {
00096 return false;
00097 }
00098 page_free(page_index);
00099 page_t &page = m_pages[page_index];
00100 page.flags = PERM_READABLE | PERM_WRITEABLE | PAGE_ALLOCATED;
00101 page.mem = new_page_mem;
00102 return true;
00103 }
00104
00105 void Memory::page_attach(unsigned int page_index, Device *driver)
00106 {
00107 OE_ASSERT(page_index < (unsigned int)(1 << m_pages_count_pow));
00108 OE_ASSERT(driver);
00109 OE_ASSERT(m_pages);
00110 page_free(page_index);
00111 page_t &page = m_pages[page_index];
00112 page.flags = PERM_READABLE | PERM_WRITEABLE;
00113 page.driver = driver;
00114 }
00115
00116 void Memory::page_free(unsigned int page_index)
00117 {
00118 OE_ASSERT(page_index < (unsigned int)(1 << m_pages_count_pow));
00119 OE_ASSERT(m_pages);
00120 page_t &page = m_pages[page_index];
00121 if (page.flags & PAGE_ALLOCATED)
00122 delete[] page.mem;
00123 page.flags = 0;
00124 page.mem = NULL;
00125 }
00126
00127
00128 uint8 Memory::mem_read8(unsigned int addr)
00129 {
00130 OE_ASSERT(m_pages);
00131 addr &= m_addr_clamp_mask;
00132 unsigned int page_index = (addr >> m_addr_page_shift);
00133 unsigned int offset = (addr & m_addr_page_mask);
00134 page_t &page = m_pages[page_index];
00135 if (page.flags & PERM_READABLE) {
00136 m_state = 0;
00137 return (page.flags & PAGE_ALLOCATED) ? page.mem[offset] : page.driver->mem_read8(addr);
00138 }
00139 else {
00140
00141 m_state = STATE_FAULT;
00142 return 0;
00143 }
00144 }
00145
00146 void Memory::mem_write8(unsigned int addr, uint8 data)
00147 {
00148 OE_ASSERT(m_pages);
00149 addr &= m_addr_clamp_mask;
00150 unsigned int page_index = (addr >> m_addr_page_shift);
00151 unsigned int offset = (addr & m_addr_page_mask);
00152 page_t &page = m_pages[page_index];
00153 if (page.flags & PERM_WRITEABLE) {
00154 m_state = 0;
00155 if (page.flags & PAGE_ALLOCATED)
00156 page.mem[offset] = data;
00157 else
00158 page.driver->mem_write8(addr, data);
00159 }
00160 else {
00161
00162 m_state = STATE_FAULT | STATE_DIR;
00163 }
00164 }
00165
00166
00167 IO::IO()
00168 :m_state(0)
00169 {
00170 }
00171
00172 IO::~IO()
00173 {
00174 }
00175
00176 void IO::port_set_perm(unsigned int port, uint32 perm)
00177 {
00178
00179 std::map<unsigned int, port_spec_t>::iterator found = m_port_map.find(port);
00180 OE_ASSERT(found != m_port_map.end());
00181 found->second.flags = perm;
00182 }
00183
00184 uint32 IO::port_get_perm(unsigned int port)
00185 {
00186
00187 std::map<unsigned int, port_spec_t>::const_iterator found = m_port_map.find(port);
00188 if (found != m_port_map.end())
00189 return found->second.flags;
00190 else
00191 return 0;
00192 }
00193
00194 bool IO::port_attach(unsigned int port_index, Device *driver)
00195 {
00196 OE_ASSERT(driver != NULL);
00197
00198 std::map<unsigned int, port_spec_t>::const_iterator found = m_port_map.find(port_index);
00199 if (found == m_port_map.end() || found->second.driver == driver) {
00200 port_spec_t port_spec;
00201 port_spec.flags = PERM_READABLE|PERM_WRITEABLE;
00202 port_spec.driver = driver;
00203 m_port_map[port_index] = port_spec;
00204 }
00205 else
00206 return false;
00207 return true;
00208 }
00209
00210 bool IO::port_free(unsigned int port_index)
00211 {
00212
00213 std::map<unsigned int, port_spec_t>::const_iterator found = m_port_map.find(port_index);
00214 if (found == m_port_map.end())
00215 return false;
00216 else
00217 m_port_map.erase(port_index);
00218 return true;
00219 }
00220
00221
00222 uint8 IO::port_read8(unsigned int port_index)
00223 {
00224
00225 std::map<unsigned int, port_spec_t>::const_iterator found = m_port_map.find(port_index);
00226 if (found == m_port_map.end()) {
00227
00228 fprintf (stderr, "[*] Attempt to read BYTE from unreserved port 0x%04X.\n", port_index);
00229 m_state = STATE_FAULT;
00230 return 0;
00231 }
00232 else
00233 return found->second.driver->port_read8(port_index);
00234 m_state = 0;
00235 }
00236 void IO::port_write8(unsigned int port_index, uint8 value)
00237 {
00238
00239 std::map<unsigned int, port_spec_t>::const_iterator found = m_port_map.find(port_index);
00240 if (found == m_port_map.end()) {
00241
00242 fprintf (stderr, "[*] Attempt to write BYTE 0x%02X to unreserved port 0x%04X.\n", value, port_index);
00243 m_state = STATE_FAULT | STATE_DIR;
00244 }
00245 else
00246 found->second.driver->port_write8(port_index, value);
00247 m_state = 0;
00248 }
00249
00250
00251 Core::Core()
00252 {
00253 cpu.attach(this);
00254 }
00255
00256 Core::~Core()
00257 {
00258 }
00259
00260
00261 Device::Device()
00262 {
00263 }
00264
00265 Device::~Device()
00266 {
00267 }
00268
00269
00270 void Device::set_name(std::string name)
00271 {
00272 m_name = name;
00273 }
00274
00275
00276 std::string Device::get_name()
00277 {
00278 return m_name;
00279 }
00280
00281
00282
00283
00284 void copy_to_mem(uint8 *buf, int buf_size, Memory &mem, unsigned int addr)
00285 {
00286 for (int i=0; i<buf_size; i++) {
00287 mem.mem_write8(addr, buf[i]);
00288 addr++;
00289 }
00290 }
00291
00292
00293 void load_ibmpc_rom(char *rom_filename, Memory &mem)
00294 {
00295
00296 FILE *stream = fopen(rom_filename, "rb");
00297 if (stream == NULL)
00298 throw "Could not open ROM file";
00299
00300 uint32 flat_addr = 0xFE000;
00301 int value = fgetc(stream);
00302 do {
00303 mem.mem_write8(flat_addr, value);
00304 flat_addr++;
00305 value = fgetc(stream);
00306 } while (!feof(stream));
00307
00308 fclose(stream);
00309 }
00310
00311 VirtualMachine::VirtualMachine()
00312 :m_mem_total_pages(256), m_was_error(false)
00313 {
00314
00315 m_core.mem.alloc_pagetable(8, 12);
00316
00317
00318
00319 for (unsigned int page_index=0; page_index < m_mem_total_pages; ++page_index) {
00320 m_core.mem.page_alloc(page_index);
00321 }
00322
00323
00324
00325
00326
00327 IBMPC::VDD_DMA *vdd_dma = new VDD_DMA;
00328 m_core.attach(vdd_dma);
00329 register_driver(vdd_dma);
00330
00331
00332 IBMPC::VDD_SYS_PPI_8255A *vdd_ppi = new IBMPC::VDD_SYS_PPI_8255A;
00333 m_core.attach(vdd_dma);
00334 register_driver(vdd_ppi);
00335
00336
00337 load_ibmpc_rom("..\\..\\bin\\BIOS.BIN", m_core.mem);
00338 }
00339
00340 VirtualMachine::~VirtualMachine()
00341 {
00342 while (m_drivers.size())
00343 {
00344 Device *driver = *(m_drivers.end()-1);
00345 driver->done();
00346 m_drivers.pop_back();
00347 }
00348 }
00349
00350 void VirtualMachine::register_driver(Device *driver)
00351 {
00352 for (unsigned int i=0; i<m_drivers.size(); ++i) {
00353 if (m_drivers[i] == driver) {
00354 fprintf (stderr, "[*] Driver '%s' attempted to register with virtual system twice.\n", driver->get_name().c_str());
00355 }
00356 }
00357 m_drivers.push_back(driver);
00358 driver->set_core(&m_core);
00359 driver->init();
00360 }
00361
00362 void VirtualMachine::unregister_driver(Device *driver)
00363 {
00364 for (std::vector<Device*>::iterator i=m_drivers.begin(); i!=m_drivers.end(); ++i) {
00365 if (*i == driver) {
00366 (*i)->done();
00367 driver->done();
00368 driver->set_core(NULL);
00369 m_drivers.erase(i);
00370 return;
00371 }
00372 }
00373
00374 fprintf(stderr, "[*] Attempt to detach driver '%s', which is not registered with this virtual system.\n", driver->get_name().c_str());
00375 }
00376
00377 int VirtualMachine::drivers_count()
00378 {
00379 return m_drivers.size();
00380 }
00381
00382 Device* VirtualMachine::get_driver(int index)
00383 {
00384 return m_drivers.at(index);
00385 }
00386
00387 Device* VirtualMachine::find_driver(std::string name)
00388 {
00389 for (unsigned int i=0; i<m_drivers.size(); ++i) {
00390 if (m_drivers[i]->get_name() == name)
00391 return m_drivers[i];
00392 }
00393 return NULL;
00394 }
00395
00396 void VirtualMachine::reset()
00397 {
00398 fprintf(stderr, "[*] Machine reset.\n");
00399 m_core.cpu.reset();
00400 }
00401
00402 void VirtualMachine::run(unsigned int cycles)
00403 {
00404
00405 m_was_error = m_core.cpu.cycle(cycles) > 0 ? true : false;
00406 }
00407
00408 bool VirtualMachine::was_error() const
00409 {
00410 return m_was_error;
00411 }
00412
00413 void VirtualMachine::set_debug(bool debug_on, bool debug_pause)
00414 {
00415 m_core.cpu.set_dbg(debug_on, debug_pause);
00416 }
00417
00418
00419 }