Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/bitsy/devpcmcia.c

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


## diffname bitsy/devpcmcia.c 2000/1118
## diff -e /dev/null /n/emeliedump/2000/1118/sys/src/9/bitsy/devpcmcia.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"

static PCMslot	slot[2];
int nslot = 2;

struct {
	Ref;
} pcmcia;

enum
{
	Qdir,
	Qmem,
	Qattr,
	Qctl,

	Nents = 3,
};

#define SLOTNO(c)	((c->qid.path>>8)&0xff)
#define TYPE(c)		(c->qid.path&0xff)
#define QID(s,t)	(((s)<<8)|(t))

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

	if(i == DEVDOTDOT){
		devdir(c, (Qid){CHDIR, 0}, "#y", 0, eve, 0555, dp);
		return 1;
	}

	if(i >= Nents*nslot)
		return -1;

	slotno = i/Nents;
	pp = slot + slotno;
	len = 0;
	switch(i%Nents){
	case 0:
		qid.path = QID(slotno, Qmem);
		sprint(name, "pcm%dmem", slotno);
		len = pp->memlen;
		break;
	case 1:
		qid.path = QID(slotno, Qattr);
		sprint(name, "pcm%dattr", slotno);
		len = pp->memlen;
		break;
	case 2:
		qid.path = QID(slotno, Qctl);
		sprint(name, "pcm%dctl", slotno);
		break;
	}
	qid.vers = 0;
	devdir(c, qid, name, len, eve, 0660, dp);
	return 1;
}

static void
slotinfo(void)
{
	ulong x = gpioregs->level;

	if(x & GPIO_OPT_IND_i){
		/* no expansion pack */
		slot[0].occupied = 0;
		slot[1].occupied = 0;
	} else {
		slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0;
		slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0;
	}
}

static void
increfp(PCMslot *pp)
{
	if(incref(&pcmcia) == 1)
		exppackpower(1);
	lock(pp);
	if(pp->ref++ == 0)
		;
	unlock(pp);
	slotinfo();
}
static void
decrefp(PCMslot *pp)
{
	slotinfo();
	lock(pp);
	if(pp->ref-- == 1)
		;
	unlock(pp);
	if(decref(&pcmcia) == 0)
		exppackpower(0);
}

/*
 *  get a map for pc card region, return corrected len
 */
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
{
	if(slotno > nslot)
		panic("pcmmap");
	if(attr)
		return &slot[slotno].attrmap;
	else
		return &slot[slotno].memmap;
}
void
pcmunmap(int, PCMmap*)
{
}

/*
 *  map in the space for the cards
 */
static void
pcmciareset(void)
{
	int j;
	PCMslot *pp;

	for(j = 0; j < nslot; j++){
		pp = &slot[j];
		pp->slotno = j;
		pp->memlen = 64*OneMeg;
		pp->msec = ~0;
		pp->verstr[0] = 0;

		pp->mem = mapmem(j == 0 ? PYHSPCM0MEM : PYHSPCM1MEM, 64*OneMeg);
		pp->memmap.ca = 0;
		pp->memmap.cea = 64*MB;
		pp->memmap.isa = (ulong)pp->mem;
		pp->memmap.len = 64*OneMeg;
		pp->memmap.attr = 0;

		pp->attr = mapmem(j == 0 ? PYHSPCM0ATTR : PYHSPCM1ATTR, OneMeg);
		pp->attrmap.ca = 0;
		pp->attrmap.cea = 64*MB;
		pp->attrmap.isa = (ulong)pp->attr;
		pp->attrmap.len = OneMeg;
		pp->attrmap.attr = 1;

		pp->regs = mapspecial(j == 0 ? PHYSPCM0REGS : PHYSPCM1REGS, 32*1024);
	}
}

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

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

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

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

static void
pcmciaclose(Chan *c)
{
	if(c->flag & COPEN)
		if(c->qid.path != CHDIR)
			decrefp(slot+SLOTNO(c));
}

/* a memmove using only bytes */
static void
memmoveb(uchar *to, uchar *from, int n)
{
	while(n-- > 0)
		*to++ = *from++;
}

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

static long
pcmread(void *a, long n, ulong off, uchar *start, ulong len)
{
	if(off > len)
		return 0;
	if(off + n > len)
		n = len - off;
	memmoves(a, start+off, n);
	return n;
}

static long
pcmctlread(void *a, long n, ulong off, PCMslot *pp)
{
	char *p, *buf, *e;

	buf = p = malloc(READSTR);
	if(waserror()){
		free(buf);
		nexterror();
	}
	e = p + READSTR;

	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);
	}
	USED(p);

	n = readstr(off, a, n, buf);
	free(buf);
	poperror();
	return n;
}

static long
pcmciaread(Chan *c, void *a, long n, vlong off)
{
	PCMslot *pp;
	ulong offset = off;

	pp = slot + SLOTNO(c);

	switch(TYPE(c)){
	case Qdir:
		return devdirread(c, a, n, 0, 0, pcmgen);
	case Qmem:
		if(!pp->occupied)
			error(Eio);
		return pcmread(a, n, offset, pp->mem, 64*OneMeg);
	case Qattr:
		if(!pp->occupied)
			error(Eio);
		return pcmread(a, n, offset, pp->attr, OneMeg);
	case Qctl:
		return pcmctlread(a, n, offset, pp);
	}
	error(Ebadarg);
	return -1;	/* not reached */
}

static long
pcmwrite(void *a, long n, ulong off, uchar *start, ulong len)
{
	if(off > len)
		error(Eio);
	if(off + n > len)
		error(Eio);
	memmoveb(start+off, a, n);
	return n;
}

static long
pcmctlwrite(char *p, long n, ulong off, PCMslot *pp)
{
	/* nothing yet */
	USED(p, n, off, pp);
	error(Ebadarg);
	return 0;
}

static long
pcmciawrite(Chan *c, void *a, long n, vlong off)
{
	PCMslot *pp;
	ulong offset = off;

	pp = slot + SLOTNO(c);

	switch(TYPE(c)){
	case Qmem:
		if(!pp->occupied)
			error(Eio);
		return pcmwrite(a, n, offset, pp->mem, 64*OneMeg);
	case Qattr:
		if(!pp->occupied)
			error(Eio);
		return pcmwrite(a, n, offset, pp->attr, OneMeg);
	case Qctl:
		if(!pp->occupied)
			error(Eio);
		return pcmctlwrite(a, n, offset, pp);
	}
	error(Ebadarg);
	return -1;	/* not reached */
}

Dev pcmciadevtab = {
	'y',
	"pcmcia",

	pcmciareset,
	devinit,
	pcmciaattach,
	devclone,
	pcmciawalk,
	pcmciastat,
	pcmciaopen,
	devcreate,
	pcmciaclose,
	pcmciaread,
	devbread,
	pcmciawrite,
	devbwrite,
	devremove,
	devwstat,
};
.
## diffname bitsy/devpcmcia.c 2000/1121
## diff -e /n/emeliedump/2000/1118/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1121/sys/src/9/bitsy/devpcmcia.c
355a

/* see what's there */
static void
slotinfo(void)
{
	ulong x = gpioregs->level;

	if(x & GPIO_OPT_IND_i){
		/* no expansion pack */
		slot[0].occupied = 0;
		slot[1].occupied = 0;
	} else {
		slot[0].occupied = (x & GPIO_CARD_IND0_i) == 0;
		slot[1].occupied = (x & GPIO_CARD_IND1_i) == 0;
	}
}

/* use reference card to turn cards on and off */
static void
increfp(PCMslot *pp)
{
	if(incref(&pcmcia) == 1){
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
		egpiobits(EGPIO_pcmcia_reset, 0);
		delay(100);	/* time to power up */
	}

	incref(pp);

	slotinfo();
}

static void
decrefp(PCMslot *pp)
{
	slotinfo();
	decref(pp);
	if(decref(&pcmcia) == 0)
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}

/*
 *  the regions are staticly mapped
 */
static void
slotmap(int slotno, ulong regs, ulong attr, ulong mem)
{
	PCMslot *pp;

	pp = &slot[slotno];
	pp->slotno = slotno;
	pp->memlen = 64*OneMeg;
	pp->msec = ~0;
	pp->verstr[0] = 0;

	pp->mem = mapmem(mem, 64*OneMeg, 0);
	pp->memmap.ca = 0;
	pp->memmap.cea = 64*MB;
	pp->memmap.isa = (ulong)pp->mem;
	pp->memmap.len = 64*OneMeg;
	pp->memmap.attr = 0;

	pp->attr = mapmem(attr, OneMeg, 0);
	pp->attrmap.ca = 0;
	pp->attrmap.cea = MB;
	pp->attrmap.isa = (ulong)pp->attr;
	pp->attrmap.len = OneMeg;
	pp->attrmap.attr = 1;

	pp->regs = mapspecial(regs, 32*1024);
}
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
{
	if(slotno > nslot)
		panic("pcmmap");
	if(attr)
		return &slot[slotno].attrmap;
	else
		return &slot[slotno].memmap;
}
void
pcmunmap(int, PCMmap*)
{
}

/*
 *  setup card timings
 *    times are in ns
 *    count = ceiling[access-time/(2*3*T)] - 1, where T is a processor cycle
 *
 */
static int
ns2count(int ns)
{
	ulong y;

	/* get 100 times cycle time */
	y = 100000000/(conf.hz/1000);

	/* get 10 times ns/(cycle*6) */
	y = (1000*ns)/(6*y);

	/* round up */
	y += 9;
	y /= 10;

	/* subtract 1 */
	return y-1;
}
static void
slottiming(int slotno, int tio, int tattr, int tmem, int fast)
{
	ulong x;

	x = 0;
	if(fast)
		x |= 1<<MECR_fast0;
	x |= ns2count(tio) << MECR_io0;
	x |= ns2count(tattr) << MECR_attr0;
	x |= ns2count(tmem) << MECR_mem0;
	if(slotno == 0){
		x |= memconfregs->mecr & 0xffff0000;
	} else {
		x <<= 16;
		x |= memconfregs->mecr & 0xffff;
	}
	memconfregs->mecr = x;
}
.
234c
	memmoveb(a, start+off, n);
.
136,158c
	/* set timing to the default, 300 */
	slottiming(0, 300, 300, 300, 0);
	slottiming(1, 300, 300, 300, 0);
.
133,134c
	/* staticly map the whole area */
	slotmap(0, PHYSPCM0REGS, PYHSPCM0ATTR, PYHSPCM0MEM);
	slotmap(1, PHYSPCM1REGS, PYHSPCM1ATTR, PYHSPCM1MEM);
.
112,129d
110c
 *  set up the cards, default timing is 300 ns
.
71,108d
29a
static void increfp(PCMslot*);
static void decrefp(PCMslot*);
static void slotmap(int, ulong, ulong, ulong);
static void slottiming(int, int, int, int, int);

.
## diffname bitsy/devpcmcia.c 2000/1122
## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1122/sys/src/9/bitsy/devpcmcia.c
321d
314,315c
	if(pp->occupied && pp->cisread == 0)
		pcmcisread(pp);
.
312d
310c
		delay(200);	/* time to power up */
.
306a
	slotinfo(nil, nil);
.
298,299c
		if(!slot[0].occupied && (x & GPIO_CARD_IND0_i)){
			slot[0].occupied = 1;
			slot[0].cisread = 0;
		}
		if(!slot[1].occupied && (x & GPIO_CARD_IND1_i)){
			slot[1].occupied = 1;
			slot[0].cisread = 0;
		}
.
289c
slotinfo(Ureg*, void*)
.
88a

	/* interrupt on card insertion */
	gpiointrenable(
.
## diffname bitsy/devpcmcia.c 2000/1128
## diff -e /n/emeliedump/2000/1122/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1128/sys/src/9/bitsy/devpcmcia.c
330c
	decref(&pp->ref);
.
322c
	incref(&pp->ref);
.
90,91c
	/* interrupt on card insertion/removal */
	gpiointrenable(GPIO_CARD_IND1_i, GPIOboth, slotinfo, nil, "pcmcia slot1 status");
	gpiointrenable(GPIO_CARD_IND0_i, GPIOboth, slotinfo, nil, "pcmcia slot0 status");
.
33a
static void slotinfo(Ureg*, void*);
.
## diffname bitsy/devpcmcia.c 2000/1130
## diff -e /n/emeliedump/2000/1128/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1130/sys/src/9/bitsy/devpcmcia.c
318d
## diffname bitsy/devpcmcia.c 2000/1201
## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1201/sys/src/9/bitsy/devpcmcia.c
360c
	pp->attrmap.isa = (ulong)attr;
.
353c
	pp->memmap.isa = (ulong)mem;
.
309c
			slot[1].cisread = 0;
.
307c
		if(x & GPIO_CARD_IND1_i){
			slot[1].occupied = 0;
			slot[1].cisread = 0;
		} else if(slot[1].occupied == 0){
.
303c
		if(x & GPIO_CARD_IND0_i){
			slot[0].occupied = 0;
			slot[0].cisread = 0;
		} else if(slot[0].occupied == 0){
.
## diffname bitsy/devpcmcia.c 2000/1205
## diff -e /n/emeliedump/2000/1201/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1205/sys/src/9/bitsy/devpcmcia.c
370c
	sp->regs = mapspecial(regs, 32*1024);
.
363,368c
	sp->attr = mapmem(attr, OneMeg, 0);
	sp->attrmap.ca = 0;
	sp->attrmap.cea = MB;
	sp->attrmap.isa = (ulong)attr;
	sp->attrmap.len = OneMeg;
	sp->attrmap.attr = 1;
.
356,361c
	sp->mem = mapmem(mem, 64*OneMeg, 0);
	sp->memmap.ca = 0;
	sp->memmap.cea = 64*MB;
	sp->memmap.isa = (ulong)mem;
	sp->memmap.len = 64*OneMeg;
	sp->memmap.attr = 0;
.
350,354c
	sp = &slot[slotno];
	sp->slotno = slotno;
	sp->memlen = 64*OneMeg;
	sp->verstr[0] = 0;
.
348c
	PCMslot *sp;
.
343c
 *  the regions are staticly masped
.
337c
	decref(&sp->ref);
.
335c
decrefp(PCMslot *sp)
.
329,331c
	incref(&sp->ref);
	slotinfo(nil, nil);
	if(sp->occupied && sp->cisread == 0)
		pcmcisread(sp);

	wunlock(sp);
	poperror();
.
327c
		delay(500);
.
325a
		delay(200);
		egpiobits(EGPIO_pcmcia_reset, 1);
		delay(100);
.
323a
	wlock(sp);
	if(waserror()){
		wunlock(sp);
		nexterror();
	}

.
322c
increfp(PCMslot *sp)
.
315d
313c
		} else {
			if(slot[1].occupied == 0)
				slot[1].cisread = 0;
.
308d
306c
		} else {
			if(slot[0].occupied == 0)
				slot[0].cisread = 0;
.
265c
		return pcmctlwrite(a, n, offset, sp);
.
263c
		if(!sp->occupied)
.
261c
		return pcmwrite(a, n, offset, sp, sp->attr, OneMeg);
.
259c
		if(!sp->occupied)
.
257c
		return pcmwrite(a, n, offset, sp, sp->mem, 64*OneMeg);
.
255c
		if(!sp->occupied)
.
251c
	sp = slot + SLOTNO(c);
.
248c
	PCMslot *sp;
.
239,241c
	Cmdbuf *cmd;
	uchar *cp;
	int index, i, dtx;
	Rune r;
	DevConf cf;

	cmd = parsecmd(p, n);
	if(strcmp(cmd->f[0], "configure") == 0){
		wlock(sp);
		if(waserror()){
			wunlock(sp);
			nexterror();
		}

		/* see if driver exists and is configurable */
		if(cmd->nf < 3)
			error(Ebadarg);
		p = cmd->f[1];
		if(*p++ != '#')
			error(Ebadarg);
		p += chartorune(&r, p);
		dtx = devno(r, 1);
		if(dtx < 0)
			error("no such device type");
		if(devtab[dtx]->config == nil)
			error("not a dynamicly configurable device");

		/* set pcmcia card configuration */
		index = 0;
		if(sp->def != nil)
			index = sp->def->index;
		if(cmd->nf > 3){
			i = atoi(cmd->f[3]);
			if(i < 0 || i >= sp->nctab)
				error("bad configuration index");
			index = i;
		}
		if(sp->cpresent & (1<<Rconfig)){
			cp = sp->attr;
			cp += sp->caddr + Rconfig;
print("writing configuration register (%lux) with index %d\n", cp, index);
			*cp = index;
		}

		/* configure device */
		strncpy(cf.type, cmd->f[2], sizeof(cf.type)-1);
		cf.type[sizeof(cf.type)-1] = 0;
		cf.mem = (ulong)sp->mem;
		cf.port = (ulong)sp->regs;
		cf.itype = GPIOfalling;
		cf.interrupt = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
		cf.size = 0;
		if(devtab[dtx]->config(1, p, &cf) < 0)
			error("couldn't configure device");

		wunlock(sp);
		poperror();

		/* don't let the power turn off */
		increfp(sp);
	}
	free(cmd);

.
237c
pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
.
232a
	poperror();
	runlock(sp);
.
227a
	rlock(sp);
	if(waserror()){
		runlock(sp);
		nexterror();
	}
.
226c
pcmwrite(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
.
219c
		return pcmctlread(a, n, offset, sp);
.
217c
		return pcmread(a, n, offset, sp, sp->attr, OneMeg);
.
215c
		if(!sp->occupied)
.
213c
		return pcmread(a, n, offset, sp, sp->mem, 64*OneMeg);
.
211c
		if(!sp->occupied)
.
205c
	sp = slot + SLOTNO(c);
.
202c
	PCMslot *sp;
.
188,189c
		if(sp->verstr[0])
			p = seprint(p, e, "version %s\n", sp->verstr);
.
186c
	if(sp->occupied){
.
174c
pcmctlread(void *a, long n, ulong off, PCMslot *sp)
.
169a
	runlock(sp);
	poperror();
.
164a
	rlock(sp);
	if(waserror()){
		runlock(sp);
		nexterror();
	}
.
163c
pcmread(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
.
91,93c
	/* if there's no pcmcia sleave, no interrupts */
	if(gpioregs->level & GPIO_OPT_IND_i)
		return;

	/* sleave there, interrupt on card removal */
	intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
	intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
.
76a
static int
bitno(ulong x)
{
	int i;

	for(i = 0; i < 8*sizeof(x); i++)
		if((1<<i) & x)
			break;
	return i;
}

.
65c
		len = sp->memlen;
.
60c
		len = sp->memlen;
.
54c
	sp = slot + slotno;
.
42c
	PCMslot *sp;
.
25a
enum
{
	/*
	 *  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 */
};

.
## diffname bitsy/devpcmcia.c 2000/1206
## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2000/1206/sys/src/9/bitsy/devpcmcia.c
319d
## diffname bitsy/devpcmcia.c 2001/0529
## diff -e /n/emeliedump/2000/1206/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devpcmcia.c
377d
323,324c
		kstrdup(&cf.type, cmd->f[2]);
.
158c
		if((c->qid.type & QTDIR) == 0)
.
143c
	if(c->qid.type & QTDIR){
.
137c
	return devstat(c, db, n, 0, 0, pcmgen);
.
134,135c
static int
pcmciastat(Chan *c, uchar *db, int n)
.
131c
	return devwalk(c, nc, name, nname, 0, 0, pcmgen);
.
128,129c
static Walkqid*
pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
.
84c
	devdir(c, qid, up->genbuf, len, eve, 0660, dp);
.
80c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dctl", slotno);
.
75c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dattr", slotno);
.
70c
		snprint(up->genbuf, sizeof up->genbuf, "pcm%dmem", slotno);
.
57c
		mkqid(&qid, Qdir, 0, QTDIR);
		devdir(c, qid, "#y", 0, eve, 0555, dp);
.
54d
48c
pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp)
.
37,38c
#define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))
#define TYPE(c)	((ulong)(c->qid.path&0xff))
.
## diffname bitsy/devpcmcia.c 2001/0616
## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0616/sys/src/9/bitsy/devpcmcia.c
440a
	}
.
439c
	if(sp->occupied && sp->cisread == 0) {
.
422a
	print("increfp\n");
.
349c
	sp = slotno(c);
.
238c
	sp = slotno(c);
.
159c
			decrefp(slotno(c));
.
147c
		increfp(slotno(c));
.
142a
	print("pcmciaopen\n");
.
79c
		qid.path = PATH(slotno, Qctl);
.
74c
		qid.path = PATH(slotno, Qattr);
.
69c
		qid.path = PATH(slotno, Qmem);
.
46a
#define TYPE(c)		(((ulong)c->qid.path)&0xff)
#define PATH(s,t)	(((s)<<8)|(t))

static PCMslot*
slotno(Chan *c)
{
	ulong x;

	x = c->qid.path;
	return slot + ((x>>8)&0xff);
}

.
37,40d
## diffname bitsy/devpcmcia.c 2001/0617
## diff -e /n/emeliedump/2001/0616/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0617/sys/src/9/bitsy/devpcmcia.c
331a
		cf.type = nil;
.
## diffname bitsy/devpcmcia.c 2001/0619
## diff -e /n/emeliedump/2001/0617/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0619/sys/src/9/bitsy/devpcmcia.c
433d
359c
	sp = slotof(c);
.
247c
	sp = slotof(c);
.
168c
			decrefp(slotof(c));
.
155,156c
	} else {
		slotp = slotof(c);
		increfp(slotp);
	}
.
151c
	PCMslot *slotp;

.
91a
	qid.type = QTFILE;
.
47c
slotof(Chan *c)
.
## diffname bitsy/devpcmcia.c 2001/0815
## diff -e /n/emeliedump/2001/0619/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2001/0815/sys/src/9/bitsy/devpcmcia.c
507a

.
497a

.
## diffname bitsy/devpcmcia.c 2002/0109
## diff -e /n/emeliedump/2001/0815/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devpcmcia.c
388a
	devshutdown,
.
## diffname bitsy/devpcmcia.c 2002/0607
## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0607/sys/src/9/bitsy/devpcmcia.c
350a
	}else if(strcmp(cmd->f[0], "remove") == 0){
		wlock(sp);
		if(waserror()){
			wunlock(sp);
			nexterror();
		}


		wunlock(sp);
		poperror();
.
118,128c
	pcmciapower(1);
.
108a
 * power up/down pcmcia
 */
static void
pcmciapower(int up)
{
	/* if there's no pcmcia sleave, no interrupts */
	if(gpioregs->level & GPIO_OPT_IND_i)
		return;
	if (up){
		/* set timing to the default, 300 */
		slottiming(0, 300, 300, 300, 0);
		slottiming(1, 300, 300, 300, 0);

		/* if there's no pcmcia sleave, no interrupts */
		if(gpioregs->level & GPIO_OPT_IND_i)
			return;

		/* sleave there, interrupt on card removal */
		intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
		intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
	}else{
	}
}

/*
.
## diffname bitsy/devpcmcia.c 2002/0613
## diff -e /n/emeliedump/2002/0607/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0613/sys/src/9/bitsy/devpcmcia.c
359a
		wunlock(&cf);
.
357d
351c
		memset(&cf, 0, sizeof cf);
		wlock(&cf);
.
## diffname bitsy/devpcmcia.c 2002/0614
## diff -e /n/emeliedump/2002/0613/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0614/sys/src/9/bitsy/devpcmcia.c
374,376c
		/* let the power turn off */
		decrefp(sp);
.
368,372c
		/* see if driver exists and is configurable */
		if(cmd->nf != 2)
			error(Ebadarg);
		p = cmd->f[1];
		if(*p++ != '#')
			error(Ebadarg);
		p += chartorune(&r, p);
		dtx = devno(r, 1);
		if(dtx < 0)
			error("no such device type");
		if(devtab[dtx]->config == nil)
			error("not a dynamicly configurable device");
		if(devtab[dtx]->config(0, p, nil) < 0)
			error("couldn't unconfigure device");
.
360d
352d
## diffname bitsy/devpcmcia.c 2002/0615
## diff -e /n/emeliedump/2002/0614/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0615/sys/src/9/bitsy/devpcmcia.c
356c
		cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
## diffname bitsy/devpcmcia.c 2002/0618
## diff -e /n/emeliedump/2002/0615/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0618/sys/src/9/bitsy/devpcmcia.c
433a
	pcmciapower,
.
358a
		sp->dev = devtab[dtx];
print("pcmctlwrite: configure %s: 0x%p\n", cmd->f[1], sp->dev);
.
143c
	/* set timing to the default, 300 */
	slottiming(0, 300, 300, 300, 0);
	slottiming(1, 300, 300, 300, 0);

	/* if there's no pcmcia sleave, no interrupts */
	if(gpioregs->level & GPIO_OPT_IND_i)
		return;

	/* sleave there, interrupt on card removal */
	intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
	intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
.
129a
		for (sp = slot; sp < slot + nslot; sp++){
			if (sp->occupied == 0)
				continue;
			if (sp->dev){
print("pcmciapower: dev 0x%p", sp->dev);
print(", power 0x%p\n", sp->dev->power);
				if (sp->dev->power)
					sp->dev->power(on);
			}
		}
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
.
126,128c
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
		delay(200);
		egpiobits(EGPIO_pcmcia_reset, 1);
		delay(100);
		egpiobits(EGPIO_pcmcia_reset, 0);
		delay(500);

		slotinfo(nil, nil);	// See what's there
		for (sp = slot; sp < slot + nslot; sp++){
			if (sp->occupied == 0)
				continue;
			if(sp->cisread == 0)
				pcmcisread(sp);
			if (sp->dev){
print("pcmciapower: dev 0x%p", sp->dev);
print(", power 0x%p\n", sp->dev->power);
				if (sp->dev->power)
					sp->dev->power(on);
			}
		}
.
117c
	if (on){
.
113a
	PCMslot *sp;

.
111,112c
void
pcmciapower(int on)
.
## diffname bitsy/devpcmcia.c 2002/0619
## diff -e /n/emeliedump/2002/0618/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0619/sys/src/9/bitsy/devpcmcia.c
400,401d
153,154d
142,145c
//				if (sp->dev->power)
//					sp->dev->power(on);
.
## diffname bitsy/devpcmcia.c 2002/0626
## diff -e /n/emeliedump/2002/0619/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0626/sys/src/9/bitsy/devpcmcia.c
540c
 *  the regions are staticly mapped
.
536a
	}
.
535c
	if(decref(&pcmcia) == 0){
iprint("increfp power down\n");
.
533a
iprint("decrefp %ld\n", sp - slot);
.
513a
iprint("increfp full power\n");
.
512a
iprint("increfp %ld\n", sp - slot);
.
450a
/*
 * power up/down pcmcia
 */
void
pcmciapower(int on)
{
	PCMslot *sp;

	/* if there's no pcmcia sleave, no interrupts */
iprint("pcmciapower %d\n", on);

	if (on){
		/* set timing to the default, 300 */
		slottiming(0, 300, 300, 300, 0);
		slottiming(1, 300, 300, 300, 0);

		/* if there's no pcmcia sleave, no interrupts */
		if(gpioregs->level & GPIO_OPT_IND_i){
			iprint("pcmciapower: no sleeve\n");
			return;
		}

		for (sp = slot; sp < slot + nslot; sp++){
			if (sp->dev){
				increfp(sp);
				iprint("pcmciapower: %s\n", sp->verstr);
				if (sp->dev->power)
					sp->dev->power(on);
			}
		}
	}else{
		if(gpioregs->level & GPIO_OPT_IND_i){
			iprint("pcmciapower: no sleeve\n");
			return;
		}

		for (sp = slot; sp < slot + nslot; sp++){
			if (sp->dev){
				if (sp->dev->power)
					sp->dev->power(on);
				decrefp(sp);
			}
			sp->occupied = 0;
			sp->cisread = 0;
		}
		egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
	}
}

.
109,159d
## diffname bitsy/devpcmcia.c 2002/0702
## diff -e /n/emeliedump/2002/0626/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0702/sys/src/9/bitsy/devpcmcia.c
425a
				delay(10000);
.
## diffname bitsy/devpcmcia.c 2002/0703
## diff -e /n/emeliedump/2002/0702/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/0703/sys/src/9/bitsy/devpcmcia.c
341c
		cf.irq = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
## diffname bitsy/devpcmcia.c 2002/1112
## diff -e /n/emeliedump/2002/0703/sys/src/9/bitsy/devpcmcia.c /n/emeliedump/2002/1112/sys/src/9/bitsy/devpcmcia.c
630a
}

/* For compat with ../pc devices. Don't use it for the bitsy 
 */
int
pcmspecial(char*, ISAConf*)
{
	return -1;
.
498a
		if (inserted(nil))
			wakeup(&pcmcia.event);
.
496a
			}
.
495c
			if(slot[1].occupied == 0){
				slot[1].inserted = 1;
.
492c
			slot[1].occupied = slot[1].inserted = 0;
.
488a
			}
.
487c
			if(slot[0].occupied == 0){
				slot[0].inserted = 1;
.
484c
			slot[0].occupied = slot[0].inserted = 0;
.
480,481c
		slot[0].occupied = slot[0].inserted = 0;
		slot[1].occupied = slot[1].inserted = 0;
.
390a
	case Qevs:
		break;
.
341c
		cf.intnum = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
.
339c
		cf.ports = &port;
		cf.ports[0].port = (ulong)sp->regs;
		cf.ports[0].size = 0;
		cf.nports = 1;
.
296a
	port_t port;
.
263a
	case Qevs:
		return pcmevsread(a, n, offset);
.
245a
pcmevsread(void *a, long n, ulong off)
{
	int i;
	char *buf = nil;
	char *e;

	if (pcmcia.evreader)
		error("At most one reader");
	off = 0;
	pcmcia.evreader++;
	if (waserror()){
		free(buf);
		pcmcia.evreader--;
		nexterror();
	}
	while((i = inserted(nil)) == 0){
		slotinfo(nil, nil);
		tsleep(&pcmcia.event, inserted, nil, 500);
	}
	pcmcia.evreader--;
	slot[i-1].inserted = 0;
	buf = malloc(READSTR);
	e = buf + READSTR;
	buf[0] = 0;
	seprint(buf, e, "#y/pcm%dctl\n", i-1);
	n = readstr(off, a, n, buf);
	free(buf);
	poperror();
	return n;
}

static long
.
244a
static int
inserted(void *)
{
	if (slot[0].inserted)
		return 1;
	if (slot[1].inserted)
		return 2;
	return 0;
}

.
90a
found:
.
70a
	if(i == Nents*nslot){
		len = 0;
		qid.path = PATH(0, Qevs);
		snprint(up->genbuf, sizeof up->genbuf, "pcmevs");
		goto found;
	}
.
69c
	if(i >= Nents*nslot + 1)
.
21a
	Qevs,
.
13a
	Rendez	event;		// where to wait for card events
	int	evreader;	// there's a reader for events
.
8a
/*
 * BUG: insertion events are detected by polling.
 *      Should look into the compaq docs to see if
 *      there's an interrupt for card insertion
 *      there's probably one.
 */

.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].