From patchwork Mon Feb 6 21:29:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Herv=C3=A9_Poussineau?= X-Patchwork-Id: 139814 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4F85F1007D1 for ; Tue, 7 Feb 2012 09:11:11 +1100 (EST) Received: from localhost ([::1]:33706 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuWmB-0004HY-5y for incoming@patchwork.ozlabs.org; Mon, 06 Feb 2012 17:11:07 -0500 Received: from eggs.gnu.org ([140.186.70.92]:44851) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuW8e-0004Zt-K7 for qemu-devel@nongnu.org; Mon, 06 Feb 2012 16:30:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RuW8c-0001TN-C1 for qemu-devel@nongnu.org; Mon, 06 Feb 2012 16:30:16 -0500 Received: from smtp1-g21.free.fr ([212.27.42.1]:34767) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuW8b-0001Sx-Am for qemu-devel@nongnu.org; Mon, 06 Feb 2012 16:30:14 -0500 Received: from localhost.localdomain (unknown [82.227.227.196]) by smtp1-g21.free.fr (Postfix) with ESMTP id A607C9401CB; Mon, 6 Feb 2012 22:30:07 +0100 (CET) From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= To: qemu-devel@nongnu.org Date: Mon, 6 Feb 2012 22:29:10 +0100 Message-Id: <1328563752-3976-10-git-send-email-hpoussin@reactos.org> X-Mailer: git-send-email 1.7.8.3 In-Reply-To: <1328563752-3976-1-git-send-email-hpoussin@reactos.org> References: <1328563752-3976-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 212.27.42.1 Cc: Kevin Wolf , =?UTF-8?q?Herv=C3=A9=20Poussineau?= Subject: [Qemu-devel] [PATCH v4 09/11] fdc: check if media rate is correct before doing any transfer X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The programmed rate has to be the same as the required rate for the floppy format ; if that's not the case, the transfer should abort. This check can be disabled by using the 'check_media_rate' property. Save media rate value only if media rate check is enabled. Signed-off-by: Hervé Poussineau --- hw/fdc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 50 insertions(+), 3 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index af007ae..d2a22fa 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -62,12 +62,15 @@ #define FD_SECTOR_SC 2 /* Sector size code */ #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */ +typedef struct FDCtrl FDCtrl; + /* Floppy disk drive emulation */ typedef enum FDiskFlags { FDISK_DBL_SIDES = 0x01, } FDiskFlags; typedef struct FDrive { + FDCtrl *fdctrl; BlockDriverState *bs; /* Drive status */ FDriveType drive; @@ -83,6 +86,7 @@ typedef struct FDrive { uint16_t bps; /* Bytes per sector */ uint8_t ro; /* Is read-only */ uint8_t media_changed; /* Is media changed */ + uint8_t media_rate; /* Data rate of medium */ } FDrive; static void fd_init(FDrive *drv) @@ -195,6 +199,7 @@ static void fd_revalidate(FDrive *drv) drv->last_sect = last_sect; drv->ro = ro; drv->drive = drive; + drv->media_rate = rate; } else { FLOPPY_DPRINTF("No disk in drive\n"); drv->last_sect = 0; @@ -206,8 +211,6 @@ static void fd_revalidate(FDrive *drv) /********************************************************/ /* Intel 82078 floppy disk controller emulation */ -typedef struct FDCtrl FDCtrl; - static void fdctrl_reset(FDCtrl *fdctrl, int do_irq); static void fdctrl_reset_fifo(FDCtrl *fdctrl); static int fdctrl_transfer_handler (void *opaque, int nchan, @@ -303,6 +306,7 @@ enum { }; enum { + FD_SR1_MA = 0x01, /* Missing address mark */ FD_SR1_NW = 0x02, /* Not writable */ FD_SR1_EC = 0x80, /* End of cylinder */ }; @@ -549,6 +553,24 @@ static const VMStateDescription vmstate_fdrive_media_changed = { } }; +static bool fdrive_media_rate_needed(void *opaque) +{ + FDrive *drive = opaque; + + return drive->fdctrl->check_media_rate; +} + +static const VMStateDescription vmstate_fdrive_media_rate = { + .name = "fdrive/media_rate", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(media_rate, FDrive), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_fdrive = { .name = "fdrive", .version_id = 1, @@ -565,6 +587,9 @@ static const VMStateDescription vmstate_fdrive = { .vmsd = &vmstate_fdrive_media_changed, .needed = &fdrive_media_changed_needed, } , { + .vmsd = &vmstate_fdrive_media_rate, + .needed = &fdrive_media_rate_needed, + } , { /* empty */ } } @@ -1078,6 +1103,19 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction) break; } + /* Check the data rate. If the programmed data rate does not match + * the currently inserted medium, the operation has to fail. */ + if (fdctrl->check_media_rate && + (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { + FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n", + fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + } + /* Set the FIFO state */ fdctrl->data_dir = direction; fdctrl->data_pos = 0; @@ -1800,7 +1838,15 @@ static void fdctrl_result_timer(void *opaque) if (cur_drv->last_sect != 0) { cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1; } - fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + /* READ_ID can't automatically succeed! */ + if (fdctrl->check_media_rate && + (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) { + FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n", + fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate); + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); + } else { + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + } } static void fdctrl_change_cb(void *opaque, bool load) @@ -1822,6 +1868,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) for (i = 0; i < MAX_FD; i++) { drive = &fdctrl->drives[i]; + drive->fdctrl = fdctrl; if (drive->bs) { if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {