Beispiel #1
0
IOReturn
IOSCSITape::WriteFilemarks(int count)
{
	SCSITaskIdentifier	task		= NULL;
	IOReturn			status		= kIOReturnError;
	SCSITaskStatus		taskStatus	= kSCSITaskStatus_No_Status;
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);

	flags |= ST_WRITTEN_TOGGLE;

	if (WRITE_FILEMARKS_6(task, 0x0, 0x0, count, 0) == true)
		taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
		status = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return status;	
}
Beispiel #2
0
int
DoReadCapacity(UInt32 id, UInt32 bus, UInt32 *blockCount, UInt32 *blockSize)
{
    OSErr       status;
    Str255      errorText;
    static const SCSI_10_Byte_Command gCapacityCommand = {
	kScsiCmdReadCapacity, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    SCSI_Sense_Data senseData;
    DeviceIdent     scsiDevice;
    SCSI_Capacity_Data  capacityData;
    UInt32      temp;
    int rtn_value;

    scsiDevice.diReserved = 0;
    scsiDevice.bus = bus;
    scsiDevice.targetID = id;
    scsiDevice.LUN = 0;

    CLEAR(capacityData);

    status = DoSCSICommand(
		scsiDevice,
		"\pRead Capacity",
		(SCSI_CommandPtr) &gCapacityCommand,
		(Ptr) &capacityData,
		sizeof (SCSI_Capacity_Data),
		scsiDirectionIn,
		NULL,
		&senseData,
		errorText
		);

    if (status == noErr) {
	temp = capacityData.lbn4;
	temp = (temp << 8) | capacityData.lbn3;
	temp = (temp << 8) | capacityData.lbn2;
	temp = (temp << 8) | capacityData.lbn1;
	*blockCount = temp;

	temp = capacityData.len4;
	temp = (temp << 8) | capacityData.len3;
	temp = (temp << 8) | capacityData.len2;
	temp = (temp << 8) | capacityData.len1;
	*blockSize = temp;

	rtn_value = 1;
    } else {
	rtn_value = 0;
    }
    return rtn_value;
}
Beispiel #3
0
int
SCSI_ReadBlock(UInt32 id, UInt32 bus, UInt32 block_size, UInt32 block, UInt8 *address)
{
    OSErr                   status;
    Str255                  errorText;
    char*       msg;
    static SCSI_10_Byte_Command gReadCommand = {
	kScsiCmdRead10, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
    SCSI_Sense_Data         senseData;
    DeviceIdent scsiDevice;
    int rtn_value;
    long count;

//printf("scsi read %d:%d block %d size %d\n", bus, id, block, block_size);
    scsiDevice.diReserved = 0;
    scsiDevice.bus = bus;
    scsiDevice.targetID = id;
    scsiDevice.LUN = 0;

    gReadCommand.lbn4 = (block >> 24) & 0xFF;
    gReadCommand.lbn3 = (block >> 16) & 0xFF;
    gReadCommand.lbn2 = (block >> 8) & 0xFF;
    gReadCommand.lbn1 = block & 0xFF;

    count = 1;
    gReadCommand.len2 = (count >> 8) & 0xFF;
    gReadCommand.len1 = count & 0xFF;

    status = DoSCSICommand(
		scsiDevice,
		"\pRead",
		(SCSI_CommandPtr) &gReadCommand,
		(Ptr) address,
		count * block_size,
		scsiDirectionIn,
		NULL,
		&senseData,
		errorText
	);
    if (status == noErr) {
	rtn_value = 1;
    } else {
	rtn_value = 0;
    }
    return rtn_value;
}
Beispiel #4
0
IOReturn
IOSCSITape::GetDeviceBlockLimits(void)
{
	SCSITaskIdentifier		task			= NULL;
	IOReturn				status			= kIOReturnError;
	UInt8					blockLimitsData[6]	= { 0 };
	SCSITaskStatus			taskStatus		= kSCSITaskStatus_DeliveryFailure;
	IOMemoryDescriptor *	dataBuffer		= NULL;
	
	dataBuffer = IOMemoryDescriptor::withAddress(&blockLimitsData, 
												 sizeof(blockLimitsData), 
												 kIODirectionIn);

	require ((dataBuffer != 0), ErrorExit);
	
	task = GetSCSITask();
	
	require ((task != 0), ErrorExit);
	
	if (READ_BLOCK_LIMITS(task, dataBuffer, 0x00) == true)
		taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
	{
		// blkgran = blockLimitsData[0] & 0x1F;
		
		blkmin =
			(blockLimitsData[4] <<  8) |
			 blockLimitsData[5];
		
		blkmax =
			(blockLimitsData[1] << 16) |
			(blockLimitsData[2] <<  8) |
			 blockLimitsData[3];
		
		STATUS_LOG("min/max block size: %d/%d", blkmin, blkmax);
		
		status = kIOReturnSuccess;
	}

	ReleaseSCSITask(task);
	dataBuffer->release();
	
ErrorExit:
	
	return status;
}
Beispiel #5
0
int
DoInquiry(UInt32 id, UInt32 bus, UInt32 *devType)
{
    OSErr       status;
    Str255      errorText;
    static const SCSI_6_Byte_Command gInquiryCommand = {
	kScsiCmdInquiry, 0, 0, 0, kRequiredSCSIinquiryLength, 0
    };
    SCSI_Sense_Data senseData;
    DeviceIdent     scsiDevice;
    SCSI_Inquiry_Data  inquiryData;
    UInt32      temp;
    int rtn_value;

    scsiDevice.diReserved = 0;
    scsiDevice.bus = bus;
    scsiDevice.targetID = id;
    scsiDevice.LUN = 0;

    CLEAR(inquiryData);

    status = DoSCSICommand(
		scsiDevice,
		"\pInquiry",
		(SCSI_CommandPtr) &gInquiryCommand,
		(Ptr) &inquiryData,
		kRequiredSCSIinquiryLength,
		scsiDirectionIn,
		NULL,
		&senseData,
		errorText
		);

    if (status == noErr) {
	*devType = inquiryData.devType & kScsiDevTypeMask;
	rtn_value = 1;
    } else {
	rtn_value = 0;
    }
    return rtn_value;
}
Beispiel #6
0
IOReturn
IOSCSITape::SetDeviceDetails(SCSI_ModeSense_Default *modeData)
{
	IOReturn				status		= kIOReturnError;
	IOMemoryDescriptor *	dataBuffer	= NULL;
	SCSITaskIdentifier		task		= NULL;
	SCSITaskStatus			taskStatus	= kSCSITaskStatus_DeviceNotResponding;
	
	dataBuffer = IOMemoryDescriptor::withAddress(modeData,
												 sizeof(SCSI_ModeSense_Default),
												 kIODirectionOut);
	
	require((dataBuffer != 0), ErrorExit);
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);
	
	if (MODE_SELECT_6(task, 
					  dataBuffer, 
					  0x0, // PF
					  0x0, // SP
					  sizeof(SCSI_ModeSense_Default), 
					  0x00) == true)
	{
		taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT);
	}
	
	if (taskStatus == kSCSITaskStatus_GOOD)
	{
		status = kIOReturnSuccess;
	}
	
	ReleaseSCSITask(task);
	dataBuffer->release();
	
ErrorExit:
	
	return status;
}
Beispiel #7
0
int
DoTestUnitReady(UInt8 targetID, int bus)
{
    OSErr                   status;
    Str255                  errorText;
    char*       msg;
    static const SCSI_6_Byte_Command gTestUnitReadyCommand = {
	kScsiCmdTestUnitReady, 0, 0, 0, 0, 0
    };
    SCSI_Sense_Data         senseData;
    DeviceIdent scsiDevice;
    int rtn_value;

    scsiDevice.diReserved = 0;
    scsiDevice.bus = bus;
    scsiDevice.targetID = targetID;
    scsiDevice.LUN = 0;

    status = DoSCSICommand(
		scsiDevice,
		"\pTest Unit Ready",
		(SCSI_CommandPtr) &gTestUnitReadyCommand,
		NULL,
		0,
		scsiDirectionNone,
		NULL,
		&senseData,
		errorText
		);
    if (status == scsiNonZeroStatus) {
	rtn_value = -1;
    } else if (status != noErr) {
	rtn_value = 0;
    } else {
	rtn_value = 1;
    }
    return rtn_value;
}
Beispiel #8
0
IOReturn
IOSCSITape::LoadUnload(int loadUnload)
{
	SCSITaskIdentifier	task			= NULL;
	IOReturn			status			= kIOReturnError;
	SCSITaskStatus		taskStatus		= kSCSITaskStatus_DeviceNotResponding;
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);
	
	if (LOAD_UNLOAD(task, 0, 0, 0, 0, loadUnload, 0) == true)
		taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
		status = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return status;
}
Beispiel #9
0
IOReturn
IOSCSITape::Space(SCSISpaceCode type, int count)
{
	SCSITaskIdentifier	task			= NULL;
	IOReturn			status			= kIOReturnError;
	SCSITaskStatus		taskStatus		= kSCSITaskStatus_No_Status;
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);
	
	if (SPACE_6(task, type, count, 0) == true)
		taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
		status = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return status;	
}
Beispiel #10
0
IOReturn
IOSCSITape::Rewind(void)
{
	IOReturn			status		= kIOReturnError;
	SCSITaskIdentifier	task		= NULL;
	SCSITaskStatus		taskStatus	= kSCSITaskStatus_DeliveryFailure;
	
	task = GetSCSITask();
	
	require ((task != 0), ErrorExit);
	
	if (REWIND(task, 0, 0) == true)
		taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
		status = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return status;
}
Beispiel #11
0
IOReturn
IOSCSITape::TestUnitReady(void)
{
	SCSITaskIdentifier	task			= NULL;
	IOReturn			result			= kIOReturnError;
	SCSITaskStatus		taskStatus		= kSCSITaskStatus_DeviceNotResponding;
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);
	
	if (TEST_UNIT_READY(task, 0x00) == true)
		taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT);
	
	if (taskStatus == kSCSITaskStatus_GOOD)
		result = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return result;
}
Beispiel #12
0
/*
 *  GetDeviceDetails()
 *  Get mode sense details and set device parameters.
 *
 *  Would have ideally liked to use super::GetModeSense() but it appears
 *  to set the DBD bit and we need the descriptor values for density,
 *  etc.
 */
IOReturn
IOSCSITape::GetDeviceDetails(void)
{
	IOReturn				status		= kIOReturnError;
	SCSITaskIdentifier		task		= NULL;
	SCSITaskStatus			taskStatus	= kSCSITaskStatus_DeviceNotResponding;
	IOMemoryDescriptor *	dataBuffer	= NULL;
	SCSI_ModeSense_Default	modeData	= { 0 };

	dataBuffer = IOMemoryDescriptor::withAddress(&modeData,
												 sizeof(modeData),
												 kIODirectionIn);
	
	require((dataBuffer != 0), ErrorExit);
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);

	if (MODE_SENSE_6(task, 
					 dataBuffer, 
					 0x0,
					 0x0,
					 0x00,
					 sizeof(SCSI_ModeSense_Default), 
					 0x00) == true)
	{
		taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT);
	}
	
	if (taskStatus == kSCSITaskStatus_GOOD)
	{
		/* copy mode data for next MODE SELECT */
		bcopy(&modeData, &lastModeData, sizeof(SCSI_ModeSense_Default));
		
		blksize = 
			(modeData.descriptor.BLOCK_LENGTH[0] << 16) |
			(modeData.descriptor.BLOCK_LENGTH[1] <<  8) |
			 modeData.descriptor.BLOCK_LENGTH[2];
		
		density = modeData.descriptor.DENSITY_CODE;
		flags &= ~(ST_READONLY | ST_BUFF_MODE);
		
		if (modeData.header.DEVICE_SPECIFIC_PARAMETER & SMH_DSP_WRITE_PROT)
			flags |= ST_READONLY;
		
		if (modeData.header.DEVICE_SPECIFIC_PARAMETER & SMH_DSP_BUFF_MODE)
			flags |= ST_BUFF_MODE;

		STATUS_LOG("density code: %d, %d-byte blocks, write-%s, %sbuffered",
				   density, blksize,
				   flags & ST_READONLY ? "protected" : "enabled",
				   flags & ST_BUFF_MODE ? "" : "un");
		
		status = kIOReturnSuccess;
	}
	
	ReleaseSCSITask(task);
	dataBuffer->release();
	
ErrorExit:
	
	return status;
}
Beispiel #13
0
IOReturn
IOSCSITape::ReadWrite(IOMemoryDescriptor *dataBuffer, int *realizedBytes)
{
	SCSITaskIdentifier	task			= NULL;
	IOReturn			status			= kIOReturnNoResources;
	SCSITaskStatus		taskStatus		= kSCSITaskStatus_No_Status;
	bool				cmdStatus		= false;
	int					transferSize	= 0;
	
	require((dataBuffer != 0), ErrorExit);
	
	transferSize = dataBuffer->getLength();

	if (IsFixedBlockSize())
	{
		if (transferSize % blksize)
		{
			STATUS_LOG("must be multiple of block size");
			return kIOReturnNotAligned;
		}
		
		transferSize /= blksize;
	}
	
	task = GetSCSITask();
	require((task != 0), ErrorExit);
	
	if (dataBuffer->getDirection() == kIODirectionIn)
	{
		cmdStatus = READ_6(
			task, 
			dataBuffer, 
			blksize, 
			0x0,
			IsFixedBlockSize() ? 0x1 : 0x0,
			transferSize,
			0x00);
	}
	else
	{
		cmdStatus = WRITE_6(
			task, 
			dataBuffer, 
			blksize, 
			IsFixedBlockSize() ? 0x1 : 0x0,
			transferSize, 
			0x00);

		flags |= ST_WRITTEN_TOGGLE;
	}
	
	if (cmdStatus == true)
		taskStatus = DoSCSICommand(task, SCSI_MOTION_TIMEOUT);
		
	*realizedBytes = GetRealizedDataTransferCount(task);

	if (taskStatus == kSCSITaskStatus_GOOD)
		status = kIOReturnSuccess;
	
	ReleaseSCSITask(task);
	
ErrorExit:
	
	return status;
}
Beispiel #14
0
IOReturn
IOSCSITape::ReadPosition(SCSI_ReadPositionShortForm *readPos, bool vendor)
{
	SCSITaskIdentifier		task			= NULL;
	IOReturn				status			= kIOReturnError;
	SCSITaskStatus			taskStatus		= kSCSITaskStatus_DeviceNotResponding;
	IOMemoryDescriptor *	dataBuffer		= NULL;
	UInt8					readPosData[20] = { 0 };
	
	dataBuffer = IOMemoryDescriptor::withAddress(&readPosData, 
												 sizeof(readPosData), 
												 kIODirectionIn);
	
	require((dataBuffer != 0), ErrorExit);
	
	task = GetSCSITask();
	
	require((task != 0), ErrorExit);
	
	if (READ_POSITION(task, 
					  dataBuffer, 
					  (vendor ? kSCSIReadPositionServiceAction_ShortFormVendorSpecific : kSCSIReadPositionServiceAction_ShortFormBlockID), 
					  0x0, 
					  0x00) == true)
	{
		taskStatus = DoSCSICommand(task, SCSI_NOMOTION_TIMEOUT);
	}
	
	if (taskStatus == kSCSITaskStatus_GOOD)
	{
		readPos->flags = readPosData[0];
		readPos->partitionNumber = readPosData[1];
		
		readPos->firstLogicalObjectLocation =
			(readPosData[4]  << 24) |
			(readPosData[5]  << 16) |
			(readPosData[6]  <<  8) |
			 readPosData[7];
		
		readPos->lastLogicalObjectLocation =
			(readPosData[8]  << 24) |
			(readPosData[9]  << 16) |
			(readPosData[10] <<  8) |
			 readPosData[11];
		
		readPos->logicalObjectsInObjectBuffer =
			(readPosData[13] << 16) |
			(readPosData[14] <<  8) |
			 readPosData[15];
		
		readPos->bytesInObjectBuffer =
			(readPosData[16] << 24) |
			(readPosData[17] << 16) |
			(readPosData[18] <<  8) |
			 readPosData[19];
		
		status = kIOReturnSuccess;
	}
	
	ReleaseSCSITask(task);
	dataBuffer->release();
	
ErrorExit:
	
	return status;
}