Subversion Repositories Kolibri OS

Rev

Rev 1628 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1628 Rev 1633
1
#include 
1
#include 
2
#include 
2
#include 
3
#include 
3
#include 
4
#include 
4
#include 
5
#include 
5
#include 
6
 
6
 
7
#include "acpi.h"
7
#include "acpi.h"
8
#include "acpi_bus.h"
8
#include "acpi_bus.h"
9
 
9
 
10
 
10
 
11
#define PREFIX "ACPI: "
11
#define PREFIX "ACPI: "
12
 
12
 
13
 
13
 
14
struct acpi_handle_node {
14
struct acpi_handle_node {
15
    struct list_head node;
15
    struct list_head node;
16
    ACPI_HANDLE handle;
16
    ACPI_HANDLE handle;
17
};
17
};
18
 
18
 
19
static const struct acpi_device_ids root_device_ids[] = {
19
static const struct acpi_device_ids root_device_ids[] = {
20
    {"PNP0A03", 0},
20
    {"PNP0A03", 0},
21
    {"", 0},
21
    {"", 0},
22
};
22
};
23
 
23
 
24
static LIST_HEAD(acpi_pci_roots);
24
LIST_HEAD(acpi_pci_roots);
25
 
25
 
26
 
26
 
27
/**
27
/**
28
 * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
28
 * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
29
 * @handle - the ACPI CA node in question.
29
 * @handle - the ACPI CA node in question.
30
 *
30
 *
31
 * Note: we could make this API take a struct acpi_device * instead, but
31
 * Note: we could make this API take a struct acpi_device * instead, but
32
 * for now, it's more convenient to operate on an acpi_handle.
32
 * for now, it's more convenient to operate on an acpi_handle.
33
 */
33
 */
34
int acpi_is_root_bridge(ACPI_HANDLE handle)
34
int acpi_is_root_bridge(ACPI_HANDLE handle)
35
{
35
{
36
    int ret;
36
    int ret;
37
    struct acpi_device *device;
37
    struct acpi_device *device;
38
 
38
 
39
    ret = acpi_bus_get_device(handle, &device);
39
    ret = acpi_bus_get_device(handle, &device);
40
    if (ret)
40
    if (ret)
41
        return 0;
41
        return 0;
42
 
42
 
43
    ret = acpi_match_device_ids(device, root_device_ids);
43
    ret = acpi_match_device_ids(device, root_device_ids);
44
    if (ret)
44
    if (ret)
45
        return 0;
45
        return 0;
46
    else
46
    else
47
        return 1;
47
        return 1;
48
}
48
}
49
 
49
 
50
 
50
 
51
struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle)
51
struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle)
52
{
52
{
53
    struct acpi_pci_root *root;
53
    struct acpi_pci_root *root;
54
 
54
 
55
    list_for_each_entry(root, &acpi_pci_roots, node) {
55
    list_for_each_entry(root, &acpi_pci_roots, node) {
56
        if (root->device->handle == handle)
56
        if (root->device->handle == handle)
57
            return root;
57
            return root;
58
    }
58
    }
59
    return NULL;
59
    return NULL;
60
}
60
}
61
 
61
 
62
 
62
 
63
/**
63
/**
64
 * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
64
 * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
65
 * @handle: the handle in question
65
 * @handle: the handle in question
66
 *
66
 *
67
 * Given an ACPI CA handle, the desired PCI device is located in the
67
 * Given an ACPI CA handle, the desired PCI device is located in the
68
 * list of PCI devices.
68
 * list of PCI devices.
69
 *
69
 *
70
 * If the device is found, its reference count is increased and this
70
 * If the device is found, its reference count is increased and this
71
 * function returns a pointer to its data structure.  The caller must
71
 * function returns a pointer to its data structure.  The caller must
72
 * decrement the reference count by calling pci_dev_put().
72
 * decrement the reference count by calling pci_dev_put().
73
 * If no device is found, %NULL is returned.
73
 * If no device is found, %NULL is returned.
74
 */
74
 */
75
struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle)
75
struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle)
76
{
76
{
77
    int dev, fn;
77
    int dev, fn;
78
    unsigned long long adr;
78
    unsigned long long adr;
79
    ACPI_STATUS status;
79
    ACPI_STATUS status;
80
    ACPI_HANDLE phandle;
80
    ACPI_HANDLE phandle;
81
    struct pci_bus *pbus;
81
    struct pci_bus *pbus;
82
    struct pci_dev *pdev = NULL;
82
    struct pci_dev *pdev = NULL;
83
    struct acpi_handle_node *node, *tmp;
83
    struct acpi_handle_node *node, *tmp;
84
    struct acpi_pci_root *root;
84
    struct acpi_pci_root *root;
85
    LIST_HEAD(device_list);
85
    LIST_HEAD(device_list);
86
 
86
 
87
    /*
87
    /*
88
     * Walk up the ACPI CA namespace until we reach a PCI root bridge.
88
     * Walk up the ACPI CA namespace until we reach a PCI root bridge.
89
     */
89
     */
90
    phandle = handle;
90
    phandle = handle;
91
    while (!acpi_is_root_bridge(phandle)) {
91
    while (!acpi_is_root_bridge(phandle)) {
92
        node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
92
        node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
93
        if (!node)
93
        if (!node)
94
            goto out;
94
            goto out;
95
 
95
 
96
        INIT_LIST_HEAD(&node->node);
96
        INIT_LIST_HEAD(&node->node);
97
        node->handle = phandle;
97
        node->handle = phandle;
98
        list_add(&node->node, &device_list);
98
        list_add(&node->node, &device_list);
99
 
99
 
100
        status = AcpiGetParent(phandle, &phandle);
100
        status = AcpiGetParent(phandle, &phandle);
101
        if (ACPI_FAILURE(status))
101
        if (ACPI_FAILURE(status))
102
            goto out;
102
            goto out;
103
    }
103
    }
104
 
104
 
105
    root = acpi_pci_find_root(phandle);
105
    root = acpi_pci_find_root(phandle);
106
    if (!root)
106
    if (!root)
107
        goto out;
107
        goto out;
108
 
108
 
109
    pbus = root->bus;
109
    pbus = root->bus;
110
 
110
 
111
    /*
111
    /*
112
     * Now, walk back down the PCI device tree until we return to our
112
     * Now, walk back down the PCI device tree until we return to our
113
     * original handle. Assumes that everything between the PCI root
113
     * original handle. Assumes that everything between the PCI root
114
     * bridge and the device we're looking for must be a P2P bridge.
114
     * bridge and the device we're looking for must be a P2P bridge.
115
     */
115
     */
116
    list_for_each_entry(node, &device_list, node) {
116
    list_for_each_entry(node, &device_list, node) {
117
        ACPI_HANDLE hnd = node->handle;
117
        ACPI_HANDLE hnd = node->handle;
118
        status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
118
        status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
119
        if (ACPI_FAILURE(status))
119
        if (ACPI_FAILURE(status))
120
            goto out;
120
            goto out;
121
        dev = (adr >> 16) & 0xffff;
121
        dev = (adr >> 16) & 0xffff;
122
        fn  = adr & 0xffff;
122
        fn  = adr & 0xffff;
123
 
123
 
124
        pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
124
        pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
125
        if (!pdev || hnd == handle)
125
        if (!pdev || hnd == handle)
126
            break;
126
            break;
127
 
127
 
128
        pbus = pdev->subordinate;
128
        pbus = pdev->subordinate;
129
//        pci_dev_put(pdev);
129
//        pci_dev_put(pdev);
130
 
130
 
131
        /*
131
        /*
132
         * This function may be called for a non-PCI device that has a
132
         * This function may be called for a non-PCI device that has a
133
         * PCI parent (eg. a disk under a PCI SATA controller).  In that
133
         * PCI parent (eg. a disk under a PCI SATA controller).  In that
134
         * case pdev->subordinate will be NULL for the parent.
134
         * case pdev->subordinate will be NULL for the parent.
135
         */
135
         */
136
        if (!pbus) {
136
        if (!pbus) {
137
            dbgprintf("Not a PCI-to-PCI bridge\n");
137
            dbgprintf("Not a PCI-to-PCI bridge\n");
138
            pdev = NULL;
138
            pdev = NULL;
139
            break;
139
            break;
140
        }
140
        }
141
    }
141
    }
142
out:
142
out:
143
    list_for_each_entry_safe(node, tmp, &device_list, node)
143
    list_for_each_entry_safe(node, tmp, &device_list, node)
144
        kfree(node);
144
        kfree(node);
145
 
145
 
146
    return pdev;
146
    return pdev;
147
}
147
}
148
148
 
-
 
149
 
-
 
150
static void print_bus_irqs(struct pci_bus *bus)
-
 
151
{
-
 
152
    struct pci_dev *dev;
-
 
153
 
-
 
154
    list_for_each_entry(dev, &bus->devices, bus_list)
-
 
155
    {
-
 
156
        dbgprintf("PCI_%x_%x bus:%d devfn: %x bios irq %d acpi irq %d\n",
-
 
157
                   dev->vendor, dev->device, dev->busnr, dev->devfn,
-
 
158
                   dev->irq, acpi_get_irq(dev));
-
 
159
    };
-
 
160
}
-
 
161
 
-
 
162
void print_pci_irqs()
-
 
163
{
-
 
164
    struct acpi_pci_root *root;
-
 
165
 
-
 
166
    ENTER();
-
 
167
    list_for_each_entry(root, &acpi_pci_roots, node)
-
 
168
    {
-
 
169
        struct pci_bus *pbus, *tbus;
-
 
170
        struct pci_dev *dev;
-
 
171
 
-
 
172
        pbus = root->bus;
-
 
173
 
-
 
174
        list_for_each_entry(dev, &pbus->devices, bus_list)
-
 
175
        {
-
 
176
            dbgprintf("PCI_%x_%x bus:%d devfn: %x bios irq %d acpi irq %d\n",
-
 
177
                      dev->vendor, dev->device, dev->busnr, dev->devfn,
-
 
178
                      dev->irq, acpi_get_irq(dev));
-
 
179
        };
-
 
180
 
-
 
181
        list_for_each_entry(tbus, &pbus->children, node)
-
 
182
        {
-
 
183
            print_bus_irqs(tbus);
-
 
184
        };
-
 
185
    }
-
 
186
    LEAVE();
-
 
187
};
-
 
188
-
 
189