cmos return current date - current irq priority in PIC (L4 Pistachio support) - help fixes

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@557 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-01-18 21:56:49 +00:00
parent 6986f88c3f
commit 6e44ba7fa2

219
vl.c
View file

@ -525,44 +525,15 @@ void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data)
} }
} }
uint32_t cmos_ioport_read(CPUState *env, uint32_t addr)
{
int ret;
if (addr == 0x70) {
return 0xff;
} else {
ret = cmos_data[cmos_index];
switch(cmos_index) {
case RTC_REG_A:
/* toggle update-in-progress bit for Linux (same hack as
plex86) */
cmos_data[RTC_REG_A] ^= 0x80;
break;
case RTC_REG_C:
pic_set_irq(8, 0);
cmos_data[RTC_REG_C] = 0x00;
break;
}
#ifdef DEBUG_CMOS
printf("cmos: read index=0x%02x val=0x%02x\n",
cmos_index, ret);
#endif
return ret;
}
}
static inline int to_bcd(int a) static inline int to_bcd(int a)
{ {
return ((a / 10) << 4) | (a % 10); return ((a / 10) << 4) | (a % 10);
} }
void cmos_init(void) static void cmos_update_time(void)
{ {
struct tm *tm; struct tm *tm;
time_t ti; time_t ti;
int val;
ti = time(NULL); ti = time(NULL);
tm = gmtime(&ti); tm = gmtime(&ti);
@ -573,6 +544,56 @@ void cmos_init(void)
cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday); cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday);
cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1); cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1);
cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100); cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100);
cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19);
}
uint32_t cmos_ioport_read(CPUState *env, uint32_t addr)
{
int ret;
if (addr == 0x70) {
return 0xff;
} else {
switch(cmos_index) {
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
case REG_IBM_CENTURY_BYTE:
cmos_update_time();
ret = cmos_data[cmos_index];
break;
case RTC_REG_A:
ret = cmos_data[cmos_index];
/* toggle update-in-progress bit for Linux (same hack as
plex86) */
cmos_data[RTC_REG_A] ^= 0x80;
break;
case RTC_REG_C:
ret = cmos_data[cmos_index];
pic_set_irq(8, 0);
cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = cmos_data[cmos_index];
break;
}
#ifdef DEBUG_CMOS
printf("cmos: read index=0x%02x val=0x%02x\n",
cmos_index, ret);
#endif
return ret;
}
}
void cmos_init(void)
{
int val;
cmos_update_time();
cmos_data[RTC_REG_A] = 0x26; cmos_data[RTC_REG_A] = 0x26;
cmos_data[RTC_REG_B] = 0x02; cmos_data[RTC_REG_B] = 0x02;
@ -580,7 +601,6 @@ void cmos_init(void)
cmos_data[RTC_REG_D] = 0x80; cmos_data[RTC_REG_D] = 0x80;
/* various important CMOS locations needed by PC/Bochs bios */ /* various important CMOS locations needed by PC/Bochs bios */
cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19);
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */
cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
@ -676,14 +696,15 @@ typedef struct PicState {
uint8_t irr; /* interrupt request register */ uint8_t irr; /* interrupt request register */
uint8_t imr; /* interrupt mask register */ uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */ uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* used to compute irq priority */ uint8_t priority_add; /* highest irq priority */
uint8_t irq_base; uint8_t irq_base;
uint8_t read_reg_select; uint8_t read_reg_select;
uint8_t poll; uint8_t poll;
uint8_t special_mask; uint8_t special_mask;
uint8_t init_state; uint8_t init_state;
uint8_t auto_eoi; uint8_t auto_eoi;
uint8_t rotate_on_autoeoi; uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
uint8_t init4; /* true if 4 byte init */ uint8_t init4; /* true if 4 byte init */
} PicState; } PicState;
@ -705,14 +726,16 @@ static inline void pic_set_irq1(PicState *s, int irq, int level)
} }
} }
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
static inline int get_priority(PicState *s, int mask) static inline int get_priority(PicState *s, int mask)
{ {
int priority; int priority;
if (mask == 0) if (mask == 0)
return -1; return 8;
priority = 7; priority = 0;
while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
priority--; priority++;
return priority; return priority;
} }
@ -723,13 +746,18 @@ static int pic_get_irq(PicState *s)
mask = s->irr & ~s->imr; mask = s->irr & ~s->imr;
priority = get_priority(s, mask); priority = get_priority(s, mask);
if (priority < 0) if (priority == 8)
return -1; return -1;
/* compute current priority */ /* compute current priority. If special fully nested mode on the
cur_priority = get_priority(s, s->isr); master, the IRQ coming from the slave is not taken into account
if (priority > cur_priority) { for the priority computation. */
mask = s->isr;
if (s->special_fully_nested_mode && s == &pics[0])
mask &= ~(1 << 2);
cur_priority = get_priority(s, mask);
if (priority < cur_priority) {
/* higher priority found: an irq should be generated */ /* higher priority found: an irq should be generated */
return priority; return (priority + s->priority_add) & 7;
} else { } else {
return -1; return -1;
} }
@ -758,6 +786,17 @@ void pic_update_irq(void)
/* from master pic */ /* from master pic */
pic_irq_requested = irq; pic_irq_requested = irq;
} }
#if defined(DEBUG_PIC)
{
int i;
for(i = 0; i < 2; i++) {
printf("pic%d: imr=%x irr=%x padd=%d\n",
i, pics[i].imr, pics[i].irr, pics[i].priority_add);
}
}
printf("pic: cpu_interrupt req=%d\n", pic_irq_requested);
#endif
cpu_interrupt(global_env, CPU_INTERRUPT_HARD); cpu_interrupt(global_env, CPU_INTERRUPT_HARD);
} }
} }
@ -787,6 +826,18 @@ void pic_set_irq(int irq, int level)
pic_update_irq(); pic_update_irq();
} }
/* acknowledge interrupt 'irq' */
static inline void pic_intack(PicState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi)
s->priority_add = (irq + 1) & 7;
} else {
s->isr |= (1 << irq);
}
s->irr &= ~(1 << irq);
}
int cpu_x86_get_pic_interrupt(CPUState *env) int cpu_x86_get_pic_interrupt(CPUState *env)
{ {
int irq, irq2, intno; int irq, irq2, intno;
@ -804,22 +855,20 @@ int cpu_x86_get_pic_interrupt(CPUState *env)
if (irq >= 8) { if (irq >= 8) {
irq2 = irq & 7; irq2 = irq & 7;
pics[1].isr |= (1 << irq2); pic_intack(&pics[1], irq2);
pics[1].irr &= ~(1 << irq2);
irq = 2; irq = 2;
intno = pics[1].irq_base + irq2; intno = pics[1].irq_base + irq2;
} else { } else {
intno = pics[0].irq_base + irq; intno = pics[0].irq_base + irq;
} }
pics[0].isr |= (1 << irq); pic_intack(&pics[0], irq);
pics[0].irr &= ~(1 << irq);
return intno; return intno;
} }
void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val) void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
{ {
PicState *s; PicState *s;
int priority; int priority, cmd, irq;
#ifdef DEBUG_PIC #ifdef DEBUG_PIC
printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
@ -837,45 +886,48 @@ void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
if (val & 0x08) if (val & 0x08)
hw_error("level sensitive irq not supported"); hw_error("level sensitive irq not supported");
} else if (val & 0x08) { } else if (val & 0x08) {
if (val & 0x04) { if (val & 0x04)
s->poll = 1; s->poll = 1;
} else {
if (val & 0x02) if (val & 0x02)
s->read_reg_select = val & 1; s->read_reg_select = val & 1;
if (val & 0x40) if (val & 0x40)
s->special_mask = (val >> 5) & 1; s->special_mask = (val >> 5) & 1;
}
} else { } else {
switch(val) { cmd = val >> 5;
case 0x00: switch(cmd) {
case 0x80: case 0:
s->rotate_on_autoeoi = val >> 7; case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break; break;
case 0x20: /* end of interrupt */ case 1: /* end of interrupt */
case 0xa0: case 5:
priority = get_priority(s, s->isr); priority = get_priority(s, s->isr);
if (priority >= 0) { if (priority != 8) {
s->isr &= ~(1 << ((priority + s->priority_add) & 7)); irq = (priority + s->priority_add) & 7;
s->isr &= ~(1 << irq);
if (cmd == 5)
s->priority_add = (irq + 1) & 7;
pic_update_irq();
} }
if (val == 0xa0) break;
s->priority_add = (s->priority_add + 1) & 7; case 3:
irq = val & 7;
s->isr &= ~(1 << irq);
pic_update_irq(); pic_update_irq();
break; break;
case 0x60 ... 0x67: case 6:
priority = val & 7;
s->isr &= ~(1 << priority);
pic_update_irq();
break;
case 0xc0 ... 0xc7:
s->priority_add = (val + 1) & 7; s->priority_add = (val + 1) & 7;
pic_update_irq(); pic_update_irq();
break; break;
case 0xe0 ... 0xe7: case 7:
priority = val & 7; irq = val & 7;
s->isr &= ~(1 << priority); s->isr &= ~(1 << irq);
s->priority_add = (priority + 1) & 7; s->priority_add = (irq + 1) & 7;
pic_update_irq(); pic_update_irq();
break; break;
default:
/* no operation */
break;
} }
} }
} else { } else {
@ -897,6 +949,7 @@ void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
} }
break; break;
case 3: case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
s->auto_eoi = (val >> 1) & 1; s->auto_eoi = (val >> 1) & 1;
s->init_state = 0; s->init_state = 0;
break; break;
@ -935,18 +988,18 @@ uint32_t pic_ioport_read(CPUState *env, uint32_t addr1)
addr = addr1; addr = addr1;
s = &pics[addr >> 7]; s = &pics[addr >> 7];
addr &= 1; addr &= 1;
if (s->poll == 1) { if (s->poll) {
ret = pic_poll_read(s, addr1); ret = pic_poll_read(s, addr1);
s->poll = 0; s->poll = 0;
} else { } else {
if (addr == 0) { if (addr == 0) {
if (s->read_reg_select) if (s->read_reg_select)
ret = s->isr; ret = s->isr;
else else
ret = s->irr; ret = s->irr;
} else { } else {
ret = s->imr; ret = s->imr;
} }
} }
#ifdef DEBUG_PIC #ifdef DEBUG_PIC
printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret); printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
@ -1729,6 +1782,9 @@ void serial_received_byte(SerialState *s, int ch)
fflush(stdout); fflush(stdout);
term_command = 1; term_command = 1;
break; break;
case 'd':
cpu_set_log(CPU_LOG_ALL);
break;
case TERM_ESCAPE: case TERM_ESCAPE:
goto send_char; goto send_char;
} }
@ -3180,7 +3236,7 @@ void help(void)
"-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-cdrom file use 'file' as IDE cdrom 2 image\n" "-cdrom file use 'file' as IDE cdrom 2 image\n"
"-boot [c|d] boot on hard disk (c) or CD-ROM (d)\n" "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n"
"-snapshot write to temporary files instead of disk image files\n" "-snapshot write to temporary files instead of disk image files\n"
"-m megs set virtual RAM size to megs MB\n" "-m megs set virtual RAM size to megs MB\n"
"-n script set network init script [default=%s]\n" "-n script set network init script [default=%s]\n"
@ -3195,7 +3251,7 @@ void help(void)
"Debug/Expert options:\n" "Debug/Expert options:\n"
"-s wait gdb connection to port %d\n" "-s wait gdb connection to port %d\n"
"-p port change gdb connection port\n" "-p port change gdb connection port\n"
"-d output log in /tmp/vl.log\n" "-d output log to %s\n"
"-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n"
"-L path set the directory for the BIOS and VGA BIOS\n" "-L path set the directory for the BIOS and VGA BIOS\n"
"\n" "\n"
@ -3206,7 +3262,8 @@ void help(void)
"qemu-fast", "qemu-fast",
#endif #endif
DEFAULT_NETWORK_SCRIPT, DEFAULT_NETWORK_SCRIPT,
DEFAULT_GDBSTUB_PORT); DEFAULT_GDBSTUB_PORT,
"/tmp/qemu.log");
term_print_help(); term_print_help();
#ifndef CONFIG_SOFTMMU #ifndef CONFIG_SOFTMMU
printf("\n" printf("\n"