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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }