Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 6ccc424 in mainline


Ignore:
Timestamp:
2018-05-22T19:06:50Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
a86174ec
Parents:
00192cd
git-author:
Jakub Jermar <jakub@…> (2018-04-21 22:14:00)
git-committer:
Jakub Jermar <jakub@…> (2018-05-22 19:06:50)
Message:

Process VIRTIO PCI configuration structures

Location:
uspace/lib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/include/pci_dev_iface.h

    r00192cd r6ccc424  
    4545#define PCI_SUB_CLASS   0x0A
    4646#define PCI_BASE_CLASS  0x0B
     47#define PCI_BAR0        0x10
    4748#define PCI_CAP_PTR     0x34
     49
     50#define PCI_BAR_COUNT   6
    4851
    4952#define PCI_STATUS_CAP_LIST     (1 << 4)
  • uspace/lib/virtio/virtio-pci.c

    r00192cd r6ccc424  
    3333
    3434#include <ddf/driver.h>
     35#include <ddf/log.h>
    3536#include <pci_dev_iface.h>
    3637
    37 static void virtio_pci_common_cfg(virtio_dev_t *vdev, hw_resource_list_t *res,
    38     uint8_t bar, uint32_t offset, uint32_t length)
    39 {
    40         /* Proceed only if we don't have common config structure yet */
     38static bool check_bar(virtio_dev_t *vdev, uint8_t bar)
     39{
     40        /* We must ignore the capability if bar is greater than 5 */
     41        if (bar >= PCI_BAR_COUNT)
     42                return false;
     43
     44        /* This is not a mapped BAR */
     45        if (!vdev->bar[bar].mapped)
     46                return false;
     47
     48        return true;
     49}
     50
     51static void virtio_pci_common_cfg(virtio_dev_t *vdev, uint8_t bar,
     52    uint32_t offset, uint32_t length)
     53{
    4154        if (vdev->common_cfg)
    4255                return;
    4356
    44         /* We must ignore the capability if bar is greater than 5 */
    45         if (bar > 5)
    46                 return;
     57        if (!check_bar(vdev, bar))
     58                return;
     59
     60        vdev->common_cfg = vdev->bar[bar].mapped_base + offset;
     61
     62        ddf_msg(LVL_NOTE, "common_cfg=%p", vdev->common_cfg);
     63}
     64
     65static void virtio_pci_notify_cfg(virtio_dev_t *vdev, uint8_t bar,
     66    uint32_t offset, uint32_t length, uint32_t multiplier)
     67{
     68        if (vdev->notify_base)
     69                return;
     70
     71        if (!check_bar(vdev, bar))
     72                return;
     73
     74        vdev->notify_base = vdev->bar[bar].mapped_base + offset;
     75        vdev->notify_off_multiplier = multiplier;
     76
     77        ddf_msg(LVL_NOTE, "notify_base=%p, off_multiplier=%u",
     78            vdev->notify_base, vdev->notify_off_multiplier);
     79}
     80
     81static void virtio_pci_isr_cfg(virtio_dev_t *vdev, uint8_t bar, uint32_t offset,
     82    uint32_t length)
     83{
     84        if (vdev->isr)
     85                return;
     86
     87        if (!check_bar(vdev, bar))
     88                return;
     89
     90        vdev->isr = vdev->bar[bar].mapped_base + offset;
     91
     92        ddf_msg(LVL_NOTE, "isr=%p", vdev->isr);
     93}
     94
     95static void virtio_pci_device_cfg(virtio_dev_t *vdev, uint8_t bar,
     96    uint32_t offset, uint32_t length)
     97{
     98        if (vdev->device_cfg)
     99                return;
     100
     101        if (!check_bar(vdev, bar))
     102                return;
     103
     104        vdev->device_cfg = vdev->bar[bar].mapped_base + offset;
     105
     106        ddf_msg(LVL_NOTE, "device_cfg=%p", vdev->device_cfg);
    47107}
    48108
    49109errno_t virtio_pci_dev_init(ddf_dev_t *dev, virtio_dev_t *vdev)
    50110{
     111        memset(vdev, 0, sizeof(virtio_dev_t));
     112
    51113        async_sess_t *pci_sess = ddf_dev_parent_sess_get(dev);
    52114        if (!pci_sess)
    53115                return ENOENT;
    54116
    55         errno_t rc;
     117        pio_window_t pio_window;
     118        errno_t rc = pio_window_get(pci_sess, &pio_window);
     119        if (rc != EOK)
     120                return rc;
     121
    56122        hw_resource_list_t hw_res;
    57123        rc = hw_res_get_resource_list(pci_sess, &hw_res);
    58124        if (rc != EOK)
    59125                return rc;
     126
     127        /*
     128         * Enable resources and reconstruct the mapping between BAR and resource
     129         * indices. We are going to need this later when the VIRTIO PCI
     130         * capabilities refer to specific BARs.
     131         *
     132         * XXX: The mapping should probably be provided by the PCI driver
     133         *      itself.
     134         */
     135        for (unsigned i = 0, j = 0; i < PCI_BAR_COUNT && j < hw_res.count;
     136            i++) {
     137                /* Detect and skip unused BARs */
     138                uint32_t bar;
     139                rc = pci_config_space_read_32(pci_sess,
     140                    PCI_BAR0 + i * sizeof(uint32_t), &bar);
     141                if (!bar)
     142                        continue;
     143
     144                rc = pio_enable_resource(&pio_window, &hw_res.resources[j],
     145                    &vdev->bar[i].mapped_base);
     146                if (rc == EOK)
     147                        vdev->bar[i].mapped = true;
     148                j++;
     149        }
    60150
    61151        /*
     
    92182                                return rc;
    93183
     184                        uint32_t multiplier;
    94185                        switch (type) {
    95186                        case VIRTIO_PCI_CAP_COMMON_CFG:
    96                                 virtio_pci_common_cfg(vdev, &hw_res, bar,
    97                                     offset, length);
     187                                virtio_pci_common_cfg(vdev, bar, offset,
     188                                    length);
    98189                                break;
    99190                        case VIRTIO_PCI_CAP_NOTIFY_CFG:
     191                                rc = pci_config_space_read_32(pci_sess,
     192                                    VIRTIO_PCI_CAP_END(c), &multiplier);
     193                                if (rc != EOK)
     194                                        return rc;
     195                                virtio_pci_notify_cfg(vdev, bar, offset, length,
     196                                    multiplier);
    100197                                break;
    101198                        case VIRTIO_PCI_CAP_ISR_CFG:
     199                                virtio_pci_isr_cfg(vdev, bar, offset, length);
    102200                                break;
    103201                        case VIRTIO_PCI_CAP_DEVICE_CFG:
     202                                virtio_pci_device_cfg(vdev, bar, offset,
     203                                    length);
    104204                                break;
    105205                        case VIRTIO_PCI_CAP_PCI_CFG:
  • uspace/lib/virtio/virtio-pci.h

    r00192cd r6ccc424  
    3434
    3535#include <ddf/driver.h>
     36#include <pci_dev_iface.h>
    3637#include <ddi.h>
    3738
     
    4041#define VIRTIO_PCI_CAP_OFFSET(c)        ((c) + 8)
    4142#define VIRTIO_PCI_CAP_LENGTH(c)        ((c) + 12)
     43#define VIRTIO_PCI_CAP_END(c)           ((c) + 16)
    4244
    4345#define VIRTIO_PCI_CAP_COMMON_CFG       1
     
    6870
    6971typedef struct {
     72        struct {
     73                bool mapped;
     74                void *mapped_base;
     75        } bar[PCI_BAR_COUNT];
     76
     77        /** Commong configuration structure */
    7078        virtio_pci_common_cfg_t *common_cfg;
     79
     80        /** Notification base address */
     81        ioport8_t *notify_base;
     82        /** Notification offset multiplier */
     83        uint32_t notify_off_multiplier;
     84
     85        /** INT#x interrupt ISR register */
     86        ioport8_t *isr;
     87
     88        /** Device-specific configuration */
     89        void *device_cfg;
    7190} virtio_dev_t;
    7291
Note: See TracChangeset for help on using the changeset viewer.