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