| 193 | #elif defined(RT_OS_OS2) |
| 194 | // parameter packet |
| 195 | #pragma pack(1) |
| 196 | struct ReadLong_param { |
| 197 | ULONG ID_code; // 'CD01' |
| 198 | UCHAR address_mode; // Addressing format of start_sector: |
| 199 | // 00 - Logical Block format |
| 200 | // 01 - Minutes/Seconds/Frame format |
| 201 | USHORT transfer_count; // Numbers of sectors to read. |
| 202 | // Must be non zero |
| 203 | ULONG start_sector; // Starting sector number of the read operation |
| 204 | UCHAR reserved; // Reserved. Must be 0 |
| 205 | UCHAR interleave_size; // Not used. Must be 0 |
| 206 | UCHAR interleave_skip_factor; // Not used. Must be 0 |
| 207 | } parm; |
| 208 | ULONG parmlen = sizeof(parm); |
| 209 | #pragma pack() |
| 210 | |
| 211 | #define SECTORSIZE 2048 |
| 212 | |
| 213 | // data packet |
| 214 | struct ReadLong_data_CD { |
| 215 | UCHAR sync_pattern[12]; |
| 216 | UCHAR msf[3]; |
| 217 | UCHAR data_mode; |
| 218 | UCHAR data_area[SECTORSIZE]; |
| 219 | UCHAR edc_ecc[288]; |
| 220 | } data_CD; |
| 221 | |
| 222 | struct ReadLong_data_DVD { |
| 223 | UCHAR data_area[SECTORSIZE]; |
| 224 | } data_DVD; |
| 225 | |
| 226 | char *data = NULL; |
| 227 | ULONG datalen, data_offset; |
| 228 | uint32_t cbRead32; |
| 229 | |
| 230 | /* parameter packet */ |
| 231 | #pragma pack(1) |
| 232 | struct PARM { |
| 233 | unsigned char command; |
| 234 | unsigned char drive; |
| 235 | } parm2; |
| 236 | #pragma pack() |
| 237 | /* data packet */ |
| 238 | BIOSPARAMETERBLOCK bpb; |
| 239 | ULONG parmlen2 = sizeof(parm2); |
| 240 | ULONG datalen2 = sizeof(bpb); |
| 241 | |
| 242 | parm2.command = 1; |
| 243 | parm2.drive = 0; |
| 244 | |
| 245 | if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS, |
| 246 | &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) ) |
| 247 | return RTErrConvertFromOS2(rc); |
| 248 | |
| 249 | if (pThis->enmType == PDMBLOCKTYPE_CDROM || pThis->enmType == PDMBLOCKTYPE_DVD) |
| 250 | { |
| 251 | switch (bpb.bMedia & 0x7f) |
| 252 | { |
| 253 | // CD |
| 254 | case 4: // CD-R |
| 255 | case 5: // CD-ROM |
| 256 | case 8: // CD-RW |
| 257 | case 12: // DDCD-ROM |
| 258 | case 13: // DDCD-R |
| 259 | case 14: // DDCD-RW |
| 260 | data = (char *)&data_CD; |
| 261 | datalen = sizeof(data_CD); |
| 262 | break; |
| 263 | // DVD |
| 264 | default: |
| 265 | data = (char *)&data_DVD; |
| 266 | datalen = sizeof(data_DVD); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | #define BUFSIZE 0x4000 |
| 271 | #define SECSIZE 512 |
| 272 | |
| 273 | ULONG parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1); |
| 274 | char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 0xffff]; |
| 275 | PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf; |
| 276 | ULONG datalen4 = BUFSIZE; |
| 277 | USHORT cyl, head, sec, n; |
| 278 | |
| 279 | switch (pThis->enmType) |
| 280 | { |
| 281 | case PDMBLOCKTYPE_CDROM: |
| 282 | case PDMBLOCKTYPE_DVD: |
| 283 | AssertReturn(!(off % SECTORSIZE), VERR_INVALID_PARAMETER); |
| 284 | cbRead32 = (cbRead > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbRead; |
| 285 | AssertReturn(!(cbRead % SECTORSIZE), VERR_INVALID_PARAMETER); |
| 286 | |
| 287 | memset(&parm, 0, sizeof(parm)); |
| 288 | parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24); |
| 289 | parm.address_mode = 0; // lba |
| 290 | |
| 291 | do |
| 292 | { |
| 293 | parm.transfer_count = 1; |
| 294 | parm.start_sector = (ULONG)(off / SECTORSIZE); |
| 295 | |
| 296 | rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_READLONG, |
| 297 | &parm, parmlen, &parmlen, data, datalen, &datalen); |
| 298 | |
| 299 | rc = RTErrConvertFromOS2(rc); |
| 300 | |
| 301 | if (RT_SUCCESS(rc)) |
| 302 | { |
| 303 | switch (bpb.bMedia & 0x7f) |
| 304 | { |
| 305 | // CD |
| 306 | case 4: // CD-R |
| 307 | case 5: // CD-ROM |
| 308 | case 8: // CD-RW |
| 309 | case 12: // DDCD-ROM |
| 310 | case 13: // DDCD-R |
| 311 | case 14: // DDCD-RW |
| 312 | switch (data_CD.data_mode) |
| 313 | { |
| 314 | case 0: |
| 315 | // Mode 0 |
| 316 | data_offset = 16; |
| 317 | break; |
| 318 | case 1: |
| 319 | // Mode 1 |
| 320 | data_offset = 16; |
| 321 | break; |
| 322 | case 2: |
| 323 | // Mode 2 |
| 324 | data_offset = 24; |
| 325 | break; |
| 326 | default: |
| 327 | data_offset = 16; |
| 328 | } |
| 329 | break; |
| 330 | |
| 331 | // DVD |
| 332 | default: |
| 333 | data_offset = 0; |
| 334 | } |
| 335 | memcpy((char *)pvBuf, data + data_offset, cbRead32); |
| 336 | } |
| 337 | |
| 338 | off += cbRead32; |
| 339 | cbRead -= cbRead32; |
| 340 | pvBuf = (uint8_t *)pvBuf + cbRead32; |
| 341 | |
| 342 | } while ((cbRead > 0) && RT_SUCCESS(rc)); |
| 343 | break; |
| 344 | |
| 345 | case PDMBLOCKTYPE_FLOPPY_360: |
| 346 | case PDMBLOCKTYPE_FLOPPY_720: |
| 347 | case PDMBLOCKTYPE_FLOPPY_1_20: |
| 348 | case PDMBLOCKTYPE_FLOPPY_1_44: |
| 349 | case PDMBLOCKTYPE_FLOPPY_2_88: |
| 350 | case PDMBLOCKTYPE_FLOPPY_FAKE_15_6: |
| 351 | case PDMBLOCKTYPE_FLOPPY_FAKE_63_5: |
| 352 | case PDMBLOCKTYPE_HARD_DISK: |
| 353 | cbRead32 = (cbRead > BUFSIZE) ? BUFSIZE : (uint32_t)cbRead; |
| 354 | |
| 355 | memset((char *)trkbuf, 0, sizeof(trkbuf)); |
| 356 | |
| 357 | do |
| 358 | { |
| 359 | cyl = off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack); |
| 360 | head = (off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack; |
| 361 | sec = off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack; |
| 362 | |
| 363 | if (sec + cbRead32 / SECSIZE > bpb.usSectorsPerTrack) |
| 364 | n = bpb.usSectorsPerTrack - sec + 1; |
| 365 | else |
| 366 | n = cbRead32 / SECSIZE; |
| 367 | |
| 368 | ptrk->bCommand = 1; |
| 369 | ptrk->usHead = head; |
| 370 | ptrk->usCylinder = cyl; |
| 371 | ptrk->usFirstSector = sec; |
| 372 | ptrk->cSectors = n; |
| 373 | |
| 374 | for (int i = 0; i < bpb.usSectorsPerTrack; i++) |
| 375 | { |
| 376 | ptrk->TrackTable[i].usSectorNumber = i + 1; |
| 377 | ptrk->TrackTable[i].usSectorSize = SECSIZE; |
| 378 | } |
| 379 | |
| 380 | rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_READTRACK, |
| 381 | trkbuf, parmlen4, &parmlen4, pvBuf, datalen4, &datalen4); |
| 382 | |
| 383 | rc = RTErrConvertFromOS2(rc); |
| 384 | |
| 385 | off += cbRead32; |
| 386 | cbRead -= cbRead32; |
| 387 | pvBuf = (uint8_t *)pvBuf + cbRead32; |
| 388 | |
| 389 | } while ((cbRead > 0) && RT_SUCCESS(rc)); |
| 390 | break; |
| 391 | |
| 392 | default: |
| 393 | rc = VERR_NOT_SUPPORTED; |
| 394 | } |
| 395 | |
| 445 | #elif defined(RT_OS_OS2) |
| 446 | // parameter packet |
| 447 | #pragma pack(1) |
| 448 | struct WriteLong_param { |
| 449 | ULONG ID_code; // 'CD01' |
| 450 | UCHAR address_mode; // Addressing format of start_sector: |
| 451 | // 00 - Logical Block format |
| 452 | // 01 - Minutes/Seconds/Frame format |
| 453 | USHORT transfer_count; // Numbers of sectors to read. |
| 454 | // Must be non zero |
| 455 | ULONG start_sector; // Starting sector number of the read operation |
| 456 | UCHAR reserved; // Reserved. Must be 0 |
| 457 | UCHAR interleave_size; // Not used. Must be 0 |
| 458 | UCHAR interleave_skip_factor; // Not used. Must be 0 |
| 459 | } parm; |
| 460 | ULONG parmlen = sizeof(parm); |
| 461 | #pragma pack() |
| 462 | |
| 463 | #define SECTORSIZE 2048 |
| 464 | |
| 465 | // data packet |
| 466 | struct WriteLong_data { |
| 467 | UCHAR sector_data[2048]; // Sector to be written to the disk |
| 468 | } data; |
| 469 | |
| 470 | ULONG datalen, data_offset; |
| 471 | uint32_t cbWrite32; |
| 472 | |
| 473 | datalen = sizeof(data); |
| 474 | |
| 475 | /* parameter packet */ |
| 476 | #pragma pack(1) |
| 477 | struct PARM { |
| 478 | unsigned char command; |
| 479 | unsigned char drive; |
| 480 | } parm2; |
| 481 | #pragma pack() |
| 482 | /* data packet */ |
| 483 | BIOSPARAMETERBLOCK bpb; |
| 484 | ULONG parmlen2 = sizeof(parm2); |
| 485 | ULONG datalen2 = sizeof(bpb); |
| 486 | |
| 487 | parm2.command = 1; |
| 488 | parm2.drive = 0; |
| 489 | |
| 490 | if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS, |
| 491 | &parm2, parmlen2, &parmlen2, &bpb, datalen2, &datalen2)) ) |
| 492 | return RTErrConvertFromOS2(rc); |
| 493 | |
| 494 | #define BUFSIZE 0x4000 |
| 495 | #define SECSIZE 512 |
| 496 | |
| 497 | ULONG parmlen4 = sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * (bpb.usSectorsPerTrack - 1); |
| 498 | char trkbuf[sizeof(TRACKLAYOUT) + sizeof(USHORT) * 2 * 0xffff]; |
| 499 | PTRACKLAYOUT ptrk = (PTRACKLAYOUT)trkbuf; |
| 500 | ULONG datalen4 = BUFSIZE; |
| 501 | USHORT cyl, head, sec, n; |
| 502 | |
| 503 | switch (pThis->enmType) |
| 504 | { |
| 505 | case PDMBLOCKTYPE_CDROM: |
| 506 | case PDMBLOCKTYPE_DVD: |
| 507 | AssertReturn(!(off % SECTORSIZE), VERR_INVALID_PARAMETER); |
| 508 | cbWrite32 = (cbWrite > SECTORSIZE) ? SECTORSIZE : (uint32_t)cbWrite; |
| 509 | AssertReturn(!(cbWrite % SECTORSIZE), VERR_INVALID_PARAMETER); |
| 510 | |
| 511 | memset(&parm, 0, sizeof(parm)); |
| 512 | parm.ID_code = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24); |
| 513 | parm.address_mode = 0; // lba |
| 514 | |
| 515 | do |
| 516 | { |
| 517 | parm.transfer_count = 1; |
| 518 | parm.start_sector = (ULONG)(off / SECTORSIZE); |
| 519 | |
| 520 | rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_CDROMDISK, CDROMDISK_WRITELONG, |
| 521 | &parm, parmlen, &parmlen, &data, datalen, &datalen); |
| 522 | |
| 523 | rc = RTErrConvertFromOS2(rc); |
| 524 | |
| 525 | if (RT_SUCCESS(rc)) |
| 526 | memcpy((char *)pvBuf, &data, cbWrite32); |
| 527 | |
| 528 | off += cbWrite32; |
| 529 | cbWrite -= cbWrite32; |
| 530 | pvBuf = (uint8_t *)pvBuf + cbWrite32; |
| 531 | |
| 532 | } while ((cbWrite > 0) && RT_SUCCESS(rc)); |
| 533 | break; |
| 534 | |
| 535 | case PDMBLOCKTYPE_FLOPPY_360: |
| 536 | case PDMBLOCKTYPE_FLOPPY_720: |
| 537 | case PDMBLOCKTYPE_FLOPPY_1_20: |
| 538 | case PDMBLOCKTYPE_FLOPPY_1_44: |
| 539 | case PDMBLOCKTYPE_FLOPPY_2_88: |
| 540 | case PDMBLOCKTYPE_FLOPPY_FAKE_15_6: |
| 541 | case PDMBLOCKTYPE_FLOPPY_FAKE_63_5: |
| 542 | case PDMBLOCKTYPE_HARD_DISK: |
| 543 | cbWrite32 = (cbWrite > BUFSIZE) ? BUFSIZE : (uint32_t)cbWrite; |
| 544 | |
| 545 | memset((char *)trkbuf, 0, sizeof(trkbuf)); |
| 546 | |
| 547 | do |
| 548 | { |
| 549 | cyl = off / (SECSIZE * bpb.cHeads * bpb.usSectorsPerTrack); |
| 550 | head = (off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl) / bpb.usSectorsPerTrack; |
| 551 | sec = off / SECSIZE - bpb.cHeads * bpb.usSectorsPerTrack * cyl - head * bpb.usSectorsPerTrack; |
| 552 | |
| 553 | if (sec + cbWrite32 / SECSIZE > bpb.usSectorsPerTrack) |
| 554 | n = bpb.usSectorsPerTrack - sec + 1; |
| 555 | else |
| 556 | n = cbWrite32 / SECSIZE; |
| 557 | |
| 558 | ptrk->bCommand = 1; |
| 559 | ptrk->usHead = head; |
| 560 | ptrk->usCylinder = cyl; |
| 561 | ptrk->usFirstSector = sec; |
| 562 | ptrk->cSectors = n; |
| 563 | |
| 564 | for (int i = 0; i < bpb.usSectorsPerTrack; i++) |
| 565 | { |
| 566 | ptrk->TrackTable[i].usSectorNumber = i + 1; |
| 567 | ptrk->TrackTable[i].usSectorSize = SECSIZE; |
| 568 | } |
| 569 | |
| 570 | rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_WRITETRACK, |
| 571 | trkbuf, parmlen4, &parmlen4, (void *)pvBuf, datalen4, &datalen4); |
| 572 | |
| 573 | rc = RTErrConvertFromOS2(rc); |
| 574 | |
| 575 | off += cbWrite32; |
| 576 | cbWrite -= cbWrite32; |
| 577 | pvBuf = (uint8_t *)pvBuf + cbWrite32; |
| 578 | |
| 579 | } while ((cbWrite > 0) && RT_SUCCESS(rc)); |
| 580 | break; |
| 581 | |
| 582 | default: |
| 583 | rc = VERR_NOT_SUPPORTED; |
| 584 | } |
| 585 | |
| 1415 | #elif defined(RT_OS_OS2) |
| 1416 | APIRET rc; |
| 1417 | ULONG sig, feat, cmd = 0; |
| 1418 | ULONG parmlen = sizeof(sig); |
| 1419 | ULONG datalen = sizeof(sig); |
| 1420 | ULONG ulAction; |
| 1421 | HFILE hDisk = NULLHANDLE; |
| 1422 | |
| 1423 | if (! (rc = DosOpen(pThis->pszDeviceOpen, &hDisk, |
| 1424 | &ulAction, 0, FILE_NORMAL, |
| 1425 | OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, |
| 1426 | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | |
| 1427 | OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, NULL)) ) |
| 1428 | { |
| 1429 | if (! hDisk) |
| 1430 | return VERR_MEDIA_NOT_PRESENT; |
| 1431 | |
| 1432 | if (pThis->enmType == PDMBLOCKTYPE_CDROM || pThis->enmType == PDMBLOCKTYPE_DVD) |
| 1433 | { |
| 1434 | // identify CDROM driver |
| 1435 | sig = ('C') | ('D' << 8) | ('9' << 16) | ('9' << 24); |
| 1436 | |
| 1437 | if ( (rc = DosDevIOCtl(hDisk, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER, |
| 1438 | &sig, sizeof(sig), NULL, |
| 1439 | &sig, sizeof(sig), NULL)) || |
| 1440 | sig != (('C') | ('D' << 8) | ('0' << 16) | ('1' << 24)) ) |
| 1441 | return VERR_MEDIA_NOT_PRESENT; |
| 1442 | } |
| 1443 | } |
| 1444 | else |
| 1445 | return RTErrConvertFromOS2(rc); |
| 1446 | |
| 1447 | RTFileFromNative(pFileDevice, hDisk); |
| 1448 | |
| 1449 | return VINF_SUCCESS; |
| 1646 | #elif defined(RT_OS_OS2) |
| 1647 | ULONG parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24); |
| 1648 | ULONG parmlen = sizeof(parm); |
| 1649 | ULONG data = 0; |
| 1650 | ULONG datalen = sizeof(data); |
| 1651 | APIRET rc; |
| 1652 | |
| 1653 | /* parameter packet */ |
| 1654 | #pragma pack(1) |
| 1655 | struct PARM { |
| 1656 | unsigned char command; |
| 1657 | unsigned char drive; |
| 1658 | } parm2; |
| 1659 | #pragma pack() |
| 1660 | /* data packet */ |
| 1661 | BIOSPARAMETERBLOCK bpb; |
| 1662 | ULONG cbSectors; |
| 1663 | ULONG parmlen2 = sizeof(parm2); |
| 1664 | ULONG datalen2 = sizeof(bpb); |
| 1665 | |
| 1666 | switch (pThis->enmType) |
| 1667 | { |
| 1668 | case PDMBLOCKTYPE_DVD: |
| 1669 | case PDMBLOCKTYPE_CDROM: |
| 1670 | if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), |
| 1671 | IOCTL_CDROMDISK, CDROMDISK_DEVICESTATUS, |
| 1672 | &parm, parmlen, &parmlen, |
| 1673 | &data, datalen, &datalen)) ) |
| 1674 | return RTErrConvertFromOS2(rc); |
| 1675 | |
| 1676 | if (data & (1 << 11)) |
| 1677 | // disk does not present |
| 1678 | return VERR_MEDIA_NOT_PRESENT; |
| 1679 | |
| 1680 | parm = ('C') | ('D' << 8) | ('0' << 16) | ('1' << 24); |
| 1681 | |
| 1682 | if ( (rc = DosDevIOCtl(RTFileToNative(pThis->hFileDevice), |
| 1683 | IOCTL_CDROMDISK, CDROMDISK_GETVOLUMESIZE, |
| 1684 | &parm, parmlen, &parmlen, |
| 1685 | &data, datalen, &datalen)) ) |
| 1686 | return RTErrConvertFromOS2(rc); |
| 1687 | |
| 1688 | // return disk size in bytes |
| 1689 | *pcb = data * 2048; |
| 1690 | return VINF_SUCCESS; |
| 1691 | |
| 1692 | case PDMBLOCKTYPE_FLOPPY_360: |
| 1693 | case PDMBLOCKTYPE_FLOPPY_720: |
| 1694 | case PDMBLOCKTYPE_FLOPPY_1_20: |
| 1695 | case PDMBLOCKTYPE_FLOPPY_1_44: |
| 1696 | case PDMBLOCKTYPE_FLOPPY_2_88: |
| 1697 | case PDMBLOCKTYPE_FLOPPY_FAKE_15_6: |
| 1698 | case PDMBLOCKTYPE_FLOPPY_FAKE_63_5: |
| 1699 | case PDMBLOCKTYPE_HARD_DISK: |
| 1700 | parm2.command = 1; // Return the BPB for the media currently in the drive |
| 1701 | parm2.drive = 0; // unused |
| 1702 | |
| 1703 | memset(&bpb, 0, sizeof(bpb)); |
| 1704 | |
| 1705 | rc = DosDevIOCtl((HFILE)RTFileToNative(pThis->hFileDevice), IOCTL_DISK, DSK_GETDEVICEPARAMS, |
| 1706 | &parm2, parmlen2, &parmlen2, |
| 1707 | &bpb, datalen2, &datalen2); |
| 1708 | |
| 1709 | if (! rc) { |
| 1710 | cbSectors = bpb.cCylinders * bpb.cHeads * bpb.usSectorsPerTrack; |
| 1711 | *pcb = cbSectors * bpb.usBytesPerSector; |
| 1712 | rc = VINF_SUCCESS; |
| 1713 | } |
| 1714 | else |
| 1715 | { |
| 1716 | rc = RTErrConvertFromOS2(rc); |
| 1717 | Log(("DrvHostBaseGetMediaSize: ioctl DSK_GETDEVICEPARAMS(%s) failed, rc=%Rrc\n", |
| 1718 | pThis->pszDevice, rc)); |
| 1719 | return rc; |
| 1720 | } |
| 1721 | return rc; |
| 1722 | |
| 1723 | default: |
| 1724 | return VERR_NOT_SUPPORTED; |
| 1725 | } |