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

📄 devpccard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/*     cardbus and pcmcia (grmph) support.*/#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"#include "io.h"#define DEBUG	0#pragma	varargck	type	"T"	int#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 */};static int managerstarted;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 char Enocard[] = "No card in slot";enum{	CMdown,	CMpower,};static Cmdtab pccardctlmsg[] ={	CMdown,		"down",	2,	CMpower,	"power",	1,};static int powerup(Cardbus *);static void configure(Cardbus *);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){	if(DEBUG)		print("engine(%ld): %s(%s)\n", 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:			if(DEBUG)				print("#Y%ld: Invalid message %s in SlotEmpty state\n",					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:			if(DEBUG)				print("#Y%ld: Invalid message %s in SlotFull state\n",					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%ld: Invalid message %s in SlotPowered state\n",				cb - cbslots, messages[message]);			break;		}		break;	case SlotConfigured:		switch (message) {		case CardEjected:			cb->state = SlotEmpty;			unconfigure(cb);			powerdown(cb);			break;		default:			if(DEBUG)				print("#Y%ld: Invalid message %s in SlotConfigured state\n",					cb - cbslots, messages[message]);			break;		}		break;	}}static voidqengine(Cardbus *cb, int message){	lock(cb);	engine(cb, message);	unlock(cb);}typedef struct Events Events;struct Events {	Cardbus	*cb;	int	message;};static Lock levents;static Events events[NUMEVENTS];static Rendez revents;static int nevents;static voidiengine(Cardbus *cb, int message){	if (nevents >= NUMEVENTS) {		print("#Y: Too many events queued, discarding request\n");		return;	}	ilock(&levents);	events[nevents].cb = cb;	events[nevents].message = message;	nevents++;	iunlock(&levents);	wakeup(&revents);}static inteventoccured(void){	return nevents > 0;}static voidprocessevents(void *){	while (1) {		int message;		Cardbus *cb;		sleep(&revents, (int (*)(void *))eventoccured, nil);		cb = nil;		message = 0;		ilock(&levents);		if (nevents > 0) {			cb = events[0].cb;			message = events[0].message;			nevents--;			if (nevents > 0)				memmove(events, &events[1], nevents * sizeof(Events));		}		iunlock(&levents);		if (cb)			qengine(cb, message);	}}static voidcbinterrupt(Ureg *, void *){	int i;	for (i = 0; i != nslots; i++) {		Cardbus *cb = &cbslots[i];		ulong event, state;		event = cb->regs[SocketEvent];		if(!(event & (SE_POWER|SE_CCD)))			continue;		state = cb->regs[SocketState];		rdreg(cb, Rcsc);	/* Ack the interrupt */		if(DEBUG)			print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n",				cb - cbslots, event, state, states[cb->state]);		if (event & SE_CCD) {			cb->regs[SocketEvent] |= SE_CCD;	/* Ack interrupt */			if (state & SE_CCD) {				if (cb->state != SlotEmpty) {					print("#Y: take cardejected interrupt\n");					iengine(cb, CardEjected);				}			}			else				iengine(cb, CardDetected);		}		if (event & SE_POWER) {			cb->regs[SocketEvent] |= SE_POWER;	/* Ack interrupt */			iengine(cb, CardPowered);		}	}}voiddevpccardlink(void){	static int initialized;	Pcidev *pci;	int i;	uchar intl;	char *p;	void *baddrva;	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;	intl = (uchar)-1;	while ((pci = pcimatch(pci, 0, 0)) != nil) {		ulong baddr;		Cardbus *cb;		int slot;		uchar pin;		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];		if (pci->vid != TI_vid) {			// Gross hack, needs a fix.  Inherit the mappings from 9load			// for the TIs (pb)			pcicfgw32(pci, PciCBMBR0, 0xffffffff);			pcicfgw32(pci, PciCBMLR0, 0);			pcicfgw32(pci, PciCBMBR1, 0xffffffff);			pcicfgw32(pci, PciCBMLR1, 0);			pcicfgw32(pci, PciCBIBR0, 0xffffffff);			pcicfgw32(pci, PciCBILR0, 0);			pcicfgw32(pci, PciCBIBR1, 0xffffffff);			pcicfgw32(pci, PciCBILR1, 0);		}		// 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%ld: No interrupt?\n", 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 (pci->vid == O2_vid) {			if(DEBUG)				print("writing O2 config\n");			pcicfgw8(cb->pci, 0x94, 0xCA);			pcicfgw8(cb->pci, 0xD4, 0xCA);		}		if (intl != 0xFF && intl != pci->intl)			intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");		intl = pci->intl;		if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;

⌨️ 快捷键说明

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