1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * PCMCIA Card Services 31*7c478bd9Sstevel@tonic-gate * The PCMCIA Card Services is a loadable module which 32*7c478bd9Sstevel@tonic-gate * presents the Card Services interface to client device 33*7c478bd9Sstevel@tonic-gate * drivers. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * Card Services uses Socket Services-like calls into the 36*7c478bd9Sstevel@tonic-gate * PCMCIA nexus driver to manipulate socket and adapter 37*7c478bd9Sstevel@tonic-gate * resources. 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * Note that a bunch of comments are not indented correctly with the 40*7c478bd9Sstevel@tonic-gate * code that they are commenting on. This is because cstyle is 41*7c478bd9Sstevel@tonic-gate * is inflexible concerning 4-column indenting. 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #if defined(DEBUG) 45*7c478bd9Sstevel@tonic-gate #define CS_DEBUG 46*7c478bd9Sstevel@tonic-gate #endif 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/var.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/thread.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 69*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #include <sys/pctypes.h> 76*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h> 77*7c478bd9Sstevel@tonic-gate #include <sys/pcmcia.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/sservice.h> 79*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis.h> 80*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h> 81*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs.h> 82*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h> 83*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_stubs.h> 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * The cs_strings header file is where all of the major strings that 87*7c478bd9Sstevel@tonic-gate * Card Services uses are located. 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_strings.h> 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * Function declarations 94*7c478bd9Sstevel@tonic-gate * 95*7c478bd9Sstevel@tonic-gate * The main Card Services entry point 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate int CardServices(int function, ...); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * functions and globals used by Socket Services 101*7c478bd9Sstevel@tonic-gate * 102*7c478bd9Sstevel@tonic-gate * WAS: void *(*cis_parser)(int, ...) = NULL; 103*7c478bd9Sstevel@tonic-gate */ 104*7c478bd9Sstevel@tonic-gate void *(*cis_parser)(int, ...) = NULL; 105*7c478bd9Sstevel@tonic-gate csfunction_t *cs_socket_services = NULL; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * event handling functions 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate static event_t ss_to_cs_events(cs_socket_t *, event_t); 111*7c478bd9Sstevel@tonic-gate static event_t cs_cse2sbm(event_t); 112*7c478bd9Sstevel@tonic-gate static void cs_event_thread(uint32_t); 113*7c478bd9Sstevel@tonic-gate static int cs_card_insertion(cs_socket_t *, event_t); 114*7c478bd9Sstevel@tonic-gate static int cs_card_removal(cs_socket_t *); 115*7c478bd9Sstevel@tonic-gate static void cs_ss_thread(uint32_t); 116*7c478bd9Sstevel@tonic-gate void cs_ready_timeout(void *); 117*7c478bd9Sstevel@tonic-gate static int cs_card_for_client(client_t *); 118*7c478bd9Sstevel@tonic-gate static int cs_request_socket_mask(client_handle_t, request_socket_mask_t *); 119*7c478bd9Sstevel@tonic-gate static int cs_release_socket_mask(client_handle_t, release_socket_mask_t *); 120*7c478bd9Sstevel@tonic-gate static int cs_get_event_mask(client_handle_t, sockevent_t *); 121*7c478bd9Sstevel@tonic-gate static int cs_set_event_mask(client_handle_t, sockevent_t *); 122*7c478bd9Sstevel@tonic-gate static int cs_event2text(event2text_t *, int); 123*7c478bd9Sstevel@tonic-gate static int cs_read_event_status(cs_socket_t *, client_t *, event_t *, 124*7c478bd9Sstevel@tonic-gate get_ss_status_t *, int); 125*7c478bd9Sstevel@tonic-gate uint32_t cs_socket_event_softintr(caddr_t); 126*7c478bd9Sstevel@tonic-gate void cs_event_softintr_timeout(void *); 127*7c478bd9Sstevel@tonic-gate static int cs_get_status(client_handle_t, get_status_t *); 128*7c478bd9Sstevel@tonic-gate static uint32_t cs_sbm2cse(uint32_t); 129*7c478bd9Sstevel@tonic-gate static unsigned cs_merge_event_masks(cs_socket_t *, client_t *); 130*7c478bd9Sstevel@tonic-gate static int cs_set_socket_event_mask(cs_socket_t *, unsigned); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * SS<->CS communication and internal socket and window handling functions 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate static uint32_t cs_add_socket(uint32_t); 136*7c478bd9Sstevel@tonic-gate static uint32_t cs_drop_socket(uint32_t); 137*7c478bd9Sstevel@tonic-gate static cs_socket_t *cs_get_sp(uint32_t); 138*7c478bd9Sstevel@tonic-gate static cs_socket_t *cs_find_sp(uint32_t); 139*7c478bd9Sstevel@tonic-gate static cs_window_t *cs_get_wp(uint32_t); 140*7c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_wp(uint32_t); 141*7c478bd9Sstevel@tonic-gate static int cs_add_windows(int, uint32_t); 142*7c478bd9Sstevel@tonic-gate static uint32_t cs_ss_init(); 143*7c478bd9Sstevel@tonic-gate static void cs_set_acc_attributes(set_window_t *, uint32_t); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * CIS handling functions 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate cistpl_callout_t *cis_cistpl_std_callout; 149*7c478bd9Sstevel@tonic-gate static int cs_parse_tuple(client_handle_t, tuple_t *, cisparse_t *, cisdata_t); 150*7c478bd9Sstevel@tonic-gate static int cs_get_tuple_data(client_handle_t, tuple_t *); 151*7c478bd9Sstevel@tonic-gate static int cs_validate_cis(client_handle_t, cisinfo_t *); 152*7c478bd9Sstevel@tonic-gate static int cs_get_firstnext_tuple(client_handle_t, tuple_t *, uint32_t); 153*7c478bd9Sstevel@tonic-gate static int cs_create_cis(cs_socket_t *); 154*7c478bd9Sstevel@tonic-gate static int cs_destroy_cis(cs_socket_t *); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * client handling functions 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate unsigned cs_create_next_client_minor(unsigned, unsigned); 160*7c478bd9Sstevel@tonic-gate static client_t *cs_find_client(client_handle_t, int *); 161*7c478bd9Sstevel@tonic-gate static client_handle_t cs_create_client_handle(unsigned, client_t *); 162*7c478bd9Sstevel@tonic-gate static int cs_destroy_client_handle(client_handle_t); 163*7c478bd9Sstevel@tonic-gate static int cs_register_client(client_handle_t *, client_reg_t *); 164*7c478bd9Sstevel@tonic-gate static int cs_deregister_client(client_handle_t); 165*7c478bd9Sstevel@tonic-gate static int cs_deregister_mtd(client_handle_t); 166*7c478bd9Sstevel@tonic-gate static void cs_clear_superclient_lock(int); 167*7c478bd9Sstevel@tonic-gate static int cs_add_client_to_socket(unsigned, client_handle_t *, 168*7c478bd9Sstevel@tonic-gate client_reg_t *, int); 169*7c478bd9Sstevel@tonic-gate static int cs_get_client_info(client_handle_t, client_info_t *); 170*7c478bd9Sstevel@tonic-gate static int cs_get_firstnext_client(get_firstnext_client_t *, uint32_t); 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * window handling functions 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate static int cs_request_window(client_handle_t, window_handle_t *, win_req_t *); 176*7c478bd9Sstevel@tonic-gate static int cs_release_window(window_handle_t); 177*7c478bd9Sstevel@tonic-gate static int cs_modify_window(window_handle_t, modify_win_t *); 178*7c478bd9Sstevel@tonic-gate static int cs_modify_mem_window(window_handle_t, modify_win_t *, win_req_t *, 179*7c478bd9Sstevel@tonic-gate int); 180*7c478bd9Sstevel@tonic-gate static int cs_map_mem_page(window_handle_t, map_mem_page_t *); 181*7c478bd9Sstevel@tonic-gate static int cs_find_mem_window(uint32_t, win_req_t *, uint32_t *); 182*7c478bd9Sstevel@tonic-gate static int cs_memwin_space_and_map_ok(inquire_window_t *, win_req_t *); 183*7c478bd9Sstevel@tonic-gate static int cs_valid_window_speed(inquire_window_t *, uint32_t); 184*7c478bd9Sstevel@tonic-gate static window_handle_t cs_create_window_handle(uint32_t); 185*7c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_window(window_handle_t); 186*7c478bd9Sstevel@tonic-gate static int cs_find_io_win(uint32_t, iowin_char_t *, uint32_t *, uint32_t *); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * IO, IRQ and configuration handling functions 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate static int cs_request_io(client_handle_t, io_req_t *); 192*7c478bd9Sstevel@tonic-gate static int cs_release_io(client_handle_t, io_req_t *); 193*7c478bd9Sstevel@tonic-gate static int cs_allocate_io_win(uint32_t, uint32_t, uint32_t *); 194*7c478bd9Sstevel@tonic-gate static int cs_setup_io_win(uint32_t, uint32_t, baseaddru_t *, 195*7c478bd9Sstevel@tonic-gate uint32_t *, uint32_t, uint32_t); 196*7c478bd9Sstevel@tonic-gate static int cs_request_irq(client_handle_t, irq_req_t *); 197*7c478bd9Sstevel@tonic-gate static int cs_release_irq(client_handle_t, irq_req_t *); 198*7c478bd9Sstevel@tonic-gate static int cs_request_configuration(client_handle_t, config_req_t *); 199*7c478bd9Sstevel@tonic-gate static int cs_release_configuration(client_handle_t, release_config_t *); 200*7c478bd9Sstevel@tonic-gate static int cs_modify_configuration(client_handle_t, modify_config_t *); 201*7c478bd9Sstevel@tonic-gate static int cs_access_configuration_register(client_handle_t, 202*7c478bd9Sstevel@tonic-gate access_config_reg_t *); 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * RESET and general info functions 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate static int cs_reset_function(client_handle_t, reset_function_t *); 208*7c478bd9Sstevel@tonic-gate static int cs_get_configuration_info(client_handle_t *, 209*7c478bd9Sstevel@tonic-gate get_configuration_info_t *); 210*7c478bd9Sstevel@tonic-gate static int cs_get_cardservices_info(client_handle_t, 211*7c478bd9Sstevel@tonic-gate get_cardservices_info_t *); 212*7c478bd9Sstevel@tonic-gate static int cs_get_physical_adapter_info(client_handle_t, 213*7c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * general functions 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate static uint32_t cs_get_socket(client_handle_t, uint32_t *, uint32_t *, 219*7c478bd9Sstevel@tonic-gate cs_socket_t **, client_t **); 220*7c478bd9Sstevel@tonic-gate static int cs_convert_speed(convert_speed_t *); 221*7c478bd9Sstevel@tonic-gate static int cs_convert_size(convert_size_t *); 222*7c478bd9Sstevel@tonic-gate static char *cs_error2text(int, int); 223*7c478bd9Sstevel@tonic-gate static int cs_map_log_socket(client_handle_t, map_log_socket_t *); 224*7c478bd9Sstevel@tonic-gate static int cs_convert_powerlevel(uint32_t, uint32_t, uint32_t, unsigned *); 225*7c478bd9Sstevel@tonic-gate static int cs_make_device_node(client_handle_t, make_device_node_t *); 226*7c478bd9Sstevel@tonic-gate static int cs_remove_device_node(client_handle_t, remove_device_node_t *); 227*7c478bd9Sstevel@tonic-gate static int cs_ddi_info(cs_ddi_info_t *); 228*7c478bd9Sstevel@tonic-gate static int cs_init_cis_window(cs_socket_t *, uint32_t *, acc_handle_t *, 229*7c478bd9Sstevel@tonic-gate uint32_t); 230*7c478bd9Sstevel@tonic-gate static int cs_sys_ctl(cs_sys_ctl_t *); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * global variables 234*7c478bd9Sstevel@tonic-gate */ 235*7c478bd9Sstevel@tonic-gate static int cs_max_client_handles = CS_MAX_CLIENTS; 236*7c478bd9Sstevel@tonic-gate static client_t cs_socket_services_client; /* global SS client */ 237*7c478bd9Sstevel@tonic-gate static client_types_t client_types[MAX_CLIENT_TYPES]; 238*7c478bd9Sstevel@tonic-gate static cs_globals_t cs_globals; 239*7c478bd9Sstevel@tonic-gate int cs_reset_timeout_time = RESET_TIMEOUT_TIME; 240*7c478bd9Sstevel@tonic-gate int cs_rc1_delay = CS_RC1_DELAY; 241*7c478bd9Sstevel@tonic-gate int cs_rc2_delay = CS_RC2_DELAY; 242*7c478bd9Sstevel@tonic-gate int cs_rq_delay = CS_RQ_DELAY; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 245*7c478bd9Sstevel@tonic-gate int cs_debug = 0; 246*7c478bd9Sstevel@tonic-gate #endif 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate /* 249*7c478bd9Sstevel@tonic-gate * cs_init - Initialize CS internal structures, databases, and state, 250*7c478bd9Sstevel@tonic-gate * and register with SS 251*7c478bd9Sstevel@tonic-gate * 252*7c478bd9Sstevel@tonic-gate * XXX - Need to make sure that if we fail at any point that we free 253*7c478bd9Sstevel@tonic-gate * any resources that we allocated, as well as kill any 254*7c478bd9Sstevel@tonic-gate * threads that may have been started. 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate int 257*7c478bd9Sstevel@tonic-gate cs_init() 258*7c478bd9Sstevel@tonic-gate { 259*7c478bd9Sstevel@tonic-gate client_types_t *ct; 260*7c478bd9Sstevel@tonic-gate client_t *client; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Initialize the CS global structure 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate bzero((caddr_t)&cs_globals, sizeof (cs_globals_t)); 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.global_lock, NULL, MUTEX_DRIVER, NULL); 268*7c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.window_lock, NULL, MUTEX_DRIVER, NULL); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate cs_globals.init_state = GLOBAL_INIT_STATE_MUTEX; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * Set up the global Socket Services client, since we're going to 274*7c478bd9Sstevel@tonic-gate * need it once we register with SS. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate client = &cs_socket_services_client; 277*7c478bd9Sstevel@tonic-gate bzero((caddr_t)client, sizeof (client_t)); 278*7c478bd9Sstevel@tonic-gate client->client_handle = CS_SS_CLIENT_HANDLE; 279*7c478bd9Sstevel@tonic-gate client->flags |= (INFO_SOCKET_SERVICES | CLIENT_CARD_INSERTED); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Setup the client type structure - this is used in the socket event 283*7c478bd9Sstevel@tonic-gate * thread to sequence the delivery of events to all clients on 284*7c478bd9Sstevel@tonic-gate * the socket. 285*7c478bd9Sstevel@tonic-gate */ 286*7c478bd9Sstevel@tonic-gate ct = &client_types[0]; 287*7c478bd9Sstevel@tonic-gate ct->type = INFO_IO_CLIENT; 288*7c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_LIFO; 289*7c478bd9Sstevel@tonic-gate ct->next = &client_types[1]; 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate ct = ct->next; 292*7c478bd9Sstevel@tonic-gate ct->type = INFO_MTD_CLIENT; 293*7c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 294*7c478bd9Sstevel@tonic-gate ct->next = &client_types[2]; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate ct = ct->next; 297*7c478bd9Sstevel@tonic-gate ct->type = INFO_MEM_CLIENT; 298*7c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 299*7c478bd9Sstevel@tonic-gate ct->next = NULL; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * cs_deinit - Deinitialize CS 306*7c478bd9Sstevel@tonic-gate * 307*7c478bd9Sstevel@tonic-gate * This function cleans up any allocated resources, stops any running threads, 308*7c478bd9Sstevel@tonic-gate * destroys any mutexes and condition variables, and finally frees up the 309*7c478bd9Sstevel@tonic-gate * global socket and window structure arrays. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate int 312*7c478bd9Sstevel@tonic-gate cs_deinit() 313*7c478bd9Sstevel@tonic-gate { 314*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 315*7c478bd9Sstevel@tonic-gate int sn, have_clients = 0, have_sockets = 0; 316*7c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 319*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) 320*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: cs_deinit\n"); 321*7c478bd9Sstevel@tonic-gate #endif 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * Deregister with the Card Services kernel stubs module 325*7c478bd9Sstevel@tonic-gate */ 326*7c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 327*7c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_DEREGISTER; 328*7c478bd9Sstevel@tonic-gate (void) csx_register_cardservices(&rcs); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate /* 331*7c478bd9Sstevel@tonic-gate * Set the GLOBAL_INIT_STATE_NO_CLIENTS flag to prevent new clients 332*7c478bd9Sstevel@tonic-gate * from registering. 333*7c478bd9Sstevel@tonic-gate */ 334*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 335*7c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_NO_CLIENTS; 336*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * Go through each socket and make sure that there are no clients 340*7c478bd9Sstevel@tonic-gate * on any of the sockets. If there are, we can't deinit until 341*7c478bd9Sstevel@tonic-gate * all the clients for every socket are gone. 342*7c478bd9Sstevel@tonic-gate */ 343*7c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 344*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 345*7c478bd9Sstevel@tonic-gate have_sockets++; 346*7c478bd9Sstevel@tonic-gate if (sp->client_list) { 347*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deinit: cannot unload module since " 348*7c478bd9Sstevel@tonic-gate "socket %d has registered clients\n", sn); 349*7c478bd9Sstevel@tonic-gate have_clients++; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * We don't allow unload if there are any clients registered 356*7c478bd9Sstevel@tonic-gate * or if there are still sockets that are active. 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate if ((have_clients > 0) || (have_sockets > 0)) 359*7c478bd9Sstevel@tonic-gate return (BAD_FUNCTION); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate #ifdef XXX 362*7c478bd9Sstevel@tonic-gate /* 363*7c478bd9Sstevel@tonic-gate * If one or more sockets have been added, we need to deallocate 364*7c478bd9Sstevel@tonic-gate * the resources associated with those sockets. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * First, tell Socket Services that we're leaving, so that we 369*7c478bd9Sstevel@tonic-gate * don't get any more event callbacks. 370*7c478bd9Sstevel@tonic-gate */ 371*7c478bd9Sstevel@tonic-gate SocketServices(CSUnregister); 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /* 374*7c478bd9Sstevel@tonic-gate * Wait for the soft int timer to tell us it's done 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 377*7c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_UNLOADING; 378*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 379*7c478bd9Sstevel@tonic-gate UNTIMEOUT(cs_globals.sotfint_tmo); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* 382*7c478bd9Sstevel@tonic-gate * Remove the soft interrupt handler. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 385*7c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR) { 386*7c478bd9Sstevel@tonic-gate ddi_remove_softintr(cs_globals.softint_id); 387*7c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SOFTINTR; 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * Go through each socket and free any resource allocated to that 395*7c478bd9Sstevel@tonic-gate * socket, as well as any mutexs and condition variables. 396*7c478bd9Sstevel@tonic-gate */ 397*7c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 398*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * untimeout possible pending ready/busy timer 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 408*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 409*7c478bd9Sstevel@tonic-gate sp->flags = SOCKET_UNLOAD_MODULE; 410*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SOFTINTR) 411*7c478bd9Sstevel@tonic-gate sp->init_state &= ~SOCKET_INIT_STATE_SOFTINTR; 412*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 413*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 416*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 417*7c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 418*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 419*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate /* 422*7c478bd9Sstevel@tonic-gate * Tell the event handler thread that we want it to exit, then 423*7c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 426*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 427*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_THREAD) { 428*7c478bd9Sstevel@tonic-gate sp->thread_state = SOCKET_THREAD_EXIT; 429*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 430*7c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 433*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * Tell the SS work thread that we want it to exit, then 437*7c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 440*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 441*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SS_THREAD) { 442*7c478bd9Sstevel@tonic-gate sp->ss_thread_state = SOCKET_THREAD_EXIT; 443*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 444*7c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_caller_cv, &sp->ss_thread_lock); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 448*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * Free the mutexii and condition variables that we used. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) { 454*7c478bd9Sstevel@tonic-gate mutex_destroy(&sp->lock); 455*7c478bd9Sstevel@tonic-gate mutex_destroy(&sp->client_lock); 456*7c478bd9Sstevel@tonic-gate mutex_destroy(&sp->cis_lock); 457*7c478bd9Sstevel@tonic-gate mutex_destroy(&sp->ss_thread_lock); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_CV) { 461*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->thread_cv); 462*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->caller_cv); 463*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->reset_cv); 464*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_thread_cv); 465*7c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_caller_cv); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * Free the memory-mapped IO structure if we allocated one. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) 473*7c478bd9Sstevel@tonic-gate kmem_free(sp->io_mmap_window, sizeof (io_mmap_window_t)); 474*7c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate /* 477*7c478bd9Sstevel@tonic-gate * Return the socket to memory-only mode and turn off the 478*7c478bd9Sstevel@tonic-gate * socket power. 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate sp->event_mask = 0; 481*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 482*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 0; 483*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 484*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 485*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 486*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 489*7c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 490*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 491*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 492*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 493*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* 496*7c478bd9Sstevel@tonic-gate * If we fail this call, there's not much we can do, so 497*7c478bd9Sstevel@tonic-gate * just continue with the resource deallocation. 498*7c478bd9Sstevel@tonic-gate */ 499*7c478bd9Sstevel@tonic-gate if ((ret = 500*7c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 501*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 502*7c478bd9Sstevel@tonic-gate "cs_deinit: socket %d SS_SetSocket failure %d\n", 503*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 506*7c478bd9Sstevel@tonic-gate } /* for (sn) */ 507*7c478bd9Sstevel@tonic-gate #endif /* XXX */ 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate /* 510*7c478bd9Sstevel@tonic-gate * Destroy the global mutexii. 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.global_lock); 513*7c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.window_lock); 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate #ifdef XXX 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * Free the global "super-client" structure 518*7c478bd9Sstevel@tonic-gate */ 519*7c478bd9Sstevel@tonic-gate if (cs_globals.sclient_list) 520*7c478bd9Sstevel@tonic-gate kmem_free(cs_globals.sclient_list, 521*7c478bd9Sstevel@tonic-gate (cs_globals.num_sockets * sizeof (struct sclient_list_t))); 522*7c478bd9Sstevel@tonic-gate cs_globals.sclient_list = NULL; 523*7c478bd9Sstevel@tonic-gate #endif /* XXX */ 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * ==== drip, drip, drip - the Card Services waterfall :-) ==== 530*7c478bd9Sstevel@tonic-gate */ 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * CardServices - general Card Services entry point for CS clients 534*7c478bd9Sstevel@tonic-gate * and Socket Services; the address of this 535*7c478bd9Sstevel@tonic-gate * function is handed to SS via the CSRegister 536*7c478bd9Sstevel@tonic-gate * SS call 537*7c478bd9Sstevel@tonic-gate */ 538*7c478bd9Sstevel@tonic-gate int 539*7c478bd9Sstevel@tonic-gate CardServices(int function, ...) 540*7c478bd9Sstevel@tonic-gate { 541*7c478bd9Sstevel@tonic-gate va_list arglist; 542*7c478bd9Sstevel@tonic-gate int retcode = CS_UNSUPPORTED_FUNCTION; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate cs_socket_t *socp; 545*7c478bd9Sstevel@tonic-gate uint32_t *offp; 546*7c478bd9Sstevel@tonic-gate acc_handle_t *hp; 547*7c478bd9Sstevel@tonic-gate client_handle_t ch; 548*7c478bd9Sstevel@tonic-gate client_handle_t *chp; 549*7c478bd9Sstevel@tonic-gate window_handle_t wh; 550*7c478bd9Sstevel@tonic-gate window_handle_t *whp; 551*7c478bd9Sstevel@tonic-gate tuple_t *tuple; 552*7c478bd9Sstevel@tonic-gate cisparse_t *cisparse; 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 555*7c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 556*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: called for function %s (0x%x)\n", 557*7c478bd9Sstevel@tonic-gate cs_error2text(function, CSFUN2TEXT_FUNCTION), 558*7c478bd9Sstevel@tonic-gate function); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate #endif 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate va_start(arglist, function); 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate /* 565*7c478bd9Sstevel@tonic-gate * Here's the Card Services waterfall 566*7c478bd9Sstevel@tonic-gate */ 567*7c478bd9Sstevel@tonic-gate switch (function) { 568*7c478bd9Sstevel@tonic-gate /* 569*7c478bd9Sstevel@tonic-gate * We got here as a result of the CIS module calling us 570*7c478bd9Sstevel@tonic-gate * in response to cs_ss_init() calling the CIS module 571*7c478bd9Sstevel@tonic-gate * at CIS_PARSER(CISP_CIS_SETUP, ...) 572*7c478bd9Sstevel@tonic-gate */ 573*7c478bd9Sstevel@tonic-gate case CISRegister: { 574*7c478bd9Sstevel@tonic-gate cisregister_t *cisr; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate cisr = va_arg(arglist, cisregister_t *); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (cisr->cis_magic != PCCS_MAGIC || 579*7c478bd9Sstevel@tonic-gate cisr->cis_version != PCCS_VERSION) { 580*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 581*7c478bd9Sstevel@tonic-gate "CS: CISRegister (%lx, %lx, %lx, %lx) *ERROR*", 582*7c478bd9Sstevel@tonic-gate (long)cisr->cis_magic, 583*7c478bd9Sstevel@tonic-gate (long)cisr->cis_version, 584*7c478bd9Sstevel@tonic-gate (long)cisr->cis_parser, 585*7c478bd9Sstevel@tonic-gate (long)cisr->cistpl_std_callout); 586*7c478bd9Sstevel@tonic-gate retcode = CS_BAD_ARGS; 587*7c478bd9Sstevel@tonic-gate } else { 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * Replace the CIS Parser entry point if 590*7c478bd9Sstevel@tonic-gate * necessary. 591*7c478bd9Sstevel@tonic-gate */ 592*7c478bd9Sstevel@tonic-gate if (cisr->cis_parser != NULL) 593*7c478bd9Sstevel@tonic-gate cis_parser = cisr->cis_parser; 594*7c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = cisr->cistpl_std_callout; 595*7c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate break; 599*7c478bd9Sstevel@tonic-gate case CISUnregister: /* XXX - should we do some more checking */ 600*7c478bd9Sstevel@tonic-gate /* XXX - need to protect this by a mutex */ 601*7c478bd9Sstevel@tonic-gate cis_parser = NULL; 602*7c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = NULL; 603*7c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate case InitCISWindow: 606*7c478bd9Sstevel@tonic-gate socp = va_arg(arglist, cs_socket_t *); 607*7c478bd9Sstevel@tonic-gate offp = va_arg(arglist, uint32_t *); 608*7c478bd9Sstevel@tonic-gate hp = va_arg(arglist, acc_handle_t *); 609*7c478bd9Sstevel@tonic-gate retcode = cs_init_cis_window(socp, offp, hp, 610*7c478bd9Sstevel@tonic-gate va_arg(arglist, uint32_t)); 611*7c478bd9Sstevel@tonic-gate break; 612*7c478bd9Sstevel@tonic-gate case RegisterClient: 613*7c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *), 614*7c478bd9Sstevel@tonic-gate retcode = cs_register_client(chp, 615*7c478bd9Sstevel@tonic-gate va_arg(arglist, client_reg_t *)); 616*7c478bd9Sstevel@tonic-gate break; 617*7c478bd9Sstevel@tonic-gate case DeregisterClient: 618*7c478bd9Sstevel@tonic-gate retcode = cs_deregister_client( 619*7c478bd9Sstevel@tonic-gate va_arg(arglist, client_handle_t)); 620*7c478bd9Sstevel@tonic-gate break; 621*7c478bd9Sstevel@tonic-gate case GetStatus: 622*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 623*7c478bd9Sstevel@tonic-gate retcode = cs_get_status(ch, 624*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_status_t *)); 625*7c478bd9Sstevel@tonic-gate break; 626*7c478bd9Sstevel@tonic-gate case ResetFunction: 627*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 628*7c478bd9Sstevel@tonic-gate retcode = cs_reset_function(ch, 629*7c478bd9Sstevel@tonic-gate va_arg(arglist, reset_function_t *)); 630*7c478bd9Sstevel@tonic-gate break; 631*7c478bd9Sstevel@tonic-gate case SetEventMask: 632*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 633*7c478bd9Sstevel@tonic-gate retcode = cs_set_event_mask(ch, 634*7c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 635*7c478bd9Sstevel@tonic-gate break; 636*7c478bd9Sstevel@tonic-gate case GetEventMask: 637*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 638*7c478bd9Sstevel@tonic-gate retcode = cs_get_event_mask(ch, 639*7c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 640*7c478bd9Sstevel@tonic-gate break; 641*7c478bd9Sstevel@tonic-gate case RequestIO: 642*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 643*7c478bd9Sstevel@tonic-gate retcode = cs_request_io(ch, 644*7c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 645*7c478bd9Sstevel@tonic-gate break; 646*7c478bd9Sstevel@tonic-gate case ReleaseIO: 647*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 648*7c478bd9Sstevel@tonic-gate retcode = cs_release_io(ch, 649*7c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 650*7c478bd9Sstevel@tonic-gate break; 651*7c478bd9Sstevel@tonic-gate case RequestIRQ: 652*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 653*7c478bd9Sstevel@tonic-gate retcode = cs_request_irq(ch, 654*7c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 655*7c478bd9Sstevel@tonic-gate break; 656*7c478bd9Sstevel@tonic-gate case ReleaseIRQ: 657*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 658*7c478bd9Sstevel@tonic-gate retcode = cs_release_irq(ch, 659*7c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 660*7c478bd9Sstevel@tonic-gate break; 661*7c478bd9Sstevel@tonic-gate case RequestWindow: 662*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 663*7c478bd9Sstevel@tonic-gate whp = va_arg(arglist, window_handle_t *); 664*7c478bd9Sstevel@tonic-gate retcode = cs_request_window(ch, whp, 665*7c478bd9Sstevel@tonic-gate va_arg(arglist, win_req_t *)); 666*7c478bd9Sstevel@tonic-gate break; 667*7c478bd9Sstevel@tonic-gate case ReleaseWindow: 668*7c478bd9Sstevel@tonic-gate retcode = cs_release_window( 669*7c478bd9Sstevel@tonic-gate va_arg(arglist, window_handle_t)); 670*7c478bd9Sstevel@tonic-gate break; 671*7c478bd9Sstevel@tonic-gate case ModifyWindow: 672*7c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 673*7c478bd9Sstevel@tonic-gate retcode = cs_modify_window(wh, 674*7c478bd9Sstevel@tonic-gate va_arg(arglist, modify_win_t *)); 675*7c478bd9Sstevel@tonic-gate break; 676*7c478bd9Sstevel@tonic-gate case MapMemPage: 677*7c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 678*7c478bd9Sstevel@tonic-gate retcode = cs_map_mem_page(wh, 679*7c478bd9Sstevel@tonic-gate va_arg(arglist, map_mem_page_t *)); 680*7c478bd9Sstevel@tonic-gate break; 681*7c478bd9Sstevel@tonic-gate case RequestSocketMask: 682*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 683*7c478bd9Sstevel@tonic-gate retcode = cs_request_socket_mask(ch, 684*7c478bd9Sstevel@tonic-gate va_arg(arglist, request_socket_mask_t *)); 685*7c478bd9Sstevel@tonic-gate break; 686*7c478bd9Sstevel@tonic-gate case ReleaseSocketMask: 687*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 688*7c478bd9Sstevel@tonic-gate retcode = cs_release_socket_mask(ch, 689*7c478bd9Sstevel@tonic-gate va_arg(arglist, release_socket_mask_t *)); 690*7c478bd9Sstevel@tonic-gate break; 691*7c478bd9Sstevel@tonic-gate case RequestConfiguration: 692*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 693*7c478bd9Sstevel@tonic-gate retcode = cs_request_configuration(ch, 694*7c478bd9Sstevel@tonic-gate va_arg(arglist, config_req_t *)); 695*7c478bd9Sstevel@tonic-gate break; 696*7c478bd9Sstevel@tonic-gate case GetPhysicalAdapterInfo: 697*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 698*7c478bd9Sstevel@tonic-gate retcode = cs_get_physical_adapter_info(ch, 699*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_physical_adapter_info_t *)); 700*7c478bd9Sstevel@tonic-gate break; 701*7c478bd9Sstevel@tonic-gate case GetCardServicesInfo: 702*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 703*7c478bd9Sstevel@tonic-gate retcode = cs_get_cardservices_info(ch, 704*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_cardservices_info_t *)); 705*7c478bd9Sstevel@tonic-gate break; 706*7c478bd9Sstevel@tonic-gate case GetConfigurationInfo: 707*7c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *); 708*7c478bd9Sstevel@tonic-gate retcode = cs_get_configuration_info(chp, 709*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_configuration_info_t *)); 710*7c478bd9Sstevel@tonic-gate break; 711*7c478bd9Sstevel@tonic-gate case ModifyConfiguration: 712*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 713*7c478bd9Sstevel@tonic-gate retcode = cs_modify_configuration(ch, 714*7c478bd9Sstevel@tonic-gate va_arg(arglist, modify_config_t *)); 715*7c478bd9Sstevel@tonic-gate break; 716*7c478bd9Sstevel@tonic-gate case AccessConfigurationRegister: 717*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 718*7c478bd9Sstevel@tonic-gate retcode = cs_access_configuration_register(ch, 719*7c478bd9Sstevel@tonic-gate va_arg(arglist, access_config_reg_t *)); 720*7c478bd9Sstevel@tonic-gate break; 721*7c478bd9Sstevel@tonic-gate case ReleaseConfiguration: 722*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 723*7c478bd9Sstevel@tonic-gate retcode = cs_release_configuration(ch, 724*7c478bd9Sstevel@tonic-gate va_arg(arglist, release_config_t *)); 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate case OpenMemory: 727*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: OpenMemory\n"); 728*7c478bd9Sstevel@tonic-gate break; 729*7c478bd9Sstevel@tonic-gate case ReadMemory: 730*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReadMemory\n"); 731*7c478bd9Sstevel@tonic-gate break; 732*7c478bd9Sstevel@tonic-gate case WriteMemory: 733*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: WriteMemory\n"); 734*7c478bd9Sstevel@tonic-gate break; 735*7c478bd9Sstevel@tonic-gate case CopyMemory: 736*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CopyMemory\n"); 737*7c478bd9Sstevel@tonic-gate break; 738*7c478bd9Sstevel@tonic-gate case RegisterEraseQueue: 739*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterEraseQueue\n"); 740*7c478bd9Sstevel@tonic-gate break; 741*7c478bd9Sstevel@tonic-gate case CheckEraseQueue: 742*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CheckEraseQueue\n"); 743*7c478bd9Sstevel@tonic-gate break; 744*7c478bd9Sstevel@tonic-gate case DeregisterEraseQueue: 745*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: DeregisterEraseQueue\n"); 746*7c478bd9Sstevel@tonic-gate break; 747*7c478bd9Sstevel@tonic-gate case CloseMemory: 748*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CloseMemory\n"); 749*7c478bd9Sstevel@tonic-gate break; 750*7c478bd9Sstevel@tonic-gate case GetFirstRegion: 751*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstRegion\n"); 752*7c478bd9Sstevel@tonic-gate break; 753*7c478bd9Sstevel@tonic-gate case GetNextRegion: 754*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextRegion\n"); 755*7c478bd9Sstevel@tonic-gate break; 756*7c478bd9Sstevel@tonic-gate case GetFirstPartition: 757*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstPartition\n"); 758*7c478bd9Sstevel@tonic-gate break; 759*7c478bd9Sstevel@tonic-gate case GetNextPartition: 760*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextPartition\n"); 761*7c478bd9Sstevel@tonic-gate break; 762*7c478bd9Sstevel@tonic-gate case ReturnSSEntry: 763*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReturnSSEntry\n"); 764*7c478bd9Sstevel@tonic-gate break; 765*7c478bd9Sstevel@tonic-gate case MapLogSocket: 766*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 767*7c478bd9Sstevel@tonic-gate retcode = cs_map_log_socket(ch, 768*7c478bd9Sstevel@tonic-gate va_arg(arglist, map_log_socket_t *)); 769*7c478bd9Sstevel@tonic-gate break; 770*7c478bd9Sstevel@tonic-gate case MapPhySocket: 771*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhySocket\n"); 772*7c478bd9Sstevel@tonic-gate break; 773*7c478bd9Sstevel@tonic-gate case MapLogWindow: 774*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapLogWindow\n"); 775*7c478bd9Sstevel@tonic-gate break; 776*7c478bd9Sstevel@tonic-gate case MapPhyWindow: 777*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhyWindow\n"); 778*7c478bd9Sstevel@tonic-gate break; 779*7c478bd9Sstevel@tonic-gate case RegisterMTD: 780*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterMTD\n"); 781*7c478bd9Sstevel@tonic-gate break; 782*7c478bd9Sstevel@tonic-gate case RegisterTimer: 783*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterTimer\n"); 784*7c478bd9Sstevel@tonic-gate break; 785*7c478bd9Sstevel@tonic-gate case SetRegion: 786*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: SetRegion\n"); 787*7c478bd9Sstevel@tonic-gate break; 788*7c478bd9Sstevel@tonic-gate case RequestExclusive: 789*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RequestExclusive\n"); 790*7c478bd9Sstevel@tonic-gate break; 791*7c478bd9Sstevel@tonic-gate case ReleaseExclusive: 792*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReleaseExclusive\n"); 793*7c478bd9Sstevel@tonic-gate break; 794*7c478bd9Sstevel@tonic-gate case GetFirstClient: 795*7c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 796*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 797*7c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 798*7c478bd9Sstevel@tonic-gate break; 799*7c478bd9Sstevel@tonic-gate case GetNextClient: 800*7c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 801*7c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 802*7c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 803*7c478bd9Sstevel@tonic-gate break; 804*7c478bd9Sstevel@tonic-gate case GetClientInfo: 805*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 806*7c478bd9Sstevel@tonic-gate retcode = cs_get_client_info(ch, 807*7c478bd9Sstevel@tonic-gate va_arg(arglist, client_info_t *)); 808*7c478bd9Sstevel@tonic-gate break; 809*7c478bd9Sstevel@tonic-gate case AddSocketServices: 810*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AddSocketServices\n"); 811*7c478bd9Sstevel@tonic-gate break; 812*7c478bd9Sstevel@tonic-gate case ReplaceSocketServices: 813*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReplaceSocketServices\n"); 814*7c478bd9Sstevel@tonic-gate break; 815*7c478bd9Sstevel@tonic-gate case VendorSpecific: 816*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: VendorSpecific\n"); 817*7c478bd9Sstevel@tonic-gate break; 818*7c478bd9Sstevel@tonic-gate case AdjustResourceInfo: 819*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AdjustResourceInfo\n"); 820*7c478bd9Sstevel@tonic-gate break; 821*7c478bd9Sstevel@tonic-gate case ValidateCIS: 822*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 823*7c478bd9Sstevel@tonic-gate retcode = cs_validate_cis(ch, 824*7c478bd9Sstevel@tonic-gate va_arg(arglist, cisinfo_t *)); 825*7c478bd9Sstevel@tonic-gate break; 826*7c478bd9Sstevel@tonic-gate case GetFirstTuple: 827*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 828*7c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 829*7c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 830*7c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 831*7c478bd9Sstevel@tonic-gate break; 832*7c478bd9Sstevel@tonic-gate case GetNextTuple: 833*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 834*7c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 835*7c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 836*7c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 837*7c478bd9Sstevel@tonic-gate break; 838*7c478bd9Sstevel@tonic-gate case GetTupleData: 839*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 840*7c478bd9Sstevel@tonic-gate retcode = cs_get_tuple_data(ch, 841*7c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *)); 842*7c478bd9Sstevel@tonic-gate break; 843*7c478bd9Sstevel@tonic-gate case ParseTuple: 844*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 845*7c478bd9Sstevel@tonic-gate tuple = va_arg(arglist, tuple_t *); 846*7c478bd9Sstevel@tonic-gate cisparse = va_arg(arglist, cisparse_t *); 847*7c478bd9Sstevel@tonic-gate retcode = cs_parse_tuple(ch, tuple, cisparse, 848*7c478bd9Sstevel@tonic-gate va_arg(arglist, uint_t)); 849*7c478bd9Sstevel@tonic-gate break; 850*7c478bd9Sstevel@tonic-gate case MakeDeviceNode: 851*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 852*7c478bd9Sstevel@tonic-gate retcode = cs_make_device_node(ch, 853*7c478bd9Sstevel@tonic-gate va_arg(arglist, make_device_node_t *)); 854*7c478bd9Sstevel@tonic-gate break; 855*7c478bd9Sstevel@tonic-gate case RemoveDeviceNode: 856*7c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 857*7c478bd9Sstevel@tonic-gate retcode = cs_remove_device_node(ch, 858*7c478bd9Sstevel@tonic-gate va_arg(arglist, remove_device_node_t *)); 859*7c478bd9Sstevel@tonic-gate break; 860*7c478bd9Sstevel@tonic-gate case ConvertSpeed: 861*7c478bd9Sstevel@tonic-gate retcode = cs_convert_speed( 862*7c478bd9Sstevel@tonic-gate va_arg(arglist, convert_speed_t *)); 863*7c478bd9Sstevel@tonic-gate break; 864*7c478bd9Sstevel@tonic-gate case ConvertSize: 865*7c478bd9Sstevel@tonic-gate retcode = cs_convert_size( 866*7c478bd9Sstevel@tonic-gate va_arg(arglist, convert_size_t *)); 867*7c478bd9Sstevel@tonic-gate break; 868*7c478bd9Sstevel@tonic-gate case Event2Text: 869*7c478bd9Sstevel@tonic-gate retcode = cs_event2text( 870*7c478bd9Sstevel@tonic-gate va_arg(arglist, event2text_t *), 1); 871*7c478bd9Sstevel@tonic-gate break; 872*7c478bd9Sstevel@tonic-gate case Error2Text: { 873*7c478bd9Sstevel@tonic-gate error2text_t *cft; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate cft = va_arg(arglist, error2text_t *); 876*7c478bd9Sstevel@tonic-gate (void) strcpy(cft->text, 877*7c478bd9Sstevel@tonic-gate cs_error2text(cft->item, CSFUN2TEXT_RETURN)); 878*7c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate break; 881*7c478bd9Sstevel@tonic-gate case CS_DDI_Info: 882*7c478bd9Sstevel@tonic-gate retcode = cs_ddi_info(va_arg(arglist, cs_ddi_info_t *)); 883*7c478bd9Sstevel@tonic-gate break; 884*7c478bd9Sstevel@tonic-gate case CS_Sys_Ctl: 885*7c478bd9Sstevel@tonic-gate retcode = cs_sys_ctl(va_arg(arglist, cs_sys_ctl_t *)); 886*7c478bd9Sstevel@tonic-gate break; 887*7c478bd9Sstevel@tonic-gate default: 888*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: {unknown function %d}\n", function); 889*7c478bd9Sstevel@tonic-gate break; 890*7c478bd9Sstevel@tonic-gate } /* switch(function) */ 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate va_end(arglist); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 895*7c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 896*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: returning %s (0x%x)\n", 897*7c478bd9Sstevel@tonic-gate cs_error2text(retcode, CSFUN2TEXT_RETURN), 898*7c478bd9Sstevel@tonic-gate retcode); 899*7c478bd9Sstevel@tonic-gate } 900*7c478bd9Sstevel@tonic-gate #endif 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate return (retcode); 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * ==== tuple and CIS handling section ==== 907*7c478bd9Sstevel@tonic-gate */ 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * cs_parse_tuple - This function supports the CS ParseTuple function call. 911*7c478bd9Sstevel@tonic-gate * 912*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if tuple parsed sucessfully 913*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 914*7c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if passed CIS list pointer is NULL 915*7c478bd9Sstevel@tonic-gate * CS_UNKNOWN_TUPLE - if unknown tuple passed to CIS parser 916*7c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if generic parser error 917*7c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for card/function 918*7c478bd9Sstevel@tonic-gate * 919*7c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 920*7c478bd9Sstevel@tonic-gate */ 921*7c478bd9Sstevel@tonic-gate static int 922*7c478bd9Sstevel@tonic-gate cs_parse_tuple(client_handle_t client_handle, tuple_t *tuple, 923*7c478bd9Sstevel@tonic-gate cisparse_t *cisparse, cisdata_t cisdata) 924*7c478bd9Sstevel@tonic-gate { 925*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 926*7c478bd9Sstevel@tonic-gate client_t *client; 927*7c478bd9Sstevel@tonic-gate uint32_t fn; 928*7c478bd9Sstevel@tonic-gate int ret; 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, 931*7c478bd9Sstevel@tonic-gate &fn, &sp, &client)) != CS_SUCCESS) 932*7c478bd9Sstevel@tonic-gate return (ret); 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate /* 935*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 936*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 939*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate /* 942*7c478bd9Sstevel@tonic-gate * Sanity check to be sure that we've got a non-NULL CIS list 943*7c478bd9Sstevel@tonic-gate * pointer. 944*7c478bd9Sstevel@tonic-gate */ 945*7c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) 946*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* 951*7c478bd9Sstevel@tonic-gate * Check to see if there is a valid CIS for this function. 952*7c478bd9Sstevel@tonic-gate * There is an implicit assumption here that if this 953*7c478bd9Sstevel@tonic-gate * is a multi-function CIS and the specified function 954*7c478bd9Sstevel@tonic-gate * number is not CS_GLOBAL_CIS that in order for there 955*7c478bd9Sstevel@tonic-gate * to be a valid function-specific CIS, there also must 956*7c478bd9Sstevel@tonic-gate * be a valid global CIS. This means that we don't need 957*7c478bd9Sstevel@tonic-gate * to know whether this tuple came from the global CIS 958*7c478bd9Sstevel@tonic-gate * or from the function-specific CIS. 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 961*7c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 962*7c478bd9Sstevel@tonic-gate ret = (int)(uintptr_t)CIS_PARSER(CISP_CIS_PARSE_TUPLE, 963*7c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, 964*7c478bd9Sstevel@tonic-gate tuple->CISOffset, 965*7c478bd9Sstevel@tonic-gate (tuple->Attributes & TUPLE_RETURN_NAME)? 966*7c478bd9Sstevel@tonic-gate HANDTPL_RETURN_NAME: 967*7c478bd9Sstevel@tonic-gate HANDTPL_PARSE_LTUPLE, 968*7c478bd9Sstevel@tonic-gate cisparse, cisdata); 969*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 970*7c478bd9Sstevel@tonic-gate if (ret == CISTPLF_UNKNOWN) 971*7c478bd9Sstevel@tonic-gate return (CS_UNKNOWN_TUPLE); 972*7c478bd9Sstevel@tonic-gate if (ret != CISTPLF_NOERROR) 973*7c478bd9Sstevel@tonic-gate return (CS_BAD_CIS); 974*7c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 975*7c478bd9Sstevel@tonic-gate } else { 976*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 977*7c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 978*7c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate return (ret); 981*7c478bd9Sstevel@tonic-gate } 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate /* 984*7c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple - returns the first/next tuple of the specified type 985*7c478bd9Sstevel@tonic-gate * this is to support the GetFirstTuple and 986*7c478bd9Sstevel@tonic-gate * GetNextTuple function call 987*7c478bd9Sstevel@tonic-gate * 988*7c478bd9Sstevel@tonic-gate * flags - one of: 989*7c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG causes function to support GetFirstTuple 990*7c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG causes function to support GetNextTuple 991*7c478bd9Sstevel@tonic-gate * 992*7c478bd9Sstevel@tonic-gate * tuple_t->Attributes flags: 993*7c478bd9Sstevel@tonic-gate * TUPLE_RETURN_LINK - XXX Not implemented, see notes below. 994*7c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES - return tuples with 995*7c478bd9Sstevel@tonic-gate * CISTPLF_IGNORE_TUPLE set in the 996*7c478bd9Sstevel@tonic-gate * cistpl_t->flags member. 997*7c478bd9Sstevel@tonic-gate * 998*7c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 999*7c478bd9Sstevel@tonic-gate * 1000*7c478bd9Sstevel@tonic-gate * On a single-function card, the caller will get back all the tuples in 1001*7c478bd9Sstevel@tonic-gate * the CIS. 1002*7c478bd9Sstevel@tonic-gate * 1003*7c478bd9Sstevel@tonic-gate * On a multi-function card, the caller will get the tuples from the 1004*7c478bd9Sstevel@tonic-gate * global CIS followed by the tuples in the function-specific CIS. The 1005*7c478bd9Sstevel@tonic-gate * caller will not get any tuples from a function-specific CIS that 1006*7c478bd9Sstevel@tonic-gate * does not belong to the caller's function. 1007*7c478bd9Sstevel@tonic-gate * 1008*7c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 1009*7c478bd9Sstevel@tonic-gate * 1010*7c478bd9Sstevel@tonic-gate * On a single-function card, the operation is the same as for regular 1011*7c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 1012*7c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS this function will return CS_NO_CIS. 1013*7c478bd9Sstevel@tonic-gate * 1014*7c478bd9Sstevel@tonic-gate * On a multi-function card, the operation is the same as for regular 1015*7c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 1016*7c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS the caller will only get tuples from the 1017*7c478bd9Sstevel@tonic-gate * global CIS. If a particular function nubmer does not exist, this 1018*7c478bd9Sstevel@tonic-gate * function will return CS_NO_CIS for that function. 1019*7c478bd9Sstevel@tonic-gate * 1020*7c478bd9Sstevel@tonic-gate * General notes: 1021*7c478bd9Sstevel@tonic-gate * 1022*7c478bd9Sstevel@tonic-gate * On both a single-function card and a multi-function card, if the tuple 1023*7c478bd9Sstevel@tonic-gate * comes from the global CIS chain, the CISTPLF_GLOBAL_CIS flag will be 1024*7c478bd9Sstevel@tonic-gate * set in the tuple_t->flags member. 1025*7c478bd9Sstevel@tonic-gate * 1026*7c478bd9Sstevel@tonic-gate * On a multi-function card, if the tuple comes from the function-specific 1027*7c478bd9Sstevel@tonic-gate * CIS chain, the CISTPLF_MF_CIS flag will be set in the tuple_t->flags 1028*7c478bd9Sstevel@tonic-gate * member. 1029*7c478bd9Sstevel@tonic-gate * 1030*7c478bd9Sstevel@tonic-gate * For other flags that are set in the tuple_t->flags member, see the 1031*7c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 1032*7c478bd9Sstevel@tonic-gate * 1033*7c478bd9Sstevel@tonic-gate * The CIS parser may not include all the tuples that are in the CIS in 1034*7c478bd9Sstevel@tonic-gate * the private CIS list that it creates and maintains. See the CIS 1035*7c478bd9Sstevel@tonic-gate * parser documentation for a list of tuples that the parser does not 1036*7c478bd9Sstevel@tonic-gate * include in the list. 1037*7c478bd9Sstevel@tonic-gate * 1038*7c478bd9Sstevel@tonic-gate * If a tuple has the CISTPLF_IGNORE_TUPLE flag set and the flags 1039*7c478bd9Sstevel@tonic-gate * parameter CIS_GET_LTUPLE_IGNORE is not set, that tuple will not 1040*7c478bd9Sstevel@tonic-gate * be returned to the caller. Instead, the next tuple that matches 1041*7c478bd9Sstevel@tonic-gate * the calling criteria will be returned (or NULL if no other tuples 1042*7c478bd9Sstevel@tonic-gate * match the calling criteria). If CIS_GET_LTUPLE_IGNORE is set in 1043*7c478bd9Sstevel@tonic-gate * the flags paramter, tuples in the CIS list that match the calling 1044*7c478bd9Sstevel@tonic-gate * criteria will be returned. 1045*7c478bd9Sstevel@tonic-gate * 1046*7c478bd9Sstevel@tonic-gate * XXX The PC Card 95 Standard says that if the TUPLE_RETURN_LINK flag in 1047*7c478bd9Sstevel@tonic-gate * the tuple_t->Attributes member is not set, then we don't return 1048*7c478bd9Sstevel@tonic-gate * any of the link tuples. This function ignores this flag and always 1049*7c478bd9Sstevel@tonic-gate * returns link tuples. 1050*7c478bd9Sstevel@tonic-gate * 1051*7c478bd9Sstevel@tonic-gate * Return codes: 1052*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - if tuple sucessfully found and returned 1053*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card inserted 1054*7c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for the specified card/function 1055*7c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if tuple not found or no more tuples 1056*7c478bd9Sstevel@tonic-gate * to return 1057*7c478bd9Sstevel@tonic-gate * 1058*7c478bd9Sstevel@tonic-gate * See notes for cs_get_socket for a description of valid client, socket 1059*7c478bd9Sstevel@tonic-gate * and function number combinations. 1060*7c478bd9Sstevel@tonic-gate */ 1061*7c478bd9Sstevel@tonic-gate static int 1062*7c478bd9Sstevel@tonic-gate cs_get_firstnext_tuple(client_handle_t client_handle, 1063*7c478bd9Sstevel@tonic-gate tuple_t *tuple, uint32_t flags) 1064*7c478bd9Sstevel@tonic-gate { 1065*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 1066*7c478bd9Sstevel@tonic-gate client_t *client; 1067*7c478bd9Sstevel@tonic-gate uint32_t fn; 1068*7c478bd9Sstevel@tonic-gate int ret; 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1071*7c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1072*7c478bd9Sstevel@tonic-gate return (ret); 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate /* 1075*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1076*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 1077*7c478bd9Sstevel@tonic-gate */ 1078*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1079*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate /* 1084*7c478bd9Sstevel@tonic-gate * If there's no CIS on this card or no CIS for the specified 1085*7c478bd9Sstevel@tonic-gate * function, then we can't do much. 1086*7c478bd9Sstevel@tonic-gate */ 1087*7c478bd9Sstevel@tonic-gate if ((!(sp->cis_flags & CW_VALID_CIS)) || 1088*7c478bd9Sstevel@tonic-gate (!(sp->cis[fn].flags & CW_VALID_CIS))) { 1089*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1090*7c478bd9Sstevel@tonic-gate return (CS_NO_CIS); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate /* 1094*7c478bd9Sstevel@tonic-gate * This will set the CIS_GET_LTUPLE_IGNORE flag if the 1095*7c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES flag is set. The 1096*7c478bd9Sstevel@tonic-gate * assumption here is that the CIS_GET_LTUPLE_IGNORE 1097*7c478bd9Sstevel@tonic-gate * flag and the TUPLE_RETURN_IGNORED_TUPLES flag 1098*7c478bd9Sstevel@tonic-gate * shares the same bit position. If this ever changes, 1099*7c478bd9Sstevel@tonic-gate * we'll ahve to re-work this section of code. 1100*7c478bd9Sstevel@tonic-gate */ 1101*7c478bd9Sstevel@tonic-gate if (tuple->Attributes & TUPLE_RETURN_IGNORED_TUPLES) 1102*7c478bd9Sstevel@tonic-gate flags |= CIS_GET_LTUPLE_IGNORE; 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate /* 1105*7c478bd9Sstevel@tonic-gate * Are we GetFirstTuple or GetNextTuple? 1106*7c478bd9Sstevel@tonic-gate */ 1107*7c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_OPMASK) & CS_GET_FIRST_FLAG) { 1108*7c478bd9Sstevel@tonic-gate /* 1109*7c478bd9Sstevel@tonic-gate * Initialize the tuple structure; we need this information when 1110*7c478bd9Sstevel@tonic-gate * we have to process a GetNextTuple or ParseTuple call. 1111*7c478bd9Sstevel@tonic-gate * If this card has a multi-function CIS, then we always start out 1112*7c478bd9Sstevel@tonic-gate * delivering tuples from the global CIS chain. If this card does 1113*7c478bd9Sstevel@tonic-gate * not have a multi-function CIS, then the function 0 CIS chain 1114*7c478bd9Sstevel@tonic-gate * will contain the complete CIS list. 1115*7c478bd9Sstevel@tonic-gate * If this is a multi-function card, then use the GET_FIRST_LTUPLE 1116*7c478bd9Sstevel@tonic-gate * macro to return the first tuple in the CIS list - we do this 1117*7c478bd9Sstevel@tonic-gate * since we don't want to return tuples with CISTPLF_IGNORE_TUPLE 1118*7c478bd9Sstevel@tonic-gate * set unless CIS_GET_LTUPLE_IGNORE is set in the flags parameter. 1119*7c478bd9Sstevel@tonic-gate * Note that we don't have to cross over into the fucntion-specific 1120*7c478bd9Sstevel@tonic-gate * CIS chain if GET_FIRST_LTUPLE returns NULL, since a MF CIS will 1121*7c478bd9Sstevel@tonic-gate * always have at least a CISTPL_LONGLINK_MFC tuple in the global 1122*7c478bd9Sstevel@tonic-gate * CIS chain - the test for NULL is just a sanity check. 1123*7c478bd9Sstevel@tonic-gate */ 1124*7c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1125*7c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = 1126*7c478bd9Sstevel@tonic-gate GET_FIRST_LTUPLE(sp->cis[CS_GLOBAL_CIS].cis, 1127*7c478bd9Sstevel@tonic-gate flags)) == NULL) { 1128*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1129*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1130*7c478bd9Sstevel@tonic-gate } /* GET_FIRST_LTUPLE */ 1131*7c478bd9Sstevel@tonic-gate } else { 1132*7c478bd9Sstevel@tonic-gate tuple->CISOffset = sp->cis[0].cis; 1133*7c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1134*7c478bd9Sstevel@tonic-gate } else { 1135*7c478bd9Sstevel@tonic-gate cistpl_t *tp; 1136*7c478bd9Sstevel@tonic-gate 1137*7c478bd9Sstevel@tonic-gate /* 1138*7c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL tuple list pointer. 1139*7c478bd9Sstevel@tonic-gate * This is necessary in the case where the caller calls us 1140*7c478bd9Sstevel@tonic-gate * with get next tuple requests but we don't have any more 1141*7c478bd9Sstevel@tonic-gate * tuples to give back. 1142*7c478bd9Sstevel@tonic-gate */ 1143*7c478bd9Sstevel@tonic-gate if (tuple->CISOffset == NULL) { 1144*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1145*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate /* 1149*7c478bd9Sstevel@tonic-gate * Point to the next tuple in the list. If we're searching for 1150*7c478bd9Sstevel@tonic-gate * a particular tuple, FIND_LTUPLE_FWD will find it. 1151*7c478bd9Sstevel@tonic-gate * 1152*7c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain that we're looking 1153*7c478bd9Sstevel@tonic-gate * at, then if we're looking at the global portion of a 1154*7c478bd9Sstevel@tonic-gate * multi-function CIS, switch to the function-specific list 1155*7c478bd9Sstevel@tonic-gate * and start looking there. 1156*7c478bd9Sstevel@tonic-gate */ 1157*7c478bd9Sstevel@tonic-gate if ((tp = GET_NEXT_TUPLE(tuple->CISOffset, flags)) == NULL) { 1158*7c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1159*7c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1160*7c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 1161*7c478bd9Sstevel@tonic-gate tp = GET_FIRST_LTUPLE(sp->cis[fn].cis, flags); 1162*7c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 1163*7c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1164*7c478bd9Sstevel@tonic-gate } /* GET_NEXT_TUPLE */ 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate /* 1167*7c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 1168*7c478bd9Sstevel@tonic-gate */ 1169*7c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 1170*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1171*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate } /* CS_GET_FIRST_FLAG */ 1174*7c478bd9Sstevel@tonic-gate 1175*7c478bd9Sstevel@tonic-gate /* 1176*7c478bd9Sstevel@tonic-gate * Check if we want to get the first of a particular type of tuple 1177*7c478bd9Sstevel@tonic-gate * or just the first tuple in the chain. 1178*7c478bd9Sstevel@tonic-gate * If there are no more tuples of the type we're searching for in 1179*7c478bd9Sstevel@tonic-gate * the chain that we're looking at, then if we're looking at 1180*7c478bd9Sstevel@tonic-gate * the global portion of a multi-function CIS, switch to the 1181*7c478bd9Sstevel@tonic-gate * function-specific list and start looking there. 1182*7c478bd9Sstevel@tonic-gate */ 1183*7c478bd9Sstevel@tonic-gate if (tuple->DesiredTuple != RETURN_FIRST_TUPLE) { 1184*7c478bd9Sstevel@tonic-gate cistpl_t *tp; 1185*7c478bd9Sstevel@tonic-gate 1186*7c478bd9Sstevel@tonic-gate if ((tp = FIND_LTUPLE_FWD(tuple->CISOffset, 1187*7c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags)) == NULL) { 1188*7c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 1189*7c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 1190*7c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 1191*7c478bd9Sstevel@tonic-gate tp = FIND_FIRST_LTUPLE(sp->cis[fn].cis, 1192*7c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags); 1193*7c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 1194*7c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 1195*7c478bd9Sstevel@tonic-gate } /* FIND_LTUPLE_FWD */ 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate /* 1198*7c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 1201*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1202*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1203*7c478bd9Sstevel@tonic-gate } 1204*7c478bd9Sstevel@tonic-gate } /* !RETURN_FIRST_TUPLE */ 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate /* 1207*7c478bd9Sstevel@tonic-gate * We've got a tuple, now fill out the rest of the tuple_t 1208*7c478bd9Sstevel@tonic-gate * structure. Callers can use the flags member to 1209*7c478bd9Sstevel@tonic-gate * determine whether or not the tuple data was copied 1210*7c478bd9Sstevel@tonic-gate * to the linked list or if it's still on the card. 1211*7c478bd9Sstevel@tonic-gate */ 1212*7c478bd9Sstevel@tonic-gate tuple->Flags = tuple->CISOffset->flags; 1213*7c478bd9Sstevel@tonic-gate tuple->TupleCode = tuple->CISOffset->type; 1214*7c478bd9Sstevel@tonic-gate tuple->TupleLink = tuple->CISOffset->len; 1215*7c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->CISOffset->len; 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1220*7c478bd9Sstevel@tonic-gate } 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate /* 1223*7c478bd9Sstevel@tonic-gate * cs_get_tuple_data - get the data portion of a tuple; this is to 1224*7c478bd9Sstevel@tonic-gate * support the GetTupleData function call. 1225*7c478bd9Sstevel@tonic-gate * 1226*7c478bd9Sstevel@tonic-gate * Note that if the data body of a tuple was not read from the CIS, 1227*7c478bd9Sstevel@tonic-gate * then this function will return CS_NO_MORE_ITEMS. 1228*7c478bd9Sstevel@tonic-gate * 1229*7c478bd9Sstevel@tonic-gate * For flags that are set in the tuple_t->flags member, see the 1230*7c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 1231*7c478bd9Sstevel@tonic-gate * These flags are copied into the tuple_t->flags member by the 1232*7c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple function call. 1233*7c478bd9Sstevel@tonic-gate * 1234*7c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 1235*7c478bd9Sstevel@tonic-gate */ 1236*7c478bd9Sstevel@tonic-gate static int 1237*7c478bd9Sstevel@tonic-gate cs_get_tuple_data(client_handle_t client_handle, tuple_t *tuple) 1238*7c478bd9Sstevel@tonic-gate { 1239*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 1240*7c478bd9Sstevel@tonic-gate client_t *client; 1241*7c478bd9Sstevel@tonic-gate int ret, nbytes; 1242*7c478bd9Sstevel@tonic-gate uint32_t fn, flags; 1243*7c478bd9Sstevel@tonic-gate cisdata_t *tsd, *tdd; 1244*7c478bd9Sstevel@tonic-gate uint32_t newoffset; 1245*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 1246*7c478bd9Sstevel@tonic-gate 1247*7c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 1248*7c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1249*7c478bd9Sstevel@tonic-gate return (ret); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate /* 1252*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1253*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 1254*7c478bd9Sstevel@tonic-gate */ 1255*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1256*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 1257*7c478bd9Sstevel@tonic-gate 1258*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 1261*7c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate /* 1264*7c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL pointer to 1265*7c478bd9Sstevel@tonic-gate * a CIS list. 1266*7c478bd9Sstevel@tonic-gate */ 1267*7c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) { 1268*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1269*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1270*7c478bd9Sstevel@tonic-gate } 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate /* 1273*7c478bd9Sstevel@tonic-gate * Since the tuple data buffer that the caller calls us with 1274*7c478bd9Sstevel@tonic-gate * is preallocated in the tuple_t structure, we ignore any 1275*7c478bd9Sstevel@tonic-gate * TupleDataMax value that the caller has setup and use the 1276*7c478bd9Sstevel@tonic-gate * actual size of the tuple data buffer in the structure. 1277*7c478bd9Sstevel@tonic-gate */ 1278*7c478bd9Sstevel@tonic-gate tuple->TupleDataMax = sizeof (tuple->TupleData); 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate /* 1281*7c478bd9Sstevel@tonic-gate * Make sure the requested offset is not past the end of the 1282*7c478bd9Sstevel@tonic-gate * tuple data body nor past the end of the user-supplied 1283*7c478bd9Sstevel@tonic-gate * buffer. 1284*7c478bd9Sstevel@tonic-gate */ 1285*7c478bd9Sstevel@tonic-gate if ((int)tuple->TupleOffset >= min((int)tuple->TupleLink, 1286*7c478bd9Sstevel@tonic-gate (int)tuple->TupleDataMax)) { 1287*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1288*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1289*7c478bd9Sstevel@tonic-gate } 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->TupleLink; 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate if ((nbytes = min((int)tuple->TupleDataMax - 1294*7c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset, 1295*7c478bd9Sstevel@tonic-gate (int)tuple->TupleDataLen - 1296*7c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset)) < 1) { 1297*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1298*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 1299*7c478bd9Sstevel@tonic-gate } 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate /* 1302*7c478bd9Sstevel@tonic-gate * The tuple data destination is always the tuple_t->TupleData 1303*7c478bd9Sstevel@tonic-gate * buffer in the tuple_t structure no matter where we read the 1304*7c478bd9Sstevel@tonic-gate * tuple data from. 1305*7c478bd9Sstevel@tonic-gate */ 1306*7c478bd9Sstevel@tonic-gate tdd = tuple->TupleData; 1307*7c478bd9Sstevel@tonic-gate bzero((caddr_t)tdd, sizeof (tuple->TupleData)); 1308*7c478bd9Sstevel@tonic-gate 1309*7c478bd9Sstevel@tonic-gate /* 1310*7c478bd9Sstevel@tonic-gate * Do we have a copy of the tuple data? If not, we have to 1311*7c478bd9Sstevel@tonic-gate * get a pointer to the CIS and read the tuple data from the 1312*7c478bd9Sstevel@tonic-gate * card itself. 1313*7c478bd9Sstevel@tonic-gate */ 1314*7c478bd9Sstevel@tonic-gate switch (tuple->CISOffset->flags & CISTPLF_SPACE_MASK) { 1315*7c478bd9Sstevel@tonic-gate case CISTPLF_LM_SPACE: 1316*7c478bd9Sstevel@tonic-gate tsd = (tuple->CISOffset->data + 1317*7c478bd9Sstevel@tonic-gate (unsigned)tuple->TupleOffset); 1318*7c478bd9Sstevel@tonic-gate while (nbytes--) 1319*7c478bd9Sstevel@tonic-gate *tdd++ = *tsd++; 1320*7c478bd9Sstevel@tonic-gate break; 1321*7c478bd9Sstevel@tonic-gate case CISTPLF_AM_SPACE: 1322*7c478bd9Sstevel@tonic-gate case CISTPLF_CM_SPACE: 1323*7c478bd9Sstevel@tonic-gate newoffset = tuple->CISOffset->offset; 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate /* 1326*7c478bd9Sstevel@tonic-gate * Setup the proper space flags as well as setup the 1327*7c478bd9Sstevel@tonic-gate * address offset to point to the start of the tuple 1328*7c478bd9Sstevel@tonic-gate * data area; we need to do the latter since the 1329*7c478bd9Sstevel@tonic-gate * cis_store_cis_addr function in cis.c sets up the 1330*7c478bd9Sstevel@tonic-gate * tuple->CISOffset->offset offset to point to the 1331*7c478bd9Sstevel@tonic-gate * start of the tuple. 1332*7c478bd9Sstevel@tonic-gate */ 1333*7c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) { 1334*7c478bd9Sstevel@tonic-gate flags = CISTPLF_AM_SPACE; 1335*7c478bd9Sstevel@tonic-gate newoffset += ((tuple->TupleOffset * 2) + 4); 1336*7c478bd9Sstevel@tonic-gate } else { 1337*7c478bd9Sstevel@tonic-gate flags = CISTPLF_CM_SPACE; 1338*7c478bd9Sstevel@tonic-gate newoffset += (tuple->TupleOffset + 2); 1339*7c478bd9Sstevel@tonic-gate } 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 1342*7c478bd9Sstevel@tonic-gate flags) != CS_SUCCESS) { 1343*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1344*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_tuple_data: socket %d " 1345*7c478bd9Sstevel@tonic-gate "can't init CIS window\n", 1346*7c478bd9Sstevel@tonic-gate sp->socket_num); 1347*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 1348*7c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 1349*7c478bd9Sstevel@tonic-gate while (nbytes--) { 1350*7c478bd9Sstevel@tonic-gate *tdd++ = csx_Get8(cis_handle, newoffset++); 1351*7c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) 1352*7c478bd9Sstevel@tonic-gate newoffset++; 1353*7c478bd9Sstevel@tonic-gate } /* while */ 1354*7c478bd9Sstevel@tonic-gate break; 1355*7c478bd9Sstevel@tonic-gate default: 1356*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1357*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 1358*7c478bd9Sstevel@tonic-gate } /* switch */ 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 1361*7c478bd9Sstevel@tonic-gate } else { 1362*7c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 1363*7c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate return (ret); 1368*7c478bd9Sstevel@tonic-gate } 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate /* 1371*7c478bd9Sstevel@tonic-gate * cs_validate_cis - validates the CIS on a card in the given socket; this 1372*7c478bd9Sstevel@tonic-gate * is to support the ValidateCIS function call. 1373*7c478bd9Sstevel@tonic-gate * 1374*7c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 1375*7c478bd9Sstevel@tonic-gate * 1376*7c478bd9Sstevel@tonic-gate * Regular PC card drivers calling ValidateCIS will get the meaning of 1377*7c478bd9Sstevel@tonic-gate * the structure members as specified in the standard. 1378*7c478bd9Sstevel@tonic-gate * 1379*7c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 1380*7c478bd9Sstevel@tonic-gate * 1381*7c478bd9Sstevel@tonic-gate * with: Function Number = CS_GLOBAL_CIS 1382*7c478bd9Sstevel@tonic-gate * 1383*7c478bd9Sstevel@tonic-gate * For a single-function card, CS_NO_CIS will be returned and the 1384*7c478bd9Sstevel@tonic-gate * cisinfo_t->Chains and cisinfo_t->Tuples members will be set to 0. 1385*7c478bd9Sstevel@tonic-gate * 1386*7c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 1387*7c478bd9Sstevel@tonic-gate * the number of CIS chains in the global portion of the CIS, and 1388*7c478bd9Sstevel@tonic-gate * cisinfo_t->Tuples will contain a count of the number of tuples in 1389*7c478bd9Sstevel@tonic-gate * the global portion of the CIS. 1390*7c478bd9Sstevel@tonic-gate * 1391*7c478bd9Sstevel@tonic-gate * with: 0 <= Function Number < CIS_MAX_FUNCTIONS 1392*7c478bd9Sstevel@tonic-gate * 1393*7c478bd9Sstevel@tonic-gate * For a single-function card, if the function number is equal to 0 and 1394*7c478bd9Sstevel@tonic-gate * has a CIS, cisinfo_t->Chains will contain a count of the number of 1395*7c478bd9Sstevel@tonic-gate * CIS chains in the CIS, and cisinfo_t->Tuples will contain a count of 1396*7c478bd9Sstevel@tonic-gate * the number of tuples in the CIS. If the card does not have a CIS, or 1397*7c478bd9Sstevel@tonic-gate * if the function number is not equal to 0, CS_NO_CIS will be returned 1398*7c478bd9Sstevel@tonic-gate * and the cisinfo_t->Chains and cisinfo_t->Tuples members will be set 1399*7c478bd9Sstevel@tonic-gate * to 0. 1400*7c478bd9Sstevel@tonic-gate * 1401*7c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 1402*7c478bd9Sstevel@tonic-gate * the number of CIS chains in the global and function-specific 1403*7c478bd9Sstevel@tonic-gate * portions of the CIS, and cisinfo_t->Tuples will contain a count of 1404*7c478bd9Sstevel@tonic-gate * the number of tuples in the global and function-specific portions of 1405*7c478bd9Sstevel@tonic-gate * the CIS. If the function does not exist or has no CIS, CS_NO_CIS 1406*7c478bd9Sstevel@tonic-gate * will be returned and the cisinfo_t->Chains and cisinfo_t->Tuples 1407*7c478bd9Sstevel@tonic-gate * members will be set to 0. 1408*7c478bd9Sstevel@tonic-gate * 1409*7c478bd9Sstevel@tonic-gate * General notes: 1410*7c478bd9Sstevel@tonic-gate * 1411*7c478bd9Sstevel@tonic-gate * If the card does not have a CIS, or if the function does not exist 1412*7c478bd9Sstevel@tonic-gate * or has no CIS, CS_NO_CIS will be returned and the cisinfo_t->Chains 1413*7c478bd9Sstevel@tonic-gate * and cisinfo_t->Tuples members will be set to 0. 1414*7c478bd9Sstevel@tonic-gate * 1415*7c478bd9Sstevel@tonic-gate * Most of the work of validating the CIS has already been done by the 1416*7c478bd9Sstevel@tonic-gate * CIS parser module, so we don't have to do much here except for 1417*7c478bd9Sstevel@tonic-gate * looking at the various flags and tuple/chain counts that were already 1418*7c478bd9Sstevel@tonic-gate * setup by the CIS parser. 1419*7c478bd9Sstevel@tonic-gate * 1420*7c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 1421*7c478bd9Sstevel@tonic-gate */ 1422*7c478bd9Sstevel@tonic-gate static int 1423*7c478bd9Sstevel@tonic-gate cs_validate_cis(client_handle_t client_handle, cisinfo_t *cisinfo) 1424*7c478bd9Sstevel@tonic-gate { 1425*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 1426*7c478bd9Sstevel@tonic-gate client_t *client; 1427*7c478bd9Sstevel@tonic-gate uint32_t fn; 1428*7c478bd9Sstevel@tonic-gate int ret; 1429*7c478bd9Sstevel@tonic-gate 1430*7c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &cisinfo->Socket, &fn, 1431*7c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 1432*7c478bd9Sstevel@tonic-gate return (ret); 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate /* 1435*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 1436*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 1437*7c478bd9Sstevel@tonic-gate */ 1438*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 1439*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 1442*7c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 1443*7c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 1444*7c478bd9Sstevel@tonic-gate cisinfo->Chains = sp->cis[fn].nchains; 1445*7c478bd9Sstevel@tonic-gate cisinfo->Tuples = sp->cis[fn].ntuples; 1446*7c478bd9Sstevel@tonic-gate 1447*7c478bd9Sstevel@tonic-gate if ((fn != CS_GLOBAL_CIS) && 1448*7c478bd9Sstevel@tonic-gate (sp->cis[CS_GLOBAL_CIS].flags & CW_VALID_CIS)) { 1449*7c478bd9Sstevel@tonic-gate cisinfo->Chains += sp->cis[CS_GLOBAL_CIS].nchains; 1450*7c478bd9Sstevel@tonic-gate cisinfo->Tuples += sp->cis[CS_GLOBAL_CIS].ntuples; 1451*7c478bd9Sstevel@tonic-gate } /* !CS_GLOBAL_CIS */ 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 1454*7c478bd9Sstevel@tonic-gate } else { 1455*7c478bd9Sstevel@tonic-gate cisinfo->Chains = 0; 1456*7c478bd9Sstevel@tonic-gate cisinfo->Tuples = 0; 1457*7c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate return (ret); 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate /* 1465*7c478bd9Sstevel@tonic-gate * cs_init_cis_window - initializes the CIS window for the passed socket 1466*7c478bd9Sstevel@tonic-gate * 1467*7c478bd9Sstevel@tonic-gate * calling: *sp - pointer to the per-socket structure 1468*7c478bd9Sstevel@tonic-gate * *offset - offset from start of AM or CM space 1469*7c478bd9Sstevel@tonic-gate * *hp - pointer to acc_handle_t to store modified 1470*7c478bd9Sstevel@tonic-gate * window access handle in 1471*7c478bd9Sstevel@tonic-gate * flags - one of: 1472*7c478bd9Sstevel@tonic-gate * CISTPLF_AM_SPACE - set window to AM space 1473*7c478bd9Sstevel@tonic-gate * CISTPLF_CM_SPACE - set window to CM space 1474*7c478bd9Sstevel@tonic-gate * 1475*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if CIS window was set up 1476*7c478bd9Sstevel@tonic-gate * *offset - contains adjusted offset to use to access 1477*7c478bd9Sstevel@tonic-gate * requested space 1478*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW if CIS window could not be setup 1479*7c478bd9Sstevel@tonic-gate * CS_GENERAL_FAILURE if socket has a CIS window number 1480*7c478bd9Sstevel@tonic-gate * but the window flags are wrong 1481*7c478bd9Sstevel@tonic-gate * 1482*7c478bd9Sstevel@tonic-gate * Note: This function will check to be sure that there is a valid 1483*7c478bd9Sstevel@tonic-gate * CIS window allocated to this socket. 1484*7c478bd9Sstevel@tonic-gate * If there is an error in setting up the window hardware, the 1485*7c478bd9Sstevel@tonic-gate * CIS window information for this socket is cleared. 1486*7c478bd9Sstevel@tonic-gate * This function is also used by routines that need to get 1487*7c478bd9Sstevel@tonic-gate * a pointer to the base of AM space to access the card's 1488*7c478bd9Sstevel@tonic-gate * configuration registers. 1489*7c478bd9Sstevel@tonic-gate * The passed offset is the un-window-size-aligned offset. 1490*7c478bd9Sstevel@tonic-gate */ 1491*7c478bd9Sstevel@tonic-gate int 1492*7c478bd9Sstevel@tonic-gate cs_init_cis_window(cs_socket_t *sp, uint32_t *offset, 1493*7c478bd9Sstevel@tonic-gate acc_handle_t *hp, uint32_t flags) 1494*7c478bd9Sstevel@tonic-gate { 1495*7c478bd9Sstevel@tonic-gate set_window_t sw; 1496*7c478bd9Sstevel@tonic-gate get_window_t gw; 1497*7c478bd9Sstevel@tonic-gate inquire_window_t iw; 1498*7c478bd9Sstevel@tonic-gate set_page_t set_page; 1499*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate /* 1502*7c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 1503*7c478bd9Sstevel@tonic-gate */ 1504*7c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 1505*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1506*7c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d has no CIS window\n", 1507*7c478bd9Sstevel@tonic-gate sp->socket_num); 1508*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1509*7c478bd9Sstevel@tonic-gate } 1510*7c478bd9Sstevel@tonic-gate 1511*7c478bd9Sstevel@tonic-gate /* 1512*7c478bd9Sstevel@tonic-gate * Check to be sure that this window is allocated for CIS use 1513*7c478bd9Sstevel@tonic-gate */ 1514*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) 1515*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate if (!(cw->state & CW_CIS)) { 1518*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1519*7c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d invalid CIS window state 0x%x\n", 1520*7c478bd9Sstevel@tonic-gate sp->socket_num, cw->state); 1521*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate /* 1525*7c478bd9Sstevel@tonic-gate * Get the characteristics of this window - we use this to 1526*7c478bd9Sstevel@tonic-gate * determine whether we need to re-map the window or 1527*7c478bd9Sstevel@tonic-gate * just move the window offset on the card. 1528*7c478bd9Sstevel@tonic-gate */ 1529*7c478bd9Sstevel@tonic-gate iw.window = sp->cis_win_num; 1530*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate /* 1533*7c478bd9Sstevel@tonic-gate * We've got a window, now set up the hardware. If we've got 1534*7c478bd9Sstevel@tonic-gate * a variable sized window, then all we need to do is to 1535*7c478bd9Sstevel@tonic-gate * get a valid mapping to the base of the window using 1536*7c478bd9Sstevel@tonic-gate * the current window size; if we've got a fixed-size 1537*7c478bd9Sstevel@tonic-gate * window, then we need to get a mapping to the window 1538*7c478bd9Sstevel@tonic-gate * starting at offset zero of the window. 1539*7c478bd9Sstevel@tonic-gate */ 1540*7c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_SIZE) { 1541*7c478bd9Sstevel@tonic-gate sw.WindowSize = sp->cis_win_size; 1542*7c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / sp->cis_win_size) * 1543*7c478bd9Sstevel@tonic-gate sp->cis_win_size); 1544*7c478bd9Sstevel@tonic-gate } else { 1545*7c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / iw.mem_win_char.MinSize) * 1546*7c478bd9Sstevel@tonic-gate iw.mem_win_char.MinSize); 1547*7c478bd9Sstevel@tonic-gate sw.WindowSize = (((*offset & ~(PAGESIZE - 1)) & 1548*7c478bd9Sstevel@tonic-gate (set_page.offset - 1)) + PAGESIZE); 1549*7c478bd9Sstevel@tonic-gate } 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate /* 1552*7c478bd9Sstevel@tonic-gate * Return a normalized base offset; this takes care of the case 1553*7c478bd9Sstevel@tonic-gate * where the required offset is greater than the window size. 1554*7c478bd9Sstevel@tonic-gate * BugID 1236404 1555*7c478bd9Sstevel@tonic-gate * code was: 1556*7c478bd9Sstevel@tonic-gate * *offset = *offset & (set_page.offset - 1); 1557*7c478bd9Sstevel@tonic-gate */ 1558*7c478bd9Sstevel@tonic-gate *offset = *offset - set_page.offset; 1559*7c478bd9Sstevel@tonic-gate 1560*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 1561*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) 1562*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_init_cis_window: WindowSize 0x%x " 1563*7c478bd9Sstevel@tonic-gate "offset 0x%x\n", 1564*7c478bd9Sstevel@tonic-gate (int)sw.WindowSize, 1565*7c478bd9Sstevel@tonic-gate (int)set_page.offset); 1566*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) 1567*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t*offset = 0x%x space = %s\n", 1568*7c478bd9Sstevel@tonic-gate (int)*offset, 1569*7c478bd9Sstevel@tonic-gate (flags & CISTPLF_AM_SPACE)? 1570*7c478bd9Sstevel@tonic-gate "CISTPLF_AM_SPACE":"CISTPLF_CM_SPACE"); 1571*7c478bd9Sstevel@tonic-gate #endif 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate sw.window = sp->cis_win_num; 1574*7c478bd9Sstevel@tonic-gate sw.socket = sp->socket_num; 1575*7c478bd9Sstevel@tonic-gate sw.state = (WS_ENABLED | WS_EXACT_MAPIN); 1576*7c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1577*7c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 1578*7c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1579*7c478bd9Sstevel@tonic-gate 1580*7c478bd9Sstevel@tonic-gate /* 1581*7c478bd9Sstevel@tonic-gate * The PCMCIA SS spec specifies this be expressed in 1582*7c478bd9Sstevel@tonic-gate * a device speed format per 5.2.7.1.3 but 1583*7c478bd9Sstevel@tonic-gate * our implementation of SS_SetWindow uses 1584*7c478bd9Sstevel@tonic-gate * actual nanoseconds. 1585*7c478bd9Sstevel@tonic-gate */ 1586*7c478bd9Sstevel@tonic-gate sw.speed = CIS_DEFAULT_SPEED; 1587*7c478bd9Sstevel@tonic-gate sw.base = 0; 1588*7c478bd9Sstevel@tonic-gate /* 1589*7c478bd9Sstevel@tonic-gate * Set up the window - if this fails, then just set the 1590*7c478bd9Sstevel@tonic-gate * CIS window number back to it's initialized value so 1591*7c478bd9Sstevel@tonic-gate * that we'll fail when we break out of the loop. 1592*7c478bd9Sstevel@tonic-gate */ 1593*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) { 1594*7c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1595*7c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 1596*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1597*7c478bd9Sstevel@tonic-gate } else { 1598*7c478bd9Sstevel@tonic-gate set_page.window = sp->cis_win_num; 1599*7c478bd9Sstevel@tonic-gate set_page.page = 0; 1600*7c478bd9Sstevel@tonic-gate set_page.state = PS_ENABLED; 1601*7c478bd9Sstevel@tonic-gate if (flags & CISTPLF_AM_SPACE) 1602*7c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 1605*7c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 1606*7c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 1607*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1608*7c478bd9Sstevel@tonic-gate } /* if (SS_SetPage) */ 1609*7c478bd9Sstevel@tonic-gate } /* if (SS_SetWindow) */ 1610*7c478bd9Sstevel@tonic-gate 1611*7c478bd9Sstevel@tonic-gate /* 1612*7c478bd9Sstevel@tonic-gate * Get the window information for the CIS window for this socket. 1613*7c478bd9Sstevel@tonic-gate */ 1614*7c478bd9Sstevel@tonic-gate gw.window = sp->cis_win_num; 1615*7c478bd9Sstevel@tonic-gate gw.socket = sp->socket_num; /* XXX - SS_GetWindow should set this */ 1616*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 1617*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate *hp = (acc_handle_t)gw.handle; 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1622*7c478bd9Sstevel@tonic-gate } 1623*7c478bd9Sstevel@tonic-gate 1624*7c478bd9Sstevel@tonic-gate /* 1625*7c478bd9Sstevel@tonic-gate * ==== client registration/deregistration section ==== 1626*7c478bd9Sstevel@tonic-gate */ 1627*7c478bd9Sstevel@tonic-gate 1628*7c478bd9Sstevel@tonic-gate /* 1629*7c478bd9Sstevel@tonic-gate * cs_register_client - This supports the RegisterClient call. 1630*7c478bd9Sstevel@tonic-gate * 1631*7c478bd9Sstevel@tonic-gate * Upon successful registration, the client_handle_t * handle argument will 1632*7c478bd9Sstevel@tonic-gate * contain the new client handle and we return CS_SUCCESS. 1633*7c478bd9Sstevel@tonic-gate */ 1634*7c478bd9Sstevel@tonic-gate static int 1635*7c478bd9Sstevel@tonic-gate cs_register_client(client_handle_t *ch, client_reg_t *cr) 1636*7c478bd9Sstevel@tonic-gate { 1637*7c478bd9Sstevel@tonic-gate uint32_t sn; 1638*7c478bd9Sstevel@tonic-gate int super_client = 0; 1639*7c478bd9Sstevel@tonic-gate sclient_reg_t *scr = cr->priv; 1640*7c478bd9Sstevel@tonic-gate struct sclient_list_t *scli; 1641*7c478bd9Sstevel@tonic-gate 1642*7c478bd9Sstevel@tonic-gate /* 1643*7c478bd9Sstevel@tonic-gate * See if we're not supposed to register any new clients. 1644*7c478bd9Sstevel@tonic-gate */ 1645*7c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_NO_CLIENTS) 1646*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate /* 1649*7c478bd9Sstevel@tonic-gate * Do a version check - if the client expects a later version of 1650*7c478bd9Sstevel@tonic-gate * Card Services than what we are, return CS_BAD_VERSION. 1651*7c478bd9Sstevel@tonic-gate * XXX - How do we specify just a PARTICULAR version of CS?? 1652*7c478bd9Sstevel@tonic-gate */ 1653*7c478bd9Sstevel@tonic-gate if (CS_VERSION < cr->Version) 1654*7c478bd9Sstevel@tonic-gate return (CS_BAD_VERSION); 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate /* 1657*7c478bd9Sstevel@tonic-gate * Check to be sure that the client has given us a valid set of 1658*7c478bd9Sstevel@tonic-gate * client type flags. We also use this opportunity to see 1659*7c478bd9Sstevel@tonic-gate * if the registering client is Socket Services or is a 1660*7c478bd9Sstevel@tonic-gate * "super-client" or a CSI client. 1661*7c478bd9Sstevel@tonic-gate * 1662*7c478bd9Sstevel@tonic-gate * Note that SS can not set any flag in the Attributes field other 1663*7c478bd9Sstevel@tonic-gate * than the INFO_SOCKET_SERVICES flag. 1664*7c478bd9Sstevel@tonic-gate * 1665*7c478bd9Sstevel@tonic-gate * Valid combinations of cr->Attributes and cr->EventMask flags: 1666*7c478bd9Sstevel@tonic-gate * 1667*7c478bd9Sstevel@tonic-gate * for Socket Services: 1668*7c478bd9Sstevel@tonic-gate * cr->Attributes: 1669*7c478bd9Sstevel@tonic-gate * set: 1670*7c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 1671*7c478bd9Sstevel@tonic-gate * clear: 1672*7c478bd9Sstevel@tonic-gate * {all other flags} 1673*7c478bd9Sstevel@tonic-gate * cr->EventMask: 1674*7c478bd9Sstevel@tonic-gate * don't care: 1675*7c478bd9Sstevel@tonic-gate * {all flags} 1676*7c478bd9Sstevel@tonic-gate * 1677*7c478bd9Sstevel@tonic-gate * for regular clients: 1678*7c478bd9Sstevel@tonic-gate * cr->Attributes: 1679*7c478bd9Sstevel@tonic-gate * only one of: 1680*7c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 1681*7c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 1682*7c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 1683*7c478bd9Sstevel@tonic-gate * don't care: 1684*7c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 1685*7c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 1686*7c478bd9Sstevel@tonic-gate * cr->EventMask: 1687*7c478bd9Sstevel@tonic-gate * clear: 1688*7c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 1689*7c478bd9Sstevel@tonic-gate * don't care: 1690*7c478bd9Sstevel@tonic-gate * {all other flags} 1691*7c478bd9Sstevel@tonic-gate * 1692*7c478bd9Sstevel@tonic-gate * for CSI clients: 1693*7c478bd9Sstevel@tonic-gate * cr->Attributes: 1694*7c478bd9Sstevel@tonic-gate * set: 1695*7c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 1696*7c478bd9Sstevel@tonic-gate * INFO_CSI_CLIENT 1697*7c478bd9Sstevel@tonic-gate * clear: 1698*7c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 1699*7c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 1700*7c478bd9Sstevel@tonic-gate * don't care: 1701*7c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 1702*7c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 1703*7c478bd9Sstevel@tonic-gate * cr->EventMask: 1704*7c478bd9Sstevel@tonic-gate * don't care: 1705*7c478bd9Sstevel@tonic-gate * {all flags} 1706*7c478bd9Sstevel@tonic-gate * 1707*7c478bd9Sstevel@tonic-gate * for "super-clients": 1708*7c478bd9Sstevel@tonic-gate * cr->Attributes: 1709*7c478bd9Sstevel@tonic-gate * set: 1710*7c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 1711*7c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 1712*7c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 1713*7c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 1714*7c478bd9Sstevel@tonic-gate * clear: 1715*7c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 1716*7c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 1717*7c478bd9Sstevel@tonic-gate * cr->EventMask: 1718*7c478bd9Sstevel@tonic-gate * don't care: 1719*7c478bd9Sstevel@tonic-gate * {all flags} 1720*7c478bd9Sstevel@tonic-gate */ 1721*7c478bd9Sstevel@tonic-gate switch (cr->Attributes & INFO_CLIENT_TYPE_MASK) { 1722*7c478bd9Sstevel@tonic-gate /* 1723*7c478bd9Sstevel@tonic-gate * Check first to see if this is Socket Services registering; if 1724*7c478bd9Sstevel@tonic-gate * so, we don't do anything but return the client handle that is 1725*7c478bd9Sstevel@tonic-gate * in the global SS client. 1726*7c478bd9Sstevel@tonic-gate */ 1727*7c478bd9Sstevel@tonic-gate case INFO_SOCKET_SERVICES: 1728*7c478bd9Sstevel@tonic-gate *ch = cs_socket_services_client.client_handle; 1729*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1730*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1731*7c478bd9Sstevel@tonic-gate /* CSI clients */ 1732*7c478bd9Sstevel@tonic-gate case (INFO_CSI_CLIENT | INFO_IO_CLIENT): 1733*7c478bd9Sstevel@tonic-gate break; 1734*7c478bd9Sstevel@tonic-gate /* regular clients */ 1735*7c478bd9Sstevel@tonic-gate case INFO_IO_CLIENT: 1736*7c478bd9Sstevel@tonic-gate case INFO_MTD_CLIENT: 1737*7c478bd9Sstevel@tonic-gate case INFO_MEM_CLIENT: 1738*7c478bd9Sstevel@tonic-gate if (cr->EventMask & CS_EVENT_ALL_CLIENTS) 1739*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1740*7c478bd9Sstevel@tonic-gate break; 1741*7c478bd9Sstevel@tonic-gate /* "super-client" clients */ 1742*7c478bd9Sstevel@tonic-gate case (INFO_IO_CLIENT | INFO_MTD_CLIENT | INFO_SOCKET_SERVICES): 1743*7c478bd9Sstevel@tonic-gate if ((!(cr->Attributes & INFO_CARD_SHARE)) || 1744*7c478bd9Sstevel@tonic-gate (cr->Attributes & INFO_CARD_EXCL)) 1745*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1746*7c478bd9Sstevel@tonic-gate /* 1747*7c478bd9Sstevel@tonic-gate * We only allow one "super-client" per system. 1748*7c478bd9Sstevel@tonic-gate */ 1749*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 1750*7c478bd9Sstevel@tonic-gate if (cs_globals.flags & GLOBAL_SUPER_CLIENT_REGISTERED) { 1751*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 1752*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate cs_globals.flags |= GLOBAL_SUPER_CLIENT_REGISTERED; 1755*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 1756*7c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 1757*7c478bd9Sstevel@tonic-gate break; 1758*7c478bd9Sstevel@tonic-gate default: 1759*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 1760*7c478bd9Sstevel@tonic-gate } /* switch (cr->Attributes) */ 1761*7c478bd9Sstevel@tonic-gate 1762*7c478bd9Sstevel@tonic-gate /* 1763*7c478bd9Sstevel@tonic-gate * Now, actually create the client node on the socket; this will 1764*7c478bd9Sstevel@tonic-gate * also return the new client handle if there were no errors 1765*7c478bd9Sstevel@tonic-gate * creating the client node. 1766*7c478bd9Sstevel@tonic-gate * The DIP2SOCKET_NUM macro will return the socket and function 1767*7c478bd9Sstevel@tonic-gate * number using the encoding specified in the cs_priv.h file. 1768*7c478bd9Sstevel@tonic-gate */ 1769*7c478bd9Sstevel@tonic-gate if (super_client != CLIENT_SUPER_CLIENT) { 1770*7c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 1771*7c478bd9Sstevel@tonic-gate sn = (uint32_t)(uintptr_t)cr->priv; 1772*7c478bd9Sstevel@tonic-gate else 1773*7c478bd9Sstevel@tonic-gate sn = DIP2SOCKET_NUM(cr->dip); 1774*7c478bd9Sstevel@tonic-gate return (cs_add_client_to_socket(sn, ch, cr, super_client)); 1775*7c478bd9Sstevel@tonic-gate } /* CLIENT_SUPER_CLIENT */ 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate /* 1778*7c478bd9Sstevel@tonic-gate * This registering client is a "super-client", so we create one 1779*7c478bd9Sstevel@tonic-gate * client node for each socket in the system. We use the 1780*7c478bd9Sstevel@tonic-gate * client_reg_t.priv structure member to point to a struct 1781*7c478bd9Sstevel@tonic-gate * that the "super-client" client knows about. The client 1782*7c478bd9Sstevel@tonic-gate * handle pointer is not used in this case. 1783*7c478bd9Sstevel@tonic-gate * We return CS_SUCCESS if at least one client node could be 1784*7c478bd9Sstevel@tonic-gate * created. The client must check the error codes in the 1785*7c478bd9Sstevel@tonic-gate * error code array to determine which clients could not 1786*7c478bd9Sstevel@tonic-gate * be created on which sockets. 1787*7c478bd9Sstevel@tonic-gate * We return CS_BAD_HANDLE if no client nodes could be created. 1788*7c478bd9Sstevel@tonic-gate */ 1789*7c478bd9Sstevel@tonic-gate scr->num_clients = 0; 1790*7c478bd9Sstevel@tonic-gate scr->max_socket_num = cs_globals.max_socket_num; 1791*7c478bd9Sstevel@tonic-gate scr->num_sockets = cs_globals.num_sockets; 1792*7c478bd9Sstevel@tonic-gate scr->num_windows = cs_globals.num_windows; 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate *(scr->sclient_list) = cs_globals.sclient_list; 1795*7c478bd9Sstevel@tonic-gate 1796*7c478bd9Sstevel@tonic-gate for (sn = 0; sn < scr->num_sockets; sn++) { 1797*7c478bd9Sstevel@tonic-gate scli = scr->sclient_list[sn]; 1798*7c478bd9Sstevel@tonic-gate if ((scli->error = cs_add_client_to_socket(sn, &scli->client_handle, 1799*7c478bd9Sstevel@tonic-gate cr, super_client)) == CS_SUCCESS) { 1800*7c478bd9Sstevel@tonic-gate scr->num_clients++; 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate } 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate /* 1805*7c478bd9Sstevel@tonic-gate * If we couldn't create any client nodes at all, then 1806*7c478bd9Sstevel@tonic-gate * return an error. 1807*7c478bd9Sstevel@tonic-gate */ 1808*7c478bd9Sstevel@tonic-gate if (!scr->num_clients) { 1809*7c478bd9Sstevel@tonic-gate /* 1810*7c478bd9Sstevel@tonic-gate * XXX - The global superclient lock now gets 1811*7c478bd9Sstevel@tonic-gate * cleared in cs_deregister_client 1812*7c478bd9Sstevel@tonic-gate */ 1813*7c478bd9Sstevel@tonic-gate /* cs_clear_superclient_lock(super_client); */ 1814*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 1815*7c478bd9Sstevel@tonic-gate } 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 1818*7c478bd9Sstevel@tonic-gate } 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate /* 1821*7c478bd9Sstevel@tonic-gate * cs_add_client_to_socket - this function creates the client node on the 1822*7c478bd9Sstevel@tonic-gate * requested socket. 1823*7c478bd9Sstevel@tonic-gate * 1824*7c478bd9Sstevel@tonic-gate * Note that if we return an error, there is no state that can be cleaned 1825*7c478bd9Sstevel@tonic-gate * up. The only way that we can return an error with allocated resources 1826*7c478bd9Sstevel@tonic-gate * would be if one of the client handle functions had an internal error. 1827*7c478bd9Sstevel@tonic-gate * Since we wouldn't get a valid client handle in this case anyway, there 1828*7c478bd9Sstevel@tonic-gate * would be no way to find out what was allocated and what wasn't. 1829*7c478bd9Sstevel@tonic-gate */ 1830*7c478bd9Sstevel@tonic-gate static int 1831*7c478bd9Sstevel@tonic-gate cs_add_client_to_socket(unsigned sn, client_handle_t *ch, 1832*7c478bd9Sstevel@tonic-gate client_reg_t *cr, int super_client) 1833*7c478bd9Sstevel@tonic-gate { 1834*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 1835*7c478bd9Sstevel@tonic-gate client_t *client, *cclp; 1836*7c478bd9Sstevel@tonic-gate int error, cie = 1; 1837*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate if (cr->event_handler == NULL) 1840*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 1841*7c478bd9Sstevel@tonic-gate 1842*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 1843*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 1846*7c478bd9Sstevel@tonic-gate 1847*7c478bd9Sstevel@tonic-gate /* 1848*7c478bd9Sstevel@tonic-gate * Run through all of the registered clients and compare the passed 1849*7c478bd9Sstevel@tonic-gate * dip to the dip of each client to make sure that this client 1850*7c478bd9Sstevel@tonic-gate * is not trying to register more than once. If they are, then 1851*7c478bd9Sstevel@tonic-gate * display a message and return an error. 1852*7c478bd9Sstevel@tonic-gate * XXX - we should really check all the sockets in case the client 1853*7c478bd9Sstevel@tonic-gate * manipulates the instance number in the dip. 1854*7c478bd9Sstevel@tonic-gate * XXX - if we check each socket, we ned to also check for the 1855*7c478bd9Sstevel@tonic-gate * "super-client" since it will use the same dip for all 1856*7c478bd9Sstevel@tonic-gate * of it's client nodes. 1857*7c478bd9Sstevel@tonic-gate */ 1858*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 1859*7c478bd9Sstevel@tonic-gate client = sp->client_list; 1860*7c478bd9Sstevel@tonic-gate while (client) { 1861*7c478bd9Sstevel@tonic-gate if (!(cr->Attributes & INFO_CSI_CLIENT) && 1862*7c478bd9Sstevel@tonic-gate (client->dip == cr->dip)) { 1863*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 1864*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1865*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d " 1866*7c478bd9Sstevel@tonic-gate "function 0x%x\n" 1867*7c478bd9Sstevel@tonic-gate "\tclient already registered with " 1868*7c478bd9Sstevel@tonic-gate "handle 0x%x\n", 1869*7c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 1870*7c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 1871*7c478bd9Sstevel@tonic-gate (int)client->client_handle); 1872*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 1873*7c478bd9Sstevel@tonic-gate } 1874*7c478bd9Sstevel@tonic-gate client = client->next; 1875*7c478bd9Sstevel@tonic-gate } /* while (client) */ 1876*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate /* 1879*7c478bd9Sstevel@tonic-gate * Create a unique client handle then make sure that we can find it. 1880*7c478bd9Sstevel@tonic-gate * This has the side effect of getting us a pointer to the 1881*7c478bd9Sstevel@tonic-gate * client structure as well. 1882*7c478bd9Sstevel@tonic-gate * Create a client list entry - cs_create_client_handle will use this 1883*7c478bd9Sstevel@tonic-gate * as the new client node. 1884*7c478bd9Sstevel@tonic-gate * We do it here so that we can grab the sp->lock mutex for the 1885*7c478bd9Sstevel@tonic-gate * duration of our manipulation of the client list. 1886*7c478bd9Sstevel@tonic-gate * If this function fails, then it will not have added the newly 1887*7c478bd9Sstevel@tonic-gate * allocated client node to the client list on this socket, 1888*7c478bd9Sstevel@tonic-gate * so we have to free the node that we allocated. 1889*7c478bd9Sstevel@tonic-gate */ 1890*7c478bd9Sstevel@tonic-gate cclp = (client_t *)kmem_zalloc(sizeof (client_t), KM_SLEEP); 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 1893*7c478bd9Sstevel@tonic-gate if (!(*ch = cs_create_client_handle(sn, cclp))) { 1894*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 1895*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1896*7c478bd9Sstevel@tonic-gate kmem_free(cclp, sizeof (client_t)); 1897*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate /* 1901*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. We should never 1902*7c478bd9Sstevel@tonic-gate * fail this since we just got a valid client handle. 1903*7c478bd9Sstevel@tonic-gate * If this fails, then we have an internal error so don't bother 1904*7c478bd9Sstevel@tonic-gate * trying to clean up the allocated client handle since the 1905*7c478bd9Sstevel@tonic-gate * whole system is probably hosed anyway and will shortly 1906*7c478bd9Sstevel@tonic-gate * esplode. 1907*7c478bd9Sstevel@tonic-gate * It doesn't make sense to call cs_deregister_client at this point 1908*7c478bd9Sstevel@tonic-gate * to clean up this broken client since the deregistration 1909*7c478bd9Sstevel@tonic-gate * code will also call cs_find_client and most likely fail. 1910*7c478bd9Sstevel@tonic-gate */ 1911*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(*ch, &error))) { 1912*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 1913*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 1914*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d function 0x%x " 1915*7c478bd9Sstevel@tonic-gate "invalid client handle created handle 0x%x\n", 1916*7c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 1917*7c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 1918*7c478bd9Sstevel@tonic-gate (int)*ch); 1919*7c478bd9Sstevel@tonic-gate return (error); 1920*7c478bd9Sstevel@tonic-gate } 1921*7c478bd9Sstevel@tonic-gate 1922*7c478bd9Sstevel@tonic-gate /* 1923*7c478bd9Sstevel@tonic-gate * Save the DDI information. 1924*7c478bd9Sstevel@tonic-gate */ 1925*7c478bd9Sstevel@tonic-gate client->dip = cr->dip; 1926*7c478bd9Sstevel@tonic-gate cr->driver_name[MODMAXNAMELEN - 1] = NULL; 1927*7c478bd9Sstevel@tonic-gate client->driver_name = (char *)kmem_zalloc(strlen(cr->driver_name) + 1, 1928*7c478bd9Sstevel@tonic-gate KM_SLEEP); 1929*7c478bd9Sstevel@tonic-gate (void) strcpy(client->driver_name, cr->driver_name); 1930*7c478bd9Sstevel@tonic-gate client->instance = ddi_get_instance(cr->dip); 1931*7c478bd9Sstevel@tonic-gate 1932*7c478bd9Sstevel@tonic-gate /* 1933*7c478bd9Sstevel@tonic-gate * Copy over the interesting items that the client gave us. 1934*7c478bd9Sstevel@tonic-gate */ 1935*7c478bd9Sstevel@tonic-gate client->flags = (cr->Attributes & INFO_CLIENT_TYPE_MASK); 1936*7c478bd9Sstevel@tonic-gate client->event_callback_handler = cr->event_handler; 1937*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)&cr->event_callback_args, 1938*7c478bd9Sstevel@tonic-gate (caddr_t)&client->event_callback_args, 1939*7c478bd9Sstevel@tonic-gate sizeof (event_callback_args_t)); 1940*7c478bd9Sstevel@tonic-gate /* 1941*7c478bd9Sstevel@tonic-gate * Set the client handle since the client needs a client handle 1942*7c478bd9Sstevel@tonic-gate * when they call us for their event handler. 1943*7c478bd9Sstevel@tonic-gate */ 1944*7c478bd9Sstevel@tonic-gate client->event_callback_args.client_handle = *ch; 1945*7c478bd9Sstevel@tonic-gate 1946*7c478bd9Sstevel@tonic-gate /* 1947*7c478bd9Sstevel@tonic-gate * Initialize the IO window numbers; if an IO window number is equal 1948*7c478bd9Sstevel@tonic-gate * to PCMCIA_MAX_WINDOWS it means that IO range is not in use. 1949*7c478bd9Sstevel@tonic-gate */ 1950*7c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = PCMCIA_MAX_WINDOWS; 1951*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 1952*7c478bd9Sstevel@tonic-gate 1953*7c478bd9Sstevel@tonic-gate /* 1954*7c478bd9Sstevel@tonic-gate * Give the client the iblock and idevice cookies to use in 1955*7c478bd9Sstevel@tonic-gate * the client's event handler high priority mutex. 1956*7c478bd9Sstevel@tonic-gate */ 1957*7c478bd9Sstevel@tonic-gate cr->iblk_cookie = sp->iblk; 1958*7c478bd9Sstevel@tonic-gate cr->idev_cookie = sp->idev; 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate /* 1961*7c478bd9Sstevel@tonic-gate * Set up the global event mask information; we copy this directly 1962*7c478bd9Sstevel@tonic-gate * from the client; since we are the only source of events, 1963*7c478bd9Sstevel@tonic-gate * any bogus bits that the client puts in here won't matter 1964*7c478bd9Sstevel@tonic-gate * because we'll never look at them. 1965*7c478bd9Sstevel@tonic-gate */ 1966*7c478bd9Sstevel@tonic-gate client->global_mask = cr->EventMask; 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate /* 1969*7c478bd9Sstevel@tonic-gate * If this client registered as a CSI client, set the appropriate 1970*7c478bd9Sstevel@tonic-gate * flag in the client's flags area. 1971*7c478bd9Sstevel@tonic-gate */ 1972*7c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 1973*7c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CSI_CLIENT; 1974*7c478bd9Sstevel@tonic-gate 1975*7c478bd9Sstevel@tonic-gate /* 1976*7c478bd9Sstevel@tonic-gate * If this client registered as a "super-client" set the appropriate 1977*7c478bd9Sstevel@tonic-gate * flag in the client's flags area. 1978*7c478bd9Sstevel@tonic-gate */ 1979*7c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) 1980*7c478bd9Sstevel@tonic-gate client->flags |= CLIENT_SUPER_CLIENT; 1981*7c478bd9Sstevel@tonic-gate 1982*7c478bd9Sstevel@tonic-gate /* 1983*7c478bd9Sstevel@tonic-gate * Save other misc information that this client gave us - it is 1984*7c478bd9Sstevel@tonic-gate * used in the GetClientInfo function. 1985*7c478bd9Sstevel@tonic-gate */ 1986*7c478bd9Sstevel@tonic-gate client->flags |= (cr->Attributes & INFO_CARD_FLAGS_MASK); 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate /* 1989*7c478bd9Sstevel@tonic-gate * Determine if we should give artificial card insertion events and 1990*7c478bd9Sstevel@tonic-gate * a registration complete event. Since we don't differentiate 1991*7c478bd9Sstevel@tonic-gate * between sharable and exclusive use cards when giving clients 1992*7c478bd9Sstevel@tonic-gate * event notification, we modify the definition of the share/excl 1993*7c478bd9Sstevel@tonic-gate * flags as follows: 1994*7c478bd9Sstevel@tonic-gate * 1995*7c478bd9Sstevel@tonic-gate * If either INFO_CARD_SHARE or INFO_CARD_EXCL is set, 1996*7c478bd9Sstevel@tonic-gate * the client will receive artificial card insertion 1997*7c478bd9Sstevel@tonic-gate * events (if the client's card is currently in the 1998*7c478bd9Sstevel@tonic-gate * socket) and a registration complete event. 1999*7c478bd9Sstevel@tonic-gate * 2000*7c478bd9Sstevel@tonic-gate * If neither of the INFO_CARD_SHARE or INFO_CARD_EXCL is 2001*7c478bd9Sstevel@tonic-gate * set, the client will not receive an artificial card 2002*7c478bd9Sstevel@tonic-gate * insertion event nor a registration complete event 2003*7c478bd9Sstevel@tonic-gate * due to the client's call to register client. 2004*7c478bd9Sstevel@tonic-gate * 2005*7c478bd9Sstevel@tonic-gate * The client's event mask is not affected by the setting 2006*7c478bd9Sstevel@tonic-gate * of these two bits. 2007*7c478bd9Sstevel@tonic-gate */ 2008*7c478bd9Sstevel@tonic-gate if (cr->Attributes & (INFO_CARD_SHARE | INFO_CARD_EXCL)) 2009*7c478bd9Sstevel@tonic-gate client->pending_events = CS_EVENT_REGISTRATION_COMPLETE; 2010*7c478bd9Sstevel@tonic-gate 2011*7c478bd9Sstevel@tonic-gate /* 2012*7c478bd9Sstevel@tonic-gate * Check to see if the card for this client is currently in 2013*7c478bd9Sstevel@tonic-gate * the socket. If it is, then set CLIENT_CARD_INSERTED 2014*7c478bd9Sstevel@tonic-gate * since clients that are calling GetStatus at attach 2015*7c478bd9Sstevel@tonic-gate * time will typically check to see if their card is 2016*7c478bd9Sstevel@tonic-gate * currently installed. 2017*7c478bd9Sstevel@tonic-gate * If this is the CSI client, we also need to check to see 2018*7c478bd9Sstevel@tonic-gate * if there is any card inserted in the socket, since 2019*7c478bd9Sstevel@tonic-gate * the cs_card_for_client function will always return 2020*7c478bd9Sstevel@tonic-gate * TRUE for a CSI client. 2021*7c478bd9Sstevel@tonic-gate * XXX What about super-clients? 2022*7c478bd9Sstevel@tonic-gate */ 2023*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) { 2024*7c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 2025*7c478bd9Sstevel@tonic-gate 2026*7c478bd9Sstevel@tonic-gate get_ss_status.socket = sp->socket_num; 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, &get_ss_status) != SUCCESS) { 2029*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2030*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2031*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2032*7c478bd9Sstevel@tonic-gate } /* SS_GetStatus */ 2033*7c478bd9Sstevel@tonic-gate 2034*7c478bd9Sstevel@tonic-gate if (!(cs_sbm2cse(get_ss_status.CardState) & 2035*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_INSERTION)) 2036*7c478bd9Sstevel@tonic-gate cie = 0; 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate } /* CLIENT_CSI_CLIENT */ 2039*7c478bd9Sstevel@tonic-gate 2040*7c478bd9Sstevel@tonic-gate if (cs_card_for_client(client) && (cie != 0)) { 2041*7c478bd9Sstevel@tonic-gate client->pending_events |= CS_EVENT_CARD_INSERTION; 2042*7c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CARD_INSERTED; 2043*7c478bd9Sstevel@tonic-gate } /* cs_card_for_client */ 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate sp->num_clients++; 2046*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2047*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2048*7c478bd9Sstevel@tonic-gate 2049*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate /* 2053*7c478bd9Sstevel@tonic-gate * cs_deregister_client - This supports the DeregisterClient call. 2054*7c478bd9Sstevel@tonic-gate */ 2055*7c478bd9Sstevel@tonic-gate static int 2056*7c478bd9Sstevel@tonic-gate cs_deregister_client(client_handle_t client_handle) 2057*7c478bd9Sstevel@tonic-gate { 2058*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 2059*7c478bd9Sstevel@tonic-gate client_t *client; 2060*7c478bd9Sstevel@tonic-gate int error, super_client = 0; 2061*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate /* 2064*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 2065*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 2066*7c478bd9Sstevel@tonic-gate */ 2067*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 2068*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2069*7c478bd9Sstevel@tonic-gate 2070*7c478bd9Sstevel@tonic-gate /* 2071*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 2072*7c478bd9Sstevel@tonic-gate */ 2073*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2074*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 2077*7c478bd9Sstevel@tonic-gate 2078*7c478bd9Sstevel@tonic-gate /* 2079*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 2080*7c478bd9Sstevel@tonic-gate */ 2081*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 2082*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2083*7c478bd9Sstevel@tonic-gate return (error); 2084*7c478bd9Sstevel@tonic-gate } 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate /* 2087*7c478bd9Sstevel@tonic-gate * Make sure that any resources allocated by this client are 2088*7c478bd9Sstevel@tonic-gate * not still allocated, and that if this is an MTD that 2089*7c478bd9Sstevel@tonic-gate * no MTD operations are still in progress. 2090*7c478bd9Sstevel@tonic-gate */ 2091*7c478bd9Sstevel@tonic-gate if (client->flags & (CLIENT_IO_ALLOCATED | 2092*7c478bd9Sstevel@tonic-gate CLIENT_IRQ_ALLOCATED | 2093*7c478bd9Sstevel@tonic-gate CLIENT_WIN_ALLOCATED | 2094*7c478bd9Sstevel@tonic-gate REQ_CONFIGURATION_DONE | 2095*7c478bd9Sstevel@tonic-gate REQ_SOCKET_MASK_DONE | 2096*7c478bd9Sstevel@tonic-gate REQ_IO_DONE | 2097*7c478bd9Sstevel@tonic-gate REQ_IRQ_DONE)) { 2098*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2099*7c478bd9Sstevel@tonic-gate return (CS_BUSY); 2100*7c478bd9Sstevel@tonic-gate } 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_MTD_IN_PROGRESS) { 2103*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2104*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 2105*7c478bd9Sstevel@tonic-gate } 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate /* 2108*7c478bd9Sstevel@tonic-gate * Any previously allocated resources are not allocated anymore, and 2109*7c478bd9Sstevel@tonic-gate * no MTD operations are in progress, so if this is an MTD client 2110*7c478bd9Sstevel@tonic-gate * then do any MTD-specific client deregistration, and then 2111*7c478bd9Sstevel@tonic-gate * nuke this client. 2112*7c478bd9Sstevel@tonic-gate * We expect cs_deregister_mtd to never fail. 2113*7c478bd9Sstevel@tonic-gate */ 2114*7c478bd9Sstevel@tonic-gate if (client->flags & INFO_MTD_CLIENT) 2115*7c478bd9Sstevel@tonic-gate (void) cs_deregister_mtd(client_handle); 2116*7c478bd9Sstevel@tonic-gate 2117*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_SUPER_CLIENT) 2118*7c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 2119*7c478bd9Sstevel@tonic-gate 2120*7c478bd9Sstevel@tonic-gate kmem_free(client->driver_name, strlen(client->driver_name) + 1); 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate error = cs_destroy_client_handle(client_handle); 2123*7c478bd9Sstevel@tonic-gate 2124*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate /* 2127*7c478bd9Sstevel@tonic-gate * If this was the "super-client" deregistering, then this 2128*7c478bd9Sstevel@tonic-gate * will clear the global "super-client" lock. 2129*7c478bd9Sstevel@tonic-gate * XXX - move this outside the per-socket code. 2130*7c478bd9Sstevel@tonic-gate */ 2131*7c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(super_client); 2132*7c478bd9Sstevel@tonic-gate 2133*7c478bd9Sstevel@tonic-gate return (error); 2134*7c478bd9Sstevel@tonic-gate } 2135*7c478bd9Sstevel@tonic-gate 2136*7c478bd9Sstevel@tonic-gate /* 2137*7c478bd9Sstevel@tonic-gate * cs_create_next_client_minor - returns the next available client minor 2138*7c478bd9Sstevel@tonic-gate * number or 0 if none available 2139*7c478bd9Sstevel@tonic-gate * 2140*7c478bd9Sstevel@tonic-gate * Note that cs_find_client will always return a valid pointer to the 2141*7c478bd9Sstevel@tonic-gate * global Socket Services client which has a client minor number 2142*7c478bd9Sstevel@tonic-gate * of 0; this means that this function can never return a 0 as the 2143*7c478bd9Sstevel@tonic-gate * next valid available client minor number. 2144*7c478bd9Sstevel@tonic-gate */ 2145*7c478bd9Sstevel@tonic-gate unsigned 2146*7c478bd9Sstevel@tonic-gate cs_create_next_client_minor(unsigned socket_num, unsigned next_minor) 2147*7c478bd9Sstevel@tonic-gate { 2148*7c478bd9Sstevel@tonic-gate unsigned max_client_handles = cs_max_client_handles; 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate do { 2151*7c478bd9Sstevel@tonic-gate next_minor &= CS_MAX_CLIENTS_MASK; 2152*7c478bd9Sstevel@tonic-gate if (!cs_find_client(MAKE_CLIENT_HANDLE( 2153*7c478bd9Sstevel@tonic-gate CS_GET_SOCKET_NUMBER(socket_num), 2154*7c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 2155*7c478bd9Sstevel@tonic-gate next_minor), NULL)) { 2156*7c478bd9Sstevel@tonic-gate return (next_minor); 2157*7c478bd9Sstevel@tonic-gate } 2158*7c478bd9Sstevel@tonic-gate next_minor++; 2159*7c478bd9Sstevel@tonic-gate } while (max_client_handles--); 2160*7c478bd9Sstevel@tonic-gate 2161*7c478bd9Sstevel@tonic-gate return (0); 2162*7c478bd9Sstevel@tonic-gate } 2163*7c478bd9Sstevel@tonic-gate 2164*7c478bd9Sstevel@tonic-gate /* 2165*7c478bd9Sstevel@tonic-gate * cs_find_client - finds the client pointer associated with the client handle 2166*7c478bd9Sstevel@tonic-gate * or NULL if client not found 2167*7c478bd9Sstevel@tonic-gate * 2168*7c478bd9Sstevel@tonic-gate * returns: (client_t *)NULL - if client not found or an error occured 2169*7c478bd9Sstevel@tonic-gate * If the error argument is not NULL, 2170*7c478bd9Sstevel@tonic-gate * it is set to: 2171*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - socket number in client_handle_t is 2172*7c478bd9Sstevel@tonic-gate * invalid 2173*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client not found 2174*7c478bd9Sstevel@tonic-gate * If no error, the error argument is not modified. 2175*7c478bd9Sstevel@tonic-gate * (client_t *) - pointer to client_t structure 2176*7c478bd9Sstevel@tonic-gate * 2177*7c478bd9Sstevel@tonic-gate * Note that each socket always has a pseudo client with a client minor number 2178*7c478bd9Sstevel@tonic-gate * of 0; this client minor number is used for Socket Services access to 2179*7c478bd9Sstevel@tonic-gate * Card Services functions. The client pointer returned for client minor 2180*7c478bd9Sstevel@tonic-gate * number 0 is the global Socket Services client pointer. 2181*7c478bd9Sstevel@tonic-gate */ 2182*7c478bd9Sstevel@tonic-gate static client_t * 2183*7c478bd9Sstevel@tonic-gate cs_find_client(client_handle_t client_handle, int *error) 2184*7c478bd9Sstevel@tonic-gate { 2185*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 2186*7c478bd9Sstevel@tonic-gate client_t *clp; 2187*7c478bd9Sstevel@tonic-gate 2188*7c478bd9Sstevel@tonic-gate /* 2189*7c478bd9Sstevel@tonic-gate * If we are being asked to see if a client with a minor number 2190*7c478bd9Sstevel@tonic-gate * of 0 exists, always return a pointer to the global Socket 2191*7c478bd9Sstevel@tonic-gate * Services client, since this client always exists, and is 2192*7c478bd9Sstevel@tonic-gate * only for use by Socket Services. There is no socket 2193*7c478bd9Sstevel@tonic-gate * associated with this special client handle. 2194*7c478bd9Sstevel@tonic-gate */ 2195*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 2196*7c478bd9Sstevel@tonic-gate return (&cs_socket_services_client); 2197*7c478bd9Sstevel@tonic-gate 2198*7c478bd9Sstevel@tonic-gate /* 2199*7c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 2200*7c478bd9Sstevel@tonic-gate */ 2201*7c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(GET_CLIENT_SOCKET(client_handle), 2202*7c478bd9Sstevel@tonic-gate cs_globals.max_socket_num))) { 2203*7c478bd9Sstevel@tonic-gate if (error) 2204*7c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 2205*7c478bd9Sstevel@tonic-gate return (NULL); 2206*7c478bd9Sstevel@tonic-gate } 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) { 2209*7c478bd9Sstevel@tonic-gate if (error) 2210*7c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 2211*7c478bd9Sstevel@tonic-gate return (NULL); 2212*7c478bd9Sstevel@tonic-gate } 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate clp = sp->client_list; 2215*7c478bd9Sstevel@tonic-gate 2216*7c478bd9Sstevel@tonic-gate while (clp) { 2217*7c478bd9Sstevel@tonic-gate if (clp->client_handle == client_handle) 2218*7c478bd9Sstevel@tonic-gate return (clp); 2219*7c478bd9Sstevel@tonic-gate clp = clp->next; 2220*7c478bd9Sstevel@tonic-gate } 2221*7c478bd9Sstevel@tonic-gate 2222*7c478bd9Sstevel@tonic-gate if (error) 2223*7c478bd9Sstevel@tonic-gate *error = CS_BAD_HANDLE; 2224*7c478bd9Sstevel@tonic-gate 2225*7c478bd9Sstevel@tonic-gate return (NULL); 2226*7c478bd9Sstevel@tonic-gate } 2227*7c478bd9Sstevel@tonic-gate 2228*7c478bd9Sstevel@tonic-gate /* 2229*7c478bd9Sstevel@tonic-gate * cs_destroy_client_handle - destroys client handle and client structure of 2230*7c478bd9Sstevel@tonic-gate * passed client handle 2231*7c478bd9Sstevel@tonic-gate * 2232*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client handle sucessfully destroyed 2233*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client handle is invalid or if trying 2234*7c478bd9Sstevel@tonic-gate * to destroy global SS client 2235*7c478bd9Sstevel@tonic-gate * {other errors} - other errors from cs_find_client() 2236*7c478bd9Sstevel@tonic-gate */ 2237*7c478bd9Sstevel@tonic-gate static int 2238*7c478bd9Sstevel@tonic-gate cs_destroy_client_handle(client_handle_t client_handle) 2239*7c478bd9Sstevel@tonic-gate { 2240*7c478bd9Sstevel@tonic-gate client_t *clp; 2241*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 2242*7c478bd9Sstevel@tonic-gate int error = CS_BAD_HANDLE; 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate /* 2245*7c478bd9Sstevel@tonic-gate * See if we were passed a valid client handle or if we're being asked 2246*7c478bd9Sstevel@tonic-gate * to destroy the Socket Services client 2247*7c478bd9Sstevel@tonic-gate */ 2248*7c478bd9Sstevel@tonic-gate if ((!(clp = cs_find_client(client_handle, &error))) || 2249*7c478bd9Sstevel@tonic-gate (CLIENT_HANDLE_IS_SS(client_handle))) 2250*7c478bd9Sstevel@tonic-gate return (error); 2251*7c478bd9Sstevel@tonic-gate 2252*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 2253*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2254*7c478bd9Sstevel@tonic-gate 2255*7c478bd9Sstevel@tonic-gate /* 2256*7c478bd9Sstevel@tonic-gate * Recycle this client's minor number. This will most likely 2257*7c478bd9Sstevel@tonic-gate * be the next client minor number we use, but it is also 2258*7c478bd9Sstevel@tonic-gate * a hint to cs_create_client_handle, and that function 2259*7c478bd9Sstevel@tonic-gate * may actually create a new client handle using a minor 2260*7c478bd9Sstevel@tonic-gate * number different that this number. 2261*7c478bd9Sstevel@tonic-gate */ 2262*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2263*7c478bd9Sstevel@tonic-gate sp->next_cl_minor = GET_CLIENT_MINOR(client_handle); 2264*7c478bd9Sstevel@tonic-gate 2265*7c478bd9Sstevel@tonic-gate /* 2266*7c478bd9Sstevel@tonic-gate * See if we're the first or not in the client list; if we're 2267*7c478bd9Sstevel@tonic-gate * not first, then just adjust the client behind us to 2268*7c478bd9Sstevel@tonic-gate * point to the client ahead of us; this could be NULL 2269*7c478bd9Sstevel@tonic-gate * if we're the last client in the list. 2270*7c478bd9Sstevel@tonic-gate */ 2271*7c478bd9Sstevel@tonic-gate if (clp->prev) { 2272*7c478bd9Sstevel@tonic-gate clp->prev->next = clp->next; 2273*7c478bd9Sstevel@tonic-gate } else { 2274*7c478bd9Sstevel@tonic-gate /* 2275*7c478bd9Sstevel@tonic-gate * We are first, so adjust the client list head pointer 2276*7c478bd9Sstevel@tonic-gate * in the socket to point to the client structure that 2277*7c478bd9Sstevel@tonic-gate * follows us; this could turn out to be NULL if we're 2278*7c478bd9Sstevel@tonic-gate * the only client on this socket. 2279*7c478bd9Sstevel@tonic-gate */ 2280*7c478bd9Sstevel@tonic-gate sp->client_list = clp->next; 2281*7c478bd9Sstevel@tonic-gate } 2282*7c478bd9Sstevel@tonic-gate 2283*7c478bd9Sstevel@tonic-gate /* 2284*7c478bd9Sstevel@tonic-gate * If we're not the last client in the list, point the next 2285*7c478bd9Sstevel@tonic-gate * client to the client behind us; this could turn out 2286*7c478bd9Sstevel@tonic-gate * to be NULL if we're the first client on this socket. 2287*7c478bd9Sstevel@tonic-gate */ 2288*7c478bd9Sstevel@tonic-gate if (clp->next) 2289*7c478bd9Sstevel@tonic-gate clp->next->prev = clp->prev; 2290*7c478bd9Sstevel@tonic-gate 2291*7c478bd9Sstevel@tonic-gate sp->num_clients--; 2292*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2293*7c478bd9Sstevel@tonic-gate 2294*7c478bd9Sstevel@tonic-gate /* 2295*7c478bd9Sstevel@tonic-gate * Free this client's memory. 2296*7c478bd9Sstevel@tonic-gate */ 2297*7c478bd9Sstevel@tonic-gate kmem_free(clp, sizeof (client_t)); 2298*7c478bd9Sstevel@tonic-gate 2299*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate /* 2303*7c478bd9Sstevel@tonic-gate * cs_create_client_handle - create a new client handle for the passed 2304*7c478bd9Sstevel@tonic-gate * socket and function number 2305*7c478bd9Sstevel@tonic-gate * 2306*7c478bd9Sstevel@tonic-gate * returns: 0 - if can't create client for some reason 2307*7c478bd9Sstevel@tonic-gate * client_handle_t - new client handle 2308*7c478bd9Sstevel@tonic-gate */ 2309*7c478bd9Sstevel@tonic-gate static client_handle_t 2310*7c478bd9Sstevel@tonic-gate cs_create_client_handle(unsigned socket_num, client_t *cclp) 2311*7c478bd9Sstevel@tonic-gate { 2312*7c478bd9Sstevel@tonic-gate client_t *clp; 2313*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 2314*7c478bd9Sstevel@tonic-gate unsigned next_minor; 2315*7c478bd9Sstevel@tonic-gate client_handle_t client_handle; 2316*7c478bd9Sstevel@tonic-gate 2317*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(socket_num)) == NULL) 2318*7c478bd9Sstevel@tonic-gate return (0); 2319*7c478bd9Sstevel@tonic-gate 2320*7c478bd9Sstevel@tonic-gate /* 2321*7c478bd9Sstevel@tonic-gate * Get the next available minor number that we can use. We use the 2322*7c478bd9Sstevel@tonic-gate * next_cl_minor number as a hint to cs_create_next_client_minor 2323*7c478bd9Sstevel@tonic-gate * and in most cases this will be the minor number we get back. 2324*7c478bd9Sstevel@tonic-gate * If for some reason we can't get a minor number, return an error. 2325*7c478bd9Sstevel@tonic-gate * The only way we could get an error would be if there are 2326*7c478bd9Sstevel@tonic-gate * already the maximum number of clients for this socket. Since 2327*7c478bd9Sstevel@tonic-gate * the maximum number of clients per socket is pretty large, 2328*7c478bd9Sstevel@tonic-gate * this error is unlikely to occur. 2329*7c478bd9Sstevel@tonic-gate */ 2330*7c478bd9Sstevel@tonic-gate if (!(next_minor = 2331*7c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor))) 2332*7c478bd9Sstevel@tonic-gate return (0); 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate /* 2335*7c478bd9Sstevel@tonic-gate * Got a new client minor number, now create a new client handle. 2336*7c478bd9Sstevel@tonic-gate */ 2337*7c478bd9Sstevel@tonic-gate client_handle = MAKE_CLIENT_HANDLE(CS_GET_SOCKET_NUMBER(socket_num), 2338*7c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 2339*7c478bd9Sstevel@tonic-gate next_minor); 2340*7c478bd9Sstevel@tonic-gate 2341*7c478bd9Sstevel@tonic-gate /* 2342*7c478bd9Sstevel@tonic-gate * If this client handle exists, then we have an internal 2343*7c478bd9Sstevel@tonic-gate * error; this should never happen, BTW. This is really 2344*7c478bd9Sstevel@tonic-gate * a double-check on the cs_create_next_client_minor 2345*7c478bd9Sstevel@tonic-gate * function, which also calls cs_find_client. 2346*7c478bd9Sstevel@tonic-gate */ 2347*7c478bd9Sstevel@tonic-gate if (cs_find_client(client_handle, NULL)) { 2348*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2349*7c478bd9Sstevel@tonic-gate "cs_create_client_handle: duplicate client handle 0x%x\n", 2350*7c478bd9Sstevel@tonic-gate (int)client_handle); 2351*7c478bd9Sstevel@tonic-gate return (0); 2352*7c478bd9Sstevel@tonic-gate } 2353*7c478bd9Sstevel@tonic-gate 2354*7c478bd9Sstevel@tonic-gate /* 2355*7c478bd9Sstevel@tonic-gate * If we don't have any clients on this socket yet, create 2356*7c478bd9Sstevel@tonic-gate * a new client and hang it on the socket client list. 2357*7c478bd9Sstevel@tonic-gate */ 2358*7c478bd9Sstevel@tonic-gate if (!sp->client_list) { 2359*7c478bd9Sstevel@tonic-gate sp->client_list = cclp; 2360*7c478bd9Sstevel@tonic-gate clp = sp->client_list; 2361*7c478bd9Sstevel@tonic-gate } else { 2362*7c478bd9Sstevel@tonic-gate /* 2363*7c478bd9Sstevel@tonic-gate * There are other clients on this socket, so look for 2364*7c478bd9Sstevel@tonic-gate * the last client and add our new client after it. 2365*7c478bd9Sstevel@tonic-gate */ 2366*7c478bd9Sstevel@tonic-gate clp = sp->client_list; 2367*7c478bd9Sstevel@tonic-gate while (clp->next) { 2368*7c478bd9Sstevel@tonic-gate clp = clp->next; 2369*7c478bd9Sstevel@tonic-gate } 2370*7c478bd9Sstevel@tonic-gate 2371*7c478bd9Sstevel@tonic-gate clp->next = cclp; 2372*7c478bd9Sstevel@tonic-gate clp->next->prev = clp; 2373*7c478bd9Sstevel@tonic-gate clp = clp->next; 2374*7c478bd9Sstevel@tonic-gate } /* if (!sp->client_list) */ 2375*7c478bd9Sstevel@tonic-gate 2376*7c478bd9Sstevel@tonic-gate /* 2377*7c478bd9Sstevel@tonic-gate * Assign the new client handle to this new client structure. 2378*7c478bd9Sstevel@tonic-gate */ 2379*7c478bd9Sstevel@tonic-gate clp->client_handle = client_handle; 2380*7c478bd9Sstevel@tonic-gate 2381*7c478bd9Sstevel@tonic-gate /* 2382*7c478bd9Sstevel@tonic-gate * Create the next available client minor number for this socket 2383*7c478bd9Sstevel@tonic-gate * and save it away. 2384*7c478bd9Sstevel@tonic-gate */ 2385*7c478bd9Sstevel@tonic-gate sp->next_cl_minor = 2386*7c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor); 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate return (client_handle); 2389*7c478bd9Sstevel@tonic-gate } 2390*7c478bd9Sstevel@tonic-gate 2391*7c478bd9Sstevel@tonic-gate /* 2392*7c478bd9Sstevel@tonic-gate * cs_clear_superclient_lock - clears the global "super-client" lock 2393*7c478bd9Sstevel@tonic-gate * 2394*7c478bd9Sstevel@tonic-gate * Note: this function uses the cs_globals.global_lock so observe proper 2395*7c478bd9Sstevel@tonic-gate * nexting of locks!! 2396*7c478bd9Sstevel@tonic-gate */ 2397*7c478bd9Sstevel@tonic-gate static void 2398*7c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(int super_client) 2399*7c478bd9Sstevel@tonic-gate { 2400*7c478bd9Sstevel@tonic-gate 2401*7c478bd9Sstevel@tonic-gate /* 2402*7c478bd9Sstevel@tonic-gate * If this was a "super-client" registering then we need 2403*7c478bd9Sstevel@tonic-gate * to clear the GLOBAL_SUPER_CLIENT_REGISTERED flag 2404*7c478bd9Sstevel@tonic-gate * so that other "super-clients" can register. 2405*7c478bd9Sstevel@tonic-gate */ 2406*7c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) { 2407*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 2408*7c478bd9Sstevel@tonic-gate cs_globals.flags &= ~GLOBAL_SUPER_CLIENT_REGISTERED; 2409*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 2410*7c478bd9Sstevel@tonic-gate } 2411*7c478bd9Sstevel@tonic-gate } 2412*7c478bd9Sstevel@tonic-gate 2413*7c478bd9Sstevel@tonic-gate /* 2414*7c478bd9Sstevel@tonic-gate * ==== event handling section ==== 2415*7c478bd9Sstevel@tonic-gate */ 2416*7c478bd9Sstevel@tonic-gate 2417*7c478bd9Sstevel@tonic-gate /* 2418*7c478bd9Sstevel@tonic-gate * cs_event - CS event hi-priority callback handler 2419*7c478bd9Sstevel@tonic-gate * 2420*7c478bd9Sstevel@tonic-gate * This function gets called by SS and is passed the event type in 2421*7c478bd9Sstevel@tonic-gate * the "event" argument, and the socket number in the "sn" 2422*7c478bd9Sstevel@tonic-gate * argument. The "sn" argument is a valid logical socket 2423*7c478bd9Sstevel@tonic-gate * number for all events except the PCE_SS_READY event. 2424*7c478bd9Sstevel@tonic-gate * 2425*7c478bd9Sstevel@tonic-gate * The PCE_SS_INIT_STATE, PCE_ADD_SOCKET and PCE_DROP_SOCKET events 2426*7c478bd9Sstevel@tonic-gate * are never called at high priority. These events return 2427*7c478bd9Sstevel@tonic-gate * the following return codes: 2428*7c478bd9Sstevel@tonic-gate * 2429*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - operation sucessful 2430*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to complete operation 2431*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - bad subfunction of 2432*7c478bd9Sstevel@tonic-gate * PCE_SS_INIT_STATE 2433*7c478bd9Sstevel@tonic-gate * 2434*7c478bd9Sstevel@tonic-gate * The caller MUST look at these return codes! 2435*7c478bd9Sstevel@tonic-gate * 2436*7c478bd9Sstevel@tonic-gate * This function is called at high-priority interrupt time for standard 2437*7c478bd9Sstevel@tonic-gate * Card Services events, and the only standard Card Services 2438*7c478bd9Sstevel@tonic-gate * event that it handles directly is the CS_EVENT_CARD_REMOVAL 2439*7c478bd9Sstevel@tonic-gate * event, which gets shuttled right into the client's event 2440*7c478bd9Sstevel@tonic-gate * handler. All other events are just queued up and the socket 2441*7c478bd9Sstevel@tonic-gate * event thread is woken up via the soft interrupt handler. 2442*7c478bd9Sstevel@tonic-gate * Note that CS_EVENT_CARD_INSERTION events are not set in the clients' 2443*7c478bd9Sstevel@tonic-gate * event field, since the CS card insertion/card ready processing 2444*7c478bd9Sstevel@tonic-gate * code is responsible for setting this event in a client's 2445*7c478bd9Sstevel@tonic-gate * event field. 2446*7c478bd9Sstevel@tonic-gate * 2447*7c478bd9Sstevel@tonic-gate */ 2448*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2449*7c478bd9Sstevel@tonic-gate uint32_t 2450*7c478bd9Sstevel@tonic-gate cs_event(event_t event, uint32_t sn, uint32_t arg) 2451*7c478bd9Sstevel@tonic-gate { 2452*7c478bd9Sstevel@tonic-gate client_t *client; 2453*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 2454*7c478bd9Sstevel@tonic-gate client_types_t *ct; 2455*7c478bd9Sstevel@tonic-gate uint32_t ret = CS_SUCCESS; 2456*7c478bd9Sstevel@tonic-gate 2457*7c478bd9Sstevel@tonic-gate /* 2458*7c478bd9Sstevel@tonic-gate * Handle special SS<->CS events 2459*7c478bd9Sstevel@tonic-gate */ 2460*7c478bd9Sstevel@tonic-gate switch (event) { 2461*7c478bd9Sstevel@tonic-gate case PCE_SS_INIT_STATE: 2462*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 2463*7c478bd9Sstevel@tonic-gate switch (sn) { 2464*7c478bd9Sstevel@tonic-gate case PCE_SS_STATE_INIT: 2465*7c478bd9Sstevel@tonic-gate if ((ret = cs_ss_init()) == CS_SUCCESS) 2466*7c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SS_READY; 2467*7c478bd9Sstevel@tonic-gate break; 2468*7c478bd9Sstevel@tonic-gate case PCE_SS_STATE_DEINIT: 2469*7c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SS_READY; 2470*7c478bd9Sstevel@tonic-gate break; 2471*7c478bd9Sstevel@tonic-gate default: 2472*7c478bd9Sstevel@tonic-gate ret = CS_UNSUPPORTED_FUNCTION; 2473*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: PCE_SS_INIT_STATE invalid " 2474*7c478bd9Sstevel@tonic-gate "directive: 0x%x\n", sn); 2475*7c478bd9Sstevel@tonic-gate break; 2476*7c478bd9Sstevel@tonic-gate } /* switch (sn) */ 2477*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 2478*7c478bd9Sstevel@tonic-gate return (ret); 2479*7c478bd9Sstevel@tonic-gate case PCE_ADD_SOCKET: 2480*7c478bd9Sstevel@tonic-gate return (cs_add_socket(sn)); 2481*7c478bd9Sstevel@tonic-gate case PCE_DROP_SOCKET: 2482*7c478bd9Sstevel@tonic-gate return (cs_drop_socket(sn)); 2483*7c478bd9Sstevel@tonic-gate } /* switch (event) */ 2484*7c478bd9Sstevel@tonic-gate 2485*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 2486*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate /* 2489*7c478bd9Sstevel@tonic-gate * Check to see if CS wants to unload - we do this since it's possible 2490*7c478bd9Sstevel@tonic-gate * to disable certain sockets. Do NOT acquire any locks yet. 2491*7c478bd9Sstevel@tonic-gate */ 2492*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_UNLOAD_MODULE) { 2493*7c478bd9Sstevel@tonic-gate if (event == PCE_CARD_INSERT) 2494*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PCMCIA: socket %d disabled - please " 2495*7c478bd9Sstevel@tonic-gate "remove card\n", sn); 2496*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2497*7c478bd9Sstevel@tonic-gate } 2498*7c478bd9Sstevel@tonic-gate 2499*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2500*7c478bd9Sstevel@tonic-gate 2501*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2502*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 2503*7c478bd9Sstevel@tonic-gate event2text_t event2text; 2504*7c478bd9Sstevel@tonic-gate 2505*7c478bd9Sstevel@tonic-gate event2text.event = event; 2506*7c478bd9Sstevel@tonic-gate (void) cs_event2text(&event2text, 0); 2507*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: event=%s (x%x), socket=0x%x\n", 2508*7c478bd9Sstevel@tonic-gate event2text.text, (int)event, (int)sn); 2509*7c478bd9Sstevel@tonic-gate } 2510*7c478bd9Sstevel@tonic-gate #endif 2511*7c478bd9Sstevel@tonic-gate 2512*7c478bd9Sstevel@tonic-gate /* 2513*7c478bd9Sstevel@tonic-gate * Convert SS events to CS events; handle the PRR if necessary. 2514*7c478bd9Sstevel@tonic-gate */ 2515*7c478bd9Sstevel@tonic-gate sp->events |= ss_to_cs_events(sp, event); 2516*7c478bd9Sstevel@tonic-gate 2517*7c478bd9Sstevel@tonic-gate /* 2518*7c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 2519*7c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 2520*7c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 2521*7c478bd9Sstevel@tonic-gate * notified in the correct order of any high-priority 2522*7c478bd9Sstevel@tonic-gate * events. 2523*7c478bd9Sstevel@tonic-gate */ 2524*7c478bd9Sstevel@tonic-gate ct = &client_types[0]; 2525*7c478bd9Sstevel@tonic-gate while (ct) { 2526*7c478bd9Sstevel@tonic-gate /* 2527*7c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 2528*7c478bd9Sstevel@tonic-gate * through each client to set up the client events as well as 2529*7c478bd9Sstevel@tonic-gate * call the client's event handler directly if we have a high 2530*7c478bd9Sstevel@tonic-gate * priority event that we need to tell the client about. 2531*7c478bd9Sstevel@tonic-gate */ 2532*7c478bd9Sstevel@tonic-gate client = sp->client_list; 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 2535*7c478bd9Sstevel@tonic-gate client_t *clp = NULL; 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate while (client) { 2538*7c478bd9Sstevel@tonic-gate clp = client; 2539*7c478bd9Sstevel@tonic-gate client = client->next; 2540*7c478bd9Sstevel@tonic-gate } 2541*7c478bd9Sstevel@tonic-gate client = clp; 2542*7c478bd9Sstevel@tonic-gate } 2543*7c478bd9Sstevel@tonic-gate 2544*7c478bd9Sstevel@tonic-gate while (client) { 2545*7c478bd9Sstevel@tonic-gate client->events |= ((sp->events & ~CS_EVENT_CARD_INSERTION) & 2546*7c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 2547*7c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 2548*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2549*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 2550*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: socket %d client [%s] " 2551*7c478bd9Sstevel@tonic-gate "events 0x%x flags 0x%x\n", 2552*7c478bd9Sstevel@tonic-gate sn, client->driver_name, 2553*7c478bd9Sstevel@tonic-gate (int)client->events, 2554*7c478bd9Sstevel@tonic-gate (int)client->flags); 2555*7c478bd9Sstevel@tonic-gate } 2556*7c478bd9Sstevel@tonic-gate #endif 2557*7c478bd9Sstevel@tonic-gate 2558*7c478bd9Sstevel@tonic-gate /* 2559*7c478bd9Sstevel@tonic-gate * Handle the suspend and card removal events 2560*7c478bd9Sstevel@tonic-gate * specially here so that the client can receive 2561*7c478bd9Sstevel@tonic-gate * these events at high-priority. 2562*7c478bd9Sstevel@tonic-gate */ 2563*7c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_PM_SUSPEND) { 2564*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 2565*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, CS_EVENT_PM_SUSPEND, 2566*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 2567*7c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 2568*7c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_PM_SUSPEND; 2569*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_PM_SUSPEND) */ 2570*7c478bd9Sstevel@tonic-gate 2571*7c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_CARD_REMOVAL) { 2572*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 2573*7c478bd9Sstevel@tonic-gate client->flags &= ~(CLIENT_CARD_INSERTED | 2574*7c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 2575*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 2576*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 2577*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 2578*7c478bd9Sstevel@tonic-gate /* 2579*7c478bd9Sstevel@tonic-gate * Check to see if the client wants low priority 2580*7c478bd9Sstevel@tonic-gate * removal events as well. 2581*7c478bd9Sstevel@tonic-gate */ 2582*7c478bd9Sstevel@tonic-gate if ((client->event_mask | client->global_mask) & 2583*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL_LOWP) { 2584*7c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CARD_REMOVAL_LOWP; 2585*7c478bd9Sstevel@tonic-gate } 2586*7c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 2587*7c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_CARD_REMOVAL; 2588*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2589*7c478bd9Sstevel@tonic-gate 2590*7c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 2591*7c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 2592*7c478bd9Sstevel@tonic-gate client = client->prev; 2593*7c478bd9Sstevel@tonic-gate } else { 2594*7c478bd9Sstevel@tonic-gate client = client->next; 2595*7c478bd9Sstevel@tonic-gate } 2596*7c478bd9Sstevel@tonic-gate } /* while (client) */ 2597*7c478bd9Sstevel@tonic-gate 2598*7c478bd9Sstevel@tonic-gate ct = ct->next; 2599*7c478bd9Sstevel@tonic-gate } /* while (ct) */ 2600*7c478bd9Sstevel@tonic-gate 2601*7c478bd9Sstevel@tonic-gate /* 2602*7c478bd9Sstevel@tonic-gate * Set the SOCKET_NEEDS_THREAD flag so that the soft interrupt 2603*7c478bd9Sstevel@tonic-gate * handler will wakeup this socket's event thread. 2604*7c478bd9Sstevel@tonic-gate */ 2605*7c478bd9Sstevel@tonic-gate if (sp->events) 2606*7c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_NEEDS_THREAD; 2607*7c478bd9Sstevel@tonic-gate 2608*7c478bd9Sstevel@tonic-gate /* 2609*7c478bd9Sstevel@tonic-gate * Fire off a soft interrupt that will cause the socket thread 2610*7c478bd9Sstevel@tonic-gate * to be woken up and any remaining events to be sent to 2611*7c478bd9Sstevel@tonic-gate * the clients on this socket. 2612*7c478bd9Sstevel@tonic-gate */ 2613*7c478bd9Sstevel@tonic-gate if ((sp->init_state & SOCKET_INIT_STATE_SOFTINTR) && 2614*7c478bd9Sstevel@tonic-gate !(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) 2615*7c478bd9Sstevel@tonic-gate ddi_trigger_softintr(sp->softint_id); 2616*7c478bd9Sstevel@tonic-gate 2617*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2618*7c478bd9Sstevel@tonic-gate 2619*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2620*7c478bd9Sstevel@tonic-gate } 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate /* 2623*7c478bd9Sstevel@tonic-gate * cs_card_insertion - handle card insertion and card ready events 2624*7c478bd9Sstevel@tonic-gate * 2625*7c478bd9Sstevel@tonic-gate * We read the CIS, if present, and store it away, then tell SS that 2626*7c478bd9Sstevel@tonic-gate * we have read the CIS and it's ready to be parsed. Since card 2627*7c478bd9Sstevel@tonic-gate * insertion and card ready events are pretty closely intertwined, 2628*7c478bd9Sstevel@tonic-gate * we handle both here. For card ready events that are not the 2629*7c478bd9Sstevel@tonic-gate * result of a card insertion event, we expect that the caller has 2630*7c478bd9Sstevel@tonic-gate * already done the appropriate processing and that we will not be 2631*7c478bd9Sstevel@tonic-gate * called unless we received a card ready event right after a card 2632*7c478bd9Sstevel@tonic-gate * insertion event, i.e. that the SOCKET_WAIT_FOR_READY flag in 2633*7c478bd9Sstevel@tonic-gate * sp->thread_state was set or if we get a CARD_READY event right 2634*7c478bd9Sstevel@tonic-gate * after a CARD_INSERTION event. 2635*7c478bd9Sstevel@tonic-gate * 2636*7c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 2637*7c478bd9Sstevel@tonic-gate * event - event to handle, one of: 2638*7c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_INSERTION 2639*7c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_READY 2640*7c478bd9Sstevel@tonic-gate * CS_EVENT_SS_UPDATED 2641*7c478bd9Sstevel@tonic-gate */ 2642*7c478bd9Sstevel@tonic-gate static int 2643*7c478bd9Sstevel@tonic-gate cs_card_insertion(cs_socket_t *sp, event_t event) 2644*7c478bd9Sstevel@tonic-gate { 2645*7c478bd9Sstevel@tonic-gate int ret; 2646*7c478bd9Sstevel@tonic-gate 2647*7c478bd9Sstevel@tonic-gate /* 2648*7c478bd9Sstevel@tonic-gate * Since we're only called while waiting for the card insertion 2649*7c478bd9Sstevel@tonic-gate * and card ready sequence to occur, we may have a pending 2650*7c478bd9Sstevel@tonic-gate * card ready timer that hasn't gone off yet if we got a 2651*7c478bd9Sstevel@tonic-gate * real card ready event. 2652*7c478bd9Sstevel@tonic-gate */ 2653*7c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 2654*7c478bd9Sstevel@tonic-gate 2655*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2656*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 2657*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: event=0x%x, socket=0x%x\n", 2658*7c478bd9Sstevel@tonic-gate (int)event, sp->socket_num); 2659*7c478bd9Sstevel@tonic-gate } 2660*7c478bd9Sstevel@tonic-gate #endif 2661*7c478bd9Sstevel@tonic-gate 2662*7c478bd9Sstevel@tonic-gate /* 2663*7c478bd9Sstevel@tonic-gate * Handle card insertion processing 2664*7c478bd9Sstevel@tonic-gate */ 2665*7c478bd9Sstevel@tonic-gate if (event & CS_EVENT_CARD_INSERTION) { 2666*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 2667*7c478bd9Sstevel@tonic-gate get_ss_status_t gs; 2668*7c478bd9Sstevel@tonic-gate 2669*7c478bd9Sstevel@tonic-gate /* 2670*7c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 2671*7c478bd9Sstevel@tonic-gate */ 2672*7c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 2673*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2674*7c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d has no " 2675*7c478bd9Sstevel@tonic-gate "CIS window\n", 2676*7c478bd9Sstevel@tonic-gate sp->socket_num); 2677*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 2678*7c478bd9Sstevel@tonic-gate } 2679*7c478bd9Sstevel@tonic-gate 2680*7c478bd9Sstevel@tonic-gate /* 2681*7c478bd9Sstevel@tonic-gate * Apply power to the socket, enable card detect and card ready 2682*7c478bd9Sstevel@tonic-gate * events, then reset the socket. 2683*7c478bd9Sstevel@tonic-gate */ 2684*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2685*7c478bd9Sstevel@tonic-gate sp->event_mask = (CS_EVENT_CARD_REMOVAL | 2686*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY); 2687*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2688*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2689*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = (SBM_CD | SBM_RDYBSY); 2690*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 2691*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 2692*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 2693*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 2694*7c478bd9Sstevel@tonic-gate 2695*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VCC, 2696*7c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 2697*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP1, 2698*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 2699*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP2, 2700*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2703*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2704*7c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failure %d\n", 2705*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 2706*7c478bd9Sstevel@tonic-gate return (ret); 2707*7c478bd9Sstevel@tonic-gate } 2708*7c478bd9Sstevel@tonic-gate 2709*7c478bd9Sstevel@tonic-gate /* 2710*7c478bd9Sstevel@tonic-gate * Clear the ready and ready_timeout events since they are now 2711*7c478bd9Sstevel@tonic-gate * bogus since we're about to reset the socket. 2712*7c478bd9Sstevel@tonic-gate * XXX - should these be cleared right after the RESET?? 2713*7c478bd9Sstevel@tonic-gate */ 2714*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2715*7c478bd9Sstevel@tonic-gate 2716*7c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 2717*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2718*7c478bd9Sstevel@tonic-gate 2719*7c478bd9Sstevel@tonic-gate SocketServices(SS_ResetSocket, sp->socket_num, 2720*7c478bd9Sstevel@tonic-gate RESET_MODE_CARD_ONLY); 2721*7c478bd9Sstevel@tonic-gate 2722*7c478bd9Sstevel@tonic-gate /* 2723*7c478bd9Sstevel@tonic-gate * We are required by the PCMCIA spec to wait some number of 2724*7c478bd9Sstevel@tonic-gate * milliseconds after reset before we access the card, so 2725*7c478bd9Sstevel@tonic-gate * we set up a timer here that will wake us up and allow us 2726*7c478bd9Sstevel@tonic-gate * to continue with our card initialization. 2727*7c478bd9Sstevel@tonic-gate */ 2728*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2729*7c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_RESET_TIMER; 2730*7c478bd9Sstevel@tonic-gate (void) timeout(cs_ready_timeout, sp, 2731*7c478bd9Sstevel@tonic-gate drv_usectohz(cs_reset_timeout_time * 1000)); 2732*7c478bd9Sstevel@tonic-gate cv_wait(&sp->reset_cv, &sp->lock); 2733*7c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_RESET_TIMER; 2734*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2735*7c478bd9Sstevel@tonic-gate 2736*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2737*7c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 2738*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d out of RESET " 2739*7c478bd9Sstevel@tonic-gate "for %d mS sp->events 0x%x\n", 2740*7c478bd9Sstevel@tonic-gate sp->socket_num, cs_reset_timeout_time, (int)sp->events); 2741*7c478bd9Sstevel@tonic-gate } 2742*7c478bd9Sstevel@tonic-gate #endif 2743*7c478bd9Sstevel@tonic-gate 2744*7c478bd9Sstevel@tonic-gate /* 2745*7c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 2746*7c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 2747*7c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 2748*7c478bd9Sstevel@tonic-gate */ 2749*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 2750*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2751*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 2752*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d " 2753*7c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 2754*7c478bd9Sstevel@tonic-gate "terminating insertion " 2755*7c478bd9Sstevel@tonic-gate "processing\n", 2756*7c478bd9Sstevel@tonic-gate sp->socket_num); 2757*7c478bd9Sstevel@tonic-gate } 2758*7c478bd9Sstevel@tonic-gate #endif 2759*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2760*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2761*7c478bd9Sstevel@tonic-gate 2762*7c478bd9Sstevel@tonic-gate /* 2763*7c478bd9Sstevel@tonic-gate * If we got a card ready event after the reset, then don't 2764*7c478bd9Sstevel@tonic-gate * bother setting up a card ready timer, since we'll blast 2765*7c478bd9Sstevel@tonic-gate * right on through to the card ready processing. 2766*7c478bd9Sstevel@tonic-gate * Get the current card status to see if it's ready; if it 2767*7c478bd9Sstevel@tonic-gate * is, we probably won't get a card ready event. 2768*7c478bd9Sstevel@tonic-gate */ 2769*7c478bd9Sstevel@tonic-gate gs.socket = sp->socket_num; 2770*7c478bd9Sstevel@tonic-gate gs.CardState = 0; 2771*7c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_GetStatus, &gs)) != SUCCESS) { 2772*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2773*7c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetStatus failure %d\n", 2774*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 2775*7c478bd9Sstevel@tonic-gate return (ret); 2776*7c478bd9Sstevel@tonic-gate } 2777*7c478bd9Sstevel@tonic-gate 2778*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2779*7c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_READY) || 2780*7c478bd9Sstevel@tonic-gate (gs.CardState & SBM_RDYBSY)) { 2781*7c478bd9Sstevel@tonic-gate event = CS_EVENT_CARD_READY; 2782*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2783*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 2784*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d card " 2785*7c478bd9Sstevel@tonic-gate "READY\n", sp->socket_num); 2786*7c478bd9Sstevel@tonic-gate } 2787*7c478bd9Sstevel@tonic-gate #endif 2788*7c478bd9Sstevel@tonic-gate 2789*7c478bd9Sstevel@tonic-gate } else { 2790*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2791*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 2792*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d setting " 2793*7c478bd9Sstevel@tonic-gate "READY timer\n", sp->socket_num); 2794*7c478bd9Sstevel@tonic-gate } 2795*7c478bd9Sstevel@tonic-gate #endif 2796*7c478bd9Sstevel@tonic-gate 2797*7c478bd9Sstevel@tonic-gate sp->rdybsy_tmo_id = timeout(cs_ready_timeout, sp, 2798*7c478bd9Sstevel@tonic-gate READY_TIMEOUT_TIME); 2799*7c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_FOR_READY; 2800*7c478bd9Sstevel@tonic-gate 2801*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 2802*7c478bd9Sstevel@tonic-gate 2803*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2804*7c478bd9Sstevel@tonic-gate 2805*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 2806*7c478bd9Sstevel@tonic-gate 2807*7c478bd9Sstevel@tonic-gate /* 2808*7c478bd9Sstevel@tonic-gate * Handle card ready processing. This is only card ready processing 2809*7c478bd9Sstevel@tonic-gate * for card ready events in conjunction with a card insertion. 2810*7c478bd9Sstevel@tonic-gate */ 2811*7c478bd9Sstevel@tonic-gate if (event == CS_EVENT_CARD_READY) { 2812*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 2813*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 2814*7c478bd9Sstevel@tonic-gate 2815*7c478bd9Sstevel@tonic-gate /* 2816*7c478bd9Sstevel@tonic-gate * The only events that we want to see now are card removal 2817*7c478bd9Sstevel@tonic-gate * events. 2818*7c478bd9Sstevel@tonic-gate */ 2819*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2820*7c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_REMOVAL; 2821*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2822*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 2823*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 2824*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2825*7c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetSocket failed\n", 2826*7c478bd9Sstevel@tonic-gate sp->socket_num); 2827*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2828*7c478bd9Sstevel@tonic-gate } 2829*7c478bd9Sstevel@tonic-gate 2830*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2831*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 2832*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 2833*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 2834*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 2835*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 2836*7c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 2837*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 2838*7c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) to reset latched values */ 2839*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 2840*7c478bd9Sstevel@tonic-gate 2841*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 2842*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2843*7c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failed\n", 2844*7c478bd9Sstevel@tonic-gate sp->socket_num); 2845*7c478bd9Sstevel@tonic-gate 2846*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 2847*7c478bd9Sstevel@tonic-gate } 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate /* 2850*7c478bd9Sstevel@tonic-gate * Grab the cis_lock mutex to protect the CIS-to-be and 2851*7c478bd9Sstevel@tonic-gate * the CIS window, then fire off the CIS parser to 2852*7c478bd9Sstevel@tonic-gate * create a local copy of the card's CIS. 2853*7c478bd9Sstevel@tonic-gate */ 2854*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2855*7c478bd9Sstevel@tonic-gate 2856*7c478bd9Sstevel@tonic-gate if ((ret = cs_create_cis(sp)) != CS_SUCCESS) { 2857*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2858*7c478bd9Sstevel@tonic-gate return (ret); 2859*7c478bd9Sstevel@tonic-gate } 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2862*7c478bd9Sstevel@tonic-gate 2863*7c478bd9Sstevel@tonic-gate /* 2864*7c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 2865*7c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 2866*7c478bd9Sstevel@tonic-gate * insertion, so destroy the CIS and terminate this 2867*7c478bd9Sstevel@tonic-gate * processing. We'll get called back to handle the 2868*7c478bd9Sstevel@tonic-gate * insertion again later. 2869*7c478bd9Sstevel@tonic-gate */ 2870*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 2871*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2872*7c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 2873*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2874*7c478bd9Sstevel@tonic-gate } else { 2875*7c478bd9Sstevel@tonic-gate /* 2876*7c478bd9Sstevel@tonic-gate * Schedule the call to the Socket Services work thread. 2877*7c478bd9Sstevel@tonic-gate */ 2878*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 2879*7c478bd9Sstevel@tonic-gate sp->ss_thread_state |= SOCKET_THREAD_CSCISInit; 2880*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 2881*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 2882*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 2883*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 2884*7c478bd9Sstevel@tonic-gate 2885*7c478bd9Sstevel@tonic-gate /* 2886*7c478bd9Sstevel@tonic-gate * Socket Services has parsed the CIS and has done any other 2887*7c478bd9Sstevel@tonic-gate * work to get the client driver loaded and attached if 2888*7c478bd9Sstevel@tonic-gate * necessary, so setup the per-client state. 2889*7c478bd9Sstevel@tonic-gate */ 2890*7c478bd9Sstevel@tonic-gate if (event == CS_EVENT_SS_UPDATED) { 2891*7c478bd9Sstevel@tonic-gate client_t *client; 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate /* 2894*7c478bd9Sstevel@tonic-gate * Now that we and SS are done handling the card insertion 2895*7c478bd9Sstevel@tonic-gate * semantics, go through each client on this socket and set 2896*7c478bd9Sstevel@tonic-gate * the CS_EVENT_CARD_INSERTION event in each client's event 2897*7c478bd9Sstevel@tonic-gate * field. We do this here instead of in cs_event so that 2898*7c478bd9Sstevel@tonic-gate * when a client gets a CS_EVENT_CARD_INSERTION event, the 2899*7c478bd9Sstevel@tonic-gate * card insertion and ready processing has already been done 2900*7c478bd9Sstevel@tonic-gate * and SocketServices has had a chance to create a dip for 2901*7c478bd9Sstevel@tonic-gate * the card in this socket. 2902*7c478bd9Sstevel@tonic-gate */ 2903*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2904*7c478bd9Sstevel@tonic-gate client = sp->client_list; 2905*7c478bd9Sstevel@tonic-gate while (client) { 2906*7c478bd9Sstevel@tonic-gate client->events |= (CS_EVENT_CARD_INSERTION & 2907*7c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 2908*7c478bd9Sstevel@tonic-gate client = client->next; 2909*7c478bd9Sstevel@tonic-gate } /* while (client) */ 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2912*7c478bd9Sstevel@tonic-gate 2913*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 2914*7c478bd9Sstevel@tonic-gate 2915*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 2916*7c478bd9Sstevel@tonic-gate } 2917*7c478bd9Sstevel@tonic-gate 2918*7c478bd9Sstevel@tonic-gate /* 2919*7c478bd9Sstevel@tonic-gate * cs_card_removal - handle card removal events 2920*7c478bd9Sstevel@tonic-gate * 2921*7c478bd9Sstevel@tonic-gate * Destroy the CIS. 2922*7c478bd9Sstevel@tonic-gate * 2923*7c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 2924*7c478bd9Sstevel@tonic-gate * 2925*7c478bd9Sstevel@tonic-gate */ 2926*7c478bd9Sstevel@tonic-gate static int 2927*7c478bd9Sstevel@tonic-gate cs_card_removal(cs_socket_t *sp) 2928*7c478bd9Sstevel@tonic-gate { 2929*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 2930*7c478bd9Sstevel@tonic-gate int ret; 2931*7c478bd9Sstevel@tonic-gate 2932*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2933*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 2934*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d\n", sp->socket_num); 2935*7c478bd9Sstevel@tonic-gate } 2936*7c478bd9Sstevel@tonic-gate #endif 2937*7c478bd9Sstevel@tonic-gate 2938*7c478bd9Sstevel@tonic-gate /* 2939*7c478bd9Sstevel@tonic-gate * Remove any pending card ready timer 2940*7c478bd9Sstevel@tonic-gate */ 2941*7c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 2942*7c478bd9Sstevel@tonic-gate 2943*7c478bd9Sstevel@tonic-gate /* 2944*7c478bd9Sstevel@tonic-gate * Clear various flags so that everyone else knows that there's 2945*7c478bd9Sstevel@tonic-gate * nothing on this socket anymore. Note that we clear the 2946*7c478bd9Sstevel@tonic-gate * SOCKET_CARD_INSERTED and SOCKET_IS_IO flags in the 2947*7c478bd9Sstevel@tonic-gate * ss_to_cs_events event mapping function. 2948*7c478bd9Sstevel@tonic-gate */ 2949*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 2950*7c478bd9Sstevel@tonic-gate sp->thread_state &= ~(SOCKET_WAIT_FOR_READY | SOCKET_RESET_TIMER); 2951*7c478bd9Sstevel@tonic-gate 2952*7c478bd9Sstevel@tonic-gate /* 2953*7c478bd9Sstevel@tonic-gate * Turn off socket power and set the socket back to memory mode. 2954*7c478bd9Sstevel@tonic-gate * Disable all socket events except for CARD_INSERTION events. 2955*7c478bd9Sstevel@tonic-gate */ 2956*7c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 2957*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 2958*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 2959*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 2960*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 2961*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 2962*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 2963*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 2964*7c478bd9Sstevel@tonic-gate 2965*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 2966*7c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 2967*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 2968*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 2969*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 2970*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 2971*7c478bd9Sstevel@tonic-gate 2972*7c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 2973*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 2974*7c478bd9Sstevel@tonic-gate "cs_card_removal: socket %d SS_SetSocket failure %d\n", 2975*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 2976*7c478bd9Sstevel@tonic-gate return (ret); 2977*7c478bd9Sstevel@tonic-gate } 2978*7c478bd9Sstevel@tonic-gate 2979*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2980*7c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 2981*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d " 2982*7c478bd9Sstevel@tonic-gate "calling cs_destroy_cis\n", 2983*7c478bd9Sstevel@tonic-gate sp->socket_num); 2984*7c478bd9Sstevel@tonic-gate } 2985*7c478bd9Sstevel@tonic-gate #endif 2986*7c478bd9Sstevel@tonic-gate 2987*7c478bd9Sstevel@tonic-gate /* 2988*7c478bd9Sstevel@tonic-gate * Destroy the CIS and tell Socket Services that we're done 2989*7c478bd9Sstevel@tonic-gate * handling the card removal event. 2990*7c478bd9Sstevel@tonic-gate */ 2991*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 2992*7c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 2993*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 2994*7c478bd9Sstevel@tonic-gate 2995*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2996*7c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 2997*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: calling CSCardRemoved\n"); 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate #endif 3000*7c478bd9Sstevel@tonic-gate 3001*7c478bd9Sstevel@tonic-gate SocketServices(CSCardRemoved, sp->socket_num); 3002*7c478bd9Sstevel@tonic-gate 3003*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3004*7c478bd9Sstevel@tonic-gate } 3005*7c478bd9Sstevel@tonic-gate 3006*7c478bd9Sstevel@tonic-gate /* 3007*7c478bd9Sstevel@tonic-gate * ss_to_cs_events - convert Socket Services events to Card Services event 3008*7c478bd9Sstevel@tonic-gate * masks; this function will not read the PRR if the 3009*7c478bd9Sstevel@tonic-gate * socket is in IO mode; this happens in cs_event_thread 3010*7c478bd9Sstevel@tonic-gate * 3011*7c478bd9Sstevel@tonic-gate * This function returns a bit mask of events. 3012*7c478bd9Sstevel@tonic-gate * 3013*7c478bd9Sstevel@tonic-gate * Note that we do some simple hysterious on card insertion and card removal 3014*7c478bd9Sstevel@tonic-gate * events to prevent spurious insertion and removal events from being 3015*7c478bd9Sstevel@tonic-gate * propogated down the chain. 3016*7c478bd9Sstevel@tonic-gate */ 3017*7c478bd9Sstevel@tonic-gate static event_t 3018*7c478bd9Sstevel@tonic-gate ss_to_cs_events(cs_socket_t *sp, event_t event) 3019*7c478bd9Sstevel@tonic-gate { 3020*7c478bd9Sstevel@tonic-gate event_t revent = 0; 3021*7c478bd9Sstevel@tonic-gate 3022*7c478bd9Sstevel@tonic-gate switch (event) { 3023*7c478bd9Sstevel@tonic-gate case PCE_CARD_STATUS_CHANGE: 3024*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_STATUS_CHANGE; 3025*7c478bd9Sstevel@tonic-gate break; 3026*7c478bd9Sstevel@tonic-gate case PCE_CARD_REMOVAL: 3027*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) { 3028*7c478bd9Sstevel@tonic-gate sp->flags &= ~(SOCKET_CARD_INSERTED | SOCKET_IS_IO); 3029*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_REMOVAL; 3030*7c478bd9Sstevel@tonic-gate /* 3031*7c478bd9Sstevel@tonic-gate * If we're processing a removal event, it makes 3032*7c478bd9Sstevel@tonic-gate * no sense to keep any insertion or ready events, 3033*7c478bd9Sstevel@tonic-gate * so nuke them here. This will not clear any 3034*7c478bd9Sstevel@tonic-gate * insertion events in the per-client event field. 3035*7c478bd9Sstevel@tonic-gate */ 3036*7c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_INSERTION | 3037*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY | 3038*7c478bd9Sstevel@tonic-gate CS_EVENT_READY_TIMEOUT); 3039*7c478bd9Sstevel@tonic-gate 3040*7c478bd9Sstevel@tonic-gate /* 3041*7c478bd9Sstevel@tonic-gate * We also don't need to wait for READY anymore since 3042*7c478bd9Sstevel@tonic-gate * it probably won't show up, or if it does, it will 3043*7c478bd9Sstevel@tonic-gate * be a bogus READY event as the card is sliding out 3044*7c478bd9Sstevel@tonic-gate * of the socket. Since we never do a cv_wait on the 3045*7c478bd9Sstevel@tonic-gate * card ready timer, it's OK for that timer to either 3046*7c478bd9Sstevel@tonic-gate * never go off (via an UNTIMEOUT in cs_card_removal) 3047*7c478bd9Sstevel@tonic-gate * or to go off but not do a cv_broadcast (since the 3048*7c478bd9Sstevel@tonic-gate * SOCKET_WAIT_FOR_READY flag is cleared here). 3049*7c478bd9Sstevel@tonic-gate */ 3050*7c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3051*7c478bd9Sstevel@tonic-gate 3052*7c478bd9Sstevel@tonic-gate } 3053*7c478bd9Sstevel@tonic-gate break; 3054*7c478bd9Sstevel@tonic-gate case PCE_CARD_INSERT: 3055*7c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3056*7c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_CARD_INSERTED; 3057*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_INSERTION; 3058*7c478bd9Sstevel@tonic-gate } 3059*7c478bd9Sstevel@tonic-gate break; 3060*7c478bd9Sstevel@tonic-gate case PCE_CARD_READY: 3061*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3062*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_READY; 3063*7c478bd9Sstevel@tonic-gate break; 3064*7c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_WARN: 3065*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3066*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_LOW; 3067*7c478bd9Sstevel@tonic-gate break; 3068*7c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_DEAD: 3069*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3070*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_DEAD; 3071*7c478bd9Sstevel@tonic-gate break; 3072*7c478bd9Sstevel@tonic-gate case PCE_CARD_WRITE_PROTECT: 3073*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 3074*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_WRITE_PROTECT; 3075*7c478bd9Sstevel@tonic-gate break; 3076*7c478bd9Sstevel@tonic-gate case PCE_PM_RESUME: 3077*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_RESUME; 3078*7c478bd9Sstevel@tonic-gate break; 3079*7c478bd9Sstevel@tonic-gate case PCE_PM_SUSPEND: 3080*7c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_SUSPEND; 3081*7c478bd9Sstevel@tonic-gate break; 3082*7c478bd9Sstevel@tonic-gate default: 3083*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ss_to_cs_events: unknown event 0x%x\n", 3084*7c478bd9Sstevel@tonic-gate (int)event); 3085*7c478bd9Sstevel@tonic-gate break; 3086*7c478bd9Sstevel@tonic-gate } /* switch(event) */ 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate return (revent); 3089*7c478bd9Sstevel@tonic-gate } 3090*7c478bd9Sstevel@tonic-gate 3091*7c478bd9Sstevel@tonic-gate /* 3092*7c478bd9Sstevel@tonic-gate * cs_ready_timeout - general purpose READY/BUSY and RESET timer 3093*7c478bd9Sstevel@tonic-gate * 3094*7c478bd9Sstevel@tonic-gate * Note that we really only expect one of the two events to be asserted when 3095*7c478bd9Sstevel@tonic-gate * we are called. XXX - Perhaps this might be a problem later on?? 3096*7c478bd9Sstevel@tonic-gate * 3097*7c478bd9Sstevel@tonic-gate * There is also the problem of cv_broadcast dropping the interrupt 3098*7c478bd9Sstevel@tonic-gate * priority, even though we have our high-priority mutex held. If 3099*7c478bd9Sstevel@tonic-gate * we hold our high-priority mutex (sp->lock) over a cv_broadcast, and 3100*7c478bd9Sstevel@tonic-gate * we get a high-priority interrupt during this time, the system will 3101*7c478bd9Sstevel@tonic-gate * deadlock or panic. Thanks to Andy Banta for finding this out in 3102*7c478bd9Sstevel@tonic-gate * the SPC/S (stc.c) driver. 3103*7c478bd9Sstevel@tonic-gate * 3104*7c478bd9Sstevel@tonic-gate * This callback routine can not grab the sp->client_lock mutex or deadlock 3105*7c478bd9Sstevel@tonic-gate * will result. 3106*7c478bd9Sstevel@tonic-gate */ 3107*7c478bd9Sstevel@tonic-gate void 3108*7c478bd9Sstevel@tonic-gate cs_ready_timeout(void *arg) 3109*7c478bd9Sstevel@tonic-gate { 3110*7c478bd9Sstevel@tonic-gate cs_socket_t *sp = arg; 3111*7c478bd9Sstevel@tonic-gate kcondvar_t *cvp = NULL; 3112*7c478bd9Sstevel@tonic-gate 3113*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3114*7c478bd9Sstevel@tonic-gate 3115*7c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_RESET_TIMER) { 3116*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3117*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3118*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_RESET_TIMER socket %d\n", 3119*7c478bd9Sstevel@tonic-gate sp->socket_num); 3120*7c478bd9Sstevel@tonic-gate } 3121*7c478bd9Sstevel@tonic-gate #endif 3122*7c478bd9Sstevel@tonic-gate 3123*7c478bd9Sstevel@tonic-gate cvp = &sp->reset_cv; 3124*7c478bd9Sstevel@tonic-gate } 3125*7c478bd9Sstevel@tonic-gate 3126*7c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3127*7c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_READY_TIMEOUT; 3128*7c478bd9Sstevel@tonic-gate cvp = &sp->thread_cv; 3129*7c478bd9Sstevel@tonic-gate 3130*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3131*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3132*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_WAIT_FOR_READY " 3133*7c478bd9Sstevel@tonic-gate "socket %d\n", sp->socket_num); 3134*7c478bd9Sstevel@tonic-gate } 3135*7c478bd9Sstevel@tonic-gate #endif 3136*7c478bd9Sstevel@tonic-gate 3137*7c478bd9Sstevel@tonic-gate } 3138*7c478bd9Sstevel@tonic-gate 3139*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3140*7c478bd9Sstevel@tonic-gate 3141*7c478bd9Sstevel@tonic-gate if (cvp) 3142*7c478bd9Sstevel@tonic-gate cv_broadcast(cvp); 3143*7c478bd9Sstevel@tonic-gate } 3144*7c478bd9Sstevel@tonic-gate 3145*7c478bd9Sstevel@tonic-gate /* 3146*7c478bd9Sstevel@tonic-gate * cs_event_softintr_timeout - wrapper function to call cs_socket_event_softintr 3147*7c478bd9Sstevel@tonic-gate */ 3148*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3149*7c478bd9Sstevel@tonic-gate void 3150*7c478bd9Sstevel@tonic-gate cs_event_softintr_timeout(void *arg) 3151*7c478bd9Sstevel@tonic-gate { 3152*7c478bd9Sstevel@tonic-gate 3153*7c478bd9Sstevel@tonic-gate /* 3154*7c478bd9Sstevel@tonic-gate * If we're trying to unload this module, then don't do 3155*7c478bd9Sstevel@tonic-gate * anything but exit. 3156*7c478bd9Sstevel@tonic-gate * We acquire the cs_globals.global_lock mutex here so that 3157*7c478bd9Sstevel@tonic-gate * we can correctly synchronize with cs_deinit when it 3158*7c478bd9Sstevel@tonic-gate * is telling us to shut down. XXX - is this bogus?? 3159*7c478bd9Sstevel@tonic-gate */ 3160*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3161*7c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) { 3162*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3163*7c478bd9Sstevel@tonic-gate (void) cs_socket_event_softintr(NULL); 3164*7c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 3165*7c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 3166*7c478bd9Sstevel@tonic-gate } else { 3167*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3168*7c478bd9Sstevel@tonic-gate } 3169*7c478bd9Sstevel@tonic-gate } 3170*7c478bd9Sstevel@tonic-gate 3171*7c478bd9Sstevel@tonic-gate /* 3172*7c478bd9Sstevel@tonic-gate * cs_socket_event_softintr - This function just does a cv_broadcast on behalf 3173*7c478bd9Sstevel@tonic-gate * of the high-priority interrupt handler. 3174*7c478bd9Sstevel@tonic-gate * 3175*7c478bd9Sstevel@tonic-gate * Note: There is no calling argument. 3176*7c478bd9Sstevel@tonic-gate */ 3177*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3178*7c478bd9Sstevel@tonic-gate uint32_t 3179*7c478bd9Sstevel@tonic-gate cs_socket_event_softintr(caddr_t notused) 3180*7c478bd9Sstevel@tonic-gate { 3181*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3182*7c478bd9Sstevel@tonic-gate uint32_t sn; 3183*7c478bd9Sstevel@tonic-gate int ret = DDI_INTR_UNCLAIMED; 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate /* 3186*7c478bd9Sstevel@tonic-gate * If the module is on it's way out, then don't bother 3187*7c478bd9Sstevel@tonic-gate * to do anything else except return. 3188*7c478bd9Sstevel@tonic-gate */ 3189*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3190*7c478bd9Sstevel@tonic-gate if ((cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING) || 3191*7c478bd9Sstevel@tonic-gate (cs_globals.init_state & GLOBAL_IN_SOFTINTR)) { 3192*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3193*7c478bd9Sstevel@tonic-gate 3194*7c478bd9Sstevel@tonic-gate /* 3195*7c478bd9Sstevel@tonic-gate * Note that we return DDI_INTR_UNCLAIMED here 3196*7c478bd9Sstevel@tonic-gate * since we don't want to be constantly 3197*7c478bd9Sstevel@tonic-gate * called back. 3198*7c478bd9Sstevel@tonic-gate */ 3199*7c478bd9Sstevel@tonic-gate return (ret); 3200*7c478bd9Sstevel@tonic-gate } else { 3201*7c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_IN_SOFTINTR; 3202*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3203*7c478bd9Sstevel@tonic-gate } 3204*7c478bd9Sstevel@tonic-gate 3205*7c478bd9Sstevel@tonic-gate /* 3206*7c478bd9Sstevel@tonic-gate * Go through each socket and dispatch the appropriate events. 3207*7c478bd9Sstevel@tonic-gate * We have to funnel everything through this one routine because 3208*7c478bd9Sstevel@tonic-gate * we can't do a cv_broadcast from a high level interrupt handler 3209*7c478bd9Sstevel@tonic-gate * and we also can't have more than one soft interrupt handler 3210*7c478bd9Sstevel@tonic-gate * on a single dip and using the same handler address. 3211*7c478bd9Sstevel@tonic-gate */ 3212*7c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3213*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 3214*7c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_READY) { 3215*7c478bd9Sstevel@tonic-gate /* 3216*7c478bd9Sstevel@tonic-gate * If we're being asked to unload CS, then don't bother 3217*7c478bd9Sstevel@tonic-gate * waking up the socket event thread handler. 3218*7c478bd9Sstevel@tonic-gate */ 3219*7c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_UNLOAD_MODULE) && 3220*7c478bd9Sstevel@tonic-gate (sp->flags & SOCKET_NEEDS_THREAD)) { 3221*7c478bd9Sstevel@tonic-gate ret = DDI_INTR_CLAIMED; 3222*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 3223*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3224*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 3225*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_NEEDS_THREAD) */ 3226*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_INIT_STATE_READY) */ 3227*7c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 3228*7c478bd9Sstevel@tonic-gate } /* for (sn) */ 3229*7c478bd9Sstevel@tonic-gate 3230*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3231*7c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_IN_SOFTINTR; 3232*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3233*7c478bd9Sstevel@tonic-gate 3234*7c478bd9Sstevel@tonic-gate return (ret); 3235*7c478bd9Sstevel@tonic-gate } 3236*7c478bd9Sstevel@tonic-gate 3237*7c478bd9Sstevel@tonic-gate /* 3238*7c478bd9Sstevel@tonic-gate * cs_event_thread - This is the per-socket event thread. 3239*7c478bd9Sstevel@tonic-gate */ 3240*7c478bd9Sstevel@tonic-gate static void 3241*7c478bd9Sstevel@tonic-gate cs_event_thread(uint32_t sn) 3242*7c478bd9Sstevel@tonic-gate { 3243*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3244*7c478bd9Sstevel@tonic-gate client_t *client; 3245*7c478bd9Sstevel@tonic-gate client_types_t *ct; 3246*7c478bd9Sstevel@tonic-gate 3247*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 3248*7c478bd9Sstevel@tonic-gate return; 3249*7c478bd9Sstevel@tonic-gate 3250*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3251*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3252*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d thread started\n", 3253*7c478bd9Sstevel@tonic-gate sp->socket_num); 3254*7c478bd9Sstevel@tonic-gate } 3255*7c478bd9Sstevel@tonic-gate #endif 3256*7c478bd9Sstevel@tonic-gate 3257*7c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_cs, &sp->client_lock, 3258*7c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_event_thread"); 3259*7c478bd9Sstevel@tonic-gate 3260*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 3261*7c478bd9Sstevel@tonic-gate 3262*7c478bd9Sstevel@tonic-gate for (;;) { 3263*7c478bd9Sstevel@tonic-gate 3264*7c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_cs); 3265*7c478bd9Sstevel@tonic-gate cv_wait(&sp->thread_cv, &sp->client_lock); 3266*7c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_cs, &sp->client_lock); 3267*7c478bd9Sstevel@tonic-gate 3268*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3269*7c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_NEEDS_THREAD; 3270*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3271*7c478bd9Sstevel@tonic-gate 3272*7c478bd9Sstevel@tonic-gate /* 3273*7c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations that 3274*7c478bd9Sstevel@tonic-gate * we are being asked to perform. 3275*7c478bd9Sstevel@tonic-gate */ 3276*7c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_THREAD_EXIT) { 3277*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3278*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3279*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 3280*7c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 3281*7c478bd9Sstevel@tonic-gate sp->socket_num); 3282*7c478bd9Sstevel@tonic-gate } 3283*7c478bd9Sstevel@tonic-gate #endif 3284*7c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_cs); 3285*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); /* wakes up cs_deinit */ 3286*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 3287*7c478bd9Sstevel@tonic-gate return; 3288*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 3289*7c478bd9Sstevel@tonic-gate 3290*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3291*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3292*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d sp->events 0x%x\n", 3293*7c478bd9Sstevel@tonic-gate sp->socket_num, 3294*7c478bd9Sstevel@tonic-gate (int)sp->events); 3295*7c478bd9Sstevel@tonic-gate } 3296*7c478bd9Sstevel@tonic-gate #endif 3297*7c478bd9Sstevel@tonic-gate 3298*7c478bd9Sstevel@tonic-gate /* 3299*7c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_INSERTION events 3300*7c478bd9Sstevel@tonic-gate */ 3301*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_INSERTION) { 3302*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3303*7c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_INSERTION; 3304*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3305*7c478bd9Sstevel@tonic-gate 3306*7c478bd9Sstevel@tonic-gate /* 3307*7c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 3308*7c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 3309*7c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 3310*7c478bd9Sstevel@tonic-gate */ 3311*7c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_REMOVAL) == 0) { 3312*7c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_INSERTION); 3313*7c478bd9Sstevel@tonic-gate } 3314*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3315*7c478bd9Sstevel@tonic-gate else if (cs_debug > 0) { 3316*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 3317*7c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 3318*7c478bd9Sstevel@tonic-gate "terminating " 3319*7c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_INSERTION " 3320*7c478bd9Sstevel@tonic-gate "processing\n", sp->socket_num); 3321*7c478bd9Sstevel@tonic-gate } 3322*7c478bd9Sstevel@tonic-gate #endif 3323*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 3324*7c478bd9Sstevel@tonic-gate 3325*7c478bd9Sstevel@tonic-gate /* 3326*7c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_READY and CS_EVENT_READY_TIMEOUT events 3327*7c478bd9Sstevel@tonic-gate */ 3328*7c478bd9Sstevel@tonic-gate if (sp->events & (CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT)) { 3329*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3330*7c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 3331*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3332*7c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 3333*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3334*7c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 3335*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3336*7c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_READY); 3337*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_WAIT_FOR_READY) */ 3338*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 3339*7c478bd9Sstevel@tonic-gate 3340*7c478bd9Sstevel@tonic-gate /* 3341*7c478bd9Sstevel@tonic-gate * Handle CS_EVENT_SS_UPDATED events 3342*7c478bd9Sstevel@tonic-gate */ 3343*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_SS_UPDATED) { 3344*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3345*7c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_SS_UPDATED; 3346*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3347*7c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_SS_UPDATED); 3348*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 3349*7c478bd9Sstevel@tonic-gate 3350*7c478bd9Sstevel@tonic-gate /* 3351*7c478bd9Sstevel@tonic-gate * Handle CS_EVENT_STATUS_CHANGE events 3352*7c478bd9Sstevel@tonic-gate */ 3353*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_STATUS_CHANGE) { 3354*7c478bd9Sstevel@tonic-gate event_t revent; 3355*7c478bd9Sstevel@tonic-gate 3356*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 3357*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3358*7c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_STATUS_CHANGE; 3359*7c478bd9Sstevel@tonic-gate 3360*7c478bd9Sstevel@tonic-gate /* 3361*7c478bd9Sstevel@tonic-gate * Go through each client and add any events that we saw to 3362*7c478bd9Sstevel@tonic-gate * the client's event list if the client has that event 3363*7c478bd9Sstevel@tonic-gate * enabled in their event mask. 3364*7c478bd9Sstevel@tonic-gate * Remove any events that may be pending for this client if 3365*7c478bd9Sstevel@tonic-gate * the client's event mask says that the client doesn't 3366*7c478bd9Sstevel@tonic-gate * want to see those events anymore. This handles the 3367*7c478bd9Sstevel@tonic-gate * case where the client had an event enabled in it's 3368*7c478bd9Sstevel@tonic-gate * event mask when the event came in but between that 3369*7c478bd9Sstevel@tonic-gate * time and the time we're called here the client 3370*7c478bd9Sstevel@tonic-gate * disabled that event. 3371*7c478bd9Sstevel@tonic-gate */ 3372*7c478bd9Sstevel@tonic-gate client = sp->client_list; 3373*7c478bd9Sstevel@tonic-gate 3374*7c478bd9Sstevel@tonic-gate while (client) { 3375*7c478bd9Sstevel@tonic-gate /* 3376*7c478bd9Sstevel@tonic-gate * Read the PRR (if it exists) and check for any events. 3377*7c478bd9Sstevel@tonic-gate * The PRR will only be read if the socket is in IO 3378*7c478bd9Sstevel@tonic-gate * mode, if there is a card in the socket, and if there 3379*7c478bd9Sstevel@tonic-gate * is a PRR. 3380*7c478bd9Sstevel@tonic-gate * We don't have to clear revent before we call the 3381*7c478bd9Sstevel@tonic-gate * cs_read_event_status function since it will 3382*7c478bd9Sstevel@tonic-gate * clear it before adding any current events. 3383*7c478bd9Sstevel@tonic-gate */ 3384*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3385*7c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 3386*7c478bd9Sstevel@tonic-gate &revent, NULL, 0); 3387*7c478bd9Sstevel@tonic-gate 3388*7c478bd9Sstevel@tonic-gate client->events = ((client->events | revent) & 3389*7c478bd9Sstevel@tonic-gate (client->event_mask | 3390*7c478bd9Sstevel@tonic-gate client->global_mask)); 3391*7c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 3392*7c478bd9Sstevel@tonic-gate client = client->next; 3393*7c478bd9Sstevel@tonic-gate } /* while (client) */ 3394*7c478bd9Sstevel@tonic-gate 3395*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3396*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 3397*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_STATUS_CHANGE) */ 3398*7c478bd9Sstevel@tonic-gate 3399*7c478bd9Sstevel@tonic-gate /* 3400*7c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 3401*7c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 3402*7c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 3403*7c478bd9Sstevel@tonic-gate * notified in the correct order. 3404*7c478bd9Sstevel@tonic-gate */ 3405*7c478bd9Sstevel@tonic-gate ct = &client_types[0]; 3406*7c478bd9Sstevel@tonic-gate while (ct) { 3407*7c478bd9Sstevel@tonic-gate /* 3408*7c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 3409*7c478bd9Sstevel@tonic-gate * through each client to set up the client events as well 3410*7c478bd9Sstevel@tonic-gate * as call the client's event handler directly if we have 3411*7c478bd9Sstevel@tonic-gate * a high priority event that we need to tell the client 3412*7c478bd9Sstevel@tonic-gate * about. 3413*7c478bd9Sstevel@tonic-gate */ 3414*7c478bd9Sstevel@tonic-gate client = sp->client_list; 3415*7c478bd9Sstevel@tonic-gate 3416*7c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 3417*7c478bd9Sstevel@tonic-gate client_t *clp = NULL; 3418*7c478bd9Sstevel@tonic-gate 3419*7c478bd9Sstevel@tonic-gate while (client) { 3420*7c478bd9Sstevel@tonic-gate clp = client; 3421*7c478bd9Sstevel@tonic-gate client = client->next; 3422*7c478bd9Sstevel@tonic-gate } 3423*7c478bd9Sstevel@tonic-gate client = clp; 3424*7c478bd9Sstevel@tonic-gate } 3425*7c478bd9Sstevel@tonic-gate 3426*7c478bd9Sstevel@tonic-gate while (client) { 3427*7c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 3428*7c478bd9Sstevel@tonic-gate uint32_t bit = 0; 3429*7c478bd9Sstevel@tonic-gate event_t event; 3430*7c478bd9Sstevel@tonic-gate 3431*7c478bd9Sstevel@tonic-gate while (client->events) { 3432*7c478bd9Sstevel@tonic-gate 3433*7c478bd9Sstevel@tonic-gate switch (event = CS_BIT_GET(client->events, bit)) { 3434*7c478bd9Sstevel@tonic-gate /* 3435*7c478bd9Sstevel@tonic-gate * Clients always receive registration complete 3436*7c478bd9Sstevel@tonic-gate * events, even if there is no card of 3437*7c478bd9Sstevel@tonic-gate * their type currently in the socket. 3438*7c478bd9Sstevel@tonic-gate */ 3439*7c478bd9Sstevel@tonic-gate case CS_EVENT_REGISTRATION_COMPLETE: 3440*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3441*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3442*7c478bd9Sstevel@tonic-gate break; 3443*7c478bd9Sstevel@tonic-gate /* 3444*7c478bd9Sstevel@tonic-gate * The client only gets a card insertion event 3445*7c478bd9Sstevel@tonic-gate * if there is currently a card in the 3446*7c478bd9Sstevel@tonic-gate * socket that the client can control. 3447*7c478bd9Sstevel@tonic-gate * The nexus determines this. We also 3448*7c478bd9Sstevel@tonic-gate * prevent the client from receiving 3449*7c478bd9Sstevel@tonic-gate * multiple CS_EVENT_CARD_INSERTION 3450*7c478bd9Sstevel@tonic-gate * events without receiving intervening 3451*7c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL events. 3452*7c478bd9Sstevel@tonic-gate */ 3453*7c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_INSERTION: 3454*7c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) { 3455*7c478bd9Sstevel@tonic-gate int send_insertion; 3456*7c478bd9Sstevel@tonic-gate 3457*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3458*7c478bd9Sstevel@tonic-gate send_insertion = client->flags; 3459*7c478bd9Sstevel@tonic-gate client->flags |= 3460*7c478bd9Sstevel@tonic-gate (CLIENT_CARD_INSERTED | 3461*7c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 3462*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3463*7c478bd9Sstevel@tonic-gate if (!(send_insertion & 3464*7c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION)) { 3465*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 3466*7c478bd9Sstevel@tonic-gate event, CS_EVENT_PRI_LOW); 3467*7c478bd9Sstevel@tonic-gate } /* if (!CLIENT_SENT_INSERTION) */ 3468*7c478bd9Sstevel@tonic-gate } 3469*7c478bd9Sstevel@tonic-gate break; 3470*7c478bd9Sstevel@tonic-gate /* 3471*7c478bd9Sstevel@tonic-gate * The CS_EVENT_CARD_REMOVAL_LOWP is a low 3472*7c478bd9Sstevel@tonic-gate * priority CS_EVENT_CARD_REMOVAL event. 3473*7c478bd9Sstevel@tonic-gate */ 3474*7c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL_LOWP: 3475*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3476*7c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_SENT_INSERTION; 3477*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3478*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 3479*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 3480*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3481*7c478bd9Sstevel@tonic-gate break; 3482*7c478bd9Sstevel@tonic-gate /* 3483*7c478bd9Sstevel@tonic-gate * The hardware card removal events are handed 3484*7c478bd9Sstevel@tonic-gate * to the client in cs_event at high 3485*7c478bd9Sstevel@tonic-gate * priority interrupt time; this card 3486*7c478bd9Sstevel@tonic-gate * removal event is a software-generated 3487*7c478bd9Sstevel@tonic-gate * event. 3488*7c478bd9Sstevel@tonic-gate */ 3489*7c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL: 3490*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3491*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3492*7c478bd9Sstevel@tonic-gate client->flags &= 3493*7c478bd9Sstevel@tonic-gate ~(CLIENT_CARD_INSERTED | 3494*7c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 3495*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3496*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3497*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3498*7c478bd9Sstevel@tonic-gate } 3499*7c478bd9Sstevel@tonic-gate break; 3500*7c478bd9Sstevel@tonic-gate /* 3501*7c478bd9Sstevel@tonic-gate * Write protect events require the info field 3502*7c478bd9Sstevel@tonic-gate * of the client's event callback args to 3503*7c478bd9Sstevel@tonic-gate * be zero if the card is not write 3504*7c478bd9Sstevel@tonic-gate * protected and one if it is. 3505*7c478bd9Sstevel@tonic-gate */ 3506*7c478bd9Sstevel@tonic-gate case CS_EVENT_WRITE_PROTECT: 3507*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3508*7c478bd9Sstevel@tonic-gate get_ss_status_t gs; 3509*7c478bd9Sstevel@tonic-gate 3510*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 3511*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3512*7c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 3513*7c478bd9Sstevel@tonic-gate NULL, 3514*7c478bd9Sstevel@tonic-gate &gs, 0); 3515*7c478bd9Sstevel@tonic-gate if (gs.CardState & SBM_WP) { 3516*7c478bd9Sstevel@tonic-gate client->event_callback_args.info = 3517*7c478bd9Sstevel@tonic-gate (void *) 3518*7c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPON; 3519*7c478bd9Sstevel@tonic-gate } else { 3520*7c478bd9Sstevel@tonic-gate client->event_callback_args.info = 3521*7c478bd9Sstevel@tonic-gate (void *) 3522*7c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPOFF; 3523*7c478bd9Sstevel@tonic-gate } 3524*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3525*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 3526*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3527*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3528*7c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 3529*7c478bd9Sstevel@tonic-gate break; 3530*7c478bd9Sstevel@tonic-gate case CS_EVENT_CLIENT_INFO: 3531*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3532*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3533*7c478bd9Sstevel@tonic-gate break; 3534*7c478bd9Sstevel@tonic-gate case 0: 3535*7c478bd9Sstevel@tonic-gate break; 3536*7c478bd9Sstevel@tonic-gate default: 3537*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 3538*7c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 3539*7c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 3540*7c478bd9Sstevel@tonic-gate } 3541*7c478bd9Sstevel@tonic-gate break; 3542*7c478bd9Sstevel@tonic-gate } /* switch */ 3543*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3544*7c478bd9Sstevel@tonic-gate CS_BIT_CLEAR(client->events, bit); 3545*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3546*7c478bd9Sstevel@tonic-gate bit++; 3547*7c478bd9Sstevel@tonic-gate } /* while (client->events) */ 3548*7c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 3549*7c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 3550*7c478bd9Sstevel@tonic-gate client = client->prev; 3551*7c478bd9Sstevel@tonic-gate } else { 3552*7c478bd9Sstevel@tonic-gate client = client->next; 3553*7c478bd9Sstevel@tonic-gate } 3554*7c478bd9Sstevel@tonic-gate } /* while (client) */ 3555*7c478bd9Sstevel@tonic-gate 3556*7c478bd9Sstevel@tonic-gate ct = ct->next; 3557*7c478bd9Sstevel@tonic-gate } /* while (ct) */ 3558*7c478bd9Sstevel@tonic-gate 3559*7c478bd9Sstevel@tonic-gate /* 3560*7c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_REMOVAL events 3561*7c478bd9Sstevel@tonic-gate */ 3562*7c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 3563*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3564*7c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_REMOVAL; 3565*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3566*7c478bd9Sstevel@tonic-gate (void) cs_card_removal(sp); 3567*7c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 3568*7c478bd9Sstevel@tonic-gate 3569*7c478bd9Sstevel@tonic-gate /* 3570*7c478bd9Sstevel@tonic-gate * If someone is waiting for us to complete, signal them now. 3571*7c478bd9Sstevel@tonic-gate */ 3572*7c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_SYNC) { 3573*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3574*7c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_SYNC; 3575*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3576*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); 3577*7c478bd9Sstevel@tonic-gate } /* SOCKET_WAIT_SYNC */ 3578*7c478bd9Sstevel@tonic-gate 3579*7c478bd9Sstevel@tonic-gate } /* for (;;) */ 3580*7c478bd9Sstevel@tonic-gate } 3581*7c478bd9Sstevel@tonic-gate 3582*7c478bd9Sstevel@tonic-gate /* 3583*7c478bd9Sstevel@tonic-gate * cs_card_for_client - checks to see if a card that the client can control 3584*7c478bd9Sstevel@tonic-gate * is currently inserted in the socket. Socket Services 3585*7c478bd9Sstevel@tonic-gate * has to tell us if this is the case. 3586*7c478bd9Sstevel@tonic-gate */ 3587*7c478bd9Sstevel@tonic-gate static int 3588*7c478bd9Sstevel@tonic-gate cs_card_for_client(client_t *client) 3589*7c478bd9Sstevel@tonic-gate { 3590*7c478bd9Sstevel@tonic-gate 3591*7c478bd9Sstevel@tonic-gate /* 3592*7c478bd9Sstevel@tonic-gate * If the client has set the CS_EVENT_ALL_CLIENTS it means that they 3593*7c478bd9Sstevel@tonic-gate * want to get all events for all clients, irrespective of 3594*7c478bd9Sstevel@tonic-gate * whether or not there is a card in the socket. Such clients 3595*7c478bd9Sstevel@tonic-gate * have to be very careful if they touch the card hardware in 3596*7c478bd9Sstevel@tonic-gate * any way to prevent causing problems for other clients on the 3597*7c478bd9Sstevel@tonic-gate * same socket. This flag will typically only be set by the 3598*7c478bd9Sstevel@tonic-gate * "super-client" or CSI types of clients that wish to get 3599*7c478bd9Sstevel@tonic-gate * information on other clients or cards in the system. 3600*7c478bd9Sstevel@tonic-gate * Note that the CS_EVENT_ALL_CLIENTS must be set in either the 3601*7c478bd9Sstevel@tonic-gate * client's global event mask or client event mask. 3602*7c478bd9Sstevel@tonic-gate * The client must also have registered as a "super-client" or as a 3603*7c478bd9Sstevel@tonic-gate * CSI client for this socket. 3604*7c478bd9Sstevel@tonic-gate */ 3605*7c478bd9Sstevel@tonic-gate if ((client->flags & (CLIENT_SUPER_CLIENT | CLIENT_CSI_CLIENT)) && 3606*7c478bd9Sstevel@tonic-gate ((client->global_mask | client->event_mask) & 3607*7c478bd9Sstevel@tonic-gate CS_EVENT_ALL_CLIENTS)) 3608*7c478bd9Sstevel@tonic-gate return (1); 3609*7c478bd9Sstevel@tonic-gate 3610*7c478bd9Sstevel@tonic-gate /* 3611*7c478bd9Sstevel@tonic-gate * Look for the PCM_DEV_ACTIVE property on this client's dip; if 3612*7c478bd9Sstevel@tonic-gate * it's found, it means that this client can control the card 3613*7c478bd9Sstevel@tonic-gate * that is currently in the socket. This is a boolean 3614*7c478bd9Sstevel@tonic-gate * property managed by Socket Services. 3615*7c478bd9Sstevel@tonic-gate */ 3616*7c478bd9Sstevel@tonic-gate if (ddi_getprop(DDI_DEV_T_ANY, client->dip, (DDI_PROP_CANSLEEP | 3617*7c478bd9Sstevel@tonic-gate DDI_PROP_NOTPROM), 3618*7c478bd9Sstevel@tonic-gate PCM_DEV_ACTIVE, NULL)) { 3619*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3620*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3621*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_for_client: client handle 0x%x " 3622*7c478bd9Sstevel@tonic-gate "driver [%s] says %s found\n", 3623*7c478bd9Sstevel@tonic-gate (int)client->client_handle, 3624*7c478bd9Sstevel@tonic-gate client->driver_name, 3625*7c478bd9Sstevel@tonic-gate PCM_DEV_ACTIVE); 3626*7c478bd9Sstevel@tonic-gate } 3627*7c478bd9Sstevel@tonic-gate #endif 3628*7c478bd9Sstevel@tonic-gate return (1); 3629*7c478bd9Sstevel@tonic-gate } 3630*7c478bd9Sstevel@tonic-gate 3631*7c478bd9Sstevel@tonic-gate return (0); 3632*7c478bd9Sstevel@tonic-gate } 3633*7c478bd9Sstevel@tonic-gate 3634*7c478bd9Sstevel@tonic-gate /* 3635*7c478bd9Sstevel@tonic-gate * cs_ss_thread - This is the Socket Services work thread. We fire off 3636*7c478bd9Sstevel@tonic-gate * any calls to Socket Services here that we want 3637*7c478bd9Sstevel@tonic-gate * to run on a thread that is seperate from the 3638*7c478bd9Sstevel@tonic-gate * per-socket event thread. 3639*7c478bd9Sstevel@tonic-gate */ 3640*7c478bd9Sstevel@tonic-gate static void 3641*7c478bd9Sstevel@tonic-gate cs_ss_thread(uint32_t sn) 3642*7c478bd9Sstevel@tonic-gate { 3643*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3644*7c478bd9Sstevel@tonic-gate 3645*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 3646*7c478bd9Sstevel@tonic-gate return; 3647*7c478bd9Sstevel@tonic-gate 3648*7c478bd9Sstevel@tonic-gate /* 3649*7c478bd9Sstevel@tonic-gate * Tell CPR that we've started a new thread. 3650*7c478bd9Sstevel@tonic-gate */ 3651*7c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_ss, &sp->ss_thread_lock, 3652*7c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_ss_thread"); 3653*7c478bd9Sstevel@tonic-gate 3654*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 3655*7c478bd9Sstevel@tonic-gate 3656*7c478bd9Sstevel@tonic-gate for (;;) { 3657*7c478bd9Sstevel@tonic-gate 3658*7c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_ss); 3659*7c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_thread_cv, &sp->ss_thread_lock); 3660*7c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_ss, &sp->ss_thread_lock); 3661*7c478bd9Sstevel@tonic-gate 3662*7c478bd9Sstevel@tonic-gate /* 3663*7c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations 3664*7c478bd9Sstevel@tonic-gate * that we are being asked to perform. 3665*7c478bd9Sstevel@tonic-gate */ 3666*7c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_EXIT) { 3667*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3668*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3669*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3670*7c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 3671*7c478bd9Sstevel@tonic-gate sp->socket_num); 3672*7c478bd9Sstevel@tonic-gate } 3673*7c478bd9Sstevel@tonic-gate #endif 3674*7c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_ss); 3675*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_caller_cv); /* wake up cs_deinit */ 3676*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 3677*7c478bd9Sstevel@tonic-gate return; 3678*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 3679*7c478bd9Sstevel@tonic-gate 3680*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3681*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3682*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 3683*7c478bd9Sstevel@tonic-gate "ss_thread_state = 0x%x\n", 3684*7c478bd9Sstevel@tonic-gate (int)sp->socket_num, 3685*7c478bd9Sstevel@tonic-gate (int)sp->ss_thread_state); 3686*7c478bd9Sstevel@tonic-gate } 3687*7c478bd9Sstevel@tonic-gate #endif 3688*7c478bd9Sstevel@tonic-gate 3689*7c478bd9Sstevel@tonic-gate /* 3690*7c478bd9Sstevel@tonic-gate * Call SocketServices(CSCISInit) to have SS parse the 3691*7c478bd9Sstevel@tonic-gate * CIS and load/attach any client drivers necessary. 3692*7c478bd9Sstevel@tonic-gate */ 3693*7c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_CSCISInit) { 3694*7c478bd9Sstevel@tonic-gate 3695*7c478bd9Sstevel@tonic-gate sp->ss_thread_state &= ~SOCKET_THREAD_CSCISInit; 3696*7c478bd9Sstevel@tonic-gate 3697*7c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 3698*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread %d " 3699*7c478bd9Sstevel@tonic-gate "card NOT inserted\n", 3700*7c478bd9Sstevel@tonic-gate sp->socket_num); 3701*7c478bd9Sstevel@tonic-gate } 3702*7c478bd9Sstevel@tonic-gate 3703*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3704*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3705*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d calling " 3706*7c478bd9Sstevel@tonic-gate "CSCISInit\n", sp->socket_num); 3707*7c478bd9Sstevel@tonic-gate } 3708*7c478bd9Sstevel@tonic-gate #endif 3709*7c478bd9Sstevel@tonic-gate 3710*7c478bd9Sstevel@tonic-gate /* 3711*7c478bd9Sstevel@tonic-gate * Tell SS that we have a complete CIS and that it can now 3712*7c478bd9Sstevel@tonic-gate * be parsed. 3713*7c478bd9Sstevel@tonic-gate * Note that in some cases the client driver may block in 3714*7c478bd9Sstevel@tonic-gate * their attach routine, causing this call to block until 3715*7c478bd9Sstevel@tonic-gate * the client completes their attach. 3716*7c478bd9Sstevel@tonic-gate */ 3717*7c478bd9Sstevel@tonic-gate SocketServices(CSCISInit, sp->socket_num); 3718*7c478bd9Sstevel@tonic-gate 3719*7c478bd9Sstevel@tonic-gate /* 3720*7c478bd9Sstevel@tonic-gate * Set the CS_EVENT_SS_UPDATED event for this socket so that the 3721*7c478bd9Sstevel@tonic-gate * event thread can continue any card insertion processing 3722*7c478bd9Sstevel@tonic-gate * that it has to do. 3723*7c478bd9Sstevel@tonic-gate */ 3724*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3725*7c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_SS_UPDATED; 3726*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3727*7c478bd9Sstevel@tonic-gate 3728*7c478bd9Sstevel@tonic-gate /* 3729*7c478bd9Sstevel@tonic-gate * Wake up this socket's event thread so that clients can 3730*7c478bd9Sstevel@tonic-gate * continue any card insertion or attach processing 3731*7c478bd9Sstevel@tonic-gate * that they need to do. 3732*7c478bd9Sstevel@tonic-gate */ 3733*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3734*7c478bd9Sstevel@tonic-gate } /* if ST_CSCISInit */ 3735*7c478bd9Sstevel@tonic-gate 3736*7c478bd9Sstevel@tonic-gate } /* for (;;) */ 3737*7c478bd9Sstevel@tonic-gate } 3738*7c478bd9Sstevel@tonic-gate 3739*7c478bd9Sstevel@tonic-gate /* 3740*7c478bd9Sstevel@tonic-gate * cs_request_socket_mask - set the client's event mask as well as causes 3741*7c478bd9Sstevel@tonic-gate * any events pending from RegisterClient to 3742*7c478bd9Sstevel@tonic-gate * be scheduled to be sent to the client 3743*7c478bd9Sstevel@tonic-gate */ 3744*7c478bd9Sstevel@tonic-gate static int 3745*7c478bd9Sstevel@tonic-gate cs_request_socket_mask(client_handle_t client_handle, 3746*7c478bd9Sstevel@tonic-gate request_socket_mask_t *se) 3747*7c478bd9Sstevel@tonic-gate { 3748*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3749*7c478bd9Sstevel@tonic-gate client_t *client; 3750*7c478bd9Sstevel@tonic-gate int error; 3751*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 3752*7c478bd9Sstevel@tonic-gate 3753*7c478bd9Sstevel@tonic-gate /* 3754*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3755*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 3756*7c478bd9Sstevel@tonic-gate */ 3757*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3758*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3759*7c478bd9Sstevel@tonic-gate 3760*7c478bd9Sstevel@tonic-gate /* 3761*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3762*7c478bd9Sstevel@tonic-gate */ 3763*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3764*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 3765*7c478bd9Sstevel@tonic-gate 3766*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3767*7c478bd9Sstevel@tonic-gate 3768*7c478bd9Sstevel@tonic-gate /* 3769*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 3770*7c478bd9Sstevel@tonic-gate */ 3771*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3772*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3773*7c478bd9Sstevel@tonic-gate return (error); 3774*7c478bd9Sstevel@tonic-gate } 3775*7c478bd9Sstevel@tonic-gate 3776*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3777*7c478bd9Sstevel@tonic-gate 3778*7c478bd9Sstevel@tonic-gate /* 3779*7c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 3780*7c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 3781*7c478bd9Sstevel@tonic-gate */ 3782*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_SOCKET_MASK_DONE) { 3783*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3784*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3785*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 3786*7c478bd9Sstevel@tonic-gate } 3787*7c478bd9Sstevel@tonic-gate 3788*7c478bd9Sstevel@tonic-gate /* 3789*7c478bd9Sstevel@tonic-gate * Set up the event mask information; we copy this directly from 3790*7c478bd9Sstevel@tonic-gate * the client; since we are the only source of events, any 3791*7c478bd9Sstevel@tonic-gate * bogus bits that the client puts in here won't matter 3792*7c478bd9Sstevel@tonic-gate * because we'll never look at them. 3793*7c478bd9Sstevel@tonic-gate */ 3794*7c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 3795*7c478bd9Sstevel@tonic-gate 3796*7c478bd9Sstevel@tonic-gate /* 3797*7c478bd9Sstevel@tonic-gate * If RegisterClient left us some events to process, set these 3798*7c478bd9Sstevel@tonic-gate * events up here. 3799*7c478bd9Sstevel@tonic-gate */ 3800*7c478bd9Sstevel@tonic-gate if (client->pending_events) { 3801*7c478bd9Sstevel@tonic-gate client->events |= client->pending_events; 3802*7c478bd9Sstevel@tonic-gate client->pending_events = 0; 3803*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3804*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3805*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: client_handle = 0x%x " 3806*7c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 3807*7c478bd9Sstevel@tonic-gate (int)client->client_handle, 3808*7c478bd9Sstevel@tonic-gate client->driver_name, 3809*7c478bd9Sstevel@tonic-gate (int)client->events); 3810*7c478bd9Sstevel@tonic-gate } 3811*7c478bd9Sstevel@tonic-gate #endif 3812*7c478bd9Sstevel@tonic-gate } 3813*7c478bd9Sstevel@tonic-gate 3814*7c478bd9Sstevel@tonic-gate client->flags |= REQ_SOCKET_MASK_DONE; 3815*7c478bd9Sstevel@tonic-gate 3816*7c478bd9Sstevel@tonic-gate /* 3817*7c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 3818*7c478bd9Sstevel@tonic-gate * to generate the appropriate events. 3819*7c478bd9Sstevel@tonic-gate */ 3820*7c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3821*7c478bd9Sstevel@tonic-gate 3822*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3823*7c478bd9Sstevel@tonic-gate 3824*7c478bd9Sstevel@tonic-gate /* 3825*7c478bd9Sstevel@tonic-gate * Wakeup the event thread if there are any client events to process. 3826*7c478bd9Sstevel@tonic-gate */ 3827*7c478bd9Sstevel@tonic-gate if (client->events) { 3828*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 3829*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 3830*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 3831*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: did cv_broadcast for " 3832*7c478bd9Sstevel@tonic-gate "client_handle = 0x%x " 3833*7c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 3834*7c478bd9Sstevel@tonic-gate (int)client->client_handle, 3835*7c478bd9Sstevel@tonic-gate client->driver_name, 3836*7c478bd9Sstevel@tonic-gate (int)client->events); 3837*7c478bd9Sstevel@tonic-gate } 3838*7c478bd9Sstevel@tonic-gate #endif 3839*7c478bd9Sstevel@tonic-gate 3840*7c478bd9Sstevel@tonic-gate } 3841*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3842*7c478bd9Sstevel@tonic-gate 3843*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3844*7c478bd9Sstevel@tonic-gate } 3845*7c478bd9Sstevel@tonic-gate 3846*7c478bd9Sstevel@tonic-gate /* 3847*7c478bd9Sstevel@tonic-gate * cs_release_socket_mask - clear the client's event mask 3848*7c478bd9Sstevel@tonic-gate * 3849*7c478bd9Sstevel@tonic-gate * Once this function returns, the client is guaranteed 3850*7c478bd9Sstevel@tonic-gate * not to get any more event callbacks. 3851*7c478bd9Sstevel@tonic-gate */ 3852*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3853*7c478bd9Sstevel@tonic-gate static int 3854*7c478bd9Sstevel@tonic-gate cs_release_socket_mask(client_handle_t client_handle, 3855*7c478bd9Sstevel@tonic-gate release_socket_mask_t *rsm) 3856*7c478bd9Sstevel@tonic-gate { 3857*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3858*7c478bd9Sstevel@tonic-gate client_t *client; 3859*7c478bd9Sstevel@tonic-gate int error; 3860*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 3861*7c478bd9Sstevel@tonic-gate 3862*7c478bd9Sstevel@tonic-gate /* 3863*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3864*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 3865*7c478bd9Sstevel@tonic-gate */ 3866*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3867*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3868*7c478bd9Sstevel@tonic-gate 3869*7c478bd9Sstevel@tonic-gate /* 3870*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3871*7c478bd9Sstevel@tonic-gate */ 3872*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3873*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 3874*7c478bd9Sstevel@tonic-gate 3875*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3876*7c478bd9Sstevel@tonic-gate 3877*7c478bd9Sstevel@tonic-gate /* 3878*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 3879*7c478bd9Sstevel@tonic-gate */ 3880*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3881*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3882*7c478bd9Sstevel@tonic-gate return (error); 3883*7c478bd9Sstevel@tonic-gate } 3884*7c478bd9Sstevel@tonic-gate 3885*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3886*7c478bd9Sstevel@tonic-gate 3887*7c478bd9Sstevel@tonic-gate /* 3888*7c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 3889*7c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 3890*7c478bd9Sstevel@tonic-gate */ 3891*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3892*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3893*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3894*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 3895*7c478bd9Sstevel@tonic-gate } 3896*7c478bd9Sstevel@tonic-gate 3897*7c478bd9Sstevel@tonic-gate /* 3898*7c478bd9Sstevel@tonic-gate * Clear both the client event mask and the global event mask. 3899*7c478bd9Sstevel@tonic-gate * We clear both since the semantics of this function are 3900*7c478bd9Sstevel@tonic-gate * that once it returns, the client will not be called at 3901*7c478bd9Sstevel@tonic-gate * it's event handler for any events until RequestSocketMask 3902*7c478bd9Sstevel@tonic-gate * is called again. 3903*7c478bd9Sstevel@tonic-gate */ 3904*7c478bd9Sstevel@tonic-gate client->event_mask = 0; 3905*7c478bd9Sstevel@tonic-gate client->global_mask = 0; 3906*7c478bd9Sstevel@tonic-gate client->flags &= ~REQ_SOCKET_MASK_DONE; 3907*7c478bd9Sstevel@tonic-gate 3908*7c478bd9Sstevel@tonic-gate /* 3909*7c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 3910*7c478bd9Sstevel@tonic-gate * to generate the appropriate events. 3911*7c478bd9Sstevel@tonic-gate */ 3912*7c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 3913*7c478bd9Sstevel@tonic-gate 3914*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3915*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3916*7c478bd9Sstevel@tonic-gate 3917*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3918*7c478bd9Sstevel@tonic-gate } 3919*7c478bd9Sstevel@tonic-gate 3920*7c478bd9Sstevel@tonic-gate /* 3921*7c478bd9Sstevel@tonic-gate * cs_get_event_mask - return the event mask for this client 3922*7c478bd9Sstevel@tonic-gate */ 3923*7c478bd9Sstevel@tonic-gate static int 3924*7c478bd9Sstevel@tonic-gate cs_get_event_mask(client_handle_t client_handle, sockevent_t *se) 3925*7c478bd9Sstevel@tonic-gate { 3926*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3927*7c478bd9Sstevel@tonic-gate client_t *client; 3928*7c478bd9Sstevel@tonic-gate int error; 3929*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 3930*7c478bd9Sstevel@tonic-gate 3931*7c478bd9Sstevel@tonic-gate /* 3932*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 3933*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 3934*7c478bd9Sstevel@tonic-gate */ 3935*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 3936*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3937*7c478bd9Sstevel@tonic-gate 3938*7c478bd9Sstevel@tonic-gate /* 3939*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 3940*7c478bd9Sstevel@tonic-gate */ 3941*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 3942*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 3943*7c478bd9Sstevel@tonic-gate 3944*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 3945*7c478bd9Sstevel@tonic-gate 3946*7c478bd9Sstevel@tonic-gate /* 3947*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 3948*7c478bd9Sstevel@tonic-gate */ 3949*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 3950*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3951*7c478bd9Sstevel@tonic-gate return (error); 3952*7c478bd9Sstevel@tonic-gate } 3953*7c478bd9Sstevel@tonic-gate 3954*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 3955*7c478bd9Sstevel@tonic-gate 3956*7c478bd9Sstevel@tonic-gate #ifdef XXX 3957*7c478bd9Sstevel@tonic-gate /* 3958*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 3959*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 3960*7c478bd9Sstevel@tonic-gate * XXX - how can a client get their event masks if their card 3961*7c478bd9Sstevel@tonic-gate * goes away? 3962*7c478bd9Sstevel@tonic-gate */ 3963*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 3964*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3965*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3966*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 3967*7c478bd9Sstevel@tonic-gate } 3968*7c478bd9Sstevel@tonic-gate #endif 3969*7c478bd9Sstevel@tonic-gate 3970*7c478bd9Sstevel@tonic-gate /* 3971*7c478bd9Sstevel@tonic-gate * We are only allowed to get the client event mask if a 3972*7c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 3973*7c478bd9Sstevel@tonic-gate * are allowed to get the global event mask at any 3974*7c478bd9Sstevel@tonic-gate * time. 3975*7c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 3976*7c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 3977*7c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 3978*7c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 3979*7c478bd9Sstevel@tonic-gate * GetEventMask. 3980*7c478bd9Sstevel@tonic-gate */ 3981*7c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 3982*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 3983*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3984*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3985*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 3986*7c478bd9Sstevel@tonic-gate } 3987*7c478bd9Sstevel@tonic-gate se->EventMask = client->event_mask; 3988*7c478bd9Sstevel@tonic-gate } else { 3989*7c478bd9Sstevel@tonic-gate se->EventMask = client->global_mask; 3990*7c478bd9Sstevel@tonic-gate } 3991*7c478bd9Sstevel@tonic-gate 3992*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 3993*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 3994*7c478bd9Sstevel@tonic-gate 3995*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3996*7c478bd9Sstevel@tonic-gate } 3997*7c478bd9Sstevel@tonic-gate 3998*7c478bd9Sstevel@tonic-gate /* 3999*7c478bd9Sstevel@tonic-gate * cs_set_event_mask - set the event mask for this client 4000*7c478bd9Sstevel@tonic-gate */ 4001*7c478bd9Sstevel@tonic-gate static int 4002*7c478bd9Sstevel@tonic-gate cs_set_event_mask(client_handle_t client_handle, sockevent_t *se) 4003*7c478bd9Sstevel@tonic-gate { 4004*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 4005*7c478bd9Sstevel@tonic-gate client_t *client; 4006*7c478bd9Sstevel@tonic-gate int error; 4007*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 4008*7c478bd9Sstevel@tonic-gate 4009*7c478bd9Sstevel@tonic-gate /* 4010*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4011*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 4012*7c478bd9Sstevel@tonic-gate */ 4013*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4014*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4015*7c478bd9Sstevel@tonic-gate 4016*7c478bd9Sstevel@tonic-gate /* 4017*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4018*7c478bd9Sstevel@tonic-gate */ 4019*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4020*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4021*7c478bd9Sstevel@tonic-gate 4022*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4023*7c478bd9Sstevel@tonic-gate 4024*7c478bd9Sstevel@tonic-gate /* 4025*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 4026*7c478bd9Sstevel@tonic-gate */ 4027*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4028*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4029*7c478bd9Sstevel@tonic-gate return (error); 4030*7c478bd9Sstevel@tonic-gate } 4031*7c478bd9Sstevel@tonic-gate 4032*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 4033*7c478bd9Sstevel@tonic-gate 4034*7c478bd9Sstevel@tonic-gate #ifdef XXX 4035*7c478bd9Sstevel@tonic-gate /* 4036*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4037*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 4038*7c478bd9Sstevel@tonic-gate */ 4039*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4040*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4041*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4042*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 4043*7c478bd9Sstevel@tonic-gate } 4044*7c478bd9Sstevel@tonic-gate #endif 4045*7c478bd9Sstevel@tonic-gate 4046*7c478bd9Sstevel@tonic-gate /* 4047*7c478bd9Sstevel@tonic-gate * We are only allowed to set the client event mask if a 4048*7c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 4049*7c478bd9Sstevel@tonic-gate * are allowed to set the global event mask at any 4050*7c478bd9Sstevel@tonic-gate * time. 4051*7c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 4052*7c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 4053*7c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 4054*7c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 4055*7c478bd9Sstevel@tonic-gate * GetEventMask. 4056*7c478bd9Sstevel@tonic-gate */ 4057*7c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 4058*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 4059*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4060*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4061*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4062*7c478bd9Sstevel@tonic-gate } 4063*7c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 4064*7c478bd9Sstevel@tonic-gate } else { 4065*7c478bd9Sstevel@tonic-gate client->global_mask = se->EventMask; 4066*7c478bd9Sstevel@tonic-gate } 4067*7c478bd9Sstevel@tonic-gate 4068*7c478bd9Sstevel@tonic-gate /* 4069*7c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 4070*7c478bd9Sstevel@tonic-gate * to generate the appropriate events. 4071*7c478bd9Sstevel@tonic-gate */ 4072*7c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 4073*7c478bd9Sstevel@tonic-gate 4074*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4075*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4076*7c478bd9Sstevel@tonic-gate 4077*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4078*7c478bd9Sstevel@tonic-gate } 4079*7c478bd9Sstevel@tonic-gate 4080*7c478bd9Sstevel@tonic-gate /* 4081*7c478bd9Sstevel@tonic-gate * cs_read_event_status - handles PRR events and returns card status 4082*7c478bd9Sstevel@tonic-gate * 4083*7c478bd9Sstevel@tonic-gate * calling: *sp - socket struct point 4084*7c478bd9Sstevel@tonic-gate * *client - client to check events on 4085*7c478bd9Sstevel@tonic-gate * *revent - pointer to event mask to update; if NULL, will 4086*7c478bd9Sstevel@tonic-gate * not be updated, if non-NULL, will be updated 4087*7c478bd9Sstevel@tonic-gate * with CS-format events; it is NOT necessary 4088*7c478bd9Sstevel@tonic-gate * to clear this value before calling this 4089*7c478bd9Sstevel@tonic-gate * function 4090*7c478bd9Sstevel@tonic-gate * *gs - pointer to a get_ss_status_t used for the SS GetStatus 4091*7c478bd9Sstevel@tonic-gate * call; it is not necessary to initialize any 4092*7c478bd9Sstevel@tonic-gate * members in this structure; set to NULL if 4093*7c478bd9Sstevel@tonic-gate * not used 4094*7c478bd9Sstevel@tonic-gate * flags - if CS_RES_IGNORE_NO_CARD is set, the check for a 4095*7c478bd9Sstevel@tonic-gate * card present will not be done 4096*7c478bd9Sstevel@tonic-gate * 4097*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 4098*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in the socket and the flags arg 4099*7c478bd9Sstevel@tonic-gate * is not set to CS_RES_IGNORE_NO_CARD 4100*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if the SS_GetStatus function returned an 4101*7c478bd9Sstevel@tonic-gate * error 4102*7c478bd9Sstevel@tonic-gate * 4103*7c478bd9Sstevel@tonic-gate * Note that if the client that configured this socket has told us that 4104*7c478bd9Sstevel@tonic-gate * the READY pin in the PRR isn't valid and the socket is in IO 4105*7c478bd9Sstevel@tonic-gate * mode, we always return that the card is READY. 4106*7c478bd9Sstevel@tonic-gate * 4107*7c478bd9Sstevel@tonic-gate * Note that if gs is not NULL, the current card state will be returned 4108*7c478bd9Sstevel@tonic-gate * in the gs->CardState member; this will always reflect the 4109*7c478bd9Sstevel@tonic-gate * current card state and the state will come from both the 4110*7c478bd9Sstevel@tonic-gate * SS_GetStatus call and the PRR, whichever is appropriate for 4111*7c478bd9Sstevel@tonic-gate * the mode that the socket is currently in. 4112*7c478bd9Sstevel@tonic-gate */ 4113*7c478bd9Sstevel@tonic-gate static int 4114*7c478bd9Sstevel@tonic-gate cs_read_event_status(cs_socket_t *sp, client_t *client, event_t *revent, 4115*7c478bd9Sstevel@tonic-gate get_ss_status_t *gs, int flags) 4116*7c478bd9Sstevel@tonic-gate { 4117*7c478bd9Sstevel@tonic-gate cfg_regs_t prrd = 0; 4118*7c478bd9Sstevel@tonic-gate 4119*7c478bd9Sstevel@tonic-gate /* 4120*7c478bd9Sstevel@tonic-gate * SOCKET_IS_IO will only be set if a RequestConfiguration 4121*7c478bd9Sstevel@tonic-gate * has been done by at least one client on this socket. 4122*7c478bd9Sstevel@tonic-gate * If there isn't a card in the socket or the caller wants to ignore 4123*7c478bd9Sstevel@tonic-gate * whether the card is in the socket or not, get the current 4124*7c478bd9Sstevel@tonic-gate * card status. 4125*7c478bd9Sstevel@tonic-gate */ 4126*7c478bd9Sstevel@tonic-gate if ((sp->flags & SOCKET_CARD_INSERTED) || 4127*7c478bd9Sstevel@tonic-gate (flags & CS_RES_IGNORE_NO_CARD)) { 4128*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 4129*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4130*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 4131*7c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 4132*7c478bd9Sstevel@tonic-gate 4133*7c478bd9Sstevel@tonic-gate /* 4134*7c478bd9Sstevel@tonic-gate * Get a handle to the CIS window 4135*7c478bd9Sstevel@tonic-gate */ 4136*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 4137*7c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 4138*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: socket %d " 4139*7c478bd9Sstevel@tonic-gate "can't init CIS window\n", 4140*7c478bd9Sstevel@tonic-gate sp->socket_num); 4141*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 4142*7c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 4143*7c478bd9Sstevel@tonic-gate 4144*7c478bd9Sstevel@tonic-gate prrd = csx_Get8(cis_handle, client->config_regs.prr_p); 4145*7c478bd9Sstevel@tonic-gate prrd &= client->pin; 4146*7c478bd9Sstevel@tonic-gate 4147*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 4148*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 4149*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: " 4150*7c478bd9Sstevel@tonic-gate "prrd 0x%x client->pin 0x%x\n", 4151*7c478bd9Sstevel@tonic-gate (int)prrd, 4152*7c478bd9Sstevel@tonic-gate client->pin); 4153*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR(1) = [%s%s%s%s%s%s%s%s]\n", 4154*7c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 4155*7c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 4156*7c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 4157*7c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 4158*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 4159*7c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 4160*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 4161*7c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 4162*7c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 4163*7c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 4164*7c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 4165*7c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 4166*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 4167*7c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 4168*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 4169*7c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 4170*7c478bd9Sstevel@tonic-gate } 4171*7c478bd9Sstevel@tonic-gate #endif 4172*7c478bd9Sstevel@tonic-gate 4173*7c478bd9Sstevel@tonic-gate /* 4174*7c478bd9Sstevel@tonic-gate * The caller wants the event changes sent back and 4175*7c478bd9Sstevel@tonic-gate * the PRR event change bits cleared. 4176*7c478bd9Sstevel@tonic-gate */ 4177*7c478bd9Sstevel@tonic-gate if (revent) { 4178*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 4179*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 4180*7c478bd9Sstevel@tonic-gate 4181*7c478bd9Sstevel@tonic-gate /* 4182*7c478bd9Sstevel@tonic-gate * Bug ID: 1193636 - Card Services sends bogus 4183*7c478bd9Sstevel@tonic-gate * events on CS_EVENT_STATUS_CHANGE events 4184*7c478bd9Sstevel@tonic-gate * Clear this before we OR-in any values. 4185*7c478bd9Sstevel@tonic-gate */ 4186*7c478bd9Sstevel@tonic-gate *revent = 0; 4187*7c478bd9Sstevel@tonic-gate 4188*7c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_WP_EVENT, PRR_WP_STATUS, 4189*7c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT, *revent); 4190*7c478bd9Sstevel@tonic-gate 4191*7c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_READY_EVENT, PRR_READY_STATUS, 4192*7c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY, *revent); 4193*7c478bd9Sstevel@tonic-gate 4194*7c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD2_EVENT, PRR_BVD2_STATUS, 4195*7c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_LOW, *revent); 4196*7c478bd9Sstevel@tonic-gate 4197*7c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD1_EVENT, PRR_BVD1_STATUS, 4198*7c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_DEAD, *revent); 4199*7c478bd9Sstevel@tonic-gate 4200*7c478bd9Sstevel@tonic-gate 4201*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 4202*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 4203*7c478bd9Sstevel@tonic-gate 4204*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR() = [%s%s%s%s%s%s%s%s]\n", 4205*7c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 4206*7c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 4207*7c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 4208*7c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 4209*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 4210*7c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 4211*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 4212*7c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 4213*7c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 4214*7c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 4215*7c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 4216*7c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 4217*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 4218*7c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 4219*7c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 4220*7c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 4221*7c478bd9Sstevel@tonic-gate } 4222*7c478bd9Sstevel@tonic-gate #endif 4223*7c478bd9Sstevel@tonic-gate 4224*7c478bd9Sstevel@tonic-gate if (prrd) 4225*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, client->config_regs.prr_p, 4226*7c478bd9Sstevel@tonic-gate prrd); 4227*7c478bd9Sstevel@tonic-gate 4228*7c478bd9Sstevel@tonic-gate /* 4229*7c478bd9Sstevel@tonic-gate * We now have to reenable the status change interrupts 4230*7c478bd9Sstevel@tonic-gate * if there are any valid bits in the PRR. Since 4231*7c478bd9Sstevel@tonic-gate * the BVD1 signal becomes the STATUS_CHANGE 4232*7c478bd9Sstevel@tonic-gate * signal when the socket is in IO mode, we just 4233*7c478bd9Sstevel@tonic-gate * have to set the SBM_BVD1 enable bit in the 4234*7c478bd9Sstevel@tonic-gate * event mask. 4235*7c478bd9Sstevel@tonic-gate */ 4236*7c478bd9Sstevel@tonic-gate if (client->pin) { 4237*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4238*7c478bd9Sstevel@tonic-gate SocketServices(SS_GetSocket, &get_socket); 4239*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4240*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 4241*7c478bd9Sstevel@tonic-gate get_socket.SCIntMask | SBM_BVD1; 4242*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4243*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4244*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4245*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4246*7c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4247*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4248*7c478bd9Sstevel@tonic-gate set_socket.State = get_socket.state; 4249*7c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket); 4250*7c478bd9Sstevel@tonic-gate } /* if (client->pin) */ 4251*7c478bd9Sstevel@tonic-gate } /* if (revent) */ 4252*7c478bd9Sstevel@tonic-gate 4253*7c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4254*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 4255*7c478bd9Sstevel@tonic-gate 4256*7c478bd9Sstevel@tonic-gate /* 4257*7c478bd9Sstevel@tonic-gate * The caller wants the current card state; we just read 4258*7c478bd9Sstevel@tonic-gate * it and return a copy of it but do not clear any of 4259*7c478bd9Sstevel@tonic-gate * the event changed bits (if we're reading the PRR). 4260*7c478bd9Sstevel@tonic-gate */ 4261*7c478bd9Sstevel@tonic-gate if (gs) { 4262*7c478bd9Sstevel@tonic-gate gs->socket = sp->socket_num; 4263*7c478bd9Sstevel@tonic-gate gs->CardState = 0; 4264*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, gs) != SUCCESS) 4265*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4266*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 4267*7c478bd9Sstevel@tonic-gate /* 4268*7c478bd9Sstevel@tonic-gate * If the socket is in IO mode, then clear the 4269*7c478bd9Sstevel@tonic-gate * gs->CardState bits that are now in the PRR 4270*7c478bd9Sstevel@tonic-gate */ 4271*7c478bd9Sstevel@tonic-gate gs->CardState &= ~(SBM_WP | SBM_BVD1 | 4272*7c478bd9Sstevel@tonic-gate SBM_BVD2 | SBM_RDYBSY); 4273*7c478bd9Sstevel@tonic-gate 4274*7c478bd9Sstevel@tonic-gate /* 4275*7c478bd9Sstevel@tonic-gate * Convert PRR status to SS_GetStatus status 4276*7c478bd9Sstevel@tonic-gate */ 4277*7c478bd9Sstevel@tonic-gate if (prrd & PRR_WP_STATUS) 4278*7c478bd9Sstevel@tonic-gate gs->CardState |= SBM_WP; 4279*7c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD2_STATUS) 4280*7c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD2; 4281*7c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD1_STATUS) 4282*7c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD1; 4283*7c478bd9Sstevel@tonic-gate 4284*7c478bd9Sstevel@tonic-gate /* 4285*7c478bd9Sstevel@tonic-gate * If the client has indicated that there is no 4286*7c478bd9Sstevel@tonic-gate * PRR or that the READY bit in the PRR isn't 4287*7c478bd9Sstevel@tonic-gate * valid, then we simulate the READY bit by 4288*7c478bd9Sstevel@tonic-gate * always returning READY. 4289*7c478bd9Sstevel@tonic-gate */ 4290*7c478bd9Sstevel@tonic-gate if (!(client->present & CONFIG_PINREPL_REG_PRESENT) || 4291*7c478bd9Sstevel@tonic-gate ((client->present & CONFIG_PINREPL_REG_PRESENT) && 4292*7c478bd9Sstevel@tonic-gate !((client->pin & 4293*7c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) == 4294*7c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT))) || 4295*7c478bd9Sstevel@tonic-gate (prrd & PRR_READY_STATUS)) 4296*7c478bd9Sstevel@tonic-gate gs->CardState |= SBM_RDYBSY; 4297*7c478bd9Sstevel@tonic-gate 4298*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 4299*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 4300*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: prrd 0x%x " 4301*7c478bd9Sstevel@tonic-gate "client->pin 0x%x " 4302*7c478bd9Sstevel@tonic-gate "gs->CardState 0x%x\n", 4303*7c478bd9Sstevel@tonic-gate prrd, client->pin, gs->CardState); 4304*7c478bd9Sstevel@tonic-gate } 4305*7c478bd9Sstevel@tonic-gate #endif 4306*7c478bd9Sstevel@tonic-gate 4307*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 4308*7c478bd9Sstevel@tonic-gate } /* if (gs) */ 4309*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4310*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_CARD_INSERTED) */ 4311*7c478bd9Sstevel@tonic-gate 4312*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 4313*7c478bd9Sstevel@tonic-gate } 4314*7c478bd9Sstevel@tonic-gate 4315*7c478bd9Sstevel@tonic-gate /* 4316*7c478bd9Sstevel@tonic-gate * cs_get_status - gets live card status and latched card status changes 4317*7c478bd9Sstevel@tonic-gate * supports the GetStatus CS call 4318*7c478bd9Sstevel@tonic-gate * 4319*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 4320*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if the passed client handle is invalid 4321*7c478bd9Sstevel@tonic-gate * 4322*7c478bd9Sstevel@tonic-gate * Note: This function resets the latched status values maintained 4323*7c478bd9Sstevel@tonic-gate * by Socket Services 4324*7c478bd9Sstevel@tonic-gate */ 4325*7c478bd9Sstevel@tonic-gate static int 4326*7c478bd9Sstevel@tonic-gate cs_get_status(client_handle_t client_handle, get_status_t *gs) 4327*7c478bd9Sstevel@tonic-gate { 4328*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 4329*7c478bd9Sstevel@tonic-gate client_t *client; 4330*7c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 4331*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 4332*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 4333*7c478bd9Sstevel@tonic-gate int error; 4334*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 4335*7c478bd9Sstevel@tonic-gate 4336*7c478bd9Sstevel@tonic-gate /* 4337*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4338*7c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 4339*7c478bd9Sstevel@tonic-gate */ 4340*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4341*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4342*7c478bd9Sstevel@tonic-gate 4343*7c478bd9Sstevel@tonic-gate /* 4344*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4345*7c478bd9Sstevel@tonic-gate */ 4346*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4347*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4348*7c478bd9Sstevel@tonic-gate 4349*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4350*7c478bd9Sstevel@tonic-gate 4351*7c478bd9Sstevel@tonic-gate /* 4352*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 4353*7c478bd9Sstevel@tonic-gate */ 4354*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4355*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4356*7c478bd9Sstevel@tonic-gate return (error); 4357*7c478bd9Sstevel@tonic-gate } 4358*7c478bd9Sstevel@tonic-gate 4359*7c478bd9Sstevel@tonic-gate /* 4360*7c478bd9Sstevel@tonic-gate * Get the current card status as well as the latched card 4361*7c478bd9Sstevel@tonic-gate * state. Set the CS_RES_IGNORE_NO_CARD so that even 4362*7c478bd9Sstevel@tonic-gate * if there is no card in the socket we'll still get 4363*7c478bd9Sstevel@tonic-gate * a valid status. 4364*7c478bd9Sstevel@tonic-gate * Note that it is not necessary to initialize any values 4365*7c478bd9Sstevel@tonic-gate * in the get_ss_status structure. 4366*7c478bd9Sstevel@tonic-gate */ 4367*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 4368*7c478bd9Sstevel@tonic-gate if ((error = cs_read_event_status(sp, client, NULL, &get_ss_status, 4369*7c478bd9Sstevel@tonic-gate CS_RES_IGNORE_NO_CARD)) != CS_SUCCESS) { 4370*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4371*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4372*7c478bd9Sstevel@tonic-gate return (error); 4373*7c478bd9Sstevel@tonic-gate } 4374*7c478bd9Sstevel@tonic-gate 4375*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4376*7c478bd9Sstevel@tonic-gate 4377*7c478bd9Sstevel@tonic-gate gs->raw_CardState = cs_sbm2cse(get_ss_status.CardState); 4378*7c478bd9Sstevel@tonic-gate 4379*7c478bd9Sstevel@tonic-gate /* 4380*7c478bd9Sstevel@tonic-gate * Assign the "live" card state to the "real" card state. If there's 4381*7c478bd9Sstevel@tonic-gate * no card in the socket or the card in the socket is not 4382*7c478bd9Sstevel@tonic-gate * for this client, then we lie and tell the caller that the 4383*7c478bd9Sstevel@tonic-gate * card is not inserted. 4384*7c478bd9Sstevel@tonic-gate */ 4385*7c478bd9Sstevel@tonic-gate gs->CardState = gs->raw_CardState; 4386*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 4387*7c478bd9Sstevel@tonic-gate gs->CardState &= ~CS_EVENT_CARD_INSERTION; 4388*7c478bd9Sstevel@tonic-gate 4389*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4390*7c478bd9Sstevel@tonic-gate 4391*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4392*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4393*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4394*7c478bd9Sstevel@tonic-gate 4395*7c478bd9Sstevel@tonic-gate gs->SocketState = cs_sbm2cse(get_socket.state); 4396*7c478bd9Sstevel@tonic-gate 4397*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4398*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 4399*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4400*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4401*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4402*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4403*7c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4404*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4405*7c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 4406*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 4407*7c478bd9Sstevel@tonic-gate 4408*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4409*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4410*7c478bd9Sstevel@tonic-gate 4411*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4412*7c478bd9Sstevel@tonic-gate } 4413*7c478bd9Sstevel@tonic-gate 4414*7c478bd9Sstevel@tonic-gate /* 4415*7c478bd9Sstevel@tonic-gate * cs_cse2sbm - converts a CS event mask to an SS (SBM_XXX) event mask 4416*7c478bd9Sstevel@tonic-gate */ 4417*7c478bd9Sstevel@tonic-gate static event_t 4418*7c478bd9Sstevel@tonic-gate cs_cse2sbm(event_t event_mask) 4419*7c478bd9Sstevel@tonic-gate { 4420*7c478bd9Sstevel@tonic-gate event_t sbm_event = 0; 4421*7c478bd9Sstevel@tonic-gate 4422*7c478bd9Sstevel@tonic-gate /* 4423*7c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 4424*7c478bd9Sstevel@tonic-gate */ 4425*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 4426*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_WP; 4427*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 4428*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD1; 4429*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 4430*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD2; 4431*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 4432*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_RDYBSY; 4433*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_LOCK) 4434*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_LOCKED; 4435*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_EJECTION_REQUEST) 4436*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_EJECT; 4437*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_INSERTION_REQUEST) 4438*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_INSERT; 4439*7c478bd9Sstevel@tonic-gate if (event_mask & (CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL)) 4440*7c478bd9Sstevel@tonic-gate sbm_event |= SBM_CD; 4441*7c478bd9Sstevel@tonic-gate 4442*7c478bd9Sstevel@tonic-gate return (sbm_event); 4443*7c478bd9Sstevel@tonic-gate } 4444*7c478bd9Sstevel@tonic-gate 4445*7c478bd9Sstevel@tonic-gate /* 4446*7c478bd9Sstevel@tonic-gate * cs_sbm2cse - converts SBM_xxx state to CS event bits 4447*7c478bd9Sstevel@tonic-gate * 4448*7c478bd9Sstevel@tonic-gate * This function should never set any of the following bits: 4449*7c478bd9Sstevel@tonic-gate * 4450*7c478bd9Sstevel@tonic-gate * CS_EVENT_MTD_REQUEST 4451*7c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO 4452*7c478bd9Sstevel@tonic-gate * CS_EVENT_TIMER_EXPIRED 4453*7c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL 4454*7c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL_LOWP 4455*7c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 4456*7c478bd9Sstevel@tonic-gate * CS_EVENT_READY_TIMEOUT 4457*7c478bd9Sstevel@tonic-gate * 4458*7c478bd9Sstevel@tonic-gate * These bits are defined in the CS_STATUS_XXX series and are 4459*7c478bd9Sstevel@tonic-gate * used by GetStatus. 4460*7c478bd9Sstevel@tonic-gate */ 4461*7c478bd9Sstevel@tonic-gate static uint32_t 4462*7c478bd9Sstevel@tonic-gate cs_sbm2cse(uint32_t state) 4463*7c478bd9Sstevel@tonic-gate { 4464*7c478bd9Sstevel@tonic-gate uint32_t rstate = 0; 4465*7c478bd9Sstevel@tonic-gate 4466*7c478bd9Sstevel@tonic-gate /* 4467*7c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 4468*7c478bd9Sstevel@tonic-gate */ 4469*7c478bd9Sstevel@tonic-gate if (state & SBM_WP) 4470*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_WRITE_PROTECT; 4471*7c478bd9Sstevel@tonic-gate if (state & SBM_BVD1) 4472*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_DEAD; 4473*7c478bd9Sstevel@tonic-gate if (state & SBM_BVD2) 4474*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_LOW; 4475*7c478bd9Sstevel@tonic-gate if (state & SBM_RDYBSY) 4476*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_READY; 4477*7c478bd9Sstevel@tonic-gate if (state & SBM_LOCKED) 4478*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_LOCK; 4479*7c478bd9Sstevel@tonic-gate if (state & SBM_EJECT) 4480*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_EJECTION_REQUEST; 4481*7c478bd9Sstevel@tonic-gate if (state & SBM_INSERT) 4482*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_INSERTION_REQUEST; 4483*7c478bd9Sstevel@tonic-gate if (state & SBM_CD) 4484*7c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_INSERTION; 4485*7c478bd9Sstevel@tonic-gate 4486*7c478bd9Sstevel@tonic-gate return (rstate); 4487*7c478bd9Sstevel@tonic-gate } 4488*7c478bd9Sstevel@tonic-gate 4489*7c478bd9Sstevel@tonic-gate /* 4490*7c478bd9Sstevel@tonic-gate * cs_merge_event_masks - merge the CS global socket event mask with the 4491*7c478bd9Sstevel@tonic-gate * passed client's event masks 4492*7c478bd9Sstevel@tonic-gate */ 4493*7c478bd9Sstevel@tonic-gate static unsigned 4494*7c478bd9Sstevel@tonic-gate cs_merge_event_masks(cs_socket_t *sp, client_t *client) 4495*7c478bd9Sstevel@tonic-gate { 4496*7c478bd9Sstevel@tonic-gate unsigned SCIntMask; 4497*7c478bd9Sstevel@tonic-gate uint32_t event_mask; 4498*7c478bd9Sstevel@tonic-gate 4499*7c478bd9Sstevel@tonic-gate /* 4500*7c478bd9Sstevel@tonic-gate * We always want to see card detect and status change events. 4501*7c478bd9Sstevel@tonic-gate */ 4502*7c478bd9Sstevel@tonic-gate SCIntMask = SBM_CD; 4503*7c478bd9Sstevel@tonic-gate 4504*7c478bd9Sstevel@tonic-gate event_mask = client->event_mask | client->global_mask | 4505*7c478bd9Sstevel@tonic-gate sp->event_mask; 4506*7c478bd9Sstevel@tonic-gate 4507*7c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_IS_IO)) { 4508*7c478bd9Sstevel@tonic-gate SCIntMask |= cs_cse2sbm(event_mask); 4509*7c478bd9Sstevel@tonic-gate } else { 4510*7c478bd9Sstevel@tonic-gate /* 4511*7c478bd9Sstevel@tonic-gate * If the socket is in IO mode and there is a PRR present, 4512*7c478bd9Sstevel@tonic-gate * then we may need to enable PCE_CARD_STATUS_CHANGE 4513*7c478bd9Sstevel@tonic-gate * events. 4514*7c478bd9Sstevel@tonic-gate */ 4515*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 4516*7c478bd9Sstevel@tonic-gate 4517*7c478bd9Sstevel@tonic-gate SCIntMask |= (cs_cse2sbm(event_mask) & 4518*7c478bd9Sstevel@tonic-gate ~(SBM_WP | SBM_BVD1 | SBM_BVD2 | SBM_RDYBSY)); 4519*7c478bd9Sstevel@tonic-gate 4520*7c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_WP_STATUS | PRR_WP_EVENT)) == 4521*7c478bd9Sstevel@tonic-gate (PRR_WP_STATUS | PRR_WP_EVENT)) 4522*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 4523*7c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4524*7c478bd9Sstevel@tonic-gate 4525*7c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_READY_STATUS | PRR_READY_EVENT)) == 4526*7c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) 4527*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 4528*7c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4529*7c478bd9Sstevel@tonic-gate 4530*7c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) == 4531*7c478bd9Sstevel@tonic-gate (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) 4532*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 4533*7c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4534*7c478bd9Sstevel@tonic-gate 4535*7c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) == 4536*7c478bd9Sstevel@tonic-gate (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) 4537*7c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 4538*7c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 4539*7c478bd9Sstevel@tonic-gate 4540*7c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 4541*7c478bd9Sstevel@tonic-gate } /* if (!SOCKET_IS_IO) */ 4542*7c478bd9Sstevel@tonic-gate 4543*7c478bd9Sstevel@tonic-gate return (SCIntMask); 4544*7c478bd9Sstevel@tonic-gate } 4545*7c478bd9Sstevel@tonic-gate 4546*7c478bd9Sstevel@tonic-gate /* 4547*7c478bd9Sstevel@tonic-gate * cs_set_socket_event_mask - set the event mask for the socket 4548*7c478bd9Sstevel@tonic-gate */ 4549*7c478bd9Sstevel@tonic-gate static int 4550*7c478bd9Sstevel@tonic-gate cs_set_socket_event_mask(cs_socket_t *sp, unsigned event_mask) 4551*7c478bd9Sstevel@tonic-gate { 4552*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 4553*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 4554*7c478bd9Sstevel@tonic-gate 4555*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 4556*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 4557*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4558*7c478bd9Sstevel@tonic-gate 4559*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4560*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = event_mask; 4561*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 4562*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 4563*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 4564*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 4565*7c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 4566*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 4567*7c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 4568*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 4569*7c478bd9Sstevel@tonic-gate 4570*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 4571*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4572*7c478bd9Sstevel@tonic-gate 4573*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4574*7c478bd9Sstevel@tonic-gate } 4575*7c478bd9Sstevel@tonic-gate 4576*7c478bd9Sstevel@tonic-gate /* 4577*7c478bd9Sstevel@tonic-gate * ==== MTD handling section ==== 4578*7c478bd9Sstevel@tonic-gate */ 4579*7c478bd9Sstevel@tonic-gate static int 4580*7c478bd9Sstevel@tonic-gate cs_deregister_mtd(client_handle_t client_handle) 4581*7c478bd9Sstevel@tonic-gate { 4582*7c478bd9Sstevel@tonic-gate 4583*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deregister_mtd: client_handle 0x%x\n", 4584*7c478bd9Sstevel@tonic-gate (int)client_handle); 4585*7c478bd9Sstevel@tonic-gate 4586*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4587*7c478bd9Sstevel@tonic-gate } 4588*7c478bd9Sstevel@tonic-gate 4589*7c478bd9Sstevel@tonic-gate /* 4590*7c478bd9Sstevel@tonic-gate * ==== memory window handling section ==== 4591*7c478bd9Sstevel@tonic-gate */ 4592*7c478bd9Sstevel@tonic-gate 4593*7c478bd9Sstevel@tonic-gate /* 4594*7c478bd9Sstevel@tonic-gate * cs_request_window - searches through window list for the socket to find a 4595*7c478bd9Sstevel@tonic-gate * memory window that matches the requested criteria; 4596*7c478bd9Sstevel@tonic-gate * this is RequestWindow 4597*7c478bd9Sstevel@tonic-gate * 4598*7c478bd9Sstevel@tonic-gate * calling: cs_request_window(client_handle_t, *window_handle_t, win_req_t *) 4599*7c478bd9Sstevel@tonic-gate * 4600*7c478bd9Sstevel@tonic-gate * On sucessful return, the window_handle_t * pointed to will 4601*7c478bd9Sstevel@tonic-gate * contain a valid window handle for this window. 4602*7c478bd9Sstevel@tonic-gate * 4603*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if window found 4604*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 4605*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 4606*7c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 4607*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 4608*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 4609*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 4610*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attrbute 4611*7c478bd9Sstevel@tonic-gate * flags are set 4612*7c478bd9Sstevel@tonic-gate */ 4613*7c478bd9Sstevel@tonic-gate static int 4614*7c478bd9Sstevel@tonic-gate cs_request_window(client_handle_t client_handle, 4615*7c478bd9Sstevel@tonic-gate window_handle_t *wh, 4616*7c478bd9Sstevel@tonic-gate win_req_t *rw) 4617*7c478bd9Sstevel@tonic-gate { 4618*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 4619*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 4620*7c478bd9Sstevel@tonic-gate client_t *client; 4621*7c478bd9Sstevel@tonic-gate modify_win_t mw; 4622*7c478bd9Sstevel@tonic-gate inquire_window_t iw; 4623*7c478bd9Sstevel@tonic-gate uint32_t aw; 4624*7c478bd9Sstevel@tonic-gate int error; 4625*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 4626*7c478bd9Sstevel@tonic-gate uint32_t socket_num; 4627*7c478bd9Sstevel@tonic-gate 4628*7c478bd9Sstevel@tonic-gate /* 4629*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4630*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 4631*7c478bd9Sstevel@tonic-gate */ 4632*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 4633*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 4634*7c478bd9Sstevel@tonic-gate 4635*7c478bd9Sstevel@tonic-gate /* 4636*7c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported flags are set. 4637*7c478bd9Sstevel@tonic-gate */ 4638*7c478bd9Sstevel@tonic-gate if (rw->Attributes & (/* Compatability */ 4639*7c478bd9Sstevel@tonic-gate WIN_PAGED | 4640*7c478bd9Sstevel@tonic-gate WIN_SHARED | 4641*7c478bd9Sstevel@tonic-gate WIN_FIRST_SHARED | 4642*7c478bd9Sstevel@tonic-gate WIN_BINDING_SPECIFIC | 4643*7c478bd9Sstevel@tonic-gate /* CS internal */ 4644*7c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 4645*7c478bd9Sstevel@tonic-gate /* IO window flags */ 4646*7c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_IO | 4647*7c478bd9Sstevel@tonic-gate /* CardBus flags */ 4648*7c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_32 | 4649*7c478bd9Sstevel@tonic-gate WIN_PREFETCH_CACHE_MASK | 4650*7c478bd9Sstevel@tonic-gate WIN_BAR_MASK)) 4651*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 4652*7c478bd9Sstevel@tonic-gate 4653*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4654*7c478bd9Sstevel@tonic-gate 4655*7c478bd9Sstevel@tonic-gate /* 4656*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4657*7c478bd9Sstevel@tonic-gate */ 4658*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 4659*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4660*7c478bd9Sstevel@tonic-gate 4661*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4662*7c478bd9Sstevel@tonic-gate 4663*7c478bd9Sstevel@tonic-gate /* 4664*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 4665*7c478bd9Sstevel@tonic-gate */ 4666*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 4667*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4668*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4669*7c478bd9Sstevel@tonic-gate return (error); 4670*7c478bd9Sstevel@tonic-gate } 4671*7c478bd9Sstevel@tonic-gate 4672*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 4673*7c478bd9Sstevel@tonic-gate 4674*7c478bd9Sstevel@tonic-gate /* 4675*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4676*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 4677*7c478bd9Sstevel@tonic-gate */ 4678*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4679*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4680*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4681*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4682*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 4683*7c478bd9Sstevel@tonic-gate } 4684*7c478bd9Sstevel@tonic-gate 4685*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4686*7c478bd9Sstevel@tonic-gate 4687*7c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 4688*7c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 4689*7c478bd9Sstevel@tonic-gate 4690*7c478bd9Sstevel@tonic-gate 4691*7c478bd9Sstevel@tonic-gate /* 4692*7c478bd9Sstevel@tonic-gate * See if we can find a window that matches the caller's criteria. 4693*7c478bd9Sstevel@tonic-gate * If we can't, then thre's not much more that we can do except 4694*7c478bd9Sstevel@tonic-gate * for return an error. 4695*7c478bd9Sstevel@tonic-gate */ 4696*7c478bd9Sstevel@tonic-gate if ((error = cs_find_mem_window(sp->socket_num, rw, &aw)) != 4697*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 4698*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4699*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4700*7c478bd9Sstevel@tonic-gate return (error); 4701*7c478bd9Sstevel@tonic-gate } 4702*7c478bd9Sstevel@tonic-gate 4703*7c478bd9Sstevel@tonic-gate /* 4704*7c478bd9Sstevel@tonic-gate * We got a window, now synthesize a new window handle for this 4705*7c478bd9Sstevel@tonic-gate * client and get a pointer to the global window structs 4706*7c478bd9Sstevel@tonic-gate * and assign this window to this client. 4707*7c478bd9Sstevel@tonic-gate * We don't have to check for errors from cs_create_window_handle 4708*7c478bd9Sstevel@tonic-gate * since that function always returns a valid window handle 4709*7c478bd9Sstevel@tonic-gate * if it is given a valid window number. 4710*7c478bd9Sstevel@tonic-gate */ 4711*7c478bd9Sstevel@tonic-gate *wh = cs_create_window_handle(aw); 4712*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(aw)) == NULL) { 4713*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4714*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4715*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 4716*7c478bd9Sstevel@tonic-gate } 4717*7c478bd9Sstevel@tonic-gate 4718*7c478bd9Sstevel@tonic-gate cw->window_handle = *wh; 4719*7c478bd9Sstevel@tonic-gate cw->client_handle = client_handle; 4720*7c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 4721*7c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_MEM); 4722*7c478bd9Sstevel@tonic-gate 4723*7c478bd9Sstevel@tonic-gate mw.Attributes = ( 4724*7c478bd9Sstevel@tonic-gate rw->Attributes | 4725*7c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 4726*7c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID); 4727*7c478bd9Sstevel@tonic-gate mw.AccessSpeed = rw->win_params.AccessSpeed; 4728*7c478bd9Sstevel@tonic-gate 4729*7c478bd9Sstevel@tonic-gate if ((error = cs_modify_mem_window(*wh, &mw, rw, socket_num)) != 4730*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 4731*7c478bd9Sstevel@tonic-gate cw->state = 0; 4732*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4733*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4734*7c478bd9Sstevel@tonic-gate return (error); 4735*7c478bd9Sstevel@tonic-gate } 4736*7c478bd9Sstevel@tonic-gate 4737*7c478bd9Sstevel@tonic-gate /* 4738*7c478bd9Sstevel@tonic-gate * Get any required card offset and pass it back to the client. 4739*7c478bd9Sstevel@tonic-gate * This is not defined in the current PCMCIA spec. It is 4740*7c478bd9Sstevel@tonic-gate * an aid to clients that want to use it to generate an 4741*7c478bd9Sstevel@tonic-gate * optimum card offset. 4742*7c478bd9Sstevel@tonic-gate */ 4743*7c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(*wh); 4744*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 4745*7c478bd9Sstevel@tonic-gate 4746*7c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 4747*7c478bd9Sstevel@tonic-gate rw->ReqOffset = rw->Size; 4748*7c478bd9Sstevel@tonic-gate else 4749*7c478bd9Sstevel@tonic-gate rw->ReqOffset = iw.mem_win_char.ReqOffset; 4750*7c478bd9Sstevel@tonic-gate 4751*7c478bd9Sstevel@tonic-gate /* 4752*7c478bd9Sstevel@tonic-gate * Increment the client's memory window count; this is how we know 4753*7c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 4754*7c478bd9Sstevel@tonic-gate */ 4755*7c478bd9Sstevel@tonic-gate client->memwin_count++; 4756*7c478bd9Sstevel@tonic-gate 4757*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4758*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4759*7c478bd9Sstevel@tonic-gate 4760*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4761*7c478bd9Sstevel@tonic-gate } 4762*7c478bd9Sstevel@tonic-gate 4763*7c478bd9Sstevel@tonic-gate /* 4764*7c478bd9Sstevel@tonic-gate * cs_release_window - deallocates the window associated with the passed 4765*7c478bd9Sstevel@tonic-gate * window handle; this is ReleaseWindow 4766*7c478bd9Sstevel@tonic-gate * 4767*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if window handle is valid and window was 4768*7c478bd9Sstevel@tonic-gate * sucessfully deallocated 4769*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if window handle is invalid or if window 4770*7c478bd9Sstevel@tonic-gate * handle is valid but window is not allocated 4771*7c478bd9Sstevel@tonic-gate */ 4772*7c478bd9Sstevel@tonic-gate static int 4773*7c478bd9Sstevel@tonic-gate cs_release_window(window_handle_t wh) 4774*7c478bd9Sstevel@tonic-gate { 4775*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 4776*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 4777*7c478bd9Sstevel@tonic-gate client_t *client; 4778*7c478bd9Sstevel@tonic-gate int error; 4779*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 4780*7c478bd9Sstevel@tonic-gate 4781*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4782*7c478bd9Sstevel@tonic-gate 4783*7c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 4784*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4785*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 4786*7c478bd9Sstevel@tonic-gate } 4787*7c478bd9Sstevel@tonic-gate 4788*7c478bd9Sstevel@tonic-gate /* 4789*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 4790*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 4791*7c478bd9Sstevel@tonic-gate */ 4792*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(cw->client_handle)) { 4793*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4794*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 4795*7c478bd9Sstevel@tonic-gate } 4796*7c478bd9Sstevel@tonic-gate 4797*7c478bd9Sstevel@tonic-gate /* 4798*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4799*7c478bd9Sstevel@tonic-gate */ 4800*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4801*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4802*7c478bd9Sstevel@tonic-gate 4803*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4804*7c478bd9Sstevel@tonic-gate 4805*7c478bd9Sstevel@tonic-gate /* 4806*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 4807*7c478bd9Sstevel@tonic-gate */ 4808*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 4809*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4810*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4811*7c478bd9Sstevel@tonic-gate return (error); 4812*7c478bd9Sstevel@tonic-gate } 4813*7c478bd9Sstevel@tonic-gate 4814*7c478bd9Sstevel@tonic-gate /* 4815*7c478bd9Sstevel@tonic-gate * Mark this window as not in use anymore. 4816*7c478bd9Sstevel@tonic-gate */ 4817*7c478bd9Sstevel@tonic-gate cw->state &= ~CW_WIN_IN_USE; 4818*7c478bd9Sstevel@tonic-gate 4819*7c478bd9Sstevel@tonic-gate /* 4820*7c478bd9Sstevel@tonic-gate * Decrement the client's memory window count; this is how we know 4821*7c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 4822*7c478bd9Sstevel@tonic-gate */ 4823*7c478bd9Sstevel@tonic-gate if (!(--(client->memwin_count))) 4824*7c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_WIN_ALLOCATED; 4825*7c478bd9Sstevel@tonic-gate 4826*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4827*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4828*7c478bd9Sstevel@tonic-gate 4829*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4830*7c478bd9Sstevel@tonic-gate } 4831*7c478bd9Sstevel@tonic-gate 4832*7c478bd9Sstevel@tonic-gate /* 4833*7c478bd9Sstevel@tonic-gate * cs_modify_window - modifies a window's characteristics; this is ModifyWindow 4834*7c478bd9Sstevel@tonic-gate */ 4835*7c478bd9Sstevel@tonic-gate static int 4836*7c478bd9Sstevel@tonic-gate cs_modify_window(window_handle_t wh, modify_win_t *mw) 4837*7c478bd9Sstevel@tonic-gate { 4838*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 4839*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 4840*7c478bd9Sstevel@tonic-gate client_t *client; 4841*7c478bd9Sstevel@tonic-gate int error; 4842*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 4843*7c478bd9Sstevel@tonic-gate 4844*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 4845*7c478bd9Sstevel@tonic-gate 4846*7c478bd9Sstevel@tonic-gate /* 4847*7c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 4848*7c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 4849*7c478bd9Sstevel@tonic-gate * has allocated that window. 4850*7c478bd9Sstevel@tonic-gate */ 4851*7c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 4852*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4853*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 4854*7c478bd9Sstevel@tonic-gate } 4855*7c478bd9Sstevel@tonic-gate 4856*7c478bd9Sstevel@tonic-gate /* 4857*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 4858*7c478bd9Sstevel@tonic-gate */ 4859*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 4860*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 4861*7c478bd9Sstevel@tonic-gate 4862*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 4863*7c478bd9Sstevel@tonic-gate 4864*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 4865*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4866*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4867*7c478bd9Sstevel@tonic-gate return (error); 4868*7c478bd9Sstevel@tonic-gate } 4869*7c478bd9Sstevel@tonic-gate 4870*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 4871*7c478bd9Sstevel@tonic-gate 4872*7c478bd9Sstevel@tonic-gate /* 4873*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 4874*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 4875*7c478bd9Sstevel@tonic-gate */ 4876*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 4877*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4878*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4879*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4880*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 4881*7c478bd9Sstevel@tonic-gate } 4882*7c478bd9Sstevel@tonic-gate 4883*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4884*7c478bd9Sstevel@tonic-gate 4885*7c478bd9Sstevel@tonic-gate mw->Attributes &= ( 4886*7c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_MASK | 4887*7c478bd9Sstevel@tonic-gate WIN_ENABLE | 4888*7c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID | 4889*7c478bd9Sstevel@tonic-gate WIN_ACC_ENDIAN_MASK | 4890*7c478bd9Sstevel@tonic-gate WIN_ACC_ORDER_MASK); 4891*7c478bd9Sstevel@tonic-gate 4892*7c478bd9Sstevel@tonic-gate mw->Attributes &= ~WIN_DATA_WIDTH_VALID; 4893*7c478bd9Sstevel@tonic-gate 4894*7c478bd9Sstevel@tonic-gate if ((error = cs_modify_mem_window(wh, mw, NULL, NULL)) != CS_SUCCESS) { 4895*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4896*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4897*7c478bd9Sstevel@tonic-gate return (error); 4898*7c478bd9Sstevel@tonic-gate } 4899*7c478bd9Sstevel@tonic-gate 4900*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 4901*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 4902*7c478bd9Sstevel@tonic-gate 4903*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 4904*7c478bd9Sstevel@tonic-gate } 4905*7c478bd9Sstevel@tonic-gate 4906*7c478bd9Sstevel@tonic-gate /* 4907*7c478bd9Sstevel@tonic-gate * cs_modify_mem_window - modifies a window's characteristics; used internally 4908*7c478bd9Sstevel@tonic-gate * by Card Services 4909*7c478bd9Sstevel@tonic-gate * 4910*7c478bd9Sstevel@tonic-gate * If *wr is NULL, it means that we're being called by ModifyWindow 4911*7c478bd9Sstevel@tonic-gate * If *wr is non-NULL, it means that we are being called by RequestWindow 4912*7c478bd9Sstevel@tonic-gate * and so we can't use SS_GetWindow. 4913*7c478bd9Sstevel@tonic-gate */ 4914*7c478bd9Sstevel@tonic-gate static int 4915*7c478bd9Sstevel@tonic-gate cs_modify_mem_window(window_handle_t wh, modify_win_t *mw, 4916*7c478bd9Sstevel@tonic-gate win_req_t *wr, int sn) 4917*7c478bd9Sstevel@tonic-gate { 4918*7c478bd9Sstevel@tonic-gate get_window_t gw; 4919*7c478bd9Sstevel@tonic-gate set_window_t sw; 4920*7c478bd9Sstevel@tonic-gate set_page_t set_page; 4921*7c478bd9Sstevel@tonic-gate get_page_t get_page; 4922*7c478bd9Sstevel@tonic-gate 4923*7c478bd9Sstevel@tonic-gate /* 4924*7c478bd9Sstevel@tonic-gate * If the win_req_t struct pointer is NULL, it means that 4925*7c478bd9Sstevel@tonic-gate * we're being called by ModifyWindow, so get the 4926*7c478bd9Sstevel@tonic-gate * current window characteristics. 4927*7c478bd9Sstevel@tonic-gate */ 4928*7c478bd9Sstevel@tonic-gate if (!wr) { 4929*7c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 4930*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 4931*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 4932*7c478bd9Sstevel@tonic-gate sw.state = gw.state; 4933*7c478bd9Sstevel@tonic-gate sw.socket = gw.socket; 4934*7c478bd9Sstevel@tonic-gate sw.WindowSize = gw.size; 4935*7c478bd9Sstevel@tonic-gate } else { 4936*7c478bd9Sstevel@tonic-gate sw.state = 0; 4937*7c478bd9Sstevel@tonic-gate sw.socket = sn; 4938*7c478bd9Sstevel@tonic-gate sw.WindowSize = wr->Size; 4939*7c478bd9Sstevel@tonic-gate } 4940*7c478bd9Sstevel@tonic-gate 4941*7c478bd9Sstevel@tonic-gate /* 4942*7c478bd9Sstevel@tonic-gate * If we're being called by RequestWindow, we must always have 4943*7c478bd9Sstevel@tonic-gate * WIN_ACCESS_SPEED_VALID set since get_window_t is not 4944*7c478bd9Sstevel@tonic-gate * defined. 4945*7c478bd9Sstevel@tonic-gate */ 4946*7c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ACCESS_SPEED_VALID) { 4947*7c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 4948*7c478bd9Sstevel@tonic-gate 4949*7c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_DEVSPEED_TO_NS; 4950*7c478bd9Sstevel@tonic-gate convert_speed.devspeed = mw->AccessSpeed; 4951*7c478bd9Sstevel@tonic-gate 4952*7c478bd9Sstevel@tonic-gate if (cs_convert_speed(&convert_speed) != CS_SUCCESS) 4953*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 4954*7c478bd9Sstevel@tonic-gate 4955*7c478bd9Sstevel@tonic-gate sw.speed = convert_speed.nS; 4956*7c478bd9Sstevel@tonic-gate } else { 4957*7c478bd9Sstevel@tonic-gate sw.speed = gw.speed; 4958*7c478bd9Sstevel@tonic-gate } 4959*7c478bd9Sstevel@tonic-gate 4960*7c478bd9Sstevel@tonic-gate if (!wr) { 4961*7c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 4962*7c478bd9Sstevel@tonic-gate get_page.page = 0; 4963*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetPage, &get_page) != SUCCESS) 4964*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 4965*7c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 4966*7c478bd9Sstevel@tonic-gate set_page.offset = get_page.offset; 4967*7c478bd9Sstevel@tonic-gate } else { 4968*7c478bd9Sstevel@tonic-gate set_page.state = 0; 4969*7c478bd9Sstevel@tonic-gate set_page.offset = 0; 4970*7c478bd9Sstevel@tonic-gate } 4971*7c478bd9Sstevel@tonic-gate 4972*7c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ENABLE) { 4973*7c478bd9Sstevel@tonic-gate sw.state |= WS_ENABLED; 4974*7c478bd9Sstevel@tonic-gate set_page.state |= PS_ENABLED; 4975*7c478bd9Sstevel@tonic-gate } else { 4976*7c478bd9Sstevel@tonic-gate sw.state &= ~WS_ENABLED; 4977*7c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ENABLED; 4978*7c478bd9Sstevel@tonic-gate } 4979*7c478bd9Sstevel@tonic-gate 4980*7c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_VALID) { 4981*7c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_16) 4982*7c478bd9Sstevel@tonic-gate sw.state |= WS_16BIT; 4983*7c478bd9Sstevel@tonic-gate else 4984*7c478bd9Sstevel@tonic-gate sw.state &= ~WS_16BIT; 4985*7c478bd9Sstevel@tonic-gate } 4986*7c478bd9Sstevel@tonic-gate 4987*7c478bd9Sstevel@tonic-gate sw.window = GET_WINDOW_NUMBER(wh); 4988*7c478bd9Sstevel@tonic-gate sw.base = 0; 4989*7c478bd9Sstevel@tonic-gate 4990*7c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&sw, mw->Attributes); 4991*7c478bd9Sstevel@tonic-gate 4992*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) 4993*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 4994*7c478bd9Sstevel@tonic-gate 4995*7c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_MEMORY_TYPE_AM) 4996*7c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 4997*7c478bd9Sstevel@tonic-gate else 4998*7c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ATTRIBUTE; 4999*7c478bd9Sstevel@tonic-gate 5000*7c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 5001*7c478bd9Sstevel@tonic-gate set_page.page = 0; 5002*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) 5003*7c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 5004*7c478bd9Sstevel@tonic-gate 5005*7c478bd9Sstevel@tonic-gate /* 5006*7c478bd9Sstevel@tonic-gate * Return the current base address of this window 5007*7c478bd9Sstevel@tonic-gate */ 5008*7c478bd9Sstevel@tonic-gate if (wr) { 5009*7c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 5010*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 5011*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 5012*7c478bd9Sstevel@tonic-gate 5013*7c478bd9Sstevel@tonic-gate wr->Base.handle = (acc_handle_t)gw.handle; 5014*7c478bd9Sstevel@tonic-gate } 5015*7c478bd9Sstevel@tonic-gate 5016*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5017*7c478bd9Sstevel@tonic-gate } 5018*7c478bd9Sstevel@tonic-gate 5019*7c478bd9Sstevel@tonic-gate /* 5020*7c478bd9Sstevel@tonic-gate * cs_map_mem_page - sets the card offset of the mapped window 5021*7c478bd9Sstevel@tonic-gate */ 5022*7c478bd9Sstevel@tonic-gate static int 5023*7c478bd9Sstevel@tonic-gate cs_map_mem_page(window_handle_t wh, map_mem_page_t *mmp) 5024*7c478bd9Sstevel@tonic-gate { 5025*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 5026*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 5027*7c478bd9Sstevel@tonic-gate client_t *client; 5028*7c478bd9Sstevel@tonic-gate inquire_window_t iw; 5029*7c478bd9Sstevel@tonic-gate get_window_t gw; 5030*7c478bd9Sstevel@tonic-gate set_page_t set_page; 5031*7c478bd9Sstevel@tonic-gate get_page_t get_page; 5032*7c478bd9Sstevel@tonic-gate int error; 5033*7c478bd9Sstevel@tonic-gate uint32_t size; 5034*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 5035*7c478bd9Sstevel@tonic-gate 5036*7c478bd9Sstevel@tonic-gate /* 5037*7c478bd9Sstevel@tonic-gate * We don't support paged windows, so never allow a page number 5038*7c478bd9Sstevel@tonic-gate * of other than 0 5039*7c478bd9Sstevel@tonic-gate */ 5040*7c478bd9Sstevel@tonic-gate if (mmp->Page) 5041*7c478bd9Sstevel@tonic-gate return (CS_BAD_PAGE); 5042*7c478bd9Sstevel@tonic-gate 5043*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5044*7c478bd9Sstevel@tonic-gate 5045*7c478bd9Sstevel@tonic-gate /* 5046*7c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 5047*7c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 5048*7c478bd9Sstevel@tonic-gate * has allocated that window. 5049*7c478bd9Sstevel@tonic-gate */ 5050*7c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 5051*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5052*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 5053*7c478bd9Sstevel@tonic-gate } 5054*7c478bd9Sstevel@tonic-gate 5055*7c478bd9Sstevel@tonic-gate /* 5056*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5057*7c478bd9Sstevel@tonic-gate */ 5058*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 5059*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 5060*7c478bd9Sstevel@tonic-gate 5061*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5062*7c478bd9Sstevel@tonic-gate 5063*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 5064*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5065*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5066*7c478bd9Sstevel@tonic-gate return (error); 5067*7c478bd9Sstevel@tonic-gate } 5068*7c478bd9Sstevel@tonic-gate 5069*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 5070*7c478bd9Sstevel@tonic-gate 5071*7c478bd9Sstevel@tonic-gate /* 5072*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 5073*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 5074*7c478bd9Sstevel@tonic-gate */ 5075*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 5076*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 5077*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5078*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5079*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 5080*7c478bd9Sstevel@tonic-gate } 5081*7c478bd9Sstevel@tonic-gate 5082*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 5083*7c478bd9Sstevel@tonic-gate 5084*7c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 5085*7c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &gw); 5086*7c478bd9Sstevel@tonic-gate 5087*7c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(wh); 5088*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 5089*7c478bd9Sstevel@tonic-gate 5090*7c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 5091*7c478bd9Sstevel@tonic-gate size = gw.size; 5092*7c478bd9Sstevel@tonic-gate else 5093*7c478bd9Sstevel@tonic-gate size = iw.mem_win_char.ReqOffset; 5094*7c478bd9Sstevel@tonic-gate 5095*7c478bd9Sstevel@tonic-gate if (((mmp->CardOffset/size)*size) != mmp->CardOffset) { 5096*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5097*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5098*7c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 5099*7c478bd9Sstevel@tonic-gate } 5100*7c478bd9Sstevel@tonic-gate 5101*7c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 5102*7c478bd9Sstevel@tonic-gate get_page.page = 0; 5103*7c478bd9Sstevel@tonic-gate SocketServices(SS_GetPage, &get_page); 5104*7c478bd9Sstevel@tonic-gate 5105*7c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 5106*7c478bd9Sstevel@tonic-gate set_page.page = 0; 5107*7c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 5108*7c478bd9Sstevel@tonic-gate set_page.offset = mmp->CardOffset; 5109*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 5110*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5111*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5112*7c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 5113*7c478bd9Sstevel@tonic-gate } 5114*7c478bd9Sstevel@tonic-gate 5115*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5116*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5117*7c478bd9Sstevel@tonic-gate 5118*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5119*7c478bd9Sstevel@tonic-gate } 5120*7c478bd9Sstevel@tonic-gate 5121*7c478bd9Sstevel@tonic-gate /* 5122*7c478bd9Sstevel@tonic-gate * cs_find_window - finds the window associated with the passed window 5123*7c478bd9Sstevel@tonic-gate * handle; if the window handle is invalid or no 5124*7c478bd9Sstevel@tonic-gate * windows match the passed window handle, NULL 5125*7c478bd9Sstevel@tonic-gate * is returned. Note that the window must be 5126*7c478bd9Sstevel@tonic-gate * allocated for this function to return a valid 5127*7c478bd9Sstevel@tonic-gate * window pointer. 5128*7c478bd9Sstevel@tonic-gate * 5129*7c478bd9Sstevel@tonic-gate * returns: cs_window_t * pointer to the found window 5130*7c478bd9Sstevel@tonic-gate * NULL if window handle invalid or window not allocated 5131*7c478bd9Sstevel@tonic-gate */ 5132*7c478bd9Sstevel@tonic-gate cs_window_t * 5133*7c478bd9Sstevel@tonic-gate cs_find_window(window_handle_t wh) 5134*7c478bd9Sstevel@tonic-gate { 5135*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 5136*7c478bd9Sstevel@tonic-gate 5137*7c478bd9Sstevel@tonic-gate if ((GET_WINDOW_NUMBER(wh) > cs_globals.num_windows) || 5138*7c478bd9Sstevel@tonic-gate (GET_WINDOW_MAGIC(wh) != WINDOW_HANDLE_MAGIC)) 5139*7c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 5140*7c478bd9Sstevel@tonic-gate 5141*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(GET_WINDOW_NUMBER(wh))) == NULL) 5142*7c478bd9Sstevel@tonic-gate return (NULL); 5143*7c478bd9Sstevel@tonic-gate 5144*7c478bd9Sstevel@tonic-gate if ((cw->state & CW_ALLOCATED) && (cw->state & CW_MEM)) 5145*7c478bd9Sstevel@tonic-gate return (cw); 5146*7c478bd9Sstevel@tonic-gate 5147*7c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 5148*7c478bd9Sstevel@tonic-gate } 5149*7c478bd9Sstevel@tonic-gate 5150*7c478bd9Sstevel@tonic-gate /* 5151*7c478bd9Sstevel@tonic-gate * cs_create_window_handle - creates a unique window handle based on the 5152*7c478bd9Sstevel@tonic-gate * passed window number. 5153*7c478bd9Sstevel@tonic-gate */ 5154*7c478bd9Sstevel@tonic-gate static window_handle_t 5155*7c478bd9Sstevel@tonic-gate cs_create_window_handle(uint32_t aw) 5156*7c478bd9Sstevel@tonic-gate { 5157*7c478bd9Sstevel@tonic-gate return (WINDOW_HANDLE_MAGIC | (aw & WINDOW_HANDLE_MASK)); 5158*7c478bd9Sstevel@tonic-gate } 5159*7c478bd9Sstevel@tonic-gate 5160*7c478bd9Sstevel@tonic-gate /* 5161*7c478bd9Sstevel@tonic-gate * cs_find_mem_window - tries to find a memory window matching the caller's 5162*7c478bd9Sstevel@tonic-gate * criteria 5163*7c478bd9Sstevel@tonic-gate * 5164*7c478bd9Sstevel@tonic-gate * We return the first window that matches the requested criteria. 5165*7c478bd9Sstevel@tonic-gate * 5166*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if memory window found 5167*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5168*7c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 5169*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 5170*7c478bd9Sstevel@tonic-gate */ 5171*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 5172*7c478bd9Sstevel@tonic-gate static int 5173*7c478bd9Sstevel@tonic-gate cs_find_mem_window(uint32_t sn, win_req_t *rw, uint32_t *assigned_window) 5174*7c478bd9Sstevel@tonic-gate { 5175*7c478bd9Sstevel@tonic-gate uint32_t wn; 5176*7c478bd9Sstevel@tonic-gate int error = CS_OUT_OF_RESOURCE; 5177*7c478bd9Sstevel@tonic-gate uint32_t window_num = PCMCIA_MAX_WINDOWS; 5178*7c478bd9Sstevel@tonic-gate uint32_t min_size = UINT_MAX; 5179*7c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 5180*7c478bd9Sstevel@tonic-gate uint32_t MinSize, MaxSize, ReqGran, MemWndCaps, WndCaps; 5181*7c478bd9Sstevel@tonic-gate uint32_t tws; 5182*7c478bd9Sstevel@tonic-gate 5183*7c478bd9Sstevel@tonic-gate iw = &inquire_window; 5184*7c478bd9Sstevel@tonic-gate 5185*7c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 5186*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 5187*7c478bd9Sstevel@tonic-gate 5188*7c478bd9Sstevel@tonic-gate /* 5189*7c478bd9Sstevel@tonic-gate * If we can't get a pointer to this window, we should contine 5190*7c478bd9Sstevel@tonic-gate * with scanning the next window, since this window might have 5191*7c478bd9Sstevel@tonic-gate * been dropped. 5192*7c478bd9Sstevel@tonic-gate */ 5193*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 5194*7c478bd9Sstevel@tonic-gate iw->window = wn; 5195*7c478bd9Sstevel@tonic-gate 5196*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireWindow, iw) != SUCCESS) 5197*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 5198*7c478bd9Sstevel@tonic-gate 5199*7c478bd9Sstevel@tonic-gate MinSize = iw->mem_win_char.MinSize; 5200*7c478bd9Sstevel@tonic-gate MaxSize = iw->mem_win_char.MaxSize; 5201*7c478bd9Sstevel@tonic-gate ReqGran = iw->mem_win_char.ReqGran; 5202*7c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 5203*7c478bd9Sstevel@tonic-gate WndCaps = iw->WndCaps; 5204*7c478bd9Sstevel@tonic-gate 5205*7c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5206*7c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_MEM(cw) && 5207*7c478bd9Sstevel@tonic-gate WndCaps & (WC_COMMON|WC_ATTRIBUTE)) { 5208*7c478bd9Sstevel@tonic-gate if ((error = cs_valid_window_speed(iw, rw->win_params.AccessSpeed)) == 5209*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 5210*7c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 5211*7c478bd9Sstevel@tonic-gate if (cs_memwin_space_and_map_ok(iw, rw)) { 5212*7c478bd9Sstevel@tonic-gate error = CS_BAD_SIZE; 5213*7c478bd9Sstevel@tonic-gate if (!rw->Size) { 5214*7c478bd9Sstevel@tonic-gate min_size = min(min_size, MinSize); 5215*7c478bd9Sstevel@tonic-gate window_num = wn; 5216*7c478bd9Sstevel@tonic-gate goto found_window; 5217*7c478bd9Sstevel@tonic-gate } else { 5218*7c478bd9Sstevel@tonic-gate if (!(MemWndCaps & WC_SIZE)) { 5219*7c478bd9Sstevel@tonic-gate if (rw->Size == MinSize) { 5220*7c478bd9Sstevel@tonic-gate min_size = MinSize; 5221*7c478bd9Sstevel@tonic-gate window_num = wn; 5222*7c478bd9Sstevel@tonic-gate goto found_window; 5223*7c478bd9Sstevel@tonic-gate } 5224*7c478bd9Sstevel@tonic-gate } else { /* WC_SIZE */ 5225*7c478bd9Sstevel@tonic-gate if (!ReqGran) { 5226*7c478bd9Sstevel@tonic-gate error = CS_BAD_WINDOW; 5227*7c478bd9Sstevel@tonic-gate } else { 5228*7c478bd9Sstevel@tonic-gate if ((rw->Size >= MinSize) && 5229*7c478bd9Sstevel@tonic-gate (rw->Size <= MaxSize)) { 5230*7c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_POW2) { 5231*7c478bd9Sstevel@tonic-gate unsigned rg = ReqGran; 5232*7c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 5233*7c478bd9Sstevel@tonic-gate rg = (rg<<1)) { 5234*7c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 5235*7c478bd9Sstevel@tonic-gate min_size = tws; 5236*7c478bd9Sstevel@tonic-gate window_num = wn; 5237*7c478bd9Sstevel@tonic-gate goto found_window; 5238*7c478bd9Sstevel@tonic-gate } 5239*7c478bd9Sstevel@tonic-gate tws += rg; 5240*7c478bd9Sstevel@tonic-gate } /* for (tws) */ 5241*7c478bd9Sstevel@tonic-gate } else { 5242*7c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 5243*7c478bd9Sstevel@tonic-gate tws += ReqGran) { 5244*7c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 5245*7c478bd9Sstevel@tonic-gate min_size = tws; 5246*7c478bd9Sstevel@tonic-gate window_num = wn; 5247*7c478bd9Sstevel@tonic-gate goto found_window; 5248*7c478bd9Sstevel@tonic-gate } 5249*7c478bd9Sstevel@tonic-gate } /* for (tws) */ 5250*7c478bd9Sstevel@tonic-gate } /* if (!WC_POW2) */ 5251*7c478bd9Sstevel@tonic-gate } /* if (Size >= MinSize) */ 5252*7c478bd9Sstevel@tonic-gate } /* if (!ReqGran) */ 5253*7c478bd9Sstevel@tonic-gate } /* if (WC_SIZE) */ 5254*7c478bd9Sstevel@tonic-gate } /* if (rw->Size) */ 5255*7c478bd9Sstevel@tonic-gate } /* if (cs_space_and_map_ok) */ 5256*7c478bd9Sstevel@tonic-gate } /* if (cs_valid_window_speed) */ 5257*7c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 5258*7c478bd9Sstevel@tonic-gate } /* if (cs_get_wp) */ 5259*7c478bd9Sstevel@tonic-gate } /* for (wn) */ 5260*7c478bd9Sstevel@tonic-gate 5261*7c478bd9Sstevel@tonic-gate /* 5262*7c478bd9Sstevel@tonic-gate * If we got here and the window_num wasn't set by any window 5263*7c478bd9Sstevel@tonic-gate * matches in the above code, it means that we didn't 5264*7c478bd9Sstevel@tonic-gate * find a window matching the caller's criteria. 5265*7c478bd9Sstevel@tonic-gate * If the error is CS_BAD_TYPE, it means that the last reason 5266*7c478bd9Sstevel@tonic-gate * that we couldn't match a window was because the caller's 5267*7c478bd9Sstevel@tonic-gate * requested speed was out of range of the last window that 5268*7c478bd9Sstevel@tonic-gate * we checked. We convert this error code to CS_OUT_OF_RESOURCE 5269*7c478bd9Sstevel@tonic-gate * to conform to the RequestWindow section of the PCMCIA 5270*7c478bd9Sstevel@tonic-gate * Card Services spec. 5271*7c478bd9Sstevel@tonic-gate */ 5272*7c478bd9Sstevel@tonic-gate if (window_num == PCMCIA_MAX_WINDOWS) { 5273*7c478bd9Sstevel@tonic-gate if (error == CS_BAD_TYPE) 5274*7c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 5275*7c478bd9Sstevel@tonic-gate return (error); 5276*7c478bd9Sstevel@tonic-gate } 5277*7c478bd9Sstevel@tonic-gate 5278*7c478bd9Sstevel@tonic-gate found_window: 5279*7c478bd9Sstevel@tonic-gate rw->Size = min_size; 5280*7c478bd9Sstevel@tonic-gate *assigned_window = window_num; 5281*7c478bd9Sstevel@tonic-gate iw->window = window_num; 5282*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 5283*7c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 5284*7c478bd9Sstevel@tonic-gate 5285*7c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_CALIGN) 5286*7c478bd9Sstevel@tonic-gate rw->Attributes |= WIN_OFFSET_SIZE; 5287*7c478bd9Sstevel@tonic-gate else 5288*7c478bd9Sstevel@tonic-gate rw->Attributes &= ~WIN_OFFSET_SIZE; 5289*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5290*7c478bd9Sstevel@tonic-gate } 5291*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 5292*7c478bd9Sstevel@tonic-gate 5293*7c478bd9Sstevel@tonic-gate /* 5294*7c478bd9Sstevel@tonic-gate * cs_memwin_space_and_map_ok - checks to see if the passed window mapping 5295*7c478bd9Sstevel@tonic-gate * capabilities and window speeds are in the 5296*7c478bd9Sstevel@tonic-gate * range of the passed window. 5297*7c478bd9Sstevel@tonic-gate * 5298*7c478bd9Sstevel@tonic-gate * returns: 0 - if the capabilities are out of range 5299*7c478bd9Sstevel@tonic-gate * 1 - if the capabilities are in range 5300*7c478bd9Sstevel@tonic-gate */ 5301*7c478bd9Sstevel@tonic-gate static int 5302*7c478bd9Sstevel@tonic-gate cs_memwin_space_and_map_ok(inquire_window_t *iw, win_req_t *rw) 5303*7c478bd9Sstevel@tonic-gate { 5304*7c478bd9Sstevel@tonic-gate 5305*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 5306*7c478bd9Sstevel@tonic-gate if (cs_debug > 240) 5307*7c478bd9Sstevel@tonic-gate printf("-> s&m_ok: Attributes 0x%x AccessSpeed 0x%x " 5308*7c478bd9Sstevel@tonic-gate "WndCaps 0x%x MemWndCaps 0x%x\n", 5309*7c478bd9Sstevel@tonic-gate (int)rw->Attributes, 5310*7c478bd9Sstevel@tonic-gate (int)rw->win_params.AccessSpeed, 5311*7c478bd9Sstevel@tonic-gate iw->WndCaps, 5312*7c478bd9Sstevel@tonic-gate iw->mem_win_char.MemWndCaps); 5313*7c478bd9Sstevel@tonic-gate #endif 5314*7c478bd9Sstevel@tonic-gate 5315*7c478bd9Sstevel@tonic-gate if (rw->win_params.AccessSpeed & WIN_USE_WAIT) { 5316*7c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_WAIT)) 5317*7c478bd9Sstevel@tonic-gate return (0); 5318*7c478bd9Sstevel@tonic-gate } 5319*7c478bd9Sstevel@tonic-gate 5320*7c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_DATA_WIDTH_16) { 5321*7c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_16BIT)) 5322*7c478bd9Sstevel@tonic-gate return (0); 5323*7c478bd9Sstevel@tonic-gate } else { 5324*7c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_8BIT)) 5325*7c478bd9Sstevel@tonic-gate return (0); 5326*7c478bd9Sstevel@tonic-gate } 5327*7c478bd9Sstevel@tonic-gate 5328*7c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_AM) { 5329*7c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_ATTRIBUTE)) 5330*7c478bd9Sstevel@tonic-gate return (0); 5331*7c478bd9Sstevel@tonic-gate } 5332*7c478bd9Sstevel@tonic-gate 5333*7c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_CM) { 5334*7c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_COMMON)) 5335*7c478bd9Sstevel@tonic-gate return (0); 5336*7c478bd9Sstevel@tonic-gate } 5337*7c478bd9Sstevel@tonic-gate 5338*7c478bd9Sstevel@tonic-gate return (1); 5339*7c478bd9Sstevel@tonic-gate } 5340*7c478bd9Sstevel@tonic-gate 5341*7c478bd9Sstevel@tonic-gate /* 5342*7c478bd9Sstevel@tonic-gate * cs_valid_window_speed - checks to see if requested window speed 5343*7c478bd9Sstevel@tonic-gate * is in range of passed window 5344*7c478bd9Sstevel@tonic-gate * 5345*7c478bd9Sstevel@tonic-gate * The inquire_window_t struct gives us speeds in nS, and we 5346*7c478bd9Sstevel@tonic-gate * get speeds in the AccessSpeed variable as a devspeed code. 5347*7c478bd9Sstevel@tonic-gate * 5348*7c478bd9Sstevel@tonic-gate * returns: CS_BAD_SPEED - if AccessSpeed is invalid devspeed code 5349*7c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if AccessSpeed is not in range of valid 5350*7c478bd9Sstevel@tonic-gate * speed for this window 5351*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - if window speed is in range 5352*7c478bd9Sstevel@tonic-gate */ 5353*7c478bd9Sstevel@tonic-gate static int 5354*7c478bd9Sstevel@tonic-gate cs_valid_window_speed(inquire_window_t *iw, uint32_t AccessSpeed) 5355*7c478bd9Sstevel@tonic-gate { 5356*7c478bd9Sstevel@tonic-gate convert_speed_t convert_speed, *cs; 5357*7c478bd9Sstevel@tonic-gate 5358*7c478bd9Sstevel@tonic-gate cs = &convert_speed; 5359*7c478bd9Sstevel@tonic-gate 5360*7c478bd9Sstevel@tonic-gate cs->Attributes = CONVERT_DEVSPEED_TO_NS; 5361*7c478bd9Sstevel@tonic-gate cs->devspeed = AccessSpeed; 5362*7c478bd9Sstevel@tonic-gate 5363*7c478bd9Sstevel@tonic-gate if (cs_convert_speed(cs) != CS_SUCCESS) 5364*7c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 5365*7c478bd9Sstevel@tonic-gate 5366*7c478bd9Sstevel@tonic-gate if ((cs->nS < iw->mem_win_char.Fastest) || 5367*7c478bd9Sstevel@tonic-gate (cs->nS > iw->mem_win_char.Slowest)) 5368*7c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 5369*7c478bd9Sstevel@tonic-gate 5370*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5371*7c478bd9Sstevel@tonic-gate } 5372*7c478bd9Sstevel@tonic-gate 5373*7c478bd9Sstevel@tonic-gate /* 5374*7c478bd9Sstevel@tonic-gate * ==== IO window handling section ==== 5375*7c478bd9Sstevel@tonic-gate */ 5376*7c478bd9Sstevel@tonic-gate 5377*7c478bd9Sstevel@tonic-gate /* 5378*7c478bd9Sstevel@tonic-gate * cs_request_io - provides IO resources for clients; this is RequestIO 5379*7c478bd9Sstevel@tonic-gate * 5380*7c478bd9Sstevel@tonic-gate * calling: cs_request_io(client_handle_t, io_req_t *) 5381*7c478bd9Sstevel@tonic-gate * 5382*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources available for client 5383*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5384*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 5385*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5386*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 5387*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 5388*7c478bd9Sstevel@tonic-gate * flags are set 5389*7c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if either or both base port addresses 5390*7c478bd9Sstevel@tonic-gate * are invalid or out of range 5391*7c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 5392*7c478bd9Sstevel@tonic-gate * already been done 5393*7c478bd9Sstevel@tonic-gate * CS_IN_USE - IO ports already in use or function has 5394*7c478bd9Sstevel@tonic-gate * already been called 5395*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if failure while trying to set window 5396*7c478bd9Sstevel@tonic-gate * characteristics 5397*7c478bd9Sstevel@tonic-gate */ 5398*7c478bd9Sstevel@tonic-gate static int 5399*7c478bd9Sstevel@tonic-gate cs_request_io(client_handle_t client_handle, io_req_t *ior) 5400*7c478bd9Sstevel@tonic-gate { 5401*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 5402*7c478bd9Sstevel@tonic-gate client_t *client; 5403*7c478bd9Sstevel@tonic-gate int error; 5404*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 5405*7c478bd9Sstevel@tonic-gate uint32_t socket_num; 5406*7c478bd9Sstevel@tonic-gate 5407*7c478bd9Sstevel@tonic-gate /* 5408*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 5409*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 5410*7c478bd9Sstevel@tonic-gate */ 5411*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 5412*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 5413*7c478bd9Sstevel@tonic-gate 5414*7c478bd9Sstevel@tonic-gate /* 5415*7c478bd9Sstevel@tonic-gate * If the client has only requested one IO range, then make sure 5416*7c478bd9Sstevel@tonic-gate * that the Attributes2 filed is clear. 5417*7c478bd9Sstevel@tonic-gate */ 5418*7c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 5419*7c478bd9Sstevel@tonic-gate ior->Attributes2 = 0; 5420*7c478bd9Sstevel@tonic-gate 5421*7c478bd9Sstevel@tonic-gate /* 5422*7c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 5423*7c478bd9Sstevel@tonic-gate */ 5424*7c478bd9Sstevel@tonic-gate if ((ior->Attributes1 | ior->Attributes2) & (IO_SHARED | 5425*7c478bd9Sstevel@tonic-gate IO_FIRST_SHARED | 5426*7c478bd9Sstevel@tonic-gate IO_FORCE_ALIAS_ACCESS | 5427*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5428*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)) 5429*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 5430*7c478bd9Sstevel@tonic-gate 5431*7c478bd9Sstevel@tonic-gate /* 5432*7c478bd9Sstevel@tonic-gate * Make sure that we have a port count for the first region. 5433*7c478bd9Sstevel@tonic-gate */ 5434*7c478bd9Sstevel@tonic-gate if (!ior->NumPorts1) 5435*7c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 5436*7c478bd9Sstevel@tonic-gate 5437*7c478bd9Sstevel@tonic-gate /* 5438*7c478bd9Sstevel@tonic-gate * If we're being asked for multiple IO ranges, then both base port 5439*7c478bd9Sstevel@tonic-gate * members must be non-zero. 5440*7c478bd9Sstevel@tonic-gate */ 5441*7c478bd9Sstevel@tonic-gate if ((ior->NumPorts2) && !(ior->BasePort1.base && ior->BasePort2.base)) 5442*7c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 5443*7c478bd9Sstevel@tonic-gate 5444*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5445*7c478bd9Sstevel@tonic-gate 5446*7c478bd9Sstevel@tonic-gate /* 5447*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5448*7c478bd9Sstevel@tonic-gate */ 5449*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5450*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 5451*7c478bd9Sstevel@tonic-gate 5452*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5453*7c478bd9Sstevel@tonic-gate 5454*7c478bd9Sstevel@tonic-gate /* 5455*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 5456*7c478bd9Sstevel@tonic-gate */ 5457*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 5458*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5459*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5460*7c478bd9Sstevel@tonic-gate return (error); 5461*7c478bd9Sstevel@tonic-gate } 5462*7c478bd9Sstevel@tonic-gate 5463*7c478bd9Sstevel@tonic-gate /* 5464*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 5465*7c478bd9Sstevel@tonic-gate * this call. 5466*7c478bd9Sstevel@tonic-gate */ 5467*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 5468*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5469*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5470*7c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 5471*7c478bd9Sstevel@tonic-gate } 5472*7c478bd9Sstevel@tonic-gate 5473*7c478bd9Sstevel@tonic-gate /* 5474*7c478bd9Sstevel@tonic-gate * If RequestIO has already been done, we don't allow this call. 5475*7c478bd9Sstevel@tonic-gate */ 5476*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 5477*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5478*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5479*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 5480*7c478bd9Sstevel@tonic-gate } 5481*7c478bd9Sstevel@tonic-gate 5482*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 5483*7c478bd9Sstevel@tonic-gate 5484*7c478bd9Sstevel@tonic-gate /* 5485*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 5486*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 5487*7c478bd9Sstevel@tonic-gate */ 5488*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 5489*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 5490*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5491*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5492*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 5493*7c478bd9Sstevel@tonic-gate } 5494*7c478bd9Sstevel@tonic-gate 5495*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 5496*7c478bd9Sstevel@tonic-gate 5497*7c478bd9Sstevel@tonic-gate /* 5498*7c478bd9Sstevel@tonic-gate * If we're only being asked for one IO range, then set BasePort2 to 5499*7c478bd9Sstevel@tonic-gate * zero, since we use it later on. 5500*7c478bd9Sstevel@tonic-gate */ 5501*7c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 5502*7c478bd9Sstevel@tonic-gate ior->BasePort2.base = 0; 5503*7c478bd9Sstevel@tonic-gate 5504*7c478bd9Sstevel@tonic-gate /* 5505*7c478bd9Sstevel@tonic-gate * See if we can allow Card Services to select the base address 5506*7c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 5507*7c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 5508*7c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 5509*7c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 5510*7c478bd9Sstevel@tonic-gate * Note that if the client specifies that the card decodes zero 5511*7c478bd9Sstevel@tonic-gate * IO address lines, then we have to use the NumPortsX 5512*7c478bd9Sstevel@tonic-gate * values to figure out how many address lines the card 5513*7c478bd9Sstevel@tonic-gate * actually decodes, and we have to round the NumPortsX 5514*7c478bd9Sstevel@tonic-gate * values up to the closest power of two. 5515*7c478bd9Sstevel@tonic-gate */ 5516*7c478bd9Sstevel@tonic-gate if (ior->IOAddrLines) { 5517*7c478bd9Sstevel@tonic-gate ior->BasePort1.base = IOADDR_FROBNITZ(ior->BasePort1.base, 5518*7c478bd9Sstevel@tonic-gate ior->IOAddrLines); 5519*7c478bd9Sstevel@tonic-gate ior->BasePort2.base = IOADDR_FROBNITZ(ior->BasePort2.base, 5520*7c478bd9Sstevel@tonic-gate ior->IOAddrLines); 5521*7c478bd9Sstevel@tonic-gate } else { 5522*7c478bd9Sstevel@tonic-gate ior->BasePort1.base = ior->BasePort1.base & 5523*7c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5524*7c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5525*7c478bd9Sstevel@tonic-gate ior->BasePort2.base = ior->BasePort2.base & 5526*7c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 5527*7c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 5528*7c478bd9Sstevel@tonic-gate } 5529*7c478bd9Sstevel@tonic-gate 5530*7c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5531*7c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 5532*7c478bd9Sstevel@tonic-gate 5533*7c478bd9Sstevel@tonic-gate 5534*7c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5535*7c478bd9Sstevel@tonic-gate /* 5536*7c478bd9Sstevel@tonic-gate * Here is where the code diverges, depending on the type of IO windows 5537*7c478bd9Sstevel@tonic-gate * that this socket supports. If this socket supportes memory 5538*7c478bd9Sstevel@tonic-gate * mapped IO windows, as determined by cs_init allocating an 5539*7c478bd9Sstevel@tonic-gate * io_mmap_window_t structure on the socket structure, then we 5540*7c478bd9Sstevel@tonic-gate * use one IO window for all the clients on this socket. We can 5541*7c478bd9Sstevel@tonic-gate * do this safely since a memory mapped IO window implies that 5542*7c478bd9Sstevel@tonic-gate * only this socket shares the complete IO space of the card. 5543*7c478bd9Sstevel@tonic-gate * See the next major block of code for a description of what we do 5544*7c478bd9Sstevel@tonic-gate * if a socket doesn't support memory mapped IO windows. 5545*7c478bd9Sstevel@tonic-gate */ 5546*7c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 5547*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 5548*7c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 5549*7c478bd9Sstevel@tonic-gate uint32_t offset; 5550*7c478bd9Sstevel@tonic-gate 5551*7c478bd9Sstevel@tonic-gate /* 5552*7c478bd9Sstevel@tonic-gate * If we haven't allocated an IO window yet, do it now. 5553*7c478bd9Sstevel@tonic-gate * Try to allocate the IO window that cs_init found for us; 5554*7c478bd9Sstevel@tonic-gate * if that fails, then call cs_find_io_win to find a window. 5555*7c478bd9Sstevel@tonic-gate */ 5556*7c478bd9Sstevel@tonic-gate if (!imw->count) { 5557*7c478bd9Sstevel@tonic-gate set_window_t set_window; 5558*7c478bd9Sstevel@tonic-gate 5559*7c478bd9Sstevel@tonic-gate if (!WINDOW_AVAILABLE_FOR_IO(imw->number)) { 5560*7c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 5561*7c478bd9Sstevel@tonic-gate 5562*7c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = (WC_IO_RANGE_PER_WINDOW | 5563*7c478bd9Sstevel@tonic-gate WC_8BIT | 5564*7c478bd9Sstevel@tonic-gate WC_16BIT); 5565*7c478bd9Sstevel@tonic-gate if ((error = cs_find_io_win(sp->socket_num, &iowin_char, 5566*7c478bd9Sstevel@tonic-gate &imw->number, &imw->size)) != CS_SUCCESS) { 5567*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5568*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5569*7c478bd9Sstevel@tonic-gate } /* cs_find_io_win */ 5570*7c478bd9Sstevel@tonic-gate } /* if (!WINDOW_AVAILABLE_FOR_IO) */ 5571*7c478bd9Sstevel@tonic-gate 5572*7c478bd9Sstevel@tonic-gate set_window.socket = socket_num; 5573*7c478bd9Sstevel@tonic-gate set_window.window = imw->number; 5574*7c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 5575*7c478bd9Sstevel@tonic-gate set_window.base.base = 0; 5576*7c478bd9Sstevel@tonic-gate set_window.WindowSize = imw->size; 5577*7c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_16BIT | 5578*7c478bd9Sstevel@tonic-gate WS_EXACT_MAPIN | WS_IO); 5579*7c478bd9Sstevel@tonic-gate 5580*7c478bd9Sstevel@tonic-gate /* XXX - what to d here? XXX */ 5581*7c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 5582*7c478bd9Sstevel@tonic-gate 5583*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) { 5584*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, 5585*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5586*7c478bd9Sstevel@tonic-gate (IO_DEALLOCATE_WINDOW | 5587*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5588*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5589*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5590*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 5591*7c478bd9Sstevel@tonic-gate } 5592*7c478bd9Sstevel@tonic-gate 5593*7c478bd9Sstevel@tonic-gate imw->handle = set_window.base.handle; 5594*7c478bd9Sstevel@tonic-gate imw->size = set_window.WindowSize; 5595*7c478bd9Sstevel@tonic-gate 5596*7c478bd9Sstevel@tonic-gate /* 5597*7c478bd9Sstevel@tonic-gate * Check the caller's port requirements to be sure that they 5598*7c478bd9Sstevel@tonic-gate * fit within our found IO window. 5599*7c478bd9Sstevel@tonic-gate */ 5600*7c478bd9Sstevel@tonic-gate if ((ior->BasePort1.base + ior->NumPorts1 + 5601*7c478bd9Sstevel@tonic-gate ior->BasePort2.base + ior->NumPorts2) > imw->size) { 5602*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5603*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5604*7c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 5605*7c478bd9Sstevel@tonic-gate } 5606*7c478bd9Sstevel@tonic-gate 5607*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(imw->number)) == NULL) { 5608*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5609*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5610*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW) 5611*7c478bd9Sstevel@tonic-gate } 5612*7c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_IO); 5613*7c478bd9Sstevel@tonic-gate 5614*7c478bd9Sstevel@tonic-gate } /* if (!imw->count) */ 5615*7c478bd9Sstevel@tonic-gate 5616*7c478bd9Sstevel@tonic-gate imw->count++; 5617*7c478bd9Sstevel@tonic-gate 5618*7c478bd9Sstevel@tonic-gate /* 5619*7c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 5620*7c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller. 5621*7c478bd9Sstevel@tonic-gate */ 5622*7c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 5623*7c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort1.handle, 0); 5624*7c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort1.handle, &offset); 5625*7c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort1.handle, 5626*7c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 5627*7c478bd9Sstevel@tonic-gate 5628*7c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 5629*7c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 5630*7c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort2.handle, 0); 5631*7c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort2.handle, &offset); 5632*7c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort2.handle, 5633*7c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 5634*7c478bd9Sstevel@tonic-gate } 5635*7c478bd9Sstevel@tonic-gate 5636*7c478bd9Sstevel@tonic-gate /* 5637*7c478bd9Sstevel@tonic-gate * We don't really use these two values if we've got a memory 5638*7c478bd9Sstevel@tonic-gate * mapped IO window since the assigned window number is stored 5639*7c478bd9Sstevel@tonic-gate * in imw->number. 5640*7c478bd9Sstevel@tonic-gate */ 5641*7c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = imw->number; 5642*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5643*7c478bd9Sstevel@tonic-gate 5644*7c478bd9Sstevel@tonic-gate /* 5645*7c478bd9Sstevel@tonic-gate * This socket supports only IO port IO windows. 5646*7c478bd9Sstevel@tonic-gate */ 5647*7c478bd9Sstevel@tonic-gate } else { 5648*7c478bd9Sstevel@tonic-gate #else /* USE_IOMMAP_WINDOW */ 5649*7c478bd9Sstevel@tonic-gate { 5650*7c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5651*7c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 5652*7c478bd9Sstevel@tonic-gate 5653*7c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort1.base; 5654*7c478bd9Sstevel@tonic-gate 5655*7c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, ior->Attributes1, 5656*7c478bd9Sstevel@tonic-gate &client->io_alloc.Window1)) != CS_SUCCESS) { 5657*7c478bd9Sstevel@tonic-gate 5658*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5659*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5660*7c478bd9Sstevel@tonic-gate return (error); 5661*7c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(1)) */ 5662*7c478bd9Sstevel@tonic-gate 5663*7c478bd9Sstevel@tonic-gate /* 5664*7c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 5665*7c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 5666*7c478bd9Sstevel@tonic-gate */ 5667*7c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 5668*7c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 5669*7c478bd9Sstevel@tonic-gate &baseaddru, 5670*7c478bd9Sstevel@tonic-gate &ior->NumPorts1, 5671*7c478bd9Sstevel@tonic-gate ior->IOAddrLines, 5672*7c478bd9Sstevel@tonic-gate ior->Attributes1)) != 5673*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 5674*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5675*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5676*7c478bd9Sstevel@tonic-gate ( 5677*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5678*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5679*7c478bd9Sstevel@tonic-gate 5680*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5681*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5682*7c478bd9Sstevel@tonic-gate return (error); 5683*7c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(1)) */ 5684*7c478bd9Sstevel@tonic-gate 5685*7c478bd9Sstevel@tonic-gate ior->BasePort1.handle = (acc_handle_t)baseaddru.handle; 5686*7c478bd9Sstevel@tonic-gate ior->BasePort1.base = baseaddru.base; 5687*7c478bd9Sstevel@tonic-gate 5688*7c478bd9Sstevel@tonic-gate /* 5689*7c478bd9Sstevel@tonic-gate * See if the client wants two IO ranges. 5690*7c478bd9Sstevel@tonic-gate */ 5691*7c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 5692*7c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 5693*7c478bd9Sstevel@tonic-gate 5694*7c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort2.base; 5695*7c478bd9Sstevel@tonic-gate 5696*7c478bd9Sstevel@tonic-gate /* 5697*7c478bd9Sstevel@tonic-gate * If we fail to allocate this window, then we must deallocate 5698*7c478bd9Sstevel@tonic-gate * the previous IO window that is already allocated. 5699*7c478bd9Sstevel@tonic-gate */ 5700*7c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, 5701*7c478bd9Sstevel@tonic-gate ior->Attributes2, 5702*7c478bd9Sstevel@tonic-gate &client->io_alloc.Window2)) != 5703*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 5704*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5705*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 5706*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5707*7c478bd9Sstevel@tonic-gate ( 5708*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5709*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5710*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5711*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5712*7c478bd9Sstevel@tonic-gate return (error); 5713*7c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(2)) */ 5714*7c478bd9Sstevel@tonic-gate /* 5715*7c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 5716*7c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 5717*7c478bd9Sstevel@tonic-gate */ 5718*7c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 5719*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 5720*7c478bd9Sstevel@tonic-gate &baseaddru, 5721*7c478bd9Sstevel@tonic-gate &ior->NumPorts2, 5722*7c478bd9Sstevel@tonic-gate ior->IOAddrLines, 5723*7c478bd9Sstevel@tonic-gate ior->Attributes2)) != 5724*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 5725*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5726*7c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 5727*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5728*7c478bd9Sstevel@tonic-gate ( 5729*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5730*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5731*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 5732*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 5733*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5734*7c478bd9Sstevel@tonic-gate ( 5735*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5736*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5737*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5738*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5739*7c478bd9Sstevel@tonic-gate return (error); 5740*7c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(2)) */ 5741*7c478bd9Sstevel@tonic-gate 5742*7c478bd9Sstevel@tonic-gate ior->BasePort2.handle = (acc_handle_t)baseaddru.handle; 5743*7c478bd9Sstevel@tonic-gate ior->BasePort2.base = baseaddru.base; 5744*7c478bd9Sstevel@tonic-gate 5745*7c478bd9Sstevel@tonic-gate } else { 5746*7c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 5747*7c478bd9Sstevel@tonic-gate } /* if (ior->NumPorts2) */ 5748*7c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 5749*7c478bd9Sstevel@tonic-gate 5750*7c478bd9Sstevel@tonic-gate /* 5751*7c478bd9Sstevel@tonic-gate * Save a copy of the client's port information so that we 5752*7c478bd9Sstevel@tonic-gate * can use it in the RequestConfiguration call. We set 5753*7c478bd9Sstevel@tonic-gate * the IO window number(s) allocated in the respective 5754*7c478bd9Sstevel@tonic-gate * section of code, above. 5755*7c478bd9Sstevel@tonic-gate */ 5756*7c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.base = ior->BasePort1.base; 5757*7c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.handle = ior->BasePort1.handle; 5758*7c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts1 = ior->NumPorts1; 5759*7c478bd9Sstevel@tonic-gate client->io_alloc.Attributes1 = ior->Attributes1; 5760*7c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.base = ior->BasePort2.base; 5761*7c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.handle = ior->BasePort2.handle; 5762*7c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2 = ior->NumPorts2; 5763*7c478bd9Sstevel@tonic-gate client->io_alloc.Attributes2 = ior->Attributes2; 5764*7c478bd9Sstevel@tonic-gate client->io_alloc.IOAddrLines = ior->IOAddrLines; 5765*7c478bd9Sstevel@tonic-gate 5766*7c478bd9Sstevel@tonic-gate /* 5767*7c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIO call. 5768*7c478bd9Sstevel@tonic-gate */ 5769*7c478bd9Sstevel@tonic-gate client->flags |= (REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5770*7c478bd9Sstevel@tonic-gate 5771*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5772*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5773*7c478bd9Sstevel@tonic-gate 5774*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5775*7c478bd9Sstevel@tonic-gate } 5776*7c478bd9Sstevel@tonic-gate 5777*7c478bd9Sstevel@tonic-gate /* 5778*7c478bd9Sstevel@tonic-gate * cs_release_io - releases IO resources allocated by RequestIO; this is 5779*7c478bd9Sstevel@tonic-gate * ReleaseIO 5780*7c478bd9Sstevel@tonic-gate * 5781*7c478bd9Sstevel@tonic-gate * calling: cs_release_io(client_handle_t, io_req_t *) 5782*7c478bd9Sstevel@tonic-gate * 5783*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources sucessfully deallocated 5784*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 5785*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 5786*7c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 5787*7c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 5788*7c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIO has been done 5789*7c478bd9Sstevel@tonic-gate */ 5790*7c478bd9Sstevel@tonic-gate static int 5791*7c478bd9Sstevel@tonic-gate cs_release_io(client_handle_t client_handle, io_req_t *ior) 5792*7c478bd9Sstevel@tonic-gate { 5793*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 5794*7c478bd9Sstevel@tonic-gate client_t *client; 5795*7c478bd9Sstevel@tonic-gate int error; 5796*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 5797*7c478bd9Sstevel@tonic-gate uint32_t socket_num; 5798*7c478bd9Sstevel@tonic-gate 5799*7c478bd9Sstevel@tonic-gate #ifdef lint 5800*7c478bd9Sstevel@tonic-gate ior = NULL; 5801*7c478bd9Sstevel@tonic-gate #endif 5802*7c478bd9Sstevel@tonic-gate 5803*7c478bd9Sstevel@tonic-gate /* 5804*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 5805*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 5806*7c478bd9Sstevel@tonic-gate */ 5807*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 5808*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 5809*7c478bd9Sstevel@tonic-gate 5810*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 5811*7c478bd9Sstevel@tonic-gate 5812*7c478bd9Sstevel@tonic-gate /* 5813*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 5814*7c478bd9Sstevel@tonic-gate */ 5815*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 5816*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 5817*7c478bd9Sstevel@tonic-gate 5818*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 5819*7c478bd9Sstevel@tonic-gate 5820*7c478bd9Sstevel@tonic-gate /* 5821*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 5822*7c478bd9Sstevel@tonic-gate */ 5823*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 5824*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5825*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5826*7c478bd9Sstevel@tonic-gate return (error); 5827*7c478bd9Sstevel@tonic-gate } 5828*7c478bd9Sstevel@tonic-gate 5829*7c478bd9Sstevel@tonic-gate /* 5830*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 5831*7c478bd9Sstevel@tonic-gate * this call. 5832*7c478bd9Sstevel@tonic-gate */ 5833*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 5834*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5835*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5836*7c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 5837*7c478bd9Sstevel@tonic-gate } 5838*7c478bd9Sstevel@tonic-gate 5839*7c478bd9Sstevel@tonic-gate /* 5840*7c478bd9Sstevel@tonic-gate * If RequestIO has not been done, we don't allow this call. 5841*7c478bd9Sstevel@tonic-gate */ 5842*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IO_DONE)) { 5843*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5844*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5845*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 5846*7c478bd9Sstevel@tonic-gate } 5847*7c478bd9Sstevel@tonic-gate 5848*7c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 5849*7c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 5850*7c478bd9Sstevel@tonic-gate 5851*7c478bd9Sstevel@tonic-gate #ifdef XXX 5852*7c478bd9Sstevel@tonic-gate /* 5853*7c478bd9Sstevel@tonic-gate * Check the passed IO allocation with the stored allocation; if 5854*7c478bd9Sstevel@tonic-gate * they don't match, then return an error. 5855*7c478bd9Sstevel@tonic-gate */ 5856*7c478bd9Sstevel@tonic-gate if ((client->io_alloc.BasePort1 != ior->BasePort1) || 5857*7c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts1 != ior->NumPorts1) || 5858*7c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes1 != ior->Attributes1) || 5859*7c478bd9Sstevel@tonic-gate (client->io_alloc.BasePort2 != ior->BasePort2) || 5860*7c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts2 != ior->NumPorts2) || 5861*7c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes2 != ior->Attributes2) || 5862*7c478bd9Sstevel@tonic-gate (client->io_alloc.IOAddrLines != ior->IOAddrLines)) { 5863*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5864*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5865*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 5866*7c478bd9Sstevel@tonic-gate } 5867*7c478bd9Sstevel@tonic-gate #endif 5868*7c478bd9Sstevel@tonic-gate 5869*7c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5870*7c478bd9Sstevel@tonic-gate /* 5871*7c478bd9Sstevel@tonic-gate * The code diverges here depending on if this socket supports 5872*7c478bd9Sstevel@tonic-gate * memory mapped IO windows or not. See comments in the 5873*7c478bd9Sstevel@tonic-gate * cs_request_io function for a description of what's 5874*7c478bd9Sstevel@tonic-gate * going on here. 5875*7c478bd9Sstevel@tonic-gate */ 5876*7c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 5877*7c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 5878*7c478bd9Sstevel@tonic-gate 5879*7c478bd9Sstevel@tonic-gate /* 5880*7c478bd9Sstevel@tonic-gate * We should never see this; if we do, it's an internal 5881*7c478bd9Sstevel@tonic-gate * consistency error. 5882*7c478bd9Sstevel@tonic-gate */ 5883*7c478bd9Sstevel@tonic-gate if (!imw->count) { 5884*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_io: socket %d !imw->count\n", 5885*7c478bd9Sstevel@tonic-gate sp->socket_num); 5886*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5887*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5888*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 5889*7c478bd9Sstevel@tonic-gate } 5890*7c478bd9Sstevel@tonic-gate 5891*7c478bd9Sstevel@tonic-gate /* 5892*7c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 5893*7c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller, 5894*7c478bd9Sstevel@tonic-gate * so it's OK to unconditionally free the handle here. 5895*7c478bd9Sstevel@tonic-gate */ 5896*7c478bd9Sstevel@tonic-gate csx_FreeHandle(&ior->BasePort1.handle); 5897*7c478bd9Sstevel@tonic-gate 5898*7c478bd9Sstevel@tonic-gate /* 5899*7c478bd9Sstevel@tonic-gate * If the IO window referance count is zero, then deallocate 5900*7c478bd9Sstevel@tonic-gate * and disable this window. 5901*7c478bd9Sstevel@tonic-gate */ 5902*7c478bd9Sstevel@tonic-gate if (!--(imw->count)) { 5903*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, NULL, 5904*7c478bd9Sstevel@tonic-gate NULL, NULL, 5905*7c478bd9Sstevel@tonic-gate ( 5906*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5907*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5908*7c478bd9Sstevel@tonic-gate } /* if (imw->count) */ 5909*7c478bd9Sstevel@tonic-gate } else { 5910*7c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5911*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5912*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5913*7c478bd9Sstevel@tonic-gate ( 5914*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5915*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5916*7c478bd9Sstevel@tonic-gate if (client->io_alloc.Window2 != PCMCIA_MAX_WINDOWS) 5917*7c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window2, 5918*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 5919*7c478bd9Sstevel@tonic-gate ( 5920*7c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 5921*7c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 5922*7c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 5923*7c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 5924*7c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 5925*7c478bd9Sstevel@tonic-gate 5926*7c478bd9Sstevel@tonic-gate /* 5927*7c478bd9Sstevel@tonic-gate * Mark the client as not having any IO resources allocated. 5928*7c478bd9Sstevel@tonic-gate */ 5929*7c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IO_DONE | CLIENT_IO_ALLOCATED); 5930*7c478bd9Sstevel@tonic-gate 5931*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 5932*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 5933*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5934*7c478bd9Sstevel@tonic-gate } 5935*7c478bd9Sstevel@tonic-gate 5936*7c478bd9Sstevel@tonic-gate /* 5937*7c478bd9Sstevel@tonic-gate * cs_find_io_win - finds an IO window that matches the parameters specified 5938*7c478bd9Sstevel@tonic-gate * in the flags argument 5939*7c478bd9Sstevel@tonic-gate * 5940*7c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for IO window on 5941*7c478bd9Sstevel@tonic-gate * *iwc - other window characteristics to match 5942*7c478bd9Sstevel@tonic-gate * *assigned_window - pointer to where we return the assigned 5943*7c478bd9Sstevel@tonic-gate * window number if we found a window or 5944*7c478bd9Sstevel@tonic-gate * undefined otherwise 5945*7c478bd9Sstevel@tonic-gate * *size - if non-NULL, the found window size will be stored here 5946*7c478bd9Sstevel@tonic-gate * 5947*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO window found 5948*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 5949*7c478bd9Sstevel@tonic-gate */ 5950*7c478bd9Sstevel@tonic-gate static int 5951*7c478bd9Sstevel@tonic-gate cs_find_io_win(uint32_t sn, iowin_char_t *iwc, uint32_t *assigned_window, 5952*7c478bd9Sstevel@tonic-gate uint32_t *size) 5953*7c478bd9Sstevel@tonic-gate { 5954*7c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 5955*7c478bd9Sstevel@tonic-gate unsigned wn; 5956*7c478bd9Sstevel@tonic-gate 5957*7c478bd9Sstevel@tonic-gate iw = &inquire_window; 5958*7c478bd9Sstevel@tonic-gate 5959*7c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 5960*7c478bd9Sstevel@tonic-gate iowin_char_t *iowc; 5961*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 5962*7c478bd9Sstevel@tonic-gate 5963*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 5964*7c478bd9Sstevel@tonic-gate 5965*7c478bd9Sstevel@tonic-gate iw->window = wn; 5966*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 5967*7c478bd9Sstevel@tonic-gate 5968*7c478bd9Sstevel@tonic-gate iowc = &iw->iowin_char; 5969*7c478bd9Sstevel@tonic-gate 5970*7c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 5971*7c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_IO(cw) && 5972*7c478bd9Sstevel@tonic-gate (iw->WndCaps & WC_IO) && 5973*7c478bd9Sstevel@tonic-gate ((iowc->IOWndCaps & iwc->IOWndCaps) == iwc->IOWndCaps)) { 5974*7c478bd9Sstevel@tonic-gate 5975*7c478bd9Sstevel@tonic-gate *assigned_window = wn; 5976*7c478bd9Sstevel@tonic-gate 5977*7c478bd9Sstevel@tonic-gate if (size) 5978*7c478bd9Sstevel@tonic-gate *size = iw->iowin_char.ReqGran; 5979*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5980*7c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 5981*7c478bd9Sstevel@tonic-gate } /* cs_get_wp */ 5982*7c478bd9Sstevel@tonic-gate } /* for (wn) */ 5983*7c478bd9Sstevel@tonic-gate 5984*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 5985*7c478bd9Sstevel@tonic-gate } 5986*7c478bd9Sstevel@tonic-gate 5987*7c478bd9Sstevel@tonic-gate /* 5988*7c478bd9Sstevel@tonic-gate * cs_allocate_io_win - finds and allocates an IO window 5989*7c478bd9Sstevel@tonic-gate * 5990*7c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for window on 5991*7c478bd9Sstevel@tonic-gate * Attributes - window attributes in io_req_t.Attributes format 5992*7c478bd9Sstevel@tonic-gate * *assigned_window - pointer to return assigned window number 5993*7c478bd9Sstevel@tonic-gate * 5994*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - IO window found and allocated 5995*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if cs_find_io_win couldn't find a 5996*7c478bd9Sstevel@tonic-gate * window that matches the passed criteria 5997*7c478bd9Sstevel@tonic-gate * 5998*7c478bd9Sstevel@tonic-gate * Note: This fucntion will find and allocate an IO window. The caller is 5999*7c478bd9Sstevel@tonic-gate * responsible for deallocating the window. 6000*7c478bd9Sstevel@tonic-gate */ 6001*7c478bd9Sstevel@tonic-gate static int 6002*7c478bd9Sstevel@tonic-gate cs_allocate_io_win(uint32_t sn, uint32_t Attributes, uint32_t *assigned_window) 6003*7c478bd9Sstevel@tonic-gate { 6004*7c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 6005*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 6006*7c478bd9Sstevel@tonic-gate 6007*7c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = 6008*7c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WC_16BIT:WC_8BIT); 6009*7c478bd9Sstevel@tonic-gate 6010*7c478bd9Sstevel@tonic-gate if (cs_find_io_win(sn, &iowin_char, assigned_window, NULL) == 6011*7c478bd9Sstevel@tonic-gate CS_SUCCESS) { 6012*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(*assigned_window)) == NULL) 6013*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 6014*7c478bd9Sstevel@tonic-gate 6015*7c478bd9Sstevel@tonic-gate cw->state = (cw->state & CW_WINDOW_VALID) | (CW_ALLOCATED | CW_IO); 6016*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6017*7c478bd9Sstevel@tonic-gate } 6018*7c478bd9Sstevel@tonic-gate 6019*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 6020*7c478bd9Sstevel@tonic-gate } 6021*7c478bd9Sstevel@tonic-gate 6022*7c478bd9Sstevel@tonic-gate /* 6023*7c478bd9Sstevel@tonic-gate * cs_setup_io_win - setup and destroy an IO window 6024*7c478bd9Sstevel@tonic-gate * 6025*7c478bd9Sstevel@tonic-gate * calling: sn - socket number 6026*7c478bd9Sstevel@tonic-gate * wn - window number 6027*7c478bd9Sstevel@tonic-gate * XXX Base - pointer to XXX 6028*7c478bd9Sstevel@tonic-gate * *NumPorts - pointer to number of allocated ports to return 6029*7c478bd9Sstevel@tonic-gate * IOAddrLines - number of IO address lines decoded by this card 6030*7c478bd9Sstevel@tonic-gate * Attributes - either io_req_t attributes, or a combination of 6031*7c478bd9Sstevel@tonic-gate * the following flags: 6032*7c478bd9Sstevel@tonic-gate * IO_DEALLOCATE_WINDOW - deallocate the window 6033*7c478bd9Sstevel@tonic-gate * IO_DISABLE_WINDOW - disable the window 6034*7c478bd9Sstevel@tonic-gate * When either of these two flags are set, *Base 6035*7c478bd9Sstevel@tonic-gate * and NumPorts should be NULL. 6036*7c478bd9Sstevel@tonic-gate * 6037*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if no failure 6038*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if error while trying to configure window 6039*7c478bd9Sstevel@tonic-gate * 6040*7c478bd9Sstevel@tonic-gate * Note: We use the IOAddrLines value to determine what base address to pass 6041*7c478bd9Sstevel@tonic-gate * to Socket Services. 6042*7c478bd9Sstevel@tonic-gate */ 6043*7c478bd9Sstevel@tonic-gate static int 6044*7c478bd9Sstevel@tonic-gate cs_setup_io_win(uint32_t sn, uint32_t wn, baseaddru_t *Base, uint32_t *NumPorts, 6045*7c478bd9Sstevel@tonic-gate uint32_t IOAddrLines, uint32_t Attributes) 6046*7c478bd9Sstevel@tonic-gate { 6047*7c478bd9Sstevel@tonic-gate set_window_t set_window; 6048*7c478bd9Sstevel@tonic-gate 6049*7c478bd9Sstevel@tonic-gate if (Attributes & (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW)) { 6050*7c478bd9Sstevel@tonic-gate 6051*7c478bd9Sstevel@tonic-gate if (Attributes & IO_DEALLOCATE_WINDOW) { 6052*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 6053*7c478bd9Sstevel@tonic-gate 6054*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) == NULL) 6055*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 6056*7c478bd9Sstevel@tonic-gate cw->state &= CW_WINDOW_VALID; 6057*7c478bd9Sstevel@tonic-gate 6058*7c478bd9Sstevel@tonic-gate } /* IO_DEALLOCATE_WINDOW */ 6059*7c478bd9Sstevel@tonic-gate 6060*7c478bd9Sstevel@tonic-gate if (Attributes & IO_DISABLE_WINDOW) { 6061*7c478bd9Sstevel@tonic-gate get_window_t get_window; 6062*7c478bd9Sstevel@tonic-gate 6063*7c478bd9Sstevel@tonic-gate get_window.window = wn; 6064*7c478bd9Sstevel@tonic-gate 6065*7c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &get_window); 6066*7c478bd9Sstevel@tonic-gate 6067*7c478bd9Sstevel@tonic-gate set_window.socket = get_window.socket; 6068*7c478bd9Sstevel@tonic-gate set_window.window = get_window.window; 6069*7c478bd9Sstevel@tonic-gate set_window.speed = get_window.speed; 6070*7c478bd9Sstevel@tonic-gate set_window.base = 0; 6071*7c478bd9Sstevel@tonic-gate set_window.WindowSize = get_window.size; 6072*7c478bd9Sstevel@tonic-gate set_window.state = get_window.state & ~WS_ENABLED; 6073*7c478bd9Sstevel@tonic-gate 6074*7c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 6075*7c478bd9Sstevel@tonic-gate 6076*7c478bd9Sstevel@tonic-gate SocketServices(SS_SetWindow, &set_window); 6077*7c478bd9Sstevel@tonic-gate } /* IO_DISABLE_WINDOW */ 6078*7c478bd9Sstevel@tonic-gate 6079*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6080*7c478bd9Sstevel@tonic-gate 6081*7c478bd9Sstevel@tonic-gate } /* if (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW) */ 6082*7c478bd9Sstevel@tonic-gate 6083*7c478bd9Sstevel@tonic-gate /* 6084*7c478bd9Sstevel@tonic-gate * See if we can allow Socket Services to select the base address 6085*7c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 6086*7c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 6087*7c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 6088*7c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 6089*7c478bd9Sstevel@tonic-gate * XXX - Is this really correct in all cases? 6090*7c478bd9Sstevel@tonic-gate */ 6091*7c478bd9Sstevel@tonic-gate if (!IOAddrLines) 6092*7c478bd9Sstevel@tonic-gate Base->base = 0; 6093*7c478bd9Sstevel@tonic-gate else 6094*7c478bd9Sstevel@tonic-gate Base->base = IOADDR_FROBNITZ(Base->base, IOAddrLines); 6095*7c478bd9Sstevel@tonic-gate 6096*7c478bd9Sstevel@tonic-gate set_window.socket = sn; 6097*7c478bd9Sstevel@tonic-gate set_window.window = wn; 6098*7c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 6099*7c478bd9Sstevel@tonic-gate set_window.base = Base->base; 6100*7c478bd9Sstevel@tonic-gate set_window.WindowSize = *NumPorts; 6101*7c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_IO | 6102*7c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WS_16BIT:0)); 6103*7c478bd9Sstevel@tonic-gate 6104*7c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 6105*7c478bd9Sstevel@tonic-gate 6106*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) 6107*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 6108*7c478bd9Sstevel@tonic-gate 6109*7c478bd9Sstevel@tonic-gate Base->base = set_window.base; 6110*7c478bd9Sstevel@tonic-gate Base->handle = set_window.handle; 6111*7c478bd9Sstevel@tonic-gate *NumPorts = set_window.WindowSize; 6112*7c478bd9Sstevel@tonic-gate 6113*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6114*7c478bd9Sstevel@tonic-gate } 6115*7c478bd9Sstevel@tonic-gate 6116*7c478bd9Sstevel@tonic-gate /* 6117*7c478bd9Sstevel@tonic-gate * ==== IRQ handling functions ==== 6118*7c478bd9Sstevel@tonic-gate */ 6119*7c478bd9Sstevel@tonic-gate 6120*7c478bd9Sstevel@tonic-gate /* 6121*7c478bd9Sstevel@tonic-gate * cs_request_irq - add's client's IRQ handler; supports RequestIRQ 6122*7c478bd9Sstevel@tonic-gate * 6123*7c478bd9Sstevel@tonic-gate * calling: irq_req_t.Attributes - must have the IRQ_TYPE_EXCLUSIVE 6124*7c478bd9Sstevel@tonic-gate * flag set, and all other flags clear, or 6125*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE will be returned 6126*7c478bd9Sstevel@tonic-gate * 6127*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources available for client 6128*7c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be allocated 6129*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 6130*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6131*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 6132*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 6133*7c478bd9Sstevel@tonic-gate * flags are set 6134*7c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6135*7c478bd9Sstevel@tonic-gate * already been done 6136*7c478bd9Sstevel@tonic-gate * CS_IN_USE - IRQ ports already in use or function has 6137*7c478bd9Sstevel@tonic-gate * already been called 6138*7c478bd9Sstevel@tonic-gate * 6139*7c478bd9Sstevel@tonic-gate * Note: We only allow level-mode interrupts. 6140*7c478bd9Sstevel@tonic-gate */ 6141*7c478bd9Sstevel@tonic-gate static int 6142*7c478bd9Sstevel@tonic-gate cs_request_irq(client_handle_t client_handle, irq_req_t *irqr) 6143*7c478bd9Sstevel@tonic-gate { 6144*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 6145*7c478bd9Sstevel@tonic-gate client_t *client; 6146*7c478bd9Sstevel@tonic-gate set_irq_handler_t set_irq_handler; 6147*7c478bd9Sstevel@tonic-gate int error; 6148*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 6149*7c478bd9Sstevel@tonic-gate 6150*7c478bd9Sstevel@tonic-gate /* 6151*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6152*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 6153*7c478bd9Sstevel@tonic-gate */ 6154*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6155*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6156*7c478bd9Sstevel@tonic-gate 6157*7c478bd9Sstevel@tonic-gate /* 6158*7c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 6159*7c478bd9Sstevel@tonic-gate */ 6160*7c478bd9Sstevel@tonic-gate if ((irqr->Attributes & (IRQ_TYPE_TIME | IRQ_TYPE_DYNAMIC_SHARING | 6161*7c478bd9Sstevel@tonic-gate IRQ_FIRST_SHARED | IRQ_PULSE_ALLOCATED | 6162*7c478bd9Sstevel@tonic-gate IRQ_FORCED_PULSE)) || 6163*7c478bd9Sstevel@tonic-gate !(irqr->Attributes & IRQ_TYPE_EXCLUSIVE)) 6164*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 6165*7c478bd9Sstevel@tonic-gate 6166*7c478bd9Sstevel@tonic-gate /* 6167*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6168*7c478bd9Sstevel@tonic-gate */ 6169*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6170*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6171*7c478bd9Sstevel@tonic-gate 6172*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6173*7c478bd9Sstevel@tonic-gate 6174*7c478bd9Sstevel@tonic-gate /* 6175*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 6176*7c478bd9Sstevel@tonic-gate */ 6177*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6178*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6179*7c478bd9Sstevel@tonic-gate return (error); 6180*7c478bd9Sstevel@tonic-gate } 6181*7c478bd9Sstevel@tonic-gate 6182*7c478bd9Sstevel@tonic-gate /* 6183*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6184*7c478bd9Sstevel@tonic-gate * this call. 6185*7c478bd9Sstevel@tonic-gate */ 6186*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6187*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6188*7c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6189*7c478bd9Sstevel@tonic-gate } 6190*7c478bd9Sstevel@tonic-gate 6191*7c478bd9Sstevel@tonic-gate /* 6192*7c478bd9Sstevel@tonic-gate * If RequestIRQ has already been done, we don't allow this call. 6193*7c478bd9Sstevel@tonic-gate */ 6194*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_IRQ_DONE) { 6195*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6196*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 6197*7c478bd9Sstevel@tonic-gate } 6198*7c478bd9Sstevel@tonic-gate 6199*7c478bd9Sstevel@tonic-gate /* 6200*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 6201*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 6202*7c478bd9Sstevel@tonic-gate */ 6203*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 6204*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6205*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 6206*7c478bd9Sstevel@tonic-gate } 6207*7c478bd9Sstevel@tonic-gate 6208*7c478bd9Sstevel@tonic-gate /* 6209*7c478bd9Sstevel@tonic-gate * Set up the parameters and ask Socket Services to give us an IRQ 6210*7c478bd9Sstevel@tonic-gate * for this client. We don't really do much, since the IRQ 6211*7c478bd9Sstevel@tonic-gate * resources are managed by SS and the kernel. We also don't 6212*7c478bd9Sstevel@tonic-gate * care which IRQ level we are given. 6213*7c478bd9Sstevel@tonic-gate */ 6214*7c478bd9Sstevel@tonic-gate set_irq_handler.socket = 6215*7c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6216*7c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 6217*7c478bd9Sstevel@tonic-gate set_irq_handler.irq = IRQ_ANY; 6218*7c478bd9Sstevel@tonic-gate 6219*7c478bd9Sstevel@tonic-gate set_irq_handler.handler_id = client_handle; 6220*7c478bd9Sstevel@tonic-gate set_irq_handler.handler = (f_t *)irqr->irq_handler; 6221*7c478bd9Sstevel@tonic-gate set_irq_handler.arg1 = irqr->irq_handler_arg; 6222*7c478bd9Sstevel@tonic-gate set_irq_handler.arg2 = NULL; 6223*7c478bd9Sstevel@tonic-gate 6224*7c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_SetIRQHandler, 6225*7c478bd9Sstevel@tonic-gate &set_irq_handler)) != SUCCESS) { 6226*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6227*7c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 6228*7c478bd9Sstevel@tonic-gate } 6229*7c478bd9Sstevel@tonic-gate 6230*7c478bd9Sstevel@tonic-gate irqr->iblk_cookie = set_irq_handler.iblk_cookie; 6231*7c478bd9Sstevel@tonic-gate irqr->idev_cookie = set_irq_handler.idev_cookie; 6232*7c478bd9Sstevel@tonic-gate 6233*7c478bd9Sstevel@tonic-gate /* 6234*7c478bd9Sstevel@tonic-gate * Save the allocated IRQ information for this client. 6235*7c478bd9Sstevel@tonic-gate */ 6236*7c478bd9Sstevel@tonic-gate client->irq_alloc.Attributes = irqr->Attributes; 6237*7c478bd9Sstevel@tonic-gate client->irq_alloc.irq = set_irq_handler.irq; 6238*7c478bd9Sstevel@tonic-gate client->irq_alloc.handler_id = set_irq_handler.handler_id; 6239*7c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler = (f_t *)set_irq_handler.handler; 6240*7c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg1 = set_irq_handler.arg1; 6241*7c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg2 = set_irq_handler.arg2; 6242*7c478bd9Sstevel@tonic-gate 6243*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 6244*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 6245*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_irq: socket %d irqr->Attributes 0x%x " 6246*7c478bd9Sstevel@tonic-gate "set_irq_handler.irq 0x%x\n", 6247*7c478bd9Sstevel@tonic-gate sp->socket_num, 6248*7c478bd9Sstevel@tonic-gate (int)irqr->Attributes, 6249*7c478bd9Sstevel@tonic-gate set_irq_handler.irq); 6250*7c478bd9Sstevel@tonic-gate #endif 6251*7c478bd9Sstevel@tonic-gate 6252*7c478bd9Sstevel@tonic-gate /* 6253*7c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIRQ call. 6254*7c478bd9Sstevel@tonic-gate */ 6255*7c478bd9Sstevel@tonic-gate client->flags |= (REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6256*7c478bd9Sstevel@tonic-gate 6257*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6258*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6259*7c478bd9Sstevel@tonic-gate } 6260*7c478bd9Sstevel@tonic-gate 6261*7c478bd9Sstevel@tonic-gate /* 6262*7c478bd9Sstevel@tonic-gate * cs_release_irq - releases IRQ resources allocated by RequestIRQ; this is 6263*7c478bd9Sstevel@tonic-gate * ReleaseIRQ 6264*7c478bd9Sstevel@tonic-gate * 6265*7c478bd9Sstevel@tonic-gate * calling: cs_release_irq(client_handle_t, irq_req_t *) 6266*7c478bd9Sstevel@tonic-gate * 6267*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources sucessfully deallocated 6268*7c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be deallocated 6269*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 6270*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6271*7c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 6272*7c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 6273*7c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIRQ has been done 6274*7c478bd9Sstevel@tonic-gate */ 6275*7c478bd9Sstevel@tonic-gate static int 6276*7c478bd9Sstevel@tonic-gate cs_release_irq(client_handle_t client_handle, irq_req_t *irqr) 6277*7c478bd9Sstevel@tonic-gate { 6278*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 6279*7c478bd9Sstevel@tonic-gate client_t *client; 6280*7c478bd9Sstevel@tonic-gate clear_irq_handler_t clear_irq_handler; 6281*7c478bd9Sstevel@tonic-gate int error; 6282*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 6283*7c478bd9Sstevel@tonic-gate 6284*7c478bd9Sstevel@tonic-gate #ifdef lint 6285*7c478bd9Sstevel@tonic-gate irqr = NULL; 6286*7c478bd9Sstevel@tonic-gate #endif 6287*7c478bd9Sstevel@tonic-gate 6288*7c478bd9Sstevel@tonic-gate /* 6289*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6290*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 6291*7c478bd9Sstevel@tonic-gate */ 6292*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6293*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6294*7c478bd9Sstevel@tonic-gate 6295*7c478bd9Sstevel@tonic-gate /* 6296*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6297*7c478bd9Sstevel@tonic-gate */ 6298*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6299*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6300*7c478bd9Sstevel@tonic-gate 6301*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6302*7c478bd9Sstevel@tonic-gate 6303*7c478bd9Sstevel@tonic-gate /* 6304*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 6305*7c478bd9Sstevel@tonic-gate */ 6306*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6307*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6308*7c478bd9Sstevel@tonic-gate return (error); 6309*7c478bd9Sstevel@tonic-gate } 6310*7c478bd9Sstevel@tonic-gate 6311*7c478bd9Sstevel@tonic-gate /* 6312*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6313*7c478bd9Sstevel@tonic-gate * this call. 6314*7c478bd9Sstevel@tonic-gate */ 6315*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6316*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6317*7c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6318*7c478bd9Sstevel@tonic-gate } 6319*7c478bd9Sstevel@tonic-gate 6320*7c478bd9Sstevel@tonic-gate /* 6321*7c478bd9Sstevel@tonic-gate * If RequestIRQ has not been done, we don't allow this call. 6322*7c478bd9Sstevel@tonic-gate */ 6323*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IRQ_DONE)) { 6324*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6325*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 6326*7c478bd9Sstevel@tonic-gate } 6327*7c478bd9Sstevel@tonic-gate 6328*7c478bd9Sstevel@tonic-gate /* 6329*7c478bd9Sstevel@tonic-gate * Tell Socket Services that we want to deregister this client's 6330*7c478bd9Sstevel@tonic-gate * IRQ handler. 6331*7c478bd9Sstevel@tonic-gate */ 6332*7c478bd9Sstevel@tonic-gate clear_irq_handler.socket = 6333*7c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 6334*7c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 6335*7c478bd9Sstevel@tonic-gate clear_irq_handler.handler_id = client->irq_alloc.handler_id; 6336*7c478bd9Sstevel@tonic-gate clear_irq_handler.handler = (f_t *)client->irq_alloc.irq_handler; 6337*7c478bd9Sstevel@tonic-gate 6338*7c478bd9Sstevel@tonic-gate /* 6339*7c478bd9Sstevel@tonic-gate * At this point, we should never fail this SS call; if we do, it 6340*7c478bd9Sstevel@tonic-gate * means that there is an internal consistancy error in either 6341*7c478bd9Sstevel@tonic-gate * Card Services or Socket Services. 6342*7c478bd9Sstevel@tonic-gate */ 6343*7c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_ClearIRQHandler, &clear_irq_handler)) != 6344*7c478bd9Sstevel@tonic-gate SUCCESS) { 6345*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6346*7c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 6347*7c478bd9Sstevel@tonic-gate } 6348*7c478bd9Sstevel@tonic-gate 6349*7c478bd9Sstevel@tonic-gate /* 6350*7c478bd9Sstevel@tonic-gate * Mark the client as not having any IRQ resources allocated. 6351*7c478bd9Sstevel@tonic-gate */ 6352*7c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 6353*7c478bd9Sstevel@tonic-gate 6354*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6355*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6356*7c478bd9Sstevel@tonic-gate } 6357*7c478bd9Sstevel@tonic-gate 6358*7c478bd9Sstevel@tonic-gate /* 6359*7c478bd9Sstevel@tonic-gate * ==== configuration handling functions ==== 6360*7c478bd9Sstevel@tonic-gate */ 6361*7c478bd9Sstevel@tonic-gate 6362*7c478bd9Sstevel@tonic-gate /* 6363*7c478bd9Sstevel@tonic-gate * cs_request_configuration - sets up socket and card configuration on behalf 6364*7c478bd9Sstevel@tonic-gate * of the client; this is RequestConfiguration 6365*7c478bd9Sstevel@tonic-gate * 6366*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully set 6367*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6368*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6369*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6370*7c478bd9Sstevel@tonic-gate * are set 6371*7c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if the socket doesn't support a mem and IO 6372*7c478bd9Sstevel@tonic-gate * interface (SOCKET_INTERFACE_MEMORY_AND_IO set) 6373*7c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 6374*7c478bd9Sstevel@tonic-gate * already been done 6375*7c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 6376*7c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6377*7c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6378*7c478bd9Sstevel@tonic-gate * 6379*7c478bd9Sstevel@tonic-gate * Bug ID: 1193637 - Card Services RequestConfiguration does not conform 6380*7c478bd9Sstevel@tonic-gate * to PCMCIA standard 6381*7c478bd9Sstevel@tonic-gate * We allow clients to do a RequestConfiguration even if they haven't 6382*7c478bd9Sstevel@tonic-gate * done a RequestIO or RequestIRQ. 6383*7c478bd9Sstevel@tonic-gate */ 6384*7c478bd9Sstevel@tonic-gate static int 6385*7c478bd9Sstevel@tonic-gate cs_request_configuration(client_handle_t client_handle, config_req_t *cr) 6386*7c478bd9Sstevel@tonic-gate { 6387*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 6388*7c478bd9Sstevel@tonic-gate client_t *client; 6389*7c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 6390*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 6391*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 6392*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 6393*7c478bd9Sstevel@tonic-gate int error; 6394*7c478bd9Sstevel@tonic-gate uint32_t newoffset; 6395*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 6396*7c478bd9Sstevel@tonic-gate 6397*7c478bd9Sstevel@tonic-gate /* 6398*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6399*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 6400*7c478bd9Sstevel@tonic-gate */ 6401*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6402*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6403*7c478bd9Sstevel@tonic-gate 6404*7c478bd9Sstevel@tonic-gate #ifdef XXX 6405*7c478bd9Sstevel@tonic-gate /* 6406*7c478bd9Sstevel@tonic-gate * If the client specifies Vcc = 0 and any non-zero value for 6407*7c478bd9Sstevel@tonic-gate * either of the Vpp members, that's an illegal condition. 6408*7c478bd9Sstevel@tonic-gate */ 6409*7c478bd9Sstevel@tonic-gate if (!(cr->Vcc) && (cr->Vpp1 || cr->Vpp2)) 6410*7c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 6411*7c478bd9Sstevel@tonic-gate #endif 6412*7c478bd9Sstevel@tonic-gate 6413*7c478bd9Sstevel@tonic-gate /* 6414*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6415*7c478bd9Sstevel@tonic-gate */ 6416*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6417*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6418*7c478bd9Sstevel@tonic-gate 6419*7c478bd9Sstevel@tonic-gate /* 6420*7c478bd9Sstevel@tonic-gate * If the client is asking for a memory and IO interface on this 6421*7c478bd9Sstevel@tonic-gate * socket, then check the socket capabilities to be sure that 6422*7c478bd9Sstevel@tonic-gate * this socket supports this configuration. 6423*7c478bd9Sstevel@tonic-gate */ 6424*7c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) { 6425*7c478bd9Sstevel@tonic-gate inquire_socket_t inquire_socket; 6426*7c478bd9Sstevel@tonic-gate 6427*7c478bd9Sstevel@tonic-gate inquire_socket.socket = sp->socket_num; 6428*7c478bd9Sstevel@tonic-gate 6429*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireSocket, &inquire_socket) != SUCCESS) 6430*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6431*7c478bd9Sstevel@tonic-gate 6432*7c478bd9Sstevel@tonic-gate if (!(inquire_socket.SocketCaps & IF_IO)) 6433*7c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 6434*7c478bd9Sstevel@tonic-gate 6435*7c478bd9Sstevel@tonic-gate } /* if (SOCKET_INTERFACE_MEMORY_AND_IO) */ 6436*7c478bd9Sstevel@tonic-gate 6437*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6438*7c478bd9Sstevel@tonic-gate 6439*7c478bd9Sstevel@tonic-gate /* 6440*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 6441*7c478bd9Sstevel@tonic-gate */ 6442*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6443*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6444*7c478bd9Sstevel@tonic-gate return (error); 6445*7c478bd9Sstevel@tonic-gate } 6446*7c478bd9Sstevel@tonic-gate 6447*7c478bd9Sstevel@tonic-gate /* 6448*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 6449*7c478bd9Sstevel@tonic-gate * this call. 6450*7c478bd9Sstevel@tonic-gate */ 6451*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 6452*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6453*7c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 6454*7c478bd9Sstevel@tonic-gate } 6455*7c478bd9Sstevel@tonic-gate 6456*7c478bd9Sstevel@tonic-gate /* 6457*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 6458*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 6459*7c478bd9Sstevel@tonic-gate */ 6460*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 6461*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6462*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 6463*7c478bd9Sstevel@tonic-gate } 6464*7c478bd9Sstevel@tonic-gate 6465*7c478bd9Sstevel@tonic-gate /* 6466*7c478bd9Sstevel@tonic-gate * At this point, most of the client's calling parameters have been 6467*7c478bd9Sstevel@tonic-gate * validated, so we can go ahead and configure the socket and 6468*7c478bd9Sstevel@tonic-gate * the card. 6469*7c478bd9Sstevel@tonic-gate */ 6470*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 6471*7c478bd9Sstevel@tonic-gate 6472*7c478bd9Sstevel@tonic-gate /* 6473*7c478bd9Sstevel@tonic-gate * Configure the socket with the interface type and voltages requested 6474*7c478bd9Sstevel@tonic-gate * by the client. 6475*7c478bd9Sstevel@tonic-gate */ 6476*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 6477*7c478bd9Sstevel@tonic-gate 6478*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6479*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6480*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6481*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6482*7c478bd9Sstevel@tonic-gate } 6483*7c478bd9Sstevel@tonic-gate 6484*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 6485*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 6486*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d " 6487*7c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 6488*7c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 6489*7c478bd9Sstevel@tonic-gate sp->socket_num, 6490*7c478bd9Sstevel@tonic-gate (int)client->irq_alloc.irq, 6491*7c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 6492*7c478bd9Sstevel@tonic-gate #endif 6493*7c478bd9Sstevel@tonic-gate 6494*7c478bd9Sstevel@tonic-gate bzero(&set_socket, sizeof (set_socket)); 6495*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 6496*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = client->irq_alloc.irq & ~IRQ_ENABLE; 6497*7c478bd9Sstevel@tonic-gate 6498*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 6499*7c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 6500*7c478bd9Sstevel@tonic-gate 6501*7c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vcc, VCC, 6502*7c478bd9Sstevel@tonic-gate &set_socket.VccLevel) != CS_SUCCESS) { 6503*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6504*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6505*7c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 6506*7c478bd9Sstevel@tonic-gate } 6507*7c478bd9Sstevel@tonic-gate 6508*7c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp1, VPP1, 6509*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 6510*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6511*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6512*7c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 6513*7c478bd9Sstevel@tonic-gate } 6514*7c478bd9Sstevel@tonic-gate 6515*7c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp2, VPP2, 6516*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 6517*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6518*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6519*7c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 6520*7c478bd9Sstevel@tonic-gate } 6521*7c478bd9Sstevel@tonic-gate 6522*7c478bd9Sstevel@tonic-gate if (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) 6523*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 6524*7c478bd9Sstevel@tonic-gate else { 6525*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_IO; 6526*7c478bd9Sstevel@tonic-gate 6527*7c478bd9Sstevel@tonic-gate /* 6528*7c478bd9Sstevel@tonic-gate * The Cirrus Logic PD6710/672X/others? adapters will write 6529*7c478bd9Sstevel@tonic-gate * protect the CIS if the socket is in MEMORY mode and the 6530*7c478bd9Sstevel@tonic-gate * WP/IOCS16 pin is true. When this happens, the CIS registers 6531*7c478bd9Sstevel@tonic-gate * will fail to be written. Go ahead and set the socket, 6532*7c478bd9Sstevel@tonic-gate * even though the event mask isn't complete yet, so we can 6533*7c478bd9Sstevel@tonic-gate * configure the adapter. Afterwards, set the socket again 6534*7c478bd9Sstevel@tonic-gate * to make sure the event mask is correct. 6535*7c478bd9Sstevel@tonic-gate */ 6536*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6537*7c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6538*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6539*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6540*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6541*7c478bd9Sstevel@tonic-gate } 6542*7c478bd9Sstevel@tonic-gate } 6543*7c478bd9Sstevel@tonic-gate 6544*7c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 6545*7c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 6546*7c478bd9Sstevel@tonic-gate 6547*7c478bd9Sstevel@tonic-gate /* 6548*7c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 6549*7c478bd9Sstevel@tonic-gate * registers. 6550*7c478bd9Sstevel@tonic-gate */ 6551*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 6552*7c478bd9Sstevel@tonic-gate client->config_regs_offset = cr->ConfigBase; 6553*7c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 6554*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 6555*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6556*7c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 6557*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6558*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6559*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d can't init " 6560*7c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 6561*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 6562*7c478bd9Sstevel@tonic-gate } 6563*7c478bd9Sstevel@tonic-gate 6564*7c478bd9Sstevel@tonic-gate /* 6565*7c478bd9Sstevel@tonic-gate * Setup the config register pointers. 6566*7c478bd9Sstevel@tonic-gate * Note that these pointers are not the complete virtual address; 6567*7c478bd9Sstevel@tonic-gate * the complete address is constructed each time the registers 6568*7c478bd9Sstevel@tonic-gate * are accessed. 6569*7c478bd9Sstevel@tonic-gate */ 6570*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 6571*7c478bd9Sstevel@tonic-gate crt = &client->config_regs; 6572*7c478bd9Sstevel@tonic-gate client->present = cr->Present; 6573*7c478bd9Sstevel@tonic-gate 6574*7c478bd9Sstevel@tonic-gate bzero((char *)crt, sizeof (config_regs_t)); 6575*7c478bd9Sstevel@tonic-gate 6576*7c478bd9Sstevel@tonic-gate /* Configuration Option Register */ 6577*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6578*7c478bd9Sstevel@tonic-gate crt->cor_p = (newoffset + CONFIG_OPTION_REG_OFFSET); 6579*7c478bd9Sstevel@tonic-gate 6580*7c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 6581*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) 6582*7c478bd9Sstevel@tonic-gate crt->ccsr_p = (newoffset + CONFIG_STATUS_REG_OFFSET); 6583*7c478bd9Sstevel@tonic-gate 6584*7c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 6585*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) 6586*7c478bd9Sstevel@tonic-gate crt->prr_p = (newoffset + CONFIG_PINREPL_REG_OFFSET); 6587*7c478bd9Sstevel@tonic-gate 6588*7c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 6589*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) 6590*7c478bd9Sstevel@tonic-gate crt->scr_p = (newoffset + CONFIG_COPY_REG_OFFSET); 6591*7c478bd9Sstevel@tonic-gate 6592*7c478bd9Sstevel@tonic-gate /* Extended Status Register */ 6593*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) 6594*7c478bd9Sstevel@tonic-gate crt->exstat_p = (newoffset + CONFIG_EXSTAT_REG_OFFSET); 6595*7c478bd9Sstevel@tonic-gate 6596*7c478bd9Sstevel@tonic-gate /* IO Base 0 Register */ 6597*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6598*7c478bd9Sstevel@tonic-gate crt->iobase0_p = (newoffset + CONFIG_IOBASE0_REG_OFFSET); 6599*7c478bd9Sstevel@tonic-gate 6600*7c478bd9Sstevel@tonic-gate /* IO Base 1 Register */ 6601*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE1_REG_PRESENT) 6602*7c478bd9Sstevel@tonic-gate crt->iobase1_p = (newoffset + CONFIG_IOBASE1_REG_OFFSET); 6603*7c478bd9Sstevel@tonic-gate 6604*7c478bd9Sstevel@tonic-gate /* IO Base 2 Register */ 6605*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE2_REG_PRESENT) 6606*7c478bd9Sstevel@tonic-gate crt->iobase2_p = (newoffset + CONFIG_IOBASE2_REG_OFFSET); 6607*7c478bd9Sstevel@tonic-gate 6608*7c478bd9Sstevel@tonic-gate /* IO Base 3 Register */ 6609*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE3_REG_PRESENT) 6610*7c478bd9Sstevel@tonic-gate crt->iobase3_p = (newoffset + CONFIG_IOBASE3_REG_OFFSET); 6611*7c478bd9Sstevel@tonic-gate 6612*7c478bd9Sstevel@tonic-gate /* IO Limit Register */ 6613*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) 6614*7c478bd9Sstevel@tonic-gate crt->iolimit_p = (newoffset + CONFIG_IOLIMIT_REG_OFFSET); 6615*7c478bd9Sstevel@tonic-gate 6616*7c478bd9Sstevel@tonic-gate /* 6617*7c478bd9Sstevel@tonic-gate * Setup the bits in the PRR mask that are valid; this is easy, just 6618*7c478bd9Sstevel@tonic-gate * copy the Pin value that the client gave us. Note that for 6619*7c478bd9Sstevel@tonic-gate * this to work, the client must set both of the XXX_STATUS 6620*7c478bd9Sstevel@tonic-gate * and the XXX_EVENT bits in the Pin member. 6621*7c478bd9Sstevel@tonic-gate */ 6622*7c478bd9Sstevel@tonic-gate client->pin = cr->Pin; 6623*7c478bd9Sstevel@tonic-gate 6624*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 6625*7c478bd9Sstevel@tonic-gate if (cs_debug > 128) 6626*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: client->pin 0x%x " 6627*7c478bd9Sstevel@tonic-gate "client->config_regs_offset 0x%x newoffset 0x%x cor_p 0x%x " 6628*7c478bd9Sstevel@tonic-gate "ccsr_p 0x%x prr_p 0x%x scr_p 0x%x\n", 6629*7c478bd9Sstevel@tonic-gate client->pin, (int)client->config_regs_offset, newoffset, 6630*7c478bd9Sstevel@tonic-gate (int)crt->cor_p, (int)crt->ccsr_p, (int)crt->prr_p, 6631*7c478bd9Sstevel@tonic-gate (int)crt->scr_p); 6632*7c478bd9Sstevel@tonic-gate #endif 6633*7c478bd9Sstevel@tonic-gate 6634*7c478bd9Sstevel@tonic-gate /* 6635*7c478bd9Sstevel@tonic-gate * If the socket isn't in IO mode, WP is asserted, and we're going to 6636*7c478bd9Sstevel@tonic-gate * write any of the config registers, issue a warning. 6637*7c478bd9Sstevel@tonic-gate */ 6638*7c478bd9Sstevel@tonic-gate if ((client->present != 0) && 6639*7c478bd9Sstevel@tonic-gate (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) && 6640*7c478bd9Sstevel@tonic-gate (get_socket.state & SBM_WP)) { 6641*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!cs_request_configuration: attempting to " 6642*7c478bd9Sstevel@tonic-gate "write CIS config regs with WP set\n"); 6643*7c478bd9Sstevel@tonic-gate } 6644*7c478bd9Sstevel@tonic-gate 6645*7c478bd9Sstevel@tonic-gate /* 6646*7c478bd9Sstevel@tonic-gate * Write any configuration registers that the client tells us are 6647*7c478bd9Sstevel@tonic-gate * present to the card; save a copy of what we wrote so that we 6648*7c478bd9Sstevel@tonic-gate * can return them if the client calls GetConfigurationInfo. 6649*7c478bd9Sstevel@tonic-gate * The order in which we write the configuration registers is 6650*7c478bd9Sstevel@tonic-gate * specified by the PCMCIA spec; we must write the socket/copy 6651*7c478bd9Sstevel@tonic-gate * register first (if it exists), and then we can write the 6652*7c478bd9Sstevel@tonic-gate * registers in any arbitrary order. 6653*7c478bd9Sstevel@tonic-gate */ 6654*7c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 6655*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) { 6656*7c478bd9Sstevel@tonic-gate crt->scr = cr->Copy; 6657*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->scr_p, crt->scr); 6658*7c478bd9Sstevel@tonic-gate } 6659*7c478bd9Sstevel@tonic-gate 6660*7c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 6661*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 6662*7c478bd9Sstevel@tonic-gate crt->prr = cr->Pin; 6663*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->prr_p, crt->prr); 6664*7c478bd9Sstevel@tonic-gate } 6665*7c478bd9Sstevel@tonic-gate 6666*7c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 6667*7c478bd9Sstevel@tonic-gate /* XXX should we set CCSR_SIG_CHG in the CCSR? XXX */ 6668*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) { 6669*7c478bd9Sstevel@tonic-gate crt->ccsr = cr->Status; 6670*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->ccsr_p, crt->ccsr); 6671*7c478bd9Sstevel@tonic-gate } 6672*7c478bd9Sstevel@tonic-gate 6673*7c478bd9Sstevel@tonic-gate /* Extended Status Register */ 6674*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) { 6675*7c478bd9Sstevel@tonic-gate crt->exstat = cr->ExtendedStatus; 6676*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->exstat_p, crt->exstat); 6677*7c478bd9Sstevel@tonic-gate } 6678*7c478bd9Sstevel@tonic-gate 6679*7c478bd9Sstevel@tonic-gate /* 6680*7c478bd9Sstevel@tonic-gate * If any IO base and limit registers exist, and this client 6681*7c478bd9Sstevel@tonic-gate * has done a RequestIO, setup the IO Base and IO Limit 6682*7c478bd9Sstevel@tonic-gate * registers. 6683*7c478bd9Sstevel@tonic-gate */ 6684*7c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 6685*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) { 6686*7c478bd9Sstevel@tonic-gate uint32_t base = client->io_alloc.BasePort1.base; 6687*7c478bd9Sstevel@tonic-gate uint32_t present = (client->present & 6688*7c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_MASK) >> 6689*7c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_SHIFT; 6690*7c478bd9Sstevel@tonic-gate uint32_t reg = crt->iobase0_p; 6691*7c478bd9Sstevel@tonic-gate 6692*7c478bd9Sstevel@tonic-gate do { 6693*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, reg, base & 0x0ff); 6694*7c478bd9Sstevel@tonic-gate reg = reg + 2; 6695*7c478bd9Sstevel@tonic-gate base = base >> 8; 6696*7c478bd9Sstevel@tonic-gate present = present >> 1; 6697*7c478bd9Sstevel@tonic-gate } while (present); 6698*7c478bd9Sstevel@tonic-gate } /* CONFIG_IOBASE0_REG_PRESENT */ 6699*7c478bd9Sstevel@tonic-gate 6700*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) { 6701*7c478bd9Sstevel@tonic-gate uint32_t np = client->io_alloc.NumPorts1 + 6702*7c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2; 6703*7c478bd9Sstevel@tonic-gate uint32_t limit, do_bit = 0; 6704*7c478bd9Sstevel@tonic-gate int lm; 6705*7c478bd9Sstevel@tonic-gate 6706*7c478bd9Sstevel@tonic-gate limit = (IONUMPORTS_FROBNITZ(np) - 1); 6707*7c478bd9Sstevel@tonic-gate 6708*7c478bd9Sstevel@tonic-gate for (lm = 7; lm >= 0; lm--) { 6709*7c478bd9Sstevel@tonic-gate if (limit & (1 << lm)) 6710*7c478bd9Sstevel@tonic-gate do_bit = 1; 6711*7c478bd9Sstevel@tonic-gate if (do_bit) 6712*7c478bd9Sstevel@tonic-gate limit |= (1 << lm); 6713*7c478bd9Sstevel@tonic-gate } /* for */ 6714*7c478bd9Sstevel@tonic-gate 6715*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->iolimit_p, limit); 6716*7c478bd9Sstevel@tonic-gate } /* CONFIG_IOLIMIT_REG_PRESENT */ 6717*7c478bd9Sstevel@tonic-gate } /* REQ_IO_DONE */ 6718*7c478bd9Sstevel@tonic-gate 6719*7c478bd9Sstevel@tonic-gate /* 6720*7c478bd9Sstevel@tonic-gate * Mark the socket as being in IO mode. 6721*7c478bd9Sstevel@tonic-gate */ 6722*7c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) 6723*7c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_IS_IO; 6724*7c478bd9Sstevel@tonic-gate 6725*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 6726*7c478bd9Sstevel@tonic-gate 6727*7c478bd9Sstevel@tonic-gate /* 6728*7c478bd9Sstevel@tonic-gate * Enable the interrupt if needed 6729*7c478bd9Sstevel@tonic-gate */ 6730*7c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6731*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 6732*7c478bd9Sstevel@tonic-gate 6733*7c478bd9Sstevel@tonic-gate /* 6734*7c478bd9Sstevel@tonic-gate * Now that we know if the PRR is present and if it is, which 6735*7c478bd9Sstevel@tonic-gate * bits in the PRR are valid, we can construct the correct 6736*7c478bd9Sstevel@tonic-gate * socket event mask. 6737*7c478bd9Sstevel@tonic-gate */ 6738*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6739*7c478bd9Sstevel@tonic-gate 6740*7c478bd9Sstevel@tonic-gate /* 6741*7c478bd9Sstevel@tonic-gate * Configuration Option Register - we handle this specially since 6742*7c478bd9Sstevel@tonic-gate * we don't allow the client to manipulate the RESET or 6743*7c478bd9Sstevel@tonic-gate * INTERRUPT bits (although a client can manipulate these 6744*7c478bd9Sstevel@tonic-gate * bits via an AccessConfigurationRegister call - explain 6745*7c478bd9Sstevel@tonic-gate * THAT logic to me). 6746*7c478bd9Sstevel@tonic-gate * XXX - we force level-mode interrupts (COR_LEVEL_IRQ) 6747*7c478bd9Sstevel@tonic-gate * XXX - we always enable the function on a multi-function card 6748*7c478bd9Sstevel@tonic-gate */ 6749*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 6750*7c478bd9Sstevel@tonic-gate crt->cor = (cr->ConfigIndex & ~COR_SOFT_RESET) | COR_LEVEL_IRQ; 6751*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 6752*7c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_BASE_LIMIT; 6753*7c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6754*7c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_FUNCTION; 6755*7c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 6756*7c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 6757*7c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 6758*7c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 6759*7c478bd9Sstevel@tonic-gate 6760*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 6761*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 6762*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration " 6763*7c478bd9Sstevel@tonic-gate "cor=x%x ConfigIndex=x%x Attributes=x%x flags=x%x\n" 6764*7c478bd9Sstevel@tonic-gate "present=x%x cis_handle=%p cor_p=x%x\n", 6765*7c478bd9Sstevel@tonic-gate crt->cor, cr->ConfigIndex, cr->Attributes, sp->cis_flags, 6766*7c478bd9Sstevel@tonic-gate client->present, cis_handle, crt->cor_p); 6767*7c478bd9Sstevel@tonic-gate #endif 6768*7c478bd9Sstevel@tonic-gate 6769*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 6770*7c478bd9Sstevel@tonic-gate } /* CONFIG_OPTION_REG_PRESENT */ 6771*7c478bd9Sstevel@tonic-gate 6772*7c478bd9Sstevel@tonic-gate if (cs_rc1_delay) 6773*7c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc1_delay * 1000); 6774*7c478bd9Sstevel@tonic-gate 6775*7c478bd9Sstevel@tonic-gate /* 6776*7c478bd9Sstevel@tonic-gate * Set the socket to the parameters that the client requested. 6777*7c478bd9Sstevel@tonic-gate */ 6778*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6779*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 6780*7c478bd9Sstevel@tonic-gate crt->cor = 0; /* XXX is 0 the right thing here? */ 6781*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 6782*7c478bd9Sstevel@tonic-gate } 6783*7c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6784*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6785*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6786*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6787*7c478bd9Sstevel@tonic-gate } 6788*7c478bd9Sstevel@tonic-gate 6789*7c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 6790*7c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 6791*7c478bd9Sstevel@tonic-gate 6792*7c478bd9Sstevel@tonic-gate /* 6793*7c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestConfiguration 6794*7c478bd9Sstevel@tonic-gate * call. 6795*7c478bd9Sstevel@tonic-gate */ 6796*7c478bd9Sstevel@tonic-gate client->flags |= REQ_CONFIGURATION_DONE; 6797*7c478bd9Sstevel@tonic-gate 6798*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6799*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6800*7c478bd9Sstevel@tonic-gate 6801*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6802*7c478bd9Sstevel@tonic-gate } 6803*7c478bd9Sstevel@tonic-gate 6804*7c478bd9Sstevel@tonic-gate /* 6805*7c478bd9Sstevel@tonic-gate * cs_release_configuration - releases configuration previously set via the 6806*7c478bd9Sstevel@tonic-gate * RequestConfiguration call; this is ReleaseConfiguration 6807*7c478bd9Sstevel@tonic-gate * 6808*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully released 6809*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6810*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6811*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 6812*7c478bd9Sstevel@tonic-gate */ 6813*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6814*7c478bd9Sstevel@tonic-gate static int 6815*7c478bd9Sstevel@tonic-gate cs_release_configuration(client_handle_t client_handle, release_config_t *rcfg) 6816*7c478bd9Sstevel@tonic-gate { 6817*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 6818*7c478bd9Sstevel@tonic-gate client_t *client; 6819*7c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 6820*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 6821*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 6822*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 6823*7c478bd9Sstevel@tonic-gate int error; 6824*7c478bd9Sstevel@tonic-gate uint32_t newoffset; 6825*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 6826*7c478bd9Sstevel@tonic-gate 6827*7c478bd9Sstevel@tonic-gate /* 6828*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6829*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 6830*7c478bd9Sstevel@tonic-gate */ 6831*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6832*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6833*7c478bd9Sstevel@tonic-gate 6834*7c478bd9Sstevel@tonic-gate /* 6835*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6836*7c478bd9Sstevel@tonic-gate */ 6837*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6838*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6839*7c478bd9Sstevel@tonic-gate 6840*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 6841*7c478bd9Sstevel@tonic-gate 6842*7c478bd9Sstevel@tonic-gate /* 6843*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 6844*7c478bd9Sstevel@tonic-gate */ 6845*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 6846*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6847*7c478bd9Sstevel@tonic-gate return (error); 6848*7c478bd9Sstevel@tonic-gate } 6849*7c478bd9Sstevel@tonic-gate 6850*7c478bd9Sstevel@tonic-gate /* 6851*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 6852*7c478bd9Sstevel@tonic-gate * this call. 6853*7c478bd9Sstevel@tonic-gate */ 6854*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 6855*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6856*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 6857*7c478bd9Sstevel@tonic-gate } 6858*7c478bd9Sstevel@tonic-gate 6859*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 6860*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 6861*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: " 6862*7c478bd9Sstevel@tonic-gate "flags=0x%x CW_MULTI_FUNCTION_CIS =0x%x \n", 6863*7c478bd9Sstevel@tonic-gate sp->cis_flags, CW_MULTI_FUNCTION_CIS); 6864*7c478bd9Sstevel@tonic-gate 6865*7c478bd9Sstevel@tonic-gate #endif 6866*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 6867*7c478bd9Sstevel@tonic-gate 6868*7c478bd9Sstevel@tonic-gate /* 6869*7c478bd9Sstevel@tonic-gate * Set the card back to a memory-only interface byte writing a zero 6870*7c478bd9Sstevel@tonic-gate * to the COR. Note that we don't update our soft copy of the 6871*7c478bd9Sstevel@tonic-gate * COR state since the PCMCIA spec only requires us to maintain 6872*7c478bd9Sstevel@tonic-gate * the last value that was written to that register during a 6873*7c478bd9Sstevel@tonic-gate * call to RequestConfiguration. 6874*7c478bd9Sstevel@tonic-gate */ 6875*7c478bd9Sstevel@tonic-gate crt = &client->config_regs; 6876*7c478bd9Sstevel@tonic-gate 6877*7c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 6878*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 6879*7c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 6880*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6881*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6882*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: socket %d can't init " 6883*7c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 6884*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 6885*7c478bd9Sstevel@tonic-gate } 6886*7c478bd9Sstevel@tonic-gate 6887*7c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 6888*7c478bd9Sstevel@tonic-gate /* 6889*7c478bd9Sstevel@tonic-gate * For the Multifunction cards do not reset the socket 6890*7c478bd9Sstevel@tonic-gate * to a memory only interface but do clear the 6891*7c478bd9Sstevel@tonic-gate * Configuration Option Register and mark this client 6892*7c478bd9Sstevel@tonic-gate * as not having a configuration by clearing the 6893*7c478bd9Sstevel@tonic-gate * REQ_CONFIGURATION_DONE flag. 6894*7c478bd9Sstevel@tonic-gate */ 6895*7c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 6896*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 6897*7c478bd9Sstevel@tonic-gate 6898*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6899*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6900*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6901*7c478bd9Sstevel@tonic-gate } 6902*7c478bd9Sstevel@tonic-gate 6903*7c478bd9Sstevel@tonic-gate /* 6904*7c478bd9Sstevel@tonic-gate * Set the socket back to a memory-only interface; don't change 6905*7c478bd9Sstevel@tonic-gate * any other parameter of the socket. 6906*7c478bd9Sstevel@tonic-gate */ 6907*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 6908*7c478bd9Sstevel@tonic-gate 6909*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 6910*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6911*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6912*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6913*7c478bd9Sstevel@tonic-gate } 6914*7c478bd9Sstevel@tonic-gate 6915*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 6916*7c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 6917*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 6918*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 6919*7c478bd9Sstevel@tonic-gate 6920*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 6921*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 6922*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 6923*7c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 6924*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 6925*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 6926*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 6927*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 6928*7c478bd9Sstevel@tonic-gate 6929*7c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 6930*7c478bd9Sstevel@tonic-gate /* 6931*7c478bd9Sstevel@tonic-gate * Some adapters (PD67xx) can write-protect the CIS when the 6932*7c478bd9Sstevel@tonic-gate * socket is in memory mode 6933*7c478bd9Sstevel@tonic-gate */ 6934*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6935*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, COR_SOFT_RESET); 6936*7c478bd9Sstevel@tonic-gate 6937*7c478bd9Sstevel@tonic-gate if (cs_rq_delay) 6938*7c478bd9Sstevel@tonic-gate drv_usecwait(cs_rq_delay * 1000); 6939*7c478bd9Sstevel@tonic-gate #endif 6940*7c478bd9Sstevel@tonic-gate 6941*7c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 6942*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 6943*7c478bd9Sstevel@tonic-gate 6944*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 6945*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6946*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6947*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6948*7c478bd9Sstevel@tonic-gate } 6949*7c478bd9Sstevel@tonic-gate 6950*7c478bd9Sstevel@tonic-gate /* 6951*7c478bd9Sstevel@tonic-gate * Mark this client as not having a configuration. 6952*7c478bd9Sstevel@tonic-gate */ 6953*7c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 6954*7c478bd9Sstevel@tonic-gate 6955*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 6956*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 6957*7c478bd9Sstevel@tonic-gate 6958*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 6959*7c478bd9Sstevel@tonic-gate } 6960*7c478bd9Sstevel@tonic-gate 6961*7c478bd9Sstevel@tonic-gate /* 6962*7c478bd9Sstevel@tonic-gate * cs_modify_configuration - modifies a configuration established by 6963*7c478bd9Sstevel@tonic-gate * RequestConfiguration; this is ModifyConfiguration 6964*7c478bd9Sstevel@tonic-gate * 6965*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully modified 6966*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 6967*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 6968*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 6969*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 6970*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 6971*7c478bd9Sstevel@tonic-gate * are set 6972*7c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 6973*7c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 6974*7c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 6975*7c478bd9Sstevel@tonic-gate */ 6976*7c478bd9Sstevel@tonic-gate static int 6977*7c478bd9Sstevel@tonic-gate cs_modify_configuration(client_handle_t client_handle, modify_config_t *mc) 6978*7c478bd9Sstevel@tonic-gate { 6979*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 6980*7c478bd9Sstevel@tonic-gate client_t *client; 6981*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 6982*7c478bd9Sstevel@tonic-gate get_socket_t get_socket; 6983*7c478bd9Sstevel@tonic-gate int error; 6984*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 6985*7c478bd9Sstevel@tonic-gate 6986*7c478bd9Sstevel@tonic-gate /* 6987*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 6988*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 6989*7c478bd9Sstevel@tonic-gate */ 6990*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 6991*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 6992*7c478bd9Sstevel@tonic-gate 6993*7c478bd9Sstevel@tonic-gate /* 6994*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 6995*7c478bd9Sstevel@tonic-gate */ 6996*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 6997*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 6998*7c478bd9Sstevel@tonic-gate 6999*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7000*7c478bd9Sstevel@tonic-gate 7001*7c478bd9Sstevel@tonic-gate /* 7002*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 7003*7c478bd9Sstevel@tonic-gate */ 7004*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7005*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7006*7c478bd9Sstevel@tonic-gate return (error); 7007*7c478bd9Sstevel@tonic-gate } 7008*7c478bd9Sstevel@tonic-gate 7009*7c478bd9Sstevel@tonic-gate /* 7010*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 7011*7c478bd9Sstevel@tonic-gate * this call. 7012*7c478bd9Sstevel@tonic-gate */ 7013*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7014*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7015*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 7016*7c478bd9Sstevel@tonic-gate } 7017*7c478bd9Sstevel@tonic-gate 7018*7c478bd9Sstevel@tonic-gate /* 7019*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7020*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 7021*7c478bd9Sstevel@tonic-gate */ 7022*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7023*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7024*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 7025*7c478bd9Sstevel@tonic-gate } 7026*7c478bd9Sstevel@tonic-gate 7027*7c478bd9Sstevel@tonic-gate /* 7028*7c478bd9Sstevel@tonic-gate * Get the current socket parameters so that we can modify them. 7029*7c478bd9Sstevel@tonic-gate */ 7030*7c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 7031*7c478bd9Sstevel@tonic-gate 7032*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 7033*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7034*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7035*7c478bd9Sstevel@tonic-gate } 7036*7c478bd9Sstevel@tonic-gate 7037*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7038*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 7039*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration: socket %d " 7040*7c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 7041*7c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 7042*7c478bd9Sstevel@tonic-gate sp->socket_num, (int)client->irq_alloc.irq, 7043*7c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 7044*7c478bd9Sstevel@tonic-gate #endif 7045*7c478bd9Sstevel@tonic-gate 7046*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 7047*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 7048*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 7049*7c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 7050*7c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 7051*7c478bd9Sstevel@tonic-gate 7052*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 7053*7c478bd9Sstevel@tonic-gate 7054*7c478bd9Sstevel@tonic-gate /* 7055*7c478bd9Sstevel@tonic-gate * Modify the IRQ routing if the client wants it modified. 7056*7c478bd9Sstevel@tonic-gate */ 7057*7c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_IRQ_CHANGE_VALID) { 7058*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting &= ~IRQ_ENABLE; 7059*7c478bd9Sstevel@tonic-gate 7060*7c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_MULTI_FUNCTION_CIS) && 7061*7c478bd9Sstevel@tonic-gate (client->present & CONFIG_OPTION_REG_PRESENT)) { 7062*7c478bd9Sstevel@tonic-gate config_regs_t *crt = &client->config_regs; 7063*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 7064*7c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 7065*7c478bd9Sstevel@tonic-gate 7066*7c478bd9Sstevel@tonic-gate /* 7067*7c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 7068*7c478bd9Sstevel@tonic-gate * registers. 7069*7c478bd9Sstevel@tonic-gate */ 7070*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7071*7c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 7072*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7073*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 7074*7c478bd9Sstevel@tonic-gate "cs_modify_configuration: socket %d can't init " 7075*7c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 7076*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 7077*7c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 7078*7c478bd9Sstevel@tonic-gate 7079*7c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 7080*7c478bd9Sstevel@tonic-gate 7081*7c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7082*7c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 7083*7c478bd9Sstevel@tonic-gate 7084*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7085*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 7086*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration:" 7087*7c478bd9Sstevel@tonic-gate " cor_p=0x%x cor=0x%x\n", 7088*7c478bd9Sstevel@tonic-gate crt->cor_p, crt->cor); 7089*7c478bd9Sstevel@tonic-gate #endif 7090*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 7091*7c478bd9Sstevel@tonic-gate 7092*7c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 7093*7c478bd9Sstevel@tonic-gate 7094*7c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 7095*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 7096*7c478bd9Sstevel@tonic-gate 7097*7c478bd9Sstevel@tonic-gate } /* CONF_IRQ_CHANGE_VALID */ 7098*7c478bd9Sstevel@tonic-gate 7099*7c478bd9Sstevel@tonic-gate /* 7100*7c478bd9Sstevel@tonic-gate * Modify the voltage levels that the client specifies. 7101*7c478bd9Sstevel@tonic-gate */ 7102*7c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 7103*7c478bd9Sstevel@tonic-gate 7104*7c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP1_CHANGE_VALID) { 7105*7c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp1, VPP1, 7106*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 7107*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7108*7c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 7109*7c478bd9Sstevel@tonic-gate } 7110*7c478bd9Sstevel@tonic-gate } else { 7111*7c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 7112*7c478bd9Sstevel@tonic-gate } 7113*7c478bd9Sstevel@tonic-gate 7114*7c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP2_CHANGE_VALID) { 7115*7c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp2, VPP2, 7116*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 7117*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7118*7c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 7119*7c478bd9Sstevel@tonic-gate } 7120*7c478bd9Sstevel@tonic-gate } else { 7121*7c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 7122*7c478bd9Sstevel@tonic-gate } 7123*7c478bd9Sstevel@tonic-gate 7124*7c478bd9Sstevel@tonic-gate /* 7125*7c478bd9Sstevel@tonic-gate * Setup the modified socket configuration. 7126*7c478bd9Sstevel@tonic-gate */ 7127*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 7128*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7129*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7130*7c478bd9Sstevel@tonic-gate } 7131*7c478bd9Sstevel@tonic-gate 7132*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7133*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7134*7c478bd9Sstevel@tonic-gate } 7135*7c478bd9Sstevel@tonic-gate 7136*7c478bd9Sstevel@tonic-gate /* 7137*7c478bd9Sstevel@tonic-gate * cs_access_configuration_register - provides a client access to the card's 7138*7c478bd9Sstevel@tonic-gate * configuration registers; this is AccessConfigurationRegister 7139*7c478bd9Sstevel@tonic-gate * 7140*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if register accessed successfully 7141*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7142*7c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if arguments are out of range 7143*7c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 7144*7c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if no config registers base address 7145*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_MODE - if no RequestConfiguration has 7146*7c478bd9Sstevel@tonic-gate * been done yet 7147*7c478bd9Sstevel@tonic-gate */ 7148*7c478bd9Sstevel@tonic-gate static int 7149*7c478bd9Sstevel@tonic-gate cs_access_configuration_register(client_handle_t client_handle, 7150*7c478bd9Sstevel@tonic-gate access_config_reg_t *acr) 7151*7c478bd9Sstevel@tonic-gate { 7152*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7153*7c478bd9Sstevel@tonic-gate client_t *client; 7154*7c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 7155*7c478bd9Sstevel@tonic-gate int error; 7156*7c478bd9Sstevel@tonic-gate uint32_t newoffset; 7157*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7158*7c478bd9Sstevel@tonic-gate 7159*7c478bd9Sstevel@tonic-gate /* 7160*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 7161*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 7162*7c478bd9Sstevel@tonic-gate */ 7163*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 7164*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 7165*7c478bd9Sstevel@tonic-gate 7166*7c478bd9Sstevel@tonic-gate /* 7167*7c478bd9Sstevel@tonic-gate * Make sure that the specifed offset is in range. 7168*7c478bd9Sstevel@tonic-gate */ 7169*7c478bd9Sstevel@tonic-gate if (acr->Offset > ((CISTPL_CONFIG_MAX_CONFIG_REGS * 2) - 2)) 7170*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 7171*7c478bd9Sstevel@tonic-gate 7172*7c478bd9Sstevel@tonic-gate /* 7173*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7174*7c478bd9Sstevel@tonic-gate */ 7175*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7176*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7177*7c478bd9Sstevel@tonic-gate 7178*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7179*7c478bd9Sstevel@tonic-gate 7180*7c478bd9Sstevel@tonic-gate /* 7181*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 7182*7c478bd9Sstevel@tonic-gate */ 7183*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7184*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7185*7c478bd9Sstevel@tonic-gate return (error); 7186*7c478bd9Sstevel@tonic-gate } 7187*7c478bd9Sstevel@tonic-gate 7188*7c478bd9Sstevel@tonic-gate /* 7189*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7190*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 7191*7c478bd9Sstevel@tonic-gate */ 7192*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7193*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7194*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 7195*7c478bd9Sstevel@tonic-gate } 7196*7c478bd9Sstevel@tonic-gate 7197*7c478bd9Sstevel@tonic-gate /* 7198*7c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 7199*7c478bd9Sstevel@tonic-gate * this call. 7200*7c478bd9Sstevel@tonic-gate */ 7201*7c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 7202*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7203*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_MODE); 7204*7c478bd9Sstevel@tonic-gate } 7205*7c478bd9Sstevel@tonic-gate 7206*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 7207*7c478bd9Sstevel@tonic-gate 7208*7c478bd9Sstevel@tonic-gate /* 7209*7c478bd9Sstevel@tonic-gate * Get a pointer to the CIS window 7210*7c478bd9Sstevel@tonic-gate */ 7211*7c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset + acr->Offset; 7212*7c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 7213*7c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 7214*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 7215*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7216*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: socket %d can't init CIS window\n", 7217*7c478bd9Sstevel@tonic-gate sp->socket_num); 7218*7c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 7219*7c478bd9Sstevel@tonic-gate } 7220*7c478bd9Sstevel@tonic-gate 7221*7c478bd9Sstevel@tonic-gate /* 7222*7c478bd9Sstevel@tonic-gate * Create the address for the config register that the client 7223*7c478bd9Sstevel@tonic-gate * wants to access. 7224*7c478bd9Sstevel@tonic-gate */ 7225*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 7226*7c478bd9Sstevel@tonic-gate 7227*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7228*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 7229*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: config_regs_offset 0x%x " 7230*7c478bd9Sstevel@tonic-gate "Offset 0x%x newoffset 0x%x\n", 7231*7c478bd9Sstevel@tonic-gate (int)client->config_regs_offset, 7232*7c478bd9Sstevel@tonic-gate (int)acr->Offset, newoffset); 7233*7c478bd9Sstevel@tonic-gate } 7234*7c478bd9Sstevel@tonic-gate #endif 7235*7c478bd9Sstevel@tonic-gate 7236*7c478bd9Sstevel@tonic-gate /* 7237*7c478bd9Sstevel@tonic-gate * Determine what the client wants us to do. The client is 7238*7c478bd9Sstevel@tonic-gate * allowed to specify any valid offset, even if it would 7239*7c478bd9Sstevel@tonic-gate * cause an unimplemented configuration register to be 7240*7c478bd9Sstevel@tonic-gate * accessed. 7241*7c478bd9Sstevel@tonic-gate */ 7242*7c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 7243*7c478bd9Sstevel@tonic-gate switch (acr->Action) { 7244*7c478bd9Sstevel@tonic-gate case CONFIG_REG_READ: 7245*7c478bd9Sstevel@tonic-gate acr->Value = csx_Get8(cis_handle, newoffset); 7246*7c478bd9Sstevel@tonic-gate break; 7247*7c478bd9Sstevel@tonic-gate case CONFIG_REG_WRITE: 7248*7c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, newoffset, acr->Value); 7249*7c478bd9Sstevel@tonic-gate break; 7250*7c478bd9Sstevel@tonic-gate default: 7251*7c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; 7252*7c478bd9Sstevel@tonic-gate break; 7253*7c478bd9Sstevel@tonic-gate } /* switch */ 7254*7c478bd9Sstevel@tonic-gate 7255*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7256*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 7257*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7258*7c478bd9Sstevel@tonic-gate 7259*7c478bd9Sstevel@tonic-gate return (error); 7260*7c478bd9Sstevel@tonic-gate } 7261*7c478bd9Sstevel@tonic-gate 7262*7c478bd9Sstevel@tonic-gate /* 7263*7c478bd9Sstevel@tonic-gate * ==== RESET and general info functions ==== 7264*7c478bd9Sstevel@tonic-gate */ 7265*7c478bd9Sstevel@tonic-gate 7266*7c478bd9Sstevel@tonic-gate /* 7267*7c478bd9Sstevel@tonic-gate * cs_reset_function - RESET the requested function on the card; this 7268*7c478bd9Sstevel@tonic-gate * is ResetFunction 7269*7c478bd9Sstevel@tonic-gate * 7270*7c478bd9Sstevel@tonic-gate * Note: We don't support this functionality yet, and the standard 7271*7c478bd9Sstevel@tonic-gate * says it's OK to reutrn CS_IN_USE if we can't do this 7272*7c478bd9Sstevel@tonic-gate * operation. 7273*7c478bd9Sstevel@tonic-gate */ 7274*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7275*7c478bd9Sstevel@tonic-gate static int 7276*7c478bd9Sstevel@tonic-gate cs_reset_function(client_handle_t ch, reset_function_t *rf) 7277*7c478bd9Sstevel@tonic-gate { 7278*7c478bd9Sstevel@tonic-gate return (CS_IN_USE); 7279*7c478bd9Sstevel@tonic-gate } 7280*7c478bd9Sstevel@tonic-gate 7281*7c478bd9Sstevel@tonic-gate /* 7282*7c478bd9Sstevel@tonic-gate * cs_get_configuration_info - return configuration info for the passed 7283*7c478bd9Sstevel@tonic-gate * socket and function number to the caller; 7284*7c478bd9Sstevel@tonic-gate * this is GetConfigurationInfo 7285*7c478bd9Sstevel@tonic-gate */ 7286*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7287*7c478bd9Sstevel@tonic-gate static int 7288*7c478bd9Sstevel@tonic-gate cs_get_configuration_info(client_handle_t *chp, get_configuration_info_t *gci) 7289*7c478bd9Sstevel@tonic-gate { 7290*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7291*7c478bd9Sstevel@tonic-gate uint32_t fn; 7292*7c478bd9Sstevel@tonic-gate client_t *client; 7293*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7294*7c478bd9Sstevel@tonic-gate 7295*7c478bd9Sstevel@tonic-gate /* 7296*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7297*7c478bd9Sstevel@tonic-gate */ 7298*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gci->Socket))) == NULL) 7299*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7300*7c478bd9Sstevel@tonic-gate 7301*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7302*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 7303*7c478bd9Sstevel@tonic-gate 7304*7c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(gci->Socket); 7305*7c478bd9Sstevel@tonic-gate 7306*7c478bd9Sstevel@tonic-gate client = sp->client_list; 7307*7c478bd9Sstevel@tonic-gate while (client) { 7308*7c478bd9Sstevel@tonic-gate 7309*7c478bd9Sstevel@tonic-gate if (GET_CLIENT_FUNCTION(client->client_handle) == fn) { 7310*7c478bd9Sstevel@tonic-gate 7311*7c478bd9Sstevel@tonic-gate /* 7312*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the 7313*7c478bd9Sstevel@tonic-gate * socket is not for this client, then return 7314*7c478bd9Sstevel@tonic-gate * an error. 7315*7c478bd9Sstevel@tonic-gate */ 7316*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7317*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7318*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7319*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 7320*7c478bd9Sstevel@tonic-gate } 7321*7c478bd9Sstevel@tonic-gate 7322*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7323*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7324*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7325*7c478bd9Sstevel@tonic-gate 7326*7c478bd9Sstevel@tonic-gate } /* GET_CLIENT_FUNCTION == fn */ 7327*7c478bd9Sstevel@tonic-gate 7328*7c478bd9Sstevel@tonic-gate client = client->next; 7329*7c478bd9Sstevel@tonic-gate } /* while (client) */ 7330*7c478bd9Sstevel@tonic-gate 7331*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7332*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7333*7c478bd9Sstevel@tonic-gate 7334*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7335*7c478bd9Sstevel@tonic-gate } 7336*7c478bd9Sstevel@tonic-gate 7337*7c478bd9Sstevel@tonic-gate /* 7338*7c478bd9Sstevel@tonic-gate * cs_get_cardservices_info - return info about Card Services to the 7339*7c478bd9Sstevel@tonic-gate * caller; this is GetCardServicesInfo 7340*7c478bd9Sstevel@tonic-gate */ 7341*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7342*7c478bd9Sstevel@tonic-gate static int 7343*7c478bd9Sstevel@tonic-gate cs_get_cardservices_info(client_handle_t ch, get_cardservices_info_t *gcsi) 7344*7c478bd9Sstevel@tonic-gate { 7345*7c478bd9Sstevel@tonic-gate gcsi->Signature[0] = 'C'; 7346*7c478bd9Sstevel@tonic-gate gcsi->Signature[1] = 'S'; 7347*7c478bd9Sstevel@tonic-gate gcsi->NumSockets = cs_globals.num_sockets; 7348*7c478bd9Sstevel@tonic-gate gcsi->Revision = CS_INTERNAL_REVISION_LEVEL; 7349*7c478bd9Sstevel@tonic-gate gcsi->CSLevel = CS_VERSION; 7350*7c478bd9Sstevel@tonic-gate gcsi->FuncsPerSocket = CIS_MAX_FUNCTIONS; 7351*7c478bd9Sstevel@tonic-gate (void) strncpy(gcsi->VendorString, 7352*7c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_VENDOR_STRING, 7353*7c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_MAX_VS_LEN); 7354*7c478bd9Sstevel@tonic-gate 7355*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7356*7c478bd9Sstevel@tonic-gate } 7357*7c478bd9Sstevel@tonic-gate 7358*7c478bd9Sstevel@tonic-gate /* 7359*7c478bd9Sstevel@tonic-gate * cs_get_physical_adapter_info - returns information about the requested 7360*7c478bd9Sstevel@tonic-gate * physical adapter; this is 7361*7c478bd9Sstevel@tonic-gate * GetPhysicalAdapterInfo 7362*7c478bd9Sstevel@tonic-gate * 7363*7c478bd9Sstevel@tonic-gate * calling: client_handle_t: 7364*7c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 7365*7c478bd9Sstevel@tonic-gate * to specify logical socket number 7366*7c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 7367*7c478bd9Sstevel@tonic-gate * client_handle_t 7368*7c478bd9Sstevel@tonic-gate * 7369*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 7370*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7371*7c478bd9Sstevel@tonic-gate * socket number is specified in 7372*7c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 7373*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7374*7c478bd9Sstevel@tonic-gate * client handle is specified 7375*7c478bd9Sstevel@tonic-gate */ 7376*7c478bd9Sstevel@tonic-gate static int 7377*7c478bd9Sstevel@tonic-gate cs_get_physical_adapter_info(client_handle_t ch, 7378*7c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *gpai) 7379*7c478bd9Sstevel@tonic-gate { 7380*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7381*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7382*7c478bd9Sstevel@tonic-gate 7383*7c478bd9Sstevel@tonic-gate if (ch == NULL) 7384*7c478bd9Sstevel@tonic-gate gpai->PhySocket = CS_GET_SOCKET_NUMBER(gpai->LogSocket); 7385*7c478bd9Sstevel@tonic-gate else 7386*7c478bd9Sstevel@tonic-gate gpai->PhySocket = GET_CLIENT_SOCKET(ch); 7387*7c478bd9Sstevel@tonic-gate 7388*7c478bd9Sstevel@tonic-gate /* 7389*7c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 7390*7c478bd9Sstevel@tonic-gate */ 7391*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gpai->PhySocket))) == NULL) 7392*7c478bd9Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7393*7c478bd9Sstevel@tonic-gate 7394*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7395*7c478bd9Sstevel@tonic-gate 7396*7c478bd9Sstevel@tonic-gate /* 7397*7c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 7398*7c478bd9Sstevel@tonic-gate */ 7399*7c478bd9Sstevel@tonic-gate if (ch != NULL) { 7400*7c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 7401*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7402*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 7403*7c478bd9Sstevel@tonic-gate } /* cs_find_client */ 7404*7c478bd9Sstevel@tonic-gate } /* ch != NULL */ 7405*7c478bd9Sstevel@tonic-gate 7406*7c478bd9Sstevel@tonic-gate gpai->flags = sp->adapter.flags; 7407*7c478bd9Sstevel@tonic-gate (void) strcpy(gpai->name, sp->adapter.name); 7408*7c478bd9Sstevel@tonic-gate gpai->major = sp->adapter.major; 7409*7c478bd9Sstevel@tonic-gate gpai->minor = sp->adapter.minor; 7410*7c478bd9Sstevel@tonic-gate gpai->instance = sp->adapter.instance; 7411*7c478bd9Sstevel@tonic-gate gpai->number = sp->adapter.number; 7412*7c478bd9Sstevel@tonic-gate gpai->num_sockets = sp->adapter.num_sockets; 7413*7c478bd9Sstevel@tonic-gate gpai->first_socket = sp->adapter.first_socket; 7414*7c478bd9Sstevel@tonic-gate 7415*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7416*7c478bd9Sstevel@tonic-gate 7417*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7418*7c478bd9Sstevel@tonic-gate } 7419*7c478bd9Sstevel@tonic-gate 7420*7c478bd9Sstevel@tonic-gate /* 7421*7c478bd9Sstevel@tonic-gate * ==== general functions ==== 7422*7c478bd9Sstevel@tonic-gate */ 7423*7c478bd9Sstevel@tonic-gate 7424*7c478bd9Sstevel@tonic-gate /* 7425*7c478bd9Sstevel@tonic-gate * cs_map_log_socket - returns the physical socket number associated with 7426*7c478bd9Sstevel@tonic-gate * either the passed client handle or the passed 7427*7c478bd9Sstevel@tonic-gate * logical socket number; this is MapLogSocket 7428*7c478bd9Sstevel@tonic-gate * 7429*7c478bd9Sstevel@tonic-gate * calling: client_handle_t: 7430*7c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 7431*7c478bd9Sstevel@tonic-gate * to specify logical socket number 7432*7c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 7433*7c478bd9Sstevel@tonic-gate * client_handle_t 7434*7c478bd9Sstevel@tonic-gate * 7435*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 7436*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 7437*7c478bd9Sstevel@tonic-gate * socket number is specified in 7438*7c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 7439*7c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 7440*7c478bd9Sstevel@tonic-gate * client handle is specified 7441*7c478bd9Sstevel@tonic-gate * 7442*7c478bd9Sstevel@tonic-gate * Note: We provide this function since the instance number of a client 7443*7c478bd9Sstevel@tonic-gate * driver doesn't necessary correspond to the physical 7444*7c478bd9Sstevel@tonic-gate * socket number 7445*7c478bd9Sstevel@tonic-gate */ 7446*7c478bd9Sstevel@tonic-gate static int 7447*7c478bd9Sstevel@tonic-gate cs_map_log_socket(client_handle_t ch, map_log_socket_t *mls) 7448*7c478bd9Sstevel@tonic-gate { 7449*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7450*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7451*7c478bd9Sstevel@tonic-gate 7452*7c478bd9Sstevel@tonic-gate if (ch == NULL) 7453*7c478bd9Sstevel@tonic-gate mls->PhySocket = CS_GET_SOCKET_NUMBER(mls->LogSocket); 7454*7c478bd9Sstevel@tonic-gate else 7455*7c478bd9Sstevel@tonic-gate mls->PhySocket = GET_CLIENT_SOCKET(ch); 7456*7c478bd9Sstevel@tonic-gate 7457*7c478bd9Sstevel@tonic-gate /* 7458*7c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 7459*7c478bd9Sstevel@tonic-gate */ 7460*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(mls->PhySocket))) == NULL) 7461*7c478bd9Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 7462*7c478bd9Sstevel@tonic-gate 7463*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7464*7c478bd9Sstevel@tonic-gate 7465*7c478bd9Sstevel@tonic-gate /* 7466*7c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 7467*7c478bd9Sstevel@tonic-gate */ 7468*7c478bd9Sstevel@tonic-gate if (ch != NULL) { 7469*7c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 7470*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7471*7c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 7472*7c478bd9Sstevel@tonic-gate } /* cs_find_client */ 7473*7c478bd9Sstevel@tonic-gate } /* ch != NULL */ 7474*7c478bd9Sstevel@tonic-gate 7475*7c478bd9Sstevel@tonic-gate mls->PhyAdapter = sp->adapter.number; 7476*7c478bd9Sstevel@tonic-gate 7477*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7478*7c478bd9Sstevel@tonic-gate 7479*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7480*7c478bd9Sstevel@tonic-gate } 7481*7c478bd9Sstevel@tonic-gate 7482*7c478bd9Sstevel@tonic-gate /* 7483*7c478bd9Sstevel@tonic-gate * cs_convert_speed - convers nS to devspeed and devspeed to nS 7484*7c478bd9Sstevel@tonic-gate * 7485*7c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 7486*7c478bd9Sstevel@tonic-gate * is only a wrapper. 7487*7c478bd9Sstevel@tonic-gate */ 7488*7c478bd9Sstevel@tonic-gate static int 7489*7c478bd9Sstevel@tonic-gate cs_convert_speed(convert_speed_t *cs) 7490*7c478bd9Sstevel@tonic-gate { 7491*7c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSPEED, cs)); 7492*7c478bd9Sstevel@tonic-gate } 7493*7c478bd9Sstevel@tonic-gate 7494*7c478bd9Sstevel@tonic-gate /* 7495*7c478bd9Sstevel@tonic-gate * cs_convert_size - converts a devsize value to a size in bytes value 7496*7c478bd9Sstevel@tonic-gate * or a size in bytes value to a devsize value 7497*7c478bd9Sstevel@tonic-gate * 7498*7c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 7499*7c478bd9Sstevel@tonic-gate * is only a wrapper. 7500*7c478bd9Sstevel@tonic-gate */ 7501*7c478bd9Sstevel@tonic-gate static int 7502*7c478bd9Sstevel@tonic-gate cs_convert_size(convert_size_t *cs) 7503*7c478bd9Sstevel@tonic-gate { 7504*7c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSIZE, cs)); 7505*7c478bd9Sstevel@tonic-gate } 7506*7c478bd9Sstevel@tonic-gate 7507*7c478bd9Sstevel@tonic-gate /* 7508*7c478bd9Sstevel@tonic-gate * cs_convert_powerlevel - converts a power level in tenths of a volt 7509*7c478bd9Sstevel@tonic-gate * to a power table entry for the specified socket 7510*7c478bd9Sstevel@tonic-gate * 7511*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if volts converted to a valid power level 7512*7c478bd9Sstevel@tonic-gate * CS_BAD_ADAPTER - if SS_InquireAdapter fails 7513*7c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if volts are not supported on this socket 7514*7c478bd9Sstevel@tonic-gate * and adapter 7515*7c478bd9Sstevel@tonic-gate */ 7516*7c478bd9Sstevel@tonic-gate static int 7517*7c478bd9Sstevel@tonic-gate cs_convert_powerlevel(uint32_t sn, uint32_t volts, uint32_t flags, unsigned *pl) 7518*7c478bd9Sstevel@tonic-gate { 7519*7c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 7520*7c478bd9Sstevel@tonic-gate int i; 7521*7c478bd9Sstevel@tonic-gate 7522*7c478bd9Sstevel@tonic-gate #ifdef lint 7523*7c478bd9Sstevel@tonic-gate if (sn == 0) 7524*7c478bd9Sstevel@tonic-gate panic("lint panic"); 7525*7c478bd9Sstevel@tonic-gate #endif 7526*7c478bd9Sstevel@tonic-gate 7527*7c478bd9Sstevel@tonic-gate *pl = 0; 7528*7c478bd9Sstevel@tonic-gate 7529*7c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireAdapter, &inquire_adapter) != SUCCESS) 7530*7c478bd9Sstevel@tonic-gate return (CS_BAD_ADAPTER); 7531*7c478bd9Sstevel@tonic-gate 7532*7c478bd9Sstevel@tonic-gate for (i = 0; (i < inquire_adapter.NumPower); i++) { 7533*7c478bd9Sstevel@tonic-gate if ((inquire_adapter.power_entry[i].ValidSignals & flags) && 7534*7c478bd9Sstevel@tonic-gate (inquire_adapter.power_entry[i].PowerLevel == volts)) { 7535*7c478bd9Sstevel@tonic-gate *pl = i; 7536*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7537*7c478bd9Sstevel@tonic-gate } 7538*7c478bd9Sstevel@tonic-gate } 7539*7c478bd9Sstevel@tonic-gate 7540*7c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 7541*7c478bd9Sstevel@tonic-gate } 7542*7c478bd9Sstevel@tonic-gate 7543*7c478bd9Sstevel@tonic-gate /* 7544*7c478bd9Sstevel@tonic-gate * cs_event2text - returns text string(s) associated with the event; this 7545*7c478bd9Sstevel@tonic-gate * function supports the Event2Text CS call. 7546*7c478bd9Sstevel@tonic-gate * 7547*7c478bd9Sstevel@tonic-gate * calling: event2text_t * - pointer to event2text struct 7548*7c478bd9Sstevel@tonic-gate * int event_source - specifies event type in event2text_t: 7549*7c478bd9Sstevel@tonic-gate * 0 - SS event 7550*7c478bd9Sstevel@tonic-gate * 1 - CS event 7551*7c478bd9Sstevel@tonic-gate * 7552*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 7553*7c478bd9Sstevel@tonic-gate */ 7554*7c478bd9Sstevel@tonic-gate static int 7555*7c478bd9Sstevel@tonic-gate cs_event2text(event2text_t *e2t, int event_source) 7556*7c478bd9Sstevel@tonic-gate { 7557*7c478bd9Sstevel@tonic-gate event_t event; 7558*7c478bd9Sstevel@tonic-gate char *sepchar = "|"; 7559*7c478bd9Sstevel@tonic-gate 7560*7c478bd9Sstevel@tonic-gate /* 7561*7c478bd9Sstevel@tonic-gate * If event_source is 0, this is a SS event 7562*7c478bd9Sstevel@tonic-gate */ 7563*7c478bd9Sstevel@tonic-gate if (!event_source) { 7564*7c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_SS_EVENTS; event++) { 7565*7c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].ss_event == e2t->event) { 7566*7c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[event].text); 7567*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7568*7c478bd9Sstevel@tonic-gate } 7569*7c478bd9Sstevel@tonic-gate } 7570*7c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[MAX_CS_EVENTS].text); 7571*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7572*7c478bd9Sstevel@tonic-gate } else { 7573*7c478bd9Sstevel@tonic-gate /* 7574*7c478bd9Sstevel@tonic-gate * This is a CS event 7575*7c478bd9Sstevel@tonic-gate */ 7576*7c478bd9Sstevel@tonic-gate e2t->text[0] = '\0'; 7577*7c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_CS_EVENTS; event++) { 7578*7c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].cs_event & e2t->event) { 7579*7c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, cs_ss_event_text[event].text); 7580*7c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, sepchar); 7581*7c478bd9Sstevel@tonic-gate } /* if (cs_ss_event_text) */ 7582*7c478bd9Sstevel@tonic-gate } /* for (event) */ 7583*7c478bd9Sstevel@tonic-gate if (e2t->text[0]) 7584*7c478bd9Sstevel@tonic-gate e2t->text[strlen(e2t->text)-1] = NULL; 7585*7c478bd9Sstevel@tonic-gate } /* if (!event_source) */ 7586*7c478bd9Sstevel@tonic-gate 7587*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7588*7c478bd9Sstevel@tonic-gate } 7589*7c478bd9Sstevel@tonic-gate 7590*7c478bd9Sstevel@tonic-gate /* 7591*7c478bd9Sstevel@tonic-gate * cs_error2text - returns a pointer to a text string containing the name 7592*7c478bd9Sstevel@tonic-gate * of the passed Card Services function or return code 7593*7c478bd9Sstevel@tonic-gate * 7594*7c478bd9Sstevel@tonic-gate * This function supports the Error2Text CS call. 7595*7c478bd9Sstevel@tonic-gate */ 7596*7c478bd9Sstevel@tonic-gate static char * 7597*7c478bd9Sstevel@tonic-gate cs_error2text(int function, int type) 7598*7c478bd9Sstevel@tonic-gate { 7599*7c478bd9Sstevel@tonic-gate cs_csfunc2text_strings_t *cfs; 7600*7c478bd9Sstevel@tonic-gate int end_marker; 7601*7c478bd9Sstevel@tonic-gate 7602*7c478bd9Sstevel@tonic-gate if (type == CSFUN2TEXT_FUNCTION) { 7603*7c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_funcstrings; 7604*7c478bd9Sstevel@tonic-gate end_marker = CSFuncListEnd; 7605*7c478bd9Sstevel@tonic-gate } else { 7606*7c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_returnstrings; 7607*7c478bd9Sstevel@tonic-gate end_marker = CS_ERRORLIST_END; 7608*7c478bd9Sstevel@tonic-gate } 7609*7c478bd9Sstevel@tonic-gate 7610*7c478bd9Sstevel@tonic-gate while (cfs->item != end_marker) { 7611*7c478bd9Sstevel@tonic-gate if (cfs->item == function) 7612*7c478bd9Sstevel@tonic-gate return (cfs->text); 7613*7c478bd9Sstevel@tonic-gate cfs++; 7614*7c478bd9Sstevel@tonic-gate } 7615*7c478bd9Sstevel@tonic-gate 7616*7c478bd9Sstevel@tonic-gate return (cfs->text); 7617*7c478bd9Sstevel@tonic-gate } 7618*7c478bd9Sstevel@tonic-gate 7619*7c478bd9Sstevel@tonic-gate /* 7620*7c478bd9Sstevel@tonic-gate * cs_make_device_node - creates/removes device nodes on a client's behalf; 7621*7c478bd9Sstevel@tonic-gate * this is MakeDeviceNode and RemoveDeviceNode 7622*7c478bd9Sstevel@tonic-gate * 7623*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if all device nodes successfully created/removed 7624*7c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if NumDevNodes is not zero when Action 7625*7c478bd9Sstevel@tonic-gate * is REMOVAL_ALL_DEVICES 7626*7c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if an invalid Action code is specified 7627*7c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 7628*7c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if can't create/remove device node 7629*7c478bd9Sstevel@tonic-gate */ 7630*7c478bd9Sstevel@tonic-gate static int 7631*7c478bd9Sstevel@tonic-gate cs_make_device_node(client_handle_t client_handle, make_device_node_t *mdn) 7632*7c478bd9Sstevel@tonic-gate { 7633*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7634*7c478bd9Sstevel@tonic-gate client_t *client; 7635*7c478bd9Sstevel@tonic-gate ss_make_device_node_t ss_make_device_node; 7636*7c478bd9Sstevel@tonic-gate int error, i; 7637*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7638*7c478bd9Sstevel@tonic-gate 7639*7c478bd9Sstevel@tonic-gate /* 7640*7c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 7641*7c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 7642*7c478bd9Sstevel@tonic-gate */ 7643*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 7644*7c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 7645*7c478bd9Sstevel@tonic-gate 7646*7c478bd9Sstevel@tonic-gate /* 7647*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7648*7c478bd9Sstevel@tonic-gate */ 7649*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 7650*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7651*7c478bd9Sstevel@tonic-gate 7652*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7653*7c478bd9Sstevel@tonic-gate 7654*7c478bd9Sstevel@tonic-gate /* 7655*7c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 7656*7c478bd9Sstevel@tonic-gate */ 7657*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 7658*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7659*7c478bd9Sstevel@tonic-gate return (error); 7660*7c478bd9Sstevel@tonic-gate } 7661*7c478bd9Sstevel@tonic-gate 7662*7c478bd9Sstevel@tonic-gate #ifdef XXX 7663*7c478bd9Sstevel@tonic-gate /* 7664*7c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 7665*7c478bd9Sstevel@tonic-gate * for this client, then return an error. 7666*7c478bd9Sstevel@tonic-gate */ 7667*7c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 7668*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7669*7c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 7670*7c478bd9Sstevel@tonic-gate } 7671*7c478bd9Sstevel@tonic-gate #endif 7672*7c478bd9Sstevel@tonic-gate 7673*7c478bd9Sstevel@tonic-gate /* 7674*7c478bd9Sstevel@tonic-gate * Setup the client's dip, since we use it later on. 7675*7c478bd9Sstevel@tonic-gate */ 7676*7c478bd9Sstevel@tonic-gate ss_make_device_node.dip = client->dip; 7677*7c478bd9Sstevel@tonic-gate 7678*7c478bd9Sstevel@tonic-gate /* 7679*7c478bd9Sstevel@tonic-gate * Make sure that we're being given a valid Action. Set the default 7680*7c478bd9Sstevel@tonic-gate * error code as well. 7681*7c478bd9Sstevel@tonic-gate */ 7682*7c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; /* for default case */ 7683*7c478bd9Sstevel@tonic-gate switch (mdn->Action) { 7684*7c478bd9Sstevel@tonic-gate case CREATE_DEVICE_NODE: 7685*7c478bd9Sstevel@tonic-gate case REMOVE_DEVICE_NODE: 7686*7c478bd9Sstevel@tonic-gate break; 7687*7c478bd9Sstevel@tonic-gate case REMOVAL_ALL_DEVICE_NODES: 7688*7c478bd9Sstevel@tonic-gate if (mdn->NumDevNodes) { 7689*7c478bd9Sstevel@tonic-gate error = CS_BAD_ATTRIBUTE; 7690*7c478bd9Sstevel@tonic-gate } else { 7691*7c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7692*7c478bd9Sstevel@tonic-gate ss_make_device_node.name = NULL; 7693*7c478bd9Sstevel@tonic-gate SocketServices(CSInitDev, &ss_make_device_node); 7694*7c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 7695*7c478bd9Sstevel@tonic-gate } 7696*7c478bd9Sstevel@tonic-gate /* fall-through case */ 7697*7c478bd9Sstevel@tonic-gate default: 7698*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7699*7c478bd9Sstevel@tonic-gate return (error); 7700*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 7701*7c478bd9Sstevel@tonic-gate } /* switch */ 7702*7c478bd9Sstevel@tonic-gate 7703*7c478bd9Sstevel@tonic-gate /* 7704*7c478bd9Sstevel@tonic-gate * Loop through the device node descriptions and create or destroy 7705*7c478bd9Sstevel@tonic-gate * the device node. 7706*7c478bd9Sstevel@tonic-gate */ 7707*7c478bd9Sstevel@tonic-gate for (i = 0; i < mdn->NumDevNodes; i++) { 7708*7c478bd9Sstevel@tonic-gate devnode_desc_t *devnode_desc = &mdn->devnode_desc[i]; 7709*7c478bd9Sstevel@tonic-gate 7710*7c478bd9Sstevel@tonic-gate ss_make_device_node.name = devnode_desc->name; 7711*7c478bd9Sstevel@tonic-gate ss_make_device_node.spec_type = devnode_desc->spec_type; 7712*7c478bd9Sstevel@tonic-gate ss_make_device_node.minor_num = devnode_desc->minor_num; 7713*7c478bd9Sstevel@tonic-gate ss_make_device_node.node_type = devnode_desc->node_type; 7714*7c478bd9Sstevel@tonic-gate 7715*7c478bd9Sstevel@tonic-gate /* 7716*7c478bd9Sstevel@tonic-gate * Set the appropriate flag for the action that we want 7717*7c478bd9Sstevel@tonic-gate * SS to perform. Note that if we ever OR-in the flag 7718*7c478bd9Sstevel@tonic-gate * here, we need to be sure to clear the flags member 7719*7c478bd9Sstevel@tonic-gate * since we sometimes OR-in other flags below. 7720*7c478bd9Sstevel@tonic-gate */ 7721*7c478bd9Sstevel@tonic-gate if (mdn->Action == CREATE_DEVICE_NODE) { 7722*7c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_CREATE_DEVICE; 7723*7c478bd9Sstevel@tonic-gate } else { 7724*7c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 7725*7c478bd9Sstevel@tonic-gate } 7726*7c478bd9Sstevel@tonic-gate 7727*7c478bd9Sstevel@tonic-gate /* 7728*7c478bd9Sstevel@tonic-gate * If this is not the last device to process, then we need 7729*7c478bd9Sstevel@tonic-gate * to tell SS that more device process requests are on 7730*7c478bd9Sstevel@tonic-gate * their way after this one. 7731*7c478bd9Sstevel@tonic-gate */ 7732*7c478bd9Sstevel@tonic-gate if (i < (mdn->NumDevNodes - 1)) 7733*7c478bd9Sstevel@tonic-gate ss_make_device_node.flags |= SS_CSINITDEV_MORE_DEVICES; 7734*7c478bd9Sstevel@tonic-gate 7735*7c478bd9Sstevel@tonic-gate if (SocketServices(CSInitDev, &ss_make_device_node) != SUCCESS) { 7736*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7737*7c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 7738*7c478bd9Sstevel@tonic-gate } /* CSInitDev */ 7739*7c478bd9Sstevel@tonic-gate } /* for (mdn->NumDevNodes) */ 7740*7c478bd9Sstevel@tonic-gate 7741*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7742*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7743*7c478bd9Sstevel@tonic-gate } 7744*7c478bd9Sstevel@tonic-gate 7745*7c478bd9Sstevel@tonic-gate /* 7746*7c478bd9Sstevel@tonic-gate * cs_remove_device_node - removes device nodes 7747*7c478bd9Sstevel@tonic-gate * 7748*7c478bd9Sstevel@tonic-gate * (see cs_make_device_node for a description of the calling 7749*7c478bd9Sstevel@tonic-gate * and return parameters) 7750*7c478bd9Sstevel@tonic-gate */ 7751*7c478bd9Sstevel@tonic-gate static int 7752*7c478bd9Sstevel@tonic-gate cs_remove_device_node(client_handle_t client_handle, remove_device_node_t *rdn) 7753*7c478bd9Sstevel@tonic-gate { 7754*7c478bd9Sstevel@tonic-gate 7755*7c478bd9Sstevel@tonic-gate /* 7756*7c478bd9Sstevel@tonic-gate * XXX - Note the assumption here that the make_device_node_t and 7757*7c478bd9Sstevel@tonic-gate * remove_device_node_t structures are identical. 7758*7c478bd9Sstevel@tonic-gate */ 7759*7c478bd9Sstevel@tonic-gate return (cs_make_device_node(client_handle, (make_device_node_t *)rdn)); 7760*7c478bd9Sstevel@tonic-gate } 7761*7c478bd9Sstevel@tonic-gate 7762*7c478bd9Sstevel@tonic-gate /* 7763*7c478bd9Sstevel@tonic-gate * cs_ddi_info - this function is used by clients that need to support 7764*7c478bd9Sstevel@tonic-gate * the xxx_getinfo function; this is CS_DDI_Info 7765*7c478bd9Sstevel@tonic-gate */ 7766*7c478bd9Sstevel@tonic-gate static int 7767*7c478bd9Sstevel@tonic-gate cs_ddi_info(cs_ddi_info_t *cdi) 7768*7c478bd9Sstevel@tonic-gate { 7769*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7770*7c478bd9Sstevel@tonic-gate client_t *client; 7771*7c478bd9Sstevel@tonic-gate int client_lock_acquired; 7772*7c478bd9Sstevel@tonic-gate 7773*7c478bd9Sstevel@tonic-gate if (cdi->driver_name == NULL) 7774*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 7775*7c478bd9Sstevel@tonic-gate 7776*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7777*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 7778*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s]\n", 7779*7c478bd9Sstevel@tonic-gate (int)cdi->Socket, cdi->driver_name); 7780*7c478bd9Sstevel@tonic-gate } 7781*7c478bd9Sstevel@tonic-gate #endif 7782*7c478bd9Sstevel@tonic-gate 7783*7c478bd9Sstevel@tonic-gate /* 7784*7c478bd9Sstevel@tonic-gate * Check to see if the socket number is in range - the system 7785*7c478bd9Sstevel@tonic-gate * framework may cause a client driver to call us with 7786*7c478bd9Sstevel@tonic-gate * a socket number that used to be present but isn't 7787*7c478bd9Sstevel@tonic-gate * anymore. This is not a bug, and it's OK to return 7788*7c478bd9Sstevel@tonic-gate * an error if the socket number is out of range. 7789*7c478bd9Sstevel@tonic-gate */ 7790*7c478bd9Sstevel@tonic-gate if (!CHECK_SOCKET_NUM(cdi->Socket, cs_globals.max_socket_num)) { 7791*7c478bd9Sstevel@tonic-gate 7792*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7793*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 7794*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s] " 7795*7c478bd9Sstevel@tonic-gate "SOCKET IS OUT OF RANGE\n", 7796*7c478bd9Sstevel@tonic-gate (int)cdi->Socket, 7797*7c478bd9Sstevel@tonic-gate cdi->driver_name); 7798*7c478bd9Sstevel@tonic-gate } 7799*7c478bd9Sstevel@tonic-gate #endif 7800*7c478bd9Sstevel@tonic-gate 7801*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7802*7c478bd9Sstevel@tonic-gate } /* if (!CHECK_SOCKET_NUM) */ 7803*7c478bd9Sstevel@tonic-gate 7804*7c478bd9Sstevel@tonic-gate /* 7805*7c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 7806*7c478bd9Sstevel@tonic-gate */ 7807*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(cdi->Socket)) == NULL) 7808*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7809*7c478bd9Sstevel@tonic-gate 7810*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 7811*7c478bd9Sstevel@tonic-gate 7812*7c478bd9Sstevel@tonic-gate client = sp->client_list; 7813*7c478bd9Sstevel@tonic-gate while (client) { 7814*7c478bd9Sstevel@tonic-gate 7815*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7816*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 7817*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d checking client [%s] " 7818*7c478bd9Sstevel@tonic-gate "handle 0x%x\n", 7819*7c478bd9Sstevel@tonic-gate (int)cdi->Socket, 7820*7c478bd9Sstevel@tonic-gate client->driver_name, 7821*7c478bd9Sstevel@tonic-gate (int)client->client_handle); 7822*7c478bd9Sstevel@tonic-gate } 7823*7c478bd9Sstevel@tonic-gate #endif 7824*7c478bd9Sstevel@tonic-gate 7825*7c478bd9Sstevel@tonic-gate if (client->driver_name != NULL) { 7826*7c478bd9Sstevel@tonic-gate if (!(strcmp(client->driver_name, cdi->driver_name))) { 7827*7c478bd9Sstevel@tonic-gate cdi->dip = client->dip; 7828*7c478bd9Sstevel@tonic-gate cdi->instance = client->instance; 7829*7c478bd9Sstevel@tonic-gate 7830*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 7831*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 7832*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: found client [%s] " 7833*7c478bd9Sstevel@tonic-gate "instance %d handle 0x%x\n", 7834*7c478bd9Sstevel@tonic-gate client->driver_name, client->instance, 7835*7c478bd9Sstevel@tonic-gate (int)client->client_handle); 7836*7c478bd9Sstevel@tonic-gate } 7837*7c478bd9Sstevel@tonic-gate #endif 7838*7c478bd9Sstevel@tonic-gate 7839*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7840*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 7841*7c478bd9Sstevel@tonic-gate } /* strcmp */ 7842*7c478bd9Sstevel@tonic-gate } /* driver_name != NULL */ 7843*7c478bd9Sstevel@tonic-gate client = client->next; 7844*7c478bd9Sstevel@tonic-gate } /* while (client) */ 7845*7c478bd9Sstevel@tonic-gate 7846*7c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 7847*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7848*7c478bd9Sstevel@tonic-gate } 7849*7c478bd9Sstevel@tonic-gate 7850*7c478bd9Sstevel@tonic-gate /* 7851*7c478bd9Sstevel@tonic-gate * cs_sys_ctl - Card Services system control; this is CS_Sys_Ctl 7852*7c478bd9Sstevel@tonic-gate */ 7853*7c478bd9Sstevel@tonic-gate static int 7854*7c478bd9Sstevel@tonic-gate cs_sys_ctl(cs_sys_ctl_t *csc) 7855*7c478bd9Sstevel@tonic-gate { 7856*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7857*7c478bd9Sstevel@tonic-gate client_t *cp; 7858*7c478bd9Sstevel@tonic-gate int sn, ret = CS_UNSUPPORTED_MODE; 7859*7c478bd9Sstevel@tonic-gate 7860*7c478bd9Sstevel@tonic-gate switch (csc->Action) { 7861*7c478bd9Sstevel@tonic-gate case CS_SYS_CTL_SEND_EVENT: 7862*7c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7863*7c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(csc->Socket); 7864*7c478bd9Sstevel@tonic-gate else 7865*7c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(csc->client_handle); 7866*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 7867*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7868*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 7869*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 7870*7c478bd9Sstevel@tonic-gate csc->Events &= CS_EVENT_CLIENT_EVENTS_MASK; 7871*7c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 7872*7c478bd9Sstevel@tonic-gate sp->events |= csc->Events; 7873*7c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_CLIENT) { 7874*7c478bd9Sstevel@tonic-gate if ((cp = cs_find_client(csc->client_handle, &ret)) == 7875*7c478bd9Sstevel@tonic-gate NULL) { 7876*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7877*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 7878*7c478bd9Sstevel@tonic-gate return (ret); 7879*7c478bd9Sstevel@tonic-gate } /* cs_find_client */ 7880*7c478bd9Sstevel@tonic-gate /* 7881*7c478bd9Sstevel@tonic-gate * Setup the events that we want to send to the client. 7882*7c478bd9Sstevel@tonic-gate */ 7883*7c478bd9Sstevel@tonic-gate cp->events |= (csc->Events & 7884*7c478bd9Sstevel@tonic-gate (cp->event_mask | cp->global_mask)); 7885*7c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_EVENT_CLIENT */ 7886*7c478bd9Sstevel@tonic-gate 7887*7c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_WAIT_SYNC) { 7888*7c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 7889*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7890*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 7891*7c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 7892*7c478bd9Sstevel@tonic-gate } else { 7893*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 7894*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 7895*7c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_WAIT_SYNC */ 7896*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 7897*7c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 7898*7c478bd9Sstevel@tonic-gate break; 7899*7c478bd9Sstevel@tonic-gate default: 7900*7c478bd9Sstevel@tonic-gate break; 7901*7c478bd9Sstevel@tonic-gate } /* switch */ 7902*7c478bd9Sstevel@tonic-gate 7903*7c478bd9Sstevel@tonic-gate return (ret); 7904*7c478bd9Sstevel@tonic-gate } 7905*7c478bd9Sstevel@tonic-gate 7906*7c478bd9Sstevel@tonic-gate /* 7907*7c478bd9Sstevel@tonic-gate * cs_get_sp - returns pointer to per-socket structure for passed 7908*7c478bd9Sstevel@tonic-gate * socket number 7909*7c478bd9Sstevel@tonic-gate * 7910*7c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure 7911*7c478bd9Sstevel@tonic-gate * NULL - invalid socket number passed in 7912*7c478bd9Sstevel@tonic-gate */ 7913*7c478bd9Sstevel@tonic-gate static cs_socket_t * 7914*7c478bd9Sstevel@tonic-gate cs_get_sp(uint32_t sn) 7915*7c478bd9Sstevel@tonic-gate { 7916*7c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 7917*7c478bd9Sstevel@tonic-gate 7918*7c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7919*7c478bd9Sstevel@tonic-gate return (NULL); 7920*7c478bd9Sstevel@tonic-gate 7921*7c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) 7922*7c478bd9Sstevel@tonic-gate return (NULL); 7923*7c478bd9Sstevel@tonic-gate 7924*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 7925*7c478bd9Sstevel@tonic-gate return (sp); 7926*7c478bd9Sstevel@tonic-gate 7927*7c478bd9Sstevel@tonic-gate return (NULL); 7928*7c478bd9Sstevel@tonic-gate } 7929*7c478bd9Sstevel@tonic-gate 7930*7c478bd9Sstevel@tonic-gate /* 7931*7c478bd9Sstevel@tonic-gate * cs_find_sp - searches socket list and returns pointer to passed socket 7932*7c478bd9Sstevel@tonic-gate * number 7933*7c478bd9Sstevel@tonic-gate * 7934*7c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure if found 7935*7c478bd9Sstevel@tonic-gate * NULL - socket not found 7936*7c478bd9Sstevel@tonic-gate */ 7937*7c478bd9Sstevel@tonic-gate static cs_socket_t * 7938*7c478bd9Sstevel@tonic-gate cs_find_sp(uint32_t sn) 7939*7c478bd9Sstevel@tonic-gate { 7940*7c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 7941*7c478bd9Sstevel@tonic-gate 7942*7c478bd9Sstevel@tonic-gate while (sp) { 7943*7c478bd9Sstevel@tonic-gate if (sp->socket_num == CS_GET_SOCKET_NUMBER(sn)) 7944*7c478bd9Sstevel@tonic-gate return (sp); 7945*7c478bd9Sstevel@tonic-gate sp = sp->next; 7946*7c478bd9Sstevel@tonic-gate } /* while */ 7947*7c478bd9Sstevel@tonic-gate 7948*7c478bd9Sstevel@tonic-gate return (NULL); 7949*7c478bd9Sstevel@tonic-gate } 7950*7c478bd9Sstevel@tonic-gate 7951*7c478bd9Sstevel@tonic-gate /* 7952*7c478bd9Sstevel@tonic-gate * cs_add_socket - add a socket 7953*7c478bd9Sstevel@tonic-gate * 7954*7c478bd9Sstevel@tonic-gate * call: sn - socket number to add 7955*7c478bd9Sstevel@tonic-gate * 7956*7c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 7957*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to add socket 7958*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - unable to get CIS window for socket 7959*7c478bd9Sstevel@tonic-gate * 7960*7c478bd9Sstevel@tonic-gate * We get called here once for each socket that the framework wants to 7961*7c478bd9Sstevel@tonic-gate * add. When we are called, the framework guarentees that until we 7962*7c478bd9Sstevel@tonic-gate * complete this routine, no other adapter instances will be allowed 7963*7c478bd9Sstevel@tonic-gate * to attach and thus no other PCE_ADD_SOCKET events will occur. 7964*7c478bd9Sstevel@tonic-gate * It is safe to call SS_InquireAdapter to get the number of 7965*7c478bd9Sstevel@tonic-gate * windows that the framework currently knows about. 7966*7c478bd9Sstevel@tonic-gate */ 7967*7c478bd9Sstevel@tonic-gate static uint32_t 7968*7c478bd9Sstevel@tonic-gate cs_add_socket(uint32_t sn) 7969*7c478bd9Sstevel@tonic-gate { 7970*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 7971*7c478bd9Sstevel@tonic-gate sservice_t sservice; 7972*7c478bd9Sstevel@tonic-gate get_cookies_and_dip_t *gcad; 7973*7c478bd9Sstevel@tonic-gate win_req_t win_req; 7974*7c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 7975*7c478bd9Sstevel@tonic-gate set_socket_t set_socket; 7976*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 7977*7c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 7978*7c478bd9Sstevel@tonic-gate inquire_window_t inquire_window; 7979*7c478bd9Sstevel@tonic-gate int ret, added_windows; 7980*7c478bd9Sstevel@tonic-gate 7981*7c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 7982*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 7983*7c478bd9Sstevel@tonic-gate 7984*7c478bd9Sstevel@tonic-gate /* 7985*7c478bd9Sstevel@tonic-gate * See if this socket has already been added - if it has, we 7986*7c478bd9Sstevel@tonic-gate * fail this. If we can't find the socket, then allocate 7987*7c478bd9Sstevel@tonic-gate * a new socket structure. If we do find the socket, then 7988*7c478bd9Sstevel@tonic-gate * check to see if it's already added; if it is, then 7989*7c478bd9Sstevel@tonic-gate * this is an error and return CS_BAD_SOCKET; if not, 7990*7c478bd9Sstevel@tonic-gate * then traverse the socket structure list and add this 7991*7c478bd9Sstevel@tonic-gate * next socket strcture to the end of the list. 7992*7c478bd9Sstevel@tonic-gate * XXX What about locking this list while we update it? Is 7993*7c478bd9Sstevel@tonic-gate * that necessary since we're using the SOCKET_IS_VALID 7994*7c478bd9Sstevel@tonic-gate * flag and since we never delete a socket from the 7995*7c478bd9Sstevel@tonic-gate * list once it's been added? 7996*7c478bd9Sstevel@tonic-gate */ 7997*7c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) { 7998*7c478bd9Sstevel@tonic-gate cs_socket_t *spp = cs_globals.sp; 7999*7c478bd9Sstevel@tonic-gate 8000*7c478bd9Sstevel@tonic-gate sp = (cs_socket_t *)kmem_zalloc(sizeof (cs_socket_t), KM_SLEEP); 8001*7c478bd9Sstevel@tonic-gate 8002*7c478bd9Sstevel@tonic-gate if (cs_globals.sp == NULL) 8003*7c478bd9Sstevel@tonic-gate cs_globals.sp = sp; 8004*7c478bd9Sstevel@tonic-gate else 8005*7c478bd9Sstevel@tonic-gate while (spp) { 8006*7c478bd9Sstevel@tonic-gate if (spp->next == NULL) { 8007*7c478bd9Sstevel@tonic-gate spp->next = sp; 8008*7c478bd9Sstevel@tonic-gate break; 8009*7c478bd9Sstevel@tonic-gate } /* if */ 8010*7c478bd9Sstevel@tonic-gate spp = spp->next; 8011*7c478bd9Sstevel@tonic-gate } /* while */ 8012*7c478bd9Sstevel@tonic-gate 8013*7c478bd9Sstevel@tonic-gate } else { 8014*7c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 8015*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8016*7c478bd9Sstevel@tonic-gate } /* cs_find_sp */ 8017*7c478bd9Sstevel@tonic-gate 8018*7c478bd9Sstevel@tonic-gate /* 8019*7c478bd9Sstevel@tonic-gate * Setup the socket number 8020*7c478bd9Sstevel@tonic-gate */ 8021*7c478bd9Sstevel@tonic-gate sp->socket_num = sn; 8022*7c478bd9Sstevel@tonic-gate 8023*7c478bd9Sstevel@tonic-gate /* 8024*7c478bd9Sstevel@tonic-gate * Find out how many windows the framework knows about 8025*7c478bd9Sstevel@tonic-gate * so far. If this number of windows is greater 8026*7c478bd9Sstevel@tonic-gate * than our current window count, bump up our 8027*7c478bd9Sstevel@tonic-gate * current window count. 8028*7c478bd9Sstevel@tonic-gate * XXX Note that there is a BIG assumption here and that 8029*7c478bd9Sstevel@tonic-gate * is that once the framework tells us that it has 8030*7c478bd9Sstevel@tonic-gate * a window (as reflected in the NumWindows 8031*7c478bd9Sstevel@tonic-gate * value) it can NEVER remove that window. 8032*7c478bd9Sstevel@tonic-gate * When we really get the drop socket and drop 8033*7c478bd9Sstevel@tonic-gate * window mechanism working correctly, we'll have 8034*7c478bd9Sstevel@tonic-gate * to revisit this. 8035*7c478bd9Sstevel@tonic-gate */ 8036*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireAdapter, &inquire_adapter); 8037*7c478bd9Sstevel@tonic-gate 8038*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 8039*7c478bd9Sstevel@tonic-gate added_windows = inquire_adapter.NumWindows - cs_globals.num_windows; 8040*7c478bd9Sstevel@tonic-gate if (added_windows > 0) { 8041*7c478bd9Sstevel@tonic-gate if (cs_add_windows(added_windows, 8042*7c478bd9Sstevel@tonic-gate cs_globals.num_windows) != CS_SUCCESS) { 8043*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8044*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 8045*7c478bd9Sstevel@tonic-gate } /* cs_add_windows */ 8046*7c478bd9Sstevel@tonic-gate 8047*7c478bd9Sstevel@tonic-gate cs_globals.num_windows = inquire_adapter.NumWindows; 8048*7c478bd9Sstevel@tonic-gate 8049*7c478bd9Sstevel@tonic-gate } /* if (added_windows) */ 8050*7c478bd9Sstevel@tonic-gate 8051*7c478bd9Sstevel@tonic-gate /* 8052*7c478bd9Sstevel@tonic-gate * Find a window that we can use for this socket's CIS window. 8053*7c478bd9Sstevel@tonic-gate */ 8054*7c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8055*7c478bd9Sstevel@tonic-gate 8056*7c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 8057*7c478bd9Sstevel@tonic-gate convert_speed.nS = CIS_DEFAULT_SPEED; 8058*7c478bd9Sstevel@tonic-gate (void) cs_convert_speed(&convert_speed); 8059*7c478bd9Sstevel@tonic-gate 8060*7c478bd9Sstevel@tonic-gate win_req.win_params.AccessSpeed = convert_speed.devspeed; 8061*7c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8); 8062*7c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_MEMORY_TYPE_CM); 8063*7c478bd9Sstevel@tonic-gate win_req.Base.base = 0; 8064*7c478bd9Sstevel@tonic-gate win_req.Size = 0; 8065*7c478bd9Sstevel@tonic-gate 8066*7c478bd9Sstevel@tonic-gate if ((ret = cs_find_mem_window(sp->socket_num, &win_req, 8067*7c478bd9Sstevel@tonic-gate &sp->cis_win_num)) != CS_SUCCESS) { 8068*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8069*7c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 8070*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't get CIS " 8071*7c478bd9Sstevel@tonic-gate "window - error 0x%x\n", 8072*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 8073*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 8074*7c478bd9Sstevel@tonic-gate } /* cs_find_mem_window */ 8075*7c478bd9Sstevel@tonic-gate 8076*7c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) { 8077*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8078*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 8079*7c478bd9Sstevel@tonic-gate } 8080*7c478bd9Sstevel@tonic-gate 8081*7c478bd9Sstevel@tonic-gate inquire_window.window = sp->cis_win_num; 8082*7c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &inquire_window); 8083*7c478bd9Sstevel@tonic-gate 8084*7c478bd9Sstevel@tonic-gate /* 8085*7c478bd9Sstevel@tonic-gate * If the CIS window is a variable sized window, then use 8086*7c478bd9Sstevel@tonic-gate * the size that cs_find_mem_window returned to us, 8087*7c478bd9Sstevel@tonic-gate * since this will be the minimum size that we can 8088*7c478bd9Sstevel@tonic-gate * set this window to. If the CIS window is a fixed 8089*7c478bd9Sstevel@tonic-gate * sized window, then use the system pagesize as the 8090*7c478bd9Sstevel@tonic-gate * CIS window size. 8091*7c478bd9Sstevel@tonic-gate */ 8092*7c478bd9Sstevel@tonic-gate if (inquire_window.mem_win_char.MemWndCaps & WC_SIZE) { 8093*7c478bd9Sstevel@tonic-gate sp->cis_win_size = win_req.Size; 8094*7c478bd9Sstevel@tonic-gate } else { 8095*7c478bd9Sstevel@tonic-gate sp->cis_win_size = PAGESIZE; 8096*7c478bd9Sstevel@tonic-gate } 8097*7c478bd9Sstevel@tonic-gate 8098*7c478bd9Sstevel@tonic-gate cw->state |= (CW_CIS | CW_ALLOCATED); 8099*7c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 8100*7c478bd9Sstevel@tonic-gate 8101*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 8102*7c478bd9Sstevel@tonic-gate 8103*7c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 8104*7c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 8105*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d using CIS window %d " 8106*7c478bd9Sstevel@tonic-gate "size 0x%x\n", (int)sp->socket_num, 8107*7c478bd9Sstevel@tonic-gate (int)sp->cis_win_num, 8108*7c478bd9Sstevel@tonic-gate (int)sp->cis_win_size); 8109*7c478bd9Sstevel@tonic-gate } 8110*7c478bd9Sstevel@tonic-gate #endif 8111*7c478bd9Sstevel@tonic-gate 8112*7c478bd9Sstevel@tonic-gate /* 8113*7c478bd9Sstevel@tonic-gate * Get the adapter information associated with this socket so 8114*7c478bd9Sstevel@tonic-gate * that we can initialize the mutexes, condition variables, 8115*7c478bd9Sstevel@tonic-gate * soft interrupt handler and per-socket adapter info. 8116*7c478bd9Sstevel@tonic-gate */ 8117*7c478bd9Sstevel@tonic-gate gcad = &sservice.get_cookies; 8118*7c478bd9Sstevel@tonic-gate gcad->socket = sp->socket_num; 8119*7c478bd9Sstevel@tonic-gate if (SocketServices(CSGetCookiesAndDip, &sservice) != SUCCESS) { 8120*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d CSGetCookiesAndDip " 8121*7c478bd9Sstevel@tonic-gate "failure\n", sp->socket_num); 8122*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8123*7c478bd9Sstevel@tonic-gate } /* CSGetCookiesAndDip */ 8124*7c478bd9Sstevel@tonic-gate 8125*7c478bd9Sstevel@tonic-gate /* 8126*7c478bd9Sstevel@tonic-gate * Save the iblock and idev cookies for RegisterClient 8127*7c478bd9Sstevel@tonic-gate */ 8128*7c478bd9Sstevel@tonic-gate sp->iblk = gcad->iblock; 8129*7c478bd9Sstevel@tonic-gate sp->idev = gcad->idevice; 8130*7c478bd9Sstevel@tonic-gate 8131*7c478bd9Sstevel@tonic-gate /* 8132*7c478bd9Sstevel@tonic-gate * Setup the per-socket adapter info 8133*7c478bd9Sstevel@tonic-gate */ 8134*7c478bd9Sstevel@tonic-gate sp->adapter.flags = 0; 8135*7c478bd9Sstevel@tonic-gate (void) strcpy(sp->adapter.name, gcad->adapter_info.name); 8136*7c478bd9Sstevel@tonic-gate sp->adapter.major = gcad->adapter_info.major; 8137*7c478bd9Sstevel@tonic-gate sp->adapter.minor = gcad->adapter_info.minor; 8138*7c478bd9Sstevel@tonic-gate sp->adapter.instance = ddi_get_instance(gcad->dip); 8139*7c478bd9Sstevel@tonic-gate sp->adapter.number = gcad->adapter_info.number; 8140*7c478bd9Sstevel@tonic-gate sp->adapter.num_sockets = gcad->adapter_info.num_sockets; 8141*7c478bd9Sstevel@tonic-gate sp->adapter.first_socket = gcad->adapter_info.first_socket; 8142*7c478bd9Sstevel@tonic-gate 8143*7c478bd9Sstevel@tonic-gate /* Setup for cs_event and cs_event_thread */ 8144*7c478bd9Sstevel@tonic-gate mutex_init(&sp->lock, NULL, MUTEX_DRIVER, *(gcad->iblock)); 8145*7c478bd9Sstevel@tonic-gate mutex_init(&sp->client_lock, NULL, MUTEX_DRIVER, NULL); 8146*7c478bd9Sstevel@tonic-gate mutex_init(&sp->cis_lock, NULL, MUTEX_DRIVER, NULL); 8147*7c478bd9Sstevel@tonic-gate 8148*7c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 8149*7c478bd9Sstevel@tonic-gate mutex_init(&sp->ss_thread_lock, NULL, MUTEX_DRIVER, NULL); 8150*7c478bd9Sstevel@tonic-gate 8151*7c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_MUTEX; 8152*7c478bd9Sstevel@tonic-gate 8153*7c478bd9Sstevel@tonic-gate /* Setup for cs_event_thread */ 8154*7c478bd9Sstevel@tonic-gate cv_init(&sp->thread_cv, NULL, CV_DRIVER, NULL); 8155*7c478bd9Sstevel@tonic-gate cv_init(&sp->caller_cv, NULL, CV_DRIVER, NULL); 8156*7c478bd9Sstevel@tonic-gate cv_init(&sp->reset_cv, NULL, CV_DRIVER, NULL); 8157*7c478bd9Sstevel@tonic-gate 8158*7c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 8159*7c478bd9Sstevel@tonic-gate cv_init(&sp->ss_thread_cv, NULL, CV_DRIVER, NULL); 8160*7c478bd9Sstevel@tonic-gate cv_init(&sp->ss_caller_cv, NULL, CV_DRIVER, NULL); 8161*7c478bd9Sstevel@tonic-gate 8162*7c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_CV; 8163*7c478bd9Sstevel@tonic-gate 8164*7c478bd9Sstevel@tonic-gate /* 8165*7c478bd9Sstevel@tonic-gate * If we haven't installed it yet, then install the soft interrupt 8166*7c478bd9Sstevel@tonic-gate * handler and save away the softint id. 8167*7c478bd9Sstevel@tonic-gate */ 8168*7c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR)) { 8169*7c478bd9Sstevel@tonic-gate if (ddi_add_softintr(gcad->dip, DDI_SOFTINT_HIGH, 8170*7c478bd9Sstevel@tonic-gate &sp->softint_id, 8171*7c478bd9Sstevel@tonic-gate NULL, NULL, 8172*7c478bd9Sstevel@tonic-gate cs_socket_event_softintr, 8173*7c478bd9Sstevel@tonic-gate (caddr_t)NULL) != DDI_SUCCESS) { 8174*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't add " 8175*7c478bd9Sstevel@tonic-gate "softintr\n", sp->socket_num); 8176*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8177*7c478bd9Sstevel@tonic-gate } /* ddi_add_softintr */ 8178*7c478bd9Sstevel@tonic-gate 8179*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 8180*7c478bd9Sstevel@tonic-gate cs_globals.softint_id = sp->softint_id; 8181*7c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SOFTINTR; 8182*7c478bd9Sstevel@tonic-gate /* XXX this timer is hokey at best... */ 8183*7c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 8184*7c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 8185*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 8186*7c478bd9Sstevel@tonic-gate } else { 8187*7c478bd9Sstevel@tonic-gate /* 8188*7c478bd9Sstevel@tonic-gate * We've already added the soft interrupt handler, so just 8189*7c478bd9Sstevel@tonic-gate * store away the softint id. 8190*7c478bd9Sstevel@tonic-gate */ 8191*7c478bd9Sstevel@tonic-gate sp->softint_id = cs_globals.softint_id; 8192*7c478bd9Sstevel@tonic-gate } /* if (!GLOBAL_INIT_STATE_SOFTINTR) */ 8193*7c478bd9Sstevel@tonic-gate 8194*7c478bd9Sstevel@tonic-gate /* 8195*7c478bd9Sstevel@tonic-gate * While this next flag doesn't really describe a per-socket 8196*7c478bd9Sstevel@tonic-gate * resource, we still set it for each socket. When the soft 8197*7c478bd9Sstevel@tonic-gate * interrupt handler finally gets removed in cs_deinit, this 8198*7c478bd9Sstevel@tonic-gate * flag will get cleared. 8199*7c478bd9Sstevel@tonic-gate */ 8200*7c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_SOFTINTR; 8201*7c478bd9Sstevel@tonic-gate 8202*7c478bd9Sstevel@tonic-gate /* 8203*7c478bd9Sstevel@tonic-gate * Socket Services defaults all sockets to power off and 8204*7c478bd9Sstevel@tonic-gate * clears all event masks. We want to receive at least 8205*7c478bd9Sstevel@tonic-gate * card insertion events, so enable them. Turn off power 8206*7c478bd9Sstevel@tonic-gate * to the socket as well. We will turn it on again when 8207*7c478bd9Sstevel@tonic-gate * we get a card insertion event. 8208*7c478bd9Sstevel@tonic-gate */ 8209*7c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 8210*7c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 8211*7c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 8212*7c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 8213*7c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 8214*7c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 8215*7c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 8216*7c478bd9Sstevel@tonic-gate 8217*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 8218*7c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 8219*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 8220*7c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 8221*7c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 8222*7c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 8223*7c478bd9Sstevel@tonic-gate 8224*7c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 8225*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d SS_SetSocket " 8226*7c478bd9Sstevel@tonic-gate "failure %d\n", sp->socket_num, ret); 8227*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8228*7c478bd9Sstevel@tonic-gate } /* SS_SetSocket */ 8229*7c478bd9Sstevel@tonic-gate 8230*7c478bd9Sstevel@tonic-gate /* 8231*7c478bd9Sstevel@tonic-gate * The various socket-specific variables are now set up, so 8232*7c478bd9Sstevel@tonic-gate * increment the global socket count and also mark the 8233*7c478bd9Sstevel@tonic-gate * socket as available. We need to set this before we 8234*7c478bd9Sstevel@tonic-gate * start any of the per-socket threads so that the threads 8235*7c478bd9Sstevel@tonic-gate * can get a valid socket pointer when they start. 8236*7c478bd9Sstevel@tonic-gate */ 8237*7c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 8238*7c478bd9Sstevel@tonic-gate cs_globals.num_sockets++; 8239*7c478bd9Sstevel@tonic-gate cs_globals.max_socket_num = 8240*7c478bd9Sstevel@tonic-gate max(cs_globals.max_socket_num, sp->socket_num + 1); 8241*7c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 8242*7c478bd9Sstevel@tonic-gate sp->flags = SOCKET_IS_VALID; 8243*7c478bd9Sstevel@tonic-gate 8244*7c478bd9Sstevel@tonic-gate /* 8245*7c478bd9Sstevel@tonic-gate * Create the per-socket event handler thread. 8246*7c478bd9Sstevel@tonic-gate */ 8247*7c478bd9Sstevel@tonic-gate sp->event_thread = CREATE_SOCKET_EVENT_THREAD(cs_event_thread, 8248*7c478bd9Sstevel@tonic-gate (uintptr_t)sn); 8249*7c478bd9Sstevel@tonic-gate 8250*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 8251*7c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_THREAD; 8252*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8253*7c478bd9Sstevel@tonic-gate 8254*7c478bd9Sstevel@tonic-gate /* 8255*7c478bd9Sstevel@tonic-gate * Create the per-socket Socket Services work thread. 8256*7c478bd9Sstevel@tonic-gate */ 8257*7c478bd9Sstevel@tonic-gate sp->ss_thread = CREATE_SOCKET_EVENT_THREAD(cs_ss_thread, 8258*7c478bd9Sstevel@tonic-gate (uintptr_t)sn); 8259*7c478bd9Sstevel@tonic-gate 8260*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 8261*7c478bd9Sstevel@tonic-gate sp->init_state |= (SOCKET_INIT_STATE_SS_THREAD | 8262*7c478bd9Sstevel@tonic-gate SOCKET_INIT_STATE_READY); 8263*7c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 8264*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8265*7c478bd9Sstevel@tonic-gate 8266*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8267*7c478bd9Sstevel@tonic-gate } 8268*7c478bd9Sstevel@tonic-gate 8269*7c478bd9Sstevel@tonic-gate /* 8270*7c478bd9Sstevel@tonic-gate * cs_drop_socket - drop a socket 8271*7c478bd9Sstevel@tonic-gate * 8272*7c478bd9Sstevel@tonic-gate * call: sn - socket number to drop 8273*7c478bd9Sstevel@tonic-gate * 8274*7c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 8275*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to drop socket 8276*7c478bd9Sstevel@tonic-gate */ 8277*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8278*7c478bd9Sstevel@tonic-gate static uint32_t 8279*7c478bd9Sstevel@tonic-gate cs_drop_socket(uint32_t sn) 8280*7c478bd9Sstevel@tonic-gate { 8281*7c478bd9Sstevel@tonic-gate #ifdef XXX 8282*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 8283*7c478bd9Sstevel@tonic-gate 8284*7c478bd9Sstevel@tonic-gate /* 8285*7c478bd9Sstevel@tonic-gate * Tell the socket event thread to exit and then wait for it 8286*7c478bd9Sstevel@tonic-gate * to do so. 8287*7c478bd9Sstevel@tonic-gate */ 8288*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8289*7c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_THREAD_EXIT; 8290*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 8291*7c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 8292*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8293*7c478bd9Sstevel@tonic-gate 8294*7c478bd9Sstevel@tonic-gate /* 8295*7c478bd9Sstevel@tonic-gate * Tell the socket SS thread to exit and then wait for it 8296*7c478bd9Sstevel@tonic-gate * to do so. 8297*7c478bd9Sstevel@tonic-gate */ 8298*7c478bd9Sstevel@tonic-gate 8299*7c478bd9Sstevel@tonic-gate /* 8300*7c478bd9Sstevel@tonic-gate * Mark the socket as dropped. 8301*7c478bd9Sstevel@tonic-gate */ 8302*7c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_VALID; 8303*7c478bd9Sstevel@tonic-gate 8304*7c478bd9Sstevel@tonic-gate #endif /* XXX */ 8305*7c478bd9Sstevel@tonic-gate 8306*7c478bd9Sstevel@tonic-gate /* XXX for now don't allow dropping sockets XXX */ 8307*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8308*7c478bd9Sstevel@tonic-gate } 8309*7c478bd9Sstevel@tonic-gate 8310*7c478bd9Sstevel@tonic-gate /* 8311*7c478bd9Sstevel@tonic-gate * cs_get_socket - returns the socket and function numbers and a pointer 8312*7c478bd9Sstevel@tonic-gate * to the socket structure 8313*7c478bd9Sstevel@tonic-gate * 8314*7c478bd9Sstevel@tonic-gate * calling: client_handle_t client_handle - client handle to extract 8315*7c478bd9Sstevel@tonic-gate * socket number from 8316*7c478bd9Sstevel@tonic-gate * uint32_t *socket - pointer to socket number to use if 8317*7c478bd9Sstevel@tonic-gate * client_handle is for the SS client; 8318*7c478bd9Sstevel@tonic-gate * this value will be filled in on 8319*7c478bd9Sstevel@tonic-gate * return with the correct socket 8320*7c478bd9Sstevel@tonic-gate * and function numbers if we 8321*7c478bd9Sstevel@tonic-gate * return CS_SUCCESS 8322*7c478bd9Sstevel@tonic-gate * uint32_t *function - pointer to return function number into 8323*7c478bd9Sstevel@tonic-gate * if not NULL 8324*7c478bd9Sstevel@tonic-gate * cs_socket_t **sp - pointer to a pointer where a pointer 8325*7c478bd9Sstevel@tonic-gate * to the socket struct will be 8326*7c478bd9Sstevel@tonic-gate * placed if this is non-NULL 8327*7c478bd9Sstevel@tonic-gate * client_t **clp - pointer to a pointer where a pointer 8328*7c478bd9Sstevel@tonic-gate * to the client struct will be 8329*7c478bd9Sstevel@tonic-gate * placed if this is non-NULL 8330*7c478bd9Sstevel@tonic-gate * 8331*7c478bd9Sstevel@tonic-gate * The socket and function numbers are derived as follows: 8332*7c478bd9Sstevel@tonic-gate * 8333*7c478bd9Sstevel@tonic-gate * Client Type Socket Number Function Number 8334*7c478bd9Sstevel@tonic-gate * PC card client From client_handle From client_handle 8335*7c478bd9Sstevel@tonic-gate * Socket Services client From *socket From *socket 8336*7c478bd9Sstevel@tonic-gate * CSI client From client_handle From *socket 8337*7c478bd9Sstevel@tonic-gate */ 8338*7c478bd9Sstevel@tonic-gate static uint32_t 8339*7c478bd9Sstevel@tonic-gate cs_get_socket(client_handle_t client_handle, uint32_t *socket, 8340*7c478bd9Sstevel@tonic-gate uint32_t *function, cs_socket_t **csp, client_t **clp) 8341*7c478bd9Sstevel@tonic-gate { 8342*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 8343*7c478bd9Sstevel@tonic-gate client_t *client; 8344*7c478bd9Sstevel@tonic-gate uint32_t sn, fn; 8345*7c478bd9Sstevel@tonic-gate int ret; 8346*7c478bd9Sstevel@tonic-gate 8347*7c478bd9Sstevel@tonic-gate sn = *socket; 8348*7c478bd9Sstevel@tonic-gate 8349*7c478bd9Sstevel@tonic-gate /* 8350*7c478bd9Sstevel@tonic-gate * If this is the Socket Services client, then return the 8351*7c478bd9Sstevel@tonic-gate * socket and function numbers specified in the passed 8352*7c478bd9Sstevel@tonic-gate * socket number parameter, otherwise extract the socket 8353*7c478bd9Sstevel@tonic-gate * and function numbers from the client handle. 8354*7c478bd9Sstevel@tonic-gate */ 8355*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 8356*7c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(sn); 8357*7c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(sn); 8358*7c478bd9Sstevel@tonic-gate } else { 8359*7c478bd9Sstevel@tonic-gate fn = GET_CLIENT_FUNCTION(client_handle); 8360*7c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(client_handle); 8361*7c478bd9Sstevel@tonic-gate } 8362*7c478bd9Sstevel@tonic-gate 8363*7c478bd9Sstevel@tonic-gate /* 8364*7c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 8365*7c478bd9Sstevel@tonic-gate */ 8366*7c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(sn, cs_globals.max_socket_num))) 8367*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8368*7c478bd9Sstevel@tonic-gate 8369*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 8370*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8371*7c478bd9Sstevel@tonic-gate 8372*7c478bd9Sstevel@tonic-gate /* 8373*7c478bd9Sstevel@tonic-gate * If we were given a pointer, then fill it in with a pointer 8374*7c478bd9Sstevel@tonic-gate * to this socket. 8375*7c478bd9Sstevel@tonic-gate */ 8376*7c478bd9Sstevel@tonic-gate if (csp) 8377*7c478bd9Sstevel@tonic-gate *csp = sp; 8378*7c478bd9Sstevel@tonic-gate 8379*7c478bd9Sstevel@tonic-gate /* 8380*7c478bd9Sstevel@tonic-gate * Search for the client; if it's not found, return an error. 8381*7c478bd9Sstevel@tonic-gate */ 8382*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 8383*7c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &ret))) { 8384*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8385*7c478bd9Sstevel@tonic-gate return (ret); 8386*7c478bd9Sstevel@tonic-gate } 8387*7c478bd9Sstevel@tonic-gate 8388*7c478bd9Sstevel@tonic-gate /* 8389*7c478bd9Sstevel@tonic-gate * If we're a CIS client, then extract the function number 8390*7c478bd9Sstevel@tonic-gate * from the socket number. 8391*7c478bd9Sstevel@tonic-gate */ 8392*7c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) 8393*7c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(*socket); 8394*7c478bd9Sstevel@tonic-gate 8395*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8396*7c478bd9Sstevel@tonic-gate 8397*7c478bd9Sstevel@tonic-gate /* 8398*7c478bd9Sstevel@tonic-gate * Return the found client pointer if the caller wants it. 8399*7c478bd9Sstevel@tonic-gate */ 8400*7c478bd9Sstevel@tonic-gate if (clp) 8401*7c478bd9Sstevel@tonic-gate *clp = client; 8402*7c478bd9Sstevel@tonic-gate 8403*7c478bd9Sstevel@tonic-gate /* 8404*7c478bd9Sstevel@tonic-gate * Return a socket number that is made up of the socket number 8405*7c478bd9Sstevel@tonic-gate * and the function number. 8406*7c478bd9Sstevel@tonic-gate */ 8407*7c478bd9Sstevel@tonic-gate *socket = CS_MAKE_SOCKET_NUMBER(sn, fn); 8408*7c478bd9Sstevel@tonic-gate 8409*7c478bd9Sstevel@tonic-gate /* 8410*7c478bd9Sstevel@tonic-gate * Return the function number if the caller wants it. 8411*7c478bd9Sstevel@tonic-gate */ 8412*7c478bd9Sstevel@tonic-gate if (function) 8413*7c478bd9Sstevel@tonic-gate *function = fn; 8414*7c478bd9Sstevel@tonic-gate 8415*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8416*7c478bd9Sstevel@tonic-gate } 8417*7c478bd9Sstevel@tonic-gate 8418*7c478bd9Sstevel@tonic-gate /* 8419*7c478bd9Sstevel@tonic-gate * cs_get_wp - returns pointer to passed window number 8420*7c478bd9Sstevel@tonic-gate * 8421*7c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 8422*7c478bd9Sstevel@tonic-gate * NULL - if invalid window number passed in 8423*7c478bd9Sstevel@tonic-gate */ 8424*7c478bd9Sstevel@tonic-gate static cs_window_t * 8425*7c478bd9Sstevel@tonic-gate cs_get_wp(uint32_t wn) 8426*7c478bd9Sstevel@tonic-gate { 8427*7c478bd9Sstevel@tonic-gate cs_window_t *cw; 8428*7c478bd9Sstevel@tonic-gate 8429*7c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 8430*7c478bd9Sstevel@tonic-gate return (NULL); 8431*7c478bd9Sstevel@tonic-gate 8432*7c478bd9Sstevel@tonic-gate if ((cw = cs_find_wp(wn)) == NULL) 8433*7c478bd9Sstevel@tonic-gate return (NULL); 8434*7c478bd9Sstevel@tonic-gate 8435*7c478bd9Sstevel@tonic-gate if (cw->state & CW_WINDOW_VALID) 8436*7c478bd9Sstevel@tonic-gate return (cw); 8437*7c478bd9Sstevel@tonic-gate 8438*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 8439*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 8440*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_wp(): wn=%d cw=%p\n", 8441*7c478bd9Sstevel@tonic-gate (int)wn, (void *)cw); 8442*7c478bd9Sstevel@tonic-gate } 8443*7c478bd9Sstevel@tonic-gate #endif 8444*7c478bd9Sstevel@tonic-gate 8445*7c478bd9Sstevel@tonic-gate return (NULL); 8446*7c478bd9Sstevel@tonic-gate } 8447*7c478bd9Sstevel@tonic-gate 8448*7c478bd9Sstevel@tonic-gate /* 8449*7c478bd9Sstevel@tonic-gate * cs_find_wp - searches window list and returns pointer to passed window 8450*7c478bd9Sstevel@tonic-gate * number 8451*7c478bd9Sstevel@tonic-gate * 8452*7c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 8453*7c478bd9Sstevel@tonic-gate * NULL - window not found 8454*7c478bd9Sstevel@tonic-gate */ 8455*7c478bd9Sstevel@tonic-gate static cs_window_t * 8456*7c478bd9Sstevel@tonic-gate cs_find_wp(uint32_t wn) 8457*7c478bd9Sstevel@tonic-gate { 8458*7c478bd9Sstevel@tonic-gate cs_window_t *cw = cs_globals.cw; 8459*7c478bd9Sstevel@tonic-gate 8460*7c478bd9Sstevel@tonic-gate while (cw) { 8461*7c478bd9Sstevel@tonic-gate if (cw->window_num == wn) 8462*7c478bd9Sstevel@tonic-gate return (cw); 8463*7c478bd9Sstevel@tonic-gate cw = cw->next; 8464*7c478bd9Sstevel@tonic-gate } /* while */ 8465*7c478bd9Sstevel@tonic-gate 8466*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 8467*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 8468*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_find_wp(): wn=%d window_num=%d cw=%p\n", 8469*7c478bd9Sstevel@tonic-gate (int)wn, (int)cw->window_num, (void *)cw); 8470*7c478bd9Sstevel@tonic-gate } 8471*7c478bd9Sstevel@tonic-gate #endif 8472*7c478bd9Sstevel@tonic-gate 8473*7c478bd9Sstevel@tonic-gate return (NULL); 8474*7c478bd9Sstevel@tonic-gate } 8475*7c478bd9Sstevel@tonic-gate 8476*7c478bd9Sstevel@tonic-gate /* 8477*7c478bd9Sstevel@tonic-gate * cs_add_windows - adds number of windows specified in "aw" to 8478*7c478bd9Sstevel@tonic-gate * the global window list; start the window 8479*7c478bd9Sstevel@tonic-gate * numbering at "bn" 8480*7c478bd9Sstevel@tonic-gate * 8481*7c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - if windows added sucessfully 8482*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if unable to add windows 8483*7c478bd9Sstevel@tonic-gate * 8484*7c478bd9Sstevel@tonic-gate * Note: The window list must be protected by a lock by the caller. 8485*7c478bd9Sstevel@tonic-gate */ 8486*7c478bd9Sstevel@tonic-gate static int 8487*7c478bd9Sstevel@tonic-gate cs_add_windows(int aw, uint32_t bn) 8488*7c478bd9Sstevel@tonic-gate { 8489*7c478bd9Sstevel@tonic-gate cs_window_t *cwp = cs_globals.cw; 8490*7c478bd9Sstevel@tonic-gate cs_window_t *cw, *cwpp; 8491*7c478bd9Sstevel@tonic-gate 8492*7c478bd9Sstevel@tonic-gate if (aw <= 0) 8493*7c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 8494*7c478bd9Sstevel@tonic-gate 8495*7c478bd9Sstevel@tonic-gate while (cwp) { 8496*7c478bd9Sstevel@tonic-gate cwpp = cwp; 8497*7c478bd9Sstevel@tonic-gate cwp = cwp->next; 8498*7c478bd9Sstevel@tonic-gate } 8499*7c478bd9Sstevel@tonic-gate 8500*7c478bd9Sstevel@tonic-gate while (aw--) { 8501*7c478bd9Sstevel@tonic-gate cw = (cs_window_t *)kmem_zalloc(sizeof (cs_window_t), KM_SLEEP); 8502*7c478bd9Sstevel@tonic-gate 8503*7c478bd9Sstevel@tonic-gate if (cs_globals.cw == NULL) { 8504*7c478bd9Sstevel@tonic-gate cs_globals.cw = cw; 8505*7c478bd9Sstevel@tonic-gate cwpp = cs_globals.cw; 8506*7c478bd9Sstevel@tonic-gate } else { 8507*7c478bd9Sstevel@tonic-gate cwpp->next = cw; 8508*7c478bd9Sstevel@tonic-gate cwpp = cwpp->next; 8509*7c478bd9Sstevel@tonic-gate } 8510*7c478bd9Sstevel@tonic-gate 8511*7c478bd9Sstevel@tonic-gate cwpp->window_num = bn++; 8512*7c478bd9Sstevel@tonic-gate cwpp->state = CW_WINDOW_VALID; 8513*7c478bd9Sstevel@tonic-gate 8514*7c478bd9Sstevel@tonic-gate } /* while (aw) */ 8515*7c478bd9Sstevel@tonic-gate 8516*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8517*7c478bd9Sstevel@tonic-gate } 8518*7c478bd9Sstevel@tonic-gate 8519*7c478bd9Sstevel@tonic-gate /* 8520*7c478bd9Sstevel@tonic-gate * cs_ss_init - initialize CS items that need to wait until we receive 8521*7c478bd9Sstevel@tonic-gate * a PCE_SS_INIT_STATE/PCE_SS_STATE_INIT event 8522*7c478bd9Sstevel@tonic-gate * 8523*7c478bd9Sstevel@tonic-gate * return: CS_SUCESS - if sucessfully initialized 8524*7c478bd9Sstevel@tonic-gate * (various) if error initializing 8525*7c478bd9Sstevel@tonic-gate * 8526*7c478bd9Sstevel@tonic-gate * At this point, we expect that Socket Services has setup the 8527*7c478bd9Sstevel@tonic-gate * following global variables for us: 8528*7c478bd9Sstevel@tonic-gate * 8529*7c478bd9Sstevel@tonic-gate * cs_socket_services - Socket Services entry point 8530*7c478bd9Sstevel@tonic-gate * cis_parser - CIS parser entry point 8531*7c478bd9Sstevel@tonic-gate */ 8532*7c478bd9Sstevel@tonic-gate static uint32_t 8533*7c478bd9Sstevel@tonic-gate cs_ss_init() 8534*7c478bd9Sstevel@tonic-gate { 8535*7c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 8536*7c478bd9Sstevel@tonic-gate csregister_t csr; 8537*7c478bd9Sstevel@tonic-gate uint32_t ret; 8538*7c478bd9Sstevel@tonic-gate 8539*7c478bd9Sstevel@tonic-gate /* 8540*7c478bd9Sstevel@tonic-gate * Fill out the parameters for CISP_CIS_SETUP 8541*7c478bd9Sstevel@tonic-gate */ 8542*7c478bd9Sstevel@tonic-gate csr.cs_magic = PCCS_MAGIC; 8543*7c478bd9Sstevel@tonic-gate csr.cs_version = PCCS_VERSION; 8544*7c478bd9Sstevel@tonic-gate csr.cs_card_services = CardServices; 8545*7c478bd9Sstevel@tonic-gate csr.cs_event = NULL; 8546*7c478bd9Sstevel@tonic-gate 8547*7c478bd9Sstevel@tonic-gate /* 8548*7c478bd9Sstevel@tonic-gate * Call into the CIS module and tell it what the private 8549*7c478bd9Sstevel@tonic-gate * Card Services entry point is. The CIS module will 8550*7c478bd9Sstevel@tonic-gate * call us back at CardServices(CISRegister, ...) 8551*7c478bd9Sstevel@tonic-gate * with the address of various CIS-specific global 8552*7c478bd9Sstevel@tonic-gate * data structures. 8553*7c478bd9Sstevel@tonic-gate */ 8554*7c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_SETUP, &csr); 8555*7c478bd9Sstevel@tonic-gate 8556*7c478bd9Sstevel@tonic-gate /* 8557*7c478bd9Sstevel@tonic-gate * Register with the Card Services kernel stubs module 8558*7c478bd9Sstevel@tonic-gate */ 8559*7c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 8560*7c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_REGISTER; 8561*7c478bd9Sstevel@tonic-gate rcs.cardservices = CardServices; 8562*7c478bd9Sstevel@tonic-gate 8563*7c478bd9Sstevel@tonic-gate if ((ret = csx_register_cardservices(&rcs)) != CS_SUCCESS) { 8564*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_init: can't register with " 8565*7c478bd9Sstevel@tonic-gate "cs_stubs, retcode = 0x%x\n", ret); 8566*7c478bd9Sstevel@tonic-gate return (ret); 8567*7c478bd9Sstevel@tonic-gate } /* csx_register_cardservices */ 8568*7c478bd9Sstevel@tonic-gate 8569*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8570*7c478bd9Sstevel@tonic-gate } 8571*7c478bd9Sstevel@tonic-gate 8572*7c478bd9Sstevel@tonic-gate /* 8573*7c478bd9Sstevel@tonic-gate * cs_create_cis - reads CIS on card in socket and creates CIS lists 8574*7c478bd9Sstevel@tonic-gate * 8575*7c478bd9Sstevel@tonic-gate * Most of the work is done in the CIS module in the CISP_CIS_LIST_CREATE 8576*7c478bd9Sstevel@tonic-gate * function. 8577*7c478bd9Sstevel@tonic-gate * 8578*7c478bd9Sstevel@tonic-gate * This function returns: 8579*7c478bd9Sstevel@tonic-gate * 8580*7c478bd9Sstevel@tonic-gate * CS_SUCCESS - if the CIS lists were created sucessfully 8581*7c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 8582*7c478bd9Sstevel@tonic-gate * not be setup 8583*7c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chains 8584*7c478bd9Sstevel@tonic-gate * CS_BAD_OFFSET - if the CIS parser tried to read past the 8585*7c478bd9Sstevel@tonic-gate * boundries of the allocated CIS window 8586*7c478bd9Sstevel@tonic-gate */ 8587*7c478bd9Sstevel@tonic-gate static int 8588*7c478bd9Sstevel@tonic-gate cs_create_cis(cs_socket_t *sp) 8589*7c478bd9Sstevel@tonic-gate { 8590*7c478bd9Sstevel@tonic-gate uint32_t ret; 8591*7c478bd9Sstevel@tonic-gate 8592*7c478bd9Sstevel@tonic-gate ret = (uint32_t)(uintptr_t)CIS_PARSER(CISP_CIS_LIST_CREATE, 8593*7c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, sp); 8594*7c478bd9Sstevel@tonic-gate 8595*7c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 8596*7c478bd9Sstevel@tonic-gate if (ret == CS_NO_CIS) { 8597*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 8598*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d has no CIS\n", 8599*7c478bd9Sstevel@tonic-gate sp->socket_num); 8600*7c478bd9Sstevel@tonic-gate } else if (ret != CS_SUCCESS) { 8601*7c478bd9Sstevel@tonic-gate if (cs_debug > 0) 8602*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d ERROR = 0x%x\n", 8603*7c478bd9Sstevel@tonic-gate sp->socket_num, ret); 8604*7c478bd9Sstevel@tonic-gate return (ret); 8605*7c478bd9Sstevel@tonic-gate } 8606*7c478bd9Sstevel@tonic-gate #else 8607*7c478bd9Sstevel@tonic-gate if (ret != CS_NO_CIS) 8608*7c478bd9Sstevel@tonic-gate if (ret != CS_SUCCESS) 8609*7c478bd9Sstevel@tonic-gate return (ret); 8610*7c478bd9Sstevel@tonic-gate #endif 8611*7c478bd9Sstevel@tonic-gate 8612*7c478bd9Sstevel@tonic-gate /* 8613*7c478bd9Sstevel@tonic-gate * If this card didn't have any CIS at all, there's not much 8614*7c478bd9Sstevel@tonic-gate * else for us to do. 8615*7c478bd9Sstevel@tonic-gate */ 8616*7c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_VALID_CIS)) 8617*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8618*7c478bd9Sstevel@tonic-gate 8619*7c478bd9Sstevel@tonic-gate /* 8620*7c478bd9Sstevel@tonic-gate * If this is a single-function card, we need to move the CIS list 8621*7c478bd9Sstevel@tonic-gate * that is currently on CS_GLOBAL_CIS to the function zero 8622*7c478bd9Sstevel@tonic-gate * CIS list. 8623*7c478bd9Sstevel@tonic-gate */ 8624*7c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_MULTI_FUNCTION_CIS)) { 8625*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)&sp->cis[CS_GLOBAL_CIS], 8626*7c478bd9Sstevel@tonic-gate (caddr_t)&sp->cis[0], sizeof (cis_info_t)); 8627*7c478bd9Sstevel@tonic-gate bzero((caddr_t)&sp->cis[CS_GLOBAL_CIS], sizeof (cis_info_t)); 8628*7c478bd9Sstevel@tonic-gate } /* !CW_MULTI_FUNCTION_CIS */ 8629*7c478bd9Sstevel@tonic-gate 8630*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8631*7c478bd9Sstevel@tonic-gate } 8632*7c478bd9Sstevel@tonic-gate 8633*7c478bd9Sstevel@tonic-gate /* 8634*7c478bd9Sstevel@tonic-gate * cs_destroy_cis - destroys CIS list for socket 8635*7c478bd9Sstevel@tonic-gate */ 8636*7c478bd9Sstevel@tonic-gate static int 8637*7c478bd9Sstevel@tonic-gate cs_destroy_cis(cs_socket_t *sp) 8638*7c478bd9Sstevel@tonic-gate { 8639*7c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_LIST_DESTROY, sp); 8640*7c478bd9Sstevel@tonic-gate 8641*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8642*7c478bd9Sstevel@tonic-gate } 8643*7c478bd9Sstevel@tonic-gate 8644*7c478bd9Sstevel@tonic-gate /* 8645*7c478bd9Sstevel@tonic-gate * cs_get_client_info - This function is GetClientInfo. 8646*7c478bd9Sstevel@tonic-gate * 8647*7c478bd9Sstevel@tonic-gate * calling: client_handle_t - client handle to get client info on 8648*7c478bd9Sstevel@tonic-gate * client_info_t * - pointer to a client_info_t structure 8649*7c478bd9Sstevel@tonic-gate * to return client information in 8650*7c478bd9Sstevel@tonic-gate * 8651*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 8652*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8653*7c478bd9Sstevel@tonic-gate * handle passed in 8654*7c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 8655*7c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 8656*7c478bd9Sstevel@tonic-gate * or if invalid client info 8657*7c478bd9Sstevel@tonic-gate * retreived from client 8658*7c478bd9Sstevel@tonic-gate */ 8659*7c478bd9Sstevel@tonic-gate static int 8660*7c478bd9Sstevel@tonic-gate cs_get_client_info(client_handle_t client_handle, client_info_t *ci) 8661*7c478bd9Sstevel@tonic-gate { 8662*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 8663*7c478bd9Sstevel@tonic-gate client_t *client; 8664*7c478bd9Sstevel@tonic-gate client_info_t *cinfo; 8665*7c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 8666*7c478bd9Sstevel@tonic-gate 8667*7c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 8668*7c478bd9Sstevel@tonic-gate ci->Attributes = (CS_CLIENT_INFO_SOCKET_SERVICES | 8669*7c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_VALID); 8670*7c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 8671*7c478bd9Sstevel@tonic-gate } /* CLIENT_HANDLE_IS_SS */ 8672*7c478bd9Sstevel@tonic-gate 8673*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 8674*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8675*7c478bd9Sstevel@tonic-gate 8676*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8677*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 8678*7c478bd9Sstevel@tonic-gate 8679*7c478bd9Sstevel@tonic-gate if ((client = cs_find_client(client_handle, &ret)) == NULL) { 8680*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8681*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8682*7c478bd9Sstevel@tonic-gate return (ret); 8683*7c478bd9Sstevel@tonic-gate } /* cs_find_client */ 8684*7c478bd9Sstevel@tonic-gate 8685*7c478bd9Sstevel@tonic-gate /* 8686*7c478bd9Sstevel@tonic-gate * If this client is not handling CS_EVENT_CLIENT_INFO events, 8687*7c478bd9Sstevel@tonic-gate * then don't bother to even wake up the event thread. 8688*7c478bd9Sstevel@tonic-gate */ 8689*7c478bd9Sstevel@tonic-gate if (!((client->event_mask | client->global_mask) & 8690*7c478bd9Sstevel@tonic-gate CS_EVENT_CLIENT_INFO)) { 8691*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8692*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8693*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8694*7c478bd9Sstevel@tonic-gate } /* !CS_EVENT_CLIENT_INFO */ 8695*7c478bd9Sstevel@tonic-gate 8696*7c478bd9Sstevel@tonic-gate cinfo = &client->event_callback_args.client_info; 8697*7c478bd9Sstevel@tonic-gate 8698*7c478bd9Sstevel@tonic-gate bzero((caddr_t)cinfo, sizeof (client_info_t)); 8699*7c478bd9Sstevel@tonic-gate cinfo->Attributes = (ci->Attributes & CS_CLIENT_INFO_SUBSVC_MASK); 8700*7c478bd9Sstevel@tonic-gate 8701*7c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CLIENT_INFO; 8702*7c478bd9Sstevel@tonic-gate 8703*7c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 8704*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 8705*7c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 8706*7c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 8707*7c478bd9Sstevel@tonic-gate 8708*7c478bd9Sstevel@tonic-gate if (cinfo->Attributes & CS_CLIENT_INFO_VALID) { 8709*7c478bd9Sstevel@tonic-gate bcopy((caddr_t)cinfo, (caddr_t)ci, sizeof (client_info_t)); 8710*7c478bd9Sstevel@tonic-gate ci->Attributes &= (CS_CLIENT_INFO_FLAGS_MASK | 8711*7c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_SUBSVC_MASK); 8712*7c478bd9Sstevel@tonic-gate ci->Attributes &= ~(CS_CLIENT_INFO_CLIENT_MASK | 8713*7c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK | 8714*7c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_CLIENT_ACTIVE); 8715*7c478bd9Sstevel@tonic-gate ci->Attributes |= (client->flags & (CS_CLIENT_INFO_CLIENT_MASK | 8716*7c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK)); 8717*7c478bd9Sstevel@tonic-gate (void) strcpy(ci->DriverName, client->driver_name); 8718*7c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) 8719*7c478bd9Sstevel@tonic-gate ci->Attributes |= CS_CLIENT_INFO_CLIENT_ACTIVE; 8720*7c478bd9Sstevel@tonic-gate } else { 8721*7c478bd9Sstevel@tonic-gate ret = CS_NO_MORE_ITEMS; 8722*7c478bd9Sstevel@tonic-gate } /* CS_CLIENT_INFO_VALID */ 8723*7c478bd9Sstevel@tonic-gate 8724*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8725*7c478bd9Sstevel@tonic-gate 8726*7c478bd9Sstevel@tonic-gate return (ret); 8727*7c478bd9Sstevel@tonic-gate } 8728*7c478bd9Sstevel@tonic-gate 8729*7c478bd9Sstevel@tonic-gate /* 8730*7c478bd9Sstevel@tonic-gate * cs_get_firstnext_client - This function is GetFirstClient and 8731*7c478bd9Sstevel@tonic-gate * GetNextClient 8732*7c478bd9Sstevel@tonic-gate * 8733*7c478bd9Sstevel@tonic-gate * calling: get_firstnext_client_t * - pointer to a get_firstnext_client_t 8734*7c478bd9Sstevel@tonic-gate * structure to return client handle and 8735*7c478bd9Sstevel@tonic-gate * attributes in 8736*7c478bd9Sstevel@tonic-gate * flags - one of the following: 8737*7c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG - get first client handle 8738*7c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG - get next client handle 8739*7c478bd9Sstevel@tonic-gate * 8740*7c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 8741*7c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 8742*7c478bd9Sstevel@tonic-gate * handle passed in 8743*7c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 8744*7c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 8745*7c478bd9Sstevel@tonic-gate * or if invalid client info 8746*7c478bd9Sstevel@tonic-gate * retreived from client 8747*7c478bd9Sstevel@tonic-gate */ 8748*7c478bd9Sstevel@tonic-gate static int 8749*7c478bd9Sstevel@tonic-gate cs_get_firstnext_client(get_firstnext_client_t *fnc, uint32_t flags) 8750*7c478bd9Sstevel@tonic-gate { 8751*7c478bd9Sstevel@tonic-gate cs_socket_t *sp; 8752*7c478bd9Sstevel@tonic-gate client_t *client; 8753*7c478bd9Sstevel@tonic-gate uint32_t sn = 0; 8754*7c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 8755*7c478bd9Sstevel@tonic-gate 8756*7c478bd9Sstevel@tonic-gate switch (flags) { 8757*7c478bd9Sstevel@tonic-gate case CS_GET_FIRST_FLAG: 8758*7c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8759*7c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 8760*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 8761*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8762*7c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 8763*7c478bd9Sstevel@tonic-gate break; 8764*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8765*7c478bd9Sstevel@tonic-gate } /* if */ 8766*7c478bd9Sstevel@tonic-gate sn++; 8767*7c478bd9Sstevel@tonic-gate } /* while */ 8768*7c478bd9Sstevel@tonic-gate 8769*7c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 8770*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8771*7c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 8772*7c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8773*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(fnc->Socket))) == 8774*7c478bd9Sstevel@tonic-gate NULL) 8775*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8776*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8777*7c478bd9Sstevel@tonic-gate if ((client = sp->client_list) == NULL) { 8778*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8779*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8780*7c478bd9Sstevel@tonic-gate } 8781*7c478bd9Sstevel@tonic-gate } else { 8782*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 8783*7c478bd9Sstevel@tonic-gate } 8784*7c478bd9Sstevel@tonic-gate 8785*7c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 8786*7c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 8787*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8788*7c478bd9Sstevel@tonic-gate break; 8789*7c478bd9Sstevel@tonic-gate case CS_GET_NEXT_FLAG: 8790*7c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 8791*7c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(fnc->client_handle); 8792*7c478bd9Sstevel@tonic-gate 8793*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 8794*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8795*7c478bd9Sstevel@tonic-gate 8796*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8797*7c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 8798*7c478bd9Sstevel@tonic-gate &ret)) == NULL) { 8799*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8800*7c478bd9Sstevel@tonic-gate return (ret); 8801*7c478bd9Sstevel@tonic-gate } 8802*7c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 8803*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8804*7c478bd9Sstevel@tonic-gate sn++; 8805*7c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 8806*7c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 8807*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8808*7c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 8809*7c478bd9Sstevel@tonic-gate break; 8810*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8811*7c478bd9Sstevel@tonic-gate } /* if */ 8812*7c478bd9Sstevel@tonic-gate sn++; 8813*7c478bd9Sstevel@tonic-gate } /* while */ 8814*7c478bd9Sstevel@tonic-gate 8815*7c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 8816*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8817*7c478bd9Sstevel@tonic-gate } /* client = client->next */ 8818*7c478bd9Sstevel@tonic-gate 8819*7c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 8820*7c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 8821*7c478bd9Sstevel@tonic-gate sp = cs_get_sp(GET_CLIENT_SOCKET(fnc->client_handle)); 8822*7c478bd9Sstevel@tonic-gate if (sp == NULL) 8823*7c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 8824*7c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 8825*7c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 8826*7c478bd9Sstevel@tonic-gate &ret)) == NULL) { 8827*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8828*7c478bd9Sstevel@tonic-gate return (ret); 8829*7c478bd9Sstevel@tonic-gate } 8830*7c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 8831*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8832*7c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 8833*7c478bd9Sstevel@tonic-gate } 8834*7c478bd9Sstevel@tonic-gate } else { 8835*7c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 8836*7c478bd9Sstevel@tonic-gate } 8837*7c478bd9Sstevel@tonic-gate 8838*7c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 8839*7c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 8840*7c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 8841*7c478bd9Sstevel@tonic-gate break; 8842*7c478bd9Sstevel@tonic-gate default: 8843*7c478bd9Sstevel@tonic-gate ret = CS_BAD_ATTRIBUTE; 8844*7c478bd9Sstevel@tonic-gate break; 8845*7c478bd9Sstevel@tonic-gate 8846*7c478bd9Sstevel@tonic-gate } /* switch */ 8847*7c478bd9Sstevel@tonic-gate 8848*7c478bd9Sstevel@tonic-gate return (ret); 8849*7c478bd9Sstevel@tonic-gate } 8850*7c478bd9Sstevel@tonic-gate 8851*7c478bd9Sstevel@tonic-gate /* 8852*7c478bd9Sstevel@tonic-gate * cs_set_acc_attributes - converts Card Services endianness and 8853*7c478bd9Sstevel@tonic-gate * data ordering values to values 8854*7c478bd9Sstevel@tonic-gate * that Socket Services understands 8855*7c478bd9Sstevel@tonic-gate * 8856*7c478bd9Sstevel@tonic-gate * calling: *sw - pointer to a set_window_t to set attributes in 8857*7c478bd9Sstevel@tonic-gate * Attributes - CS attributes 8858*7c478bd9Sstevel@tonic-gate */ 8859*7c478bd9Sstevel@tonic-gate static void 8860*7c478bd9Sstevel@tonic-gate cs_set_acc_attributes(set_window_t *sw, uint32_t Attributes) 8861*7c478bd9Sstevel@tonic-gate { 8862*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 8863*7c478bd9Sstevel@tonic-gate 8864*7c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ENDIAN_MASK) { 8865*7c478bd9Sstevel@tonic-gate case WIN_ACC_LITTLE_ENDIAN: 8866*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 8867*7c478bd9Sstevel@tonic-gate break; 8868*7c478bd9Sstevel@tonic-gate case WIN_ACC_BIG_ENDIAN: 8869*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 8870*7c478bd9Sstevel@tonic-gate break; 8871*7c478bd9Sstevel@tonic-gate case WIN_ACC_NEVER_SWAP: 8872*7c478bd9Sstevel@tonic-gate default: 8873*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 8874*7c478bd9Sstevel@tonic-gate break; 8875*7c478bd9Sstevel@tonic-gate } /* switch */ 8876*7c478bd9Sstevel@tonic-gate 8877*7c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ORDER_MASK) { 8878*7c478bd9Sstevel@tonic-gate case WIN_ACC_UNORDERED_OK: 8879*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC; 8880*7c478bd9Sstevel@tonic-gate break; 8881*7c478bd9Sstevel@tonic-gate case WIN_ACC_MERGING_OK: 8882*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_MERGING_OK_ACC; 8883*7c478bd9Sstevel@tonic-gate break; 8884*7c478bd9Sstevel@tonic-gate case WIN_ACC_LOADCACHING_OK: 8885*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_LOADCACHING_OK_ACC; 8886*7c478bd9Sstevel@tonic-gate break; 8887*7c478bd9Sstevel@tonic-gate case WIN_ACC_STORECACHING_OK: 8888*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC; 8889*7c478bd9Sstevel@tonic-gate break; 8890*7c478bd9Sstevel@tonic-gate case WIN_ACC_STRICT_ORDER: 8891*7c478bd9Sstevel@tonic-gate default: 8892*7c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 8893*7c478bd9Sstevel@tonic-gate break; 8894*7c478bd9Sstevel@tonic-gate } /* switch */ 8895*7c478bd9Sstevel@tonic-gate } 8896