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

📄 pci.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
static voidpcirouting(void){	Slot *e;	Router *r;	int size, i, fn, tbdf;	Pcidev *sbpci, *pci;	uchar *p, pin, irq, link, *map;	// Search for PCI interrupt routing table in BIOS	for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)		if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')			break;	if(p >= (uchar *)KADDR(0xfffff))		return;	r = (Router *)p;	// print("PCI interrupt routing table version %d.%d at %.6uX\n",	// 	r->version[0], r->version[1], (ulong)r & 0xfffff);	tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);	sbpci = pcimatchtbdf(tbdf);	if(sbpci == nil) {		print("pcirouting: Cannot find south bridge %T\n", tbdf);		return;	}	for(i = 0; i != nelem(southbridges); i++)		if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did)			break;	if(i == nelem(southbridges)) {		print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did);		return;	}	southbridge = &southbridges[i];	if(southbridge->get == nil || southbridge->set == nil)		return;	pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0];	size = (r->size[1] << 8)|r->size[0];	for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {		// print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);		// for (i = 0; i != 4; i++) {		// 	uchar *m = &e->maps[i * 3];		// 	print("[%d] %.2uX %.4uX ",		// 		i, m[0], (m[2] << 8)|m[1]);		// }		// print("\n");		for(fn = 0; fn != 8; fn++) {			tbdf = (BusPCI << 24)|(e->bus << 16)|((e->dev | fn) << 8);			pci = pcimatchtbdf(tbdf);			if(pci == nil)				continue;			pin = pcicfgr8(pci, PciINTP);			if(pin == 0 || pin == 0xff) 				continue;			map = &e->maps[(pin - 1) * 3];			link = map[0];			irq = southbridge->get(sbpci, link);			if(irq == 0 || irq == pci->intl)				continue;			if(pci->intl != 0 && pci->intl != 0xFF) {				print("pcirouting: BIOS workaround: %T at pin %d link %d irq %d -> %d\n",					  tbdf, pin, link, irq, pci->intl);				southbridge->set(sbpci, link, pci->intl);				continue;			}			print("pcirouting: %T at pin %d link %d irq %d\n", tbdf, pin, link, irq);			pcicfgw8(pci, PciINTL, irq);			pci->intl = irq;		}	}}static void pcireservemem(void);voidpcibussize(Pcidev *root, ulong *msize, ulong *iosize){	*msize = 0;	*iosize = 0;	pcibusmap(root, msize, iosize, 0);}static voidpcicfginit(void){	char *p;	Pcidev **list;	ulong mema, ioa;	int bno, n, pcibios;	lock(&pcicfginitlock);	if(pcicfgmode != -1)		goto out;	pcibios = 0;	if(getconf("*nobios"))		nobios = 1;	else if(getconf("*pcibios"))		pcibios = 1;	if(getconf("*nopcirouting"))		nopcirouting = 1;	/*	 * 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 Mode1 accesses fail try	 * for Mode2 (Mode2 is deprecated).	 */	if(!pcibios){		/*		 * 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;	fmtinstall('T', tbdffmt);	if(p = getconf("*pcimaxbno")){		n = strtoul(p, 0, 0);		if(n < pcimaxbno)			pcimaxbno = n;	}	if(p = getconf("*pcimaxdno")){		n = strtoul(p, 0, 0);		if(n < pcimaxdno)			pcimaxdno = n;	}	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.  			  */			for(pci = pciroot; pci != nil; pci = pci->link){				if (pci->ccrb == 6 && pci->ccru == 7) {					ushort bcr;					/* reset the cardbus */					bcr = pcicfgr16(pci, PciBCR);					pcicfgw16(pci, PciBCR, 0x40 | bcr);					delay(50);				}			}		}	}	if(pciroot == nil)		goto out;	if(nobios) {		/*		 * Work out how big the top bus is		 */		pcibussize(pciroot, &mema, &ioa);			/*		 * Align the windows and map it		 */		ioa = 0x1000;		mema = 0x90000000;		pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);		pcibusmap(pciroot, &mema, &ioa, 1);		DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);			unlock(&pcicfginitlock);		return;	}	if (!nopcirouting)		pcirouting();out:	pcireservemem();	unlock(&pcicfginitlock);	if(getconf("*pcihinv"))		pcihinv(nil);}static voidpcireservemem(void){	int i;	Pcidev *p;		/*	 * mark all the physical address space claimed by pci devices	 * as in use, so that upaalloc doesn't give it out.	 */	for(p=pciroot; p; p=p->list)		for(i=0; i<nelem(p->mem); i++)			if(p->mem[i].bar && (p->mem[i].bar&1) == 0)				upareserve(p->mem[i].bar&~0x0F, p->mem[i].size);}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();	lock(&pcicfginitlock);	pcilhinv(p);	unlock(&pcicfginitlock);}voidpcireset(void){	Pcidev *p;	if(pcicfgmode == -1)		pcicfginit();	for(p = pcilist; p != nil; p = p->list) {		/* don't mess with the bridges */		if(p->ccrb == 0x06)			continue;		pciclrbme(p);	}}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 + -