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)feat/start
parent
f9bc4452b5
commit
f70172129c
|
|
@ -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\
|
||||
bio.o\
|
||||
fs.o\
|
||||
8253pit.o\
|
||||
|
||||
# Cross-compiling (e.g., on Mac OS X)
|
||||
TOOLPREFIX = i386-jos-elf-
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ console_init()
|
|||
devsw[CONSOLE].d_write = console_write;
|
||||
devsw[CONSOLE].d_read = console_read;
|
||||
|
||||
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_KBD));
|
||||
ioapic_enable(IRQ_KBD, 0);
|
||||
|
||||
use_console_lock = 1;
|
||||
|
|
|
|||
6
defs.h
6
defs.h
|
|
@ -49,9 +49,15 @@ int checkstring(uint);
|
|||
int putint(struct proc*, uint, int);
|
||||
|
||||
// picirq.c
|
||||
extern ushort irq_mask_8259A;
|
||||
void pic_init(void);
|
||||
void irq_setmask_8259A(ushort);
|
||||
|
||||
// 8253pit.c
|
||||
void pit8253_timerinit(void);
|
||||
|
||||
// mp.c
|
||||
extern int ismp;
|
||||
void mp_init(void);
|
||||
void mp_startthem(void);
|
||||
int mp_bcpu(void);
|
||||
|
|
|
|||
1
ide.c
1
ide.c
|
|
@ -50,6 +50,7 @@ void
|
|||
ide_init(void)
|
||||
{
|
||||
initlock(&ide_lock, "ide");
|
||||
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_IDE));
|
||||
ioapic_enable (IRQ_IDE, ncpu - 1);
|
||||
ide_wait_ready(0);
|
||||
disk_1_present = ide_probe_disk1();
|
||||
|
|
|
|||
6
ioapic.c
6
ioapic.c
|
|
@ -37,12 +37,13 @@ ioapic_init(void)
|
|||
uchar id;
|
||||
int i;
|
||||
|
||||
if (ismp) {
|
||||
io = (struct ioapic*) IO_APIC_BASE;
|
||||
l = ioapic_read(io, IOAPIC_VER);
|
||||
nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
|
||||
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
|
||||
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++) {
|
||||
// active-hi and edge-triggered for ISA interrupts
|
||||
// Assume that pin 0 on the first I/O APIC is an ExtINT pin.
|
||||
|
|
@ -60,6 +61,7 @@ ioapic_init(void)
|
|||
h &= ~IOART_DEST;
|
||||
ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -68,6 +70,7 @@ ioapic_enable (int irq, int cpunum)
|
|||
uint l, h;
|
||||
struct ioapic *io;
|
||||
|
||||
if (ismp) {
|
||||
io = (struct ioapic*) IO_APIC_BASE;
|
||||
l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
|
||||
l = l & ~IOART_INTMASK; // allow INTs
|
||||
|
|
@ -76,4 +79,5 @@ ioapic_enable (int irq, int cpunum)
|
|||
h &= ~IOART_DEST;
|
||||
h |= (cpunum << APIC_ID_SHIFT);
|
||||
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
|
||||
lapic_timerinit(void)
|
||||
{
|
||||
if (lapicaddr) {
|
||||
lapic_write(LAPIC_TDCR, LAPIC_X1);
|
||||
lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
|
||||
(IRQ_OFFSET + IRQ_TIMER));
|
||||
lapic_write(LAPIC_TCCR, 10000000);
|
||||
lapic_write(LAPIC_TICR, 10000000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lapic_timerintr(void)
|
||||
{
|
||||
if (lapicaddr)
|
||||
lapic_write(LAPIC_EOI, 0);
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +126,9 @@ lapic_init(int c)
|
|||
{
|
||||
uint r, lvt;
|
||||
|
||||
if (lapicaddr == 0)
|
||||
return;
|
||||
|
||||
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
||||
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
||||
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
||||
|
|
@ -155,25 +161,32 @@ lapic_init(int c)
|
|||
void
|
||||
lapic_enableintr(void)
|
||||
{
|
||||
if (lapicaddr)
|
||||
lapic_write(LAPIC_TPR, 0);
|
||||
}
|
||||
|
||||
void
|
||||
lapic_disableintr(void)
|
||||
{
|
||||
if (lapicaddr)
|
||||
lapic_write(LAPIC_TPR, 0xFF);
|
||||
}
|
||||
|
||||
void
|
||||
lapic_eoi(void)
|
||||
{
|
||||
if (lapicaddr)
|
||||
lapic_write(LAPIC_EOI, 0);
|
||||
}
|
||||
|
||||
int
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
7
main.c
7
main.c
|
|
@ -71,8 +71,11 @@ main0(void)
|
|||
// start other CPUs
|
||||
mp_startthem();
|
||||
|
||||
// turn on timer and enable interrupts on the local APIC
|
||||
lapic_timerinit();
|
||||
// turn on timer
|
||||
if (ismp) lapic_timerinit();
|
||||
else pit8253_timerinit();
|
||||
|
||||
// enable interrupts on the local APIC
|
||||
lapic_enableintr();
|
||||
|
||||
// Enable interrupts on this processor.
|
||||
|
|
|
|||
8
mp.c
8
mp.c
|
|
@ -30,6 +30,7 @@ static char *buses[] = {
|
|||
};
|
||||
|
||||
struct cpu cpus[NCPU];
|
||||
int ismp;
|
||||
int ncpu;
|
||||
uchar ioapic_id;
|
||||
|
||||
|
|
@ -124,8 +125,11 @@ mp_init(void)
|
|||
uchar byte;
|
||||
|
||||
ncpu = 0;
|
||||
if((r = mp_detect()) != 0)
|
||||
if((r = mp_detect()) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ismp = 1;
|
||||
|
||||
// Run through the table saving information needed for starting
|
||||
// application processors and initialising any I/O APICs. The table
|
||||
|
|
@ -165,7 +169,7 @@ mp_init(void)
|
|||
p += sizeof(struct mpie);
|
||||
continue;
|
||||
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){
|
||||
cprintf("%uX ", *p);
|
||||
p++;
|
||||
|
|
|
|||
4
picirq.c
4
picirq.c
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
// Current IRQ mask.
|
||||
// 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_mask_8259A = mask;
|
||||
|
|
|
|||
|
|
@ -60,3 +60,4 @@ lapic.c
|
|||
ioapic.c
|
||||
picirq.c
|
||||
console.c
|
||||
8253pit.c
|
||||
Loading…
Reference in New Issue