⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devastar.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h"/* *  Stargate's Avanstar serial board.  There are ISA, EISA, microchannel *  versions.  We only handle the ISA one. * *  At the expense of performance, I've tried to be careful about *  endian-ness to make this convertable to other ISA bus machines. *  However, xchgw() is in assembler and will have to be translated. */#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 LENDIANtypedef struct Astar Astar;typedef struct Astarchan Astarchan;enum{	/* ISA control ports */	ISAid=		0,		/* Id port and its values */	 ISAid0=	 0xEC,	 ISAid1=	 0x13,	 ISAid0x=	 0x69,	 ISAid1x=	 0x96,	ISActl1=	1,		/* board control */	 ISAien=	 1<<7,		/*  interrupt enable */	 ISAirq=	 7<<4,		/*  mask for irq code */	 ISAnotdl=	 1<<1,		/*  download bit (0 == 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 */	 ISAmen=	 1<<4,		/*  enable memory to respond to ISA cycles */	 ISAmbank=	 0xf<<0,	/*  shift for 4 bit memory bank */	ISAmaddr=	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) */	Pageshift=	14,		/* footprint of card mem in ISA space */	Pagesize=	1<<Pageshift,	Pagemask=	Pagesize-1,	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 */};#define APAGE(x) ((x)>>Pageshift)#define LOCKPAGE(a, o) if((a)->needpage){ilock(&(a)->pagelock);setpage(a, o);}#define UNLOCKPAGE(a) if((a)->needpage)iunlock(&(a)->pagelock)/* 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,};/* 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	ccbn;		/* control channel block count */	ushort	ccboff;		/* control channel block offset */	ushort	ccbsz;		/* 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' */};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.cmd2 bit */	Gintack=	0x1,	/* 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),};/* control program channel control block */typedef struct CCB CCB;struct CCB{	ushort	baud;		/* baud rate */	ushort	format;		/* data format */	ushort	proto;		/* 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 */	char	xon[2];		/* 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 */	char	xoff[2];	/* xoff characters */	ushort	status2;	char	strip[2];	/* strip/error characters */};enum{	/* special baud rate codes for CCB.baud */	Cb76800=	0xff00,	Cb115200=	0xff01,	/* CCB.format fields */	Clenmask=	3<<0,	/* data bits */	C1stop=		0<<2,	/* stop bits */	C2stop=		1<<2,	Cnopar=		0<<3,	/* parity */	Coddpar=	1<<3,	Cevenpar=	3<<3,	Cmarkpar=	5<<3,	Cspacepar=	7<<3,	Cparmask=	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 */};/* host per controller info */struct Astar{	QLock;				/* lock for rendez */	Rendez		r;		/* waiting for command completion */	ISAConf;	Pcidev*		pci;	Lock		pagelock;	/* lock for setting page */	int		page;		/* page currently mapped */	int		id;		/* from plan9.ini */	int		nchan;		/* number of channels */	Astarchan	*c;		/* channels */	int		ramsize;	/* 16k or 256k */	int		memsize;	/* size of memory currently mapped */	int		needpage;	int		pagebase;	/* pci */	GCB		*gcb;		/* global board comm area */	uchar		*addr;		/* base of memory area */	int		running;};/* host per channel info */struct Astarchan{	QLock;			/* lock for rendez */	Rendez	r;		/* waiting for command completion */	Astar	*a;		/* controller */	CCB	*ccb;		/* channel control block */	int	perm;	int	opens;	int	baud;		/* baud rate */	int	framing;	/* framing errors */	int	overrun;	/* overruns */	int	hup_dsr;	/* hangup when dsr goes away */	int	hup_dcd;	/* hangup when dcd goes away */	int	dtr;		/* non-zero means dtr on */	int	rts;		/* non-zero means rts on */	int	dsr;		/* non-zero means dsr on */	int	dcd;		/* non-zero means dcd on */	Queue	*iq;	Queue	*oq;};Astar *astar[Maxcard];static int nastar;enum{	Qmem= 1,	Qbctl,	Qdata,	Qctl,	Qstat,};#define TYPE(x)		((x)&0xff)#define BOARD(x)	(((x)>>16)&0xff)#define CHAN(x)		(((x)>>8)&0xff)#define QID(b,c,t)	(((b)<<16)|((c)<<8)|(t))static int	astarsetup(Astar*);static void	astarintr(Ureg*, void*);static void	astarkick(void*);static void	astarkickin(void*);static void	enable(Astarchan*);static void	disable(Astarchan*);static void	astarctl(Astarchan*, char*);/* *  Only 16k maps into ISA space */static voidsetpage(Astar *a, ulong offset){	int i;	if(a->pci){		print("#G%d: setpage caller pc %luX\n", a->id, getcallerpc(&a));		return;	}	i = APAGE(offset);	if(i == a->page)		return;	outb(a->port+ISActl2, ISAmen|i);	a->page = i;}/* *  generate the astar directory entries */static intastargen(Chan *c, Dirtab *, int , int i, Dir *db){	int dev, sofar, ch, t;	extern ulong kerndate;	memset(db, 0, sizeof(Dir));	sofar = 0;	if(i == DEVDOTDOT){		devdir(c, (Qid){CHDIR, 0}, "#G", 0, eve, 0555, db);		return 1;	}	for(dev = 0; dev < nastar; dev++){		if(sofar == i){			sprint(db->name, "astar%dmem", astar[dev]->id);			db->qid.path = QID(dev, 0, Qmem);			db->mode = 0660;			db->length = astar[dev]->memsize;			break;		}		sofar++;		if(sofar == i){			sprint(db->name, "astar%dctl", astar[dev]->id);			db->qid.path = QID(dev, 0, Qbctl);			db->mode = 0660;			break;		}		sofar++;		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", astar[dev]->id, ch);				db->mode = astar[dev]->c[ch].perm;				db->qid.path = QID(dev, ch, Qdata);				db->length = qlen(astar[dev]->c[ch].iq);				break;			case 1:				sprint(db->name, "eia%d%2.2dctl", astar[dev]->id, ch);				db->mode = astar[dev]->c[ch].perm;				db->qid.path = QID(dev, ch, Qctl);				break;			case 2:				sprint(db->name, "eia%d%2.2dstat", astar[dev]->id, ch);				db->mode = 0444;				db->qid.path = QID(dev, ch, Qstat);				break;			}			break;		}		sofar += 3*astar[dev]->nchan;	}	if(dev == nastar)		return -1;	db->qid.vers = 0;	db->atime = seconds();	db->mtime = kerndate;	memmove(db->uid, eve, NAMELEN);	memmove(db->gid, eve, NAMELEN);	db->type = devtab[c->type]->dc;	db->dev = c->dev;	if(c->flag&CMSG)		db->mode |= CHMOUNT;	return 1;}static voidastarreset(void){	int i, x;	Astar *a;	Pcidev *p;	char name[8];	p = nil;	for(i = 0; i < Maxcard; i++){		a = astar[nastar] = xalloc(sizeof(Astar));		if(isaconfig("serial", i, a) == 0){			xfree(a);			astar[nastar] = 0;			continue;		}		a->ramsize = 0;		/* check all possible names */		if(cistrcmp(a->type, "a100i") == 0)			a->ramsize = 16*1024; 		else if(cistrcmp(a->type, "a200i") == 0 ||		      cistrcmp(a->type,"A200I") == 0 ||		      cistrcmp(a->type, "a16i") == 0)			a->ramsize = 256*1024;		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){			xfree(a);			astar[nastar] = 0;			continue;		}		a->id = i;		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);			sprint(name, "astar%d", i);			if(ioalloc(a->port, p->mem[1].size, 0, name) < 0){				print("#G%d: port 0x%lux in use\n", a->id, a->port);				xfree(a);				astar[nastar] = 0;				continue;			}			/*			 * 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%d: didn't reset\n", a->id);			/*			 * So the memory can be read before any other			 * initialisation takes place.			 */			a->memsize = a->ramsize;		}		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 %lud\n",			a->id, a->type, a->port, a->addr, a->irq);		nastar++;	}}/* isa ports an ax00i can appear at */static int isaport[] = { 0x200, 0x208, 0x300, 0x308, 0x600, 0x608, 0x700, 0x708, 0 };static intastarprobe(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)		|| (c == ISAid0x && c1 == ISAid1x)		|| (c == ISAid1x && c1 == ISAid0x);}static intastarsetup(Astar *a){	int i, found;	char name[8];	/* see if the card exists */	found = 0;	if(a->port == 0)		for(i = 0; isaport[i]; i++){			a->port = isaport[i];			sprint(name, "astar%d", a->id);			if(ioalloc(a->port, 6, 0, name) < 0)				continue;			found = astarprobe(isaport[i]);			if(found){				isaport[i] = -1;				break;			}		}	else {		sprint(name, "astar%d", a->id);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -