Annotation of qemu/roms/seabios/src/virtio-ring.c, revision 1.1.1.1

1.1       root        1: /* virtio-pci.c - virtio ring management
                      2:  *
                      3:  * (c) Copyright 2008 Bull S.A.S.
                      4:  *
                      5:  *  Author: Laurent Vivier <[email protected]>
                      6:  *
                      7:  *  some parts from Linux Virtio Ring
                      8:  *
                      9:  *  Copyright Rusty Russell IBM Corporation 2007
                     10:  *
                     11:  *  Adopted for Seabios: Gleb Natapov <[email protected]>
                     12:  *
                     13:  * This work is licensed under the terms of the GNU LGPLv3
                     14:  * See the COPYING file in the top-level directory.
                     15:  *
                     16:  *
                     17:  */
                     18: 
                     19: #include "virtio-ring.h"
                     20: #include "virtio-pci.h"
                     21: #include "biosvar.h" // GET_GLOBAL
                     22: #include "util.h" // dprintf
                     23: 
                     24: #define BUG() do {                                      \
                     25:         dprintf(1, "BUG: failure at %s:%d/%s()!\n",     \
                     26:                 __FILE__, __LINE__, __func__);          \
                     27:                 while(1);                               \
                     28:         } while (0)
                     29: #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
                     30: 
                     31: /*
                     32:  * vring_more_used
                     33:  *
                     34:  * is there some used buffers ?
                     35:  *
                     36:  */
                     37: 
                     38: int vring_more_used(struct vring_virtqueue *vq)
                     39: {
                     40:     struct vring_used *used = GET_FLATPTR(vq->vring.used);
                     41:     int more = GET_FLATPTR(vq->last_used_idx) != GET_FLATPTR(used->idx);
                     42:     /* Make sure ring reads are done after idx read above. */
                     43:     smp_rmb();
                     44:     return more;
                     45: }
                     46: 
                     47: /*
                     48:  * vring_free
                     49:  *
                     50:  * put at the begin of the free list the current desc[head]
                     51:  */
                     52: 
                     53: void vring_detach(struct vring_virtqueue *vq, unsigned int head)
                     54: {
                     55:     struct vring *vr = &vq->vring;
                     56:     struct vring_desc *desc = GET_FLATPTR(vr->desc);
                     57:     unsigned int i;
                     58: 
                     59:     /* find end of given descriptor */
                     60: 
                     61:     i = head;
                     62:     while (GET_FLATPTR(desc[i].flags) & VRING_DESC_F_NEXT)
                     63:         i = GET_FLATPTR(desc[i].next);
                     64: 
                     65:     /* link it with free list and point to it */
                     66: 
                     67:     SET_FLATPTR(desc[i].next, GET_FLATPTR(vq->free_head));
                     68:     SET_FLATPTR(vq->free_head, head);
                     69: }
                     70: 
                     71: /*
                     72:  * vring_get_buf
                     73:  *
                     74:  * get a buffer from the used list
                     75:  *
                     76:  */
                     77: 
                     78: int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
                     79: {
                     80:     struct vring *vr = &vq->vring;
                     81:     struct vring_used_elem *elem;
                     82:     struct vring_used *used = GET_FLATPTR(vq->vring.used);
                     83:     u32 id;
                     84:     int ret;
                     85: 
                     86: //    BUG_ON(!vring_more_used(vq));
                     87: 
                     88:     elem = &used->ring[GET_FLATPTR(vq->last_used_idx) % GET_FLATPTR(vr->num)];
                     89:     id = GET_FLATPTR(elem->id);
                     90:     if (len != NULL)
                     91:         *len = GET_FLATPTR(elem->len);
                     92: 
                     93:     ret = GET_FLATPTR(vq->vdata[id]);
                     94: 
                     95:     vring_detach(vq, id);
                     96: 
                     97:     SET_FLATPTR(vq->last_used_idx, GET_FLATPTR(vq->last_used_idx) + 1);
                     98: 
                     99:     return ret;
                    100: }
                    101: 
                    102: void vring_add_buf(struct vring_virtqueue *vq,
                    103:                    struct vring_list list[],
                    104:                    unsigned int out, unsigned int in,
                    105:                    int index, int num_added)
                    106: {
                    107:     struct vring *vr = &vq->vring;
                    108:     int i, av, head, prev;
                    109:     struct vring_desc *desc = GET_FLATPTR(vr->desc);
                    110:     struct vring_avail *avail = GET_FLATPTR(vr->avail);
                    111: 
                    112:     BUG_ON(out + in == 0);
                    113: 
                    114:     prev = 0;
                    115:     head = GET_FLATPTR(vq->free_head);
                    116:     for (i = head; out; i = GET_FLATPTR(desc[i].next), out--) {
                    117:         SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT);
                    118:         SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
                    119:         SET_FLATPTR(desc[i].len, list->length);
                    120:         prev = i;
                    121:         list++;
                    122:     }
                    123:     for ( ; in; i = GET_FLATPTR(desc[i].next), in--) {
                    124:         SET_FLATPTR(desc[i].flags, VRING_DESC_F_NEXT|VRING_DESC_F_WRITE);
                    125:         SET_FLATPTR(desc[i].addr, (u64)virt_to_phys(list->addr));
                    126:         SET_FLATPTR(desc[i].len, list->length);
                    127:         prev = i;
                    128:         list++;
                    129:     }
                    130:     SET_FLATPTR(desc[prev].flags,
                    131:                 GET_FLATPTR(desc[prev].flags) & ~VRING_DESC_F_NEXT);
                    132: 
                    133:     SET_FLATPTR(vq->free_head, i);
                    134: 
                    135:     SET_FLATPTR(vq->vdata[head], index);
                    136: 
                    137:     av = (GET_FLATPTR(avail->idx) + num_added) % GET_FLATPTR(vr->num);
                    138:     SET_FLATPTR(avail->ring[av], head);
                    139: }
                    140: 
                    141: void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
                    142: {
                    143:     struct vring *vr = &vq->vring;
                    144:     struct vring_avail *avail = GET_FLATPTR(vr->avail);
                    145: 
                    146:     /* Make sure idx update is done after ring write. */
                    147:     smp_wmb();
                    148:     SET_FLATPTR(avail->idx, GET_FLATPTR(avail->idx) + num_added);
                    149: 
                    150:     vp_notify(ioaddr, GET_FLATPTR(vq->queue_index));
                    151: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.