Break up vl.h.
[qemu] / hw / pc.c
diff --git a/hw/pc.c b/hw/pc.c
index 7d86f32..99bb906 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1,8 +1,8 @@
 /*
  * QEMU PC System Emulator
- * 
+ *
  * Copyright (c) 2003-2004 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "vl.h"
+#include "hw.h"
+#include "pc.h"
+#include "fdc.h"
+#include "pci.h"
+#include "block.h"
+#include "sysemu.h"
+#include "audio/audio.h"
+#include "net.h"
+#include "smbus.h"
+#include "boards.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -65,7 +74,7 @@ uint64_t cpu_get_tsc(CPUX86State *env)
 #if USE_KQEMU
     if (env->kqemu_enabled) {
         return cpu_get_real_ticks();
-    } else 
+    } else
 #endif
     {
         return cpu_get_ticks();
@@ -89,10 +98,13 @@ int cpu_get_pic_interrupt(CPUState *env)
     if (intno >= 0) {
         /* set irq request if a PIC irq is still pending */
         /* XXX: improve that */
-        pic_update_irq(isa_pic); 
+        pic_update_irq(isa_pic);
         return intno;
     }
     /* read the irq from the PIC */
+    if (!apic_accept_pic_intr(env))
+        return -1;
+
     intno = pic_read_irq(isa_pic);
     return intno;
 }
@@ -100,10 +112,8 @@ int cpu_get_pic_interrupt(CPUState *env)
 static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
-    if (level)
+    if (level && apic_accept_pic_intr(env))
         cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
 /* PC cmos mappings */
@@ -134,7 +144,7 @@ static int cmos_get_fd_drive_type(int fd0)
     return val;
 }
 
-static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd) 
+static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
 {
     RTCState *s = rtc_state;
     int cylinders, heads, sectors;
@@ -151,10 +161,28 @@ static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
     rtc_set_memory(s, info_ofs + 8, sectors);
 }
 
+/* convert boot_device letter to something recognizable by the bios */
+static int boot_device2nibble(char boot_device)
+{
+    switch(boot_device) {
+    case 'a':
+    case 'b':
+        return 0x01; /* floppy boot */
+    case 'c':
+        return 0x02; /* hard drive boot */
+    case 'd':
+        return 0x03; /* CD-ROM boot */
+    case 'n':
+        return 0x04; /* Network boot */
+    }
+    return 0;
+}
+
 /* hd_table must contain 4 block drivers */
-static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
+static void cmos_init(int ram_size, const char *boot_device, BlockDriverState **hd_table)
 {
     RTCState *s = rtc_state;
+    int nbds, bds[3] = { 0, };
     int val;
     int fd0, fd1, nb;
     int i;
@@ -182,25 +210,24 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
         val = 65535;
     rtc_set_memory(s, 0x34, val);
     rtc_set_memory(s, 0x35, val >> 8);
-    
-    switch(boot_device) {
-    case 'a':
-    case 'b':
-        rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
-        if (!fd_bootchk)
-            rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
-        break;
-    default:
-    case 'c':
-        rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
-        break;
-    case 'd':
-        rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
-        break;
-    case 'n':
-        rtc_set_memory(s, 0x3d, 0x04); /* Network boot */
-        break; 
+
+    /* set boot devices, and disable floppy signature check if requested */
+#define PC_MAX_BOOT_DEVICES 3
+    nbds = strlen(boot_device);
+    if (nbds > PC_MAX_BOOT_DEVICES) {
+        fprintf(stderr, "Too many boot devices for PC\n");
+        exit(1);
+    }
+    for (i = 0; i < nbds; i++) {
+        bds[i] = boot_device2nibble(boot_device[i]);
+        if (bds[i] == 0) {
+            fprintf(stderr, "Invalid boot device for PC: '%c'\n",
+                    boot_device[i]);
+            exit(1);
+        }
     }
+    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
+    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ?  0x0 : 0x1));
 
     /* floppy type */
 
@@ -209,7 +236,7 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
 
     val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
     rtc_set_memory(s, 0x10, val);
-    
+
     val = 0;
     nb = 0;
     if (fd0 < 3)
@@ -235,7 +262,7 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
     rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
     if (hd_table[0])
         cmos_init_hd(0x19, 0x1b, hd_table[0]);
-    if (hd_table[1]) 
+    if (hd_table[1])
         cmos_init_hd(0x1a, 0x24, hd_table[1]);
 
     val = 0;
@@ -294,7 +321,7 @@ void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
 {
     static const char shutdown_str[8] = "Shutdown";
     static int shutdown_index = 0;
-    
+
     switch(addr) {
         /* Bochs BIOS messages */
     case 0x400:
@@ -404,7 +431,7 @@ static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
     bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
 }
 
-int load_kernel(const char *filename, uint8_t *addr, 
+int load_kernel(const char *filename, uint8_t *addr,
                 uint8_t *real_addr)
 {
     int fd, size;
@@ -420,7 +447,7 @@ int load_kernel(const char *filename, uint8_t *addr,
     setup_sects = real_addr[0x1F1];
     if (!setup_sects)
         setup_sects = 4;
-    if (read(fd, real_addr + 512, setup_sects * 512) != 
+    if (read(fd, real_addr + 512, setup_sects * 512) !=
         setup_sects * 512)
         goto fail;
 
@@ -476,7 +503,9 @@ static void load_linux(const char *kernel_filename,
     }
 
     /* kernel protocol version */
+#if 0
     fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
+#endif
     if (ldl_p(header+0x202) == 0x53726448)
        protocol = lduw_p(header+0x206);
     else
@@ -499,6 +528,7 @@ static void load_linux(const char *kernel_filename,
        prot_addr    = phys_ram_base + 0x100000;
     }
 
+#if 0
     fprintf(stderr,
            "qemu: real_addr     = %#zx\n"
            "qemu: cmdline_addr  = %#zx\n"
@@ -506,6 +536,7 @@ static void load_linux(const char *kernel_filename,
            real_addr-phys_ram_base,
            cmdline_addr-phys_ram_base,
            prot_addr-phys_ram_base);
+#endif
 
     /* highest address for loading the initrd */
     if (protocol >= 0x203)
@@ -662,11 +693,11 @@ static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
+static void pc_init1(int ram_size, int vga_ram_size, const char *boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
                      const char *initrd_filename,
-                     int pci_enabled)
+                     int pci_enabled, const char *cpu_model)
 {
     char buf[1024];
     int ret, linux_boot, i;
@@ -682,8 +713,20 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
     linux_boot = (kernel_filename != NULL);
 
     /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+    
     for(i = 0; i < smp_cpus; i++) {
-        env = cpu_init();
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find x86 CPU definition\n");
+            exit(1);
+        }
         if (i != 0)
             env->hflags |= HF_HALTED_MASK;
         if (smp_cpus > 1) {
@@ -706,9 +749,11 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
     vga_ram_addr = qemu_ram_alloc(vga_ram_size);
 
     /* BIOS load */
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
     bios_size = get_image_size(buf);
-    if (bios_size <= 0 || 
+    if (bios_size <= 0 ||
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
@@ -727,7 +772,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
     }
     vga_bios_size = get_image_size(buf);
-    if (vga_bios_size <= 0 || vga_bios_size > 65536) 
+    if (vga_bios_size <= 0 || vga_bios_size > 65536)
         goto vga_bios_error;
     vga_bios_offset = qemu_ram_alloc(65536);
 
@@ -739,17 +784,17 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
     }
 
     /* setup basic memory access */
-    cpu_register_physical_memory(0xc0000, 0x10000, 
+    cpu_register_physical_memory(0xc0000, 0x10000,
                                  vga_bios_offset | IO_MEM_ROM);
 
     /* map the last 128KB of the BIOS in ISA space */
     isa_bios_size = bios_size;
     if (isa_bios_size > (128 * 1024))
         isa_bios_size = 128 * 1024;
-    cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size, 
+    cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
                                  IO_MEM_UNASSIGNED);
-    cpu_register_physical_memory(0x100000 - isa_bios_size, 
-                                 isa_bios_size, 
+    cpu_register_physical_memory(0x100000 - isa_bios_size,
+                                 isa_bios_size,
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
     {
@@ -760,7 +805,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
         for (i = 0; i < nb_option_roms; i++) {
             size = get_image_size(option_rom[i]);
             if (size < 0) {
-                fprintf(stderr, "Could not load option rom '%s'\n", 
+                fprintf(stderr, "Could not load option rom '%s'\n",
                         option_rom[i]);
                 exit(1);
             }
@@ -781,9 +826,9 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
     }
 
     /* map all the bios at the top of memory */
-    cpu_register_physical_memory((uint32_t)(-bios_size), 
+    cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
-    
+
     bochs_bios_init();
 
     if (linux_boot)
@@ -807,11 +852,11 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
 
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
-            pci_cirrus_vga_init(pci_bus, 
-                                ds, phys_ram_base + vga_ram_addr, 
+            pci_cirrus_vga_init(pci_bus,
+                                ds, phys_ram_base + vga_ram_addr,
                                 vga_ram_addr, vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr, 
+            isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr,
                                 vga_ram_addr, vga_ram_size);
         }
     } else if (vmsvga_enabled) {
@@ -822,10 +867,10 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
             fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
     } else {
         if (pci_enabled) {
-            pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, 
+            pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
                          vga_ram_addr, vga_ram_size, 0, 0);
         } else {
-            isa_vga_init(ds, phys_ram_base + vga_ram_addr, 
+            isa_vga_init(ds, phys_ram_base + vga_ram_addr,
                          vga_ram_addr, vga_ram_size);
         }
     }
@@ -914,7 +959,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
             smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
         }
     }
-    
+
     if (i440fx_state) {
         i440fx_init_memory_mappings(i440fx_state);
     }
@@ -937,10 +982,10 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
 #endif
 }
 
-static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
-                        DisplayState *ds, const char **fd_filename, 
-                        int snapshot, 
-                        const char *kernel_filename, 
+static void pc_init_pci(int ram_size, int vga_ram_size, const char *boot_device,
+                        DisplayState *ds, const char **fd_filename,
+                        int snapshot,
+                        const char *kernel_filename,
                         const char *kernel_cmdline,
                         const char *initrd_filename,
                         const char *cpu_model)
@@ -948,13 +993,13 @@ static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
              kernel_filename, kernel_cmdline,
-             initrd_filename, 1);
+             initrd_filename, 1, cpu_model);
 }
 
-static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
-                        DisplayState *ds, const char **fd_filename, 
-                        int snapshot, 
-                        const char *kernel_filename, 
+static void pc_init_isa(int ram_size, int vga_ram_size, const char *boot_device,
+                        DisplayState *ds, const char **fd_filename,
+                        int snapshot,
+                        const char *kernel_filename,
                         const char *kernel_cmdline,
                         const char *initrd_filename,
                         const char *cpu_model)
@@ -962,7 +1007,7 @@ static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
              kernel_filename, kernel_cmdline,
-             initrd_filename, 0);
+             initrd_filename, 0, cpu_model);
 }
 
 QEMUMachine pc_machine = {