/****************************************************************************** agtiapi_ProbeCard() Purpose: sets thisCardInst->cardIdIndex to structure variant consistent with card. ag_card_type[idx].vendorId we already determined is PCI_VENDOR_ID_PMC_SIERRA. Parameters: device_t dev, ag_card_info_t *thisCardInst, int thisCard Return: 0 - success other values are not as good Note: This implementation is tailored to FreeBSD in alignment with the probe functionality of the FreeBSD environment. ******************************************************************************/ STATIC int agtiapi_ProbeCard( device_t dev, ag_card_info_t *thisCardInst, int thisCard ) { int idx; u_int16_t agtiapi_vendor; // PCI vendor ID u_int16_t agtiapi_dev; // PCI device ID AGTIAPI_PRINTK("agtiapi_ProbeCard: start\n"); agtiapi_vendor = pci_get_vendor( dev ); // get PCI vendor ID agtiapi_dev = pci_get_device( dev ); // get PCI device ID for( idx = 0; idx < COUNT(ag_card_type); idx++ ) { if ( ag_card_type[idx].deviceId == agtiapi_dev && ag_card_type[idx].vendorId == agtiapi_vendor) { // device ID match memset( (void *)&agCardInfoList[ thisCard ], 0, sizeof(ag_card_info_t) ); thisCardInst->cardIdIndex = idx; thisCardInst->pPCIDev = dev; thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex; thisCardInst->cardID = pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n", thisCardInst->pPCIDev, thisCardInst ); device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] ); return 0; } } return 1; }
osGLOBAL bit32 ostiNumOfLUNIOCTLreq( tiRoot_t *root, void *param1, void *param2, void **tiRequestBody, tiIORequest_t **tiIORequest ) { bit32 status = IOCTL_CALL_SUCCESS; pccb_t pccb; AGTIAPI_PRINTK("ostiNumOfLUNIOCTLreq: start\n"); struct agtiapi_softc *pCard = TIROOT_TO_CARD(root); /* get a ccb */ if ((pccb = agtiapi_GetCCB(pCard)) == NULL) { printf("ostiNumOfLUNIOCTLreq - GetCCB ERROR\n"); status = IOCTL_CALL_FAIL; //BUG_ON(1); } *tiIORequest = (tiIORequest_t*)&pccb->tiIORequest; *tiRequestBody = &pccb->tdIOReqBody; AGTIAPI_PRINTK("ostiNumOfLUNIOCTLreq:end\n"); return status; }
// this is just stub code to allow compile and use of the module ... // now that a call to this function has been added with windows specific // intentions. osGLOBAL void ostiGetSenseKeyCount(tiRoot_t *root, bit32 fIsClear, void *SenseKeyCount, bit32 length ) { AGTIAPI_PRINTK( "ostiGetSenseKeyCount stub only: rt%p, fcl%d, kyCt%p, ln%d\n", root, fIsClear, SenseKeyCount, length ); }
osGLOBAL void ostiGetSCSIStatusCount(tiRoot_t *root, bit32 fIsClear, void *ScsiStatusCount, bit32 length ) { AGTIAPI_PRINTK( "ostiGetSCSIStatusCount: stub only rt%p, fcl%d, kyCt%p, ln%d\n", root, fIsClear, ScsiStatusCount, length ); }
/****************************************************************************** agtiapi_MemFree() Purpose: Free agtiapi_MemAlloc() allocated memory Parameters: ag_card_info_t *pCardInfo (IN) Pointer to card info structure Return: none ******************************************************************************/ STATIC void agtiapi_MemFree( ag_card_info_t *pCardInfo ) { U32 idx; // release memory vs. alloc in agtiapi_MemAlloc; cached case for( idx = 0; idx < pCardInfo->cacheIndex; idx++ ) { if( pCardInfo->tiCachedMem[idx] ) { free( pCardInfo->tiCachedMem[idx], M_PMC_MMAL ); AGTIAPI_PRINTK( "agtiapi_MemFree: TI_CACHED_MEM Mem[%d] %p\n", idx, pCardInfo->tiCachedMem[idx] ); } } // release memory vs. alloc in agtiapi_typhAlloc; used in agtiapi_MemAlloc struct agtiapi_softc *pmsc = pCardInfo->pCard; // get card reference if( pmsc->typh_busaddr != 0 ) { bus_dmamap_unload( pmsc->typh_dmat, pmsc->typh_mapp ); } if( pmsc->typh_mem != NULL ) { bus_dmamem_free( pmsc->typh_dmat, pmsc->typh_mem, pmsc->typh_mapp ); } if( pmsc->typh_dmat != NULL ) { bus_dma_tag_destroy( pmsc->typh_dmat ); } //reference values: // pCardInfo->dmaIndex // pCardInfo->tiDmaMem[idx].dmaVirtAddr // pCardInfo->tiDmaMem[idx].memSize // pCardInfo->tiDmaMem[idx].type == TI_CACHED_DMA_MEM // pCardInfo->tiDmaMem[idx].type == TI_DMA_MEM /* This code is redundant. Commenting out for now to maintain a placekeeper. Free actually takes place in agtiapi_ReleaseHBA as calls on osti_dmat. dm // release possible lower layer dynamic memory for( idx = 0; idx < AGTIAPI_DYNAMIC_MAX; idx++ ) { if( pCardInfo->dynamicMem[idx].dmaVirtAddr != NULL ) { printf( "agtiapi_MemFree: dynMem[%d] virtAddr" " %p / %lx size: %d\n", idx, pCardInfo->dynamicMem[idx].dmaVirtAddr, (long unsigned int)pCardInfo->dynamicMem[idx].dmaPhysAddr, pCardInfo->dynamicMem[idx].memSize ); if( pCardInfo->dynamicMem[idx].dmaPhysAddr ) some form of free call would go here ( pCardInfo->dynamicMem[idx].dmaVirtAddr, pCardInfo->dynamicMem[idx].memSize, ... ); else free case for cacheable memory would go here } } */ return; }
/****************************************************************************** agtiapi_MemAlloc() Purpose: Handle various memory allocation requests. Parameters: ag_card_info_t *pCardInfo (IN) Pointer to card info structure void **VirtAlloc (OUT) Allocated memory virtual address dma_addr_t *pDmaAddr (OUT) Allocated dma memory physical address void **VirtAddr (OUT) Aligned memory virtual address U32 *pPhysAddrUp (OUT) Allocated memory physical upper 32 bits U32 *pPhysAddrLow (OUT) Allocated memory physical lower 32 bits U32 MemSize (IN) Allocated memory size U32 Type (IN) Type of memory required U32 Align (IN) Required memory alignment Return: AGTIAPI_SUCCESS - success AGTIAPI_FAIL - fail ******************************************************************************/ STATIC agBOOLEAN agtiapi_MemAlloc( ag_card_info_t *thisCardInst, void **VirtAlloc, vm_paddr_t *pDmaAddr, void **VirtAddr, U32 *pPhysAddrUp, U32 *pPhysAddrLow, U32 MemSize, U32 Type, U32 Align ) { U32_64 alignOffset = 0; if( Align ) alignOffset = Align - 1; // printf( "agtiapi_MemAlloc: debug find mem TYPE, %d vs. CACHE %d, DMA %d \n", // ( Type & ( BIT(0) | BIT(1) ) ), TI_CACHED_MEM, TI_DMA_MEM ); if ((Type & (BIT(0) | BIT(1))) == TI_CACHED_MEM) { *VirtAlloc = malloc( MemSize + Align, M_PMC_MMAL, M_ZERO | M_NOWAIT ); *VirtAddr = (void *)(((U32_64)*VirtAlloc + alignOffset) & ~alignOffset); } else { struct agtiapi_softc *pmsc = thisCardInst->pCard; // get card reference U32 residAlign = 0; // find virt index value *VirtAlloc = (void*)( (U64)pmsc->typh_mem + pmsc->typhIdx ); *VirtAddr = (void *)( ( (U32_64)*VirtAlloc + alignOffset) & ~alignOffset ); if( *VirtAddr != *VirtAlloc ) residAlign = (U64)*VirtAddr - (U64)*VirtAlloc; // find alignment needed pmsc->typhIdx += residAlign + MemSize; // update index residAlign = 0; // reset variable for reuse // find phys index val pDmaAddr = (vm_paddr_t*)( (U64)pmsc->typh_busaddr + pmsc->tyPhsIx ); vm_paddr_t *lPhysAligned = (vm_paddr_t*)( ( (U64)pDmaAddr + alignOffset ) & ~alignOffset ); if( lPhysAligned != pDmaAddr ) residAlign = (U64)lPhysAligned - (U64)pDmaAddr; // find alignment needed pmsc->tyPhsIx += residAlign + MemSize; // update index *pPhysAddrUp = HIGH_32_BITS( (U64)lPhysAligned ); *pPhysAddrLow = LOW_32_BITS( (U64)lPhysAligned ); //printf( "agtiapi_MemAlloc: physIx 0x%x size 0x%x resid:0x%x " // "addr:0x%p addrAligned:0x%p Align:0x%x\n", // pmsc->tyPhsIx, MemSize, residAlign, pDmaAddr, lPhysAligned, // Align ); } if ( !*VirtAlloc ) { AGTIAPI_PRINTK( "agtiapi_MemAlloc memory allocation ERROR x%x\n", Type & (U32)(BIT(0) | BIT(1))); return AGTIAPI_FAIL; } return AGTIAPI_SUCCESS; }
/****************************************************************************** ostiInitiatorSMPCompleted() Purpose: IO request completion call back Parameters: tiRoot_t *ptiRoot (IN) Pointer to the HBA tiRoot tiIORequest_t *ptiSMPRequest (IN) Pointer to the SMP request structure tiIOStatus_t IOStatus (IN) I/O complated status U32 tiSMPInfoLen (IN) Number of bytes of response frame len tiFrameHandle (IN) Handle that referes to response frame U32 context (IN) Interrupt dealing context Returns: Note: ******************************************************************************/ void ostiInitiatorSMPCompleted(tiRoot_t *ptiRoot, tiIORequest_t *ptiSMPRequest, tiSMPStatus_t smpStatus, bit32 tiSMPInfoLen, void *tiFrameHandle, bit32 context) { struct agtiapi_softc *pCard; ccb_t *pccb; pCard = TIROOT_TO_CARD(ptiRoot); pccb = (ccb_t *)ptiSMPRequest->osData; AGTIAPI_PRINTK("ostiInitiatorSMPCompleted: start\n"); OSTI_OUT_ENTER(ptiRoot); pccb->ccbStatus = (U16)smpStatus; if(smpStatus != tiSMPSuccess) { AGTIAPI_PRINTK("ostiInitiatorSMPCompleted: SMP Error\n"); } else { union ccb *ccb = pccb->ccb; struct ccb_smpio *csmpio = &ccb->smpio; memcpy(csmpio->smp_response, tiFrameHandle, tiSMPInfoLen); csmpio->smp_response_len = tiSMPInfoLen; agtiapi_hexdump("ostiInitiatorSMPCompleted: Response Payload in CAM", (bit8 *)csmpio->smp_response, csmpio->smp_response_len); } pccb->flags |= REQ_DONE; agtiapi_QueueCCB(pCard, &pCard->smpDoneHead, &pCard->smpDoneTail AG_CARD_LOCAL_LOCK(&pCard->doneSMPLock), pccb); AGTIAPI_PRINTK("ostiInitiatorSMPCompleted: Done\n"); OSTI_OUT_LEAVE(ptiRoot); return; }
// this is just stub code to allow compile and use of the module ... // now that a call to this function has been added with windows specific // intentions. osGLOBAL bit32 ostiSetDeviceQueueDepth( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, bit32 QueueDepth ) { bit32 retVal = 0; struct agtiapi_softc *pCard = TIROOT_TO_CARD(tiRoot); ccb_t *pccb = (ccb_t *) tiIORequest->osData; tiDeviceHandle_t *tiDeviceHandle = pccb->devHandle; ag_device_t *pDevice = (ag_device_t *)tiDeviceHandle->osData; AGTIAPI_PRINTK( "ostiSetDeviceQueueDepth stub only: root%p, req%p, qdeep%d\n", tiRoot, tiIORequest, QueueDepth ); pDevice->qdepth = QueueDepth; return retVal; }
void osti_FastIOCb(tiRoot_t *ptiRoot, void *arg, tiIOStatus_t IOStatus, U32 statusDetail) { ccb_t *pccb = (ccb_t*)arg; ag_card_t *pCard; static int callNum = 0; callNum++; BUG_ON(!pccb); if ((callNum % CMDS_PER_IO_DUP) != 0) { goto err; } pccb->ccbStatus = IOStatus; pccb->scsiStatus = statusDetail; /* pccb->pSenseData is copied already */ if (pccb->flags & AGTIAPI_ABORT) { AGTIAPI_PRINTK("agtiapi_SuperIOCb: aborted ccb %p, flag %x\n", pccb, pccb->flags); pccb->startTime = 0; /* indicate aborted IO completion */ BUG_ON(1); goto err; } pCard = TIROOT_TO_CARD(ptiRoot); pccb->flags |= REQ_DONE; agtiapi_QueueCCB(pCard, &pCard->ccbDoneHead, &pCard->ccbDoneTail AG_CARD_LOCAL_LOCK(&pCard->doneLock), pccb); err: return; } /* osti_FastIOCb */
/****************************************************************************** PMC-Sierra TISA Initiator Device Driver for Linux 2.x.x. Module Name: osapi.c Abstract: Linux iSCSI/FC Initiator driver module itsdk required OS functions Environment: Part of oslayer module, Kernel or loadable module ******************************************************************************* ostiInitiatorEvent() Purpose: TI layer call back to OSlayer to inform events Parameters: tiRoot_t *ptiRoot (IN) Pointer to HBA data structure tiDeviceHandle_t *ptiDevHandle (IN) Pointer to device handle tiIntrEvenType_t evenType (IN) Event type tiIntrEventStatus_t evetStatus (IN) Event status void *parm (IN) pointer to even specific data Return: Note: TBD, further event process required. ******************************************************************************/ void ostiInitiatorEvent( tiRoot_t *ptiRoot, tiPortalContext_t *ptiPortalContext, tiDeviceHandle_t *ptiDevHandle, tiIntrEventType_t eventType, U32 eventStatus, void *parm ) { ag_portal_data_t *pPortalData; ag_portal_info_t *pPortalInfo; struct agtiapi_softc *pCard = TIROOT_TO_CARD( ptiRoot ); ccb_t *pccb; ccb_t *pTMccb; ccb_t *ccbIO; #ifdef AGTIAPI_EVENT_LOG AGTIAPI_PRINTK("Initiator Event:\n"); AGTIAPI_PRINTK("DevHandle %p, eventType 0x%x, eventStatus 0x%x\n", ptiDevHandle, eventType, eventStatus); AGTIAPI_PRINTK("Parameter: %s\n", (char *)parm); #endif AGTIAPI_PRINTK("ostiInitiatorEvent: eventType 0x%x eventStatus 0x%x\n", eventType, eventStatus); switch (eventType) { case tiIntrEventTypeCnxError: if (eventStatus == tiCnxUp) { AGTIAPI_PRINTK("tiIntrEventTypeCnxError - tiCnxUp!\n"); } if (eventStatus == tiCnxDown) { AGTIAPI_PRINTK("tiIntrEventTypeCnxError - tiCnxDown!\n"); } break; case tiIntrEventTypeDiscovery: pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(ptiPortalContext); pCard->flags |= AGTIAPI_CB_DONE; if (eventStatus == tiDiscOK) { AGTIAPI_PRINTK("eventStatus - tiDiscOK\n"); AGTIAPI_PRINTK("ostiInitiatorEvent: pcard %d eventStatus - tiDiscOK\n", pCard->cardNo ); PORTAL_STATUS(pPortalData) |= AGTIAPI_DISC_COMPLETE; #ifndef HOTPLUG_SUPPORT if (!(pCard->flags & AGTIAPI_INIT_TIME)) #else if (TRUE) #endif { agtiapi_GetDevHandle(pCard, &pPortalData->portalInfo, tiIntrEventTypeDiscovery, tiDiscOK); PORTAL_STATUS(pPortalData) |= (AGTIAPI_DISC_DONE | AGTIAPI_PORT_LINK_UP); } /* Trigger CheckIOTimeout */ callout_reset(&pCard->IO_timer, 20*hz, agtiapi_CheckIOTimeout, pCard); } else if (eventStatus == tiDiscFailed) { AGTIAPI_PRINTK("eventStatus - tiDiscFailed\n"); agtiapi_GetDevHandle(pCard, &pPortalData->portalInfo, tiIntrEventTypeDiscovery, tiDiscFailed); PORTAL_STATUS(pPortalData) &= ~AGTIAPI_DISC_DONE; } AGTIAPI_PRINTK("tiIntrEventTypeDiscovery - portal %p, status 0x%x\n", pPortalData, PORTAL_STATUS(pPortalData)); break; case tiIntrEventTypeDeviceChange: AGTIAPI_PRINTK("tiIntrEventTypeDeviceChange - portal %p es %d\n", ptiPortalContext->osData, eventStatus); pPortalData = PORTAL_CONTEXT_TO_PORTALDATA(ptiPortalContext); pPortalInfo = &pPortalData->portalInfo; #ifndef HOTPLUG_SUPPORT if (!(pCard->flags & AGTIAPI_INIT_TIME)) #else if (TRUE) #endif { agtiapi_GetDevHandle(pCard, pPortalInfo, tiIntrEventTypeDeviceChange, eventStatus); // agtiapi_StartIO(pCard); } break; case tiIntrEventTypeTransportRecovery: AGTIAPI_PRINTK("tiIntrEventTypeTransportRecovery!\n"); break; case tiIntrEventTypeTaskManagement: AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement!\n"); pccb = (pccb_t)((tiIORequest_t *)parm)->osData; if (pccb->flags & TASK_TIMEOUT) { AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: TM timeout!\n"); agtiapi_FreeTMCCB(pCard, pccb); } else { pccb->flags |= AGTIAPI_CB_DONE; if (eventStatus == tiTMOK) { pccb->flags |= TASK_SUCCESS; AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: pTMccb %p flag %x \n", pccb, pccb->flags); /* Incase of TM_DEV_RESET, issue LocalAbort to abort pending IO */ if (pccb->flags & DEV_RESET) { AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: Target Reset\n"); ccbIO = pccb->pccbIO; AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: IO to be aborted locally %p flag %x \n", ccbIO, ccbIO->flags); if (ccbIO->startTime == 0) /* IO has been completed. No local abort */ { } else if (tiINIIOAbort(&pCard->tiRoot, &ccbIO->tiIORequest) != tiSuccess) { AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: Local Abort failed\n"); /* TODO: call Soft reset here */ } } else if (eventStatus == tiTMFailed) { ccbIO = pccb->pccbIO; if (ccbIO->startTime == 0) /* IO has been completed. */ { AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: TM failed because IO has been completed! pTMccb %p flag %x \n", pccb, pccb->flags); } else { AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: TM failed! pTMccb %p flag %x \n", pccb, pccb->flags); /* TODO:*/ /* if TM_ABORT_TASK, call TM_TARGET_RESET */ /* if TM_TARGET_RESET, call Soft_Reset */ } } /* Free TM_DEV_RESET ccb */ agtiapi_FreeTMCCB(pCard, pccb); } } break; case tiIntrEventTypeLocalAbort: AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort!\n"); pccb = (pccb_t)((tiIORequest_t *)parm)->osData; pccb->flags |= AGTIAPI_CB_DONE; if (eventStatus == tiAbortOK) { AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort: taskTag pccb %p flag %x \n", pccb, pccb->flags); /* If this was LocalAbort for TM ABORT_TASK, issue TM_DEV_RESET */ if (pccb->flags & TASK_MANAGEMENT) { if ((pTMccb = agtiapi_GetCCB(pCard)) == NULL) { AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort: TM resource unavailable!\n"); /* TODO: SoftReset here? */ } pTMccb->pmcsc = pCard; pTMccb->targetId = pccb->targetId; pTMccb->devHandle = pccb->devHandle; /* save pending io to issue local abort at Task mgmt CB */ pTMccb->pccbIO = pccb->pccbIO; pTMccb->flags &= ~(TASK_SUCCESS | ACTIVE); pTMccb->flags |= DEV_RESET; if (tiINITaskManagement(&pCard->tiRoot, pccb->devHandle, AG_TARGET_WARM_RESET, &pccb->tiSuperScsiRequest.scsiCmnd.lun, &pccb->tiIORequest, &pTMccb->tiIORequest) == tiSuccess) { AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort: TM_TARGET_RESET request success ccb %p, pTMccb %p\n", pccb, pTMccb); pTMccb->startTime = ticks; } else { AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort: TM_TARGET_RESET request failed ccb %p, pTMccb %p\n", pccb, pTMccb); agtiapi_FreeTMCCB(pCard, pTMccb); /* TODO: SoftReset here? */ } /* Free ABORT_TASK TM ccb */ agtiapi_FreeTMCCB(pCard, pccb); } } else if (eventStatus == tiAbortFailed) { /* TODO: */ /* If TM_ABORT_TASK fails, issue TM_DEV_RESET */ /* if TM_DEV_RESET fails, issue Soft_Reset */ AGTIAPI_PRINTK("tiIntrEventTypeLocalAbort: Abort Failed pccb %p\n", pccb); } break; default: AGTIAPI_PRINTK("tiIntrEventType default!\n"); break; } }
/****************************************************************************** ostiInitiatorIOCompleted() Purpose: IO request completion call back Parameters: tiRoot_t *ptiRoot (IN) Pointer to the HBA tiRoot tiIORequest_t *ptiIORequest (IN) Pointer to the tiIORequest structure tiIOStatus_t IOStatus (IN) I/O complated status U32 statusDetail (IN) Additional information on status tiSenseData_t *pSensedata (IN) Sense data buffer pointer U32 context (IN) Interrupt dealing context Returns: Note: ******************************************************************************/ void ostiInitiatorIOCompleted(tiRoot_t *ptiRoot, tiIORequest_t *ptiIORequest, tiIOStatus_t IOStatus, U32 statusDetail, tiSenseData_t *pSenseData, U32 context ) { struct agtiapi_softc *pCard; ccb_t *pccb; pCard = TIROOT_TO_CARD(ptiRoot); pccb = (ccb_t *)ptiIORequest->osData; AGTIAPI_IO( "ostiInitiatorIOCompleted: start\n" ); if (IOStatus == tiIODifError) { return; } OSTI_OUT_ENTER(ptiRoot); pccb->ccbStatus = (U16)IOStatus; pccb->scsiStatus = statusDetail; if ((IOStatus == tiIOSuccess) && (statusDetail == SCSI_CHECK_CONDITION)) { if (pSenseData == (tiSenseData_t *)agNULL) { AGTIAPI_PRINTK( "ostiInitiatorIOCompleted: " "check condition without sense data!\n" ); } else { union ccb *ccb = pccb->ccb; struct ccb_scsiio *csio = &ccb->csio; int sense_len = 0; if (pccb->senseLen > pSenseData->senseLen) { csio->sense_resid = pccb->senseLen - pSenseData->senseLen; } else { csio->sense_resid = 0; } sense_len = MIN( pSenseData->senseLen, pccb->senseLen - csio->sense_resid ); bzero(&csio->sense_data, sizeof(csio->sense_data)); AGTIAPI_PRINTK("ostiInitiatorIOCompleted: check condition copying\n"); memcpy( (void *)pccb->pSenseData, pSenseData->senseData, sense_len ); agtiapi_hexdump( "ostiInitiatorIOCompleted check condition", (bit8 *)&csio->sense_data, sense_len ); } } if ((IOStatus == tiIOFailed) && (statusDetail == tiDetailAborted)) { AGTIAPI_PRINTK("ostiInitiatorIOCompleted - aborted ccb %p, flag %x\n", pccb, pccb->flags); /* indicate aborted IO completion */ pccb->startTime = 0; agtiapi_Done(pCard, pccb); } else { #ifdef AGTIAPI_SA /* * SAS no data command does not trigger interrupt. * Command is completed in tdlayer and IO completion is called directly. * The completed IO therefore is not post processed. * Flag is raised and TDTimer will check and process IO for SAS. * This is a temporary solution. - Eddie, 07-17-2006 */ pCard->flags |= AGTIAPI_FLAG_UP; #endif pccb->flags |= REQ_DONE; agtiapi_QueueCCB(pCard, &pCard->ccbDoneHead, &pCard->ccbDoneTail AG_CARD_LOCAL_LOCK(&pCard->doneLock), pccb); } OSTI_OUT_LEAVE(ptiRoot); return; }
/****************************************************************************** agtiapi_ScopeDMARes() Purpose: Determine the amount of DMA (non-cache) memory resources which will be required for a card ( and necessarily allocated in agtiapi_InitResource() ) Parameters: ag_card_info_t *thisCardInst (IN) Return: size of DMA memory which call to agtiapi_InitResource() will consume Note: this funcion mirrors the flow of agtiapi_InitResource() results are stored in agtiapi_softc fields ******************************************************************************/ STATIC int agtiapi_ScopeDMARes( ag_card_info_t *thisCardInst ) { struct agtiapi_softc *pmsc = thisCardInst->pCard; U32 lAllMem = 0; // total memory count; typhn U32 lTmpAlign, lTmpType, lTmpLen; // tiLoLevelResource U32 numVal; ag_resource_info_t *pRscInfo; pRscInfo = &thisCardInst->tiRscInfo; if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) { for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count; numVal++ ) { if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength == 0 ) { printf( "agtiapi_ScopeDMARes: skip ZERO %d\n", numVal ); continue; } // check for 64 bit alignment lTmpAlign = pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment; if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) { AGTIAPI_PRINTK("agtiapi_ScopeDMARes: set ALIGN %d\n", numVal); //pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment = lTmpAlign = AGTIAPI_64BIT_ALIGN; } if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_DMA_MEM) || ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) { //thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type = lTmpType = #ifdef CACHED_DMA pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1)); #else TI_DMA_MEM; #endif if( lTmpType == TI_DMA_MEM ) { lTmpLen = pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength; lAllMem += lTmpLen + lTmpAlign; } //printf( "agtiapi_ScopeDMARes: call 1 0x%x\n", lAllMem ); } else if ( ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1)) ) == TI_CACHED_MEM ) { // these are not the droids we're looking for if( thisCardInst->cacheIndex >= sizeof(thisCardInst->tiCachedMem) / sizeof(thisCardInst->tiCachedMem[0]) ) { AGTIAPI_PRINTK( "agtiapi_ScopeDMARes: Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex ); return lAllMem; } } else { printf( "agtiapi_ScopeDMARes: Unknown required memory type %d " "ERROR!\n", pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type ); return lAllMem; } } } // end: TI data structure resources ... // nothing for tiInitiatorResource // begin: tiTdSharedMem if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) { // check for 64 bit alignment lTmpAlign = pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment; if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) { //pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment=AGTIAPI_64BIT_ALIGN; lTmpAlign = AGTIAPI_64BIT_ALIGN; } if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1))) == TI_DMA_MEM ) { lTmpLen = pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength; lAllMem += lTmpLen + lTmpAlign; // printf( "agtiapi_ScopeDMARes: call 4D 0x%x\n", lAllMem ); } else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1))) != TI_CACHED_MEM ) { printf( "agtiapi_ScopeDMARes: Unknown required memory type ERROR!\n" ); } } // end: tiTdSharedMem pmsc->typhn = lAllMem; return lAllMem; } // agtiapi_ScopeDMARes() ends here
/****************************************************************************** agtiapi_InitResource() Purpose: Mapping PCI memory space Allocate and initialize per card based resource Parameters: ag_card_info_t *pCardInfo (IN) Return: AGTIAPI_SUCCESS - success AGTIAPI_FAIL - fail Note: ******************************************************************************/ STATIC agBOOLEAN agtiapi_InitResource( ag_card_info_t *thisCardInst ) { struct agtiapi_softc *pmsc = thisCardInst->pCard; device_t devx = thisCardInst->pPCIDev; //AGTIAPI_PRINTK( "agtiapi_InitResource: begin; pointer values %p / %p \n", // devx, thisCardInst ); // no IO mapped card implementation, we'll implement memory mapping if( agtiapi_typhAlloc( thisCardInst ) == AGTIAPI_FAIL ) { printf( "agtiapi_InitResource: failed call to agtiapi_typhAlloc \n" ); return AGTIAPI_FAIL; } AGTIAPI_PRINTK( "agtiapi_InitResource: dma alloc MemSpan %p -- %p\n", (void*) pmsc->typh_busaddr, (void*) ( (U32_64)pmsc->typh_busaddr + pmsc->typhn ) ); // logical BARs for SPC: // bar 0 and 1 - logical BAR0 // bar 2 and 3 - logical BAR1 // bar4 - logical BAR2 // bar5 - logical BAR3 // Skiping the assignments for bar 1 and bar 3 (making bar 0, 2 64-bit): U32 bar; U32 lBar = 0; // logicalBar for (bar = 0; bar < PCI_NUMBER_BARS; bar++) { if ((bar==1) || (bar==3)) continue; thisCardInst->pciMemBaseRIDSpc[lBar] = PCIR_BAR(bar); thisCardInst->pciMemBaseRscSpc[lBar] = bus_alloc_resource_any( devx, SYS_RES_MEMORY, &(thisCardInst->pciMemBaseRIDSpc[lBar]), RF_ACTIVE ); AGTIAPI_PRINTK( "agtiapi_InitResource: bus_alloc_resource_any rtn %p \n", thisCardInst->pciMemBaseRscSpc[lBar] ); if ( thisCardInst->pciMemBaseRscSpc[lBar] != NULL ) { thisCardInst->pciMemVirtAddrSpc[lBar] = (caddr_t)rman_get_virtual( thisCardInst->pciMemBaseRscSpc[lBar] ); thisCardInst->pciMemBaseSpc[lBar] = bus_get_resource_start( devx, SYS_RES_MEMORY, thisCardInst->pciMemBaseRIDSpc[lBar]); thisCardInst->pciMemSizeSpc[lBar] = bus_get_resource_count( devx, SYS_RES_MEMORY, thisCardInst->pciMemBaseRIDSpc[lBar] ); AGTIAPI_PRINTK( "agtiapi_InitResource: PCI: bar %d, lBar %d " "VirtAddr=%lx, len=%d\n", bar, lBar, (long unsigned int)thisCardInst->pciMemVirtAddrSpc[lBar], thisCardInst->pciMemSizeSpc[lBar] ); } else { thisCardInst->pciMemVirtAddrSpc[lBar] = 0; thisCardInst->pciMemBaseSpc[lBar] = 0; thisCardInst->pciMemSizeSpc[lBar] = 0; } lBar++; } thisCardInst->pciMemVirtAddr = thisCardInst->pciMemVirtAddrSpc[0]; thisCardInst->pciMemSize = thisCardInst->pciMemSizeSpc[0]; thisCardInst->pciMemBase = thisCardInst->pciMemBaseSpc[0]; // Allocate all TI data structure required resources. // tiLoLevelResource U32 numVal; ag_resource_info_t *pRscInfo; pRscInfo = &thisCardInst->tiRscInfo; pRscInfo->tiLoLevelResource.loLevelOption.pciFunctionNumber = pci_get_function( devx ); struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; int ticksPerSec; ticksPerSec = tvtohz( &tv ); int uSecPerTick = 1000000/USEC_PER_TICK; if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) { //AGTIAPI_INIT("agtiapi_InitResource: loLevelMem count = %d\n", // pRscInfo->tiLoLevelResource.loLevelMem.count); // adjust tick value to meet Linux requirement pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick = uSecPerTick; AGTIAPI_PRINTK( "agtiapi_InitResource: " "pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick" " 0x%x\n", pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick ); for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count; numVal++ ) { if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength == 0 ) { AGTIAPI_PRINTK("agtiapi_InitResource: skip ZERO %d\n", numVal); continue; } // check for 64 bit alignment if ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment < AGTIAPI_64BIT_ALIGN ) { AGTIAPI_PRINTK("agtiapi_InitResource: set ALIGN %d\n", numVal); pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment = AGTIAPI_64BIT_ALIGN; } if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_DMA_MEM) || ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) { if ( thisCardInst->dmaIndex >= sizeof(thisCardInst->tiDmaMem) / sizeof(thisCardInst->tiDmaMem[0]) ) { AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n", thisCardInst->dmaIndex ); return AGTIAPI_FAIL; } thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type = #ifdef CACHED_DMA pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1)); #else TI_DMA_MEM; #endif if( agtiapi_MemAlloc( thisCardInst, &thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr, &thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaPhysAddr, &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr, &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal]. physAddrUpper, &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal]. physAddrLower, pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength, thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type, pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment) != AGTIAPI_SUCCESS ) { return AGTIAPI_FAIL; } thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize = pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength; //AGTIAPI_INIT("agtiapi_InitResource: LoMem %d dmaIndex=%d DMA virt" // " %p, phys 0x%x, length %d align %d\n", // numVal, pCardInfo->dmaIndex, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].physAddrLower, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment); thisCardInst->dmaIndex++; } else if ( (pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_CACHED_MEM) { if (thisCardInst->cacheIndex >= sizeof(thisCardInst->tiCachedMem) / sizeof(thisCardInst->tiCachedMem[0])) { AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex ); return AGTIAPI_FAIL; } if ( agtiapi_MemAlloc( thisCardInst, &thisCardInst->tiCachedMem[thisCardInst->cacheIndex], (vm_paddr_t *)agNULL, &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr, (U32 *)agNULL, (U32 *)agNULL, pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength, TI_CACHED_MEM, pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment) != AGTIAPI_SUCCESS ) { return AGTIAPI_FAIL; } //AGTIAPI_INIT("agtiapi_InitResource: LoMem %d cacheIndex=%d CACHED " // "vaddr %p / %p, length %d align %d\n", // numVal, pCardInfo->cacheIndex, // pCardInfo->tiCachedMem[pCardInfo->cacheIndex], // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength, // pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment); thisCardInst->cacheIndex++; } else if ( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type & (BIT(0) | BIT(1))) == TI_DMA_MEM_CHIP)) { // not expecting this case, print warning that should get attention printf( "RED ALARM: we need a BAR for TI_DMA_MEM_CHIP, ignoring!" ); } else { printf( "agtiapi_InitResource: Unknown required memory type %d " "ERROR!\n", pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type); return AGTIAPI_FAIL; } } } // end: TI data structure resources ... // begin: tiInitiatorResource if ( pmsc->flags & AGTIAPI_INITIATOR ) { if ( pRscInfo->tiInitiatorResource.initiatorMem.count != 0 ) { //AGTIAPI_INIT("agtiapi_InitResource: initiatorMem count = %d\n", // pRscInfo->tiInitiatorResource.initiatorMem.count); numVal = (U32)( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick / uSecPerTick ); if( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick % uSecPerTick > 0 ) pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick = (numVal + 1) * uSecPerTick; else pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick = numVal * uSecPerTick; for ( numVal = 0; numVal < pRscInfo->tiInitiatorResource.initiatorMem.count; numVal++ ) { // check for 64 bit alignment if( pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. alignment < AGTIAPI_64BIT_ALIGN ) { pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. alignment = AGTIAPI_64BIT_ALIGN; } if( thisCardInst->cacheIndex >= sizeof( thisCardInst->tiCachedMem) / sizeof( thisCardInst->tiCachedMem[0])) { AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex ); return AGTIAPI_FAIL; } // initiator memory is cached, no check is needed if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst->tiCachedMem[thisCardInst->cacheIndex], (vm_paddr_t *)agNULL, &pRscInfo->tiInitiatorResource.initiatorMem. tdCachedMem[numVal].virtPtr, (U32 *)agNULL, (U32 *)agNULL, pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. totalLength, TI_CACHED_MEM, pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. alignment) != AGTIAPI_SUCCESS) { return AGTIAPI_FAIL; } // AGTIAPI_INIT("agtiapi_InitResource: IniMem %d cacheIndex=%d CACHED " // "vaddr %p / %p, length %d align 0x%x\n", // numVal, // pCardInfo->cacheIndex, // pCardInfo->tiCachedMem[pCardInfo->cacheIndex], // pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. // virtPtr, //pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. // totalLength, // pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal]. // alignment); thisCardInst->cacheIndex++; } } } // end: tiInitiatorResource // begin: tiTdSharedMem if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) { // check for 64 bit alignment if( pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment < AGTIAPI_64BIT_ALIGN ) { pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment = AGTIAPI_64BIT_ALIGN; } if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1))) == TI_DMA_MEM ) { if( thisCardInst->dmaIndex >= sizeof(thisCardInst->tiDmaMem) / sizeof(thisCardInst->tiDmaMem[0]) ) { AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n", thisCardInst->dmaIndex); return AGTIAPI_FAIL; } if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst-> tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr, &thisCardInst->tiDmaMem[thisCardInst->dmaIndex]. dmaPhysAddr, &pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr, &pRscInfo->tiSharedMem.tdSharedCachedMem1. physAddrUpper, &pRscInfo->tiSharedMem.tdSharedCachedMem1. physAddrLower, pRscInfo->tiSharedMem.tdSharedCachedMem1. totalLength, TI_DMA_MEM, pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment) != AGTIAPI_SUCCESS ) return AGTIAPI_FAIL; thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize = pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength + pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment; // printf( "agtiapi_InitResource: SharedMem DmaIndex=%d DMA " // "virt %p / %p, phys 0x%x, align %d\n", // thisCardInst->dmaIndex, // thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr, // pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr, // pRscInfo->tiSharedMem.tdSharedCachedMem1.physAddrLower, // pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment); thisCardInst->dmaIndex++; } else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1))) == TI_CACHED_MEM ) { if( thisCardInst->cacheIndex >= sizeof(thisCardInst->tiCachedMem) / sizeof(thisCardInst->tiCachedMem[0]) ) { AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex); return AGTIAPI_FAIL; } if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst-> tiCachedMem[thisCardInst->cacheIndex], (vm_paddr_t *)agNULL, &pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr, (U32 *)agNULL, (U32 *)agNULL, pRscInfo-> tiSharedMem.tdSharedCachedMem1.totalLength, TI_CACHED_MEM, pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment) != AGTIAPI_SUCCESS ) return AGTIAPI_FAIL; // printf( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED " // "vaddr %p / %p, length %d align 0x%x\n", // thisCardInst->cacheIndex, // thisCardInst->tiCachedMem[thisCardInst->cacheIndex], // pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr, // pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength, // pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment); AGTIAPI_PRINTK( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED " "vaddr %p / %p, length %d align 0x%x\n", thisCardInst->cacheIndex, thisCardInst->tiCachedMem[thisCardInst->cacheIndex], pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr, pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength, pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment ); thisCardInst->cacheIndex++; } else { AGTIAPI_PRINTK( "agtiapi_InitResource: " "Unknown required memory type ERROR!\n" ); return AGTIAPI_FAIL; } } // end: tiTdSharedMem DELAY( 200000 ); // or use AGTIAPI_INIT_MDELAY(200); return AGTIAPI_SUCCESS; } // agtiapi_InitResource() ends here