Convert PCMCIA bus handling code to use QBus internally. MicroDrive code is still unaffected.
Signed-off-by: Dmitry Eremin-Solenikov <dbarysh...@gmail.com> --- Makefile.objs | 3 ++ hw/pcmcia.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/pcmcia.h | 15 +++++++- hw/pxa2xx_pcmcia.c | 2 +- vl.c | 43 ---------------------- 5 files changed, 120 insertions(+), 45 deletions(-) create mode 100644 hw/pcmcia.c diff --git a/Makefile.objs b/Makefile.objs index 44ce368..153a148 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -289,6 +289,9 @@ hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o +# PCMCIA +hw-obj-y += pcmcia.o + ###################################################################### # libdis # NOTE: the disassembler code is only needed for debugging diff --git a/hw/pcmcia.c b/hw/pcmcia.c new file mode 100644 index 0000000..17a49b6 --- /dev/null +++ b/hw/pcmcia.c @@ -0,0 +1,102 @@ +/* + * QEMU System Emulator + * PCMCIA subsystem + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2011 Dmitry Eremin-Solenikov + * + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "hw.h" +#include "pcmcia.h" +#include "monitor.h" + +/***********************************************************/ +/* PCMCIA/Cardbus */ + +static struct pcmcia_socket_entry_s { + PCMCIASocket *socket; + struct pcmcia_socket_entry_s *next; +} *pcmcia_sockets = 0; + +static BusInfo pcmcia_bus_info = { + .name = "PCMCIA", + .size = sizeof(PCMCIASocket), +}; + +void pcmcia_socket_register(PCMCIASocket *socket, DeviceState *parent) +{ + struct pcmcia_socket_entry_s *entry; + + qbus_create_inplace(&socket->qbus, &pcmcia_bus_info, + parent, "pcmcia"); + + entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s)); + entry->socket = socket; + entry->next = pcmcia_sockets; + pcmcia_sockets = entry; +} + +void pcmcia_socket_unregister(PCMCIASocket *socket) +{ + struct pcmcia_socket_entry_s *entry, **ptr; + + ptr = &pcmcia_sockets; + for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr) + if (entry->socket == socket) { + *ptr = entry->next; + qemu_free(entry); + } + + qbus_free(&socket->qbus); +} + +void pcmcia_info(Monitor *mon) +{ + struct pcmcia_socket_entry_s *iter; + + if (!pcmcia_sockets) { + monitor_printf(mon, "No PCMCIA sockets\n"); + } + + for (iter = pcmcia_sockets; iter; iter = iter->next) { + monitor_printf(mon, "%s: %s\n", iter->socket->slot_string, + iter->socket->attached ? iter->socket->card_string : + "Empty"); + } +} + +static int pcmcia_device_init(DeviceState *dev, DeviceInfo *info) +{ + PCMCIACardState *state = DO_UPCAST(PCMCIACardState, dev, dev); + PCMCIACardInfo *pinfo = DO_UPCAST(PCMCIACardInfo, qdev, info); + int rc; + + state->info = pinfo; + rc = pinfo->init(state); + return rc; +} + +void pcmcia_card_register(PCMCIACardInfo *info) +{ + info->qdev.init = pcmcia_device_init; + info->qdev.bus_info = &pcmcia_bus_info; + assert(info->qdev.size >= sizeof(PCMCIACardState)); + qdev_register(&info->qdev); +} diff --git a/hw/pcmcia.h b/hw/pcmcia.h index f0b16b8..561d86c 100644 --- a/hw/pcmcia.h +++ b/hw/pcmcia.h @@ -1,19 +1,30 @@ /* PCMCIA/Cardbus */ #include "qemu-common.h" +#include "qdev.h" typedef struct { + BusState qbus; qemu_irq irq; int attached; const char *slot_string; const char *card_string; } PCMCIASocket; -void pcmcia_socket_register(PCMCIASocket *socket); +void pcmcia_socket_register(PCMCIASocket *socket, DeviceState *parent); void pcmcia_socket_unregister(PCMCIASocket *socket); void pcmcia_info(Monitor *mon); +typedef struct PCMCIACardInfo { + DeviceInfo qdev; + + int (*init)(PCMCIACardState *state); +} PCMCIACardInfo; + struct PCMCIACardState { + DeviceState dev; + PCMCIACardInfo *info; + void *state; PCMCIASocket *slot; int (*attach)(void *state); @@ -30,6 +41,8 @@ struct PCMCIACardState { void (*io_write)(void *state, uint32_t address, uint16_t value); }; +void pcmcia_card_register(PCMCIACardInfo *info); + #define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ #define CISTPL_NO_LINK 0x14 /* No Link Tuple */ #define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */ diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c index 3d93829..61afaf1 100644 --- a/hw/pxa2xx_pcmcia.c +++ b/hw/pxa2xx_pcmcia.c @@ -187,7 +187,7 @@ static int pxa2xx_pcmcia_initfn(SysBusDevice *dev) s->slot.slot_string = str; s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; - pcmcia_socket_register(&s->slot); + pcmcia_socket_register(&s->slot, &s->busdev.qdev); return 0; } diff --git a/vl.c b/vl.c index 68c3b53..2b277a6 100644 --- a/vl.c +++ b/vl.c @@ -980,49 +980,6 @@ void do_usb_del(Monitor *mon, const QDict *qdict) } /***********************************************************/ -/* PCMCIA/Cardbus */ - -static struct pcmcia_socket_entry_s { - PCMCIASocket *socket; - struct pcmcia_socket_entry_s *next; -} *pcmcia_sockets = 0; - -void pcmcia_socket_register(PCMCIASocket *socket) -{ - struct pcmcia_socket_entry_s *entry; - - entry = qemu_malloc(sizeof(struct pcmcia_socket_entry_s)); - entry->socket = socket; - entry->next = pcmcia_sockets; - pcmcia_sockets = entry; -} - -void pcmcia_socket_unregister(PCMCIASocket *socket) -{ - struct pcmcia_socket_entry_s *entry, **ptr; - - ptr = &pcmcia_sockets; - for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr) - if (entry->socket == socket) { - *ptr = entry->next; - qemu_free(entry); - } -} - -void pcmcia_info(Monitor *mon) -{ - struct pcmcia_socket_entry_s *iter; - - if (!pcmcia_sockets) - monitor_printf(mon, "No PCMCIA sockets\n"); - - for (iter = pcmcia_sockets; iter; iter = iter->next) - monitor_printf(mon, "%s: %s\n", iter->socket->slot_string, - iter->socket->attached ? iter->socket->card_string : - "Empty"); -} - -/***********************************************************/ /* machine registration */ static QEMUMachine *first_machine = NULL; -- 1.7.4.1