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

📄 devpccard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
			baddr = upaalloc(size, size);			baddrva = vmap(baddr, size);			pcicfgw32(cb->pci, PciBAR0, baddr);			cb->regs = (ulong *)baddrva;		}		else			cb->regs = (ulong *)vmap(baddr, 4096);		cb->state = SlotEmpty;		/* Don't really know what to do with this... */		i82365probe(cb, LegacyAddr, LegacyAddr + 1);		print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,			 variant[i].name, baddr, pci->intl);	}	if (nslots == 0){		iofree(LegacyAddr);		return;	}	_pcmspecial = pccard_pcmspecial;	_pcmspecialclose = pccard_pcmspecialclose;	for (i = 0; i != nslots; i++) {		Cardbus *cb = &cbslots[i];		if ((cb->regs[SocketState] & SE_CCD) == 0)			engine(cb, CardDetected);	}	delay(500);			/* Allow time for power up */	for (i = 0; i != nslots; i++) {		Cardbus *cb = &cbslots[i];		if (cb->regs[SocketState] & SE_POWER)			engine(cb, CardPowered);		/* Ack and enable interrupts on all events */		//cb->regs[SocketEvent] = cb->regs[SocketEvent];		cb->regs[SocketMask] |= 0xF;		wrreg(cb, Rcscic, 0xC);	}}static intpowerup(Cardbus *cb){	ulong state;	ushort bcr;	state = cb->regs[SocketState];	if (state & SS_PC16) {		if(DEBUG)			print("#Y%ld: Probed a PC16 card, powering up card\n",				cb - cbslots);		cb->type = PC16;		memset(&cb->linfo, 0, sizeof(Pcminfo));		/* power up and unreset, wait's are empirical (???) */		wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);		delay(300);		wrreg(cb, Rigc, 0);		delay(100);		wrreg(cb, Rigc, Fnotreset);		delay(500);//		return 1;	}	if (state & SS_CCD)		return 0;	if (state & SS_NOTCARD) {		print("#Y%ld: No card inserted\n", cb - cbslots);		return 0;	}	if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {		print("#Y%ld: Unsupported voltage, powering down card!\n",			cb - cbslots);		cb->regs[SocketControl] = 0;		return 0;	}	if(DEBUG)		print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,			(state & SS_POWER)? "": "not ",			(state & SS_3V)? 3: (state & SS_5V)? 5: -1);	/* Power up the card	 * and make sure the secondary bus is not in reset.	 */	cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;	delay(50);	bcr = pcicfgr16(cb->pci, PciBCR);	bcr &= ~0x40;	pcicfgw16(cb->pci, PciBCR, bcr);	delay(100);	if (state & SS_PC16)		cb->type = PC16;	else		cb->type = PC32;	return 1;}static voidpowerdown(Cardbus *cb){	ushort bcr;	if (cb->type == PC16) {		wrreg(cb, Rpc, 0);	/* turn off card power */		wrreg(cb, Rwe, 0);	/* no windows */		cb->type = -1;		return;	}	bcr = pcicfgr16(cb->pci, PciBCR);	bcr |= 0x40;	pcicfgw16(cb->pci, PciBCR, bcr);	cb->regs[SocketControl] = 0;	cb->type = -1;}static voidconfigure(Cardbus *cb){	int i, r;	ulong size, bar;	Pcidev *pci;	ulong membase, iobase, memlen, iolen, rombase, romlen;	if(DEBUG)		print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);	if (cb->state == SlotConfigured)		return;	engine(cb, CardConfigured);	delay(50);					/* Emperically established */	if (cb->type == PC16) {		i82365configure(cb);		return;	}	/* Scan the CardBus for new PCI devices */	pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);	/*	 * size the devices on the bus, reserve a minimum for devices arriving later,	 * allow for ROM space, allocate space, and set the cardbus mapping registers	 */	pcibussize(cb->pci->bridge, &memlen, &iolen);	/* TO DO: need initial alignments */	romlen = 0;	for(pci = cb->pci->bridge; pci != nil; pci = pci->list){		size = pcibarsize(pci, PciEBAR0);		if(size > 0){			pci->rom.bar = -1;			pci->rom.size = size;			romlen += size;		}	}	if(iolen < 512)		iolen = 512;	iobase = ioreserve(~0, iolen, 0, "cardbus");	pcicfgw32(cb->pci, PciCBIBR0, iobase);	pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);	pcicfgw32(cb->pci, PciCBIBR1, 0);	pcicfgw32(cb->pci, PciCBILR1, 0);	rombase = memlen;	memlen += romlen;	if(memlen < 1*1024*1024)		memlen = 1*1024*1024;	membase = upaalloc(memlen, 4*1024*1024);	/* TO DO: better alignment */	pcicfgw32(cb->pci, PciCBMBR0, membase);	pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1);	pcicfgw32(cb->pci, PciCBMBR1, 0);	pcicfgw32(cb->pci, PciCBMLR1, 0);//	pcibussize(cb->pci->bridge, &membase, &iobase);	/* now assign them */	rombase += membase;	for(pci = cb->pci->bridge; pci != nil; pci = pci->list){		r = pcicfgr16(pci, PciPCR);		r &= ~(PciPCR_IO|PciPCR_MEM);		pcicfgw16(pci, PciPCR, r);		/*		 * Treat the found device as an ordinary PCI card.		 * It seems that the CIS is not always present in		 * CardBus cards.		 * XXX, need to support multifunction cards		 */		for(i = 0; i < Nbars; i++) {			if(pci->mem[i].size == 0)				continue;			bar = pci->mem[i].bar;			if(bar & 1)				bar += iobase;			else				bar += membase;			pci->mem[i].bar = bar;			pcicfgw32(pci, PciBAR0 + 4*i, bar);			if((bar & 1) == 0){				print("%T mem[%d] %8.8lux %d\n", pci->tbdf, i, bar, pci->mem[i].size);				if(bar & 0x80){	/* TO DO: enable prefetch */					;				}			}		}		if((size = pcibarsize(pci, PciEBAR0)) > 0) {	/* TO DO: can this be done by pci.c? */			pci->rom.bar = rombase;			pci->rom.size = size;			rombase += size;			pcicfgw32(pci, PciEBAR0, pci->rom.bar);		}		/* Set the basic PCI registers for the device */		pci->pcr = pcicfgr16(pci, PciPCR);		pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;		pci->cls = 8;		pci->ltr = 64;		pcicfgw16(pci, PciPCR, pci->pcr);		pcicfgw8(pci, PciCLS, pci->cls);		pcicfgw8(pci, PciLTR, pci->ltr);		if (pcicfgr8(pci, PciINTP)) {			pci->intl = pcicfgr8(cb->pci, PciINTL);			pcicfgw8(pci, PciINTL, pci->intl);			/* Route interrupts to INTA#/B# */			pcicfgw16(cb->pci, PciBCR,					  pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));		}	}}static voidunconfigure(Cardbus *cb){	Pcidev *pci;	int i, ioindex, memindex, r;	if (cb->type == PC16) {		print("#Y%d: Don't know how to unconfigure a PC16 card\n",			 (int)(cb - cbslots));		memset(&cb->linfo, 0, sizeof(Pcminfo));		return;	}	pci = cb->pci->bridge;	if (pci == nil)		return;		/* Not configured */	cb->pci->bridge = nil;	memindex = ioindex = 0;	while (pci) {		Pcidev *_pci;		for (i = 0; i != Nbars; i++) {			if (pci->mem[i].size == 0)				continue;			if (pci->mem[i].bar & 1) {				iofree(pci->mem[i].bar & ~1);				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,						 (ushort)-1);				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);				ioindex++;				continue;			}			upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);			r = pcicfgr16(cb->pci, PciBCR);			r &= ~(1 << (8 + memindex));			pcicfgw16(cb->pci, PciBCR, r);			memindex++;		}		if (pci->rom.bar && memindex < 2) {			upafree(pci->rom.bar & ~0xF, pci->rom.size);			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);			memindex++;		}		_pci = pci->list;		free(_pci);		pci = _pci;	}}static voidi82365configure(Cardbus *cb){	int this;	Cisdat cis;	PCMmap *m;	uchar type, link;	/*	 * Read all tuples in attribute space.	 */	m = isamap(cb, 0, 0, 1);	if(m == 0)		return;	cis.cisbase = KADDR(m->isa);	cis.cispos = 0;	cis.cisskip = 2;	cis.cislen = m->len;	/* loop through all the tuples */	for(;;){		this = cis.cispos;		if(readc(&cis, &type) != 1)			break;		if(type == 0xFF)			break;		if(readc(&cis, &link) != 1)			break;		switch(type){		default:			break;		case 0x15:			tvers1(cb, &cis, type);			break;		case 0x1A:			tcfig(cb, &cis, type);			break;		case 0x1B:			tentry(cb, &cis, type);			break;		}		if(link == 0xFF)			break;		cis.cispos = this + (2+link);	}	isaunmap(m);}/* *  look for a card whose version contains 'idstr' */static intpccard_pcmspecial(char *idstr, ISAConf *isa){	int i, irq;	PCMconftab *ct, *et;	Pcminfo *pi;	Cardbus *cb;	uchar x, we, *p;	cb = nil;	for (i = 0; i != nslots; i++) {		cb = &cbslots[i];		lock(cb);		if (cb->state == SlotConfigured &&		    cb->type == PC16 &&		    !cb->special &&		    strstr(cb->linfo.verstr, idstr))			break;		unlock(cb);	}	if (i == nslots) {		//if(DEBUG)		//	print("#Y: %s not found\n", idstr);		return -1;	}	pi = &cb->linfo;	/* 	  *  configure the PCMslot for IO.  We assume very heavily that we can read 	  *  configuration info from the CIS.  If not, we won't set up correctly. 	  */	irq = isa->irq;	if(irq == 2)		irq = 9;	et = &pi->ctab[pi->nctab];	ct = nil;	for(i = 0; i < isa->nopt; i++){		int index;		char *cp;		if(strncmp(isa->opt[i], "index=", 6))			continue;		index = strtol(&isa->opt[i][6], &cp, 0);		if(cp == &isa->opt[i][6] || index >= pi->nctab) {			unlock(cb);			print("#Y%d: Cannot find index %d in conf table\n",				 (int)(cb - cbslots), index);			return -1;		}		ct = &pi->ctab[index];	}	if(ct == nil){		PCMconftab *t;		/* assume default is right */		if(pi->defctab)			ct = pi->defctab;		else			ct = pi->ctab;		/* try for best match */		if(ct->nio == 0		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){			for(t = pi->ctab; t < et; t++)				if(t->nio				&& t->io[0].start == isa->port				&& ((1<<irq) & t->irqs)){					ct = t;					break;				}		}		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){			for(t = pi->ctab; t < et; t++)				if(t->nio && ((1<<irq) & t->irqs)){					ct = t;					break;				}		}		if(ct->nio == 0){			for(t = pi->ctab; t < et; t++)				if(t->nio){					ct = t;					break;				}		}	}	if(ct == et || ct->nio == 0) {		unlock(cb);		print("#Y%d: No configuration?\n", (int)(cb - cbslots));		return -1;	}	if(isa->port == 0 && ct->io[0].start == 0) {		unlock(cb);		print("#Y%d: No part or start address\n", (int)(cb - cbslots));		return -1;	}	cb->special = 1;	/* taken */	/* route interrupts */	isa->irq = irq;	wrreg(cb, Rigc, irq | Fnotreset | Fiocard);	/* set power and enable device */	x = vcode(ct->vpp1);	wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);	/* 16-bit data path */	if(ct->bit16)		x = Ftiming|Fiocs16|Fwidth16;	else		x = Ftiming;	if(ct->nio == 2 && ct->io[1].start)		x |= x<<4;	wrreg(cb, Rio, x);	/*	 * enable io port map 0	 * the 'top' register value includes the last valid address	 */	if(isa->port == 0)		isa->port = ct->io[0].start;	we = rdreg(cb, Rwe);	wrreg(cb, Riobtm0lo, isa->port);	wrreg(cb, Riobtm0hi, isa->port>>8);	i = isa->port+ct->io[0].len-1;	wrreg(cb, Riotop0lo, i);	wrreg(cb, Riotop0hi, i>>8);	we |= 1<<6;	if(ct->nio == 2 && ct->io[1].start){		wrreg(cb, Riobtm1lo, ct->io[1].start);		wrreg(cb, Riobtm1hi, ct->io[1].start>>8);		i = ct->io[1].start+ct->io[1].len-1;		wrreg(cb, Riotop1lo, i);		wrreg(cb, Riotop1hi, i>>8);		we |= 1<<7;	}	wrreg(cb, Rwe, we);	/* only touch Rconfig if it is present */	if(pi->conf_present & (1<<Rconfig)){		PCMmap *m;		/*  Reset adapter */		m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);		p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);		/* set configuration and interrupt type */		x = ct->index;		if(ct->irqtype & 0x20)			x |= Clevel;		*p = x;		delay(5);		isaunmap(m);	}	pi->port = isa->port;	pi->irq = isa->irq;	unlock(cb);	print("#Y%ld: %s irq %d, port %lX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);	return (int)(cb - cbslots);}static voidpccard_pcmspecialclose(int slotno){	Cardbus *cb = &cbslots[slotno];	wrreg(cb, Rwe, 0);	/* no windows */	cb->special = 0;}static Chan*pccardattach(char *spec){	if (!managerstarted) {		managerstarted = 1;		kproc("cardbus", processevents, nil);	}	return devattach('Y', spec);}enum{	Qdir,	Qctl,	Nents = 1,};#define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))#define TYPE(c)	((ulong)(c->qid.path&0xff))#define QID(s,t)	(((s)<<8)|(t))static intpccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp){	int slotno;	Qid qid;	long len;	int entry;	if(i == DEVDOTDOT){		mkqid(&qid, Qdir, 0, QTDIR);		devdir(c, qid, "#Y", 0, eve, 0555, dp);		return 1;	}	len = 0;	if(i >= Nents * nslots) return -1;	slotno = i / Nents;	entry = i % Nents;	if (entry == 0) {		qid.path = QID(slotno, Qctl);		snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno);	}	else {		/* Entries for memory regions.  I'll implement them when		     needed. (pb) */	}	qid.vers = 0;	qid.type = QTFILE;	devdir(c, qid, up->genbuf, len, eve, 0660, dp);	return 1;}static Walkqid*pccardwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, 0, 0, pccardgen);}static intpccardstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, 0, 0, pccardgen);}static voidincrefp(Cardbus *cb){	lock(&cb->refslock);	cb->refs++;	unlock(&cb->refslock);}static voiddecrefp(Cardbus *cb){	lock(&cb->refslock);	cb->refs--;	unlock(&cb->refslock);}static Chan*pccardopen(Chan *c, int omode){	if (c->qid.type & QTDIR){		if(omode != OREAD)			error(Eperm);	} else		increfp(&cbslots[SLOTNO(c)]);	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;}static voidpccardclose(Chan *c){	if(c->flag & COPEN)		if((c->qid.type & QTDIR) == 0)			decrefp(&cbslots[SLOTNO(c)]);

⌨️ 快捷键说明

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