1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/*
* Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Jerome Glisse
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "radeon_pci.h"
int radeon_pci_init(struct radeon_pci *pradeon)
{
struct pci_slot_match match;
struct pci_device_iterator *iter;
struct pci_device *device;
int r = 0;
pradeon->dev = NULL;
if (pci_system_init()) {
fprintf(stderr, "Failed to initialize libpciaccess\n");
return -1;
}
match.domain = PCI_MATCH_ANY;
match.bus = PCI_MATCH_ANY;
match.dev = PCI_MATCH_ANY;
match.func = 0;
match.match_data = 0;
iter = pci_slot_match_iterator_create(&match);
while ((device = pci_device_next(iter))) {
pci_device_probe(device);
if ((device->device_class & 0x00FF0000) != 0x30000) {
continue;
}
/* ATI vendor id 0x1002 and we are looking for a video
* card class 0x03 with subclass 0x00 (VGA)
*/
if (device->vendor_id == 0x1002) {
pradeon->mmio_base = device->regions[2].base_addr;
pradeon->mmio_size = device->regions[2].size;
pradeon->dev = device;
fprintf(stderr, "probed %02d:%02d.%d 0x%08X (0x%08X %d|0x%08X)\n",
device->bus, device->dev, device->func, device->device_class,
(unsigned)pradeon->mmio_base, (unsigned)pradeon->mmio_size,
(unsigned)pradeon->mmio_size);
break;
}
}
pci_iterator_destroy(iter);
if (!pradeon->dev) {
fprintf(stderr, "Cannot find radeon device\n");
return -1;
}
r = pci_device_map_range(pradeon->dev, pradeon->mmio_base, pradeon->mmio_size,
PCI_DEV_MAP_FLAG_WRITABLE,
(void**)&pradeon->mmio);
if (r) {
fprintf(stderr, "Mapping mmio failed (are you root ?)\n");
return -1;
}
return 0;
}
void radeon_pci_fini(struct radeon_pci *pradeon)
{
if (pci_device_unmap_range(pradeon->dev, pradeon->mmio, pradeon->mmio_size)) {
fprintf(stderr, "Unmapping mmio failed\n");
}
}
uint32_t radeon_mmio_rd32(struct radeon_pci *pradeon, uint32_t offset)
{
uint32_t value;
if (pradeon->mmio == NULL) {
fprintf(stderr, "(%s:%d) internal error\n", __func__, __LINE__);
exit(1);
}
value = *(uint32_t * volatile)(pradeon->mmio + offset);
return value;
}
void radeon_mmio_wr32(struct radeon_pci *pradeon, uint32_t offset, uint32_t value)
{
if (pradeon->mmio == NULL) {
fprintf(stderr, "(%s:%d) internal error\n", __func__, __LINE__);
exit(1);
}
*(uint32_t * volatile)(pradeon->mmio + offset) = value;
}
|