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
37static status_t
38device_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
78static status_t
79device_close(void* cookie)
80{
81	return B_OK;
82}
83
84
85static status_t
86device_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
102static status_t
103device_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
138static status_t
139device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
140{
141	*_length = 0;
142	return B_NOT_ALLOWED;
143}
144
145
146static status_t
147device_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
155device_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