Index: src/VBox/Devices/Storage/DrvHostBase.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostBase.cpp	(revision 109)
+++ src/VBox/Devices/Storage/DrvHostBase.cpp	(working copy)
@@ -96,6 +96,15 @@
         /*IN*/ ULONG                Length,
         /*IN*/ FS_INFORMATION_CLASS FileSystemInformationClass );
 
+#elif defined(RT_OS_OS2)
+# define  OS2EMX_PLAIN_CHAR
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
+# define  IOCTL_CDROMDISK2         0x82
+# define  CDROMDISK_WRITELONG      0x52
+# define  CDROMDISK2_FEATURES      0x63
+# define  FEATURE_EXECMD_SUPPORT   0x00000004L
 #elif defined(RT_OS_FREEBSD)
 # include <sys/cdefs.h>
 # include <sys/param.h>
@@ -181,6 +190,209 @@
             pvBuf   = (uint8_t *)pvBuf + cbRead32;
         } while ((cbRead > 0) && RT_SUCCESS(rc));
 
+#elif defined(RT_OS_OS2)
+        // parameter packet
+        #pragma pack(1)
+        struct ReadLong_param {
+            ULONG       ID_code;                // 'CD01'
+            UCHAR       address_mode;           // Addressing format of start_sector:
+                                                //  00 - Logical Block format
+                                                //  01 - Minutes/Seconds/Frame format
+            USHORT      transfer_count;         // Numbers of sectors to read.
+                                                //  Must  be non zero
+            ULONG       start_sector;           // Starting sector number of the read operation
+            UCHAR       reserved;               // Reserved. Must be 0
+            UCHAR       interleave_size;        // Not used. Must be 0
+            UCHAR       interleave_skip_factor; // Not used. Must be 0
+        } parm;
+        ULONG parmlen = sizeof(parm);
+        #pragma pack()
+
+        #define SECTORSIZE      2048
+
+        // data packet
+        struct ReadLong_data_CD {
+            UCHAR        sync_pattern[12];
+            UCHAR        msf[3];
+            UCHAR        data_mode;
+            UCHAR        data_area[SECTORSIZE];
+            UCHAR        edc_ecc[288];
+        } data_CD;
+
+        struct ReadLong_data_DVD {
+            UCHAR        data_area[SECTORSIZE];
+        } data_DVD;
+
+        char *data = NULL;
+        ULONG datalen, data_offset;
+        uint32_t cbRead32;
+
+        /* parameter packet */
+        #pragma pack(1)
+        struct PARM {
+            unsigned char command;
+            unsigned char drive;
+        } parm2;
+        #pragma pack()
+        /* data packet      */
+        BIOSPARAMETERBLOCK bpb;
+        ULONG parmlen2 = sizeof(parm2);
+        ULONG datalen2 = sizeof(bpb);
+
+        parm2.command = 1;
+        parm2.drive = 0;
+
+        if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                               &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) )
+            return RTErrConvertFromOS2(rc);
+
+        if (pThis->enmType == PDMBLOCKTYPE_CDROM || pThis->enmType == PDMBLOCKTYPE_DVD)
+        {
+            switch (bpb.bMedia & 0x7f)
+            {
+                // CD
+                case 4:  // CD-R
+                case 5:  // CD-ROM
+                case 8:  // CD-RW
+                case 12: // DDCD-ROM
+                case 13: // DDCD-R
+                case 14: // DDCD-RW
+                    data = (char *)&data_CD;
+                    datalen = sizeof(data_CD);
+                    break;
+                // DVD
+                default:
+                    data = (char *)&data_DVD;
+                    datalen = sizeof(data_DVD);
+            }
+        }
+
+        #define BUFSIZE 0x4000
+        #define SECSIZE 512
+
+        ULONG parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1);
+        char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 0xffff];
+        PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf;
+        ULONG datalen4 = BUFSIZE;
+        USHORT cyl, head, sec, n;
+
+        switch (pThis->enmType)
+        {
+            case PDMBLOCKTYPE_CDROM:
+            case PDMBLOCKTYPE_DVD:
+                AssertReturn(!(off % SECTORSIZE), VERR_INVALID_PARAMETER);
+                cbRead32 = (cbRead > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbRead;
+                AssertReturn(!(cbRead % SECTORSIZE), VERR_INVALID_PARAMETER);
+
+                memset(&parm, 0, sizeof(parm));
+                parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+                parm.address_mode = 0; // lba
+
+                do
+                {
+                    parm.transfer_count = 1;
+                    parm.start_sector = (ULONG)(off / SECTORSIZE);
+
+                    rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_READLONG,
+                                     &parm, parmlen, &parmlen, data, datalen, &datalen);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_SUCCESS(rc))
+                    {
+                        switch (bpb.bMedia & 0x7f)
+                        {
+                            // CD
+                            case 4:  // CD-R
+                            case 5:  // CD-ROM
+                            case 8:  // CD-RW
+                            case 12: // DDCD-ROM
+                            case 13: // DDCD-R
+                            case 14: // DDCD-RW
+                                switch (data_CD.data_mode)
+                                {
+                                    case 0:
+                                        // Mode 0
+                                        data_offset = 16;
+                                        break;
+                                    case 1:
+                                        // Mode 1
+                                        data_offset = 16;
+                                        break;
+                                    case 2:
+                                        // Mode 2
+                                        data_offset = 24;
+                                        break;
+                                    default:
+                                        data_offset = 16;
+                                }
+                                break;
+
+                            // DVD
+                            default:
+                                data_offset = 0;
+                        }
+                        memcpy((char *)pvBuf, data + data_offset, cbRead32);
+                    }
+
+                    off    += cbRead32;
+                    cbRead -= cbRead32;
+                    pvBuf   = (uint8_t *)pvBuf + cbRead32;
+
+                } while ((cbRead > 0) && RT_SUCCESS(rc));
+                break;
+
+            case PDMBLOCKTYPE_FLOPPY_360:
+            case PDMBLOCKTYPE_FLOPPY_720:
+            case PDMBLOCKTYPE_FLOPPY_1_20:
+            case PDMBLOCKTYPE_FLOPPY_1_44:
+            case PDMBLOCKTYPE_FLOPPY_2_88:
+            case PDMBLOCKTYPE_FLOPPY_FAKE_15_6:
+            case PDMBLOCKTYPE_FLOPPY_FAKE_63_5:
+            case PDMBLOCKTYPE_HARD_DISK:
+                cbRead32 = (cbRead > BUFSIZE) ? BUFSIZE : (uint32_t)cbRead;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                do
+                {
+                    cyl = off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack);
+                    head = (off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack;
+                    sec = off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack;
+
+                    if (sec + cbRead32 / SECSIZE > bpb.usSectorsPerTrack)
+                        n = bpb.usSectorsPerTrack - sec + 1;
+                    else
+                        n = cbRead32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    for (int i = 0; i < bpb.usSectorsPerTrack; i++)
+                    {
+                        ptrk->TrackTable[i].usSectorNumber = i + 1;
+                        ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                    }
+
+                    rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_READTRACK,
+                                     trkbuf, parmlen4, &parmlen4, pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    off    += cbRead32;
+                    cbRead -= cbRead32;
+                    pvBuf   = (uint8_t *)pvBuf + cbRead32;
+
+                } while ((cbRead > 0) && RT_SUCCESS(rc));
+                break;
+
+            default:
+                rc = VERR_NOT_SUPPORTED;
+        }
+
 #else
         /*
          * Seek and read.
@@ -230,6 +442,147 @@
             /** @todo write support... */
             rc = VERR_WRITE_PROTECT;
 
+#elif defined(RT_OS_OS2)
+        // parameter packet
+        #pragma pack(1)
+        struct WriteLong_param {
+            ULONG       ID_code;                // 'CD01'
+            UCHAR       address_mode;           // Addressing format of start_sector:
+                                                //  00 - Logical Block format
+                                                //  01 - Minutes/Seconds/Frame format
+            USHORT      transfer_count;         // Numbers of sectors to read.
+                                                //  Must  be non zero
+            ULONG       start_sector;           // Starting sector number of the read operation
+            UCHAR       reserved;               // Reserved. Must be 0
+            UCHAR       interleave_size;        // Not used. Must be 0
+            UCHAR       interleave_skip_factor; // Not used. Must be 0
+        } parm;
+        ULONG parmlen = sizeof(parm);
+        #pragma pack()
+
+        #define SECTORSIZE      2048
+
+        // data packet
+        struct WriteLong_data {
+            UCHAR       sector_data[2048]; // Sector to be written to the disk
+        } data;
+
+        ULONG datalen, data_offset;
+        uint32_t cbWrite32;
+
+        datalen = sizeof(data);
+
+        /* parameter packet */
+        #pragma pack(1)
+        struct PARM {
+            unsigned char command;
+            unsigned char drive;
+        } parm2;
+        #pragma pack()
+        /* data packet      */
+        BIOSPARAMETERBLOCK bpb;
+        ULONG parmlen2 = sizeof(parm2);
+        ULONG datalen2 = sizeof(bpb);
+
+        parm2.command = 1;
+        parm2.drive = 0;
+
+        if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                               &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) )
+            return RTErrConvertFromOS2(rc);
+
+        #define BUFSIZE 0x4000
+        #define SECSIZE 512
+
+        ULONG parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1);
+        char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 0xffff];
+        PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf;
+        ULONG datalen4 = BUFSIZE;
+        USHORT cyl, head, sec, n;
+
+        switch (pThis->enmType)
+        {
+            case PDMBLOCKTYPE_CDROM:
+            case PDMBLOCKTYPE_DVD:
+                AssertReturn(!(off % SECTORSIZE), VERR_INVALID_PARAMETER);
+                cbWrite32 = (cbWrite > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbWrite;
+                AssertReturn(!(cbWrite % SECTORSIZE), VERR_INVALID_PARAMETER);
+
+                memset(&parm, 0, sizeof(parm));
+                parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+                parm.address_mode = 0; // lba
+
+                do
+                {
+                    parm.transfer_count = 1;
+                    parm.start_sector = (ULONG)(off / SECTORSIZE);
+
+                    rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_WRITELONG,
+                                     &parm, parmlen, &parmlen, &data, datalen, &datalen);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    if (RT_SUCCESS(rc))
+                        memcpy((char *)pvBuf, &data, cbWrite32);
+
+                    off += cbWrite32;
+                    cbWrite -= cbWrite32;
+                    pvBuf = (uint8_t *)pvBuf + cbWrite32;
+
+                } while ((cbWrite > 0) && RT_SUCCESS(rc));
+                break;
+
+            case PDMBLOCKTYPE_FLOPPY_360:
+            case PDMBLOCKTYPE_FLOPPY_720:
+            case PDMBLOCKTYPE_FLOPPY_1_20:
+            case PDMBLOCKTYPE_FLOPPY_1_44:
+            case PDMBLOCKTYPE_FLOPPY_2_88:
+            case PDMBLOCKTYPE_FLOPPY_FAKE_15_6:
+            case PDMBLOCKTYPE_FLOPPY_FAKE_63_5:
+            case PDMBLOCKTYPE_HARD_DISK:
+                cbWrite32 = (cbWrite > BUFSIZE) ? BUFSIZE : (uint32_t)cbWrite;
+
+                memset((char *)trkbuf, 0, sizeof(trkbuf));
+
+                do
+                {
+                    cyl = off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack);
+                    head = (off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack;
+                    sec = off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack;
+
+                    if (sec + cbWrite32 / SECSIZE > bpb.usSectorsPerTrack)
+                        n = bpb.usSectorsPerTrack - sec + 1;
+                    else
+                        n = cbWrite32 / SECSIZE;
+
+                    ptrk->bCommand = 1;
+                    ptrk->usHead = head;
+                    ptrk->usCylinder = cyl;
+                    ptrk->usFirstSector = sec;
+                    ptrk->cSectors = n;
+
+                    for (int i = 0; i < bpb.usSectorsPerTrack; i++)
+                    {
+                        ptrk->TrackTable[i].usSectorNumber = i + 1;
+                        ptrk->TrackTable[i].usSectorSize = SECSIZE;
+                    }
+
+                    rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_WRITETRACK,
+                                     trkbuf, parmlen4, &parmlen4, (void *)pvBuf, datalen4, &datalen4);
+
+                    rc = RTErrConvertFromOS2(rc);
+
+                    off    += cbWrite32;
+                    cbWrite -= cbWrite32;
+                    pvBuf   = (uint8_t *)pvBuf + cbWrite32;
+
+                } while ((cbWrite > 0) && RT_SUCCESS(rc));
+                break;
+
+            default:
+                rc = VERR_NOT_SUPPORTED;
+        }
+
 #else
             /*
              * Seek and write.
@@ -1059,6 +1412,41 @@
     RTFileClose(hFileDevice);
     return rc;
 
+#elif defined(RT_OS_OS2)
+    APIRET rc;
+    ULONG  sig, feat, cmd = 0;
+    ULONG  parmlen = sizeof(sig);
+    ULONG  datalen = sizeof(sig);
+    ULONG  ulAction;
+    HFILE  hDisk = NULLHANDLE;
+
+    if (! (rc = DosOpen(pThis->pszDeviceOpen, &hDisk,
+                        &ulAction, 0, FILE_NORMAL,
+                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+                        OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE |
+                        OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, NULL)) )
+    {
+        if (! hDisk)
+            return VERR_MEDIA_NOT_PRESENT;
+
+        if (pThis->enmType == PDMBLOCKTYPE_CDROM || pThis->enmType == PDMBLOCKTYPE_DVD)
+        {
+            // identify CDROM driver
+            sig = ('C') | ('D' << 8) | ('9' << 16) | ('9' << 24);
+
+            if ( (rc = DosDevIOCtl(hDisk, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER,
+                                   &sig, sizeof(sig), NULL,
+                                   &sig, sizeof(sig), NULL)) ||
+                  sig != (('C') | ('D' << 8) | ('0' << 16) | ('1' << 24)) )
+                return VERR_MEDIA_NOT_PRESENT;
+        }
+    }
+    else
+        return RTErrConvertFromOS2(rc);
+
+    RTFileFromNative(pFileDevice, hDisk);
+
+    return VINF_SUCCESS;
 #else
     uint32_t fFlags = (fReadOnly ? RTFILE_O_READ : RTFILE_O_READWRITE) | RTFILE_O_OPEN | RTFILE_O_DENY_NONE;
 # ifdef RT_OS_LINUX
@@ -1128,6 +1516,13 @@
     }
     RTFILE hFileRawDevice;
     int rc = drvHostBaseOpen(pThis, &hFileDevice, &hFileRawDevice, pThis->fReadOnlyConfig);
+#elif defined(RT_OS_OS2)
+    if (pThis->hFileDevice != NIL_RTFILE)
+    {
+        RTFileClose(pThis->hFileDevice);
+        pThis->hFileDevice = NIL_RTFILE;
+    }
+    int rc = drvHostBaseOpen(pThis, &hFileDevice, pThis->fReadOnlyConfig);
 #else
     int rc = drvHostBaseOpen(pThis, &hFileDevice, pThis->fReadOnlyConfig);
 #endif
@@ -1248,6 +1643,86 @@
     }
     LogFlow(("drvHostBaseGetMediaSize: NtQueryVolumeInformationFile -> %#lx\n", rcNt, rc));
     return rc;
+#elif defined(RT_OS_OS2)
+    ULONG parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+    ULONG parmlen = sizeof(parm);
+    ULONG data = 0;
+    ULONG datalen = sizeof(data);
+    APIRET rc;
+
+    /* parameter packet */
+    #pragma pack(1)
+    struct PARM {
+        unsigned char command;
+        unsigned char drive;
+    } parm2;
+    #pragma pack()
+    /* data packet      */
+    BIOSPARAMETERBLOCK bpb;
+    ULONG cbSectors;
+    ULONG parmlen2 = sizeof(parm2);
+    ULONG datalen2 = sizeof(bpb);
+
+    switch (pThis->enmType)
+    {
+        case PDMBLOCKTYPE_DVD:
+        case PDMBLOCKTYPE_CDROM:
+            if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice),
+                                   IOCTL_CDROMDISK, CDROMDISK_DEVICESTATUS,
+                                   &parm, parmlen, &parmlen,
+                                   &data, datalen, &datalen)) )
+                return RTErrConvertFromOS2(rc);
+
+            if (data & (1 << 11))
+                // disk does not present
+                return VERR_MEDIA_NOT_PRESENT;
+
+            parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+
+            if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice),
+                                   IOCTL_CDROMDISK, CDROMDISK_GETVOLUMESIZE,
+                                   &parm, parmlen, &parmlen,
+                                   &data, datalen, &datalen)) )
+                return RTErrConvertFromOS2(rc);
+
+            // return disk size in bytes
+            *pcb = data * 2048;
+            return VINF_SUCCESS;
+
+        case PDMBLOCKTYPE_FLOPPY_360:
+        case PDMBLOCKTYPE_FLOPPY_720:
+        case PDMBLOCKTYPE_FLOPPY_1_20:
+        case PDMBLOCKTYPE_FLOPPY_1_44:
+        case PDMBLOCKTYPE_FLOPPY_2_88:
+        case PDMBLOCKTYPE_FLOPPY_FAKE_15_6:
+        case PDMBLOCKTYPE_FLOPPY_FAKE_63_5:
+        case PDMBLOCKTYPE_HARD_DISK:
+            parm2.command = 1; // Return the BPB for the media currently in the drive
+            parm2.drive = 0;   // unused
+
+            memset(&bpb, 0, sizeof(bpb));
+
+            rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                             &parm2, parmlen2, &parmlen2, 
+                             &bpb, datalen2, &datalen2);
+
+            if (! rc) {
+                cbSectors = bpb.cCylinders * bpb.cHeads * bpb.usSectorsPerTrack;
+                *pcb = cbSectors * bpb.usBytesPerSector;
+                rc = VINF_SUCCESS;
+            }
+            else
+            {
+                rc = RTErrConvertFromOS2(rc);
+                Log(("DrvHostBaseGetMediaSize: ioctl DSK_GETDEVICEPARAMS(%s) failed, rc=%Rrc\n",
+                     pThis->pszDevice, rc));
+                return rc;
+            }
+            return rc;
+
+        default:
+            return VERR_NOT_SUPPORTED;
+    }
 #else
     return RTFileSeek(pThis->hFileDevice, 0, RTFILE_SEEK_END, pcb);
 #endif
@@ -2041,7 +2516,7 @@
     pThis->fAttachFailError = fAttachFailError;
 
     /* name to open & watch for */
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     int iBit = RT_C_TO_UPPER(pThis->pszDevice[0]) - 'A';
     if (    iBit > 'Z' - 'A'
         ||  pThis->pszDevice[1] != ':'
@@ -2051,7 +2526,11 @@
         return VERR_INVALID_PARAMETER;
     }
     pThis->fUnitMask = 1 << iBit;
+#if defined(RT_OS_WINDOWS)
     RTStrAPrintf(&pThis->pszDeviceOpen, "\\\\.\\%s", pThis->pszDevice);
+#else
+    RTStrAPrintf(&pThis->pszDeviceOpen, "%s", pThis->pszDevice);
+#endif
 
 #elif defined(RT_OS_SOLARIS)
     char *pszBlockDevName = getfullblkname(pThis->pszDevice);
@@ -2199,7 +2678,7 @@
             }
         }
     }
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     if (RT_SUCCESS(src))
         DRVHostBaseMediaPresent(pThis);
 #endif
Index: src/VBox/Devices/Storage/DrvHostDVD.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostDVD.cpp	(revision 109)
+++ src/VBox/Devices/Storage/DrvHostDVD.cpp	(working copy)
@@ -86,6 +86,12 @@
 # undef _interlockedbittestandreset64
 # undef USE_MEDIA_POLLING
 
+#elif defined(RT_OS_OS2)
+# define  INCL_BASE
+# define  INCL_DOSDEVICES
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
+
 #elif defined(RT_OS_FREEBSD)
 # include <sys/cdefs.h>
 # include <sys/param.h>
@@ -106,6 +112,7 @@
 #include <iprt/string.h>
 #include <iprt/thread.h>
 #include <iprt/critsect.h>
+#include <iprt/mem.h>
 #include <VBox/scsi.h>
 
 #include "VBoxDD.h"
@@ -202,6 +209,17 @@
                 AssertMsgFailed(("Failed to open '%s' for ejecting this tray.\n",  rc));
 
 
+#elif defined(RT_OS_OS2)
+            ULONG parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+            ULONG parmlen = sizeof(parm);
+
+            if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice),
+                               IOCTL_CDROMDISK, CDROMDISK_EJECTDISK,
+                               &parm, parmlen, &parmlen,
+                               NULL, 0, NULL)))
+                rc = VINF_SUCCESS;
+            else
+                rc = RTErrConvertFromOS2(rc);
 #else
             AssertMsgFailed(("Eject is not implemented!\n"));
             rc = VINF_SUCCESS;
@@ -280,6 +298,28 @@
         /** @todo figure out the return codes for already locked. */
         rc = RTErrConvertFromWin32(GetLastError());
 
+#elif defined(RT_OS_OS2)
+    #pragma pack(1)
+    typedef struct _PARM
+    {
+        ULONG sig;
+        char flag;
+    } PARM;
+    #pragma pack()
+
+    ULONG  parmlen, datalen = 0;
+    PARM   parm;
+    APIRET rc;
+
+    parm.sig = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+    parm.flag = fLock ? 1 : 0;
+
+    if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_LOCKUNLOCKDOOR,
+                            &parm, sizeof(PARM), &parmlen,
+                            0, datalen, &datalen)))
+        rc = VINF_SUCCESS;
+    else
+        rc = RTErrConvertFromOS2(rc);
 #else
     AssertMsgFailed(("Lock/Unlock is not implemented!\n"));
     int rc = VINF_SUCCESS;
@@ -631,6 +671,89 @@
         rc = RTErrConvertFromWin32(GetLastError());
     Log2(("%s: scsistatus=%d bytes returned=%d tlength=%d\n", __FUNCTION__, Req.spt.ScsiStatus, cbReturned, Req.spt.DataTransferLength));
 
+#elif defined(RT_OS_OS2)
+    #define CDROMDISK_EXECMD  0x7A
+    int flags;
+
+    struct ExecCMD {
+       ULONG        ID_code;          // 'CD01'
+       USHORT       data_length;      // length of the Data Packet
+       USHORT       cmd_length;       // length of the Command Buffer
+       USHORT       flags;            // flags
+       UCHAR        cmd_buffer[16];   // Command Buffer for SCSI command
+       ULONG        cmd_timeout;      // Timeout for executing command (0 - default)
+    } cmd;
+    // flags:
+    #define EX_DIRECTION_IN  0x0001
+    #define EX_PLAYING_CHK   0x0002
+    #define EX_RETURN_STATUS 0x0004
+    #define EX_SET_TIMEOUT   0x0008
+
+    struct RetStatus {
+        UCHAR       sense_key;    // Sense Key
+        UCHAR       asc_code;     // Additional Sense Code (ASC)
+        UCHAR       ascq_code;    // Additional Sense Code Qualifier (ASCQ)
+    };
+
+    ULONG cmdlen = sizeof(cmd);
+    ULONG datalen;
+    char  *data;
+
+    switch (enmTxDir)
+    {
+        case PDMBLOCKTXDIR_NONE:
+            Assert(*pcbBuf == 0);
+            flags = 0;
+            break;
+        case PDMBLOCKTXDIR_FROM_DEVICE:
+            Assert(*pcbBuf != 0);
+            /* Make sure that the buffer is clear for commands reading
+             * data. The actually received data may be shorter than what
+             * we expect, and due to the unreliable feedback about how much
+             * data the ioctl actually transferred, it's impossible to
+             * prevent that. Returning previous buffer contents may cause
+             * security problems inside the guest OS, if users can issue
+             * commands to the CDROM device. */
+            memset(pvBuf, 0, *pcbBuf);
+            flags = EX_DIRECTION_IN;
+            break;
+        case PDMBLOCKTXDIR_TO_DEVICE:
+            Assert(*pcbBuf != 0);
+            flags = 0;
+            break;
+        default:
+            AssertMsgFailed(("enmTxDir invalid!\n"));
+            flags = 0;
+    }
+    flags |= EX_SET_TIMEOUT | EX_RETURN_STATUS;
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24);
+    cmd.cmd_length = sizeof(cmd.cmd_buffer);
+    memcpy((char *)cmd.cmd_buffer, (char *)pbCmd, 12);
+    cmd.flags = flags;
+    cmd.cmd_timeout = cTimeoutMillies;
+    cmd.data_length = *pcbBuf + cbSense;
+    data = (char *)RTMemAllocZ(cmd.data_length);
+    datalen = cmd.data_length;
+    memcpy(data, pvBuf, *pcbBuf);
+
+    if (! (rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice),
+                    IOCTL_CDROMDISK, CDROMDISK_EXECMD, 
+                    &cmd, cmdlen, &cmdlen, data, datalen, &datalen)) )
+    {
+        if (datalen > cmd.data_length)
+            memcpy(pabSense, (char *)pvBuf + *pcbBuf, cbSense);
+        else
+            memset(pabSense, 0, cbSense);
+ 
+        memcpy(pvBuf, data, *pcbBuf);
+        RTMemFree(data);
+    }
+    else
+        rc = RTErrConvertFromOS2(rc);
+
+    Log2(("%s: bytes returned=%d\n", __FUNCTION__, *pcbBuf));
+    
 #else
 # error "Unsupported platform."
 #endif
Index: src/VBox/Devices/Storage/DrvHostFloppy.cpp
===================================================================
--- src/VBox/Devices/Storage/DrvHostFloppy.cpp	(revision 109)
+++ src/VBox/Devices/Storage/DrvHostFloppy.cpp	(working copy)
@@ -28,10 +28,14 @@
 # include <sys/fcntl.h>
 # include <errno.h>
 
-# elif defined(RT_OS_WINDOWS)
+#elif defined(RT_OS_WINDOWS)
 # include <windows.h>
 # include <dbt.h>
 
+#elif defined(RT_OS_OS2)
+# define  INCL_BASE
+# define  INCL_DOSDEVIOCTL
+# include <os2.h>
 #elif defined(RT_OS_L4)
 
 #else /* !RT_OS_WINDOWS nor RT_OS_LINUX nor RT_OS_L4 */
@@ -101,6 +105,56 @@
 }
 #endif /* RT_OS_WINDOWS */
 
+#ifdef RT_OS_OS2
+
+/* parameter packet */
+#pragma pack(1)
+struct PARM {
+    unsigned char command;
+    unsigned char drive;
+};
+#pragma pack()
+
+/**
+ * Get media size - needs a special IOCTL.
+ *
+ * @param   pThis   The instance data.
+ */
+static DECLCALLBACK(int) drvHostFloppyGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb)
+{
+    struct PARM parm;
+    BIOSPARAMETERBLOCK bpb;
+    ULONG cbSectors;
+    ULONG parmlen = sizeof(parm);
+    ULONG datalen = sizeof(bpb);
+    APIRET rc;
+
+    parm.command = 1; // Return the BPB for the media currently in the drive
+    parm.drive = 0;   // unused
+
+    memset(&bpb, 0, sizeof(bpb));
+
+    rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS,
+                     &parm, parmlen, &parmlen,
+                     &bpb, datalen, &datalen);
+
+    if (! rc) {
+        cbSectors = bpb.cCylinders * bpb.cHeads * bpb.usSectorsPerTrack;
+        *pcb = cbSectors * bpb.usBytesPerSector;
+        rc = VINF_SUCCESS;
+    }
+    else
+    {
+        rc = RTErrConvertFromOS2(rc);
+        Log(("DrvHostFloppy: ioctl DSK_GETDEVICEPARAMS(%s) failed, rc=%Rrc\n",
+             pThis->pszDevice, rc));
+        return rc;
+    }
+
+    return rc;
+}
+#endif /* RT_OS_OS2 */
+
 #ifdef RT_OS_LINUX
 /**
  * Get media size and do change processing.
@@ -198,7 +252,7 @@
             /*
              * Override stuff.
              */
-#ifdef RT_OS_WINDOWS
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
             pThis->Base.pfnGetMediaSize = drvHostFloppyGetMediaSize;
 #endif
 #ifdef RT_OS_LINUX
Index: src/VBox/Devices/Storage/DrvHostBase.h
===================================================================
--- src/VBox/Devices/Storage/DrvHostBase.h	(revision 109)
+++ src/VBox/Devices/Storage/DrvHostBase.h	(working copy)
@@ -129,6 +129,10 @@
     /** The unit mask. */
     DWORD                   fUnitMask;
 #endif
+#ifdef RT_OS_OS2
+    /** The unit mask. */
+    ULONG                   fUnitMask;
+#endif
 
 #ifdef RT_OS_LINUX
     /** Double buffer required for ioctl with the Linux kernel as long as we use
