qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 03/10] ide: add support for ide extenders


From: Alexander Graf
Subject: [Qemu-devel] [PATCH 03/10] ide: add support for ide extenders
Date: Wed, 17 Nov 2010 02:05:29 +0100

From: Roland Elek <address@hidden>

An "extender" (from the "extends" keyword denoting a subclass in
various object-oriented languages) is a device that builds upon an
IDE bus, but needs to change various aspects of its inner workings
to customize it to its needs. An example of an extender is an AHCI
HBA. We add support for extenders by defining a struct that contains
callback function pointers that can be set by the device building
upon the bus. The IDE core was modified so that ide_transfer_start,
ide_set_irq and ide_dma_start call the function pointed to by the
respective field in the extender struct, instead of doing their
original jobs. The original functions are available as
pata_transfer_start, pata_set_irq and pata_dma_start. The extender
callbacks are initialized to these in ide_init2, making them the
defaults, and eliminating the need to modify ATA controller code.

Signed-off-by: Roland Elek <address@hidden>
---
 hw/ide/core.c     |   34 +++++++++++++++++++++++++++++++++-
 hw/ide/internal.h |   26 +++++++++++++++++++-------
 2 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 1849069..276b853 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -67,6 +67,8 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 static int ide_handle_rw_error(IDEState *s, int error, int op);
 static void ide_flush_cache(IDEState *s);
 
+static void pata_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+
 static void padstr(char *str, const char *src, int len)
 {
     int i, v;
@@ -325,6 +327,12 @@ static inline void ide_dma_submit_check(IDEState *s,
 static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                                EndTransferFunc *end_transfer_func)
 {
+    s->bus->extender.transfer_start_fn(s,buf,size,end_transfer_func);
+}
+
+static void pata_transfer_start(IDEState *s, uint8_t *buf, int size,
+                               EndTransferFunc *end_transfer_func)
+{
     s->end_transfer_func = end_transfer_func;
     s->data_ptr = buf;
     s->data_end = buf + size;
@@ -2580,6 +2588,18 @@ static void ide_dummy_transfer_stop(IDEState *s)
     s->io_buffer[3] = 0xff;
 }
 
+static void pata_set_irq(IDEBus *bus)
+{
+    BMDMAState *bm = bus->bmdma;
+
+    if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
+        if (bm) {
+            bm->status |= BM_STATUS_INT;
+        }
+        qemu_irq_raise(bus->irq);
+    }
+}
+
 static void ide_reset(IDEState *s)
 {
 #ifdef DEBUG_IDE
@@ -2725,6 +2745,9 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
         ide_reset(&bus->ifs[i]);
     }
     bus->irq = irq;
+    bus->extender.transfer_start_fn = pata_transfer_start;
+    bus->extender.irq_set_fn = pata_set_irq;
+    bus->extender.dma_start_fn = pata_dma_start;
 }
 
 /* TODO convert users to qdev and remove */
@@ -2748,6 +2771,9 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, 
DriveInfo *hd0,
         }
     }
     bus->irq = irq;
+    bus->extender.transfer_start_fn = pata_transfer_start;
+    bus->extender.irq_set_fn = pata_set_irq;
+    bus->extender.dma_start_fn = pata_dma_start;
 }
 
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2)
@@ -2919,9 +2945,10 @@ const VMStateDescription vmstate_ide_bus = {
 /***********************************************************/
 /* PCI IDE definitions */
 
-static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
+static void pata_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
 {
     BMDMAState *bm = s->bus->bmdma;
+
     if(!bm)
         return;
     bm->unit = s->unit;
@@ -2936,6 +2963,11 @@ static void ide_dma_start(IDEState *s, 
BlockDriverCompletionFunc *dma_cb)
     }
 }
 
+static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
+{
+    s->bus->extender.dma_start_fn(s,dma_cb);
+}
+
 static void ide_dma_restart(IDEState *s, int is_read)
 {
     BMDMAState *bm = s->bus->bmdma;
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index e7e1f80..19e5efb 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -20,6 +20,7 @@ typedef struct IDEDevice IDEDevice;
 typedef struct IDEDeviceInfo IDEDeviceInfo;
 typedef struct IDEState IDEState;
 typedef struct BMDMAState BMDMAState;
+typedef struct IDEExtender IDEExtender;
 
 /* Bits of HD_STATUS */
 #define ERR_STAT               0x01
@@ -366,6 +367,14 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
 
 typedef void EndTransferFunc(IDEState *);
 
+
+typedef void TransferStartFunc(IDEState *,
+                             uint8_t *,
+                             int,
+                             EndTransferFunc *);
+typedef void IRQSetFunc(IDEBus *);
+typedef void DMAStartFunc(IDEState *, BlockDriverCompletionFunc *);
+
 /* NOTE: IDEState represents in fact one drive */
 struct IDEState {
     IDEBus *bus;
@@ -442,12 +451,21 @@ struct IDEState {
     uint8_t *smart_selftest_data;
 };
 
+/* This struct represents a device that uses an IDE bus, but requires
+ * modifications to how it works. An example is AHCI. */
+struct IDEExtender {
+    TransferStartFunc *transfer_start_fn;
+    IRQSetFunc *irq_set_fn;
+    DMAStartFunc *dma_start_fn;
+};
+
 struct IDEBus {
     BusState qbus;
     IDEDevice *master;
     IDEDevice *slave;
     BMDMAState *bmdma;
     IDEState ifs[2];
+    IDEExtender extender;
     uint8_t unit;
     uint8_t cmd;
     qemu_irq irq;
@@ -512,13 +530,7 @@ static inline IDEState *bmdma_active_if(BMDMAState *bmdma)
 
 static inline void ide_set_irq(IDEBus *bus)
 {
-    BMDMAState *bm = bus->bmdma;
-    if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
-        if (bm) {
-            bm->status |= BM_STATUS_INT;
-        }
-        qemu_irq_raise(bus->irq);
-    }
+    bus->extender.irq_set_fn(bus);
 }
 
 /* hw/ide/core.c */
-- 
1.6.0.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]