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

📄 pci.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * a device behind these addresses so if Mode1 accesses fail try	 * for Mode2 (Mode2 is deprecated).	 */	/*	 * Bits [30:24] of PciADDR must be 0,	 * according to the spec.	 */	n = inl(PciADDR);	if(!(n & 0x7FF00000)){		outl(PciADDR, 0x80000000);		outb(PciADDR+3, 0);		if(inl(PciADDR) & 0x80000000){			pcicfgmode = 1;			pcimaxdno = 31;		}	}	outl(PciADDR, n);	if(pcicfgmode < 0){		/*		 * The 'key' part of PciCSE should be 0.		 */		n = inb(PciCSE);		if(!(n & 0xF0)){			outb(PciCSE, 0x0E);			if(inb(PciCSE) == 0x0E){				pcicfgmode = 2;				pcimaxdno = 15;			}		}		outb(PciCSE, n);	}	if(pcicfgmode < 0)		goto out;	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++) {		bno = pciscan(bno, list);		while(*list)			list = &(*list)->link;	}	pcirouting();out:	unlock(&pcicfginitlock);	if(getconf("*pcihinv"))		pcihinv(nil);}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;}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 ushortpciimask(Pcidev *pci){	ushort imask;	imask = 0;	while (pci) {		if (pcicfgr8(pci, PciINTP) && pci->intl < 16)			imask |= 1 << pci->intl;		if (pci->bridge)			imask |= pciimask(pci->bridge);		pci = pci->list;	}	return imask;}ucharpciintl(Pcidev *pci){	ushort imask;	int i;	if (pci == nil)		pci = pcilist;	imask = pciimask(pci) | 1;	for (i = 0; i != 16; i++)		if ((imask & (1 << i)) == 0)			return i;	return 0;}voidpcihinv(Pcidev* p){	int i;	Pcidev *t;	if(pcicfgmode == -1)		pcicfginit();	if(p == nil) {		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);		}		print("\n");	}	while(p != nil) {		if(p->bridge != nil)			pcihinv(p->bridge);		p = p->link;	}}voidpcireset(void){	Pcidev *p;	int pcr;	if(pcicfgmode == -1)		pcicfginit();	for(p = pcilist; p != nil; p = p->list){		pcr = pcicfgr16(p, PciPSR);		pcicfgw16(p, PciPSR, pcr & ~0x04);	}}voidpcisetioe(Pcidev* p){	p->pcr |= IOen;	pcicfgw16(p, PciPCR, p->pcr);}voidpciclrioe(Pcidev* p){	p->pcr &= ~IOen;	pcicfgw16(p, PciPCR, p->pcr);}voidpcisetbme(Pcidev* p){	p->pcr |= MASen;	pcicfgw16(p, PciPCR, p->pcr);}voidpciclrbme(Pcidev* p){	p->pcr &= ~MASen;	pcicfgw16(p, PciPCR, p->pcr);}voidpcisetmwi(Pcidev* p){	p->pcr |= MemWrInv;	pcicfgw16(p, PciPCR, p->pcr);}voidpciclrmwi(Pcidev* p){	p->pcr &= ~MemWrInv;	pcicfgw16(p, PciPCR, p->pcr);}static intpcigetpmrb(Pcidev* p){	int ptr;	if(p->pmrb != 0)		return p->pmrb;	p->pmrb = -1;	/*	 * If there are no extended capabilities implemented,	 * (bit 4 in the status register) assume there's no standard	 * power management method.	 * Find the capabilities pointer based on PCI header type.	 */	if(!(pcicfgr16(p, PciPSR) & 0x0010))		return -1;	switch(pcicfgr8(p, PciHDT)){	default:		return -1;	case 0:					/* all other */	case 1:					/* PCI to PCI bridge */		ptr = 0x34;		break;	case 2:					/* CardBus bridge */		ptr = 0x14;		break;	}	ptr = pcicfgr32(p, ptr);	while(ptr != 0){		/*		 * Check for validity.		 * Can't be in standard header and must be double		 * word aligned.		 */		if(ptr < 0x40 || (ptr & ~0xFC))			return -1;		if(pcicfgr8(p, ptr) == 0x01){			p->pmrb = ptr;			return ptr;		}		ptr = pcicfgr8(p, ptr+1);	}	return -1;}intpcigetpms(Pcidev* p){	int pmcsr, ptr;	if((ptr = pcigetpmrb(p)) == -1)		return -1;	/*	 * Power Management Register Block:	 *  offset 0:	Capability ID	 *	   1:	next item pointer	 *	   2:	capabilities	 *	   4:	control/status	 *	   6:	bridge support extensions	 *	   7:	data	 */	pmcsr = pcicfgr16(p, ptr+4);	return pmcsr & 0x0003;}intpcisetpms(Pcidev* p, int state){	int ostate, pmc, pmcsr, ptr;	if((ptr = pcigetpmrb(p)) == -1)		return -1;	pmc = pcicfgr16(p, ptr+2);	pmcsr = pcicfgr16(p, ptr+4);	ostate = pmcsr & 0x0003;	pmcsr &= ~0x0003;	switch(state){	default:		return -1;	case 0:		break;	case 1:		if(!(pmc & 0x0200))			return -1;		break;	case 2:		if(!(pmc & 0x0400))			return -1;		break;	case 3:		break;	}	pmcsr |= state;	pcicfgw16(p, ptr+4, pmcsr);	return ostate;}

⌨️ 快捷键说明

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