Annotation of qemu/roms/SLOF/lib/libvirtio/virtio.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 <cpu.h>
        !            14: #include <cache.h>
        !            15: #include <byteorder.h>
        !            16: #include "virtio.h"
        !            17: 
        !            18: /* PCI virtio header offsets */
        !            19: #define VIRTIOHDR_DEVICE_FEATURES      0
        !            20: #define VIRTIOHDR_GUEST_FEATURES       4
        !            21: #define VIRTIOHDR_QUEUE_ADDRESS        8
        !            22: #define VIRTIOHDR_QUEUE_SIZE           12
        !            23: #define VIRTIOHDR_QUEUE_SELECT         14
        !            24: #define VIRTIOHDR_QUEUE_NOTIFY         16
        !            25: #define VIRTIOHDR_DEVICE_STATUS        18
        !            26: #define VIRTIOHDR_ISR_STATUS           19
        !            27: #define VIRTIOHDR_DEVICE_CONFIG        20
        !            28: 
        !            29: 
        !            30: /**
        !            31:  * Calculate ring size according to queue size number
        !            32:  */
        !            33: unsigned long virtio_vring_size(unsigned int qsize)
        !            34: {
        !            35:        return VQ_ALIGN(sizeof(struct vring_desc) * qsize + 2 * (2 + qsize))
        !            36:                + VQ_ALIGN(sizeof(struct vring_used_elem) * qsize);
        !            37: }
        !            38: 
        !            39: 
        !            40: /**
        !            41:  * Get number of elements in a vring
        !            42:  * @param   dev  pointer to virtio device information
        !            43:  * @param   queue virtio queue number
        !            44:  * @return  number of elements
        !            45:  */
        !            46: int virtio_get_qsize(struct virtio_device *dev, int queue)
        !            47: {
        !            48:        int size = 0;
        !            49: 
        !            50:        if (dev->type == VIRTIO_TYPE_PCI) {
        !            51:                ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
        !            52:                            cpu_to_le16(queue));
        !            53:                eieio();
        !            54:                size = le16_to_cpu(ci_read_16(dev->base+VIRTIOHDR_QUEUE_SIZE));
        !            55:        }
        !            56: 
        !            57:        return size;
        !            58: }
        !            59: 
        !            60: 
        !            61: /**
        !            62:  * Get address of descriptor vring
        !            63:  * @param   dev  pointer to virtio device information
        !            64:  * @param   queue virtio queue number
        !            65:  * @return  pointer to the descriptor ring
        !            66:  */
        !            67: struct vring_desc *virtio_get_vring_desc(struct virtio_device *dev, int queue)
        !            68: {
        !            69:        struct vring_desc *desc = 0;
        !            70: 
        !            71:        if (dev->type == VIRTIO_TYPE_PCI) {
        !            72:                ci_write_16(dev->base+VIRTIOHDR_QUEUE_SELECT,
        !            73:                            cpu_to_le16(queue));
        !            74:                eieio();
        !            75:                desc = (void*)(4096L *
        !            76:                   le32_to_cpu(ci_read_32(dev->base+VIRTIOHDR_QUEUE_ADDRESS)));
        !            77:        }
        !            78: 
        !            79:        return desc;
        !            80: }
        !            81: 
        !            82: 
        !            83: /**
        !            84:  * Get address of "available" vring
        !            85:  * @param   dev  pointer to virtio device information
        !            86:  * @param   queue virtio queue number
        !            87:  * @return  pointer to the "available" ring
        !            88:  */
        !            89: struct vring_avail *virtio_get_vring_avail(struct virtio_device *dev, int queue)
        !            90: {
        !            91:        return (void*)((uint64_t)virtio_get_vring_desc(dev, queue)
        !            92:                        + virtio_get_qsize(dev, queue) * sizeof(struct vring_desc));
        !            93: }
        !            94: 
        !            95: 
        !            96: /**
        !            97:  * Get address of "used" vring
        !            98:  * @param   dev  pointer to virtio device information
        !            99:  * @param   queue virtio queue number
        !           100:  * @return  pointer to the "used" ring
        !           101:  */
        !           102: struct vring_used *virtio_get_vring_used(struct virtio_device *dev, int queue)
        !           103: {
        !           104:        return (void*)VQ_ALIGN((uint64_t)virtio_get_vring_avail(dev, queue)
        !           105:                                  + virtio_get_qsize(dev, queue)
        !           106:                                    * sizeof(struct vring_avail));
        !           107: }
        !           108: 
        !           109: 
        !           110: /**
        !           111:  * Reset virtio device
        !           112:  */
        !           113: void virtio_reset_device(struct virtio_device *dev)
        !           114: {
        !           115:        if (dev->type == VIRTIO_TYPE_PCI) {
        !           116:                ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, 0);
        !           117:        }
        !           118: }
        !           119: 
        !           120: 
        !           121: /**
        !           122:  * Notify hypervisor about queue update
        !           123:  */
        !           124: void virtio_queue_notify(struct virtio_device *dev, int queue)
        !           125: {
        !           126:        if (dev->type == VIRTIO_TYPE_PCI) {
        !           127:                ci_write_16(dev->base+VIRTIOHDR_QUEUE_NOTIFY, cpu_to_le16(queue));
        !           128:        }
        !           129: }
        !           130: 
        !           131: 
        !           132: /**
        !           133:  * Set device status bits
        !           134:  */
        !           135: void virtio_set_status(struct virtio_device *dev, int status)
        !           136: {
        !           137:        if (dev->type == VIRTIO_TYPE_PCI) {
        !           138:                ci_write_8(dev->base+VIRTIOHDR_DEVICE_STATUS, status);
        !           139:        }
        !           140: }
        !           141: 
        !           142: 
        !           143: /**
        !           144:  * Set guest feature bits
        !           145:  */
        !           146: void virtio_set_guest_features(struct virtio_device *dev, int features)
        !           147: 
        !           148: {
        !           149:        if (dev->type == VIRTIO_TYPE_PCI) {
        !           150:                ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, features);
        !           151:        }
        !           152: }
        !           153: 
        !           154: 
        !           155: /**
        !           156:  * Get additional config values
        !           157:  */
        !           158: uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size)
        !           159: {
        !           160:        uint64_t val = ~0ULL;
        !           161:        void *confbase;
        !           162: 
        !           163:        switch (dev->type) {
        !           164:         case VIRTIO_TYPE_PCI:
        !           165:                confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
        !           166:                break;
        !           167:         default:
        !           168:                return ~0ULL;
        !           169:        }
        !           170:        switch (size) {
        !           171:         case 1:
        !           172:                val = ci_read_8(confbase+offset);
        !           173:                break;
        !           174:         case 2:
        !           175:                val = ci_read_16(confbase+offset);
        !           176:                break;
        !           177:         case 4:
        !           178:                val = ci_read_32(confbase+offset);
        !           179:                break;
        !           180:         case 8:
        !           181:                /* We don't support 8 bytes PIO accesses
        !           182:                 * in qemu and this is all PIO
        !           183:                 */
        !           184:                val = ci_read_32(confbase+offset);
        !           185:                val <<= 32;
        !           186:                val |= ci_read_32(confbase+offset+4);
        !           187:                break;
        !           188:        }
        !           189: 
        !           190:        return val;
        !           191: }
        !           192: 
        !           193: /**
        !           194:  * Get config blob
        !           195:  */
        !           196: int __virtio_read_config(struct virtio_device *dev, void *dst,
        !           197:                          int offset, int len)
        !           198: {
        !           199:        void *confbase;
        !           200:        unsigned char *buf = dst;
        !           201:        int i;
        !           202: 
        !           203:        switch (dev->type) {
        !           204:         case VIRTIO_TYPE_PCI:
        !           205:                confbase = dev->base+VIRTIOHDR_DEVICE_CONFIG;
        !           206:                break;
        !           207:         default:
        !           208:                return 0;
        !           209:        }
        !           210:        for (i = 0; i < len; i++)
        !           211:                buf[i] = ci_read_8(confbase + offset + i);
        !           212:        return len;
        !           213: }

unix.superglobalmegacorp.com

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