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

📄 pci.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 3 页
字号:
	pcibus[busind].pb_rreg16= pcii_rreg16;	pcibus[busind].pb_rreg32= pcii_rreg32;	pcibus[busind].pb_wreg16= pcii_wreg16;	pcibus[busind].pb_wreg32= pcii_wreg32;	pcibus[busind].pb_rsts= pcii_rsts;	pcibus[busind].pb_wsts= pcii_wsts;	dstr= pci_dev_name(vid, did);	if (!dstr)		dstr= "unknown device";	if (debug)	{		printf("pci_intel_init: %s (%04X/%04X)\n",			dstr, vid, did);	}	probe_bus(busind);	r= do_isabridge(busind);	if (r != OK)	{		/* Disable all devices for this bus */		for (i= 0; i<nr_pcidev; i++)		{			if (pcidev[i].pd_busind != busind)				continue;			pcidev[i].pd_inuse= 1;		}		return;	}	/* Look for PCI bridges (for AGP) */	do_pcibridge(busind);}/*===========================================================================* *				probe_bus				     * *===========================================================================*/PRIVATE void probe_bus(busind)int busind;{	u32_t dev, func;	u16_t vid, did, sts;	u8_t headt;	u8_t baseclass, subclass, infclass;	int devind;	char *s, *dstr;#if DEBUGprintf("probe_bus(%d)\n", busind);#endif	if (nr_pcidev >= NR_PCIDEV)		panic("PCI","too many PCI devices", nr_pcidev);	devind= nr_pcidev;	for (dev= 0; dev<32; dev++)	{		for (func= 0; func < 8; func++)		{			pcidev[devind].pd_busind= busind;			pcidev[devind].pd_dev= dev;			pcidev[devind].pd_func= func;			pci_attr_wsts(devind, 				PSR_SSE|PSR_RMAS|PSR_RTAS);			vid= pci_attr_r16(devind, PCI_VID);			did= pci_attr_r16(devind, PCI_DID);			headt= pci_attr_r8(devind, PCI_HEADT);			sts= pci_attr_rsts(devind);			if (vid == NO_VID)				break;	/* Nothing here */			if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS))			{				if (qemu_pci)				{					printf(			"pci: ignoring bad value 0x%x in sts for QEMU\n",					sts & (PSR_SSE|PSR_RMAS|PSR_RTAS));				}				else					break;			}			dstr= pci_dev_name(vid, did);			if (debug)			{				if (dstr)				{					printf("%d.%lu.%lu: %s (%04X/%04X)\n",						busind, (unsigned long)dev,						(unsigned long)func, dstr,						vid, did);				}				else				{					printf(		"%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n",						busind, (unsigned long)dev,						(unsigned long)func, vid,						pci_vid_name(vid), did);				}			}			baseclass= pci_attr_r8(devind, PCI_BCR);			subclass= pci_attr_r8(devind, PCI_SCR);			infclass= pci_attr_r8(devind, PCI_PIFR);			s= pci_subclass_name(baseclass, subclass, infclass);			if (!s)				s= pci_baseclass_name(baseclass);			{				if (!s)					s= "(unknown class)";			}			if (debug)			{				printf("\tclass %s (%X/%X/%X)\n", s,					baseclass, subclass, infclass);			}			devind= nr_pcidev;			nr_pcidev++;			pcidev[devind].pd_baseclass= baseclass;			pcidev[devind].pd_subclass= subclass;			pcidev[devind].pd_infclass= infclass;			pcidev[devind].pd_vid= vid;			pcidev[devind].pd_did= did;			pcidev[devind].pd_inuse= 0;			if (nr_pcidev >= NR_PCIDEV)			  panic("PCI","too many PCI devices", nr_pcidev);			devind= nr_pcidev;			if (func == 0 && !(headt & PHT_MULTIFUNC))				break;		}	}}/*===========================================================================* *				do_isabridge				     * *===========================================================================*/PRIVATE int do_isabridge(busind)int busind;{	int unknown_bridge= -1;	int bridge_dev= -1;	int i, j, r, type;	u16_t vid, did;	char *dstr;	j= 0;	/* lint */	vid= did= 0;	/* lint */	for (i= 0; i< nr_pcidev; i++)	{		if (pcidev[i].pd_busind != busind)			continue;		if (pcidev[i].pd_baseclass == 0x06 &&			pcidev[i].pd_subclass == 0x01 &&			pcidev[i].pd_infclass == 0x00)		{			/* ISA bridge. Report if no supported bridge is			 * found.			 */			unknown_bridge= i;		}		vid= pcidev[i].pd_vid;		did= pcidev[i].pd_did;		for (j= 0; pci_isabridge[j].vid != 0; j++)		{			if (pci_isabridge[j].vid != vid)				continue;			if (pci_isabridge[j].did != did)				continue;			if (pci_isabridge[j].checkclass &&				unknown_bridge != i)			{				/* This part of multifunction device is				 * not the bridge.				 */				continue;			}			break;		}		if (pci_isabridge[j].vid)		{			bridge_dev= i;			break;		}	}	if (bridge_dev != -1)	{		dstr= pci_dev_name(vid, did);		if (!dstr)			dstr= "unknown device";		if (debug)		{			printf("found ISA bridge (%04X/%04X) %s\n",				vid, did, dstr);		}		pcibus[busind].pb_isabridge_dev= bridge_dev;		type= pci_isabridge[j].type;		pcibus[busind].pb_isabridge_type= type;		switch(type)		{		case PCI_IB_PIIX:			r= do_piix(bridge_dev);			break;		case PCI_IB_VIA:			r= do_via_isabr(bridge_dev);			break;		case PCI_IB_AMD:			r= do_amd_isabr(bridge_dev);			break;		case PCI_IB_SIS:			r= do_sis_isabr(bridge_dev);			break;		default:			panic("PCI","unknown ISA bridge type", type);		}		return r;	}	if (unknown_bridge == -1)	{		printf("(warning) no ISA bridge found on bus %d", busind);		return 0;	}	printf("(warning) unsupported ISA bridge %04X/%04X for bus %d\n",		pcidev[unknown_bridge].pd_vid,		pcidev[unknown_bridge].pd_did,		busind);	return 0;}/*===========================================================================* *				do_pcibridge				     * *===========================================================================*/PRIVATE void do_pcibridge(busind)int busind;{	int devind, i;	int ind, type;	u16_t vid, did;	u8_t sbusn, baseclass, subclass, infclass;	u32_t t3;	vid= did= 0;	/* lint */	for (devind= 0; devind< nr_pcidev; devind++)	{		if (pcidev[devind].pd_busind != busind)			continue;		vid= pcidev[devind].pd_vid;		did= pcidev[devind].pd_did;		for (i= 0; pci_pcibridge[i].vid != 0; i++)		{			if (pci_pcibridge[i].vid != vid)				continue;			if (pci_pcibridge[i].did != did)				continue;			break;		}		if (pci_pcibridge[i].vid == 0)		{			if (debug)			{				/* Report unsupported bridges */				baseclass= pci_attr_r8(devind, PCI_BCR);				subclass= pci_attr_r8(devind, PCI_SCR);				infclass= pci_attr_r8(devind, PCI_PIFR);				t3= ((baseclass << 16) | (subclass << 8) |					infclass);				if (t3 != PCI_T3_PCI2PCI &&					t3 != PCI_T3_PCI2PCI_SUBTR)				{					/* No a PCI-to-PCI bridge */					continue;				}				printf(			"Ignoring unknown PCI-to-PCI bridge: %04X/%04X\n",					vid, did);			}			continue;		}		type= pci_pcibridge[i].type;		if (debug)			printf("PCI-to-PCI bridge: %04X/%04X\n", vid, did);		/* Assume that the BIOS initialized the secondary bus		 * number.		 */		sbusn= pci_attr_r8(devind, PPB_SBUSN);#if DEBUG		printf("sbusn = %d\n", sbusn);#endif		if (nr_pcibus >= NR_PCIBUS)			panic("PCI","too many PCI busses", nr_pcibus);		ind= nr_pcibus;		nr_pcibus++;		pcibus[ind].pb_type= PBT_PCIBRIDGE;		pcibus[ind].pb_isabridge_dev= -1;		pcibus[ind].pb_isabridge_type= 0;		pcibus[ind].pb_devind= devind;		pcibus[ind].pb_bus= sbusn;		pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8;		pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16;		pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32;		pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16;		pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32;		switch(type)		{		case PCI_PCIB_INTEL:		case PCI_AGPB_INTEL:			pcibus[ind].pb_rsts= pcibr_intel_rsts;			pcibus[ind].pb_wsts= pcibr_intel_wsts;			break;		case PCI_AGPB_VIA:			pcibus[ind].pb_rsts= pcibr_via_rsts;			pcibus[ind].pb_wsts= pcibr_via_wsts;			break;		default:		    panic("PCI","unknown PCI-PCI bridge type", type);		}		probe_bus(ind);	}}/*===========================================================================* *				do_piix					     * *===========================================================================*/PRIVATE int do_piix(devind)int devind;{	int i, s, dev, func, irqrc, irq;	u16_t elcr1, elcr2, elcr;#if DEBUG	printf("in piix\n");#endif	dev= pcidev[devind].pd_dev;	func= pcidev[devind].pd_func;#if USER_SPACE	if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1)))		printf("Warning, sys_inb failed: %d\n", s);	if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2)))		printf("Warning, sys_inb failed: %d\n", s);#else	elcr1= inb(PIIX_ELCR1);	elcr2= inb(PIIX_ELCR2);#endif	elcr= elcr1 | (elcr2 << 8);	for (i= 0; i<4; i++)	{		irqrc= pci_attr_r8(devind, PIIX_PIRQRCA+i);		if (irqrc & PIIX_IRQ_DI)		{			if (debug)				printf("INT%c: disabled\n", 'A'+i);		}		else		{			irq= irqrc & PIIX_IRQ_MASK;			if (debug)				printf("INT%c: %d\n", 'A'+i, irq);			if (!(elcr & (1 << irq)))			{				if (debug)				{					printf(				"(warning) IRQ %d is not level triggered\n", 						irq);				}			}			irq_mode_pci(irq);		}	}	return 0;}/*===========================================================================* *				do_amd_isabr				     * *===========================================================================*/PRIVATE int do_amd_isabr(devind)int devind;{	int i, bus, dev, func, xdevind, irq, edge;	u8_t levmask;	u16_t pciirq;	/* Find required function */	func= AMD_ISABR_FUNC;	bus= pcidev[devind].pd_busind;	dev= pcidev[devind].pd_dev;	/* Fake a device with the required function */	if (nr_pcidev >= NR_PCIDEV)		panic("PCI","too many PCI devices", nr_pcidev);	xdevind= nr_pcidev;	pcidev[xdevind].pd_busind= bus;	pcidev[xdevind].pd_dev= dev;	pcidev[xdevind].pd_func= func;	pcidev[xdevind].pd_inuse= 1;	nr_pcidev++;	levmask= pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV);	pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE);	for (i= 0; i<4; i++)	{		edge= (levmask >> i) & 1;		irq= (pciirq >> (4*i)) & 0xf;		if (!irq)		{			if (debug)				printf("INT%c: disabled\n", 'A'+i);		}		else		{			if (debug)				printf("INT%c: %d\n", 'A'+i, irq);			if (edge && debug)			{				printf(				"(warning) IRQ %d is not level triggered\n",					irq);			}			irq_mode_pci(irq);		}	}	nr_pcidev--;	return 0;}/*===========================================================================* *				do_sis_isabr				     * *===========================================================================*/PRIVATE int do_sis_isabr(devind)int devind;{

⌨️ 快捷键说明

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