~kris/9p

9hist

673d2fe8805d24559336baf1fdd94d67d93174a5 — David du Colombier 25 years ago 0ae1ad8
Plan 9 from Bell Labs 2000-11-11
M bitsy/clock.c => bitsy/clock.c +18 -6
@@ 7,6 7,19 @@
#include	"ureg.h"
#include	"../port/error.h"

typedef struct OSTimer
{
	ulong	osmr[4];	/* match registers */
	ulong	oscr;		/* counter register */
	ulong	ossr;		/* status register */
	ulong	ower;		/* watchdog enable register */
	ulong	oier;		/* timer interrupt enable register */
} OSTimer;

static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
static int clockinited;

static void	clockintr(Ureg*, void*);

void
clockinit(void)


@@ 36,16 49,13 @@ fastticks(uvlong *hz)
static void
clockintr(Ureg *ureg, void*)
{
	Clock0link *lp;
	static int inclockintr;

	/* reset previous interrupt */
	timerregs->ossr |= 1<<0;

	/* post interrupt 1/HZ secs from now */
	timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;

	portclock();
	portclock(ureg);
}

void


@@ 57,7 67,8 @@ delay(int ms)
	if(clockinited){
		while(ms-- > 0){
			start = timerregs->oscr;
			while(timerregs->oscr-start < ClockFreq/1000);
			while(timerregs->oscr-start < ClockFreq/1000)
				;
		}
	} else {
		while(ms-- > 0){


@@ 75,7 86,8 @@ void

	if(clockinited){
		start = timerregs->oscr;
		while(timerregs->oscr - start < µs∗ClockFreq/1000000);
		while(timerregs->oscr - start < (µs*ClockFreq)/1000000)
			;
	} else {
		while(µs-- > 0){
			for(i = 0; i < 10; i++)

M bitsy/devflash.c => bitsy/devflash.c +119 -8
@@ 30,13 30,6 @@ static ulong *flash = (ulong*)FLASHZERO;
/*
 *  common flash memory interface
 */
enum
{
	CFIidoff=	0x10,
	CFIsysoff=	0x1B,
	CFIgeomoff=	0x27,
};

struct CFIid
{
	ulong	q;


@@ 70,5 63,123 @@ struct CFIsys
struct CFIgeom
{
	ulong	size;		/* 2**n bytes */
	ulong	
	ulong	dev_code;	/* ??? */
	ulong	max_multi;	/* max bytes in a multibyte write */
	ulong	nregion;	/* number of erase regions */
	ulong	region[1];	/* erase region info */
};

#define mirror(x) (((x)<<16)|(x))

void
cfiquery(void)
{
	struct CFIid *id;

	flash[0x55] = mirror(0x98);
	id = (struct CFIid*)&flash[0x10];
	if(id.q != 'q' || id.r != 'r' || id.y != 'y')
		print("CFI not supported by flash\n");
	
	flash[0x55] = mirror(0xFF);
}

void
cfigeom(void)
{
}

/*
 *  flash device interface
 */

enum
{
	Qf0=1,
	Qf1,
	Qf2,
	Qf3,
};

Dirtab flashdir[]={
	"f0",		{ Qf0, 0 },	0,	0664,
	"f1",		{ Qf1, 0 },	0,	0664,
	"f2",		{ Qf2, 0 },	0,	0664,
	"f3",		{ Qf3, 0 },	0,	0664,
};

void
flashinit(void)
{
	cfiquery();
	cfigeom();
}

static Chan*
flashattach(char* spec)
{
	return devattach('r', spec);
}

static int	 
flashwalk(Chan* c, char* name)
{
	return devwalk(c, name, flashdir, nelem(flashdir), devgen);
}

static void	 
flashstat(Chan* c, char* dp)
{
	devstat(c, dp, flashdir, nelem(flashdir), devgen);
}

static Chan*
flashopen(Chan* c, int omode)
{
	omode = openmode(omode);
	if(strcmp(up->user, eve)!=0)
		error(Eperm);
	return devopen(c, omode, flashdir, nelem(flashdir), devgen);
}

static void	 
flashclose(Chan*)
{
}

static long	 
flashread(Chan* c, void* a, long n, vlong off)
{
	USED(c, a, off);
	error("UUO");
	return n;
}

static long	 
flashwrite(Chan* c, void* a, long n, vlong)
{
	USED(c, a, off);
	error("UUO");
	return n;
}

Dev flashdevtab = {
	'F',
	"flash",

	devreset,
	flashinit,
	flashattach,
	devclone,
	flashwalk,
	flashstat,
	flashopen,
	devcreate,
	flashclose,
	flashread,
	devbread,
	flashwrite,
	devbwrite,
	devremove,
	devwstat,
};

M bitsy/devuda1341.c => bitsy/devuda1341.c +80 -66
@@ 71,10 71,10 @@ enum {
/*
 * UDA1341 L3 address and command types
 */
#define UDA1341_L3Addr	5
#define UDA1341_DATA0	0
#define UDA1341_DATA1	1
#define UDA1341_STATUS	2
#define UDA1341_L3Addr	5

typedef struct	AQueue	AQueue;
typedef struct	Buf	Buf;


@@ 135,7 135,7 @@ struct	IOstate
	int				dma;			/* dma chan, alloc on open, free on close */
	int				bufinit;		/* boolean, if buffers allocated */
	Buf				buf[Nbuf];		/* buffers and queues */
	int				active;			/* # of dmas in progress */
	Ref				active;			/* # of dmas in progress */
	volatile Buf	*current;		/* next dma to finish */
	volatile Buf	*next;			/* next candidate for dma */
	volatile Buf	*filling;		/* buffer being filled */


@@ 336,7 336,7 @@ L3_getbyte(int mode)
 * in the upper 6 bits).
 */
static int
L3_write(char addr, char *data, int len)
L3_write(uchar addr, uchar *data, int len)
{
	int mode = 0;
	int bytes = len;


@@ 355,7 355,7 @@ L3_write(char addr, char *data, int len)
 * in the upper 6 bits).
 */
static int
L3_read(char addr, char * data, int len)
L3_read(uchar addr, uchar *data, int len)
{
	int mode = 0;
	int bytes = len;


@@ 387,7 387,6 @@ setempty(IOstate *b)

	for (i = 0; i < Nbuf; i++) {
		b->buf[i].nbytes = 0;
		b->buf[i].active = 0;
	}
	b->filling = b->buf;
	b->current = b->buf;


@@ 395,10 394,12 @@ setempty(IOstate *b)
}

static int
audioqnotfull(IOstate *s)
audioqnotfull(void *x)
{
	IOstate *s = x;

	/* called with lock */
	return s->active == 0 || s->filling != s->current;
	return s->active.ref == 0 || s->filling != s->current;
}

static int


@@ 409,10 410,11 @@ audioqnotempty(IOstate *s)
}

static int
audioidle(IOstate *s)
audioidle(void *x)
{
	IOstate *s = x;
	/* called with lock */
	return s->active == 0;
	return s->active.ref == 0;
}

static void


@@ 424,61 426,77 @@ audioinit(void)
static void
audioenable(void)
{
	int err;
	uchar	data[2];

	L3_init();

	/* Setup the uarts */
    ppcregs->assignment &= ~(1<<18);	/* Could be the other way round! */

    gpioregs->altfunc &= ~(GPIO_SSP_TXD | GPIO_SSP_RXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM);
	gpioregs->altfunc |= (GPIO_SSP_CLK);
	gpioregs->direction &= ~(GPIO_SSP_CLK);
    gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o);
	gpioregs->altfunc |= (GPIO_SSP_CLK_i);
	gpioregs->direction &= ~(GPIO_SSP_CLK_i);

	sspregs->control0 = 0x10<<0 | 0x1<<4 | 1<<7 | 0x8<<8;
	sspregs->control1 = 0<<3 + 0<<4 + 1<<5;

	/* Enable the audio power */
          set_bitsy_egpio(EGPIO_BITSY_CODEC_NRESET|EGPIO_BITSY_AUD_AMP_ON|EGPIO_BITSY_AUD_PWR_ON);
          clr_bitsy_egpio(EGPIO_BITSY_QMUTE);
	  gpioregs->direction |=  (GPIO_BITSY_CLK_SET0|GPIO_BITSY_CLK_SET1);
	  /* external clock configured for 44100 samples/sec */
          GPSR =   GPIO_BITSY_CLK_SET0;
          GPCR =   GPIO_BITSY_CLK_SET1;
	audiopower(1);
	amplifierpower(1);
	audiomute(0);

	gpioregs->direction |=  (GPIO_CLK_SET0_o|GPIO_CLK_SET1_o);
	  /* external clock configured for 44100 samples/sec */
    gpioregs->set = GPIO_CLK_SET0_o;
    gpioregs->clear = GPIO_CLK_SET1_o;
 
        printk("gpioregs->altfunc=%08x gpioregs->direction=%08x GPLR=%08x\n", gpioregs->altfunc, gpioregs->direction, GPLR);
        printk("PPDR=%08x PPSR=%08x PPAR=%08x PPFR=%08x\n", PPDR, PPSR, PPAR, PPFR);

	/* Wait for the UDA1341 to wake up */
	mdelay(100);
        printk("Ser4SSSR=%08x\n", Ser4SSSR);

    audio_uda1341_reset();

	/* Set some default mixer values... */
	STATUS_1.DAC_gain = 1;
	STATUS_1.ADC_gain = 1;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, (char*)&STATUS_1, 1 );
	DATA0_0.volume = 15;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_0, 1 );
	DATA0_2.mode = 3;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_2, 1 );
	DATA0_ext2.mixer_mode = 2;
	DATA0_ext2.mic_level = 4;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext2, 2 );
	DATA0_ext4.AGC_ctrl = 1;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext4, 2 );
	DATA0_ext6.AGC_level = 3;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_DATA0, (char*)&DATA0_ext6, 2 );
	delay(100);
    print("Ser4SSSR=0x%lux\n", sspregs->status);

	print("audio enabled\n");
	/* Reset the chip */
	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */;
	L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1 );

	return 0;
    gpioregs->clear = EGPIO_codec_reset;
    gpioregs->set = EGPIO_codec_reset;

	data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */;
	L3_write( (UDA1341_L3Addr<<2)|UDA1341_STATUS, data, 1 );
	/* Reset done */

	/* write uda 1341 status[1] */
	data[0] = 0x80 | 0x3<<UdaStatusPC | 1<<UdaStatusIGS | 1<<UdaStatusOGS;
	L3_write(UDA1341_L3Addr<<2 | UDA1341_STATUS, data, 1);

	/* write uda 1341 data0[0] (volume) */
	data[0] = 0x00 | /* volume */ 15 & 0x3f;	/* 6 bits, others must be 0 */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 1);

	/* write uda 1341 data0[2] (mode switch) */
	data[0] = 0x80 | 3;	/* mode = 3 */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 1);

	/* set mixer mode and level */
	data[0] = 0xc0 | 2 /* ext address */;
	data[1] = 0xe0 | 2 | 4 << 2;	/* mixer mode and mic level */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2);

	/* set agc control and input amplifier gain */
	data[0] = 0xc0 | 4 /* ext address */;
	data[1] = 0xe0 | 1<<4 | 3;	/* AGC control and input ampl gain */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2 );

	/* set agc time constant and output level */
	data[0] = 0xc0 | 6 /* ext address */;
	data[1] = 0xe0 | 0<<2 | 3;	/* agc time constant and output level */
	L3_write(UDA1341_L3Addr<<2 | UDA1341_DATA0, data, 2 );

	print("audio enabled\n");
}

static void
sendaudio(IOstat *b) {
sendaudio(IOstate *b) {
	/* call this with lock held */
	while (b->next != b->filling) {
		assert(b->next->nbytes);


@@ 487,12 505,12 @@ sendaudio(IOstat *b) {
		incref(&b->active);
		b->next++;
		if (b->next == &b->buf[Nbuf])
			b->next == &b->buf[0];
			b->next = &b->buf[0];
	}
}

static void
audiointr(void *x, ulong state) {
audiointr(void *x, ulong) {
	IOstate *s = x;

	if (s == &audio.o) {


@@ 500,14 518,14 @@ audiointr(void *x, ulong state) {
		/* Only interrupt routine touches s->current */
		s->current->nbytes = 0;
		s->current++;
		if (b->current == &b->buf[Nbuf])
			b->current == &b->buf[0];
		if (canlock(s)) {
		if (s->current == &s->buf[Nbuf])
			s->current = &s->buf[0];
		if (canlock((Lock*)s)) {
			sendaudio(s);
			unlock(s);
			unlock((Lock*)s);
		}
	}
	wakeup(s->vous);
	wakeup(&s->vous);
}

static Chan*


@@ 554,7 572,7 @@ audioopen(Chan *c, int omode)
			qunlock(&audio);
			error(Einuse);
		}
		audiopower(1);
		audioenable();
		if (omode & Aread) {
			/* read */
			audio.amode |= Aread;


@@ 565,14 583,14 @@ audioopen(Chan *c, int omode)
		}
		if (omode & 0x2) {
			/* write */
			amplifierpower(1);
			audiomute(0);
//			amplifierpower(1);
//			audiomute(0);
			audio.amode |= Awrite;
			if(audio.o.bufinit == 0)
				bufinit(&audio.o);
			setempty(&audio.o);
			audio.o.chan = c;
			&audio.o.dma = dmaalloc(0, 0, 8, 2, AudioDMA, void *port, void (*f)(int, ulong))
			audio.o.dma = dmaalloc(0, 0, 8, 2, AudioDMA, Port4MCP, audiointr, (void*)&audio.o);
		}
		qunlock(&audio);
//		mxvolume();


@@ 589,7 607,6 @@ audioopen(Chan *c, int omode)
static void
audioclose(Chan *c)
{
	IOstate *b;

	switch(c->qid.path & ~CHDIR) {
	default:


@@ 622,7 639,7 @@ audioclose(Chan *c)
				}
				while(!audioidle(&audio.o))
					sleep(&audio.o.vous, audioidle, &audio.o);
				audioamplifier(0);
				amplifierpower(0);
				setempty(&audio.o);
			}
			if (audio.i.chan == c) {


@@ 648,7 665,6 @@ audioread(Chan *c, void *v, long n, vlong off)
	int liv, riv, lov, rov;
	long m, n0;
	char buf[300];
	Buf *b;
	int j;
	ulong offset = off;
	char *a;


@@ 722,7 738,6 @@ audiowrite(Chan *c, void *vp, long n, vlong)
	long m, n0;
	int i, nf, v, left, right, in, out;
	char buf[255], *field[Ncmd];
	Buf *b;
	char *p;
	IOstate *a;



@@ 759,7 774,6 @@ audiowrite(Chan *c, void *vp, long n, vlong)
					audio.rovol[v] = m;
				if(right && in)
					audio.rivol[v] = m;
				mxvolume();
				goto cont0;
			}



@@ 775,8 789,8 @@ audiowrite(Chan *c, void *vp, long n, vlong)
			}

			if(strcmp(field[i], "reset") == 0) {
				resetlevel();
				mxvolume();
//				resetlevel();
//				mxvolume();
				goto cont0;
			}
			if(strcmp(field[i], "in") == 0) {


@@ 816,13 830,13 @@ audiowrite(Chan *c, void *vp, long n, vlong)
		}
		while(n > 0) {
			/* wait if dma in progress */
			while (a->active && a->filling == a->current)
			while (a->active.ref && a->filling == a->current)
				sleep(&a->vous, audioqnotfull, a);

			m = Bufsize - a->filling->nbytes;
			if(m > n)
				m = n;
			memmove(a->filling->buf + a->filling->nbytes, p, m);
			memmove(a->filling->virt + a->filling->nbytes, p, m);

			a->filling->nbytes += m;
			n -= m;


@@ 841,7 855,7 @@ audiowrite(Chan *c, void *vp, long n, vlong)
	return n0 - n;
}

Dev audiodevtab = {
Dev uda1341devtab = {
	'A',
	"audio",


M bitsy/fns.h => bitsy/fns.h +4 -0
@@ 1,5 1,8 @@
#include "../port/portfns.h"

void	amplifierpower(int);
void	audiopower(int);
void	audiomute(int);
void	cacheflush(void);
void	cachewb(void);
void	cachewbaddr(void*);


@@ 11,6 14,7 @@ void	clockinit(void);
#define	coherence()
void	delay(int);
void	µdelay(int);
void	dmainit(void);
void	evenaddr(ulong);
void	flushmmu(void);
int		fpiarm(Ureg *ur);

M bitsy/io.h => bitsy/io.h +26 -0
@@ 76,6 76,32 @@ enum
	GPIO_COM_CTS_i=		1<<25,	/* CTS from UART3 */
	GPIO_COM_RTS_o=		1<<26,	/* RTS to UART3 */
	GPIO_OPT_IND_i=		1<<27,	/* expansion pack inserted */
/* Peripheral Unit GPIO pin assignments: */
	GPIO_SSP_TXD_o=		1<<10,	/* SSP Transmit Data */
	GPIO_SSP_RXD_i=		1<<11,	/* SSP Receive Data */
	GPIO_SSP_SCLK_o=	1<<12,	/* SSP Sample CLocK */
	GPIO_SSP_SFRM_o=	1<<13,	/* SSP Sample FRaMe */
	/* ser. port 1: */
	GPIO_UART_TXD_o=	1<<14,	/* UART Transmit Data */
	GPIO_UART_RXD_i=	1<<15,	/* UART Receive Data */
	GPIO_SDLC_SCLK_io=	1<<16,	/* SDLC Sample CLocK (I/O) */
	GPIO_SDLC_AAF_o=	1<<17,	/* SDLC Abort After Frame */
	GPIO_UART_SCLK1_i=	1<<18,	/* UART Sample CLocK 1 */
	/* ser. port 4: */
	GPIO_SSP_CLK_i=		1<<19,	/* SSP external CLocK */
	/* ser. port 3: */
	GPIO_UART_SCLK3_i=	1<<20,	/* UART Sample CLocK 3 */
	/* ser. port 4: */
	GPIO_MCP_CLK_i=		1<<21,	/* MCP CLocK */
	/* test controller: */
	GPIO_TIC_ACK_o=		1<<21,	/* TIC ACKnowledge */
	GPIO_MBGNT_o=		1<<21,	/* Memory Bus GraNT */
	GPIO_TREQA_i=		1<<22,	/* TIC REQuest A */
	GPIO_MBREQ_i=		1<<22,	/* Memory Bus REQuest */
	GPIO_TREQB_i=		1<<23,	/* TIC REQuest B */
	GPIO_1Hz_o=			1<<25,	/* 1 Hz clock */
	GPIO_RCLK_o=		1<<26,	/* internal (R) CLocK (O, fcpu/2) */
	GPIO_32_768kHz_o=	1<<27,	/* 32.768 kHz clock (O, RTC) */
};

enum

M bitsy/main.c => bitsy/main.c +3 -0
@@ 14,6 14,8 @@ Conf	conf;
int 	noprint;

static void	gpioinit(void);
static void ppcinit(void);
static void sspinit(void);

void
main(void)


@@ 41,6 43,7 @@ main(void)
	trapinit();
	sa1100_uartsetup(1);
	rs232power(1);
	dmainit();
	screeninit();
	printinit();	/* from here on, print works, before this we need iprint */
	clockinit();

M bitsy/sa1110dma.c => bitsy/sa1110dma.c +21 -12
@@ 38,16 38,16 @@ enum {
	BIU		=	7
};

typedef struct Chan {
typedef struct DMAchan {
	int		inuse;
	Rendez	r;
	void	(*intr)(int, ulong);
	void	(*intr)(void*, ulong);
	void	*param;
} Chan;
} DMAchan;

struct {
	Lock;
	Chan	chan[6];
	DMAchan	chan[6];
} dma;

struct dmaregs {


@@ 61,14 61,21 @@ struct dmaregs {
	ulong	dxcntB;
} *dmaregs;

static void	dmaintr(Ureg*, void *);

void
dmainit(void) {
	int i;

	/* map the lcd regs into the kernel's virtual space */
	dmaregs = (struct dmaregs*)mapspecial(DMAREGS, NDMA*sizeof(struct dmaregs));;
	for (i = 0; i < NDMA; i++) {
		intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
	}
}

int
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, void *port, void (*intr)(int, ulong), void *param) {
dmaalloc(int rd, int bigendian, int burstsize, int datumsize, int device, ulong port, void (*intr)(void*, ulong), void *param) {
	int i;

	lock(&dma);


@@ 110,7 117,7 @@ dmastart(int chan, void *addr, int count) {
	if (((status = dmaregs[chan].dcsr_rd) & ((1<<DONEA)|(1<<DONEB))) == 0)
		return 0;

	cachewbregion(addr, count);
	cachewbregion((ulong)addr, count);
	if ((status & (1<<BIU | 1<<STRTB)) == (1<<BIU | 1<<STRTB) ||
				(status & (1<<BIU | 1<<STRTA)) == (1<<STRTA)) {
		dmaregs[chan].dcsr_clr |= 1<<DONEA | 1<<STRTA;


@@ 164,12 171,14 @@ static void
dmaintr(Ureg*, void *x)
{
	int i;
	struct dmaregs *regs = x;
	ulong dcsr;

	for (i = 0; i < NDMA; i++) {
		if ((dcsr = dmaregs[i].dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR))
			wakeup(&dma.chan[i].r);
			if (dma.chan[i].intr)
				(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
	}
	i = regs - dmaregs;
	if ((dcsr = regs->dcsr_rd) & (1<<DONEA | 1<<DONEB | 1<<ERROR)) {
		wakeup(&dma.chan[i].r);
		if (dma.chan[i].intr)
			(*dma.chan[i].intr)(dma.chan[i].param, dcsr);
	} else
		print("spurious DMA interrupt, channel %d, status 0x%lux\n", i, dcsr);
}

M bitsy/sa1110dma.h => bitsy/sa1110dma.h +4 -1
@@ 2,10 2,13 @@
enum {
	Port4MCP		= 0x80060008,
	Port4SSP		= 0x8007006c,
	AudioDMA		= 0xa,
	SSPXmitDMA		= 0xe,
	SSPRecvDMA		= 0xf,
};

void	dmainit(void);
int		dmaalloc(int, int, int, int, int, void *, void (*)(void*, ulong), void*);
int		dmaalloc(int, int, int, int, int, ulong, void (*)(void*, ulong), void*);
void	dmafree(int);
ulong	dmastart(int, void *, int);
ulong	dmadone(int, ulong);

D ip/bootp.c => ip/bootp.c +0 -191
@@ 1,191 0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "kernel.h"
#include "ip.h"

static	ulong	fsip;
static	ulong	auip;
static	ulong	gwip;
static	ulong	ipmask;
static	ulong	ipaddr;

uchar	sys[NAMELEN];

enum
{
	Bootrequest = 1,
	Bootreply   = 2,
};

typedef struct Bootp
{
	uchar	op;		/* opcode */
	uchar	htype;		/* hardware type */
	uchar	hlen;		/* hardware address len */
	uchar	hops;		/* hops */
	uchar	xid[4];		/* a random number */
	uchar	secs[2];	/* elapsed snce client started booting */
	uchar	pad[2];
	uchar	ciaddr[4];	/* client IP address (client tells server) */
	uchar	yiaddr[4];	/* client IP address (server tells client) */
	uchar	siaddr[4];	/* server IP address */
	uchar	giaddr[4];	/* gateway IP address */
	uchar	chaddr[16];	/* client hardware address */
	uchar	sname[64];	/* server host name (optional) */
	uchar	file[128];	/* boot file name */
	uchar	vend[128];	/* vendor-specific goo */
} Bootp;

/*
 * bootp returns:
 *
 * "fsip d.d.d.d
 * auip d.d.d.d
 * gwip d.d.d.d
 * ipmask d.d.d.d
 * ipaddr d.d.d.d"
 *
 * where d.d.d.d is the IP address in dotted decimal notation, and each
 * address is followed by a newline.
 */
enum
{
	bootpreadlen = sizeof("fsip") + sizeof("auip") + sizeof("gwip")
		+ sizeof("ipmask") + sizeof("ipaddr")
		+ 5 * sizeof("000.000.000.000") + sizeof("")
};

static	Bootp	req;
static	int	recv;
static	int	done;
static	Rendez	bootpr;
static	char	rcvbuf[512];

void
rcvbootp(void *a)
{
	int n, fd;
	Bootp *rp;
	char *field[4];
	uchar ip[IPaddrlen];

	fd = (int)a;
	while(done == 0) {
		n = kread(fd, rcvbuf, sizeof(rcvbuf));
		if(n <= 0)
			break;
		rp = (Bootp*)rcvbuf;
		if(memcmp(req.chaddr, rp->chaddr, 6) == 0
		&& rp->htype == 1 && rp->hlen == 6
		&& getfields((char*)rp->vend+4, field, 4, 1, " ") == 4
		&& strncmp((char*)rp->vend, "p9  ", 4) == 0){
			if(ipaddr == 0)
				ipaddr = nhgetl(rp->yiaddr);
			if(ipmask == 0)
				ipmask = parseip(ip, field[0]);
			if(fsip == 0)
				fsip = parseip(ip, field[1]);
			if(auip == 0)
				auip = parseip(ip, field[2]);
			if(gwip == 0)
				gwip = parseip(ip, field[3]);
			break;
		}
	}

	recv = 1;
	wakeup(&bootpr);
	pexit("", 0);
}

char*
bootp(Ipifc *ifc)
{
	int fd, tries, n;
	char ia[5+3*16], im[16], *av[3];
	char nipaddr[4], ngwip[4], nipmask[4];

	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcadd(ifc, av, 3);

	fd = kdial("udp!255.255.255.255!67", "68", nil, nil);
	if(fd < 0)
		return "bootp dial failed";

	/* create request */
	memset(&req, 0, sizeof(req));
	req.op = Bootrequest;
	req.htype = 1;			/* ethernet (all we know) */
	req.hlen = 6;			/* ethernet (all we know) */

	/* Hardware MAC address */
	memmove(req.chaddr, ifc->mac, 6);
	/* Fill in the local IP address if we know it */
	ipv4local(ifc, req.ciaddr);
	memset(req.file, 0, sizeof(req.file));
	strcpy((char*)req.vend, "p9  ");

	kproc("rcvbootp", rcvbootp, (void*)fd);

	/*
	 * broadcast bootp's till we get a reply,
	 * or fixed number of tries
	 */
	tries = 0;
	while(recv == 0) {
		if(kwrite(fd, &req, sizeof(req)) < 0)
			print("bootp: write: %r");

		tsleep(&bootpr, return0, 0, 1000);
		if(++tries > 10) {
			print("bootp: timed out\n");
			break;
		}
	}
	kclose(fd);
	done = 1;

	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcrem(ifc, av, 3, 1);

	hnputl(nipaddr, ipaddr);
	sprint(ia, "%V", nipaddr);
	hnputl(nipmask, ipmask);
	sprint(im, "%V", nipmask);
	av[1] = ia;
	av[2] = im;
	ipifcadd(ifc, av, 3);

	if(gwip != 0) {
		hnputl(ngwip, gwip);
		n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip);
		routewrite(ifc->conv->p->f, nil, ia, n);
	}
	return nil;
}

int
bootpread(char *bp, ulong offset, int len)
{
	int n;
	char buf[bootpreadlen], a[4];

	hnputl(a, fsip);
	n = sprint(buf, "fsip %15V\n", a);
	hnputl(a, auip);
	n += sprint(buf + n, "auip %15V\n", a);
	hnputl(a, gwip);
	n += sprint(buf + n, "gwip %15V\n", a);
	hnputl(a, ipmask);
	n += sprint(buf + n, "ipmask %15V\n", a);
	hnputl(a, ipaddr);
	sprint(buf + n, "ipaddr %15V\n", a);

	return readstr(offset, bp, len, buf);
}

R ip/dial.c => ip/chandial.c +20 -32
@@ 4,10 4,9 @@
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"kernel.h"

typedef struct DS DS;
static int	call(char*, char*, DS*);
static Chan*	call(char*, char*, DS*);
static void	_dial_string_parse(char*, DS*);

enum


@@ 24,21 23,21 @@ struct DS
	char	*rem;
	char	*local;				/* other args */
	char	*dir;
	int	*cfdp;
	Chan	**ctlp;
};

/*
 *  the dialstring is of the form '[/net/]proto!dest'
 */
int
kdial(char *dest, char *local, char *dir, int *cfdp)
Chan*
chandial(char *dest, char *local, char *dir, Chan **ctlp)
{
	DS ds;
	char clone[Maxpath];

	ds.local = local;
	ds.dir = dir;
	ds.cfdp = cfdp;
	ds.ctlp = ctlp;

	_dial_string_parse(dest, &ds);
	if(ds.netdir == 0)


@@ 49,24 48,21 @@ kdial(char *dest, char *local, char *dir, int *cfdp)
	return call(clone, ds.rem, &ds);
}

static int
static Chan*
call(char *clone, char *dest, DS *ds)
{
	int fd, cfd, n;
	int n;
	Chan *dchan, *cchan;
	char name[3*NAMELEN+5], data[3*NAMELEN+10], *p;

	cfd = kopen(clone, ORDWR);
	if(cfd < 0){
		kwerrstr("%s: %r", clone);
		return -1;
	}
	cchan = namec(clone, Aopen, ORDWR, 0);

	/* get directory name */
	n = kread(cfd, name, sizeof(name)-1);
	if(n < 0){
		kclose(cfd);
		return -1;
	if(waserror()){
		cclose(cchan);
		nexterror();
	}
	n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0);
	name[n] = 0;
	for(p = name; *p == ' '; p++)
		;


@@ 82,24 78,16 @@ call(char *clone, char *dest, DS *ds)
		snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
	else
		snprint(name, sizeof(name), "connect %s", dest);
	if(kwrite(cfd, name, strlen(name)) < 0){
		kwerrstr("%s failed: %r", name);
		kclose(cfd);
		return -1;
	}
	devtab[cchan->type]->write(cchan, name, strlen(name), 0);

	/* open data connection */
	fd = kopen(data, ORDWR);
	if(fd < 0){
		kwerrstr("can't open %s: %r", data);
		kclose(cfd);
		return -1;
	}
	if(ds->cfdp)
		*ds->cfdp = cfd;
	dchan = namec(data, Aopen, ORDWR, 0);
	if(ds->ctlp)
		*ds->ctlp = cchan;
	else
		kclose(cfd);
	return fd;
		cclose(cchan);
	poperror();
	return dchan;

}


M ip/ethermedium.c => ip/ethermedium.c +6 -22
@@ 6,7 6,6 @@
#include "../port/error.h"

#include "ip.h"
#include "kernel.h"

typedef struct Etherhdr Etherhdr;
struct Etherhdr


@@ 110,7 109,7 @@ etherbind(Ipifc *ifc, int argc, char **argv)
	char addr[2*NAMELEN];
	char dir[2*NAMELEN];
	char *buf;
	int fd, cfd, n;
	int n;
	char *ptr;
	Etherrock *er;



@@ 138,27 137,16 @@ etherbind(Ipifc *ifc, int argc, char **argv)
	 *  this device.
	 */
	snprint(addr, sizeof(addr), "%s!0x800", argv[2]);
	fd = kdial(addr, nil, dir, &cfd);
	if(fd < 0)
		error("dial 0x800 failed");
	mchan = commonfdtochan(fd, ORDWR, 0, 1);
	cchan = commonfdtochan(cfd, ORDWR, 0, 1);
	kclose(fd);
	kclose(cfd);
	mchan = chandial(addr, nil, dir, &cchan);

	/*
	 *  get mac address
	 */
	snprint(addr, sizeof(addr), "%s/stats", dir);
	fd = kopen(addr, OREAD);
	if(fd < 0)
		error("can't read ether stats");

	buf = smalloc(512);
	n = kread(fd, buf, 511);
	kclose(fd);
	if(n <= 0)
		error(Eio);
	achan = namec(addr, Aopen, OREAD, 0);
	n = devtab[achan->type]->read(achan, buf, 511, 0);
	cclose(achan);
	buf[n] = 0;

	ptr = strstr(buf, "addr: ");


@@ 172,11 160,7 @@ etherbind(Ipifc *ifc, int argc, char **argv)
 	 *  open arp conversation
	 */
	snprint(addr, sizeof(addr), "%s!0x806", argv[2]);
	fd = kdial(addr, nil, nil, nil);
	if(fd < 0)
		error("dial 0x806 failed");
	achan = commonfdtochan(fd, ORDWR, 0, 1);
	kclose(fd);
	achan = chandial(addr, nil, nil, nil);

	er = smalloc(sizeof(*er));
	er->mchan = mchan;

D ip/ihbootp.c => ip/ihbootp.c +0 -259
@@ 1,259 0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "kernel.h"
#include "ip.h"

static	ulong	fsip;
static	ulong	auip;
static	ulong	gwip;
static	ulong	ipmask;
static	ulong	ipaddr;

uchar	sys[NAMELEN];

enum
{
	Bootrequest = 1,
	Bootreply   = 2,
};

typedef struct Bootp
{
	uchar	op;		/* opcode */
	uchar	htype;		/* hardware type */
	uchar	hlen;		/* hardware address len */
	uchar	hops;		/* hops */
	uchar	xid[4];		/* a random number */
	uchar	secs[2];	/* elapsed snce client started booting */
	uchar	pad[2];
	uchar	ciaddr[4];	/* client IP address (client tells server) */
	uchar	yiaddr[4];	/* client IP address (server tells client) */
	uchar	siaddr[4];	/* server IP address */
	uchar	giaddr[4];	/* gateway IP address */
	uchar	chaddr[16];	/* client hardware address */
	uchar	sname[64];	/* server host name (optional) */
	uchar	file[128];	/* boot file name */
	uchar	vend[128];	/* vendor-specific goo */
} Bootp;

/*
 * bootp returns:
 *
 * "fsip d.d.d.d
 * auip d.d.d.d
 * gwip d.d.d.d
 * ipmask d.d.d.d
 * ipaddr d.d.d.d"
 *
 * where d.d.d.d is the IP address in dotted decimal notation, and each
 * address is followed by a newline.
 */
enum
{
	bootpreadlen = sizeof("fsip") + sizeof("auip") + sizeof("gwip")
		+ sizeof("ipmask") + sizeof("ipaddr")
		+ 5 * sizeof("000.000.000.000") + sizeof("")
};

static	Bootp	req;
static	int	recv;
static	int	done;
static	Rendez	bootpr;
static	char	rcvbuf[512];


/*
 * Parse the vendor specific fields according to RFC 1084.
 * We are overloading the "cookie server" to be the Inferno 
 * authentication server and the "resource location server"
 * to be the Inferno file server.
 *
 * If the vendor specific field is formatted properly, it
 * will being with the four bytes 99.130.83.99 and end with
 * an 0xFF byte.
 */
static void
parsevend(uchar* vend)
{
	/* The field must start with 99.130.83.99 to be compliant */
	if ((vend[0] != 99) || (vend[1] != 130) ||
	    (vend[2] != 83) || (vend[3] != 99))
		return;

	/* Skip over the magic cookie */
	vend += 4;

	while ((vend[0] != 0) && (vend[0] != 0xFF)) {
		switch (vend[0]) {
		case 1:	/* Subnet mask field */
			/* There must be only on subnet mask */
			if (vend[1] != 4)
				return;

			ipmask = (vend[2]<<24)|
				 (vend[3]<<16)|
				 (vend[4]<<8)|
				  vend[5];
			break;

		case 3:	/* Gateway/router field */
			/* We are only concerned with first address */
			if (vend[1] < 4)
				return;

			gwip =	(vend[2]<<24)|
				(vend[3]<<16)|
				(vend[4]<<8)|
				 vend[5];
			break;

		case 8:	/* "Cookie server" (auth server) field */
			/* We are only concerned with first address */
			if (vend[1] < 4)
				return;

			auip =	(vend[2]<<24)|
				(vend[3]<<16)|
				(vend[4]<<8)|
				 vend[5];
			break;

		case 11:	/* "Resource loc server" (file server) field */
			/* We are only concerned with first address */
			if (vend[1] < 4)
				return;

			fsip =	(vend[2]<<24)|
				(vend[3]<<16)|
				(vend[4]<<8)|
				 vend[5];
			break;

		default:	/* Everything else stops us */
			return;
		}

		/* Skip over the field */
		vend += vend[1] + 2;
	}
}

void
rcvbootp(void *a)
{
	int n, fd;
	Bootp *rp;

	fd = (int)a;
	while(done == 0) {
		n = kread(fd, rcvbuf, sizeof(rcvbuf));
		if(n <= 0)
			break;
		rp = (Bootp*)rcvbuf;
		if (memcmp(req.chaddr, rp->chaddr, 6) == 0 &&
		   rp->htype == 1 && rp->hlen == 6) {
			ipaddr = (rp->yiaddr[0]<<24)|
				 (rp->yiaddr[1]<<16)|
				 (rp->yiaddr[2]<<8)|
				  rp->yiaddr[3];
			parsevend(rp->vend);
			break;
		}
	}

	recv = 1;
	wakeup(&bootpr);
	pexit("", 0);
}

char*
bootp(Ipifc *ifc)
{
	int fd, tries, n;
	char ia[5+3*16], im[16], *av[3];
	char nipaddr[4], ngwip[4], nipmask[4];

	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcadd(ifc, av, 3);

	fd = kdial("udp!255.255.255.255!67", "68", nil, nil);
	if(fd < 0)
		return "bootp dial failed";

	/* create request */
	memset(&req, 0, sizeof(req));
	req.op = Bootrequest;
	req.htype = 1;			/* ethernet (all we know) */
	req.hlen = 6;			/* ethernet (all we know) */

	/* Hardware MAC address */
	memmove(req.chaddr, ifc->mac, 6);
	/* Fill in the local IP address if we know it */
	ipv4local(ifc, req.ciaddr);
	memset(req.file, 0, sizeof(req.file));
	strcpy((char*)req.vend, "p9  ");

	kproc("rcvbootp", rcvbootp, (void*)fd);

	/*
	 * broadcast bootp's till we get a reply,
	 * or fixed number of tries
	 */
	tries = 0;
	while(recv == 0) {
		if(kwrite(fd, &req, sizeof(req)) < 0)
			print("bootp: write: %r");

		tsleep(&bootpr, return0, 0, 1000);
		if(++tries > 10) {
			print("bootp: timed out\n");
			break;
		}
	}
	kclose(fd);
	done = 1;

	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcrem(ifc, av, 3, 1);

	hnputl(nipaddr, ipaddr);
	sprint(ia, "%V", nipaddr);
	hnputl(nipmask, ipmask);
	sprint(im, "%V", nipmask);
	av[1] = ia;
	av[2] = im;
	ipifcadd(ifc, av, 3);

	if(gwip != 0) {
		hnputl(ngwip, gwip);
		n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip);
		routewrite(ifc->conv->p->f, nil, ia, n);
	}
	return nil;
}

int
bootpread(char *bp, ulong offset, int len)
{
	int n;
	char buf[bootpreadlen], a[4];

	hnputl(a, fsip);
	n = sprint(buf, "fsip %15V\n", a);
	hnputl(a, auip);
	n += sprint(buf + n, "auip %15V\n", a);
	hnputl(a, gwip);
	n += sprint(buf + n, "gwip %15V\n", a);
	hnputl(a, ipmask);
	n += sprint(buf + n, "ipmask %15V\n", a);
	hnputl(a, ipaddr);
	sprint(buf + n, "ipaddr %15V\n", a);

	return readstr(offset, bp, len, buf);
}

M ip/ip.c => ip/ip.c +1 -1
@@ 5,7 5,7 @@
#include	"fns.h"
#include	"../port/error.h"

#include	"ip.h"
#include	"../ip/ip.h"

typedef struct Iphdr	Iphdr;
typedef struct Fragment	Fragment;

M ip/ip.h => ip/ip.h +5 -0
@@ 505,6 505,11 @@ char*		commonuser(void);
char*		commonerror(void);

/*
 * chandial.c
 */
extern Chan*	chandial(char*, char*, char*, Chan**);

/*
 *  global to all of the stack
 */
extern int	debug;

M ip/ipaux.c => ip/ipaux.c +0 -1
@@ 4,7 4,6 @@
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"kernel.h"
#include	"ip.h"

/*

M ip/ipifc.c => ip/ipifc.c +0 -2
@@ 630,8 630,6 @@ ipifcctl(Conv* c, char**argv, int argc)
	ifc = (Ipifc*)c->ptcl;
	if(strcmp(argv[0], "add") == 0)
		return ipifcadd(ifc, argv, argc);
 	else if(strcmp(argv[0], "bootp") == 0)
		return bootp(ifc);
	else if(strcmp(argv[0], "remove") == 0)
		return ipifcrem(ifc, argv, argc, 1);
	else if(strcmp(argv[0], "unbind") == 0)

D ip/kernel.h => ip/kernel.h +0 -15
@@ 1,15 0,0 @@
extern	long	kclose(int);
extern	int	kdial(char*, char*, char*, int*);
extern	void	kerrstr(char*);
extern	void	kgerrstr(char*);
extern	long	kopen(char*, int);
extern	long	kread(int, void*, long);
extern	long	kseek(int, vlong, int);
extern	long	kwrite(int, void*, long);
extern	void	kwerrstr(char *, ...);

extern	char*	strdup(char*);
extern	char*	strrchr(char*, char);
extern	char*	strstr(char*, char*);

extern int	newfd(Chan*);

D ip/kio.c => ip/kio.c +0 -199
@@ 1,199 0,0 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"kernel.h"

#define validaddr(a, b, c)

long
kclose(int fd)
{
	if(waserror())
		return -1;
	/*
	 * Take no reference on the chan because we don't really need the
	 * data structure, and are calling fdtochan only for error checks.
	 * fdclose takes care of processes racing through here.
	 */
	fdtochan(fd, -1, 0, 0);
	fdclose(fd, 0);

	poperror();
	return 0;
}

long
kopen(char *path, int mode)
{
	int fd;
	Chan *c = 0;

	if(waserror()) {
		if(c)
			cclose(c);
		return -1;
	}

	openmode(mode);
	validaddr((ulong)path, 1, 0);
	c = namec(path, Aopen, mode, 0);
	fd = newfd(c);

	poperror();
	return fd;
}

long
kread(int fd, void *va, long n)
{
	int dir;
	Chan *c;

	if(waserror())
		return -1;

	validaddr((ulong)va, n, 1);
	c = fdtochan(fd, OREAD, 1, 1);
	if(waserror()) {
		cclose(c);
		nexterror();
	}

	dir = c->qid.path&CHDIR;
	if(dir) {
		n -= n%DIRLEN;
		if(c->offset%DIRLEN || n==0)
			error(Etoosmall);
	}

	if(dir && c->mh)
		n = unionread(c, va, n);
	else if(devtab[c->type]->dc != L'M')
		n = devtab[c->type]->read(c, va, n, c->offset);
	else
		n = mntread9p(c, va, n, c->offset);

	lock(c);
	c->offset += n;
	unlock(c);

	poperror();
	cclose(c);

	poperror();
	return n;
}

long
kseek(int fd, vlong offset, int whence)
{
	Chan *c;
	char buf[DIRLEN];
	Dir dir;
	long off;

	if(waserror())
		return -1;

	c = fdtochan(fd, -1, 1, 1);
	if(waserror()) {
		cclose(c);
		nexterror();
	}
	if(c->qid.path & CHDIR)
		error(Eisdir);

	if(devtab[c->type]->dc == '|')
		error(Eisstream);

	off = 0;
	switch(whence) {
	case 0:
		off = offset;
		c->offset = offset;
		break;
	case 1:
		lock(c);	/* lock for read/write update */
		c->offset += offset;
		off = c->offset;
		unlock(c);
		break;
	case 2:
		devtab[c->type]->stat(c, buf);
		convM2D(buf, &dir);
		c->offset = dir.length + offset;
		off = c->offset;
		break;
	}
	poperror();
	cclose(c);
	poperror();
	return off;
}

long
kwrite(int fd, void *va, long n)
{
	Chan *c;

	if(waserror())
		return -1;

	validaddr((ulong)va, n, 0);
	c = fdtochan(fd, OWRITE, 1, 1);
	if(waserror()) {
		cclose(c);
		nexterror();
	}

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

	n = devtab[c->type]->write(c, va, n, c->offset);

	lock(c);
	c->offset += n;
	unlock(c);

	poperror();
	cclose(c);

	poperror();
	return n;
}

/* Set kernel error string */
void
kerrstr(char *err)
{
	if(up != nil)
		strncpy(up->error, err, ERRLEN);
}

/* Get kernel error string */
void
kgerrstr(char *err)
{
	char *s;

	s = "<no-up>";
	if(up != nil)
		s = up->error;
	strncpy(err, s, ERRLEN);
}

/* Set kernel error string, using formatted print */
void
kwerrstr(char *fmt, ...)
{
	va_list arg;
	char buf[256];

	va_start(arg, fmt);
	doprint(buf, buf+sizeof(buf), fmt, arg);
	va_end(arg);
	strncpy(up->error, buf, ERRLEN);
}

M ip/netdevmedium.c => ip/netdevmedium.c +1 -8
@@ 6,7 6,6 @@
#include "../port/error.h"

#include "ip.h"
#include "kernel.h"

static void	netdevbind(Ipifc *ifc, int argc, char **argv);
static void	netdevunbind(Ipifc *ifc);


@@ 41,19 40,13 @@ Medium netdevmedium =
static void
netdevbind(Ipifc *ifc, int argc, char **argv)
{
	int fd;
	Chan *mchan;
	Netdevrock *er;

	if(argc < 2)
		error(Ebadarg);

	fd = kopen(argv[2], ORDWR);
	if(fd < 0)
		error("fd open failed");

	mchan = commonfdtochan(fd, ORDWR, 0, 1);
	kclose(fd);
	mchan = namec(argv[2], Aopen, ORDWR, 0);

	er = smalloc(sizeof(*er));
	er->mchan = mchan;

M ip/nullmedium.c => ip/nullmedium.c +0 -1
@@ 6,7 6,6 @@
#include "../port/error.h"

#include "ip.h"
#include "kernel.h"

static void
nullbind(Ipifc*, int, char**)

M ip/pktmedium.c => ip/pktmedium.c +0 -1
@@ 6,7 6,6 @@
#include "../port/error.h"

#include "ip.h"
#include "kernel.h"


static void	pktbind(Ipifc *ifc, int argc, char **argv);

D ip/plan9.c => ip/plan9.c +0 -35
@@ 1,35 0,0 @@
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"ip.h"

/*
 *  some hacks for commonality twixt inferno and plan9
 */

char*
commonuser(void)
{
	return up->env->user;
}

Chan*
commonfdtochan(int fd, int mode, int a, int b)
{
	return fdtochan(up->env->fgrp, fd, mode, a, b);
}

char*
commonerror(void)
{
	return up->env->error;
}

int
postnote(Proc*, char*)
{
	return -1;
}

M ip/ptclbsum.c => ip/ptclbsum.c +0 -1
@@ 4,7 4,6 @@
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"kernel.h"
#include	"ip.h"

static	short	endian	= 1;

M ip/tripmedium.c => ip/tripmedium.c +0 -1
@@ 7,7 7,6 @@

#include "ip.h"
#include "trip.h"
#include "kernel.h"

static void	tripread(void *a);
static void	tripbind(Ipifc *ifc, int argc, char **argv);

M mpc/fns.h => mpc/fns.h +2 -2
@@ 10,7 10,7 @@ void	clockcheck(void);
void	clockinit(void);
void	clockintr(Ureg*);
void	clrfptrap(void);
#define coherence()		// not need on single processor machines
#define coherence()
void	cpminit(void);
int	cpuidentify(void);
void	cpuidprint(void);


@@ 88,7 88,7 @@ ulong	rmapalloc(RMap*, ulong, int, int);
void	screeninit(void);
void	setpanic(void);
int	screenprint(char*, ...);			/* debugging */
#define screenputs(x, y)		// no screen
#define screenputs(x, y)
ulong	sdraminit(ulong*);
int	segflush(void*, ulong);
void	spireset(void);

M pc/devi82365.c => pc/devi82365.c +1 -1
@@ 1027,7 1027,7 @@ pcmio(int slotno, ISAConf *isa)
	/* route interrupts */
	isa->irq = irq;
	wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
	

	/* set power and enable device */
	x = vcode(ct->vpp1);
	wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);

M port/lib.h => port/lib.h +1 -0
@@ 23,6 23,7 @@ extern	char	*strncat(char*, char*, long);
extern	char	*strncpy(char*, char*, long);
extern	int	strncmp(char*, char*, long);
extern	long	strlen(char*);
extern	char*	strstr(char*, char*);
extern	int	atoi(char*);

enum