/* * 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" #include "reg.h" int dump_range(struct dump *dump, struct radeon_pci *pradeon, struct range *range) { unsigned i; dump->nregs = (range->loffset - range->foffset) / range->stride; dump->regs = calloc(1, sizeof(struct reg) * dump->nregs); if (dump->regs == NULL) { return -ENOMEM; } for (i = 0; i < dump->nregs; i++) { dump->regs[i].domain = range->domain; dump->regs[i].offset = range->foffset + range->stride * i; if (dump->regs[i].offset > pradeon->mmio_size) { radeon_mmio_wr32(pradeon, 0x0, dump->regs[i].offset); dump->regs[i].value = radeon_mmio_rd32(pradeon, 0x4); } else { dump->regs[i].value = radeon_mmio_rd32(pradeon, dump->regs[i].offset); } } return 0; } void dump_print(struct dump *dump) { unsigned i; for (i = 0; i < dump->nregs; i++) { printf("[0x%08X] 0x%08X 0x%08X\n", dump->regs[i].domain, dump->regs[i].offset, dump->regs[i].value); } } void dump_write(struct dump *dump, struct radeon_pci *pradeon) { unsigned i; for (i = 0; i < dump->nregs; i++) { printf("WRITE [0x%08X] 0x%08X 0x%08X\n", dump->regs[i].domain, dump->regs[i].offset, dump->regs[i].value); radeon_mmio_wr32(pradeon, dump->regs[i].offset, dump->regs[i].value); } } static unsigned file_nlines(FILE *file) { unsigned line = 0; char tmp[256]; fseek(file, 0, SEEK_SET); while (!feof(file)) { fgets(tmp, 256, file); line++; } return line; } int dump_read(struct dump *dump, const char *filename) { FILE *file; unsigned nline, i; char tmp[256]; int r; file = fopen(filename, "r"); if (file == NULL) { return -EINVAL; } nline = file_nlines(file); dump->regs = calloc(1, sizeof(struct reg) * nline); if (dump->regs == NULL) { return -ENOMEM; } fseek(file, 0, SEEK_SET); dump->nregs = i = 0; while (!feof(file)) { if (fgets(tmp, 256, file) == NULL) { continue; } r = sscanf(tmp, "[0x%08X] 0x%08X 0x%08X", &dump->regs[i].domain, &dump->regs[i].offset, &dump->regs[i].value); if (r == 3) { i++; dump->nregs++; } } return 0; } void dump_fini(struct dump *dump) { free(dump->regs); dump->nregs = 0; dump->regs = NULL; } static int reg_same(struct reg *areg, struct reg *breg) { return (areg->domain == breg->domain && areg->offset == breg->offset); } #define MAX(X,Y) (((X) > (Y)) ? (X) : (Y)) int dump_keep_same(struct dump *odump, struct dump *adump, struct dump *bdump) { unsigned i, j, o; odump->nregs = MAX(adump->nregs, bdump->nregs); odump->regs = calloc(1, sizeof(struct reg) * odump->nregs); if (odump->regs == NULL) { return -ENOMEM; } for (i = 0, o = 0; i < adump->nregs; i++) { for (j = 0; j < bdump->nregs; j++) { if (reg_same(&adump->regs[i], &bdump->regs[j]) && adump->regs[i].value == bdump->regs[j].value) { odump->regs[o] = adump->regs[i]; o++; } } } odump->nregs = o; return 0; } int dump_keep_diff(struct dump *odump, struct dump *adump, struct dump *bdump) { unsigned i, j, o; odump->nregs = MAX(adump->nregs, bdump->nregs); odump->regs = calloc(1, sizeof(struct reg) * odump->nregs); if (odump->regs == NULL) { return -ENOMEM; } for (i = 0, o = 0; i < adump->nregs; i++) { for (j = 0; j < bdump->nregs; j++) { if (reg_same(&adump->regs[i], &bdump->regs[j]) && adump->regs[i].value != bdump->regs[j].value) { odump->regs[o] = adump->regs[i]; o++; } } } odump->nregs = o; return 0; }