Annotation of qemu/roms/SLOF/lib/libvirtio/virtio-blk.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 2011 IBM Corporation
        !             3:  * All rights reserved.
        !             4:  * This program and the accompanying materials
        !             5:  * are made available under the terms of the BSD License
        !             6:  * which accompanies this distribution, and is available at
        !             7:  * http://www.opensource.org/licenses/bsd-license.php
        !             8:  *
        !             9:  * Contributors:
        !            10:  *     IBM Corporation - initial implementation
        !            11:  *****************************************************************************/
        !            12: 
        !            13: #include <stdio.h>
        !            14: #include "virtio.h"
        !            15: #include "virtio-blk.h"
        !            16: 
        !            17: #define sync()  asm volatile (" sync \n" ::: "memory")
        !            18: 
        !            19: 
        !            20: /**
        !            21:  * Initialize virtio-block device.
        !            22:  * @param  dev  pointer to virtio device information
        !            23:  */
        !            24: int
        !            25: virtioblk_init(struct virtio_device *dev)
        !            26: {
        !            27:        struct vring_avail *vq_avail;
        !            28: 
        !            29:        /* Reset device */
        !            30:        // XXX That will clear the virtq base. We need to move
        !            31:        //     initializing it to here anyway
        !            32:        //
        !            33:        //       virtio_reset_device(dev);
        !            34: 
        !            35:        /* Acknowledge device. */
        !            36:        virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE);
        !            37: 
        !            38:        /* Tell HV that we know how to drive the device. */
        !            39:        virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER);
        !            40: 
        !            41:        /* Device specific setup - we do not support special features right now */
        !            42:        virtio_set_guest_features(dev,  0);
        !            43: 
        !            44:        vq_avail = virtio_get_vring_avail(dev, 0);
        !            45:        vq_avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
        !            46:        vq_avail->idx = 0;
        !            47: 
        !            48:        /* Tell HV that setup succeeded */
        !            49:        virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER
        !            50:                                |VIRTIO_STAT_DRIVER_OK);
        !            51: 
        !            52:        return 0;
        !            53: }
        !            54: 
        !            55: 
        !            56: /**
        !            57:  * Shutdown the virtio-block device.
        !            58:  * @param  dev  pointer to virtio device information
        !            59:  */
        !            60: void
        !            61: virtioblk_shutdown(struct virtio_device *dev)
        !            62: {
        !            63:        /* Quiesce device */
        !            64:        virtio_set_status(dev, VIRTIO_STAT_FAILED);
        !            65: 
        !            66:        /* Reset device */
        !            67:        virtio_reset_device(dev);
        !            68: }
        !            69: 
        !            70: 
        !            71: /**
        !            72:  * Read blocks
        !            73:  * @param  reg  pointer to "reg" property
        !            74:  * @param  buf  pointer to destination buffer
        !            75:  * @param  blocknum  block number of the first block that should be read
        !            76:  * @param  cnt  amount of blocks that should be read
        !            77:  * @return number of blocks that have been read successfully
        !            78:  */
        !            79: int
        !            80: virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt)
        !            81: {
        !            82:        struct vring_desc *desc;
        !            83:        int id, i;
        !            84:        static struct virtio_blk_req blkhdr;
        !            85:        //struct virtio_blk_config *blkconf;
        !            86:        uint64_t capacity;
        !            87:        uint32_t vq_size;
        !            88:        struct vring_desc *vq_desc;             /* Descriptor vring */
        !            89:        struct vring_avail *vq_avail;           /* "Available" vring */
        !            90:        struct vring_used *vq_used;             /* "Used" vring */
        !            91:        volatile uint8_t status = -1;
        !            92:        volatile uint16_t *current_used_idx;
        !            93:        uint16_t last_used_idx;
        !            94: 
        !            95:        //printf("virtioblk_read: dev=%p buf=%p blocknum=%li count=%li\n",
        !            96:        //      dev, buf, blocknum, cnt);
        !            97: 
        !            98:        /* Check whether request is within disk capacity */
        !            99:        capacity = virtio_get_config(dev, 0, sizeof(capacity));
        !           100:        if (blocknum + cnt - 1 > capacity) {
        !           101:                puts("virtioblk_read: Access beyond end of device!");
        !           102:                return 0;
        !           103:        }
        !           104: 
        !           105:        vq_size = virtio_get_qsize(dev, 0);
        !           106:        vq_desc = virtio_get_vring_desc(dev, 0);
        !           107:        vq_avail = virtio_get_vring_avail(dev, 0);
        !           108:        vq_used = virtio_get_vring_used(dev, 0);
        !           109: 
        !           110:        last_used_idx = vq_used->idx;
        !           111:        current_used_idx = &vq_used->idx;
        !           112: 
        !           113:        /* Set up header */
        !           114:        blkhdr.type = VIRTIO_BLK_T_IN | VIRTIO_BLK_T_BARRIER;
        !           115:        blkhdr.ioprio = 1;
        !           116:        blkhdr.sector = blocknum;
        !           117: 
        !           118:        /* Determine descriptor index */
        !           119:        id = (vq_avail->idx * 3) % vq_size;
        !           120: 
        !           121:        /* Set up virtqueue descriptor for header */
        !           122:        desc = &vq_desc[id];
        !           123:        desc->addr = (uint64_t)&blkhdr;
        !           124:        desc->len = sizeof(struct virtio_blk_req);
        !           125:        desc->flags = VRING_DESC_F_NEXT;
        !           126:        desc->next = (id + 1) % vq_size;
        !           127: 
        !           128:        /* Set up virtqueue descriptor for data */
        !           129:        desc = &vq_desc[(id + 1) % vq_size];
        !           130:        desc->addr = (uint64_t)buf;
        !           131:        desc->len = cnt * 512;
        !           132:        desc->flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
        !           133:        desc->next = (id + 2) % vq_size;
        !           134: 
        !           135:        /* Set up virtqueue descriptor for status */
        !           136:        desc = &vq_desc[(id + 2) % vq_size];
        !           137:        desc->addr = (uint64_t)&status;
        !           138:        desc->len = 1;
        !           139:        desc->flags = VRING_DESC_F_WRITE;
        !           140:        desc->next = 0;
        !           141: 
        !           142:        vq_avail->ring[vq_avail->idx % vq_size] = id;
        !           143:        sync();
        !           144:        vq_avail->idx += 1;
        !           145: 
        !           146:        /* Tell HV that the queue is ready */
        !           147:        virtio_queue_notify(dev, 0);
        !           148: 
        !           149:        /* Wait for host to consume the descriptor */
        !           150:        i = 10000000;
        !           151:        while (*current_used_idx == last_used_idx && i-- > 0) {
        !           152:                // do something better
        !           153:                sync();
        !           154:        }
        !           155: 
        !           156:        if (status == 0)
        !           157:                return cnt;
        !           158: 
        !           159:        printf("virtioblk_read failed! status = %i\n", status);
        !           160: 
        !           161:        return 0;
        !           162: }

unix.superglobalmegacorp.com

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