Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 7442)
@@ -1060,5 +1060,5 @@
     ComPtr<IHardDisk> hardDisk;
     Bstr filePath;
-    rc = machine->GetHardDisk(DiskControllerType_IDE0, 0, hardDisk.asOutParam());
+    rc = machine->GetHardDisk(StorageBus_IDE, 0, 0, hardDisk.asOutParam());
     if (SUCCEEDED(rc) && hardDisk)
     {
@@ -1083,5 +1083,5 @@
             RTPrintf("hda=\"none\"\n");
     }
-    rc = machine->GetHardDisk(DiskControllerType_IDE0, 1, hardDisk.asOutParam());
+    rc = machine->GetHardDisk(StorageBus_IDE, 0, 1, hardDisk.asOutParam());
     if (SUCCEEDED(rc) && hardDisk)
     {
@@ -1106,5 +1106,5 @@
             RTPrintf("hdb=\"none\"\n");
     }
-    rc = machine->GetHardDisk(DiskControllerType_IDE1, 1, hardDisk.asOutParam());
+    rc = machine->GetHardDisk(StorageBus_IDE, 1, 1, hardDisk.asOutParam());
     if (SUCCEEDED(rc) && hardDisk)
     {
@@ -4510,5 +4510,5 @@
             if (strcmp(hdds[0], "none") == 0)
             {
-                machine->DetachHardDisk(DiskControllerType_IDE0, 0);
+                machine->DetachHardDisk(StorageBus_IDE, 0, 0);
             }
             else
@@ -4543,5 +4543,5 @@
                 {
                     hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                    CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0, 0));
+                    CHECK_ERROR(machine, AttachHardDisk(uuid, StorageBus_IDE, 0, 0));
                 }
                 else
@@ -4555,5 +4555,5 @@
             if (strcmp(hdds[1], "none") == 0)
             {
-                machine->DetachHardDisk(DiskControllerType_IDE0, 1);
+                machine->DetachHardDisk(StorageBus_IDE, 0, 1);
             }
             else
@@ -4588,5 +4588,5 @@
                 {
                     hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                    CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0, 1));
+                    CHECK_ERROR(machine, AttachHardDisk(uuid, StorageBus_IDE, 0, 1));
                 }
                 else
@@ -4600,5 +4600,5 @@
             if (strcmp(hdds[2], "none") == 0)
             {
-                machine->DetachHardDisk(DiskControllerType_IDE1, 1);
+                machine->DetachHardDisk(StorageBus_IDE, 1, 1);
             }
             else
@@ -4633,5 +4633,5 @@
                 {
                     hardDisk->COMGETTER(Id)(uuid.asOutParam());
-                    CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE1, 1));
+                    CHECK_ERROR(machine, AttachHardDisk(uuid, StorageBus_IDE, 1, 1));
                 }
                 else
Index: trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 7442)
@@ -1616,6 +1616,6 @@
             Guid uuid;
             hardDisk->COMGETTER(Id)(uuid.asOutParam());
-            gMachine->DetachHardDisk(DiskControllerType_IDE0, 0);
-            gMachine->AttachHardDisk(uuid, DiskControllerType_IDE0, 0);
+            gMachine->DetachHardDisk(StorageBus_IDE, 0, 0);
+            gMachine->AttachHardDisk(uuid, StorageBus_IDE, 0, 0);
             /// @todo why is this attachment saved?
         }
Index: trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(revision 7442)
@@ -215,9 +215,12 @@
     }
 
-    QString toString (KDiskControllerType t) const
-    {
-        AssertMsg (!diskControllerTypes [t].isNull(), ("No text for %d", t));
-        return diskControllerTypes [t];
-    }
+    QString toString (KStorageBus t) const
+    {
+        AssertMsg (!storageBuses [t].isNull(), ("No text for %d", t));
+        return storageBuses [t];
+    }
+
+    QString toString (KStorageBus t, LONG c) const;
+    QString toString (KStorageBus t, LONG c, LONG d) const;
 
     QString toString (KHardDiskType t) const
@@ -316,6 +319,4 @@
         return toString (aHD.GetType());
     }
-
-    QString toString (KDiskControllerType t, LONG d) const;
 
     QString toString (KDeviceType t) const
@@ -631,5 +632,7 @@
     QStringVector sessionStates;
     QStringVector deviceTypes;
-    QStringVector diskControllerTypes;
+    QStringVector storageBuses;
+    QStringVector storageBusDevices;
+    QStringVector storageBusChannels;
     QStringVector diskTypes;
     QStringVector diskStorageTypes;
@@ -637,5 +640,4 @@
     QStringVector portModeTypes;
     QStringVector usbFilterActionTypes;
-    QStringVector diskControllerDevices;
     QStringVector audioDriverTypes;
     QStringVector audioControllerTypes;
Index: trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/include/VBoxProblemReporter.h	(revision 7442)
@@ -196,7 +196,7 @@
         const CVirtualDiskImage &vdi, const CProgress &progress);
     void cannotAttachHardDisk (QWidget *parent, const CMachine &m, const QUuid &id,
-                               KDiskControllerType ctl, LONG dev);
+                               KStorageBus bus, LONG channel, LONG dev);
     void cannotDetachHardDisk (QWidget *parent, const CMachine &m,
-                               KDiskControllerType ctl, LONG dev);
+                               KStorageBus bus, LONG channel, LONG dev);
     void cannotRegisterMedia (QWidget *parent, const CVirtualBox &vbox,
                               VBoxDefs::DiskType type, const QString &src);
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleWnd.cpp	(revision 7442)
@@ -1744,7 +1744,7 @@
             CHardDisk hd = hda.GetHardDisk();
             data += QString ("<br><nobr><b>%1 %2</b>: %3</nobr>")
-                .arg (vboxGlobal().toString (hda.GetController()))
-                .arg (vboxGlobal().toString (hda.GetController(),
-                                hda.GetDeviceNumber()))
+                .arg (vboxGlobal().toString (hda.GetBus(), hda.GetChannel()))
+                .arg (vboxGlobal().toString (hda.GetBus(), hda.GetChannel(),
+                                             hda.GetDevice()))
                 .arg (QDir::convertSeparators (hd.GetLocation()));
             hasDisks = true;
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(revision 7442)
@@ -741,5 +741,7 @@
     , sessionStates (KSessionState_COUNT)
     , deviceTypes (KDeviceType_COUNT)
-    , diskControllerTypes (KDiskControllerType_COUNT)
+    , storageBuses (KStorageBus_COUNT)
+    , storageBusDevices (3)
+    , storageBusChannels (3)
     , diskTypes (KHardDiskType_COUNT)
     , diskStorageTypes (KHardDiskStorageType_COUNT)
@@ -747,5 +749,4 @@
     , portModeTypes (KPortMode_COUNT)
     , usbFilterActionTypes (KUSBDeviceFilterAction_COUNT)
-    , diskControllerDevices (3)
     , audioDriverTypes (KAudioDriverType_COUNT)
     , audioControllerTypes (KAudioControllerType_COUNT)
@@ -963,22 +964,42 @@
 }
 
-QString VBoxGlobal::toString (KDiskControllerType t, LONG d) const
-{
-    Assert (diskControllerDevices.count() == 3);
+QString VBoxGlobal::toString (KStorageBus t, LONG c, LONG d) const
+{
+    Assert (storageBusDevices.count() == 3);
+    QString dev;
+
+    NOREF(c);
+    switch (t)
+    {
+        case KStorageBus_IDE:
+        {
+            if (d == 0 || d == 1)
+            {
+                dev = storageBusDevices [d];
+                break;
+            }
+        }
+        default:
+            dev = storageBusDevices [2].arg (d);
+    }
+    return dev;
+}
+
+QString VBoxGlobal::toString (KStorageBus t, LONG c) const
+{
+    Assert (storageBusChannels.count() == 3);
     QString dev;
     switch (t)
     {
-        case KDiskControllerType_IDE0:
-        case KDiskControllerType_IDE1:
-        {
-            if (d == 0 || d == 1)
+        case KStorageBus_IDE:
+        {
+            if (c == 0 || c == 1)
             {
-                dev = diskControllerDevices [d];
+                dev = storageBusChannels [c];
                 break;
             }
-            // fall through
         }
         default:
-            dev = diskControllerDevices [2].arg (d);
+            dev = storageBusChannels [2].arg (c);
     }
     return dev;
@@ -1375,7 +1396,7 @@
                     hardDisks += QString (sSectionItemTpl)
                         .arg (QString ("%1 %2")
-                              .arg (toString (hda.GetController()))
-                              .arg (toString (hda.GetController(),
-                                              hda.GetDeviceNumber())))
+                              .arg (toString (hda.GetBus(), hda.GetChannel()))
+                              .arg (toString (hda.GetBus(), hda.GetChannel(),
+                                              hda.GetDevice())))
                         .arg (QString ("%1 [<nobr>%2</nobr>]")
                               .arg (prepareFileNameForHTML (src))
@@ -2270,9 +2291,24 @@
     deviceTypes [KDeviceType_HardDisk] =        tr ("Hard Disk", "DeviceType");
     deviceTypes [KDeviceType_Network] =         tr ("Network", "DeviceType");
-
-    diskControllerTypes [KDiskControllerType_IDE0] =
-        tr ("Primary", "DiskControllerType");
-    diskControllerTypes [KDiskControllerType_IDE1] =
-        tr ("Secondary", "DiskControllerType");
+    deviceTypes [KDeviceType_USB] =             tr ("USB", "DeviceType");
+    deviceTypes [KDeviceType_SharedFolder] =    tr ("Shared Folder", "DeviceType");
+
+    storageBuses [KStorageBus_IDE] =
+        tr ("IDE", "StorageBus");
+    storageBuses [KStorageBus_SATA] =
+        tr ("SATA", "StorageBus");
+
+    Assert (storageBusChannels.count() == 3);
+    storageBusChannels [0] =
+        tr ("Primary", "StorageBusChannel");
+    storageBusChannels [1] =
+        tr ("Secondary", "StorageBusChannel");
+    storageBusChannels [2] =
+        tr ("Channel&nbsp;%1", "StorageBusChannel");
+
+    Assert (storageBusDevices.count() == 3);
+    storageBusDevices [0] = tr ("Master", "StorageBusDevice");
+    storageBusDevices [1] = tr ("Slave", "StorageBusDevice");
+    storageBusDevices [2] = tr ("Device&nbsp;%1", "StorageBusDevice");
 
     diskTypes [KHardDiskType_Normal] =
@@ -2312,9 +2348,4 @@
     usbFilterActionTypes [KUSBDeviceFilterAction_Hold] =
         tr ("Hold", "USBFilterActionType");
-
-    Assert (diskControllerDevices.count() == 3);
-    diskControllerDevices [0] = tr ("Master", "DiskControllerDevice");
-    diskControllerDevices [1] = tr ("Slave", "DiskControllerDevice");
-    diskControllerDevices [2] = tr ("Device&nbsp;%1", "DiskControllerDevice");
 
     audioDriverTypes [KAudioDriverType_Null] =
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp	(revision 7442)
@@ -1066,11 +1066,13 @@
 void VBoxProblemReporter::cannotAttachHardDisk (
     QWidget *parent, const CMachine &m, const QUuid &id,
-    KDiskControllerType ctl, LONG dev)
+    KStorageBus bus, LONG channel, LONG dev)
 {
     message (parent, Error,
         tr ("Failed to attach a hard disk image with UUID %1 "
-            "to the device slot %2 of the controller %3 of the machine <b>%4</b>.")
-            .arg (id).arg (vboxGlobal().toString (ctl, dev))
-            .arg (vboxGlobal().toString (ctl))
+            "to device slot %2 on channel %3 of the %4 bus of the machine <b>%5</b>.")
+            .arg (id)
+            .arg (vboxGlobal().toString (bus, channel, dev))
+            .arg (vboxGlobal().toString (bus, channel))
+            .arg (vboxGlobal().toString (bus))
             .arg (CMachine (m).GetName()),
         formatErrorInfo (m));
@@ -1079,11 +1081,12 @@
 void VBoxProblemReporter::cannotDetachHardDisk (
     QWidget *parent, const CMachine &m,
-    KDiskControllerType ctl, LONG dev)
+    KStorageBus bus, LONG channel, LONG dev)
 {
     message (parent, Error,
         tr ("Failed to detach a hard disk image "
-            "from the device slot %1 of the controller %2 of the machine <b>%3</b>.")
-            .arg (vboxGlobal().toString (ctl, dev))
-            .arg (vboxGlobal().toString (ctl))
+            "from device slot %1 on channel %2 of the %3 bus of the machine <b>%4</b>.")
+            .arg (vboxGlobal().toString (bus, channel, dev))
+            .arg (vboxGlobal().toString (bus, channel))
+            .arg (vboxGlobal().toString (bus))
             .arg (CMachine (m).GetName()),
         formatErrorInfo (m));
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxSelectorWnd.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxSelectorWnd.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxSelectorWnd.cpp	(revision 7442)
@@ -846,5 +846,5 @@
                 {
                     CHardDiskAttachment att = hen.GetNext();
-                    machine.DetachHardDisk (att.GetController(), att.GetDeviceNumber());
+                    machine.DetachHardDisk (att.GetBus(), att.GetChannel(), att.GetDevice());
                 }
             }
Index: trunk/src/VBox/Frontends/VirtualBox/ui/VBoxDiskImageManagerDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/ui/VBoxDiskImageManagerDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/ui/VBoxDiskImageManagerDlg.ui.h	(revision 7442)
@@ -2180,9 +2180,10 @@
                 if (hda.GetHardDisk().GetId() == aItemId)
                 {
-                    machine.DetachHardDisk (hda.GetController(),
-                                            hda.GetDeviceNumber());
+                    machine.DetachHardDisk (hda.GetBus(),
+                                            hda.GetChannel(),
+                                            hda.GetDevice());
                     if (!machine.isOk())
                         vboxProblem().cannotDetachHardDisk (this,
-                            machine, hda.GetController(), hda.GetDeviceNumber());
+                            machine, hda.GetBus(), hda.GetChannel(), hda.GetDevice());
                     break;
                 }
Index: trunk/src/VBox/Frontends/VirtualBox/ui/VBoxNewVMWzd.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/ui/VBoxNewVMWzd.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/ui/VBoxNewVMWzd.ui.h	(revision 7442)
@@ -361,5 +361,5 @@
         {
             CMachine m = session.GetMachine();
-            m.AttachHardDisk (uuidHD, KDiskControllerType_IDE0, 0);
+            m.AttachHardDisk (uuidHD, KStorageBus_IDE, 0, 0);
             if (m.isOk())
             {
@@ -372,5 +372,5 @@
             else
                 vboxProblem().cannotAttachHardDisk (this, m, uuidHD,
-                                                    KDiskControllerType_IDE0, 0);
+                                                    KStorageBus_IDE, 0, 0);
             session.Close();
         }
Index: trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui	(revision 7442)
@@ -160,5 +160,5 @@
     <function returnType="QString" access="pritave">parseStatistics( const QString &amp; )</function>
     <function access="private">refreshStatistics()</function>
-    <function returnType="QString" access="pritave">formatHardDisk( const QString &amp;, KDiskControllerType, LONG, int, int )</function>
+    <function returnType="QString" access="pritave">formatHardDisk( const QString &amp;, KStorageBus, LONG, LONG, int, int )</function>
     <function returnType="QString" access="pritave">formatAdapter( const QString &amp;, ULONG, int, int )</function>
     <function returnType="QString" access="pritave">composeArticle( const QString &amp;, int, int )</function>
Index: trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMInformationDlg.ui.h	(revision 7442)
@@ -475,25 +475,25 @@
     /* Hard Disk Statistics. */
     QString primaryMaster = QString ("%1 %2")
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE0))
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE0, 0));
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0, 0));
     QString primarySlave = QString ("%1 %2")
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE0))
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE0, 1));
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0, 1));
     QString secondarySlave = QString ("%1 %2")
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE1))
-        .arg (vboxGlobal().toString (KDiskControllerType_IDE1, 1));
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 1))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 1, 1));
 
     result += hdrRow.arg ("hd_16px.png").arg (tr ("IDE Hard Disk Statistics"));
-    result += formatHardDisk (primaryMaster, KDiskControllerType_IDE0, 0, 0, 1);
+    result += formatHardDisk (primaryMaster, KStorageBus_IDE, 0, 0, 0, 1);
     result += interline;
-    result += formatHardDisk (primarySlave, KDiskControllerType_IDE0, 1, 4, 5);
+    result += formatHardDisk (primarySlave, KStorageBus_IDE, 0, 1, 4, 5);
     result += interline;
-    result += formatHardDisk (secondarySlave, KDiskControllerType_IDE1, 1, 12, 13);
+    result += formatHardDisk (secondarySlave, KStorageBus_IDE, 1, 1, 12, 13);
     result += paragraph;
 
     /* CD/DVD-ROM Statistics. */
     result += hdrRow.arg ("cd_16px.png").arg (tr ("CD/DVD-ROM Statistics"));
-    result += formatHardDisk (QString::null /* tr ("Secondary Master") */,
-                              KDiskControllerType_IDE1, 0, 8, 9);
+    result += formatHardDisk (QString::null,
+                              KStorageBus_IDE, 1, 0, 8, 9);
     result += paragraph;
 
@@ -514,6 +514,6 @@
 
 QString VBoxVMInformationDlg::formatHardDisk (const QString &aName,
-                                              KDiskControllerType aType,
-                                              LONG aSlot, int aStart, int aFinish)
+                                              KStorageBus aBus, LONG aChannel,
+                                              LONG aDevice, int aStart, int aFinish)
 {
     if (mSession.isNull())
@@ -524,6 +524,6 @@
 
     QString result = aName.isNull() ? QString::null : header.arg (aName);
-    CHardDisk hd = machine.GetHardDisk (aType, aSlot);
-    if (!hd.isNull() || (aType == KDiskControllerType_IDE1 && aSlot == 0))
+    CHardDisk hd = machine.GetHardDisk (aBus, aChannel, aDevice);
+    if (!hd.isNull() || (aBus == KStorageBus_IDE && aChannel == 1 && aDevice == 0))
     {
         result += composeArticle (QString::null, aStart, aFinish);
Index: trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui.h	(revision 7442)
@@ -1703,5 +1703,6 @@
         struct
         {
-            KDiskControllerType ctl;
+            KStorageBus bus;
+            LONG channel;
             LONG dev;
             struct {
@@ -1714,7 +1715,7 @@
         diskSet[] =
         {
-            { KDiskControllerType_IDE0, 0, {grbHDA, cbHDA, txHDA, &uuidHDA} },
-            { KDiskControllerType_IDE0, 1, {grbHDB, cbHDB, txHDB, &uuidHDB} },
-            { KDiskControllerType_IDE1, 1, {grbHDD, cbHDD, txHDD, &uuidHDD} },
+            { KStorageBus_IDE, 0, 0, {grbHDA, cbHDA, txHDA, &uuidHDA} },
+            { KStorageBus_IDE, 0, 1, {grbHDB, cbHDB, txHDB, &uuidHDB} },
+            { KStorageBus_IDE, 1, 1, {grbHDD, cbHDD, txHDD, &uuidHDD} },
         };
 
@@ -1730,6 +1731,7 @@
             for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
             {
-                if (diskSet [i].ctl == hda.GetController() &&
-                    diskSet [i].dev == hda.GetDeviceNumber())
+                if (diskSet [i].bus == hda.GetBus() &&
+                    diskSet [i].channel == hda.GetChannel() &&
+                    diskSet [i].dev == hda.GetDevice())
                 {
                     CHardDisk hd = hda.GetHardDisk();
@@ -2086,5 +2088,6 @@
         struct
         {
-            KDiskControllerType ctl;
+            KStorageBus bus;
+            LONG channel;
             LONG dev;
             struct {
@@ -2095,7 +2098,7 @@
         diskSet[] =
         {
-            { KDiskControllerType_IDE0, 0, {grbHDA, &uuidHDA} },
-            { KDiskControllerType_IDE0, 1, {grbHDB, &uuidHDB} },
-            { KDiskControllerType_IDE1, 1, {grbHDD, &uuidHDD} }
+            { KStorageBus_IDE, 0, 0, {grbHDA, &uuidHDA} },
+            { KStorageBus_IDE, 0, 1, {grbHDB, &uuidHDB} },
+            { KStorageBus_IDE, 1, 1, {grbHDD, &uuidHDD} }
         };
 
@@ -2111,11 +2114,12 @@
             for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
             {
-                if (diskSet [i].ctl == hda.GetController() &&
-                    diskSet [i].dev == hda.GetDeviceNumber())
+                if (diskSet [i].bus == hda.GetBus() &&
+                    diskSet [i].channel == hda.GetChannel() &&
+                    diskSet [i].dev == hda.GetDevice())
                 {
-                    cmachine.DetachHardDisk (diskSet [i].ctl, diskSet [i].dev);
+                    cmachine.DetachHardDisk (diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                     if (!cmachine.isOk())
                         vboxProblem().cannotDetachHardDisk (
-                            this, cmachine, diskSet [i].ctl, diskSet [i].dev);
+                            this, cmachine, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                 }
             }
@@ -2128,8 +2132,8 @@
             if (diskSet [i].data.grb->isChecked() && !(*newId).isNull())
             {
-                cmachine.AttachHardDisk (*newId, diskSet [i].ctl, diskSet [i].dev);
+                cmachine.AttachHardDisk (*newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                 if (!cmachine.isOk())
                     vboxProblem().cannotAttachHardDisk (
-                        this, cmachine, *newId, diskSet [i].ctl, diskSet [i].dev);
+                        this, cmachine, *newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
             }
         }
Index: trunk/src/VBox/Frontends/VirtualBox4/include/VBoxGlobal.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/include/VBoxGlobal.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/include/VBoxGlobal.h	(revision 7442)
@@ -218,9 +218,12 @@
     }
 
-    QString toString (KDiskControllerType t) const
-    {
-        AssertMsg (!diskControllerTypes [t].isNull(), ("No text for %d", t));
-        return diskControllerTypes [t];
-    }
+    QString toString (KStorageBus t) const
+    {
+        AssertMsg (!storageBuses [t].isNull(), ("No text for %d", t));
+        return storageBuses [t];
+    }
+
+    QString toString (KStorageBus t, LONG c) const;
+    QString toString (KStorageBus t, LONG c, LONG d) const;
 
     QString toString (KHardDiskType t) const
@@ -319,6 +322,4 @@
         return toString (aHD.GetType());
     }
-
-    QString toString (KDiskControllerType t, LONG d) const;
 
     QString toString (KDeviceType t) const
@@ -636,5 +637,7 @@
     QStringVector sessionStates;
     QStringVector deviceTypes;
-    QStringVector diskControllerTypes;
+    QStringVector storageBuses;
+    QStringVector storageBusDevices;
+    QStringVector storageBusChannels;
     QStringVector diskTypes;
     QStringVector diskStorageTypes;
@@ -642,5 +645,4 @@
     QStringVector portModeTypes;
     QStringVector usbFilterActionTypes;
-    QStringVector diskControllerDevices;
     QStringVector audioDriverTypes;
     QStringVector audioControllerTypes;
Index: trunk/src/VBox/Frontends/VirtualBox4/include/VBoxProblemReporter.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/include/VBoxProblemReporter.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/include/VBoxProblemReporter.h	(revision 7442)
@@ -195,7 +195,7 @@
         const CVirtualDiskImage &vdi, const CProgress &progress);
     void cannotAttachHardDisk (QWidget *parent, const CMachine &m, const QUuid &id,
-                               KDiskControllerType ctl, LONG dev);
+                               KStorageBus bus, LONG channel, LONG dev);
     void cannotDetachHardDisk (QWidget *parent, const CMachine &m,
-                               KDiskControllerType ctl, LONG dev);
+                               KStorageBus bus, LONG channel, LONG dev);
     void cannotRegisterMedia (QWidget *parent, const CVirtualBox &vbox,
                               VBoxDefs::DiskType type, const QString &src);
Index: trunk/src/VBox/Frontends/VirtualBox4/src/VBoxConsoleWnd.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/src/VBoxConsoleWnd.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/src/VBoxConsoleWnd.cpp	(revision 7442)
@@ -1759,7 +1759,7 @@
             CHardDisk hd = hda.GetHardDisk();
             data += QString ("<br><nobr><b>%1 %2</b>: %3</nobr>")
-                .arg (vboxGlobal().toString (hda.GetController()))
-                .arg (vboxGlobal().toString (hda.GetController(),
-                                hda.GetDeviceNumber()))
+                .arg (vboxGlobal().toString (hda.GetBus(), hda.GetChannel()))
+                .arg (vboxGlobal().toString (hda.GetBus(), hda.GetChannel(),
+                                             hda.GetDevice()))
                 .arg (QDir::convertSeparators (hd.GetLocation()));
             hasDisks = true;
Index: trunk/src/VBox/Frontends/VirtualBox4/src/VBoxGlobal.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/src/VBoxGlobal.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/src/VBoxGlobal.cpp	(revision 7442)
@@ -752,5 +752,7 @@
     , sessionStates (KSessionState_COUNT)
     , deviceTypes (KDeviceType_COUNT)
-    , diskControllerTypes (KDiskControllerType_COUNT)
+    , storageBuses (KStorageBus_COUNT)
+    , storageBusDevices (3)
+    , storageBusChannels (3)
     , diskTypes (KHardDiskType_COUNT)
     , diskStorageTypes (KHardDiskStorageType_COUNT)
@@ -758,5 +760,4 @@
     , portModeTypes (KPortMode_COUNT)
     , usbFilterActionTypes (KUSBDeviceFilterAction_COUNT)
-    , diskControllerDevices (3)
     , audioDriverTypes (KAudioDriverType_COUNT)
     , audioControllerTypes (KAudioControllerType_COUNT)
@@ -974,22 +975,42 @@
 }
 
-QString VBoxGlobal::toString (KDiskControllerType t, LONG d) const
-{
-    Assert (diskControllerDevices.count() == 3);
+QString VBoxGlobal::toString (KStorageBus t, LONG c, LONG d) const
+{
+    Assert (storageBusDevices.count() == 3);
+    QString dev;
+
+    NOREF(c);
+    switch (t)
+    {
+        case KStorageBus_IDE:
+        {
+            if (d == 0 || d == 1)
+            {
+                dev = storageBusDevices [d];
+                break;
+            }
+        }
+        default:
+            dev = storageBusDevices [2].arg (d);
+    }
+    return dev;
+}
+
+QString VBoxGlobal::toString (KStorageBus t, LONG c) const
+{
+    Assert (storageBusChannels.count() == 3);
     QString dev;
     switch (t)
     {
-        case KDiskControllerType_IDE0:
-        case KDiskControllerType_IDE1:
-        {
-            if (d == 0 || d == 1)
+        case KStorageBus_IDE:
+        {
+            if (c == 0 || c == 1)
             {
-                dev = diskControllerDevices [d];
+                dev = storageBusChannels [c];
                 break;
             }
-            // fall through
         }
         default:
-            dev = diskControllerDevices [2].arg (d);
+            dev = storageBusChannels [2].arg (c);
     }
     return dev;
@@ -1386,7 +1407,7 @@
                     hardDisks += QString (sSectionItemTpl)
                         .arg (QString ("%1 %2")
-                              .arg (toString (hda.GetController()))
-                              .arg (toString (hda.GetController(),
-                                              hda.GetDeviceNumber())))
+                              .arg (toString (hda.GetBus(), hda.GetChannel()))
+                              .arg (toString (hda.GetBus(), hda.GetChannel(),
+                                              hda.GetDevice())))
                         .arg (QString ("%1 [<nobr>%2</nobr>]")
                               .arg (prepareFileNameForHTML (src))
@@ -2280,9 +2301,24 @@
     deviceTypes [KDeviceType_HardDisk] =        tr ("Hard Disk", "DeviceType");
     deviceTypes [KDeviceType_Network] =         tr ("Network", "DeviceType");
-
-    diskControllerTypes [KDiskControllerType_IDE0] =
-        tr ("Primary", "DiskControllerType");
-    diskControllerTypes [KDiskControllerType_IDE1] =
-        tr ("Secondary", "DiskControllerType");
+    deviceTypes [KDeviceType_USB] =             tr ("USB", "DeviceType");
+    deviceTypes [KDeviceType_SharedFolder] =    tr ("Shared Folder", "DeviceType");
+
+    storageBuses [KStorageBus_IDE] =
+        tr ("IDE", "StorageBus");
+    storageBuses [KStorageBus_SATA] =
+        tr ("SATA", "StorageBus");
+
+    Assert (storageBusChannels.count() == 3);
+    storageBusChannels [0] =
+        tr ("Primary", "StorageBusChannel");
+    storageBusChannels [1] =
+        tr ("Secondary", "StorageBusChannel");
+    storageBusChannels [2] =
+        tr ("Channel&nbsp;%1", "StorageBusChannel");
+
+    Assert (storageBusDevices.count() == 3);
+    storageBusDevices [0] = tr ("Master", "StorageBusDevice");
+    storageBusDevices [1] = tr ("Slave", "StorageBusDevice");
+    storageBusDevices [2] = tr ("Device&nbsp;%1", "StorageBusDevice");
 
     diskTypes [KHardDiskType_Normal] =
@@ -2322,9 +2358,4 @@
     usbFilterActionTypes [KUSBDeviceFilterAction_Hold] =
         tr ("Hold", "USBFilterActionType");
-
-    Assert (diskControllerDevices.count() == 3);
-    diskControllerDevices [0] = tr ("Master", "DiskControllerDevice");
-    diskControllerDevices [1] = tr ("Slave", "DiskControllerDevice");
-    diskControllerDevices [2] = tr ("Device&nbsp;%1", "DiskControllerDevice");
 
     audioDriverTypes [KAudioDriverType_Null] =
Index: trunk/src/VBox/Frontends/VirtualBox4/src/VBoxProblemReporter.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/src/VBoxProblemReporter.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/src/VBoxProblemReporter.cpp	(revision 7442)
@@ -1074,11 +1074,13 @@
 void VBoxProblemReporter::cannotAttachHardDisk (
     QWidget *parent, const CMachine &m, const QUuid &id,
-    KDiskControllerType ctl, LONG dev)
+    KStorageBus bus, LONG channel, LONG dev)
 {
     message (parent, Error,
         tr ("Failed to attach a hard disk image with UUID %1 "
-            "to the device slot %2 of the controller %3 of the machine <b>%4</b>.")
-            .arg (id).arg (vboxGlobal().toString (ctl, dev))
-            .arg (vboxGlobal().toString (ctl))
+            "to device slot %2 on channel %3 of the %4 bus of the machine <b>%5</b>.")
+            .arg (id)
+            .arg (vboxGlobal().toString (bus, channel, dev))
+            .arg (vboxGlobal().toString (bus, channel))
+            .arg (vboxGlobal().toString (bus))
             .arg (CMachine (m).GetName()),
         formatErrorInfo (m));
@@ -1087,11 +1089,12 @@
 void VBoxProblemReporter::cannotDetachHardDisk (
     QWidget *parent, const CMachine &m,
-    KDiskControllerType ctl, LONG dev)
+    KStorageBus bus, LONG channel, LONG dev)
 {
     message (parent, Error,
         tr ("Failed to detach a hard disk image "
-            "from the device slot %1 of the controller %2 of the machine <b>%3</b>.")
-            .arg (vboxGlobal().toString (ctl, dev))
-            .arg (vboxGlobal().toString (ctl))
+            "from device slot %1 on channel %2 of the %3 bus of the machine <b>%4</b>.")
+            .arg (vboxGlobal().toString (bus, channel, dev))
+            .arg (vboxGlobal().toString (bus, channel))
+            .arg (vboxGlobal().toString (bus))
             .arg (CMachine (m).GetName()),
         formatErrorInfo (m));
Index: trunk/src/VBox/Frontends/VirtualBox4/src/VBoxSelectorWnd.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/src/VBoxSelectorWnd.cpp	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/src/VBoxSelectorWnd.cpp	(revision 7442)
@@ -850,5 +850,5 @@
                 {
                     CHardDiskAttachment att = hen.GetNext();
-                    machine.DetachHardDisk (att.GetController(), att.GetDeviceNumber());
+                    machine.DetachHardDisk (att.GetBus(), att.GetChannel(), att.GetDevice());
                 }
             }
Index: trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxDiskImageManagerDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxDiskImageManagerDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxDiskImageManagerDlg.ui.h	(revision 7442)
@@ -2205,9 +2205,10 @@
                 if (hda.GetHardDisk().GetId() == aItemId)
                 {
-                    machine.DetachHardDisk (hda.GetController(),
-                                            hda.GetDeviceNumber());
+                    machine.DetachHardDisk (hda.GetBus(),
+                                            hda.GetChannel(),
+                                            hda.GetDevice());
                     if (!machine.isOk())
                         vboxProblem().cannotDetachHardDisk (this,
-                            machine, hda.GetController(), hda.GetDeviceNumber());
+                            machine, hda.GetBus(), hda.GetChannel(), hda.GetDevice());
                     break;
                 }
Index: trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxNewVMWzd.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxNewVMWzd.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxNewVMWzd.ui.h	(revision 7442)
@@ -369,5 +369,5 @@
         {
             CMachine m = session.GetMachine();
-            m.AttachHardDisk (uuidHD, KDiskControllerType_IDE0, 0);
+            m.AttachHardDisk (uuidHD, KStorageBus_IDE, 0, 0);
             if (m.isOk())
             {
@@ -380,5 +380,5 @@
             else
                 vboxProblem().cannotAttachHardDisk (this, m, uuidHD,
-                                                    KDiskControllerType_IDE0, 0);
+                                                    KStorageBus_IDE, 0, 0);
             session.Close();
         }
Index: trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui	(revision 7442)
@@ -160,5 +160,5 @@
     <function returnType="QString" access="pritave">parseStatistics( const QString &amp; )</function>
     <function access="private">refreshStatistics()</function>
-    <function returnType="QString" access="pritave">formatHardDisk( const QString &amp;, KDiskControllerType, LONG, int, int )</function>
+    <function returnType="QString" access="pritave">formatHardDisk( const QString &amp;, KStorageBus, LONG, LONG, int, int )</function>
     <function returnType="QString" access="pritave">formatAdapter( const QString &amp;, ULONG, int, int )</function>
     <function returnType="QString" access="pritave">composeArticle( const QString &amp;, int, int )</function>
Index: trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMInformationDlg.ui.h	(revision 7442)
@@ -485,16 +485,26 @@
 
     /* Hard Disk Statistics. */
+    QString primaryMaster = QString ("%1 %2")
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0, 0));
+    QString primarySlave = QString ("%1 %2")
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 0, 1));
+    QString secondarySlave = QString ("%1 %2")
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 1))
+        .arg (vboxGlobal().toString (KStorageBus_IDE, 1, 1));
+
     result += hdrRow.arg (":/hd_16px.png").arg (tr ("IDE Hard Disk Statistics"));
-    result += formatHardDisk (tr ("Primary Master"), KDiskControllerType_IDE0, 0, 0, 1);
+    result += formatHardDisk (primaryMaster, KStorageBus_IDE, 0, 0, 0, 1);
     result += interline;
-    result += formatHardDisk (tr ("Primary Slave"), KDiskControllerType_IDE0, 1, 4, 5);
+    result += formatHardDisk (primarySlave, KStorageBus_IDE, 0, 1, 4, 5);
     result += interline;
-    result += formatHardDisk (tr ("Secondary Slave"), KDiskControllerType_IDE1, 1, 12, 13);
+    result += formatHardDisk (secondarySlave, KStorageBus_IDE, 1, 1, 12, 13);
     result += paragraph;
 
     /* CD/DVD-ROM Statistics. */
     result += hdrRow.arg (":/cd_16px.png").arg (tr ("CD/DVD-ROM Statistics"));
-    result += formatHardDisk (QString::null /* tr ("Secondary Master") */,
-                              KDiskControllerType_IDE1, 0, 8, 9);
+    result += formatHardDisk (QString::null,
+                              KStorageBus_IDE, 1, 0, 8, 9);
     result += paragraph;
 
@@ -515,6 +525,6 @@
 
 QString VBoxVMInformationDlg::formatHardDisk (const QString &aName,
-                                              KDiskControllerType aType,
-                                              LONG aSlot, int aStart, int aFinish)
+                                              KStorageBus aBus, LONG aChannel,
+                                              LONG aDevice, int aStart, int aFinish)
 {
     if (mSession.isNull())
@@ -525,6 +535,6 @@
 
     QString result = aName.isNull() ? QString::null : header.arg (aName);
-    CHardDisk hd = machine.GetHardDisk (aType, aSlot);
-    if (!hd.isNull() || (aType == KDiskControllerType_IDE1 && aSlot == 0))
+    CHardDisk hd = machine.GetHardDisk (aBus, aChannel, aDevice);
+    if (!hd.isNull() || (aBus == KStorageBus_IDE && aChannel == 1 && aDevice == 0))
     {
         result += composeArticle (QString::null, aStart, aFinish);
Index: trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMSettingsDlg.ui.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMSettingsDlg.ui.h	(revision 7441)
+++ trunk/src/VBox/Frontends/VirtualBox4/ui/VBoxVMSettingsDlg.ui.h	(revision 7442)
@@ -1718,5 +1718,6 @@
         struct
         {
-            KDiskControllerType ctl;
+            KStorageBus bus;
+            LONG channel;
             LONG dev;
             struct {
@@ -1729,7 +1730,7 @@
         diskSet[] =
         {
-            { KDiskControllerType_IDE0, 0, {grbHDA, cbHDA, txHDA, &uuidHDA} },
-            { KDiskControllerType_IDE0, 1, {grbHDB, cbHDB, txHDB, &uuidHDB} },
-            { KDiskControllerType_IDE1, 1, {grbHDD, cbHDD, txHDD, &uuidHDD} },
+            { KStorageBus_IDE, 0, 0, {grbHDA, cbHDA, txHDA, &uuidHDA} },
+            { KStorageBus_IDE, 0, 1, {grbHDB, cbHDB, txHDB, &uuidHDB} },
+            { KStorageBus_IDE, 1, 1, {grbHDD, cbHDD, txHDD, &uuidHDD} },
         };
 
@@ -1745,6 +1746,7 @@
             for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
             {
-                if (diskSet [i].ctl == hda.GetController() &&
-                    diskSet [i].dev == hda.GetDeviceNumber())
+                if (diskSet [i].bus == hda.GetBus() &&
+                    diskSet [i].channel == hda.GetChannel() &&
+                    diskSet [i].dev == hda.GetDevice())
                 {
                     CHardDisk hd = hda.GetHardDisk();
@@ -2101,5 +2103,6 @@
         struct
         {
-            KDiskControllerType ctl;
+            KStorageBus bus;
+            LONG channel;
             LONG dev;
             struct {
@@ -2110,7 +2113,7 @@
         diskSet[] =
         {
-            { KDiskControllerType_IDE0, 0, {grbHDA, &uuidHDA} },
-            { KDiskControllerType_IDE0, 1, {grbHDB, &uuidHDB} },
-            { KDiskControllerType_IDE1, 1, {grbHDD, &uuidHDD} }
+            { KStorageBus_IDE, 0, 0, {grbHDA, &uuidHDA} },
+            { KStorageBus_IDE, 0, 1, {grbHDB, &uuidHDB} },
+            { KStorageBus_IDE, 1, 1, {grbHDD, &uuidHDD} }
         };
 
@@ -2126,11 +2129,12 @@
             for (uint i = 0; i < SIZEOF_ARRAY (diskSet); i++)
             {
-                if (diskSet [i].ctl == hda.GetController() &&
-                    diskSet [i].dev == hda.GetDeviceNumber())
+                if (diskSet [i].bus == hda.GetBus() &&
+                    diskSet [i].channel == hda.GetChannel() &&
+                    diskSet [i].dev == hda.GetDevice())
                 {
-                    cmachine.DetachHardDisk (diskSet [i].ctl, diskSet [i].dev);
+                    cmachine.DetachHardDisk (diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                     if (!cmachine.isOk())
                         vboxProblem().cannotDetachHardDisk (
-                            this, cmachine, diskSet [i].ctl, diskSet [i].dev);
+                            this, cmachine, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                 }
             }
@@ -2143,8 +2147,8 @@
             if (diskSet [i].data.grb->isChecked() && !(*newId).isNull())
             {
-                cmachine.AttachHardDisk (*newId, diskSet [i].ctl, diskSet [i].dev);
+                cmachine.AttachHardDisk (*newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
                 if (!cmachine.isOk())
                     vboxProblem().cannotAttachHardDisk (
-                        this, cmachine, *newId, diskSet [i].ctl, diskSet [i].dev);
+                        this, cmachine, *newId, diskSet [i].bus, diskSet [i].channel, diskSet [i].dev);
             }
         }
Index: trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 7441)
+++ trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 7442)
@@ -6131,30 +6131,37 @@
     ComPtr<IHardDisk> hardDisk;
     hrc = hda->COMGETTER(HardDisk)(hardDisk.asOutParam());                      H();
-    DiskControllerType_T enmCtl;
-    hrc = hda->COMGETTER(Controller)(&enmCtl);                                  H();
+    StorageBus_T enmBus;
+    hrc = hda->COMGETTER(Bus)(&enmBus);                                         H();
     LONG lDev;
-    hrc = hda->COMGETTER(DeviceNumber)(&lDev);                                  H();
-
-    int i;
-    switch (enmCtl)
-    {
-        case DiskControllerType_IDE0:
-            i = 0;
-            break;
-        case DiskControllerType_IDE1:
-            i = 2;
+    hrc = hda->COMGETTER(Device)(&lDev);                                        H();
+    LONG lChannel;
+    hrc = hda->COMGETTER(Channel)(&lChannel);                                   H();
+
+    int iLUN;
+    switch (enmBus)
+    {
+        case StorageBus_IDE:
+        {
+            if (lChannel >= 2)
+            {
+                AssertMsgFailed(("invalid controller channel number: %d\n", lChannel));
+                return VERR_GENERAL_FAILURE;
+            }
+
+            if (lDev >= 2)
+            {
+                AssertMsgFailed(("invalid controller device number: %d\n", lDev));
+                return VERR_GENERAL_FAILURE;
+            }
+            iLUN = 2*lChannel + lDev;
+        }
+        break;
+        case StorageBus_SATA:
+            iLUN = lChannel;
             break;
         default:
-            AssertMsgFailed(("invalid disk controller type: %d\n", enmCtl));
+            AssertMsgFailed(("invalid disk controller type: %d\n", enmBus));
             return VERR_GENERAL_FAILURE;
     }
-
-    if (lDev < 0 || lDev >= 2)
-    {
-        AssertMsgFailed(("invalid controller device number: %d\n", lDev));
-        return VERR_GENERAL_FAILURE;
-    }
-
-    i = i + lDev;
 
     /*
@@ -6163,5 +6170,5 @@
      */
     PCFGMNODE pCfg;
-    PCFGMNODE pLunL1 = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/piix3ide/0/LUN#%d/AttachedDriver/", i);
+    PCFGMNODE pLunL1 = CFGMR3GetChildF(CFGMR3GetRoot(pVM), "Devices/piix3ide/0/LUN#%d/AttachedDriver/", iLUN);
     if (!pLunL1)
     {
@@ -6170,5 +6177,5 @@
 
         PCFGMNODE pLunL0;
-        rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%d", i);                        RC_CHECK();
+        rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%d", iLUN);                     RC_CHECK();
         rc = CFGMR3InsertString(pLunL0, "Driver",              "Block");            RC_CHECK();
         rc = CFGMR3InsertNode(pLunL0,   "Config", &pCfg);                           RC_CHECK();
@@ -6248,5 +6255,5 @@
         }
         else
-            LogFlowFunc (("LUN#%d: old leaf image '%s'\n", i, pszPath));
+            LogFlowFunc (("LUN#%d: old leaf image '%s'\n", iLUN, pszPath));
 
         MMR3HeapFree(pszPath);
@@ -6256,5 +6263,5 @@
          * Detach the driver and replace the config node.
          */
-        rc = PDMR3DeviceDetach(pVM, "piix3ide", 0, i);                              RC_CHECK();
+        rc = PDMR3DeviceDetach(pVM, "piix3ide", 0, iLUN);                           RC_CHECK();
         CFGMR3RemoveNode(pCfg);
         rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg);                             RC_CHECK();
@@ -6271,5 +6278,5 @@
     hrc = hardDisk->COMGETTER(Location)(&str);                                  H();
     STR_CONV();
-    LogFlowFunc (("LUN#%d: leaf image '%s'\n", i, psz));
+    LogFlowFunc (("LUN#%d: leaf image '%s'\n", iLUN, psz));
     rc = CFGMR3InsertString(pCfg, "Path", psz);                                 RC_CHECK();
     STR_FREE();
@@ -6303,5 +6310,5 @@
      * Attach the new driver.
      */
-    rc = PDMR3DeviceAttach(pVM, "piix3ide", 0, i, NULL);                        RC_CHECK();
+    rc = PDMR3DeviceAttach(pVM, "piix3ide", 0, iLUN, NULL);                     RC_CHECK();
 
     LogFlowFunc (("Returns success\n"));
Index: trunk/src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 7441)
+++ trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 7442)
@@ -96,5 +96,4 @@
     char           *psz = NULL;
     BSTR            str = NULL;
-    unsigned        i;
 
 #define STR_CONV()  do { rc = RTUtf16ToUtf8(str, &psz); RC_CHECK(); } while (0)
@@ -224,4 +223,6 @@
     PCFGMNODE pLunL1 = NULL;        /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
     PCFGMNODE pLunL2 = NULL;        /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
+    PCFGMNODE pIdeInst = NULL;      /* /Devices/piix3ide/0/ */
+    PCFGMNODE pSataInst = NULL;     /* /Devices/ahci/0/ */
 
     rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices);                             RC_CHECK();
@@ -573,15 +574,15 @@
      */
     rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */                 RC_CHECK();
-    rc = CFGMR3InsertNode(pDev,     "0", &pInst);                                   RC_CHECK();
-    rc = CFGMR3InsertInteger(pInst, "Trusted",              1);     /* boolean */   RC_CHECK();
-    rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo",          1);                     RC_CHECK();
+    rc = CFGMR3InsertNode(pDev,     "0", &pIdeInst);                                RC_CHECK();
+    rc = CFGMR3InsertInteger(pIdeInst, "Trusted",              1);  /* boolean */   RC_CHECK();
+    rc = CFGMR3InsertInteger(pIdeInst, "PCIDeviceNo",          1);                  RC_CHECK();
     Assert(!afPciDeviceNo[1]);
     afPciDeviceNo[1] = true;
-    rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo",        1);                     RC_CHECK();
-    rc = CFGMR3InsertNode(pInst,    "Config", &pCfg);                               RC_CHECK();
+    rc = CFGMR3InsertInteger(pIdeInst, "PCIFunctionNo",        1);                  RC_CHECK();
+    rc = CFGMR3InsertNode(pIdeInst,    "Config", &pCfg);                            RC_CHECK();
     rc = CFGMR3InsertInteger(pCfg,  "PIIX4", fPIIX4);               /* boolean */   RC_CHECK();
 
     /* Attach the status driver */
-    rc = CFGMR3InsertNode(pInst,    "LUN#999", &pLunL0);                            RC_CHECK();
+    rc = CFGMR3InsertNode(pIdeInst,    "LUN#999", &pLunL0);                         RC_CHECK();
     rc = CFGMR3InsertString(pLunL0, "Driver",               "MainStatus");          RC_CHECK();
     rc = CFGMR3InsertNode(pLunL0,   "Config", &pCfg);                               RC_CHECK();
@@ -590,4 +591,38 @@
     rc = CFGMR3InsertInteger(pCfg,  "Last",     3);                                 RC_CHECK();
 
+    /*
+     * SATA controller
+     */
+    ComPtr<ISATAController> sataController;
+    hrc = pMachine->COMGETTER(SATAController)(sataController.asOutParam());
+    BOOL enabled = FALSE;
+
+    if (sataController)
+    {
+        hrc = sataController->COMGETTER(Enabled)(&enabled);                         H();
+
+        if (enabled)
+        {
+            rc = CFGMR3InsertNode(pDevices, "ahci", &pDev);                             RC_CHECK();
+            rc = CFGMR3InsertNode(pDev,     "0", &pSataInst);                           RC_CHECK();
+            rc = CFGMR3InsertInteger(pIdeInst, "Trusted",              1);              RC_CHECK();
+            rc = CFGMR3InsertInteger(pIdeInst, "PCIDeviceNo",          13);             RC_CHECK();
+            Assert(!afPciDeviceNo[13]);
+            afPciDeviceNo[13] = true;
+            rc = CFGMR3InsertInteger(pIdeInst, "PCIFunctionNo",        1);              RC_CHECK();
+            rc = CFGMR3InsertNode(pIdeInst,    "Config", &pCfg);                        RC_CHECK();
+
+            for (uint32_t i = 0; i < 4; i++)
+            {
+                const char *g_apszConfig[] =
+                    { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
+                LONG aPortNumber;
+
+                hrc = sataController->GetIDEEmulationPort(i, &aPortNumber);             H();
+                rc = CFGMR3InsertInteger(pCfg, g_apszConfig[i], aPortNumber);           RC_CHECK();
+            }
+        }
+    }
+
     /* Attach the harddisks */
     ComPtr<IHardDiskAttachmentCollection> hdaColl;
@@ -600,199 +635,214 @@
            &&   fMore)
     {
+        PCFGMNODE pHardDiskCtl;
         ComPtr<IHardDiskAttachment> hda;
         hrc = hdaEnum->GetNext(hda.asOutParam());                                   H();
         ComPtr<IHardDisk> hardDisk;
         hrc = hda->COMGETTER(HardDisk)(hardDisk.asOutParam());                      H();
-        DiskControllerType_T enmCtl;
-        hrc = hda->COMGETTER(Controller)(&enmCtl);                                  H();
+        StorageBus_T enmBus;
+        hrc = hda->COMGETTER(Bus)(&enmBus);                                         H();
         LONG lDev;
-        hrc = hda->COMGETTER(DeviceNumber)(&lDev);                                  H();
-
-        switch (enmCtl)
-        {
-            case DiskControllerType_IDE0:
-                i = 0;
-                break;
-            case DiskControllerType_IDE1:
-                i = 2;
+        hrc = hda->COMGETTER(Device)(&lDev);                                        H();
+        LONG lChannel;
+        hrc = hda->COMGETTER(Channel)(&lChannel);                                   H();
+
+        int iLUN;
+        switch (enmBus)
+        {
+            case StorageBus_IDE:
+            {
+                if (lChannel >= 2 || lChannel < 0)
+                {
+                    AssertMsgFailed(("invalid controller channel number: %d\n", lChannel));
+                    return VERR_GENERAL_FAILURE;
+                }
+
+                if (lDev >= 2 || lDev < 0)
+                {
+                    AssertMsgFailed(("invalid controller device number: %d\n", lDev));
+                    return VERR_GENERAL_FAILURE;
+                }
+                iLUN = 2*lChannel + lDev;
+                pHardDiskCtl = pIdeInst;
+            }
+            break;
+            case StorageBus_SATA:
+                iLUN = lChannel;
+                pHardDiskCtl = enabled ? pSataInst : NULL;
                 break;
             default:
-                AssertMsgFailed(("invalid disk controller type: %d\n", enmCtl));
+                AssertMsgFailed(("invalid disk controller type: %d\n", enmBus));
                 return VERR_GENERAL_FAILURE;
         }
 
-        if (lDev < 0 || lDev >= 2)
-        {
-            AssertMsgFailed(("invalid controller device number: %d\n", lDev));
-            return VERR_GENERAL_FAILURE;
-        }
-
-        i = i + lDev;
-
-        char szLUN[16];
-        RTStrPrintf(szLUN, sizeof(szLUN), "LUN#%d", i);
-        rc = CFGMR3InsertNode(pInst,    szLUN, &pLunL0);                            RC_CHECK();
-        rc = CFGMR3InsertString(pLunL0, "Driver",               "Block");           RC_CHECK();
-        rc = CFGMR3InsertNode(pLunL0,   "Config", &pCfg);                           RC_CHECK();
-        rc = CFGMR3InsertString(pCfg,   "Type",                 "HardDisk");        RC_CHECK();
-        rc = CFGMR3InsertInteger(pCfg,  "Mountable",            0);                 RC_CHECK();
-
-        HardDiskStorageType_T hddType;
-        hardDisk->COMGETTER(StorageType)(&hddType);
-        if (hddType == HardDiskStorageType_VirtualDiskImage)
-        {
-            ComPtr<IVirtualDiskImage> vdiDisk = hardDisk;
-            AssertBreak (!vdiDisk.isNull(), hrc = E_FAIL);
-
-            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "VBoxHDD");               RC_CHECK();
-            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
-            hrc = vdiDisk->COMGETTER(FilePath)(&str);                                   H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
-            STR_FREE();
-
-            /* Create an inversed tree of parents. */
-            ComPtr<IHardDisk> parentHardDisk = hardDisk;
-            for (PCFGMNODE pParent = pCfg;;)
-            {
-                ComPtr<IHardDisk> curHardDisk;
-                hrc = parentHardDisk->COMGETTER(Parent)(curHardDisk.asOutParam());      H();
-                if (!curHardDisk)
-                    break;
-
-                vdiDisk = curHardDisk;
+        /* Can be NULL if SATA controller is not enabled and current hard disk is attached to SATA controller. */
+        if (pHardDiskCtl)
+        {
+            char szLUN[16];
+            RTStrPrintf(szLUN, sizeof(szLUN), "LUN#%d", iLUN);
+            rc = CFGMR3InsertNode(pHardDiskCtl,    szLUN, &pLunL0);                     RC_CHECK();
+            rc = CFGMR3InsertString(pLunL0, "Driver",               "Block");           RC_CHECK();
+            rc = CFGMR3InsertNode(pLunL0,   "Config", &pCfg);                           RC_CHECK();
+            rc = CFGMR3InsertString(pCfg,   "Type",                 "HardDisk");        RC_CHECK();
+            rc = CFGMR3InsertInteger(pCfg,  "Mountable",            0);                 RC_CHECK();
+
+            HardDiskStorageType_T hddType;
+            hardDisk->COMGETTER(StorageType)(&hddType);
+            if (hddType == HardDiskStorageType_VirtualDiskImage)
+            {
+                ComPtr<IVirtualDiskImage> vdiDisk = hardDisk;
                 AssertBreak (!vdiDisk.isNull(), hrc = E_FAIL);
 
-                PCFGMNODE pCur;
-                rc = CFGMR3InsertNode(pParent, "Parent", &pCur);                        RC_CHECK();
-                hrc = vdiDisk->COMGETTER(FilePath)(&str);                               H();
+                rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "VBoxHDD");               RC_CHECK();
+                rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
+                hrc = vdiDisk->COMGETTER(FilePath)(&str);                                   H();
                 STR_CONV();
-                rc = CFGMR3InsertString(pCur,  "Path", psz);                            RC_CHECK();
+                rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
                 STR_FREE();
-                rc = CFGMR3InsertInteger(pCur, "ReadOnly", 1);                          RC_CHECK();
-
-                /* next */
-                pParent = pCur;
-                parentHardDisk = curHardDisk;
-            }
-        }
-        else if (hddType == HardDiskStorageType_ISCSIHardDisk)
-        {
-            ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
-            AssertBreak (!iSCSIDisk.isNull(), hrc = E_FAIL);
-
-            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "iSCSI");                 RC_CHECK();
-            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
-
-            /* Set up the iSCSI initiator driver configuration. */
-            hrc = iSCSIDisk->COMGETTER(Target)(&str);                                   H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "TargetName",   psz);                       RC_CHECK();
-            STR_FREE();
-
-            // @todo currently there is no Initiator name config.
-            rc = CFGMR3InsertString(pCfg,   "InitiatorName", "iqn.2006-02.de.innotek.initiator"); RC_CHECK();
-
-            ULONG64 lun;
-            hrc = iSCSIDisk->COMGETTER(Lun)(&lun);                                      H();
-            rc = CFGMR3InsertInteger(pCfg,   "LUN",         lun);                       RC_CHECK();
-
-            hrc = iSCSIDisk->COMGETTER(Server)(&str);                                   H();
-            STR_CONV();
-            USHORT port;
-            hrc = iSCSIDisk->COMGETTER(Port)(&port);                                    H();
-            if (port != 0)
-            {
-                char *pszTN;
-                RTStrAPrintf(&pszTN, "%s:%u", psz, port);
-                rc = CFGMR3InsertString(pCfg,   "TargetAddress",    pszTN);             RC_CHECK();
-                RTStrFree(pszTN);
+
+                /* Create an inversed tree of parents. */
+                ComPtr<IHardDisk> parentHardDisk = hardDisk;
+                for (PCFGMNODE pParent = pCfg;;)
+                {
+                    ComPtr<IHardDisk> curHardDisk;
+                    hrc = parentHardDisk->COMGETTER(Parent)(curHardDisk.asOutParam());      H();
+                    if (!curHardDisk)
+                        break;
+
+                    vdiDisk = curHardDisk;
+                    AssertBreak (!vdiDisk.isNull(), hrc = E_FAIL);
+
+                    PCFGMNODE pCur;
+                    rc = CFGMR3InsertNode(pParent, "Parent", &pCur);                        RC_CHECK();
+                    hrc = vdiDisk->COMGETTER(FilePath)(&str);                               H();
+                    STR_CONV();
+                    rc = CFGMR3InsertString(pCur,  "Path", psz);                            RC_CHECK();
+                    STR_FREE();
+                    rc = CFGMR3InsertInteger(pCur, "ReadOnly", 1);                          RC_CHECK();
+
+                    /* next */
+                    pParent = pCur;
+                    parentHardDisk = curHardDisk;
+                }
+            }
+            else if (hddType == HardDiskStorageType_ISCSIHardDisk)
+            {
+                ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
+                AssertBreak (!iSCSIDisk.isNull(), hrc = E_FAIL);
+
+                rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "iSCSI");                 RC_CHECK();
+                rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
+
+                /* Set up the iSCSI initiator driver configuration. */
+                hrc = iSCSIDisk->COMGETTER(Target)(&str);                                   H();
+                STR_CONV();
+                rc = CFGMR3InsertString(pCfg,   "TargetName",   psz);                       RC_CHECK();
+                STR_FREE();
+
+                // @todo currently there is no Initiator name config.
+                rc = CFGMR3InsertString(pCfg,   "InitiatorName", "iqn.2006-02.de.innotek.initiator"); RC_CHECK();
+
+                ULONG64 lun;
+                hrc = iSCSIDisk->COMGETTER(Lun)(&lun);                                      H();
+                rc = CFGMR3InsertInteger(pCfg,   "LUN",         lun);                       RC_CHECK();
+
+                hrc = iSCSIDisk->COMGETTER(Server)(&str);                                   H();
+                STR_CONV();
+                USHORT port;
+                hrc = iSCSIDisk->COMGETTER(Port)(&port);                                    H();
+                if (port != 0)
+                {
+                    char *pszTN;
+                    RTStrAPrintf(&pszTN, "%s:%u", psz, port);
+                    rc = CFGMR3InsertString(pCfg,   "TargetAddress",    pszTN);             RC_CHECK();
+                    RTStrFree(pszTN);
+                }
+                else
+                {
+                    rc = CFGMR3InsertString(pCfg,   "TargetAddress",    psz);               RC_CHECK();
+                }
+                STR_FREE();
+
+                hrc = iSCSIDisk->COMGETTER(UserName)(&str);                                 H();
+                if (str)
+                {
+                    STR_CONV();
+                    rc = CFGMR3InsertString(pCfg,   "InitiatorUsername",    psz);           RC_CHECK();
+                    STR_FREE();
+                }
+
+                hrc = iSCSIDisk->COMGETTER(Password)(&str);                                 H();
+                if (str)
+                {
+                    STR_CONV();
+                    rc = CFGMR3InsertString(pCfg,   "InitiatorSecret",      psz);           RC_CHECK();
+                    STR_FREE();
+                }
+
+                // @todo currently there is no target username config.
+                //rc = CFGMR3InsertString(pCfg,   "TargetUsername",   "");                    RC_CHECK();
+
+                // @todo currently there is no target password config.
+                //rc = CFGMR3InsertString(pCfg,   "TargetSecret",     "");                    RC_CHECK();
+
+                /* The iSCSI initiator needs an attached iSCSI transport driver. */
+                rc = CFGMR3InsertNode(pLunL1,   "AttachedDriver", &pLunL2);                 RC_CHECK();
+                rc = CFGMR3InsertString(pLunL2, "Driver",           "iSCSITCP");            RC_CHECK();
+                /* Currently the transport driver has no config options. */
+            }
+            else if (hddType == HardDiskStorageType_VMDKImage)
+            {
+                ComPtr<IVMDKImage> vmdkDisk = hardDisk;
+                AssertBreak (!vmdkDisk.isNull(), hrc = E_FAIL);
+
+                rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
+#if 1 /* Enable new VD container code (and new VMDK), as the bugs are fixed. */
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");               RC_CHECK();
+#else
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "VmdkHDD");               RC_CHECK();
+#endif
+                rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
+                hrc = vmdkDisk->COMGETTER(FilePath)(&str);                                  H();
+                STR_CONV();
+                rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
+                STR_FREE();
+                rc = CFGMR3InsertString(pCfg,   "Format",           "VMDK");                RC_CHECK();
+            }
+            else if (hddType == HardDiskStorageType_CustomHardDisk)
+            {
+                ComPtr<ICustomHardDisk> customHardDisk = hardDisk;
+                AssertBreak (!customHardDisk.isNull(), hrc = E_FAIL);
+
+                rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");                    RC_CHECK();
+                rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
+                hrc = customHardDisk->COMGETTER(Location)(&str);                            H();
+                STR_CONV();
+                rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
+                STR_FREE();
+                hrc = customHardDisk->COMGETTER(Format)(&str);                              H();
+                STR_CONV();
+                rc = CFGMR3InsertString(pCfg,   "Format",           psz);                   RC_CHECK();
+                STR_FREE();
+            }
+            else if (hddType == HardDiskStorageType_VHDImage)
+            {
+                ComPtr<IVHDImage> vhdDisk = hardDisk;
+                AssertBreak (!vhdDisk.isNull(), hrc = E_FAIL);
+
+                rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
+                rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");                    RC_CHECK();
+                rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
+                hrc = vhdDisk->COMGETTER(FilePath)(&str);                                   H();
+                STR_CONV();
+                rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
+                rc = CFGMR3InsertString(pCfg,   "Format",           "VHD");                 RC_CHECK();
+                STR_FREE();
             }
             else
-            {
-                rc = CFGMR3InsertString(pCfg,   "TargetAddress",    psz);               RC_CHECK();
-            }
-            STR_FREE();
-
-            hrc = iSCSIDisk->COMGETTER(UserName)(&str);                                 H();
-            if (str)
-            {
-                STR_CONV();
-                rc = CFGMR3InsertString(pCfg,   "InitiatorUsername",    psz);           RC_CHECK();
-                STR_FREE();
-            }
-
-            hrc = iSCSIDisk->COMGETTER(Password)(&str);                                 H();
-            if (str)
-            {
-                STR_CONV();
-                rc = CFGMR3InsertString(pCfg,   "InitiatorSecret",      psz);           RC_CHECK();
-                STR_FREE();
-            }
-
-            // @todo currently there is no target username config.
-            //rc = CFGMR3InsertString(pCfg,   "TargetUsername",   "");                    RC_CHECK();
-
-            // @todo currently there is no target password config.
-            //rc = CFGMR3InsertString(pCfg,   "TargetSecret",     "");                    RC_CHECK();
-
-            /* The iSCSI initiator needs an attached iSCSI transport driver. */
-            rc = CFGMR3InsertNode(pLunL1,   "AttachedDriver", &pLunL2);                 RC_CHECK();
-            rc = CFGMR3InsertString(pLunL2, "Driver",           "iSCSITCP");            RC_CHECK();
-            /* Currently the transport driver has no config options. */
-        }
-        else if (hddType == HardDiskStorageType_VMDKImage)
-        {
-            ComPtr<IVMDKImage> vmdkDisk = hardDisk;
-            AssertBreak (!vmdkDisk.isNull(), hrc = E_FAIL);
-
-            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
-#if 1 /* Enable new VD container code (and new VMDK), as the bugs are fixed. */
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");               RC_CHECK();
-#else
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "VmdkHDD");               RC_CHECK();
-#endif
-            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
-            hrc = vmdkDisk->COMGETTER(FilePath)(&str);                                  H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
-            STR_FREE();
-            rc = CFGMR3InsertString(pCfg,   "Format",           "VMDK");                RC_CHECK();
-        }
-        else if (hddType == HardDiskStorageType_CustomHardDisk)
-        {
-            ComPtr<ICustomHardDisk> customHardDisk = hardDisk;
-            AssertBreak (!customHardDisk.isNull(), hrc = E_FAIL);
-
-            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");                    RC_CHECK();
-            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
-            hrc = customHardDisk->COMGETTER(Location)(&str);                            H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
-            STR_FREE();
-            hrc = customHardDisk->COMGETTER(Format)(&str);                              H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "Format",           psz);                   RC_CHECK();
-            STR_FREE();
-        }
-        else if (hddType == HardDiskStorageType_VHDImage)
-        {
-            ComPtr<IVHDImage> vhdDisk = hardDisk;
-            AssertBreak (!vhdDisk.isNull(), hrc = E_FAIL);
-
-            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
-            rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");                    RC_CHECK();
-            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
-            hrc = vhdDisk->COMGETTER(FilePath)(&str);                                   H();
-            STR_CONV();
-            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
-            rc = CFGMR3InsertString(pCfg,   "Format",           "VHD");                 RC_CHECK();
-            STR_FREE();
-        }
-        else
-           AssertFailed();
+               AssertFailed();
+        }
     }
     H();
@@ -803,5 +853,5 @@
     {
         // ASSUME: DVD drive is always attached to LUN#2 (i.e. secondary IDE master)
-        rc = CFGMR3InsertNode(pInst,    "LUN#2", &pLunL0);                          RC_CHECK();
+        rc = CFGMR3InsertNode(pIdeInst,    "LUN#2", &pLunL0);                       RC_CHECK();
         ComPtr<IHostDVDDrive> hostDvdDrive;
         hrc = dvdDrive->GetHostDrive(hostDvdDrive.asOutParam());                    H();
@@ -1288,5 +1338,4 @@
     ComPtr<IAudioAdapter> audioAdapter;
     hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());             H();
-    BOOL enabled = FALSE;
     if (audioAdapter)
         hrc = audioAdapter->COMGETTER(Enabled)(&enabled);                           H();
Index: trunk/src/VBox/Main/HardDiskAttachmentImpl.cpp
===================================================================
--- trunk/src/VBox/Main/HardDiskAttachmentImpl.cpp	(revision 7441)
+++ trunk/src/VBox/Main/HardDiskAttachmentImpl.cpp	(revision 7442)
@@ -28,6 +28,7 @@
 HRESULT HardDiskAttachment::FinalConstruct()
 {
-    mController = DiskControllerType_Null;
-    mDeviceNumber = 0;
+    mBus = StorageBus_Null;
+    mChannel = 0;
+    mDevice = 0;
 
     return S_OK;
@@ -46,12 +47,28 @@
  *
  *  @param aHD      hard disk object
- *  @param aCtl     controller type
- *  @param aDev     device number on the controller
+ *  @param aBus     bus type
+ *  @param aChannel channel number
+ *  @param aDevice  device number on the channel
  *  @param aDirty   whether the attachment is initially dirty or not
  */
-HRESULT HardDiskAttachment::init (HardDisk *aHD, DiskControllerType_T aCtl, LONG aDev,
+HRESULT HardDiskAttachment::init (HardDisk *aHD, StorageBus_T aBus, LONG aChannel, LONG aDevice,
                                   BOOL aDirty)
 {
     ComAssertRet (aHD, E_INVALIDARG);
+
+    if (aBus == StorageBus_IDE)
+    {
+        if (aChannel < 0 || aChannel > 1)
+            return setError (E_FAIL,
+                tr ("Invalid IDE channel for hard disk '%ls': %d. "
+                    "IDE channel number must be in range [0,1]"),
+                aHD->toString().raw(), aChannel);
+        if (aDevice < 0 || aDevice > 1 || (aChannel == 1 && aDevice == 0))
+            return setError (E_FAIL,
+                tr ("Invalid IDE device slot for hard disk '%ls': %d. "
+                    "IDE device slot number must be in range [0,1] for "
+                    "channel 0 and always 1 for channel 1"),
+                aHD->toString().raw(), aDevice);
+    }
 
     AutoLock alock (this);
@@ -60,6 +77,7 @@
 
     mHardDisk = aHD;
-    mController = aCtl;
-    mDeviceNumber = aDev;
+    mBus = aBus;
+    mChannel = aChannel;
+    mDevice = aDevice;
 
     setReady (true);
@@ -84,7 +102,7 @@
 }
 
-STDMETHODIMP HardDiskAttachment::COMGETTER(Controller) (DiskControllerType_T *aController)
+STDMETHODIMP HardDiskAttachment::COMGETTER(Bus) (StorageBus_T *aBus)
 {
-    if (!aController)
+    if (!aBus)
         return E_POINTER;
 
@@ -92,11 +110,11 @@
     CHECK_READY();
 
-    *aController = mController;
+    *aBus = mBus;
     return S_OK;
 }
 
-STDMETHODIMP HardDiskAttachment::COMGETTER(DeviceNumber) (LONG *aDeviceNumber)
+STDMETHODIMP HardDiskAttachment::COMGETTER(Channel) (LONG *aChannel)
 {
-    if (!aDeviceNumber)
+    if (!aChannel)
         return E_INVALIDARG;
 
@@ -104,6 +122,18 @@
     CHECK_READY();
 
-    *aDeviceNumber = mDeviceNumber;
+    *aChannel = mChannel;
     return S_OK;
 }
 
+STDMETHODIMP HardDiskAttachment::COMGETTER(Device) (LONG *aDevice)
+{
+    if (!aDevice)
+        return E_INVALIDARG;
+
+    AutoLock alock (this);
+    CHECK_READY();
+
+    *aDevice = mDevice;
+    return S_OK;
+}
+
Index: trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/MachineImpl.cpp	(revision 7441)
+++ trunk/src/VBox/Main/MachineImpl.cpp	(revision 7442)
@@ -40,4 +40,5 @@
 #include "VirtualBoxErrorInfoImpl.h"
 #include "GuestImpl.h"
+#include "SATAControllerImpl.h"
 
 #include "USBProxyService.h"
@@ -278,6 +279,7 @@
         while (thatIt != thatAtts.end())
         {
-            if ((*it)->deviceNumber() == (*thatIt)->deviceNumber() &&
-                (*it)->controller() == (*thatIt)->controller() &&
+            if ((*it)->bus() == (*thatIt)->bus() &&
+                (*it)->channel() == (*thatIt)->channel() &&
+                (*it)->device() == (*thatIt)->device() &&
                 (*it)->hardDisk().equalsTo ((*thatIt)->hardDisk()))
             {
@@ -1285,4 +1287,24 @@
 }
 
+STDMETHODIMP Machine::COMGETTER(SATAController) (ISATAController **aSATAController)
+{
+#ifdef VBOX_WITH_AHCI
+    if (!aSATAController)
+        return E_POINTER;
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReaderLock alock (this);
+
+    return mSATAController.queryInterfaceTo (aSATAController);
+#else
+    /* Note: The GUI depends on this method returning E_NOTIMPL with no
+     * extended error info to indicate that SATA is simply not available
+     * (w/o treting it as a failure), for example, as in OSE */
+    return E_NOTIMPL;
+#endif
+}
+
 STDMETHODIMP Machine::COMGETTER(SettingsFilePath) (BSTR *aFilePath)
 {
@@ -1602,13 +1624,11 @@
 
 STDMETHODIMP Machine::AttachHardDisk (INPTR GUIDPARAM aId,
-                                      DiskControllerType_T aCtl, LONG aDev)
+                                      StorageBus_T aBus, LONG aChannel, LONG aDevice)
 {
     Guid id = aId;
 
-    if (id.isEmpty() ||
-        aCtl == DiskControllerType_Null ||
-        aDev < 0 || aDev > 1)
+    if (id.isEmpty() || aBus == StorageBus_Null)
         return E_INVALIDARG;
-
+ 
     AutoCaller autoCaller (this);
     CheckComRCReturnRC (autoCaller.rc());
@@ -1635,12 +1655,12 @@
     {
         ComObjPtr <HardDiskAttachment> hda = *it;
-        if (hda->controller() == aCtl && hda->deviceNumber() == aDev)
+        if (hda->bus() == aBus && hda->channel() == aChannel && hda->device() == aDevice)
         {
             ComObjPtr <HardDisk> hd = hda->hardDisk();
             AutoLock hdLock (hd);
             return setError (E_FAIL,
-                tr ("Hard disk '%ls' is already attached to device slot %d "
-                    "on controller %d"),
-                hd->toString().raw(), aDev, aCtl);
+                tr ("Hard disk '%ls' is already attached to device slot %d on "
+                    "channel %d of bus %d"),
+                hd->toString().raw(), aDevice, aChannel, aBus);
         }
     }
@@ -1649,4 +1669,10 @@
     ComObjPtr <HardDisk> hd;
     rc = mParent->getHardDisk (id, hd);
+    CheckComRCReturnRC (rc);
+
+    /* create an attachment object early to let it check argiuments */
+    ComObjPtr <HardDiskAttachment> attachment;
+    attachment.createObject();
+    rc = attachment->init (hd, aBus, aChannel, aDevice, false /* aDirty */);
     CheckComRCReturnRC (rc);
 
@@ -1712,8 +1738,9 @@
                                 return setError (E_FAIL,
                                     tr ("Normal/Writethrough hard disk '%ls' is "
-                                        "currently attached to device slot %d "
-                                        "on controller %d of this machine"),
+                                        "currently attached to device slot %d on channel %d "
+                                        "of bus %d of this machine"),
                                     hd->toString().raw(),
-                                    (*it)->deviceNumber(), (*it)->controller());
+                                    (*it)->device(),
+                                    (*it)->channel(), (*it)->bus());
                             }
                         }
@@ -1757,7 +1784,5 @@
     }
 
-    ComObjPtr <HardDiskAttachment> attachment;
-    attachment.createObject();
-    attachment->init (hd, aCtl, aDev, dirty);
+    attachment->setDirty (dirty);
 
     mHDData.backup();
@@ -1770,11 +1795,10 @@
 }
 
-STDMETHODIMP Machine::GetHardDisk (DiskControllerType_T aCtl,
-                                   LONG aDev, IHardDisk **aHardDisk)
-{
-    if (aCtl == DiskControllerType_Null ||
-        aDev < 0 || aDev > 1)
+STDMETHODIMP Machine::GetHardDisk (StorageBus_T aBus, LONG aChannel,
+                                   LONG aDevice, IHardDisk **aHardDisk)
+{
+    if (aBus == StorageBus_Null)
         return E_INVALIDARG;
-
+ 
     AutoCaller autoCaller (this);
     CheckComRCReturnRC (autoCaller.rc());
@@ -1788,5 +1812,5 @@
     {
         ComObjPtr <HardDiskAttachment> hda = *it;
-        if (hda->controller() == aCtl && hda->deviceNumber() == aDev)
+        if (hda->bus() == aBus && hda->channel() == aChannel && hda->device() == aDevice)
         {
             hda->hardDisk().queryInterfaceTo (aHardDisk);
@@ -1796,12 +1820,11 @@
 
     return setError (E_INVALIDARG,
-        tr ("No hard disk attached to device slot %d on controller %d"),
-            aDev, aCtl);
-}
-
-STDMETHODIMP Machine::DetachHardDisk (DiskControllerType_T aCtl, LONG aDev)
-{
-    if (aCtl == DiskControllerType_Null ||
-        aDev < 0 || aDev > 1)
+        tr ("No hard disk attached to device slot %d on channel %d of bus %d"),
+            aDevice, aChannel, aBus);
+}
+
+STDMETHODIMP Machine::DetachHardDisk (StorageBus_T aBus, LONG aChannel, LONG aDevice)
+{
+    if (aBus == StorageBus_Null)
         return E_INVALIDARG;
 
@@ -1824,5 +1847,5 @@
     {
         ComObjPtr <HardDiskAttachment> hda = *it;
-        if (hda->controller() == aCtl && hda->deviceNumber() == aDev)
+        if (hda->bus() == aBus && hda->channel() == aChannel && hda->device() == aDevice)
         {
             ComObjPtr <HardDisk> hd = hda->hardDisk();
@@ -1889,6 +1912,6 @@
 
     return setError (E_INVALIDARG,
-        tr ("No hard disk attached to device slot %d on controller %d"),
-        aDev, aCtl);
+        tr ("No hard disk attached to device slot %d on channel %d of bus %d"),
+        aDevice, aChannel, aBus);
 }
 
@@ -3638,4 +3661,8 @@
     mUSBController->init (this);
 
+    /* create the SATA controller object (always present, default is disabled) */
+    unconst (mSATAController).createObject();
+    mSATAController->init (this);
+
     /* create associated network adapter objects */
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
@@ -3683,4 +3710,10 @@
         mUSBController->uninit();
         unconst (mUSBController).setNull();
+    }
+
+    if (mSATAController)
+    {
+        mSATAController->uninit();
+        unconst (mSATAController).setNull();
     }
 
@@ -4282,4 +4315,8 @@
     CheckComRCReturnRC (rc);
 
+    /* SATA Controller */
+    rc = mSATAController->loadSettings (aNode);
+    CheckComRCReturnRC (rc);
+
     /* Network node (required) */
     {
@@ -4460,7 +4497,9 @@
         Guid uuid = (*it).value <Guid> ("hardDisk");
         /* bus (controller) type (required) */
-        const char *bus = (*it).stringValue ("bus");
+        const char *busStr = (*it).stringValue ("bus");
+        /* channel (required) */
+        LONG channel = (*it).value <LONG> ("channel");
         /* device (required) */
-        const char *device = (*it).stringValue ("device");
+        LONG device = (*it).value <LONG> ("device");
 
         /* find a hard disk by UUID */
@@ -4491,29 +4530,13 @@
 
         /* attach the device */
-        DiskControllerType_T ctl = DiskControllerType_Null;
-        LONG dev = -1;
-
-        if (strcmp (bus, "ide0") == 0)
-        {
-            ctl = DiskControllerType_IDE0;
-            if (strcmp (device, "master") == 0)
-                dev = 0;
-            else if (strcmp (device, "slave") == 0)
-                dev = 1;
-            else
-                ComAssertMsgFailedRet (("Invalid device '%s'\n", device),
-                                       E_FAIL);
-        }
-        else if (strcmp (bus, "ide1") == 0)
-        {
-            ctl = DiskControllerType_IDE1;
-            if (strcmp (device, "master") == 0)
-                rc = setError (E_FAIL, tr("Could not attach a disk as a master "
-                                          "device on the secondary controller"));
-            else if (strcmp (device, "slave") == 0)
-                dev = 1;
-            else
-                ComAssertMsgFailedRet (("Invalid device '%s'\n", device),
-                                       E_FAIL);
+        StorageBus_T bus = StorageBus_Null;
+
+        if (strcmp (busStr, "IDE") == 0)
+        {
+            bus = StorageBus_IDE;
+        }
+        else if (strcmp (busStr, "SATA") == 0)
+        {
+            bus = StorageBus_SATA;
         }
         else
@@ -4523,5 +4546,5 @@
         ComObjPtr <HardDiskAttachment> attachment;
         attachment.createObject();
-        rc = attachment->init (hd, ctl, dev, false /* aDirty */);
+        rc = attachment->init (hd, bus, channel, device, false /* aDirty */);
         CheckComRCBreakRC (rc);
 
@@ -4536,5 +4559,5 @@
     }
 
-    return S_OK;
+    return rc;
 }
 
@@ -5659,4 +5682,8 @@
     CheckComRCReturnRC (rc);
 
+    /* SATA Controller (required) */
+    rc = mSATAController->saveSettings (aNode);
+    CheckComRCReturnRC (rc);
+
     /* Network adapters (required) */
     {
@@ -5793,24 +5820,16 @@
         {
             const char *bus = NULL;
-            switch (att->controller())
+            switch (att->bus())
             {
-                case DiskControllerType_IDE0: bus = "ide0"; break;
-                case DiskControllerType_IDE1: bus = "ide1"; break;
+                case StorageBus_IDE:  bus = "IDE"; break;
+                case StorageBus_SATA: bus = "SATA"; break;
                 default:
                     ComAssertFailedRet (E_FAIL);
             }
 
-            const char *dev = NULL;
-            switch (att->deviceNumber())
-            {
-                case 0: dev = "master"; break;
-                case 1: dev = "slave"; break;
-                default:
-                    ComAssertFailedRet (E_FAIL);
-            }
-
             hdNode.setValue <Guid> ("hardDisk", att->hardDisk()->id());
             hdNode.setStringValue ("bus", bus);
-            hdNode.setStringValue ("device", dev);
+            hdNode.setValue <LONG> ("channel", att->channel());
+            hdNode.setValue <LONG> ("device", att->device());
         }
     }
@@ -6073,6 +6092,7 @@
                          *  be used
                          */
-                        if ((*it)->deviceNumber() == hda->deviceNumber() &&
-                            (*it)->controller() == hda->controller())
+                        if ((*it)->device() == hda->device() &&
+                            (*it)->channel() == hda->channel() &&
+                            (*it)->bus() == hda->bus())
                         {
                             foundIt = it;
@@ -6095,6 +6115,7 @@
                                  ++ it2)
                             {
-                                if ((*it2)->deviceNumber() == (*it)->deviceNumber() &&
-                                    (*it2)->controller() == (*it)->controller() &&
+                                if ((*it2)->device() == (*it)->device() &&
+                                    (*it2)->channel() == (*it)->channel() &&
+                                    (*it2)->bus() == (*it)->bus() &&
                                     (*it2)->hardDisk()->root().equalsTo (hd))
                                 {
@@ -6165,6 +6186,7 @@
                                  *  be used
                                  */
-                                if ((*it)->deviceNumber() == hda->deviceNumber() &&
-                                    (*it)->controller() == hda->controller())
+                                if ((*it)->device() == hda->device() &&
+                                    (*it)->channel() == hda->channel() &&
+                                    (*it)->bus() == hda->bus())
                                 {
                                     foundIt = it;
@@ -6482,5 +6504,5 @@
             ComObjPtr <HardDiskAttachment> newHda;
             newHda.createObject();
-            rc = newHda->init (newHd, hda->controller(), hda->deviceNumber(),
+            rc = newHda->init (newHd, hda->bus(), hda->channel(), hda->device(),
                                false /* aDirty */);
 
@@ -6704,4 +6726,5 @@
         (mAudioAdapter && mAudioAdapter->isModified()) ||
         (mUSBController && mUSBController->isModified()) ||
+        (mSATAController && mSATAController->isModified()) ||
         (mBIOSSettings && mBIOSSettings->isModified());
 }
@@ -6746,4 +6769,5 @@
         (mAudioAdapter && mAudioAdapter->isReallyModified()) ||
         (mUSBController && mUSBController->isReallyModified()) ||
+        (mSATAController && mSATAController->isReallyModified()) ||
         (mBIOSSettings && mBIOSSettings->isReallyModified());
 }
@@ -6805,5 +6829,5 @@
 
     bool vrdpChanged = false, dvdChanged = false, floppyChanged = false,
-         usbChanged = false;
+         usbChanged = false, sataChanged = false;
 
     ComPtr <INetworkAdapter> networkAdapters [ELEMENTS (mNetworkAdapters)];
@@ -6830,4 +6854,7 @@
     if (mUSBController)
         usbChanged = mUSBController->rollback();
+
+    if (mSATAController)
+        sataChanged = mSATAController->rollback();
 
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
@@ -6864,4 +6891,6 @@
         if (usbChanged)
             that->onUSBControllerChange();
+        if (sataChanged)
+            that->onSATAControllerChange();
 
         for (ULONG slot = 0; slot < ELEMENTS (networkAdapters); slot ++)
@@ -6917,4 +6946,5 @@
     mAudioAdapter->commit();
     mUSBController->commit();
+    mSATAController->commit();
 
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
@@ -6982,4 +7012,5 @@
     mAudioAdapter->copyFrom (aThat->mAudioAdapter);
     mUSBController->copyFrom (aThat->mUSBController);
+    mSATAController->copyFrom (aThat->mSATAController);
 
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
@@ -7184,4 +7215,7 @@
     unconst (mUSBController).createObject();
     mUSBController->init (this, aMachine->mUSBController);
+    /* create another SATA controller object that will be mutable */
+    unconst (mSATAController).createObject();
+    mSATAController->init (this, aMachine->mSATAController);
     /* create a list of network adapters that will be mutable */
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
@@ -9783,4 +9817,7 @@
     mUSBController->initCopy (this, mPeer->mUSBController);
 
+    unconst (mSATAController).createObject();
+    mSATAController->initCopy (this, mPeer->mSATAController);
+
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
     {
@@ -9882,4 +9919,7 @@
     mUSBController->init (this);
 
+    unconst (mSATAController).createObject();
+    mSATAController->init (this);
+
     for (ULONG slot = 0; slot < ELEMENTS (mNetworkAdapters); slot ++)
     {
Index: trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/Makefile.kmk	(revision 7441)
+++ trunk/src/VBox/Main/Makefile.kmk	(revision 7442)
@@ -137,4 +137,7 @@
 ifdef VBOX_WITH_E1000
 VBoxSVC_DEFS += VBOX_WITH_E1000
+endif
+ifdef VBOX_WITH_AHCI
+VBoxSVC_DEFS += VBOX_WITH_AHCI
 endif
 ifdef VBOX_WITHOUT_LINUX_COMPILER_H
@@ -195,4 +198,5 @@
 	ParallelPortImpl.cpp \
 	USBControllerImpl.cpp \
+	SATAControllerImpl.cpp \
 	AudioAdapterImpl.cpp \
 	SharedFolderImpl.cpp \
Index: trunk/src/VBox/Main/SATAControllerImpl.cpp
===================================================================
--- trunk/src/VBox/Main/SATAControllerImpl.cpp	(revision 7442)
+++ trunk/src/VBox/Main/SATAControllerImpl.cpp	(revision 7442)
@@ -0,0 +1,444 @@
+/* $Id$ */
+
+/** @file
+ *
+ * Implementation of ISATAController.
+ */
+
+/*
+ * Copyright (C) 2008 innotek GmbH
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+
+#include "SATAControllerImpl.h"
+#include "MachineImpl.h"
+#include "VirtualBoxImpl.h"
+#include "Logging.h"
+
+#include <iprt/string.h>
+#include <iprt/cpputils.h>
+#include <VBox/err.h>
+
+#include <algorithm>
+
+// defines
+/////////////////////////////////////////////////////////////////////////////
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR (SATAController)
+
+HRESULT SATAController::FinalConstruct()
+{
+    return S_OK;
+}
+
+void SATAController::FinalRelease()
+{
+    uninit();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Initializes the USB controller object.
+ *
+ * @returns COM result indicator.
+ * @param aParent       Pointer to our parent object.
+ */
+HRESULT SATAController::init (Machine *aParent)
+{
+    LogFlowThisFunc (("aParent=%p\n", aParent));
+
+    ComAssertRet (aParent, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan (this);
+    AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
+
+    unconst (mParent) = aParent;
+    /* mPeer is left null */
+
+    mData.allocate();
+
+    /* Confirm a successful initialization */
+    autoInitSpan.setSucceeded();
+
+    return S_OK;
+}
+
+
+/**
+ * Initializes the SATA controller object given another SATA controller object
+ * (a kind of copy constructor). This object shares data with
+ * the object passed as an argument.
+ *
+ * @returns COM result indicator.
+ * @param aParent       Pointer to our parent object.
+ * @param aPeer         The object to share.
+ *
+ * @note This object must be destroyed before the original object
+ * it shares data with is destroyed.
+ */
+HRESULT SATAController::init (Machine *aParent, SATAController *aPeer)
+{
+    LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
+
+    ComAssertRet (aParent && aPeer, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan (this);
+    AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
+
+    unconst (mParent) = aParent;
+    unconst (mPeer) = aPeer;
+
+    AutoLock thatlock (aPeer);
+    mData.share (aPeer->mData);
+
+    /* Confirm a successful initialization */
+    autoInitSpan.setSucceeded();
+
+    return S_OK;
+}
+
+
+/**
+ *  Initializes the SATA controller object given another guest object
+ *  (a kind of copy constructor). This object makes a private copy of data
+ *  of the original object passed as an argument.
+ */
+HRESULT SATAController::initCopy (Machine *aParent, SATAController *aPeer)
+{
+    LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
+
+    ComAssertRet (aParent && aPeer, E_INVALIDARG);
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan (this);
+    AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
+
+    unconst (mParent) = aParent;
+    /* mPeer is left null */
+
+    AutoLock thatlock (aPeer);
+    mData.attachCopy (aPeer->mData);
+
+    /* Confirm a successful initialization */
+    autoInitSpan.setSucceeded();
+
+    return S_OK;
+}
+
+
+/**
+ * Uninitializes the instance and sets the ready flag to FALSE.
+ * Called either from FinalRelease() or by the parent when it gets destroyed.
+ */
+void SATAController::uninit()
+{
+    LogFlowThisFunc (("\n"));
+
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan (this);
+    if (autoUninitSpan.uninitDone())
+        return;
+
+    /* uninit all filters (including those still referenced by clients) */
+    uninitDependentChildren();
+
+    mData.free();
+
+    unconst (mPeer).setNull();
+    unconst (mParent).setNull();
+}
+
+
+// ISATAController properties
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP SATAController::COMGETTER(Enabled) (BOOL *aEnabled)
+{
+    if (!aEnabled)
+        return E_POINTER;
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReaderLock alock (this);
+
+    *aEnabled = mData->mEnabled;
+
+    return S_OK;
+}
+
+
+STDMETHODIMP SATAController::COMSETTER(Enabled) (BOOL aEnabled)
+{
+    LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    /* the machine needs to be mutable */
+    Machine::AutoMutableStateDependency adep (mParent);
+    CheckComRCReturnRC (adep.rc());
+
+    AutoLock alock (this);
+
+    if (mData->mEnabled != aEnabled)
+    {
+        mData.backup();
+        mData->mEnabled = aEnabled;
+
+        /* leave the lock for safety */
+        alock.leave();
+
+        mParent->onSATAControllerChange();
+    }
+
+    return S_OK;
+}
+
+// ISATAController methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP SATAController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
+{
+    if (!aPortNumber)
+        return E_POINTER;
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    /* the machine needs to be mutable */
+    Machine::AutoMutableStateDependency adep (mParent);
+    CheckComRCReturnRC (adep.rc());
+    AutoLock alock (this);
+
+    switch (DevicePosition)
+    {
+        case 0:
+            *aPortNumber = mData->mPortIde0Master;
+            break;
+        case 1:
+            *aPortNumber = mData->mPortIde0Slave;
+            break;
+        case 2:
+            *aPortNumber = mData->mPortIde1Master;
+            break;
+        case 3:
+            *aPortNumber = mData->mPortIde1Slave;
+            break;
+        default:
+            return E_INVALIDARG;
+    }
+
+    return S_OK;
+}
+
+STDMETHODIMP SATAController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
+{
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    /* the machine needs to be mutable */
+    Machine::AutoMutableStateDependency adep (mParent);
+    CheckComRCReturnRC (adep.rc());
+    AutoLock alock (this);
+
+    switch (DevicePosition)
+    {
+        case 0:
+            mData->mPortIde0Master = aPortNumber;
+            break;
+        case 1:
+            mData->mPortIde0Slave = aPortNumber;
+            break;
+        case 2:
+            mData->mPortIde1Master = aPortNumber;
+            break;
+        case 3:
+            mData->mPortIde1Slave = aPortNumber;
+            break;
+        default:
+            return E_INVALIDARG;
+    }
+
+    return S_OK;
+}
+
+
+// public methods only for internal purposes
+/////////////////////////////////////////////////////////////////////////////
+
+/** 
+ *  Loads settings from the given machine node.
+ *  May be called once right after this object creation.
+ * 
+ *  @param aMachineNode <Machine> node.
+ * 
+ *  @note Locks this object for writing. 
+ */
+HRESULT SATAController::loadSettings (const settings::Key &aMachineNode)
+{
+    using namespace settings;
+
+    AssertReturn (!aMachineNode.isNull(), E_FAIL);
+
+    AutoCaller autoCaller (this);
+    AssertComRCReturnRC (autoCaller.rc());
+
+    AutoLock alock (this);
+
+    /* SATA Controller node (required) */
+    Key controller = aMachineNode.key ("SATAController");
+
+    /* enabled (required) */
+    mData->mEnabled = controller.value <bool> ("enabled");
+
+    /* ide emulation settings (optional, default to 0,1,2,3 respectively) */
+    mData->mPortIde0Master = controller.value <ULONG> ("IDE0MasterEmulationPort");
+    mData->mPortIde0Slave = controller.value <ULONG> ("IDE0SlaveEmulationPort");
+    mData->mPortIde1Master = controller.value <ULONG> ("IDE1MasterEmulationPort");
+    mData->mPortIde1Slave = controller.value <ULONG> ("IDE1SlaveEmulationPort");
+
+    return S_OK;
+}
+
+/** 
+ *  Saves settings to the given machine node.
+ * 
+ *  @param aMachineNode <Machine> node.
+ * 
+ *  @note Locks this object for reading.
+ */
+HRESULT SATAController::saveSettings (settings::Key &aMachineNode)
+{
+    using namespace settings;
+
+    AssertReturn (!aMachineNode.isNull(), E_FAIL);
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReaderLock alock (this);
+
+    /* first, delete the entry */
+    Key controller = aMachineNode.findKey ("SATAController");
+    if (!controller.isNull())
+        controller.zap();
+    /* then, recreate it */
+    controller = aMachineNode.createKey ("SATAController");
+
+    /* enabled */
+    controller.setValue <bool> ("enabled", !!mData->mEnabled);
+
+    /* ide emulation settings */
+    controller.setValue <ULONG> ("IDE0MasterEmulationPort", mData->mPortIde0Master);
+    controller.setValue <ULONG> ("IDE0SlaveEmulationPort", mData->mPortIde0Slave);
+    controller.setValue <ULONG> ("IDE1MasterEmulationPort", mData->mPortIde1Master);
+    controller.setValue <ULONG> ("IDE1SlaveEmulationPort", mData->mPortIde1Slave);
+
+    return S_OK;
+}
+
+/** @note Locks objects for reading! */
+bool SATAController::isModified()
+{
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), false);
+
+    AutoReaderLock alock (this);
+
+    if (mData.isBackedUp())
+        return true;
+
+    return false;
+}
+
+/** @note Locks objects for reading! */
+bool SATAController::isReallyModified()
+{
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), false);
+
+    AutoReaderLock alock (this);
+
+    if (mData.hasActualChanges())
+        return true;
+
+    return false;
+}
+
+/** @note Locks objects for writing! */
+bool SATAController::rollback()
+{
+    AutoCaller autoCaller (this);
+    AssertComRCReturn (autoCaller.rc(), false);
+
+    /* we need the machine state */
+    Machine::AutoAnyStateDependency adep (mParent);
+    AssertComRCReturn (adep.rc(), false);
+
+    AutoLock alock (this);
+
+    bool dataChanged = false;
+
+    if (mData.isBackedUp())
+    {
+        /* we need to check all data to see whether anything will be changed
+         * after rollback */
+        dataChanged = mData.hasActualChanges();
+        mData.rollback();
+    }
+
+    return dataChanged;
+}
+
+/** @note Locks objects for writing! */
+void SATAController::commit()
+{
+    AutoCaller autoCaller (this);
+    AssertComRCReturnVoid (autoCaller.rc());
+
+    AutoLock alock (this);
+
+    if (mData.isBackedUp())
+    {
+        mData.commit();
+        if (mPeer)
+        {
+            // attach new data to the peer and reshare it
+            AutoLock peerlock (mPeer);
+            mPeer->mData.attach (mData);
+        }
+    }
+}
+
+/** @note Locks object for writing and that object for reading! */
+void SATAController::copyFrom (SATAController *aThat)
+{
+    AutoCaller autoCaller (this);
+    AssertComRCReturnVoid (autoCaller.rc());
+
+    AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
+
+    /* this will back up current data */
+    mData.assignCopy (aThat->mData);
+}
+
+// private methods
+/////////////////////////////////////////////////////////////////////////////
+
Index: trunk/src/VBox/Main/VirtualBoxImplExtra.cpp
===================================================================
--- trunk/src/VBox/Main/VirtualBoxImplExtra.cpp	(revision 7441)
+++ trunk/src/VBox/Main/VirtualBoxImplExtra.cpp	(revision 7442)
@@ -31,4 +31,26 @@
 #include "xml_SettingsConverter_xsl.h"
 
+static const unsigned char g_ab_xml_VirtualBox_settings_root_xsd[] =
+"<xsd:schema"
+"  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+"  xmlns=\"http://www.innotek.de/VirtualBox-settings\"" 
+"  xmlns:vb=\"http://www.innotek.de/VirtualBox-settings\""
+"  targetNamespace=\"http://www.innotek.de/VirtualBox-settings\""
+"  elementFormDefault=\"qualified\""
+">"
+"<xsd:element name=\"VirtualBox\">"
+"  <xsd:complexType>"
+"    <xsd:complexContent>"
+"      <xsd:extension base=\"TVirtualBox\">"
+"        <xsd:attribute name=\"version\" type=\"xsd:token\" fixed=\"" VBOX_XML_VERSION_FULL "\" use=\"required\"/>"
+"      </xsd:extension>"
+"    </xsd:complexContent>"
+"  </xsd:complexType>"
+"</xsd:element>"
+"</xsd:schema>";
+
+static const unsigned g_cb_xml_VirtualBox_settings_root_xsd =
+    sizeof (g_ab_xml_VirtualBox_settings_root_xsd);
+
 /**
  * Resolves external entities while parting and validating XML settings files.
@@ -48,4 +70,11 @@
             MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_common_xsd,
                        g_cb_xml_VirtualBox_settings_common_xsd, aURI);
+    }
+
+    if (strcmp (aURI, VBOX_XML_SCHEMA_ROOT) == 0)
+    {
+        return new settings::
+            MemoryBuf ((const char *) g_ab_xml_VirtualBox_settings_root_xsd,
+                       g_cb_xml_VirtualBox_settings_root_xsd, aURI);
     }
 
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 7441)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 7442)
@@ -385,16 +385,15 @@
 
   <enum
-    name="DiskControllerType"
-    uuid="1115b810-2ee7-4ebd-8b39-92e98c9a2b48"
+    name="StorageBus"
+    uuid="715984a5-093c-43bb-aa42-a16ed16828dd"
   >
-    <desc>
-      Disk controller type for hard disk attachments.
-    </desc>
+    <desc>Interface bus type for storage devices.</desc>
 
     <const name="Null"              value="0">
       <desc><tt>null</tt> value. Never used by the API.</desc>
     </const>
-    <const name="IDE0"              value="1"/>
-    <const name="IDE1"              value="2"/>
+
+    <const name="IDE"      value="1"/>
+    <const name="SATA"     value="2"/>
   </enum>
 
@@ -2772,4 +2771,10 @@
     </attribute>
 
+    <attribute name="SATAController" type="ISATAController" readonly="yes">
+      <desc>
+        Associated SATA controller object.
+      </desc>
+    </attribute>
+
     <attribute name="settingsFilePath" type="wstring" readonly="yes">
       <desc>
@@ -3029,7 +3034,7 @@
 
         Attaches a virtual hard disk identified by the given UUID to the
-        given device slot of the given controller. The specified device
-        must not have another disk attached and the given hard disk must
-        not be already attached to this machine.
+        given device slot of the given channel on the given bus. The
+        specified device slot must not have another disk attached and the
+        given hard disk must not be already attached to this machine.
 
         See <link to="IHardDisk"/> for detailed information about
@@ -3046,9 +3051,12 @@
 
       </desc>
-      <param name="diskID" type="uuid" dir="in">
+      <param name="id" type="uuid" dir="in">
         <desc>UUID of the hard disk to attach.</desc>
       </param>
-      <param name="controller" type="DiskControllerType" dir="in">
+      <param name="bus" type="StorageBus" dir="in">
         <desc>Controller to attach the hard disk to.</desc>
+      </param>
+      <param name="channel" type="long" dir="in">
+        <desc>Device slot to attach the hard disk to.</desc>
       </param>
       <param name="device" type="long" dir="in">
@@ -3062,6 +3070,7 @@
         given controller under the specified device number.
       </desc>
-      <param name="controller" type="DiskControllerType" dir="in"/>
-      <param name="deviceNumber" type="long" dir="in"/>
+      <param name="bus" type="StorageBus" dir="in"/>
+      <param name="channel" type="long" dir="in"/>
+      <param name="device" type="long" dir="in"/>
       <param name="hardDisk" type="IHardDisk" dir="return"/>
     </method>
@@ -3090,9 +3099,12 @@
 
       </desc>
-      <param name="controller" type="DiskControllerType" dir="in">
-        <desc>Controller to dettach the hard disk from.</desc>
+      <param name="bus" type="StorageBus" dir="in">
+        <desc>Bus to dettach the hard disk from.</desc>
+      </param>
+      <param name="channel" type="long" dir="in">
+        <desc>Channel number to dettach the hard disk from.</desc>
       </param>
       <param name="device" type="long" dir="in">
-        <desc>Device slot to dettach the hard disk from.</desc>
+        <desc>Device slot number to dettach the hard disk from.</desc>
       </param>
     </method>
@@ -5711,10 +5723,14 @@
     </attribute>
 
-    <attribute name="controller" type="DiskControllerType" readonly="yes">
+    <attribute name="bus" type="StorageBus" readonly="yes">
       <desc>Disk controller ID of this attachment.</desc>
     </attribute>
 
-    <attribute name="deviceNumber" type="long" readonly="yes">
-      <desc>Device number of the attachment.</desc>
+    <attribute name="channel" type="long" readonly="yes">
+      <desc>Channel number of the attachment.</desc>
+    </attribute>
+
+    <attribute name="device" type="long" readonly="yes">
+      <desc>Device slot number of the attachment.</desc>
     </attribute>
 
@@ -9739,4 +9755,37 @@
   </interface>
 
+  <!--
+  // ISATAController
+  /////////////////////////////////////////////////////////////////////////
+  -->
+
+  <interface
+    name="ISATAController" extends="$unknown"
+    uuid="9a4b868b-1376-4533-8ef5-065b8e8cedff"
+    wsmap="managed"
+  >
+    <attribute name="enabled" type="boolean">
+      <desc>
+        Flag whether the SATA controller is present in the
+        guest system. If disabled, the virtual guest hardware will
+        not contain any SATA controller. Can only be changed when
+        the VM is powered off.
+      </desc>
+    </attribute>
+
+    <method name="GetIDEEmulationPort">
+      <desc>Gets the corresponding port number which is emulated as an IDE device.</desc>
+      <param name="devicePosition" type="long" dir="in"/>
+      <param name="portNumber" type="long" dir="return"/>
+    </method>
+
+    <method name="SetIDEEmulationPort">
+      <desc>Sets the port number which is emulated as an IDE device.</desc>
+      <param name="devicePosition" type="long" dir="in"/>
+      <param name="portNumber" type="long" dir="in"/>
+    </method>
+
+  </interface>
+
 <if target="wsdl">
 
Index: trunk/src/VBox/Main/include/HardDiskAttachmentImpl.h
===================================================================
--- trunk/src/VBox/Main/include/HardDiskAttachmentImpl.h	(revision 7441)
+++ trunk/src/VBox/Main/include/HardDiskAttachmentImpl.h	(revision 7442)
@@ -49,20 +49,23 @@
 
     // public initializer/uninitializer for internal purposes only
-    HRESULT init (HardDisk *aHD, DiskControllerType_T aCtl, LONG aDev, BOOL aDirty);
+    HRESULT init (HardDisk *aHD, StorageBus_T aBus, LONG aChannel, LONG aDevice, BOOL aDirty);
 
     // IHardDiskAttachment properties
-    STDMETHOD(COMGETTER(HardDisk)) (IHardDisk **aHardDisk);
-    STDMETHOD(COMGETTER(Controller)) (DiskControllerType_T *aController);
-    STDMETHOD(COMGETTER(DeviceNumber)) (LONG *aDeviceNumber);
+    STDMETHOD(COMGETTER(HardDisk))   (IHardDisk **aHardDisk);
+    STDMETHOD(COMGETTER(Bus))        (StorageBus_T *aBus);
+    STDMETHOD(COMGETTER(Channel))    (LONG *aChannel);
+    STDMETHOD(COMGETTER(Device))     (LONG *aDevice);
 
     // public methods for internal purposes only
+    // (ensure there is a caller and a read or write lock before calling them!)
 
     BOOL isDirty() const { return mDirty; }
+    void setDirty (BOOL aDirty) { mDirty = aDirty; }
 
     const ComObjPtr <HardDisk> &hardDisk() const { return mHardDisk; }
-    DiskControllerType_T controller() const { return mController; }
-    LONG deviceNumber() const { return mDeviceNumber; }
+    StorageBus_T bus() const { return mBus; }
+    LONG channel() const { return mChannel; }
+    LONG device() const { return mDevice; }
 
-    /** @note Don't forget to lock this object! */
     void updateHardDisk (const ComObjPtr <HardDisk> &aHardDisk, BOOL aDirty)
     {
@@ -78,6 +81,7 @@
     BOOL mDirty;
     ComObjPtr <HardDisk> mHardDisk;
-    DiskControllerType_T mController;
-    LONG mDeviceNumber;
+    StorageBus_T mBus;
+    LONG mChannel;
+    LONG mDevice;
 };
 
Index: trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- trunk/src/VBox/Main/include/MachineImpl.h	(revision 7441)
+++ trunk/src/VBox/Main/include/MachineImpl.h	(revision 7442)
@@ -34,4 +34,5 @@
 #include "ParallelPortImpl.h"
 #include "BIOSSettingsImpl.h"
+#include "SATAControllerImpl.h"
 
 // generated header
@@ -466,4 +467,5 @@
     STDMETHOD(COMGETTER(AudioAdapter))(IAudioAdapter **audioAdapter);
     STDMETHOD(COMGETTER(USBController)) (IUSBController * *aUSBController);
+    STDMETHOD(COMGETTER(SATAController)) (ISATAController **aSATAController);
     STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aFilePath);
     STDMETHOD(COMGETTER(SettingsFileVersion)) (BSTR *aSettingsFileVersion);
@@ -486,7 +488,7 @@
     STDMETHOD(SetBootOrder)(ULONG aPosition, DeviceType_T aDevice);
     STDMETHOD(GetBootOrder)(ULONG aPosition, DeviceType_T *aDevice);
-    STDMETHOD(AttachHardDisk)(INPTR GUIDPARAM aId, DiskControllerType_T aCtl, LONG aDev);
-    STDMETHOD(GetHardDisk)(DiskControllerType_T aCtl, LONG aDev, IHardDisk **aHardDisk);
-    STDMETHOD(DetachHardDisk) (DiskControllerType_T aCtl, LONG aDev);
+    STDMETHOD(AttachHardDisk)(INPTR GUIDPARAM aId, StorageBus_T aBus, LONG aChannel, LONG aDevice);
+    STDMETHOD(GetHardDisk)(StorageBus_T aBus, LONG aChannel, LONG aDevice, IHardDisk **aHardDisk);
+    STDMETHOD(DetachHardDisk) (StorageBus_T aBus, LONG aChannel, LONG aDevice);
     STDMETHOD(GetSerialPort) (ULONG slot, ISerialPort **port);
     STDMETHOD(GetParallelPort) (ULONG slot, IParallelPort **port);
@@ -560,4 +562,5 @@
     virtual HRESULT onVRDPServerChange() { return S_OK; }
     virtual HRESULT onUSBControllerChange() { return S_OK; }
+    virtual HRESULT onSATAControllerChange() { return S_OK; }
     virtual HRESULT onSharedFolderChange() { return S_OK; }
 
@@ -719,4 +722,5 @@
     const ComObjPtr <AudioAdapter> mAudioAdapter;
     const ComObjPtr <USBController> mUSBController;
+    const ComObjPtr <SATAController> mSATAController;
     const ComObjPtr <BIOSSettings> mBIOSSettings;
     const ComObjPtr <NetworkAdapter>
Index: trunk/src/VBox/Main/include/SATAControllerImpl.h
===================================================================
--- trunk/src/VBox/Main/include/SATAControllerImpl.h	(revision 7442)
+++ trunk/src/VBox/Main/include/SATAControllerImpl.h	(revision 7442)
@@ -0,0 +1,138 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VBox SATAController COM Class declaration.
+ */
+
+/*
+ * Copyright (C) 2008 innotek GmbH
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_SATACONTROLLERIMPL
+#define ____H_SATACONTROLLERIMPL
+
+#include "VirtualBoxBase.h"
+
+#include <list>
+
+class Machine;
+
+class ATL_NO_VTABLE SATAController :
+    public VirtualBoxBaseWithChildrenNEXT,
+    public VirtualBoxSupportErrorInfoImpl <SATAController, ISATAController>,
+    public VirtualBoxSupportTranslation <SATAController>,
+    public ISATAController
+{
+private:
+
+    struct Data
+    {
+        /* Constructor. */
+        Data() : mEnabled (FALSE),
+                 mPortIde0Master (0),
+                 mPortIde0Slave (1),
+                 mPortIde1Master (2),
+                 mPortIde1Slave (3) { }
+
+        bool operator== (const Data &that) const
+        {
+            return this == &that || ((mEnabled == that.mEnabled) &&
+                    (mPortIde0Master == that.mPortIde0Master) &&
+                    (mPortIde0Slave  == that.mPortIde0Slave)  &&
+                    (mPortIde1Master == that.mPortIde1Master) &&
+                    (mPortIde1Slave  == that.mPortIde1Slave));
+        }
+
+        /** Enabled indicator. */
+        BOOL  mEnabled;
+        /** Port which acts as primary master for ide emulation. */
+        ULONG mPortIde0Master;
+        /** Port which acts as primary slave for ide emulation. */
+        ULONG mPortIde0Slave;
+        /** Port which acts as secondary master for ide emulation. */
+        ULONG mPortIde1Master;
+        /** Port which acts as secondary slave for ide emulation. */
+        ULONG mPortIde1Slave;
+    };
+
+public:
+
+    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (SATAController)
+
+    DECLARE_NOT_AGGREGATABLE (SATAController)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+    BEGIN_COM_MAP(SATAController)
+        COM_INTERFACE_ENTRY (ISupportErrorInfo)
+        COM_INTERFACE_ENTRY (ISATAController)
+    END_COM_MAP()
+
+    NS_DECL_ISUPPORTS
+
+    DECLARE_EMPTY_CTOR_DTOR (SATAController)
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    // public initializer/uninitializer for internal purposes only
+    HRESULT init (Machine *aParent);
+    HRESULT init (Machine *aParent, SATAController *aThat);
+    HRESULT initCopy (Machine *aParent, SATAController *aThat);
+    void uninit();
+
+    // ISATAController properties
+    STDMETHOD(COMGETTER(Enabled)) (BOOL *aEnabled);
+    STDMETHOD(COMSETTER(Enabled)) (BOOL aEnabled);
+
+    // ISATAController methods
+    STDMETHOD(GetIDEEmulationPort) (LONG DevicePosition, LONG *aPortNumber);
+    STDMETHOD(SetIDEEmulationPort) (LONG DevicePosition, LONG aPortNumber);
+
+    // public methods only for internal purposes
+
+    HRESULT loadSettings (const settings::Key &aMachineNode);
+    HRESULT saveSettings (settings::Key &aMachineNode);
+
+    bool isModified();
+    bool isReallyModified();
+    bool rollback();
+    void commit();
+    void copyFrom (SATAController *aThat);
+
+    HRESULT onMachineRegistered (BOOL aRegistered);
+
+    // public methods for internal purposes only
+    // (ensure there is a caller and a read lock before calling them!)
+
+    /** @note this doesn't require a read lock since mParent is constant. */
+    const ComObjPtr <Machine, ComWeakRef> &parent() { return mParent; };
+
+    const Backupable<Data> &data() { return mData; }
+
+    // for VirtualBoxSupportErrorInfoImpl
+    static const wchar_t *getComponentName() { return L"SATAController"; }
+
+private:
+
+    void printList();
+
+    /** Parent object. */
+    const ComObjPtr<Machine, ComWeakRef> mParent;
+    /** Peer object. */
+    const ComObjPtr <SATAController> mPeer;
+    /** Data. */
+    Backupable <Data> mData;
+
+};
+
+#endif //!____H_SATACONTROLLERIMPL
Index: trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h
===================================================================
--- trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h	(revision 7441)
+++ trunk/src/VBox/Main/include/VirtualBoxXMLUtil.h	(revision 7442)
@@ -25,5 +25,5 @@
 
 /** VirtualBox XML settings version number substring ("x.y")  */
-#define VBOX_XML_VERSION "1.2"
+#define VBOX_XML_VERSION        "1.3.pre"
 
 /** VirtualBox XML settings version platform substring */
@@ -51,10 +51,10 @@
 #define VBOX_XML_VERSION_FULL   VBOX_XML_VERSION "-" VBOX_XML_PLATFORM
 
-/** VirtualBox XML common settings version string */
-#define VBOX_XML_PLATFORM_COMMON  "common"
-
-/** VirtualBox XML settings schema file */
+/** VirtualBox XML settings platform-specific (main) schema file */
 #define VBOX_XML_SCHEMA         "VirtualBox-settings-" VBOX_XML_PLATFORM ".xsd"
-#define VBOX_XML_SCHEMA_COMMON  "VirtualBox-settings-" VBOX_XML_PLATFORM_COMMON ".xsd"
+/** VirtualBox XML settings common schema include file */
+#define VBOX_XML_SCHEMA_COMMON  "VirtualBox-settings-common.xsd"
+/** VirtualBox XML settings root element schema include file */
+#define VBOX_XML_SCHEMA_ROOT    "VirtualBox-settings-root.xsd"
 
 /** VirtualBox XML settings converter file */
Index: trunk/src/VBox/Main/linux/server.cpp
===================================================================
--- trunk/src/VBox/Main/linux/server.cpp	(revision 7441)
+++ trunk/src/VBox/Main/linux/server.cpp	(revision 7442)
@@ -97,4 +97,5 @@
 #include <USBControllerImpl.h>
 #include <USBDeviceImpl.h>
+#include <SATAControllerImpl.h>
 #include <AudioAdapterImpl.h>
 #include <SystemPropertiesImpl.h>
@@ -160,4 +161,6 @@
 NS_DECL_CLASSINFO(USBController)
 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(USBController, IUSBController)
+NS_DECL_CLASSINFO(SATAController)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SATAController, ISATAController)
 NS_DECL_CLASSINFO(USBDeviceFilter)
 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(USBDeviceFilter, IUSBDeviceFilter)
Index: trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
===================================================================
--- trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 7441)
+++ trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 7442)
@@ -366,6 +366,7 @@
                     hardDisk->GetId(&vdiUUID);
                     rc = machine->AttachHardDisk(*vdiUUID,
-                                                DiskControllerType::IDE0, // controler identifier
-                                                0);                       // device number on the controller
+                                                StorageBus::IDE, // controler identifier
+                                                0,               // channel number on the controller
+                                                0);              // device number on the controller
                     nsMemory::Free(vdiUUID);
                     if (NS_FAILED(rc))
Index: trunk/src/VBox/Main/xml/SchemaDefs.xsl
===================================================================
--- trunk/src/VBox/Main/xml/SchemaDefs.xsl	(revision 7441)
+++ trunk/src/VBox/Main/xml/SchemaDefs.xsl	(revision 7442)
@@ -92,61 +92,64 @@
   <!-- process include statements -->
   <xsl:for-each select="xsd:include">
-    <xsl:apply-templates select="document(@schemaLocation)/xsd:schema"/>
+    <!-- skip VirtualBox-settings-root.xsd inclusion as it is computed at runtime -->
+    <xsl:if test="not(@schemaLocation='VirtualBox-settings-root.xsd')">
+      <xsl:apply-templates select="document(@schemaLocation)/xsd:schema"/>
+    </xsl:if>
   </xsl:for-each>
 
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MinGuestRAM'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TMemory']/xsd:attribute[@name='RAMSize']//xsd:minInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MinGuestRAM'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TMemory']/xsd:attribute[@name='RAMSize']//xsd:minInclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MaxGuestRAM'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TMemory']/xsd:attribute[@name='RAMSize']//xsd:maxInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MaxGuestRAM'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TMemory']/xsd:attribute[@name='RAMSize']//xsd:maxInclusive/@value
+    "/>
   </xsl:call-template>
 
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MinGuestVRAM'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TDisplay']/xsd:attribute[@name='VRAMSize']//xsd:minInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MinGuestVRAM'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TDisplay']/xsd:attribute[@name='VRAMSize']//xsd:minInclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MaxGuestVRAM'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TDisplay']/xsd:attribute[@name='VRAMSize']//xsd:maxInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MaxGuestVRAM'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TDisplay']/xsd:attribute[@name='VRAMSize']//xsd:maxInclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MaxGuestMonitors'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TDisplay']/xsd:attribute[@name='MonitorCount']//xsd:maxInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MaxGuestMonitors'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TDisplay']/xsd:attribute[@name='MonitorCount']//xsd:maxInclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        NetworkAdapterCount'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TNetworkAdapter']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        NetworkAdapterCount'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TNetworkAdapter']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        SerialPortCount'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TUartPort']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        SerialPortCount'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TUartPort']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        ParallelPortCount'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TLptPort']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        ParallelPortCount'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TLptPort']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
+    "/>
   </xsl:call-template>
   <xsl:call-template name="defineEnumMember">
-      <xsl:with-param name="member" select="'        MaxBootPosition'"/>
-      <xsl:with-param name="select" select="
-        xsd:complexType[@name='TBoot']//xsd:element[@name='Order']//xsd:attribute[@name='position']//xsd:maxInclusive/@value
-      "/>
+    <xsl:with-param name="member" select="'        MaxBootPosition'"/>
+    <xsl:with-param name="select" select="
+      xsd:complexType[@name='TBoot']//xsd:element[@name='Order']//xsd:attribute[@name='position']//xsd:maxInclusive/@value
+    "/>
   </xsl:call-template>
 
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 7442)
@@ -498,17 +498,11 @@
     <xsd:simpleType>
       <xsd:restriction base="xsd:token">
-        <xsd:enumeration value="ide0"/>
-        <xsd:enumeration value="ide1"/>
-      </xsd:restriction>
-    </xsd:simpleType>
-  </xsd:attribute>
-  <xsd:attribute name="device" use="required">
-    <xsd:simpleType>
-      <xsd:restriction base="xsd:token">
-        <xsd:enumeration value="master"/>
-        <xsd:enumeration value="slave"/>
-      </xsd:restriction>
-    </xsd:simpleType>
-  </xsd:attribute>
+        <xsd:enumeration value="IDE"/>
+        <xsd:enumeration value="SATA"/>
+      </xsd:restriction>
+    </xsd:simpleType>
+  </xsd:attribute>
+  <xsd:attribute name="channel" type="xsd:unsignedInt" use="required"/>
+  <xsd:attribute name="device" type="xsd:unsignedInt" default="0"/>
 </xsd:complexType>
 
@@ -658,4 +652,12 @@
   <xsd:attribute name="MemoryBalloonSize"        type="xsd:unsignedInt" default="0"/>
   <xsd:attribute name="StatisticsUpdateInterval" type="xsd:unsignedInt" default="0"/>
+</xsd:complexType>
+
+<xsd:complexType name="TSATAController">
+  <xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
+  <xsd:attribute name="IDE0MasterEmulationPort" type="xsd:unsignedInt" default="0"/>
+  <xsd:attribute name="IDE0SlaveEmulationPort" type="xsd:unsignedInt" default="1"/>
+  <xsd:attribute name="IDE1MasterEmulationPort" type="xsd:unsignedInt" default="2"/>
+  <xsd:attribute name="IDE1SlaveEmulationPort" type="xsd:unsignedInt" default="3"/>
 </xsd:complexType>
 
@@ -676,4 +678,5 @@
     <xsd:element name="FloppyDrive" type="TFloppyDrive"/>
     <xsd:element name="USBController" type="TUSBController"/>
+    <xsd:element name="SATAController" type="TSATAController"/>
     <xsd:element name="Network" type="TNetwork">
       <xsd:unique name="THardware-Network-Adapter">
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-freebsd.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (freebsd).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -102,18 +109,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-freebsd" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-linux.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-linux.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-linux.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-linux.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (linux).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -103,18 +110,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-linux" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-macosx.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (macosx).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -101,18 +108,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-macosx" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-os2.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-os2.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-os2.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-os2.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (os2).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -101,18 +108,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-os2" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-solaris.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (solaris).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -101,18 +108,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-solaris" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
Index: trunk/src/VBox/Main/xml/VirtualBox-settings-windows.xsd
===================================================================
--- trunk/src/VBox/Main/xml/VirtualBox-settings-windows.xsd	(revision 7441)
+++ trunk/src/VBox/Main/xml/VirtualBox-settings-windows.xsd	(revision 7442)
@@ -27,10 +27,17 @@
 <xsd:annotation>
   <xsd:documentation xml:lang="en">
-    innotek VirtualBox Settings Schema Version 1.0-windows.
-    Copyright (c) 2004-2007 innotek GmbH.
+    innotek VirtualBox Settings Schema (windows).
+    Copyright (c) 2004-2008 innotek GmbH.
   </xsd:documentation>
 </xsd:annotation>
 
 <xsd:include schemaLocation="VirtualBox-settings-common.xsd"/>
+
+<!--
+  this includes a computed VirtualBox element definition that contains
+  a proper 'version' attribute constraint (e.g. recent verison number
+  and platform suffix)
+-->
+<xsd:include schemaLocation="VirtualBox-settings-root.xsd"/>
 
 <!--
@@ -100,18 +107,3 @@
 </xsd:complexType>
 
-<!--
-// Root element
-/////////////////////////////////////////////////////////////////////////
--->
-
-<xsd:element name="VirtualBox">
-  <xsd:complexType>
-    <xsd:complexContent>
-      <xsd:extension base="TVirtualBox">
-        <xsd:attribute name="version" type="xsd:token" fixed="1.2-windows" use="required"/>
-      </xsd:extension>
-    </xsd:complexContent>
-  </xsd:complexType>
-</xsd:element>
-
 </xsd:schema>
