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