summaryrefslogtreecommitdiff
path: root/bsd-core/i915_drv.c
blob: e6769d17e35172e7e9c18dc288dee55b06672667 (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
113
114
115
116
117
118
119
120
121
122
/* i915_drv.c -- Intel i915 driver -*- linux-c -*-
 * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
 */
/*-
 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
 * All Rights Reserved.
 *
 * 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
 * VA LINUX SYSTEMS AND/OR ITS 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:
 *    Gareth Hughes <gareth@valinux.com>
 *
 */

#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "drm_pciids.h"

/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
static drm_pci_id_list_t i915_pciidlist[] = {
	i915_PCI_IDS
};

static void i915_configure(struct drm_device *dev)
{
	dev->driver.buf_priv_size	= 1;	/* No dev_priv */
	dev->driver.load		= i915_driver_load;
	dev->driver.preclose		= i915_driver_preclose;
	dev->driver.lastclose		= i915_driver_lastclose;
	dev->driver.device_is_agp	= i915_driver_device_is_agp;
	dev->driver.get_vblank_counter	= i915_get_vblank_counter;
	dev->driver.enable_vblank	= i915_enable_vblank;
	dev->driver.disable_vblank	= i915_disable_vblank;
	dev->driver.irq_preinstall	= i915_driver_irq_preinstall;
	dev->driver.irq_postinstall	= i915_driver_irq_postinstall;
	dev->driver.irq_uninstall	= i915_driver_irq_uninstall;
	dev->driver.irq_handler		= i915_driver_irq_handler;

	dev->driver.ioctls		= i915_ioctls;
	dev->driver.max_ioctl		= i915_max_ioctl;

	dev->driver.name		= DRIVER_NAME;
	dev->driver.desc		= DRIVER_DESC;
	dev->driver.date		= DRIVER_DATE;
	dev->driver.major		= DRIVER_MAJOR;
	dev->driver.minor		= DRIVER_MINOR;
	dev->driver.patchlevel		= DRIVER_PATCHLEVEL;

	dev->driver.use_agp		= 1;
	dev->driver.require_agp		= 1;
	dev->driver.use_mtrr		= 1;
	dev->driver.use_irq		= 1;
	dev->driver.use_vbl_irq		= 1;
	dev->driver.use_vbl_irq2	= 1;
}

#ifdef __FreeBSD__
static int
i915_probe(device_t dev)
{
	return drm_probe(dev, i915_pciidlist);
}

static int
i915_attach(device_t nbdev)
{
	struct drm_device *dev = device_get_softc(nbdev);

	bzero(dev, sizeof(struct drm_device));
	i915_configure(dev);
	return drm_attach(nbdev, i915_pciidlist);
}

static device_method_t i915_methods[] = {
	/* Device interface */
	DEVMETHOD(device_probe,		i915_probe),
	DEVMETHOD(device_attach,	i915_attach),
	DEVMETHOD(device_detach,	drm_detach),

	{ 0, 0 }
};

static driver_t i915_driver = {
#if __FreeBSD_version >= 700010
	"drm",
#else
	"drmsub",
#endif
	i915_methods,
	sizeof(struct drm_device)
};

extern devclass_t drm_devclass;
#if __FreeBSD_version >= 700010
DRIVER_MODULE(i915, vgapci, i915_driver, drm_devclass, 0, 0);
#else
DRIVER_MODULE(i915, agp, i915_driver, drm_devclass, 0, 0);
#endif
MODULE_DEPEND(i915, drm, 1, 1, 1);

#elif defined(__NetBSD__) || defined(__OpenBSD__)
CFDRIVER_DECL(i915, DV_TTY, NULL);
#endif
by 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 <errno.h> #include <stdlib.h> #include <string.h> #include "bof.h" /* * helpers */ static int bof_entry_grow(bof_t *bof) { bof_t **array; if (bof->array_size < bof->nentry) return 0; array = realloc(bof->array, (bof->nentry + 16) * sizeof(void*)); if (array == NULL) return -ENOMEM; bof->array = array; bof->nentry += 16; return 0; } /* * object */ bof_t *bof_object(void) { bof_t *object; object = calloc(1, sizeof(bof_t)); if (object == NULL) return NULL; object->refcount = 1; object->type = BOF_TYPE_OBJECT; object->size = 12; return object; } bof_t *bof_object_get(bof_t *object, const char *keyname) { unsigned i; for (i = 0; i < object->array_size; i += 2) { if (!strcmp(object->array[i]->value, keyname)) { return object->array[i + 1]; } } return NULL; } int bof_object_set(bof_t *object, const char *keyname, bof_t *value) { bof_t *key; int r; if (object->type != BOF_TYPE_OBJECT) return -EINVAL; r = bof_entry_grow(object); if (r) return r; key = bof_string(keyname); if (key == NULL) return -ENOMEM; object->array[object->array_size++] = key; object->array[object->array_size++] = value; object->size += value->size; object->size += key->size; bof_incref(value); return 0; } /* * array */ bof_t *bof_array(void) { bof_t *array = bof_object(); if (array == NULL) return NULL; array->type = BOF_TYPE_ARRAY; array->size = 12; return array; } int bof_array_append(bof_t *array, bof_t *value) { int r; if (array->type != BOF_TYPE_ARRAY) return -EINVAL; r = bof_entry_grow(array); if (r) return r; array->array[array->array_size++] = value; array->size += value->size; bof_incref(value); return 0; } bof_t *bof_array_get(bof_t *bof, unsigned i) { if (!bof_is_array(bof) || i >= bof->array_size) return NULL; return bof->array[i]; } unsigned bof_array_size(bof_t *bof) { if (!bof_is_array(bof)) return 0; return bof->array_size; } /* * blob */ bof_t *bof_blob(unsigned size, void *value) { bof_t *blob = bof_object(); if (blob == NULL) return NULL; blob->type = BOF_TYPE_BLOB; blob->value = calloc(1, size); if (blob->value == NULL) { bof_decref(blob); return NULL; } blob->size = size; memcpy(blob->value, value, size); blob->size += 12; return blob; } unsigned bof_blob_size(bof_t *bof) { if (!bof_is_blob(bof)) return 0; return bof->size - 12; } void *bof_blob_value(bof_t *bof) { if (!bof_is_blob(bof)) return NULL; return bof->value; } /* * string */ bof_t *bof_string(const char *value) { bof_t *string = bof_object(); if (string == NULL) return NULL; string->type = BOF_TYPE_STRING; string->size = strlen(value) + 1; string->value = calloc(1, string->size); if (string->value == NULL) { bof_decref(string); return NULL; } strcpy(string->value, value); string->size += 12; return string; } /* * int32 */ bof_t *bof_int32(int32_t value) { bof_t *int32 = bof_object(); if (int32 == NULL) return NULL; int32->type = BOF_TYPE_INT32; int32->size = 4; int32->value = calloc(1, int32->size); if (int32->value == NULL) { bof_decref(int32); return NULL; } memcpy(int32->value, &value, 4); int32->size += 12; return int32; } int32_t bof_int32_value(bof_t *bof) { return *((uint32_t*)bof->value); } /* * common */ static void bof_indent(int level) { int i; for (i = 0; i < level; i++) fprintf(stderr, " "); } static void bof_print_bof(bof_t *bof, int level, int entry) { bof_indent(level); if (bof == NULL) { fprintf(stderr, "--NULL-- for entry %d\n", entry); return; } switch (bof->type) { case BOF_TYPE_STRING: fprintf(stderr, "%p string [%s %d]\n", bof, (char*)bof->value, bof->size); break; case BOF_TYPE_INT32: fprintf(stderr, "%p int32 [%d %d]\n", bof, *(int*)bof->value, bof->size); break; case BOF_TYPE_BLOB: fprintf(stderr, "%p blob [%d]\n", bof, bof->size); break; case BOF_TYPE_NULL: fprintf(stderr, "%p null [%d]\n", bof, bof->size); break; case BOF_TYPE_OBJECT: fprintf(stderr, "%p object [%d %d]\n", bof, bof->array_size / 2, bof->size); break; case BOF_TYPE_ARRAY: fprintf(stderr, "%p array [%d %d]\n", bof, bof->array_size, bof->size); break; default: fprintf(stderr, "%p unknown [%d]\n", bof, bof->type); return; } } static void bof_print_rec(bof_t *bof, int level, int entry) { unsigned i; bof_print_bof(bof, level, entry); for (i = 0; i < bof->array_size; i++) { bof_print_rec(bof->array[i], level + 2, i); } } void bof_print(bof_t *bof) { bof_print_rec(bof, 0, 0); } static int bof_read(bof_t *root, FILE *file, long end, int level) { bof_t *bof = NULL; int r; if (ftell(file) >= end) { return 0; } r = bof_entry_grow(root); if (r) return r; bof = bof_object(); if (bof == NULL) return -ENOMEM; bof->offset = ftell(file); r = fread(&bof->type, 4, 1, file); if (r != 1) goto out_err; r = fread(&bof->size, 4, 1, file); if (r != 1) goto out_err; r = fread(&bof->array_size, 4, 1, file); if (r != 1) goto out_err; switch (bof->type) { case BOF_TYPE_STRING: case BOF_TYPE_INT32: case BOF_TYPE_BLOB: bof->value = calloc(1, bof->size - 12); if (bof->value == NULL) { goto out_err; } r = fread(bof->value, bof->size - 12, 1, file); if (r != 1) { fprintf(stderr, "error reading %d\n", bof->size - 12); goto out_err; } break; case BOF_TYPE_NULL: return 0; case BOF_TYPE_OBJECT: case BOF_TYPE_ARRAY: r = bof_read(bof, file, bof->offset + bof->size, level + 2); if (r) goto out_err; break; default: fprintf(stderr, "invalid type %d\n", bof->type); goto out_err; } root->array[root->centry++] = bof; return bof_read(root, file, end, level); out_err: bof_decref(bof); return -EINVAL; } bof_t *bof_load_file(const char *filename) { bof_t *root = bof_object(); int r; if (root == NULL) { fprintf(stderr, "%s failed to create root object\n", __func__); return NULL; } root->file = fopen(filename, "r"); if (root->file == NULL) goto out_err; r = fseek(root->file, 0L, SEEK_SET); if (r) { fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename); goto out_err; } root->offset = ftell(root->file); r = fread(&root->type, 4, 1, root->file); if (r != 1) goto out_err; r = fread(&root->size, 4, 1, root->file); if (r != 1) goto out_err; r = fread(&root->array_size, 4, 1, root->file); if (r != 1) goto out_err; r = bof_read(root, root->file, root->offset + root->size, 2); if (r) goto out_err; return root; out_err: bof_decref(root); return NULL; } void bof_incref(bof_t *bof) { bof->refcount++; } void bof_decref(bof_t *bof) { unsigned i; if (bof == NULL) return; if (--bof->refcount > 0) return; for (i = 0; i < bof->array_size; i++) { bof_decref(bof->array[i]); bof->array[i] = NULL; } bof->array_size = 0; if (bof->file) { fclose(bof->file); bof->file = NULL; } free(bof->array); free(bof->value); free(bof); } static int bof_file_write(bof_t *bof, FILE *file) { unsigned i; int r; r = fwrite(&bof->type, 4, 1, file); if (r != 1) return -EINVAL; r = fwrite(&bof->size, 4, 1, file); if (r != 1) return -EINVAL; r = fwrite(&bof->array_size, 4, 1, file); if (r != 1) return -EINVAL; switch (bof->type) { case BOF_TYPE_NULL: if (bof->size) return -EINVAL; break; case BOF_TYPE_STRING: case BOF_TYPE_INT32: case BOF_TYPE_BLOB: r = fwrite(bof->value, bof->size - 12, 1, file); if (r != 1) return -EINVAL; break; case BOF_TYPE_OBJECT: case BOF_TYPE_ARRAY: for (i = 0; i < bof->array_size; i++) { r = bof_file_write(bof->array[i], file); if (r) return r; } break; default: return -EINVAL; } return 0; } int bof_dump_file(bof_t *bof, const char *filename) { unsigned i; int r = 0; if (bof->file) { fclose(bof->file); bof->file = NULL; } bof->file = fopen(filename, "w"); if (bof->file == NULL) { fprintf(stderr, "%s failed to open file %s\n", __func__, filename); r = -EINVAL; goto out_err; } r = fseek(bof->file, 0L, SEEK_SET); if (r) { fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename); goto out_err; } r = fwrite(&bof->type, 4, 1, bof->file); if (r != 1) goto out_err; r = fwrite(&bof->size, 4, 1, bof->file); if (r != 1) goto out_err; r = fwrite(&bof->array_size, 4, 1, bof->file); if (r != 1) goto out_err; for (i = 0; i < bof->array_size; i++) { r = bof_file_write(bof->array[i], bof->file); if (r) return r; } out_err: fclose(bof->file); bof->file = NULL; return r; }