📄 write.cc
字号:
#include "bus.hh"const ClockValue addr_latency = 5;const ClockValue mem_latency = 20;static ClockValuewrite_doubleword(Device* dev, UInt64 addr, UInt64 x){ if (dev->width == 8) return dev->write(addr, &x, 8); else { ClockValue latency = 0; if (/* big_endian_mem() */ 1) { int shift = 64; int size = 8; do { shift -= dev->width * 8; UInt64 tmp = x >> shift; latency += dev->write(addr, &tmp, dev->width); size -= dev->width; addr += dev->width; } while (size); } else { int size = 8; do { latency += dev->write(addr, &x, dev->width); x >>= dev->width * 8; size -= dev->width; addr += dev->width; } while (size); } return latency; }}static ClockValuewrite_block(Device* dev, UInt64 addr, const UInt64* buf, int size){ // Do a burst write with a correct subblock ordering. assert(size >= 8 && size % 8 == 0); ClockValue latency = 0; int counter = 0; do { latency += write_doubleword(dev, addr ^ counter, buf[counter / 8]); counter += 8; } while (counter < size); return latency;}static ClockValuewrite_short(Device* dev, UInt64 addr, UInt64 x, int size){ if (is_power_of_two(size) && size <= dev->width) return dev->write(addr, &x, size); else { int width = (is_power_of_two(size)) ? dev->width : 1; ClockValue latency = 0; if (/* big_endian_mem() */ 1) { int shift = size * 8; do { shift -= width * 8; UInt64 tmp = x >> shift; latency += dev->write(addr, &tmp, width); size -= width; addr += width; } while (size); } else { do { latency += dev->write(addr, &x, width); x >>= width * 8; size -= width; addr += width; } while (size); } return latency; }}ClockValueMIPS64SimpleBus::write(UInt64 addr, const UInt64* buf, int size){ UInt32 reg, val; // Discard the coherency protocol. addr = physical_address(addr); assert(size > 0 && (size <= 8 || size % 8 == 0)); assert(!is_power_of_two(size) || (addr & (size - 1)) == 0); if (addr < memory_size) { // Fast access to the main memory. if (size >= 8) { UInt64* dst = &ram[addr / 8]; int i = 0; for (; i < size / 8; ++i) *dst++ = *buf++; return addr_latency + i * mem_latency; } else { unsigned offset = bits(addr, 2, 0) * 8; if (!big_endian_host()) offset = 64 - (size * 8) - offset; ram[addr / 8] = set_bits(ram[addr / 8], *buf, offset + size * 8 - 1, offset); return addr_latency + mem_latency; } } else if (addr < 0x10000000) { // Don't do anything. return addr_latency; } else if (addr < 0x14000000) { // PCI I/O space (8 x 4MB), memory space (8 x 4MB) // We treat the two spaces as equivalent Device* device = pcidev[((addr - 0x10000000) / (0x400000) + 1) & 7]; if (!device) { // Device not present. log("Device not present (%016lx)", addr); return bus_error(addr_latency); } else { ClockValue latency = addr_latency + (size < 8) ? write_short(device, addr, *buf, size) : write_block(device, addr, buf, size); if (is_bus_error(latency)) { return bus_latency(latency); } else { return latency; } } } else if (addr < 0x14000000) { assert(!"PCI mem space"); return 0; } else if (addr < 0x1c000000) { reg = addr - 0x14000000; val = *buf; val = byte_swap(val); switch (reg) { case 0x850: case 0x854: case 0x858: case 0x85c: timer[(reg-0x850)/4]->write(val); break; case 0x864: timer_control = val; for (int i = 0; i < 4; i++) { timer[i]->control(val & 1, val & 2); val >>= 2; } break; case 0xc18: intr_pending &= val; check_interrupts(); break; case 0xc1c: intr_mask = val; check_interrupts(); break; case 0xcf8: pciconfig_address = val; break; case 0xcfc: pciconfig_write(pciconfig_address, &val, size); break; default: log("Write unimplemented GT register %x %x", reg, val); break; } return 0; } else if (addr < 0x20000000) { Device* device = decode[(addr - 0x1c000000) / (0x400000)]; if (!device && (addr >= 0x1c800000) && (addr < 0x1c800040)) device = cs1_subdecode[(addr - 0x1c800000) / (0x10)]; // U4600 hack if (!device) { // Device not present. log("Device not present (%016lx)", addr); return bus_error(addr_latency); } else { ClockValue latency = addr_latency + (size < 8) ? write_short(device, addr, *buf, size) : write_block(device, addr, buf, size); if (is_bus_error(latency)) { return bus_latency(latency); } else { return latency; } } } else { // A bus interrupt. return addr_latency; }}ClockValueMIPS64SimpleBus::pciconfig_write(UInt32 addr, const UInt32* buf, int size){ unsigned int bus = (addr >> 16) & 0xff; unsigned int devno = (addr >> 11) & 0x1f; unsigned int function = (addr >> 8) & 7; unsigned int reg = (addr & 0xff); if ((bus == 0) && (function == 0) && (devno < 8) && pcidev[devno]) { PCIDevice *device = pcidev[devno]; if ((reg >= 0x10) && (reg < 0x28)) /* BAR */ { unsigned int bar = (reg - 0x10) >> 2; device->bar[bar] &= ~(0xffc00000); device->bar[bar] |= *buf & 0xffc00000; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -