1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * PCMCIA Card Services 31*0Sstevel@tonic-gate * The PCMCIA Card Services is a loadable module which 32*0Sstevel@tonic-gate * presents the Card Services interface to client device 33*0Sstevel@tonic-gate * drivers. 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * Card Services uses Socket Services-like calls into the 36*0Sstevel@tonic-gate * PCMCIA nexus driver to manipulate socket and adapter 37*0Sstevel@tonic-gate * resources. 38*0Sstevel@tonic-gate * 39*0Sstevel@tonic-gate * Note that a bunch of comments are not indented correctly with the 40*0Sstevel@tonic-gate * code that they are commenting on. This is because cstyle is 41*0Sstevel@tonic-gate * is inflexible concerning 4-column indenting. 42*0Sstevel@tonic-gate */ 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate #if defined(DEBUG) 45*0Sstevel@tonic-gate #define CS_DEBUG 46*0Sstevel@tonic-gate #endif 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <sys/types.h> 49*0Sstevel@tonic-gate #include <sys/systm.h> 50*0Sstevel@tonic-gate #include <sys/user.h> 51*0Sstevel@tonic-gate #include <sys/buf.h> 52*0Sstevel@tonic-gate #include <sys/file.h> 53*0Sstevel@tonic-gate #include <sys/uio.h> 54*0Sstevel@tonic-gate #include <sys/conf.h> 55*0Sstevel@tonic-gate #include <sys/stat.h> 56*0Sstevel@tonic-gate #include <sys/autoconf.h> 57*0Sstevel@tonic-gate #include <sys/vtoc.h> 58*0Sstevel@tonic-gate #include <sys/dkio.h> 59*0Sstevel@tonic-gate #include <sys/ddi.h> 60*0Sstevel@tonic-gate #include <sys/sunddi.h> 61*0Sstevel@tonic-gate #include <sys/debug.h> 62*0Sstevel@tonic-gate #include <sys/varargs.h> 63*0Sstevel@tonic-gate #include <sys/var.h> 64*0Sstevel@tonic-gate #include <sys/proc.h> 65*0Sstevel@tonic-gate #include <sys/thread.h> 66*0Sstevel@tonic-gate #include <sys/utsname.h> 67*0Sstevel@tonic-gate #include <sys/vtrace.h> 68*0Sstevel@tonic-gate #include <sys/kstat.h> 69*0Sstevel@tonic-gate #include <sys/kmem.h> 70*0Sstevel@tonic-gate #include <sys/modctl.h> 71*0Sstevel@tonic-gate #include <sys/kobj.h> 72*0Sstevel@tonic-gate #include <sys/callb.h> 73*0Sstevel@tonic-gate #include <sys/time.h> 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate #include <sys/pctypes.h> 76*0Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h> 77*0Sstevel@tonic-gate #include <sys/pcmcia.h> 78*0Sstevel@tonic-gate #include <sys/sservice.h> 79*0Sstevel@tonic-gate #include <pcmcia/sys/cis.h> 80*0Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h> 81*0Sstevel@tonic-gate #include <pcmcia/sys/cs.h> 82*0Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h> 83*0Sstevel@tonic-gate #include <pcmcia/sys/cs_stubs.h> 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * The cs_strings header file is where all of the major strings that 87*0Sstevel@tonic-gate * Card Services uses are located. 88*0Sstevel@tonic-gate */ 89*0Sstevel@tonic-gate #include <pcmcia/sys/cs_strings.h> 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * Function declarations 94*0Sstevel@tonic-gate * 95*0Sstevel@tonic-gate * The main Card Services entry point 96*0Sstevel@tonic-gate */ 97*0Sstevel@tonic-gate int CardServices(int function, ...); 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * functions and globals used by Socket Services 101*0Sstevel@tonic-gate * 102*0Sstevel@tonic-gate * WAS: void *(*cis_parser)(int, ...) = NULL; 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate void *(*cis_parser)(int, ...) = NULL; 105*0Sstevel@tonic-gate csfunction_t *cs_socket_services = NULL; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate /* 108*0Sstevel@tonic-gate * event handling functions 109*0Sstevel@tonic-gate */ 110*0Sstevel@tonic-gate static event_t ss_to_cs_events(cs_socket_t *, event_t); 111*0Sstevel@tonic-gate static event_t cs_cse2sbm(event_t); 112*0Sstevel@tonic-gate static void cs_event_thread(uint32_t); 113*0Sstevel@tonic-gate static int cs_card_insertion(cs_socket_t *, event_t); 114*0Sstevel@tonic-gate static int cs_card_removal(cs_socket_t *); 115*0Sstevel@tonic-gate static void cs_ss_thread(uint32_t); 116*0Sstevel@tonic-gate void cs_ready_timeout(void *); 117*0Sstevel@tonic-gate static int cs_card_for_client(client_t *); 118*0Sstevel@tonic-gate static int cs_request_socket_mask(client_handle_t, request_socket_mask_t *); 119*0Sstevel@tonic-gate static int cs_release_socket_mask(client_handle_t, release_socket_mask_t *); 120*0Sstevel@tonic-gate static int cs_get_event_mask(client_handle_t, sockevent_t *); 121*0Sstevel@tonic-gate static int cs_set_event_mask(client_handle_t, sockevent_t *); 122*0Sstevel@tonic-gate static int cs_event2text(event2text_t *, int); 123*0Sstevel@tonic-gate static int cs_read_event_status(cs_socket_t *, client_t *, event_t *, 124*0Sstevel@tonic-gate get_ss_status_t *, int); 125*0Sstevel@tonic-gate uint32_t cs_socket_event_softintr(caddr_t); 126*0Sstevel@tonic-gate void cs_event_softintr_timeout(void *); 127*0Sstevel@tonic-gate static int cs_get_status(client_handle_t, get_status_t *); 128*0Sstevel@tonic-gate static uint32_t cs_sbm2cse(uint32_t); 129*0Sstevel@tonic-gate static unsigned cs_merge_event_masks(cs_socket_t *, client_t *); 130*0Sstevel@tonic-gate static int cs_set_socket_event_mask(cs_socket_t *, unsigned); 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate /* 133*0Sstevel@tonic-gate * SS<->CS communication and internal socket and window handling functions 134*0Sstevel@tonic-gate */ 135*0Sstevel@tonic-gate static uint32_t cs_add_socket(uint32_t); 136*0Sstevel@tonic-gate static uint32_t cs_drop_socket(uint32_t); 137*0Sstevel@tonic-gate static cs_socket_t *cs_get_sp(uint32_t); 138*0Sstevel@tonic-gate static cs_socket_t *cs_find_sp(uint32_t); 139*0Sstevel@tonic-gate static cs_window_t *cs_get_wp(uint32_t); 140*0Sstevel@tonic-gate static cs_window_t *cs_find_wp(uint32_t); 141*0Sstevel@tonic-gate static int cs_add_windows(int, uint32_t); 142*0Sstevel@tonic-gate static uint32_t cs_ss_init(); 143*0Sstevel@tonic-gate static void cs_set_acc_attributes(set_window_t *, uint32_t); 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate /* 146*0Sstevel@tonic-gate * CIS handling functions 147*0Sstevel@tonic-gate */ 148*0Sstevel@tonic-gate cistpl_callout_t *cis_cistpl_std_callout; 149*0Sstevel@tonic-gate static int cs_parse_tuple(client_handle_t, tuple_t *, cisparse_t *, cisdata_t); 150*0Sstevel@tonic-gate static int cs_get_tuple_data(client_handle_t, tuple_t *); 151*0Sstevel@tonic-gate static int cs_validate_cis(client_handle_t, cisinfo_t *); 152*0Sstevel@tonic-gate static int cs_get_firstnext_tuple(client_handle_t, tuple_t *, uint32_t); 153*0Sstevel@tonic-gate static int cs_create_cis(cs_socket_t *); 154*0Sstevel@tonic-gate static int cs_destroy_cis(cs_socket_t *); 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* 157*0Sstevel@tonic-gate * client handling functions 158*0Sstevel@tonic-gate */ 159*0Sstevel@tonic-gate unsigned cs_create_next_client_minor(unsigned, unsigned); 160*0Sstevel@tonic-gate static client_t *cs_find_client(client_handle_t, int *); 161*0Sstevel@tonic-gate static client_handle_t cs_create_client_handle(unsigned, client_t *); 162*0Sstevel@tonic-gate static int cs_destroy_client_handle(client_handle_t); 163*0Sstevel@tonic-gate static int cs_register_client(client_handle_t *, client_reg_t *); 164*0Sstevel@tonic-gate static int cs_deregister_client(client_handle_t); 165*0Sstevel@tonic-gate static int cs_deregister_mtd(client_handle_t); 166*0Sstevel@tonic-gate static void cs_clear_superclient_lock(int); 167*0Sstevel@tonic-gate static int cs_add_client_to_socket(unsigned, client_handle_t *, 168*0Sstevel@tonic-gate client_reg_t *, int); 169*0Sstevel@tonic-gate static int cs_get_client_info(client_handle_t, client_info_t *); 170*0Sstevel@tonic-gate static int cs_get_firstnext_client(get_firstnext_client_t *, uint32_t); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* 173*0Sstevel@tonic-gate * window handling functions 174*0Sstevel@tonic-gate */ 175*0Sstevel@tonic-gate static int cs_request_window(client_handle_t, window_handle_t *, win_req_t *); 176*0Sstevel@tonic-gate static int cs_release_window(window_handle_t); 177*0Sstevel@tonic-gate static int cs_modify_window(window_handle_t, modify_win_t *); 178*0Sstevel@tonic-gate static int cs_modify_mem_window(window_handle_t, modify_win_t *, win_req_t *, 179*0Sstevel@tonic-gate int); 180*0Sstevel@tonic-gate static int cs_map_mem_page(window_handle_t, map_mem_page_t *); 181*0Sstevel@tonic-gate static int cs_find_mem_window(uint32_t, win_req_t *, uint32_t *); 182*0Sstevel@tonic-gate static int cs_memwin_space_and_map_ok(inquire_window_t *, win_req_t *); 183*0Sstevel@tonic-gate static int cs_valid_window_speed(inquire_window_t *, uint32_t); 184*0Sstevel@tonic-gate static window_handle_t cs_create_window_handle(uint32_t); 185*0Sstevel@tonic-gate static cs_window_t *cs_find_window(window_handle_t); 186*0Sstevel@tonic-gate static int cs_find_io_win(uint32_t, iowin_char_t *, uint32_t *, uint32_t *); 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * IO, IRQ and configuration handling functions 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate static int cs_request_io(client_handle_t, io_req_t *); 192*0Sstevel@tonic-gate static int cs_release_io(client_handle_t, io_req_t *); 193*0Sstevel@tonic-gate static int cs_allocate_io_win(uint32_t, uint32_t, uint32_t *); 194*0Sstevel@tonic-gate static int cs_setup_io_win(uint32_t, uint32_t, baseaddru_t *, 195*0Sstevel@tonic-gate uint32_t *, uint32_t, uint32_t); 196*0Sstevel@tonic-gate static int cs_request_irq(client_handle_t, irq_req_t *); 197*0Sstevel@tonic-gate static int cs_release_irq(client_handle_t, irq_req_t *); 198*0Sstevel@tonic-gate static int cs_request_configuration(client_handle_t, config_req_t *); 199*0Sstevel@tonic-gate static int cs_release_configuration(client_handle_t, release_config_t *); 200*0Sstevel@tonic-gate static int cs_modify_configuration(client_handle_t, modify_config_t *); 201*0Sstevel@tonic-gate static int cs_access_configuration_register(client_handle_t, 202*0Sstevel@tonic-gate access_config_reg_t *); 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate /* 205*0Sstevel@tonic-gate * RESET and general info functions 206*0Sstevel@tonic-gate */ 207*0Sstevel@tonic-gate static int cs_reset_function(client_handle_t, reset_function_t *); 208*0Sstevel@tonic-gate static int cs_get_configuration_info(client_handle_t *, 209*0Sstevel@tonic-gate get_configuration_info_t *); 210*0Sstevel@tonic-gate static int cs_get_cardservices_info(client_handle_t, 211*0Sstevel@tonic-gate get_cardservices_info_t *); 212*0Sstevel@tonic-gate static int cs_get_physical_adapter_info(client_handle_t, 213*0Sstevel@tonic-gate get_physical_adapter_info_t *); 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* 216*0Sstevel@tonic-gate * general functions 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate static uint32_t cs_get_socket(client_handle_t, uint32_t *, uint32_t *, 219*0Sstevel@tonic-gate cs_socket_t **, client_t **); 220*0Sstevel@tonic-gate static int cs_convert_speed(convert_speed_t *); 221*0Sstevel@tonic-gate static int cs_convert_size(convert_size_t *); 222*0Sstevel@tonic-gate static char *cs_error2text(int, int); 223*0Sstevel@tonic-gate static int cs_map_log_socket(client_handle_t, map_log_socket_t *); 224*0Sstevel@tonic-gate static int cs_convert_powerlevel(uint32_t, uint32_t, uint32_t, unsigned *); 225*0Sstevel@tonic-gate static int cs_make_device_node(client_handle_t, make_device_node_t *); 226*0Sstevel@tonic-gate static int cs_remove_device_node(client_handle_t, remove_device_node_t *); 227*0Sstevel@tonic-gate static int cs_ddi_info(cs_ddi_info_t *); 228*0Sstevel@tonic-gate static int cs_init_cis_window(cs_socket_t *, uint32_t *, acc_handle_t *, 229*0Sstevel@tonic-gate uint32_t); 230*0Sstevel@tonic-gate static int cs_sys_ctl(cs_sys_ctl_t *); 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate /* 233*0Sstevel@tonic-gate * global variables 234*0Sstevel@tonic-gate */ 235*0Sstevel@tonic-gate static int cs_max_client_handles = CS_MAX_CLIENTS; 236*0Sstevel@tonic-gate static client_t cs_socket_services_client; /* global SS client */ 237*0Sstevel@tonic-gate static client_types_t client_types[MAX_CLIENT_TYPES]; 238*0Sstevel@tonic-gate static cs_globals_t cs_globals; 239*0Sstevel@tonic-gate int cs_reset_timeout_time = RESET_TIMEOUT_TIME; 240*0Sstevel@tonic-gate int cs_rc1_delay = CS_RC1_DELAY; 241*0Sstevel@tonic-gate int cs_rc2_delay = CS_RC2_DELAY; 242*0Sstevel@tonic-gate int cs_rq_delay = CS_RQ_DELAY; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate #ifdef CS_DEBUG 245*0Sstevel@tonic-gate int cs_debug = 0; 246*0Sstevel@tonic-gate #endif 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate /* 249*0Sstevel@tonic-gate * cs_init - Initialize CS internal structures, databases, and state, 250*0Sstevel@tonic-gate * and register with SS 251*0Sstevel@tonic-gate * 252*0Sstevel@tonic-gate * XXX - Need to make sure that if we fail at any point that we free 253*0Sstevel@tonic-gate * any resources that we allocated, as well as kill any 254*0Sstevel@tonic-gate * threads that may have been started. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate int 257*0Sstevel@tonic-gate cs_init() 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate client_types_t *ct; 260*0Sstevel@tonic-gate client_t *client; 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * Initialize the CS global structure 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate bzero((caddr_t)&cs_globals, sizeof (cs_globals_t)); 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate mutex_init(&cs_globals.global_lock, NULL, MUTEX_DRIVER, NULL); 268*0Sstevel@tonic-gate mutex_init(&cs_globals.window_lock, NULL, MUTEX_DRIVER, NULL); 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate cs_globals.init_state = GLOBAL_INIT_STATE_MUTEX; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate /* 273*0Sstevel@tonic-gate * Set up the global Socket Services client, since we're going to 274*0Sstevel@tonic-gate * need it once we register with SS. 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate client = &cs_socket_services_client; 277*0Sstevel@tonic-gate bzero((caddr_t)client, sizeof (client_t)); 278*0Sstevel@tonic-gate client->client_handle = CS_SS_CLIENT_HANDLE; 279*0Sstevel@tonic-gate client->flags |= (INFO_SOCKET_SERVICES | CLIENT_CARD_INSERTED); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* 282*0Sstevel@tonic-gate * Setup the client type structure - this is used in the socket event 283*0Sstevel@tonic-gate * thread to sequence the delivery of events to all clients on 284*0Sstevel@tonic-gate * the socket. 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate ct = &client_types[0]; 287*0Sstevel@tonic-gate ct->type = INFO_IO_CLIENT; 288*0Sstevel@tonic-gate ct->order = CLIENT_EVENTS_LIFO; 289*0Sstevel@tonic-gate ct->next = &client_types[1]; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate ct = ct->next; 292*0Sstevel@tonic-gate ct->type = INFO_MTD_CLIENT; 293*0Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 294*0Sstevel@tonic-gate ct->next = &client_types[2]; 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate ct = ct->next; 297*0Sstevel@tonic-gate ct->type = INFO_MEM_CLIENT; 298*0Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 299*0Sstevel@tonic-gate ct->next = NULL; 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate return (CS_SUCCESS); 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate /* 305*0Sstevel@tonic-gate * cs_deinit - Deinitialize CS 306*0Sstevel@tonic-gate * 307*0Sstevel@tonic-gate * This function cleans up any allocated resources, stops any running threads, 308*0Sstevel@tonic-gate * destroys any mutexes and condition variables, and finally frees up the 309*0Sstevel@tonic-gate * global socket and window structure arrays. 310*0Sstevel@tonic-gate */ 311*0Sstevel@tonic-gate int 312*0Sstevel@tonic-gate cs_deinit() 313*0Sstevel@tonic-gate { 314*0Sstevel@tonic-gate cs_socket_t *sp; 315*0Sstevel@tonic-gate int sn, have_clients = 0, have_sockets = 0; 316*0Sstevel@tonic-gate cs_register_cardservices_t rcs; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate #if defined(CS_DEBUG) 319*0Sstevel@tonic-gate if (cs_debug > 1) 320*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: cs_deinit\n"); 321*0Sstevel@tonic-gate #endif 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * Deregister with the Card Services kernel stubs module 325*0Sstevel@tonic-gate */ 326*0Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 327*0Sstevel@tonic-gate rcs.function = CS_ENTRY_DEREGISTER; 328*0Sstevel@tonic-gate (void) csx_register_cardservices(&rcs); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate /* 331*0Sstevel@tonic-gate * Set the GLOBAL_INIT_STATE_NO_CLIENTS flag to prevent new clients 332*0Sstevel@tonic-gate * from registering. 333*0Sstevel@tonic-gate */ 334*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 335*0Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_NO_CLIENTS; 336*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * Go through each socket and make sure that there are no clients 340*0Sstevel@tonic-gate * on any of the sockets. If there are, we can't deinit until 341*0Sstevel@tonic-gate * all the clients for every socket are gone. 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 344*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 345*0Sstevel@tonic-gate have_sockets++; 346*0Sstevel@tonic-gate if (sp->client_list) { 347*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deinit: cannot unload module since " 348*0Sstevel@tonic-gate "socket %d has registered clients\n", sn); 349*0Sstevel@tonic-gate have_clients++; 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* 355*0Sstevel@tonic-gate * We don't allow unload if there are any clients registered 356*0Sstevel@tonic-gate * or if there are still sockets that are active. 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate if ((have_clients > 0) || (have_sockets > 0)) 359*0Sstevel@tonic-gate return (BAD_FUNCTION); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate #ifdef XXX 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * If one or more sockets have been added, we need to deallocate 364*0Sstevel@tonic-gate * the resources associated with those sockets. 365*0Sstevel@tonic-gate */ 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* 368*0Sstevel@tonic-gate * First, tell Socket Services that we're leaving, so that we 369*0Sstevel@tonic-gate * don't get any more event callbacks. 370*0Sstevel@tonic-gate */ 371*0Sstevel@tonic-gate SocketServices(CSUnregister); 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * Wait for the soft int timer to tell us it's done 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 377*0Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_UNLOADING; 378*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 379*0Sstevel@tonic-gate UNTIMEOUT(cs_globals.sotfint_tmo); 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate /* 382*0Sstevel@tonic-gate * Remove the soft interrupt handler. 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 385*0Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR) { 386*0Sstevel@tonic-gate ddi_remove_softintr(cs_globals.softint_id); 387*0Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SOFTINTR; 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate return (CS_SUCCESS); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * Go through each socket and free any resource allocated to that 395*0Sstevel@tonic-gate * socket, as well as any mutexs and condition variables. 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 398*0Sstevel@tonic-gate set_socket_t set_socket; 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* 403*0Sstevel@tonic-gate * untimeout possible pending ready/busy timer 404*0Sstevel@tonic-gate */ 405*0Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 408*0Sstevel@tonic-gate mutex_enter(&sp->lock); 409*0Sstevel@tonic-gate sp->flags = SOCKET_UNLOAD_MODULE; 410*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SOFTINTR) 411*0Sstevel@tonic-gate sp->init_state &= ~SOCKET_INIT_STATE_SOFTINTR; 412*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 413*0Sstevel@tonic-gate mutex_exit(&sp->lock); 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 416*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 417*0Sstevel@tonic-gate (void) cs_destroy_cis(sp); 418*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 419*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * Tell the event handler thread that we want it to exit, then 423*0Sstevel@tonic-gate * wait around until it tells us that it has exited. 424*0Sstevel@tonic-gate */ 425*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 426*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 427*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_THREAD) { 428*0Sstevel@tonic-gate sp->thread_state = SOCKET_THREAD_EXIT; 429*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 430*0Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 431*0Sstevel@tonic-gate } 432*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 433*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* 436*0Sstevel@tonic-gate * Tell the SS work thread that we want it to exit, then 437*0Sstevel@tonic-gate * wait around until it tells us that it has exited. 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 440*0Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 441*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SS_THREAD) { 442*0Sstevel@tonic-gate sp->ss_thread_state = SOCKET_THREAD_EXIT; 443*0Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 444*0Sstevel@tonic-gate cv_wait(&sp->ss_caller_cv, &sp->ss_thread_lock); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 448*0Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate /* 451*0Sstevel@tonic-gate * Free the mutexii and condition variables that we used. 452*0Sstevel@tonic-gate */ 453*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) { 454*0Sstevel@tonic-gate mutex_destroy(&sp->lock); 455*0Sstevel@tonic-gate mutex_destroy(&sp->client_lock); 456*0Sstevel@tonic-gate mutex_destroy(&sp->cis_lock); 457*0Sstevel@tonic-gate mutex_destroy(&sp->ss_thread_lock); 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_CV) { 461*0Sstevel@tonic-gate cv_destroy(&sp->thread_cv); 462*0Sstevel@tonic-gate cv_destroy(&sp->caller_cv); 463*0Sstevel@tonic-gate cv_destroy(&sp->reset_cv); 464*0Sstevel@tonic-gate cv_destroy(&sp->ss_thread_cv); 465*0Sstevel@tonic-gate cv_destroy(&sp->ss_caller_cv); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 469*0Sstevel@tonic-gate /* 470*0Sstevel@tonic-gate * Free the memory-mapped IO structure if we allocated one. 471*0Sstevel@tonic-gate */ 472*0Sstevel@tonic-gate if (sp->io_mmap_window) 473*0Sstevel@tonic-gate kmem_free(sp->io_mmap_window, sizeof (io_mmap_window_t)); 474*0Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate /* 477*0Sstevel@tonic-gate * Return the socket to memory-only mode and turn off the 478*0Sstevel@tonic-gate * socket power. 479*0Sstevel@tonic-gate */ 480*0Sstevel@tonic-gate sp->event_mask = 0; 481*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 482*0Sstevel@tonic-gate set_socket.SCIntMask = 0; 483*0Sstevel@tonic-gate set_socket.IREQRouting = 0; 484*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 485*0Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 486*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 489*0Sstevel@tonic-gate &set_socket.VccLevel); 490*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 491*0Sstevel@tonic-gate &set_socket.Vpp1Level); 492*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 493*0Sstevel@tonic-gate &set_socket.Vpp2Level); 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate /* 496*0Sstevel@tonic-gate * If we fail this call, there's not much we can do, so 497*0Sstevel@tonic-gate * just continue with the resource deallocation. 498*0Sstevel@tonic-gate */ 499*0Sstevel@tonic-gate if ((ret = 500*0Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 501*0Sstevel@tonic-gate cmn_err(CE_CONT, 502*0Sstevel@tonic-gate "cs_deinit: socket %d SS_SetSocket failure %d\n", 503*0Sstevel@tonic-gate sp->socket_num, ret); 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate } /* cs_get_sp */ 506*0Sstevel@tonic-gate } /* for (sn) */ 507*0Sstevel@tonic-gate #endif /* XXX */ 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate /* 510*0Sstevel@tonic-gate * Destroy the global mutexii. 511*0Sstevel@tonic-gate */ 512*0Sstevel@tonic-gate mutex_destroy(&cs_globals.global_lock); 513*0Sstevel@tonic-gate mutex_destroy(&cs_globals.window_lock); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate #ifdef XXX 516*0Sstevel@tonic-gate /* 517*0Sstevel@tonic-gate * Free the global "super-client" structure 518*0Sstevel@tonic-gate */ 519*0Sstevel@tonic-gate if (cs_globals.sclient_list) 520*0Sstevel@tonic-gate kmem_free(cs_globals.sclient_list, 521*0Sstevel@tonic-gate (cs_globals.num_sockets * sizeof (struct sclient_list_t))); 522*0Sstevel@tonic-gate cs_globals.sclient_list = NULL; 523*0Sstevel@tonic-gate #endif /* XXX */ 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate return (CS_SUCCESS); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate /* 529*0Sstevel@tonic-gate * ==== drip, drip, drip - the Card Services waterfall :-) ==== 530*0Sstevel@tonic-gate */ 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate /* 533*0Sstevel@tonic-gate * CardServices - general Card Services entry point for CS clients 534*0Sstevel@tonic-gate * and Socket Services; the address of this 535*0Sstevel@tonic-gate * function is handed to SS via the CSRegister 536*0Sstevel@tonic-gate * SS call 537*0Sstevel@tonic-gate */ 538*0Sstevel@tonic-gate int 539*0Sstevel@tonic-gate CardServices(int function, ...) 540*0Sstevel@tonic-gate { 541*0Sstevel@tonic-gate va_list arglist; 542*0Sstevel@tonic-gate int retcode = CS_UNSUPPORTED_FUNCTION; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate cs_socket_t *socp; 545*0Sstevel@tonic-gate uint32_t *offp; 546*0Sstevel@tonic-gate acc_handle_t *hp; 547*0Sstevel@tonic-gate client_handle_t ch; 548*0Sstevel@tonic-gate client_handle_t *chp; 549*0Sstevel@tonic-gate window_handle_t wh; 550*0Sstevel@tonic-gate window_handle_t *whp; 551*0Sstevel@tonic-gate tuple_t *tuple; 552*0Sstevel@tonic-gate cisparse_t *cisparse; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate #ifdef CS_DEBUG 555*0Sstevel@tonic-gate if (cs_debug > 127) { 556*0Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: called for function %s (0x%x)\n", 557*0Sstevel@tonic-gate cs_error2text(function, CSFUN2TEXT_FUNCTION), 558*0Sstevel@tonic-gate function); 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate #endif 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate va_start(arglist, function); 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate /* 565*0Sstevel@tonic-gate * Here's the Card Services waterfall 566*0Sstevel@tonic-gate */ 567*0Sstevel@tonic-gate switch (function) { 568*0Sstevel@tonic-gate /* 569*0Sstevel@tonic-gate * We got here as a result of the CIS module calling us 570*0Sstevel@tonic-gate * in response to cs_ss_init() calling the CIS module 571*0Sstevel@tonic-gate * at CIS_PARSER(CISP_CIS_SETUP, ...) 572*0Sstevel@tonic-gate */ 573*0Sstevel@tonic-gate case CISRegister: { 574*0Sstevel@tonic-gate cisregister_t *cisr; 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate cisr = va_arg(arglist, cisregister_t *); 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate if (cisr->cis_magic != PCCS_MAGIC || 579*0Sstevel@tonic-gate cisr->cis_version != PCCS_VERSION) { 580*0Sstevel@tonic-gate cmn_err(CE_WARN, 581*0Sstevel@tonic-gate "CS: CISRegister (%lx, %lx, %lx, %lx) *ERROR*", 582*0Sstevel@tonic-gate (long)cisr->cis_magic, 583*0Sstevel@tonic-gate (long)cisr->cis_version, 584*0Sstevel@tonic-gate (long)cisr->cis_parser, 585*0Sstevel@tonic-gate (long)cisr->cistpl_std_callout); 586*0Sstevel@tonic-gate retcode = CS_BAD_ARGS; 587*0Sstevel@tonic-gate } else { 588*0Sstevel@tonic-gate /* 589*0Sstevel@tonic-gate * Replace the CIS Parser entry point if 590*0Sstevel@tonic-gate * necessary. 591*0Sstevel@tonic-gate */ 592*0Sstevel@tonic-gate if (cisr->cis_parser != NULL) 593*0Sstevel@tonic-gate cis_parser = cisr->cis_parser; 594*0Sstevel@tonic-gate cis_cistpl_std_callout = cisr->cistpl_std_callout; 595*0Sstevel@tonic-gate retcode = CS_SUCCESS; 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate break; 599*0Sstevel@tonic-gate case CISUnregister: /* XXX - should we do some more checking */ 600*0Sstevel@tonic-gate /* XXX - need to protect this by a mutex */ 601*0Sstevel@tonic-gate cis_parser = NULL; 602*0Sstevel@tonic-gate cis_cistpl_std_callout = NULL; 603*0Sstevel@tonic-gate retcode = CS_SUCCESS; 604*0Sstevel@tonic-gate break; 605*0Sstevel@tonic-gate case InitCISWindow: 606*0Sstevel@tonic-gate socp = va_arg(arglist, cs_socket_t *); 607*0Sstevel@tonic-gate offp = va_arg(arglist, uint32_t *); 608*0Sstevel@tonic-gate hp = va_arg(arglist, acc_handle_t *); 609*0Sstevel@tonic-gate retcode = cs_init_cis_window(socp, offp, hp, 610*0Sstevel@tonic-gate va_arg(arglist, uint32_t)); 611*0Sstevel@tonic-gate break; 612*0Sstevel@tonic-gate case RegisterClient: 613*0Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *), 614*0Sstevel@tonic-gate retcode = cs_register_client(chp, 615*0Sstevel@tonic-gate va_arg(arglist, client_reg_t *)); 616*0Sstevel@tonic-gate break; 617*0Sstevel@tonic-gate case DeregisterClient: 618*0Sstevel@tonic-gate retcode = cs_deregister_client( 619*0Sstevel@tonic-gate va_arg(arglist, client_handle_t)); 620*0Sstevel@tonic-gate break; 621*0Sstevel@tonic-gate case GetStatus: 622*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 623*0Sstevel@tonic-gate retcode = cs_get_status(ch, 624*0Sstevel@tonic-gate va_arg(arglist, get_status_t *)); 625*0Sstevel@tonic-gate break; 626*0Sstevel@tonic-gate case ResetFunction: 627*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 628*0Sstevel@tonic-gate retcode = cs_reset_function(ch, 629*0Sstevel@tonic-gate va_arg(arglist, reset_function_t *)); 630*0Sstevel@tonic-gate break; 631*0Sstevel@tonic-gate case SetEventMask: 632*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 633*0Sstevel@tonic-gate retcode = cs_set_event_mask(ch, 634*0Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 635*0Sstevel@tonic-gate break; 636*0Sstevel@tonic-gate case GetEventMask: 637*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 638*0Sstevel@tonic-gate retcode = cs_get_event_mask(ch, 639*0Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 640*0Sstevel@tonic-gate break; 641*0Sstevel@tonic-gate case RequestIO: 642*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 643*0Sstevel@tonic-gate retcode = cs_request_io(ch, 644*0Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 645*0Sstevel@tonic-gate break; 646*0Sstevel@tonic-gate case ReleaseIO: 647*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 648*0Sstevel@tonic-gate retcode = cs_release_io(ch, 649*0Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 650*0Sstevel@tonic-gate break; 651*0Sstevel@tonic-gate case RequestIRQ: 652*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 653*0Sstevel@tonic-gate retcode = cs_request_irq(ch, 654*0Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 655*0Sstevel@tonic-gate break; 656*0Sstevel@tonic-gate case ReleaseIRQ: 657*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 658*0Sstevel@tonic-gate retcode = cs_release_irq(ch, 659*0Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 660*0Sstevel@tonic-gate break; 661*0Sstevel@tonic-gate case RequestWindow: 662*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 663*0Sstevel@tonic-gate whp = va_arg(arglist, window_handle_t *); 664*0Sstevel@tonic-gate retcode = cs_request_window(ch, whp, 665*0Sstevel@tonic-gate va_arg(arglist, win_req_t *)); 666*0Sstevel@tonic-gate break; 667*0Sstevel@tonic-gate case ReleaseWindow: 668*0Sstevel@tonic-gate retcode = cs_release_window( 669*0Sstevel@tonic-gate va_arg(arglist, window_handle_t)); 670*0Sstevel@tonic-gate break; 671*0Sstevel@tonic-gate case ModifyWindow: 672*0Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 673*0Sstevel@tonic-gate retcode = cs_modify_window(wh, 674*0Sstevel@tonic-gate va_arg(arglist, modify_win_t *)); 675*0Sstevel@tonic-gate break; 676*0Sstevel@tonic-gate case MapMemPage: 677*0Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 678*0Sstevel@tonic-gate retcode = cs_map_mem_page(wh, 679*0Sstevel@tonic-gate va_arg(arglist, map_mem_page_t *)); 680*0Sstevel@tonic-gate break; 681*0Sstevel@tonic-gate case RequestSocketMask: 682*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 683*0Sstevel@tonic-gate retcode = cs_request_socket_mask(ch, 684*0Sstevel@tonic-gate va_arg(arglist, request_socket_mask_t *)); 685*0Sstevel@tonic-gate break; 686*0Sstevel@tonic-gate case ReleaseSocketMask: 687*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 688*0Sstevel@tonic-gate retcode = cs_release_socket_mask(ch, 689*0Sstevel@tonic-gate va_arg(arglist, release_socket_mask_t *)); 690*0Sstevel@tonic-gate break; 691*0Sstevel@tonic-gate case RequestConfiguration: 692*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 693*0Sstevel@tonic-gate retcode = cs_request_configuration(ch, 694*0Sstevel@tonic-gate va_arg(arglist, config_req_t *)); 695*0Sstevel@tonic-gate break; 696*0Sstevel@tonic-gate case GetPhysicalAdapterInfo: 697*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 698*0Sstevel@tonic-gate retcode = cs_get_physical_adapter_info(ch, 699*0Sstevel@tonic-gate va_arg(arglist, get_physical_adapter_info_t *)); 700*0Sstevel@tonic-gate break; 701*0Sstevel@tonic-gate case GetCardServicesInfo: 702*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 703*0Sstevel@tonic-gate retcode = cs_get_cardservices_info(ch, 704*0Sstevel@tonic-gate va_arg(arglist, get_cardservices_info_t *)); 705*0Sstevel@tonic-gate break; 706*0Sstevel@tonic-gate case GetConfigurationInfo: 707*0Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *); 708*0Sstevel@tonic-gate retcode = cs_get_configuration_info(chp, 709*0Sstevel@tonic-gate va_arg(arglist, get_configuration_info_t *)); 710*0Sstevel@tonic-gate break; 711*0Sstevel@tonic-gate case ModifyConfiguration: 712*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 713*0Sstevel@tonic-gate retcode = cs_modify_configuration(ch, 714*0Sstevel@tonic-gate va_arg(arglist, modify_config_t *)); 715*0Sstevel@tonic-gate break; 716*0Sstevel@tonic-gate case AccessConfigurationRegister: 717*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 718*0Sstevel@tonic-gate retcode = cs_access_configuration_register(ch, 719*0Sstevel@tonic-gate va_arg(arglist, access_config_reg_t *)); 720*0Sstevel@tonic-gate break; 721*0Sstevel@tonic-gate case ReleaseConfiguration: 722*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 723*0Sstevel@tonic-gate retcode = cs_release_configuration(ch, 724*0Sstevel@tonic-gate va_arg(arglist, release_config_t *)); 725*0Sstevel@tonic-gate break; 726*0Sstevel@tonic-gate case OpenMemory: 727*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: OpenMemory\n"); 728*0Sstevel@tonic-gate break; 729*0Sstevel@tonic-gate case ReadMemory: 730*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReadMemory\n"); 731*0Sstevel@tonic-gate break; 732*0Sstevel@tonic-gate case WriteMemory: 733*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: WriteMemory\n"); 734*0Sstevel@tonic-gate break; 735*0Sstevel@tonic-gate case CopyMemory: 736*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CopyMemory\n"); 737*0Sstevel@tonic-gate break; 738*0Sstevel@tonic-gate case RegisterEraseQueue: 739*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterEraseQueue\n"); 740*0Sstevel@tonic-gate break; 741*0Sstevel@tonic-gate case CheckEraseQueue: 742*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CheckEraseQueue\n"); 743*0Sstevel@tonic-gate break; 744*0Sstevel@tonic-gate case DeregisterEraseQueue: 745*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: DeregisterEraseQueue\n"); 746*0Sstevel@tonic-gate break; 747*0Sstevel@tonic-gate case CloseMemory: 748*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CloseMemory\n"); 749*0Sstevel@tonic-gate break; 750*0Sstevel@tonic-gate case GetFirstRegion: 751*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstRegion\n"); 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate case GetNextRegion: 754*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextRegion\n"); 755*0Sstevel@tonic-gate break; 756*0Sstevel@tonic-gate case GetFirstPartition: 757*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstPartition\n"); 758*0Sstevel@tonic-gate break; 759*0Sstevel@tonic-gate case GetNextPartition: 760*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextPartition\n"); 761*0Sstevel@tonic-gate break; 762*0Sstevel@tonic-gate case ReturnSSEntry: 763*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReturnSSEntry\n"); 764*0Sstevel@tonic-gate break; 765*0Sstevel@tonic-gate case MapLogSocket: 766*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 767*0Sstevel@tonic-gate retcode = cs_map_log_socket(ch, 768*0Sstevel@tonic-gate va_arg(arglist, map_log_socket_t *)); 769*0Sstevel@tonic-gate break; 770*0Sstevel@tonic-gate case MapPhySocket: 771*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhySocket\n"); 772*0Sstevel@tonic-gate break; 773*0Sstevel@tonic-gate case MapLogWindow: 774*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapLogWindow\n"); 775*0Sstevel@tonic-gate break; 776*0Sstevel@tonic-gate case MapPhyWindow: 777*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhyWindow\n"); 778*0Sstevel@tonic-gate break; 779*0Sstevel@tonic-gate case RegisterMTD: 780*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterMTD\n"); 781*0Sstevel@tonic-gate break; 782*0Sstevel@tonic-gate case RegisterTimer: 783*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterTimer\n"); 784*0Sstevel@tonic-gate break; 785*0Sstevel@tonic-gate case SetRegion: 786*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: SetRegion\n"); 787*0Sstevel@tonic-gate break; 788*0Sstevel@tonic-gate case RequestExclusive: 789*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RequestExclusive\n"); 790*0Sstevel@tonic-gate break; 791*0Sstevel@tonic-gate case ReleaseExclusive: 792*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReleaseExclusive\n"); 793*0Sstevel@tonic-gate break; 794*0Sstevel@tonic-gate case GetFirstClient: 795*0Sstevel@tonic-gate retcode = cs_get_firstnext_client( 796*0Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 797*0Sstevel@tonic-gate CS_GET_FIRST_FLAG); 798*0Sstevel@tonic-gate break; 799*0Sstevel@tonic-gate case GetNextClient: 800*0Sstevel@tonic-gate retcode = cs_get_firstnext_client( 801*0Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 802*0Sstevel@tonic-gate CS_GET_NEXT_FLAG); 803*0Sstevel@tonic-gate break; 804*0Sstevel@tonic-gate case GetClientInfo: 805*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 806*0Sstevel@tonic-gate retcode = cs_get_client_info(ch, 807*0Sstevel@tonic-gate va_arg(arglist, client_info_t *)); 808*0Sstevel@tonic-gate break; 809*0Sstevel@tonic-gate case AddSocketServices: 810*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AddSocketServices\n"); 811*0Sstevel@tonic-gate break; 812*0Sstevel@tonic-gate case ReplaceSocketServices: 813*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReplaceSocketServices\n"); 814*0Sstevel@tonic-gate break; 815*0Sstevel@tonic-gate case VendorSpecific: 816*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: VendorSpecific\n"); 817*0Sstevel@tonic-gate break; 818*0Sstevel@tonic-gate case AdjustResourceInfo: 819*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AdjustResourceInfo\n"); 820*0Sstevel@tonic-gate break; 821*0Sstevel@tonic-gate case ValidateCIS: 822*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 823*0Sstevel@tonic-gate retcode = cs_validate_cis(ch, 824*0Sstevel@tonic-gate va_arg(arglist, cisinfo_t *)); 825*0Sstevel@tonic-gate break; 826*0Sstevel@tonic-gate case GetFirstTuple: 827*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 828*0Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 829*0Sstevel@tonic-gate va_arg(arglist, tuple_t *), 830*0Sstevel@tonic-gate CS_GET_FIRST_FLAG); 831*0Sstevel@tonic-gate break; 832*0Sstevel@tonic-gate case GetNextTuple: 833*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 834*0Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 835*0Sstevel@tonic-gate va_arg(arglist, tuple_t *), 836*0Sstevel@tonic-gate CS_GET_NEXT_FLAG); 837*0Sstevel@tonic-gate break; 838*0Sstevel@tonic-gate case GetTupleData: 839*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 840*0Sstevel@tonic-gate retcode = cs_get_tuple_data(ch, 841*0Sstevel@tonic-gate va_arg(arglist, tuple_t *)); 842*0Sstevel@tonic-gate break; 843*0Sstevel@tonic-gate case ParseTuple: 844*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 845*0Sstevel@tonic-gate tuple = va_arg(arglist, tuple_t *); 846*0Sstevel@tonic-gate cisparse = va_arg(arglist, cisparse_t *); 847*0Sstevel@tonic-gate retcode = cs_parse_tuple(ch, tuple, cisparse, 848*0Sstevel@tonic-gate va_arg(arglist, uint_t)); 849*0Sstevel@tonic-gate break; 850*0Sstevel@tonic-gate case MakeDeviceNode: 851*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 852*0Sstevel@tonic-gate retcode = cs_make_device_node(ch, 853*0Sstevel@tonic-gate va_arg(arglist, make_device_node_t *)); 854*0Sstevel@tonic-gate break; 855*0Sstevel@tonic-gate case RemoveDeviceNode: 856*0Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 857*0Sstevel@tonic-gate retcode = cs_remove_device_node(ch, 858*0Sstevel@tonic-gate va_arg(arglist, remove_device_node_t *)); 859*0Sstevel@tonic-gate break; 860*0Sstevel@tonic-gate case ConvertSpeed: 861*0Sstevel@tonic-gate retcode = cs_convert_speed( 862*0Sstevel@tonic-gate va_arg(arglist, convert_speed_t *)); 863*0Sstevel@tonic-gate break; 864*0Sstevel@tonic-gate case ConvertSize: 865*0Sstevel@tonic-gate retcode = cs_convert_size( 866*0Sstevel@tonic-gate va_arg(arglist, convert_size_t *)); 867*0Sstevel@tonic-gate break; 868*0Sstevel@tonic-gate case Event2Text: 869*0Sstevel@tonic-gate retcode = cs_event2text( 870*0Sstevel@tonic-gate va_arg(arglist, event2text_t *), 1); 871*0Sstevel@tonic-gate break; 872*0Sstevel@tonic-gate case Error2Text: { 873*0Sstevel@tonic-gate error2text_t *cft; 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate cft = va_arg(arglist, error2text_t *); 876*0Sstevel@tonic-gate (void) strcpy(cft->text, 877*0Sstevel@tonic-gate cs_error2text(cft->item, CSFUN2TEXT_RETURN)); 878*0Sstevel@tonic-gate retcode = CS_SUCCESS; 879*0Sstevel@tonic-gate } 880*0Sstevel@tonic-gate break; 881*0Sstevel@tonic-gate case CS_DDI_Info: 882*0Sstevel@tonic-gate retcode = cs_ddi_info(va_arg(arglist, cs_ddi_info_t *)); 883*0Sstevel@tonic-gate break; 884*0Sstevel@tonic-gate case CS_Sys_Ctl: 885*0Sstevel@tonic-gate retcode = cs_sys_ctl(va_arg(arglist, cs_sys_ctl_t *)); 886*0Sstevel@tonic-gate break; 887*0Sstevel@tonic-gate default: 888*0Sstevel@tonic-gate cmn_err(CE_CONT, "CS: {unknown function %d}\n", function); 889*0Sstevel@tonic-gate break; 890*0Sstevel@tonic-gate } /* switch(function) */ 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate va_end(arglist); 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate #ifdef CS_DEBUG 895*0Sstevel@tonic-gate if (cs_debug > 127) { 896*0Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: returning %s (0x%x)\n", 897*0Sstevel@tonic-gate cs_error2text(retcode, CSFUN2TEXT_RETURN), 898*0Sstevel@tonic-gate retcode); 899*0Sstevel@tonic-gate } 900*0Sstevel@tonic-gate #endif 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate return (retcode); 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate /* 906*0Sstevel@tonic-gate * ==== tuple and CIS handling section ==== 907*0Sstevel@tonic-gate */ 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate /* 910*0Sstevel@tonic-gate * cs_parse_tuple - This function supports the CS ParseTuple function call. 911*0Sstevel@tonic-gate * 912*0Sstevel@tonic-gate * returns: CS_SUCCESS - if tuple parsed sucessfully 913*0Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 914*0Sstevel@tonic-gate * CS_BAD_ARGS - if passed CIS list pointer is NULL 915*0Sstevel@tonic-gate * CS_UNKNOWN_TUPLE - if unknown tuple passed to CIS parser 916*0Sstevel@tonic-gate * CS_BAD_CIS - if generic parser error 917*0Sstevel@tonic-gate * CS_NO_CIS - if no CIS for card/function 918*0Sstevel@tonic-gate * 919*0Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 920*0Sstevel@tonic-gate */ 921*0Sstevel@tonic-gate static int 922*0Sstevel@tonic-gate cs_parse_tuple(client_handle_t client_handle, tuple_t *tuple, 923*0Sstevel@tonic-gate cisparse_t *cisparse, cisdata_t cisdata) 924*0Sstevel@tonic-gate { 925*0Sstevel@tonic-gate cs_socket_t *sp; 926*0Sstevel@tonic-gate client_t *client; 927*0Sstevel@tonic-gate uint32_t fn; 928*0Sstevel@tonic-gate int ret; 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, 931*0Sstevel@tonic-gate &fn, &sp, &client)) != CS_SUCCESS) 932*0Sstevel@tonic-gate return (ret); 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate /* 935*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 936*0Sstevel@tonic-gate * for this client, then return an error. 937*0Sstevel@tonic-gate */ 938*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 939*0Sstevel@tonic-gate return (CS_NO_CARD); 940*0Sstevel@tonic-gate 941*0Sstevel@tonic-gate /* 942*0Sstevel@tonic-gate * Sanity check to be sure that we've got a non-NULL CIS list 943*0Sstevel@tonic-gate * pointer. 944*0Sstevel@tonic-gate */ 945*0Sstevel@tonic-gate if (!(tuple->CISOffset)) 946*0Sstevel@tonic-gate return (CS_BAD_ARGS); 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate /* 951*0Sstevel@tonic-gate * Check to see if there is a valid CIS for this function. 952*0Sstevel@tonic-gate * There is an implicit assumption here that if this 953*0Sstevel@tonic-gate * is a multi-function CIS and the specified function 954*0Sstevel@tonic-gate * number is not CS_GLOBAL_CIS that in order for there 955*0Sstevel@tonic-gate * to be a valid function-specific CIS, there also must 956*0Sstevel@tonic-gate * be a valid global CIS. This means that we don't need 957*0Sstevel@tonic-gate * to know whether this tuple came from the global CIS 958*0Sstevel@tonic-gate * or from the function-specific CIS. 959*0Sstevel@tonic-gate */ 960*0Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 961*0Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 962*0Sstevel@tonic-gate ret = (int)(uintptr_t)CIS_PARSER(CISP_CIS_PARSE_TUPLE, 963*0Sstevel@tonic-gate cis_cistpl_std_callout, 964*0Sstevel@tonic-gate tuple->CISOffset, 965*0Sstevel@tonic-gate (tuple->Attributes & TUPLE_RETURN_NAME)? 966*0Sstevel@tonic-gate HANDTPL_RETURN_NAME: 967*0Sstevel@tonic-gate HANDTPL_PARSE_LTUPLE, 968*0Sstevel@tonic-gate cisparse, cisdata); 969*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 970*0Sstevel@tonic-gate if (ret == CISTPLF_UNKNOWN) 971*0Sstevel@tonic-gate return (CS_UNKNOWN_TUPLE); 972*0Sstevel@tonic-gate if (ret != CISTPLF_NOERROR) 973*0Sstevel@tonic-gate return (CS_BAD_CIS); 974*0Sstevel@tonic-gate ret = CS_SUCCESS; 975*0Sstevel@tonic-gate } else { 976*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 977*0Sstevel@tonic-gate ret = CS_NO_CIS; 978*0Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate return (ret); 981*0Sstevel@tonic-gate } 982*0Sstevel@tonic-gate 983*0Sstevel@tonic-gate /* 984*0Sstevel@tonic-gate * cs_get_firstnext_tuple - returns the first/next tuple of the specified type 985*0Sstevel@tonic-gate * this is to support the GetFirstTuple and 986*0Sstevel@tonic-gate * GetNextTuple function call 987*0Sstevel@tonic-gate * 988*0Sstevel@tonic-gate * flags - one of: 989*0Sstevel@tonic-gate * CS_GET_FIRST_FLAG causes function to support GetFirstTuple 990*0Sstevel@tonic-gate * CS_GET_NEXT_FLAG causes function to support GetNextTuple 991*0Sstevel@tonic-gate * 992*0Sstevel@tonic-gate * tuple_t->Attributes flags: 993*0Sstevel@tonic-gate * TUPLE_RETURN_LINK - XXX Not implemented, see notes below. 994*0Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES - return tuples with 995*0Sstevel@tonic-gate * CISTPLF_IGNORE_TUPLE set in the 996*0Sstevel@tonic-gate * cistpl_t->flags member. 997*0Sstevel@tonic-gate * 998*0Sstevel@tonic-gate * Notes for regular PC card driver callers: 999*0Sstevel@tonic-gate * 1000*0Sstevel@tonic-gate * On a single-function card, the caller will get back all the tuples in 1001*0Sstevel@tonic-gate * the CIS. 1002*0Sstevel@tonic-gate * 1003*0Sstevel@tonic-gate * On a multi-function card, the caller will get the tuples from the 1004*0Sstevel@tonic-gate * global CIS followed by the tuples in the function-specific CIS. The 1005*0Sstevel@tonic-gate * caller will not get any tuples from a function-specific CIS that 1006*0Sstevel@tonic-gate * does not belong to the caller's function. 1007*0Sstevel@tonic-gate * 1008*0Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 1009*0Sstevel@tonic-gate * 1010*0Sstevel@tonic-gate * On a single-function card, the operation is the same as for regular 1011*0Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 1012*0Sstevel@tonic-gate * is set to CS_GLOBAL_CIS this function will return CS_NO_CIS. 1013*0Sstevel@tonic-gate * 1014*0Sstevel@tonic-gate * On a multi-function card, the operation is the same as for regular 1015*0Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 1016*0Sstevel@tonic-gate * is set to CS_GLOBAL_CIS the caller will only get tuples from the 1017*0Sstevel@tonic-gate * global CIS. If a particular function nubmer does not exist, this 1018*0Sstevel@tonic-gate * function will return CS_NO_CIS for that function. 1019*0Sstevel@tonic-gate * 1020*0Sstevel@tonic-gate * General notes: 1021*0Sstevel@tonic-gate * 1022*0Sstevel@tonic-gate * On both a single-function card and a multi-function card, if the tuple 1023*0Sstevel@tonic-gate * comes from the global CIS chain, the CISTPLF_GLOBAL_CIS flag will be 1024*0Sstevel@tonic-gate * set in the tuple_t->flags member. 1025*0Sstevel@tonic-gate * 1026*0Sstevel@tonic-gate * On a multi-function card, if the tuple comes from the function-specific 1027*0Sstevel@tonic-gate * CIS chain, the CISTPLF_MF_CIS flag will be set in the tuple_t->flags 1028*0Sstevel@tonic-gate * member. 1029*0Sstevel@tonic-gate * 1030*0Sstevel@tonic-gate * For other flags that are set in the tuple_t->flags member, see the 1031*0Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 1032*0Sstevel@tonic-gate * 1033*0Sstevel@tonic-gate * The CIS parser may not include all the tuples that are in the CIS in 1034*0Sstevel@tonic-gate * the private CIS list that it creates and maintains. See the CIS 1035*0Sstevel@tonic-gate * parser documentation for a list of tuples that the parser does not 1036*0Sstevel@tonic-gate * include in the list. 1037*0Sstevel@tonic-gate * 1038*0Sstevel@tonic-gate * If a tuple has the CISTPLF_IGNORE_TUPLE flag set and the flags 1039*0Sstevel@tonic-gate * parameter CIS_GET_LTUPLE_IGNORE is not set, that tuple will not 1040*0Sstevel@tonic-gate * be returned to the caller. Instead, the next tuple that matches 1041*0Sstevel@tonic-gate * the calling criteria will be returned (or NULL if no other tuples 1042*0Sstevel@tonic-gate * match the calling criteria). If CIS_GET_LTUPLE_IGNORE is set in 1043*0Sstevel@tonic-gate * the flags paramter, tuples in the CIS list that match the calling 1044*0Sstevel@tonic-gate * criteria will be returned. 1045*0Sstevel@tonic-gate * 1046*0Sstevel@tonic-gate * XXX The PC Card 95 Standard says that if the TUPLE_RETURN_LINK flag in 1047*0Sstevel@tonic-gate * the tuple_t->Attributes member is not set, then we don't return 1048*0Sstevel@tonic-gate * any of the link tuples. This function ignores this flag and always 1049*0Sstevel@tonic-gate * returns link tuples. 1050*0Sstevel@tonic-gate * 1051*0Sstevel@tonic-gate * Return codes: 1052*0Sstevel@tonic-gate * CS_SUCCESS - if tuple sucessfully found and returned 1053*0Sstevel@tonic-gate * CS_NO_CARD - if no card inserted 1054*0Sstevel@tonic-gate * CS_NO_CIS - if no CIS for the specified card/function 1055*0Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if tuple not found or no more tuples 1056*0Sstevel@tonic-gate * to return 1057*0Sstevel@tonic-gate * 1058*0Sstevel@tonic-gate * See notes for cs_get_socket for a description of valid client, socket 1059*0Sstevel@tonic-gate * and function number combinations. 1060*0Sstevel@tonic-gate */ 1061*0Sstevel@tonic-gate static int 1062*0Sstevel@tonic-gate cs_get_firstnext_tuple(client_handle_t client_handle, 1063*0Sstevel@tonic-gate tuple_t *tuple, uint32_t flags) 1064*0Sstevel@tonic-gate { 1065*0Sstevel@tonic-gate cs_socket_t *sp; 1066*0Sstevel@tonic-gate client_t *client; 1067*0Sstevel@tonic-gate uint32_t fn; 1068*0Sstevel@tonic-gate int ret; 1069*0Sstevel@tonic-gate 1070*0Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1071*0Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1072*0Sstevel@tonic-gate return (ret); 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate /* 1075*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1076*0Sstevel@tonic-gate * for this client, then return an error. 1077*0Sstevel@tonic-gate */ 1078*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1079*0Sstevel@tonic-gate return (CS_NO_CARD); 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate /* 1084*0Sstevel@tonic-gate * If there's no CIS on this card or no CIS for the specified 1085*0Sstevel@tonic-gate * function, then we can't do much. 1086*0Sstevel@tonic-gate */ 1087*0Sstevel@tonic-gate if ((!(sp->cis_flags & CW_VALID_CIS)) || 1088*0Sstevel@tonic-gate (!(sp->cis[fn].flags & CW_VALID_CIS))) { 1089*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1090*0Sstevel@tonic-gate return (CS_NO_CIS); 1091*0Sstevel@tonic-gate } 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate /* 1094*0Sstevel@tonic-gate * This will set the CIS_GET_LTUPLE_IGNORE flag if the 1095*0Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES flag is set. The 1096*0Sstevel@tonic-gate * assumption here is that the CIS_GET_LTUPLE_IGNORE 1097*0Sstevel@tonic-gate * flag and the TUPLE_RETURN_IGNORED_TUPLES flag 1098*0Sstevel@tonic-gate * shares the same bit position. If this ever changes, 1099*0Sstevel@tonic-gate * we'll ahve to re-work this section of code. 1100*0Sstevel@tonic-gate */ 1101*0Sstevel@tonic-gate if (tuple->Attributes & TUPLE_RETURN_IGNORED_TUPLES) 1102*0Sstevel@tonic-gate flags |= CIS_GET_LTUPLE_IGNORE; 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate /* 1105*0Sstevel@tonic-gate * Are we GetFirstTuple or GetNextTuple? 1106*0Sstevel@tonic-gate */ 1107*0Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_OPMASK) & CS_GET_FIRST_FLAG) { 1108*0Sstevel@tonic-gate /* 1109*0Sstevel@tonic-gate * Initialize the tuple structure; we need this information when 1110*0Sstevel@tonic-gate * we have to process a GetNextTuple or ParseTuple call. 1111*0Sstevel@tonic-gate * If this card has a multi-function CIS, then we always start out 1112*0Sstevel@tonic-gate * delivering tuples from the global CIS chain. If this card does 1113*0Sstevel@tonic-gate * not have a multi-function CIS, then the function 0 CIS chain 1114*0Sstevel@tonic-gate * will contain the complete CIS list. 1115*0Sstevel@tonic-gate * If this is a multi-function card, then use the GET_FIRST_LTUPLE 1116*0Sstevel@tonic-gate * macro to return the first tuple in the CIS list - we do this 1117*0Sstevel@tonic-gate * since we don't want to return tuples with CISTPLF_IGNORE_TUPLE 1118*0Sstevel@tonic-gate * set unless CIS_GET_LTUPLE_IGNORE is set in the flags parameter. 1119*0Sstevel@tonic-gate * Note that we don't have to cross over into the fucntion-specific 1120*0Sstevel@tonic-gate * CIS chain if GET_FIRST_LTUPLE returns NULL, since a MF CIS will 1121*0Sstevel@tonic-gate * always have at least a CISTPL_LONGLINK_MFC tuple in the global 1122*0Sstevel@tonic-gate * CIS chain - the test for NULL is just a sanity check. 1123*0Sstevel@tonic-gate */ 1124*0Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1125*0Sstevel@tonic-gate if ((tuple->CISOffset = 1126*0Sstevel@tonic-gate GET_FIRST_LTUPLE(sp->cis[CS_GLOBAL_CIS].cis, 1127*0Sstevel@tonic-gate flags)) == NULL) { 1128*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1129*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1130*0Sstevel@tonic-gate } /* GET_FIRST_LTUPLE */ 1131*0Sstevel@tonic-gate } else { 1132*0Sstevel@tonic-gate tuple->CISOffset = sp->cis[0].cis; 1133*0Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1134*0Sstevel@tonic-gate } else { 1135*0Sstevel@tonic-gate cistpl_t *tp; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate /* 1138*0Sstevel@tonic-gate * Check to be sure that we have a non-NULL tuple list pointer. 1139*0Sstevel@tonic-gate * This is necessary in the case where the caller calls us 1140*0Sstevel@tonic-gate * with get next tuple requests but we don't have any more 1141*0Sstevel@tonic-gate * tuples to give back. 1142*0Sstevel@tonic-gate */ 1143*0Sstevel@tonic-gate if (tuple->CISOffset == NULL) { 1144*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1145*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate /* 1149*0Sstevel@tonic-gate * Point to the next tuple in the list. If we're searching for 1150*0Sstevel@tonic-gate * a particular tuple, FIND_LTUPLE_FWD will find it. 1151*0Sstevel@tonic-gate * 1152*0Sstevel@tonic-gate * If there are no more tuples in the chain that we're looking 1153*0Sstevel@tonic-gate * at, then if we're looking at the global portion of a 1154*0Sstevel@tonic-gate * multi-function CIS, switch to the function-specific list 1155*0Sstevel@tonic-gate * and start looking there. 1156*0Sstevel@tonic-gate */ 1157*0Sstevel@tonic-gate if ((tp = GET_NEXT_TUPLE(tuple->CISOffset, flags)) == NULL) { 1158*0Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1159*0Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1160*0Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 1161*0Sstevel@tonic-gate tp = GET_FIRST_LTUPLE(sp->cis[fn].cis, flags); 1162*0Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 1163*0Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1164*0Sstevel@tonic-gate } /* GET_NEXT_TUPLE */ 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate /* 1167*0Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 1168*0Sstevel@tonic-gate */ 1169*0Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 1170*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1171*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1172*0Sstevel@tonic-gate } 1173*0Sstevel@tonic-gate } /* CS_GET_FIRST_FLAG */ 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* 1176*0Sstevel@tonic-gate * Check if we want to get the first of a particular type of tuple 1177*0Sstevel@tonic-gate * or just the first tuple in the chain. 1178*0Sstevel@tonic-gate * If there are no more tuples of the type we're searching for in 1179*0Sstevel@tonic-gate * the chain that we're looking at, then if we're looking at 1180*0Sstevel@tonic-gate * the global portion of a multi-function CIS, switch to the 1181*0Sstevel@tonic-gate * function-specific list and start looking there. 1182*0Sstevel@tonic-gate */ 1183*0Sstevel@tonic-gate if (tuple->DesiredTuple != RETURN_FIRST_TUPLE) { 1184*0Sstevel@tonic-gate cistpl_t *tp; 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate if ((tp = FIND_LTUPLE_FWD(tuple->CISOffset, 1187*0Sstevel@tonic-gate tuple->DesiredTuple, flags)) == NULL) { 1188*0Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1189*0Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1190*0Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 1191*0Sstevel@tonic-gate tp = FIND_FIRST_LTUPLE(sp->cis[fn].cis, 1192*0Sstevel@tonic-gate tuple->DesiredTuple, flags); 1193*0Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 1194*0Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1195*0Sstevel@tonic-gate } /* FIND_LTUPLE_FWD */ 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate /* 1198*0Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 1199*0Sstevel@tonic-gate */ 1200*0Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 1201*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1202*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1203*0Sstevel@tonic-gate } 1204*0Sstevel@tonic-gate } /* !RETURN_FIRST_TUPLE */ 1205*0Sstevel@tonic-gate 1206*0Sstevel@tonic-gate /* 1207*0Sstevel@tonic-gate * We've got a tuple, now fill out the rest of the tuple_t 1208*0Sstevel@tonic-gate * structure. Callers can use the flags member to 1209*0Sstevel@tonic-gate * determine whether or not the tuple data was copied 1210*0Sstevel@tonic-gate * to the linked list or if it's still on the card. 1211*0Sstevel@tonic-gate */ 1212*0Sstevel@tonic-gate tuple->Flags = tuple->CISOffset->flags; 1213*0Sstevel@tonic-gate tuple->TupleCode = tuple->CISOffset->type; 1214*0Sstevel@tonic-gate tuple->TupleLink = tuple->CISOffset->len; 1215*0Sstevel@tonic-gate tuple->TupleDataLen = tuple->CISOffset->len; 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1218*0Sstevel@tonic-gate 1219*0Sstevel@tonic-gate return (CS_SUCCESS); 1220*0Sstevel@tonic-gate } 1221*0Sstevel@tonic-gate 1222*0Sstevel@tonic-gate /* 1223*0Sstevel@tonic-gate * cs_get_tuple_data - get the data portion of a tuple; this is to 1224*0Sstevel@tonic-gate * support the GetTupleData function call. 1225*0Sstevel@tonic-gate * 1226*0Sstevel@tonic-gate * Note that if the data body of a tuple was not read from the CIS, 1227*0Sstevel@tonic-gate * then this function will return CS_NO_MORE_ITEMS. 1228*0Sstevel@tonic-gate * 1229*0Sstevel@tonic-gate * For flags that are set in the tuple_t->flags member, see the 1230*0Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 1231*0Sstevel@tonic-gate * These flags are copied into the tuple_t->flags member by the 1232*0Sstevel@tonic-gate * cs_get_firstnext_tuple function call. 1233*0Sstevel@tonic-gate * 1234*0Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 1235*0Sstevel@tonic-gate */ 1236*0Sstevel@tonic-gate static int 1237*0Sstevel@tonic-gate cs_get_tuple_data(client_handle_t client_handle, tuple_t *tuple) 1238*0Sstevel@tonic-gate { 1239*0Sstevel@tonic-gate cs_socket_t *sp; 1240*0Sstevel@tonic-gate client_t *client; 1241*0Sstevel@tonic-gate int ret, nbytes; 1242*0Sstevel@tonic-gate uint32_t fn, flags; 1243*0Sstevel@tonic-gate cisdata_t *tsd, *tdd; 1244*0Sstevel@tonic-gate uint32_t newoffset; 1245*0Sstevel@tonic-gate acc_handle_t cis_handle; 1246*0Sstevel@tonic-gate 1247*0Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1248*0Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1249*0Sstevel@tonic-gate return (ret); 1250*0Sstevel@tonic-gate 1251*0Sstevel@tonic-gate /* 1252*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1253*0Sstevel@tonic-gate * for this client, then return an error. 1254*0Sstevel@tonic-gate */ 1255*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1256*0Sstevel@tonic-gate return (CS_NO_CARD); 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1259*0Sstevel@tonic-gate 1260*0Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 1261*0Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate /* 1264*0Sstevel@tonic-gate * Check to be sure that we have a non-NULL pointer to 1265*0Sstevel@tonic-gate * a CIS list. 1266*0Sstevel@tonic-gate */ 1267*0Sstevel@tonic-gate if (!(tuple->CISOffset)) { 1268*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1269*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1270*0Sstevel@tonic-gate } 1271*0Sstevel@tonic-gate 1272*0Sstevel@tonic-gate /* 1273*0Sstevel@tonic-gate * Since the tuple data buffer that the caller calls us with 1274*0Sstevel@tonic-gate * is preallocated in the tuple_t structure, we ignore any 1275*0Sstevel@tonic-gate * TupleDataMax value that the caller has setup and use the 1276*0Sstevel@tonic-gate * actual size of the tuple data buffer in the structure. 1277*0Sstevel@tonic-gate */ 1278*0Sstevel@tonic-gate tuple->TupleDataMax = sizeof (tuple->TupleData); 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate /* 1281*0Sstevel@tonic-gate * Make sure the requested offset is not past the end of the 1282*0Sstevel@tonic-gate * tuple data body nor past the end of the user-supplied 1283*0Sstevel@tonic-gate * buffer. 1284*0Sstevel@tonic-gate */ 1285*0Sstevel@tonic-gate if ((int)tuple->TupleOffset >= min((int)tuple->TupleLink, 1286*0Sstevel@tonic-gate (int)tuple->TupleDataMax)) { 1287*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1288*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1289*0Sstevel@tonic-gate } 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gate tuple->TupleDataLen = tuple->TupleLink; 1292*0Sstevel@tonic-gate 1293*0Sstevel@tonic-gate if ((nbytes = min((int)tuple->TupleDataMax - 1294*0Sstevel@tonic-gate (int)tuple->TupleOffset, 1295*0Sstevel@tonic-gate (int)tuple->TupleDataLen - 1296*0Sstevel@tonic-gate (int)tuple->TupleOffset)) < 1) { 1297*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1298*0Sstevel@tonic-gate return (CS_BAD_ARGS); 1299*0Sstevel@tonic-gate } 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate /* 1302*0Sstevel@tonic-gate * The tuple data destination is always the tuple_t->TupleData 1303*0Sstevel@tonic-gate * buffer in the tuple_t structure no matter where we read the 1304*0Sstevel@tonic-gate * tuple data from. 1305*0Sstevel@tonic-gate */ 1306*0Sstevel@tonic-gate tdd = tuple->TupleData; 1307*0Sstevel@tonic-gate bzero((caddr_t)tdd, sizeof (tuple->TupleData)); 1308*0Sstevel@tonic-gate 1309*0Sstevel@tonic-gate /* 1310*0Sstevel@tonic-gate * Do we have a copy of the tuple data? If not, we have to 1311*0Sstevel@tonic-gate * get a pointer to the CIS and read the tuple data from the 1312*0Sstevel@tonic-gate * card itself. 1313*0Sstevel@tonic-gate */ 1314*0Sstevel@tonic-gate switch (tuple->CISOffset->flags & CISTPLF_SPACE_MASK) { 1315*0Sstevel@tonic-gate case CISTPLF_LM_SPACE: 1316*0Sstevel@tonic-gate tsd = (tuple->CISOffset->data + 1317*0Sstevel@tonic-gate (unsigned)tuple->TupleOffset); 1318*0Sstevel@tonic-gate while (nbytes--) 1319*0Sstevel@tonic-gate *tdd++ = *tsd++; 1320*0Sstevel@tonic-gate break; 1321*0Sstevel@tonic-gate case CISTPLF_AM_SPACE: 1322*0Sstevel@tonic-gate case CISTPLF_CM_SPACE: 1323*0Sstevel@tonic-gate newoffset = tuple->CISOffset->offset; 1324*0Sstevel@tonic-gate 1325*0Sstevel@tonic-gate /* 1326*0Sstevel@tonic-gate * Setup the proper space flags as well as setup the 1327*0Sstevel@tonic-gate * address offset to point to the start of the tuple 1328*0Sstevel@tonic-gate * data area; we need to do the latter since the 1329*0Sstevel@tonic-gate * cis_store_cis_addr function in cis.c sets up the 1330*0Sstevel@tonic-gate * tuple->CISOffset->offset offset to point to the 1331*0Sstevel@tonic-gate * start of the tuple. 1332*0Sstevel@tonic-gate */ 1333*0Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) { 1334*0Sstevel@tonic-gate flags = CISTPLF_AM_SPACE; 1335*0Sstevel@tonic-gate newoffset += ((tuple->TupleOffset * 2) + 4); 1336*0Sstevel@tonic-gate } else { 1337*0Sstevel@tonic-gate flags = CISTPLF_CM_SPACE; 1338*0Sstevel@tonic-gate newoffset += (tuple->TupleOffset + 2); 1339*0Sstevel@tonic-gate } 1340*0Sstevel@tonic-gate 1341*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 1342*0Sstevel@tonic-gate flags) != CS_SUCCESS) { 1343*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1344*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_tuple_data: socket %d " 1345*0Sstevel@tonic-gate "can't init CIS window\n", 1346*0Sstevel@tonic-gate sp->socket_num); 1347*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 1348*0Sstevel@tonic-gate } /* cs_init_cis_window */ 1349*0Sstevel@tonic-gate while (nbytes--) { 1350*0Sstevel@tonic-gate *tdd++ = csx_Get8(cis_handle, newoffset++); 1351*0Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) 1352*0Sstevel@tonic-gate newoffset++; 1353*0Sstevel@tonic-gate } /* while */ 1354*0Sstevel@tonic-gate break; 1355*0Sstevel@tonic-gate default: 1356*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1357*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 1358*0Sstevel@tonic-gate } /* switch */ 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate ret = CS_SUCCESS; 1361*0Sstevel@tonic-gate } else { 1362*0Sstevel@tonic-gate ret = CS_NO_CIS; 1363*0Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate return (ret); 1368*0Sstevel@tonic-gate } 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate /* 1371*0Sstevel@tonic-gate * cs_validate_cis - validates the CIS on a card in the given socket; this 1372*0Sstevel@tonic-gate * is to support the ValidateCIS function call. 1373*0Sstevel@tonic-gate * 1374*0Sstevel@tonic-gate * Notes for regular PC card driver callers: 1375*0Sstevel@tonic-gate * 1376*0Sstevel@tonic-gate * Regular PC card drivers calling ValidateCIS will get the meaning of 1377*0Sstevel@tonic-gate * the structure members as specified in the standard. 1378*0Sstevel@tonic-gate * 1379*0Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 1380*0Sstevel@tonic-gate * 1381*0Sstevel@tonic-gate * with: Function Number = CS_GLOBAL_CIS 1382*0Sstevel@tonic-gate * 1383*0Sstevel@tonic-gate * For a single-function card, CS_NO_CIS will be returned and the 1384*0Sstevel@tonic-gate * cisinfo_t->Chains and cisinfo_t->Tuples members will be set to 0. 1385*0Sstevel@tonic-gate * 1386*0Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 1387*0Sstevel@tonic-gate * the number of CIS chains in the global portion of the CIS, and 1388*0Sstevel@tonic-gate * cisinfo_t->Tuples will contain a count of the number of tuples in 1389*0Sstevel@tonic-gate * the global portion of the CIS. 1390*0Sstevel@tonic-gate * 1391*0Sstevel@tonic-gate * with: 0 <= Function Number < CIS_MAX_FUNCTIONS 1392*0Sstevel@tonic-gate * 1393*0Sstevel@tonic-gate * For a single-function card, if the function number is equal to 0 and 1394*0Sstevel@tonic-gate * has a CIS, cisinfo_t->Chains will contain a count of the number of 1395*0Sstevel@tonic-gate * CIS chains in the CIS, and cisinfo_t->Tuples will contain a count of 1396*0Sstevel@tonic-gate * the number of tuples in the CIS. If the card does not have a CIS, or 1397*0Sstevel@tonic-gate * if the function number is not equal to 0, CS_NO_CIS will be returned 1398*0Sstevel@tonic-gate * and the cisinfo_t->Chains and cisinfo_t->Tuples members will be set 1399*0Sstevel@tonic-gate * to 0. 1400*0Sstevel@tonic-gate * 1401*0Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 1402*0Sstevel@tonic-gate * the number of CIS chains in the global and function-specific 1403*0Sstevel@tonic-gate * portions of the CIS, and cisinfo_t->Tuples will contain a count of 1404*0Sstevel@tonic-gate * the number of tuples in the global and function-specific portions of 1405*0Sstevel@tonic-gate * the CIS. If the function does not exist or has no CIS, CS_NO_CIS 1406*0Sstevel@tonic-gate * will be returned and the cisinfo_t->Chains and cisinfo_t->Tuples 1407*0Sstevel@tonic-gate * members will be set to 0. 1408*0Sstevel@tonic-gate * 1409*0Sstevel@tonic-gate * General notes: 1410*0Sstevel@tonic-gate * 1411*0Sstevel@tonic-gate * If the card does not have a CIS, or if the function does not exist 1412*0Sstevel@tonic-gate * or has no CIS, CS_NO_CIS will be returned and the cisinfo_t->Chains 1413*0Sstevel@tonic-gate * and cisinfo_t->Tuples members will be set to 0. 1414*0Sstevel@tonic-gate * 1415*0Sstevel@tonic-gate * Most of the work of validating the CIS has already been done by the 1416*0Sstevel@tonic-gate * CIS parser module, so we don't have to do much here except for 1417*0Sstevel@tonic-gate * looking at the various flags and tuple/chain counts that were already 1418*0Sstevel@tonic-gate * setup by the CIS parser. 1419*0Sstevel@tonic-gate * 1420*0Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 1421*0Sstevel@tonic-gate */ 1422*0Sstevel@tonic-gate static int 1423*0Sstevel@tonic-gate cs_validate_cis(client_handle_t client_handle, cisinfo_t *cisinfo) 1424*0Sstevel@tonic-gate { 1425*0Sstevel@tonic-gate cs_socket_t *sp; 1426*0Sstevel@tonic-gate client_t *client; 1427*0Sstevel@tonic-gate uint32_t fn; 1428*0Sstevel@tonic-gate int ret; 1429*0Sstevel@tonic-gate 1430*0Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &cisinfo->Socket, &fn, 1431*0Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1432*0Sstevel@tonic-gate return (ret); 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate /* 1435*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1436*0Sstevel@tonic-gate * for this client, then return an error. 1437*0Sstevel@tonic-gate */ 1438*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1439*0Sstevel@tonic-gate return (CS_NO_CARD); 1440*0Sstevel@tonic-gate 1441*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1442*0Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 1443*0Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 1444*0Sstevel@tonic-gate cisinfo->Chains = sp->cis[fn].nchains; 1445*0Sstevel@tonic-gate cisinfo->Tuples = sp->cis[fn].ntuples; 1446*0Sstevel@tonic-gate 1447*0Sstevel@tonic-gate if ((fn != CS_GLOBAL_CIS) && 1448*0Sstevel@tonic-gate (sp->cis[CS_GLOBAL_CIS].flags & CW_VALID_CIS)) { 1449*0Sstevel@tonic-gate cisinfo->Chains += sp->cis[CS_GLOBAL_CIS].nchains; 1450*0Sstevel@tonic-gate cisinfo->Tuples += sp->cis[CS_GLOBAL_CIS].ntuples; 1451*0Sstevel@tonic-gate } /* !CS_GLOBAL_CIS */ 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate ret = CS_SUCCESS; 1454*0Sstevel@tonic-gate } else { 1455*0Sstevel@tonic-gate cisinfo->Chains = 0; 1456*0Sstevel@tonic-gate cisinfo->Tuples = 0; 1457*0Sstevel@tonic-gate ret = CS_NO_CIS; 1458*0Sstevel@tonic-gate } 1459*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate return (ret); 1462*0Sstevel@tonic-gate } 1463*0Sstevel@tonic-gate 1464*0Sstevel@tonic-gate /* 1465*0Sstevel@tonic-gate * cs_init_cis_window - initializes the CIS window for the passed socket 1466*0Sstevel@tonic-gate * 1467*0Sstevel@tonic-gate * calling: *sp - pointer to the per-socket structure 1468*0Sstevel@tonic-gate * *offset - offset from start of AM or CM space 1469*0Sstevel@tonic-gate * *hp - pointer to acc_handle_t to store modified 1470*0Sstevel@tonic-gate * window access handle in 1471*0Sstevel@tonic-gate * flags - one of: 1472*0Sstevel@tonic-gate * CISTPLF_AM_SPACE - set window to AM space 1473*0Sstevel@tonic-gate * CISTPLF_CM_SPACE - set window to CM space 1474*0Sstevel@tonic-gate * 1475*0Sstevel@tonic-gate * returns: CS_SUCCESS if CIS window was set up 1476*0Sstevel@tonic-gate * *offset - contains adjusted offset to use to access 1477*0Sstevel@tonic-gate * requested space 1478*0Sstevel@tonic-gate * CS_BAD_WINDOW if CIS window could not be setup 1479*0Sstevel@tonic-gate * CS_GENERAL_FAILURE if socket has a CIS window number 1480*0Sstevel@tonic-gate * but the window flags are wrong 1481*0Sstevel@tonic-gate * 1482*0Sstevel@tonic-gate * Note: This function will check to be sure that there is a valid 1483*0Sstevel@tonic-gate * CIS window allocated to this socket. 1484*0Sstevel@tonic-gate * If there is an error in setting up the window hardware, the 1485*0Sstevel@tonic-gate * CIS window information for this socket is cleared. 1486*0Sstevel@tonic-gate * This function is also used by routines that need to get 1487*0Sstevel@tonic-gate * a pointer to the base of AM space to access the card's 1488*0Sstevel@tonic-gate * configuration registers. 1489*0Sstevel@tonic-gate * The passed offset is the un-window-size-aligned offset. 1490*0Sstevel@tonic-gate */ 1491*0Sstevel@tonic-gate int 1492*0Sstevel@tonic-gate cs_init_cis_window(cs_socket_t *sp, uint32_t *offset, 1493*0Sstevel@tonic-gate acc_handle_t *hp, uint32_t flags) 1494*0Sstevel@tonic-gate { 1495*0Sstevel@tonic-gate set_window_t sw; 1496*0Sstevel@tonic-gate get_window_t gw; 1497*0Sstevel@tonic-gate inquire_window_t iw; 1498*0Sstevel@tonic-gate set_page_t set_page; 1499*0Sstevel@tonic-gate cs_window_t *cw; 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate /* 1502*0Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 1503*0Sstevel@tonic-gate */ 1504*0Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 1505*0Sstevel@tonic-gate cmn_err(CE_CONT, 1506*0Sstevel@tonic-gate "cs_init_cis_window: socket %d has no CIS window\n", 1507*0Sstevel@tonic-gate sp->socket_num); 1508*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1509*0Sstevel@tonic-gate } 1510*0Sstevel@tonic-gate 1511*0Sstevel@tonic-gate /* 1512*0Sstevel@tonic-gate * Check to be sure that this window is allocated for CIS use 1513*0Sstevel@tonic-gate */ 1514*0Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) 1515*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1516*0Sstevel@tonic-gate 1517*0Sstevel@tonic-gate if (!(cw->state & CW_CIS)) { 1518*0Sstevel@tonic-gate cmn_err(CE_CONT, 1519*0Sstevel@tonic-gate "cs_init_cis_window: socket %d invalid CIS window state 0x%x\n", 1520*0Sstevel@tonic-gate sp->socket_num, cw->state); 1521*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1522*0Sstevel@tonic-gate } 1523*0Sstevel@tonic-gate 1524*0Sstevel@tonic-gate /* 1525*0Sstevel@tonic-gate * Get the characteristics of this window - we use this to 1526*0Sstevel@tonic-gate * determine whether we need to re-map the window or 1527*0Sstevel@tonic-gate * just move the window offset on the card. 1528*0Sstevel@tonic-gate */ 1529*0Sstevel@tonic-gate iw.window = sp->cis_win_num; 1530*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gate /* 1533*0Sstevel@tonic-gate * We've got a window, now set up the hardware. If we've got 1534*0Sstevel@tonic-gate * a variable sized window, then all we need to do is to 1535*0Sstevel@tonic-gate * get a valid mapping to the base of the window using 1536*0Sstevel@tonic-gate * the current window size; if we've got a fixed-size 1537*0Sstevel@tonic-gate * window, then we need to get a mapping to the window 1538*0Sstevel@tonic-gate * starting at offset zero of the window. 1539*0Sstevel@tonic-gate */ 1540*0Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_SIZE) { 1541*0Sstevel@tonic-gate sw.WindowSize = sp->cis_win_size; 1542*0Sstevel@tonic-gate set_page.offset = ((*offset / sp->cis_win_size) * 1543*0Sstevel@tonic-gate sp->cis_win_size); 1544*0Sstevel@tonic-gate } else { 1545*0Sstevel@tonic-gate set_page.offset = ((*offset / iw.mem_win_char.MinSize) * 1546*0Sstevel@tonic-gate iw.mem_win_char.MinSize); 1547*0Sstevel@tonic-gate sw.WindowSize = (((*offset & ~(PAGESIZE - 1)) & 1548*0Sstevel@tonic-gate (set_page.offset - 1)) + PAGESIZE); 1549*0Sstevel@tonic-gate } 1550*0Sstevel@tonic-gate 1551*0Sstevel@tonic-gate /* 1552*0Sstevel@tonic-gate * Return a normalized base offset; this takes care of the case 1553*0Sstevel@tonic-gate * where the required offset is greater than the window size. 1554*0Sstevel@tonic-gate * BugID 1236404 1555*0Sstevel@tonic-gate * code was: 1556*0Sstevel@tonic-gate * *offset = *offset & (set_page.offset - 1); 1557*0Sstevel@tonic-gate */ 1558*0Sstevel@tonic-gate *offset = *offset - set_page.offset; 1559*0Sstevel@tonic-gate 1560*0Sstevel@tonic-gate #ifdef CS_DEBUG 1561*0Sstevel@tonic-gate if (cs_debug > 1) 1562*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_init_cis_window: WindowSize 0x%x " 1563*0Sstevel@tonic-gate "offset 0x%x\n", 1564*0Sstevel@tonic-gate (int)sw.WindowSize, 1565*0Sstevel@tonic-gate (int)set_page.offset); 1566*0Sstevel@tonic-gate if (cs_debug > 1) 1567*0Sstevel@tonic-gate cmn_err(CE_CONT, "\t*offset = 0x%x space = %s\n", 1568*0Sstevel@tonic-gate (int)*offset, 1569*0Sstevel@tonic-gate (flags & CISTPLF_AM_SPACE)? 1570*0Sstevel@tonic-gate "CISTPLF_AM_SPACE":"CISTPLF_CM_SPACE"); 1571*0Sstevel@tonic-gate #endif 1572*0Sstevel@tonic-gate 1573*0Sstevel@tonic-gate sw.window = sp->cis_win_num; 1574*0Sstevel@tonic-gate sw.socket = sp->socket_num; 1575*0Sstevel@tonic-gate sw.state = (WS_ENABLED | WS_EXACT_MAPIN); 1576*0Sstevel@tonic-gate sw.attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1577*0Sstevel@tonic-gate sw.attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 1578*0Sstevel@tonic-gate sw.attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1579*0Sstevel@tonic-gate 1580*0Sstevel@tonic-gate /* 1581*0Sstevel@tonic-gate * The PCMCIA SS spec specifies this be expressed in 1582*0Sstevel@tonic-gate * a device speed format per 5.2.7.1.3 but 1583*0Sstevel@tonic-gate * our implementation of SS_SetWindow uses 1584*0Sstevel@tonic-gate * actual nanoseconds. 1585*0Sstevel@tonic-gate */ 1586*0Sstevel@tonic-gate sw.speed = CIS_DEFAULT_SPEED; 1587*0Sstevel@tonic-gate sw.base = 0; 1588*0Sstevel@tonic-gate /* 1589*0Sstevel@tonic-gate * Set up the window - if this fails, then just set the 1590*0Sstevel@tonic-gate * CIS window number back to it's initialized value so 1591*0Sstevel@tonic-gate * that we'll fail when we break out of the loop. 1592*0Sstevel@tonic-gate */ 1593*0Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) { 1594*0Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1595*0Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 1596*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1597*0Sstevel@tonic-gate } else { 1598*0Sstevel@tonic-gate set_page.window = sp->cis_win_num; 1599*0Sstevel@tonic-gate set_page.page = 0; 1600*0Sstevel@tonic-gate set_page.state = PS_ENABLED; 1601*0Sstevel@tonic-gate if (flags & CISTPLF_AM_SPACE) 1602*0Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 1603*0Sstevel@tonic-gate 1604*0Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 1605*0Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1606*0Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 1607*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1608*0Sstevel@tonic-gate } /* if (SS_SetPage) */ 1609*0Sstevel@tonic-gate } /* if (SS_SetWindow) */ 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate /* 1612*0Sstevel@tonic-gate * Get the window information for the CIS window for this socket. 1613*0Sstevel@tonic-gate */ 1614*0Sstevel@tonic-gate gw.window = sp->cis_win_num; 1615*0Sstevel@tonic-gate gw.socket = sp->socket_num; /* XXX - SS_GetWindow should set this */ 1616*0Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 1617*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate *hp = (acc_handle_t)gw.handle; 1620*0Sstevel@tonic-gate 1621*0Sstevel@tonic-gate return (CS_SUCCESS); 1622*0Sstevel@tonic-gate } 1623*0Sstevel@tonic-gate 1624*0Sstevel@tonic-gate /* 1625*0Sstevel@tonic-gate * ==== client registration/deregistration section ==== 1626*0Sstevel@tonic-gate */ 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate /* 1629*0Sstevel@tonic-gate * cs_register_client - This supports the RegisterClient call. 1630*0Sstevel@tonic-gate * 1631*0Sstevel@tonic-gate * Upon successful registration, the client_handle_t * handle argument will 1632*0Sstevel@tonic-gate * contain the new client handle and we return CS_SUCCESS. 1633*0Sstevel@tonic-gate */ 1634*0Sstevel@tonic-gate static int 1635*0Sstevel@tonic-gate cs_register_client(client_handle_t *ch, client_reg_t *cr) 1636*0Sstevel@tonic-gate { 1637*0Sstevel@tonic-gate uint32_t sn; 1638*0Sstevel@tonic-gate int super_client = 0; 1639*0Sstevel@tonic-gate sclient_reg_t *scr = cr->priv; 1640*0Sstevel@tonic-gate struct sclient_list_t *scli; 1641*0Sstevel@tonic-gate 1642*0Sstevel@tonic-gate /* 1643*0Sstevel@tonic-gate * See if we're not supposed to register any new clients. 1644*0Sstevel@tonic-gate */ 1645*0Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_NO_CLIENTS) 1646*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 1647*0Sstevel@tonic-gate 1648*0Sstevel@tonic-gate /* 1649*0Sstevel@tonic-gate * Do a version check - if the client expects a later version of 1650*0Sstevel@tonic-gate * Card Services than what we are, return CS_BAD_VERSION. 1651*0Sstevel@tonic-gate * XXX - How do we specify just a PARTICULAR version of CS?? 1652*0Sstevel@tonic-gate */ 1653*0Sstevel@tonic-gate if (CS_VERSION < cr->Version) 1654*0Sstevel@tonic-gate return (CS_BAD_VERSION); 1655*0Sstevel@tonic-gate 1656*0Sstevel@tonic-gate /* 1657*0Sstevel@tonic-gate * Check to be sure that the client has given us a valid set of 1658*0Sstevel@tonic-gate * client type flags. We also use this opportunity to see 1659*0Sstevel@tonic-gate * if the registering client is Socket Services or is a 1660*0Sstevel@tonic-gate * "super-client" or a CSI client. 1661*0Sstevel@tonic-gate * 1662*0Sstevel@tonic-gate * Note that SS can not set any flag in the Attributes field other 1663*0Sstevel@tonic-gate * than the INFO_SOCKET_SERVICES flag. 1664*0Sstevel@tonic-gate * 1665*0Sstevel@tonic-gate * Valid combinations of cr->Attributes and cr->EventMask flags: 1666*0Sstevel@tonic-gate * 1667*0Sstevel@tonic-gate * for Socket Services: 1668*0Sstevel@tonic-gate * cr->Attributes: 1669*0Sstevel@tonic-gate * set: 1670*0Sstevel@tonic-gate * INFO_SOCKET_SERVICES 1671*0Sstevel@tonic-gate * clear: 1672*0Sstevel@tonic-gate * {all other flags} 1673*0Sstevel@tonic-gate * cr->EventMask: 1674*0Sstevel@tonic-gate * don't care: 1675*0Sstevel@tonic-gate * {all flags} 1676*0Sstevel@tonic-gate * 1677*0Sstevel@tonic-gate * for regular clients: 1678*0Sstevel@tonic-gate * cr->Attributes: 1679*0Sstevel@tonic-gate * only one of: 1680*0Sstevel@tonic-gate * INFO_IO_CLIENT 1681*0Sstevel@tonic-gate * INFO_MTD_CLIENT 1682*0Sstevel@tonic-gate * INFO_MEM_CLIENT 1683*0Sstevel@tonic-gate * don't care: 1684*0Sstevel@tonic-gate * INFO_CARD_SHARE 1685*0Sstevel@tonic-gate * INFO_CARD_EXCL 1686*0Sstevel@tonic-gate * cr->EventMask: 1687*0Sstevel@tonic-gate * clear: 1688*0Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 1689*0Sstevel@tonic-gate * don't care: 1690*0Sstevel@tonic-gate * {all other flags} 1691*0Sstevel@tonic-gate * 1692*0Sstevel@tonic-gate * for CSI clients: 1693*0Sstevel@tonic-gate * cr->Attributes: 1694*0Sstevel@tonic-gate * set: 1695*0Sstevel@tonic-gate * INFO_IO_CLIENT 1696*0Sstevel@tonic-gate * INFO_CSI_CLIENT 1697*0Sstevel@tonic-gate * clear: 1698*0Sstevel@tonic-gate * INFO_MTD_CLIENT 1699*0Sstevel@tonic-gate * INFO_MEM_CLIENT 1700*0Sstevel@tonic-gate * don't care: 1701*0Sstevel@tonic-gate * INFO_CARD_SHARE 1702*0Sstevel@tonic-gate * INFO_CARD_EXCL 1703*0Sstevel@tonic-gate * cr->EventMask: 1704*0Sstevel@tonic-gate * don't care: 1705*0Sstevel@tonic-gate * {all flags} 1706*0Sstevel@tonic-gate * 1707*0Sstevel@tonic-gate * for "super-clients": 1708*0Sstevel@tonic-gate * cr->Attributes: 1709*0Sstevel@tonic-gate * set: 1710*0Sstevel@tonic-gate * INFO_IO_CLIENT 1711*0Sstevel@tonic-gate * INFO_MTD_CLIENT 1712*0Sstevel@tonic-gate * INFO_SOCKET_SERVICES 1713*0Sstevel@tonic-gate * INFO_CARD_SHARE 1714*0Sstevel@tonic-gate * clear: 1715*0Sstevel@tonic-gate * INFO_MEM_CLIENT 1716*0Sstevel@tonic-gate * INFO_CARD_EXCL 1717*0Sstevel@tonic-gate * cr->EventMask: 1718*0Sstevel@tonic-gate * don't care: 1719*0Sstevel@tonic-gate * {all flags} 1720*0Sstevel@tonic-gate */ 1721*0Sstevel@tonic-gate switch (cr->Attributes & INFO_CLIENT_TYPE_MASK) { 1722*0Sstevel@tonic-gate /* 1723*0Sstevel@tonic-gate * Check first to see if this is Socket Services registering; if 1724*0Sstevel@tonic-gate * so, we don't do anything but return the client handle that is 1725*0Sstevel@tonic-gate * in the global SS client. 1726*0Sstevel@tonic-gate */ 1727*0Sstevel@tonic-gate case INFO_SOCKET_SERVICES: 1728*0Sstevel@tonic-gate *ch = cs_socket_services_client.client_handle; 1729*0Sstevel@tonic-gate return (CS_SUCCESS); 1730*0Sstevel@tonic-gate /* NOTREACHED */ 1731*0Sstevel@tonic-gate /* CSI clients */ 1732*0Sstevel@tonic-gate case (INFO_CSI_CLIENT | INFO_IO_CLIENT): 1733*0Sstevel@tonic-gate break; 1734*0Sstevel@tonic-gate /* regular clients */ 1735*0Sstevel@tonic-gate case INFO_IO_CLIENT: 1736*0Sstevel@tonic-gate case INFO_MTD_CLIENT: 1737*0Sstevel@tonic-gate case INFO_MEM_CLIENT: 1738*0Sstevel@tonic-gate if (cr->EventMask & CS_EVENT_ALL_CLIENTS) 1739*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1740*0Sstevel@tonic-gate break; 1741*0Sstevel@tonic-gate /* "super-client" clients */ 1742*0Sstevel@tonic-gate case (INFO_IO_CLIENT | INFO_MTD_CLIENT | INFO_SOCKET_SERVICES): 1743*0Sstevel@tonic-gate if ((!(cr->Attributes & INFO_CARD_SHARE)) || 1744*0Sstevel@tonic-gate (cr->Attributes & INFO_CARD_EXCL)) 1745*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1746*0Sstevel@tonic-gate /* 1747*0Sstevel@tonic-gate * We only allow one "super-client" per system. 1748*0Sstevel@tonic-gate */ 1749*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 1750*0Sstevel@tonic-gate if (cs_globals.flags & GLOBAL_SUPER_CLIENT_REGISTERED) { 1751*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 1752*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1753*0Sstevel@tonic-gate } 1754*0Sstevel@tonic-gate cs_globals.flags |= GLOBAL_SUPER_CLIENT_REGISTERED; 1755*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 1756*0Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 1757*0Sstevel@tonic-gate break; 1758*0Sstevel@tonic-gate default: 1759*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1760*0Sstevel@tonic-gate } /* switch (cr->Attributes) */ 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate /* 1763*0Sstevel@tonic-gate * Now, actually create the client node on the socket; this will 1764*0Sstevel@tonic-gate * also return the new client handle if there were no errors 1765*0Sstevel@tonic-gate * creating the client node. 1766*0Sstevel@tonic-gate * The DIP2SOCKET_NUM macro will return the socket and function 1767*0Sstevel@tonic-gate * number using the encoding specified in the cs_priv.h file. 1768*0Sstevel@tonic-gate */ 1769*0Sstevel@tonic-gate if (super_client != CLIENT_SUPER_CLIENT) { 1770*0Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 1771*0Sstevel@tonic-gate sn = (uint32_t)(uintptr_t)cr->priv; 1772*0Sstevel@tonic-gate else 1773*0Sstevel@tonic-gate sn = DIP2SOCKET_NUM(cr->dip); 1774*0Sstevel@tonic-gate return (cs_add_client_to_socket(sn, ch, cr, super_client)); 1775*0Sstevel@tonic-gate } /* CLIENT_SUPER_CLIENT */ 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate /* 1778*0Sstevel@tonic-gate * This registering client is a "super-client", so we create one 1779*0Sstevel@tonic-gate * client node for each socket in the system. We use the 1780*0Sstevel@tonic-gate * client_reg_t.priv structure member to point to a struct 1781*0Sstevel@tonic-gate * that the "super-client" client knows about. The client 1782*0Sstevel@tonic-gate * handle pointer is not used in this case. 1783*0Sstevel@tonic-gate * We return CS_SUCCESS if at least one client node could be 1784*0Sstevel@tonic-gate * created. The client must check the error codes in the 1785*0Sstevel@tonic-gate * error code array to determine which clients could not 1786*0Sstevel@tonic-gate * be created on which sockets. 1787*0Sstevel@tonic-gate * We return CS_BAD_HANDLE if no client nodes could be created. 1788*0Sstevel@tonic-gate */ 1789*0Sstevel@tonic-gate scr->num_clients = 0; 1790*0Sstevel@tonic-gate scr->max_socket_num = cs_globals.max_socket_num; 1791*0Sstevel@tonic-gate scr->num_sockets = cs_globals.num_sockets; 1792*0Sstevel@tonic-gate scr->num_windows = cs_globals.num_windows; 1793*0Sstevel@tonic-gate 1794*0Sstevel@tonic-gate *(scr->sclient_list) = cs_globals.sclient_list; 1795*0Sstevel@tonic-gate 1796*0Sstevel@tonic-gate for (sn = 0; sn < scr->num_sockets; sn++) { 1797*0Sstevel@tonic-gate scli = scr->sclient_list[sn]; 1798*0Sstevel@tonic-gate if ((scli->error = cs_add_client_to_socket(sn, &scli->client_handle, 1799*0Sstevel@tonic-gate cr, super_client)) == CS_SUCCESS) { 1800*0Sstevel@tonic-gate scr->num_clients++; 1801*0Sstevel@tonic-gate } 1802*0Sstevel@tonic-gate } 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate /* 1805*0Sstevel@tonic-gate * If we couldn't create any client nodes at all, then 1806*0Sstevel@tonic-gate * return an error. 1807*0Sstevel@tonic-gate */ 1808*0Sstevel@tonic-gate if (!scr->num_clients) { 1809*0Sstevel@tonic-gate /* 1810*0Sstevel@tonic-gate * XXX - The global superclient lock now gets 1811*0Sstevel@tonic-gate * cleared in cs_deregister_client 1812*0Sstevel@tonic-gate */ 1813*0Sstevel@tonic-gate /* cs_clear_superclient_lock(super_client); */ 1814*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 1815*0Sstevel@tonic-gate } 1816*0Sstevel@tonic-gate 1817*0Sstevel@tonic-gate return (CS_SUCCESS); 1818*0Sstevel@tonic-gate } 1819*0Sstevel@tonic-gate 1820*0Sstevel@tonic-gate /* 1821*0Sstevel@tonic-gate * cs_add_client_to_socket - this function creates the client node on the 1822*0Sstevel@tonic-gate * requested socket. 1823*0Sstevel@tonic-gate * 1824*0Sstevel@tonic-gate * Note that if we return an error, there is no state that can be cleaned 1825*0Sstevel@tonic-gate * up. The only way that we can return an error with allocated resources 1826*0Sstevel@tonic-gate * would be if one of the client handle functions had an internal error. 1827*0Sstevel@tonic-gate * Since we wouldn't get a valid client handle in this case anyway, there 1828*0Sstevel@tonic-gate * would be no way to find out what was allocated and what wasn't. 1829*0Sstevel@tonic-gate */ 1830*0Sstevel@tonic-gate static int 1831*0Sstevel@tonic-gate cs_add_client_to_socket(unsigned sn, client_handle_t *ch, 1832*0Sstevel@tonic-gate client_reg_t *cr, int super_client) 1833*0Sstevel@tonic-gate { 1834*0Sstevel@tonic-gate cs_socket_t *sp; 1835*0Sstevel@tonic-gate client_t *client, *cclp; 1836*0Sstevel@tonic-gate int error, cie = 1; 1837*0Sstevel@tonic-gate int client_lock_acquired; 1838*0Sstevel@tonic-gate 1839*0Sstevel@tonic-gate if (cr->event_handler == NULL) 1840*0Sstevel@tonic-gate return (CS_BAD_ARGS); 1841*0Sstevel@tonic-gate 1842*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 1843*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 1844*0Sstevel@tonic-gate 1845*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 1846*0Sstevel@tonic-gate 1847*0Sstevel@tonic-gate /* 1848*0Sstevel@tonic-gate * Run through all of the registered clients and compare the passed 1849*0Sstevel@tonic-gate * dip to the dip of each client to make sure that this client 1850*0Sstevel@tonic-gate * is not trying to register more than once. If they are, then 1851*0Sstevel@tonic-gate * display a message and return an error. 1852*0Sstevel@tonic-gate * XXX - we should really check all the sockets in case the client 1853*0Sstevel@tonic-gate * manipulates the instance number in the dip. 1854*0Sstevel@tonic-gate * XXX - if we check each socket, we ned to also check for the 1855*0Sstevel@tonic-gate * "super-client" since it will use the same dip for all 1856*0Sstevel@tonic-gate * of it's client nodes. 1857*0Sstevel@tonic-gate */ 1858*0Sstevel@tonic-gate mutex_enter(&sp->lock); 1859*0Sstevel@tonic-gate client = sp->client_list; 1860*0Sstevel@tonic-gate while (client) { 1861*0Sstevel@tonic-gate if (!(cr->Attributes & INFO_CSI_CLIENT) && 1862*0Sstevel@tonic-gate (client->dip == cr->dip)) { 1863*0Sstevel@tonic-gate mutex_exit(&sp->lock); 1864*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1865*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d " 1866*0Sstevel@tonic-gate "function 0x%x\n" 1867*0Sstevel@tonic-gate "\tclient already registered with " 1868*0Sstevel@tonic-gate "handle 0x%x\n", 1869*0Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 1870*0Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 1871*0Sstevel@tonic-gate (int)client->client_handle); 1872*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 1873*0Sstevel@tonic-gate } 1874*0Sstevel@tonic-gate client = client->next; 1875*0Sstevel@tonic-gate } /* while (client) */ 1876*0Sstevel@tonic-gate mutex_exit(&sp->lock); 1877*0Sstevel@tonic-gate 1878*0Sstevel@tonic-gate /* 1879*0Sstevel@tonic-gate * Create a unique client handle then make sure that we can find it. 1880*0Sstevel@tonic-gate * This has the side effect of getting us a pointer to the 1881*0Sstevel@tonic-gate * client structure as well. 1882*0Sstevel@tonic-gate * Create a client list entry - cs_create_client_handle will use this 1883*0Sstevel@tonic-gate * as the new client node. 1884*0Sstevel@tonic-gate * We do it here so that we can grab the sp->lock mutex for the 1885*0Sstevel@tonic-gate * duration of our manipulation of the client list. 1886*0Sstevel@tonic-gate * If this function fails, then it will not have added the newly 1887*0Sstevel@tonic-gate * allocated client node to the client list on this socket, 1888*0Sstevel@tonic-gate * so we have to free the node that we allocated. 1889*0Sstevel@tonic-gate */ 1890*0Sstevel@tonic-gate cclp = (client_t *)kmem_zalloc(sizeof (client_t), KM_SLEEP); 1891*0Sstevel@tonic-gate 1892*0Sstevel@tonic-gate mutex_enter(&sp->lock); 1893*0Sstevel@tonic-gate if (!(*ch = cs_create_client_handle(sn, cclp))) { 1894*0Sstevel@tonic-gate mutex_exit(&sp->lock); 1895*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1896*0Sstevel@tonic-gate kmem_free(cclp, sizeof (client_t)); 1897*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 1898*0Sstevel@tonic-gate } 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate /* 1901*0Sstevel@tonic-gate * Make sure that this is a valid client handle. We should never 1902*0Sstevel@tonic-gate * fail this since we just got a valid client handle. 1903*0Sstevel@tonic-gate * If this fails, then we have an internal error so don't bother 1904*0Sstevel@tonic-gate * trying to clean up the allocated client handle since the 1905*0Sstevel@tonic-gate * whole system is probably hosed anyway and will shortly 1906*0Sstevel@tonic-gate * esplode. 1907*0Sstevel@tonic-gate * It doesn't make sense to call cs_deregister_client at this point 1908*0Sstevel@tonic-gate * to clean up this broken client since the deregistration 1909*0Sstevel@tonic-gate * code will also call cs_find_client and most likely fail. 1910*0Sstevel@tonic-gate */ 1911*0Sstevel@tonic-gate if (!(client = cs_find_client(*ch, &error))) { 1912*0Sstevel@tonic-gate mutex_exit(&sp->lock); 1913*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1914*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d function 0x%x " 1915*0Sstevel@tonic-gate "invalid client handle created handle 0x%x\n", 1916*0Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 1917*0Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 1918*0Sstevel@tonic-gate (int)*ch); 1919*0Sstevel@tonic-gate return (error); 1920*0Sstevel@tonic-gate } 1921*0Sstevel@tonic-gate 1922*0Sstevel@tonic-gate /* 1923*0Sstevel@tonic-gate * Save the DDI information. 1924*0Sstevel@tonic-gate */ 1925*0Sstevel@tonic-gate client->dip = cr->dip; 1926*0Sstevel@tonic-gate cr->driver_name[MODMAXNAMELEN - 1] = NULL; 1927*0Sstevel@tonic-gate client->driver_name = (char *)kmem_zalloc(strlen(cr->driver_name) + 1, 1928*0Sstevel@tonic-gate KM_SLEEP); 1929*0Sstevel@tonic-gate (void) strcpy(client->driver_name, cr->driver_name); 1930*0Sstevel@tonic-gate client->instance = ddi_get_instance(cr->dip); 1931*0Sstevel@tonic-gate 1932*0Sstevel@tonic-gate /* 1933*0Sstevel@tonic-gate * Copy over the interesting items that the client gave us. 1934*0Sstevel@tonic-gate */ 1935*0Sstevel@tonic-gate client->flags = (cr->Attributes & INFO_CLIENT_TYPE_MASK); 1936*0Sstevel@tonic-gate client->event_callback_handler = cr->event_handler; 1937*0Sstevel@tonic-gate bcopy((caddr_t)&cr->event_callback_args, 1938*0Sstevel@tonic-gate (caddr_t)&client->event_callback_args, 1939*0Sstevel@tonic-gate sizeof (event_callback_args_t)); 1940*0Sstevel@tonic-gate /* 1941*0Sstevel@tonic-gate * Set the client handle since the client needs a client handle 1942*0Sstevel@tonic-gate * when they call us for their event handler. 1943*0Sstevel@tonic-gate */ 1944*0Sstevel@tonic-gate client->event_callback_args.client_handle = *ch; 1945*0Sstevel@tonic-gate 1946*0Sstevel@tonic-gate /* 1947*0Sstevel@tonic-gate * Initialize the IO window numbers; if an IO window number is equal 1948*0Sstevel@tonic-gate * to PCMCIA_MAX_WINDOWS it means that IO range is not in use. 1949*0Sstevel@tonic-gate */ 1950*0Sstevel@tonic-gate client->io_alloc.Window1 = PCMCIA_MAX_WINDOWS; 1951*0Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 1952*0Sstevel@tonic-gate 1953*0Sstevel@tonic-gate /* 1954*0Sstevel@tonic-gate * Give the client the iblock and idevice cookies to use in 1955*0Sstevel@tonic-gate * the client's event handler high priority mutex. 1956*0Sstevel@tonic-gate */ 1957*0Sstevel@tonic-gate cr->iblk_cookie = sp->iblk; 1958*0Sstevel@tonic-gate cr->idev_cookie = sp->idev; 1959*0Sstevel@tonic-gate 1960*0Sstevel@tonic-gate /* 1961*0Sstevel@tonic-gate * Set up the global event mask information; we copy this directly 1962*0Sstevel@tonic-gate * from the client; since we are the only source of events, 1963*0Sstevel@tonic-gate * any bogus bits that the client puts in here won't matter 1964*0Sstevel@tonic-gate * because we'll never look at them. 1965*0Sstevel@tonic-gate */ 1966*0Sstevel@tonic-gate client->global_mask = cr->EventMask; 1967*0Sstevel@tonic-gate 1968*0Sstevel@tonic-gate /* 1969*0Sstevel@tonic-gate * If this client registered as a CSI client, set the appropriate 1970*0Sstevel@tonic-gate * flag in the client's flags area. 1971*0Sstevel@tonic-gate */ 1972*0Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 1973*0Sstevel@tonic-gate client->flags |= CLIENT_CSI_CLIENT; 1974*0Sstevel@tonic-gate 1975*0Sstevel@tonic-gate /* 1976*0Sstevel@tonic-gate * If this client registered as a "super-client" set the appropriate 1977*0Sstevel@tonic-gate * flag in the client's flags area. 1978*0Sstevel@tonic-gate */ 1979*0Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) 1980*0Sstevel@tonic-gate client->flags |= CLIENT_SUPER_CLIENT; 1981*0Sstevel@tonic-gate 1982*0Sstevel@tonic-gate /* 1983*0Sstevel@tonic-gate * Save other misc information that this client gave us - it is 1984*0Sstevel@tonic-gate * used in the GetClientInfo function. 1985*0Sstevel@tonic-gate */ 1986*0Sstevel@tonic-gate client->flags |= (cr->Attributes & INFO_CARD_FLAGS_MASK); 1987*0Sstevel@tonic-gate 1988*0Sstevel@tonic-gate /* 1989*0Sstevel@tonic-gate * Determine if we should give artificial card insertion events and 1990*0Sstevel@tonic-gate * a registration complete event. Since we don't differentiate 1991*0Sstevel@tonic-gate * between sharable and exclusive use cards when giving clients 1992*0Sstevel@tonic-gate * event notification, we modify the definition of the share/excl 1993*0Sstevel@tonic-gate * flags as follows: 1994*0Sstevel@tonic-gate * 1995*0Sstevel@tonic-gate * If either INFO_CARD_SHARE or INFO_CARD_EXCL is set, 1996*0Sstevel@tonic-gate * the client will receive artificial card insertion 1997*0Sstevel@tonic-gate * events (if the client's card is currently in the 1998*0Sstevel@tonic-gate * socket) and a registration complete event. 1999*0Sstevel@tonic-gate * 2000*0Sstevel@tonic-gate * If neither of the INFO_CARD_SHARE or INFO_CARD_EXCL is 2001*0Sstevel@tonic-gate * set, the client will not receive an artificial card 2002*0Sstevel@tonic-gate * insertion event nor a registration complete event 2003*0Sstevel@tonic-gate * due to the client's call to register client. 2004*0Sstevel@tonic-gate * 2005*0Sstevel@tonic-gate * The client's event mask is not affected by the setting 2006*0Sstevel@tonic-gate * of these two bits. 2007*0Sstevel@tonic-gate */ 2008*0Sstevel@tonic-gate if (cr->Attributes & (INFO_CARD_SHARE | INFO_CARD_EXCL)) 2009*0Sstevel@tonic-gate client->pending_events = CS_EVENT_REGISTRATION_COMPLETE; 2010*0Sstevel@tonic-gate 2011*0Sstevel@tonic-gate /* 2012*0Sstevel@tonic-gate * Check to see if the card for this client is currently in 2013*0Sstevel@tonic-gate * the socket. If it is, then set CLIENT_CARD_INSERTED 2014*0Sstevel@tonic-gate * since clients that are calling GetStatus at attach 2015*0Sstevel@tonic-gate * time will typically check to see if their card is 2016*0Sstevel@tonic-gate * currently installed. 2017*0Sstevel@tonic-gate * If this is the CSI client, we also need to check to see 2018*0Sstevel@tonic-gate * if there is any card inserted in the socket, since 2019*0Sstevel@tonic-gate * the cs_card_for_client function will always return 2020*0Sstevel@tonic-gate * TRUE for a CSI client. 2021*0Sstevel@tonic-gate * XXX What about super-clients? 2022*0Sstevel@tonic-gate */ 2023*0Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) { 2024*0Sstevel@tonic-gate get_ss_status_t get_ss_status; 2025*0Sstevel@tonic-gate 2026*0Sstevel@tonic-gate get_ss_status.socket = sp->socket_num; 2027*0Sstevel@tonic-gate 2028*0Sstevel@tonic-gate if (SocketServices(SS_GetStatus, &get_ss_status) != SUCCESS) { 2029*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2030*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2031*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2032*0Sstevel@tonic-gate } /* SS_GetStatus */ 2033*0Sstevel@tonic-gate 2034*0Sstevel@tonic-gate if (!(cs_sbm2cse(get_ss_status.CardState) & 2035*0Sstevel@tonic-gate CS_EVENT_CARD_INSERTION)) 2036*0Sstevel@tonic-gate cie = 0; 2037*0Sstevel@tonic-gate 2038*0Sstevel@tonic-gate } /* CLIENT_CSI_CLIENT */ 2039*0Sstevel@tonic-gate 2040*0Sstevel@tonic-gate if (cs_card_for_client(client) && (cie != 0)) { 2041*0Sstevel@tonic-gate client->pending_events |= CS_EVENT_CARD_INSERTION; 2042*0Sstevel@tonic-gate client->flags |= CLIENT_CARD_INSERTED; 2043*0Sstevel@tonic-gate } /* cs_card_for_client */ 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate sp->num_clients++; 2046*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2047*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2048*0Sstevel@tonic-gate 2049*0Sstevel@tonic-gate return (CS_SUCCESS); 2050*0Sstevel@tonic-gate } 2051*0Sstevel@tonic-gate 2052*0Sstevel@tonic-gate /* 2053*0Sstevel@tonic-gate * cs_deregister_client - This supports the DeregisterClient call. 2054*0Sstevel@tonic-gate */ 2055*0Sstevel@tonic-gate static int 2056*0Sstevel@tonic-gate cs_deregister_client(client_handle_t client_handle) 2057*0Sstevel@tonic-gate { 2058*0Sstevel@tonic-gate cs_socket_t *sp; 2059*0Sstevel@tonic-gate client_t *client; 2060*0Sstevel@tonic-gate int error, super_client = 0; 2061*0Sstevel@tonic-gate int client_lock_acquired; 2062*0Sstevel@tonic-gate 2063*0Sstevel@tonic-gate /* 2064*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 2065*0Sstevel@tonic-gate * is, we don't do anything except for return success. 2066*0Sstevel@tonic-gate */ 2067*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 2068*0Sstevel@tonic-gate return (CS_SUCCESS); 2069*0Sstevel@tonic-gate 2070*0Sstevel@tonic-gate /* 2071*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 2072*0Sstevel@tonic-gate */ 2073*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2074*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2075*0Sstevel@tonic-gate 2076*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 2077*0Sstevel@tonic-gate 2078*0Sstevel@tonic-gate /* 2079*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 2080*0Sstevel@tonic-gate */ 2081*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 2082*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2083*0Sstevel@tonic-gate return (error); 2084*0Sstevel@tonic-gate } 2085*0Sstevel@tonic-gate 2086*0Sstevel@tonic-gate /* 2087*0Sstevel@tonic-gate * Make sure that any resources allocated by this client are 2088*0Sstevel@tonic-gate * not still allocated, and that if this is an MTD that 2089*0Sstevel@tonic-gate * no MTD operations are still in progress. 2090*0Sstevel@tonic-gate */ 2091*0Sstevel@tonic-gate if (client->flags & (CLIENT_IO_ALLOCATED | 2092*0Sstevel@tonic-gate CLIENT_IRQ_ALLOCATED | 2093*0Sstevel@tonic-gate CLIENT_WIN_ALLOCATED | 2094*0Sstevel@tonic-gate REQ_CONFIGURATION_DONE | 2095*0Sstevel@tonic-gate REQ_SOCKET_MASK_DONE | 2096*0Sstevel@tonic-gate REQ_IO_DONE | 2097*0Sstevel@tonic-gate REQ_IRQ_DONE)) { 2098*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2099*0Sstevel@tonic-gate return (CS_BUSY); 2100*0Sstevel@tonic-gate } 2101*0Sstevel@tonic-gate 2102*0Sstevel@tonic-gate if (client->flags & CLIENT_MTD_IN_PROGRESS) { 2103*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2104*0Sstevel@tonic-gate return (CS_IN_USE); 2105*0Sstevel@tonic-gate } 2106*0Sstevel@tonic-gate 2107*0Sstevel@tonic-gate /* 2108*0Sstevel@tonic-gate * Any previously allocated resources are not allocated anymore, and 2109*0Sstevel@tonic-gate * no MTD operations are in progress, so if this is an MTD client 2110*0Sstevel@tonic-gate * then do any MTD-specific client deregistration, and then 2111*0Sstevel@tonic-gate * nuke this client. 2112*0Sstevel@tonic-gate * We expect cs_deregister_mtd to never fail. 2113*0Sstevel@tonic-gate */ 2114*0Sstevel@tonic-gate if (client->flags & INFO_MTD_CLIENT) 2115*0Sstevel@tonic-gate (void) cs_deregister_mtd(client_handle); 2116*0Sstevel@tonic-gate 2117*0Sstevel@tonic-gate if (client->flags & CLIENT_SUPER_CLIENT) 2118*0Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 2119*0Sstevel@tonic-gate 2120*0Sstevel@tonic-gate kmem_free(client->driver_name, strlen(client->driver_name) + 1); 2121*0Sstevel@tonic-gate 2122*0Sstevel@tonic-gate error = cs_destroy_client_handle(client_handle); 2123*0Sstevel@tonic-gate 2124*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2125*0Sstevel@tonic-gate 2126*0Sstevel@tonic-gate /* 2127*0Sstevel@tonic-gate * If this was the "super-client" deregistering, then this 2128*0Sstevel@tonic-gate * will clear the global "super-client" lock. 2129*0Sstevel@tonic-gate * XXX - move this outside the per-socket code. 2130*0Sstevel@tonic-gate */ 2131*0Sstevel@tonic-gate cs_clear_superclient_lock(super_client); 2132*0Sstevel@tonic-gate 2133*0Sstevel@tonic-gate return (error); 2134*0Sstevel@tonic-gate } 2135*0Sstevel@tonic-gate 2136*0Sstevel@tonic-gate /* 2137*0Sstevel@tonic-gate * cs_create_next_client_minor - returns the next available client minor 2138*0Sstevel@tonic-gate * number or 0 if none available 2139*0Sstevel@tonic-gate * 2140*0Sstevel@tonic-gate * Note that cs_find_client will always return a valid pointer to the 2141*0Sstevel@tonic-gate * global Socket Services client which has a client minor number 2142*0Sstevel@tonic-gate * of 0; this means that this function can never return a 0 as the 2143*0Sstevel@tonic-gate * next valid available client minor number. 2144*0Sstevel@tonic-gate */ 2145*0Sstevel@tonic-gate unsigned 2146*0Sstevel@tonic-gate cs_create_next_client_minor(unsigned socket_num, unsigned next_minor) 2147*0Sstevel@tonic-gate { 2148*0Sstevel@tonic-gate unsigned max_client_handles = cs_max_client_handles; 2149*0Sstevel@tonic-gate 2150*0Sstevel@tonic-gate do { 2151*0Sstevel@tonic-gate next_minor &= CS_MAX_CLIENTS_MASK; 2152*0Sstevel@tonic-gate if (!cs_find_client(MAKE_CLIENT_HANDLE( 2153*0Sstevel@tonic-gate CS_GET_SOCKET_NUMBER(socket_num), 2154*0Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 2155*0Sstevel@tonic-gate next_minor), NULL)) { 2156*0Sstevel@tonic-gate return (next_minor); 2157*0Sstevel@tonic-gate } 2158*0Sstevel@tonic-gate next_minor++; 2159*0Sstevel@tonic-gate } while (max_client_handles--); 2160*0Sstevel@tonic-gate 2161*0Sstevel@tonic-gate return (0); 2162*0Sstevel@tonic-gate } 2163*0Sstevel@tonic-gate 2164*0Sstevel@tonic-gate /* 2165*0Sstevel@tonic-gate * cs_find_client - finds the client pointer associated with the client handle 2166*0Sstevel@tonic-gate * or NULL if client not found 2167*0Sstevel@tonic-gate * 2168*0Sstevel@tonic-gate * returns: (client_t *)NULL - if client not found or an error occured 2169*0Sstevel@tonic-gate * If the error argument is not NULL, 2170*0Sstevel@tonic-gate * it is set to: 2171*0Sstevel@tonic-gate * CS_BAD_SOCKET - socket number in client_handle_t is 2172*0Sstevel@tonic-gate * invalid 2173*0Sstevel@tonic-gate * CS_BAD_HANDLE - client not found 2174*0Sstevel@tonic-gate * If no error, the error argument is not modified. 2175*0Sstevel@tonic-gate * (client_t *) - pointer to client_t structure 2176*0Sstevel@tonic-gate * 2177*0Sstevel@tonic-gate * Note that each socket always has a pseudo client with a client minor number 2178*0Sstevel@tonic-gate * of 0; this client minor number is used for Socket Services access to 2179*0Sstevel@tonic-gate * Card Services functions. The client pointer returned for client minor 2180*0Sstevel@tonic-gate * number 0 is the global Socket Services client pointer. 2181*0Sstevel@tonic-gate */ 2182*0Sstevel@tonic-gate static client_t * 2183*0Sstevel@tonic-gate cs_find_client(client_handle_t client_handle, int *error) 2184*0Sstevel@tonic-gate { 2185*0Sstevel@tonic-gate cs_socket_t *sp; 2186*0Sstevel@tonic-gate client_t *clp; 2187*0Sstevel@tonic-gate 2188*0Sstevel@tonic-gate /* 2189*0Sstevel@tonic-gate * If we are being asked to see if a client with a minor number 2190*0Sstevel@tonic-gate * of 0 exists, always return a pointer to the global Socket 2191*0Sstevel@tonic-gate * Services client, since this client always exists, and is 2192*0Sstevel@tonic-gate * only for use by Socket Services. There is no socket 2193*0Sstevel@tonic-gate * associated with this special client handle. 2194*0Sstevel@tonic-gate */ 2195*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 2196*0Sstevel@tonic-gate return (&cs_socket_services_client); 2197*0Sstevel@tonic-gate 2198*0Sstevel@tonic-gate /* 2199*0Sstevel@tonic-gate * Check to be sure that the socket number is in range 2200*0Sstevel@tonic-gate */ 2201*0Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(GET_CLIENT_SOCKET(client_handle), 2202*0Sstevel@tonic-gate cs_globals.max_socket_num))) { 2203*0Sstevel@tonic-gate if (error) 2204*0Sstevel@tonic-gate *error = CS_BAD_SOCKET; 2205*0Sstevel@tonic-gate return (NULL); 2206*0Sstevel@tonic-gate } 2207*0Sstevel@tonic-gate 2208*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) { 2209*0Sstevel@tonic-gate if (error) 2210*0Sstevel@tonic-gate *error = CS_BAD_SOCKET; 2211*0Sstevel@tonic-gate return (NULL); 2212*0Sstevel@tonic-gate } 2213*0Sstevel@tonic-gate 2214*0Sstevel@tonic-gate clp = sp->client_list; 2215*0Sstevel@tonic-gate 2216*0Sstevel@tonic-gate while (clp) { 2217*0Sstevel@tonic-gate if (clp->client_handle == client_handle) 2218*0Sstevel@tonic-gate return (clp); 2219*0Sstevel@tonic-gate clp = clp->next; 2220*0Sstevel@tonic-gate } 2221*0Sstevel@tonic-gate 2222*0Sstevel@tonic-gate if (error) 2223*0Sstevel@tonic-gate *error = CS_BAD_HANDLE; 2224*0Sstevel@tonic-gate 2225*0Sstevel@tonic-gate return (NULL); 2226*0Sstevel@tonic-gate } 2227*0Sstevel@tonic-gate 2228*0Sstevel@tonic-gate /* 2229*0Sstevel@tonic-gate * cs_destroy_client_handle - destroys client handle and client structure of 2230*0Sstevel@tonic-gate * passed client handle 2231*0Sstevel@tonic-gate * 2232*0Sstevel@tonic-gate * returns: CS_SUCCESS - if client handle sucessfully destroyed 2233*0Sstevel@tonic-gate * CS_BAD_HANDLE - if client handle is invalid or if trying 2234*0Sstevel@tonic-gate * to destroy global SS client 2235*0Sstevel@tonic-gate * {other errors} - other errors from cs_find_client() 2236*0Sstevel@tonic-gate */ 2237*0Sstevel@tonic-gate static int 2238*0Sstevel@tonic-gate cs_destroy_client_handle(client_handle_t client_handle) 2239*0Sstevel@tonic-gate { 2240*0Sstevel@tonic-gate client_t *clp; 2241*0Sstevel@tonic-gate cs_socket_t *sp; 2242*0Sstevel@tonic-gate int error = CS_BAD_HANDLE; 2243*0Sstevel@tonic-gate 2244*0Sstevel@tonic-gate /* 2245*0Sstevel@tonic-gate * See if we were passed a valid client handle or if we're being asked 2246*0Sstevel@tonic-gate * to destroy the Socket Services client 2247*0Sstevel@tonic-gate */ 2248*0Sstevel@tonic-gate if ((!(clp = cs_find_client(client_handle, &error))) || 2249*0Sstevel@tonic-gate (CLIENT_HANDLE_IS_SS(client_handle))) 2250*0Sstevel@tonic-gate return (error); 2251*0Sstevel@tonic-gate 2252*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2253*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2254*0Sstevel@tonic-gate 2255*0Sstevel@tonic-gate /* 2256*0Sstevel@tonic-gate * Recycle this client's minor number. This will most likely 2257*0Sstevel@tonic-gate * be the next client minor number we use, but it is also 2258*0Sstevel@tonic-gate * a hint to cs_create_client_handle, and that function 2259*0Sstevel@tonic-gate * may actually create a new client handle using a minor 2260*0Sstevel@tonic-gate * number different that this number. 2261*0Sstevel@tonic-gate */ 2262*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2263*0Sstevel@tonic-gate sp->next_cl_minor = GET_CLIENT_MINOR(client_handle); 2264*0Sstevel@tonic-gate 2265*0Sstevel@tonic-gate /* 2266*0Sstevel@tonic-gate * See if we're the first or not in the client list; if we're 2267*0Sstevel@tonic-gate * not first, then just adjust the client behind us to 2268*0Sstevel@tonic-gate * point to the client ahead of us; this could be NULL 2269*0Sstevel@tonic-gate * if we're the last client in the list. 2270*0Sstevel@tonic-gate */ 2271*0Sstevel@tonic-gate if (clp->prev) { 2272*0Sstevel@tonic-gate clp->prev->next = clp->next; 2273*0Sstevel@tonic-gate } else { 2274*0Sstevel@tonic-gate /* 2275*0Sstevel@tonic-gate * We are first, so adjust the client list head pointer 2276*0Sstevel@tonic-gate * in the socket to point to the client structure that 2277*0Sstevel@tonic-gate * follows us; this could turn out to be NULL if we're 2278*0Sstevel@tonic-gate * the only client on this socket. 2279*0Sstevel@tonic-gate */ 2280*0Sstevel@tonic-gate sp->client_list = clp->next; 2281*0Sstevel@tonic-gate } 2282*0Sstevel@tonic-gate 2283*0Sstevel@tonic-gate /* 2284*0Sstevel@tonic-gate * If we're not the last client in the list, point the next 2285*0Sstevel@tonic-gate * client to the client behind us; this could turn out 2286*0Sstevel@tonic-gate * to be NULL if we're the first client on this socket. 2287*0Sstevel@tonic-gate */ 2288*0Sstevel@tonic-gate if (clp->next) 2289*0Sstevel@tonic-gate clp->next->prev = clp->prev; 2290*0Sstevel@tonic-gate 2291*0Sstevel@tonic-gate sp->num_clients--; 2292*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2293*0Sstevel@tonic-gate 2294*0Sstevel@tonic-gate /* 2295*0Sstevel@tonic-gate * Free this client's memory. 2296*0Sstevel@tonic-gate */ 2297*0Sstevel@tonic-gate kmem_free(clp, sizeof (client_t)); 2298*0Sstevel@tonic-gate 2299*0Sstevel@tonic-gate return (CS_SUCCESS); 2300*0Sstevel@tonic-gate } 2301*0Sstevel@tonic-gate 2302*0Sstevel@tonic-gate /* 2303*0Sstevel@tonic-gate * cs_create_client_handle - create a new client handle for the passed 2304*0Sstevel@tonic-gate * socket and function number 2305*0Sstevel@tonic-gate * 2306*0Sstevel@tonic-gate * returns: 0 - if can't create client for some reason 2307*0Sstevel@tonic-gate * client_handle_t - new client handle 2308*0Sstevel@tonic-gate */ 2309*0Sstevel@tonic-gate static client_handle_t 2310*0Sstevel@tonic-gate cs_create_client_handle(unsigned socket_num, client_t *cclp) 2311*0Sstevel@tonic-gate { 2312*0Sstevel@tonic-gate client_t *clp; 2313*0Sstevel@tonic-gate cs_socket_t *sp; 2314*0Sstevel@tonic-gate unsigned next_minor; 2315*0Sstevel@tonic-gate client_handle_t client_handle; 2316*0Sstevel@tonic-gate 2317*0Sstevel@tonic-gate if ((sp = cs_get_sp(socket_num)) == NULL) 2318*0Sstevel@tonic-gate return (0); 2319*0Sstevel@tonic-gate 2320*0Sstevel@tonic-gate /* 2321*0Sstevel@tonic-gate * Get the next available minor number that we can use. We use the 2322*0Sstevel@tonic-gate * next_cl_minor number as a hint to cs_create_next_client_minor 2323*0Sstevel@tonic-gate * and in most cases this will be the minor number we get back. 2324*0Sstevel@tonic-gate * If for some reason we can't get a minor number, return an error. 2325*0Sstevel@tonic-gate * The only way we could get an error would be if there are 2326*0Sstevel@tonic-gate * already the maximum number of clients for this socket. Since 2327*0Sstevel@tonic-gate * the maximum number of clients per socket is pretty large, 2328*0Sstevel@tonic-gate * this error is unlikely to occur. 2329*0Sstevel@tonic-gate */ 2330*0Sstevel@tonic-gate if (!(next_minor = 2331*0Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor))) 2332*0Sstevel@tonic-gate return (0); 2333*0Sstevel@tonic-gate 2334*0Sstevel@tonic-gate /* 2335*0Sstevel@tonic-gate * Got a new client minor number, now create a new client handle. 2336*0Sstevel@tonic-gate */ 2337*0Sstevel@tonic-gate client_handle = MAKE_CLIENT_HANDLE(CS_GET_SOCKET_NUMBER(socket_num), 2338*0Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 2339*0Sstevel@tonic-gate next_minor); 2340*0Sstevel@tonic-gate 2341*0Sstevel@tonic-gate /* 2342*0Sstevel@tonic-gate * If this client handle exists, then we have an internal 2343*0Sstevel@tonic-gate * error; this should never happen, BTW. This is really 2344*0Sstevel@tonic-gate * a double-check on the cs_create_next_client_minor 2345*0Sstevel@tonic-gate * function, which also calls cs_find_client. 2346*0Sstevel@tonic-gate */ 2347*0Sstevel@tonic-gate if (cs_find_client(client_handle, NULL)) { 2348*0Sstevel@tonic-gate cmn_err(CE_CONT, 2349*0Sstevel@tonic-gate "cs_create_client_handle: duplicate client handle 0x%x\n", 2350*0Sstevel@tonic-gate (int)client_handle); 2351*0Sstevel@tonic-gate return (0); 2352*0Sstevel@tonic-gate } 2353*0Sstevel@tonic-gate 2354*0Sstevel@tonic-gate /* 2355*0Sstevel@tonic-gate * If we don't have any clients on this socket yet, create 2356*0Sstevel@tonic-gate * a new client and hang it on the socket client list. 2357*0Sstevel@tonic-gate */ 2358*0Sstevel@tonic-gate if (!sp->client_list) { 2359*0Sstevel@tonic-gate sp->client_list = cclp; 2360*0Sstevel@tonic-gate clp = sp->client_list; 2361*0Sstevel@tonic-gate } else { 2362*0Sstevel@tonic-gate /* 2363*0Sstevel@tonic-gate * There are other clients on this socket, so look for 2364*0Sstevel@tonic-gate * the last client and add our new client after it. 2365*0Sstevel@tonic-gate */ 2366*0Sstevel@tonic-gate clp = sp->client_list; 2367*0Sstevel@tonic-gate while (clp->next) { 2368*0Sstevel@tonic-gate clp = clp->next; 2369*0Sstevel@tonic-gate } 2370*0Sstevel@tonic-gate 2371*0Sstevel@tonic-gate clp->next = cclp; 2372*0Sstevel@tonic-gate clp->next->prev = clp; 2373*0Sstevel@tonic-gate clp = clp->next; 2374*0Sstevel@tonic-gate } /* if (!sp->client_list) */ 2375*0Sstevel@tonic-gate 2376*0Sstevel@tonic-gate /* 2377*0Sstevel@tonic-gate * Assign the new client handle to this new client structure. 2378*0Sstevel@tonic-gate */ 2379*0Sstevel@tonic-gate clp->client_handle = client_handle; 2380*0Sstevel@tonic-gate 2381*0Sstevel@tonic-gate /* 2382*0Sstevel@tonic-gate * Create the next available client minor number for this socket 2383*0Sstevel@tonic-gate * and save it away. 2384*0Sstevel@tonic-gate */ 2385*0Sstevel@tonic-gate sp->next_cl_minor = 2386*0Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor); 2387*0Sstevel@tonic-gate 2388*0Sstevel@tonic-gate return (client_handle); 2389*0Sstevel@tonic-gate } 2390*0Sstevel@tonic-gate 2391*0Sstevel@tonic-gate /* 2392*0Sstevel@tonic-gate * cs_clear_superclient_lock - clears the global "super-client" lock 2393*0Sstevel@tonic-gate * 2394*0Sstevel@tonic-gate * Note: this function uses the cs_globals.global_lock so observe proper 2395*0Sstevel@tonic-gate * nexting of locks!! 2396*0Sstevel@tonic-gate */ 2397*0Sstevel@tonic-gate static void 2398*0Sstevel@tonic-gate cs_clear_superclient_lock(int super_client) 2399*0Sstevel@tonic-gate { 2400*0Sstevel@tonic-gate 2401*0Sstevel@tonic-gate /* 2402*0Sstevel@tonic-gate * If this was a "super-client" registering then we need 2403*0Sstevel@tonic-gate * to clear the GLOBAL_SUPER_CLIENT_REGISTERED flag 2404*0Sstevel@tonic-gate * so that other "super-clients" can register. 2405*0Sstevel@tonic-gate */ 2406*0Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) { 2407*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 2408*0Sstevel@tonic-gate cs_globals.flags &= ~GLOBAL_SUPER_CLIENT_REGISTERED; 2409*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 2410*0Sstevel@tonic-gate } 2411*0Sstevel@tonic-gate } 2412*0Sstevel@tonic-gate 2413*0Sstevel@tonic-gate /* 2414*0Sstevel@tonic-gate * ==== event handling section ==== 2415*0Sstevel@tonic-gate */ 2416*0Sstevel@tonic-gate 2417*0Sstevel@tonic-gate /* 2418*0Sstevel@tonic-gate * cs_event - CS event hi-priority callback handler 2419*0Sstevel@tonic-gate * 2420*0Sstevel@tonic-gate * This function gets called by SS and is passed the event type in 2421*0Sstevel@tonic-gate * the "event" argument, and the socket number in the "sn" 2422*0Sstevel@tonic-gate * argument. The "sn" argument is a valid logical socket 2423*0Sstevel@tonic-gate * number for all events except the PCE_SS_READY event. 2424*0Sstevel@tonic-gate * 2425*0Sstevel@tonic-gate * The PCE_SS_INIT_STATE, PCE_ADD_SOCKET and PCE_DROP_SOCKET events 2426*0Sstevel@tonic-gate * are never called at high priority. These events return 2427*0Sstevel@tonic-gate * the following return codes: 2428*0Sstevel@tonic-gate * 2429*0Sstevel@tonic-gate * CS_SUCCESS - operation sucessful 2430*0Sstevel@tonic-gate * CS_BAD_SOCKET - unable to complete operation 2431*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - bad subfunction of 2432*0Sstevel@tonic-gate * PCE_SS_INIT_STATE 2433*0Sstevel@tonic-gate * 2434*0Sstevel@tonic-gate * The caller MUST look at these return codes! 2435*0Sstevel@tonic-gate * 2436*0Sstevel@tonic-gate * This function is called at high-priority interrupt time for standard 2437*0Sstevel@tonic-gate * Card Services events, and the only standard Card Services 2438*0Sstevel@tonic-gate * event that it handles directly is the CS_EVENT_CARD_REMOVAL 2439*0Sstevel@tonic-gate * event, which gets shuttled right into the client's event 2440*0Sstevel@tonic-gate * handler. All other events are just queued up and the socket 2441*0Sstevel@tonic-gate * event thread is woken up via the soft interrupt handler. 2442*0Sstevel@tonic-gate * Note that CS_EVENT_CARD_INSERTION events are not set in the clients' 2443*0Sstevel@tonic-gate * event field, since the CS card insertion/card ready processing 2444*0Sstevel@tonic-gate * code is responsible for setting this event in a client's 2445*0Sstevel@tonic-gate * event field. 2446*0Sstevel@tonic-gate * 2447*0Sstevel@tonic-gate */ 2448*0Sstevel@tonic-gate /*ARGSUSED*/ 2449*0Sstevel@tonic-gate uint32_t 2450*0Sstevel@tonic-gate cs_event(event_t event, uint32_t sn, uint32_t arg) 2451*0Sstevel@tonic-gate { 2452*0Sstevel@tonic-gate client_t *client; 2453*0Sstevel@tonic-gate cs_socket_t *sp; 2454*0Sstevel@tonic-gate client_types_t *ct; 2455*0Sstevel@tonic-gate uint32_t ret = CS_SUCCESS; 2456*0Sstevel@tonic-gate 2457*0Sstevel@tonic-gate /* 2458*0Sstevel@tonic-gate * Handle special SS<->CS events 2459*0Sstevel@tonic-gate */ 2460*0Sstevel@tonic-gate switch (event) { 2461*0Sstevel@tonic-gate case PCE_SS_INIT_STATE: 2462*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 2463*0Sstevel@tonic-gate switch (sn) { 2464*0Sstevel@tonic-gate case PCE_SS_STATE_INIT: 2465*0Sstevel@tonic-gate if ((ret = cs_ss_init()) == CS_SUCCESS) 2466*0Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SS_READY; 2467*0Sstevel@tonic-gate break; 2468*0Sstevel@tonic-gate case PCE_SS_STATE_DEINIT: 2469*0Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SS_READY; 2470*0Sstevel@tonic-gate break; 2471*0Sstevel@tonic-gate default: 2472*0Sstevel@tonic-gate ret = CS_UNSUPPORTED_FUNCTION; 2473*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: PCE_SS_INIT_STATE invalid " 2474*0Sstevel@tonic-gate "directive: 0x%x\n", sn); 2475*0Sstevel@tonic-gate break; 2476*0Sstevel@tonic-gate } /* switch (sn) */ 2477*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 2478*0Sstevel@tonic-gate return (ret); 2479*0Sstevel@tonic-gate case PCE_ADD_SOCKET: 2480*0Sstevel@tonic-gate return (cs_add_socket(sn)); 2481*0Sstevel@tonic-gate case PCE_DROP_SOCKET: 2482*0Sstevel@tonic-gate return (cs_drop_socket(sn)); 2483*0Sstevel@tonic-gate } /* switch (event) */ 2484*0Sstevel@tonic-gate 2485*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 2486*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2487*0Sstevel@tonic-gate 2488*0Sstevel@tonic-gate /* 2489*0Sstevel@tonic-gate * Check to see if CS wants to unload - we do this since it's possible 2490*0Sstevel@tonic-gate * to disable certain sockets. Do NOT acquire any locks yet. 2491*0Sstevel@tonic-gate */ 2492*0Sstevel@tonic-gate if (sp->flags & SOCKET_UNLOAD_MODULE) { 2493*0Sstevel@tonic-gate if (event == PCE_CARD_INSERT) 2494*0Sstevel@tonic-gate cmn_err(CE_CONT, "PCMCIA: socket %d disabled - please " 2495*0Sstevel@tonic-gate "remove card\n", sn); 2496*0Sstevel@tonic-gate return (CS_SUCCESS); 2497*0Sstevel@tonic-gate } 2498*0Sstevel@tonic-gate 2499*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2500*0Sstevel@tonic-gate 2501*0Sstevel@tonic-gate #ifdef CS_DEBUG 2502*0Sstevel@tonic-gate if (cs_debug > 1) { 2503*0Sstevel@tonic-gate event2text_t event2text; 2504*0Sstevel@tonic-gate 2505*0Sstevel@tonic-gate event2text.event = event; 2506*0Sstevel@tonic-gate (void) cs_event2text(&event2text, 0); 2507*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: event=%s (x%x), socket=0x%x\n", 2508*0Sstevel@tonic-gate event2text.text, (int)event, (int)sn); 2509*0Sstevel@tonic-gate } 2510*0Sstevel@tonic-gate #endif 2511*0Sstevel@tonic-gate 2512*0Sstevel@tonic-gate /* 2513*0Sstevel@tonic-gate * Convert SS events to CS events; handle the PRR if necessary. 2514*0Sstevel@tonic-gate */ 2515*0Sstevel@tonic-gate sp->events |= ss_to_cs_events(sp, event); 2516*0Sstevel@tonic-gate 2517*0Sstevel@tonic-gate /* 2518*0Sstevel@tonic-gate * We want to maintain the required event dispatching order as 2519*0Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 2520*0Sstevel@tonic-gate * clients on this socket to make sure that they are 2521*0Sstevel@tonic-gate * notified in the correct order of any high-priority 2522*0Sstevel@tonic-gate * events. 2523*0Sstevel@tonic-gate */ 2524*0Sstevel@tonic-gate ct = &client_types[0]; 2525*0Sstevel@tonic-gate while (ct) { 2526*0Sstevel@tonic-gate /* 2527*0Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 2528*0Sstevel@tonic-gate * through each client to set up the client events as well as 2529*0Sstevel@tonic-gate * call the client's event handler directly if we have a high 2530*0Sstevel@tonic-gate * priority event that we need to tell the client about. 2531*0Sstevel@tonic-gate */ 2532*0Sstevel@tonic-gate client = sp->client_list; 2533*0Sstevel@tonic-gate 2534*0Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 2535*0Sstevel@tonic-gate client_t *clp = NULL; 2536*0Sstevel@tonic-gate 2537*0Sstevel@tonic-gate while (client) { 2538*0Sstevel@tonic-gate clp = client; 2539*0Sstevel@tonic-gate client = client->next; 2540*0Sstevel@tonic-gate } 2541*0Sstevel@tonic-gate client = clp; 2542*0Sstevel@tonic-gate } 2543*0Sstevel@tonic-gate 2544*0Sstevel@tonic-gate while (client) { 2545*0Sstevel@tonic-gate client->events |= ((sp->events & ~CS_EVENT_CARD_INSERTION) & 2546*0Sstevel@tonic-gate (client->event_mask | client->global_mask)); 2547*0Sstevel@tonic-gate if (client->flags & ct->type) { 2548*0Sstevel@tonic-gate #ifdef CS_DEBUG 2549*0Sstevel@tonic-gate if (cs_debug > 1) { 2550*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: socket %d client [%s] " 2551*0Sstevel@tonic-gate "events 0x%x flags 0x%x\n", 2552*0Sstevel@tonic-gate sn, client->driver_name, 2553*0Sstevel@tonic-gate (int)client->events, 2554*0Sstevel@tonic-gate (int)client->flags); 2555*0Sstevel@tonic-gate } 2556*0Sstevel@tonic-gate #endif 2557*0Sstevel@tonic-gate 2558*0Sstevel@tonic-gate /* 2559*0Sstevel@tonic-gate * Handle the suspend and card removal events 2560*0Sstevel@tonic-gate * specially here so that the client can receive 2561*0Sstevel@tonic-gate * these events at high-priority. 2562*0Sstevel@tonic-gate */ 2563*0Sstevel@tonic-gate if (client->events & CS_EVENT_PM_SUSPEND) { 2564*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 2565*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, CS_EVENT_PM_SUSPEND, 2566*0Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 2567*0Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 2568*0Sstevel@tonic-gate client->events &= ~CS_EVENT_PM_SUSPEND; 2569*0Sstevel@tonic-gate } /* if (CS_EVENT_PM_SUSPEND) */ 2570*0Sstevel@tonic-gate 2571*0Sstevel@tonic-gate if (client->events & CS_EVENT_CARD_REMOVAL) { 2572*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 2573*0Sstevel@tonic-gate client->flags &= ~(CLIENT_CARD_INSERTED | 2574*0Sstevel@tonic-gate CLIENT_SENT_INSERTION); 2575*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 2576*0Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 2577*0Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 2578*0Sstevel@tonic-gate /* 2579*0Sstevel@tonic-gate * Check to see if the client wants low priority 2580*0Sstevel@tonic-gate * removal events as well. 2581*0Sstevel@tonic-gate */ 2582*0Sstevel@tonic-gate if ((client->event_mask | client->global_mask) & 2583*0Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL_LOWP) { 2584*0Sstevel@tonic-gate client->events |= CS_EVENT_CARD_REMOVAL_LOWP; 2585*0Sstevel@tonic-gate } 2586*0Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 2587*0Sstevel@tonic-gate client->events &= ~CS_EVENT_CARD_REMOVAL; 2588*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2589*0Sstevel@tonic-gate 2590*0Sstevel@tonic-gate } /* if (ct->type) */ 2591*0Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 2592*0Sstevel@tonic-gate client = client->prev; 2593*0Sstevel@tonic-gate } else { 2594*0Sstevel@tonic-gate client = client->next; 2595*0Sstevel@tonic-gate } 2596*0Sstevel@tonic-gate } /* while (client) */ 2597*0Sstevel@tonic-gate 2598*0Sstevel@tonic-gate ct = ct->next; 2599*0Sstevel@tonic-gate } /* while (ct) */ 2600*0Sstevel@tonic-gate 2601*0Sstevel@tonic-gate /* 2602*0Sstevel@tonic-gate * Set the SOCKET_NEEDS_THREAD flag so that the soft interrupt 2603*0Sstevel@tonic-gate * handler will wakeup this socket's event thread. 2604*0Sstevel@tonic-gate */ 2605*0Sstevel@tonic-gate if (sp->events) 2606*0Sstevel@tonic-gate sp->flags |= SOCKET_NEEDS_THREAD; 2607*0Sstevel@tonic-gate 2608*0Sstevel@tonic-gate /* 2609*0Sstevel@tonic-gate * Fire off a soft interrupt that will cause the socket thread 2610*0Sstevel@tonic-gate * to be woken up and any remaining events to be sent to 2611*0Sstevel@tonic-gate * the clients on this socket. 2612*0Sstevel@tonic-gate */ 2613*0Sstevel@tonic-gate if ((sp->init_state & SOCKET_INIT_STATE_SOFTINTR) && 2614*0Sstevel@tonic-gate !(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) 2615*0Sstevel@tonic-gate ddi_trigger_softintr(sp->softint_id); 2616*0Sstevel@tonic-gate 2617*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2618*0Sstevel@tonic-gate 2619*0Sstevel@tonic-gate return (CS_SUCCESS); 2620*0Sstevel@tonic-gate } 2621*0Sstevel@tonic-gate 2622*0Sstevel@tonic-gate /* 2623*0Sstevel@tonic-gate * cs_card_insertion - handle card insertion and card ready events 2624*0Sstevel@tonic-gate * 2625*0Sstevel@tonic-gate * We read the CIS, if present, and store it away, then tell SS that 2626*0Sstevel@tonic-gate * we have read the CIS and it's ready to be parsed. Since card 2627*0Sstevel@tonic-gate * insertion and card ready events are pretty closely intertwined, 2628*0Sstevel@tonic-gate * we handle both here. For card ready events that are not the 2629*0Sstevel@tonic-gate * result of a card insertion event, we expect that the caller has 2630*0Sstevel@tonic-gate * already done the appropriate processing and that we will not be 2631*0Sstevel@tonic-gate * called unless we received a card ready event right after a card 2632*0Sstevel@tonic-gate * insertion event, i.e. that the SOCKET_WAIT_FOR_READY flag in 2633*0Sstevel@tonic-gate * sp->thread_state was set or if we get a CARD_READY event right 2634*0Sstevel@tonic-gate * after a CARD_INSERTION event. 2635*0Sstevel@tonic-gate * 2636*0Sstevel@tonic-gate * calling: sp - pointer to socket structure 2637*0Sstevel@tonic-gate * event - event to handle, one of: 2638*0Sstevel@tonic-gate * CS_EVENT_CARD_INSERTION 2639*0Sstevel@tonic-gate * CS_EVENT_CARD_READY 2640*0Sstevel@tonic-gate * CS_EVENT_SS_UPDATED 2641*0Sstevel@tonic-gate */ 2642*0Sstevel@tonic-gate static int 2643*0Sstevel@tonic-gate cs_card_insertion(cs_socket_t *sp, event_t event) 2644*0Sstevel@tonic-gate { 2645*0Sstevel@tonic-gate int ret; 2646*0Sstevel@tonic-gate 2647*0Sstevel@tonic-gate /* 2648*0Sstevel@tonic-gate * Since we're only called while waiting for the card insertion 2649*0Sstevel@tonic-gate * and card ready sequence to occur, we may have a pending 2650*0Sstevel@tonic-gate * card ready timer that hasn't gone off yet if we got a 2651*0Sstevel@tonic-gate * real card ready event. 2652*0Sstevel@tonic-gate */ 2653*0Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 2654*0Sstevel@tonic-gate 2655*0Sstevel@tonic-gate #ifdef CS_DEBUG 2656*0Sstevel@tonic-gate if (cs_debug > 1) { 2657*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: event=0x%x, socket=0x%x\n", 2658*0Sstevel@tonic-gate (int)event, sp->socket_num); 2659*0Sstevel@tonic-gate } 2660*0Sstevel@tonic-gate #endif 2661*0Sstevel@tonic-gate 2662*0Sstevel@tonic-gate /* 2663*0Sstevel@tonic-gate * Handle card insertion processing 2664*0Sstevel@tonic-gate */ 2665*0Sstevel@tonic-gate if (event & CS_EVENT_CARD_INSERTION) { 2666*0Sstevel@tonic-gate set_socket_t set_socket; 2667*0Sstevel@tonic-gate get_ss_status_t gs; 2668*0Sstevel@tonic-gate 2669*0Sstevel@tonic-gate /* 2670*0Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 2671*0Sstevel@tonic-gate */ 2672*0Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 2673*0Sstevel@tonic-gate cmn_err(CE_CONT, 2674*0Sstevel@tonic-gate "cs_card_insertion: socket %d has no " 2675*0Sstevel@tonic-gate "CIS window\n", 2676*0Sstevel@tonic-gate sp->socket_num); 2677*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 2678*0Sstevel@tonic-gate } 2679*0Sstevel@tonic-gate 2680*0Sstevel@tonic-gate /* 2681*0Sstevel@tonic-gate * Apply power to the socket, enable card detect and card ready 2682*0Sstevel@tonic-gate * events, then reset the socket. 2683*0Sstevel@tonic-gate */ 2684*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2685*0Sstevel@tonic-gate sp->event_mask = (CS_EVENT_CARD_REMOVAL | 2686*0Sstevel@tonic-gate CS_EVENT_CARD_READY); 2687*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2688*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2689*0Sstevel@tonic-gate set_socket.SCIntMask = (SBM_CD | SBM_RDYBSY); 2690*0Sstevel@tonic-gate set_socket.IREQRouting = 0; 2691*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 2692*0Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 2693*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 2694*0Sstevel@tonic-gate 2695*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VCC, 2696*0Sstevel@tonic-gate &set_socket.VccLevel); 2697*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP1, 2698*0Sstevel@tonic-gate &set_socket.Vpp1Level); 2699*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP2, 2700*0Sstevel@tonic-gate &set_socket.Vpp2Level); 2701*0Sstevel@tonic-gate 2702*0Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2703*0Sstevel@tonic-gate cmn_err(CE_CONT, 2704*0Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failure %d\n", 2705*0Sstevel@tonic-gate sp->socket_num, ret); 2706*0Sstevel@tonic-gate return (ret); 2707*0Sstevel@tonic-gate } 2708*0Sstevel@tonic-gate 2709*0Sstevel@tonic-gate /* 2710*0Sstevel@tonic-gate * Clear the ready and ready_timeout events since they are now 2711*0Sstevel@tonic-gate * bogus since we're about to reset the socket. 2712*0Sstevel@tonic-gate * XXX - should these be cleared right after the RESET?? 2713*0Sstevel@tonic-gate */ 2714*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2715*0Sstevel@tonic-gate 2716*0Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 2717*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2718*0Sstevel@tonic-gate 2719*0Sstevel@tonic-gate SocketServices(SS_ResetSocket, sp->socket_num, 2720*0Sstevel@tonic-gate RESET_MODE_CARD_ONLY); 2721*0Sstevel@tonic-gate 2722*0Sstevel@tonic-gate /* 2723*0Sstevel@tonic-gate * We are required by the PCMCIA spec to wait some number of 2724*0Sstevel@tonic-gate * milliseconds after reset before we access the card, so 2725*0Sstevel@tonic-gate * we set up a timer here that will wake us up and allow us 2726*0Sstevel@tonic-gate * to continue with our card initialization. 2727*0Sstevel@tonic-gate */ 2728*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2729*0Sstevel@tonic-gate sp->thread_state |= SOCKET_RESET_TIMER; 2730*0Sstevel@tonic-gate (void) timeout(cs_ready_timeout, sp, 2731*0Sstevel@tonic-gate drv_usectohz(cs_reset_timeout_time * 1000)); 2732*0Sstevel@tonic-gate cv_wait(&sp->reset_cv, &sp->lock); 2733*0Sstevel@tonic-gate sp->thread_state &= ~SOCKET_RESET_TIMER; 2734*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2735*0Sstevel@tonic-gate 2736*0Sstevel@tonic-gate #ifdef CS_DEBUG 2737*0Sstevel@tonic-gate if (cs_debug > 2) { 2738*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d out of RESET " 2739*0Sstevel@tonic-gate "for %d mS sp->events 0x%x\n", 2740*0Sstevel@tonic-gate sp->socket_num, cs_reset_timeout_time, (int)sp->events); 2741*0Sstevel@tonic-gate } 2742*0Sstevel@tonic-gate #endif 2743*0Sstevel@tonic-gate 2744*0Sstevel@tonic-gate /* 2745*0Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 2746*0Sstevel@tonic-gate * means that we likely got CD line bounce on the 2747*0Sstevel@tonic-gate * insertion, so terminate this processing. 2748*0Sstevel@tonic-gate */ 2749*0Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 2750*0Sstevel@tonic-gate #ifdef CS_DEBUG 2751*0Sstevel@tonic-gate if (cs_debug > 0) { 2752*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d " 2753*0Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 2754*0Sstevel@tonic-gate "terminating insertion " 2755*0Sstevel@tonic-gate "processing\n", 2756*0Sstevel@tonic-gate sp->socket_num); 2757*0Sstevel@tonic-gate } 2758*0Sstevel@tonic-gate #endif 2759*0Sstevel@tonic-gate return (CS_SUCCESS); 2760*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2761*0Sstevel@tonic-gate 2762*0Sstevel@tonic-gate /* 2763*0Sstevel@tonic-gate * If we got a card ready event after the reset, then don't 2764*0Sstevel@tonic-gate * bother setting up a card ready timer, since we'll blast 2765*0Sstevel@tonic-gate * right on through to the card ready processing. 2766*0Sstevel@tonic-gate * Get the current card status to see if it's ready; if it 2767*0Sstevel@tonic-gate * is, we probably won't get a card ready event. 2768*0Sstevel@tonic-gate */ 2769*0Sstevel@tonic-gate gs.socket = sp->socket_num; 2770*0Sstevel@tonic-gate gs.CardState = 0; 2771*0Sstevel@tonic-gate if ((ret = SocketServices(SS_GetStatus, &gs)) != SUCCESS) { 2772*0Sstevel@tonic-gate cmn_err(CE_CONT, 2773*0Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetStatus failure %d\n", 2774*0Sstevel@tonic-gate sp->socket_num, ret); 2775*0Sstevel@tonic-gate return (ret); 2776*0Sstevel@tonic-gate } 2777*0Sstevel@tonic-gate 2778*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2779*0Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_READY) || 2780*0Sstevel@tonic-gate (gs.CardState & SBM_RDYBSY)) { 2781*0Sstevel@tonic-gate event = CS_EVENT_CARD_READY; 2782*0Sstevel@tonic-gate #ifdef CS_DEBUG 2783*0Sstevel@tonic-gate if (cs_debug > 1) { 2784*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d card " 2785*0Sstevel@tonic-gate "READY\n", sp->socket_num); 2786*0Sstevel@tonic-gate } 2787*0Sstevel@tonic-gate #endif 2788*0Sstevel@tonic-gate 2789*0Sstevel@tonic-gate } else { 2790*0Sstevel@tonic-gate #ifdef CS_DEBUG 2791*0Sstevel@tonic-gate if (cs_debug > 1) { 2792*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d setting " 2793*0Sstevel@tonic-gate "READY timer\n", sp->socket_num); 2794*0Sstevel@tonic-gate } 2795*0Sstevel@tonic-gate #endif 2796*0Sstevel@tonic-gate 2797*0Sstevel@tonic-gate sp->rdybsy_tmo_id = timeout(cs_ready_timeout, sp, 2798*0Sstevel@tonic-gate READY_TIMEOUT_TIME); 2799*0Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_FOR_READY; 2800*0Sstevel@tonic-gate 2801*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 2802*0Sstevel@tonic-gate 2803*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2804*0Sstevel@tonic-gate 2805*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 2806*0Sstevel@tonic-gate 2807*0Sstevel@tonic-gate /* 2808*0Sstevel@tonic-gate * Handle card ready processing. This is only card ready processing 2809*0Sstevel@tonic-gate * for card ready events in conjunction with a card insertion. 2810*0Sstevel@tonic-gate */ 2811*0Sstevel@tonic-gate if (event == CS_EVENT_CARD_READY) { 2812*0Sstevel@tonic-gate get_socket_t get_socket; 2813*0Sstevel@tonic-gate set_socket_t set_socket; 2814*0Sstevel@tonic-gate 2815*0Sstevel@tonic-gate /* 2816*0Sstevel@tonic-gate * The only events that we want to see now are card removal 2817*0Sstevel@tonic-gate * events. 2818*0Sstevel@tonic-gate */ 2819*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2820*0Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_REMOVAL; 2821*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2822*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 2823*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 2824*0Sstevel@tonic-gate cmn_err(CE_CONT, 2825*0Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetSocket failed\n", 2826*0Sstevel@tonic-gate sp->socket_num); 2827*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2828*0Sstevel@tonic-gate } 2829*0Sstevel@tonic-gate 2830*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2831*0Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 2832*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 2833*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 2834*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 2835*0Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 2836*0Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 2837*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 2838*0Sstevel@tonic-gate /* XXX (is ~0 correct here?) to reset latched values */ 2839*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; 2840*0Sstevel@tonic-gate 2841*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 2842*0Sstevel@tonic-gate cmn_err(CE_CONT, 2843*0Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failed\n", 2844*0Sstevel@tonic-gate sp->socket_num); 2845*0Sstevel@tonic-gate 2846*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 2847*0Sstevel@tonic-gate } 2848*0Sstevel@tonic-gate 2849*0Sstevel@tonic-gate /* 2850*0Sstevel@tonic-gate * Grab the cis_lock mutex to protect the CIS-to-be and 2851*0Sstevel@tonic-gate * the CIS window, then fire off the CIS parser to 2852*0Sstevel@tonic-gate * create a local copy of the card's CIS. 2853*0Sstevel@tonic-gate */ 2854*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2855*0Sstevel@tonic-gate 2856*0Sstevel@tonic-gate if ((ret = cs_create_cis(sp)) != CS_SUCCESS) { 2857*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2858*0Sstevel@tonic-gate return (ret); 2859*0Sstevel@tonic-gate } 2860*0Sstevel@tonic-gate 2861*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2862*0Sstevel@tonic-gate 2863*0Sstevel@tonic-gate /* 2864*0Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 2865*0Sstevel@tonic-gate * means that we likely got CD line bounce on the 2866*0Sstevel@tonic-gate * insertion, so destroy the CIS and terminate this 2867*0Sstevel@tonic-gate * processing. We'll get called back to handle the 2868*0Sstevel@tonic-gate * insertion again later. 2869*0Sstevel@tonic-gate */ 2870*0Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 2871*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2872*0Sstevel@tonic-gate (void) cs_destroy_cis(sp); 2873*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2874*0Sstevel@tonic-gate } else { 2875*0Sstevel@tonic-gate /* 2876*0Sstevel@tonic-gate * Schedule the call to the Socket Services work thread. 2877*0Sstevel@tonic-gate */ 2878*0Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 2879*0Sstevel@tonic-gate sp->ss_thread_state |= SOCKET_THREAD_CSCISInit; 2880*0Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 2881*0Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 2882*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2883*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 2884*0Sstevel@tonic-gate 2885*0Sstevel@tonic-gate /* 2886*0Sstevel@tonic-gate * Socket Services has parsed the CIS and has done any other 2887*0Sstevel@tonic-gate * work to get the client driver loaded and attached if 2888*0Sstevel@tonic-gate * necessary, so setup the per-client state. 2889*0Sstevel@tonic-gate */ 2890*0Sstevel@tonic-gate if (event == CS_EVENT_SS_UPDATED) { 2891*0Sstevel@tonic-gate client_t *client; 2892*0Sstevel@tonic-gate 2893*0Sstevel@tonic-gate /* 2894*0Sstevel@tonic-gate * Now that we and SS are done handling the card insertion 2895*0Sstevel@tonic-gate * semantics, go through each client on this socket and set 2896*0Sstevel@tonic-gate * the CS_EVENT_CARD_INSERTION event in each client's event 2897*0Sstevel@tonic-gate * field. We do this here instead of in cs_event so that 2898*0Sstevel@tonic-gate * when a client gets a CS_EVENT_CARD_INSERTION event, the 2899*0Sstevel@tonic-gate * card insertion and ready processing has already been done 2900*0Sstevel@tonic-gate * and SocketServices has had a chance to create a dip for 2901*0Sstevel@tonic-gate * the card in this socket. 2902*0Sstevel@tonic-gate */ 2903*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2904*0Sstevel@tonic-gate client = sp->client_list; 2905*0Sstevel@tonic-gate while (client) { 2906*0Sstevel@tonic-gate client->events |= (CS_EVENT_CARD_INSERTION & 2907*0Sstevel@tonic-gate (client->event_mask | client->global_mask)); 2908*0Sstevel@tonic-gate client = client->next; 2909*0Sstevel@tonic-gate } /* while (client) */ 2910*0Sstevel@tonic-gate 2911*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2912*0Sstevel@tonic-gate 2913*0Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 2914*0Sstevel@tonic-gate 2915*0Sstevel@tonic-gate return (CS_SUCCESS); 2916*0Sstevel@tonic-gate } 2917*0Sstevel@tonic-gate 2918*0Sstevel@tonic-gate /* 2919*0Sstevel@tonic-gate * cs_card_removal - handle card removal events 2920*0Sstevel@tonic-gate * 2921*0Sstevel@tonic-gate * Destroy the CIS. 2922*0Sstevel@tonic-gate * 2923*0Sstevel@tonic-gate * calling: sp - pointer to socket structure 2924*0Sstevel@tonic-gate * 2925*0Sstevel@tonic-gate */ 2926*0Sstevel@tonic-gate static int 2927*0Sstevel@tonic-gate cs_card_removal(cs_socket_t *sp) 2928*0Sstevel@tonic-gate { 2929*0Sstevel@tonic-gate set_socket_t set_socket; 2930*0Sstevel@tonic-gate int ret; 2931*0Sstevel@tonic-gate 2932*0Sstevel@tonic-gate #ifdef CS_DEBUG 2933*0Sstevel@tonic-gate if (cs_debug > 0) { 2934*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d\n", sp->socket_num); 2935*0Sstevel@tonic-gate } 2936*0Sstevel@tonic-gate #endif 2937*0Sstevel@tonic-gate 2938*0Sstevel@tonic-gate /* 2939*0Sstevel@tonic-gate * Remove any pending card ready timer 2940*0Sstevel@tonic-gate */ 2941*0Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 2942*0Sstevel@tonic-gate 2943*0Sstevel@tonic-gate /* 2944*0Sstevel@tonic-gate * Clear various flags so that everyone else knows that there's 2945*0Sstevel@tonic-gate * nothing on this socket anymore. Note that we clear the 2946*0Sstevel@tonic-gate * SOCKET_CARD_INSERTED and SOCKET_IS_IO flags in the 2947*0Sstevel@tonic-gate * ss_to_cs_events event mapping function. 2948*0Sstevel@tonic-gate */ 2949*0Sstevel@tonic-gate mutex_enter(&sp->lock); 2950*0Sstevel@tonic-gate sp->thread_state &= ~(SOCKET_WAIT_FOR_READY | SOCKET_RESET_TIMER); 2951*0Sstevel@tonic-gate 2952*0Sstevel@tonic-gate /* 2953*0Sstevel@tonic-gate * Turn off socket power and set the socket back to memory mode. 2954*0Sstevel@tonic-gate * Disable all socket events except for CARD_INSERTION events. 2955*0Sstevel@tonic-gate */ 2956*0Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 2957*0Sstevel@tonic-gate mutex_exit(&sp->lock); 2958*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2959*0Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 2960*0Sstevel@tonic-gate set_socket.IREQRouting = 0; 2961*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 2962*0Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 2963*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 2964*0Sstevel@tonic-gate 2965*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 2966*0Sstevel@tonic-gate &set_socket.VccLevel); 2967*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 2968*0Sstevel@tonic-gate &set_socket.Vpp1Level); 2969*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 2970*0Sstevel@tonic-gate &set_socket.Vpp2Level); 2971*0Sstevel@tonic-gate 2972*0Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2973*0Sstevel@tonic-gate cmn_err(CE_CONT, 2974*0Sstevel@tonic-gate "cs_card_removal: socket %d SS_SetSocket failure %d\n", 2975*0Sstevel@tonic-gate sp->socket_num, ret); 2976*0Sstevel@tonic-gate return (ret); 2977*0Sstevel@tonic-gate } 2978*0Sstevel@tonic-gate 2979*0Sstevel@tonic-gate #ifdef CS_DEBUG 2980*0Sstevel@tonic-gate if (cs_debug > 2) { 2981*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d " 2982*0Sstevel@tonic-gate "calling cs_destroy_cis\n", 2983*0Sstevel@tonic-gate sp->socket_num); 2984*0Sstevel@tonic-gate } 2985*0Sstevel@tonic-gate #endif 2986*0Sstevel@tonic-gate 2987*0Sstevel@tonic-gate /* 2988*0Sstevel@tonic-gate * Destroy the CIS and tell Socket Services that we're done 2989*0Sstevel@tonic-gate * handling the card removal event. 2990*0Sstevel@tonic-gate */ 2991*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2992*0Sstevel@tonic-gate (void) cs_destroy_cis(sp); 2993*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2994*0Sstevel@tonic-gate 2995*0Sstevel@tonic-gate #ifdef CS_DEBUG 2996*0Sstevel@tonic-gate if (cs_debug > 2) { 2997*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: calling CSCardRemoved\n"); 2998*0Sstevel@tonic-gate } 2999*0Sstevel@tonic-gate #endif 3000*0Sstevel@tonic-gate 3001*0Sstevel@tonic-gate SocketServices(CSCardRemoved, sp->socket_num); 3002*0Sstevel@tonic-gate 3003*0Sstevel@tonic-gate return (CS_SUCCESS); 3004*0Sstevel@tonic-gate } 3005*0Sstevel@tonic-gate 3006*0Sstevel@tonic-gate /* 3007*0Sstevel@tonic-gate * ss_to_cs_events - convert Socket Services events to Card Services event 3008*0Sstevel@tonic-gate * masks; this function will not read the PRR if the 3009*0Sstevel@tonic-gate * socket is in IO mode; this happens in cs_event_thread 3010*0Sstevel@tonic-gate * 3011*0Sstevel@tonic-gate * This function returns a bit mask of events. 3012*0Sstevel@tonic-gate * 3013*0Sstevel@tonic-gate * Note that we do some simple hysterious on card insertion and card removal 3014*0Sstevel@tonic-gate * events to prevent spurious insertion and removal events from being 3015*0Sstevel@tonic-gate * propogated down the chain. 3016*0Sstevel@tonic-gate */ 3017*0Sstevel@tonic-gate static event_t 3018*0Sstevel@tonic-gate ss_to_cs_events(cs_socket_t *sp, event_t event) 3019*0Sstevel@tonic-gate { 3020*0Sstevel@tonic-gate event_t revent = 0; 3021*0Sstevel@tonic-gate 3022*0Sstevel@tonic-gate switch (event) { 3023*0Sstevel@tonic-gate case PCE_CARD_STATUS_CHANGE: 3024*0Sstevel@tonic-gate revent |= CS_EVENT_STATUS_CHANGE; 3025*0Sstevel@tonic-gate break; 3026*0Sstevel@tonic-gate case PCE_CARD_REMOVAL: 3027*0Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) { 3028*0Sstevel@tonic-gate sp->flags &= ~(SOCKET_CARD_INSERTED | SOCKET_IS_IO); 3029*0Sstevel@tonic-gate revent |= CS_EVENT_CARD_REMOVAL; 3030*0Sstevel@tonic-gate /* 3031*0Sstevel@tonic-gate * If we're processing a removal event, it makes 3032*0Sstevel@tonic-gate * no sense to keep any insertion or ready events, 3033*0Sstevel@tonic-gate * so nuke them here. This will not clear any 3034*0Sstevel@tonic-gate * insertion events in the per-client event field. 3035*0Sstevel@tonic-gate */ 3036*0Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_INSERTION | 3037*0Sstevel@tonic-gate CS_EVENT_CARD_READY | 3038*0Sstevel@tonic-gate CS_EVENT_READY_TIMEOUT); 3039*0Sstevel@tonic-gate 3040*0Sstevel@tonic-gate /* 3041*0Sstevel@tonic-gate * We also don't need to wait for READY anymore since 3042*0Sstevel@tonic-gate * it probably won't show up, or if it does, it will 3043*0Sstevel@tonic-gate * be a bogus READY event as the card is sliding out 3044*0Sstevel@tonic-gate * of the socket. Since we never do a cv_wait on the 3045*0Sstevel@tonic-gate * card ready timer, it's OK for that timer to either 3046*0Sstevel@tonic-gate * never go off (via an UNTIMEOUT in cs_card_removal) 3047*0Sstevel@tonic-gate * or to go off but not do a cv_broadcast (since the 3048*0Sstevel@tonic-gate * SOCKET_WAIT_FOR_READY flag is cleared here). 3049*0Sstevel@tonic-gate */ 3050*0Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3051*0Sstevel@tonic-gate 3052*0Sstevel@tonic-gate } 3053*0Sstevel@tonic-gate break; 3054*0Sstevel@tonic-gate case PCE_CARD_INSERT: 3055*0Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3056*0Sstevel@tonic-gate sp->flags |= SOCKET_CARD_INSERTED; 3057*0Sstevel@tonic-gate revent |= CS_EVENT_CARD_INSERTION; 3058*0Sstevel@tonic-gate } 3059*0Sstevel@tonic-gate break; 3060*0Sstevel@tonic-gate case PCE_CARD_READY: 3061*0Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3062*0Sstevel@tonic-gate revent |= CS_EVENT_CARD_READY; 3063*0Sstevel@tonic-gate break; 3064*0Sstevel@tonic-gate case PCE_CARD_BATTERY_WARN: 3065*0Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3066*0Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_LOW; 3067*0Sstevel@tonic-gate break; 3068*0Sstevel@tonic-gate case PCE_CARD_BATTERY_DEAD: 3069*0Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3070*0Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_DEAD; 3071*0Sstevel@tonic-gate break; 3072*0Sstevel@tonic-gate case PCE_CARD_WRITE_PROTECT: 3073*0Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3074*0Sstevel@tonic-gate revent |= CS_EVENT_WRITE_PROTECT; 3075*0Sstevel@tonic-gate break; 3076*0Sstevel@tonic-gate case PCE_PM_RESUME: 3077*0Sstevel@tonic-gate revent |= CS_EVENT_PM_RESUME; 3078*0Sstevel@tonic-gate break; 3079*0Sstevel@tonic-gate case PCE_PM_SUSPEND: 3080*0Sstevel@tonic-gate revent |= CS_EVENT_PM_SUSPEND; 3081*0Sstevel@tonic-gate break; 3082*0Sstevel@tonic-gate default: 3083*0Sstevel@tonic-gate cmn_err(CE_CONT, "ss_to_cs_events: unknown event 0x%x\n", 3084*0Sstevel@tonic-gate (int)event); 3085*0Sstevel@tonic-gate break; 3086*0Sstevel@tonic-gate } /* switch(event) */ 3087*0Sstevel@tonic-gate 3088*0Sstevel@tonic-gate return (revent); 3089*0Sstevel@tonic-gate } 3090*0Sstevel@tonic-gate 3091*0Sstevel@tonic-gate /* 3092*0Sstevel@tonic-gate * cs_ready_timeout - general purpose READY/BUSY and RESET timer 3093*0Sstevel@tonic-gate * 3094*0Sstevel@tonic-gate * Note that we really only expect one of the two events to be asserted when 3095*0Sstevel@tonic-gate * we are called. XXX - Perhaps this might be a problem later on?? 3096*0Sstevel@tonic-gate * 3097*0Sstevel@tonic-gate * There is also the problem of cv_broadcast dropping the interrupt 3098*0Sstevel@tonic-gate * priority, even though we have our high-priority mutex held. If 3099*0Sstevel@tonic-gate * we hold our high-priority mutex (sp->lock) over a cv_broadcast, and 3100*0Sstevel@tonic-gate * we get a high-priority interrupt during this time, the system will 3101*0Sstevel@tonic-gate * deadlock or panic. Thanks to Andy Banta for finding this out in 3102*0Sstevel@tonic-gate * the SPC/S (stc.c) driver. 3103*0Sstevel@tonic-gate * 3104*0Sstevel@tonic-gate * This callback routine can not grab the sp->client_lock mutex or deadlock 3105*0Sstevel@tonic-gate * will result. 3106*0Sstevel@tonic-gate */ 3107*0Sstevel@tonic-gate void 3108*0Sstevel@tonic-gate cs_ready_timeout(void *arg) 3109*0Sstevel@tonic-gate { 3110*0Sstevel@tonic-gate cs_socket_t *sp = arg; 3111*0Sstevel@tonic-gate kcondvar_t *cvp = NULL; 3112*0Sstevel@tonic-gate 3113*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3114*0Sstevel@tonic-gate 3115*0Sstevel@tonic-gate if (sp->thread_state & SOCKET_RESET_TIMER) { 3116*0Sstevel@tonic-gate #ifdef CS_DEBUG 3117*0Sstevel@tonic-gate if (cs_debug > 1) { 3118*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_RESET_TIMER socket %d\n", 3119*0Sstevel@tonic-gate sp->socket_num); 3120*0Sstevel@tonic-gate } 3121*0Sstevel@tonic-gate #endif 3122*0Sstevel@tonic-gate 3123*0Sstevel@tonic-gate cvp = &sp->reset_cv; 3124*0Sstevel@tonic-gate } 3125*0Sstevel@tonic-gate 3126*0Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3127*0Sstevel@tonic-gate sp->events |= CS_EVENT_READY_TIMEOUT; 3128*0Sstevel@tonic-gate cvp = &sp->thread_cv; 3129*0Sstevel@tonic-gate 3130*0Sstevel@tonic-gate #ifdef CS_DEBUG 3131*0Sstevel@tonic-gate if (cs_debug > 1) { 3132*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_WAIT_FOR_READY " 3133*0Sstevel@tonic-gate "socket %d\n", sp->socket_num); 3134*0Sstevel@tonic-gate } 3135*0Sstevel@tonic-gate #endif 3136*0Sstevel@tonic-gate 3137*0Sstevel@tonic-gate } 3138*0Sstevel@tonic-gate 3139*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3140*0Sstevel@tonic-gate 3141*0Sstevel@tonic-gate if (cvp) 3142*0Sstevel@tonic-gate cv_broadcast(cvp); 3143*0Sstevel@tonic-gate } 3144*0Sstevel@tonic-gate 3145*0Sstevel@tonic-gate /* 3146*0Sstevel@tonic-gate * cs_event_softintr_timeout - wrapper function to call cs_socket_event_softintr 3147*0Sstevel@tonic-gate */ 3148*0Sstevel@tonic-gate /* ARGSUSED */ 3149*0Sstevel@tonic-gate void 3150*0Sstevel@tonic-gate cs_event_softintr_timeout(void *arg) 3151*0Sstevel@tonic-gate { 3152*0Sstevel@tonic-gate 3153*0Sstevel@tonic-gate /* 3154*0Sstevel@tonic-gate * If we're trying to unload this module, then don't do 3155*0Sstevel@tonic-gate * anything but exit. 3156*0Sstevel@tonic-gate * We acquire the cs_globals.global_lock mutex here so that 3157*0Sstevel@tonic-gate * we can correctly synchronize with cs_deinit when it 3158*0Sstevel@tonic-gate * is telling us to shut down. XXX - is this bogus?? 3159*0Sstevel@tonic-gate */ 3160*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3161*0Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) { 3162*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3163*0Sstevel@tonic-gate (void) cs_socket_event_softintr(NULL); 3164*0Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 3165*0Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 3166*0Sstevel@tonic-gate } else { 3167*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3168*0Sstevel@tonic-gate } 3169*0Sstevel@tonic-gate } 3170*0Sstevel@tonic-gate 3171*0Sstevel@tonic-gate /* 3172*0Sstevel@tonic-gate * cs_socket_event_softintr - This function just does a cv_broadcast on behalf 3173*0Sstevel@tonic-gate * of the high-priority interrupt handler. 3174*0Sstevel@tonic-gate * 3175*0Sstevel@tonic-gate * Note: There is no calling argument. 3176*0Sstevel@tonic-gate */ 3177*0Sstevel@tonic-gate /*ARGSUSED*/ 3178*0Sstevel@tonic-gate uint32_t 3179*0Sstevel@tonic-gate cs_socket_event_softintr(caddr_t notused) 3180*0Sstevel@tonic-gate { 3181*0Sstevel@tonic-gate cs_socket_t *sp; 3182*0Sstevel@tonic-gate uint32_t sn; 3183*0Sstevel@tonic-gate int ret = DDI_INTR_UNCLAIMED; 3184*0Sstevel@tonic-gate 3185*0Sstevel@tonic-gate /* 3186*0Sstevel@tonic-gate * If the module is on it's way out, then don't bother 3187*0Sstevel@tonic-gate * to do anything else except return. 3188*0Sstevel@tonic-gate */ 3189*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3190*0Sstevel@tonic-gate if ((cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING) || 3191*0Sstevel@tonic-gate (cs_globals.init_state & GLOBAL_IN_SOFTINTR)) { 3192*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3193*0Sstevel@tonic-gate 3194*0Sstevel@tonic-gate /* 3195*0Sstevel@tonic-gate * Note that we return DDI_INTR_UNCLAIMED here 3196*0Sstevel@tonic-gate * since we don't want to be constantly 3197*0Sstevel@tonic-gate * called back. 3198*0Sstevel@tonic-gate */ 3199*0Sstevel@tonic-gate return (ret); 3200*0Sstevel@tonic-gate } else { 3201*0Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_IN_SOFTINTR; 3202*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3203*0Sstevel@tonic-gate } 3204*0Sstevel@tonic-gate 3205*0Sstevel@tonic-gate /* 3206*0Sstevel@tonic-gate * Go through each socket and dispatch the appropriate events. 3207*0Sstevel@tonic-gate * We have to funnel everything through this one routine because 3208*0Sstevel@tonic-gate * we can't do a cv_broadcast from a high level interrupt handler 3209*0Sstevel@tonic-gate * and we also can't have more than one soft interrupt handler 3210*0Sstevel@tonic-gate * on a single dip and using the same handler address. 3211*0Sstevel@tonic-gate */ 3212*0Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3213*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 3214*0Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_READY) { 3215*0Sstevel@tonic-gate /* 3216*0Sstevel@tonic-gate * If we're being asked to unload CS, then don't bother 3217*0Sstevel@tonic-gate * waking up the socket event thread handler. 3218*0Sstevel@tonic-gate */ 3219*0Sstevel@tonic-gate if (!(sp->flags & SOCKET_UNLOAD_MODULE) && 3220*0Sstevel@tonic-gate (sp->flags & SOCKET_NEEDS_THREAD)) { 3221*0Sstevel@tonic-gate ret = DDI_INTR_CLAIMED; 3222*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 3223*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3224*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 3225*0Sstevel@tonic-gate } /* if (SOCKET_NEEDS_THREAD) */ 3226*0Sstevel@tonic-gate } /* if (SOCKET_INIT_STATE_READY) */ 3227*0Sstevel@tonic-gate } /* cs_get_sp */ 3228*0Sstevel@tonic-gate } /* for (sn) */ 3229*0Sstevel@tonic-gate 3230*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3231*0Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_IN_SOFTINTR; 3232*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3233*0Sstevel@tonic-gate 3234*0Sstevel@tonic-gate return (ret); 3235*0Sstevel@tonic-gate } 3236*0Sstevel@tonic-gate 3237*0Sstevel@tonic-gate /* 3238*0Sstevel@tonic-gate * cs_event_thread - This is the per-socket event thread. 3239*0Sstevel@tonic-gate */ 3240*0Sstevel@tonic-gate static void 3241*0Sstevel@tonic-gate cs_event_thread(uint32_t sn) 3242*0Sstevel@tonic-gate { 3243*0Sstevel@tonic-gate cs_socket_t *sp; 3244*0Sstevel@tonic-gate client_t *client; 3245*0Sstevel@tonic-gate client_types_t *ct; 3246*0Sstevel@tonic-gate 3247*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 3248*0Sstevel@tonic-gate return; 3249*0Sstevel@tonic-gate 3250*0Sstevel@tonic-gate #ifdef CS_DEBUG 3251*0Sstevel@tonic-gate if (cs_debug > 1) { 3252*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d thread started\n", 3253*0Sstevel@tonic-gate sp->socket_num); 3254*0Sstevel@tonic-gate } 3255*0Sstevel@tonic-gate #endif 3256*0Sstevel@tonic-gate 3257*0Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_cs, &sp->client_lock, 3258*0Sstevel@tonic-gate callb_generic_cpr, "cs_event_thread"); 3259*0Sstevel@tonic-gate 3260*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 3261*0Sstevel@tonic-gate 3262*0Sstevel@tonic-gate for (;;) { 3263*0Sstevel@tonic-gate 3264*0Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_cs); 3265*0Sstevel@tonic-gate cv_wait(&sp->thread_cv, &sp->client_lock); 3266*0Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_cs, &sp->client_lock); 3267*0Sstevel@tonic-gate 3268*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3269*0Sstevel@tonic-gate sp->flags &= ~SOCKET_NEEDS_THREAD; 3270*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3271*0Sstevel@tonic-gate 3272*0Sstevel@tonic-gate /* 3273*0Sstevel@tonic-gate * Check to see if there are any special thread operations that 3274*0Sstevel@tonic-gate * we are being asked to perform. 3275*0Sstevel@tonic-gate */ 3276*0Sstevel@tonic-gate if (sp->thread_state & SOCKET_THREAD_EXIT) { 3277*0Sstevel@tonic-gate #ifdef CS_DEBUG 3278*0Sstevel@tonic-gate if (cs_debug > 1) { 3279*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 3280*0Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 3281*0Sstevel@tonic-gate sp->socket_num); 3282*0Sstevel@tonic-gate } 3283*0Sstevel@tonic-gate #endif 3284*0Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_cs); 3285*0Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); /* wakes up cs_deinit */ 3286*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 3287*0Sstevel@tonic-gate return; 3288*0Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 3289*0Sstevel@tonic-gate 3290*0Sstevel@tonic-gate #ifdef CS_DEBUG 3291*0Sstevel@tonic-gate if (cs_debug > 1) { 3292*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d sp->events 0x%x\n", 3293*0Sstevel@tonic-gate sp->socket_num, 3294*0Sstevel@tonic-gate (int)sp->events); 3295*0Sstevel@tonic-gate } 3296*0Sstevel@tonic-gate #endif 3297*0Sstevel@tonic-gate 3298*0Sstevel@tonic-gate /* 3299*0Sstevel@tonic-gate * Handle CS_EVENT_CARD_INSERTION events 3300*0Sstevel@tonic-gate */ 3301*0Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_INSERTION) { 3302*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3303*0Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_INSERTION; 3304*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3305*0Sstevel@tonic-gate 3306*0Sstevel@tonic-gate /* 3307*0Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 3308*0Sstevel@tonic-gate * means that we likely got CD line bounce on the 3309*0Sstevel@tonic-gate * insertion, so terminate this processing. 3310*0Sstevel@tonic-gate */ 3311*0Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_REMOVAL) == 0) { 3312*0Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_INSERTION); 3313*0Sstevel@tonic-gate } 3314*0Sstevel@tonic-gate #ifdef CS_DEBUG 3315*0Sstevel@tonic-gate else if (cs_debug > 0) { 3316*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 3317*0Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 3318*0Sstevel@tonic-gate "terminating " 3319*0Sstevel@tonic-gate "CS_EVENT_CARD_INSERTION " 3320*0Sstevel@tonic-gate "processing\n", sp->socket_num); 3321*0Sstevel@tonic-gate } 3322*0Sstevel@tonic-gate #endif 3323*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 3324*0Sstevel@tonic-gate 3325*0Sstevel@tonic-gate /* 3326*0Sstevel@tonic-gate * Handle CS_EVENT_CARD_READY and CS_EVENT_READY_TIMEOUT events 3327*0Sstevel@tonic-gate */ 3328*0Sstevel@tonic-gate if (sp->events & (CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT)) { 3329*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3330*0Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 3331*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3332*0Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3333*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3334*0Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3335*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3336*0Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_READY); 3337*0Sstevel@tonic-gate } /* if (SOCKET_WAIT_FOR_READY) */ 3338*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 3339*0Sstevel@tonic-gate 3340*0Sstevel@tonic-gate /* 3341*0Sstevel@tonic-gate * Handle CS_EVENT_SS_UPDATED events 3342*0Sstevel@tonic-gate */ 3343*0Sstevel@tonic-gate if (sp->events & CS_EVENT_SS_UPDATED) { 3344*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3345*0Sstevel@tonic-gate sp->events &= ~CS_EVENT_SS_UPDATED; 3346*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3347*0Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_SS_UPDATED); 3348*0Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 3349*0Sstevel@tonic-gate 3350*0Sstevel@tonic-gate /* 3351*0Sstevel@tonic-gate * Handle CS_EVENT_STATUS_CHANGE events 3352*0Sstevel@tonic-gate */ 3353*0Sstevel@tonic-gate if (sp->events & CS_EVENT_STATUS_CHANGE) { 3354*0Sstevel@tonic-gate event_t revent; 3355*0Sstevel@tonic-gate 3356*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 3357*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3358*0Sstevel@tonic-gate sp->events &= ~CS_EVENT_STATUS_CHANGE; 3359*0Sstevel@tonic-gate 3360*0Sstevel@tonic-gate /* 3361*0Sstevel@tonic-gate * Go through each client and add any events that we saw to 3362*0Sstevel@tonic-gate * the client's event list if the client has that event 3363*0Sstevel@tonic-gate * enabled in their event mask. 3364*0Sstevel@tonic-gate * Remove any events that may be pending for this client if 3365*0Sstevel@tonic-gate * the client's event mask says that the client doesn't 3366*0Sstevel@tonic-gate * want to see those events anymore. This handles the 3367*0Sstevel@tonic-gate * case where the client had an event enabled in it's 3368*0Sstevel@tonic-gate * event mask when the event came in but between that 3369*0Sstevel@tonic-gate * time and the time we're called here the client 3370*0Sstevel@tonic-gate * disabled that event. 3371*0Sstevel@tonic-gate */ 3372*0Sstevel@tonic-gate client = sp->client_list; 3373*0Sstevel@tonic-gate 3374*0Sstevel@tonic-gate while (client) { 3375*0Sstevel@tonic-gate /* 3376*0Sstevel@tonic-gate * Read the PRR (if it exists) and check for any events. 3377*0Sstevel@tonic-gate * The PRR will only be read if the socket is in IO 3378*0Sstevel@tonic-gate * mode, if there is a card in the socket, and if there 3379*0Sstevel@tonic-gate * is a PRR. 3380*0Sstevel@tonic-gate * We don't have to clear revent before we call the 3381*0Sstevel@tonic-gate * cs_read_event_status function since it will 3382*0Sstevel@tonic-gate * clear it before adding any current events. 3383*0Sstevel@tonic-gate */ 3384*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3385*0Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 3386*0Sstevel@tonic-gate &revent, NULL, 0); 3387*0Sstevel@tonic-gate 3388*0Sstevel@tonic-gate client->events = ((client->events | revent) & 3389*0Sstevel@tonic-gate (client->event_mask | 3390*0Sstevel@tonic-gate client->global_mask)); 3391*0Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 3392*0Sstevel@tonic-gate client = client->next; 3393*0Sstevel@tonic-gate } /* while (client) */ 3394*0Sstevel@tonic-gate 3395*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3396*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 3397*0Sstevel@tonic-gate } /* if (CS_EVENT_STATUS_CHANGE) */ 3398*0Sstevel@tonic-gate 3399*0Sstevel@tonic-gate /* 3400*0Sstevel@tonic-gate * We want to maintain the required event dispatching order as 3401*0Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 3402*0Sstevel@tonic-gate * clients on this socket to make sure that they are 3403*0Sstevel@tonic-gate * notified in the correct order. 3404*0Sstevel@tonic-gate */ 3405*0Sstevel@tonic-gate ct = &client_types[0]; 3406*0Sstevel@tonic-gate while (ct) { 3407*0Sstevel@tonic-gate /* 3408*0Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 3409*0Sstevel@tonic-gate * through each client to set up the client events as well 3410*0Sstevel@tonic-gate * as call the client's event handler directly if we have 3411*0Sstevel@tonic-gate * a high priority event that we need to tell the client 3412*0Sstevel@tonic-gate * about. 3413*0Sstevel@tonic-gate */ 3414*0Sstevel@tonic-gate client = sp->client_list; 3415*0Sstevel@tonic-gate 3416*0Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 3417*0Sstevel@tonic-gate client_t *clp = NULL; 3418*0Sstevel@tonic-gate 3419*0Sstevel@tonic-gate while (client) { 3420*0Sstevel@tonic-gate clp = client; 3421*0Sstevel@tonic-gate client = client->next; 3422*0Sstevel@tonic-gate } 3423*0Sstevel@tonic-gate client = clp; 3424*0Sstevel@tonic-gate } 3425*0Sstevel@tonic-gate 3426*0Sstevel@tonic-gate while (client) { 3427*0Sstevel@tonic-gate if (client->flags & ct->type) { 3428*0Sstevel@tonic-gate uint32_t bit = 0; 3429*0Sstevel@tonic-gate event_t event; 3430*0Sstevel@tonic-gate 3431*0Sstevel@tonic-gate while (client->events) { 3432*0Sstevel@tonic-gate 3433*0Sstevel@tonic-gate switch (event = CS_BIT_GET(client->events, bit)) { 3434*0Sstevel@tonic-gate /* 3435*0Sstevel@tonic-gate * Clients always receive registration complete 3436*0Sstevel@tonic-gate * events, even if there is no card of 3437*0Sstevel@tonic-gate * their type currently in the socket. 3438*0Sstevel@tonic-gate */ 3439*0Sstevel@tonic-gate case CS_EVENT_REGISTRATION_COMPLETE: 3440*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3441*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3442*0Sstevel@tonic-gate break; 3443*0Sstevel@tonic-gate /* 3444*0Sstevel@tonic-gate * The client only gets a card insertion event 3445*0Sstevel@tonic-gate * if there is currently a card in the 3446*0Sstevel@tonic-gate * socket that the client can control. 3447*0Sstevel@tonic-gate * The nexus determines this. We also 3448*0Sstevel@tonic-gate * prevent the client from receiving 3449*0Sstevel@tonic-gate * multiple CS_EVENT_CARD_INSERTION 3450*0Sstevel@tonic-gate * events without receiving intervening 3451*0Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL events. 3452*0Sstevel@tonic-gate */ 3453*0Sstevel@tonic-gate case CS_EVENT_CARD_INSERTION: 3454*0Sstevel@tonic-gate if (cs_card_for_client(client)) { 3455*0Sstevel@tonic-gate int send_insertion; 3456*0Sstevel@tonic-gate 3457*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3458*0Sstevel@tonic-gate send_insertion = client->flags; 3459*0Sstevel@tonic-gate client->flags |= 3460*0Sstevel@tonic-gate (CLIENT_CARD_INSERTED | 3461*0Sstevel@tonic-gate CLIENT_SENT_INSERTION); 3462*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3463*0Sstevel@tonic-gate if (!(send_insertion & 3464*0Sstevel@tonic-gate CLIENT_SENT_INSERTION)) { 3465*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 3466*0Sstevel@tonic-gate event, CS_EVENT_PRI_LOW); 3467*0Sstevel@tonic-gate } /* if (!CLIENT_SENT_INSERTION) */ 3468*0Sstevel@tonic-gate } 3469*0Sstevel@tonic-gate break; 3470*0Sstevel@tonic-gate /* 3471*0Sstevel@tonic-gate * The CS_EVENT_CARD_REMOVAL_LOWP is a low 3472*0Sstevel@tonic-gate * priority CS_EVENT_CARD_REMOVAL event. 3473*0Sstevel@tonic-gate */ 3474*0Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL_LOWP: 3475*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3476*0Sstevel@tonic-gate client->flags &= ~CLIENT_SENT_INSERTION; 3477*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3478*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 3479*0Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 3480*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3481*0Sstevel@tonic-gate break; 3482*0Sstevel@tonic-gate /* 3483*0Sstevel@tonic-gate * The hardware card removal events are handed 3484*0Sstevel@tonic-gate * to the client in cs_event at high 3485*0Sstevel@tonic-gate * priority interrupt time; this card 3486*0Sstevel@tonic-gate * removal event is a software-generated 3487*0Sstevel@tonic-gate * event. 3488*0Sstevel@tonic-gate */ 3489*0Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL: 3490*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3491*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3492*0Sstevel@tonic-gate client->flags &= 3493*0Sstevel@tonic-gate ~(CLIENT_CARD_INSERTED | 3494*0Sstevel@tonic-gate CLIENT_SENT_INSERTION); 3495*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3496*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3497*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3498*0Sstevel@tonic-gate } 3499*0Sstevel@tonic-gate break; 3500*0Sstevel@tonic-gate /* 3501*0Sstevel@tonic-gate * Write protect events require the info field 3502*0Sstevel@tonic-gate * of the client's event callback args to 3503*0Sstevel@tonic-gate * be zero if the card is not write 3504*0Sstevel@tonic-gate * protected and one if it is. 3505*0Sstevel@tonic-gate */ 3506*0Sstevel@tonic-gate case CS_EVENT_WRITE_PROTECT: 3507*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3508*0Sstevel@tonic-gate get_ss_status_t gs; 3509*0Sstevel@tonic-gate 3510*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 3511*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3512*0Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 3513*0Sstevel@tonic-gate NULL, 3514*0Sstevel@tonic-gate &gs, 0); 3515*0Sstevel@tonic-gate if (gs.CardState & SBM_WP) { 3516*0Sstevel@tonic-gate client->event_callback_args.info = 3517*0Sstevel@tonic-gate (void *) 3518*0Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPON; 3519*0Sstevel@tonic-gate } else { 3520*0Sstevel@tonic-gate client->event_callback_args.info = 3521*0Sstevel@tonic-gate (void *) 3522*0Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPOFF; 3523*0Sstevel@tonic-gate } 3524*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3525*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 3526*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3527*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3528*0Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 3529*0Sstevel@tonic-gate break; 3530*0Sstevel@tonic-gate case CS_EVENT_CLIENT_INFO: 3531*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3532*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3533*0Sstevel@tonic-gate break; 3534*0Sstevel@tonic-gate case 0: 3535*0Sstevel@tonic-gate break; 3536*0Sstevel@tonic-gate default: 3537*0Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3538*0Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3539*0Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3540*0Sstevel@tonic-gate } 3541*0Sstevel@tonic-gate break; 3542*0Sstevel@tonic-gate } /* switch */ 3543*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3544*0Sstevel@tonic-gate CS_BIT_CLEAR(client->events, bit); 3545*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3546*0Sstevel@tonic-gate bit++; 3547*0Sstevel@tonic-gate } /* while (client->events) */ 3548*0Sstevel@tonic-gate } /* if (ct->type) */ 3549*0Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 3550*0Sstevel@tonic-gate client = client->prev; 3551*0Sstevel@tonic-gate } else { 3552*0Sstevel@tonic-gate client = client->next; 3553*0Sstevel@tonic-gate } 3554*0Sstevel@tonic-gate } /* while (client) */ 3555*0Sstevel@tonic-gate 3556*0Sstevel@tonic-gate ct = ct->next; 3557*0Sstevel@tonic-gate } /* while (ct) */ 3558*0Sstevel@tonic-gate 3559*0Sstevel@tonic-gate /* 3560*0Sstevel@tonic-gate * Handle CS_EVENT_CARD_REMOVAL events 3561*0Sstevel@tonic-gate */ 3562*0Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 3563*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3564*0Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_REMOVAL; 3565*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3566*0Sstevel@tonic-gate (void) cs_card_removal(sp); 3567*0Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 3568*0Sstevel@tonic-gate 3569*0Sstevel@tonic-gate /* 3570*0Sstevel@tonic-gate * If someone is waiting for us to complete, signal them now. 3571*0Sstevel@tonic-gate */ 3572*0Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_SYNC) { 3573*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3574*0Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_SYNC; 3575*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3576*0Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); 3577*0Sstevel@tonic-gate } /* SOCKET_WAIT_SYNC */ 3578*0Sstevel@tonic-gate 3579*0Sstevel@tonic-gate } /* for (;;) */ 3580*0Sstevel@tonic-gate } 3581*0Sstevel@tonic-gate 3582*0Sstevel@tonic-gate /* 3583*0Sstevel@tonic-gate * cs_card_for_client - checks to see if a card that the client can control 3584*0Sstevel@tonic-gate * is currently inserted in the socket. Socket Services 3585*0Sstevel@tonic-gate * has to tell us if this is the case. 3586*0Sstevel@tonic-gate */ 3587*0Sstevel@tonic-gate static int 3588*0Sstevel@tonic-gate cs_card_for_client(client_t *client) 3589*0Sstevel@tonic-gate { 3590*0Sstevel@tonic-gate 3591*0Sstevel@tonic-gate /* 3592*0Sstevel@tonic-gate * If the client has set the CS_EVENT_ALL_CLIENTS it means that they 3593*0Sstevel@tonic-gate * want to get all events for all clients, irrespective of 3594*0Sstevel@tonic-gate * whether or not there is a card in the socket. Such clients 3595*0Sstevel@tonic-gate * have to be very careful if they touch the card hardware in 3596*0Sstevel@tonic-gate * any way to prevent causing problems for other clients on the 3597*0Sstevel@tonic-gate * same socket. This flag will typically only be set by the 3598*0Sstevel@tonic-gate * "super-client" or CSI types of clients that wish to get 3599*0Sstevel@tonic-gate * information on other clients or cards in the system. 3600*0Sstevel@tonic-gate * Note that the CS_EVENT_ALL_CLIENTS must be set in either the 3601*0Sstevel@tonic-gate * client's global event mask or client event mask. 3602*0Sstevel@tonic-gate * The client must also have registered as a "super-client" or as a 3603*0Sstevel@tonic-gate * CSI client for this socket. 3604*0Sstevel@tonic-gate */ 3605*0Sstevel@tonic-gate if ((client->flags & (CLIENT_SUPER_CLIENT | CLIENT_CSI_CLIENT)) && 3606*0Sstevel@tonic-gate ((client->global_mask | client->event_mask) & 3607*0Sstevel@tonic-gate CS_EVENT_ALL_CLIENTS)) 3608*0Sstevel@tonic-gate return (1); 3609*0Sstevel@tonic-gate 3610*0Sstevel@tonic-gate /* 3611*0Sstevel@tonic-gate * Look for the PCM_DEV_ACTIVE property on this client's dip; if 3612*0Sstevel@tonic-gate * it's found, it means that this client can control the card 3613*0Sstevel@tonic-gate * that is currently in the socket. This is a boolean 3614*0Sstevel@tonic-gate * property managed by Socket Services. 3615*0Sstevel@tonic-gate */ 3616*0Sstevel@tonic-gate if (ddi_getprop(DDI_DEV_T_ANY, client->dip, (DDI_PROP_CANSLEEP | 3617*0Sstevel@tonic-gate DDI_PROP_NOTPROM), 3618*0Sstevel@tonic-gate PCM_DEV_ACTIVE, NULL)) { 3619*0Sstevel@tonic-gate #ifdef CS_DEBUG 3620*0Sstevel@tonic-gate if (cs_debug > 1) { 3621*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_for_client: client handle 0x%x " 3622*0Sstevel@tonic-gate "driver [%s] says %s found\n", 3623*0Sstevel@tonic-gate (int)client->client_handle, 3624*0Sstevel@tonic-gate client->driver_name, 3625*0Sstevel@tonic-gate PCM_DEV_ACTIVE); 3626*0Sstevel@tonic-gate } 3627*0Sstevel@tonic-gate #endif 3628*0Sstevel@tonic-gate return (1); 3629*0Sstevel@tonic-gate } 3630*0Sstevel@tonic-gate 3631*0Sstevel@tonic-gate return (0); 3632*0Sstevel@tonic-gate } 3633*0Sstevel@tonic-gate 3634*0Sstevel@tonic-gate /* 3635*0Sstevel@tonic-gate * cs_ss_thread - This is the Socket Services work thread. We fire off 3636*0Sstevel@tonic-gate * any calls to Socket Services here that we want 3637*0Sstevel@tonic-gate * to run on a thread that is seperate from the 3638*0Sstevel@tonic-gate * per-socket event thread. 3639*0Sstevel@tonic-gate */ 3640*0Sstevel@tonic-gate static void 3641*0Sstevel@tonic-gate cs_ss_thread(uint32_t sn) 3642*0Sstevel@tonic-gate { 3643*0Sstevel@tonic-gate cs_socket_t *sp; 3644*0Sstevel@tonic-gate 3645*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 3646*0Sstevel@tonic-gate return; 3647*0Sstevel@tonic-gate 3648*0Sstevel@tonic-gate /* 3649*0Sstevel@tonic-gate * Tell CPR that we've started a new thread. 3650*0Sstevel@tonic-gate */ 3651*0Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_ss, &sp->ss_thread_lock, 3652*0Sstevel@tonic-gate callb_generic_cpr, "cs_ss_thread"); 3653*0Sstevel@tonic-gate 3654*0Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 3655*0Sstevel@tonic-gate 3656*0Sstevel@tonic-gate for (;;) { 3657*0Sstevel@tonic-gate 3658*0Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_ss); 3659*0Sstevel@tonic-gate cv_wait(&sp->ss_thread_cv, &sp->ss_thread_lock); 3660*0Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_ss, &sp->ss_thread_lock); 3661*0Sstevel@tonic-gate 3662*0Sstevel@tonic-gate /* 3663*0Sstevel@tonic-gate * Check to see if there are any special thread operations 3664*0Sstevel@tonic-gate * that we are being asked to perform. 3665*0Sstevel@tonic-gate */ 3666*0Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_EXIT) { 3667*0Sstevel@tonic-gate #ifdef CS_DEBUG 3668*0Sstevel@tonic-gate if (cs_debug > 1) { 3669*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3670*0Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 3671*0Sstevel@tonic-gate sp->socket_num); 3672*0Sstevel@tonic-gate } 3673*0Sstevel@tonic-gate #endif 3674*0Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_ss); 3675*0Sstevel@tonic-gate cv_broadcast(&sp->ss_caller_cv); /* wake up cs_deinit */ 3676*0Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 3677*0Sstevel@tonic-gate return; 3678*0Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 3679*0Sstevel@tonic-gate 3680*0Sstevel@tonic-gate #ifdef CS_DEBUG 3681*0Sstevel@tonic-gate if (cs_debug > 1) { 3682*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3683*0Sstevel@tonic-gate "ss_thread_state = 0x%x\n", 3684*0Sstevel@tonic-gate (int)sp->socket_num, 3685*0Sstevel@tonic-gate (int)sp->ss_thread_state); 3686*0Sstevel@tonic-gate } 3687*0Sstevel@tonic-gate #endif 3688*0Sstevel@tonic-gate 3689*0Sstevel@tonic-gate /* 3690*0Sstevel@tonic-gate * Call SocketServices(CSCISInit) to have SS parse the 3691*0Sstevel@tonic-gate * CIS and load/attach any client drivers necessary. 3692*0Sstevel@tonic-gate */ 3693*0Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_CSCISInit) { 3694*0Sstevel@tonic-gate 3695*0Sstevel@tonic-gate sp->ss_thread_state &= ~SOCKET_THREAD_CSCISInit; 3696*0Sstevel@tonic-gate 3697*0Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3698*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread %d " 3699*0Sstevel@tonic-gate "card NOT inserted\n", 3700*0Sstevel@tonic-gate sp->socket_num); 3701*0Sstevel@tonic-gate } 3702*0Sstevel@tonic-gate 3703*0Sstevel@tonic-gate #ifdef CS_DEBUG 3704*0Sstevel@tonic-gate if (cs_debug > 1) { 3705*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d calling " 3706*0Sstevel@tonic-gate "CSCISInit\n", sp->socket_num); 3707*0Sstevel@tonic-gate } 3708*0Sstevel@tonic-gate #endif 3709*0Sstevel@tonic-gate 3710*0Sstevel@tonic-gate /* 3711*0Sstevel@tonic-gate * Tell SS that we have a complete CIS and that it can now 3712*0Sstevel@tonic-gate * be parsed. 3713*0Sstevel@tonic-gate * Note that in some cases the client driver may block in 3714*0Sstevel@tonic-gate * their attach routine, causing this call to block until 3715*0Sstevel@tonic-gate * the client completes their attach. 3716*0Sstevel@tonic-gate */ 3717*0Sstevel@tonic-gate SocketServices(CSCISInit, sp->socket_num); 3718*0Sstevel@tonic-gate 3719*0Sstevel@tonic-gate /* 3720*0Sstevel@tonic-gate * Set the CS_EVENT_SS_UPDATED event for this socket so that the 3721*0Sstevel@tonic-gate * event thread can continue any card insertion processing 3722*0Sstevel@tonic-gate * that it has to do. 3723*0Sstevel@tonic-gate */ 3724*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3725*0Sstevel@tonic-gate sp->events |= CS_EVENT_SS_UPDATED; 3726*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3727*0Sstevel@tonic-gate 3728*0Sstevel@tonic-gate /* 3729*0Sstevel@tonic-gate * Wake up this socket's event thread so that clients can 3730*0Sstevel@tonic-gate * continue any card insertion or attach processing 3731*0Sstevel@tonic-gate * that they need to do. 3732*0Sstevel@tonic-gate */ 3733*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3734*0Sstevel@tonic-gate } /* if ST_CSCISInit */ 3735*0Sstevel@tonic-gate 3736*0Sstevel@tonic-gate } /* for (;;) */ 3737*0Sstevel@tonic-gate } 3738*0Sstevel@tonic-gate 3739*0Sstevel@tonic-gate /* 3740*0Sstevel@tonic-gate * cs_request_socket_mask - set the client's event mask as well as causes 3741*0Sstevel@tonic-gate * any events pending from RegisterClient to 3742*0Sstevel@tonic-gate * be scheduled to be sent to the client 3743*0Sstevel@tonic-gate */ 3744*0Sstevel@tonic-gate static int 3745*0Sstevel@tonic-gate cs_request_socket_mask(client_handle_t client_handle, 3746*0Sstevel@tonic-gate request_socket_mask_t *se) 3747*0Sstevel@tonic-gate { 3748*0Sstevel@tonic-gate cs_socket_t *sp; 3749*0Sstevel@tonic-gate client_t *client; 3750*0Sstevel@tonic-gate int error; 3751*0Sstevel@tonic-gate int client_lock_acquired; 3752*0Sstevel@tonic-gate 3753*0Sstevel@tonic-gate /* 3754*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3755*0Sstevel@tonic-gate * is, we don't do anything except for return success. 3756*0Sstevel@tonic-gate */ 3757*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3758*0Sstevel@tonic-gate return (CS_SUCCESS); 3759*0Sstevel@tonic-gate 3760*0Sstevel@tonic-gate /* 3761*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3762*0Sstevel@tonic-gate */ 3763*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3764*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 3765*0Sstevel@tonic-gate 3766*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3767*0Sstevel@tonic-gate 3768*0Sstevel@tonic-gate /* 3769*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 3770*0Sstevel@tonic-gate */ 3771*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3772*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3773*0Sstevel@tonic-gate return (error); 3774*0Sstevel@tonic-gate } 3775*0Sstevel@tonic-gate 3776*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3777*0Sstevel@tonic-gate 3778*0Sstevel@tonic-gate /* 3779*0Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 3780*0Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 3781*0Sstevel@tonic-gate */ 3782*0Sstevel@tonic-gate if (client->flags & REQ_SOCKET_MASK_DONE) { 3783*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3784*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3785*0Sstevel@tonic-gate return (CS_IN_USE); 3786*0Sstevel@tonic-gate } 3787*0Sstevel@tonic-gate 3788*0Sstevel@tonic-gate /* 3789*0Sstevel@tonic-gate * Set up the event mask information; we copy this directly from 3790*0Sstevel@tonic-gate * the client; since we are the only source of events, any 3791*0Sstevel@tonic-gate * bogus bits that the client puts in here won't matter 3792*0Sstevel@tonic-gate * because we'll never look at them. 3793*0Sstevel@tonic-gate */ 3794*0Sstevel@tonic-gate client->event_mask = se->EventMask; 3795*0Sstevel@tonic-gate 3796*0Sstevel@tonic-gate /* 3797*0Sstevel@tonic-gate * If RegisterClient left us some events to process, set these 3798*0Sstevel@tonic-gate * events up here. 3799*0Sstevel@tonic-gate */ 3800*0Sstevel@tonic-gate if (client->pending_events) { 3801*0Sstevel@tonic-gate client->events |= client->pending_events; 3802*0Sstevel@tonic-gate client->pending_events = 0; 3803*0Sstevel@tonic-gate #ifdef CS_DEBUG 3804*0Sstevel@tonic-gate if (cs_debug > 1) { 3805*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: client_handle = 0x%x " 3806*0Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 3807*0Sstevel@tonic-gate (int)client->client_handle, 3808*0Sstevel@tonic-gate client->driver_name, 3809*0Sstevel@tonic-gate (int)client->events); 3810*0Sstevel@tonic-gate } 3811*0Sstevel@tonic-gate #endif 3812*0Sstevel@tonic-gate } 3813*0Sstevel@tonic-gate 3814*0Sstevel@tonic-gate client->flags |= REQ_SOCKET_MASK_DONE; 3815*0Sstevel@tonic-gate 3816*0Sstevel@tonic-gate /* 3817*0Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 3818*0Sstevel@tonic-gate * to generate the appropriate events. 3819*0Sstevel@tonic-gate */ 3820*0Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3821*0Sstevel@tonic-gate 3822*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3823*0Sstevel@tonic-gate 3824*0Sstevel@tonic-gate /* 3825*0Sstevel@tonic-gate * Wakeup the event thread if there are any client events to process. 3826*0Sstevel@tonic-gate */ 3827*0Sstevel@tonic-gate if (client->events) { 3828*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3829*0Sstevel@tonic-gate #ifdef CS_DEBUG 3830*0Sstevel@tonic-gate if (cs_debug > 1) { 3831*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: did cv_broadcast for " 3832*0Sstevel@tonic-gate "client_handle = 0x%x " 3833*0Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 3834*0Sstevel@tonic-gate (int)client->client_handle, 3835*0Sstevel@tonic-gate client->driver_name, 3836*0Sstevel@tonic-gate (int)client->events); 3837*0Sstevel@tonic-gate } 3838*0Sstevel@tonic-gate #endif 3839*0Sstevel@tonic-gate 3840*0Sstevel@tonic-gate } 3841*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3842*0Sstevel@tonic-gate 3843*0Sstevel@tonic-gate return (CS_SUCCESS); 3844*0Sstevel@tonic-gate } 3845*0Sstevel@tonic-gate 3846*0Sstevel@tonic-gate /* 3847*0Sstevel@tonic-gate * cs_release_socket_mask - clear the client's event mask 3848*0Sstevel@tonic-gate * 3849*0Sstevel@tonic-gate * Once this function returns, the client is guaranteed 3850*0Sstevel@tonic-gate * not to get any more event callbacks. 3851*0Sstevel@tonic-gate */ 3852*0Sstevel@tonic-gate /*ARGSUSED*/ 3853*0Sstevel@tonic-gate static int 3854*0Sstevel@tonic-gate cs_release_socket_mask(client_handle_t client_handle, 3855*0Sstevel@tonic-gate release_socket_mask_t *rsm) 3856*0Sstevel@tonic-gate { 3857*0Sstevel@tonic-gate cs_socket_t *sp; 3858*0Sstevel@tonic-gate client_t *client; 3859*0Sstevel@tonic-gate int error; 3860*0Sstevel@tonic-gate int client_lock_acquired; 3861*0Sstevel@tonic-gate 3862*0Sstevel@tonic-gate /* 3863*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3864*0Sstevel@tonic-gate * is, we don't do anything except for return success. 3865*0Sstevel@tonic-gate */ 3866*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3867*0Sstevel@tonic-gate return (CS_SUCCESS); 3868*0Sstevel@tonic-gate 3869*0Sstevel@tonic-gate /* 3870*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3871*0Sstevel@tonic-gate */ 3872*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3873*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 3874*0Sstevel@tonic-gate 3875*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3876*0Sstevel@tonic-gate 3877*0Sstevel@tonic-gate /* 3878*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 3879*0Sstevel@tonic-gate */ 3880*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3881*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3882*0Sstevel@tonic-gate return (error); 3883*0Sstevel@tonic-gate } 3884*0Sstevel@tonic-gate 3885*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3886*0Sstevel@tonic-gate 3887*0Sstevel@tonic-gate /* 3888*0Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 3889*0Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 3890*0Sstevel@tonic-gate */ 3891*0Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3892*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3893*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3894*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 3895*0Sstevel@tonic-gate } 3896*0Sstevel@tonic-gate 3897*0Sstevel@tonic-gate /* 3898*0Sstevel@tonic-gate * Clear both the client event mask and the global event mask. 3899*0Sstevel@tonic-gate * We clear both since the semantics of this function are 3900*0Sstevel@tonic-gate * that once it returns, the client will not be called at 3901*0Sstevel@tonic-gate * it's event handler for any events until RequestSocketMask 3902*0Sstevel@tonic-gate * is called again. 3903*0Sstevel@tonic-gate */ 3904*0Sstevel@tonic-gate client->event_mask = 0; 3905*0Sstevel@tonic-gate client->global_mask = 0; 3906*0Sstevel@tonic-gate client->flags &= ~REQ_SOCKET_MASK_DONE; 3907*0Sstevel@tonic-gate 3908*0Sstevel@tonic-gate /* 3909*0Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 3910*0Sstevel@tonic-gate * to generate the appropriate events. 3911*0Sstevel@tonic-gate */ 3912*0Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3913*0Sstevel@tonic-gate 3914*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3915*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3916*0Sstevel@tonic-gate 3917*0Sstevel@tonic-gate return (CS_SUCCESS); 3918*0Sstevel@tonic-gate } 3919*0Sstevel@tonic-gate 3920*0Sstevel@tonic-gate /* 3921*0Sstevel@tonic-gate * cs_get_event_mask - return the event mask for this client 3922*0Sstevel@tonic-gate */ 3923*0Sstevel@tonic-gate static int 3924*0Sstevel@tonic-gate cs_get_event_mask(client_handle_t client_handle, sockevent_t *se) 3925*0Sstevel@tonic-gate { 3926*0Sstevel@tonic-gate cs_socket_t *sp; 3927*0Sstevel@tonic-gate client_t *client; 3928*0Sstevel@tonic-gate int error; 3929*0Sstevel@tonic-gate int client_lock_acquired; 3930*0Sstevel@tonic-gate 3931*0Sstevel@tonic-gate /* 3932*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3933*0Sstevel@tonic-gate * is, we don't do anything except for return success. 3934*0Sstevel@tonic-gate */ 3935*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3936*0Sstevel@tonic-gate return (CS_SUCCESS); 3937*0Sstevel@tonic-gate 3938*0Sstevel@tonic-gate /* 3939*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3940*0Sstevel@tonic-gate */ 3941*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3942*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 3943*0Sstevel@tonic-gate 3944*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3945*0Sstevel@tonic-gate 3946*0Sstevel@tonic-gate /* 3947*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 3948*0Sstevel@tonic-gate */ 3949*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3950*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3951*0Sstevel@tonic-gate return (error); 3952*0Sstevel@tonic-gate } 3953*0Sstevel@tonic-gate 3954*0Sstevel@tonic-gate mutex_enter(&sp->lock); 3955*0Sstevel@tonic-gate 3956*0Sstevel@tonic-gate #ifdef XXX 3957*0Sstevel@tonic-gate /* 3958*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 3959*0Sstevel@tonic-gate * for this client, then return an error. 3960*0Sstevel@tonic-gate * XXX - how can a client get their event masks if their card 3961*0Sstevel@tonic-gate * goes away? 3962*0Sstevel@tonic-gate */ 3963*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 3964*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3965*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3966*0Sstevel@tonic-gate return (CS_NO_CARD); 3967*0Sstevel@tonic-gate } 3968*0Sstevel@tonic-gate #endif 3969*0Sstevel@tonic-gate 3970*0Sstevel@tonic-gate /* 3971*0Sstevel@tonic-gate * We are only allowed to get the client event mask if a 3972*0Sstevel@tonic-gate * RequestSocketMask has been called previously. We 3973*0Sstevel@tonic-gate * are allowed to get the global event mask at any 3974*0Sstevel@tonic-gate * time. 3975*0Sstevel@tonic-gate * The global event mask is initially set by the client 3976*0Sstevel@tonic-gate * in the call to RegisterClient. The client event 3977*0Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 3978*0Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 3979*0Sstevel@tonic-gate * GetEventMask. 3980*0Sstevel@tonic-gate */ 3981*0Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 3982*0Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3983*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3984*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3985*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 3986*0Sstevel@tonic-gate } 3987*0Sstevel@tonic-gate se->EventMask = client->event_mask; 3988*0Sstevel@tonic-gate } else { 3989*0Sstevel@tonic-gate se->EventMask = client->global_mask; 3990*0Sstevel@tonic-gate } 3991*0Sstevel@tonic-gate 3992*0Sstevel@tonic-gate mutex_exit(&sp->lock); 3993*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3994*0Sstevel@tonic-gate 3995*0Sstevel@tonic-gate return (CS_SUCCESS); 3996*0Sstevel@tonic-gate } 3997*0Sstevel@tonic-gate 3998*0Sstevel@tonic-gate /* 3999*0Sstevel@tonic-gate * cs_set_event_mask - set the event mask for this client 4000*0Sstevel@tonic-gate */ 4001*0Sstevel@tonic-gate static int 4002*0Sstevel@tonic-gate cs_set_event_mask(client_handle_t client_handle, sockevent_t *se) 4003*0Sstevel@tonic-gate { 4004*0Sstevel@tonic-gate cs_socket_t *sp; 4005*0Sstevel@tonic-gate client_t *client; 4006*0Sstevel@tonic-gate int error; 4007*0Sstevel@tonic-gate int client_lock_acquired; 4008*0Sstevel@tonic-gate 4009*0Sstevel@tonic-gate /* 4010*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4011*0Sstevel@tonic-gate * is, we don't do anything except for return success. 4012*0Sstevel@tonic-gate */ 4013*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4014*0Sstevel@tonic-gate return (CS_SUCCESS); 4015*0Sstevel@tonic-gate 4016*0Sstevel@tonic-gate /* 4017*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4018*0Sstevel@tonic-gate */ 4019*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4020*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4021*0Sstevel@tonic-gate 4022*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4023*0Sstevel@tonic-gate 4024*0Sstevel@tonic-gate /* 4025*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 4026*0Sstevel@tonic-gate */ 4027*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4028*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4029*0Sstevel@tonic-gate return (error); 4030*0Sstevel@tonic-gate } 4031*0Sstevel@tonic-gate 4032*0Sstevel@tonic-gate mutex_enter(&sp->lock); 4033*0Sstevel@tonic-gate 4034*0Sstevel@tonic-gate #ifdef XXX 4035*0Sstevel@tonic-gate /* 4036*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4037*0Sstevel@tonic-gate * for this client, then return an error. 4038*0Sstevel@tonic-gate */ 4039*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4040*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4041*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4042*0Sstevel@tonic-gate return (CS_NO_CARD); 4043*0Sstevel@tonic-gate } 4044*0Sstevel@tonic-gate #endif 4045*0Sstevel@tonic-gate 4046*0Sstevel@tonic-gate /* 4047*0Sstevel@tonic-gate * We are only allowed to set the client event mask if a 4048*0Sstevel@tonic-gate * RequestSocketMask has been called previously. We 4049*0Sstevel@tonic-gate * are allowed to set the global event mask at any 4050*0Sstevel@tonic-gate * time. 4051*0Sstevel@tonic-gate * The global event mask is initially set by the client 4052*0Sstevel@tonic-gate * in the call to RegisterClient. The client event 4053*0Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 4054*0Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 4055*0Sstevel@tonic-gate * GetEventMask. 4056*0Sstevel@tonic-gate */ 4057*0Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 4058*0Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 4059*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4060*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4061*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4062*0Sstevel@tonic-gate } 4063*0Sstevel@tonic-gate client->event_mask = se->EventMask; 4064*0Sstevel@tonic-gate } else { 4065*0Sstevel@tonic-gate client->global_mask = se->EventMask; 4066*0Sstevel@tonic-gate } 4067*0Sstevel@tonic-gate 4068*0Sstevel@tonic-gate /* 4069*0Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 4070*0Sstevel@tonic-gate * to generate the appropriate events. 4071*0Sstevel@tonic-gate */ 4072*0Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 4073*0Sstevel@tonic-gate 4074*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4075*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4076*0Sstevel@tonic-gate 4077*0Sstevel@tonic-gate return (CS_SUCCESS); 4078*0Sstevel@tonic-gate } 4079*0Sstevel@tonic-gate 4080*0Sstevel@tonic-gate /* 4081*0Sstevel@tonic-gate * cs_read_event_status - handles PRR events and returns card status 4082*0Sstevel@tonic-gate * 4083*0Sstevel@tonic-gate * calling: *sp - socket struct point 4084*0Sstevel@tonic-gate * *client - client to check events on 4085*0Sstevel@tonic-gate * *revent - pointer to event mask to update; if NULL, will 4086*0Sstevel@tonic-gate * not be updated, if non-NULL, will be updated 4087*0Sstevel@tonic-gate * with CS-format events; it is NOT necessary 4088*0Sstevel@tonic-gate * to clear this value before calling this 4089*0Sstevel@tonic-gate * function 4090*0Sstevel@tonic-gate * *gs - pointer to a get_ss_status_t used for the SS GetStatus 4091*0Sstevel@tonic-gate * call; it is not necessary to initialize any 4092*0Sstevel@tonic-gate * members in this structure; set to NULL if 4093*0Sstevel@tonic-gate * not used 4094*0Sstevel@tonic-gate * flags - if CS_RES_IGNORE_NO_CARD is set, the check for a 4095*0Sstevel@tonic-gate * card present will not be done 4096*0Sstevel@tonic-gate * 4097*0Sstevel@tonic-gate * returns: CS_SUCCESS 4098*0Sstevel@tonic-gate * CS_NO_CARD - if no card is in the socket and the flags arg 4099*0Sstevel@tonic-gate * is not set to CS_RES_IGNORE_NO_CARD 4100*0Sstevel@tonic-gate * CS_BAD_SOCKET - if the SS_GetStatus function returned an 4101*0Sstevel@tonic-gate * error 4102*0Sstevel@tonic-gate * 4103*0Sstevel@tonic-gate * Note that if the client that configured this socket has told us that 4104*0Sstevel@tonic-gate * the READY pin in the PRR isn't valid and the socket is in IO 4105*0Sstevel@tonic-gate * mode, we always return that the card is READY. 4106*0Sstevel@tonic-gate * 4107*0Sstevel@tonic-gate * Note that if gs is not NULL, the current card state will be returned 4108*0Sstevel@tonic-gate * in the gs->CardState member; this will always reflect the 4109*0Sstevel@tonic-gate * current card state and the state will come from both the 4110*0Sstevel@tonic-gate * SS_GetStatus call and the PRR, whichever is appropriate for 4111*0Sstevel@tonic-gate * the mode that the socket is currently in. 4112*0Sstevel@tonic-gate */ 4113*0Sstevel@tonic-gate static int 4114*0Sstevel@tonic-gate cs_read_event_status(cs_socket_t *sp, client_t *client, event_t *revent, 4115*0Sstevel@tonic-gate get_ss_status_t *gs, int flags) 4116*0Sstevel@tonic-gate { 4117*0Sstevel@tonic-gate cfg_regs_t prrd = 0; 4118*0Sstevel@tonic-gate 4119*0Sstevel@tonic-gate /* 4120*0Sstevel@tonic-gate * SOCKET_IS_IO will only be set if a RequestConfiguration 4121*0Sstevel@tonic-gate * has been done by at least one client on this socket. 4122*0Sstevel@tonic-gate * If there isn't a card in the socket or the caller wants to ignore 4123*0Sstevel@tonic-gate * whether the card is in the socket or not, get the current 4124*0Sstevel@tonic-gate * card status. 4125*0Sstevel@tonic-gate */ 4126*0Sstevel@tonic-gate if ((sp->flags & SOCKET_CARD_INSERTED) || 4127*0Sstevel@tonic-gate (flags & CS_RES_IGNORE_NO_CARD)) { 4128*0Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 4129*0Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4130*0Sstevel@tonic-gate acc_handle_t cis_handle; 4131*0Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 4132*0Sstevel@tonic-gate 4133*0Sstevel@tonic-gate /* 4134*0Sstevel@tonic-gate * Get a handle to the CIS window 4135*0Sstevel@tonic-gate */ 4136*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 4137*0Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 4138*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: socket %d " 4139*0Sstevel@tonic-gate "can't init CIS window\n", 4140*0Sstevel@tonic-gate sp->socket_num); 4141*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 4142*0Sstevel@tonic-gate } /* cs_init_cis_window */ 4143*0Sstevel@tonic-gate 4144*0Sstevel@tonic-gate prrd = csx_Get8(cis_handle, client->config_regs.prr_p); 4145*0Sstevel@tonic-gate prrd &= client->pin; 4146*0Sstevel@tonic-gate 4147*0Sstevel@tonic-gate #ifdef CS_DEBUG 4148*0Sstevel@tonic-gate if (cs_debug > 1) { 4149*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: " 4150*0Sstevel@tonic-gate "prrd 0x%x client->pin 0x%x\n", 4151*0Sstevel@tonic-gate (int)prrd, 4152*0Sstevel@tonic-gate client->pin); 4153*0Sstevel@tonic-gate cmn_err(CE_CONT, "PRR(1) = [%s%s%s%s%s%s%s%s]\n", 4154*0Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 4155*0Sstevel@tonic-gate "PRR_WP_STATUS ":""), 4156*0Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 4157*0Sstevel@tonic-gate "PRR_READY_STATUS ":""), 4158*0Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 4159*0Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 4160*0Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 4161*0Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 4162*0Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 4163*0Sstevel@tonic-gate "PRR_WP_EVENT ":""), 4164*0Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 4165*0Sstevel@tonic-gate "PRR_READY_EVENT ":""), 4166*0Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 4167*0Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 4168*0Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 4169*0Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 4170*0Sstevel@tonic-gate } 4171*0Sstevel@tonic-gate #endif 4172*0Sstevel@tonic-gate 4173*0Sstevel@tonic-gate /* 4174*0Sstevel@tonic-gate * The caller wants the event changes sent back and 4175*0Sstevel@tonic-gate * the PRR event change bits cleared. 4176*0Sstevel@tonic-gate */ 4177*0Sstevel@tonic-gate if (revent) { 4178*0Sstevel@tonic-gate get_socket_t get_socket; 4179*0Sstevel@tonic-gate set_socket_t set_socket; 4180*0Sstevel@tonic-gate 4181*0Sstevel@tonic-gate /* 4182*0Sstevel@tonic-gate * Bug ID: 1193636 - Card Services sends bogus 4183*0Sstevel@tonic-gate * events on CS_EVENT_STATUS_CHANGE events 4184*0Sstevel@tonic-gate * Clear this before we OR-in any values. 4185*0Sstevel@tonic-gate */ 4186*0Sstevel@tonic-gate *revent = 0; 4187*0Sstevel@tonic-gate 4188*0Sstevel@tonic-gate PRR_EVENT(prrd, PRR_WP_EVENT, PRR_WP_STATUS, 4189*0Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT, *revent); 4190*0Sstevel@tonic-gate 4191*0Sstevel@tonic-gate PRR_EVENT(prrd, PRR_READY_EVENT, PRR_READY_STATUS, 4192*0Sstevel@tonic-gate CS_EVENT_CARD_READY, *revent); 4193*0Sstevel@tonic-gate 4194*0Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD2_EVENT, PRR_BVD2_STATUS, 4195*0Sstevel@tonic-gate CS_EVENT_BATTERY_LOW, *revent); 4196*0Sstevel@tonic-gate 4197*0Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD1_EVENT, PRR_BVD1_STATUS, 4198*0Sstevel@tonic-gate CS_EVENT_BATTERY_DEAD, *revent); 4199*0Sstevel@tonic-gate 4200*0Sstevel@tonic-gate 4201*0Sstevel@tonic-gate #ifdef CS_DEBUG 4202*0Sstevel@tonic-gate if (cs_debug > 1) { 4203*0Sstevel@tonic-gate 4204*0Sstevel@tonic-gate cmn_err(CE_CONT, "PRR() = [%s%s%s%s%s%s%s%s]\n", 4205*0Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 4206*0Sstevel@tonic-gate "PRR_WP_STATUS ":""), 4207*0Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 4208*0Sstevel@tonic-gate "PRR_READY_STATUS ":""), 4209*0Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 4210*0Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 4211*0Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 4212*0Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 4213*0Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 4214*0Sstevel@tonic-gate "PRR_WP_EVENT ":""), 4215*0Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 4216*0Sstevel@tonic-gate "PRR_READY_EVENT ":""), 4217*0Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 4218*0Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 4219*0Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 4220*0Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 4221*0Sstevel@tonic-gate } 4222*0Sstevel@tonic-gate #endif 4223*0Sstevel@tonic-gate 4224*0Sstevel@tonic-gate if (prrd) 4225*0Sstevel@tonic-gate csx_Put8(cis_handle, client->config_regs.prr_p, 4226*0Sstevel@tonic-gate prrd); 4227*0Sstevel@tonic-gate 4228*0Sstevel@tonic-gate /* 4229*0Sstevel@tonic-gate * We now have to reenable the status change interrupts 4230*0Sstevel@tonic-gate * if there are any valid bits in the PRR. Since 4231*0Sstevel@tonic-gate * the BVD1 signal becomes the STATUS_CHANGE 4232*0Sstevel@tonic-gate * signal when the socket is in IO mode, we just 4233*0Sstevel@tonic-gate * have to set the SBM_BVD1 enable bit in the 4234*0Sstevel@tonic-gate * event mask. 4235*0Sstevel@tonic-gate */ 4236*0Sstevel@tonic-gate if (client->pin) { 4237*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4238*0Sstevel@tonic-gate SocketServices(SS_GetSocket, &get_socket); 4239*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4240*0Sstevel@tonic-gate set_socket.SCIntMask = 4241*0Sstevel@tonic-gate get_socket.SCIntMask | SBM_BVD1; 4242*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4243*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4244*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4245*0Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4246*0Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4247*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4248*0Sstevel@tonic-gate set_socket.State = get_socket.state; 4249*0Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket); 4250*0Sstevel@tonic-gate } /* if (client->pin) */ 4251*0Sstevel@tonic-gate } /* if (revent) */ 4252*0Sstevel@tonic-gate 4253*0Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4254*0Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 4255*0Sstevel@tonic-gate 4256*0Sstevel@tonic-gate /* 4257*0Sstevel@tonic-gate * The caller wants the current card state; we just read 4258*0Sstevel@tonic-gate * it and return a copy of it but do not clear any of 4259*0Sstevel@tonic-gate * the event changed bits (if we're reading the PRR). 4260*0Sstevel@tonic-gate */ 4261*0Sstevel@tonic-gate if (gs) { 4262*0Sstevel@tonic-gate gs->socket = sp->socket_num; 4263*0Sstevel@tonic-gate gs->CardState = 0; 4264*0Sstevel@tonic-gate if (SocketServices(SS_GetStatus, gs) != SUCCESS) 4265*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4266*0Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 4267*0Sstevel@tonic-gate /* 4268*0Sstevel@tonic-gate * If the socket is in IO mode, then clear the 4269*0Sstevel@tonic-gate * gs->CardState bits that are now in the PRR 4270*0Sstevel@tonic-gate */ 4271*0Sstevel@tonic-gate gs->CardState &= ~(SBM_WP | SBM_BVD1 | 4272*0Sstevel@tonic-gate SBM_BVD2 | SBM_RDYBSY); 4273*0Sstevel@tonic-gate 4274*0Sstevel@tonic-gate /* 4275*0Sstevel@tonic-gate * Convert PRR status to SS_GetStatus status 4276*0Sstevel@tonic-gate */ 4277*0Sstevel@tonic-gate if (prrd & PRR_WP_STATUS) 4278*0Sstevel@tonic-gate gs->CardState |= SBM_WP; 4279*0Sstevel@tonic-gate if (prrd & PRR_BVD2_STATUS) 4280*0Sstevel@tonic-gate gs->CardState |= SBM_BVD2; 4281*0Sstevel@tonic-gate if (prrd & PRR_BVD1_STATUS) 4282*0Sstevel@tonic-gate gs->CardState |= SBM_BVD1; 4283*0Sstevel@tonic-gate 4284*0Sstevel@tonic-gate /* 4285*0Sstevel@tonic-gate * If the client has indicated that there is no 4286*0Sstevel@tonic-gate * PRR or that the READY bit in the PRR isn't 4287*0Sstevel@tonic-gate * valid, then we simulate the READY bit by 4288*0Sstevel@tonic-gate * always returning READY. 4289*0Sstevel@tonic-gate */ 4290*0Sstevel@tonic-gate if (!(client->present & CONFIG_PINREPL_REG_PRESENT) || 4291*0Sstevel@tonic-gate ((client->present & CONFIG_PINREPL_REG_PRESENT) && 4292*0Sstevel@tonic-gate !((client->pin & 4293*0Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) == 4294*0Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT))) || 4295*0Sstevel@tonic-gate (prrd & PRR_READY_STATUS)) 4296*0Sstevel@tonic-gate gs->CardState |= SBM_RDYBSY; 4297*0Sstevel@tonic-gate 4298*0Sstevel@tonic-gate #ifdef CS_DEBUG 4299*0Sstevel@tonic-gate if (cs_debug > 1) { 4300*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: prrd 0x%x " 4301*0Sstevel@tonic-gate "client->pin 0x%x " 4302*0Sstevel@tonic-gate "gs->CardState 0x%x\n", 4303*0Sstevel@tonic-gate prrd, client->pin, gs->CardState); 4304*0Sstevel@tonic-gate } 4305*0Sstevel@tonic-gate #endif 4306*0Sstevel@tonic-gate 4307*0Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 4308*0Sstevel@tonic-gate } /* if (gs) */ 4309*0Sstevel@tonic-gate return (CS_SUCCESS); 4310*0Sstevel@tonic-gate } /* if (SOCKET_CARD_INSERTED) */ 4311*0Sstevel@tonic-gate 4312*0Sstevel@tonic-gate return (CS_NO_CARD); 4313*0Sstevel@tonic-gate } 4314*0Sstevel@tonic-gate 4315*0Sstevel@tonic-gate /* 4316*0Sstevel@tonic-gate * cs_get_status - gets live card status and latched card status changes 4317*0Sstevel@tonic-gate * supports the GetStatus CS call 4318*0Sstevel@tonic-gate * 4319*0Sstevel@tonic-gate * returns: CS_SUCCESS 4320*0Sstevel@tonic-gate * CS_BAD_HANDLE if the passed client handle is invalid 4321*0Sstevel@tonic-gate * 4322*0Sstevel@tonic-gate * Note: This function resets the latched status values maintained 4323*0Sstevel@tonic-gate * by Socket Services 4324*0Sstevel@tonic-gate */ 4325*0Sstevel@tonic-gate static int 4326*0Sstevel@tonic-gate cs_get_status(client_handle_t client_handle, get_status_t *gs) 4327*0Sstevel@tonic-gate { 4328*0Sstevel@tonic-gate cs_socket_t *sp; 4329*0Sstevel@tonic-gate client_t *client; 4330*0Sstevel@tonic-gate get_ss_status_t get_ss_status; 4331*0Sstevel@tonic-gate get_socket_t get_socket; 4332*0Sstevel@tonic-gate set_socket_t set_socket; 4333*0Sstevel@tonic-gate int error; 4334*0Sstevel@tonic-gate int client_lock_acquired; 4335*0Sstevel@tonic-gate 4336*0Sstevel@tonic-gate /* 4337*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4338*0Sstevel@tonic-gate * is, we don't do anything except for return success. 4339*0Sstevel@tonic-gate */ 4340*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4341*0Sstevel@tonic-gate return (CS_SUCCESS); 4342*0Sstevel@tonic-gate 4343*0Sstevel@tonic-gate /* 4344*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4345*0Sstevel@tonic-gate */ 4346*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4347*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4348*0Sstevel@tonic-gate 4349*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4350*0Sstevel@tonic-gate 4351*0Sstevel@tonic-gate /* 4352*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 4353*0Sstevel@tonic-gate */ 4354*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4355*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4356*0Sstevel@tonic-gate return (error); 4357*0Sstevel@tonic-gate } 4358*0Sstevel@tonic-gate 4359*0Sstevel@tonic-gate /* 4360*0Sstevel@tonic-gate * Get the current card status as well as the latched card 4361*0Sstevel@tonic-gate * state. Set the CS_RES_IGNORE_NO_CARD so that even 4362*0Sstevel@tonic-gate * if there is no card in the socket we'll still get 4363*0Sstevel@tonic-gate * a valid status. 4364*0Sstevel@tonic-gate * Note that it is not necessary to initialize any values 4365*0Sstevel@tonic-gate * in the get_ss_status structure. 4366*0Sstevel@tonic-gate */ 4367*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 4368*0Sstevel@tonic-gate if ((error = cs_read_event_status(sp, client, NULL, &get_ss_status, 4369*0Sstevel@tonic-gate CS_RES_IGNORE_NO_CARD)) != CS_SUCCESS) { 4370*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4371*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4372*0Sstevel@tonic-gate return (error); 4373*0Sstevel@tonic-gate } 4374*0Sstevel@tonic-gate 4375*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4376*0Sstevel@tonic-gate 4377*0Sstevel@tonic-gate gs->raw_CardState = cs_sbm2cse(get_ss_status.CardState); 4378*0Sstevel@tonic-gate 4379*0Sstevel@tonic-gate /* 4380*0Sstevel@tonic-gate * Assign the "live" card state to the "real" card state. If there's 4381*0Sstevel@tonic-gate * no card in the socket or the card in the socket is not 4382*0Sstevel@tonic-gate * for this client, then we lie and tell the caller that the 4383*0Sstevel@tonic-gate * card is not inserted. 4384*0Sstevel@tonic-gate */ 4385*0Sstevel@tonic-gate gs->CardState = gs->raw_CardState; 4386*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 4387*0Sstevel@tonic-gate gs->CardState &= ~CS_EVENT_CARD_INSERTION; 4388*0Sstevel@tonic-gate 4389*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4390*0Sstevel@tonic-gate 4391*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4392*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4393*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4394*0Sstevel@tonic-gate 4395*0Sstevel@tonic-gate gs->SocketState = cs_sbm2cse(get_socket.state); 4396*0Sstevel@tonic-gate 4397*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4398*0Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 4399*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4400*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4401*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4402*0Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4403*0Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4404*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4405*0Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 4406*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; 4407*0Sstevel@tonic-gate 4408*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4409*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4410*0Sstevel@tonic-gate 4411*0Sstevel@tonic-gate return (CS_SUCCESS); 4412*0Sstevel@tonic-gate } 4413*0Sstevel@tonic-gate 4414*0Sstevel@tonic-gate /* 4415*0Sstevel@tonic-gate * cs_cse2sbm - converts a CS event mask to an SS (SBM_XXX) event mask 4416*0Sstevel@tonic-gate */ 4417*0Sstevel@tonic-gate static event_t 4418*0Sstevel@tonic-gate cs_cse2sbm(event_t event_mask) 4419*0Sstevel@tonic-gate { 4420*0Sstevel@tonic-gate event_t sbm_event = 0; 4421*0Sstevel@tonic-gate 4422*0Sstevel@tonic-gate /* 4423*0Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 4424*0Sstevel@tonic-gate */ 4425*0Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 4426*0Sstevel@tonic-gate sbm_event |= SBM_WP; 4427*0Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 4428*0Sstevel@tonic-gate sbm_event |= SBM_BVD1; 4429*0Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 4430*0Sstevel@tonic-gate sbm_event |= SBM_BVD2; 4431*0Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 4432*0Sstevel@tonic-gate sbm_event |= SBM_RDYBSY; 4433*0Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_LOCK) 4434*0Sstevel@tonic-gate sbm_event |= SBM_LOCKED; 4435*0Sstevel@tonic-gate if (event_mask & CS_EVENT_EJECTION_REQUEST) 4436*0Sstevel@tonic-gate sbm_event |= SBM_EJECT; 4437*0Sstevel@tonic-gate if (event_mask & CS_EVENT_INSERTION_REQUEST) 4438*0Sstevel@tonic-gate sbm_event |= SBM_INSERT; 4439*0Sstevel@tonic-gate if (event_mask & (CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL)) 4440*0Sstevel@tonic-gate sbm_event |= SBM_CD; 4441*0Sstevel@tonic-gate 4442*0Sstevel@tonic-gate return (sbm_event); 4443*0Sstevel@tonic-gate } 4444*0Sstevel@tonic-gate 4445*0Sstevel@tonic-gate /* 4446*0Sstevel@tonic-gate * cs_sbm2cse - converts SBM_xxx state to CS event bits 4447*0Sstevel@tonic-gate * 4448*0Sstevel@tonic-gate * This function should never set any of the following bits: 4449*0Sstevel@tonic-gate * 4450*0Sstevel@tonic-gate * CS_EVENT_MTD_REQUEST 4451*0Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO 4452*0Sstevel@tonic-gate * CS_EVENT_TIMER_EXPIRED 4453*0Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL 4454*0Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL_LOWP 4455*0Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 4456*0Sstevel@tonic-gate * CS_EVENT_READY_TIMEOUT 4457*0Sstevel@tonic-gate * 4458*0Sstevel@tonic-gate * These bits are defined in the CS_STATUS_XXX series and are 4459*0Sstevel@tonic-gate * used by GetStatus. 4460*0Sstevel@tonic-gate */ 4461*0Sstevel@tonic-gate static uint32_t 4462*0Sstevel@tonic-gate cs_sbm2cse(uint32_t state) 4463*0Sstevel@tonic-gate { 4464*0Sstevel@tonic-gate uint32_t rstate = 0; 4465*0Sstevel@tonic-gate 4466*0Sstevel@tonic-gate /* 4467*0Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 4468*0Sstevel@tonic-gate */ 4469*0Sstevel@tonic-gate if (state & SBM_WP) 4470*0Sstevel@tonic-gate rstate |= CS_EVENT_WRITE_PROTECT; 4471*0Sstevel@tonic-gate if (state & SBM_BVD1) 4472*0Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_DEAD; 4473*0Sstevel@tonic-gate if (state & SBM_BVD2) 4474*0Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_LOW; 4475*0Sstevel@tonic-gate if (state & SBM_RDYBSY) 4476*0Sstevel@tonic-gate rstate |= CS_EVENT_CARD_READY; 4477*0Sstevel@tonic-gate if (state & SBM_LOCKED) 4478*0Sstevel@tonic-gate rstate |= CS_EVENT_CARD_LOCK; 4479*0Sstevel@tonic-gate if (state & SBM_EJECT) 4480*0Sstevel@tonic-gate rstate |= CS_EVENT_EJECTION_REQUEST; 4481*0Sstevel@tonic-gate if (state & SBM_INSERT) 4482*0Sstevel@tonic-gate rstate |= CS_EVENT_INSERTION_REQUEST; 4483*0Sstevel@tonic-gate if (state & SBM_CD) 4484*0Sstevel@tonic-gate rstate |= CS_EVENT_CARD_INSERTION; 4485*0Sstevel@tonic-gate 4486*0Sstevel@tonic-gate return (rstate); 4487*0Sstevel@tonic-gate } 4488*0Sstevel@tonic-gate 4489*0Sstevel@tonic-gate /* 4490*0Sstevel@tonic-gate * cs_merge_event_masks - merge the CS global socket event mask with the 4491*0Sstevel@tonic-gate * passed client's event masks 4492*0Sstevel@tonic-gate */ 4493*0Sstevel@tonic-gate static unsigned 4494*0Sstevel@tonic-gate cs_merge_event_masks(cs_socket_t *sp, client_t *client) 4495*0Sstevel@tonic-gate { 4496*0Sstevel@tonic-gate unsigned SCIntMask; 4497*0Sstevel@tonic-gate uint32_t event_mask; 4498*0Sstevel@tonic-gate 4499*0Sstevel@tonic-gate /* 4500*0Sstevel@tonic-gate * We always want to see card detect and status change events. 4501*0Sstevel@tonic-gate */ 4502*0Sstevel@tonic-gate SCIntMask = SBM_CD; 4503*0Sstevel@tonic-gate 4504*0Sstevel@tonic-gate event_mask = client->event_mask | client->global_mask | 4505*0Sstevel@tonic-gate sp->event_mask; 4506*0Sstevel@tonic-gate 4507*0Sstevel@tonic-gate if (!(sp->flags & SOCKET_IS_IO)) { 4508*0Sstevel@tonic-gate SCIntMask |= cs_cse2sbm(event_mask); 4509*0Sstevel@tonic-gate } else { 4510*0Sstevel@tonic-gate /* 4511*0Sstevel@tonic-gate * If the socket is in IO mode and there is a PRR present, 4512*0Sstevel@tonic-gate * then we may need to enable PCE_CARD_STATUS_CHANGE 4513*0Sstevel@tonic-gate * events. 4514*0Sstevel@tonic-gate */ 4515*0Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4516*0Sstevel@tonic-gate 4517*0Sstevel@tonic-gate SCIntMask |= (cs_cse2sbm(event_mask) & 4518*0Sstevel@tonic-gate ~(SBM_WP | SBM_BVD1 | SBM_BVD2 | SBM_RDYBSY)); 4519*0Sstevel@tonic-gate 4520*0Sstevel@tonic-gate if ((client->pin & (PRR_WP_STATUS | PRR_WP_EVENT)) == 4521*0Sstevel@tonic-gate (PRR_WP_STATUS | PRR_WP_EVENT)) 4522*0Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 4523*0Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4524*0Sstevel@tonic-gate 4525*0Sstevel@tonic-gate if ((client->pin & (PRR_READY_STATUS | PRR_READY_EVENT)) == 4526*0Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) 4527*0Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 4528*0Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4529*0Sstevel@tonic-gate 4530*0Sstevel@tonic-gate if ((client->pin & (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) == 4531*0Sstevel@tonic-gate (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) 4532*0Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 4533*0Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4534*0Sstevel@tonic-gate 4535*0Sstevel@tonic-gate if ((client->pin & (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) == 4536*0Sstevel@tonic-gate (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) 4537*0Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 4538*0Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4539*0Sstevel@tonic-gate 4540*0Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4541*0Sstevel@tonic-gate } /* if (!SOCKET_IS_IO) */ 4542*0Sstevel@tonic-gate 4543*0Sstevel@tonic-gate return (SCIntMask); 4544*0Sstevel@tonic-gate } 4545*0Sstevel@tonic-gate 4546*0Sstevel@tonic-gate /* 4547*0Sstevel@tonic-gate * cs_set_socket_event_mask - set the event mask for the socket 4548*0Sstevel@tonic-gate */ 4549*0Sstevel@tonic-gate static int 4550*0Sstevel@tonic-gate cs_set_socket_event_mask(cs_socket_t *sp, unsigned event_mask) 4551*0Sstevel@tonic-gate { 4552*0Sstevel@tonic-gate get_socket_t get_socket; 4553*0Sstevel@tonic-gate set_socket_t set_socket; 4554*0Sstevel@tonic-gate 4555*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4556*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4557*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4558*0Sstevel@tonic-gate 4559*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4560*0Sstevel@tonic-gate set_socket.SCIntMask = event_mask; 4561*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4562*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4563*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4564*0Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4565*0Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4566*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4567*0Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 4568*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; 4569*0Sstevel@tonic-gate 4570*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4571*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4572*0Sstevel@tonic-gate 4573*0Sstevel@tonic-gate return (CS_SUCCESS); 4574*0Sstevel@tonic-gate } 4575*0Sstevel@tonic-gate 4576*0Sstevel@tonic-gate /* 4577*0Sstevel@tonic-gate * ==== MTD handling section ==== 4578*0Sstevel@tonic-gate */ 4579*0Sstevel@tonic-gate static int 4580*0Sstevel@tonic-gate cs_deregister_mtd(client_handle_t client_handle) 4581*0Sstevel@tonic-gate { 4582*0Sstevel@tonic-gate 4583*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deregister_mtd: client_handle 0x%x\n", 4584*0Sstevel@tonic-gate (int)client_handle); 4585*0Sstevel@tonic-gate 4586*0Sstevel@tonic-gate return (CS_SUCCESS); 4587*0Sstevel@tonic-gate } 4588*0Sstevel@tonic-gate 4589*0Sstevel@tonic-gate /* 4590*0Sstevel@tonic-gate * ==== memory window handling section ==== 4591*0Sstevel@tonic-gate */ 4592*0Sstevel@tonic-gate 4593*0Sstevel@tonic-gate /* 4594*0Sstevel@tonic-gate * cs_request_window - searches through window list for the socket to find a 4595*0Sstevel@tonic-gate * memory window that matches the requested criteria; 4596*0Sstevel@tonic-gate * this is RequestWindow 4597*0Sstevel@tonic-gate * 4598*0Sstevel@tonic-gate * calling: cs_request_window(client_handle_t, *window_handle_t, win_req_t *) 4599*0Sstevel@tonic-gate * 4600*0Sstevel@tonic-gate * On sucessful return, the window_handle_t * pointed to will 4601*0Sstevel@tonic-gate * contain a valid window handle for this window. 4602*0Sstevel@tonic-gate * 4603*0Sstevel@tonic-gate * returns: CS_SUCCESS - if window found 4604*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 4605*0Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 4606*0Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 4607*0Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 4608*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 4609*0Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 4610*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attrbute 4611*0Sstevel@tonic-gate * flags are set 4612*0Sstevel@tonic-gate */ 4613*0Sstevel@tonic-gate static int 4614*0Sstevel@tonic-gate cs_request_window(client_handle_t client_handle, 4615*0Sstevel@tonic-gate window_handle_t *wh, 4616*0Sstevel@tonic-gate win_req_t *rw) 4617*0Sstevel@tonic-gate { 4618*0Sstevel@tonic-gate cs_socket_t *sp; 4619*0Sstevel@tonic-gate cs_window_t *cw; 4620*0Sstevel@tonic-gate client_t *client; 4621*0Sstevel@tonic-gate modify_win_t mw; 4622*0Sstevel@tonic-gate inquire_window_t iw; 4623*0Sstevel@tonic-gate uint32_t aw; 4624*0Sstevel@tonic-gate int error; 4625*0Sstevel@tonic-gate int client_lock_acquired; 4626*0Sstevel@tonic-gate uint32_t socket_num; 4627*0Sstevel@tonic-gate 4628*0Sstevel@tonic-gate /* 4629*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4630*0Sstevel@tonic-gate * is, we don't support SS using this call. 4631*0Sstevel@tonic-gate */ 4632*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4633*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 4634*0Sstevel@tonic-gate 4635*0Sstevel@tonic-gate /* 4636*0Sstevel@tonic-gate * Make sure that none of the unsupported flags are set. 4637*0Sstevel@tonic-gate */ 4638*0Sstevel@tonic-gate if (rw->Attributes & (/* Compatability */ 4639*0Sstevel@tonic-gate WIN_PAGED | 4640*0Sstevel@tonic-gate WIN_SHARED | 4641*0Sstevel@tonic-gate WIN_FIRST_SHARED | 4642*0Sstevel@tonic-gate WIN_BINDING_SPECIFIC | 4643*0Sstevel@tonic-gate /* CS internal */ 4644*0Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 4645*0Sstevel@tonic-gate /* IO window flags */ 4646*0Sstevel@tonic-gate WIN_MEMORY_TYPE_IO | 4647*0Sstevel@tonic-gate /* CardBus flags */ 4648*0Sstevel@tonic-gate WIN_DATA_WIDTH_32 | 4649*0Sstevel@tonic-gate WIN_PREFETCH_CACHE_MASK | 4650*0Sstevel@tonic-gate WIN_BAR_MASK)) 4651*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 4652*0Sstevel@tonic-gate 4653*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4654*0Sstevel@tonic-gate 4655*0Sstevel@tonic-gate /* 4656*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4657*0Sstevel@tonic-gate */ 4658*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4659*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4660*0Sstevel@tonic-gate 4661*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4662*0Sstevel@tonic-gate 4663*0Sstevel@tonic-gate /* 4664*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 4665*0Sstevel@tonic-gate */ 4666*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4667*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4668*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4669*0Sstevel@tonic-gate return (error); 4670*0Sstevel@tonic-gate } 4671*0Sstevel@tonic-gate 4672*0Sstevel@tonic-gate mutex_enter(&sp->lock); 4673*0Sstevel@tonic-gate 4674*0Sstevel@tonic-gate /* 4675*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4676*0Sstevel@tonic-gate * for this client, then return an error. 4677*0Sstevel@tonic-gate */ 4678*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4679*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4680*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4681*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4682*0Sstevel@tonic-gate return (CS_NO_CARD); 4683*0Sstevel@tonic-gate } 4684*0Sstevel@tonic-gate 4685*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4686*0Sstevel@tonic-gate 4687*0Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 4688*0Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 4689*0Sstevel@tonic-gate 4690*0Sstevel@tonic-gate 4691*0Sstevel@tonic-gate /* 4692*0Sstevel@tonic-gate * See if we can find a window that matches the caller's criteria. 4693*0Sstevel@tonic-gate * If we can't, then thre's not much more that we can do except 4694*0Sstevel@tonic-gate * for return an error. 4695*0Sstevel@tonic-gate */ 4696*0Sstevel@tonic-gate if ((error = cs_find_mem_window(sp->socket_num, rw, &aw)) != 4697*0Sstevel@tonic-gate CS_SUCCESS) { 4698*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4699*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4700*0Sstevel@tonic-gate return (error); 4701*0Sstevel@tonic-gate } 4702*0Sstevel@tonic-gate 4703*0Sstevel@tonic-gate /* 4704*0Sstevel@tonic-gate * We got a window, now synthesize a new window handle for this 4705*0Sstevel@tonic-gate * client and get a pointer to the global window structs 4706*0Sstevel@tonic-gate * and assign this window to this client. 4707*0Sstevel@tonic-gate * We don't have to check for errors from cs_create_window_handle 4708*0Sstevel@tonic-gate * since that function always returns a valid window handle 4709*0Sstevel@tonic-gate * if it is given a valid window number. 4710*0Sstevel@tonic-gate */ 4711*0Sstevel@tonic-gate *wh = cs_create_window_handle(aw); 4712*0Sstevel@tonic-gate if ((cw = cs_get_wp(aw)) == NULL) { 4713*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4714*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4715*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 4716*0Sstevel@tonic-gate } 4717*0Sstevel@tonic-gate 4718*0Sstevel@tonic-gate cw->window_handle = *wh; 4719*0Sstevel@tonic-gate cw->client_handle = client_handle; 4720*0Sstevel@tonic-gate cw->socket_num = sp->socket_num; 4721*0Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_MEM); 4722*0Sstevel@tonic-gate 4723*0Sstevel@tonic-gate mw.Attributes = ( 4724*0Sstevel@tonic-gate rw->Attributes | 4725*0Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 4726*0Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID); 4727*0Sstevel@tonic-gate mw.AccessSpeed = rw->win_params.AccessSpeed; 4728*0Sstevel@tonic-gate 4729*0Sstevel@tonic-gate if ((error = cs_modify_mem_window(*wh, &mw, rw, socket_num)) != 4730*0Sstevel@tonic-gate CS_SUCCESS) { 4731*0Sstevel@tonic-gate cw->state = 0; 4732*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4733*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4734*0Sstevel@tonic-gate return (error); 4735*0Sstevel@tonic-gate } 4736*0Sstevel@tonic-gate 4737*0Sstevel@tonic-gate /* 4738*0Sstevel@tonic-gate * Get any required card offset and pass it back to the client. 4739*0Sstevel@tonic-gate * This is not defined in the current PCMCIA spec. It is 4740*0Sstevel@tonic-gate * an aid to clients that want to use it to generate an 4741*0Sstevel@tonic-gate * optimum card offset. 4742*0Sstevel@tonic-gate */ 4743*0Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(*wh); 4744*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 4745*0Sstevel@tonic-gate 4746*0Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 4747*0Sstevel@tonic-gate rw->ReqOffset = rw->Size; 4748*0Sstevel@tonic-gate else 4749*0Sstevel@tonic-gate rw->ReqOffset = iw.mem_win_char.ReqOffset; 4750*0Sstevel@tonic-gate 4751*0Sstevel@tonic-gate /* 4752*0Sstevel@tonic-gate * Increment the client's memory window count; this is how we know 4753*0Sstevel@tonic-gate * when a client has any allocated memory windows. 4754*0Sstevel@tonic-gate */ 4755*0Sstevel@tonic-gate client->memwin_count++; 4756*0Sstevel@tonic-gate 4757*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4758*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4759*0Sstevel@tonic-gate 4760*0Sstevel@tonic-gate return (CS_SUCCESS); 4761*0Sstevel@tonic-gate } 4762*0Sstevel@tonic-gate 4763*0Sstevel@tonic-gate /* 4764*0Sstevel@tonic-gate * cs_release_window - deallocates the window associated with the passed 4765*0Sstevel@tonic-gate * window handle; this is ReleaseWindow 4766*0Sstevel@tonic-gate * 4767*0Sstevel@tonic-gate * returns: CS_SUCCESS if window handle is valid and window was 4768*0Sstevel@tonic-gate * sucessfully deallocated 4769*0Sstevel@tonic-gate * CS_BAD_HANDLE if window handle is invalid or if window 4770*0Sstevel@tonic-gate * handle is valid but window is not allocated 4771*0Sstevel@tonic-gate */ 4772*0Sstevel@tonic-gate static int 4773*0Sstevel@tonic-gate cs_release_window(window_handle_t wh) 4774*0Sstevel@tonic-gate { 4775*0Sstevel@tonic-gate cs_socket_t *sp; 4776*0Sstevel@tonic-gate cs_window_t *cw; 4777*0Sstevel@tonic-gate client_t *client; 4778*0Sstevel@tonic-gate int error; 4779*0Sstevel@tonic-gate int client_lock_acquired; 4780*0Sstevel@tonic-gate 4781*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4782*0Sstevel@tonic-gate 4783*0Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 4784*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4785*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 4786*0Sstevel@tonic-gate } 4787*0Sstevel@tonic-gate 4788*0Sstevel@tonic-gate /* 4789*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4790*0Sstevel@tonic-gate * is, we don't support SS using this call. 4791*0Sstevel@tonic-gate */ 4792*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(cw->client_handle)) { 4793*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4794*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 4795*0Sstevel@tonic-gate } 4796*0Sstevel@tonic-gate 4797*0Sstevel@tonic-gate /* 4798*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4799*0Sstevel@tonic-gate */ 4800*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4801*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4802*0Sstevel@tonic-gate 4803*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4804*0Sstevel@tonic-gate 4805*0Sstevel@tonic-gate /* 4806*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 4807*0Sstevel@tonic-gate */ 4808*0Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 4809*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4810*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4811*0Sstevel@tonic-gate return (error); 4812*0Sstevel@tonic-gate } 4813*0Sstevel@tonic-gate 4814*0Sstevel@tonic-gate /* 4815*0Sstevel@tonic-gate * Mark this window as not in use anymore. 4816*0Sstevel@tonic-gate */ 4817*0Sstevel@tonic-gate cw->state &= ~CW_WIN_IN_USE; 4818*0Sstevel@tonic-gate 4819*0Sstevel@tonic-gate /* 4820*0Sstevel@tonic-gate * Decrement the client's memory window count; this is how we know 4821*0Sstevel@tonic-gate * when a client has any allocated memory windows. 4822*0Sstevel@tonic-gate */ 4823*0Sstevel@tonic-gate if (!(--(client->memwin_count))) 4824*0Sstevel@tonic-gate client->flags &= ~CLIENT_WIN_ALLOCATED; 4825*0Sstevel@tonic-gate 4826*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4827*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4828*0Sstevel@tonic-gate 4829*0Sstevel@tonic-gate return (CS_SUCCESS); 4830*0Sstevel@tonic-gate } 4831*0Sstevel@tonic-gate 4832*0Sstevel@tonic-gate /* 4833*0Sstevel@tonic-gate * cs_modify_window - modifies a window's characteristics; this is ModifyWindow 4834*0Sstevel@tonic-gate */ 4835*0Sstevel@tonic-gate static int 4836*0Sstevel@tonic-gate cs_modify_window(window_handle_t wh, modify_win_t *mw) 4837*0Sstevel@tonic-gate { 4838*0Sstevel@tonic-gate cs_socket_t *sp; 4839*0Sstevel@tonic-gate cs_window_t *cw; 4840*0Sstevel@tonic-gate client_t *client; 4841*0Sstevel@tonic-gate int error; 4842*0Sstevel@tonic-gate int client_lock_acquired; 4843*0Sstevel@tonic-gate 4844*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4845*0Sstevel@tonic-gate 4846*0Sstevel@tonic-gate /* 4847*0Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 4848*0Sstevel@tonic-gate * to the window structure, and if we can, get the client that 4849*0Sstevel@tonic-gate * has allocated that window. 4850*0Sstevel@tonic-gate */ 4851*0Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 4852*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4853*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 4854*0Sstevel@tonic-gate } 4855*0Sstevel@tonic-gate 4856*0Sstevel@tonic-gate /* 4857*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4858*0Sstevel@tonic-gate */ 4859*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4860*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 4861*0Sstevel@tonic-gate 4862*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4863*0Sstevel@tonic-gate 4864*0Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 4865*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4866*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4867*0Sstevel@tonic-gate return (error); 4868*0Sstevel@tonic-gate } 4869*0Sstevel@tonic-gate 4870*0Sstevel@tonic-gate mutex_enter(&sp->lock); 4871*0Sstevel@tonic-gate 4872*0Sstevel@tonic-gate /* 4873*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4874*0Sstevel@tonic-gate * for this client, then return an error. 4875*0Sstevel@tonic-gate */ 4876*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4877*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4878*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4879*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4880*0Sstevel@tonic-gate return (CS_NO_CARD); 4881*0Sstevel@tonic-gate } 4882*0Sstevel@tonic-gate 4883*0Sstevel@tonic-gate mutex_exit(&sp->lock); 4884*0Sstevel@tonic-gate 4885*0Sstevel@tonic-gate mw->Attributes &= ( 4886*0Sstevel@tonic-gate WIN_MEMORY_TYPE_MASK | 4887*0Sstevel@tonic-gate WIN_ENABLE | 4888*0Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID | 4889*0Sstevel@tonic-gate WIN_ACC_ENDIAN_MASK | 4890*0Sstevel@tonic-gate WIN_ACC_ORDER_MASK); 4891*0Sstevel@tonic-gate 4892*0Sstevel@tonic-gate mw->Attributes &= ~WIN_DATA_WIDTH_VALID; 4893*0Sstevel@tonic-gate 4894*0Sstevel@tonic-gate if ((error = cs_modify_mem_window(wh, mw, NULL, NULL)) != CS_SUCCESS) { 4895*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4896*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4897*0Sstevel@tonic-gate return (error); 4898*0Sstevel@tonic-gate } 4899*0Sstevel@tonic-gate 4900*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4901*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4902*0Sstevel@tonic-gate 4903*0Sstevel@tonic-gate return (CS_SUCCESS); 4904*0Sstevel@tonic-gate } 4905*0Sstevel@tonic-gate 4906*0Sstevel@tonic-gate /* 4907*0Sstevel@tonic-gate * cs_modify_mem_window - modifies a window's characteristics; used internally 4908*0Sstevel@tonic-gate * by Card Services 4909*0Sstevel@tonic-gate * 4910*0Sstevel@tonic-gate * If *wr is NULL, it means that we're being called by ModifyWindow 4911*0Sstevel@tonic-gate * If *wr is non-NULL, it means that we are being called by RequestWindow 4912*0Sstevel@tonic-gate * and so we can't use SS_GetWindow. 4913*0Sstevel@tonic-gate */ 4914*0Sstevel@tonic-gate static int 4915*0Sstevel@tonic-gate cs_modify_mem_window(window_handle_t wh, modify_win_t *mw, 4916*0Sstevel@tonic-gate win_req_t *wr, int sn) 4917*0Sstevel@tonic-gate { 4918*0Sstevel@tonic-gate get_window_t gw; 4919*0Sstevel@tonic-gate set_window_t sw; 4920*0Sstevel@tonic-gate set_page_t set_page; 4921*0Sstevel@tonic-gate get_page_t get_page; 4922*0Sstevel@tonic-gate 4923*0Sstevel@tonic-gate /* 4924*0Sstevel@tonic-gate * If the win_req_t struct pointer is NULL, it means that 4925*0Sstevel@tonic-gate * we're being called by ModifyWindow, so get the 4926*0Sstevel@tonic-gate * current window characteristics. 4927*0Sstevel@tonic-gate */ 4928*0Sstevel@tonic-gate if (!wr) { 4929*0Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 4930*0Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 4931*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 4932*0Sstevel@tonic-gate sw.state = gw.state; 4933*0Sstevel@tonic-gate sw.socket = gw.socket; 4934*0Sstevel@tonic-gate sw.WindowSize = gw.size; 4935*0Sstevel@tonic-gate } else { 4936*0Sstevel@tonic-gate sw.state = 0; 4937*0Sstevel@tonic-gate sw.socket = sn; 4938*0Sstevel@tonic-gate sw.WindowSize = wr->Size; 4939*0Sstevel@tonic-gate } 4940*0Sstevel@tonic-gate 4941*0Sstevel@tonic-gate /* 4942*0Sstevel@tonic-gate * If we're being called by RequestWindow, we must always have 4943*0Sstevel@tonic-gate * WIN_ACCESS_SPEED_VALID set since get_window_t is not 4944*0Sstevel@tonic-gate * defined. 4945*0Sstevel@tonic-gate */ 4946*0Sstevel@tonic-gate if (mw->Attributes & WIN_ACCESS_SPEED_VALID) { 4947*0Sstevel@tonic-gate convert_speed_t convert_speed; 4948*0Sstevel@tonic-gate 4949*0Sstevel@tonic-gate convert_speed.Attributes = CONVERT_DEVSPEED_TO_NS; 4950*0Sstevel@tonic-gate convert_speed.devspeed = mw->AccessSpeed; 4951*0Sstevel@tonic-gate 4952*0Sstevel@tonic-gate if (cs_convert_speed(&convert_speed) != CS_SUCCESS) 4953*0Sstevel@tonic-gate return (CS_BAD_SPEED); 4954*0Sstevel@tonic-gate 4955*0Sstevel@tonic-gate sw.speed = convert_speed.nS; 4956*0Sstevel@tonic-gate } else { 4957*0Sstevel@tonic-gate sw.speed = gw.speed; 4958*0Sstevel@tonic-gate } 4959*0Sstevel@tonic-gate 4960*0Sstevel@tonic-gate if (!wr) { 4961*0Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 4962*0Sstevel@tonic-gate get_page.page = 0; 4963*0Sstevel@tonic-gate if (SocketServices(SS_GetPage, &get_page) != SUCCESS) 4964*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 4965*0Sstevel@tonic-gate set_page.state = get_page.state; 4966*0Sstevel@tonic-gate set_page.offset = get_page.offset; 4967*0Sstevel@tonic-gate } else { 4968*0Sstevel@tonic-gate set_page.state = 0; 4969*0Sstevel@tonic-gate set_page.offset = 0; 4970*0Sstevel@tonic-gate } 4971*0Sstevel@tonic-gate 4972*0Sstevel@tonic-gate if (mw->Attributes & WIN_ENABLE) { 4973*0Sstevel@tonic-gate sw.state |= WS_ENABLED; 4974*0Sstevel@tonic-gate set_page.state |= PS_ENABLED; 4975*0Sstevel@tonic-gate } else { 4976*0Sstevel@tonic-gate sw.state &= ~WS_ENABLED; 4977*0Sstevel@tonic-gate set_page.state &= ~PS_ENABLED; 4978*0Sstevel@tonic-gate } 4979*0Sstevel@tonic-gate 4980*0Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_VALID) { 4981*0Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_16) 4982*0Sstevel@tonic-gate sw.state |= WS_16BIT; 4983*0Sstevel@tonic-gate else 4984*0Sstevel@tonic-gate sw.state &= ~WS_16BIT; 4985*0Sstevel@tonic-gate } 4986*0Sstevel@tonic-gate 4987*0Sstevel@tonic-gate sw.window = GET_WINDOW_NUMBER(wh); 4988*0Sstevel@tonic-gate sw.base = 0; 4989*0Sstevel@tonic-gate 4990*0Sstevel@tonic-gate cs_set_acc_attributes(&sw, mw->Attributes); 4991*0Sstevel@tonic-gate 4992*0Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) 4993*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 4994*0Sstevel@tonic-gate 4995*0Sstevel@tonic-gate if (mw->Attributes & WIN_MEMORY_TYPE_AM) 4996*0Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 4997*0Sstevel@tonic-gate else 4998*0Sstevel@tonic-gate set_page.state &= ~PS_ATTRIBUTE; 4999*0Sstevel@tonic-gate 5000*0Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 5001*0Sstevel@tonic-gate set_page.page = 0; 5002*0Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) 5003*0Sstevel@tonic-gate return (CS_BAD_OFFSET); 5004*0Sstevel@tonic-gate 5005*0Sstevel@tonic-gate /* 5006*0Sstevel@tonic-gate * Return the current base address of this window 5007*0Sstevel@tonic-gate */ 5008*0Sstevel@tonic-gate if (wr) { 5009*0Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 5010*0Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 5011*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 5012*0Sstevel@tonic-gate 5013*0Sstevel@tonic-gate wr->Base.handle = (acc_handle_t)gw.handle; 5014*0Sstevel@tonic-gate } 5015*0Sstevel@tonic-gate 5016*0Sstevel@tonic-gate return (CS_SUCCESS); 5017*0Sstevel@tonic-gate } 5018*0Sstevel@tonic-gate 5019*0Sstevel@tonic-gate /* 5020*0Sstevel@tonic-gate * cs_map_mem_page - sets the card offset of the mapped window 5021*0Sstevel@tonic-gate */ 5022*0Sstevel@tonic-gate static int 5023*0Sstevel@tonic-gate cs_map_mem_page(window_handle_t wh, map_mem_page_t *mmp) 5024*0Sstevel@tonic-gate { 5025*0Sstevel@tonic-gate cs_socket_t *sp; 5026*0Sstevel@tonic-gate cs_window_t *cw; 5027*0Sstevel@tonic-gate client_t *client; 5028*0Sstevel@tonic-gate inquire_window_t iw; 5029*0Sstevel@tonic-gate get_window_t gw; 5030*0Sstevel@tonic-gate set_page_t set_page; 5031*0Sstevel@tonic-gate get_page_t get_page; 5032*0Sstevel@tonic-gate int error; 5033*0Sstevel@tonic-gate uint32_t size; 5034*0Sstevel@tonic-gate int client_lock_acquired; 5035*0Sstevel@tonic-gate 5036*0Sstevel@tonic-gate /* 5037*0Sstevel@tonic-gate * We don't support paged windows, so never allow a page number 5038*0Sstevel@tonic-gate * of other than 0 5039*0Sstevel@tonic-gate */ 5040*0Sstevel@tonic-gate if (mmp->Page) 5041*0Sstevel@tonic-gate return (CS_BAD_PAGE); 5042*0Sstevel@tonic-gate 5043*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5044*0Sstevel@tonic-gate 5045*0Sstevel@tonic-gate /* 5046*0Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 5047*0Sstevel@tonic-gate * to the window structure, and if we can, get the client that 5048*0Sstevel@tonic-gate * has allocated that window. 5049*0Sstevel@tonic-gate */ 5050*0Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 5051*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5052*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 5053*0Sstevel@tonic-gate } 5054*0Sstevel@tonic-gate 5055*0Sstevel@tonic-gate /* 5056*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5057*0Sstevel@tonic-gate */ 5058*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 5059*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 5060*0Sstevel@tonic-gate 5061*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5062*0Sstevel@tonic-gate 5063*0Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 5064*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5065*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5066*0Sstevel@tonic-gate return (error); 5067*0Sstevel@tonic-gate } 5068*0Sstevel@tonic-gate 5069*0Sstevel@tonic-gate mutex_enter(&sp->lock); 5070*0Sstevel@tonic-gate 5071*0Sstevel@tonic-gate /* 5072*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 5073*0Sstevel@tonic-gate * for this client, then return an error. 5074*0Sstevel@tonic-gate */ 5075*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 5076*0Sstevel@tonic-gate mutex_exit(&sp->lock); 5077*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5078*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5079*0Sstevel@tonic-gate return (CS_NO_CARD); 5080*0Sstevel@tonic-gate } 5081*0Sstevel@tonic-gate 5082*0Sstevel@tonic-gate mutex_exit(&sp->lock); 5083*0Sstevel@tonic-gate 5084*0Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 5085*0Sstevel@tonic-gate SocketServices(SS_GetWindow, &gw); 5086*0Sstevel@tonic-gate 5087*0Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(wh); 5088*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 5089*0Sstevel@tonic-gate 5090*0Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 5091*0Sstevel@tonic-gate size = gw.size; 5092*0Sstevel@tonic-gate else 5093*0Sstevel@tonic-gate size = iw.mem_win_char.ReqOffset; 5094*0Sstevel@tonic-gate 5095*0Sstevel@tonic-gate if (((mmp->CardOffset/size)*size) != mmp->CardOffset) { 5096*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5097*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5098*0Sstevel@tonic-gate return (CS_BAD_OFFSET); 5099*0Sstevel@tonic-gate } 5100*0Sstevel@tonic-gate 5101*0Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 5102*0Sstevel@tonic-gate get_page.page = 0; 5103*0Sstevel@tonic-gate SocketServices(SS_GetPage, &get_page); 5104*0Sstevel@tonic-gate 5105*0Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 5106*0Sstevel@tonic-gate set_page.page = 0; 5107*0Sstevel@tonic-gate set_page.state = get_page.state; 5108*0Sstevel@tonic-gate set_page.offset = mmp->CardOffset; 5109*0Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 5110*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5111*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5112*0Sstevel@tonic-gate return (CS_BAD_OFFSET); 5113*0Sstevel@tonic-gate } 5114*0Sstevel@tonic-gate 5115*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5116*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5117*0Sstevel@tonic-gate 5118*0Sstevel@tonic-gate return (CS_SUCCESS); 5119*0Sstevel@tonic-gate } 5120*0Sstevel@tonic-gate 5121*0Sstevel@tonic-gate /* 5122*0Sstevel@tonic-gate * cs_find_window - finds the window associated with the passed window 5123*0Sstevel@tonic-gate * handle; if the window handle is invalid or no 5124*0Sstevel@tonic-gate * windows match the passed window handle, NULL 5125*0Sstevel@tonic-gate * is returned. Note that the window must be 5126*0Sstevel@tonic-gate * allocated for this function to return a valid 5127*0Sstevel@tonic-gate * window pointer. 5128*0Sstevel@tonic-gate * 5129*0Sstevel@tonic-gate * returns: cs_window_t * pointer to the found window 5130*0Sstevel@tonic-gate * NULL if window handle invalid or window not allocated 5131*0Sstevel@tonic-gate */ 5132*0Sstevel@tonic-gate cs_window_t * 5133*0Sstevel@tonic-gate cs_find_window(window_handle_t wh) 5134*0Sstevel@tonic-gate { 5135*0Sstevel@tonic-gate cs_window_t *cw; 5136*0Sstevel@tonic-gate 5137*0Sstevel@tonic-gate if ((GET_WINDOW_NUMBER(wh) > cs_globals.num_windows) || 5138*0Sstevel@tonic-gate (GET_WINDOW_MAGIC(wh) != WINDOW_HANDLE_MAGIC)) 5139*0Sstevel@tonic-gate return ((cs_window_t *)NULL); 5140*0Sstevel@tonic-gate 5141*0Sstevel@tonic-gate if ((cw = cs_get_wp(GET_WINDOW_NUMBER(wh))) == NULL) 5142*0Sstevel@tonic-gate return (NULL); 5143*0Sstevel@tonic-gate 5144*0Sstevel@tonic-gate if ((cw->state & CW_ALLOCATED) && (cw->state & CW_MEM)) 5145*0Sstevel@tonic-gate return (cw); 5146*0Sstevel@tonic-gate 5147*0Sstevel@tonic-gate return ((cs_window_t *)NULL); 5148*0Sstevel@tonic-gate } 5149*0Sstevel@tonic-gate 5150*0Sstevel@tonic-gate /* 5151*0Sstevel@tonic-gate * cs_create_window_handle - creates a unique window handle based on the 5152*0Sstevel@tonic-gate * passed window number. 5153*0Sstevel@tonic-gate */ 5154*0Sstevel@tonic-gate static window_handle_t 5155*0Sstevel@tonic-gate cs_create_window_handle(uint32_t aw) 5156*0Sstevel@tonic-gate { 5157*0Sstevel@tonic-gate return (WINDOW_HANDLE_MAGIC | (aw & WINDOW_HANDLE_MASK)); 5158*0Sstevel@tonic-gate } 5159*0Sstevel@tonic-gate 5160*0Sstevel@tonic-gate /* 5161*0Sstevel@tonic-gate * cs_find_mem_window - tries to find a memory window matching the caller's 5162*0Sstevel@tonic-gate * criteria 5163*0Sstevel@tonic-gate * 5164*0Sstevel@tonic-gate * We return the first window that matches the requested criteria. 5165*0Sstevel@tonic-gate * 5166*0Sstevel@tonic-gate * returns: CS_SUCCESS - if memory window found 5167*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5168*0Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 5169*0Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 5170*0Sstevel@tonic-gate */ 5171*0Sstevel@tonic-gate /* BEGIN CSTYLED */ 5172*0Sstevel@tonic-gate static int 5173*0Sstevel@tonic-gate cs_find_mem_window(uint32_t sn, win_req_t *rw, uint32_t *assigned_window) 5174*0Sstevel@tonic-gate { 5175*0Sstevel@tonic-gate uint32_t wn; 5176*0Sstevel@tonic-gate int error = CS_OUT_OF_RESOURCE; 5177*0Sstevel@tonic-gate uint32_t window_num = PCMCIA_MAX_WINDOWS; 5178*0Sstevel@tonic-gate uint32_t min_size = UINT_MAX; 5179*0Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 5180*0Sstevel@tonic-gate uint32_t MinSize, MaxSize, ReqGran, MemWndCaps, WndCaps; 5181*0Sstevel@tonic-gate uint32_t tws; 5182*0Sstevel@tonic-gate 5183*0Sstevel@tonic-gate iw = &inquire_window; 5184*0Sstevel@tonic-gate 5185*0Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 5186*0Sstevel@tonic-gate cs_window_t *cw; 5187*0Sstevel@tonic-gate 5188*0Sstevel@tonic-gate /* 5189*0Sstevel@tonic-gate * If we can't get a pointer to this window, we should contine 5190*0Sstevel@tonic-gate * with scanning the next window, since this window might have 5191*0Sstevel@tonic-gate * been dropped. 5192*0Sstevel@tonic-gate */ 5193*0Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 5194*0Sstevel@tonic-gate iw->window = wn; 5195*0Sstevel@tonic-gate 5196*0Sstevel@tonic-gate if (SocketServices(SS_InquireWindow, iw) != SUCCESS) 5197*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 5198*0Sstevel@tonic-gate 5199*0Sstevel@tonic-gate MinSize = iw->mem_win_char.MinSize; 5200*0Sstevel@tonic-gate MaxSize = iw->mem_win_char.MaxSize; 5201*0Sstevel@tonic-gate ReqGran = iw->mem_win_char.ReqGran; 5202*0Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 5203*0Sstevel@tonic-gate WndCaps = iw->WndCaps; 5204*0Sstevel@tonic-gate 5205*0Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5206*0Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_MEM(cw) && 5207*0Sstevel@tonic-gate WndCaps & (WC_COMMON|WC_ATTRIBUTE)) { 5208*0Sstevel@tonic-gate if ((error = cs_valid_window_speed(iw, rw->win_params.AccessSpeed)) == 5209*0Sstevel@tonic-gate CS_SUCCESS) { 5210*0Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 5211*0Sstevel@tonic-gate if (cs_memwin_space_and_map_ok(iw, rw)) { 5212*0Sstevel@tonic-gate error = CS_BAD_SIZE; 5213*0Sstevel@tonic-gate if (!rw->Size) { 5214*0Sstevel@tonic-gate min_size = min(min_size, MinSize); 5215*0Sstevel@tonic-gate window_num = wn; 5216*0Sstevel@tonic-gate goto found_window; 5217*0Sstevel@tonic-gate } else { 5218*0Sstevel@tonic-gate if (!(MemWndCaps & WC_SIZE)) { 5219*0Sstevel@tonic-gate if (rw->Size == MinSize) { 5220*0Sstevel@tonic-gate min_size = MinSize; 5221*0Sstevel@tonic-gate window_num = wn; 5222*0Sstevel@tonic-gate goto found_window; 5223*0Sstevel@tonic-gate } 5224*0Sstevel@tonic-gate } else { /* WC_SIZE */ 5225*0Sstevel@tonic-gate if (!ReqGran) { 5226*0Sstevel@tonic-gate error = CS_BAD_WINDOW; 5227*0Sstevel@tonic-gate } else { 5228*0Sstevel@tonic-gate if ((rw->Size >= MinSize) && 5229*0Sstevel@tonic-gate (rw->Size <= MaxSize)) { 5230*0Sstevel@tonic-gate if (MemWndCaps & WC_POW2) { 5231*0Sstevel@tonic-gate unsigned rg = ReqGran; 5232*0Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 5233*0Sstevel@tonic-gate rg = (rg<<1)) { 5234*0Sstevel@tonic-gate if (rw->Size == tws) { 5235*0Sstevel@tonic-gate min_size = tws; 5236*0Sstevel@tonic-gate window_num = wn; 5237*0Sstevel@tonic-gate goto found_window; 5238*0Sstevel@tonic-gate } 5239*0Sstevel@tonic-gate tws += rg; 5240*0Sstevel@tonic-gate } /* for (tws) */ 5241*0Sstevel@tonic-gate } else { 5242*0Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 5243*0Sstevel@tonic-gate tws += ReqGran) { 5244*0Sstevel@tonic-gate if (rw->Size == tws) { 5245*0Sstevel@tonic-gate min_size = tws; 5246*0Sstevel@tonic-gate window_num = wn; 5247*0Sstevel@tonic-gate goto found_window; 5248*0Sstevel@tonic-gate } 5249*0Sstevel@tonic-gate } /* for (tws) */ 5250*0Sstevel@tonic-gate } /* if (!WC_POW2) */ 5251*0Sstevel@tonic-gate } /* if (Size >= MinSize) */ 5252*0Sstevel@tonic-gate } /* if (!ReqGran) */ 5253*0Sstevel@tonic-gate } /* if (WC_SIZE) */ 5254*0Sstevel@tonic-gate } /* if (rw->Size) */ 5255*0Sstevel@tonic-gate } /* if (cs_space_and_map_ok) */ 5256*0Sstevel@tonic-gate } /* if (cs_valid_window_speed) */ 5257*0Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 5258*0Sstevel@tonic-gate } /* if (cs_get_wp) */ 5259*0Sstevel@tonic-gate } /* for (wn) */ 5260*0Sstevel@tonic-gate 5261*0Sstevel@tonic-gate /* 5262*0Sstevel@tonic-gate * If we got here and the window_num wasn't set by any window 5263*0Sstevel@tonic-gate * matches in the above code, it means that we didn't 5264*0Sstevel@tonic-gate * find a window matching the caller's criteria. 5265*0Sstevel@tonic-gate * If the error is CS_BAD_TYPE, it means that the last reason 5266*0Sstevel@tonic-gate * that we couldn't match a window was because the caller's 5267*0Sstevel@tonic-gate * requested speed was out of range of the last window that 5268*0Sstevel@tonic-gate * we checked. We convert this error code to CS_OUT_OF_RESOURCE 5269*0Sstevel@tonic-gate * to conform to the RequestWindow section of the PCMCIA 5270*0Sstevel@tonic-gate * Card Services spec. 5271*0Sstevel@tonic-gate */ 5272*0Sstevel@tonic-gate if (window_num == PCMCIA_MAX_WINDOWS) { 5273*0Sstevel@tonic-gate if (error == CS_BAD_TYPE) 5274*0Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 5275*0Sstevel@tonic-gate return (error); 5276*0Sstevel@tonic-gate } 5277*0Sstevel@tonic-gate 5278*0Sstevel@tonic-gate found_window: 5279*0Sstevel@tonic-gate rw->Size = min_size; 5280*0Sstevel@tonic-gate *assigned_window = window_num; 5281*0Sstevel@tonic-gate iw->window = window_num; 5282*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 5283*0Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 5284*0Sstevel@tonic-gate 5285*0Sstevel@tonic-gate if (MemWndCaps & WC_CALIGN) 5286*0Sstevel@tonic-gate rw->Attributes |= WIN_OFFSET_SIZE; 5287*0Sstevel@tonic-gate else 5288*0Sstevel@tonic-gate rw->Attributes &= ~WIN_OFFSET_SIZE; 5289*0Sstevel@tonic-gate return (CS_SUCCESS); 5290*0Sstevel@tonic-gate } 5291*0Sstevel@tonic-gate /* END CSTYLED */ 5292*0Sstevel@tonic-gate 5293*0Sstevel@tonic-gate /* 5294*0Sstevel@tonic-gate * cs_memwin_space_and_map_ok - checks to see if the passed window mapping 5295*0Sstevel@tonic-gate * capabilities and window speeds are in the 5296*0Sstevel@tonic-gate * range of the passed window. 5297*0Sstevel@tonic-gate * 5298*0Sstevel@tonic-gate * returns: 0 - if the capabilities are out of range 5299*0Sstevel@tonic-gate * 1 - if the capabilities are in range 5300*0Sstevel@tonic-gate */ 5301*0Sstevel@tonic-gate static int 5302*0Sstevel@tonic-gate cs_memwin_space_and_map_ok(inquire_window_t *iw, win_req_t *rw) 5303*0Sstevel@tonic-gate { 5304*0Sstevel@tonic-gate 5305*0Sstevel@tonic-gate #ifdef CS_DEBUG 5306*0Sstevel@tonic-gate if (cs_debug > 240) 5307*0Sstevel@tonic-gate printf("-> s&m_ok: Attributes 0x%x AccessSpeed 0x%x " 5308*0Sstevel@tonic-gate "WndCaps 0x%x MemWndCaps 0x%x\n", 5309*0Sstevel@tonic-gate (int)rw->Attributes, 5310*0Sstevel@tonic-gate (int)rw->win_params.AccessSpeed, 5311*0Sstevel@tonic-gate iw->WndCaps, 5312*0Sstevel@tonic-gate iw->mem_win_char.MemWndCaps); 5313*0Sstevel@tonic-gate #endif 5314*0Sstevel@tonic-gate 5315*0Sstevel@tonic-gate if (rw->win_params.AccessSpeed & WIN_USE_WAIT) { 5316*0Sstevel@tonic-gate if (!(iw->WndCaps & WC_WAIT)) 5317*0Sstevel@tonic-gate return (0); 5318*0Sstevel@tonic-gate } 5319*0Sstevel@tonic-gate 5320*0Sstevel@tonic-gate if (rw->Attributes & WIN_DATA_WIDTH_16) { 5321*0Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_16BIT)) 5322*0Sstevel@tonic-gate return (0); 5323*0Sstevel@tonic-gate } else { 5324*0Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_8BIT)) 5325*0Sstevel@tonic-gate return (0); 5326*0Sstevel@tonic-gate } 5327*0Sstevel@tonic-gate 5328*0Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_AM) { 5329*0Sstevel@tonic-gate if (!(iw->WndCaps & WC_ATTRIBUTE)) 5330*0Sstevel@tonic-gate return (0); 5331*0Sstevel@tonic-gate } 5332*0Sstevel@tonic-gate 5333*0Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_CM) { 5334*0Sstevel@tonic-gate if (!(iw->WndCaps & WC_COMMON)) 5335*0Sstevel@tonic-gate return (0); 5336*0Sstevel@tonic-gate } 5337*0Sstevel@tonic-gate 5338*0Sstevel@tonic-gate return (1); 5339*0Sstevel@tonic-gate } 5340*0Sstevel@tonic-gate 5341*0Sstevel@tonic-gate /* 5342*0Sstevel@tonic-gate * cs_valid_window_speed - checks to see if requested window speed 5343*0Sstevel@tonic-gate * is in range of passed window 5344*0Sstevel@tonic-gate * 5345*0Sstevel@tonic-gate * The inquire_window_t struct gives us speeds in nS, and we 5346*0Sstevel@tonic-gate * get speeds in the AccessSpeed variable as a devspeed code. 5347*0Sstevel@tonic-gate * 5348*0Sstevel@tonic-gate * returns: CS_BAD_SPEED - if AccessSpeed is invalid devspeed code 5349*0Sstevel@tonic-gate * CS_BAD_TYPE - if AccessSpeed is not in range of valid 5350*0Sstevel@tonic-gate * speed for this window 5351*0Sstevel@tonic-gate * CS_SUCCESS - if window speed is in range 5352*0Sstevel@tonic-gate */ 5353*0Sstevel@tonic-gate static int 5354*0Sstevel@tonic-gate cs_valid_window_speed(inquire_window_t *iw, uint32_t AccessSpeed) 5355*0Sstevel@tonic-gate { 5356*0Sstevel@tonic-gate convert_speed_t convert_speed, *cs; 5357*0Sstevel@tonic-gate 5358*0Sstevel@tonic-gate cs = &convert_speed; 5359*0Sstevel@tonic-gate 5360*0Sstevel@tonic-gate cs->Attributes = CONVERT_DEVSPEED_TO_NS; 5361*0Sstevel@tonic-gate cs->devspeed = AccessSpeed; 5362*0Sstevel@tonic-gate 5363*0Sstevel@tonic-gate if (cs_convert_speed(cs) != CS_SUCCESS) 5364*0Sstevel@tonic-gate return (CS_BAD_SPEED); 5365*0Sstevel@tonic-gate 5366*0Sstevel@tonic-gate if ((cs->nS < iw->mem_win_char.Fastest) || 5367*0Sstevel@tonic-gate (cs->nS > iw->mem_win_char.Slowest)) 5368*0Sstevel@tonic-gate return (CS_BAD_TYPE); 5369*0Sstevel@tonic-gate 5370*0Sstevel@tonic-gate return (CS_SUCCESS); 5371*0Sstevel@tonic-gate } 5372*0Sstevel@tonic-gate 5373*0Sstevel@tonic-gate /* 5374*0Sstevel@tonic-gate * ==== IO window handling section ==== 5375*0Sstevel@tonic-gate */ 5376*0Sstevel@tonic-gate 5377*0Sstevel@tonic-gate /* 5378*0Sstevel@tonic-gate * cs_request_io - provides IO resources for clients; this is RequestIO 5379*0Sstevel@tonic-gate * 5380*0Sstevel@tonic-gate * calling: cs_request_io(client_handle_t, io_req_t *) 5381*0Sstevel@tonic-gate * 5382*0Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources available for client 5383*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5384*0Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 5385*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5386*0Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 5387*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 5388*0Sstevel@tonic-gate * flags are set 5389*0Sstevel@tonic-gate * CS_BAD_BASE - if either or both base port addresses 5390*0Sstevel@tonic-gate * are invalid or out of range 5391*0Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 5392*0Sstevel@tonic-gate * already been done 5393*0Sstevel@tonic-gate * CS_IN_USE - IO ports already in use or function has 5394*0Sstevel@tonic-gate * already been called 5395*0Sstevel@tonic-gate * CS_BAD_WINDOW - if failure while trying to set window 5396*0Sstevel@tonic-gate * characteristics 5397*0Sstevel@tonic-gate */ 5398*0Sstevel@tonic-gate static int 5399*0Sstevel@tonic-gate cs_request_io(client_handle_t client_handle, io_req_t *ior) 5400*0Sstevel@tonic-gate { 5401*0Sstevel@tonic-gate cs_socket_t *sp; 5402*0Sstevel@tonic-gate client_t *client; 5403*0Sstevel@tonic-gate int error; 5404*0Sstevel@tonic-gate int client_lock_acquired; 5405*0Sstevel@tonic-gate uint32_t socket_num; 5406*0Sstevel@tonic-gate 5407*0Sstevel@tonic-gate /* 5408*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 5409*0Sstevel@tonic-gate * is, we don't support SS using this call. 5410*0Sstevel@tonic-gate */ 5411*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 5412*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 5413*0Sstevel@tonic-gate 5414*0Sstevel@tonic-gate /* 5415*0Sstevel@tonic-gate * If the client has only requested one IO range, then make sure 5416*0Sstevel@tonic-gate * that the Attributes2 filed is clear. 5417*0Sstevel@tonic-gate */ 5418*0Sstevel@tonic-gate if (!ior->NumPorts2) 5419*0Sstevel@tonic-gate ior->Attributes2 = 0; 5420*0Sstevel@tonic-gate 5421*0Sstevel@tonic-gate /* 5422*0Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 5423*0Sstevel@tonic-gate */ 5424*0Sstevel@tonic-gate if ((ior->Attributes1 | ior->Attributes2) & (IO_SHARED | 5425*0Sstevel@tonic-gate IO_FIRST_SHARED | 5426*0Sstevel@tonic-gate IO_FORCE_ALIAS_ACCESS | 5427*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5428*0Sstevel@tonic-gate IO_DISABLE_WINDOW)) 5429*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 5430*0Sstevel@tonic-gate 5431*0Sstevel@tonic-gate /* 5432*0Sstevel@tonic-gate * Make sure that we have a port count for the first region. 5433*0Sstevel@tonic-gate */ 5434*0Sstevel@tonic-gate if (!ior->NumPorts1) 5435*0Sstevel@tonic-gate return (CS_BAD_BASE); 5436*0Sstevel@tonic-gate 5437*0Sstevel@tonic-gate /* 5438*0Sstevel@tonic-gate * If we're being asked for multiple IO ranges, then both base port 5439*0Sstevel@tonic-gate * members must be non-zero. 5440*0Sstevel@tonic-gate */ 5441*0Sstevel@tonic-gate if ((ior->NumPorts2) && !(ior->BasePort1.base && ior->BasePort2.base)) 5442*0Sstevel@tonic-gate return (CS_BAD_BASE); 5443*0Sstevel@tonic-gate 5444*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5445*0Sstevel@tonic-gate 5446*0Sstevel@tonic-gate /* 5447*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5448*0Sstevel@tonic-gate */ 5449*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5450*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 5451*0Sstevel@tonic-gate 5452*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5453*0Sstevel@tonic-gate 5454*0Sstevel@tonic-gate /* 5455*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 5456*0Sstevel@tonic-gate */ 5457*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 5458*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5459*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5460*0Sstevel@tonic-gate return (error); 5461*0Sstevel@tonic-gate } 5462*0Sstevel@tonic-gate 5463*0Sstevel@tonic-gate /* 5464*0Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 5465*0Sstevel@tonic-gate * this call. 5466*0Sstevel@tonic-gate */ 5467*0Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 5468*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5469*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5470*0Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 5471*0Sstevel@tonic-gate } 5472*0Sstevel@tonic-gate 5473*0Sstevel@tonic-gate /* 5474*0Sstevel@tonic-gate * If RequestIO has already been done, we don't allow this call. 5475*0Sstevel@tonic-gate */ 5476*0Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 5477*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5478*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5479*0Sstevel@tonic-gate return (CS_IN_USE); 5480*0Sstevel@tonic-gate } 5481*0Sstevel@tonic-gate 5482*0Sstevel@tonic-gate mutex_enter(&sp->lock); 5483*0Sstevel@tonic-gate 5484*0Sstevel@tonic-gate /* 5485*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 5486*0Sstevel@tonic-gate * for this client, then return an error. 5487*0Sstevel@tonic-gate */ 5488*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 5489*0Sstevel@tonic-gate mutex_exit(&sp->lock); 5490*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5491*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5492*0Sstevel@tonic-gate return (CS_NO_CARD); 5493*0Sstevel@tonic-gate } 5494*0Sstevel@tonic-gate 5495*0Sstevel@tonic-gate mutex_exit(&sp->lock); 5496*0Sstevel@tonic-gate 5497*0Sstevel@tonic-gate /* 5498*0Sstevel@tonic-gate * If we're only being asked for one IO range, then set BasePort2 to 5499*0Sstevel@tonic-gate * zero, since we use it later on. 5500*0Sstevel@tonic-gate */ 5501*0Sstevel@tonic-gate if (!ior->NumPorts2) 5502*0Sstevel@tonic-gate ior->BasePort2.base = 0; 5503*0Sstevel@tonic-gate 5504*0Sstevel@tonic-gate /* 5505*0Sstevel@tonic-gate * See if we can allow Card Services to select the base address 5506*0Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 5507*0Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 5508*0Sstevel@tonic-gate * address lines to uniquely use that address, then we have 5509*0Sstevel@tonic-gate * the flexibility to choose an alternative base address. 5510*0Sstevel@tonic-gate * Note that if the client specifies that the card decodes zero 5511*0Sstevel@tonic-gate * IO address lines, then we have to use the NumPortsX 5512*0Sstevel@tonic-gate * values to figure out how many address lines the card 5513*0Sstevel@tonic-gate * actually decodes, and we have to round the NumPortsX 5514*0Sstevel@tonic-gate * values up to the closest power of two. 5515*0Sstevel@tonic-gate */ 5516*0Sstevel@tonic-gate if (ior->IOAddrLines) { 5517*0Sstevel@tonic-gate ior->BasePort1.base = IOADDR_FROBNITZ(ior->BasePort1.base, 5518*0Sstevel@tonic-gate ior->IOAddrLines); 5519*0Sstevel@tonic-gate ior->BasePort2.base = IOADDR_FROBNITZ(ior->BasePort2.base, 5520*0Sstevel@tonic-gate ior->IOAddrLines); 5521*0Sstevel@tonic-gate } else { 5522*0Sstevel@tonic-gate ior->BasePort1.base = ior->BasePort1.base & 5523*0Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5524*0Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5525*0Sstevel@tonic-gate ior->BasePort2.base = ior->BasePort2.base & 5526*0Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5527*0Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5528*0Sstevel@tonic-gate } 5529*0Sstevel@tonic-gate 5530*0Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5531*0Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 5532*0Sstevel@tonic-gate 5533*0Sstevel@tonic-gate 5534*0Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5535*0Sstevel@tonic-gate /* 5536*0Sstevel@tonic-gate * Here is where the code diverges, depending on the type of IO windows 5537*0Sstevel@tonic-gate * that this socket supports. If this socket supportes memory 5538*0Sstevel@tonic-gate * mapped IO windows, as determined by cs_init allocating an 5539*0Sstevel@tonic-gate * io_mmap_window_t structure on the socket structure, then we 5540*0Sstevel@tonic-gate * use one IO window for all the clients on this socket. We can 5541*0Sstevel@tonic-gate * do this safely since a memory mapped IO window implies that 5542*0Sstevel@tonic-gate * only this socket shares the complete IO space of the card. 5543*0Sstevel@tonic-gate * See the next major block of code for a description of what we do 5544*0Sstevel@tonic-gate * if a socket doesn't support memory mapped IO windows. 5545*0Sstevel@tonic-gate */ 5546*0Sstevel@tonic-gate if (sp->io_mmap_window) { 5547*0Sstevel@tonic-gate cs_window_t *cw; 5548*0Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 5549*0Sstevel@tonic-gate uint32_t offset; 5550*0Sstevel@tonic-gate 5551*0Sstevel@tonic-gate /* 5552*0Sstevel@tonic-gate * If we haven't allocated an IO window yet, do it now. 5553*0Sstevel@tonic-gate * Try to allocate the IO window that cs_init found for us; 5554*0Sstevel@tonic-gate * if that fails, then call cs_find_io_win to find a window. 5555*0Sstevel@tonic-gate */ 5556*0Sstevel@tonic-gate if (!imw->count) { 5557*0Sstevel@tonic-gate set_window_t set_window; 5558*0Sstevel@tonic-gate 5559*0Sstevel@tonic-gate if (!WINDOW_AVAILABLE_FOR_IO(imw->number)) { 5560*0Sstevel@tonic-gate iowin_char_t iowin_char; 5561*0Sstevel@tonic-gate 5562*0Sstevel@tonic-gate iowin_char.IOWndCaps = (WC_IO_RANGE_PER_WINDOW | 5563*0Sstevel@tonic-gate WC_8BIT | 5564*0Sstevel@tonic-gate WC_16BIT); 5565*0Sstevel@tonic-gate if ((error = cs_find_io_win(sp->socket_num, &iowin_char, 5566*0Sstevel@tonic-gate &imw->number, &imw->size)) != CS_SUCCESS) { 5567*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5568*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5569*0Sstevel@tonic-gate } /* cs_find_io_win */ 5570*0Sstevel@tonic-gate } /* if (!WINDOW_AVAILABLE_FOR_IO) */ 5571*0Sstevel@tonic-gate 5572*0Sstevel@tonic-gate set_window.socket = socket_num; 5573*0Sstevel@tonic-gate set_window.window = imw->number; 5574*0Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 5575*0Sstevel@tonic-gate set_window.base.base = 0; 5576*0Sstevel@tonic-gate set_window.WindowSize = imw->size; 5577*0Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_16BIT | 5578*0Sstevel@tonic-gate WS_EXACT_MAPIN | WS_IO); 5579*0Sstevel@tonic-gate 5580*0Sstevel@tonic-gate /* XXX - what to d here? XXX */ 5581*0Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 5582*0Sstevel@tonic-gate 5583*0Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) { 5584*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, 5585*0Sstevel@tonic-gate NULL, NULL, NULL, 5586*0Sstevel@tonic-gate (IO_DEALLOCATE_WINDOW | 5587*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5588*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5589*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5590*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 5591*0Sstevel@tonic-gate } 5592*0Sstevel@tonic-gate 5593*0Sstevel@tonic-gate imw->handle = set_window.base.handle; 5594*0Sstevel@tonic-gate imw->size = set_window.WindowSize; 5595*0Sstevel@tonic-gate 5596*0Sstevel@tonic-gate /* 5597*0Sstevel@tonic-gate * Check the caller's port requirements to be sure that they 5598*0Sstevel@tonic-gate * fit within our found IO window. 5599*0Sstevel@tonic-gate */ 5600*0Sstevel@tonic-gate if ((ior->BasePort1.base + ior->NumPorts1 + 5601*0Sstevel@tonic-gate ior->BasePort2.base + ior->NumPorts2) > imw->size) { 5602*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5603*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5604*0Sstevel@tonic-gate return (CS_BAD_BASE); 5605*0Sstevel@tonic-gate } 5606*0Sstevel@tonic-gate 5607*0Sstevel@tonic-gate if ((cw = cs_get_wp(imw->number)) == NULL) { 5608*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5609*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5610*0Sstevel@tonic-gate return (CS_BAD_WINDOW) 5611*0Sstevel@tonic-gate } 5612*0Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_IO); 5613*0Sstevel@tonic-gate 5614*0Sstevel@tonic-gate } /* if (!imw->count) */ 5615*0Sstevel@tonic-gate 5616*0Sstevel@tonic-gate imw->count++; 5617*0Sstevel@tonic-gate 5618*0Sstevel@tonic-gate /* 5619*0Sstevel@tonic-gate * All common access handles for this type of adapter are 5620*0Sstevel@tonic-gate * duped. We never give the original back to the caller. 5621*0Sstevel@tonic-gate */ 5622*0Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 5623*0Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort1.handle, 0); 5624*0Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort1.handle, &offset); 5625*0Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort1.handle, 5626*0Sstevel@tonic-gate ior->BasePort1.base + offset); 5627*0Sstevel@tonic-gate 5628*0Sstevel@tonic-gate if (ior->NumPorts2) { 5629*0Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 5630*0Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort2.handle, 0); 5631*0Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort2.handle, &offset); 5632*0Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort2.handle, 5633*0Sstevel@tonic-gate ior->BasePort1.base + offset); 5634*0Sstevel@tonic-gate } 5635*0Sstevel@tonic-gate 5636*0Sstevel@tonic-gate /* 5637*0Sstevel@tonic-gate * We don't really use these two values if we've got a memory 5638*0Sstevel@tonic-gate * mapped IO window since the assigned window number is stored 5639*0Sstevel@tonic-gate * in imw->number. 5640*0Sstevel@tonic-gate */ 5641*0Sstevel@tonic-gate client->io_alloc.Window1 = imw->number; 5642*0Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5643*0Sstevel@tonic-gate 5644*0Sstevel@tonic-gate /* 5645*0Sstevel@tonic-gate * This socket supports only IO port IO windows. 5646*0Sstevel@tonic-gate */ 5647*0Sstevel@tonic-gate } else { 5648*0Sstevel@tonic-gate #else /* USE_IOMMAP_WINDOW */ 5649*0Sstevel@tonic-gate { 5650*0Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5651*0Sstevel@tonic-gate baseaddru_t baseaddru; 5652*0Sstevel@tonic-gate 5653*0Sstevel@tonic-gate baseaddru.base = ior->BasePort1.base; 5654*0Sstevel@tonic-gate 5655*0Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, ior->Attributes1, 5656*0Sstevel@tonic-gate &client->io_alloc.Window1)) != CS_SUCCESS) { 5657*0Sstevel@tonic-gate 5658*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5659*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5660*0Sstevel@tonic-gate return (error); 5661*0Sstevel@tonic-gate } /* if (cs_allocate_io_win(1)) */ 5662*0Sstevel@tonic-gate 5663*0Sstevel@tonic-gate /* 5664*0Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 5665*0Sstevel@tonic-gate * deallocate the previously allocated window. 5666*0Sstevel@tonic-gate */ 5667*0Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 5668*0Sstevel@tonic-gate client->io_alloc.Window1, 5669*0Sstevel@tonic-gate &baseaddru, 5670*0Sstevel@tonic-gate &ior->NumPorts1, 5671*0Sstevel@tonic-gate ior->IOAddrLines, 5672*0Sstevel@tonic-gate ior->Attributes1)) != 5673*0Sstevel@tonic-gate CS_SUCCESS) { 5674*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5675*0Sstevel@tonic-gate NULL, NULL, NULL, 5676*0Sstevel@tonic-gate ( 5677*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5678*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5679*0Sstevel@tonic-gate 5680*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5681*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5682*0Sstevel@tonic-gate return (error); 5683*0Sstevel@tonic-gate } /* if (cs_setup_io_win(1)) */ 5684*0Sstevel@tonic-gate 5685*0Sstevel@tonic-gate ior->BasePort1.handle = (acc_handle_t)baseaddru.handle; 5686*0Sstevel@tonic-gate ior->BasePort1.base = baseaddru.base; 5687*0Sstevel@tonic-gate 5688*0Sstevel@tonic-gate /* 5689*0Sstevel@tonic-gate * See if the client wants two IO ranges. 5690*0Sstevel@tonic-gate */ 5691*0Sstevel@tonic-gate if (ior->NumPorts2) { 5692*0Sstevel@tonic-gate baseaddru_t baseaddru; 5693*0Sstevel@tonic-gate 5694*0Sstevel@tonic-gate baseaddru.base = ior->BasePort2.base; 5695*0Sstevel@tonic-gate 5696*0Sstevel@tonic-gate /* 5697*0Sstevel@tonic-gate * If we fail to allocate this window, then we must deallocate 5698*0Sstevel@tonic-gate * the previous IO window that is already allocated. 5699*0Sstevel@tonic-gate */ 5700*0Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, 5701*0Sstevel@tonic-gate ior->Attributes2, 5702*0Sstevel@tonic-gate &client->io_alloc.Window2)) != 5703*0Sstevel@tonic-gate CS_SUCCESS) { 5704*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5705*0Sstevel@tonic-gate client->io_alloc.Window2, 5706*0Sstevel@tonic-gate NULL, NULL, NULL, 5707*0Sstevel@tonic-gate ( 5708*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5709*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5710*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5711*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5712*0Sstevel@tonic-gate return (error); 5713*0Sstevel@tonic-gate } /* if (cs_allocate_io_win(2)) */ 5714*0Sstevel@tonic-gate /* 5715*0Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 5716*0Sstevel@tonic-gate * deallocate the previously allocated window. 5717*0Sstevel@tonic-gate */ 5718*0Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 5719*0Sstevel@tonic-gate client->io_alloc.Window2, 5720*0Sstevel@tonic-gate &baseaddru, 5721*0Sstevel@tonic-gate &ior->NumPorts2, 5722*0Sstevel@tonic-gate ior->IOAddrLines, 5723*0Sstevel@tonic-gate ior->Attributes2)) != 5724*0Sstevel@tonic-gate CS_SUCCESS) { 5725*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5726*0Sstevel@tonic-gate client->io_alloc.Window1, 5727*0Sstevel@tonic-gate NULL, NULL, NULL, 5728*0Sstevel@tonic-gate ( 5729*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5730*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5731*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5732*0Sstevel@tonic-gate client->io_alloc.Window2, 5733*0Sstevel@tonic-gate NULL, NULL, NULL, 5734*0Sstevel@tonic-gate ( 5735*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5736*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5737*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5738*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5739*0Sstevel@tonic-gate return (error); 5740*0Sstevel@tonic-gate } /* if (cs_setup_io_win(2)) */ 5741*0Sstevel@tonic-gate 5742*0Sstevel@tonic-gate ior->BasePort2.handle = (acc_handle_t)baseaddru.handle; 5743*0Sstevel@tonic-gate ior->BasePort2.base = baseaddru.base; 5744*0Sstevel@tonic-gate 5745*0Sstevel@tonic-gate } else { 5746*0Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5747*0Sstevel@tonic-gate } /* if (ior->NumPorts2) */ 5748*0Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 5749*0Sstevel@tonic-gate 5750*0Sstevel@tonic-gate /* 5751*0Sstevel@tonic-gate * Save a copy of the client's port information so that we 5752*0Sstevel@tonic-gate * can use it in the RequestConfiguration call. We set 5753*0Sstevel@tonic-gate * the IO window number(s) allocated in the respective 5754*0Sstevel@tonic-gate * section of code, above. 5755*0Sstevel@tonic-gate */ 5756*0Sstevel@tonic-gate client->io_alloc.BasePort1.base = ior->BasePort1.base; 5757*0Sstevel@tonic-gate client->io_alloc.BasePort1.handle = ior->BasePort1.handle; 5758*0Sstevel@tonic-gate client->io_alloc.NumPorts1 = ior->NumPorts1; 5759*0Sstevel@tonic-gate client->io_alloc.Attributes1 = ior->Attributes1; 5760*0Sstevel@tonic-gate client->io_alloc.BasePort2.base = ior->BasePort2.base; 5761*0Sstevel@tonic-gate client->io_alloc.BasePort2.handle = ior->BasePort2.handle; 5762*0Sstevel@tonic-gate client->io_alloc.NumPorts2 = ior->NumPorts2; 5763*0Sstevel@tonic-gate client->io_alloc.Attributes2 = ior->Attributes2; 5764*0Sstevel@tonic-gate client->io_alloc.IOAddrLines = ior->IOAddrLines; 5765*0Sstevel@tonic-gate 5766*0Sstevel@tonic-gate /* 5767*0Sstevel@tonic-gate * Mark this client as having done a successful RequestIO call. 5768*0Sstevel@tonic-gate */ 5769*0Sstevel@tonic-gate client->flags |= (REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5770*0Sstevel@tonic-gate 5771*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5772*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5773*0Sstevel@tonic-gate 5774*0Sstevel@tonic-gate return (CS_SUCCESS); 5775*0Sstevel@tonic-gate } 5776*0Sstevel@tonic-gate 5777*0Sstevel@tonic-gate /* 5778*0Sstevel@tonic-gate * cs_release_io - releases IO resources allocated by RequestIO; this is 5779*0Sstevel@tonic-gate * ReleaseIO 5780*0Sstevel@tonic-gate * 5781*0Sstevel@tonic-gate * calling: cs_release_io(client_handle_t, io_req_t *) 5782*0Sstevel@tonic-gate * 5783*0Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources sucessfully deallocated 5784*0Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 5785*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5786*0Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 5787*0Sstevel@tonic-gate * done without a ReleaseConfiguration 5788*0Sstevel@tonic-gate * CS_IN_USE - no RequestIO has been done 5789*0Sstevel@tonic-gate */ 5790*0Sstevel@tonic-gate static int 5791*0Sstevel@tonic-gate cs_release_io(client_handle_t client_handle, io_req_t *ior) 5792*0Sstevel@tonic-gate { 5793*0Sstevel@tonic-gate cs_socket_t *sp; 5794*0Sstevel@tonic-gate client_t *client; 5795*0Sstevel@tonic-gate int error; 5796*0Sstevel@tonic-gate int client_lock_acquired; 5797*0Sstevel@tonic-gate uint32_t socket_num; 5798*0Sstevel@tonic-gate 5799*0Sstevel@tonic-gate #ifdef lint 5800*0Sstevel@tonic-gate ior = NULL; 5801*0Sstevel@tonic-gate #endif 5802*0Sstevel@tonic-gate 5803*0Sstevel@tonic-gate /* 5804*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 5805*0Sstevel@tonic-gate * is, we don't support SS using this call. 5806*0Sstevel@tonic-gate */ 5807*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 5808*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 5809*0Sstevel@tonic-gate 5810*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5811*0Sstevel@tonic-gate 5812*0Sstevel@tonic-gate /* 5813*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5814*0Sstevel@tonic-gate */ 5815*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5816*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 5817*0Sstevel@tonic-gate 5818*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5819*0Sstevel@tonic-gate 5820*0Sstevel@tonic-gate /* 5821*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 5822*0Sstevel@tonic-gate */ 5823*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 5824*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5825*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5826*0Sstevel@tonic-gate return (error); 5827*0Sstevel@tonic-gate } 5828*0Sstevel@tonic-gate 5829*0Sstevel@tonic-gate /* 5830*0Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 5831*0Sstevel@tonic-gate * this call. 5832*0Sstevel@tonic-gate */ 5833*0Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 5834*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5835*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5836*0Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 5837*0Sstevel@tonic-gate } 5838*0Sstevel@tonic-gate 5839*0Sstevel@tonic-gate /* 5840*0Sstevel@tonic-gate * If RequestIO has not been done, we don't allow this call. 5841*0Sstevel@tonic-gate */ 5842*0Sstevel@tonic-gate if (!(client->flags & REQ_IO_DONE)) { 5843*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5844*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5845*0Sstevel@tonic-gate return (CS_IN_USE); 5846*0Sstevel@tonic-gate } 5847*0Sstevel@tonic-gate 5848*0Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5849*0Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 5850*0Sstevel@tonic-gate 5851*0Sstevel@tonic-gate #ifdef XXX 5852*0Sstevel@tonic-gate /* 5853*0Sstevel@tonic-gate * Check the passed IO allocation with the stored allocation; if 5854*0Sstevel@tonic-gate * they don't match, then return an error. 5855*0Sstevel@tonic-gate */ 5856*0Sstevel@tonic-gate if ((client->io_alloc.BasePort1 != ior->BasePort1) || 5857*0Sstevel@tonic-gate (client->io_alloc.NumPorts1 != ior->NumPorts1) || 5858*0Sstevel@tonic-gate (client->io_alloc.Attributes1 != ior->Attributes1) || 5859*0Sstevel@tonic-gate (client->io_alloc.BasePort2 != ior->BasePort2) || 5860*0Sstevel@tonic-gate (client->io_alloc.NumPorts2 != ior->NumPorts2) || 5861*0Sstevel@tonic-gate (client->io_alloc.Attributes2 != ior->Attributes2) || 5862*0Sstevel@tonic-gate (client->io_alloc.IOAddrLines != ior->IOAddrLines)) { 5863*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5864*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5865*0Sstevel@tonic-gate return (CS_BAD_ARGS); 5866*0Sstevel@tonic-gate } 5867*0Sstevel@tonic-gate #endif 5868*0Sstevel@tonic-gate 5869*0Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5870*0Sstevel@tonic-gate /* 5871*0Sstevel@tonic-gate * The code diverges here depending on if this socket supports 5872*0Sstevel@tonic-gate * memory mapped IO windows or not. See comments in the 5873*0Sstevel@tonic-gate * cs_request_io function for a description of what's 5874*0Sstevel@tonic-gate * going on here. 5875*0Sstevel@tonic-gate */ 5876*0Sstevel@tonic-gate if (sp->io_mmap_window) { 5877*0Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 5878*0Sstevel@tonic-gate 5879*0Sstevel@tonic-gate /* 5880*0Sstevel@tonic-gate * We should never see this; if we do, it's an internal 5881*0Sstevel@tonic-gate * consistency error. 5882*0Sstevel@tonic-gate */ 5883*0Sstevel@tonic-gate if (!imw->count) { 5884*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_io: socket %d !imw->count\n", 5885*0Sstevel@tonic-gate sp->socket_num); 5886*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5887*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5888*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 5889*0Sstevel@tonic-gate } 5890*0Sstevel@tonic-gate 5891*0Sstevel@tonic-gate /* 5892*0Sstevel@tonic-gate * All common access handles for this type of adapter are 5893*0Sstevel@tonic-gate * duped. We never give the original back to the caller, 5894*0Sstevel@tonic-gate * so it's OK to unconditionally free the handle here. 5895*0Sstevel@tonic-gate */ 5896*0Sstevel@tonic-gate csx_FreeHandle(&ior->BasePort1.handle); 5897*0Sstevel@tonic-gate 5898*0Sstevel@tonic-gate /* 5899*0Sstevel@tonic-gate * If the IO window referance count is zero, then deallocate 5900*0Sstevel@tonic-gate * and disable this window. 5901*0Sstevel@tonic-gate */ 5902*0Sstevel@tonic-gate if (!--(imw->count)) { 5903*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, NULL, 5904*0Sstevel@tonic-gate NULL, NULL, 5905*0Sstevel@tonic-gate ( 5906*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5907*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5908*0Sstevel@tonic-gate } /* if (imw->count) */ 5909*0Sstevel@tonic-gate } else { 5910*0Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5911*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5912*0Sstevel@tonic-gate NULL, NULL, NULL, 5913*0Sstevel@tonic-gate ( 5914*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5915*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5916*0Sstevel@tonic-gate if (client->io_alloc.Window2 != PCMCIA_MAX_WINDOWS) 5917*0Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window2, 5918*0Sstevel@tonic-gate NULL, NULL, NULL, 5919*0Sstevel@tonic-gate ( 5920*0Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5921*0Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5922*0Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5923*0Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 5924*0Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5925*0Sstevel@tonic-gate 5926*0Sstevel@tonic-gate /* 5927*0Sstevel@tonic-gate * Mark the client as not having any IO resources allocated. 5928*0Sstevel@tonic-gate */ 5929*0Sstevel@tonic-gate client->flags &= ~(REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5930*0Sstevel@tonic-gate 5931*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5932*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5933*0Sstevel@tonic-gate return (CS_SUCCESS); 5934*0Sstevel@tonic-gate } 5935*0Sstevel@tonic-gate 5936*0Sstevel@tonic-gate /* 5937*0Sstevel@tonic-gate * cs_find_io_win - finds an IO window that matches the parameters specified 5938*0Sstevel@tonic-gate * in the flags argument 5939*0Sstevel@tonic-gate * 5940*0Sstevel@tonic-gate * calling: sn - socket number to look for IO window on 5941*0Sstevel@tonic-gate * *iwc - other window characteristics to match 5942*0Sstevel@tonic-gate * *assigned_window - pointer to where we return the assigned 5943*0Sstevel@tonic-gate * window number if we found a window or 5944*0Sstevel@tonic-gate * undefined otherwise 5945*0Sstevel@tonic-gate * *size - if non-NULL, the found window size will be stored here 5946*0Sstevel@tonic-gate * 5947*0Sstevel@tonic-gate * returns: CS_SUCCESS - if IO window found 5948*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5949*0Sstevel@tonic-gate */ 5950*0Sstevel@tonic-gate static int 5951*0Sstevel@tonic-gate cs_find_io_win(uint32_t sn, iowin_char_t *iwc, uint32_t *assigned_window, 5952*0Sstevel@tonic-gate uint32_t *size) 5953*0Sstevel@tonic-gate { 5954*0Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 5955*0Sstevel@tonic-gate unsigned wn; 5956*0Sstevel@tonic-gate 5957*0Sstevel@tonic-gate iw = &inquire_window; 5958*0Sstevel@tonic-gate 5959*0Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 5960*0Sstevel@tonic-gate iowin_char_t *iowc; 5961*0Sstevel@tonic-gate cs_window_t *cw; 5962*0Sstevel@tonic-gate 5963*0Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 5964*0Sstevel@tonic-gate 5965*0Sstevel@tonic-gate iw->window = wn; 5966*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 5967*0Sstevel@tonic-gate 5968*0Sstevel@tonic-gate iowc = &iw->iowin_char; 5969*0Sstevel@tonic-gate 5970*0Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5971*0Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_IO(cw) && 5972*0Sstevel@tonic-gate (iw->WndCaps & WC_IO) && 5973*0Sstevel@tonic-gate ((iowc->IOWndCaps & iwc->IOWndCaps) == iwc->IOWndCaps)) { 5974*0Sstevel@tonic-gate 5975*0Sstevel@tonic-gate *assigned_window = wn; 5976*0Sstevel@tonic-gate 5977*0Sstevel@tonic-gate if (size) 5978*0Sstevel@tonic-gate *size = iw->iowin_char.ReqGran; 5979*0Sstevel@tonic-gate return (CS_SUCCESS); 5980*0Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 5981*0Sstevel@tonic-gate } /* cs_get_wp */ 5982*0Sstevel@tonic-gate } /* for (wn) */ 5983*0Sstevel@tonic-gate 5984*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 5985*0Sstevel@tonic-gate } 5986*0Sstevel@tonic-gate 5987*0Sstevel@tonic-gate /* 5988*0Sstevel@tonic-gate * cs_allocate_io_win - finds and allocates an IO window 5989*0Sstevel@tonic-gate * 5990*0Sstevel@tonic-gate * calling: sn - socket number to look for window on 5991*0Sstevel@tonic-gate * Attributes - window attributes in io_req_t.Attributes format 5992*0Sstevel@tonic-gate * *assigned_window - pointer to return assigned window number 5993*0Sstevel@tonic-gate * 5994*0Sstevel@tonic-gate * returns: CS_SUCCESS - IO window found and allocated 5995*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if cs_find_io_win couldn't find a 5996*0Sstevel@tonic-gate * window that matches the passed criteria 5997*0Sstevel@tonic-gate * 5998*0Sstevel@tonic-gate * Note: This fucntion will find and allocate an IO window. The caller is 5999*0Sstevel@tonic-gate * responsible for deallocating the window. 6000*0Sstevel@tonic-gate */ 6001*0Sstevel@tonic-gate static int 6002*0Sstevel@tonic-gate cs_allocate_io_win(uint32_t sn, uint32_t Attributes, uint32_t *assigned_window) 6003*0Sstevel@tonic-gate { 6004*0Sstevel@tonic-gate iowin_char_t iowin_char; 6005*0Sstevel@tonic-gate cs_window_t *cw; 6006*0Sstevel@tonic-gate 6007*0Sstevel@tonic-gate iowin_char.IOWndCaps = 6008*0Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WC_16BIT:WC_8BIT); 6009*0Sstevel@tonic-gate 6010*0Sstevel@tonic-gate if (cs_find_io_win(sn, &iowin_char, assigned_window, NULL) == 6011*0Sstevel@tonic-gate CS_SUCCESS) { 6012*0Sstevel@tonic-gate if ((cw = cs_get_wp(*assigned_window)) == NULL) 6013*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 6014*0Sstevel@tonic-gate 6015*0Sstevel@tonic-gate cw->state = (cw->state & CW_WINDOW_VALID) | (CW_ALLOCATED | CW_IO); 6016*0Sstevel@tonic-gate return (CS_SUCCESS); 6017*0Sstevel@tonic-gate } 6018*0Sstevel@tonic-gate 6019*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 6020*0Sstevel@tonic-gate } 6021*0Sstevel@tonic-gate 6022*0Sstevel@tonic-gate /* 6023*0Sstevel@tonic-gate * cs_setup_io_win - setup and destroy an IO window 6024*0Sstevel@tonic-gate * 6025*0Sstevel@tonic-gate * calling: sn - socket number 6026*0Sstevel@tonic-gate * wn - window number 6027*0Sstevel@tonic-gate * XXX Base - pointer to XXX 6028*0Sstevel@tonic-gate * *NumPorts - pointer to number of allocated ports to return 6029*0Sstevel@tonic-gate * IOAddrLines - number of IO address lines decoded by this card 6030*0Sstevel@tonic-gate * Attributes - either io_req_t attributes, or a combination of 6031*0Sstevel@tonic-gate * the following flags: 6032*0Sstevel@tonic-gate * IO_DEALLOCATE_WINDOW - deallocate the window 6033*0Sstevel@tonic-gate * IO_DISABLE_WINDOW - disable the window 6034*0Sstevel@tonic-gate * When either of these two flags are set, *Base 6035*0Sstevel@tonic-gate * and NumPorts should be NULL. 6036*0Sstevel@tonic-gate * 6037*0Sstevel@tonic-gate * returns: CS_SUCCESS - if no failure 6038*0Sstevel@tonic-gate * CS_BAD_WINDOW - if error while trying to configure window 6039*0Sstevel@tonic-gate * 6040*0Sstevel@tonic-gate * Note: We use the IOAddrLines value to determine what base address to pass 6041*0Sstevel@tonic-gate * to Socket Services. 6042*0Sstevel@tonic-gate */ 6043*0Sstevel@tonic-gate static int 6044*0Sstevel@tonic-gate cs_setup_io_win(uint32_t sn, uint32_t wn, baseaddru_t *Base, uint32_t *NumPorts, 6045*0Sstevel@tonic-gate uint32_t IOAddrLines, uint32_t Attributes) 6046*0Sstevel@tonic-gate { 6047*0Sstevel@tonic-gate set_window_t set_window; 6048*0Sstevel@tonic-gate 6049*0Sstevel@tonic-gate if (Attributes & (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW)) { 6050*0Sstevel@tonic-gate 6051*0Sstevel@tonic-gate if (Attributes & IO_DEALLOCATE_WINDOW) { 6052*0Sstevel@tonic-gate cs_window_t *cw; 6053*0Sstevel@tonic-gate 6054*0Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) == NULL) 6055*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 6056*0Sstevel@tonic-gate cw->state &= CW_WINDOW_VALID; 6057*0Sstevel@tonic-gate 6058*0Sstevel@tonic-gate } /* IO_DEALLOCATE_WINDOW */ 6059*0Sstevel@tonic-gate 6060*0Sstevel@tonic-gate if (Attributes & IO_DISABLE_WINDOW) { 6061*0Sstevel@tonic-gate get_window_t get_window; 6062*0Sstevel@tonic-gate 6063*0Sstevel@tonic-gate get_window.window = wn; 6064*0Sstevel@tonic-gate 6065*0Sstevel@tonic-gate SocketServices(SS_GetWindow, &get_window); 6066*0Sstevel@tonic-gate 6067*0Sstevel@tonic-gate set_window.socket = get_window.socket; 6068*0Sstevel@tonic-gate set_window.window = get_window.window; 6069*0Sstevel@tonic-gate set_window.speed = get_window.speed; 6070*0Sstevel@tonic-gate set_window.base = 0; 6071*0Sstevel@tonic-gate set_window.WindowSize = get_window.size; 6072*0Sstevel@tonic-gate set_window.state = get_window.state & ~WS_ENABLED; 6073*0Sstevel@tonic-gate 6074*0Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 6075*0Sstevel@tonic-gate 6076*0Sstevel@tonic-gate SocketServices(SS_SetWindow, &set_window); 6077*0Sstevel@tonic-gate } /* IO_DISABLE_WINDOW */ 6078*0Sstevel@tonic-gate 6079*0Sstevel@tonic-gate return (CS_SUCCESS); 6080*0Sstevel@tonic-gate 6081*0Sstevel@tonic-gate } /* if (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW) */ 6082*0Sstevel@tonic-gate 6083*0Sstevel@tonic-gate /* 6084*0Sstevel@tonic-gate * See if we can allow Socket Services to select the base address 6085*0Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 6086*0Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 6087*0Sstevel@tonic-gate * address lines to uniquely use that address, then we have 6088*0Sstevel@tonic-gate * the flexibility to choose an alternative base address. 6089*0Sstevel@tonic-gate * XXX - Is this really correct in all cases? 6090*0Sstevel@tonic-gate */ 6091*0Sstevel@tonic-gate if (!IOAddrLines) 6092*0Sstevel@tonic-gate Base->base = 0; 6093*0Sstevel@tonic-gate else 6094*0Sstevel@tonic-gate Base->base = IOADDR_FROBNITZ(Base->base, IOAddrLines); 6095*0Sstevel@tonic-gate 6096*0Sstevel@tonic-gate set_window.socket = sn; 6097*0Sstevel@tonic-gate set_window.window = wn; 6098*0Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 6099*0Sstevel@tonic-gate set_window.base = Base->base; 6100*0Sstevel@tonic-gate set_window.WindowSize = *NumPorts; 6101*0Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_IO | 6102*0Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WS_16BIT:0)); 6103*0Sstevel@tonic-gate 6104*0Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 6105*0Sstevel@tonic-gate 6106*0Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) 6107*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 6108*0Sstevel@tonic-gate 6109*0Sstevel@tonic-gate Base->base = set_window.base; 6110*0Sstevel@tonic-gate Base->handle = set_window.handle; 6111*0Sstevel@tonic-gate *NumPorts = set_window.WindowSize; 6112*0Sstevel@tonic-gate 6113*0Sstevel@tonic-gate return (CS_SUCCESS); 6114*0Sstevel@tonic-gate } 6115*0Sstevel@tonic-gate 6116*0Sstevel@tonic-gate /* 6117*0Sstevel@tonic-gate * ==== IRQ handling functions ==== 6118*0Sstevel@tonic-gate */ 6119*0Sstevel@tonic-gate 6120*0Sstevel@tonic-gate /* 6121*0Sstevel@tonic-gate * cs_request_irq - add's client's IRQ handler; supports RequestIRQ 6122*0Sstevel@tonic-gate * 6123*0Sstevel@tonic-gate * calling: irq_req_t.Attributes - must have the IRQ_TYPE_EXCLUSIVE 6124*0Sstevel@tonic-gate * flag set, and all other flags clear, or 6125*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE will be returned 6126*0Sstevel@tonic-gate * 6127*0Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources available for client 6128*0Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be allocated 6129*0Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 6130*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6131*0Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 6132*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 6133*0Sstevel@tonic-gate * flags are set 6134*0Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6135*0Sstevel@tonic-gate * already been done 6136*0Sstevel@tonic-gate * CS_IN_USE - IRQ ports already in use or function has 6137*0Sstevel@tonic-gate * already been called 6138*0Sstevel@tonic-gate * 6139*0Sstevel@tonic-gate * Note: We only allow level-mode interrupts. 6140*0Sstevel@tonic-gate */ 6141*0Sstevel@tonic-gate static int 6142*0Sstevel@tonic-gate cs_request_irq(client_handle_t client_handle, irq_req_t *irqr) 6143*0Sstevel@tonic-gate { 6144*0Sstevel@tonic-gate cs_socket_t *sp; 6145*0Sstevel@tonic-gate client_t *client; 6146*0Sstevel@tonic-gate set_irq_handler_t set_irq_handler; 6147*0Sstevel@tonic-gate int error; 6148*0Sstevel@tonic-gate int client_lock_acquired; 6149*0Sstevel@tonic-gate 6150*0Sstevel@tonic-gate /* 6151*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6152*0Sstevel@tonic-gate * is, we don't support SS using this call. 6153*0Sstevel@tonic-gate */ 6154*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6155*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6156*0Sstevel@tonic-gate 6157*0Sstevel@tonic-gate /* 6158*0Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 6159*0Sstevel@tonic-gate */ 6160*0Sstevel@tonic-gate if ((irqr->Attributes & (IRQ_TYPE_TIME | IRQ_TYPE_DYNAMIC_SHARING | 6161*0Sstevel@tonic-gate IRQ_FIRST_SHARED | IRQ_PULSE_ALLOCATED | 6162*0Sstevel@tonic-gate IRQ_FORCED_PULSE)) || 6163*0Sstevel@tonic-gate !(irqr->Attributes & IRQ_TYPE_EXCLUSIVE)) 6164*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 6165*0Sstevel@tonic-gate 6166*0Sstevel@tonic-gate /* 6167*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6168*0Sstevel@tonic-gate */ 6169*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6170*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6171*0Sstevel@tonic-gate 6172*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6173*0Sstevel@tonic-gate 6174*0Sstevel@tonic-gate /* 6175*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 6176*0Sstevel@tonic-gate */ 6177*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6178*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6179*0Sstevel@tonic-gate return (error); 6180*0Sstevel@tonic-gate } 6181*0Sstevel@tonic-gate 6182*0Sstevel@tonic-gate /* 6183*0Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6184*0Sstevel@tonic-gate * this call. 6185*0Sstevel@tonic-gate */ 6186*0Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6187*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6188*0Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6189*0Sstevel@tonic-gate } 6190*0Sstevel@tonic-gate 6191*0Sstevel@tonic-gate /* 6192*0Sstevel@tonic-gate * If RequestIRQ has already been done, we don't allow this call. 6193*0Sstevel@tonic-gate */ 6194*0Sstevel@tonic-gate if (client->flags & REQ_IRQ_DONE) { 6195*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6196*0Sstevel@tonic-gate return (CS_IN_USE); 6197*0Sstevel@tonic-gate } 6198*0Sstevel@tonic-gate 6199*0Sstevel@tonic-gate /* 6200*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 6201*0Sstevel@tonic-gate * for this client, then return an error. 6202*0Sstevel@tonic-gate */ 6203*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 6204*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6205*0Sstevel@tonic-gate return (CS_NO_CARD); 6206*0Sstevel@tonic-gate } 6207*0Sstevel@tonic-gate 6208*0Sstevel@tonic-gate /* 6209*0Sstevel@tonic-gate * Set up the parameters and ask Socket Services to give us an IRQ 6210*0Sstevel@tonic-gate * for this client. We don't really do much, since the IRQ 6211*0Sstevel@tonic-gate * resources are managed by SS and the kernel. We also don't 6212*0Sstevel@tonic-gate * care which IRQ level we are given. 6213*0Sstevel@tonic-gate */ 6214*0Sstevel@tonic-gate set_irq_handler.socket = 6215*0Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6216*0Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 6217*0Sstevel@tonic-gate set_irq_handler.irq = IRQ_ANY; 6218*0Sstevel@tonic-gate 6219*0Sstevel@tonic-gate set_irq_handler.handler_id = client_handle; 6220*0Sstevel@tonic-gate set_irq_handler.handler = (f_t *)irqr->irq_handler; 6221*0Sstevel@tonic-gate set_irq_handler.arg1 = irqr->irq_handler_arg; 6222*0Sstevel@tonic-gate set_irq_handler.arg2 = NULL; 6223*0Sstevel@tonic-gate 6224*0Sstevel@tonic-gate if ((error = SocketServices(SS_SetIRQHandler, 6225*0Sstevel@tonic-gate &set_irq_handler)) != SUCCESS) { 6226*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6227*0Sstevel@tonic-gate return (CS_BAD_IRQ); 6228*0Sstevel@tonic-gate } 6229*0Sstevel@tonic-gate 6230*0Sstevel@tonic-gate irqr->iblk_cookie = set_irq_handler.iblk_cookie; 6231*0Sstevel@tonic-gate irqr->idev_cookie = set_irq_handler.idev_cookie; 6232*0Sstevel@tonic-gate 6233*0Sstevel@tonic-gate /* 6234*0Sstevel@tonic-gate * Save the allocated IRQ information for this client. 6235*0Sstevel@tonic-gate */ 6236*0Sstevel@tonic-gate client->irq_alloc.Attributes = irqr->Attributes; 6237*0Sstevel@tonic-gate client->irq_alloc.irq = set_irq_handler.irq; 6238*0Sstevel@tonic-gate client->irq_alloc.handler_id = set_irq_handler.handler_id; 6239*0Sstevel@tonic-gate client->irq_alloc.irq_handler = (f_t *)set_irq_handler.handler; 6240*0Sstevel@tonic-gate client->irq_alloc.irq_handler_arg1 = set_irq_handler.arg1; 6241*0Sstevel@tonic-gate client->irq_alloc.irq_handler_arg2 = set_irq_handler.arg2; 6242*0Sstevel@tonic-gate 6243*0Sstevel@tonic-gate #ifdef CS_DEBUG 6244*0Sstevel@tonic-gate if (cs_debug > 0) 6245*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_irq: socket %d irqr->Attributes 0x%x " 6246*0Sstevel@tonic-gate "set_irq_handler.irq 0x%x\n", 6247*0Sstevel@tonic-gate sp->socket_num, 6248*0Sstevel@tonic-gate (int)irqr->Attributes, 6249*0Sstevel@tonic-gate set_irq_handler.irq); 6250*0Sstevel@tonic-gate #endif 6251*0Sstevel@tonic-gate 6252*0Sstevel@tonic-gate /* 6253*0Sstevel@tonic-gate * Mark this client as having done a successful RequestIRQ call. 6254*0Sstevel@tonic-gate */ 6255*0Sstevel@tonic-gate client->flags |= (REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6256*0Sstevel@tonic-gate 6257*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6258*0Sstevel@tonic-gate return (CS_SUCCESS); 6259*0Sstevel@tonic-gate } 6260*0Sstevel@tonic-gate 6261*0Sstevel@tonic-gate /* 6262*0Sstevel@tonic-gate * cs_release_irq - releases IRQ resources allocated by RequestIRQ; this is 6263*0Sstevel@tonic-gate * ReleaseIRQ 6264*0Sstevel@tonic-gate * 6265*0Sstevel@tonic-gate * calling: cs_release_irq(client_handle_t, irq_req_t *) 6266*0Sstevel@tonic-gate * 6267*0Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources sucessfully deallocated 6268*0Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be deallocated 6269*0Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 6270*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6271*0Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 6272*0Sstevel@tonic-gate * done without a ReleaseConfiguration 6273*0Sstevel@tonic-gate * CS_IN_USE - no RequestIRQ has been done 6274*0Sstevel@tonic-gate */ 6275*0Sstevel@tonic-gate static int 6276*0Sstevel@tonic-gate cs_release_irq(client_handle_t client_handle, irq_req_t *irqr) 6277*0Sstevel@tonic-gate { 6278*0Sstevel@tonic-gate cs_socket_t *sp; 6279*0Sstevel@tonic-gate client_t *client; 6280*0Sstevel@tonic-gate clear_irq_handler_t clear_irq_handler; 6281*0Sstevel@tonic-gate int error; 6282*0Sstevel@tonic-gate int client_lock_acquired; 6283*0Sstevel@tonic-gate 6284*0Sstevel@tonic-gate #ifdef lint 6285*0Sstevel@tonic-gate irqr = NULL; 6286*0Sstevel@tonic-gate #endif 6287*0Sstevel@tonic-gate 6288*0Sstevel@tonic-gate /* 6289*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6290*0Sstevel@tonic-gate * is, we don't support SS using this call. 6291*0Sstevel@tonic-gate */ 6292*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6293*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6294*0Sstevel@tonic-gate 6295*0Sstevel@tonic-gate /* 6296*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6297*0Sstevel@tonic-gate */ 6298*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6299*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6300*0Sstevel@tonic-gate 6301*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6302*0Sstevel@tonic-gate 6303*0Sstevel@tonic-gate /* 6304*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 6305*0Sstevel@tonic-gate */ 6306*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6307*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6308*0Sstevel@tonic-gate return (error); 6309*0Sstevel@tonic-gate } 6310*0Sstevel@tonic-gate 6311*0Sstevel@tonic-gate /* 6312*0Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6313*0Sstevel@tonic-gate * this call. 6314*0Sstevel@tonic-gate */ 6315*0Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6316*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6317*0Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6318*0Sstevel@tonic-gate } 6319*0Sstevel@tonic-gate 6320*0Sstevel@tonic-gate /* 6321*0Sstevel@tonic-gate * If RequestIRQ has not been done, we don't allow this call. 6322*0Sstevel@tonic-gate */ 6323*0Sstevel@tonic-gate if (!(client->flags & REQ_IRQ_DONE)) { 6324*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6325*0Sstevel@tonic-gate return (CS_IN_USE); 6326*0Sstevel@tonic-gate } 6327*0Sstevel@tonic-gate 6328*0Sstevel@tonic-gate /* 6329*0Sstevel@tonic-gate * Tell Socket Services that we want to deregister this client's 6330*0Sstevel@tonic-gate * IRQ handler. 6331*0Sstevel@tonic-gate */ 6332*0Sstevel@tonic-gate clear_irq_handler.socket = 6333*0Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6334*0Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 6335*0Sstevel@tonic-gate clear_irq_handler.handler_id = client->irq_alloc.handler_id; 6336*0Sstevel@tonic-gate clear_irq_handler.handler = (f_t *)client->irq_alloc.irq_handler; 6337*0Sstevel@tonic-gate 6338*0Sstevel@tonic-gate /* 6339*0Sstevel@tonic-gate * At this point, we should never fail this SS call; if we do, it 6340*0Sstevel@tonic-gate * means that there is an internal consistancy error in either 6341*0Sstevel@tonic-gate * Card Services or Socket Services. 6342*0Sstevel@tonic-gate */ 6343*0Sstevel@tonic-gate if ((error = SocketServices(SS_ClearIRQHandler, &clear_irq_handler)) != 6344*0Sstevel@tonic-gate SUCCESS) { 6345*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6346*0Sstevel@tonic-gate return (CS_BAD_IRQ); 6347*0Sstevel@tonic-gate } 6348*0Sstevel@tonic-gate 6349*0Sstevel@tonic-gate /* 6350*0Sstevel@tonic-gate * Mark the client as not having any IRQ resources allocated. 6351*0Sstevel@tonic-gate */ 6352*0Sstevel@tonic-gate client->flags &= ~(REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6353*0Sstevel@tonic-gate 6354*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6355*0Sstevel@tonic-gate return (CS_SUCCESS); 6356*0Sstevel@tonic-gate } 6357*0Sstevel@tonic-gate 6358*0Sstevel@tonic-gate /* 6359*0Sstevel@tonic-gate * ==== configuration handling functions ==== 6360*0Sstevel@tonic-gate */ 6361*0Sstevel@tonic-gate 6362*0Sstevel@tonic-gate /* 6363*0Sstevel@tonic-gate * cs_request_configuration - sets up socket and card configuration on behalf 6364*0Sstevel@tonic-gate * of the client; this is RequestConfiguration 6365*0Sstevel@tonic-gate * 6366*0Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully set 6367*0Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6368*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6369*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6370*0Sstevel@tonic-gate * are set 6371*0Sstevel@tonic-gate * CS_BAD_TYPE - if the socket doesn't support a mem and IO 6372*0Sstevel@tonic-gate * interface (SOCKET_INTERFACE_MEMORY_AND_IO set) 6373*0Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6374*0Sstevel@tonic-gate * already been done 6375*0Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 6376*0Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6377*0Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6378*0Sstevel@tonic-gate * 6379*0Sstevel@tonic-gate * Bug ID: 1193637 - Card Services RequestConfiguration does not conform 6380*0Sstevel@tonic-gate * to PCMCIA standard 6381*0Sstevel@tonic-gate * We allow clients to do a RequestConfiguration even if they haven't 6382*0Sstevel@tonic-gate * done a RequestIO or RequestIRQ. 6383*0Sstevel@tonic-gate */ 6384*0Sstevel@tonic-gate static int 6385*0Sstevel@tonic-gate cs_request_configuration(client_handle_t client_handle, config_req_t *cr) 6386*0Sstevel@tonic-gate { 6387*0Sstevel@tonic-gate cs_socket_t *sp; 6388*0Sstevel@tonic-gate client_t *client; 6389*0Sstevel@tonic-gate volatile config_regs_t *crt; 6390*0Sstevel@tonic-gate set_socket_t set_socket; 6391*0Sstevel@tonic-gate get_socket_t get_socket; 6392*0Sstevel@tonic-gate acc_handle_t cis_handle; 6393*0Sstevel@tonic-gate int error; 6394*0Sstevel@tonic-gate uint32_t newoffset; 6395*0Sstevel@tonic-gate int client_lock_acquired; 6396*0Sstevel@tonic-gate 6397*0Sstevel@tonic-gate /* 6398*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6399*0Sstevel@tonic-gate * is, we don't support SS using this call. 6400*0Sstevel@tonic-gate */ 6401*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6402*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6403*0Sstevel@tonic-gate 6404*0Sstevel@tonic-gate #ifdef XXX 6405*0Sstevel@tonic-gate /* 6406*0Sstevel@tonic-gate * If the client specifies Vcc = 0 and any non-zero value for 6407*0Sstevel@tonic-gate * either of the Vpp members, that's an illegal condition. 6408*0Sstevel@tonic-gate */ 6409*0Sstevel@tonic-gate if (!(cr->Vcc) && (cr->Vpp1 || cr->Vpp2)) 6410*0Sstevel@tonic-gate return (CS_BAD_VCC); 6411*0Sstevel@tonic-gate #endif 6412*0Sstevel@tonic-gate 6413*0Sstevel@tonic-gate /* 6414*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6415*0Sstevel@tonic-gate */ 6416*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6417*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6418*0Sstevel@tonic-gate 6419*0Sstevel@tonic-gate /* 6420*0Sstevel@tonic-gate * If the client is asking for a memory and IO interface on this 6421*0Sstevel@tonic-gate * socket, then check the socket capabilities to be sure that 6422*0Sstevel@tonic-gate * this socket supports this configuration. 6423*0Sstevel@tonic-gate */ 6424*0Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) { 6425*0Sstevel@tonic-gate inquire_socket_t inquire_socket; 6426*0Sstevel@tonic-gate 6427*0Sstevel@tonic-gate inquire_socket.socket = sp->socket_num; 6428*0Sstevel@tonic-gate 6429*0Sstevel@tonic-gate if (SocketServices(SS_InquireSocket, &inquire_socket) != SUCCESS) 6430*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6431*0Sstevel@tonic-gate 6432*0Sstevel@tonic-gate if (!(inquire_socket.SocketCaps & IF_IO)) 6433*0Sstevel@tonic-gate return (CS_BAD_TYPE); 6434*0Sstevel@tonic-gate 6435*0Sstevel@tonic-gate } /* if (SOCKET_INTERFACE_MEMORY_AND_IO) */ 6436*0Sstevel@tonic-gate 6437*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6438*0Sstevel@tonic-gate 6439*0Sstevel@tonic-gate /* 6440*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 6441*0Sstevel@tonic-gate */ 6442*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6443*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6444*0Sstevel@tonic-gate return (error); 6445*0Sstevel@tonic-gate } 6446*0Sstevel@tonic-gate 6447*0Sstevel@tonic-gate /* 6448*0Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6449*0Sstevel@tonic-gate * this call. 6450*0Sstevel@tonic-gate */ 6451*0Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6452*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6453*0Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6454*0Sstevel@tonic-gate } 6455*0Sstevel@tonic-gate 6456*0Sstevel@tonic-gate /* 6457*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 6458*0Sstevel@tonic-gate * for this client, then return an error. 6459*0Sstevel@tonic-gate */ 6460*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 6461*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6462*0Sstevel@tonic-gate return (CS_NO_CARD); 6463*0Sstevel@tonic-gate } 6464*0Sstevel@tonic-gate 6465*0Sstevel@tonic-gate /* 6466*0Sstevel@tonic-gate * At this point, most of the client's calling parameters have been 6467*0Sstevel@tonic-gate * validated, so we can go ahead and configure the socket and 6468*0Sstevel@tonic-gate * the card. 6469*0Sstevel@tonic-gate */ 6470*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 6471*0Sstevel@tonic-gate 6472*0Sstevel@tonic-gate /* 6473*0Sstevel@tonic-gate * Configure the socket with the interface type and voltages requested 6474*0Sstevel@tonic-gate * by the client. 6475*0Sstevel@tonic-gate */ 6476*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 6477*0Sstevel@tonic-gate 6478*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6479*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6480*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6481*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6482*0Sstevel@tonic-gate } 6483*0Sstevel@tonic-gate 6484*0Sstevel@tonic-gate #ifdef CS_DEBUG 6485*0Sstevel@tonic-gate if (cs_debug > 0) 6486*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d " 6487*0Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 6488*0Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 6489*0Sstevel@tonic-gate sp->socket_num, 6490*0Sstevel@tonic-gate (int)client->irq_alloc.irq, 6491*0Sstevel@tonic-gate get_socket.IRQRouting); 6492*0Sstevel@tonic-gate #endif 6493*0Sstevel@tonic-gate 6494*0Sstevel@tonic-gate bzero(&set_socket, sizeof (set_socket)); 6495*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 6496*0Sstevel@tonic-gate set_socket.IREQRouting = client->irq_alloc.irq & ~IRQ_ENABLE; 6497*0Sstevel@tonic-gate 6498*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 6499*0Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 6500*0Sstevel@tonic-gate 6501*0Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vcc, VCC, 6502*0Sstevel@tonic-gate &set_socket.VccLevel) != CS_SUCCESS) { 6503*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6504*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6505*0Sstevel@tonic-gate return (CS_BAD_VCC); 6506*0Sstevel@tonic-gate } 6507*0Sstevel@tonic-gate 6508*0Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp1, VPP1, 6509*0Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 6510*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6511*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6512*0Sstevel@tonic-gate return (CS_BAD_VPP); 6513*0Sstevel@tonic-gate } 6514*0Sstevel@tonic-gate 6515*0Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp2, VPP2, 6516*0Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 6517*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6518*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6519*0Sstevel@tonic-gate return (CS_BAD_VPP); 6520*0Sstevel@tonic-gate } 6521*0Sstevel@tonic-gate 6522*0Sstevel@tonic-gate if (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) 6523*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 6524*0Sstevel@tonic-gate else { 6525*0Sstevel@tonic-gate set_socket.IFType = IF_IO; 6526*0Sstevel@tonic-gate 6527*0Sstevel@tonic-gate /* 6528*0Sstevel@tonic-gate * The Cirrus Logic PD6710/672X/others? adapters will write 6529*0Sstevel@tonic-gate * protect the CIS if the socket is in MEMORY mode and the 6530*0Sstevel@tonic-gate * WP/IOCS16 pin is true. When this happens, the CIS registers 6531*0Sstevel@tonic-gate * will fail to be written. Go ahead and set the socket, 6532*0Sstevel@tonic-gate * even though the event mask isn't complete yet, so we can 6533*0Sstevel@tonic-gate * configure the adapter. Afterwards, set the socket again 6534*0Sstevel@tonic-gate * to make sure the event mask is correct. 6535*0Sstevel@tonic-gate */ 6536*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6537*0Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6538*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6539*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6540*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6541*0Sstevel@tonic-gate } 6542*0Sstevel@tonic-gate } 6543*0Sstevel@tonic-gate 6544*0Sstevel@tonic-gate if (cs_rc2_delay) 6545*0Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 6546*0Sstevel@tonic-gate 6547*0Sstevel@tonic-gate /* 6548*0Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 6549*0Sstevel@tonic-gate * registers. 6550*0Sstevel@tonic-gate */ 6551*0Sstevel@tonic-gate mutex_enter(&sp->lock); 6552*0Sstevel@tonic-gate client->config_regs_offset = cr->ConfigBase; 6553*0Sstevel@tonic-gate newoffset = client->config_regs_offset; 6554*0Sstevel@tonic-gate mutex_exit(&sp->lock); 6555*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6556*0Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 6557*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6558*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6559*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d can't init " 6560*0Sstevel@tonic-gate "CIS window\n", sp->socket_num); 6561*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 6562*0Sstevel@tonic-gate } 6563*0Sstevel@tonic-gate 6564*0Sstevel@tonic-gate /* 6565*0Sstevel@tonic-gate * Setup the config register pointers. 6566*0Sstevel@tonic-gate * Note that these pointers are not the complete virtual address; 6567*0Sstevel@tonic-gate * the complete address is constructed each time the registers 6568*0Sstevel@tonic-gate * are accessed. 6569*0Sstevel@tonic-gate */ 6570*0Sstevel@tonic-gate mutex_enter(&sp->lock); 6571*0Sstevel@tonic-gate crt = &client->config_regs; 6572*0Sstevel@tonic-gate client->present = cr->Present; 6573*0Sstevel@tonic-gate 6574*0Sstevel@tonic-gate bzero((char *)crt, sizeof (config_regs_t)); 6575*0Sstevel@tonic-gate 6576*0Sstevel@tonic-gate /* Configuration Option Register */ 6577*0Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6578*0Sstevel@tonic-gate crt->cor_p = (newoffset + CONFIG_OPTION_REG_OFFSET); 6579*0Sstevel@tonic-gate 6580*0Sstevel@tonic-gate /* Configuration and Status Register */ 6581*0Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) 6582*0Sstevel@tonic-gate crt->ccsr_p = (newoffset + CONFIG_STATUS_REG_OFFSET); 6583*0Sstevel@tonic-gate 6584*0Sstevel@tonic-gate /* Pin Replacement Register */ 6585*0Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) 6586*0Sstevel@tonic-gate crt->prr_p = (newoffset + CONFIG_PINREPL_REG_OFFSET); 6587*0Sstevel@tonic-gate 6588*0Sstevel@tonic-gate /* Socket and Copy Register */ 6589*0Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) 6590*0Sstevel@tonic-gate crt->scr_p = (newoffset + CONFIG_COPY_REG_OFFSET); 6591*0Sstevel@tonic-gate 6592*0Sstevel@tonic-gate /* Extended Status Register */ 6593*0Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) 6594*0Sstevel@tonic-gate crt->exstat_p = (newoffset + CONFIG_EXSTAT_REG_OFFSET); 6595*0Sstevel@tonic-gate 6596*0Sstevel@tonic-gate /* IO Base 0 Register */ 6597*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6598*0Sstevel@tonic-gate crt->iobase0_p = (newoffset + CONFIG_IOBASE0_REG_OFFSET); 6599*0Sstevel@tonic-gate 6600*0Sstevel@tonic-gate /* IO Base 1 Register */ 6601*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE1_REG_PRESENT) 6602*0Sstevel@tonic-gate crt->iobase1_p = (newoffset + CONFIG_IOBASE1_REG_OFFSET); 6603*0Sstevel@tonic-gate 6604*0Sstevel@tonic-gate /* IO Base 2 Register */ 6605*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE2_REG_PRESENT) 6606*0Sstevel@tonic-gate crt->iobase2_p = (newoffset + CONFIG_IOBASE2_REG_OFFSET); 6607*0Sstevel@tonic-gate 6608*0Sstevel@tonic-gate /* IO Base 3 Register */ 6609*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE3_REG_PRESENT) 6610*0Sstevel@tonic-gate crt->iobase3_p = (newoffset + CONFIG_IOBASE3_REG_OFFSET); 6611*0Sstevel@tonic-gate 6612*0Sstevel@tonic-gate /* IO Limit Register */ 6613*0Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) 6614*0Sstevel@tonic-gate crt->iolimit_p = (newoffset + CONFIG_IOLIMIT_REG_OFFSET); 6615*0Sstevel@tonic-gate 6616*0Sstevel@tonic-gate /* 6617*0Sstevel@tonic-gate * Setup the bits in the PRR mask that are valid; this is easy, just 6618*0Sstevel@tonic-gate * copy the Pin value that the client gave us. Note that for 6619*0Sstevel@tonic-gate * this to work, the client must set both of the XXX_STATUS 6620*0Sstevel@tonic-gate * and the XXX_EVENT bits in the Pin member. 6621*0Sstevel@tonic-gate */ 6622*0Sstevel@tonic-gate client->pin = cr->Pin; 6623*0Sstevel@tonic-gate 6624*0Sstevel@tonic-gate #ifdef CS_DEBUG 6625*0Sstevel@tonic-gate if (cs_debug > 128) 6626*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: client->pin 0x%x " 6627*0Sstevel@tonic-gate "client->config_regs_offset 0x%x newoffset 0x%x cor_p 0x%x " 6628*0Sstevel@tonic-gate "ccsr_p 0x%x prr_p 0x%x scr_p 0x%x\n", 6629*0Sstevel@tonic-gate client->pin, (int)client->config_regs_offset, newoffset, 6630*0Sstevel@tonic-gate (int)crt->cor_p, (int)crt->ccsr_p, (int)crt->prr_p, 6631*0Sstevel@tonic-gate (int)crt->scr_p); 6632*0Sstevel@tonic-gate #endif 6633*0Sstevel@tonic-gate 6634*0Sstevel@tonic-gate /* 6635*0Sstevel@tonic-gate * If the socket isn't in IO mode, WP is asserted, and we're going to 6636*0Sstevel@tonic-gate * write any of the config registers, issue a warning. 6637*0Sstevel@tonic-gate */ 6638*0Sstevel@tonic-gate if ((client->present != 0) && 6639*0Sstevel@tonic-gate (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) && 6640*0Sstevel@tonic-gate (get_socket.state & SBM_WP)) { 6641*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!cs_request_configuration: attempting to " 6642*0Sstevel@tonic-gate "write CIS config regs with WP set\n"); 6643*0Sstevel@tonic-gate } 6644*0Sstevel@tonic-gate 6645*0Sstevel@tonic-gate /* 6646*0Sstevel@tonic-gate * Write any configuration registers that the client tells us are 6647*0Sstevel@tonic-gate * present to the card; save a copy of what we wrote so that we 6648*0Sstevel@tonic-gate * can return them if the client calls GetConfigurationInfo. 6649*0Sstevel@tonic-gate * The order in which we write the configuration registers is 6650*0Sstevel@tonic-gate * specified by the PCMCIA spec; we must write the socket/copy 6651*0Sstevel@tonic-gate * register first (if it exists), and then we can write the 6652*0Sstevel@tonic-gate * registers in any arbitrary order. 6653*0Sstevel@tonic-gate */ 6654*0Sstevel@tonic-gate /* Socket and Copy Register */ 6655*0Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) { 6656*0Sstevel@tonic-gate crt->scr = cr->Copy; 6657*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->scr_p, crt->scr); 6658*0Sstevel@tonic-gate } 6659*0Sstevel@tonic-gate 6660*0Sstevel@tonic-gate /* Pin Replacement Register */ 6661*0Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 6662*0Sstevel@tonic-gate crt->prr = cr->Pin; 6663*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->prr_p, crt->prr); 6664*0Sstevel@tonic-gate } 6665*0Sstevel@tonic-gate 6666*0Sstevel@tonic-gate /* Configuration and Status Register */ 6667*0Sstevel@tonic-gate /* XXX should we set CCSR_SIG_CHG in the CCSR? XXX */ 6668*0Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) { 6669*0Sstevel@tonic-gate crt->ccsr = cr->Status; 6670*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->ccsr_p, crt->ccsr); 6671*0Sstevel@tonic-gate } 6672*0Sstevel@tonic-gate 6673*0Sstevel@tonic-gate /* Extended Status Register */ 6674*0Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) { 6675*0Sstevel@tonic-gate crt->exstat = cr->ExtendedStatus; 6676*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->exstat_p, crt->exstat); 6677*0Sstevel@tonic-gate } 6678*0Sstevel@tonic-gate 6679*0Sstevel@tonic-gate /* 6680*0Sstevel@tonic-gate * If any IO base and limit registers exist, and this client 6681*0Sstevel@tonic-gate * has done a RequestIO, setup the IO Base and IO Limit 6682*0Sstevel@tonic-gate * registers. 6683*0Sstevel@tonic-gate */ 6684*0Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 6685*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) { 6686*0Sstevel@tonic-gate uint32_t base = client->io_alloc.BasePort1.base; 6687*0Sstevel@tonic-gate uint32_t present = (client->present & 6688*0Sstevel@tonic-gate CONFIG_IOBASE_REG_MASK) >> 6689*0Sstevel@tonic-gate CONFIG_IOBASE_REG_SHIFT; 6690*0Sstevel@tonic-gate uint32_t reg = crt->iobase0_p; 6691*0Sstevel@tonic-gate 6692*0Sstevel@tonic-gate do { 6693*0Sstevel@tonic-gate csx_Put8(cis_handle, reg, base & 0x0ff); 6694*0Sstevel@tonic-gate reg = reg + 2; 6695*0Sstevel@tonic-gate base = base >> 8; 6696*0Sstevel@tonic-gate present = present >> 1; 6697*0Sstevel@tonic-gate } while (present); 6698*0Sstevel@tonic-gate } /* CONFIG_IOBASE0_REG_PRESENT */ 6699*0Sstevel@tonic-gate 6700*0Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) { 6701*0Sstevel@tonic-gate uint32_t np = client->io_alloc.NumPorts1 + 6702*0Sstevel@tonic-gate client->io_alloc.NumPorts2; 6703*0Sstevel@tonic-gate uint32_t limit, do_bit = 0; 6704*0Sstevel@tonic-gate int lm; 6705*0Sstevel@tonic-gate 6706*0Sstevel@tonic-gate limit = (IONUMPORTS_FROBNITZ(np) - 1); 6707*0Sstevel@tonic-gate 6708*0Sstevel@tonic-gate for (lm = 7; lm >= 0; lm--) { 6709*0Sstevel@tonic-gate if (limit & (1 << lm)) 6710*0Sstevel@tonic-gate do_bit = 1; 6711*0Sstevel@tonic-gate if (do_bit) 6712*0Sstevel@tonic-gate limit |= (1 << lm); 6713*0Sstevel@tonic-gate } /* for */ 6714*0Sstevel@tonic-gate 6715*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->iolimit_p, limit); 6716*0Sstevel@tonic-gate } /* CONFIG_IOLIMIT_REG_PRESENT */ 6717*0Sstevel@tonic-gate } /* REQ_IO_DONE */ 6718*0Sstevel@tonic-gate 6719*0Sstevel@tonic-gate /* 6720*0Sstevel@tonic-gate * Mark the socket as being in IO mode. 6721*0Sstevel@tonic-gate */ 6722*0Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) 6723*0Sstevel@tonic-gate sp->flags |= SOCKET_IS_IO; 6724*0Sstevel@tonic-gate 6725*0Sstevel@tonic-gate mutex_exit(&sp->lock); 6726*0Sstevel@tonic-gate 6727*0Sstevel@tonic-gate /* 6728*0Sstevel@tonic-gate * Enable the interrupt if needed 6729*0Sstevel@tonic-gate */ 6730*0Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6731*0Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 6732*0Sstevel@tonic-gate 6733*0Sstevel@tonic-gate /* 6734*0Sstevel@tonic-gate * Now that we know if the PRR is present and if it is, which 6735*0Sstevel@tonic-gate * bits in the PRR are valid, we can construct the correct 6736*0Sstevel@tonic-gate * socket event mask. 6737*0Sstevel@tonic-gate */ 6738*0Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6739*0Sstevel@tonic-gate 6740*0Sstevel@tonic-gate /* 6741*0Sstevel@tonic-gate * Configuration Option Register - we handle this specially since 6742*0Sstevel@tonic-gate * we don't allow the client to manipulate the RESET or 6743*0Sstevel@tonic-gate * INTERRUPT bits (although a client can manipulate these 6744*0Sstevel@tonic-gate * bits via an AccessConfigurationRegister call - explain 6745*0Sstevel@tonic-gate * THAT logic to me). 6746*0Sstevel@tonic-gate * XXX - we force level-mode interrupts (COR_LEVEL_IRQ) 6747*0Sstevel@tonic-gate * XXX - we always enable the function on a multi-function card 6748*0Sstevel@tonic-gate */ 6749*0Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 6750*0Sstevel@tonic-gate crt->cor = (cr->ConfigIndex & ~COR_SOFT_RESET) | COR_LEVEL_IRQ; 6751*0Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6752*0Sstevel@tonic-gate crt->cor |= COR_ENABLE_BASE_LIMIT; 6753*0Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6754*0Sstevel@tonic-gate crt->cor |= COR_ENABLE_FUNCTION; 6755*0Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 6756*0Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6757*0Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 6758*0Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 6759*0Sstevel@tonic-gate 6760*0Sstevel@tonic-gate #ifdef CS_DEBUG 6761*0Sstevel@tonic-gate if (cs_debug > 0) 6762*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration " 6763*0Sstevel@tonic-gate "cor=x%x ConfigIndex=x%x Attributes=x%x flags=x%x\n" 6764*0Sstevel@tonic-gate "present=x%x cis_handle=%p cor_p=x%x\n", 6765*0Sstevel@tonic-gate crt->cor, cr->ConfigIndex, cr->Attributes, sp->cis_flags, 6766*0Sstevel@tonic-gate client->present, cis_handle, crt->cor_p); 6767*0Sstevel@tonic-gate #endif 6768*0Sstevel@tonic-gate 6769*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 6770*0Sstevel@tonic-gate } /* CONFIG_OPTION_REG_PRESENT */ 6771*0Sstevel@tonic-gate 6772*0Sstevel@tonic-gate if (cs_rc1_delay) 6773*0Sstevel@tonic-gate drv_usecwait(cs_rc1_delay * 1000); 6774*0Sstevel@tonic-gate 6775*0Sstevel@tonic-gate /* 6776*0Sstevel@tonic-gate * Set the socket to the parameters that the client requested. 6777*0Sstevel@tonic-gate */ 6778*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6779*0Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 6780*0Sstevel@tonic-gate crt->cor = 0; /* XXX is 0 the right thing here? */ 6781*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 6782*0Sstevel@tonic-gate } 6783*0Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6784*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6785*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6786*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6787*0Sstevel@tonic-gate } 6788*0Sstevel@tonic-gate 6789*0Sstevel@tonic-gate if (cs_rc2_delay) 6790*0Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 6791*0Sstevel@tonic-gate 6792*0Sstevel@tonic-gate /* 6793*0Sstevel@tonic-gate * Mark this client as having done a successful RequestConfiguration 6794*0Sstevel@tonic-gate * call. 6795*0Sstevel@tonic-gate */ 6796*0Sstevel@tonic-gate client->flags |= REQ_CONFIGURATION_DONE; 6797*0Sstevel@tonic-gate 6798*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6799*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6800*0Sstevel@tonic-gate 6801*0Sstevel@tonic-gate return (CS_SUCCESS); 6802*0Sstevel@tonic-gate } 6803*0Sstevel@tonic-gate 6804*0Sstevel@tonic-gate /* 6805*0Sstevel@tonic-gate * cs_release_configuration - releases configuration previously set via the 6806*0Sstevel@tonic-gate * RequestConfiguration call; this is ReleaseConfiguration 6807*0Sstevel@tonic-gate * 6808*0Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully released 6809*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6810*0Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6811*0Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 6812*0Sstevel@tonic-gate */ 6813*0Sstevel@tonic-gate /*ARGSUSED*/ 6814*0Sstevel@tonic-gate static int 6815*0Sstevel@tonic-gate cs_release_configuration(client_handle_t client_handle, release_config_t *rcfg) 6816*0Sstevel@tonic-gate { 6817*0Sstevel@tonic-gate cs_socket_t *sp; 6818*0Sstevel@tonic-gate client_t *client; 6819*0Sstevel@tonic-gate volatile config_regs_t *crt; 6820*0Sstevel@tonic-gate set_socket_t set_socket; 6821*0Sstevel@tonic-gate get_socket_t get_socket; 6822*0Sstevel@tonic-gate acc_handle_t cis_handle; 6823*0Sstevel@tonic-gate int error; 6824*0Sstevel@tonic-gate uint32_t newoffset; 6825*0Sstevel@tonic-gate int client_lock_acquired; 6826*0Sstevel@tonic-gate 6827*0Sstevel@tonic-gate /* 6828*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6829*0Sstevel@tonic-gate * is, we don't support SS using this call. 6830*0Sstevel@tonic-gate */ 6831*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6832*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6833*0Sstevel@tonic-gate 6834*0Sstevel@tonic-gate /* 6835*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6836*0Sstevel@tonic-gate */ 6837*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6838*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6839*0Sstevel@tonic-gate 6840*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6841*0Sstevel@tonic-gate 6842*0Sstevel@tonic-gate /* 6843*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 6844*0Sstevel@tonic-gate */ 6845*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6846*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6847*0Sstevel@tonic-gate return (error); 6848*0Sstevel@tonic-gate } 6849*0Sstevel@tonic-gate 6850*0Sstevel@tonic-gate /* 6851*0Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 6852*0Sstevel@tonic-gate * this call. 6853*0Sstevel@tonic-gate */ 6854*0Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 6855*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6856*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 6857*0Sstevel@tonic-gate } 6858*0Sstevel@tonic-gate 6859*0Sstevel@tonic-gate #ifdef CS_DEBUG 6860*0Sstevel@tonic-gate if (cs_debug > 0) 6861*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: " 6862*0Sstevel@tonic-gate "flags=0x%x CW_MULTI_FUNCTION_CIS =0x%x \n", 6863*0Sstevel@tonic-gate sp->cis_flags, CW_MULTI_FUNCTION_CIS); 6864*0Sstevel@tonic-gate 6865*0Sstevel@tonic-gate #endif 6866*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 6867*0Sstevel@tonic-gate 6868*0Sstevel@tonic-gate /* 6869*0Sstevel@tonic-gate * Set the card back to a memory-only interface byte writing a zero 6870*0Sstevel@tonic-gate * to the COR. Note that we don't update our soft copy of the 6871*0Sstevel@tonic-gate * COR state since the PCMCIA spec only requires us to maintain 6872*0Sstevel@tonic-gate * the last value that was written to that register during a 6873*0Sstevel@tonic-gate * call to RequestConfiguration. 6874*0Sstevel@tonic-gate */ 6875*0Sstevel@tonic-gate crt = &client->config_regs; 6876*0Sstevel@tonic-gate 6877*0Sstevel@tonic-gate newoffset = client->config_regs_offset; 6878*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6879*0Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 6880*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6881*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6882*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: socket %d can't init " 6883*0Sstevel@tonic-gate "CIS window\n", sp->socket_num); 6884*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 6885*0Sstevel@tonic-gate } 6886*0Sstevel@tonic-gate 6887*0Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6888*0Sstevel@tonic-gate /* 6889*0Sstevel@tonic-gate * For the Multifunction cards do not reset the socket 6890*0Sstevel@tonic-gate * to a memory only interface but do clear the 6891*0Sstevel@tonic-gate * Configuration Option Register and mark this client 6892*0Sstevel@tonic-gate * as not having a configuration by clearing the 6893*0Sstevel@tonic-gate * REQ_CONFIGURATION_DONE flag. 6894*0Sstevel@tonic-gate */ 6895*0Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 6896*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 6897*0Sstevel@tonic-gate 6898*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6899*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6900*0Sstevel@tonic-gate return (CS_SUCCESS); 6901*0Sstevel@tonic-gate } 6902*0Sstevel@tonic-gate 6903*0Sstevel@tonic-gate /* 6904*0Sstevel@tonic-gate * Set the socket back to a memory-only interface; don't change 6905*0Sstevel@tonic-gate * any other parameter of the socket. 6906*0Sstevel@tonic-gate */ 6907*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 6908*0Sstevel@tonic-gate 6909*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6910*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6911*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6912*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6913*0Sstevel@tonic-gate } 6914*0Sstevel@tonic-gate 6915*0Sstevel@tonic-gate mutex_enter(&sp->lock); 6916*0Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6917*0Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6918*0Sstevel@tonic-gate mutex_exit(&sp->lock); 6919*0Sstevel@tonic-gate 6920*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 6921*0Sstevel@tonic-gate set_socket.IREQRouting = 0; 6922*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 6923*0Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 6924*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 6925*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 6926*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 6927*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 6928*0Sstevel@tonic-gate 6929*0Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 6930*0Sstevel@tonic-gate /* 6931*0Sstevel@tonic-gate * Some adapters (PD67xx) can write-protect the CIS when the 6932*0Sstevel@tonic-gate * socket is in memory mode 6933*0Sstevel@tonic-gate */ 6934*0Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6935*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, COR_SOFT_RESET); 6936*0Sstevel@tonic-gate 6937*0Sstevel@tonic-gate if (cs_rq_delay) 6938*0Sstevel@tonic-gate drv_usecwait(cs_rq_delay * 1000); 6939*0Sstevel@tonic-gate #endif 6940*0Sstevel@tonic-gate 6941*0Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6942*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 6943*0Sstevel@tonic-gate 6944*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6945*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6946*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6947*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6948*0Sstevel@tonic-gate } 6949*0Sstevel@tonic-gate 6950*0Sstevel@tonic-gate /* 6951*0Sstevel@tonic-gate * Mark this client as not having a configuration. 6952*0Sstevel@tonic-gate */ 6953*0Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 6954*0Sstevel@tonic-gate 6955*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6956*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6957*0Sstevel@tonic-gate 6958*0Sstevel@tonic-gate return (CS_SUCCESS); 6959*0Sstevel@tonic-gate } 6960*0Sstevel@tonic-gate 6961*0Sstevel@tonic-gate /* 6962*0Sstevel@tonic-gate * cs_modify_configuration - modifies a configuration established by 6963*0Sstevel@tonic-gate * RequestConfiguration; this is ModifyConfiguration 6964*0Sstevel@tonic-gate * 6965*0Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully modified 6966*0Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6967*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6968*0Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 6969*0Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 6970*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6971*0Sstevel@tonic-gate * are set 6972*0Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 6973*0Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6974*0Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6975*0Sstevel@tonic-gate */ 6976*0Sstevel@tonic-gate static int 6977*0Sstevel@tonic-gate cs_modify_configuration(client_handle_t client_handle, modify_config_t *mc) 6978*0Sstevel@tonic-gate { 6979*0Sstevel@tonic-gate cs_socket_t *sp; 6980*0Sstevel@tonic-gate client_t *client; 6981*0Sstevel@tonic-gate set_socket_t set_socket; 6982*0Sstevel@tonic-gate get_socket_t get_socket; 6983*0Sstevel@tonic-gate int error; 6984*0Sstevel@tonic-gate int client_lock_acquired; 6985*0Sstevel@tonic-gate 6986*0Sstevel@tonic-gate /* 6987*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6988*0Sstevel@tonic-gate * is, we don't support SS using this call. 6989*0Sstevel@tonic-gate */ 6990*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6991*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6992*0Sstevel@tonic-gate 6993*0Sstevel@tonic-gate /* 6994*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6995*0Sstevel@tonic-gate */ 6996*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6997*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 6998*0Sstevel@tonic-gate 6999*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7000*0Sstevel@tonic-gate 7001*0Sstevel@tonic-gate /* 7002*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 7003*0Sstevel@tonic-gate */ 7004*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7005*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7006*0Sstevel@tonic-gate return (error); 7007*0Sstevel@tonic-gate } 7008*0Sstevel@tonic-gate 7009*0Sstevel@tonic-gate /* 7010*0Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 7011*0Sstevel@tonic-gate * this call. 7012*0Sstevel@tonic-gate */ 7013*0Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7014*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7015*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 7016*0Sstevel@tonic-gate } 7017*0Sstevel@tonic-gate 7018*0Sstevel@tonic-gate /* 7019*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7020*0Sstevel@tonic-gate * for this client, then return an error. 7021*0Sstevel@tonic-gate */ 7022*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7023*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7024*0Sstevel@tonic-gate return (CS_NO_CARD); 7025*0Sstevel@tonic-gate } 7026*0Sstevel@tonic-gate 7027*0Sstevel@tonic-gate /* 7028*0Sstevel@tonic-gate * Get the current socket parameters so that we can modify them. 7029*0Sstevel@tonic-gate */ 7030*0Sstevel@tonic-gate get_socket.socket = sp->socket_num; 7031*0Sstevel@tonic-gate 7032*0Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 7033*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7034*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7035*0Sstevel@tonic-gate } 7036*0Sstevel@tonic-gate 7037*0Sstevel@tonic-gate #ifdef CS_DEBUG 7038*0Sstevel@tonic-gate if (cs_debug > 0) 7039*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration: socket %d " 7040*0Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 7041*0Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 7042*0Sstevel@tonic-gate sp->socket_num, (int)client->irq_alloc.irq, 7043*0Sstevel@tonic-gate get_socket.IRQRouting); 7044*0Sstevel@tonic-gate #endif 7045*0Sstevel@tonic-gate 7046*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 7047*0Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 7048*0Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 7049*0Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 7050*0Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 7051*0Sstevel@tonic-gate 7052*0Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 7053*0Sstevel@tonic-gate 7054*0Sstevel@tonic-gate /* 7055*0Sstevel@tonic-gate * Modify the IRQ routing if the client wants it modified. 7056*0Sstevel@tonic-gate */ 7057*0Sstevel@tonic-gate if (mc->Attributes & CONF_IRQ_CHANGE_VALID) { 7058*0Sstevel@tonic-gate set_socket.IREQRouting &= ~IRQ_ENABLE; 7059*0Sstevel@tonic-gate 7060*0Sstevel@tonic-gate if ((sp->cis_flags & CW_MULTI_FUNCTION_CIS) && 7061*0Sstevel@tonic-gate (client->present & CONFIG_OPTION_REG_PRESENT)) { 7062*0Sstevel@tonic-gate config_regs_t *crt = &client->config_regs; 7063*0Sstevel@tonic-gate acc_handle_t cis_handle; 7064*0Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 7065*0Sstevel@tonic-gate 7066*0Sstevel@tonic-gate /* 7067*0Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 7068*0Sstevel@tonic-gate * registers. 7069*0Sstevel@tonic-gate */ 7070*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7071*0Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 7072*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7073*0Sstevel@tonic-gate cmn_err(CE_CONT, 7074*0Sstevel@tonic-gate "cs_modify_configuration: socket %d can't init " 7075*0Sstevel@tonic-gate "CIS window\n", sp->socket_num); 7076*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 7077*0Sstevel@tonic-gate } /* cs_init_cis_window */ 7078*0Sstevel@tonic-gate 7079*0Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 7080*0Sstevel@tonic-gate 7081*0Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7082*0Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 7083*0Sstevel@tonic-gate 7084*0Sstevel@tonic-gate #ifdef CS_DEBUG 7085*0Sstevel@tonic-gate if (cs_debug > 0) 7086*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration:" 7087*0Sstevel@tonic-gate " cor_p=0x%x cor=0x%x\n", 7088*0Sstevel@tonic-gate crt->cor_p, crt->cor); 7089*0Sstevel@tonic-gate #endif 7090*0Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 7091*0Sstevel@tonic-gate 7092*0Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 7093*0Sstevel@tonic-gate 7094*0Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7095*0Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 7096*0Sstevel@tonic-gate 7097*0Sstevel@tonic-gate } /* CONF_IRQ_CHANGE_VALID */ 7098*0Sstevel@tonic-gate 7099*0Sstevel@tonic-gate /* 7100*0Sstevel@tonic-gate * Modify the voltage levels that the client specifies. 7101*0Sstevel@tonic-gate */ 7102*0Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 7103*0Sstevel@tonic-gate 7104*0Sstevel@tonic-gate if (mc->Attributes & CONF_VPP1_CHANGE_VALID) { 7105*0Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp1, VPP1, 7106*0Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 7107*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7108*0Sstevel@tonic-gate return (CS_BAD_VPP); 7109*0Sstevel@tonic-gate } 7110*0Sstevel@tonic-gate } else { 7111*0Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 7112*0Sstevel@tonic-gate } 7113*0Sstevel@tonic-gate 7114*0Sstevel@tonic-gate if (mc->Attributes & CONF_VPP2_CHANGE_VALID) { 7115*0Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp2, VPP2, 7116*0Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 7117*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7118*0Sstevel@tonic-gate return (CS_BAD_VPP); 7119*0Sstevel@tonic-gate } 7120*0Sstevel@tonic-gate } else { 7121*0Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 7122*0Sstevel@tonic-gate } 7123*0Sstevel@tonic-gate 7124*0Sstevel@tonic-gate /* 7125*0Sstevel@tonic-gate * Setup the modified socket configuration. 7126*0Sstevel@tonic-gate */ 7127*0Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 7128*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7129*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7130*0Sstevel@tonic-gate } 7131*0Sstevel@tonic-gate 7132*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7133*0Sstevel@tonic-gate return (CS_SUCCESS); 7134*0Sstevel@tonic-gate } 7135*0Sstevel@tonic-gate 7136*0Sstevel@tonic-gate /* 7137*0Sstevel@tonic-gate * cs_access_configuration_register - provides a client access to the card's 7138*0Sstevel@tonic-gate * configuration registers; this is AccessConfigurationRegister 7139*0Sstevel@tonic-gate * 7140*0Sstevel@tonic-gate * returns: CS_SUCCESS - if register accessed successfully 7141*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7142*0Sstevel@tonic-gate * CS_BAD_ARGS - if arguments are out of range 7143*0Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 7144*0Sstevel@tonic-gate * CS_BAD_BASE - if no config registers base address 7145*0Sstevel@tonic-gate * CS_UNSUPPORTED_MODE - if no RequestConfiguration has 7146*0Sstevel@tonic-gate * been done yet 7147*0Sstevel@tonic-gate */ 7148*0Sstevel@tonic-gate static int 7149*0Sstevel@tonic-gate cs_access_configuration_register(client_handle_t client_handle, 7150*0Sstevel@tonic-gate access_config_reg_t *acr) 7151*0Sstevel@tonic-gate { 7152*0Sstevel@tonic-gate cs_socket_t *sp; 7153*0Sstevel@tonic-gate client_t *client; 7154*0Sstevel@tonic-gate acc_handle_t cis_handle; 7155*0Sstevel@tonic-gate int error; 7156*0Sstevel@tonic-gate uint32_t newoffset; 7157*0Sstevel@tonic-gate int client_lock_acquired; 7158*0Sstevel@tonic-gate 7159*0Sstevel@tonic-gate /* 7160*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 7161*0Sstevel@tonic-gate * is, we don't support SS using this call. 7162*0Sstevel@tonic-gate */ 7163*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 7164*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 7165*0Sstevel@tonic-gate 7166*0Sstevel@tonic-gate /* 7167*0Sstevel@tonic-gate * Make sure that the specifed offset is in range. 7168*0Sstevel@tonic-gate */ 7169*0Sstevel@tonic-gate if (acr->Offset > ((CISTPL_CONFIG_MAX_CONFIG_REGS * 2) - 2)) 7170*0Sstevel@tonic-gate return (CS_BAD_ARGS); 7171*0Sstevel@tonic-gate 7172*0Sstevel@tonic-gate /* 7173*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7174*0Sstevel@tonic-gate */ 7175*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7176*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7177*0Sstevel@tonic-gate 7178*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7179*0Sstevel@tonic-gate 7180*0Sstevel@tonic-gate /* 7181*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 7182*0Sstevel@tonic-gate */ 7183*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7184*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7185*0Sstevel@tonic-gate return (error); 7186*0Sstevel@tonic-gate } 7187*0Sstevel@tonic-gate 7188*0Sstevel@tonic-gate /* 7189*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7190*0Sstevel@tonic-gate * for this client, then return an error. 7191*0Sstevel@tonic-gate */ 7192*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7193*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7194*0Sstevel@tonic-gate return (CS_NO_CARD); 7195*0Sstevel@tonic-gate } 7196*0Sstevel@tonic-gate 7197*0Sstevel@tonic-gate /* 7198*0Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 7199*0Sstevel@tonic-gate * this call. 7200*0Sstevel@tonic-gate */ 7201*0Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7202*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7203*0Sstevel@tonic-gate return (CS_UNSUPPORTED_MODE); 7204*0Sstevel@tonic-gate } 7205*0Sstevel@tonic-gate 7206*0Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 7207*0Sstevel@tonic-gate 7208*0Sstevel@tonic-gate /* 7209*0Sstevel@tonic-gate * Get a pointer to the CIS window 7210*0Sstevel@tonic-gate */ 7211*0Sstevel@tonic-gate newoffset = client->config_regs_offset + acr->Offset; 7212*0Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7213*0Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 7214*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 7215*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7216*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: socket %d can't init CIS window\n", 7217*0Sstevel@tonic-gate sp->socket_num); 7218*0Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 7219*0Sstevel@tonic-gate } 7220*0Sstevel@tonic-gate 7221*0Sstevel@tonic-gate /* 7222*0Sstevel@tonic-gate * Create the address for the config register that the client 7223*0Sstevel@tonic-gate * wants to access. 7224*0Sstevel@tonic-gate */ 7225*0Sstevel@tonic-gate mutex_enter(&sp->lock); 7226*0Sstevel@tonic-gate 7227*0Sstevel@tonic-gate #ifdef CS_DEBUG 7228*0Sstevel@tonic-gate if (cs_debug > 1) { 7229*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: config_regs_offset 0x%x " 7230*0Sstevel@tonic-gate "Offset 0x%x newoffset 0x%x\n", 7231*0Sstevel@tonic-gate (int)client->config_regs_offset, 7232*0Sstevel@tonic-gate (int)acr->Offset, newoffset); 7233*0Sstevel@tonic-gate } 7234*0Sstevel@tonic-gate #endif 7235*0Sstevel@tonic-gate 7236*0Sstevel@tonic-gate /* 7237*0Sstevel@tonic-gate * Determine what the client wants us to do. The client is 7238*0Sstevel@tonic-gate * allowed to specify any valid offset, even if it would 7239*0Sstevel@tonic-gate * cause an unimplemented configuration register to be 7240*0Sstevel@tonic-gate * accessed. 7241*0Sstevel@tonic-gate */ 7242*0Sstevel@tonic-gate error = CS_SUCCESS; 7243*0Sstevel@tonic-gate switch (acr->Action) { 7244*0Sstevel@tonic-gate case CONFIG_REG_READ: 7245*0Sstevel@tonic-gate acr->Value = csx_Get8(cis_handle, newoffset); 7246*0Sstevel@tonic-gate break; 7247*0Sstevel@tonic-gate case CONFIG_REG_WRITE: 7248*0Sstevel@tonic-gate csx_Put8(cis_handle, newoffset, acr->Value); 7249*0Sstevel@tonic-gate break; 7250*0Sstevel@tonic-gate default: 7251*0Sstevel@tonic-gate error = CS_BAD_ARGS; 7252*0Sstevel@tonic-gate break; 7253*0Sstevel@tonic-gate } /* switch */ 7254*0Sstevel@tonic-gate 7255*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7256*0Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 7257*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7258*0Sstevel@tonic-gate 7259*0Sstevel@tonic-gate return (error); 7260*0Sstevel@tonic-gate } 7261*0Sstevel@tonic-gate 7262*0Sstevel@tonic-gate /* 7263*0Sstevel@tonic-gate * ==== RESET and general info functions ==== 7264*0Sstevel@tonic-gate */ 7265*0Sstevel@tonic-gate 7266*0Sstevel@tonic-gate /* 7267*0Sstevel@tonic-gate * cs_reset_function - RESET the requested function on the card; this 7268*0Sstevel@tonic-gate * is ResetFunction 7269*0Sstevel@tonic-gate * 7270*0Sstevel@tonic-gate * Note: We don't support this functionality yet, and the standard 7271*0Sstevel@tonic-gate * says it's OK to reutrn CS_IN_USE if we can't do this 7272*0Sstevel@tonic-gate * operation. 7273*0Sstevel@tonic-gate */ 7274*0Sstevel@tonic-gate /*ARGSUSED*/ 7275*0Sstevel@tonic-gate static int 7276*0Sstevel@tonic-gate cs_reset_function(client_handle_t ch, reset_function_t *rf) 7277*0Sstevel@tonic-gate { 7278*0Sstevel@tonic-gate return (CS_IN_USE); 7279*0Sstevel@tonic-gate } 7280*0Sstevel@tonic-gate 7281*0Sstevel@tonic-gate /* 7282*0Sstevel@tonic-gate * cs_get_configuration_info - return configuration info for the passed 7283*0Sstevel@tonic-gate * socket and function number to the caller; 7284*0Sstevel@tonic-gate * this is GetConfigurationInfo 7285*0Sstevel@tonic-gate */ 7286*0Sstevel@tonic-gate /*ARGSUSED*/ 7287*0Sstevel@tonic-gate static int 7288*0Sstevel@tonic-gate cs_get_configuration_info(client_handle_t *chp, get_configuration_info_t *gci) 7289*0Sstevel@tonic-gate { 7290*0Sstevel@tonic-gate cs_socket_t *sp; 7291*0Sstevel@tonic-gate uint32_t fn; 7292*0Sstevel@tonic-gate client_t *client; 7293*0Sstevel@tonic-gate int client_lock_acquired; 7294*0Sstevel@tonic-gate 7295*0Sstevel@tonic-gate /* 7296*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7297*0Sstevel@tonic-gate */ 7298*0Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gci->Socket))) == NULL) 7299*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7300*0Sstevel@tonic-gate 7301*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7302*0Sstevel@tonic-gate mutex_enter(&sp->lock); 7303*0Sstevel@tonic-gate 7304*0Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(gci->Socket); 7305*0Sstevel@tonic-gate 7306*0Sstevel@tonic-gate client = sp->client_list; 7307*0Sstevel@tonic-gate while (client) { 7308*0Sstevel@tonic-gate 7309*0Sstevel@tonic-gate if (GET_CLIENT_FUNCTION(client->client_handle) == fn) { 7310*0Sstevel@tonic-gate 7311*0Sstevel@tonic-gate /* 7312*0Sstevel@tonic-gate * If there's no card in the socket or the card in the 7313*0Sstevel@tonic-gate * socket is not for this client, then return 7314*0Sstevel@tonic-gate * an error. 7315*0Sstevel@tonic-gate */ 7316*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7317*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7318*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7319*0Sstevel@tonic-gate return (CS_NO_CARD); 7320*0Sstevel@tonic-gate } 7321*0Sstevel@tonic-gate 7322*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7323*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7324*0Sstevel@tonic-gate return (CS_SUCCESS); 7325*0Sstevel@tonic-gate 7326*0Sstevel@tonic-gate } /* GET_CLIENT_FUNCTION == fn */ 7327*0Sstevel@tonic-gate 7328*0Sstevel@tonic-gate client = client->next; 7329*0Sstevel@tonic-gate } /* while (client) */ 7330*0Sstevel@tonic-gate 7331*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7332*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7333*0Sstevel@tonic-gate 7334*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7335*0Sstevel@tonic-gate } 7336*0Sstevel@tonic-gate 7337*0Sstevel@tonic-gate /* 7338*0Sstevel@tonic-gate * cs_get_cardservices_info - return info about Card Services to the 7339*0Sstevel@tonic-gate * caller; this is GetCardServicesInfo 7340*0Sstevel@tonic-gate */ 7341*0Sstevel@tonic-gate /*ARGSUSED*/ 7342*0Sstevel@tonic-gate static int 7343*0Sstevel@tonic-gate cs_get_cardservices_info(client_handle_t ch, get_cardservices_info_t *gcsi) 7344*0Sstevel@tonic-gate { 7345*0Sstevel@tonic-gate gcsi->Signature[0] = 'C'; 7346*0Sstevel@tonic-gate gcsi->Signature[1] = 'S'; 7347*0Sstevel@tonic-gate gcsi->NumSockets = cs_globals.num_sockets; 7348*0Sstevel@tonic-gate gcsi->Revision = CS_INTERNAL_REVISION_LEVEL; 7349*0Sstevel@tonic-gate gcsi->CSLevel = CS_VERSION; 7350*0Sstevel@tonic-gate gcsi->FuncsPerSocket = CIS_MAX_FUNCTIONS; 7351*0Sstevel@tonic-gate (void) strncpy(gcsi->VendorString, 7352*0Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_VENDOR_STRING, 7353*0Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_MAX_VS_LEN); 7354*0Sstevel@tonic-gate 7355*0Sstevel@tonic-gate return (CS_SUCCESS); 7356*0Sstevel@tonic-gate } 7357*0Sstevel@tonic-gate 7358*0Sstevel@tonic-gate /* 7359*0Sstevel@tonic-gate * cs_get_physical_adapter_info - returns information about the requested 7360*0Sstevel@tonic-gate * physical adapter; this is 7361*0Sstevel@tonic-gate * GetPhysicalAdapterInfo 7362*0Sstevel@tonic-gate * 7363*0Sstevel@tonic-gate * calling: client_handle_t: 7364*0Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 7365*0Sstevel@tonic-gate * to specify logical socket number 7366*0Sstevel@tonic-gate * !NULL - extract logical socket number from 7367*0Sstevel@tonic-gate * client_handle_t 7368*0Sstevel@tonic-gate * 7369*0Sstevel@tonic-gate * returns: CS_SUCCESS 7370*0Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7371*0Sstevel@tonic-gate * socket number is specified in 7372*0Sstevel@tonic-gate * map_log_socket_t->LogSocket 7373*0Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7374*0Sstevel@tonic-gate * client handle is specified 7375*0Sstevel@tonic-gate */ 7376*0Sstevel@tonic-gate static int 7377*0Sstevel@tonic-gate cs_get_physical_adapter_info(client_handle_t ch, 7378*0Sstevel@tonic-gate get_physical_adapter_info_t *gpai) 7379*0Sstevel@tonic-gate { 7380*0Sstevel@tonic-gate cs_socket_t *sp; 7381*0Sstevel@tonic-gate int client_lock_acquired; 7382*0Sstevel@tonic-gate 7383*0Sstevel@tonic-gate if (ch == NULL) 7384*0Sstevel@tonic-gate gpai->PhySocket = CS_GET_SOCKET_NUMBER(gpai->LogSocket); 7385*0Sstevel@tonic-gate else 7386*0Sstevel@tonic-gate gpai->PhySocket = GET_CLIENT_SOCKET(ch); 7387*0Sstevel@tonic-gate 7388*0Sstevel@tonic-gate /* 7389*0Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 7390*0Sstevel@tonic-gate */ 7391*0Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gpai->PhySocket))) == NULL) 7392*0Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7393*0Sstevel@tonic-gate 7394*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7395*0Sstevel@tonic-gate 7396*0Sstevel@tonic-gate /* 7397*0Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 7398*0Sstevel@tonic-gate */ 7399*0Sstevel@tonic-gate if (ch != NULL) { 7400*0Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 7401*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7402*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 7403*0Sstevel@tonic-gate } /* cs_find_client */ 7404*0Sstevel@tonic-gate } /* ch != NULL */ 7405*0Sstevel@tonic-gate 7406*0Sstevel@tonic-gate gpai->flags = sp->adapter.flags; 7407*0Sstevel@tonic-gate (void) strcpy(gpai->name, sp->adapter.name); 7408*0Sstevel@tonic-gate gpai->major = sp->adapter.major; 7409*0Sstevel@tonic-gate gpai->minor = sp->adapter.minor; 7410*0Sstevel@tonic-gate gpai->instance = sp->adapter.instance; 7411*0Sstevel@tonic-gate gpai->number = sp->adapter.number; 7412*0Sstevel@tonic-gate gpai->num_sockets = sp->adapter.num_sockets; 7413*0Sstevel@tonic-gate gpai->first_socket = sp->adapter.first_socket; 7414*0Sstevel@tonic-gate 7415*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7416*0Sstevel@tonic-gate 7417*0Sstevel@tonic-gate return (CS_SUCCESS); 7418*0Sstevel@tonic-gate } 7419*0Sstevel@tonic-gate 7420*0Sstevel@tonic-gate /* 7421*0Sstevel@tonic-gate * ==== general functions ==== 7422*0Sstevel@tonic-gate */ 7423*0Sstevel@tonic-gate 7424*0Sstevel@tonic-gate /* 7425*0Sstevel@tonic-gate * cs_map_log_socket - returns the physical socket number associated with 7426*0Sstevel@tonic-gate * either the passed client handle or the passed 7427*0Sstevel@tonic-gate * logical socket number; this is MapLogSocket 7428*0Sstevel@tonic-gate * 7429*0Sstevel@tonic-gate * calling: client_handle_t: 7430*0Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 7431*0Sstevel@tonic-gate * to specify logical socket number 7432*0Sstevel@tonic-gate * !NULL - extract logical socket number from 7433*0Sstevel@tonic-gate * client_handle_t 7434*0Sstevel@tonic-gate * 7435*0Sstevel@tonic-gate * returns: CS_SUCCESS 7436*0Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7437*0Sstevel@tonic-gate * socket number is specified in 7438*0Sstevel@tonic-gate * map_log_socket_t->LogSocket 7439*0Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7440*0Sstevel@tonic-gate * client handle is specified 7441*0Sstevel@tonic-gate * 7442*0Sstevel@tonic-gate * Note: We provide this function since the instance number of a client 7443*0Sstevel@tonic-gate * driver doesn't necessary correspond to the physical 7444*0Sstevel@tonic-gate * socket number 7445*0Sstevel@tonic-gate */ 7446*0Sstevel@tonic-gate static int 7447*0Sstevel@tonic-gate cs_map_log_socket(client_handle_t ch, map_log_socket_t *mls) 7448*0Sstevel@tonic-gate { 7449*0Sstevel@tonic-gate cs_socket_t *sp; 7450*0Sstevel@tonic-gate int client_lock_acquired; 7451*0Sstevel@tonic-gate 7452*0Sstevel@tonic-gate if (ch == NULL) 7453*0Sstevel@tonic-gate mls->PhySocket = CS_GET_SOCKET_NUMBER(mls->LogSocket); 7454*0Sstevel@tonic-gate else 7455*0Sstevel@tonic-gate mls->PhySocket = GET_CLIENT_SOCKET(ch); 7456*0Sstevel@tonic-gate 7457*0Sstevel@tonic-gate /* 7458*0Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 7459*0Sstevel@tonic-gate */ 7460*0Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(mls->PhySocket))) == NULL) 7461*0Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7462*0Sstevel@tonic-gate 7463*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7464*0Sstevel@tonic-gate 7465*0Sstevel@tonic-gate /* 7466*0Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 7467*0Sstevel@tonic-gate */ 7468*0Sstevel@tonic-gate if (ch != NULL) { 7469*0Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 7470*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7471*0Sstevel@tonic-gate return (CS_BAD_HANDLE); 7472*0Sstevel@tonic-gate } /* cs_find_client */ 7473*0Sstevel@tonic-gate } /* ch != NULL */ 7474*0Sstevel@tonic-gate 7475*0Sstevel@tonic-gate mls->PhyAdapter = sp->adapter.number; 7476*0Sstevel@tonic-gate 7477*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7478*0Sstevel@tonic-gate 7479*0Sstevel@tonic-gate return (CS_SUCCESS); 7480*0Sstevel@tonic-gate } 7481*0Sstevel@tonic-gate 7482*0Sstevel@tonic-gate /* 7483*0Sstevel@tonic-gate * cs_convert_speed - convers nS to devspeed and devspeed to nS 7484*0Sstevel@tonic-gate * 7485*0Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 7486*0Sstevel@tonic-gate * is only a wrapper. 7487*0Sstevel@tonic-gate */ 7488*0Sstevel@tonic-gate static int 7489*0Sstevel@tonic-gate cs_convert_speed(convert_speed_t *cs) 7490*0Sstevel@tonic-gate { 7491*0Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSPEED, cs)); 7492*0Sstevel@tonic-gate } 7493*0Sstevel@tonic-gate 7494*0Sstevel@tonic-gate /* 7495*0Sstevel@tonic-gate * cs_convert_size - converts a devsize value to a size in bytes value 7496*0Sstevel@tonic-gate * or a size in bytes value to a devsize value 7497*0Sstevel@tonic-gate * 7498*0Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 7499*0Sstevel@tonic-gate * is only a wrapper. 7500*0Sstevel@tonic-gate */ 7501*0Sstevel@tonic-gate static int 7502*0Sstevel@tonic-gate cs_convert_size(convert_size_t *cs) 7503*0Sstevel@tonic-gate { 7504*0Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSIZE, cs)); 7505*0Sstevel@tonic-gate } 7506*0Sstevel@tonic-gate 7507*0Sstevel@tonic-gate /* 7508*0Sstevel@tonic-gate * cs_convert_powerlevel - converts a power level in tenths of a volt 7509*0Sstevel@tonic-gate * to a power table entry for the specified socket 7510*0Sstevel@tonic-gate * 7511*0Sstevel@tonic-gate * returns: CS_SUCCESS - if volts converted to a valid power level 7512*0Sstevel@tonic-gate * CS_BAD_ADAPTER - if SS_InquireAdapter fails 7513*0Sstevel@tonic-gate * CS_BAD_ARGS - if volts are not supported on this socket 7514*0Sstevel@tonic-gate * and adapter 7515*0Sstevel@tonic-gate */ 7516*0Sstevel@tonic-gate static int 7517*0Sstevel@tonic-gate cs_convert_powerlevel(uint32_t sn, uint32_t volts, uint32_t flags, unsigned *pl) 7518*0Sstevel@tonic-gate { 7519*0Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 7520*0Sstevel@tonic-gate int i; 7521*0Sstevel@tonic-gate 7522*0Sstevel@tonic-gate #ifdef lint 7523*0Sstevel@tonic-gate if (sn == 0) 7524*0Sstevel@tonic-gate panic("lint panic"); 7525*0Sstevel@tonic-gate #endif 7526*0Sstevel@tonic-gate 7527*0Sstevel@tonic-gate *pl = 0; 7528*0Sstevel@tonic-gate 7529*0Sstevel@tonic-gate if (SocketServices(SS_InquireAdapter, &inquire_adapter) != SUCCESS) 7530*0Sstevel@tonic-gate return (CS_BAD_ADAPTER); 7531*0Sstevel@tonic-gate 7532*0Sstevel@tonic-gate for (i = 0; (i < inquire_adapter.NumPower); i++) { 7533*0Sstevel@tonic-gate if ((inquire_adapter.power_entry[i].ValidSignals & flags) && 7534*0Sstevel@tonic-gate (inquire_adapter.power_entry[i].PowerLevel == volts)) { 7535*0Sstevel@tonic-gate *pl = i; 7536*0Sstevel@tonic-gate return (CS_SUCCESS); 7537*0Sstevel@tonic-gate } 7538*0Sstevel@tonic-gate } 7539*0Sstevel@tonic-gate 7540*0Sstevel@tonic-gate return (CS_BAD_ARGS); 7541*0Sstevel@tonic-gate } 7542*0Sstevel@tonic-gate 7543*0Sstevel@tonic-gate /* 7544*0Sstevel@tonic-gate * cs_event2text - returns text string(s) associated with the event; this 7545*0Sstevel@tonic-gate * function supports the Event2Text CS call. 7546*0Sstevel@tonic-gate * 7547*0Sstevel@tonic-gate * calling: event2text_t * - pointer to event2text struct 7548*0Sstevel@tonic-gate * int event_source - specifies event type in event2text_t: 7549*0Sstevel@tonic-gate * 0 - SS event 7550*0Sstevel@tonic-gate * 1 - CS event 7551*0Sstevel@tonic-gate * 7552*0Sstevel@tonic-gate * returns: CS_SUCCESS 7553*0Sstevel@tonic-gate */ 7554*0Sstevel@tonic-gate static int 7555*0Sstevel@tonic-gate cs_event2text(event2text_t *e2t, int event_source) 7556*0Sstevel@tonic-gate { 7557*0Sstevel@tonic-gate event_t event; 7558*0Sstevel@tonic-gate char *sepchar = "|"; 7559*0Sstevel@tonic-gate 7560*0Sstevel@tonic-gate /* 7561*0Sstevel@tonic-gate * If event_source is 0, this is a SS event 7562*0Sstevel@tonic-gate */ 7563*0Sstevel@tonic-gate if (!event_source) { 7564*0Sstevel@tonic-gate for (event = 0; event < MAX_SS_EVENTS; event++) { 7565*0Sstevel@tonic-gate if (cs_ss_event_text[event].ss_event == e2t->event) { 7566*0Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[event].text); 7567*0Sstevel@tonic-gate return (CS_SUCCESS); 7568*0Sstevel@tonic-gate } 7569*0Sstevel@tonic-gate } 7570*0Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[MAX_CS_EVENTS].text); 7571*0Sstevel@tonic-gate return (CS_SUCCESS); 7572*0Sstevel@tonic-gate } else { 7573*0Sstevel@tonic-gate /* 7574*0Sstevel@tonic-gate * This is a CS event 7575*0Sstevel@tonic-gate */ 7576*0Sstevel@tonic-gate e2t->text[0] = '\0'; 7577*0Sstevel@tonic-gate for (event = 0; event < MAX_CS_EVENTS; event++) { 7578*0Sstevel@tonic-gate if (cs_ss_event_text[event].cs_event & e2t->event) { 7579*0Sstevel@tonic-gate (void) strcat(e2t->text, cs_ss_event_text[event].text); 7580*0Sstevel@tonic-gate (void) strcat(e2t->text, sepchar); 7581*0Sstevel@tonic-gate } /* if (cs_ss_event_text) */ 7582*0Sstevel@tonic-gate } /* for (event) */ 7583*0Sstevel@tonic-gate if (e2t->text[0]) 7584*0Sstevel@tonic-gate e2t->text[strlen(e2t->text)-1] = NULL; 7585*0Sstevel@tonic-gate } /* if (!event_source) */ 7586*0Sstevel@tonic-gate 7587*0Sstevel@tonic-gate return (CS_SUCCESS); 7588*0Sstevel@tonic-gate } 7589*0Sstevel@tonic-gate 7590*0Sstevel@tonic-gate /* 7591*0Sstevel@tonic-gate * cs_error2text - returns a pointer to a text string containing the name 7592*0Sstevel@tonic-gate * of the passed Card Services function or return code 7593*0Sstevel@tonic-gate * 7594*0Sstevel@tonic-gate * This function supports the Error2Text CS call. 7595*0Sstevel@tonic-gate */ 7596*0Sstevel@tonic-gate static char * 7597*0Sstevel@tonic-gate cs_error2text(int function, int type) 7598*0Sstevel@tonic-gate { 7599*0Sstevel@tonic-gate cs_csfunc2text_strings_t *cfs; 7600*0Sstevel@tonic-gate int end_marker; 7601*0Sstevel@tonic-gate 7602*0Sstevel@tonic-gate if (type == CSFUN2TEXT_FUNCTION) { 7603*0Sstevel@tonic-gate cfs = cs_csfunc2text_funcstrings; 7604*0Sstevel@tonic-gate end_marker = CSFuncListEnd; 7605*0Sstevel@tonic-gate } else { 7606*0Sstevel@tonic-gate cfs = cs_csfunc2text_returnstrings; 7607*0Sstevel@tonic-gate end_marker = CS_ERRORLIST_END; 7608*0Sstevel@tonic-gate } 7609*0Sstevel@tonic-gate 7610*0Sstevel@tonic-gate while (cfs->item != end_marker) { 7611*0Sstevel@tonic-gate if (cfs->item == function) 7612*0Sstevel@tonic-gate return (cfs->text); 7613*0Sstevel@tonic-gate cfs++; 7614*0Sstevel@tonic-gate } 7615*0Sstevel@tonic-gate 7616*0Sstevel@tonic-gate return (cfs->text); 7617*0Sstevel@tonic-gate } 7618*0Sstevel@tonic-gate 7619*0Sstevel@tonic-gate /* 7620*0Sstevel@tonic-gate * cs_make_device_node - creates/removes device nodes on a client's behalf; 7621*0Sstevel@tonic-gate * this is MakeDeviceNode and RemoveDeviceNode 7622*0Sstevel@tonic-gate * 7623*0Sstevel@tonic-gate * returns: CS_SUCCESS - if all device nodes successfully created/removed 7624*0Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if NumDevNodes is not zero when Action 7625*0Sstevel@tonic-gate * is REMOVAL_ALL_DEVICES 7626*0Sstevel@tonic-gate * CS_BAD_ARGS - if an invalid Action code is specified 7627*0Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7628*0Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if can't create/remove device node 7629*0Sstevel@tonic-gate */ 7630*0Sstevel@tonic-gate static int 7631*0Sstevel@tonic-gate cs_make_device_node(client_handle_t client_handle, make_device_node_t *mdn) 7632*0Sstevel@tonic-gate { 7633*0Sstevel@tonic-gate cs_socket_t *sp; 7634*0Sstevel@tonic-gate client_t *client; 7635*0Sstevel@tonic-gate ss_make_device_node_t ss_make_device_node; 7636*0Sstevel@tonic-gate int error, i; 7637*0Sstevel@tonic-gate int client_lock_acquired; 7638*0Sstevel@tonic-gate 7639*0Sstevel@tonic-gate /* 7640*0Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 7641*0Sstevel@tonic-gate * is, we don't support SS using this call. 7642*0Sstevel@tonic-gate */ 7643*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 7644*0Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 7645*0Sstevel@tonic-gate 7646*0Sstevel@tonic-gate /* 7647*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7648*0Sstevel@tonic-gate */ 7649*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7650*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7651*0Sstevel@tonic-gate 7652*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7653*0Sstevel@tonic-gate 7654*0Sstevel@tonic-gate /* 7655*0Sstevel@tonic-gate * Make sure that this is a valid client handle. 7656*0Sstevel@tonic-gate */ 7657*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7658*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7659*0Sstevel@tonic-gate return (error); 7660*0Sstevel@tonic-gate } 7661*0Sstevel@tonic-gate 7662*0Sstevel@tonic-gate #ifdef XXX 7663*0Sstevel@tonic-gate /* 7664*0Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7665*0Sstevel@tonic-gate * for this client, then return an error. 7666*0Sstevel@tonic-gate */ 7667*0Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7668*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7669*0Sstevel@tonic-gate return (CS_NO_CARD); 7670*0Sstevel@tonic-gate } 7671*0Sstevel@tonic-gate #endif 7672*0Sstevel@tonic-gate 7673*0Sstevel@tonic-gate /* 7674*0Sstevel@tonic-gate * Setup the client's dip, since we use it later on. 7675*0Sstevel@tonic-gate */ 7676*0Sstevel@tonic-gate ss_make_device_node.dip = client->dip; 7677*0Sstevel@tonic-gate 7678*0Sstevel@tonic-gate /* 7679*0Sstevel@tonic-gate * Make sure that we're being given a valid Action. Set the default 7680*0Sstevel@tonic-gate * error code as well. 7681*0Sstevel@tonic-gate */ 7682*0Sstevel@tonic-gate error = CS_BAD_ARGS; /* for default case */ 7683*0Sstevel@tonic-gate switch (mdn->Action) { 7684*0Sstevel@tonic-gate case CREATE_DEVICE_NODE: 7685*0Sstevel@tonic-gate case REMOVE_DEVICE_NODE: 7686*0Sstevel@tonic-gate break; 7687*0Sstevel@tonic-gate case REMOVAL_ALL_DEVICE_NODES: 7688*0Sstevel@tonic-gate if (mdn->NumDevNodes) { 7689*0Sstevel@tonic-gate error = CS_BAD_ATTRIBUTE; 7690*0Sstevel@tonic-gate } else { 7691*0Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7692*0Sstevel@tonic-gate ss_make_device_node.name = NULL; 7693*0Sstevel@tonic-gate SocketServices(CSInitDev, &ss_make_device_node); 7694*0Sstevel@tonic-gate error = CS_SUCCESS; 7695*0Sstevel@tonic-gate } 7696*0Sstevel@tonic-gate /* fall-through case */ 7697*0Sstevel@tonic-gate default: 7698*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7699*0Sstevel@tonic-gate return (error); 7700*0Sstevel@tonic-gate /* NOTREACHED */ 7701*0Sstevel@tonic-gate } /* switch */ 7702*0Sstevel@tonic-gate 7703*0Sstevel@tonic-gate /* 7704*0Sstevel@tonic-gate * Loop through the device node descriptions and create or destroy 7705*0Sstevel@tonic-gate * the device node. 7706*0Sstevel@tonic-gate */ 7707*0Sstevel@tonic-gate for (i = 0; i < mdn->NumDevNodes; i++) { 7708*0Sstevel@tonic-gate devnode_desc_t *devnode_desc = &mdn->devnode_desc[i]; 7709*0Sstevel@tonic-gate 7710*0Sstevel@tonic-gate ss_make_device_node.name = devnode_desc->name; 7711*0Sstevel@tonic-gate ss_make_device_node.spec_type = devnode_desc->spec_type; 7712*0Sstevel@tonic-gate ss_make_device_node.minor_num = devnode_desc->minor_num; 7713*0Sstevel@tonic-gate ss_make_device_node.node_type = devnode_desc->node_type; 7714*0Sstevel@tonic-gate 7715*0Sstevel@tonic-gate /* 7716*0Sstevel@tonic-gate * Set the appropriate flag for the action that we want 7717*0Sstevel@tonic-gate * SS to perform. Note that if we ever OR-in the flag 7718*0Sstevel@tonic-gate * here, we need to be sure to clear the flags member 7719*0Sstevel@tonic-gate * since we sometimes OR-in other flags below. 7720*0Sstevel@tonic-gate */ 7721*0Sstevel@tonic-gate if (mdn->Action == CREATE_DEVICE_NODE) { 7722*0Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_CREATE_DEVICE; 7723*0Sstevel@tonic-gate } else { 7724*0Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7725*0Sstevel@tonic-gate } 7726*0Sstevel@tonic-gate 7727*0Sstevel@tonic-gate /* 7728*0Sstevel@tonic-gate * If this is not the last device to process, then we need 7729*0Sstevel@tonic-gate * to tell SS that more device process requests are on 7730*0Sstevel@tonic-gate * their way after this one. 7731*0Sstevel@tonic-gate */ 7732*0Sstevel@tonic-gate if (i < (mdn->NumDevNodes - 1)) 7733*0Sstevel@tonic-gate ss_make_device_node.flags |= SS_CSINITDEV_MORE_DEVICES; 7734*0Sstevel@tonic-gate 7735*0Sstevel@tonic-gate if (SocketServices(CSInitDev, &ss_make_device_node) != SUCCESS) { 7736*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7737*0Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 7738*0Sstevel@tonic-gate } /* CSInitDev */ 7739*0Sstevel@tonic-gate } /* for (mdn->NumDevNodes) */ 7740*0Sstevel@tonic-gate 7741*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7742*0Sstevel@tonic-gate return (CS_SUCCESS); 7743*0Sstevel@tonic-gate } 7744*0Sstevel@tonic-gate 7745*0Sstevel@tonic-gate /* 7746*0Sstevel@tonic-gate * cs_remove_device_node - removes device nodes 7747*0Sstevel@tonic-gate * 7748*0Sstevel@tonic-gate * (see cs_make_device_node for a description of the calling 7749*0Sstevel@tonic-gate * and return parameters) 7750*0Sstevel@tonic-gate */ 7751*0Sstevel@tonic-gate static int 7752*0Sstevel@tonic-gate cs_remove_device_node(client_handle_t client_handle, remove_device_node_t *rdn) 7753*0Sstevel@tonic-gate { 7754*0Sstevel@tonic-gate 7755*0Sstevel@tonic-gate /* 7756*0Sstevel@tonic-gate * XXX - Note the assumption here that the make_device_node_t and 7757*0Sstevel@tonic-gate * remove_device_node_t structures are identical. 7758*0Sstevel@tonic-gate */ 7759*0Sstevel@tonic-gate return (cs_make_device_node(client_handle, (make_device_node_t *)rdn)); 7760*0Sstevel@tonic-gate } 7761*0Sstevel@tonic-gate 7762*0Sstevel@tonic-gate /* 7763*0Sstevel@tonic-gate * cs_ddi_info - this function is used by clients that need to support 7764*0Sstevel@tonic-gate * the xxx_getinfo function; this is CS_DDI_Info 7765*0Sstevel@tonic-gate */ 7766*0Sstevel@tonic-gate static int 7767*0Sstevel@tonic-gate cs_ddi_info(cs_ddi_info_t *cdi) 7768*0Sstevel@tonic-gate { 7769*0Sstevel@tonic-gate cs_socket_t *sp; 7770*0Sstevel@tonic-gate client_t *client; 7771*0Sstevel@tonic-gate int client_lock_acquired; 7772*0Sstevel@tonic-gate 7773*0Sstevel@tonic-gate if (cdi->driver_name == NULL) 7774*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 7775*0Sstevel@tonic-gate 7776*0Sstevel@tonic-gate #ifdef CS_DEBUG 7777*0Sstevel@tonic-gate if (cs_debug > 0) { 7778*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s]\n", 7779*0Sstevel@tonic-gate (int)cdi->Socket, cdi->driver_name); 7780*0Sstevel@tonic-gate } 7781*0Sstevel@tonic-gate #endif 7782*0Sstevel@tonic-gate 7783*0Sstevel@tonic-gate /* 7784*0Sstevel@tonic-gate * Check to see if the socket number is in range - the system 7785*0Sstevel@tonic-gate * framework may cause a client driver to call us with 7786*0Sstevel@tonic-gate * a socket number that used to be present but isn't 7787*0Sstevel@tonic-gate * anymore. This is not a bug, and it's OK to return 7788*0Sstevel@tonic-gate * an error if the socket number is out of range. 7789*0Sstevel@tonic-gate */ 7790*0Sstevel@tonic-gate if (!CHECK_SOCKET_NUM(cdi->Socket, cs_globals.max_socket_num)) { 7791*0Sstevel@tonic-gate 7792*0Sstevel@tonic-gate #ifdef CS_DEBUG 7793*0Sstevel@tonic-gate if (cs_debug > 0) { 7794*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s] " 7795*0Sstevel@tonic-gate "SOCKET IS OUT OF RANGE\n", 7796*0Sstevel@tonic-gate (int)cdi->Socket, 7797*0Sstevel@tonic-gate cdi->driver_name); 7798*0Sstevel@tonic-gate } 7799*0Sstevel@tonic-gate #endif 7800*0Sstevel@tonic-gate 7801*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7802*0Sstevel@tonic-gate } /* if (!CHECK_SOCKET_NUM) */ 7803*0Sstevel@tonic-gate 7804*0Sstevel@tonic-gate /* 7805*0Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7806*0Sstevel@tonic-gate */ 7807*0Sstevel@tonic-gate if ((sp = cs_get_sp(cdi->Socket)) == NULL) 7808*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7809*0Sstevel@tonic-gate 7810*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7811*0Sstevel@tonic-gate 7812*0Sstevel@tonic-gate client = sp->client_list; 7813*0Sstevel@tonic-gate while (client) { 7814*0Sstevel@tonic-gate 7815*0Sstevel@tonic-gate #ifdef CS_DEBUG 7816*0Sstevel@tonic-gate if (cs_debug > 0) { 7817*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d checking client [%s] " 7818*0Sstevel@tonic-gate "handle 0x%x\n", 7819*0Sstevel@tonic-gate (int)cdi->Socket, 7820*0Sstevel@tonic-gate client->driver_name, 7821*0Sstevel@tonic-gate (int)client->client_handle); 7822*0Sstevel@tonic-gate } 7823*0Sstevel@tonic-gate #endif 7824*0Sstevel@tonic-gate 7825*0Sstevel@tonic-gate if (client->driver_name != NULL) { 7826*0Sstevel@tonic-gate if (!(strcmp(client->driver_name, cdi->driver_name))) { 7827*0Sstevel@tonic-gate cdi->dip = client->dip; 7828*0Sstevel@tonic-gate cdi->instance = client->instance; 7829*0Sstevel@tonic-gate 7830*0Sstevel@tonic-gate #ifdef CS_DEBUG 7831*0Sstevel@tonic-gate if (cs_debug > 0) { 7832*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: found client [%s] " 7833*0Sstevel@tonic-gate "instance %d handle 0x%x\n", 7834*0Sstevel@tonic-gate client->driver_name, client->instance, 7835*0Sstevel@tonic-gate (int)client->client_handle); 7836*0Sstevel@tonic-gate } 7837*0Sstevel@tonic-gate #endif 7838*0Sstevel@tonic-gate 7839*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7840*0Sstevel@tonic-gate return (CS_SUCCESS); 7841*0Sstevel@tonic-gate } /* strcmp */ 7842*0Sstevel@tonic-gate } /* driver_name != NULL */ 7843*0Sstevel@tonic-gate client = client->next; 7844*0Sstevel@tonic-gate } /* while (client) */ 7845*0Sstevel@tonic-gate 7846*0Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7847*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7848*0Sstevel@tonic-gate } 7849*0Sstevel@tonic-gate 7850*0Sstevel@tonic-gate /* 7851*0Sstevel@tonic-gate * cs_sys_ctl - Card Services system control; this is CS_Sys_Ctl 7852*0Sstevel@tonic-gate */ 7853*0Sstevel@tonic-gate static int 7854*0Sstevel@tonic-gate cs_sys_ctl(cs_sys_ctl_t *csc) 7855*0Sstevel@tonic-gate { 7856*0Sstevel@tonic-gate cs_socket_t *sp; 7857*0Sstevel@tonic-gate client_t *cp; 7858*0Sstevel@tonic-gate int sn, ret = CS_UNSUPPORTED_MODE; 7859*0Sstevel@tonic-gate 7860*0Sstevel@tonic-gate switch (csc->Action) { 7861*0Sstevel@tonic-gate case CS_SYS_CTL_SEND_EVENT: 7862*0Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7863*0Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(csc->Socket); 7864*0Sstevel@tonic-gate else 7865*0Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(csc->client_handle); 7866*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 7867*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7868*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 7869*0Sstevel@tonic-gate mutex_enter(&sp->lock); 7870*0Sstevel@tonic-gate csc->Events &= CS_EVENT_CLIENT_EVENTS_MASK; 7871*0Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7872*0Sstevel@tonic-gate sp->events |= csc->Events; 7873*0Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_CLIENT) { 7874*0Sstevel@tonic-gate if ((cp = cs_find_client(csc->client_handle, &ret)) == 7875*0Sstevel@tonic-gate NULL) { 7876*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7877*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 7878*0Sstevel@tonic-gate return (ret); 7879*0Sstevel@tonic-gate } /* cs_find_client */ 7880*0Sstevel@tonic-gate /* 7881*0Sstevel@tonic-gate * Setup the events that we want to send to the client. 7882*0Sstevel@tonic-gate */ 7883*0Sstevel@tonic-gate cp->events |= (csc->Events & 7884*0Sstevel@tonic-gate (cp->event_mask | cp->global_mask)); 7885*0Sstevel@tonic-gate } /* CS_SYS_CTL_EVENT_CLIENT */ 7886*0Sstevel@tonic-gate 7887*0Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_WAIT_SYNC) { 7888*0Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 7889*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7890*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 7891*0Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 7892*0Sstevel@tonic-gate } else { 7893*0Sstevel@tonic-gate mutex_exit(&sp->lock); 7894*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 7895*0Sstevel@tonic-gate } /* CS_SYS_CTL_WAIT_SYNC */ 7896*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 7897*0Sstevel@tonic-gate ret = CS_SUCCESS; 7898*0Sstevel@tonic-gate break; 7899*0Sstevel@tonic-gate default: 7900*0Sstevel@tonic-gate break; 7901*0Sstevel@tonic-gate } /* switch */ 7902*0Sstevel@tonic-gate 7903*0Sstevel@tonic-gate return (ret); 7904*0Sstevel@tonic-gate } 7905*0Sstevel@tonic-gate 7906*0Sstevel@tonic-gate /* 7907*0Sstevel@tonic-gate * cs_get_sp - returns pointer to per-socket structure for passed 7908*0Sstevel@tonic-gate * socket number 7909*0Sstevel@tonic-gate * 7910*0Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure 7911*0Sstevel@tonic-gate * NULL - invalid socket number passed in 7912*0Sstevel@tonic-gate */ 7913*0Sstevel@tonic-gate static cs_socket_t * 7914*0Sstevel@tonic-gate cs_get_sp(uint32_t sn) 7915*0Sstevel@tonic-gate { 7916*0Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 7917*0Sstevel@tonic-gate 7918*0Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7919*0Sstevel@tonic-gate return (NULL); 7920*0Sstevel@tonic-gate 7921*0Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) 7922*0Sstevel@tonic-gate return (NULL); 7923*0Sstevel@tonic-gate 7924*0Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 7925*0Sstevel@tonic-gate return (sp); 7926*0Sstevel@tonic-gate 7927*0Sstevel@tonic-gate return (NULL); 7928*0Sstevel@tonic-gate } 7929*0Sstevel@tonic-gate 7930*0Sstevel@tonic-gate /* 7931*0Sstevel@tonic-gate * cs_find_sp - searches socket list and returns pointer to passed socket 7932*0Sstevel@tonic-gate * number 7933*0Sstevel@tonic-gate * 7934*0Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure if found 7935*0Sstevel@tonic-gate * NULL - socket not found 7936*0Sstevel@tonic-gate */ 7937*0Sstevel@tonic-gate static cs_socket_t * 7938*0Sstevel@tonic-gate cs_find_sp(uint32_t sn) 7939*0Sstevel@tonic-gate { 7940*0Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 7941*0Sstevel@tonic-gate 7942*0Sstevel@tonic-gate while (sp) { 7943*0Sstevel@tonic-gate if (sp->socket_num == CS_GET_SOCKET_NUMBER(sn)) 7944*0Sstevel@tonic-gate return (sp); 7945*0Sstevel@tonic-gate sp = sp->next; 7946*0Sstevel@tonic-gate } /* while */ 7947*0Sstevel@tonic-gate 7948*0Sstevel@tonic-gate return (NULL); 7949*0Sstevel@tonic-gate } 7950*0Sstevel@tonic-gate 7951*0Sstevel@tonic-gate /* 7952*0Sstevel@tonic-gate * cs_add_socket - add a socket 7953*0Sstevel@tonic-gate * 7954*0Sstevel@tonic-gate * call: sn - socket number to add 7955*0Sstevel@tonic-gate * 7956*0Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 7957*0Sstevel@tonic-gate * CS_BAD_SOCKET - unable to add socket 7958*0Sstevel@tonic-gate * CS_BAD_WINDOW - unable to get CIS window for socket 7959*0Sstevel@tonic-gate * 7960*0Sstevel@tonic-gate * We get called here once for each socket that the framework wants to 7961*0Sstevel@tonic-gate * add. When we are called, the framework guarentees that until we 7962*0Sstevel@tonic-gate * complete this routine, no other adapter instances will be allowed 7963*0Sstevel@tonic-gate * to attach and thus no other PCE_ADD_SOCKET events will occur. 7964*0Sstevel@tonic-gate * It is safe to call SS_InquireAdapter to get the number of 7965*0Sstevel@tonic-gate * windows that the framework currently knows about. 7966*0Sstevel@tonic-gate */ 7967*0Sstevel@tonic-gate static uint32_t 7968*0Sstevel@tonic-gate cs_add_socket(uint32_t sn) 7969*0Sstevel@tonic-gate { 7970*0Sstevel@tonic-gate cs_socket_t *sp; 7971*0Sstevel@tonic-gate sservice_t sservice; 7972*0Sstevel@tonic-gate get_cookies_and_dip_t *gcad; 7973*0Sstevel@tonic-gate win_req_t win_req; 7974*0Sstevel@tonic-gate convert_speed_t convert_speed; 7975*0Sstevel@tonic-gate set_socket_t set_socket; 7976*0Sstevel@tonic-gate cs_window_t *cw; 7977*0Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 7978*0Sstevel@tonic-gate inquire_window_t inquire_window; 7979*0Sstevel@tonic-gate int ret, added_windows; 7980*0Sstevel@tonic-gate 7981*0Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7982*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 7983*0Sstevel@tonic-gate 7984*0Sstevel@tonic-gate /* 7985*0Sstevel@tonic-gate * See if this socket has already been added - if it has, we 7986*0Sstevel@tonic-gate * fail this. If we can't find the socket, then allocate 7987*0Sstevel@tonic-gate * a new socket structure. If we do find the socket, then 7988*0Sstevel@tonic-gate * check to see if it's already added; if it is, then 7989*0Sstevel@tonic-gate * this is an error and return CS_BAD_SOCKET; if not, 7990*0Sstevel@tonic-gate * then traverse the socket structure list and add this 7991*0Sstevel@tonic-gate * next socket strcture to the end of the list. 7992*0Sstevel@tonic-gate * XXX What about locking this list while we update it? Is 7993*0Sstevel@tonic-gate * that necessary since we're using the SOCKET_IS_VALID 7994*0Sstevel@tonic-gate * flag and since we never delete a socket from the 7995*0Sstevel@tonic-gate * list once it's been added? 7996*0Sstevel@tonic-gate */ 7997*0Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) { 7998*0Sstevel@tonic-gate cs_socket_t *spp = cs_globals.sp; 7999*0Sstevel@tonic-gate 8000*0Sstevel@tonic-gate sp = (cs_socket_t *)kmem_zalloc(sizeof (cs_socket_t), KM_SLEEP); 8001*0Sstevel@tonic-gate 8002*0Sstevel@tonic-gate if (cs_globals.sp == NULL) 8003*0Sstevel@tonic-gate cs_globals.sp = sp; 8004*0Sstevel@tonic-gate else 8005*0Sstevel@tonic-gate while (spp) { 8006*0Sstevel@tonic-gate if (spp->next == NULL) { 8007*0Sstevel@tonic-gate spp->next = sp; 8008*0Sstevel@tonic-gate break; 8009*0Sstevel@tonic-gate } /* if */ 8010*0Sstevel@tonic-gate spp = spp->next; 8011*0Sstevel@tonic-gate } /* while */ 8012*0Sstevel@tonic-gate 8013*0Sstevel@tonic-gate } else { 8014*0Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 8015*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8016*0Sstevel@tonic-gate } /* cs_find_sp */ 8017*0Sstevel@tonic-gate 8018*0Sstevel@tonic-gate /* 8019*0Sstevel@tonic-gate * Setup the socket number 8020*0Sstevel@tonic-gate */ 8021*0Sstevel@tonic-gate sp->socket_num = sn; 8022*0Sstevel@tonic-gate 8023*0Sstevel@tonic-gate /* 8024*0Sstevel@tonic-gate * Find out how many windows the framework knows about 8025*0Sstevel@tonic-gate * so far. If this number of windows is greater 8026*0Sstevel@tonic-gate * than our current window count, bump up our 8027*0Sstevel@tonic-gate * current window count. 8028*0Sstevel@tonic-gate * XXX Note that there is a BIG assumption here and that 8029*0Sstevel@tonic-gate * is that once the framework tells us that it has 8030*0Sstevel@tonic-gate * a window (as reflected in the NumWindows 8031*0Sstevel@tonic-gate * value) it can NEVER remove that window. 8032*0Sstevel@tonic-gate * When we really get the drop socket and drop 8033*0Sstevel@tonic-gate * window mechanism working correctly, we'll have 8034*0Sstevel@tonic-gate * to revisit this. 8035*0Sstevel@tonic-gate */ 8036*0Sstevel@tonic-gate SocketServices(SS_InquireAdapter, &inquire_adapter); 8037*0Sstevel@tonic-gate 8038*0Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 8039*0Sstevel@tonic-gate added_windows = inquire_adapter.NumWindows - cs_globals.num_windows; 8040*0Sstevel@tonic-gate if (added_windows > 0) { 8041*0Sstevel@tonic-gate if (cs_add_windows(added_windows, 8042*0Sstevel@tonic-gate cs_globals.num_windows) != CS_SUCCESS) { 8043*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8044*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 8045*0Sstevel@tonic-gate } /* cs_add_windows */ 8046*0Sstevel@tonic-gate 8047*0Sstevel@tonic-gate cs_globals.num_windows = inquire_adapter.NumWindows; 8048*0Sstevel@tonic-gate 8049*0Sstevel@tonic-gate } /* if (added_windows) */ 8050*0Sstevel@tonic-gate 8051*0Sstevel@tonic-gate /* 8052*0Sstevel@tonic-gate * Find a window that we can use for this socket's CIS window. 8053*0Sstevel@tonic-gate */ 8054*0Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8055*0Sstevel@tonic-gate 8056*0Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 8057*0Sstevel@tonic-gate convert_speed.nS = CIS_DEFAULT_SPEED; 8058*0Sstevel@tonic-gate (void) cs_convert_speed(&convert_speed); 8059*0Sstevel@tonic-gate 8060*0Sstevel@tonic-gate win_req.win_params.AccessSpeed = convert_speed.devspeed; 8061*0Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8); 8062*0Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_MEMORY_TYPE_CM); 8063*0Sstevel@tonic-gate win_req.Base.base = 0; 8064*0Sstevel@tonic-gate win_req.Size = 0; 8065*0Sstevel@tonic-gate 8066*0Sstevel@tonic-gate if ((ret = cs_find_mem_window(sp->socket_num, &win_req, 8067*0Sstevel@tonic-gate &sp->cis_win_num)) != CS_SUCCESS) { 8068*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8069*0Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8070*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't get CIS " 8071*0Sstevel@tonic-gate "window - error 0x%x\n", 8072*0Sstevel@tonic-gate sp->socket_num, ret); 8073*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 8074*0Sstevel@tonic-gate } /* cs_find_mem_window */ 8075*0Sstevel@tonic-gate 8076*0Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) { 8077*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8078*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 8079*0Sstevel@tonic-gate } 8080*0Sstevel@tonic-gate 8081*0Sstevel@tonic-gate inquire_window.window = sp->cis_win_num; 8082*0Sstevel@tonic-gate SocketServices(SS_InquireWindow, &inquire_window); 8083*0Sstevel@tonic-gate 8084*0Sstevel@tonic-gate /* 8085*0Sstevel@tonic-gate * If the CIS window is a variable sized window, then use 8086*0Sstevel@tonic-gate * the size that cs_find_mem_window returned to us, 8087*0Sstevel@tonic-gate * since this will be the minimum size that we can 8088*0Sstevel@tonic-gate * set this window to. If the CIS window is a fixed 8089*0Sstevel@tonic-gate * sized window, then use the system pagesize as the 8090*0Sstevel@tonic-gate * CIS window size. 8091*0Sstevel@tonic-gate */ 8092*0Sstevel@tonic-gate if (inquire_window.mem_win_char.MemWndCaps & WC_SIZE) { 8093*0Sstevel@tonic-gate sp->cis_win_size = win_req.Size; 8094*0Sstevel@tonic-gate } else { 8095*0Sstevel@tonic-gate sp->cis_win_size = PAGESIZE; 8096*0Sstevel@tonic-gate } 8097*0Sstevel@tonic-gate 8098*0Sstevel@tonic-gate cw->state |= (CW_CIS | CW_ALLOCATED); 8099*0Sstevel@tonic-gate cw->socket_num = sp->socket_num; 8100*0Sstevel@tonic-gate 8101*0Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8102*0Sstevel@tonic-gate 8103*0Sstevel@tonic-gate #if defined(CS_DEBUG) 8104*0Sstevel@tonic-gate if (cs_debug > 1) { 8105*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d using CIS window %d " 8106*0Sstevel@tonic-gate "size 0x%x\n", (int)sp->socket_num, 8107*0Sstevel@tonic-gate (int)sp->cis_win_num, 8108*0Sstevel@tonic-gate (int)sp->cis_win_size); 8109*0Sstevel@tonic-gate } 8110*0Sstevel@tonic-gate #endif 8111*0Sstevel@tonic-gate 8112*0Sstevel@tonic-gate /* 8113*0Sstevel@tonic-gate * Get the adapter information associated with this socket so 8114*0Sstevel@tonic-gate * that we can initialize the mutexes, condition variables, 8115*0Sstevel@tonic-gate * soft interrupt handler and per-socket adapter info. 8116*0Sstevel@tonic-gate */ 8117*0Sstevel@tonic-gate gcad = &sservice.get_cookies; 8118*0Sstevel@tonic-gate gcad->socket = sp->socket_num; 8119*0Sstevel@tonic-gate if (SocketServices(CSGetCookiesAndDip, &sservice) != SUCCESS) { 8120*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d CSGetCookiesAndDip " 8121*0Sstevel@tonic-gate "failure\n", sp->socket_num); 8122*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8123*0Sstevel@tonic-gate } /* CSGetCookiesAndDip */ 8124*0Sstevel@tonic-gate 8125*0Sstevel@tonic-gate /* 8126*0Sstevel@tonic-gate * Save the iblock and idev cookies for RegisterClient 8127*0Sstevel@tonic-gate */ 8128*0Sstevel@tonic-gate sp->iblk = gcad->iblock; 8129*0Sstevel@tonic-gate sp->idev = gcad->idevice; 8130*0Sstevel@tonic-gate 8131*0Sstevel@tonic-gate /* 8132*0Sstevel@tonic-gate * Setup the per-socket adapter info 8133*0Sstevel@tonic-gate */ 8134*0Sstevel@tonic-gate sp->adapter.flags = 0; 8135*0Sstevel@tonic-gate (void) strcpy(sp->adapter.name, gcad->adapter_info.name); 8136*0Sstevel@tonic-gate sp->adapter.major = gcad->adapter_info.major; 8137*0Sstevel@tonic-gate sp->adapter.minor = gcad->adapter_info.minor; 8138*0Sstevel@tonic-gate sp->adapter.instance = ddi_get_instance(gcad->dip); 8139*0Sstevel@tonic-gate sp->adapter.number = gcad->adapter_info.number; 8140*0Sstevel@tonic-gate sp->adapter.num_sockets = gcad->adapter_info.num_sockets; 8141*0Sstevel@tonic-gate sp->adapter.first_socket = gcad->adapter_info.first_socket; 8142*0Sstevel@tonic-gate 8143*0Sstevel@tonic-gate /* Setup for cs_event and cs_event_thread */ 8144*0Sstevel@tonic-gate mutex_init(&sp->lock, NULL, MUTEX_DRIVER, *(gcad->iblock)); 8145*0Sstevel@tonic-gate mutex_init(&sp->client_lock, NULL, MUTEX_DRIVER, NULL); 8146*0Sstevel@tonic-gate mutex_init(&sp->cis_lock, NULL, MUTEX_DRIVER, NULL); 8147*0Sstevel@tonic-gate 8148*0Sstevel@tonic-gate /* Setup for Socket Services work thread */ 8149*0Sstevel@tonic-gate mutex_init(&sp->ss_thread_lock, NULL, MUTEX_DRIVER, NULL); 8150*0Sstevel@tonic-gate 8151*0Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_MUTEX; 8152*0Sstevel@tonic-gate 8153*0Sstevel@tonic-gate /* Setup for cs_event_thread */ 8154*0Sstevel@tonic-gate cv_init(&sp->thread_cv, NULL, CV_DRIVER, NULL); 8155*0Sstevel@tonic-gate cv_init(&sp->caller_cv, NULL, CV_DRIVER, NULL); 8156*0Sstevel@tonic-gate cv_init(&sp->reset_cv, NULL, CV_DRIVER, NULL); 8157*0Sstevel@tonic-gate 8158*0Sstevel@tonic-gate /* Setup for Socket Services work thread */ 8159*0Sstevel@tonic-gate cv_init(&sp->ss_thread_cv, NULL, CV_DRIVER, NULL); 8160*0Sstevel@tonic-gate cv_init(&sp->ss_caller_cv, NULL, CV_DRIVER, NULL); 8161*0Sstevel@tonic-gate 8162*0Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_CV; 8163*0Sstevel@tonic-gate 8164*0Sstevel@tonic-gate /* 8165*0Sstevel@tonic-gate * If we haven't installed it yet, then install the soft interrupt 8166*0Sstevel@tonic-gate * handler and save away the softint id. 8167*0Sstevel@tonic-gate */ 8168*0Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR)) { 8169*0Sstevel@tonic-gate if (ddi_add_softintr(gcad->dip, DDI_SOFTINT_HIGH, 8170*0Sstevel@tonic-gate &sp->softint_id, 8171*0Sstevel@tonic-gate NULL, NULL, 8172*0Sstevel@tonic-gate cs_socket_event_softintr, 8173*0Sstevel@tonic-gate (caddr_t)NULL) != DDI_SUCCESS) { 8174*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't add " 8175*0Sstevel@tonic-gate "softintr\n", sp->socket_num); 8176*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8177*0Sstevel@tonic-gate } /* ddi_add_softintr */ 8178*0Sstevel@tonic-gate 8179*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 8180*0Sstevel@tonic-gate cs_globals.softint_id = sp->softint_id; 8181*0Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SOFTINTR; 8182*0Sstevel@tonic-gate /* XXX this timer is hokey at best... */ 8183*0Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 8184*0Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 8185*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 8186*0Sstevel@tonic-gate } else { 8187*0Sstevel@tonic-gate /* 8188*0Sstevel@tonic-gate * We've already added the soft interrupt handler, so just 8189*0Sstevel@tonic-gate * store away the softint id. 8190*0Sstevel@tonic-gate */ 8191*0Sstevel@tonic-gate sp->softint_id = cs_globals.softint_id; 8192*0Sstevel@tonic-gate } /* if (!GLOBAL_INIT_STATE_SOFTINTR) */ 8193*0Sstevel@tonic-gate 8194*0Sstevel@tonic-gate /* 8195*0Sstevel@tonic-gate * While this next flag doesn't really describe a per-socket 8196*0Sstevel@tonic-gate * resource, we still set it for each socket. When the soft 8197*0Sstevel@tonic-gate * interrupt handler finally gets removed in cs_deinit, this 8198*0Sstevel@tonic-gate * flag will get cleared. 8199*0Sstevel@tonic-gate */ 8200*0Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_SOFTINTR; 8201*0Sstevel@tonic-gate 8202*0Sstevel@tonic-gate /* 8203*0Sstevel@tonic-gate * Socket Services defaults all sockets to power off and 8204*0Sstevel@tonic-gate * clears all event masks. We want to receive at least 8205*0Sstevel@tonic-gate * card insertion events, so enable them. Turn off power 8206*0Sstevel@tonic-gate * to the socket as well. We will turn it on again when 8207*0Sstevel@tonic-gate * we get a card insertion event. 8208*0Sstevel@tonic-gate */ 8209*0Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 8210*0Sstevel@tonic-gate set_socket.socket = sp->socket_num; 8211*0Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 8212*0Sstevel@tonic-gate set_socket.IREQRouting = 0; 8213*0Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 8214*0Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 8215*0Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 8216*0Sstevel@tonic-gate 8217*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 8218*0Sstevel@tonic-gate &set_socket.VccLevel); 8219*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 8220*0Sstevel@tonic-gate &set_socket.Vpp1Level); 8221*0Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 8222*0Sstevel@tonic-gate &set_socket.Vpp2Level); 8223*0Sstevel@tonic-gate 8224*0Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 8225*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d SS_SetSocket " 8226*0Sstevel@tonic-gate "failure %d\n", sp->socket_num, ret); 8227*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8228*0Sstevel@tonic-gate } /* SS_SetSocket */ 8229*0Sstevel@tonic-gate 8230*0Sstevel@tonic-gate /* 8231*0Sstevel@tonic-gate * The various socket-specific variables are now set up, so 8232*0Sstevel@tonic-gate * increment the global socket count and also mark the 8233*0Sstevel@tonic-gate * socket as available. We need to set this before we 8234*0Sstevel@tonic-gate * start any of the per-socket threads so that the threads 8235*0Sstevel@tonic-gate * can get a valid socket pointer when they start. 8236*0Sstevel@tonic-gate */ 8237*0Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 8238*0Sstevel@tonic-gate cs_globals.num_sockets++; 8239*0Sstevel@tonic-gate cs_globals.max_socket_num = 8240*0Sstevel@tonic-gate max(cs_globals.max_socket_num, sp->socket_num + 1); 8241*0Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 8242*0Sstevel@tonic-gate sp->flags = SOCKET_IS_VALID; 8243*0Sstevel@tonic-gate 8244*0Sstevel@tonic-gate /* 8245*0Sstevel@tonic-gate * Create the per-socket event handler thread. 8246*0Sstevel@tonic-gate */ 8247*0Sstevel@tonic-gate sp->event_thread = CREATE_SOCKET_EVENT_THREAD(cs_event_thread, 8248*0Sstevel@tonic-gate (uintptr_t)sn); 8249*0Sstevel@tonic-gate 8250*0Sstevel@tonic-gate mutex_enter(&sp->lock); 8251*0Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_THREAD; 8252*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8253*0Sstevel@tonic-gate 8254*0Sstevel@tonic-gate /* 8255*0Sstevel@tonic-gate * Create the per-socket Socket Services work thread. 8256*0Sstevel@tonic-gate */ 8257*0Sstevel@tonic-gate sp->ss_thread = CREATE_SOCKET_EVENT_THREAD(cs_ss_thread, 8258*0Sstevel@tonic-gate (uintptr_t)sn); 8259*0Sstevel@tonic-gate 8260*0Sstevel@tonic-gate mutex_enter(&sp->lock); 8261*0Sstevel@tonic-gate sp->init_state |= (SOCKET_INIT_STATE_SS_THREAD | 8262*0Sstevel@tonic-gate SOCKET_INIT_STATE_READY); 8263*0Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 8264*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8265*0Sstevel@tonic-gate 8266*0Sstevel@tonic-gate return (CS_SUCCESS); 8267*0Sstevel@tonic-gate } 8268*0Sstevel@tonic-gate 8269*0Sstevel@tonic-gate /* 8270*0Sstevel@tonic-gate * cs_drop_socket - drop a socket 8271*0Sstevel@tonic-gate * 8272*0Sstevel@tonic-gate * call: sn - socket number to drop 8273*0Sstevel@tonic-gate * 8274*0Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 8275*0Sstevel@tonic-gate * CS_BAD_SOCKET - unable to drop socket 8276*0Sstevel@tonic-gate */ 8277*0Sstevel@tonic-gate /*ARGSUSED*/ 8278*0Sstevel@tonic-gate static uint32_t 8279*0Sstevel@tonic-gate cs_drop_socket(uint32_t sn) 8280*0Sstevel@tonic-gate { 8281*0Sstevel@tonic-gate #ifdef XXX 8282*0Sstevel@tonic-gate cs_socket_t *sp; 8283*0Sstevel@tonic-gate 8284*0Sstevel@tonic-gate /* 8285*0Sstevel@tonic-gate * Tell the socket event thread to exit and then wait for it 8286*0Sstevel@tonic-gate * to do so. 8287*0Sstevel@tonic-gate */ 8288*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8289*0Sstevel@tonic-gate sp->thread_state |= SOCKET_THREAD_EXIT; 8290*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 8291*0Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 8292*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8293*0Sstevel@tonic-gate 8294*0Sstevel@tonic-gate /* 8295*0Sstevel@tonic-gate * Tell the socket SS thread to exit and then wait for it 8296*0Sstevel@tonic-gate * to do so. 8297*0Sstevel@tonic-gate */ 8298*0Sstevel@tonic-gate 8299*0Sstevel@tonic-gate /* 8300*0Sstevel@tonic-gate * Mark the socket as dropped. 8301*0Sstevel@tonic-gate */ 8302*0Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_VALID; 8303*0Sstevel@tonic-gate 8304*0Sstevel@tonic-gate #endif /* XXX */ 8305*0Sstevel@tonic-gate 8306*0Sstevel@tonic-gate /* XXX for now don't allow dropping sockets XXX */ 8307*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8308*0Sstevel@tonic-gate } 8309*0Sstevel@tonic-gate 8310*0Sstevel@tonic-gate /* 8311*0Sstevel@tonic-gate * cs_get_socket - returns the socket and function numbers and a pointer 8312*0Sstevel@tonic-gate * to the socket structure 8313*0Sstevel@tonic-gate * 8314*0Sstevel@tonic-gate * calling: client_handle_t client_handle - client handle to extract 8315*0Sstevel@tonic-gate * socket number from 8316*0Sstevel@tonic-gate * uint32_t *socket - pointer to socket number to use if 8317*0Sstevel@tonic-gate * client_handle is for the SS client; 8318*0Sstevel@tonic-gate * this value will be filled in on 8319*0Sstevel@tonic-gate * return with the correct socket 8320*0Sstevel@tonic-gate * and function numbers if we 8321*0Sstevel@tonic-gate * return CS_SUCCESS 8322*0Sstevel@tonic-gate * uint32_t *function - pointer to return function number into 8323*0Sstevel@tonic-gate * if not NULL 8324*0Sstevel@tonic-gate * cs_socket_t **sp - pointer to a pointer where a pointer 8325*0Sstevel@tonic-gate * to the socket struct will be 8326*0Sstevel@tonic-gate * placed if this is non-NULL 8327*0Sstevel@tonic-gate * client_t **clp - pointer to a pointer where a pointer 8328*0Sstevel@tonic-gate * to the client struct will be 8329*0Sstevel@tonic-gate * placed if this is non-NULL 8330*0Sstevel@tonic-gate * 8331*0Sstevel@tonic-gate * The socket and function numbers are derived as follows: 8332*0Sstevel@tonic-gate * 8333*0Sstevel@tonic-gate * Client Type Socket Number Function Number 8334*0Sstevel@tonic-gate * PC card client From client_handle From client_handle 8335*0Sstevel@tonic-gate * Socket Services client From *socket From *socket 8336*0Sstevel@tonic-gate * CSI client From client_handle From *socket 8337*0Sstevel@tonic-gate */ 8338*0Sstevel@tonic-gate static uint32_t 8339*0Sstevel@tonic-gate cs_get_socket(client_handle_t client_handle, uint32_t *socket, 8340*0Sstevel@tonic-gate uint32_t *function, cs_socket_t **csp, client_t **clp) 8341*0Sstevel@tonic-gate { 8342*0Sstevel@tonic-gate cs_socket_t *sp; 8343*0Sstevel@tonic-gate client_t *client; 8344*0Sstevel@tonic-gate uint32_t sn, fn; 8345*0Sstevel@tonic-gate int ret; 8346*0Sstevel@tonic-gate 8347*0Sstevel@tonic-gate sn = *socket; 8348*0Sstevel@tonic-gate 8349*0Sstevel@tonic-gate /* 8350*0Sstevel@tonic-gate * If this is the Socket Services client, then return the 8351*0Sstevel@tonic-gate * socket and function numbers specified in the passed 8352*0Sstevel@tonic-gate * socket number parameter, otherwise extract the socket 8353*0Sstevel@tonic-gate * and function numbers from the client handle. 8354*0Sstevel@tonic-gate */ 8355*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 8356*0Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(sn); 8357*0Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(sn); 8358*0Sstevel@tonic-gate } else { 8359*0Sstevel@tonic-gate fn = GET_CLIENT_FUNCTION(client_handle); 8360*0Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(client_handle); 8361*0Sstevel@tonic-gate } 8362*0Sstevel@tonic-gate 8363*0Sstevel@tonic-gate /* 8364*0Sstevel@tonic-gate * Check to be sure that the socket number is in range 8365*0Sstevel@tonic-gate */ 8366*0Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(sn, cs_globals.max_socket_num))) 8367*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8368*0Sstevel@tonic-gate 8369*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 8370*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8371*0Sstevel@tonic-gate 8372*0Sstevel@tonic-gate /* 8373*0Sstevel@tonic-gate * If we were given a pointer, then fill it in with a pointer 8374*0Sstevel@tonic-gate * to this socket. 8375*0Sstevel@tonic-gate */ 8376*0Sstevel@tonic-gate if (csp) 8377*0Sstevel@tonic-gate *csp = sp; 8378*0Sstevel@tonic-gate 8379*0Sstevel@tonic-gate /* 8380*0Sstevel@tonic-gate * Search for the client; if it's not found, return an error. 8381*0Sstevel@tonic-gate */ 8382*0Sstevel@tonic-gate mutex_enter(&sp->lock); 8383*0Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &ret))) { 8384*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8385*0Sstevel@tonic-gate return (ret); 8386*0Sstevel@tonic-gate } 8387*0Sstevel@tonic-gate 8388*0Sstevel@tonic-gate /* 8389*0Sstevel@tonic-gate * If we're a CIS client, then extract the function number 8390*0Sstevel@tonic-gate * from the socket number. 8391*0Sstevel@tonic-gate */ 8392*0Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) 8393*0Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(*socket); 8394*0Sstevel@tonic-gate 8395*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8396*0Sstevel@tonic-gate 8397*0Sstevel@tonic-gate /* 8398*0Sstevel@tonic-gate * Return the found client pointer if the caller wants it. 8399*0Sstevel@tonic-gate */ 8400*0Sstevel@tonic-gate if (clp) 8401*0Sstevel@tonic-gate *clp = client; 8402*0Sstevel@tonic-gate 8403*0Sstevel@tonic-gate /* 8404*0Sstevel@tonic-gate * Return a socket number that is made up of the socket number 8405*0Sstevel@tonic-gate * and the function number. 8406*0Sstevel@tonic-gate */ 8407*0Sstevel@tonic-gate *socket = CS_MAKE_SOCKET_NUMBER(sn, fn); 8408*0Sstevel@tonic-gate 8409*0Sstevel@tonic-gate /* 8410*0Sstevel@tonic-gate * Return the function number if the caller wants it. 8411*0Sstevel@tonic-gate */ 8412*0Sstevel@tonic-gate if (function) 8413*0Sstevel@tonic-gate *function = fn; 8414*0Sstevel@tonic-gate 8415*0Sstevel@tonic-gate return (CS_SUCCESS); 8416*0Sstevel@tonic-gate } 8417*0Sstevel@tonic-gate 8418*0Sstevel@tonic-gate /* 8419*0Sstevel@tonic-gate * cs_get_wp - returns pointer to passed window number 8420*0Sstevel@tonic-gate * 8421*0Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 8422*0Sstevel@tonic-gate * NULL - if invalid window number passed in 8423*0Sstevel@tonic-gate */ 8424*0Sstevel@tonic-gate static cs_window_t * 8425*0Sstevel@tonic-gate cs_get_wp(uint32_t wn) 8426*0Sstevel@tonic-gate { 8427*0Sstevel@tonic-gate cs_window_t *cw; 8428*0Sstevel@tonic-gate 8429*0Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 8430*0Sstevel@tonic-gate return (NULL); 8431*0Sstevel@tonic-gate 8432*0Sstevel@tonic-gate if ((cw = cs_find_wp(wn)) == NULL) 8433*0Sstevel@tonic-gate return (NULL); 8434*0Sstevel@tonic-gate 8435*0Sstevel@tonic-gate if (cw->state & CW_WINDOW_VALID) 8436*0Sstevel@tonic-gate return (cw); 8437*0Sstevel@tonic-gate 8438*0Sstevel@tonic-gate #ifdef CS_DEBUG 8439*0Sstevel@tonic-gate if (cs_debug > 0) { 8440*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_wp(): wn=%d cw=%p\n", 8441*0Sstevel@tonic-gate (int)wn, (void *)cw); 8442*0Sstevel@tonic-gate } 8443*0Sstevel@tonic-gate #endif 8444*0Sstevel@tonic-gate 8445*0Sstevel@tonic-gate return (NULL); 8446*0Sstevel@tonic-gate } 8447*0Sstevel@tonic-gate 8448*0Sstevel@tonic-gate /* 8449*0Sstevel@tonic-gate * cs_find_wp - searches window list and returns pointer to passed window 8450*0Sstevel@tonic-gate * number 8451*0Sstevel@tonic-gate * 8452*0Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 8453*0Sstevel@tonic-gate * NULL - window not found 8454*0Sstevel@tonic-gate */ 8455*0Sstevel@tonic-gate static cs_window_t * 8456*0Sstevel@tonic-gate cs_find_wp(uint32_t wn) 8457*0Sstevel@tonic-gate { 8458*0Sstevel@tonic-gate cs_window_t *cw = cs_globals.cw; 8459*0Sstevel@tonic-gate 8460*0Sstevel@tonic-gate while (cw) { 8461*0Sstevel@tonic-gate if (cw->window_num == wn) 8462*0Sstevel@tonic-gate return (cw); 8463*0Sstevel@tonic-gate cw = cw->next; 8464*0Sstevel@tonic-gate } /* while */ 8465*0Sstevel@tonic-gate 8466*0Sstevel@tonic-gate #ifdef CS_DEBUG 8467*0Sstevel@tonic-gate if (cs_debug > 0) { 8468*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_find_wp(): wn=%d window_num=%d cw=%p\n", 8469*0Sstevel@tonic-gate (int)wn, (int)cw->window_num, (void *)cw); 8470*0Sstevel@tonic-gate } 8471*0Sstevel@tonic-gate #endif 8472*0Sstevel@tonic-gate 8473*0Sstevel@tonic-gate return (NULL); 8474*0Sstevel@tonic-gate } 8475*0Sstevel@tonic-gate 8476*0Sstevel@tonic-gate /* 8477*0Sstevel@tonic-gate * cs_add_windows - adds number of windows specified in "aw" to 8478*0Sstevel@tonic-gate * the global window list; start the window 8479*0Sstevel@tonic-gate * numbering at "bn" 8480*0Sstevel@tonic-gate * 8481*0Sstevel@tonic-gate * return: CS_SUCCESS - if windows added sucessfully 8482*0Sstevel@tonic-gate * CS_BAD_WINDOW - if unable to add windows 8483*0Sstevel@tonic-gate * 8484*0Sstevel@tonic-gate * Note: The window list must be protected by a lock by the caller. 8485*0Sstevel@tonic-gate */ 8486*0Sstevel@tonic-gate static int 8487*0Sstevel@tonic-gate cs_add_windows(int aw, uint32_t bn) 8488*0Sstevel@tonic-gate { 8489*0Sstevel@tonic-gate cs_window_t *cwp = cs_globals.cw; 8490*0Sstevel@tonic-gate cs_window_t *cw, *cwpp; 8491*0Sstevel@tonic-gate 8492*0Sstevel@tonic-gate if (aw <= 0) 8493*0Sstevel@tonic-gate return (CS_BAD_WINDOW); 8494*0Sstevel@tonic-gate 8495*0Sstevel@tonic-gate while (cwp) { 8496*0Sstevel@tonic-gate cwpp = cwp; 8497*0Sstevel@tonic-gate cwp = cwp->next; 8498*0Sstevel@tonic-gate } 8499*0Sstevel@tonic-gate 8500*0Sstevel@tonic-gate while (aw--) { 8501*0Sstevel@tonic-gate cw = (cs_window_t *)kmem_zalloc(sizeof (cs_window_t), KM_SLEEP); 8502*0Sstevel@tonic-gate 8503*0Sstevel@tonic-gate if (cs_globals.cw == NULL) { 8504*0Sstevel@tonic-gate cs_globals.cw = cw; 8505*0Sstevel@tonic-gate cwpp = cs_globals.cw; 8506*0Sstevel@tonic-gate } else { 8507*0Sstevel@tonic-gate cwpp->next = cw; 8508*0Sstevel@tonic-gate cwpp = cwpp->next; 8509*0Sstevel@tonic-gate } 8510*0Sstevel@tonic-gate 8511*0Sstevel@tonic-gate cwpp->window_num = bn++; 8512*0Sstevel@tonic-gate cwpp->state = CW_WINDOW_VALID; 8513*0Sstevel@tonic-gate 8514*0Sstevel@tonic-gate } /* while (aw) */ 8515*0Sstevel@tonic-gate 8516*0Sstevel@tonic-gate return (CS_SUCCESS); 8517*0Sstevel@tonic-gate } 8518*0Sstevel@tonic-gate 8519*0Sstevel@tonic-gate /* 8520*0Sstevel@tonic-gate * cs_ss_init - initialize CS items that need to wait until we receive 8521*0Sstevel@tonic-gate * a PCE_SS_INIT_STATE/PCE_SS_STATE_INIT event 8522*0Sstevel@tonic-gate * 8523*0Sstevel@tonic-gate * return: CS_SUCESS - if sucessfully initialized 8524*0Sstevel@tonic-gate * (various) if error initializing 8525*0Sstevel@tonic-gate * 8526*0Sstevel@tonic-gate * At this point, we expect that Socket Services has setup the 8527*0Sstevel@tonic-gate * following global variables for us: 8528*0Sstevel@tonic-gate * 8529*0Sstevel@tonic-gate * cs_socket_services - Socket Services entry point 8530*0Sstevel@tonic-gate * cis_parser - CIS parser entry point 8531*0Sstevel@tonic-gate */ 8532*0Sstevel@tonic-gate static uint32_t 8533*0Sstevel@tonic-gate cs_ss_init() 8534*0Sstevel@tonic-gate { 8535*0Sstevel@tonic-gate cs_register_cardservices_t rcs; 8536*0Sstevel@tonic-gate csregister_t csr; 8537*0Sstevel@tonic-gate uint32_t ret; 8538*0Sstevel@tonic-gate 8539*0Sstevel@tonic-gate /* 8540*0Sstevel@tonic-gate * Fill out the parameters for CISP_CIS_SETUP 8541*0Sstevel@tonic-gate */ 8542*0Sstevel@tonic-gate csr.cs_magic = PCCS_MAGIC; 8543*0Sstevel@tonic-gate csr.cs_version = PCCS_VERSION; 8544*0Sstevel@tonic-gate csr.cs_card_services = CardServices; 8545*0Sstevel@tonic-gate csr.cs_event = NULL; 8546*0Sstevel@tonic-gate 8547*0Sstevel@tonic-gate /* 8548*0Sstevel@tonic-gate * Call into the CIS module and tell it what the private 8549*0Sstevel@tonic-gate * Card Services entry point is. The CIS module will 8550*0Sstevel@tonic-gate * call us back at CardServices(CISRegister, ...) 8551*0Sstevel@tonic-gate * with the address of various CIS-specific global 8552*0Sstevel@tonic-gate * data structures. 8553*0Sstevel@tonic-gate */ 8554*0Sstevel@tonic-gate CIS_PARSER(CISP_CIS_SETUP, &csr); 8555*0Sstevel@tonic-gate 8556*0Sstevel@tonic-gate /* 8557*0Sstevel@tonic-gate * Register with the Card Services kernel stubs module 8558*0Sstevel@tonic-gate */ 8559*0Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 8560*0Sstevel@tonic-gate rcs.function = CS_ENTRY_REGISTER; 8561*0Sstevel@tonic-gate rcs.cardservices = CardServices; 8562*0Sstevel@tonic-gate 8563*0Sstevel@tonic-gate if ((ret = csx_register_cardservices(&rcs)) != CS_SUCCESS) { 8564*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_init: can't register with " 8565*0Sstevel@tonic-gate "cs_stubs, retcode = 0x%x\n", ret); 8566*0Sstevel@tonic-gate return (ret); 8567*0Sstevel@tonic-gate } /* csx_register_cardservices */ 8568*0Sstevel@tonic-gate 8569*0Sstevel@tonic-gate return (CS_SUCCESS); 8570*0Sstevel@tonic-gate } 8571*0Sstevel@tonic-gate 8572*0Sstevel@tonic-gate /* 8573*0Sstevel@tonic-gate * cs_create_cis - reads CIS on card in socket and creates CIS lists 8574*0Sstevel@tonic-gate * 8575*0Sstevel@tonic-gate * Most of the work is done in the CIS module in the CISP_CIS_LIST_CREATE 8576*0Sstevel@tonic-gate * function. 8577*0Sstevel@tonic-gate * 8578*0Sstevel@tonic-gate * This function returns: 8579*0Sstevel@tonic-gate * 8580*0Sstevel@tonic-gate * CS_SUCCESS - if the CIS lists were created sucessfully 8581*0Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 8582*0Sstevel@tonic-gate * not be setup 8583*0Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chains 8584*0Sstevel@tonic-gate * CS_BAD_OFFSET - if the CIS parser tried to read past the 8585*0Sstevel@tonic-gate * boundries of the allocated CIS window 8586*0Sstevel@tonic-gate */ 8587*0Sstevel@tonic-gate static int 8588*0Sstevel@tonic-gate cs_create_cis(cs_socket_t *sp) 8589*0Sstevel@tonic-gate { 8590*0Sstevel@tonic-gate uint32_t ret; 8591*0Sstevel@tonic-gate 8592*0Sstevel@tonic-gate ret = (uint32_t)(uintptr_t)CIS_PARSER(CISP_CIS_LIST_CREATE, 8593*0Sstevel@tonic-gate cis_cistpl_std_callout, sp); 8594*0Sstevel@tonic-gate 8595*0Sstevel@tonic-gate #ifdef CS_DEBUG 8596*0Sstevel@tonic-gate if (ret == CS_NO_CIS) { 8597*0Sstevel@tonic-gate if (cs_debug > 0) 8598*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d has no CIS\n", 8599*0Sstevel@tonic-gate sp->socket_num); 8600*0Sstevel@tonic-gate } else if (ret != CS_SUCCESS) { 8601*0Sstevel@tonic-gate if (cs_debug > 0) 8602*0Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d ERROR = 0x%x\n", 8603*0Sstevel@tonic-gate sp->socket_num, ret); 8604*0Sstevel@tonic-gate return (ret); 8605*0Sstevel@tonic-gate } 8606*0Sstevel@tonic-gate #else 8607*0Sstevel@tonic-gate if (ret != CS_NO_CIS) 8608*0Sstevel@tonic-gate if (ret != CS_SUCCESS) 8609*0Sstevel@tonic-gate return (ret); 8610*0Sstevel@tonic-gate #endif 8611*0Sstevel@tonic-gate 8612*0Sstevel@tonic-gate /* 8613*0Sstevel@tonic-gate * If this card didn't have any CIS at all, there's not much 8614*0Sstevel@tonic-gate * else for us to do. 8615*0Sstevel@tonic-gate */ 8616*0Sstevel@tonic-gate if (!(sp->cis_flags & CW_VALID_CIS)) 8617*0Sstevel@tonic-gate return (CS_SUCCESS); 8618*0Sstevel@tonic-gate 8619*0Sstevel@tonic-gate /* 8620*0Sstevel@tonic-gate * If this is a single-function card, we need to move the CIS list 8621*0Sstevel@tonic-gate * that is currently on CS_GLOBAL_CIS to the function zero 8622*0Sstevel@tonic-gate * CIS list. 8623*0Sstevel@tonic-gate */ 8624*0Sstevel@tonic-gate if (!(sp->cis_flags & CW_MULTI_FUNCTION_CIS)) { 8625*0Sstevel@tonic-gate bcopy((caddr_t)&sp->cis[CS_GLOBAL_CIS], 8626*0Sstevel@tonic-gate (caddr_t)&sp->cis[0], sizeof (cis_info_t)); 8627*0Sstevel@tonic-gate bzero((caddr_t)&sp->cis[CS_GLOBAL_CIS], sizeof (cis_info_t)); 8628*0Sstevel@tonic-gate } /* !CW_MULTI_FUNCTION_CIS */ 8629*0Sstevel@tonic-gate 8630*0Sstevel@tonic-gate return (CS_SUCCESS); 8631*0Sstevel@tonic-gate } 8632*0Sstevel@tonic-gate 8633*0Sstevel@tonic-gate /* 8634*0Sstevel@tonic-gate * cs_destroy_cis - destroys CIS list for socket 8635*0Sstevel@tonic-gate */ 8636*0Sstevel@tonic-gate static int 8637*0Sstevel@tonic-gate cs_destroy_cis(cs_socket_t *sp) 8638*0Sstevel@tonic-gate { 8639*0Sstevel@tonic-gate CIS_PARSER(CISP_CIS_LIST_DESTROY, sp); 8640*0Sstevel@tonic-gate 8641*0Sstevel@tonic-gate return (CS_SUCCESS); 8642*0Sstevel@tonic-gate } 8643*0Sstevel@tonic-gate 8644*0Sstevel@tonic-gate /* 8645*0Sstevel@tonic-gate * cs_get_client_info - This function is GetClientInfo. 8646*0Sstevel@tonic-gate * 8647*0Sstevel@tonic-gate * calling: client_handle_t - client handle to get client info on 8648*0Sstevel@tonic-gate * client_info_t * - pointer to a client_info_t structure 8649*0Sstevel@tonic-gate * to return client information in 8650*0Sstevel@tonic-gate * 8651*0Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 8652*0Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8653*0Sstevel@tonic-gate * handle passed in 8654*0Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 8655*0Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 8656*0Sstevel@tonic-gate * or if invalid client info 8657*0Sstevel@tonic-gate * retreived from client 8658*0Sstevel@tonic-gate */ 8659*0Sstevel@tonic-gate static int 8660*0Sstevel@tonic-gate cs_get_client_info(client_handle_t client_handle, client_info_t *ci) 8661*0Sstevel@tonic-gate { 8662*0Sstevel@tonic-gate cs_socket_t *sp; 8663*0Sstevel@tonic-gate client_t *client; 8664*0Sstevel@tonic-gate client_info_t *cinfo; 8665*0Sstevel@tonic-gate int ret = CS_SUCCESS; 8666*0Sstevel@tonic-gate 8667*0Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 8668*0Sstevel@tonic-gate ci->Attributes = (CS_CLIENT_INFO_SOCKET_SERVICES | 8669*0Sstevel@tonic-gate CS_CLIENT_INFO_VALID); 8670*0Sstevel@tonic-gate return (CS_SUCCESS); 8671*0Sstevel@tonic-gate } /* CLIENT_HANDLE_IS_SS */ 8672*0Sstevel@tonic-gate 8673*0Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 8674*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8675*0Sstevel@tonic-gate 8676*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8677*0Sstevel@tonic-gate mutex_enter(&sp->lock); 8678*0Sstevel@tonic-gate 8679*0Sstevel@tonic-gate if ((client = cs_find_client(client_handle, &ret)) == NULL) { 8680*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8681*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8682*0Sstevel@tonic-gate return (ret); 8683*0Sstevel@tonic-gate } /* cs_find_client */ 8684*0Sstevel@tonic-gate 8685*0Sstevel@tonic-gate /* 8686*0Sstevel@tonic-gate * If this client is not handling CS_EVENT_CLIENT_INFO events, 8687*0Sstevel@tonic-gate * then don't bother to even wake up the event thread. 8688*0Sstevel@tonic-gate */ 8689*0Sstevel@tonic-gate if (!((client->event_mask | client->global_mask) & 8690*0Sstevel@tonic-gate CS_EVENT_CLIENT_INFO)) { 8691*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8692*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8693*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8694*0Sstevel@tonic-gate } /* !CS_EVENT_CLIENT_INFO */ 8695*0Sstevel@tonic-gate 8696*0Sstevel@tonic-gate cinfo = &client->event_callback_args.client_info; 8697*0Sstevel@tonic-gate 8698*0Sstevel@tonic-gate bzero((caddr_t)cinfo, sizeof (client_info_t)); 8699*0Sstevel@tonic-gate cinfo->Attributes = (ci->Attributes & CS_CLIENT_INFO_SUBSVC_MASK); 8700*0Sstevel@tonic-gate 8701*0Sstevel@tonic-gate client->events |= CS_EVENT_CLIENT_INFO; 8702*0Sstevel@tonic-gate 8703*0Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 8704*0Sstevel@tonic-gate mutex_exit(&sp->lock); 8705*0Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 8706*0Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 8707*0Sstevel@tonic-gate 8708*0Sstevel@tonic-gate if (cinfo->Attributes & CS_CLIENT_INFO_VALID) { 8709*0Sstevel@tonic-gate bcopy((caddr_t)cinfo, (caddr_t)ci, sizeof (client_info_t)); 8710*0Sstevel@tonic-gate ci->Attributes &= (CS_CLIENT_INFO_FLAGS_MASK | 8711*0Sstevel@tonic-gate CS_CLIENT_INFO_SUBSVC_MASK); 8712*0Sstevel@tonic-gate ci->Attributes &= ~(CS_CLIENT_INFO_CLIENT_MASK | 8713*0Sstevel@tonic-gate INFO_CARD_FLAGS_MASK | 8714*0Sstevel@tonic-gate CS_CLIENT_INFO_CLIENT_ACTIVE); 8715*0Sstevel@tonic-gate ci->Attributes |= (client->flags & (CS_CLIENT_INFO_CLIENT_MASK | 8716*0Sstevel@tonic-gate INFO_CARD_FLAGS_MASK)); 8717*0Sstevel@tonic-gate (void) strcpy(ci->DriverName, client->driver_name); 8718*0Sstevel@tonic-gate if (cs_card_for_client(client)) 8719*0Sstevel@tonic-gate ci->Attributes |= CS_CLIENT_INFO_CLIENT_ACTIVE; 8720*0Sstevel@tonic-gate } else { 8721*0Sstevel@tonic-gate ret = CS_NO_MORE_ITEMS; 8722*0Sstevel@tonic-gate } /* CS_CLIENT_INFO_VALID */ 8723*0Sstevel@tonic-gate 8724*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8725*0Sstevel@tonic-gate 8726*0Sstevel@tonic-gate return (ret); 8727*0Sstevel@tonic-gate } 8728*0Sstevel@tonic-gate 8729*0Sstevel@tonic-gate /* 8730*0Sstevel@tonic-gate * cs_get_firstnext_client - This function is GetFirstClient and 8731*0Sstevel@tonic-gate * GetNextClient 8732*0Sstevel@tonic-gate * 8733*0Sstevel@tonic-gate * calling: get_firstnext_client_t * - pointer to a get_firstnext_client_t 8734*0Sstevel@tonic-gate * structure to return client handle and 8735*0Sstevel@tonic-gate * attributes in 8736*0Sstevel@tonic-gate * flags - one of the following: 8737*0Sstevel@tonic-gate * CS_GET_FIRST_FLAG - get first client handle 8738*0Sstevel@tonic-gate * CS_GET_NEXT_FLAG - get next client handle 8739*0Sstevel@tonic-gate * 8740*0Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 8741*0Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8742*0Sstevel@tonic-gate * handle passed in 8743*0Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 8744*0Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 8745*0Sstevel@tonic-gate * or if invalid client info 8746*0Sstevel@tonic-gate * retreived from client 8747*0Sstevel@tonic-gate */ 8748*0Sstevel@tonic-gate static int 8749*0Sstevel@tonic-gate cs_get_firstnext_client(get_firstnext_client_t *fnc, uint32_t flags) 8750*0Sstevel@tonic-gate { 8751*0Sstevel@tonic-gate cs_socket_t *sp; 8752*0Sstevel@tonic-gate client_t *client; 8753*0Sstevel@tonic-gate uint32_t sn = 0; 8754*0Sstevel@tonic-gate int ret = CS_SUCCESS; 8755*0Sstevel@tonic-gate 8756*0Sstevel@tonic-gate switch (flags) { 8757*0Sstevel@tonic-gate case CS_GET_FIRST_FLAG: 8758*0Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8759*0Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 8760*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 8761*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8762*0Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 8763*0Sstevel@tonic-gate break; 8764*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8765*0Sstevel@tonic-gate } /* if */ 8766*0Sstevel@tonic-gate sn++; 8767*0Sstevel@tonic-gate } /* while */ 8768*0Sstevel@tonic-gate 8769*0Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 8770*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8771*0Sstevel@tonic-gate } else if (fnc->Attributes & 8772*0Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8773*0Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(fnc->Socket))) == 8774*0Sstevel@tonic-gate NULL) 8775*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8776*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8777*0Sstevel@tonic-gate if ((client = sp->client_list) == NULL) { 8778*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8779*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8780*0Sstevel@tonic-gate } 8781*0Sstevel@tonic-gate } else { 8782*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 8783*0Sstevel@tonic-gate } 8784*0Sstevel@tonic-gate 8785*0Sstevel@tonic-gate fnc->client_handle = client->client_handle; 8786*0Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 8787*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8788*0Sstevel@tonic-gate break; 8789*0Sstevel@tonic-gate case CS_GET_NEXT_FLAG: 8790*0Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8791*0Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(fnc->client_handle); 8792*0Sstevel@tonic-gate 8793*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 8794*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8795*0Sstevel@tonic-gate 8796*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8797*0Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 8798*0Sstevel@tonic-gate &ret)) == NULL) { 8799*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8800*0Sstevel@tonic-gate return (ret); 8801*0Sstevel@tonic-gate } 8802*0Sstevel@tonic-gate if ((client = client->next) == NULL) { 8803*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8804*0Sstevel@tonic-gate sn++; 8805*0Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 8806*0Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 8807*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8808*0Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 8809*0Sstevel@tonic-gate break; 8810*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8811*0Sstevel@tonic-gate } /* if */ 8812*0Sstevel@tonic-gate sn++; 8813*0Sstevel@tonic-gate } /* while */ 8814*0Sstevel@tonic-gate 8815*0Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 8816*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8817*0Sstevel@tonic-gate } /* client = client->next */ 8818*0Sstevel@tonic-gate 8819*0Sstevel@tonic-gate } else if (fnc->Attributes & 8820*0Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8821*0Sstevel@tonic-gate sp = cs_get_sp(GET_CLIENT_SOCKET(fnc->client_handle)); 8822*0Sstevel@tonic-gate if (sp == NULL) 8823*0Sstevel@tonic-gate return (CS_BAD_SOCKET); 8824*0Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8825*0Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 8826*0Sstevel@tonic-gate &ret)) == NULL) { 8827*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8828*0Sstevel@tonic-gate return (ret); 8829*0Sstevel@tonic-gate } 8830*0Sstevel@tonic-gate if ((client = client->next) == NULL) { 8831*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8832*0Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8833*0Sstevel@tonic-gate } 8834*0Sstevel@tonic-gate } else { 8835*0Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 8836*0Sstevel@tonic-gate } 8837*0Sstevel@tonic-gate 8838*0Sstevel@tonic-gate fnc->client_handle = client->client_handle; 8839*0Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 8840*0Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8841*0Sstevel@tonic-gate break; 8842*0Sstevel@tonic-gate default: 8843*0Sstevel@tonic-gate ret = CS_BAD_ATTRIBUTE; 8844*0Sstevel@tonic-gate break; 8845*0Sstevel@tonic-gate 8846*0Sstevel@tonic-gate } /* switch */ 8847*0Sstevel@tonic-gate 8848*0Sstevel@tonic-gate return (ret); 8849*0Sstevel@tonic-gate } 8850*0Sstevel@tonic-gate 8851*0Sstevel@tonic-gate /* 8852*0Sstevel@tonic-gate * cs_set_acc_attributes - converts Card Services endianness and 8853*0Sstevel@tonic-gate * data ordering values to values 8854*0Sstevel@tonic-gate * that Socket Services understands 8855*0Sstevel@tonic-gate * 8856*0Sstevel@tonic-gate * calling: *sw - pointer to a set_window_t to set attributes in 8857*0Sstevel@tonic-gate * Attributes - CS attributes 8858*0Sstevel@tonic-gate */ 8859*0Sstevel@tonic-gate static void 8860*0Sstevel@tonic-gate cs_set_acc_attributes(set_window_t *sw, uint32_t Attributes) 8861*0Sstevel@tonic-gate { 8862*0Sstevel@tonic-gate sw->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 8863*0Sstevel@tonic-gate 8864*0Sstevel@tonic-gate switch (Attributes & WIN_ACC_ENDIAN_MASK) { 8865*0Sstevel@tonic-gate case WIN_ACC_LITTLE_ENDIAN: 8866*0Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 8867*0Sstevel@tonic-gate break; 8868*0Sstevel@tonic-gate case WIN_ACC_BIG_ENDIAN: 8869*0Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 8870*0Sstevel@tonic-gate break; 8871*0Sstevel@tonic-gate case WIN_ACC_NEVER_SWAP: 8872*0Sstevel@tonic-gate default: 8873*0Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 8874*0Sstevel@tonic-gate break; 8875*0Sstevel@tonic-gate } /* switch */ 8876*0Sstevel@tonic-gate 8877*0Sstevel@tonic-gate switch (Attributes & WIN_ACC_ORDER_MASK) { 8878*0Sstevel@tonic-gate case WIN_ACC_UNORDERED_OK: 8879*0Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC; 8880*0Sstevel@tonic-gate break; 8881*0Sstevel@tonic-gate case WIN_ACC_MERGING_OK: 8882*0Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_MERGING_OK_ACC; 8883*0Sstevel@tonic-gate break; 8884*0Sstevel@tonic-gate case WIN_ACC_LOADCACHING_OK: 8885*0Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_LOADCACHING_OK_ACC; 8886*0Sstevel@tonic-gate break; 8887*0Sstevel@tonic-gate case WIN_ACC_STORECACHING_OK: 8888*0Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC; 8889*0Sstevel@tonic-gate break; 8890*0Sstevel@tonic-gate case WIN_ACC_STRICT_ORDER: 8891*0Sstevel@tonic-gate default: 8892*0Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 8893*0Sstevel@tonic-gate break; 8894*0Sstevel@tonic-gate } /* switch */ 8895*0Sstevel@tonic-gate } 8896