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 if (info->shared_info->bios_type == kUnknownBiosType) 146 return B_NOT_ALLOWED; 147 148 display_mode mode; 149 if (user_memcpy(&mode, buffer, sizeof(display_mode)) != B_OK) 150 return B_BAD_ADDRESS; 151 152 return vesa_set_custom_display_mode(*info, mode); 153 } 154 155 case VESA_GET_DPMS_MODE: 156 { 157 if (bufferLength != sizeof(uint32)) 158 return B_BAD_VALUE; 159 160 uint32 mode; 161 status_t status = vesa_get_dpms_mode(*info, mode); 162 if (status != B_OK) 163 return status; 164 165 return user_memcpy(buffer, &mode, sizeof(mode)); 166 } 167 168 case VESA_SET_DPMS_MODE: 169 { 170 if (bufferLength != sizeof(uint32)) 171 return B_BAD_VALUE; 172 173 uint32 mode; 174 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 175 return B_BAD_ADDRESS; 176 177 return vesa_set_dpms_mode(*info, mode); 178 } 179 180 case VESA_SET_INDEXED_COLORS: 181 { 182 color_space space 183 = (color_space)info->shared_info->current_mode.space; 184 if (space != B_GRAY8 && space != B_CMAP8) 185 return B_ERROR; 186 187 vesa_set_indexed_colors_args args; 188 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 189 return B_BAD_ADDRESS; 190 191 status_t status = B_NOT_SUPPORTED; 192 if (space != B_GRAY8) { 193 status = vesa_set_indexed_colors(*info, args.first, args.colors, 194 args.count); 195 } 196 197 // Try VGA as a fallback 198 if (status != B_OK && (info->vbe_capabilities 199 & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) { 200 return vga_set_indexed_colors(args.first, args.colors, 201 args.count); 202 } 203 204 return status; 205 } 206 207 case VGA_PLANAR_BLIT: 208 { 209 if (info->shared_info->current_mode.space != B_GRAY8 210 || (info->vbe_capabilities 211 & CAPABILITY_NOT_VGA_COMPATIBLE) != 0) 212 return B_NOT_SUPPORTED; 213 214 vga_planar_blit_args args; 215 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 216 return B_BAD_ADDRESS; 217 218 return vga_planar_blit(info->shared_info, args.source, 219 args.source_bytes_per_row, args.left, args.top, 220 args.right, args.bottom); 221 } 222 223 default: 224 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", 225 msg, bufferLength)); 226 break; 227 } 228 229 return B_DEV_INVALID_IOCTL; 230 } 231 232 233 static status_t 234 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 235 { 236 *_length = 0; 237 return B_NOT_ALLOWED; 238 } 239 240 241 static status_t 242 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/, 243 size_t* _length) 244 { 245 *_length = 0; 246 return B_NOT_ALLOWED; 247 } 248 249 250 device_hooks gDeviceHooks = { 251 device_open, 252 device_close, 253 device_free, 254 device_ioctl, 255 device_read, 256 device_write, 257 NULL, 258 NULL, 259 NULL, 260 NULL 261 }; 262