1 /* 2 * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. 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 <vesa.h> 21 22 #include "driver.h" 23 #include "utility.h" 24 #include "vesa_info.h" 25 #include "vesa_private.h" 26 #include "vga.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 vesa_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 = vesa_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 vesa_info* info = (vesa_info*)cookie; 89 90 mutex_lock(&gLock); 91 92 if (info->open_count-- == 1) { 93 // release info structure 94 vesa_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 vesa_info* info = (vesa_info*)cookie; 106 107 switch (msg) { 108 case B_GET_ACCELERANT_SIGNATURE: 109 dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME); 110 if (user_strlcpy((char*)buffer, VESA_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 case VESA_SET_DISPLAY_MODE: 129 { 130 if (bufferLength != sizeof(uint32)) 131 return B_BAD_VALUE; 132 133 uint32 mode; 134 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 135 return B_BAD_ADDRESS; 136 137 return vesa_set_display_mode(*info, mode); 138 } 139 140 case VESA_SET_CUSTOM_DISPLAY_MODE: 141 { 142 if (bufferLength != sizeof(display_mode)) 143 return B_BAD_VALUE; 144 145 display_mode mode; 146 if (user_memcpy(&mode, buffer, sizeof(display_mode)) != B_OK) 147 return B_BAD_ADDRESS; 148 149 return vesa_set_custom_display_mode(*info, mode); 150 } 151 152 case VESA_GET_DPMS_MODE: 153 { 154 if (bufferLength != sizeof(uint32)) 155 return B_BAD_VALUE; 156 157 uint32 mode; 158 status_t status = vesa_get_dpms_mode(*info, mode); 159 if (status != B_OK) 160 return status; 161 162 return user_memcpy(buffer, &mode, sizeof(mode)); 163 } 164 165 case VESA_SET_DPMS_MODE: 166 { 167 if (bufferLength != sizeof(uint32)) 168 return B_BAD_VALUE; 169 170 uint32 mode; 171 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 172 return B_BAD_ADDRESS; 173 174 return vesa_set_dpms_mode(*info, mode); 175 } 176 177 case VESA_SET_INDEXED_COLORS: 178 { 179 color_space space 180 = (color_space)info->shared_info->current_mode.space; 181 if (space != B_GRAY8 && space != B_CMAP8) 182 return B_ERROR; 183 184 vesa_set_indexed_colors_args args; 185 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 186 return B_BAD_ADDRESS; 187 188 status_t status = B_NOT_SUPPORTED; 189 if (space != B_GRAY8) { 190 status = vesa_set_indexed_colors(*info, args.first, args.colors, 191 args.count); 192 } 193 194 // Try VGA as a fallback 195 if (status != B_OK && (info->vbe_capabilities 196 & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) { 197 return vga_set_indexed_colors(args.first, args.colors, 198 args.count); 199 } 200 201 return status; 202 } 203 204 case VGA_PLANAR_BLIT: 205 { 206 if (info->shared_info->current_mode.space != B_GRAY8 207 || (info->vbe_capabilities 208 & CAPABILITY_NOT_VGA_COMPATIBLE) != 0) 209 return B_NOT_SUPPORTED; 210 211 vga_planar_blit_args args; 212 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 213 return B_BAD_ADDRESS; 214 215 return vga_planar_blit(info->shared_info, args.source, 216 args.source_bytes_per_row, args.left, args.top, 217 args.right, args.bottom); 218 } 219 220 default: 221 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", 222 msg, bufferLength)); 223 break; 224 } 225 226 return B_DEV_INVALID_IOCTL; 227 } 228 229 230 static status_t 231 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 232 { 233 *_length = 0; 234 return B_NOT_ALLOWED; 235 } 236 237 238 static status_t 239 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/, 240 size_t* _length) 241 { 242 *_length = 0; 243 return B_NOT_ALLOWED; 244 } 245 246 247 device_hooks gDeviceHooks = { 248 device_open, 249 device_close, 250 device_free, 251 device_ioctl, 252 device_read, 253 device_write, 254 NULL, 255 NULL, 256 NULL, 257 NULL 258 }; 259