📄 pcibus.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.pci;import org.jpc.emulator.motherboard.*;import org.jpc.emulator.memory.*;import org.jpc.emulator.pci.peripheral.*;import org.jpc.emulator.*;import java.io.*;public class PCIBus implements HardwareComponent{ private int busNumber; private int devFNMinimum; private boolean updated; //openpic_t openpic; // Neccessary? private PCIDevice devices[]; private PCIISABridge isaBridge; private IOPortHandler ioportHandler; private PhysicalAddressSpace memory; //pci_mem_base? private int pciIRQIndex; private int pciIRQLevels[][]; public static final int PCI_COMMAND = 0x04; final static private int PCI_VENDOR_ID = 0x00; final static private int PCI_DEVICE_ID = 0x02; final static private int PCI_COMMAND_IO = 0x1; final static private int PCI_COMMAND_MEMORY = 0x2; final static private int PCI_CLASS_DEVICE = 0x0a; final static private int PCI_INTERRUPT_LINE = 0x3c; final static private int PCI_INTERRUPT_PIN = 0x3d; final static private int PCI_MIN_GNT = 0x3e; final static private int PCI_MAX_LAT = 0x3f; final static private int PCI_DEVICES_MAX = 64; public static final int PCI_IRQ_WORDS = ((PCI_DEVICES_MAX + 31) / 32); public PCIBus() { busNumber = 0; pciIRQIndex = 0; devices = new PCIDevice[256]; pciIRQLevels = new int[4][PCI_IRQ_WORDS]; devFNMinimum = 8; } public void dumpState(DataOutput output) throws IOException { output.writeInt(busNumber); output.writeInt(devFNMinimum); output.writeInt(pciIRQIndex); output.writeInt(pciIRQLevels.length); output.writeInt(pciIRQLevels[0].length); for (int i=0; i < pciIRQLevels.length; i++) for (int j=0; j < pciIRQLevels[0].length; j++) output.writeInt(pciIRQLevels[i][j]); output.writeInt(biosIOAddress); output.writeInt(biosMemoryAddress); } public void loadState(DataInput input) throws IOException { updated = false; devices = new PCIDevice[256]; busNumber = input.readInt(); devFNMinimum = input.readInt(); pciIRQIndex = input.readInt(); int len1 = input.readInt(); int len2 = input.readInt(); pciIRQLevels = new int[len1][len2]; for (int i=0; i < pciIRQLevels.length; i++) for (int j=0; j < pciIRQLevels[0].length; j++) pciIRQLevels[i][j] = input.readInt(); biosIOAddress = input.readInt(); biosMemoryAddress = input.readInt(); } public boolean registerDevice(PCIDevice device) { if (pciIRQIndex >= PCI_DEVICES_MAX) { return false; } /* if (device instanceof PCIISABridge) devFNMinimum = 8; else devFNMinimum = 16; */ if (device.autoAssignDevFN()) { int devFN = findFreeDevFN(); if (0 <= devFN) { device.assignDevFN(devFN); } } else { PCIDevice oldDevice = devices[device.getCurrentDevFN()]; if (oldDevice != null) { System.err.println("Trying to temporarily unregister a pci device, this may not work."); oldDevice.deassignDevFN(); } } device.setIRQIndex(pciIRQIndex++); this.addDevice(device); IRQBouncer bouncer = isaBridge.makeBouncer(device); device.addIRQBouncer(bouncer); return this.registerPCIIORegions(device); } private int findFreeDevFN() { for(int i = devFNMinimum; i < 256; i += 8) { if (null == devices[i]) return i; } return -1; } private boolean registerPCIIORegions(PCIDevice device) { IORegion[] regions = device.getIORegions(); if (regions == null) return true; boolean ret = true; for (int i = 0; i < regions.length; i++) { IORegion region = regions[i]; if (PCIDevice.PCI_NUM_REGIONS <= region.getRegionNumber()) { ret = false; continue; } region.setAddress(-1); if (region.getRegionNumber() == PCIDevice.PCI_ROM_SLOT) device.putConfigInt(0x30, region.getType()); else device.putConfigInt(0x10 + region.getRegionNumber() * 4, region.getType()); } return ret; } private void updateMappings(PCIDevice device) { int lastAddress, newAddress, configOffset; IORegion[] regions = device.getIORegions(); if (regions == null) return; short command = device.getConfigShort(PCI_COMMAND); for(int i = 0; i < regions.length; i++) { IORegion r = regions[i]; if (null == r) continue; if (PCIDevice.PCI_NUM_REGIONS <= r.getRegionNumber()) continue; if (PCIDevice.PCI_ROM_SLOT == r.getRegionNumber()) configOffset = 0x30; else configOffset = 0x10 + r.getRegionNumber() * 4; if (r instanceof IOPortIORegion) { if (0 != (command & PCI_COMMAND_IO)) { newAddress = device.getConfigInt(configOffset); newAddress &= ~(r.getSize() - 1); lastAddress = newAddress + (int)r.getSize() - 1; if (lastAddress <= (0xffffffffl & newAddress) || 0 == newAddress || 0x10000 <= (0xffffffffl & lastAddress)) newAddress = -1; } else newAddress = -1; } else if (r instanceof MemoryMappedIORegion) { if (0 != (command & PCI_COMMAND_MEMORY)) { newAddress = device.getConfigInt(configOffset); if (PCIDevice.PCI_ROM_SLOT == r.getRegionNumber() && (0 == (newAddress & 1))) { newAddress = -1; } else { newAddress &= ~(r.getSize() - 1); lastAddress = newAddress + (int)r.getSize() - 1; if (lastAddress <= newAddress || 0 == newAddress || -1 == lastAddress) newAddress = -1; } } else newAddress = -1; } else { throw new IllegalStateException("Unknown IORegion Type"); } if (r.getAddress() != newAddress) { if (r.getAddress() != -1) { if (r instanceof IOPortIORegion) { int deviceClass; deviceClass = device.getConfigByte(0x0a) | (device.getConfigByte(0x0b) << 8); if (0x0101 == deviceClass && 4 == r.getSize()) { //r.unmap(); must actually be partial System.err.println("Supposed to partially unmap"); ioportHandler.deregisterIOPortCapable((IOPortIORegion)r); } else { //r.unmap(); ioportHandler.deregisterIOPortCapable((IOPortIORegion)r); } } else if (r instanceof MemoryMappedIORegion) { memory.unmap(r.getAddress(), (int)r.getSize()); } } r.setAddress(newAddress); if (r.getAddress() != -1) { if (r instanceof IOPortIORegion) { IOPortIORegion pr = (IOPortIORegion) r; ioportHandler.registerIOPortCapable((IOPortIORegion)r); } else if (r instanceof MemoryMappedIORegion) { MemoryMappedIORegion mmap = (MemoryMappedIORegion) r; memory.mapMemoryRegion(mmap, r.getAddress(), (int)r.getSize()); } } } } } private void addDevice(PCIDevice device) { devices[device.getCurrentDevFN()] = device; } //PCIHostBridge shifted functionality private PCIDevice validPCIDataAccess(int address) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -