1*6c3169a3SBruce Richardson /*- 2*6c3169a3SBruce Richardson * BSD LICENSE 3*6c3169a3SBruce Richardson * 4*6c3169a3SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5*6c3169a3SBruce Richardson * All rights reserved. 6*6c3169a3SBruce Richardson * 7*6c3169a3SBruce Richardson * Redistribution and use in source and binary forms, with or without 8*6c3169a3SBruce Richardson * modification, are permitted provided that the following conditions 9*6c3169a3SBruce Richardson * are met: 10*6c3169a3SBruce Richardson * 11*6c3169a3SBruce Richardson * * Redistributions of source code must retain the above copyright 12*6c3169a3SBruce Richardson * notice, this list of conditions and the following disclaimer. 13*6c3169a3SBruce Richardson * * Redistributions in binary form must reproduce the above copyright 14*6c3169a3SBruce Richardson * notice, this list of conditions and the following disclaimer in 15*6c3169a3SBruce Richardson * the documentation and/or other materials provided with the 16*6c3169a3SBruce Richardson * distribution. 17*6c3169a3SBruce Richardson * * Neither the name of Intel Corporation nor the names of its 18*6c3169a3SBruce Richardson * contributors may be used to endorse or promote products derived 19*6c3169a3SBruce Richardson * from this software without specific prior written permission. 20*6c3169a3SBruce Richardson * 21*6c3169a3SBruce Richardson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*6c3169a3SBruce Richardson * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*6c3169a3SBruce Richardson * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*6c3169a3SBruce Richardson * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*6c3169a3SBruce Richardson * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*6c3169a3SBruce Richardson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*6c3169a3SBruce Richardson * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*6c3169a3SBruce Richardson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*6c3169a3SBruce Richardson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*6c3169a3SBruce Richardson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*6c3169a3SBruce Richardson * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*6c3169a3SBruce Richardson */ 33*6c3169a3SBruce Richardson #include <stdint.h> 34*6c3169a3SBruce Richardson 35*6c3169a3SBruce Richardson #include "virtio_pci.h" 36*6c3169a3SBruce Richardson #include "virtio_logs.h" 37*6c3169a3SBruce Richardson 38*6c3169a3SBruce Richardson static uint8_t vtpci_get_status(struct virtio_hw *); 39*6c3169a3SBruce Richardson 40*6c3169a3SBruce Richardson void 41*6c3169a3SBruce Richardson vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset, 42*6c3169a3SBruce Richardson void *dst, int length) 43*6c3169a3SBruce Richardson { 44*6c3169a3SBruce Richardson uint64_t off; 45*6c3169a3SBruce Richardson uint8_t *d; 46*6c3169a3SBruce Richardson int size; 47*6c3169a3SBruce Richardson 48*6c3169a3SBruce Richardson off = VIRTIO_PCI_CONFIG(hw) + offset; 49*6c3169a3SBruce Richardson for (d = dst; length > 0; d += size, off += size, length -= size) { 50*6c3169a3SBruce Richardson if (length >= 4) { 51*6c3169a3SBruce Richardson size = 4; 52*6c3169a3SBruce Richardson *(uint32_t *)d = VIRTIO_READ_REG_4(hw, off); 53*6c3169a3SBruce Richardson } else if (length >= 2) { 54*6c3169a3SBruce Richardson size = 2; 55*6c3169a3SBruce Richardson *(uint16_t *)d = VIRTIO_READ_REG_2(hw, off); 56*6c3169a3SBruce Richardson } else { 57*6c3169a3SBruce Richardson size = 1; 58*6c3169a3SBruce Richardson *d = VIRTIO_READ_REG_1(hw, off); 59*6c3169a3SBruce Richardson } 60*6c3169a3SBruce Richardson } 61*6c3169a3SBruce Richardson } 62*6c3169a3SBruce Richardson 63*6c3169a3SBruce Richardson void 64*6c3169a3SBruce Richardson vtpci_write_dev_config(struct virtio_hw *hw, uint64_t offset, 65*6c3169a3SBruce Richardson void *src, int length) 66*6c3169a3SBruce Richardson { 67*6c3169a3SBruce Richardson uint64_t off; 68*6c3169a3SBruce Richardson uint8_t *s; 69*6c3169a3SBruce Richardson int size; 70*6c3169a3SBruce Richardson 71*6c3169a3SBruce Richardson off = VIRTIO_PCI_CONFIG(hw) + offset; 72*6c3169a3SBruce Richardson for (s = src; length > 0; s += size, off += size, length -= size) { 73*6c3169a3SBruce Richardson if (length >= 4) { 74*6c3169a3SBruce Richardson size = 4; 75*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_4(hw, off, *(uint32_t *)s); 76*6c3169a3SBruce Richardson } else if (length >= 2) { 77*6c3169a3SBruce Richardson size = 2; 78*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_2(hw, off, *(uint16_t *)s); 79*6c3169a3SBruce Richardson } else { 80*6c3169a3SBruce Richardson size = 1; 81*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_1(hw, off, *s); 82*6c3169a3SBruce Richardson } 83*6c3169a3SBruce Richardson } 84*6c3169a3SBruce Richardson } 85*6c3169a3SBruce Richardson 86*6c3169a3SBruce Richardson uint32_t 87*6c3169a3SBruce Richardson vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features) 88*6c3169a3SBruce Richardson { 89*6c3169a3SBruce Richardson uint32_t features; 90*6c3169a3SBruce Richardson /* 91*6c3169a3SBruce Richardson * Limit negotiated features to what the driver, virtqueue, and 92*6c3169a3SBruce Richardson * host all support. 93*6c3169a3SBruce Richardson */ 94*6c3169a3SBruce Richardson features = host_features & hw->guest_features; 95*6c3169a3SBruce Richardson 96*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features); 97*6c3169a3SBruce Richardson return features; 98*6c3169a3SBruce Richardson } 99*6c3169a3SBruce Richardson 100*6c3169a3SBruce Richardson 101*6c3169a3SBruce Richardson void 102*6c3169a3SBruce Richardson vtpci_reset(struct virtio_hw *hw) 103*6c3169a3SBruce Richardson { 104*6c3169a3SBruce Richardson /* 105*6c3169a3SBruce Richardson * Setting the status to RESET sets the host device to 106*6c3169a3SBruce Richardson * the original, uninitialized state. 107*6c3169a3SBruce Richardson */ 108*6c3169a3SBruce Richardson vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_RESET); 109*6c3169a3SBruce Richardson vtpci_get_status(hw); 110*6c3169a3SBruce Richardson } 111*6c3169a3SBruce Richardson 112*6c3169a3SBruce Richardson void 113*6c3169a3SBruce Richardson vtpci_reinit_complete(struct virtio_hw *hw) 114*6c3169a3SBruce Richardson { 115*6c3169a3SBruce Richardson vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK); 116*6c3169a3SBruce Richardson } 117*6c3169a3SBruce Richardson 118*6c3169a3SBruce Richardson static uint8_t 119*6c3169a3SBruce Richardson vtpci_get_status(struct virtio_hw *hw) 120*6c3169a3SBruce Richardson { 121*6c3169a3SBruce Richardson return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS); 122*6c3169a3SBruce Richardson } 123*6c3169a3SBruce Richardson 124*6c3169a3SBruce Richardson void 125*6c3169a3SBruce Richardson vtpci_set_status(struct virtio_hw *hw, uint8_t status) 126*6c3169a3SBruce Richardson { 127*6c3169a3SBruce Richardson if (status != VIRTIO_CONFIG_STATUS_RESET) 128*6c3169a3SBruce Richardson status = (uint8_t)(status | vtpci_get_status(hw)); 129*6c3169a3SBruce Richardson 130*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status); 131*6c3169a3SBruce Richardson } 132*6c3169a3SBruce Richardson 133*6c3169a3SBruce Richardson uint8_t 134*6c3169a3SBruce Richardson vtpci_isr(struct virtio_hw *hw) 135*6c3169a3SBruce Richardson { 136*6c3169a3SBruce Richardson 137*6c3169a3SBruce Richardson return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR); 138*6c3169a3SBruce Richardson } 139*6c3169a3SBruce Richardson 140*6c3169a3SBruce Richardson 141*6c3169a3SBruce Richardson /* Enable one vector (0) for Link State Intrerrupt */ 142*6c3169a3SBruce Richardson uint16_t 143*6c3169a3SBruce Richardson vtpci_irq_config(struct virtio_hw *hw, uint16_t vec) 144*6c3169a3SBruce Richardson { 145*6c3169a3SBruce Richardson VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec); 146*6c3169a3SBruce Richardson return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR); 147*6c3169a3SBruce Richardson } 148