IOReturn XboxOneControllerDriver::sendHello() { IOReturn ior = kIOReturnSuccess; IOMemoryDescriptor* hello = nullptr; IOByteCount bytesWritten = 0; constexpr size_t helloSize = sizeof XboxOneControllerHelloMessage; if (_interruptPipe == nullptr) // paranoid check { IO_LOG_DEBUG("_interruptPipe is null"); ior = kIOReturnInternalError; goto cleanup; } // Create the hello message that we're about to send to the controller. hello = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, helloSize); if (hello == nullptr) { IO_LOG_DEBUG("Could not allocate buffer for hello message."); ior = kIOReturnNoMemory; goto cleanup; } bytesWritten = hello->writeBytes(0, XboxOneControllerHelloMessage, helloSize); if (bytesWritten != helloSize) // paranoid check { ior = kIOReturnOverrun; goto cleanup; } // Now send the message ior = _interruptPipe->Write(hello, 0, 0, hello->getLength()); if (ior != kIOReturnSuccess) { IO_LOG_DEBUG("Couldn't send hello message to controller: %08x\n", ior); goto cleanup; } cleanup: if (hello != nullptr) { hello->release(); } return ior; }
bool AppleSamplePCI::start( IOService * provider ) { IOMemoryDescriptor * mem; IOMemoryMap * map; IOLog("AppleSamplePCI::start\n"); if( !super::start( provider )) return( false ); /* * Our provider class is specified in the driver property table * as IOPCIDevice, so the provider must be of that class. * The assert is just to make absolutely sure for debugging. */ assert( OSDynamicCast( IOPCIDevice, provider )); fPCIDevice = (IOPCIDevice *) provider; /* * Enable memory response from the card */ fPCIDevice->setMemoryEnable( true ); /* * Log some info about the device */ /* print all the device's memory ranges */ for( UInt32 index = 0; index < fPCIDevice->getDeviceMemoryCount(); index++ ) { mem = fPCIDevice->getDeviceMemoryWithIndex( index ); assert( mem ); IOLog("Range[%ld] %08lx:%08lx\n", index, mem->getPhysicalAddress(), mem->getLength()); } /* look up a range based on its config space base address register */ mem = fPCIDevice->getDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); if( mem ) IOLog("Range@0x%x %08lx:%08lx\n", kIOPCIConfigBaseAddress0, mem->getPhysicalAddress(), mem->getLength()); /* map a range based on its config space base address register, * this is how the driver gets access to its memory mapped registers * the getVirtualAddress() method returns a kernel virtual address * for the register mapping */ map = fPCIDevice->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); if( map ) { IOLog("Range@0x%x (%08lx) mapped to kernel virtual address %08x\n", kIOPCIConfigBaseAddress0, map->getPhysicalAddress(), map->getVirtualAddress()); /* release the map object, and the mapping itself */ map->release(); } /* read a config space register */ IOLog("Config register@0x%x = %08lx\n", kIOPCIConfigCommand, fPCIDevice->configRead32(kIOPCIConfigCommand) ); // construct a memory descriptor for a buffer below the 4Gb line & // so addressable by 32 bit DMA. This could be used for a // DMA program buffer for example IOBufferMemoryDescriptor * bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( // task to hold the memory kernel_task, // options kIOMemoryPhysicallyContiguous, // size 64*1024, // physicalMask - 32 bit addressable and page aligned 0x00000000FFFFF000ULL); if (bmd) { generateDMAAddresses(bmd); } else { IOLog("IOBufferMemoryDescriptor::inTaskWithPhysicalMask failed\n"); } fLowMemory = bmd; /* publish ourselves so clients can find us */ registerService(); return( true ); }
IOReturn SATSMARTUserClient::GetIdentifyData (UInt32 * dataOut, IOByteCount * outputSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s %p(%ld)\n", getClassName(), this, __FUNCTION__, dataOut, (long)(outputSize)); if (!dataOut || !outputSize || *outputSize < kATADefaultSectorSize ) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress(dataOut, kATADefaultSectorSize, kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( kATADefaultSectorSize ); command->setTransferChunkSize ( kATADefaultSectorSize ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setCommand ( kATAcmdDriveIdentify ); command->setFlags ( mATAFlagIORead ); command->setRegMask ( ( ataRegMask ) ( mATAErrFeaturesValid | mATAStatusCmdValid ) ); status = SendSMARTCommand ( command ); if ( status == kIOReturnSuccess ) { #if defined(__BIG_ENDIAN__) UInt8 * bufferToCopy = identifyDataPtr; // The identify device info needs to be byte-swapped on big-endian (ppc) // systems becuase it is data that is produced by the drive, read across a // 16-bit little-endian PCI interface, directly into a big-endian system. // Regular data doesn't need to be byte-swapped because it is written and // read from the host and is intrinsically byte-order correct. IOByteCount index; UInt8 temp; UInt8 * firstBytePtr; UInt8 * identifyDataPtr = ( UInt8 * )dataOut; for ( index = 0; index < buffer->getLength ( ); index += 2 ) { firstBytePtr = identifyDataPtr; // save pointer temp = *identifyDataPtr++; // Save Byte0, point to Byte1 *firstBytePtr = *identifyDataPtr; // Byte0 = Byte1 *identifyDataPtr++ = temp; // Byte1 = Byte0 } #endif *outputSize = buffer->getLength ( ); DEBUG_LOG("%s[%p]::%s cpy %p %p\n", getClassName(), this, __FUNCTION__, (void*)*outputSize, (void*)buffer->getLength()); } ReleaseBufferPrepared: buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %x\n", getClassName(), this, __FUNCTION__, status); return status; }
IOReturn SATSMARTUserClient::ReadDataThresholds (UInt32 * dataOut, IOByteCount * outputSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__); if (!dataOut || !outputSize || *outputSize != sizeof ( ATASMARTDataThresholds ) ) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress(dataOut, sizeof ( ATASMARTDataThresholds ), kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( sizeof ( ATASMARTDataThresholds ) ); command->setFeatures ( kFeaturesRegisterReadDataThresholds ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIORead ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "ReadDataThresholds unsupported\n" ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "ReadDataThresholds Not readable\n" ); status = kIOReturnNotReadable; } } *outputSize = buffer->getLength(); buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this, __FUNCTION__, status); return status; }
IOReturn SATSMARTUserClient::ReadLogAtAddress ( ATASMARTReadLogStruct * structIn, void * structOut, IOByteCount inStructSize, IOByteCount *outStructSize) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s %p(%ld) %p(%ld)\n", getClassName(), this, __FUNCTION__, structIn, (long)inStructSize, structOut, (long)(outStructSize)); if ( inStructSize != sizeof ( ATASMARTReadLogStruct ) || !outStructSize || *outStructSize < 1) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } buffer = IOMemoryDescriptor::withAddress (structOut, *outStructSize, kIODirectionIn); if ( buffer == NULL ) { status = kIOReturnNoResources; goto ReleaseCommand; } status = buffer->prepare ( ); DEBUG_LOG("%s[%p]::%s status %x\n", getClassName(), this, __FUNCTION__, status); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( buffer->getLength()); command->setFeatures ( kFeaturesRegisterReadLogAtAddress ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setSectorCount ( structIn->numSectors ); command->setSectorNumber ( structIn->logAddress ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIORead ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "ReadLogAtAddress %d unsupported\n", structIn->logAddress ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "ReadLogAtAddress %d unreadable\n", structIn->logAddress ); status = kIOReturnNotReadable; } } *outStructSize = buffer->getLength(); buffer->complete ( ); ReleaseBuffer: buffer->release ( ); buffer = NULL; ReleaseCommand: DeallocateCommand ( command ); command = NULL; ReleaseProvider: fProvider->release ( ); ErrorExit: fOutstandingCommands--; DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this, __FUNCTION__, status); return status; }