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
device_open(const char * name,uint32 flags,void ** _cookie)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
5987784cafSAlexander 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
6887784cafSAlexander von Gluck IV if (status == B_OK) {
6987784cafSAlexander von Gluck IV info->open_count++;
7087784cafSAlexander von Gluck IV *_cookie = info;
7187784cafSAlexander von Gluck IV }
7287784cafSAlexander 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
device_close(void * cookie)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
device_free(void * cookie)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
device_ioctl(void * cookie,uint32 msg,void * buffer,size_t bufferLength)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
1401005a276SAdrien Destugues case VESA_SET_CUSTOM_DISPLAY_MODE:
1411005a276SAdrien Destugues {
1421005a276SAdrien Destugues if (bufferLength != sizeof(display_mode))
1431005a276SAdrien Destugues return B_BAD_VALUE;
1441005a276SAdrien Destugues
145*9fec431fSPulkoMandy if (info->shared_info->bios_type == kUnknownBiosType)
146*9fec431fSPulkoMandy return B_NOT_ALLOWED;
147*9fec431fSPulkoMandy
1481005a276SAdrien Destugues display_mode mode;
1491005a276SAdrien Destugues if (user_memcpy(&mode, buffer, sizeof(display_mode)) != B_OK)
1501005a276SAdrien Destugues return B_BAD_ADDRESS;
1511005a276SAdrien Destugues
1521005a276SAdrien Destugues return vesa_set_custom_display_mode(*info, mode);
1531005a276SAdrien Destugues }
1541005a276SAdrien Destugues
155bfd4c59bSAxel Dörfler case VESA_GET_DPMS_MODE:
156bfd4c59bSAxel Dörfler {
157bfd4c59bSAxel Dörfler if (bufferLength != sizeof(uint32))
158bfd4c59bSAxel Dörfler return B_BAD_VALUE;
159bfd4c59bSAxel Dörfler
160bfd4c59bSAxel Dörfler uint32 mode;
161bfd4c59bSAxel Dörfler status_t status = vesa_get_dpms_mode(*info, mode);
162bfd4c59bSAxel Dörfler if (status != B_OK)
163bfd4c59bSAxel Dörfler return status;
164bfd4c59bSAxel Dörfler
165bfd4c59bSAxel Dörfler return user_memcpy(buffer, &mode, sizeof(mode));
166bfd4c59bSAxel Dörfler }
167bfd4c59bSAxel Dörfler
168bfd4c59bSAxel Dörfler case VESA_SET_DPMS_MODE:
169bfd4c59bSAxel Dörfler {
170bfd4c59bSAxel Dörfler if (bufferLength != sizeof(uint32))
171bfd4c59bSAxel Dörfler return B_BAD_VALUE;
172bfd4c59bSAxel Dörfler
173bfd4c59bSAxel Dörfler uint32 mode;
174bb693d77SAxel Dörfler if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK)
175bfd4c59bSAxel Dörfler return B_BAD_ADDRESS;
176bfd4c59bSAxel Dörfler
177bfd4c59bSAxel Dörfler return vesa_set_dpms_mode(*info, mode);
178bfd4c59bSAxel Dörfler }
179bfd4c59bSAxel Dörfler
180bb693d77SAxel Dörfler case VESA_SET_INDEXED_COLORS:
1810c6f7795SAxel Dörfler {
182b2a75cf5SAxel Dörfler color_space space
183b2a75cf5SAxel Dörfler = (color_space)info->shared_info->current_mode.space;
184b2a75cf5SAxel Dörfler if (space != B_GRAY8 && space != B_CMAP8)
185b2a75cf5SAxel Dörfler return B_ERROR;
186b2a75cf5SAxel Dörfler
187bb693d77SAxel Dörfler vesa_set_indexed_colors_args args;
188bb693d77SAxel Dörfler if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
1890c6f7795SAxel Dörfler return B_BAD_ADDRESS;
1900c6f7795SAxel Dörfler
191b2a75cf5SAxel Dörfler status_t status = B_NOT_SUPPORTED;
192b2a75cf5SAxel Dörfler if (space != B_GRAY8) {
193b2a75cf5SAxel Dörfler status = vesa_set_indexed_colors(*info, args.first, args.colors,
194b2a75cf5SAxel Dörfler args.count);
195b2a75cf5SAxel Dörfler }
196bb693d77SAxel Dörfler
197b2a75cf5SAxel Dörfler // Try VGA as a fallback
198b2a75cf5SAxel Dörfler if (status != B_OK && (info->vbe_capabilities
199b2a75cf5SAxel Dörfler & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) {
200bb693d77SAxel Dörfler return vga_set_indexed_colors(args.first, args.colors,
201bb693d77SAxel Dörfler args.count);
202bb693d77SAxel Dörfler }
203bb693d77SAxel Dörfler
204b2a75cf5SAxel Dörfler return status;
2050c6f7795SAxel Dörfler }
2060c6f7795SAxel Dörfler
2070c6f7795SAxel Dörfler case VGA_PLANAR_BLIT:
2080c6f7795SAxel Dörfler {
209bb693d77SAxel Dörfler if (info->shared_info->current_mode.space != B_GRAY8
210b2a75cf5SAxel Dörfler || (info->vbe_capabilities
211b2a75cf5SAxel Dörfler & CAPABILITY_NOT_VGA_COMPATIBLE) != 0)
212bb693d77SAxel Dörfler return B_NOT_SUPPORTED;
213bb693d77SAxel Dörfler
2140c6f7795SAxel Dörfler vga_planar_blit_args args;
215bb693d77SAxel Dörfler if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
2160c6f7795SAxel Dörfler return B_BAD_ADDRESS;
2170c6f7795SAxel Dörfler
2180c6f7795SAxel Dörfler return vga_planar_blit(info->shared_info, args.source,
2190c6f7795SAxel Dörfler args.source_bytes_per_row, args.left, args.top,
2200c6f7795SAxel Dörfler args.right, args.bottom);
2210c6f7795SAxel Dörfler }
2220c6f7795SAxel Dörfler
22393ee2104SAxel Dörfler default:
224bfd4c59bSAxel Dörfler TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
225bfd4c59bSAxel Dörfler msg, bufferLength));
226bfd4c59bSAxel Dörfler break;
22793ee2104SAxel Dörfler }
22893ee2104SAxel Dörfler
22993ee2104SAxel Dörfler return B_DEV_INVALID_IOCTL;
23093ee2104SAxel Dörfler }
23193ee2104SAxel Dörfler
23293ee2104SAxel Dörfler
23393ee2104SAxel Dörfler static status_t
device_read(void *,off_t,void *,size_t * _length)23493ee2104SAxel Dörfler device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
23593ee2104SAxel Dörfler {
23693ee2104SAxel Dörfler *_length = 0;
23793ee2104SAxel Dörfler return B_NOT_ALLOWED;
23893ee2104SAxel Dörfler }
23993ee2104SAxel Dörfler
24093ee2104SAxel Dörfler
24193ee2104SAxel Dörfler static status_t
device_write(void *,off_t,const void *,size_t * _length)242bfd4c59bSAxel Dörfler device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
243bfd4c59bSAxel Dörfler size_t* _length)
24493ee2104SAxel Dörfler {
24593ee2104SAxel Dörfler *_length = 0;
24693ee2104SAxel Dörfler return B_NOT_ALLOWED;
24793ee2104SAxel Dörfler }
24893ee2104SAxel Dörfler
249bfd4c59bSAxel Dörfler
250bfd4c59bSAxel Dörfler device_hooks gDeviceHooks = {
251bfd4c59bSAxel Dörfler device_open,
252bfd4c59bSAxel Dörfler device_close,
253bfd4c59bSAxel Dörfler device_free,
254bfd4c59bSAxel Dörfler device_ioctl,
255bfd4c59bSAxel Dörfler device_read,
256bfd4c59bSAxel Dörfler device_write,
257bfd4c59bSAxel Dörfler NULL,
258bfd4c59bSAxel Dörfler NULL,
259bfd4c59bSAxel Dörfler NULL,
260bfd4c59bSAxel Dörfler NULL
261bfd4c59bSAxel Dörfler };
262