void amdrv100init(uint8_t bus, uint8_t slot) { printf("amd_rv100: init on bus:slot %x:%x\n", bus, slot); uint16_t vendor = pci_config_read_word(bus, slot, 0, 0); if(vendor == 0xFFFF) { puts("amd_rv100: init failed: device not found on specified bus:slot\n"); return; } uint16_t device = pci_config_read_word(bus, slot, 0, 2); if(device != 0x4c59) { puts("amd_rv100: init failed: device is not compatible\n"); return; } uint32_t fbaddr = pci_config_read_dword(bus, slot, 0, 0x10) & ~0xF; uint32_t port = pci_config_read_dword(bus, slot, 0, 0x14) & ~0x3; printf("amd_rv100: framebuffer addr: 0x%x port: 0x%x\n", fbaddr, port); vga_card* v = graphics_add_card(); if(!v) return; v->bus = bus; v->slot = slot; v->data[0] = fbaddr; v->data[1] = port; pci_config_write_byte(bus, slot, 0, 0x3d, 1); pci_config_write_byte(bus, slot, 0, 0x3c, 11); vdestroy(); vinit(1024, 768, 32, 1024 * 4, fbaddr); printf("amd_rv100: finished.\n"); }
void __pci_parse(struct pci_device *pdev) { /* first determine header type */ uint8_t header = pci_config_read_byte(pdev, 0x0E); if (header == 0x00) { int need_eprom = 1; /* determine bars and iobases */ for(int i = 0; i < 6; i++) { /* there are 6 BARs read them, check if the first byte is 1 */ uint32_t r = pci_config_read_dword(pdev, 0x10 + i * 4); if (r & 1) pdev->iobase = r & 0xFFFFFFFC; else { pdev->membase = r; if (!r) continue; need_eprom = 0; pci_config_write_dword(pdev, 0x10 + i * 4, 0xffffffff); uint32_t size = pci_config_read_dword(pdev, 0x10 + i * 4); size &= 0xfffffff0; size = ~size; size += 1; pci_config_write_dword(pdev, 0x10 + i * 4, pdev->membase); pdev->memsize = size; if (pdev->memsize != 0) printk("membase: 0x%x size: %d\n", pdev->membase, size); } } if (need_eprom) { uint32_t eprom = pci_config_read_dword(pdev, 0x30); if (eprom) { pci_config_write_dword(pdev, 0x30, 0xffffffff); uint32_t size = pci_config_read_dword(pdev, 0x30); size &= 0xfffffff0; size = ~size; size += 1; pci_config_write_dword(pdev, 0x30, eprom); printk("eprom is 0x%x && size is 0x%x\n", eprom, size); } } /* read IRQ */ uint8_t irq = pci_config_read_byte(pdev, 0x3C); pdev->irq = irq; } else { pci_info(pdev, "unknown header!\n"); } }
// Writes an 8-bit value to a PCI device's configuration space. void pci_config_write_byte(uint32_t bus, uint32_t device, uint32_t function, uint32_t offset, uint8_t data) { uint32_t result = pci_config_read_dword(bus, device, function, offset); uint32_t t_offset = (offset & 0x03) * 8; result &= ~(0xFF << t_offset); result |= ((uint32_t)data << t_offset); pci_config_write_dword(bus, device, function, offset, data); }
void vbgfx_set_res(vga_card* v, int64_t w, int64_t h, uint8_t bpp) { if(!v) return; if(!v->data[0]) return; if(w * h > 1440000) return; uint32_t iobase = v->data[0]; outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_ENABLE); outw(iobase + VBGFX_IO_DATA, 0); //disable VBE extensions //write resolution outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_XRES); outw(iobase + VBGFX_IO_DATA, w); outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_YRES); outw(iobase + VBGFX_IO_DATA, h); //write bpp outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_BPP); outw(iobase + VBGFX_IO_DATA, bpp); //reset video module vdestroy(); //enable VBE extensions and LFB outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_ENABLE); outw(iobase + VBGFX_IO_DATA, 1 | 0x40); //init video module int64_t width, height, bppix; uint32_t lfb_addr = pci_config_read_dword(v->bus, v->slot, 0, 0x10) & ~0xF; outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_XRES); width = inw(iobase + VBGFX_IO_DATA); outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_YRES); height = inw(iobase + VBGFX_IO_DATA); outw(iobase + VBGFX_IO_INDEX, VBGFX_INDEX_BPP); bppix = inl(iobase + VBGFX_IO_DATA); vinit(width, height, bppix, w * 4, lfb_addr); }
ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID* PciId, UINT32 Register, UINT64* Value, UINT32 Width) { switch(Width) { case 8: *((u8*)Value) = (u8)pci_config_read_word(PciId->Bus, PciId->Device, PciId->Function, Register); break; case 16: *((u16*)Value) = pci_config_read_word(PciId->Bus, PciId->Device, PciId->Function, Register); break; case 32: *((u32*)Value) = pci_config_read_dword(PciId->Bus, PciId->Device, PciId->Function, Register); break; case 64: ((u32*)Value)[0] = pci_config_read_dword(PciId->Bus, PciId->Device, PciId->Function, Register); ((u32*)Value)[1] = pci_config_read_dword(PciId->Bus, PciId->Device, PciId->Function, Register+4); break; default: syslog(KERN_ERR, "acpi: %s: unsupported width %d!", __func__, Width); return AE_ERROR; } return AE_OK; }
// Enumerates all the PCI devices on the system that we can find. void pci_enumerate(void) { uint32_t bus = 0; uint32_t device = 0; uint32_t function = 0; uint16_t vendor_id = 0; uint16_t device_id = 0; uint8_t header_type = 0; int j = 0; #if PCI_ENUMERATION_DEBUG debug_printf(LOG_INFO "Enumerating PCI devices. This might take a while.\n"); #endif // Clear out the list of PCI devices in case it hasn't been done yet. for (int i = 0; i < PCI_MAX_DEVICES; i++) { pci_devices[i].device_handled = PCI_DEVICE_FREE; } // The main enumeration loop. We do a brute force scan on each bus for devices, and each // device for functions. We log each function we find as a found PCI device in the PCI // device structure list. for(bus = 0; bus < 256; bus++) { for(device = 0; device < 32; device++) { function = 0; if ((vendor_id = pci_config_read_word(bus, device, function, 0)) != 0xFFFF) { device_id = pci_config_read_word(bus, device, function, 2); header_type = pci_config_read_byte(bus, device, function, 0x0E); #if PCI_ENUMERATION_DEBUG debug_printf(LOG_INFO "%02X:%02X:%d - 0x%04X:0x%04X - Header Type 0x%02X - 0x%08X\n", bus, device, function, vendor_id, device_id, header_type, pci_config_read_dword(bus, device, function, 0x08)); #endif pci_devices[j].bus = bus; pci_devices[j].device = device; pci_devices[j].function = function; pci_devices[j].vendor_id = vendor_id; pci_devices[j].device_id = device_id; pci_devices[j].device_handled = PCI_DEVICE_EXISTS; if (++j == PCI_MAX_DEVICES) break; // If bit 7 is set in the header type, we are dealing with a // multifunction device. We need to iterate through the 7 other // functions to see if they exist. Multifunction PCI devices are // allowed to have discontiguous functions, much to the chagrin // of anyone writing a PCI device enumerator. if (header_type & 0x80) { for (function = 1; function < 8; function++) { if ((vendor_id = pci_config_read_word(bus, device, function, 0)) != 0xFFFF) { device_id = pci_config_read_word(bus, device, function, 2); header_type = pci_config_read_byte(bus, device, function, 0x0E); #if PCI_ENUMERATION_DEBUG debug_printf(LOG_INFO "%02X:%02X:%d - 0x%04X:0x%04X - Header Type 0x%02X - 0x%08X\n", bus, device, function, vendor_id, device_id, header_type, pci_config_read_dword(bus, device, function, 0x08)); #endif pci_devices[j].bus = bus; pci_devices[j].device = device; pci_devices[j].function = function; pci_devices[j].vendor_id = vendor_id; pci_devices[j].device_id = device_id; pci_devices[j].device_handled = PCI_DEVICE_EXISTS; if (++j == PCI_MAX_DEVICES) break; } } } } } // If we run out of PCI device structures to fill, log it. if (j == PCI_MAX_DEVICES) { debug_printf(LOG_WARNING "PCI_MAX_DEVICES hit at bus %02X device %02X function %d.\n", bus, device, function); break; } } #if PCI_ENUMERATION_DEBUG debug_printf(LOG_INFO "Enumerated %d PCI devices.\n", j); #endif }
// Reads an 8-bit value from a PCI device's configuration space. uint8_t pci_config_read_byte(uint32_t bus, uint32_t device, uint32_t function, uint32_t offset) { uint32_t result = pci_config_read_dword(bus, device, function, offset); uint32_t t_offset = (offset & 0x03) * 8; return (result >> t_offset) & 0xFF; }