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