110802Srene.dejong@arm.com/* 210802Srene.dejong@arm.com * Copyright (c) 2013-2015 ARM Limited 310802Srene.dejong@arm.com * All rights reserved 410802Srene.dejong@arm.com * 510802Srene.dejong@arm.com * The license below extends only to copyright in the software and shall 610802Srene.dejong@arm.com * not be construed as granting a license to any other intellectual 710802Srene.dejong@arm.com * property including but not limited to intellectual property relating 810802Srene.dejong@arm.com * to a hardware implementation of the functionality of the software 910802Srene.dejong@arm.com * licensed hereunder. You may use the software subject to the license 1010802Srene.dejong@arm.com * terms below provided that you ensure that this notice is replicated 1110802Srene.dejong@arm.com * unmodified and in its entirety in all distributions of the software, 1210802Srene.dejong@arm.com * modified or unmodified, in source code or in binary form. 1310802Srene.dejong@arm.com * 1410802Srene.dejong@arm.com * Redistribution and use in source and binary forms, with or without 1510802Srene.dejong@arm.com * modification, are permitted provided that the following conditions are 1610802Srene.dejong@arm.com * met: redistributions of source code must retain the above copyright 1710802Srene.dejong@arm.com * notice, this list of conditions and the following disclaimer; 1810802Srene.dejong@arm.com * redistributions in binary form must reproduce the above copyright 1910802Srene.dejong@arm.com * notice, this list of conditions and the following disclaimer in the 2010802Srene.dejong@arm.com * documentation and/or other materials provided with the distribution; 2110802Srene.dejong@arm.com * neither the name of the copyright holders nor the names of its 2210802Srene.dejong@arm.com * contributors may be used to endorse or promote products derived from 2310802Srene.dejong@arm.com * this software without specific prior written permission. 2410802Srene.dejong@arm.com * 2510802Srene.dejong@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610802Srene.dejong@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710802Srene.dejong@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810802Srene.dejong@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910802Srene.dejong@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010802Srene.dejong@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110802Srene.dejong@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210802Srene.dejong@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310802Srene.dejong@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410802Srene.dejong@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510802Srene.dejong@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610802Srene.dejong@arm.com * 3710802Srene.dejong@arm.com * Authors: Rene de Jong 3810802Srene.dejong@arm.com */ 3910802Srene.dejong@arm.com 4010802Srene.dejong@arm.com 4110802Srene.dejong@arm.com/** @file 4210802Srene.dejong@arm.com * This is a base class for UFS devices 4310802Srene.dejong@arm.com * The UFS interface consists out of one host controller which connects a 4410802Srene.dejong@arm.com * number of devices which together contain up to 8 logic units. A Logical 4510802Srene.dejong@arm.com * Unit is an externally addressable, independent, processing entity that 4610802Srene.dejong@arm.com * processes SCSI tasks (commands) and performs task management functions. 4710802Srene.dejong@arm.com * The decision has been made to abstract the device away, and model the 4810802Srene.dejong@arm.com * different logic units. Effectively this means that there is one Host layer 4910802Srene.dejong@arm.com * which handles all the UFS commands (everything UTP, UPIU and UNIpro 5010802Srene.dejong@arm.com * related) and a SCSI layer, which handles the SCSI interpretation and the 5110802Srene.dejong@arm.com * interaction with the "disk" (effectively the LBA that that particular 5210802Srene.dejong@arm.com * Logic Unit controls). Each Logic unit should therefor control a disk image 5310802Srene.dejong@arm.com * and a timing model. The UFS protocol has three types of commands 5410802Srene.dejong@arm.com * (explained later). Each has different phases and each phase need to wait 5510802Srene.dejong@arm.com * for its particular data. This is the reason that this model contains a lot 5610802Srene.dejong@arm.com * of events. For clarity, a state diagram in doxygen has been provided. To 5710802Srene.dejong@arm.com * fully apreciate the stages that the model flows through, the states have 5810802Srene.dejong@arm.com * been broken into three state diagrams. It is best if one imagines the 5910802Srene.dejong@arm.com * command flow state machine to be happening in the UFSHost layer, and the 6010802Srene.dejong@arm.com * other two to flow through all the layers of the model (UFS host, SCSI and 6110802Srene.dejong@arm.com * NVM model). See it as a quarry, one state diagram is moving the crane into 6210802Srene.dejong@arm.com * place, and the other ones are transporting the dirt down, or the valuables 6310802Srene.dejong@arm.com * up. For complete information about the working of UFS please refer to 6410802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 or 6510802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd223 6610802Srene.dejong@arm.com * The documents are available free of charge, although you will need to have 6710802Srene.dejong@arm.com * an acount. 6810802Srene.dejong@arm.com */ 6910802Srene.dejong@arm.com 7010802Srene.dejong@arm.com/** UFS command flow state machine 7110802Srene.dejong@arm.com *digraph CommandFlow{ 7210802Srene.dejong@arm.com node [fontsize=10]; 7310802Srene.dejong@arm.com IDLE -> transferHandler 7410802Srene.dejong@arm.com [ label=" transfer/task/command request " fontsize=6]; 7510802Srene.dejong@arm.com transferHandler -> command 7610802Srene.dejong@arm.com [ label=" It is a command " fontsize=6]; 7710802Srene.dejong@arm.com command -> IDLE 7810802Srene.dejong@arm.com [ label=" Command done, no further action " fontsize=6]; 7910802Srene.dejong@arm.com transferHandler -> taskStart 8010802Srene.dejong@arm.com [ label=" It is a task " fontsize=6]; 8110802Srene.dejong@arm.com taskStart -> finalUTP 8210802Srene.dejong@arm.com [ label=" Task handled, now acknowledge (UFS) " fontsize=6]; 8310802Srene.dejong@arm.com transferHandler -> transferStart 8410802Srene.dejong@arm.com [ label=" It is a transfer " fontsize=6]; 8510802Srene.dejong@arm.com transferStart -> SCSIResume 8610802Srene.dejong@arm.com [ label=" Transfer, obtain the specific command " fontsize=6]; 8710802Srene.dejong@arm.com SCSIResume -> DiskDataFlowPhase 8810802Srene.dejong@arm.com [ label=" Disk data transfer (see other graphs) " fontsize=6]; 8910802Srene.dejong@arm.com SCSIResume -> DeviceDataPhase 9010802Srene.dejong@arm.com [ label=" Device info transfer (handled in SCSIResume) " 9110802Srene.dejong@arm.com fontsize=6]; 9210802Srene.dejong@arm.com DiskDataFlowPhase -> transferDone 9310802Srene.dejong@arm.com [ label=" Transfer done, acknowledge SCSI command " fontsize=6]; 9410802Srene.dejong@arm.com DeviceDataPhase -> transferDone 9510802Srene.dejong@arm.com [ label=" Transfer done, acknowledge SCSI command " fontsize=6]; 9610802Srene.dejong@arm.com transferDone -> finalUTP 9710802Srene.dejong@arm.com [ label=" Transfer handled, now acknowledge (UFS) " fontsize=6]; 9810802Srene.dejong@arm.com finalUTP -> readDone 9910802Srene.dejong@arm.com [ label=" All handled, clear data structures " fontsize=6]; 10010802Srene.dejong@arm.com readDone -> IDLE 10110802Srene.dejong@arm.com [ label=" All handled, nothing outstanding " fontsize=6]; 10210802Srene.dejong@arm.com readDone -> transferHandler 10310802Srene.dejong@arm.com [ label=" All handled, handle next outstanding " fontsize=6]; 10410802Srene.dejong@arm.com } 10510802Srene.dejong@arm.com */ 10610802Srene.dejong@arm.com/** UFS read transaction flow state machine 10710802Srene.dejong@arm.com digraph readFlow{ 10810802Srene.dejong@arm.com node [fontsize=10]; 10910802Srene.dejong@arm.com getScatterGather -> commitReadFromDisk 11010802Srene.dejong@arm.com [ label=" Put the information about the data transfer to the disk " 11110802Srene.dejong@arm.com fontsize=6]; 11210802Srene.dejong@arm.com commitReadFromDisk -> waitForReads 11310802Srene.dejong@arm.com [ label=" Push the reads to the flashmodel and wait for callbacks " 11410802Srene.dejong@arm.com fontsize=6]; 11510802Srene.dejong@arm.com waitForReads -> pushToDMA 11610802Srene.dejong@arm.com [ label=" Push to the DMA and wait for them to finish " fontsize=6]; 11710802Srene.dejong@arm.com pushToDMA -> waitForReads 11810802Srene.dejong@arm.com [ label=" Wait for the next disk event " fontsize=6]; 11910802Srene.dejong@arm.com pushToDMA -> waitForDMA 12010802Srene.dejong@arm.com [ label=" Wait for the last DMA transfer to finish " fontsize=6]; 12110802Srene.dejong@arm.com waitForDMA -> finishTransfer 12210802Srene.dejong@arm.com [ label=" Continue with the command flow " fontsize=6]; 12310802Srene.dejong@arm.com } 12410802Srene.dejong@arm.com */ 12510802Srene.dejong@arm.com/** UFS write transaction flow state machine 12610802Srene.dejong@arm.com digraph WriteFlow{ 12710802Srene.dejong@arm.com node [fontsize=10]; 12810802Srene.dejong@arm.com getScatterGather -> getFromDMA 12910802Srene.dejong@arm.com [ label=" Put the transfer information to the DMA " fontsize=6]; 13010802Srene.dejong@arm.com getFromDMA -> waitForDMA 13110802Srene.dejong@arm.com [ label=" Wait for dma actions to arrive " fontsize=6]; 13210802Srene.dejong@arm.com waitForDMA -> pushToDisk 13310802Srene.dejong@arm.com [ label=" Push arrived DMA to disk " fontsize=6]; 13410802Srene.dejong@arm.com pushToDisk -> waitForDMA 13510802Srene.dejong@arm.com [ label=" Wait for next DMA action " fontsize=6]; 13610802Srene.dejong@arm.com pushToDisk -> waitForDisk 13710802Srene.dejong@arm.com [ label=" All DMA actions are done, wait for disk " fontsize=6]; 13810802Srene.dejong@arm.com waitForDisk -> finishTransfer 13910802Srene.dejong@arm.com [ label=" All transactions are done , continue the command flow " 14010802Srene.dejong@arm.com fontsize=6]; 14110802Srene.dejong@arm.com } 14210802Srene.dejong@arm.com */ 14310802Srene.dejong@arm.com 14410802Srene.dejong@arm.com#ifndef __DEV_ARM_UFS_DEVICE_HH__ 14510802Srene.dejong@arm.com#define __DEV_ARM_UFS_DEVICE_HH__ 14610802Srene.dejong@arm.com 14710802Srene.dejong@arm.com#include <deque> 14810802Srene.dejong@arm.com 14910802Srene.dejong@arm.com#include "base/addr_range.hh" 15010802Srene.dejong@arm.com#include "base/bitfield.hh" 15110802Srene.dejong@arm.com#include "base/statistics.hh" 15210802Srene.dejong@arm.com#include "debug/UFSHostDevice.hh" 15310802Srene.dejong@arm.com#include "dev/arm/abstract_nvm.hh" 15410802Srene.dejong@arm.com#include "dev/arm/base_gic.hh" 15511264Sandreas.sandberg@arm.com#include "dev/storage/disk_image.hh" 15610802Srene.dejong@arm.com#include "dev/dma_device.hh" 15710802Srene.dejong@arm.com#include "dev/io_device.hh" 15810802Srene.dejong@arm.com#include "mem/packet.hh" 15910802Srene.dejong@arm.com#include "mem/packet_access.hh" 16010802Srene.dejong@arm.com#include "params/UFSHostDevice.hh" 16110802Srene.dejong@arm.com#include "sim/serialize.hh" 16210802Srene.dejong@arm.com#include "sim/stats.hh" 16310802Srene.dejong@arm.com 16410802Srene.dejong@arm.com/** 16510802Srene.dejong@arm.com * Host controller layer: This is your Host controller 16610802Srene.dejong@arm.com * This layer handles the UFS functionality. 16710802Srene.dejong@arm.com * It tracks all the different transaction stages and uses 16810802Srene.dejong@arm.com * the device layer and the flash layer to determine the transaction flow. 16910802Srene.dejong@arm.com */ 17010802Srene.dejong@arm.comclass UFSHostDevice : public DmaDevice 17110802Srene.dejong@arm.com{ 17210802Srene.dejong@arm.com public: 17310802Srene.dejong@arm.com 17410802Srene.dejong@arm.com UFSHostDevice(const UFSHostDeviceParams* p); 17510802Srene.dejong@arm.com 17611168Sandreas.hansson@arm.com DrainState drain() override; 17710802Srene.dejong@arm.com void checkDrain(); 17811168Sandreas.hansson@arm.com void serialize(CheckpointOut &cp) const override; 17911168Sandreas.hansson@arm.com void unserialize(CheckpointIn &cp) override; 18010802Srene.dejong@arm.com 18110802Srene.dejong@arm.com private: 18210802Srene.dejong@arm.com /** 18310802Srene.dejong@arm.com * Host Controller Interface 18410802Srene.dejong@arm.com * This is a set of registers that allow the driver to control the 18510802Srene.dejong@arm.com * transactions to the flash devices. 18610802Srene.dejong@arm.com * As defined in: 18710802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd223 18810802Srene.dejong@arm.com */ 18910802Srene.dejong@arm.com struct HCIMem { 19010802Srene.dejong@arm.com /** 19110802Srene.dejong@arm.com * Specify the host capabilities 19210802Srene.dejong@arm.com */ 19310802Srene.dejong@arm.com uint32_t HCCAP; 19410802Srene.dejong@arm.com uint32_t HCversion; 19510802Srene.dejong@arm.com uint32_t HCHCDDID; 19610802Srene.dejong@arm.com uint32_t HCHCPMID; 19710802Srene.dejong@arm.com 19810802Srene.dejong@arm.com /** 19910802Srene.dejong@arm.com * Operation and runtime registers 20010802Srene.dejong@arm.com */ 20110802Srene.dejong@arm.com uint32_t ORInterruptStatus; 20210802Srene.dejong@arm.com uint32_t ORInterruptEnable; 20310802Srene.dejong@arm.com uint32_t ORHostControllerStatus; 20410802Srene.dejong@arm.com uint32_t ORHostControllerEnable; 20510802Srene.dejong@arm.com uint32_t ORUECPA; 20610802Srene.dejong@arm.com uint32_t ORUECDL; 20710802Srene.dejong@arm.com uint32_t ORUECN; 20810802Srene.dejong@arm.com uint32_t ORUECT; 20910802Srene.dejong@arm.com uint32_t ORUECDME; 21010802Srene.dejong@arm.com uint32_t ORUTRIACR; 21110802Srene.dejong@arm.com 21210802Srene.dejong@arm.com /** 21310802Srene.dejong@arm.com * vendor specific register 21410802Srene.dejong@arm.com */ 21510802Srene.dejong@arm.com uint32_t vendorSpecific; 21610802Srene.dejong@arm.com 21710802Srene.dejong@arm.com /** 21810802Srene.dejong@arm.com * Transfer control registers 21910802Srene.dejong@arm.com */ 22010802Srene.dejong@arm.com uint32_t TRUTRLBA; 22110802Srene.dejong@arm.com uint32_t TRUTRLBAU; 22210802Srene.dejong@arm.com uint32_t TRUTRLDBR; 22310802Srene.dejong@arm.com uint32_t TRUTRLCLR; 22410802Srene.dejong@arm.com uint32_t TRUTRLRSR; 22510802Srene.dejong@arm.com 22610802Srene.dejong@arm.com /** 22710802Srene.dejong@arm.com * Task control registers 22810802Srene.dejong@arm.com */ 22910802Srene.dejong@arm.com uint32_t TMUTMRLBA; 23010802Srene.dejong@arm.com uint32_t TMUTMRLBAU; 23110802Srene.dejong@arm.com uint32_t TMUTMRLDBR; 23210802Srene.dejong@arm.com uint32_t TMUTMRLCLR; 23310802Srene.dejong@arm.com uint32_t TMUTMRLRSR; 23410802Srene.dejong@arm.com 23510802Srene.dejong@arm.com /** 23610802Srene.dejong@arm.com * Command registers 23710802Srene.dejong@arm.com */ 23810802Srene.dejong@arm.com uint32_t CMDUICCMDR; 23910802Srene.dejong@arm.com uint32_t CMDUCMDARG1; 24010802Srene.dejong@arm.com uint32_t CMDUCMDARG2; 24110802Srene.dejong@arm.com uint32_t CMDUCMDARG3; 24210802Srene.dejong@arm.com }; 24310802Srene.dejong@arm.com 24410802Srene.dejong@arm.com /** 24510802Srene.dejong@arm.com * All the data structures are defined in the UFS standard 24610802Srene.dejong@arm.com * This standard be found at the JEDEC website free of charge 24710802Srene.dejong@arm.com * (login required): 24810802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 24910802Srene.dejong@arm.com */ 25010802Srene.dejong@arm.com 25110802Srene.dejong@arm.com /** 25210802Srene.dejong@arm.com * struct UTPUPIUHeader - UPIU header structure 25310802Srene.dejong@arm.com * dWord0: UPIU header DW-0 25410802Srene.dejong@arm.com * dWord1: UPIU header DW-1 25510802Srene.dejong@arm.com * dWord2: UPIU header DW-2 25610802Srene.dejong@arm.com */ 25710802Srene.dejong@arm.com struct UTPUPIUHeader { 25810802Srene.dejong@arm.com uint32_t dWord0; 25910802Srene.dejong@arm.com uint32_t dWord1; 26010802Srene.dejong@arm.com uint32_t dWord2; 26110802Srene.dejong@arm.com }; 26210802Srene.dejong@arm.com 26310802Srene.dejong@arm.com /** 26410802Srene.dejong@arm.com * struct UTPUPIURSP - Response UPIU structure 26510802Srene.dejong@arm.com * header: UPIU header DW-0 to DW-2 26610802Srene.dejong@arm.com * residualTransferCount: Residual transfer count DW-3 26710802Srene.dejong@arm.com * reserved: Reserved DW-4 to DW-7 26810802Srene.dejong@arm.com * senseDataLen: Sense data length DW-8 U16 26910802Srene.dejong@arm.com * senseData: Sense data field DW-8 to DW-12 27010802Srene.dejong@arm.com */ 27110802Srene.dejong@arm.com struct UTPUPIURSP { 27210802Srene.dejong@arm.com struct UTPUPIUHeader header; 27310802Srene.dejong@arm.com uint32_t residualTransferCount; 27410802Srene.dejong@arm.com uint32_t reserved[4]; 27510802Srene.dejong@arm.com uint16_t senseDataLen; 27610802Srene.dejong@arm.com uint8_t senseData[18]; 27710802Srene.dejong@arm.com }; 27810802Srene.dejong@arm.com 27910802Srene.dejong@arm.com /** 28010802Srene.dejong@arm.com * struct UTPUPIUTaskReq - Task request UPIU structure 28110802Srene.dejong@arm.com * header - UPIU header structure DW0 to DW-2 28210802Srene.dejong@arm.com * inputParam1: Input param 1 DW-3 28310802Srene.dejong@arm.com * inputParam2: Input param 2 DW-4 28410802Srene.dejong@arm.com * inputParam3: Input param 3 DW-5 28510802Srene.dejong@arm.com * reserved: Reserver DW-6 to DW-7 28610802Srene.dejong@arm.com */ 28710802Srene.dejong@arm.com struct UTPUPIUTaskReq { 28810802Srene.dejong@arm.com struct UTPUPIUHeader header; 28910802Srene.dejong@arm.com uint32_t inputParam1; 29010802Srene.dejong@arm.com uint32_t inputParam2; 29110802Srene.dejong@arm.com uint32_t inputParam3; 29210802Srene.dejong@arm.com uint32_t reserved[2]; 29310802Srene.dejong@arm.com }; 29410802Srene.dejong@arm.com 29510802Srene.dejong@arm.com /** 29610802Srene.dejong@arm.com * struct UFSHCDSGEntry - UFSHCI PRD Entry 29710802Srene.dejong@arm.com * baseAddr: Lower 32bit physical address DW-0 29810802Srene.dejong@arm.com * upperAddr: Upper 32bit physical address DW-1 29910802Srene.dejong@arm.com * reserved: Reserved for future use DW-2 30010802Srene.dejong@arm.com * size: size of physical segment DW-3 30110802Srene.dejong@arm.com */ 30210802Srene.dejong@arm.com struct UFSHCDSGEntry { 30310802Srene.dejong@arm.com uint32_t baseAddr; 30410802Srene.dejong@arm.com uint32_t upperAddr; 30510802Srene.dejong@arm.com uint32_t reserved; 30610802Srene.dejong@arm.com uint32_t size; 30710802Srene.dejong@arm.com }; 30810802Srene.dejong@arm.com 30910802Srene.dejong@arm.com /** 31010802Srene.dejong@arm.com * struct UTPTransferCMDDesc - UFS Commad Descriptor structure 31110802Srene.dejong@arm.com * commandUPIU: Command UPIU Frame address 31210802Srene.dejong@arm.com * responseUPIU: Response UPIU Frame address 31310802Srene.dejong@arm.com * PRDTable: Physcial Region Descriptor 31410802Srene.dejong@arm.com * All lengths as defined by JEDEC220 31510802Srene.dejong@arm.com */ 31610802Srene.dejong@arm.com struct UTPTransferCMDDesc { 31710802Srene.dejong@arm.com uint8_t commandUPIU[128]; 31810802Srene.dejong@arm.com uint8_t responseUPIU[128]; 31910802Srene.dejong@arm.com struct UFSHCDSGEntry PRDTable[128]; 32010802Srene.dejong@arm.com }; 32110802Srene.dejong@arm.com 32210802Srene.dejong@arm.com /** 32310802Srene.dejong@arm.com * UPIU tranfer message. 32410802Srene.dejong@arm.com */ 32510802Srene.dejong@arm.com struct UPIUMessage { 32610802Srene.dejong@arm.com struct UTPUPIUHeader header; 32710802Srene.dejong@arm.com uint32_t dataOffset; 32810802Srene.dejong@arm.com uint32_t dataCount; 32910802Srene.dejong@arm.com std::vector<uint32_t> dataMsg; 33010802Srene.dejong@arm.com }; 33110802Srene.dejong@arm.com 33210802Srene.dejong@arm.com /** 33310802Srene.dejong@arm.com * struct UTPTransferReqDesc - UTRD structure 33410802Srene.dejong@arm.com * header: UTRD header DW-0 to DW-3 33510802Srene.dejong@arm.com * commandDescBaseAddrLo: UCD base address low DW-4 33610802Srene.dejong@arm.com * commandDescBaseAddrHi: UCD base address high DW-5 33710802Srene.dejong@arm.com * responseUPIULength: response UPIU length DW-6 33810802Srene.dejong@arm.com * responseUPIUOffset: response UPIU offset DW-6 33910802Srene.dejong@arm.com * PRDTableLength: Physical region descriptor length DW-7 34010802Srene.dejong@arm.com * PRDTableOffset: Physical region descriptor offset DW-7 34110802Srene.dejong@arm.com */ 34210802Srene.dejong@arm.com struct UTPTransferReqDesc { 34310802Srene.dejong@arm.com 34410802Srene.dejong@arm.com /** 34510802Srene.dejong@arm.com * struct RequestDescHeader 34610802Srene.dejong@arm.com * dword0: Descriptor Header DW0 34710802Srene.dejong@arm.com * dword1: Descriptor Header DW1 34810802Srene.dejong@arm.com * dword2: Descriptor Header DW2 34910802Srene.dejong@arm.com * dword3: Descriptor Header DW3 35010802Srene.dejong@arm.com */ 35110802Srene.dejong@arm.com struct RequestDescHeader { 35210802Srene.dejong@arm.com uint32_t dWord0; 35310802Srene.dejong@arm.com uint32_t dWord1; 35410802Srene.dejong@arm.com uint32_t dWord2; 35510802Srene.dejong@arm.com uint32_t dWord3; 35610802Srene.dejong@arm.com } header; 35710802Srene.dejong@arm.com 35810802Srene.dejong@arm.com /* DW 4-5*/ 35910802Srene.dejong@arm.com uint32_t commandDescBaseAddrLo; 36010802Srene.dejong@arm.com uint32_t commandDescBaseAddrHi; 36110802Srene.dejong@arm.com 36210802Srene.dejong@arm.com /* DW 6 */ 36310802Srene.dejong@arm.com uint16_t responseUPIULength; 36410802Srene.dejong@arm.com uint16_t responseUPIUOffset; 36510802Srene.dejong@arm.com 36610802Srene.dejong@arm.com /* DW 7 */ 36710802Srene.dejong@arm.com uint16_t PRDTableLength; 36810802Srene.dejong@arm.com uint16_t PRDTableOffset; 36910802Srene.dejong@arm.com }; 37010802Srene.dejong@arm.com 37110802Srene.dejong@arm.com /** 37210802Srene.dejong@arm.com * SCSI reply structure. In here is all the information that is needed to 37310802Srene.dejong@arm.com * build a SCSI reply. 37410802Srene.dejong@arm.com */ 37510802Srene.dejong@arm.com struct SCSIReply { 37613025Smadnaurice@googlemail.com void reset() { 37713025Smadnaurice@googlemail.com memset(static_cast<void*>(this), 0, sizeof(*this)); 37813025Smadnaurice@googlemail.com } 37913025Smadnaurice@googlemail.com 38010802Srene.dejong@arm.com uint8_t status; 38110802Srene.dejong@arm.com uint32_t msgSize; 38210802Srene.dejong@arm.com uint8_t LUN; 38310802Srene.dejong@arm.com struct UPIUMessage message; 38410802Srene.dejong@arm.com uint8_t senseSize; 38510802Srene.dejong@arm.com uint8_t expectMore;//0x01 is for writes, 0x02 is for reads 38610802Srene.dejong@arm.com uint64_t offset; 38710802Srene.dejong@arm.com uint8_t senseCode[19]; 38810802Srene.dejong@arm.com }; 38910802Srene.dejong@arm.com 39010802Srene.dejong@arm.com /** 39110802Srene.dejong@arm.com * Logic unit information structure. SCSI requires information of each LUN. 39210802Srene.dejong@arm.com * This structure is defined in the SCSI standard, and can also be found in 39310802Srene.dejong@arm.com * the UFS standard. http://www.jedec.org/standards-documents/results/jesd220 39410802Srene.dejong@arm.com */ 39510802Srene.dejong@arm.com struct LUNInfo { 39610802Srene.dejong@arm.com uint32_t dWord0; 39710802Srene.dejong@arm.com uint32_t dWord1; 39810802Srene.dejong@arm.com uint32_t vendor0; 39910802Srene.dejong@arm.com uint32_t vendor1; 40010802Srene.dejong@arm.com uint32_t product0; 40110802Srene.dejong@arm.com uint32_t product1; 40210802Srene.dejong@arm.com uint32_t product2; 40310802Srene.dejong@arm.com uint32_t product3; 40410802Srene.dejong@arm.com uint32_t productRevision; 40510802Srene.dejong@arm.com }; 40610802Srene.dejong@arm.com 40710802Srene.dejong@arm.com /** 40810802Srene.dejong@arm.com * Different events, and scenarios require different types of information. 40910802Srene.dejong@arm.com * Keep in mind that for a read-from-disk transaction the host at first a 41010802Srene.dejong@arm.com * datastructure fetches to determine where and what the command is, then the 41110802Srene.dejong@arm.com * command fetches and the structure fetches to determine where the 41210802Srene.dejong@arm.com * different read transactions should be placed and then transfers all the 41310802Srene.dejong@arm.com * read fragments. It then answers to the original caller with two replies, 41410802Srene.dejong@arm.com * one for the command, and one for UFS. Each of these stages trigger a 41510802Srene.dejong@arm.com * different event, and each event needs to know what happened in the 41610802Srene.dejong@arm.com * previous stage and what is going to happen in the current one. This 41710802Srene.dejong@arm.com * happens also for writes, SCSI maintanance, UFS maintanance, command 41810802Srene.dejong@arm.com * management and task management. 41910802Srene.dejong@arm.com */ 42010802Srene.dejong@arm.com 42110802Srene.dejong@arm.com /** 42210802Srene.dejong@arm.com * Transfer information. 42310802Srene.dejong@arm.com * @filePointer this does not point to a file, but to a position on the disk 42410802Srene.dejong@arm.com * image (which is from the software systems perspective a position in a file) 42510802Srene.dejong@arm.com */ 42610802Srene.dejong@arm.com struct transferInfo { 42710802Srene.dejong@arm.com std::vector <uint8_t> buffer; 42810802Srene.dejong@arm.com uint32_t size; 42910802Srene.dejong@arm.com uint64_t offset; 43010802Srene.dejong@arm.com uint32_t filePointer; 43110802Srene.dejong@arm.com uint32_t lunID; 43210802Srene.dejong@arm.com }; 43310802Srene.dejong@arm.com 43410802Srene.dejong@arm.com /** 43510802Srene.dejong@arm.com * transfer completion info. 43610802Srene.dejong@arm.com * This information is needed by transferDone to finish the transfer. 43710802Srene.dejong@arm.com */ 43810802Srene.dejong@arm.com struct transferDoneInfo { 43910802Srene.dejong@arm.com Addr responseStartAddr; 44010802Srene.dejong@arm.com uint32_t reqPos; 44110802Srene.dejong@arm.com struct UTPUPIURSP requestOut; 44210802Srene.dejong@arm.com uint32_t size; 44310802Srene.dejong@arm.com Addr address; 44410802Srene.dejong@arm.com uint8_t *destination; 44510802Srene.dejong@arm.com bool finished; 44610802Srene.dejong@arm.com uint32_t lunID; 44710802Srene.dejong@arm.com }; 44810802Srene.dejong@arm.com 44910802Srene.dejong@arm.com /** 45010802Srene.dejong@arm.com * Transfer start information. 45110802Srene.dejong@arm.com */ 45210802Srene.dejong@arm.com struct transferStart { 45310802Srene.dejong@arm.com struct UTPTransferReqDesc* destination; 45410802Srene.dejong@arm.com uint32_t mask; 45510802Srene.dejong@arm.com Addr address; 45610802Srene.dejong@arm.com uint32_t size; 45710802Srene.dejong@arm.com uint32_t done; 45810802Srene.dejong@arm.com uint32_t lun_id; 45910802Srene.dejong@arm.com }; 46010802Srene.dejong@arm.com 46110802Srene.dejong@arm.com /** 46210802Srene.dejong@arm.com * Task start information. This is for the device, so no lun id needed. 46310802Srene.dejong@arm.com */ 46410802Srene.dejong@arm.com struct taskStart { 46510802Srene.dejong@arm.com struct UTPUPIUTaskReq destination; 46610802Srene.dejong@arm.com uint32_t mask; 46710802Srene.dejong@arm.com Addr address; 46810802Srene.dejong@arm.com uint32_t size; 46910802Srene.dejong@arm.com bool done; 47010802Srene.dejong@arm.com }; 47110802Srene.dejong@arm.com 47210802Srene.dejong@arm.com /** 47310802Srene.dejong@arm.com * After a SCSI command has been identified, the SCSI resume function will 47410802Srene.dejong@arm.com * handle it. This information will provide context information. 47510802Srene.dejong@arm.com */ 47610802Srene.dejong@arm.com struct SCSIResumeInfo { 47710802Srene.dejong@arm.com struct UTPTransferReqDesc* RequestIn; 47810802Srene.dejong@arm.com int reqPos; 47910802Srene.dejong@arm.com Addr finalAddress; 48010802Srene.dejong@arm.com uint32_t finalSize; 48110802Srene.dejong@arm.com std::vector <uint8_t> destination; 48210802Srene.dejong@arm.com uint32_t done; 48310802Srene.dejong@arm.com }; 48410802Srene.dejong@arm.com 48510802Srene.dejong@arm.com /** 48610802Srene.dejong@arm.com * Disk transfer burst information. Needed to allow communication between the 48710802Srene.dejong@arm.com * disk transactions and dma transactions. 48810802Srene.dejong@arm.com */ 48910802Srene.dejong@arm.com struct writeToDiskBurst { 49010802Srene.dejong@arm.com Addr start; 49110802Srene.dejong@arm.com uint64_t SCSIDiskOffset; 49210802Srene.dejong@arm.com uint32_t size; 49310802Srene.dejong@arm.com uint32_t LUN; 49410802Srene.dejong@arm.com }; 49510802Srene.dejong@arm.com 49610802Srene.dejong@arm.com /** 49710802Srene.dejong@arm.com * Statistics 49810802Srene.dejong@arm.com */ 49910802Srene.dejong@arm.com struct UFSHostDeviceStats { 50010802Srene.dejong@arm.com /** Queue lengths */ 50110802Srene.dejong@arm.com Stats::Scalar currentSCSIQueue; 50210802Srene.dejong@arm.com Stats::Scalar currentReadSSDQueue; 50310802Srene.dejong@arm.com Stats::Scalar currentWriteSSDQueue; 50410802Srene.dejong@arm.com 50510802Srene.dejong@arm.com /** Amount of data read/written */ 50610802Srene.dejong@arm.com Stats::Scalar totalReadSSD; 50710802Srene.dejong@arm.com Stats::Scalar totalWrittenSSD; 50810802Srene.dejong@arm.com Stats::Scalar totalReadDiskTransactions; 50910802Srene.dejong@arm.com Stats::Scalar totalWriteDiskTransactions; 51010802Srene.dejong@arm.com Stats::Scalar totalReadUFSTransactions; 51110802Srene.dejong@arm.com Stats::Scalar totalWriteUFSTransactions; 51210802Srene.dejong@arm.com 51310802Srene.dejong@arm.com /** Average bandwidth for reads and writes */ 51410802Srene.dejong@arm.com Stats::Formula averageReadSSDBW; 51510802Srene.dejong@arm.com Stats::Formula averageWriteSSDBW; 51610802Srene.dejong@arm.com 51710802Srene.dejong@arm.com /** Average Queue lengths*/ 51810802Srene.dejong@arm.com Stats::Average averageSCSIQueue; 51910802Srene.dejong@arm.com Stats::Average averageReadSSDQueue; 52010802Srene.dejong@arm.com Stats::Average averageWriteSSDQueue; 52110802Srene.dejong@arm.com 52210802Srene.dejong@arm.com /** Number of doorbells rung*/ 52310802Srene.dejong@arm.com Stats::Formula curDoorbell; 52410802Srene.dejong@arm.com Stats::Scalar maxDoorbell; 52510802Srene.dejong@arm.com Stats::Average averageDoorbell; 52610802Srene.dejong@arm.com 52710802Srene.dejong@arm.com /** Histogram of latencies*/ 52810802Srene.dejong@arm.com Stats::Histogram transactionLatency; 52910802Srene.dejong@arm.com Stats::Histogram idleTimes; 53010802Srene.dejong@arm.com }; 53110802Srene.dejong@arm.com 53210802Srene.dejong@arm.com /** 53310802Srene.dejong@arm.com * device layer: This is your Logic unit 53410802Srene.dejong@arm.com * This layer implements the SCSI functionality of the UFS Device 53510802Srene.dejong@arm.com * One logic unit controls one or more disk partitions 53610802Srene.dejong@arm.com */ 53710802Srene.dejong@arm.com class UFSSCSIDevice: SimObject 53810802Srene.dejong@arm.com { 53910802Srene.dejong@arm.com public: 54010802Srene.dejong@arm.com /** 54110802Srene.dejong@arm.com * Constructor and destructor 54210802Srene.dejong@arm.com */ 54310802Srene.dejong@arm.com UFSSCSIDevice(const UFSHostDeviceParams* p, uint32_t lun_id, Callback* 54410802Srene.dejong@arm.com transfer_cb, Callback *read_cb); 54510802Srene.dejong@arm.com ~UFSSCSIDevice(); 54610802Srene.dejong@arm.com 54710802Srene.dejong@arm.com /** 54810802Srene.dejong@arm.com * SCSI command handle function; determines what the command is and 54910802Srene.dejong@arm.com * returns a reply structure that allows the host device to continue 55010802Srene.dejong@arm.com * with the transfer. 55110802Srene.dejong@arm.com */ 55210802Srene.dejong@arm.com struct SCSIReply SCSICMDHandle(uint32_t* SCSI_msg); 55310802Srene.dejong@arm.com 55410802Srene.dejong@arm.com /** 55510802Srene.dejong@arm.com * Disk access functions. These will transfer the data from/to the disk 55610802Srene.dejong@arm.com */ 55710802Srene.dejong@arm.com 55810802Srene.dejong@arm.com /** 55910802Srene.dejong@arm.com * Read flash. read the data from the disk image. This function 56010802Srene.dejong@arm.com * doesn't model timing behaviour 56110802Srene.dejong@arm.com */ 56210802Srene.dejong@arm.com void readFlash(uint8_t* readaddr, uint64_t offset, uint32_t size); 56310802Srene.dejong@arm.com 56410802Srene.dejong@arm.com /** 56510802Srene.dejong@arm.com * Write flash. write the data to the disk image. This function 56610802Srene.dejong@arm.com * doesn't model timing behaviour 56710802Srene.dejong@arm.com */ 56810802Srene.dejong@arm.com void writeFlash(uint8_t* writeaddr, uint64_t offset, uint32_t size); 56910802Srene.dejong@arm.com 57010802Srene.dejong@arm.com /** 57110802Srene.dejong@arm.com * finished command. Probe to find out wether this logic unit 57210802Srene.dejong@arm.com * finished its transfer and triggered the callback; The host needs 57310802Srene.dejong@arm.com * this to handle the final part of the transaction. 57410802Srene.dejong@arm.com */ 57510802Srene.dejong@arm.com bool finishedCommand() const {return transferCompleted;}; 57610802Srene.dejong@arm.com 57710802Srene.dejong@arm.com /** 57810802Srene.dejong@arm.com * Clear signal. Handle for the host to clear the transfer complete 57910802Srene.dejong@arm.com * signal. 58010802Srene.dejong@arm.com */ 58110802Srene.dejong@arm.com void clearSignal() {transferCompleted = false;}; 58210802Srene.dejong@arm.com 58310802Srene.dejong@arm.com /** 58410802Srene.dejong@arm.com * Finished read. Probe to find out which logic unit finished its 58510802Srene.dejong@arm.com * read. This is needed, because multiple units can do transactions 58610802Srene.dejong@arm.com * at the same time, and need to push back data at the right time in 58710802Srene.dejong@arm.com * the right order. (because writes work the other way round, they do 58810802Srene.dejong@arm.com * not need this mechanism) 58910802Srene.dejong@arm.com */ 59010802Srene.dejong@arm.com bool finishedRead() const {return readCompleted;}; 59110802Srene.dejong@arm.com 59210802Srene.dejong@arm.com /** 59310802Srene.dejong@arm.com * Clear signal. Handle for the host to clear the read complete 59410802Srene.dejong@arm.com * signal. 59510802Srene.dejong@arm.com */ 59610802Srene.dejong@arm.com void clearReadSignal() {readCompleted = false;}; 59710802Srene.dejong@arm.com 59810802Srene.dejong@arm.com /** 59910802Srene.dejong@arm.com * Start the transactions to (and from) the disk 60010802Srene.dejong@arm.com * The host will queue all the transactions. Once the next phase 60110802Srene.dejong@arm.com * commences, this function should be started. 60210802Srene.dejong@arm.com */ 60310802Srene.dejong@arm.com void SSDReadStart(uint32_t total_read); 60410802Srene.dejong@arm.com void SSDWriteStart(); 60510802Srene.dejong@arm.com 60610802Srene.dejong@arm.com /** 60710802Srene.dejong@arm.com * Sets total amount of write transactions that needs to be made. 60810802Srene.dejong@arm.com * First they need to be fetched via DMA, so this value is needed in 60910802Srene.dejong@arm.com * a later stage. 61010802Srene.dejong@arm.com */ 61110802Srene.dejong@arm.com void setTotalWrite(uint32_t total_write) {totalWrite = total_write;}; 61210802Srene.dejong@arm.com 61310802Srene.dejong@arm.com /** 61410802Srene.dejong@arm.com * End of transfer information 61510802Srene.dejong@arm.com */ 61610802Srene.dejong@arm.com transferDoneInfo transferInfo; 61710802Srene.dejong@arm.com 61810802Srene.dejong@arm.com /** 61910802Srene.dejong@arm.com * Information message queues, as there can be multiple messages 62010802Srene.dejong@arm.com * queued for handling in this system. These are the main 62110802Srene.dejong@arm.com * communication interfaces between the Host and the device layers 62210802Srene.dejong@arm.com */ 62310802Srene.dejong@arm.com 62410802Srene.dejong@arm.com /** 62510802Srene.dejong@arm.com * SCSIInfoQueue: each LU handles its own SCSI commands. 62610802Srene.dejong@arm.com */ 62710802Srene.dejong@arm.com std::deque<struct SCSIResumeInfo> SCSIInfoQueue; 62810802Srene.dejong@arm.com 62910802Srene.dejong@arm.com /** 63010802Srene.dejong@arm.com * SSDReadInfo: Structure from disk to dma, that contains data, and 63110802Srene.dejong@arm.com * helper info to get it to the right place in the memory. 63210802Srene.dejong@arm.com */ 63310802Srene.dejong@arm.com std::deque<struct transferInfo> SSDReadInfo; 63410802Srene.dejong@arm.com 63510802Srene.dejong@arm.com /** 63610802Srene.dejong@arm.com * SSDWriteDoneInfo: Structure from dma to disk, that contains data, 63710802Srene.dejong@arm.com * and helper info to get it to the right place in the memory. 63810802Srene.dejong@arm.com * The done is added because it is going to the last phase of the 63910802Srene.dejong@arm.com * write transfer. 64010802Srene.dejong@arm.com */ 64110802Srene.dejong@arm.com std::deque<struct transferInfo> SSDWriteDoneInfo; 64210802Srene.dejong@arm.com 64310802Srene.dejong@arm.com private: 64410802Srene.dejong@arm.com /** 64510802Srene.dejong@arm.com * Functions to indicate that the action to the SSD has completed. 64610802Srene.dejong@arm.com */ 64710802Srene.dejong@arm.com /** 64810802Srene.dejong@arm.com * Read Call back; This is the callback function for the memory model 64910802Srene.dejong@arm.com */ 65010802Srene.dejong@arm.com void readCallback(); 65110802Srene.dejong@arm.com 65210802Srene.dejong@arm.com /** 65310802Srene.dejong@arm.com * SSD Read done; Determines if the final callback of the transaction 65410802Srene.dejong@arm.com * should be made at the end of a read transfer. 65510802Srene.dejong@arm.com */ 65610802Srene.dejong@arm.com void SSDReadDone(); 65710802Srene.dejong@arm.com 65810802Srene.dejong@arm.com /** 65910802Srene.dejong@arm.com * SSD Write Done; This is the callback function for the memory model. 66010802Srene.dejong@arm.com */ 66110802Srene.dejong@arm.com void SSDWriteDone(); 66210802Srene.dejong@arm.com 66310802Srene.dejong@arm.com /** 66410802Srene.dejong@arm.com * Status of SCSI. This may be linked to a status check in the future. 66510802Srene.dejong@arm.com * For now it (mainly) fills a data structure with sense information 66610802Srene.dejong@arm.com * for a successfull transaction 66710802Srene.dejong@arm.com */ 66810802Srene.dejong@arm.com void statusCheck(uint8_t status, uint8_t* sensecodelist); 66910802Srene.dejong@arm.com 67010802Srene.dejong@arm.com /** 67110802Srene.dejong@arm.com * set signal to indicate that the transaction has been completed. 67210802Srene.dejong@arm.com */ 67310802Srene.dejong@arm.com void setSignal() {transferCompleted = true;}; 67410802Srene.dejong@arm.com 67510802Srene.dejong@arm.com /** 67610802Srene.dejong@arm.com * set signal to indicate that the read action has been completed 67710802Srene.dejong@arm.com */ 67810802Srene.dejong@arm.com void setReadSignal() {readCompleted = true;}; 67910802Srene.dejong@arm.com 68010802Srene.dejong@arm.com /** 68110802Srene.dejong@arm.com * The objects this model links to. 68210802Srene.dejong@arm.com * 1: the disk data model 68310802Srene.dejong@arm.com * 2: the memory timing model 68410802Srene.dejong@arm.com */ 68510802Srene.dejong@arm.com DiskImage* flashDisk; 68610802Srene.dejong@arm.com AbstractNVM* flashDevice; 68710802Srene.dejong@arm.com 68810802Srene.dejong@arm.com /** 68910802Srene.dejong@arm.com * Logic unit dimensions 69010802Srene.dejong@arm.com */ 69110802Srene.dejong@arm.com const uint32_t blkSize; 69210802Srene.dejong@arm.com const uint32_t lunAvail; 69310802Srene.dejong@arm.com const uint64_t diskSize; 69410802Srene.dejong@arm.com const uint32_t capacityLower; 69510802Srene.dejong@arm.com const uint32_t capacityUpper; 69610802Srene.dejong@arm.com 69710802Srene.dejong@arm.com /** 69810802Srene.dejong@arm.com * Logic unit info; needed for SCSI Info messages and LU 69910802Srene.dejong@arm.com * identification 70010802Srene.dejong@arm.com */ 70110802Srene.dejong@arm.com struct LUNInfo lunInfo; 70210802Srene.dejong@arm.com const uint32_t lunID; 70310802Srene.dejong@arm.com 70410802Srene.dejong@arm.com /** 70510802Srene.dejong@arm.com * Signals to Host layer 70610802Srene.dejong@arm.com * 1: signal for transaction completion 70710802Srene.dejong@arm.com * 2: signal for read action completion 70810802Srene.dejong@arm.com */ 70910802Srene.dejong@arm.com bool transferCompleted; 71010802Srene.dejong@arm.com bool readCompleted; 71110802Srene.dejong@arm.com 71210802Srene.dejong@arm.com /** 71310802Srene.dejong@arm.com * Total amount transactions that need to be made 71410802Srene.dejong@arm.com */ 71510802Srene.dejong@arm.com uint32_t totalRead; 71610802Srene.dejong@arm.com uint32_t totalWrite; 71710802Srene.dejong@arm.com 71810802Srene.dejong@arm.com /** 71910802Srene.dejong@arm.com * transaction progress tracking 72010802Srene.dejong@arm.com */ 72110802Srene.dejong@arm.com uint32_t amountOfWriteTransfers; 72210802Srene.dejong@arm.com uint32_t amountOfReadTransfers; 72310802Srene.dejong@arm.com 72410802Srene.dejong@arm.com /** 72510802Srene.dejong@arm.com * Callbacks between Host and Device 72610802Srene.dejong@arm.com */ 72710802Srene.dejong@arm.com Callback* signalDone; 72810802Srene.dejong@arm.com Callback* deviceReadCallback; 72910802Srene.dejong@arm.com 73010802Srene.dejong@arm.com /** 73110802Srene.dejong@arm.com * Callbacks between Device and Memory 73210802Srene.dejong@arm.com */ 73310802Srene.dejong@arm.com Callback* memReadCallback; 73410802Srene.dejong@arm.com Callback* memWriteCallback; 73510802Srene.dejong@arm.com 73610802Srene.dejong@arm.com /* 73710802Srene.dejong@arm.com * Default response header layout. For more information refer to 73810802Srene.dejong@arm.com * chapter 7 http://www.jedec.org/standards-documents/results/jesd220 73910802Srene.dejong@arm.com */ 74010802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord0 = 0x0000C022; 74110802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord1 = 0x00000000; 74210802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord2 = 0x40000000; 74310802Srene.dejong@arm.com 74410802Srene.dejong@arm.com /* 74510802Srene.dejong@arm.com * SCSI mode pages values assigned in ufs_device.cc 74610802Srene.dejong@arm.com * The mode pages give device specific information via the SCSI 74710802Srene.dejong@arm.com * protocol. They are defined in 74810802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 74910802Srene.dejong@arm.com */ 75010802Srene.dejong@arm.com static const unsigned int controlPage[3]; 75110802Srene.dejong@arm.com static const unsigned int recoveryPage[3]; 75210802Srene.dejong@arm.com static const unsigned int cachingPage[5]; 75310802Srene.dejong@arm.com 75410802Srene.dejong@arm.com /* 75510802Srene.dejong@arm.com * SCSI command set; defined in 75610802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 75710802Srene.dejong@arm.com */ 75810802Srene.dejong@arm.com enum SCSICommandSet { 75910802Srene.dejong@arm.com SCSIInquiry = 0x12, 76010802Srene.dejong@arm.com SCSIRead6 = 0x08, 76110802Srene.dejong@arm.com SCSIRead10 = 0x28, 76210802Srene.dejong@arm.com SCSIRead16 = 0x88, 76310802Srene.dejong@arm.com SCSIReadCapacity10 = 0x25, 76410802Srene.dejong@arm.com SCSIReadCapacity16 = 0x9E, 76510802Srene.dejong@arm.com SCSIReportLUNs = 0xA0, 76610802Srene.dejong@arm.com SCSIStartStop = 0x1B, 76710802Srene.dejong@arm.com SCSITestUnitReady = 0x00, 76810802Srene.dejong@arm.com SCSIVerify10 = 0x2F, 76910802Srene.dejong@arm.com SCSIWrite6 = 0x0A, 77010802Srene.dejong@arm.com SCSIWrite10 = 0x2A, 77110802Srene.dejong@arm.com SCSIWrite16 = 0x8A, 77210802Srene.dejong@arm.com SCSIFormatUnit = 0x04, 77310802Srene.dejong@arm.com SCSISendDiagnostic = 0x1D, 77410802Srene.dejong@arm.com SCSISynchronizeCache = 0x35, 77510802Srene.dejong@arm.com //UFS SCSI additional command set for full functionality 77610802Srene.dejong@arm.com SCSIModeSelect10 = 0x55, 77710802Srene.dejong@arm.com SCSIModeSense6 = 0x1A, 77810802Srene.dejong@arm.com SCSIModeSense10 = 0x5A, 77910802Srene.dejong@arm.com SCSIRequestSense = 0x03, 78010802Srene.dejong@arm.com SCSIUnmap = 0x42, 78110802Srene.dejong@arm.com SCSIWriteBuffer = 0x3B, 78210802Srene.dejong@arm.com SCSIReadBuffer = 0x3C, 78310802Srene.dejong@arm.com //SCSI commands not supported by UFS; but Linux send them anyway 78410802Srene.dejong@arm.com SCSIMaintenanceIn = 0xA3 78510802Srene.dejong@arm.com }; 78610802Srene.dejong@arm.com 78710802Srene.dejong@arm.com /* 78810802Srene.dejong@arm.com * SCSI status codes; defined in 78910802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 79010802Srene.dejong@arm.com */ 79110802Srene.dejong@arm.com enum SCSIStatusCodes { 79210802Srene.dejong@arm.com SCSIGood = 0x00, 79310802Srene.dejong@arm.com SCSICheckCondition = 0x02, 79410802Srene.dejong@arm.com SCSIConditionGood = 0x04, 79510802Srene.dejong@arm.com SCSIBusy = 0x08, 79610802Srene.dejong@arm.com SCSIIntermediateGood = 0x10, 79710802Srene.dejong@arm.com SCSIIntermediatCGood = 0x14, 79810802Srene.dejong@arm.com SCSIReservationConflict = 0x18, 79910802Srene.dejong@arm.com SCSICommandTerminated = 0x22, 80010802Srene.dejong@arm.com SCSITaskSetFull = 0x28, 80110802Srene.dejong@arm.com SCSIACAActive = 0x30, 80210802Srene.dejong@arm.com SCSITaskAborted = 0x40 80310802Srene.dejong@arm.com }; 80410802Srene.dejong@arm.com 80510802Srene.dejong@arm.com /* 80610802Srene.dejong@arm.com * SCSI sense codes; defined in 80710802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 80810802Srene.dejong@arm.com */ 80910802Srene.dejong@arm.com enum SCSISenseCodes { 81010802Srene.dejong@arm.com SCSINoSense = 0x00, 81110802Srene.dejong@arm.com SCSIRecoverdError = 0x01, 81210802Srene.dejong@arm.com SCSINotReady = 0x02, 81310802Srene.dejong@arm.com SCSIMediumError = 0x03, 81410802Srene.dejong@arm.com SCSIHardwareError = 0x04, 81510802Srene.dejong@arm.com SCSIIllegalRequest = 0x05, 81610802Srene.dejong@arm.com SCSIUnitAttention = 0x06, 81710802Srene.dejong@arm.com SCSIDataProtect = 0x07, 81810802Srene.dejong@arm.com SCSIBlankCheck = 0x08, 81910802Srene.dejong@arm.com SCSIAbortedCommand = 0x0B, 82010802Srene.dejong@arm.com SCSIVolumeOverflow = 0x0D, 82110802Srene.dejong@arm.com SCSIMisCompare = 0x0E 82210802Srene.dejong@arm.com }; 82310802Srene.dejong@arm.com 82410802Srene.dejong@arm.com }; 82510802Srene.dejong@arm.com 82610802Srene.dejong@arm.com //All access functions are inherrited; no need to make them public 82710802Srene.dejong@arm.com /** 82810802Srene.dejong@arm.com * Address range functions 82910802Srene.dejong@arm.com */ 83011174Sandreas.hansson@arm.com AddrRangeList getAddrRanges() const override; 83110802Srene.dejong@arm.com 83210802Srene.dejong@arm.com /** 83310802Srene.dejong@arm.com * register access functions 83410802Srene.dejong@arm.com */ 83511174Sandreas.hansson@arm.com Tick read(PacketPtr pkt) override; 83611174Sandreas.hansson@arm.com Tick write(PacketPtr pkt) override; 83710802Srene.dejong@arm.com // end of access functions 83810802Srene.dejong@arm.com 83910802Srene.dejong@arm.com /** 84010802Srene.dejong@arm.com * Initialization function. Sets the sefault HCI register values 84110802Srene.dejong@arm.com */ 84210802Srene.dejong@arm.com void setValues(); 84310802Srene.dejong@arm.com 84410802Srene.dejong@arm.com /** 84510802Srene.dejong@arm.com * Handler functions. Each function handles a different stage of the 84610802Srene.dejong@arm.com * transfer. Note that the UFS protocol specifies three types of messages 84710802Srene.dejong@arm.com * to the host (and devices): 84810802Srene.dejong@arm.com * 1: Command (to Host specifically) 84910802Srene.dejong@arm.com * 2: Task (to device; to control flow, not for data) 85010802Srene.dejong@arm.com * 3: Transfer (to device; to transfer data) 85110802Srene.dejong@arm.com */ 85210802Srene.dejong@arm.com /** 85310802Srene.dejong@arm.com * request handler. This function finds the cause of the request and 85410802Srene.dejong@arm.com * triggers the right follow-up action (command handler, task handler, 85510802Srene.dejong@arm.com * or transferhandler) 85610802Srene.dejong@arm.com */ 85710802Srene.dejong@arm.com void requestHandler(); 85810802Srene.dejong@arm.com 85910802Srene.dejong@arm.com /** 86010802Srene.dejong@arm.com * Command handler function. Handles the command send to the Host 86110802Srene.dejong@arm.com * controller 86210802Srene.dejong@arm.com */ 86310802Srene.dejong@arm.com void commandHandler(); 86410802Srene.dejong@arm.com 86510802Srene.dejong@arm.com /** 86610802Srene.dejong@arm.com * Task Start function. Starts the task handler once the task data 86710802Srene.dejong@arm.com * structure has arrived 86810802Srene.dejong@arm.com */ 86910802Srene.dejong@arm.com void taskStart(); 87010802Srene.dejong@arm.com 87110802Srene.dejong@arm.com /** 87210802Srene.dejong@arm.com * Task handler function. Handles the tasks send to the devices 87310802Srene.dejong@arm.com * because there are not many tasks implemented yet this is kept in the 87410802Srene.dejong@arm.com * Host controller layer 87510802Srene.dejong@arm.com */ 87610802Srene.dejong@arm.com void taskHandler(struct UTPUPIUTaskReq* request_in, 87710802Srene.dejong@arm.com uint32_t req_pos, Addr finaladdress, uint32_t finalsize); 87810802Srene.dejong@arm.com 87910802Srene.dejong@arm.com /** 88010802Srene.dejong@arm.com * Transfer Start function. Starts the transfer handler once the transfer 88110802Srene.dejong@arm.com * data structure has arrived 88210802Srene.dejong@arm.com */ 88310802Srene.dejong@arm.com void transferStart(); 88410802Srene.dejong@arm.com 88510802Srene.dejong@arm.com /** 88610802Srene.dejong@arm.com * Transfer handler function. Handles the transfers send to the devices 88710802Srene.dejong@arm.com * Important to understand here is that a Logic unit is not a device (a 88810802Srene.dejong@arm.com * device can contain multiple logic units). This function analyses the 88910802Srene.dejong@arm.com * first data structure that has been transfered. Which will tell the 89010802Srene.dejong@arm.com * host to expect SCSI frames for the rest of the transaction. Note that 89110802Srene.dejong@arm.com * the host has no indication whatsoever which LU to address. That will 89210802Srene.dejong@arm.com * follow in the next transaction. 89310802Srene.dejong@arm.com */ 89410802Srene.dejong@arm.com void transferHandler(struct UTPTransferReqDesc* 89510802Srene.dejong@arm.com request_in, int req_pos, Addr finaladdress, 89610802Srene.dejong@arm.com uint32_t finalsize, uint32_t done); 89710802Srene.dejong@arm.com 89810802Srene.dejong@arm.com /** 89910802Srene.dejong@arm.com * Transfer SCSI function. Determines which Logic unit to address and 90010802Srene.dejong@arm.com * starts the SCSI resume function 90110802Srene.dejong@arm.com */ 90210802Srene.dejong@arm.com void SCSIStart(); 90310802Srene.dejong@arm.com 90410802Srene.dejong@arm.com /** 90510802Srene.dejong@arm.com * Starts the scsi handling function in the apropriate Logic unit, 90610802Srene.dejong@arm.com * prepares the right data transfer scheme and kicks it off. 90710802Srene.dejong@arm.com */ 90810802Srene.dejong@arm.com void SCSIResume(uint32_t lun_id); 90910802Srene.dejong@arm.com 91010802Srene.dejong@arm.com /** 91110802Srene.dejong@arm.com * LU callback function to indicate that the action has completed. 91210802Srene.dejong@arm.com */ 91310802Srene.dejong@arm.com void LUNSignal(); 91410802Srene.dejong@arm.com 91510802Srene.dejong@arm.com /** 91610802Srene.dejong@arm.com * transfer done, the beginning of the final stage of the transfer. 91710802Srene.dejong@arm.com * Acknowledges UPIU frame and prepares the UTP response frame 91810802Srene.dejong@arm.com */ 91910802Srene.dejong@arm.com void transferDone(Addr responseStartAddr, uint32_t req_pos, 92010802Srene.dejong@arm.com struct UTPUPIURSP request_out, uint32_t size, 92110802Srene.dejong@arm.com Addr address, uint8_t* destination, bool finished, 92210802Srene.dejong@arm.com uint32_t lun_id); 92310802Srene.dejong@arm.com /** 92410802Srene.dejong@arm.com * final UTP, sends the last acknowledge data structure to the system; 92510802Srene.dejong@arm.com * prepares the clean up functions. 92610802Srene.dejong@arm.com */ 92710802Srene.dejong@arm.com void finalUTP(); 92810802Srene.dejong@arm.com 92910802Srene.dejong@arm.com /** 93010802Srene.dejong@arm.com * Interrupt control functions 93110802Srene.dejong@arm.com */ 93210802Srene.dejong@arm.com void clearInterrupt(); 93310802Srene.dejong@arm.com void generateInterrupt(); 93410802Srene.dejong@arm.com 93510802Srene.dejong@arm.com /** 93610802Srene.dejong@arm.com * DMA transfer functions 93710802Srene.dejong@arm.com * These allow the host to push/pull the data to the memory 93810802Srene.dejong@arm.com * The provided event indicates what the next phase it that will handle 93910802Srene.dejong@arm.com * the obtained data, or what the follow up action is once the data has 94010802Srene.dejong@arm.com * been pushed to the memory 94110802Srene.dejong@arm.com */ 94210802Srene.dejong@arm.com void writeDevice(Event* additional_action, bool toDisk, Addr start, 94310802Srene.dejong@arm.com int size, uint8_t* destination, uint64_t SCSIDiskOffset, 94410802Srene.dejong@arm.com uint32_t lun_id); 94510802Srene.dejong@arm.com void readDevice(bool lastTransfer, Addr SCSIStart, uint32_t SCSISize, 94610802Srene.dejong@arm.com uint8_t* SCSIDestination, bool no_cache, 94710802Srene.dejong@arm.com Event* additional_action); 94810802Srene.dejong@arm.com 94910802Srene.dejong@arm.com /** 95010802Srene.dejong@arm.com * Disk transfer management functions 95110802Srene.dejong@arm.com * these set up the queues, and initiated them, leading to the data 95210802Srene.dejong@arm.com * transaction timing model based on the scatter gather list constructed 95310802Srene.dejong@arm.com * in SCSIresume. 95410802Srene.dejong@arm.com */ 95510802Srene.dejong@arm.com void manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t 95610802Srene.dejong@arm.com sg_table_length, struct UFSHCDSGEntry* sglist); 95710802Srene.dejong@arm.com void manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t offset, 95810802Srene.dejong@arm.com uint32_t sg_table_length, 95910802Srene.dejong@arm.com struct UFSHCDSGEntry* sglist); 96010802Srene.dejong@arm.com 96110802Srene.dejong@arm.com /** 96210802Srene.dejong@arm.com * Read done 96310802Srene.dejong@arm.com * Started at the end of a transaction after the last read action. Cleans 96410802Srene.dejong@arm.com * up UTP descriptor and other remaining data structures. It also raises 96510802Srene.dejong@arm.com * the interrupt. 96610802Srene.dejong@arm.com */ 96710802Srene.dejong@arm.com void readDone(); 96810802Srene.dejong@arm.com 96910802Srene.dejong@arm.com /** 97010802Srene.dejong@arm.com * Write done 97110802Srene.dejong@arm.com * After a DMA write with data intended for the disk, this function is 97210802Srene.dejong@arm.com * called. It ensures that the disk image is modified, and that the 97310802Srene.dejong@arm.com * correct timing function is triggered. 97410802Srene.dejong@arm.com */ 97510802Srene.dejong@arm.com void writeDone(); 97610802Srene.dejong@arm.com 97710802Srene.dejong@arm.com /** 97810802Srene.dejong@arm.com * Read callback 97910802Srene.dejong@arm.com * Call back function for the logic units to indicate the completion of 98010802Srene.dejong@arm.com * a read action. Note that this is needed because the read functionality 98110802Srene.dejong@arm.com * needs to push data structures back to the memory. 98210802Srene.dejong@arm.com */ 98310802Srene.dejong@arm.com void readCallback(); 98410802Srene.dejong@arm.com 98510802Srene.dejong@arm.com /** 98610802Srene.dejong@arm.com * Read garbage 98710802Srene.dejong@arm.com * A read from disk data structure can vary in size and is therefor 98810802Srene.dejong@arm.com * allocated on creation. It can only be destroyed once that particular 98910802Srene.dejong@arm.com * read action has completed. This function is called on completion of a 99010802Srene.dejong@arm.com * read from disk action to handle this. 99110802Srene.dejong@arm.com */ 99210802Srene.dejong@arm.com void readGarbage(); 99310802Srene.dejong@arm.com 99410802Srene.dejong@arm.com /**register statistics*/ 99511174Sandreas.hansson@arm.com void regStats() override; 99610802Srene.dejong@arm.com 99710802Srene.dejong@arm.com /** 99810802Srene.dejong@arm.com * Host controller information 99910802Srene.dejong@arm.com */ 100010802Srene.dejong@arm.com const Addr pioAddr; 100110802Srene.dejong@arm.com const Addr pioSize; 100210802Srene.dejong@arm.com const Tick pioDelay; 100310802Srene.dejong@arm.com const int intNum; 100410802Srene.dejong@arm.com BaseGic* gic; 100510802Srene.dejong@arm.com const uint32_t lunAvail; 100610802Srene.dejong@arm.com const uint8_t UFSSlots; 100710802Srene.dejong@arm.com 100810802Srene.dejong@arm.com /** 100910802Srene.dejong@arm.com * Host controller memory 101010802Srene.dejong@arm.com */ 101110802Srene.dejong@arm.com HCIMem UFSHCIMem; 101210802Srene.dejong@arm.com 101310802Srene.dejong@arm.com /** 101410802Srene.dejong@arm.com * Track number of DMA transactions in progress 101510802Srene.dejong@arm.com */ 101610802Srene.dejong@arm.com int readPendingNum; 101710802Srene.dejong@arm.com int writePendingNum; 101810802Srene.dejong@arm.com 101910802Srene.dejong@arm.com /** 102010802Srene.dejong@arm.com * Statistics helper variables 102110802Srene.dejong@arm.com * Active doorbells indicates how many doorbells are in teh process of 102210802Srene.dejong@arm.com * being handled. 102310802Srene.dejong@arm.com * Pending doorbells have been handled and are waiting to be acknowledged 102410802Srene.dejong@arm.com * by the host system. 102510802Srene.dejong@arm.com * The doorbell register is 32 bits wide, so one byte is enough to keep 102610802Srene.dejong@arm.com * track of the numbers 102710802Srene.dejong@arm.com */ 102810802Srene.dejong@arm.com uint8_t activeDoorbells; 102910802Srene.dejong@arm.com uint8_t pendingDoorbells; 103010802Srene.dejong@arm.com 103110802Srene.dejong@arm.com /** 103210802Srene.dejong@arm.com * interrupt verification 103310802Srene.dejong@arm.com * This keeps track of the number of interrupts generated. It is usefull 103410802Srene.dejong@arm.com * for debug purposes. Make sure that the implemented driver prints the 103510802Srene.dejong@arm.com * number of interrupts it has handled so far to fully benefit from this 103610802Srene.dejong@arm.com * feature. 103710802Srene.dejong@arm.com */ 103810802Srene.dejong@arm.com uint32_t countInt; 103910802Srene.dejong@arm.com 104010802Srene.dejong@arm.com /** 104110802Srene.dejong@arm.com * Track the transfer 104210802Srene.dejong@arm.com * This is allows the driver to "group" certain transfers together by 104310802Srene.dejong@arm.com * using a tag in the UPIU. The messages with the same tag should be 104410802Srene.dejong@arm.com * handled together, i.e. their doorbells should be cleared when they are 104510802Srene.dejong@arm.com * all done. but we need to keep track of the ones we already handled, 104610802Srene.dejong@arm.com * this integer shadows the doorbells to allow this behaviour. 104710802Srene.dejong@arm.com */ 104810802Srene.dejong@arm.com uint32_t transferTrack; 104910802Srene.dejong@arm.com uint32_t taskCommandTrack; 105010802Srene.dejong@arm.com 105110802Srene.dejong@arm.com /** 105210802Srene.dejong@arm.com * Helper for latency stats 105310802Srene.dejong@arm.com * These variables keep track of the latency for every doorbell. 105410802Srene.dejong@arm.com * Eventually the latenmcies will be put in a histogram. 105510802Srene.dejong@arm.com */ 105610802Srene.dejong@arm.com Tick transactionStart[32]; 105710802Srene.dejong@arm.com Tick idlePhaseStart; 105810802Srene.dejong@arm.com 105910802Srene.dejong@arm.com /** 106010802Srene.dejong@arm.com * logic units connected to the UFS Host device 106110802Srene.dejong@arm.com * Note again that the "device" as such is represented by one or multiple 106210802Srene.dejong@arm.com * logic units. 106310802Srene.dejong@arm.com */ 106410802Srene.dejong@arm.com std::vector<UFSSCSIDevice*> UFSDevice; 106510802Srene.dejong@arm.com 106610802Srene.dejong@arm.com /** 106710802Srene.dejong@arm.com * SCSI reply structure, used for direct answering. Might be refered to 106810802Srene.dejong@arm.com * during the assembly of the reply (data, and response; e.g. if 106910802Srene.dejong@arm.com * something goes wrong along the way, the reply will be different) 107010802Srene.dejong@arm.com */ 107110802Srene.dejong@arm.com struct SCSIReply request_out_datain; 107210802Srene.dejong@arm.com 107310802Srene.dejong@arm.com /** 107410802Srene.dejong@arm.com * SCSI resume info 107510802Srene.dejong@arm.com * information structure for SCSI resume. it keeps track of all the 107610802Srene.dejong@arm.com * information that is needed to successfully complete the transaction 107710802Srene.dejong@arm.com * (response addresses, communicated information so far, etc.). 107810802Srene.dejong@arm.com */ 107910802Srene.dejong@arm.com struct SCSIResumeInfo SCSIInfo; 108010802Srene.dejong@arm.com 108110802Srene.dejong@arm.com /** 108210802Srene.dejong@arm.com * To finish the transaction one needs information about the original 108310802Srene.dejong@arm.com * message. This is stored in this queue 108410802Srene.dejong@arm.com * transferEnd uses the same structure as transferStartInfo, because all 108510802Srene.dejong@arm.com * the information it needs is in there. It improves readability in the 108610802Srene.dejong@arm.com * cc file. 108710802Srene.dejong@arm.com */ 108810802Srene.dejong@arm.com std::deque<struct transferStart> transferEnd; 108910802Srene.dejong@arm.com 109010802Srene.dejong@arm.com /** 109110802Srene.dejong@arm.com * When a task/transfer is started it needs information about the 109210802Srene.dejong@arm.com * task/transfer it is about to perform. This is defined in these 109310802Srene.dejong@arm.com * structures. If multiple tasks/transfers are issued at the same time, 109410802Srene.dejong@arm.com * they still need to be fetched one by one. They then need to be 109510802Srene.dejong@arm.com * executed in the order specified by the UFS standard (least significant 109610802Srene.dejong@arm.com * doorbell first). The tasks/transfers are placed in the queue in that 109710802Srene.dejong@arm.com * specific order. 109810802Srene.dejong@arm.com */ 109910802Srene.dejong@arm.com std::deque<struct taskStart> taskInfo; 110010802Srene.dejong@arm.com std::deque<struct transferStart> transferStartInfo; 110110802Srene.dejong@arm.com 110210802Srene.dejong@arm.com /** 110310802Srene.dejong@arm.com * Information to get a DMA transaction 110410802Srene.dejong@arm.com */ 110510802Srene.dejong@arm.com std::deque<struct writeToDiskBurst> dmaWriteInfo; 110610802Srene.dejong@arm.com 110710802Srene.dejong@arm.com /** 110810802Srene.dejong@arm.com * Information from DMA transaction to disk 110910802Srene.dejong@arm.com */ 111010802Srene.dejong@arm.com std::deque<struct transferInfo> SSDWriteinfo; 111110802Srene.dejong@arm.com 111210802Srene.dejong@arm.com /** 111310802Srene.dejong@arm.com * Information from the Disk, waiting to be pushed to the DMA 111410802Srene.dejong@arm.com */ 111510802Srene.dejong@arm.com std::deque<struct transferInfo> SSDReadPending; 111610802Srene.dejong@arm.com 111710802Srene.dejong@arm.com /** 111810802Srene.dejong@arm.com * garbage queue, ensure clearing of the allocated memory 111910802Srene.dejong@arm.com */ 112010802Srene.dejong@arm.com std::deque<struct UTPTransferReqDesc*> garbage; 112110802Srene.dejong@arm.com 112210802Srene.dejong@arm.com /** 112310802Srene.dejong@arm.com * RequestHandler stats 112410802Srene.dejong@arm.com */ 112510802Srene.dejong@arm.com struct UFSHostDeviceStats stats; 112610802Srene.dejong@arm.com 112710802Srene.dejong@arm.com /** 112810802Srene.dejong@arm.com * Transfer flow events 112910802Srene.dejong@arm.com * Basically these events form two queues, one from memory to UFS device 113010802Srene.dejong@arm.com * (DMA) and one from device to flash (SSD). The SSD "queue" is 113110802Srene.dejong@arm.com * maintained by the flash and the lun classes and does not form a queue 113210802Srene.dejong@arm.com * of events as such, but rather a queue of information. This can be done 113310802Srene.dejong@arm.com * because the flow of the events is completely in the control of these 113410802Srene.dejong@arm.com * classes. (Whereas in the DMA case we rely on an external class) 113510802Srene.dejong@arm.com */ 113612086Sspwilson2@wisc.edu std::deque<EventFunctionWrapper> readDoneEvent; 113712086Sspwilson2@wisc.edu std::deque<EventFunctionWrapper> writeDoneEvent; 113810802Srene.dejong@arm.com 113910802Srene.dejong@arm.com /** 114010802Srene.dejong@arm.com * Callbacks for the logic units. One to indicate the completion of a 114110802Srene.dejong@arm.com * transaction, the other one to indicate the completion of a read 114210802Srene.dejong@arm.com * action. 114310802Srene.dejong@arm.com */ 114410802Srene.dejong@arm.com Callback* transferDoneCallback; 114510802Srene.dejong@arm.com Callback* memReadCallback; 114610802Srene.dejong@arm.com 114710802Srene.dejong@arm.com /** 114810802Srene.dejong@arm.com * The events that control the functionality. 114910802Srene.dejong@arm.com * After a doorbell has been set, either a taskevent or a transfer event 115010802Srene.dejong@arm.com * is scheduled. A transfer event might schedule a SCSI event, all events 115110802Srene.dejong@arm.com * sequences end with an UTP event, which can be considered as the event 115210802Srene.dejong@arm.com * which answers the doorbell. 115310802Srene.dejong@arm.com */ 115410802Srene.dejong@arm.com /** 115510802Srene.dejong@arm.com * Wait for the SCSI specific data to arive 115610802Srene.dejong@arm.com */ 115712087Sspwilson2@wisc.edu EventFunctionWrapper SCSIResumeEvent; 115810802Srene.dejong@arm.com 115910802Srene.dejong@arm.com /** 116010802Srene.dejong@arm.com * Wait for the moment where we can send the last frame 116110802Srene.dejong@arm.com */ 116212087Sspwilson2@wisc.edu EventFunctionWrapper UTPEvent; 116310802Srene.dejong@arm.com 116410802Srene.dejong@arm.com /** 116510802Srene.dejong@arm.com * Event after a read to clean up the UTP data structures 116610802Srene.dejong@arm.com */ 116712087Sspwilson2@wisc.edu std::deque<EventFunctionWrapper> readGarbageEventQueue; 116810802Srene.dejong@arm.com 116910802Srene.dejong@arm.com /** 117010802Srene.dejong@arm.com * Multiple tasks transfers can be scheduled at once for the device, the 117110802Srene.dejong@arm.com * only thing we know for sure about them is that they will happen in a 117210802Srene.dejong@arm.com * first come first serve order; hence we need to queue. 117310802Srene.dejong@arm.com */ 117412087Sspwilson2@wisc.edu std::deque<EventFunctionWrapper> taskEventQueue; 117512087Sspwilson2@wisc.edu std::deque<EventFunctionWrapper> transferEventQueue; 117610802Srene.dejong@arm.com 117710802Srene.dejong@arm.com /** 117810802Srene.dejong@arm.com * Bits of interest within UFS data packages 117910802Srene.dejong@arm.com */ 118010802Srene.dejong@arm.com static const unsigned int UTPTransferREQCOMPL = 0x01;//UFS_BIT(0) 118110802Srene.dejong@arm.com static const unsigned int UTPTaskREQCOMPL = 0x200;//UFS_BIT(9) 118210802Srene.dejong@arm.com static const unsigned int UICCommandCOMPL = 0x400;//UFS_BIT(10) 118310802Srene.dejong@arm.com static const unsigned int UICCommandReady = 0x08;//UFS_BIT(3) 118410802Srene.dejong@arm.com 118510802Srene.dejong@arm.com /* 118610802Srene.dejong@arm.com * UFSHCI Registers; please refer to 118710802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd223 118810802Srene.dejong@arm.com * for their definition. 118910802Srene.dejong@arm.com */ 119010802Srene.dejong@arm.com enum UFSHCIRegisters { 119110802Srene.dejong@arm.com regControllerCapabilities = 0x00, 119210802Srene.dejong@arm.com regUFSVersion = 0x08, 119310802Srene.dejong@arm.com regControllerDEVID = 0x10, 119410802Srene.dejong@arm.com regControllerPRODID = 0x14, 119510802Srene.dejong@arm.com regInterruptStatus = 0x20, 119610802Srene.dejong@arm.com regInterruptEnable = 0x24, 119710802Srene.dejong@arm.com regControllerStatus = 0x30, 119810802Srene.dejong@arm.com regControllerEnable = 0x34, 119910802Srene.dejong@arm.com regUICErrorCodePHYAdapterLayer = 0x38, 120010802Srene.dejong@arm.com regUICErrorCodeDataLinkLayer = 0x3C, 120110802Srene.dejong@arm.com regUICErrorCodeNetworkLayer = 0x40, 120210802Srene.dejong@arm.com regUICErrorCodeTransportLayer = 0x44, 120310802Srene.dejong@arm.com regUICErrorCodeDME = 0x48, 120410802Srene.dejong@arm.com regUTPTransferREQINTAGGControl = 0x4C, 120510802Srene.dejong@arm.com regUTPTransferREQListBaseL = 0x50, 120610802Srene.dejong@arm.com regUTPTransferREQListBaseH = 0x54, 120710802Srene.dejong@arm.com regUTPTransferREQDoorbell = 0x58, 120810802Srene.dejong@arm.com regUTPTransferREQListClear = 0x5C, 120910802Srene.dejong@arm.com regUTPTransferREQListRunStop = 0x60, 121010802Srene.dejong@arm.com regUTPTaskREQListBaseL = 0x70, 121110802Srene.dejong@arm.com regUTPTaskREQListBaseH = 0x74, 121210802Srene.dejong@arm.com regUTPTaskREQDoorbell = 0x78, 121310802Srene.dejong@arm.com regUTPTaskREQListClear = 0x7C, 121410802Srene.dejong@arm.com regUTPTaskREQListRunStop = 0x80, 121510802Srene.dejong@arm.com regUICCommand = 0x90, 121610802Srene.dejong@arm.com regUICCommandArg1 = 0x94, 121710802Srene.dejong@arm.com regUICCommandArg2 = 0x98, 121810802Srene.dejong@arm.com regUICCommandArg3 = 0x9C 121910802Srene.dejong@arm.com }; 122010802Srene.dejong@arm.com}; 122110802Srene.dejong@arm.com 122210802Srene.dejong@arm.com#endif //__DEV_ARM_UFS_DEVICE_HH__ 1223