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

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


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

#include	"devtab.h"
#include	"../port/netif.h"

/*
 *  Stargate's Avanstar serial board.  There are ISA, EISA, microchannel versions.
 *  At the moment we only handle the ISA one.
 */
typedef struct Astar Astar;
typedef struct Astarport Astarchan;

enum
{
	/* ISA control ports */
	ISAid=		0,		/* Id port and its values */
	 ISAid0=	 0xEC,
	 ISAid1=	 0x13,
	ISActl1=	1,		/* board control */
	 ISAien=	 1<<7,		/*  interrupt enable */
	 ISAirqm=	 4,		/*  shift for 3 bit irq code */
	 ISAdl=		 1<<1,		/*  download bit (1 == download) */
	 ISApr=		 1<<0,		/*  program ready */
	ISActl2=	2,		/* board control */
	 ISA186ien=	 1<<7,		/*  I186 irq enable bit state */
	 ISA186idata=	 1<<6,		/*  I186 irq data bit state */
	 ISAmemen=	 1<<4,		/*  enable memory to respond to ISA cycles */
	 ISAmembank=	 0,		/*  shift for 4 bit memory bank */
	ISAmemaddr=	3,		/* bits 14-19 of the boards mem address */
	ISAstat1=	4,		/* board status (1 bit per channel) */
	ISAstat2=	5,		/* board status (1 bit per channel) */
};

/* control program global control block */
typedef struct GCB GCB;
struct GCB
{
	ushort	cmd;		/* command word */
	ushort	status;		/* status word */
	ushort	serv;		/* service request, must be accessed via exchange 'X' */
	ushort	avail;		/* available buffer space */
	ushort	type;		/* board type */
	ushort	cpvers;		/* control program version */
	ushort	ccbc;		/* control channel block count */
	ushort	ccbo;		/* control channel block offset */
	ushort	ccbc;		/* control channel block size */
	ushort	cmd2;		/* command word 2 */
	ushort	status2;	/* status word 2 */
	ushort	errserv;	/* comm error service request 'X' */
	ushort	inserv;		/* input buffer service request 'X' */
	ushort	outserv;	/* output buffer service request 'X' */
	ushort	modemserv;	/* modem change service request 'X' */
	ushort	cmdserv;	/* channel command service request 'X' */
};

/* control program channel control block */
typedef struct CCB CCB;
struct CCB
{
	ushort	baud;		/* baud rate */
	ushort	format;		/* data format */
	ushort	line;		/* line protocol */
	ushort	insize;		/* input buffer size */
	ushort	outsize;	/* output buffer size */
	ushort 	intrigger;	/* input buffer trigger rate */
	ushort	outlow;		/* output buffer low water mark */
	ushort	xon;		/* xon characters */
	ushort	inhigh;		/* input buffer high water mark */
	ushort	inlow;		/* input buffer low water mark */
	ushort	cmd;		/* channel command */
	ushort	status;		/* channel status */
	ushort	inbase;		/* input buffer start addr */
	ushort 	inlim;		/* input buffer ending addr */
	ushort	outbase;	/* output buffer start addr */
	ushort 	outlim;		/* output buffer ending addr */
	ushort	inwp;		/* input read and write pointers */
	ushort	inrp;
	ushort	outwp;		/* output read and write pointers */
	ushort	outrp;
	ushort	errstat;	/* error status */
	ushort	badp;		/* bad character pointer */
	ushort	mctl;		/* modem control */
	ushort	mstat;		/* modem status */
	ushort	bstat;		/* blocking status */
	ushort	rflag;		/* character received flag */
	ushort	xoff;		/* xoff characters */
	ushort	status2;
	uchort	strip;		/* strip/error characters */
};

/* host per controller info */
struct Astar
{
	int		port;		/* number of first port */
	GCB		*gbc;		/* board comm area */
	Astarchan	*c;		/* channels */
};

/* host per channel info */
struct Astarchan
{
	QLock;

	/* buffers */
	int	(*putc)(Queue*, int);
	Queue	*iq;
	Queue	*oq;


	/* staging areas to avoid some of the per character costs */
	uchar	istage[Stagesize];
	uchar	*ip;
	uchar	*ie;

	uchar	ostage[Stagesize];
	uchar	*op;
	uchar	*oe;
};

/*
 *  Stargate's Avanstar serial port cards.  Currently only the ISA version
 *  is supported.
 */
void
avanstarreset(void)
{
	int i;
	Dirtab *dp;

	for(i = 0; i < Maxcard; i++){
		sc = scard[i] = xalloc(sizeof(Scard));
		if(isaconfig("serial", i, sc) == 0){
			xfree(sc);
			break;
		}

	ndir = 3*nuart;
	ns16552dir = xalloc(ndir * sizeof(Dirtab));
	dp = ns16552dir;
	for(i = 0; i < nuart; i++){
		/* 3 directory entries per port */
		sprint(dp->name, "eia%d", i);
		dp->qid.path = NETQID(i, Ndataqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dctl", i);
		dp->qid.path = NETQID(i, Nctlqid);
		dp->perm = 0660;
		dp++;
		sprint(dp->name, "eia%dstat", i);
		dp->qid.path = NETQID(i, Nstatqid);
		dp->perm = 0444;
		dp++;
	}
}
.
## diffname pc/devastar.c 1994/1107
## diff -e /n/fornaxdump/1994/1106/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1107/sys/src/brazil/pc/devastar.c
160a
}

void
astarinit(void)
{
}

int isaport[] =
	{ 0x200, 0x208, 0x300, 0x308, 0x600, 0x608, 0x700, 0x708, 0 };

int
isax00i(int port)
{
	uchar c, c1;

	if(port < 0)
		return 0;

	c = inb(port + ISAid);
	c1 = inb(port + ISAid);
	return (c == ISAid0 && c1 == ISAid1)
		|| (c == ISAid1 && c1 == ISAid0));
}

int
astarsetup(Astar *a)
{
	int i, j, found;

	/* see if the card exists */
	found = 0;
	if(a->port == 0)
		for(i = 0; isaport[i]; i++){
			a->port = isaport[i];
			found = isax00i(isaport[i]);
			if(found){
				isaport[i] = -1;
				break;
			}
		}
	else
		found = isax00i(a->port);
	if(!found){
		print("avanstar %d not found\n", a->id);
		return -1;
	}

	/* set memory address */
	outb(a->port + ISAmaddr, (a->mem>>12) & 0xfc);
	a->gcb = KZERO | a->mem;

	/* set interrupt level */
	if(isairqcode(a->irq) == -1){
		print("Avanstar %d bad irq %d\n", a->id, a->irq);
		return -1;
	}
	c = inb(a->port + ISActl1) & ~ISAirq;
	outb(a->port + ISActl1, c | isairqcode(a->irq));
.
142a
		if(strcmp(a->type, "a100i") == 0 || strcmp(a->type,"A100I") == 0)
			a->ramsize = 16*1024;
		else if(strcmp(a->type, "a200i") == 0 || strcmp(a->type,"A200I") == 0)
			a->ramsize = 256*1024;
		else
			continue;
		if(a->mem == 0)
			a->mem = 0xD0000;
		if(a->irq == 0)
			a->irq = 15;
		a->id = i;

		if(astarsetup(a) < 0){
			xfree(a);
			astar[i] = 0;
			continue;
		}
	}

.
137,139c
		a = astar[i] = xalloc(sizeof(Astar));
		if(isaconfig("serial", i, &a) == 0){
			xfree(a);
			astar[i] = 0;
.
133a
	Astar *a;
.
131c
astarreset(void)
.
126,129c
Astar *a[Maxcard];

int astarsetup(Astar*);

.
111c

.
109a
	CCB	*ccb;	/* control block */

.
100c
	ISAConf;
	int		id;		/* from plan9.ini */
	int		ramsize;	/* 16k or 256k */
.
96a
enum
{
	/* special baud rate codes for CCB.baud */
	Cb76800=	0xff00,
	Cb115200=	0xff01,

	/* CCB.format fields */
	C5bit=		0<<0,	/* data bits */
	C6bit=		0<<1,
	C7bit=		0<<2,
	C8bit=		0<<3,
	C1stop=		0<<2,	/* stop bits */
	C2stop=		1<<2,
	Cnopar=		0<<3,	/* parity */
	Coddpar=	1<<3,
	Cevenpar=	3<<3,
	Cmarkpar=	5<<3,
	Cspacepar=	7<<3,
	Cnormal=	0<<6,	/* normal mode */
	Cecho=		1<<6,	/* echo mode */
	Clloop=		2<<6,	/* local loopback */
	Crloop=		3<<6,	/* remote loopback */

	/* CCB.proto fields */
	Cobeyxon=	1<<0,	/* obey received xoff/xon controls */
	Canyxon=	1<<1,	/* any rcvd character restarts xmit */
	Cgenxon=	1<<2,	/* generate xoff/xon controls */
	Cobeycts=	1<<3,	/* obey hardware flow ctl */
	Cgendtr=	1<<4,	/* dtr off when uart rcvr full */
	C½duplex=	1<<5,	/* rts off while xmitting */
	Cgenrts=	1<<6,	/* generate hardware flow ctl */
	Cmctl=		1<<7,	/* direct modem control via CCB.mctl */
	Cstrip=		1<<12,	/* to strip out characters */
	Ceia422=	1<<13,	/* to select eia 422 lines */

	/* CCB.cmd fields */
	Cconfall=	1<<0,	/* configure channel and UART */
	Cconfchan=	1<<1,	/* configure just channel */
	Cflushin=	1<<2,	/* flush input buffer */
	Cflushout=	1<<3,	/* flush output buffer */
	Crcvena=	1<<4,	/* enable receiver */
	Crcvdis=	1<<5,	/* disable receiver */
	Cxmtena=	1<<6,	/* enable transmitter */
	Cxmtdis=	1<<7,	/* disable transmitter */
	Cmreset=	1<<9,	/* reset modem */

	/* CCB.errstat fields */
	Coverrun=	1<<0,
	Cparity=	1<<1,
	Cframing=	1<<2,
	Cbreak=		1<<3,

	/* CCB.mctl fields */
	Cdtrctl=	1<<0,
	Crtsctl=	1<<1,
	Cbreakctl=	1<<4


	/* CCB.mstat fields */
	Cctsstat=	1<<0,
	Cdsrstat=	1<<1,
	Cristat=	1<<2,
	Cdcdstat=	1<<3,

	/* CCB.bstat fields */
	Cbrcvoff=	1<<0,
	Cbxmtoff=	1<<1,
	Clbxoff=	1<<2,	/* transmitter blocked by XOFF */
	Clbcts=		1<<3,	/* transmitter blocked by CTS */
	Crbxoff=	1<<4,	/* remote blocked by xoff */
	Crbrts=		1<<4,	/* remote blocked by rts */
};

.
94c
	char	strip[2];	/* strip/error characters */
.
92c
	char	xoff[2];	/* xoff characters */
.
73c
	char	xon[2];		/* xon characters */
.
68c
	ushort	proto;		/* line protocol */
.
61a
enum
{
	/* GCB.cmd commands/codes */
	Greadycmd=	0,
	Gdiagcmd=	1,
	Gresetcmd=	2,

	/* GCB.status values */
	Gready=		0,
	Gstopped=	1,
	Gramerr=	2,
	Gbadcmd=	3,
	Gbusy=		4,

	/* GCB.type values */
	Gx00m=		0x6,
	G100e=		0xA,
	Gx00i=		0xC,

	/* GCB.status2 bits */
	Ghas232=	(1<<0),
	Ghas422=	(1<<1),
	Ghasmodems=	(1<<2),
	Ghasrj11s=	(1<<7),
	Ghasring=	(1<<8),
	Ghasdcd=	(1<<9),
	Ghasdtr=	(1<<10),
	Ghasdsr=	(1<<11),
	Ghascts=	(1<<12),
	Ghasrts=	(1<<13),
};

.
39a
/* IRQ codes */
static int isairqcode[16] =
{
	-1,	-1,	-1,	0<<4,
	1<<4,	2<<4,	-1,	-1,
	-1,	3<<4,	4<<4,	5<<4,
	6<<4,	-1,	-1,	7<<4,
};

.
37a

	Maxcards=	3,
.
33,35c
	 ISAmen=	 1<<4,		/*  enable memory to respond to ISA cycles */
	 ISAmbank=	 0,		/*  shift for 4 bit memory bank */
	ISAmaddr=	3,		/* bits 14-19 of the boards mem address */
.
27c
	 ISAirq=	 7<<4,		/*  mask for irq code */
.
17c
typedef struct Astarchan Astarchan;
.
13,14c
 *  Stargate's Avanstar serial board.  There are ISA, EISA, microchannel
 *  versions.  We only handle the ISA one.
.
## diffname pc/devastar.c 1994/1108
## diff -e /n/fornaxdump/1994/1107/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1108/sys/src/brazil/pc/devastar.c
272c
			a->mem = 0xD4000;
.
270a

.
231d
## diffname pc/devastar.c 1994/1109
## diff -e /n/fornaxdump/1994/1108/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1109/sys/src/brazil/pc/devastar.c
359a

	return 0;
.
336c
			found = astarprobe(isaport[i]);
.
326c
static int
.
312,313c
static int
astarprobe(int port)
.
309,310c
/* isa ports an ax00i can appear at */
int isaport[] = { 0x200, 0x208, 0x300, 0x308, 0x600, 0x608, 0x700, 0x708, 0 };
.
281a
		nastar++;
.
279c
			astar[nastar] = 0;
.
260c
			astar[nastar] = 0;
.
257c
		a = astar[nastar] = xalloc(sizeof(Astar));
.
247c
static int astarsetup(Astar*);
.
245c
Astar *astar[Maxcard];
int nastar;
.
227a
	Astar	*a;	/* controller */
.
## diffname pc/devastar.c 1994/1111
## diff -e /n/fornaxdump/1994/1109/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1111/sys/src/brazil/pc/devastar.c
362a

	return 0;
}

void
astarinit(void)
{
}

Chan*
astarattach(char *spec)
{
	return devattach('g', spec);
}

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

int
astarwalk(Chan *c, char *name)
{
	return devwalk(c, name, 0, 0, astargen);
}

void
astarstat(Chan *c, char *dp)
{
	devstat(c, dp, 0, 0, astargen);
}

Chan*
astaropen(Chan *c, int omode)
{
	Uart *p;

	c = devopen(c, omode, 0, 0, astargen);

	return c;
}

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

void
astarclose(Chan *c)
{
	USED(c);
}

long
astarread(Chan *c, void *buf, long n, ulong offset)
{
	Astar *a;

	if(c->qid.path & CHDIR)
		return devdirread(c, buf, n, 0, 0, astargen);

	switch(TYPE(c->qid.path)){
	case Qmem:
		a = astar[
		return qread(p->iq, buf, n);
	}

	return 0;
}

long
astarwrite(Chan *c, void *buf, long n, ulong offset)
{
	Uart *p;

	if(c->qid.path & CHDIR)
		error(Eperm);

	switch(TYPE(c->qid.path)){
	case Qmem:
		return qread(p->iq, buf, n);
	}
.
307,311d
286,304d
250a
int
devgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *db)
{
	int dev, sofar, ch, t;

	USED(tab, ntab);
	sofar = 0;

	for(dev = 0; dev < nstar; dev++){
		if(sofar == i){
			sprint(db->name, "atar%dmem", astar[dev].id);
			db->qid = QID(dev, 0, Qmem);
			db->mode = 0660;
			break;
		}

		if(i < sofar + 3*astar[dev].nchan){
			i -= sofar;
			ch = i/3;
			t = i%3;
			switch(t){
			case 0:
				sprint(db->name, "eia%d%2.2d", dev, ch);
				db->mode = astar[dev]->c[ch].perm;
				db->qid = QID(dev, 0, Qdata);
				break;
			case 1:
				sprint(db->name, "eia%d%2.2dctl", dev, ch);
				db->mode = astar[dev]->c[ch].perm;
				db->qid = QID(dev, 0, Qctl);
				break;
			case 2:
				sprint(db->name, "eia%d%2.2dstat", dev, ch);
				db->mode = 0444;
				db->qid = QID(dev, 0, Qstat);
				break;
			break;
		}

		sofar += 1 + 3*astar[dev].nchan;
	}

	if(j == nstar)
		return -1;

	db->atime = seconds();
	db->mtime = kerndate;
	db->hlength = 0;
	db->length = length;
	memmove(db->uid, eve, NAMELEN);
	memmove(db->gid, eve, NAMELEN);
	db->type = devchar[c->type];
	db->dev = c->dev;
	if(c->flag&CMSG)
		db->mode |= CHMOUNT;

	return 1;
}

.
248a
enum
{
	Qmem=	0,
	Qdata,
	Qctl,
	Qstat,
};
#define TYPE(x)		((x)&0xff)
#define BOARD(x)	((((x)&~CHDIR)>>16)&0xff)
#define CHAN(x)		((((x)&~CHDIR)>>8)&0xff)
#define QID(b,c,t)	(((b)<<16)|((c)<<8)|(t))

.
247c
static int nastar;
.
234,243d
229a
	int	perm;
.
220d
217a
	int		nchan;		/* number of channels */
	Astarchan	*c;		/* channels */
.
10d
## diffname pc/devastar.c 1994/1112
## diff -e /n/fornaxdump/1994/1111/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1112/sys/src/brazil/pc/devastar.c
487a
}

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

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

void
astarwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
.
484c
		a = astar[BOARD(c->qid.path)];
		if(offset+n > Pramsize){
			if(offset >= Pramsize)
				return 0;
			n = Pramsize - offset;
		}

		if(waserror()){
			qunlock(a);
			nexterror();
		}
		qlock(a);
		to = buf;
		while(n > 0){
			/* map in right piece of memory */
			outb(a->port + ISActl2, ISAmen|(offset>>Footshift));
			i = offset%Footprint;
			from = a->addr + i;
			i = Footprint - i;
			if(i > n)
				i = n;
			
			/* byte at a time so endian doesn't matter */
			for(e = from + i; from < e;)
				*to++ = *from++;

			n -= i;
		}
		qunlock(a);
		poperror();
		break;
	case Qbctl:
		if(n > sizeof cmsg)
			n = sizeof(cmsg) - 1;
		memmove(cmsg, buf, n);
		cmsg[n] = 0;

		if(waserror()){
			qunlock(a);
			nexterror();
		}
		qlock(a);
		if(strncmp(cmsg, "download", 8) == 0){
			/* put board in download mode */
			outb(a->port + ISActl1, ISAdl);

			/* enable ISA access to first 16k */
			outb(a->port + ISActl2, ISAmen);

		} else if(strncmp(cmsg, "run", 3) == 0){
			/* take board out of download mode and enable IRQ */
			outb(a->port + ISActl1, ISAien|isairqcode[a->irq]);

			/* enable ISA access to first 16k */
			outb(a->port + ISActl2, ISAmen);

			/* wait for control program to signal life */
			for(i = 0; i < 21; i++){
				if(inb(a->port + ISActl1) & ISApr)
					break;
				tsleep(&a->r, return0, 0, 500);
			}
			if((inb(a->port + ISActl1) & ISApr) == 0)
				print("astar%d program not ready\n", a->id);

		} else
			error(Ebadarg);
		qunlock(a);
		poperror();
		break;
.
477c
	Astar *a;
	char *to, *from, *e;
	int i;
	char cmsg[32];
.
467,468c
		a = astar[BOARD(c->qid.path)];
		if(offset+n > Pramsize){
			if(offset >= Pramsize)
				return 0;
			n = Pramsize - offset;
		}

		if(waserror()){
			qunlock(a);
			nexterror();
		}
		qlock(a);
		from = buf;
		while(n > 0){
			/* map in right piece of memory */
			outb(a->port + ISActl2, ISAmen|(offset>>Footshift));
			i = offset%Footprint;
			to = a->addr + i;
			i = Footprint - i;
			if(i > n)
				i = n;
			
			/* byte at a time so endian doesn't matter */
			for(e = from + i; from < e;)
				*to++ = *from++;

			n -= i;
		}
		qunlock(a);
		poperror();
		break;
	case Qbctl:
		a = astar[BOARD(c->qid.path)];
		sprint(status, "id %2.2ux%2.2ux ctl1 %2.2ux ctl2 %2.2ux maddr %2.2ux stat %2.2ux%2.2ux",
			inb(a->port+ISAid), inb(a->port+ISAid),
			inb(a->port+ISActl1), inb(a->port+ISActl2), 
			inb(a->port+ISAmaddr),
			inb(a->port+ISAstat2), inb(a->port+ISAstat1));
		n = readstr(offset, buf, n, status);
		break;
.
460a
	char *to, *from, *e;
	char status[128];
.
459a
	int i;
.
454c
	Astar *a;
	int i;

	switch(TYPE(c->qid.path)){
	case Qmem:
		a = astar[BOARD(c->qid.path)];
		qlock(a);
		if(--a->opens == 0){
			/* take board out of download mode and enable IRQ */
			outb(a->port + ISActl1, ISAien|isairqcode[a->irq]);

			/* enable ISA access to first 16k */
			outb(a->port + ISActl2, ISAmen|0);

			/* wait for program ready */
			for(i = 0; i < 21; i++){
				if(inb(a->port + ISActl1) & ISApr)
					break;
				tsleep(&r, return0, 0, 500);
			}
			if((inb(a->port + ISActl1) & ISApr) == 0)
				print("astar%d program not ready\n", a->id);
		}
		qunlock(a);
		break;
	}
.
445,451d
440a
	switch(TYPE(c->qid.path)){
	case Qmem:
	case Qbctl:
		if(!iseve())
			error(Eperm);
		break;
	}

.
437c
	Astar *a;
.
399,400d
395c
	if(isairqcode[a->irq] == -1){
.
392c
	a->gbc = (GCB*)(KZERO | a->mem);
	a->addr = (char*)(KZERO | a->mem);
.
384c
		found = astarprobe(a->port);
.
370c
	int i, found;
.
364c
		|| (c == ISAid1 && c1 == ISAid0);
.
345a
		print("serial%d avanstar addr %lux irq %d\n", i, a->addr, a->irq);
.
322c
		if(isaconfig("serial", i, a) == 0){
.
318d
302c
	db->length = 0;				/* update ???? */
.
296c
	if(dev == nastar)
.
292,293c
		sofar += 3*astar[dev]->nchan;
.
289a
			}
.
288c
				db->qid.path = QID(dev, 0, Qstat);
.
283c
				db->qid.path = QID(dev, 0, Qctl);
.
278c
				db->qid.path = QID(dev, 0, Qdata);
.
270c
		if(sofar == i){
			sprint(db->name, "atar%dctl", astar[dev]->id);
			db->qid.path = QID(dev, 0, Qbctl);
			db->mode = 0660;
			break;
		}
		sofar++;

		if(i - sofar < 3*astar[dev]->nchan){
.
268a
		sofar++;
.
264,265c
			sprint(db->name, "atar%dmem", astar[dev]->id);
			db->qid.path = QID(dev, 0, Qmem);
.
262c
	for(dev = 0; dev < nastar; dev++){
.
257a
	extern ulong kerndate;
.
255c
astargen(Chan *c, Dirtab *tab, int ntab, int i, Dir *db)
.
242a
	Qbctl,
.
230a
	int	opens;
.
220a
	char		*addr;		/* memory area */
.
217a
	Rendez		r;
.
214a
	QLock;

.
194c
	Cbreakctl=	1<<4,
.
38c
	Maxcard=	8,
	Pramsize=	64*1024,	/* size of program ram */
	Footshift=	14,		/* footprint of card mem in ISA space */
	Footprint=	1<<Footshift,
.
## diffname pc/devastar.c 1994/1113
## diff -e /n/fornaxdump/1994/1112/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1113/sys/src/brazil/pc/devastar.c
666a

.
608,641c
		return bctlwrite(a, cmsg);
	case Qdata:
		ac = a->c + CHAN(c->qid.path);
		return qwrite(ac->oq, buf, n);
	case Qctl:
		if(n > sizeof cmsg)
			n = sizeof(cmsg) - 1;
		memmove(cmsg, buf, n);
		cmsg[n] = 0;
		return astarctl(a, msg);
.
572,602c
		return memwrite(a, buf, n, offset);
.
569a
	a = astar[BOARD(c->qid.path)];
.
563,564c
	Astarchan *ac;
.
558a

.
555,556d
553a
	case 'f':
	case 'F':
		qflush(ac->oq);
		break;
	case 'H':
	case 'h':
		qhangup(ac->iq);
		qhangup(ac->oq);
		break;
	case 'L':
	case 'l':
		n -= 5;
		if(n < 0 || n > 3)
			error(Ebadarg);
		n |= LEUS(ac->ccb->format) & ~Clenmask;
		ac->ccb->format = LEUS(n);
		command = Cconfall;
		break;
	case 'm':
	case 'M':
		n = LEUS(ac->ccb->format) | Cobeycts;
		ac->ccb->proto = LEUS(n);
		command = Cconfall;
		break;
	case 'n':
	case 'N':
		qnoblock(p->oq, n);
		break;
	case 'P':
	case 'p':
		switch(*(cmd+1)){
		case 'e':
			n = Cevenpar;
			break;
		case 'o':
			n = Coddpar;
			break;
		default:
			n = Cnopar;
			break;
		}
		n |= LEUS(ac->ccb->format) & ~Cparmask;
		ac->ccb->format = LEUS(n);
		command = Cconfall;
		break;
	case 'K':
	case 'k':
		break;
	case 'R':
	case 'r':
		break;
	case 'Q':
	case 'q':
		qsetlimit(ac->iq, n);
		qsetlimit(ac->oq, n);
		break;
	case 'X':
	case 'x':
		n = LEUS(ac->ccb->format) | Cobeyxon;
		ac->ccb->proto = LEUS(n);
		command = Cconfall;
		break;
.
545,552c
	case 'D':
	case 'd':
.
543c
		nexterror();
	}
	qlock(a);

	if(strncmp(cmsg, "download", 8) == 0){
		if(a->running)
			error(Eio);

		/* put board in download mode */
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c & ~ISAnotdl);
		a->memsize = Pramsize;

		/* enable ISA access to first 16k */
		outb(a->port+ISActl2, ISAmen);

	} else if(strncmp(cmsg, "run", 3) == 0){
		if(a->running)
			error(Eio);
		startcp(a);

	} else
		error(Ebadarg);

	qunlock(a);
	poperror();
	return n;
}

/*
 *  change channel parameters
 */
void
astarctl(Astarchan *ac, char *cmd)
{
	int i, n;
	int command;

	/* let output drain for a while */
	for(i = 0; i < 16 && qlen(ac->oq); i++)
		tsleep(&ac->r, qlen, ac->oq, 125);

	if(strncmp(cmd, "break", 5) == 0)
		cmd = "k";

	command = 0;
	n = atoi(cmd+1);
	switch(*cmd){
	case 'B':
	case 'b':
		switch(n){
		case 76800:
			ac->ccb->baud = LEUS(Cb76800);
			break;
		case 115200:
			ac->ccb->baud = LEUS(Cb115200);
			break;
		default:
			ac->ccb->baud = LEUS(n);
			break;
		}
		command = Cconfall;
.
541a
	}

	/* setup the channels */
	a->running = 1;
	a->nchan = i;
	a->c = xalloc(a->nchan * sizeof(Astarchan));
	for(i = 0; i < a->nchan; i++){
		chansetup(a, &a->c[i], (CCB*)x);
		x += sz;
	}
}

static long
bctlwrite(Astar *a, char *msg)
{
	int i;
	uchar c;

	if(waserror()){
.
540c
static long
memwrite(Astar *a, uchar *from, long n, ulong offset)
{
	uchar *to, *e;
	int i, rem;

	if(offset+n > a->memsize){
		if(offset >= a->memsize)
			return 0;
		n = a->memsize - offset;
	}

	if(waserror()){
		qunlock(a);
		nexterror();
	}
	qlock(a);

	for(rem = n; rem > 0; rem -= i){

		/* map in right piece of memory */
		setpage(a, offset);
		i = offset&Pagemask;
		from = a->addr + i;
		i = Pagesize - i;
		if(i > rem)
			i = rem;
		
		/* byte at a time so endian doesn't matter */
		for(e = from + i; from < e;)
			*to++ = *from++;
	}

	qunlock(a);
	poperror();
	return n;
}

/*
 *  setup a channel
 */
static void
chansetup(Astar *a, Astarchan *ac, void *ccb)
{
	ac->a = a;
	ac->ccb = ccb;
	ac->iq = qopen(4*1024, 0, 0, 0);
	ac->oq = qopen(4*1024, 0, astarkick, p);
}

/*
 *  start control progarm
 */
static void
startcp(Astar *a)
{
	int n, i, sz;
	uchar *x;
	CCB *ccb;

	if(a->running)
		error(Eio);

	/* take board out of download mode and enable IRQ */
	outb(a->port+ISActl1, ISAien|isairqcode[a->irq]|ISAnotdl);
	a->memsize = a->ramsize;

	/* wait for control program to signal life */
	for(i = 0; i < 21; i++){
		if(inb(a->port+ISActl1) & ISApr)
			break;
		tsleep(&a->r, return0, 0, 500);
	}
	if((inb(a->port+ISActl1) & ISApr) == 0){
		print("astar%d program not ready\n", a->id);
		error(Eio);
	}

	setpage(a, 0);
	i = LEUS(a->gcb->type);
	switch(i){
	default:
		print("astar%d wrong board type %ux\n", a->id, i);
		error(Eio);
	case 0xc:
		break;
	}

	/* check assumptions */
	n = LEUS(a->gcb->ccbn);
	if(n != 8 && n != 16){
		print("astar%d had %d channels?\n", a->id, i);
		error(Eio);
	}
	x = a->addr + LEUS(a->gcb->ccboff);
	sz = LEUS(a->gcb->ccbsz);
	if(x+n*sz > a->addr+Pagesize){
		print("astar%d ccb's not in 1st page\n", a->id);
		error(Eio);
	}
	for(i = 0; i < n; i++){
		ccb = (CCB*)(x + i*sz);
		if(APAGE(LEUS(ccb->inbase)) != APAGE(LEUS(ccb->inlim)) ||
		   APAGE(LEUS(ccb->outbase)) != APAGE(LEUS(ccb->outlim))){
			print("astar%d chan buffer spans pages\n", a->id);
			error(Eio);
.
521,538c
	return 0;
}
.
514,519c
		return memread(astar[BOARD(c->qid.path)], buf, n, offset);
	case Qbctl:
		return bctlread(astar[BOARD(c->qid.path)], buf, n, offset);
	}
.
504,507d
500a
static long
memread(Astar *a, uchar *to, long n, ulong offset)
{
	uchar *from, *e;
	int i, rem;

	if(offset+n > a->memsize){
		if(offset >= a->memsize)
			return 0;
		n = a->memsize - offset;
	}

	if(waserror()){
		qunlock(a);
		nexterror();
	}
	qlock(a);

	for(rem = n; rem > 0; rem -= i){

		/* map in right piece of memory */
		setpage(a, offset);
		i = offset&Pagemask;
		to = a->addr + i;
		i = Pagesize - i;
		if(i > rem)
			i = rem;
		
		/* byte at a time so endian doesn't matter */
		for(e = from + i; from < e;)
			*to++ = *from++;
	}

	qunlock(a);
	poperror();
	return n;
}

static long
bctlread(Chan *c, void *buf, long n, ulong offset)
{
	char s[128];

	sprint(s, "id %4.4ux ctl1 %2.2ux ctl2 %2.2ux maddr %2.2ux stat %4.4ux",
		(inb(a->port+ISAid)<<8)|inb(a->port+ISAid),
		inb(a->port+ISActl1), inb(a->port+ISActl2), 
		inb(a->port+ISAmaddr),
		(inb(a->port+ISAstat2)<<8)|inb(a->port+ISAstat1));
	return readstr(offset, buf, n, s);
}

.
493c
			if((inb(a->port+ISActl1) & ISApr) == 0)
.
489c
				if(inb(a->port+ISActl1) & ISApr)
.
485c
			outb(a->port+ISActl2, ISAmen|0);
.
482c
			outb(a->port+ISActl1, ISAien|isairqcode[a->irq]);
.
410c
	outb(a->port+ISAmaddr, (a->mem>>12) & 0xfc);
.
380,381c
	c = inb(port+ISAid);
	c1 = inb(port+ISAid);
.
357a
		a->page = -1;
.
262a
/*
 *  Only 16k maps into ISA space
 */
void
setpage(Astar *a, ulong offset)
{
	int i;

	i = APAGE(offset);
	if(i == a->page)
		return;
	outb(a->port+ISActl2, ISAmen|i);
	a->page = i;
}

/*
 *  generate the astar directory entries
 */
.
242a
	Rendez	r;
.
236c
	CCB	*ccb;	/* channel control block */
.
226,227c
	int		memsize;	/* size of memory currently mapped */
	int		page;		/* page currently mapped */
	GCB		*gbc;		/* global board comm area */
	uchar		*addr;		/* base of memory area */
	int		running;

	Rendez		r;		/* when waiting for board */
.
223d
159a
	Cparmask=	7<<3,
.
149,152c
	Clenmask=	3<<0,	/* data bits */
.
63,65c
	ushort	ccbn;		/* control channel block count */
	ushort	ccboff;		/* control channel block offset */
	ushort	ccbsz;		/* control channel block size */
.
43a
#define APAGE(x) ((x)>>Pageshift)

.
40,41c
	Pageshift=	14,		/* footprint of card mem in ISA space */
	Pagesize=	1<<Pageshift,
	Pagemask=	Pagesize-1,
.
14a
#define LENDIAN 1

/* unsigned short little endian representation */
#ifdef LENDIAN
#define LEUS(x) (x)
#else
#define LEUS(x) ( (((x)<<8)&0xff00) | (((x)>>8)&0xff) )
#endif LENDIAN

.
13a
 *
 *  At the expense of performance, I've tried to be careful about
 *  endian-ness to make this convertable to other ISA bus machines.
 *  However, xchngus() is in assembler and will have to be translated.
.
## diffname pc/devastar.c 1994/1114
## diff -e /n/fornaxdump/1994/1113/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1114/sys/src/brazil/pc/devastar.c
920a
/*
 *  get output going
 */
static void
astarkick1(Astarchan *ac)
{
	Astar *a = ac->a;
	CCB *ccb = a->ccb;
	uchar tmp[256];
	int n;

	for(;;){
		setpage(a, 0);
	}
}
static void
astarkick(Astarchan *ac)
{
	ilock(&ac->a->pagelock);
	astarkick(ac);
	iunlock(&ac->a->pagelock);
}

/*
 *  handle an interrupt
 */
static void
astarintr(Ureg *ur, void *arg)
{
	Astar *a = arg;
	Astarchan *ac;
	ulong vec, invec, outvec, errvec, mvec, cmdvec;
	int i;

	USED(ur);
	lock(&a->pagelock);
	setpage(a, 0);

	/* get causes */
	invec = LEUS(xchgw(&a->gcb->inserv, 0));
	outvec = LEUS(xchgw(&a->gcb->outserv, 0));
	errvec = LEUS(xchgw(&a->gcb->errserv, 0));
	mvec = LEUS(xchgw(&a->gcb->modemserv, 0));
	cmdvec = LEUS(xchgw(&a->gcb->cmdserv, 0));

	/* reenable interrupts */
	a->cmd2 = LEUS(Gintack);

	/* service interrupts */
	ac = a->c;
	for(vec = LEUS(xchgw(&a->gcb->inserv, 0)); vec; vec >>= 1){
		if(vec&1){
		}
		setpage(a, 0);
		ac++;
	}
	ac = a->c;
	for(vec = LEUS(xchgw(&a->gcb->outserv, 0)); vec; vec >>= 1){
		if(vec&1)
			astarkick1(ac);
		setpage(a, 0);
		ac++;
	}
	ac = a->c;
	for(vec = LEUS(xchgw(&a->gcb->cmdserv, 0)); vec; vec >>= 1){
		if(vec&1)
			wakeup(&ac->r);
		ac++;
	}
	unlock(&a->pagelock);
}
.
894c

		if(waserror()){
			qunlock(ac);
			nexterror();
		}
		qlock(ac);
		astarctl(ac, msg);
		qunlock(ac);
		poperror();
.
889a
		ac = a->c + CHAN(c->qid.path);
.
865d
862a
	iunlock(&a->pagelock);

	if(command)
		chancmd(ac, command);
.
858,859c
		n = LEUS(ccb->proto);
		if(i)
			n |= Cobeyxon;
		else
			n &= ~Cobeyxon;
		ccb->proto = LEUS(n);
.
849a
		n = LEUS(ccb->mctl);
		if(i)
			 n |= Crtsctl;
		else
			 n &= ~Crtsctl;
		ccb->mctl = LEUS(n);
.
846a
		if(i <= 0)
			i = 250;
		n = LEUS(ccb->mctl) | Cbreakctl;
		ccb->mctl = LEUS(n);
		iunlock(&a->pagelock);

		tsleep(&ac->r, return0, 0, i);

		ilock(&a->pagelock);
		setpage(a, 0);
		n &= ~Cbreakctl;
		ccb->mctl = LEUS(n);
.
841,842c
		n |= LEUS(ccb->format) & ~Cparmask;
		ccb->format = LEUS(n);
.
820,821c
		/* turn on cts */
		n = LEUS(ccb->proto);
		if(i)
			n |= Cobeycts;
		else
			n &= ~Cobeycts;
		ccb->proto = LEUS(n);

		/* set fifo sizes */
		ccb->intrigger = 8;
		ccb->outlow = 32;

.
814,815c
		n |= LEUS(ccb->format) & ~Clenmask;
		ccb->format = LEUS(n);
.
798a
		n = LEUS(ccb->mctl);
		if(i)
			 n |= Cdtrctl;
		else
			 n &= ~Cdtrctl;
		ccb->mctl = LEUS(n);
.
792c
			ccb->baud = LEUS(n);
.
789c
			ccb->baud = LEUS(Cb115200);
.
786c
			ccb->baud = LEUS(Cb76800);
.
784c
		switch(i){
.
780c
	i = atoi(cmd+1);
	a = ac->a;
	ilock(&a->pagelock);
	setpage(a, 0);
.
778a
	ccb = ac->ccb;
.
770a
	CCB *ccb;
	Astar *a;
.
766c
static void
.
764a
 *  (must be called with ac qlocked)
.
763a
 *  Send a command to a channel
 *  (must be called with ac qlocked)
 */
static int
chancmddone(void *arg)
{
	CCB *ccb = arg;
	int x;

	ilock(&ac->a->pagelock);
	setpage(ac->a, 0);
	x = ccb->cmd;
	iunlock(&ac->a->pagelock);

	return x;
}
static void
chancmd(Astarchan *ac, int cmd)
{
	int i;
	CCB *ccb;

	ccb = ac->ccb;

	ilock(&ac->a->pagelock);
	setpage(ac->a, 0);
	ccb->cmd = cmd;
	iunlock(&ac->a->pagelock);

	/* wait outside of lock */
	tsleep(&ac->r, chancmddone, ccb, 1000);

	ilock(&ac->a->pagelock);
	setpage(ac->a, 0);
	if(ccb->cmd){
		print("astar%d cmd didn't terminate\n", ac->a->id);
		error(Eio);
	}
	if(ccb->status){
		print("astar%d cmd status %ux\n", ac->a->id, ccb->status);
		error(Eio);
	}
	iunlock(&ac->a->pagelock);
}

/*
 *  enable a channel for IO, set standard params.
 *  (must be called with ac qlocked)
 */
static void
enable(Astarchan *ac)
{
	Astar qÍ*a = ac->a;
	/* make sure we control RTS, DTR and break */
	ilock(&a->pagelock);
	setpage(a, 0);
	n = LEUS(ac->ccb->proto) | Cmctl;
	ac->ccb->proto = LEUS(n);
	iunlock(&a->pagelock);

	chancmd(ac, Crcvena|Cxmtena|Cflushin|Cflushout|Confall);

	astarctl(ac, "b9600");
	astarctl(ac, "l8");
	astarctl(ac, "p0");
	astarctl(ac, "d1");
	astarctl(ac, "r1");
}

/*
 *  disable a channel for IO
 *  (must be called with ac qlocked)
 */
static void
disable(Astarchan *ac)
{
	astarctl(ac, "d0");
	astarctl(ac, "r0");

	ilock(&ac->a->pagelock);
	setpage(ac->a, 0);
	ccb->intrigger = 8;
	ccb->outlow = 32;
	iunlock(&ac->a->pagelock);

	chancmd(ac, Crcvdis|Cxmtdis|Cflushin|Cflushout|Cconfall);
}

/*
.
721c
		ac = &a->c[i];
		ac->a = a;
		ac->ccb = (CCB*)x;
		ac->iq = qopen(4*1024, 0, 0, 0);
		ac->oq = qopen(4*1024, 0, astarkick, ac);
.
714a
	iunlock(&a->pagelock);
	poperror();
.
684a
	if(waserror()){
		iunlock(&a->pagelock);
		poperror();
	}
	ilock(&a->pagelock);
.
665a
	Astarchan *ac;
.
646,657d
640,641d
637c
			*to++ = *tp++;
		iunlock(&a->pagelock);
		from += i;
.
635c
		/*
		 *  byte at a time so endian doesn't matter,
		 *  go via tmp to avoid pagefaults while ilock'd
		 */
		memmove(tmp, from, i);
		tp = tmp;
		ilock(&a->pagelock);
		setpage(a, offset);
.
633a
		if(i > sizeof tmp)
			i = sizeof tmp;
.
630c
		to = a->addr + i;
.
628d
619,624d
611a
	uchar tmp[256];
.
610c
	uchar *to, *e, *tp;
.
606a
/*
 *  write ISA mapped memory
 */
.
576a
/*
 *  read ISA status
 */
.
572,573d
569c
			*tp++ = *from++;
		iunlock(&a->pagelock);
		memmove(to, tmp, i);
		to += i;
.
566,567c
		if(i > sizeof tmp)
			i = sizeof tmp;

		/*
		 *  byte at a time so endian doesn't matter,
		 *  go via tmp to avoid pagefaults while ilock'd
		 */
		tp = tmp;
		ilock(&a->pagelock);
		setpage(a, offset);
.
562c
		from = a->addr + i;
.
560d
551,556d
543a
	uchar tmp[256];
.
542c
	uchar *from, *e, *tp;
.
538a
/*
 *  read ISA mapped memory
 */
.
534c
		if(--ac->opens == 0)
			disable(ac);
		qunlock(ac);
		poperror();
.
516,532c
		break;
	case Qdata:
	case Qctl:
		qlock(ac);
		if(waserror()){
			qunlock(a);
			nexterror();
.
502a
	case Qdata:
	case Qctl:
		qlock(ac);
		if(waserror()){
			qunlock(a);
			nexterror();
		}
		if(ac->opens++ == 0)
			enable(ac);
		qunlock(ac);
		poperror();
		break;
.
403a

		setvec(Int0vec + a->irq, astarintr, a);
.
285c
static void
.
280c
static int	astarsetup(Astar*);
static void	astarintr(Ureg*, void*);
static void	astarkick(Astarchan*);
static void	enable(Astarchan*);
static void	disable(Astarchan*);
.
261d
258d
251c
	QLock;		/* lock for rendez */
	Rendez	r;	/* waiting for command completion */
.
245d
240d
234a
	Lock		pagelock;	/* lock for setting page */
	int		page;		/* page currently mapped */
.
232c
	QLock;				/* lock for rendez */
	Rendez		r;		/* waiting for command completion */
.
109a
	/* GCB.cmd2 bit */
	Gintack=	0x1,

.
## diffname pc/devastar.c 1994/1115
## diff -e /n/fornaxdump/1994/1114/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1115/sys/src/brazil/pc/devastar.c
1160c
	for(vec = cmdvec; vec; vec >>= 1){
.
1156d
1153c
	for(vec = outvec; vec; vec >>= 1){
.
1146,1149c
	for(vec = invec; vec; vec >>= 1){
		if(vec&1)
			astarinput(ac);
.
1142c
	a->gcb->cmd2 = LEUS(Gintack);
.
1139a
	USED(mvec);
	USED(cmdvec);
	USED(errvec);
.
1128d
1119a
 *  process input
 */
static void
astarinput(Astarchan *ac)
{
	Astar *a = ac->a;
	CCB *ccb = ac->ccb;
	uchar buf[256];
	uchar *rp, *wp, *bp, *ep, *p, *e;
	int n;

	setpage(a, 0);
	ep = a->addr;
	rp = ep + LEUS(ccb->inrp);
	wp = ep + LEUS(ccb->inwp);
	bp = ep + LEUS(ccb->inbase);
	ep = ep + LEUS(ccb->inlim);
	for(;;){
		n = wp - rp;
		if(n == 0)
			break;
		if(n < 0)
			n += ep - bp + 1;
		if(n > sizeof(buf))
			n = sizeof(buf);
		setpage(a, bp - a->addr);
		e = buf + n;
		for(p = buf; p < e;){
			*p++ = *rp++;
			if(rp > ep)
				rp = bp;
		}
		qproduce(ac->iq, buf, n);
	}
	setpage(a, 0);
	ccb->inrp = LEUS(rp - a->addr);
}

/*
.
1115c
	astarkick1(ac);
.
1108a
		ccb->outwp = LEUS(wp - a->addr);
.
1107a
		n = rp - wp - 1;
		if(n < 0)
			n += ep - bp + 1;
		if(n == 0)
			break;
		if(n > sizeof(buf))
			n = sizeof(buf);
		n = qconsume(ac->oq, buf, n);
		if(n <= 0)
			break;
		setpage(a, bp - a->addr);
		e = buf + n;
		for(p = buf; p < e;){
			*wp++ = *p++;
			if(wp > ep)
				wp = bp;
		}
.
1106a
	setpage(a, 0);
	ep = a->addr;
	rp = ep + LEUS(ccb->outrp);
	wp = ep + LEUS(ccb->outwp);
	bp = ep + LEUS(ccb->outbase);
	ep = ep + LEUS(ccb->outlim);
.
1103,1104c
	CCB *ccb = ac->ccb;
	uchar buf[256];
	uchar *rp, *wp, *bp, *ep, *p, *e;
.
1092,1093c
	Dir d;
	Astarchan *ac;

	if(!iseve())
		error(Eperm);
	if(CHDIR & c->qid.path)
		error(Eperm);
	if(TYPE(c->qid.path) != Qdata && TYPE(c->qid.path) != Qctl)
		error(Eperm);
	ac = astar[BOARD(c->qid.path)]->c + CHAN(c->qid.path);

	convM2D(dp, &d);
	d.mode &= 0666;
	ac->perm = d.mode;
.
1067c
		astarctl(ac, cmsg);
.
1051c
		bctlwrite(a, cmsg);
		return n;
.
1012,1013c
		qsetlimit(ac->iq, i);
		qsetlimit(ac->oq, i);
.
967c
		qnoblock(ac->oq, i);
.
961d
942c
		n = i - 5;
.
917c
			ccb->baud = LEUS(i);
.
905a

.
902a

.
874,875c
	ac->ccb->intrigger = 0;
.
859a

	chancmd(ac, Crcvena|Cxmtena|Cconfall);
.
853,854d
851a
	chancmd(ac, Cconfall);
.
850a
	ac->ccb->outlow = 64;
.
845c
	Astar *a = ac->a;
	int n;

.
835d
831,832c
	if(status){
		print("astar%d cmd status %ux\n", ac->a->id, status);
.
827c
	status = ccb->status;
	cmd = ccb->cmd;
	iunlock(&ac->a->pagelock);
	if(cmd){
.
823c
	tsleep(&ac->r, chancmddone, ac, 1000);
.
813a
	int status;
.
812d
807c
	return !x;
.
804c
	x = ac->ccb->cmd;
.
799c
	Astarchan *ac = arg;
.
789d
780,781c
		/* start up downloaded program */
.
778a
	} else if(strncmp(cmsg, "sharedmem", 9) == 0){
		/* map shared memory */
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c | ISAnotdl);
		a->memsize = a->ramsize;

		/* enable ISA access to first 16k */
		outb(a->port+ISActl2, ISAmen);

.
770a
	if(strncmp(cmsg, "download", 8) == 0){
.
767,769c
	if(a->running)
		error(Eio);
.
758d
755,756c
static void
bctlwrite(Astar *a, char *cmsg)
.
752a

	/* reenable interrupts */
	a->gcb->cmd2 = LEUS(Gintack);
.
748a
		ac->perm = 0660;
.
668a

		offset += i;
.
665c
		for(e = tp + i; tp < e;)
.
654,655c
		if(i > sizeof(tmp))
			i = sizeof(tmp);
.
624a
	case Qdata:
		a = astar[BOARD(c->qid.path)];
		ac = a->c + CHAN(c->qid.path);
		return qread(ac->oq, buf, n);
.
615a
	Astar *a;
	Astarchan *ac;
.
601c
bctlread(Astar *a, void *buf, long n, ulong offset)
.
591a

		offset += i;
.
587c
		for(e = tp + i; tp < e;)
.
577,578c
		if(i > sizeof(tmp))
			i = sizeof(tmp);
.
546a
			qclose(ac->iq);
			qclose(ac->oq);
		}
.
545c
		if(--ac->opens == 0){
.
542c
			qunlock(ac);
.
539a
		ac = a->c + CHAN(c->qid.path);
.
534a
	a = astar[BOARD(c->qid.path)];

.
533c
	Astarchan *ac;
.
516c
			qunlock(ac);
.
513a
		ac = a->c + CHAN(c->qid.path);
.
504a
	a = astar[BOARD(c->qid.path)];
.
502a
	Astarchan *ac;
.
478c
	return devattach('G', spec);
.
458,459c
	a->gcb = (GCB*)(KZERO | a->mem);
	a->addr = (uchar*)(KZERO | a->mem);
.
409c
		print("serial%d avanstar port %d addr %lux irq %d\n", i, a->port,
			a->addr, a->irq);
.
396a
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c | ISAnotdl);
		a->memsize = a->ramsize;

.
379c
	int i, c;
.
364,365d
361a
	db->qid.vers = 0;
.
351c
				db->qid.path = QID(dev, ch, Qstat);
.
346c
				db->qid.path = QID(dev, ch, Qctl);
.
341c
				db->qid.path = QID(dev, ch, Qdata);
.
326c
			sprint(db->name, "astar%dctl", astar[dev]->id);
.
320a
			db->length = astar[dev]->memsize;
.
318c
			sprint(db->name, "astar%dmem", astar[dev]->id);
.
312a
	memset(db, 0, sizeof(Dir));

.
287a
static void	astarctl(Astarchan*, char*);
.
246c
	GCB		*gcb;		/* global board comm area */
.
216d
40c
	 ISAnotdl=	 1<<1,		/*  download bit (0 == download) */
.
## diffname pc/devastar.c 1994/1116
## diff -e /n/fornaxdump/1994/1115/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1116/sys/src/brazil/pc/devastar.c
1250c
	if(a->needpage)
		setpage(a, 0);
.
1238a
 *  get flow controlled input going again
 */
static void
astarkick(Astarchan *ac)
{
	ilock(&ac->a->pagelock);
	astarinput(ac);
	iunlock(&ac->a->pagelock);
}

/*
.
1234,1235c
	if(a->needpage)
		setpage(a, 0);
.
1232c
		if(qroduce(ac->iq, buf, n) < 0)
			break;	/* flow controlled */
		if(a->needpage)
			setpage(a, 0);
		ccb->inrp = LEUS(rp - a->addr);
.
1225c
		if(a->needpage)
			setpage(a, bp - a->addr);
.
1211c
	if(a->needpage)
		setpage(a, 0);
.
1187c
		if(a->needpage)
			setpage(a, 0);
.
1180c
		if(a->needpage)
			setpage(a, bp - a->addr);
.
1163c
	if(a->needpage)
		setpage(a, 0);
.
1068c
	UNLOCKPAGE(a);
.
1038,1039c
		LOCKPAGE(a, 0);
.
1034c
		UNLOCKPAGE(a);
.
1002,1004d
996,999c
		if(i){
			n |= Cobeycts|Cgenrts;
			n &= ~Cmctl;
		} else {
			n &= ~(Cobeycts|Cgenrts);
			n |= Cmctl;
		}
.
962a
		ac->baud = i;

		/* set trigger level to about 50  per second */
		n = i/500;
		i = (LEUS(ccb->inlim) - LEUS(ccb->inbase))/2;
		if(n > i)
			n = i;
		ccb->intrigger = LEUS(n);

.
951a
		/* set baud rate (high rates are special - only 16 bits) */
.
946,947c
	LOCKPAGE(a, 0);
.
914,918d
892c
	UNLOCKPAGE(a);
.
887,888c
	LOCKPAGE(a, 0);
.
865c
	UNLOCKPAGE(ac->a);
.
861,862c
	LOCKPAGE(ac->a, 0);
.
856c
	UNLOCKPAGE(ac->a);
.
853,854c
	LOCKPAGE(ac->a, 0);
.
841c
	UNLOCKPAGE(ac->a);
.
838,839c
	LOCKPAGE(ac->a, 0);
.
806c
		setpage(a, 0);
.
803a
		a->needpage = 1;
.
782a
	UNLOCKPAGE(a);
.
781c
	/* enable control program interrupt generation */
	LOCKPAGE(a, 0);
.
776c
		ac->iq = qopen(4*1024, 0, astarkickin, ac);
.
764c

	UNLOCKPAGE(a);
.
733,734c
	LOCKPAGE(a, 0);
.
730c
		UNLOCKPAGE(a);
.
716a
	setpage(a, 0);
	if(a->memsize <= Pagesize)
		a->needpage = 0;
	else
		a->needpage = 1;
.
691c
		UNLOCKPAGE(a);
.
687,688c
		LOCKPAGE(a, offset);
.
648c
		return qread(ac->iq, buf, n);
.
605c
		UNLOCKPAGE(a);
.
601,602c
		LOCKPAGE(a, offset);
.
530a
			qreopen(ac->iq);
			qreopen(ac->oq);
		}
.
529c
		if(ac->opens++ == 0){
.
284a
static void	astarkickin(Astarchan*);
.
260a
	int	baud;
.
248d
244a
	int		needpage;
.
59a
#define LOCKPAGE(a, o) if((a)->needpage){ilock(&(a)->pagelock);setpage(a, o);}
#define UNLOCKPAGE(a) if((a)->needpage)iunlock(&(a)->pagelock)

.
## diffname pc/devastar.c 1994/1117
## diff -e /n/fornaxdump/1994/1116/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1117/sys/src/brazil/pc/devastar.c
1309c
			astaroutput(ac);
.
1264c
astarkickin(Astarchan *ac)
.
1250c
		if(qproduce(ac->iq, buf, n) < 0)
.
1211c
	astaroutput(ac);
.
1168c
astaroutput(Astarchan *ac)
.
923a
	LOCKPAGE(ac->a, 0);
	n = LEUS(ac->ccb->proto) | Cmctl;
	ac->ccb->proto = LEUS(n);
	UNLOCKPAGE(ac->a);
.
920a
	int n;

.
357c
				sprint(db->name, "eia%d%2.2dstat", dev, ch+1);
.
352c
				sprint(db->name, "eia%d%2.2dctl", dev, ch+1);
.
347c
				sprint(db->name, "eia%d%2.2d", dev, ch+1);
.
## diffname pc/devastar.c 1994/1118
## diff -e /n/fornaxdump/1994/1117/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1118/sys/src/brazil/pc/devastar.c
792a
	setvec(Int0vec + a->irq, astarintr, a);
.
424c
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c & ~ISAnotdl);
		a->memsize = Pramsize;

		c = inb(a->port+ISActl2);
		outb(a->port+ISActl2, c & ~ISAmen);
		a->page = -1;
.
413d
404,407d
402a
		}
.
401c
		else {
			xfree(a);
			astar[nastar] = 0;
.
394c
			continue;
.
357c
				sprint(db->name, "eia%d%2.2dstat", dev, ch);
.
352c
				sprint(db->name, "eia%d%2.2dctl", dev, ch);
.
347c
				sprint(db->name, "eia%d%2.2d", dev, ch);
.
## diffname pc/devastar.c 1994/1119
## diff -e /n/fornaxdump/1994/1118/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1119/sys/src/brazil/pc/devastar.c
1295a
	if(a->running == 0){
		print("astar interrupt but cp not running\n");
		return;
	}
.
795,800d
780a
print("setting up channels\n");
.
778a
	/* enable control program interrupt generation */
	a->gcb->cmd2 = LEUS(Gintack);

.
747a

.
733a
print("waiting for cp\n");
.
724a
print("out of download\n");
.
428a

		setvec(Int0vec + a->irq, astarintr, a);
.
425,427d
421a
		/* disable ISA memory response */
		c = inb(a->port+ISActl2);
		outb(a->port+ISActl2, c & ~ISAmen);

		/* download mode to turn off cpu */
.
418c
		print("serial%d avanstar port 0x%lux addr %lux irq %d\n", i, a->port,
.
## diffname pc/devastar.c 1994/1120
## diff -e /n/fornaxdump/1994/1119/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1120/sys/src/brazil/pc/devastar.c
839c
		a->page = -1;
		setpage(a, 0);
.
829a
		a->page = -1;
.
732d
730c
	c = inb(a->port+ISActl1);
	outb(a->port+ISActl1, c|ISAien|ISAnotdl);
.
720c
	int c, n, i, sz;
.
486a
	/* set ISA memory address */
	outb(a->port+ISAmaddr, (a->mem>>12) & 0xfc);
	a->gcb = (GCB*)(KZERO | a->mem);
	a->addr = (uchar*)(KZERO | a->mem);

	/* set up interrupt level, reset processor, leave interrupts off */
	c = inb(a->port+ISActl1);
	c &= ~(ISAnotdl|ISAien|ISAirq);
	c |= isairqcode[a->irq];
	outb(a->port+ISActl1, c);
	setvec(Int0vec + a->irq, astarintr, a);

	/* disable ISA memory response */
	c = inb(a->port+ISActl2);
	outb(a->port+ISActl2, c & ~ISAmen);
	a->memsize = 0;
	a->page = -1;

.
476,481c
	/* check interrupt level */
.
456c
	int i, c, found;
.
421,432d
418c
		print("serial%d avanstar port 0x%lux addr %lux irq %d\n", a->id, a->port,
.
406a
		/* defaults */
.
396a
		/* check all possible names */
.
305c

	c = inb(a->port+ISActl2) & ~ISAmbank;
	outb(a->port+ISActl2, ISAmen|i|c);
.
300c
	int i, c;
.
46c
	 ISAmbank=	 0xf<<0,		/*  shift for 4 bit memory bank */
.
## diffname pc/devastar.c 1994/1121
## diff -e /n/fornaxdump/1994/1120/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1121/sys/src/brazil/pc/devastar.c
1342a
		ac++;
	}
	ac = a->c;
	for(vec = errvec; vec; vec >>= 1){
		c = LEUS(ac->ccb->errstat);
		if(c & Cframing)
			ac->framing++;
		if(c & Coverrun)
			ac->overrun++;
.
1321d
1308,1311d
1304a
	if(a->running == 0)
		panic("astar interrupt but cp not running\n");

.
1302a
	int c;
.
1008a
		ac->dtr = n;
.
810a

	/* set up interrupt level, enable interrupts */
	c = inb(a->port+ISActl1);
	c &= ~ISAirq;
	c |= ISAien|isairqcode[a->irq];
	outb(a->port+ISActl1, c);

	setvec(Int0vec + a->irq, astarintr, a);

	/* enable control program interrupt generation */
	LOCKPAGE(a, 0);
	a->gcb->cmd2 = LEUS(Gintack);
	UNLOCKPAGE(a);
.
801c
	a->c = smalloc(a->nchan * sizeof(Astarchan));
.
796d
791,793d
744d
741a
	a->page = -1;
	setpage(a, 0);
.
734d
660a
	case Qstat:
		a = astar[BOARD(c->qid.path)];
		return statread(a->c + CHAN(c->qid.path), buf, n, offset);
.
650a
static long
statread(Astarchan *ac, void *buf, long n, ulong offset)
{
	char s[128];
	int mstat, bstat;

	LOCKPAGE(ac->a, 0);
	mstat = LEUS(ac->ccb->mstat);
	bstat = LEUS(ac->ccb->bstat);
	UNLOCKPAGE(ac->a);

	/* CCB.mstat fields */
	sprint(s, "ferr %d oerr %d baud %d", ac->framing, ac->overrun, ac->baud);
	if(mstat & Cctsstat)
		strcat(s, " cts");
	if(mstat & Cdsrstat)
		strcat(s, " dsr");
	if(mstat & Cristat)
		strcat(s, " ring");
	if(mstat & Cdcdstat)
		strcat(s, " dcd");
	if(ac->opens)
		strcat(s, " dtr");
	if((bstat & Crbrts) == 0)
		strcat(s, " rts");

	return readstr(offset, buf, n, s);
}

.
491a
	/* reset processor */
	outb(a->port+ISActl1, 0);

.
487,488c
	outb(a->port+ISActl2, 0);
.
479,485d
448c
	int i, found;
.
423a
		print("\tctl1 %ux ctl2 %ux maddr %ux stat1 %ux stat2 %ux\n", inb(a->port+ISActl1),
			inb(a->port+ISActl2), inb(a->port+ISAmaddr), inb(a->port+ISAstat1),
			inb(a->port+ISAstat2));
.
388c
	int i;
.
359c
				sprint(db->name, "eia%d%2.2dstat", astar[dev]->id, ch);
.
354c
				sprint(db->name, "eia%d%2.2dctl", astar[dev]->id, ch);
.
349c
				sprint(db->name, "eia%d%2.2d", astar[dev]->id, ch);
.
306,307c
	outb(a->port+ISActl2, ISAmen|i);
.
300c
	int i;
.
264c
	int	baud;		/* baud rate */
	int	framing;	/* framing errors */
	int	overrun;	/* overruns */
	int	dtr;		/* non-zero means dtr on */
.
260,261c
	Astar	*a;		/* controller */
	CCB	*ccb;		/* channel control block */
.
257,258c
	QLock;			/* lock for rendez */
	Rendez	r;		/* waiting for command completion */
.
46c
	 ISAmbank=	 0xf<<0,	/*  shift for 4 bit memory bank */
.
## diffname pc/devastar.c 1994/1122
## diff -e /n/fornaxdump/1994/1121/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1122/sys/src/brazil/pc/devastar.c
1128a
		ac->rts = i;
.
1050c
		ac->dtr = i;
.
963d
833a
		ac->baud = 9600;	/* a100i default */
.
675a
	strcat(s, "\n");
.
674c
	if(ac->rts && (bstat & Crbrts) == 0)
.
672c
	if(ac->dtr)
.
663c
	sprint(s, "opens %d ferr %d oerr %d baud %d", ac->opens, ac->framing,
		ac->overrun, ac->baud);
.
579c
		if(--(ac->opens) == 0){
.
285,286c
#define BOARD(x)	(((x)>>16)&0xff)
#define CHAN(x)		(((x)>>8)&0xff)
.
267a
	int	rts;		/* non-zero means rts on */
.
## diffname pc/devastar.c 1994/1210
## diff -e /n/fornaxdump/1994/1122/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1210/sys/src/brazil/pc/devastar.c
419a
		if(isaget(a->mem, Pagesize, 0) == 0)
			panic("astarreset: %lux", a->mem);

.
## diffname pc/devastar.c 1994/1218
## diff -e /n/fornaxdump/1994/1210/sys/src/brazil/pc/devastar.c /n/fornaxdump/1994/1218/sys/src/brazil/pc/devastar.c
420c
		if(getisa(a->mem, Pagesize, 0) == 0)
.
## diffname pc/devastar.c 1995/0106
## diff -e /n/fornaxdump/1994/1218/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0106/sys/src/brazil/pc/devastar.c
421a
		a->mem & ~KZERO;
.
420c
		a->mem = getisa(a->mem, Pagesize, Pagesize);
		if(a->mem == 0)
.
414,415d
## diffname pc/devastar.c 1995/0108
## diff -e /n/fornaxdump/1995/0106/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devastar.c
1200a
}

long
astarbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
711a
Block*
astarbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname pc/devastar.c 1995/0115
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0115/sys/src/brazil/pc/devastar.c
421c
		a->mem &= ~KZERO;
.
## diffname pc/devastar.c 1995/0127
## diff -e /n/fornaxdump/1995/0115/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0127/sys/src/brazil/pc/devastar.c
548a
			ac->qopens--;
.
## diffname pc/devastar.c 1995/0207
## diff -e /n/fornaxdump/1995/0127/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0207/sys/src/brazil/pc/devastar.c
549c
			ac->opens--;
.
## diffname pc/devastar.c 1995/0505
## diff -e /n/fornaxdump/1995/0207/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0505/sys/src/brazil/pc/devastar.c
765c
 *  start control program
.
## diffname pc/devastar.c 1995/0726
## diff -e /n/fornaxdump/1995/0505/sys/src/brazil/pc/devastar.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devastar.c
1219d
1217c
astarcreate(Chan*, char*, int, ulong)
.
## diffname pc/devastar.c 1996/0223
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devastar.c /n/fornaxdump/1996/0223/sys/src/brazil/pc/devastar.c
9d
## diffname pc/devastar.c 1996/0807
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/pc/devastar.c /n/fornaxdump/1996/0807/sys/src/brazil/pc/devastar.c
450c
		|| (c == ISAid1 && c1 == ISAid0)
		|| (c == ISAid0x && c1 == ISAid1x)
		|| (c == ISAid1x && c1 == ISAid0x);
.
35a
	 ISAid0x=	 0x69,
	 ISAid1x=	 0x96,
.
## diffname pc/devastar.c 1996/0808
## diff -e /n/fornaxdump/1996/0807/sys/src/brazil/pc/devastar.c /n/fornaxdump/1996/0808/sys/src/brazil/pc/devastar.c
887,894c
		downloadmode(a);
.
767a
 *  put board into download mode
 */
static void
downloadmode(Astar *a)
{
	int c, i;

	/* put board in download mode */
	c = inb(a->port+ISActl1);
	outb(a->port+ISActl1, c & ~ISAnotdl);
	a->memsize = Pramsize;
	a->needpage = 1;

	/* give it up to 5 seconds to reset */
	for(i = 0; i < 21; i++){
		if(!(inb(a->port+ISActl1) & ISAnotdl))
			break;
		tsleep(&a->r, return0, 0, 500);
	}
	if(inb(a->port+ISActl1) & ISAnotdl){
		print("astar%d did not reset\n", a->id);
		error(Eio);
	}

	/* enable ISA access to first 16k */
	a->page = -1;
	setpage(a, 0);
}

/*
.
## diffname pc/devastar.c 1997/0327
## diff -e /n/fornaxdump/1996/0808/sys/src/brazil/pc/devastar.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devastar.c
1316a

.
1273a
Dev astardevtab = {
	astarreset,
	devinit,
	astarattach,
	devclone,
	astarwalk,
	astarstat,
	astaropen,
	devcreate,
	astarclose,
	astarread,
	devbread,
	astarwrite,
	devbwrite,
	devremove,
	astarwstat,
};

.
1236,1255c
static void
.
1192c
static long
.
1098,1099c
		qhangup(ac->iq, nil);
		qhangup(ac->oq, nil);
.
893c
	intrenable(VectorPIC + a->irq, astarintr, a, BUSUNKNOWN);
.
716,721d
690c
static long
.
568c
static void
.
531c
static Chan*
.
525c
static void
.
513,519c
static int
.
502,507c
static Chan*
.
439c
static int isaport[] = { 0x200, 0x208, 0x300, 0x308, 0x600, 0x608, 0x700, 0x708, 0 };
.
419c
		a->mem = umbmalloc(a->mem, Pagesize, Pagesize);
.
389c
static void
.
318c
static int
.
## diffname pc/devastar.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devastar.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devastar.c
1238a
	'G',
	"astar",

.
381c
	db->type = devtab[c->type]->dc;
.
## diffname pc/devastar.c 1997/0710
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devastar.c /n/emeliedump/1997/0710/sys/src/brazil/pc/devastar.c
566,567d
562a
	if((c->flag & COPEN) == 0)
		return;

.
280c
	Qmem= 1,
.
## diffname pc/devastar.c 1997/0917
## diff -e /n/emeliedump/1997/0710/sys/src/brazil/pc/devastar.c /n/emeliedump/1997/0917/sys/src/brazil/pc/devastar.c
1394d
1387a
	globvec = LEUS(xchgw(&a->gcb->serv, 0));
	USED(globvec);
.
1376c
	ulong globvec, vec, invec, outvec, errvec, mvec, cmdvec;
.
406c
 		else if(strcmp(a->type, "a200i") == 0 ||
		      strcmp(a->type,"A200I") == 0 ||
		      strcmp(a->type, "a16i") == 0)
.
## diffname pc/devastar.c 1997/0919
## diff -e /n/emeliedump/1997/0917/sys/src/brazil/pc/devastar.c /n/emeliedump/1997/0919/sys/src/brazil/pc/devastar.c
1349,1350c
		if(ac->opens == 0 || qproduce(ac->iq, buf, n) < 0)
			break;	/* flow controlled or not open */
.
## diffname pc/devastar.c 1998/0109
## diff -e /n/emeliedump/1997/0919/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0109/sys/src/brazil/pc/devastar.c
1399a
	if(a->pci){
		/*
		 * Only the PCI doorbell interrupt is expected.
		 */
		status = inl(a->port+PCIstatus);
		if((status & 0x0810E000) != 0x00002000)
			print("#G%d: unexpected interrupt %uX\n", a->id, status);
		if(status & 0x00002000)
			outl(a->port+PCIdoorbell1, 1);
	}
.
1383c
		panic("#G%d: interrupt but cp not running\n", a->id);
.
1380a

.
1379c
	int c, status;
.
1191c
		if(a->pci)
			return pcimemwrite(a, buf, n, offset);
		return isamemwrite(a, buf, n, offset);
.
966c
		print("#G%d: cmd status %ux\n", ac->a->id, status);
.
962c
		print("#G%d: cmd didn't terminate\n", ac->a->id);
.
918a
	} else if(strncmp(cmsg, "test", 4) == 0){
		uchar *p;

#ifdef notdef
		p = a->addr;
		a->page = -1;
		setpage(a, 16*1024);
		*p = 'X';
		p = a->addr;
		print("page0: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);
		setpage(a, 2*16*1024);
		print("page1: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);
		p = a->addr;
		*p = 'Y';
		p = a->addr;
		print("page1: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);
		setpage(a, 16*1024);
		p = a->addr;
		print("page0: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);
#else
		p = a->addr;
		*p = 'A';
		print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		p = a->addr+(16*1024);
		*p = 'B';
		print("16K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		p = a->addr;
		print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		*p = 'C';
		print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		p = a->addr+(64*1024);
		*p = 'D';
		print("64K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		p = a->addr;
		print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);

		p = a->addr+(16*1024);
		print("16K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p);
#endif /* notdef */

.
905,914d
890,891d
879,880d
874,877c
	if(a->pci){
		/*
		 * Which bits in the interrupt control register should be set?
		 */
		outl(a->port+PCIcontrol, 0x00031F00);
		intrenable(VectorPIC + a->irq, astarintr, a, a->pci->tbdf);
	}
	else{
		c = inb(a->port+ISActl1);
		c &= ~ISAirq;
		c |= ISAien|isairqcode[a->irq];
		outb(a->port+ISActl1, c);
		intrenable(VectorPIC + a->irq, astarintr, a, BUSUNKNOWN);
	}
.
850c
			print("#G%d: chan buffer spans pages\n", a->id);
.
843c
		print("#G%d: ccb's not in 1st page\n", a->id);
.
837c
		print("#G%d: has %d channels?\n", a->id, i);
.
830c
	case 0x0C:
	case 0x12:					/* AvanstarXp */
.
828c
		print("#G%d: wrong board type %uX\n", a->id, i);
.
814,817d
805,812d
803c
	else{
		a->page = -1;
		setpage(a, 0);
.
801c
	if(a->pci || a->memsize <= Pagesize)
.
798,799c
	if(a->pci){
		outl(a->port+PCImailbox, 1);

		/* wait for control program to signal life */
		delay(100);
		for(i = 0; i < 10; i++){
			if(inl(a->port+PCImailbox) & 0x80000000)
				break;
			tsleep(&a->r, return0, 0, 100);
		}
		if(!(inl(a->port+PCImailbox) & 0x80000000)){
			print("#G%d: program not ready\n", a->id);
			//error(Eio);
		}

		a->addr = (uchar*)(a->mem+0x10000);
	}
	else{
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c|ISAien|ISAnotdl);

		/* wait for control program to signal life */
		for(i = 0; i < 21; i++){
			if(inb(a->port+ISActl1) & ISApr)
				break;
			tsleep(&a->r, return0, 0, 500);
		}
		if((inb(a->port+ISActl1) & ISApr) == 0){
			print("#G%d: program not ready\n", a->id);
			error(Eio);
		}
	}

.
778,780c
		/* give it up to 5 seconds to reset */
		for(i = 0; i < 21; i++){
			if(!(inb(a->port+ISActl1) & ISAnotdl))
				break;
			tsleep(&a->r, return0, 0, 500);
		}
		if(inb(a->port+ISActl1) & ISAnotdl){
			print("#G%d: did not reset\n", a->id);
			error(Eio);
		}

		/* enable ISA access to first 16k */
		a->page = -1;
		setpage(a, 0);
	}
.
773,776c
	else{
		a->memsize = Pramsize;
		a->needpage = 1;
		c = inb(a->port+ISActl1);
		outb(a->port+ISActl1, c & ~ISAnotdl);
.
762,771c
	if(a->pci){
		/*
		 * Don't let the download write over the
		 * i960 data structures.
		 */
		a->memsize = 0xD000;
		a->addr = (uchar*)a->mem;
.
712c
isamemwrite(Astar *a, uchar *from, long n, ulong offset)
.
708a
 *  write PCI mapped memory
 */
static long
pcimemwrite(Astar *a, uchar *from, long n, ulong offset)
{
	uchar *to;
	int rem;
	ulong limit;

	/*
	 * Disallow writes above 0xD000 where the i960
	 * data structures live if writing in the lower bank.
	 */
	if(a->addr == (uchar*)a->mem)
		limit = 0xD000;
	else
		limit = a->memsize;
	if(offset+n > limit){
		if(offset >= limit)
			return 0;
		n = limit - offset;
	}

	to = a->addr+offset;
	for(rem = n; rem > 0; rem--)
		*to++ = *from++;

	return n;
}

/*
.
696c
		a = astar[BOARD(c->qid.path)];
		if(a->pci)
			return pcimemread(a, buf, n, offset);
		return isamemread(a, buf, n, offset);
.
643,647c
	if(a->pci)
		sprint(s, "range %uX remap %uX region %uX mailbox %uX doorbell0 %uX doorbell1 %uX control %uX command %uX",
			inl(a->port+PCIrange),
			inl(a->port+PCIremap),
			inl(a->port+PCIregion),
			inl(a->port+PCImailbox),
			inl(a->port+PCIdoorbell0),
			inl(a->port+PCIdoorbell1),
			inl(a->port+PCIcontrol),
			inl(a->port+PCIcommand));
	else
		sprint(s, "id %4.4ux ctl1 %2.2ux ctl2 %2.2ux maddr %2.2ux stat %4.4ux",
			(inb(a->port+ISAid)<<8)|inb(a->port+ISAid),
			inb(a->port+ISActl1), inb(a->port+ISActl2), 
			inb(a->port+ISAmaddr),
			(inb(a->port+ISAstat2)<<8)|inb(a->port+ISAstat1));

.
594c
isamemread(Astar *a, uchar *to, long n, ulong offset)
.
590a
 *  read PCI mapped memory
 */
static long
pcimemread(Astar *a, uchar *to, long n, ulong offset)
{
	uchar *from;
	int rem;

	if(offset+n > a->memsize){
		if(offset >= a->memsize)
			return 0;
		n = a->memsize - offset;
	}

	from = a->addr+offset;
	for(rem = n; rem > 0; rem--)
		*to++ = *from++;

	return n;
}

/*
.
490,491c
	a->gcb = KADDR(a->mem);
	a->addr = KADDR(a->mem);
.
484c
		print("#G%d: bad irq %d\n", a->id, a->irq);
.
478c
		print("#G%d: not found\n", a->id);
.
431,435c
		else{
			/* defaults */
			if(a->irq == 0)
				a->irq = 15;
	
			a->mem = umbmalloc(a->mem, Pagesize, Pagesize);
			if(a->mem == 0)
				panic("astarreset: %lux", a->mem);
			a->mem = PADDR(a->mem);
	
			if(astarsetup(a) < 0){
				xfree(a);
				astar[nastar] = 0;
				continue;
			}
			print("\tctl1 %ux ctl2 %ux maddr %ux stat1 %ux stat2 %ux\n",
				inb(a->port+ISActl1), inb(a->port+ISActl2), inb(a->port+ISAmaddr),
				inb(a->port+ISAstat1), inb(a->port+ISAstat2));
		}

		print("#G%d: %s port 0x%luX addr 0x%luX irq %d\n",
			a->id, a->type, a->port, a->addr, a->irq);
.
426,429c
			/*
			 * So the memory can be read before any other
			 * initialisation takes place.
			 */
			a->memsize = a->ramsize;
.
421,424c
			/*
			 * Toggle the software reset and wait for
			 * the adapter local init status to indicate done.
			 */
			outl(a->port+PCIremap, 0xA0000001);
			x = inl(a->port+PCIcommand);
			outl(a->port+PCIcommand, 0x40000000|x);
			microdelay(1);
			outl(a->port+PCIcommand, x);
			delay(100);
			for(x = 0; x < 10000; x++){
				 if(inl(a->port+PCIcommand) & 0x80000000)
					break;
			}
			if(!(inl(a->port+PCIcommand) & 0x80000000))
				print("#G: didn't reset\n", a->id);
.
419a
		if(a->pci){
			a->irq = p->intl;
			a->port = p->mem[1].bar & ~0x03;
			a->mem = upamalloc(p->mem[2].bar & ~0x0F, p->mem[2].size, 0);
			a->addr = (uchar*)a->mem;
			a->gcb = (GCB*)(a->mem+0x10000);
.
416,418d
410c
		else if(cistrcmp(a->type, "AvanstarXp") == 0){
			if(p = pcimatch(p, 0x114F, 0x6001)){
				a->pci = p;
				/*
				 * It's really 128KB, but split into
				 * two 64KB chunks.
				 */
				a->ramsize = 64*1024;
			}
		}

		if(a->ramsize == 0){
.
406,408c
 		else if(cistrcmp(a->type, "a200i") == 0 ||
		      cistrcmp(a->type,"A200I") == 0 ||
		      cistrcmp(a->type, "a16i") == 0)
.
404c
		if(cistrcmp(a->type, "a100i") == 0 || cistrcmp(a->type,"A100I") == 0)
.
402a
		a->ramsize = 0;
.
394a
	p = nil;
.
393a
	Pcidev *p;
.
392c
	int i, x;
.
306a
	if(a->pci){
		print("#G%d: setpage caller pc %uX\n", a->id, getcallerpc(a));
		return;
	}

.
249a
	int		pagebase;	/* pci */
.
241a
	Pcidev*		pci;
.
56a

	PCIrange=	0x00,
	PCIremap=	0x04,
	PCIregion=	0x18,
	PCImailbox=	0x40,
	PCIdoorbell0=	0x60,
	PCIdoorbell1=	0x64,
	PCIcontrol=	0x68,		/* write */
	PCIstatus=	0x68,		/* read */
	PCIcommand=	0x6C,

	Maxcard=	8,
	Pramsize=	64*1024,	/* size of program ram */
.
52,53d
16c
 *  However, xchgw() is in assembler and will have to be translated.
.
## diffname pc/devastar.c 1998/0319
## diff -e /n/emeliedump/1998/0109/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devastar.c
1389a
	ulong offset = off;
.
1385c
astarwrite(Chan *c, void *buf, long n, vlong off)
.
785a
	ulong offset = off;
.
782c
astarread(Chan *c, void *buf, long n, vlong off)
.
352c
			db->length1 = astar[dev]->memsize; /* BOTCH */
			db->length2 = astar[dev]->memsize; /* BOTCH */
.
344d
337c
astargen(Chan *c, Dirtab *, int , int i, Dir *db)
.
## diffname pc/devastar.c 1998/0414
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0414/sys/src/brazil/pc/devastar.c
571a
	ulong ctlrno;
	char *p;

	ctlrno = 0;
	if(spec && *spec){
		ctlrno = strtoul(spec, &p, 0);
		if((ctlrno == 0 && p == spec) || *p || (ctlrno >= Maxcard))
			error(Ebadarg);
	}
	if(astar[ctlrno] == nil)
		error(Enodev);

.
351,352c
			db->length = astar[dev]->memsize;
.
## diffname pc/devastar.c 1998/0813
## diff -e /n/emeliedump/1998/0414/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0813/sys/src/brazil/pc/devastar.c
470c
				print("#G%d: didn't reset\n", a->id);
.
## diffname pc/devastar.c 1998/0825
## diff -e /n/emeliedump/1998/0813/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devastar.c
1134c
		print("16K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1131c
		print(" 0K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1128c
		print("64K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1124c
		print(" 0K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1121c
		print(" 0K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1118c
		print("16K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
1114c
		print(" 0K: %8.8luX %2.2uX\n", inl(a->port+PCIremap), *p);
.
742c
		sprint(s, "range %luX remap %luX region %luX mailbox %luX doorbell0 %luX doorbell1 %luX control %luX command %luX",
.
548c
		print("#G%d: bad irq %lud\n", a->id, a->irq);
.
498c
		print("#G%d: %s port 0x%luX addr 0x%luX irq %lud\n",
.
321c
		print("#G%d: setpage caller pc %luX\n", a->id, getcallerpc(a));
.
## diffname pc/devastar.c 1998/0910
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0910/sys/src/brazil/pc/devastar.c
1063c
		intrenable(a->irq, astarintr, a, BUSUNKNOWN);
.
1056c
		intrenable(a->irq, astarintr, a, a->pci->tbdf);
.
## diffname pc/devastar.c 1998/0926
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/devastar.c /n/emeliedump/1998/0926/sys/src/brazil/pc/devastar.c
1092,1136d
## diffname pc/devastar.c 1999/0315
## diff -e /n/emeliedump/1998/0926/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0315/sys/src/brazil/pc/devastar.c
1605a
		ac++;
	}
	ac = a->c;
	for(vec = mvec; vec; vec >>= 1){
		if(vec&1)
			astarmodemchange(ac);
.
1574d
1545a
static void
astarmodemchange(Astarchan *ac)
{
	Astar *a = ac->a;
	int mstat;

	if(a->needpage)
		setpage(a, 0);
	mstat = LEUS(ac->ccb->mstat);
	if(ac->hup_dsr && ac->dsr == 1 && (mstat & Cdsrstat) == 0
	|| ac->hup_dcd && ac->dcd == 1 && (mstat & Cdcdstat) == 0){
		qhangup(ac->iq, nil);
		qhangup(ac->oq, nil);
	}
	ac->dsr = mstat & Cdsrstat;
	ac->dcd = mstat & Cdcdstat;
}

.
1186a
	ac->dsr = ac->dcd = 0;
.
788a
		ac->baud,
		ac->hup_dcd,
		ac->dtr,
		ac->hup_dsr,
		(fstat & Clenmask),
		0, 	/* change in modem status? */
		(fstat & Cparmask) ? ((fstat & Cevenpar) == Cevenpar ? 'e' : 'o') : 'n',
		(bstat & Crbrts) ? 1 : 0,
		(fstat & C2stop) ? 2 : 1,

		ac - ac->a->c,
		ac->framing,
		ac->overrun,
		(mstat & Cctsstat)    ? " cts"  : "",
		(mstat & Cdsrstat)    ? " dsr"  : "",
		(mstat & Cdcdstat)    ? " dcd"  : "",
		(mstat & Cristat)   ? " ring" : ""
	);
.
772,787c
	snprint(s, sizeof s,
		"b%d c%d d%d e%d l%d m%d p%c r%d s%d\n"
		"%ld %d %d%s%s%s%s\n",
.
769a
	fstat = LEUS(ac->ccb->format);
.
764,765c
	char s[256];
	int mstat, bstat, fstat;
.
282a
	int	dsr;		/* non-zero means dsr on */
	int	dcd;		/* non-zero means dcd on */
.
280a
	int	hup_dsr;	/* hangup when dsr goes away */
	int	hup_dcd;	/* hangup when dcd goes away */
.
## diffname pc/devastar.c 1999/0501
## diff -e /n/emeliedump/1999/0315/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0501/sys/src/brazil/pc/devastar.c
325c
		print("#G%d: setpage caller pc %luX\n", a->id, getcallerpc(&a));
.
## diffname pc/devastar.c 1999/0629
## diff -e /n/emeliedump/1999/0501/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0629/sys/src/brazil/pc/devastar.c
1551a
	Astarchan *ac;

	ac = v;
.
1550c
astarkickin(void *v)
.
1495a
	Astarchan *ac;

	ac = v;
.
1494c
astarkick(void *v)
.
1214c
		tsleep(&ac->r, (int (*)(void*))qlen, ac->oq, 125);
.
310,311c
static void	astarkick(void*);
static void	astarkickin(void*);
.
## diffname pc/devastar.c 1999/0714
## diff -e /n/emeliedump/1999/0629/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devastar.c
552a
		iofree(a->port);
.
546a
		iofree(a->port);
.
544a
	}
.
543c
	else {
		sprint(name, "astar%d", a->id);
		if(ioalloc(a->port, 6, 0, name) < 0){
			print("#G%d: port 0x%lux in use\n", a->id, a->port);
			return -1;
		}
.
536a
			sprint(name, "astar%d", a->id);
			if(ioalloc(a->port, 6, 0, name) < 0)
				continue;
.
530a
	char name[8];
.
458a
			sprint(name, "astar%d", i);
			if(ioalloc(a->port, p->mem[2].size, 0, name) < 0){
				print("#G%d: port 0x%lux in use", a->id, a->port);
				xfree(a);
				astar[nastar] = 0;
				continue;
			}

.
415a
	char name[8];
.
## diffname pc/devastar.c 1999/0721
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0721/sys/src/brazil/pc/devastar.c
461,462c
			if(ioalloc(a->port, p->mem[1].size, 0, name) < 0){
				print("#G%d: port 0x%lux in use\n", a->id, a->port);
.
## diffname pc/devastar.c 1999/0801
## diff -e /n/emeliedump/1999/0721/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0801/sys/src/brazil/pc/devastar.c
376a
				db->length = qlen(astar[dev]->c[ch].iq);
.
## diffname pc/devastar.c 1999/0819
## diff -e /n/emeliedump/1999/0801/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devastar.c
1095c
		intrenable(a->irq, astarintr, a, BUSUNKNOWN, name);
.
1088c
		intrenable(a->irq, astarintr, a, a->pci->tbdf, name);
.
1081a
	snprint(name, sizeof name, "astar%d", a->id);
.
979a
	char name[10];
.
## diffname pc/devastar.c 1999/1230
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devastar.c /n/emeliedump/1999/1230/sys/src/9/pc/devastar.c
349a
	if(i == DEVDOTDOT){
		devdir(c, (Qid){CHDIR, 0}, "#G", 0, eve, 0555, db);
		return 1;
	}

.
## diffname pc/devastar.c 2000/0606
## diff -e /n/emeliedump/1999/1230/sys/src/9/pc/devastar.c /n/emeliedump/2000/0606/sys/src/9/pc/devastar.c
435c
		if(cistrcmp(a->type, "a100i") == 0)
.
## diffname pc/devastar.c 2001/0503
## diff -e /n/emeliedump/2000/0606/sys/src/9/pc/devastar.c /n/emeliedump/2001/0503/sys/src/9/pc/devastar.c
692d
682,685d
## diffname pc/devastar.c 2001/0527
## diff -e /n/emeliedump/2001/0503/sys/src/9/pc/devastar.c /n/emeliedump/2001/0527/sys/src/9/pc/devastar.c
687a
		poperror();
.
681a
		if(waserror()){
			qunlock(ac);
			nexterror();
		}
.
## diffname pc/devastar.c 2001/1106 # deleted
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devastar.c /n/emeliedump/2001/1106/sys/src/9/pc/devastar.c
1,1687d

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].