示例#1
0
文件: pci.c 项目: Harvey-OS/harvey
int
pcisetpms(Pcidev* p, int state)
{
	int pmc, pmcsr, ptr;

	if((ptr = pcicap(p, PciCapPMG)) == -1)
		return -1;

	pmc = pcicfgr16(p, ptr+Pmgcap);
	pmcsr = pcicfgr16(p, ptr+Pmgctl);

	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;
	}
	pcicfgw16(p, ptr+4, (pmcsr & ~3)  | state);
	return pmcsr & 3;
}
示例#2
0
static uint16_t
cfgget16(uintptr_t p, void* r)
{
	Reg *ro = r;
	Pcidev d;

	d.tbdf = ro->tbdf;
	return pcicfgr16(&d, p);
}
示例#3
0
文件: pci.c 项目: Harvey-OS/harvey
int
pcigetpms(Pcidev* p)
{
	int ptr;

	if((ptr = pcicap(p, PciCapPMG)) == -1)
		return -1;
	return pcicfgr16(p, ptr+Pmgctl) & 0x0003;
}
示例#4
0
static Vdev*
viopnpdevs(int typ)
{
	Vdev *vd, *h, *t;
	Pcidev *p;
	int n, i;

	h = t = nil;
	for(p = nil; p = pcimatch(p, 0, 0);){
		if(p->vid != 0x1AF4)
			continue;
		if((p->did < 0x1000) || (p->did >= 0x1040))
			continue;
		if(p->rid != 0)
			continue;
		if(pcicfgr16(p, 0x2E) != typ)
			continue;
		if((vd = malloc(sizeof(*vd))) == nil){
			print("virtio: no memory for Vdev\n");
			break;
		}
		vd->port = p->mem[0].bar & ~0x1;
		if(ioalloc(vd->port, p->mem[0].size, 0, "virtio") < 0){
			print("virtio: port %lux in use\n", vd->port);
			free(vd);
			continue;
		}
		vd->typ = typ;
		vd->pci = p;

		/* reset */
		outb(vd->port+Status, 0);

		vd->feat = inl(vd->port+Devfeat);
		outb(vd->port+Status, Acknowledge|Driver);
		for(i=0; i<nelem(vd->queue); i++){
			outs(vd->port+Qselect, i);
			n = ins(vd->port+Qsize);
			if(n == 0 || (n & (n-1)) != 0)
				break;
			if((vd->queue[i] = mkvqueue(n)) == nil)
				break;
			coherence();
			outl(vd->port+Qaddr, PADDR(vd->queue[i]->desc)/BY2PG);
		}
		vd->nqueue = i;
	
		if(h == nil)
			h = vd;
		else
			t->next = vd;
		t = vd;
	}

	return h;
}
示例#5
0
文件: devlm78.c 项目: 8l/inferno
/*  figure out what kind of interface we could have */
void
lm78reset(void)
{
	int pcs;
	Pcidev *p;

	lm78.ifc = None;
	p = nil;
	while((p = pcimatch(p, IntelVendID, 0)) != nil){
		switch(p->did){
		/*  these bridges use the PCSC to map the lm78 into port space. */
		/*  for this case the lm78's CS# select is connected to the PIIX's */
		/*  PCS# output and the bottom 3 bits of address are passed to the */
		/*  LM78's A0-A2 inputs. */
		case PiixID:
		case Piix3ID:
			pcs = pcicfgr16(p, PCSC);
			if(pcs & 3) {
				/* already enabled */
				lm78.port = pcs & ~3;
				lm78.ifc = Parallel;
				return;	
			}

			/*  enable the chip, use default address 0x50 */
			pcicfgw16(p, PCSC, 0x50|PCSC8bytes);
			pcs = pcicfgr16(p, PCSC);
			lm78.port = pcs & ~3;
			lm78.ifc = Parallel;
			return;

		/*  this bridge puts the lm78's serial interface on the smbus */
		case Piix4PMID:
			lm78.smbus = piix4smbus();
			if(lm78.smbus == nil)
				continue;
			print("found piix4 smbus, base %lud\n", lm78.smbus->base);
			lm78.ifc = Smbus;
			return;
		}
	}
}
示例#6
0
文件: pci.c 项目: Harvey-OS/harvey
int
pcicapoff(Pcidev *p)
{
	int off;
	/* status register bit 4 has capabilities */
	if((pcicfgr16(p, PciPSR) & 1<<4) == 0)
		return -1;
	switch(pcicfgr8(p, PciHDT) & 0x7f){
	default:
		return -1;
	case 0:				/* etc */
	case 1:				/* pci to pci bridge */
		off = 0x34;
		break;
	case 2:				/* cardbus bridge */
		off = 0x14;
		break;
	}
	return off;
}
示例#7
0
文件: pci.c 项目: Harvey-OS/harvey
static void
pcicfginit(void)
{
	int sbno, bno, n;
	Pcidev **list, *p;

	if(pcicfgmode != -1)
		return;
	lock(&pcicfginitlock);
	if(pcicfgmode != -1){
		unlock(&pcicfginitlock);
		return;
	}

	fmtinstall('T', tbdffmt);

	/*
	 * Try to determine if PCI Mode1 configuration implemented.
	 * (Bits [30:24] of PciADDR must be 0, according to the spec.)
	 * Mode2 won't appear in 64-bit machines.
	 */
	n = inl(PciADDR);
	if(!(n & 0x7F000000)){
		outl(PciADDR, 0x80000000);
		outb(PciADDR+3, 0);
		if(inl(PciADDR) & 0x80000000)
			pcicfgmode = 1;
	}
	outl(PciADDR, n);

	if(pcicfgmode < 0){
		unlock(&pcicfginitlock);
		return;
	}

	list = &pciroot;
	for(bno = 0; bno <= Maxbus; bno++) {
		sbno = bno;
		bno = pcilscan(bno, "0.0.0", list);

		while(*list)
			list = &(*list)->link;
		if(sbno != 0)
			continue;
		/*
		 * If we have found a PCI-to-Cardbus bridge, make sure
		 * it has no valid mappings anymore.
		 */
		for(p = pciroot; p != nil; p = p->link){
			if (p->ccrb == 6 && p->ccru == 7) {
				/* reset the cardbus */
				pcicfgw16(p, PciBCR, 0x40 | pcicfgr16(p, PciBCR));
				delay(50);
			}
		}
	}

	pcireservemem();
	unlock(&pcicfginitlock);

	// Bring the virtio devices live.
	
	virtiosetup();

	//if(getconf("*pcihinv"))
	pcihinv(nil);
}
示例#8
0
文件: pci.c 项目: Harvey-OS/harvey
static int
pcilscan(int bno, char *path, Pcidev** list)
{
	Pcidev *p, *head, *tail;
	int dno, fno, i, hdt, l, maxfno, maxubn, sbn, tbdf, ubn, capoff;

	maxubn = bno;
	head = nil;
	tail = nil;
	for(dno = 0; dno <= Maxdev; dno++){
		maxfno = 0;
		for(fno = 0; fno <= maxfno; fno++){
			/*
			 * For this possible device, form the
			 * bus+device+function triplet needed to address it
			 * and try to read the vendor and device ID.
			 * If successful, allocate a device struct and
			 * start to fill it in with some useful information
			 * from the device's configuration space.
			 */
			tbdf = MKBUS(BusPCI, bno, dno, fno);
			l = pcicfgrw(tbdf, PciVID, 0, Read, 4);
			if(l == 0xFFFFFFFF || l == 0)
				continue;
			p = malloc(sizeof(*p));
			p->caplist = nil;
			p->capidx = nil;
			p->capcnt = 0;
			p->tbdf = tbdf;
			p->vid = l;
			p->did = l>>16;
			p->path = path;

			if(pcilist != nil)
				pcitail->list = p;
			else
				pcilist = p;
			pcitail = p;

			p->pcr = pcicfgr16(p, PciPCR);
			p->rid = pcicfgr8(p, PciRID);
			p->ccrp = pcicfgr8(p, PciCCRp);
			p->ccru = pcicfgr8(p, PciCCRu);
			p->ccrb = pcicfgr8(p, PciCCRb);
			p->cls = pcicfgr8(p, PciCLS);
			p->ltr = pcicfgr8(p, PciLTR);

			p->intl = pcicfgr8(p, PciINTL);
			p->intp = pcicfgr8(p, PciINTP);

			/*
			 * If the device is a multi-function device adjust the
			 * loop count so all possible functions are checked.
			 */
			hdt = pcicfgr8(p, PciHDT);
			if(hdt & 0x80)
				maxfno = Maxfn;

			/*
			 * If appropriate, read the base address registers
			 * and work out the sizes.
			 */
			switch(p->ccrb) {
			default:
				if((hdt & 0x7F) != 0)
					break;
				for(i = 0; i < nelem(p->mem); i++) {
					p->mem[i].bar = pcicfgr32(p, PciBAR0+4*i);
					p->mem[i].size = pcibarsize(p, PciBAR0+4*i);
				}
				break;

			/*
			 * Some virtio-pci devices have ccrb == 0x00, their BARs and
			 * sizes also should be picked here.
			 */

			case 0x05:		/* memory controller */
			case 0x06:		/* bridge device */
				break;
			}

			/*
			 * Try to gather PCI capabilities. If the offset of capabilities
			 * in the config area cannot be found, skip this step. For simplicity,
			 * capabilities will be linked in a LIFO so we don't deal with list
			 * heads and tails.
			 */

			capoff = pcicapoff(p);
			int off = capoff;
			while(capoff != -1) {
				off = pcicfgr8(p, off);
				if((off < 0x40) || (off & 3))
					break;
				off &= ~3;
				Pcicap *c = malloc(sizeof(*c));
				c->dev = p;
				c->link = p->caplist;
				p->caplist = c;
				p->capcnt++;
				c->vndr = pcicfgr8(p, off + PciCapVndr);
				c->caplen = pcicfgr8(p, off + PciCapLen);
				c->type = pcicfgr8(p, off + PciCapType);
				c->bar = pcicfgr8(p, off + PciCapBar);
				c->offset = pcicfgr32(p, off + PciCapOff);
				c->length = pcicfgr32(p, off + PciCapLength);
				off++;
			}

			if(p->capcnt > 0) {
				p->capidx = malloc(p->capcnt * sizeof(Pcicap *));
				Pcicap *pcp = p->caplist;
				for(int pix = 0; ; pix++) {
					p->capidx[pix] = pcp;
					pcp = pcp->link;
					if(pcp == nil)
						break;
				}
			}
			if(head != nil)
				tail->link = p;
			else
				head = p;
			tail = p;
		}
	}

	*list = head;
	for(p = head; p != nil; p = p->link) {
		/*
		 * Find PCI-PCI bridges and recursively descend the tree.
		 */
		if(p->ccrb != 0x06 || p->ccru != 0x04)
			continue;

		/*
		 * If the secondary or subordinate bus number is not
		 * initialised try to do what the PCI BIOS should have
		 * done and fill in the numbers as the tree is descended.
		 * On the way down the subordinate bus number is set to
		 * 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) {
			print("%T: unconfigured bridge\n", p->tbdf);

			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);
			pcicfgw32(p, PciPBN, Maxbus<<16 | sbn<<8 | bno);
			pcicfgw16(p, PciSPSR, 0xFFFF);
			char *bus = mallocz(256, 1);
			snprint(bus, 256, "%s/%d.%d.0", path, BUSBNO(p->tbdf), BUSDNO(p->tbdf));
			maxubn = pcilscan(sbn, bus, &p->bridge);
			pcicfgw32(p, PciPBN, maxubn<<16 | sbn<<8 | bno);
		}
		else {
			/*
			 * You can't go back.
			 * This shouldn't be possible, but the
			 * Iwill DK8-HTX seems to have subordinate
			 * bus numbers which get smaller on the
			 * way down. Need to look more closely at
			 * this.
			 */
			if(ubn > maxubn) {
				maxubn = ubn;
			}
			char *bus = mallocz(256, 1);
			snprint(bus, 256, "%s/%d.%d.0", path, BUSBNO(p->tbdf), BUSDNO(p->tbdf));
			pcilscan(sbn, bus, &p->bridge);
		}
	}

	return maxubn;
}
示例#9
0
文件: uartpci.c 项目: 99years/plan9
static Uart*
uartpcipnp(void)
{
	Pcidev *p;
	char *name;
	int ctlrno, n, subid;
	Uart *head, *tail, *uart;

	/*
	 * Loop through all PCI devices looking for simple serial
	 * controllers (ccrb == 0x07) and configure the ones which
	 * are familiar. All suitable devices are configured to
	 * simply point to the generic i8250 driver.
	 */
	head = tail = nil;
	ctlrno = 0;
	for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
		if(p->ccrb != 0x07 || p->ccru > 2)
			continue;

		switch((p->did<<16)|p->vid){
		default:
			continue;
		case (0x9835<<16)|0x9710:	/* StarTech PCI2S550 */
			uart = uartpci(ctlrno, p, 0, 1, 1843200, "PCI2S550-0");
			if(uart == nil)
				continue;
			uart->next = uartpci(ctlrno, p, 1, 1, 1843200, "PCI2S550-1");
			break;
		case (0x950A<<16)|0x1415:	/* Oxford Semi OX16PCI954 */
			/*
			 * These are common devices used by 3rd-party
			 * manufacturers.
			 * Must check the subsystem VID and DID for correct
			 * match, mostly to get the clock frequency right.
			 */
			subid = pcicfgr16(p, PciSVID);
			subid |= pcicfgr16(p, PciSID)<<16;
			switch(subid){
			default:
				continue;
			case (0x2000<<16)|0x131F:/* SIIG CyberSerial PCIe */
				uart = uartpci(ctlrno, p, 0, 1, 18432000, "CyberSerial-1S");
				if(uart == nil)
					continue;
				break;
			}
			break;
		case (0x9501<<16)|0x1415:	/* Oxford Semi OX16PCI954 */
			/*
			 * These are common devices used by 3rd-party
			 * manufacturers.
			 * Should check the subsystem VID and DID for correct
			 * match, mostly to get the clock frequency right.
			 */
			subid = pcicfgr16(p, PciSVID);
			subid |= pcicfgr16(p, PciSID)<<16;
			switch(subid){
			default:
				continue;
			case (0<<16)|0x1415:	/* StarTech PCI4S550 */
				uart = uartpci(ctlrno, p, 0, 1, 18432000, "PCI4S550-0");
				if(uart == nil)
					continue;
				break;
			}
			break;
		case (0x9050<<16)|0x10B5:	/* Perle PCI-Fast4 series */
		case (0x9030<<16)|0x10B5:	/* Perle Ultraport series */
			/*
			 * These devices consists of a PLX bridge (the above
			 * PCI VID+DID) behind which are some 16C654 UARTs.
			 * Must check the subsystem VID and DID for correct
			 * match.
			 */
			subid = pcicfgr16(p, PciSVID);
			subid |= pcicfgr16(p, PciSID)<<16;
			switch(subid){
			default:
				continue;
			case (0x0011<<16)|0x12E0:	/* Perle PCI-Fast16 */
				n = 16;
				name = "PCI-Fast16";
				break;
			case (0x0021<<16)|0x12E0:	/* Perle PCI-Fast8 */
				n = 8;
				name = "PCI-Fast8";
				break;
			case (0x0031<<16)|0x12E0:	/* Perle PCI-Fast4 */
				n = 4;
				name = "PCI-Fast4";
				break;
			case (0x0021<<16)|0x155F:	/* Perle Ultraport8 */
				n = 8;
				name = "Ultraport8";	/* 16C754 UARTs */
				break;
			}
			uart = uartpci(ctlrno, p, 2, n, 7372800, name);
			if(uart == nil)
				continue;
			break;
		}

		if(head != nil)
			tail->next = uart;
		else
			head = uart;
		for(tail = uart; tail->next != nil; tail = tail->next)
			;
		ctlrno++;
	}

	return head;
}