1 /* 2 * Copyright 2005, Jérôme DUVAL. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <Drivers.h> 7 #include <OS.h> 8 #include <bus_manager.h> 9 #include <malloc.h> 10 #include <module.h> 11 #include <stdio.h> 12 #include <string.h> 13 #include <sys/ioccom.h> 14 #include <sys/ioctl.h> 15 16 #define __KERNEL__ 17 #include <pcmcia/cs_types.h> 18 #include <pcmcia/cs.h> 19 #include <pcmcia/cistpl.h> 20 #include <pcmcia/ds.h> 21 22 #define copy_from_user memcpy 23 #define copy_to_user memcpy 24 #define CardServices gPcmciaCs->_CardServices 25 #define get_handle gPcmciaDs->get_handle 26 27 const char sockname[] = "bus/pcmcia/sock/%ld"; 28 static char ** devices; 29 uint32 devices_count = 0; 30 31 int32 api_version = B_CUR_DRIVER_API_VERSION; 32 33 cs_client_module_info *gPcmciaCs; 34 ds_module_info *gPcmciaDs; 35 36 static status_t 37 ds_open(const char *name, uint32 flags, void **_cookie) 38 { 39 int32 socket = -1; 40 int32 i; 41 *_cookie = NULL; 42 43 for (i=0; i<devices_count; i++) { 44 if (strcmp(name, devices[i]) == 0) { 45 socket = i; 46 break; 47 } 48 } 49 50 if (socket < 0) { 51 return B_BAD_VALUE; 52 } 53 54 if (get_handle(socket, (client_handle_t *)_cookie) != B_OK) { 55 return ENODEV; 56 } 57 58 return B_OK; 59 } 60 61 62 static status_t 63 ds_close(void *cookie) 64 { 65 return B_OK; 66 } 67 68 69 static status_t 70 ds_free(void *cookie) 71 { 72 return B_OK; 73 } 74 75 76 static status_t 77 ds_read(void *cookie, off_t position, void *data, size_t *numBytes) 78 { 79 return B_ERROR; 80 } 81 82 83 static status_t 84 ds_write(void *cookie, off_t position, const void *data, size_t *numBytes) 85 { 86 return B_ERROR; 87 } 88 89 90 /*====================================================================*/ 91 92 static status_t 93 ds_ioctl(void *cookie, uint32 cmd, void *arg, size_t len) 94 { 95 /*socket_info_t *s = (socket_info_t *) cookie; 96 u_int size = IOCPARM_LEN(cmd); 97 status_t ret, err; 98 ds_ioctl_arg_t buf; 99 100 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; 101 102 err = ret = 0; 103 104 if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); 105 106 switch (cmd) { 107 case DS_ADJUST_RESOURCE_INFO: 108 ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust); 109 break; 110 case DS_GET_CARD_SERVICES_INFO: 111 ret = CardServices(GetCardServicesInfo, &buf.servinfo); 112 break; 113 case DS_GET_CONFIGURATION_INFO: 114 ret = CardServices(GetConfigurationInfo, s->handle, &buf.config); 115 break; 116 case DS_GET_FIRST_TUPLE: 117 ret = CardServices(GetFirstTuple, s->handle, &buf.tuple); 118 break; 119 case DS_GET_NEXT_TUPLE: 120 ret = CardServices(GetNextTuple, s->handle, &buf.tuple); 121 break; 122 case DS_GET_TUPLE_DATA: 123 buf.tuple.TupleData = buf.tuple_parse.data; 124 buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); 125 ret = CardServices(GetTupleData, s->handle, &buf.tuple); 126 break; 127 case DS_PARSE_TUPLE: 128 buf.tuple.TupleData = buf.tuple_parse.data; 129 ret = CardServices(ParseTuple, s->handle, &buf.tuple, 130 &buf.tuple_parse.parse); 131 break; 132 case DS_RESET_CARD: 133 ret = CardServices(ResetCard, s->handle, NULL); 134 break; 135 case DS_GET_STATUS: 136 ret = CardServices(GetStatus, s->handle, &buf.status); 137 break; 138 case DS_VALIDATE_CIS: 139 ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo); 140 break; 141 case DS_SUSPEND_CARD: 142 ret = CardServices(SuspendCard, s->handle, NULL); 143 break; 144 case DS_RESUME_CARD: 145 ret = CardServices(ResumeCard, s->handle, NULL); 146 break; 147 case DS_EJECT_CARD: 148 ret = CardServices(EjectCard, s->handle, NULL); 149 break; 150 case DS_INSERT_CARD: 151 ret = CardServices(InsertCard, s->handle, NULL); 152 break; 153 case DS_ACCESS_CONFIGURATION_REGISTER: 154 if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) 155 return -EPERM; 156 ret = CardServices(AccessConfigurationRegister, s->handle, 157 &buf.conf_reg); 158 break; 159 case DS_GET_FIRST_REGION: 160 ret = CardServices(GetFirstRegion, s->handle, &buf.region); 161 break; 162 case DS_GET_NEXT_REGION: 163 ret = CardServices(GetNextRegion, s->handle, &buf.region); 164 break; 165 case DS_GET_FIRST_WINDOW: 166 buf.win_info.handle = (window_handle_t)s->handle; 167 ret = CardServices(GetFirstWindow, &buf.win_info.handle, 168 &buf.win_info.window); 169 break; 170 case DS_GET_NEXT_WINDOW: 171 ret = CardServices(GetNextWindow, &buf.win_info.handle, 172 &buf.win_info.window); 173 break; 174 case DS_GET_MEM_PAGE: 175 ret = CardServices(GetMemPage, buf.win_info.handle, 176 &buf.win_info.map); 177 break; 178 case DS_REPLACE_CIS: 179 ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump); 180 break; 181 */ 182 client_handle_t h = (client_handle_t) cookie; 183 u_int size = IOCPARM_LEN(cmd); 184 status_t ret, err; 185 ds_ioctl_arg_t buf; 186 187 if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; 188 189 err = ret = 0; 190 191 if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); 192 193 switch (cmd) { 194 case DS_ADJUST_RESOURCE_INFO: 195 ret = CardServices(AdjustResourceInfo, h, &buf.adjust); 196 break; 197 case DS_GET_CARD_SERVICES_INFO: 198 ret = CardServices(GetCardServicesInfo, &buf.servinfo); 199 break; 200 case DS_GET_CONFIGURATION_INFO: 201 ret = CardServices(GetConfigurationInfo, h, &buf.config); 202 break; 203 case DS_GET_FIRST_TUPLE: 204 ret = CardServices(GetFirstTuple, h, &buf.tuple); 205 break; 206 case DS_GET_NEXT_TUPLE: 207 ret = CardServices(GetNextTuple, h, &buf.tuple); 208 break; 209 case DS_GET_TUPLE_DATA: 210 buf.tuple.TupleData = buf.tuple_parse.data; 211 buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); 212 ret = CardServices(GetTupleData, h, &buf.tuple); 213 break; 214 case DS_PARSE_TUPLE: 215 buf.tuple.TupleData = buf.tuple_parse.data; 216 ret = CardServices(ParseTuple, h, &buf.tuple, 217 &buf.tuple_parse.parse); 218 break; 219 case DS_RESET_CARD: 220 ret = CardServices(ResetCard, h, NULL); 221 break; 222 case DS_GET_STATUS: 223 ret = CardServices(GetStatus, h, &buf.status); 224 break; 225 case DS_VALIDATE_CIS: 226 ret = CardServices(ValidateCIS, h, &buf.cisinfo); 227 break; 228 case DS_SUSPEND_CARD: 229 ret = CardServices(SuspendCard, h, NULL); 230 break; 231 case DS_RESUME_CARD: 232 ret = CardServices(ResumeCard, h, NULL); 233 break; 234 case DS_EJECT_CARD: 235 ret = CardServices(EjectCard, h, NULL); 236 break; 237 case DS_INSERT_CARD: 238 ret = CardServices(InsertCard, h, NULL); 239 break; 240 /* case DS_ACCESS_CONFIGURATION_REGISTER: 241 if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) 242 return -EPERM; 243 ret = CardServices(AccessConfigurationRegister, h, 244 &buf.conf_reg); 245 break; 246 case DS_GET_FIRST_REGION: 247 ret = CardServices(GetFirstRegion, h, &buf.region); 248 break; 249 case DS_GET_NEXT_REGION: 250 ret = CardServices(GetNextRegion, h, &buf.region); 251 break; 252 case DS_GET_FIRST_WINDOW: 253 buf.win_info.handle = (window_handle_t)h; 254 ret = CardServices(GetFirstWindow, &buf.win_info.handle, 255 &buf.win_info.window); 256 break; 257 case DS_GET_NEXT_WINDOW: 258 ret = CardServices(GetNextWindow, &buf.win_info.handle, 259 &buf.win_info.window); 260 break; 261 case DS_GET_MEM_PAGE: 262 ret = CardServices(GetMemPage, buf.win_info.handle, 263 &buf.win_info.map); 264 break;*/ 265 case DS_REPLACE_CIS: 266 ret = CardServices(ReplaceCIS, h, &buf.cisdump); 267 break; 268 269 /* case DS_BIND_REQUEST: 270 if (!capable(CAP_SYS_ADMIN)) return -EPERM; 271 err = bind_request(i, &buf.bind_info); 272 break; 273 case DS_GET_DEVICE_INFO: 274 err = get_device_info(i, &buf.bind_info, 1); 275 break; 276 case DS_GET_NEXT_DEVICE: 277 err = get_device_info(i, &buf.bind_info, 0); 278 break; 279 case DS_UNBIND_REQUEST: 280 err = unbind_request(i, &buf.bind_info); 281 break; 282 case DS_BIND_MTD: 283 if (!capable(CAP_SYS_ADMIN)) return -EPERM; 284 err = bind_mtd(i, &buf.mtd_info); 285 break;*/ 286 default: 287 err = -EINVAL; 288 } 289 290 if ((err == 0) && (ret != CS_SUCCESS)) { 291 switch (ret) { 292 case CS_BAD_SOCKET: case CS_NO_CARD: 293 err = ENODEV; break; 294 case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: 295 case CS_BAD_TUPLE: 296 err = EINVAL; break; 297 case CS_IN_USE: 298 err = EBUSY; break; 299 case CS_OUT_OF_RESOURCE: 300 err = ENOSPC; break; 301 case CS_NO_MORE_ITEMS: 302 err = ENODATA; break; 303 case CS_UNSUPPORTED_FUNCTION: 304 err = ENOSYS; break; 305 default: 306 err = EIO; break; 307 } 308 } 309 310 if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size); 311 312 return err; 313 } /* ds_ioctl */ 314 315 316 status_t 317 init_hardware() 318 { 319 return B_OK; 320 } 321 322 323 const char ** 324 publish_devices(void) 325 { 326 return (const char **)devices; 327 } 328 329 330 static device_hooks hooks = { 331 &ds_open, 332 &ds_close, 333 &ds_free, 334 &ds_ioctl, 335 &ds_read, 336 &ds_write, 337 NULL, 338 NULL, 339 NULL, 340 NULL 341 }; 342 343 device_hooks * 344 find_device(const char *name) 345 { 346 return &hooks; 347 } 348 349 350 status_t 351 init_driver() 352 { 353 status_t err; 354 client_handle_t handle; 355 uint32 i; 356 357 #if DEBUG && !defined(__HAIKU__) 358 load_driver_symbols("ds"); 359 #endif 360 361 if ((err = get_module(CS_CLIENT_MODULE_NAME, (module_info **)&gPcmciaCs))!=B_OK) 362 return err; 363 if ((err = get_module(DS_MODULE_NAME, (module_info **)&gPcmciaDs))!=B_OK) { 364 put_module(CS_CLIENT_MODULE_NAME); 365 return err; 366 } 367 368 devices_count = 0; 369 while (get_handle(devices_count, &handle)==B_OK) { 370 devices_count++; 371 } 372 373 if (devices_count <= 0) { 374 put_module(CS_CLIENT_MODULE_NAME); 375 put_module(DS_MODULE_NAME); 376 return ENODEV; 377 } 378 379 devices = malloc(sizeof(char *) * (devices_count+1)); 380 if (!devices) { 381 put_module(CS_CLIENT_MODULE_NAME); 382 put_module(DS_MODULE_NAME); 383 return ENOMEM; 384 } 385 for (i=0; i<devices_count; i++) { 386 devices[i] = strdup(sockname); 387 sprintf(devices[i], sockname, i); 388 } 389 devices[devices_count] = NULL; 390 391 return B_OK; 392 } 393 394 395 void 396 uninit_driver() 397 { 398 int32 i = 0; 399 for (i=0; i<devices_count; i++) { 400 free (devices[i]); 401 } 402 free(devices); 403 devices = NULL; 404 405 put_module(DS_MODULE_NAME); 406 put_module(CS_CLIENT_MODULE_NAME); 407 } 408 409