Skip to content
Snippets Groups Projects
virtio-blk.hh 6.79 KiB
Newer Older
  • Learn to ignore specific revisions
  • Guy Zana's avatar
    Guy Zana committed
    #ifndef VIRTIO_BLK_DRIVER_H
    #define VIRTIO_BLK_DRIVER_H
    
    /* This header is BSD licensed so anyone can use the definitions to implement
     * compatible drivers/servers.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 3. Neither the name of IBM nor the names of its contributors
     *    may be used to endorse or promote products derived from this software
     *    without specific prior written permission.
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     * SUCH DAMAGE. */
    
    
    #include "drivers/virtio.hh"
    
    #include "drivers/pci-device.hh"
    
    Guy Zana's avatar
    Guy Zana committed
    
    namespace virtio {
    
        class virtio_blk : public virtio_driver {
        public:
    
            // The feature bitmap for virtio blk
            enum BlkFeatures {
                VIRTIO_BLK_F_BARRIER=0,        /* Does host support barriers? */
                VIRTIO_BLK_F_SIZE_MAX=1,       /* Indicates maximum segment size */
                VIRTIO_BLK_F_SEG_MAX=2,        /* Indicates maximum # of segments */
                VIRTIO_BLK_F_GEOMETRY=4,       /* Legacy geometry available  */
                VIRTIO_BLK_F_RO=5,             /* Disk is read-only */
                VIRTIO_BLK_F_BLK_SIZE=6,       /* Block size of disk is available*/
                VIRTIO_BLK_F_SCSI=7,           /* Supports scsi command passthru */
                VIRTIO_BLK_F_WCE=9,            /* Writeback mode enabled after reset */
                VIRTIO_BLK_F_TOPOLOGY=10,      /* Topology information is available */
                VIRTIO_BLK_F_CONFIG_WCE=11,    /* Writeback mode available in config */
            };
    
            enum {
                VIRTIO_BLK_DEVICE_ID=0x1001,
                VIRTIO_BLK_ID_BYTES=20,      /* ID string length */
    
                /*
                 * Command types
                 *
                 * Usage is a bit tricky as some bits are used as flags and some are not.
                 *
                 * Rules:
                 *   VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
                 *   VIRTIO_BLK_T_BARRIER.  VIRTIO_BLK_T_FLUSH is a command of its own
                 *   and may not be combined with any of the other flags.
                 */
    
            enum virtio_blk_request_type {
    
    Guy Zana's avatar
    Guy Zana committed
                VIRTIO_BLK_T_IN=0,
                VIRTIO_BLK_T_OUT=1,
                /* This bit says it's a scsi command, not an actual read or write. */
                VIRTIO_BLK_T_SCSI_CMD=2,
                /* Cache flush command */
                VIRTIO_BLK_T_FLUSH=4,
                /* Get device ID command */
                VIRTIO_BLK_T_GET_ID=8,
                /* Barrier before this op. */
                VIRTIO_BLK_T_BARRIER=0x80000000,
    
    Guy Zana's avatar
    Guy Zana committed
                /* And this is the final byte of the write scatter-gather list. */
                VIRTIO_BLK_S_OK=0,
                VIRTIO_BLK_S_IOERR=1,
                VIRTIO_BLK_S_UNSUPP=2,
            };
    
            struct virtio_blk_config {
                    /* The capacity (in 512-byte sectors). */
                    u64 capacity;
                    /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
                    u32 size_max;
                    /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
                    u32 seg_max;
                    /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
                    struct virtio_blk_geometry {
                            u16 cylinders;
                            u8 heads;
                            u8 sectors;
                    } geometry;
    
                    /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
                    u32 blk_size;
    
                    /* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY  */
                    /* exponent for physical block per logical block. */
                    u8 physical_block_exp;
                    /* alignment offset in logical blocks. */
                    u8 alignment_offset;
                    /* minimum I/O size without performance penalty in logical blocks. */
                    u16 min_io_size;
                    /* optimal sustained I/O size in logical blocks. */
                    u32 opt_io_size;
    
                    /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
                    u8 wce;
            } __attribute__((packed));
    
            /* This is the first element of the read scatter-gather list. */
            struct virtio_blk_outhdr {
                    /* VIRTIO_BLK_T* */
                    u32 type;
                    /* io priority. */
                    u32 ioprio;
                    /* Sector (ie. 512 byte offset) */
                    u64 sector;
            };
    
            struct virtio_scsi_inhdr {
                    u32 errors;
                    u32 data_len;
                    u32 sense_len;
                    u32 residual;
            };
            
    
            struct virtio_blk_res {
                u8 status;
            };
    
    
                virtio_blk_req(void* req = nullptr, sglist* sg = nullptr, virtio_blk_res* res = nullptr, struct bio* b=nullptr)
                    :req_header(req), payload(sg), status(res), bio(b) {};
                ~virtio_blk_req();
    
                void* req_header;
                sglist* payload;
                virtio_blk_res* status;
    
            virtio_blk(unsigned dev_idx=0);
    
    Guy Zana's avatar
    Guy Zana committed
            virtual ~virtio_blk();
    
    
            virtual const std::string get_name(void) { return _driver_name; }
    
            virtual bool load(void);
            virtual bool unload(void);
    
    Guy Zana's avatar
    Guy Zana committed
    
            virtual u32 get_driver_features(void) { return ((1 << VIRTIO_BLK_F_SIZE_MAX)); }
    
    
            virtio_blk_req* make_virtio_req(u64 sector, virtio_blk_request_type type, int val);
    
            int make_virtio_request(struct bio*);
    
            std::string _driver_name;
    
            virtio_blk_config _config;
    
    
            //maintains the virtio instance number for multiple drives
            static int _instance;
            int _id;