run without lapic and ioapic, if they are not present
if no lapic available, use 8253pit for clock now xv6 runs both on qemu (uniprocessor) and bochs (uniprocessor and MP)
This commit is contained in:
parent
f9bc4452b5
commit
f70172129c
12 changed files with 128 additions and 48 deletions
46
8253pit.c
Normal file
46
8253pit.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "traps.h"
|
||||||
|
|
||||||
|
// Register definitions for the Intel
|
||||||
|
// 8253/8254/82C54 Programmable Interval Timer (PIT).
|
||||||
|
|
||||||
|
#define IO_TIMER1 0x040 /* 8253 Timer #1 */
|
||||||
|
#define IO_TIMER2 0x048 /* 8253 Timer #2 (EISA only) */
|
||||||
|
|
||||||
|
//
|
||||||
|
// Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
|
||||||
|
// appropriate count to generate a frequency of freq hz.
|
||||||
|
|
||||||
|
#define TIMER_FREQ 1193182
|
||||||
|
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||||
|
|
||||||
|
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
|
||||||
|
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
|
||||||
|
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
|
||||||
|
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
|
||||||
|
#define TIMER_SEL0 0x00 /* select counter 0 */
|
||||||
|
#define TIMER_SEL1 0x40 /* select counter 1 */
|
||||||
|
#define TIMER_SEL2 0x80 /* select counter 2 */
|
||||||
|
#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
|
||||||
|
#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
|
||||||
|
#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
|
||||||
|
#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
|
||||||
|
#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
|
||||||
|
#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
|
||||||
|
#define TIMER_LATCH 0x00 /* latch counter for reading */
|
||||||
|
#define TIMER_LSB 0x10 /* r/w counter LSB */
|
||||||
|
#define TIMER_MSB 0x20 /* r/w counter MSB */
|
||||||
|
#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
|
||||||
|
#define TIMER_BCD 0x01 /* count in BCD */
|
||||||
|
|
||||||
|
void
|
||||||
|
pit8253_timerinit(void)
|
||||||
|
{
|
||||||
|
// initialize 8253 clock to interrupt 100 times/sec
|
||||||
|
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
|
||||||
|
outb(IO_TIMER1, TIMER_DIV(100) % 256);
|
||||||
|
outb(IO_TIMER1, TIMER_DIV(100) / 256);
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1<<IRQ_TIMER));
|
||||||
|
}
|
1
Makefile
1
Makefile
|
@ -21,6 +21,7 @@ OBJS = \
|
||||||
vectors.o\
|
vectors.o\
|
||||||
bio.o\
|
bio.o\
|
||||||
fs.o\
|
fs.o\
|
||||||
|
8253pit.o\
|
||||||
|
|
||||||
# Cross-compiling (e.g., on Mac OS X)
|
# Cross-compiling (e.g., on Mac OS X)
|
||||||
TOOLPREFIX = i386-jos-elf-
|
TOOLPREFIX = i386-jos-elf-
|
||||||
|
|
|
@ -409,6 +409,7 @@ console_init()
|
||||||
devsw[CONSOLE].d_write = console_write;
|
devsw[CONSOLE].d_write = console_write;
|
||||||
devsw[CONSOLE].d_read = console_read;
|
devsw[CONSOLE].d_read = console_read;
|
||||||
|
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_KBD));
|
||||||
ioapic_enable(IRQ_KBD, 0);
|
ioapic_enable(IRQ_KBD, 0);
|
||||||
|
|
||||||
use_console_lock = 1;
|
use_console_lock = 1;
|
||||||
|
|
6
defs.h
6
defs.h
|
@ -49,9 +49,15 @@ int checkstring(uint);
|
||||||
int putint(struct proc*, uint, int);
|
int putint(struct proc*, uint, int);
|
||||||
|
|
||||||
// picirq.c
|
// picirq.c
|
||||||
|
extern ushort irq_mask_8259A;
|
||||||
void pic_init(void);
|
void pic_init(void);
|
||||||
|
void irq_setmask_8259A(ushort);
|
||||||
|
|
||||||
|
// 8253pit.c
|
||||||
|
void pit8253_timerinit(void);
|
||||||
|
|
||||||
// mp.c
|
// mp.c
|
||||||
|
extern int ismp;
|
||||||
void mp_init(void);
|
void mp_init(void);
|
||||||
void mp_startthem(void);
|
void mp_startthem(void);
|
||||||
int mp_bcpu(void);
|
int mp_bcpu(void);
|
||||||
|
|
1
ide.c
1
ide.c
|
@ -50,6 +50,7 @@ void
|
||||||
ide_init(void)
|
ide_init(void)
|
||||||
{
|
{
|
||||||
initlock(&ide_lock, "ide");
|
initlock(&ide_lock, "ide");
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_IDE));
|
||||||
ioapic_enable (IRQ_IDE, ncpu - 1);
|
ioapic_enable (IRQ_IDE, ncpu - 1);
|
||||||
ide_wait_ready(0);
|
ide_wait_ready(0);
|
||||||
disk_1_present = ide_probe_disk1();
|
disk_1_present = ide_probe_disk1();
|
||||||
|
|
6
ioapic.c
6
ioapic.c
|
@ -37,12 +37,13 @@ ioapic_init(void)
|
||||||
uchar id;
|
uchar id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (ismp) {
|
||||||
io = (struct ioapic*) IO_APIC_BASE;
|
io = (struct ioapic*) IO_APIC_BASE;
|
||||||
l = ioapic_read(io, IOAPIC_VER);
|
l = ioapic_read(io, IOAPIC_VER);
|
||||||
nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
|
nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
|
||||||
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
|
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
|
||||||
if(id != ioapic_id)
|
if(id != ioapic_id)
|
||||||
panic("ioapic_init: id isn't equal to ioapic_id\n");
|
cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n");
|
||||||
for(i = 0; i < nintr; i++) {
|
for(i = 0; i < nintr; i++) {
|
||||||
// active-hi and edge-triggered for ISA interrupts
|
// active-hi and edge-triggered for ISA interrupts
|
||||||
// Assume that pin 0 on the first I/O APIC is an ExtINT pin.
|
// Assume that pin 0 on the first I/O APIC is an ExtINT pin.
|
||||||
|
@ -61,6 +62,7 @@ ioapic_init(void)
|
||||||
ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
|
ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ioapic_enable (int irq, int cpunum)
|
ioapic_enable (int irq, int cpunum)
|
||||||
|
@ -68,6 +70,7 @@ ioapic_enable (int irq, int cpunum)
|
||||||
uint l, h;
|
uint l, h;
|
||||||
struct ioapic *io;
|
struct ioapic *io;
|
||||||
|
|
||||||
|
if (ismp) {
|
||||||
io = (struct ioapic*) IO_APIC_BASE;
|
io = (struct ioapic*) IO_APIC_BASE;
|
||||||
l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
|
l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
|
||||||
l = l & ~IOART_INTMASK; // allow INTs
|
l = l & ~IOART_INTMASK; // allow INTs
|
||||||
|
@ -77,3 +80,4 @@ ioapic_enable (int irq, int cpunum)
|
||||||
h |= (cpunum << APIC_ID_SHIFT);
|
h |= (cpunum << APIC_ID_SHIFT);
|
||||||
ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
|
ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
15
lapic.c
15
lapic.c
|
@ -105,16 +105,19 @@ lapic_write(int r, int data)
|
||||||
void
|
void
|
||||||
lapic_timerinit(void)
|
lapic_timerinit(void)
|
||||||
{
|
{
|
||||||
|
if (lapicaddr) {
|
||||||
lapic_write(LAPIC_TDCR, LAPIC_X1);
|
lapic_write(LAPIC_TDCR, LAPIC_X1);
|
||||||
lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
|
lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
|
||||||
(IRQ_OFFSET + IRQ_TIMER));
|
(IRQ_OFFSET + IRQ_TIMER));
|
||||||
lapic_write(LAPIC_TCCR, 10000000);
|
lapic_write(LAPIC_TCCR, 10000000);
|
||||||
lapic_write(LAPIC_TICR, 10000000);
|
lapic_write(LAPIC_TICR, 10000000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_timerintr(void)
|
lapic_timerintr(void)
|
||||||
{
|
{
|
||||||
|
if (lapicaddr)
|
||||||
lapic_write(LAPIC_EOI, 0);
|
lapic_write(LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +126,9 @@ lapic_init(int c)
|
||||||
{
|
{
|
||||||
uint r, lvt;
|
uint r, lvt;
|
||||||
|
|
||||||
|
if (lapicaddr == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
||||||
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
||||||
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
||||||
|
@ -155,25 +161,32 @@ lapic_init(int c)
|
||||||
void
|
void
|
||||||
lapic_enableintr(void)
|
lapic_enableintr(void)
|
||||||
{
|
{
|
||||||
|
if (lapicaddr)
|
||||||
lapic_write(LAPIC_TPR, 0);
|
lapic_write(LAPIC_TPR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_disableintr(void)
|
lapic_disableintr(void)
|
||||||
{
|
{
|
||||||
|
if (lapicaddr)
|
||||||
lapic_write(LAPIC_TPR, 0xFF);
|
lapic_write(LAPIC_TPR, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_eoi(void)
|
lapic_eoi(void)
|
||||||
{
|
{
|
||||||
|
if (lapicaddr)
|
||||||
lapic_write(LAPIC_EOI, 0);
|
lapic_write(LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cpu(void)
|
cpu(void)
|
||||||
{
|
{
|
||||||
int x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
int x;
|
||||||
|
if (lapicaddr)
|
||||||
|
x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
||||||
|
else
|
||||||
|
x = 0;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
main.c
7
main.c
|
@ -71,8 +71,11 @@ main0(void)
|
||||||
// start other CPUs
|
// start other CPUs
|
||||||
mp_startthem();
|
mp_startthem();
|
||||||
|
|
||||||
// turn on timer and enable interrupts on the local APIC
|
// turn on timer
|
||||||
lapic_timerinit();
|
if (ismp) lapic_timerinit();
|
||||||
|
else pit8253_timerinit();
|
||||||
|
|
||||||
|
// enable interrupts on the local APIC
|
||||||
lapic_enableintr();
|
lapic_enableintr();
|
||||||
|
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
|
|
8
mp.c
8
mp.c
|
@ -30,6 +30,7 @@ static char *buses[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
int ismp;
|
||||||
int ncpu;
|
int ncpu;
|
||||||
uchar ioapic_id;
|
uchar ioapic_id;
|
||||||
|
|
||||||
|
@ -124,8 +125,11 @@ mp_init(void)
|
||||||
uchar byte;
|
uchar byte;
|
||||||
|
|
||||||
ncpu = 0;
|
ncpu = 0;
|
||||||
if((r = mp_detect()) != 0)
|
if((r = mp_detect()) != 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ismp = 1;
|
||||||
|
|
||||||
// Run through the table saving information needed for starting
|
// Run through the table saving information needed for starting
|
||||||
// application processors and initialising any I/O APICs. The table
|
// application processors and initialising any I/O APICs. The table
|
||||||
|
@ -165,7 +169,7 @@ mp_init(void)
|
||||||
p += sizeof(struct mpie);
|
p += sizeof(struct mpie);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
|
cprintf("mp_init: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
|
||||||
while(p < e){
|
while(p < e){
|
||||||
cprintf("%uX ", *p);
|
cprintf("%uX ", *p);
|
||||||
p++;
|
p++;
|
||||||
|
|
4
picirq.c
4
picirq.c
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
// Current IRQ mask.
|
// Current IRQ mask.
|
||||||
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
|
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
|
||||||
static ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
|
ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
|
||||||
|
|
||||||
static void
|
void
|
||||||
irq_setmask_8259A(ushort mask)
|
irq_setmask_8259A(ushort mask)
|
||||||
{
|
{
|
||||||
irq_mask_8259A = mask;
|
irq_mask_8259A = mask;
|
||||||
|
|
|
@ -60,3 +60,4 @@ lapic.c
|
||||||
ioapic.c
|
ioapic.c
|
||||||
picirq.c
|
picirq.c
|
||||||
console.c
|
console.c
|
||||||
|
8253pit.c
|
2
traps.h
2
traps.h
|
@ -27,8 +27,8 @@
|
||||||
|
|
||||||
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
||||||
|
|
||||||
|
#define IRQ_TIMER 0
|
||||||
#define IRQ_KBD 1
|
#define IRQ_KBD 1
|
||||||
#define IRQ_IDE 14
|
#define IRQ_IDE 14
|
||||||
#define IRQ_TIMER 18
|
|
||||||
#define IRQ_ERROR 19
|
#define IRQ_ERROR 19
|
||||||
#define IRQ_SPURIOUS 31
|
#define IRQ_SPURIOUS 31
|
||||||
|
|
Loading…
Reference in a new issue