110b59a9bSPeter Grehan /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4abd6790cSBryan Venteicher * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org> 510b59a9bSPeter Grehan * All rights reserved. 610b59a9bSPeter Grehan * 710b59a9bSPeter Grehan * Redistribution and use in source and binary forms, with or without 810b59a9bSPeter Grehan * modification, are permitted provided that the following conditions 910b59a9bSPeter Grehan * are met: 1010b59a9bSPeter Grehan * 1. Redistributions of source code must retain the above copyright 1110b59a9bSPeter Grehan * notice unmodified, this list of conditions, and the following 1210b59a9bSPeter Grehan * disclaimer. 1310b59a9bSPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 1410b59a9bSPeter Grehan * notice, this list of conditions and the following disclaimer in the 1510b59a9bSPeter Grehan * documentation and/or other materials provided with the distribution. 1610b59a9bSPeter Grehan * 1710b59a9bSPeter Grehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1810b59a9bSPeter Grehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1910b59a9bSPeter Grehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2010b59a9bSPeter Grehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2110b59a9bSPeter Grehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2210b59a9bSPeter Grehan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310b59a9bSPeter Grehan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410b59a9bSPeter Grehan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510b59a9bSPeter Grehan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2610b59a9bSPeter Grehan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710b59a9bSPeter Grehan */ 2810b59a9bSPeter Grehan 2910b59a9bSPeter Grehan #ifndef _VIRTIO_VIRTQUEUE_H 3010b59a9bSPeter Grehan #define _VIRTIO_VIRTQUEUE_H 3110b59a9bSPeter Grehan 3210b59a9bSPeter Grehan struct virtqueue; 3310b59a9bSPeter Grehan struct sglist; 3410b59a9bSPeter Grehan 3510b59a9bSPeter Grehan /* Device callback for a virtqueue interrupt. */ 366632efe4SBryan Venteicher typedef void virtqueue_intr_t(void *); 3710b59a9bSPeter Grehan 38b619f40aSBryan Venteicher /* 39b619f40aSBryan Venteicher * Hint on how long the next interrupt should be postponed. This is 40b619f40aSBryan Venteicher * only used when the EVENT_IDX feature is negotiated. 41b619f40aSBryan Venteicher */ 42b619f40aSBryan Venteicher typedef enum { 43b619f40aSBryan Venteicher VQ_POSTPONE_SHORT, 44b619f40aSBryan Venteicher VQ_POSTPONE_LONG, 45b619f40aSBryan Venteicher VQ_POSTPONE_EMPTIED /* Until all available desc are used. */ 46b619f40aSBryan Venteicher } vq_postpone_t; 47b619f40aSBryan Venteicher 4810b59a9bSPeter Grehan #define VIRTQUEUE_MAX_NAME_SZ 32 4910b59a9bSPeter Grehan 5010b59a9bSPeter Grehan /* One for each virtqueue the device wishes to allocate. */ 5110b59a9bSPeter Grehan struct vq_alloc_info { 5210b59a9bSPeter Grehan char vqai_name[VIRTQUEUE_MAX_NAME_SZ]; 5310b59a9bSPeter Grehan int vqai_maxindirsz; 5410b59a9bSPeter Grehan virtqueue_intr_t *vqai_intr; 5510b59a9bSPeter Grehan void *vqai_intr_arg; 5610b59a9bSPeter Grehan struct virtqueue **vqai_vq; 5710b59a9bSPeter Grehan }; 5810b59a9bSPeter Grehan 5910b59a9bSPeter Grehan #define VQ_ALLOC_INFO_INIT(_i,_nsegs,_intr,_arg,_vqp,_str,...) do { \ 6010b59a9bSPeter Grehan snprintf((_i)->vqai_name, VIRTQUEUE_MAX_NAME_SZ, _str, \ 6110b59a9bSPeter Grehan ##__VA_ARGS__); \ 6210b59a9bSPeter Grehan (_i)->vqai_maxindirsz = (_nsegs); \ 6310b59a9bSPeter Grehan (_i)->vqai_intr = (_intr); \ 6410b59a9bSPeter Grehan (_i)->vqai_intr_arg = (_arg); \ 6510b59a9bSPeter Grehan (_i)->vqai_vq = (_vqp); \ 6610b59a9bSPeter Grehan } while (0) 6710b59a9bSPeter Grehan 6810b59a9bSPeter Grehan int virtqueue_alloc(device_t dev, uint16_t queue, uint16_t size, 699da9560cSBryan Venteicher bus_size_t notify_offset, int align, vm_paddr_t highaddr, 709da9560cSBryan Venteicher struct vq_alloc_info *info, struct virtqueue **vqp); 7110b59a9bSPeter Grehan void *virtqueue_drain(struct virtqueue *vq, int *last); 7210b59a9bSPeter Grehan void virtqueue_free(struct virtqueue *vq); 7310b59a9bSPeter Grehan int virtqueue_reinit(struct virtqueue *vq, uint16_t size); 7410b59a9bSPeter Grehan 756632efe4SBryan Venteicher int virtqueue_intr_filter(struct virtqueue *vq); 766632efe4SBryan Venteicher void virtqueue_intr(struct virtqueue *vq); 7710b59a9bSPeter Grehan int virtqueue_enable_intr(struct virtqueue *vq); 78b619f40aSBryan Venteicher int virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint); 7910b59a9bSPeter Grehan void virtqueue_disable_intr(struct virtqueue *vq); 8010b59a9bSPeter Grehan 8110b59a9bSPeter Grehan /* Get physical address of the virtqueue ring. */ 8210b59a9bSPeter Grehan vm_paddr_t virtqueue_paddr(struct virtqueue *vq); 8388126356SBryan Venteicher vm_paddr_t virtqueue_desc_paddr(struct virtqueue *vq); 8488126356SBryan Venteicher vm_paddr_t virtqueue_avail_paddr(struct virtqueue *vq); 8588126356SBryan Venteicher vm_paddr_t virtqueue_used_paddr(struct virtqueue *vq); 8610b59a9bSPeter Grehan 8788126356SBryan Venteicher uint16_t virtqueue_index(struct virtqueue *vq); 88*ccb576a8SMina Galić bool virtqueue_full(struct virtqueue *vq); 89*ccb576a8SMina Galić bool virtqueue_empty(struct virtqueue *vq); 9010b59a9bSPeter Grehan int virtqueue_size(struct virtqueue *vq); 914b59668fSBryan Venteicher int virtqueue_nfree(struct virtqueue *vq); 9210b59a9bSPeter Grehan int virtqueue_nused(struct virtqueue *vq); 9310b59a9bSPeter Grehan void virtqueue_notify(struct virtqueue *vq); 9410b59a9bSPeter Grehan void virtqueue_dump(struct virtqueue *vq); 9510b59a9bSPeter Grehan 9610b59a9bSPeter Grehan int virtqueue_enqueue(struct virtqueue *vq, void *cookie, 9710b59a9bSPeter Grehan struct sglist *sg, int readable, int writable); 9810b59a9bSPeter Grehan void *virtqueue_dequeue(struct virtqueue *vq, uint32_t *len); 9910b59a9bSPeter Grehan void *virtqueue_poll(struct virtqueue *vq, uint32_t *len); 10010b59a9bSPeter Grehan 10110b59a9bSPeter Grehan #endif /* _VIRTIO_VIRTQUEUE_H */ 102