Example #1
0
File: pci.c Project: levex/levos5
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");
	}
}
Example #2
0
int pci_config_read(unsigned char bus, unsigned char dev, unsigned char func,
		    unsigned char cmd, int len, unsigned long *val)
{
    int ret;
    
    ret = enable_app_io();
    if (ret != 0)
	return(ret);
    switch(len)
    {
	case 4:
	    ret = pci_config_read_long(bus, dev, func, cmd);
	    break;
	case 2:
	    ret = pci_config_read_word(bus, dev, func, cmd);
	    break;
	case 1:
	    ret = pci_config_read_byte(bus, dev, func, cmd);
	    break;
	default:
	    printf("libdha_pci: wrong length to read: %u\n",len);
    }
    disable_app_io();

    *val = ret;
    return(0);
}
Example #3
0
void pci_enumerate_device(struct PCIEnumeration *pci_enum, uint8_t bus, uint8_t device) {
	struct PCIIdentifier id = {.function = 0, .device = device, .bus = bus};

	/* if vendor ID is 0xFFFF, device does not exist */
	if(pci_config_read_word(id, PCI_OFFSET_VENDOR_ID) == 0xFFFF) { return; }
	pci_enumerate_function(pci_enum, id);

	/* if device has multiple functions */
	if((pci_config_read_byte(id, PCI_OFFSET_HEADER_TYPE) & 0x80) != 0) {
		for(uint8_t function = 1; function < 8; ++function) {
			struct PCIIdentifier func_id = {.function = function, .device = device, .bus = bus};

			/* if vendor ID is 0xFFFF, function does not exist */
			if(pci_config_read_word(func_id, PCI_OFFSET_VENDOR_ID) != 0xFFFF) {
				pci_enumerate_function(pci_enum, func_id);
			}
		}
	}
}

void pci_enumerate_function(struct PCIEnumeration *pci_enum, struct PCIIdentifier id) {
	uint8_t baseclass = pci_config_read_byte(id, PCI_OFFSET_CLASS);
	uint8_t subclass = pci_config_read_byte(id, PCI_OFFSET_SUBCLASS);

	pci_enum->info[pci_enum->count].id = id;
	pci_enum->info[pci_enum->count].baseclass = baseclass;
	pci_enum->info[pci_enum->count].subclass = subclass;
	++pci_enum->count;

	switch(baseclass) {
	case 0x6: /* bridge */
		switch(subclass) {
		case 0x4: /* PCI-to-PCI */
			pci_enumerate_bus(pci_enum, pci_config_read_byte(id, PCI_OFFSET_SECONDARY_BUS));
			break;
		}
		break;
	}
}
Example #4
0
void pci_enumerate_buses(struct PCIEnumeration *pci_enum) {
	struct PCIIdentifier id = {0, 0, 0};
	pci_enum->count = 0;

	/* single PCI host controller */
	if((pci_config_read_byte(id, PCI_OFFSET_HEADER_TYPE) & 0x80) == 0) {
		pci_enumerate_bus(pci_enum, 0);
	} else {
		for(id.function = 0; id.function < 8; ++id.function) {
			if(pci_config_read_word(id, PCI_OFFSET_VENDOR_ID) != 0xFFFF) { break; }
			pci_enumerate_bus(pci_enum, id.function);
		}
	}
}
Example #5
0
int pci_config_read(unsigned char bus, unsigned char dev, unsigned char func,
		    unsigned char cmd, int len, unsigned long *val)
{
    int ret;
    int dhahelper_fd;
    if ( (dhahelper_fd = open("/dev/dhahelper",O_RDWR)) > 0)
    {
	int retval;
	dhahelper_pci_config_t pcic;
	pcic.operation = PCI_OP_READ;
	pcic.bus = bus;
	pcic.dev = dev;
	pcic.func = func;
	pcic.cmd = cmd;
	pcic.size = len;
	retval = ioctl(dhahelper_fd, DHAHELPER_PCI_CONFIG, &pcic);
	close(dhahelper_fd);
	*val = pcic.ret;
	return retval;
    }
    ret = enable_app_io();
    if (ret != 0)
	return(ret);
    switch(len)
    {
	case 4:
	    ret = pci_config_read_long(bus, dev, func, cmd);
	    break;
	case 2:
	    ret = pci_config_read_word(bus, dev, func, cmd);
	    break;
	case 1:
	    ret = pci_config_read_byte(bus, dev, func, cmd);
	    break;
	default:
	    printf("libdha_pci: wrong length to read: %u\n",len);
    }
    disable_app_io();

    *val = ret;
    return(0);
}
Example #6
0
/*main(int argc, char *argv[])*/
static int __pci_scan(pciinfo_t *pci_list,unsigned *num_pci)
{
    unsigned int idx;
    struct pci_config_reg pcr;
    int do_mode1_scan = 0, do_mode2_scan = 0;
    int func, hostbridges=0;
    int ret = -1;
    
    pci_lst = pci_list;
    pcicards = 0;
 
    ret = enable_app_io();
    if (ret != 0)
	return(ret);

    if((pcr._configtype = pci_config_type()) == 0xFFFF) return ENODEV;
 
    /* Try pci config 1 probe first */
 
    if ((pcr._configtype == 1) || do_mode1_scan) {
    /*printf("\nPCI probing configuration type 1\n");*/
 
    pcr._ioaddr = 0xFFFF;
 
    pcr._pcibuses[0] = 0;
    pcr._pcinumbus = 1;
    pcr._pcibusidx = 0;
    idx = 0;
 
    do {
        /*printf("Probing for devices on PCI bus %d:\n\n", pcr._pcibusidx);*/
 
        for (pcr._cardnum = 0x0; pcr._cardnum < MAX_PCI_DEVICES_PER_BUS;
		pcr._cardnum += 0x1) {
	  func = 0;
	  do { /* loop over the different functions, if present */
	    pcr._device_vendor = pci_get_vendor(pcr._pcibuses[pcr._pcibusidx], pcr._cardnum,
						func);
            if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
                break;   /* nothing there */
 
	    /*printf("\npci bus 0x%x cardnum 0x%02x function 0x%04x: vendor 0x%04x device 0x%04x\n",
	        pcr._pcibuses[pcr._pcibusidx], pcr._cardnum, func,
		pcr._vendor, pcr._device);*/
	    pcibus = pcr._pcibuses[pcr._pcibusidx];
	    pcicard = pcr._cardnum;
	    pcifunc = func;
 
	    pcr._status_command = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_CMD_STAT_REG);
	    pcr._class_revision = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_CLASS_REG);
	    pcr._bist_header_latency_cache = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_HEADER_MISC);
	    pcr._base0 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START);
	    pcr._base1 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START+4);
	    pcr._base2 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START+8);
	    pcr._base3 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START+0x0C);
	    pcr._base4 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START+0x10);
	    pcr._base5 = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_REG_START+0x14);
	    pcr._baserom = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAP_ROM_REG);
#if 0
	    pcr._int_pin = pci_config_read_byte(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_INTERRUPT_PIN);
	    pcr._int_line = pci_config_read_byte(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_INTERRUPT_REG);
	    pcr._min_gnt = pci_config_read_byte(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MIN_GNT);
	    pcr._max_lat = pci_config_read_byte(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_MAX_LAT);
#else
	    pcr._max_min_ipin_iline = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_INTERRUPT_REG);
#endif
	    pcr._user_config = pci_config_read_long(pcr._pcibuses[pcr._pcibusidx],
					pcr._cardnum,func,PCI_REG_USERCONFIG);
            /* check for pci-pci bridges */
#define PCI_CLASS_MASK 		0xff000000
#define PCI_SUBCLASS_MASK 	0x00ff0000
#define PCI_CLASS_BRIDGE 	0x06000000
#define PCI_SUBCLASS_BRIDGE_PCI	0x00040000
	    switch(pcr._class_revision & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
		case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
		    if (pcr._secondary_bus_number > 0) {
		        pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
		    }
			break;
		case PCI_CLASS_BRIDGE:
		    if ( ++hostbridges > 1) {
			pcr._pcibuses[pcr._pcinumbus] = pcr._pcinumbus;
			pcr._pcinumbus++;
		    }
			break;
		default:
			break;
	    }
	    if((func==0) && ((pcr._header_type & PCI_MULTIFUNC_DEV) == 0)) {
	        /* not a multi function device */
		func = 8;
	    } else {
	        func++;
	    }
 
	    if (idx++ >= MAX_PCI_DEVICES)
	        continue;
 
	    identify_card(&pcr);
	  } while( func < 8 );
        }
    } while (++pcr._pcibusidx < pcr._pcinumbus);
    }
 
#if !defined(__alpha__) && !defined(__powerpc__)
    /* Now try pci config 2 probe (deprecated) */
 
    if ((pcr._configtype == 2) || do_mode2_scan) {
    OUTPORT8(PCI_MODE2_ENABLE_REG, 0xF1);
    OUTPORT8(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
 
    /*printf("\nPCI probing configuration type 2\n");*/
 
    pcr._pcibuses[0] = 0;
    pcr._pcinumbus = 1;
    pcr._pcibusidx = 0;
    idx = 0;
 
    do {
        for (pcr._ioaddr = 0xC000; pcr._ioaddr < 0xD000; pcr._ioaddr += 0x0100){
	    OUTPORT8(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
            pcr._device_vendor = INPORT32(pcr._ioaddr);
	    OUTPORT8(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
 
            if ((pcr._vendor == 0xFFFF) || (pcr._device == 0xFFFF))
                continue;
            if ((pcr._vendor == 0xF0F0) || (pcr._device == 0xF0F0))
                continue;  /* catch ASUS P55TP4XE motherboards */
 
	    /*printf("\npci bus 0x%x slot at 0x%04x, vendor 0x%04x device 0x%04x\n",
	        pcr._pcibuses[pcr._pcibusidx], pcr._ioaddr, pcr._vendor,
                pcr._device);*/
	    pcibus = pcr._pcibuses[pcr._pcibusidx] ;
	    pcicard = pcr._ioaddr ; pcifunc = 0 ;
 
	    OUTPORT8(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */
            pcr._status_command = INPORT32(pcr._ioaddr + 0x04);
            pcr._class_revision = INPORT32(pcr._ioaddr + 0x08);
            pcr._bist_header_latency_cache = INPORT32(pcr._ioaddr + 0x0C);
            pcr._base0 = INPORT32(pcr._ioaddr + 0x10);
            pcr._base1 = INPORT32(pcr._ioaddr + 0x14);
            pcr._base2 = INPORT32(pcr._ioaddr + 0x18);
            pcr._base3 = INPORT32(pcr._ioaddr + 0x1C);
            pcr._base4 = INPORT32(pcr._ioaddr + 0x20);
            pcr._base5 = INPORT32(pcr._ioaddr + 0x24);
            pcr._baserom = INPORT32(pcr._ioaddr + 0x30);
            pcr._max_min_ipin_iline = INPORT8(pcr._ioaddr + 0x3C);
            pcr._user_config = INPORT32(pcr._ioaddr + 0x40);
	    OUTPORT8(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */
 
            /* check for pci-pci bridges (currently we only know Digital) */
            if ((pcr._vendor == 0x1011) && (pcr._device == 0x0001))
                if (pcr._secondary_bus_number > 0)
                    pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number;
 
	    if (idx++ >= MAX_PCI_DEVICES)
	        continue;
 
	    identify_card(&pcr);
	}
    } while (++pcr._pcibusidx < pcr._pcinumbus);
 
    OUTPORT8(PCI_MODE2_ENABLE_REG, 0x00);
    }
 
#endif /* __alpha__ */
 
    disable_app_io();
    *num_pci = pcicards;
 
    return 0 ;
 
}
Example #7
0
// 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
}