~ubuntu-branches/ubuntu/oneiric/seabios/oneiric

« back to all changes in this revision

Viewing changes to .pc/0052-seabios-pci-introduce-helper-function-to-initialize-.patch/src/pci.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-10-22 11:04:31 UTC
  • Revision ID: james.westby@ubuntu.com-20101022110431-fnfj73ra6xkq623n
Tags: 0.6.0-0ubuntu2
Add all patches which were included in qemu-0.13.0-rc2 (per
commit on Jul 13, 2010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// PCI config space access functions.
 
2
//
 
3
// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 
4
// Copyright (C) 2002  MandrakeSoft S.A.
 
5
//
 
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
 
7
 
 
8
#include "pci.h" // pci_config_writel
 
9
#include "ioport.h" // outl
 
10
#include "util.h" // dprintf
 
11
#include "config.h" // CONFIG_*
 
12
#include "pci_regs.h" // PCI_VENDOR_ID
 
13
#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
 
14
 
 
15
void pci_config_writel(u16 bdf, u32 addr, u32 val)
 
16
{
 
17
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
18
    outl(val, PORT_PCI_DATA);
 
19
}
 
20
 
 
21
void pci_config_writew(u16 bdf, u32 addr, u16 val)
 
22
{
 
23
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
24
    outw(val, PORT_PCI_DATA + (addr & 2));
 
25
}
 
26
 
 
27
void pci_config_writeb(u16 bdf, u32 addr, u8 val)
 
28
{
 
29
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
30
    outb(val, PORT_PCI_DATA + (addr & 3));
 
31
}
 
32
 
 
33
u32 pci_config_readl(u16 bdf, u32 addr)
 
34
{
 
35
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
36
    return inl(PORT_PCI_DATA);
 
37
}
 
38
 
 
39
u16 pci_config_readw(u16 bdf, u32 addr)
 
40
{
 
41
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
42
    return inw(PORT_PCI_DATA + (addr & 2));
 
43
}
 
44
 
 
45
u8 pci_config_readb(u16 bdf, u32 addr)
 
46
{
 
47
    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
 
48
    return inb(PORT_PCI_DATA + (addr & 3));
 
49
}
 
50
 
 
51
void
 
52
pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
 
53
{
 
54
    u16 val = pci_config_readw(bdf, addr);
 
55
    val = (val & ~off) | on;
 
56
    pci_config_writew(bdf, addr, val);
 
57
}
 
58
 
 
59
// Helper function for foreachpci() macro - return next device
 
60
int
 
61
pci_next(int bdf, int *pmax)
 
62
{
 
63
    if (pci_bdf_to_fn(bdf) == 1
 
64
        && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
 
65
        // Last found device wasn't a multi-function device - skip to
 
66
        // the next device.
 
67
        bdf += 7;
 
68
 
 
69
    int max = *pmax;
 
70
    for (;;) {
 
71
        if (bdf >= max) {
 
72
            if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
 
73
                bdf = CONFIG_PCI_ROOT1 << 8;
 
74
            else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
 
75
                bdf = CONFIG_PCI_ROOT2 << 8;
 
76
            else
 
77
                return -1;
 
78
            *pmax = max = bdf + 0x0100;
 
79
        }
 
80
 
 
81
        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
 
82
        if (v != 0x0000 && v != 0xffff)
 
83
            // Device is present.
 
84
            break;
 
85
 
 
86
        if (pci_bdf_to_fn(bdf) == 0)
 
87
            bdf += 8;
 
88
        else
 
89
            bdf += 1;
 
90
    }
 
91
 
 
92
    // Check if found device is a bridge.
 
93
    u32 v = pci_config_readb(bdf, PCI_HEADER_TYPE);
 
94
    v &= 0x7f;
 
95
    if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
 
96
        v = pci_config_readl(bdf, PCI_PRIMARY_BUS);
 
97
        int newmax = (v & 0xff00) + 0x0100;
 
98
        if (newmax > max)
 
99
            *pmax = newmax;
 
100
    }
 
101
 
 
102
    return bdf;
 
103
}
 
104
 
 
105
// Find a vga device with legacy address decoding enabled.
 
106
int
 
107
pci_find_vga(void)
 
108
{
 
109
    int bdf = 0x0000, max = 0x0100;
 
110
    for (;;) {
 
111
        if (bdf >= max) {
 
112
            if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
 
113
                bdf = CONFIG_PCI_ROOT1 << 8;
 
114
            else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
 
115
                bdf = CONFIG_PCI_ROOT2 << 8;
 
116
            else
 
117
                return -1;
 
118
            max = bdf + 0x0100;
 
119
        }
 
120
 
 
121
        u16 cls = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
122
        if (cls == 0x0000 || cls == 0xffff) {
 
123
            // Device not present.
 
124
            if (pci_bdf_to_fn(bdf) == 0)
 
125
                bdf += 8;
 
126
            else
 
127
                bdf += 1;
 
128
            continue;
 
129
        }
 
130
        if (cls == PCI_CLASS_DISPLAY_VGA) {
 
131
            u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
 
132
            if (cmd & PCI_COMMAND_IO && cmd & PCI_COMMAND_MEMORY)
 
133
                // Found active vga card
 
134
                return bdf;
 
135
        }
 
136
 
 
137
        // Check if device is a bridge.
 
138
        u8 hdr = pci_config_readb(bdf, PCI_HEADER_TYPE);
 
139
        u8 ht = hdr & 0x7f;
 
140
        if (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS) {
 
141
            u32 ctrl = pci_config_readb(bdf, PCI_BRIDGE_CONTROL);
 
142
            if (ctrl & PCI_BRIDGE_CTL_VGA) {
 
143
                // Found a VGA enabled bridge.
 
144
                u32 pbus = pci_config_readl(bdf, PCI_PRIMARY_BUS);
 
145
                bdf = (pbus & 0xff00);
 
146
                max = bdf + 0x100;
 
147
                continue;
 
148
            }
 
149
        }
 
150
 
 
151
        if (pci_bdf_to_fn(bdf) == 0 && (hdr & 0x80) == 0)
 
152
            // Last found device wasn't a multi-function device - skip to
 
153
            // the next device.
 
154
            bdf += 8;
 
155
        else
 
156
            bdf += 1;
 
157
    }
 
158
}
 
159
 
 
160
// Search for a device with the specified vendor and device ids.
 
161
int
 
162
pci_find_device(u16 vendid, u16 devid)
 
163
{
 
164
    u32 id = (devid << 16) | vendid;
 
165
    int bdf, max;
 
166
    foreachpci(bdf, max) {
 
167
        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
 
168
        if (v == id)
 
169
            return bdf;
 
170
    }
 
171
    return -1;
 
172
}
 
173
 
 
174
// Search for a device with the specified class id.
 
175
int
 
176
pci_find_class(u16 classid)
 
177
{
 
178
    int bdf, max;
 
179
    foreachpci(bdf, max) {
 
180
        u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
181
        if (v == classid)
 
182
            return bdf;
 
183
    }
 
184
    return -1;
 
185
}