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

📄 pci.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * the maximum as it's not known how many buses are behind		 * this one; the final value is set on the way back up.		 */		sbn = pcicfgr8(p, PciSBN);		ubn = pcicfgr8(p, PciUBN);		if(sbn == 0 || ubn == 0) {			sbn = maxubn+1;			/*			 * Make sure memory, I/O and master enables are			 * off, set the primary, secondary and subordinate			 * bus numbers and clear the secondary status before			 * attempting to scan the secondary bus.			 *			 * Initialisation of the bridge should be done here.			 */			pcicfgw32(p, PciPCR, 0xFFFF0000);			l = (MaxUBN<<16)|(sbn<<8)|bno;			pcicfgw32(p, PciPBN, l);			pcicfgw16(p, PciSPSR, 0xFFFF);			maxubn = pcilscan(sbn, &p->bridge);			l = (maxubn<<16)|(sbn<<8)|bno;			pcicfgw32(p, PciPBN, l);		}		else {			maxubn = ubn;			pcilscan(sbn, &p->bridge);		}	}	return maxubn;}intpciscan(int bno, Pcidev **list){	int ubn;	qlock(&pcicfginitlock);	ubn = pcilscan(bno, list);	qunlock(&pcicfginitlock);	return ubn;}static voidpcicfginit(void){	char *p;	int bno;	Pcidev **list;	ulong mema, ioa;	qlock(&pcicfginitlock);	if(pcicfgmode != -1)		goto out;	/*	 * Try to determine which PCI configuration mode is implemented.	 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses	 * a DWORD at 0xCF8 and another at 0xCFC and will pass through	 * any non-DWORD accesses as normal I/O cycles. There shouldn't be	 * a device behind these addresses so if Mode2 accesses fail try	 * for Mode1 (which is preferred, Mode2 is deprecated).	 */	outb(PciCSE, 0);	if(inb(PciCSE) == 0){		pcicfgmode = 2;		pcimaxdno = 15;	}	else {		outl(PciADDR, 0);		if(inl(PciADDR) == 0){			pcicfgmode = 1;			pcimaxdno = 31;		}	}		if(pcicfgmode < 0)		goto out;	fmtinstall('T', tbdffmt);	if(p = getconf("*pcimaxbno"))		pcimaxbno = strtoul(p, 0, 0);	if(p = getconf("*pcimaxdno"))		pcimaxdno = strtoul(p, 0, 0);	list = &pciroot;	for(bno = 0; bno <= pcimaxbno; bno++) {		int sbno = bno;		bno = pcilscan(bno, list);		while(*list)			list = &(*list)->link;		if (sbno == 0) {			Pcidev *pci;			/*			  * If we have found a PCI-to-Cardbus bridge, make sure			  * it has no valid mappings anymore.  			  */			pci = pciroot;			while (pci) {				if (pci->ccrb == 6 && pci->ccru == 7) {					ushort bcr;					/* reset the cardbus */					bcr = pcicfgr16(pci, PciBCR);					pcicfgw16(pci, PciBCR, 0x40 | bcr);					delay(50);				}				pci = pci->link;			}		}	}	if(pciroot == nil)		goto out;	/*	 * Work out how big the top bus is	 */	mema = 0;	ioa = 0;	pcibusmap(pciroot, &mema, &ioa, 0);	DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",		mema, pcimask(mema), ioa);	/*	 * Align the windows and map it	 */	ioa = 0x1000;	mema = 0;	pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);	pcibusmap(pciroot, &mema, &ioa, 1);	DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);out:	qunlock(&pcicfginitlock);}static intpcicfgrw8(int tbdf, int rno, int data, int read){	int o, type, x;	if(pcicfgmode == -1)		pcicfginit();	if(BUSBNO(tbdf))		type = 0x01;	else		type = 0x00;	x = -1;	if(BUSDNO(tbdf) > pcimaxdno)		return x;	lock(&pcicfglock);	switch(pcicfgmode){	case 1:		o = rno & 0x03;		rno &= ~0x03;		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);		if(read)			x = inb(PciDATA+o);		else			outb(PciDATA+o, data);		outl(PciADDR, 0);		break;	case 2:		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));		outb(PciFORWARD, BUSBNO(tbdf));		if(read)			x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);		else			outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);		outb(PciCSE, 0);		break;	}	unlock(&pcicfglock);	return x;}intpcicfgr8(Pcidev* pcidev, int rno){	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);}voidpcicfgw8(Pcidev* pcidev, int rno, int data){	pcicfgrw8(pcidev->tbdf, rno, data, 0);}static intpcicfgrw16(int tbdf, int rno, int data, int read){	int o, type, x;	if(pcicfgmode == -1)		pcicfginit();	if(BUSBNO(tbdf))		type = 0x01;	else		type = 0x00;	x = -1;	if(BUSDNO(tbdf) > pcimaxdno)		return x;	lock(&pcicfglock);	switch(pcicfgmode){	case 1:		o = rno & 0x02;		rno &= ~0x03;		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);		if(read)			x = ins(PciDATA+o);		else			outs(PciDATA+o, data);		outl(PciADDR, 0);		break;	case 2:		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));		outb(PciFORWARD, BUSBNO(tbdf));		if(read)			x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);		else			outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);		outb(PciCSE, 0);		break;	}	unlock(&pcicfglock);	return x;}intpcicfgr16(Pcidev* pcidev, int rno){	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);}voidpcicfgw16(Pcidev* pcidev, int rno, int data){	pcicfgrw16(pcidev->tbdf, rno, data, 0);}static intpcicfgrw32(int tbdf, int rno, int data, int read){	int type, x;	if(pcicfgmode == -1)		pcicfginit();	if(BUSBNO(tbdf))		type = 0x01;	else		type = 0x00;	x = -1;	if(BUSDNO(tbdf) > pcimaxdno)		return x;	lock(&pcicfglock);	switch(pcicfgmode){	case 1:		rno &= ~0x03;		outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);		if(read)			x = inl(PciDATA);		else			outl(PciDATA, data);		outl(PciADDR, 0);		break;	case 2:		outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));		outb(PciFORWARD, BUSBNO(tbdf));		if(read)			x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);		else			outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);		outb(PciCSE, 0);		break;	}	unlock(&pcicfglock);	return x;}intpcicfgr32(Pcidev* pcidev, int rno){	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);}voidpcicfgw32(Pcidev* pcidev, int rno, int data){	pcicfgrw32(pcidev->tbdf, rno, data, 0);}Pcidev*pcimatch(Pcidev* prev, int vid, int did){	if(pcicfgmode == -1)		pcicfginit();	if(prev == nil)		prev = pcilist;	else		prev = prev->list;	while(prev != nil){		if((vid == 0 || prev->vid == vid)		&& (did == 0 || prev->did == did))			break;		prev = prev->list;	}	return prev;}Pcidev*pcimatchtbdf(int tbdf){	Pcidev *pcidev;	if(pcicfgmode == -1)		pcicfginit();	for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {		if(pcidev->tbdf == tbdf)			break;	}	return pcidev;}ucharpciipin(Pcidev *pci, uchar pin){	if (pci == nil)		pci = pcilist;	while (pci) {		uchar intl;		if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)			return pci->intl;		if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)			return intl;		pci = pci->list;	}	return 0;}static voidpcilhinv(Pcidev* p){	int i;	Pcidev *t;	if(p == nil) {		putstrn(PCICONS.output, PCICONS.ptr);		p = pciroot;		print("bus dev type vid  did intl memory\n");	}	for(t = p; t != nil; t = t->link) {		print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),			t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);		for(i = 0; i < nelem(p->mem); i++) {			if(t->mem[i].size == 0)				continue;			print("%d:%.8lux %d ", i,				t->mem[i].bar, t->mem[i].size);		}		if(t->ioa.bar || t->ioa.size)			print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);		if(t->mema.bar || t->mema.size)			print("mema:%.8lux %d ", t->mema.bar, t->mema.size);		if(t->bridge)			print("->%d", BUSBNO(t->bridge->tbdf));		print("\n");	}	while(p != nil) {		if(p->bridge != nil)			pcilhinv(p->bridge);		p = p->link;	}	}voidpcihinv(Pcidev* p){	if(pcicfgmode == -1)		pcicfginit();	qlock(&pcicfginitlock);	pcilhinv(p);	qunlock(&pcicfginitlock);}voidpcireset(void){	Pcidev *p;	int pcr;	if(pcicfgmode == -1)		pcicfginit();	for(p = pcilist; p != nil; p = p->list){		pcr = pcicfgr16(p, PciPCR);		pcr &= ~0x0004;		pcicfgw16(p, PciPCR, pcr);	}}voidpcisetbme(Pcidev* p){	int pcr;	pcr = pcicfgr16(p, PciPCR);	pcr |= MASen;	pcicfgw16(p, PciPCR, pcr);}voidpciclrbme(Pcidev* p){	int pcr;	pcr = pcicfgr16(p, PciPCR);	pcr &= ~MASen;	pcicfgw16(p, PciPCR, pcr);}

⌨️ 快捷键说明

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