VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DrvHostBase-freebsd.cpp@ 64249

Last change on this file since 64249 was 64246, checked in by vboxsync, 9 years ago

Devices/Storage/DrvHost*: Move determining the medai size to the host specific sources

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.8 KB
Line 
1/* $Id: DrvHostBase-freebsd.cpp 64246 2016-10-13 13:08:51Z vboxsync $ */
2/** @file
3 * DrvHostBase - Host base drive access driver, FreeBSD specifics.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_DRV_HOST_BASE
18#include <sys/cdefs.h>
19#include <sys/param.h>
20#include <errno.h>
21#include <stdio.h>
22#include <cam/cam.h>
23#include <cam/cam_ccb.h>
24#include <cam/scsi/scsi_message.h>
25#include <cam/scsi/scsi_pass.h>
26#include <VBox/scsi.h>
27#include <iprt/log.h>
28
29#include "DrvHostBase.h"
30
31
32DECLHIDDEN(int) drvHostBaseScsiCmdOs(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMMEDIATXDIR enmTxDir,
33 void *pvBuf, uint32_t *pcbBuf, uint8_t *pbSense, size_t cbSense, uint32_t cTimeoutMillies)
34{
35 /*
36 * Minimal input validation.
37 */
38 Assert(enmTxDir == PDMMEDIATXDIR_NONE || enmTxDir == PDMMEDIATXDIR_FROM_DEVICE || enmTxDir == PDMMEDIATXDIR_TO_DEVICE);
39 Assert(!pvBuf || pcbBuf);
40 Assert(pvBuf || enmTxDir == PDMMEDIATXDIR_NONE);
41 Assert(pbSense || !cbSense);
42 AssertPtr(pbCmd);
43 Assert(cbCmd <= 16 && cbCmd >= 1);
44 const uint32_t cbBuf = pcbBuf ? *pcbBuf : 0;
45 if (pcbBuf)
46 *pcbBuf = 0;
47
48 Assert(pThis->ppScsiTaskDI);
49
50 int rc = VERR_GENERAL_FAILURE;
51 SCSITaskInterface **ppScsiTaskI = (*pThis->ppScsiTaskDI)->CreateSCSITask(pThis->ppScsiTaskDI);
52 if (!ppScsiTaskI)
53 return VERR_NO_MEMORY;
54 do
55 {
56 /* Setup the scsi command. */
57 SCSICommandDescriptorBlock cdb = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
58 memcpy(&cdb[0], pbCmd, cbCmd);
59 IOReturn irc = (*ppScsiTaskI)->SetCommandDescriptorBlock(ppScsiTaskI, cdb, cbCmd);
60 AssertBreak(irc == kIOReturnSuccess);
61
62 /* Setup the buffer. */
63 if (enmTxDir == PDMMEDIATXDIR_NONE)
64 irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, NULL, 0, 0, kSCSIDataTransfer_NoDataTransfer);
65 else
66 {
67 IOVirtualRange Range = { (IOVirtualAddress)pvBuf, cbBuf };
68 irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, &Range, 1, cbBuf,
69 enmTxDir == PDMMEDIATXDIR_FROM_DEVICE
70 ? kSCSIDataTransfer_FromTargetToInitiator
71 : kSCSIDataTransfer_FromInitiatorToTarget);
72 }
73 AssertBreak(irc == kIOReturnSuccess);
74
75 /* Set the timeout. */
76 irc = (*ppScsiTaskI)->SetTimeoutDuration(ppScsiTaskI, cTimeoutMillies ? cTimeoutMillies : 30000 /*ms*/);
77 AssertBreak(irc == kIOReturnSuccess);
78
79 /* Execute the command and get the response. */
80 SCSI_Sense_Data SenseData = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
81 SCSIServiceResponse ServiceResponse = kSCSIServiceResponse_Request_In_Process;
82 SCSITaskStatus TaskStatus = kSCSITaskStatus_GOOD;
83 UInt64 cbReturned = 0;
84 irc = (*ppScsiTaskI)->ExecuteTaskSync(ppScsiTaskI, &SenseData, &TaskStatus, &cbReturned);
85 AssertBreak(irc == kIOReturnSuccess);
86 if (pcbBuf)
87 *pcbBuf = (int32_t)cbReturned;
88
89 irc = (*ppScsiTaskI)->GetSCSIServiceResponse(ppScsiTaskI, &ServiceResponse);
90 AssertBreak(irc == kIOReturnSuccess);
91 AssertBreak(ServiceResponse == kSCSIServiceResponse_TASK_COMPLETE);
92
93 if (TaskStatus == kSCSITaskStatus_GOOD)
94 rc = VINF_SUCCESS;
95 else if ( TaskStatus == kSCSITaskStatus_CHECK_CONDITION
96 && pbSense)
97 {
98 memset(pbSense, 0, cbSense); /* lazy */
99 memcpy(pbSense, &SenseData, RT_MIN(sizeof(SenseData), cbSense));
100 rc = VERR_UNRESOLVED_ERROR;
101 }
102 /** @todo convert sense codes when caller doesn't wish to do this himself. */
103 /*else if ( TaskStatus == kSCSITaskStatus_CHECK_CONDITION
104 && SenseData.ADDITIONAL_SENSE_CODE == 0x3A)
105 rc = VERR_MEDIA_NOT_PRESENT; */
106 else
107 {
108 rc = enmTxDir == PDMMEDIATXDIR_NONE
109 ? VERR_DEV_IO_ERROR
110 : enmTxDir == PDMMEDIATXDIR_FROM_DEVICE
111 ? VERR_READ_ERROR
112 : VERR_WRITE_ERROR;
113 if (pThis->cLogRelErrors++ < 10)
114 LogRel(("DVD scsi error: cmd={%.*Rhxs} TaskStatus=%#x key=%#x ASC=%#x ASCQ=%#x (%Rrc)\n",
115 cbCmd, pbCmd, TaskStatus, SenseData.SENSE_KEY, SenseData.ADDITIONAL_SENSE_CODE,
116 SenseData.ADDITIONAL_SENSE_CODE_QUALIFIER, rc));
117 }
118 } while (0);
119
120 (*ppScsiTaskI)->Release(ppScsiTaskI);
121
122 return rc;
123}
124
125
126DECLHIDDEN(int) drvHostBaseGetMediaSizeOs(PDRVHOSTBASE pThis, uint64_t *pcb)
127{
128 /*
129 * Try a READ_CAPACITY command...
130 */
131 struct
132 {
133 uint32_t cBlocks;
134 uint32_t cbBlock;
135 } Buf = {0, 0};
136 uint32_t cbBuf = sizeof(Buf);
137 uint8_t abCmd[16] =
138 {
139 SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0,
140 0,0,0,0,0,0,0,0,0
141 };
142 int rc = drvHostBaseScsiCmdOs(pThis, abCmd, 6, PDMMEDIATXDIR_FROM_DEVICE, &Buf, &cbBuf, NULL, 0, 0);
143 if (RT_SUCCESS(rc))
144 {
145 Assert(cbBuf == sizeof(Buf));
146 Buf.cBlocks = RT_BE2H_U32(Buf.cBlocks);
147 Buf.cbBlock = RT_BE2H_U32(Buf.cbBlock);
148 //if (Buf.cbBlock > 2048) /* everyone else is doing this... check if it needed/right.*/
149 // Buf.cbBlock = 2048;
150 pThis->cbBlock = Buf.cbBlock;
151
152 *pcb = (uint64_t)Buf.cBlocks * Buf.cbBlock;
153 }
154 return rc;
155}
156
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette