Index: trunk/src/VBox/Devices/Storage/ATAController.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/ATAController.cpp	(revision 37262)
+++ trunk/src/VBox/Devices/Storage/ATAController.cpp	(revision 37264)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -685,21 +685,7 @@
 {
     uint16_t *p;
-    char aSerial[20];
-    int rc;
-    RTUUID Uuid;
 
     Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
     Assert(s->cbElementaryTransfer == 512);
-    rc = s->pDrvBlock ? s->pDrvBlock->pfnGetUuid(s->pDrvBlock, &Uuid) : RTUuidClear(&Uuid);
-    if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
-    {
-        PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
-        /* Generate a predictable serial for drives which don't have a UUID. */
-        RTStrPrintf(aSerial, sizeof(aSerial), "VB%x-%04x%04x",
-                    s->iLUN + ATADEVSTATE_2_DEVINS(s)->iInstance * 32,
-                    pCtl->IOPortBase1, pCtl->IOPortBase2);
-    }
-    else
-        RTStrPrintf(aSerial, sizeof(aSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
 
     p = (uint16_t *)s->CTXALLSUFF(pbIOBuffer);
@@ -711,10 +697,10 @@
     p[5] = RT_H2LE_U16(512);
     p[6] = RT_H2LE_U16(s->PCHSGeometry.cSectors);
-    ataPadString((uint8_t *)(p + 10), aSerial, 20); /* serial number */
+    ataPadString((uint8_t *)(p + 10), s->pszSerialNumber, ATA_SERIAL_NUMBER_LENGTH); /* serial number */
     p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
     p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
     p[22] = RT_H2LE_U16(0); /* ECC bytes per sector */
-    ataPadString((uint8_t *)(p + 23), "1.0", 8); /* firmware version */
-    ataPadString((uint8_t *)(p + 27), "VBOX HARDDISK", 40); /* model */
+    ataPadString((uint8_t *)(p + 23), s->pszFirmwareRevision, ATA_FIRMWARE_REVISION_LENGTH); /* firmware version */
+    ataPadString((uint8_t *)(p + 27), s->pszModelNumber, ATA_MODEL_NUMBER_LENGTH); /* model */
 #if ATA_MAX_MULT_SECTORS > 1
     p[47] = RT_H2LE_U16(0x8000 | ATA_MAX_MULT_SECTORS);
@@ -777,4 +763,6 @@
         p[103] = RT_H2LE_U16(s->cTotalSectors >> 48);
     }
+    if (s->fNonRotational)
+        p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
     uint32_t uCsum = ataChecksum(p, 510);
     p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
@@ -812,21 +800,7 @@
 {
     uint16_t *p;
-    char aSerial[20];
-    RTUUID Uuid;
-    int rc;
 
     Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
     Assert(s->cbElementaryTransfer == 512);
-    rc = s->pDrvBlock ? s->pDrvBlock->pfnGetUuid(s->pDrvBlock, &Uuid) : RTUuidClear(&Uuid);
-    if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
-    {
-        PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
-        /* Generate a predictable serial for drives which don't have a UUID. */
-        RTStrPrintf(aSerial, sizeof(aSerial), "VB%x-%04x%04x",
-                    s->iLUN + ATADEVSTATE_2_DEVINS(s)->iInstance * 32,
-                    pCtl->IOPortBase1, pCtl->IOPortBase2);
-    }
-    else
-        RTStrPrintf(aSerial, sizeof(aSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
 
     p = (uint16_t *)s->CTXALLSUFF(pbIOBuffer);
@@ -834,9 +808,9 @@
     /* Removable CDROM, 50us response, 12 byte packets */
     p[0] = RT_H2LE_U16(2 << 14 | 5 << 8 | 1 << 7 | 2 << 5 | 0 << 0);
-    ataPadString((uint8_t *)(p + 10), aSerial, 20); /* serial number */
+    ataPadString((uint8_t *)(p + 10), s->pszSerialNumber, ATA_SERIAL_NUMBER_LENGTH); /* serial number */
     p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
     p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
-    ataPadString((uint8_t *)(p + 23), "1.0", 8); /* firmware version */
-    ataPadString((uint8_t *)(p + 27), "VBOX CD-ROM", 40); /* model */
+    ataPadString((uint8_t *)(p + 23), s->pszFirmwareRevision, ATA_FIRMWARE_REVISION_LENGTH); /* firmware version */
+    ataPadString((uint8_t *)(p + 27), s->pszModelNumber, ATA_MODEL_NUMBER_LENGTH); /* model */
     p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
     p[50] = RT_H2LE_U16(1 << 14);  /* No drive specific standby timer minimum */
@@ -1910,7 +1884,7 @@
     pbBuf[6] = 0; /* reserved */
     pbBuf[7] = 0; /* reserved */
-    ataSCSIPadStr(pbBuf + 8, "VBOX", 8);
-    ataSCSIPadStr(pbBuf + 16, "CD-ROM", 16);
-    ataSCSIPadStr(pbBuf + 32, "1.0", 4);
+    ataSCSIPadStr(pbBuf + 8, s->pszInquiryVendorId, 8);
+    ataSCSIPadStr(pbBuf + 16, s->pszInquiryProductId, 16);
+    ataSCSIPadStr(pbBuf + 32, s->pszInquiryRevision, 4);
     s->iSourceSink = ATAFN_SS_NULL;
     atapiCmdOK(s);
@@ -5595,6 +5569,14 @@
                       unsigned iLUNMaster, PPDMIBASE pDrvBaseMaster, PPDMLED pLedMaster,
                       PSTAMCOUNTER pStatBytesReadMaster, PSTAMCOUNTER pStatBytesWrittenMaster,
+                      const char *pszSerialNumberMaster, const char *pszFirmwareRevisionMaster,
+                      const char *pszModelNumberMaster, const char *pszInquiryVendorIdMaster,
+                      const char *pszInquiryProductIdMaster, const char *pszInquiryRevisionMaster,
+                      bool fNonRotationalMaster,
                       unsigned iLUNSlave, PPDMIBASE pDrvBaseSlave, PPDMLED pLedSlave,
                       PSTAMCOUNTER pStatBytesReadSlave, PSTAMCOUNTER pStatBytesWrittenSlave,
+                      const char *pszSerialNumberSlave, const char *pszFirmwareRevisionSlave,
+                      const char *pszModelNumberSlave, const char *pszInquiryVendorIdSlave,
+                      const char *pszInquiryProductIdSlave, const char *pszInquiryRevisionSlave,
+                      bool fNonRotationalSlave,
                       uint32_t *pcbSSMState, const char *szName)
 {
@@ -5613,14 +5595,21 @@
     for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
     {
-        pCtl->aIfs[j].iLUN              = j == 0 ? iLUNMaster : iLUNSlave;
-        pCtl->aIfs[j].pDevInsR3         = pDevIns;
-        pCtl->aIfs[j].pDevInsR0         = PDMDEVINS_2_R0PTR(pDevIns);
-        pCtl->aIfs[j].pDevInsRC         = PDMDEVINS_2_RCPTR(pDevIns);
-        pCtl->aIfs[j].pControllerR3     = pCtl;
-        pCtl->aIfs[j].pControllerR0     = MMHyperR3ToR0(PDMDevHlpGetVM(pDevIns), pCtl);
-        pCtl->aIfs[j].pControllerRC     = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), pCtl);
-        pCtl->aIfs[j].pLed              = j == 0 ? pLedMaster : pLedSlave;
-        pCtl->aIfs[j].pStatBytesRead    = j == 0 ? pStatBytesReadMaster : pStatBytesReadSlave;
-        pCtl->aIfs[j].pStatBytesWritten = j == 0 ? pStatBytesWrittenMaster : pStatBytesWrittenSlave;
+        pCtl->aIfs[j].iLUN                  = j == 0 ? iLUNMaster : iLUNSlave;
+        pCtl->aIfs[j].pDevInsR3             = pDevIns;
+        pCtl->aIfs[j].pDevInsR0             = PDMDEVINS_2_R0PTR(pDevIns);
+        pCtl->aIfs[j].pDevInsRC             = PDMDEVINS_2_RCPTR(pDevIns);
+        pCtl->aIfs[j].pControllerR3         = pCtl;
+        pCtl->aIfs[j].pControllerR0         = MMHyperR3ToR0(PDMDevHlpGetVM(pDevIns), pCtl);
+        pCtl->aIfs[j].pControllerRC         = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), pCtl);
+        pCtl->aIfs[j].pLed                  = j == 0 ? pLedMaster : pLedSlave;
+        pCtl->aIfs[j].pStatBytesRead        = j == 0 ? pStatBytesReadMaster : pStatBytesReadSlave;
+        pCtl->aIfs[j].pStatBytesWritten     = j == 0 ? pStatBytesWrittenMaster : pStatBytesWrittenSlave;
+        pCtl->aIfs[j].pszSerialNumber       = j == 0 ? pszSerialNumberMaster : pszSerialNumberSlave;
+        pCtl->aIfs[j].pszFirmwareRevision   = j == 0 ? pszFirmwareRevisionMaster : pszFirmwareRevisionSlave;
+        pCtl->aIfs[j].pszModelNumber        = j == 0 ? pszModelNumberMaster : pszModelNumberSlave;
+        pCtl->aIfs[j].pszInquiryVendorId    = j == 0 ? pszInquiryVendorIdMaster : pszInquiryVendorIdSlave;
+        pCtl->aIfs[j].pszInquiryProductId   = j == 0 ? pszInquiryProductIdMaster : pszInquiryProductIdSlave;
+        pCtl->aIfs[j].pszInquiryRevision    = j == 0 ? pszInquiryRevisionMaster : pszInquiryRevisionSlave;
+        pCtl->aIfs[j].fNonRotational        = j == 0 ? fNonRotationalMaster : fNonRotationalSlave;
     }
 
Index: trunk/src/VBox/Devices/Storage/ATAController.h
===================================================================
--- trunk/src/VBox/Devices/Storage/ATAController.h	(revision 37262)
+++ trunk/src/VBox/Devices/Storage/ATAController.h	(revision 37264)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2008 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -213,4 +213,18 @@
     STAMPROFILE     StatFlushes;
 
+    /** The serial number to use for IDENTIFY DEVICE commands. */
+    R3PTRTYPE(const char *) pszSerialNumber;
+    /** The firmware revision to use for IDENTIFY DEVICE commands. */
+    R3PTRTYPE(const char *) pszFirmwareRevision;
+    /** The model number to use for IDENTIFY DEVICE commands. */
+    R3PTRTYPE(const char *) pszModelNumber;
+    /** The vendor identification string for SCSI INQUIRY commands. */
+    R3PTRTYPE(const char *) pszInquiryVendorId;
+    /** The product identification string for SCSI INQUIRY commands. */
+    R3PTRTYPE(const char *) pszInquiryProductId;
+    /** The revision string for SCSI INQUIRY commands. */
+    R3PTRTYPE(const char *) pszInquiryRevision;
+    /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */
+    bool            fNonRotational;
     /** Enable passing through commands directly to the ATAPI drive. */
     bool            fATAPIPassthrough;
@@ -415,6 +429,28 @@
  * @param   pDevIns Pointer to the device instance which creates a controller.
  * @param   pCtl    Pointer to the unitialized ATA controller structure.
+ * @param   iLUNMaster     Port number of the master device.
  * @param   pDrvBaseMaster Pointer to the base driver interface which acts as the master.
+ * @param   pLedMaster     Pointer to LED state for master device.
+ * @param   pStatBytesReadMaster    Pointer to statistics structure for reads.
+ * @param   pStatBytesWrittenMaster Pointer to statistics structure for writes.
+ * @param   pszSerialNumberMaster       VPD serial number for master.
+ * @param   pszFirmwareRevisionMaster   VPD firmware revision for master
+ * @param   pszModelNumberMaster        VPD model number for master
+ * @param   pszInquiryVendorIdMaster    VPD vendor ID for master
+ * @param   pszInquiryProductIdMaster   VPD product ID for master
+ * @param   pszInquiryRevisionMaster    VPD revision for master
+ * @param   fNonRotationalMaster    Flag for non-rotational media.
+ * @param   iLUNSlave      Port number of the slave device.
  * @param   pDrvBaseSlave  Pointer to the base driver interface which acts as the slave.
+ * @param   pLedSlave      Pointer to LED state for slave device.
+ * @param   pStatBytesReadSlave     Pointer to statistics structure for reads.
+ * @param   pStatBytesWrittenSlave  Pointer to statistics structure for writes.
+ * @param   pszSerialNumberSlave        VPD serial number for slave.
+ * @param   pszFirmwareRevisionSlave    VPD firmware revision for slave
+ * @param   pszModelNumberSlave         VPD model number for slave
+ * @param   pszInquiryVendorIdSlave     VPD vendor ID for slave
+ * @param   pszInquiryProductIdSlave    VPD product ID for slave
+ * @param   pszInquiryRevisionSlave     VPD revision for slave
+ * @param   fNonRotationalSlave     Flag for non-rotational media.
  * @param   pcbSSMState    Where to store the size of the device state for loading/saving.
  * @param   szName         Name of the controller (Used to initialize the critical section).
@@ -423,6 +459,14 @@
                       unsigned iLUNMaster, PPDMIBASE pDrvBaseMaster, PPDMLED pLedMaster,
                       PSTAMCOUNTER pStatBytesReadMaster, PSTAMCOUNTER pStatBytesWrittenMaster,
+                      const char *pszSerialNumberMaster, const char *pszFirmwareRevisionMaster,
+                      const char *pszModelNumberMaster, const char *pszInquiryVendorIdMaster,
+                      const char *pszInquiryProductIdMaster, const char *pszInquiryRevisionMaster,
+                      bool fNonRotationalMaster,
                       unsigned iLUNSlave, PPDMIBASE pDrvBaseSlave, PPDMLED pLedSlave,
                       PSTAMCOUNTER pStatBytesReadSlave, PSTAMCOUNTER pStatBytesWrittenSlave,
+                      const char *pszSerialNumberSlave, const char *pszFirmwareRevisionSlave,
+                      const char *pszModelNumberSlave, const char *pszInquiryVendorIdSlave,
+                      const char *pszInquiryProductIdSlave, const char *pszInquiryRevisionSlave,
+                      bool fNonRotationalSlave,
                       uint32_t *pcbSSMState, const char *szName);
 
Index: trunk/src/VBox/Devices/Storage/DevAHCI.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DevAHCI.cpp	(revision 37262)
+++ trunk/src/VBox/Devices/Storage/DevAHCI.cpp	(revision 37264)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -412,4 +412,6 @@
     /** First D2H FIS was send. */
     bool                            fFirstD2HFisSend;
+    /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */
+    bool                            fNonRotational;
     /** Attached device is a CD/DVD drive. */
     bool                            fATAPI;
@@ -3072,4 +3074,6 @@
     p[102] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 32);
     p[103] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 48);
+    if (pAhciPort->fNonRotational)
+        p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
 
     /* The following are SATA specific */
@@ -7079,5 +7083,5 @@
 
 /**
- * LsiLogic status info callback.
+ * AHCI status info callback.
  *
  * @param   pDevIns     The device instance.
@@ -8489,4 +8493,9 @@
             }
 
+            rc = CFGMR3QueryBoolDef(pCfgNode, "NonRotationalMedium", &pAhciPort->fNonRotational, false);
+            if (RT_FAILURE(rc))
+                return PDMDEV_SET_ERROR(pDevIns, rc,
+                            N_("PIIX3 configuration error: failed to read \"NonRotationalMedium\" as boolean"));
+
             /* There are three other identification strings for CD drives used for INQUIRY */
             if (pAhciPort->fATAPI)
@@ -8623,8 +8632,22 @@
                                    &pThis->ahciPort[iPortMaster].StatBytesRead,
                                    &pThis->ahciPort[iPortMaster].StatBytesWritten,
+                                   pThis->ahciPort[iPortMaster].szSerialNumber,
+                                   pThis->ahciPort[iPortMaster].szFirmwareRevision,
+                                   pThis->ahciPort[iPortMaster].szModelNumber,
+                                   pThis->ahciPort[iPortMaster].szInquiryVendorId,
+                                   pThis->ahciPort[iPortMaster].szInquiryProductId,
+                                   pThis->ahciPort[iPortMaster].szInquiryRevision,
+                                   pThis->ahciPort[iPortMaster].fNonRotational,
                                    iPortSlave, pThis->ahciPort[iPortSlave].pDrvBase,
                                    &pThis->ahciPort[iPortSlave].Led,
                                    &pThis->ahciPort[iPortSlave].StatBytesRead,
                                    &pThis->ahciPort[iPortSlave].StatBytesWritten,
+                                   pThis->ahciPort[iPortSlave].szSerialNumber,
+                                   pThis->ahciPort[iPortSlave].szFirmwareRevision,
+                                   pThis->ahciPort[iPortSlave].szModelNumber,
+                                   pThis->ahciPort[iPortSlave].szInquiryVendorId,
+                                   pThis->ahciPort[iPortSlave].szInquiryProductId,
+                                   pThis->ahciPort[iPortSlave].szInquiryRevision,
+                                   pThis->ahciPort[iPortSlave].fNonRotational,
                                    &cbSSMState, szName);
             if (RT_FAILURE(rc))
Index: trunk/src/VBox/Devices/Storage/DevATA.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 37262)
+++ trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 37264)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -103,14 +103,4 @@
 #define ATA_MEDIA_TYPE_DATA                     1    /**< Data CD */
 #define ATA_MEDIA_TYPE_CDDA                     2    /**< CD-DA  (audio) CD type */
-
-/**
- * Length of the configurable VPD data (without termination)
- */
-#define ATA_SERIAL_NUMBER_LENGTH        20
-#define ATA_FIRMWARE_REVISION_LENGTH     8
-#define ATA_MODEL_NUMBER_LENGTH         40
-#define ATAPI_INQUIRY_VENDOR_ID_LENGTH   8
-#define ATAPI_INQUIRY_PRODUCT_ID_LENGTH 16
-#define ATAPI_INQUIRY_REVISION_LENGTH    4
 
 /*******************************************************************************
@@ -257,4 +247,6 @@
     STAMPROFILE     StatFlushes;
 
+    /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */
+    bool            fNonRotational;
     /** Enable passing through commands directly to the ATAPI drive. */
     bool            fATAPIPassthrough;
@@ -1246,4 +1238,6 @@
         p[103] = RT_H2LE_U16(s->cTotalSectors >> 48);
     }
+    if (s->fNonRotational)
+        p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
     uint32_t uCsum = ataChecksum(p, 510);
     p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
@@ -7162,4 +7156,9 @@
                     }
 
+                    rc = CFGMR3QueryBoolDef(pCfgNode, "NonRotationalMedium", &pIf->fNonRotational, false);
+                    if (RT_FAILURE(rc))
+                        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                    N_("PIIX3 configuration error: failed to read \"NonRotationalMedium\" as boolean"));
+
                     /* There are three other identification strings for CD drives used for INQUIRY */
                     if (pIf->fATAPI)
Index: trunk/src/VBox/Devices/Storage/ide.h
===================================================================
--- trunk/src/VBox/Devices/Storage/ide.h	(revision 37262)
+++ trunk/src/VBox/Devices/Storage/ide.h	(revision 37264)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -168,4 +168,11 @@
      |  ((((thismode ^ currmode) & 0xf8) == 0) ? 1 << ((currmode & 0x07) + 8) : 0))
 
+/**
+ * Length of the ATA VPD data (without termination)
+ */
+#define ATA_SERIAL_NUMBER_LENGTH        20
+#define ATA_FIRMWARE_REVISION_LENGTH     8
+#define ATA_MODEL_NUMBER_LENGTH         40
+
 
 /* ATAPI defines */
@@ -179,4 +186,15 @@
 #define ATAPI_INT_REASON_TAG_MASK       0xf8
 
+
+/**
+ * Length of the ATAPI VPD data (without termination)
+ *
+ * @todo move to scsi.h
+ */
+#define ATAPI_INQUIRY_VENDOR_ID_LENGTH   8
+#define ATAPI_INQUIRY_PRODUCT_ID_LENGTH 16
+#define ATAPI_INQUIRY_REVISION_LENGTH    4
+
+
 #if defined(DEBUG) && defined(IN_RING3)
 const char * ATACmdText(uint8_t uCmd);
