All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jens Axboe <qemu@kernel.dk>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 2/3] ide lba48 support
Date: Thu, 2 Feb 2006 10:53:22 +0100	[thread overview]
Message-ID: <20060202095322.GG4215@suse.de> (raw)
In-Reply-To: <43E1377B.5000800@bellard.org>

On Wed, Feb 01 2006, Fabrice Bellard wrote:
> Jens Axboe wrote:
> >Subject: [PATCH] Add lba48 support to ide
> >From: Jens Axboe <axboe@suse.de>
> >Date: 1136376117 +0100
> >
> >Add lba48 support for the ide code. Read back of hob registers isn't
> >there yet, though.
> 
> Do you have a more recent patch ? In your latest patch, the lba48 field 
> is never reset and the nsector may be broken.

The lba48 setting did look a little odd, should be corrected now. I
guess that is what would affect the nsector stuff, it looks correct to
me know.

>From nobody Mon Sep 17 00:00:00 2001
From: Jens Axboe <axboe@suse.de>
Date: Thu Feb 2 10:51:20 2006 +0100
Subject: [PATCH] Add lba48 support to ide

Enables qemu to support ide disk images > 2^28 * 512 bytes.

---

 hw/ide.c |  157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 137 insertions(+), 20 deletions(-)

b67eb122b5646ddcfd13d45563bbe6aa5309e9c0
diff --git a/hw/ide.c b/hw/ide.c
index 50b8e63..01b10e1 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -307,14 +307,24 @@ typedef struct IDEState {
     /* ide regs */
     uint8_t feature;
     uint8_t error;
-    uint16_t nsector; /* 0 is 256 to ease computations */
+    uint32_t nsector;
     uint8_t sector;
     uint8_t lcyl;
     uint8_t hcyl;
+    /* other part of tf for lba48 support */
+    uint8_t hob_feature;
+    uint8_t hob_nsector;
+    uint8_t hob_sector;
+    uint8_t hob_lcyl;
+    uint8_t hob_hcyl;
+
     uint8_t select;
     uint8_t status;
+
     /* 0x3f6 command, only meaningful for drive 0 */
     uint8_t cmd;
+    /* set for lba48 access */
+    uint8_t lba48;
     /* depends on bit 4 in select, only meaningful for drive 0 */
     struct IDEState *cur_drive; 
     BlockDriverState *bs;
@@ -462,13 +472,19 @@ static void ide_identify(IDEState *s)
     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));
+    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
+    put_le16(p + 83, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
     put_le16(p + 84, (1 << 14));
     put_le16(p + 85, (1 << 14));
-    put_le16(p + 86, 0);
+    /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
+    put_le16(p + 86, (1 << 14) | (1 << 13) | (1 <<12) | (1 << 10));
     put_le16(p + 87, (1 << 14));
     put_le16(p + 88, 0x3f | (1 << 13)); /* udma5 set and supported */
     put_le16(p + 93, 1 | (1 << 14) | 0x2000);
+    put_le16(p + 100, s->nb_sectors);
+    put_le16(p + 101, s->nb_sectors >> 16);
+    put_le16(p + 102, s->nb_sectors >> 32);
+    put_le16(p + 103, s->nb_sectors >> 48);
 
     memcpy(s->identify_data, p, sizeof(s->identify_data));
     s->identify_set = 1;
@@ -572,12 +588,19 @@ static int64_t ide_get_sector(IDEState *
     int64_t sector_num;
     if (s->select & 0x40) {
         /* lba */
-        sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | 
-            (s->lcyl << 8) | s->sector;
+	if (!s->lba48) {
+	    sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
+		(s->lcyl << 8) | s->sector;
+	} else {
+	    sector_num = ((int64_t)s->hob_hcyl << 40) |
+		((int64_t) s->hob_lcyl << 32) |
+		((int64_t) s->hob_sector << 24) |
+		((int64_t) s->hcyl << 16) |
+		((int64_t) s->lcyl << 8) | s->sector;
+	}
     } else {
         sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
-            (s->select & 0x0f) * s->sectors + 
-            (s->sector - 1);
+            (s->select & 0x0f) * s->sectors + (s->sector - 1);
     }
     return sector_num;
 }
@@ -586,10 +609,19 @@ static void ide_set_sector(IDEState *s, 
 {
     unsigned int cyl, r;
     if (s->select & 0x40) {
-        s->select = (s->select & 0xf0) | (sector_num >> 24);
-        s->hcyl = (sector_num >> 16);
-        s->lcyl = (sector_num >> 8);
-        s->sector = (sector_num);
+	if (!s->lba48) {
+            s->select = (s->select & 0xf0) | (sector_num >> 24);
+            s->hcyl = (sector_num >> 16);
+            s->lcyl = (sector_num >> 8);
+            s->sector = (sector_num);
+	} else {
+	    s->sector = sector_num;
+	    s->lcyl = sector_num >> 8;
+	    s->hcyl = sector_num >> 16;
+	    s->hob_sector = sector_num >> 24;
+	    s->hob_lcyl = sector_num >> 32;
+	    s->hob_hcyl = sector_num >> 40;
+	}
     } else {
         cyl = sector_num / (s->heads * s->sectors);
         r = sector_num % (s->heads * s->sectors);
@@ -1475,43 +1507,89 @@ static void cdrom_change_cb(void *opaque
     s->nb_sectors = nb_sectors;
 }
 
+static void ide_cmd_lba48_transform(IDEState *s, int lba48)
+{
+    s->lba48 = lba48;
+
+    /* handle the 'magic' 0 nsector count conversion here. to avoid
+     * fiddling with the rest of the read logic, we just store the
+     * full sector count in ->nsector and ignore ->hob_nsector from now
+     */
+    if (!s->lba48) {
+	if (!s->nsector)
+	    s->nsector = 256;
+    } else {
+	if (!s->nsector && !s->hob_nsector)
+	    s->nsector = 65536;
+	else {
+	    int lo = s->nsector;
+	    int hi = s->hob_nsector;
+
+	    s->nsector = (hi << 8) | lo;
+	}
+    }
+}
+
+static void ide_clear_hob(IDEState *ide_if)
+{
+    /* any write clears HOB high bit of device control register */
+    ide_if[0].select &= ~(1 << 7);
+    ide_if[1].select &= ~(1 << 7);
+}
+
 static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     IDEState *ide_if = opaque;
     IDEState *s;
     int unit, n;
+    int lba48 = 0;
 
 #ifdef DEBUG_IDE
     printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
 #endif
+
     addr &= 7;
     switch(addr) {
     case 0:
         break;
     case 1:
+	ide_clear_hob(ide_if);
         /* NOTE: data is written to the two drives */
+	ide_if[0].hob_feature = ide_if[0].feature;
+	ide_if[1].hob_feature = ide_if[1].feature;
         ide_if[0].feature = val;
         ide_if[1].feature = val;
         break;
     case 2:
-        if (val == 0)
-            val = 256;
+	ide_clear_hob(ide_if);
+	ide_if[0].hob_nsector = ide_if[0].nsector;
+	ide_if[1].hob_nsector = ide_if[1].nsector;
         ide_if[0].nsector = val;
         ide_if[1].nsector = val;
         break;
     case 3:
+	ide_clear_hob(ide_if);
+	ide_if[0].hob_sector = ide_if[0].sector;
+	ide_if[1].hob_sector = ide_if[1].sector;
         ide_if[0].sector = val;
         ide_if[1].sector = val;
         break;
     case 4:
+	ide_clear_hob(ide_if);
+	ide_if[0].hob_lcyl = ide_if[0].lcyl;
+	ide_if[1].hob_lcyl = ide_if[1].lcyl;
         ide_if[0].lcyl = val;
         ide_if[1].lcyl = val;
         break;
     case 5:
+	ide_clear_hob(ide_if);
+	ide_if[0].hob_hcyl = ide_if[0].hcyl;
+	ide_if[1].hob_hcyl = ide_if[1].hcyl;
         ide_if[0].hcyl = val;
         ide_if[1].hcyl = val;
         break;
     case 6:
+	/* FIXME: HOB readback uses bit 7 */
         ide_if[0].select = (val & ~0x10) | 0xa0;
         ide_if[1].select = (val | 0x10) | 0xa0;
         /* select drive */
@@ -1529,6 +1607,7 @@ static void ide_ioport_write(void *opaqu
         /* ignore commands to non existant slave */
         if (s != ide_if && !s->bs) 
             break;
+
         switch(val) {
         case WIN_IDENTIFY:
             if (s->bs && !s->is_cdrom) {
@@ -1560,35 +1639,50 @@ static void ide_ioport_write(void *opaqu
             }
             ide_set_irq(s);
             break;
+        case WIN_VERIFY_EXT:
+	    lba48 = 1;
         case WIN_VERIFY:
         case WIN_VERIFY_ONCE:
             /* do sector number check ? */
+	    ide_cmd_lba48_transform(s, lba48);
             s->status = READY_STAT;
             ide_set_irq(s);
             break;
+	case WIN_READ_EXT:
+	    lba48 = 1;
         case WIN_READ:
         case WIN_READ_ONCE:
             if (!s->bs) 
                 goto abort_cmd;
+	    ide_cmd_lba48_transform(s, lba48);
             s->req_nb_sectors = 1;
             ide_sector_read(s);
             break;
+	case WIN_WRITE_EXT:
+	    lba48 = 1;
         case WIN_WRITE:
         case WIN_WRITE_ONCE:
+	    ide_cmd_lba48_transform(s, lba48);
             s->error = 0;
             s->status = SEEK_STAT | READY_STAT;
             s->req_nb_sectors = 1;
             ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
             break;
+	case WIN_MULTREAD_EXT:
+	    lba48 = 1;
         case WIN_MULTREAD:
             if (!s->mult_sectors)
                 goto abort_cmd;
+	    ide_cmd_lba48_transform(s, lba48);
             s->req_nb_sectors = s->mult_sectors;
             ide_sector_read(s);
             break;
+        case WIN_MULTWRITE_EXT:
+	    lba48 = 1;
         case WIN_MULTWRITE:
             if (!s->mult_sectors)
                 goto abort_cmd;
+	    ide_cmd_lba48_transform(s, lba48);
             s->error = 0;
             s->status = SEEK_STAT | READY_STAT;
             s->req_nb_sectors = s->mult_sectors;
@@ -1597,19 +1691,28 @@ static void ide_ioport_write(void *opaqu
                 n = s->req_nb_sectors;
             ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
             break;
+	case WIN_READDMA_EXT:
+	    lba48 = 1;
         case WIN_READDMA:
         case WIN_READDMA_ONCE:
             if (!s->bs) 
                 goto abort_cmd;
+	    ide_cmd_lba48_transform(s, lba48);
             ide_sector_read_dma(s);
             break;
+	case WIN_WRITEDMA_EXT:
+	    lba48 = 1;
         case WIN_WRITEDMA:
         case WIN_WRITEDMA_ONCE:
             if (!s->bs) 
                 goto abort_cmd;
+	    ide_cmd_lba48_transform(s, lba48);
             ide_sector_write_dma(s);
             break;
+        case WIN_READ_NATIVE_MAX_EXT:
+	    lba48 = 1;
         case WIN_READ_NATIVE_MAX:
+	    ide_cmd_lba48_transform(s, lba48);
             ide_set_sector(s, s->nb_sectors - 1);
             s->status = READY_STAT;
             ide_set_irq(s);
@@ -1659,9 +1762,10 @@ static void ide_ioport_write(void *opaqu
                 goto abort_cmd;
             }
             break;
+        case WIN_FLUSH_CACHE:
+        case WIN_FLUSH_CACHE_EXT:
 	case WIN_STANDBYNOW1:
         case WIN_IDLEIMMEDIATE:
-        case WIN_FLUSH_CACHE:
 	    s->status = READY_STAT;
             ide_set_irq(s);
             break;
@@ -1713,9 +1817,12 @@ static uint32_t ide_ioport_read(void *op
     IDEState *ide_if = opaque;
     IDEState *s = ide_if->cur_drive;
     uint32_t addr;
-    int ret;
+    int ret, hob;
 
     addr = addr1 & 7;
+    /* FIXME: HOB readback uses bit 7, but it's always set right now */
+    //hob = s->select & (1 << 7);
+    hob = 0;
     switch(addr) {
     case 0:
         ret = 0xff;
@@ -1723,32 +1830,42 @@ static uint32_t ide_ioport_read(void *op
     case 1:
         if (!ide_if[0].bs && !ide_if[1].bs)
             ret = 0;
-        else
+        else if (!hob)
             ret = s->error;
+	else
+	    ret = s->hob_feature;
         break;
     case 2:
         if (!ide_if[0].bs && !ide_if[1].bs)
             ret = 0;
-        else
+        else if (!hob)
             ret = s->nsector & 0xff;
+	else
+	    ret = s->hob_nsector;
         break;
     case 3:
         if (!ide_if[0].bs && !ide_if[1].bs)
             ret = 0;
-        else
+        else if (!hob)
             ret = s->sector;
+	else
+	    ret = s->hob_sector;
         break;
     case 4:
         if (!ide_if[0].bs && !ide_if[1].bs)
             ret = 0;
-        else
+        else if (!hob)
             ret = s->lcyl;
+	else
+	    ret = s->hob_lcyl;
         break;
     case 5:
         if (!ide_if[0].bs && !ide_if[1].bs)
             ret = 0;
-        else
+        else if (!hob)
             ret = s->hcyl;
+	else
+	    ret = s->hob_hcyl;
         break;
     case 6:
         if (!ide_if[0].bs && !ide_if[1].bs)
-- 
1.1.6.g8233


-- 
Jens Axboe

  reply	other threads:[~2006-02-02 14:49 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-04 12:12 [Qemu-devel] [PATCH 0/3] qemu ide updates Jens Axboe
2006-01-04 12:12 ` [Qemu-devel] [PATCH 1/3] ide id updates Jens Axboe
2006-01-04 12:13 ` [Qemu-devel] [PATCH 2/3] ide lba48 support Jens Axboe
2006-02-01 22:34   ` Fabrice Bellard
2006-02-02  9:53     ` Jens Axboe [this message]
2006-01-04 12:16 ` [Qemu-devel] [PATCH 3/3] proper support of FLUSH_CACHE and FLUSH_CACHE_EXT Jens Axboe
2006-01-04 21:07   ` Johannes Schindelin
2006-01-05  8:14     ` Jens Axboe
2006-01-05  9:18       ` Jens Axboe
2006-01-05 13:25         ` Johannes Schindelin
2006-01-05 18:07           ` Jens Axboe
2006-01-05 13:11       ` Johannes Schindelin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060202095322.GG4215@suse.de \
    --to=qemu@kernel.dk \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.