Annotation of qemu/roms/ipxe/src/drivers/bus/virtio-ring.c, revision 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:  * This work is licensed under the terms of the GNU GPL, version 2 or later.
        !            12:  * See the COPYING file in the top-level directory.
        !            13:  *
        !            14:  *
        !            15:  */
        !            16: 
        !            17: FILE_LICENCE ( GPL2_OR_LATER );
        !            18: 
        !            19: #include "etherboot.h"
        !            20: #include "ipxe/io.h"
        !            21: #include "ipxe/virtio-ring.h"
        !            22: #include "ipxe/virtio-pci.h"
        !            23: 
        !            24: #define BUG() do { \
        !            25:    printf("BUG: failure at %s:%d/%s()!\n", \
        !            26:           __FILE__, __LINE__, __FUNCTION__); \
        !            27:    while(1); \
        !            28: } while (0)
        !            29: #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
        !            30: 
        !            31: /*
        !            32:  * vring_free
        !            33:  *
        !            34:  * put at the begin of the free list the current desc[head]
        !            35:  */
        !            36: 
        !            37: void vring_detach(struct vring_virtqueue *vq, unsigned int head)
        !            38: {
        !            39:    struct vring *vr = &vq->vring;
        !            40:    unsigned int i;
        !            41: 
        !            42:    /* find end of given descriptor */
        !            43: 
        !            44:    i = head;
        !            45:    while (vr->desc[i].flags & VRING_DESC_F_NEXT)
        !            46:            i = vr->desc[i].next;
        !            47: 
        !            48:    /* link it with free list and point to it */
        !            49: 
        !            50:    vr->desc[i].next = vq->free_head;
        !            51:    wmb();
        !            52:    vq->free_head = head;
        !            53: }
        !            54: 
        !            55: /*
        !            56:  * vring_get_buf
        !            57:  *
        !            58:  * get a buffer from the used list
        !            59:  *
        !            60:  */
        !            61: 
        !            62: void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
        !            63: {
        !            64:    struct vring *vr = &vq->vring;
        !            65:    struct vring_used_elem *elem;
        !            66:    u32 id;
        !            67:    void *opaque;
        !            68: 
        !            69:    BUG_ON(!vring_more_used(vq));
        !            70: 
        !            71:    elem = &vr->used->ring[vq->last_used_idx % vr->num];
        !            72:    wmb();
        !            73:    id = elem->id;
        !            74:    if (len != NULL)
        !            75:            *len = elem->len;
        !            76: 
        !            77:    opaque = vq->vdata[id];
        !            78: 
        !            79:    vring_detach(vq, id);
        !            80: 
        !            81:    vq->last_used_idx++;
        !            82: 
        !            83:    return opaque;
        !            84: }
        !            85: 
        !            86: void vring_add_buf(struct vring_virtqueue *vq,
        !            87:                   struct vring_list list[],
        !            88:                   unsigned int out, unsigned int in,
        !            89:                   void *opaque, int num_added)
        !            90: {
        !            91:    struct vring *vr = &vq->vring;
        !            92:    int i, avail, head, prev;
        !            93: 
        !            94:    BUG_ON(out + in == 0);
        !            95: 
        !            96:    prev = 0;
        !            97:    head = vq->free_head;
        !            98:    for (i = head; out; i = vr->desc[i].next, out--) {
        !            99: 
        !           100:            vr->desc[i].flags = VRING_DESC_F_NEXT;
        !           101:            vr->desc[i].addr = (u64)virt_to_phys(list->addr);
        !           102:            vr->desc[i].len = list->length;
        !           103:            prev = i;
        !           104:            list++;
        !           105:    }
        !           106:    for ( ; in; i = vr->desc[i].next, in--) {
        !           107: 
        !           108:            vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
        !           109:            vr->desc[i].addr = (u64)virt_to_phys(list->addr);
        !           110:            vr->desc[i].len = list->length;
        !           111:            prev = i;
        !           112:            list++;
        !           113:    }
        !           114:    vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
        !           115: 
        !           116:    vq->free_head = i;
        !           117: 
        !           118:    vq->vdata[head] = opaque;
        !           119: 
        !           120:    avail = (vr->avail->idx + num_added) % vr->num;
        !           121:    vr->avail->ring[avail] = head;
        !           122:    wmb();
        !           123: }
        !           124: 
        !           125: void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
        !           126: {
        !           127:    struct vring *vr = &vq->vring;
        !           128: 
        !           129:    wmb();
        !           130:    vr->avail->idx += num_added;
        !           131: 
        !           132:    mb();
        !           133:    if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
        !           134:            vp_notify(ioaddr, vq->queue_index);
        !           135: }
        !           136: 

unix.superglobalmegacorp.com

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