Revision 6f4cbd39 hw/pci.c

b/hw/pci.c
164 164
    if (version_id >= 2)
165 165
        for (i = 0; i < 4; i ++)
166 166
            s->irq_state[i] = qemu_get_be32(f);
167

  
168 167
    return 0;
169 168
}
170 169

  
......
895 894

  
896 895
    return (PCIDevice *)dev;
897 896
}
897

  
898
static int pci_find_space(PCIDevice *pdev, uint8_t size)
899
{
900
    int offset = PCI_CONFIG_HEADER_SIZE;
901
    int i;
902
    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
903
        if (pdev->used[i])
904
            offset = i + 1;
905
        else if (i - offset + 1 == size)
906
            return offset;
907
    return 0;
908
}
909

  
910
static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id,
911
                                        uint8_t *prev_p)
912
{
913
    uint8_t next, prev;
914

  
915
    if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST))
916
        return 0;
917

  
918
    for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]);
919
         prev = next + PCI_CAP_LIST_NEXT)
920
        if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id)
921
            break;
922

  
923
    if (prev_p)
924
        *prev_p = prev;
925
    return next;
926
}
927

  
928
/* Reserve space and add capability to the linked list in pci config space */
929
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
930
{
931
    uint8_t offset = pci_find_space(pdev, size);
932
    uint8_t *config = pdev->config + offset;
933
    if (!offset)
934
        return -ENOSPC;
935
    config[PCI_CAP_LIST_ID] = cap_id;
936
    config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
937
    pdev->config[PCI_CAPABILITY_LIST] = offset;
938
    pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
939
    memset(pdev->used + offset, 0xFF, size);
940
    /* Make capability read-only by default */
941
    memset(pdev->wmask + offset, 0, size);
942
    return offset;
943
}
944

  
945
/* Unlink capability from the pci config space. */
946
void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
947
{
948
    uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev);
949
    if (!offset)
950
        return;
951
    pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT];
952
    /* Make capability writeable again */
953
    memset(pdev->wmask + offset, 0xff, size);
954
    memset(pdev->used + offset, 0, size);
955

  
956
    if (!pdev->config[PCI_CAPABILITY_LIST])
957
        pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST;
958
}
959

  
960
/* Reserve space for capability at a known offset (to call after load). */
961
void pci_reserve_capability(PCIDevice *pdev, uint8_t offset, uint8_t size)
962
{
963
    memset(pdev->used + offset, 0xff, size);
964
}
965

  
966
uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id)
967
{
968
    return pci_find_capability_list(pdev, cap_id, NULL);
969
}

Also available in: Unified diff