IOSCSIDeviceClass.cpp [plain text]
#define CFRUNLOOP_NEW_API 1
#include <CoreFoundation/CFMachPort.h>
#include "IOSCSIDeviceClass.h"
#include "IOCDBCommandClass.h"
#include "IOSCSIUserClient.h"
__BEGIN_DECLS
#include <mach/mach_interface.h>
#include <IOKit/iokitmig.h>
__END_DECLS
#define connectCheck() do { \
if (!fConnection) \
return kIOReturnNoDevice; \
} while (0)
#define openCheck() do { \
if (!fIsOpen) \
return kIOReturnNotOpen; \
} while (0)
#define allChecks() do { \
connectCheck(); \
openCheck(); \
} while (0)
IOCFPlugInInterface ** IOSCSIDeviceClass::alloc()
{
IOSCSIDeviceClass *me;
me = new IOSCSIDeviceClass;
if (me)
return (IOCFPlugInInterface **) &me->iunknown.pseudoVTable;
else
return 0;
}
IOSCSIDeviceClass::IOSCSIDeviceClass()
: IOSCSIIUnknown(&sIOCFPlugInInterfaceV1),
fService(MACH_PORT_NULL),
fConnection(MACH_PORT_NULL),
fAsyncPort(MACH_PORT_NULL),
fIsOpen(false),
fIsLUNZero(false)
{
fCDBDevice.pseudoVTable = (IUnknownVTbl *) &sCDBDeviceInterfaceV1;
fCDBDevice.obj = this;
fSCSIDevice.pseudoVTable = (IUnknownVTbl *) &sSCSIDeviceInterfaceV1;
fSCSIDevice.obj = this;
}
IOSCSIDeviceClass::~IOSCSIDeviceClass()
{
if (fConnection) {
IOServiceClose(fConnection);
fConnection = MACH_PORT_NULL;
}
if (fService) {
IOObjectRelease(fService);
fService = MACH_PORT_NULL;
}
}
HRESULT IOSCSIDeviceClass::queryInterface(REFIID iid, void **ppv)
{
CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid);
HRESULT res = S_OK;
if (CFEqual(uuid, kIOCDBCommandInterfaceID)) {
*ppv = (void *) allocCommand();
}
else if (CFEqual(uuid, IUnknownUUID)
|| CFEqual(uuid, kIOCFPlugInInterfaceID)) {
*ppv = &iunknown;
addRef();
}
else if (CFEqual(uuid, kIOCDBDeviceInterfaceID)) {
*ppv = &fCDBDevice;
addRef();
}
else if (CFEqual(uuid, kIOSCSIDeviceInterfaceID)) {
*ppv = &fSCSIDevice;
addRef();
}
else
*ppv = 0;
if (!*ppv)
res = E_NOINTERFACE;
CFRelease(uuid);
return res;
}
IOReturn IOSCSIDeviceClass::
probe(CFDictionaryRef propertyTable, io_service_t inService, SInt32 *order)
{
if (!inService || !IOObjectConformsTo(inService, "IOSCSIDevice"))
return kIOReturnBadArgument;
return kIOReturnSuccess;
}
IOReturn IOSCSIDeviceClass::
start(CFDictionaryRef propertyTable, io_service_t inService)
{
IOReturn res;
CFMutableDictionaryRef entryProperties = 0;
kern_return_t kr;
fService = inService;
res = IOServiceOpen(fService, mach_task_self(), 0, &fConnection);
if (res != kIOReturnSuccess)
return res;
connectCheck();
kr = IORegistryEntryCreateCFProperties(fService,
&entryProperties,
NULL, 0);
if (entryProperties) {
CFTypeRef val;
val = CFDictionaryGetValue(entryProperties,
CFSTR(kSCSIPropertyLun));
if (val && CFGetTypeID(val) == CFNumberGetTypeID()) {
int zeroVal = 0;
CFNumberRef zero = CFNumberCreate(NULL,
kCFNumberIntType,
&zeroVal);
fIsLUNZero = !CFNumberCompare((CFNumberRef) val, zero, 0);
CFRelease(zero);
}
CFRelease(entryProperties);
}
return kIOReturnSuccess;
}
IOReturn IOSCSIDeviceClass::
createAsyncEventSource(CFRunLoopSourceRef *source)
{
IOReturn ret;
CFMachPortRef cfPort;
CFMachPortContext context;
Boolean shouldFreeInfo;
if (!fAsyncPort) {
ret = createAsyncPort(0);
if (kIOReturnSuccess != ret)
return ret;
}
context.version = 1;
context.info = this;
context.retain = NULL;
context.release = NULL;
context.copyDescription = NULL;
cfPort = CFMachPortCreateWithPort(NULL, fAsyncPort,
(CFMachPortCallBack) IODispatchCalloutFromMessage,
&context, &shouldFreeInfo);
if (!cfPort)
return kIOReturnNoMemory;
fCFSource = CFMachPortCreateRunLoopSource(NULL, cfPort, 0);
CFRelease(cfPort);
if (!fCFSource)
return kIOReturnNoMemory;
if (source)
*source = fCFSource;
return kIOReturnSuccess;
}
CFRunLoopSourceRef IOSCSIDeviceClass::getAsyncEventSource()
{
return fCFSource;
}
IOReturn IOSCSIDeviceClass::createAsyncPort(mach_port_t *port)
{
IOReturn ret;
ret = IOCreateReceivePort(kOSAsyncCompleteMessageID, &fAsyncPort);
if (kIOReturnSuccess == ret) {
if (port)
*port = fAsyncPort;
if (fIsOpen) {
natural_t asyncRef[1];
mach_msg_type_number_t len = 0;
return io_async_method_structureI_structureO(
fConnection, fAsyncPort, asyncRef, 1,
kIOCDBUserClientSetAsyncPort, NULL, 0, NULL, &len);
}
}
return ret;
}
mach_port_t IOSCSIDeviceClass::getAsyncPort()
{
return fAsyncPort;
}
IOReturn IOSCSIDeviceClass::
getInquiryData(void *inquiryBuffer,
UInt32 inquiryBufSize,
UInt32 *inquiryDataSize)
{
connectCheck();
int args[6], i = 0;
args[i++] = (int) inquiryBufSize;
return io_connect_method_scalarI_structureO(fConnection,
kIOCDBUserClientGetInquiryData, args, i,
(char *) inquiryBuffer, (mach_msg_type_number_t *) inquiryDataSize);
}
IOReturn IOSCSIDeviceClass::open()
{
IOReturn ret;
connectCheck();
if (fIsOpen)
return kIOReturnSuccess;
mach_msg_type_number_t len = 0;
ret = io_connect_method_scalarI_scalarO(
fConnection, kIOCDBUserClientOpen, NULL, 0, NULL, &len);
if (ret != kIOReturnSuccess)
return ret;
fIsOpen = true;
if (fAsyncPort) {
natural_t asyncRef[1];
mach_msg_type_number_t len = 0;
ret = io_async_method_scalarI_scalarO(
fConnection, fAsyncPort, asyncRef, 1,
kIOCDBUserClientSetAsyncPort, NULL, 0, NULL, &len);
if (ret != kIOReturnSuccess) {
close();
return ret;
}
}
return ret;
}
IOReturn IOSCSIDeviceClass::close()
{
allChecks();
IOCDBCommandClass::
commandDeviceClosing((IOCDBDeviceInterface **) &fCDBDevice);
mach_msg_type_number_t len = 0;
(void) io_connect_method_scalarI_scalarO(fConnection,
kIOCDBUserClientClose, NULL, 0, NULL, &len);
fIsOpen = false;
fIsLUNZero = false;
return kIOReturnSuccess;
}
IOCDBCommandInterface **IOSCSIDeviceClass::allocCommand()
{
if (fIsOpen)
return IOCDBCommandClass::
alloc((IOCDBDeviceInterface **) &fCDBDevice, fConnection);
else
return 0;
}
IOReturn IOSCSIDeviceClass::abort()
{
allChecks();
mach_msg_type_number_t len = 0;
return io_connect_method_scalarI_scalarO(fConnection,
kIOCDBUserClientAbort, NULL, 0, NULL, &len);
}
IOReturn IOSCSIDeviceClass::reset()
{
allChecks();
mach_msg_type_number_t len = 0;
return io_connect_method_scalarI_scalarO(fConnection,
kIOCDBUserClientReset, NULL, 0, NULL, &len);
}
IOReturn IOSCSIDeviceClass::holdQueue(UInt32 queueType)
{
allChecks();
mach_msg_type_number_t len = 0;
int args[6], i = 0;
args[i++] = (int) queueType;
return io_connect_method_scalarI_scalarO(fConnection,
kIOSCSIUserClientHoldQueue, args, i, NULL, &len);
}
IOReturn IOSCSIDeviceClass::releaseQueue(UInt32 queueType)
{
allChecks();
mach_msg_type_number_t len = 0;
int args[6], i = 0;
args[i++] = (int) queueType;
return io_connect_method_scalarI_scalarO(fConnection,
kIOSCSIUserClientReleaseQueue, args, i, NULL, &len);
}
IOReturn IOSCSIDeviceClass::flushQueue(UInt32 queueType, IOReturn rc)
{
allChecks();
mach_msg_type_number_t len = 0;
int args[6], i = 0;
args[i++] = (int) queueType;
args[i++] = (int) rc;
return io_connect_method_scalarI_scalarO(fConnection,
kIOSCSIUserClientFlushQueue, args, i, NULL, &len);
}
IOReturn IOSCSIDeviceClass::setTargetParms(SCSITargetParms *targetParms)
{
allChecks();
mach_msg_type_number_t len = 0;
return io_connect_method_structureI_structureO(fConnection,
kIOSCSIUserClientSetTargetParms,
(char *) targetParms, sizeof(SCSITargetParms), NULL, &len);
}
IOReturn IOSCSIDeviceClass::getTargetParms(SCSITargetParms *targetParms)
{
allChecks();
mach_msg_type_number_t len = sizeof(SCSITargetParms);
return io_connect_method_structureI_structureO(fConnection,
kIOSCSIUserClientGetTargetParms,
NULL, 0, (char *) targetParms, &len);
}
IOReturn IOSCSIDeviceClass::setLunParms(SCSILunParms *lunParms)
{
allChecks();
mach_msg_type_number_t len = 0;
return io_connect_method_structureI_structureO(fConnection,
kIOSCSIUserClientSetLunParms,
(char *) lunParms, sizeof(SCSILunParms), NULL, &len);
}
IOReturn IOSCSIDeviceClass::getLunParms(SCSILunParms *lunParms)
{
allChecks();
mach_msg_type_number_t len = sizeof(SCSILunParms);
return io_connect_method_structureI_structureO(fConnection,
kIOSCSIUserClientGetLunParms,
NULL, 0, (char *) lunParms, &len);
}
IOReturn IOSCSIDeviceClass::
notifyIdle(void *target, IOCDBCallbackFunction callback, void *refcon)
{
allChecks();
mach_msg_type_number_t len = 0;
int args[6], i = 0;
args[i++] = (int) target;
args[i++] = (int) callback;
args[i++] = (int) refcon;
return io_connect_method_scalarI_scalarO(fConnection,
kIOSCSIUserClientNotifyIdle, args, i, NULL, &len);
}
IOCFPlugInInterface IOSCSIDeviceClass::sIOCFPlugInInterfaceV1 = {
0,
&IOSCSIIUnknown::genericQueryInterface,
&IOSCSIIUnknown::genericAddRef,
&IOSCSIIUnknown::genericRelease,
1, 0, &IOSCSIDeviceClass::deviceProbe,
&IOSCSIDeviceClass::deviceStart,
&IOSCSIDeviceClass::deviceClose
};
IOCDBDeviceInterface IOSCSIDeviceClass::sCDBDeviceInterfaceV1 = {
0,
&IOSCSIIUnknown::genericQueryInterface,
&IOSCSIIUnknown::genericAddRef,
&IOSCSIIUnknown::genericRelease,
&IOSCSIDeviceClass::deviceCreateAsyncEventSource,
&IOSCSIDeviceClass::deviceGetAsyncEventSource,
&IOSCSIDeviceClass::deviceCreateAsyncPort,
&IOSCSIDeviceClass::deviceGetAsyncPort,
&IOSCSIDeviceClass::deviceGetInquiryData,
&IOSCSIDeviceClass::deviceOpen,
&IOSCSIDeviceClass::deviceClose,
&IOSCSIDeviceClass::deviceAllocCommand,
&IOSCSIDeviceClass::deviceAbort,
&IOSCSIDeviceClass::deviceReset
};
IOSCSIDeviceStruct IOSCSIDeviceClass::sSCSIDeviceInterfaceV1 = {
0,
&IOSCSIIUnknown::genericQueryInterface,
&IOSCSIIUnknown::genericAddRef,
&IOSCSIIUnknown::genericRelease,
&IOSCSIDeviceClass::deviceCreateAsyncEventSource,
&IOSCSIDeviceClass::deviceGetAsyncEventSource,
&IOSCSIDeviceClass::deviceCreateAsyncPort,
&IOSCSIDeviceClass::deviceGetAsyncPort,
&IOSCSIDeviceClass::deviceGetInquiryData,
&IOSCSIDeviceClass::deviceOpen,
&IOSCSIDeviceClass::deviceClose,
&IOSCSIDeviceClass::deviceAllocCommand,
&IOSCSIDeviceClass::deviceAbort,
&IOSCSIDeviceClass::deviceReset,
&IOSCSIDeviceClass::deviceHoldQueue,
&IOSCSIDeviceClass::deviceReleaseQueue,
&IOSCSIDeviceClass::deviceFlushQueue,
&IOSCSIDeviceClass::deviceNotifyIdle,
&IOSCSIDeviceClass::deviceSetTargetParms,
&IOSCSIDeviceClass::deviceGetTargetParms,
&IOSCSIDeviceClass::deviceSetLunParms,
&IOSCSIDeviceClass::deviceGetLunParms
};
IOReturn IOSCSIDeviceClass::
deviceProbe(void *self,
CFDictionaryRef propertyTable,
io_service_t inService, SInt32 *order)
{ return getThis(self)->probe(propertyTable, inService, order); }
IOReturn IOSCSIDeviceClass::deviceStart(void *self,
CFDictionaryRef propertyTable,
io_service_t inService)
{ return getThis(self)->start(propertyTable, inService); }
IOReturn IOSCSIDeviceClass::deviceStop(void *self)
{ return getThis(self)->close(); }
IOReturn IOSCSIDeviceClass::
deviceCreateAsyncEventSource(void *self, CFRunLoopSourceRef *source)
{ return getThis(self)->createAsyncEventSource(source); }
CFRunLoopSourceRef IOSCSIDeviceClass::
deviceGetAsyncEventSource(void *self)
{ return getThis(self)->getAsyncEventSource(); }
IOReturn IOSCSIDeviceClass::
deviceCreateAsyncPort(void *self, mach_port_t *port)
{ return getThis(self)->createAsyncPort(port); }
mach_port_t IOSCSIDeviceClass::
deviceGetAsyncPort(void *self)
{ return getThis(self)->getAsyncPort(); }
IOReturn IOSCSIDeviceClass::
deviceGetInquiryData(void *self,
void *inquiryBuffer,
UInt32 inquiryBufSize,
UInt32 *inquiryDataSize)
{
return getThis(self)->getInquiryData(inquiryBuffer,
inquiryBufSize,
inquiryDataSize);
}
IOReturn IOSCSIDeviceClass::deviceOpen(void *self)
{ return getThis(self)->open(); }
IOReturn IOSCSIDeviceClass::deviceClose(void *self)
{ return getThis(self)->close(); }
IOCDBCommandInterface **IOSCSIDeviceClass::deviceAllocCommand(void *self)
{ return getThis(self)->allocCommand(); }
IOReturn IOSCSIDeviceClass::deviceAbort(void *self)
{ return getThis(self)->abort(); }
IOReturn IOSCSIDeviceClass::deviceReset(void *self)
{ return getThis(self)->reset(); }
IOReturn IOSCSIDeviceClass::deviceHoldQueue(void *self, UInt32 queueType)
{ return getThis(self)->holdQueue(queueType); }
IOReturn IOSCSIDeviceClass::deviceReleaseQueue(void *self, UInt32 queueType)
{ return getThis(self)->releaseQueue(queueType); }
IOReturn IOSCSIDeviceClass::
deviceFlushQueue(void *self, UInt32 queueType, IOReturn rc)
{ return getThis(self)->flushQueue(queueType, rc); }
IOReturn IOSCSIDeviceClass::
deviceNotifyIdle(void *self,
void *target, IOCDBCallbackFunction callback, void *refcon)
{ return getThis(self)->notifyIdle(target, callback, refcon); }
IOReturn IOSCSIDeviceClass::
deviceSetTargetParms(void *self, SCSITargetParms *targetParms)
{ return getThis(self)->setTargetParms(targetParms); }
IOReturn IOSCSIDeviceClass::
deviceGetTargetParms(void *self, SCSITargetParms *targetParms)
{ return getThis(self)->getTargetParms(targetParms); }
IOReturn IOSCSIDeviceClass::
deviceSetLunParms(void *self, SCSILunParms *lunParms)
{ return getThis(self)->setLunParms(lunParms); }
IOReturn IOSCSIDeviceClass::
deviceGetLunParms(void *self, SCSILunParms *lunParms)
{ return getThis(self)->getLunParms(lunParms); }