~kris/9p

9hist

28a392d9a611b7bb06c6f7a08fe1a5a7bdb6064a — David du Colombier 28 years ago 1131845
Plan 9 from Bell Labs 1998-09-10
M pc/apic.c => pc/apic.c +8 -11
@@ 114,7 114,7 @@ lapiconline(void)
	 */
	microdelay((TK2MS(1)*1000/conf.nmach) * m->machno);
	lapicw(LapicTICR, clkin/HZ);
	lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|VectorTIMER);
	lapicw(LapicTIMER, LapicCLKIN|LapicPERIODIC|(VectorPIC+IrqTIMER));

	lapicw(LapicTPR, 0);
}


@@ 127,7 127,7 @@ lapictimerinit(void)

	v = m->cpumhz*1000;
	lapicw(LapicTDCR, LapicX1);
	lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|VectorTIMER);
	lapicw(LapicTIMER, ApicIMASK|LapicCLKIN|LapicONESHOT|(VectorPIC+IrqTIMER));

	if(clkin == 0){
		lapicw(LapicTICR, v);


@@ 154,7 154,7 @@ lapicinit(Apic* apic)
	r = (lapicr(LapicID)>>24) & 0xFF;
	lapicw(LapicLDR, (1<<r)<<24);
	lapicw(LapicTPR, 0xFF);
	lapicw(LapicSVR, LapicENABLE|VectorSPURIOUS);
	lapicw(LapicSVR, LapicENABLE|(VectorPIC+IrqSPURIOUS));

	lapictimerinit();



@@ 183,7 183,7 @@ lapicinit(Apic* apic)
	lvt = (lapicr(LapicVER)>>16) & 0xFF;
	if(lvt >= 4)
		lapicw(LapicPCINT, ApicIMASK);
	lapicw(LapicERROR, VectorERROR);
	lapicw(LapicERROR, VectorPIC+IrqERROR);
	lapicw(LapicESR, 0);
	lapicr(LapicESR);



@@ 271,8 271,6 @@ lapicicrw(int hi, int lo)
	lapicw(LapicICRLO, lo);
}

static int ioapicvecbase = VectorPIC;

void
ioapicrdtr(Apic* apic, int sel, int* hi, int* lo)
{


@@ 283,9 281,11 @@ ioapicrdtr(Apic* apic, int sel, int* hi, int* lo)

	lock(apic);
	*apic->addr = sel+1;
	*hi = *iowin;
	if(hi)
		*hi = *iowin;
	*apic->addr = sel;
	*lo = *iowin;
	if(lo)
		*lo = *iowin;
	unlock(apic);
}



@@ 322,9 322,6 @@ ioapicinit(Apic* apic, int apicno)
	*apic->addr = IoapicVER;
	apic->mre = (*iowin>>16) & 0xFF;

	apic->vecbase = ioapicvecbase;
	ioapicvecbase += apic->mre+1;

	*apic->addr = IoapicID;
	*iowin = apicno<<24;
	unlock(apic);

M pc/audio.h => pc/audio.h +1 -1
@@ 10,5 10,5 @@ enum
#define CACHELINESZ		8
#define UNCACHED(type, v)	(type*)((ulong)(v))

#define Int0vec			VectorPIC
#define Int0vec
#define setvec(v, f, a)		intrenable(v, f, a, BUSUNKNOWN)

M pc/dat.h => pc/dat.h +2 -37
@@ 1,7 1,5 @@
typedef struct Conf	Conf;
typedef struct FPsave	FPsave;
typedef struct Irq	Irq;
typedef struct Irqctl	Irqctl;
typedef struct ISAConf	ISAConf;
typedef struct Label	Label;
typedef struct Lock	Lock;


@@ 16,6 14,7 @@ typedef struct PMMU	PMMU;
typedef struct Proc	Proc;
typedef struct Segdesc	Segdesc;
typedef struct Ureg	Ureg;
typedef struct Vctl	Vctl;

/*
 *  parameters for sysproc.c


@@ 220,7 219,7 @@ struct PCArch
	int	(*modempower)(int);	/* 1 == on, 0 == off */

	void	(*intrinit)(void);
	int	(*intrenable)(int, int, Irqctl*);
	int	(*intrenable)(Vctl*);

	void	(*clockenable)(void);
	uvlong	(*fastclock)(uvlong*);


@@ 259,37 258,3 @@ Mach* machp[MAXMACH];

extern Mach	*m;
#define up	(((Mach*)MACHADDR)->externup)

/*
 *  SCSI bus
 */
enum {
	MaxScsi		= 4,
	NTarget		= 8,
};
struct Target {
	int	ctlrno;
	int	target;
	uchar*	inq;
	uchar*	scratch;

	Rendez	rendez;

	int	ok;
};
typedef int 	(*Scsiio)(Target*, int, uchar*, int, void*, int*);

typedef struct Irq {
	void	(*f)(Ureg*, void*);	/* handler to call */
	void*	a;			/* argument to call it with */

	Irq*	next;			/* link to next handler */
} Irq;

typedef struct Irqctl {
	int	(*isr)(int);		/* get isr bit for this irq */
	int	(*eoi)(int);		/* eoi */
	int	isintr;

	Irq*	irq;			/* handlers on this IRQ */
} Irqctl;

M pc/devastar.c => pc/devastar.c +2 -2
@@ 1053,14 1053,14 @@ startcp(Astar *a)
		 * Which bits in the interrupt control register should be set?
		 */
		outl(a->port+PCIcontrol, 0x00031F00);
		intrenable(VectorPIC + a->irq, astarintr, a, a->pci->tbdf);
		intrenable(a->irq, astarintr, a, a->pci->tbdf);
	}
	else{
		c = inb(a->port+ISActl1);
		c &= ~ISAirq;
		c |= ISAien|isairqcode[a->irq];
		outb(a->port+ISActl1, c);
		intrenable(VectorPIC + a->irq, astarintr, a, BUSUNKNOWN);
		intrenable(a->irq, astarintr, a, BUSUNKNOWN);
	}

	/* enable control program interrupt generation */

M pc/devata.c => pc/devata.c +1 -1
@@ 556,7 556,7 @@ atactlrreset(void)
				resetok = 1;
		}

		if(atactlrprobe(ctlrno, VectorPIC+isa.irq, resetok))
		if(atactlrprobe(ctlrno, isa.irq, resetok))
			continue;

		if(spindown == 0 || atadrive[driveno] == 0)

M pc/devether.c => pc/devether.c +1 -1
@@ 354,7 354,7 @@ etherreset(void)
			 */
			if(ether->irq == 2)
				ether->irq = 9;
			intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf);
			intrenable(ether->irq, ether->interrupt, ether, ether->tbdf);

			i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
				ctlrno, ether->type, ether->mbps, ether->port, ether->irq);

M pc/devi82365.c => pc/devi82365.c +6 -6
@@ 600,7 600,7 @@ static void
i82365reset(void)
{
	static int already;
	int i, j, vector;
	int i, j, irq;
	I82365 *cp;
	Slot *pp;
	ISAConf isa;


@@ 610,9 610,9 @@ i82365reset(void)
	already = 1;

	memset(&isa, 0, sizeof(ISAConf));
	vector = VectorPCMCIA;
	irq = IrqPCMCIA;
	if(isaconfig("pcmcia", 0, &isa) && isa.irq)
		vector = VectorPIC+isa.irq;
		irq = isa.irq;

	/* look for controllers */
	i82386probe(0x3E0, 0x3E1, 0);


@@ 628,7 628,7 @@ i82365reset(void)
	for(i = 0; i < ncontroller; i++){
		cp = controller[i];
		print("#y%d: %d slot %s: port 0x%uX irq %d\n",
			i, cp->nslot, chipname[cp->type], cp->xreg, vector-VectorPIC);
			i, cp->nslot, chipname[cp->type], cp->xreg, irq);
		for(j = 0; j < cp->nslot; j++){
			pp = lastslot++;
			pp->slotno = pp - slot;


@@ 638,14 638,14 @@ i82365reset(void)
			slotdis(pp);

			/* interrupt on status change */
			wrreg(pp, Rcscic, ((vector-VectorPIC)<<4) | Fchangeena);
			wrreg(pp, Rcscic, (irq<<4) | Fchangeena);
			rdreg(pp, Rcsc);
		}
	}

	/* for card management interrupts */
	if(ncontroller)
		intrenable(vector, i82365intr, 0, BUSUNKNOWN);
		intrenable(irq, i82365intr, 0, BUSUNKNOWN);
}

static Chan*

M pc/devlpt.c => pc/devlpt.c +1 -1
@@ 80,7 80,7 @@ lptattach(char *spec)
	if(!set){
		outb(lptbase[i-1]+Qpcr, 0);	/* turn off interrupts */
		set = 1;
		intrenable(VectorLPT, lptintr, 0, BUSUNKNOWN);
		intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN);
	}
	if(i < 1 || i > NDEV)
		error(Ebadarg);

M pc/floppy.h => pc/floppy.h +1 -1
@@ 157,7 157,7 @@ floppysetup1(FController *fl)
		floppysetdef(&fl->d[1]);
	}

	intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
	intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN);
}

/*

M pc/fns.h => pc/fns.h +4 -2
@@ 2,7 2,7 @@

void	aamloop(int);
void	addconf(char*, char*);
void	addscsilink(char*, Scsiio (*)(int, ISAConf*));
//void	addscsilink(char*, Scsiio (*)(int, ISAConf*));
void	archinit(void);
void	bootargs(ulong);
int	cistrcmp(char*, char*);


@@ 38,7 38,7 @@ void	i8253init(int);
void	i8253enable(void);
uvlong	i8253read(uvlong*);
void	i8259init(void);
int	i8259enable(int, int, Irqctl*);
int	i8259enable(Vctl*);
void	idle(void);
int	inb(int);
void	insb(int, void*, int);


@@ 81,6 81,7 @@ void	pcicfgw16(Pcidev*, int, int);
void	pcicfgw32(Pcidev*, int, int);
void	pcihinv(Pcidev*);
Pcidev* pcimatch(Pcidev*, int, int);
Pcidev* pcimatchtbdf(int);
void	pcireset(void);
PCMmap*	pcmmap(int, ulong, int, int);
int	pcmspecial(char*, ISAConf*);


@@ 97,6 98,7 @@ void	screeninit(void);
int	screenprint(char*, ...);			/* debugging */
void	(*screenputs)(char*, int);
void	touser(void*);
void	trapenable(int, void (*)(Ureg*, void*), void*);
void	trapinit(void);
int	tas(void*);
ulong	umbmalloc(ulong, int, int);

M pc/i8253.c => pc/i8253.c +1 -1
@@ 111,7 111,7 @@ i8253init(int aalcycles)
void
i8253enable(void)
{
	intrenable(VectorCLOCK, clockintr, 0, BUSUNKNOWN);
	intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN);
}

/*

M pc/i8259.c => pc/i8259.c +37 -28
@@ 27,20 27,21 @@ enum

static int int0mask;			/* interrupts enabled for first 8259 */
static int int1mask;			/* interrupts enabled for second 8259 */

int elcr;				/* mask of level-triggered interrupts */
static int elcr;			/* mask of level-triggered interrupts */
static Lock i8259lock;

void
i8259init(void)
{
	int elcr1;

	ilock(&i8259lock);
	int0mask = 0xFF;
	int1mask = 0xFF;

	/*
	 *  Set up the first 8259 interrupt processor.
	 *  Make 8259 interrupts start at CPU vector Int0vec.
	 *  Make 8259 interrupts start at CPU vector VectorPIC.
	 *  Set the 8259 as master with edge triggered
	 *  input with fully nested interrupts.
	 */


@@ 91,59 92,67 @@ i8259init(void)
			elcr = (inb(Elcr2)<<8)|elcr1;
	}
	outb(Elcr1, elcr1);
	iunlock(&i8259lock);
//	if(elcr)
//		print("ELCR: %4.4uX\n", elcr);
}

int
i8259isr(int v)
i8259isr(int vno)
{
	int isr;

	if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC)
		return 0;

	/*
	 *  tell the 8259 that we're done with the
	 *  highest level interrupt (interrupts are still
	 *  off at this point)
	 */
	isr = 0;
	if(v >= VectorPIC && v <= MaxVectorPIC){
		isr = inb(Int0ctl);
		outb(Int0ctl, EOI);
		if(v >= VectorPIC+8){
			isr |= inb(Int1ctl)<<8;
			outb(Int1ctl, EOI);
		}
	ilock(&i8259lock);
	isr = inb(Int0ctl);
	outb(Int0ctl, EOI);
	if(vno >= VectorPIC+8){
		isr |= inb(Int1ctl)<<8;
		outb(Int1ctl, EOI);
	}
	iunlock(&i8259lock);

	return isr & (1<<(v-VectorPIC));
	return isr & (1<<(vno-VectorPIC));
}

int
i8259enable(int v, int, Irqctl* irqctl)
i8259enable(Vctl* v)
{
	if(v < VectorPIC || v > MaxVectorPIC){
		print("i8259enable: vector %d out of range\n", v);
		return -1;
	}
	v -= VectorPIC;
	int irq;

	/*
	 *  enable corresponding interrupt in 8259
	 * Given an IRQ, enable the corresponding interrupt in the i8259
	 * and return the vector to be used. The i8259 is set to use a fixed
	 * range of vectors starting at VectorPIC.
	 */
	if(v < 8){
		int0mask &= ~(1<<v);
	irq = v->irq;
	if(irq < 0 || irq > MaxIrqPIC){
		print("i8259enable: irq %d out of range\n", irq);
		return -1;
	}

	ilock(&i8259lock);
	if(irq < 8){
		int0mask &= ~(1<<irq);
		outb(Int0aux, int0mask);
	}
	else{
		int1mask &= ~(1<<(v-8));
		int1mask &= ~(1<<(irq-8));
		outb(Int1aux, int1mask);
	}

	if(elcr & (1<<v))
		irqctl->eoi = i8259isr;
	if(elcr & (1<<irq))
		v->eoi = i8259isr;
	else
		irqctl->isr = i8259isr;
	irqctl->isintr = 1;
		v->isr = i8259isr;
	iunlock(&i8259lock);

	return v;
	return VectorPIC+irq;
}

M pc/io.h => pc/io.h +62 -23
@@ 10,34 10,48 @@ enum {
	VectorPF	= 14,		/* page fault */
	VectorCERR	= 16,		/* coprocessor error */

	VectorINTR	= 32,		/* maskable interrupts */

	VectorLAPIC	= 32,		/* local APIC interrupts */
	VectorLINT0	= VectorLAPIC+0,/* LINT[01] must be offsets 0 and 1 */
	VectorLINT1	= VectorLAPIC+1,
	VectorTIMER	= VectorLAPIC+2,
	VectorERROR	= VectorLAPIC+3,
	VectorPCINT	= VectorLAPIC+4,
	VectorSPURIOUS	= VectorLAPIC+15,/* must have bits [3-0] == 0x0F */
	MaxVectorLAPIC	= VectorLAPIC+15,
	VectorPIC	= 32,		/* external i8259 interrupts */
	IrqCLOCK	= 0,
	IrqKBD		= 1,
	IrqUART1	= 3,
	IrqUART0	= 4,
	IrqPCMCIA	= 5,
	IrqFLOPPY	= 6,
	IrqLPT		= 7,
	IrqIRQ7		= 7,
	IrqAUX		= 12,		/* PS/2 port */
	IrqIRQ13	= 13,		/* coprocessor on 386 */
	IrqATA0		= 14,
	MaxIrqPIC	= 15,

	VectorLAPIC	= VectorPIC+16,	/* local APIC interrupts */
	IrqLINT0	= 16,		/* LINT[01] must be offsets 0 and 1 */
	IrqLINT1	= 17,
	IrqTIMER	= 18,
	IrqERROR	= 19,
	IrqPCINT	= 20,
	IrqSPURIOUS	= 31,		/* must have bits [3-0] == 0x0F */
	MaxIrqLAPIC	= 31,

	VectorSYSCALL	= 64,

	VectorPIC	= 128,		/* external [A]PIC interrupts */
	VectorCLOCK	= VectorPIC+0,
	VectorKBD	= VectorPIC+1,
	VectorUART1	= VectorPIC+3,
	VectorUART0	= VectorPIC+4,
	VectorPCMCIA	= VectorPIC+5,
	VectorFLOPPY	= VectorPIC+6,
	VectorLPT	= VectorPIC+7,
	VectorIRQ7	= VectorPIC+7,
	VectorAUX	= VectorPIC+12,	/* PS/2 port */
	VectorIRQ13	= VectorPIC+13,	/* coprocessor on x386 */
	VectorATA0	= VectorPIC+14,
	MaxVectorPIC	= VectorPIC+15,
	VectorAPIC	= 65,		/* external APIC interrupts */
	MaxVectorAPIC	= 255,
};

typedef struct Vctl {
	Vctl*	next;			/* handlers on this vector */

	int	isintr;			/* interrupt or fault/trap */
	int	irq;
	int	tbdf;
	int	(*isr)(int);		/* get isr bit for this irq */
	int	(*eoi)(int);		/* eoi */

	void	(*f)(Ureg*, void*);	/* handler to call */
	void*	a;			/* argument to call it with */
} Vctl;

enum {
	BusCBUS		= 0,		/* Corollary CBUS */
	BusCBUSII,			/* Corollary CBUS II */


@@ 163,3 177,28 @@ struct PCMmap {
	int	attr;			/* attribute memory */
	int	ref;
};

/*
 *  SCSI bus
 */
enum {
	MaxScsi		= 8,
	NTarget		= 8,		/* should be 16... */
};
struct Target {
	int	ctlrno;
	int	target;
	uchar*	inq;
	uchar*	scratch;

	Rendez	rendez;

	int	ok;
};

typedef int (*Scsiio)(Target*, int, uchar*, int, void*, int*);

typedef struct SCSIdev {
	char*	type;
	Scsiio	(*reset)(int, ISAConf*);
} SCSIdev;

M pc/kbd.c => pc/kbd.c +2 -2
@@ 372,7 372,7 @@ i8042auxenable(void (*putc)(int, int))
		return;
	}
	auxputc = putc;
	intrenable(VectorAUX, i8042intr, 0, BUSUNKNOWN);
	intrenable(IrqAUX, i8042intr, 0, BUSUNKNOWN);
	iunlock(&i8042lock);
}



@@ 386,7 386,7 @@ kbdinit(void)
		panic("kbdinit");
	qnoblock(kbdq, 1);

	intrenable(VectorKBD, i8042intr, 0, BUSUNKNOWN);
	intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN);

	/* wait for a quiescent controller */
	while((c = inb(Status)) & (Outbusy | Inready))

M pc/main.c => pc/main.c +9 -9
@@ 408,7 408,7 @@ confinit(void)
			poolsetparam("Image", 0, 0, 4*1024*1024);
		/*
		 * give terminals lots of image memory, too; the dynamic
		 * allocation will balance the load properly, we hope.
		 * allocation will balance the load properly, hopefully.
		 * be careful with 32-bit overflow.
		 */
		poolsetparam("Image", (BY2PG*conf.npage/100)*(100-pcnt), 0, 0);


@@ 427,7 427,7 @@ confinit(void)
	conf.nimage = 200;
}

char *mathmsg[] =
static char* mathmsg[] =
{
	"invalid",
	"denormalized",


@@ 442,7 442,7 @@ char *mathmsg[] =
/*
 *  math coprocessor error
 */
void
static void
matherror(Ureg *ur, void*)
{
	ulong status;


@@ 482,7 482,7 @@ matherror(Ureg *ur, void*)
/*
 *  math coprocessor emulation fault
 */
void
static void
mathemu(Ureg*, void*)
{
	switch(up->fpstate){


@@ 503,7 503,7 @@ mathemu(Ureg*, void*)
/*
 *  math coprocessor segment overrun
 */
void
static void
mathover(Ureg*, void*)
{
	pexit("math overrun", 0);


@@ 512,11 512,11 @@ mathover(Ureg*, void*)
void
mathinit(void)
{
	intrenable(VectorCERR, matherror, 0, BUSUNKNOWN);
	trapenable(VectorCERR, matherror, 0);
	if(X86FAMILY(m->cpuidax) == 3)
		intrenable(VectorIRQ13, matherror, 0, BUSUNKNOWN);
	intrenable(VectorCNA, mathemu, 0, BUSUNKNOWN);
	intrenable(VectorCSO, mathover, 0, BUSUNKNOWN);
		intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN);
	trapenable(VectorCNA, mathemu, 0);
	trapenable(VectorCSO, mathover, 0);
}

/*

M pc/mp.c => pc/mp.c +96 -60
@@ 19,6 19,7 @@ static Apic mpapic[MaxAPICNO+1];
static int machno2apicno[MaxAPICNO+1];	/* inverse map: machno -> APIC ID */
static Lock mprdthilock;
static int mprdthi;
static Ref mpvnoref;			/* unique vector assignment */

static char* buses[] = {
	"CBUSI ",


@@ 54,7 55,6 @@ mkprocessor(PCMPprocessor* p)
	apic->type = PcmpPROCESSOR;
	apic->apicno = p->apicno;
	apic->flags = p->flags;
	apic->vecbase = VectorLAPIC;
	apic->lintr[0] = ApicIMASK;
	apic->lintr[1] = ApicIMASK;



@@ 183,7 183,7 @@ mkiointr(PCMPintr* p)
}

static int
mpintrinit(Bus* bus, PCMPintr* intr, int vector)
mpintrinit(Bus* bus, PCMPintr* intr, int vno)
{
	int el, po, v;



@@ 191,7 191,7 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vector)
	 * Parse an I/O or Local APIC interrupt table entry and
	 * return the encoded vector.
	 */
	v = vector;
	v = vno;

	po = intr->flags & PcmpPOMASK;
	el = intr->flags & PcmpELMASK;


@@ 230,7 230,7 @@ mpintrinit(Bus* bus, PCMPintr* intr, int vector)

	/*
	 */
	if(bus->type == BusEISA && !po && !el /*&& !(elcr & (1<<(v-VectorPIC)))*/){
	if(bus->type == BusEISA && !po && !el){
		po = PcmpHIGH;
		el = PcmpEDGE;
	}


@@ 265,8 265,6 @@ mklintr(PCMPintr* p)
	/*
	 * The offsets of vectors for LINT[01] are known to be
	 * 0 and 1 from the local APIC vector space at VectorLAPIC.
	 * Can't use apic->vecbase here as this vector may be applied
	 * to all local APICs (apicno == 0xFF).
	 */
	if((bus = mpgetbus(p->busno)) == 0)
		return 0;


@@ 274,7 272,7 @@ mklintr(PCMPintr* p)

	/*
	 * Pentium Pros have problems if LINT[01] are set to ExtINT
	 * so just bag it. Should be OK for SMP mode.
	 * so just bag it, SMP mode shouldn't need ExtINT anyway.
	 */
	if(p->intr == PcmpExtINT || p->intr == PcmpNMI)
		v = ApicIMASK;


@@ 545,9 543,9 @@ mpinit(void)
	 * and do not appear in the I/O APIC so it is OK
	 * to set them now.
	 */
	intrenable(VectorTIMER, clockintr, 0, BUSUNKNOWN);
	intrenable(VectorERROR, lapicerror, 0, BUSUNKNOWN);
	intrenable(VectorSPURIOUS, lapicspurious, 0, BUSUNKNOWN);
	intrenable(IrqTIMER, clockintr, 0, BUSUNKNOWN);
	intrenable(IrqERROR, lapicerror, 0, BUSUNKNOWN);
	intrenable(IrqSPURIOUS, lapicspurious, 0, BUSUNKNOWN);
	lapiconline();

	checkmtrr();


@@ 570,81 568,114 @@ mpinit(void)
}

static int
mpintrenablex(int v, int tbdf, Irqctl* irqctl)
mpintrenablex(Vctl* v)
{
	Bus *bus;
	Aintr *aintr;
	Apic *apic;
	int bno, dno, lo, n, type;
	Pcidev *pcidev;
	int bno, dno, irq, lo, n, type, vno;

	/*
	 * Find the bus, default is ISA.
	 * There cannot be multiple ISA or EISA buses.
	 */
	type = BUSTYPE(tbdf);
	bno = BUSBNO(tbdf);
	dno = BUSDNO(tbdf);
	type = BUSTYPE(v->tbdf);
	bno = BUSBNO(v->tbdf);
	dno = BUSDNO(v->tbdf);
	n = 0;
	for(bus = mpbus; bus; bus = bus->next){
	for(bus = mpbus; bus != nil; bus = bus->next){
		if(bus->type != type)
			continue;
		if(n == bno)
			break;
		n++;
	}
	if(bus == 0){
	if(bus == nil){
		print("ioapicirq: can't find bus type %d\n", type);
		return -1;
	}

	/*
	 * Find the interrupt info.
	 * For PCI devices the interrupt pin (INT[ABCD]) and device
	 * number are encoded into the entry irq field, so create something
	 * to match on. The interrupt pin used by the device has to be
	 * obtained from the PCI config space.
	 */
	if(bus->type == BusPCI){
		pcidev = pcimatchtbdf(v->tbdf);
		if(pcidev != nil && (n = pcicfgr8(pcidev, PciINTP)) != 0)
			irq = (dno<<2)|(n-1);
		else
			irq = -1;
		//print("pcidev %uX: irq %uX v->irq %uX\n", v->tbdf, irq, v->irq);
	}
	else
		irq = v->irq;

	/*
	 * Find a matching interrupt entry from the list of interrupts
	 * attached to this bus.
	 */
	for(aintr = bus->aintr; aintr; aintr = aintr->next){
		if(bus->type == BusPCI){
			n = (aintr->intr->irq>>2) & 0x1F;
			if(n != dno)
				continue;
			/*
			 * Problem: there can be an entry for
			 * each of the device #INT[ABCD] lines.
			 * For now look only for #INTA.
			 */
			if(aintr->intr->irq & 0x03)
				continue;
		}
		else{
			n = aintr->intr->irq;
			if(n != (v-VectorPIC))
				continue;
		if(aintr->intr->irq != irq)
			continue;

		/*
		 * Check not already enabled. This is a bad thing as it implies the
		 * same device is requesting the same interrupt to be enabled multiple
		 * times. The RDT read here is safe for now as currently interrupts
		 * are never disabled once enabled.
		 */
		apic = aintr->apic;
		ioapicrdtr(apic, aintr->intr->intin, 0, &lo);
		if(!(lo & ApicIMASK)){
			print("mpintrenable: multiple enable of irq %d, tbdf %uX\n",
				v->irq, v->tbdf);
			return -1;
		}

		lo = mpintrinit(bus, aintr->intr, v);
		/*
		 * With the APIC a unique vector can be assigned to each request
		 * to enable an interrupt. There are two reasons this is a good idea:
		 * 1) to prevent lost interrupts, no more than 2 interrupts should
		 *    be assigned per block of 16 vectors (there is an in-service
		 *    entry and a holding entry for each priority level and there is
		 *    a priority level per block of 16 interrupts).
		 * 2) each input pin on the IOAPIC will receive a different vector
		 *    regardless of whether the devices on that pin use the same IRQ
		 *    as devices on another pin.
		 */
		vno = VectorAPIC + (incref(&mpvnoref)-1)*8;
		if(vno > MaxVectorAPIC){
			print("mpintrenable: vno %d, irq %d, tbdf %uX\n",
				vno, v->irq, v->tbdf);
			return -1;
		}
		lo = mpintrinit(bus, aintr->intr, vno);
		if(lo & ApicIMASK)
			return -1;
		lo |= ApicLOGICAL;

		apic = aintr->apic;
		if((apic->flags & PcmpEN) && apic->type == PcmpIOAPIC){
			lock(&mprdthilock);
 			ioapicrdtw(apic, aintr->intr->intin, mprdthi, lo);
			unlock(&mprdthilock);
		}

		irqctl->isr = lapicisr;
		irqctl->eoi = lapiceoi;
		irqctl->isintr = 1;
		v->isr = lapicisr;
		v->eoi = lapiceoi;

		return lo & 0xFF;
		return vno;
	}

	return -1;
}

int
mpintrenable(int v, int tbdf, Irqctl* irqctl)
mpintrenable(Vctl* v)
{
	int r;
	int irq, tbdf, vno;

	/*
	 * If the bus is known, try it.


@@ 652,23 683,24 @@ mpintrenable(int v, int tbdf, Irqctl* irqctl)
	 * interrupts local to the processor (local APIC, coprocessor
	 * breakpoint and page-fault).
	 */
	if(tbdf != BUSUNKNOWN && (r = mpintrenablex(v, tbdf, irqctl)) != -1)
		return r;

	if(v >= VectorLAPIC && v <= MaxVectorLAPIC){
		if(v != VectorSPURIOUS)
			irqctl->isr = lapiceoi;
		irqctl->isintr = 1;
		return v;
	tbdf = v->tbdf;
	if(tbdf != BUSUNKNOWN && (vno = mpintrenablex(v)) != -1)
		return vno;

	irq = v->irq;
	if(irq >= IrqLINT0 && irq <= MaxIrqLAPIC){
		if(irq != IrqSPURIOUS)
			v->isr = lapiceoi;
		return VectorPIC+irq;
	}
	if(v < VectorPIC || v > MaxVectorPIC){
		print("mpintrenable: vector %d out of range\n", v);
	if(irq < 0 || irq > MaxIrqPIC){
		print("mpintrenable: irq %d out of range\n", irq);
		return -1;
	}

	/*
	 * Either didn't find it or we have to try the default
	 * buses (ISA and EISA). This hack is due to either over-zealousness
	 * Either didn't find it or have to try the default buses
	 * (ISA and EISA). This hack is due to either over-zealousness 
	 * or laziness on the part of some manufacturers.
	 *
	 * The MP configuration table on some older systems


@@ 678,14 710,16 @@ mpintrenable(int v, int tbdf, Irqctl* irqctl)
	 * be compatible with ISA.
	 */
	if(mpisabus != -1){
		r = mpintrenablex(v, MKBUS(BusISA, 0, 0, 0), irqctl);
		if(r != -1)
			return r;
		v->tbdf = MKBUS(BusISA, 0, 0, 0);
		vno = mpintrenablex(v);
		if(vno != -1)
			return vno;
	}
	if(mpeisabus != -1){
		r = mpintrenablex(v, MKBUS(BusEISA, 0, 0, 0), irqctl);
		if(r != -1)
			return r;
		v->tbdf = MKBUS(BusEISA, 0, 0, 0);
		vno = mpintrenablex(v);
		if(vno != -1)
			return vno;
	}

	return -1;


@@ 704,8 738,10 @@ mpshutdown(void)
		 * If this processor received the CTRL-ALT-DEL from
		 * the keyboard, acknowledge it. Send an INIT to self.
		 */
#ifdef FIXTHIS
		if(lapicisr(VectorKBD))
			lapiceoi(VectorKBD);
#endif /* FIX THIS */
		idle();
	}


M pc/mp.h => pc/mp.h +1 -2
@@ 158,7 158,6 @@ typedef struct Apic {
	int	apicno;
	ulong*	addr;			/* register base address */
	int	flags;			/* PcmpBP|PcmpEN */
	int	vecbase;		/* starting vector offset */

	Lock;				/* I/O APIC: register access */
	int	mre;			/* I/O APIC: maximum redirection entry */


@@ 221,6 220,6 @@ extern void lapicicrw(int, int);

extern void mpinit(void);
extern void mpshutdown(void);
extern int mpintrenable(int, int, Irqctl*);
extern int mpintrenable(Vctl*);

extern _MP_ *_mp_;

M pc/ns16552.h => pc/ns16552.h +2 -2
@@ 94,9 94,9 @@ ns16552install(void)

	/* first two ports are always there and always the normal frequency */
	ns16552setup(0x3F8, UartFREQ, "eia0");
	intrenable(VectorUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	intrenable(IrqUART0, ns16552intrx, (void*)0, BUSUNKNOWN);
	ns16552setup(0x2F8, UartFREQ, "eia1");
	intrenable(VectorUART1, ns16552intrx, (void*)1, BUSUNKNOWN);
	intrenable(IrqUART1, ns16552intrx, (void*)1, BUSUNKNOWN);
	addclock0link(uartclock);

	/* set up a serial console */

M pc/pcmciamodem.c => pc/pcmciamodem.c +1 -0
@@ 49,6 49,7 @@ pcmciamodemlink(void)
		if(isa.port == 0)
			isa.port = 0x2F8;

		slot = -1;
		for(j = 0; modems[j]; j++){
			slot = pcmspecial(modems[j], &isa);
			if(slot >= 0)

M pc/scsi.c => pc/scsi.c +8 -36
@@ 7,8 7,7 @@
#include "ureg.h"
#include "../port/error.h"

enum
{
enum {
	Ninq		= 255,
	Nscratch	= 255,



@@ 22,49 21,22 @@ enum
	CMDwrite10	= 0x2A,
};

typedef struct
{
typedef struct {
	ISAConf;
	Scsiio	io;

	Target	target[NTarget];
} Ctlr;

static	Ctlr*	scsi[MaxScsi];

typedef struct Link Link;
typedef struct Link
{
	char	*type;
	Scsiio	(*reset)(int, ISAConf*);

	Link*	link;
} Link;

static Link *link;
static int linkcount;
static Ctlr* scsi[MaxScsi];

void
addscsilink(char *t, Scsiio (*r)(int, ISAConf*))
{
	Link *lp;

	if((lp = xalloc(sizeof(Link))) == 0)
		return;
	lp->type = t;
	lp->reset = r;

	lp->link = link;
	link = lp;
	linkcount++;
}
extern SCSIdev* scsidev[];

void
scsireset(void)
{
	Ctlr *ctlr;
	int ctlrno, t;
	Link *lp;
	int ctlrno, i, t;

	for(ctlr = 0, ctlrno = 0; ctlrno < MaxScsi; ctlrno++){
		if(ctlr == 0)


@@ 72,10 44,10 @@ scsireset(void)
		memset(ctlr, 0, sizeof(Ctlr));
		if(isaconfig("scsi", ctlrno, ctlr) == 0)
			continue;
		for(lp = link; lp; lp = lp->link){
			if(strcmp(lp->type, ctlr->type))
		for(i = 0; scsidev[i]; i++){
			if(strcmp(ctlr->type, scsidev[i]->type))
				continue;
			if((ctlr->io = lp->reset(ctlrno, ctlr)) == 0)
			if((ctlr->io = scsidev[i]->reset(ctlrno, ctlr)) == 0)
				break;

			print("scsi#%d: %s: port 0x%luX irq %lud",

M pc/trap.c => pc/trap.c +109 -75
@@ 12,36 12,58 @@ void	noted(Ureg*, ulong);
static void debugbpt(Ureg*, void*);
static void fault386(Ureg*, void*);

static Lock irqctllock;
static Irqctl *irqctl[256];
static Lock vctllock;
static Vctl *vctl[256];

void
intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf)
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf)
{
	Irq *irq;
	Irqctl *ctl;

	lock(&irqctllock);
	if(irqctl[v] == 0)
		irqctl[v] = xalloc(sizeof(Irqctl));
	ctl = irqctl[v];

	if(v >= VectorINTR && arch->intrenable(v, tbdf, ctl) == -1){
		if(ctl->irq == nil){
			irqctl[v] = nil;
			xfree(ctl);
		}
		unlock(&irqctllock);
		print("intrenable: didn't find v %d, tbdf 0x%uX\n", v, tbdf);
	int vno;
	Vctl *v;

	v = xalloc(sizeof(Vctl));
	v->isintr = 1;
	v->irq = irq;
	v->tbdf = tbdf;
	v->f = f;
	v->a = a;

	ilock(&vctllock);
	vno = arch->intrenable(v);
	//print("irq%d, vno %d\n", irq, vno);
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX\n", irq, tbdf);
		xfree(v);
		return;
	}
	if(vctl[vno]){
		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
			panic("intrenable: irq handler botch: %luX %luX %luX %luX\n",
				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
		v->next = vctl[vno]->next;
	}
	vctl[vno] = v;
	iunlock(&vctllock);
}

	irq = xalloc(sizeof(Irq));
	irq->f = f;
	irq->a = a;
	irq->next = ctl->irq;
	ctl->irq = irq;
	unlock(&irqctllock);
void
trapenable(int vno, void (*f)(Ureg*, void*), void* a)
{
	Vctl *v;

	if(vno < 0 || vno >= VectorPIC)
		panic("trapenable: vno %d\n", vno);
	v = xalloc(sizeof(Vctl));
	v->tbdf = BUSUNKNOWN;
	v->f = f;
	v->a = a;

	lock(&vctllock);
	if(vctl[vno])
		v->next = vctl[vno]->next;
	vctl[vno] = v;
	unlock(&vctllock);
}

static void


@@ 94,32 116,45 @@ trapinit(void)
	 * Special traps.
	 * Syscall() is called directly without going through trap().
	 */
	intrenable(VectorBPT, debugbpt, 0, BUSUNKNOWN);
	intrenable(VectorPF, fault386, 0, BUSUNKNOWN);
	trapenable(VectorBPT, debugbpt, 0);
	trapenable(VectorPF, fault386, 0);

	nmienable();
}

static char *excname[] = {
	[0]	"divide error",
	[1]	"debug exception",
	[2]	"nonmaskable interrupt",
	[3]	"breakpoint",
	[4]	"overflow",
	[5]	"bounds check",
	[6]	"invalid opcode",
	[7]	"coprocessor not available",
	[8]	"double fault",
	[9]	"coprocessor segment overrun",
	[10]	"invalid TSS",
	[11]	"segment not present",
	[12]	"stack exception",
	[13]	"general protection violation",
	[14]	"page fault",
	[15]	"15 (reserved)",
	[16]	"coprocessor error",
	[17]	"alignment check",
	[18]	"machine check",
static char* excname[32] = {
	"divide error",
	"debug exception",
	"nonmaskable interrupt",
	"breakpoint",
	"overflow",
	"bounds check",
	"invalid opcode",
	"coprocessor not available",
	"double fault",
	"coprocessor segment overrun",
	"invalid TSS",
	"segment not present",
	"stack exception",
	"general protection violation",
	"page fault",
	"15 (reserved)",
	"coprocessor error",
	"alignment check",
	"machine check",
	"19 (reserved)",
	"20 (reserved)",
	"21 (reserved)",
	"22 (reserved)",
	"23 (reserved)",
	"24 (reserved)",
	"25 (reserved)",
	"26 (reserved)",
	"27 (reserved)",
	"28 (reserved)",
	"29 (reserved)",
	"30 (reserved)",
	"31 (reserved)",
};

/*


@@ 131,10 166,9 @@ static char *excname[] = {
void
trap(Ureg* ureg)
{
	int i, v, user;
	int i, vno, user;
	char buf[ERRLEN];
	Irqctl *ctl;
	Irq *irq;
	Vctl *ctl, *v;
	Mach *mach;

	user = 0;


@@ 143,21 177,22 @@ trap(Ureg* ureg)
		up->dbgreg = ureg;
	}

	v = ureg->trap;
	if(ctl = irqctl[v]){
	vno = ureg->trap;
	if(ctl = vctl[vno]){
		if(ctl->isintr){
			m->intr++;
			if(ctl->isr)
				ctl->isr(v);
			if(v >= VectorPIC && v <= MaxVectorPIC)
				m->lastintr = v-VectorPIC;
			if(vno >= VectorPIC && vno != VectorSYSCALL)
				m->lastintr = ctl->irq;
		}

		for(irq = ctl->irq; irq; irq = irq->next)
			irq->f(ureg, irq->a);

		if(ctl->isr)
			ctl->isr(vno);
		for(v = ctl; v != nil; v = v->next){
			if(v->f)
				v->f(ureg, v->a);
		}
		if(ctl->eoi)
			ctl->eoi(v);
			ctl->eoi(vno);

		/* 
		 *  preemptive scheduling.  to limit stack depth,


@@ 165,7 200,7 @@ trap(Ureg* ureg)
		 *  the current interrupt before being preempted a
		 *  second time.
		 */
		if(ctl->isintr && v != VectorTIMER && v != VectorCLOCK)
		if(ctl->isintr && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK)
		if(up && up->state == Running)
		if(anyhigher())
		if(up->preempted == 0)


@@ 177,12 212,12 @@ trap(Ureg* ureg)
			return;
		}
	}
	else if(v <= 16 && user){
	else if(vno <= nelem(excname) && user){
		spllo();
		sprint(buf, "sys: trap: %s", excname[v]);
		sprint(buf, "sys: trap: %s", excname[vno]);
		postnote(up, 1, buf, NDebug);
	}
	else if(v >= VectorPIC && v <= MaxVectorPIC){
	else if(vno >= VectorPIC && vno != VectorSYSCALL){
		/*
		 * An unknown interrupt.
		 * Check for a default IRQ7. This can happen when


@@ 192,7 227,7 @@ trap(Ureg* ureg)
		 * In fact, just ignore all such interrupts.
		 */
		print("cpu%d: spurious interrupt %d, last %d",
			m->machno, v-VectorPIC, m->lastintr);
			m->machno, vno, m->lastintr);
		for(i = 0; i < 32; i++){
			if(!(active.machs & (1<<i)))
				continue;


@@ 206,7 241,7 @@ trap(Ureg* ureg)
		return;
	}
	else{
		if(v == VectorNMI){
		if(vno == VectorNMI){
			nmienable();
			if(m->machno != 0){
				print("cpu%d: PC %8.8luX\n", m->machno, ureg->pc);


@@ 214,9 249,9 @@ trap(Ureg* ureg)
			}
		}
		dumpregs(ureg);
		if(v < nelem(excname))
			panic("%s", excname[v]);
		panic("unknown trap/intr: %d\n", v);
		if(vno < nelem(excname))
			panic("%s", excname[vno]);
		panic("unknown trap/intr: %d\n", vno);
	}

	if(user && (up->procctl || up->nnote)){


@@ 335,14 370,13 @@ fault386(Ureg* ureg, void*)
	spllo();
	n = fault(addr, read);
	if(n < 0){
		if(user){
			sprint(buf, "sys: trap: fault %s addr=0x%lux",
				read? "read" : "write", addr);
			postnote(up, 1, buf, NDebug);
			return;
		if(!user){
			dumpregs(ureg);
			panic("fault: 0x%lux\n", addr);
		}
		dumpregs(ureg);
		panic("fault: 0x%lux\n", addr);
		sprint(buf, "sys: trap: fault %s addr=0x%lux",
			read? "read" : "write", addr);
		postnote(up, 1, buf, NDebug);
	}
	up->insyscall = insyscall;
}

M port/devssl.c => port/devssl.c +32 -10
@@ 789,6 789,26 @@ initRC4key_40(OneWay *w)
	setupRC4state(w->state, w->secret, w->slen);
}

/*
 *  128 bit RC4 is the same as n-bit RC4.  However,
 *  we ignore all but the first 128 bits of the key.
 */
static void
initRC4key_128(OneWay *w)
{
	if(w->state){
		free(w->state);
		w->state = 0;
	}

	if(w->slen > 16)
		w->slen = 16;

	w->state = malloc(sizeof(RC4state));
	setupRC4state(w->state, w->secret, w->slen);
}


typedef struct Hashalg Hashalg;
struct Hashalg
{


@@ 834,22 854,24 @@ struct Encalg
#ifdef NOSPOOKS
Encalg encrypttab[] =
{
	{ "descbc", 8, DESCBC, initDESkey, },
	{ "desecb", 8, DESECB, initDESkey, },
	{ "descbc_40", 8, DESCBC, initDESkey_40, },
	{ "desecb_40", 8, DESECB, initDESkey_40, },
	{ "rc4", 1, RC4, initRC4key, },
	{ "descbc", 8, DESCBC, initDESkey, },           /* DEPRECATED -- use des_56_cbc */
	{ "desecb", 8, DESECB, initDESkey, },           /* DEPRECATED -- use des_56_ecb */
	{ "des_56_cbc", 8, DESCBC, initDESkey, },
	{ "des_56_ecb", 8, DESECB, initDESkey, },
	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
	{ "rc4_256", 1, RC4, initRC4key, },
	{ "rc4_128", 1, RC4, initRC4key_128, },
	{ "rc4_40", 1, RC4, initRC4key_40, },
	{ 0 }
};
#else
Encalg encrypttab[] =
{
	{ "descbc", 8, DESCBC, initDESkey_40, },
	{ "desecb", 8, DESECB, initDESkey_40, },
	{ "descbc_40", 8, DESCBC, initDESkey_40, },
	{ "desecb_40", 8, DESECB, initDESkey_40, },
	{ "rc4", 1, RC4, initRC4key_40, },
	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
	{ "rc4_40", 1, RC4, initRC4key_40, },
	{ 0 }
};