ufs_device.hh revision 11264
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 { 37610802Srene.dejong@arm.com uint8_t status; 37710802Srene.dejong@arm.com uint32_t msgSize; 37810802Srene.dejong@arm.com uint8_t LUN; 37910802Srene.dejong@arm.com struct UPIUMessage message; 38010802Srene.dejong@arm.com uint8_t senseSize; 38110802Srene.dejong@arm.com uint8_t expectMore;//0x01 is for writes, 0x02 is for reads 38210802Srene.dejong@arm.com uint64_t offset; 38310802Srene.dejong@arm.com uint8_t senseCode[19]; 38410802Srene.dejong@arm.com }; 38510802Srene.dejong@arm.com 38610802Srene.dejong@arm.com /** 38710802Srene.dejong@arm.com * Logic unit information structure. SCSI requires information of each LUN. 38810802Srene.dejong@arm.com * This structure is defined in the SCSI standard, and can also be found in 38910802Srene.dejong@arm.com * the UFS standard. http://www.jedec.org/standards-documents/results/jesd220 39010802Srene.dejong@arm.com */ 39110802Srene.dejong@arm.com struct LUNInfo { 39210802Srene.dejong@arm.com uint32_t dWord0; 39310802Srene.dejong@arm.com uint32_t dWord1; 39410802Srene.dejong@arm.com uint32_t vendor0; 39510802Srene.dejong@arm.com uint32_t vendor1; 39610802Srene.dejong@arm.com uint32_t product0; 39710802Srene.dejong@arm.com uint32_t product1; 39810802Srene.dejong@arm.com uint32_t product2; 39910802Srene.dejong@arm.com uint32_t product3; 40010802Srene.dejong@arm.com uint32_t productRevision; 40110802Srene.dejong@arm.com }; 40210802Srene.dejong@arm.com 40310802Srene.dejong@arm.com /** 40410802Srene.dejong@arm.com * Different events, and scenarios require different types of information. 40510802Srene.dejong@arm.com * Keep in mind that for a read-from-disk transaction the host at first a 40610802Srene.dejong@arm.com * datastructure fetches to determine where and what the command is, then the 40710802Srene.dejong@arm.com * command fetches and the structure fetches to determine where the 40810802Srene.dejong@arm.com * different read transactions should be placed and then transfers all the 40910802Srene.dejong@arm.com * read fragments. It then answers to the original caller with two replies, 41010802Srene.dejong@arm.com * one for the command, and one for UFS. Each of these stages trigger a 41110802Srene.dejong@arm.com * different event, and each event needs to know what happened in the 41210802Srene.dejong@arm.com * previous stage and what is going to happen in the current one. This 41310802Srene.dejong@arm.com * happens also for writes, SCSI maintanance, UFS maintanance, command 41410802Srene.dejong@arm.com * management and task management. 41510802Srene.dejong@arm.com */ 41610802Srene.dejong@arm.com 41710802Srene.dejong@arm.com /** 41810802Srene.dejong@arm.com * Transfer information. 41910802Srene.dejong@arm.com * @filePointer this does not point to a file, but to a position on the disk 42010802Srene.dejong@arm.com * image (which is from the software systems perspective a position in a file) 42110802Srene.dejong@arm.com */ 42210802Srene.dejong@arm.com struct transferInfo { 42310802Srene.dejong@arm.com std::vector <uint8_t> buffer; 42410802Srene.dejong@arm.com uint32_t size; 42510802Srene.dejong@arm.com uint64_t offset; 42610802Srene.dejong@arm.com uint32_t filePointer; 42710802Srene.dejong@arm.com uint32_t lunID; 42810802Srene.dejong@arm.com }; 42910802Srene.dejong@arm.com 43010802Srene.dejong@arm.com /** 43110802Srene.dejong@arm.com * transfer completion info. 43210802Srene.dejong@arm.com * This information is needed by transferDone to finish the transfer. 43310802Srene.dejong@arm.com */ 43410802Srene.dejong@arm.com struct transferDoneInfo { 43510802Srene.dejong@arm.com Addr responseStartAddr; 43610802Srene.dejong@arm.com uint32_t reqPos; 43710802Srene.dejong@arm.com struct UTPUPIURSP requestOut; 43810802Srene.dejong@arm.com uint32_t size; 43910802Srene.dejong@arm.com Addr address; 44010802Srene.dejong@arm.com uint8_t *destination; 44110802Srene.dejong@arm.com bool finished; 44210802Srene.dejong@arm.com uint32_t lunID; 44310802Srene.dejong@arm.com }; 44410802Srene.dejong@arm.com 44510802Srene.dejong@arm.com /** 44610802Srene.dejong@arm.com * Transfer start information. 44710802Srene.dejong@arm.com */ 44810802Srene.dejong@arm.com struct transferStart { 44910802Srene.dejong@arm.com struct UTPTransferReqDesc* destination; 45010802Srene.dejong@arm.com uint32_t mask; 45110802Srene.dejong@arm.com Addr address; 45210802Srene.dejong@arm.com uint32_t size; 45310802Srene.dejong@arm.com uint32_t done; 45410802Srene.dejong@arm.com uint32_t lun_id; 45510802Srene.dejong@arm.com }; 45610802Srene.dejong@arm.com 45710802Srene.dejong@arm.com /** 45810802Srene.dejong@arm.com * Task start information. This is for the device, so no lun id needed. 45910802Srene.dejong@arm.com */ 46010802Srene.dejong@arm.com struct taskStart { 46110802Srene.dejong@arm.com struct UTPUPIUTaskReq destination; 46210802Srene.dejong@arm.com uint32_t mask; 46310802Srene.dejong@arm.com Addr address; 46410802Srene.dejong@arm.com uint32_t size; 46510802Srene.dejong@arm.com bool done; 46610802Srene.dejong@arm.com }; 46710802Srene.dejong@arm.com 46810802Srene.dejong@arm.com /** 46910802Srene.dejong@arm.com * After a SCSI command has been identified, the SCSI resume function will 47010802Srene.dejong@arm.com * handle it. This information will provide context information. 47110802Srene.dejong@arm.com */ 47210802Srene.dejong@arm.com struct SCSIResumeInfo { 47310802Srene.dejong@arm.com struct UTPTransferReqDesc* RequestIn; 47410802Srene.dejong@arm.com int reqPos; 47510802Srene.dejong@arm.com Addr finalAddress; 47610802Srene.dejong@arm.com uint32_t finalSize; 47710802Srene.dejong@arm.com std::vector <uint8_t> destination; 47810802Srene.dejong@arm.com uint32_t done; 47910802Srene.dejong@arm.com }; 48010802Srene.dejong@arm.com 48110802Srene.dejong@arm.com /** 48210802Srene.dejong@arm.com * Disk transfer burst information. Needed to allow communication between the 48310802Srene.dejong@arm.com * disk transactions and dma transactions. 48410802Srene.dejong@arm.com */ 48510802Srene.dejong@arm.com struct writeToDiskBurst { 48610802Srene.dejong@arm.com Addr start; 48710802Srene.dejong@arm.com uint64_t SCSIDiskOffset; 48810802Srene.dejong@arm.com uint32_t size; 48910802Srene.dejong@arm.com uint32_t LUN; 49010802Srene.dejong@arm.com }; 49110802Srene.dejong@arm.com 49210802Srene.dejong@arm.com /** 49310802Srene.dejong@arm.com * Statistics 49410802Srene.dejong@arm.com */ 49510802Srene.dejong@arm.com struct UFSHostDeviceStats { 49610802Srene.dejong@arm.com /** Queue lengths */ 49710802Srene.dejong@arm.com Stats::Scalar currentSCSIQueue; 49810802Srene.dejong@arm.com Stats::Scalar currentReadSSDQueue; 49910802Srene.dejong@arm.com Stats::Scalar currentWriteSSDQueue; 50010802Srene.dejong@arm.com 50110802Srene.dejong@arm.com /** Amount of data read/written */ 50210802Srene.dejong@arm.com Stats::Scalar totalReadSSD; 50310802Srene.dejong@arm.com Stats::Scalar totalWrittenSSD; 50410802Srene.dejong@arm.com Stats::Scalar totalReadDiskTransactions; 50510802Srene.dejong@arm.com Stats::Scalar totalWriteDiskTransactions; 50610802Srene.dejong@arm.com Stats::Scalar totalReadUFSTransactions; 50710802Srene.dejong@arm.com Stats::Scalar totalWriteUFSTransactions; 50810802Srene.dejong@arm.com 50910802Srene.dejong@arm.com /** Average bandwidth for reads and writes */ 51010802Srene.dejong@arm.com Stats::Formula averageReadSSDBW; 51110802Srene.dejong@arm.com Stats::Formula averageWriteSSDBW; 51210802Srene.dejong@arm.com 51310802Srene.dejong@arm.com /** Average Queue lengths*/ 51410802Srene.dejong@arm.com Stats::Average averageSCSIQueue; 51510802Srene.dejong@arm.com Stats::Average averageReadSSDQueue; 51610802Srene.dejong@arm.com Stats::Average averageWriteSSDQueue; 51710802Srene.dejong@arm.com 51810802Srene.dejong@arm.com /** Number of doorbells rung*/ 51910802Srene.dejong@arm.com Stats::Formula curDoorbell; 52010802Srene.dejong@arm.com Stats::Scalar maxDoorbell; 52110802Srene.dejong@arm.com Stats::Average averageDoorbell; 52210802Srene.dejong@arm.com 52310802Srene.dejong@arm.com /** Histogram of latencies*/ 52410802Srene.dejong@arm.com Stats::Histogram transactionLatency; 52510802Srene.dejong@arm.com Stats::Histogram idleTimes; 52610802Srene.dejong@arm.com }; 52710802Srene.dejong@arm.com 52810802Srene.dejong@arm.com /** 52910802Srene.dejong@arm.com * device layer: This is your Logic unit 53010802Srene.dejong@arm.com * This layer implements the SCSI functionality of the UFS Device 53110802Srene.dejong@arm.com * One logic unit controls one or more disk partitions 53210802Srene.dejong@arm.com */ 53310802Srene.dejong@arm.com class UFSSCSIDevice: SimObject 53410802Srene.dejong@arm.com { 53510802Srene.dejong@arm.com public: 53610802Srene.dejong@arm.com /** 53710802Srene.dejong@arm.com * Constructor and destructor 53810802Srene.dejong@arm.com */ 53910802Srene.dejong@arm.com UFSSCSIDevice(const UFSHostDeviceParams* p, uint32_t lun_id, Callback* 54010802Srene.dejong@arm.com transfer_cb, Callback *read_cb); 54110802Srene.dejong@arm.com ~UFSSCSIDevice(); 54210802Srene.dejong@arm.com 54310802Srene.dejong@arm.com /** 54410802Srene.dejong@arm.com * SCSI command handle function; determines what the command is and 54510802Srene.dejong@arm.com * returns a reply structure that allows the host device to continue 54610802Srene.dejong@arm.com * with the transfer. 54710802Srene.dejong@arm.com */ 54810802Srene.dejong@arm.com struct SCSIReply SCSICMDHandle(uint32_t* SCSI_msg); 54910802Srene.dejong@arm.com 55010802Srene.dejong@arm.com /** 55110802Srene.dejong@arm.com * Disk access functions. These will transfer the data from/to the disk 55210802Srene.dejong@arm.com */ 55310802Srene.dejong@arm.com 55410802Srene.dejong@arm.com /** 55510802Srene.dejong@arm.com * Read flash. read the data from the disk image. This function 55610802Srene.dejong@arm.com * doesn't model timing behaviour 55710802Srene.dejong@arm.com */ 55810802Srene.dejong@arm.com void readFlash(uint8_t* readaddr, uint64_t offset, uint32_t size); 55910802Srene.dejong@arm.com 56010802Srene.dejong@arm.com /** 56110802Srene.dejong@arm.com * Write flash. write the data to the disk image. This function 56210802Srene.dejong@arm.com * doesn't model timing behaviour 56310802Srene.dejong@arm.com */ 56410802Srene.dejong@arm.com void writeFlash(uint8_t* writeaddr, uint64_t offset, uint32_t size); 56510802Srene.dejong@arm.com 56610802Srene.dejong@arm.com /** 56710802Srene.dejong@arm.com * finished command. Probe to find out wether this logic unit 56810802Srene.dejong@arm.com * finished its transfer and triggered the callback; The host needs 56910802Srene.dejong@arm.com * this to handle the final part of the transaction. 57010802Srene.dejong@arm.com */ 57110802Srene.dejong@arm.com bool finishedCommand() const {return transferCompleted;}; 57210802Srene.dejong@arm.com 57310802Srene.dejong@arm.com /** 57410802Srene.dejong@arm.com * Clear signal. Handle for the host to clear the transfer complete 57510802Srene.dejong@arm.com * signal. 57610802Srene.dejong@arm.com */ 57710802Srene.dejong@arm.com void clearSignal() {transferCompleted = false;}; 57810802Srene.dejong@arm.com 57910802Srene.dejong@arm.com /** 58010802Srene.dejong@arm.com * Finished read. Probe to find out which logic unit finished its 58110802Srene.dejong@arm.com * read. This is needed, because multiple units can do transactions 58210802Srene.dejong@arm.com * at the same time, and need to push back data at the right time in 58310802Srene.dejong@arm.com * the right order. (because writes work the other way round, they do 58410802Srene.dejong@arm.com * not need this mechanism) 58510802Srene.dejong@arm.com */ 58610802Srene.dejong@arm.com bool finishedRead() const {return readCompleted;}; 58710802Srene.dejong@arm.com 58810802Srene.dejong@arm.com /** 58910802Srene.dejong@arm.com * Clear signal. Handle for the host to clear the read complete 59010802Srene.dejong@arm.com * signal. 59110802Srene.dejong@arm.com */ 59210802Srene.dejong@arm.com void clearReadSignal() {readCompleted = false;}; 59310802Srene.dejong@arm.com 59410802Srene.dejong@arm.com /** 59510802Srene.dejong@arm.com * Start the transactions to (and from) the disk 59610802Srene.dejong@arm.com * The host will queue all the transactions. Once the next phase 59710802Srene.dejong@arm.com * commences, this function should be started. 59810802Srene.dejong@arm.com */ 59910802Srene.dejong@arm.com void SSDReadStart(uint32_t total_read); 60010802Srene.dejong@arm.com void SSDWriteStart(); 60110802Srene.dejong@arm.com 60210802Srene.dejong@arm.com /** 60310802Srene.dejong@arm.com * Sets total amount of write transactions that needs to be made. 60410802Srene.dejong@arm.com * First they need to be fetched via DMA, so this value is needed in 60510802Srene.dejong@arm.com * a later stage. 60610802Srene.dejong@arm.com */ 60710802Srene.dejong@arm.com void setTotalWrite(uint32_t total_write) {totalWrite = total_write;}; 60810802Srene.dejong@arm.com 60910802Srene.dejong@arm.com /** 61010802Srene.dejong@arm.com * End of transfer information 61110802Srene.dejong@arm.com */ 61210802Srene.dejong@arm.com transferDoneInfo transferInfo; 61310802Srene.dejong@arm.com 61410802Srene.dejong@arm.com /** 61510802Srene.dejong@arm.com * Information message queues, as there can be multiple messages 61610802Srene.dejong@arm.com * queued for handling in this system. These are the main 61710802Srene.dejong@arm.com * communication interfaces between the Host and the device layers 61810802Srene.dejong@arm.com */ 61910802Srene.dejong@arm.com 62010802Srene.dejong@arm.com /** 62110802Srene.dejong@arm.com * SCSIInfoQueue: each LU handles its own SCSI commands. 62210802Srene.dejong@arm.com */ 62310802Srene.dejong@arm.com std::deque<struct SCSIResumeInfo> SCSIInfoQueue; 62410802Srene.dejong@arm.com 62510802Srene.dejong@arm.com /** 62610802Srene.dejong@arm.com * SSDReadInfo: Structure from disk to dma, that contains data, and 62710802Srene.dejong@arm.com * helper info to get it to the right place in the memory. 62810802Srene.dejong@arm.com */ 62910802Srene.dejong@arm.com std::deque<struct transferInfo> SSDReadInfo; 63010802Srene.dejong@arm.com 63110802Srene.dejong@arm.com /** 63210802Srene.dejong@arm.com * SSDWriteDoneInfo: Structure from dma to disk, that contains data, 63310802Srene.dejong@arm.com * and helper info to get it to the right place in the memory. 63410802Srene.dejong@arm.com * The done is added because it is going to the last phase of the 63510802Srene.dejong@arm.com * write transfer. 63610802Srene.dejong@arm.com */ 63710802Srene.dejong@arm.com std::deque<struct transferInfo> SSDWriteDoneInfo; 63810802Srene.dejong@arm.com 63910802Srene.dejong@arm.com private: 64010802Srene.dejong@arm.com /** 64110802Srene.dejong@arm.com * Functions to indicate that the action to the SSD has completed. 64210802Srene.dejong@arm.com */ 64310802Srene.dejong@arm.com /** 64410802Srene.dejong@arm.com * Read Call back; This is the callback function for the memory model 64510802Srene.dejong@arm.com */ 64610802Srene.dejong@arm.com void readCallback(); 64710802Srene.dejong@arm.com 64810802Srene.dejong@arm.com /** 64910802Srene.dejong@arm.com * SSD Read done; Determines if the final callback of the transaction 65010802Srene.dejong@arm.com * should be made at the end of a read transfer. 65110802Srene.dejong@arm.com */ 65210802Srene.dejong@arm.com void SSDReadDone(); 65310802Srene.dejong@arm.com 65410802Srene.dejong@arm.com /** 65510802Srene.dejong@arm.com * SSD Write Done; This is the callback function for the memory model. 65610802Srene.dejong@arm.com */ 65710802Srene.dejong@arm.com void SSDWriteDone(); 65810802Srene.dejong@arm.com 65910802Srene.dejong@arm.com /** 66010802Srene.dejong@arm.com * Status of SCSI. This may be linked to a status check in the future. 66110802Srene.dejong@arm.com * For now it (mainly) fills a data structure with sense information 66210802Srene.dejong@arm.com * for a successfull transaction 66310802Srene.dejong@arm.com */ 66410802Srene.dejong@arm.com void statusCheck(uint8_t status, uint8_t* sensecodelist); 66510802Srene.dejong@arm.com 66610802Srene.dejong@arm.com /** 66710802Srene.dejong@arm.com * set signal to indicate that the transaction has been completed. 66810802Srene.dejong@arm.com */ 66910802Srene.dejong@arm.com void setSignal() {transferCompleted = true;}; 67010802Srene.dejong@arm.com 67110802Srene.dejong@arm.com /** 67210802Srene.dejong@arm.com * set signal to indicate that the read action has been completed 67310802Srene.dejong@arm.com */ 67410802Srene.dejong@arm.com void setReadSignal() {readCompleted = true;}; 67510802Srene.dejong@arm.com 67610802Srene.dejong@arm.com /** 67710802Srene.dejong@arm.com * The objects this model links to. 67810802Srene.dejong@arm.com * 1: the disk data model 67910802Srene.dejong@arm.com * 2: the memory timing model 68010802Srene.dejong@arm.com */ 68110802Srene.dejong@arm.com DiskImage* flashDisk; 68210802Srene.dejong@arm.com AbstractNVM* flashDevice; 68310802Srene.dejong@arm.com 68410802Srene.dejong@arm.com /** 68510802Srene.dejong@arm.com * Logic unit dimensions 68610802Srene.dejong@arm.com */ 68710802Srene.dejong@arm.com const uint32_t blkSize; 68810802Srene.dejong@arm.com const uint32_t lunAvail; 68910802Srene.dejong@arm.com const uint64_t diskSize; 69010802Srene.dejong@arm.com const uint32_t capacityLower; 69110802Srene.dejong@arm.com const uint32_t capacityUpper; 69210802Srene.dejong@arm.com 69310802Srene.dejong@arm.com /** 69410802Srene.dejong@arm.com * Logic unit info; needed for SCSI Info messages and LU 69510802Srene.dejong@arm.com * identification 69610802Srene.dejong@arm.com */ 69710802Srene.dejong@arm.com struct LUNInfo lunInfo; 69810802Srene.dejong@arm.com const uint32_t lunID; 69910802Srene.dejong@arm.com 70010802Srene.dejong@arm.com /** 70110802Srene.dejong@arm.com * Signals to Host layer 70210802Srene.dejong@arm.com * 1: signal for transaction completion 70310802Srene.dejong@arm.com * 2: signal for read action completion 70410802Srene.dejong@arm.com */ 70510802Srene.dejong@arm.com bool transferCompleted; 70610802Srene.dejong@arm.com bool readCompleted; 70710802Srene.dejong@arm.com 70810802Srene.dejong@arm.com /** 70910802Srene.dejong@arm.com * Total amount transactions that need to be made 71010802Srene.dejong@arm.com */ 71110802Srene.dejong@arm.com uint32_t totalRead; 71210802Srene.dejong@arm.com uint32_t totalWrite; 71310802Srene.dejong@arm.com 71410802Srene.dejong@arm.com /** 71510802Srene.dejong@arm.com * transaction progress tracking 71610802Srene.dejong@arm.com */ 71710802Srene.dejong@arm.com uint32_t amountOfWriteTransfers; 71810802Srene.dejong@arm.com uint32_t amountOfReadTransfers; 71910802Srene.dejong@arm.com 72010802Srene.dejong@arm.com /** 72110802Srene.dejong@arm.com * Callbacks between Host and Device 72210802Srene.dejong@arm.com */ 72310802Srene.dejong@arm.com Callback* signalDone; 72410802Srene.dejong@arm.com Callback* deviceReadCallback; 72510802Srene.dejong@arm.com 72610802Srene.dejong@arm.com /** 72710802Srene.dejong@arm.com * Callbacks between Device and Memory 72810802Srene.dejong@arm.com */ 72910802Srene.dejong@arm.com Callback* memReadCallback; 73010802Srene.dejong@arm.com Callback* memWriteCallback; 73110802Srene.dejong@arm.com 73210802Srene.dejong@arm.com /* 73310802Srene.dejong@arm.com * Default response header layout. For more information refer to 73410802Srene.dejong@arm.com * chapter 7 http://www.jedec.org/standards-documents/results/jesd220 73510802Srene.dejong@arm.com */ 73610802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord0 = 0x0000C022; 73710802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord1 = 0x00000000; 73810802Srene.dejong@arm.com static const unsigned int UPIUHeaderDataIndWord2 = 0x40000000; 73910802Srene.dejong@arm.com 74010802Srene.dejong@arm.com /* 74110802Srene.dejong@arm.com * SCSI mode pages values assigned in ufs_device.cc 74210802Srene.dejong@arm.com * The mode pages give device specific information via the SCSI 74310802Srene.dejong@arm.com * protocol. They are defined in 74410802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 74510802Srene.dejong@arm.com */ 74610802Srene.dejong@arm.com static const unsigned int controlPage[3]; 74710802Srene.dejong@arm.com static const unsigned int recoveryPage[3]; 74810802Srene.dejong@arm.com static const unsigned int cachingPage[5]; 74910802Srene.dejong@arm.com 75010802Srene.dejong@arm.com /* 75110802Srene.dejong@arm.com * SCSI command set; defined in 75210802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 75310802Srene.dejong@arm.com */ 75410802Srene.dejong@arm.com enum SCSICommandSet { 75510802Srene.dejong@arm.com SCSIInquiry = 0x12, 75610802Srene.dejong@arm.com SCSIRead6 = 0x08, 75710802Srene.dejong@arm.com SCSIRead10 = 0x28, 75810802Srene.dejong@arm.com SCSIRead16 = 0x88, 75910802Srene.dejong@arm.com SCSIReadCapacity10 = 0x25, 76010802Srene.dejong@arm.com SCSIReadCapacity16 = 0x9E, 76110802Srene.dejong@arm.com SCSIReportLUNs = 0xA0, 76210802Srene.dejong@arm.com SCSIStartStop = 0x1B, 76310802Srene.dejong@arm.com SCSITestUnitReady = 0x00, 76410802Srene.dejong@arm.com SCSIVerify10 = 0x2F, 76510802Srene.dejong@arm.com SCSIWrite6 = 0x0A, 76610802Srene.dejong@arm.com SCSIWrite10 = 0x2A, 76710802Srene.dejong@arm.com SCSIWrite16 = 0x8A, 76810802Srene.dejong@arm.com SCSIFormatUnit = 0x04, 76910802Srene.dejong@arm.com SCSISendDiagnostic = 0x1D, 77010802Srene.dejong@arm.com SCSISynchronizeCache = 0x35, 77110802Srene.dejong@arm.com //UFS SCSI additional command set for full functionality 77210802Srene.dejong@arm.com SCSIModeSelect10 = 0x55, 77310802Srene.dejong@arm.com SCSIModeSense6 = 0x1A, 77410802Srene.dejong@arm.com SCSIModeSense10 = 0x5A, 77510802Srene.dejong@arm.com SCSIRequestSense = 0x03, 77610802Srene.dejong@arm.com SCSIUnmap = 0x42, 77710802Srene.dejong@arm.com SCSIWriteBuffer = 0x3B, 77810802Srene.dejong@arm.com SCSIReadBuffer = 0x3C, 77910802Srene.dejong@arm.com //SCSI commands not supported by UFS; but Linux send them anyway 78010802Srene.dejong@arm.com SCSIMaintenanceIn = 0xA3 78110802Srene.dejong@arm.com }; 78210802Srene.dejong@arm.com 78310802Srene.dejong@arm.com /* 78410802Srene.dejong@arm.com * SCSI status codes; defined in 78510802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 78610802Srene.dejong@arm.com */ 78710802Srene.dejong@arm.com enum SCSIStatusCodes { 78810802Srene.dejong@arm.com SCSIGood = 0x00, 78910802Srene.dejong@arm.com SCSICheckCondition = 0x02, 79010802Srene.dejong@arm.com SCSIConditionGood = 0x04, 79110802Srene.dejong@arm.com SCSIBusy = 0x08, 79210802Srene.dejong@arm.com SCSIIntermediateGood = 0x10, 79310802Srene.dejong@arm.com SCSIIntermediatCGood = 0x14, 79410802Srene.dejong@arm.com SCSIReservationConflict = 0x18, 79510802Srene.dejong@arm.com SCSICommandTerminated = 0x22, 79610802Srene.dejong@arm.com SCSITaskSetFull = 0x28, 79710802Srene.dejong@arm.com SCSIACAActive = 0x30, 79810802Srene.dejong@arm.com SCSITaskAborted = 0x40 79910802Srene.dejong@arm.com }; 80010802Srene.dejong@arm.com 80110802Srene.dejong@arm.com /* 80210802Srene.dejong@arm.com * SCSI sense codes; defined in 80310802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd220 80410802Srene.dejong@arm.com */ 80510802Srene.dejong@arm.com enum SCSISenseCodes { 80610802Srene.dejong@arm.com SCSINoSense = 0x00, 80710802Srene.dejong@arm.com SCSIRecoverdError = 0x01, 80810802Srene.dejong@arm.com SCSINotReady = 0x02, 80910802Srene.dejong@arm.com SCSIMediumError = 0x03, 81010802Srene.dejong@arm.com SCSIHardwareError = 0x04, 81110802Srene.dejong@arm.com SCSIIllegalRequest = 0x05, 81210802Srene.dejong@arm.com SCSIUnitAttention = 0x06, 81310802Srene.dejong@arm.com SCSIDataProtect = 0x07, 81410802Srene.dejong@arm.com SCSIBlankCheck = 0x08, 81510802Srene.dejong@arm.com SCSIAbortedCommand = 0x0B, 81610802Srene.dejong@arm.com SCSIVolumeOverflow = 0x0D, 81710802Srene.dejong@arm.com SCSIMisCompare = 0x0E 81810802Srene.dejong@arm.com }; 81910802Srene.dejong@arm.com 82010802Srene.dejong@arm.com }; 82110802Srene.dejong@arm.com 82210802Srene.dejong@arm.com //All access functions are inherrited; no need to make them public 82310802Srene.dejong@arm.com /** 82410802Srene.dejong@arm.com * Address range functions 82510802Srene.dejong@arm.com */ 82611174Sandreas.hansson@arm.com AddrRangeList getAddrRanges() const override; 82710802Srene.dejong@arm.com 82810802Srene.dejong@arm.com /** 82910802Srene.dejong@arm.com * register access functions 83010802Srene.dejong@arm.com */ 83111174Sandreas.hansson@arm.com Tick read(PacketPtr pkt) override; 83211174Sandreas.hansson@arm.com Tick write(PacketPtr pkt) override; 83310802Srene.dejong@arm.com // end of access functions 83410802Srene.dejong@arm.com 83510802Srene.dejong@arm.com /** 83610802Srene.dejong@arm.com * Initialization function. Sets the sefault HCI register values 83710802Srene.dejong@arm.com */ 83810802Srene.dejong@arm.com void setValues(); 83910802Srene.dejong@arm.com 84010802Srene.dejong@arm.com /** 84110802Srene.dejong@arm.com * Handler functions. Each function handles a different stage of the 84210802Srene.dejong@arm.com * transfer. Note that the UFS protocol specifies three types of messages 84310802Srene.dejong@arm.com * to the host (and devices): 84410802Srene.dejong@arm.com * 1: Command (to Host specifically) 84510802Srene.dejong@arm.com * 2: Task (to device; to control flow, not for data) 84610802Srene.dejong@arm.com * 3: Transfer (to device; to transfer data) 84710802Srene.dejong@arm.com */ 84810802Srene.dejong@arm.com /** 84910802Srene.dejong@arm.com * request handler. This function finds the cause of the request and 85010802Srene.dejong@arm.com * triggers the right follow-up action (command handler, task handler, 85110802Srene.dejong@arm.com * or transferhandler) 85210802Srene.dejong@arm.com */ 85310802Srene.dejong@arm.com void requestHandler(); 85410802Srene.dejong@arm.com 85510802Srene.dejong@arm.com /** 85610802Srene.dejong@arm.com * Command handler function. Handles the command send to the Host 85710802Srene.dejong@arm.com * controller 85810802Srene.dejong@arm.com */ 85910802Srene.dejong@arm.com void commandHandler(); 86010802Srene.dejong@arm.com 86110802Srene.dejong@arm.com /** 86210802Srene.dejong@arm.com * Task Start function. Starts the task handler once the task data 86310802Srene.dejong@arm.com * structure has arrived 86410802Srene.dejong@arm.com */ 86510802Srene.dejong@arm.com void taskStart(); 86610802Srene.dejong@arm.com 86710802Srene.dejong@arm.com /** 86810802Srene.dejong@arm.com * Task handler function. Handles the tasks send to the devices 86910802Srene.dejong@arm.com * because there are not many tasks implemented yet this is kept in the 87010802Srene.dejong@arm.com * Host controller layer 87110802Srene.dejong@arm.com */ 87210802Srene.dejong@arm.com void taskHandler(struct UTPUPIUTaskReq* request_in, 87310802Srene.dejong@arm.com uint32_t req_pos, Addr finaladdress, uint32_t finalsize); 87410802Srene.dejong@arm.com 87510802Srene.dejong@arm.com /** 87610802Srene.dejong@arm.com * Transfer Start function. Starts the transfer handler once the transfer 87710802Srene.dejong@arm.com * data structure has arrived 87810802Srene.dejong@arm.com */ 87910802Srene.dejong@arm.com void transferStart(); 88010802Srene.dejong@arm.com 88110802Srene.dejong@arm.com /** 88210802Srene.dejong@arm.com * Transfer handler function. Handles the transfers send to the devices 88310802Srene.dejong@arm.com * Important to understand here is that a Logic unit is not a device (a 88410802Srene.dejong@arm.com * device can contain multiple logic units). This function analyses the 88510802Srene.dejong@arm.com * first data structure that has been transfered. Which will tell the 88610802Srene.dejong@arm.com * host to expect SCSI frames for the rest of the transaction. Note that 88710802Srene.dejong@arm.com * the host has no indication whatsoever which LU to address. That will 88810802Srene.dejong@arm.com * follow in the next transaction. 88910802Srene.dejong@arm.com */ 89010802Srene.dejong@arm.com void transferHandler(struct UTPTransferReqDesc* 89110802Srene.dejong@arm.com request_in, int req_pos, Addr finaladdress, 89210802Srene.dejong@arm.com uint32_t finalsize, uint32_t done); 89310802Srene.dejong@arm.com 89410802Srene.dejong@arm.com /** 89510802Srene.dejong@arm.com * Transfer SCSI function. Determines which Logic unit to address and 89610802Srene.dejong@arm.com * starts the SCSI resume function 89710802Srene.dejong@arm.com */ 89810802Srene.dejong@arm.com void SCSIStart(); 89910802Srene.dejong@arm.com 90010802Srene.dejong@arm.com /** 90110802Srene.dejong@arm.com * Starts the scsi handling function in the apropriate Logic unit, 90210802Srene.dejong@arm.com * prepares the right data transfer scheme and kicks it off. 90310802Srene.dejong@arm.com */ 90410802Srene.dejong@arm.com void SCSIResume(uint32_t lun_id); 90510802Srene.dejong@arm.com 90610802Srene.dejong@arm.com /** 90710802Srene.dejong@arm.com * LU callback function to indicate that the action has completed. 90810802Srene.dejong@arm.com */ 90910802Srene.dejong@arm.com void LUNSignal(); 91010802Srene.dejong@arm.com 91110802Srene.dejong@arm.com /** 91210802Srene.dejong@arm.com * transfer done, the beginning of the final stage of the transfer. 91310802Srene.dejong@arm.com * Acknowledges UPIU frame and prepares the UTP response frame 91410802Srene.dejong@arm.com */ 91510802Srene.dejong@arm.com void transferDone(Addr responseStartAddr, uint32_t req_pos, 91610802Srene.dejong@arm.com struct UTPUPIURSP request_out, uint32_t size, 91710802Srene.dejong@arm.com Addr address, uint8_t* destination, bool finished, 91810802Srene.dejong@arm.com uint32_t lun_id); 91910802Srene.dejong@arm.com /** 92010802Srene.dejong@arm.com * final UTP, sends the last acknowledge data structure to the system; 92110802Srene.dejong@arm.com * prepares the clean up functions. 92210802Srene.dejong@arm.com */ 92310802Srene.dejong@arm.com void finalUTP(); 92410802Srene.dejong@arm.com 92510802Srene.dejong@arm.com /** 92610802Srene.dejong@arm.com * Interrupt control functions 92710802Srene.dejong@arm.com */ 92810802Srene.dejong@arm.com void clearInterrupt(); 92910802Srene.dejong@arm.com void generateInterrupt(); 93010802Srene.dejong@arm.com 93110802Srene.dejong@arm.com /** 93210802Srene.dejong@arm.com * DMA transfer functions 93310802Srene.dejong@arm.com * These allow the host to push/pull the data to the memory 93410802Srene.dejong@arm.com * The provided event indicates what the next phase it that will handle 93510802Srene.dejong@arm.com * the obtained data, or what the follow up action is once the data has 93610802Srene.dejong@arm.com * been pushed to the memory 93710802Srene.dejong@arm.com */ 93810802Srene.dejong@arm.com void writeDevice(Event* additional_action, bool toDisk, Addr start, 93910802Srene.dejong@arm.com int size, uint8_t* destination, uint64_t SCSIDiskOffset, 94010802Srene.dejong@arm.com uint32_t lun_id); 94110802Srene.dejong@arm.com void readDevice(bool lastTransfer, Addr SCSIStart, uint32_t SCSISize, 94210802Srene.dejong@arm.com uint8_t* SCSIDestination, bool no_cache, 94310802Srene.dejong@arm.com Event* additional_action); 94410802Srene.dejong@arm.com 94510802Srene.dejong@arm.com /** 94610802Srene.dejong@arm.com * Disk transfer management functions 94710802Srene.dejong@arm.com * these set up the queues, and initiated them, leading to the data 94810802Srene.dejong@arm.com * transaction timing model based on the scatter gather list constructed 94910802Srene.dejong@arm.com * in SCSIresume. 95010802Srene.dejong@arm.com */ 95110802Srene.dejong@arm.com void manageWriteTransfer(uint8_t LUN, uint64_t offset, uint32_t 95210802Srene.dejong@arm.com sg_table_length, struct UFSHCDSGEntry* sglist); 95310802Srene.dejong@arm.com void manageReadTransfer(uint32_t size, uint32_t LUN, uint64_t offset, 95410802Srene.dejong@arm.com uint32_t sg_table_length, 95510802Srene.dejong@arm.com struct UFSHCDSGEntry* sglist); 95610802Srene.dejong@arm.com 95710802Srene.dejong@arm.com /** 95810802Srene.dejong@arm.com * Read done 95910802Srene.dejong@arm.com * Started at the end of a transaction after the last read action. Cleans 96010802Srene.dejong@arm.com * up UTP descriptor and other remaining data structures. It also raises 96110802Srene.dejong@arm.com * the interrupt. 96210802Srene.dejong@arm.com */ 96310802Srene.dejong@arm.com void readDone(); 96410802Srene.dejong@arm.com 96510802Srene.dejong@arm.com /** 96610802Srene.dejong@arm.com * Write done 96710802Srene.dejong@arm.com * After a DMA write with data intended for the disk, this function is 96810802Srene.dejong@arm.com * called. It ensures that the disk image is modified, and that the 96910802Srene.dejong@arm.com * correct timing function is triggered. 97010802Srene.dejong@arm.com */ 97110802Srene.dejong@arm.com void writeDone(); 97210802Srene.dejong@arm.com 97310802Srene.dejong@arm.com /** 97410802Srene.dejong@arm.com * Read callback 97510802Srene.dejong@arm.com * Call back function for the logic units to indicate the completion of 97610802Srene.dejong@arm.com * a read action. Note that this is needed because the read functionality 97710802Srene.dejong@arm.com * needs to push data structures back to the memory. 97810802Srene.dejong@arm.com */ 97910802Srene.dejong@arm.com void readCallback(); 98010802Srene.dejong@arm.com 98110802Srene.dejong@arm.com /** 98210802Srene.dejong@arm.com * Read garbage 98310802Srene.dejong@arm.com * A read from disk data structure can vary in size and is therefor 98410802Srene.dejong@arm.com * allocated on creation. It can only be destroyed once that particular 98510802Srene.dejong@arm.com * read action has completed. This function is called on completion of a 98610802Srene.dejong@arm.com * read from disk action to handle this. 98710802Srene.dejong@arm.com */ 98810802Srene.dejong@arm.com void readGarbage(); 98910802Srene.dejong@arm.com 99010802Srene.dejong@arm.com /**register statistics*/ 99111174Sandreas.hansson@arm.com void regStats() override; 99210802Srene.dejong@arm.com 99310802Srene.dejong@arm.com /** 99410802Srene.dejong@arm.com * Host controller information 99510802Srene.dejong@arm.com */ 99610802Srene.dejong@arm.com const Addr pioAddr; 99710802Srene.dejong@arm.com const Addr pioSize; 99810802Srene.dejong@arm.com const Tick pioDelay; 99910802Srene.dejong@arm.com const int intNum; 100010802Srene.dejong@arm.com BaseGic* gic; 100110802Srene.dejong@arm.com const uint32_t lunAvail; 100210802Srene.dejong@arm.com const uint8_t UFSSlots; 100310802Srene.dejong@arm.com 100410802Srene.dejong@arm.com /** 100510802Srene.dejong@arm.com * Host controller memory 100610802Srene.dejong@arm.com */ 100710802Srene.dejong@arm.com HCIMem UFSHCIMem; 100810802Srene.dejong@arm.com 100910802Srene.dejong@arm.com /** 101010802Srene.dejong@arm.com * Track number of DMA transactions in progress 101110802Srene.dejong@arm.com */ 101210802Srene.dejong@arm.com int readPendingNum; 101310802Srene.dejong@arm.com int writePendingNum; 101410802Srene.dejong@arm.com 101510802Srene.dejong@arm.com /** 101610802Srene.dejong@arm.com * Statistics helper variables 101710802Srene.dejong@arm.com * Active doorbells indicates how many doorbells are in teh process of 101810802Srene.dejong@arm.com * being handled. 101910802Srene.dejong@arm.com * Pending doorbells have been handled and are waiting to be acknowledged 102010802Srene.dejong@arm.com * by the host system. 102110802Srene.dejong@arm.com * The doorbell register is 32 bits wide, so one byte is enough to keep 102210802Srene.dejong@arm.com * track of the numbers 102310802Srene.dejong@arm.com */ 102410802Srene.dejong@arm.com uint8_t activeDoorbells; 102510802Srene.dejong@arm.com uint8_t pendingDoorbells; 102610802Srene.dejong@arm.com 102710802Srene.dejong@arm.com /** 102810802Srene.dejong@arm.com * interrupt verification 102910802Srene.dejong@arm.com * This keeps track of the number of interrupts generated. It is usefull 103010802Srene.dejong@arm.com * for debug purposes. Make sure that the implemented driver prints the 103110802Srene.dejong@arm.com * number of interrupts it has handled so far to fully benefit from this 103210802Srene.dejong@arm.com * feature. 103310802Srene.dejong@arm.com */ 103410802Srene.dejong@arm.com uint32_t countInt; 103510802Srene.dejong@arm.com 103610802Srene.dejong@arm.com /** 103710802Srene.dejong@arm.com * Track the transfer 103810802Srene.dejong@arm.com * This is allows the driver to "group" certain transfers together by 103910802Srene.dejong@arm.com * using a tag in the UPIU. The messages with the same tag should be 104010802Srene.dejong@arm.com * handled together, i.e. their doorbells should be cleared when they are 104110802Srene.dejong@arm.com * all done. but we need to keep track of the ones we already handled, 104210802Srene.dejong@arm.com * this integer shadows the doorbells to allow this behaviour. 104310802Srene.dejong@arm.com */ 104410802Srene.dejong@arm.com uint32_t transferTrack; 104510802Srene.dejong@arm.com uint32_t taskCommandTrack; 104610802Srene.dejong@arm.com 104710802Srene.dejong@arm.com /** 104810802Srene.dejong@arm.com * Helper for latency stats 104910802Srene.dejong@arm.com * These variables keep track of the latency for every doorbell. 105010802Srene.dejong@arm.com * Eventually the latenmcies will be put in a histogram. 105110802Srene.dejong@arm.com */ 105210802Srene.dejong@arm.com Tick transactionStart[32]; 105310802Srene.dejong@arm.com Tick idlePhaseStart; 105410802Srene.dejong@arm.com 105510802Srene.dejong@arm.com /** 105610802Srene.dejong@arm.com * logic units connected to the UFS Host device 105710802Srene.dejong@arm.com * Note again that the "device" as such is represented by one or multiple 105810802Srene.dejong@arm.com * logic units. 105910802Srene.dejong@arm.com */ 106010802Srene.dejong@arm.com std::vector<UFSSCSIDevice*> UFSDevice; 106110802Srene.dejong@arm.com 106210802Srene.dejong@arm.com /** 106310802Srene.dejong@arm.com * SCSI reply structure, used for direct answering. Might be refered to 106410802Srene.dejong@arm.com * during the assembly of the reply (data, and response; e.g. if 106510802Srene.dejong@arm.com * something goes wrong along the way, the reply will be different) 106610802Srene.dejong@arm.com */ 106710802Srene.dejong@arm.com struct SCSIReply request_out_datain; 106810802Srene.dejong@arm.com 106910802Srene.dejong@arm.com /** 107010802Srene.dejong@arm.com * SCSI resume info 107110802Srene.dejong@arm.com * information structure for SCSI resume. it keeps track of all the 107210802Srene.dejong@arm.com * information that is needed to successfully complete the transaction 107310802Srene.dejong@arm.com * (response addresses, communicated information so far, etc.). 107410802Srene.dejong@arm.com */ 107510802Srene.dejong@arm.com struct SCSIResumeInfo SCSIInfo; 107610802Srene.dejong@arm.com 107710802Srene.dejong@arm.com /** 107810802Srene.dejong@arm.com * To finish the transaction one needs information about the original 107910802Srene.dejong@arm.com * message. This is stored in this queue 108010802Srene.dejong@arm.com * transferEnd uses the same structure as transferStartInfo, because all 108110802Srene.dejong@arm.com * the information it needs is in there. It improves readability in the 108210802Srene.dejong@arm.com * cc file. 108310802Srene.dejong@arm.com */ 108410802Srene.dejong@arm.com std::deque<struct transferStart> transferEnd; 108510802Srene.dejong@arm.com 108610802Srene.dejong@arm.com /** 108710802Srene.dejong@arm.com * When a task/transfer is started it needs information about the 108810802Srene.dejong@arm.com * task/transfer it is about to perform. This is defined in these 108910802Srene.dejong@arm.com * structures. If multiple tasks/transfers are issued at the same time, 109010802Srene.dejong@arm.com * they still need to be fetched one by one. They then need to be 109110802Srene.dejong@arm.com * executed in the order specified by the UFS standard (least significant 109210802Srene.dejong@arm.com * doorbell first). The tasks/transfers are placed in the queue in that 109310802Srene.dejong@arm.com * specific order. 109410802Srene.dejong@arm.com */ 109510802Srene.dejong@arm.com std::deque<struct taskStart> taskInfo; 109610802Srene.dejong@arm.com std::deque<struct transferStart> transferStartInfo; 109710802Srene.dejong@arm.com 109810802Srene.dejong@arm.com /** 109910802Srene.dejong@arm.com * Information to get a DMA transaction 110010802Srene.dejong@arm.com */ 110110802Srene.dejong@arm.com std::deque<struct writeToDiskBurst> dmaWriteInfo; 110210802Srene.dejong@arm.com 110310802Srene.dejong@arm.com /** 110410802Srene.dejong@arm.com * Information from DMA transaction to disk 110510802Srene.dejong@arm.com */ 110610802Srene.dejong@arm.com std::deque<struct transferInfo> SSDWriteinfo; 110710802Srene.dejong@arm.com 110810802Srene.dejong@arm.com /** 110910802Srene.dejong@arm.com * Information from the Disk, waiting to be pushed to the DMA 111010802Srene.dejong@arm.com */ 111110802Srene.dejong@arm.com std::deque<struct transferInfo> SSDReadPending; 111210802Srene.dejong@arm.com 111310802Srene.dejong@arm.com /** 111410802Srene.dejong@arm.com * garbage queue, ensure clearing of the allocated memory 111510802Srene.dejong@arm.com */ 111610802Srene.dejong@arm.com std::deque<struct UTPTransferReqDesc*> garbage; 111710802Srene.dejong@arm.com 111810802Srene.dejong@arm.com /** 111910802Srene.dejong@arm.com * RequestHandler stats 112010802Srene.dejong@arm.com */ 112110802Srene.dejong@arm.com struct UFSHostDeviceStats stats; 112210802Srene.dejong@arm.com 112310802Srene.dejong@arm.com /** 112410802Srene.dejong@arm.com * Transfer flow events 112510802Srene.dejong@arm.com * Basically these events form two queues, one from memory to UFS device 112610802Srene.dejong@arm.com * (DMA) and one from device to flash (SSD). The SSD "queue" is 112710802Srene.dejong@arm.com * maintained by the flash and the lun classes and does not form a queue 112810802Srene.dejong@arm.com * of events as such, but rather a queue of information. This can be done 112910802Srene.dejong@arm.com * because the flow of the events is completely in the control of these 113010802Srene.dejong@arm.com * classes. (Whereas in the DMA case we rely on an external class) 113110802Srene.dejong@arm.com */ 113210802Srene.dejong@arm.com std::deque<EventWrapper<UFSHostDevice, &UFSHostDevice::readDone> > 113310802Srene.dejong@arm.com readDoneEvent; 113410802Srene.dejong@arm.com std::deque<EventWrapper<UFSHostDevice, &UFSHostDevice::writeDone> > 113510802Srene.dejong@arm.com writeDoneEvent; 113610802Srene.dejong@arm.com 113710802Srene.dejong@arm.com /** 113810802Srene.dejong@arm.com * Callbacks for the logic units. One to indicate the completion of a 113910802Srene.dejong@arm.com * transaction, the other one to indicate the completion of a read 114010802Srene.dejong@arm.com * action. 114110802Srene.dejong@arm.com */ 114210802Srene.dejong@arm.com Callback* transferDoneCallback; 114310802Srene.dejong@arm.com Callback* memReadCallback; 114410802Srene.dejong@arm.com 114510802Srene.dejong@arm.com /** 114610802Srene.dejong@arm.com * The events that control the functionality. 114710802Srene.dejong@arm.com * After a doorbell has been set, either a taskevent or a transfer event 114810802Srene.dejong@arm.com * is scheduled. A transfer event might schedule a SCSI event, all events 114910802Srene.dejong@arm.com * sequences end with an UTP event, which can be considered as the event 115010802Srene.dejong@arm.com * which answers the doorbell. 115110802Srene.dejong@arm.com */ 115210802Srene.dejong@arm.com /** 115310802Srene.dejong@arm.com * Wait for the SCSI specific data to arive 115410802Srene.dejong@arm.com */ 115510802Srene.dejong@arm.com EventWrapper<UFSHostDevice, &UFSHostDevice::SCSIStart> SCSIResumeEvent; 115610802Srene.dejong@arm.com 115710802Srene.dejong@arm.com /** 115810802Srene.dejong@arm.com * Wait for the moment where we can send the last frame 115910802Srene.dejong@arm.com */ 116010802Srene.dejong@arm.com EventWrapper<UFSHostDevice, &UFSHostDevice::finalUTP> UTPEvent; 116110802Srene.dejong@arm.com 116210802Srene.dejong@arm.com /** 116310802Srene.dejong@arm.com * Event after a read to clean up the UTP data structures 116410802Srene.dejong@arm.com */ 116510802Srene.dejong@arm.com std::deque<EventWrapper<UFSHostDevice, &UFSHostDevice::readGarbage> > 116610802Srene.dejong@arm.com readGarbageEventQueue; 116710802Srene.dejong@arm.com 116810802Srene.dejong@arm.com /** 116910802Srene.dejong@arm.com * Multiple tasks transfers can be scheduled at once for the device, the 117010802Srene.dejong@arm.com * only thing we know for sure about them is that they will happen in a 117110802Srene.dejong@arm.com * first come first serve order; hence we need to queue. 117210802Srene.dejong@arm.com */ 117310802Srene.dejong@arm.com std::deque<EventWrapper<UFSHostDevice, &UFSHostDevice::taskStart> > 117410802Srene.dejong@arm.com taskEventQueue; 117510802Srene.dejong@arm.com std::deque<EventWrapper<UFSHostDevice, &UFSHostDevice::transferStart> > 117610802Srene.dejong@arm.com transferEventQueue; 117710802Srene.dejong@arm.com 117810802Srene.dejong@arm.com /** 117910802Srene.dejong@arm.com * Bits of interest within UFS data packages 118010802Srene.dejong@arm.com */ 118110802Srene.dejong@arm.com static const unsigned int UTPTransferREQCOMPL = 0x01;//UFS_BIT(0) 118210802Srene.dejong@arm.com static const unsigned int UTPTaskREQCOMPL = 0x200;//UFS_BIT(9) 118310802Srene.dejong@arm.com static const unsigned int UICCommandCOMPL = 0x400;//UFS_BIT(10) 118410802Srene.dejong@arm.com static const unsigned int UICCommandReady = 0x08;//UFS_BIT(3) 118510802Srene.dejong@arm.com 118610802Srene.dejong@arm.com /* 118710802Srene.dejong@arm.com * UFSHCI Registers; please refer to 118810802Srene.dejong@arm.com * http://www.jedec.org/standards-documents/results/jesd223 118910802Srene.dejong@arm.com * for their definition. 119010802Srene.dejong@arm.com */ 119110802Srene.dejong@arm.com enum UFSHCIRegisters { 119210802Srene.dejong@arm.com regControllerCapabilities = 0x00, 119310802Srene.dejong@arm.com regUFSVersion = 0x08, 119410802Srene.dejong@arm.com regControllerDEVID = 0x10, 119510802Srene.dejong@arm.com regControllerPRODID = 0x14, 119610802Srene.dejong@arm.com regInterruptStatus = 0x20, 119710802Srene.dejong@arm.com regInterruptEnable = 0x24, 119810802Srene.dejong@arm.com regControllerStatus = 0x30, 119910802Srene.dejong@arm.com regControllerEnable = 0x34, 120010802Srene.dejong@arm.com regUICErrorCodePHYAdapterLayer = 0x38, 120110802Srene.dejong@arm.com regUICErrorCodeDataLinkLayer = 0x3C, 120210802Srene.dejong@arm.com regUICErrorCodeNetworkLayer = 0x40, 120310802Srene.dejong@arm.com regUICErrorCodeTransportLayer = 0x44, 120410802Srene.dejong@arm.com regUICErrorCodeDME = 0x48, 120510802Srene.dejong@arm.com regUTPTransferREQINTAGGControl = 0x4C, 120610802Srene.dejong@arm.com regUTPTransferREQListBaseL = 0x50, 120710802Srene.dejong@arm.com regUTPTransferREQListBaseH = 0x54, 120810802Srene.dejong@arm.com regUTPTransferREQDoorbell = 0x58, 120910802Srene.dejong@arm.com regUTPTransferREQListClear = 0x5C, 121010802Srene.dejong@arm.com regUTPTransferREQListRunStop = 0x60, 121110802Srene.dejong@arm.com regUTPTaskREQListBaseL = 0x70, 121210802Srene.dejong@arm.com regUTPTaskREQListBaseH = 0x74, 121310802Srene.dejong@arm.com regUTPTaskREQDoorbell = 0x78, 121410802Srene.dejong@arm.com regUTPTaskREQListClear = 0x7C, 121510802Srene.dejong@arm.com regUTPTaskREQListRunStop = 0x80, 121610802Srene.dejong@arm.com regUICCommand = 0x90, 121710802Srene.dejong@arm.com regUICCommandArg1 = 0x94, 121810802Srene.dejong@arm.com regUICCommandArg2 = 0x98, 121910802Srene.dejong@arm.com regUICCommandArg3 = 0x9C 122010802Srene.dejong@arm.com }; 122110802Srene.dejong@arm.com}; 122210802Srene.dejong@arm.com 122310802Srene.dejong@arm.com#endif //__DEV_ARM_UFS_DEVICE_HH__ 1224