]> git.proxmox.com Git - mirror_qemu.git/commitdiff
cdrom_read_toc support (Blue Swirl)
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 5 Dec 2005 20:30:36 +0000 (20:30 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 5 Dec 2005 20:30:36 +0000 (20:30 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1693 c046a42c-6fe2-441c-8c8c-71466251a162

hw/esp.c

index 169531ff17adf2deab00e98d2597b41dfda55fbd..9603b74b1eca095b3eb4a07be424f1411843cb04 100644 (file)
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -75,6 +75,148 @@ typedef struct ESPState {
 #define SEQ_0 0x0
 #define SEQ_CD 0x4
 
+/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */
+static void lba_to_msf(uint8_t *buf, int lba)
+{
+    lba += 150;
+    buf[0] = (lba / 75) / 60;
+    buf[1] = (lba / 75) % 60;
+    buf[2] = lba % 75;
+}
+
+static inline void cpu_to_ube16(uint8_t *buf, int val)
+{
+    buf[0] = val >> 8;
+    buf[1] = val;
+}
+
+static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
+{
+    buf[0] = val >> 24;
+    buf[1] = val >> 16;
+    buf[2] = val >> 8;
+    buf[3] = val;
+}
+
+/* same toc as bochs. Return -1 if error or the toc length */
+/* XXX: check this */
+static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
+{
+    uint8_t *q;
+    int len;
+    
+    if (start_track > 1 && start_track != 0xaa)
+        return -1;
+    q = buf + 2;
+    *q++ = 1; /* first session */
+    *q++ = 1; /* last session */
+    if (start_track <= 1) {
+        *q++ = 0; /* reserved */
+        *q++ = 0x14; /* ADR, control */
+        *q++ = 1;    /* track number */
+        *q++ = 0; /* reserved */
+        if (msf) {
+            *q++ = 0; /* reserved */
+            lba_to_msf(q, 0);
+            q += 3;
+        } else {
+            /* sector 0 */
+            cpu_to_ube32(q, 0);
+            q += 4;
+        }
+    }
+    /* lead out track */
+    *q++ = 0; /* reserved */
+    *q++ = 0x16; /* ADR, control */
+    *q++ = 0xaa; /* track number */
+    *q++ = 0; /* reserved */
+    if (msf) {
+        *q++ = 0; /* reserved */
+        lba_to_msf(q, nb_sectors);
+        q += 3;
+    } else {
+        cpu_to_ube32(q, nb_sectors);
+        q += 4;
+    }
+    len = q - buf;
+    cpu_to_ube16(buf, len - 2);
+    return len;
+}
+
+/* mostly same info as PearPc */
+static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, 
+                              int session_num)
+{
+    uint8_t *q;
+    int len;
+    
+    q = buf + 2;
+    *q++ = 1; /* first session */
+    *q++ = 1; /* last session */
+
+    *q++ = 1; /* session number */
+    *q++ = 0x14; /* data track */
+    *q++ = 0; /* track number */
+    *q++ = 0xa0; /* lead-in */
+    *q++ = 0; /* min */
+    *q++ = 0; /* sec */
+    *q++ = 0; /* frame */
+    *q++ = 0;
+    *q++ = 1; /* first track */
+    *q++ = 0x00; /* disk type */
+    *q++ = 0x00;
+    
+    *q++ = 1; /* session number */
+    *q++ = 0x14; /* data track */
+    *q++ = 0; /* track number */
+    *q++ = 0xa1;
+    *q++ = 0; /* min */
+    *q++ = 0; /* sec */
+    *q++ = 0; /* frame */
+    *q++ = 0;
+    *q++ = 1; /* last track */
+    *q++ = 0x00;
+    *q++ = 0x00;
+    
+    *q++ = 1; /* session number */
+    *q++ = 0x14; /* data track */
+    *q++ = 0; /* track number */
+    *q++ = 0xa2; /* lead-out */
+    *q++ = 0; /* min */
+    *q++ = 0; /* sec */
+    *q++ = 0; /* frame */
+    if (msf) {
+        *q++ = 0; /* reserved */
+        lba_to_msf(q, nb_sectors);
+        q += 3;
+    } else {
+        cpu_to_ube32(q, nb_sectors);
+        q += 4;
+    }
+
+    *q++ = 1; /* session number */
+    *q++ = 0x14; /* ADR, control */
+    *q++ = 0;    /* track number */
+    *q++ = 1;    /* point */
+    *q++ = 0; /* min */
+    *q++ = 0; /* sec */
+    *q++ = 0; /* frame */
+    if (msf) {
+        *q++ = 0; 
+        lba_to_msf(q, 0);
+        q += 3;
+    } else {
+        *q++ = 0; 
+        *q++ = 0; 
+        *q++ = 0; 
+        *q++ = 0; 
+    }
+
+    len = q - buf;
+    cpu_to_ube16(buf, len - 2);
+    return len;
+}
+
 static void handle_satn(ESPState *s)
 {
     uint8_t buf[32];
@@ -128,6 +270,7 @@ static void handle_satn(ESPState *s)
        memcpy(&s->ti_buf[8], "QEMU   ", 8);
        s->ti_buf[2] = 1;
        s->ti_buf[3] = 2;
+       s->ti_buf[4] = 32;
        s->ti_dir = 1;
        s->ti_size = 36;
        break;
@@ -190,6 +333,45 @@ static void handle_satn(ESPState *s)
            s->ti_dir = 0;
            break;
        }
+    case 0x43:
+        {
+            int start_track, format, msf, len;
+
+            msf = buf[2] & 2;
+            format = buf[3] & 0xf;
+            start_track = buf[7];
+            bdrv_get_geometry(s->bd[target], &nb_sectors);
+            DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
+            switch(format) {
+            case 0:
+                len = cdrom_read_toc(nb_sectors, buf, msf, start_track);
+                if (len < 0)
+                    goto error_cmd;
+                s->ti_size = len;
+                break;
+            case 1:
+                /* multi session : only a single session defined */
+                memset(buf, 0, 12);
+                buf[1] = 0x0a;
+                buf[2] = 0x01;
+                buf[3] = 0x01;
+                s->ti_size = 12;
+                break;
+            case 2:
+                len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);
+                if (len < 0)
+                    goto error_cmd;
+                s->ti_size = len;
+                break;
+            default:
+            error_cmd:
+                DPRINTF("Read TOC error\n");
+                // XXX error handling
+                break;
+            }
+           s->ti_dir = 1;
+            break;
+        }
     default:
        DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
        break;