/** This function flushes the range of addresses from Start to Start+Length from the processor's data cache. If Start is not aligned to a cache line boundary, then the bytes before Start to the preceding cache line boundary are also flushed. If Start+Length is not aligned to a cache line boundary, then the bytes past Start+Length to the end of the next cache line boundary are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be supported. If the data cache is fully coherent with all DMA operations, then this function can just return EFI_SUCCESS. If the processor does not support flushing a range of the data cache, then the entire data cache can be flushed. @param This The EFI_CPU_ARCH_PROTOCOL instance. @param Start The beginning physical address to flush from the processor's data cache. @param Length The number of bytes to flush from the processor's data cache. This function may flush more bytes than Length specifies depending upon the granularity of the flush operation that the processor supports. @param FlushType Specifies the type of flush operation to perform. @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from the processor's data cache. @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified by FlushType. @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed from the processor's data cache. **/ EFI_STATUS EFIAPI CpuFlushCpuDataCache ( IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 Length, IN EFI_CPU_FLUSH_TYPE FlushType ) { switch (FlushType) { case EfiCpuFlushTypeWriteBack: WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; case EfiCpuFlushTypeInvalidate: InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; case EfiCpuFlushTypeWriteBackInvalidate: WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI ArmMmuPeiLibConstructor ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { extern UINT32 ArmReplaceLiveTranslationEntrySize; EFI_FV_FILE_INFO FileInfo; EFI_STATUS Status; ASSERT (FileHandle != NULL); Status = (*PeiServices)->FfsGetFileInfo (FileHandle, &FileInfo); ASSERT_EFI_ERROR (Status); // // Some platforms do not cope very well with cache maintenance being // performed on regions backed by NOR flash. Since the firmware image // can be assumed to be clean to the PoC when running XIP, even when PEI // is executing from DRAM, we only need to perform the cache maintenance // when not executing in place. // if ((UINTN)FileInfo.Buffer <= (UINTN)ArmReplaceLiveTranslationEntry && ((UINTN)FileInfo.Buffer + FileInfo.BufferSize >= (UINTN)ArmReplaceLiveTranslationEntry + ArmReplaceLiveTranslationEntrySize)) { DEBUG ((EFI_D_INFO, "ArmMmuLib: skipping cache maintenance on XIP PEIM\n")); } else { DEBUG ((EFI_D_INFO, "ArmMmuLib: performing cache maintenance on shadowed PEIM\n")); // // The ArmReplaceLiveTranslationEntry () helper function may be invoked // with the MMU off so we have to ensure that it gets cleaned to the PoC // WriteBackDataCacheRange (ArmReplaceLiveTranslationEntry, ArmReplaceLiveTranslationEntrySize); } return RETURN_SUCCESS; }
STATIC EFI_STATUS prepare_cmd ( struct hisi_hba *hba, EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet ) { struct hisi_sas_slot *slot; struct hisi_sas_cmd_hdr *hdr; struct hisi_sas_sge_page *sge; struct hisi_sas_sts *sts; struct hisi_sas_cmd *cmd; EFI_SCSI_SENSE_DATA *SensePtr = Packet->SenseData; VOID *Buffer = NULL; UINT32 BufferSize = 0; int queue = hba->queue; UINT32 r, w = 0, slot_idx = 0; UINT8 *p; while (1) { w = READ_REG32(DLVRY_Q_0_WR_PTR + (queue * 0x14)); r = READ_REG32(DLVRY_Q_0_RD_PTR + (queue * 0x14)); slot_idx = queue * QUEUE_SLOTS + w; slot = &hba->slots[slot_idx]; if (slot->used || (r == (w+1) % QUEUE_SLOTS)) { queue = (queue + 1) % QUEUE_CNT; if (queue == hba->queue) { DEBUG ((EFI_D_ERROR, "could not find free slot\n")); return EFI_NOT_READY; } continue; } break; } hdr = &hba->cmd_hdr[queue][w]; cmd = &hba->command_table[queue][w]; sts = &hba->status_buf[queue][w]; sge = &hba->sge[queue][w]; ZeroMem (cmd, sizeof (struct hisi_sas_cmd)); ZeroMem (sts, sizeof (struct hisi_sas_sts)); if (SensePtr) ZeroMem (SensePtr, sizeof (EFI_SCSI_SENSE_DATA)); slot->used = TRUE; slot->sts = sts; hba->queue = (queue + 1) % QUEUE_CNT; //only consider ssp //prep_ssp_v1_hw /* create header */ hdr->dw0 = (1 << CMD_HDR_RESP_REPORT_OFF) | (0x2 << CMD_HDR_TLR_CTRL_OFF) | (hba->port_id << CMD_HDR_PORT_OFF) | (1 << CMD_HDR_MODE_OFF) | /* ini mode */ (1 << CMD_HDR_CMD_OFF); /* ssp */ hdr->dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF; /* device_id = 0 */ hdr->dw1 |= 0 << CMD_HDR_DEVICE_ID_OFF; hdr->dw2 = 0x83000d; hdr->transfer_tags = slot_idx << CMD_HDR_IPTT_OFF; if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) { Buffer = Packet->InDataBuffer; BufferSize = Packet->InTransferLength; if (Buffer) { hdr->dw1 |= 1 << CMD_HDR_SSP_FRAME_TYPE_OFF; InvalidateDataCacheRange (Buffer, BufferSize); } } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) { Buffer = Packet->OutDataBuffer; BufferSize = Packet->OutTransferLength; if (Buffer) hdr->dw1 |= 2 << CMD_HDR_SSP_FRAME_TYPE_OFF; } else { hdr->dw1 |= 0 << CMD_HDR_SSP_FRAME_TYPE_OFF; } if (Buffer != NULL) { struct hisi_sas_sge *sg; UINT32 remain, len, pos = 0; int i = 0; remain = len = BufferSize; while (remain) { if (len > SGE_LIMIT) len = SGE_LIMIT; sg = &sge->sg[i]; sg->addr = (UINT64)(Buffer + pos); sg->page_ctrl_0 = sg->page_ctrl_1 = 0; sg->data_len = len; sg->data_off = 0; remain -= len; pos += len; len = remain; i++; } hdr->prd_table_addr = (UINT64)sge; hdr->sg_len = i << CMD_HDR_DATA_SGL_LEN_OFF; } hdr->data_transfer_len = BufferSize; hdr->cmd_table_addr = (UINT64)cmd; hdr->sts_buffer_addr = (UINT64)sts; CopyMem (&cmd->cmd[36], Packet->Cdb, Packet->CdbLength); if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) WriteBackDataCacheRange (Buffer, BufferSize); asm("dsb sy"); asm("isb sy"); //start_delivery_v1_hw WRITE_REG32(DLVRY_Q_0_WR_PTR + queue * 0x14, ++w % QUEUE_SLOTS); //waiting for slot free, dma completed while (slot->used) { if (READ_REG32(OQ_INT_SRC) & BIT(queue)) { MicroSecondDelay(500); break; } NanoSecondDelay (100); } p = (UINT8 *)&slot->sts->status[0]; if (p[SENSE_DATA_PRES]) { /* hack for spin up */ SensePtr->Sense_Key = EFI_SCSI_SK_NOT_READY; SensePtr->Addnl_Sense_Code = EFI_SCSI_ASC_NOT_READY; SensePtr->Addnl_Sense_Code_Qualifier = EFI_SCSI_ASCQ_IN_PROGRESS; MicroSecondDelay(1000000); } return EFI_SUCCESS; }