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