From 564e90f57185274130aba7b157a7dca1941dcfef Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Fri, 4 May 2012 15:37:18 -0700 Subject: Add a tool to work on i915 hardware in user mode This is the beginning of a tool that transforms the i9x5 code to user mode code. Consider this a very early stage although it does produce two programs. Requires spatch 1.0 or greater. To try it out, assuming you have an up-to-date spatch, sh transform make make broken Please don't fall to the temptation to auto-magicize this process. It's primitive for a reason. That said, suggestions welcome of course. Change-Id: I0188e36637b198b06c17f6d3c714d990e88bd57d Signed-off-by: Ronald G. Minnich Reviewed-on: http://review.coreboot.org/1003 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- util/i915tool/Makefile | 20 ++ util/i915tool/README | 11 + util/i915tool/main.c | 255 ++++++++++++++ util/i915tool/pci.c | 97 +++++ util/i915tool/plusplusplus | 3 + util/i915tool/spatches/deldev.cocci | 29 ++ util/i915tool/spatches/drm_crtc.cocci | 32 ++ util/i915tool/spatches/fixcalls.cocci | 148 ++++++++ util/i915tool/spatches/fx.cocci | 10 + util/i915tool/spatches/getdrmmodefn.cocci | 6 + util/i915tool/spatches/getfn.cocci | 61 ++++ util/i915tool/spatches/i915_dma.c.cocci | 3 + util/i915tool/spatches/i915_drv.c.cocci | 8 + util/i915tool/spatches/i915_drv.cocci | 178 ++++++++++ util/i915tool/spatches/intel_bios.cocci | 7 + util/i915tool/spatches/intel_display.c.cocci | 507 +++++++++++++++++++++++++++ util/i915tool/spatches/removeinclude.cocci | 6 + util/i915tool/spatches/ringbuffer.cocci | 14 + util/i915tool/transform | 151 ++++++++ util/i915tool/video.h | 133 +++++++ 20 files changed, 1679 insertions(+) create mode 100644 util/i915tool/Makefile create mode 100644 util/i915tool/README create mode 100644 util/i915tool/main.c create mode 100644 util/i915tool/pci.c create mode 100644 util/i915tool/plusplusplus create mode 100644 util/i915tool/spatches/deldev.cocci create mode 100644 util/i915tool/spatches/drm_crtc.cocci create mode 100644 util/i915tool/spatches/fixcalls.cocci create mode 100644 util/i915tool/spatches/fx.cocci create mode 100644 util/i915tool/spatches/getdrmmodefn.cocci create mode 100644 util/i915tool/spatches/getfn.cocci create mode 100644 util/i915tool/spatches/i915_dma.c.cocci create mode 100644 util/i915tool/spatches/i915_drv.c.cocci create mode 100644 util/i915tool/spatches/i915_drv.cocci create mode 100644 util/i915tool/spatches/intel_bios.cocci create mode 100644 util/i915tool/spatches/intel_display.c.cocci create mode 100644 util/i915tool/spatches/removeinclude.cocci create mode 100644 util/i915tool/spatches/ringbuffer.cocci create mode 100644 util/i915tool/transform create mode 100644 util/i915tool/video.h diff --git a/util/i915tool/Makefile b/util/i915tool/Makefile new file mode 100644 index 0000000000..4cd807a6b4 --- /dev/null +++ b/util/i915tool/Makefile @@ -0,0 +1,20 @@ +source=main.c pci.c final/intel_bios.c final/drm_modes.c final/i915_drv.c + +all: probe + +broken: video + +video: $(source) final/intel_display.c + cc -include video.h -Iinputs -static -g -o video $(source) \ + -lpci final/intel_display.c + +probe: $(source) + cc -include video.h -Iinputs -static -g -o probe $(source) -lpci +clean: + rm -f *.o video probe + +moreclean: clean + rm final/* per-file-changes/* tmp/* + +superclean: moreclean + rm inputs/* diff --git a/util/i915tool/README b/util/i915tool/README new file mode 100644 index 0000000000..cb5f986acf --- /dev/null +++ b/util/i915tool/README @@ -0,0 +1,11 @@ +spatches are the semantic patches +tmp is just tmp +inputs are copied from $LINUX +per-file-changes contain input files that have specific transforms +final contains the final form of the file, with 'global' changes applied (e.g. kzalloc -> calloc) + +transform copies files from $LINUX and then transforms them for use by stand-alone program/coreboot + +The Makefile is simple; this runs 'fast enough' that a complicated Makefile is not worth it. + +There's still some duct tape here but it's getting there. diff --git a/util/i915tool/main.c b/util/i915tool/main.c new file mode 100644 index 0000000000..cb828e1da3 --- /dev/null +++ b/util/i915tool/main.c @@ -0,0 +1,255 @@ +/* + * This file is part of i915tool + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "video.h" + +int verbose = 1; +static unsigned short addrport, dataport; +struct drm_device *i915; +unsigned short vendor=0x8086, device=0x0116; +struct pci_dev fake = {.vendor_id=0x8086, .device_id = 0x0116}; +int dofake = 0; +u8 *bios_image = NULL; +u8 *mmiobase; +u32 mmiophys; +int mmiosize; +size_t bios_image_size; +/* temporary */ +unsigned int i915_lvds_downclock = 0; +int i915_vbt_sdvo_panel_type = -1; + +/* */ + +/* not sure how we want to do this so let's guess */ +/* to make it easy, we start at zero and assume 250 hz. */ +unsigned long msecs(void) +{ + struct timeval start, now; + static int first = 0; + unsigned long j; + if (! first++) + gettimeofday(&start, NULL); + gettimeofday(&now, NULL); + j = (now.tv_sec - start.tv_sec)*1000 + (now.tv_usec-start.tv_usec)/1000; + return j; +} + +void +mdelay(unsigned long ms) +{ + unsigned long start; + start = msecs(); + while (msecs() < (start + ms)) + ; +} + +void +hexdump(u8 *base, int size) +{ + int i, j; + for(i = 0; i < size/sizeof(u32); i += 8) { + printf("%#x: ", i); + for(j = 0; j < 8; j++) + printf("%08x", base[i+j]); + printf("\n"); + } +} +void udelay(int i) +{ + printf("UDELAY!\n"); +} + +unsigned long io_I915_READ(unsigned long addr) +{ + unsigned long val; + if (dofake) + return 0xcafebabe; + outl(addr, addrport); + val = inl(dataport); + if (verbose) + fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr); + return val; +} + +void io_I915_WRITE(unsigned long addr, unsigned long val) +{ + if (dofake) + return; + outl(addr, addrport); + outl(val, dataport); + if (verbose) + fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr); +} + +unsigned long I915_READ(unsigned long addr) +{ + volatile u32 *ptr = (u32 *)(mmiobase + addr); + unsigned long val; + if (dofake) + return 0xcafebabe; + val = *ptr; + if (verbose) + fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr); + return val; +} + +void I915_WRITE(unsigned long addr, unsigned long val) +{ + volatile u32 *ptr = (u32 *)(mmiobase + addr); + if (dofake) + return; + *ptr = val; + if (verbose) + fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr); +} + +u16 I915_READ16(unsigned long addr) +{ + volatile u16 *ptr = (u16 *)(mmiobase + addr); + unsigned long val; + if (dofake) + return 0xbabe; + val = *ptr; + if (verbose) + fprintf(stderr, "%s: %x <- %x\n", __func__, val, addr); + return val; +} + +void I915_WRITE16(unsigned long addr, u16 val) +{ + volatile u16 *ptr = (u16 *)(mmiobase + addr); + if (dofake) + return; + *ptr = val; + if (verbose) + fprintf(stderr, "%s: %x -> %x\n", __func__, val, addr); +} + +#define GTT_RETRY 1000 +static int gtt_poll(u32 reg, u32 mask, u32 value) +{ + unsigned try = GTT_RETRY; + u32 data; + + while (try--) { + data = I915_READ(reg); + if ((data & mask) == value){ + printf("succeeds after %d tries\n", GTT_RETRY-try); + return 1; + } + udelay(10); + } + + fprintf(stderr, "GT init timeout\n"); + return 0; +} +void *pci_map_rom(struct pci_dev *dev, size_t *size) +{ + *size = bios_image_size; + return bios_image; +} + +void *pci_unmap_rom(struct pci_dev *dev, void *bios) +{ + return NULL; +} + +void *dmi_check_system(unsigned long ignore) +{ + return NULL; +} + +void +mapit(void) +{ + int kfd; + kfd = open("/dev/mem", O_RDWR); + if (kfd < 0) + errx(1, "/dev/kmem"); + mmiobase = mmap(NULL, mmiosize, PROT_WRITE|PROT_READ, MAP_SHARED, kfd, + mmiophys); + if ((void *)-1 == mmiobase) + errx(1, "mmap"); +} + +void +devinit() +{ + u32 val; + /* force wake. */ + I915_WRITE(0xa18c, 1); + gtt_poll(0x130090, 1, 1); +} +int main(int argc, char *argv[]) +{ + struct pci_dev *pci_dev_find(struct drm_device *dev); + + for(argc--, argv++; argc; argc--, argv++) { + if (argv[0][0] != '-') + break; + if (!strcmp(argv[0], "-f")) + dofake++; + } + i915 = calloc(1, sizeof(*i915)); + i915->dev_private = calloc(1, sizeof(*i915->dev_private)); + /* until we do a bit more w/ coccinelle */ + i915->dev_private->dev = i915; + + if (dofake) { + i915->pdev = &fake; + if (! find_idlist(i915, vendor, device)) + errx(1, "can't find fake device in pciidlist"); + } else { + if (! pci_dev_find(i915)) + errx(1, "No VGA device of any kind found\n"); + } + + if (argc) { + FILE *fd; + int amt; + /* size it later */ + bios_image = malloc(8*1048576); + fd = fopen(argv[0], "r"); + amt = fread(bios_image, 65536, 128, fd); + if (amt < 1) { + free(bios_image); + } else { + i915->bios_bin = bios_image; + i915->dev_private->opregion.vbt = bios_image; + bios_image_size = amt * 65536; + fclose(fd); + } + } + /* get the base address for the mmio indirection registers -- BAR 2 */ + addrport = i915->pdev->base_addr[4] & ~3; + dataport = addrport + 4; + printf("Addrport is at %x, dataport at %x\n", addrport, dataport); + /* get the base of the mmio space */ + mmiophys = i915->pdev->base_addr[0] & ~0xf; + mmiosize = i915->pdev->size[0]; + printf("phys base is %#x, size %d\n", mmiophys, mmiosize); + mapit(); + devinit(); + //hexdump(mmiobase, mmiosize); + /* we should use ioperm but hey ... it's had troubles */ + iopl(3); + intel_setup_bios(i915); + if (i915->bios_bin) + intel_parse_bios(i915); +} diff --git a/util/i915tool/pci.c b/util/i915tool/pci.c new file mode 100644 index 0000000000..ca942dc314 --- /dev/null +++ b/util/i915tool/pci.c @@ -0,0 +1,97 @@ +/* + * This file is part of i915tool + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "video.h" + +int find_idlist(struct drm_device *dev, u16 vendor, u16 device) +{ + extern const struct pci_device_id pciidlist[]; + int succ = 0; + int i; + for(i = 0; pciidlist[i].vendor && !succ; i++){ + if (vendor == pciidlist[i].vendor && device == + pciidlist[i].device){ + dev->dev_private->info = + (void *)(pciidlist[i].driver_data); + succ = 1; + } + } + return succ; +} + +/* there's only going to be one device ... */ +int pci_dev_find(struct drm_device *dev) +{ + struct pci_access *pacc = NULL; + struct pci_dev *temp; + int succ = 0; + pacc = pci_alloc(); + if (! pacc) + return 0; + pci_init(pacc); + pci_scan_bus(pacc); + + for (temp = pacc->devices; temp && ! dev->pdev; temp = temp->next){ + if ((temp->device_class & 0xff00) == PCI_CLASS_DISPLAY_VGA ) { + pci_fill_info(temp, PCI_FILL_IDENT | + PCI_FILL_BASES | PCI_FILL_CLASS); + dev->pdev = temp; + } + } + + if (dev->pdev) + succ = find_idlist(dev, dev->pdev->vendor_id, + dev->pdev->device_id); + return succ; +} + +/* Support library for kernel style pci functions. We could do a semantic + * patch for it but this is easier to debug as we can fill it with prints + * if we want. And no cpp abuse here. Keep it simple. + */ + +void pci_read_config_byte(struct pci_dev *dev, unsigned long offset, u8 *val) +{ + *val = pci_read_byte(dev, offset); +} + +void pci_write_config_byte(struct pci_dev *dev, unsigned long offset, u8 val) +{ + pci_write_byte(dev, offset, val); +} + +void pci_read_config_word(struct pci_dev *dev, unsigned long offset, u16 *val) +{ + *val = pci_read_word(dev, offset); +} + +void pci_write_config_word(struct pci_dev *dev, unsigned long offset, u16 val) +{ + pci_write_word(dev, offset, val); +} + +void pci_read_config_dword(struct pci_dev *dev, unsigned long offset, u32 *val) +{ + *val = pci_read_long(dev, offset); +} + +void pci_write_config_dword(struct pci_dev *dev, unsigned long offset, u32 val) +{ + pci_write_long(dev, offset, val); +} diff --git a/util/i915tool/plusplusplus b/util/i915tool/plusplusplus new file mode 100644 index 0000000000..a5dcd19972 --- /dev/null +++ b/util/i915tool/plusplusplus @@ -0,0 +1,3 @@ +#!/bin/bash +sed 's,^\+\+\+.*,+++ '$2',' < $1 > $1.pat + diff --git a/util/i915tool/spatches/deldev.cocci b/util/i915tool/spatches/deldev.cocci new file mode 100644 index 0000000000..504dae7230 --- /dev/null +++ b/util/i915tool/spatches/deldev.cocci @@ -0,0 +1,29 @@ +@@ +identifier dev; +expression i; +@@ +-struct drm_i915_private *dev = i; ++extern struct drm_device *i915; struct drm_i915_private *dev = i915->dev_private; +@@ +identifier dev; +expression i; +@@ +-struct pci_dev *dev = i; ++extern struct drm_device *i915; struct pci_dev *dev = i915->pdev; +@@ +@@ +-#include "i915_drm.h" +@@ +@@ +-#include "drm.h" +@@ +@@ +-#include "drmP.h" +@@ +@@ +-#include "i915_trace.h" +@@ +identifier d; +@@ +-(d)->pci_device ++(d)->pdev->device_id diff --git a/util/i915tool/spatches/drm_crtc.cocci b/util/i915tool/spatches/drm_crtc.cocci new file mode 100644 index 0000000000..662f25316c --- /dev/null +++ b/util/i915tool/spatches/drm_crtc.cocci @@ -0,0 +1,32 @@ +@@ +identifier s; +identifier head; +@@ +struct s {... +- struct list_head head; +...}; +@@ +@@ +-#include <...> +@@ +@@ +( +-struct drm_crtc_funcs{...}; +| +-struct drm_crtc{...}; +| +-struct drm_connector_funcs{...}; +| +-struct drm_encoder_funcs{...}; +| +-struct drm_encoder{...}; +| +-struct drm_connector{...}; +| +-struct drm_mode_config_funcs{...}; +| +-struct drm_mode_config{...}; +| +-struct drm_framebuffer_funcs{...}; +) + diff --git a/util/i915tool/spatches/fixcalls.cocci b/util/i915tool/spatches/fixcalls.cocci new file mode 100644 index 0000000000..50e6458fd3 --- /dev/null +++ b/util/i915tool/spatches/fixcalls.cocci @@ -0,0 +1,148 @@ +@@ +identifier f; +type T; +@@ +T f(...){<... +-vga_get_uninterruptible(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-vga_put(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-intel_init_quirks(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-drm_mode_config_init(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-INIT_WORK(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-setup_timer(...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-DRM_DEBUG_KMS( ++fprintf(stderr, +...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-DRM_ERROR( ++fprintf(stderr, +...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-DRM_DEBUG( ++fprintf(stderr, +...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-DRM_DEBUG_DRIVER( ++fprintf(stderr, +...); +...>} +@@ +identifier f; +type T; +@@ +T f(...){<... +-intel_init_display(...); +...>} +@ rulekz @ +identifier t; +identifier f; +expression E1, E2; +type T; +@@ +T f(...){<... +t = kzalloc(E1, E2); +...>} +@@ +identifier rulekz.f; +expression E1, E2; +@@ + +- kzalloc(E1 ++ calloc(1, E1 +- ,E2 + ) +@@ +identifier d; +@@ +-static +const struct pci_device_id d[] = {...}; +@@ +expression E1; +@@ +-WARN( ++if ( +E1 +-, ++) fprintf(stderr, +...); +@@ +expression E1; +@@ +-BUG_ON( ++assert( +E1); +@@ +@@ +-jiffies ++msecs() +@@ +expression E1; +@@ +-jiffies_to_msecs( +E1 +-) +@@ +expression E1; +@@ +-msecs_to_jiffies( +E1 +-) +@@ +expression E1, E2; +@@ +-time_after( ++( +E1 +-, ++> +E2) diff --git a/util/i915tool/spatches/fx.cocci b/util/i915tool/spatches/fx.cocci new file mode 100644 index 0000000000..e47ddcab69 --- /dev/null +++ b/util/i915tool/spatches/fx.cocci @@ -0,0 +1,10 @@ +@@ +identifier f; +type T; +@@ +T f(...){... +-\(DRM_DEBUG_KMS|DRM_ERRRO\)( ++fprintf(stderr, +...); +...} + diff --git a/util/i915tool/spatches/getdrmmodefn.cocci b/util/i915tool/spatches/getdrmmodefn.cocci new file mode 100644 index 0000000000..d5cd17edc6 --- /dev/null +++ b/util/i915tool/spatches/getdrmmodefn.cocci @@ -0,0 +1,6 @@ +@@ +@@ +- drm_mode_set_name(...) {...} +@@ +@@ +- drm_mode_debug_printmodeline(...) {...} diff --git a/util/i915tool/spatches/getfn.cocci b/util/i915tool/spatches/getfn.cocci new file mode 100644 index 0000000000..8dea561187 --- /dev/null +++ b/util/i915tool/spatches/getfn.cocci @@ -0,0 +1,61 @@ +@@ +@@ +- get_blocksize(...) {...} +@@ +@@ +- lvds_dvo_timing_equal_size(...) {...} +@@ +@@ +- fill_detail_timing_data(...) {...} +@@ +@@ +- intel_setup_bios(...) {...} +@@ +@@ +- intel_parse_bios(...){...} +@@ +@@ +- init_vbt_defaults(...){...} +@@ +@@ +- parse_general_features(...){...} +@@ +@@ +- parse_general_definitions(...){...} +@@ +@@ +- parse_lfp_panel_data(...){...} +@@ +@@ +- parse_sdvo_panel_data(...){...} +@@ +@@ +- parse_sdvo_device_mapping(...){...} +@@ +@@ +- parse_device_mapping(...){...} +@@ +@@ +- parse_driver_features(...){...} +@@ +@@ +- parse_edp(...){...} +@@ +@@ +- find_section(...){...} +@@ +@@ +- get_lvds_dvo_timing(...){...} +@@ +@@ +- intel_bios_ssc_frequency(...){...} +@@ +identifier d; +type T; +@@ +- static T d; +@@ +expression S; +identifier d; +@@ +-#define d S diff --git a/util/i915tool/spatches/i915_dma.c.cocci b/util/i915tool/spatches/i915_dma.c.cocci new file mode 100644 index 0000000000..0ae2d55e8d --- /dev/null +++ b/util/i915tool/spatches/i915_dma.c.cocci @@ -0,0 +1,3 @@ +@@ +@@ +- i915_driver_load(...) {...} diff --git a/util/i915tool/spatches/i915_drv.c.cocci b/util/i915tool/spatches/i915_drv.c.cocci new file mode 100644 index 0000000000..0d64d939af --- /dev/null +++ b/util/i915tool/spatches/i915_drv.c.cocci @@ -0,0 +1,8 @@ +@inteldeviceinfo@ +identifier d; +@@ +-const struct intel_device_info d = {...}; +@@ +identifier d; +@@ +-static const struct pci_device_id d[] = {...}; diff --git a/util/i915tool/spatches/i915_drv.cocci b/util/i915tool/spatches/i915_drv.cocci new file mode 100644 index 0000000000..633e270067 --- /dev/null +++ b/util/i915tool/spatches/i915_drv.cocci @@ -0,0 +1,178 @@ +@@ +identifier d; +@@ +( +-struct drm_i915_fence_reg{...}; +| +-struct drm_i915_error_state{...}; +| +-struct drm_i915_gem_object{...}; +| +-struct drm_i915_display_funcs {...}; +| +-struct drm_i915_gem_phys_object{...}; +| +-struct mem_block{...}; +| +-struct drm_i915_gem_request{...}; +| +-struct drm_i915_file_private{...}; +| +-struct drm_i915_master_private{...}; +| +-struct intel_gmbus{...}; +| +-struct work_struct d; +| +-struct mem_*d; +| +-struct timer_list d; +| +-struct intel_fbc_work *d; +| +-struct drm_i915_error_state *d; +| +-struct i2c_adapter d; +| +-struct i2c_adapter *d; +| +-struct intel_hw_status_page{...}; +| +-struct intel_hw_status_page d; +) +@@ +@@ +-#include<...> +@@ +identifier d; +@@ +struct s {... +- struct drm_i915_display_funcs d; +... +}; +@@ +identifier d; +@@ +struct s {... +-struct notifier_block d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-spinlock_t d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-atomic_t d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-drm_dma_handle_t *d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-drm_local_map_t d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-spinlock_t *d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-struct i2c_adapter d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-struct i2c_adapter *d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +( +-struct inteL_gmbus {...} *d; +| +-struct drm_i915_gem_object *d; +) +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-struct work_struct d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-struct resource d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-struct timer_list d; +... +}; +@@ +identifier s; +identifier d; +@@ +struct s {... +-wait_queue_head_t d; +... +}; +@@ +identifier s; +identifier d; +constant c; +@@ +struct s {... +-struct intel_ring_buffer d[c]; +... +}; +@@ +identifier s; +identifier d; +constant c; +@@ +struct s {... +-struct drm_i915_fence_reg d[c]; +... +}; + diff --git a/util/i915tool/spatches/intel_bios.cocci b/util/i915tool/spatches/intel_bios.cocci new file mode 100644 index 0000000000..2e71363206 --- /dev/null +++ b/util/i915tool/spatches/intel_bios.cocci @@ -0,0 +1,7 @@ +@@ +@@ +-#include<...> ++#include "video.h" +@@ +@@ +-#include"..." diff --git a/util/i915tool/spatches/intel_display.c.cocci b/util/i915tool/spatches/intel_display.c.cocci new file mode 100644 index 0000000000..d7d87d3a9f --- /dev/null +++ b/util/i915tool/spatches/intel_display.c.cocci @@ -0,0 +1,507 @@ +@@ +@@ +-struct intel_limit {... }; +@@ +identifier d; +@@ +- intel_limit_t d = {...}; +@@ +@@ +- intel_connector_attach_encoder(...){...} +@@ +@@ +- intel_modeset_cleanup(...){...} +@@ +@@ +- intel_modeset_gem_init(...){...} +@@ +@@ +- intel_modeset_init(...){...} +@@ +@@ +- i915_disable_vga(...){...} +@@ +@@ +- intel_init_quirks(...){...} +@@ +@@ +- quirk_ssc_force_disable(...){...} +@@ +@@ +- quirk_pipea_force (...){...} +@@ +@@ +- intel_init_display(...){...} +@@ +@@ +- intel_init_clock_gating(...){...} +@@ +@@ +- ironlake_enable_rc6(...){...} +@@ +@@ +- ironlake_disable_rc6(...){...} +@@ +@@ +- ironlake_teardown_rc6(...){...} +@@ +@@ +- cpt_init_clock_gating(...){...} +@@ +@@ +- ibx_init_clock_gating(...){...} +@@ +@@ +- i830_init_clock_gating(...){...} +@@ +@@ +- i85x_init_clock_gating(...){...} +@@ +@@ +- gen3_init_clock_gating(...){...} +@@ +@@ +- broadwater_init_clock_gating(...){...} +@@ +@@ +- crestline_init_clock_gating(...){...} +@@ +@@ +- g4x_init_clock_gating(...){...} +@@ +@@ +- ivybridge_init_clock_gating(...){...} +@@ +@@ +- gen6_init_clock_gating(...){...} +@@ +@@ +- ironlake_init_clock_gating(...){...} +@@ +@@ +- gen6_update_ring_freq(...){...} +@@ +@@ +- gen6_enable_rps(...){...} +@@ +@@ +- intel_init_emon(...){...} +@@ +@@ +- gen6_disable_rps(...){...} +@@ +@@ +- gen6_set_rps(...){...} +@@ +@@ +- ironlake_disable_drps(...){...} +@@ +@@ +- ironlake_enable_drps(...){...} +@@ +@@ +- intel_user_framebuffer_destroy(...){...} +@@ +@@ +- intel_setup_outputs(...){...} +@@ +@@ +- intel_crtc_init(...){...} +@@ +@@ +- intel_crtc_reset(...){...} +@@ +@@ +- intel_prepare_page_flip(...){...} +@@ +@@ +- intel_finish_page_flip_plane(...){...} +@@ +@@ +- intel_finish_page_flip(...){...} +@@ +@@ +- intel_unpin_work_fn(...){...} +@@ +@@ +- intel_crtc_destroy(...){...} +@@ +@@ +- intel_mark_busy(...){...} +@@ +@@ +- intel_idle_update(...){...} +@@ +@@ +- intel_decrease_pllclock(...){...} +@@ +@@ +- intel_increase_pllclock(...){...} +@@ +@@ +- intel_crtc_idle_timer(...){...} +@@ +@@ +- intel_gpu_idle_timer(...){...} +@@ +@@ +- ivb_update_cursor(...){...} +@@ +@@ +- i9xx_update_cursor(...){...} +@@ +@@ +- i845_update_cursor(...){...} +@@ +@@ +- intel_crtc_load_lut(...){...} +@@ +@@ +- ironlake_update_pch_refclk(...){...} +@@ +@@ +- intel_update_watermarks(...){...} +@@ +@@ +- sandybridge_update_wm(...){...} +@@ +@@ +- ironlake_update_wm(...){...} +@@ +@@ +- i830_update_wm(...){...} +@@ +@@ +- i9xx_update_wm(...){...} +@@ +@@ +- i965_update_wm(...){...} +@@ +@@ +- g4x_update_wm(...){...} +@@ +@@ +- pineview_update_wm(...){...} +@@ +@@ +- pineview_disable_cxsr(...){...} +@@ +@@ +- intel_encoder_destroy(...){...} +@@ +@@ +- intel_encoder_commit (...){...} +@@ +@@ +- intel_encoder_prepare (...){...} +@@ +@@ +- ironlake_crtc_commit(...){...} +@@ +@@ +- ironlake_crtc_prepare(...){...} +@@ +@@ +- i9xx_crtc_commit(...){...} +@@ +@@ +- i9xx_crtc_prepare(...){...} +@@ +@@ +- intel_crtc_disable(...){...} +@@ +@@ +- intel_crtc_dpms(...){...} +@@ +@@ +- i9xx_crtc_dpms(...){...} +@@ +@@ +- i9xx_crtc_disable(...){...} +@@ +@@ +- i9xx_crtc_enable(...){...} +@@ +@@ +- intel_crtc_dpms_overlay(...){...} +@@ +@@ +- ironlake_crtc_dpms(...){...} +@@ +@@ +- ironlake_crtc_disable(...){...} +@@ +@@ +- ironlake_crtc_enable(...){...} +@@ +@@ +- intel_cpt_verify_modeset(...){...} +@@ +@@ +- ironlake_pch_enable(...){...} +@@ +@@ +- intel_crtc_wait_for_pending_flips(...){...} +@@ +@@ +- intel_clear_scanline_wait(...){...} +@@ +@@ +- ironlake_fdi_disable(...){...} +@@ +@@ +- cpt_phase_pointer_disable(...){...} +@@ +@@ +- ironlake_fdi_pll_enable(...){...} +@@ +@@ +- ivb_manual_fdi_link_train(...){...} +@@ +@@ +- gen6_fdi_link_train(...){...} +@@ +@@ +- ironlake_fdi_link_train(...){...} +@@ +@@ +- cpt_phase_pointer_enable(...){...} +@@ +@@ +- intel_fdi_normal_train(...){...} +@@ +@@ +- ironlake_set_pll_edp(...){...} +@@ +@@ +- intel_update_fbc(...){...} +@@ +@@ +- intel_disable_fbc(...){...} +@@ +@@ +- intel_enable_fbc(...){...} +@@ +@@ +- intel_cancel_fbc_work(...){...} +@@ +@@ +- intel_fbc_work_fn(...){...} +@@ +@@ +- ironlake_disable_fbc(...){...} +@@ +@@ +- ironlake_enable_fbc(...){...} +@@ +@@ +- sandybridge_blit_fbc_update(...){...} +@@ +@@ +- g4x_disable_fbc(...){...} +@@ +@@ +- g4x_enable_fbc(...){...} +@@ +@@ +- i8xx_enable_fbc(...){...} +@@ +@@ +- i8xx_disable_fbc(...){...} +@@ +@@ +- intel_disable_pll(...){...} +@@ +@@ +- intel_enable_pll(...){...} +@@ +@@ +- intel_clock(...){...} +@@ +@@ +- pineview_clock(...){...} +@@ +@@ +- intel_ironlake_limit(...){...} +@@ +@@ +- intel_g4x_limit(...){...} +@@ +@@ +- intel_limit(...){...} +@@ +@@ +- intel_pipe_has_type(...){...} +@@ +@@ +- intel_PLL_is_valid(...){...} +@@ +@@ +- intel_find_best_PLL(...){...} +@@ +@@ +- intel_g4x_find_best_PLL(...){...} +@@ +@@ +- intel_find_pll_ironlake_dp(...){...} +@@ +@@ +- intel_fbc_enabled(...){...} +@@ +@@ +- intel_pin_and_fence_fb_obj(...){...} +@@ +@@ +- i9xx_update_plane(...){...} +@@ +@@ +- ironlake_update_plane(...){...} +@@ +@@ +- intel_pipe_set_base_atomic(...){...} +@@ +@@ +- intel_pipe_set_base(...){...} +@@ +@@ +- intel_crtc_driving_pch(...){...} +@@ +@@ +- intel_crtc_mode_fixup(...){...} +@@ +@@ +- single_enabled_crtc(...){...} +@@ +@@ +- g4x_compute_wm0(...){...} +@@ +@@ +- g4x_compute_srwm(...){...} +@@ +@@ +- ironlake_compute_srwm(...){...} +@@ +@@ +- intel_panel_use_ssc(...){...} +@@ +@@ +- intel_choose_pipe_bpp_dither(...){...} +@@ +@@ +- i9xx_crtc_mode_set(...){...} +@@ +@@ +- ironlake_crtc_mode_set(...){...} +@@ +@@ +- intel_crtc_mode_set(...){...} +@@ +@@ +- intel_crtc_update_cursor(...){...} +@@ +@@ +- intel_crtc_cursor_set(...){...} +@@ +@@ +- intel_crtc_cursor_move(...){...} +@@ +@@ +- intel_crtc_fb_gamma_set(...){...} +@@ +@@ +- intel_crtc_fb_gamma_get(...){...} +@@ +@@ +- intel_crtc_gamma_set(...){...} +@@ +@@ +- intel_framebuffer_create(...){...} +@@ +@@ +- intel_framebuffer_size_for_mode(...){...} +@@ +@@ +- intel_framebuffer_create_for_mode(...){...} +@@ +@@ +- mode_fits_in_fbdev(...){...} +@@ +@@ +- intel_get_load_detect_pipe(...){...} +@@ +@@ +- intel_release_load_detect_pipe(...){...} +@@ +@@ +- intel_crtc_clock_get(...){...} +@@ +@@ +- intel_crtc_mode_get(...){...} +@@ +@@ +- do_intel_finish_page_flip(...){...} +@@ +@@ +- intel_gen2_queue_flip(...){...} +@@ +@@ +- intel_gen3_queue_flip(...){...} +@@ +@@ +- intel_gen4_queue_flip(...){...} +@@ +@@ +- intel_gen6_queue_flip(...){...} +@@ +@@ +- intel_gen7_queue_flip(...){...} +@@ +@@ +- intel_default_queue_flip(...){...} +@@ +@@ +- intel_crtc_page_flip(...){...} +@@ +@@ +- intel_get_pipe_from_crtc_id(...){...} +@@ +@@ +- intel_encoder_clones(...){...} +@@ +@@ +- intel_user_framebuffer_create_handle(...){...} +@@ +@@ +- intel_framebuffer_init(...){...} +@@ +@@ +- intel_user_framebuffer_create(...){...} +@@ +@@ +- intel_alloc_context_page(...){...} +@@ +@@ +- ironlake_setup_rc6(...){...} +@@ +@@ +- intel_best_encoder(...){...} +@@ +identifier d; +@@ +- struct drm_framebuffer_funcs d = {...}; +@@ +identifier d; +@@ +- struct drm_mode_config_funcs d = {...}; +@@ +identifier d; +@@ +-static struct drm_crtc_helper_funcs d = {...}; +@@ +identifier d; +@@ +-static struct drm_crtc_funcs d = {...}; +@@ +identifier d; +@@ +- struct intel_quirk d[] = {...}; diff --git a/util/i915tool/spatches/removeinclude.cocci b/util/i915tool/spatches/removeinclude.cocci new file mode 100644 index 0000000000..ff1bfeaa21 --- /dev/null +++ b/util/i915tool/spatches/removeinclude.cocci @@ -0,0 +1,6 @@ +@@ +@@ +-#include<...> +@@ +@@ +-#include"..." diff --git a/util/i915tool/spatches/ringbuffer.cocci b/util/i915tool/spatches/ringbuffer.cocci new file mode 100644 index 0000000000..68f0c98676 --- /dev/null +++ b/util/i915tool/spatches/ringbuffer.cocci @@ -0,0 +1,14 @@ +@@ +identifier d; +type T; +@@ +-T d(...){...} +@@ +identifier d; +type T; +@@ +-T d(...); +@@ +identifier d; +@@ +-struct d{...}; diff --git a/util/i915tool/transform b/util/i915tool/transform new file mode 100644 index 0000000000..3e191cb7e9 --- /dev/null +++ b/util/i915tool/transform @@ -0,0 +1,151 @@ +#!/bin/bash +# This script has been honed over quite a few iterations. The trick is to make +# it easy for you to see what transformations occur +# without burying you in files. +# Also, coccinelle is not perfect, so we have to help her at times. As she +# gets smarter, we can shrink thigns we do in here. +# So we get input files, then do per-file changes, then do all-file changes +# I've deliberately made this script simple. Please don't decide it needs to +# be automagic. Just let it work in its simple way. Also, if you change even +# one simple thing, ALWAYS rerun this script do make sure you did not make a +# global test. NEVER test one little thing in isolation. That way +# lies madness. +# The only thing you need to set is +# export LINUX=/path/to/your/linux/tree. +# Order in which we do things. +# 1. Get source files into inputs. +# 2. cp them to per-file-changes +# Note that we even copy ones that might not currently need per-file +# changes. Because they may in future and it keeps the script simple. +# We tried both ways and like this best. +# 3. run 'ed' across a few files that need it +# 4. run coccinelle with any per-file changes +# There is some ugliness here as we have to do a reverse patch step. Sorry. +# 5. cp per-file-changes/* to final +# 6. run coccinelle files that apply to more than one file +# it's best to run coccinelle on as many files as possible, she's pretty +# smart about +# certain transformations, e.g. if you remove a function definition she can +# remove all calls to that function (usually) +# +# Now you can +# make (will build all working tools) +# or +# make broken +# for things that don't build yet. + +# Step 1 +rm inputs/* per-file-changes/* final/* tmp/* +cp $LINUX/drivers/gpu/drm/i915/i915_reg.h inputs +cp $LINUX/drivers/gpu/drm/i915/i915_drv.? inputs +cp $LINUX/drivers/gpu/drm/i915/intel_display.c inputs +cp $LINUX/drivers/gpu/drm/i915/intel_bios.c inputs +cp $LINUX/drivers/gpu/drm/i915/intel_bios.h inputs +cp $LINUX/drivers/gpu/drm/i915/intel_ringbuffer.h inputs +cp $LINUX/drivers/gpu/drm/i915/i915_dma.c inputs +cp $LINUX/include/drm/drm_crtc.h inputs +cp $LINUX/include/drm/drm_mode.h inputs +cp $LINUX/include/drm/drm_dp_helper.h inputs +cp $LINUX/drivers/gpu/drm/drm_modes.c inputs + +# Step 2 +cp inputs/* per-file-changes + +# Step 3 +# We tried sed but it had some issues that ed did not +# coccinelle can't handle anonymous structs +# also some stuff is easier with ed. +# also there are bugs spatches/in coccinelle it seems :-( +# the literal deletes below suck and we need to figure +# out wtf went wrong. +ed per-file-changes/i915_drv.h << EOF +/intel_gtt/ +. +?struct *{?,/mm;/d +. +/i915_trace.h/ +. +.,/#define POSTING_READ16/d +/struct *intel_gmbus/ +.,/\*gmb/d +. +g/notifier_block/d +g/struct *drm_i915_display_funcs *display;/d +g/struct *completion *[a-z].*;/d +w +q +EOF + +ed per-file-changes/drm_crtc.h <per-file-changes/intel_bios.c +spatch -sp_file spatches/getfn.cocci inputs/intel_bios.c -U 0 > tmp/res +./plusplusplus tmp/res per-file-changes/intel_bios.c +(cd per-file-changes/; patch -p1 -R ) < tmp/res.pat + +>per-file-changes/drm_modes.c +spatch -sp_file spatches/getdrmmodefn.cocci inputs/drm_modes.c -U 0 \ + > tmp/drm_modes +./plusplusplus tmp/drm_modes per-file-changes/drm_modes.c +(cd per-file-changes/; patch -p1 -R ) < tmp/drm_modes.pat + +spatch -sp_file spatches/i915_dma.c.cocci inputs/i915_dma.c -U 0 \ + > tmp/i915_dma.c.patch +./plusplusplus tmp/i915_dma.c.patch per-file-changes/i915_dma.c +# This is the only way I can make sure the right file gets patched! +# someone tell me why. It keeps picking the wrong one. +(cd per-file-changes/; patch -p1 -R ) < tmp/i915_dma.c.patch.pat +spatch --in-place -sp_file spatches/fixcalls.cocci per-file-changes/i915_dma.c +#patch -p0 -R < tmp/i915_dma.c.patch.pat + +#echo '#include "video.h"' +>per-file-changes/i915_drv.c +spatch -sp_file spatches/i915_drv.c.cocci inputs/i915_drv.c -U 0 \ + > tmp/i915_drv.c.patch +./plusplusplus tmp/i915_drv.c.patch per-file-changes/i915_drv.c +# This is the only way I can make sure the right file gets patched! +# someone tell me why. It keeps picking the wrong one. +(cd per-file-changes/; patch -p1 -R ) < tmp/i915_drv.c.patch.pat +spatch --in-place -sp_file spatches/fixcalls.cocci per-file-changes/i915_drv.c + +# Finally, a basic spatch sequence! + +spatch --in-place -sp_file \ + spatches/intel_display.c.cocci per-file-changes/intel_display.c \ + > /dev/null + +spatch --in-place -sp_file spatches/i915_drv.cocci \ + per-file-changes/i915_drv.h >/dev/null + +# Now do the common changes to all files. +cp per-file-changes/* final +spatch --in-place -sp_file spatches/ringbuffer.cocci \ + final/intel_ringbuffer.h >/dev/null +spatch --in-place -sp_file spatches/removeinclude.cocci \ + final/intel_display.c > /dev/null +spatch --in-place -sp_file spatches/fixcalls.cocci final/intel_display.c \ + >/dev/null +spatch --in-place -sp_file spatches/ringbuffer.cocci final/drm_dp_helper.h\ + >/dev/null +spatch --in-place -sp_file spatches/removeinclude.cocci final/drm_dp_helper.h\ + >/dev/null +spatch --in-place -sp_file spatches/i915_drv.cocci final/intel_ringbuffer.h\ + >/dev/null +spatch --in-place -sp_file spatches/deldev.cocci final/intel_bios.c \ + final/intel_bios.h final/i915_drv.h final/intel_ringbuffer.h>/dev/null +spatch --in-place -sp_file spatches/fixcalls.cocci final/intel_bios.c \ + >/dev/null +spatch --in-place -sp_file spatches/drm_crtc.cocci final/drm_crtc.h >/dev/null diff --git a/util/i915tool/video.h b/util/i915tool/video.h new file mode 100644 index 0000000000..6919830c38 --- /dev/null +++ b/util/i915tool/video.h @@ -0,0 +1,133 @@ +/* cocci issues ;-( */ +#ifndef VIDEO_H +#define VIDEO_H 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* stuff we can't get coccinelle to do yet */ +#define __iomem +#define __read_mostly +#define __always_unused +#define module_param_named(a, b, c, d) +#define MODULE_PARM_DESC(a, b) +#define DRM_DEBUG_KMS printf +#define CONFIG_DRM_I915_KMS 1 +#define module_init(x); +#define module_exit(x); + +#define MODULE_AUTHOR(x) +#define MODULE_DESCRIPTION(x) +#define MODULE_LICENSE(a) +#define MODULE_DEVICE_TABLE(a, b) + +/* constants that will never change from linux/vga.h */ +/* Legacy VGA regions */ +#define VGA_RSRC_NONE 0x00 +#define VGA_RSRC_LEGACY_IO 0x01 +#define VGA_RSRC_LEGACY_MEM 0x02 +#define VGA_RSRC_LEGACY_MASK (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM) +/* Non-legacy access */ +#define VGA_RSRC_NORMAL_IO 0x04 +#define VGA_RSRC_NORMAL_MEM 0x08 + + +/* define in pci.h! */ +#include +/* idiocy. how many names to we need for a type? */ +typedef u32 uint32_t; +typedef u64 uint64_t; +/* WTF */ +typedef int bool; +enum {false = 0, true}; + +/* we define our own. The kernel one is too full of stuff. */ +struct mode_config { + int num_fb; + int num_connector; + int num_crtc; + int num_encoder; + int min_width, min_height, max_width, max_height; +}; + +struct drm_device { + struct pci_dev *pdev; + u8 *bios_bin; + struct drm_i915_private *dev_private; + struct mode_config mode_config; +}; + +/* we're willing to define our own here because it's relatively unchanging */ +#define PCI_ANY_ID (~0) + +struct pci_device_id { + u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ + u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ + u32 class, class_mask; /* (class,subclass,prog-if) triplet */ + unsigned long driver_data; /* Data private to the driver */ +}; + + +/* per the cocinelle people, they can't handle this. + * It also almost never changes */ +#define INTEL_VGA_DEVICE(id, info) { \ + .class = PCI_CLASS_DISPLAY_VGA << 8, \ + .class_mask = 0xff0000, \ + .vendor = 0x8086, \ + .device = id, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .driver_data = (unsigned long) info } + +#define wait_for(condition, time) (sleep(1+time/50) && (!condition)) + + +/* random crap from kernel.h. + * Kernel.h is a catch-all for all kinds of junk and it's + * not worth using coccinelle (yet) to pull it apart. Maybe later. + * And, yes, gcc still does not have nelem! + */ +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) +#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask)) +#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) + + +/* temporary. */ +void *dmi_check_system(unsigned long); + +#include "final/drm_dp_helper.h" +#include "final/i915_reg.h" +#include "final/i915_drv.h" +#include "final/drm_mode.h" +#include "final/drm_crtc.h" + +unsigned long I915_READ(unsigned long addr); +void I915_WRITE(unsigned long addr, unsigned long val); +u16 I915_READ16(unsigned long addr); +void I915_WRITE16(unsigned long addr, u16 val); +unsigned long msecs(void); +void mdelay(unsigned long ms); + +/* these should be the same. */ +#define POSTING_READ I915_READ +#define POSTING_READ16 I915_READ16 + +void *pci_map_rom(struct pci_dev *dev, size_t *size); +void *pci_unmap_rom(struct pci_dev *dev, void *p); +extern unsigned int i915_lvds_downclock; +extern int i915_vbt_sdvo_panel_type; +unsigned long lvds_do_not_use_alternate_frequency; +#endif /* VIDEO_H */ -- cgit v1.2.3