⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci-scan.c

📁 ADTEK RTK8189C Linux 2.4.X Driver
💻 C
📖 第 1 页 / 共 2 页
字号:
	int pci_index, cards_found = 0;
	unsigned char pci_bus, pci_device_fn;
	struct pci_dev *pdev;
	struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl;
	void *newdev;

	if ( ! pcibios_present())
		return -ENODEV;

	for (pci_index = 0; pci_index < 0xff; pci_index++) {
		u32 pci_id, subsys_id, pci_class_rev;
		u16 pci_command, new_command;
		int chip_idx, irq, pci_flags;
		long pciaddr;
		long ioaddr;
		u32 pci_busaddr;
		u8 pci_irq_line;

		if (pcibios_find_class (drv_id->pci_class, pci_index,
								&pci_bus, &pci_device_fn)
			!= PCIBIOS_SUCCESSFUL)
			break;
		pcibios_read_config_dword(pci_bus, pci_device_fn,
								  PCI_VENDOR_ID, &pci_id);
		/* Offset 0x2c is PCI_SUBSYSTEM_ID aka PCI_SUBSYSTEM_VENDOR_ID. */
		pcibios_read_config_dword(pci_bus, pci_device_fn, 0x2c, &subsys_id);
		pcibios_read_config_dword(pci_bus, pci_device_fn,
								  PCI_REVISION_ID, &pci_class_rev);

		for (chip_idx = 0; pci_tbl[chip_idx].name; chip_idx++) {
			struct pci_id_info *chip = &pci_tbl[chip_idx];
			if ((pci_id & chip->id.pci_mask) == chip->id.pci
				&& (subsys_id & chip->id.subsystem_mask) == chip->id.subsystem
				&& (pci_class_rev&chip->id.revision_mask) == chip->id.revision)
				break;
		}
		if (pci_tbl[chip_idx].name == 0) 		/* Compiled out! */
			continue;

		pci_flags = pci_tbl[chip_idx].pci_flags;
		pdev = pci_find_slot(pci_bus, pci_device_fn);
		pcibios_read_config_byte(pci_bus, pci_device_fn,
								 PCI_INTERRUPT_LINE, &pci_irq_line);
		irq = pci_irq_line;
		pcibios_read_config_dword(pci_bus, pci_device_fn,
								  ((pci_flags >> 2) & 0x1C) + 0x10,
								  &pci_busaddr);
		pciaddr = pci_busaddr;
#if defined(__alpha__)
		if (pci_flags & PCI_ADDR_64BITS) {
			pcibios_read_config_dword(pci_bus, pci_device_fn,
									  ((pci_flags >> 2) & 0x1C) + 0x14,
									  &pci_busaddr);
			pciaddr |= ((long)pci_busaddr)<<32;
		}
#endif

		if (debug > 2)
			printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
				   pci_tbl[chip_idx].name, pciaddr, irq);

		if ( ! (pci_flags & PCI_UNUSED_IRQ)  &&
			 (irq == 0 || irq == 255)) {
			if (pci_bus == 32) 	/* Broken CardBus activation. */
				printk(KERN_WARNING "Resources for CardBus device '%s' have"
					   " not been allocated.\n"
					   KERN_WARNING "It will not be activated.\n",
					   pci_tbl[chip_idx].name);
			else
				printk(KERN_WARNING "PCI device '%s' was not assigned an "
					   "IRQ.\n"
					   KERN_WARNING "It will not be activated.\n",
				   pci_tbl[chip_idx].name);
			continue;
		}

		if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) {
			ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;
			if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
				continue;
		} else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,
										   pci_tbl[chip_idx].io_size)) == 0) {
			printk(KERN_INFO "Failed to map PCI address %#lx.\n",
				   pciaddr);
			continue;
		}

		if ( ! (pci_flags & PCI_NO_ACPI_WAKE))
			acpi_wake(pdev);
		pcibios_read_config_word(pci_bus, pci_device_fn,
								 PCI_COMMAND, &pci_command);
		new_command = pci_command | (pci_flags & 7);
		if (pci_command != new_command) {
			printk(KERN_INFO "  The PCI BIOS has not enabled the"
				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
				   pci_bus, pci_device_fn, pci_command, new_command);
			pcibios_write_config_word(pci_bus, pci_device_fn,
									  PCI_COMMAND, new_command);
		}

		newdev = drv_id->probe1(pdev, initial_device,
							   ioaddr, irq, chip_idx, cards_found);

		if (newdev  && (pci_flags & PCI_COMMAND_MASTER)  &&
			! (pci_flags & PCI_NO_MIN_LATENCY)) {
			u8 pci_latency;
			pcibios_read_config_byte(pci_bus, pci_device_fn,
									 PCI_LATENCY_TIMER, &pci_latency);
			if (pci_latency < min_pci_latency) {
				printk(KERN_INFO "  PCI latency timer (CFLT) is "
					   "unreasonably low at %d.  Setting to %d clocks.\n",
					   pci_latency, min_pci_latency);
				pcibios_write_config_byte(pci_bus, pci_device_fn,
										  PCI_LATENCY_TIMER, min_pci_latency);
			}
		}
		if (newdev) {
			struct dev_info *devp =
				kmalloc(sizeof(struct dev_info), GFP_KERNEL);
			if (devp) {
				devp->next = dev_list;
				devp->dev = newdev;
				devp->drv_id = drv_id;
				dev_list = devp;
			}
		}
		initial_device = 0;
		cards_found++;
	}

	if (((drv_id->flags & PCI_HOTSWAP)
		 && register_cb_hook && (*register_cb_hook)(drv_id) == 0)
		|| cards_found) {
		MOD_INC_USE_COUNT;
		drv_id->next = drv_list;
		drv_list = drv_id;
		return 0;
	} else
		return cards_found ? 0 : -ENODEV;
}
#endif

void pci_drv_unregister(struct drv_id_info *drv_id)
{
	struct drv_id_info **drvp;
	struct dev_info **devip = &dev_list;

	if (unregister_cb_hook)
		(*unregister_cb_hook)(drv_id);

	for (drvp = &drv_list; *drvp; drvp = &(*drvp)->next)
		if (*drvp == drv_id) {
			*drvp = (*drvp)->next;
			MOD_DEC_USE_COUNT;
			break;
		}
	while (*devip) {
		struct dev_info *thisdevi = *devip;
		if (thisdevi->drv_id == drv_id) {
			*devip = thisdevi->next;
			kfree(thisdevi);
		} else
			devip = &(*devip)->next;
	}

	return;
}

/*
  Search PCI configuration space for the specified capability registers.
  Return the index, or 0 on failure.
*/
int pci_find_capability(struct pci_dev *pdev, int findtype)
{
	u16 pci_status, cap_type;
	u8 pci_cap_idx;
	int cap_idx;

	pci_read_config_word(pdev, PCI_STATUS, &pci_status);
	if ( ! (pci_status & PCI_STATUS_CAP_LIST))
		return 0;
	pci_read_config_byte(pdev, PCI_CAPABILITY_LIST, &pci_cap_idx);
	cap_idx = pci_cap_idx;
	for (cap_idx = pci_cap_idx; cap_idx; cap_idx = (cap_type >> 8) & 0xff) {
		pci_read_config_word(pdev, cap_idx, &cap_type);
		if ((cap_type & 0xff) == findtype)
			return cap_idx;
	}
	return 0;
}


/* Change a device from D3 (sleep) to D0 (active).
   Return the old power state.
   This is more complicated than you might first expect since most cards
   forget all PCI config info during the transition! */
int acpi_wake(struct pci_dev *pdev)
{
	u32 base[5], romaddr;
	u16 pci_command, pwr_command;
	u8  pci_latency, pci_cacheline, irq;
	int i, pwr_cmd_idx = pci_find_capability(pdev, PCI_CAP_ID_PM);

	if (pwr_cmd_idx == 0)
		return 0;
	pci_read_config_word(pdev, pwr_cmd_idx + 4, &pwr_command);
	if ((pwr_command & 3) == 0)
		return 0;
	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
	for (i = 0; i < 5; i++)
		pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + i*4,
								  &base[i]);
	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr);
	pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency);
	pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
	pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq);

	pci_write_config_word(pdev, pwr_cmd_idx + 4, 0x0000);
	for (i = 0; i < 5; i++)
		if (base[i])
			pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0 + i*4,
									   base[i]);
	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr);
	pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq);
	pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
	pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency);
	pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5);
	return pwr_command & 3;
}

int acpi_set_pwr_state(struct pci_dev *pdev, enum acpi_pwr_state new_state)
{
	u16 pwr_command;
	int pwr_cmd_idx = pci_find_capability(pdev, PCI_CAP_ID_PM);

	if (pwr_cmd_idx == 0)
		return 0;
	pci_read_config_word(pdev, pwr_cmd_idx + 4, &pwr_command);
	if ((pwr_command & 3) == ACPI_D3  &&  new_state != ACPI_D3)
		acpi_wake(pdev);		/* The complicated sequence. */
	pci_write_config_word(pdev, pwr_cmd_idx + 4,
							  (pwr_command & ~3) | new_state);
	return pwr_command & 3;
}

#ifdef MODULE
int init_module(void)
{
	return 0;
}
void cleanup_module(void)
{
	if (dev_list != NULL)
		printk(KERN_WARNING "pci-scan: Unfreed device references.\n");
	return;
}
#endif


/*
 * Local variables:
 *  compile-command: "gcc -DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -Wall -Wstrict-prototypes -O6 -c pci-scan.c"
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -