From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Eu7Xe-0008Fw-QH for qemu-devel@nongnu.org; Wed, 04 Jan 2006 07:15:00 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Eu7Vg-0008A3-Lp for qemu-devel@nongnu.org; Wed, 04 Jan 2006 07:14:54 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Eu7VY-00089b-Kw for qemu-devel@nongnu.org; Wed, 04 Jan 2006 07:12:50 -0500 Received: from [195.184.98.160] (helo=virtualhost.dk) by monty-python.gnu.org with esmtp (TLS-1.0:DHE_RSA_3DES_EDE_CBC_SHA:24) (Exim 4.34) id 1Eu7Ww-0001MD-PC for qemu-devel@nongnu.org; Wed, 04 Jan 2006 07:14:15 -0500 Received: from [62.242.22.158] (helo=router.home.kernel.dk) by virtualhost.dk with esmtp (Exim 3.36 #1) id 1Eu7Tr-0003A6-00 for qemu-devel@nongnu.org; Wed, 04 Jan 2006 13:11:03 +0100 Received: from nelson.home.kernel.dk ([192.168.0.33] helo=kernel.dk) by router.home.kernel.dk with esmtp (Exim 4.22) id 1Eu7Tq-0003oK-Eu for qemu-devel@nongnu.org; Wed, 04 Jan 2006 13:11:02 +0100 Date: Wed, 4 Jan 2006 13:12:57 +0100 From: Jens Axboe Message-ID: <20060104121256.GB3389@suse.de> References: <20060104121208.GA3389@suse.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20060104121208.GA3389@suse.de> Subject: [Qemu-devel] [PATCH 1/3] ide id updates Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Hi, Subject: [PATCH] ide id updates From: Jens Axboe Date: 1136375788 +0100 Some changes to the ata/atapi identify code and default values: - Store the drive id in the IDEState, so we can reliably set and query new values. Right now doing things like: doesn't work, as the IDENTIFY command will re-fill default values everytime. - Fill in IORDY, dma timings, and mdma modes. - Don't set both 1 << 14 and 0x4000 for word 93, it's the same thing. - Fill in supported/set ata specs - Implement real setting of transfer mode (sub feature 0x03 of WIN_SETFEATURES) so we can reflect the transfer mode requested by the OS. With this patch, Linux correctly identifies and sets DMA mode in the drive by default. --- hw/ide.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 54 insertions(+), 7 deletions(-) eaa17552cf9891cbc8fc46b826fde10a4d5e07c7 diff --git a/hw/ide.c b/hw/ide.c index 28ed5ab..8196ace 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -296,6 +296,8 @@ typedef struct IDEState { int cylinders, heads, sectors; int64_t nb_sectors; int mult_sectors; + int identify_set; + uint16_t identify_data[256]; SetIRQFunc *set_irq; void *irq_opaque; int irq; @@ -414,6 +416,11 @@ static void ide_identify(IDEState *s) unsigned int oldsize; char buf[20]; + if (s->identify_set) { + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); + return; + } + memset(s->io_buffer, 0, 512); p = (uint16_t *)s->io_buffer; put_le16(p + 0, 0x0040); @@ -433,10 +440,10 @@ static void ide_identify(IDEState *s) put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); #endif put_le16(p + 48, 1); /* dword I/O */ - put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */ + put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */ put_le16(p + 51, 0x200); /* PIO transfer cycle */ put_le16(p + 52, 0x200); /* DMA transfer cycle */ - put_le16(p + 53, 1 | 1 << 2); /* words 54-58,88 are valid */ + put_le16(p + 53, 1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 are valid */ put_le16(p + 54, s->cylinders); put_le16(p + 55, s->heads); put_le16(p + 56, s->sectors); @@ -447,15 +454,24 @@ static void ide_identify(IDEState *s) put_le16(p + 59, 0x100 | s->mult_sectors); put_le16(p + 60, s->nb_sectors); put_le16(p + 61, s->nb_sectors >> 16); - put_le16(p + 80, (1 << 1) | (1 << 2)); + put_le16(p + 63, 0x07); /* mdma0-2 supported */ + put_le16(p + 65, 120); + put_le16(p + 66, 120); + put_le16(p + 67, 120); + put_le16(p + 68, 120); + put_le16(p + 80, 0xf0); /* ata3 -> ata6 supported */ + put_le16(p + 81, 0x16); /* conforms to ata5 */ put_le16(p + 82, (1 << 14)); put_le16(p + 83, (1 << 14)); put_le16(p + 84, (1 << 14)); put_le16(p + 85, (1 << 14)); put_le16(p + 86, 0); put_le16(p + 87, (1 << 14)); - put_le16(p + 88, 0x1f | (1 << 13)); - put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000); + put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */ + put_le16(p + 93, 1 | (1 << 14) | 0x2000); + + memcpy(s->identify_data, p, sizeof(s->identify_data)); + s->identify_set = 1; } static void ide_atapi_identify(IDEState *s) @@ -463,6 +479,11 @@ static void ide_atapi_identify(IDEState uint16_t *p; char buf[20]; + if (s->identify_set) { + memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); + return; + } + memset(s->io_buffer, 0, 512); p = (uint16_t *)s->io_buffer; /* Removable CDROM, 50us response, 12 byte packets */ @@ -483,11 +504,14 @@ static void ide_atapi_identify(IDEState put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ - + put_le16(p + 71, 30); /* in ns */ put_le16(p + 72, 30); /* in ns */ put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ + + memcpy(s->identify_data, p, sizeof(s->identify_data)); + s->identify_set = 1; } static void ide_set_signature(IDEState *s) @@ -1601,13 +1625,36 @@ static void ide_ioport_write(void *opaqu /* XXX: valid for CDROM ? */ switch(s->feature) { case 0x02: /* write cache enable */ - case 0x03: /* set transfer mode */ case 0x82: /* write cache disable */ case 0xaa: /* read look-ahead enable */ case 0x55: /* read look-ahead disable */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s); break; + case 0x03: { /* set transfer mode */ + uint8_t val = s->nsector & 0x07; + + switch (s->nsector >> 3) { + case 0x00: /* pio default */ + case 0x01: /* pio mode */ + put_le16(s->identify_data + 63,0x07); + put_le16(s->identify_data + 88,0x3f); + break; + case 0x04: /* mdma mode */ + put_le16(s->identify_data + 63,0x07 | (1 << (val + 8))); + put_le16(s->identify_data + 88,0x3f); + break; + case 0x08: /* udma mode */ + put_le16(s->identify_data + 63,0x07); + put_le16(s->identify_data + 88,0x3f | (1 << (val + 8))); + break; + default: + goto abort_cmd; + } + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + } default: goto abort_cmd; } -- 1.0.GIT -- Jens Axboe