xref: /haiku/src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*
2  * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "device.h"
9 
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include <Drivers.h>
14 #include <graphic_driver.h>
15 #include <image.h>
16 #include <KernelExport.h>
17 #include <OS.h>
18 #include <PCI.h>
19 #include <SupportDefs.h>
20 
21 #include <vesa.h>
22 
23 #include "driver.h"
24 #include "utility.h"
25 #include "vesa_info.h"
26 #include "framebuffer_private.h"
27 
28 
29 //#define TRACE_DEVICE
30 #ifdef TRACE_DEVICE
31 #	define TRACE(x) dprintf x
32 #else
33 #	define TRACE(x) ;
34 #endif
35 
36 
37 static status_t
38 device_open(const char* name, uint32 flags, void** _cookie)
39 {
40 	int id;
41 
42 	// find accessed device
43 	char* thisName;
44 
45 	// search for device name
46 	for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
47 		if (!strcmp(name, thisName))
48 			break;
49 	}
50 	if (thisName == NULL)
51 		return B_BAD_VALUE;
52 
53 	framebuffer_info* info = gDeviceInfo[id];
54 
55 	mutex_lock(&gLock);
56 
57 	status_t status = B_OK;
58 
59 	if (info->open_count == 0) {
60 		// this device has been opened for the first time, so
61 		// we allocate needed resources and initialize the structure
62 		if (status == B_OK)
63 			status = framebuffer_init(*info);
64 		if (status == B_OK)
65 			info->id = id;
66 	}
67 
68 	if (status == B_OK) {
69 		info->open_count++;
70 		*_cookie = info;
71 	}
72 
73 	mutex_unlock(&gLock);
74 	return status;
75 }
76 
77 
78 static status_t
79 device_close(void* cookie)
80 {
81 	return B_OK;
82 }
83 
84 
85 static status_t
86 device_free(void* cookie)
87 {
88 	struct framebuffer_info* info = (framebuffer_info*)cookie;
89 
90 	mutex_lock(&gLock);
91 
92 	if (info->open_count-- == 1) {
93 		// release info structure
94 		framebuffer_uninit(*info);
95 	}
96 
97 	mutex_unlock(&gLock);
98 	return B_OK;
99 }
100 
101 
102 static status_t
103 device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
104 {
105 	struct framebuffer_info* info = (framebuffer_info*)cookie;
106 
107 	switch (msg) {
108 		case B_GET_ACCELERANT_SIGNATURE:
109 			dprintf(DEVICE_NAME ": acc: %s\n", ACCELERANT_NAME);
110 			if (user_strlcpy((char*)buffer, ACCELERANT_NAME,
111 					B_FILE_NAME_LENGTH) < B_OK)
112 				return B_BAD_ADDRESS;
113 
114 			return B_OK;
115 
116 		// needed to share data between kernel and accelerant
117 		case VESA_GET_PRIVATE_DATA:
118 			return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
119 
120 		// needed for cloning
121 		case VESA_GET_DEVICE_NAME:
122 			if (user_strlcpy((char*)buffer, gDeviceNames[info->id],
123 					B_PATH_NAME_LENGTH) < B_OK)
124 				return B_BAD_ADDRESS;
125 
126 			return B_OK;
127 
128 		default:
129 			TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
130 				msg, bufferLength));
131 			break;
132 	}
133 
134 	return B_DEV_INVALID_IOCTL;
135 }
136 
137 
138 static status_t
139 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
140 {
141 	*_length = 0;
142 	return B_NOT_ALLOWED;
143 }
144 
145 
146 static status_t
147 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
148 	size_t* _length)
149 {
150 	*_length = 0;
151 	return B_NOT_ALLOWED;
152 }
153 
154 
155 device_hooks gDeviceHooks = {
156 	device_open,
157 	device_close,
158 	device_free,
159 	device_ioctl,
160 	device_read,
161 	device_write,
162 	NULL,
163 	NULL,
164 	NULL,
165 	NULL
166 };
167