9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* Re: [9fans] ide fs patch for the current plan9 version
@ 2001-05-16 21:13 geoff
  0 siblings, 0 replies; 5+ messages in thread
From: geoff @ 2001-05-16 21:13 UTC (permalink / raw)
  To: 9fans

Yes, it is simpler to just keep the source tree clean, if you have
that option.  My ex-department tried the experiment of overlaying the
contents of our file server, which we kept pretty lean, on top of the
main Plan 9 file server.  It kept us current yet allowed us to
implement different administrative policies and in general substitute
our own files for those on the main file server.  We didn't have
permission to clean the main source tree.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] ide fs patch for the current plan9 version
  2001-05-16 13:02 nemo
@ 2001-05-17  4:54 ` Eric Dorman
  0 siblings, 0 replies; 5+ messages in thread
From: Eric Dorman @ 2001-05-17  4:54 UTC (permalink / raw)
  To: 9fans

nemo@gsyc.escet.urjc.es wrote:
> Hi,
> I'll try to keep the patch up-to-date wrt the distributed fs code
> until the day when the new integrated fs code be done and released.

good deal.  doesn't look like i'm going to get back
to it... Real Life(TM) intrudes...

--eld


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] ide fs patch for the current plan9 version
  2001-05-16 19:31 geoff
@ 2001-05-16 21:00 ` Francisco J Ballesteros
  0 siblings, 0 replies; 5+ messages in thread
From: Francisco J Ballesteros @ 2001-05-16 21:00 UTC (permalink / raw)
  To: 9fans



geoff@collyer.net wrote:
 
> You probably ought to "mk clean" before you "mk" in
> /sys/src/fs/plan9pc.  We tried this sort of overlaid source tree and
> found a couple of hazards: existing object (.8) files in the
> underlying tree (/sys/src/fs in this case) can cause trouble if they
> are unwritable (e.g., due to lack of permission) or if they are newer
> than source files in the overlaying tree (./idefs in this case).
> 
> Russ and I didn't quite finish a program called stitch to perform this
> sort of overlay dynamically (it worked under light load).  Stitch

Isn't it more simple just to keep the source directory always clean and
always overlay your one before mk'ing? 
Or am I missing something?


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] ide fs patch for the current plan9 version
@ 2001-05-16 19:31 geoff
  2001-05-16 21:00 ` Francisco J Ballesteros
  0 siblings, 1 reply; 5+ messages in thread
From: geoff @ 2001-05-16 19:31 UTC (permalink / raw)
  To: 9fans

> To apply the patch, I suggest you create two directories
> ./idefs/port and ./idefs/plan9pc, then run rc idefs.rc on ./idefs and
> bind -bc ./idefs/port /sys/src/fs/port 
> bind -bc ./idefs/plan9pc /sys/src/fs/plan9pc
> 
> after that you can mk in /sys/src/fs/plan9pc.  

You probably ought to "mk clean" before you "mk" in
/sys/src/fs/plan9pc.  We tried this sort of overlaid source tree and
found a couple of hazards: existing object (.8) files in the
underlying tree (/sys/src/fs in this case) can cause trouble if they
are unwritable (e.g., due to lack of permission) or if they are newer
than source files in the overlaying tree (./idefs in this case).

Russ and I didn't quite finish a program called stitch to perform this
sort of overlay dynamically (it worked under light load).  Stitch
changed the semantics of creation slightly so that new files in the
served tree were always created in the uppermost layer, though that
could be easily adjusted.  I also made a small tweak to mk to
understand enough about overlays that it would ignore targets (e.g.,
newer object files) in lower layers for the purpose of computing work
to be done.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [9fans] ide fs patch for the current plan9 version
@ 2001-05-16 13:02 nemo
  2001-05-17  4:54 ` Eric Dorman
  0 siblings, 1 reply; 5+ messages in thread
From: nemo @ 2001-05-16 13:02 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 1121 bytes --]

Hi,

this is just edorman's  patch for the fs kernel to let it work
with ide disks. Unlike the original patch as posted in 9fans,
this one can be `applied'  to the   current fs
kernel source. There is almost no change actually.


I don't know if the patch might break the fs code for regular scsi disks,
since it is `removing' some code which seems to be working on a scsi-based
fs. I couldn't try because I don't have scsi disks around. 

In any case,  I'm using the current fs code w/ this patch applied and it
seems to work ok. 
My configuration string (if I remember well) is ch0fh2. The
block size is 16K, but you may change the define for RBUFSIZE in
plan9pc/dat.h.

I'll try to keep the patch up-to-date wrt the distributed fs code
until the day when the new integrated fs code be done and released.

To apply the patch, I suggest you create two directories
./idefs/port and ./idefs/plan9pc, then run rc idefs.rc on ./idefs and
bind -bc ./idefs/port /sys/src/fs/port 
bind -bc ./idefs/plan9pc /sys/src/fs/plan9pc

after that you can mk in /sys/src/fs/plan9pc.  

hope this helps




[-- Attachment #2: Type: message/rfc822, Size: 105984 bytes --]


# To unbundle, run this file
echo plan9pc/dat.h
sed 's/.//' >plan9pc/dat.h <<'//GO.SYSIN DD plan9pc/dat.h'
-#define RBUFSIZE	(16*1024)	/* raw buffer size */
-#define	DSIZE		546000
-
-#include "../port/portdat.h"
-
-extern	Mach	mach0;
-
-typedef struct Segdesc	Segdesc;
-struct Segdesc
-{
-	ulong	d0;
-	ulong	d1;
-};
-
-typedef struct Mbank {
-	ulong	base;
-	ulong	limit;
-} Mbank;
-
-#define MAXBANK		8
-
-typedef struct Mconf {
-	Lock;
-	Mbank	bank[MAXBANK];
-	int	nbank;
-	ulong	topofmem;
-} Mconf;
-extern Mconf mconf;
-
-/*
- *  a parsed plan9.ini line
- */
-#define ISAOPTLEN	16
-#define NISAOPT		8
-
-typedef struct ISAConf {
-	char	type[NAMELEN];
-	ulong	port;
-	ulong	irq;
-	ulong	dma;
-	ulong	mem;
-	ulong	size;
-	ulong	freq;
-
-	int	nopt;
-	char	opt[NISAOPT][ISAOPTLEN];
-} ISAConf;
-
-typedef struct Pcidev Pcidev;
-
-extern char nvrfile[128];
//GO.SYSIN DD plan9pc/dat.h
echo plan9pc/devata.c
sed 's/.//' >plan9pc/devata.c <<'//GO.SYSIN DD plan9pc/devata.c'
-#include "all.h"
-#include "io.h"
-#include "mem.h"
-
-
-/* There were some chunks of code commented out in the originial
-   ide patches for version 2 which are not commented out in version 3
-   I leave those pieces of code commented out here too.
- */
-
-#define DEBUG	0
-#define DPRINT	if(DEBUG)print
-#define IDEBUG	0
-#define IDPRINT if(IDEBUG)print
-
-typedef	struct Drive		Drive;
-typedef	struct Ident		Ident;
-typedef	struct Controller	Controller;
-
-enum
-{
-	/* ports */
-	Pbase0=		0x1F0,	/* primary */
-	Pbase1=		0x170,	/* secondary */
-	Pbase2=		0x1E8,	/* tertiary */
-	Pbase3=		0x168,	/* quaternary */
-	Pdata=		0,	/* data port (16 bits) */
-	Perror=		1,	/* error port (read) */
-	 Eabort=	(1<<2),
-	Pfeature=	1,	/* buffer mode port (write) */
-	Pcount=		2,	/* sector count port */
-	Psector=	3,	/* sector number port */
-	Pcyllsb=	4,	/* least significant byte cylinder # */
-	Pcylmsb=	5,	/* most significant byte cylinder # */
-	Pdh=		6,	/* drive/head port */
-	 DHmagic=	0xA0,
-	 DHslave=	0x10,
-	Pstatus=	7,	/* status port (read) */
-	 Sbusy=		 (1<<7),
-	 Sready=	 (1<<6),
-	 Sdrq=		 (1<<3),
-	 Serr=		 (1<<0),
-	Pcmd=		7,	/* cmd port (write) */
-
-	/* commands */
-	Crecal=		0x10,
-	Cread=		0x20,
-	Cwrite=		0x30,
-	Cident=		0xEC,
-	Cident2=	0xFF,	/* pseudo command for post Cident interrupt */
-	Csetbuf=	0xEF,
-
-	Cpktcmd=	0xA0,
-	Cidentd=	0xA1,
-	Ctur=		0x00,
-	Creqsense=	0x03,
-	Ccapacity=	0x25,
-	Cread2=		0x28,
-	Cwrite2=	0x2A,
-
-	ATAtimo=	6000,		/* ms to wait for things to complete */
-	ATAPItimo=	10000,
-
-	NCtlr=		4,
-	NDrive=		NCtlr*2,
-
-	Maxloop=	1000000,
-};
-
-/*
- *  ident sector from drive.  this is from ANSI X3.221-1994
- */
-struct Ident
-{
-	ushort	config;		/* general configuration info */
-	ushort	cyls;		/* # of cylinders (default) */
-	ushort	reserved0;
-	ushort	heads;		/* # of heads (default) */
-	ushort	b2t;		/* unformatted bytes/track */
-	ushort	b2s;		/* unformated bytes/sector */
-	ushort	s2t;		/* sectors/track (default) */
-	ushort	reserved1[3];
-/* 10 */
-	ushort	serial[10];	/* serial number */
-	ushort	type;		/* buffer type */
-	ushort	bsize;		/* buffer size/512 */
-	ushort	ecc;		/* ecc bytes returned by read long */
-	ushort	firm[4];	/* firmware revision */
-	ushort	model[20];	/* model number */
-/* 47 */
-	ushort	s2i;		/* number of sectors/interrupt */
-	ushort	dwtf;		/* double word transfer flag */
-	ushort	capabilities;
-	ushort	reserved2;
-	ushort	piomode;
-	ushort	dmamode;
-	ushort	cvalid;		/* (cvald&1) if next 4 words are valid */
-	ushort	ccyls;		/* current # cylinders */
-	ushort	cheads;		/* current # heads */
-	ushort	cs2t;		/* current sectors/track */
-	ushort	ccap[2];	/* current capacity in sectors */
-	ushort	cs2i;		/* current number of sectors/interrupt */
-/* 60 */
-	ushort	lbasecs[2];	/* # LBA user addressable sectors */
-	ushort	dmasingle;
-	ushort	dmadouble;
-/* 64 */
-	ushort	reserved3[64];
-	ushort	vendor[32];	/* vendor specific */
-	ushort	reserved4[96];
-};
-
-enum {
-	Maxxfer		= 16*1024,	/* maximum transfer size/cmd */
-	Npart		= 8+2,		/* 8 sub partitions, disk, and partition */
-};
-
-typedef struct {
-	ulong	start;
-	ulong	end;
-	char	name[NAMELEN+1];
-} Partition;
-
-typedef struct {
-	int	online;
-	int	npart;		/* number of real partitions */
-	Partition p[Npart];
-	ulong	offset;
-	Partition *current;	/* current partition */
-
-	ulong	cap;		/* total sectors */
-	int	bytes;		/* bytes/sector */
-	int	sectors;	/* sectors/track */
-	int	heads;		/* heads/cyl */
-	long	cyl;		/* cylinders/drive */
-
-	char	lba;		/* true if drive has logical block addressing */
-	char	multi;		/* non-zero if drive does multiple block xfers */
-} Disc;
-
-/*
- *  an ata drive
- */
-struct Drive
-{
-	Controller *cp;
-	uchar	driveno;
-	uchar	dh;
-	uchar	atapi;		/* ATAPI */
-	uchar	drqintr;	/* ATAPI */
-	ulong	vers;		/* ATAPI */
-
-	int	partok;
-
-	Disc;
-};
-
-/*
- *  a controller for 2 drives
- */
-struct Controller
-{
-	QLock;
-	int	pbase;		/* base port */
-	uchar	ctlrno;
-
-	/*
-	 *  current operation
-	 */
-	int	cmd;		/* current command */
-	uchar	cmdblk[12];	/* ATAPI */
-	int	len;		/* ATAPI */
-	int	count;		/* ATAPI */
-	uchar	lastcmd;	/* debugging info */
-	uchar	*buf;		/* xfer buffer */
-	int	tcyl;		/* target cylinder */
-	int	thead;		/* target head */
-	int	tsec;		/* target sector */
-	int	tbyte;		/* target byte */
-	int	nsecs;		/* length of transfer (sectors) */
-	int	sofar;		/* sectors transferred so far */
-	int	status;
-	int	error;
-	Drive	*dp;		/* drive being accessed */
-};
-
-static int atactlrmask;
-static Controller *atactlr[NCtlr];
-static int atadrivemask;
-static Drive *atadrive[NDrive];
-static int pbase[NCtlr] = {
-	Pbase0, Pbase1, Pbase2, Pbase3,
-};
-static int defirq[NCtlr] = {
-	14, 15, 0, 0,
-};
-
-static void	ataintr(Ureg*, void*);
-static long	ataxfer(Drive*, Partition*, int, ulong, long);
-static int	ataident(Drive*);
-static Drive*	atapart(Drive*);
-static int	ataparams(Drive*);
-static void	atarecal(Drive*);
-static int	ataprobe(Drive*, int, int, int);
-static Drive*	atapipart(Drive*);
-static void	atapiintr(Controller*);
-static long	atapiio(Drive*, long);
-
-static void
-atactlrprobe(int ctlrno, int irq)
-{
-	Controller *ctlr;
-	Drive *drive;
-	int driveno, port;
-
-	if(atactlrmask & (1<<ctlrno))
-		return;
-	atactlrmask |= 1<<ctlrno;
-
-	port = pbase[ctlrno];
-	outb(port+Pdh, DHmagic);
-	delay(1);
-	if((inb(port+Pdh) & 0xFF) != DHmagic){
-		DPRINT("ata%d: DHmagic not ok\n", ctlrno);
-		return;
-	}
-	DPRINT("ata%d: DHmagic ok\n", ctlrno);
-
-	atactlr[ctlrno] = ialloc(sizeof(Controller), 0);
-	ctlr = atactlr[ctlrno];
-	ctlr->pbase = port;
-	ctlr->ctlrno = ctlrno;
-	ctlr->buf = ialloc(Maxxfer, 0);
-	inb(ctlr->pbase+Pstatus);
-	setvec(irq, ataintr, ctlr);
-
-	driveno = ctlrno*2;
-	atadrive[driveno] = ialloc(sizeof(Drive), 0);
-	drive = atadrive[driveno];
-	drive->cp = ctlr;
-	drive->driveno = driveno;
-	drive->dh = DHmagic;
-
-	driveno++;
-	atadrive[driveno] = ialloc(sizeof(Drive), 0);
-	drive = atadrive[driveno];
-	drive->cp = ctlr;
-	drive->driveno = driveno;
-	drive->dh = DHmagic|DHslave;
-}
-
-static Drive*
-atadriveprobe(int driveno)
-{
-	Drive *drive;
-	int ctlrno;
-	ISAConf isa;
-
-	ctlrno = driveno/2;
-	if(atactlr[ctlrno] == 0){
-		if(atactlrmask & (1<<ctlrno))
-			return 0;
-		memset(&isa, 0, sizeof(ISAConf));
-		if(isaconfig("ata", ctlrno, &isa) == 0)
-			return 0;
-		if(ctlrno && isa.irq)
-			atactlrprobe(ctlrno, Int0vec+isa.irq);
-		if(atactlr[ctlrno] == 0)
-			return 0;
-	}
-
-	drive = atadrive[driveno];
-	drive->driveno = driveno;
-	if(drive->online == 0){
-		if(atadrivemask & (1<<driveno))
-			return 0;
-		atadrivemask |= 1<<driveno;
-		if(ataparams(drive))
-			return 0;
-		if(drive->lba)
-			print("hd%d: LBA %lud sectors\n",
-				drive->driveno, drive->cap);
-		else
-			print("hd%d: CHS %ld/%d/%d %lud sectors\n",
-				drive->driveno, drive->cyl, drive->heads,
-				drive->sectors, drive->cap);
-		drive->online = 1;
-	}
-
-	return atapart(drive);
-}
-
-int
-atainit(void)
-{
-	ISAConf isa;
-	int ctlrno;
-
-	for(ctlrno = 0; ctlrno < NCtlr; ctlrno++){
-		memset(&isa, 0, sizeof(ISAConf));
-		if(isaconfig("ata", ctlrno, &isa) == 0 && ctlrno > 1)
-			continue;
-		if(isa.irq == 0 && (isa.irq = defirq[ctlrno]) == 0)
-			continue;
-		atactlrprobe(ctlrno, Int0vec+isa.irq);
-	}
-	DPRINT("atainit: mask 0x%ux 0x%ux\n", atactlrmask, atadrivemask);
-
-	return 0xFF;
-}
-
-long
-ataseek(int driveno, long offset)
-{
-	Drive *drive;
-// more permissive for ide disks
-	drive = atadrive[driveno];
-	if (drive->online == 0)
-		return -1;
-
-// real check was
-//	if((drive = atadriveprobe(driveno)) == 0)
-//		return -1;
-
-	drive->offset = offset;
-	return offset;
-}
-
-/*
- *  did an interrupt happen?
- */
-static void
-atawait(Controller *cp, int timo)
-{
-	ulong start;
-	int x;
-
-	x = spllo();
-	start = m->ticks;
-	while(TK2MS(m->ticks - start) < timo){
-		if(cp->cmd == 0)
-			break;
-		if(cp->cmd == Cident2 && TK2MS(m->ticks - start) >= 1000)
-			break;
-	}
-	if(TK2MS(m->ticks - start) >= timo){
-		DPRINT("atawait timed out 0x%ux\n", inb(cp->pbase+Pstatus));
-		ataintr(0, cp);
-	}
-	splx(x);
-}
-
-int
-setatapart(int driveno, char *p)
-{
-	Partition *pp;
-	Drive *dp;
-
-	if((dp = atadriveprobe(driveno)) == 0)
-		return 0;
-
-	for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
-		if(strcmp(pp->name, p) == 0){
-			dp->current = pp;
-			return 1;
-		}
-	return 0;
-}
-
-long
-ataread(int driveno, void *a, long n)
-{
-	Drive *dp;
-	long rv, i;
-	int skip;
-	uchar *aa = a;
-	Partition *pp;
-	Controller *cp;
-
-// for ide
-	dp = atadrive[ driveno ];
-	if( dp->online == 0 )
-		return 0;
-
-// real code was
-//	if((dp = atadriveprobe(driveno)) == 0)
-//		return 0;
-
-	pp = dp->current;
-//  can ide leave pp as nil?
-//	if(pp == 0)
-//		return -1;
-	cp = dp->cp;
-
-	skip = dp->offset % dp->bytes;
-	for(rv = 0; rv < n; rv += i){
-		i = ataxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip);
-		if(i == 0)
-			break;
-		if(i < 0)
-			return -1;
-		i -= skip;
-		if(i > n - rv)
-			i = n - rv;
-		memmove(aa+rv, cp->buf + skip, i);
-		skip = 0;
-	}
-	dp->offset += rv;
-
-	return rv;
-}
-
-long
-atawrite(int driveno, void *a, long n)
-{
-	Drive *dp;
-	long rv, i, partial;
-	uchar *aa = a;
-	Partition *pp;
-	Controller *cp;
-
-// ide
-	dp = atadrive[ driveno ];
-	if( dp->online == 0 )
-		return 0;
-//	if((dp = atadriveprobe(driveno)) == 0)
-//		return 0;
-
-	pp = dp->current;
-//	if(pp == 0)
-//		return -1;
-	cp = dp->cp;
-
-	/*
-	 *  if not starting on a sector boundary,
-	 *  read in the first sector before writing
-	 *  it out.
-	 */
-	partial = dp->offset % dp->bytes;
-	if(partial){
-		ataxfer(dp, pp, Cread, dp->offset-partial, dp->bytes);
-		if(partial+n > dp->bytes)
-			rv = dp->bytes - partial;
-		else
-			rv = n;
-		memmove(cp->buf+partial, aa, rv);
-		if(ataxfer(dp, pp, Cwrite, dp->offset-partial, dp->bytes) < 0)
-			return -1;
-	} else
-		rv = 0;
-
-	/*
-	 *  write out the full sectors
-	 */
-	partial = (n - rv) % dp->bytes;
-	n -= partial;
-	for(; rv < n; rv += i){
-		i = n - rv;
-		if(i > Maxxfer)
-			i = Maxxfer;
-		memmove(cp->buf, aa+rv, i);
-		i = ataxfer(dp, pp, Cwrite, dp->offset+rv, i);
-		if(i == 0)
-			break;
-		if(i < 0)
-			return -1;
-	}
-
-	/*
-	 *  if not ending on a sector boundary,
-	 *  read in the last sector before writing
-	 *  it out.
-	 */
-	if(partial){
-		if(ataxfer(dp, pp, Cread, dp->offset+rv, dp->bytes) < 0)
-			return -1;
-		memmove(cp->buf, aa+rv, partial);
-		if(ataxfer(dp, pp, Cwrite, dp->offset+rv, dp->bytes) < 0)
-			return -1;
-		rv += partial;
-	}
-	dp->offset += rv;
-	return rv;
-}
-
-/*
- *  wait for the controller to be ready to accept a command
- */
-static int
-cmdreadywait(Drive *drive)
-{
-	ulong end;
-	uchar dh, status;
-	Controller *ctlr;
-
-	ctlr = drive->cp;
-	end = m->ticks+MS2TK(10)+1;
-	dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave);
-	
-	status = 0;
-	while(m->ticks < end){
-		status = inb(ctlr->pbase+Pstatus);
-		if(status & Sbusy)
-			continue;
-		if(dh){
-			outb(ctlr->pbase+Pdh, drive->dh);
-			dh = 0;
-			continue;
-		}
-		if(drive->atapi || (status & Sready))
-			return 0;
-	}
-	USED(status);
-
-	DPRINT("hd%d: cmdreadywait failed 0x%ux\n", drive->driveno, status);
-	outb(ctlr->pbase+Pdh, DHmagic);
-	return -1;
-}
-
-/*
- *  transfer a number of sectors.  ataintr will perform all the iterative
- *  parts.
- */
-static long
-ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len)
-{
-	Controller *cp;
-	long lsec;
-	int loop;
-
-	if(dp->online == 0){
-		DPRINT("hd%d: disk not on line\n", dp->driveno);
-		return -1;
-	}
-
-	/*
-	 *  cut transfer size down to disk buffer size
-	 */
-	start = start / dp->bytes;
-	if(len > Maxxfer)
-		len = Maxxfer;
-	len = (len + dp->bytes - 1) / dp->bytes;
-
-	/*
-	 *  calculate physical address
-	 */
-	cp = dp->cp;
-	if (pp){	// ide did not check; was assumed non-nil by 3rd ed fs.
-		lsec = start + pp->start;
-		if(lsec >= pp->end){
-			DPRINT("hd%d: read past end of partition\n", dp->driveno);
-			return 0;
-		}
-	} else
-		lsec = start;
-
-	if(dp->lba){
-		cp->tsec = lsec & 0xff;
-		cp->tcyl = (lsec>>8) & 0xffff;
-		cp->thead = (lsec>>24) & 0xf;
-	} else {
-		cp->tcyl = lsec/(dp->sectors*dp->heads);
-		cp->tsec = (lsec % dp->sectors) + 1;
-		cp->thead = (lsec/dp->sectors) % dp->heads;
-	}
-
-	/*
-	 *  can't xfer past end of disk
-	 */
-	if (pp) // ide did not check
-	if(lsec+len > pp->end)
-		len = pp->end - lsec;
-	cp->nsecs = len;
-
-	if(dp->atapi){
-		if(cmd == Cread)
-			cp->cmd = Cread2;
-		else
-			cp->cmd = Cwrite2;
-		cp->dp = dp;
-		cp->sofar = 0;
-		cp->status = 0;
-		return atapiio(dp, lsec);
-	}
-
-	if(cmdreadywait(dp) < 0)
-		return -1;
-
-	/*
-	 *  start the transfer
-	 */
-	cp->cmd = cmd;
-	cp->dp = dp;
-	cp->sofar = 0;
-	cp->status = 0;
-	DPRINT("hd%d: xfer:\ttcyl %d, tsec %d, thead %d\n",
-		dp->driveno, cp->tcyl, cp->tsec, cp->thead);
-	DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
-	outb(cp->pbase+Pcount, cp->nsecs);
-	outb(cp->pbase+Psector, cp->tsec);
-	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead);
-	outb(cp->pbase+Pcyllsb, cp->tcyl);
-	outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
-	outb(cp->pbase+Pcmd, cmd);
-
-	if(cmd == Cwrite){
-		loop = 0;
-		while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
-			if(++loop > 10000)
-				panic("ataxfer");
-		outss(cp->pbase+Pdata, cp->buf, dp->bytes/2);
-	}
-
-	atawait(cp, ATAtimo);
-
-	if(cp->status & Serr){
-		DPRINT("hd%d: err: status 0x%ux, err 0x%ux\n",
-			dp->driveno, cp->status, cp->error);
-		DPRINT("\ttcyl %d, tsec %d, thead %d\n",
-			cp->tcyl, cp->tsec, cp->thead);
-		DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
-		return -1;
-	}
-
-	return cp->nsecs*dp->bytes;
-}
-
-static int
-isatapi(Drive *drive)
-{
-	Controller *cp;
-
-	cp = drive->cp;
-	outb(cp->pbase+Pdh, drive->dh);
-	IDPRINT("hd%d: isatapi %d\n", drive->driveno, drive->atapi);
-	outb(cp->pbase+Pcmd, 0x08);
-	drive->atapi = 1;
-	if(cmdreadywait(drive)){
-		drive->atapi = 0;
-		return 0;
-	}
-	drive->atapi = 0;
-	drive->bytes = 512;
-	microdelay(1);
-	if(inb(cp->pbase+Pstatus)){
-		IDPRINT("hd%d: isatapi status 0x%ux\n",
-			drive->driveno, inb(cp->pbase+Pstatus));
-		return 0;
-	}
-	if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14){
-		IDPRINT("hd%d: isatapi cyl 0x%ux 0x%ux\n",
-			drive->driveno, inb(cp->pbase+Pcylmsb), inb(cp->pbase+Pcyllsb));
-		return 0;
-	}
-	drive->atapi = 1;
-
-	return 1;
-}
-
-/*
- *  get parameters from the drive
- */
-static int
-ataident(Drive *dp)
-{
-	Controller *cp;
-	Ident *ip;
-	ulong lbasecs;
-	char id[21];
-
-	dp->bytes = 512;
-	cp = dp->cp;
-
-retryatapi:
-	cp->nsecs = 1;
-	cp->sofar = 0;
-	cp->dp = dp;
-	outb(cp->pbase+Pdh, dp->dh);
-	microdelay(1);
-	if(inb(cp->pbase+Pcylmsb) == 0xEB && inb(cp->pbase+Pcyllsb) == 0x14){
-		dp->atapi = 1;
-		cp->cmd = Cidentd;
-	}
-	else
-		cp->cmd = Cident;
-	outb(cp->pbase+Pcmd, cp->cmd);
-
-	IDPRINT("hd%d: ident command 0x%ux sent\n", dp->driveno, cp->cmd);
-	atawait(cp, ATAPItimo);
-
-	if(cp->status & Serr){
-		IDPRINT("hd%d: bad disk ident status\n", dp->driveno);
-		if(cp->error & Eabort){
-			if(isatapi(dp) && cp->cmd != Cidentd)
-				goto retryatapi;
-		}
-		return -1;
-	}
-	
-	atawait(cp, ATAtimo);
-
-	ip = (Ident*)cp->buf;
-	memmove(id, ip->model, sizeof(id)-1);
-	id[sizeof(id)-1] = 0;
-
-	IDPRINT("hd%d: config 0x%ux capabilities 0x%ux\n",
-		dp->driveno, ip->config, ip->capabilities);
-	if(dp->atapi){
-		if((ip->config & 0x0060) == 0x0020)
-			dp->drqintr = 1;
-		if((ip->config & 0x1F00) == 0x0000)
-			dp->atapi = 2;
-	}
-
-	lbasecs = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16);
-	if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){
-		dp->lba = 1;
-		dp->cap = lbasecs;
-	} else {
-		dp->lba = 0;
-	
-		if(ip->cvalid&(1<<0)){
-			/* use current settings */
-			dp->cyl = ip->ccyls;
-			dp->heads = ip->cheads;
-			dp->sectors = ip->cs2t;
-		}
-		else{
-			/* use default (unformatted) settings */
-			dp->cyl = ip->cyls;
-			dp->heads = ip->heads;
-			dp->sectors = ip->s2t;
-		}
-
-		/*
-		 * Very strange, but some old non-LBA discs report
-		 * sectors > 32.
-		if(dp->heads >= 64 || dp->sectors >= 32)
-			return -1;
-		 */
-		dp->cap = dp->cyl * dp->heads * dp->sectors;
-	}
-	IDPRINT("hd%d: %s  lba/atapi/drqintr: %d/%d/%d  C/H/S: %ld/%d/%d  CAP: %ld\n",
-		dp->driveno, id,
-		dp->lba, dp->atapi, dp->drqintr,
-		dp->cyl, dp->heads, dp->sectors,
-		dp->cap);
-
-	return 0;
-}
-
-/*
- *  probe the given sector to see if it exists
- */
-static int
-ataprobe(Drive *dp, int cyl, int sec, int head)
-{
-	Controller *cp;
-
-	cp = dp->cp;
-	if(cmdreadywait(dp) < 0)
-		return -1;
-
-	/*
-	 *  start the transfer
-	 */
-	cp->cmd = Cread;
-	cp->dp = dp;
-	cp->sofar = 0;
-	cp->nsecs = 1;
-	cp->status = 0;
-	outb(cp->pbase+Pcount, 1);
-	outb(cp->pbase+Psector, sec+1);
-	outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head);
-	outb(cp->pbase+Pcyllsb, cyl);
-	outb(cp->pbase+Pcylmsb, cyl>>8);
-	outb(cp->pbase+Pcmd, Cread);
-
-	atawait(cp, ATAtimo);
-
-	if(cp->status & Serr)
-		return -1;
-
-	return 0;
-}
-
-/*
- *  figure out the drive parameters
- */
-static int
-ataparams(Drive *dp)
-{
-	int i, hi, lo;
-
-	/*
-	 *  first try the easy way, ask the drive and make sure it
-	 *  isn't lying.
-	 */
-	dp->bytes = 512;
-	if(ataident(dp) < 0)
-		return -1;
-	if(dp->atapi)
-		return 0;
-	if(dp->lba){
-		i = dp->cap - 1;
-		if(ataprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0)
-			return 0;
-	} else {
-		if(ataprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
-			return 0;
-	}
-
-	IDPRINT("hd%d: ataparam: cyl %ld sectors %d heads %d\n",
-		dp->driveno, dp->cyl, dp->sectors, dp->heads);
-	/*
-	 *  the drive lied, determine parameters by seeing which ones
-	 *  work to read sectors.
-	 */
-	dp->lba = 0;
-	for(i = 0; i < 16; i++)
-		if(ataprobe(dp, 0, 0, i) < 0)
-			break;
-	dp->heads = i;
-	for(i = 0; i < 64; i++)
-		if(ataprobe(dp, 0, i, 0) < 0)
-			break;
-	dp->sectors = i;
-	for(i = 512; ; i += 512)
-		if(ataprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
-			break;
-	lo = i - 512;
-	hi = i;
-	for(; hi-lo > 1;){
-		i = lo + (hi - lo)/2;
-		if(ataprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
-			hi = i;
-		else
-			lo = i;
-	}
-	dp->cyl = lo + 1;
-	dp->cap = dp->cyl * dp->heads * dp->sectors;
-
-	if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0)
-		return -1;
-
-	return 0;
-}
-
-static Drive*
-atapart(Drive *dp)
-{
-	Partition *pp;
-
-	if(dp->partok)
-		return dp;
-
-	/*
-	 *  we always have a partition for the whole disk
-	 */
-	pp = &dp->p[0];
-	strcpy(pp->name, "disk");
-	dp->npart = 1;
-	pp->start = 0;
-	if(dp->atapi)
-		return atapipart(dp);
-	pp->end = dp->cap;
-	dp->partok = 1;
-
-	return dp;
-}
-
-/*
- *  we get an interrupt for every sector transferred
- */
-static void
-ataintr(Ureg*, void *arg)
-{
-	Controller *cp;
-	Drive *dp;
-	long loop;
-
-	cp = arg;
-	if((dp = cp->dp) == 0)
-		return;
-
-	loop = 0;
-	while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
-		if(++loop > Maxloop){
-			print("hd%d: intr busy: status 0x%ux\n", dp->driveno, cp->status);
-			break;
-		}
-	switch(cp->cmd){
-	case Cwrite:
-		if(cp->status & Serr){
-			cp->error = inb(cp->pbase+Perror);
-			cp->cmd = 0;
-			return;
-		}
-		cp->sofar++;
-		if(cp->sofar < cp->nsecs){
-			loop = 0;
-			while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
-				if(++loop > 10000){
-					print("ataintr 1");
-					cp->cmd = 0;
-					return;
-				}
-			outss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
-				dp->bytes/2);
-		} else{
-			cp->cmd = 0;
-		}
-		break;
-	case Cread:
-	case Cident:
-	case Cidentd:
-		if(cp->status & Serr){
-			cp->cmd = 0;
-			cp->error = inb(cp->pbase+Perror);
-			return;
-		}
-		loop = 0;
-		while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
-			if(++loop > Maxloop){
-				print("hd%d: intr drq: cmd %ux status 0x%ux",
-					dp->driveno, cp->cmd, inb(cp->pbase+Pstatus));
-				cp->cmd = 0;
-				return;
-			}
-		inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
-			dp->bytes/2);
-		cp->sofar++;
-		if(cp->sofar >= cp->nsecs){
-			if(cp->cmd == Cident && (cp->status & Sready) == 0)
-				cp->cmd = Cident2; /* sometimes we get a second intr */
-			else
-				cp->cmd = 0;
-			inb(cp->pbase+Pstatus);
-		}
-		break;
-	case Csetbuf:
-	case Cident2:
-		cp->cmd = 0;
-		break;
-	case Cpktcmd:
-		atapiintr(cp);
-		break;
-	default:
-		cp->cmd = 0;
-		break;
-	}
-}
-
-static int
-atapiexec(Drive *dp)
-{
-	Controller *cp;
-	int loop, s;
-
-	cp = dp->cp;
-
-	if(cmdreadywait(dp))
-		return -1;
-
-	s = splhi();	
-	cp->sofar = 0;
-	cp->error = 0;
-	cp->cmd = Cpktcmd;
-	outb(cp->pbase+Pcount, 0);
-	outb(cp->pbase+Psector, 0);
-	outb(cp->pbase+Pfeature, 0);
-	outb(cp->pbase+Pcyllsb, cp->len);
-	outb(cp->pbase+Pcylmsb, cp->len>>8);
-	outb(cp->pbase+Pdh, dp->dh);
-	outb(cp->pbase+Pcmd, cp->cmd);
-
-	if(dp->drqintr == 0){
-		microdelay(1);
-		for(loop = 0; (inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0; loop++){
-			if(loop < 10000)
-				continue;
-			panic("hd%d: cmddrqwait: cmd=0x%ux status=0x%ux\n",
-				dp->driveno, cp->cmd, inb(cp->pbase+Pstatus));
-		}
-		outss(cp->pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2);
-	}
-	splx(s);
-
-	atawait(cp, ATAPItimo);
-
-	if(cp->status & Serr){
-		DPRINT("hd%d: Bad packet command 0x%ux, error 0x%ux\n",
-			dp->driveno, cp->cmdblk[0], cp->error);
-		return -1;
-	}
-
-	return 0;
-}
-
-static long
-atapiio(Drive *dp, long lba)
-{
-	int n;
-	Controller *cp;
-
-	cp = dp->cp;
-
-	n = cp->nsecs*dp->bytes;
-	cp->len = n;
-	cp->count = 0;
-	memset(cp->cmdblk, 0, 12);
-	cp->cmdblk[0] = cp->cmd;
-	cp->cmdblk[2] = lba >> 24;
-	cp->cmdblk[3] = lba >> 16;
-	cp->cmdblk[4] = lba >> 8;
-	cp->cmdblk[5] = lba;
-	cp->cmdblk[7] = cp->nsecs>>8;
-	cp->cmdblk[8] = cp->nsecs;
-	if(atapiexec(dp))
-		return -1;
-	if(cp->count != n)
-		print("hd%d: short read %d != %d\n", dp->driveno, cp->count, n);
-
-	return n;
-}
-
-static Drive*
-atapipart(Drive *dp)
-{
-	Controller *cp;
-	Partition *pp;
-	int retrycount;
-
-	cp = dp->cp;
-
-	pp = &dp->p[0];
-	pp->end = 0;
-
-	retrycount = 0;
-retry:
-	if(retrycount++){
-		IDPRINT("hd%d: atapipart: cmd 0x%ux error 0x%ux, retry %d\n",
-			dp->driveno, cp->cmdblk[0], cp->error, retrycount);
-		if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){
-			dp->vers++;
-			if(retrycount < 3)
-				goto again;
-		}
-		cp->dp = 0;
-		IDPRINT("hd%d: atapipart: cmd %ux return error %ux, retry %d\n",
-			dp->driveno, cp->cmd, cp->error, retrycount);
-		return 0;
-	}
-again:
-	cp->dp = dp;
-
-	cp->len = 18;
-	cp->count = 0;
-	memset(cp->cmdblk, 0, sizeof(cp->cmdblk));
-	cp->cmdblk[0] = Creqsense;
-	cp->cmdblk[4] = 18;
-	DPRINT("reqsense %d\n", retrycount);
-	atapiexec(dp);
-	//if(atapiexec(dp))
-	//	goto retry;
-	if(cp->count != 18){
-		print("cmd=0x%2.2ux, lastcmd=0x%2.2ux ", cp->cmd, cp->lastcmd);
-		print("cdsize count %d, status 0x%2.2ux, error 0x%2.2ux\n",
-			cp->count, cp->status, cp->error);
-		return 0;
-	}
-
-	cp->len = 8;
-	cp->count = 0;
-	memset(cp->cmdblk, 0, sizeof(cp->cmdblk));
-	cp->cmdblk[0] = Ccapacity;
-	DPRINT("capacity %d\n", retrycount);
-	if(atapiexec(dp))
-		goto retry;
-	if(cp->count != 8){
-		print("cmd=0x%2.2ux, lastcmd=0x%2.2ux ", cp->cmd, cp->lastcmd);
-		print("cdsize count %d, status 0x%2.2ux, error 0x%2.2ux\n",
-			cp->count, cp->status, cp->error);
-		return 0;
-	}
-	dp->sectors = (cp->buf[0]<<24)|(cp->buf[1]<<16)|(cp->buf[2]<<8)|cp->buf[3];
-	dp->bytes = (cp->buf[4]<<24)|(cp->buf[5]<<16)|(cp->buf[6]<<8)|cp->buf[7];
-	if(dp->bytes > 2048 && dp->bytes <= 2352)
-		dp->bytes = 2048;
-	dp->cap = dp->sectors;
-	IDPRINT("hd%d: atapipart secs %ud, bytes %ud, cap %lud\n",
-		dp->driveno, dp->sectors, dp->bytes, dp->cap);
-	cp->dp = 0;
-
-	pp->end = dp->sectors;
-	dp->partok = 1;
-
-	return dp;
-}
-
-static void
-atapiintr(Controller *cp)
-{
-	uchar cause;
-	int count, loop, pbase;
-
-	pbase = cp->pbase;
-	cause = inb(pbase+Pcount) & 0x03;
-	DPRINT("hd%d: atapiintr 0x%ux\n", cp->dp->driveno, cause);
-	switch(cause){
-
-	case 1:						/* command */
-		if(cp->status & Serr){
-			cp->lastcmd = cp->cmd;
-			cp->cmd = 0;
-			cp->error = inb(pbase+Perror);
-			break;
-		}
-		outss(pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2);
-		break;
-
-	case 0:						/* data out */
-	case 2:						/* data in */
-		if(cp->buf == 0){
-			cp->lastcmd = cp->cmd;
-			cp->cmd = 0;
-			if(cp->status & Serr)
-				cp->error = inb(pbase+Perror);
-			cp->cmd = 0;
-			break;	
-		}
-		loop = 0;
-		while((cp->status & (Serr|Sdrq)) == 0){
-			if(++loop > Maxloop){
-				cp->status |= Serr;
-				break;
-			}
-			cp->status = inb(pbase+Pstatus);
-		}
-		if(cp->status & Serr){
-			cp->lastcmd = cp->cmd;
-			cp->cmd = 0;
-			cp->error = inb(pbase+Perror);
-			print("hd%d: Cpktcmd status=0x%ux, error=0x%ux\n",
-				cp->dp->driveno, cp->status, cp->error);
-			break;
-		}
-		count = inb(pbase+Pcyllsb)|(inb(pbase+Pcylmsb)<<8);
-		if(cp->count+count > Maxxfer)
-			panic("hd%d: count %d, already %d\n", count, cp->count);
-		if(cause == 0)
-			outss(pbase+Pdata, cp->buf+cp->count, count/2);
-		else
-			inss(pbase+Pdata, cp->buf+cp->count, count/2);
-		cp->count += count;
-		break;
-
-	case 3:						/* status */
-		cp->lastcmd = cp->cmd;
-		cp->cmd = 0;
-		if(cp->status & Serr)
-			cp->error = inb(cp->pbase+Perror);
-		break;
-	}
-}
-
-ideread( Device *d, long b, void *c )
-{
-	Drive	*dp;
-	Controller	*cp;
-	int		x;
-
-	dp = d->private;
-	cp = dp->cp;
-
-	qlock( cp );
-
-	DPRINT("ideread(dev %x, %ld, %x, %d): %x\n"
-		, d, b, c, dp->driveno, dp );
-	ataseek( dp->driveno, b * RBUFSIZE );
-	x = ataread( dp->driveno, c, RBUFSIZE )==0;
-	qunlock( cp );
-
-	return x;
-}
-
-idewrite( Device *d, long b, void *c)
-{
-	Drive	*dp;
-	Controller	*cp;
-	int	x;
-
-	dp = d->private;
-	cp = dp->cp;
-
-	qlock( cp );
-
-	DPRINT("idewrite(%x, %ld, %x): driveno %d\n", d, b, c, dp->driveno );
-	ataseek( dp->driveno, b * RBUFSIZE );
-	x = atawrite( dp->driveno, c, RBUFSIZE )==0;
-	qunlock( cp );
-
-	return x;
-}
-
-long	atasize( Device *d )
-{
-	Drive	*dp;
-
-	dp = d->private;
-	DPRINT("atasize(%x):  %uld -> %uld\n", d, dp->cap, dp->cap / RBUFSIZE * 512);
-	return (dp->cap / RBUFSIZE * 512);
-}
-
-void	ideinit( Device *d )
-{	
-	Drive	*dp;
-
-	if( d->private )
-		return;
-
-	if( (dp = atadriveprobe( d->wren.ctrl * 2 + d->wren.targ ) ) )	{
-		DPRINT("ideinit( device %x ctrl %d targ %d ) driveno %d dp %x\n"
-			, d, d->wren.ctrl, d->wren.targ, dp->driveno, dp );
-		d->private = dp;
-	}
-}
//GO.SYSIN DD plan9pc/devata.c
echo plan9pc/fns.h
sed 's/.//' >plan9pc/fns.h <<'//GO.SYSIN DD plan9pc/fns.h'
-ulong	strtoul(char*, char**, int);
-
-#include "../port/portfns.h"
-
-void	aamloop(int);
-void	cgaputc(int);
-void	cgaputs(char*, int);
-int	cistrcmp(char*, char*);
-int	cistrncmp(char*, char*, int);
-void	(*coherence)(void);
-void	etherinit(void);
-void	etherstart(void);
-int	floppyinit(void);
-void	floppyproc(void);
-long	floppyread(int, void*, long);
-long	floppyseek(int, long);
-long	floppywrite(int, void*, long);
-char*	getconf(char*);
-ulong	getcr0(void);
-ulong	getcr2(void);
-ulong	getcr4(void);
-int	getfields(char*, char**, int, char);
-ulong	getstatus(void);
-int	atainit(void);
-long	ataread(int, void*, long);
-long	ataseek(int, long);
-long	atawrite(int, void*, long);
-void	i8042a20(void);
-void	i8042reset(void);
-int	inb(int);
-void	insb(int, void*, int);
-ushort	ins(int);
-void	inss(int, void*, int);
-ulong	inl(int);
-void	insl(int, void*, int);
-int	isaconfig(char*, int, ISAConf*);
-void	kbdinit(void);
-int	kbdintr0(void);
-int	kbdgetc(void);
-long*	mapaddr(ulong);
-void	microdelay(int);
-void	mmuinit(void);
-uchar	nvramread(int);
-void	outb(int, int);
-void	outsb(int, void*, int);
-void	outs(int, ushort);
-void	outss(int, void*, int);
-void	outl(int, ulong);
-void	outsl(int, void*, int);
-int	pcicfgr8(Pcidev*, int);
-int	pcicfgr16(Pcidev*, int);
-int	pcicfgr32(Pcidev*, int);
-void	pcicfgw8(Pcidev*, int, int);
-void	pcicfgw16(Pcidev*, int, int);
-void	pcicfgw32(Pcidev*, int, int);
-void	pcihinv(Pcidev*);
-Pcidev* pcimatch(Pcidev*, int, int);
-Pcidev* pcimatchtbdf(int);
-void	pcireset(void);
-void	pcisetbme(Pcidev*);
-void	printcpufreq(void);
-void	putgdt(Segdesc*, int);
-void	putidt(Segdesc*, int);
-void	putcr3(ulong);
-void	putcr4(ulong);
-void	puttr(ulong);
-void	rdmsr(int, vlong*);
-void	scsiinit(void);
-long	scsiread(int, void*, long);
-long	scsiseek(int, long);
-long	scsiwrite(int, void*, long);
-int	setatapart(int, char*);
-int	setscsipart(int, char*);
-void	setvec(int, void (*)(Ureg*, void*), void*);
-int	tas(Lock*);
-void	trapinit(void);
-void	uartspecial(int, void (*)(int), int (*)(void), int);
-int	uartgetc(void);
-void	uartputc(int);
-void	wbflush(void);
-void	cpuid(char*, int*, int*);
-#define PADDR(a)	((ulong)(a)&~KZERO)
-
-void	ideinit(Device *d);
-int	ideread(Device *d, long,  void*);
-int idewrite(Device *d, long, void*);
-long	atasize(Device *d);
-void	atainitstub(Device *d);
//GO.SYSIN DD plan9pc/fns.h
echo port/config.c
sed 's/.//' >port/config.c <<'//GO.SYSIN DD port/config.c'
-#include	"all.h"
-#include	"io.h"
-
-struct
-{
-	char*	icharp;
-	char*	charp;
-	int	error;
-	int	newconf;	/* clear befor start */
-	int	modconf;	/* write back when done */
-	int	nextiter;
-	int	lastiter;
-	int	diriter;
-	int	ipauthset;
-	Device*	lastcw;
-	Device*	devlist;
-} f;
-
-int
-devcmpr(Device *d1, Device *d2)
-{
-
-loop:
-	if(d1 == d2)
-		return 0;
-	if(d1 == 0 || d2 == 0 || d1->type != d2->type)
-		return 1;
-
-	switch(d1->type) {
-	default:
-		print("cant compare dev: %D\n", d1);
-		panic("devcmp");
-		break;
-
-	case Devmcat:
-	case Devmlev:
-		d1 = d1->cat.first;
-		d2 = d2->cat.first;
-		while(d1 && d2) {
-			if(devcmpr(d1, d2))
-				return 1;
-			d1 = d1->link;
-			d2 = d2->link;
-		}
-		goto loop;
-
-	case Devnone:
-		return 0;
-
-	case Devro:
-		d1 = d1->ro.parent;
-		d2 = d2->ro.parent;
-		goto loop;
-
-	case Devjuke:
-	case Devcw:
-		if(devcmpr(d1->cw.c, d2->cw.c))
-			break;
-		d1 = d1->cw.w;
-		d2 = d2->cw.w;
-		goto loop;
-
-	case Devfworm:
-		d1 = d1->fw.fw;
-		d2 = d2->fw.fw;
-		goto loop;
-
-	case Devwren:
-	case Devworm:
-	case Devlworm:
-	case Devide:
-		if(d1->wren.ctrl == d2->wren.ctrl)
-		if(d1->wren.targ == d2->wren.targ)
-		if(d1->wren.lun == d2->wren.lun)
-			return 0;
-		break;
-
-	case Devpart:
-		if(d1->part.base == d2->part.base)
-		if(d1->part.size == d2->part.size) {
-			d1 = d1->part.d;
-			d2 = d2->part.d;
-			goto loop;
-		}
-		break;
-	}
-	return 1;
-}
-
-void
-cdiag(char *s, int c1)
-{
-
-	f.charp--;
-	if(f.error == 0) {
-		print("config diag: %s -- <%c>\n", s, c1);
-		f.error = 1;
-	}
-}
-
-int
-cnumb(void)
-{
-	int c, n;
-
-	c = *f.charp++;
-	if(c == '<') {
-		n = f.nextiter;
-		if(n >= 0) {
-			f.nextiter = n+f.diriter;
-			if(n == f.lastiter) {
-				f.nextiter = -1;
-				f.lastiter = -1;
-			}
-			for(;;) {
-				c = *f.charp++;
-				if(c == '>')
-					break;
-			}
-			return n;
-		}
-		n = cnumb();
-		if(*f.charp++ != '-') {
-			cdiag("- expected", f.charp[-1]);
-			return 0;
-		}
-		c = cnumb();
-		if(*f.charp++ != '>') {
-			cdiag("> expected", f.charp[-1]);
-			return 0;
-		}
-		f.lastiter = c;
-		f.diriter = 1;
-		if(n > c)
-			f.diriter = -1;
-		f.nextiter = n+f.diriter;
-		return n;
-	}
-	if(c < '0' || c > '9') {
-		cdiag("number expected", c);
-		return 0;
-	}
-	n = 0;
-	while(c >= '0' && c <= '9') {
-		n = n*10 + (c-'0');
-		c = *f.charp++;
-	}
-	f.charp--;
-	return n;
-}
-
-Device*
-config1(int c)
-{
-	Device *d, *t;
-	int m;
-
-	d = ialloc(sizeof(Device), 0);
-	for(;;) {
-		t = config();
-		if(d->cat.first == 0)
-			d->cat.first = t;
-		else
-			d->cat.last->link = t;
-		d->cat.last = t;
-		if(f.error)
-			goto bad;
-		m = *f.charp;
-		if(c == '(' && m == ')') {
-			d->type = Devmcat;
-			break;
-		}
-		if(c == '[' && m == ']') {
-			d->type = Devmlev;
-			break;
-		}
-	}
-	f.charp++;
-	if(d->cat.first == d->cat.last)
-		d = d->cat.first;
-	return d;
-
-bad:
-	return devnone;
-}
-
-Device*
-config(void)
-{
-	int c, m;
-	Device *d;
-	char *icp;
-
-	if(f.error)
-		goto bad;
-	d = ialloc(sizeof(Device), 0);
-
-	c = *f.charp++;
-	switch(c) {
-	default:
-		cdiag("unknown type", c);
-		goto bad;
-
-	case '(':	/* (d+) one or multiple cat */
-	case '[':	/* [d+] one or multiple interleave */
-		return config1(c);
-
-	case 'f':	/* fd fake worm */
-		d->type = Devfworm;
-		d->fw.fw = config();
-		break;
-
-	case 'n':
-		d->type = Devnone;
-		break;
-
-	case 'w':	/* w[#.]# wren [ctrl] unit [part] */
-	case 'r':	/* r[#.]#[.#] worm [ctrl] unit [part] */
-	case 'l':	/* r[#.]#[.#] worm [ctrl] unit [part] */
-	case 'h':	/* h[#.]# ide [ctlr] unit [part] */
-		icp = f.charp;
-		d->type = Devwren;
-		if(c == 'h')
-			d->type = Devide;
-		else
-			d->type = Devwren;
-		d->wren.ctrl = 0;
-		d->wren.targ = cnumb();
-		d->wren.lun = 0;
-		m = *f.charp;
-		if(m == '.') {
-			f.charp++;
-			d->wren.lun = cnumb();
-			m = *f.charp;
-			if(m == '.') {
-				f.charp++;
-				d->wren.ctrl = d->wren.targ;
-				d->wren.targ = d->wren.lun;
-				d->wren.lun = cnumb();
-			}
-		}
-		if(f.nextiter >= 0)
-			f.charp = icp-1;
-		if(c == 'r') {	/* worms are virtual and not uniqued */
-			d->type = Devworm;
-			break;
-		}
-		if(c == 'l') {
-			d->type = Devlworm;
-			break;
-		}
-		break;
-
-	case 'o':	/* o ro part of last cw */
-		if(f.lastcw == 0) {
-			cdiag("no cw to match", c);
-			goto bad;
-		}
-		return f.lastcw->cw.ro;
-
-	case 'j':	/* DD jukebox */
-		d->type = Devjuke;
-		d->j.j = config();
-		d->j.m = config();
-		break;
-
-	case 'c':	/* cache/worm */
-		d->type = Devcw;
-		d->cw.c = config();
-		d->cw.w = config();
-		d->cw.ro = ialloc(sizeof(Device), 0);
-		d->cw.ro->type = Devro;
-		d->cw.ro->ro.parent = d;
-		f.lastcw = d;
-		break;
-
-	case 'p':	/* pd#.# partition base% size% */
-		d->type = Devpart;
-		d->part.d = config();
-		d->part.base = cnumb();
-		c = *f.charp++;
-		if(c != '.')
-			cdiag("dot expected", c);
-		d->part.size = cnumb();
-		break;
-
-	case 'x':	/* xD swab a device */
-		d->type = Devswab;
-		d->swab.d = config();
-		break;
-	}
-	d->dlink = f.devlist;
-	f.devlist = d;
-	return d;
-
-bad:
-	return devnone;
-}
-
-char*
-strdup(char *s)
-{
-	int n;
-	char *s1;
-
-	n = strlen(s);
-	s1 = ialloc(n+1, 0);
-	strcpy(s1, s);
-	return s1;
-}
-
-Device*
-iconfig(char *s)
-{
-	Device *d;
-
-	f.nextiter = -1;
-	f.lastiter = -1;
-	f.error = 0;
-	f.icharp = s;
-	f.charp = f.icharp;
-	d = config();
-	if(*f.charp) {
-		cdiag("junk on end", *f.charp);
-		f.error = 1;
-	}
-	return d;
-}
-
-int
-testconfig(char *s)
-{
-
-	iconfig(s);
-	return f.error;
-}
-
-int
-astrcmp(char *a, char *b)
-{
-	int n, c;
-
-	n = strlen(b);
-	if(memcmp(a, b, n))
-		return 1;
-	c = a[n];
-	if(c == 0) {
-		aindex = 0;
-		return 0;
-	}
-	if(a[n+1])
-		return 1;
-	if(c >= '0' && c <= '9') {
-		aindex = c - '0';
-		return 0;
-	}
-	return 1;
-}
-
-void
-mergeconf(Iobuf *p)
-{
-	char word[100];
-	char *cp;
-	Filsys *fs;
-
-	cp = p->iobuf;
-	goto line;
-
-loop:
-	if(*cp != '\n')
-		goto bad;
-	cp++;
-
-line:
-	cp = getwd(word, cp);
-	if(strcmp(word, "") == 0)
-		return;
-	if(strcmp(word, "service") == 0) {
-		cp = getwd(word, cp);
-		if(service[0] == 0)
-			strcpy(service, word);
-		goto loop;
-	}
-	if(strcmp(word, "ipauth") == 0) {
-		cp = getwd(word, cp);
-		if(!f.ipauthset)
-			if(chartoip(authip, word))
-				goto bad;
-		goto loop;
-	}
-	if(astrcmp(word, "ip") == 0) {
-		cp = getwd(word, cp);
-		if(!nzip(ipaddr[aindex].sysip))
-			if(chartoip(ipaddr[aindex].sysip, word))
-				goto bad;
-		goto loop;
-	}
-	if(astrcmp(word, "ipgw") == 0) {
-		cp = getwd(word, cp);
-		if(!nzip(ipaddr[aindex].defgwip))
-			if(chartoip(ipaddr[aindex].defgwip, word))
-				goto bad;
-		goto loop;
-	}
-	if(astrcmp(word, "ipsntp") == 0) {
-		cp = getwd(word, cp);
-		if (!nzip(sntpip))
-			if (chartoip(sntpip, word))
-				goto bad;
-		goto loop;
-	}
-	if(astrcmp(word, "ipmask") == 0) {
-		cp = getwd(word, cp);
-		if(!nzip(ipaddr[aindex].defmask))
-			if(chartoip(ipaddr[aindex].defmask, word))
-				goto bad;
-		goto loop;
-	}
-	if(strcmp(word, "filsys") == 0) {
-		cp = getwd(word, cp);
-		for(fs=filsys; fs->name; fs++)
-			if(strcmp(fs->name, word) == 0) {
-				if(fs->flags & FEDIT) {
-					cp = getwd(word, cp);
-					goto loop;
-				}
-				break;
-			}
-		fs->name = strdup(word);
-		cp = getwd(word, cp);
-		fs->conf = strdup(word);
-		goto loop;
-	}
-	goto bad;
-
-bad:
-	putbuf(p);
-	panic("unknown word in config block: %s", word);
-}
-
-void
-sysinit(void)
-{
-	Filsys *fs;
-	int error, i;
-	Device *d;
-	Iobuf *p;
-
-	dofilter(u->time+0, C0a, C0b, 1);
-	dofilter(u->time+1, C1a, C1b, 1);
-	dofilter(u->time+2, C2a, C2b, 1);
-	dofilter(cons.work+0, C0a, C0b, 1);
-	dofilter(cons.work+1, C1a, C1b, 1);
-	dofilter(cons.work+2, C2a, C2b, 1);
-	dofilter(cons.rate+0, C0a, C0b, 1000);
-	dofilter(cons.rate+1, C1a, C1b, 1000);
-	dofilter(cons.rate+2, C2a, C2b, 1000);
-	dofilter(cons.bhit+0, C0a, C0b, 1);
-	dofilter(cons.bhit+1, C1a, C1b, 1);
-	dofilter(cons.bhit+2, C2a, C2b, 1);
-	dofilter(cons.bread+0, C0a, C0b, 1);
-	dofilter(cons.bread+1, C1a, C1b, 1);
-	dofilter(cons.bread+2, C2a, C2b, 1);
-	dofilter(cons.brahead+0, C0a, C0b, 1);
-	dofilter(cons.brahead+1, C1a, C1b, 1);
-	dofilter(cons.brahead+2, C2a, C2b, 1);
-	dofilter(cons.binit+0, C0a, C0b, 1);
-	dofilter(cons.binit+1, C1a, C1b, 1);
-	dofilter(cons.binit+2, C2a, C2b, 1);
-	cons.chan = chaninit(Devcon, 1);
-
-start:
-	/*
-	 * part 1 -- read the config file
-	 */
-	devnone = iconfig("n");
-
-	print("config %s\n", nvr.config);
-
-	d = iconfig(nvr.config);
-	devinit(d);
-	if(f.newconf) {
-		p = getbuf(d, 0, Bmod);
-		memset(p->iobuf, 0, RBUFSIZE);
-		settag(p, Tconfig, 0);
-	} else
-		p = getbuf(d, 0, Bread|Bmod);
-	if(!p || checktag(p, Tconfig, 0))
-		panic("config io");
-	mergeconf(p);
-	if(f.modconf) {
-		memset(p->iobuf, 0, BUFSIZE);
-		p->flags |= Bmod|Bimm;
-		if(service[0])
-			sprint(strchr(p->iobuf, 0), "service %s\n", service);
-		for(fs=filsys; fs->name; fs++)
-			if(fs->conf)
-				sprint(strchr(p->iobuf, 0),
-					"filsys %s %s\n", fs->name, fs->conf);
-		sprint(strchr(p->iobuf, 0), "ipauth %I\n", authip);
-		sprint(strchr(p->iobuf, 0), "ipsntp %I\n", sntpip);
-		for(i=0; i<10; i++) {
-			sprint(strchr(p->iobuf, 0),
-				"ip%d %I\n", i, ipaddr[i].sysip);
-			sprint(strchr(p->iobuf, 0),
-				"ipgw%d %I\n", i, ipaddr[i].defgwip);
-			sprint(strchr(p->iobuf, 0),
-				"ipmask%d %I\n", i, ipaddr[i].defmask);
-		}
-		putbuf(p);
-		f.modconf = 0;
-		f.newconf = 0;
-		print("config block written\n");
-		goto start;
-	}
-	putbuf(p);
-
-	print("service    %s\n", service);
-	print("ipauth  %I\n", authip);
-	print("ipsntp  %I\n", sntpip);
-	for(i=0; i<10; i++) {
-		if(nzip(ipaddr[i].sysip)) {
-			print("ip%d     %I\n", i, ipaddr[i].sysip);
-			print("ipgw%d   %I\n", i, ipaddr[i].defgwip);
-			print("ipmask%d %I\n", i, ipaddr[i].defmask);
-		}
-	}
-
-loop:
-	/*
-	 * part 2 -- squeeze out the deleted filesystems
-	 */
-	for(fs=filsys; fs->name; fs++)
-		if(fs->conf == 0) {
-			for(; fs->name; fs++)
-				*fs = *(fs+1);
-			goto loop;
-		}
-	if(filsys[0].name == 0)
-		panic("no filsys");
-
-	/*
-	 * part 3 -- compile the device expression
-	 */
-	error = 0;
-	for(fs=filsys; fs->name; fs++) {
-		print("filsys %s %s\n", fs->name, fs->conf);
-		fs->dev = iconfig(fs->conf);
-		if(f.error) {
-			error = 1;
-			continue;
-		}
-	}
-	if(error)
-		panic("fs config");
-
-	/*
-	 * part 4 -- initialize the devices
-	 */
-	for(fs=filsys; fs->name; fs++) {
-		print("sysinit: %s\n", fs->name);
-		if(fs->flags & FREAM)
-			devream(fs->dev, 1);
-		if(fs->flags & FRECOVER)
-			devrecover(fs->dev);
-		devinit(fs->dev);
-	}
-}
-
-void
-getline(char *line)
-{
-	char *p;
-	int c;
-
-	p = line;
-	for(;;) {
-		c = rawchar(0);
-		if(c == 0 || c == '\n') {
-			*p = 0;
-			return;
-		}
-		if(c == '\b') {
-			p--;
-			continue;
-		}
-		*p++ = c;
-	}
-}
-
-void
-arginit(void)
-{
-	int verb, c;
-	char line[300], word[300], *cp;
-	uchar localip[Pasize];
-	Filsys *fs;
-	uchar csum;
-
-	print("nvr read\n");
-	nvread(NVRAUTHADDR, &nvr, sizeof(nvr));
-	csum = nvcsum(nvr.authkey, sizeof(nvr.authkey));
-	if(csum != nvr.authsum) {
-		print("\n\n ** NVR key checksum is incorrect  **\n");
-		print(" ** set password to allow attaches **\n\n");
-		memset(nvr.authkey, 0, sizeof(nvr.authkey));
-		goto loop;
-	}
-	csum = nvcsum(nvr.config, sizeof(nvr.config));
-	if(csum != nvr.configsum) {
-		print("\n\n ** NVR config checksum is incorrect  **\n");
-		memset(nvr.config, 0, sizeof(nvr.config));
-		goto loop;
-	}
-
-	print("for config mode hit a key within 5 seconds\n");
-	c = rawchar(5);
-	if(c == 0) {
-		print("	no config\n");
-		return;
-	}
-
-loop:
-	print("config: ");
-	getline(line);
-	cp = getwd(word, line);
-	if(strcmp(word, "end") == 0)
-		return;
-	if(strcmp(word, "halt") == 0)
-		exit();
-
-	if(strcmp(word, "allow") == 0) {
-		wstatallow = 1;
-		writeallow = 1;
-		goto loop;
-	}
-
-	if(strcmp(word, "noauth") == 0) {
-		noauth = !noauth;
-		goto loop;
-	}
-	if(strcmp(word, "noattach") == 0) {
-		noattach = !noattach;
-		goto loop;
-	}
-	if(strcmp(word, "ream") == 0) {
-		verb = FREAM;
-		goto gfsname;
-	}
-	if(strcmp(word, "recover") == 0) {
-		verb = FRECOVER;
-		goto gfsname;
-	}
-	if(strcmp(word, "filsys") == 0) {
-		verb = FEDIT;
-		goto gfsname;
-	}
-	if(strcmp(word, "nvram") == 0) {
-		getwd(word, cp);
-		if(testconfig(word))
-			goto loop;
-		c = strlen(word);
-		if(c >= sizeof(nvr.config)) {
-			print("config string too long\n");
-			goto loop;
-		}
-		memset(nvr.config, 0, sizeof(nvr.config));
-		memmove(nvr.config, word, c);
-		nvr.configsum = nvcsum(nvr.config, sizeof(nvr.config));
-		nvwrite(NVRAUTHADDR, &nvr, sizeof(nvr));
-		goto loop;
-	}
-	if(strcmp(word, "config") == 0) {
-		getwd(word, cp);
-		if(testconfig(word))
-			goto loop;
-		c = strlen(word);
-		if(c >= sizeof(nvr.config)) {
-			print("config string too long\n");
-			goto loop;
-		}
-		memset(nvr.config, 0, sizeof(nvr.config));
-		memmove(nvr.config, word, c);
-		nvr.configsum = nvcsum(nvr.config, sizeof(nvr.config));
-		nvwrite(NVRAUTHADDR, &nvr, sizeof(nvr));
-		f.newconf = 1;
-		goto loop;
-	}
-	if(strcmp(word, "service") == 0) {
-		getwd(word, cp);
-		strcpy(service, word);
-		f.modconf = 1;
-		goto loop;
-	}
-	if(strcmp(word, "ipauth") == 0) {
-		f.ipauthset = 1;
-		verb = 2;
-		goto ipname;
-	}
-	if(astrcmp(word, "ip") == 0) {
-		verb = 0;
-		goto ipname;
-	}
-	if(astrcmp(word, "ipgw") == 0) {
-		verb = 1;
-		goto ipname;
-	}
-	if(astrcmp(word, "ipmask") == 0) {
-		verb = 3;
-		goto ipname;
-	}
-	if(astrcmp(word, "ipsntp") == 0) {
-		verb = 4;
-		goto ipname;
-	}
-	print("unknown config command\n");
-	print("	type end to get out\n");
-	goto loop;
-
-ipname:
-	getwd(word, cp);
-	if(chartoip(localip, word)) {
-		print("bad ip address\n");
-		goto loop;
-	}
-	switch(verb) {
-	case 0:
-		memmove(ipaddr[aindex].sysip, localip,
-			sizeof(ipaddr[aindex].sysip));
-		break;
-	case 1:
-		memmove(ipaddr[aindex].defgwip, localip,
-			sizeof(ipaddr[aindex].defgwip));
-		break;
-	case 2:
-		memmove(authip, localip,
-			sizeof(authip));
-		break;
-	case 3:
-		memmove(ipaddr[aindex].defmask, localip,
-			sizeof(ipaddr[aindex].defmask));
-		break;
-	case 4:
-		memmove(sntpip, localip,
-			sizeof(sntpip));
-		break;
-	}
-	f.modconf = 1;
-	goto loop;
-
-gfsname:
-	cp = getwd(word, cp);
-	for(fs=filsys; fs->name; fs++)
-		if(strcmp(word, fs->name) == 0)
-			goto found;
-	memset(fs, 0, sizeof(*fs));
-	fs->name = strdup(word);
-
-found:
-	switch(verb) {
-	case FREAM:
-		if(strcmp(fs->name, "main") == 0)
-			wstatallow = 1;		/* only set, never reset */
-	case FRECOVER:
-		fs->flags |= verb;
-		goto loop;
-	case FEDIT:
-		f.modconf = 1;
-		getwd(word, cp);
-		fs->flags |= verb;
-		if(word[0] == 0) {
-			fs->conf = 0;
-			goto loop;
-		}
-		if(testconfig(word))
-			goto loop;
-		fs->conf = strdup(word);
-		goto loop;
-	}
-}
//GO.SYSIN DD port/config.c
echo port/main.c
sed 's/.//' >port/main.c <<'//GO.SYSIN DD port/main.c'
-#include	"all.h"
-#include	"mem.h"
-#include	"io.h"
-#include	"ureg.h"
-
-void
-machinit(void)
-{
-	int n;
-
-	n = m->machno;
-	memset(m, 0, sizeof(Mach));
-	m->machno = n;
-	m->mmask = 1<<m->machno;
-	m->lights = 0;
-
-	active.exiting = 0;
-	active.machs = 1;
-}
-
-static
-void
-confinit(void)
-{
-	conf.nmach = 1;
-	conf.nproc = 50;
-
-	conf.mem = meminit();
-	conf.sparemem = conf.mem/12;		/* 8% spare for chk etc */
-
-	conf.nalarm = 200;
-	conf.nuid = 1000;
-	conf.nserve = 15;
-	conf.nfile = 30000;
-	conf.nlgmsg = 100;
-	conf.nsmmsg = 500;
-	conf.wcpsize = 1024*1024;
-	localconfinit();
-
-	conf.nwpath = conf.nfile*8;
-	conf.gidspace = conf.nuid*3;
-
-	cons.flags = 0;
-}
-
-void
-main(void)
-{
-	int i;
-
-	echo = 1;
-	predawn = 1;
-		formatinit();
-		machinit();
-		vecinit();
-		confinit();
-		lockinit();
-		printinit();
-		procinit();
-		clockinit();
-		alarminit();
-
-		mainlock.wr.name = "mainr";
-		mainlock.rd.name = "mainw";
-		reflock.name = "ref";
-
-		qlock(&reflock);
-		qunlock(&reflock);
-		serveq = newqueue(1000);
-		raheadq = newqueue(1000);
-		authreply = newqueue(Nqueue);
-
-		mbinit();
-
-		sntpinit();
-		otherinit();
-
-		files = ialloc(conf.nfile * sizeof(*files), 0);
-		for(i=0; i<conf.nfile; i++) {
-			qlock(&files[i]);
-			files[i].name = "file";
-			qunlock(&files[i]);
-		}
-
-		wpaths = ialloc(conf.nwpath * sizeof(*wpaths), 0);
-		uid = ialloc(conf.nuid * sizeof(*uid), 0);
-		gidspace = ialloc(conf.gidspace * sizeof(*gidspace), 0);
-
-		print("iobufinit\n");
-		iobufinit();
-
-		arginit();
-
-		userinit(touser, 0, "ini");
-
-	predawn = 0;
-		launchinit();
-		schedinit();
-}
-
-/*
- * read ahead processes.
- * read message from q and then
- * read the device.
- */
-int
-rbcmp(void *va, void *vb)
-{
-	Rabuf *ra, *rb;
-
-	ra = *(Rabuf**)va;
-	rb = *(Rabuf**)vb;
-	if(rb == 0)
-		return 1;
-	if(ra == 0)
-		return -1;
-	if(ra->dev > rb->dev)
-		return 1;
-	if(ra->dev < rb->dev)
-		return -1;
-	if(ra->addr > rb->addr)
-		return 1;
-	if(ra->addr < rb->addr)
-		return -1;
-	return 0;
-}
-
-void
-rahead(void)
-{
-	Rabuf *rb[50];
-	Iobuf *p;
-	int i, n;
-
-loop:
-	rb[0] = recv(raheadq, 0);
-	for(n=1; n<nelem(rb); n++) {
-		if(raheadq->count <= 0)
-			break;
-		rb[n] = recv(raheadq, 0);
-	}
-	qsort(rb, n, sizeof(rb[0]), rbcmp);
-	for(i=0; i<n; i++) {
-		if(rb[i] == 0)
-			continue;
-		p = getbuf(rb[i]->dev, rb[i]->addr, Bread);
-		if(p)
-			putbuf(p);
-		lock(&rabuflock);
-		rb[i]->link = rabuffree;
-		rabuffree = rb[i];
-		unlock(&rabuflock);
-	}
-	goto loop;
-}
-
-/*
- * main filesystem server loop.
- * entered by many processes.
- * they wait for message buffers and
- * then process them.
- */
-void
-serve(void)
-{
-	Fcall fi, fo;
-	Msgbuf *mb, *mb1;
-	Chan *cp;
-	int t, n;
-
-loop:
-	qlock(&reflock);
-	mb = recv(serveq, 0);
-	cp = mb->chan;
-	rlock(&cp->reflock);
-	qunlock(&reflock);
-
-	rlock(&mainlock);
-
-	/*
-	 * conversion to structure and
-	 * simple syntax checks.
-	 */
-	if(convM2S(mb->data, &fi, mb->count) == 0) {
-		print("bad M2S conversion\n");
-		goto error;
-	}
-	t = fi.type;
-
-	if(t < 0 || t >= MAXSYSCALL || (t&1) || !p9call[t]) {
-		print("bad message type\n");
-		goto error;
-	}
-
-	/*
-	 * allocate reply message
-	 */
-	if(t == Tread) {
-		mb1 = mballoc(MAXMSG+MAXDAT, cp, Mbreply2);
-		fo.data = mb1->data + 8;
-	} else
-		mb1 = mballoc(MAXMSG, cp, Mbreply3);
-
-	/*
-	 * call the file system
-	 */
-	cons.work[0].count++;
-	cons.work[1].count++;
-	cons.work[2].count++;
-	cp->work.count++;
-	cons.rate[0].count += mb->count;
-	cons.rate[1].count += mb->count;
-	cons.rate[2].count += mb->count;
-	cp->rate.count += mb->count;
-	fo.err = 0;
-
-	(*p9call[t])(cp, &fi, &fo);
-
-	fo.type = t+1;
-	fo.tag = fi.tag;
-
-	if(fo.err) {
-		if(cons.flags&errorflag)
-			print("	type %d: error: %s\n", t,
-				errstr[fo.err]);
-		if(CHAT(cp))
-			print("	error: %s\n", errstr[fo.err]);
-		fo.type = Rerror;
-		strncpy(fo.ename, errstr[fo.err], sizeof(fo.ename));
-	}
-
-	n = convS2M(&fo, mb1->data);
-	if(n == 0) {
-		print("bad S2M conversion\n");
-		mbfree(mb1);
-		goto error;
-	}
-	mb1->count = n;
-	mb1->param = mb->param;
-	cons.rate[0].count += n;
-	cons.rate[1].count += n;
-	cons.rate[2].count += n;
-	cp->rate.count += n;
-	send(cp->reply, mb1);
-
-out:
-	mbfree(mb);
-	runlock(&mainlock);
-	runlock(&cp->reflock);
-	goto loop;
-
-error:
-	print("type=%d count=%d\n", mb->data[0], mb->count);
-	print(" %.2x %.2x %.2x %.2x\n",
-		mb->data[1]&0xff, mb->data[2]&0xff,
-		mb->data[3]&0xff, mb->data[4]&0xff);
-	print(" %.2x %.2x %.2x %.2x\n",
-		mb->data[5]&0xff, mb->data[6]&0xff,
-		mb->data[7]&0xff, mb->data[8]&0xff);
-	print(" %.2x %.2x %.2x %.2x\n",
-		mb->data[9]&0xff, mb->data[10]&0xff,
-		mb->data[11]&0xff, mb->data[12]&0xff);
-
-	mb1 = mballoc(3, cp, Mbreply4);
-	mb1->data[0] = Rnop;	/* your nop was ok */
-	mb1->data[1] = ~0;
-	mb1->data[2] = ~0;
-	mb1->count = 3;
-	mb1->param = mb->param;
-	send(cp->reply, mb1);
-	goto out;
-}
-
-void
-init0(void)
-{
-	m->proc = u;
-	u->state = Running;
-	u->mach = m;
-	spllo();
-
-	(*u->start)();
-}
-
-void*
-getarg(void)
-{
-
-	return u->arg;
-}
-
-void
-exit(void)
-{
-	u = 0;
-	lock(&active);
-	active.machs &= ~(1<<m->machno);
-	active.exiting = 1;
-	unlock(&active);
-	if(!predawn)
-		spllo();
-	print("cpu %d exiting\n", m->machno);
-	while(active.machs)
-		delay(1);
-	print("halted. press a key to reboot.\n");
-	delay(300);	/* time to drain print q */
-	splhi();
-	rawchar(5 * 60); // reboot in 5mins or key press
-	consreset();
-	firmware();
-}
-
-/*
- * 1 sec timer
- * process+alarm+rendez+rwlock
- */
-static	Rendez	sec;
-
-static
-void
-callsec(Alarm *a, void *arg)
-{
-	User *u;
-
-	cancel(a);
-	u = arg;
-	wakeup(&u->tsleep);
-}
-
-void
-waitsec(int msec)
-{
-	alarm(msec, callsec, u);
-	sleep(&u->tsleep, no, 0);
-}
-
-#define	DUMPTIME	5	/* 5 am */
-#define	WEEKMASK	0	/* every day (1=sun, 2=mon 4=tue) */
-
-/*
- * process to copy dump blocks from
- * cache to worm. it runs flat out when
- * it gets work, but only looks for
- * work every 10 seconds.
- */
-void
-wormcopy(void)
-{
-	int f;
-	Filsys *fs;
-	ulong nddate, ntoytime, t;
-	long dt;
-
-recalc:
-	/*
-	 * calculate the next dump time.
-	 * minimum delay is 100 minutes.
-	 */
-	t = time();
-	nddate = nextime(t+MINUTE(100), DUMPTIME, WEEKMASK);
-	if(!conf.nodump)
-		print("next dump at %T\n", nddate);
-
-	ntoytime = time() + HOUR(1);
-
-loop:
-	dt = time() - t;
-	if(dt < 0) {
-		print("time went back\n");
-		goto recalc;
-	}
-	if(dt > MINUTE(100)) {
-		print("time jumped ahead\n");
-		goto recalc;
-	}
-	t += dt;
-	f = 0;
-
-	if(t > ntoytime) {
-		dt = time() - rtctime();
-		if(dt < 0)
-			dt = -dt;
-		if(dt > 10)
-			print("rtc time more than 10 secounds out\n");
-		else
-		if(dt > 1)
-			settime(rtctime());
-		ntoytime = time() + HOUR(1);
-		goto loop;
-	}
-
-	if(!f) {
-		if(t > nddate) {
-			if(!conf.nodump) {
-				print("automatic dump %T\n", t);
-				for(fs=filsys; fs->name; fs++)
-					if(fs->dev->type == Devcw)
-						cfsdump(fs);
-			}
-			goto recalc;
-		}
-	}
-
-	rlock(&mainlock);
-	for(fs=filsys; fs->name; fs++)
-		if(fs->dev->type == Devcw)
-			f |= dumpblock(fs->dev);
-	runlock(&mainlock);
-
-	if(!f)
-		f = dowcp();
-
-	if(!f)
-		waitsec(10000);
-	wormprobe();
-	goto loop;
-}
-
-/*
- * process to synch blocks
- * it puts out a block/line every second
- * it waits 10 seconds if caught up.
- * in both cases, it takes about 10 seconds
- * to get up-to-date.
- */
-void
-synccopy(void)
-{
-	int f;
-
-loop:
-	rlock(&mainlock);
-	f = syncblock();
-	runlock(&mainlock);
-	if(!f)
-		waitsec(10000);
-	else
-		waitsec(1000);
-/*	pokewcp();	*/
-	goto loop;
-}
//GO.SYSIN DD port/main.c
echo port/portdat.h
sed 's/.//' >port/portdat.h <<'//GO.SYSIN DD port/portdat.h'
-/*
- * fundamental constants
- */
-#define SUPER_ADDR	2		/* address of superblock */
-#define ROOT_ADDR	3		/* address of superblock */
-#define	ERRREC		64		/* size of a error record */
-#define	DIRREC		116		/* size of a directory ascii record */
-#define	NAMELEN		28		/* size of names */
-#define	NDBLOCK		6		/* number of direct blocks in Dentry */
-#define	MAXDAT		8192		/* max allowable data message */
-#define	MAXMSG		128		/* max size protocol message sans data */
-#define	OFFMSG		60		/* offset of msg in buffer */
-#define NDRIVE		16		/* size of drive structure */
-#define NTLOCK		200		/* number of active file Tlocks */
-#define	LRES		3		/* profiling resolution */
-#define NATTID		10		/* the last 10 ID's in attaches */
-#define	C0a		59		/* time constants for filters */
-#define	C0b		60
-#define	C1a		599
-#define	C1b		600
-#define	C2a		5999
-#define	C2b		6000
-
-/*
- *  more wonderful constants for authentication
- */
-#include <auth.h>
-
-/*
- * derived constants
- */
-#define	BUFSIZE		(RBUFSIZE-sizeof(Tag))
-#define DIRPERBUF	(BUFSIZE/sizeof(Dentry))
-#define INDPERBUF	(BUFSIZE/sizeof(long))
-#define INDPERBUF2	(INDPERBUF*INDPERBUF)
-#define FEPERBUF	((BUFSIZE-sizeof(Super1)-sizeof(long))/sizeof(long))
-#define	SMALLBUF	(MAXMSG)
-#define	LARGEBUF	(MAXMSG+MAXDAT+256)
-#define	RAGAP		(300*1024)/BUFSIZE		/* readahead parameter */
-#define CEPERBK		((BUFSIZE-BKPERBLK*sizeof(long))/\
-				(sizeof(Centry)*BKPERBLK))
-#define	BKPERBLK	10
-
-typedef struct	Alarm	Alarm;
-typedef	struct	Conf	Conf;
-typedef	struct	Label	Label;
-typedef	struct	Lock	Lock;
-typedef	struct	Mach	Mach;
-typedef	struct	QLock	QLock;
-typedef	struct	Ureg	Ureg;
-typedef	struct	User	User;
-typedef	struct	Fcall	Fcall;
-typedef	struct	Fbuf	Fbuf;
-typedef	struct	Super1	Super1;
-typedef	struct	Superb	Superb;
-typedef	struct	Filsys	Filsys;
-typedef	struct	Startsb	Startsb;
-typedef	struct	Dentry	Dentry;
-typedef	struct	Tag	Tag;
-typedef struct  Talarm	Talarm;
-typedef	struct	Uid	Uid;
-typedef struct	Device	Device;
-typedef struct	Qid	Qid;
-typedef	struct	Iobuf	Iobuf;
-typedef	struct	Wpath	Wpath;
-typedef	struct	File	File;
-typedef	struct	Chan	Chan;
-typedef	struct	Cons	Cons;
-typedef	struct	Time	Time;
-typedef	struct	Tm	Tm;
-typedef	struct	Rtc	Rtc;
-typedef	struct	Hiob	Hiob;
-typedef	struct	RWlock	RWlock;
-typedef	struct	Msgbuf	Msgbuf;
-typedef	struct	Queue	Queue;
-typedef	struct	Command	Command;
-typedef	struct	Flag	Flag;
-typedef	struct	Bp	Bp;
-typedef	struct	Rabuf	Rabuf;
-typedef	struct	Rendez	Rendez;
-typedef	struct	Filter	Filter;
-typedef		ulong	Float;
-typedef	struct	Tlock	Tlock;
-typedef	struct	Enpkt	Enpkt;
-typedef	struct	Arppkt	Arppkt;
-typedef	struct	Ippkt	Ippkt;
-typedef	struct	Ilpkt	Ilpkt;
-typedef	struct	Udppkt	Udppkt;
-typedef	struct	Icmppkt	Icmppkt;
-typedef	struct	Ifc	Ifc;
-typedef	struct	Cache	Cache;
-typedef	struct	Centry	Centry;
-typedef	struct	Bucket	Bucket;
-
-struct	Lock
-{
-	ulong*	sbsem;		/* addr of sync bus semaphore */
-	ulong	pc;
-	ulong	sr;
-};
-
-struct	Rendez
-{
-	Lock;
-	User*	p;
-};
-
-struct	Filter
-{
-	ulong	count;			/* count and old count kept separate */
-	ulong	oldcount;		/*	so interrput can read them */
-	int	c1;			/* time const multiplier */
-	int	c2;			/* time const divider */
-	int	c3;			/* scale for printing */
-	Float	filter;			/* filter */ 
-};
-
-struct	QLock
-{
-	Lock;			/* to use object */
-	User*	head;		/* next process waiting for object */
-	User*	tail;		/* last process waiting for object */
-	char*	name;		/* for diagnostics */
-	int	locked;		/* flag, is locked */
-};
-
-struct	RWlock
-{
-	int	nread;
-	QLock	wr;
-	QLock	rd;
-};
-
-/*
- * send/recv queue structure
- */
-struct	Queue
-{
-	Lock;			/* to manipulate values */
-	int	size;		/* size of queue */
-	int	loc;		/* circular pointer */
-	int	count;		/* how many in queue */
-	User*	rhead;		/* process's waiting for send */
-	User*	rtail;
-	User*	whead;		/* process's waiting for recv */
-	User*	wtail;
-	void*	args[1];	/* list of saved pointers, [->size] */
-};
-
-struct	Tag
-{
-	short	pad;
-	short	tag;
-	long	path;
-};
-
-struct	Device
-{
-	uchar	type;
-	uchar	init;
-	Device*	link;			/* link for mcat/mlev */
-	Device*	dlink;			/* link all devices */
-	void*	private;
-	long	size;
-	union
-	{
-		struct			/* worm wren */
-		{
-			int	ctrl;
-			int	targ;
-			int	lun;
-		} wren;
-		struct			/* ata/ide */
-		{
-			int	ctrl;
-			int	unit;
-		} ata;
-		struct			/* mcat mlev */
-		{
-			Device*	first;
-			Device*	last;
-			int	ndev;
-		} cat;
-		struct			/* cw */
-		{
-			Device*	c;
-			Device*	w;
-			Device*	ro;
-		} cw;
-		struct			/* juke */
-		{
-			Device*	j;
-			Device*	m;
-		} j;
-		struct			/* ro */
-		{
-			Device*	parent;
-		} ro;
-		struct			/* fworm */
-		{
-			Device*	fw;
-		} fw;
-		struct			/* part */
-		{
-			Device*	d;
-			long	base;
-			long	size;
-		} part;
-		struct			/* part */
-		{
-			Device*	d;
-		} swab;
-	};
-};
-
-struct	Rabuf
-{
-	union
-	{
-		struct
-		{
-			Device*	dev;
-			long	addr;
-		};
-		Rabuf*	link;
-	};
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Qid
-{
-	long	path;
-	long	version;
-};
-
-struct	Hiob
-{
-	Iobuf*	link;
-	Lock;
-};
-
-enum
-{
-	Easize		= 6,		/* Ether address size */
-	Pasize		= 4,		/* IP protocol address size */
-};
-
-typedef
-struct
-{
-	Queue*	reply;		/* ethernet output */
-	uchar	iphis[Pasize];	/* his ip address (index) */
-	uchar	ipgate[Pasize];	/* his ip/gateway address */
-	Chan*	link;		/* list of il channels */
-} Enp;
-
-enum
-{
-	Nqt=	8,
-};
-
-typedef
-struct	Ilp
-{
-	Enp;			/* must be first -- botch */
-
-	int	alloc;		/* 1 means allocated */
-	int	srcp;		/* source port (index) */
-	int	dstp;		/* dest port (index) */
-	int	state;		/* connection state */
-
-	Msgbuf*	unacked;
-	Msgbuf*	unackedtail;
-
-	Msgbuf*	outoforder;
-
-	ulong	next;		/* id of next to send */
-	ulong	recvd;		/* last packet received */
-	ulong	start;		/* local start id */
-	ulong	rstart;		/* remote start id */
-	ulong	acksent;	/* Last packet acked */
-
-	ulong	lastxmit;	/* time of last xmit */
-	ulong	lastrecv;	/* time of last recv */
-	ulong	timeout;	/* time out counter */
-	ulong	acktime;	/* acknowledge timer */
-	ulong	querytime;	/* Query timer */
-
-	ulong	delay;		/* Average of the fixed rtt delay */
-	ulong	rate;		/* Average byte rate */
-	ulong	mdev;		/* Mean deviation of predicted to real rtt */
-	ulong	maxrtt;		/* largest rtt seen */
-	ulong	rttack;		/* The ack we are waiting for */
-	int	rttlen;		/* Length of rttack packet */
-	ulong	rttstart;	/* Time we issued rttack packet */
-	ulong	unackedbytes;
-	int	rexmit;		/* number of rexmits of *unacked */
-
-	ulong	qt[Nqt+1];	/* state table for query messages */
-	int	qtx;		/* ... index into qt */
-
-	int	window;		/* maximum receive window */
-
-	Rendez	syn;		/* connect hang out */
-} Ilp;
-
-struct	Chan
-{
-	char	type;			/* major driver type i.e. Dev* */
-	char	whochan[50];
-	char	whoname[NAMELEN];
-	ulong	flags;
-	int	chan;			/* overall channel number, mostly for printing */
-	int	nmsgs;			/* outstanding messages, set under flock -- for flush */
-	ulong	whotime;
-	Filter	work;
-	Filter	rate;
-	int	nfile;			/* used by cmd_files */
-	RWlock	reflock;
-	Chan*	next;			/* link list of chans */
-	Queue*	send;
-	Queue*	reply;
-	uchar	chal[CHALLEN];		/* locally generated challenge */
-	uchar	rchal[CHALLEN];		/* remotely generated challenge */
-	Lock	idlock;
-	ulong	idoffset;		/* offset of id vector */
-	ulong	idvec;			/* vector of acceptable id's */
-
-	Ifc*	ifc;
-	union
-	{
-		/*
-		 * il ether circuit structure
-		 */
-		Ilp	ilp;
-	};
-};
-
-struct	Filsys
-{
-	char*	name;			/* name of filsys */
-	char*	conf;			/* symbolic configuration */
-	Device*	dev;			/* device that filsys is on */
-	int	flags;
-		#define	FREAM		(1<<0)	/* mkfs */
-		#define	FRECOVER	(1<<1)	/* install last dump */
-		#define	FEDIT		(1<<2)	/* modified */
-};
-
-struct	Startsb
-{
-	char*	name;
-	long	startsb;
-};
-
-struct	Time
-{
-	ulong	lasttoy;
-	long	bias;
-	long	offset;
-};
-
-/*
- * array of qids that are locked
- */
-struct	Tlock
-{
-	Device*	dev;
-	ulong	time;
-	long	qpath;
-	File*	file;
-};
-
-struct	Cons
-{
-	ulong	flags;		/* overall flags for all channels */
-	QLock;			/* generic qlock for mutex */
-	int	uid;		/* botch -- used to get uid on cons_create */
-	int	gid;		/* botch -- used to get gid on cons_create */
-	int	nuid;		/* number of uids */
-	int	ngid;		/* number of gids */
-	long	offset;		/* used to read files, c.f. fchar */
-	int	chano;		/* generator for channel numbers */
-	Chan*	chan;		/* console channel */
-	Filsys*	curfs;		/* current filesystem */
-
-	int	profile;	/* are we profiling? */
-	long*	profbuf;
-	ulong	minpc;
-	ulong	maxpc;
-	ulong	nprofbuf;
-
-	long	nlarge;		/* number of large message buffers */
-	long	nsmall;		/* ... small ... */
-	long	nwormre;	/* worm read errors */
-	long	nwormwe;	/* worm write errors */
-	long	nwormhit;	/* worm read cache hits */
-	long	nwormmiss;	/* worm read cache non-hits */
-	int	noage;		/* dont update cache age, dump and check */
-	long	nwrenre;	/* disk read errors */
-	long	nwrenwe;	/* disk write errors */
-	long	nreseq;		/* cache bucket resequence */
-
-	Filter	work[3];	/* thruput in messages */
-	Filter	rate[3];	/* thruput in bytes */
-	Filter	bhit[3];	/* getbufs that hit */
-	Filter	bread[3];	/* getbufs that miss and read */
-	Filter	brahead[3];	/* messages to readahead */
-	Filter	binit[3];	/* getbufs that miss and dont read */
-};
-
-struct	File
-{
-	QLock;
-	Qid	qid;
-	Wpath*	wpath;
-	Chan*	cp;		/* null means a free slot */
-	Tlock*	tlock;		/* if file is locked */
-	File*	next;		/* in cp->flist */
-	Filsys*	fs;
-	long	addr;
-	long	slot;
-	long	lastra;		/* read ahead address */
-	ushort	fid;
-	short	uid;
-	char	open;
-		#define	FREAD	1
-		#define	FWRITE	2
-		#define	FREMOV	4
-};
-
-struct	Wpath
-{
-	Wpath*	up;		/* pointer upwards in path */
-	long	addr;		/* directory entry addr */
-	long	slot;		/* directory entry slot */
-	short	refs;		/* number of files using this structure */
-};
-
-struct	Iobuf
-{
-	QLock;
-	Device*	dev;
-	Iobuf*	next;		/* for hash */
-	Iobuf*	fore;		/* for lru */
-	Iobuf*	back;		/* for lru */
-	char*	iobuf;		/* only active while locked */
-	char*	xiobuf;		/* "real" buffer pointer */
-	long	addr;
-	int	flags;
-};
-
-struct	Uid
-{
-	short	uid;		/* user id */
-	short	lead;		/* leader of group */
-	short	*gtab;		/* group table */
-	int	ngrp;		/* number of group entries */
-	char	name[NAMELEN];	/* user name */
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Dentry
-{
-	char	name[NAMELEN];
-	short	uid;
-	short	gid;
-	ushort	mode;
-		#define	DALLOC	0x8000
-		#define	DDIR	0x4000
-		#define	DAPND	0x2000
-		#define	DLOCK	0x1000
-		#define	DREAD	0x4
-		#define	DWRITE	0x2
-		#define	DEXEC	0x1
-	short	wuid;
-	Qid	qid;
-	long	size;
-	long	dblock[NDBLOCK];
-	long	iblock;
-	long	diblock;
-	long	atime;
-	long	mtime;
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Super1
-{
-	long	fstart;
-	long	fsize;
-	long	tfree;
-	long	qidgen;		/* generator for unique ids */
-	/*
-	 * Stuff for WWC device
-	 */
-	long	cwraddr;	/* cfs root addr */
-	long	roraddr;	/* dump root addr */
-	long	last;		/* last super block addr */
-	long	next;		/* next super block addr */
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Fbuf
-{
-	long	nfree;
-	long	free[FEPERBUF];
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Superb
-{
-	Fbuf	fbuf;
-	Super1;
-};
-
-struct	Fcall
-{
-	char	type;
-	ushort	fid;
-	short	err;
-	short	tag;
-	union
-	{
-		struct
-		{
-			short	uid;		/* T-Userstr */
-			short	oldtag;		/* T-nFlush */
-			Qid	qid;		/* R-Attach, R-Clwalk, R-Walk,
-						 * R-Open, R-Create */
-			char	rauth[AUTHENTLEN];	/* R-attach */
-		};
-		struct
-		{
-			char	uname[NAMELEN];	/* T-nAttach */
-			char	aname[NAMELEN];	/* T-nAttach */
-			char	ticket[TICKETLEN];	/* T-attach */
-			char	auth[AUTHENTLEN];	/* T-attach */
-		};
-		struct
-		{
-			char	ename[ERRREC];	/* R-nError */
-			char	chal[CHALLEN];	/* T-session, R-session */
-			char	authid[NAMELEN];	/* R-session */
-			char	authdom[DOMLEN];	/* R-session */
-		};
-		struct
-		{
-			char	name[NAMELEN];	/* T-Walk, T-Clwalk, T-Create, T-Remove */
-			long	perm;		/* T-Create */
-			ushort	newfid;		/* T-Clone, T-Clwalk */
-			char	mode;		/* T-Create, T-Open */
-		};
-		struct
-		{
-			long	offset;		/* T-Read, T-Write */
-			long	count;		/* T-Read, T-Write, R-Read */
-			char*	data;		/* T-Write, R-Read */
-		};
-		struct
-		{
-			char	stat[DIRREC];	/* T-Wstat, R-Stat */
-		};
-	};
-};
-
-struct	Label
-{
-	ulong	pc;
-	ulong	sp;
-};
-
-struct	Alarm
-{
-	Lock;
-	Alarm*	next;
-	int	busy;
-	int	dt;		/* in ticks */
-	void	(*f)(Alarm*, void*);
-	void*	arg;
-};
-
-struct Talarm
-{
-	Lock;
-	User	*list;
-};
-
-struct	Conf
-{
-	ulong	nmach;		/* processors */
-	ulong	nproc;		/* processes */
-	ulong	mem;		/* total physical bytes of memory */
-	ulong	sparemem;	/* memory left for check/dump and chans */
-	ulong	nalarm;		/* alarms */
-	ulong	nuid;		/* distinct uids */
-	ulong	nserve;		/* server processes */
-	ulong	nfile;		/* number of fid -- system wide */
-	ulong	nwpath;		/* number of active paths, derrived from nfile */
-	ulong	gidspace;	/* space for gid names -- derrived from nuid */
-	ulong	nlgmsg;		/* number of large message buffers */
-	ulong	nsmmsg;		/* number of small message buffers */
-	ulong	wcpsize;	/* memory for worm copies */
-	ulong	recovcw;	/* recover addresses */
-	ulong	recovro;
-	ulong	firstsb;
-	ulong	recovsb;
-	uchar	nodump;		/* no periodic dumps */
-	uchar	ripoff;
-	uchar	dumpreread;	/* read and compare in dump copy */
-
-	ulong	npage0;		/* total physical pages of memory */
-	ulong	npage1;		/* total physical pages of memory */
-	ulong	base0;		/* base of bank 0 */
-	ulong	base1;		/* base of bank 1 */
-};
-
-/*
- * message buffers
- * 2 types, large and small
- */
-struct	Msgbuf
-{
-	short	count;
-	short	flags;
-		#define	LARGE	(1<<0)
-		#define	FREE	(1<<1)
-		#define BFREE	(1<<2)
-	Chan*	chan;
-	Msgbuf*	next;
-	ulong	param;
-	int	category;
-	char*	data;
-	char*	xdata;
-};
-
-/*
- * message buffer categories
- */
-enum
-{
-	Mxxx		= 0,
-	Mbreply1,
-	Mbreply2,
-	Mbreply3,
-	Mbreply4,
-	Mbarp1,
-	Mbarp2,
-	Mbip1,
-	Mbip2,
-	Mbip3,
-	Mbil1,
-	Mbil2,
-	Mbil3,
-	Mbil4,
-	Mbilauth,
-	Maeth1,
-	Maeth2,
-	Maeth3,
-	Mbeth1,
-	Mbeth2,
-	Mbeth3,
-	Mbeth4,
-	Mbsntp,
-	MAXCAT,
-};
-
-struct	Mach
-{
-	int	machno;		/* physical id of processor */
-	int	mmask;		/* 1<<m->machno */
-	ulong	ticks;		/* of the clock since boot time */
-	int	lights;		/* light lights, this processor */
-	User*	proc;		/* current process on this processor */
-	Label	sched;		/* scheduler wakeup */
-	Lock	alarmlock;	/* access to alarm list */
-	void*	alarm;		/* alarms bound to this clock */
-	void	(*intr)(Ureg*, ulong);	/* pending interrupt */
-	User*	intrp;		/* process that was interrupted */
-	ulong	cause;		/* arg to intr */
-	Ureg*	ureg;		/* arg to intr */
-	uchar	stack[1];
-};
-
-#define	MAXSTACK 4000
-#define	NHAS	100
-struct	User
-{
-	Label	sched;
-	Mach*	mach;		/* machine running this proc */
-	User*	rnext;		/* next process in run queue */
-	User*	qnext;		/* next process on queue for a QLock */
-	void	(*start)(void);	/* startup function */
-	char*	text;		/* name of this process */
-	void*	arg;
-	Filter	time[3];	/* cpu time used */
-	int	exiting;
-	int	pid;
-	int	state;
-	Rendez	tsleep;
-
-	ulong	twhen;
-	Rendez	*trend;
-	User	*tlink;
-	int	(*tfn)(void*);
-
-	struct
-	{
-		QLock*	q[NHAS];/* list of locks this process has */
-		QLock*	want;	/* lock waiting */
-	} has;
-	uchar	stack[MAXSTACK];
-};
-
-#define	PRINTSIZE	256
-struct
-{
-	Lock;
-	int	machs;
-	int	exiting;
-} active;
-
-struct	Command
-{
-	char*	arg0;
-	char*	help;
-	void	(*func)(int, char*[]);
-};
-
-struct	Flag
-{
-	char*	arg0;
-	char*	help;
-	ulong	flag;
-};
-
-struct	Tm
-{
-	/* see ctime(3) */
-	int	sec;
-	int	min;
-	int	hour;
-	int	mday;
-	int	mon;
-	int	year;
-	int	wday;
-	int	yday;
-	int	isdst;
-};
-
-struct	Rtc
-{
-	int	sec;
-	int	min;
-	int	hour;
-	int	mday;
-	int	mon;
-	int	year;
-};
-
-/*
- * cw device
- */
-
-/* DONT TOUCH, this is the disk structure */
-struct	Cache
-{
-	long	maddr;		/* cache map addr */
-	long	msize;		/* cache map size in buckets */
-	long	caddr;		/* cache addr */
-	long	csize;		/* cache size */
-	long	fsize;		/* current size of worm */
-	long	wsize;		/* max size of the worm */
-	long	wmax;		/* highwater write */
-
-	long	sbaddr;		/* super block addr */
-	long	cwraddr;	/* cw root addr */
-	long	roraddr;	/* dump root addr */
-
-	long	toytime;	/* somewhere convienent */
-	long	time;
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Centry
-{
-	ushort	age;
-	short	state;
-	long	waddr;		/* worm addr */
-};
-
-/* DONT TOUCH, this is the disk structure */
-struct	Bucket
-{
-	long	agegen;		/* generator for ages in this bkt */
-	Centry	entry[CEPERBK];
-};
-
-/*
- * scsi i/o
- */
-enum
-{
-	SCSIread = 0,
-	SCSIwrite = 1,
-};
-
-/*
- * Process states
- */
-enum
-{
-	Dead = 0,
-	Moribund,
-	Zombie,
-	Ready,
-	Scheding,
-	Running,
-	Queueing,
-	Sending,
-	Recving,
-	MMUing,
-	Exiting,
-	Inwait,
-	Wakeme,
-	Broken,
-};
-
-/*
- * Lights
- */
-enum
-{
-	Lreal	= 0,	/* blink in clock interrupt */
-	Lintr,		/* on while in interrupt */
-	Lpanic,		/* in panic */
-	Lcwmap,		/* in cw lookup */
-};
-
-/*
- * devnone block numbers
- */
-enum
-{
-	Cwio1 	= 1,
-	Cwio2,
-	Cwxx1,
-	Cwxx2,
-	Cwxx3,
-	Cwxx4,
-	Cwdump1,
-	Cwdump2,
-	Cuidbuf,
-	Cckbuf,
-};
-
-#define	MAXFDATA	8192
-/*
- * P9 protocol message types
- */
-/* DONT TOUCH, this the 9P protocol */
-enum
-{
-	Tnop =		50,
-	Rnop,
-	Tosession =	52,
-	Rosession,
-	Terror =	54,	/* illegal */
-	Rerror,
-	Tflush =	56,
-	Rflush,
-	Toattach =	58,
-	Roattach,
-	Tclone =	60,
-	Rclone,
-	Twalk =		62,
-	Rwalk,
-	Topen =		64,
-	Ropen,
-	Tcreate =	66,
-	Rcreate,
-	Tread =		68,
-	Rread,
-	Twrite =	70,
-	Rwrite,
-	Tclunk =	72,
-	Rclunk,
-	Tremove =	74,
-	Rremove,
-	Tstat =		76,
-	Rstat,
-	Twstat =	78,
-	Rwstat,
-	Tclwalk =	80,
-	Rclwalk,
-	Tauth =		82,	/* illegal */
-	Rauth,			/* illegal */
-	Tsession =	84,
-	Rsession,
-	Tattach =	86,
-	Rattach,
-
-	MAXSYSCALL
-};
-
-/*
- * error codes generated from the file server
- */
-enum
-{
-	Ebadspc = 1,
-	Efid,
-	Echar,
-	Eopen,
-	Ecount,
-	Ealloc,
-	Eqid,
-	Eaccess,
-	Eentry,
-	Emode,
-	Edir1,
-	Edir2,
-	Ephase,
-	Eexist,
-	Edot,
-	Eempty,
-	Ebadu,
-	Enotu,
-	Enotg,
-	Ename,
-	Ewalk,
-	Eronly,
-	Efull,
-	Eoffset,
-	Elocked,
-	Ebroken,
-	Eauth,
-	Enoattach,
-	MAXERR
-};
-
-/*
- * device types
- */
-enum
-{
-	Devnone 	= 0,
-	Devcon,			/* console */
-	Devwren,		/* scsi disk drive */
-	Devworm,		/* scsi video drive */
-	Devlworm,		/* scsi video drive (labeled) */
-	Devfworm,		/* fake read-only device */
-	Devjuke,		/* jukebox */
-	Devcw,			/* cache with worm */
-	Devro,			/* readonly worm */
-	Devcycl,		/* cyclone fiber uart */
-	Devmcat,		/* multiple cat devices */
-	Devmlev,		/* multiple interleave devices */
-	Devil,			/* internet link */
-	Devpart,		/* partition */
-	Devfloppy,		/* floppy drive */
-	Devide,			/* IDE drive */
-	Devswab,		/* swab data between mem and device */
-	Devdup,			/* Dup drive */
-	MAXDEV
-};
-
-/*
- * tags on block
- */
-/* DONT TOUCH, this is in disk structures */
-enum
-{
-	Tnone		= 0,
-	Tsuper,			/* the super block */
-	Tdir,			/* directory contents */
-	Tind1,			/* points to blocks */
-	Tind2,			/* points to Tind1 */
-	Tfile,			/* file contents */
-	Tfree,			/* in free list */
-	Tbuck,			/* cache fs bucket */
-	Tvirgo,			/* fake worm virgin bits */
-	Tcache,			/* cw cache things */
-	Tconfig,		/* configuration block */
-	MAXTAG
-};
-
-/*
- * flags to getbuf
- */
-enum
-{
-	Bread	= (1<<0),	/* read the block if miss */
-	Bprobe	= (1<<1),	/* return null if miss */
-	Bmod	= (1<<2),	/* buffer is dirty, needs writing */
-	Bimm	= (1<<3),	/* write immediately on putbuf */
-	Bres	= (1<<4),	/* reserved, never renammed */
-};
-
-/*
- * open modes passed into P9 open/create
- */
-/* DONT TOUCH, this the P9 protocol */
-enum
-{
-	MREAD	= 0,
-	MWRITE,
-	MBOTH,
-	MEXEC,
-	MTRUNC	= (1<<4),	/* truncate on open */
-	MCEXEC	= (1<<5),	/* close on exec (host) */
-	MRCLOSE	= (1<<6),	/* remove on close */
-};
-
-
-/*
- * Ethernet header
- */
-enum
-{
-	ETHERMINTU	= 60,		/* minimum transmit size */
-	ETHERMAXTU	= 1514,		/* maximum transmit size */
-
-	Arptype		= 0x0806,
-	Iptype		= 0x0800,
-
-	Icmpproto	= 1,
-	Igmpproto	= 2,
-	Tcpproto	= 6,
-	Udpproto	= 17,
-	Ilproto		= 40,
-
-	Nqueue		= 20,
-	Nfrag		= 6,		/* max number of non-contig ip fragments */
-	Nrock		= 20,		/* number of partial ip assembly stations */
-	Nb		= 211,		/* number of arp hash buckets */
-	Ne		= 10,		/* number of entries in each arp hash bucket */
-
-	Ensize		= 14,		/* ether header size */
-	Ipsize		= 20,		/* ip header size -- doesnt include Ensize */
-	Arpsize		= 28,		/* arp header size -- doesnt include Ensize */
-	Ilsize		= 18,		/* il header size -- doesnt include Ipsize/Ensize */
-	Udpsize		= 8,		/* il header size -- doesnt include Ipsize/Ensize */
-	Udpphsize	= 12,		/* udp pseudo ip header size */
-
-	IP_VER		= 0x40,			/* Using IP version 4 */
-	IP_HLEN		= Ipsize/4,		/* Header length in longs */
-	IP_DF		= 0x4000,		/* Don't fragment */
-	IP_MF		= 0x2000,		/* More fragments */
-
-	Arprequest	= 1,
-	Arpreply,
-
-	Ilfsport	= 17008,
-	Ilauthport	= 17020,
-	Ilfsout		= 5000,
-	SNTP		= 123,
-	SNTP_LOCAL	= 6001,
-};
-
-struct	Enpkt
-{
-	uchar	d[Easize];		/* destination address */
-	uchar	s[Easize];		/* source address */
-	uchar	type[2];		/* packet type */
-
-	uchar	data[ETHERMAXTU-(6+6+2)];
-	uchar	crc[4];
-};
-
-struct	Arppkt
-{
-	uchar	d[Easize];			/* ether header */
-	uchar	s[Easize];
-	uchar	type[2];
-
-	uchar	hrd[2];				/* hardware type, must be ether==1 */
-	uchar	pro[2];				/* protocol, must be ip */
-	uchar	hln;				/* hardware address len, must be Easize */
-	uchar	pln;				/* protocol address len, must be Pasize */
-	uchar	op[2];
-	uchar	sha[Easize];
-	uchar	spa[Pasize];
-	uchar	tha[Easize];
-	uchar	tpa[Pasize];
-};
-
-struct	Ippkt
-{
-	uchar	d[Easize];		/* ether header */
-	uchar	s[Easize];
-	uchar	type[2];
-
-	uchar	vihl;			/* Version and header length */
-	uchar	tos;			/* Type of service */
-	uchar	length[2];		/* packet length */
-	uchar	id[2];			/* Identification */
-	uchar	frag[2];		/* Fragment information */
-	uchar	ttl;			/* Time to live */
-	uchar	proto;			/* Protocol */
-	uchar	cksum[2];		/* Header checksum */
-	uchar	src[Pasize];		/* Ip source */
-	uchar	dst[Pasize];		/* Ip destination */
-};
-
-struct	Ilpkt
-{
-	uchar	d[Easize];		/* ether header */
-	uchar	s[Easize];
-	uchar	type[2];
-
-	uchar	vihl;			/* ip header */
-	uchar	tos;
-	uchar	length[2];
-	uchar	id[2];
-	uchar	frag[2];
-	uchar	ttl;
-	uchar	proto;
-	uchar	cksum[2];
-	uchar	src[Pasize];
-	uchar	dst[Pasize];
-
-	uchar	ilsum[2];		/* Checksum including header */
-	uchar	illen[2];		/* Packet length */
-	uchar	iltype;			/* Packet type */
-	uchar	ilspec;			/* Special */
-	uchar	ilsrc[2];		/* Src port */
-	uchar	ildst[2];		/* Dst port */
-	uchar	ilid[4];		/* Sequence id */
-	uchar	ilack[4];		/* Acked sequence */
-};
-
-struct	Udppkt
-{
-	uchar	d[Easize];		/* ether header */
-	uchar	s[Easize];
-	uchar	type[2];
-
-	uchar	vihl;			/* ip header */
-	uchar	tos;
-	uchar	length[2];
-	uchar	id[2];
-	uchar	frag[2];
-	uchar	ttl;
-	uchar	proto;
-	uchar	cksum[2];
-	uchar	src[Pasize];
-	uchar	dst[Pasize];
-
-	uchar	udpsrc[2];		/* Src port */
-	uchar	udpdst[2];		/* Dst port */
-	uchar	udplen[2];		/* Packet length */
-	uchar	udpsum[2];		/* Checksum including header */
-};
-
-struct	Icmppkt
-{
-	uchar	d[Easize];		/* ether header */
-	uchar	s[Easize];
-	uchar	type[2];
-
-	uchar	vihl;			/* ip header */
-	uchar	tos;
-	uchar	length[2];
-	uchar	id[2];
-	uchar	frag[2];
-	uchar	ttl;
-	uchar	proto;
-	uchar	cksum[2];
-	uchar	src[Pasize];
-	uchar	dst[Pasize];
-
-	uchar	icmptype;		/* Src port */
-	uchar	icmpcode;		/* Dst port */
-	uchar	icmpsum[2];		/* Checksum including header */
-
-	uchar	icmpbody[10];		/* Depends on type */
-};
-
-struct	Ifc
-{
-	Lock;
-	Queue*	reply;
-	Filter	work[3];
-	Filter	rate[3];
-	ulong	rcverr;
-	ulong	txerr;
-	ulong	sumerr;
-	ulong	rxpkt;
-	ulong	txpkt;
-	uchar	ea[Easize];		/* my ether address */
-	uchar	ipa[Pasize];		/* my ip address, pulled from netdb */
-	uchar	netgate[Pasize];	/* my ip gateway, pulled from netdb */
-	ulong	ipaddr;
-	ulong	mask;
-	ulong	cmask;
-	Ifc	*next;			/* List of configured interfaces */
-};
-
-extern	register	Mach*	m;
-extern	register	User*	u;
-extern  Talarm		talarm;
-
-Conf	conf;
-Cons	cons;
-#define	MACHP(n)	((Mach*)(MACHADDR+n*BY2PG))
-
-#pragma	varargck	type	"D"	Device*
-#pragma	varargck	type	"T"	ulong
-#pragma	varargck	type	"I"	uchar*
-#pragma	varargck	type	"E"	uchar*
-#pragma	varargck	type	"F"	Filter*
-#pragma	varargck	type	"G"	int
//GO.SYSIN DD port/portdat.h
echo port/sub.c
sed 's/.//' >port/sub.c <<'//GO.SYSIN DD port/sub.c'
-#include	"all.h"
-#include	"io.h"
-
-Filsys*
-fsstr(char *p)
-{
-	Filsys *fs;
-
-	for(fs=filsys; fs->name; fs++)
-		if(strcmp(fs->name, p) == 0)
-			return fs;
-	return 0;
-}
-
-/*
- * allocate 'count' contiguous channels
- * of type 'type' and return pointer to base
- */
-Chan*
-chaninit(int type, int count)
-{
-	Chan *cp, *icp;
-	int i;
-
-	icp = ialloc(count * sizeof(*icp), 0);
-	cp = icp;
-	for(i=0; i<count; i++) {
-		cp->next = chans;
-		chans = cp;
-		cp->type = type;
-		cp->chan = cons.chano;
-		cons.chano++;
-		strncpy(cp->whoname, "<none>", sizeof(cp->whoname));
-		dofilter(&cp->work, C0a, C0b, 1);
-		dofilter(&cp->rate, C0a, C0b, 1000);
-		fileinit(cp);
-		wlock(&cp->reflock);
-		wunlock(&cp->reflock);
-		rlock(&cp->reflock);
-		runlock(&cp->reflock);
-		cp++;
-	}
-	return icp;
-}
-
-void
-fileinit(Chan *cp)
-{
-	File *f, *prev;
-	Tlock *t;
-	int h;
-
-loop:
-	lock(&flock);
-	for(h=0; h<nelem(flist); h++) {
-		for(prev=0,f=flist[h]; f; prev=f,f=f->next) {
-			if(f->cp != cp)
-				continue;
-			if(prev) {
-				prev->next = f->next;
-				f->next = flist[h];
-				flist[h] = f;
-			}
-			goto out;
-		}
-	}
-	unlock(&flock);
-	return;
-
-out:
-	flist[h] = f->next;
-	unlock(&flock);
-
-	qlock(f);
-	if(t = f->tlock) {
-		t->time = 0;
-		f->tlock = 0;
-	}
-	if(f->open & FREMOV)
-		doremove(f, 0);
-	freewp(f->wpath);
-	f->open = 0;
-	f->cp = 0;
-	qunlock(f);
-
-	goto loop;
-}
-
-/*
- * returns a locked file structure
- */
-File*
-filep(Chan *cp, int fid, int flag)
-{
-	File *f;
-	int h;
-
-	if(fid == NOF)
-		return 0;
-
-	h = (long)cp + fid;
-	if(h < 0)
-		h = ~h;
-	h = h % nelem(flist);
-
-loop:
-	lock(&flock);
-	for(f=flist[h]; f; f=f->next)
-		if(f->fid == fid && f->cp == cp)
-			goto out;
-
-	if(flag) {
-		f = newfp();
-		if(f) {
-			f->fid = fid;
-			f->cp = cp;
-			f->wpath = 0;
-			f->tlock = 0;
-			f->next = flist[h];
-			flist[h] = f;
-			goto out;
-		}
-	}
-	unlock(&flock);
-	return 0;
-
-out:
-	unlock(&flock);
-	qlock(f);
-	if(f->fid == fid && f->cp == cp)
-		return f;
-	qunlock(f);
-	goto loop;
-}
-
-/*
- * always called with flock locked
- */
-File*
-newfp(void)
-{
-	static first;
-	File *f;
-	int start, i;
-
-	i = first;
-	start = i;
-	do {
-		f = &files[i];
-		i++;
-		if(i >= conf.nfile)
-			i = 0;
-		if(f->cp)
-			continue;
-
-		first = i;
-
-		return f;
-	} while(i != start);
-
-	print("out of files\n");
-	return 0;
-}
-
-void
-freefp(File *fp)
-{
-	Chan *cp;
-	File *f, *prev;
-	int h;
-
-	if(!fp || !(cp = fp->cp))
-		return;
-
-	h = (long)cp + fp->fid;
-	if(h < 0)
-		h = ~h;
-	h = h % nelem(flist);
-
-	lock(&flock);
-	for(prev=0,f=flist[h]; f; prev=f,f=f->next)
-		if(f == fp) {
-			if(prev)
-				prev->next = f->next;
-			else
-				flist[h] = f->next;
-			break;
-		}
-	fp->cp = 0;
-	unlock(&flock);
-}
-
-int
-iaccess(File *f, Dentry *d, int m)
-{
-
-	/* uid none gets only other permissions */
-	if(f->uid == 0)
-		goto doother;
-
-	/*
-	 * owner
-	 */
-	if(f->uid == d->uid)
-		if((m<<6) & d->mode)
-			return 0;
-	/*
-	 * group membership
-	 */
-	if(ingroup(f->uid, d->gid))
-		if((m<<3) & d->mode)
-			return 0;
-
-doother:
-	/*
-	 * other
-	 */
-	if(m & d->mode) {
-		if((d->mode & DDIR) && (m == DEXEC))
-			return 0;
-		if(!ingroup(f->uid, 9999))
-			return 0;
-	}
-
-	/*
-	 * various forms of superuser
-	 */
-	if(wstatallow)
-		return 0;
-	if(duallow != 0 && duallow == f->uid)
-		if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
-			return 0;
-
-	return 1;
-}
-
-Tlock*
-tlocked(Iobuf *p, Dentry *d)
-{
-	Tlock *t, *t1;
-	long qpath, tim;
-	Device *dev;
-
-	tim = toytime();
-	qpath = d->qid.path;
-	dev = p->dev;
-
-again:
-	t1 = 0;
-	for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
-		if(t->qpath == qpath)
-		if(t->time >= tim)
-		if(t->dev == dev)
-			return nil;		/* its locked */
-		if(t1 != nil && t->time == 0)
-			t1 = t;			/* remember free lock */
-	}
-	if(t1 == 0) {
-		// reclaim old locks
-		lock(&tlocklock);
-		for(t=tlocks+NTLOCK-1; t>=tlocks; t--)
-			if(t->time < tim) {
-				t->time = 0;
-				t1 = t;
-			}
-		unlock(&tlocklock);
-	}
-	if(t1) {
-		lock(&tlocklock);
-		if(t1->time != 0) {
-			unlock(&tlocklock);
-			goto again;
-		}
-		t1->dev = dev;
-		t1->qpath = qpath;
-		t1->time = tim + TLOCK;
-		unlock(&tlocklock);
-	}
-	/* botch
-	 * out of tlock nodes simulates
-	 * a locked file
-	 */
-	return t1;
-}
-
-Wpath*
-newwp(void)
-{
-	static int si = 0;
-	int i;
-	Wpath *w, *sw, *ew;
-
-	i = si + 1;
-	if(i < 0 || i >= conf.nwpath)
-		i = 0;
-	si = i;
-	sw = &wpaths[i];
-	ew = &wpaths[conf.nwpath];
-	for(w=sw;;) {
-		w++;
-		if(w >= ew)
-			w = &wpaths[0];
-		if(w == sw) {
-			print("out of wpaths\n");
-			return 0;
-		}
-		if(w->refs)
-			continue;
-		lock(&wpathlock);
-		if(w->refs) {
-			unlock(&wpathlock);
-			continue;
-		}
-		w->refs = 1;
-		w->up = 0;
-		unlock(&wpathlock);
-		return w;
-	}
-
-}
-
-void
-freewp(Wpath *w)
-{
-	lock(&wpathlock);
-	for(; w; w=w->up)
-		w->refs--;
-	unlock(&wpathlock);
-}
-
-Qid
-newqid(Device *dev)
-{
-	Iobuf *p;
-	Superb *sb;
-	Qid qid;
-
-	p = getbuf(dev, superaddr(dev), Bread|Bmod);
-	if(!p || checktag(p, Tsuper, QPSUPER))
-		panic("newqid: super block");
-	sb = (Superb*)p->iobuf;
-	sb->qidgen++;
-	qid.path = sb->qidgen;
-	qid.version = 0;
-	putbuf(p);
-	return qid;
-}
-
-void
-buffree(Device *dev, long addr, int d)
-{
-	Iobuf *p;
-	long a;
-	int i;
-
-	if(!addr)
-		return;
-	if(d > 0) {
-		d--;
-		p = getbuf(dev, addr, Bread);
-		if(p) {
-			for(i=INDPERBUF-1; i>=0; i--) {
-				a = ((long*)p->iobuf)[i];
-				buffree(dev, a, d);
-			}
-			putbuf(p);
-		}
-	}
-	/*
-	 * stop outstanding i/o
-	 */
-	p = getbuf(dev, addr, Bprobe);
-	if(p) {
-		p->flags &= ~(Bmod|Bimm);
-		putbuf(p);
-	}
-	/*
-	 * dont put written worm
-	 * blocks into free list
-	 */
-	if(dev->type == Devcw) {
-		i = cwfree(dev, addr);
-		if(i)
-			return;
-	}
-	p = getbuf(dev, superaddr(dev), Bread|Bmod);
-	if(!p || checktag(p, Tsuper, QPSUPER))
-		panic("buffree: super block");
-	addfree(dev, addr, (Superb*)p->iobuf);
-	putbuf(p);
-}
-
-long
-bufalloc(Device *dev, int tag, long qid, int uid)
-{
-	Iobuf *bp, *p;
-	Superb *sb;
-	long a;
-	int n;
-
-	p = getbuf(dev, superaddr(dev), Bread|Bmod);
-	if(!p || checktag(p, Tsuper, QPSUPER)) {
-		print("bufalloc: super block\n");
-		if(p)
-			putbuf(p);
-		return 0;
-	}
-	sb = (Superb*)p->iobuf;
-
-loop:
-	n = --sb->fbuf.nfree;
-	sb->tfree--;
-	if(n < 0 || n >= FEPERBUF) {
-		print("bufalloc: bad freelist\n");
-		n = 0;
-		sb->fbuf.free[0] = 0;
-	}
-	a = sb->fbuf.free[n];
-	if(n <= 0) {
-		if(a == 0) {
-			sb->tfree = 0;
-			sb->fbuf.nfree = 1;
-			if(dev->type == Devcw) {
-				n = uid;
-				if(n < 0 || n >= nelem(growacct))
-					n = 0;
-				growacct[n]++;
-				if(cwgrow(dev, sb, uid))
-					goto loop;
-			}
-			putbuf(p);
-			print("fs full uid=%d\n", uid);
-			return 0;
-		}
-		bp = getbuf(dev, a, Bread);
-		if(!bp || checktag(bp, Tfree, QPNONE)) {
-			if(bp)
-				putbuf(bp);
-			putbuf(p);
-			return 0;
-		}
-		sb->fbuf = *(Fbuf*)bp->iobuf;
-		putbuf(bp);
-	}
-
-	bp = getbuf(dev, a, Bmod);
-	memset(bp->iobuf, 0, RBUFSIZE);
-	settag(bp, tag, qid);
-	if(tag == Tind1 || tag == Tind2 || tag == Tdir)
-		bp->flags |= Bimm;
-	putbuf(bp);
-	putbuf(p);
-	return a;
-}
-
-/*
- * what are legal characters in a name?
- * only disallow control characters.
- * a) utf avoids control characters.
- * b) '/' may not be the separator
- */
-int
-checkname(char *n)
-{
-	int i, c;
-
-	for(i=0; i<NAMELEN; i++) {
-		c = *n & 0xff;
-		if(c == 0) {
-			if(i == 0)
-				return 1;
-			memset(n, 0, NAMELEN-i);
-			return 0;
-		}
-		if(c <= 040)
-			return 1;
-		n++;
-	}
-	return 1;	/* too long */
-}
-
-void
-addfree(Device *dev, long addr, Superb *sb)
-{
-	int n;
-	Iobuf *p;
-
-	n = sb->fbuf.nfree;
-	if(n < 0 || n > FEPERBUF)
-		panic("addfree: bad freelist");
-	if(n >= FEPERBUF) {
-		p = getbuf(dev, addr, Bmod|Bimm);
-		if(p == 0)
-			panic("addfree: getbuf");
-		*(Fbuf*)p->iobuf = sb->fbuf;
-		settag(p, Tfree, QPNONE);
-		putbuf(p);
-		n = 0;
-	}
-	sb->fbuf.free[n++] = addr;
-	sb->fbuf.nfree = n;
-	sb->tfree++;
-	if(addr >= sb->fsize)
-		sb->fsize = addr+1;
-}
-
-int
-Cconv(Op *o)
-{
-	Chan *cp;
-	char s[20];
-
-	cp = *(Chan**)o->argp;
-	sprint(s, "C%d.%.3d", cp->type, cp->chan);
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(cp);
-}
-
-int
-Dconv(Op *o)
-{
-	Device *d;
-	int c, c1;
-	char s[100];
-
-	d = *(Device**)o->argp;
-	if(d == 0) {
-		sprint(s, "D***");
-		goto out;
-	}
-	switch(d->type) {
-	default:
-		sprint(s, "D%d", d->type);
-		break;
-	case Devwren:
-		c = 'w';
-		goto d1;
-	case Devworm:
-		c = 'r';
-		goto d1;
-	case Devlworm:
-		c = 'l';
-		goto d1;
-	d1:
-		if(d->wren.ctrl == 0 && d->wren.lun == 0)
-			sprint(s, "%c%d", c, d->wren.targ);
-		else
-			sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, d->wren.lun);
-		break;
-	case Devmcat:
-		c = '(';
-		c1 = ')';
-		goto d2;
-	case Devmlev:
-		c = '[';
-		c1 = ']';
-	d2:
-		if(d->cat.first == d->cat.last)
-			sprint(s, "%c%D%c", c, d->cat.first, c1);
-		else
-		if(d->cat.first->link == d->cat.last)
-			sprint(s, "%c%D%D%c", c, d->cat.first, d->cat.last, c1);
-		else
-			sprint(s, "%c%D-%D%c", c, d->cat.first, d->cat.last, c1);
-		break;
-	case Devro:
-		sprint(s, "o%D%D", d->ro.parent->cw.c, d->ro.parent->cw.w);
-		break;
-	case Devcw:
-		sprint(s, "c%D%D", d->cw.c, d->cw.w);
-		break;
-	case Devjuke:
-		sprint(s, "j%D%D", d->j.j, d->j.m);
-		break;
-	case Devpart:
-		sprint(s, "p%ld.%ld", d->part.base, d->part.size);
-		break;
-	case Devswab:
-		sprint(s, "x%D", d->swab.d);
-		break;
-	}
-out:
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(d);
-}
-
-int
-Fconv(Op *o)
-{
-	Filter* a;
-	char s[30];
-
-	a = *(Filter**)o->argp;
-
-	sprint(s, "%lud", fdf(a->filter, a->c3*a->c1));
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(a);
-}
-
-int
-Gconv(Op *o)
-{
-	int t;
-	char s[20];
-
-	t = *(int*)o->argp;
-	strcpy(s, "<badtag>");
-	if(t >= 0 && t < MAXTAG)
-		sprint(s, "%s", tagnames[t]);
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(t);
-}
-
-int
-Econv(Op *o)
-{
-	char s[64];
-	uchar *p;
-
-	p = *((uchar**)o->argp);
-	sprint(s, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux",
-		p[0], p[1], p[2], p[3], p[4], p[5]);
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(uchar*);
-}
-
-int
-Iconv(Op *o)
-{
-	char s[64];
-	uchar *p;
-
-	p = *((uchar**)o->argp);
-	sprint(s, "%d.%d.%d.%d",
-		p[0], p[1], p[2], p[3]);
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(uchar*);
-}
-
-int
-Nconv(Op *o)
-{
-	char s[64];
-	uchar *p;
-	long n;
-
-	p = *((uchar**)o->argp);
-	n = (p[0]<<8) | p[1];
-	if(!(o->f3 & FSHORT))
-		n = (n<<16) | (p[2]<<8) | p[3];
-	sprint(s, "%lud", n);
-	strconv(s, o, o->f1, o->f2);
-	return sizeof(uchar*);
-}
-
-void
-formatinit(void)
-{
-
-	fmtinstall('C', Cconv);	/* print channels */
-	fmtinstall('D', Dconv);	/* print devices */
-	fmtinstall('F', Fconv);	/* print filters */
-	fmtinstall('G', Gconv);	/* print tags */
-	fmtinstall('T', Tconv);	/* print times */
-	fmtinstall('E', Econv);	/* print ether addresses */
-	fmtinstall('I', Iconv);	/* print ip addresses */
-	fmtinstall('N', Nconv);	/* print network order integers */
-}
-
-int
-nzip(uchar ip[Pasize])
-{
-	if(ip[0] || ip[1] || ip[2] || ip[3])
-		return 1;
-	return 0;
-}
-
-void
-rootream(Device *dev, long addr)
-{
-	Iobuf *p;
-	Dentry *d;
-
-	p = getbuf(dev, addr, Bmod|Bimm);
-	memset(p->iobuf, 0, RBUFSIZE);
-	settag(p, Tdir, QPROOT);
-	d = getdir(p, 0);
-	strcpy(d->name, "/");
-	d->uid = -1;
-	d->gid = -1;
-	d->mode = DALLOC | DDIR |
-		((DREAD|DEXEC) << 6) |
-		((DREAD|DEXEC) << 3) |
-		((DREAD|DEXEC) << 0);
-	d->qid = QID(QPROOT|QPDIR,0);
-	d->atime = time();
-	d->mtime = d->atime;
-	d->wuid = 0;
-	putbuf(p);
-}
-
-void
-superream(Device *dev, long addr)
-{
-	Iobuf *p;
-	Superb *s;
-	long i;
-
-	p = getbuf(dev, addr, Bmod|Bimm);
-	memset(p->iobuf, 0, RBUFSIZE);
-	settag(p, Tsuper, QPSUPER);
-
-	s = (Superb*)p->iobuf;
-	s->fstart = 2;
-	s->fsize = devsize(dev);
-	s->fbuf.nfree = 1;
-	s->qidgen = 10;
-	for(i=s->fsize-1; i>=addr+2; i--)
-		addfree(dev, i, s);
-	putbuf(p);
-}
-
-struct
-{
-	Lock;
-	Msgbuf	*smsgbuf;
-	Msgbuf	*lmsgbuf;
-} msgalloc;
-
-void
-mbinit(void)
-{
-	Msgbuf *mb;
-	Rabuf *rb;
-	int i;
-
-	lock(&msgalloc);
-	unlock(&msgalloc);
-	msgalloc.lmsgbuf = 0;
-	msgalloc.smsgbuf = 0;
-	for(i=0; i<conf.nlgmsg; i++) {
-		mb = ialloc(sizeof(Msgbuf), 0);
-		if(1)
-			mb->xdata = ialloc(LARGEBUF+256, 256);
-		else
-			mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE);
-		mb->flags = LARGE;
-		mbfree(mb);
-		cons.nlarge++;
-	}
-	for(i=0; i<conf.nsmmsg; i++) {
-		mb = ialloc(sizeof(Msgbuf), 0);
-		if(1)
-			mb->xdata = ialloc(SMALLBUF+256, 256);
-		else
-			mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE);
-		mb->flags = 0;
-		mbfree(mb);
-		cons.nsmall++;
-	}
-	memset(mballocs, 0, sizeof(mballocs));
-
-	lock(&rabuflock);
-	unlock(&rabuflock);
-	rabuffree = 0;
-	for(i=0; i<1000; i++) {
-		rb = ialloc(sizeof(*rb), 0);
-		rb->link = rabuffree;
-		rabuffree = rb;
-	}
-}
-
-Msgbuf*
-mballoc(int count, Chan *cp, int category)
-{
-	Msgbuf *mb;
-
-	ilock(&msgalloc);
-	if(count > SMALLBUF) {
-		if(count > LARGEBUF)
-			panic("msgbuf count");
-		mb = msgalloc.lmsgbuf;
-		if(mb == 0) {
-			mb = ialloc(sizeof(Msgbuf), 0);
-			if(1)
-				mb->xdata = ialloc(LARGEBUF+256, 256);
-			else
-				mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE);
-			cons.nlarge++;
-		} else
-			msgalloc.lmsgbuf = mb->next;
-		mb->flags = LARGE;
-	} else {
-		mb = msgalloc.smsgbuf;
-		if(mb == 0) {
-			mb = ialloc(sizeof(Msgbuf), 0);
-			if(1)
-				mb->xdata = ialloc(SMALLBUF+256, 256);
-			else
-				mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE);
-			cons.nsmall++;
-		} else
-			msgalloc.smsgbuf = mb->next;
-		mb->flags = 0;
-	}
-	mballocs[category]++;
-	iunlock(&msgalloc);
-	mb->count = count;
-	mb->chan = cp;
-	mb->next = 0;
-	mb->param = 0;
-	mb->category = category;
-	if(1)
-		mb->data = mb->xdata+256;
-	else
-		mb->data = mb->xdata+OFFMSG;
-	return mb;
-}
-
-void
-mbfree(Msgbuf *mb)
-{
-	if(mb->flags & FREE)
-		panic("mbfree already free");
-
-	ilock(&msgalloc);
-	mballocs[mb->category]--;
-	mb->flags |= FREE;
-	if(mb->flags & LARGE) {
-		mb->next = msgalloc.lmsgbuf;
-		msgalloc.lmsgbuf = mb;
-	} else {
-		mb->next = msgalloc.smsgbuf;
-		msgalloc.smsgbuf = mb;
-	}
-	mb->data = 0;
-	iunlock(&msgalloc);
-}
-
-/*
- * returns 1 if n is prime
- * used for adjusting lengths
- * of hashing things.
- * there is no need to be clever
- */
-int
-prime(long n)
-{
-	long i;
-
-	if((n%2) == 0)
-		return 0;
-	for(i=3;; i+=2) {
-		if((n%i) == 0)
-			return 0;
-		if(i*i >= n)
-			return 1;
-	}
-}
-
-char*
-getwd(char *word, char *line)
-{
-	int c, n;
-
-	while(*line == ' ')
-		line++;
-	for(n=0; n<80; n++) {
-		c = *line;
-		if(c == ' ' || c == 0 || c == '\n')
-			break;
-		line++;
-		*word++ = c;
-	}
-	*word = 0;
-	return line;
-}
-
-void
-hexdump(void *a, int n)
-{
-	char s1[30], s2[4];
-	uchar *p;
-	int i;
-
-	p = a;
-	s1[0] = 0;
-	for(i=0; i<n; i++) {
-		sprint(s2, " %.2ux", p[i]);
-		strcat(s1, s2);
-		if((i&7) == 7) {
-			print("%s\n", s1);
-			s1[0] = 0;
-		}
-	}
-	if(s1[0])
-		print("%s\n", s1);
-}
-
-void*
-recv(Queue *q, int)
-{
-	User *p;
-	void *a;
-	int i, c;
-	long s;
-
-	if(q == 0)
-		panic("recv null q");
-	for(;;) {
-		lock(q);
-		c = q->count;
-		if(c > 0) {
-			i = q->loc;
-			a = q->args[i];
-			i++;
-			if(i >= q->size)
-				i = 0;
-			q->loc = i;
-			q->count = c-1;
-			p = q->whead;
-			if(p) {
-				q->whead = p->qnext;
-				if(q->whead == 0)
-					q->wtail = 0;
-				ready(p);
-			}
-			unlock(q);
-			return a;
-		}
-		p = q->rtail;
-		if(p == 0)
-			q->rhead = u;
-		else
-			p->qnext = u;
-		q->rtail = u;
-		u->qnext = 0;
-		s = splhi();
-		u->state = Recving;
-		unlock(q);
-		sched();
-		splx(s);
-	}
-	return 0;
-}
-
-void
-send(Queue *q, void *a)
-{
-	User *p;
-	int i, c;
-	long s;
-
-	if(q == 0)
-		panic("send null q");
-	for(;;) {
-		lock(q);
-		c = q->count;
-		if(c < q->size) {
-			i = q->loc + c;
-			if(i >= q->size)
-				i -= q->size;
-			q->args[i] = a;
-			q->count = c+1;
-			p = q->rhead;
-			if(p) {
-				q->rhead = p->qnext;
-				if(q->rhead == 0)
-					q->rtail = 0;
-				ready(p);
-			}
-			unlock(q);
-			return;
-		}
-		p = q->wtail;
-		if(p == 0)
-			q->whead = u;
-		else
-			p->qnext = u;
-		q->wtail = u;
-		u->qnext = 0;
-		s = splhi();
-		u->state = Sending;
-		unlock(q);
-		sched();
-		splx(s);
-	}
-}
-
-Queue*
-newqueue(int size)
-{
-	Queue *q;
-
-	q = ialloc(sizeof(Queue) + (size-1)*sizeof(void*), 0);
-	q->size = size;
-	lock(q);
-	unlock(q);
-	return q;
-}
-
-no(void*)
-{
-	return 0;
-}
-
-int
-devread(Device *d, long b, void *c)
-{
-	int e;
-
-loop:
-	switch(d->type)
-	{
-	case Devcw:
-		return cwread(d, b, c);
-
-	case Devjuke:
-		d = d->j.m;
-		goto loop;
-
-	case Devro:
-		return roread(d, b, c);
-
-	case Devwren:
-		return wrenread(d, b, c);
-	case Devide:
-		return ideread(d, b, c);
-
-	case Devworm:
-	case Devlworm:
-		return wormread(d, b, c);
-
-	case Devfworm:
-		return fwormread(d, b, c);
-
-	case Devmcat:
-		return mcatread(d, b, c);
-
-	case Devmlev:
-		return mlevread(d, b, c);
-
-	case Devpart:
-		return partread(d, b, c);
-
-	case Devswab:
-		e = devread(d->swab.d, b, c);
-		if(e == 0)
-			swab(c, 0);
-		return e;
-	}
-	panic("illegal device in read: %D %ld", d, b);
-	return 1;
-}
-
-int
-devwrite(Device *d, long b, void *c)
-{
-	int e;
-
-loop:
-	switch(d->type)
-	{
-	case Devcw:
-		return cwwrite(d, b, c);
-
-	case Devjuke:
-		d = d->j.m;
-		goto loop;
-
-	case Devro:
-		print("write to ro device %D(%ld)\n", d, b);
-		return 1;
-
-	case Devwren:
-		return wrenwrite(d, b, c);
-	case Devide:
-		return idewrite(d, b, c);
-
-	case Devworm:
-	case Devlworm:
-		return wormwrite(d, b, c);
-
-	case Devfworm:
-		return fwormwrite(d, b, c);
-
-	case Devmcat:
-		return mcatwrite(d, b, c);
-
-	case Devmlev:
-		return mlevwrite(d, b, c);
-
-	case Devpart:
-		return partwrite(d, b, c);
-
-	case Devswab:
-		swab(c, 1);
-		e = devwrite(d->swab.d, b, c);
-		swab(c, 0);
-		return e;
-	}
-	panic("illegal device in write: %D %ld", d, b);
-	return 1;
-}
-
-long
-devsize(Device *d)
-{
-
-loop:
-	switch(d->type)
-	{
-	case Devcw:
-	case Devro:
-		return cwsize(d);
-
-	case Devjuke:
-		d = d->j.m;
-		goto loop;
-
-	case Devwren:
-		return wrensize(d);
-	case Devide:
-		return atasize(d);
-
-	case Devworm:
-	case Devlworm:
-		return wormsize(d);
-
-	case Devfworm:
-		return fwormsize(d);
-
-	case Devmcat:
-		return mcatsize(d);
-
-	case Devmlev:
-		return mlevsize(d);
-
-	case Devpart:
-		return partsize(d);
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-	panic("illegal device in dev_size: %D", d);
-	return 0;
-}
-
-long
-superaddr(Device *d)
-{
-
-loop:
-	switch(d->type) {
-	default:
-		return SUPER_ADDR;
-
-	case Devcw:
-	case Devro:
-		return cwsaddr(d);
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-}
-
-long
-getraddr(Device *d)
-{
-
-loop:
-	switch(d->type) {
-	default:
-		return ROOT_ADDR;
-
-	case Devcw:
-	case Devro:
-		return cwraddr(d);
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-}
-
-void
-devream(Device *d, int top)
-{
-	Device *l;
-
-loop:
-	print("	devream: %D %d\n", d, top);
-	switch(d->type) {
-	default:
-		print("ream: unknown dev type %D\n", d);
-		return;
-
-	case Devcw:
-		devream(d->cw.w, 0);
-		devream(d->cw.c, 0);
-		if(top) {
-			wlock(&mainlock);
-			cwream(d);
-			wunlock(&mainlock);
-		}
-		devinit(d);
-		return;
-
-	case Devfworm:
-		devream(d->fw.fw, 0);
-		fwormream(d);
-		break;
-
-	case Devpart:
-		devream(d->part.d, 0);
-		break;
-
-	case Devmlev:
-	case Devmcat:
-		for(l=d->cat.first; l; l=l->link)
-			devream(l, 0);
-		break;
-
-	case Devjuke:
-	case Devworm:
-	case Devlworm:
-	case Devwren:
-		break;
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-	devinit(d);
-	if(top) {
-		wlock(&mainlock);
-		rootream(d, ROOT_ADDR);
-		superream(d, SUPER_ADDR);
-		wunlock(&mainlock);
-	}
-}
-
-void
-devrecover(Device *d)
-{
-
-loop:
-	print("recover: %D\n", d);
-	switch(d->type) {
-	default:
-		print("recover: unknown dev type %D\n", d);
-		return;
-
-	case Devcw:
-		wlock(&mainlock);	/* recover */
-		cwrecover(d);
-		wunlock(&mainlock);
-		break;
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-}
-
-void
-devinit(Device *d)
-{
-
-loop:
-	if(d->init)
-		return;
-	d->init = 1;
-	print("	devinit %D\n", d);
-	switch(d->type) {
-	default:
-		print("devinit unknown device %D\n", d);
-		return;
-
-	case Devro:
-		cwinit(d->ro.parent);
-		break;
-
-	case Devcw:
-		cwinit(d);
-		break;
-
-	case Devjuke:
-		jukeinit(d);
-		break;
-
-	case Devwren:
-		wreninit(d);
-		break;
-
-	case Devide:
-		ideinit(d);
-	case Devworm:
-	case Devlworm:
-		break;
-
-	case Devfworm:
-		fworminit(d);
-		break;
-
-	case Devmcat:
-		mcatinit(d);
-		break;
-
-	case Devmlev:
-		mlevinit(d);
-		break;
-
-	case Devpart:
-		partinit(d);
-		break;
-
-	case Devswab:
-		d = d->swab.d;
-		goto loop;
-	}
-}
-
-void
-swab2(void *c)
-{
-	uchar *p;
-	int t;
-
-	p = c;
-
-	t = p[0];
-	p[0] = p[1];
-	p[1] = t;
-}
-
-void
-swab4(void *c)
-{
-	uchar *p;
-	int t;
-
-	p = c;
-
-	t = p[0];
-	p[0] = p[3];
-	p[3] = t;
-
-	t = p[1];
-	p[1] = p[2];
-	p[2] = t;
-}
-
-/*
- * swab a block
- *	flag = 0 -- convert from foreign to native
- *	flag = 1 -- convert from native to foreign
- */
-void
-swab(void *c, int flag)
-{
-	uchar *p;
-	Tag *t;
-	int i, j;
-	Dentry *d;
-	Cache *h;
-	Bucket *b;
-	Superb *s;
-	Fbuf *f;
-	long *l;
-
-	/* swab the tag */
-	p = (uchar*)c;
-	t = (Tag*)(p + BUFSIZE);
-	if(!flag) {
-		swab2(&t->pad);
-		swab2(&t->tag);
-		swab4(&t->path);
-	}
-
-	/* swab each block type */
-	switch(t->tag) {
-
-	default:
-		print("no swab for tag=%G rw=%d\n", t->tag, flag);
-		for(j=0; j<16; j++)
-			print(" %.2x", p[BUFSIZE+j]);
-		print("\n");
-		for(i=0; i<16; i++) {
-			print("%.4x", i*16);
-			for(j=0; j<16; j++)
-				print(" %.2x", p[i*16+j]);
-			print("\n");
-		}
-		break;
-
-	case Tsuper:
-		s = (Superb*)p;
-		swab4(&s->fbuf.nfree);
-		for(i=0; i<FEPERBUF; i++)
-			swab4(&s->fbuf.free[i]);
-		swab4(&s->fstart);
-		swab4(&s->fsize);
-		swab4(&s->tfree);
-		swab4(&s->qidgen);
-		swab4(&s->cwraddr);
-		swab4(&s->roraddr);
-		swab4(&s->last);
-		swab4(&s->next);
-		break;
-
-	case Tdir:
-		for(i=0; i<DIRPERBUF; i++) {
-			d = (Dentry*)p + i;
-			swab2(&d->uid);
-			swab2(&d->gid);
-			swab2(&d->mode);
-			swab2(&d->wuid);
-			swab4(&d->qid.path);
-			swab4(&d->qid.version);
-			swab4(&d->size);
-			for(j=0; j<NDBLOCK; j++)
-				swab4(&d->dblock[j]);
-			swab4(&d->iblock);
-			swab4(&d->diblock);
-			swab4(&d->atime);
-			swab4(&d->mtime);
-		}
-		break;
-
-	case Tind1:
-	case Tind2:
-		l = (long*)p;
-		for(i=0; i<INDPERBUF; i++) {
-			swab4(l);
-			l++;
-		}
-		break;
-
-	case Tfree:
-		f = (Fbuf*)p;
-		swab4(&f->nfree);
-		for(i=0; i<FEPERBUF; i++)
-			swab4(&f->free[i]);
-		break;
-
-	case Tbuck:
-		for(i=0; i<BKPERBLK; i++) {
-			b = (Bucket*)p + i;
-			swab4(&b->agegen);
-			for(j=0; j<CEPERBK; j++) {
-				swab2(&b->entry[j].age);
-				swab2(&b->entry[j].state);
-				swab4(&b->entry[j].waddr);
-			}
-		}
-		break;
-
-	case Tcache:
-		h = (Cache*)p;
-		swab4(&h->maddr);
-		swab4(&h->msize);
-		swab4(&h->caddr);
-		swab4(&h->csize);
-		swab4(&h->fsize);
-		swab4(&h->wsize);
-		swab4(&h->wmax);
-		swab4(&h->sbaddr);
-		swab4(&h->cwraddr);
-		swab4(&h->roraddr);
-		swab4(&h->toytime);
-		swab4(&h->time);
-		break;
-
-	case Tnone:	// unitialized
-	case Tfile:	// someone elses problem
-	case Tvirgo:	// bit map -- all bytes
-	case Tconfig:	// configuration string -- all bytes
-		break;
-	}
-
-	/* swab the tag */
-	if(flag) {
-		swab2(&t->pad);
-		swab2(&t->tag);
-		swab4(&t->path);
-	}
-}
//GO.SYSIN DD port/sub.c

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2001-05-17  4:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-05-16 21:13 [9fans] ide fs patch for the current plan9 version geoff
  -- strict thread matches above, loose matches on Subject: below --
2001-05-16 19:31 geoff
2001-05-16 21:00 ` Francisco J Ballesteros
2001-05-16 13:02 nemo
2001-05-17  4:54 ` Eric Dorman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).