From 28a392d9a611b7bb06c6f7a08fe1a5a7bdb6064a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 10 Sep 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-09-10 --- pc/apic.c | 19 +++-- pc/audio.h | 2 +- pc/dat.h | 39 +--------- pc/devastar.c | 4 +- pc/devata.c | 2 +- pc/devether.c | 2 +- pc/devi82365.c | 12 ++-- pc/devlpt.c | 2 +- pc/floppy.h | 2 +- pc/fns.h | 6 +- pc/i8253.c | 2 +- pc/i8259.c | 65 +++++++++-------- pc/io.h | 85 ++++++++++++++++------ pc/kbd.c | 4 +- pc/main.c | 18 ++--- pc/mp.c | 156 ++++++++++++++++++++++++---------------- pc/mp.h | 3 +- pc/ns16552.h | 4 +- pc/pcmciamodem.c | 1 + pc/scsi.c | 44 +++--------- pc/trap.c | 184 ++++++++++++++++++++++++++++------------------- port/devssl.c | 42 ++++++++--- 22 files changed, 387 insertions(+), 311 deletions(-) diff --git a/pc/apic.c b/pc/apic.c index ae8c8b34acbd89fcbba8068f7577ea4b872911c7..e450b912d170e0113310b3694e65ea335c49f96c 100644 --- a/pc/apic.c +++ b/pc/apic.c @@ -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<>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); diff --git a/pc/audio.h b/pc/audio.h index bf4c12312e595bfb84aad62bf03fc55a0229b318..9de05d0bb33dfcac83299b0baa612f5ae45dcb92 100644 --- a/pc/audio.h +++ b/pc/audio.h @@ -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) diff --git a/pc/dat.h b/pc/dat.h index 25c55e5a132fbd05131a8a68dcaffd651b79f80b..77578fdb69e6184d0d68c88f14687016eb7ac3e8 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -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; diff --git a/pc/devastar.c b/pc/devastar.c index 2972580334979e1c1227e813114bfae94b174956..af1ae9f2217e03d83aed0352d7b9a5b4a02b763c 100644 --- a/pc/devastar.c +++ b/pc/devastar.c @@ -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 */ diff --git a/pc/devata.c b/pc/devata.c index 5ac613fadb31b35fbac9a4b78fd1915ba188a5e0..71734a4274b47d85e13069f0bd66b594452dc840 100644 --- a/pc/devata.c +++ b/pc/devata.c @@ -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) diff --git a/pc/devether.c b/pc/devether.c index 1a5e94f355cff926e2b2043fafca7c77c03db5c3..4ab7c530127a2e75973057a5822d2412a774a6df 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -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); diff --git a/pc/devi82365.c b/pc/devi82365.c index 2a221a8b0f5e52b17d5224b6c30e0828f0107ad5..a1731c9ed2841b87565effb081675a24991ce57e 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -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* diff --git a/pc/devlpt.c b/pc/devlpt.c index fe8f87395fe886007d35fe6e84015f8f9f52f8f4..f77352c1feb6c2b46430a89c588224412a2f5d67 100644 --- a/pc/devlpt.c +++ b/pc/devlpt.c @@ -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); diff --git a/pc/floppy.h b/pc/floppy.h index f39ab30f25d4d67b3ecf1d4eb7e144f8849c5231..2a3a49fb5ccab43fde8d7cee7f3e194dab2ec8bf 100644 --- a/pc/floppy.h +++ b/pc/floppy.h @@ -157,7 +157,7 @@ floppysetup1(FController *fl) floppysetdef(&fl->d[1]); } - intrenable(VectorFLOPPY, pcfloppyintr, fl, BUSUNKNOWN); + intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN); } /* diff --git a/pc/fns.h b/pc/fns.h index bd3ec3c5f0ad9c9ffbb1e093f424baaf1a1bbd5b..f20e7b3d31b42f4ad3f821e3cbe3e4f9a0d64454 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -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); diff --git a/pc/i8253.c b/pc/i8253.c index 94925eca3a37d75be4e252b2bde9ecd56cd14e5a..eebf08742866c599aa57e211a78538fd87dfee23 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -111,7 +111,7 @@ i8253init(int aalcycles) void i8253enable(void) { - intrenable(VectorCLOCK, clockintr, 0, BUSUNKNOWN); + intrenable(IrqCLOCK, clockintr, 0, BUSUNKNOWN); } /* diff --git a/pc/i8259.c b/pc/i8259.c index d269dc651d673912c9323890663c4b1a15da341c..6d3d2f0d0fb9a7bc806dfff328fcd52703b5bd4d 100644 --- a/pc/i8259.c +++ b/pc/i8259.c @@ -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<irq; + if(irq < 0 || irq > MaxIrqPIC){ + print("i8259enable: irq %d out of range\n", irq); + return -1; + } + + ilock(&i8259lock); + if(irq < 8){ + int0mask &= ~(1<eoi = i8259isr; + if(elcr & (1<eoi = i8259isr; else - irqctl->isr = i8259isr; - irqctl->isintr = 1; + v->isr = i8259isr; + iunlock(&i8259lock); - return v; + return VectorPIC+irq; } diff --git a/pc/io.h b/pc/io.h index 01feea69aa569267110909c1c7957749bb0535f0..6c425eab53108a32f50b6eafb0e178cabfadb830 100644 --- a/pc/io.h +++ b/pc/io.h @@ -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; diff --git a/pc/kbd.c b/pc/kbd.c index 1de2713b0c9bd301d9994444236149fa0e1f913f..a063ce5e6e3347fcff1527132a32535faffe32b2 100644 --- a/pc/kbd.c +++ b/pc/kbd.c @@ -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)) diff --git a/pc/main.c b/pc/main.c index 23f9d3bfb12bcb16d64e35112e7e85ed4646ce60..257428e191b25a569634c5fe13367beac598cc53 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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); } /* diff --git a/pc/mp.c b/pc/mp.c index 3eaf15294338e3922e0608f2d9f10b821443aff6..1806ffff5eb7139758ce6342e4bfc0e9dbd26dda 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -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(); } diff --git a/pc/mp.h b/pc/mp.h index 8419892b58cfc735473df1a2dacb0e274325b2fe..9195c9e91f84a76d14df4674017e76f649845b09 100644 --- a/pc/mp.h +++ b/pc/mp.h @@ -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_; diff --git a/pc/ns16552.h b/pc/ns16552.h index 0d8dc2c65a2c4034dd87888ff6224fe0e40a5dd2..ec89332b0164b6235e90d72cb494473cac2296fa 100644 --- a/pc/ns16552.h +++ b/pc/ns16552.h @@ -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 */ diff --git a/pc/pcmciamodem.c b/pc/pcmciamodem.c index 6fcb1874f3e3a29e555f9133d145e96cc94c7ef5..ff90f65d861c4e8aaf829b920596e350c421eccc 100644 --- a/pc/pcmciamodem.c +++ b/pc/pcmciamodem.c @@ -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) diff --git a/pc/scsi.c b/pc/scsi.c index e2b8454dc0931d964a6422413b02fc8f5eb97d9f..74c7f6a7590cbb88b23eac3f5cc0deaf601c19a7 100644 --- a/pc/scsi.c +++ b/pc/scsi.c @@ -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", diff --git a/pc/trap.c b/pc/trap.c index fdc5bdbfe6bb3a430c8c95aa98035181554c417c..9ef0979d22226e22f2de3e4627da10e2b54863c5 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -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<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; } diff --git a/port/devssl.c b/port/devssl.c index 16ce7c3e06ac9c7f15fb368072bc4473c58d68df..537adfe6f9846a38ca3301361f25abeb1beb8c57 100644 --- a/port/devssl.c +++ b/port/devssl.c @@ -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 } };