xref: /haiku/src/add-ons/kernel/drivers/graphics/vesa/device.cpp (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
1 /*
2  * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "device.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <Drivers.h>
13 #include <graphic_driver.h>
14 #include <image.h>
15 #include <KernelExport.h>
16 #include <OS.h>
17 #include <PCI.h>
18 #include <SupportDefs.h>
19 
20 #include "driver.h"
21 #include "utility.h"
22 #include "vesa_info.h"
23 #include "vesa_private.h"
24 #include "vga.h"
25 
26 
27 //#define TRACE_DEVICE
28 #ifdef TRACE_DEVICE
29 #	define TRACE(x) dprintf x
30 #else
31 #	define TRACE(x) ;
32 #endif
33 
34 
35 /* device hooks prototypes */
36 
37 static status_t device_open(const char *, uint32, void **);
38 static status_t device_close(void *);
39 static status_t device_free(void *);
40 static status_t device_ioctl(void *, uint32, void *, size_t);
41 static status_t device_read(void *, off_t, void *, size_t *);
42 static status_t device_write(void *, off_t, const void *, size_t *);
43 
44 
45 device_hooks gDeviceHooks = {
46 	device_open,
47 	device_close,
48 	device_free,
49 	device_ioctl,
50 	device_read,
51 	device_write,
52 	NULL,
53 	NULL,
54 	NULL,
55 	NULL
56 };
57 
58 
59 //	#pragma mark -
60 //	the device will be accessed through the following functions (a.k.a. device hooks)
61 
62 
63 static status_t
64 device_open(const char *name, uint32 flags, void **_cookie)
65 {
66 	int id;
67 
68 	// find accessed device
69 	{
70 		char *thisName;
71 
72 		// search for device name
73 		for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
74 			if (!strcmp(name, thisName))
75 				break;
76 		}
77 		if (!thisName)
78 			return EINVAL;
79 	}
80 
81 	vesa_info *info = gDeviceInfo[id];
82 	*_cookie = info;
83 
84 	acquire_lock(&gLock);
85 
86 	status_t status = B_OK;
87 
88 	if (info->open_count++ == 0) {
89 		// this device has been opened for the first time, so
90 		// we allocate needed resources and initialize the structure
91 		if (status == B_OK)
92 			status = vesa_init(*info);
93 		if (status == B_OK)
94 			info->id = id;
95 	}
96 
97 	release_lock(&gLock);
98 	return status;
99 }
100 
101 
102 static status_t
103 device_close(void *cookie)
104 {
105 	return B_OK;
106 }
107 
108 
109 static status_t
110 device_free(void *cookie)
111 {
112 	struct vesa_info *info = (vesa_info *)cookie;
113 
114 	acquire_lock(&gLock);
115 
116 	if (info->open_count-- == 1) {
117 		// release info structure
118 		vesa_uninit(*info);
119 	}
120 
121 	release_lock(&gLock);
122 	return B_OK;
123 }
124 
125 
126 static status_t
127 device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
128 {
129 	struct vesa_info *info = (vesa_info *)cookie;
130 
131 	switch (msg) {
132 		case B_GET_ACCELERANT_SIGNATURE:
133 			dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME);
134 			if (user_strlcpy((char *)buffer, VESA_ACCELERANT_NAME,
135 					B_FILE_NAME_LENGTH) < B_OK)
136 				return B_BAD_ADDRESS;
137 
138 			return B_OK;
139 
140 		// needed to share data between kernel and accelerant
141 		case VESA_GET_PRIVATE_DATA:
142 			return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
143 
144 		// needed for cloning
145 		case VESA_GET_DEVICE_NAME:
146 			if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
147 					B_PATH_NAME_LENGTH) < B_OK)
148 				return B_BAD_ADDRESS;
149 
150 			return B_OK;
151 
152 		case VGA_SET_INDEXED_COLORS:
153 		{
154 			vga_set_indexed_colors_args args;
155 			if (user_memcpy(&args, buffer, sizeof(args)) < B_OK)
156 				return B_BAD_ADDRESS;
157 
158 			return vga_set_indexed_colors(args.first, args.colors, args.count);
159 		}
160 
161 		case VGA_PLANAR_BLIT:
162 		{
163 			vga_planar_blit_args args;
164 			if (user_memcpy(&args, buffer, sizeof(args)) < B_OK)
165 				return B_BAD_ADDRESS;
166 
167 			return vga_planar_blit(info->shared_info, args.source,
168 				args.source_bytes_per_row, args.left, args.top,
169 				args.right, args.bottom);
170 		}
171 
172 		default:
173 			TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength));
174 	}
175 
176 	return B_DEV_INVALID_IOCTL;
177 }
178 
179 
180 static status_t
181 device_read(void */*cookie*/, off_t /*pos*/, void */*buffer*/, size_t *_length)
182 {
183 	*_length = 0;
184 	return B_NOT_ALLOWED;
185 }
186 
187 
188 static status_t
189 device_write(void */*cookie*/, off_t /*pos*/, const void */*buffer*/, size_t *_length)
190 {
191 	*_length = 0;
192 	return B_NOT_ALLOWED;
193 }
194 
195