- Timestamp:
- Apr 6, 2007 6:14:10 AM (18 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Builtins.cpp
r1763 r1965 102 102 if (VBOX_FAILURE(rc)) 103 103 return rc; 104 #if defined(VBOX_WITH_USB) && (defined(__ WIN__) || defined(__LINUX__) || defined(__L4ENV__))104 #if defined(VBOX_WITH_USB) && (defined(__L4ENV__) || defined(__LINUX__) || defined(__WIN__)) 105 105 rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceOHCI); 106 106 if (VBOX_FAILURE(rc)) … … 153 153 if (VBOX_FAILURE(rc)) 154 154 return rc; 155 #if !defined(__L4ENV__) && !defined(__DARWIN__) && !defined(__OS2__)155 #if defined(__DARWIN__) || defined(__LINUX__) || defined(__WIN__) 156 156 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostDVD); 157 157 if (VBOX_FAILURE(rc)) 158 158 return rc; 159 #endif 160 #if defined(__LINUX__) || defined(__WIN__) 159 161 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostFloppy); 160 162 if (VBOX_FAILURE(rc)) … … 185 187 return rc; 186 188 #endif 187 #if !defined(__DARWIN__) && !defined(__OS2__)189 #if defined(__L4ENV__) || defined(__LINUX__) || defined(__WIN__) 188 190 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostInterface); 189 191 if (VBOX_FAILURE(rc)) … … 203 205 return rc; 204 206 205 #if defined(VBOX_WITH_USB) && (defined(__ WIN__) || defined(__LINUX__) || defined(__L4ENV__))207 #if defined(VBOX_WITH_USB) && (defined(__L4ENV__) || defined(__LINUX__) || defined(__WIN__)) 206 208 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvVUSBRootHub); 207 209 if (VBOX_FAILURE(rc)) -
trunk/src/VBox/Devices/Makefile
r1931 r1965 122 122 VBoxDD_LIBS.darwin = \ 123 123 $(LIB_REM) 124 VBoxDD_LDFLAGS.darwin = -install_name @executable_path/VBoxDD.dylib -framework CoreAudio 124 VBoxDD_LDFLAGS.darwin = -install_name @executable_path/VBoxDD.dylib -framework CoreAudio -framework IOKit -framework Carbon 125 125 VBoxDD_LDFLAGS.linux = -Wl,--no-undefined 126 126 VBoxDD_LDFLAGS.l4 = -Wl,--no-undefined … … 128 128 129 129 # damn, fix this. 130 ifeq ($(BUILD_TARGET),win) 130 ifeq ($(BUILD_TARGET),win) 131 131 $(PATH_LIB)/VBoxDD2.lib: $(PATH_BIN)/VBoxDD2.dll 132 132 $(PATH_LIB)/VBoxDDU.lib: $(PATH_BIN)/VBoxDDU.dll … … 336 336 Network/slirp 337 337 Drivers_SOURCES = \ 338 Audio/audio.c \ 339 Audio/audiosniffer.c \ 340 Audio/mixeng.c \ 341 Audio/noaudio.c \ 342 Input/DrvKeyboardQueue.cpp \ 338 343 Input/DrvMouseQueue.cpp \ 339 Input/DrvKeyboardQueue.cpp \340 Storage/VBoxHDD.cpp \341 Storage/DrvBlock.cpp \342 Storage/VmdkHDD.cpp \343 Storage/DrvMediaISO.cpp \344 Storage/DrvRawImage.cpp \345 Storage/DrvHostBase.cpp \346 Storage/DrvHostDVD.cpp \347 Storage/DrvHostFloppy.cpp \348 Storage/DrvHostRawDisk.cpp \349 PC/DrvACPI.cpp \350 344 Network/DrvIntNet.cpp \ 345 Network/DrvNAT.cpp \ 351 346 Network/DrvNetSniffer.cpp \ 352 Network/ DrvNAT.cpp\347 Network/slirp/bootp.c \ 353 348 Network/slirp/cksum.c \ 349 Network/slirp/debug.c \ 354 350 Network/slirp/if.c \ 355 351 Network/slirp/ip_icmp.c \ 356 352 Network/slirp/ip_input.c \ 357 353 Network/slirp/ip_output.c \ 358 Network/slirp/slirp.c \359 354 Network/slirp/mbuf.c \ 360 355 Network/slirp/misc.c \ 361 356 Network/slirp/sbuf.c \ 357 Network/slirp/slirp.c \ 362 358 Network/slirp/socket.c \ 363 359 Network/slirp/tcp_input.c \ … … 367 363 Network/slirp/tftp.c \ 368 364 Network/slirp/udp.c \ 369 Network/slirp/bootp.c \ 370 Network/slirp/debug.c \ 371 Audio/audio.c \ 372 Audio/mixeng.c \ 373 Audio/noaudio.c \ 374 Audio/audiosniffer.c \ 365 PC/DrvACPI.cpp \ 375 366 Serial/DrvChar.cpp \ 376 Serial/DrvNamedPipe.cpp 367 Serial/DrvNamedPipe.cpp \ 368 Storage/DrvBlock.cpp \ 369 Storage/DrvHostBase.cpp \ 370 Storage/DrvHostDVD.cpp \ 371 Storage/DrvHostFloppy.cpp \ 372 Storage/DrvHostRawDisk.cpp \ 373 Storage/DrvMediaISO.cpp \ 374 Storage/DrvRawImage.cpp \ 375 Storage/VBoxHDD.cpp \ 376 Storage/VmdkHDD.cpp 377 377 378 378 # -- OS specific -- … … 380 380 ifeq ($(BUILD_TARGET),darwin) 381 381 Drivers_SOURCES := $(filter-out \ 382 Storage/DrvHost% \ 382 Storage/DrvHostRaw% \ 383 Storage/DrvHostFloppy% \ 383 384 , $(Drivers_SOURCES)) \ 384 385 Audio/coreaudio.c -
trunk/src/VBox/Devices/Storage/DrvHostBase.cpp
r262 r1965 26 26 *******************************************************************************/ 27 27 #define LOG_GROUP LOG_GROUP_DRV_HOST_BASE 28 #ifdef __LINUX__ 28 #ifdef __DARWIN__ 29 # include <mach/mach.h> 30 # include <Carbon/Carbon.h> 31 # include <IOKit/IOKitLib.h> 32 # include <IOKit/storage/IOStorageDeviceCharacteristics.h> 33 # include <IOKit/scsi-commands/SCSITaskLib.h> 34 # include <IOKit/scsi-commands/SCSICommandOperationCodes.h> 35 # include <mach/mach_error.h> 36 # include <VBox/scsi.h> 37 38 #elif defined(__L4ENV__) 39 /* Nothing special requires... yeah, right. */ 40 41 #elif defined(__LINUX__) 29 42 # include <sys/ioctl.h> 30 43 # include <sys/fcntl.h> … … 79 92 /*IN*/ FS_INFORMATION_CLASS FileSystemInformationClass ); 80 93 81 #elif defined(__L4ENV__) 82 83 #else /* !__WIN__ nor __LINUX__ nor __L4ENV__ */ 94 #else 84 95 # error "Unsupported Platform." 85 #endif /* !__WIN__ nor __LINUX__ nor __L4ENV__ */96 #endif 86 97 87 98 #include <VBox/pdm.h> … … 100 111 #include <iprt/asm.h> 101 112 #include <iprt/critsect.h> 113 #include <iprt/ctype.h> 102 114 103 115 #include "DrvHostBase.h" … … 120 132 */ 121 133 int rc; 134 #ifdef __DARWIN__ 135 if ( pThis->fMediaPresent 136 && pThis->ppScsiTaskDI 137 && pThis->cbBlock) 138 #else 122 139 if (pThis->fMediaPresent) 123 { 140 #endif 141 { 142 #ifdef __DARWIN__ 143 /* 144 * Issue a READ(12) request. 145 */ 146 const uint32_t LBA = off / pThis->cbBlock; 147 AssertReturn(!(off % pThis->cbBlock), VERR_INVALID_PARAMETER); 148 const uint32_t cBlocks = cbRead / pThis->cbBlock; 149 AssertReturn(!(cbRead % pThis->cbBlock), VERR_INVALID_PARAMETER); 150 uint8_t abCmd[16] = 151 { 152 SCSI_READ_12, 0, 153 RT_BYTE4(LBA), RT_BYTE3(LBA), RT_BYTE2(LBA), RT_BYTE1(LBA), 154 RT_BYTE4(cBlocks), RT_BYTE3(cBlocks), RT_BYTE2(cBlocks), RT_BYTE1(cBlocks), 155 0, 0, 0, 0, 0 156 }; 157 rc = DRVHostBaseScsiCmd(pThis, abCmd, 12, PDMBLOCKTXDIR_FROM_DEVICE, pvBuf, &cbRead, NULL, 0, 0); 158 159 #else 124 160 /* 125 161 * Seek and read. … … 143 179 Log(("%s-%d: drvHostBaseRead: RTFileSeek(%d,%#llx,) -> %Vrc\n", pThis->pDrvIns->pDrvReg->szDriverName, 144 180 pThis->pDrvIns->iInstance, pThis->FileDevice, off, rc)); 181 #endif 145 182 } 146 183 else … … 172 209 if (pThis->fMediaPresent) 173 210 { 211 #ifdef __DARWIN__ 212 /** @todo write support... */ 213 rc = VERR_WRITE_PROTECT; 214 215 #else 174 216 /* 175 217 * Seek and write. … … 187 229 Log(("%s-%d: drvHostBaseWrite: RTFileSeek(%d,%#llx,) -> %Vrc\n", 188 230 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->FileDevice, off, rc)); 231 #endif 189 232 } 190 233 else … … 211 254 if (pThis->fMediaPresent) 212 255 { 256 #ifdef __DARWIN__ 257 rc = VINF_SUCCESS; 258 /** @todo scsi device buffer flush... */ 259 #else 213 260 rc = RTFileFlush(pThis->FileDevice); 261 #endif 214 262 } 215 263 else … … 512 560 513 561 /** 514 * Wrapper for open / RTFileOpen. 562 * Wrapper for open / RTFileOpen / IOKit. 563 * 564 * @remark The Darwin code must correspond exactly to the enumeration 565 * done in Main/darwin/iokit.c. 515 566 */ 516 567 static int drvHostBaseOpen(PDRVHOSTBASE pThis, PRTFILE pFileDevice, bool fReadOnly) 517 568 { 518 #ifdef __LINUX__ 569 #ifdef __DARWIN__ 570 /* Darwin is kind of special... */ 571 Assert(!pFileDevice); NOREF(pFileDevice); 572 Assert(!pThis->cbBlock); 573 Assert(!pThis->MasterPort); 574 Assert(!pThis->ppMMCDI); 575 Assert(!pThis->ppScsiTaskDI); 576 577 /* 578 * Open the master port on the first invocation. 579 */ 580 kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &pThis->MasterPort); 581 AssertReturn(krc == KERN_SUCCESS, VERR_GENERAL_FAILURE); 582 583 /* 584 * Create a matching dictionary for searching for DVD services in the IOKit. 585 * 586 * [If I understand this correctly, plain CDROMs doesn't show up as 587 * IODVDServices. Too keep things simple, we will only support DVDs 588 * until somebody complains about it and we get hardware to test it on. 589 * (Unless I'm much mistaken, there aren't any (orignal) intel macs with 590 * plain cdroms.)] 591 */ 592 CFMutableDictionaryRef RefMatchingDict = IOServiceMatching("IODVDServices"); 593 AssertReturn(RefMatchingDict, NULL); 594 595 /* 596 * do the search and get a collection of keyboards. 597 */ 598 io_iterator_t DVDServices = NULL; 599 IOReturn irc = IOServiceGetMatchingServices(pThis->MasterPort, RefMatchingDict, &DVDServices); 600 AssertMsgReturn(irc == kIOReturnSuccess, ("irc=%d\n", irc), NULL); 601 RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */ 602 603 /* 604 * Enumerate the DVD drives (services). 605 * (This enumeration must be identical to the one performed in DrvHostBase.cpp.) 606 */ 607 int rc = VERR_FILE_NOT_FOUND; 608 unsigned i = 0; 609 io_object_t DVDService; 610 while ((DVDService = IOIteratorNext(DVDServices)) != 0) 611 { 612 /* 613 * Get the properties we use to identify the DVD drive. 614 * 615 * While there is a (weird 12 byte) GUID, it isn't persistent 616 * accross boots. So, we have to use a combination of the 617 * vendor name and product name properties with an optional 618 * sequence number for identification. 619 */ 620 CFMutableDictionaryRef PropsRef = 0; 621 kern_return_t krc = IORegistryEntryCreateCFProperties(DVDService, &PropsRef, kCFAllocatorDefault, kNilOptions); 622 if (krc == KERN_SUCCESS) 623 { 624 /* Get the Device Characteristics dictionary. */ 625 CFDictionaryRef DevCharRef = (CFDictionaryRef)CFDictionaryGetValue(PropsRef, CFSTR(kIOPropertyDeviceCharacteristicsKey)); 626 if (DevCharRef) 627 { 628 /* The vendor name. */ 629 char szVendor[128]; 630 char *pszVendor = &szVendor[0]; 631 CFTypeRef ValueRef = CFDictionaryGetValue(DevCharRef, CFSTR(kIOPropertyVendorNameKey)); 632 if ( ValueRef 633 && CFGetTypeID(ValueRef) == CFStringGetTypeID() 634 && CFStringGetCString((CFStringRef)ValueRef, szVendor, sizeof(szVendor), kCFStringEncodingUTF8)) 635 pszVendor = RTStrStrip(szVendor); 636 else 637 *pszVendor = '\0'; 638 639 /* The product name. */ 640 char szProduct[128]; 641 char *pszProduct = &szProduct[0]; 642 ValueRef = CFDictionaryGetValue(DevCharRef, CFSTR(kIOPropertyProductNameKey)); 643 if ( ValueRef 644 && CFGetTypeID(ValueRef) == CFStringGetTypeID() 645 && CFStringGetCString((CFStringRef)ValueRef, szProduct, sizeof(szProduct), kCFStringEncodingUTF8)) 646 pszProduct = RTStrStrip(szProduct); 647 else 648 *pszProduct = '\0'; 649 650 /* Construct the two names and compare thwm with the one we're searching for. */ 651 char szName1[256 + 32]; 652 char szName2[256 + 32]; 653 if (*pszVendor || *pszProduct) 654 { 655 if (*pszVendor && *pszProduct) 656 { 657 RTStrPrintf(szName1, sizeof(szName1), "%s %s", pszVendor, pszProduct); 658 RTStrPrintf(szName2, sizeof(szName2), "%s %s (#%u)", pszVendor, pszProduct, i); 659 } 660 else 661 { 662 strcpy(szName1, *pszVendor ? pszVendor : pszProduct); 663 RTStrPrintf(szName2, sizeof(szName2), "%s %s (#%u)", *pszVendor ? pszVendor : pszProduct, i); 664 } 665 } 666 else 667 { 668 RTStrPrintf(szName1, sizeof(szName1), "(#%u)", i); 669 strcpy(szName2, szName1); 670 } 671 672 if ( !strcmp(szName1, pThis->pszDeviceOpen) 673 || !strcmp(szName2, pThis->pszDeviceOpen)) 674 { 675 /* 676 * Found it! Now, get the client interface and stuff. 677 * Note that we could also query kIOSCSITaskDeviceUserClientTypeID here if the 678 * MMC client plugin is missing. For now we assume this won't be necessary. 679 */ 680 SInt32 Score = 0; 681 IOCFPlugInInterface **ppPlugInInterface = NULL; 682 krc = IOCreatePlugInInterfaceForService(DVDService, kIOMMCDeviceUserClientTypeID, kIOCFPlugInInterfaceID, 683 &ppPlugInInterface, &Score); 684 if (krc == KERN_SUCCESS) 685 { 686 HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface, 687 CFUUIDGetUUIDBytes(kIOMMCDeviceInterfaceID), 688 (LPVOID *)&pThis->ppMMCDI); 689 (*ppPlugInInterface)->Release(ppPlugInInterface); 690 ppPlugInInterface = NULL; 691 if (hrc == S_OK) 692 { 693 pThis->ppScsiTaskDI = (*pThis->ppMMCDI)->GetSCSITaskDeviceInterface(pThis->ppMMCDI); 694 if (pThis->ppScsiTaskDI) 695 rc = VINF_SUCCESS; 696 else 697 { 698 LogRel(("GetSCSITaskDeviceInterface failed on '%s'\n", pThis->pszDeviceOpen)); 699 rc = VERR_NOT_SUPPORTED; 700 (*pThis->ppMMCDI)->Release(pThis->ppMMCDI); 701 } 702 } 703 else 704 { 705 rc = VERR_GENERAL_FAILURE;//RTErrConvertFromDarwinCOM(krc); 706 pThis->ppMMCDI = NULL; 707 } 708 } 709 else /* Check for kIOSCSITaskDeviceUserClientTypeID? */ 710 rc = VERR_GENERAL_FAILURE;//RTErrConvertFromDarwinKern(krc); 711 712 /* 713 * Obtain exclusive access to the device 714 * (to prevent the host and/or user from interfering). 715 */ 716 if (VBOX_SUCCESS(rc)) 717 { 718 irc = (*pThis->ppScsiTaskDI)->ObtainExclusiveAccess(pThis->ppScsiTaskDI); 719 if (irc == kIOReturnSuccess) 720 rc = VINF_SUCCESS; 721 else if (irc == kIOReturnBusy) 722 rc = VERR_DRIVE_LOCKED; /* mounted. */ 723 else if (irc == kIOReturnExclusiveAccess) 724 rc = VERR_SHARING_VIOLATION; /* already used exclusivly. */ 725 else 726 rc = VERR_GENERAL_FAILURE; 727 } 728 729 /* Cleanup on failure. */ 730 if (VBOX_FAILURE(rc)) 731 { 732 if (pThis->ppScsiTaskDI) 733 { 734 (*pThis->ppScsiTaskDI)->Release(pThis->ppScsiTaskDI); 735 pThis->ppScsiTaskDI = NULL; 736 } 737 if (pThis->ppMMCDI) 738 { 739 (*pThis->ppMMCDI)->Release(pThis->ppMMCDI); 740 pThis->ppMMCDI = NULL; 741 } 742 } 743 744 IOObjectRelease(DVDService); 745 break; 746 } 747 } 748 CFRelease(PropsRef); 749 } 750 else 751 AssertMsgFailed(("krc=%#x\n", krc)); 752 753 IOObjectRelease(DVDService); 754 i++; 755 } 756 757 IOObjectRelease(DVDServices); 758 return rc; 759 760 #elif defined(__LINUX__) 761 /** @todo we've got RTFILE_O_NON_BLOCK now. Change the code to use RTFileOpen. */ 519 762 int FileDevice = open(pThis->pszDeviceOpen, (pThis->fReadOnlyConfig ? O_RDONLY : O_RDWR) | O_NONBLOCK); 520 763 if (FileDevice < 0) … … 522 765 *pFileDevice = FileDevice; 523 766 return VINF_SUCCESS; 767 524 768 #else 525 769 return RTFileOpen(pFileDevice, pThis->pszDeviceOpen, … … 528 772 } 529 773 774 530 775 /** 531 776 * (Re)opens the device. 777 * 778 * This is used to open the device during construction, but it's also used to re-open 779 * the device when a media is inserted. This re-open will kill off any cached data 780 * that Linux for some peculiar reason thinks should survive a media change... 532 781 * 533 782 * @returns VBOX status code. … … 536 785 static int drvHostBaseReopen(PDRVHOSTBASE pThis) 537 786 { 787 #ifndef __DARWIN__ /* Only *one* open for darwin. */ 538 788 LogFlow(("%s-%d: drvHostBaseReopen: '%s'\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->pszDeviceOpen)); 539 789 540 /*541 * Reopen the device to kill any cached data which for some peculiar reason stays on some OSes (linux)...542 */543 790 RTFILE FileDevice; 544 791 int rc = drvHostBaseOpen(pThis, &FileDevice, pThis->fReadOnlyConfig); … … 564 811 RTFileClose(pThis->FileDevice); 565 812 pThis->FileDevice = FileDevice; 813 #endif /* !__DARWIN__ */ 566 814 return VINF_SUCCESS; 567 815 } … … 577 825 static int drvHostBaseGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb) 578 826 { 579 #ifdef __WIN__ 827 #ifdef __DARWIN__ 828 /* 829 * Try a READ_CAPACITY command... 830 */ 831 struct 832 { 833 uint32_t cBlocks; 834 uint32_t cbBlock; 835 } Buf = {0, 0}; 836 size_t cbBuf = sizeof(Buf); 837 uint8_t abCmd[16] = 838 { 839 SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 840 0,0,0,0,0,0,0,0,0 841 }; 842 int rc = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_FROM_DEVICE, &Buf, &cbBuf, NULL, 0, 0); 843 if (VBOX_SUCCESS(rc)) 844 { 845 Assert(cbBuf == sizeof(Buf)); 846 Buf.cBlocks = RT_BE2H_U32(Buf.cBlocks); 847 Buf.cbBlock = RT_BE2H_U32(Buf.cbBlock); 848 //if (Buf.cbBlock > 2048) /* everyone else is doing this... check if it needed/right.*/ 849 // Buf.cbBlock = 2048; 850 pThis->cbBlock = Buf.cbBlock; 851 852 *pcb = (uint64_t)Buf.cBlocks * Buf.cbBlock; 853 } 854 return rc; 855 856 #elif defined(__WIN__) 580 857 /* use NT api, retry a few times if the media is being verified. */ 581 858 IO_STATUS_BLOCK IoStatusBlock = {0}; … … 610 887 #endif 611 888 } 889 890 891 #ifdef __DARWIN__ 892 /** 893 * Execute a SCSI command. 894 * 895 * @param pThis The instance data. 896 * @param pbCmd Pointer to the SCSI command. 897 * @param cbCmd The size of the SCSI command. 898 * @param enmTxDir The transfer direction. 899 * @param pvBuf The buffer. Can be NULL if enmTxDir is PDMBLOCKTXDIR_NONE. 900 * @param pcbBuf Where to get the buffer size from and put the actual transfer size. Can be NULL. 901 * @param pbSense Where to put the sense data. Can be NULL. 902 * @param cbSense Size of the sense data buffer. 903 * @param cTimeoutMillies The timeout. 0 mean the default timeout. 904 * 905 * @returns VINF_SUCCESS on success (no sense code). 906 * @returns VERR_UNRESOLVED_ERROR if sense code is present. 907 * @returns Some other VBox status code on failures without sense code. 908 * 909 * @todo Fix VERR_UNRESOLVED_ERROR abuse. 910 */ 911 DECLCALLBACK(int) DRVHostBaseScsiCmd(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMBLOCKTXDIR enmTxDir, 912 void *pvBuf, size_t *pcbBuf, uint8_t *pbSense, size_t cbSense, uint32_t cTimeoutMillies) 913 { 914 /* 915 * Minimal input validation. 916 */ 917 Assert(enmTxDir == PDMBLOCKTXDIR_NONE || enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE || enmTxDir == PDMBLOCKTXDIR_TO_DEVICE); 918 Assert(!pvBuf || (pcbBuf && *pcbBuf)); 919 Assert(pvBuf || enmTxDir == PDMBLOCKTXDIR_NONE); 920 Assert(pbSense || !cbSense); 921 AssertPtr(pbCmd); 922 Assert(cbCmd <= 16 && cbCmd >= 1); 923 const size_t cbBuf = pcbBuf ? *pcbBuf : 0; 924 if (pcbBuf) 925 *pcbBuf = 0; 926 927 # ifdef __DARWIN__ 928 Assert(pThis->ppScsiTaskDI); 929 930 int rc = VERR_GENERAL_FAILURE; 931 SCSITaskInterface **ppScsiTaskI = (*pThis->ppScsiTaskDI)->CreateSCSITask(pThis->ppScsiTaskDI); 932 if (!ppScsiTaskI) 933 return VERR_NO_MEMORY; 934 do 935 { 936 /* Setup the scsi command. */ 937 SCSICommandDescriptorBlock cdb = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; 938 memcpy(&cdb[0], pbCmd, cbCmd); 939 IOReturn irc = (*ppScsiTaskI)->SetCommandDescriptorBlock(ppScsiTaskI, cdb, cbCmd); 940 AssertBreak(irc == kIOReturnSuccess,); 941 942 /* Setup the buffer. */ 943 if (enmTxDir == PDMBLOCKTXDIR_NONE) 944 irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, NULL, 0, 0, kSCSIDataTransfer_NoDataTransfer); 945 else 946 { 947 IOVirtualRange Range = { (IOVirtualAddress)pvBuf, cbBuf }; 948 irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, &Range, 1, cbBuf, 949 enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE 950 ? kSCSIDataTransfer_FromTargetToInitiator 951 : kSCSIDataTransfer_FromInitiatorToTarget); 952 } 953 AssertBreak(irc == kIOReturnSuccess,); 954 955 /* Set the timeout. */ 956 irc = (*ppScsiTaskI)->SetTimeoutDuration(ppScsiTaskI, cTimeoutMillies ? cTimeoutMillies : 30000 /*ms*/); 957 AssertBreak(irc == kIOReturnSuccess,); 958 959 /* Execute the command and get the response. */ 960 SCSI_Sense_Data SenseData = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; 961 SCSIServiceResponse ServiceResponse = kSCSIServiceResponse_Request_In_Process; 962 SCSITaskStatus TaskStatus = kSCSITaskStatus_GOOD; 963 UInt64 cbReturned = 0; 964 irc = (*ppScsiTaskI)->ExecuteTaskSync(ppScsiTaskI, &SenseData, &TaskStatus, &cbReturned); 965 AssertBreak(irc == kIOReturnSuccess,); 966 if (pcbBuf) 967 *pcbBuf = cbReturned; 968 969 irc = (*ppScsiTaskI)->GetSCSIServiceResponse(ppScsiTaskI, &ServiceResponse); 970 AssertBreak(irc == kIOReturnSuccess,); 971 AssertBreak(ServiceResponse == kSCSIServiceResponse_TASK_COMPLETE,); 972 973 if (TaskStatus == kSCSITaskStatus_GOOD) 974 rc = VINF_SUCCESS; 975 else if ( TaskStatus == kSCSITaskStatus_CHECK_CONDITION 976 && pbSense) 977 { 978 memset(pbSense, 0, cbSense); /* lazy */ 979 memcpy(pbSense, &SenseData, RT_MIN(sizeof(SenseData), cbSense)); 980 rc = VERR_UNRESOLVED_ERROR; 981 } 982 /** @todo convert sense codes when caller doesn't wish to do this himself. */ 983 /*else if ( TaskStatus == kSCSITaskStatus_CHECK_CONDITION 984 && SenseData.ADDITIONAL_SENSE_CODE == 0x3A) 985 rc = VERR_MEDIA_NOT_PRESENT; */ 986 else 987 { 988 rc = enmTxDir == PDMBLOCKTXDIR_NONE 989 ? VERR_DEV_IO_ERROR 990 : enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE 991 ? VERR_READ_ERROR 992 : VERR_WRITE_ERROR; 993 if (pThis->cLogRelErrors++ < 10) 994 LogRel(("DVD scsi error: cmd={%.*Rhxs} TaskStatus=%#x key=%#x ASC=%#x ASCQ=%#x (%Vrc)\n", 995 cbCmd, pbCmd, TaskStatus, SenseData.SENSE_KEY, SenseData.ADDITIONAL_SENSE_CODE, 996 SenseData.ADDITIONAL_SENSE_CODE_QUALIFIER, rc)); 997 } 998 } while (0); 999 1000 (*ppScsiTaskI)->Release(ppScsiTaskI); 1001 1002 # endif 1003 1004 return rc; 1005 } 1006 #endif 612 1007 613 1008 … … 907 1302 */ 908 1303 if ( pThis->fLocked 1304 #ifdef __DARWIN__ 1305 && pThis->ppScsiTaskDI 1306 #else 909 1307 && pThis->FileDevice != NIL_RTFILE 1308 #endif 910 1309 && pThis->pfnDoLock) 911 1310 { … … 933 1332 #endif 934 1333 1334 #ifdef __DARWIN__ 1335 if (pThis->ppScsiTaskDI) 1336 { 1337 (*pThis->ppScsiTaskDI)->ReleaseExclusiveAccess(pThis->ppScsiTaskDI); 1338 (*pThis->ppScsiTaskDI)->Release(pThis->ppScsiTaskDI); 1339 pThis->ppScsiTaskDI = NULL; 1340 } 1341 if (pThis->ppMMCDI) 1342 { 1343 (*pThis->ppMMCDI)->Release(pThis->ppMMCDI); 1344 pThis->ppMMCDI = NULL; 1345 } 1346 if (pThis->MasterPort) 1347 { 1348 mach_port_deallocate(mach_task_self(), pThis->MasterPort); 1349 pThis->MasterPort = NULL; 1350 } 1351 #else 935 1352 if (pThis->FileDevice != NIL_RTFILE) 936 1353 { … … 939 1356 pThis->FileDevice = NIL_RTFILE; 940 1357 } 1358 #endif 941 1359 942 1360 if (pThis->pszDevice) … … 980 1398 pThis->pDrvIns = pDrvIns; 981 1399 pThis->ThreadPoller = NIL_RTTHREAD; 1400 #ifdef __DARWIN__ 1401 pThis->MasterPort = NULL; 1402 pThis->ppMMCDI = NULL; 1403 pThis->ppScsiTaskDI = NULL; 1404 pThis->cbBlock = 0; 1405 #else 982 1406 pThis->FileDevice = NIL_RTFILE; 1407 #endif 983 1408 pThis->enmType = enmType; 1409 //pThis->cErrors = 0; 984 1410 985 1411 pThis->pfnGetMediaSize = drvHostBaseGetMediaSize; … … 1197 1623 * Open the device. 1198 1624 */ 1625 #ifdef __DARWIN__ 1626 rc = drvHostBaseOpen(pThis, NULL, pThis->fReadOnlyConfig); 1627 #else 1199 1628 rc = drvHostBaseReopen(pThis); 1629 #endif 1200 1630 if (VBOX_FAILURE(rc)) 1201 1631 { 1202 char pszPathReal[256];1203 1632 char *pszDevice = pThis->pszDevice; 1204 if (RT_SUCCESS(RTPathReal(pszDevice, pszPathReal, sizeof(pszPathReal)))) 1205 pszDevice = pszPathReal; 1206 AssertMsgFailed(("Could not open host device %s, rc=%Vrc\n", pThis->pszDevice, rc)); 1633 #ifndef __DARWIN__ 1634 char szPathReal[256]; 1635 if (RT_SUCCESS(RTPathReal(pszDevice, szPathReal, sizeof(szPathReal)))) 1636 pszDevice = szPathReal; 1207 1637 pThis->FileDevice = NIL_RTFILE; 1638 #endif 1639 AssertMsgFailed(("Could not open host device %s, rc=%Vrc\n", pszDevice, rc)); 1208 1640 switch (rc) 1209 1641 { … … 1219 1651 "of that device"), 1220 1652 #endif 1221 psz PathReal, pThis->fReadOnlyConfig ? "readonly" : "read/write",1222 psz PathReal);1653 pszDevice, pThis->fReadOnlyConfig ? "readonly" : "read/write", 1654 pszDevice); 1223 1655 default: 1224 1656 return rc; -
trunk/src/VBox/Devices/Storage/DrvHostBase.h
r1 r1965 74 74 * This is invalid if no drive is in the drive. */ 75 75 uint64_t volatile cbSize; 76 #ifndef __DARWIN__ 76 77 /** The filehandle of the device. */ 77 78 RTFILE FileDevice; 79 #endif 78 80 79 81 /** Handle of the poller thread. */ … … 98 100 /** BIOS Geometry: Sectors. */ 99 101 uint32_t cSectors; 102 103 /** The number of errors that could go into the release log. (flood gate) */ 104 uint32_t cLogRelErrors; 105 106 #ifdef __DARWIN__ 107 /** The master port. */ 108 mach_port_t MasterPort; 109 /** The MMC-2 Device Interface. (This is only used to get the scsi task interface.) */ 110 MMCDeviceInterface **ppMMCDI; 111 /** The SCSI Task Device Interface. */ 112 SCSITaskDeviceInterface **ppScsiTaskDI; 113 /** The block size. Set when querying the media size. */ 114 uint32_t cbBlock; 115 #endif 100 116 101 117 #ifdef __WIN__ … … 145 161 void DRVHostBaseMediaNotPresent(PDRVHOSTBASE pThis); 146 162 DECLCALLBACK(void) DRVHostBaseDestruct(PPDMDRVINS pDrvIns); 163 #ifdef __DARWIN__ 164 DECLCALLBACK(int) DRVHostBaseScsiCmd(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMBLOCKTXDIR enmTxDir, 165 void *pvBuf, size_t *pcbBuf, uint8_t *pbSense, size_t cbSense, uint32_t cTimeoutMillies); 166 #endif 147 167 148 168 -
trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp
r1 r1965 26 26 *******************************************************************************/ 27 27 #define LOG_GROUP LOG_GROUP_DRV_HOST_DVD 28 #ifdef __LINUX__ 28 #ifdef __DARWIN__ 29 # include <mach/mach.h> 30 # include <Carbon/Carbon.h> 31 # include <IOKit/IOKitLib.h> 32 # include <IOKit/IOCFPlugIn.h> 33 # include <IOKit/scsi-commands/SCSITaskLib.h> 34 # include <IOKit/scsi-commands/SCSICommandOperationCodes.h> 35 # include <IOKit/storage/IOStorageDeviceCharacteristics.h> 36 # include <mach/mach_error.h> 37 # define USE_MEDIA_POLLING 38 39 #elif defined(__L4ENV__) 40 /* nothing (yet). */ 41 42 #elif defined __LINUX__ 29 43 # include <sys/ioctl.h> 30 44 /* This is a hack to work around conflicts between these linux kernel headers … … 39 53 # include <sys/fcntl.h> 40 54 # include <errno.h> 55 # define USE_MEDIA_POLLING 41 56 42 57 #elif defined(__WIN__) … … 44 59 # include <winioctl.h> 45 60 # include <ntddscsi.h> 46 47 #elif defined(__L4ENV__) 48 49 #else /* !__WIN__ nor __LINUX__ nor __L4ENV__ */ 61 # undef USE_MEDIA_POLLING 62 63 #else 50 64 # error "Unsupported Platform." 51 #endif /* !__WIN__ nor __LINUX__ nor __L4ENV__ */65 #endif 52 66 53 67 #include <VBox/pdm.h> … … 84 98 * Eject the disc. 85 99 */ 86 #ifdef __LINUX__ 100 #ifdef __DARWIN__ 101 uint8_t abCmd[16] = 102 { 103 SCSI_START_STOP_UNIT, 0, 0, 0, 2 /*eject+stop*/, 0, 104 0,0,0,0,0,0,0,0,0,0 105 }; 106 rc = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, NULL, 0, 0); 107 108 #elif defined(__LINUX__) 87 109 rc = ioctl(pThis->FileDevice, CDROMEJECT, 0); 88 110 if (rc < 0) … … 151 173 static DECLCALLBACK(int) drvHostDvdDoLock(PDRVHOSTBASE pThis, bool fLock) 152 174 { 153 #ifdef __LINUX__ 175 #ifdef __DARWIN__ 176 # if 0 /// @todo dig up the specification for this command and implement it. (not important on mac) 177 uint8_t abCmd[16] = 178 { 179 SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0, 180 0,0,0,0,0,0,0,0,0,0 181 }; 182 int rc = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, NULL, 0, 0); 183 # else 184 int rc = VINF_SUCCESS; 185 # endif 186 187 #elif defined(__LINUX__) 154 188 int rc = ioctl(pThis->FileDevice, CDROM_LOCKDOOR, (int)fLock); 155 189 if (rc < 0) … … 210 244 211 245 212 #ifdef __LINUX__246 #ifdef USE_MEDIA_POLLING 213 247 /** 214 248 * Do media change polling. … … 219 253 * Poll for media change. 220 254 */ 221 #ifdef __LINUX__ 255 #ifdef __DARWIN__ 256 AssertReturn(pThis->ppScsiTaskDI, VERR_INTERNAL_ERROR); 257 258 /* 259 * Issue a TEST UNIT READY request. 260 */ 261 bool fMediaChanged = false; 262 bool fMediaPresent = false; 263 uint8_t abCmd[16] = { SCSI_TEST_UNIT_READY, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; 264 uint8_t abSense[32]; 265 int rc2 = DRVHostBaseScsiCmd(pThis, abCmd, 6, PDMBLOCKTXDIR_NONE, NULL, NULL, abSense, sizeof(abSense), 0); 266 if (VBOX_SUCCESS(rc2)) 267 fMediaPresent = true; 268 else if ( rc2 == VERR_UNRESOLVED_ERROR 269 && abSense[2] == 6 /* unit attention */ 270 && ( (abSense[12] == 0x29 && abSense[13] < 5 /* reset */) 271 || (abSense[12] == 0x2a && abSense[13] == 0 /* parameters changed */) //??? 272 || (abSense[12] == 0x3f && abSense[13] == 0 /* target operating conditions have changed */) //??? 273 || (abSense[12] == 0x3f && abSense[13] == 2 /* changed operating definition */) //??? 274 || (abSense[12] == 0x3f && abSense[13] == 3 /* inquery parameters changed */) 275 || (abSense[12] == 0x3f && abSense[13] == 5 /* device identifier changed */) 276 ) 277 ) 278 { 279 fMediaPresent = false; 280 fMediaChanged = true; 281 /** @todo check this media chance stuff on Darwin. */ 282 } 283 284 #elif defined(__LINUX__) 222 285 bool fMediaPresent = ioctl(pThis->FileDevice, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK; 223 286 … … 243 306 * Poll for media change. 244 307 */ 245 bool fMediaChanged; 246 #ifdef __LINUX__ 247 fMediaChanged = ioctl(pThis->FileDevice, CDROM_MEDIA_CHANGED, CDSL_CURRENT) == 1; 248 308 #ifdef __DARWIN__ 309 /* taken care of above. */ 310 #elif defined(__LINUX__) 311 bool fMediaChanged = ioctl(pThis->FileDevice, CDROM_MEDIA_CHANGED, CDSL_CURRENT) == 1; 249 312 #else 250 313 # error "Unsupported platform." … … 252 315 if (fMediaChanged) 253 316 { 254 int rc;255 317 LogFlow(("drvHostDVDMediaThread: Media changed!\n")); 256 318 DRVHostBaseMediaNotPresent(pThis); … … 262 324 return rc; 263 325 } 264 #endif /* __LINUX__*/326 #endif /* USE_MEDIA_POLLING */ 265 327 266 328 267 329 /** @copydoc PDMIBLOCK::pfnSendCmd */ 268 static int drvHostDvdSendCmd(PPDMIBLOCK pInterface, const uint8_t *pbCmd, PDMBLOCKTXDIR enmTxDir, void *pvBuf, size_t *pcbBuf, uint8_t *pbStat, uint32_t cTimeoutMillies) 330 static int drvHostDvdSendCmd(PPDMIBLOCK pInterface, const uint8_t *pbCmd, PDMBLOCKTXDIR enmTxDir, void *pvBuf, size_t *pcbBuf, 331 uint8_t *pbStat, uint32_t cTimeoutMillies) 269 332 { 270 333 PDRVHOSTBASE pThis = PDMIBLOCK_2_DRVHOSTBASE(pInterface); 271 int direction;272 334 int rc; 273 335 LogFlow(("%s: cmd[0]=%#04x txdir=%d pcbBuf=%d timeout=%d\n", __FUNCTION__, pbCmd[0], enmTxDir, *pcbBuf, cTimeoutMillies)); 274 #ifdef __LINUX__ 336 337 #ifdef __DARWIN__ 338 /* 339 * Pass the request on to the internal scsi command interface. 340 * The command seems to be 12 bytes long, the docs a bit copy&pasty on the command length point... 341 */ 342 if (enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE) 343 memset(pvBuf, '\0', *pcbBuf); /* we got read size, but zero it anyway. */ 344 uint8_t abSense[32]; 345 rc = DRVHostBaseScsiCmd(pThis, pbCmd, 12, PDMBLOCKTXDIR_FROM_DEVICE, pvBuf, pcbBuf, abSense, sizeof(abSense), cTimeoutMillies); 346 if (rc == VERR_UNRESOLVED_ERROR) 347 { 348 *pbStat = abSense[2] & 0x0f; 349 rc = VINF_SUCCESS; 350 } 351 352 #elif defined(__L4ENV__) 353 /* Not really ported to L4 yet. */ 354 rc = VERR_INTERNAL_ERROR; 355 356 #elif defined(__LINUX__) 357 int direction; 275 358 struct cdrom_generic_command cgc; 276 359 request_sense sense; … … 331 414 * of data transferred (for packet commands with little data transfer 332 415 * it's 0). So just assume that everything worked ok. */ 416 333 417 #elif defined(__WIN__) 334 struct _REQ { 418 int direction; 419 struct _REQ 420 { 335 421 SCSI_PASS_THROUGH_DIRECT spt; 336 422 uint8_t aSense[18]; … … 386 472 rc = RTErrConvertFromWin32(GetLastError()); 387 473 Log2(("%s: scsistatus=%d bytes returned=%d tlength=%d\n", __FUNCTION__, Req.spt.ScsiStatus, cbReturned, Req.spt.DataTransferLength)); 388 #elif defined(__L4ENV__) 389 /* L4 is silently unsupported. */ 474 390 475 #else 391 476 # error "Unsupported platform." … … 444 529 pThis->IMount.pfnUnmount = drvHostDvdUnmount; 445 530 pThis->pfnDoLock = drvHostDvdDoLock; 531 #ifdef USE_MEDIA_POLLING 532 if (!fPassthrough) 533 pThis->pfnPoll = drvHostDvdPoll; 534 else 535 pThis->pfnPoll = NULL; 536 #endif 446 537 #ifdef __LINUX__ 447 if (!fPassthrough)448 pThis->pfnPoll = drvHostDvdPoll;449 else450 pThis->pfnPoll = NULL;451 538 pThis->pfnGetMediaSize = drvHostDvdGetMediaSize; 452 539 #endif
Note:
See TracChangeset
for help on using the changeset viewer.