| New on Forum
Join Date: Jul 2007
Posts: 5
| Re: Drive locked / reset drive For anyone interested, the problem ended up being with the state of the drive cache. The drive cache was waiting for more data. Synchronizing the drive cache solved half of the problem. This involved sending SCSI command 0x35 to the drive. The easy way to do this is to download sdparm.exe [ http://sg.torque.net/sg/sdparm.html#mozTocId891504]. The difficult way is to write some windows driver code that looks like the following:
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS
{
SCSI_PASS_THROUGH spt;
ULONG Filler; // realign buffers to double word boundary
UCHAR ucSenseBuf[32];
UCHAR ucDataBuf[1024];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
memset(&sptwb, 0,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.spt.PathId = 0;
sptwb.spt.TargetId = 0;
sptwb.spt.Lun = 0;
sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
sptwb.spt.SenseInfoLength = 24;
sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.spt.DataTransferLength = 192;
sptwb.spt.TimeOutValue = 120;
sptwb.spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) ;
sptwb.spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf );
sptwb.spt.Cdb[0] = 0xXX;
sptwb.spt.Cdb[1] = 0xXX;
sptwb.spt.Cdb[2] = 0xXX;
sptwb.spt.Cdb[3] = 0xXX;
dwLength = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
sptwb.spt.DataTransferLength;
dwStatus = DeviceIoControl(g_hUsbDriver,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
dwLength,
&dwReturn,
FALSE);
At this point the drive will respond. However, it is locked. There are two ways to fix this. The first way is to use sdparm.exe again. The second way is to unlock the drive using Windows driver code that looks like the following:
#include
#include
#include
#include
#include
HANDLE OpenVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
UINT uDriveType;
TCHAR szVolumeName[8];
TCHAR szRootName[5];
DWORD dwAccessFlags;
wsprintf(szRootName, szRootFormat, cDriveLetter);
uDriveType = GetDriveType(szRootName);
switch(uDriveType) {
case DRIVE_REMOVABLE:
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
break;
case DRIVE_CDROM:
dwAccessFlags = GENERIC_READ;
break;
default:
_tprintf(TEXT("Cannot eject. Drive type is incorrect.\n"));
return INVALID_HANDLE_VALUE;
}
wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);
hVolume = CreateFile( szVolumeName,
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE)
ReportError(TEXT("CreateFile"));
return hVolume;
}
BOOL CloseVolume(HANDLE hVolume)
{
return CloseHandle(hVolume);
}
#define LOCK_TIMEOUT 10000 // 10 Seconds
#define LOCK_RETRIES 20
BOOL LockVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
DWORD dwSleepAmount;
int nTryCount;
dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
// Do this in a loop until a timeout period has expired
for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
if (DeviceIoControl(hVolume,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL))
{
printf("locked volume\n");
return TRUE;
}
Sleep(dwSleepAmount);
}
printf("did not lock volume\n");
return FALSE;
}
BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
{
DWORD dwBytesReturned;
PREVENT_MEDIA_REMOVAL PMRBuffer;
PMRBuffer.PreventMediaRemoval = fPreventRemoval;
BOOL result = DeviceIoControl( hVolume,
IOCTL_STORAGE_MEDIA_REMOVAL,
&PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
NULL, 0,
&dwBytesReturned,
NULL);
printf("%s prevent removal\n",result ? "did" : "did not");
return result;
}
void main(int argc, char * argv[])
{
HANDLE cdrom = OpenVolume(argv[1][0]);
if(cdrom == INVALID_HANDLE_VALUE)
{
printf("invalid handle\n");
return;
}
if(LockVolume(cdrom) == false)
{
printf("could not lock volume\n");
return;
}
if(PreventRemovalOfVolume(cdrom, true) == false)
{
printf("could not prevent removal\n");
return;
}
CloseVolume(cdrom);
printf("complete\n");
return ;
}
In both accounts, sdparm is nicer. However, with the unlocking of the drive, I am not sure if there are any window side software locks being used in addition to the hardware lock on the drive. So, for unlocking it may be safer to do the windows call. You will need to download the Windows driver development kit in order to compile it, though. |