0001
0002
0003 #include "linux/virtio_pci.h"
0004 #include <linux/virtio_pci_legacy.h>
0005 #include <linux/module.h>
0006 #include <linux/pci.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 int vp_legacy_probe(struct virtio_pci_legacy_device *ldev)
0017 {
0018 struct pci_dev *pci_dev = ldev->pci_dev;
0019 int rc;
0020
0021
0022 if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
0023 return -ENODEV;
0024
0025 if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION)
0026 return -ENODEV;
0027
0028 rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64));
0029 if (rc) {
0030 rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
0031 } else {
0032
0033
0034
0035
0036 dma_set_coherent_mask(&pci_dev->dev,
0037 DMA_BIT_MASK(32 + VIRTIO_PCI_QUEUE_ADDR_SHIFT));
0038 }
0039
0040 if (rc)
0041 dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n");
0042
0043 rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy");
0044 if (rc)
0045 return rc;
0046
0047 ldev->ioaddr = pci_iomap(pci_dev, 0, 0);
0048 if (!ldev->ioaddr) {
0049 rc = -EIO;
0050 goto err_iomap;
0051 }
0052
0053 ldev->isr = ldev->ioaddr + VIRTIO_PCI_ISR;
0054
0055 ldev->id.vendor = pci_dev->subsystem_vendor;
0056 ldev->id.device = pci_dev->subsystem_device;
0057
0058 return 0;
0059 err_iomap:
0060 pci_release_region(pci_dev, 0);
0061 return rc;
0062 }
0063 EXPORT_SYMBOL_GPL(vp_legacy_probe);
0064
0065
0066
0067
0068
0069 void vp_legacy_remove(struct virtio_pci_legacy_device *ldev)
0070 {
0071 struct pci_dev *pci_dev = ldev->pci_dev;
0072
0073 pci_iounmap(pci_dev, ldev->ioaddr);
0074 pci_release_region(pci_dev, 0);
0075 }
0076 EXPORT_SYMBOL_GPL(vp_legacy_remove);
0077
0078
0079
0080
0081
0082
0083
0084 u64 vp_legacy_get_features(struct virtio_pci_legacy_device *ldev)
0085 {
0086
0087 return ioread32(ldev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
0088 }
0089 EXPORT_SYMBOL_GPL(vp_legacy_get_features);
0090
0091
0092
0093
0094
0095
0096
0097 u64 vp_legacy_get_driver_features(struct virtio_pci_legacy_device *ldev)
0098 {
0099 return ioread32(ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
0100 }
0101 EXPORT_SYMBOL_GPL(vp_legacy_get_driver_features);
0102
0103
0104
0105
0106
0107
0108 void vp_legacy_set_features(struct virtio_pci_legacy_device *ldev,
0109 u32 features)
0110 {
0111 iowrite32(features, ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
0112 }
0113 EXPORT_SYMBOL_GPL(vp_legacy_set_features);
0114
0115
0116
0117
0118
0119
0120
0121 u8 vp_legacy_get_status(struct virtio_pci_legacy_device *ldev)
0122 {
0123 return ioread8(ldev->ioaddr + VIRTIO_PCI_STATUS);
0124 }
0125 EXPORT_SYMBOL_GPL(vp_legacy_get_status);
0126
0127
0128
0129
0130
0131
0132 void vp_legacy_set_status(struct virtio_pci_legacy_device *ldev,
0133 u8 status)
0134 {
0135 iowrite8(status, ldev->ioaddr + VIRTIO_PCI_STATUS);
0136 }
0137 EXPORT_SYMBOL_GPL(vp_legacy_set_status);
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 u16 vp_legacy_queue_vector(struct virtio_pci_legacy_device *ldev,
0148 u16 index, u16 vector)
0149 {
0150 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0151 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
0152
0153 return ioread16(ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
0154 }
0155 EXPORT_SYMBOL_GPL(vp_legacy_queue_vector);
0156
0157
0158
0159
0160
0161
0162
0163
0164 u16 vp_legacy_config_vector(struct virtio_pci_legacy_device *ldev,
0165 u16 vector)
0166 {
0167
0168 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
0169
0170
0171 return ioread16(ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
0172 }
0173 EXPORT_SYMBOL_GPL(vp_legacy_config_vector);
0174
0175
0176
0177
0178
0179
0180
0181 void vp_legacy_set_queue_address(struct virtio_pci_legacy_device *ldev,
0182 u16 index, u32 queue_pfn)
0183 {
0184 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0185 iowrite32(queue_pfn, ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
0186 }
0187 EXPORT_SYMBOL_GPL(vp_legacy_set_queue_address);
0188
0189
0190
0191
0192
0193
0194
0195
0196 bool vp_legacy_get_queue_enable(struct virtio_pci_legacy_device *ldev,
0197 u16 index)
0198 {
0199 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0200 return ioread32(ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
0201 }
0202 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_enable);
0203
0204
0205
0206
0207
0208
0209
0210
0211 u16 vp_legacy_get_queue_size(struct virtio_pci_legacy_device *ldev,
0212 u16 index)
0213 {
0214 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0215 return ioread16(ldev->ioaddr + VIRTIO_PCI_QUEUE_NUM);
0216 }
0217 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_size);
0218
0219 MODULE_VERSION("0.1");
0220 MODULE_DESCRIPTION("Legacy Virtio PCI Device");
0221 MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>");
0222 MODULE_LICENSE("GPL");