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 }
};