| 61 |
/* output Bochs bios info messages */ |
/* output Bochs bios info messages */ |
| 62 |
//#define DEBUG_BIOS |
//#define DEBUG_BIOS |
| 63 |
|
|
| 64 |
|
//#define DEBUG_CMOS |
| 65 |
|
|
| 66 |
/* debug PIC */ |
/* debug PIC */ |
| 67 |
//#define DEBUG_PIC |
//#define DEBUG_PIC |
| 68 |
|
|
| 75 |
/* debug PC keyboard : only mouse */ |
/* debug PC keyboard : only mouse */ |
| 76 |
//#define DEBUG_MOUSE |
//#define DEBUG_MOUSE |
| 77 |
|
|
| 78 |
|
//#define DEBUG_SERIAL |
| 79 |
|
|
| 80 |
#define PHYS_RAM_BASE 0xac000000 |
#define PHYS_RAM_BASE 0xac000000 |
| 81 |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| 82 |
|
|
| 201 |
#define KERNEL_CS 0x10 |
#define KERNEL_CS 0x10 |
| 202 |
#define KERNEL_DS 0x18 |
#define KERNEL_DS 0x18 |
| 203 |
|
|
| 204 |
#define MAX_IOPORTS 4096 |
/* XXX: use a two level table to limit memory usage */ |
| 205 |
|
#define MAX_IOPORTS 65536 |
| 206 |
|
|
| 207 |
static const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
static const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
| 208 |
char phys_ram_file[1024]; |
char phys_ram_file[1024]; |
| 466 |
{ |
{ |
| 467 |
if (addr == 0x70) { |
if (addr == 0x70) { |
| 468 |
cmos_index = data & 0x7f; |
cmos_index = data & 0x7f; |
| 469 |
|
} else { |
| 470 |
|
#ifdef DEBUG_CMOS |
| 471 |
|
printf("cmos: write index=0x%02x val=0x%02x\n", |
| 472 |
|
cmos_index, data); |
| 473 |
|
#endif |
| 474 |
|
switch(addr) { |
| 475 |
|
case RTC_SECONDS_ALARM: |
| 476 |
|
case RTC_MINUTES_ALARM: |
| 477 |
|
case RTC_HOURS_ALARM: |
| 478 |
|
/* XXX: not supported */ |
| 479 |
|
cmos_data[cmos_index] = data; |
| 480 |
|
break; |
| 481 |
|
case RTC_SECONDS: |
| 482 |
|
case RTC_MINUTES: |
| 483 |
|
case RTC_HOURS: |
| 484 |
|
case RTC_DAY_OF_WEEK: |
| 485 |
|
case RTC_DAY_OF_MONTH: |
| 486 |
|
case RTC_MONTH: |
| 487 |
|
case RTC_YEAR: |
| 488 |
|
cmos_data[cmos_index] = data; |
| 489 |
|
break; |
| 490 |
|
case RTC_REG_A: |
| 491 |
|
case RTC_REG_B: |
| 492 |
|
cmos_data[cmos_index] = data; |
| 493 |
|
break; |
| 494 |
|
case RTC_REG_C: |
| 495 |
|
case RTC_REG_D: |
| 496 |
|
/* cannot write to them */ |
| 497 |
|
break; |
| 498 |
|
default: |
| 499 |
|
cmos_data[cmos_index] = data; |
| 500 |
|
break; |
| 501 |
|
} |
| 502 |
} |
} |
| 503 |
} |
} |
| 504 |
|
|
| 509 |
if (addr == 0x70) { |
if (addr == 0x70) { |
| 510 |
return 0xff; |
return 0xff; |
| 511 |
} else { |
} else { |
|
/* toggle update-in-progress bit for Linux (same hack as |
|
|
plex86) */ |
|
| 512 |
ret = cmos_data[cmos_index]; |
ret = cmos_data[cmos_index]; |
| 513 |
if (cmos_index == RTC_REG_A) |
switch(cmos_index) { |
| 514 |
|
case RTC_REG_A: |
| 515 |
|
/* toggle update-in-progress bit for Linux (same hack as |
| 516 |
|
plex86) */ |
| 517 |
cmos_data[RTC_REG_A] ^= 0x80; |
cmos_data[RTC_REG_A] ^= 0x80; |
| 518 |
else if (cmos_index == RTC_REG_C) |
break; |
| 519 |
|
case RTC_REG_C: |
| 520 |
|
pic_set_irq(8, 0); |
| 521 |
cmos_data[RTC_REG_C] = 0x00; |
cmos_data[RTC_REG_C] = 0x00; |
| 522 |
|
break; |
| 523 |
|
} |
| 524 |
|
#ifdef DEBUG_CMOS |
| 525 |
|
printf("cmos: read index=0x%02x val=0x%02x\n", |
| 526 |
|
cmos_index, ret); |
| 527 |
|
#endif |
| 528 |
return ret; |
return ret; |
| 529 |
} |
} |
| 530 |
} |
} |
| 722 |
irq, |
irq, |
| 723 |
(double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec); |
(double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec); |
| 724 |
#endif |
#endif |
| 725 |
#ifdef DEBUG_PIC |
#if defined(DEBUG_PIC) |
| 726 |
printf("pic_interrupt: irq=%d\n", irq); |
printf("pic_interrupt: irq=%d\n", irq); |
| 727 |
#endif |
#endif |
| 728 |
|
|
| 1238 |
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ |
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ |
| 1239 |
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ |
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ |
| 1240 |
|
|
| 1241 |
|
/* |
| 1242 |
|
* These are the definitions for the Modem Control Register |
| 1243 |
|
*/ |
| 1244 |
|
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ |
| 1245 |
|
#define UART_MCR_OUT2 0x08 /* Out2 complement */ |
| 1246 |
|
#define UART_MCR_OUT1 0x04 /* Out1 complement */ |
| 1247 |
|
#define UART_MCR_RTS 0x02 /* RTS complement */ |
| 1248 |
|
#define UART_MCR_DTR 0x01 /* DTR complement */ |
| 1249 |
|
|
| 1250 |
|
/* |
| 1251 |
|
* These are the definitions for the Modem Status Register |
| 1252 |
|
*/ |
| 1253 |
|
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ |
| 1254 |
|
#define UART_MSR_RI 0x40 /* Ring Indicator */ |
| 1255 |
|
#define UART_MSR_DSR 0x20 /* Data Set Ready */ |
| 1256 |
|
#define UART_MSR_CTS 0x10 /* Clear to Send */ |
| 1257 |
|
#define UART_MSR_DDCD 0x08 /* Delta DCD */ |
| 1258 |
|
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ |
| 1259 |
|
#define UART_MSR_DDSR 0x02 /* Delta DSR */ |
| 1260 |
|
#define UART_MSR_DCTS 0x01 /* Delta CTS */ |
| 1261 |
|
#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ |
| 1262 |
|
|
| 1263 |
#define UART_LSR_TEMT 0x40 /* Transmitter empty */ |
#define UART_LSR_TEMT 0x40 /* Transmitter empty */ |
| 1264 |
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ |
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ |
| 1265 |
#define UART_LSR_BI 0x10 /* Break interrupt indicator */ |
#define UART_LSR_BI 0x10 /* Break interrupt indicator */ |
| 1278 |
uint8_t lsr; /* read only */ |
uint8_t lsr; /* read only */ |
| 1279 |
uint8_t msr; |
uint8_t msr; |
| 1280 |
uint8_t scr; |
uint8_t scr; |
| 1281 |
|
/* NOTE: this hidden state is necessary for tx irq generation as |
| 1282 |
|
it can be reset while reading iir */ |
| 1283 |
|
int thr_ipending; |
| 1284 |
} SerialState; |
} SerialState; |
| 1285 |
|
|
| 1286 |
SerialState serial_ports[1]; |
SerialState serial_ports[1]; |
| 1291 |
|
|
| 1292 |
if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { |
if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { |
| 1293 |
s->iir = UART_IIR_RDI; |
s->iir = UART_IIR_RDI; |
| 1294 |
} else if ((s->lsr & UART_LSR_THRE) && (s->ier & UART_IER_THRI)) { |
} else if (s->thr_ipending && (s->ier & UART_IER_THRI)) { |
| 1295 |
s->iir = UART_IIR_THRI; |
s->iir = UART_IIR_THRI; |
| 1296 |
} else { |
} else { |
| 1297 |
s->iir = UART_IIR_NO_INT; |
s->iir = UART_IIR_NO_INT; |
| 1310 |
int ret; |
int ret; |
| 1311 |
|
|
| 1312 |
addr &= 7; |
addr &= 7; |
| 1313 |
|
#ifdef DEBUG_SERIAL |
| 1314 |
|
printf("serial: write addr=0x%02x val=0x%02x\n", addr, val); |
| 1315 |
|
#endif |
| 1316 |
switch(addr) { |
switch(addr) { |
| 1317 |
default: |
default: |
| 1318 |
case 0: |
case 0: |
| 1319 |
if (s->lcr & UART_LCR_DLAB) { |
if (s->lcr & UART_LCR_DLAB) { |
| 1320 |
s->divider = (s->divider & 0xff00) | val; |
s->divider = (s->divider & 0xff00) | val; |
| 1321 |
} else { |
} else { |
| 1322 |
|
s->thr_ipending = 0; |
| 1323 |
s->lsr &= ~UART_LSR_THRE; |
s->lsr &= ~UART_LSR_THRE; |
| 1324 |
serial_update_irq(); |
serial_update_irq(); |
| 1325 |
|
|
| 1327 |
do { |
do { |
| 1328 |
ret = write(1, &ch, 1); |
ret = write(1, &ch, 1); |
| 1329 |
} while (ret != 1); |
} while (ret != 1); |
| 1330 |
|
s->thr_ipending = 1; |
| 1331 |
s->lsr |= UART_LSR_THRE; |
s->lsr |= UART_LSR_THRE; |
| 1332 |
s->lsr |= UART_LSR_TEMT; |
s->lsr |= UART_LSR_TEMT; |
| 1333 |
serial_update_irq(); |
serial_update_irq(); |
| 1386 |
break; |
break; |
| 1387 |
case 2: |
case 2: |
| 1388 |
ret = s->iir; |
ret = s->iir; |
| 1389 |
|
/* reset THR pending bit */ |
| 1390 |
|
if ((ret & 0x7) == UART_IIR_THRI) |
| 1391 |
|
s->thr_ipending = 0; |
| 1392 |
|
serial_update_irq(); |
| 1393 |
break; |
break; |
| 1394 |
case 3: |
case 3: |
| 1395 |
ret = s->lcr; |
ret = s->lcr; |
| 1401 |
ret = s->lsr; |
ret = s->lsr; |
| 1402 |
break; |
break; |
| 1403 |
case 6: |
case 6: |
| 1404 |
ret = s->msr; |
if (s->mcr & UART_MCR_LOOP) { |
| 1405 |
|
/* in loopback, the modem output pins are connected to the |
| 1406 |
|
inputs */ |
| 1407 |
|
ret = (s->mcr & 0x0c) << 4; |
| 1408 |
|
ret |= (s->mcr & 0x02) << 3; |
| 1409 |
|
ret |= (s->mcr & 0x01) << 5; |
| 1410 |
|
} else { |
| 1411 |
|
ret = s->msr; |
| 1412 |
|
} |
| 1413 |
break; |
break; |
| 1414 |
case 7: |
case 7: |
| 1415 |
ret = s->scr; |
ret = s->scr; |
| 1416 |
break; |
break; |
| 1417 |
} |
} |
| 1418 |
|
#ifdef DEBUG_SERIAL |
| 1419 |
|
printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret); |
| 1420 |
|
#endif |
| 1421 |
return ret; |
return ret; |
| 1422 |
} |
} |
| 1423 |
|
|
| 1480 |
SerialState *s = &serial_ports[0]; |
SerialState *s = &serial_ports[0]; |
| 1481 |
|
|
| 1482 |
s->lsr = UART_LSR_TEMT | UART_LSR_THRE; |
s->lsr = UART_LSR_TEMT | UART_LSR_THRE; |
| 1483 |
|
s->iir = UART_IIR_NO_INT; |
| 1484 |
|
|
| 1485 |
register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
| 1486 |
register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
| 1487 |
} |
} |
| 2201 |
{ |
{ |
| 2202 |
KBDState *s = &kbd_state; |
KBDState *s = &kbd_state; |
| 2203 |
KBDQueue *q; |
KBDQueue *q; |
| 2204 |
int val; |
int val, index; |
| 2205 |
|
|
| 2206 |
q = &s->queues[0]; /* first check KBD data */ |
q = &s->queues[0]; /* first check KBD data */ |
| 2207 |
if (q->count == 0) |
if (q->count == 0) |
| 2208 |
q = &s->queues[1]; /* then check AUX data */ |
q = &s->queues[1]; /* then check AUX data */ |
| 2209 |
if (q->count == 0) { |
if (q->count == 0) { |
| 2210 |
/* XXX: return something else ? */ |
/* NOTE: if no data left, we return the last keyboard one |
| 2211 |
val = 0; |
(needed for EMM386) */ |
| 2212 |
|
/* XXX: need a timer to do things correctly */ |
| 2213 |
|
q = &s->queues[0]; |
| 2214 |
|
index = q->rptr - 1; |
| 2215 |
|
if (index < 0) |
| 2216 |
|
index = KBD_QUEUE_SIZE - 1; |
| 2217 |
|
val = q->data[index]; |
| 2218 |
} else { |
} else { |
| 2219 |
val = q->data[q->rptr]; |
val = q->data[q->rptr]; |
| 2220 |
if (++q->rptr == KBD_QUEUE_SIZE) |
if (++q->rptr == KBD_QUEUE_SIZE) |
| 2829 |
pic_set_irq(0, 1); |
pic_set_irq(0, 1); |
| 2830 |
pic_set_irq(0, 0); |
pic_set_irq(0, 0); |
| 2831 |
timer_irq_pending = 0; |
timer_irq_pending = 0; |
| 2832 |
|
/* XXX: RTC test */ |
| 2833 |
|
if (cmos_data[RTC_REG_B] & 0x40) { |
| 2834 |
|
pic_set_irq(8, 1); |
| 2835 |
|
} |
| 2836 |
} |
} |
| 2837 |
|
|
| 2838 |
/* VGA */ |
/* VGA */ |
| 3219 |
env->idt.limit = 0xffff; |
env->idt.limit = 0xffff; |
| 3220 |
env->gdt.limit = 0xffff; |
env->gdt.limit = 0xffff; |
| 3221 |
env->ldt.limit = 0xffff; |
env->ldt.limit = 0xffff; |
| 3222 |
|
env->ldt.flags = DESC_P_MASK; |
| 3223 |
|
env->tr.limit = 0xffff; |
| 3224 |
|
env->tr.flags = DESC_P_MASK; |
| 3225 |
|
|
| 3226 |
/* not correct (CS base=0xffff0000) */ |
/* not correct (CS base=0xffff0000) */ |
| 3227 |
cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0x000f0000, 0xffff, 0); |
cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0x000f0000, 0xffff, 0); |