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