henesyinit from p9fd787fda5 years agoHistory
1957 lines · 40.4 KB · C
RawDownload
/*     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" #define ioalloc(addr, len, align, name)	(addr)#define iofree(addr)extern int pciscan(int, Pcidev **);extern ulong pcibarsize(Pcidev *, int); 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 = 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, 	Ricoh_vid = 0x1180,	Ricoh_476_did = 0x0476,	Ricoh_478_did = 0x0478, 	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 {	ushort	r_vid;	ushort	r_did;	char		*r_name;} variant_t; static variant_t variant[] = {{	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",	},}; /* 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, 	Nbars = 6,	Ncmd = 10,	CBIRQ = 9, 	PC16,	PC32,}; enum {	Ti82365,	Tpd6710,	Tpd6720,	Tvg46x,}; static char *chipname[] = {[Ti82365]		"Intel 82365SL",[Tpd6710]	"Cirrus Logic PD6710",[Tpd6720]	"Cirrus Logic PD6720",[Tvg46x]		"Vadem VG-46x",}; /* *  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 {	uchar		*cisbase;	int			cispos;	int			cisskip;	int			cislen;} Cisdat; /* configuration table entry */typedef struct PCMconftab	PCMconftab;struct PCMconftab{	int	index;	ushort	irqs;		/* legal irqs */	uchar	irqtype;	uchar	bit16;		/* true for 16 bit access */	struct {		ulong	start;		ulong	len;	} io[16];	int	nio;	uchar	vpp1;	uchar	vpp2;	uchar	memwait;	ulong	maxwait;	ulong	readywait;	ulong	otherwait;}; typedef struct {	char			pi_verstr[512];		/* Version string */	PCMmap		pi_mmap[4];		/* maps, last is always for the kernel */	ulong		pi_conf_addr;		/* Config address */	uchar		pi_conf_present;	/* Config register present */	int			pi_nctab;			/* In use configuration tables */	PCMconftab	pi_ctab[8];		/* Configuration tables */	PCMconftab	*pi_defctab;		/* Default conftab */ 	int			pi_port;			/* Actual port usage */	int			pi_irq;			/* Actual IRQ usage */} pcminfo_t; #define qlock(i)	{/* nothing to do */;}#define qunlock(i)	{/* nothing to do */;}typedef struct QLock { int r; } QLock; typedef struct {	QLock;	variant_t		*cb_variant;		/* Which CardBus chipset */	Pcidev		*cb_pci;			/* The bridge itself */	ulong		*cb_regs;			/* Cardbus registers */	int			cb_ltype;			/* Legacy type */	int			cb_lindex;		/* Legacy port index address */	int			cb_ldata;			/* Legacy port data address */	int			cb_lbase;			/* Base register for this socket */ 	int			cb_state;			/* Current state of card */	int			cb_type;			/* Type of card */	pcminfo_t	cb_linfo;			/* PCMCIA slot info */ 	int			cb_refs;			/* Number of refs to slot */	QLock		cb_refslock;		/* inc/dev ref lock */} cb_t; static int managerstarted; enum {	Mshift=	12,	Mgran=	(1<<Mshift),	/* granularity of maps */	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */}; static cb_t 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"; static void cbint(Ureg *, void *);static int powerup(cb_t *);static void configure(cb_t *);static void managecard(cb_t *);static void cardmanager(void *);static void eject(cb_t *);static void interrupt(Ureg *, void *);static void powerdown(cb_t *cb);static void unconfigure(cb_t *cb); static void i82365probe(cb_t *cb, int lindex, int ldata);static void i82365configure(cb_t *cb);static PCMmap *isamap(cb_t *cb, ulong offset, int len, int attr);static void isaunmap(PCMmap* m);static uchar rdreg(cb_t *cb, int index);static void wrreg(cb_t *cb, int index, uchar val);static int readc(Cisdat *cis, uchar *x);static void tvers1(cb_t *cb, Cisdat *cis, int );static void tcfig(cb_t *cb, Cisdat *cis, int );static void tentry(cb_t *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(cb_t *cb, int message){	// print("engine(%d): %s(%s)\n", 	//	 (int)(cb - cbslots), states[cb->cb_state], messages[message]);	switch (cb->cb_state) {	case SlotEmpty: 		switch (message) {		case CardDetected:			cb->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->cb_state = SlotPowered;			configure(cb);			break;		case CardEjected:			cb->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->cb_state = SlotConfigured;			break;		case CardEjected:			cb->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->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;	}} static voidqengine(cb_t *cb, int message){	qlock(cb);	engine(cb, message);	qunlock(cb);} typedef struct {	cb_t	*e_cb;	int	e_message;} events_t; static Lock levents;static events_t events[NUMEVENTS];// static Rendez revents;static int nevents; //static void//iengine(cb_t *cb, int message)//{//	if (nevents >= NUMEVENTS) {//		print("#Y: Too many events queued, discarding request\n");//		return;//	}//	ilock(&levents);//	events[nevents].e_cb = cb;//	events[nevents].e_message = message;//	nevents++;//	iunlock(&levents);//	wakeup(&revents);//} static inteventoccured(void){	return nevents > 0;} // static void// processevents(void *)// {//	while (1) {//		int message;//		cb_t *cb;////		sleep(&revents, (int (*)(void *))eventoccured, nil);////		cb = nil;//		message = 0;//		ilock(&levents);//		if (nevents > 0) {//			cb = events[0].e_cb;//			message = events[0].e_message;//			nevents--;//			if (nevents > 0)//				memmove(events, &events[1], nevents * sizeof(events_t));

Lines 1–500 of 1957.