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

📄 devpccard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (nslots == 0)		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) {			// 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_BADVCC) {		print("#Y%ld: Bad VCC request to card, powering down card!\n", 			 cb - cbslots);		cb->regs[SocketControl] = 0;		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;	}	//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);	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){	Pcidev *pci;	ulong size, bar;	int i, ioindex, memindex, r;	//print("configuring slot %d (%s)\n", (int)(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);	pci = cb->pci->bridge;	while (pci) {		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		 */		memindex = ioindex = 0;		for (i = 0; i != Nbars; i++) {			if (pci->mem[i].size == 0)				continue;			if (pci->mem[i].bar & 1) {				// Allocate I/O space				if (ioindex > 1) {					print("#Y%ld: WARNING: Can only configure 2 I/O slots\n", cb - cbslots);					continue;				}				bar = ioreserve(-1, pci->mem[i].size, 0, "cardbus");				pci->mem[i].bar = bar | 1;				pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), 					          pci->mem[i].bar);				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8, bar);				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 						 bar + pci->mem[i].size - 1);				//print("ioindex[%d] %.8uX (%d)\n", 				//	ioindex, bar, pci->mem[i].size);				ioindex++;				continue;			}			// Allocating memory space			if (memindex > 1) {				print("#Y%ld: WARNING: Can only configure 2 memory slots\n", cb - cbslots);				continue;			}			bar = upamalloc(0, pci->mem[i].size, BY2PG);			pci->mem[i].bar = bar | (pci->mem[i].bar & 0x80);			pcicfgw32(pci, PciBAR0 + i * sizeof(ulong), pci->mem[i].bar);			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, bar);			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 					  bar + pci->mem[i].size - 1);			if (pci->mem[i].bar & 0x80) {				/* Enable prefetch */				r = pcicfgr16(cb->pci, PciBCR);				r |= 1 << (8 + memindex);				pcicfgw16(cb->pci, PciBCR, r);			}			//print("memindex[%d] %.8uX (%d)\n", 			//	  memindex, bar, pci->mem[i].size);			memindex++;		}		if ((size = pcibarsize(pci, PciEBAR0)) > 0) {			if (memindex > 1)				print("#Y%ld: WARNING: Too many memory spaces, not mapping ROM space\n",					cb - cbslots);			else {				pci->rom.bar = upamalloc(0, size, BY2PG);				pci->rom.size = size;				pcicfgw32(pci, PciEBAR0, pci->rom.bar);				pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8,						 pci->rom.bar);				pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 						 pci->rom.bar + pci->rom.size - 1);			}		}		/* 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));		}					pci = pci->list;	}}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) {		// 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)/* && ((ct->irqtype & 0x40)==0 || isa->irq>7)*/)			x |= Clevel;		*p = x;		delay(5);		isaunmap(m);	}	pi->port = isa->port;	pi->irq = isa->irq;	unlock(cb);	print("#Y%d: %s irq %ld, port %lX\n", (int)(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 intxcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr){	PCMmap *m;	Cisdat cis;	int i, l;	uchar *p;	uchar type, link, n, c;	int this, subtype;

⌨️ 快捷键说明

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