/* * Copyright 2010 Jerome Glisse * * 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 #include #include #include #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; }