void IOVideoSampleStream::postFreeInputBuffer(UInt64 vbiTime, UInt64 outputTime, UInt64 totalFrameCount, UInt64 droppedFrameCount,UInt64 lastDisplayedSequenceNumber) { IOStreamBuffer* buf = OSDynamicCast(IOStreamBuffer, _freeBuffers->getObject(0)); if (NULL == buf) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - no free buffers\n"); if ((getOutputQueue())->entryCount > 0) { //all the free buffers are in the queue already so just alert the host (void) sendOutputNotification(); } return; } _freeBuffers->removeObject(0); IOMemoryDescriptor *ctrlDescriptor = OSDynamicCast(IOMemoryDescriptor, buf->getControlBuffer()); if (NULL != ctrlDescriptor) { USBLog(1, "IOVideoSampleStream got control buffer descriptor\n"); SampleVideoDeviceControlBuffer theBuffControl, readBackControl; USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - passed in vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld lastDisplayedSequenceNumber = %lld \n", vbiTime, outputTime, totalFrameCount, droppedFrameCount, lastDisplayedSequenceNumber); theBuffControl.vbiTime = vbiTime; theBuffControl.outputTime = outputTime; theBuffControl.totalFrameCount = totalFrameCount; theBuffControl.droppedFrameCount = droppedFrameCount; theBuffControl.firstVBITime = 0; theBuffControl.sequenceNumber = lastDisplayedSequenceNumber; theBuffControl.discontinuityFlags = 0; (void) ctrlDescriptor->prepare(); ctrlDescriptor->writeBytes(0, &theBuffControl, buf->getControlBuffer()->getLength()); ctrlDescriptor->readBytes(0, &readBackControl, buf->getControlBuffer()->getLength()); USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - control buffer info vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld sequencenumber = %lld\n", readBackControl.vbiTime, readBackControl.outputTime, readBackControl.totalFrameCount, readBackControl.droppedFrameCount,readBackControl.sequenceNumber); (void) ctrlDescriptor->complete(); } IOReturn result = enqueueOutputBuffer(buf, 0, buf->getDataBuffer()->getLength(), 0, buf->getControlBuffer()->getLength()); if (result != kIOReturnSuccess) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help enqueueOutputBuffer failed! (%x)\n", result); return; } result = sendOutputNotification(); if (result != kIOReturnSuccess) { USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help sendOutputNotification failed! (%x)\n", result); return; } }
int st_readwrite(dev_t dev, struct uio *uio, int ioflag) { IOSCSITape *st = IOSCSITape::devices[minor(dev)]; IOMemoryDescriptor *dataBuffer = IOMemoryDescriptorFromUIO(uio); int status = ENOSYS; IOReturn opStatus = kIOReturnError; int lastRealizedBytes = 0; if (dataBuffer == 0) return ENOMEM; dataBuffer->prepare(); opStatus = st->ReadWrite(dataBuffer, &lastRealizedBytes); dataBuffer->complete(); dataBuffer->release(); if (opStatus == kIOReturnSuccess) { uio_setresid(uio, uio_resid(uio) - lastRealizedBytes); if (st->blkno != -1) { if (st->IsFixedBlockSize()) st->blkno += (lastRealizedBytes / st->blksize); else st->blkno++; } status = KERN_SUCCESS; } else if (st->sense_flags & SENSE_FILEMARK) { if (st->fileno != -1) { st->fileno++; st->blkno = 0; } status = KERN_SUCCESS; } return status; }
bool IOFWUserLocalIsochPort::initWithUserDCLProgram ( AllocateParams * params, IOFireWireUserClient & userclient, IOFireWireController & controller ) { // sanity checking if ( params->programExportBytes == 0 ) { ErrorLog ( "No program!" ) ; return false ; } fLock = IORecursiveLockAlloc () ; if ( ! fLock ) { ErrorLog ( "Couldn't allocate recursive lock\n" ) ; return false ; } // init easy params fUserObj = params->userObj ; fUserClient = & userclient ; fDCLPool = NULL ; fProgramCount = 0; fStarted = false ; IOReturn error = kIOReturnSuccess ; // get user program ranges: IOAddressRange * bufferRanges = new IOAddressRange[ params->bufferRangeCount ] ; if ( !bufferRanges ) { error = kIOReturnNoMemory ; } if ( !error ) { error = fUserClient->copyUserData(params->bufferRanges,(mach_vm_address_t)bufferRanges, sizeof ( IOAddressRange ) * params->bufferRangeCount ) ; } // create descriptor for program buffers IOMemoryDescriptor * bufferDesc = NULL ; if ( ! error ) { IOByteCount length = 0 ; for ( unsigned index = 0; index < params->bufferRangeCount; ++index ) { length += bufferRanges[ index ].length ; } bufferDesc = IOMemoryDescriptor::withAddressRanges ( bufferRanges, params->bufferRangeCount, kIODirectionOutIn, fUserClient->getOwningTask() ) ; if ( ! bufferDesc ) { error = kIOReturnNoMemory ; } else { // IOLog( "IOFWUserLocalIsochPort::initWithUserDCLProgram - checkMemoryInRange status 0x%08lx\n", checkMemoryInRange( bufferDesc, 0x000000001FFFFFFF ) ); error = bufferDesc->prepare( kIODirectionPrepareToPhys32 ) ; FWTrace( kFWTIsoch, kTPIsochPortUserInitWithUserDCLProgram, (uintptr_t)(fUserClient->getOwner()->getController()->getLink()), error, length, 0 ); // IOLog( "IOFWUserLocalIsochPort::initWithUserDCLProgram - prep 32 checkMemoryInRange status 0x%08lx\n", checkMemoryInRange( bufferDesc, 0x000000001FFFFFFF ) ); } } // create map for buffers; we will need to get a virtual address for them IOMemoryMap * bufferMap = NULL ; if ( !error ) { bufferMap = bufferDesc->map() ; if ( !bufferMap ) { DebugLog( "Couldn't map program buffers\n" ) ; error = kIOReturnVMError ; } bufferDesc->release() ; } IOMemoryDescriptor * userProgramExportDesc = NULL ; if ( !error ) { userProgramExportDesc = IOMemoryDescriptor::withAddressRange( params->programData, params->programExportBytes, kIODirectionOut, fUserClient->getOwningTask() ) ; } // get map of program export data if ( userProgramExportDesc ) { error = userProgramExportDesc->prepare() ; } if ( !error ) { DCLCommand * opcodes = NULL ; switch ( params->version ) { case kDCLExportDataLegacyVersion : error = importUserProgram( userProgramExportDesc, params->bufferRangeCount, bufferRanges, bufferMap ) ; ErrorLogCond( error, "importUserProgram returned %x\n", error ) ; if ( ! error ) { opcodes = (DCLCommand*)fProgramBuffer ; } break ; case kDCLExportDataNuDCLRosettaVersion : fDCLPool = fUserClient->getOwner()->getBus()->createDCLPool() ; if ( ! fDCLPool ) { error = kIOReturnNoMemory ; } if ( !error ) { error = fDCLPool->importUserProgram( userProgramExportDesc, params->bufferRangeCount, bufferRanges, bufferMap ) ; } fProgramBuffer = new UInt8[ sizeof( DCLNuDCLLeader ) ] ; { DCLNuDCLLeader * leader = (DCLNuDCLLeader*)fProgramBuffer ; { leader->pNextDCLCommand = NULL ; // unused - always NULL leader->opcode = kDCLNuDCLLeaderOp ; leader->program = fDCLPool ; } opcodes = (DCLCommand*)leader ; } break ; default : ErrorLog ( "unsupported DCL program type\n" ) ; error = kIOReturnBadArgument ; break ; } ErrorLogCond( !opcodes, "Couldn't get opcodes\n" ) ; IODCLProgram * program = NULL ; if ( opcodes ) { // IOFWLocalIsochPort::printDCLProgram( opcodes ) ; IOFireWireBus::DCLTaskInfoAux infoAux ; { infoAux.version = 2 ; infoAux.u.v2.bufferMemoryMap = bufferMap ; infoAux.u.v2.workloop = params->options & kFWIsochPortUseSeparateKernelThread ? createRealtimeThread() : NULL ; infoAux.u.v2.options = (IOFWIsochPortOptions)params->options ; } IOFireWireBus::DCLTaskInfo info = { 0, 0, 0, 0, 0, 0, & infoAux } ; program = fUserClient->getOwner()->getController()->getLink()->createDCLProgram( params->talking, opcodes, & info, params->startEvent, params->startState, params->startMask ) ; bufferMap->release() ; // retained by DCL program bufferMap = NULL ; if ( infoAux.u.v2.workloop ) { // If we created a custom workloop, it will be retained by the program... // We can release our reference... infoAux.u.v2.workloop->release() ; } DebugLogCond( !program, "createDCLProgram returned nil\n" ) ; } if ( program ) { if ( ! super::init( program, & controller ) ) { ErrorLog ( "IOFWUserIsochPort::init failed\n" ) ; error = kIOReturnError ; } } else { DebugLog ( "Couldn't create DCL program\n" ) ; error = kIOReturnNoMemory ; } userProgramExportDesc->complete() ; userProgramExportDesc->release() ; userProgramExportDesc = NULL ; } delete [] bufferRanges ; InfoLog( "-IOFWUserLocalIsochPort::initWithUserDCLProgram error=%x (build date "__TIME__" "__DATE__")\n", error ) ; return ( ! error ) ; }
// // start // when this method is called, I have been selected as the driver for this device. // I can still return false to allow a different driver to load // bool local_IOath3kfrmwr::start(IOService *provider) { IOReturn err; const IOUSBConfigurationDescriptor *cd; // Do all the work here, on an IOKit matching thread. // 0.1 Get my USB Device DEBUG_LOG("%s(%p)::start!\n", getName(), this); pUsbDev = OSDynamicCast(IOUSBDevice, provider); if(!pUsbDev) { DEBUG_LOG("%s(%p)::start - Provider isn't a USB device!!!\n", getName(), this); return false; } // 0.2 Reset the device err = pUsbDev->ResetDevice(); if (err) { DEBUG_LOG("%s(%p)::start - failed to reset the device\n", getName(), this); pUsbDev->close(this); return false; } else IOLog("%s(%p)::start: device reset\n", getName(), this); // 0.3 Find the first config/interface int numconf = 0; if ((numconf = pUsbDev->GetNumConfigurations()) < 1) { DEBUG_LOG("%s(%p)::start - no composite configurations\n", getName(), this); return false; } else DEBUG_LOG("%s(%p)::start: num configurations %d\n", getName(), this, numconf); cd = pUsbDev->GetFullConfigurationDescriptor(0); // Set the configuration to the first config if (!cd) { DEBUG_LOG("%s(%p)::start - no config descriptor\n", getName(), this); return false; } // 1.0 Open the USB device if (!pUsbDev->open(this)) { DEBUG_LOG("%s(%p)::start - unable to open device for configuration\n", getName(), this); return false; } // 1.1 Set the configuration to the first config err = pUsbDev->SetConfiguration(this, cd->bConfigurationValue, true); if (err) { DEBUG_LOG("%s(%p)::start - unable to set the configuration\n", getName(), this); pUsbDev->close(this); return false; } DEBUG_LOG("%s(%p)::start - UPLOADED - %c\n", getName(), this,uploaded); //Uploading only one time if (!uploaded) { // 1.2 Get the status of the USB device (optional, for diag.) USBStatus status; err = pUsbDev->GetDeviceStatus(&status); if (err) { DEBUG_LOG("%s(%p)::start - unable to get device status\n", getName(), this); pUsbDev->close(this); return false; } else IOLog("%s(%p)::start: device status %d\n", getName(), this, (int)status); // 2.0 Find the interface for bulk endpoint transfers IOUSBFindInterfaceRequest request; request.bInterfaceClass = kIOUSBFindInterfaceDontCare; request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; request.bAlternateSetting = kIOUSBFindInterfaceDontCare; IOUSBInterface * intf = pUsbDev->FindNextInterface(NULL, &request); if (!intf) { DEBUG_LOG("%s(%p)::start - unable to find interface\n", getName(), this); pUsbDev->close(this); return false; } // 2.1 Open the interface if (!intf->open(this)) { DEBUG_LOG("%s(%p)::start - unable to open interface\n", getName(), this); pUsbDev->close(this); return false; } // 2.2 Get info on endpoints (optional, for diag.) int numep = intf->GetNumEndpoints(); DEBUG_LOG("%s(%p)::start: interface has %d endpoints\n", getName(), this, numep); UInt8 transferType = 0; UInt16 maxPacketSize = 0; UInt8 interval = 0; err = intf->GetEndpointProperties(0, 0x02, kUSBOut, &transferType, &maxPacketSize, &interval); if (err) { DEBUG_LOG("%s(%p)::start - failed to get endpoint 2 properties\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } else DEBUG_LOG("%s(%p)::start: EP2 %d %d %d\n", getName(), this, transferType, maxPacketSize, interval); err = intf->GetEndpointProperties(0, 0x01, kUSBIn, &transferType, &maxPacketSize, &interval); if (err) { DEBUG_LOG("%s(%p)::start - failed to get endpoint 1 properties\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } else {DEBUG_LOG("%s(%p)::start: EP1 %d %d %d\n", getName(), this, transferType, maxPacketSize, interval); } // 2.3 Get the pipe for bulk endpoint 2 Out IOUSBPipe * pipe = intf->GetPipeObj(0x02); if (!pipe) { DEBUG_LOG("%s(%p)::start - failed to find bulk out pipe\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } /* // TODO: Test the alternative way to do it: IOUSBFindEndpointRequest pipereq; pipereq.type = kUSBBulk; pipereq.direction = kUSBOut; pipereq.maxPacketSize = BULK_SIZE; pipereq.interval = 0; IOUSBPipe *pipe = intf->FindNextPipe(NULL, &pipereq); pipe = intf->FindNextPipe(pipe, &pipereq); if (!pipe) { DEBUG_LOG("%s(%p)::start - failed to find bulk out pipe 2\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } */ // 3.0 Send request to Control Endpoint to initiate the firmware transfer IOUSBDevRequest ctlreq; ctlreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice); ctlreq.bRequest = USB_REQ_DFU_DNLOAD; ctlreq.wValue = 0; ctlreq.wIndex = 0; ctlreq.wLength = 20; ctlreq.pData = firmware_buf; #if 0 // Trying to troubleshoot the problem after Restart (with OSBundleRequired Root) for (int irep = 0; irep < 5; irep++) { // retry on error err = pUsbDev->DeviceRequest(&ctlreq); // (synchronous, will block) if (err) DEBUG_LOG("%s(%p)::start - failed to initiate firmware transfer (%d), retrying (%d)\n", getName(), this, err, irep+1); else break; } #else err = pUsbDev->DeviceRequest(&ctlreq); // (synchronous, will block) #endif if (err) { DEBUG_LOG("%s(%p)::start - failed to initiate firmware transfer (%d)\n", getName(), this, err); intf->close(this); pUsbDev->close(this); return false; } // 3.1 Create IOMemoryDescriptor for bulk transfers char buftmp[BULK_SIZE]; IOMemoryDescriptor * membuf = IOMemoryDescriptor::withAddress(&buftmp, BULK_SIZE, kIODirectionNone); if (!membuf) { DEBUG_LOG("%s(%p)::start - failed to map memory descriptor\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } err = membuf->prepare(); if (err) { DEBUG_LOG("%s(%p)::start - failed to prepare memory descriptor\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } // 3.2 Send the rest of firmware to the bulk pipe char * buf = firmware_buf; int size = sizeof(firmware_buf); buf += 20; size -= 20; int ii = 1; while (size) { int to_send = size < BULK_SIZE ? size : BULK_SIZE; memcpy(buftmp, buf, to_send); err = pipe->Write(membuf, 10000, 10000, to_send); if (err) { DEBUG_LOG("%s(%p)::start - failed to write firmware to bulk pipe (%d)\n", getName(), this, ii); intf->close(this); pUsbDev->close(this); return false; } buf += to_send; size -= to_send; ii++; } IOLog("%s(%p)::start: firmware was sent to bulk pipe\n", getName(), this); err = membuf->complete(); if (err) { DEBUG_LOG("%s(%p)::start - failed to complete memory descriptor\n", getName(), this); intf->close(this); pUsbDev->close(this); uploaded = false; return false; } /* // TODO: Test the alternative way to do it: IOMemoryDescriptor * membuf = IOMemoryDescriptor::withAddress(&firmware_buf[20], 246804-20, kIODirectionNone); // sizeof(firmware_buf) if (!membuf) { DEBUG_LOG("%s(%p)::start - failed to map memory descriptor\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } err = membuf->prepare(); if (err) { DEBUG_LOG("%s(%p)::start - failed to prepare memory descriptor\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } //err = pipe->Write(membuf); err = pipe->Write(membuf, 10000, 10000, 246804-20, NULL); if (err) { DEBUG_LOG("%s(%p)::start - failed to write firmware to bulk pipe\n", getName(), this); intf->close(this); pUsbDev->close(this); return false; } DEBUG_LOG("%s(%p)::start: firmware was sent to bulk pipe\n", getName(), this); */ // 4.0 Get device status (it fails, but somehow is important for operational device) err = pUsbDev->GetDeviceStatus(&status); if (err) { DEBUG_LOG("%s(%p)::start - unable to get device status\n", getName(), this); intf->close(this); pUsbDev->close(this); DEBUG_LOG("%s(%p)::start - Firmware Uploaded State Changed to - %c\n", getName(), this,uploaded); // Set the Upload State uploaded = true; return false; } else {DEBUG_LOG("%s(%p)::start: device status %d\n", getName(), this, (int)status); } // Close the interface intf->close(this); DEBUG_LOG("%s(%p)::start - Firmware Uploaded State Changed to - %c\n", getName(), this,uploaded); // Set the Upload State uploaded = true; } else { IOLog("%s(%p)::Firmware already uploaded\n", getName(), this); } // Close the USB device pUsbDev->close(this); return false; // return false to allow a different driver to load }
IOReturn SamplePCIUserClientClassName::method2( SampleStructForMethod2 * structIn, SampleResultsForMethod2 * structOut, IOByteCount inputSize, IOByteCount * outputSize ) { IOReturn err; IOMemoryDescriptor * memDesc = 0; UInt32 param1 = structIn->parameter1; uint64_t clientAddr = structIn->data_pointer; uint64_t size = structIn->data_length; // Rosetta if (fCrossEndian) { param1 = OSSwapInt32(param1); } IOLog("SamplePCIUserClient::method2(" UInt32_x_FORMAT ")\n", param1); IOLog( "fClientShared->string == \"%s\"\n", fClientShared->string ); structOut->results1 = 0x87654321; // Rosetta if (fCrossEndian) { structOut->results1 = OSSwapInt64(structOut->results1); clientAddr = OSSwapInt64(clientAddr); size = OSSwapInt64(size); } do { #if defined(__ppc__) && (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) // construct a memory descriptor for the out of line client memory // old 32 bit API - this will fail and log a backtrace if the task is 64 bit IOLog("The Pre-Leopard way to construct a memory descriptor\n"); memDesc = IOMemoryDescriptor::withAddress( (vm_address_t) clientAddr, (IOByteCount) size, kIODirectionNone, fTask ); if (memDesc == NULL) { IOLog("IOMemoryDescriptor::withAddress failed\n"); err = kIOReturnVMError; continue; } #else // 64 bit API - works on all tasks, whether 64 bit or 32 bit IOLog("The Leopard and later way to construct a memory descriptor\n"); memDesc = IOMemoryDescriptor::withAddressRange( clientAddr, size, kIODirectionNone, fTask ); if (memDesc == NULL) { IOLog("IOMemoryDescriptor::withAddresswithAddressRange failed\n"); err = kIOReturnVMError; continue; } #endif // Wire it and make sure we can write it err = memDesc->prepare( kIODirectionOutIn ); if (kIOReturnSuccess != err) { IOLog("IOMemoryDescriptor::prepare failed(0x%08x)\n", err); continue; } // Generate a DMA list for the client memory err = fDriver->generateDMAAddresses(memDesc); // Other methods to access client memory: // readBytes/writeBytes allow programmed I/O to/from an offset in the buffer char pioBuffer[ 200 ]; memDesc->readBytes(32, &pioBuffer, sizeof(pioBuffer)); IOLog("readBytes: \"%s\"\n", pioBuffer); // map() will create a mapping in the kernel address space. IOMemoryMap* memMap = memDesc->map(); if (memMap) { char* address = (char *) memMap->getVirtualAddress(); IOLog("kernel mapped: \"%s\"\n", address + 32); memMap->release(); } else { IOLog("memDesc map(kernel) failed\n"); } // this map() will create a mapping in the users (the client of this IOUserClient) address space. #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 memMap = memDesc->map(fTask, 0, kIOMapAnywhere); #else memMap = memDesc->createMappingInTask(fTask, 0, kIOMapAnywhere); #endif if (memMap) { #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 IOLog("The pre-Leopard way to construct a memory descriptor\n"); // old 32 bit API - this will truncate and log a backtrace if the task is 64 bit IOVirtualAddress address32 = memMap->getVirtualAddress(); IOLog("user32 mapped: " VirtAddr_FORMAT "\n", address32); #else IOLog("The Leopard and later way to construct a memory descriptor\n"); // new 64 bit API - same for 32 bit and 64 bit client tasks mach_vm_address_t address64 = memMap->getAddress(); IOLog("user64 mapped: 0x%016llx\n", address64); memMap->release(); #endif } else { IOLog("memDesc map(user) failed\n"); } // Done with the I/O now. memDesc->complete( kIODirectionOutIn ); } while ( false ); if (memDesc) memDesc->release(); return err; }
bool RadeonController::start( IOService * provider ) { if (!super::start(provider)) return false; device = OSDynamicCast(IOPCIDevice, provider); if (device == NULL) return false; //get user options OSBoolean *prop; OSDictionary *dict = OSDynamicCast(OSDictionary, getProperty("UserOptions")); bzero(&options, sizeof(UserOptions)); options.HWCursorSupport = FALSE; options.enableGammaTable = FALSE; options.enableOSXI2C = FALSE; options.lowPowerMode = FALSE; if (dict) { prop = OSDynamicCast(OSBoolean, dict->getObject("enableHWCursor")); if (prop) options.HWCursorSupport = prop->getValue(); prop = OSDynamicCast(OSBoolean, dict->getObject("debugMode")); if (prop) options.debugMode = prop->getValue(); if (options.debugMode) options.HWCursorSupport = FALSE; prop = OSDynamicCast(OSBoolean, dict->getObject("enableGammaTable")); if (prop) options.enableGammaTable = prop->getValue(); prop = OSDynamicCast(OSBoolean, dict->getObject("lowPowerMode")); if (prop) options.lowPowerMode = prop->getValue(); } options.verbosity = 1; #ifdef DEBUG if (0 == getRegistryRoot()->getProperty("RadeonDumpReady")) { getRegistryRoot()->setProperty("RadeonDumpReady", kOSBooleanTrue); DumpMsg.mVerbose = 1; DumpMsg.client = 1; DumpMsg.mMsgBufferSize = 65535; if (dict) { OSNumber *optionNum; optionNum = OSDynamicCast(OSNumber, dict->getObject("verboseLevel")); if (optionNum) DumpMsg.mVerbose = optionNum->unsigned32BitValue(); optionNum = OSDynamicCast(OSNumber, dict->getObject("MsgBufferSize")); if (optionNum) DumpMsg.mMsgBufferSize = max(65535, optionNum->unsigned32BitValue()); } DumpMsg.mMsgBufferEnabled = false; DumpMsg.mMsgBufferPos = 0; DumpMsg.mMessageLock = IOLockAlloc(); DumpMsg.mMsgBuffer = (char *) IOMalloc(DumpMsg.mMsgBufferSize); if (!DumpMsg.mMsgBuffer) { IOLog("error: couldn't allocate message buffer (%ld bytes)\n", DumpMsg.mMsgBufferSize); return false; } enableMsgBuffer(true); } else DumpMsg.client += 1; options.verbosity = DumpMsg.mVerbose; #endif device->setMemoryEnable(true); IOMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress2 ); if (IOMap == NULL) return false; FBMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); if (FBMap == NULL) return false; memoryMap.MMIOBase = (pointer) IOMap->getVirtualAddress(); memoryMap.MMIOMapSize = IOMap->getLength(); memoryMap.FbBase = (pointer) FBMap->getVirtualAddress(); memoryMap.FbMapSize = FBMap->getLength(); memoryMap.FbPhysBase = (unsigned long)FBMap->getPhysicalAddress(); memoryMap.bitsPerPixel = 32; memoryMap.bitsPerComponent = 8; memoryMap.colorFormat = 0; //0 for non-64 bit memoryMap.BIOSCopy = NULL; memoryMap.BIOSLength = 0; IOMemoryDescriptor * mem; mem = IOMemoryDescriptor::withPhysicalAddress((IOPhysicalAddress) RHD_VBIOS_BASE, RHD_VBIOS_SIZE, kIODirectionOut); if (mem) { memoryMap.BIOSCopy = (unsigned char *)IOMalloc(RHD_VBIOS_SIZE); if (memoryMap.BIOSCopy) { mem->prepare(kIODirectionOut); if (!(memoryMap.BIOSLength = mem->readBytes(0, memoryMap.BIOSCopy, RHD_VBIOS_SIZE))) { LOG("Cannot read BIOS image\n"); memoryMap.BIOSLength = 0; } if ((unsigned int)memoryMap.BIOSLength != RHD_VBIOS_SIZE) LOG("Read only %d of %d bytes of BIOS image\n", memoryMap.BIOSLength, RHD_VBIOS_SIZE); mem->complete(kIODirectionOut); } } if (dict) { const char typeKey[2][8] = {"@0,TYPE", "@1,TYPE"}; const char EDIDKey[2][8] = {"@0,EDID", "@1,EDID"}; const char fixedModesKey[2][17] = {"@0,UseFixedModes", "@1,UseFixedModes"}; OSString *type; OSData *edidData; OSBoolean *boolData; int i; for (i = 0;i < 2;i++) { type = OSDynamicCast(OSString, dict->getObject(typeKey[i])); if (!type) continue; edidData = OSDynamicCast(OSData, dict->getObject(EDIDKey[i])); if (edidData == NULL) continue; options.EDID_Block[i] = (unsigned char *)IOMalloc(edidData->getLength()); if (options.EDID_Block[i] == NULL) continue; strncpy(options.outputTypes[i], type->getCStringNoCopy(), outputTypeLength); bcopy(edidData->getBytesNoCopy(), options.EDID_Block[i], edidData->getLength()); options.EDID_Length[i] = edidData->getLength(); boolData = OSDynamicCast(OSBoolean, dict->getObject(fixedModesKey[i])); if (boolData) options.UseFixedModes[i] = boolData->getValue(); } } xf86Screens[0] = IONew(ScrnInfoRec, 1); //using global variable, will change it later ScrnInfoPtr pScrn = xf86Screens[0]; if (pScrn == NULL) return false; bzero(pScrn, sizeof(ScrnInfoRec)); MAKE_REG_ENTRY(&nub, device); pciRec.chipType = device->configRead16(kIOPCIConfigDeviceID); pciRec.subsysVendor = device->configRead16(kIOPCIConfigSubSystemVendorID); pciRec.subsysCard = device->configRead16(kIOPCIConfigSubSystemID); pciRec.biosSize = 16; //RHD_VBIOS_SIZE = 1 << 16 pScrn->PciTag = &nub; pScrn->PciInfo = &pciRec; pScrn->options = &options; pScrn->memPhysBase = (unsigned long)FBMap->getPhysicalAddress(); pScrn->fbOffset = 0; //scanout offset pScrn->bitsPerPixel = 32; pScrn->bitsPerComponent = 8; pScrn->colorFormat = 0; pScrn->depth = pScrn->bitsPerPixel; pScrn->memoryMap = &memoryMap; createNubs(provider); setModel(device); return true; }
IOReturn org_pqrs_driver_KeyRemap4MacBook_UserClient_kext::callback_synchronized_communication(const BridgeUserClientStruct* inputdata, uint64_t* outputdata) { IOReturn result = kIOReturnSuccess; IOMemoryDescriptor* memorydescriptor = NULL; if (! inputdata || ! outputdata) { result = kIOReturnBadArgument; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnBadArgument\n"); goto finish; } if (provider_ == NULL || isInactive()) { // Return an error if we don't have a provider. This could happen if the user process // called callback_synchronized_communication without calling IOServiceOpen first. // Or, the user client could be in the process of being terminated and is thus inactive. result = kIOReturnNotAttached; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnNotAttached\n"); goto finish; } if (! provider_->isOpen(this)) { // Return an error if we do not have the driver open. This could happen if the user process // did not call callback_open before calling this function. result = kIOReturnNotOpen; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnNotOpen\n"); goto finish; } memorydescriptor = IOMemoryDescriptor::withAddressRange(inputdata->data, inputdata->size, kIODirectionNone, task_); if (! memorydescriptor) { result = kIOReturnVMError; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication kIOReturnVMError\n"); goto finish; } // wire it and make sure we can write it result = memorydescriptor->prepare(kIODirectionOutIn); if (kIOReturnSuccess != result) { IOLOG_ERROR("UserClient_kext::callback_synchronized_communication IOMemoryDescriptor::prepare failed(0x%x)\n", result); goto finish; } { // this map() will create a mapping in the users (the client of this IOUserClient) address space. IOMemoryMap* memorymap = memorydescriptor->map(); if (! memorymap) { result = kIOReturnVMError; IOLOG_ERROR("UserClient_kext::callback_synchronized_communication IOMemoryDescriptor::map failed\n"); } else { mach_vm_address_t address = memorymap->getAddress(); handle_synchronized_communication(inputdata->type, inputdata->option, address, inputdata->size, outputdata); memorymap->release(); } } // Done with the I/O now. memorydescriptor->complete(kIODirectionOutIn); finish: if (memorydescriptor) { memorydescriptor->release(); } return result; }
IOReturn IrDAUserClient::getIrDALog(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize) { #if (hasTracing > 0) IOMemoryDescriptor *md; // make a memory descriptor for the client's big buffer unsigned char *input = (unsigned char *)pIn; mach_vm_address_t bigaddr; IOByteCount biglen; IrDALogInfo *info; require(inputSize == 9, Fail); require(outPutSize, Fail); require(*outPutSize == sizeof(IrDALogInfo), Fail); //bigaddr = input[1] << 24 | input[2] << 16 | input[3] << 8 | input[4]; //biglen = input[5] << 24 | input[6] << 16 | input[7] << 8 | input[8]; bcopy(&input[1], &bigaddr, sizeof(bigaddr)); bcopy(&input[5], &biglen, sizeof(biglen)); //IOLog("biglen is %d\n", biglen); // create and init the memory descriptor //md = IOMemoryDescriptor::withAddress(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction //use withAddressRange() and prepare() instead md = IOMemoryDescriptor::withAddressRange(bigaddr, biglen, kIODirectionOutIn, fTask); // REVIEW direction md->prepare(kIODirectionOutIn); require(md, Fail); info = IrDALogGetInfo(); // get the info block //ELG(info->hdr, info->hdrSize, 'irda', "info hdr"); //ELG(info->eventLog, info->eventLogSize, 'irda', "info events"); //ELG(info->msgBuffer, info->msgBufferSize, 'irda', "info msg buf"); bcopy(info, pOut, sizeof(*info)); // copy the info record back to the client *outPutSize = sizeof(*info); // set the output size (nop, it already is) // copy the buffer over now if there is room if (biglen >= info->hdrSize + info->eventLogSize + info->msgBufferSize) { IOByteCount ct; IOReturn rc; rc = md->prepare(kIODirectionNone); if (rc) {ELG(-1, rc, 'irda', "prepare failed"); } ct = md->writeBytes(0, info->hdr, info->hdrSize); if (ct != info->hdrSize) ELG(-1, rc, 'irda', "write of hdr failed"); ct = md->writeBytes(info->hdrSize, info->eventLog, info->eventLogSize); if (ct != info->eventLogSize) ELG(-1, rc, 'irda', "write of events failed"); ct = md->writeBytes(info->hdrSize+info->eventLogSize, info->msgBuffer, info->msgBufferSize); if (ct != info->msgBufferSize) ELG(-1, rc, 'irda', "write of msgs failed"); ELG(0, info->hdrSize+info->eventLogSize, 'irda', "wrote msgs at offset"); rc = md->complete(kIODirectionNone); if (!rc) { ELG(0, 0, 'irda', "complete worked"); } else { ELG(-1, rc, 'irda', "complete failed"); } // todo check return code of above before resetting the buffer IrDALogReset(); // reset the buffer now } md->release(); // free it return kIOReturnSuccess; Fail: #endif // hasTracing > 0 return kIOReturnBadArgument; }
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::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::WriteLogAtAddress ( ATASMARTWriteLogStruct * writeLogData, UInt32 inStructSize ) { IOReturn status = kIOReturnSuccess; IOSATCommand * command = NULL; IOMemoryDescriptor * buffer = NULL; DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__); if ( inStructSize != sizeof ( ATASMARTWriteLogStruct ) || writeLogData->numSectors > 16 || writeLogData->data_length > kSATMaxDataSize) { return kIOReturnBadArgument; } fOutstandingCommands++; if ( isInactive ( ) ) { status = kIOReturnNoDevice; goto ErrorExit; } fProvider->retain ( ); command = AllocateCommand ( ); if ( command == NULL ) { status = kIOReturnNoResources; goto ReleaseProvider; } //buffer = IOMemoryDescriptor::withAddress(writeLogData->buffer, writeLogData->bufferSize, kIODirectionOut); buffer = IOMemoryDescriptor::withAddressRange(writeLogData->data_pointer, writeLogData->data_length, kIODirectionOut, fTask); if ( buffer == NULL ) { status = kIOReturnVMError; goto ReleaseCommand; } status = buffer->prepare ( ); if ( status != kIOReturnSuccess ) { goto ReleaseBuffer; } command->setBuffer ( buffer ); command->setByteCount ( writeLogData->data_length ); command->setFeatures ( kFeaturesRegisterWriteLogAtAddress ); command->setOpcode ( kATAFnExecIO ); command->setTimeoutMS ( kATAThirtySecondTimeoutInMS ); command->setSectorCount ( writeLogData->numSectors ); command->setSectorNumber ( writeLogData->logAddress ); command->setCylLo ( kSMARTMagicCylinderLoValue ); command->setCylHi ( kSMARTMagicCylinderHiValue ); command->setCommand ( kATAcmdSMART ); command->setFlags ( mATAFlagIOWrite ); status = SendSMARTCommand ( command ); if ( status == kIOReturnIOError ) { if ( command->getEndErrorReg ( ) & 0x04 ) { ERROR_LOG ( "WriteLogAtAddress %d unsupported\n", writeLogData->logAddress ); status = kIOReturnUnsupported; } if ( command->getEndErrorReg ( ) & 0x10 ) { ERROR_LOG ( "WriteLogAtAddress %d unwriteable\n", writeLogData->logAddress ); status = kIOReturnNotWritable; } } 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; }