110390SAndreas.Sandberg@ARM.com/*
210390SAndreas.Sandberg@ARM.com * Copyright (c) 2014 ARM Limited
310390SAndreas.Sandberg@ARM.com * All rights reserved
410390SAndreas.Sandberg@ARM.com *
510390SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall
610390SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual
710390SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating
810390SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software
910390SAndreas.Sandberg@ARM.com * licensed hereunder.  You may use the software subject to the license
1010390SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated
1110390SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software,
1210390SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form.
1310390SAndreas.Sandberg@ARM.com *
1410390SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
1510390SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
1610390SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
1710390SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
1810390SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
1910390SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
2010390SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
2110390SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
2210390SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
2310390SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
2410390SAndreas.Sandberg@ARM.com *
2510390SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610390SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710390SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810390SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910390SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010390SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110390SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210390SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310390SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410390SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510390SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610390SAndreas.Sandberg@ARM.com *
3710390SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg
3810390SAndreas.Sandberg@ARM.com */
3910390SAndreas.Sandberg@ARM.com
4010390SAndreas.Sandberg@ARM.com#ifndef __DEV_VIRTIO_BLOCK_HH__
4110390SAndreas.Sandberg@ARM.com#define __DEV_VIRTIO_BLOCK_HH__
4210390SAndreas.Sandberg@ARM.com
4310390SAndreas.Sandberg@ARM.com#include "dev/virtio/base.hh"
4411264Sandreas.sandberg@arm.com#include "dev/storage/disk_image.hh"
4510390SAndreas.Sandberg@ARM.com
4610390SAndreas.Sandberg@ARM.comstruct VirtIOBlockParams;
4710390SAndreas.Sandberg@ARM.com
4810390SAndreas.Sandberg@ARM.com/**
4910390SAndreas.Sandberg@ARM.com * VirtIO block device
5010390SAndreas.Sandberg@ARM.com *
5110390SAndreas.Sandberg@ARM.com * The block device uses the following queues:
5210390SAndreas.Sandberg@ARM.com *  -# Requests
5310390SAndreas.Sandberg@ARM.com *
5410390SAndreas.Sandberg@ARM.com * A guest issues a request by creating a descriptor chain that starts
5510390SAndreas.Sandberg@ARM.com * with a BlkRequest. Immediately after the BlkRequest follows the
5610390SAndreas.Sandberg@ARM.com * data for the request. The data buffer(s) are either input or output
5710390SAndreas.Sandberg@ARM.com * descriptors depending on the request type. The last byte in the
5810390SAndreas.Sandberg@ARM.com * descriptor chain should always be writable by the host and contains
5910390SAndreas.Sandberg@ARM.com * the request status code (OK/Error).
6010390SAndreas.Sandberg@ARM.com *
6110390SAndreas.Sandberg@ARM.com * The protocol supports asynchronous request completion by returning
6210390SAndreas.Sandberg@ARM.com * descriptor chains when they have been populated by the backing
6310390SAndreas.Sandberg@ARM.com * store. However, there is little point in doing so here.
6410390SAndreas.Sandberg@ARM.com *
6510390SAndreas.Sandberg@ARM.com * @see https://github.com/rustyrussell/virtio-spec
6610390SAndreas.Sandberg@ARM.com * @see http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html
6710390SAndreas.Sandberg@ARM.com */
6810390SAndreas.Sandberg@ARM.comclass VirtIOBlock : public VirtIODeviceBase
6910390SAndreas.Sandberg@ARM.com{
7010390SAndreas.Sandberg@ARM.com  public:
7110390SAndreas.Sandberg@ARM.com    typedef VirtIOBlockParams Params;
7210390SAndreas.Sandberg@ARM.com    VirtIOBlock(Params *params);
7310390SAndreas.Sandberg@ARM.com    virtual ~VirtIOBlock();
7410390SAndreas.Sandberg@ARM.com
7510390SAndreas.Sandberg@ARM.com    void readConfig(PacketPtr pkt, Addr cfgOffset);
7610390SAndreas.Sandberg@ARM.com
7710390SAndreas.Sandberg@ARM.com  protected:
7810390SAndreas.Sandberg@ARM.com    static const DeviceId ID_BLOCK = 0x02;
7910390SAndreas.Sandberg@ARM.com
8010390SAndreas.Sandberg@ARM.com    /**
8110390SAndreas.Sandberg@ARM.com     * Block device configuration structure
8210390SAndreas.Sandberg@ARM.com     *
8310390SAndreas.Sandberg@ARM.com     * @note This needs to be changed if the supported feature set
8410390SAndreas.Sandberg@ARM.com     * changes!
8510390SAndreas.Sandberg@ARM.com     */
8610390SAndreas.Sandberg@ARM.com    struct Config {
8710390SAndreas.Sandberg@ARM.com        uint64_t capacity;
8810390SAndreas.Sandberg@ARM.com    } M5_ATTR_PACKED;
8910390SAndreas.Sandberg@ARM.com    Config config;
9010390SAndreas.Sandberg@ARM.com
9110390SAndreas.Sandberg@ARM.com    /** @{
9210390SAndreas.Sandberg@ARM.com     * @name Feature bits
9310390SAndreas.Sandberg@ARM.com     */
9410390SAndreas.Sandberg@ARM.com    static const FeatureBits F_SIZE_MAX = (1 << 1);
9510390SAndreas.Sandberg@ARM.com    static const FeatureBits F_SEG_MAX = (1 << 2);
9610390SAndreas.Sandberg@ARM.com    static const FeatureBits F_GEOMETRY = (1 << 4);
9710390SAndreas.Sandberg@ARM.com    static const FeatureBits F_RO = (1 << 5);
9810390SAndreas.Sandberg@ARM.com    static const FeatureBits F_BLK_SIZE = (1 << 6);
9910390SAndreas.Sandberg@ARM.com    static const FeatureBits F_TOPOLOGY = (1 << 10);
10010390SAndreas.Sandberg@ARM.com    /** @} */
10110390SAndreas.Sandberg@ARM.com
10210390SAndreas.Sandberg@ARM.com    /** @{
10310390SAndreas.Sandberg@ARM.com     * @name VirtIO block requests
10410390SAndreas.Sandberg@ARM.com     */
10510390SAndreas.Sandberg@ARM.com    typedef uint32_t RequestType;
10610390SAndreas.Sandberg@ARM.com    /** Read request */
10710390SAndreas.Sandberg@ARM.com    static const RequestType T_IN = 0;
10810390SAndreas.Sandberg@ARM.com    /** Write request */
10910390SAndreas.Sandberg@ARM.com    static const RequestType T_OUT = 1;
11010390SAndreas.Sandberg@ARM.com    /** Flush device buffers */
11110390SAndreas.Sandberg@ARM.com    static const RequestType T_FLUSH = 4;
11210390SAndreas.Sandberg@ARM.com    /** @} */
11310390SAndreas.Sandberg@ARM.com
11410390SAndreas.Sandberg@ARM.com    /** @{
11510390SAndreas.Sandberg@ARM.com     * @name VirtIO block request status
11610390SAndreas.Sandberg@ARM.com     */
11710390SAndreas.Sandberg@ARM.com    typedef uint8_t Status;
11810390SAndreas.Sandberg@ARM.com    /** Request succeeded */
11910390SAndreas.Sandberg@ARM.com    static const Status S_OK = 0;
12010390SAndreas.Sandberg@ARM.com    /** Request failed due to a device error */
12110390SAndreas.Sandberg@ARM.com    static const Status S_IOERR = 1;
12210390SAndreas.Sandberg@ARM.com    /** Request not supported */
12310390SAndreas.Sandberg@ARM.com    static const Status S_UNSUPP = 2;
12410390SAndreas.Sandberg@ARM.com    /** @} */
12510390SAndreas.Sandberg@ARM.com
12610390SAndreas.Sandberg@ARM.com    /** VirtIO block device request as sent by guest */
12710390SAndreas.Sandberg@ARM.com    struct BlkRequest {
12810390SAndreas.Sandberg@ARM.com        RequestType type;
12910390SAndreas.Sandberg@ARM.com        uint32_t reserved;
13010390SAndreas.Sandberg@ARM.com        uint64_t sector;
13110390SAndreas.Sandberg@ARM.com    } M5_ATTR_PACKED;
13210390SAndreas.Sandberg@ARM.com
13310390SAndreas.Sandberg@ARM.com    /**
13410390SAndreas.Sandberg@ARM.com     * Device read request.
13510390SAndreas.Sandberg@ARM.com     *
13610390SAndreas.Sandberg@ARM.com     * @param req Disk request from guest.
13710390SAndreas.Sandberg@ARM.com     * @param desc_chain Request descriptor chain (from start of
13810390SAndreas.Sandberg@ARM.com     *                   request)
13910390SAndreas.Sandberg@ARM.com     * @param off_data Offset into the descriptor chain where data
14010390SAndreas.Sandberg@ARM.com     *                 should be written.
14110390SAndreas.Sandberg@ARM.com     * @param size Request data size.
14210390SAndreas.Sandberg@ARM.com     */
14310390SAndreas.Sandberg@ARM.com    Status read(const BlkRequest &req, VirtDescriptor *desc_chain,
14410390SAndreas.Sandberg@ARM.com                size_t off_data, size_t size);
14510390SAndreas.Sandberg@ARM.com    /**
14610390SAndreas.Sandberg@ARM.com     * Device write request.
14710390SAndreas.Sandberg@ARM.com     *
14810390SAndreas.Sandberg@ARM.com     * @param req Disk request from guest.
14910390SAndreas.Sandberg@ARM.com     * @param desc_chain Request descriptor chain (from start of
15010390SAndreas.Sandberg@ARM.com     *                   request)
15110390SAndreas.Sandberg@ARM.com     * @param off_data Offset into the descriptor chain where data
15210390SAndreas.Sandberg@ARM.com     *                 should be read.
15310390SAndreas.Sandberg@ARM.com     * @param size Request data size.
15410390SAndreas.Sandberg@ARM.com     */
15510390SAndreas.Sandberg@ARM.com    Status write(const BlkRequest &req, VirtDescriptor *desc_chain,
15610390SAndreas.Sandberg@ARM.com                 size_t off_data, size_t size);
15710390SAndreas.Sandberg@ARM.com
15810390SAndreas.Sandberg@ARM.com  protected:
15910390SAndreas.Sandberg@ARM.com    /**
16010390SAndreas.Sandberg@ARM.com     * Virtqueue for disk requests.
16110390SAndreas.Sandberg@ARM.com     */
16210390SAndreas.Sandberg@ARM.com    class RequestQueue
16310390SAndreas.Sandberg@ARM.com        : public VirtQueue
16410390SAndreas.Sandberg@ARM.com    {
16510390SAndreas.Sandberg@ARM.com      public:
16610390SAndreas.Sandberg@ARM.com        RequestQueue(PortProxy &proxy, uint16_t size, VirtIOBlock &_parent)
16710390SAndreas.Sandberg@ARM.com            : VirtQueue(proxy, size), parent(_parent) {}
16810390SAndreas.Sandberg@ARM.com        virtual ~RequestQueue() {}
16910390SAndreas.Sandberg@ARM.com
17010390SAndreas.Sandberg@ARM.com        void onNotifyDescriptor(VirtDescriptor *desc);
17110390SAndreas.Sandberg@ARM.com
17210390SAndreas.Sandberg@ARM.com        std::string name() const { return parent.name() + ".qRequests"; }
17310390SAndreas.Sandberg@ARM.com
17410390SAndreas.Sandberg@ARM.com      protected:
17510390SAndreas.Sandberg@ARM.com        VirtIOBlock &parent;
17610390SAndreas.Sandberg@ARM.com    };
17710390SAndreas.Sandberg@ARM.com
17810390SAndreas.Sandberg@ARM.com    /** Device I/O request queue */
17910390SAndreas.Sandberg@ARM.com    RequestQueue qRequests;
18010390SAndreas.Sandberg@ARM.com
18110390SAndreas.Sandberg@ARM.com    /** Image backing this device */
18210390SAndreas.Sandberg@ARM.com    DiskImage &image;
18310390SAndreas.Sandberg@ARM.com};
18410390SAndreas.Sandberg@ARM.com
18510390SAndreas.Sandberg@ARM.com#endif // __DEV_VIRTIO_BLOCK_HH__
186