static bool pci_config_data_in(struct kvm *kvm, u16 port, void *data, int size, u32 count) { unsigned long start; u8 dev_num; /* * If someone accesses PCI configuration space offsets that are not * aligned to 4 bytes, it uses ioports to signify that. */ start = port - PCI_CONFIG_DATA; dev_num = pci_config_address.device_number; if (pci_device_exists(0, dev_num, 0)) { unsigned long offset; offset = start + (pci_config_address.register_number << 2); if (offset < sizeof(struct pci_device_header)) { void *p = pci_devices[dev_num]; memcpy(data, p + offset, size); } else memset(data, 0x00, size); } else memset(data, 0xff, size); return true; }
int main (void) { pci_device_info_type *device_info; unsigned int number_of_devices; unsigned int counter; unsigned int probe_counter; system_process_name_set (PACKAGE_NAME); system_thread_name_set ("Initialising"); if (log_init (&log_structure, PACKAGE_NAME, &empty_tag) != LOG_RETURN_SUCCESS) { return -1; } if (pci_init (&pci_structure, &empty_tag) != PCI_RETURN_SUCCESS) { log_print (&log_structure, LOG_URGENCY_EMERGENCY, "Couldn't create connection to PCI service."); return -1; } system_call_process_parent_unblock (); for (probe_counter = 0; pci_device_probe[probe_counter].vendor_id != 0xFFFF; probe_counter++) { pci_device_exists (&pci_structure, &pci_device_probe[probe_counter], &device_info, &number_of_devices); if (number_of_devices != 0) { for (counter = 0; counter < number_of_devices; counter++) { if (system_thread_create () == SYSTEM_RETURN_THREAD_NEW) { handle_8139 (&device_info[counter]); } } } } return 0; }
void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size) { u8 dev_num; dev_num = addr.device_number; if (pci_device_exists(0, dev_num, 0)) { unsigned long offset; offset = addr.w & 0xff; if (offset < sizeof(struct pci_device_header)) { void *p = device__find_dev(DEVICE_BUS_PCI, dev_num)->data; memcpy(data, p + offset, size); } else { memset(data, 0x00, size); } } else { memset(data, 0xff, size); } }
void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size) { u8 dev_num; dev_num = addr.device_number; if (pci_device_exists(0, dev_num, 0)) { unsigned long offset; offset = addr.w & 0xff; if (offset < sizeof(struct pci_device_header)) { void *p = device__find_dev(DEVICE_BUS_PCI, dev_num)->data; struct pci_device_header *hdr = p; u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32)); u32 sz = cpu_to_le32(PCI_IO_SIZE); if (bar < 6 && hdr->bar_size[bar]) sz = hdr->bar_size[bar]; /* * If the kernel masks the BAR it would expect to find the * size of the BAR there next time it reads from it. * When the kernel got the size it would write the address * back. */ if (*(u32 *)(p + offset)) { /* See if kernel tries to mask one of the BARs */ if ((offset >= PCI_BAR_OFFSET(0)) && (offset <= PCI_BAR_OFFSET(6)) && (ioport__read32(data) == 0xFFFFFFFF)) memcpy(p + offset, &sz, sizeof(sz)); else memcpy(p + offset, data, size); } } } }