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