summaryrefslogtreecommitdiff
path: root/radeon_pci.c
blob: f3484727e447356923db37dd994918aeda98fda7 (plain)
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;
}