/*-----------------------------------------------------------------------------* * This routine queues an SRB to reset the SCSI Bus * *-----------------------------------------------------------------------------*/ void Sym8xxSCSIController::resetCommand( IOSCSIParallelCommand *scsiCommand ) { SRB * srb; IOMemoryDescriptor * iomd; // printf( "SCSI(Symbios8xx): resetCommand\n\r" ); srb = (SRB *) scsiCommand->getCommandData(); bzero( srb, sizeof(SRB) ); iomd = SCSI_IOMDs[ SCSI_RESET_IOMD ]; // special "target" for reset srb->srbIOMD = iomd; // save in SRB for later ->complete() call // ::initWithAddress() causes any previous contents of IOMD to be ::complete()'d if ( iomd->initWithAddress( srb, sizeof( SRB ), kIODirectionOutIn ) ) { iomd->prepare(); srb->srbPhys = (SRB *) iomd->getPhysicalAddress(); } else { // this should never happen, as we have allocated enough // IOMDs for MAX_SCSI_TARGETS plus 2 extra for reset and // a "fudge factor" just in case. panic( "Sym8xxSCSIController::resetCommand - IOMemoryDescriptor reinitialization failed" ); } srb->scsiCommand = scsiCommand; Sym8xxSCSIBusReset( srb ); }
/** * Start this service. */ bool org_virtualbox_VBoxGuest::start(IOService *pProvider) { if (!IOService::start(pProvider)) return false; /* Low level initialization should be performed only once */ if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) { IOService::stop(pProvider); return false; } m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); if (m_pIOPCIDevice) { if (isVmmDev(m_pIOPCIDevice)) { /* Enable memory response from VMM device */ m_pIOPCIDevice->setMemoryEnable(true); m_pIOPCIDevice->setIOEnable(true); IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); if (pMem) { IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ if((IOPortBasePhys >> 16) == 0) { RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; void *pvMMIOBase = NULL; uint32_t cbMMIO = 0; m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); if (m_pMap) { pvMMIOBase = (void *)m_pMap->getVirtualAddress(); cbMMIO = m_pMap->getLength(); } int rc = VBoxGuestInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_MacOS_x64, #else VBOXOSTYPE_MacOS, #endif 0); if (RT_SUCCESS(rc)) { rc = VbgdDarwinCharDevInit(); if (rc == KMOD_RETURN_SUCCESS) { if (setupVmmDevInterrupts(pProvider)) { /* register the service. */ registerService(); LogRel(("VBoxGuest: IOService started\n")); return true; } LogRel(("VBoxGuest: Failed to set up interrupts\n")); VbgdDarwinCharDevRemove(); } else LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); VBoxGuestDeleteDevExt(&g_DevExt); } else LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); if (m_pMap) { m_pMap->release(); m_pMap = NULL; } } } else LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); } else
/*-----------------------------------------------------------------------------* * *-----------------------------------------------------------------------------*/ void Sym8xxSCSIController::executeCommand( IOSCSIParallelCommand *scsiCommand ) { SRB *srb = NULL; SCSICDBInfo scsiCDB; SCSITargetLun targetLun; Nexus *nexus; Nexus *nexusPhys; UInt32 len; bool isWrite; IOMemoryDescriptor * iomd; srb = (SRB *) scsiCommand->getCommandData(); bzero( srb, sizeof(SRB) ); srb->scsiCommand = scsiCommand; scsiCommand->getCDB( &scsiCDB ); scsiCommand->getTargetLun( &targetLun ); srb->target = targetLun.target; srb->lun = targetLun.lun; srb->srbCDBFlags = scsiCDB.cdbFlags; // 1 IOMD per target, since only 1 transaction possible with current architecture iomd = SCSI_IOMDs[(int) srb->target ]; srb->srbIOMD = iomd; // ::initWithAddress() causes any previous IOMDs to be ::complete()'d if ( iomd->initWithAddress( srb, sizeof( SRB ), kIODirectionOutIn ) ) { iomd->prepare(); srb->srbPhys = (SRB *) iomd->getPhysicalAddress(); } else { // this should never happen, as we have allocated enough // IOMDs for MAX_SCSI_TARGETS plus 1 extra for reset panic( "Sym8xxSCSIController::executeCommand - IOMemoryDescriptor reinitialization failed" ); } /* * Setup the Nexus struct. This part of the SRB is read/written both by the * script and the driver. */ nexus = &srb->nexus; nexusPhys = &srb->srbPhys->nexus; nexus->targetParms.target = srb->target; // printf( "SCSI(Symbios8xx): executeCommand: T/L = %d:%d Cmd = %08x CmdType = %d\n\r", // targetLun.target, targetLun.lun, (int)scsiCommand, scsiCommand->getCmdType() ); switch ( scsiCommand->getCmdType() ) { case kSCSICommandAbort: case kSCSICommandAbortAll: case kSCSICommandDeviceReset: Sym8xxAbortCommand( scsiCommand ); return; default: ; } /* * Set client data buffer pointers in the SRB */ scsiCommand->getPointers( &srb->xferDesc, &srb->xferCount, &isWrite ); srb->directionMask = (isWrite) ? 0x00000000 :0x01000000; nexus->cdb.ppData = OSSwapHostToLittleInt32((UInt32)&nexusPhys->cdbData); len = scsiCDB.cdbLength; nexus->cdb.length = OSSwapHostToLittleInt32( len ); // implicit copying of arrays is not desireable. explicitly spell out what is being copied // [rdar://problem/4092008] // nexus->cdbData = scsiCDB.cdb; bcopy( &scsiCDB.cdb, &nexus->cdbData, sizeof( nexus->cdbData ) ); Sym8xxCalcMsgs( scsiCommand ); /* * Setup initial data transfer list (SGList) */ nexus->ppSGList = (SGEntry *)OSSwapHostToLittleInt32((UInt32)&nexusPhys->sgListData[2]); Sym8xxUpdateSGList( srb ); Sym8xxStartSRB( srb ); }
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 ); }