From patchwork Wed Nov 17 01:05:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 71495 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 868A7B71A2 for ; Wed, 17 Nov 2010 12:12:14 +1100 (EST) Received: from localhost ([127.0.0.1]:58540 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PIWZH-0006E3-Nq for incoming@patchwork.ozlabs.org; Tue, 16 Nov 2010 20:12:11 -0500 Received: from [140.186.70.92] (port=60869 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PIWT3-00034t-AM for qemu-devel@nongnu.org; Tue, 16 Nov 2010 20:05:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PIWSy-0002TV-0C for qemu-devel@nongnu.org; Tue, 16 Nov 2010 20:05:45 -0500 Received: from cantor.suse.de ([195.135.220.2]:47303 helo=mx1.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PIWSx-0002SN-KF for qemu-devel@nongnu.org; Tue, 16 Nov 2010 20:05:39 -0500 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 256B794393; Wed, 17 Nov 2010 02:05:38 +0100 (CET) From: Alexander Graf To: QEMU-devel Developers Date: Wed, 17 Nov 2010 02:05:29 +0100 Message-Id: <1289955937-24121-4-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1289955937-24121-1-git-send-email-agraf@suse.de> References: <1289955937-24121-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: tj@kernel.org, Joerg Roedel , Sebastian Herbszt , Roland Elek Subject: [Qemu-devel] [PATCH 03/10] ide: add support for ide extenders X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Roland Elek 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 --- 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 */