xref: /haiku/src/add-ons/kernel/drivers/graphics/vesa/device.cpp (revision 87784cafb89306b7e11440470a23302c14469c28)
193ee2104SAxel Dörfler /*
2bfd4c59bSAxel Dörfler  * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
393ee2104SAxel Dörfler  * Distributed under the terms of the MIT License.
493ee2104SAxel Dörfler  */
593ee2104SAxel Dörfler 
693ee2104SAxel Dörfler 
70c6f7795SAxel Dörfler #include "device.h"
893ee2104SAxel Dörfler 
993ee2104SAxel Dörfler #include <stdlib.h>
1093ee2104SAxel Dörfler #include <string.h>
1193ee2104SAxel Dörfler 
126328832fSAxel Dörfler #include <Drivers.h>
136328832fSAxel Dörfler #include <graphic_driver.h>
146328832fSAxel Dörfler #include <image.h>
156328832fSAxel Dörfler #include <KernelExport.h>
166328832fSAxel Dörfler #include <OS.h>
176328832fSAxel Dörfler #include <PCI.h>
186328832fSAxel Dörfler #include <SupportDefs.h>
196328832fSAxel Dörfler 
20bb693d77SAxel Dörfler #include <vesa.h>
21bb693d77SAxel Dörfler 
226328832fSAxel Dörfler #include "driver.h"
236328832fSAxel Dörfler #include "utility.h"
246328832fSAxel Dörfler #include "vesa_info.h"
256328832fSAxel Dörfler #include "vesa_private.h"
266328832fSAxel Dörfler #include "vga.h"
276328832fSAxel Dörfler 
2893ee2104SAxel Dörfler 
2993ee2104SAxel Dörfler //#define TRACE_DEVICE
3093ee2104SAxel Dörfler #ifdef TRACE_DEVICE
3193ee2104SAxel Dörfler #	define TRACE(x) dprintf x
3293ee2104SAxel Dörfler #else
3393ee2104SAxel Dörfler #	define TRACE(x) ;
3493ee2104SAxel Dörfler #endif
3593ee2104SAxel Dörfler 
3693ee2104SAxel Dörfler 
3793ee2104SAxel Dörfler static status_t
3893ee2104SAxel Dörfler device_open(const char* name, uint32 flags, void** _cookie)
3993ee2104SAxel Dörfler {
4093ee2104SAxel Dörfler 	int id;
4193ee2104SAxel Dörfler 
4293ee2104SAxel Dörfler 	// find accessed device
4393ee2104SAxel Dörfler 	char* thisName;
4493ee2104SAxel Dörfler 
4593ee2104SAxel Dörfler 	// search for device name
4693ee2104SAxel Dörfler 	for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
4793ee2104SAxel Dörfler 		if (!strcmp(name, thisName))
4893ee2104SAxel Dörfler 			break;
4993ee2104SAxel Dörfler 	}
50bfd4c59bSAxel Dörfler 	if (thisName == NULL)
51bfd4c59bSAxel Dörfler 		return B_BAD_VALUE;
5293ee2104SAxel Dörfler 
5393ee2104SAxel Dörfler 	vesa_info* info = gDeviceInfo[id];
5493ee2104SAxel Dörfler 
554ea01167SAxel Dörfler 	mutex_lock(&gLock);
5693ee2104SAxel Dörfler 
5793ee2104SAxel Dörfler 	status_t status = B_OK;
5893ee2104SAxel Dörfler 
59*87784cafSAlexander von Gluck IV 	if (info->open_count == 0) {
6093ee2104SAxel Dörfler 		// this device has been opened for the first time, so
6193ee2104SAxel Dörfler 		// we allocate needed resources and initialize the structure
62e5b4782bSAxel Dörfler 		if (status == B_OK)
6393ee2104SAxel Dörfler 			status = vesa_init(*info);
64e5b4782bSAxel Dörfler 		if (status == B_OK)
65e5b4782bSAxel Dörfler 			info->id = id;
6693ee2104SAxel Dörfler 	}
6793ee2104SAxel Dörfler 
68*87784cafSAlexander von Gluck IV 	if (status == B_OK) {
69*87784cafSAlexander von Gluck IV 		info->open_count++;
70*87784cafSAlexander von Gluck IV 		*_cookie = info;
71*87784cafSAlexander von Gluck IV 	}
72*87784cafSAlexander von Gluck IV 
734ea01167SAxel Dörfler 	mutex_unlock(&gLock);
7493ee2104SAxel Dörfler 	return status;
7593ee2104SAxel Dörfler }
7693ee2104SAxel Dörfler 
7793ee2104SAxel Dörfler 
7893ee2104SAxel Dörfler static status_t
7993ee2104SAxel Dörfler device_close(void* cookie)
8093ee2104SAxel Dörfler {
8193ee2104SAxel Dörfler 	return B_OK;
8293ee2104SAxel Dörfler }
8393ee2104SAxel Dörfler 
8493ee2104SAxel Dörfler 
8593ee2104SAxel Dörfler static status_t
8693ee2104SAxel Dörfler device_free(void* cookie)
8793ee2104SAxel Dörfler {
8893ee2104SAxel Dörfler 	struct vesa_info* info = (vesa_info*)cookie;
8993ee2104SAxel Dörfler 
904ea01167SAxel Dörfler 	mutex_lock(&gLock);
9193ee2104SAxel Dörfler 
9293ee2104SAxel Dörfler 	if (info->open_count-- == 1) {
9393ee2104SAxel Dörfler 		// release info structure
9493ee2104SAxel Dörfler 		vesa_uninit(*info);
9593ee2104SAxel Dörfler 	}
9693ee2104SAxel Dörfler 
974ea01167SAxel Dörfler 	mutex_unlock(&gLock);
9893ee2104SAxel Dörfler 	return B_OK;
9993ee2104SAxel Dörfler }
10093ee2104SAxel Dörfler 
10193ee2104SAxel Dörfler 
10293ee2104SAxel Dörfler static status_t
10393ee2104SAxel Dörfler device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
10493ee2104SAxel Dörfler {
10593ee2104SAxel Dörfler 	struct vesa_info* info = (vesa_info*)cookie;
10693ee2104SAxel Dörfler 
10793ee2104SAxel Dörfler 	switch (msg) {
10893ee2104SAxel Dörfler 		case B_GET_ACCELERANT_SIGNATURE:
10993ee2104SAxel Dörfler 			dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME);
1106328832fSAxel Dörfler 			if (user_strlcpy((char*)buffer, VESA_ACCELERANT_NAME,
1116328832fSAxel Dörfler 					B_FILE_NAME_LENGTH) < B_OK)
1126328832fSAxel Dörfler 				return B_BAD_ADDRESS;
1136328832fSAxel Dörfler 
11493ee2104SAxel Dörfler 			return B_OK;
11593ee2104SAxel Dörfler 
11693ee2104SAxel Dörfler 		// needed to share data between kernel and accelerant
11793ee2104SAxel Dörfler 		case VESA_GET_PRIVATE_DATA:
11893ee2104SAxel Dörfler 			return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
11993ee2104SAxel Dörfler 
12093ee2104SAxel Dörfler 		// needed for cloning
12193ee2104SAxel Dörfler 		case VESA_GET_DEVICE_NAME:
1226328832fSAxel Dörfler 			if (user_strlcpy((char*)buffer, gDeviceNames[info->id],
1236328832fSAxel Dörfler 					B_PATH_NAME_LENGTH) < B_OK)
12493ee2104SAxel Dörfler 				return B_BAD_ADDRESS;
1256328832fSAxel Dörfler 
12693ee2104SAxel Dörfler 			return B_OK;
12793ee2104SAxel Dörfler 
1289f161845SAxel Dörfler 		case VESA_SET_DISPLAY_MODE:
1299f161845SAxel Dörfler 		{
130bfd4c59bSAxel Dörfler 			if (bufferLength != sizeof(uint32))
131bfd4c59bSAxel Dörfler 				return B_BAD_VALUE;
1329f161845SAxel Dörfler 
133bfd4c59bSAxel Dörfler 			uint32 mode;
134bb693d77SAxel Dörfler 			if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK)
1359f161845SAxel Dörfler 				return B_BAD_ADDRESS;
1369f161845SAxel Dörfler 
1379f161845SAxel Dörfler 			return vesa_set_display_mode(*info, mode);
1389f161845SAxel Dörfler 		}
1399f161845SAxel Dörfler 
140bfd4c59bSAxel Dörfler 		case VESA_GET_DPMS_MODE:
141bfd4c59bSAxel Dörfler 		{
142bfd4c59bSAxel Dörfler 			if (bufferLength != sizeof(uint32))
143bfd4c59bSAxel Dörfler 				return B_BAD_VALUE;
144bfd4c59bSAxel Dörfler 
145bfd4c59bSAxel Dörfler 			uint32 mode;
146bfd4c59bSAxel Dörfler 			status_t status = vesa_get_dpms_mode(*info, mode);
147bfd4c59bSAxel Dörfler 			if (status != B_OK)
148bfd4c59bSAxel Dörfler 				return status;
149bfd4c59bSAxel Dörfler 
150bfd4c59bSAxel Dörfler 			return user_memcpy(buffer, &mode, sizeof(mode));
151bfd4c59bSAxel Dörfler 		}
152bfd4c59bSAxel Dörfler 
153bfd4c59bSAxel Dörfler 		case VESA_SET_DPMS_MODE:
154bfd4c59bSAxel Dörfler 		{
155bfd4c59bSAxel Dörfler 			if (bufferLength != sizeof(uint32))
156bfd4c59bSAxel Dörfler 				return B_BAD_VALUE;
157bfd4c59bSAxel Dörfler 
158bfd4c59bSAxel Dörfler 			uint32 mode;
159bb693d77SAxel Dörfler 			if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK)
160bfd4c59bSAxel Dörfler 				return B_BAD_ADDRESS;
161bfd4c59bSAxel Dörfler 
162bfd4c59bSAxel Dörfler 			return vesa_set_dpms_mode(*info, mode);
163bfd4c59bSAxel Dörfler 		}
164bfd4c59bSAxel Dörfler 
165bb693d77SAxel Dörfler 		case VESA_SET_INDEXED_COLORS:
1660c6f7795SAxel Dörfler 		{
167b2a75cf5SAxel Dörfler 			color_space space
168b2a75cf5SAxel Dörfler 				= (color_space)info->shared_info->current_mode.space;
169b2a75cf5SAxel Dörfler 			if (space != B_GRAY8 && space != B_CMAP8)
170b2a75cf5SAxel Dörfler 				return B_ERROR;
171b2a75cf5SAxel Dörfler 
172bb693d77SAxel Dörfler 			vesa_set_indexed_colors_args args;
173bb693d77SAxel Dörfler 			if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
1740c6f7795SAxel Dörfler 				return B_BAD_ADDRESS;
1750c6f7795SAxel Dörfler 
176b2a75cf5SAxel Dörfler 			status_t status = B_NOT_SUPPORTED;
177b2a75cf5SAxel Dörfler 			if (space != B_GRAY8) {
178b2a75cf5SAxel Dörfler 				status = vesa_set_indexed_colors(*info, args.first, args.colors,
179b2a75cf5SAxel Dörfler 					args.count);
180b2a75cf5SAxel Dörfler 			}
181bb693d77SAxel Dörfler 
182b2a75cf5SAxel Dörfler 			// Try VGA as a fallback
183b2a75cf5SAxel Dörfler 			if (status != B_OK && (info->vbe_capabilities
184b2a75cf5SAxel Dörfler 					& CAPABILITY_NOT_VGA_COMPATIBLE) == 0) {
185bb693d77SAxel Dörfler 				return vga_set_indexed_colors(args.first, args.colors,
186bb693d77SAxel Dörfler 					args.count);
187bb693d77SAxel Dörfler 			}
188bb693d77SAxel Dörfler 
189b2a75cf5SAxel Dörfler 			return status;
1900c6f7795SAxel Dörfler 		}
1910c6f7795SAxel Dörfler 
1920c6f7795SAxel Dörfler 		case VGA_PLANAR_BLIT:
1930c6f7795SAxel Dörfler 		{
194bb693d77SAxel Dörfler 			if (info->shared_info->current_mode.space != B_GRAY8
195b2a75cf5SAxel Dörfler 				|| (info->vbe_capabilities
196b2a75cf5SAxel Dörfler 					& CAPABILITY_NOT_VGA_COMPATIBLE) != 0)
197bb693d77SAxel Dörfler 				return B_NOT_SUPPORTED;
198bb693d77SAxel Dörfler 
1990c6f7795SAxel Dörfler 			vga_planar_blit_args args;
200bb693d77SAxel Dörfler 			if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
2010c6f7795SAxel Dörfler 				return B_BAD_ADDRESS;
2020c6f7795SAxel Dörfler 
2030c6f7795SAxel Dörfler 			return vga_planar_blit(info->shared_info, args.source,
2040c6f7795SAxel Dörfler 				args.source_bytes_per_row, args.left, args.top,
2050c6f7795SAxel Dörfler 				args.right, args.bottom);
2060c6f7795SAxel Dörfler 		}
2070c6f7795SAxel Dörfler 
20893ee2104SAxel Dörfler 		default:
209bfd4c59bSAxel Dörfler 			TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
210bfd4c59bSAxel Dörfler 				msg, bufferLength));
211bfd4c59bSAxel Dörfler 			break;
21293ee2104SAxel Dörfler 	}
21393ee2104SAxel Dörfler 
21493ee2104SAxel Dörfler 	return B_DEV_INVALID_IOCTL;
21593ee2104SAxel Dörfler }
21693ee2104SAxel Dörfler 
21793ee2104SAxel Dörfler 
21893ee2104SAxel Dörfler static status_t
21993ee2104SAxel Dörfler device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
22093ee2104SAxel Dörfler {
22193ee2104SAxel Dörfler 	*_length = 0;
22293ee2104SAxel Dörfler 	return B_NOT_ALLOWED;
22393ee2104SAxel Dörfler }
22493ee2104SAxel Dörfler 
22593ee2104SAxel Dörfler 
22693ee2104SAxel Dörfler static status_t
227bfd4c59bSAxel Dörfler device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
228bfd4c59bSAxel Dörfler 	size_t* _length)
22993ee2104SAxel Dörfler {
23093ee2104SAxel Dörfler 	*_length = 0;
23193ee2104SAxel Dörfler 	return B_NOT_ALLOWED;
23293ee2104SAxel Dörfler }
23393ee2104SAxel Dörfler 
234bfd4c59bSAxel Dörfler 
235bfd4c59bSAxel Dörfler device_hooks gDeviceHooks = {
236bfd4c59bSAxel Dörfler 	device_open,
237bfd4c59bSAxel Dörfler 	device_close,
238bfd4c59bSAxel Dörfler 	device_free,
239bfd4c59bSAxel Dörfler 	device_ioctl,
240bfd4c59bSAxel Dörfler 	device_read,
241bfd4c59bSAxel Dörfler 	device_write,
242bfd4c59bSAxel Dörfler 	NULL,
243bfd4c59bSAxel Dörfler 	NULL,
244bfd4c59bSAxel Dörfler 	NULL,
245bfd4c59bSAxel Dörfler 	NULL
246bfd4c59bSAxel Dörfler };
247