4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "virtio_pci.h"
36 #include "virtio_logs.h"
37 #include "virtqueue.h"
40 legacy_read_dev_config(struct virtio_hw *hw, size_t offset,
41 void *dst, int length)
47 off = VIRTIO_PCI_CONFIG(hw) + offset;
48 for (d = dst; length > 0; d += size, off += size, length -= size) {
51 *(uint32_t *)d = VIRTIO_READ_REG_4(hw, off);
52 } else if (length >= 2) {
54 *(uint16_t *)d = VIRTIO_READ_REG_2(hw, off);
57 *d = VIRTIO_READ_REG_1(hw, off);
63 legacy_write_dev_config(struct virtio_hw *hw, size_t offset,
64 const void *src, int length)
70 off = VIRTIO_PCI_CONFIG(hw) + offset;
71 for (s = src; length > 0; s += size, off += size, length -= size) {
74 VIRTIO_WRITE_REG_4(hw, off, *(const uint32_t *)s);
75 } else if (length >= 2) {
77 VIRTIO_WRITE_REG_2(hw, off, *(const uint16_t *)s);
80 VIRTIO_WRITE_REG_1(hw, off, *s);
86 legacy_get_features(struct virtio_hw *hw)
88 return VIRTIO_READ_REG_4(hw, VIRTIO_PCI_HOST_FEATURES);
92 legacy_set_features(struct virtio_hw *hw, uint32_t features)
94 VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
98 legacy_get_status(struct virtio_hw *hw)
100 return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
104 legacy_set_status(struct virtio_hw *hw, uint8_t status)
106 VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
110 legacy_reset(struct virtio_hw *hw)
112 legacy_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
116 legacy_get_isr(struct virtio_hw *hw)
118 return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
121 /* Enable one vector (0) for Link State Intrerrupt */
123 legacy_set_config_irq(struct virtio_hw *hw, uint16_t vec)
125 VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
126 return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
130 legacy_get_queue_num(struct virtio_hw *hw, uint16_t queue_id)
132 VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, queue_id);
133 return VIRTIO_READ_REG_2(hw, VIRTIO_PCI_QUEUE_NUM);
137 legacy_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
139 VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
141 VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN,
142 vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
146 legacy_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
148 VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->vq_queue_index);
150 VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0);
154 legacy_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
156 VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_NOTIFY, vq->vq_queue_index);
160 static const struct virtio_pci_ops legacy_ops = {
161 .read_dev_cfg = legacy_read_dev_config,
162 .write_dev_cfg = legacy_write_dev_config,
163 .reset = legacy_reset,
164 .get_status = legacy_get_status,
165 .set_status = legacy_set_status,
166 .get_features = legacy_get_features,
167 .set_features = legacy_set_features,
168 .get_isr = legacy_get_isr,
169 .set_config_irq = legacy_set_config_irq,
170 .get_queue_num = legacy_get_queue_num,
171 .setup_queue = legacy_setup_queue,
172 .del_queue = legacy_del_queue,
173 .notify_queue = legacy_notify_queue,
178 vtpci_read_dev_config(struct virtio_hw *hw, size_t offset,
179 void *dst, int length)
181 hw->vtpci_ops->read_dev_cfg(hw, offset, dst, length);
185 vtpci_write_dev_config(struct virtio_hw *hw, size_t offset,
186 const void *src, int length)
188 hw->vtpci_ops->write_dev_cfg(hw, offset, src, length);
192 vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features)
197 * Limit negotiated features to what the driver, virtqueue, and
200 features = host_features & hw->guest_features;
201 hw->vtpci_ops->set_features(hw, features);
207 vtpci_reset(struct virtio_hw *hw)
209 hw->vtpci_ops->set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
210 /* flush status write */
211 hw->vtpci_ops->get_status(hw);
215 vtpci_reinit_complete(struct virtio_hw *hw)
217 vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
221 vtpci_set_status(struct virtio_hw *hw, uint8_t status)
223 if (status != VIRTIO_CONFIG_STATUS_RESET)
224 status |= hw->vtpci_ops->get_status(hw);
226 hw->vtpci_ops->set_status(hw, status);
230 vtpci_isr(struct virtio_hw *hw)
232 return hw->vtpci_ops->get_isr(hw);
236 /* Enable one vector (0) for Link State Intrerrupt */
238 vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
240 return hw->vtpci_ops->set_config_irq(hw, vec);
244 vtpci_init(struct rte_pci_device *dev __rte_unused, struct virtio_hw *hw)
246 hw->vtpci_ops = &legacy_ops;