1 /*
   2  * Copyright (c) 2010 Minoura Makoto.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24  */
  25 
  26 /*
  27  * Part of the file derived from `Virtio PCI Card Specification v0.8.6 DRAFT'
  28  * Appendix A.
  29  */
  30 
  31 /*
  32  * An interface for efficient virtio implementation.
  33  *
  34  * This header is BSD licensed so anyone can use the definitions
  35  * to implement compatible drivers/servers.
  36  *
  37  * Copyright 2007, 2009, IBM Corporation
  38  * All rights reserved.
  39  *
  40  * Redistribution and use in source and binary forms, with or without
  41  * modification, are permitted provided that the following conditions
  42  * are met:
  43  * 1. Redistributions of source code must retain the above copyright
  44  *    notice, this list of conditions and the following disclaimer.
  45  * 2. Redistributions in binary form must reproduce the above copyright
  46  *    notice, this list of conditions and the following disclaimer in the
  47  *    documentation and/or other materials provided with the distribution.
  48  * 3. Neither the name of IBM nor the names of its contributors
  49  *    may be used to endorse or promote products derived from this software
  50  *    without specific prior written permission.
  51  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  52  * ``AS IS'' ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  53  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  54  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
  55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  61  * SUCH DAMAGE.
  62  */
  63 
  64 /*
  65  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  66  */
  67 
  68 #ifndef __VIRTIOVAR_H__
  69 #define __VIRTIOVAR_H__
  70 
  71 #include <sys/types.h>
  72 #include <sys/dditypes.h>
  73 #include <sys/cmn_err.h>
  74 #include <sys/list.h>
  75 
  76 #ifdef DEBUG
  77 #define dev_debug(dip, fmt, arg...) \
  78         dev_err(dip, fmt, ##arg)
  79 #else
  80 #define dev_debug(dip, fmt, arg...)
  81 #endif
  82 
  83 struct vq_entry {
  84         list_node_t             qe_list;
  85         struct virtqueue        *qe_queue;
  86         uint16_t                qe_index; /* index in vq_desc array */
  87         /* followings are used only when it is the `head' entry */
  88         struct vq_entry         *qe_next;
  89         struct vring_desc       *qe_desc;
  90         ddi_dma_cookie_t        qe_indirect_dma_cookie;
  91         ddi_dma_handle_t        qe_indirect_dma_handle;
  92         ddi_acc_handle_t        qe_indirect_dma_acch;
  93         struct vring_desc       *qe_indirect_descs;
  94         unsigned int            qe_indirect_next;
  95 };
  96 
  97 struct virtqueue {
  98         struct virtio_softc     *vq_owner;
  99         unsigned int            vq_num; /* queue size (# of entries) */
 100         unsigned int            vq_indirect_num;
 101         int                     vq_index; /* queue number (0, 1, ...) */
 102 
 103         /* vring pointers (KVA) */
 104         struct vring_desc       *vq_descs;
 105         struct vring_avail      *vq_avail;
 106         struct vring_used       *vq_used;
 107 
 108         /* virtqueue allocation info */
 109         void                    *vq_vaddr;
 110         int                     vq_availoffset;
 111         int                     vq_usedoffset;
 112         ddi_dma_cookie_t        vq_dma_cookie;
 113         ddi_dma_handle_t        vq_dma_handle;
 114         ddi_acc_handle_t        vq_dma_acch;
 115 
 116         int                     vq_maxsegsize;
 117 
 118         /* free entry management */
 119         struct vq_entry         *vq_entries;
 120         list_t                  vq_freelist;
 121         kmutex_t                vq_freelist_lock;
 122         int                     vq_used_entries;
 123 
 124         /* enqueue/dequeue status */
 125         uint16_t                vq_avail_idx;
 126         kmutex_t                vq_avail_lock;
 127         uint16_t                vq_used_idx;
 128         kmutex_t                vq_used_lock;
 129 };
 130 
 131 struct virtio_softc {
 132         dev_info_t              *sc_dev;
 133 
 134         uint_t                  sc_intr_prio;
 135 
 136         ddi_acc_handle_t        sc_ioh;
 137         caddr_t                 sc_io_addr;
 138         int                     sc_config_offset;
 139 
 140         uint32_t                sc_features;
 141 
 142         int                     sc_nvqs; /* set by the user */
 143 
 144         ddi_intr_handle_t       *sc_intr_htable;
 145         int                     sc_intr_num;
 146         boolean_t               sc_intr_config;
 147         int                     sc_intr_cap;
 148 };
 149 
 150 struct virtio_int_handler {
 151         ddi_intr_handler_t *vh_func;
 152         void *vh_priv;
 153 };
 154 
 155 /* public interface */
 156 uint32_t virtio_negotiate_features(struct virtio_softc *, uint32_t);
 157 size_t virtio_show_features(uint32_t features, char *buffer, size_t len);
 158 boolean_t virtio_has_feature(struct virtio_softc *sc, uint32_t feature);
 159 void virtio_set_status(struct virtio_softc *sc, unsigned int);
 160 #define virtio_device_reset(sc) virtio_set_status((sc), 0)
 161 
 162 uint8_t virtio_read_device_config_1(struct virtio_softc *sc,
 163                 unsigned int index);
 164 uint16_t virtio_read_device_config_2(struct virtio_softc *sc,
 165                 unsigned int index);
 166 uint32_t virtio_read_device_config_4(struct virtio_softc *sc,
 167                 unsigned int index);
 168 uint64_t virtio_read_device_config_8(struct virtio_softc *sc,
 169                 unsigned int index);
 170 void virtio_write_device_config_1(struct virtio_softc *sc,
 171                 unsigned int index, uint8_t value);
 172 void virtio_write_device_config_2(struct virtio_softc *sc,
 173                 unsigned int index, uint16_t value);
 174 void virtio_write_device_config_4(struct virtio_softc *sc,
 175                 unsigned int index, uint32_t value);
 176 void virtio_write_device_config_8(struct virtio_softc *sc,
 177                 unsigned int index, uint64_t value);
 178 
 179 struct virtqueue *virtio_alloc_vq(struct virtio_softc *sc,
 180                 unsigned int index, unsigned int size,
 181                 unsigned int indirect_num, const char *name);
 182 void virtio_free_vq(struct virtqueue *);
 183 void virtio_reset(struct virtio_softc *);
 184 struct vq_entry *vq_alloc_entry(struct virtqueue *vq);
 185 void vq_free_entry(struct virtqueue *vq, struct vq_entry *qe);
 186 uint_t vq_num_used(struct virtqueue *vq);
 187 
 188 void virtio_stop_vq_intr(struct virtqueue *);
 189 void virtio_start_vq_intr(struct virtqueue *);
 190 
 191 void virtio_ve_add_cookie(struct vq_entry *qe, ddi_dma_handle_t dma_handle,
 192     ddi_dma_cookie_t dma_cookie, unsigned int ncookies, boolean_t write);
 193 void virtio_ve_add_indirect_buf(struct vq_entry *qe, uint64_t paddr,
 194     uint32_t len, boolean_t write);
 195 void virtio_ve_set(struct vq_entry *qe, uint64_t paddr, uint32_t len,
 196                 boolean_t write);
 197 
 198 void virtio_push_chain(struct vq_entry *qe, boolean_t sync);
 199 struct vq_entry *virtio_pull_chain(struct virtqueue *vq, uint32_t *len);
 200 void virtio_free_chain(struct vq_entry *ve);
 201 void virtio_sync_vq(struct virtqueue *vq);
 202 
 203 int virtio_register_ints(struct virtio_softc *sc,
 204                 struct virtio_int_handler *config_handler,
 205                 struct virtio_int_handler vq_handlers[]);
 206 void virtio_release_ints(struct virtio_softc *sc);
 207 int virtio_enable_ints(struct virtio_softc *sc);
 208 
 209 #endif /* __VIRTIOVAR_H__ */