plan 9 kernel history: overview | file list | diff list

1995/0117/pc/devi82365.c (diff list | history)

1994/1209/sys/src/9/pc/devi82365.c:316,3221994/1210/sys/src/9/pc/devi82365.c:316,324 (short | long)
1994/1209    
 
		/* grab ISA address space for memory maps */ 
		for(i = 0; i < Nmap; i++) 
			pp->mmap[i].isa = isamem(Mchunk); 
1994/1210    
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); 
		if(pp->mmap[i].isa == 0) 
			panic("getmap"); 
1994/1209    
	} 
 
	/* look for a map that starts in the right place */ 
1994/1210/sys/src/9/pc/devi82365.c:845,8531994/1211/sys/src/9/pc/devi82365.c:845,850 (short | long)
1994/1209    
static int 
readc(Slot *pp, uchar *x) 
{ 
	uchar l, r; 
	ushort s; 
                 
	if(pp->cispos > pp->cisbase + Mchunk) 
		return 0; 
 
1994/1211/sys/src/9/pc/devi82365.c:264,2741995/0107/sys/src/9/pc/devi82365.c:264,277 (short | long)
1994/1209    
static void 
slotdis(Slot *pp) 
{ 
1995/0107    
	int x; 
 
1994/1209    
	/* disable the windows into the card */ 
	wrreg(pp, Rwe, 0); 
 
	/* disable the card */ 
	wrreg(pp, Rpc, 5|Fautopower); 
1995/0107    
	x = vcode(5) | (vcode(5)<<2); 
	wrreg(pp, Rpc, x|Fautopower); 
1994/1209    
	pp->enabled = 0; 
} 
 
1995/0107/sys/src/9/pc/devi82365.c:712,7171995/0108/sys/src/9/pc/devi82365.c:712,723 (short | long)
1994/1209    
	return n; 
} 
 
1995/0108    
Block* 
i82365bread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1994/1209    
long 
pcmwrite(int dev, int attr, void *a, long n, ulong offset) 
{ 
1995/0107/sys/src/9/pc/devi82365.c:762,7671995/0108/sys/src/9/pc/devi82365.c:768,779
1994/1209    
		error(Ebadusefd); 
	} 
	return n; 
1995/0108    
} 
 
long 
i82365bwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1994/1209    
} 
 
/* 
1995/0108/sys/src/9/pc/devi82365.c:151,1561995/0111/sys/src/9/pc/devi82365.c:151,157 (short | long)
1994/1209    
	uchar	busy; 
 
	/* cis info */ 
1995/0111    
	uchar	verstr[512];	/* version string */ 
1994/1209    
	uchar	vpp1; 
	uchar	vpp2; 
	uchar	bit16; 
1995/0108/sys/src/9/pc/devi82365.c:379,3851995/0111/sys/src/9/pc/devi82365.c:380,386
1994/1209    
	qunlock(pp->cp); 
} 
 
int 
1995/0111    
char* 
1994/1209    
pcmspecial(int dev) 
{ 
	Slot *pp; 
1995/0108/sys/src/9/pc/devi82365.c:386,4021995/0111/sys/src/9/pc/devi82365.c:387,403
1994/1209    
 
	i82365reset(); 
	if(dev >= nslot) 
		return -1; 
1995/0111    
		return 0; 
1994/1209    
	pp = slot + dev; 
	if(pp->special) 
		return -1; 
1995/0111    
		return 0; 
1994/1209    
	increfp(pp); 
	if(!pp->occupied){ 
		decrefp(pp); 
		return -1; 
1995/0111    
		return 0; 
1994/1209    
	} 
	pp->special = 1; 
	return 0; 
1995/0111    
	return pp->verstr; 
1994/1209    
} 
 
void 
1995/0108/sys/src/9/pc/devi82365.c:850,8581995/0111/sys/src/9/pc/devi82365.c:851,861
1994/1209    
 */ 
static void	tcfig(Slot*, int); 
static void	tentry(Slot*, int); 
1995/0111    
static void	tvers1(Slot*, int); 
1994/1209    
 
static void (*parse[256])(Slot*, int) = 
{ 
1995/0111    
[0x15]	tvers1, 
1994/1209    
[0x1A]	tcfig, 
[0x1B]	tentry, 
}; 
1995/0108/sys/src/9/pc/devi82365.c:1158,11611995/0111/sys/src/9/pc/devi82365.c:1161,1187
1994/1209    
		break; 
	} 
	pp->configed++; 
1995/0111    
} 
 
void 
tvers1(Slot *pp, int ttype) 
{ 
	uchar c, major, minor; 
	int  i; 
 
	USED(ttype); 
	if(readc(pp, &major) != 1) 
		return; 
	if(readc(pp, &minor) != 1) 
		return; 
	for(i = 0; i < sizeof(pp->verstr)-1; i++){ 
		if(readc(&c) != 1) 
			return; 
		if(c == 0) 
			c = '\n'; 
		if(c == 0xff) 
			break; 
		pp->verstr[i] = c; 
	} 
	pp->verstr[i] = 0; 
1994/1209    
} 
1995/0111/sys/src/9/pc/devi82365.c:1059,10811995/0114/sys/src/9/pc/devi82365.c:1059,1079 (short | long)
1994/1209    
	int i; 
	ulong address, len; 
 
	for(;;){ 
		if(readc(pp, &c) != 1) 
			break; 
1995/0114    
	if(readc(pp, &c) != 1) 
		return; 
1994/1209    
 
		pp->nioregs = 1<<(c&0x1f); 
		pp->bit16 = ((c>>5)&3) >= 2; 
		if((c & 0x80) == 0) 
			break; 
1995/0114    
	pp->nioregs = 1<<(c&0x1f); 
	pp->bit16 = ((c>>5)&3) >= 2; 
	if((c & 0x80) == 0) 
		return; 
1994/1209    
 
		if(readc(pp, &c) != 1) 
			break; 
1995/0114    
	if(readc(pp, &c) != 1) 
		return; 
1994/1209    
 
		for(i = (c&0xf)+1; i; i--){ 
			address = getlong(pp, (c>>4)&0x3); 
			len = getlong(pp, (c>>6)&0x3); 
			USED(address, len); 
		} 
1995/0114    
	for(i = (c&0xf)+1; i; i--){ 
		address = getlong(pp, (c>>4)&0x3); 
		len = getlong(pp, (c>>6)&0x3); 
		USED(address, len); 
1994/1209    
	} 
} 
 
1995/0114/sys/src/9/pc/devi82365.c:151,1571995/0117/sys/src/9/pc/devi82365.c:151,157 (short | long)
1994/1209    
	uchar	busy; 
 
	/* cis info */ 
1995/0111    
	uchar	verstr[512];	/* version string */ 
1995/0117    
	char	verstr[512];	/* version string */ 
1994/1209    
	uchar	vpp1; 
	uchar	vpp2; 
	uchar	bit16; 
1995/0114/sys/src/9/pc/devi82365.c:1173,11791995/0117/sys/src/9/pc/devi82365.c:1173,1179
1995/0111    
	if(readc(pp, &minor) != 1) 
		return; 
	for(i = 0; i < sizeof(pp->verstr)-1; i++){ 
		if(readc(&c) != 1) 
1995/0117    
		if(readc(pp, &c) != 1) 
1995/0111    
			return; 
		if(c == 0) 
			c = '\n'; 
1995/0117/sys/src/9/pc/devi82365.c:815,8211995/0118/sys/src/9/pc/devi82365.c:815,821 (short | long)
1994/1209    
 
	/* enable io port map 0 */ 
	if(isa->port == 0) 
		isa->port = 300; 
1995/0118    
		isa->port = 0x300; 
1994/1209    
	we = rdreg(pp, Rwe); 
	wrreg(pp, Riobtm0lo, isa->port); 
	wrreg(pp, Riobtm0hi, isa->port>>8); 
1995/0118/sys/src/9/pc/devi82365.c:163,1681995/0131/sys/src/9/pc/devi82365.c:163,171 (short | long)
1994/1209    
	ulong	caddr;		/* relative address of config registers */ 
	uchar	*cisbase;	/* base of mapped in attribute space */ 
	uchar	*cispos;	/* current position scanning cis */ 
1995/0131    
	ulong	maxwait; 
	ulong	readywait; 
	ulong	otherwait; 
1994/1209    
 
	/* memory maps */ 
	int	time; 
1995/0118/sys/src/9/pc/devi82365.c:1043,10551995/0131/sys/src/9/pc/devi82365.c:1046,1058
1994/1209    
		return; 
	i = c&0x3; 
	if(i != 3) 
		ttiming(pp, i);		/* max wait */ 
1995/0131    
		pp->maxwait = ttiming(pp, i);		/* max wait */ 
1994/1209    
	i = (c>>2)&0x7; 
	if(i != 7) 
		ttiming(pp, i);		/* max ready/busy wait */ 
1995/0131    
		pp->readywait = ttiming(pp, i);		/* max ready/busy wait */ 
1994/1209    
	i = (c>>5)&0x7; 
	if(i != 7) 
		ttiming(pp, i);		/* reserved wait */ 
1995/0131    
		pp->otherwait = ttiming(pp, i);		/* reserved wait */ 
1994/1209    
} 
 
void 
1995/0131/sys/src/9/pc/devi82365.c:117,1231995/0209/sys/src/9/pc/devi82365.c:117,122 (short | long)
1994/1209    
}; 
struct I82365 
{ 
	QLock; 
	int	type; 
	int	dev; 
	int	nslot; 
1995/0131/sys/src/9/pc/devi82365.c:130,1351995/0209/sys/src/9/pc/devi82365.c:129,135
1994/1209    
/* a Slot slot */ 
struct Slot 
{ 
1995/0209    
	Lock; 
1994/1209    
	int	ref; 
 
	I82365	*cp;		/* controller for this slot */ 
1995/0131/sys/src/9/pc/devi82365.c:168,1731995/0209/sys/src/9/pc/devi82365.c:168,174
1995/0131    
	ulong	otherwait; 
1994/1209    
 
	/* memory maps */ 
1995/0209    
	QLock	mlock;		/* lock down the maps */ 
1994/1209    
	int	time; 
	PCMmap	mmap[Nmap]; 
}; 
1995/0131/sys/src/9/pc/devi82365.c:322,3311995/0209/sys/src/9/pc/devi82365.c:323,333
1994/1209    
		pp->gotmem = 1; 
 
		/* grab ISA address space for memory maps */ 
		for(i = 0; i < Nmap; i++) 
1995/0209    
		for(i = 0; i < Nmap; i++){ 
1994/1210    
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); 
		if(pp->mmap[i].isa == 0) 
			panic("getmap"); 
1995/0209    
			if(pp->mmap[i].isa == 0) 
				panic("getmap"); 
		} 
1994/1209    
	} 
 
	/* look for a map that starts in the right place */ 
1995/0131/sys/src/9/pc/devi82365.c:368,3861995/0209/sys/src/9/pc/devi82365.c:370,388
1994/1209    
static void 
increfp(Slot *pp) 
{ 
	qlock(pp->cp); 
1995/0209    
	lock(pp); 
1994/1209    
	if(pp->ref++ == 0) 
		slotena(pp); 
	qunlock(pp->cp); 
1995/0209    
	unlock(pp); 
1994/1209    
} 
 
static void 
decrefp(Slot *pp) 
{ 
	qlock(pp->cp); 
1995/0209    
	lock(pp); 
1994/1209    
	if(pp->ref-- == 1) 
		slotdis(pp); 
	qunlock(pp->cp); 
1995/0209    
	unlock(pp); 
1994/1209    
} 
 
1995/0111    
char* 
1995/0131/sys/src/9/pc/devi82365.c:653,6591995/0209/sys/src/9/pc/devi82365.c:655,660
1994/1209    
	pp = slot + dev; 
	if(pp->memlen < offset) 
		return 0; 
	qlock(pp->cp); 
	ac = a; 
	if(pp->memlen < offset + n) 
		n = pp->memlen - offset; 
1995/0131/sys/src/9/pc/devi82365.c:670,6761995/0209/sys/src/9/pc/devi82365.c:671,676
1994/1209    
		offset += i; 
		ac += i; 
	} 
	qunlock(pp->cp); 
	return n; 
} 
 
1995/0131/sys/src/9/pc/devi82365.c:687,6931995/0209/sys/src/9/pc/devi82365.c:687,697
1994/1209    
		return devdirread(c, a, n, 0, 0, pcmgen); 
	case Qmem: 
	case Qattr: 
1995/0209    
		qlock(&pp->mlock); 
1994/1209    
		n = pcmread(DEV(c), p==Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1994/1209    
		break; 
	case Qctl: 
		cp = buf; 
1995/0131/sys/src/9/pc/devi82365.c:734,7401995/0209/sys/src/9/pc/devi82365.c:738,743
1994/1209    
	pp = slot + dev; 
	if(pp->memlen < offset) 
		return 0; 
	qlock(pp->cp); 
	ac = a; 
	if(pp->memlen < offset + n) 
		n = pp->memlen - offset; 
1995/0131/sys/src/9/pc/devi82365.c:749,7551995/0209/sys/src/9/pc/devi82365.c:752,757
1994/1209    
		offset += i; 
		ac += i; 
	} 
	qunlock(pp->cp); 
	return n; 
} 
 
1995/0131/sys/src/9/pc/devi82365.c:766,7721995/0209/sys/src/9/pc/devi82365.c:768,778
1994/1209    
		pp = slot + DEV(c); 
		if(pp->occupied == 0 || pp->enabled == 0) 
			error(Eio); 
1995/0209    
		qlock(&pp->mlock); 
1994/1209    
		n = pcmwrite(pp->dev, p == Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1994/1209    
		break; 
	default: 
		error(Ebadusefd); 
1995/0209/sys/src/9/pc/devi82365.c:184,1961995/0215/sys/src/9/pc/devi82365.c:184,200 (short | long)
1994/1209    
static uchar 
rdreg(Slot *pp, int index) 
{ 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->xreg, pp->base + index); 
1995/0215    
	microdelay(10); 
1994/1209    
	return inb(pp->cp->dreg); 
} 
static void 
wrreg(Slot *pp, int index, uchar val) 
{ 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->xreg, pp->base + index); 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->dreg, val); 
} 
 
1995/0209/sys/src/9/pc/devi82365.c:687,6921995/0215/sys/src/9/pc/devi82365.c:691,697
1994/1209    
		return devdirread(c, a, n, 0, 0, pcmgen); 
	case Qmem: 
	case Qattr: 
1995/0215    
		pp = slot + DEV(c); 
1995/0209    
		qlock(&pp->mlock); 
1994/1209    
		n = pcmread(DEV(c), p==Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
1995/0215/sys/src/9/pc/devi82365.c:15,211995/0222/sys/src/9/pc/devi82365.c:15,21 (short | long)
1994/1209    
 */ 
 
/* 
 *  Intel 82365SL PCIC controller for the Slot or 
1995/0222    
 *  Intel 82365SL PCIC controller for the PCMCIA or 
1994/1209    
 *  Cirrus Logic PD6710/PD6720 which is mostly register compatible 
 */ 
enum 
1995/0215/sys/src/9/pc/devi82365.c:64,691995/0222/sys/src/9/pc/devi82365.c:64,70
1994/1209    
	Rfifo=		0x17,		/* fifo control */ 
	 Fflush=	 (1<<7),	/*  flush fifo */ 
	Rmisc2=		0x1E,		/* misc control 2 */ 
1995/0222    
	 Flowpow=	 (1<<1),	/*  low power mode */ 
1994/1209    
	Rchipinfo=	0x1F,		/* chip information */ 
	Ratactl=	0x26,		/* ATA control */ 
 
1995/0215/sys/src/9/pc/devi82365.c:72,831995/0222/sys/src/9/pc/devi82365.c:73,85
1994/1209    
	 */ 
	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */ 
	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */ 
1995/0222    
	 F16bit=	 (1<<7),	/*  16-bit wide data path */ 
1994/1209    
	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */ 
	Mtophi=		0x3,		/* System mem addr mapping stop high byte */ 
	 F16bit=	 (1<<7),	/*  16-bit wide data path */ 
1995/0222    
	 Ftimer1=	 (1<<6),	/*  timer set 1 */ 
1994/1209    
	Mofflo=		0x4,		/* Card memory offset address low byte */ 
	Moffhi=		0x5,		/* Card memory offset address high byte */ 
	 Fregactive=	 (1<<6),	/*  attribute meory */ 
1995/0222    
	 Fregactive=	 (1<<6),	/*  attribute memory */ 
1994/1209    
 
	Mbits=		13,		/* msb of Mchunk */ 
	Mchunk=		1<<Mbits,	/* logical mapping granularity */ 
1995/0215/sys/src/9/pc/devi82365.c:135,1411995/0222/sys/src/9/pc/devi82365.c:137,143
1994/1209    
	I82365	*cp;		/* controller for this slot */ 
	long	memlen;		/* memory length */ 
	uchar	base;		/* index register base */ 
	uchar	dev;		/* slot number */ 
1995/0222    
	uchar	slotno;		/* slot number */ 
1994/1209    
 
	/* status */ 
	uchar	special;	/* in use for a special device */ 
1995/0215/sys/src/9/pc/devi82365.c:147,1531995/0222/sys/src/9/pc/devi82365.c:149,154
1994/1209    
	uchar	powered; 
	uchar	configed; 
	uchar	enabled; 
	uchar	iocard; 
	uchar	busy; 
 
	/* cis info */ 
1995/0215/sys/src/9/pc/devi82365.c:161,1681995/0222/sys/src/9/pc/devi82365.c:162,169
1994/1209    
	uchar	def;		/* default configuration */ 
	ushort	irqs;		/* valid interrupt levels */ 
	ulong	caddr;		/* relative address of config registers */ 
	uchar	*cisbase;	/* base of mapped in attribute space */ 
	uchar	*cispos;	/* current position scanning cis */ 
1995/0222    
	int	cispos;		/* current position scanning cis */ 
	uchar	*cisbase; 
1995/0131    
	ulong	maxwait; 
	ulong	readywait; 
	ulong	otherwait; 
1995/0215/sys/src/9/pc/devi82365.c:177,1821995/0222/sys/src/9/pc/devi82365.c:178,184
1994/1209    
static nslot; 
 
static void cisread(Slot*); 
1995/0222    
static void i82365intr(Ureg*, void*); 
1994/1209    
 
/* 
 *  reading and writing card registers 
1995/0215/sys/src/9/pc/devi82365.c:184,2001995/0222/sys/src/9/pc/devi82365.c:186,198
1994/1209    
static uchar 
rdreg(Slot *pp, int index) 
{ 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->xreg, pp->base + index); 
1995/0215    
	microdelay(10); 
1994/1209    
	return inb(pp->cp->dreg); 
} 
static void 
wrreg(Slot *pp, int index, uchar val) 
{ 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->xreg, pp->base + index); 
1995/0215    
	microdelay(10); 
1994/1209    
	outb(pp->cp->dreg, val); 
} 
 
1995/0215/sys/src/9/pc/devi82365.c:212,2201995/0222/sys/src/9/pc/devi82365.c:210,215
1994/1209    
	pp->battery = (isr & 3) == 3; 
	pp->wrprot = isr & (1<<4); 
	pp->busy = isr & (1<<5); 
                 
	isr = rdreg(pp, Rigc); 
	pp->iocard = isr & Fiocard; 
} 
 
static int 
1995/0215/sys/src/9/pc/devi82365.c:236,2701995/0222/sys/src/9/pc/devi82365.c:231,260
1994/1209    
static void 
slotena(Slot *pp) 
{ 
	int x; 
                 
	if(pp->enabled) 
		return; 
 
	if(pp->already == 0){ 
		pp->already = 1; 
1995/0222    
	/* enable the card */ 
	wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena); 
	delay(300);	/* give the card time to sit up and take notice */ 
	wrreg(pp, Rigc, 0); 
	delay(100); 
	wrreg(pp, Rigc, Fnotreset); 
	delay(100); 
	wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); 
1994/1209    
 
		/* interrupt on card status change */ 
		wrreg(pp, Rigc, Fnotreset); 
		wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena 
			| Fbwarnena | Fbdeadena); 
	} 
                 
	/* display status */ 
	slotinfo(pp); 
	if(pp->occupied){ 
		/* enable the card */ 
		wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena); 
		pp->enabled = 1; 
		cisread(pp); 
 
		/* set real power values if we configured successfully */ 
		if(pp->configed){ 
			x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2); 
			wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); 
		} 
1995/0222    
		if(pp->configed) 
			wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena); 
1994/1209    
 
	} 
1995/0222    
	} else 
		wrreg(pp, Rpc, vcode(5)|Fautopower); 
	pp->enabled = 1; 
1994/1209    
} 
 
/* 
1995/0215/sys/src/9/pc/devi82365.c:273,2861995/0222/sys/src/9/pc/devi82365.c:263,271
1994/1209    
static void 
slotdis(Slot *pp) 
{ 
1995/0107    
	int x; 
                 
1994/1209    
	/* disable the windows into the card */ 
	wrreg(pp, Rwe, 0); 
                 
	/* disable the card */ 
1995/0107    
	x = vcode(5) | (vcode(5)<<2); 
	wrreg(pp, Rpc, x|Fautopower); 
1995/0222    
	wrreg(pp, Rmisc2, Flowpow);	 	/* low power mode */ 
	wrreg(pp, Rpc, vcode(5)|Fautopower);			/* turn off card */ 
	wrreg(pp, Rwe, 0);			/* no windows */ 
1994/1209    
	pp->enabled = 0; 
} 
 
1995/0215/sys/src/9/pc/devi82365.c:288,3121995/0222/sys/src/9/pc/devi82365.c:273,296
1994/1209    
 *  status change interrupt 
 */ 
static void 
i82365intr(Ureg *ur) 
1995/0222    
i82365intr(Ureg *ur, void *a) 
1994/1209    
{ 
	uchar csc; 
1995/0222    
	uchar csc, was; 
1994/1209    
	Slot *pp; 
 
	USED(ur); 
1995/0222    
	USED(ur,a); 
	if(slot == 0) 
		return; 
 
1994/1209    
	for(pp = slot; pp < lastslot; pp++){ 
		csc = rdreg(pp, Rcsc); 
1995/0222    
		was = pp->occupied; 
1994/1209    
		slotinfo(pp); 
		if(csc & 1) 
			print("slot card %d battery dead\n", pp->dev); 
		if(csc & (1<<1)) 
			print("slot card %d battery warning\n", pp->dev); 
		if(csc & (1<<3)){ 
			if(pp->occupied && pp->ref){ 
				print("slot card %d inserted\n", pp->dev); 
				slotena(pp); 
			} else { 
				print("slot card %d removed\n", pp->dev); 
1995/0222    
		if(csc & (1<<3) && was != pp->occupied){ 
			if(pp->occupied) 
				print("slot%d card inserted\n", pp->slotno); 
			else { 
				print("slot%d card removed\n", pp->slotno); 
1994/1209    
				slotdis(pp); 
			} 
		} 
1995/0215/sys/src/9/pc/devi82365.c:361,3671995/0222/sys/src/9/pc/devi82365.c:345,351
1994/1209    
	wrreg(pp, MAP(i, Mbtmlo), m->isa>>12); 
	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(12+8)) | F16bit); 
	wrreg(pp, MAP(i, Mtoplo), (m->isa+Mchunk-1)>>12); 
	wrreg(pp, MAP(i, Mtophi), (m->isa+Mchunk-1)>>(12+8)); 
1995/0222    
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) | Ftimer1); 
1994/1209    
	offset -= m->isa; 
	offset &= (1<<25)-1; 
	offset >>= 12; 
1995/0215/sys/src/9/pc/devi82365.c:389,4221995/0222/sys/src/9/pc/devi82365.c:373,413
1995/0209    
	unlock(pp); 
1994/1209    
} 
 
1995/0111    
char* 
1994/1209    
pcmspecial(int dev) 
1995/0222    
/* 
 *  look for a card whose version contains 'idstr' 
 */ 
int 
pcmspecial(char *idstr, ISAConf *isa) 
1994/1209    
{ 
	Slot *pp; 
1995/0222    
	extern char *strstr(char*, char*); 
1994/1209    
 
	i82365reset(); 
	if(dev >= nslot) 
1995/0111    
		return 0; 
1994/1209    
	pp = slot + dev; 
	if(pp->special) 
1995/0111    
		return 0; 
1994/1209    
	increfp(pp); 
	if(!pp->occupied){ 
1995/0222    
	for(pp = slot; pp < lastslot; pp++){ 
		if(pp->special) 
			continue;	/* already taken */ 
		increfp(pp); 
 
		if(pp->occupied) 
		if(strstr(pp->verstr, idstr)) 
		if(isa == 0 || pcmio(pp->slotno, isa) == 0){ 
			pp->special = 1; 
			return pp->slotno; 
		} 
 
1994/1209    
		decrefp(pp); 
1995/0111    
		return 0; 
1994/1209    
	} 
	pp->special = 1; 
1995/0111    
	return pp->verstr; 
1995/0222    
	return -1; 
1994/1209    
} 
 
void 
pcmspecialclose(int dev) 
1995/0222    
pcmspecialclose(int slotno) 
1994/1209    
{ 
	Slot *pp; 
 
	if(dev >= nslot) 
1995/0222    
	if(slotno >= nslot) 
1994/1209    
		panic("pcmspecialclose"); 
	pp = slot + dev; 
1995/0222    
	pp = slot + slotno; 
1994/1209    
	pp->special = 0; 
	decrefp(pp); 
} 
1995/0215/sys/src/9/pc/devi82365.c:429,4411995/0222/sys/src/9/pc/devi82365.c:420,433
1994/1209    
	Qctl, 
}; 
 
#define DEV(c)	(c->qid.path>>8) 
#define TYPE(c)	(c->qid.path&0xff) 
1995/0222    
#define SLOTNO(c)	((c->qid.path>>8)&0xff) 
#define TYPE(c)		(c->qid.path&0xff) 
#define QID(s,t)	(((s)<<8)|(t)) 
1994/1209    
 
static int 
pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) 
{ 
	int dev; 
1995/0222    
	int slotno; 
1994/1209    
	Qid qid; 
	long len; 
	Slot *pp; 
1995/0215/sys/src/9/pc/devi82365.c:444,4661995/0222/sys/src/9/pc/devi82365.c:436,458
1994/1209    
	USED(tab, ntab); 
	if(i>=3*nslot) 
		return -1; 
	dev = i/3; 
	pp = slot + dev; 
1995/0222    
	slotno = i/3; 
	pp = slot + slotno; 
1994/1209    
	len = 0; 
	switch(i%3){ 
	case 0: 
		qid.path = (dev<<8) | Qmem; 
		sprint(name, "pcm%dmem", dev); 
1995/0222    
		qid.path = QID(slotno, Qmem); 
		sprint(name, "pcm%dmem", slotno); 
1994/1209    
		len = pp->memlen; 
		break; 
	case 1: 
		qid.path = (dev<<8) | Qattr; 
		sprint(name, "pcm%dattr", dev); 
1995/0222    
		qid.path = QID(slotno, Qattr); 
		sprint(name, "pcm%dattr", slotno); 
1994/1209    
		len = pp->memlen; 
		break; 
	case 2: 
		qid.path = (dev<<8) | Qctl; 
		sprint(name, "pcm%dctl", dev); 
1995/0222    
		qid.path = QID(slotno, Qctl); 
		sprint(name, "pcm%dctl", slotno); 
1994/1209    
		break; 
	} 
	qid.vers = 0; 
1995/0215/sys/src/9/pc/devi82365.c:538,5431995/0222/sys/src/9/pc/devi82365.c:530,537
1994/1209    
	/* look for controllers */ 
	i82386probe(0x3E0, 0x3E1, 0); 
	i82386probe(0x3E0, 0x3E1, 1); 
1995/0222    
	i82386probe(0x3E2, 0x3E3, 0); 
	i82386probe(0x3E2, 0x3E3, 1); 
1994/1209    
	for(i = 0; i < ncontroller; i++) 
		nslot += controller[i]->nslot; 
	slot = xalloc(nslot * sizeof(Slot)); 
1995/0215/sys/src/9/pc/devi82365.c:547,5601995/0222/sys/src/9/pc/devi82365.c:541,557
1994/1209    
	for(i = 0; i < ncontroller; i++){ 
		cp = controller[i]; 
		for(j = 0; j < cp->nslot; j++){ 
			lastslot->dev = lastslot - slot; 
1995/0222    
			lastslot->slotno = lastslot - slot; 
1994/1209    
			lastslot->memlen = 64*MB; 
			lastslot->base = (cp->dev<<7) | (j<<6); 
			lastslot->cp = cp; 
			wrreg(lastslot, Rpc, 5|Fautopower); 
1995/0222    
			slotdis(lastslot); 
1994/1209    
			lastslot++; 
		} 
	} 
1995/0222    
 
	/* for card management interrupts */ 
	setvec(PCMCIAvec, i82365intr, 0); 
1994/1209    
} 
 
void 
1995/0215/sys/src/9/pc/devi82365.c:593,5991995/0222/sys/src/9/pc/devi82365.c:590,596
1994/1209    
		if(omode != OREAD) 
			error(Eperm); 
	} else 
		increfp(slot + DEV(c)); 
1995/0222    
		increfp(slot + SLOTNO(c)); 
1994/1209    
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
1995/0215/sys/src/9/pc/devi82365.c:624,6341995/0222/sys/src/9/pc/devi82365.c:621,639
1994/1209    
void 
i82365close(Chan *c) 
{ 
	USED(c); 
	if(c->qid.path != CHDIR) 
		decrefp(slot+DEV(c)); 
1995/0222    
	if(c->flag & COPEN) 
		if(c->qid.path != CHDIR) 
			decrefp(slot+SLOTNO(c)); 
1994/1209    
} 
 
1995/0222    
/* a memmove using only bytes */ 
static void 
memmoveb(uchar *to, uchar *from, int n) 
{ 
	while(n-- > 0) 
		*to++ = *from++; 
} 
 
1994/1209    
/* a memmove using only shorts & bytes */ 
static void 
memmoves(uchar *to, uchar *from, int n) 
1995/0215/sys/src/9/pc/devi82365.c:648,6541995/0222/sys/src/9/pc/devi82365.c:653,659
1994/1209    
} 
 
long 
pcmread(int dev, int attr, void *a, long n, ulong offset) 
1995/0222    
pcmread(int slotno, int attr, void *a, long n, ulong offset) 
1994/1209    
{ 
	int i, len; 
	PCMmap *m; 
1995/0215/sys/src/9/pc/devi82365.c:656,6621995/0222/sys/src/9/pc/devi82365.c:661,667
1994/1209    
	uchar *ac; 
	Slot *pp; 
 
	pp = slot + dev; 
1995/0222    
	pp = slot + slotno; 
1994/1209    
	if(pp->memlen < offset) 
		return 0; 
	ac = a; 
1995/0215/sys/src/9/pc/devi82365.c:671,6771995/0222/sys/src/9/pc/devi82365.c:676,682
1994/1209    
		else 
			i = len; 
		ka = KZERO|(m->isa + (offset&(Mchunk-1))); 
		memmoves(ac, (void*)ka, i); 
1995/0222    
		memmoveb(ac, (void*)ka, i); 
1994/1209    
		offset += i; 
		ac += i; 
	} 
1995/0215/sys/src/9/pc/devi82365.c:678,6871995/0222/sys/src/9/pc/devi82365.c:683,698
1994/1209    
	return n; 
} 
 
1995/0222    
Block* 
i82365bread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1994/1209    
long 
i82365read(Chan *c, void *a, long n, ulong offset) 
{ 
	char *cp, buf[128]; 
1995/0222    
	char *cp, buf[2048]; 
1994/1209    
	ulong p; 
	Slot *pp; 
 
1995/0215/sys/src/9/pc/devi82365.c:691,6991995/0222/sys/src/9/pc/devi82365.c:702,710
1994/1209    
		return devdirread(c, a, n, 0, 0, pcmgen); 
	case Qmem: 
	case Qattr: 
1995/0215    
		pp = slot + DEV(c); 
1995/0222    
		pp = slot + SLOTNO(c); 
1995/0209    
		qlock(&pp->mlock); 
1994/1209    
		n = pcmread(DEV(c), p==Qattr, a, n, offset); 
1995/0222    
		n = pcmread(SLOTNO(c), p==Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1995/0215/sys/src/9/pc/devi82365.c:700,7061995/0222/sys/src/9/pc/devi82365.c:711,717
1994/1209    
		break; 
	case Qctl: 
		cp = buf; 
		pp = slot + DEV(c); 
1995/0222    
		pp = slot + SLOTNO(c); 
1994/1209    
		if(pp->occupied) 
			cp += sprint(cp, "occupied\n"); 
		if(pp->enabled) 
1995/0215/sys/src/9/pc/devi82365.c:707,7141995/0222/sys/src/9/pc/devi82365.c:718,723
1994/1209    
			cp += sprint(cp, "enabled\n"); 
		if(pp->powered) 
			cp += sprint(cp, "powered\n"); 
		if(pp->iocard) 
			cp += sprint(cp, "iocard\n"); 
		if(pp->configed) 
			cp += sprint(cp, "configed\n"); 
		if(pp->wrprot) 
1995/0215/sys/src/9/pc/devi82365.c:716,7211995/0222/sys/src/9/pc/devi82365.c:725,742
1994/1209    
		if(pp->busy) 
			cp += sprint(cp, "busy\n"); 
		cp += sprint(cp, "battery lvl %d\n", pp->battery); 
1995/0222    
{ 
	int i; 
 
	cp += sprint(cp, "x %x d %x b %x\n", pp->cp->xreg, pp->cp->dreg, pp->base); 
	for(i = 0; i < 0x40; i++){ 
		cp += sprint(cp, "%2.2ux ", rdreg(pp, i)); 
		if((i%8) == 7) 
			cp += sprint(cp, "\n"); 
	} 
	if(i%8) 
		cp += sprint(cp, "\n"); 
} 
1994/1209    
		*cp = 0; 
		return readstr(offset, a, n, buf); 
	default: 
1995/0215/sys/src/9/pc/devi82365.c:725,7341995/0222/sys/src/9/pc/devi82365.c:746,755
1994/1209    
	return n; 
} 
 
1995/0108    
Block* 
i82365bread(Chan *c, long n, ulong offset) 
1995/0222    
long 
i82365bwrite(Chan *c, Block *bp, ulong offset) 
1995/0108    
{ 
	return devbread(c, n, offset); 
1995/0222    
	return devbwrite(c, bp, offset); 
1995/0108    
} 
 
1994/1209    
long 
1995/0215/sys/src/9/pc/devi82365.c:753,7591995/0222/sys/src/9/pc/devi82365.c:774,780
1994/1209    
		else 
			i = len; 
		ka = KZERO|(m->isa + (offset&(Mchunk-1))); 
		memmoves((void*)ka, ac, i); 
1995/0222    
		memmoveb((void*)ka, ac, i); 
1994/1209    
		offset += i; 
		ac += i; 
	} 
1995/0215/sys/src/9/pc/devi82365.c:770,7801995/0222/sys/src/9/pc/devi82365.c:791,801
1994/1209    
	switch(p){ 
	case Qmem: 
	case Qattr: 
		pp = slot + DEV(c); 
1995/0222    
		pp = slot + SLOTNO(c); 
1994/1209    
		if(pp->occupied == 0 || pp->enabled == 0) 
			error(Eio); 
1995/0209    
		qlock(&pp->mlock); 
1994/1209    
		n = pcmwrite(pp->dev, p == Qattr, a, n, offset); 
1995/0222    
		n = pcmwrite(pp->slotno, p == Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1995/0215/sys/src/9/pc/devi82365.c:785,7961995/0222/sys/src/9/pc/devi82365.c:806,811
1994/1209    
	return n; 
1995/0108    
} 
 
long 
i82365bwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1994/1209    
} 
                 
/* 
 *  configure the Slot for IO.  We assume very heavily that we can read 
 *  cofiguration info from the CIS.  If not, we won't set up correctly. 
1995/0215/sys/src/9/pc/devi82365.c:820,8261995/0222/sys/src/9/pc/devi82365.c:835,841
1994/1209    
	wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); 
	 
	/* set power and enable device */ 
	x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2); 
1995/0222    
	x = vcode(pp->vpp1); 
1994/1209    
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); 
 
	/* 16-bit data path */ 
1995/0215/sys/src/9/pc/devi82365.c:842,8511995/0222/sys/src/9/pc/devi82365.c:857,866
1994/1209    
		/*  Reset adapter */ 
		x = Creset; 
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
		delay(2); 
1995/0222    
		delay(5); 
1994/1209    
		x = 0; 
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
		delay(2); 
1995/0222    
		delay(5); 
1994/1209    
	 
		/* 
		 *  Set level sensitive (not pulsed) interrupts and 
1995/0215/sys/src/9/pc/devi82365.c:854,8601995/0222/sys/src/9/pc/devi82365.c:869,875
1994/1209    
		 */ 
		x = Clevel | 1; 
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
		delay(2); 
1995/0222    
		delay(5); 
1994/1209    
	} 
	return 0; 
} 
1995/0215/sys/src/9/pc/devi82365.c:877,8871995/0222/sys/src/9/pc/devi82365.c:892,901
1994/1209    
static int 
readc(Slot *pp, uchar *x) 
{ 
	if(pp->cispos > pp->cisbase + Mchunk) 
1995/0222    
	if(pp->cispos >= Mchunk) 
1994/1209    
		return 0; 
                 
	*x = *(pp->cispos); 
	pp->cispos += 2; 
1995/0222    
	*x = pp->cisbase[2*pp->cispos]; 
	pp->cispos++; 
1994/1209    
	return 1; 
} 
 
1995/0215/sys/src/9/pc/devi82365.c:888,8981995/0222/sys/src/9/pc/devi82365.c:902,911
1994/1209    
static void 
cisread(Slot *pp) 
{ 
	PCMmap *m; 
	uchar link; 
	uchar type; 
	uchar *this; 
	int i; 
1995/0222    
	int this, i; 
	PCMmap *m; 
1994/1209    
 
	pp->vpp1 = pp->vpp2 = 5; 
	pp->bit16 = 0; 
1995/0215/sys/src/9/pc/devi82365.c:901,9091995/0222/sys/src/9/pc/devi82365.c:914,924
1994/1209    
	pp->def = 0; 
	pp->irqs = 0xffff; 
 
	/* map in the attribute memory cis should be in */ 
	m = getmap(pp, 0, 1); 
	pp->cispos = pp->cisbase = (uchar*)(KZERO|m->isa); 
1995/0222    
	if(m == 0) 
		return; 
	pp->cisbase = (uchar*)(KZERO|m->isa); 
	pp->cispos = 0; 
1994/1209    
 
	/* loop through all the tuples */ 
	for(i = 0; i < 1000; i++){ 
1995/0215/sys/src/9/pc/devi82365.c:916,9241995/0222/sys/src/9/pc/devi82365.c:931,937
1994/1209    
			(*parse[type])(pp, type); 
		if(link == 0xff) 
			break; 
		pp->cispos = this + 2*(2+link); 
		if(this > pp->cisbase + Mchunk) 
			break; 
1995/0222    
		pp->cispos = this + (2+link); 
1994/1209    
	} 
} 
 
1995/0222/sys/src/9/pc/devi82365.c:92,971995/0223/sys/src/9/pc/devi82365.c:92,99 (short | long)
1994/1209    
	Rconfig=	0, 
	 Creset=	 (1<<7),	/*  reset device */ 
	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */ 
1995/0223    
 
	Maxctab=	8,		/* maximum configuration table entries */ 
1994/1209    
}; 
 
#define MAP(x,o)	(Rmap + (x)*0x8 + o) 
1995/0222/sys/src/9/pc/devi82365.c:99,1041995/0223/sys/src/9/pc/devi82365.c:101,107
1994/1209    
typedef struct I82365	I82365; 
typedef struct Slot	Slot; 
typedef struct PCMmap	PCMmap; 
1995/0223    
typedef struct Conftab	Conftab; 
1994/1209    
 
/* maps between ISA memory space and the card memory space */ 
struct PCMmap 
1995/0222/sys/src/9/pc/devi82365.c:128,1341995/0223/sys/src/9/pc/devi82365.c:131,153
1994/1209    
static I82365 *controller[4]; 
static int ncontroller; 
 
/* a Slot slot */ 
1995/0223    
/* configuration table entry */ 
struct Conftab 
{ 
	int	index; 
	ushort	irqs;		/* legal irqs */ 
	ushort	port;		/* port address */ 
	uchar	nioregs;	/* number of io registers */ 
	uchar	bit16;		/* true for 16 bit access */ 
	uchar	vpp1; 
	uchar	vpp2; 
	uchar	memwait; 
	ulong	maxwait; 
	ulong	readywait; 
	ulong	otherwait; 
}; 
 
/* a card slot */ 
1994/1209    
struct Slot 
{ 
1995/0209    
	Lock; 
1995/0222/sys/src/9/pc/devi82365.c:142,1481995/0223/sys/src/9/pc/devi82365.c:161,166
1994/1209    
	/* status */ 
	uchar	special;	/* in use for a special device */ 
	uchar	already;	/* already inited */ 
	uchar	gotmem;		/* already got memmap space */ 
	uchar	occupied; 
	uchar	battery; 
	uchar	wrprot; 
1995/0222/sys/src/9/pc/devi82365.c:153,1771995/0223/sys/src/9/pc/devi82365.c:171,191
1994/1209    
 
	/* cis info */ 
1995/0117    
	char	verstr[512];	/* version string */ 
1994/1209    
	uchar	vpp1; 
	uchar	vpp2; 
	uchar	bit16; 
	uchar	nioregs; 
	uchar	memwait; 
	uchar	cpresent;	/* config registers present */ 
	uchar	def;		/* default configuration */ 
	ushort	irqs;		/* valid interrupt levels */ 
	ulong	caddr;		/* relative address of config registers */ 
1995/0223    
	int	nctab;		/* number of config table entries */ 
	Conftab	ctab[Maxctab]; 
	Conftab	*def;		/* default conftab */ 
 
	/* for walking through cis */ 
1995/0222    
	int	cispos;		/* current position scanning cis */ 
	uchar	*cisbase; 
1995/0131    
	ulong	maxwait; 
	ulong	readywait; 
	ulong	otherwait; 
1994/1209    
 
	/* memory maps */ 
1995/0209    
	QLock	mlock;		/* lock down the maps */ 
1994/1209    
	int	time; 
	PCMmap	mmap[Nmap]; 
1995/0223    
	PCMmap	mmap[Nmap];	/* maps, last is always for the kernel */ 
	int	nmap;		/* number of maps */ 
1994/1209    
}; 
static Slot	*slot; 
static Slot	*lastslot; 
1995/0222/sys/src/9/pc/devi82365.c:234,2601995/0223/sys/src/9/pc/devi82365.c:248,268
1994/1209    
	if(pp->enabled) 
		return; 
 
1995/0222    
	/* enable the card */ 
	wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena); 
	delay(300);	/* give the card time to sit up and take notice */ 
1995/0223    
	/* power up and reset, wait's are empirical (???) */ 
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena); 
	delay(300); 
1995/0222    
	wrreg(pp, Rigc, 0); 
	delay(100); 
	wrreg(pp, Rigc, Fnotreset); 
	delay(100); 
	wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); 
1995/0223    
	delay(500); 
1994/1209    
 
	/* display status */ 
1995/0223    
	/* get configuration */ 
1994/1209    
	slotinfo(pp); 
	if(pp->occupied){ 
		cisread(pp); 
                 
		/* set real power values if we configured successfully */ 
1995/0222    
		if(pp->configed) 
			wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena); 
1994/1209    
                 
1995/0223    
		pp->enabled = 1; 
1995/0222    
	} else 
		wrreg(pp, Rpc, vcode(5)|Fautopower); 
	pp->enabled = 1; 
1995/0223    
		wrreg(pp, Rpc, Fautopower); 
1994/1209    
} 
 
/* 
1995/0222/sys/src/9/pc/devi82365.c:263,2701995/0223/sys/src/9/pc/devi82365.c:271,277
1994/1209    
static void 
slotdis(Slot *pp) 
{ 
1995/0222    
	wrreg(pp, Rmisc2, Flowpow);	 	/* low power mode */ 
	wrreg(pp, Rpc, vcode(5)|Fautopower);			/* turn off card */ 
1995/0223    
	wrreg(pp, Rpc, Fautopower);		/* turn off card */ 
1995/0222    
	wrreg(pp, Rwe, 0);			/* no windows */ 
1994/1209    
	pp->enabled = 0; 
} 
1995/0222/sys/src/9/pc/devi82365.c:307,3281995/0223/sys/src/9/pc/devi82365.c:314,324
1994/1209    
	PCMmap *m, *lru; 
	int i; 
 
	if(pp->gotmem == 0){ 
		pp->gotmem = 1; 
                 
		/* grab ISA address space for memory maps */ 
1995/0209    
		for(i = 0; i < Nmap; i++){ 
1994/1210    
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); 
1995/0209    
			if(pp->mmap[i].isa == 0) 
				panic("getmap"); 
		} 
1994/1209    
	} 
                 
	/* look for a map that starts in the right place */ 
	we = rdreg(pp, Rwe); 
	bit = 1; 
	lru = pp->mmap; 
	for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){ 
1995/0223    
	for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){ 
1994/1209    
		if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){ 
			m->time = pp->time++; 
			return m; 
1995/0222/sys/src/9/pc/devi82365.c:345,3511995/0223/sys/src/9/pc/devi82365.c:341,347
1994/1209    
	wrreg(pp, MAP(i, Mbtmlo), m->isa>>12); 
	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(12+8)) | F16bit); 
	wrreg(pp, MAP(i, Mtoplo), (m->isa+Mchunk-1)>>12); 
1995/0222    
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) | Ftimer1); 
1995/0223    
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) /*| Ftimer1/**/); 
1994/1209    
	offset -= m->isa; 
	offset &= (1<<25)-1; 
	offset >>= 12; 
1995/0222/sys/src/9/pc/devi82365.c:509,5141995/0223/sys/src/9/pc/devi82365.c:505,514
1994/1209    
	print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot, 
		chipname[cp->type]); 
 
1995/0223    
	/* low power mode */ 
	outb(x, Rmisc2 + (dev<<7)); 
	outb(d, Flowpow); 
 
1994/1209    
	controller[ncontroller++] = cp; 
	return cp; 
} 
1995/0222/sys/src/9/pc/devi82365.c:522,5271995/0223/sys/src/9/pc/devi82365.c:522,528
1994/1209    
	static int already; 
	int i, j; 
	I82365 *cp; 
1995/0223    
	Slot *pp; 
1994/1209    
 
	if(already) 
		return; 
1995/0222/sys/src/9/pc/devi82365.c:541,5551995/0223/sys/src/9/pc/devi82365.c:542,568
1994/1209    
	for(i = 0; i < ncontroller; i++){ 
		cp = controller[i]; 
		for(j = 0; j < cp->nslot; j++){ 
1995/0222    
			lastslot->slotno = lastslot - slot; 
1994/1209    
			lastslot->memlen = 64*MB; 
			lastslot->base = (cp->dev<<7) | (j<<6); 
			lastslot->cp = cp; 
1995/0222    
			slotdis(lastslot); 
1994/1209    
			lastslot++; 
1995/0223    
			pp = lastslot++; 
			pp->slotno = pp - slot; 
			pp->memlen = 64*MB; 
			pp->base = (cp->dev<<7) | (j<<6); 
			pp->cp = cp; 
			slotdis(pp); 
 
			/* interrupt on status change */ 
			wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); 
1994/1209    
		} 
	} 
1995/0222    
 
1995/0223    
	/* get ISA address space for memory maps */ 
	for(i = 0; i < Nmap; i++) 
		for(pp = slot; pp < lastslot; pp++){ 
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); 
			if(pp->mmap[i].isa == 0) 
				break; 
			pp->nmap++; 
		} 
 
1995/0222    
	/* for card management interrupts */ 
	setvec(PCMCIAvec, i82365intr, 0); 
1994/1209    
} 
1995/0222/sys/src/9/pc/devi82365.c:815,8201995/0223/sys/src/9/pc/devi82365.c:828,834
1994/1209    
{ 
	uchar we, x; 
	Slot *pp; 
1995/0223    
	Conftab *ct; 
1994/1209    
 
	if(dev > nslot) 
		return -1; 
1995/0222/sys/src/9/pc/devi82365.c:823,8451995/0223/sys/src/9/pc/devi82365.c:837,869
1994/1209    
	if(!pp->occupied) 
		return -1; 
 
	/* if no io registers, assume not an io card (iffy!) */ 
	if(pp->nioregs == 0) 
1995/0223    
	/* find a configuration with the right port */ 
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) 
		if(ct->nioregs && ct->port == isa->port) 
			break; 
 
	/* if non found, settle for one with the some ioregs */ 
	if(ct == &pp->ctab[pp->nctab]) 
		for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) 
			if(ct->nioregs) 
				break; 
 
	if(ct == &pp->ctab[pp->nctab]) 
1994/1209    
		return -1; 
 
	/* route interrupts, make sure card can use specified interrupt */ 
1995/0223    
print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs); 
 
	/* route interrupts */ 
1994/1209    
	if(isa->irq == 2) 
		isa->irq = 9; 
	if(((1<<isa->irq) & pp->irqs) == 0) 
		return -1; 
	wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); 
	 
	/* set power and enable device */ 
1995/0222    
	x = vcode(pp->vpp1); 
1995/0223    
	x = vcode(ct->vpp1); 
1994/1209    
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); 
 
	/* 16-bit data path */ 
	if(pp->bit16) 
1995/0223    
	if(ct->bit16) 
1994/1209    
		wrreg(pp, Rio, (1<<0)|(1<<1)); 
 
	/* enable io port map 0 */ 
1995/0222/sys/src/9/pc/devi82365.c:848,8551995/0223/sys/src/9/pc/devi82365.c:872,879
1994/1209    
	we = rdreg(pp, Rwe); 
	wrreg(pp, Riobtm0lo, isa->port); 
	wrreg(pp, Riobtm0hi, isa->port>>8); 
	wrreg(pp, Riotop0lo, (isa->port+pp->nioregs)); 
	wrreg(pp, Riotop0hi, (isa->port+pp->nioregs)>>8); 
1995/0223    
	wrreg(pp, Riotop0lo, (isa->port+ct->nioregs)); 
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8); 
1994/1209    
	wrreg(pp, Rwe, we | (1<<6)); 
 
	/* only touch Rconfig if it is present */ 
1995/0222/sys/src/9/pc/devi82365.c:867,8731995/0223/sys/src/9/pc/devi82365.c:891,900
1994/1209    
		 *  configuration number 1. 
		 *  Setting the configuration number enables IO port access. 
		 */ 
		x = Clevel | 1; 
1995/0223    
		if(isa->irq > 7) 
			x = Clevel | ct->index; 
		else 
			x = ct->index; 
1994/1209    
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
1995/0222    
		delay(5); 
1994/1209    
	} 
1995/0222/sys/src/9/pc/devi82365.c:907,9181995/0223/sys/src/9/pc/devi82365.c:934,944
1995/0222    
	int this, i; 
	PCMmap *m; 
1994/1209    
 
	pp->vpp1 = pp->vpp2 = 5; 
	pp->bit16 = 0; 
1995/0223    
	memset(pp->ctab, 0, sizeof(pp->ctab)); 
1994/1209    
	pp->caddr = 0; 
	pp->cpresent = 0; 
	pp->def = 0; 
	pp->irqs = 0xffff; 
1995/0223    
	pp->configed = 0; 
	pp->nctab = 0; 
1994/1209    
 
	m = getmap(pp, 0, 1); 
1995/0222    
	if(m == 0) 
1995/0222/sys/src/9/pc/devi82365.c:1062,10681995/0223/sys/src/9/pc/devi82365.c:1088,1094
1994/1209    
} 
 
static void 
timing(Slot *pp) 
1995/0223    
timing(Slot *pp, Conftab *ct) 
1994/1209    
{ 
	uchar c, i; 
 
1995/0222/sys/src/9/pc/devi82365.c:1070,10961995/0223/sys/src/9/pc/devi82365.c:1096,1122
1994/1209    
		return; 
	i = c&0x3; 
	if(i != 3) 
1995/0131    
		pp->maxwait = ttiming(pp, i);		/* max wait */ 
1995/0223    
		ct->maxwait = ttiming(pp, i);		/* max wait */ 
1994/1209    
	i = (c>>2)&0x7; 
	if(i != 7) 
1995/0131    
		pp->readywait = ttiming(pp, i);		/* max ready/busy wait */ 
1995/0223    
		ct->readywait = ttiming(pp, i);		/* max ready/busy wait */ 
1994/1209    
	i = (c>>5)&0x7; 
	if(i != 7) 
1995/0131    
		pp->otherwait = ttiming(pp, i);		/* reserved wait */ 
1995/0223    
		ct->otherwait = ttiming(pp, i);		/* reserved wait */ 
1994/1209    
} 
 
void 
iospaces(Slot *pp) 
1995/0223    
iospaces(Slot *pp, Conftab *ct) 
1994/1209    
{ 
	uchar c; 
	int i; 
	ulong address, len; 
1995/0223    
	ulong len; 
1994/1209    
 
1995/0114    
	if(readc(pp, &c) != 1) 
		return; 
1994/1209    
 
1995/0114    
	pp->nioregs = 1<<(c&0x1f); 
	pp->bit16 = ((c>>5)&3) >= 2; 
1995/0223    
	ct->nioregs = 1<<(c&0x1f); 
	ct->bit16 = ((c>>5)&3) >= 2; 
1995/0114    
	if((c & 0x80) == 0) 
		return; 
1994/1209    
 
1995/0222/sys/src/9/pc/devi82365.c:1098,11111995/0223/sys/src/9/pc/devi82365.c:1124,1137
1995/0114    
		return; 
1994/1209    
 
1995/0114    
	for(i = (c&0xf)+1; i; i--){ 
		address = getlong(pp, (c>>4)&0x3); 
1995/0223    
		ct->port = getlong(pp, (c>>4)&0x3); 
1995/0114    
		len = getlong(pp, (c>>6)&0x3); 
		USED(address, len); 
1995/0223    
		USED(len); 
1994/1209    
	} 
} 
 
static void 
irq(Slot *pp) 
1995/0223    
irq(Slot *pp, Conftab *ct) 
1994/1209    
{ 
	uchar c; 
 
1995/0222/sys/src/9/pc/devi82365.c:1112,11201995/0223/sys/src/9/pc/devi82365.c:1138,1146
1994/1209    
	if(readc(pp, &c) != 1) 
		return; 
	if(c & 0x10) 
		pp->irqs = getlong(pp, 2); 
1995/0223    
		ct->irqs = getlong(pp, 2); 
1994/1209    
	else 
		pp->irqs = 1<<(c&0xf); 
1995/0223    
		ct->irqs = 1<<(c&0xf); 
1994/1209    
} 
 
static void 
1995/0222/sys/src/9/pc/devi82365.c:1135,11761995/0223/sys/src/9/pc/devi82365.c:1161,1218
1994/1209    
tentry(Slot *pp, int ttype) 
{ 
	uchar c, i, feature; 
1995/0223    
	Conftab *ct; 
1994/1209    
 
	USED(ttype); 
1995/0223    
 
	if(pp->nctab >= Maxctab) 
		return; 
1994/1209    
	if(readc(pp, &c) != 1) 
		return; 
	if(c&0x40) 
		pp->def = 1; 
1995/0223    
	ct = &pp->ctab[pp->nctab++]; 
 
	/* copy from last default config */ 
	if(pp->def) 
		*ct = *pp->def; 
 
	ct->index = c & 0x3f; 
 
	/* is this the new default? */ 
	if(c & 0x40) 
		pp->def = ct; 
 
	/* memory wait specified? */ 
1994/1209    
	if(c & 0x80){ 
		if(readc(pp, &i) != 1) 
			return; 
		if(i&0x80) 
			pp->memwait = 1; 
1995/0223    
			ct->memwait = 1; 
1994/1209    
	} 
1995/0223    
 
1994/1209    
	if(readc(pp, &feature) != 1) 
		return; 
	switch(feature&0x3){ 
	case 1: 
		pp->vpp1 = pp->vpp2 = power(pp); 
1995/0223    
		ct->vpp1 = ct->vpp2 = power(pp); 
1994/1209    
		break; 
	case 2: 
		power(pp); 
		pp->vpp1 = pp->vpp2 = power(pp); 
1995/0223    
		ct->vpp1 = ct->vpp2 = power(pp); 
1994/1209    
		break; 
	case 3: 
		power(pp); 
		pp->vpp1 = power(pp); 
		pp->vpp2 = power(pp); 
1995/0223    
		ct->vpp1 = power(pp); 
		ct->vpp2 = power(pp); 
1994/1209    
		break; 
	default: 
		break; 
	} 
	if(feature&0x4) 
		timing(pp); 
1995/0223    
		timing(pp, ct); 
1994/1209    
	if(feature&0x8) 
		iospaces(pp); 
1995/0223    
		iospaces(pp, ct); 
1994/1209    
	if(feature&0x10) 
		irq(pp); 
1995/0223    
		irq(pp, ct); 
1994/1209    
	switch(feature&0x3){ 
	case 1: 
		memspace(pp, 0, 2, 0); 
1995/0223/sys/src/9/pc/devi82365.c:100,1181995/0225/sys/src/9/pc/devi82365.c:100,107 (short | long)
1994/1209    
 
typedef struct I82365	I82365; 
typedef struct Slot	Slot; 
typedef struct PCMmap	PCMmap; 
1995/0223    
typedef struct Conftab	Conftab; 
1994/1209    
 
/* maps between ISA memory space and the card memory space */ 
struct PCMmap 
{ 
	ulong	ca;		/* card address */ 
	ulong	cea;		/* card end address */ 
	ulong	isa;		/* ISA address */ 
	int	attr;		/* attribute memory */ 
	int	time; 
}; 
                 
/* a controller */ 
enum 
{ 
1995/0223/sys/src/9/pc/devi82365.c:182,1981995/0225/sys/src/9/pc/devi82365.c:171,189
1995/0222    
	uchar	*cisbase; 
1994/1209    
 
	/* memory maps */ 
1995/0209    
	QLock	mlock;		/* lock down the maps */ 
1995/0225    
	Lock	mlock;		/* lock down the maps */ 
1994/1209    
	int	time; 
1995/0223    
	PCMmap	mmap[Nmap];	/* maps, last is always for the kernel */ 
	int	nmap;		/* number of maps */ 
1994/1209    
}; 
static Slot	*slot; 
static Slot	*lastslot; 
static nslot; 
 
static void cisread(Slot*); 
1995/0222    
static void i82365intr(Ureg*, void*); 
1995/0225    
static void	cisread(Slot*); 
static void	i82365intr(Ureg*, void*); 
static int	pcmio(int, ISAConf*); 
static long	pcmread(int, int, void*, long, ulong); 
static long	pcmwrite(int, int, void*, long, ulong); 
1994/1209    
 
/* 
 *  reading and writing card registers 
1995/0223/sys/src/9/pc/devi82365.c:304,3561995/0225/sys/src/9/pc/devi82365.c:295,402
1994/1209    
	} 
} 
 
1995/0225    
enum 
{ 
	Mshift=	12, 
	Mgran=	(1<<Mshift),	/* granularity of maps */ 
	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */ 
}; 
 
1994/1209    
/* 
 *  get a map for pc card region, return corrected len 
 */ 
static PCMmap* 
getmap(Slot *pp, ulong offset, int attr) 
1995/0225    
PCMmap* 
pcmmap(int slotno, ulong offset, int len, int attr) 
1994/1209    
{ 
1995/0225    
	Slot *pp; 
1994/1209    
	uchar we, bit; 
	PCMmap *m, *lru; 
1995/0225    
	PCMmap *m, *nm; 
1994/1209    
	int i; 
1995/0225    
	ulong e; 
1994/1209    
 
	/* look for a map that starts in the right place */ 
1995/0225    
	pp = slot + slotno; 
	lock(&pp->mlock); 
 
	/* convert offset to granularity */ 
	if(len <= 0) 
		len = 1; 
	e = ROUND(offset+len, Mgran); 
	offset &= Mmask; 
	len = e - offset; 
 
	/* look for a map that covers the right area */ 
1994/1209    
	we = rdreg(pp, Rwe); 
	bit = 1; 
	lru = pp->mmap; 
1995/0223    
	for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){ 
1994/1209    
		if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){ 
			m->time = pp->time++; 
1995/0225    
	nm = 0; 
	for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){ 
		if((we & bit)) 
		if(m->attr == attr) 
		if(offset >= m->ca && e <= m->cea){ 
 
			m->ref++; 
			unlock(&pp->mlock); 
1994/1209    
			return m; 
		} 
		bit <<= 1; 
		if(lru->time > m->time) 
			lru = m; 
1995/0225    
		if(nm == 0 && m->ref == 0) 
			nm = m; 
1994/1209    
	} 
1995/0225    
	m = nm; 
	if(m == 0){ 
		unlock(&pp->mlock); 
		return 0; 
	} 
1994/1209    
 
	/* use the least recently used */ 
	m = lru; 
	offset &= ~(Mchunk - 1); 
1995/0225    
	/* if isa space isn't big enough, free it and get more */ 
	if(m->len < len){ 
		if(m->isa){ 
			putisa(m->isa, m->len); 
			m->len = 0; 
		} 
		m->isa = getisa(0, len, Mgran)&~KZERO; 
		if(m->isa == 0){ 
			print("pcmmap: out of isa space\n"); 
			unlock(&pp->mlock); 
			return 0; 
		} 
		m->len = len; 
	} 
 
	/* set up new map */ 
1994/1209    
	m->ca = offset; 
	m->cea = m->ca + Mchunk; 
1995/0225    
	m->cea = m->ca + m->len; 
1994/1209    
	m->attr = attr; 
	m->time = pp->time++; 
	i = m - pp->mmap; 
1995/0225    
	i = m-pp->mmap; 
1994/1209    
	bit = 1<<i; 
	wrreg(pp, Rwe, we & ~bit);		/* disable map before changing it */ 
	wrreg(pp, MAP(i, Mbtmlo), m->isa>>12); 
	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(12+8)) | F16bit); 
	wrreg(pp, MAP(i, Mtoplo), (m->isa+Mchunk-1)>>12); 
1995/0223    
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) /*| Ftimer1/**/); 
1995/0225    
	wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift); 
	wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit); 
	wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift); 
	wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8))); 
1994/1209    
	offset -= m->isa; 
	offset &= (1<<25)-1; 
	offset >>= 12; 
1995/0225    
	offset >>= Mshift; 
1994/1209    
	wrreg(pp, MAP(i, Mofflo), offset); 
	wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0)); 
	wrreg(pp, Rwe, we | bit);		/* enable map */ 
1995/0225    
	m->ref = 1; 
 
	unlock(&pp->mlock); 
1994/1209    
	return m; 
} 
 
1995/0225    
void 
pcmunmap(int slotno, PCMmap* m) 
{ 
	Slot *pp; 
 
	pp = slot + slotno; 
	lock(&pp->mlock); 
	m->ref--; 
	unlock(&pp->mlock); 
} 
 
 
1994/1209    
static void 
increfp(Slot *pp) 
{ 
1995/0223/sys/src/9/pc/devi82365.c:554,5681995/0225/sys/src/9/pc/devi82365.c:600,605
1994/1209    
		} 
	} 
1995/0222    
 
1995/0223    
	/* get ISA address space for memory maps */ 
	for(i = 0; i < Nmap; i++) 
		for(pp = slot; pp < lastslot; pp++){ 
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); 
			if(pp->mmap[i].isa == 0) 
				break; 
			pp->nmap++; 
		} 
                 
1995/0222    
	/* for card management interrupts */ 
	setvec(PCMCIAvec, i82365intr, 0); 
1994/1209    
} 
1995/0223/sys/src/9/pc/devi82365.c:665,6711995/0225/sys/src/9/pc/devi82365.c:702,708
1994/1209    
	} 
} 
 
long 
1995/0225    
static long 
1995/0222    
pcmread(int slotno, int attr, void *a, long n, ulong offset) 
1994/1209    
{ 
	int i, len; 
1995/0223/sys/src/9/pc/devi82365.c:677,6981995/0225/sys/src/9/pc/devi82365.c:714,746
1995/0222    
	pp = slot + slotno; 
1994/1209    
	if(pp->memlen < offset) 
		return 0; 
	ac = a; 
	if(pp->memlen < offset + n) 
		n = pp->memlen - offset; 
1995/0225    
 
	m = 0; 
	if(waserror()){ 
		if(m) 
			pcmunmap(pp->slotno, m); 
		nexterror(); 
	} 
 
	ac = a; 
1994/1209    
	for(len = n; len > 0; len -= i){ 
		if(pp->occupied == 0 || pp->enabled == 0) 
			error(Eio); 
		m = getmap(pp, offset, attr); 
1995/0225    
		m = pcmmap(pp->slotno, offset, 0, attr); 
		if(m == 0) 
			error("can't map PCMCIA card"); 
1994/1209    
		if(offset + len > m->cea) 
			i = m->cea - offset; 
		else 
			i = len; 
		ka = KZERO|(m->isa + (offset&(Mchunk-1))); 
1995/0225    
		ka = KZERO|(m->isa + offset - m->ca); 
1995/0222    
		memmoveb(ac, (void*)ka, i); 
1995/0225    
		pcmunmap(pp->slotno, m); 
1994/1209    
		offset += i; 
		ac += i; 
	} 
1995/0225    
 
	poperror(); 
1994/1209    
	return n; 
} 
 
1995/0223/sys/src/9/pc/devi82365.c:715,7271995/0225/sys/src/9/pc/devi82365.c:763,769
1994/1209    
		return devdirread(c, a, n, 0, 0, pcmgen); 
	case Qmem: 
	case Qattr: 
1995/0222    
		pp = slot + SLOTNO(c); 
1995/0209    
		qlock(&pp->mlock); 
1995/0222    
		n = pcmread(SLOTNO(c), p==Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1994/1209    
		break; 
1995/0225    
		return pcmread(SLOTNO(c), p==Qattr, a, n, offset); 
1994/1209    
	case Qctl: 
		cp = buf; 
1995/0222    
		pp = slot + SLOTNO(c); 
1995/0223/sys/src/9/pc/devi82365.c:765,7711995/0225/sys/src/9/pc/devi82365.c:807,813
1995/0222    
	return devbwrite(c, bp, offset); 
1995/0108    
} 
 
1994/1209    
long 
1995/0225    
static long 
1994/1209    
pcmwrite(int dev, int attr, void *a, long n, ulong offset) 
{ 
	int i, len; 
1995/0223/sys/src/9/pc/devi82365.c:777,7961995/0225/sys/src/9/pc/devi82365.c:819,851
1994/1209    
	pp = slot + dev; 
	if(pp->memlen < offset) 
		return 0; 
	ac = a; 
	if(pp->memlen < offset + n) 
		n = pp->memlen - offset; 
1995/0225    
 
	m = 0; 
	if(waserror()){ 
		if(m) 
			pcmunmap(pp->slotno, m); 
		nexterror(); 
	} 
 
	ac = a; 
1994/1209    
	for(len = n; len > 0; len -= i){ 
		m = getmap(pp, offset, attr); 
1995/0225    
		m = pcmmap(pp->slotno, offset, 0, attr); 
		if(m == 0) 
			error("can't map PCMCIA card"); 
1994/1209    
		if(offset + len > m->cea) 
			i = m->cea - offset; 
		else 
			i = len; 
		ka = KZERO|(m->isa + (offset&(Mchunk-1))); 
1995/0225    
		ka = KZERO|(m->isa + offset - m->ca); 
1995/0222    
		memmoveb((void*)ka, ac, i); 
1995/0225    
		pcmunmap(pp->slotno, m); 
1994/1209    
		offset += i; 
		ac += i; 
	} 
1995/0225    
 
	poperror(); 
1994/1209    
	return n; 
} 
 
1995/0223/sys/src/9/pc/devi82365.c:807,8151995/0225/sys/src/9/pc/devi82365.c:862,868
1995/0222    
		pp = slot + SLOTNO(c); 
1994/1209    
		if(pp->occupied == 0 || pp->enabled == 0) 
			error(Eio); 
1995/0209    
		qlock(&pp->mlock); 
1995/0222    
		n = pcmwrite(pp->slotno, p == Qattr, a, n, offset); 
1995/0209    
		qunlock(&pp->mlock); 
		if(n < 0) 
			error(Eio); 
1994/1209    
		break; 
1995/0223/sys/src/9/pc/devi82365.c:823,8461995/0225/sys/src/9/pc/devi82365.c:876,901
1994/1209    
 *  configure the Slot for IO.  We assume very heavily that we can read 
 *  cofiguration info from the CIS.  If not, we won't set up correctly. 
 */ 
int 
pcmio(int dev, ISAConf *isa) 
1995/0225    
static int 
pcmio(int slotno, ISAConf *isa) 
1994/1209    
{ 
	uchar we, x; 
1995/0225    
	uchar we, x, *p; 
1994/1209    
	Slot *pp; 
1995/0223    
	Conftab *ct; 
1995/0225    
	PCMmap *m; 
1994/1209    
 
	if(dev > nslot) 
1995/0225    
	if(slotno > nslot) 
1994/1209    
		return -1; 
	pp = slot + dev; 
1995/0225    
	pp = slot + slotno; 
1994/1209    
 
	if(!pp->occupied) 
		return -1; 
 
1995/0223    
	/* find a configuration with the right port */ 
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) 
1995/0225    
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){ 
1995/0223    
		if(ct->nioregs && ct->port == isa->port) 
			break; 
1995/0225    
	} 
1995/0223    
 
	/* if non found, settle for one with the some ioregs */ 
	if(ct == &pp->ctab[pp->nctab]) 
1995/0223/sys/src/9/pc/devi82365.c:851,8641995/0225/sys/src/9/pc/devi82365.c:906,917
1995/0223    
	if(ct == &pp->ctab[pp->nctab]) 
1994/1209    
		return -1; 
 
1995/0223    
print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs); 
                 
	/* route interrupts */ 
1994/1209    
	if(isa->irq == 2) 
		isa->irq = 9; 
	wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); 
	 
	/* set power and enable device */ 
1995/0225    
	/* set power and enable slotnoice */ 
1995/0223    
	x = vcode(ct->vpp1); 
1994/1209    
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); 
 
1995/0223/sys/src/9/pc/devi82365.c:868,8741995/0225/sys/src/9/pc/devi82365.c:921,927
1994/1209    
 
	/* enable io port map 0 */ 
	if(isa->port == 0) 
1995/0118    
		isa->port = 0x300; 
1995/0225    
		isa->port = ct->port; 
1994/1209    
	we = rdreg(pp, Rwe); 
	wrreg(pp, Riobtm0lo, isa->port); 
	wrreg(pp, Riobtm0hi, isa->port>>8); 
1995/0223/sys/src/9/pc/devi82365.c:879,8891995/0225/sys/src/9/pc/devi82365.c:932,942
1994/1209    
	/* only touch Rconfig if it is present */ 
	if(pp->cpresent & (1<<Rconfig)){ 
		/*  Reset adapter */ 
		x = Creset; 
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
1995/0225    
		m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1); 
		p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca)); 
		*p = Creset; 
1995/0222    
		delay(5); 
1994/1209    
		x = 0; 
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
1995/0225    
		*p = 0; 
1995/0222    
		delay(5); 
1994/1209    
	 
		/* 
1995/0223/sys/src/9/pc/devi82365.c:892,9021995/0225/sys/src/9/pc/devi82365.c:945,955
1994/1209    
		 *  Setting the configuration number enables IO port access. 
		 */ 
1995/0223    
		if(isa->irq > 7) 
			x = Clevel | ct->index; 
1995/0225    
			*p = Clevel | ct->index; 
1995/0223    
		else 
			x = ct->index; 
1994/1209    
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); 
1995/0225    
			*p = ct->index; 
1995/0222    
		delay(5); 
1995/0225    
		pcmunmap(slotno, m); 
1994/1209    
	} 
	return 0; 
} 
1995/0223/sys/src/9/pc/devi82365.c:940,9461995/0225/sys/src/9/pc/devi82365.c:993,999
1995/0223    
	pp->configed = 0; 
	pp->nctab = 0; 
1994/1209    
 
	m = getmap(pp, 0, 1); 
1995/0225    
	m = pcmmap(pp->slotno, 0, 0, 1); 
1995/0222    
	if(m == 0) 
		return; 
	pp->cisbase = (uchar*)(KZERO|m->isa); 
1995/0223/sys/src/9/pc/devi82365.c:959,9641995/0225/sys/src/9/pc/devi82365.c:1012,1018
1994/1209    
			break; 
1995/0222    
		pp->cispos = this + (2+link); 
1994/1209    
	} 
1995/0225    
	pcmunmap(pp->slotno, m); 
1994/1209    
} 
 
static ulong 
1995/0225/sys/src/9/pc/devi82365.c:559,5641995/0328/sys/src/9/pc/devi82365.c:559,577 (short | long)
1994/1209    
	return cp; 
} 
 
1995/0328    
static void 
i82365dump(Slot *pp) 
{ 
	int i; 
 
	for(i = 0; i < 0x40; i++){ 
		if((i&0x7) == 0) 
			print("\n%ux:	", i); 
		print("%ux ", rdreg(pp, i)); 
	} 
	print("\n"); 
} 
 
1994/1209    
/* 
 *  set up for slot cards 
 */ 
1995/0225/sys/src/9/pc/devi82365.c:593,5991995/0328/sys/src/9/pc/devi82365.c:606,615
1995/0223    
			pp->memlen = 64*MB; 
			pp->base = (cp->dev<<7) | (j<<6); 
			pp->cp = cp; 
1995/0328    
if(pp == slot)i82365dump(pp); 
/* 
1995/0223    
			slotdis(pp); 
1995/0328    
*/ 
1995/0223    
 
			/* interrupt on status change */ 
			wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); 
1995/0225/sys/src/9/pc/devi82365.c:780,7971995/0328/sys/src/9/pc/devi82365.c:796,801
1994/1209    
		if(pp->busy) 
			cp += sprint(cp, "busy\n"); 
		cp += sprint(cp, "battery lvl %d\n", pp->battery); 
1995/0222    
{ 
	int i; 
                 
	cp += sprint(cp, "x %x d %x b %x\n", pp->cp->xreg, pp->cp->dreg, pp->base); 
	for(i = 0; i < 0x40; i++){ 
		cp += sprint(cp, "%2.2ux ", rdreg(pp, i)); 
		if((i%8) == 7) 
			cp += sprint(cp, "\n"); 
	} 
	if(i%8) 
		cp += sprint(cp, "\n"); 
} 
1994/1209    
		*cp = 0; 
		return readstr(offset, a, n, buf); 
	default: 
1995/0225/sys/src/9/pc/devi82365.c:934,9541995/0328/sys/src/9/pc/devi82365.c:938,958
1994/1209    
		/*  Reset adapter */ 
1995/0225    
		m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1); 
		p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca)); 
1995/0328    
if(strstr(pp->verstr, "KeepInTouch") == 0){ 
1995/0225    
		*p = Creset; 
1995/0222    
		delay(5); 
1995/0225    
		*p = 0; 
1995/0222    
		delay(5); 
1994/1209    
	                 
		/* 
		 *  Set level sensitive (not pulsed) interrupts and 
		 *  configuration number 1. 
		 *  Setting the configuration number enables IO port access. 
		 */ 
1995/0328    
} 
 
		/* set configuration */ 
if(strstr(pp->verstr, "KeepInTouch") == 0){ 
1995/0223    
		if(isa->irq > 7) 
1995/0225    
			*p = Clevel | ct->index; 
1995/0223    
		else 
1995/0225    
			*p = ct->index; 
1995/0222    
		delay(5); 
1995/0328    
} else i82365dump(pp); 
1995/0225    
		pcmunmap(slotno, m); 
1994/1209    
	} 
	return 0; 
1995/0225/sys/src/9/pc/devi82365.c:1306,13081995/0328/sys/src/9/pc/devi82365.c:1310,1313
1995/0111    
	} 
	pp->verstr[i] = 0; 
1994/1209    
} 
1995/0328    
 
1995/0328/sys/src/9/pc/devi82365.c:41,461995/0329/sys/src/9/pc/devi82365.c:41,49 (short | long)
1994/1209    
	Rwe= 		0x6,		/* address window enable */ 
	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */ 
	Rio= 		0x7,		/* I/O control */ 
1995/0329    
	 Fwidth16=	 (1<<0),	/*  16 bit data width */ 
	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */ 
	 Ftiming=	 (1<<3),	/*  timing register to use */ 
1994/1209    
	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 */ 
1995/0328/sys/src/9/pc/devi82365.c:126,1311995/0329/sys/src/9/pc/devi82365.c:129,135
1995/0223    
	int	index; 
	ushort	irqs;		/* legal irqs */ 
	ushort	port;		/* port address */ 
1995/0329    
	uchar	irqtype; 
1995/0223    
	uchar	nioregs;	/* number of io registers */ 
	uchar	bit16;		/* true for 16 bit access */ 
	uchar	vpp1; 
1995/0328/sys/src/9/pc/devi82365.c:239,2521995/0329/sys/src/9/pc/devi82365.c:243,262
1994/1209    
	if(pp->enabled) 
		return; 
 
1995/0223    
	/* power up and reset, wait's are empirical (???) */ 
1995/0329    
	/* power up and unreset, wait's are empirical (???) */ 
1995/0223    
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena); 
	delay(300); 
1995/0222    
	wrreg(pp, Rigc, 0); 
	delay(100); 
	wrreg(pp, Rigc, Fnotreset); 
1995/0223    
	delay(500); 
1994/1209    
 
1995/0329    
	wrreg(pp, Rpc, 0); 
	delay(500); 
 
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena); 
	delay(300); 
	wrreg(pp, Rigc, Fnotreset); 
	delay(500); 
 
1995/0223    
	/* get configuration */ 
1994/1209    
	slotinfo(pp); 
	if(pp->occupied){ 
1995/0328/sys/src/9/pc/devi82365.c:253,2591995/0329/sys/src/9/pc/devi82365.c:263,269
1994/1209    
		cisread(pp); 
1995/0223    
		pp->enabled = 1; 
1995/0222    
	} else 
1995/0223    
		wrreg(pp, Rpc, Fautopower); 
1995/0329    
		wrreg(pp, Rpc, 0); 
1994/1209    
} 
 
/* 
1995/0328/sys/src/9/pc/devi82365.c:262,2691995/0329/sys/src/9/pc/devi82365.c:272,279
1994/1209    
static void 
slotdis(Slot *pp) 
{ 
1995/0223    
	wrreg(pp, Rpc, Fautopower);		/* turn off card */ 
1995/0222    
	wrreg(pp, Rwe, 0);			/* no windows */ 
1995/0329    
	wrreg(pp, Rwe, 0);		/* no windows */ 
	wrreg(pp, Rpc, 0);		/* turn off card power */ 
1994/1209    
	pp->enabled = 0; 
} 
 
1995/0328/sys/src/9/pc/devi82365.c:606,6151995/0329/sys/src/9/pc/devi82365.c:616,622
1995/0223    
			pp->memlen = 64*MB; 
			pp->base = (cp->dev<<7) | (j<<6); 
			pp->cp = cp; 
1995/0328    
if(pp == slot)i82365dump(pp); 
/* 
1995/0223    
			slotdis(pp); 
1995/0328    
*/ 
1995/0223    
 
			/* interrupt on status change */ 
			wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); 
1995/0328/sys/src/9/pc/devi82365.c:796,8011995/0329/sys/src/9/pc/devi82365.c:803,818
1994/1209    
		if(pp->busy) 
			cp += sprint(cp, "busy\n"); 
		cp += sprint(cp, "battery lvl %d\n", pp->battery); 
1995/0329    
{ 
	int i; 
 
	for(i = 0; i < 0x40; i++){ 
		if((i&0x7) == 0) 
			cp += sprint(cp, "\n%ux:	", i); 
		cp += sprint(cp, "%ux ", rdreg(pp, i)); 
	} 
	cp += sprint(cp, "\n"); 
} 
1994/1209    
		*cp = 0; 
		return readstr(offset, a, n, buf); 
	default: 
1995/0328/sys/src/9/pc/devi82365.c:915,9271995/0329/sys/src/9/pc/devi82365.c:932,947
1994/1209    
		isa->irq = 9; 
	wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); 
	 
1995/0225    
	/* set power and enable slotnoice */ 
1995/0329    
	/* set power and enable device */ 
1995/0223    
	x = vcode(ct->vpp1); 
1994/1209    
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); 
 
	/* 16-bit data path */ 
1995/0223    
	if(ct->bit16) 
1994/1209    
		wrreg(pp, Rio, (1<<0)|(1<<1)); 
1995/0329    
		x = Fiocs16|Fwidth16; 
	else 
		x = 0; 
	wrreg(pp, Rio, Ftiming|x); 
1994/1209    
 
	/* enable io port map 0 */ 
	if(isa->port == 0) 
1995/0328/sys/src/9/pc/devi82365.c:929,9361995/0329/sys/src/9/pc/devi82365.c:949,956
1994/1209    
	we = rdreg(pp, Rwe); 
	wrreg(pp, Riobtm0lo, isa->port); 
	wrreg(pp, Riobtm0hi, isa->port>>8); 
1995/0223    
	wrreg(pp, Riotop0lo, (isa->port+ct->nioregs)); 
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8); 
1995/0329    
	wrreg(pp, Riotop0lo, (isa->port+ct->nioregs-1)); 
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs-1)>>8); 
1994/1209    
	wrreg(pp, Rwe, we | (1<<6)); 
 
	/* only touch Rconfig if it is present */ 
1995/0328/sys/src/9/pc/devi82365.c:938,9581995/0329/sys/src/9/pc/devi82365.c:958,971
1994/1209    
		/*  Reset adapter */ 
1995/0225    
		m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1); 
		p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca)); 
1995/0328    
if(strstr(pp->verstr, "KeepInTouch") == 0){ 
1995/0225    
		*p = Creset; 
1995/0222    
		delay(5); 
1995/0225    
		*p = 0; 
1995/0222    
		delay(5); 
1995/0328    
} 
 
		/* set configuration */ 
if(strstr(pp->verstr, "KeepInTouch") == 0){ 
1995/0223    
		if(isa->irq > 7) 
1995/0225    
			*p = Clevel | ct->index; 
1995/0223    
		else 
1995/0225    
			*p = ct->index; 
1995/0329    
		/* set configuration and interrupt type */ 
		x = ct->index; 
		if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7)) 
			x |= Clevel; 
		*p = x|ct->index; 
1995/0222    
		delay(5); 
1995/0328    
} else i82365dump(pp); 
1995/0329    
 
1995/0225    
		pcmunmap(slotno, m); 
1994/1209    
	} 
	return 0; 
1995/0328/sys/src/9/pc/devi82365.c:1066,10801995/0329/sys/src/9/pc/devi82365.c:1079,1104
1994/1209    
{ 
	uchar c; 
	ulong microvolts; 
1995/0329    
	ulong exp; 
1994/1209    
 
	if(readc(pp, &c) != 1) 
		return 0; 
	microvolts = vexp[c&0x7]*vmant[(c>>3)&0xf]; 
1995/0329    
	exp = vexp[c&0x7]; 
	microvolts = vmant[(c>>3)&0xf]*exp; 
1994/1209    
	while(c & 0x80){ 
		if(readc(pp, &c) != 1) 
			return 0; 
		if(c == 0x7d || c == 0x7e || c == 0x7f) 
			microvolts = 0; 
1995/0329    
		switch(c){ 
		case 0x7d: 
			break;		/* high impedence when sleeping */ 
		case 0x7e: 
		case 0x7f: 
			microvolts = 0;	/* no connection */ 
			break; 
		default: 
			exp /= 10; 
			microvolts += exp*(c&0x7f); 
		} 
1994/1209    
	} 
	return microvolts; 
} 
1995/0328/sys/src/9/pc/devi82365.c:1121,11271995/0329/sys/src/9/pc/devi82365.c:1145,1151
1994/1209    
		nanoamps(pp); 
	if(feature & 0x20) 
		nanoamps(pp); 
	if(feature & 0x20) 
1995/0329    
	if(feature & 0x40) 
1994/1209    
		nanoamps(pp); 
	return mv/1000000; 
} 
1995/0328/sys/src/9/pc/devi82365.c:1195,12001995/0329/sys/src/9/pc/devi82365.c:1219,1225
1994/1209    
 
	if(readc(pp, &c) != 1) 
		return; 
1995/0329    
	ct->irqtype = c & 0xe0; 
1994/1209    
	if(c & 0x10) 
1995/0223    
		ct->irqs = getlong(pp, 2); 
1994/1209    
	else 
1995/0328/sys/src/9/pc/devi82365.c:1271,12771995/0329/sys/src/9/pc/devi82365.c:1296,1302
1995/0223    
		iospaces(pp, ct); 
1994/1209    
	if(feature&0x10) 
1995/0223    
		irq(pp, ct); 
1994/1209    
	switch(feature&0x3){ 
1995/0329    
	switch((feature>>5)&0x3){ 
1994/1209    
	case 1: 
		memspace(pp, 0, 2, 0); 
		break; 
1995/0329/sys/src/9/pc/devi82365.c:246,2621995/0331/sys/src/9/pc/devi82365.c:246,256 (short | long)
1995/0329    
	/* power up and unreset, wait's are empirical (???) */ 
1995/0223    
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena); 
	delay(300); 
1995/0331    
	wrreg(pp, Rigc, 0); 
	delay(100); 
1995/0222    
	wrreg(pp, Rigc, Fnotreset); 
1995/0223    
	delay(500); 
1994/1209    
 
1995/0329    
	wrreg(pp, Rpc, 0); 
	delay(500); 
                 
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena); 
	delay(300); 
	wrreg(pp, Rigc, Fnotreset); 
	delay(500); 
                 
1995/0223    
	/* get configuration */ 
1994/1209    
	slotinfo(pp); 
	if(pp->occupied){ 
1995/0329/sys/src/9/pc/devi82365.c:263,2691995/0331/sys/src/9/pc/devi82365.c:257,263
1994/1209    
		cisread(pp); 
1995/0223    
		pp->enabled = 1; 
1995/0222    
	} else 
1995/0329    
		wrreg(pp, Rpc, 0); 
1995/0331    
		wrreg(pp, Rpc, Fautopower); 
1994/1209    
} 
 
/* 
1995/0329/sys/src/9/pc/devi82365.c:272,2791995/0331/sys/src/9/pc/devi82365.c:266,273
1994/1209    
static void 
slotdis(Slot *pp) 
{ 
1995/0329    
	wrreg(pp, Rwe, 0);		/* no windows */ 
	wrreg(pp, Rpc, 0);		/* turn off card power */ 
1995/0331    
	wrreg(pp, Rpc, 0);	/* turn off card power */ 
	wrreg(pp, Rwe, 0);	/* no windows */ 
1994/1209    
	pp->enabled = 0; 
} 
 
1995/0329/sys/src/9/pc/devi82365.c:1306,13121995/0331/sys/src/9/pc/devi82365.c:1300,1306
1994/1209    
	case 3: 
		if(readc(pp, &c) != 1) 
			return; 
		for(i = 0; i <= c&0x7; i++) 
1995/0331    
		for(i = 0; i <= (c&0x7); i++) 
1994/1209    
			memspace(pp, (c>>5)&0x3, (c>>3)&0x3, c&0x80); 
		break; 
	} 
1995/0331/sys/src/9/pc/devi82365.c:898,9041995/0401/sys/src/9/pc/devi82365.c:898,909 (short | long)
1994/1209    
	Slot *pp; 
1995/0223    
	Conftab *ct; 
1995/0225    
	PCMmap *m; 
1995/0401    
	int irq; 
1994/1209    
 
1995/0401    
	irq = isa->irq; 
	if(irq == 2) 
		irq = 9; 
 
1995/0225    
	if(slotno > nslot) 
1994/1209    
		return -1; 
1995/0225    
	pp = slot + slotno; 
1995/0331/sys/src/9/pc/devi82365.c:908,9141995/0401/sys/src/9/pc/devi82365.c:913,919
1994/1209    
 
1995/0223    
	/* find a configuration with the right port */ 
1995/0225    
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){ 
1995/0223    
		if(ct->nioregs && ct->port == isa->port) 
1995/0401    
		if(ct->nioregs && ct->port == isa->port && ((1<<irq) & ct->irqs)) 
1995/0223    
			break; 
1995/0225    
	} 
1995/0223    
 
1995/0331/sys/src/9/pc/devi82365.c:915,9211995/0401/sys/src/9/pc/devi82365.c:920,926
1995/0223    
	/* if non found, settle for one with the some ioregs */ 
	if(ct == &pp->ctab[pp->nctab]) 
		for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) 
			if(ct->nioregs) 
1995/0401    
			if(ct->nioregs && ((1<<irq) & ct->irqs)) 
1995/0223    
				break; 
 
	if(ct == &pp->ctab[pp->nctab]) 
1995/0331/sys/src/9/pc/devi82365.c:922,9301995/0401/sys/src/9/pc/devi82365.c:927,934
1994/1209    
		return -1; 
 
1995/0223    
	/* route interrupts */ 
1994/1209    
	if(isa->irq == 2) 
		isa->irq = 9; 
	wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); 
1995/0401    
	isa->irq = irq; 
	wrreg(pp, Rigc, irq | Fnotreset | Fiocard); 
1994/1209    
	 
1995/0329    
	/* set power and enable device */ 
1995/0223    
	x = vcode(ct->vpp1); 
1995/0331/sys/src/9/pc/devi82365.c:957,9631995/0401/sys/src/9/pc/devi82365.c:961,967
1995/0329    
		x = ct->index; 
		if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7)) 
			x |= Clevel; 
		*p = x|ct->index; 
1995/0401    
		*p = x; 
1995/0222    
		delay(5); 
1995/0329    
 
1995/0225    
		pcmunmap(slotno, m); 
1995/0331/sys/src/9/pc/devi82365.c:1218,12231995/0401/sys/src/9/pc/devi82365.c:1222,1228
1995/0223    
		ct->irqs = getlong(pp, 2); 
1994/1209    
	else 
1995/0223    
		ct->irqs = 1<<(c&0xf); 
1995/0401    
	ct->irqs &= 0xDEB8;		/* levels available to card */ 
1994/1209    
} 
 
static void 
1995/0401/sys/src/9/pc/devi82365.c:869,8771995/0519/sys/src/9/pc/devi82365.c:869,891 (short | long)
1994/1209    
{ 
	ulong p; 
	Slot *pp; 
1995/0519    
	char buf[32]; 
1994/1209    
 
	p = TYPE(c); 
	switch(p){ 
1995/0519    
	case Qctl: 
		if(n >= sizeof(buf)) 
			n = sizeof(buf) - 1; 
		strncpy(buf, a, n); 
		buf[n] = 0; 
		pp = slot + SLOTNO(c); 
		if(!pp->occupied) 
			error(Eio); 
 
		/* set vpp on card */ 
		if(strncmp(buf, "vpp", 3) == 0) 
			wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena); 
		break; 
1994/1209    
	case Qmem: 
	case Qattr: 
1995/0222    
		pp = slot + SLOTNO(c); 
1995/0519/sys/src/9/pc/devi82365.c:665,6871995/0726/sys/src/9/pc/devi82365.c:665,684 (short | long)
1994/1209    
} 
 
void 
i82365create(Chan *c, char *name, int omode, ulong perm) 
1995/0726    
i82365create(Chan*, char*, int, ulong) 
1994/1209    
{ 
	USED(c, name, omode, perm); 
	error(Eperm); 
} 
 
void 
i82365remove(Chan *c) 
1995/0726    
i82365remove(Chan*) 
1994/1209    
{ 
	USED(c); 
	error(Eperm); 
} 
 
void 
i82365wstat(Chan *c, char *dp) 
1995/0726    
i82365wstat(Chan*, char*) 
1994/1209    
{ 
	USED(c, dp); 
	error(Eperm); 
} 
 
1995/0726/sys/src/9/pc/devi82365.c:277,2821995/1006/sys/src/9/pc/devi82365.c:277,283 (short | long)
1994/1209    
static void 
1995/0222    
i82365intr(Ureg *ur, void *a) 
1994/1209    
{ 
1995/1006    
	int tries, changed; 
1995/0222    
	uchar csc, was; 
1994/1209    
	Slot *pp; 
 
1995/0726/sys/src/9/pc/devi82365.c:284,3011995/1006/sys/src/9/pc/devi82365.c:285,309
1995/0222    
	if(slot == 0) 
		return; 
 
1994/1209    
	for(pp = slot; pp < lastslot; pp++){ 
		csc = rdreg(pp, Rcsc); 
1995/0222    
		was = pp->occupied; 
1994/1209    
		slotinfo(pp); 
1995/0222    
		if(csc & (1<<3) && was != pp->occupied){ 
			if(pp->occupied) 
				print("slot%d card inserted\n", pp->slotno); 
			else { 
				print("slot%d card removed\n", pp->slotno); 
1994/1209    
				slotdis(pp); 
1995/1006    
	changed = 0; 
	for(tries = 0; tries < 5; tries++){ 
		for(pp = slot; pp < lastslot; pp++){ 
			csc = rdreg(pp, Rcsc); 
			was = pp->occupied; 
			slotinfo(pp); 
			if(csc & (1<<3) && was != pp->occupied){ 
				changed++; 
				if(pp->occupied) 
					print("slot%d card inserted\n", pp->slotno); 
				else { 
					print("slot%d card removed\n", pp->slotno); 
					slotdis(pp); 
				} 
1994/1209    
			} 
		} 
1995/1006    
		if(changed) 
			break; 
		delay(100); 
1994/1209    
	} 
} 
 
1995/1006/sys/src/9/pc/devi82365.c:277,2831995/1007/sys/src/9/pc/devi82365.c:277,282 (short | long)
1994/1209    
static void 
1995/0222    
i82365intr(Ureg *ur, void *a) 
1994/1209    
{ 
1995/1006    
	int tries, changed; 
1995/0222    
	uchar csc, was; 
1994/1209    
	Slot *pp; 
 
1995/1006/sys/src/9/pc/devi82365.c:285,3091995/1007/sys/src/9/pc/devi82365.c:284,301
1995/0222    
	if(slot == 0) 
		return; 
 
1995/1006    
	changed = 0; 
	for(tries = 0; tries < 5; tries++){ 
		for(pp = slot; pp < lastslot; pp++){ 
			csc = rdreg(pp, Rcsc); 
			was = pp->occupied; 
			slotinfo(pp); 
			if(csc & (1<<3) && was != pp->occupied){ 
				changed++; 
				if(pp->occupied) 
					print("slot%d card inserted\n", pp->slotno); 
				else { 
					print("slot%d card removed\n", pp->slotno); 
					slotdis(pp); 
				} 
1995/1007    
	for(pp = slot; pp < lastslot; pp++){ 
		csc = rdreg(pp, Rcsc); 
		was = pp->occupied; 
		slotinfo(pp); 
		if(csc & (1<<3) && was != pp->occupied){ 
			if(pp->occupied) 
				print("slot%d card inserted\n", pp->slotno); 
			else { 
				print("slot%d card removed\n", pp->slotno); 
				slotdis(pp); 
1994/1209    
			} 
		} 
1995/1006    
		if(changed) 
			break; 
		delay(100); 
1994/1209    
	} 
} 
 
1995/1007/sys/src/9/pc/devi82365.c:538,5491995/1017/sys/src/9/pc/devi82365.c:538,549 (short | long)
1994/1209    
		outb(x, Rchipinfo + (dev<<7)); 
		outb(d, 0); 
		c = inb(d); 
		if((c & 0xdf) == 0xdc){ 
			c = inb(d); 
			if((c & 0xdf) != 0x0c) 
				break; 
		} 
		if(c & 0x40){ 
1995/1017    
		if((c & 0xc0) != 0xc0) 
			break; 
		c = inb(d); 
		if((c & 0xc0) != 0x00) 
			break; 
		if(c & 0x20){ 
1994/1209    
			cp->type = Tpd6720; 
		} else { 
			cp->type = Tpd6710; 
1995/1007/sys/src/9/pc/devi82365.c:907,9131995/1017/sys/src/9/pc/devi82365.c:907,913
1994/1209    
{ 
1995/0225    
	uchar we, x, *p; 
1994/1209    
	Slot *pp; 
1995/0223    
	Conftab *ct; 
1995/1017    
	Conftab *ct, *et, *t; 
1995/0225    
	PCMmap *m; 
1995/0401    
	int irq; 
1994/1209    
 
1995/1007/sys/src/9/pc/devi82365.c:922,9401995/1017/sys/src/9/pc/devi82365.c:922,959
1994/1209    
	if(!pp->occupied) 
		return -1; 
 
1995/0223    
	/* find a configuration with the right port */ 
1995/0225    
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){ 
1995/0401    
		if(ct->nioregs && ct->port == isa->port && ((1<<irq) & ct->irqs)) 
1995/0223    
			break; 
1995/0225    
	} 
1995/1017    
	et = &pp->ctab[pp->nctab]; 
1995/0223    
 
	/* if non found, settle for one with the some ioregs */ 
	if(ct == &pp->ctab[pp->nctab]) 
		for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) 
1995/0401    
			if(ct->nioregs && ((1<<irq) & ct->irqs)) 
1995/1017    
	/* assume default is right */ 
	if(pp->def) 
		ct = pp->def; 
	else 
		ct = pp->ctab; 
 
	/* try for best match */ 
	if(ct->nioregs == 0 || ct->port != isa->port || ((1<<irq) & ct->irqs) == 0){ 
		for(t = pp->ctab; t < et; t++) 
			if(t->nioregs && t->port == isa->port && ((1<<irq) & t->irqs)){ 
				ct = t; 
1995/0223    
				break; 
1995/1017    
			} 
	} 
	if(ct->nioregs == 0 || ((1<<irq) & ct->irqs) == 0){ 
		for(t = pp->ctab; t < et; t++) 
			if(t->nioregs && ((1<<irq) & t->irqs)){ 
				ct = t; 
				break; 
			} 
	} 
	if(ct->nioregs == 0){ 
		for(t = pp->ctab; t < et; t++) 
			if(t->nioregs){ 
				ct = t; 
				break; 
			} 
	} 
1995/0223    
 
	if(ct == &pp->ctab[pp->nctab]) 
1995/1017    
	if(ct == et || ct->nioregs == 0) 
1994/1209    
		return -1; 
 
1995/0223    
	/* route interrupts */ 
1995/1017/sys/src/9/pc/devi82365.c:289,3001995/1027/sys/src/9/pc/devi82365.c:289,296 (short | long)
1995/1007    
		was = pp->occupied; 
		slotinfo(pp); 
		if(csc & (1<<3) && was != pp->occupied){ 
			if(pp->occupied) 
				print("slot%d card inserted\n", pp->slotno); 
			else { 
				print("slot%d card removed\n", pp->slotno); 
1995/1027    
			if(!pp->occupied) 
1995/1007    
				slotdis(pp); 
1994/1209    
			} 
		} 
	} 
} 
1995/1027/sys/src/9/pc/devi82365.c:1265,12711995/1121/sys/src/9/pc/devi82365.c:1265,1271 (short | long)
1994/1209    
	} 
} 
 
void 
1995/1121    
static void 
1994/1209    
tentry(Slot *pp, int ttype) 
{ 
	uchar c, i, feature; 
1995/1027/sys/src/9/pc/devi82365.c:1338,13441995/1121/sys/src/9/pc/devi82365.c:1338,1344
1994/1209    
	pp->configed++; 
1995/0111    
} 
 
void 
1995/1121    
static void 
1995/0111    
tvers1(Slot *pp, int ttype) 
{ 
	uchar c, major, minor; 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)