diff -Nuar ioemu-orig/hw/ide.c ioemu/hw/ide.c --- a/tools/ioemu/hw/ide.c 2007-03-01 15:18:35.000000000 -0700 +++ b/tools/ioemu/hw/ide.c 2007-03-01 15:19:15.000000000 -0700 @@ -392,6 +392,9 @@ int type; /* see IDE_TYPE_xxx */ } PCIIDEState; +static PCIIDEState *principal_ide_controller; +extern FILE *logfile; + #define DMA_MULTI_THREAD #ifdef DMA_MULTI_THREAD @@ -2001,6 +2004,27 @@ ide_dummy_transfer_stop(s); } +void ide_unplug_harddisks(void) +{ + IDEState *s; + int i; + + if (!principal_ide_controller) { + fprintf(logfile, "No principal controller?\n"); + return; + } + for (i = 0; i < 4; i++) { + s = principal_ide_controller->ide_if + i; + if (!s->bs) + continue; /* drive not present */ + if (s->is_cdrom) + continue; /* cdrom */ + /* Is a hard disk, unplug it. */ + s->bs = NULL; + ide_reset(s); + } +} + struct partition { uint8_t boot_ind; /* 0x80 - active */ uint8_t head; /* starting head */ @@ -2436,6 +2460,9 @@ sizeof(PCIIDEState), -1, NULL, NULL); + if (principal_ide_controller) + abort(); + principal_ide_controller = d; d->type = IDE_TYPE_CMD646; pci_conf = d->dev.config; pci_conf[0x00] = 0x95; // CMD646 @@ -2493,6 +2520,9 @@ NULL, NULL); d->type = IDE_TYPE_PIIX3; + if (principal_ide_controller) + abort(); + principal_ide_controller = d; pci_conf = d->dev.config; pci_conf[0x00] = 0x86; // Intel pci_conf[0x01] = 0x80; diff -Nuar ioemu-orig/hw/pci.c ioemu/hw/pci.c --- a/tools/ioemu/hw/pci.c 2007-03-01 15:18:35.000000000 -0700 +++ b/tools/ioemu/hw/pci.c 2007-03-01 15:19:15.000000000 -0700 @@ -514,3 +514,24 @@ } } +void pci_unplug_netifs(void) +{ + PCIBus *bus; + int x; + + /* We only support one PCI bus */ + for (bus = first_bus; bus; bus = NULL) { + for (x = 0; x < 256; x++) { + if (bus->devices[x] && + bus->devices[x]->config[0xa] == 0 && + bus->devices[x]->config[0xb] == 2) { + /* Found a netif. Remove it from the bus. Note that + we don't free it here, since there could still be + references to it floating around. There are only + ever one or two structures leaked, and it's not + worth finding them all. */ + bus->devices[x] = NULL; + } + } + } +} diff -Nuar ioemu-orig/hw/xen_platform.c ioemu/hw/xen_platform.c --- a/tools/ioemu/hw/xen_platform.c 2007-03-01 15:18:35.000000000 -0700 +++ b/tools/ioemu/hw/xen_platform.c 2007-03-01 15:19:15.000000000 -0700 @@ -29,9 +29,36 @@ extern FILE *logfile; +static uint32_t ioport_base; + static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - return; + DECLARE_DOMCTL; + int rc; + + switch (addr - ioport_base) { + case 0: + fprintf(logfile, "Init hypercall page %x, addr %x.\n", val, addr); + domctl.domain = (domid_t)domid; + domctl.u.hypercall_init.gmfn = val; + domctl.cmd = XEN_DOMCTL_hypercall_init; + rc = xc_domctl(xc_handle, &domctl); + fprintf(logfile, "result -> %d.\n", rc); + break; + case 4: + fprintf(logfile, "Disconnect IDE hard disk...\n"); + ide_unplug_harddisks(); + fprintf(logfile, "Disconnect netifs...\n"); + pci_unplug_netifs(); + fprintf(logfile, "Shutdown taps...\n"); + net_tap_shutdown_all(); + fprintf(logfile, "Done.\n"); + break; + default: + fprintf(logfile, "Write to bad port %x (base %x) on evtchn device.\n", + addr, ioport_base); + break; + } } static uint32_t platform_ioport_read(void *opaque, uint32_t addr) @@ -42,6 +69,8 @@ static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { + ioport_base = addr; + register_ioport_write(addr, 16, 4, platform_ioport_write, NULL); register_ioport_read(addr, 16, 1, platform_ioport_read, NULL); } diff -Nuar ioemu-orig/vl.c ioemu/vl.c --- a/tools/ioemu/vl.c 2007-03-01 15:18:35.000000000 -0700 +++ b/tools/ioemu/vl.c 2007-03-01 15:19:15.000000000 -0700 @@ -170,6 +170,19 @@ char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'}; extern int domid; +typedef struct IOHandlerRecord { + int fd; + IOCanRWHandler *fd_read_poll; + IOHandler *fd_read; + IOHandler *fd_write; + void *opaque; + /* temporary data */ + struct pollfd *ufd; + struct IOHandlerRecord *next; +} IOHandlerRecord; + +static IOHandlerRecord *first_io_handler; + char vncpasswd[64]; unsigned char challenge[AUTHCHALLENGESIZE]; @@ -3084,6 +3097,7 @@ typedef struct TAPState { VLANClientState *vc; int fd; + struct TAPState *next; } TAPState; static void tap_receive(void *opaque, const uint8_t *buf, int size) @@ -3111,6 +3125,36 @@ } } +static TAPState *head_net_tap; + +void net_tap_shutdown_all(void) +{ + struct IOHandlerRecord **pioh, *ioh; + + while (head_net_tap) { + pioh = &first_io_handler; + for (;;) { + ioh = *pioh; + if (ioh == NULL) + break; + if (ioh->fd == head_net_tap->fd) { + *pioh = ioh->next; + qemu_free(ioh); + break; + } + pioh = &ioh->next; + } + if (!ioh) + fprintf(stderr, + "warning: can't find iohandler for %d to close it properly.\n", + head_net_tap->fd); + close(head_net_tap->fd); + head_net_tap = head_net_tap->next; + } +} + + + /* fd support */ static TAPState *net_tap_fd_init(VLANState *vlan, int fd) @@ -3122,6 +3166,8 @@ return NULL; s->fd = fd; s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s); + s->next = head_net_tap; + head_net_tap = s; qemu_set_fd_handler(s->fd, tap_send, NULL, s); snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd); return s; @@ -4047,19 +4093,6 @@ #define MAX_IO_HANDLERS 64 -typedef struct IOHandlerRecord { - int fd; - IOCanRWHandler *fd_read_poll; - IOHandler *fd_read; - IOHandler *fd_write; - void *opaque; - /* temporary data */ - struct pollfd *ufd; - struct IOHandlerRecord *next; -} IOHandlerRecord; - -static IOHandlerRecord *first_io_handler; - /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ int qemu_set_fd_handler2(int fd, diff -Nuar ioemu-orig/vl.h ioemu/vl.h --- a/tools/ioemu/vl.h 2007-03-01 15:18:35.000000000 -0700 +++ b/tools/ioemu/vl.h 2007-03-01 15:19:15.000000000 -0700 @@ -826,6 +826,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn); int pmac_ide_init (BlockDriverState **hd_table, SetIRQFunc *set_irq, void *irq_opaque, int irq); +void ide_unplug_harddisks(void); /* cdrom.c */ int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); @@ -1268,6 +1269,8 @@ extern char domain_name[]; void destroy_hvm_domain(void); +void net_tap_shutdown_all(void); +void pci_unplug_netifs(void); /* VNC Authentication */ #define AUTHCHALLENGESIZE 16