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

📄 devpccard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/*     cardbus and pcmcia (grmph) support.*/#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "error.h"#include "io.h"extern int pciscan(int, Pcidev **);int (*_pcmspecial)(char *, ISAConf *);void (*_pcmspecialclose)(int);intpcmspecial(char *idstr, ISAConf *isa){	return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;}voidpcmspecialclose(int a){	if (_pcmspecialclose != nil)		_pcmspecialclose(a);}static ulongioreserve(ulong, int size, int align, char *){	static ulong isaend = 0x400; /*0xfd00*/	ulong ioaddr;	if (align)		isaend = ((isaend + align - 1) / align) * align;	ioaddr = isaend;	isaend += size;	return ioaddr;}#define MAP(x,o)	(Rmap + (x)*0x8 + o)enum {	TI_vid = 0x104c,	TI_1131_did = 0xAC15,	TI_1250_did = 0xAC16,	TI_1450_did = 0xAC1B,	TI_1251A_did = 0xAC1D,	TI_1420_did = 0xAC51,	Ricoh_vid = 0x1180,	Ricoh_475_did = 0x0475,	Ricoh_476_did = 0x0476,	Ricoh_478_did = 0x0478,	O2_vid = 0x1217,	O2_OZ711M3_did = 0x7134,	Nslots = 4,		/* Maximum number of CardBus slots to use */	K = 1024,	M = K * K,	LegacyAddr = 0x3e0,	NUMEVENTS = 10,	TI1131xSC = 0x80,		// system control		TI122X_SC_INTRTIE	= 1 << 29,	TI12xxIM = 0x8c,		// 	TI1131xCC = 0x91,		// card control		TI113X_CC_RIENB = 1 << 7,		TI113X_CC_ZVENABLE = 1 << 6,		TI113X_CC_PCI_IRQ_ENA = 1 << 5,		TI113X_CC_PCI_IREQ = 1 << 4,		TI113X_CC_PCI_CSC = 1 << 3,		TI113X_CC_SPKROUTEN = 1 << 1,		TI113X_CC_IFG = 1 << 0,	TI1131xDC = 0x92,		// device control};typedef struct Variant Variant;struct Variant {	ushort	vid;	ushort	did;	char	*name;};static Variant variant[] = {{	Ricoh_vid,	Ricoh_475_did,	"Ricoh 475 PCI/Cardbus bridge",	},{	Ricoh_vid,	Ricoh_476_did,	"Ricoh 476 PCI/Cardbus bridge",	},{	Ricoh_vid,	Ricoh_478_did,	"Ricoh 478 PCI/Cardbus bridge",	},{	TI_vid,		TI_1131_did,	"TI PCI-1131 Cardbus Controller", },{	TI_vid,		TI_1250_did,	"TI PCI-1250 Cardbus Controller", },{	TI_vid,		TI_1450_did,	"TI PCI-1450 Cardbus Controller", },{	TI_vid,		TI_1251A_did,	"TI PCI-1251A Cardbus Controller", },{	TI_vid,		TI_1420_did,	"TI PCI-1420 Cardbus Controller", },{	O2_vid,		O2_OZ711M3_did,	"O2Micro OZ711M3 MemoryCardBus", },};/* Cardbus registers */enum {	SocketEvent = 0,		SE_CCD = 3 << 1,		SE_POWER = 1 << 3,	SocketMask = 1,	SocketState = 2,		SS_CCD = 3 << 1,		SS_POWER = 1 << 3,		SS_PC16 = 1 << 4,		SS_CBC = 1 << 5,		SS_NOTCARD = 1 << 7,		SS_BADVCC = 1 << 9,		SS_5V = 1 << 10,		SS_3V = 1 << 11,	SocketForce = 3,	SocketControl = 4,		SC_5V = 0x22,		SC_3V = 0x33,};enum {	PciPCR_IO = 1 << 0,	PciPCR_MEM = 1 << 1,	PciPCR_Master = 1 << 2,	PciPMC = 0xa4,	Nbars = 6,	Ncmd = 10,	CBIRQ = 9,	PC16,	PC32,};enum {	Ti82365,	Tpd6710,	Tpd6720,	Tvg46x,};/* *  Intel 82365SL PCIC controller for the PCMCIA or *  Cirrus Logic PD6710/PD6720 which is mostly register compatible */enum{	/*	 *  registers indices	 */	Rid=		0x0,		/* identification and revision */	Ris=		0x1,		/* interface status */	Rpc=	 	0x2,		/* power control */	 Foutena=	 (1<<7),	/*  output enable */	 Fautopower=	 (1<<5),	/*  automatic power switching */	 Fcardena=	 (1<<4),	/*  PC card enable */	Rigc= 		0x3,		/* interrupt and general control */	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */	 Fnotreset=	 (1<<6),	/*  reset if not set */		 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */ 	Rcsc= 		0x4,		/* card status change */	Rcscic= 	0x5,		/* card status change interrupt config */	 Fchangeena=	 (1<<3),	/*  card changed */	 Fbwarnena=	 (1<<1),	/*  card battery warning */	 Fbdeadena=	 (1<<0),	/*  card battery dead */	Rwe= 		0x6,		/* address window enable */	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */	Rio= 		0x7,		/* I/O control */	 Fwidth16=	 (1<<0),	/*  16 bit data width */	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */	 Fzerows=	 (1<<2),	/*  zero wait state */	 Ftiming=	 (1<<3),	/*  timing register to use */	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */	Rmap=		0x10,		/* map 0 */	/*	 *  CL-PD67xx extension registers	 */	Rmisc1=		0x16,		/* misc control 1 */	 F5Vdetect=	 (1<<0),	 Fvcc3V=	 (1<<1),	 Fpmint=	 (1<<2),	 Fpsirq=	 (1<<3),	 Fspeaker=	 (1<<4),	 Finpack=	 (1<<7),	Rfifo=		0x17,		/* fifo control */	 Fflush=	 (1<<7),	/*  flush fifo */	Rmisc2=		0x1E,		/* misc control 2 */	 Flowpow=	 (1<<1),	/*  low power mode */	Rchipinfo=	0x1F,		/* chip information */	Ratactl=	0x26,		/* ATA control */	/*	 *  offsets into the system memory address maps	 */	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */	 F16bit=	 (1<<7),	/*  16-bit wide data path */	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */	Mtophi=		0x3,		/* System mem addr mapping stop high byte */	 Ftimer1=	 (1<<6),	/*  timer set 1 */	Mofflo=		0x4,		/* Card memory offset address low byte */	Moffhi=		0x5,		/* Card memory offset address high byte */	 Fregactive=	 (1<<6),	/*  attribute memory */	/*	 *  configuration registers - they start at an offset in attribute	 *  memory found in the CIS.	 */	Rconfig=	0,	 Creset=	 (1<<7),	/*  reset device */	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */};/* *  read and crack the card information structure enough to set *  important parameters like power *//* cis memory walking */typedef struct Cisdat Cisdat;struct Cisdat {	uchar		*cisbase;	int		cispos;	int		cisskip;	int		cislen;};typedef struct Pcminfo Pcminfo;struct Pcminfo {	char		verstr[512];		/* Version string */	PCMmap		mmap[4];		/* maps, last is always for the kernel */	ulong		conf_addr;		/* Config address */	uchar		conf_present;		/* Config register present */	int		nctab;			/* In use configuration tables */	PCMconftab	ctab[8];		/* Configuration tables */	PCMconftab	*defctab;		/* Default conftab */	int		port;			/* Actual port usage */	int		irq;			/* Actual IRQ usage */};typedef struct Cardbus Cardbus;struct Cardbus {	Lock;	Variant		*variant;		/* Which CardBus chipset */	Pcidev		*pci;			/* The bridge itself */	ulong		*regs;			/* Cardbus registers */	int		ltype;			/* Legacy type */	int		lindex;			/* Legacy port index address */	int		ldata;			/* Legacy port data address */	int		lbase;			/* Base register for this socket */	int		state;			/* Current state of card */	int		type;			/* Type of card */	Pcminfo		linfo;			/* PCMCIA slot info */	int		special;		/* card is allocated to a driver */	int		refs;			/* Number of refs to slot */	Lock		refslock;		/* inc/dev ref lock */};enum {	Mshift=	12,	Mgran=	(1<<Mshift),	/* granularity of maps */	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */};static Cardbus cbslots[Nslots];static int nslots;static ulong exponent[8] = { 	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };static ulong vmant[16] = {	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,};static ulong mantissa[16] = { 	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };static void cbint(Ureg *, void *);static int powerup(Cardbus *);static void configure(Cardbus *);static void managecard(Cardbus *);static void cardmanager(void *);static void eject(Cardbus *);static void interrupt(Ureg *, void *);static void powerdown(Cardbus *cb);static void unconfigure(Cardbus *cb);static void i82365probe(Cardbus *cb, int lindex, int ldata);static void i82365configure(Cardbus *cb);static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);static void isaunmap(PCMmap* m);static uchar rdreg(Cardbus *cb, int index);static void wrreg(Cardbus *cb, int index, uchar val);static int readc(Cisdat *cis, uchar *x);static void tvers1(Cardbus *cb, Cisdat *cis, int );static void tcfig(Cardbus *cb, Cisdat *cis, int );static void tentry(Cardbus *cb, Cisdat *cis, int );static int vcode(int volt);static int pccard_pcmspecial(char *idstr, ISAConf *isa);static void pccard_pcmspecialclose(int slotno);enum {	CardDetected,	CardPowered,	CardEjected,	CardConfigured,};static char *messages[] = {[CardDetected]		"CardDetected",[CardPowered]		"CardPowered",[CardEjected]		"CardEjected",[CardConfigured]	"CardConfigured",};enum {	SlotEmpty,	SlotFull,	SlotPowered,	SlotConfigured,};static char *states[] = {[SlotEmpty]		"SlotEmpty",[SlotFull]		"SlotFull",[SlotPowered]		"SlotPowered",[SlotConfigured]	"SlotConfigured",};static voidengine(Cardbus *cb, int message){	// print("engine(%d): %s(%s)\n", 	//	 (int)(cb - cbslots), states[cb->state], messages[message]);	switch (cb->state) {	case SlotEmpty:		switch (message) {		case CardDetected:			cb->state = SlotFull;			powerup(cb);			break;		case CardEjected:			break;		default:			//print("#Y%d: Invalid message %s in SlotEmpty state\n",			//	(int)(cb - cbslots), messages[message]);			break;		}		break;	case SlotFull:		switch (message) {		case CardPowered:			cb->state = SlotPowered;			configure(cb);			break;		case CardEjected:			cb->state = SlotEmpty;			powerdown(cb);			break;		default:			//print("#Y%d: Invalid message %s in SlotFull state\n",			//	(int)(cb - cbslots), messages[message]);			break;		}		break;	case SlotPowered:		switch (message) {		case CardConfigured:			cb->state = SlotConfigured;			break;		case CardEjected:			cb->state = SlotEmpty;			unconfigure(cb);			powerdown(cb);			break;		default:			print("#Y%d: Invalid message %s in SlotPowered state\n",				(int)(cb - cbslots), messages[message]);			break;		}		break;	case SlotConfigured:		switch (message) {		case CardEjected:			cb->state = SlotEmpty;			unconfigure(cb);			powerdown(cb);			break;		default:			//print("#Y%d: Invalid message %s in SlotConfigured state\n",			//	(int)(cb - cbslots), messages[message]);			break;		}		break;	}}voiddevpccardlink(void){	static int initialized;	Pcidev *pci;	int i;	char *p;	if (initialized) 		return;	initialized = 1;	if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)		return;	if(_pcmspecial)		return;	/* Allocate legacy space */	if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)		print("#Y: WARNING: Cannot allocate legacy ports\n");	/* Find all CardBus controllers */	pci = nil;	while ((pci = pcimatch(pci, 0, 0)) != nil) {		ulong baddr;		uchar pin;		Cardbus *cb;		int slot;		if(pci->ccrb != 6 || pci->ccru != 7)			continue;		for (i = 0; i != nelem(variant); i++)			if (pci->vid == variant[i].vid && pci->did == variant[i].did)				break;		if (i == nelem(variant))			continue;		/* initialize this slot */		slot = nslots++;		cb = &cbslots[slot];		cb->pci = pci;		cb->variant = &variant[i];		// Set up PCI bus numbers if needed.		if (pcicfgr8(pci, PciSBN) == 0) {			static int busbase = 0x20;			pcicfgw8(pci, PciSBN, busbase);			pcicfgw8(pci, PciUBN, busbase + 2);			busbase += 3;		}		// Patch up intl if needed.		if ((pin = pcicfgr8(pci, PciINTP)) != 0 && 		    (pci->intl == 0xff || pci->intl == 0)) {			pci->intl = pciipin(nil, pin);			pcicfgw8(pci, PciINTL, pci->intl);			if (pci->intl == 0xff || pci->intl == 0)				print("#Y%d: No interrupt?\n", (int)(cb - cbslots));		}				// Don't you love standards!		if (pci->vid == TI_vid) {			if (pci->did <= TI_1131_did) {				uchar cc;				cc = pcicfgr8(pci, TI1131xCC);				cc &= ~(TI113X_CC_PCI_IRQ_ENA |						TI113X_CC_PCI_IREQ | 						TI113X_CC_PCI_CSC |						TI113X_CC_ZVENABLE);				cc |= TI113X_CC_PCI_IRQ_ENA | 						TI113X_CC_PCI_IREQ | 						TI113X_CC_SPKROUTEN;				pcicfgw8(pci, TI1131xCC, cc);				// PCI interrupts only				pcicfgw8(pci, TI1131xDC, 						pcicfgr8(pci, TI1131xDC) & ~6);				// CSC ints to PCI bus.				wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);			}			else if (pci->did == TI_1250_did) {				print("No support yet for the TI_1250_did, prod pb\n");			}			else if (pci->did == TI_1420_did) {				// Disable Vcc protection				pcicfgw32(cb->pci, 0x80, 					pcicfgr32(cb->pci, 0x80) | (1 << 21));			}						pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);		}			if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;			baddr = upamalloc(baddr, size, size);			pcicfgw32(cb->pci, PciBAR0, baddr);			cb->regs = (ulong *)KADDR(baddr);		}		else			cb->regs = (ulong *)KADDR(upamalloc(baddr, 4096, 0));		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);	}

⌨️ 快捷键说明

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