Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/devi82365.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/devi82365.c 1994/1209
## diff -e /dev/null /n/fornaxdump/1994/1209/sys/src/brazil/pc/devi82365.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"

/*
 *  Support for up to 4 Slot card slots.  Generalizing above that is hard
 *  since addressing is not obvious. - presotto
 *
 *  WARNING: This has never been tried with more than one card slot.
 */

/*
 *  Intel 82365SL PCIC controller for the Slot 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 */
	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 */
	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 */
	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 */
	Mofflo=		0x4,		/* Card memory offset address low byte */
	Moffhi=		0x5,		/* Card memory offset address high byte */
	 Fregactive=	 (1<<6),	/*  attribute meory */

	Mbits=		13,		/* msb of Mchunk */
	Mchunk=		1<<Mbits,	/* logical mapping granularity */
	Nmap=		4,		/* max number of maps to use */

	/*
	 *  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 */
};

#define MAP(x,o)	(Rmap + (x)*0x8 + o)

typedef struct I82365	I82365;
typedef struct Slot	Slot;
typedef struct PCMmap	PCMmap;

/* 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
{
	Ti82365,
	Tpd6710,
	Tpd6720,
};
struct I82365
{
	QLock;
	int	type;
	int	dev;
	int	nslot;
	int	xreg;		/* index register address */
	int	dreg;		/* data register address */
};
static I82365 *controller[4];
static int ncontroller;

/* a Slot slot */
struct Slot
{
	int	ref;

	I82365	*cp;		/* controller for this slot */
	long	memlen;		/* memory length */
	uchar	base;		/* index register base */
	uchar	dev;		/* slot number */

	/* 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;
	uchar	powered;
	uchar	configed;
	uchar	enabled;
	uchar	iocard;
	uchar	busy;

	/* cis info */
	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 */
	uchar	*cisbase;	/* base of mapped in attribute space */
	uchar	*cispos;	/* current position scanning cis */

	/* memory maps */
	int	time;
	PCMmap	mmap[Nmap];
};
static Slot	*slot;
static Slot	*lastslot;
static nslot;

static void cisread(Slot*);

/*
 *  reading and writing card registers
 */
static uchar
rdreg(Slot *pp, int index)
{
	outb(pp->cp->xreg, pp->base + index);
	return inb(pp->cp->dreg);
}
static void
wrreg(Slot *pp, int index, uchar val)
{
	outb(pp->cp->xreg, pp->base + index);
	outb(pp->cp->dreg, val);
}

/*
 *  get info about card
 */
static void
slotinfo(Slot *pp)
{
	uchar isr;

	isr = rdreg(pp, Ris);
	pp->occupied = (isr & (3<<2)) == (3<<2);
	pp->powered = isr & (1<<6);
	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
vcode(int volt)
{
	switch(volt){
	case 5:
		return 1;
	case 12:
		return 2;
	default:
		return 0;
	}
}

/*
 *  enable the slot card
 */
static void
slotena(Slot *pp)
{
	int x;

	if(pp->enabled)
		return;

	if(pp->already == 0){
		pp->already = 1;

		/* 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);
		}

	}
}

/*
 *  disable the slot card
 */
static void
slotdis(Slot *pp)
{
	/* disable the windows into the card */
	wrreg(pp, Rwe, 0);

	/* disable the card */
	wrreg(pp, Rpc, 5|Fautopower);
	pp->enabled = 0;
}

/*
 *  status change interrupt
 */
static void
i82365intr(Ureg *ur)
{
	uchar csc;
	Slot *pp;

	USED(ur);
	for(pp = slot; pp < lastslot; pp++){
		csc = rdreg(pp, Rcsc);
		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);
				slotdis(pp);
			}
		}
	}
}

/*
 *  get a map for pc card region, return corrected len
 */
static PCMmap*
getmap(Slot *pp, ulong offset, int attr)
{
	uchar we, bit;
	PCMmap *m, *lru;
	int i;

	if(pp->gotmem == 0){
		pp->gotmem = 1;

		/* grab ISA address space for memory maps */
		for(i = 0; i < Nmap; i++)
			pp->mmap[i].isa = isamem(Mchunk);
	}

	/* 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++){
		if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){
			m->time = pp->time++;
			return m;
		}
		bit <<= 1;
		if(lru->time > m->time)
			lru = m;
	}

	/* use the least recently used */
	m = lru;
	offset &= ~(Mchunk - 1);
	m->ca = offset;
	m->cea = m->ca + Mchunk;
	m->attr = attr;
	m->time = pp->time++;
	i = m - pp->mmap;
	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);
	wrreg(pp, MAP(i, Mtophi), (m->isa+Mchunk-1)>>(12+8));
	offset -= m->isa;
	offset &= (1<<25)-1;
	offset >>= 12;
	wrreg(pp, MAP(i, Mofflo), offset);
	wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
	wrreg(pp, Rwe, we | bit);		/* enable map */
	return m;
}

static void
increfp(Slot *pp)
{
	qlock(pp->cp);
	if(pp->ref++ == 0)
		slotena(pp);
	qunlock(pp->cp);
}

static void
decrefp(Slot *pp)
{
	qlock(pp->cp);
	if(pp->ref-- == 1)
		slotdis(pp);
	qunlock(pp->cp);
}

int
pcmspecial(int dev)
{
	Slot *pp;

	i82365reset();
	if(dev >= nslot)
		return -1;
	pp = slot + dev;
	if(pp->special)
		return -1;
	increfp(pp);
	if(!pp->occupied){
		decrefp(pp);
		return -1;
	}
	pp->special = 1;
	return 0;
}

void
pcmspecialclose(int dev)
{
	Slot *pp;

	if(dev >= nslot)
		panic("pcmspecialclose");
	pp = slot + dev;
	pp->special = 0;
	decrefp(pp);
}

enum
{
	Qdir,
	Qmem,
	Qattr,
	Qctl,
};

#define DEV(c)	(c->qid.path>>8)
#define TYPE(c)	(c->qid.path&0xff)

static int
pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
{
	int dev;
	Qid qid;
	long len;
	Slot *pp;
	char name[NAMELEN];

	USED(tab, ntab);
	if(i>=3*nslot)
		return -1;
	dev = i/3;
	pp = slot + dev;
	len = 0;
	switch(i%3){
	case 0:
		qid.path = (dev<<8) | Qmem;
		sprint(name, "pcm%dmem", dev);
		len = pp->memlen;
		break;
	case 1:
		qid.path = (dev<<8) | Qattr;
		sprint(name, "pcm%dattr", dev);
		len = pp->memlen;
		break;
	case 2:
		qid.path = (dev<<8) | Qctl;
		sprint(name, "pcm%dctl", dev);
		break;
	}
	qid.vers = 0;
	devdir(c, qid, name, len, eve, 0660, dp);
	return 1;
}

static char *chipname[] =
{
[Ti82365]	"Intel 82365SL",
[Tpd6710]	"Cirrus Logic PD6710",
[Tpd6720]	"Cirrus Logic PD6720",
};

static I82365*
i82386probe(int x, int d, int dev)
{
	uchar c;
	I82365 *cp;

	outb(x, Rid + (dev<<7));
	c = inb(d);
	if((c & 0xf0) != 0x80)
		return 0;		/* not this family */

	cp = xalloc(sizeof(I82365));
	cp->xreg = x;
	cp->dreg = d;
	cp->dev = dev;
	cp->type = Ti82365;
	cp->nslot = 2;

	switch(c){
	case 0x82:
	case 0x83:
		/* could be a cirrus */
		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){
			cp->type = Tpd6720;
		} else {
			cp->type = Tpd6710;
			cp->nslot = 1;
		}
		break;
	}

	print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot,
		chipname[cp->type]);

	controller[ncontroller++] = cp;
	return cp;
}

/*
 *  set up for slot cards
 */
void
i82365reset(void)
{
	static int already;
	int i, j;
	I82365 *cp;

	if(already)
		return;
	already = 1;

	/* look for controllers */
	i82386probe(0x3E0, 0x3E1, 0);
	i82386probe(0x3E0, 0x3E1, 1);
	for(i = 0; i < ncontroller; i++)
		nslot += controller[i]->nslot;
	slot = xalloc(nslot * sizeof(Slot));

	/* if the card is there turn on 5V power to keep its battery alive */
	lastslot = slot;
	for(i = 0; i < ncontroller; i++){
		cp = controller[i];
		for(j = 0; j < cp->nslot; j++){
			lastslot->dev = lastslot - slot;
			lastslot->memlen = 64*MB;
			lastslot->base = (cp->dev<<7) | (j<<6);
			lastslot->cp = cp;
			wrreg(lastslot, Rpc, 5|Fautopower);
			lastslot++;
		}
	}
}

void
i82365init(void)
{
}

Chan *
i82365attach(char *spec)
{
	return devattach('y', spec);
}

Chan *
i82365clone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
i82365walk(Chan *c, char *name)
{
	return devwalk(c, name, 0, 0, pcmgen);
}

void
i82365stat(Chan *c, char *db)
{
	devstat(c, db, 0, 0, pcmgen);
}

Chan *
i82365open(Chan *c, int omode)
{
	if(c->qid.path == CHDIR){
		if(omode != OREAD)
			error(Eperm);
	} else
		increfp(slot + DEV(c));
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void
i82365create(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
i82365remove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
i82365wstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

void
i82365close(Chan *c)
{
	USED(c);
	if(c->qid.path != CHDIR)
		decrefp(slot+DEV(c));
}

/* a memmove using only shorts & bytes */
static void
memmoves(uchar *to, uchar *from, int n)
{
	ushort *t, *f;

	if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
		while(n-- > 0)
			*to++ = *from++;
	} else {
		n = n/2;
		t = (ushort*)to;
		f = (ushort*)from;
		while(n-- > 0)
			*t++ = *f++;
	}
}

long
pcmread(int dev, int attr, void *a, long n, ulong offset)
{
	int i, len;
	PCMmap *m;
	ulong ka;
	uchar *ac;
	Slot *pp;

	pp = slot + dev;
	if(pp->memlen < offset)
		return 0;
	qlock(pp->cp);
	ac = a;
	if(pp->memlen < offset + n)
		n = pp->memlen - offset;
	for(len = n; len > 0; len -= i){
		if(pp->occupied == 0 || pp->enabled == 0)
			error(Eio);
		m = getmap(pp, offset, attr);
		if(offset + len > m->cea)
			i = m->cea - offset;
		else
			i = len;
		ka = KZERO|(m->isa + (offset&(Mchunk-1)));
		memmoves(ac, (void*)ka, i);
		offset += i;
		ac += i;
	}
	qunlock(pp->cp);
	return n;
}

long
i82365read(Chan *c, void *a, long n, ulong offset)
{
	char *cp, buf[128];
	ulong p;
	Slot *pp;

	p = TYPE(c);
	switch(p){
	case Qdir:
		return devdirread(c, a, n, 0, 0, pcmgen);
	case Qmem:
	case Qattr:
		n = pcmread(DEV(c), p==Qattr, a, n, offset);
		break;
	case Qctl:
		cp = buf;
		pp = slot + DEV(c);
		if(pp->occupied)
			cp += sprint(cp, "occupied\n");
		if(pp->enabled)
			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)
			cp += sprint(cp, "write protected\n");
		if(pp->busy)
			cp += sprint(cp, "busy\n");
		cp += sprint(cp, "battery lvl %d\n", pp->battery);
		*cp = 0;
		return readstr(offset, a, n, buf);
	default:
		n=0;
		break;
	}
	return n;
}

long
pcmwrite(int dev, int attr, void *a, long n, ulong offset)
{
	int i, len;
	PCMmap *m;
	ulong ka;
	uchar *ac;
	Slot *pp;

	pp = slot + dev;
	if(pp->memlen < offset)
		return 0;
	qlock(pp->cp);
	ac = a;
	if(pp->memlen < offset + n)
		n = pp->memlen - offset;
	for(len = n; len > 0; len -= i){
		m = getmap(pp, offset, attr);
		if(offset + len > m->cea)
			i = m->cea - offset;
		else
			i = len;
		ka = KZERO|(m->isa + (offset&(Mchunk-1)));
		memmoves((void*)ka, ac, i);
		offset += i;
		ac += i;
	}
	qunlock(pp->cp);
	return n;
}

long
i82365write(Chan *c, void *a, long n, ulong offset)
{
	ulong p;
	Slot *pp;

	p = TYPE(c);
	switch(p){
	case Qmem:
	case Qattr:
		pp = slot + DEV(c);
		if(pp->occupied == 0 || pp->enabled == 0)
			error(Eio);
		n = pcmwrite(pp->dev, p == Qattr, a, n, offset);
		break;
	default:
		error(Ebadusefd);
	}
	return n;
}

/*
 *  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)
{
	uchar we, x;
	Slot *pp;

	if(dev > nslot)
		return -1;
	pp = slot + dev;

	if(!pp->occupied)
		return -1;

	/* if no io registers, assume not an io card (iffy!) */
	if(pp->nioregs == 0)
		return -1;

	/* route interrupts, make sure card can use specified interrupt */
	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 */
	x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2);
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);

	/* 16-bit data path */
	if(pp->bit16)
		wrreg(pp, Rio, (1<<0)|(1<<1));

	/* enable io port map 0 */
	if(isa->port == 0)
		isa->port = 300;
	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);
	wrreg(pp, Rwe, we | (1<<6));

	/* only touch Rconfig if it is present */
	if(pp->cpresent & (1<<Rconfig)){
		/*  Reset adapter */
		x = Creset;
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
		delay(2);
		x = 0;
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
		delay(2);
	
		/*
		 *  Set level sensitive (not pulsed) interrupts and
		 *  configuration number 1.
		 *  Setting the configuration number enables IO port access.
		 */
		x = Clevel | 1;
		pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig);
		delay(2);
	}
	return 0;
}

/*
 *  read and crack the card information structure enough to set
 *  important parameters like power
 */
static void	tcfig(Slot*, int);
static void	tentry(Slot*, int);

static void (*parse[256])(Slot*, int) =
{
[0x1A]	tcfig,
[0x1B]	tentry,
};

static int
readc(Slot *pp, uchar *x)
{
	uchar l, r;
	ushort s;

	if(pp->cispos > pp->cisbase + Mchunk)
		return 0;

	*x = *(pp->cispos);
	pp->cispos += 2;
	return 1;
}

static void
cisread(Slot *pp)
{
	PCMmap *m;
	uchar link;
	uchar type;
	uchar *this;
	int i;

	pp->vpp1 = pp->vpp2 = 5;
	pp->bit16 = 0;
	pp->caddr = 0;
	pp->cpresent = 0;
	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);

	/* loop through all the tuples */
	for(i = 0; i < 1000; i++){
		this = pp->cispos;
		if(readc(pp, &type) != 1)
			break;
		if(readc(pp, &link) != 1)
			break;
		if(parse[type])
			(*parse[type])(pp, type);
		if(link == 0xff)
			break;
		pp->cispos = this + 2*(2+link);
		if(this > pp->cisbase + Mchunk)
			break;
	}
}

static ulong
getlong(Slot *pp, int size)
{
	uchar c;
	int i;
	ulong x;

	x = 0;
	for(i = 0; i < size; i++){
		if(readc(pp, &c) != 1)
			break;
		x |= c<<(i*8);
	}
	return x;
}

static void
tcfig(Slot *pp, int ttype)
{
	uchar size, rasize, rmsize;
	uchar last;

	USED(ttype);
	if(readc(pp, &size) != 1)
		return;
	rasize = (size&0x3) + 1;
	rmsize = ((size>>2)&0xf) + 1;
	if(readc(pp, &last) != 1)
		return;
	pp->caddr = getlong(pp, rasize);
	pp->cpresent = getlong(pp, rmsize);
}

static ulong vexp[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
microvolt(Slot *pp)
{
	uchar c;
	ulong microvolts;

	if(readc(pp, &c) != 1)
		return 0;
	microvolts = vexp[c&0x7]*vmant[(c>>3)&0xf];
	while(c & 0x80){
		if(readc(pp, &c) != 1)
			return 0;
		if(c == 0x7d || c == 0x7e || c == 0x7f)
			microvolts = 0;
	}
	return microvolts;
}

static ulong
nanoamps(Slot *pp)
{
	uchar c;
	ulong nanoamps;

	if(readc(pp, &c) != 1)
		return 0;
	nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
	while(c & 0x80){
		if(readc(pp, &c) != 1)
			return 0;
		if(c == 0x7d || c == 0x7e || c == 0x7f)
			nanoamps = 0;
	}
	return nanoamps;
}

/*
 *  only nominal voltage is important for config
 */
static ulong
power(Slot *pp)
{
	uchar feature;
	ulong mv;

	mv = 0;
	if(readc(pp, &feature) != 1)
		return 0;
	if(feature & 1)
		mv = microvolt(pp);
	if(feature & 2)
		microvolt(pp);
	if(feature & 4)
		microvolt(pp);
	if(feature & 8)
		nanoamps(pp);
	if(feature & 0x10)
		nanoamps(pp);
	if(feature & 0x20)
		nanoamps(pp);
	if(feature & 0x20)
		nanoamps(pp);
	return mv/1000000;
}

static ulong mantissa[16] =
{ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };

static ulong exponent[8] =
{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };

static ulong
ttiming(Slot *pp, int scale)
{
	uchar unscaled;
	ulong nanosecs;

	if(readc(pp, &unscaled) != 1)
		return 0;
	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
	nanosecs = nanosecs * vexp[scale];
	return nanosecs;
}

static void
timing(Slot *pp)
{
	uchar c, i;

	if(readc(pp, &c) != 1)
		return;
	i = c&0x3;
	if(i != 3)
		ttiming(pp, i);		/* max wait */
	i = (c>>2)&0x7;
	if(i != 7)
		ttiming(pp, i);		/* max ready/busy wait */
	i = (c>>5)&0x7;
	if(i != 7)
		ttiming(pp, i);		/* reserved wait */
}

void
iospaces(Slot *pp)
{
	uchar c;
	int i;
	ulong address, len;

	for(;;){
		if(readc(pp, &c) != 1)
			break;

		pp->nioregs = 1<<(c&0x1f);
		pp->bit16 = ((c>>5)&3) >= 2;
		if((c & 0x80) == 0)
			break;

		if(readc(pp, &c) != 1)
			break;

		for(i = (c&0xf)+1; i; i--){
			address = getlong(pp, (c>>4)&0x3);
			len = getlong(pp, (c>>6)&0x3);
			USED(address, len);
		}
	}
}

static void
irq(Slot *pp)
{
	uchar c;

	if(readc(pp, &c) != 1)
		return;
	if(c & 0x10)
		pp->irqs = getlong(pp, 2);
	else
		pp->irqs = 1<<(c&0xf);
}

static void
memspace(Slot *pp, int asize, int lsize, int host)
{
	ulong haddress, address, len;

	len = getlong(pp, lsize)*256;
	address = getlong(pp, asize)*256;
	USED(len, address);
	if(host){
		haddress = getlong(pp, asize)*256;
		USED(haddress);
	}
}

void
tentry(Slot *pp, int ttype)
{
	uchar c, i, feature;

	USED(ttype);
	if(readc(pp, &c) != 1)
		return;
	if(c&0x40)
		pp->def = 1;
	if(c & 0x80){
		if(readc(pp, &i) != 1)
			return;
		if(i&0x80)
			pp->memwait = 1;
	}
	if(readc(pp, &feature) != 1)
		return;
	switch(feature&0x3){
	case 1:
		pp->vpp1 = pp->vpp2 = power(pp);
		break;
	case 2:
		power(pp);
		pp->vpp1 = pp->vpp2 = power(pp);
		break;
	case 3:
		power(pp);
		pp->vpp1 = power(pp);
		pp->vpp2 = power(pp);
		break;
	default:
		break;
	}
	if(feature&0x4)
		timing(pp);
	if(feature&0x8)
		iospaces(pp);
	if(feature&0x10)
		irq(pp);
	switch(feature&0x3){
	case 1:
		memspace(pp, 0, 2, 0);
		break;
	case 2:
		memspace(pp, 2, 2, 0);
		break;
	case 3:
		if(readc(pp, &c) != 1)
			return;
		for(i = 0; i <= c&0x7; i++)
			memspace(pp, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
		break;
	}
	pp->configed++;
}
.
## diffname pc/devi82365.c 1994/1210
## diff -e /n/fornaxdump/1994/1209/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1994/1210/sys/src/brazil/pc/devi82365.c
319c
			pp->mmap[i].isa = getisa(0, Mchunk, BY2PG);
		if(pp->mmap[i].isa == 0)
			panic("getmap");
.
## diffname pc/devi82365.c 1994/1211
## diff -e /n/fornaxdump/1994/1210/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1994/1211/sys/src/brazil/pc/devi82365.c
848,850d
## diffname pc/devi82365.c 1995/0107
## diff -e /n/fornaxdump/1994/1211/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0107/sys/src/brazil/pc/devi82365.c
271c
	x = vcode(5) | (vcode(5)<<2);
	wrreg(pp, Rpc, x|Fautopower);
.
266a
	int x;

.
## diffname pc/devi82365.c 1995/0108
## diff -e /n/fornaxdump/1995/0107/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devi82365.c
764a
}

long
i82365bwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
714a
Block*
i82365bread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname pc/devi82365.c 1995/0111
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0111/sys/src/brazil/pc/devi82365.c
1160a
}

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;
.
855a
[0x15]	tvers1,
.
852a
static void	tvers1(Slot*, int);
.
399c
	return pp->verstr;
.
396c
		return 0;
.
392c
		return 0;
.
389c
		return 0;
.
382c
char*
.
153a
	uchar	verstr[512];	/* version string */
.
## diffname pc/devi82365.c 1995/0114
## diff -e /n/fornaxdump/1995/0111/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0114/sys/src/brazil/pc/devi82365.c
1074,1078c
	for(i = (c&0xf)+1; i; i--){
		address = getlong(pp, (c>>4)&0x3);
		len = getlong(pp, (c>>6)&0x3);
		USED(address, len);
.
1071,1072c
	if(readc(pp, &c) != 1)
		return;
.
1066,1069c
	pp->nioregs = 1<<(c&0x1f);
	pp->bit16 = ((c>>5)&3) >= 2;
	if((c & 0x80) == 0)
		return;
.
1062,1064c
	if(readc(pp, &c) != 1)
		return;
.
## diffname pc/devi82365.c 1995/0117
## diff -e /n/fornaxdump/1995/0114/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devi82365.c
1176c
		if(readc(pp, &c) != 1)
.
154c
	char	verstr[512];	/* version string */
.
## diffname pc/devi82365.c 1995/0118
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0118/sys/src/brazil/pc/devi82365.c
818c
		isa->port = 0x300;
.
## diffname pc/devi82365.c 1995/0131
## diff -e /n/fornaxdump/1995/0118/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0131/sys/src/brazil/pc/devi82365.c
1052c
		pp->otherwait = ttiming(pp, i);		/* reserved wait */
.
1049c
		pp->readywait = ttiming(pp, i);		/* max ready/busy wait */
.
1046c
		pp->maxwait = ttiming(pp, i);		/* max wait */
.
165a
	ulong	maxwait;
	ulong	readywait;
	ulong	otherwait;
.
## diffname pc/devi82365.c 1995/0209
## diff -e /n/fornaxdump/1995/0131/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0209/sys/src/brazil/pc/devi82365.c
769a
		qunlock(&pp->mlock);
		if(n < 0)
			error(Eio);
.
768a
		qlock(&pp->mlock);
.
752d
737d
690a
		qunlock(&pp->mlock);
		if(n < 0)
			error(Eio);
.
689a
		qlock(&pp->mlock);
.
673d
656d
383c
	unlock(pp);
.
380c
	lock(pp);
.
374c
	unlock(pp);
.
371c
	lock(pp);
.
327,328c
			if(pp->mmap[i].isa == 0)
				panic("getmap");
		}
.
325c
		for(i = 0; i < Nmap; i++){
.
170a
	QLock	mlock;		/* lock down the maps */
.
132a
	Lock;
.
120d
## diffname pc/devi82365.c 1995/0215
## diff -e /n/fornaxdump/1995/0209/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0215/sys/src/brazil/pc/devi82365.c
689a
		pp = slot + DEV(c);
.
193a
	microdelay(10);
.
192a
	microdelay(10);
.
187a
	microdelay(10);
.
186a
	microdelay(10);
.
## diffname pc/devi82365.c 1995/0222
## diff -e /n/fornaxdump/1995/0215/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0222/sys/src/brazil/pc/devi82365.c
919,921c
		pp->cispos = this + (2+link);
.
906c
	if(m == 0)
		return;
	pp->cisbase = (uchar*)(KZERO|m->isa);
	pp->cispos = 0;
.
904d
894,895c
	int this, i;
	PCMmap *m;
.
891d
882,884c
	*x = pp->cisbase[2*pp->cispos];
	pp->cispos++;
.
880c
	if(pp->cispos >= Mchunk)
.
857c
		delay(5);
.
848c
		delay(5);
.
845c
		delay(5);
.
823c
	x = vcode(pp->vpp1);
.
788,793d
777c
		n = pcmwrite(pp->slotno, p == Qattr, a, n, offset);
.
773c
		pp = slot + SLOTNO(c);
.
756c
		memmoveb((void*)ka, ac, i);
.
731c
	return devbwrite(c, bp, offset);
.
728,729c
long
i82365bwrite(Chan *c, Block *bp, ulong offset)
.
718a
{
	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");
}
.
710,711d
703c
		pp = slot + SLOTNO(c);
.
696c
		n = pcmread(SLOTNO(c), p==Qattr, a, n, offset);
.
694c
		pp = slot + SLOTNO(c);
.
684c
	char *cp, buf[2048];
.
680a
Block*
i82365bread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
674c
		memmoveb(ac, (void*)ka, i);
.
659c
	pp = slot + slotno;
.
651c
pcmread(int slotno, int attr, void *a, long n, ulong offset)
.
631a
/* a memmove using only bytes */
static void
memmoveb(uchar *to, uchar *from, int n)
{
	while(n-- > 0)
		*to++ = *from++;
}

.
627,629c
	if(c->flag & COPEN)
		if(c->qid.path != CHDIR)
			decrefp(slot+SLOTNO(c));
.
596c
		increfp(slot + SLOTNO(c));
.
557a

	/* for card management interrupts */
	setvec(PCMCIAvec, i82365intr, 0);
.
554c
			slotdis(lastslot);
.
550c
			lastslot->slotno = lastslot - slot;
.
540a
	i82386probe(0x3E2, 0x3E3, 0);
	i82386probe(0x3E2, 0x3E3, 1);
.
462,463c
		qid.path = QID(slotno, Qctl);
		sprint(name, "pcm%dctl", slotno);
.
457,458c
		qid.path = QID(slotno, Qattr);
		sprint(name, "pcm%dattr", slotno);
.
452,453c
		qid.path = QID(slotno, Qmem);
		sprint(name, "pcm%dmem", slotno);
.
447,448c
	slotno = i/3;
	pp = slot + slotno;
.
438c
	int slotno;
.
432,433c
#define SLOTNO(c)	((c->qid.path>>8)&0xff)
#define TYPE(c)		(c->qid.path&0xff)
#define QID(s,t)	(((s)<<8)|(t))
.
419c
	pp = slot + slotno;
.
417c
	if(slotno >= nslot)
.
413c
pcmspecialclose(int slotno)
.
408,409c
	return -1;
.
406d
398,404c
	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;
		}

.
395a
	extern char *strstr(char*, char*);
.
392,393c
/*
 *  look for a card whose version contains 'idstr'
 */
int
pcmspecial(char *idstr, ISAConf *isa)
.
364c
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) | Ftimer1);
.
300,309c
		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);
.
298a
		was = pp->occupied;
.
296c
	USED(ur,a);
	if(slot == 0)
		return;

.
293c
	uchar csc, was;
.
291c
i82365intr(Ureg *ur, void *a)
.
276,283c
	wrreg(pp, Rmisc2, Flowpow);	 	/* low power mode */
	wrreg(pp, Rpc, vcode(5)|Fautopower);			/* turn off card */
	wrreg(pp, Rwe, 0);			/* no windows */
.
267c
	} else
		wrreg(pp, Rpc, vcode(5)|Fautopower);
	pp->enabled = 1;
.
262,265c
		if(pp->configed)
			wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena);
.
256,258d
247,252d
244,245c
	/* 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);
.
239,240d
215,217d
197d
195d
189d
187d
179a
static void i82365intr(Ureg*, void*);
.
164,165c
	int	cispos;		/* current position scanning cis */
	uchar	*cisbase;
.
150d
138c
	uchar	slotno;		/* slot number */
.
80c
	 Fregactive=	 (1<<6),	/*  attribute memory */
.
77c
	 Ftimer1=	 (1<<6),	/*  timer set 1 */
.
74a
	 F16bit=	 (1<<7),	/*  16-bit wide data path */
.
66a
	 Flowpow=	 (1<<1),	/*  low power mode */
.
18c
 *  Intel 82365SL PCIC controller for the PCMCIA or
.
## diffname pc/devi82365.c 1995/0223
## diff -e /n/fornaxdump/1995/0222/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0223/sys/src/brazil/pc/devi82365.c
1173c
		irq(pp, ct);
.
1171c
		iospaces(pp, ct);
.
1169c
		timing(pp, ct);
.
1162,1163c
		ct->vpp1 = power(pp);
		ct->vpp2 = power(pp);
.
1158c
		ct->vpp1 = ct->vpp2 = power(pp);
.
1154c
		ct->vpp1 = ct->vpp2 = power(pp);
.
1149a

.
1148c
			ct->memwait = 1;
.
1142,1143c
	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? */
.
1139a

	if(pp->nctab >= Maxctab)
		return;
.
1137a
	Conftab *ct;
.
1117c
		ct->irqs = 1<<(c&0xf);
.
1115c
		ct->irqs = getlong(pp, 2);
.
1108c
irq(Slot *pp, Conftab *ct)
.
1103c
		USED(len);
.
1101c
		ct->port = getlong(pp, (c>>4)&0x3);
.
1092,1093c
	ct->nioregs = 1<<(c&0x1f);
	ct->bit16 = ((c>>5)&3) >= 2;
.
1087c
	ulong len;
.
1083c
iospaces(Slot *pp, Conftab *ct)
.
1079c
		ct->otherwait = ttiming(pp, i);		/* reserved wait */
.
1076c
		ct->readywait = ttiming(pp, i);		/* max ready/busy wait */
.
1073c
		ct->maxwait = ttiming(pp, i);		/* max wait */
.
1065c
timing(Slot *pp, Conftab *ct)
.
914,915c
	pp->configed = 0;
	pp->nctab = 0;
.
910,911c
	memset(pp->ctab, 0, sizeof(pp->ctab));
.
870c
		if(isa->irq > 7)
			x = Clevel | ct->index;
		else
			x = ct->index;
.
851,852c
	wrreg(pp, Riotop0lo, (isa->port+ct->nioregs));
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs)>>8);
.
842c
	if(ct->bit16)
.
838c
	x = vcode(ct->vpp1);
.
833,834d
830c
print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs);

	/* route interrupts */
.
826,827c
	/* 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])
.
817a
	Conftab *ct;
.
552a
	/* 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++;
		}

.
544,549c
			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);
.
524a
	Slot *pp;
.
511a
	/* low power mode */
	outb(x, Rmisc2 + (dev<<7));
	outb(d, Flowpow);

.
348c
	wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) /*| Ftimer1/**/);
.
325c
	for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){
.
310,320d
266,267c
	wrreg(pp, Rpc, Fautopower);		/* turn off card */
.
256,257c
		wrreg(pp, Rpc, Fautopower);
.
250,254c
		pp->enabled = 1;
.
246c
	/* get configuration */
.
243,244c
	delay(500);
.
237,239c
	/* power up and reset, wait's are empirical (???) */
	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
	delay(300);
.
174c
	PCMmap	mmap[Nmap];	/* maps, last is always for the kernel */
	int	nmap;		/* number of maps */
.
167,169d
164a
	int	nctab;		/* number of config table entries */
	Conftab	ctab[Maxctab];
	Conftab	*def;		/* default conftab */

	/* for walking through cis */
.
162,163d
156,160d
145d
131c
/* 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 */
.
101a
typedef struct Conftab	Conftab;
.
94a

	Maxctab=	8,		/* maximum configuration table entries */
.
## diffname pc/devi82365.c 1995/0225
## diff -e /n/fornaxdump/1995/0223/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0225/sys/src/brazil/pc/devi82365.c
961a
	pcmunmap(pp->slotno, m);
.
943c
	m = pcmmap(pp->slotno, 0, 0, 1);
.
899a
		pcmunmap(slotno, m);
.
897,898c
			*p = ct->index;
.
895c
			*p = Clevel | ct->index;
.
885,886c
		*p = 0;
.
882,883c
		m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
		p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca));
		*p = Creset;
.
871c
		isa->port = ct->port;
.
861c
	/* set power and enable slotnoice */
.
854,855d
843a
	}
.
841c
	for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){
.
835c
	pp = slot + slotno;
.
833c
	if(slotno > nslot)
.
831a
	PCMmap *m;
.
829c
	uchar we, x, *p;
.
826,827c
static int
pcmio(int slotno, ISAConf *isa)
.
812d
810d
793a

	poperror();
.
790a
		pcmunmap(pp->slotno, m);
.
789c
		ka = KZERO|(m->isa + offset - m->ca);
.
784c
		m = pcmmap(pp->slotno, offset, 0, attr);
		if(m == 0)
			error("can't map PCMCIA card");
.
782a

	m = 0;
	if(waserror()){
		if(m)
			pcmunmap(pp->slotno, m);
		nexterror();
	}

	ac = a;
.
780d
768c
static long
.
718,724c
		return pcmread(SLOTNO(c), p==Qattr, a, n, offset);
.
695a

	poperror();
.
692a
		pcmunmap(pp->slotno, m);
.
691c
		ka = KZERO|(m->isa + offset - m->ca);
.
684,686c
		m = pcmmap(pp->slotno, offset, 0, attr);
		if(m == 0)
			error("can't map PCMCIA card");
.
682a

	m = 0;
	if(waserror()){
		if(m)
			pcmunmap(pp->slotno, m);
		nexterror();
	}

	ac = a;
.
680d
668c
static long
.
557,565d
353a
void
pcmunmap(int slotno, PCMmap* m)
{
	Slot *pp;

	pp = slot + slotno;
	lock(&pp->mlock);
	m->ref--;
	unlock(&pp->mlock);
}


.
350a
	m->ref = 1;

	unlock(&pp->mlock);
.
347c
	offset >>= Mshift;
.
341,344c
	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)));
.
337,338c
	i = m-pp->mmap;
.
335c
	m->cea = m->ca + m->len;
.
331,333c
	/* 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 */
.
329a
	m = nm;
	if(m == 0){
		unlock(&pp->mlock);
		return 0;
	}
.
327,328c
		if(nm == 0 && m->ref == 0)
			nm = m;
.
320,323c
	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);
.
317c
	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 */
.
315a
	ulong e;
.
314c
	PCMmap *m, *nm;
.
312a
	Slot *pp;
.
310,311c
PCMmap*
pcmmap(int slotno, ulong offset, int len, int attr)
.
306a
enum
{
	Mshift=	12,
	Mgran=	(1<<Mshift),	/* granularity of maps */
	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
};

.
194,195c
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);
.
188d
185c
	Lock	mlock;		/* lock down the maps */
.
106,115d
103d
## diffname pc/devi82365.c 1995/0328
## diff -e /n/fornaxdump/1995/0225/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0328/sys/src/brazil/pc/devi82365.c
1308a

.
951a
} else i82365dump(pp);
.
941,946c
}

		/* set configuration */
if(strstr(pp->verstr, "KeepInTouch") == 0){
.
936a
if(strstr(pp->verstr, "KeepInTouch") == 0){
.
783,794d
596a
*/
.
595a
if(pp == slot)i82365dump(pp);
/*
.
561a
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");
}

.
## diffname pc/devi82365.c 1995/0329
## diff -e /n/fornaxdump/1995/0328/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0329/sys/src/brazil/pc/devi82365.c
1274c
	switch((feature>>5)&0x3){
.
1197a
	ct->irqtype = c & 0xe0;
.
1124c
	if(feature & 0x40)
.
1076,1077c
		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);
		}
.
1072c
	exp = vexp[c&0x7];
	microvolts = vmant[(c>>3)&0xf]*exp;
.
1068a
	ulong exp;
.
955c

.
948,953c
		/* 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;
.
941,946d
932,933c
	wrreg(pp, Riotop0lo, (isa->port+ct->nioregs-1));
	wrreg(pp, Riotop0hi, (isa->port+ct->nioregs-1)>>8);
.
924c
		x = Fiocs16|Fwidth16;
	else
		x = 0;
	wrreg(pp, Rio, Ftiming|x);
.
918c
	/* set power and enable device */
.
798a
{
	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");
}
.
612d
609,610d
265,266c
	wrreg(pp, Rwe, 0);		/* no windows */
	wrreg(pp, Rpc, 0);		/* turn off card power */
.
256c
		wrreg(pp, Rpc, 0);
.
249a
	wrreg(pp, Rpc, 0);
	delay(500);

	wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
	delay(300);
	wrreg(pp, Rigc, Fnotreset);
	delay(500);

.
245,246d
242c
	/* power up and unreset, wait's are empirical (???) */
.
128a
	uchar	irqtype;
.
43a
	 Fwidth16=	 (1<<0),	/*  16 bit data width */
	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
	 Ftiming=	 (1<<3),	/*  timing register to use */
.
## diffname pc/devi82365.c 1995/0331
## diff -e /n/fornaxdump/1995/0329/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0331/sys/src/brazil/pc/devi82365.c
1309c
		for(i = 0; i <= (c&0x7); i++)
.
275,276c
	wrreg(pp, Rpc, 0);	/* turn off card power */
	wrreg(pp, Rwe, 0);	/* no windows */
.
266c
		wrreg(pp, Rpc, Fautopower);
.
252,259d
248a
	wrreg(pp, Rigc, 0);
	delay(100);
.
## diffname pc/devi82365.c 1995/0401
## diff -e /n/fornaxdump/1995/0331/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0401/sys/src/brazil/pc/devi82365.c
1220a
	ct->irqs &= 0xDEB8;		/* levels available to card */
.
960c
		*p = x;
.
925,927c
	isa->irq = irq;
	wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
.
918c
			if(ct->nioregs && ((1<<irq) & ct->irqs))
.
911c
		if(ct->nioregs && ct->port == isa->port && ((1<<irq) & ct->irqs))
.
901a
	irq = isa->irq;
	if(irq == 2)
		irq = 9;

.
900a
	int irq;
.
## diffname pc/devi82365.c 1995/0519
## diff -e /n/fornaxdump/1995/0401/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0519/sys/src/brazil/pc/devi82365.c
874a
	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;
.
871a
	char buf[32];
.
## diffname pc/devi82365.c 1995/0726
## diff -e /n/fornaxdump/1995/0519/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devi82365.c
684d
682c
i82365wstat(Chan*, char*)
.
677d
675c
i82365remove(Chan*)
.
670d
668c
i82365create(Chan*, char*, int, ulong)
.
## diffname pc/devi82365.c 1995/1006
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1006/sys/src/brazil/pc/devi82365.c
298a
		if(changed)
			break;
		delay(100);
.
287,296c
	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);
				}
.
279a
	int tries, changed;
.
## diffname pc/devi82365.c 1995/1007
## diff -e /n/fornaxdump/1995/1006/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1007/sys/src/brazil/pc/devi82365.c
304,306d
288,301c
	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);
.
280d
## diffname pc/devi82365.c 1995/1017
## diff -e /n/fornaxdump/1995/1007/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1017/sys/src/brazil/pc/devi82365.c
937c
	if(ct == et || ct->nioregs == 0)
.
935a
			}
	}
	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;
			}
	}
.
931,934c
	/* 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;
.
925,929c
	et = &pp->ctab[pp->nctab];
.
910c
	Conftab *ct, *et, *t;
.
541,546c
		if((c & 0xc0) != 0xc0)
			break;
		c = inb(d);
		if((c & 0xc0) != 0x00)
			break;
		if(c & 0x20){
.
## diffname pc/devi82365.c 1995/1027
## diff -e /n/fornaxdump/1995/1017/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1027/sys/src/brazil/pc/devi82365.c
297d
292,295c
			if(!pp->occupied)
.
## diffname pc/devi82365.c 1995/1121
## diff -e /n/fornaxdump/1995/1027/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1995/1121/sys/src/brazil/pc/devi82365.c
1341c
static void
.
1268c
static void
.
## diffname pc/devi82365.c 1996/0303
## diff -e /n/fornaxdump/1995/1121/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0303/sys/src/brazil/pc/devi82365.c
190a

void i82365reset(void);
.
8d
## diffname pc/devi82365.c 1996/0604
## diff -e /n/fornaxdump/1996/0303/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0604/sys/src/brazil/pc/devi82365.c
900c
 *  configuration info from the CIS.  If not, we won't set up correctly.
.
613a
			rdreg(pp, Rcsc);
.
569,571c
		if((i&0x0F) == 0)
			print("\n%2.2uX:	", i);
		if(((i+1) & 0x0F) == 0x08)
			print(" - ");
		print("%2.2uX ", rdreg(pp, i));
.
557c
	c = inb(d);
	outb(d, c & ~Flowpow);
.
551a
	if(cp->type == Ti82365){
		outb(x, 0x0E + (dev<<7));
		outb(x, 0x37 + (dev<<7));
		outb(x, 0x3A + (dev<<7));
		c = inb(d);
		outb(d, c|0xC0);
		outb(x, Rid + (dev<<7));
		c = inb(d);
		print("ctlr id %uX\n", c & 0xFF);
		if(c & 0x08)
			cp->type = Tvg46x;
		outb(x, 0x3A + (dev<<7));
		c = inb(d);
		outb(d, c & ~0xC0);
	}

.
510a
[Tvg46x]	"Vadem VG-46x",
.
191a
static void i82365dump(Slot*);
.
112a
	Tvg46x,
.
## diffname pc/devi82365.c 1996/0613
## diff -e /n/fornaxdump/1996/0604/sys/src/brazil/pc/devi82365.c /n/fornaxdump/1996/0613/sys/src/brazil/pc/devi82365.c
1070a
			break;
		if(type == 0xFF)
.
977a
	if(isa->port == 0 && ct->port == 0)
		return -1;
.
968,974d
961,966c
	if(ct == 0){
	
		/* 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;
					break;
				}
		}
		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;
				}
		}
.
947,959c
	ct = 0;
	for(i = 0; i < isa->nopt; i++){
		if(strncmp(isa->opt[i], "index=", 6))
			continue;
		index = strtol(&isa->opt[i][6], &cp, 0);
		if(cp == &isa->opt[i][6] || index >= pp->nctab)
			return -1;
		ct = &pp->ctab[index];
.
932c
	int i, index, irq;
	char *cp;
.
## diffname pc/devi82365.c 1997/0327
## diff -e /n/fornaxdump/1996/0613/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devi82365.c
1255c
static void
.
920a
Dev i82365devtab = {
	i82365reset,
	devinit,
	i82365attach,
	devclone,
	i82365walk,
	i82365stat,
	i82365open,
	devcreate,
	i82365close,
	i82365read,
	devbread,
	i82365write,
	devbwrite,
	devremove,
	devwstat,
};

.
884c
static long
.
836,841d
781,787c
static long
.
687,705c
static void
.
673c
static Chan*
.
667c
static void
.
655,661c
static int
.
644,649c
static Chan*
.
641c
	intrenable(VectorPCMCIA, i82365intr, 0, BUSUNKNOWN);
.
635c
			wrreg(pp, Rcscic, ((VectorPCMCIA-VectorPIC)<<4) | Fchangeena);
.
601c
static void
.
402d
359c
		m->isa = umbmalloc(0, len, Mgran)&~KZERO;
.
356c
			umbfree(m->isa, m->len);
.
192d
187a
static void	i82365reset(void);
.
## diffname pc/devi82365.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devi82365.c
879a
	'y',
	"i82365",

.
## diffname pc/devi82365.c 1997/0522
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/0522/sys/src/brazil/pc/devi82365.c
640c
	if(ncontroller)
		intrenable(VectorPCMCIA, i82365intr, 0, BUSUNKNOWN);
.
## diffname pc/devi82365.c 1997/1101
## diff -e /n/emeliedump/1997/0522/sys/src/brazil/pc/devi82365.c /n/emeliedump/1997/1101/sys/src/brazil/pc/devi82365.c
359a
print("m->isa = 0x%uX, %d\n", m->isa, len);
.
## diffname pc/devi82365.c 1998/0221
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0221/sys/src/brazil/pc/devi82365.c
360d
133c
	ulong	nioregs;	/* number of io registers */
.
## diffname pc/devi82365.c 1998/0312
## diff -e /n/emeliedump/1998/0221/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0312/sys/src/brazil/pc/devi82365.c
1384d
1059c
	pp->cisbase = KADDR(m->isa);
.
1003c
		p = KADDR(m->isa + pp->caddr + Rconfig - m->ca);
.
877c
	error(Ebadarg);
	return -1;	/* not reached */
.
873,875c
		return n;
.
870c
		n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, offset);
.
864c
		return n;
.
850,851c
	switch(TYPE(c)){
.
846d
832,833c
		memmoveb(KADDR(m->isa + offset - m->ca), ac, i);
.
806d
792,799d
790c
	error(Ebadarg);
	return -1;	/* not reached */
.
785,788c
		n = readstr(offset, a, n, p);
		free(p);

		return n;
.
780,783c
			len += snprint(p+len, READSTR-len, "busy\n");
		snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery);
.
778c
			len += snprint(p+len, READSTR-len, "write protected\n");
.
776c
			len += snprint(p+len, READSTR-len, "configed\n");
.
774c
			len += snprint(p+len, READSTR-len, "powered\n");
.
772c
			len += snprint(p+len, READSTR-len, "enabled\n");
.
770c
			len += snprint(p+len, READSTR-len, "occupied\n");
.
768a

.
767c
		p = malloc(READSTR);
		len = 0;
.
765c
		return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, offset);
.
759,760c
	switch(TYPE(c)){
.
755,756c
	char *p;
	int len;
.
741,742c
		memmoveb(ac, KADDR(m->isa + offset - m->ca), i);
.
715d
570,571c
	print("#y%d: %d slot %s\n", ncontroller, cp->nslot, chipname[cp->type]);
.
562c
		if(c != id && !(c & 0x08))
			print("#y%d: id %uX changed to %uX\n", ncontroller, id, c);
.
535a
	case 0x84:
.
533c
	switch(id){
.
522,523c
	id = inb(d);
	if((id & 0xf0) != 0x80)
.
518c
	uchar c, id;
.
359c
		m->isa = PADDR(umbmalloc(0, len, Mgran));
.
## diffname pc/devi82365.c 1998/0317
## diff -e /n/emeliedump/1998/0312/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0317/sys/src/brazil/pc/devi82365.c
642c
		intrenable(vector, i82365intr, 0, BUSUNKNOWN);
.
635c
			wrreg(pp, Rcscic, ((vector-VectorPIC)<<4) | Fchangeena);
.
625a
		print("#y%d: %d slot %s: port 0x%uX irq %d\n",
			i, cp->nslot, chipname[cp->type], cp->xreg, vector-VectorPIC);
.
612a
	memset(&isa, 0, sizeof(ISAConf));
	vector = VectorPCMCIA;
	if(isaconfig("pcmcia", 0, &isa) && isa.irq)
		vector = VectorPIC+isa.irq;

.
607a
	ISAConf isa;
.
605c
	int i, j, vector;
.
572,573d
## diffname pc/devi82365.c 1998/0319
## diff -e /n/emeliedump/1998/0317/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devi82365.c
1360d
1355c
tvers1(Slot *pp, int )
.
1287,1288d
1282c
tentry(Slot *pp, int )
.
1094d
1089c
tcfig(Slot *pp, int )
.
842a
	ulong offset = off;
.
839c
i82365write(Chan *c, void *a, long n, vlong off)
.
762a
	ulong offset = off;
.
758c
i82365read(Chan *c, void *a, long n, vlong off)
.
480,481c
	if(i >= 3*nslot)
.
472c
pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
.
286d
281c
i82365intr(Ureg *, void *)
.
## diffname pc/devi82365.c 1998/0327
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0327/sys/src/brazil/pc/devi82365.c
863c
		n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off);
.
842d
803a
	ulong offset = off;
.
798c
pcmwrite(int dev, int attr, void *a, long n, vlong off)
.
768c
		return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off);
.
721a
	ulong offset = off;
.
716c
pcmread(int slotno, int attr, void *a, long n, vlong off)
.
190,191c
static long	pcmread(int, int, void*, long, vlong);
static long	pcmwrite(int, int, void*, long, vlong);
.
## diffname pc/devi82365.c 1998/0811
## diff -e /n/emeliedump/1998/0327/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0811/sys/src/brazil/pc/devi82365.c
484c
	switch(i%Nents){
.
481c
	slotno = i/Nents;
.
479c
	if(i >= Nents*nslot)
.
463a

	Nents = 3,
.
## diffname pc/devi82365.c 1998/0910
## diff -e /n/emeliedump/1998/0811/sys/src/brazil/pc/devi82365.c /n/emeliedump/1998/0910/sys/src/brazil/pc/devi82365.c
648c
		intrenable(irq, i82365intr, 0, BUSUNKNOWN);
.
641c
			wrreg(pp, Rcscic, (irq<<4) | Fchangeena);
.
631c
			i, cp->nslot, chipname[cp->type], cp->xreg, irq);
.
615c
		irq = isa.irq;
.
613c
	irq = IrqPCMCIA;
.
603c
	int i, j, irq;
.
## diffname pc/devi82365.c 1999/0303
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0303/sys/src/brazil/pc/devi82365.c
1251a
	ct->nio = nio;
.
1247,1250c
	nio = (c&0xf)+1;
	for(i = 0; i < nio; i++){
		ct->io[i].start = getlong(pp, (c>>4)&0x3);
		ct->io[0].len = getlong(pp, (c>>6)&0x3);
.
1242a
	}
.
1241c
	if(!(c & 0x80)){
		ct->io[0].start = 0;
		ct->io[0].len = 1<<(c&0x1f);
		ct->nio = 1;
.
1239d
1235a
	ct->nio = 0;
.
1233,1234c
	int i, nio;
.
990,992c
	i = isa->port+ct->io[0].len-1;
	wrreg(pp, Riotop0lo, i);
	wrreg(pp, Riotop0hi, i>>8);
	we |= 1<<6;
	if(ct->nio == 2 && ct->io[1].start){
		wrreg(pp, Riobtm1lo, ct->io[1].start);
		wrreg(pp, Riobtm1hi, ct->io[1].start>>8);
		i = ct->io[1].start+ct->io[1].len-1;
		wrreg(pp, Riotop1lo, i);
		wrreg(pp, Riotop1hi, i>>8);
		we |= 1<<7;
	}
	wrreg(pp, Rwe, we);
.
986c
		isa->port = ct->io[0].start;
.
981,982c
		x = Ftiming;
	if(ct->nio == 2 && ct->io[1].start)
		x |= x<<4;
	wrreg(pp, Rio, x);
.
979c
		x = Ftiming|Fiocs16|Fwidth16;
.
966c
	if(isa->port == 0 && ct->io[0].start == 0)
.
964c
	if(ct == et || ct->nio == 0)
.
957c
				if(t->nio){
.
955c
		if(ct->nio == 0){
.
950c
				if(t->nio && ((1<<irq) & t->irqs)){
.
948c
		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
.
943c
				if(t->nio
				&& t->io[0].start == isa->port
				&& ((1<<irq) & t->irqs)){
.
941c
		if(ct->nio == 0
		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
.
134a
	struct {
		ulong	start;
		ulong	len;
	} io[16];
	int	nio;
.
133d
131d
44a
	 Fzerows=	 (1<<2),	/*  zero wait state */
.
## diffname pc/devi82365.c 1999/0714
## diff -e /n/emeliedump/1999/0303/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devi82365.c
621,625c
	/* look for controllers if the ports aren't already taken */
	if(ioalloc(0x3E0, 2, 0, "i82386.0") >= 0){
		i82386probe(0x3E0, 0x3E1, 0);
		i82386probe(0x3E0, 0x3E1, 1);
		if(ncontroller == 0)
			iofree(0x3E0);
	}
	if(ioalloc(0x3E2, 2, 0, "i82386.1") >= 0){
		i = ncontroller;
		i82386probe(0x3E2, 0x3E3, 0);
		i82386probe(0x3E2, 0x3E3, 1);
		if(ncontroller == i)
			iofree(0x3E2);
	}
.
## diffname pc/devi82365.c 1999/0819
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devi82365.c
661c
		intrenable(irq, i82365intr, 0, BUSUNKNOWN, "i82365");
.
## diffname pc/devi82365.c 1999/1230
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devi82365.c /n/emeliedump/1999/1230/sys/src/9/pc/devi82365.c
484a
	if(i == DEVDOTDOT){
		devdir(c, (Qid){CHDIR, 0}, "#y", 0, eve, 0555, dp);
		return 1;
	}

.
## diffname pc/devi82365.c 2000/0605
## diff -e /n/emeliedump/1999/1230/sys/src/9/pc/devi82365.c /n/emeliedump/2000/0605/sys/src/9/pc/devi82365.c
1402c
		if(readc(cis, &c) != 1)
.
1399c
	if(readc(cis, &minor) != 1)
.
1397c
	if(readc(cis, &major) != 1)
.
1392c
tvers1(Slot *pp, Cisdat *cis, int )
.
1385c
			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
.
1382c
		if(readc(cis, &c) != 1)
.
1379c
		memspace(cis, 2, 2, 0);
.
1376c
		memspace(cis, 0, 2, 0);
.
1373c
		irq(cis, ct);
.
1371c
		iospaces(cis, ct);
.
1369c
		timing(cis, ct);
.
1361,1363c
		power(cis);
		ct->vpp1 = power(cis);
		ct->vpp2 = power(cis);
.
1357,1358c
		power(cis);
		ct->vpp1 = ct->vpp2 = power(cis);
.
1354c
		ct->vpp1 = ct->vpp2 = power(cis);
.
1350c
	if(readc(cis, &feature) != 1)
.
1344c
		if(readc(cis, &i) != 1)
.
1328c
	if(readc(cis, &c) != 1)
.
1321c
tentry(Slot *pp, Cisdat *cis, int )
.
1315c
		haddress = getlong(cis, asize)*256;
.
1311,1312c
	len = getlong(cis, lsize)*256;
	address = getlong(cis, asize)*256;
.
1307c
memspace(Cisdat *cis, int asize, int lsize, int host)
.
1300c
		ct->irqs = getlong(cis, 2);
.
1296c
	if(readc(cis, &c) != 1)
.
1292c
irq(Cisdat *cis, Conftab *ct)
.
1285,1286c
		ct->io[i].start = getlong(cis, (c>>4)&0x3);
		ct->io[0].len = getlong(cis, (c>>6)&0x3);
.
1280c
	if(readc(cis, &c) != 1)
.
1269c
	if(readc(cis, &c) != 1)
.
1263c
iospaces(Cisdat *cis, Conftab *ct)
.
1259c
		ct->otherwait = ttiming(cis, i);		/* reserved wait */
.
1256c
		ct->readywait = ttiming(cis, i);		/* max ready/busy wait */
.
1253c
		ct->maxwait = ttiming(cis, i);		/* max wait */
.
1249c
	if(readc(cis, &c) != 1)
.
1245c
timing(Cisdat *cis, Conftab *ct)
.
1237c
	if(readc(cis, &unscaled) != 1)
.
1232c
ttiming(Cisdat *cis, int scale)
.
1221c
		nanoamps(cis);
.
1219c
		nanoamps(cis);
.
1217c
		nanoamps(cis);
.
1215c
		nanoamps(cis);
.
1213c
		microvolt(cis);
.
1211c
		microvolt(cis);
.
1209c
		mv = microvolt(cis);
.
1206c
	if(readc(cis, &feature) != 1)
.
1200c
power(Cisdat *cis)
.
1188c
		if(readc(cis, &c) != 1)
.
1184c
	if(readc(cis, &c) != 1)
.
1179c
nanoamps(Cisdat *cis)
.
1161c
		if(readc(cis, &c) != 1)
.
1156c
	if(readc(cis, &c) != 1)
.
1150c
microvolt(Cisdat *cis)
.
1136,1137c
	pp->caddr = getlong(cis, rasize);
	pp->cpresent = getlong(cis, rmsize);
.
1134c
	if(readc(cis, &last) != 1)
.
1130c
	if(readc(cis, &size) != 1)
.
1125c
tcfig(Slot *pp, Cisdat *cis, int )
.
1117c
		if(readc(cis, &c) != 1)
.
1109c
getlong(Cisdat *cis, int size)
.
1107a
int
pcmcistuple(int slotno, int tuple, void *v, int nv)
{
	int n;

	/* try attribute space, then memory */
	if((n = xcistuple(slotno, tuple, v, nv, 1)) >= 0)
		return n;
	return xcistuple(slotno, tuple, v, nv, 0);
}

static void
cisread(Slot *pp)
{
	uchar v[256];
	int i, nv;
	Cisdat cis;

	memset(pp->ctab, 0, sizeof(pp->ctab));
	pp->caddr = 0;
	pp->cpresent = 0;
	pp->configed = 0;
	pp->nctab = 0;

	for(i = 0; i < nelem(cistab); i++) {
		if((nv = pcmcistuple(pp->slotno, cistab[i].n, v, sizeof(v))) >= 0) {
			cis.cisbase = v;
			cis.cispos = 0;
			cis.cisskip = 1;
			cis.cislen = nv;
			
			(*cistab[i].parse)(pp, &cis, cistab[i].n);
		}
	}
}

.
1105c
	pcmunmap(slotno, m);
	return -1;
.
1103c
		if(type == tuple) {
			p = v;
			for(l=0; l<nv && l<link; l++)
				if(readc(&cis, p++) != 1)
					break;
			pcmunmap(slotno, m);
			return nv;
		}
		cis.cispos = this + (2+link);
.
1099,1101c
		if(link == 0xFF)
.
1097c
		if(readc(&cis, &link) != 1)
.
1092,1093c
		this = cis.cispos;
		if(readc(&cis, &type) != 1)
.
1089a
	cis.cisbase = KADDR(m->isa);
	cis.cispos = 0;
	cis.cisskip = attr ? 2 : 1;
	cis.cislen = Mchunk;

.
1086,1088c
		return -1;
.
1078,1084c
	m = pcmmap(slotno, 0, 0, attr);
.
1076a
	Cisdat cis;
	int i, l;
	uchar *p;
	uchar type, link;
	int this;
.
1073,1075d
1070,1071c
static int
xcistuple(int slotno, int tuple, void *v, int nv, int attr)
.
1065c
	*x = pp->cisbase[pp->cisskip*pp->cispos];
.
1063c
	if(pp->cispos >= pp->cislen)
.
1061c
readc(Cisdat *pp, uchar *x)
.
1053,1057c
struct {
	int n;
	void (*parse)(Slot*, Cisdat*, int);
} cistab[] = {
	0x15, tvers1,
	0x1A, tcfig,
	0x1B, tentry,
.
1049,1051c
static void	tcfig(Slot*, Cisdat*, int);
static void	tentry(Slot*, Cisdat*, int);
static void	tvers1(Slot*, Cisdat*, int);
.
178,179c
	Cisdat;
.
146a
/* cis memory walking */
struct Cisdat
{
	uchar	*cisbase;
	int	cispos;
	int	cisskip;
	int	cislen;
};

.
106a
typedef struct Cisdat Cisdat;
.
## diffname pc/devi82365.c 2000/1005
## diff -e /n/emeliedump/2000/0605/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1005/sys/src/9/pc/devi82365.c
673,675c
		/* for card management interrupts */
		sprint(buf, "i82365.%d", i);
		intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf);
	}
.
671d
668c
			wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena);
.
658c
			i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq);
.
644,645c
		i82365probe(0x3E2, 0x3E3, 0);
		i82365probe(0x3E2, 0x3E3, 1);
.
642c
	if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){
.
636,638c
	if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){
		i82365probe(0x3E0, 0x3E1, 0);
		i82365probe(0x3E0, 0x3E1, 1);
.
630,634d
624c
	char buf[NAMELEN];
.
621c
	int i, j;
.
594a
	memset(&isa, 0, sizeof(ISAConf));
	if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq)
		cp->irq = isa.irq;
	else
		cp->irq = IrqPCMCIA;

	for(i = 0; i < isa.nopt; i++){
		if(cistrncmp(isa.opt[i], "nslot=", 6))
			continue;
		nslot = strtol(&isa.opt[i][6], nil, 0);
		if(nslot > 0 && nslot <= 2)
			cp->nslot = nslot;
	}
print("%uX/%d: nslot = %d\n", x, dev, cp->nslot);

.
537a
	ISAConf isa;
	int i, nslot;
.
534c
i82365probe(int x, int d, int dev)
.
455a
print("not found\n");
.
453d
447,451c
		if(pp->occupied) {
print("[%s] ", pp->verstr);
			if(strstr(pp->verstr, idstr))
			if(isa == 0 || pcmio(pp->slotno, isa) == 0){
				pp->special = 1;
print("done\n");
				return pp->slotno;
			}
.
441a
print("Looking for %s ...", idstr);
.
276a
print("done-");
.
268a
print("...");
.
267a
print(">");
.
266a
print("<");
.
265a
print(">");
.
264a
print("<");
.
263a
print(">");
.
261a
print("-enabling<");
.
123a
	int	irq;
.
## diffname pc/devi82365.c 2000/1006
## diff -e /n/emeliedump/2000/1005/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1006/sys/src/9/pc/devi82365.c
623d
468d
465c
		} else
			pp->special = 1;
.
462d
458d
450,451c
	if (! resetdone) {
		i82365reset();
		resetdone++;
	}
.
448a
	static int resetdone;
.
285d
276d
274d
272d
270d
268d
266d
263d
## diffname pc/devi82365.c 2000/1007
## diff -e /n/emeliedump/2000/1006/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1007/sys/src/9/pc/devi82365.c
443,446c
	i82365reset();
.
## diffname pc/devi82365.c 2000/1021
## diff -e /n/emeliedump/2000/1007/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1021/sys/src/9/pc/devi82365.c
1164c
		if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) {
.
1147c
	return xcistuple(slotno, tuple, subtuple, v, nv, 0);
.
1145c
	if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
.
1140c
pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
.
1127c
			for(l=0; l<nv && l<n; l++)
.
1125c

		n = link;
		if (link > 1 && subtuple != -1) {
			if (readc(&cis, &c) != 1)
				break;
			subtype = c;
			n--;
		} else
			subtype = -1;

		if(type == tuple && subtype == subtuple) {
.
1102,1103c
	uchar type, link, n, c;
	int this, subtype;
.
1096c
xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
.
## diffname pc/devi82365.c 2000/1106
## diff -e /n/emeliedump/2000/1021/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1106/sys/src/9/pc/devi82365.c
458a
print("\n");
.
452a
print(" - found\n");
.
449a
print("[%8.8s]", pp->verstr);
.
443a
print("pcmcia: looking for %s: ", idstr);
.
## diffname pc/devi82365.c 2000/1107
## diff -e /n/emeliedump/2000/1106/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1107/sys/src/9/pc/devi82365.c
682a
			pp->msec = ~0;
.
462d
460c
		if (enabled)
			decrefp(pp);
.
451,456c
			if(strstr(pp->verstr, idstr)) {
				if (!enabled)
					increfp(pp);
				if(isa == 0 || pcmio(pp->slotno, isa) == 0){
					pp->special = 1;
					return pp->slotno;
				}
.
448c
		enabled = 0;
		/* make sure we don't power on cards when we already know what's
		 * in them.  We'll reread every two minutes if necessary
		 */
		if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) {
			increfp(pp);
			enabled++;
		}
.
444d
441c
	int enabled;
.
238a
	pp->msec = TK2MS(MACHP(0)->ticks);
.
180a
	ulong	msec;		/* time of last slotinfo call */
.
## diffname pc/devi82365.c 2000/1109
## diff -e /n/emeliedump/2000/1107/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1109/sys/src/9/pc/devi82365.c
1500a
print("pcmcia: %s\n", pp->verstr);
.
## diffname pc/devi82365.c 2000/1110
## diff -e /n/emeliedump/2000/1109/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1110/sys/src/9/pc/devi82365.c
1501d
## diffname pc/devi82365.c 2000/1111
## diff -e /n/emeliedump/2000/1110/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1111/sys/src/9/pc/devi82365.c
1030c

.
## diffname pc/devi82365.c 2000/1115
## diff -e /n/emeliedump/2000/1111/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1115/sys/src/9/pc/devi82365.c
671c
		i82365probe(0x3E2, 0x3E3, 0) ||
.
664c
		i82365probe(0x3E0, 0x3E1, 0) ||
.
## diffname pc/devi82365.c 2000/1116
## diff -e /n/emeliedump/2000/1115/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1116/sys/src/9/pc/devi82365.c
1185a
	pp->verstr[0] = 0;
.
846,847c
		n = readstr(offset, a, n, buf);
		free(buf);
.
843,844c
			p = seprint(p, e, "busy\n");
		seprint(p, e, "battery lvl %d\n", pp->battery);
.
841c
			p = seprint(p, e, "write protected\n");
.
839c
			p = seprint(p, e, "configed\n");
.
837c
			p = seprint(p, e, "powered\n");
.
835c
			p = seprint(p, e, "enabled\n");
.
832,833c
		buf[0] = 0;
		if(pp->occupied){
			p = seprint(p, e, "occupied\n");
			if(pp->verstr[0])
				p = seprint(p, e, "version %s\n", pp->verstr);
		}
.
828,829c
		buf = p = malloc(READSTR);
		e = p + READSTR;
.
816,817c
	char *p, *buf, *e;
.
692a
			pp->verstr[0] = 0;
.
671c
		i82365probe(0x3E2, 0x3E3, 0);
.
664c
		i82365probe(0x3E0, 0x3E1, 0);
.
606a
#endif asdf
.
602a

		/* go back to Intel compatible id */
.
599,600d
593a

		/* make the id register show the Vadem id */
.
591a
		/* unlock the Vadem extended regs */
.
590a
#ifdef adsf
	/* if it's not a Cirrus, it could be a Vadem... */
.
560c
		return 0;		/* not a memory & I/O card */
	if((id & 0x0f) == 0x00)
		return 0;		/* no revision number, not possible */
.
461a
				}
.
459,460c
			if(strstr(pp->verstr, idstr)){
				if (!enabled){
					enabled = 1;
.
453c
		enabled = 0;
		if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){
.
449,451c

		/*
		 *  make sure we don't power on cards when we already know what's
		 *  in them.  We'll reread every two minutes if necessary
.
## diffname pc/devi82365.c 2000/1118
## diff -e /n/emeliedump/2000/1116/sys/src/9/pc/devi82365.c /n/emeliedump/2000/1118/sys/src/9/pc/devi82365.c
1096,1518d
975,976c
	PCMslot *pp;
	PCMconftab *ct, *et, *t;
.
968c
 *  configure the PCMslot for IO.  We assume very heavily that we can read
.
915c
	PCMslot *pp;
.
877c
	PCMslot *pp;
.
830c
	PCMslot *pp;
.
791c
	PCMslot *pp;
.
690c
	slot = xalloc(nslot * sizeof(PCMslot));
.
667c
	PCMslot *pp;
.
644c
i82365dump(PCMslot *pp)
.
618d
597d
511c
	PCMslot *pp;
.
482c
	PCMslot *pp;
.
441c
	PCMslot *pp;
.
427c
decrefp(PCMslot *pp)
.
418c
increfp(PCMslot *pp)
.
409c
	PCMslot *pp;
.
349c
	for(m = pp->mmap; m < &pp->mmap[nelem(pp->mmap)]; m++){
.
329c
	PCMslot *pp;
.
300c
	PCMslot *pp;
.
286c
slotdis(PCMslot *pp)
.
276c
		pcmcisread(pp);
.
260c
slotena(PCMslot *pp)
.
230c
slotinfo(PCMslot *pp)
.
222,223c
	outb(((I82365*)pp->cp)->xreg, pp->base + index);
	outb(((I82365*)pp->cp)->dreg, val);
.
220c
wrreg(PCMslot *pp, int index, uchar val)
.
216,217c
	outb(((I82365*)pp->cp)->xreg, pp->base + index);
	return inb(((I82365*)pp->cp)->dreg);
.
214c
rdreg(PCMslot *pp, int index)
.
208c
static void i82365dump(PCMslot*);
.
201d
128,198c
static PCMslot	*slot;
static PCMslot	*lastslot;
.
105,107d
98,99d
87,90d
10c
 *  Support for up to 4 PCMslot card slots.  Generalizing above that is hard
.
## diffname pc/devi82365.c 2001/0315
## diff -e /n/emeliedump/2000/1118/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0315/sys/src/9/pc/devi82365.c
297c
			print("pcmmap: %d out of isa space\n", len);
.
## diffname pc/devi82365.c 2001/0517
## diff -e /n/emeliedump/2001/0315/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0517/sys/src/9/pc/devi82365.c
591a

	/* First find Ricoh controllers on the PCI bus */
	p = nil;
	while ((p = pcimatch(p, Ricoh_vid, 0)) != nil) {
		for (i = 0; i != nelem(variant); i++)
			if (p->did == variant[i].r_did)
				break;
		if (i == nelem(variant)) {
			print("No match on %.4X/%.4X\n", p->vid, p->did);
			continue;
		}

		print("#y: %s, intl %d\n", variant[i].r_name, p->intl);

		for (i = 0; i != 0xE4 / 4; i++)
			iprint("pci[%.2X] %.8ulX\n", i * 4, pcicfgr32(p, i * 4));
		break;
	}
.
583a
	Pcidev *p;
.
99a
enum {
	Ricoh_vid = 0x1180,
	Ricoh_476_did = 0x476,
};

static struct {
	ushort	r_did;
	char		*r_name;
} variant[] = {
{	Ricoh_476_did,	"Ricoh 476 PCI/Cardbus bridge",	}
};

.
## diffname pc/devi82365.c 2001/0519
## diff -e /n/emeliedump/2001/0517/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0519/sys/src/9/pc/devi82365.c
605,622d
596d
100,111d
## diffname pc/devi82365.c 2001/0527
## diff -e /n/emeliedump/2001/0519/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0527/sys/src/9/pc/devi82365.c
872d
674c
		if((c->qid.type & QTDIR) == 0)
.
659c
	if(c->qid.type & QTDIR){
.
653c
	return devstat(c, db, n, 0, 0, pcmgen);
.
650,651c
static int
i82365stat(Chan *c, uchar *db, int n)
.
647c
	return devwalk(c, nc, name, nname, 0, 0, pcmgen);
.
644,645c
static Walkqid*
i82365walk(Chan *c, Chan *nc, char **name, int nname)
.
633c
		snprint(buf, sizeof buf, "i82365.%d", i);
.
587c
	char buf[32];
.
462c
	devdir(c, qid, up->genbuf, len, eve, 0660, dp);
.
458c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
.
453c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
.
448c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
.
436c
		mkqid(&qid, Qdir, 0, QTDIR);
		devdir(c, qid, "#y", 0, eve, 0555, dp);
.
433d
427c
pcmgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
.
422,423c
#define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c)		((ulong)(c->qid.path&0xff))
.
297c
			print("pcmmap: out of isa space\n");
.
## diffname pc/devi82365.c 2001/0529
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0529/sys/src/9/pc/devi82365.c
423c
#define TYPE(c)	((ulong)(c->qid.path&0xff))
.
## diffname pc/devi82365.c 2001/0619
## diff -e /n/emeliedump/2001/0529/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0619/sys/src/9/pc/devi82365.c
978c
	/*
	 * enable io port map 0
	 * the 'top' register value includes the last valid address
	 */
.
## diffname pc/devi82365.c 2001/0627
## diff -e /n/emeliedump/2001/0619/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0627/sys/src/9/pc/devi82365.c
461a
	qid.type = QTFILE;
.
## diffname pc/devi82365.c 2001/0720
## diff -e /n/emeliedump/2001/0627/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0720/sys/src/9/pc/devi82365.c
539,543d
515a

		/* low power mode */
		outb(x, Rmisc2 + (dev<<7));
		c = inb(d);
		outb(d, c & ~Flowpow);
.
## diffname pc/devi82365.c 2001/0730
## diff -e /n/emeliedump/2001/0720/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0730/sys/src/9/pc/devi82365.c
573d
570a
		print("%2.2uX ", rdreg(pp, i));
.
## diffname pc/devi82365.c 2001/0731
## diff -e /n/emeliedump/2001/0730/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0731/sys/src/9/pc/devi82365.c
612d
470,471c
[Tpd6710]	"Cirrus Logic CL-PD6710",
[Tpd6720]	"Cirrus Logic CL-PD6720",
.
161a
print("isr %2.2uX misc1 %2.2uX\n", isr, rdreg(pp, Rmisc1));
.
15,19d
10,13c
 *  Intel 82365SL PCIC controller and compatibles.
.
## diffname pc/devi82365.c 2001/0801
## diff -e /n/emeliedump/2001/0731/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0801/sys/src/9/pc/devi82365.c
154d
## diffname pc/devi82365.c 2001/0905
## diff -e /n/emeliedump/2001/0801/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0905/sys/src/9/pc/devi82365.c
580a

	if (!getconf("pcmcia0"))
		return;
	
	if (_pcmspecial) {
		print("#y: PCMCIA and CardBus at the same time?\n");
		return;
	}
	
	_pcmspecial = pcmcia_pcmspecial;
	_pcmspecialclose = pcmcia_pcmspecialclose;
.
392,393c
static void
pcmcia_pcmspecialclose(int slotno)
.
351,352c
static int
pcmcia_pcmspecial(char *idstr, ISAConf *isa)
.
## diffname pc/devi82365.c 2001/0906
## diff -e /n/emeliedump/2001/0905/sys/src/9/pc/devi82365.c /n/emeliedump/2001/0906/sys/src/9/pc/devi82365.c
872c
	devreset,
.
593,595d
581a
	if(already)
		return;
	already = 1;

.
573,574c
void
devi82365link(void)
.
358d
116d
## diffname pc/devi82365.c 2002/0109
## diff -e /n/emeliedump/2001/0906/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0109/sys/src/9/pc/devi82365.c
872a
	devshutdown,
.
## diffname pc/devi82365.c 2002/0110
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0110/sys/src/9/pc/devi82365.c
1012c
		if(ct->irqtype & 0x20)
.
1010c
		/*  set configuration and interrupt type.
		 *  if level is possible on the card, use it.
		 */
.
## diffname pc/devi82365.c 2002/0403
## diff -e /n/emeliedump/2002/0110/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0403/sys/src/9/pc/devi82365.c
594d
587,591d
584c
	if(_pcmspecial)
.
## diffname pc/devi82365.c 2002/0414
## diff -e /n/emeliedump/2002/0403/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0414/sys/src/9/pc/devi82365.c
603a

	if(ncontroller == 0)
		return;

	_pcmspecial = pcmcia_pcmspecial;
	_pcmspecialclose = pcmcia_pcmspecialclose;

.
587,589d
## diffname pc/devi82365.c 2002/0502
## diff -e /n/emeliedump/2002/0414/sys/src/9/pc/devi82365.c /n/emeliedump/2002/0502/sys/src/9/pc/devi82365.c
582a

	if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0)
		return;
.
578c
	char buf[32], *p;
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.