On Tue, Oct 8, 2013 at 3:18 PM, Jani Nikula <jani.nikula@xxxxxxxxx> wrote: > Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> > --- > tools/Makefile.am | 1 + > tools/intel_opregion_decode.c | 438 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 439 insertions(+) > create mode 100644 tools/intel_opregion_decode.c > > diff --git a/tools/Makefile.am b/tools/Makefile.am > index 19810cf..59fea97 100644 > --- a/tools/Makefile.am > +++ b/tools/Makefile.am > @@ -13,6 +13,7 @@ bin_PROGRAMS = \ > intel_gpu_top \ > intel_gpu_time \ > intel_gtt \ > + intel_opregion_decode \ > intel_perf_counters \ > intel_stepping \ > intel_reg_checker \ > diff --git a/tools/intel_opregion_decode.c b/tools/intel_opregion_decode.c > new file mode 100644 > index 0000000..e5f79df > --- /dev/null > +++ b/tools/intel_opregion_decode.c > @@ -0,0 +1,438 @@ > +/* > + * Copyright © 2013 Intel Corporation > + * > + * 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 > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * 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 NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS 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: > + * Jani Nikula <jani.nikula@xxxxxxxxx> > + * > + */ > + > +#include <errno.h> > +#include <fcntl.h> > +#include <getopt.h> > +#include <stdint.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/mman.h> > +#include <sys/stat.h> > +#include <sys/types.h> > + > +#include "intel_gpu_tools.h" > + > +#define OPREGION_HEADER_OFFSET 0 > +#define OPREGION_ACPI_OFFSET 0x100 > +#define OPREGION_SWSCI_OFFSET 0x200 > +#define OPREGION_ASLE_OFFSET 0x300 > +#define OPREGION_VBT_OFFSET 0x400 > +#define OPREGION_ASLE_EXT_OFFSET 0x1C00 > + > +#define MBOX_ACPI (1 << 0) > +#define MBOX_SWSCI (1 << 1) > +#define MBOX_ASLE (1 << 2) > +#define MBOX_VBT (1 << 3) > +#define MBOX_ASLE_EXT (1 << 4) > + > +struct opregion_header { > + char sign[16]; > + uint32_t size; > + uint32_t over; > + char sver[32]; > + char vver[16]; > + char gver[16]; > + uint32_t mbox; > + uint32_t dmod; > + uint32_t pcon; > + char dver[32]; > + uint8_t rsv1[124]; > +} __attribute__((packed)); > + > +/* OpRegion mailbox #1: public ACPI methods */ > +struct opregion_acpi { > + uint32_t drdy; /* driver readiness */ > + uint32_t csts; /* notification status */ > + uint32_t cevt; /* current event */ > + uint8_t rsvd1[20]; > + uint32_t didl[8]; /* supported display devices ID list */ > + uint32_t cpdl[8]; /* currently presented display list */ > + uint32_t cadl[8]; /* currently active display list */ > + uint32_t nadl[8]; /* next active devices list */ > + uint32_t aslp; /* ASL sleep time-out */ > + uint32_t tidx; /* toggle table index */ > + uint32_t chpd; /* current hotplug enable indicator */ > + uint32_t clid; /* current lid state*/ > + uint32_t cdck; /* current docking state */ > + uint32_t sxsw; /* Sx state resume */ > + uint32_t evts; /* ASL supported events */ > + uint32_t cnot; /* current OS notification */ > + uint32_t nrdy; /* driver status */ > + uint32_t did2[7]; > + uint32_t cpd2[7]; > + uint8_t rsvd2[4]; > +} __attribute__((packed)); > + > +/* OpRegion mailbox #2: SWSCI */ > +struct opregion_swsci { > + uint32_t scic; /* SWSCI command|status|data */ > + uint32_t parm; /* command parameters */ > + uint32_t dslp; /* driver sleep time-out */ > + uint8_t rsvd[244]; spec that I have here (HSW one) says 240 reserved. with that fixed or explained I'll add my rv-b tag and merge all 6 patches (including bios reader ones that I already reviewed) upstream. > +} __attribute__((packed)); > + > +/* OpRegion mailbox #3: ASLE */ > +struct opregion_asle { > + uint32_t ardy; /* driver readiness */ > + uint32_t aslc; /* ASLE interrupt command */ > + uint32_t tche; /* technology enabled indicator */ > + uint32_t alsi; /* current ALS illuminance reading */ > + uint32_t bclp; /* backlight brightness to set */ > + uint32_t pfit; /* panel fitting state */ > + uint32_t cblv; /* current brightness level */ > + uint16_t bclm[20]; /* backlight level duty cycle mapping table */ > + uint32_t cpfm; /* current panel fitting mode */ > + uint32_t epfm; /* enabled panel fitting modes */ > + uint8_t plut_header; /* panel LUT and identifier */ > + uint8_t plut_identifier[10]; /* panel LUT and identifier */ > + uint8_t plut[63]; /* panel LUT and identifier */ > + uint32_t pfmb; /* PWM freq and min brightness */ > + uint32_t ccdv; > + uint32_t pcft; > + uint32_t srot; > + uint32_t iuer; > + uint8_t fdss[8]; > + uint32_t fdsp; > + uint32_t stat; > + uint8_t rsvd[86]; > +} __attribute__((packed)); > + > +/* OpRegion mailbox #4: VBT */ > +struct opregion_vbt { > + char product_string[20]; > + /* rest ignored */ > +} __attribute__((packed)); > + > +/* OpRegion mailbox #5: ASLE extension */ > +struct opregion_asle_ext { > + uint32_t phed; > + uint8_t bddc[256]; > +} __attribute__((packed)); > + > +static uint32_t decode_header(const void *buffer) > +{ > + const struct opregion_header *header = buffer; > + char *s; > + > + if (strncmp("IntelGraphicsMem", header->sign, sizeof(header->sign))) { > + fprintf(stderr, "invalid opregion signature\n"); > + return 0; > + } > + > + printf("OpRegion Header:\n"); > + > + s = strndup(header->sign, sizeof(header->sign)); > + printf("\tsign:\t%s\n", s); > + free(s); > + > + printf("\tsize:\t0x%08x\n", header->size); > + printf("\tover:\t0x%08x\n", header->over); > + > + s = strndup(header->sver, sizeof(header->sver)); > + printf("\tsver:\t%s\n", s); > + free(s); > + > + s = strndup(header->vver, sizeof(header->vver)); > + printf("\tvver:\t%s\n", s); > + free(s); > + > + s = strndup(header->gver, sizeof(header->gver)); > + printf("\tgver:\t%s\n", s); > + free(s); > + > + printf("\tmbox:\t0x%08x\n", header->mbox); > + > + printf("\tdmod:\t0x%08x\n", header->dmod); > + printf("\tpcon:\t0x%08x\n", header->pcon); > + > + s = strndup(header->dver, sizeof(header->dver)); > + printf("\tdver:\t%s\n", s); > + free(s); > + > + printf("\n"); > + > + return header->mbox; > +} > + > +static void decode_acpi(const void *buffer) > +{ > + const struct opregion_acpi *acpi = buffer; > + int i; > + > + printf("OpRegion Mailbox 1: Public ACPI Methods:\n"); > + > + printf("\tdrdy:\t0x%08x\n", acpi->drdy); > + printf("\tcsts:\t0x%08x\n", acpi->csts); > + printf("\tcevt:\t0x%08x\n", acpi->cevt); > + > + printf("\tdidl:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->didl); i++) > + printf("\t\tdidl[%d]:\t0x%08x\n", i, acpi->didl[i]); > + > + printf("\tcpdl:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->cpdl); i++) > + printf("\t\tcpdl[%d]:\t0x%08x\n", i, acpi->cpdl[i]); > + > + printf("\tcadl:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->cadl); i++) > + printf("\t\tcadl[%d]:\t0x%08x\n", i, acpi->cadl[i]); > + > + printf("\tnadl:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->nadl); i++) > + printf("\t\tnadl[%d]:\t0x%08x\n", i, acpi->nadl[i]); > + > + printf("\taslp:\t0x%08x\n", acpi->aslp); > + printf("\ttidx:\t0x%08x\n", acpi->tidx); > + printf("\tchpd:\t0x%08x\n", acpi->chpd); > + printf("\tclid:\t0x%08x\n", acpi->clid); > + printf("\tcdck:\t0x%08x\n", acpi->cdck); > + printf("\tsxsw:\t0x%08x\n", acpi->sxsw); > + printf("\tevts:\t0x%08x\n", acpi->evts); > + printf("\tcnot:\t0x%08x\n", acpi->cnot); > + printf("\tnrdy:\t0x%08x\n", acpi->nrdy); > + > + printf("\tdid2:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->did2); i++) > + printf("\t\tdid2[%d]:\t0x%08x\n", i, acpi->did2[i]); > + > + printf("\tcpd2:\n"); > + for (i = 0; i < ARRAY_SIZE(acpi->cpd2); i++) > + printf("\t\tcpd2[%d]:\t0x%08x\n", i, acpi->cpd2[i]); > + > + printf("\n"); > +} > + > +static void decode_swsci(const void *buffer) > +{ > + const struct opregion_swsci *swsci = buffer; > + > + printf("OpRegion Mailbox 2: Software SCI Interface (SWSCI):\n"); > + > + printf("\tscic:\t0x%08x\n", swsci->scic); > + printf("\tparm:\t0x%08x\n", swsci->parm); > + printf("\tdslp:\t0x%08x\n", swsci->dslp); > + > + printf("\n"); > +} > + > +static void decode_asle(const void *buffer) > +{ > + const struct opregion_asle *asle = buffer; > + int i; > + > + printf("OpRegion Mailbox 3: BIOS to Driver Notification (ASLE):\n"); > + > + printf("\tardy:\t0x%08x\n", asle->ardy); > + printf("\taslc:\t0x%08x\n", asle->aslc); > + printf("\ttche:\t0x%08x\n", asle->tche); > + printf("\talsi:\t0x%08x\n", asle->alsi); > + printf("\tbclp:\t0x%08x\n", asle->bclp); > + printf("\tpfit:\t0x%08x\n", asle->pfit); > + printf("\tcblv:\t0x%08x\n", asle->cblv); > + > + printf("\tbclm:\n"); > + for (i = 0; i < ARRAY_SIZE(asle->bclm); i++) > + printf("\t\tbclm[%d]:\t0x%04x\n", i, asle->bclm[i]); > + > + printf("\tcpfm:\t0x%08x\n", asle->cpfm); > + printf("\tepfm:\t0x%08x\n", asle->epfm); > + > + printf("\tplut header:\t0x%02x\n", asle->plut_header); > + > + printf("\tplut identifier:"); > + for (i = 0; i < ARRAY_SIZE(asle->plut_identifier); i++) > + printf(" %02x", asle->plut_identifier[i]); > + printf("\n"); > + > + printf("\tplut:\n"); > + for (i = 0; i < ARRAY_SIZE(asle->plut); i++) { > + const int COLUMNS = 7; > + > + if (i % COLUMNS == 0) > + printf("\t\tplut[%d]:\t", i / COLUMNS); > + > + printf("%02x ", asle->plut[i]); > + > + if (i % COLUMNS == COLUMNS - 1) > + printf("\n"); > + } > + > + printf("\tpfmb:\t0x%08x\n", asle->pfmb); > + printf("\tccdv:\t0x%08x\n", asle->ccdv); > + printf("\tpcft:\t0x%08x\n", asle->pcft); > + printf("\tsrot:\t0x%08x\n", asle->srot); > + printf("\tiuer:\t0x%08x\n", asle->iuer); > + > + printf("\tfdss:\t"); > + for (i = 0; i < ARRAY_SIZE(asle->fdss); i++) > + printf("%02x ", asle->fdss[i]); > + printf("\n"); > + > + printf("\tfdsp:\t0x%08x\n", asle->fdsp); > + printf("\tstat:\t0x%08x\n", asle->stat); > + > + printf("\n"); > +} > + > +static void decode_vbt(const void *buffer) > +{ > + const struct opregion_vbt *vbt = buffer; > + char *s; > + > + printf("OpRegion Mailbox 4: Video BIOS Table (VBT):\n"); > + > + s = strndup(vbt->product_string, sizeof(vbt->product_string)); > + printf("\tproduct string:\t%s\n", s); > + free(s); > + > + printf("\t(use intel_bios_reader to decode the VBT)\n"); > + > + printf("\n"); > +} > + > +static void decode_asle_ext(const void *buffer) > +{ > + const struct opregion_asle_ext *asle_ext = buffer; > + int i; > + > + printf("OpRegion Mailbox 5: BIOS to Driver Notification Extension:\n"); > + > + printf("\tphed:\t0x%08x\n", asle_ext->phed); > + > + printf("\tbddc:\n"); > + for (i = 0; i < ARRAY_SIZE(asle_ext->bddc); i++) { > + const int COLUMNS = 16; > + > + if (i % COLUMNS == 0) > + printf("\t\tbddc[0x%02x]:\t", i); > + > + printf("%02x ", asle_ext->bddc[i]); > + > + if (i % COLUMNS == COLUMNS - 1) > + printf("\n"); > + } > + > + printf("\n"); > +} > + > +static void decode_opregion(const uint8_t *opregion, int size) > +{ > + uint32_t mbox; > + > + /* XXX: allow decoding up to size */ > + if (OPREGION_ASLE_EXT_OFFSET + sizeof(struct opregion_asle_ext) > size) { > + fprintf(stderr, "buffer too small\n"); > + return; > + } > + > + mbox = decode_header(opregion + OPREGION_HEADER_OFFSET); > + if (mbox & MBOX_ACPI) > + decode_acpi(opregion + OPREGION_ACPI_OFFSET); > + if (mbox & MBOX_SWSCI) > + decode_swsci(opregion + OPREGION_SWSCI_OFFSET); > + if (mbox & MBOX_ASLE) > + decode_asle(opregion + OPREGION_ASLE_OFFSET); > + if (mbox & MBOX_VBT) > + decode_vbt(opregion + OPREGION_VBT_OFFSET); > + if (mbox & MBOX_ASLE_EXT) > + decode_asle_ext(opregion + OPREGION_ASLE_EXT_OFFSET); > +} > + > +int main(int argc, char *argv[]) > +{ > + const char *filename = "/sys/kernel/debug/dri/0/i915_opregion"; > + int fd; > + struct stat finfo; > + uint8_t *opregion; > + int c, option_index = 0; > + > + static struct option long_options[] = { > + { "file", required_argument, 0, 'f' }, > + { "help", no_argument, 0, 'h' }, > + { 0 }, > + }; > + > + while ((c = getopt_long(argc, argv, "hf:", > + long_options, &option_index)) != -1) { > + switch (c) { > + case 'h': > + printf("usage: intel_opregion_decode [-f|--file=<input>]\n"); > + return 0; > + case 'f': > + filename = optarg; > + break; > + default: > + fprintf(stderr, "unkown command options\n"); > + return 1; > + } > + } > + > + fd = open(filename, O_RDONLY); > + if (fd == -1) { > + printf("Couldn't open \"%s\": %s\n", filename, strerror(errno)); > + return 1; > + } > + > + if (stat(filename, &finfo)) { > + printf("failed to stat \"%s\": %s\n", filename, strerror(errno)); > + return 1; > + } > + > + if (finfo.st_size == 0) { > + int len = 0, ret; > + finfo.st_size = 8192; > + opregion = malloc(finfo.st_size); > + while ((ret = read(fd, opregion + len, finfo.st_size - len))) { > + if (ret < 0) { > + printf("failed to read \"%s\": %s\n", filename, > + strerror(errno)); > + return 1; > + } > + > + len += ret; > + if (len == finfo.st_size) { > + finfo.st_size *= 2; > + opregion = realloc(opregion, finfo.st_size); > + } > + } > + } else { > + opregion = mmap(NULL, finfo.st_size, PROT_READ, MAP_SHARED, > + fd, 0); > + if (opregion == MAP_FAILED) { > + printf("failed to map \"%s\": %s\n", filename, > + strerror(errno)); > + return 1; > + } > + } > + > + decode_opregion(opregion, finfo.st_size); > + > + return 0; > +} > -- > 1.7.10.4 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx Thanks -- Rodrigo Vivi Blog: http://blog.vivi.eng.br _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx