1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * PCMCIA Card Services 29 * The PCMCIA Card Services is a loadable module which 30 * presents the Card Services interface to client device 31 * drivers. 32 * 33 * Card Services uses Socket Services-like calls into the 34 * PCMCIA nexus driver to manipulate socket and adapter 35 * resources. 36 * 37 * Note that a bunch of comments are not indented correctly with the 38 * code that they are commenting on. This is because cstyle is 39 * is inflexible concerning 4-column indenting. 40 */ 41 42 #if defined(DEBUG) 43 #define CS_DEBUG 44 #endif 45 46 #include <sys/types.h> 47 #include <sys/systm.h> 48 #include <sys/user.h> 49 #include <sys/buf.h> 50 #include <sys/file.h> 51 #include <sys/uio.h> 52 #include <sys/conf.h> 53 #include <sys/stat.h> 54 #include <sys/autoconf.h> 55 #include <sys/vtoc.h> 56 #include <sys/dkio.h> 57 #include <sys/ddi.h> 58 #include <sys/sunddi.h> 59 #include <sys/debug.h> 60 #include <sys/varargs.h> 61 #include <sys/var.h> 62 #include <sys/proc.h> 63 #include <sys/thread.h> 64 #include <sys/utsname.h> 65 #include <sys/vtrace.h> 66 #include <sys/kstat.h> 67 #include <sys/kmem.h> 68 #include <sys/modctl.h> 69 #include <sys/kobj.h> 70 #include <sys/callb.h> 71 #include <sys/time.h> 72 73 #include <sys/pctypes.h> 74 #include <pcmcia/sys/cs_types.h> 75 #include <sys/pcmcia.h> 76 #include <sys/sservice.h> 77 #include <pcmcia/sys/cis.h> 78 #include <pcmcia/sys/cis_handlers.h> 79 #include <pcmcia/sys/cs.h> 80 #include <pcmcia/sys/cs_priv.h> 81 #include <pcmcia/sys/cs_stubs.h> 82 83 /* 84 * The cs_strings header file is where all of the major strings that 85 * Card Services uses are located. 86 */ 87 #include <pcmcia/sys/cs_strings.h> 88 89 90 /* 91 * Function declarations 92 * 93 * The main Card Services entry point 94 */ 95 int CardServices(int function, ...); 96 97 /* 98 * functions and globals used by Socket Services 99 * 100 * WAS: void *(*cis_parser)(int, ...) = NULL; 101 */ 102 void *(*cis_parser)(int, ...) = NULL; 103 csfunction_t *cs_socket_services = NULL; 104 105 /* 106 * event handling functions 107 */ 108 static event_t ss_to_cs_events(cs_socket_t *, event_t); 109 static event_t cs_cse2sbm(event_t); 110 static void cs_event_thread(uint32_t); 111 static int cs_card_insertion(cs_socket_t *, event_t); 112 static int cs_card_removal(cs_socket_t *); 113 static void cs_ss_thread(uint32_t); 114 void cs_ready_timeout(void *); 115 static int cs_card_for_client(client_t *); 116 static int cs_request_socket_mask(client_handle_t, request_socket_mask_t *); 117 static int cs_release_socket_mask(client_handle_t, release_socket_mask_t *); 118 static int cs_get_event_mask(client_handle_t, sockevent_t *); 119 static int cs_set_event_mask(client_handle_t, sockevent_t *); 120 static int cs_event2text(event2text_t *, int); 121 static int cs_read_event_status(cs_socket_t *, client_t *, event_t *, 122 get_ss_status_t *, int); 123 uint32_t cs_socket_event_softintr(caddr_t); 124 void cs_event_softintr_timeout(void *); 125 static int cs_get_status(client_handle_t, get_status_t *); 126 static uint32_t cs_sbm2cse(uint32_t); 127 static unsigned cs_merge_event_masks(cs_socket_t *, client_t *); 128 static int cs_set_socket_event_mask(cs_socket_t *, unsigned); 129 130 /* 131 * SS<->CS communication and internal socket and window handling functions 132 */ 133 static uint32_t cs_add_socket(uint32_t); 134 static uint32_t cs_drop_socket(uint32_t); 135 static cs_socket_t *cs_get_sp(uint32_t); 136 static cs_socket_t *cs_find_sp(uint32_t); 137 static cs_window_t *cs_get_wp(uint32_t); 138 static cs_window_t *cs_find_wp(uint32_t); 139 static int cs_add_windows(int, uint32_t); 140 static uint32_t cs_ss_init(); 141 static void cs_set_acc_attributes(set_window_t *, uint32_t); 142 143 /* 144 * CIS handling functions 145 */ 146 cistpl_callout_t *cis_cistpl_std_callout; 147 static int cs_parse_tuple(client_handle_t, tuple_t *, cisparse_t *, cisdata_t); 148 static int cs_get_tuple_data(client_handle_t, tuple_t *); 149 static int cs_validate_cis(client_handle_t, cisinfo_t *); 150 static int cs_get_firstnext_tuple(client_handle_t, tuple_t *, uint32_t); 151 static int cs_create_cis(cs_socket_t *); 152 static int cs_destroy_cis(cs_socket_t *); 153 154 /* 155 * client handling functions 156 */ 157 unsigned cs_create_next_client_minor(unsigned, unsigned); 158 static client_t *cs_find_client(client_handle_t, int *); 159 static client_handle_t cs_create_client_handle(unsigned, client_t *); 160 static int cs_destroy_client_handle(client_handle_t); 161 static int cs_register_client(client_handle_t *, client_reg_t *); 162 static int cs_deregister_client(client_handle_t); 163 static int cs_deregister_mtd(client_handle_t); 164 static void cs_clear_superclient_lock(int); 165 static int cs_add_client_to_socket(unsigned, client_handle_t *, 166 client_reg_t *, int); 167 static int cs_get_client_info(client_handle_t, client_info_t *); 168 static int cs_get_firstnext_client(get_firstnext_client_t *, uint32_t); 169 170 /* 171 * window handling functions 172 */ 173 static int cs_request_window(client_handle_t, window_handle_t *, win_req_t *); 174 static int cs_release_window(window_handle_t); 175 static int cs_modify_window(window_handle_t, modify_win_t *); 176 static int cs_modify_mem_window(window_handle_t, modify_win_t *, win_req_t *, 177 int); 178 static int cs_map_mem_page(window_handle_t, map_mem_page_t *); 179 static int cs_find_mem_window(uint32_t, win_req_t *, uint32_t *); 180 static int cs_memwin_space_and_map_ok(inquire_window_t *, win_req_t *); 181 static int cs_valid_window_speed(inquire_window_t *, uint32_t); 182 static window_handle_t cs_create_window_handle(uint32_t); 183 static cs_window_t *cs_find_window(window_handle_t); 184 static int cs_find_io_win(uint32_t, iowin_char_t *, uint32_t *, uint32_t *); 185 186 /* 187 * IO, IRQ and configuration handling functions 188 */ 189 static int cs_request_io(client_handle_t, io_req_t *); 190 static int cs_release_io(client_handle_t, io_req_t *); 191 static int cs_allocate_io_win(uint32_t, uint32_t, uint32_t *); 192 static int cs_setup_io_win(uint32_t, uint32_t, baseaddru_t *, 193 uint32_t *, uint32_t, uint32_t); 194 static int cs_request_irq(client_handle_t, irq_req_t *); 195 static int cs_release_irq(client_handle_t, irq_req_t *); 196 static int cs_request_configuration(client_handle_t, config_req_t *); 197 static int cs_release_configuration(client_handle_t, release_config_t *); 198 static int cs_modify_configuration(client_handle_t, modify_config_t *); 199 static int cs_access_configuration_register(client_handle_t, 200 access_config_reg_t *); 201 202 /* 203 * RESET and general info functions 204 */ 205 static int cs_reset_function(client_handle_t, reset_function_t *); 206 static int cs_get_configuration_info(client_handle_t *, 207 get_configuration_info_t *); 208 static int cs_get_cardservices_info(client_handle_t, 209 get_cardservices_info_t *); 210 static int cs_get_physical_adapter_info(client_handle_t, 211 get_physical_adapter_info_t *); 212 213 /* 214 * general functions 215 */ 216 static uint32_t cs_get_socket(client_handle_t, uint32_t *, uint32_t *, 217 cs_socket_t **, client_t **); 218 static int cs_convert_speed(convert_speed_t *); 219 static int cs_convert_size(convert_size_t *); 220 static char *cs_error2text(int, int); 221 static int cs_map_log_socket(client_handle_t, map_log_socket_t *); 222 static int cs_convert_powerlevel(uint32_t, uint32_t, uint32_t, unsigned *); 223 static int cs_make_device_node(client_handle_t, make_device_node_t *); 224 static int cs_remove_device_node(client_handle_t, remove_device_node_t *); 225 static int cs_ddi_info(cs_ddi_info_t *); 226 static int cs_init_cis_window(cs_socket_t *, uint32_t *, acc_handle_t *, 227 uint32_t); 228 static int cs_sys_ctl(cs_sys_ctl_t *); 229 230 /* 231 * global variables 232 */ 233 static int cs_max_client_handles = CS_MAX_CLIENTS; 234 static client_t cs_socket_services_client; /* global SS client */ 235 static client_types_t client_types[MAX_CLIENT_TYPES]; 236 static cs_globals_t cs_globals; 237 int cs_reset_timeout_time = RESET_TIMEOUT_TIME; 238 int cs_rc1_delay = CS_RC1_DELAY; 239 int cs_rc2_delay = CS_RC2_DELAY; 240 int cs_rq_delay = CS_RQ_DELAY; 241 242 #ifdef CS_DEBUG 243 int cs_debug = 0; 244 #endif 245 246 /* 247 * cs_init - Initialize CS internal structures, databases, and state, 248 * and register with SS 249 * 250 * XXX - Need to make sure that if we fail at any point that we free 251 * any resources that we allocated, as well as kill any 252 * threads that may have been started. 253 */ 254 int 255 cs_init() 256 { 257 client_types_t *ct; 258 client_t *client; 259 260 /* 261 * Initialize the CS global structure 262 */ 263 bzero((caddr_t)&cs_globals, sizeof (cs_globals_t)); 264 265 mutex_init(&cs_globals.global_lock, NULL, MUTEX_DRIVER, NULL); 266 mutex_init(&cs_globals.window_lock, NULL, MUTEX_DRIVER, NULL); 267 268 cs_globals.init_state = GLOBAL_INIT_STATE_MUTEX; 269 270 /* 271 * Set up the global Socket Services client, since we're going to 272 * need it once we register with SS. 273 */ 274 client = &cs_socket_services_client; 275 bzero((caddr_t)client, sizeof (client_t)); 276 client->client_handle = CS_SS_CLIENT_HANDLE; 277 client->flags |= (INFO_SOCKET_SERVICES | CLIENT_CARD_INSERTED); 278 279 /* 280 * Setup the client type structure - this is used in the socket event 281 * thread to sequence the delivery of events to all clients on 282 * the socket. 283 */ 284 ct = &client_types[0]; 285 ct->type = INFO_IO_CLIENT; 286 ct->order = CLIENT_EVENTS_LIFO; 287 ct->next = &client_types[1]; 288 289 ct = ct->next; 290 ct->type = INFO_MTD_CLIENT; 291 ct->order = CLIENT_EVENTS_FIFO; 292 ct->next = &client_types[2]; 293 294 ct = ct->next; 295 ct->type = INFO_MEM_CLIENT; 296 ct->order = CLIENT_EVENTS_FIFO; 297 ct->next = NULL; 298 299 return (CS_SUCCESS); 300 } 301 302 /* 303 * cs_deinit - Deinitialize CS 304 * 305 * This function cleans up any allocated resources, stops any running threads, 306 * destroys any mutexes and condition variables, and finally frees up the 307 * global socket and window structure arrays. 308 */ 309 int 310 cs_deinit() 311 { 312 cs_socket_t *sp; 313 int sn, have_clients = 0, have_sockets = 0; 314 cs_register_cardservices_t rcs; 315 316 #if defined(CS_DEBUG) 317 if (cs_debug > 1) 318 cmn_err(CE_CONT, "CS: cs_deinit\n"); 319 #endif 320 321 /* 322 * Deregister with the Card Services kernel stubs module 323 */ 324 rcs.magic = CS_STUBS_MAGIC; 325 rcs.function = CS_ENTRY_DEREGISTER; 326 (void) csx_register_cardservices(&rcs); 327 328 /* 329 * Set the GLOBAL_INIT_STATE_NO_CLIENTS flag to prevent new clients 330 * from registering. 331 */ 332 mutex_enter(&cs_globals.global_lock); 333 cs_globals.init_state |= GLOBAL_INIT_STATE_NO_CLIENTS; 334 mutex_exit(&cs_globals.global_lock); 335 336 /* 337 * Go through each socket and make sure that there are no clients 338 * on any of the sockets. If there are, we can't deinit until 339 * all the clients for every socket are gone. 340 */ 341 for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 342 if ((sp = cs_get_sp(sn)) != NULL) { 343 have_sockets++; 344 if (sp->client_list) { 345 cmn_err(CE_CONT, "cs_deinit: cannot unload module since " 346 "socket %d has registered clients\n", sn); 347 have_clients++; 348 } 349 } 350 } 351 352 /* 353 * We don't allow unload if there are any clients registered 354 * or if there are still sockets that are active. 355 */ 356 if ((have_clients > 0) || (have_sockets > 0)) 357 return (BAD_FUNCTION); 358 359 #ifdef XXX 360 /* 361 * If one or more sockets have been added, we need to deallocate 362 * the resources associated with those sockets. 363 */ 364 365 /* 366 * First, tell Socket Services that we're leaving, so that we 367 * don't get any more event callbacks. 368 */ 369 SocketServices(CSUnregister); 370 371 /* 372 * Wait for the soft int timer to tell us it's done 373 */ 374 mutex_enter(&cs_globals.global_lock); 375 cs_globals.init_state |= GLOBAL_INIT_STATE_UNLOADING; 376 mutex_exit(&cs_globals.global_lock); 377 UNTIMEOUT(cs_globals.sotfint_tmo); 378 379 /* 380 * Remove the soft interrupt handler. 381 */ 382 mutex_enter(&cs_globals.global_lock); 383 if (cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR) { 384 ddi_remove_softintr(cs_globals.softint_id); 385 cs_globals.init_state &= ~GLOBAL_INIT_STATE_SOFTINTR; 386 } 387 mutex_exit(&cs_globals.global_lock); 388 389 return (CS_SUCCESS); 390 391 /* 392 * Go through each socket and free any resource allocated to that 393 * socket, as well as any mutexs and condition variables. 394 */ 395 for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 396 set_socket_t set_socket; 397 398 if ((sp = cs_get_sp(sn)) != NULL) { 399 400 /* 401 * untimeout possible pending ready/busy timer 402 */ 403 UNTIMEOUT(sp->rdybsy_tmo_id); 404 405 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 406 mutex_enter(&sp->lock); 407 sp->flags = SOCKET_UNLOAD_MODULE; 408 if (sp->init_state & SOCKET_INIT_STATE_SOFTINTR) 409 sp->init_state &= ~SOCKET_INIT_STATE_SOFTINTR; 410 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 411 mutex_exit(&sp->lock); 412 413 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 414 mutex_enter(&sp->cis_lock); 415 (void) cs_destroy_cis(sp); 416 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 417 mutex_exit(&sp->cis_lock); 418 419 /* 420 * Tell the event handler thread that we want it to exit, then 421 * wait around until it tells us that it has exited. 422 */ 423 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 424 mutex_enter(&sp->client_lock); 425 if (sp->init_state & SOCKET_INIT_STATE_THREAD) { 426 sp->thread_state = SOCKET_THREAD_EXIT; 427 cv_broadcast(&sp->thread_cv); 428 cv_wait(&sp->caller_cv, &sp->client_lock); 429 } 430 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 431 mutex_exit(&sp->client_lock); 432 433 /* 434 * Tell the SS work thread that we want it to exit, then 435 * wait around until it tells us that it has exited. 436 */ 437 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 438 mutex_enter(&sp->ss_thread_lock); 439 if (sp->init_state & SOCKET_INIT_STATE_SS_THREAD) { 440 sp->ss_thread_state = SOCKET_THREAD_EXIT; 441 cv_broadcast(&sp->ss_thread_cv); 442 cv_wait(&sp->ss_caller_cv, &sp->ss_thread_lock); 443 } 444 445 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 446 mutex_exit(&sp->ss_thread_lock); 447 448 /* 449 * Free the mutexii and condition variables that we used. 450 */ 451 if (sp->init_state & SOCKET_INIT_STATE_MUTEX) { 452 mutex_destroy(&sp->lock); 453 mutex_destroy(&sp->client_lock); 454 mutex_destroy(&sp->cis_lock); 455 mutex_destroy(&sp->ss_thread_lock); 456 } 457 458 if (sp->init_state & SOCKET_INIT_STATE_CV) { 459 cv_destroy(&sp->thread_cv); 460 cv_destroy(&sp->caller_cv); 461 cv_destroy(&sp->reset_cv); 462 cv_destroy(&sp->ss_thread_cv); 463 cv_destroy(&sp->ss_caller_cv); 464 } 465 466 #ifdef USE_IOMMAP_WINDOW 467 /* 468 * Free the memory-mapped IO structure if we allocated one. 469 */ 470 if (sp->io_mmap_window) 471 kmem_free(sp->io_mmap_window, sizeof (io_mmap_window_t)); 472 #endif /* USE_IOMMAP_WINDOW */ 473 474 /* 475 * Return the socket to memory-only mode and turn off the 476 * socket power. 477 */ 478 sp->event_mask = 0; 479 set_socket.socket = sp->socket_num; 480 set_socket.SCIntMask = 0; 481 set_socket.IREQRouting = 0; 482 set_socket.IFType = IF_MEMORY; 483 set_socket.CtlInd = 0; /* turn off controls and indicators */ 484 set_socket.State = (unsigned)~0; /* clear latched state bits */ 485 486 (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 487 &set_socket.VccLevel); 488 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 489 &set_socket.Vpp1Level); 490 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 491 &set_socket.Vpp2Level); 492 493 /* 494 * If we fail this call, there's not much we can do, so 495 * just continue with the resource deallocation. 496 */ 497 if ((ret = 498 SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 499 cmn_err(CE_CONT, 500 "cs_deinit: socket %d SS_SetSocket failure %d\n", 501 sp->socket_num, ret); 502 } 503 } /* cs_get_sp */ 504 } /* for (sn) */ 505 #endif /* XXX */ 506 507 /* 508 * Destroy the global mutexii. 509 */ 510 mutex_destroy(&cs_globals.global_lock); 511 mutex_destroy(&cs_globals.window_lock); 512 513 #ifdef XXX 514 /* 515 * Free the global "super-client" structure 516 */ 517 if (cs_globals.sclient_list) 518 kmem_free(cs_globals.sclient_list, 519 (cs_globals.num_sockets * sizeof (struct sclient_list_t))); 520 cs_globals.sclient_list = NULL; 521 #endif /* XXX */ 522 523 return (CS_SUCCESS); 524 } 525 526 /* 527 * ==== drip, drip, drip - the Card Services waterfall :-) ==== 528 */ 529 530 /* 531 * CardServices - general Card Services entry point for CS clients 532 * and Socket Services; the address of this 533 * function is handed to SS via the CSRegister 534 * SS call 535 */ 536 int 537 CardServices(int function, ...) 538 { 539 va_list arglist; 540 int retcode = CS_UNSUPPORTED_FUNCTION; 541 542 cs_socket_t *socp; 543 uint32_t *offp; 544 acc_handle_t *hp; 545 client_handle_t ch; 546 client_handle_t *chp; 547 window_handle_t wh; 548 window_handle_t *whp; 549 tuple_t *tuple; 550 cisparse_t *cisparse; 551 552 #ifdef CS_DEBUG 553 if (cs_debug > 127) { 554 cmn_err(CE_CONT, "CardServices: called for function %s (0x%x)\n", 555 cs_error2text(function, CSFUN2TEXT_FUNCTION), 556 function); 557 } 558 #endif 559 560 va_start(arglist, function); 561 562 /* 563 * Here's the Card Services waterfall 564 */ 565 switch (function) { 566 /* 567 * We got here as a result of the CIS module calling us 568 * in response to cs_ss_init() calling the CIS module 569 * at CIS_PARSER(CISP_CIS_SETUP, ...) 570 */ 571 case CISRegister: { 572 cisregister_t *cisr; 573 574 cisr = va_arg(arglist, cisregister_t *); 575 576 if (cisr->cis_magic != PCCS_MAGIC || 577 cisr->cis_version != PCCS_VERSION) { 578 cmn_err(CE_WARN, 579 "CS: CISRegister (%lx, %lx, %lx, %lx) *ERROR*", 580 (long)cisr->cis_magic, 581 (long)cisr->cis_version, 582 (long)cisr->cis_parser, 583 (long)cisr->cistpl_std_callout); 584 retcode = CS_BAD_ARGS; 585 } else { 586 /* 587 * Replace the CIS Parser entry point if 588 * necessary. 589 */ 590 if (cisr->cis_parser != NULL) 591 cis_parser = cisr->cis_parser; 592 cis_cistpl_std_callout = cisr->cistpl_std_callout; 593 retcode = CS_SUCCESS; 594 } 595 } 596 break; 597 case CISUnregister: /* XXX - should we do some more checking */ 598 /* XXX - need to protect this by a mutex */ 599 cis_parser = NULL; 600 cis_cistpl_std_callout = NULL; 601 retcode = CS_SUCCESS; 602 break; 603 case InitCISWindow: 604 socp = va_arg(arglist, cs_socket_t *); 605 offp = va_arg(arglist, uint32_t *); 606 hp = va_arg(arglist, acc_handle_t *); 607 retcode = cs_init_cis_window(socp, offp, hp, 608 va_arg(arglist, uint32_t)); 609 break; 610 case RegisterClient: 611 chp = va_arg(arglist, client_handle_t *), 612 retcode = cs_register_client(chp, 613 va_arg(arglist, client_reg_t *)); 614 break; 615 case DeregisterClient: 616 retcode = cs_deregister_client( 617 va_arg(arglist, client_handle_t)); 618 break; 619 case GetStatus: 620 ch = va_arg(arglist, client_handle_t); 621 retcode = cs_get_status(ch, 622 va_arg(arglist, get_status_t *)); 623 break; 624 case ResetFunction: 625 ch = va_arg(arglist, client_handle_t); 626 retcode = cs_reset_function(ch, 627 va_arg(arglist, reset_function_t *)); 628 break; 629 case SetEventMask: 630 ch = va_arg(arglist, client_handle_t); 631 retcode = cs_set_event_mask(ch, 632 va_arg(arglist, sockevent_t *)); 633 break; 634 case GetEventMask: 635 ch = va_arg(arglist, client_handle_t); 636 retcode = cs_get_event_mask(ch, 637 va_arg(arglist, sockevent_t *)); 638 break; 639 case RequestIO: 640 ch = va_arg(arglist, client_handle_t); 641 retcode = cs_request_io(ch, 642 va_arg(arglist, io_req_t *)); 643 break; 644 case ReleaseIO: 645 ch = va_arg(arglist, client_handle_t); 646 retcode = cs_release_io(ch, 647 va_arg(arglist, io_req_t *)); 648 break; 649 case RequestIRQ: 650 ch = va_arg(arglist, client_handle_t); 651 retcode = cs_request_irq(ch, 652 va_arg(arglist, irq_req_t *)); 653 break; 654 case ReleaseIRQ: 655 ch = va_arg(arglist, client_handle_t); 656 retcode = cs_release_irq(ch, 657 va_arg(arglist, irq_req_t *)); 658 break; 659 case RequestWindow: 660 ch = va_arg(arglist, client_handle_t); 661 whp = va_arg(arglist, window_handle_t *); 662 retcode = cs_request_window(ch, whp, 663 va_arg(arglist, win_req_t *)); 664 break; 665 case ReleaseWindow: 666 retcode = cs_release_window( 667 va_arg(arglist, window_handle_t)); 668 break; 669 case ModifyWindow: 670 wh = va_arg(arglist, window_handle_t); 671 retcode = cs_modify_window(wh, 672 va_arg(arglist, modify_win_t *)); 673 break; 674 case MapMemPage: 675 wh = va_arg(arglist, window_handle_t); 676 retcode = cs_map_mem_page(wh, 677 va_arg(arglist, map_mem_page_t *)); 678 break; 679 case RequestSocketMask: 680 ch = va_arg(arglist, client_handle_t); 681 retcode = cs_request_socket_mask(ch, 682 va_arg(arglist, request_socket_mask_t *)); 683 break; 684 case ReleaseSocketMask: 685 ch = va_arg(arglist, client_handle_t); 686 retcode = cs_release_socket_mask(ch, 687 va_arg(arglist, release_socket_mask_t *)); 688 break; 689 case RequestConfiguration: 690 ch = va_arg(arglist, client_handle_t); 691 retcode = cs_request_configuration(ch, 692 va_arg(arglist, config_req_t *)); 693 break; 694 case GetPhysicalAdapterInfo: 695 ch = va_arg(arglist, client_handle_t); 696 retcode = cs_get_physical_adapter_info(ch, 697 va_arg(arglist, get_physical_adapter_info_t *)); 698 break; 699 case GetCardServicesInfo: 700 ch = va_arg(arglist, client_handle_t); 701 retcode = cs_get_cardservices_info(ch, 702 va_arg(arglist, get_cardservices_info_t *)); 703 break; 704 case GetConfigurationInfo: 705 chp = va_arg(arglist, client_handle_t *); 706 retcode = cs_get_configuration_info(chp, 707 va_arg(arglist, get_configuration_info_t *)); 708 break; 709 case ModifyConfiguration: 710 ch = va_arg(arglist, client_handle_t); 711 retcode = cs_modify_configuration(ch, 712 va_arg(arglist, modify_config_t *)); 713 break; 714 case AccessConfigurationRegister: 715 ch = va_arg(arglist, client_handle_t); 716 retcode = cs_access_configuration_register(ch, 717 va_arg(arglist, access_config_reg_t *)); 718 break; 719 case ReleaseConfiguration: 720 ch = va_arg(arglist, client_handle_t); 721 retcode = cs_release_configuration(ch, 722 va_arg(arglist, release_config_t *)); 723 break; 724 case OpenMemory: 725 cmn_err(CE_CONT, "CS: OpenMemory\n"); 726 break; 727 case ReadMemory: 728 cmn_err(CE_CONT, "CS: ReadMemory\n"); 729 break; 730 case WriteMemory: 731 cmn_err(CE_CONT, "CS: WriteMemory\n"); 732 break; 733 case CopyMemory: 734 cmn_err(CE_CONT, "CS: CopyMemory\n"); 735 break; 736 case RegisterEraseQueue: 737 cmn_err(CE_CONT, "CS: RegisterEraseQueue\n"); 738 break; 739 case CheckEraseQueue: 740 cmn_err(CE_CONT, "CS: CheckEraseQueue\n"); 741 break; 742 case DeregisterEraseQueue: 743 cmn_err(CE_CONT, "CS: DeregisterEraseQueue\n"); 744 break; 745 case CloseMemory: 746 cmn_err(CE_CONT, "CS: CloseMemory\n"); 747 break; 748 case GetFirstRegion: 749 cmn_err(CE_CONT, "CS: GetFirstRegion\n"); 750 break; 751 case GetNextRegion: 752 cmn_err(CE_CONT, "CS: GetNextRegion\n"); 753 break; 754 case GetFirstPartition: 755 cmn_err(CE_CONT, "CS: GetFirstPartition\n"); 756 break; 757 case GetNextPartition: 758 cmn_err(CE_CONT, "CS: GetNextPartition\n"); 759 break; 760 case ReturnSSEntry: 761 cmn_err(CE_CONT, "CS: ReturnSSEntry\n"); 762 break; 763 case MapLogSocket: 764 ch = va_arg(arglist, client_handle_t); 765 retcode = cs_map_log_socket(ch, 766 va_arg(arglist, map_log_socket_t *)); 767 break; 768 case MapPhySocket: 769 cmn_err(CE_CONT, "CS: MapPhySocket\n"); 770 break; 771 case MapLogWindow: 772 cmn_err(CE_CONT, "CS: MapLogWindow\n"); 773 break; 774 case MapPhyWindow: 775 cmn_err(CE_CONT, "CS: MapPhyWindow\n"); 776 break; 777 case RegisterMTD: 778 cmn_err(CE_CONT, "CS: RegisterMTD\n"); 779 break; 780 case RegisterTimer: 781 cmn_err(CE_CONT, "CS: RegisterTimer\n"); 782 break; 783 case SetRegion: 784 cmn_err(CE_CONT, "CS: SetRegion\n"); 785 break; 786 case RequestExclusive: 787 cmn_err(CE_CONT, "CS: RequestExclusive\n"); 788 break; 789 case ReleaseExclusive: 790 cmn_err(CE_CONT, "CS: ReleaseExclusive\n"); 791 break; 792 case GetFirstClient: 793 retcode = cs_get_firstnext_client( 794 va_arg(arglist, get_firstnext_client_t *), 795 CS_GET_FIRST_FLAG); 796 break; 797 case GetNextClient: 798 retcode = cs_get_firstnext_client( 799 va_arg(arglist, get_firstnext_client_t *), 800 CS_GET_NEXT_FLAG); 801 break; 802 case GetClientInfo: 803 ch = va_arg(arglist, client_handle_t); 804 retcode = cs_get_client_info(ch, 805 va_arg(arglist, client_info_t *)); 806 break; 807 case AddSocketServices: 808 cmn_err(CE_CONT, "CS: AddSocketServices\n"); 809 break; 810 case ReplaceSocketServices: 811 cmn_err(CE_CONT, "CS: ReplaceSocketServices\n"); 812 break; 813 case VendorSpecific: 814 cmn_err(CE_CONT, "CS: VendorSpecific\n"); 815 break; 816 case AdjustResourceInfo: 817 cmn_err(CE_CONT, "CS: AdjustResourceInfo\n"); 818 break; 819 case ValidateCIS: 820 ch = va_arg(arglist, client_handle_t); 821 retcode = cs_validate_cis(ch, 822 va_arg(arglist, cisinfo_t *)); 823 break; 824 case GetFirstTuple: 825 ch = va_arg(arglist, client_handle_t); 826 retcode = cs_get_firstnext_tuple(ch, 827 va_arg(arglist, tuple_t *), 828 CS_GET_FIRST_FLAG); 829 break; 830 case GetNextTuple: 831 ch = va_arg(arglist, client_handle_t); 832 retcode = cs_get_firstnext_tuple(ch, 833 va_arg(arglist, tuple_t *), 834 CS_GET_NEXT_FLAG); 835 break; 836 case GetTupleData: 837 ch = va_arg(arglist, client_handle_t); 838 retcode = cs_get_tuple_data(ch, 839 va_arg(arglist, tuple_t *)); 840 break; 841 case ParseTuple: 842 ch = va_arg(arglist, client_handle_t); 843 tuple = va_arg(arglist, tuple_t *); 844 cisparse = va_arg(arglist, cisparse_t *); 845 retcode = cs_parse_tuple(ch, tuple, cisparse, 846 va_arg(arglist, uint_t)); 847 break; 848 case MakeDeviceNode: 849 ch = va_arg(arglist, client_handle_t); 850 retcode = cs_make_device_node(ch, 851 va_arg(arglist, make_device_node_t *)); 852 break; 853 case RemoveDeviceNode: 854 ch = va_arg(arglist, client_handle_t); 855 retcode = cs_remove_device_node(ch, 856 va_arg(arglist, remove_device_node_t *)); 857 break; 858 case ConvertSpeed: 859 retcode = cs_convert_speed( 860 va_arg(arglist, convert_speed_t *)); 861 break; 862 case ConvertSize: 863 retcode = cs_convert_size( 864 va_arg(arglist, convert_size_t *)); 865 break; 866 case Event2Text: 867 retcode = cs_event2text( 868 va_arg(arglist, event2text_t *), 1); 869 break; 870 case Error2Text: { 871 error2text_t *cft; 872 873 cft = va_arg(arglist, error2text_t *); 874 (void) strcpy(cft->text, 875 cs_error2text(cft->item, CSFUN2TEXT_RETURN)); 876 retcode = CS_SUCCESS; 877 } 878 break; 879 case CS_DDI_Info: 880 retcode = cs_ddi_info(va_arg(arglist, cs_ddi_info_t *)); 881 break; 882 case CS_Sys_Ctl: 883 retcode = cs_sys_ctl(va_arg(arglist, cs_sys_ctl_t *)); 884 break; 885 default: 886 cmn_err(CE_CONT, "CS: {unknown function %d}\n", function); 887 break; 888 } /* switch(function) */ 889 890 va_end(arglist); 891 892 #ifdef CS_DEBUG 893 if (cs_debug > 127) { 894 cmn_err(CE_CONT, "CardServices: returning %s (0x%x)\n", 895 cs_error2text(retcode, CSFUN2TEXT_RETURN), 896 retcode); 897 } 898 #endif 899 900 return (retcode); 901 } 902 903 /* 904 * ==== tuple and CIS handling section ==== 905 */ 906 907 /* 908 * cs_parse_tuple - This function supports the CS ParseTuple function call. 909 * 910 * returns: CS_SUCCESS - if tuple parsed sucessfully 911 * CS_NO_CARD - if no card in socket 912 * CS_BAD_ARGS - if passed CIS list pointer is NULL 913 * CS_UNKNOWN_TUPLE - if unknown tuple passed to CIS parser 914 * CS_BAD_CIS - if generic parser error 915 * CS_NO_CIS - if no CIS for card/function 916 * 917 * See notes for the cs_get_firstnext_tuple function. 918 */ 919 static int 920 cs_parse_tuple(client_handle_t client_handle, tuple_t *tuple, 921 cisparse_t *cisparse, cisdata_t cisdata) 922 { 923 cs_socket_t *sp; 924 client_t *client; 925 uint32_t fn; 926 int ret; 927 928 if ((ret = cs_get_socket(client_handle, &tuple->Socket, 929 &fn, &sp, &client)) != CS_SUCCESS) 930 return (ret); 931 932 /* 933 * If there's no card in the socket or the card in the socket is not 934 * for this client, then return an error. 935 */ 936 if (!(client->flags & CLIENT_CARD_INSERTED)) 937 return (CS_NO_CARD); 938 939 /* 940 * Sanity check to be sure that we've got a non-NULL CIS list 941 * pointer. 942 */ 943 if (!(tuple->CISOffset)) 944 return (CS_BAD_ARGS); 945 946 mutex_enter(&sp->cis_lock); 947 948 /* 949 * Check to see if there is a valid CIS for this function. 950 * There is an implicit assumption here that if this 951 * is a multi-function CIS and the specified function 952 * number is not CS_GLOBAL_CIS that in order for there 953 * to be a valid function-specific CIS, there also must 954 * be a valid global CIS. This means that we don't need 955 * to know whether this tuple came from the global CIS 956 * or from the function-specific CIS. 957 */ 958 if ((sp->cis_flags & CW_VALID_CIS) && 959 (sp->cis[fn].flags & CW_VALID_CIS)) { 960 ret = (int)(uintptr_t)CIS_PARSER(CISP_CIS_PARSE_TUPLE, 961 cis_cistpl_std_callout, 962 tuple->CISOffset, 963 (tuple->Attributes & TUPLE_RETURN_NAME)? 964 HANDTPL_RETURN_NAME: 965 HANDTPL_PARSE_LTUPLE, 966 cisparse, cisdata); 967 mutex_exit(&sp->cis_lock); 968 if (ret == CISTPLF_UNKNOWN) 969 return (CS_UNKNOWN_TUPLE); 970 if (ret != CISTPLF_NOERROR) 971 return (CS_BAD_CIS); 972 ret = CS_SUCCESS; 973 } else { 974 mutex_exit(&sp->cis_lock); 975 ret = CS_NO_CIS; 976 } /* if (CW_VALID_CIS) */ 977 978 return (ret); 979 } 980 981 /* 982 * cs_get_firstnext_tuple - returns the first/next tuple of the specified type 983 * this is to support the GetFirstTuple and 984 * GetNextTuple function call 985 * 986 * flags - one of: 987 * CS_GET_FIRST_FLAG causes function to support GetFirstTuple 988 * CS_GET_NEXT_FLAG causes function to support GetNextTuple 989 * 990 * tuple_t->Attributes flags: 991 * TUPLE_RETURN_LINK - XXX Not implemented, see notes below. 992 * TUPLE_RETURN_IGNORED_TUPLES - return tuples with 993 * CISTPLF_IGNORE_TUPLE set in the 994 * cistpl_t->flags member. 995 * 996 * Notes for regular PC card driver callers: 997 * 998 * On a single-function card, the caller will get back all the tuples in 999 * the CIS. 1000 * 1001 * On a multi-function card, the caller will get the tuples from the 1002 * global CIS followed by the tuples in the function-specific CIS. The 1003 * caller will not get any tuples from a function-specific CIS that 1004 * does not belong to the caller's function. 1005 * 1006 * Notes for Socket Services, the "super-client" or CSI driver callers: 1007 * 1008 * On a single-function card, the operation is the same as for regular 1009 * PC card driver callers with the addition that if the function number 1010 * is set to CS_GLOBAL_CIS this function will return CS_NO_CIS. 1011 * 1012 * On a multi-function card, the operation is the same as for regular 1013 * PC card driver callers with the addition that if the function number 1014 * is set to CS_GLOBAL_CIS the caller will only get tuples from the 1015 * global CIS. If a particular function nubmer does not exist, this 1016 * function will return CS_NO_CIS for that function. 1017 * 1018 * General notes: 1019 * 1020 * On both a single-function card and a multi-function card, if the tuple 1021 * comes from the global CIS chain, the CISTPLF_GLOBAL_CIS flag will be 1022 * set in the tuple_t->flags member. 1023 * 1024 * On a multi-function card, if the tuple comes from the function-specific 1025 * CIS chain, the CISTPLF_MF_CIS flag will be set in the tuple_t->flags 1026 * member. 1027 * 1028 * For other flags that are set in the tuple_t->flags member, see the 1029 * comments for the cis_list_lcreate function in the cis.c file. 1030 * 1031 * The CIS parser may not include all the tuples that are in the CIS in 1032 * the private CIS list that it creates and maintains. See the CIS 1033 * parser documentation for a list of tuples that the parser does not 1034 * include in the list. 1035 * 1036 * If a tuple has the CISTPLF_IGNORE_TUPLE flag set and the flags 1037 * parameter CIS_GET_LTUPLE_IGNORE is not set, that tuple will not 1038 * be returned to the caller. Instead, the next tuple that matches 1039 * the calling criteria will be returned (or NULL if no other tuples 1040 * match the calling criteria). If CIS_GET_LTUPLE_IGNORE is set in 1041 * the flags paramter, tuples in the CIS list that match the calling 1042 * criteria will be returned. 1043 * 1044 * XXX The PC Card 95 Standard says that if the TUPLE_RETURN_LINK flag in 1045 * the tuple_t->Attributes member is not set, then we don't return 1046 * any of the link tuples. This function ignores this flag and always 1047 * returns link tuples. 1048 * 1049 * Return codes: 1050 * CS_SUCCESS - if tuple sucessfully found and returned 1051 * CS_NO_CARD - if no card inserted 1052 * CS_NO_CIS - if no CIS for the specified card/function 1053 * CS_NO_MORE_ITEMS - if tuple not found or no more tuples 1054 * to return 1055 * 1056 * See notes for cs_get_socket for a description of valid client, socket 1057 * and function number combinations. 1058 */ 1059 static int 1060 cs_get_firstnext_tuple(client_handle_t client_handle, 1061 tuple_t *tuple, uint32_t flags) 1062 { 1063 cs_socket_t *sp; 1064 client_t *client; 1065 uint32_t fn; 1066 int ret; 1067 1068 if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1069 &sp, &client)) != CS_SUCCESS) 1070 return (ret); 1071 1072 /* 1073 * If there's no card in the socket or the card in the socket is not 1074 * for this client, then return an error. 1075 */ 1076 if (!(client->flags & CLIENT_CARD_INSERTED)) 1077 return (CS_NO_CARD); 1078 1079 mutex_enter(&sp->cis_lock); 1080 1081 /* 1082 * If there's no CIS on this card or no CIS for the specified 1083 * function, then we can't do much. 1084 */ 1085 if ((!(sp->cis_flags & CW_VALID_CIS)) || 1086 (!(sp->cis[fn].flags & CW_VALID_CIS))) { 1087 mutex_exit(&sp->cis_lock); 1088 return (CS_NO_CIS); 1089 } 1090 1091 /* 1092 * This will set the CIS_GET_LTUPLE_IGNORE flag if the 1093 * TUPLE_RETURN_IGNORED_TUPLES flag is set. The 1094 * assumption here is that the CIS_GET_LTUPLE_IGNORE 1095 * flag and the TUPLE_RETURN_IGNORED_TUPLES flag 1096 * shares the same bit position. If this ever changes, 1097 * we'll ahve to re-work this section of code. 1098 */ 1099 if (tuple->Attributes & TUPLE_RETURN_IGNORED_TUPLES) 1100 flags |= CIS_GET_LTUPLE_IGNORE; 1101 1102 /* 1103 * Are we GetFirstTuple or GetNextTuple? 1104 */ 1105 if ((flags & CIS_GET_LTUPLE_OPMASK) & CS_GET_FIRST_FLAG) { 1106 /* 1107 * Initialize the tuple structure; we need this information when 1108 * we have to process a GetNextTuple or ParseTuple call. 1109 * If this card has a multi-function CIS, then we always start out 1110 * delivering tuples from the global CIS chain. If this card does 1111 * not have a multi-function CIS, then the function 0 CIS chain 1112 * will contain the complete CIS list. 1113 * If this is a multi-function card, then use the GET_FIRST_LTUPLE 1114 * macro to return the first tuple in the CIS list - we do this 1115 * since we don't want to return tuples with CISTPLF_IGNORE_TUPLE 1116 * set unless CIS_GET_LTUPLE_IGNORE is set in the flags parameter. 1117 * Note that we don't have to cross over into the fucntion-specific 1118 * CIS chain if GET_FIRST_LTUPLE returns NULL, since a MF CIS will 1119 * always have at least a CISTPL_LONGLINK_MFC tuple in the global 1120 * CIS chain - the test for NULL is just a sanity check. 1121 */ 1122 if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1123 if ((tuple->CISOffset = 1124 GET_FIRST_LTUPLE(sp->cis[CS_GLOBAL_CIS].cis, 1125 flags)) == NULL) { 1126 mutex_exit(&sp->cis_lock); 1127 return (CS_NO_MORE_ITEMS); 1128 } /* GET_FIRST_LTUPLE */ 1129 } else { 1130 tuple->CISOffset = sp->cis[0].cis; 1131 } /* CW_MULTI_FUNCTION_CIS */ 1132 } else { 1133 cistpl_t *tp; 1134 1135 /* 1136 * Check to be sure that we have a non-NULL tuple list pointer. 1137 * This is necessary in the case where the caller calls us 1138 * with get next tuple requests but we don't have any more 1139 * tuples to give back. 1140 */ 1141 if (tuple->CISOffset == NULL) { 1142 mutex_exit(&sp->cis_lock); 1143 return (CS_NO_MORE_ITEMS); 1144 } 1145 1146 /* 1147 * Point to the next tuple in the list. If we're searching for 1148 * a particular tuple, FIND_LTUPLE_FWD will find it. 1149 * 1150 * If there are no more tuples in the chain that we're looking 1151 * at, then if we're looking at the global portion of a 1152 * multi-function CIS, switch to the function-specific list 1153 * and start looking there. 1154 */ 1155 if ((tp = GET_NEXT_TUPLE(tuple->CISOffset, flags)) == NULL) { 1156 if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1157 if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1158 (fn != CS_GLOBAL_CIS)) { 1159 tp = GET_FIRST_LTUPLE(sp->cis[fn].cis, flags); 1160 } /* CISTPLF_GLOBAL_CIS */ 1161 } /* CW_MULTI_FUNCTION_CIS */ 1162 } /* GET_NEXT_TUPLE */ 1163 1164 /* 1165 * If there are no more tuples in the chain, then return. 1166 */ 1167 if ((tuple->CISOffset = tp) == NULL) { 1168 mutex_exit(&sp->cis_lock); 1169 return (CS_NO_MORE_ITEMS); 1170 } 1171 } /* CS_GET_FIRST_FLAG */ 1172 1173 /* 1174 * Check if we want to get the first of a particular type of tuple 1175 * or just the first tuple in the chain. 1176 * If there are no more tuples of the type we're searching for in 1177 * the chain that we're looking at, then if we're looking at 1178 * the global portion of a multi-function CIS, switch to the 1179 * function-specific list and start looking there. 1180 */ 1181 if (tuple->DesiredTuple != RETURN_FIRST_TUPLE) { 1182 cistpl_t *tp; 1183 1184 if ((tp = FIND_LTUPLE_FWD(tuple->CISOffset, 1185 tuple->DesiredTuple, flags)) == NULL) { 1186 if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1187 if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1188 (fn != CS_GLOBAL_CIS)) { 1189 tp = FIND_FIRST_LTUPLE(sp->cis[fn].cis, 1190 tuple->DesiredTuple, flags); 1191 } /* CISTPLF_GLOBAL_CIS */ 1192 } /* CW_MULTI_FUNCTION_CIS */ 1193 } /* FIND_LTUPLE_FWD */ 1194 1195 /* 1196 * If there are no more tuples in the chain, then return. 1197 */ 1198 if ((tuple->CISOffset = tp) == NULL) { 1199 mutex_exit(&sp->cis_lock); 1200 return (CS_NO_MORE_ITEMS); 1201 } 1202 } /* !RETURN_FIRST_TUPLE */ 1203 1204 /* 1205 * We've got a tuple, now fill out the rest of the tuple_t 1206 * structure. Callers can use the flags member to 1207 * determine whether or not the tuple data was copied 1208 * to the linked list or if it's still on the card. 1209 */ 1210 tuple->Flags = tuple->CISOffset->flags; 1211 tuple->TupleCode = tuple->CISOffset->type; 1212 tuple->TupleLink = tuple->CISOffset->len; 1213 tuple->TupleDataLen = tuple->CISOffset->len; 1214 1215 mutex_exit(&sp->cis_lock); 1216 1217 return (CS_SUCCESS); 1218 } 1219 1220 /* 1221 * cs_get_tuple_data - get the data portion of a tuple; this is to 1222 * support the GetTupleData function call. 1223 * 1224 * Note that if the data body of a tuple was not read from the CIS, 1225 * then this function will return CS_NO_MORE_ITEMS. 1226 * 1227 * For flags that are set in the tuple_t->flags member, see the 1228 * comments for the cis_list_lcreate function in the cis.c file. 1229 * These flags are copied into the tuple_t->flags member by the 1230 * cs_get_firstnext_tuple function call. 1231 * 1232 * See notes for the cs_get_firstnext_tuple function. 1233 */ 1234 static int 1235 cs_get_tuple_data(client_handle_t client_handle, tuple_t *tuple) 1236 { 1237 cs_socket_t *sp; 1238 client_t *client; 1239 int ret, nbytes; 1240 uint32_t fn, flags; 1241 cisdata_t *tsd, *tdd; 1242 uint32_t newoffset; 1243 acc_handle_t cis_handle; 1244 1245 if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1246 &sp, &client)) != CS_SUCCESS) 1247 return (ret); 1248 1249 /* 1250 * If there's no card in the socket or the card in the socket is not 1251 * for this client, then return an error. 1252 */ 1253 if (!(client->flags & CLIENT_CARD_INSERTED)) 1254 return (CS_NO_CARD); 1255 1256 mutex_enter(&sp->cis_lock); 1257 1258 if ((sp->cis_flags & CW_VALID_CIS) && 1259 (sp->cis[fn].flags & CW_VALID_CIS)) { 1260 1261 /* 1262 * Check to be sure that we have a non-NULL pointer to 1263 * a CIS list. 1264 */ 1265 if (!(tuple->CISOffset)) { 1266 mutex_exit(&sp->cis_lock); 1267 return (CS_NO_MORE_ITEMS); 1268 } 1269 1270 /* 1271 * Since the tuple data buffer that the caller calls us with 1272 * is preallocated in the tuple_t structure, we ignore any 1273 * TupleDataMax value that the caller has setup and use the 1274 * actual size of the tuple data buffer in the structure. 1275 */ 1276 tuple->TupleDataMax = sizeof (tuple->TupleData); 1277 1278 /* 1279 * Make sure the requested offset is not past the end of the 1280 * tuple data body nor past the end of the user-supplied 1281 * buffer. 1282 */ 1283 if ((int)tuple->TupleOffset >= min((int)tuple->TupleLink, 1284 (int)tuple->TupleDataMax)) { 1285 mutex_exit(&sp->cis_lock); 1286 return (CS_NO_MORE_ITEMS); 1287 } 1288 1289 tuple->TupleDataLen = tuple->TupleLink; 1290 1291 if ((nbytes = min((int)tuple->TupleDataMax - 1292 (int)tuple->TupleOffset, 1293 (int)tuple->TupleDataLen - 1294 (int)tuple->TupleOffset)) < 1) { 1295 mutex_exit(&sp->cis_lock); 1296 return (CS_BAD_ARGS); 1297 } 1298 1299 /* 1300 * The tuple data destination is always the tuple_t->TupleData 1301 * buffer in the tuple_t structure no matter where we read the 1302 * tuple data from. 1303 */ 1304 tdd = tuple->TupleData; 1305 bzero((caddr_t)tdd, sizeof (tuple->TupleData)); 1306 1307 /* 1308 * Do we have a copy of the tuple data? If not, we have to 1309 * get a pointer to the CIS and read the tuple data from the 1310 * card itself. 1311 */ 1312 switch (tuple->CISOffset->flags & CISTPLF_SPACE_MASK) { 1313 case CISTPLF_LM_SPACE: 1314 tsd = (tuple->CISOffset->data + 1315 (unsigned)tuple->TupleOffset); 1316 while (nbytes--) 1317 *tdd++ = *tsd++; 1318 break; 1319 case CISTPLF_AM_SPACE: 1320 case CISTPLF_CM_SPACE: 1321 newoffset = tuple->CISOffset->offset; 1322 1323 /* 1324 * Setup the proper space flags as well as setup the 1325 * address offset to point to the start of the tuple 1326 * data area; we need to do the latter since the 1327 * cis_store_cis_addr function in cis.c sets up the 1328 * tuple->CISOffset->offset offset to point to the 1329 * start of the tuple. 1330 */ 1331 if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) { 1332 flags = CISTPLF_AM_SPACE; 1333 newoffset += ((tuple->TupleOffset * 2) + 4); 1334 } else { 1335 flags = CISTPLF_CM_SPACE; 1336 newoffset += (tuple->TupleOffset + 2); 1337 } 1338 1339 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 1340 flags) != CS_SUCCESS) { 1341 mutex_exit(&sp->cis_lock); 1342 cmn_err(CE_CONT, "cs_get_tuple_data: socket %d " 1343 "can't init CIS window\n", 1344 sp->socket_num); 1345 return (CS_GENERAL_FAILURE); 1346 } /* cs_init_cis_window */ 1347 while (nbytes--) { 1348 *tdd++ = csx_Get8(cis_handle, newoffset++); 1349 if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) 1350 newoffset++; 1351 } /* while */ 1352 break; 1353 default: 1354 mutex_exit(&sp->cis_lock); 1355 return (CS_GENERAL_FAILURE); 1356 } /* switch */ 1357 1358 ret = CS_SUCCESS; 1359 } else { 1360 ret = CS_NO_CIS; 1361 } /* if (CW_VALID_CIS) */ 1362 1363 mutex_exit(&sp->cis_lock); 1364 1365 return (ret); 1366 } 1367 1368 /* 1369 * cs_validate_cis - validates the CIS on a card in the given socket; this 1370 * is to support the ValidateCIS function call. 1371 * 1372 * Notes for regular PC card driver callers: 1373 * 1374 * Regular PC card drivers calling ValidateCIS will get the meaning of 1375 * the structure members as specified in the standard. 1376 * 1377 * Notes for Socket Services, the "super-client" or CSI driver callers: 1378 * 1379 * with: Function Number = CS_GLOBAL_CIS 1380 * 1381 * For a single-function card, CS_NO_CIS will be returned and the 1382 * cisinfo_t->Chains and cisinfo_t->Tuples members will be set to 0. 1383 * 1384 * For a multi-function card, cisinfo_t->Chains will contain a count of 1385 * the number of CIS chains in the global portion of the CIS, and 1386 * cisinfo_t->Tuples will contain a count of the number of tuples in 1387 * the global portion of the CIS. 1388 * 1389 * with: 0 <= Function Number < CIS_MAX_FUNCTIONS 1390 * 1391 * For a single-function card, if the function number is equal to 0 and 1392 * has a CIS, cisinfo_t->Chains will contain a count of the number of 1393 * CIS chains in the CIS, and cisinfo_t->Tuples will contain a count of 1394 * the number of tuples in the CIS. If the card does not have a CIS, or 1395 * if the function number is not equal to 0, CS_NO_CIS will be returned 1396 * and the cisinfo_t->Chains and cisinfo_t->Tuples members will be set 1397 * to 0. 1398 * 1399 * For a multi-function card, cisinfo_t->Chains will contain a count of 1400 * the number of CIS chains in the global and function-specific 1401 * portions of the CIS, and cisinfo_t->Tuples will contain a count of 1402 * the number of tuples in the global and function-specific portions of 1403 * the CIS. If the function does not exist or has no CIS, CS_NO_CIS 1404 * will be returned and the cisinfo_t->Chains and cisinfo_t->Tuples 1405 * members will be set to 0. 1406 * 1407 * General notes: 1408 * 1409 * If the card does not have a CIS, or if the function does not exist 1410 * or has no CIS, CS_NO_CIS will be returned and the cisinfo_t->Chains 1411 * and cisinfo_t->Tuples members will be set to 0. 1412 * 1413 * Most of the work of validating the CIS has already been done by the 1414 * CIS parser module, so we don't have to do much here except for 1415 * looking at the various flags and tuple/chain counts that were already 1416 * setup by the CIS parser. 1417 * 1418 * See notes for the cs_get_firstnext_tuple function. 1419 */ 1420 static int 1421 cs_validate_cis(client_handle_t client_handle, cisinfo_t *cisinfo) 1422 { 1423 cs_socket_t *sp; 1424 client_t *client; 1425 uint32_t fn; 1426 int ret; 1427 1428 if ((ret = cs_get_socket(client_handle, &cisinfo->Socket, &fn, 1429 &sp, &client)) != CS_SUCCESS) 1430 return (ret); 1431 1432 /* 1433 * If there's no card in the socket or the card in the socket is not 1434 * for this client, then return an error. 1435 */ 1436 if (!(client->flags & CLIENT_CARD_INSERTED)) 1437 return (CS_NO_CARD); 1438 1439 mutex_enter(&sp->cis_lock); 1440 if ((sp->cis_flags & CW_VALID_CIS) && 1441 (sp->cis[fn].flags & CW_VALID_CIS)) { 1442 cisinfo->Chains = sp->cis[fn].nchains; 1443 cisinfo->Tuples = sp->cis[fn].ntuples; 1444 1445 if ((fn != CS_GLOBAL_CIS) && 1446 (sp->cis[CS_GLOBAL_CIS].flags & CW_VALID_CIS)) { 1447 cisinfo->Chains += sp->cis[CS_GLOBAL_CIS].nchains; 1448 cisinfo->Tuples += sp->cis[CS_GLOBAL_CIS].ntuples; 1449 } /* !CS_GLOBAL_CIS */ 1450 1451 ret = CS_SUCCESS; 1452 } else { 1453 cisinfo->Chains = 0; 1454 cisinfo->Tuples = 0; 1455 ret = CS_NO_CIS; 1456 } 1457 mutex_exit(&sp->cis_lock); 1458 1459 return (ret); 1460 } 1461 1462 /* 1463 * cs_init_cis_window - initializes the CIS window for the passed socket 1464 * 1465 * calling: *sp - pointer to the per-socket structure 1466 * *offset - offset from start of AM or CM space 1467 * *hp - pointer to acc_handle_t to store modified 1468 * window access handle in 1469 * flags - one of: 1470 * CISTPLF_AM_SPACE - set window to AM space 1471 * CISTPLF_CM_SPACE - set window to CM space 1472 * 1473 * returns: CS_SUCCESS if CIS window was set up 1474 * *offset - contains adjusted offset to use to access 1475 * requested space 1476 * CS_BAD_WINDOW if CIS window could not be setup 1477 * CS_GENERAL_FAILURE if socket has a CIS window number 1478 * but the window flags are wrong 1479 * 1480 * Note: This function will check to be sure that there is a valid 1481 * CIS window allocated to this socket. 1482 * If there is an error in setting up the window hardware, the 1483 * CIS window information for this socket is cleared. 1484 * This function is also used by routines that need to get 1485 * a pointer to the base of AM space to access the card's 1486 * configuration registers. 1487 * The passed offset is the un-window-size-aligned offset. 1488 */ 1489 int 1490 cs_init_cis_window(cs_socket_t *sp, uint32_t *offset, 1491 acc_handle_t *hp, uint32_t flags) 1492 { 1493 set_window_t sw; 1494 get_window_t gw; 1495 inquire_window_t iw; 1496 set_page_t set_page; 1497 cs_window_t *cw; 1498 1499 /* 1500 * Check to be sure that we have a valid CIS window 1501 */ 1502 if (!SOCKET_HAS_CIS_WINDOW(sp)) { 1503 cmn_err(CE_CONT, 1504 "cs_init_cis_window: socket %d has no CIS window\n", 1505 sp->socket_num); 1506 return (CS_BAD_WINDOW); 1507 } 1508 1509 /* 1510 * Check to be sure that this window is allocated for CIS use 1511 */ 1512 if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) 1513 return (CS_BAD_WINDOW); 1514 1515 if (!(cw->state & CW_CIS)) { 1516 cmn_err(CE_CONT, 1517 "cs_init_cis_window: socket %d invalid CIS window state 0x%x\n", 1518 sp->socket_num, cw->state); 1519 return (CS_BAD_WINDOW); 1520 } 1521 1522 /* 1523 * Get the characteristics of this window - we use this to 1524 * determine whether we need to re-map the window or 1525 * just move the window offset on the card. 1526 */ 1527 iw.window = sp->cis_win_num; 1528 SocketServices(SS_InquireWindow, &iw); 1529 1530 /* 1531 * We've got a window, now set up the hardware. If we've got 1532 * a variable sized window, then all we need to do is to 1533 * get a valid mapping to the base of the window using 1534 * the current window size; if we've got a fixed-size 1535 * window, then we need to get a mapping to the window 1536 * starting at offset zero of the window. 1537 */ 1538 if (iw.mem_win_char.MemWndCaps & WC_SIZE) { 1539 sw.WindowSize = sp->cis_win_size; 1540 set_page.offset = ((*offset / sp->cis_win_size) * 1541 sp->cis_win_size); 1542 } else { 1543 set_page.offset = ((*offset / iw.mem_win_char.MinSize) * 1544 iw.mem_win_char.MinSize); 1545 sw.WindowSize = (((*offset & ~(PAGESIZE - 1)) & 1546 (set_page.offset - 1)) + PAGESIZE); 1547 } 1548 1549 /* 1550 * Return a normalized base offset; this takes care of the case 1551 * where the required offset is greater than the window size. 1552 * BugID 1236404 1553 * code was: 1554 * *offset = *offset & (set_page.offset - 1); 1555 */ 1556 *offset = *offset - set_page.offset; 1557 1558 #ifdef CS_DEBUG 1559 if (cs_debug > 1) 1560 cmn_err(CE_CONT, "cs_init_cis_window: WindowSize 0x%x " 1561 "offset 0x%x\n", 1562 (int)sw.WindowSize, 1563 (int)set_page.offset); 1564 if (cs_debug > 1) 1565 cmn_err(CE_CONT, "\t*offset = 0x%x space = %s\n", 1566 (int)*offset, 1567 (flags & CISTPLF_AM_SPACE)? 1568 "CISTPLF_AM_SPACE":"CISTPLF_CM_SPACE"); 1569 #endif 1570 1571 sw.window = sp->cis_win_num; 1572 sw.socket = sp->socket_num; 1573 sw.state = (WS_ENABLED | WS_EXACT_MAPIN); 1574 sw.attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1575 sw.attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 1576 sw.attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1577 1578 /* 1579 * The PCMCIA SS spec specifies this be expressed in 1580 * a device speed format per 5.2.7.1.3 but 1581 * our implementation of SS_SetWindow uses 1582 * actual nanoseconds. 1583 */ 1584 sw.speed = CIS_DEFAULT_SPEED; 1585 sw.base = 0; 1586 /* 1587 * Set up the window - if this fails, then just set the 1588 * CIS window number back to it's initialized value so 1589 * that we'll fail when we break out of the loop. 1590 */ 1591 if (SocketServices(SS_SetWindow, &sw) != SUCCESS) { 1592 sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1593 cw->state = 0; /* XXX do we really want to do this? */ 1594 return (CS_BAD_WINDOW); 1595 } else { 1596 set_page.window = sp->cis_win_num; 1597 set_page.page = 0; 1598 set_page.state = PS_ENABLED; 1599 if (flags & CISTPLF_AM_SPACE) 1600 set_page.state |= PS_ATTRIBUTE; 1601 1602 if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 1603 sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1604 cw->state = 0; /* XXX do we really want to do this? */ 1605 return (CS_BAD_WINDOW); 1606 } /* if (SS_SetPage) */ 1607 } /* if (SS_SetWindow) */ 1608 1609 /* 1610 * Get the window information for the CIS window for this socket. 1611 */ 1612 gw.window = sp->cis_win_num; 1613 gw.socket = sp->socket_num; /* XXX - SS_GetWindow should set this */ 1614 if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 1615 return (CS_BAD_WINDOW); 1616 1617 *hp = (acc_handle_t)gw.handle; 1618 1619 return (CS_SUCCESS); 1620 } 1621 1622 /* 1623 * ==== client registration/deregistration section ==== 1624 */ 1625 1626 /* 1627 * cs_register_client - This supports the RegisterClient call. 1628 * 1629 * Upon successful registration, the client_handle_t * handle argument will 1630 * contain the new client handle and we return CS_SUCCESS. 1631 */ 1632 static int 1633 cs_register_client(client_handle_t *ch, client_reg_t *cr) 1634 { 1635 uint32_t sn; 1636 int super_client = 0; 1637 sclient_reg_t *scr = cr->priv; 1638 struct sclient_list_t *scli; 1639 1640 /* 1641 * See if we're not supposed to register any new clients. 1642 */ 1643 if (cs_globals.init_state & GLOBAL_INIT_STATE_NO_CLIENTS) 1644 return (CS_OUT_OF_RESOURCE); 1645 1646 /* 1647 * Do a version check - if the client expects a later version of 1648 * Card Services than what we are, return CS_BAD_VERSION. 1649 * XXX - How do we specify just a PARTICULAR version of CS?? 1650 */ 1651 if (CS_VERSION < cr->Version) 1652 return (CS_BAD_VERSION); 1653 1654 /* 1655 * Check to be sure that the client has given us a valid set of 1656 * client type flags. We also use this opportunity to see 1657 * if the registering client is Socket Services or is a 1658 * "super-client" or a CSI client. 1659 * 1660 * Note that SS can not set any flag in the Attributes field other 1661 * than the INFO_SOCKET_SERVICES flag. 1662 * 1663 * Valid combinations of cr->Attributes and cr->EventMask flags: 1664 * 1665 * for Socket Services: 1666 * cr->Attributes: 1667 * set: 1668 * INFO_SOCKET_SERVICES 1669 * clear: 1670 * {all other flags} 1671 * cr->EventMask: 1672 * don't care: 1673 * {all flags} 1674 * 1675 * for regular clients: 1676 * cr->Attributes: 1677 * only one of: 1678 * INFO_IO_CLIENT 1679 * INFO_MTD_CLIENT 1680 * INFO_MEM_CLIENT 1681 * don't care: 1682 * INFO_CARD_SHARE 1683 * INFO_CARD_EXCL 1684 * cr->EventMask: 1685 * clear: 1686 * CS_EVENT_ALL_CLIENTS 1687 * don't care: 1688 * {all other flags} 1689 * 1690 * for CSI clients: 1691 * cr->Attributes: 1692 * set: 1693 * INFO_IO_CLIENT 1694 * INFO_CSI_CLIENT 1695 * clear: 1696 * INFO_MTD_CLIENT 1697 * INFO_MEM_CLIENT 1698 * don't care: 1699 * INFO_CARD_SHARE 1700 * INFO_CARD_EXCL 1701 * cr->EventMask: 1702 * don't care: 1703 * {all flags} 1704 * 1705 * for "super-clients": 1706 * cr->Attributes: 1707 * set: 1708 * INFO_IO_CLIENT 1709 * INFO_MTD_CLIENT 1710 * INFO_SOCKET_SERVICES 1711 * INFO_CARD_SHARE 1712 * clear: 1713 * INFO_MEM_CLIENT 1714 * INFO_CARD_EXCL 1715 * cr->EventMask: 1716 * don't care: 1717 * {all flags} 1718 */ 1719 switch (cr->Attributes & INFO_CLIENT_TYPE_MASK) { 1720 /* 1721 * Check first to see if this is Socket Services registering; if 1722 * so, we don't do anything but return the client handle that is 1723 * in the global SS client. 1724 */ 1725 case INFO_SOCKET_SERVICES: 1726 *ch = cs_socket_services_client.client_handle; 1727 return (CS_SUCCESS); 1728 /* NOTREACHED */ 1729 /* CSI clients */ 1730 case (INFO_CSI_CLIENT | INFO_IO_CLIENT): 1731 break; 1732 /* regular clients */ 1733 case INFO_IO_CLIENT: 1734 case INFO_MTD_CLIENT: 1735 case INFO_MEM_CLIENT: 1736 if (cr->EventMask & CS_EVENT_ALL_CLIENTS) 1737 return (CS_BAD_ATTRIBUTE); 1738 break; 1739 /* "super-client" clients */ 1740 case (INFO_IO_CLIENT | INFO_MTD_CLIENT | INFO_SOCKET_SERVICES): 1741 if ((!(cr->Attributes & INFO_CARD_SHARE)) || 1742 (cr->Attributes & INFO_CARD_EXCL)) 1743 return (CS_BAD_ATTRIBUTE); 1744 /* 1745 * We only allow one "super-client" per system. 1746 */ 1747 mutex_enter(&cs_globals.global_lock); 1748 if (cs_globals.flags & GLOBAL_SUPER_CLIENT_REGISTERED) { 1749 mutex_exit(&cs_globals.global_lock); 1750 return (CS_NO_MORE_ITEMS); 1751 } 1752 cs_globals.flags |= GLOBAL_SUPER_CLIENT_REGISTERED; 1753 mutex_exit(&cs_globals.global_lock); 1754 super_client = CLIENT_SUPER_CLIENT; 1755 break; 1756 default: 1757 return (CS_BAD_ATTRIBUTE); 1758 } /* switch (cr->Attributes) */ 1759 1760 /* 1761 * Now, actually create the client node on the socket; this will 1762 * also return the new client handle if there were no errors 1763 * creating the client node. 1764 * The DIP2SOCKET_NUM macro will return the socket and function 1765 * number using the encoding specified in the cs_priv.h file. 1766 */ 1767 if (super_client != CLIENT_SUPER_CLIENT) { 1768 if (cr->Attributes & INFO_CSI_CLIENT) 1769 sn = (uint32_t)(uintptr_t)cr->priv; 1770 else 1771 sn = DIP2SOCKET_NUM(cr->dip); 1772 return (cs_add_client_to_socket(sn, ch, cr, super_client)); 1773 } /* CLIENT_SUPER_CLIENT */ 1774 1775 /* 1776 * This registering client is a "super-client", so we create one 1777 * client node for each socket in the system. We use the 1778 * client_reg_t.priv structure member to point to a struct 1779 * that the "super-client" client knows about. The client 1780 * handle pointer is not used in this case. 1781 * We return CS_SUCCESS if at least one client node could be 1782 * created. The client must check the error codes in the 1783 * error code array to determine which clients could not 1784 * be created on which sockets. 1785 * We return CS_BAD_HANDLE if no client nodes could be created. 1786 */ 1787 scr->num_clients = 0; 1788 scr->max_socket_num = cs_globals.max_socket_num; 1789 scr->num_sockets = cs_globals.num_sockets; 1790 scr->num_windows = cs_globals.num_windows; 1791 1792 *(scr->sclient_list) = cs_globals.sclient_list; 1793 1794 for (sn = 0; sn < scr->num_sockets; sn++) { 1795 scli = scr->sclient_list[sn]; 1796 if ((scli->error = cs_add_client_to_socket(sn, &scli->client_handle, 1797 cr, super_client)) == CS_SUCCESS) { 1798 scr->num_clients++; 1799 } 1800 } 1801 1802 /* 1803 * If we couldn't create any client nodes at all, then 1804 * return an error. 1805 */ 1806 if (!scr->num_clients) { 1807 /* 1808 * XXX - The global superclient lock now gets 1809 * cleared in cs_deregister_client 1810 */ 1811 /* cs_clear_superclient_lock(super_client); */ 1812 return (CS_BAD_HANDLE); 1813 } 1814 1815 return (CS_SUCCESS); 1816 } 1817 1818 /* 1819 * cs_add_client_to_socket - this function creates the client node on the 1820 * requested socket. 1821 * 1822 * Note that if we return an error, there is no state that can be cleaned 1823 * up. The only way that we can return an error with allocated resources 1824 * would be if one of the client handle functions had an internal error. 1825 * Since we wouldn't get a valid client handle in this case anyway, there 1826 * would be no way to find out what was allocated and what wasn't. 1827 */ 1828 static int 1829 cs_add_client_to_socket(unsigned sn, client_handle_t *ch, 1830 client_reg_t *cr, int super_client) 1831 { 1832 cs_socket_t *sp; 1833 client_t *client, *cclp; 1834 int error, cie = 1; 1835 int client_lock_acquired; 1836 1837 if (cr->event_handler == NULL) 1838 return (CS_BAD_ARGS); 1839 1840 if ((sp = cs_get_sp(sn)) == NULL) 1841 return (CS_BAD_SOCKET); 1842 1843 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 1844 1845 /* 1846 * Run through all of the registered clients and compare the passed 1847 * dip to the dip of each client to make sure that this client 1848 * is not trying to register more than once. If they are, then 1849 * display a message and return an error. 1850 * XXX - we should really check all the sockets in case the client 1851 * manipulates the instance number in the dip. 1852 * XXX - if we check each socket, we ned to also check for the 1853 * "super-client" since it will use the same dip for all 1854 * of it's client nodes. 1855 */ 1856 mutex_enter(&sp->lock); 1857 client = sp->client_list; 1858 while (client) { 1859 if (!(cr->Attributes & INFO_CSI_CLIENT) && 1860 (client->dip == cr->dip)) { 1861 mutex_exit(&sp->lock); 1862 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1863 cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d " 1864 "function 0x%x\n" 1865 "\tclient already registered with " 1866 "handle 0x%x\n", 1867 (int)CS_GET_SOCKET_NUMBER(sn), 1868 (int)CS_GET_FUNCTION_NUMBER(sn), 1869 (int)client->client_handle); 1870 return (CS_BAD_HANDLE); 1871 } 1872 client = client->next; 1873 } /* while (client) */ 1874 mutex_exit(&sp->lock); 1875 1876 /* 1877 * Create a unique client handle then make sure that we can find it. 1878 * This has the side effect of getting us a pointer to the 1879 * client structure as well. 1880 * Create a client list entry - cs_create_client_handle will use this 1881 * as the new client node. 1882 * We do it here so that we can grab the sp->lock mutex for the 1883 * duration of our manipulation of the client list. 1884 * If this function fails, then it will not have added the newly 1885 * allocated client node to the client list on this socket, 1886 * so we have to free the node that we allocated. 1887 */ 1888 cclp = (client_t *)kmem_zalloc(sizeof (client_t), KM_SLEEP); 1889 1890 mutex_enter(&sp->lock); 1891 if (!(*ch = cs_create_client_handle(sn, cclp))) { 1892 mutex_exit(&sp->lock); 1893 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1894 kmem_free(cclp, sizeof (client_t)); 1895 return (CS_OUT_OF_RESOURCE); 1896 } 1897 1898 /* 1899 * Make sure that this is a valid client handle. We should never 1900 * fail this since we just got a valid client handle. 1901 * If this fails, then we have an internal error so don't bother 1902 * trying to clean up the allocated client handle since the 1903 * whole system is probably hosed anyway and will shortly 1904 * esplode. 1905 * It doesn't make sense to call cs_deregister_client at this point 1906 * to clean up this broken client since the deregistration 1907 * code will also call cs_find_client and most likely fail. 1908 */ 1909 if (!(client = cs_find_client(*ch, &error))) { 1910 mutex_exit(&sp->lock); 1911 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1912 cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d function 0x%x " 1913 "invalid client handle created handle 0x%x\n", 1914 (int)CS_GET_SOCKET_NUMBER(sn), 1915 (int)CS_GET_FUNCTION_NUMBER(sn), 1916 (int)*ch); 1917 return (error); 1918 } 1919 1920 /* 1921 * Save the DDI information. 1922 */ 1923 client->dip = cr->dip; 1924 cr->driver_name[MODMAXNAMELEN - 1] = NULL; 1925 client->driver_name = (char *)kmem_zalloc(strlen(cr->driver_name) + 1, 1926 KM_SLEEP); 1927 (void) strcpy(client->driver_name, cr->driver_name); 1928 client->instance = ddi_get_instance(cr->dip); 1929 1930 /* 1931 * Copy over the interesting items that the client gave us. 1932 */ 1933 client->flags = (cr->Attributes & INFO_CLIENT_TYPE_MASK); 1934 client->event_callback_handler = cr->event_handler; 1935 bcopy((caddr_t)&cr->event_callback_args, 1936 (caddr_t)&client->event_callback_args, 1937 sizeof (event_callback_args_t)); 1938 /* 1939 * Set the client handle since the client needs a client handle 1940 * when they call us for their event handler. 1941 */ 1942 client->event_callback_args.client_handle = *ch; 1943 1944 /* 1945 * Initialize the IO window numbers; if an IO window number is equal 1946 * to PCMCIA_MAX_WINDOWS it means that IO range is not in use. 1947 */ 1948 client->io_alloc.Window1 = PCMCIA_MAX_WINDOWS; 1949 client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 1950 1951 /* 1952 * Give the client the iblock and idevice cookies to use in 1953 * the client's event handler high priority mutex. 1954 */ 1955 cr->iblk_cookie = sp->iblk; 1956 cr->idev_cookie = sp->idev; 1957 1958 /* 1959 * Set up the global event mask information; we copy this directly 1960 * from the client; since we are the only source of events, 1961 * any bogus bits that the client puts in here won't matter 1962 * because we'll never look at them. 1963 */ 1964 client->global_mask = cr->EventMask; 1965 1966 /* 1967 * If this client registered as a CSI client, set the appropriate 1968 * flag in the client's flags area. 1969 */ 1970 if (cr->Attributes & INFO_CSI_CLIENT) 1971 client->flags |= CLIENT_CSI_CLIENT; 1972 1973 /* 1974 * If this client registered as a "super-client" set the appropriate 1975 * flag in the client's flags area. 1976 */ 1977 if (super_client == CLIENT_SUPER_CLIENT) 1978 client->flags |= CLIENT_SUPER_CLIENT; 1979 1980 /* 1981 * Save other misc information that this client gave us - it is 1982 * used in the GetClientInfo function. 1983 */ 1984 client->flags |= (cr->Attributes & INFO_CARD_FLAGS_MASK); 1985 1986 /* 1987 * Determine if we should give artificial card insertion events and 1988 * a registration complete event. Since we don't differentiate 1989 * between sharable and exclusive use cards when giving clients 1990 * event notification, we modify the definition of the share/excl 1991 * flags as follows: 1992 * 1993 * If either INFO_CARD_SHARE or INFO_CARD_EXCL is set, 1994 * the client will receive artificial card insertion 1995 * events (if the client's card is currently in the 1996 * socket) and a registration complete event. 1997 * 1998 * If neither of the INFO_CARD_SHARE or INFO_CARD_EXCL is 1999 * set, the client will not receive an artificial card 2000 * insertion event nor a registration complete event 2001 * due to the client's call to register client. 2002 * 2003 * The client's event mask is not affected by the setting 2004 * of these two bits. 2005 */ 2006 if (cr->Attributes & (INFO_CARD_SHARE | INFO_CARD_EXCL)) 2007 client->pending_events = CS_EVENT_REGISTRATION_COMPLETE; 2008 2009 /* 2010 * Check to see if the card for this client is currently in 2011 * the socket. If it is, then set CLIENT_CARD_INSERTED 2012 * since clients that are calling GetStatus at attach 2013 * time will typically check to see if their card is 2014 * currently installed. 2015 * If this is the CSI client, we also need to check to see 2016 * if there is any card inserted in the socket, since 2017 * the cs_card_for_client function will always return 2018 * TRUE for a CSI client. 2019 * XXX What about super-clients? 2020 */ 2021 if (client->flags & CLIENT_CSI_CLIENT) { 2022 get_ss_status_t get_ss_status; 2023 2024 get_ss_status.socket = sp->socket_num; 2025 2026 if (SocketServices(SS_GetStatus, &get_ss_status) != SUCCESS) { 2027 mutex_exit(&sp->lock); 2028 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2029 return (CS_BAD_SOCKET); 2030 } /* SS_GetStatus */ 2031 2032 if (!(cs_sbm2cse(get_ss_status.CardState) & 2033 CS_EVENT_CARD_INSERTION)) 2034 cie = 0; 2035 2036 } /* CLIENT_CSI_CLIENT */ 2037 2038 if (cs_card_for_client(client) && (cie != 0)) { 2039 client->pending_events |= CS_EVENT_CARD_INSERTION; 2040 client->flags |= CLIENT_CARD_INSERTED; 2041 } /* cs_card_for_client */ 2042 2043 sp->num_clients++; 2044 mutex_exit(&sp->lock); 2045 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2046 2047 return (CS_SUCCESS); 2048 } 2049 2050 /* 2051 * cs_deregister_client - This supports the DeregisterClient call. 2052 */ 2053 static int 2054 cs_deregister_client(client_handle_t client_handle) 2055 { 2056 cs_socket_t *sp; 2057 client_t *client; 2058 int error, super_client = 0; 2059 int client_lock_acquired; 2060 2061 /* 2062 * Check to see if this is the Socket Services client handle; if it 2063 * is, we don't do anything except for return success. 2064 */ 2065 if (CLIENT_HANDLE_IS_SS(client_handle)) 2066 return (CS_SUCCESS); 2067 2068 /* 2069 * Get a pointer to this client's socket structure. 2070 */ 2071 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2072 return (CS_BAD_SOCKET); 2073 2074 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 2075 2076 /* 2077 * Make sure that this is a valid client handle. 2078 */ 2079 if (!(client = cs_find_client(client_handle, &error))) { 2080 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2081 return (error); 2082 } 2083 2084 /* 2085 * Make sure that any resources allocated by this client are 2086 * not still allocated, and that if this is an MTD that 2087 * no MTD operations are still in progress. 2088 */ 2089 if (client->flags & (CLIENT_IO_ALLOCATED | 2090 CLIENT_IRQ_ALLOCATED | 2091 CLIENT_WIN_ALLOCATED | 2092 REQ_CONFIGURATION_DONE | 2093 REQ_SOCKET_MASK_DONE | 2094 REQ_IO_DONE | 2095 REQ_IRQ_DONE)) { 2096 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2097 return (CS_BUSY); 2098 } 2099 2100 if (client->flags & CLIENT_MTD_IN_PROGRESS) { 2101 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2102 return (CS_IN_USE); 2103 } 2104 2105 /* 2106 * Any previously allocated resources are not allocated anymore, and 2107 * no MTD operations are in progress, so if this is an MTD client 2108 * then do any MTD-specific client deregistration, and then 2109 * nuke this client. 2110 * We expect cs_deregister_mtd to never fail. 2111 */ 2112 if (client->flags & INFO_MTD_CLIENT) 2113 (void) cs_deregister_mtd(client_handle); 2114 2115 if (client->flags & CLIENT_SUPER_CLIENT) 2116 super_client = CLIENT_SUPER_CLIENT; 2117 2118 kmem_free(client->driver_name, strlen(client->driver_name) + 1); 2119 2120 error = cs_destroy_client_handle(client_handle); 2121 2122 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2123 2124 /* 2125 * If this was the "super-client" deregistering, then this 2126 * will clear the global "super-client" lock. 2127 * XXX - move this outside the per-socket code. 2128 */ 2129 cs_clear_superclient_lock(super_client); 2130 2131 return (error); 2132 } 2133 2134 /* 2135 * cs_create_next_client_minor - returns the next available client minor 2136 * number or 0 if none available 2137 * 2138 * Note that cs_find_client will always return a valid pointer to the 2139 * global Socket Services client which has a client minor number 2140 * of 0; this means that this function can never return a 0 as the 2141 * next valid available client minor number. 2142 */ 2143 unsigned 2144 cs_create_next_client_minor(unsigned socket_num, unsigned next_minor) 2145 { 2146 unsigned max_client_handles = cs_max_client_handles; 2147 2148 do { 2149 next_minor &= CS_MAX_CLIENTS_MASK; 2150 if (!cs_find_client(MAKE_CLIENT_HANDLE( 2151 CS_GET_SOCKET_NUMBER(socket_num), 2152 CS_GET_FUNCTION_NUMBER(socket_num), 2153 next_minor), NULL)) { 2154 return (next_minor); 2155 } 2156 next_minor++; 2157 } while (max_client_handles--); 2158 2159 return (0); 2160 } 2161 2162 /* 2163 * cs_find_client - finds the client pointer associated with the client handle 2164 * or NULL if client not found 2165 * 2166 * returns: (client_t *)NULL - if client not found or an error occured 2167 * If the error argument is not NULL, 2168 * it is set to: 2169 * CS_BAD_SOCKET - socket number in client_handle_t is 2170 * invalid 2171 * CS_BAD_HANDLE - client not found 2172 * If no error, the error argument is not modified. 2173 * (client_t *) - pointer to client_t structure 2174 * 2175 * Note that each socket always has a pseudo client with a client minor number 2176 * of 0; this client minor number is used for Socket Services access to 2177 * Card Services functions. The client pointer returned for client minor 2178 * number 0 is the global Socket Services client pointer. 2179 */ 2180 static client_t * 2181 cs_find_client(client_handle_t client_handle, int *error) 2182 { 2183 cs_socket_t *sp; 2184 client_t *clp; 2185 2186 /* 2187 * If we are being asked to see if a client with a minor number 2188 * of 0 exists, always return a pointer to the global Socket 2189 * Services client, since this client always exists, and is 2190 * only for use by Socket Services. There is no socket 2191 * associated with this special client handle. 2192 */ 2193 if (CLIENT_HANDLE_IS_SS(client_handle)) 2194 return (&cs_socket_services_client); 2195 2196 /* 2197 * Check to be sure that the socket number is in range 2198 */ 2199 if (!(CHECK_SOCKET_NUM(GET_CLIENT_SOCKET(client_handle), 2200 cs_globals.max_socket_num))) { 2201 if (error) 2202 *error = CS_BAD_SOCKET; 2203 return (NULL); 2204 } 2205 2206 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) { 2207 if (error) 2208 *error = CS_BAD_SOCKET; 2209 return (NULL); 2210 } 2211 2212 clp = sp->client_list; 2213 2214 while (clp) { 2215 if (clp->client_handle == client_handle) 2216 return (clp); 2217 clp = clp->next; 2218 } 2219 2220 if (error) 2221 *error = CS_BAD_HANDLE; 2222 2223 return (NULL); 2224 } 2225 2226 /* 2227 * cs_destroy_client_handle - destroys client handle and client structure of 2228 * passed client handle 2229 * 2230 * returns: CS_SUCCESS - if client handle sucessfully destroyed 2231 * CS_BAD_HANDLE - if client handle is invalid or if trying 2232 * to destroy global SS client 2233 * {other errors} - other errors from cs_find_client() 2234 */ 2235 static int 2236 cs_destroy_client_handle(client_handle_t client_handle) 2237 { 2238 client_t *clp; 2239 cs_socket_t *sp; 2240 int error = CS_BAD_HANDLE; 2241 2242 /* 2243 * See if we were passed a valid client handle or if we're being asked 2244 * to destroy the Socket Services client 2245 */ 2246 if ((!(clp = cs_find_client(client_handle, &error))) || 2247 (CLIENT_HANDLE_IS_SS(client_handle))) 2248 return (error); 2249 2250 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2251 return (CS_BAD_SOCKET); 2252 2253 /* 2254 * Recycle this client's minor number. This will most likely 2255 * be the next client minor number we use, but it is also 2256 * a hint to cs_create_client_handle, and that function 2257 * may actually create a new client handle using a minor 2258 * number different that this number. 2259 */ 2260 mutex_enter(&sp->lock); 2261 sp->next_cl_minor = GET_CLIENT_MINOR(client_handle); 2262 2263 /* 2264 * See if we're the first or not in the client list; if we're 2265 * not first, then just adjust the client behind us to 2266 * point to the client ahead of us; this could be NULL 2267 * if we're the last client in the list. 2268 */ 2269 if (clp->prev) { 2270 clp->prev->next = clp->next; 2271 } else { 2272 /* 2273 * We are first, so adjust the client list head pointer 2274 * in the socket to point to the client structure that 2275 * follows us; this could turn out to be NULL if we're 2276 * the only client on this socket. 2277 */ 2278 sp->client_list = clp->next; 2279 } 2280 2281 /* 2282 * If we're not the last client in the list, point the next 2283 * client to the client behind us; this could turn out 2284 * to be NULL if we're the first client on this socket. 2285 */ 2286 if (clp->next) 2287 clp->next->prev = clp->prev; 2288 2289 sp->num_clients--; 2290 mutex_exit(&sp->lock); 2291 2292 /* 2293 * Free this client's memory. 2294 */ 2295 kmem_free(clp, sizeof (client_t)); 2296 2297 return (CS_SUCCESS); 2298 } 2299 2300 /* 2301 * cs_create_client_handle - create a new client handle for the passed 2302 * socket and function number 2303 * 2304 * returns: 0 - if can't create client for some reason 2305 * client_handle_t - new client handle 2306 */ 2307 static client_handle_t 2308 cs_create_client_handle(unsigned socket_num, client_t *cclp) 2309 { 2310 client_t *clp; 2311 cs_socket_t *sp; 2312 unsigned next_minor; 2313 client_handle_t client_handle; 2314 2315 if ((sp = cs_get_sp(socket_num)) == NULL) 2316 return (0); 2317 2318 /* 2319 * Get the next available minor number that we can use. We use the 2320 * next_cl_minor number as a hint to cs_create_next_client_minor 2321 * and in most cases this will be the minor number we get back. 2322 * If for some reason we can't get a minor number, return an error. 2323 * The only way we could get an error would be if there are 2324 * already the maximum number of clients for this socket. Since 2325 * the maximum number of clients per socket is pretty large, 2326 * this error is unlikely to occur. 2327 */ 2328 if (!(next_minor = 2329 cs_create_next_client_minor(socket_num, sp->next_cl_minor))) 2330 return (0); 2331 2332 /* 2333 * Got a new client minor number, now create a new client handle. 2334 */ 2335 client_handle = MAKE_CLIENT_HANDLE(CS_GET_SOCKET_NUMBER(socket_num), 2336 CS_GET_FUNCTION_NUMBER(socket_num), 2337 next_minor); 2338 2339 /* 2340 * If this client handle exists, then we have an internal 2341 * error; this should never happen, BTW. This is really 2342 * a double-check on the cs_create_next_client_minor 2343 * function, which also calls cs_find_client. 2344 */ 2345 if (cs_find_client(client_handle, NULL)) { 2346 cmn_err(CE_CONT, 2347 "cs_create_client_handle: duplicate client handle 0x%x\n", 2348 (int)client_handle); 2349 return (0); 2350 } 2351 2352 /* 2353 * If we don't have any clients on this socket yet, create 2354 * a new client and hang it on the socket client list. 2355 */ 2356 if (!sp->client_list) { 2357 sp->client_list = cclp; 2358 clp = sp->client_list; 2359 } else { 2360 /* 2361 * There are other clients on this socket, so look for 2362 * the last client and add our new client after it. 2363 */ 2364 clp = sp->client_list; 2365 while (clp->next) { 2366 clp = clp->next; 2367 } 2368 2369 clp->next = cclp; 2370 clp->next->prev = clp; 2371 clp = clp->next; 2372 } /* if (!sp->client_list) */ 2373 2374 /* 2375 * Assign the new client handle to this new client structure. 2376 */ 2377 clp->client_handle = client_handle; 2378 2379 /* 2380 * Create the next available client minor number for this socket 2381 * and save it away. 2382 */ 2383 sp->next_cl_minor = 2384 cs_create_next_client_minor(socket_num, sp->next_cl_minor); 2385 2386 return (client_handle); 2387 } 2388 2389 /* 2390 * cs_clear_superclient_lock - clears the global "super-client" lock 2391 * 2392 * Note: this function uses the cs_globals.global_lock so observe proper 2393 * nexting of locks!! 2394 */ 2395 static void 2396 cs_clear_superclient_lock(int super_client) 2397 { 2398 2399 /* 2400 * If this was a "super-client" registering then we need 2401 * to clear the GLOBAL_SUPER_CLIENT_REGISTERED flag 2402 * so that other "super-clients" can register. 2403 */ 2404 if (super_client == CLIENT_SUPER_CLIENT) { 2405 mutex_enter(&cs_globals.global_lock); 2406 cs_globals.flags &= ~GLOBAL_SUPER_CLIENT_REGISTERED; 2407 mutex_exit(&cs_globals.global_lock); 2408 } 2409 } 2410 2411 /* 2412 * ==== event handling section ==== 2413 */ 2414 2415 /* 2416 * cs_event - CS event hi-priority callback handler 2417 * 2418 * This function gets called by SS and is passed the event type in 2419 * the "event" argument, and the socket number in the "sn" 2420 * argument. The "sn" argument is a valid logical socket 2421 * number for all events except the PCE_SS_READY event. 2422 * 2423 * The PCE_SS_INIT_STATE, PCE_ADD_SOCKET and PCE_DROP_SOCKET events 2424 * are never called at high priority. These events return 2425 * the following return codes: 2426 * 2427 * CS_SUCCESS - operation sucessful 2428 * CS_BAD_SOCKET - unable to complete operation 2429 * CS_UNSUPPORTED_FUNCTION - bad subfunction of 2430 * PCE_SS_INIT_STATE 2431 * 2432 * The caller MUST look at these return codes! 2433 * 2434 * This function is called at high-priority interrupt time for standard 2435 * Card Services events, and the only standard Card Services 2436 * event that it handles directly is the CS_EVENT_CARD_REMOVAL 2437 * event, which gets shuttled right into the client's event 2438 * handler. All other events are just queued up and the socket 2439 * event thread is woken up via the soft interrupt handler. 2440 * Note that CS_EVENT_CARD_INSERTION events are not set in the clients' 2441 * event field, since the CS card insertion/card ready processing 2442 * code is responsible for setting this event in a client's 2443 * event field. 2444 * 2445 */ 2446 /*ARGSUSED*/ 2447 uint32_t 2448 cs_event(event_t event, uint32_t sn, uint32_t arg) 2449 { 2450 client_t *client; 2451 cs_socket_t *sp; 2452 client_types_t *ct; 2453 uint32_t ret = CS_SUCCESS; 2454 2455 /* 2456 * Handle special SS<->CS events 2457 */ 2458 switch (event) { 2459 case PCE_SS_INIT_STATE: 2460 mutex_enter(&cs_globals.global_lock); 2461 switch (sn) { 2462 case PCE_SS_STATE_INIT: 2463 if ((ret = cs_ss_init()) == CS_SUCCESS) 2464 cs_globals.init_state |= GLOBAL_INIT_STATE_SS_READY; 2465 break; 2466 case PCE_SS_STATE_DEINIT: 2467 cs_globals.init_state &= ~GLOBAL_INIT_STATE_SS_READY; 2468 break; 2469 default: 2470 ret = CS_UNSUPPORTED_FUNCTION; 2471 cmn_err(CE_CONT, "cs_event: PCE_SS_INIT_STATE invalid " 2472 "directive: 0x%x\n", sn); 2473 break; 2474 } /* switch (sn) */ 2475 mutex_exit(&cs_globals.global_lock); 2476 return (ret); 2477 case PCE_ADD_SOCKET: 2478 return (cs_add_socket(sn)); 2479 case PCE_DROP_SOCKET: 2480 return (cs_drop_socket(sn)); 2481 } /* switch (event) */ 2482 2483 if ((sp = cs_get_sp(sn)) == NULL) 2484 return (CS_BAD_SOCKET); 2485 2486 /* 2487 * Check to see if CS wants to unload - we do this since it's possible 2488 * to disable certain sockets. Do NOT acquire any locks yet. 2489 */ 2490 if (sp->flags & SOCKET_UNLOAD_MODULE) { 2491 if (event == PCE_CARD_INSERT) 2492 cmn_err(CE_CONT, "PCMCIA: socket %d disabled - please " 2493 "remove card\n", sn); 2494 return (CS_SUCCESS); 2495 } 2496 2497 mutex_enter(&sp->lock); 2498 2499 #ifdef CS_DEBUG 2500 if (cs_debug > 1) { 2501 event2text_t event2text; 2502 2503 event2text.event = event; 2504 (void) cs_event2text(&event2text, 0); 2505 cmn_err(CE_CONT, "cs_event: event=%s (x%x), socket=0x%x\n", 2506 event2text.text, (int)event, (int)sn); 2507 } 2508 #endif 2509 2510 /* 2511 * Convert SS events to CS events; handle the PRR if necessary. 2512 */ 2513 sp->events |= ss_to_cs_events(sp, event); 2514 2515 /* 2516 * We want to maintain the required event dispatching order as 2517 * specified in the PCMCIA spec, so we cycle through all 2518 * clients on this socket to make sure that they are 2519 * notified in the correct order of any high-priority 2520 * events. 2521 */ 2522 ct = &client_types[0]; 2523 while (ct) { 2524 /* 2525 * Point to the head of the client list for this socket, and go 2526 * through each client to set up the client events as well as 2527 * call the client's event handler directly if we have a high 2528 * priority event that we need to tell the client about. 2529 */ 2530 client = sp->client_list; 2531 2532 if (ct->order & CLIENT_EVENTS_LIFO) { 2533 client_t *clp = NULL; 2534 2535 while (client) { 2536 clp = client; 2537 client = client->next; 2538 } 2539 client = clp; 2540 } 2541 2542 while (client) { 2543 client->events |= ((sp->events & ~CS_EVENT_CARD_INSERTION) & 2544 (client->event_mask | client->global_mask)); 2545 if (client->flags & ct->type) { 2546 #ifdef CS_DEBUG 2547 if (cs_debug > 1) { 2548 cmn_err(CE_CONT, "cs_event: socket %d client [%s] " 2549 "events 0x%x flags 0x%x\n", 2550 sn, client->driver_name, 2551 (int)client->events, 2552 (int)client->flags); 2553 } 2554 #endif 2555 2556 /* 2557 * Handle the suspend and card removal events 2558 * specially here so that the client can receive 2559 * these events at high-priority. 2560 */ 2561 if (client->events & CS_EVENT_PM_SUSPEND) { 2562 if (client->flags & CLIENT_CARD_INSERTED) { 2563 CLIENT_EVENT_CALLBACK(client, CS_EVENT_PM_SUSPEND, 2564 CS_EVENT_PRI_HIGH); 2565 } /* if (CLIENT_CARD_INSERTED) */ 2566 client->events &= ~CS_EVENT_PM_SUSPEND; 2567 } /* if (CS_EVENT_PM_SUSPEND) */ 2568 2569 if (client->events & CS_EVENT_CARD_REMOVAL) { 2570 if (client->flags & CLIENT_CARD_INSERTED) { 2571 client->flags &= ~(CLIENT_CARD_INSERTED | 2572 CLIENT_SENT_INSERTION); 2573 CLIENT_EVENT_CALLBACK(client, 2574 CS_EVENT_CARD_REMOVAL, 2575 CS_EVENT_PRI_HIGH); 2576 /* 2577 * Check to see if the client wants low priority 2578 * removal events as well. 2579 */ 2580 if ((client->event_mask | client->global_mask) & 2581 CS_EVENT_CARD_REMOVAL_LOWP) { 2582 client->events |= CS_EVENT_CARD_REMOVAL_LOWP; 2583 } 2584 } /* if (CLIENT_CARD_INSERTED) */ 2585 client->events &= ~CS_EVENT_CARD_REMOVAL; 2586 } /* if (CS_EVENT_CARD_REMOVAL) */ 2587 2588 } /* if (ct->type) */ 2589 if (ct->order & CLIENT_EVENTS_LIFO) { 2590 client = client->prev; 2591 } else { 2592 client = client->next; 2593 } 2594 } /* while (client) */ 2595 2596 ct = ct->next; 2597 } /* while (ct) */ 2598 2599 /* 2600 * Set the SOCKET_NEEDS_THREAD flag so that the soft interrupt 2601 * handler will wakeup this socket's event thread. 2602 */ 2603 if (sp->events) 2604 sp->flags |= SOCKET_NEEDS_THREAD; 2605 2606 /* 2607 * Fire off a soft interrupt that will cause the socket thread 2608 * to be woken up and any remaining events to be sent to 2609 * the clients on this socket. 2610 */ 2611 if ((sp->init_state & SOCKET_INIT_STATE_SOFTINTR) && 2612 !(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) 2613 ddi_trigger_softintr(sp->softint_id); 2614 2615 mutex_exit(&sp->lock); 2616 2617 return (CS_SUCCESS); 2618 } 2619 2620 /* 2621 * cs_card_insertion - handle card insertion and card ready events 2622 * 2623 * We read the CIS, if present, and store it away, then tell SS that 2624 * we have read the CIS and it's ready to be parsed. Since card 2625 * insertion and card ready events are pretty closely intertwined, 2626 * we handle both here. For card ready events that are not the 2627 * result of a card insertion event, we expect that the caller has 2628 * already done the appropriate processing and that we will not be 2629 * called unless we received a card ready event right after a card 2630 * insertion event, i.e. that the SOCKET_WAIT_FOR_READY flag in 2631 * sp->thread_state was set or if we get a CARD_READY event right 2632 * after a CARD_INSERTION event. 2633 * 2634 * calling: sp - pointer to socket structure 2635 * event - event to handle, one of: 2636 * CS_EVENT_CARD_INSERTION 2637 * CS_EVENT_CARD_READY 2638 * CS_EVENT_SS_UPDATED 2639 */ 2640 static int 2641 cs_card_insertion(cs_socket_t *sp, event_t event) 2642 { 2643 int ret; 2644 2645 /* 2646 * Since we're only called while waiting for the card insertion 2647 * and card ready sequence to occur, we may have a pending 2648 * card ready timer that hasn't gone off yet if we got a 2649 * real card ready event. 2650 */ 2651 UNTIMEOUT(sp->rdybsy_tmo_id); 2652 2653 #ifdef CS_DEBUG 2654 if (cs_debug > 1) { 2655 cmn_err(CE_CONT, "cs_card_insertion: event=0x%x, socket=0x%x\n", 2656 (int)event, sp->socket_num); 2657 } 2658 #endif 2659 2660 /* 2661 * Handle card insertion processing 2662 */ 2663 if (event & CS_EVENT_CARD_INSERTION) { 2664 set_socket_t set_socket; 2665 get_ss_status_t gs; 2666 2667 /* 2668 * Check to be sure that we have a valid CIS window 2669 */ 2670 if (!SOCKET_HAS_CIS_WINDOW(sp)) { 2671 cmn_err(CE_CONT, 2672 "cs_card_insertion: socket %d has no " 2673 "CIS window\n", 2674 sp->socket_num); 2675 return (CS_GENERAL_FAILURE); 2676 } 2677 2678 /* 2679 * Apply power to the socket, enable card detect and card ready 2680 * events, then reset the socket. 2681 */ 2682 mutex_enter(&sp->lock); 2683 sp->event_mask = (CS_EVENT_CARD_REMOVAL | 2684 CS_EVENT_CARD_READY); 2685 mutex_exit(&sp->lock); 2686 set_socket.socket = sp->socket_num; 2687 set_socket.SCIntMask = (SBM_CD | SBM_RDYBSY); 2688 set_socket.IREQRouting = 0; 2689 set_socket.IFType = IF_MEMORY; 2690 set_socket.CtlInd = 0; /* turn off controls and indicators */ 2691 set_socket.State = (unsigned)~0; /* clear latched state bits */ 2692 2693 (void) cs_convert_powerlevel(sp->socket_num, 50, VCC, 2694 &set_socket.VccLevel); 2695 (void) cs_convert_powerlevel(sp->socket_num, 50, VPP1, 2696 &set_socket.Vpp1Level); 2697 (void) cs_convert_powerlevel(sp->socket_num, 50, VPP2, 2698 &set_socket.Vpp2Level); 2699 2700 if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2701 cmn_err(CE_CONT, 2702 "cs_card_insertion: socket %d SS_SetSocket failure %d\n", 2703 sp->socket_num, ret); 2704 return (ret); 2705 } 2706 2707 /* 2708 * Clear the ready and ready_timeout events since they are now 2709 * bogus since we're about to reset the socket. 2710 * XXX - should these be cleared right after the RESET?? 2711 */ 2712 mutex_enter(&sp->lock); 2713 2714 sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 2715 mutex_exit(&sp->lock); 2716 2717 SocketServices(SS_ResetSocket, sp->socket_num, 2718 RESET_MODE_CARD_ONLY); 2719 2720 /* 2721 * We are required by the PCMCIA spec to wait some number of 2722 * milliseconds after reset before we access the card, so 2723 * we set up a timer here that will wake us up and allow us 2724 * to continue with our card initialization. 2725 */ 2726 mutex_enter(&sp->lock); 2727 sp->thread_state |= SOCKET_RESET_TIMER; 2728 (void) timeout(cs_ready_timeout, sp, 2729 drv_usectohz(cs_reset_timeout_time * 1000)); 2730 cv_wait(&sp->reset_cv, &sp->lock); 2731 sp->thread_state &= ~SOCKET_RESET_TIMER; 2732 mutex_exit(&sp->lock); 2733 2734 #ifdef CS_DEBUG 2735 if (cs_debug > 2) { 2736 cmn_err(CE_CONT, "cs_card_insertion: socket %d out of RESET " 2737 "for %d mS sp->events 0x%x\n", 2738 sp->socket_num, cs_reset_timeout_time, (int)sp->events); 2739 } 2740 #endif 2741 2742 /* 2743 * If we have a pending CS_EVENT_CARD_REMOVAL event it 2744 * means that we likely got CD line bounce on the 2745 * insertion, so terminate this processing. 2746 */ 2747 if (sp->events & CS_EVENT_CARD_REMOVAL) { 2748 #ifdef CS_DEBUG 2749 if (cs_debug > 0) { 2750 cmn_err(CE_CONT, "cs_card_insertion: socket %d " 2751 "CS_EVENT_CARD_REMOVAL event " 2752 "terminating insertion " 2753 "processing\n", 2754 sp->socket_num); 2755 } 2756 #endif 2757 return (CS_SUCCESS); 2758 } /* if (CS_EVENT_CARD_REMOVAL) */ 2759 2760 /* 2761 * If we got a card ready event after the reset, then don't 2762 * bother setting up a card ready timer, since we'll blast 2763 * right on through to the card ready processing. 2764 * Get the current card status to see if it's ready; if it 2765 * is, we probably won't get a card ready event. 2766 */ 2767 gs.socket = sp->socket_num; 2768 gs.CardState = 0; 2769 if ((ret = SocketServices(SS_GetStatus, &gs)) != SUCCESS) { 2770 cmn_err(CE_CONT, 2771 "cs_card_insertion: socket %d SS_GetStatus failure %d\n", 2772 sp->socket_num, ret); 2773 return (ret); 2774 } 2775 2776 mutex_enter(&sp->lock); 2777 if ((sp->events & CS_EVENT_CARD_READY) || 2778 (gs.CardState & SBM_RDYBSY)) { 2779 event = CS_EVENT_CARD_READY; 2780 #ifdef CS_DEBUG 2781 if (cs_debug > 1) { 2782 cmn_err(CE_CONT, "cs_card_insertion: socket %d card " 2783 "READY\n", sp->socket_num); 2784 } 2785 #endif 2786 2787 } else { 2788 #ifdef CS_DEBUG 2789 if (cs_debug > 1) { 2790 cmn_err(CE_CONT, "cs_card_insertion: socket %d setting " 2791 "READY timer\n", sp->socket_num); 2792 } 2793 #endif 2794 2795 sp->rdybsy_tmo_id = timeout(cs_ready_timeout, sp, 2796 READY_TIMEOUT_TIME); 2797 sp->thread_state |= SOCKET_WAIT_FOR_READY; 2798 2799 } /* if (CS_EVENT_CARD_READY) */ 2800 2801 mutex_exit(&sp->lock); 2802 2803 } /* if (CS_EVENT_CARD_INSERTION) */ 2804 2805 /* 2806 * Handle card ready processing. This is only card ready processing 2807 * for card ready events in conjunction with a card insertion. 2808 */ 2809 if (event == CS_EVENT_CARD_READY) { 2810 get_socket_t get_socket; 2811 set_socket_t set_socket; 2812 2813 /* 2814 * The only events that we want to see now are card removal 2815 * events. 2816 */ 2817 mutex_enter(&sp->lock); 2818 sp->event_mask = CS_EVENT_CARD_REMOVAL; 2819 mutex_exit(&sp->lock); 2820 get_socket.socket = sp->socket_num; 2821 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 2822 cmn_err(CE_CONT, 2823 "cs_card_insertion: socket %d SS_GetSocket failed\n", 2824 sp->socket_num); 2825 return (CS_BAD_SOCKET); 2826 } 2827 2828 set_socket.socket = sp->socket_num; 2829 set_socket.SCIntMask = SBM_CD; 2830 set_socket.VccLevel = get_socket.VccLevel; 2831 set_socket.Vpp1Level = get_socket.Vpp1Level; 2832 set_socket.Vpp2Level = get_socket.Vpp2Level; 2833 set_socket.IREQRouting = get_socket.IRQRouting; 2834 set_socket.IFType = get_socket.IFType; 2835 set_socket.CtlInd = get_socket.CtlInd; 2836 /* XXX (is ~0 correct here?) to reset latched values */ 2837 set_socket.State = (unsigned)~0; 2838 2839 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 2840 cmn_err(CE_CONT, 2841 "cs_card_insertion: socket %d SS_SetSocket failed\n", 2842 sp->socket_num); 2843 2844 return (CS_BAD_SOCKET); 2845 } 2846 2847 /* 2848 * Grab the cis_lock mutex to protect the CIS-to-be and 2849 * the CIS window, then fire off the CIS parser to 2850 * create a local copy of the card's CIS. 2851 */ 2852 mutex_enter(&sp->cis_lock); 2853 2854 if ((ret = cs_create_cis(sp)) != CS_SUCCESS) { 2855 mutex_exit(&sp->cis_lock); 2856 return (ret); 2857 } 2858 2859 mutex_exit(&sp->cis_lock); 2860 2861 /* 2862 * If we have a pending CS_EVENT_CARD_REMOVAL event it 2863 * means that we likely got CD line bounce on the 2864 * insertion, so destroy the CIS and terminate this 2865 * processing. We'll get called back to handle the 2866 * insertion again later. 2867 */ 2868 if (sp->events & CS_EVENT_CARD_REMOVAL) { 2869 mutex_enter(&sp->cis_lock); 2870 (void) cs_destroy_cis(sp); 2871 mutex_exit(&sp->cis_lock); 2872 } else { 2873 /* 2874 * Schedule the call to the Socket Services work thread. 2875 */ 2876 mutex_enter(&sp->ss_thread_lock); 2877 sp->ss_thread_state |= SOCKET_THREAD_CSCISInit; 2878 cv_broadcast(&sp->ss_thread_cv); 2879 mutex_exit(&sp->ss_thread_lock); 2880 } /* if (CS_EVENT_CARD_REMOVAL) */ 2881 } /* if (CS_EVENT_CARD_READY) */ 2882 2883 /* 2884 * Socket Services has parsed the CIS and has done any other 2885 * work to get the client driver loaded and attached if 2886 * necessary, so setup the per-client state. 2887 */ 2888 if (event == CS_EVENT_SS_UPDATED) { 2889 client_t *client; 2890 2891 /* 2892 * Now that we and SS are done handling the card insertion 2893 * semantics, go through each client on this socket and set 2894 * the CS_EVENT_CARD_INSERTION event in each client's event 2895 * field. We do this here instead of in cs_event so that 2896 * when a client gets a CS_EVENT_CARD_INSERTION event, the 2897 * card insertion and ready processing has already been done 2898 * and SocketServices has had a chance to create a dip for 2899 * the card in this socket. 2900 */ 2901 mutex_enter(&sp->lock); 2902 client = sp->client_list; 2903 while (client) { 2904 client->events |= (CS_EVENT_CARD_INSERTION & 2905 (client->event_mask | client->global_mask)); 2906 client = client->next; 2907 } /* while (client) */ 2908 2909 mutex_exit(&sp->lock); 2910 2911 } /* if (CS_EVENT_SS_UPDATED) */ 2912 2913 return (CS_SUCCESS); 2914 } 2915 2916 /* 2917 * cs_card_removal - handle card removal events 2918 * 2919 * Destroy the CIS. 2920 * 2921 * calling: sp - pointer to socket structure 2922 * 2923 */ 2924 static int 2925 cs_card_removal(cs_socket_t *sp) 2926 { 2927 set_socket_t set_socket; 2928 int ret; 2929 2930 #ifdef CS_DEBUG 2931 if (cs_debug > 0) { 2932 cmn_err(CE_CONT, "cs_card_removal: socket %d\n", sp->socket_num); 2933 } 2934 #endif 2935 2936 /* 2937 * Remove any pending card ready timer 2938 */ 2939 UNTIMEOUT(sp->rdybsy_tmo_id); 2940 2941 /* 2942 * Clear various flags so that everyone else knows that there's 2943 * nothing on this socket anymore. Note that we clear the 2944 * SOCKET_CARD_INSERTED and SOCKET_IS_IO flags in the 2945 * ss_to_cs_events event mapping function. 2946 */ 2947 mutex_enter(&sp->lock); 2948 sp->thread_state &= ~(SOCKET_WAIT_FOR_READY | SOCKET_RESET_TIMER); 2949 2950 /* 2951 * Turn off socket power and set the socket back to memory mode. 2952 * Disable all socket events except for CARD_INSERTION events. 2953 */ 2954 sp->event_mask = CS_EVENT_CARD_INSERTION; 2955 mutex_exit(&sp->lock); 2956 set_socket.socket = sp->socket_num; 2957 set_socket.SCIntMask = SBM_CD; 2958 set_socket.IREQRouting = 0; 2959 set_socket.IFType = IF_MEMORY; 2960 set_socket.CtlInd = 0; /* turn off controls and indicators */ 2961 set_socket.State = (unsigned)~0; /* clear latched state bits */ 2962 2963 (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 2964 &set_socket.VccLevel); 2965 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 2966 &set_socket.Vpp1Level); 2967 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 2968 &set_socket.Vpp2Level); 2969 2970 if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2971 cmn_err(CE_CONT, 2972 "cs_card_removal: socket %d SS_SetSocket failure %d\n", 2973 sp->socket_num, ret); 2974 return (ret); 2975 } 2976 2977 #ifdef CS_DEBUG 2978 if (cs_debug > 2) { 2979 cmn_err(CE_CONT, "cs_card_removal: socket %d " 2980 "calling cs_destroy_cis\n", 2981 sp->socket_num); 2982 } 2983 #endif 2984 2985 /* 2986 * Destroy the CIS and tell Socket Services that we're done 2987 * handling the card removal event. 2988 */ 2989 mutex_enter(&sp->cis_lock); 2990 (void) cs_destroy_cis(sp); 2991 mutex_exit(&sp->cis_lock); 2992 2993 #ifdef CS_DEBUG 2994 if (cs_debug > 2) { 2995 cmn_err(CE_CONT, "cs_card_removal: calling CSCardRemoved\n"); 2996 } 2997 #endif 2998 2999 SocketServices(CSCardRemoved, sp->socket_num); 3000 3001 return (CS_SUCCESS); 3002 } 3003 3004 /* 3005 * ss_to_cs_events - convert Socket Services events to Card Services event 3006 * masks; this function will not read the PRR if the 3007 * socket is in IO mode; this happens in cs_event_thread 3008 * 3009 * This function returns a bit mask of events. 3010 * 3011 * Note that we do some simple hysterious on card insertion and card removal 3012 * events to prevent spurious insertion and removal events from being 3013 * propogated down the chain. 3014 */ 3015 static event_t 3016 ss_to_cs_events(cs_socket_t *sp, event_t event) 3017 { 3018 event_t revent = 0; 3019 3020 switch (event) { 3021 case PCE_CARD_STATUS_CHANGE: 3022 revent |= CS_EVENT_STATUS_CHANGE; 3023 break; 3024 case PCE_CARD_REMOVAL: 3025 if (sp->flags & SOCKET_CARD_INSERTED) { 3026 sp->flags &= ~(SOCKET_CARD_INSERTED | SOCKET_IS_IO); 3027 revent |= CS_EVENT_CARD_REMOVAL; 3028 /* 3029 * If we're processing a removal event, it makes 3030 * no sense to keep any insertion or ready events, 3031 * so nuke them here. This will not clear any 3032 * insertion events in the per-client event field. 3033 */ 3034 sp->events &= ~(CS_EVENT_CARD_INSERTION | 3035 CS_EVENT_CARD_READY | 3036 CS_EVENT_READY_TIMEOUT); 3037 3038 /* 3039 * We also don't need to wait for READY anymore since 3040 * it probably won't show up, or if it does, it will 3041 * be a bogus READY event as the card is sliding out 3042 * of the socket. Since we never do a cv_wait on the 3043 * card ready timer, it's OK for that timer to either 3044 * never go off (via an UNTIMEOUT in cs_card_removal) 3045 * or to go off but not do a cv_broadcast (since the 3046 * SOCKET_WAIT_FOR_READY flag is cleared here). 3047 */ 3048 sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3049 3050 } 3051 break; 3052 case PCE_CARD_INSERT: 3053 if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3054 sp->flags |= SOCKET_CARD_INSERTED; 3055 revent |= CS_EVENT_CARD_INSERTION; 3056 } 3057 break; 3058 case PCE_CARD_READY: 3059 if (sp->flags & SOCKET_CARD_INSERTED) 3060 revent |= CS_EVENT_CARD_READY; 3061 break; 3062 case PCE_CARD_BATTERY_WARN: 3063 if (sp->flags & SOCKET_CARD_INSERTED) 3064 revent |= CS_EVENT_BATTERY_LOW; 3065 break; 3066 case PCE_CARD_BATTERY_DEAD: 3067 if (sp->flags & SOCKET_CARD_INSERTED) 3068 revent |= CS_EVENT_BATTERY_DEAD; 3069 break; 3070 case PCE_CARD_WRITE_PROTECT: 3071 if (sp->flags & SOCKET_CARD_INSERTED) 3072 revent |= CS_EVENT_WRITE_PROTECT; 3073 break; 3074 case PCE_PM_RESUME: 3075 revent |= CS_EVENT_PM_RESUME; 3076 break; 3077 case PCE_PM_SUSPEND: 3078 revent |= CS_EVENT_PM_SUSPEND; 3079 break; 3080 default: 3081 cmn_err(CE_CONT, "ss_to_cs_events: unknown event 0x%x\n", 3082 (int)event); 3083 break; 3084 } /* switch(event) */ 3085 3086 return (revent); 3087 } 3088 3089 /* 3090 * cs_ready_timeout - general purpose READY/BUSY and RESET timer 3091 * 3092 * Note that we really only expect one of the two events to be asserted when 3093 * we are called. XXX - Perhaps this might be a problem later on?? 3094 * 3095 * There is also the problem of cv_broadcast dropping the interrupt 3096 * priority, even though we have our high-priority mutex held. If 3097 * we hold our high-priority mutex (sp->lock) over a cv_broadcast, and 3098 * we get a high-priority interrupt during this time, the system will 3099 * deadlock or panic. Thanks to Andy Banta for finding this out in 3100 * the SPC/S (stc.c) driver. 3101 * 3102 * This callback routine can not grab the sp->client_lock mutex or deadlock 3103 * will result. 3104 */ 3105 void 3106 cs_ready_timeout(void *arg) 3107 { 3108 cs_socket_t *sp = arg; 3109 kcondvar_t *cvp = NULL; 3110 3111 mutex_enter(&sp->lock); 3112 3113 if (sp->thread_state & SOCKET_RESET_TIMER) { 3114 #ifdef CS_DEBUG 3115 if (cs_debug > 1) { 3116 cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_RESET_TIMER socket %d\n", 3117 sp->socket_num); 3118 } 3119 #endif 3120 3121 cvp = &sp->reset_cv; 3122 } 3123 3124 if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3125 sp->events |= CS_EVENT_READY_TIMEOUT; 3126 cvp = &sp->thread_cv; 3127 3128 #ifdef CS_DEBUG 3129 if (cs_debug > 1) { 3130 cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_WAIT_FOR_READY " 3131 "socket %d\n", sp->socket_num); 3132 } 3133 #endif 3134 3135 } 3136 3137 mutex_exit(&sp->lock); 3138 3139 if (cvp) 3140 cv_broadcast(cvp); 3141 } 3142 3143 /* 3144 * cs_event_softintr_timeout - wrapper function to call cs_socket_event_softintr 3145 */ 3146 /* ARGSUSED */ 3147 void 3148 cs_event_softintr_timeout(void *arg) 3149 { 3150 3151 /* 3152 * If we're trying to unload this module, then don't do 3153 * anything but exit. 3154 * We acquire the cs_globals.global_lock mutex here so that 3155 * we can correctly synchronize with cs_deinit when it 3156 * is telling us to shut down. XXX - is this bogus?? 3157 */ 3158 mutex_enter(&cs_globals.global_lock); 3159 if (!(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) { 3160 mutex_exit(&cs_globals.global_lock); 3161 (void) cs_socket_event_softintr(NULL); 3162 cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 3163 NULL, SOFTINT_TIMEOUT_TIME); 3164 } else { 3165 mutex_exit(&cs_globals.global_lock); 3166 } 3167 } 3168 3169 /* 3170 * cs_socket_event_softintr - This function just does a cv_broadcast on behalf 3171 * of the high-priority interrupt handler. 3172 * 3173 * Note: There is no calling argument. 3174 */ 3175 /*ARGSUSED*/ 3176 uint32_t 3177 cs_socket_event_softintr(caddr_t notused) 3178 { 3179 cs_socket_t *sp; 3180 uint32_t sn; 3181 int ret = DDI_INTR_UNCLAIMED; 3182 3183 /* 3184 * If the module is on it's way out, then don't bother 3185 * to do anything else except return. 3186 */ 3187 mutex_enter(&cs_globals.global_lock); 3188 if ((cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING) || 3189 (cs_globals.init_state & GLOBAL_IN_SOFTINTR)) { 3190 mutex_exit(&cs_globals.global_lock); 3191 3192 /* 3193 * Note that we return DDI_INTR_UNCLAIMED here 3194 * since we don't want to be constantly 3195 * called back. 3196 */ 3197 return (ret); 3198 } else { 3199 cs_globals.init_state |= GLOBAL_IN_SOFTINTR; 3200 mutex_exit(&cs_globals.global_lock); 3201 } 3202 3203 /* 3204 * Go through each socket and dispatch the appropriate events. 3205 * We have to funnel everything through this one routine because 3206 * we can't do a cv_broadcast from a high level interrupt handler 3207 * and we also can't have more than one soft interrupt handler 3208 * on a single dip and using the same handler address. 3209 */ 3210 for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3211 if ((sp = cs_get_sp(sn)) != NULL) { 3212 if (sp->init_state & SOCKET_INIT_STATE_READY) { 3213 /* 3214 * If we're being asked to unload CS, then don't bother 3215 * waking up the socket event thread handler. 3216 */ 3217 if (!(sp->flags & SOCKET_UNLOAD_MODULE) && 3218 (sp->flags & SOCKET_NEEDS_THREAD)) { 3219 ret = DDI_INTR_CLAIMED; 3220 mutex_enter(&sp->client_lock); 3221 cv_broadcast(&sp->thread_cv); 3222 mutex_exit(&sp->client_lock); 3223 } /* if (SOCKET_NEEDS_THREAD) */ 3224 } /* if (SOCKET_INIT_STATE_READY) */ 3225 } /* cs_get_sp */ 3226 } /* for (sn) */ 3227 3228 mutex_enter(&cs_globals.global_lock); 3229 cs_globals.init_state &= ~GLOBAL_IN_SOFTINTR; 3230 mutex_exit(&cs_globals.global_lock); 3231 3232 return (ret); 3233 } 3234 3235 /* 3236 * cs_event_thread - This is the per-socket event thread. 3237 */ 3238 static void 3239 cs_event_thread(uint32_t sn) 3240 { 3241 cs_socket_t *sp; 3242 client_t *client; 3243 client_types_t *ct; 3244 3245 if ((sp = cs_get_sp(sn)) == NULL) 3246 return; 3247 3248 #ifdef CS_DEBUG 3249 if (cs_debug > 1) { 3250 cmn_err(CE_CONT, "cs_event_thread: socket %d thread started\n", 3251 sp->socket_num); 3252 } 3253 #endif 3254 3255 CALLB_CPR_INIT(&sp->cprinfo_cs, &sp->client_lock, 3256 callb_generic_cpr, "cs_event_thread"); 3257 3258 mutex_enter(&sp->client_lock); 3259 3260 for (;;) { 3261 3262 CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_cs); 3263 cv_wait(&sp->thread_cv, &sp->client_lock); 3264 CALLB_CPR_SAFE_END(&sp->cprinfo_cs, &sp->client_lock); 3265 3266 mutex_enter(&sp->lock); 3267 sp->flags &= ~SOCKET_NEEDS_THREAD; 3268 mutex_exit(&sp->lock); 3269 3270 /* 3271 * Check to see if there are any special thread operations that 3272 * we are being asked to perform. 3273 */ 3274 if (sp->thread_state & SOCKET_THREAD_EXIT) { 3275 #ifdef CS_DEBUG 3276 if (cs_debug > 1) { 3277 cmn_err(CE_CONT, "cs_event_thread: socket %d " 3278 "SOCKET_THREAD_EXIT\n", 3279 sp->socket_num); 3280 } 3281 #endif 3282 CALLB_CPR_EXIT(&sp->cprinfo_cs); 3283 cv_broadcast(&sp->caller_cv); /* wakes up cs_deinit */ 3284 mutex_exit(&sp->client_lock); 3285 return; 3286 } /* if (SOCKET_THREAD_EXIT) */ 3287 3288 #ifdef CS_DEBUG 3289 if (cs_debug > 1) { 3290 cmn_err(CE_CONT, "cs_event_thread: socket %d sp->events 0x%x\n", 3291 sp->socket_num, 3292 (int)sp->events); 3293 } 3294 #endif 3295 3296 /* 3297 * Handle CS_EVENT_CARD_INSERTION events 3298 */ 3299 if (sp->events & CS_EVENT_CARD_INSERTION) { 3300 mutex_enter(&sp->lock); 3301 sp->events &= ~CS_EVENT_CARD_INSERTION; 3302 mutex_exit(&sp->lock); 3303 3304 /* 3305 * If we have a pending CS_EVENT_CARD_REMOVAL event it 3306 * means that we likely got CD line bounce on the 3307 * insertion, so terminate this processing. 3308 */ 3309 if ((sp->events & CS_EVENT_CARD_REMOVAL) == 0) { 3310 (void) cs_card_insertion(sp, CS_EVENT_CARD_INSERTION); 3311 } 3312 #ifdef CS_DEBUG 3313 else if (cs_debug > 0) { 3314 cmn_err(CE_CONT, "cs_event_thread: socket %d " 3315 "CS_EVENT_CARD_REMOVAL event " 3316 "terminating " 3317 "CS_EVENT_CARD_INSERTION " 3318 "processing\n", sp->socket_num); 3319 } 3320 #endif 3321 } /* if (CS_EVENT_CARD_INSERTION) */ 3322 3323 /* 3324 * Handle CS_EVENT_CARD_READY and CS_EVENT_READY_TIMEOUT events 3325 */ 3326 if (sp->events & (CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT)) { 3327 mutex_enter(&sp->lock); 3328 sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 3329 mutex_exit(&sp->lock); 3330 if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3331 mutex_enter(&sp->lock); 3332 sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3333 mutex_exit(&sp->lock); 3334 (void) cs_card_insertion(sp, CS_EVENT_CARD_READY); 3335 } /* if (SOCKET_WAIT_FOR_READY) */ 3336 } /* if (CS_EVENT_CARD_READY) */ 3337 3338 /* 3339 * Handle CS_EVENT_SS_UPDATED events 3340 */ 3341 if (sp->events & CS_EVENT_SS_UPDATED) { 3342 mutex_enter(&sp->lock); 3343 sp->events &= ~CS_EVENT_SS_UPDATED; 3344 mutex_exit(&sp->lock); 3345 (void) cs_card_insertion(sp, CS_EVENT_SS_UPDATED); 3346 } /* if (CS_EVENT_SS_UPDATED) */ 3347 3348 /* 3349 * Handle CS_EVENT_STATUS_CHANGE events 3350 */ 3351 if (sp->events & CS_EVENT_STATUS_CHANGE) { 3352 event_t revent; 3353 3354 mutex_enter(&sp->cis_lock); 3355 mutex_enter(&sp->lock); 3356 sp->events &= ~CS_EVENT_STATUS_CHANGE; 3357 3358 /* 3359 * Go through each client and add any events that we saw to 3360 * the client's event list if the client has that event 3361 * enabled in their event mask. 3362 * Remove any events that may be pending for this client if 3363 * the client's event mask says that the client doesn't 3364 * want to see those events anymore. This handles the 3365 * case where the client had an event enabled in it's 3366 * event mask when the event came in but between that 3367 * time and the time we're called here the client 3368 * disabled that event. 3369 */ 3370 client = sp->client_list; 3371 3372 while (client) { 3373 /* 3374 * Read the PRR (if it exists) and check for any events. 3375 * The PRR will only be read if the socket is in IO 3376 * mode, if there is a card in the socket, and if there 3377 * is a PRR. 3378 * We don't have to clear revent before we call the 3379 * cs_read_event_status function since it will 3380 * clear it before adding any current events. 3381 */ 3382 if (client->flags & CLIENT_CARD_INSERTED) { 3383 (void) cs_read_event_status(sp, client, 3384 &revent, NULL, 0); 3385 3386 client->events = ((client->events | revent) & 3387 (client->event_mask | 3388 client->global_mask)); 3389 } /* CLIENT_CARD_INSERTED */ 3390 client = client->next; 3391 } /* while (client) */ 3392 3393 mutex_exit(&sp->lock); 3394 mutex_exit(&sp->cis_lock); 3395 } /* if (CS_EVENT_STATUS_CHANGE) */ 3396 3397 /* 3398 * We want to maintain the required event dispatching order as 3399 * specified in the PCMCIA spec, so we cycle through all 3400 * clients on this socket to make sure that they are 3401 * notified in the correct order. 3402 */ 3403 ct = &client_types[0]; 3404 while (ct) { 3405 /* 3406 * Point to the head of the client list for this socket, and go 3407 * through each client to set up the client events as well 3408 * as call the client's event handler directly if we have 3409 * a high priority event that we need to tell the client 3410 * about. 3411 */ 3412 client = sp->client_list; 3413 3414 if (ct->order & CLIENT_EVENTS_LIFO) { 3415 client_t *clp = NULL; 3416 3417 while (client) { 3418 clp = client; 3419 client = client->next; 3420 } 3421 client = clp; 3422 } 3423 3424 while (client) { 3425 if (client->flags & ct->type) { 3426 uint32_t bit = 0; 3427 event_t event; 3428 3429 while (client->events) { 3430 3431 switch (event = CS_BIT_GET(client->events, bit)) { 3432 /* 3433 * Clients always receive registration complete 3434 * events, even if there is no card of 3435 * their type currently in the socket. 3436 */ 3437 case CS_EVENT_REGISTRATION_COMPLETE: 3438 CLIENT_EVENT_CALLBACK(client, event, 3439 CS_EVENT_PRI_LOW); 3440 break; 3441 /* 3442 * The client only gets a card insertion event 3443 * if there is currently a card in the 3444 * socket that the client can control. 3445 * The nexus determines this. We also 3446 * prevent the client from receiving 3447 * multiple CS_EVENT_CARD_INSERTION 3448 * events without receiving intervening 3449 * CS_EVENT_CARD_REMOVAL events. 3450 */ 3451 case CS_EVENT_CARD_INSERTION: 3452 if (cs_card_for_client(client)) { 3453 int send_insertion; 3454 3455 mutex_enter(&sp->lock); 3456 send_insertion = client->flags; 3457 client->flags |= 3458 (CLIENT_CARD_INSERTED | 3459 CLIENT_SENT_INSERTION); 3460 mutex_exit(&sp->lock); 3461 if (!(send_insertion & 3462 CLIENT_SENT_INSERTION)) { 3463 CLIENT_EVENT_CALLBACK(client, 3464 event, CS_EVENT_PRI_LOW); 3465 } /* if (!CLIENT_SENT_INSERTION) */ 3466 } 3467 break; 3468 /* 3469 * The CS_EVENT_CARD_REMOVAL_LOWP is a low 3470 * priority CS_EVENT_CARD_REMOVAL event. 3471 */ 3472 case CS_EVENT_CARD_REMOVAL_LOWP: 3473 mutex_enter(&sp->lock); 3474 client->flags &= ~CLIENT_SENT_INSERTION; 3475 mutex_exit(&sp->lock); 3476 CLIENT_EVENT_CALLBACK(client, 3477 CS_EVENT_CARD_REMOVAL, 3478 CS_EVENT_PRI_LOW); 3479 break; 3480 /* 3481 * The hardware card removal events are handed 3482 * to the client in cs_event at high 3483 * priority interrupt time; this card 3484 * removal event is a software-generated 3485 * event. 3486 */ 3487 case CS_EVENT_CARD_REMOVAL: 3488 if (client->flags & CLIENT_CARD_INSERTED) { 3489 mutex_enter(&sp->lock); 3490 client->flags &= 3491 ~(CLIENT_CARD_INSERTED | 3492 CLIENT_SENT_INSERTION); 3493 mutex_exit(&sp->lock); 3494 CLIENT_EVENT_CALLBACK(client, event, 3495 CS_EVENT_PRI_LOW); 3496 } 3497 break; 3498 /* 3499 * Write protect events require the info field 3500 * of the client's event callback args to 3501 * be zero if the card is not write 3502 * protected and one if it is. 3503 */ 3504 case CS_EVENT_WRITE_PROTECT: 3505 if (client->flags & CLIENT_CARD_INSERTED) { 3506 get_ss_status_t gs; 3507 3508 mutex_enter(&sp->cis_lock); 3509 mutex_enter(&sp->lock); 3510 (void) cs_read_event_status(sp, client, 3511 NULL, 3512 &gs, 0); 3513 if (gs.CardState & SBM_WP) { 3514 client->event_callback_args.info = 3515 (void *) 3516 CS_EVENT_WRITE_PROTECT_WPON; 3517 } else { 3518 client->event_callback_args.info = 3519 (void *) 3520 CS_EVENT_WRITE_PROTECT_WPOFF; 3521 } 3522 mutex_exit(&sp->lock); 3523 mutex_exit(&sp->cis_lock); 3524 CLIENT_EVENT_CALLBACK(client, event, 3525 CS_EVENT_PRI_LOW); 3526 } /* CLIENT_CARD_INSERTED */ 3527 break; 3528 case CS_EVENT_CLIENT_INFO: 3529 CLIENT_EVENT_CALLBACK(client, event, 3530 CS_EVENT_PRI_LOW); 3531 break; 3532 case 0: 3533 break; 3534 default: 3535 if (client->flags & CLIENT_CARD_INSERTED) { 3536 CLIENT_EVENT_CALLBACK(client, event, 3537 CS_EVENT_PRI_LOW); 3538 } 3539 break; 3540 } /* switch */ 3541 mutex_enter(&sp->lock); 3542 CS_BIT_CLEAR(client->events, bit); 3543 mutex_exit(&sp->lock); 3544 bit++; 3545 } /* while (client->events) */ 3546 } /* if (ct->type) */ 3547 if (ct->order & CLIENT_EVENTS_LIFO) { 3548 client = client->prev; 3549 } else { 3550 client = client->next; 3551 } 3552 } /* while (client) */ 3553 3554 ct = ct->next; 3555 } /* while (ct) */ 3556 3557 /* 3558 * Handle CS_EVENT_CARD_REMOVAL events 3559 */ 3560 if (sp->events & CS_EVENT_CARD_REMOVAL) { 3561 mutex_enter(&sp->lock); 3562 sp->events &= ~CS_EVENT_CARD_REMOVAL; 3563 mutex_exit(&sp->lock); 3564 (void) cs_card_removal(sp); 3565 } /* if (CS_EVENT_CARD_REMOVAL) */ 3566 3567 /* 3568 * If someone is waiting for us to complete, signal them now. 3569 */ 3570 if (sp->thread_state & SOCKET_WAIT_SYNC) { 3571 mutex_enter(&sp->lock); 3572 sp->thread_state &= ~SOCKET_WAIT_SYNC; 3573 mutex_exit(&sp->lock); 3574 cv_broadcast(&sp->caller_cv); 3575 } /* SOCKET_WAIT_SYNC */ 3576 3577 } /* for (;;) */ 3578 } 3579 3580 /* 3581 * cs_card_for_client - checks to see if a card that the client can control 3582 * is currently inserted in the socket. Socket Services 3583 * has to tell us if this is the case. 3584 */ 3585 static int 3586 cs_card_for_client(client_t *client) 3587 { 3588 3589 /* 3590 * If the client has set the CS_EVENT_ALL_CLIENTS it means that they 3591 * want to get all events for all clients, irrespective of 3592 * whether or not there is a card in the socket. Such clients 3593 * have to be very careful if they touch the card hardware in 3594 * any way to prevent causing problems for other clients on the 3595 * same socket. This flag will typically only be set by the 3596 * "super-client" or CSI types of clients that wish to get 3597 * information on other clients or cards in the system. 3598 * Note that the CS_EVENT_ALL_CLIENTS must be set in either the 3599 * client's global event mask or client event mask. 3600 * The client must also have registered as a "super-client" or as a 3601 * CSI client for this socket. 3602 */ 3603 if ((client->flags & (CLIENT_SUPER_CLIENT | CLIENT_CSI_CLIENT)) && 3604 ((client->global_mask | client->event_mask) & 3605 CS_EVENT_ALL_CLIENTS)) 3606 return (1); 3607 3608 /* 3609 * Look for the PCM_DEV_ACTIVE property on this client's dip; if 3610 * it's found, it means that this client can control the card 3611 * that is currently in the socket. This is a boolean 3612 * property managed by Socket Services. 3613 */ 3614 if (ddi_getprop(DDI_DEV_T_ANY, client->dip, (DDI_PROP_CANSLEEP | 3615 DDI_PROP_NOTPROM), 3616 PCM_DEV_ACTIVE, NULL)) { 3617 #ifdef CS_DEBUG 3618 if (cs_debug > 1) { 3619 cmn_err(CE_CONT, "cs_card_for_client: client handle 0x%x " 3620 "driver [%s] says %s found\n", 3621 (int)client->client_handle, 3622 client->driver_name, 3623 PCM_DEV_ACTIVE); 3624 } 3625 #endif 3626 return (1); 3627 } 3628 3629 return (0); 3630 } 3631 3632 /* 3633 * cs_ss_thread - This is the Socket Services work thread. We fire off 3634 * any calls to Socket Services here that we want 3635 * to run on a thread that is seperate from the 3636 * per-socket event thread. 3637 */ 3638 static void 3639 cs_ss_thread(uint32_t sn) 3640 { 3641 cs_socket_t *sp; 3642 3643 if ((sp = cs_get_sp(sn)) == NULL) 3644 return; 3645 3646 /* 3647 * Tell CPR that we've started a new thread. 3648 */ 3649 CALLB_CPR_INIT(&sp->cprinfo_ss, &sp->ss_thread_lock, 3650 callb_generic_cpr, "cs_ss_thread"); 3651 3652 mutex_enter(&sp->ss_thread_lock); 3653 3654 for (;;) { 3655 3656 CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_ss); 3657 cv_wait(&sp->ss_thread_cv, &sp->ss_thread_lock); 3658 CALLB_CPR_SAFE_END(&sp->cprinfo_ss, &sp->ss_thread_lock); 3659 3660 /* 3661 * Check to see if there are any special thread operations 3662 * that we are being asked to perform. 3663 */ 3664 if (sp->ss_thread_state & SOCKET_THREAD_EXIT) { 3665 #ifdef CS_DEBUG 3666 if (cs_debug > 1) { 3667 cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3668 "SOCKET_THREAD_EXIT\n", 3669 sp->socket_num); 3670 } 3671 #endif 3672 CALLB_CPR_EXIT(&sp->cprinfo_ss); 3673 cv_broadcast(&sp->ss_caller_cv); /* wake up cs_deinit */ 3674 mutex_exit(&sp->ss_thread_lock); 3675 return; 3676 } /* if (SOCKET_THREAD_EXIT) */ 3677 3678 #ifdef CS_DEBUG 3679 if (cs_debug > 1) { 3680 cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3681 "ss_thread_state = 0x%x\n", 3682 (int)sp->socket_num, 3683 (int)sp->ss_thread_state); 3684 } 3685 #endif 3686 3687 /* 3688 * Call SocketServices(CSCISInit) to have SS parse the 3689 * CIS and load/attach any client drivers necessary. 3690 */ 3691 if (sp->ss_thread_state & SOCKET_THREAD_CSCISInit) { 3692 3693 sp->ss_thread_state &= ~SOCKET_THREAD_CSCISInit; 3694 3695 if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3696 cmn_err(CE_CONT, "cs_ss_thread %d " 3697 "card NOT inserted\n", 3698 sp->socket_num); 3699 } 3700 3701 #ifdef CS_DEBUG 3702 if (cs_debug > 1) { 3703 cmn_err(CE_CONT, "cs_ss_thread: socket %d calling " 3704 "CSCISInit\n", sp->socket_num); 3705 } 3706 #endif 3707 3708 /* 3709 * Tell SS that we have a complete CIS and that it can now 3710 * be parsed. 3711 * Note that in some cases the client driver may block in 3712 * their attach routine, causing this call to block until 3713 * the client completes their attach. 3714 */ 3715 SocketServices(CSCISInit, sp->socket_num); 3716 3717 /* 3718 * Set the CS_EVENT_SS_UPDATED event for this socket so that the 3719 * event thread can continue any card insertion processing 3720 * that it has to do. 3721 */ 3722 mutex_enter(&sp->lock); 3723 sp->events |= CS_EVENT_SS_UPDATED; 3724 mutex_exit(&sp->lock); 3725 3726 /* 3727 * Wake up this socket's event thread so that clients can 3728 * continue any card insertion or attach processing 3729 * that they need to do. 3730 */ 3731 cv_broadcast(&sp->thread_cv); 3732 } /* if ST_CSCISInit */ 3733 3734 } /* for (;;) */ 3735 } 3736 3737 /* 3738 * cs_request_socket_mask - set the client's event mask as well as causes 3739 * any events pending from RegisterClient to 3740 * be scheduled to be sent to the client 3741 */ 3742 static int 3743 cs_request_socket_mask(client_handle_t client_handle, 3744 request_socket_mask_t *se) 3745 { 3746 cs_socket_t *sp; 3747 client_t *client; 3748 int error; 3749 int client_lock_acquired; 3750 3751 /* 3752 * Check to see if this is the Socket Services client handle; if it 3753 * is, we don't do anything except for return success. 3754 */ 3755 if (CLIENT_HANDLE_IS_SS(client_handle)) 3756 return (CS_SUCCESS); 3757 3758 /* 3759 * Get a pointer to this client's socket structure. 3760 */ 3761 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3762 return (CS_BAD_SOCKET); 3763 3764 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3765 3766 /* 3767 * Make sure that this is a valid client handle. 3768 */ 3769 if (!(client = cs_find_client(client_handle, &error))) { 3770 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3771 return (error); 3772 } 3773 3774 mutex_enter(&sp->lock); 3775 3776 /* 3777 * If this client has already done a RequestSocketMask without 3778 * a corresponding ReleaseSocketMask, then return an error. 3779 */ 3780 if (client->flags & REQ_SOCKET_MASK_DONE) { 3781 mutex_exit(&sp->lock); 3782 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3783 return (CS_IN_USE); 3784 } 3785 3786 /* 3787 * Set up the event mask information; we copy this directly from 3788 * the client; since we are the only source of events, any 3789 * bogus bits that the client puts in here won't matter 3790 * because we'll never look at them. 3791 */ 3792 client->event_mask = se->EventMask; 3793 3794 /* 3795 * If RegisterClient left us some events to process, set these 3796 * events up here. 3797 */ 3798 if (client->pending_events) { 3799 client->events |= client->pending_events; 3800 client->pending_events = 0; 3801 #ifdef CS_DEBUG 3802 if (cs_debug > 1) { 3803 cmn_err(CE_CONT, "cs_request_socket_mask: client_handle = 0x%x " 3804 "driver_name = [%s] events = 0x%x\n", 3805 (int)client->client_handle, 3806 client->driver_name, 3807 (int)client->events); 3808 } 3809 #endif 3810 } 3811 3812 client->flags |= REQ_SOCKET_MASK_DONE; 3813 3814 /* 3815 * Merge all the clients' event masks and set the socket 3816 * to generate the appropriate events. 3817 */ 3818 (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3819 3820 mutex_exit(&sp->lock); 3821 3822 /* 3823 * Wakeup the event thread if there are any client events to process. 3824 */ 3825 if (client->events) { 3826 cv_broadcast(&sp->thread_cv); 3827 #ifdef CS_DEBUG 3828 if (cs_debug > 1) { 3829 cmn_err(CE_CONT, "cs_request_socket_mask: did cv_broadcast for " 3830 "client_handle = 0x%x " 3831 "driver_name = [%s] events = 0x%x\n", 3832 (int)client->client_handle, 3833 client->driver_name, 3834 (int)client->events); 3835 } 3836 #endif 3837 3838 } 3839 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3840 3841 return (CS_SUCCESS); 3842 } 3843 3844 /* 3845 * cs_release_socket_mask - clear the client's event mask 3846 * 3847 * Once this function returns, the client is guaranteed 3848 * not to get any more event callbacks. 3849 */ 3850 /*ARGSUSED*/ 3851 static int 3852 cs_release_socket_mask(client_handle_t client_handle, 3853 release_socket_mask_t *rsm) 3854 { 3855 cs_socket_t *sp; 3856 client_t *client; 3857 int error; 3858 int client_lock_acquired; 3859 3860 /* 3861 * Check to see if this is the Socket Services client handle; if it 3862 * is, we don't do anything except for return success. 3863 */ 3864 if (CLIENT_HANDLE_IS_SS(client_handle)) 3865 return (CS_SUCCESS); 3866 3867 /* 3868 * Get a pointer to this client's socket structure. 3869 */ 3870 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3871 return (CS_BAD_SOCKET); 3872 3873 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3874 3875 /* 3876 * Make sure that this is a valid client handle. 3877 */ 3878 if (!(client = cs_find_client(client_handle, &error))) { 3879 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3880 return (error); 3881 } 3882 3883 mutex_enter(&sp->lock); 3884 3885 /* 3886 * If this client has already done a RequestSocketMask without 3887 * a corresponding ReleaseSocketMask, then return an error. 3888 */ 3889 if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3890 mutex_exit(&sp->lock); 3891 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3892 return (CS_BAD_SOCKET); 3893 } 3894 3895 /* 3896 * Clear both the client event mask and the global event mask. 3897 * We clear both since the semantics of this function are 3898 * that once it returns, the client will not be called at 3899 * it's event handler for any events until RequestSocketMask 3900 * is called again. 3901 */ 3902 client->event_mask = 0; 3903 client->global_mask = 0; 3904 client->flags &= ~REQ_SOCKET_MASK_DONE; 3905 3906 /* 3907 * Merge all the clients' event masks and set the socket 3908 * to generate the appropriate events. 3909 */ 3910 (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3911 3912 mutex_exit(&sp->lock); 3913 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3914 3915 return (CS_SUCCESS); 3916 } 3917 3918 /* 3919 * cs_get_event_mask - return the event mask for this client 3920 */ 3921 static int 3922 cs_get_event_mask(client_handle_t client_handle, sockevent_t *se) 3923 { 3924 cs_socket_t *sp; 3925 client_t *client; 3926 int error; 3927 int client_lock_acquired; 3928 3929 /* 3930 * Check to see if this is the Socket Services client handle; if it 3931 * is, we don't do anything except for return success. 3932 */ 3933 if (CLIENT_HANDLE_IS_SS(client_handle)) 3934 return (CS_SUCCESS); 3935 3936 /* 3937 * Get a pointer to this client's socket structure. 3938 */ 3939 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3940 return (CS_BAD_SOCKET); 3941 3942 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3943 3944 /* 3945 * Make sure that this is a valid client handle. 3946 */ 3947 if (!(client = cs_find_client(client_handle, &error))) { 3948 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3949 return (error); 3950 } 3951 3952 mutex_enter(&sp->lock); 3953 3954 #ifdef XXX 3955 /* 3956 * If there's no card in the socket or the card in the socket is not 3957 * for this client, then return an error. 3958 * XXX - how can a client get their event masks if their card 3959 * goes away? 3960 */ 3961 if (!(client->flags & CLIENT_CARD_INSERTED)) { 3962 mutex_exit(&sp->lock); 3963 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3964 return (CS_NO_CARD); 3965 } 3966 #endif 3967 3968 /* 3969 * We are only allowed to get the client event mask if a 3970 * RequestSocketMask has been called previously. We 3971 * are allowed to get the global event mask at any 3972 * time. 3973 * The global event mask is initially set by the client 3974 * in the call to RegisterClient. The client event 3975 * mask is set by the client in calls to SetEventMask 3976 * and RequestSocketMask and gotten in calls to 3977 * GetEventMask. 3978 */ 3979 if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 3980 if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3981 mutex_exit(&sp->lock); 3982 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3983 return (CS_BAD_SOCKET); 3984 } 3985 se->EventMask = client->event_mask; 3986 } else { 3987 se->EventMask = client->global_mask; 3988 } 3989 3990 mutex_exit(&sp->lock); 3991 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3992 3993 return (CS_SUCCESS); 3994 } 3995 3996 /* 3997 * cs_set_event_mask - set the event mask for this client 3998 */ 3999 static int 4000 cs_set_event_mask(client_handle_t client_handle, sockevent_t *se) 4001 { 4002 cs_socket_t *sp; 4003 client_t *client; 4004 int error; 4005 int client_lock_acquired; 4006 4007 /* 4008 * Check to see if this is the Socket Services client handle; if it 4009 * is, we don't do anything except for return success. 4010 */ 4011 if (CLIENT_HANDLE_IS_SS(client_handle)) 4012 return (CS_SUCCESS); 4013 4014 /* 4015 * Get a pointer to this client's socket structure. 4016 */ 4017 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4018 return (CS_BAD_SOCKET); 4019 4020 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4021 4022 /* 4023 * Make sure that this is a valid client handle. 4024 */ 4025 if (!(client = cs_find_client(client_handle, &error))) { 4026 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4027 return (error); 4028 } 4029 4030 mutex_enter(&sp->lock); 4031 4032 #ifdef XXX 4033 /* 4034 * If there's no card in the socket or the card in the socket is not 4035 * for this client, then return an error. 4036 */ 4037 if (!(client->flags & CLIENT_CARD_INSERTED)) { 4038 mutex_exit(&sp->lock); 4039 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4040 return (CS_NO_CARD); 4041 } 4042 #endif 4043 4044 /* 4045 * We are only allowed to set the client event mask if a 4046 * RequestSocketMask has been called previously. We 4047 * are allowed to set the global event mask at any 4048 * time. 4049 * The global event mask is initially set by the client 4050 * in the call to RegisterClient. The client event 4051 * mask is set by the client in calls to SetEventMask 4052 * and RequestSocketMask and gotten in calls to 4053 * GetEventMask. 4054 */ 4055 if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 4056 if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 4057 mutex_exit(&sp->lock); 4058 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4059 return (CS_BAD_SOCKET); 4060 } 4061 client->event_mask = se->EventMask; 4062 } else { 4063 client->global_mask = se->EventMask; 4064 } 4065 4066 /* 4067 * Merge all the clients' event masks and set the socket 4068 * to generate the appropriate events. 4069 */ 4070 (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 4071 4072 mutex_exit(&sp->lock); 4073 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4074 4075 return (CS_SUCCESS); 4076 } 4077 4078 /* 4079 * cs_read_event_status - handles PRR events and returns card status 4080 * 4081 * calling: *sp - socket struct point 4082 * *client - client to check events on 4083 * *revent - pointer to event mask to update; if NULL, will 4084 * not be updated, if non-NULL, will be updated 4085 * with CS-format events; it is NOT necessary 4086 * to clear this value before calling this 4087 * function 4088 * *gs - pointer to a get_ss_status_t used for the SS GetStatus 4089 * call; it is not necessary to initialize any 4090 * members in this structure; set to NULL if 4091 * not used 4092 * flags - if CS_RES_IGNORE_NO_CARD is set, the check for a 4093 * card present will not be done 4094 * 4095 * returns: CS_SUCCESS 4096 * CS_NO_CARD - if no card is in the socket and the flags arg 4097 * is not set to CS_RES_IGNORE_NO_CARD 4098 * CS_BAD_SOCKET - if the SS_GetStatus function returned an 4099 * error 4100 * 4101 * Note that if the client that configured this socket has told us that 4102 * the READY pin in the PRR isn't valid and the socket is in IO 4103 * mode, we always return that the card is READY. 4104 * 4105 * Note that if gs is not NULL, the current card state will be returned 4106 * in the gs->CardState member; this will always reflect the 4107 * current card state and the state will come from both the 4108 * SS_GetStatus call and the PRR, whichever is appropriate for 4109 * the mode that the socket is currently in. 4110 */ 4111 static int 4112 cs_read_event_status(cs_socket_t *sp, client_t *client, event_t *revent, 4113 get_ss_status_t *gs, int flags) 4114 { 4115 cfg_regs_t prrd = 0; 4116 4117 /* 4118 * SOCKET_IS_IO will only be set if a RequestConfiguration 4119 * has been done by at least one client on this socket. 4120 * If there isn't a card in the socket or the caller wants to ignore 4121 * whether the card is in the socket or not, get the current 4122 * card status. 4123 */ 4124 if ((sp->flags & SOCKET_CARD_INSERTED) || 4125 (flags & CS_RES_IGNORE_NO_CARD)) { 4126 if (sp->flags & SOCKET_IS_IO) { 4127 if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4128 acc_handle_t cis_handle; 4129 uint32_t newoffset = client->config_regs_offset; 4130 4131 /* 4132 * Get a handle to the CIS window 4133 */ 4134 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 4135 CISTPLF_AM_SPACE) != CS_SUCCESS) { 4136 cmn_err(CE_CONT, "cs_read_event_status: socket %d " 4137 "can't init CIS window\n", 4138 sp->socket_num); 4139 return (CS_GENERAL_FAILURE); 4140 } /* cs_init_cis_window */ 4141 4142 prrd = csx_Get8(cis_handle, client->config_regs.prr_p); 4143 prrd &= client->pin; 4144 4145 #ifdef CS_DEBUG 4146 if (cs_debug > 1) { 4147 cmn_err(CE_CONT, "cs_read_event_status: " 4148 "prrd 0x%x client->pin 0x%x\n", 4149 (int)prrd, 4150 client->pin); 4151 cmn_err(CE_CONT, "PRR(1) = [%s%s%s%s%s%s%s%s]\n", 4152 ((prrd & PRR_WP_STATUS)? 4153 "PRR_WP_STATUS ":""), 4154 ((prrd & PRR_READY_STATUS)? 4155 "PRR_READY_STATUS ":""), 4156 ((prrd & PRR_BVD2_STATUS)? 4157 "PRR_BVD2_STATUS ":""), 4158 ((prrd & PRR_BVD1_STATUS)? 4159 "PRR_BVD1_STATUS ":""), 4160 ((prrd & PRR_WP_EVENT)? 4161 "PRR_WP_EVENT ":""), 4162 ((prrd & PRR_READY_EVENT)? 4163 "PRR_READY_EVENT ":""), 4164 ((prrd & PRR_BVD2_EVENT)? 4165 "PRR_BVD2_EVENT ":""), 4166 ((prrd & PRR_BVD1_EVENT)? 4167 "PRR_BVD1_EVENT ":"")); 4168 } 4169 #endif 4170 4171 /* 4172 * The caller wants the event changes sent back and 4173 * the PRR event change bits cleared. 4174 */ 4175 if (revent) { 4176 get_socket_t get_socket; 4177 set_socket_t set_socket; 4178 4179 /* 4180 * Bug ID: 1193636 - Card Services sends bogus 4181 * events on CS_EVENT_STATUS_CHANGE events 4182 * Clear this before we OR-in any values. 4183 */ 4184 *revent = 0; 4185 4186 PRR_EVENT(prrd, PRR_WP_EVENT, PRR_WP_STATUS, 4187 CS_EVENT_WRITE_PROTECT, *revent); 4188 4189 PRR_EVENT(prrd, PRR_READY_EVENT, PRR_READY_STATUS, 4190 CS_EVENT_CARD_READY, *revent); 4191 4192 PRR_EVENT(prrd, PRR_BVD2_EVENT, PRR_BVD2_STATUS, 4193 CS_EVENT_BATTERY_LOW, *revent); 4194 4195 PRR_EVENT(prrd, PRR_BVD1_EVENT, PRR_BVD1_STATUS, 4196 CS_EVENT_BATTERY_DEAD, *revent); 4197 4198 4199 #ifdef CS_DEBUG 4200 if (cs_debug > 1) { 4201 4202 cmn_err(CE_CONT, "PRR() = [%s%s%s%s%s%s%s%s]\n", 4203 ((prrd & PRR_WP_STATUS)? 4204 "PRR_WP_STATUS ":""), 4205 ((prrd & PRR_READY_STATUS)? 4206 "PRR_READY_STATUS ":""), 4207 ((prrd & PRR_BVD2_STATUS)? 4208 "PRR_BVD2_STATUS ":""), 4209 ((prrd & PRR_BVD1_STATUS)? 4210 "PRR_BVD1_STATUS ":""), 4211 ((prrd & PRR_WP_EVENT)? 4212 "PRR_WP_EVENT ":""), 4213 ((prrd & PRR_READY_EVENT)? 4214 "PRR_READY_EVENT ":""), 4215 ((prrd & PRR_BVD2_EVENT)? 4216 "PRR_BVD2_EVENT ":""), 4217 ((prrd & PRR_BVD1_EVENT)? 4218 "PRR_BVD1_EVENT ":"")); 4219 } 4220 #endif 4221 4222 if (prrd) 4223 csx_Put8(cis_handle, client->config_regs.prr_p, 4224 prrd); 4225 4226 /* 4227 * We now have to reenable the status change interrupts 4228 * if there are any valid bits in the PRR. Since 4229 * the BVD1 signal becomes the STATUS_CHANGE 4230 * signal when the socket is in IO mode, we just 4231 * have to set the SBM_BVD1 enable bit in the 4232 * event mask. 4233 */ 4234 if (client->pin) { 4235 get_socket.socket = sp->socket_num; 4236 SocketServices(SS_GetSocket, &get_socket); 4237 set_socket.socket = sp->socket_num; 4238 set_socket.SCIntMask = 4239 get_socket.SCIntMask | SBM_BVD1; 4240 set_socket.VccLevel = get_socket.VccLevel; 4241 set_socket.Vpp1Level = get_socket.Vpp1Level; 4242 set_socket.Vpp2Level = get_socket.Vpp2Level; 4243 set_socket.IREQRouting = get_socket.IRQRouting; 4244 set_socket.IFType = get_socket.IFType; 4245 set_socket.CtlInd = get_socket.CtlInd; 4246 set_socket.State = get_socket.state; 4247 SocketServices(SS_SetSocket, &set_socket); 4248 } /* if (client->pin) */ 4249 } /* if (revent) */ 4250 4251 } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4252 } /* if (SOCKET_IS_IO) */ 4253 4254 /* 4255 * The caller wants the current card state; we just read 4256 * it and return a copy of it but do not clear any of 4257 * the event changed bits (if we're reading the PRR). 4258 */ 4259 if (gs) { 4260 gs->socket = sp->socket_num; 4261 gs->CardState = 0; 4262 if (SocketServices(SS_GetStatus, gs) != SUCCESS) 4263 return (CS_BAD_SOCKET); 4264 if (sp->flags & SOCKET_IS_IO) { 4265 /* 4266 * If the socket is in IO mode, then clear the 4267 * gs->CardState bits that are now in the PRR 4268 */ 4269 gs->CardState &= ~(SBM_WP | SBM_BVD1 | 4270 SBM_BVD2 | SBM_RDYBSY); 4271 4272 /* 4273 * Convert PRR status to SS_GetStatus status 4274 */ 4275 if (prrd & PRR_WP_STATUS) 4276 gs->CardState |= SBM_WP; 4277 if (prrd & PRR_BVD2_STATUS) 4278 gs->CardState |= SBM_BVD2; 4279 if (prrd & PRR_BVD1_STATUS) 4280 gs->CardState |= SBM_BVD1; 4281 4282 /* 4283 * If the client has indicated that there is no 4284 * PRR or that the READY bit in the PRR isn't 4285 * valid, then we simulate the READY bit by 4286 * always returning READY. 4287 */ 4288 if (!(client->present & CONFIG_PINREPL_REG_PRESENT) || 4289 ((client->present & CONFIG_PINREPL_REG_PRESENT) && 4290 !((client->pin & 4291 (PRR_READY_STATUS | PRR_READY_EVENT)) == 4292 (PRR_READY_STATUS | PRR_READY_EVENT))) || 4293 (prrd & PRR_READY_STATUS)) 4294 gs->CardState |= SBM_RDYBSY; 4295 4296 #ifdef CS_DEBUG 4297 if (cs_debug > 1) { 4298 cmn_err(CE_CONT, "cs_read_event_status: prrd 0x%x " 4299 "client->pin 0x%x " 4300 "gs->CardState 0x%x\n", 4301 prrd, client->pin, gs->CardState); 4302 } 4303 #endif 4304 4305 } /* if (SOCKET_IS_IO) */ 4306 } /* if (gs) */ 4307 return (CS_SUCCESS); 4308 } /* if (SOCKET_CARD_INSERTED) */ 4309 4310 return (CS_NO_CARD); 4311 } 4312 4313 /* 4314 * cs_get_status - gets live card status and latched card status changes 4315 * supports the GetStatus CS call 4316 * 4317 * returns: CS_SUCCESS 4318 * CS_BAD_HANDLE if the passed client handle is invalid 4319 * 4320 * Note: This function resets the latched status values maintained 4321 * by Socket Services 4322 */ 4323 static int 4324 cs_get_status(client_handle_t client_handle, get_status_t *gs) 4325 { 4326 cs_socket_t *sp; 4327 client_t *client; 4328 get_ss_status_t get_ss_status; 4329 get_socket_t get_socket; 4330 set_socket_t set_socket; 4331 int error; 4332 int client_lock_acquired; 4333 4334 /* 4335 * Check to see if this is the Socket Services client handle; if it 4336 * is, we don't do anything except for return success. 4337 */ 4338 if (CLIENT_HANDLE_IS_SS(client_handle)) 4339 return (CS_SUCCESS); 4340 4341 /* 4342 * Get a pointer to this client's socket structure. 4343 */ 4344 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4345 return (CS_BAD_SOCKET); 4346 4347 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4348 4349 /* 4350 * Make sure that this is a valid client handle. 4351 */ 4352 if (!(client = cs_find_client(client_handle, &error))) { 4353 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4354 return (error); 4355 } 4356 4357 /* 4358 * Get the current card status as well as the latched card 4359 * state. Set the CS_RES_IGNORE_NO_CARD so that even 4360 * if there is no card in the socket we'll still get 4361 * a valid status. 4362 * Note that it is not necessary to initialize any values 4363 * in the get_ss_status structure. 4364 */ 4365 mutex_enter(&sp->cis_lock); 4366 if ((error = cs_read_event_status(sp, client, NULL, &get_ss_status, 4367 CS_RES_IGNORE_NO_CARD)) != CS_SUCCESS) { 4368 mutex_exit(&sp->cis_lock); 4369 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4370 return (error); 4371 } 4372 4373 mutex_exit(&sp->cis_lock); 4374 4375 gs->raw_CardState = cs_sbm2cse(get_ss_status.CardState); 4376 4377 /* 4378 * Assign the "live" card state to the "real" card state. If there's 4379 * no card in the socket or the card in the socket is not 4380 * for this client, then we lie and tell the caller that the 4381 * card is not inserted. 4382 */ 4383 gs->CardState = gs->raw_CardState; 4384 if (!(client->flags & CLIENT_CARD_INSERTED)) 4385 gs->CardState &= ~CS_EVENT_CARD_INSERTION; 4386 4387 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4388 4389 get_socket.socket = sp->socket_num; 4390 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4391 return (CS_BAD_SOCKET); 4392 4393 gs->SocketState = cs_sbm2cse(get_socket.state); 4394 4395 set_socket.socket = sp->socket_num; 4396 set_socket.SCIntMask = get_socket.SCIntMask; 4397 set_socket.VccLevel = get_socket.VccLevel; 4398 set_socket.Vpp1Level = get_socket.Vpp1Level; 4399 set_socket.Vpp2Level = get_socket.Vpp2Level; 4400 set_socket.IREQRouting = get_socket.IRQRouting; 4401 set_socket.IFType = get_socket.IFType; 4402 set_socket.CtlInd = get_socket.CtlInd; 4403 /* XXX (is ~0 correct here?) reset latched values */ 4404 set_socket.State = (unsigned)~0; 4405 4406 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4407 return (CS_BAD_SOCKET); 4408 4409 return (CS_SUCCESS); 4410 } 4411 4412 /* 4413 * cs_cse2sbm - converts a CS event mask to an SS (SBM_XXX) event mask 4414 */ 4415 static event_t 4416 cs_cse2sbm(event_t event_mask) 4417 { 4418 event_t sbm_event = 0; 4419 4420 /* 4421 * XXX - we need to handle PM_CHANGE and RESET here as well 4422 */ 4423 if (event_mask & CS_EVENT_WRITE_PROTECT) 4424 sbm_event |= SBM_WP; 4425 if (event_mask & CS_EVENT_BATTERY_DEAD) 4426 sbm_event |= SBM_BVD1; 4427 if (event_mask & CS_EVENT_BATTERY_LOW) 4428 sbm_event |= SBM_BVD2; 4429 if (event_mask & CS_EVENT_CARD_READY) 4430 sbm_event |= SBM_RDYBSY; 4431 if (event_mask & CS_EVENT_CARD_LOCK) 4432 sbm_event |= SBM_LOCKED; 4433 if (event_mask & CS_EVENT_EJECTION_REQUEST) 4434 sbm_event |= SBM_EJECT; 4435 if (event_mask & CS_EVENT_INSERTION_REQUEST) 4436 sbm_event |= SBM_INSERT; 4437 if (event_mask & (CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL)) 4438 sbm_event |= SBM_CD; 4439 4440 return (sbm_event); 4441 } 4442 4443 /* 4444 * cs_sbm2cse - converts SBM_xxx state to CS event bits 4445 * 4446 * This function should never set any of the following bits: 4447 * 4448 * CS_EVENT_MTD_REQUEST 4449 * CS_EVENT_CLIENT_INFO 4450 * CS_EVENT_TIMER_EXPIRED 4451 * CS_EVENT_CARD_REMOVAL 4452 * CS_EVENT_CARD_REMOVAL_LOWP 4453 * CS_EVENT_ALL_CLIENTS 4454 * CS_EVENT_READY_TIMEOUT 4455 * 4456 * These bits are defined in the CS_STATUS_XXX series and are 4457 * used by GetStatus. 4458 */ 4459 static uint32_t 4460 cs_sbm2cse(uint32_t state) 4461 { 4462 uint32_t rstate = 0; 4463 4464 /* 4465 * XXX - we need to handle PM_CHANGE and RESET here as well 4466 */ 4467 if (state & SBM_WP) 4468 rstate |= CS_EVENT_WRITE_PROTECT; 4469 if (state & SBM_BVD1) 4470 rstate |= CS_EVENT_BATTERY_DEAD; 4471 if (state & SBM_BVD2) 4472 rstate |= CS_EVENT_BATTERY_LOW; 4473 if (state & SBM_RDYBSY) 4474 rstate |= CS_EVENT_CARD_READY; 4475 if (state & SBM_LOCKED) 4476 rstate |= CS_EVENT_CARD_LOCK; 4477 if (state & SBM_EJECT) 4478 rstate |= CS_EVENT_EJECTION_REQUEST; 4479 if (state & SBM_INSERT) 4480 rstate |= CS_EVENT_INSERTION_REQUEST; 4481 if (state & SBM_CD) 4482 rstate |= CS_EVENT_CARD_INSERTION; 4483 4484 return (rstate); 4485 } 4486 4487 /* 4488 * cs_merge_event_masks - merge the CS global socket event mask with the 4489 * passed client's event masks 4490 */ 4491 static unsigned 4492 cs_merge_event_masks(cs_socket_t *sp, client_t *client) 4493 { 4494 unsigned SCIntMask; 4495 uint32_t event_mask; 4496 4497 /* 4498 * We always want to see card detect and status change events. 4499 */ 4500 SCIntMask = SBM_CD; 4501 4502 event_mask = client->event_mask | client->global_mask | 4503 sp->event_mask; 4504 4505 if (!(sp->flags & SOCKET_IS_IO)) { 4506 SCIntMask |= cs_cse2sbm(event_mask); 4507 } else { 4508 /* 4509 * If the socket is in IO mode and there is a PRR present, 4510 * then we may need to enable PCE_CARD_STATUS_CHANGE 4511 * events. 4512 */ 4513 if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4514 4515 SCIntMask |= (cs_cse2sbm(event_mask) & 4516 ~(SBM_WP | SBM_BVD1 | SBM_BVD2 | SBM_RDYBSY)); 4517 4518 if ((client->pin & (PRR_WP_STATUS | PRR_WP_EVENT)) == 4519 (PRR_WP_STATUS | PRR_WP_EVENT)) 4520 if (event_mask & CS_EVENT_WRITE_PROTECT) 4521 SCIntMask |= SBM_BVD1; 4522 4523 if ((client->pin & (PRR_READY_STATUS | PRR_READY_EVENT)) == 4524 (PRR_READY_STATUS | PRR_READY_EVENT)) 4525 if (event_mask & CS_EVENT_CARD_READY) 4526 SCIntMask |= SBM_BVD1; 4527 4528 if ((client->pin & (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) == 4529 (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) 4530 if (event_mask & CS_EVENT_BATTERY_LOW) 4531 SCIntMask |= SBM_BVD1; 4532 4533 if ((client->pin & (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) == 4534 (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) 4535 if (event_mask & CS_EVENT_BATTERY_DEAD) 4536 SCIntMask |= SBM_BVD1; 4537 4538 } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4539 } /* if (!SOCKET_IS_IO) */ 4540 4541 return (SCIntMask); 4542 } 4543 4544 /* 4545 * cs_set_socket_event_mask - set the event mask for the socket 4546 */ 4547 static int 4548 cs_set_socket_event_mask(cs_socket_t *sp, unsigned event_mask) 4549 { 4550 get_socket_t get_socket; 4551 set_socket_t set_socket; 4552 4553 get_socket.socket = sp->socket_num; 4554 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4555 return (CS_BAD_SOCKET); 4556 4557 set_socket.socket = sp->socket_num; 4558 set_socket.SCIntMask = event_mask; 4559 set_socket.VccLevel = get_socket.VccLevel; 4560 set_socket.Vpp1Level = get_socket.Vpp1Level; 4561 set_socket.Vpp2Level = get_socket.Vpp2Level; 4562 set_socket.IREQRouting = get_socket.IRQRouting; 4563 set_socket.IFType = get_socket.IFType; 4564 set_socket.CtlInd = get_socket.CtlInd; 4565 /* XXX (is ~0 correct here?) reset latched values */ 4566 set_socket.State = (unsigned)~0; 4567 4568 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4569 return (CS_BAD_SOCKET); 4570 4571 return (CS_SUCCESS); 4572 } 4573 4574 /* 4575 * ==== MTD handling section ==== 4576 */ 4577 static int 4578 cs_deregister_mtd(client_handle_t client_handle) 4579 { 4580 4581 cmn_err(CE_CONT, "cs_deregister_mtd: client_handle 0x%x\n", 4582 (int)client_handle); 4583 4584 return (CS_SUCCESS); 4585 } 4586 4587 /* 4588 * ==== memory window handling section ==== 4589 */ 4590 4591 /* 4592 * cs_request_window - searches through window list for the socket to find a 4593 * memory window that matches the requested criteria; 4594 * this is RequestWindow 4595 * 4596 * calling: cs_request_window(client_handle_t, *window_handle_t, win_req_t *) 4597 * 4598 * On sucessful return, the window_handle_t * pointed to will 4599 * contain a valid window handle for this window. 4600 * 4601 * returns: CS_SUCCESS - if window found 4602 * CS_OUT_OF_RESOURCE - if no windows match requirements 4603 * CS_BAD_HANDLE - client handle is invalid 4604 * CS_BAD_SIZE - if requested size can not be met 4605 * CS_BAD_WINDOW - if an internal error occured 4606 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 4607 * CS_NO_CARD - if no card is in socket 4608 * CS_BAD_ATTRIBUTE - if any of the unsupported Attrbute 4609 * flags are set 4610 */ 4611 static int 4612 cs_request_window(client_handle_t client_handle, 4613 window_handle_t *wh, 4614 win_req_t *rw) 4615 { 4616 cs_socket_t *sp; 4617 cs_window_t *cw; 4618 client_t *client; 4619 modify_win_t mw; 4620 inquire_window_t iw; 4621 uint32_t aw; 4622 int error; 4623 int client_lock_acquired; 4624 uint32_t socket_num; 4625 4626 /* 4627 * Check to see if this is the Socket Services client handle; if it 4628 * is, we don't support SS using this call. 4629 */ 4630 if (CLIENT_HANDLE_IS_SS(client_handle)) 4631 return (CS_UNSUPPORTED_FUNCTION); 4632 4633 /* 4634 * Make sure that none of the unsupported flags are set. 4635 */ 4636 if (rw->Attributes & (/* Compatability */ 4637 WIN_PAGED | 4638 WIN_SHARED | 4639 WIN_FIRST_SHARED | 4640 WIN_BINDING_SPECIFIC | 4641 /* CS internal */ 4642 WIN_DATA_WIDTH_VALID | 4643 /* IO window flags */ 4644 WIN_MEMORY_TYPE_IO | 4645 /* CardBus flags */ 4646 WIN_DATA_WIDTH_32 | 4647 WIN_PREFETCH_CACHE_MASK | 4648 WIN_BAR_MASK)) 4649 return (CS_BAD_ATTRIBUTE); 4650 4651 mutex_enter(&cs_globals.window_lock); 4652 4653 /* 4654 * Get a pointer to this client's socket structure. 4655 */ 4656 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4657 return (CS_BAD_SOCKET); 4658 4659 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4660 4661 /* 4662 * Make sure that this is a valid client handle. 4663 */ 4664 if (!(client = cs_find_client(client_handle, &error))) { 4665 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4666 mutex_exit(&cs_globals.window_lock); 4667 return (error); 4668 } 4669 4670 mutex_enter(&sp->lock); 4671 4672 /* 4673 * If there's no card in the socket or the card in the socket is not 4674 * for this client, then return an error. 4675 */ 4676 if (!(client->flags & CLIENT_CARD_INSERTED)) { 4677 mutex_exit(&sp->lock); 4678 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4679 mutex_exit(&cs_globals.window_lock); 4680 return (CS_NO_CARD); 4681 } 4682 4683 mutex_exit(&sp->lock); 4684 4685 socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 4686 GET_CLIENT_FUNCTION(client_handle)); 4687 4688 4689 /* 4690 * See if we can find a window that matches the caller's criteria. 4691 * If we can't, then thre's not much more that we can do except 4692 * for return an error. 4693 */ 4694 if ((error = cs_find_mem_window(sp->socket_num, rw, &aw)) != 4695 CS_SUCCESS) { 4696 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4697 mutex_exit(&cs_globals.window_lock); 4698 return (error); 4699 } 4700 4701 /* 4702 * We got a window, now synthesize a new window handle for this 4703 * client and get a pointer to the global window structs 4704 * and assign this window to this client. 4705 * We don't have to check for errors from cs_create_window_handle 4706 * since that function always returns a valid window handle 4707 * if it is given a valid window number. 4708 */ 4709 *wh = cs_create_window_handle(aw); 4710 if ((cw = cs_get_wp(aw)) == NULL) { 4711 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4712 mutex_exit(&cs_globals.window_lock); 4713 return (CS_BAD_WINDOW); 4714 } 4715 4716 cw->window_handle = *wh; 4717 cw->client_handle = client_handle; 4718 cw->socket_num = sp->socket_num; 4719 cw->state |= (CW_ALLOCATED | CW_MEM); 4720 4721 mw.Attributes = ( 4722 rw->Attributes | 4723 WIN_DATA_WIDTH_VALID | 4724 WIN_ACCESS_SPEED_VALID); 4725 mw.AccessSpeed = rw->win_params.AccessSpeed; 4726 4727 if ((error = cs_modify_mem_window(*wh, &mw, rw, socket_num)) != 4728 CS_SUCCESS) { 4729 cw->state = 0; 4730 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4731 mutex_exit(&cs_globals.window_lock); 4732 return (error); 4733 } 4734 4735 /* 4736 * Get any required card offset and pass it back to the client. 4737 * This is not defined in the current PCMCIA spec. It is 4738 * an aid to clients that want to use it to generate an 4739 * optimum card offset. 4740 */ 4741 iw.window = GET_WINDOW_NUMBER(*wh); 4742 SocketServices(SS_InquireWindow, &iw); 4743 4744 if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 4745 rw->ReqOffset = rw->Size; 4746 else 4747 rw->ReqOffset = iw.mem_win_char.ReqOffset; 4748 4749 /* 4750 * Increment the client's memory window count; this is how we know 4751 * when a client has any allocated memory windows. 4752 */ 4753 client->memwin_count++; 4754 4755 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4756 mutex_exit(&cs_globals.window_lock); 4757 4758 return (CS_SUCCESS); 4759 } 4760 4761 /* 4762 * cs_release_window - deallocates the window associated with the passed 4763 * window handle; this is ReleaseWindow 4764 * 4765 * returns: CS_SUCCESS if window handle is valid and window was 4766 * sucessfully deallocated 4767 * CS_BAD_HANDLE if window handle is invalid or if window 4768 * handle is valid but window is not allocated 4769 */ 4770 static int 4771 cs_release_window(window_handle_t wh) 4772 { 4773 cs_socket_t *sp; 4774 cs_window_t *cw; 4775 client_t *client; 4776 int error; 4777 int client_lock_acquired; 4778 4779 mutex_enter(&cs_globals.window_lock); 4780 4781 if (!(cw = cs_find_window(wh))) { 4782 mutex_exit(&cs_globals.window_lock); 4783 return (CS_BAD_HANDLE); 4784 } 4785 4786 /* 4787 * Check to see if this is the Socket Services client handle; if it 4788 * is, we don't support SS using this call. 4789 */ 4790 if (CLIENT_HANDLE_IS_SS(cw->client_handle)) { 4791 mutex_exit(&cs_globals.window_lock); 4792 return (CS_UNSUPPORTED_FUNCTION); 4793 } 4794 4795 /* 4796 * Get a pointer to this client's socket structure. 4797 */ 4798 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4799 return (CS_BAD_SOCKET); 4800 4801 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4802 4803 /* 4804 * Make sure that this is a valid client handle. 4805 */ 4806 if (!(client = cs_find_client(cw->client_handle, &error))) { 4807 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4808 mutex_exit(&cs_globals.window_lock); 4809 return (error); 4810 } 4811 4812 /* 4813 * Mark this window as not in use anymore. 4814 */ 4815 cw->state &= ~CW_WIN_IN_USE; 4816 4817 /* 4818 * Decrement the client's memory window count; this is how we know 4819 * when a client has any allocated memory windows. 4820 */ 4821 if (!(--(client->memwin_count))) 4822 client->flags &= ~CLIENT_WIN_ALLOCATED; 4823 4824 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4825 mutex_exit(&cs_globals.window_lock); 4826 4827 return (CS_SUCCESS); 4828 } 4829 4830 /* 4831 * cs_modify_window - modifies a window's characteristics; this is ModifyWindow 4832 */ 4833 static int 4834 cs_modify_window(window_handle_t wh, modify_win_t *mw) 4835 { 4836 cs_socket_t *sp; 4837 cs_window_t *cw; 4838 client_t *client; 4839 int error; 4840 int client_lock_acquired; 4841 4842 mutex_enter(&cs_globals.window_lock); 4843 4844 /* 4845 * Do some sanity checking - make sure that we can find a pointer 4846 * to the window structure, and if we can, get the client that 4847 * has allocated that window. 4848 */ 4849 if (!(cw = cs_find_window(wh))) { 4850 mutex_exit(&cs_globals.window_lock); 4851 return (CS_BAD_HANDLE); 4852 } 4853 4854 /* 4855 * Get a pointer to this client's socket structure. 4856 */ 4857 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4858 return (CS_BAD_SOCKET); 4859 4860 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4861 4862 if (!(client = cs_find_client(cw->client_handle, &error))) { 4863 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4864 mutex_exit(&cs_globals.window_lock); 4865 return (error); 4866 } 4867 4868 mutex_enter(&sp->lock); 4869 4870 /* 4871 * If there's no card in the socket or the card in the socket is not 4872 * for this client, then return an error. 4873 */ 4874 if (!(client->flags & CLIENT_CARD_INSERTED)) { 4875 mutex_exit(&sp->lock); 4876 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4877 mutex_exit(&cs_globals.window_lock); 4878 return (CS_NO_CARD); 4879 } 4880 4881 mutex_exit(&sp->lock); 4882 4883 mw->Attributes &= ( 4884 WIN_MEMORY_TYPE_MASK | 4885 WIN_ENABLE | 4886 WIN_ACCESS_SPEED_VALID | 4887 WIN_ACC_ENDIAN_MASK | 4888 WIN_ACC_ORDER_MASK); 4889 4890 mw->Attributes &= ~WIN_DATA_WIDTH_VALID; 4891 4892 if ((error = cs_modify_mem_window(wh, mw, NULL, NULL)) != CS_SUCCESS) { 4893 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4894 mutex_exit(&cs_globals.window_lock); 4895 return (error); 4896 } 4897 4898 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4899 mutex_exit(&cs_globals.window_lock); 4900 4901 return (CS_SUCCESS); 4902 } 4903 4904 /* 4905 * cs_modify_mem_window - modifies a window's characteristics; used internally 4906 * by Card Services 4907 * 4908 * If *wr is NULL, it means that we're being called by ModifyWindow 4909 * If *wr is non-NULL, it means that we are being called by RequestWindow 4910 * and so we can't use SS_GetWindow. 4911 */ 4912 static int 4913 cs_modify_mem_window(window_handle_t wh, modify_win_t *mw, 4914 win_req_t *wr, int sn) 4915 { 4916 get_window_t gw; 4917 set_window_t sw; 4918 set_page_t set_page; 4919 get_page_t get_page; 4920 4921 /* 4922 * If the win_req_t struct pointer is NULL, it means that 4923 * we're being called by ModifyWindow, so get the 4924 * current window characteristics. 4925 */ 4926 if (!wr) { 4927 gw.window = GET_WINDOW_NUMBER(wh); 4928 if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 4929 return (CS_BAD_WINDOW); 4930 sw.state = gw.state; 4931 sw.socket = gw.socket; 4932 sw.WindowSize = gw.size; 4933 } else { 4934 sw.state = 0; 4935 sw.socket = sn; 4936 sw.WindowSize = wr->Size; 4937 } 4938 4939 /* 4940 * If we're being called by RequestWindow, we must always have 4941 * WIN_ACCESS_SPEED_VALID set since get_window_t is not 4942 * defined. 4943 */ 4944 if (mw->Attributes & WIN_ACCESS_SPEED_VALID) { 4945 convert_speed_t convert_speed; 4946 4947 convert_speed.Attributes = CONVERT_DEVSPEED_TO_NS; 4948 convert_speed.devspeed = mw->AccessSpeed; 4949 4950 if (cs_convert_speed(&convert_speed) != CS_SUCCESS) 4951 return (CS_BAD_SPEED); 4952 4953 sw.speed = convert_speed.nS; 4954 } else { 4955 sw.speed = gw.speed; 4956 } 4957 4958 if (!wr) { 4959 get_page.window = GET_WINDOW_NUMBER(wh); 4960 get_page.page = 0; 4961 if (SocketServices(SS_GetPage, &get_page) != SUCCESS) 4962 return (CS_BAD_WINDOW); 4963 set_page.state = get_page.state; 4964 set_page.offset = get_page.offset; 4965 } else { 4966 set_page.state = 0; 4967 set_page.offset = 0; 4968 } 4969 4970 if (mw->Attributes & WIN_ENABLE) { 4971 sw.state |= WS_ENABLED; 4972 set_page.state |= PS_ENABLED; 4973 } else { 4974 sw.state &= ~WS_ENABLED; 4975 set_page.state &= ~PS_ENABLED; 4976 } 4977 4978 if (mw->Attributes & WIN_DATA_WIDTH_VALID) { 4979 if (mw->Attributes & WIN_DATA_WIDTH_16) 4980 sw.state |= WS_16BIT; 4981 else 4982 sw.state &= ~WS_16BIT; 4983 } 4984 4985 sw.window = GET_WINDOW_NUMBER(wh); 4986 sw.base = 0; 4987 4988 cs_set_acc_attributes(&sw, mw->Attributes); 4989 4990 if (SocketServices(SS_SetWindow, &sw) != SUCCESS) 4991 return (CS_BAD_WINDOW); 4992 4993 if (mw->Attributes & WIN_MEMORY_TYPE_AM) 4994 set_page.state |= PS_ATTRIBUTE; 4995 else 4996 set_page.state &= ~PS_ATTRIBUTE; 4997 4998 set_page.window = GET_WINDOW_NUMBER(wh); 4999 set_page.page = 0; 5000 if (SocketServices(SS_SetPage, &set_page) != SUCCESS) 5001 return (CS_BAD_OFFSET); 5002 5003 /* 5004 * Return the current base address of this window 5005 */ 5006 if (wr) { 5007 gw.window = GET_WINDOW_NUMBER(wh); 5008 if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 5009 return (CS_BAD_WINDOW); 5010 5011 wr->Base.handle = (acc_handle_t)gw.handle; 5012 } 5013 5014 return (CS_SUCCESS); 5015 } 5016 5017 /* 5018 * cs_map_mem_page - sets the card offset of the mapped window 5019 */ 5020 static int 5021 cs_map_mem_page(window_handle_t wh, map_mem_page_t *mmp) 5022 { 5023 cs_socket_t *sp; 5024 cs_window_t *cw; 5025 client_t *client; 5026 inquire_window_t iw; 5027 get_window_t gw; 5028 set_page_t set_page; 5029 get_page_t get_page; 5030 int error; 5031 uint32_t size; 5032 int client_lock_acquired; 5033 5034 /* 5035 * We don't support paged windows, so never allow a page number 5036 * of other than 0 5037 */ 5038 if (mmp->Page) 5039 return (CS_BAD_PAGE); 5040 5041 mutex_enter(&cs_globals.window_lock); 5042 5043 /* 5044 * Do some sanity checking - make sure that we can find a pointer 5045 * to the window structure, and if we can, get the client that 5046 * has allocated that window. 5047 */ 5048 if (!(cw = cs_find_window(wh))) { 5049 mutex_exit(&cs_globals.window_lock); 5050 return (CS_BAD_HANDLE); 5051 } 5052 5053 /* 5054 * Get a pointer to this client's socket structure. 5055 */ 5056 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 5057 return (CS_BAD_SOCKET); 5058 5059 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5060 5061 if (!(client = cs_find_client(cw->client_handle, &error))) { 5062 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5063 mutex_exit(&cs_globals.window_lock); 5064 return (error); 5065 } 5066 5067 mutex_enter(&sp->lock); 5068 5069 /* 5070 * If there's no card in the socket or the card in the socket is not 5071 * for this client, then return an error. 5072 */ 5073 if (!(client->flags & CLIENT_CARD_INSERTED)) { 5074 mutex_exit(&sp->lock); 5075 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5076 mutex_exit(&cs_globals.window_lock); 5077 return (CS_NO_CARD); 5078 } 5079 5080 mutex_exit(&sp->lock); 5081 5082 gw.window = GET_WINDOW_NUMBER(wh); 5083 SocketServices(SS_GetWindow, &gw); 5084 5085 iw.window = GET_WINDOW_NUMBER(wh); 5086 SocketServices(SS_InquireWindow, &iw); 5087 5088 if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 5089 size = gw.size; 5090 else 5091 size = iw.mem_win_char.ReqOffset; 5092 5093 if (((mmp->CardOffset/size)*size) != mmp->CardOffset) { 5094 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5095 mutex_exit(&cs_globals.window_lock); 5096 return (CS_BAD_OFFSET); 5097 } 5098 5099 get_page.window = GET_WINDOW_NUMBER(wh); 5100 get_page.page = 0; 5101 SocketServices(SS_GetPage, &get_page); 5102 5103 set_page.window = GET_WINDOW_NUMBER(wh); 5104 set_page.page = 0; 5105 set_page.state = get_page.state; 5106 set_page.offset = mmp->CardOffset; 5107 if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 5108 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5109 mutex_exit(&cs_globals.window_lock); 5110 return (CS_BAD_OFFSET); 5111 } 5112 5113 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5114 mutex_exit(&cs_globals.window_lock); 5115 5116 return (CS_SUCCESS); 5117 } 5118 5119 /* 5120 * cs_find_window - finds the window associated with the passed window 5121 * handle; if the window handle is invalid or no 5122 * windows match the passed window handle, NULL 5123 * is returned. Note that the window must be 5124 * allocated for this function to return a valid 5125 * window pointer. 5126 * 5127 * returns: cs_window_t * pointer to the found window 5128 * NULL if window handle invalid or window not allocated 5129 */ 5130 cs_window_t * 5131 cs_find_window(window_handle_t wh) 5132 { 5133 cs_window_t *cw; 5134 5135 if ((GET_WINDOW_NUMBER(wh) > cs_globals.num_windows) || 5136 (GET_WINDOW_MAGIC(wh) != WINDOW_HANDLE_MAGIC)) 5137 return ((cs_window_t *)NULL); 5138 5139 if ((cw = cs_get_wp(GET_WINDOW_NUMBER(wh))) == NULL) 5140 return (NULL); 5141 5142 if ((cw->state & CW_ALLOCATED) && (cw->state & CW_MEM)) 5143 return (cw); 5144 5145 return ((cs_window_t *)NULL); 5146 } 5147 5148 /* 5149 * cs_create_window_handle - creates a unique window handle based on the 5150 * passed window number. 5151 */ 5152 static window_handle_t 5153 cs_create_window_handle(uint32_t aw) 5154 { 5155 return (WINDOW_HANDLE_MAGIC | (aw & WINDOW_HANDLE_MASK)); 5156 } 5157 5158 /* 5159 * cs_find_mem_window - tries to find a memory window matching the caller's 5160 * criteria 5161 * 5162 * We return the first window that matches the requested criteria. 5163 * 5164 * returns: CS_SUCCESS - if memory window found 5165 * CS_OUT_OF_RESOURCE - if no windows match requirements 5166 * CS_BAD_SIZE - if requested size can not be met 5167 * CS_BAD_WINDOW - if an internal error occured 5168 */ 5169 /* BEGIN CSTYLED */ 5170 static int 5171 cs_find_mem_window(uint32_t sn, win_req_t *rw, uint32_t *assigned_window) 5172 { 5173 uint32_t wn; 5174 int error = CS_OUT_OF_RESOURCE; 5175 uint32_t window_num = PCMCIA_MAX_WINDOWS; 5176 uint32_t min_size = UINT_MAX; 5177 inquire_window_t inquire_window, *iw; 5178 uint32_t MinSize, MaxSize, ReqGran, MemWndCaps, WndCaps; 5179 uint32_t tws; 5180 5181 iw = &inquire_window; 5182 5183 for (wn = 0; wn < cs_globals.num_windows; wn++) { 5184 cs_window_t *cw; 5185 5186 /* 5187 * If we can't get a pointer to this window, we should contine 5188 * with scanning the next window, since this window might have 5189 * been dropped. 5190 */ 5191 if ((cw = cs_get_wp(wn)) != NULL) { 5192 iw->window = wn; 5193 5194 if (SocketServices(SS_InquireWindow, iw) != SUCCESS) 5195 return (CS_BAD_WINDOW); 5196 5197 MinSize = iw->mem_win_char.MinSize; 5198 MaxSize = iw->mem_win_char.MaxSize; 5199 ReqGran = iw->mem_win_char.ReqGran; 5200 MemWndCaps = iw->mem_win_char.MemWndCaps; 5201 WndCaps = iw->WndCaps; 5202 5203 if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5204 WINDOW_AVAILABLE_FOR_MEM(cw) && 5205 WndCaps & (WC_COMMON|WC_ATTRIBUTE)) { 5206 if ((error = cs_valid_window_speed(iw, rw->win_params.AccessSpeed)) == 5207 CS_SUCCESS) { 5208 error = CS_OUT_OF_RESOURCE; 5209 if (cs_memwin_space_and_map_ok(iw, rw)) { 5210 error = CS_BAD_SIZE; 5211 if (!rw->Size) { 5212 min_size = min(min_size, MinSize); 5213 window_num = wn; 5214 goto found_window; 5215 } else { 5216 if (!(MemWndCaps & WC_SIZE)) { 5217 if (rw->Size == MinSize) { 5218 min_size = MinSize; 5219 window_num = wn; 5220 goto found_window; 5221 } 5222 } else { /* WC_SIZE */ 5223 if (!ReqGran) { 5224 error = CS_BAD_WINDOW; 5225 } else { 5226 if ((rw->Size >= MinSize) && 5227 (rw->Size <= MaxSize)) { 5228 if (MemWndCaps & WC_POW2) { 5229 unsigned rg = ReqGran; 5230 for (tws = MinSize; tws <= MaxSize; 5231 rg = (rg<<1)) { 5232 if (rw->Size == tws) { 5233 min_size = tws; 5234 window_num = wn; 5235 goto found_window; 5236 } 5237 tws += rg; 5238 } /* for (tws) */ 5239 } else { 5240 for (tws = MinSize; tws <= MaxSize; 5241 tws += ReqGran) { 5242 if (rw->Size == tws) { 5243 min_size = tws; 5244 window_num = wn; 5245 goto found_window; 5246 } 5247 } /* for (tws) */ 5248 } /* if (!WC_POW2) */ 5249 } /* if (Size >= MinSize) */ 5250 } /* if (!ReqGran) */ 5251 } /* if (WC_SIZE) */ 5252 } /* if (rw->Size) */ 5253 } /* if (cs_space_and_map_ok) */ 5254 } /* if (cs_valid_window_speed) */ 5255 } /* if (WINDOW_FOR_SOCKET) */ 5256 } /* if (cs_get_wp) */ 5257 } /* for (wn) */ 5258 5259 /* 5260 * If we got here and the window_num wasn't set by any window 5261 * matches in the above code, it means that we didn't 5262 * find a window matching the caller's criteria. 5263 * If the error is CS_BAD_TYPE, it means that the last reason 5264 * that we couldn't match a window was because the caller's 5265 * requested speed was out of range of the last window that 5266 * we checked. We convert this error code to CS_OUT_OF_RESOURCE 5267 * to conform to the RequestWindow section of the PCMCIA 5268 * Card Services spec. 5269 */ 5270 if (window_num == PCMCIA_MAX_WINDOWS) { 5271 if (error == CS_BAD_TYPE) 5272 error = CS_OUT_OF_RESOURCE; 5273 return (error); 5274 } 5275 5276 found_window: 5277 rw->Size = min_size; 5278 *assigned_window = window_num; 5279 iw->window = window_num; 5280 SocketServices(SS_InquireWindow, iw); 5281 MemWndCaps = iw->mem_win_char.MemWndCaps; 5282 5283 if (MemWndCaps & WC_CALIGN) 5284 rw->Attributes |= WIN_OFFSET_SIZE; 5285 else 5286 rw->Attributes &= ~WIN_OFFSET_SIZE; 5287 return (CS_SUCCESS); 5288 } 5289 /* END CSTYLED */ 5290 5291 /* 5292 * cs_memwin_space_and_map_ok - checks to see if the passed window mapping 5293 * capabilities and window speeds are in the 5294 * range of the passed window. 5295 * 5296 * returns: 0 - if the capabilities are out of range 5297 * 1 - if the capabilities are in range 5298 */ 5299 static int 5300 cs_memwin_space_and_map_ok(inquire_window_t *iw, win_req_t *rw) 5301 { 5302 5303 #ifdef CS_DEBUG 5304 if (cs_debug > 240) 5305 printf("-> s&m_ok: Attributes 0x%x AccessSpeed 0x%x " 5306 "WndCaps 0x%x MemWndCaps 0x%x\n", 5307 (int)rw->Attributes, 5308 (int)rw->win_params.AccessSpeed, 5309 iw->WndCaps, 5310 iw->mem_win_char.MemWndCaps); 5311 #endif 5312 5313 if (rw->win_params.AccessSpeed & WIN_USE_WAIT) { 5314 if (!(iw->WndCaps & WC_WAIT)) 5315 return (0); 5316 } 5317 5318 if (rw->Attributes & WIN_DATA_WIDTH_16) { 5319 if (!(iw->mem_win_char.MemWndCaps & WC_16BIT)) 5320 return (0); 5321 } else { 5322 if (!(iw->mem_win_char.MemWndCaps & WC_8BIT)) 5323 return (0); 5324 } 5325 5326 if (rw->Attributes & WIN_MEMORY_TYPE_AM) { 5327 if (!(iw->WndCaps & WC_ATTRIBUTE)) 5328 return (0); 5329 } 5330 5331 if (rw->Attributes & WIN_MEMORY_TYPE_CM) { 5332 if (!(iw->WndCaps & WC_COMMON)) 5333 return (0); 5334 } 5335 5336 return (1); 5337 } 5338 5339 /* 5340 * cs_valid_window_speed - checks to see if requested window speed 5341 * is in range of passed window 5342 * 5343 * The inquire_window_t struct gives us speeds in nS, and we 5344 * get speeds in the AccessSpeed variable as a devspeed code. 5345 * 5346 * returns: CS_BAD_SPEED - if AccessSpeed is invalid devspeed code 5347 * CS_BAD_TYPE - if AccessSpeed is not in range of valid 5348 * speed for this window 5349 * CS_SUCCESS - if window speed is in range 5350 */ 5351 static int 5352 cs_valid_window_speed(inquire_window_t *iw, uint32_t AccessSpeed) 5353 { 5354 convert_speed_t convert_speed, *cs; 5355 5356 cs = &convert_speed; 5357 5358 cs->Attributes = CONVERT_DEVSPEED_TO_NS; 5359 cs->devspeed = AccessSpeed; 5360 5361 if (cs_convert_speed(cs) != CS_SUCCESS) 5362 return (CS_BAD_SPEED); 5363 5364 if ((cs->nS < iw->mem_win_char.Fastest) || 5365 (cs->nS > iw->mem_win_char.Slowest)) 5366 return (CS_BAD_TYPE); 5367 5368 return (CS_SUCCESS); 5369 } 5370 5371 /* 5372 * ==== IO window handling section ==== 5373 */ 5374 5375 /* 5376 * cs_request_io - provides IO resources for clients; this is RequestIO 5377 * 5378 * calling: cs_request_io(client_handle_t, io_req_t *) 5379 * 5380 * returns: CS_SUCCESS - if IO resources available for client 5381 * CS_OUT_OF_RESOURCE - if no windows match requirements 5382 * CS_BAD_HANDLE - client handle is invalid 5383 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5384 * CS_NO_CARD - if no card is in socket 5385 * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 5386 * flags are set 5387 * CS_BAD_BASE - if either or both base port addresses 5388 * are invalid or out of range 5389 * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 5390 * already been done 5391 * CS_IN_USE - IO ports already in use or function has 5392 * already been called 5393 * CS_BAD_WINDOW - if failure while trying to set window 5394 * characteristics 5395 */ 5396 static int 5397 cs_request_io(client_handle_t client_handle, io_req_t *ior) 5398 { 5399 cs_socket_t *sp; 5400 client_t *client; 5401 int error; 5402 int client_lock_acquired; 5403 uint32_t socket_num; 5404 5405 /* 5406 * Check to see if this is the Socket Services client handle; if it 5407 * is, we don't support SS using this call. 5408 */ 5409 if (CLIENT_HANDLE_IS_SS(client_handle)) 5410 return (CS_UNSUPPORTED_FUNCTION); 5411 5412 /* 5413 * If the client has only requested one IO range, then make sure 5414 * that the Attributes2 filed is clear. 5415 */ 5416 if (!ior->NumPorts2) 5417 ior->Attributes2 = 0; 5418 5419 /* 5420 * Make sure that none of the unsupported or reserved flags are set. 5421 */ 5422 if ((ior->Attributes1 | ior->Attributes2) & (IO_SHARED | 5423 IO_FIRST_SHARED | 5424 IO_FORCE_ALIAS_ACCESS | 5425 IO_DEALLOCATE_WINDOW | 5426 IO_DISABLE_WINDOW)) 5427 return (CS_BAD_ATTRIBUTE); 5428 5429 /* 5430 * Make sure that we have a port count for the first region. 5431 */ 5432 if (!ior->NumPorts1) 5433 return (CS_BAD_BASE); 5434 5435 /* 5436 * If we're being asked for multiple IO ranges, then both base port 5437 * members must be non-zero. 5438 */ 5439 if ((ior->NumPorts2) && !(ior->BasePort1.base && ior->BasePort2.base)) 5440 return (CS_BAD_BASE); 5441 5442 mutex_enter(&cs_globals.window_lock); 5443 5444 /* 5445 * Get a pointer to this client's socket structure. 5446 */ 5447 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5448 return (CS_BAD_SOCKET); 5449 5450 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5451 5452 /* 5453 * Make sure that this is a valid client handle. 5454 */ 5455 if (!(client = cs_find_client(client_handle, &error))) { 5456 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5457 mutex_exit(&cs_globals.window_lock); 5458 return (error); 5459 } 5460 5461 /* 5462 * If RequestConfiguration has already been done, we don't allow 5463 * this call. 5464 */ 5465 if (client->flags & REQ_CONFIGURATION_DONE) { 5466 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5467 mutex_exit(&cs_globals.window_lock); 5468 return (CS_CONFIGURATION_LOCKED); 5469 } 5470 5471 /* 5472 * If RequestIO has already been done, we don't allow this call. 5473 */ 5474 if (client->flags & REQ_IO_DONE) { 5475 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5476 mutex_exit(&cs_globals.window_lock); 5477 return (CS_IN_USE); 5478 } 5479 5480 mutex_enter(&sp->lock); 5481 5482 /* 5483 * If there's no card in the socket or the card in the socket is not 5484 * for this client, then return an error. 5485 */ 5486 if (!(client->flags & CLIENT_CARD_INSERTED)) { 5487 mutex_exit(&sp->lock); 5488 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5489 mutex_exit(&cs_globals.window_lock); 5490 return (CS_NO_CARD); 5491 } 5492 5493 mutex_exit(&sp->lock); 5494 5495 /* 5496 * If we're only being asked for one IO range, then set BasePort2 to 5497 * zero, since we use it later on. 5498 */ 5499 if (!ior->NumPorts2) 5500 ior->BasePort2.base = 0; 5501 5502 /* 5503 * See if we can allow Card Services to select the base address 5504 * value for this card; if the client has specified a non-zero 5505 * base IO address but the card doesn't decode enough IO 5506 * address lines to uniquely use that address, then we have 5507 * the flexibility to choose an alternative base address. 5508 * Note that if the client specifies that the card decodes zero 5509 * IO address lines, then we have to use the NumPortsX 5510 * values to figure out how many address lines the card 5511 * actually decodes, and we have to round the NumPortsX 5512 * values up to the closest power of two. 5513 */ 5514 if (ior->IOAddrLines) { 5515 ior->BasePort1.base = IOADDR_FROBNITZ(ior->BasePort1.base, 5516 ior->IOAddrLines); 5517 ior->BasePort2.base = IOADDR_FROBNITZ(ior->BasePort2.base, 5518 ior->IOAddrLines); 5519 } else { 5520 ior->BasePort1.base = ior->BasePort1.base & 5521 ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5522 IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5523 ior->BasePort2.base = ior->BasePort2.base & 5524 ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5525 IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5526 } 5527 5528 socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5529 GET_CLIENT_FUNCTION(client_handle)); 5530 5531 5532 #ifdef USE_IOMMAP_WINDOW 5533 /* 5534 * Here is where the code diverges, depending on the type of IO windows 5535 * that this socket supports. If this socket supportes memory 5536 * mapped IO windows, as determined by cs_init allocating an 5537 * io_mmap_window_t structure on the socket structure, then we 5538 * use one IO window for all the clients on this socket. We can 5539 * do this safely since a memory mapped IO window implies that 5540 * only this socket shares the complete IO space of the card. 5541 * See the next major block of code for a description of what we do 5542 * if a socket doesn't support memory mapped IO windows. 5543 */ 5544 if (sp->io_mmap_window) { 5545 cs_window_t *cw; 5546 io_mmap_window_t *imw = sp->io_mmap_window; 5547 uint32_t offset; 5548 5549 /* 5550 * If we haven't allocated an IO window yet, do it now. 5551 * Try to allocate the IO window that cs_init found for us; 5552 * if that fails, then call cs_find_io_win to find a window. 5553 */ 5554 if (!imw->count) { 5555 set_window_t set_window; 5556 5557 if (!WINDOW_AVAILABLE_FOR_IO(imw->number)) { 5558 iowin_char_t iowin_char; 5559 5560 iowin_char.IOWndCaps = (WC_IO_RANGE_PER_WINDOW | 5561 WC_8BIT | 5562 WC_16BIT); 5563 if ((error = cs_find_io_win(sp->socket_num, &iowin_char, 5564 &imw->number, &imw->size)) != CS_SUCCESS) { 5565 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5566 mutex_exit(&cs_globals.window_lock); 5567 } /* cs_find_io_win */ 5568 } /* if (!WINDOW_AVAILABLE_FOR_IO) */ 5569 5570 set_window.socket = socket_num; 5571 set_window.window = imw->number; 5572 set_window.speed = IO_WIN_SPEED; 5573 set_window.base.base = 0; 5574 set_window.WindowSize = imw->size; 5575 set_window.state = (WS_ENABLED | WS_16BIT | 5576 WS_EXACT_MAPIN | WS_IO); 5577 5578 /* XXX - what to d here? XXX */ 5579 cs_set_acc_attributes(&set_window, Attributes); 5580 5581 if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) { 5582 (void) cs_setup_io_win(socket_num, imw->number, 5583 NULL, NULL, NULL, 5584 (IO_DEALLOCATE_WINDOW | 5585 IO_DISABLE_WINDOW)); 5586 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5587 mutex_exit(&cs_globals.window_lock); 5588 return (CS_BAD_WINDOW); 5589 } 5590 5591 imw->handle = set_window.base.handle; 5592 imw->size = set_window.WindowSize; 5593 5594 /* 5595 * Check the caller's port requirements to be sure that they 5596 * fit within our found IO window. 5597 */ 5598 if ((ior->BasePort1.base + ior->NumPorts1 + 5599 ior->BasePort2.base + ior->NumPorts2) > imw->size) { 5600 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5601 mutex_exit(&cs_globals.window_lock); 5602 return (CS_BAD_BASE); 5603 } 5604 5605 if ((cw = cs_get_wp(imw->number)) == NULL) { 5606 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5607 mutex_exit(&cs_globals.window_lock); 5608 return (CS_BAD_WINDOW) 5609 } 5610 cw->state |= (CW_ALLOCATED | CW_IO); 5611 5612 } /* if (!imw->count) */ 5613 5614 imw->count++; 5615 5616 /* 5617 * All common access handles for this type of adapter are 5618 * duped. We never give the original back to the caller. 5619 */ 5620 /* XXX need to set endianess and data ordering flags */ 5621 csx_DupHandle(imw->handle, &ior->BasePort1.handle, 0); 5622 csx_GetHandleOffset(ior->BasePort1.handle, &offset); 5623 csx_SetHandleOffset(ior->BasePort1.handle, 5624 ior->BasePort1.base + offset); 5625 5626 if (ior->NumPorts2) { 5627 /* XXX need to set endianess and data ordering flags */ 5628 csx_DupHandle(imw->handle, &ior->BasePort2.handle, 0); 5629 csx_GetHandleOffset(ior->BasePort2.handle, &offset); 5630 csx_SetHandleOffset(ior->BasePort2.handle, 5631 ior->BasePort1.base + offset); 5632 } 5633 5634 /* 5635 * We don't really use these two values if we've got a memory 5636 * mapped IO window since the assigned window number is stored 5637 * in imw->number. 5638 */ 5639 client->io_alloc.Window1 = imw->number; 5640 client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5641 5642 /* 5643 * This socket supports only IO port IO windows. 5644 */ 5645 } else { 5646 #else /* USE_IOMMAP_WINDOW */ 5647 { 5648 #endif /* USE_IOMMAP_WINDOW */ 5649 baseaddru_t baseaddru; 5650 5651 baseaddru.base = ior->BasePort1.base; 5652 5653 if ((error = cs_allocate_io_win(sp->socket_num, ior->Attributes1, 5654 &client->io_alloc.Window1)) != CS_SUCCESS) { 5655 5656 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5657 mutex_exit(&cs_globals.window_lock); 5658 return (error); 5659 } /* if (cs_allocate_io_win(1)) */ 5660 5661 /* 5662 * Setup the window hardware; if this fails, then we need to 5663 * deallocate the previously allocated window. 5664 */ 5665 if ((error = cs_setup_io_win(socket_num, 5666 client->io_alloc.Window1, 5667 &baseaddru, 5668 &ior->NumPorts1, 5669 ior->IOAddrLines, 5670 ior->Attributes1)) != 5671 CS_SUCCESS) { 5672 (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5673 NULL, NULL, NULL, 5674 ( 5675 IO_DEALLOCATE_WINDOW | 5676 IO_DISABLE_WINDOW)); 5677 5678 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5679 mutex_exit(&cs_globals.window_lock); 5680 return (error); 5681 } /* if (cs_setup_io_win(1)) */ 5682 5683 ior->BasePort1.handle = (acc_handle_t)baseaddru.handle; 5684 ior->BasePort1.base = baseaddru.base; 5685 5686 /* 5687 * See if the client wants two IO ranges. 5688 */ 5689 if (ior->NumPorts2) { 5690 baseaddru_t baseaddru; 5691 5692 baseaddru.base = ior->BasePort2.base; 5693 5694 /* 5695 * If we fail to allocate this window, then we must deallocate 5696 * the previous IO window that is already allocated. 5697 */ 5698 if ((error = cs_allocate_io_win(sp->socket_num, 5699 ior->Attributes2, 5700 &client->io_alloc.Window2)) != 5701 CS_SUCCESS) { 5702 (void) cs_setup_io_win(socket_num, 5703 client->io_alloc.Window2, 5704 NULL, NULL, NULL, 5705 ( 5706 IO_DEALLOCATE_WINDOW | 5707 IO_DISABLE_WINDOW)); 5708 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5709 mutex_exit(&cs_globals.window_lock); 5710 return (error); 5711 } /* if (cs_allocate_io_win(2)) */ 5712 /* 5713 * Setup the window hardware; if this fails, then we need to 5714 * deallocate the previously allocated window. 5715 */ 5716 if ((error = cs_setup_io_win(socket_num, 5717 client->io_alloc.Window2, 5718 &baseaddru, 5719 &ior->NumPorts2, 5720 ior->IOAddrLines, 5721 ior->Attributes2)) != 5722 CS_SUCCESS) { 5723 (void) cs_setup_io_win(socket_num, 5724 client->io_alloc.Window1, 5725 NULL, NULL, NULL, 5726 ( 5727 IO_DEALLOCATE_WINDOW | 5728 IO_DISABLE_WINDOW)); 5729 (void) cs_setup_io_win(socket_num, 5730 client->io_alloc.Window2, 5731 NULL, NULL, NULL, 5732 ( 5733 IO_DEALLOCATE_WINDOW | 5734 IO_DISABLE_WINDOW)); 5735 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5736 mutex_exit(&cs_globals.window_lock); 5737 return (error); 5738 } /* if (cs_setup_io_win(2)) */ 5739 5740 ior->BasePort2.handle = (acc_handle_t)baseaddru.handle; 5741 ior->BasePort2.base = baseaddru.base; 5742 5743 } else { 5744 client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5745 } /* if (ior->NumPorts2) */ 5746 } /* if (sp->io_mmap_window) */ 5747 5748 /* 5749 * Save a copy of the client's port information so that we 5750 * can use it in the RequestConfiguration call. We set 5751 * the IO window number(s) allocated in the respective 5752 * section of code, above. 5753 */ 5754 client->io_alloc.BasePort1.base = ior->BasePort1.base; 5755 client->io_alloc.BasePort1.handle = ior->BasePort1.handle; 5756 client->io_alloc.NumPorts1 = ior->NumPorts1; 5757 client->io_alloc.Attributes1 = ior->Attributes1; 5758 client->io_alloc.BasePort2.base = ior->BasePort2.base; 5759 client->io_alloc.BasePort2.handle = ior->BasePort2.handle; 5760 client->io_alloc.NumPorts2 = ior->NumPorts2; 5761 client->io_alloc.Attributes2 = ior->Attributes2; 5762 client->io_alloc.IOAddrLines = ior->IOAddrLines; 5763 5764 /* 5765 * Mark this client as having done a successful RequestIO call. 5766 */ 5767 client->flags |= (REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5768 5769 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5770 mutex_exit(&cs_globals.window_lock); 5771 5772 return (CS_SUCCESS); 5773 } 5774 5775 /* 5776 * cs_release_io - releases IO resources allocated by RequestIO; this is 5777 * ReleaseIO 5778 * 5779 * calling: cs_release_io(client_handle_t, io_req_t *) 5780 * 5781 * returns: CS_SUCCESS - if IO resources sucessfully deallocated 5782 * CS_BAD_HANDLE - client handle is invalid 5783 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5784 * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 5785 * done without a ReleaseConfiguration 5786 * CS_IN_USE - no RequestIO has been done 5787 */ 5788 static int 5789 cs_release_io(client_handle_t client_handle, io_req_t *ior) 5790 { 5791 cs_socket_t *sp; 5792 client_t *client; 5793 int error; 5794 int client_lock_acquired; 5795 uint32_t socket_num; 5796 5797 #ifdef lint 5798 ior = NULL; 5799 #endif 5800 5801 /* 5802 * Check to see if this is the Socket Services client handle; if it 5803 * is, we don't support SS using this call. 5804 */ 5805 if (CLIENT_HANDLE_IS_SS(client_handle)) 5806 return (CS_UNSUPPORTED_FUNCTION); 5807 5808 mutex_enter(&cs_globals.window_lock); 5809 5810 /* 5811 * Get a pointer to this client's socket structure. 5812 */ 5813 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5814 return (CS_BAD_SOCKET); 5815 5816 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5817 5818 /* 5819 * Make sure that this is a valid client handle. 5820 */ 5821 if (!(client = cs_find_client(client_handle, &error))) { 5822 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5823 mutex_exit(&cs_globals.window_lock); 5824 return (error); 5825 } 5826 5827 /* 5828 * If RequestConfiguration has already been done, we don't allow 5829 * this call. 5830 */ 5831 if (client->flags & REQ_CONFIGURATION_DONE) { 5832 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5833 mutex_exit(&cs_globals.window_lock); 5834 return (CS_CONFIGURATION_LOCKED); 5835 } 5836 5837 /* 5838 * If RequestIO has not been done, we don't allow this call. 5839 */ 5840 if (!(client->flags & REQ_IO_DONE)) { 5841 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5842 mutex_exit(&cs_globals.window_lock); 5843 return (CS_IN_USE); 5844 } 5845 5846 socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5847 GET_CLIENT_FUNCTION(client_handle)); 5848 5849 #ifdef XXX 5850 /* 5851 * Check the passed IO allocation with the stored allocation; if 5852 * they don't match, then return an error. 5853 */ 5854 if ((client->io_alloc.BasePort1 != ior->BasePort1) || 5855 (client->io_alloc.NumPorts1 != ior->NumPorts1) || 5856 (client->io_alloc.Attributes1 != ior->Attributes1) || 5857 (client->io_alloc.BasePort2 != ior->BasePort2) || 5858 (client->io_alloc.NumPorts2 != ior->NumPorts2) || 5859 (client->io_alloc.Attributes2 != ior->Attributes2) || 5860 (client->io_alloc.IOAddrLines != ior->IOAddrLines)) { 5861 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5862 mutex_exit(&cs_globals.window_lock); 5863 return (CS_BAD_ARGS); 5864 } 5865 #endif 5866 5867 #ifdef USE_IOMMAP_WINDOW 5868 /* 5869 * The code diverges here depending on if this socket supports 5870 * memory mapped IO windows or not. See comments in the 5871 * cs_request_io function for a description of what's 5872 * going on here. 5873 */ 5874 if (sp->io_mmap_window) { 5875 io_mmap_window_t *imw = sp->io_mmap_window; 5876 5877 /* 5878 * We should never see this; if we do, it's an internal 5879 * consistency error. 5880 */ 5881 if (!imw->count) { 5882 cmn_err(CE_CONT, "cs_release_io: socket %d !imw->count\n", 5883 sp->socket_num); 5884 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5885 mutex_exit(&cs_globals.window_lock); 5886 return (CS_GENERAL_FAILURE); 5887 } 5888 5889 /* 5890 * All common access handles for this type of adapter are 5891 * duped. We never give the original back to the caller, 5892 * so it's OK to unconditionally free the handle here. 5893 */ 5894 csx_FreeHandle(&ior->BasePort1.handle); 5895 5896 /* 5897 * If the IO window referance count is zero, then deallocate 5898 * and disable this window. 5899 */ 5900 if (!--(imw->count)) { 5901 (void) cs_setup_io_win(socket_num, imw->number, NULL, 5902 NULL, NULL, 5903 ( 5904 IO_DEALLOCATE_WINDOW | 5905 IO_DISABLE_WINDOW)); 5906 } /* if (imw->count) */ 5907 } else { 5908 #endif /* USE_IOMMAP_WINDOW */ 5909 (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5910 NULL, NULL, NULL, 5911 ( 5912 IO_DEALLOCATE_WINDOW | 5913 IO_DISABLE_WINDOW)); 5914 if (client->io_alloc.Window2 != PCMCIA_MAX_WINDOWS) 5915 (void) cs_setup_io_win(socket_num, client->io_alloc.Window2, 5916 NULL, NULL, NULL, 5917 ( 5918 IO_DEALLOCATE_WINDOW | 5919 IO_DISABLE_WINDOW)); 5920 #ifdef USE_IOMMAP_WINDOW 5921 } /* if (sp->io_mmap_window) */ 5922 #endif /* USE_IOMMAP_WINDOW */ 5923 5924 /* 5925 * Mark the client as not having any IO resources allocated. 5926 */ 5927 client->flags &= ~(REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5928 5929 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5930 mutex_exit(&cs_globals.window_lock); 5931 return (CS_SUCCESS); 5932 } 5933 5934 /* 5935 * cs_find_io_win - finds an IO window that matches the parameters specified 5936 * in the flags argument 5937 * 5938 * calling: sn - socket number to look for IO window on 5939 * *iwc - other window characteristics to match 5940 * *assigned_window - pointer to where we return the assigned 5941 * window number if we found a window or 5942 * undefined otherwise 5943 * *size - if non-NULL, the found window size will be stored here 5944 * 5945 * returns: CS_SUCCESS - if IO window found 5946 * CS_OUT_OF_RESOURCE - if no windows match requirements 5947 */ 5948 static int 5949 cs_find_io_win(uint32_t sn, iowin_char_t *iwc, uint32_t *assigned_window, 5950 uint32_t *size) 5951 { 5952 inquire_window_t inquire_window, *iw; 5953 unsigned wn; 5954 5955 iw = &inquire_window; 5956 5957 for (wn = 0; wn < cs_globals.num_windows; wn++) { 5958 iowin_char_t *iowc; 5959 cs_window_t *cw; 5960 5961 if ((cw = cs_get_wp(wn)) != NULL) { 5962 5963 iw->window = wn; 5964 SocketServices(SS_InquireWindow, iw); 5965 5966 iowc = &iw->iowin_char; 5967 5968 if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5969 WINDOW_AVAILABLE_FOR_IO(cw) && 5970 (iw->WndCaps & WC_IO) && 5971 ((iowc->IOWndCaps & iwc->IOWndCaps) == iwc->IOWndCaps)) { 5972 5973 *assigned_window = wn; 5974 5975 if (size) 5976 *size = iw->iowin_char.ReqGran; 5977 return (CS_SUCCESS); 5978 } /* if (WINDOW_FOR_SOCKET) */ 5979 } /* cs_get_wp */ 5980 } /* for (wn) */ 5981 5982 return (CS_OUT_OF_RESOURCE); 5983 } 5984 5985 /* 5986 * cs_allocate_io_win - finds and allocates an IO window 5987 * 5988 * calling: sn - socket number to look for window on 5989 * Attributes - window attributes in io_req_t.Attributes format 5990 * *assigned_window - pointer to return assigned window number 5991 * 5992 * returns: CS_SUCCESS - IO window found and allocated 5993 * CS_OUT_OF_RESOURCE - if cs_find_io_win couldn't find a 5994 * window that matches the passed criteria 5995 * 5996 * Note: This fucntion will find and allocate an IO window. The caller is 5997 * responsible for deallocating the window. 5998 */ 5999 static int 6000 cs_allocate_io_win(uint32_t sn, uint32_t Attributes, uint32_t *assigned_window) 6001 { 6002 iowin_char_t iowin_char; 6003 cs_window_t *cw; 6004 6005 iowin_char.IOWndCaps = 6006 ((Attributes & IO_DATA_PATH_WIDTH_16)?WC_16BIT:WC_8BIT); 6007 6008 if (cs_find_io_win(sn, &iowin_char, assigned_window, NULL) == 6009 CS_SUCCESS) { 6010 if ((cw = cs_get_wp(*assigned_window)) == NULL) 6011 return (CS_OUT_OF_RESOURCE); 6012 6013 cw->state = (cw->state & CW_WINDOW_VALID) | (CW_ALLOCATED | CW_IO); 6014 return (CS_SUCCESS); 6015 } 6016 6017 return (CS_OUT_OF_RESOURCE); 6018 } 6019 6020 /* 6021 * cs_setup_io_win - setup and destroy an IO window 6022 * 6023 * calling: sn - socket number 6024 * wn - window number 6025 * XXX Base - pointer to XXX 6026 * *NumPorts - pointer to number of allocated ports to return 6027 * IOAddrLines - number of IO address lines decoded by this card 6028 * Attributes - either io_req_t attributes, or a combination of 6029 * the following flags: 6030 * IO_DEALLOCATE_WINDOW - deallocate the window 6031 * IO_DISABLE_WINDOW - disable the window 6032 * When either of these two flags are set, *Base 6033 * and NumPorts should be NULL. 6034 * 6035 * returns: CS_SUCCESS - if no failure 6036 * CS_BAD_WINDOW - if error while trying to configure window 6037 * 6038 * Note: We use the IOAddrLines value to determine what base address to pass 6039 * to Socket Services. 6040 */ 6041 static int 6042 cs_setup_io_win(uint32_t sn, uint32_t wn, baseaddru_t *Base, uint32_t *NumPorts, 6043 uint32_t IOAddrLines, uint32_t Attributes) 6044 { 6045 set_window_t set_window; 6046 6047 if (Attributes & (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW)) { 6048 6049 if (Attributes & IO_DEALLOCATE_WINDOW) { 6050 cs_window_t *cw; 6051 6052 if ((cw = cs_get_wp(wn)) == NULL) 6053 return (CS_BAD_WINDOW); 6054 cw->state &= CW_WINDOW_VALID; 6055 6056 } /* IO_DEALLOCATE_WINDOW */ 6057 6058 if (Attributes & IO_DISABLE_WINDOW) { 6059 get_window_t get_window; 6060 6061 get_window.window = wn; 6062 6063 SocketServices(SS_GetWindow, &get_window); 6064 6065 set_window.socket = get_window.socket; 6066 set_window.window = get_window.window; 6067 set_window.speed = get_window.speed; 6068 set_window.base = 0; 6069 set_window.WindowSize = get_window.size; 6070 set_window.state = get_window.state & ~WS_ENABLED; 6071 6072 cs_set_acc_attributes(&set_window, Attributes); 6073 6074 SocketServices(SS_SetWindow, &set_window); 6075 } /* IO_DISABLE_WINDOW */ 6076 6077 return (CS_SUCCESS); 6078 6079 } /* if (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW) */ 6080 6081 /* 6082 * See if we can allow Socket Services to select the base address 6083 * value for this card; if the client has specified a non-zero 6084 * base IO address but the card doesn't decode enough IO 6085 * address lines to uniquely use that address, then we have 6086 * the flexibility to choose an alternative base address. 6087 * XXX - Is this really correct in all cases? 6088 */ 6089 if (!IOAddrLines) 6090 Base->base = 0; 6091 else 6092 Base->base = IOADDR_FROBNITZ(Base->base, IOAddrLines); 6093 6094 set_window.socket = sn; 6095 set_window.window = wn; 6096 set_window.speed = IO_WIN_SPEED; 6097 set_window.base = Base->base; 6098 set_window.WindowSize = *NumPorts; 6099 set_window.state = (WS_ENABLED | WS_IO | 6100 ((Attributes & IO_DATA_PATH_WIDTH_16)?WS_16BIT:0)); 6101 6102 cs_set_acc_attributes(&set_window, Attributes); 6103 6104 if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) 6105 return (CS_BAD_WINDOW); 6106 6107 Base->base = set_window.base; 6108 Base->handle = set_window.handle; 6109 *NumPorts = set_window.WindowSize; 6110 6111 return (CS_SUCCESS); 6112 } 6113 6114 /* 6115 * ==== IRQ handling functions ==== 6116 */ 6117 6118 /* 6119 * cs_request_irq - add's client's IRQ handler; supports RequestIRQ 6120 * 6121 * calling: irq_req_t.Attributes - must have the IRQ_TYPE_EXCLUSIVE 6122 * flag set, and all other flags clear, or 6123 * CS_BAD_ATTRIBUTE will be returned 6124 * 6125 * returns: CS_SUCCESS - if IRQ resources available for client 6126 * CS_BAD_IRQ - if IRQ can not be allocated 6127 * CS_BAD_HANDLE - client handle is invalid 6128 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6129 * CS_NO_CARD - if no card is in socket 6130 * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 6131 * flags are set 6132 * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6133 * already been done 6134 * CS_IN_USE - IRQ ports already in use or function has 6135 * already been called 6136 * 6137 * Note: We only allow level-mode interrupts. 6138 */ 6139 static int 6140 cs_request_irq(client_handle_t client_handle, irq_req_t *irqr) 6141 { 6142 cs_socket_t *sp; 6143 client_t *client; 6144 set_irq_handler_t set_irq_handler; 6145 int error; 6146 int client_lock_acquired; 6147 6148 /* 6149 * Check to see if this is the Socket Services client handle; if it 6150 * is, we don't support SS using this call. 6151 */ 6152 if (CLIENT_HANDLE_IS_SS(client_handle)) 6153 return (CS_UNSUPPORTED_FUNCTION); 6154 6155 /* 6156 * Make sure that none of the unsupported or reserved flags are set. 6157 */ 6158 if ((irqr->Attributes & (IRQ_TYPE_TIME | IRQ_TYPE_DYNAMIC_SHARING | 6159 IRQ_FIRST_SHARED | IRQ_PULSE_ALLOCATED | 6160 IRQ_FORCED_PULSE)) || 6161 !(irqr->Attributes & IRQ_TYPE_EXCLUSIVE)) 6162 return (CS_BAD_ATTRIBUTE); 6163 6164 /* 6165 * Get a pointer to this client's socket structure. 6166 */ 6167 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6168 return (CS_BAD_SOCKET); 6169 6170 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6171 6172 /* 6173 * Make sure that this is a valid client handle. 6174 */ 6175 if (!(client = cs_find_client(client_handle, &error))) { 6176 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6177 return (error); 6178 } 6179 6180 /* 6181 * If RequestConfiguration has already been done, we don't allow 6182 * this call. 6183 */ 6184 if (client->flags & REQ_CONFIGURATION_DONE) { 6185 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6186 return (CS_CONFIGURATION_LOCKED); 6187 } 6188 6189 /* 6190 * If RequestIRQ has already been done, we don't allow this call. 6191 */ 6192 if (client->flags & REQ_IRQ_DONE) { 6193 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6194 return (CS_IN_USE); 6195 } 6196 6197 /* 6198 * If there's no card in the socket or the card in the socket is not 6199 * for this client, then return an error. 6200 */ 6201 if (!(client->flags & CLIENT_CARD_INSERTED)) { 6202 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6203 return (CS_NO_CARD); 6204 } 6205 6206 /* 6207 * Set up the parameters and ask Socket Services to give us an IRQ 6208 * for this client. We don't really do much, since the IRQ 6209 * resources are managed by SS and the kernel. We also don't 6210 * care which IRQ level we are given. 6211 */ 6212 set_irq_handler.socket = 6213 CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6214 GET_CLIENT_FUNCTION(client_handle)); 6215 set_irq_handler.irq = IRQ_ANY; 6216 6217 set_irq_handler.handler_id = client_handle; 6218 set_irq_handler.handler = (f_t *)irqr->irq_handler; 6219 set_irq_handler.arg1 = irqr->irq_handler_arg; 6220 set_irq_handler.arg2 = NULL; 6221 6222 if ((error = SocketServices(SS_SetIRQHandler, 6223 &set_irq_handler)) != SUCCESS) { 6224 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6225 return (CS_BAD_IRQ); 6226 } 6227 6228 irqr->iblk_cookie = set_irq_handler.iblk_cookie; 6229 irqr->idev_cookie = set_irq_handler.idev_cookie; 6230 6231 /* 6232 * Save the allocated IRQ information for this client. 6233 */ 6234 client->irq_alloc.Attributes = irqr->Attributes; 6235 client->irq_alloc.irq = set_irq_handler.irq; 6236 client->irq_alloc.handler_id = set_irq_handler.handler_id; 6237 client->irq_alloc.irq_handler = (f_t *)set_irq_handler.handler; 6238 client->irq_alloc.irq_handler_arg1 = set_irq_handler.arg1; 6239 client->irq_alloc.irq_handler_arg2 = set_irq_handler.arg2; 6240 6241 #ifdef CS_DEBUG 6242 if (cs_debug > 0) 6243 cmn_err(CE_CONT, "cs_request_irq: socket %d irqr->Attributes 0x%x " 6244 "set_irq_handler.irq 0x%x\n", 6245 sp->socket_num, 6246 (int)irqr->Attributes, 6247 set_irq_handler.irq); 6248 #endif 6249 6250 /* 6251 * Mark this client as having done a successful RequestIRQ call. 6252 */ 6253 client->flags |= (REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6254 6255 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6256 return (CS_SUCCESS); 6257 } 6258 6259 /* 6260 * cs_release_irq - releases IRQ resources allocated by RequestIRQ; this is 6261 * ReleaseIRQ 6262 * 6263 * calling: cs_release_irq(client_handle_t, irq_req_t *) 6264 * 6265 * returns: CS_SUCCESS - if IRQ resources sucessfully deallocated 6266 * CS_BAD_IRQ - if IRQ can not be deallocated 6267 * CS_BAD_HANDLE - client handle is invalid 6268 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6269 * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 6270 * done without a ReleaseConfiguration 6271 * CS_IN_USE - no RequestIRQ has been done 6272 */ 6273 static int 6274 cs_release_irq(client_handle_t client_handle, irq_req_t *irqr) 6275 { 6276 cs_socket_t *sp; 6277 client_t *client; 6278 clear_irq_handler_t clear_irq_handler; 6279 int error; 6280 int client_lock_acquired; 6281 6282 #ifdef lint 6283 irqr = NULL; 6284 #endif 6285 6286 /* 6287 * Check to see if this is the Socket Services client handle; if it 6288 * is, we don't support SS using this call. 6289 */ 6290 if (CLIENT_HANDLE_IS_SS(client_handle)) 6291 return (CS_UNSUPPORTED_FUNCTION); 6292 6293 /* 6294 * Get a pointer to this client's socket structure. 6295 */ 6296 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6297 return (CS_BAD_SOCKET); 6298 6299 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6300 6301 /* 6302 * Make sure that this is a valid client handle. 6303 */ 6304 if (!(client = cs_find_client(client_handle, &error))) { 6305 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6306 return (error); 6307 } 6308 6309 /* 6310 * If RequestConfiguration has already been done, we don't allow 6311 * this call. 6312 */ 6313 if (client->flags & REQ_CONFIGURATION_DONE) { 6314 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6315 return (CS_CONFIGURATION_LOCKED); 6316 } 6317 6318 /* 6319 * If RequestIRQ has not been done, we don't allow this call. 6320 */ 6321 if (!(client->flags & REQ_IRQ_DONE)) { 6322 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6323 return (CS_IN_USE); 6324 } 6325 6326 /* 6327 * Tell Socket Services that we want to deregister this client's 6328 * IRQ handler. 6329 */ 6330 clear_irq_handler.socket = 6331 CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6332 GET_CLIENT_FUNCTION(client_handle)); 6333 clear_irq_handler.handler_id = client->irq_alloc.handler_id; 6334 clear_irq_handler.handler = (f_t *)client->irq_alloc.irq_handler; 6335 6336 /* 6337 * At this point, we should never fail this SS call; if we do, it 6338 * means that there is an internal consistancy error in either 6339 * Card Services or Socket Services. 6340 */ 6341 if ((error = SocketServices(SS_ClearIRQHandler, &clear_irq_handler)) != 6342 SUCCESS) { 6343 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6344 return (CS_BAD_IRQ); 6345 } 6346 6347 /* 6348 * Mark the client as not having any IRQ resources allocated. 6349 */ 6350 client->flags &= ~(REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6351 6352 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6353 return (CS_SUCCESS); 6354 } 6355 6356 /* 6357 * ==== configuration handling functions ==== 6358 */ 6359 6360 /* 6361 * cs_request_configuration - sets up socket and card configuration on behalf 6362 * of the client; this is RequestConfiguration 6363 * 6364 * returns: CS_SUCCESS - if configuration sucessfully set 6365 * CS_BAD_SOCKET - if Socket Services returns an error 6366 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6367 * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6368 * are set 6369 * CS_BAD_TYPE - if the socket doesn't support a mem and IO 6370 * interface (SOCKET_INTERFACE_MEMORY_AND_IO set) 6371 * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6372 * already been done 6373 * CS_BAD_VCC - if Vcc value is not supported by socket 6374 * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6375 * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6376 * 6377 * Bug ID: 1193637 - Card Services RequestConfiguration does not conform 6378 * to PCMCIA standard 6379 * We allow clients to do a RequestConfiguration even if they haven't 6380 * done a RequestIO or RequestIRQ. 6381 */ 6382 static int 6383 cs_request_configuration(client_handle_t client_handle, config_req_t *cr) 6384 { 6385 cs_socket_t *sp; 6386 client_t *client; 6387 volatile config_regs_t *crt; 6388 set_socket_t set_socket; 6389 get_socket_t get_socket; 6390 acc_handle_t cis_handle; 6391 int error; 6392 uint32_t newoffset; 6393 int client_lock_acquired; 6394 6395 /* 6396 * Check to see if this is the Socket Services client handle; if it 6397 * is, we don't support SS using this call. 6398 */ 6399 if (CLIENT_HANDLE_IS_SS(client_handle)) 6400 return (CS_UNSUPPORTED_FUNCTION); 6401 6402 #ifdef XXX 6403 /* 6404 * If the client specifies Vcc = 0 and any non-zero value for 6405 * either of the Vpp members, that's an illegal condition. 6406 */ 6407 if (!(cr->Vcc) && (cr->Vpp1 || cr->Vpp2)) 6408 return (CS_BAD_VCC); 6409 #endif 6410 6411 /* 6412 * Get a pointer to this client's socket structure. 6413 */ 6414 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6415 return (CS_BAD_SOCKET); 6416 6417 /* 6418 * If the client is asking for a memory and IO interface on this 6419 * socket, then check the socket capabilities to be sure that 6420 * this socket supports this configuration. 6421 */ 6422 if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) { 6423 inquire_socket_t inquire_socket; 6424 6425 inquire_socket.socket = sp->socket_num; 6426 6427 if (SocketServices(SS_InquireSocket, &inquire_socket) != SUCCESS) 6428 return (CS_BAD_SOCKET); 6429 6430 if (!(inquire_socket.SocketCaps & IF_IO)) 6431 return (CS_BAD_TYPE); 6432 6433 } /* if (SOCKET_INTERFACE_MEMORY_AND_IO) */ 6434 6435 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6436 6437 /* 6438 * Make sure that this is a valid client handle. 6439 */ 6440 if (!(client = cs_find_client(client_handle, &error))) { 6441 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6442 return (error); 6443 } 6444 6445 /* 6446 * If RequestConfiguration has already been done, we don't allow 6447 * this call. 6448 */ 6449 if (client->flags & REQ_CONFIGURATION_DONE) { 6450 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6451 return (CS_CONFIGURATION_LOCKED); 6452 } 6453 6454 /* 6455 * If there's no card in the socket or the card in the socket is not 6456 * for this client, then return an error. 6457 */ 6458 if (!(client->flags & CLIENT_CARD_INSERTED)) { 6459 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6460 return (CS_NO_CARD); 6461 } 6462 6463 /* 6464 * At this point, most of the client's calling parameters have been 6465 * validated, so we can go ahead and configure the socket and 6466 * the card. 6467 */ 6468 mutex_enter(&sp->cis_lock); 6469 6470 /* 6471 * Configure the socket with the interface type and voltages requested 6472 * by the client. 6473 */ 6474 get_socket.socket = sp->socket_num; 6475 6476 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6477 mutex_exit(&sp->cis_lock); 6478 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6479 return (CS_BAD_SOCKET); 6480 } 6481 6482 #ifdef CS_DEBUG 6483 if (cs_debug > 0) 6484 cmn_err(CE_CONT, "cs_request_configuration: socket %d " 6485 "client->irq_alloc.irq 0x%x " 6486 "get_socket.IRQRouting 0x%x\n", 6487 sp->socket_num, 6488 (int)client->irq_alloc.irq, 6489 get_socket.IRQRouting); 6490 #endif 6491 6492 bzero(&set_socket, sizeof (set_socket)); 6493 set_socket.socket = sp->socket_num; 6494 set_socket.IREQRouting = client->irq_alloc.irq & ~IRQ_ENABLE; 6495 6496 set_socket.CtlInd = get_socket.CtlInd; 6497 set_socket.State = 0; /* don't reset latched values */ 6498 6499 if (cs_convert_powerlevel(sp->socket_num, cr->Vcc, VCC, 6500 &set_socket.VccLevel) != CS_SUCCESS) { 6501 mutex_exit(&sp->cis_lock); 6502 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6503 return (CS_BAD_VCC); 6504 } 6505 6506 if (cs_convert_powerlevel(sp->socket_num, cr->Vpp1, VPP1, 6507 &set_socket.Vpp1Level) != CS_SUCCESS) { 6508 mutex_exit(&sp->cis_lock); 6509 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6510 return (CS_BAD_VPP); 6511 } 6512 6513 if (cs_convert_powerlevel(sp->socket_num, cr->Vpp2, VPP2, 6514 &set_socket.Vpp2Level) != CS_SUCCESS) { 6515 mutex_exit(&sp->cis_lock); 6516 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6517 return (CS_BAD_VPP); 6518 } 6519 6520 if (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) 6521 set_socket.IFType = IF_MEMORY; 6522 else { 6523 set_socket.IFType = IF_IO; 6524 6525 /* 6526 * The Cirrus Logic PD6710/672X/others? adapters will write 6527 * protect the CIS if the socket is in MEMORY mode and the 6528 * WP/IOCS16 pin is true. When this happens, the CIS registers 6529 * will fail to be written. Go ahead and set the socket, 6530 * even though the event mask isn't complete yet, so we can 6531 * configure the adapter. Afterwards, set the socket again 6532 * to make sure the event mask is correct. 6533 */ 6534 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6535 sp->flags &= ~SOCKET_IS_IO; 6536 mutex_exit(&sp->cis_lock); 6537 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6538 return (CS_BAD_SOCKET); 6539 } 6540 } 6541 6542 if (cs_rc2_delay) 6543 drv_usecwait(cs_rc2_delay * 1000); 6544 6545 /* 6546 * Get a pointer to a window that contains the configuration 6547 * registers. 6548 */ 6549 mutex_enter(&sp->lock); 6550 client->config_regs_offset = cr->ConfigBase; 6551 newoffset = client->config_regs_offset; 6552 mutex_exit(&sp->lock); 6553 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6554 CISTPLF_AM_SPACE) != CS_SUCCESS) { 6555 mutex_exit(&sp->cis_lock); 6556 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6557 cmn_err(CE_CONT, "cs_request_configuration: socket %d can't init " 6558 "CIS window\n", sp->socket_num); 6559 return (CS_GENERAL_FAILURE); 6560 } 6561 6562 /* 6563 * Setup the config register pointers. 6564 * Note that these pointers are not the complete virtual address; 6565 * the complete address is constructed each time the registers 6566 * are accessed. 6567 */ 6568 mutex_enter(&sp->lock); 6569 crt = &client->config_regs; 6570 client->present = cr->Present; 6571 6572 bzero((char *)crt, sizeof (config_regs_t)); 6573 6574 /* Configuration Option Register */ 6575 if (client->present & CONFIG_OPTION_REG_PRESENT) 6576 crt->cor_p = (newoffset + CONFIG_OPTION_REG_OFFSET); 6577 6578 /* Configuration and Status Register */ 6579 if (client->present & CONFIG_STATUS_REG_PRESENT) 6580 crt->ccsr_p = (newoffset + CONFIG_STATUS_REG_OFFSET); 6581 6582 /* Pin Replacement Register */ 6583 if (client->present & CONFIG_PINREPL_REG_PRESENT) 6584 crt->prr_p = (newoffset + CONFIG_PINREPL_REG_OFFSET); 6585 6586 /* Socket and Copy Register */ 6587 if (client->present & CONFIG_COPY_REG_PRESENT) 6588 crt->scr_p = (newoffset + CONFIG_COPY_REG_OFFSET); 6589 6590 /* Extended Status Register */ 6591 if (client->present & CONFIG_EXSTAT_REG_PRESENT) 6592 crt->exstat_p = (newoffset + CONFIG_EXSTAT_REG_OFFSET); 6593 6594 /* IO Base 0 Register */ 6595 if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6596 crt->iobase0_p = (newoffset + CONFIG_IOBASE0_REG_OFFSET); 6597 6598 /* IO Base 1 Register */ 6599 if (client->present & CONFIG_IOBASE1_REG_PRESENT) 6600 crt->iobase1_p = (newoffset + CONFIG_IOBASE1_REG_OFFSET); 6601 6602 /* IO Base 2 Register */ 6603 if (client->present & CONFIG_IOBASE2_REG_PRESENT) 6604 crt->iobase2_p = (newoffset + CONFIG_IOBASE2_REG_OFFSET); 6605 6606 /* IO Base 3 Register */ 6607 if (client->present & CONFIG_IOBASE3_REG_PRESENT) 6608 crt->iobase3_p = (newoffset + CONFIG_IOBASE3_REG_OFFSET); 6609 6610 /* IO Limit Register */ 6611 if (client->present & CONFIG_IOLIMIT_REG_PRESENT) 6612 crt->iolimit_p = (newoffset + CONFIG_IOLIMIT_REG_OFFSET); 6613 6614 /* 6615 * Setup the bits in the PRR mask that are valid; this is easy, just 6616 * copy the Pin value that the client gave us. Note that for 6617 * this to work, the client must set both of the XXX_STATUS 6618 * and the XXX_EVENT bits in the Pin member. 6619 */ 6620 client->pin = cr->Pin; 6621 6622 #ifdef CS_DEBUG 6623 if (cs_debug > 128) 6624 cmn_err(CE_CONT, "cs_request_configuration: client->pin 0x%x " 6625 "client->config_regs_offset 0x%x newoffset 0x%x cor_p 0x%x " 6626 "ccsr_p 0x%x prr_p 0x%x scr_p 0x%x\n", 6627 client->pin, (int)client->config_regs_offset, newoffset, 6628 (int)crt->cor_p, (int)crt->ccsr_p, (int)crt->prr_p, 6629 (int)crt->scr_p); 6630 #endif 6631 6632 /* 6633 * If the socket isn't in IO mode, WP is asserted, and we're going to 6634 * write any of the config registers, issue a warning. 6635 */ 6636 if ((client->present != 0) && 6637 (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) && 6638 (get_socket.state & SBM_WP)) { 6639 cmn_err(CE_NOTE, "!cs_request_configuration: attempting to " 6640 "write CIS config regs with WP set\n"); 6641 } 6642 6643 /* 6644 * Write any configuration registers that the client tells us are 6645 * present to the card; save a copy of what we wrote so that we 6646 * can return them if the client calls GetConfigurationInfo. 6647 * The order in which we write the configuration registers is 6648 * specified by the PCMCIA spec; we must write the socket/copy 6649 * register first (if it exists), and then we can write the 6650 * registers in any arbitrary order. 6651 */ 6652 /* Socket and Copy Register */ 6653 if (client->present & CONFIG_COPY_REG_PRESENT) { 6654 crt->scr = cr->Copy; 6655 csx_Put8(cis_handle, crt->scr_p, crt->scr); 6656 } 6657 6658 /* Pin Replacement Register */ 6659 if (client->present & CONFIG_PINREPL_REG_PRESENT) { 6660 crt->prr = cr->Pin; 6661 csx_Put8(cis_handle, crt->prr_p, crt->prr); 6662 } 6663 6664 /* Configuration and Status Register */ 6665 /* XXX should we set CCSR_SIG_CHG in the CCSR? XXX */ 6666 if (client->present & CONFIG_STATUS_REG_PRESENT) { 6667 crt->ccsr = cr->Status; 6668 csx_Put8(cis_handle, crt->ccsr_p, crt->ccsr); 6669 } 6670 6671 /* Extended Status Register */ 6672 if (client->present & CONFIG_EXSTAT_REG_PRESENT) { 6673 crt->exstat = cr->ExtendedStatus; 6674 csx_Put8(cis_handle, crt->exstat_p, crt->exstat); 6675 } 6676 6677 /* 6678 * If any IO base and limit registers exist, and this client 6679 * has done a RequestIO, setup the IO Base and IO Limit 6680 * registers. 6681 */ 6682 if (client->flags & REQ_IO_DONE) { 6683 if (client->present & CONFIG_IOBASE0_REG_PRESENT) { 6684 uint32_t base = client->io_alloc.BasePort1.base; 6685 uint32_t present = (client->present & 6686 CONFIG_IOBASE_REG_MASK) >> 6687 CONFIG_IOBASE_REG_SHIFT; 6688 uint32_t reg = crt->iobase0_p; 6689 6690 do { 6691 csx_Put8(cis_handle, reg, base & 0x0ff); 6692 reg = reg + 2; 6693 base = base >> 8; 6694 present = present >> 1; 6695 } while (present); 6696 } /* CONFIG_IOBASE0_REG_PRESENT */ 6697 6698 if (client->present & CONFIG_IOLIMIT_REG_PRESENT) { 6699 uint32_t np = client->io_alloc.NumPorts1 + 6700 client->io_alloc.NumPorts2; 6701 uint32_t limit, do_bit = 0; 6702 int lm; 6703 6704 limit = (IONUMPORTS_FROBNITZ(np) - 1); 6705 6706 for (lm = 7; lm >= 0; lm--) { 6707 if (limit & (1 << lm)) 6708 do_bit = 1; 6709 if (do_bit) 6710 limit |= (1 << lm); 6711 } /* for */ 6712 6713 csx_Put8(cis_handle, crt->iolimit_p, limit); 6714 } /* CONFIG_IOLIMIT_REG_PRESENT */ 6715 } /* REQ_IO_DONE */ 6716 6717 /* 6718 * Mark the socket as being in IO mode. 6719 */ 6720 if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) 6721 sp->flags |= SOCKET_IS_IO; 6722 6723 mutex_exit(&sp->lock); 6724 6725 /* 6726 * Enable the interrupt if needed 6727 */ 6728 if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6729 set_socket.IREQRouting |= IRQ_ENABLE; 6730 6731 /* 6732 * Now that we know if the PRR is present and if it is, which 6733 * bits in the PRR are valid, we can construct the correct 6734 * socket event mask. 6735 */ 6736 set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6737 6738 /* 6739 * Configuration Option Register - we handle this specially since 6740 * we don't allow the client to manipulate the RESET or 6741 * INTERRUPT bits (although a client can manipulate these 6742 * bits via an AccessConfigurationRegister call - explain 6743 * THAT logic to me). 6744 * XXX - we force level-mode interrupts (COR_LEVEL_IRQ) 6745 * XXX - we always enable the function on a multi-function card 6746 */ 6747 if (client->present & CONFIG_OPTION_REG_PRESENT) { 6748 crt->cor = (cr->ConfigIndex & ~COR_SOFT_RESET) | COR_LEVEL_IRQ; 6749 if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6750 crt->cor |= COR_ENABLE_BASE_LIMIT; 6751 if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6752 crt->cor |= COR_ENABLE_FUNCTION; 6753 crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 6754 if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6755 crt->cor |= COR_ENABLE_IREQ_ROUTING; 6756 } /* CW_MULTI_FUNCTION_CIS */ 6757 6758 #ifdef CS_DEBUG 6759 if (cs_debug > 0) 6760 cmn_err(CE_CONT, "cs_request_configuration " 6761 "cor=x%x ConfigIndex=x%x Attributes=x%x flags=x%x\n" 6762 "present=x%x cis_handle=%p cor_p=x%x\n", 6763 crt->cor, cr->ConfigIndex, cr->Attributes, sp->cis_flags, 6764 client->present, cis_handle, crt->cor_p); 6765 #endif 6766 6767 csx_Put8(cis_handle, crt->cor_p, crt->cor); 6768 } /* CONFIG_OPTION_REG_PRESENT */ 6769 6770 if (cs_rc1_delay) 6771 drv_usecwait(cs_rc1_delay * 1000); 6772 6773 /* 6774 * Set the socket to the parameters that the client requested. 6775 */ 6776 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6777 if (client->present & CONFIG_OPTION_REG_PRESENT) { 6778 crt->cor = 0; /* XXX is 0 the right thing here? */ 6779 csx_Put8(cis_handle, crt->cor_p, crt->cor); 6780 } 6781 sp->flags &= ~SOCKET_IS_IO; 6782 mutex_exit(&sp->cis_lock); 6783 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6784 return (CS_BAD_SOCKET); 6785 } 6786 6787 if (cs_rc2_delay) 6788 drv_usecwait(cs_rc2_delay * 1000); 6789 6790 /* 6791 * Mark this client as having done a successful RequestConfiguration 6792 * call. 6793 */ 6794 client->flags |= REQ_CONFIGURATION_DONE; 6795 6796 mutex_exit(&sp->cis_lock); 6797 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6798 6799 return (CS_SUCCESS); 6800 } 6801 6802 /* 6803 * cs_release_configuration - releases configuration previously set via the 6804 * RequestConfiguration call; this is ReleaseConfiguration 6805 * 6806 * returns: CS_SUCCESS - if configuration sucessfully released 6807 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6808 * CS_BAD_SOCKET - if Socket Services returns an error 6809 * CS_BAD_HANDLE - a RequestConfiguration has not been done 6810 */ 6811 /*ARGSUSED*/ 6812 static int 6813 cs_release_configuration(client_handle_t client_handle, release_config_t *rcfg) 6814 { 6815 cs_socket_t *sp; 6816 client_t *client; 6817 volatile config_regs_t *crt; 6818 set_socket_t set_socket; 6819 get_socket_t get_socket; 6820 acc_handle_t cis_handle; 6821 int error; 6822 uint32_t newoffset; 6823 int client_lock_acquired; 6824 6825 /* 6826 * Check to see if this is the Socket Services client handle; if it 6827 * is, we don't support SS using this call. 6828 */ 6829 if (CLIENT_HANDLE_IS_SS(client_handle)) 6830 return (CS_UNSUPPORTED_FUNCTION); 6831 6832 /* 6833 * Get a pointer to this client's socket structure. 6834 */ 6835 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6836 return (CS_BAD_SOCKET); 6837 6838 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6839 6840 /* 6841 * Make sure that this is a valid client handle. 6842 */ 6843 if (!(client = cs_find_client(client_handle, &error))) { 6844 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6845 return (error); 6846 } 6847 6848 /* 6849 * If RequestConfiguration has not been done, we don't allow 6850 * this call. 6851 */ 6852 if (!(client->flags & REQ_CONFIGURATION_DONE)) { 6853 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6854 return (CS_BAD_HANDLE); 6855 } 6856 6857 #ifdef CS_DEBUG 6858 if (cs_debug > 0) 6859 cmn_err(CE_CONT, "cs_release_configuration: " 6860 "flags=0x%x CW_MULTI_FUNCTION_CIS =0x%x \n", 6861 sp->cis_flags, CW_MULTI_FUNCTION_CIS); 6862 6863 #endif 6864 mutex_enter(&sp->cis_lock); 6865 6866 /* 6867 * Set the card back to a memory-only interface byte writing a zero 6868 * to the COR. Note that we don't update our soft copy of the 6869 * COR state since the PCMCIA spec only requires us to maintain 6870 * the last value that was written to that register during a 6871 * call to RequestConfiguration. 6872 */ 6873 crt = &client->config_regs; 6874 6875 newoffset = client->config_regs_offset; 6876 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6877 CISTPLF_AM_SPACE) != CS_SUCCESS) { 6878 mutex_exit(&sp->cis_lock); 6879 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6880 cmn_err(CE_CONT, "cs_release_configuration: socket %d can't init " 6881 "CIS window\n", sp->socket_num); 6882 return (CS_GENERAL_FAILURE); 6883 } 6884 6885 if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6886 /* 6887 * For the Multifunction cards do not reset the socket 6888 * to a memory only interface but do clear the 6889 * Configuration Option Register and mark this client 6890 * as not having a configuration by clearing the 6891 * REQ_CONFIGURATION_DONE flag. 6892 */ 6893 client->flags &= ~REQ_CONFIGURATION_DONE; 6894 csx_Put8(cis_handle, crt->cor_p, 0); 6895 6896 mutex_exit(&sp->cis_lock); 6897 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6898 return (CS_SUCCESS); 6899 } 6900 6901 /* 6902 * Set the socket back to a memory-only interface; don't change 6903 * any other parameter of the socket. 6904 */ 6905 get_socket.socket = sp->socket_num; 6906 6907 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6908 mutex_exit(&sp->cis_lock); 6909 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6910 return (CS_BAD_SOCKET); 6911 } 6912 6913 mutex_enter(&sp->lock); 6914 sp->flags &= ~SOCKET_IS_IO; 6915 set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6916 mutex_exit(&sp->lock); 6917 6918 set_socket.socket = sp->socket_num; 6919 set_socket.IREQRouting = 0; 6920 set_socket.CtlInd = get_socket.CtlInd; 6921 set_socket.State = 0; /* don't reset latched values */ 6922 set_socket.VccLevel = get_socket.VccLevel; 6923 set_socket.Vpp1Level = get_socket.Vpp1Level; 6924 set_socket.Vpp2Level = get_socket.Vpp2Level; 6925 set_socket.IFType = IF_MEMORY; 6926 6927 if (client->present & CONFIG_OPTION_REG_PRESENT) 6928 csx_Put8(cis_handle, crt->cor_p, 0); 6929 6930 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6931 mutex_exit(&sp->cis_lock); 6932 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6933 return (CS_BAD_SOCKET); 6934 } 6935 6936 /* 6937 * Mark this client as not having a configuration. 6938 */ 6939 client->flags &= ~REQ_CONFIGURATION_DONE; 6940 6941 mutex_exit(&sp->cis_lock); 6942 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6943 6944 return (CS_SUCCESS); 6945 } 6946 6947 /* 6948 * cs_modify_configuration - modifies a configuration established by 6949 * RequestConfiguration; this is ModifyConfiguration 6950 * 6951 * returns: CS_SUCCESS - if configuration sucessfully modified 6952 * CS_BAD_SOCKET - if Socket Services returns an error 6953 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6954 * CS_BAD_HANDLE - a RequestConfiguration has not been done 6955 * CS_NO_CARD - if no card in socket 6956 * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6957 * are set 6958 * CS_BAD_VCC - if Vcc value is not supported by socket 6959 * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6960 * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6961 */ 6962 static int 6963 cs_modify_configuration(client_handle_t client_handle, modify_config_t *mc) 6964 { 6965 cs_socket_t *sp; 6966 client_t *client; 6967 set_socket_t set_socket; 6968 get_socket_t get_socket; 6969 int error; 6970 int client_lock_acquired; 6971 6972 /* 6973 * Check to see if this is the Socket Services client handle; if it 6974 * is, we don't support SS using this call. 6975 */ 6976 if (CLIENT_HANDLE_IS_SS(client_handle)) 6977 return (CS_UNSUPPORTED_FUNCTION); 6978 6979 /* 6980 * Get a pointer to this client's socket structure. 6981 */ 6982 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6983 return (CS_BAD_SOCKET); 6984 6985 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6986 6987 /* 6988 * Make sure that this is a valid client handle. 6989 */ 6990 if (!(client = cs_find_client(client_handle, &error))) { 6991 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6992 return (error); 6993 } 6994 6995 /* 6996 * If RequestConfiguration has not been done, we don't allow 6997 * this call. 6998 */ 6999 if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7000 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7001 return (CS_BAD_HANDLE); 7002 } 7003 7004 /* 7005 * If there's no card in the socket or the card in the socket is not 7006 * for this client, then return an error. 7007 */ 7008 if (!(client->flags & CLIENT_CARD_INSERTED)) { 7009 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7010 return (CS_NO_CARD); 7011 } 7012 7013 /* 7014 * Get the current socket parameters so that we can modify them. 7015 */ 7016 get_socket.socket = sp->socket_num; 7017 7018 if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 7019 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7020 return (CS_BAD_SOCKET); 7021 } 7022 7023 #ifdef CS_DEBUG 7024 if (cs_debug > 0) 7025 cmn_err(CE_CONT, "cs_modify_configuration: socket %d " 7026 "client->irq_alloc.irq 0x%x " 7027 "get_socket.IRQRouting 0x%x\n", 7028 sp->socket_num, (int)client->irq_alloc.irq, 7029 get_socket.IRQRouting); 7030 #endif 7031 7032 set_socket.socket = sp->socket_num; 7033 set_socket.SCIntMask = get_socket.SCIntMask; 7034 set_socket.CtlInd = get_socket.CtlInd; 7035 set_socket.State = 0; /* don't reset latched values */ 7036 set_socket.IFType = get_socket.IFType; 7037 7038 set_socket.IREQRouting = get_socket.IRQRouting; 7039 7040 /* 7041 * Modify the IRQ routing if the client wants it modified. 7042 */ 7043 if (mc->Attributes & CONF_IRQ_CHANGE_VALID) { 7044 set_socket.IREQRouting &= ~IRQ_ENABLE; 7045 7046 if ((sp->cis_flags & CW_MULTI_FUNCTION_CIS) && 7047 (client->present & CONFIG_OPTION_REG_PRESENT)) { 7048 config_regs_t *crt = &client->config_regs; 7049 acc_handle_t cis_handle; 7050 uint32_t newoffset = client->config_regs_offset; 7051 7052 /* 7053 * Get a pointer to a window that contains the configuration 7054 * registers. 7055 */ 7056 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7057 CISTPLF_AM_SPACE) != CS_SUCCESS) { 7058 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7059 cmn_err(CE_CONT, 7060 "cs_modify_configuration: socket %d can't init " 7061 "CIS window\n", sp->socket_num); 7062 return (CS_GENERAL_FAILURE); 7063 } /* cs_init_cis_window */ 7064 7065 crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 7066 7067 if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7068 crt->cor |= COR_ENABLE_IREQ_ROUTING; 7069 7070 #ifdef CS_DEBUG 7071 if (cs_debug > 0) 7072 cmn_err(CE_CONT, "cs_modify_configuration:" 7073 " cor_p=0x%x cor=0x%x\n", 7074 crt->cor_p, crt->cor); 7075 #endif 7076 csx_Put8(cis_handle, crt->cor_p, crt->cor); 7077 7078 } /* CW_MULTI_FUNCTION_CIS */ 7079 7080 if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7081 set_socket.IREQRouting |= IRQ_ENABLE; 7082 7083 } /* CONF_IRQ_CHANGE_VALID */ 7084 7085 /* 7086 * Modify the voltage levels that the client specifies. 7087 */ 7088 set_socket.VccLevel = get_socket.VccLevel; 7089 7090 if (mc->Attributes & CONF_VPP1_CHANGE_VALID) { 7091 if (cs_convert_powerlevel(sp->socket_num, mc->Vpp1, VPP1, 7092 &set_socket.Vpp1Level) != CS_SUCCESS) { 7093 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7094 return (CS_BAD_VPP); 7095 } 7096 } else { 7097 set_socket.Vpp1Level = get_socket.Vpp1Level; 7098 } 7099 7100 if (mc->Attributes & CONF_VPP2_CHANGE_VALID) { 7101 if (cs_convert_powerlevel(sp->socket_num, mc->Vpp2, VPP2, 7102 &set_socket.Vpp2Level) != CS_SUCCESS) { 7103 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7104 return (CS_BAD_VPP); 7105 } 7106 } else { 7107 set_socket.Vpp2Level = get_socket.Vpp2Level; 7108 } 7109 7110 /* 7111 * Setup the modified socket configuration. 7112 */ 7113 if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 7114 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7115 return (CS_BAD_SOCKET); 7116 } 7117 7118 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7119 return (CS_SUCCESS); 7120 } 7121 7122 /* 7123 * cs_access_configuration_register - provides a client access to the card's 7124 * configuration registers; this is AccessConfigurationRegister 7125 * 7126 * returns: CS_SUCCESS - if register accessed successfully 7127 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7128 * CS_BAD_ARGS - if arguments are out of range 7129 * CS_NO_CARD - if no card in socket 7130 * CS_BAD_BASE - if no config registers base address 7131 * CS_UNSUPPORTED_MODE - if no RequestConfiguration has 7132 * been done yet 7133 */ 7134 static int 7135 cs_access_configuration_register(client_handle_t client_handle, 7136 access_config_reg_t *acr) 7137 { 7138 cs_socket_t *sp; 7139 client_t *client; 7140 acc_handle_t cis_handle; 7141 int error; 7142 uint32_t newoffset; 7143 int client_lock_acquired; 7144 7145 /* 7146 * Check to see if this is the Socket Services client handle; if it 7147 * is, we don't support SS using this call. 7148 */ 7149 if (CLIENT_HANDLE_IS_SS(client_handle)) 7150 return (CS_UNSUPPORTED_FUNCTION); 7151 7152 /* 7153 * Make sure that the specifed offset is in range. 7154 */ 7155 if (acr->Offset > ((CISTPL_CONFIG_MAX_CONFIG_REGS * 2) - 2)) 7156 return (CS_BAD_ARGS); 7157 7158 /* 7159 * Get a pointer to this client's socket structure. 7160 */ 7161 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7162 return (CS_BAD_SOCKET); 7163 7164 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7165 7166 /* 7167 * Make sure that this is a valid client handle. 7168 */ 7169 if (!(client = cs_find_client(client_handle, &error))) { 7170 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7171 return (error); 7172 } 7173 7174 /* 7175 * If there's no card in the socket or the card in the socket is not 7176 * for this client, then return an error. 7177 */ 7178 if (!(client->flags & CLIENT_CARD_INSERTED)) { 7179 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7180 return (CS_NO_CARD); 7181 } 7182 7183 /* 7184 * If RequestConfiguration has not been done, we don't allow 7185 * this call. 7186 */ 7187 if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7188 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7189 return (CS_UNSUPPORTED_MODE); 7190 } 7191 7192 mutex_enter(&sp->cis_lock); 7193 7194 /* 7195 * Get a pointer to the CIS window 7196 */ 7197 newoffset = client->config_regs_offset + acr->Offset; 7198 if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7199 CISTPLF_AM_SPACE) != CS_SUCCESS) { 7200 mutex_exit(&sp->cis_lock); 7201 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7202 cmn_err(CE_CONT, "cs_ACR: socket %d can't init CIS window\n", 7203 sp->socket_num); 7204 return (CS_GENERAL_FAILURE); 7205 } 7206 7207 /* 7208 * Create the address for the config register that the client 7209 * wants to access. 7210 */ 7211 mutex_enter(&sp->lock); 7212 7213 #ifdef CS_DEBUG 7214 if (cs_debug > 1) { 7215 cmn_err(CE_CONT, "cs_ACR: config_regs_offset 0x%x " 7216 "Offset 0x%x newoffset 0x%x\n", 7217 (int)client->config_regs_offset, 7218 (int)acr->Offset, newoffset); 7219 } 7220 #endif 7221 7222 /* 7223 * Determine what the client wants us to do. The client is 7224 * allowed to specify any valid offset, even if it would 7225 * cause an unimplemented configuration register to be 7226 * accessed. 7227 */ 7228 error = CS_SUCCESS; 7229 switch (acr->Action) { 7230 case CONFIG_REG_READ: 7231 acr->Value = csx_Get8(cis_handle, newoffset); 7232 break; 7233 case CONFIG_REG_WRITE: 7234 csx_Put8(cis_handle, newoffset, acr->Value); 7235 break; 7236 default: 7237 error = CS_BAD_ARGS; 7238 break; 7239 } /* switch */ 7240 7241 mutex_exit(&sp->lock); 7242 mutex_exit(&sp->cis_lock); 7243 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7244 7245 return (error); 7246 } 7247 7248 /* 7249 * ==== RESET and general info functions ==== 7250 */ 7251 7252 /* 7253 * cs_reset_function - RESET the requested function on the card; this 7254 * is ResetFunction 7255 * 7256 * Note: We don't support this functionality yet, and the standard 7257 * says it's OK to reutrn CS_IN_USE if we can't do this 7258 * operation. 7259 */ 7260 /*ARGSUSED*/ 7261 static int 7262 cs_reset_function(client_handle_t ch, reset_function_t *rf) 7263 { 7264 return (CS_IN_USE); 7265 } 7266 7267 /* 7268 * cs_get_configuration_info - return configuration info for the passed 7269 * socket and function number to the caller; 7270 * this is GetConfigurationInfo 7271 */ 7272 /*ARGSUSED*/ 7273 static int 7274 cs_get_configuration_info(client_handle_t *chp, get_configuration_info_t *gci) 7275 { 7276 cs_socket_t *sp; 7277 uint32_t fn; 7278 client_t *client; 7279 int client_lock_acquired; 7280 7281 /* 7282 * Get a pointer to this client's socket structure. 7283 */ 7284 if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gci->Socket))) == NULL) 7285 return (CS_BAD_SOCKET); 7286 7287 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7288 mutex_enter(&sp->lock); 7289 7290 fn = CS_GET_FUNCTION_NUMBER(gci->Socket); 7291 7292 client = sp->client_list; 7293 while (client) { 7294 7295 if (GET_CLIENT_FUNCTION(client->client_handle) == fn) { 7296 7297 /* 7298 * If there's no card in the socket or the card in the 7299 * socket is not for this client, then return 7300 * an error. 7301 */ 7302 if (!(client->flags & CLIENT_CARD_INSERTED)) { 7303 mutex_exit(&sp->lock); 7304 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7305 return (CS_NO_CARD); 7306 } 7307 7308 mutex_exit(&sp->lock); 7309 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7310 return (CS_SUCCESS); 7311 7312 } /* GET_CLIENT_FUNCTION == fn */ 7313 7314 client = client->next; 7315 } /* while (client) */ 7316 7317 mutex_exit(&sp->lock); 7318 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7319 7320 return (CS_BAD_SOCKET); 7321 } 7322 7323 /* 7324 * cs_get_cardservices_info - return info about Card Services to the 7325 * caller; this is GetCardServicesInfo 7326 */ 7327 /*ARGSUSED*/ 7328 static int 7329 cs_get_cardservices_info(client_handle_t ch, get_cardservices_info_t *gcsi) 7330 { 7331 gcsi->Signature[0] = 'C'; 7332 gcsi->Signature[1] = 'S'; 7333 gcsi->NumSockets = cs_globals.num_sockets; 7334 gcsi->Revision = CS_INTERNAL_REVISION_LEVEL; 7335 gcsi->CSLevel = CS_VERSION; 7336 gcsi->FuncsPerSocket = CIS_MAX_FUNCTIONS; 7337 (void) strncpy(gcsi->VendorString, 7338 CS_GET_CARDSERVICES_INFO_VENDOR_STRING, 7339 CS_GET_CARDSERVICES_INFO_MAX_VS_LEN); 7340 7341 return (CS_SUCCESS); 7342 } 7343 7344 /* 7345 * cs_get_physical_adapter_info - returns information about the requested 7346 * physical adapter; this is 7347 * GetPhysicalAdapterInfo 7348 * 7349 * calling: client_handle_t: 7350 * NULL - use map_log_socket_t->LogSocket member 7351 * to specify logical socket number 7352 * !NULL - extract logical socket number from 7353 * client_handle_t 7354 * 7355 * returns: CS_SUCCESS 7356 * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7357 * socket number is specified in 7358 * map_log_socket_t->LogSocket 7359 * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7360 * client handle is specified 7361 */ 7362 static int 7363 cs_get_physical_adapter_info(client_handle_t ch, 7364 get_physical_adapter_info_t *gpai) 7365 { 7366 cs_socket_t *sp; 7367 int client_lock_acquired; 7368 7369 if (ch == NULL) 7370 gpai->PhySocket = CS_GET_SOCKET_NUMBER(gpai->LogSocket); 7371 else 7372 gpai->PhySocket = GET_CLIENT_SOCKET(ch); 7373 7374 /* 7375 * Determine if the passed socket number is valid or not. 7376 */ 7377 if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gpai->PhySocket))) == NULL) 7378 return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7379 7380 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7381 7382 /* 7383 * If we were passed a client handle, determine if it's valid or not. 7384 */ 7385 if (ch != NULL) { 7386 if (cs_find_client(ch, NULL) == NULL) { 7387 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7388 return (CS_BAD_HANDLE); 7389 } /* cs_find_client */ 7390 } /* ch != NULL */ 7391 7392 gpai->flags = sp->adapter.flags; 7393 (void) strcpy(gpai->name, sp->adapter.name); 7394 gpai->major = sp->adapter.major; 7395 gpai->minor = sp->adapter.minor; 7396 gpai->instance = sp->adapter.instance; 7397 gpai->number = sp->adapter.number; 7398 gpai->num_sockets = sp->adapter.num_sockets; 7399 gpai->first_socket = sp->adapter.first_socket; 7400 7401 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7402 7403 return (CS_SUCCESS); 7404 } 7405 7406 /* 7407 * ==== general functions ==== 7408 */ 7409 7410 /* 7411 * cs_map_log_socket - returns the physical socket number associated with 7412 * either the passed client handle or the passed 7413 * logical socket number; this is MapLogSocket 7414 * 7415 * calling: client_handle_t: 7416 * NULL - use map_log_socket_t->LogSocket member 7417 * to specify logical socket number 7418 * !NULL - extract logical socket number from 7419 * client_handle_t 7420 * 7421 * returns: CS_SUCCESS 7422 * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7423 * socket number is specified in 7424 * map_log_socket_t->LogSocket 7425 * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7426 * client handle is specified 7427 * 7428 * Note: We provide this function since the instance number of a client 7429 * driver doesn't necessary correspond to the physical 7430 * socket number 7431 */ 7432 static int 7433 cs_map_log_socket(client_handle_t ch, map_log_socket_t *mls) 7434 { 7435 cs_socket_t *sp; 7436 int client_lock_acquired; 7437 7438 if (ch == NULL) 7439 mls->PhySocket = CS_GET_SOCKET_NUMBER(mls->LogSocket); 7440 else 7441 mls->PhySocket = GET_CLIENT_SOCKET(ch); 7442 7443 /* 7444 * Determine if the passed socket number is valid or not. 7445 */ 7446 if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(mls->PhySocket))) == NULL) 7447 return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7448 7449 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7450 7451 /* 7452 * If we were passed a client handle, determine if it's valid or not. 7453 */ 7454 if (ch != NULL) { 7455 if (cs_find_client(ch, NULL) == NULL) { 7456 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7457 return (CS_BAD_HANDLE); 7458 } /* cs_find_client */ 7459 } /* ch != NULL */ 7460 7461 mls->PhyAdapter = sp->adapter.number; 7462 7463 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7464 7465 return (CS_SUCCESS); 7466 } 7467 7468 /* 7469 * cs_convert_speed - convers nS to devspeed and devspeed to nS 7470 * 7471 * The actual function is is in the CIS parser module; this 7472 * is only a wrapper. 7473 */ 7474 static int 7475 cs_convert_speed(convert_speed_t *cs) 7476 { 7477 return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSPEED, cs)); 7478 } 7479 7480 /* 7481 * cs_convert_size - converts a devsize value to a size in bytes value 7482 * or a size in bytes value to a devsize value 7483 * 7484 * The actual function is is in the CIS parser module; this 7485 * is only a wrapper. 7486 */ 7487 static int 7488 cs_convert_size(convert_size_t *cs) 7489 { 7490 return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSIZE, cs)); 7491 } 7492 7493 /* 7494 * cs_convert_powerlevel - converts a power level in tenths of a volt 7495 * to a power table entry for the specified socket 7496 * 7497 * returns: CS_SUCCESS - if volts converted to a valid power level 7498 * CS_BAD_ADAPTER - if SS_InquireAdapter fails 7499 * CS_BAD_ARGS - if volts are not supported on this socket 7500 * and adapter 7501 */ 7502 static int 7503 cs_convert_powerlevel(uint32_t sn, uint32_t volts, uint32_t flags, unsigned *pl) 7504 { 7505 inquire_adapter_t inquire_adapter; 7506 int i; 7507 7508 #ifdef lint 7509 if (sn == 0) 7510 panic("lint panic"); 7511 #endif 7512 7513 *pl = 0; 7514 7515 if (SocketServices(SS_InquireAdapter, &inquire_adapter) != SUCCESS) 7516 return (CS_BAD_ADAPTER); 7517 7518 for (i = 0; (i < inquire_adapter.NumPower); i++) { 7519 if ((inquire_adapter.power_entry[i].ValidSignals & flags) && 7520 (inquire_adapter.power_entry[i].PowerLevel == volts)) { 7521 *pl = i; 7522 return (CS_SUCCESS); 7523 } 7524 } 7525 7526 return (CS_BAD_ARGS); 7527 } 7528 7529 /* 7530 * cs_event2text - returns text string(s) associated with the event; this 7531 * function supports the Event2Text CS call. 7532 * 7533 * calling: event2text_t * - pointer to event2text struct 7534 * int event_source - specifies event type in event2text_t: 7535 * 0 - SS event 7536 * 1 - CS event 7537 * 7538 * returns: CS_SUCCESS 7539 */ 7540 static int 7541 cs_event2text(event2text_t *e2t, int event_source) 7542 { 7543 event_t event; 7544 char *sepchar = "|"; 7545 7546 /* 7547 * If event_source is 0, this is a SS event 7548 */ 7549 if (!event_source) { 7550 for (event = 0; event < MAX_SS_EVENTS; event++) { 7551 if (cs_ss_event_text[event].ss_event == e2t->event) { 7552 (void) strcpy(e2t->text, cs_ss_event_text[event].text); 7553 return (CS_SUCCESS); 7554 } 7555 } 7556 (void) strcpy(e2t->text, cs_ss_event_text[MAX_CS_EVENTS].text); 7557 return (CS_SUCCESS); 7558 } else { 7559 /* 7560 * This is a CS event 7561 */ 7562 e2t->text[0] = '\0'; 7563 for (event = 0; event < MAX_CS_EVENTS; event++) { 7564 if (cs_ss_event_text[event].cs_event & e2t->event) { 7565 (void) strcat(e2t->text, cs_ss_event_text[event].text); 7566 (void) strcat(e2t->text, sepchar); 7567 } /* if (cs_ss_event_text) */ 7568 } /* for (event) */ 7569 if (e2t->text[0]) 7570 e2t->text[strlen(e2t->text)-1] = NULL; 7571 } /* if (!event_source) */ 7572 7573 return (CS_SUCCESS); 7574 } 7575 7576 /* 7577 * cs_error2text - returns a pointer to a text string containing the name 7578 * of the passed Card Services function or return code 7579 * 7580 * This function supports the Error2Text CS call. 7581 */ 7582 static char * 7583 cs_error2text(int function, int type) 7584 { 7585 cs_csfunc2text_strings_t *cfs; 7586 int end_marker; 7587 7588 if (type == CSFUN2TEXT_FUNCTION) { 7589 cfs = cs_csfunc2text_funcstrings; 7590 end_marker = CSFuncListEnd; 7591 } else { 7592 cfs = cs_csfunc2text_returnstrings; 7593 end_marker = CS_ERRORLIST_END; 7594 } 7595 7596 while (cfs->item != end_marker) { 7597 if (cfs->item == function) 7598 return (cfs->text); 7599 cfs++; 7600 } 7601 7602 return (cfs->text); 7603 } 7604 7605 /* 7606 * cs_make_device_node - creates/removes device nodes on a client's behalf; 7607 * this is MakeDeviceNode and RemoveDeviceNode 7608 * 7609 * returns: CS_SUCCESS - if all device nodes successfully created/removed 7610 * CS_BAD_ATTRIBUTE - if NumDevNodes is not zero when Action 7611 * is REMOVAL_ALL_DEVICES 7612 * CS_BAD_ARGS - if an invalid Action code is specified 7613 * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7614 * CS_OUT_OF_RESOURCE - if can't create/remove device node 7615 */ 7616 static int 7617 cs_make_device_node(client_handle_t client_handle, make_device_node_t *mdn) 7618 { 7619 cs_socket_t *sp; 7620 client_t *client; 7621 ss_make_device_node_t ss_make_device_node; 7622 int error, i; 7623 int client_lock_acquired; 7624 7625 /* 7626 * Check to see if this is the Socket Services client handle; if it 7627 * is, we don't support SS using this call. 7628 */ 7629 if (CLIENT_HANDLE_IS_SS(client_handle)) 7630 return (CS_UNSUPPORTED_FUNCTION); 7631 7632 /* 7633 * Get a pointer to this client's socket structure. 7634 */ 7635 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7636 return (CS_BAD_SOCKET); 7637 7638 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7639 7640 /* 7641 * Make sure that this is a valid client handle. 7642 */ 7643 if (!(client = cs_find_client(client_handle, &error))) { 7644 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7645 return (error); 7646 } 7647 7648 #ifdef XXX 7649 /* 7650 * If there's no card in the socket or the card in the socket is not 7651 * for this client, then return an error. 7652 */ 7653 if (!(client->flags & CLIENT_CARD_INSERTED)) { 7654 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7655 return (CS_NO_CARD); 7656 } 7657 #endif 7658 7659 /* 7660 * Setup the client's dip, since we use it later on. 7661 */ 7662 ss_make_device_node.dip = client->dip; 7663 7664 /* 7665 * Make sure that we're being given a valid Action. Set the default 7666 * error code as well. 7667 */ 7668 error = CS_BAD_ARGS; /* for default case */ 7669 switch (mdn->Action) { 7670 case CREATE_DEVICE_NODE: 7671 case REMOVE_DEVICE_NODE: 7672 break; 7673 case REMOVAL_ALL_DEVICE_NODES: 7674 if (mdn->NumDevNodes) { 7675 error = CS_BAD_ATTRIBUTE; 7676 } else { 7677 ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7678 ss_make_device_node.name = NULL; 7679 SocketServices(CSInitDev, &ss_make_device_node); 7680 error = CS_SUCCESS; 7681 } 7682 /* FALLTHROUGH */ 7683 default: 7684 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7685 return (error); 7686 /* NOTREACHED */ 7687 } /* switch */ 7688 7689 /* 7690 * Loop through the device node descriptions and create or destroy 7691 * the device node. 7692 */ 7693 for (i = 0; i < mdn->NumDevNodes; i++) { 7694 devnode_desc_t *devnode_desc = &mdn->devnode_desc[i]; 7695 7696 ss_make_device_node.name = devnode_desc->name; 7697 ss_make_device_node.spec_type = devnode_desc->spec_type; 7698 ss_make_device_node.minor_num = devnode_desc->minor_num; 7699 ss_make_device_node.node_type = devnode_desc->node_type; 7700 7701 /* 7702 * Set the appropriate flag for the action that we want 7703 * SS to perform. Note that if we ever OR-in the flag 7704 * here, we need to be sure to clear the flags member 7705 * since we sometimes OR-in other flags below. 7706 */ 7707 if (mdn->Action == CREATE_DEVICE_NODE) { 7708 ss_make_device_node.flags = SS_CSINITDEV_CREATE_DEVICE; 7709 } else { 7710 ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7711 } 7712 7713 /* 7714 * If this is not the last device to process, then we need 7715 * to tell SS that more device process requests are on 7716 * their way after this one. 7717 */ 7718 if (i < (mdn->NumDevNodes - 1)) 7719 ss_make_device_node.flags |= SS_CSINITDEV_MORE_DEVICES; 7720 7721 if (SocketServices(CSInitDev, &ss_make_device_node) != SUCCESS) { 7722 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7723 return (CS_OUT_OF_RESOURCE); 7724 } /* CSInitDev */ 7725 } /* for (mdn->NumDevNodes) */ 7726 7727 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7728 return (CS_SUCCESS); 7729 } 7730 7731 /* 7732 * cs_remove_device_node - removes device nodes 7733 * 7734 * (see cs_make_device_node for a description of the calling 7735 * and return parameters) 7736 */ 7737 static int 7738 cs_remove_device_node(client_handle_t client_handle, remove_device_node_t *rdn) 7739 { 7740 7741 /* 7742 * XXX - Note the assumption here that the make_device_node_t and 7743 * remove_device_node_t structures are identical. 7744 */ 7745 return (cs_make_device_node(client_handle, (make_device_node_t *)rdn)); 7746 } 7747 7748 /* 7749 * cs_ddi_info - this function is used by clients that need to support 7750 * the xxx_getinfo function; this is CS_DDI_Info 7751 */ 7752 static int 7753 cs_ddi_info(cs_ddi_info_t *cdi) 7754 { 7755 cs_socket_t *sp; 7756 client_t *client; 7757 int client_lock_acquired; 7758 7759 if (cdi->driver_name == NULL) 7760 return (CS_BAD_ATTRIBUTE); 7761 7762 #ifdef CS_DEBUG 7763 if (cs_debug > 0) { 7764 cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s]\n", 7765 (int)cdi->Socket, cdi->driver_name); 7766 } 7767 #endif 7768 7769 /* 7770 * Check to see if the socket number is in range - the system 7771 * framework may cause a client driver to call us with 7772 * a socket number that used to be present but isn't 7773 * anymore. This is not a bug, and it's OK to return 7774 * an error if the socket number is out of range. 7775 */ 7776 if (!CHECK_SOCKET_NUM(cdi->Socket, cs_globals.max_socket_num)) { 7777 7778 #ifdef CS_DEBUG 7779 if (cs_debug > 0) { 7780 cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s] " 7781 "SOCKET IS OUT OF RANGE\n", 7782 (int)cdi->Socket, 7783 cdi->driver_name); 7784 } 7785 #endif 7786 7787 return (CS_BAD_SOCKET); 7788 } /* if (!CHECK_SOCKET_NUM) */ 7789 7790 /* 7791 * Get a pointer to this client's socket structure. 7792 */ 7793 if ((sp = cs_get_sp(cdi->Socket)) == NULL) 7794 return (CS_BAD_SOCKET); 7795 7796 EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7797 7798 client = sp->client_list; 7799 while (client) { 7800 7801 #ifdef CS_DEBUG 7802 if (cs_debug > 0) { 7803 cmn_err(CE_CONT, "cs_ddi_info: socket %d checking client [%s] " 7804 "handle 0x%x\n", 7805 (int)cdi->Socket, 7806 client->driver_name, 7807 (int)client->client_handle); 7808 } 7809 #endif 7810 7811 if (client->driver_name != NULL) { 7812 if (!(strcmp(client->driver_name, cdi->driver_name))) { 7813 cdi->dip = client->dip; 7814 cdi->instance = client->instance; 7815 7816 #ifdef CS_DEBUG 7817 if (cs_debug > 0) { 7818 cmn_err(CE_CONT, "cs_ddi_info: found client [%s] " 7819 "instance %d handle 0x%x\n", 7820 client->driver_name, client->instance, 7821 (int)client->client_handle); 7822 } 7823 #endif 7824 7825 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7826 return (CS_SUCCESS); 7827 } /* strcmp */ 7828 } /* driver_name != NULL */ 7829 client = client->next; 7830 } /* while (client) */ 7831 7832 EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7833 return (CS_BAD_SOCKET); 7834 } 7835 7836 /* 7837 * cs_sys_ctl - Card Services system control; this is CS_Sys_Ctl 7838 */ 7839 static int 7840 cs_sys_ctl(cs_sys_ctl_t *csc) 7841 { 7842 cs_socket_t *sp; 7843 client_t *cp; 7844 int sn, ret = CS_UNSUPPORTED_MODE; 7845 7846 switch (csc->Action) { 7847 case CS_SYS_CTL_SEND_EVENT: 7848 if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7849 sn = CS_GET_SOCKET_NUMBER(csc->Socket); 7850 else 7851 sn = GET_CLIENT_SOCKET(csc->client_handle); 7852 if ((sp = cs_get_sp(sn)) == NULL) 7853 return (CS_BAD_SOCKET); 7854 mutex_enter(&sp->client_lock); 7855 mutex_enter(&sp->lock); 7856 csc->Events &= CS_EVENT_CLIENT_EVENTS_MASK; 7857 if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7858 sp->events |= csc->Events; 7859 if (csc->Flags & CS_SYS_CTL_EVENT_CLIENT) { 7860 if ((cp = cs_find_client(csc->client_handle, &ret)) == 7861 NULL) { 7862 mutex_exit(&sp->lock); 7863 mutex_exit(&sp->client_lock); 7864 return (ret); 7865 } /* cs_find_client */ 7866 /* 7867 * Setup the events that we want to send to the client. 7868 */ 7869 cp->events |= (csc->Events & 7870 (cp->event_mask | cp->global_mask)); 7871 } /* CS_SYS_CTL_EVENT_CLIENT */ 7872 7873 if (csc->Flags & CS_SYS_CTL_WAIT_SYNC) { 7874 sp->thread_state |= SOCKET_WAIT_SYNC; 7875 mutex_exit(&sp->lock); 7876 cv_broadcast(&sp->thread_cv); 7877 cv_wait(&sp->caller_cv, &sp->client_lock); 7878 } else { 7879 mutex_exit(&sp->lock); 7880 cv_broadcast(&sp->thread_cv); 7881 } /* CS_SYS_CTL_WAIT_SYNC */ 7882 mutex_exit(&sp->client_lock); 7883 ret = CS_SUCCESS; 7884 break; 7885 default: 7886 break; 7887 } /* switch */ 7888 7889 return (ret); 7890 } 7891 7892 /* 7893 * cs_get_sp - returns pointer to per-socket structure for passed 7894 * socket number 7895 * 7896 * return: (cs_socket_t *) - pointer to socket structure 7897 * NULL - invalid socket number passed in 7898 */ 7899 static cs_socket_t * 7900 cs_get_sp(uint32_t sn) 7901 { 7902 cs_socket_t *sp = cs_globals.sp; 7903 7904 if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7905 return (NULL); 7906 7907 if ((sp = cs_find_sp(sn)) == NULL) 7908 return (NULL); 7909 7910 if (sp->flags & SOCKET_IS_VALID) 7911 return (sp); 7912 7913 return (NULL); 7914 } 7915 7916 /* 7917 * cs_find_sp - searches socket list and returns pointer to passed socket 7918 * number 7919 * 7920 * return: (cs_socket_t *) - pointer to socket structure if found 7921 * NULL - socket not found 7922 */ 7923 static cs_socket_t * 7924 cs_find_sp(uint32_t sn) 7925 { 7926 cs_socket_t *sp = cs_globals.sp; 7927 7928 while (sp) { 7929 if (sp->socket_num == CS_GET_SOCKET_NUMBER(sn)) 7930 return (sp); 7931 sp = sp->next; 7932 } /* while */ 7933 7934 return (NULL); 7935 } 7936 7937 /* 7938 * cs_add_socket - add a socket 7939 * 7940 * call: sn - socket number to add 7941 * 7942 * return: CS_SUCCESS - operation sucessful 7943 * CS_BAD_SOCKET - unable to add socket 7944 * CS_BAD_WINDOW - unable to get CIS window for socket 7945 * 7946 * We get called here once for each socket that the framework wants to 7947 * add. When we are called, the framework guarentees that until we 7948 * complete this routine, no other adapter instances will be allowed 7949 * to attach and thus no other PCE_ADD_SOCKET events will occur. 7950 * It is safe to call SS_InquireAdapter to get the number of 7951 * windows that the framework currently knows about. 7952 */ 7953 static uint32_t 7954 cs_add_socket(uint32_t sn) 7955 { 7956 cs_socket_t *sp; 7957 sservice_t sservice; 7958 get_cookies_and_dip_t *gcad; 7959 win_req_t win_req; 7960 convert_speed_t convert_speed; 7961 set_socket_t set_socket; 7962 cs_window_t *cw; 7963 inquire_adapter_t inquire_adapter; 7964 inquire_window_t inquire_window; 7965 int ret, added_windows; 7966 7967 if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7968 return (CS_BAD_SOCKET); 7969 7970 /* 7971 * See if this socket has already been added - if it has, we 7972 * fail this. If we can't find the socket, then allocate 7973 * a new socket structure. If we do find the socket, then 7974 * check to see if it's already added; if it is, then 7975 * this is an error and return CS_BAD_SOCKET; if not, 7976 * then traverse the socket structure list and add this 7977 * next socket strcture to the end of the list. 7978 * XXX What about locking this list while we update it? Is 7979 * that necessary since we're using the SOCKET_IS_VALID 7980 * flag and since we never delete a socket from the 7981 * list once it's been added? 7982 */ 7983 if ((sp = cs_find_sp(sn)) == NULL) { 7984 cs_socket_t *spp = cs_globals.sp; 7985 7986 sp = (cs_socket_t *)kmem_zalloc(sizeof (cs_socket_t), KM_SLEEP); 7987 7988 if (cs_globals.sp == NULL) 7989 cs_globals.sp = sp; 7990 else 7991 while (spp) { 7992 if (spp->next == NULL) { 7993 spp->next = sp; 7994 break; 7995 } /* if */ 7996 spp = spp->next; 7997 } /* while */ 7998 7999 } else { 8000 if (sp->flags & SOCKET_IS_VALID) 8001 return (CS_BAD_SOCKET); 8002 } /* cs_find_sp */ 8003 8004 /* 8005 * Setup the socket number 8006 */ 8007 sp->socket_num = sn; 8008 8009 /* 8010 * Find out how many windows the framework knows about 8011 * so far. If this number of windows is greater 8012 * than our current window count, bump up our 8013 * current window count. 8014 * XXX Note that there is a BIG assumption here and that 8015 * is that once the framework tells us that it has 8016 * a window (as reflected in the NumWindows 8017 * value) it can NEVER remove that window. 8018 * When we really get the drop socket and drop 8019 * window mechanism working correctly, we'll have 8020 * to revisit this. 8021 */ 8022 SocketServices(SS_InquireAdapter, &inquire_adapter); 8023 8024 mutex_enter(&cs_globals.window_lock); 8025 added_windows = inquire_adapter.NumWindows - cs_globals.num_windows; 8026 if (added_windows > 0) { 8027 if (cs_add_windows(added_windows, 8028 cs_globals.num_windows) != CS_SUCCESS) { 8029 mutex_exit(&cs_globals.window_lock); 8030 return (CS_BAD_WINDOW); 8031 } /* cs_add_windows */ 8032 8033 cs_globals.num_windows = inquire_adapter.NumWindows; 8034 8035 } /* if (added_windows) */ 8036 8037 /* 8038 * Find a window that we can use for this socket's CIS window. 8039 */ 8040 sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8041 8042 convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 8043 convert_speed.nS = CIS_DEFAULT_SPEED; 8044 (void) cs_convert_speed(&convert_speed); 8045 8046 win_req.win_params.AccessSpeed = convert_speed.devspeed; 8047 win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8); 8048 win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_MEMORY_TYPE_CM); 8049 win_req.Base.base = 0; 8050 win_req.Size = 0; 8051 8052 if ((ret = cs_find_mem_window(sp->socket_num, &win_req, 8053 &sp->cis_win_num)) != CS_SUCCESS) { 8054 mutex_exit(&cs_globals.window_lock); 8055 sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8056 cmn_err(CE_CONT, "cs_add_socket: socket %d can't get CIS " 8057 "window - error 0x%x\n", 8058 sp->socket_num, ret); 8059 return (CS_BAD_WINDOW); 8060 } /* cs_find_mem_window */ 8061 8062 if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) { 8063 mutex_exit(&cs_globals.window_lock); 8064 return (CS_BAD_WINDOW); 8065 } 8066 8067 inquire_window.window = sp->cis_win_num; 8068 SocketServices(SS_InquireWindow, &inquire_window); 8069 8070 /* 8071 * If the CIS window is a variable sized window, then use 8072 * the size that cs_find_mem_window returned to us, 8073 * since this will be the minimum size that we can 8074 * set this window to. If the CIS window is a fixed 8075 * sized window, then use the system pagesize as the 8076 * CIS window size. 8077 */ 8078 if (inquire_window.mem_win_char.MemWndCaps & WC_SIZE) { 8079 sp->cis_win_size = win_req.Size; 8080 } else { 8081 sp->cis_win_size = PAGESIZE; 8082 } 8083 8084 cw->state |= (CW_CIS | CW_ALLOCATED); 8085 cw->socket_num = sp->socket_num; 8086 8087 mutex_exit(&cs_globals.window_lock); 8088 8089 #if defined(CS_DEBUG) 8090 if (cs_debug > 1) { 8091 cmn_err(CE_CONT, "cs_add_socket: socket %d using CIS window %d " 8092 "size 0x%x\n", (int)sp->socket_num, 8093 (int)sp->cis_win_num, 8094 (int)sp->cis_win_size); 8095 } 8096 #endif 8097 8098 /* 8099 * Get the adapter information associated with this socket so 8100 * that we can initialize the mutexes, condition variables, 8101 * soft interrupt handler and per-socket adapter info. 8102 */ 8103 gcad = &sservice.get_cookies; 8104 gcad->socket = sp->socket_num; 8105 if (SocketServices(CSGetCookiesAndDip, &sservice) != SUCCESS) { 8106 cmn_err(CE_CONT, "cs_add_socket: socket %d CSGetCookiesAndDip " 8107 "failure\n", sp->socket_num); 8108 return (CS_BAD_SOCKET); 8109 } /* CSGetCookiesAndDip */ 8110 8111 /* 8112 * Save the iblock and idev cookies for RegisterClient 8113 */ 8114 sp->iblk = gcad->iblock; 8115 sp->idev = gcad->idevice; 8116 8117 /* 8118 * Setup the per-socket adapter info 8119 */ 8120 sp->adapter.flags = 0; 8121 (void) strcpy(sp->adapter.name, gcad->adapter_info.name); 8122 sp->adapter.major = gcad->adapter_info.major; 8123 sp->adapter.minor = gcad->adapter_info.minor; 8124 sp->adapter.instance = ddi_get_instance(gcad->dip); 8125 sp->adapter.number = gcad->adapter_info.number; 8126 sp->adapter.num_sockets = gcad->adapter_info.num_sockets; 8127 sp->adapter.first_socket = gcad->adapter_info.first_socket; 8128 8129 /* Setup for cs_event and cs_event_thread */ 8130 mutex_init(&sp->lock, NULL, MUTEX_DRIVER, *(gcad->iblock)); 8131 mutex_init(&sp->client_lock, NULL, MUTEX_DRIVER, NULL); 8132 mutex_init(&sp->cis_lock, NULL, MUTEX_DRIVER, NULL); 8133 8134 /* Setup for Socket Services work thread */ 8135 mutex_init(&sp->ss_thread_lock, NULL, MUTEX_DRIVER, NULL); 8136 8137 sp->init_state |= SOCKET_INIT_STATE_MUTEX; 8138 8139 /* Setup for cs_event_thread */ 8140 cv_init(&sp->thread_cv, NULL, CV_DRIVER, NULL); 8141 cv_init(&sp->caller_cv, NULL, CV_DRIVER, NULL); 8142 cv_init(&sp->reset_cv, NULL, CV_DRIVER, NULL); 8143 8144 /* Setup for Socket Services work thread */ 8145 cv_init(&sp->ss_thread_cv, NULL, CV_DRIVER, NULL); 8146 cv_init(&sp->ss_caller_cv, NULL, CV_DRIVER, NULL); 8147 8148 sp->init_state |= SOCKET_INIT_STATE_CV; 8149 8150 /* 8151 * If we haven't installed it yet, then install the soft interrupt 8152 * handler and save away the softint id. 8153 */ 8154 if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR)) { 8155 if (ddi_add_softintr(gcad->dip, DDI_SOFTINT_HIGH, 8156 &sp->softint_id, 8157 NULL, NULL, 8158 cs_socket_event_softintr, 8159 (caddr_t)NULL) != DDI_SUCCESS) { 8160 cmn_err(CE_CONT, "cs_add_socket: socket %d can't add " 8161 "softintr\n", sp->socket_num); 8162 return (CS_BAD_SOCKET); 8163 } /* ddi_add_softintr */ 8164 8165 mutex_enter(&cs_globals.global_lock); 8166 cs_globals.softint_id = sp->softint_id; 8167 cs_globals.init_state |= GLOBAL_INIT_STATE_SOFTINTR; 8168 /* XXX this timer is hokey at best... */ 8169 cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 8170 NULL, SOFTINT_TIMEOUT_TIME); 8171 mutex_exit(&cs_globals.global_lock); 8172 } else { 8173 /* 8174 * We've already added the soft interrupt handler, so just 8175 * store away the softint id. 8176 */ 8177 sp->softint_id = cs_globals.softint_id; 8178 } /* if (!GLOBAL_INIT_STATE_SOFTINTR) */ 8179 8180 /* 8181 * While this next flag doesn't really describe a per-socket 8182 * resource, we still set it for each socket. When the soft 8183 * interrupt handler finally gets removed in cs_deinit, this 8184 * flag will get cleared. 8185 */ 8186 sp->init_state |= SOCKET_INIT_STATE_SOFTINTR; 8187 8188 /* 8189 * Socket Services defaults all sockets to power off and 8190 * clears all event masks. We want to receive at least 8191 * card insertion events, so enable them. Turn off power 8192 * to the socket as well. We will turn it on again when 8193 * we get a card insertion event. 8194 */ 8195 sp->event_mask = CS_EVENT_CARD_INSERTION; 8196 set_socket.socket = sp->socket_num; 8197 set_socket.SCIntMask = SBM_CD; 8198 set_socket.IREQRouting = 0; 8199 set_socket.IFType = IF_MEMORY; 8200 set_socket.CtlInd = 0; /* turn off controls and indicators */ 8201 set_socket.State = (unsigned)~0; /* clear latched state bits */ 8202 8203 (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 8204 &set_socket.VccLevel); 8205 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 8206 &set_socket.Vpp1Level); 8207 (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 8208 &set_socket.Vpp2Level); 8209 8210 if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 8211 cmn_err(CE_CONT, "cs_add_socket: socket %d SS_SetSocket " 8212 "failure %d\n", sp->socket_num, ret); 8213 return (CS_BAD_SOCKET); 8214 } /* SS_SetSocket */ 8215 8216 /* 8217 * The various socket-specific variables are now set up, so 8218 * increment the global socket count and also mark the 8219 * socket as available. We need to set this before we 8220 * start any of the per-socket threads so that the threads 8221 * can get a valid socket pointer when they start. 8222 */ 8223 mutex_enter(&cs_globals.global_lock); 8224 cs_globals.num_sockets++; 8225 cs_globals.max_socket_num = 8226 max(cs_globals.max_socket_num, sp->socket_num + 1); 8227 mutex_exit(&cs_globals.global_lock); 8228 sp->flags = SOCKET_IS_VALID; 8229 8230 /* 8231 * Create the per-socket event handler thread. 8232 */ 8233 sp->event_thread = CREATE_SOCKET_EVENT_THREAD(cs_event_thread, 8234 (uintptr_t)sn); 8235 8236 mutex_enter(&sp->lock); 8237 sp->init_state |= SOCKET_INIT_STATE_THREAD; 8238 mutex_exit(&sp->lock); 8239 8240 /* 8241 * Create the per-socket Socket Services work thread. 8242 */ 8243 sp->ss_thread = CREATE_SOCKET_EVENT_THREAD(cs_ss_thread, 8244 (uintptr_t)sn); 8245 8246 mutex_enter(&sp->lock); 8247 sp->init_state |= (SOCKET_INIT_STATE_SS_THREAD | 8248 SOCKET_INIT_STATE_READY); 8249 sp->event_mask = CS_EVENT_CARD_INSERTION; 8250 mutex_exit(&sp->lock); 8251 8252 return (CS_SUCCESS); 8253 } 8254 8255 /* 8256 * cs_drop_socket - drop a socket 8257 * 8258 * call: sn - socket number to drop 8259 * 8260 * return: CS_SUCCESS - operation sucessful 8261 * CS_BAD_SOCKET - unable to drop socket 8262 */ 8263 /*ARGSUSED*/ 8264 static uint32_t 8265 cs_drop_socket(uint32_t sn) 8266 { 8267 #ifdef XXX 8268 cs_socket_t *sp; 8269 8270 /* 8271 * Tell the socket event thread to exit and then wait for it 8272 * to do so. 8273 */ 8274 mutex_enter(&sp->client_lock); 8275 sp->thread_state |= SOCKET_THREAD_EXIT; 8276 cv_broadcast(&sp->thread_cv); 8277 cv_wait(&sp->caller_cv, &sp->client_lock); 8278 mutex_exit(&sp->client_lock); 8279 8280 /* 8281 * Tell the socket SS thread to exit and then wait for it 8282 * to do so. 8283 */ 8284 8285 /* 8286 * Mark the socket as dropped. 8287 */ 8288 sp->flags &= ~SOCKET_IS_VALID; 8289 8290 #endif /* XXX */ 8291 8292 /* XXX for now don't allow dropping sockets XXX */ 8293 return (CS_BAD_SOCKET); 8294 } 8295 8296 /* 8297 * cs_get_socket - returns the socket and function numbers and a pointer 8298 * to the socket structure 8299 * 8300 * calling: client_handle_t client_handle - client handle to extract 8301 * socket number from 8302 * uint32_t *socket - pointer to socket number to use if 8303 * client_handle is for the SS client; 8304 * this value will be filled in on 8305 * return with the correct socket 8306 * and function numbers if we 8307 * return CS_SUCCESS 8308 * uint32_t *function - pointer to return function number into 8309 * if not NULL 8310 * cs_socket_t **sp - pointer to a pointer where a pointer 8311 * to the socket struct will be 8312 * placed if this is non-NULL 8313 * client_t **clp - pointer to a pointer where a pointer 8314 * to the client struct will be 8315 * placed if this is non-NULL 8316 * 8317 * The socket and function numbers are derived as follows: 8318 * 8319 * Client Type Socket Number Function Number 8320 * PC card client From client_handle From client_handle 8321 * Socket Services client From *socket From *socket 8322 * CSI client From client_handle From *socket 8323 */ 8324 static uint32_t 8325 cs_get_socket(client_handle_t client_handle, uint32_t *socket, 8326 uint32_t *function, cs_socket_t **csp, client_t **clp) 8327 { 8328 cs_socket_t *sp; 8329 client_t *client; 8330 uint32_t sn, fn; 8331 int ret; 8332 8333 sn = *socket; 8334 8335 /* 8336 * If this is the Socket Services client, then return the 8337 * socket and function numbers specified in the passed 8338 * socket number parameter, otherwise extract the socket 8339 * and function numbers from the client handle. 8340 */ 8341 if (CLIENT_HANDLE_IS_SS(client_handle)) { 8342 fn = CS_GET_FUNCTION_NUMBER(sn); 8343 sn = CS_GET_SOCKET_NUMBER(sn); 8344 } else { 8345 fn = GET_CLIENT_FUNCTION(client_handle); 8346 sn = GET_CLIENT_SOCKET(client_handle); 8347 } 8348 8349 /* 8350 * Check to be sure that the socket number is in range 8351 */ 8352 if (!(CHECK_SOCKET_NUM(sn, cs_globals.max_socket_num))) 8353 return (CS_BAD_SOCKET); 8354 8355 if ((sp = cs_get_sp(sn)) == NULL) 8356 return (CS_BAD_SOCKET); 8357 8358 /* 8359 * If we were given a pointer, then fill it in with a pointer 8360 * to this socket. 8361 */ 8362 if (csp) 8363 *csp = sp; 8364 8365 /* 8366 * Search for the client; if it's not found, return an error. 8367 */ 8368 mutex_enter(&sp->lock); 8369 if (!(client = cs_find_client(client_handle, &ret))) { 8370 mutex_exit(&sp->lock); 8371 return (ret); 8372 } 8373 8374 /* 8375 * If we're a CIS client, then extract the function number 8376 * from the socket number. 8377 */ 8378 if (client->flags & CLIENT_CSI_CLIENT) 8379 fn = CS_GET_FUNCTION_NUMBER(*socket); 8380 8381 mutex_exit(&sp->lock); 8382 8383 /* 8384 * Return the found client pointer if the caller wants it. 8385 */ 8386 if (clp) 8387 *clp = client; 8388 8389 /* 8390 * Return a socket number that is made up of the socket number 8391 * and the function number. 8392 */ 8393 *socket = CS_MAKE_SOCKET_NUMBER(sn, fn); 8394 8395 /* 8396 * Return the function number if the caller wants it. 8397 */ 8398 if (function) 8399 *function = fn; 8400 8401 return (CS_SUCCESS); 8402 } 8403 8404 /* 8405 * cs_get_wp - returns pointer to passed window number 8406 * 8407 * return: (cs_window_t *) - pointer to window structure 8408 * NULL - if invalid window number passed in 8409 */ 8410 static cs_window_t * 8411 cs_get_wp(uint32_t wn) 8412 { 8413 cs_window_t *cw; 8414 8415 if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 8416 return (NULL); 8417 8418 if ((cw = cs_find_wp(wn)) == NULL) 8419 return (NULL); 8420 8421 if (cw->state & CW_WINDOW_VALID) 8422 return (cw); 8423 8424 #ifdef CS_DEBUG 8425 if (cs_debug > 0) { 8426 cmn_err(CE_CONT, "cs_get_wp(): wn=%d cw=%p\n", 8427 (int)wn, (void *)cw); 8428 } 8429 #endif 8430 8431 return (NULL); 8432 } 8433 8434 /* 8435 * cs_find_wp - searches window list and returns pointer to passed window 8436 * number 8437 * 8438 * return: (cs_window_t *) - pointer to window structure 8439 * NULL - window not found 8440 */ 8441 static cs_window_t * 8442 cs_find_wp(uint32_t wn) 8443 { 8444 cs_window_t *cw = cs_globals.cw; 8445 8446 while (cw) { 8447 if (cw->window_num == wn) 8448 return (cw); 8449 cw = cw->next; 8450 } /* while */ 8451 8452 #ifdef CS_DEBUG 8453 if (cs_debug > 0) { 8454 cmn_err(CE_CONT, "cs_find_wp(): wn=%d window_num=%d cw=%p\n", 8455 (int)wn, (int)cw->window_num, (void *)cw); 8456 } 8457 #endif 8458 8459 return (NULL); 8460 } 8461 8462 /* 8463 * cs_add_windows - adds number of windows specified in "aw" to 8464 * the global window list; start the window 8465 * numbering at "bn" 8466 * 8467 * return: CS_SUCCESS - if windows added sucessfully 8468 * CS_BAD_WINDOW - if unable to add windows 8469 * 8470 * Note: The window list must be protected by a lock by the caller. 8471 */ 8472 static int 8473 cs_add_windows(int aw, uint32_t bn) 8474 { 8475 cs_window_t *cwp = cs_globals.cw; 8476 cs_window_t *cw, *cwpp; 8477 8478 if (aw <= 0) 8479 return (CS_BAD_WINDOW); 8480 8481 while (cwp) { 8482 cwpp = cwp; 8483 cwp = cwp->next; 8484 } 8485 8486 while (aw--) { 8487 cw = (cs_window_t *)kmem_zalloc(sizeof (cs_window_t), KM_SLEEP); 8488 8489 if (cs_globals.cw == NULL) { 8490 cs_globals.cw = cw; 8491 cwpp = cs_globals.cw; 8492 } else { 8493 cwpp->next = cw; 8494 cwpp = cwpp->next; 8495 } 8496 8497 cwpp->window_num = bn++; 8498 cwpp->state = CW_WINDOW_VALID; 8499 8500 } /* while (aw) */ 8501 8502 return (CS_SUCCESS); 8503 } 8504 8505 /* 8506 * cs_ss_init - initialize CS items that need to wait until we receive 8507 * a PCE_SS_INIT_STATE/PCE_SS_STATE_INIT event 8508 * 8509 * return: CS_SUCESS - if sucessfully initialized 8510 * (various) if error initializing 8511 * 8512 * At this point, we expect that Socket Services has setup the 8513 * following global variables for us: 8514 * 8515 * cs_socket_services - Socket Services entry point 8516 * cis_parser - CIS parser entry point 8517 */ 8518 static uint32_t 8519 cs_ss_init() 8520 { 8521 cs_register_cardservices_t rcs; 8522 csregister_t csr; 8523 uint32_t ret; 8524 8525 /* 8526 * Fill out the parameters for CISP_CIS_SETUP 8527 */ 8528 csr.cs_magic = PCCS_MAGIC; 8529 csr.cs_version = PCCS_VERSION; 8530 csr.cs_card_services = CardServices; 8531 csr.cs_event = NULL; 8532 8533 /* 8534 * Call into the CIS module and tell it what the private 8535 * Card Services entry point is. The CIS module will 8536 * call us back at CardServices(CISRegister, ...) 8537 * with the address of various CIS-specific global 8538 * data structures. 8539 */ 8540 CIS_PARSER(CISP_CIS_SETUP, &csr); 8541 8542 /* 8543 * Register with the Card Services kernel stubs module 8544 */ 8545 rcs.magic = CS_STUBS_MAGIC; 8546 rcs.function = CS_ENTRY_REGISTER; 8547 rcs.cardservices = CardServices; 8548 8549 if ((ret = csx_register_cardservices(&rcs)) != CS_SUCCESS) { 8550 cmn_err(CE_CONT, "cs_ss_init: can't register with " 8551 "cs_stubs, retcode = 0x%x\n", ret); 8552 return (ret); 8553 } /* csx_register_cardservices */ 8554 8555 return (CS_SUCCESS); 8556 } 8557 8558 /* 8559 * cs_create_cis - reads CIS on card in socket and creates CIS lists 8560 * 8561 * Most of the work is done in the CIS module in the CISP_CIS_LIST_CREATE 8562 * function. 8563 * 8564 * This function returns: 8565 * 8566 * CS_SUCCESS - if the CIS lists were created sucessfully 8567 * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 8568 * not be setup 8569 * CS_BAD_CIS - if error creating CIS chains 8570 * CS_BAD_OFFSET - if the CIS parser tried to read past the 8571 * boundries of the allocated CIS window 8572 */ 8573 static int 8574 cs_create_cis(cs_socket_t *sp) 8575 { 8576 uint32_t ret; 8577 8578 ret = (uint32_t)(uintptr_t)CIS_PARSER(CISP_CIS_LIST_CREATE, 8579 cis_cistpl_std_callout, sp); 8580 8581 #ifdef CS_DEBUG 8582 if (ret == CS_NO_CIS) { 8583 if (cs_debug > 0) 8584 cmn_err(CE_CONT, "cs_create_cis: socket %d has no CIS\n", 8585 sp->socket_num); 8586 } else if (ret != CS_SUCCESS) { 8587 if (cs_debug > 0) 8588 cmn_err(CE_CONT, "cs_create_cis: socket %d ERROR = 0x%x\n", 8589 sp->socket_num, ret); 8590 return (ret); 8591 } 8592 #else 8593 if (ret != CS_NO_CIS) 8594 if (ret != CS_SUCCESS) 8595 return (ret); 8596 #endif 8597 8598 /* 8599 * If this card didn't have any CIS at all, there's not much 8600 * else for us to do. 8601 */ 8602 if (!(sp->cis_flags & CW_VALID_CIS)) 8603 return (CS_SUCCESS); 8604 8605 /* 8606 * If this is a single-function card, we need to move the CIS list 8607 * that is currently on CS_GLOBAL_CIS to the function zero 8608 * CIS list. 8609 */ 8610 if (!(sp->cis_flags & CW_MULTI_FUNCTION_CIS)) { 8611 bcopy((caddr_t)&sp->cis[CS_GLOBAL_CIS], 8612 (caddr_t)&sp->cis[0], sizeof (cis_info_t)); 8613 bzero((caddr_t)&sp->cis[CS_GLOBAL_CIS], sizeof (cis_info_t)); 8614 } /* !CW_MULTI_FUNCTION_CIS */ 8615 8616 return (CS_SUCCESS); 8617 } 8618 8619 /* 8620 * cs_destroy_cis - destroys CIS list for socket 8621 */ 8622 static int 8623 cs_destroy_cis(cs_socket_t *sp) 8624 { 8625 CIS_PARSER(CISP_CIS_LIST_DESTROY, sp); 8626 8627 return (CS_SUCCESS); 8628 } 8629 8630 /* 8631 * cs_get_client_info - This function is GetClientInfo. 8632 * 8633 * calling: client_handle_t - client handle to get client info on 8634 * client_info_t * - pointer to a client_info_t structure 8635 * to return client information in 8636 * 8637 * returns: CS_SUCCESS - if client info retreived from client 8638 * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8639 * handle passed in 8640 * CS_NO_MORE_ITEMS - if client does not handle the 8641 * CS_EVENT_CLIENT_INFO event 8642 * or if invalid client info 8643 * retreived from client 8644 */ 8645 static int 8646 cs_get_client_info(client_handle_t client_handle, client_info_t *ci) 8647 { 8648 cs_socket_t *sp; 8649 client_t *client; 8650 client_info_t *cinfo; 8651 int ret = CS_SUCCESS; 8652 8653 if (CLIENT_HANDLE_IS_SS(client_handle)) { 8654 ci->Attributes = (CS_CLIENT_INFO_SOCKET_SERVICES | 8655 CS_CLIENT_INFO_VALID); 8656 return (CS_SUCCESS); 8657 } /* CLIENT_HANDLE_IS_SS */ 8658 8659 if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 8660 return (CS_BAD_SOCKET); 8661 8662 mutex_enter(&sp->client_lock); 8663 mutex_enter(&sp->lock); 8664 8665 if ((client = cs_find_client(client_handle, &ret)) == NULL) { 8666 mutex_exit(&sp->lock); 8667 mutex_exit(&sp->client_lock); 8668 return (ret); 8669 } /* cs_find_client */ 8670 8671 /* 8672 * If this client is not handling CS_EVENT_CLIENT_INFO events, 8673 * then don't bother to even wake up the event thread. 8674 */ 8675 if (!((client->event_mask | client->global_mask) & 8676 CS_EVENT_CLIENT_INFO)) { 8677 mutex_exit(&sp->lock); 8678 mutex_exit(&sp->client_lock); 8679 return (CS_NO_MORE_ITEMS); 8680 } /* !CS_EVENT_CLIENT_INFO */ 8681 8682 cinfo = &client->event_callback_args.client_info; 8683 8684 bzero((caddr_t)cinfo, sizeof (client_info_t)); 8685 cinfo->Attributes = (ci->Attributes & CS_CLIENT_INFO_SUBSVC_MASK); 8686 8687 client->events |= CS_EVENT_CLIENT_INFO; 8688 8689 sp->thread_state |= SOCKET_WAIT_SYNC; 8690 mutex_exit(&sp->lock); 8691 cv_broadcast(&sp->thread_cv); 8692 cv_wait(&sp->caller_cv, &sp->client_lock); 8693 8694 if (cinfo->Attributes & CS_CLIENT_INFO_VALID) { 8695 bcopy((caddr_t)cinfo, (caddr_t)ci, sizeof (client_info_t)); 8696 ci->Attributes &= (CS_CLIENT_INFO_FLAGS_MASK | 8697 CS_CLIENT_INFO_SUBSVC_MASK); 8698 ci->Attributes &= ~(CS_CLIENT_INFO_CLIENT_MASK | 8699 INFO_CARD_FLAGS_MASK | 8700 CS_CLIENT_INFO_CLIENT_ACTIVE); 8701 ci->Attributes |= (client->flags & (CS_CLIENT_INFO_CLIENT_MASK | 8702 INFO_CARD_FLAGS_MASK)); 8703 (void) strcpy(ci->DriverName, client->driver_name); 8704 if (cs_card_for_client(client)) 8705 ci->Attributes |= CS_CLIENT_INFO_CLIENT_ACTIVE; 8706 } else { 8707 ret = CS_NO_MORE_ITEMS; 8708 } /* CS_CLIENT_INFO_VALID */ 8709 8710 mutex_exit(&sp->client_lock); 8711 8712 return (ret); 8713 } 8714 8715 /* 8716 * cs_get_firstnext_client - This function is GetFirstClient and 8717 * GetNextClient 8718 * 8719 * calling: get_firstnext_client_t * - pointer to a get_firstnext_client_t 8720 * structure to return client handle and 8721 * attributes in 8722 * flags - one of the following: 8723 * CS_GET_FIRST_FLAG - get first client handle 8724 * CS_GET_NEXT_FLAG - get next client handle 8725 * 8726 * returns: CS_SUCCESS - if client info retreived from client 8727 * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8728 * handle passed in 8729 * CS_NO_MORE_ITEMS - if client does not handle the 8730 * CS_EVENT_CLIENT_INFO event 8731 * or if invalid client info 8732 * retreived from client 8733 */ 8734 static int 8735 cs_get_firstnext_client(get_firstnext_client_t *fnc, uint32_t flags) 8736 { 8737 cs_socket_t *sp; 8738 client_t *client; 8739 uint32_t sn = 0; 8740 int ret = CS_SUCCESS; 8741 8742 switch (flags) { 8743 case CS_GET_FIRST_FLAG: 8744 if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8745 while (sn < cs_globals.max_socket_num) { 8746 if ((sp = cs_get_sp(sn)) != NULL) { 8747 mutex_enter(&sp->client_lock); 8748 if ((client = sp->client_list) != NULL) 8749 break; 8750 mutex_exit(&sp->client_lock); 8751 } /* if */ 8752 sn++; 8753 } /* while */ 8754 8755 if (sn == cs_globals.max_socket_num) 8756 return (CS_NO_MORE_ITEMS); 8757 } else if (fnc->Attributes & 8758 CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8759 if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(fnc->Socket))) == 8760 NULL) 8761 return (CS_BAD_SOCKET); 8762 mutex_enter(&sp->client_lock); 8763 if ((client = sp->client_list) == NULL) { 8764 mutex_exit(&sp->client_lock); 8765 return (CS_NO_MORE_ITEMS); 8766 } 8767 } else { 8768 return (CS_BAD_ATTRIBUTE); 8769 } 8770 8771 fnc->client_handle = client->client_handle; 8772 fnc->num_clients = sp->num_clients; 8773 mutex_exit(&sp->client_lock); 8774 break; 8775 case CS_GET_NEXT_FLAG: 8776 if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8777 sn = GET_CLIENT_SOCKET(fnc->client_handle); 8778 8779 if ((sp = cs_get_sp(sn)) == NULL) 8780 return (CS_BAD_SOCKET); 8781 8782 mutex_enter(&sp->client_lock); 8783 if ((client = cs_find_client(fnc->client_handle, 8784 &ret)) == NULL) { 8785 mutex_exit(&sp->client_lock); 8786 return (ret); 8787 } 8788 if ((client = client->next) == NULL) { 8789 mutex_exit(&sp->client_lock); 8790 sn++; 8791 while (sn < cs_globals.max_socket_num) { 8792 if ((sp = cs_get_sp(sn)) != NULL) { 8793 mutex_enter(&sp->client_lock); 8794 if ((client = sp->client_list) != NULL) 8795 break; 8796 mutex_exit(&sp->client_lock); 8797 } /* if */ 8798 sn++; 8799 } /* while */ 8800 8801 if (sn == cs_globals.max_socket_num) 8802 return (CS_NO_MORE_ITEMS); 8803 } /* client = client->next */ 8804 8805 } else if (fnc->Attributes & 8806 CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8807 sp = cs_get_sp(GET_CLIENT_SOCKET(fnc->client_handle)); 8808 if (sp == NULL) 8809 return (CS_BAD_SOCKET); 8810 mutex_enter(&sp->client_lock); 8811 if ((client = cs_find_client(fnc->client_handle, 8812 &ret)) == NULL) { 8813 mutex_exit(&sp->client_lock); 8814 return (ret); 8815 } 8816 if ((client = client->next) == NULL) { 8817 mutex_exit(&sp->client_lock); 8818 return (CS_NO_MORE_ITEMS); 8819 } 8820 } else { 8821 return (CS_BAD_ATTRIBUTE); 8822 } 8823 8824 fnc->client_handle = client->client_handle; 8825 fnc->num_clients = sp->num_clients; 8826 mutex_exit(&sp->client_lock); 8827 break; 8828 default: 8829 ret = CS_BAD_ATTRIBUTE; 8830 break; 8831 8832 } /* switch */ 8833 8834 return (ret); 8835 } 8836 8837 /* 8838 * cs_set_acc_attributes - converts Card Services endianness and 8839 * data ordering values to values 8840 * that Socket Services understands 8841 * 8842 * calling: *sw - pointer to a set_window_t to set attributes in 8843 * Attributes - CS attributes 8844 */ 8845 static void 8846 cs_set_acc_attributes(set_window_t *sw, uint32_t Attributes) 8847 { 8848 sw->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 8849 8850 switch (Attributes & WIN_ACC_ENDIAN_MASK) { 8851 case WIN_ACC_LITTLE_ENDIAN: 8852 sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 8853 break; 8854 case WIN_ACC_BIG_ENDIAN: 8855 sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 8856 break; 8857 case WIN_ACC_NEVER_SWAP: 8858 default: 8859 sw->attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 8860 break; 8861 } /* switch */ 8862 8863 switch (Attributes & WIN_ACC_ORDER_MASK) { 8864 case WIN_ACC_UNORDERED_OK: 8865 sw->attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC; 8866 break; 8867 case WIN_ACC_MERGING_OK: 8868 sw->attr.devacc_attr_dataorder = DDI_MERGING_OK_ACC; 8869 break; 8870 case WIN_ACC_LOADCACHING_OK: 8871 sw->attr.devacc_attr_dataorder = DDI_LOADCACHING_OK_ACC; 8872 break; 8873 case WIN_ACC_STORECACHING_OK: 8874 sw->attr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC; 8875 break; 8876 case WIN_ACC_STRICT_ORDER: 8877 default: 8878 sw->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 8879 break; 8880 } /* switch */ 8881 } 8882