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

📄 rt_pci.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_BYTE),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/int rt_pcibios_write_config_word (unsigned int bus,	unsigned int device_fn, unsigned int where, unsigned short value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_WORD),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/int rt_pcibios_write_config_dword (unsigned int bus,	unsigned int device_fn, unsigned int where, unsigned int value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"		: "=a" (ret)		: "0" (PCIBIOS_WRITE_CONFIG_DWORD),		  "c" (value),		  "b" (bx),		  "D" ((long) where),		  "S" (&pci_indirect));	restore_flags(flags);	return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/static void check_pcibios(void){	unsigned long signature;	unsigned char present_status;	unsigned char major_revision;	unsigned char minor_revision;	unsigned long flags;	int pack;	if ((pcibios_entry = bios32_service(PCI_SERVICE))) {		pci_indirect.address = pcibios_entry;		save_flags(flags);		__asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK			"lcall (%%edi)\n\t"#else			"lcall *(%%edi)\n\t"#endif			"jc 1f\n\t"			"xor %%ah, %%ah\n"			"1:\tshl $8, %%eax\n\t"			"movw %%bx, %%ax"			: "=d" (signature),			  "=a" (pack)			: "1" (PCIBIOS_PCI_BIOS_PRESENT),			  "D" (&pci_indirect)			: "bx", "cx");		restore_flags(flags);		present_status = (pack >> 16) & 0xff;		major_revision = (pack >> 8) & 0xff;		minor_revision = pack & 0xff;		if (present_status || (signature != PCI_SIGNATURE)) {			printf("ERROR: BIOS32 dice PCI BIOS, pero no PCI "				"BIOS????\n");			pcibios_entry = 0;		}#if	DEBUG		if (pcibios_entry) {			printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"				" entrada en %#X\n", major_revision,				minor_revision, pcibios_entry);		}#endif	}}/***************************************************************************************/static void pcibios_init(void){	union bios32 *check;	unsigned char sum;	int i, length;	unsigned long bios32_entry = 0;	/*	  El procedimiento estandar para localizar el directorio de 	  servicios de BIOS32 se tiene que escanear una estructura BIOS32	  valida entre los rangos 0xE0000 0xFFFFF	 */	for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {		if (check->fields.signature != BIOS32_SIGNATURE)			continue;		length = check->fields.length * 16;		if (!length)			continue;		sum = 0;		for (i = 0; i < length ; ++i)			sum += check->chars[i];		if (sum != 0)			continue;		if (check->fields.revision != 0) {			printf("pcibios_init : revision no soportada %d en %#X\n", check->fields.revision,(unsigned int) check);			continue;		}#if	DEBUG		printf("pcibios_init : BIOS32 Service Directory "			"estructura en %#X\n", check);#endif		if (!bios32_entry) {			if (check->fields.entry >= 0x100000) {			  printf("pcibios_init: entrada en la memoria alta\n");				return;			} else {				bios32_entry = check->fields.entry;#if	DEBUG				printf("pcibios_init : BIOS32 Service Directory \nentrada en %#X\n", bios32_entry);#endif				bios32_indirect.address = bios32_entry;			}		}	}	if (bios32_entry)		check_pcibios();}/***************************************************************************************/int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq){        int ret;        __asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi); cld\n\t"#else		"lcall *(%%esi); cld\n\t"#endif                "jc 1f\n\t"                "xor %%ah, %%ah\n"                "1:"                : "=a" (ret)                : "0" (PCIBIOS_SET_PCI_HW_INT),                  "b" ((dev->bus << 8) | dev->devfn),                  "c" ((irq << 8) | (pin + 10)),                  "S" (&pci_indirect));        return !(ret & 0xff00);}#endif	/* CONFIG_PCI_DIRECT no definido *//***************************************************************************************/int rt_pci_set_power_state(struct pci_dev *dev, int state){	int pm;	u16 pmcsr;	/* bound the state we're entering */	if (state > 3) state = 3;	/* Validate current state:	 * Can enter D0 from any state, but if we can only go deeper 	 * to sleep if we're already in a low power state	 */	if (state > 0 && dev->current_state > state)		return -EINVAL;	else if (dev->current_state == state) 		return 0;        /* we're already there */	/* find PCI PM capability in list */	pm = rt_pci_find_capability(dev, PCI_CAP_ID_PM);		/* abort if the device doesn't support PM capabilities */	if (!pm) return -EIO; 	/* check if this device supports the desired state */	if (state == 1 || state == 2) {		u16 pmc;		rt_pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);		if (state == 1 && !(pmc & PCI_PM_CAP_D1)) return -EIO;		else if (state == 2 && !(pmc & PCI_PM_CAP_D2)) return -EIO;	}	/* If we're in D3, force entire word to 0.	 * This doesn't affect PME_Status, disables PME_En, and	 * sets PowerState to 0.	 */	if (dev->current_state >= 3)		pmcsr = 0;	else {		rt_pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;		pmcsr |= state;	}	/* enter specified state */	rt_pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr);	/* Mandatory power management transition delays */	/* see PCI PM 1.1 5.6.1 table 18 */	if(state == 3 || dev->current_state == 3)	{		//set_current_state(TASK_UNINTERRUPTIBLE);		//schedule_timeout(HZ/100);	  rtl_delay(200000);	}	else if(state == 2 || dev->current_state == 2)		rtl_delay(200000);	dev->current_state = state;	return 0;}/** * rt_pci_find_capability - query for devices' capabilities  * @dev: PCI device to query * @cap: capability code * * Tell if a device supports a given PCI capability. * Returns the address of the requested capability structure within the * device's PCI configuration space or 0 in case the device does not * support it.  Possible values for @cap: * *  %PCI_CAP_ID_PM           Power Management  * *  %PCI_CAP_ID_AGP          Accelerated Graphics Port  * *  %PCI_CAP_ID_VPD          Vital Product Data  * *  %PCI_CAP_ID_SLOTID       Slot Identification  * *  %PCI_CAP_ID_MSI          Message Signalled Interrupts * *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap  */int rt_pci_find_capability(struct pci_dev *dev, int cap){	u16 status;	u8 pos, id;	int ttl = 48;	rt_pci_read_config_word(dev, PCI_STATUS, &status);	if (!(status & PCI_STATUS_CAP_LIST))		return 0;	switch (dev->hdr_type) {	case PCI_HEADER_TYPE_NORMAL:	case PCI_HEADER_TYPE_BRIDGE:		rt_pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);		break;	case PCI_HEADER_TYPE_CARDBUS:		rt_pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);		break;	default:		return 0;	}	while (ttl-- && pos >= 0x40) {		pos &= ~3;		rt_pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);		if (id == 0xff)			break;		if (id == cap)			return pos;		rt_pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);	}	return 0;}/***************************************************************************************//* This function only can be called inside init_module                                 *//***************************************************************************************/struct pci_dev * rt_pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from){  return(pci_find_device(vendor, device, from));}/***************************************************************************************//* This function only can be called inside init_module                                 *//***************************************************************************************/int rt_pci_enable_device(struct pci_dev *dev){  return(pci_enable_device(dev));}/***************************************************************************************//**  * rt_pci_restore_state - Restore the saved state of a PCI device * @dev: - PCI device that we're dealing with * @buffer: - saved PCI config space * */int rt_pci_restore_state(struct pci_dev *dev, u32 *buffer){	int i;	if (buffer) {		for (i = 0; i < 16; i++)			rt_pci_write_config_dword(dev,i * 4, buffer[i]);	}	/*	 * otherwise, write the context information we know from bootup.	 * This works around a problem where warm-booting from Windows	 * combined with a D3(hot)->D0 transition causes PCI config	 * header data to be forgotten.	 */		else {		for (i = 0; i < 6; i ++)			rt_pci_write_config_dword(dev,					       PCI_BASE_ADDRESS_0 + (i * 4),					       dev->resource[i].start);		rt_pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);	}	return 0;}

⌨️ 快捷键说明

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