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 *_cookie = info; 55 56 mutex_lock(&gLock); 57 58 status_t status = B_OK; 59 60 if (info->open_count++ == 0) { 61 // this device has been opened for the first time, so 62 // we allocate needed resources and initialize the structure 63 if (status == B_OK) 64 status = vesa_init(*info); 65 if (status == B_OK) 66 info->id = id; 67 } 68 69 mutex_unlock(&gLock); 70 return status; 71 } 72 73 74 static status_t 75 device_close(void* cookie) 76 { 77 return B_OK; 78 } 79 80 81 static status_t 82 device_free(void* cookie) 83 { 84 struct vesa_info* info = (vesa_info*)cookie; 85 86 mutex_lock(&gLock); 87 88 if (info->open_count-- == 1) { 89 // release info structure 90 vesa_uninit(*info); 91 } 92 93 mutex_unlock(&gLock); 94 return B_OK; 95 } 96 97 98 static status_t 99 device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) 100 { 101 struct vesa_info* info = (vesa_info*)cookie; 102 103 switch (msg) { 104 case B_GET_ACCELERANT_SIGNATURE: 105 dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME); 106 if (user_strlcpy((char*)buffer, VESA_ACCELERANT_NAME, 107 B_FILE_NAME_LENGTH) < B_OK) 108 return B_BAD_ADDRESS; 109 110 return B_OK; 111 112 // needed to share data between kernel and accelerant 113 case VESA_GET_PRIVATE_DATA: 114 return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); 115 116 // needed for cloning 117 case VESA_GET_DEVICE_NAME: 118 if (user_strlcpy((char*)buffer, gDeviceNames[info->id], 119 B_PATH_NAME_LENGTH) < B_OK) 120 return B_BAD_ADDRESS; 121 122 return B_OK; 123 124 case VESA_SET_DISPLAY_MODE: 125 { 126 if (bufferLength != sizeof(uint32)) 127 return B_BAD_VALUE; 128 129 uint32 mode; 130 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 131 return B_BAD_ADDRESS; 132 133 return vesa_set_display_mode(*info, mode); 134 } 135 136 case VESA_GET_DPMS_MODE: 137 { 138 if (bufferLength != sizeof(uint32)) 139 return B_BAD_VALUE; 140 141 uint32 mode; 142 status_t status = vesa_get_dpms_mode(*info, mode); 143 if (status != B_OK) 144 return status; 145 146 return user_memcpy(buffer, &mode, sizeof(mode)); 147 } 148 149 case VESA_SET_DPMS_MODE: 150 { 151 if (bufferLength != sizeof(uint32)) 152 return B_BAD_VALUE; 153 154 uint32 mode; 155 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 156 return B_BAD_ADDRESS; 157 158 return vesa_set_dpms_mode(*info, mode); 159 } 160 161 case VESA_SET_INDEXED_COLORS: 162 { 163 color_space space 164 = (color_space)info->shared_info->current_mode.space; 165 if (space != B_GRAY8 && space != B_CMAP8) 166 return B_ERROR; 167 168 vesa_set_indexed_colors_args args; 169 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 170 return B_BAD_ADDRESS; 171 172 status_t status = B_NOT_SUPPORTED; 173 if (space != B_GRAY8) { 174 status = vesa_set_indexed_colors(*info, args.first, args.colors, 175 args.count); 176 } 177 178 // Try VGA as a fallback 179 if (status != B_OK && (info->vbe_capabilities 180 & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) { 181 return vga_set_indexed_colors(args.first, args.colors, 182 args.count); 183 } 184 185 return status; 186 } 187 188 case VGA_PLANAR_BLIT: 189 { 190 if (info->shared_info->current_mode.space != B_GRAY8 191 || (info->vbe_capabilities 192 & CAPABILITY_NOT_VGA_COMPATIBLE) != 0) 193 return B_NOT_SUPPORTED; 194 195 vga_planar_blit_args args; 196 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 197 return B_BAD_ADDRESS; 198 199 return vga_planar_blit(info->shared_info, args.source, 200 args.source_bytes_per_row, args.left, args.top, 201 args.right, args.bottom); 202 } 203 204 default: 205 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", 206 msg, bufferLength)); 207 break; 208 } 209 210 return B_DEV_INVALID_IOCTL; 211 } 212 213 214 static status_t 215 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 216 { 217 *_length = 0; 218 return B_NOT_ALLOWED; 219 } 220 221 222 static status_t 223 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/, 224 size_t* _length) 225 { 226 *_length = 0; 227 return B_NOT_ALLOWED; 228 } 229 230 231 device_hooks gDeviceHooks = { 232 device_open, 233 device_close, 234 device_free, 235 device_ioctl, 236 device_read, 237 device_write, 238 NULL, 239 NULL, 240 NULL, 241 NULL 242 }; 243