17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 235f9e250aShx * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * PCMCIA Card Services 297c478bd9Sstevel@tonic-gate * The PCMCIA Card Services is a loadable module which 307c478bd9Sstevel@tonic-gate * presents the Card Services interface to client device 317c478bd9Sstevel@tonic-gate * drivers. 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * Card Services uses Socket Services-like calls into the 347c478bd9Sstevel@tonic-gate * PCMCIA nexus driver to manipulate socket and adapter 357c478bd9Sstevel@tonic-gate * resources. 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * Note that a bunch of comments are not indented correctly with the 387c478bd9Sstevel@tonic-gate * code that they are commenting on. This is because cstyle is 397c478bd9Sstevel@tonic-gate * is inflexible concerning 4-column indenting. 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #if defined(DEBUG) 437c478bd9Sstevel@tonic-gate #define CS_DEBUG 447c478bd9Sstevel@tonic-gate #endif 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <sys/types.h> 477c478bd9Sstevel@tonic-gate #include <sys/systm.h> 487c478bd9Sstevel@tonic-gate #include <sys/user.h> 497c478bd9Sstevel@tonic-gate #include <sys/buf.h> 507c478bd9Sstevel@tonic-gate #include <sys/file.h> 517c478bd9Sstevel@tonic-gate #include <sys/uio.h> 527c478bd9Sstevel@tonic-gate #include <sys/conf.h> 537c478bd9Sstevel@tonic-gate #include <sys/stat.h> 547c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 557c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 567c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 577c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 587c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 597c478bd9Sstevel@tonic-gate #include <sys/debug.h> 607c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 617c478bd9Sstevel@tonic-gate #include <sys/var.h> 627c478bd9Sstevel@tonic-gate #include <sys/proc.h> 637c478bd9Sstevel@tonic-gate #include <sys/thread.h> 647c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 657c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 667c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 677c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 687c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 697c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 707c478bd9Sstevel@tonic-gate #include <sys/callb.h> 717c478bd9Sstevel@tonic-gate #include <sys/time.h> 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #include <sys/pctypes.h> 747c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h> 757c478bd9Sstevel@tonic-gate #include <sys/pcmcia.h> 767c478bd9Sstevel@tonic-gate #include <sys/sservice.h> 777c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis.h> 787c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h> 797c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs.h> 807c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h> 817c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_stubs.h> 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * The cs_strings header file is where all of the major strings that 857c478bd9Sstevel@tonic-gate * Card Services uses are located. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_strings.h> 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Function declarations 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * The main Card Services entry point 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate int CardServices(int function, ...); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * functions and globals used by Socket Services 997c478bd9Sstevel@tonic-gate * 1007c478bd9Sstevel@tonic-gate * WAS: void *(*cis_parser)(int, ...) = NULL; 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate void *(*cis_parser)(int, ...) = NULL; 1037c478bd9Sstevel@tonic-gate csfunction_t *cs_socket_services = NULL; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * event handling functions 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate static event_t ss_to_cs_events(cs_socket_t *, event_t); 1097c478bd9Sstevel@tonic-gate static event_t cs_cse2sbm(event_t); 1107c478bd9Sstevel@tonic-gate static void cs_event_thread(uint32_t); 1117c478bd9Sstevel@tonic-gate static int cs_card_insertion(cs_socket_t *, event_t); 1127c478bd9Sstevel@tonic-gate static int cs_card_removal(cs_socket_t *); 1137c478bd9Sstevel@tonic-gate static void cs_ss_thread(uint32_t); 1147c478bd9Sstevel@tonic-gate void cs_ready_timeout(void *); 1157c478bd9Sstevel@tonic-gate static int cs_card_for_client(client_t *); 1167c478bd9Sstevel@tonic-gate static int cs_request_socket_mask(client_handle_t, request_socket_mask_t *); 1177c478bd9Sstevel@tonic-gate static int cs_release_socket_mask(client_handle_t, release_socket_mask_t *); 1187c478bd9Sstevel@tonic-gate static int cs_get_event_mask(client_handle_t, sockevent_t *); 1197c478bd9Sstevel@tonic-gate static int cs_set_event_mask(client_handle_t, sockevent_t *); 1207c478bd9Sstevel@tonic-gate static int cs_event2text(event2text_t *, int); 1217c478bd9Sstevel@tonic-gate static int cs_read_event_status(cs_socket_t *, client_t *, event_t *, 1227c478bd9Sstevel@tonic-gate get_ss_status_t *, int); 1237c478bd9Sstevel@tonic-gate uint32_t cs_socket_event_softintr(caddr_t); 1247c478bd9Sstevel@tonic-gate void cs_event_softintr_timeout(void *); 1257c478bd9Sstevel@tonic-gate static int cs_get_status(client_handle_t, get_status_t *); 1267c478bd9Sstevel@tonic-gate static uint32_t cs_sbm2cse(uint32_t); 1277c478bd9Sstevel@tonic-gate static unsigned cs_merge_event_masks(cs_socket_t *, client_t *); 1287c478bd9Sstevel@tonic-gate static int cs_set_socket_event_mask(cs_socket_t *, unsigned); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate /* 1317c478bd9Sstevel@tonic-gate * SS<->CS communication and internal socket and window handling functions 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate static uint32_t cs_add_socket(uint32_t); 1347c478bd9Sstevel@tonic-gate static uint32_t cs_drop_socket(uint32_t); 1357c478bd9Sstevel@tonic-gate static cs_socket_t *cs_get_sp(uint32_t); 1367c478bd9Sstevel@tonic-gate static cs_socket_t *cs_find_sp(uint32_t); 1377c478bd9Sstevel@tonic-gate static cs_window_t *cs_get_wp(uint32_t); 1387c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_wp(uint32_t); 1397c478bd9Sstevel@tonic-gate static int cs_add_windows(int, uint32_t); 1407c478bd9Sstevel@tonic-gate static uint32_t cs_ss_init(); 1417c478bd9Sstevel@tonic-gate static void cs_set_acc_attributes(set_window_t *, uint32_t); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * CIS handling functions 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate cistpl_callout_t *cis_cistpl_std_callout; 1477c478bd9Sstevel@tonic-gate static int cs_parse_tuple(client_handle_t, tuple_t *, cisparse_t *, cisdata_t); 1487c478bd9Sstevel@tonic-gate static int cs_get_tuple_data(client_handle_t, tuple_t *); 1497c478bd9Sstevel@tonic-gate static int cs_validate_cis(client_handle_t, cisinfo_t *); 1507c478bd9Sstevel@tonic-gate static int cs_get_firstnext_tuple(client_handle_t, tuple_t *, uint32_t); 1517c478bd9Sstevel@tonic-gate static int cs_create_cis(cs_socket_t *); 1527c478bd9Sstevel@tonic-gate static int cs_destroy_cis(cs_socket_t *); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * client handling functions 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate unsigned cs_create_next_client_minor(unsigned, unsigned); 1587c478bd9Sstevel@tonic-gate static client_t *cs_find_client(client_handle_t, int *); 1597c478bd9Sstevel@tonic-gate static client_handle_t cs_create_client_handle(unsigned, client_t *); 1607c478bd9Sstevel@tonic-gate static int cs_destroy_client_handle(client_handle_t); 1617c478bd9Sstevel@tonic-gate static int cs_register_client(client_handle_t *, client_reg_t *); 1627c478bd9Sstevel@tonic-gate static int cs_deregister_client(client_handle_t); 1637c478bd9Sstevel@tonic-gate static int cs_deregister_mtd(client_handle_t); 1647c478bd9Sstevel@tonic-gate static void cs_clear_superclient_lock(int); 1657c478bd9Sstevel@tonic-gate static int cs_add_client_to_socket(unsigned, client_handle_t *, 1667c478bd9Sstevel@tonic-gate client_reg_t *, int); 1677c478bd9Sstevel@tonic-gate static int cs_get_client_info(client_handle_t, client_info_t *); 1687c478bd9Sstevel@tonic-gate static int cs_get_firstnext_client(get_firstnext_client_t *, uint32_t); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * window handling functions 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate static int cs_request_window(client_handle_t, window_handle_t *, win_req_t *); 1747c478bd9Sstevel@tonic-gate static int cs_release_window(window_handle_t); 1757c478bd9Sstevel@tonic-gate static int cs_modify_window(window_handle_t, modify_win_t *); 1767c478bd9Sstevel@tonic-gate static int cs_modify_mem_window(window_handle_t, modify_win_t *, win_req_t *, 1777c478bd9Sstevel@tonic-gate int); 1787c478bd9Sstevel@tonic-gate static int cs_map_mem_page(window_handle_t, map_mem_page_t *); 1797c478bd9Sstevel@tonic-gate static int cs_find_mem_window(uint32_t, win_req_t *, uint32_t *); 1807c478bd9Sstevel@tonic-gate static int cs_memwin_space_and_map_ok(inquire_window_t *, win_req_t *); 1817c478bd9Sstevel@tonic-gate static int cs_valid_window_speed(inquire_window_t *, uint32_t); 1827c478bd9Sstevel@tonic-gate static window_handle_t cs_create_window_handle(uint32_t); 1837c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_window(window_handle_t); 1847c478bd9Sstevel@tonic-gate static int cs_find_io_win(uint32_t, iowin_char_t *, uint32_t *, uint32_t *); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * IO, IRQ and configuration handling functions 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate static int cs_request_io(client_handle_t, io_req_t *); 1907c478bd9Sstevel@tonic-gate static int cs_release_io(client_handle_t, io_req_t *); 1917c478bd9Sstevel@tonic-gate static int cs_allocate_io_win(uint32_t, uint32_t, uint32_t *); 1927c478bd9Sstevel@tonic-gate static int cs_setup_io_win(uint32_t, uint32_t, baseaddru_t *, 1937c478bd9Sstevel@tonic-gate uint32_t *, uint32_t, uint32_t); 1947c478bd9Sstevel@tonic-gate static int cs_request_irq(client_handle_t, irq_req_t *); 1957c478bd9Sstevel@tonic-gate static int cs_release_irq(client_handle_t, irq_req_t *); 1967c478bd9Sstevel@tonic-gate static int cs_request_configuration(client_handle_t, config_req_t *); 1977c478bd9Sstevel@tonic-gate static int cs_release_configuration(client_handle_t, release_config_t *); 1987c478bd9Sstevel@tonic-gate static int cs_modify_configuration(client_handle_t, modify_config_t *); 1997c478bd9Sstevel@tonic-gate static int cs_access_configuration_register(client_handle_t, 2007c478bd9Sstevel@tonic-gate access_config_reg_t *); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * RESET and general info functions 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate static int cs_reset_function(client_handle_t, reset_function_t *); 2067c478bd9Sstevel@tonic-gate static int cs_get_configuration_info(client_handle_t *, 2077c478bd9Sstevel@tonic-gate get_configuration_info_t *); 2087c478bd9Sstevel@tonic-gate static int cs_get_cardservices_info(client_handle_t, 2097c478bd9Sstevel@tonic-gate get_cardservices_info_t *); 2107c478bd9Sstevel@tonic-gate static int cs_get_physical_adapter_info(client_handle_t, 2117c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * general functions 2157c478bd9Sstevel@tonic-gate */ 2167c478bd9Sstevel@tonic-gate static uint32_t cs_get_socket(client_handle_t, uint32_t *, uint32_t *, 2177c478bd9Sstevel@tonic-gate cs_socket_t **, client_t **); 2187c478bd9Sstevel@tonic-gate static int cs_convert_speed(convert_speed_t *); 2197c478bd9Sstevel@tonic-gate static int cs_convert_size(convert_size_t *); 2207c478bd9Sstevel@tonic-gate static char *cs_error2text(int, int); 2217c478bd9Sstevel@tonic-gate static int cs_map_log_socket(client_handle_t, map_log_socket_t *); 2227c478bd9Sstevel@tonic-gate static int cs_convert_powerlevel(uint32_t, uint32_t, uint32_t, unsigned *); 2237c478bd9Sstevel@tonic-gate static int cs_make_device_node(client_handle_t, make_device_node_t *); 2247c478bd9Sstevel@tonic-gate static int cs_remove_device_node(client_handle_t, remove_device_node_t *); 2257c478bd9Sstevel@tonic-gate static int cs_ddi_info(cs_ddi_info_t *); 2267c478bd9Sstevel@tonic-gate static int cs_init_cis_window(cs_socket_t *, uint32_t *, acc_handle_t *, 2277c478bd9Sstevel@tonic-gate uint32_t); 2287c478bd9Sstevel@tonic-gate static int cs_sys_ctl(cs_sys_ctl_t *); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * global variables 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate static int cs_max_client_handles = CS_MAX_CLIENTS; 2347c478bd9Sstevel@tonic-gate static client_t cs_socket_services_client; /* global SS client */ 2357c478bd9Sstevel@tonic-gate static client_types_t client_types[MAX_CLIENT_TYPES]; 2367c478bd9Sstevel@tonic-gate static cs_globals_t cs_globals; 2377c478bd9Sstevel@tonic-gate int cs_reset_timeout_time = RESET_TIMEOUT_TIME; 2387c478bd9Sstevel@tonic-gate int cs_rc1_delay = CS_RC1_DELAY; 2397c478bd9Sstevel@tonic-gate int cs_rc2_delay = CS_RC2_DELAY; 2407c478bd9Sstevel@tonic-gate int cs_rq_delay = CS_RQ_DELAY; 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2437c478bd9Sstevel@tonic-gate int cs_debug = 0; 2447c478bd9Sstevel@tonic-gate #endif 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * cs_init - Initialize CS internal structures, databases, and state, 2487c478bd9Sstevel@tonic-gate * and register with SS 2497c478bd9Sstevel@tonic-gate * 2507c478bd9Sstevel@tonic-gate * XXX - Need to make sure that if we fail at any point that we free 2517c478bd9Sstevel@tonic-gate * any resources that we allocated, as well as kill any 2527c478bd9Sstevel@tonic-gate * threads that may have been started. 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate int 2557c478bd9Sstevel@tonic-gate cs_init() 2567c478bd9Sstevel@tonic-gate { 2577c478bd9Sstevel@tonic-gate client_types_t *ct; 2587c478bd9Sstevel@tonic-gate client_t *client; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * Initialize the CS global structure 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate bzero((caddr_t)&cs_globals, sizeof (cs_globals_t)); 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.global_lock, NULL, MUTEX_DRIVER, NULL); 2667c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.window_lock, NULL, MUTEX_DRIVER, NULL); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate cs_globals.init_state = GLOBAL_INIT_STATE_MUTEX; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * Set up the global Socket Services client, since we're going to 2727c478bd9Sstevel@tonic-gate * need it once we register with SS. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate client = &cs_socket_services_client; 2757c478bd9Sstevel@tonic-gate bzero((caddr_t)client, sizeof (client_t)); 2767c478bd9Sstevel@tonic-gate client->client_handle = CS_SS_CLIENT_HANDLE; 2777c478bd9Sstevel@tonic-gate client->flags |= (INFO_SOCKET_SERVICES | CLIENT_CARD_INSERTED); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Setup the client type structure - this is used in the socket event 2817c478bd9Sstevel@tonic-gate * thread to sequence the delivery of events to all clients on 2827c478bd9Sstevel@tonic-gate * the socket. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate ct = &client_types[0]; 2857c478bd9Sstevel@tonic-gate ct->type = INFO_IO_CLIENT; 2867c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_LIFO; 2877c478bd9Sstevel@tonic-gate ct->next = &client_types[1]; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate ct = ct->next; 2907c478bd9Sstevel@tonic-gate ct->type = INFO_MTD_CLIENT; 2917c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 2927c478bd9Sstevel@tonic-gate ct->next = &client_types[2]; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate ct = ct->next; 2957c478bd9Sstevel@tonic-gate ct->type = INFO_MEM_CLIENT; 2967c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 2977c478bd9Sstevel@tonic-gate ct->next = NULL; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * cs_deinit - Deinitialize CS 3047c478bd9Sstevel@tonic-gate * 3057c478bd9Sstevel@tonic-gate * This function cleans up any allocated resources, stops any running threads, 3067c478bd9Sstevel@tonic-gate * destroys any mutexes and condition variables, and finally frees up the 3077c478bd9Sstevel@tonic-gate * global socket and window structure arrays. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate int 3107c478bd9Sstevel@tonic-gate cs_deinit() 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3137c478bd9Sstevel@tonic-gate int sn, have_clients = 0, have_sockets = 0; 3147c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 3177c478bd9Sstevel@tonic-gate if (cs_debug > 1) 3187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: cs_deinit\n"); 3197c478bd9Sstevel@tonic-gate #endif 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * Deregister with the Card Services kernel stubs module 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 3257c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_DEREGISTER; 3267c478bd9Sstevel@tonic-gate (void) csx_register_cardservices(&rcs); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* 3297c478bd9Sstevel@tonic-gate * Set the GLOBAL_INIT_STATE_NO_CLIENTS flag to prevent new clients 3307c478bd9Sstevel@tonic-gate * from registering. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3337c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_NO_CLIENTS; 3347c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * Go through each socket and make sure that there are no clients 3387c478bd9Sstevel@tonic-gate * on any of the sockets. If there are, we can't deinit until 3397c478bd9Sstevel@tonic-gate * all the clients for every socket are gone. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3427c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 3437c478bd9Sstevel@tonic-gate have_sockets++; 3447c478bd9Sstevel@tonic-gate if (sp->client_list) { 3457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deinit: cannot unload module since " 3467c478bd9Sstevel@tonic-gate "socket %d has registered clients\n", sn); 3477c478bd9Sstevel@tonic-gate have_clients++; 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * We don't allow unload if there are any clients registered 3547c478bd9Sstevel@tonic-gate * or if there are still sockets that are active. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate if ((have_clients > 0) || (have_sockets > 0)) 3577c478bd9Sstevel@tonic-gate return (BAD_FUNCTION); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate #ifdef XXX 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * If one or more sockets have been added, we need to deallocate 3627c478bd9Sstevel@tonic-gate * the resources associated with those sockets. 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * First, tell Socket Services that we're leaving, so that we 3677c478bd9Sstevel@tonic-gate * don't get any more event callbacks. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate SocketServices(CSUnregister); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * Wait for the soft int timer to tell us it's done 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3757c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_UNLOADING; 3767c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3777c478bd9Sstevel@tonic-gate UNTIMEOUT(cs_globals.sotfint_tmo); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * Remove the soft interrupt handler. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3837c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR) { 3847c478bd9Sstevel@tonic-gate ddi_remove_softintr(cs_globals.softint_id); 3857c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SOFTINTR; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate /* 3927c478bd9Sstevel@tonic-gate * Go through each socket and free any resource allocated to that 3937c478bd9Sstevel@tonic-gate * socket, as well as any mutexs and condition variables. 3947c478bd9Sstevel@tonic-gate */ 3957c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3967c478bd9Sstevel@tonic-gate set_socket_t set_socket; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * untimeout possible pending ready/busy timer 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4067c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 4077c478bd9Sstevel@tonic-gate sp->flags = SOCKET_UNLOAD_MODULE; 4087c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SOFTINTR) 4097c478bd9Sstevel@tonic-gate sp->init_state &= ~SOCKET_INIT_STATE_SOFTINTR; 4107c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4117c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4147c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 4157c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 4167c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4177c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * Tell the event handler thread that we want it to exit, then 4217c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4247c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 4257c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_THREAD) { 4267c478bd9Sstevel@tonic-gate sp->thread_state = SOCKET_THREAD_EXIT; 4277c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 4287c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4317c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * Tell the SS work thread that we want it to exit, then 4357c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4387c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 4397c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SS_THREAD) { 4407c478bd9Sstevel@tonic-gate sp->ss_thread_state = SOCKET_THREAD_EXIT; 4417c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 4427c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_caller_cv, &sp->ss_thread_lock); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4467c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * Free the mutexii and condition variables that we used. 4507c478bd9Sstevel@tonic-gate */ 4517c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) { 4527c478bd9Sstevel@tonic-gate mutex_destroy(&sp->lock); 4537c478bd9Sstevel@tonic-gate mutex_destroy(&sp->client_lock); 4547c478bd9Sstevel@tonic-gate mutex_destroy(&sp->cis_lock); 4557c478bd9Sstevel@tonic-gate mutex_destroy(&sp->ss_thread_lock); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_CV) { 4597c478bd9Sstevel@tonic-gate cv_destroy(&sp->thread_cv); 4607c478bd9Sstevel@tonic-gate cv_destroy(&sp->caller_cv); 4617c478bd9Sstevel@tonic-gate cv_destroy(&sp->reset_cv); 4627c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_thread_cv); 4637c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_caller_cv); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 4677c478bd9Sstevel@tonic-gate /* 4687c478bd9Sstevel@tonic-gate * Free the memory-mapped IO structure if we allocated one. 4697c478bd9Sstevel@tonic-gate */ 4707c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) 4717c478bd9Sstevel@tonic-gate kmem_free(sp->io_mmap_window, sizeof (io_mmap_window_t)); 4727c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * Return the socket to memory-only mode and turn off the 4767c478bd9Sstevel@tonic-gate * socket power. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate sp->event_mask = 0; 4797c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4807c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 0; 4817c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 4827c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 4837c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 4847c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 4877c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 4887c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 4897c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 4907c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 4917c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * If we fail this call, there's not much we can do, so 4957c478bd9Sstevel@tonic-gate * just continue with the resource deallocation. 4967c478bd9Sstevel@tonic-gate */ 4977c478bd9Sstevel@tonic-gate if ((ret = 4987c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 4997c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 5007c478bd9Sstevel@tonic-gate "cs_deinit: socket %d SS_SetSocket failure %d\n", 5017c478bd9Sstevel@tonic-gate sp->socket_num, ret); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 5047c478bd9Sstevel@tonic-gate } /* for (sn) */ 5057c478bd9Sstevel@tonic-gate #endif /* XXX */ 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* 5087c478bd9Sstevel@tonic-gate * Destroy the global mutexii. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.global_lock); 5117c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.window_lock); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate #ifdef XXX 5147c478bd9Sstevel@tonic-gate /* 5157c478bd9Sstevel@tonic-gate * Free the global "super-client" structure 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate if (cs_globals.sclient_list) 5187c478bd9Sstevel@tonic-gate kmem_free(cs_globals.sclient_list, 5197c478bd9Sstevel@tonic-gate (cs_globals.num_sockets * sizeof (struct sclient_list_t))); 5207c478bd9Sstevel@tonic-gate cs_globals.sclient_list = NULL; 5217c478bd9Sstevel@tonic-gate #endif /* XXX */ 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* 5277c478bd9Sstevel@tonic-gate * ==== drip, drip, drip - the Card Services waterfall :-) ==== 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* 5317c478bd9Sstevel@tonic-gate * CardServices - general Card Services entry point for CS clients 5327c478bd9Sstevel@tonic-gate * and Socket Services; the address of this 5337c478bd9Sstevel@tonic-gate * function is handed to SS via the CSRegister 5347c478bd9Sstevel@tonic-gate * SS call 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate int 5377c478bd9Sstevel@tonic-gate CardServices(int function, ...) 5387c478bd9Sstevel@tonic-gate { 5397c478bd9Sstevel@tonic-gate va_list arglist; 5407c478bd9Sstevel@tonic-gate int retcode = CS_UNSUPPORTED_FUNCTION; 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate cs_socket_t *socp; 5437c478bd9Sstevel@tonic-gate uint32_t *offp; 5447c478bd9Sstevel@tonic-gate acc_handle_t *hp; 5457c478bd9Sstevel@tonic-gate client_handle_t ch; 5467c478bd9Sstevel@tonic-gate client_handle_t *chp; 5477c478bd9Sstevel@tonic-gate window_handle_t wh; 5487c478bd9Sstevel@tonic-gate window_handle_t *whp; 5497c478bd9Sstevel@tonic-gate tuple_t *tuple; 5507c478bd9Sstevel@tonic-gate cisparse_t *cisparse; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 5537c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 5547c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: called for function %s (0x%x)\n", 5557c478bd9Sstevel@tonic-gate cs_error2text(function, CSFUN2TEXT_FUNCTION), 5567c478bd9Sstevel@tonic-gate function); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate #endif 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate va_start(arglist, function); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* 5637c478bd9Sstevel@tonic-gate * Here's the Card Services waterfall 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate switch (function) { 5667c478bd9Sstevel@tonic-gate /* 5677c478bd9Sstevel@tonic-gate * We got here as a result of the CIS module calling us 5687c478bd9Sstevel@tonic-gate * in response to cs_ss_init() calling the CIS module 5697c478bd9Sstevel@tonic-gate * at CIS_PARSER(CISP_CIS_SETUP, ...) 5707c478bd9Sstevel@tonic-gate */ 5717c478bd9Sstevel@tonic-gate case CISRegister: { 5727c478bd9Sstevel@tonic-gate cisregister_t *cisr; 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate cisr = va_arg(arglist, cisregister_t *); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate if (cisr->cis_magic != PCCS_MAGIC || 5777c478bd9Sstevel@tonic-gate cisr->cis_version != PCCS_VERSION) { 5787c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5797c478bd9Sstevel@tonic-gate "CS: CISRegister (%lx, %lx, %lx, %lx) *ERROR*", 5807c478bd9Sstevel@tonic-gate (long)cisr->cis_magic, 5817c478bd9Sstevel@tonic-gate (long)cisr->cis_version, 5827c478bd9Sstevel@tonic-gate (long)cisr->cis_parser, 5837c478bd9Sstevel@tonic-gate (long)cisr->cistpl_std_callout); 5847c478bd9Sstevel@tonic-gate retcode = CS_BAD_ARGS; 5857c478bd9Sstevel@tonic-gate } else { 5867c478bd9Sstevel@tonic-gate /* 5877c478bd9Sstevel@tonic-gate * Replace the CIS Parser entry point if 5887c478bd9Sstevel@tonic-gate * necessary. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate if (cisr->cis_parser != NULL) 5917c478bd9Sstevel@tonic-gate cis_parser = cisr->cis_parser; 5927c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = cisr->cistpl_std_callout; 5937c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate break; 5977c478bd9Sstevel@tonic-gate case CISUnregister: /* XXX - should we do some more checking */ 5987c478bd9Sstevel@tonic-gate /* XXX - need to protect this by a mutex */ 5997c478bd9Sstevel@tonic-gate cis_parser = NULL; 6007c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = NULL; 6017c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 6027c478bd9Sstevel@tonic-gate break; 6037c478bd9Sstevel@tonic-gate case InitCISWindow: 6047c478bd9Sstevel@tonic-gate socp = va_arg(arglist, cs_socket_t *); 6057c478bd9Sstevel@tonic-gate offp = va_arg(arglist, uint32_t *); 6067c478bd9Sstevel@tonic-gate hp = va_arg(arglist, acc_handle_t *); 6077c478bd9Sstevel@tonic-gate retcode = cs_init_cis_window(socp, offp, hp, 6087c478bd9Sstevel@tonic-gate va_arg(arglist, uint32_t)); 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate case RegisterClient: 6117c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *), 6127c478bd9Sstevel@tonic-gate retcode = cs_register_client(chp, 6137c478bd9Sstevel@tonic-gate va_arg(arglist, client_reg_t *)); 6147c478bd9Sstevel@tonic-gate break; 6157c478bd9Sstevel@tonic-gate case DeregisterClient: 6167c478bd9Sstevel@tonic-gate retcode = cs_deregister_client( 6177c478bd9Sstevel@tonic-gate va_arg(arglist, client_handle_t)); 6187c478bd9Sstevel@tonic-gate break; 6197c478bd9Sstevel@tonic-gate case GetStatus: 6207c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6217c478bd9Sstevel@tonic-gate retcode = cs_get_status(ch, 6227c478bd9Sstevel@tonic-gate va_arg(arglist, get_status_t *)); 6237c478bd9Sstevel@tonic-gate break; 6247c478bd9Sstevel@tonic-gate case ResetFunction: 6257c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6267c478bd9Sstevel@tonic-gate retcode = cs_reset_function(ch, 6277c478bd9Sstevel@tonic-gate va_arg(arglist, reset_function_t *)); 6287c478bd9Sstevel@tonic-gate break; 6297c478bd9Sstevel@tonic-gate case SetEventMask: 6307c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6317c478bd9Sstevel@tonic-gate retcode = cs_set_event_mask(ch, 6327c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 6337c478bd9Sstevel@tonic-gate break; 6347c478bd9Sstevel@tonic-gate case GetEventMask: 6357c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6367c478bd9Sstevel@tonic-gate retcode = cs_get_event_mask(ch, 6377c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 6387c478bd9Sstevel@tonic-gate break; 6397c478bd9Sstevel@tonic-gate case RequestIO: 6407c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6417c478bd9Sstevel@tonic-gate retcode = cs_request_io(ch, 6427c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate case ReleaseIO: 6457c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6467c478bd9Sstevel@tonic-gate retcode = cs_release_io(ch, 6477c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 6487c478bd9Sstevel@tonic-gate break; 6497c478bd9Sstevel@tonic-gate case RequestIRQ: 6507c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6517c478bd9Sstevel@tonic-gate retcode = cs_request_irq(ch, 6527c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 6537c478bd9Sstevel@tonic-gate break; 6547c478bd9Sstevel@tonic-gate case ReleaseIRQ: 6557c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6567c478bd9Sstevel@tonic-gate retcode = cs_release_irq(ch, 6577c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 6587c478bd9Sstevel@tonic-gate break; 6597c478bd9Sstevel@tonic-gate case RequestWindow: 6607c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6617c478bd9Sstevel@tonic-gate whp = va_arg(arglist, window_handle_t *); 6627c478bd9Sstevel@tonic-gate retcode = cs_request_window(ch, whp, 6637c478bd9Sstevel@tonic-gate va_arg(arglist, win_req_t *)); 6647c478bd9Sstevel@tonic-gate break; 6657c478bd9Sstevel@tonic-gate case ReleaseWindow: 6667c478bd9Sstevel@tonic-gate retcode = cs_release_window( 6677c478bd9Sstevel@tonic-gate va_arg(arglist, window_handle_t)); 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate case ModifyWindow: 6707c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 6717c478bd9Sstevel@tonic-gate retcode = cs_modify_window(wh, 6727c478bd9Sstevel@tonic-gate va_arg(arglist, modify_win_t *)); 6737c478bd9Sstevel@tonic-gate break; 6747c478bd9Sstevel@tonic-gate case MapMemPage: 6757c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 6767c478bd9Sstevel@tonic-gate retcode = cs_map_mem_page(wh, 6777c478bd9Sstevel@tonic-gate va_arg(arglist, map_mem_page_t *)); 6787c478bd9Sstevel@tonic-gate break; 6797c478bd9Sstevel@tonic-gate case RequestSocketMask: 6807c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6817c478bd9Sstevel@tonic-gate retcode = cs_request_socket_mask(ch, 6827c478bd9Sstevel@tonic-gate va_arg(arglist, request_socket_mask_t *)); 6837c478bd9Sstevel@tonic-gate break; 6847c478bd9Sstevel@tonic-gate case ReleaseSocketMask: 6857c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6867c478bd9Sstevel@tonic-gate retcode = cs_release_socket_mask(ch, 6877c478bd9Sstevel@tonic-gate va_arg(arglist, release_socket_mask_t *)); 6887c478bd9Sstevel@tonic-gate break; 6897c478bd9Sstevel@tonic-gate case RequestConfiguration: 6907c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6917c478bd9Sstevel@tonic-gate retcode = cs_request_configuration(ch, 6927c478bd9Sstevel@tonic-gate va_arg(arglist, config_req_t *)); 6937c478bd9Sstevel@tonic-gate break; 6947c478bd9Sstevel@tonic-gate case GetPhysicalAdapterInfo: 6957c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6967c478bd9Sstevel@tonic-gate retcode = cs_get_physical_adapter_info(ch, 6977c478bd9Sstevel@tonic-gate va_arg(arglist, get_physical_adapter_info_t *)); 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate case GetCardServicesInfo: 7007c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7017c478bd9Sstevel@tonic-gate retcode = cs_get_cardservices_info(ch, 7027c478bd9Sstevel@tonic-gate va_arg(arglist, get_cardservices_info_t *)); 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate case GetConfigurationInfo: 7057c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *); 7067c478bd9Sstevel@tonic-gate retcode = cs_get_configuration_info(chp, 7077c478bd9Sstevel@tonic-gate va_arg(arglist, get_configuration_info_t *)); 7087c478bd9Sstevel@tonic-gate break; 7097c478bd9Sstevel@tonic-gate case ModifyConfiguration: 7107c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7117c478bd9Sstevel@tonic-gate retcode = cs_modify_configuration(ch, 7127c478bd9Sstevel@tonic-gate va_arg(arglist, modify_config_t *)); 7137c478bd9Sstevel@tonic-gate break; 7147c478bd9Sstevel@tonic-gate case AccessConfigurationRegister: 7157c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7167c478bd9Sstevel@tonic-gate retcode = cs_access_configuration_register(ch, 7177c478bd9Sstevel@tonic-gate va_arg(arglist, access_config_reg_t *)); 7187c478bd9Sstevel@tonic-gate break; 7197c478bd9Sstevel@tonic-gate case ReleaseConfiguration: 7207c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7217c478bd9Sstevel@tonic-gate retcode = cs_release_configuration(ch, 7227c478bd9Sstevel@tonic-gate va_arg(arglist, release_config_t *)); 7237c478bd9Sstevel@tonic-gate break; 7247c478bd9Sstevel@tonic-gate case OpenMemory: 7257c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: OpenMemory\n"); 7267c478bd9Sstevel@tonic-gate break; 7277c478bd9Sstevel@tonic-gate case ReadMemory: 7287c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReadMemory\n"); 7297c478bd9Sstevel@tonic-gate break; 7307c478bd9Sstevel@tonic-gate case WriteMemory: 7317c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: WriteMemory\n"); 7327c478bd9Sstevel@tonic-gate break; 7337c478bd9Sstevel@tonic-gate case CopyMemory: 7347c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CopyMemory\n"); 7357c478bd9Sstevel@tonic-gate break; 7367c478bd9Sstevel@tonic-gate case RegisterEraseQueue: 7377c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterEraseQueue\n"); 7387c478bd9Sstevel@tonic-gate break; 7397c478bd9Sstevel@tonic-gate case CheckEraseQueue: 7407c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CheckEraseQueue\n"); 7417c478bd9Sstevel@tonic-gate break; 7427c478bd9Sstevel@tonic-gate case DeregisterEraseQueue: 7437c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: DeregisterEraseQueue\n"); 7447c478bd9Sstevel@tonic-gate break; 7457c478bd9Sstevel@tonic-gate case CloseMemory: 7467c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CloseMemory\n"); 7477c478bd9Sstevel@tonic-gate break; 7487c478bd9Sstevel@tonic-gate case GetFirstRegion: 7497c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstRegion\n"); 7507c478bd9Sstevel@tonic-gate break; 7517c478bd9Sstevel@tonic-gate case GetNextRegion: 7527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextRegion\n"); 7537c478bd9Sstevel@tonic-gate break; 7547c478bd9Sstevel@tonic-gate case GetFirstPartition: 7557c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstPartition\n"); 7567c478bd9Sstevel@tonic-gate break; 7577c478bd9Sstevel@tonic-gate case GetNextPartition: 7587c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextPartition\n"); 7597c478bd9Sstevel@tonic-gate break; 7607c478bd9Sstevel@tonic-gate case ReturnSSEntry: 7617c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReturnSSEntry\n"); 7627c478bd9Sstevel@tonic-gate break; 7637c478bd9Sstevel@tonic-gate case MapLogSocket: 7647c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7657c478bd9Sstevel@tonic-gate retcode = cs_map_log_socket(ch, 7667c478bd9Sstevel@tonic-gate va_arg(arglist, map_log_socket_t *)); 7677c478bd9Sstevel@tonic-gate break; 7687c478bd9Sstevel@tonic-gate case MapPhySocket: 7697c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhySocket\n"); 7707c478bd9Sstevel@tonic-gate break; 7717c478bd9Sstevel@tonic-gate case MapLogWindow: 7727c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapLogWindow\n"); 7737c478bd9Sstevel@tonic-gate break; 7747c478bd9Sstevel@tonic-gate case MapPhyWindow: 7757c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhyWindow\n"); 7767c478bd9Sstevel@tonic-gate break; 7777c478bd9Sstevel@tonic-gate case RegisterMTD: 7787c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterMTD\n"); 7797c478bd9Sstevel@tonic-gate break; 7807c478bd9Sstevel@tonic-gate case RegisterTimer: 7817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterTimer\n"); 7827c478bd9Sstevel@tonic-gate break; 7837c478bd9Sstevel@tonic-gate case SetRegion: 7847c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: SetRegion\n"); 7857c478bd9Sstevel@tonic-gate break; 7867c478bd9Sstevel@tonic-gate case RequestExclusive: 7877c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RequestExclusive\n"); 7887c478bd9Sstevel@tonic-gate break; 7897c478bd9Sstevel@tonic-gate case ReleaseExclusive: 7907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReleaseExclusive\n"); 7917c478bd9Sstevel@tonic-gate break; 7927c478bd9Sstevel@tonic-gate case GetFirstClient: 7937c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 7947c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 7957c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 7967c478bd9Sstevel@tonic-gate break; 7977c478bd9Sstevel@tonic-gate case GetNextClient: 7987c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 7997c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 8007c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 8017c478bd9Sstevel@tonic-gate break; 8027c478bd9Sstevel@tonic-gate case GetClientInfo: 8037c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8047c478bd9Sstevel@tonic-gate retcode = cs_get_client_info(ch, 8057c478bd9Sstevel@tonic-gate va_arg(arglist, client_info_t *)); 8067c478bd9Sstevel@tonic-gate break; 8077c478bd9Sstevel@tonic-gate case AddSocketServices: 8087c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AddSocketServices\n"); 8097c478bd9Sstevel@tonic-gate break; 8107c478bd9Sstevel@tonic-gate case ReplaceSocketServices: 8117c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReplaceSocketServices\n"); 8127c478bd9Sstevel@tonic-gate break; 8137c478bd9Sstevel@tonic-gate case VendorSpecific: 8147c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: VendorSpecific\n"); 8157c478bd9Sstevel@tonic-gate break; 8167c478bd9Sstevel@tonic-gate case AdjustResourceInfo: 8177c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AdjustResourceInfo\n"); 8187c478bd9Sstevel@tonic-gate break; 8197c478bd9Sstevel@tonic-gate case ValidateCIS: 8207c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8217c478bd9Sstevel@tonic-gate retcode = cs_validate_cis(ch, 8227c478bd9Sstevel@tonic-gate va_arg(arglist, cisinfo_t *)); 8237c478bd9Sstevel@tonic-gate break; 8247c478bd9Sstevel@tonic-gate case GetFirstTuple: 8257c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8267c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 8277c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 8287c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 8297c478bd9Sstevel@tonic-gate break; 8307c478bd9Sstevel@tonic-gate case GetNextTuple: 8317c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8327c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 8337c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 8347c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 8357c478bd9Sstevel@tonic-gate break; 8367c478bd9Sstevel@tonic-gate case GetTupleData: 8377c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8387c478bd9Sstevel@tonic-gate retcode = cs_get_tuple_data(ch, 8397c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *)); 8407c478bd9Sstevel@tonic-gate break; 8417c478bd9Sstevel@tonic-gate case ParseTuple: 8427c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8437c478bd9Sstevel@tonic-gate tuple = va_arg(arglist, tuple_t *); 8447c478bd9Sstevel@tonic-gate cisparse = va_arg(arglist, cisparse_t *); 8457c478bd9Sstevel@tonic-gate retcode = cs_parse_tuple(ch, tuple, cisparse, 8467c478bd9Sstevel@tonic-gate va_arg(arglist, uint_t)); 8477c478bd9Sstevel@tonic-gate break; 8487c478bd9Sstevel@tonic-gate case MakeDeviceNode: 8497c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8507c478bd9Sstevel@tonic-gate retcode = cs_make_device_node(ch, 8517c478bd9Sstevel@tonic-gate va_arg(arglist, make_device_node_t *)); 8527c478bd9Sstevel@tonic-gate break; 8537c478bd9Sstevel@tonic-gate case RemoveDeviceNode: 8547c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8557c478bd9Sstevel@tonic-gate retcode = cs_remove_device_node(ch, 8567c478bd9Sstevel@tonic-gate va_arg(arglist, remove_device_node_t *)); 8577c478bd9Sstevel@tonic-gate break; 8587c478bd9Sstevel@tonic-gate case ConvertSpeed: 8597c478bd9Sstevel@tonic-gate retcode = cs_convert_speed( 8607c478bd9Sstevel@tonic-gate va_arg(arglist, convert_speed_t *)); 8617c478bd9Sstevel@tonic-gate break; 8627c478bd9Sstevel@tonic-gate case ConvertSize: 8637c478bd9Sstevel@tonic-gate retcode = cs_convert_size( 8647c478bd9Sstevel@tonic-gate va_arg(arglist, convert_size_t *)); 8657c478bd9Sstevel@tonic-gate break; 8667c478bd9Sstevel@tonic-gate case Event2Text: 8677c478bd9Sstevel@tonic-gate retcode = cs_event2text( 8687c478bd9Sstevel@tonic-gate va_arg(arglist, event2text_t *), 1); 8697c478bd9Sstevel@tonic-gate break; 8707c478bd9Sstevel@tonic-gate case Error2Text: { 8717c478bd9Sstevel@tonic-gate error2text_t *cft; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate cft = va_arg(arglist, error2text_t *); 8747c478bd9Sstevel@tonic-gate (void) strcpy(cft->text, 8757c478bd9Sstevel@tonic-gate cs_error2text(cft->item, CSFUN2TEXT_RETURN)); 8767c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate break; 8797c478bd9Sstevel@tonic-gate case CS_DDI_Info: 8807c478bd9Sstevel@tonic-gate retcode = cs_ddi_info(va_arg(arglist, cs_ddi_info_t *)); 8817c478bd9Sstevel@tonic-gate break; 8827c478bd9Sstevel@tonic-gate case CS_Sys_Ctl: 8837c478bd9Sstevel@tonic-gate retcode = cs_sys_ctl(va_arg(arglist, cs_sys_ctl_t *)); 8847c478bd9Sstevel@tonic-gate break; 8857c478bd9Sstevel@tonic-gate default: 8867c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: {unknown function %d}\n", function); 8877c478bd9Sstevel@tonic-gate break; 8887c478bd9Sstevel@tonic-gate } /* switch(function) */ 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate va_end(arglist); 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 8937c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 8947c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: returning %s (0x%x)\n", 8957c478bd9Sstevel@tonic-gate cs_error2text(retcode, CSFUN2TEXT_RETURN), 8967c478bd9Sstevel@tonic-gate retcode); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate #endif 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate return (retcode); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * ==== tuple and CIS handling section ==== 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate /* 9087c478bd9Sstevel@tonic-gate * cs_parse_tuple - This function supports the CS ParseTuple function call. 9097c478bd9Sstevel@tonic-gate * 9107c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if tuple parsed sucessfully 9117c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 9127c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if passed CIS list pointer is NULL 9137c478bd9Sstevel@tonic-gate * CS_UNKNOWN_TUPLE - if unknown tuple passed to CIS parser 9147c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if generic parser error 9157c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for card/function 9167c478bd9Sstevel@tonic-gate * 9177c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate static int 9207c478bd9Sstevel@tonic-gate cs_parse_tuple(client_handle_t client_handle, tuple_t *tuple, 9217c478bd9Sstevel@tonic-gate cisparse_t *cisparse, cisdata_t cisdata) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate cs_socket_t *sp; 9247c478bd9Sstevel@tonic-gate client_t *client; 9257c478bd9Sstevel@tonic-gate uint32_t fn; 9267c478bd9Sstevel@tonic-gate int ret; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, 9297c478bd9Sstevel@tonic-gate &fn, &sp, &client)) != CS_SUCCESS) 9307c478bd9Sstevel@tonic-gate return (ret); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 9347c478bd9Sstevel@tonic-gate * for this client, then return an error. 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 9377c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * Sanity check to be sure that we've got a non-NULL CIS list 9417c478bd9Sstevel@tonic-gate * pointer. 9427c478bd9Sstevel@tonic-gate */ 9437c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) 9447c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* 9497c478bd9Sstevel@tonic-gate * Check to see if there is a valid CIS for this function. 9507c478bd9Sstevel@tonic-gate * There is an implicit assumption here that if this 9517c478bd9Sstevel@tonic-gate * is a multi-function CIS and the specified function 9527c478bd9Sstevel@tonic-gate * number is not CS_GLOBAL_CIS that in order for there 9537c478bd9Sstevel@tonic-gate * to be a valid function-specific CIS, there also must 9547c478bd9Sstevel@tonic-gate * be a valid global CIS. This means that we don't need 9557c478bd9Sstevel@tonic-gate * to know whether this tuple came from the global CIS 9567c478bd9Sstevel@tonic-gate * or from the function-specific CIS. 9577c478bd9Sstevel@tonic-gate */ 9587c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 9597c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 9607c478bd9Sstevel@tonic-gate ret = (int)(uintptr_t)CIS_PARSER(CISP_CIS_PARSE_TUPLE, 9617c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, 9627c478bd9Sstevel@tonic-gate tuple->CISOffset, 9637c478bd9Sstevel@tonic-gate (tuple->Attributes & TUPLE_RETURN_NAME)? 9647c478bd9Sstevel@tonic-gate HANDTPL_RETURN_NAME: 9657c478bd9Sstevel@tonic-gate HANDTPL_PARSE_LTUPLE, 9667c478bd9Sstevel@tonic-gate cisparse, cisdata); 9677c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 9687c478bd9Sstevel@tonic-gate if (ret == CISTPLF_UNKNOWN) 9697c478bd9Sstevel@tonic-gate return (CS_UNKNOWN_TUPLE); 9707c478bd9Sstevel@tonic-gate if (ret != CISTPLF_NOERROR) 9717c478bd9Sstevel@tonic-gate return (CS_BAD_CIS); 9727c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 9737c478bd9Sstevel@tonic-gate } else { 9747c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 9757c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 9767c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate return (ret); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate /* 9827c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple - returns the first/next tuple of the specified type 9837c478bd9Sstevel@tonic-gate * this is to support the GetFirstTuple and 9847c478bd9Sstevel@tonic-gate * GetNextTuple function call 9857c478bd9Sstevel@tonic-gate * 9867c478bd9Sstevel@tonic-gate * flags - one of: 9877c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG causes function to support GetFirstTuple 9887c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG causes function to support GetNextTuple 9897c478bd9Sstevel@tonic-gate * 9907c478bd9Sstevel@tonic-gate * tuple_t->Attributes flags: 9917c478bd9Sstevel@tonic-gate * TUPLE_RETURN_LINK - XXX Not implemented, see notes below. 9927c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES - return tuples with 9937c478bd9Sstevel@tonic-gate * CISTPLF_IGNORE_TUPLE set in the 9947c478bd9Sstevel@tonic-gate * cistpl_t->flags member. 9957c478bd9Sstevel@tonic-gate * 9967c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 9977c478bd9Sstevel@tonic-gate * 9987c478bd9Sstevel@tonic-gate * On a single-function card, the caller will get back all the tuples in 9997c478bd9Sstevel@tonic-gate * the CIS. 10007c478bd9Sstevel@tonic-gate * 10017c478bd9Sstevel@tonic-gate * On a multi-function card, the caller will get the tuples from the 10027c478bd9Sstevel@tonic-gate * global CIS followed by the tuples in the function-specific CIS. The 10037c478bd9Sstevel@tonic-gate * caller will not get any tuples from a function-specific CIS that 10047c478bd9Sstevel@tonic-gate * does not belong to the caller's function. 10057c478bd9Sstevel@tonic-gate * 10067c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 10077c478bd9Sstevel@tonic-gate * 10087c478bd9Sstevel@tonic-gate * On a single-function card, the operation is the same as for regular 10097c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 10107c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS this function will return CS_NO_CIS. 10117c478bd9Sstevel@tonic-gate * 10127c478bd9Sstevel@tonic-gate * On a multi-function card, the operation is the same as for regular 10137c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 10147c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS the caller will only get tuples from the 10157c478bd9Sstevel@tonic-gate * global CIS. If a particular function nubmer does not exist, this 10167c478bd9Sstevel@tonic-gate * function will return CS_NO_CIS for that function. 10177c478bd9Sstevel@tonic-gate * 10187c478bd9Sstevel@tonic-gate * General notes: 10197c478bd9Sstevel@tonic-gate * 10207c478bd9Sstevel@tonic-gate * On both a single-function card and a multi-function card, if the tuple 10217c478bd9Sstevel@tonic-gate * comes from the global CIS chain, the CISTPLF_GLOBAL_CIS flag will be 10227c478bd9Sstevel@tonic-gate * set in the tuple_t->flags member. 10237c478bd9Sstevel@tonic-gate * 10247c478bd9Sstevel@tonic-gate * On a multi-function card, if the tuple comes from the function-specific 10257c478bd9Sstevel@tonic-gate * CIS chain, the CISTPLF_MF_CIS flag will be set in the tuple_t->flags 10267c478bd9Sstevel@tonic-gate * member. 10277c478bd9Sstevel@tonic-gate * 10287c478bd9Sstevel@tonic-gate * For other flags that are set in the tuple_t->flags member, see the 10297c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 10307c478bd9Sstevel@tonic-gate * 10317c478bd9Sstevel@tonic-gate * The CIS parser may not include all the tuples that are in the CIS in 10327c478bd9Sstevel@tonic-gate * the private CIS list that it creates and maintains. See the CIS 10337c478bd9Sstevel@tonic-gate * parser documentation for a list of tuples that the parser does not 10347c478bd9Sstevel@tonic-gate * include in the list. 10357c478bd9Sstevel@tonic-gate * 10367c478bd9Sstevel@tonic-gate * If a tuple has the CISTPLF_IGNORE_TUPLE flag set and the flags 10377c478bd9Sstevel@tonic-gate * parameter CIS_GET_LTUPLE_IGNORE is not set, that tuple will not 10387c478bd9Sstevel@tonic-gate * be returned to the caller. Instead, the next tuple that matches 10397c478bd9Sstevel@tonic-gate * the calling criteria will be returned (or NULL if no other tuples 10407c478bd9Sstevel@tonic-gate * match the calling criteria). If CIS_GET_LTUPLE_IGNORE is set in 10417c478bd9Sstevel@tonic-gate * the flags paramter, tuples in the CIS list that match the calling 10427c478bd9Sstevel@tonic-gate * criteria will be returned. 10437c478bd9Sstevel@tonic-gate * 10447c478bd9Sstevel@tonic-gate * XXX The PC Card 95 Standard says that if the TUPLE_RETURN_LINK flag in 10457c478bd9Sstevel@tonic-gate * the tuple_t->Attributes member is not set, then we don't return 10467c478bd9Sstevel@tonic-gate * any of the link tuples. This function ignores this flag and always 10477c478bd9Sstevel@tonic-gate * returns link tuples. 10487c478bd9Sstevel@tonic-gate * 10497c478bd9Sstevel@tonic-gate * Return codes: 10507c478bd9Sstevel@tonic-gate * CS_SUCCESS - if tuple sucessfully found and returned 10517c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card inserted 10527c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for the specified card/function 10537c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if tuple not found or no more tuples 10547c478bd9Sstevel@tonic-gate * to return 10557c478bd9Sstevel@tonic-gate * 10567c478bd9Sstevel@tonic-gate * See notes for cs_get_socket for a description of valid client, socket 10577c478bd9Sstevel@tonic-gate * and function number combinations. 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate static int 10607c478bd9Sstevel@tonic-gate cs_get_firstnext_tuple(client_handle_t client_handle, 10617c478bd9Sstevel@tonic-gate tuple_t *tuple, uint32_t flags) 10627c478bd9Sstevel@tonic-gate { 10637c478bd9Sstevel@tonic-gate cs_socket_t *sp; 10647c478bd9Sstevel@tonic-gate client_t *client; 10657c478bd9Sstevel@tonic-gate uint32_t fn; 10667c478bd9Sstevel@tonic-gate int ret; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 10697c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 10707c478bd9Sstevel@tonic-gate return (ret); 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate /* 10737c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 10747c478bd9Sstevel@tonic-gate * for this client, then return an error. 10757c478bd9Sstevel@tonic-gate */ 10767c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 10777c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate /* 10827c478bd9Sstevel@tonic-gate * If there's no CIS on this card or no CIS for the specified 10837c478bd9Sstevel@tonic-gate * function, then we can't do much. 10847c478bd9Sstevel@tonic-gate */ 10857c478bd9Sstevel@tonic-gate if ((!(sp->cis_flags & CW_VALID_CIS)) || 10867c478bd9Sstevel@tonic-gate (!(sp->cis[fn].flags & CW_VALID_CIS))) { 10877c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 10887c478bd9Sstevel@tonic-gate return (CS_NO_CIS); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate /* 10927c478bd9Sstevel@tonic-gate * This will set the CIS_GET_LTUPLE_IGNORE flag if the 10937c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES flag is set. The 10947c478bd9Sstevel@tonic-gate * assumption here is that the CIS_GET_LTUPLE_IGNORE 10957c478bd9Sstevel@tonic-gate * flag and the TUPLE_RETURN_IGNORED_TUPLES flag 10967c478bd9Sstevel@tonic-gate * shares the same bit position. If this ever changes, 10977c478bd9Sstevel@tonic-gate * we'll ahve to re-work this section of code. 10987c478bd9Sstevel@tonic-gate */ 10997c478bd9Sstevel@tonic-gate if (tuple->Attributes & TUPLE_RETURN_IGNORED_TUPLES) 11007c478bd9Sstevel@tonic-gate flags |= CIS_GET_LTUPLE_IGNORE; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate /* 11037c478bd9Sstevel@tonic-gate * Are we GetFirstTuple or GetNextTuple? 11047c478bd9Sstevel@tonic-gate */ 11057c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_OPMASK) & CS_GET_FIRST_FLAG) { 11067c478bd9Sstevel@tonic-gate /* 11077c478bd9Sstevel@tonic-gate * Initialize the tuple structure; we need this information when 11087c478bd9Sstevel@tonic-gate * we have to process a GetNextTuple or ParseTuple call. 11097c478bd9Sstevel@tonic-gate * If this card has a multi-function CIS, then we always start out 11107c478bd9Sstevel@tonic-gate * delivering tuples from the global CIS chain. If this card does 11117c478bd9Sstevel@tonic-gate * not have a multi-function CIS, then the function 0 CIS chain 11127c478bd9Sstevel@tonic-gate * will contain the complete CIS list. 11137c478bd9Sstevel@tonic-gate * If this is a multi-function card, then use the GET_FIRST_LTUPLE 11147c478bd9Sstevel@tonic-gate * macro to return the first tuple in the CIS list - we do this 11157c478bd9Sstevel@tonic-gate * since we don't want to return tuples with CISTPLF_IGNORE_TUPLE 11167c478bd9Sstevel@tonic-gate * set unless CIS_GET_LTUPLE_IGNORE is set in the flags parameter. 11177c478bd9Sstevel@tonic-gate * Note that we don't have to cross over into the fucntion-specific 11187c478bd9Sstevel@tonic-gate * CIS chain if GET_FIRST_LTUPLE returns NULL, since a MF CIS will 11197c478bd9Sstevel@tonic-gate * always have at least a CISTPL_LONGLINK_MFC tuple in the global 11207c478bd9Sstevel@tonic-gate * CIS chain - the test for NULL is just a sanity check. 11217c478bd9Sstevel@tonic-gate */ 11227c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11237c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = 11247c478bd9Sstevel@tonic-gate GET_FIRST_LTUPLE(sp->cis[CS_GLOBAL_CIS].cis, 11257c478bd9Sstevel@tonic-gate flags)) == NULL) { 11267c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11277c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11287c478bd9Sstevel@tonic-gate } /* GET_FIRST_LTUPLE */ 11297c478bd9Sstevel@tonic-gate } else { 11307c478bd9Sstevel@tonic-gate tuple->CISOffset = sp->cis[0].cis; 11317c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11327c478bd9Sstevel@tonic-gate } else { 11337c478bd9Sstevel@tonic-gate cistpl_t *tp; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate /* 11367c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL tuple list pointer. 11377c478bd9Sstevel@tonic-gate * This is necessary in the case where the caller calls us 11387c478bd9Sstevel@tonic-gate * with get next tuple requests but we don't have any more 11397c478bd9Sstevel@tonic-gate * tuples to give back. 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate if (tuple->CISOffset == NULL) { 11427c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11437c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11447c478bd9Sstevel@tonic-gate } 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate /* 11477c478bd9Sstevel@tonic-gate * Point to the next tuple in the list. If we're searching for 11487c478bd9Sstevel@tonic-gate * a particular tuple, FIND_LTUPLE_FWD will find it. 11497c478bd9Sstevel@tonic-gate * 11507c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain that we're looking 11517c478bd9Sstevel@tonic-gate * at, then if we're looking at the global portion of a 11527c478bd9Sstevel@tonic-gate * multi-function CIS, switch to the function-specific list 11537c478bd9Sstevel@tonic-gate * and start looking there. 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate if ((tp = GET_NEXT_TUPLE(tuple->CISOffset, flags)) == NULL) { 11567c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11577c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 11587c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 11597c478bd9Sstevel@tonic-gate tp = GET_FIRST_LTUPLE(sp->cis[fn].cis, flags); 11607c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 11617c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11627c478bd9Sstevel@tonic-gate } /* GET_NEXT_TUPLE */ 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 11687c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11697c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate } /* CS_GET_FIRST_FLAG */ 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate /* 11747c478bd9Sstevel@tonic-gate * Check if we want to get the first of a particular type of tuple 11757c478bd9Sstevel@tonic-gate * or just the first tuple in the chain. 11767c478bd9Sstevel@tonic-gate * If there are no more tuples of the type we're searching for in 11777c478bd9Sstevel@tonic-gate * the chain that we're looking at, then if we're looking at 11787c478bd9Sstevel@tonic-gate * the global portion of a multi-function CIS, switch to the 11797c478bd9Sstevel@tonic-gate * function-specific list and start looking there. 11807c478bd9Sstevel@tonic-gate */ 11817c478bd9Sstevel@tonic-gate if (tuple->DesiredTuple != RETURN_FIRST_TUPLE) { 11827c478bd9Sstevel@tonic-gate cistpl_t *tp; 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate if ((tp = FIND_LTUPLE_FWD(tuple->CISOffset, 11857c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags)) == NULL) { 11867c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11877c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 11887c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 11897c478bd9Sstevel@tonic-gate tp = FIND_FIRST_LTUPLE(sp->cis[fn].cis, 11907c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags); 11917c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 11927c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11937c478bd9Sstevel@tonic-gate } /* FIND_LTUPLE_FWD */ 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 11977c478bd9Sstevel@tonic-gate */ 11987c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 11997c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12007c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate } /* !RETURN_FIRST_TUPLE */ 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate /* 12057c478bd9Sstevel@tonic-gate * We've got a tuple, now fill out the rest of the tuple_t 12067c478bd9Sstevel@tonic-gate * structure. Callers can use the flags member to 12077c478bd9Sstevel@tonic-gate * determine whether or not the tuple data was copied 12087c478bd9Sstevel@tonic-gate * to the linked list or if it's still on the card. 12097c478bd9Sstevel@tonic-gate */ 12107c478bd9Sstevel@tonic-gate tuple->Flags = tuple->CISOffset->flags; 12117c478bd9Sstevel@tonic-gate tuple->TupleCode = tuple->CISOffset->type; 12127c478bd9Sstevel@tonic-gate tuple->TupleLink = tuple->CISOffset->len; 12137c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->CISOffset->len; 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate /* 12217c478bd9Sstevel@tonic-gate * cs_get_tuple_data - get the data portion of a tuple; this is to 12227c478bd9Sstevel@tonic-gate * support the GetTupleData function call. 12237c478bd9Sstevel@tonic-gate * 12247c478bd9Sstevel@tonic-gate * Note that if the data body of a tuple was not read from the CIS, 12257c478bd9Sstevel@tonic-gate * then this function will return CS_NO_MORE_ITEMS. 12267c478bd9Sstevel@tonic-gate * 12277c478bd9Sstevel@tonic-gate * For flags that are set in the tuple_t->flags member, see the 12287c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 12297c478bd9Sstevel@tonic-gate * These flags are copied into the tuple_t->flags member by the 12307c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple function call. 12317c478bd9Sstevel@tonic-gate * 12327c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate static int 12357c478bd9Sstevel@tonic-gate cs_get_tuple_data(client_handle_t client_handle, tuple_t *tuple) 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate cs_socket_t *sp; 12387c478bd9Sstevel@tonic-gate client_t *client; 12397c478bd9Sstevel@tonic-gate int ret, nbytes; 12407c478bd9Sstevel@tonic-gate uint32_t fn, flags; 12417c478bd9Sstevel@tonic-gate cisdata_t *tsd, *tdd; 12427c478bd9Sstevel@tonic-gate uint32_t newoffset; 12437c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 12467c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 12477c478bd9Sstevel@tonic-gate return (ret); 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate /* 12507c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 12517c478bd9Sstevel@tonic-gate * for this client, then return an error. 12527c478bd9Sstevel@tonic-gate */ 12537c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 12547c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 12597c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate /* 12627c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL pointer to 12637c478bd9Sstevel@tonic-gate * a CIS list. 12647c478bd9Sstevel@tonic-gate */ 12657c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) { 12667c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12677c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* 12717c478bd9Sstevel@tonic-gate * Since the tuple data buffer that the caller calls us with 12727c478bd9Sstevel@tonic-gate * is preallocated in the tuple_t structure, we ignore any 12737c478bd9Sstevel@tonic-gate * TupleDataMax value that the caller has setup and use the 12747c478bd9Sstevel@tonic-gate * actual size of the tuple data buffer in the structure. 12757c478bd9Sstevel@tonic-gate */ 12767c478bd9Sstevel@tonic-gate tuple->TupleDataMax = sizeof (tuple->TupleData); 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * Make sure the requested offset is not past the end of the 12807c478bd9Sstevel@tonic-gate * tuple data body nor past the end of the user-supplied 12817c478bd9Sstevel@tonic-gate * buffer. 12827c478bd9Sstevel@tonic-gate */ 12837c478bd9Sstevel@tonic-gate if ((int)tuple->TupleOffset >= min((int)tuple->TupleLink, 12847c478bd9Sstevel@tonic-gate (int)tuple->TupleDataMax)) { 12857c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12867c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->TupleLink; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate if ((nbytes = min((int)tuple->TupleDataMax - 12927c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset, 12937c478bd9Sstevel@tonic-gate (int)tuple->TupleDataLen - 12947c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset)) < 1) { 12957c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12967c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* 13007c478bd9Sstevel@tonic-gate * The tuple data destination is always the tuple_t->TupleData 13017c478bd9Sstevel@tonic-gate * buffer in the tuple_t structure no matter where we read the 13027c478bd9Sstevel@tonic-gate * tuple data from. 13037c478bd9Sstevel@tonic-gate */ 13047c478bd9Sstevel@tonic-gate tdd = tuple->TupleData; 13057c478bd9Sstevel@tonic-gate bzero((caddr_t)tdd, sizeof (tuple->TupleData)); 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* 13087c478bd9Sstevel@tonic-gate * Do we have a copy of the tuple data? If not, we have to 13097c478bd9Sstevel@tonic-gate * get a pointer to the CIS and read the tuple data from the 13107c478bd9Sstevel@tonic-gate * card itself. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate switch (tuple->CISOffset->flags & CISTPLF_SPACE_MASK) { 13137c478bd9Sstevel@tonic-gate case CISTPLF_LM_SPACE: 13147c478bd9Sstevel@tonic-gate tsd = (tuple->CISOffset->data + 13157c478bd9Sstevel@tonic-gate (unsigned)tuple->TupleOffset); 13167c478bd9Sstevel@tonic-gate while (nbytes--) 13177c478bd9Sstevel@tonic-gate *tdd++ = *tsd++; 13187c478bd9Sstevel@tonic-gate break; 13197c478bd9Sstevel@tonic-gate case CISTPLF_AM_SPACE: 13207c478bd9Sstevel@tonic-gate case CISTPLF_CM_SPACE: 13217c478bd9Sstevel@tonic-gate newoffset = tuple->CISOffset->offset; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate /* 13247c478bd9Sstevel@tonic-gate * Setup the proper space flags as well as setup the 13257c478bd9Sstevel@tonic-gate * address offset to point to the start of the tuple 13267c478bd9Sstevel@tonic-gate * data area; we need to do the latter since the 13277c478bd9Sstevel@tonic-gate * cis_store_cis_addr function in cis.c sets up the 13287c478bd9Sstevel@tonic-gate * tuple->CISOffset->offset offset to point to the 13297c478bd9Sstevel@tonic-gate * start of the tuple. 13307c478bd9Sstevel@tonic-gate */ 13317c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) { 13327c478bd9Sstevel@tonic-gate flags = CISTPLF_AM_SPACE; 13337c478bd9Sstevel@tonic-gate newoffset += ((tuple->TupleOffset * 2) + 4); 13347c478bd9Sstevel@tonic-gate } else { 13357c478bd9Sstevel@tonic-gate flags = CISTPLF_CM_SPACE; 13367c478bd9Sstevel@tonic-gate newoffset += (tuple->TupleOffset + 2); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 13407c478bd9Sstevel@tonic-gate flags) != CS_SUCCESS) { 13417c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13427c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_tuple_data: socket %d " 13437c478bd9Sstevel@tonic-gate "can't init CIS window\n", 13447c478bd9Sstevel@tonic-gate sp->socket_num); 13457c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 13467c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 13477c478bd9Sstevel@tonic-gate while (nbytes--) { 13487c478bd9Sstevel@tonic-gate *tdd++ = csx_Get8(cis_handle, newoffset++); 13497c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) 13507c478bd9Sstevel@tonic-gate newoffset++; 13517c478bd9Sstevel@tonic-gate } /* while */ 13527c478bd9Sstevel@tonic-gate break; 13537c478bd9Sstevel@tonic-gate default: 13547c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13557c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 13567c478bd9Sstevel@tonic-gate } /* switch */ 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 13597c478bd9Sstevel@tonic-gate } else { 13607c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 13617c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate return (ret); 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* 13697c478bd9Sstevel@tonic-gate * cs_validate_cis - validates the CIS on a card in the given socket; this 13707c478bd9Sstevel@tonic-gate * is to support the ValidateCIS function call. 13717c478bd9Sstevel@tonic-gate * 13727c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 13737c478bd9Sstevel@tonic-gate * 13747c478bd9Sstevel@tonic-gate * Regular PC card drivers calling ValidateCIS will get the meaning of 13757c478bd9Sstevel@tonic-gate * the structure members as specified in the standard. 13767c478bd9Sstevel@tonic-gate * 13777c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 13787c478bd9Sstevel@tonic-gate * 13797c478bd9Sstevel@tonic-gate * with: Function Number = CS_GLOBAL_CIS 13807c478bd9Sstevel@tonic-gate * 13817c478bd9Sstevel@tonic-gate * For a single-function card, CS_NO_CIS will be returned and the 13827c478bd9Sstevel@tonic-gate * cisinfo_t->Chains and cisinfo_t->Tuples members will be set to 0. 13837c478bd9Sstevel@tonic-gate * 13847c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 13857c478bd9Sstevel@tonic-gate * the number of CIS chains in the global portion of the CIS, and 13867c478bd9Sstevel@tonic-gate * cisinfo_t->Tuples will contain a count of the number of tuples in 13877c478bd9Sstevel@tonic-gate * the global portion of the CIS. 13887c478bd9Sstevel@tonic-gate * 13897c478bd9Sstevel@tonic-gate * with: 0 <= Function Number < CIS_MAX_FUNCTIONS 13907c478bd9Sstevel@tonic-gate * 13917c478bd9Sstevel@tonic-gate * For a single-function card, if the function number is equal to 0 and 13927c478bd9Sstevel@tonic-gate * has a CIS, cisinfo_t->Chains will contain a count of the number of 13937c478bd9Sstevel@tonic-gate * CIS chains in the CIS, and cisinfo_t->Tuples will contain a count of 13947c478bd9Sstevel@tonic-gate * the number of tuples in the CIS. If the card does not have a CIS, or 13957c478bd9Sstevel@tonic-gate * if the function number is not equal to 0, CS_NO_CIS will be returned 13967c478bd9Sstevel@tonic-gate * and the cisinfo_t->Chains and cisinfo_t->Tuples members will be set 13977c478bd9Sstevel@tonic-gate * to 0. 13987c478bd9Sstevel@tonic-gate * 13997c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 14007c478bd9Sstevel@tonic-gate * the number of CIS chains in the global and function-specific 14017c478bd9Sstevel@tonic-gate * portions of the CIS, and cisinfo_t->Tuples will contain a count of 14027c478bd9Sstevel@tonic-gate * the number of tuples in the global and function-specific portions of 14037c478bd9Sstevel@tonic-gate * the CIS. If the function does not exist or has no CIS, CS_NO_CIS 14047c478bd9Sstevel@tonic-gate * will be returned and the cisinfo_t->Chains and cisinfo_t->Tuples 14057c478bd9Sstevel@tonic-gate * members will be set to 0. 14067c478bd9Sstevel@tonic-gate * 14077c478bd9Sstevel@tonic-gate * General notes: 14087c478bd9Sstevel@tonic-gate * 14097c478bd9Sstevel@tonic-gate * If the card does not have a CIS, or if the function does not exist 14107c478bd9Sstevel@tonic-gate * or has no CIS, CS_NO_CIS will be returned and the cisinfo_t->Chains 14117c478bd9Sstevel@tonic-gate * and cisinfo_t->Tuples members will be set to 0. 14127c478bd9Sstevel@tonic-gate * 14137c478bd9Sstevel@tonic-gate * Most of the work of validating the CIS has already been done by the 14147c478bd9Sstevel@tonic-gate * CIS parser module, so we don't have to do much here except for 14157c478bd9Sstevel@tonic-gate * looking at the various flags and tuple/chain counts that were already 14167c478bd9Sstevel@tonic-gate * setup by the CIS parser. 14177c478bd9Sstevel@tonic-gate * 14187c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 14197c478bd9Sstevel@tonic-gate */ 14207c478bd9Sstevel@tonic-gate static int 14217c478bd9Sstevel@tonic-gate cs_validate_cis(client_handle_t client_handle, cisinfo_t *cisinfo) 14227c478bd9Sstevel@tonic-gate { 14237c478bd9Sstevel@tonic-gate cs_socket_t *sp; 14247c478bd9Sstevel@tonic-gate client_t *client; 14257c478bd9Sstevel@tonic-gate uint32_t fn; 14267c478bd9Sstevel@tonic-gate int ret; 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &cisinfo->Socket, &fn, 14297c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 14307c478bd9Sstevel@tonic-gate return (ret); 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate /* 14337c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 14347c478bd9Sstevel@tonic-gate * for this client, then return an error. 14357c478bd9Sstevel@tonic-gate */ 14367c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 14377c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 14407c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 14417c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 14427c478bd9Sstevel@tonic-gate cisinfo->Chains = sp->cis[fn].nchains; 14437c478bd9Sstevel@tonic-gate cisinfo->Tuples = sp->cis[fn].ntuples; 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate if ((fn != CS_GLOBAL_CIS) && 14467c478bd9Sstevel@tonic-gate (sp->cis[CS_GLOBAL_CIS].flags & CW_VALID_CIS)) { 14477c478bd9Sstevel@tonic-gate cisinfo->Chains += sp->cis[CS_GLOBAL_CIS].nchains; 14487c478bd9Sstevel@tonic-gate cisinfo->Tuples += sp->cis[CS_GLOBAL_CIS].ntuples; 14497c478bd9Sstevel@tonic-gate } /* !CS_GLOBAL_CIS */ 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 14527c478bd9Sstevel@tonic-gate } else { 14537c478bd9Sstevel@tonic-gate cisinfo->Chains = 0; 14547c478bd9Sstevel@tonic-gate cisinfo->Tuples = 0; 14557c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate return (ret); 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate /* 14637c478bd9Sstevel@tonic-gate * cs_init_cis_window - initializes the CIS window for the passed socket 14647c478bd9Sstevel@tonic-gate * 14657c478bd9Sstevel@tonic-gate * calling: *sp - pointer to the per-socket structure 14667c478bd9Sstevel@tonic-gate * *offset - offset from start of AM or CM space 14677c478bd9Sstevel@tonic-gate * *hp - pointer to acc_handle_t to store modified 14687c478bd9Sstevel@tonic-gate * window access handle in 14697c478bd9Sstevel@tonic-gate * flags - one of: 14707c478bd9Sstevel@tonic-gate * CISTPLF_AM_SPACE - set window to AM space 14717c478bd9Sstevel@tonic-gate * CISTPLF_CM_SPACE - set window to CM space 14727c478bd9Sstevel@tonic-gate * 14737c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if CIS window was set up 14747c478bd9Sstevel@tonic-gate * *offset - contains adjusted offset to use to access 14757c478bd9Sstevel@tonic-gate * requested space 14767c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW if CIS window could not be setup 14777c478bd9Sstevel@tonic-gate * CS_GENERAL_FAILURE if socket has a CIS window number 14787c478bd9Sstevel@tonic-gate * but the window flags are wrong 14797c478bd9Sstevel@tonic-gate * 14807c478bd9Sstevel@tonic-gate * Note: This function will check to be sure that there is a valid 14817c478bd9Sstevel@tonic-gate * CIS window allocated to this socket. 14827c478bd9Sstevel@tonic-gate * If there is an error in setting up the window hardware, the 14837c478bd9Sstevel@tonic-gate * CIS window information for this socket is cleared. 14847c478bd9Sstevel@tonic-gate * This function is also used by routines that need to get 14857c478bd9Sstevel@tonic-gate * a pointer to the base of AM space to access the card's 14867c478bd9Sstevel@tonic-gate * configuration registers. 14877c478bd9Sstevel@tonic-gate * The passed offset is the un-window-size-aligned offset. 14887c478bd9Sstevel@tonic-gate */ 14897c478bd9Sstevel@tonic-gate int 14907c478bd9Sstevel@tonic-gate cs_init_cis_window(cs_socket_t *sp, uint32_t *offset, 14917c478bd9Sstevel@tonic-gate acc_handle_t *hp, uint32_t flags) 14927c478bd9Sstevel@tonic-gate { 14937c478bd9Sstevel@tonic-gate set_window_t sw; 14947c478bd9Sstevel@tonic-gate get_window_t gw; 14957c478bd9Sstevel@tonic-gate inquire_window_t iw; 14967c478bd9Sstevel@tonic-gate set_page_t set_page; 14977c478bd9Sstevel@tonic-gate cs_window_t *cw; 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate /* 15007c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 15017c478bd9Sstevel@tonic-gate */ 15027c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 15037c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15047c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d has no CIS window\n", 15057c478bd9Sstevel@tonic-gate sp->socket_num); 15067c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate /* 15107c478bd9Sstevel@tonic-gate * Check to be sure that this window is allocated for CIS use 15117c478bd9Sstevel@tonic-gate */ 15127c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) 15137c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate if (!(cw->state & CW_CIS)) { 15167c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15177c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d invalid CIS window state 0x%x\n", 15187c478bd9Sstevel@tonic-gate sp->socket_num, cw->state); 15197c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate /* 15237c478bd9Sstevel@tonic-gate * Get the characteristics of this window - we use this to 15247c478bd9Sstevel@tonic-gate * determine whether we need to re-map the window or 15257c478bd9Sstevel@tonic-gate * just move the window offset on the card. 15267c478bd9Sstevel@tonic-gate */ 15277c478bd9Sstevel@tonic-gate iw.window = sp->cis_win_num; 15287c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* 15317c478bd9Sstevel@tonic-gate * We've got a window, now set up the hardware. If we've got 15327c478bd9Sstevel@tonic-gate * a variable sized window, then all we need to do is to 15337c478bd9Sstevel@tonic-gate * get a valid mapping to the base of the window using 15347c478bd9Sstevel@tonic-gate * the current window size; if we've got a fixed-size 15357c478bd9Sstevel@tonic-gate * window, then we need to get a mapping to the window 15367c478bd9Sstevel@tonic-gate * starting at offset zero of the window. 15377c478bd9Sstevel@tonic-gate */ 15387c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_SIZE) { 15397c478bd9Sstevel@tonic-gate sw.WindowSize = sp->cis_win_size; 15407c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / sp->cis_win_size) * 15417c478bd9Sstevel@tonic-gate sp->cis_win_size); 15427c478bd9Sstevel@tonic-gate } else { 15437c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / iw.mem_win_char.MinSize) * 15447c478bd9Sstevel@tonic-gate iw.mem_win_char.MinSize); 15457c478bd9Sstevel@tonic-gate sw.WindowSize = (((*offset & ~(PAGESIZE - 1)) & 15467c478bd9Sstevel@tonic-gate (set_page.offset - 1)) + PAGESIZE); 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate /* 15507c478bd9Sstevel@tonic-gate * Return a normalized base offset; this takes care of the case 15517c478bd9Sstevel@tonic-gate * where the required offset is greater than the window size. 15527c478bd9Sstevel@tonic-gate * BugID 1236404 15537c478bd9Sstevel@tonic-gate * code was: 15547c478bd9Sstevel@tonic-gate * *offset = *offset & (set_page.offset - 1); 15557c478bd9Sstevel@tonic-gate */ 15567c478bd9Sstevel@tonic-gate *offset = *offset - set_page.offset; 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 15597c478bd9Sstevel@tonic-gate if (cs_debug > 1) 15607c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_init_cis_window: WindowSize 0x%x " 15617c478bd9Sstevel@tonic-gate "offset 0x%x\n", 15627c478bd9Sstevel@tonic-gate (int)sw.WindowSize, 15637c478bd9Sstevel@tonic-gate (int)set_page.offset); 15647c478bd9Sstevel@tonic-gate if (cs_debug > 1) 15657c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t*offset = 0x%x space = %s\n", 15667c478bd9Sstevel@tonic-gate (int)*offset, 15677c478bd9Sstevel@tonic-gate (flags & CISTPLF_AM_SPACE)? 15687c478bd9Sstevel@tonic-gate "CISTPLF_AM_SPACE":"CISTPLF_CM_SPACE"); 15697c478bd9Sstevel@tonic-gate #endif 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate sw.window = sp->cis_win_num; 15727c478bd9Sstevel@tonic-gate sw.socket = sp->socket_num; 15737c478bd9Sstevel@tonic-gate sw.state = (WS_ENABLED | WS_EXACT_MAPIN); 15747c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 15757c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 15767c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate /* 15797c478bd9Sstevel@tonic-gate * The PCMCIA SS spec specifies this be expressed in 15807c478bd9Sstevel@tonic-gate * a device speed format per 5.2.7.1.3 but 15817c478bd9Sstevel@tonic-gate * our implementation of SS_SetWindow uses 15827c478bd9Sstevel@tonic-gate * actual nanoseconds. 15837c478bd9Sstevel@tonic-gate */ 15847c478bd9Sstevel@tonic-gate sw.speed = CIS_DEFAULT_SPEED; 15857c478bd9Sstevel@tonic-gate sw.base = 0; 15867c478bd9Sstevel@tonic-gate /* 15877c478bd9Sstevel@tonic-gate * Set up the window - if this fails, then just set the 15887c478bd9Sstevel@tonic-gate * CIS window number back to it's initialized value so 15897c478bd9Sstevel@tonic-gate * that we'll fail when we break out of the loop. 15907c478bd9Sstevel@tonic-gate */ 15917c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) { 15927c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 15937c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 15947c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15957c478bd9Sstevel@tonic-gate } else { 15967c478bd9Sstevel@tonic-gate set_page.window = sp->cis_win_num; 15977c478bd9Sstevel@tonic-gate set_page.page = 0; 15987c478bd9Sstevel@tonic-gate set_page.state = PS_ENABLED; 15997c478bd9Sstevel@tonic-gate if (flags & CISTPLF_AM_SPACE) 16007c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 16037c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 16047c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 16057c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 16067c478bd9Sstevel@tonic-gate } /* if (SS_SetPage) */ 16077c478bd9Sstevel@tonic-gate } /* if (SS_SetWindow) */ 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* 16107c478bd9Sstevel@tonic-gate * Get the window information for the CIS window for this socket. 16117c478bd9Sstevel@tonic-gate */ 16127c478bd9Sstevel@tonic-gate gw.window = sp->cis_win_num; 16137c478bd9Sstevel@tonic-gate gw.socket = sp->socket_num; /* XXX - SS_GetWindow should set this */ 16147c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 16157c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate *hp = (acc_handle_t)gw.handle; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate /* 16237c478bd9Sstevel@tonic-gate * ==== client registration/deregistration section ==== 16247c478bd9Sstevel@tonic-gate */ 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate /* 16277c478bd9Sstevel@tonic-gate * cs_register_client - This supports the RegisterClient call. 16287c478bd9Sstevel@tonic-gate * 16297c478bd9Sstevel@tonic-gate * Upon successful registration, the client_handle_t * handle argument will 16307c478bd9Sstevel@tonic-gate * contain the new client handle and we return CS_SUCCESS. 16317c478bd9Sstevel@tonic-gate */ 16327c478bd9Sstevel@tonic-gate static int 16337c478bd9Sstevel@tonic-gate cs_register_client(client_handle_t *ch, client_reg_t *cr) 16347c478bd9Sstevel@tonic-gate { 16357c478bd9Sstevel@tonic-gate uint32_t sn; 16367c478bd9Sstevel@tonic-gate int super_client = 0; 16377c478bd9Sstevel@tonic-gate sclient_reg_t *scr = cr->priv; 16387c478bd9Sstevel@tonic-gate struct sclient_list_t *scli; 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate /* 16417c478bd9Sstevel@tonic-gate * See if we're not supposed to register any new clients. 16427c478bd9Sstevel@tonic-gate */ 16437c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_NO_CLIENTS) 16447c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate /* 16477c478bd9Sstevel@tonic-gate * Do a version check - if the client expects a later version of 16487c478bd9Sstevel@tonic-gate * Card Services than what we are, return CS_BAD_VERSION. 16497c478bd9Sstevel@tonic-gate * XXX - How do we specify just a PARTICULAR version of CS?? 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate if (CS_VERSION < cr->Version) 16527c478bd9Sstevel@tonic-gate return (CS_BAD_VERSION); 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate /* 16557c478bd9Sstevel@tonic-gate * Check to be sure that the client has given us a valid set of 16567c478bd9Sstevel@tonic-gate * client type flags. We also use this opportunity to see 16577c478bd9Sstevel@tonic-gate * if the registering client is Socket Services or is a 16587c478bd9Sstevel@tonic-gate * "super-client" or a CSI client. 16597c478bd9Sstevel@tonic-gate * 16607c478bd9Sstevel@tonic-gate * Note that SS can not set any flag in the Attributes field other 16617c478bd9Sstevel@tonic-gate * than the INFO_SOCKET_SERVICES flag. 16627c478bd9Sstevel@tonic-gate * 16637c478bd9Sstevel@tonic-gate * Valid combinations of cr->Attributes and cr->EventMask flags: 16647c478bd9Sstevel@tonic-gate * 16657c478bd9Sstevel@tonic-gate * for Socket Services: 16667c478bd9Sstevel@tonic-gate * cr->Attributes: 16677c478bd9Sstevel@tonic-gate * set: 16687c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 16697c478bd9Sstevel@tonic-gate * clear: 16707c478bd9Sstevel@tonic-gate * {all other flags} 16717c478bd9Sstevel@tonic-gate * cr->EventMask: 16727c478bd9Sstevel@tonic-gate * don't care: 16737c478bd9Sstevel@tonic-gate * {all flags} 16747c478bd9Sstevel@tonic-gate * 16757c478bd9Sstevel@tonic-gate * for regular clients: 16767c478bd9Sstevel@tonic-gate * cr->Attributes: 16777c478bd9Sstevel@tonic-gate * only one of: 16787c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 16797c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 16807c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 16817c478bd9Sstevel@tonic-gate * don't care: 16827c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 16837c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 16847c478bd9Sstevel@tonic-gate * cr->EventMask: 16857c478bd9Sstevel@tonic-gate * clear: 16867c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 16877c478bd9Sstevel@tonic-gate * don't care: 16887c478bd9Sstevel@tonic-gate * {all other flags} 16897c478bd9Sstevel@tonic-gate * 16907c478bd9Sstevel@tonic-gate * for CSI clients: 16917c478bd9Sstevel@tonic-gate * cr->Attributes: 16927c478bd9Sstevel@tonic-gate * set: 16937c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 16947c478bd9Sstevel@tonic-gate * INFO_CSI_CLIENT 16957c478bd9Sstevel@tonic-gate * clear: 16967c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 16977c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 16987c478bd9Sstevel@tonic-gate * don't care: 16997c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 17007c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 17017c478bd9Sstevel@tonic-gate * cr->EventMask: 17027c478bd9Sstevel@tonic-gate * don't care: 17037c478bd9Sstevel@tonic-gate * {all flags} 17047c478bd9Sstevel@tonic-gate * 17057c478bd9Sstevel@tonic-gate * for "super-clients": 17067c478bd9Sstevel@tonic-gate * cr->Attributes: 17077c478bd9Sstevel@tonic-gate * set: 17087c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 17097c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 17107c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 17117c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 17127c478bd9Sstevel@tonic-gate * clear: 17137c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 17147c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 17157c478bd9Sstevel@tonic-gate * cr->EventMask: 17167c478bd9Sstevel@tonic-gate * don't care: 17177c478bd9Sstevel@tonic-gate * {all flags} 17187c478bd9Sstevel@tonic-gate */ 17197c478bd9Sstevel@tonic-gate switch (cr->Attributes & INFO_CLIENT_TYPE_MASK) { 17207c478bd9Sstevel@tonic-gate /* 17217c478bd9Sstevel@tonic-gate * Check first to see if this is Socket Services registering; if 17227c478bd9Sstevel@tonic-gate * so, we don't do anything but return the client handle that is 17237c478bd9Sstevel@tonic-gate * in the global SS client. 17247c478bd9Sstevel@tonic-gate */ 17257c478bd9Sstevel@tonic-gate case INFO_SOCKET_SERVICES: 17267c478bd9Sstevel@tonic-gate *ch = cs_socket_services_client.client_handle; 17277c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 17287c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17297c478bd9Sstevel@tonic-gate /* CSI clients */ 17307c478bd9Sstevel@tonic-gate case (INFO_CSI_CLIENT | INFO_IO_CLIENT): 17317c478bd9Sstevel@tonic-gate break; 17327c478bd9Sstevel@tonic-gate /* regular clients */ 17337c478bd9Sstevel@tonic-gate case INFO_IO_CLIENT: 17347c478bd9Sstevel@tonic-gate case INFO_MTD_CLIENT: 17357c478bd9Sstevel@tonic-gate case INFO_MEM_CLIENT: 17367c478bd9Sstevel@tonic-gate if (cr->EventMask & CS_EVENT_ALL_CLIENTS) 17377c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17387c478bd9Sstevel@tonic-gate break; 17397c478bd9Sstevel@tonic-gate /* "super-client" clients */ 17407c478bd9Sstevel@tonic-gate case (INFO_IO_CLIENT | INFO_MTD_CLIENT | INFO_SOCKET_SERVICES): 17417c478bd9Sstevel@tonic-gate if ((!(cr->Attributes & INFO_CARD_SHARE)) || 17427c478bd9Sstevel@tonic-gate (cr->Attributes & INFO_CARD_EXCL)) 17437c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17447c478bd9Sstevel@tonic-gate /* 17457c478bd9Sstevel@tonic-gate * We only allow one "super-client" per system. 17467c478bd9Sstevel@tonic-gate */ 17477c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 17487c478bd9Sstevel@tonic-gate if (cs_globals.flags & GLOBAL_SUPER_CLIENT_REGISTERED) { 17497c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 17507c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate cs_globals.flags |= GLOBAL_SUPER_CLIENT_REGISTERED; 17537c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 17547c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 17557c478bd9Sstevel@tonic-gate break; 17567c478bd9Sstevel@tonic-gate default: 17577c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17587c478bd9Sstevel@tonic-gate } /* switch (cr->Attributes) */ 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate /* 17617c478bd9Sstevel@tonic-gate * Now, actually create the client node on the socket; this will 17627c478bd9Sstevel@tonic-gate * also return the new client handle if there were no errors 17637c478bd9Sstevel@tonic-gate * creating the client node. 17647c478bd9Sstevel@tonic-gate * The DIP2SOCKET_NUM macro will return the socket and function 17657c478bd9Sstevel@tonic-gate * number using the encoding specified in the cs_priv.h file. 17667c478bd9Sstevel@tonic-gate */ 17677c478bd9Sstevel@tonic-gate if (super_client != CLIENT_SUPER_CLIENT) { 17687c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 17697c478bd9Sstevel@tonic-gate sn = (uint32_t)(uintptr_t)cr->priv; 17707c478bd9Sstevel@tonic-gate else 17717c478bd9Sstevel@tonic-gate sn = DIP2SOCKET_NUM(cr->dip); 17727c478bd9Sstevel@tonic-gate return (cs_add_client_to_socket(sn, ch, cr, super_client)); 17737c478bd9Sstevel@tonic-gate } /* CLIENT_SUPER_CLIENT */ 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate /* 17767c478bd9Sstevel@tonic-gate * This registering client is a "super-client", so we create one 17777c478bd9Sstevel@tonic-gate * client node for each socket in the system. We use the 17787c478bd9Sstevel@tonic-gate * client_reg_t.priv structure member to point to a struct 17797c478bd9Sstevel@tonic-gate * that the "super-client" client knows about. The client 17807c478bd9Sstevel@tonic-gate * handle pointer is not used in this case. 17817c478bd9Sstevel@tonic-gate * We return CS_SUCCESS if at least one client node could be 17827c478bd9Sstevel@tonic-gate * created. The client must check the error codes in the 17837c478bd9Sstevel@tonic-gate * error code array to determine which clients could not 17847c478bd9Sstevel@tonic-gate * be created on which sockets. 17857c478bd9Sstevel@tonic-gate * We return CS_BAD_HANDLE if no client nodes could be created. 17867c478bd9Sstevel@tonic-gate */ 17877c478bd9Sstevel@tonic-gate scr->num_clients = 0; 17887c478bd9Sstevel@tonic-gate scr->max_socket_num = cs_globals.max_socket_num; 17897c478bd9Sstevel@tonic-gate scr->num_sockets = cs_globals.num_sockets; 17907c478bd9Sstevel@tonic-gate scr->num_windows = cs_globals.num_windows; 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate *(scr->sclient_list) = cs_globals.sclient_list; 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate for (sn = 0; sn < scr->num_sockets; sn++) { 17957c478bd9Sstevel@tonic-gate scli = scr->sclient_list[sn]; 17967c478bd9Sstevel@tonic-gate if ((scli->error = cs_add_client_to_socket(sn, &scli->client_handle, 17977c478bd9Sstevel@tonic-gate cr, super_client)) == CS_SUCCESS) { 17987c478bd9Sstevel@tonic-gate scr->num_clients++; 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate /* 18037c478bd9Sstevel@tonic-gate * If we couldn't create any client nodes at all, then 18047c478bd9Sstevel@tonic-gate * return an error. 18057c478bd9Sstevel@tonic-gate */ 18067c478bd9Sstevel@tonic-gate if (!scr->num_clients) { 18077c478bd9Sstevel@tonic-gate /* 18087c478bd9Sstevel@tonic-gate * XXX - The global superclient lock now gets 18097c478bd9Sstevel@tonic-gate * cleared in cs_deregister_client 18107c478bd9Sstevel@tonic-gate */ 18117c478bd9Sstevel@tonic-gate /* cs_clear_superclient_lock(super_client); */ 18127c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate /* 18197c478bd9Sstevel@tonic-gate * cs_add_client_to_socket - this function creates the client node on the 18207c478bd9Sstevel@tonic-gate * requested socket. 18217c478bd9Sstevel@tonic-gate * 18227c478bd9Sstevel@tonic-gate * Note that if we return an error, there is no state that can be cleaned 18237c478bd9Sstevel@tonic-gate * up. The only way that we can return an error with allocated resources 18247c478bd9Sstevel@tonic-gate * would be if one of the client handle functions had an internal error. 18257c478bd9Sstevel@tonic-gate * Since we wouldn't get a valid client handle in this case anyway, there 18267c478bd9Sstevel@tonic-gate * would be no way to find out what was allocated and what wasn't. 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate static int 18297c478bd9Sstevel@tonic-gate cs_add_client_to_socket(unsigned sn, client_handle_t *ch, 18307c478bd9Sstevel@tonic-gate client_reg_t *cr, int super_client) 18317c478bd9Sstevel@tonic-gate { 18327c478bd9Sstevel@tonic-gate cs_socket_t *sp; 18337c478bd9Sstevel@tonic-gate client_t *client, *cclp; 18347c478bd9Sstevel@tonic-gate int error, cie = 1; 18357c478bd9Sstevel@tonic-gate int client_lock_acquired; 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate if (cr->event_handler == NULL) 18387c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 18417c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate /* 18467c478bd9Sstevel@tonic-gate * Run through all of the registered clients and compare the passed 18477c478bd9Sstevel@tonic-gate * dip to the dip of each client to make sure that this client 18487c478bd9Sstevel@tonic-gate * is not trying to register more than once. If they are, then 18497c478bd9Sstevel@tonic-gate * display a message and return an error. 18507c478bd9Sstevel@tonic-gate * XXX - we should really check all the sockets in case the client 18517c478bd9Sstevel@tonic-gate * manipulates the instance number in the dip. 18527c478bd9Sstevel@tonic-gate * XXX - if we check each socket, we ned to also check for the 18537c478bd9Sstevel@tonic-gate * "super-client" since it will use the same dip for all 18547c478bd9Sstevel@tonic-gate * of it's client nodes. 18557c478bd9Sstevel@tonic-gate */ 18567c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 18577c478bd9Sstevel@tonic-gate client = sp->client_list; 18587c478bd9Sstevel@tonic-gate while (client) { 18597c478bd9Sstevel@tonic-gate if (!(cr->Attributes & INFO_CSI_CLIENT) && 18607c478bd9Sstevel@tonic-gate (client->dip == cr->dip)) { 18617c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18627c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 18637c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d " 18647c478bd9Sstevel@tonic-gate "function 0x%x\n" 18657c478bd9Sstevel@tonic-gate "\tclient already registered with " 18667c478bd9Sstevel@tonic-gate "handle 0x%x\n", 18677c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 18687c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 18697c478bd9Sstevel@tonic-gate (int)client->client_handle); 18707c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 18717c478bd9Sstevel@tonic-gate } 18727c478bd9Sstevel@tonic-gate client = client->next; 18737c478bd9Sstevel@tonic-gate } /* while (client) */ 18747c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18757c478bd9Sstevel@tonic-gate 18767c478bd9Sstevel@tonic-gate /* 18777c478bd9Sstevel@tonic-gate * Create a unique client handle then make sure that we can find it. 18787c478bd9Sstevel@tonic-gate * This has the side effect of getting us a pointer to the 18797c478bd9Sstevel@tonic-gate * client structure as well. 18807c478bd9Sstevel@tonic-gate * Create a client list entry - cs_create_client_handle will use this 18817c478bd9Sstevel@tonic-gate * as the new client node. 18827c478bd9Sstevel@tonic-gate * We do it here so that we can grab the sp->lock mutex for the 18837c478bd9Sstevel@tonic-gate * duration of our manipulation of the client list. 18847c478bd9Sstevel@tonic-gate * If this function fails, then it will not have added the newly 18857c478bd9Sstevel@tonic-gate * allocated client node to the client list on this socket, 18867c478bd9Sstevel@tonic-gate * so we have to free the node that we allocated. 18877c478bd9Sstevel@tonic-gate */ 18887c478bd9Sstevel@tonic-gate cclp = (client_t *)kmem_zalloc(sizeof (client_t), KM_SLEEP); 18897c478bd9Sstevel@tonic-gate 18907c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 18917c478bd9Sstevel@tonic-gate if (!(*ch = cs_create_client_handle(sn, cclp))) { 18927c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 18947c478bd9Sstevel@tonic-gate kmem_free(cclp, sizeof (client_t)); 18957c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 18967c478bd9Sstevel@tonic-gate } 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate /* 18997c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. We should never 19007c478bd9Sstevel@tonic-gate * fail this since we just got a valid client handle. 19017c478bd9Sstevel@tonic-gate * If this fails, then we have an internal error so don't bother 19027c478bd9Sstevel@tonic-gate * trying to clean up the allocated client handle since the 19037c478bd9Sstevel@tonic-gate * whole system is probably hosed anyway and will shortly 19047c478bd9Sstevel@tonic-gate * esplode. 19057c478bd9Sstevel@tonic-gate * It doesn't make sense to call cs_deregister_client at this point 19067c478bd9Sstevel@tonic-gate * to clean up this broken client since the deregistration 19077c478bd9Sstevel@tonic-gate * code will also call cs_find_client and most likely fail. 19087c478bd9Sstevel@tonic-gate */ 19097c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(*ch, &error))) { 19107c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 19117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 19127c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d function 0x%x " 19137c478bd9Sstevel@tonic-gate "invalid client handle created handle 0x%x\n", 19147c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 19157c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 19167c478bd9Sstevel@tonic-gate (int)*ch); 19177c478bd9Sstevel@tonic-gate return (error); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate /* 19217c478bd9Sstevel@tonic-gate * Save the DDI information. 19227c478bd9Sstevel@tonic-gate */ 19237c478bd9Sstevel@tonic-gate client->dip = cr->dip; 1924*c48c3045SToomas Soome cr->driver_name[MODMAXNAMELEN - 1] = '\0'; 1925*c48c3045SToomas Soome client->driver_name = kmem_zalloc(strlen(cr->driver_name) + 1, 1926*c48c3045SToomas Soome KM_SLEEP); 19277c478bd9Sstevel@tonic-gate (void) strcpy(client->driver_name, cr->driver_name); 19287c478bd9Sstevel@tonic-gate client->instance = ddi_get_instance(cr->dip); 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate /* 19317c478bd9Sstevel@tonic-gate * Copy over the interesting items that the client gave us. 19327c478bd9Sstevel@tonic-gate */ 19337c478bd9Sstevel@tonic-gate client->flags = (cr->Attributes & INFO_CLIENT_TYPE_MASK); 19347c478bd9Sstevel@tonic-gate client->event_callback_handler = cr->event_handler; 19357c478bd9Sstevel@tonic-gate bcopy((caddr_t)&cr->event_callback_args, 19367c478bd9Sstevel@tonic-gate (caddr_t)&client->event_callback_args, 19377c478bd9Sstevel@tonic-gate sizeof (event_callback_args_t)); 19387c478bd9Sstevel@tonic-gate /* 19397c478bd9Sstevel@tonic-gate * Set the client handle since the client needs a client handle 19407c478bd9Sstevel@tonic-gate * when they call us for their event handler. 19417c478bd9Sstevel@tonic-gate */ 19427c478bd9Sstevel@tonic-gate client->event_callback_args.client_handle = *ch; 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate /* 19457c478bd9Sstevel@tonic-gate * Initialize the IO window numbers; if an IO window number is equal 19467c478bd9Sstevel@tonic-gate * to PCMCIA_MAX_WINDOWS it means that IO range is not in use. 19477c478bd9Sstevel@tonic-gate */ 19487c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = PCMCIA_MAX_WINDOWS; 19497c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate /* 19527c478bd9Sstevel@tonic-gate * Give the client the iblock and idevice cookies to use in 19537c478bd9Sstevel@tonic-gate * the client's event handler high priority mutex. 19547c478bd9Sstevel@tonic-gate */ 19557c478bd9Sstevel@tonic-gate cr->iblk_cookie = sp->iblk; 19567c478bd9Sstevel@tonic-gate cr->idev_cookie = sp->idev; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate /* 19597c478bd9Sstevel@tonic-gate * Set up the global event mask information; we copy this directly 19607c478bd9Sstevel@tonic-gate * from the client; since we are the only source of events, 19617c478bd9Sstevel@tonic-gate * any bogus bits that the client puts in here won't matter 19627c478bd9Sstevel@tonic-gate * because we'll never look at them. 19637c478bd9Sstevel@tonic-gate */ 19647c478bd9Sstevel@tonic-gate client->global_mask = cr->EventMask; 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate /* 19677c478bd9Sstevel@tonic-gate * If this client registered as a CSI client, set the appropriate 19687c478bd9Sstevel@tonic-gate * flag in the client's flags area. 19697c478bd9Sstevel@tonic-gate */ 19707c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 19717c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CSI_CLIENT; 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate /* 19747c478bd9Sstevel@tonic-gate * If this client registered as a "super-client" set the appropriate 19757c478bd9Sstevel@tonic-gate * flag in the client's flags area. 19767c478bd9Sstevel@tonic-gate */ 19777c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) 19787c478bd9Sstevel@tonic-gate client->flags |= CLIENT_SUPER_CLIENT; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate /* 19817c478bd9Sstevel@tonic-gate * Save other misc information that this client gave us - it is 19827c478bd9Sstevel@tonic-gate * used in the GetClientInfo function. 19837c478bd9Sstevel@tonic-gate */ 19847c478bd9Sstevel@tonic-gate client->flags |= (cr->Attributes & INFO_CARD_FLAGS_MASK); 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate /* 19877c478bd9Sstevel@tonic-gate * Determine if we should give artificial card insertion events and 19887c478bd9Sstevel@tonic-gate * a registration complete event. Since we don't differentiate 19897c478bd9Sstevel@tonic-gate * between sharable and exclusive use cards when giving clients 19907c478bd9Sstevel@tonic-gate * event notification, we modify the definition of the share/excl 19917c478bd9Sstevel@tonic-gate * flags as follows: 19927c478bd9Sstevel@tonic-gate * 19937c478bd9Sstevel@tonic-gate * If either INFO_CARD_SHARE or INFO_CARD_EXCL is set, 19947c478bd9Sstevel@tonic-gate * the client will receive artificial card insertion 19957c478bd9Sstevel@tonic-gate * events (if the client's card is currently in the 19967c478bd9Sstevel@tonic-gate * socket) and a registration complete event. 19977c478bd9Sstevel@tonic-gate * 19987c478bd9Sstevel@tonic-gate * If neither of the INFO_CARD_SHARE or INFO_CARD_EXCL is 19997c478bd9Sstevel@tonic-gate * set, the client will not receive an artificial card 20007c478bd9Sstevel@tonic-gate * insertion event nor a registration complete event 20017c478bd9Sstevel@tonic-gate * due to the client's call to register client. 20027c478bd9Sstevel@tonic-gate * 20037c478bd9Sstevel@tonic-gate * The client's event mask is not affected by the setting 20047c478bd9Sstevel@tonic-gate * of these two bits. 20057c478bd9Sstevel@tonic-gate */ 20067c478bd9Sstevel@tonic-gate if (cr->Attributes & (INFO_CARD_SHARE | INFO_CARD_EXCL)) 20077c478bd9Sstevel@tonic-gate client->pending_events = CS_EVENT_REGISTRATION_COMPLETE; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate /* 20107c478bd9Sstevel@tonic-gate * Check to see if the card for this client is currently in 20117c478bd9Sstevel@tonic-gate * the socket. If it is, then set CLIENT_CARD_INSERTED 20127c478bd9Sstevel@tonic-gate * since clients that are calling GetStatus at attach 20137c478bd9Sstevel@tonic-gate * time will typically check to see if their card is 20147c478bd9Sstevel@tonic-gate * currently installed. 20157c478bd9Sstevel@tonic-gate * If this is the CSI client, we also need to check to see 20167c478bd9Sstevel@tonic-gate * if there is any card inserted in the socket, since 20177c478bd9Sstevel@tonic-gate * the cs_card_for_client function will always return 20187c478bd9Sstevel@tonic-gate * TRUE for a CSI client. 20197c478bd9Sstevel@tonic-gate * XXX What about super-clients? 20207c478bd9Sstevel@tonic-gate */ 20217c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) { 20227c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate get_ss_status.socket = sp->socket_num; 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, &get_ss_status) != SUCCESS) { 20277c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 20287c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20297c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 20307c478bd9Sstevel@tonic-gate } /* SS_GetStatus */ 20317c478bd9Sstevel@tonic-gate 20327c478bd9Sstevel@tonic-gate if (!(cs_sbm2cse(get_ss_status.CardState) & 20337c478bd9Sstevel@tonic-gate CS_EVENT_CARD_INSERTION)) 20347c478bd9Sstevel@tonic-gate cie = 0; 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate } /* CLIENT_CSI_CLIENT */ 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate if (cs_card_for_client(client) && (cie != 0)) { 20397c478bd9Sstevel@tonic-gate client->pending_events |= CS_EVENT_CARD_INSERTION; 20407c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CARD_INSERTED; 20417c478bd9Sstevel@tonic-gate } /* cs_card_for_client */ 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate sp->num_clients++; 20447c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 20457c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate /* 20517c478bd9Sstevel@tonic-gate * cs_deregister_client - This supports the DeregisterClient call. 20527c478bd9Sstevel@tonic-gate */ 20537c478bd9Sstevel@tonic-gate static int 20547c478bd9Sstevel@tonic-gate cs_deregister_client(client_handle_t client_handle) 20557c478bd9Sstevel@tonic-gate { 20567c478bd9Sstevel@tonic-gate cs_socket_t *sp; 20577c478bd9Sstevel@tonic-gate client_t *client; 20587c478bd9Sstevel@tonic-gate int error, super_client = 0; 20597c478bd9Sstevel@tonic-gate int client_lock_acquired; 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate /* 20627c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 20637c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 20647c478bd9Sstevel@tonic-gate */ 20657c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 20667c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate /* 20697c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 20707c478bd9Sstevel@tonic-gate */ 20717c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 20727c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate /* 20777c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 20787c478bd9Sstevel@tonic-gate */ 20797c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 20807c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20817c478bd9Sstevel@tonic-gate return (error); 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate /* 20857c478bd9Sstevel@tonic-gate * Make sure that any resources allocated by this client are 20867c478bd9Sstevel@tonic-gate * not still allocated, and that if this is an MTD that 20877c478bd9Sstevel@tonic-gate * no MTD operations are still in progress. 20887c478bd9Sstevel@tonic-gate */ 20897c478bd9Sstevel@tonic-gate if (client->flags & (CLIENT_IO_ALLOCATED | 20907c478bd9Sstevel@tonic-gate CLIENT_IRQ_ALLOCATED | 20917c478bd9Sstevel@tonic-gate CLIENT_WIN_ALLOCATED | 20927c478bd9Sstevel@tonic-gate REQ_CONFIGURATION_DONE | 20937c478bd9Sstevel@tonic-gate REQ_SOCKET_MASK_DONE | 20947c478bd9Sstevel@tonic-gate REQ_IO_DONE | 20957c478bd9Sstevel@tonic-gate REQ_IRQ_DONE)) { 20967c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20977c478bd9Sstevel@tonic-gate return (CS_BUSY); 20987c478bd9Sstevel@tonic-gate } 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_MTD_IN_PROGRESS) { 21017c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 21027c478bd9Sstevel@tonic-gate return (CS_IN_USE); 21037c478bd9Sstevel@tonic-gate } 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate /* 21067c478bd9Sstevel@tonic-gate * Any previously allocated resources are not allocated anymore, and 21077c478bd9Sstevel@tonic-gate * no MTD operations are in progress, so if this is an MTD client 21087c478bd9Sstevel@tonic-gate * then do any MTD-specific client deregistration, and then 21097c478bd9Sstevel@tonic-gate * nuke this client. 21107c478bd9Sstevel@tonic-gate * We expect cs_deregister_mtd to never fail. 21117c478bd9Sstevel@tonic-gate */ 21127c478bd9Sstevel@tonic-gate if (client->flags & INFO_MTD_CLIENT) 21137c478bd9Sstevel@tonic-gate (void) cs_deregister_mtd(client_handle); 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_SUPER_CLIENT) 21167c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate kmem_free(client->driver_name, strlen(client->driver_name) + 1); 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate error = cs_destroy_client_handle(client_handle); 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate /* 21257c478bd9Sstevel@tonic-gate * If this was the "super-client" deregistering, then this 21267c478bd9Sstevel@tonic-gate * will clear the global "super-client" lock. 21277c478bd9Sstevel@tonic-gate * XXX - move this outside the per-socket code. 21287c478bd9Sstevel@tonic-gate */ 21297c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(super_client); 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate return (error); 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate /* 21357c478bd9Sstevel@tonic-gate * cs_create_next_client_minor - returns the next available client minor 21367c478bd9Sstevel@tonic-gate * number or 0 if none available 21377c478bd9Sstevel@tonic-gate * 21387c478bd9Sstevel@tonic-gate * Note that cs_find_client will always return a valid pointer to the 21397c478bd9Sstevel@tonic-gate * global Socket Services client which has a client minor number 21407c478bd9Sstevel@tonic-gate * of 0; this means that this function can never return a 0 as the 21417c478bd9Sstevel@tonic-gate * next valid available client minor number. 21427c478bd9Sstevel@tonic-gate */ 21437c478bd9Sstevel@tonic-gate unsigned 21447c478bd9Sstevel@tonic-gate cs_create_next_client_minor(unsigned socket_num, unsigned next_minor) 21457c478bd9Sstevel@tonic-gate { 21467c478bd9Sstevel@tonic-gate unsigned max_client_handles = cs_max_client_handles; 21477c478bd9Sstevel@tonic-gate 21487c478bd9Sstevel@tonic-gate do { 21497c478bd9Sstevel@tonic-gate next_minor &= CS_MAX_CLIENTS_MASK; 21507c478bd9Sstevel@tonic-gate if (!cs_find_client(MAKE_CLIENT_HANDLE( 21517c478bd9Sstevel@tonic-gate CS_GET_SOCKET_NUMBER(socket_num), 21527c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 21537c478bd9Sstevel@tonic-gate next_minor), NULL)) { 21547c478bd9Sstevel@tonic-gate return (next_minor); 21557c478bd9Sstevel@tonic-gate } 21567c478bd9Sstevel@tonic-gate next_minor++; 21577c478bd9Sstevel@tonic-gate } while (max_client_handles--); 21587c478bd9Sstevel@tonic-gate 21597c478bd9Sstevel@tonic-gate return (0); 21607c478bd9Sstevel@tonic-gate } 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate /* 21637c478bd9Sstevel@tonic-gate * cs_find_client - finds the client pointer associated with the client handle 21647c478bd9Sstevel@tonic-gate * or NULL if client not found 21657c478bd9Sstevel@tonic-gate * 21667c478bd9Sstevel@tonic-gate * returns: (client_t *)NULL - if client not found or an error occured 21677c478bd9Sstevel@tonic-gate * If the error argument is not NULL, 21687c478bd9Sstevel@tonic-gate * it is set to: 21697c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - socket number in client_handle_t is 21707c478bd9Sstevel@tonic-gate * invalid 21717c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client not found 21727c478bd9Sstevel@tonic-gate * If no error, the error argument is not modified. 21737c478bd9Sstevel@tonic-gate * (client_t *) - pointer to client_t structure 21747c478bd9Sstevel@tonic-gate * 21757c478bd9Sstevel@tonic-gate * Note that each socket always has a pseudo client with a client minor number 21767c478bd9Sstevel@tonic-gate * of 0; this client minor number is used for Socket Services access to 21777c478bd9Sstevel@tonic-gate * Card Services functions. The client pointer returned for client minor 21787c478bd9Sstevel@tonic-gate * number 0 is the global Socket Services client pointer. 21797c478bd9Sstevel@tonic-gate */ 21807c478bd9Sstevel@tonic-gate static client_t * 21817c478bd9Sstevel@tonic-gate cs_find_client(client_handle_t client_handle, int *error) 21827c478bd9Sstevel@tonic-gate { 21837c478bd9Sstevel@tonic-gate cs_socket_t *sp; 21847c478bd9Sstevel@tonic-gate client_t *clp; 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate /* 21877c478bd9Sstevel@tonic-gate * If we are being asked to see if a client with a minor number 21887c478bd9Sstevel@tonic-gate * of 0 exists, always return a pointer to the global Socket 21897c478bd9Sstevel@tonic-gate * Services client, since this client always exists, and is 21907c478bd9Sstevel@tonic-gate * only for use by Socket Services. There is no socket 21917c478bd9Sstevel@tonic-gate * associated with this special client handle. 21927c478bd9Sstevel@tonic-gate */ 21937c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 21947c478bd9Sstevel@tonic-gate return (&cs_socket_services_client); 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate /* 21977c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 21987c478bd9Sstevel@tonic-gate */ 21997c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(GET_CLIENT_SOCKET(client_handle), 22007c478bd9Sstevel@tonic-gate cs_globals.max_socket_num))) { 22017c478bd9Sstevel@tonic-gate if (error) 22027c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 22037c478bd9Sstevel@tonic-gate return (NULL); 22047c478bd9Sstevel@tonic-gate } 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) { 22077c478bd9Sstevel@tonic-gate if (error) 22087c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 22097c478bd9Sstevel@tonic-gate return (NULL); 22107c478bd9Sstevel@tonic-gate } 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate clp = sp->client_list; 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate while (clp) { 22157c478bd9Sstevel@tonic-gate if (clp->client_handle == client_handle) 22167c478bd9Sstevel@tonic-gate return (clp); 22177c478bd9Sstevel@tonic-gate clp = clp->next; 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate if (error) 22217c478bd9Sstevel@tonic-gate *error = CS_BAD_HANDLE; 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate return (NULL); 22247c478bd9Sstevel@tonic-gate } 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate /* 22277c478bd9Sstevel@tonic-gate * cs_destroy_client_handle - destroys client handle and client structure of 22287c478bd9Sstevel@tonic-gate * passed client handle 22297c478bd9Sstevel@tonic-gate * 22307c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client handle sucessfully destroyed 22317c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client handle is invalid or if trying 22327c478bd9Sstevel@tonic-gate * to destroy global SS client 22337c478bd9Sstevel@tonic-gate * {other errors} - other errors from cs_find_client() 22347c478bd9Sstevel@tonic-gate */ 22357c478bd9Sstevel@tonic-gate static int 22367c478bd9Sstevel@tonic-gate cs_destroy_client_handle(client_handle_t client_handle) 22377c478bd9Sstevel@tonic-gate { 22387c478bd9Sstevel@tonic-gate client_t *clp; 22397c478bd9Sstevel@tonic-gate cs_socket_t *sp; 22407c478bd9Sstevel@tonic-gate int error = CS_BAD_HANDLE; 22417c478bd9Sstevel@tonic-gate 22427c478bd9Sstevel@tonic-gate /* 22437c478bd9Sstevel@tonic-gate * See if we were passed a valid client handle or if we're being asked 22447c478bd9Sstevel@tonic-gate * to destroy the Socket Services client 22457c478bd9Sstevel@tonic-gate */ 22467c478bd9Sstevel@tonic-gate if ((!(clp = cs_find_client(client_handle, &error))) || 22477c478bd9Sstevel@tonic-gate (CLIENT_HANDLE_IS_SS(client_handle))) 22487c478bd9Sstevel@tonic-gate return (error); 22497c478bd9Sstevel@tonic-gate 22507c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 22517c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate /* 22547c478bd9Sstevel@tonic-gate * Recycle this client's minor number. This will most likely 22557c478bd9Sstevel@tonic-gate * be the next client minor number we use, but it is also 22567c478bd9Sstevel@tonic-gate * a hint to cs_create_client_handle, and that function 22577c478bd9Sstevel@tonic-gate * may actually create a new client handle using a minor 22587c478bd9Sstevel@tonic-gate * number different that this number. 22597c478bd9Sstevel@tonic-gate */ 22607c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 22617c478bd9Sstevel@tonic-gate sp->next_cl_minor = GET_CLIENT_MINOR(client_handle); 22627c478bd9Sstevel@tonic-gate 22637c478bd9Sstevel@tonic-gate /* 22647c478bd9Sstevel@tonic-gate * See if we're the first or not in the client list; if we're 22657c478bd9Sstevel@tonic-gate * not first, then just adjust the client behind us to 22667c478bd9Sstevel@tonic-gate * point to the client ahead of us; this could be NULL 22677c478bd9Sstevel@tonic-gate * if we're the last client in the list. 22687c478bd9Sstevel@tonic-gate */ 22697c478bd9Sstevel@tonic-gate if (clp->prev) { 22707c478bd9Sstevel@tonic-gate clp->prev->next = clp->next; 22717c478bd9Sstevel@tonic-gate } else { 22727c478bd9Sstevel@tonic-gate /* 22737c478bd9Sstevel@tonic-gate * We are first, so adjust the client list head pointer 22747c478bd9Sstevel@tonic-gate * in the socket to point to the client structure that 22757c478bd9Sstevel@tonic-gate * follows us; this could turn out to be NULL if we're 22767c478bd9Sstevel@tonic-gate * the only client on this socket. 22777c478bd9Sstevel@tonic-gate */ 22787c478bd9Sstevel@tonic-gate sp->client_list = clp->next; 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate /* 22827c478bd9Sstevel@tonic-gate * If we're not the last client in the list, point the next 22837c478bd9Sstevel@tonic-gate * client to the client behind us; this could turn out 22847c478bd9Sstevel@tonic-gate * to be NULL if we're the first client on this socket. 22857c478bd9Sstevel@tonic-gate */ 22867c478bd9Sstevel@tonic-gate if (clp->next) 22877c478bd9Sstevel@tonic-gate clp->next->prev = clp->prev; 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate sp->num_clients--; 22907c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 22917c478bd9Sstevel@tonic-gate 22927c478bd9Sstevel@tonic-gate /* 22937c478bd9Sstevel@tonic-gate * Free this client's memory. 22947c478bd9Sstevel@tonic-gate */ 22957c478bd9Sstevel@tonic-gate kmem_free(clp, sizeof (client_t)); 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 22987c478bd9Sstevel@tonic-gate } 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate /* 23017c478bd9Sstevel@tonic-gate * cs_create_client_handle - create a new client handle for the passed 23027c478bd9Sstevel@tonic-gate * socket and function number 23037c478bd9Sstevel@tonic-gate * 23047c478bd9Sstevel@tonic-gate * returns: 0 - if can't create client for some reason 23057c478bd9Sstevel@tonic-gate * client_handle_t - new client handle 23067c478bd9Sstevel@tonic-gate */ 23077c478bd9Sstevel@tonic-gate static client_handle_t 23087c478bd9Sstevel@tonic-gate cs_create_client_handle(unsigned socket_num, client_t *cclp) 23097c478bd9Sstevel@tonic-gate { 23107c478bd9Sstevel@tonic-gate client_t *clp; 23117c478bd9Sstevel@tonic-gate cs_socket_t *sp; 23127c478bd9Sstevel@tonic-gate unsigned next_minor; 23137c478bd9Sstevel@tonic-gate client_handle_t client_handle; 23147c478bd9Sstevel@tonic-gate 23157c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(socket_num)) == NULL) 23167c478bd9Sstevel@tonic-gate return (0); 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate /* 23197c478bd9Sstevel@tonic-gate * Get the next available minor number that we can use. We use the 23207c478bd9Sstevel@tonic-gate * next_cl_minor number as a hint to cs_create_next_client_minor 23217c478bd9Sstevel@tonic-gate * and in most cases this will be the minor number we get back. 23227c478bd9Sstevel@tonic-gate * If for some reason we can't get a minor number, return an error. 23237c478bd9Sstevel@tonic-gate * The only way we could get an error would be if there are 23247c478bd9Sstevel@tonic-gate * already the maximum number of clients for this socket. Since 23257c478bd9Sstevel@tonic-gate * the maximum number of clients per socket is pretty large, 23267c478bd9Sstevel@tonic-gate * this error is unlikely to occur. 23277c478bd9Sstevel@tonic-gate */ 23287c478bd9Sstevel@tonic-gate if (!(next_minor = 23297c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor))) 23307c478bd9Sstevel@tonic-gate return (0); 23317c478bd9Sstevel@tonic-gate 23327c478bd9Sstevel@tonic-gate /* 23337c478bd9Sstevel@tonic-gate * Got a new client minor number, now create a new client handle. 23347c478bd9Sstevel@tonic-gate */ 23357c478bd9Sstevel@tonic-gate client_handle = MAKE_CLIENT_HANDLE(CS_GET_SOCKET_NUMBER(socket_num), 23367c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 23377c478bd9Sstevel@tonic-gate next_minor); 23387c478bd9Sstevel@tonic-gate 23397c478bd9Sstevel@tonic-gate /* 23407c478bd9Sstevel@tonic-gate * If this client handle exists, then we have an internal 23417c478bd9Sstevel@tonic-gate * error; this should never happen, BTW. This is really 23427c478bd9Sstevel@tonic-gate * a double-check on the cs_create_next_client_minor 23437c478bd9Sstevel@tonic-gate * function, which also calls cs_find_client. 23447c478bd9Sstevel@tonic-gate */ 23457c478bd9Sstevel@tonic-gate if (cs_find_client(client_handle, NULL)) { 23467c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 23477c478bd9Sstevel@tonic-gate "cs_create_client_handle: duplicate client handle 0x%x\n", 23487c478bd9Sstevel@tonic-gate (int)client_handle); 23497c478bd9Sstevel@tonic-gate return (0); 23507c478bd9Sstevel@tonic-gate } 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate /* 23537c478bd9Sstevel@tonic-gate * If we don't have any clients on this socket yet, create 23547c478bd9Sstevel@tonic-gate * a new client and hang it on the socket client list. 23557c478bd9Sstevel@tonic-gate */ 23567c478bd9Sstevel@tonic-gate if (!sp->client_list) { 23577c478bd9Sstevel@tonic-gate sp->client_list = cclp; 23587c478bd9Sstevel@tonic-gate clp = sp->client_list; 23597c478bd9Sstevel@tonic-gate } else { 23607c478bd9Sstevel@tonic-gate /* 23617c478bd9Sstevel@tonic-gate * There are other clients on this socket, so look for 23627c478bd9Sstevel@tonic-gate * the last client and add our new client after it. 23637c478bd9Sstevel@tonic-gate */ 23647c478bd9Sstevel@tonic-gate clp = sp->client_list; 23657c478bd9Sstevel@tonic-gate while (clp->next) { 23667c478bd9Sstevel@tonic-gate clp = clp->next; 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate clp->next = cclp; 23707c478bd9Sstevel@tonic-gate clp->next->prev = clp; 23717c478bd9Sstevel@tonic-gate clp = clp->next; 23727c478bd9Sstevel@tonic-gate } /* if (!sp->client_list) */ 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate /* 23757c478bd9Sstevel@tonic-gate * Assign the new client handle to this new client structure. 23767c478bd9Sstevel@tonic-gate */ 23777c478bd9Sstevel@tonic-gate clp->client_handle = client_handle; 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate /* 23807c478bd9Sstevel@tonic-gate * Create the next available client minor number for this socket 23817c478bd9Sstevel@tonic-gate * and save it away. 23827c478bd9Sstevel@tonic-gate */ 23837c478bd9Sstevel@tonic-gate sp->next_cl_minor = 23847c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor); 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate return (client_handle); 23877c478bd9Sstevel@tonic-gate } 23887c478bd9Sstevel@tonic-gate 23897c478bd9Sstevel@tonic-gate /* 23907c478bd9Sstevel@tonic-gate * cs_clear_superclient_lock - clears the global "super-client" lock 23917c478bd9Sstevel@tonic-gate * 23927c478bd9Sstevel@tonic-gate * Note: this function uses the cs_globals.global_lock so observe proper 23937c478bd9Sstevel@tonic-gate * nexting of locks!! 23947c478bd9Sstevel@tonic-gate */ 23957c478bd9Sstevel@tonic-gate static void 23967c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(int super_client) 23977c478bd9Sstevel@tonic-gate { 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate /* 24007c478bd9Sstevel@tonic-gate * If this was a "super-client" registering then we need 24017c478bd9Sstevel@tonic-gate * to clear the GLOBAL_SUPER_CLIENT_REGISTERED flag 24027c478bd9Sstevel@tonic-gate * so that other "super-clients" can register. 24037c478bd9Sstevel@tonic-gate */ 24047c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) { 24057c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 24067c478bd9Sstevel@tonic-gate cs_globals.flags &= ~GLOBAL_SUPER_CLIENT_REGISTERED; 24077c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 24087c478bd9Sstevel@tonic-gate } 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate 24117c478bd9Sstevel@tonic-gate /* 24127c478bd9Sstevel@tonic-gate * ==== event handling section ==== 24137c478bd9Sstevel@tonic-gate */ 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate /* 24167c478bd9Sstevel@tonic-gate * cs_event - CS event hi-priority callback handler 24177c478bd9Sstevel@tonic-gate * 24187c478bd9Sstevel@tonic-gate * This function gets called by SS and is passed the event type in 24197c478bd9Sstevel@tonic-gate * the "event" argument, and the socket number in the "sn" 24207c478bd9Sstevel@tonic-gate * argument. The "sn" argument is a valid logical socket 24217c478bd9Sstevel@tonic-gate * number for all events except the PCE_SS_READY event. 24227c478bd9Sstevel@tonic-gate * 24237c478bd9Sstevel@tonic-gate * The PCE_SS_INIT_STATE, PCE_ADD_SOCKET and PCE_DROP_SOCKET events 24247c478bd9Sstevel@tonic-gate * are never called at high priority. These events return 24257c478bd9Sstevel@tonic-gate * the following return codes: 24267c478bd9Sstevel@tonic-gate * 24277c478bd9Sstevel@tonic-gate * CS_SUCCESS - operation sucessful 24287c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to complete operation 24297c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - bad subfunction of 24307c478bd9Sstevel@tonic-gate * PCE_SS_INIT_STATE 24317c478bd9Sstevel@tonic-gate * 24327c478bd9Sstevel@tonic-gate * The caller MUST look at these return codes! 24337c478bd9Sstevel@tonic-gate * 24347c478bd9Sstevel@tonic-gate * This function is called at high-priority interrupt time for standard 24357c478bd9Sstevel@tonic-gate * Card Services events, and the only standard Card Services 24367c478bd9Sstevel@tonic-gate * event that it handles directly is the CS_EVENT_CARD_REMOVAL 24377c478bd9Sstevel@tonic-gate * event, which gets shuttled right into the client's event 24387c478bd9Sstevel@tonic-gate * handler. All other events are just queued up and the socket 24397c478bd9Sstevel@tonic-gate * event thread is woken up via the soft interrupt handler. 24407c478bd9Sstevel@tonic-gate * Note that CS_EVENT_CARD_INSERTION events are not set in the clients' 24417c478bd9Sstevel@tonic-gate * event field, since the CS card insertion/card ready processing 24427c478bd9Sstevel@tonic-gate * code is responsible for setting this event in a client's 24437c478bd9Sstevel@tonic-gate * event field. 24447c478bd9Sstevel@tonic-gate * 24457c478bd9Sstevel@tonic-gate */ 24467c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24477c478bd9Sstevel@tonic-gate uint32_t 24487c478bd9Sstevel@tonic-gate cs_event(event_t event, uint32_t sn, uint32_t arg) 24497c478bd9Sstevel@tonic-gate { 24507c478bd9Sstevel@tonic-gate client_t *client; 24517c478bd9Sstevel@tonic-gate cs_socket_t *sp; 24527c478bd9Sstevel@tonic-gate client_types_t *ct; 24537c478bd9Sstevel@tonic-gate uint32_t ret = CS_SUCCESS; 24547c478bd9Sstevel@tonic-gate 24557c478bd9Sstevel@tonic-gate /* 24567c478bd9Sstevel@tonic-gate * Handle special SS<->CS events 24577c478bd9Sstevel@tonic-gate */ 24587c478bd9Sstevel@tonic-gate switch (event) { 24597c478bd9Sstevel@tonic-gate case PCE_SS_INIT_STATE: 24607c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 24617c478bd9Sstevel@tonic-gate switch (sn) { 24627c478bd9Sstevel@tonic-gate case PCE_SS_STATE_INIT: 24637c478bd9Sstevel@tonic-gate if ((ret = cs_ss_init()) == CS_SUCCESS) 24647c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SS_READY; 24657c478bd9Sstevel@tonic-gate break; 24667c478bd9Sstevel@tonic-gate case PCE_SS_STATE_DEINIT: 24677c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SS_READY; 24687c478bd9Sstevel@tonic-gate break; 24697c478bd9Sstevel@tonic-gate default: 24707c478bd9Sstevel@tonic-gate ret = CS_UNSUPPORTED_FUNCTION; 24717c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: PCE_SS_INIT_STATE invalid " 24727c478bd9Sstevel@tonic-gate "directive: 0x%x\n", sn); 24737c478bd9Sstevel@tonic-gate break; 24747c478bd9Sstevel@tonic-gate } /* switch (sn) */ 24757c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 24767c478bd9Sstevel@tonic-gate return (ret); 24777c478bd9Sstevel@tonic-gate case PCE_ADD_SOCKET: 24787c478bd9Sstevel@tonic-gate return (cs_add_socket(sn)); 24797c478bd9Sstevel@tonic-gate case PCE_DROP_SOCKET: 24807c478bd9Sstevel@tonic-gate return (cs_drop_socket(sn)); 24817c478bd9Sstevel@tonic-gate } /* switch (event) */ 24827c478bd9Sstevel@tonic-gate 24837c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 24847c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate /* 24877c478bd9Sstevel@tonic-gate * Check to see if CS wants to unload - we do this since it's possible 24887c478bd9Sstevel@tonic-gate * to disable certain sockets. Do NOT acquire any locks yet. 24897c478bd9Sstevel@tonic-gate */ 24907c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_UNLOAD_MODULE) { 24917c478bd9Sstevel@tonic-gate if (event == PCE_CARD_INSERT) 24927c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PCMCIA: socket %d disabled - please " 24937c478bd9Sstevel@tonic-gate "remove card\n", sn); 24947c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 24987c478bd9Sstevel@tonic-gate 24997c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 25007c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 25017c478bd9Sstevel@tonic-gate event2text_t event2text; 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate event2text.event = event; 25047c478bd9Sstevel@tonic-gate (void) cs_event2text(&event2text, 0); 25057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: event=%s (x%x), socket=0x%x\n", 25067c478bd9Sstevel@tonic-gate event2text.text, (int)event, (int)sn); 25077c478bd9Sstevel@tonic-gate } 25087c478bd9Sstevel@tonic-gate #endif 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate /* 25117c478bd9Sstevel@tonic-gate * Convert SS events to CS events; handle the PRR if necessary. 25127c478bd9Sstevel@tonic-gate */ 25137c478bd9Sstevel@tonic-gate sp->events |= ss_to_cs_events(sp, event); 25147c478bd9Sstevel@tonic-gate 25157c478bd9Sstevel@tonic-gate /* 25167c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 25177c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 25187c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 25197c478bd9Sstevel@tonic-gate * notified in the correct order of any high-priority 25207c478bd9Sstevel@tonic-gate * events. 25217c478bd9Sstevel@tonic-gate */ 25227c478bd9Sstevel@tonic-gate ct = &client_types[0]; 25237c478bd9Sstevel@tonic-gate while (ct) { 25247c478bd9Sstevel@tonic-gate /* 25257c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 25267c478bd9Sstevel@tonic-gate * through each client to set up the client events as well as 25277c478bd9Sstevel@tonic-gate * call the client's event handler directly if we have a high 25287c478bd9Sstevel@tonic-gate * priority event that we need to tell the client about. 25297c478bd9Sstevel@tonic-gate */ 25307c478bd9Sstevel@tonic-gate client = sp->client_list; 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 25337c478bd9Sstevel@tonic-gate client_t *clp = NULL; 25347c478bd9Sstevel@tonic-gate 25357c478bd9Sstevel@tonic-gate while (client) { 25367c478bd9Sstevel@tonic-gate clp = client; 25377c478bd9Sstevel@tonic-gate client = client->next; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate client = clp; 25407c478bd9Sstevel@tonic-gate } 25417c478bd9Sstevel@tonic-gate 25427c478bd9Sstevel@tonic-gate while (client) { 25437c478bd9Sstevel@tonic-gate client->events |= ((sp->events & ~CS_EVENT_CARD_INSERTION) & 25447c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 25457c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 25467c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 25477c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 25487c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: socket %d client [%s] " 25497c478bd9Sstevel@tonic-gate "events 0x%x flags 0x%x\n", 25507c478bd9Sstevel@tonic-gate sn, client->driver_name, 25517c478bd9Sstevel@tonic-gate (int)client->events, 25527c478bd9Sstevel@tonic-gate (int)client->flags); 25537c478bd9Sstevel@tonic-gate } 25547c478bd9Sstevel@tonic-gate #endif 25557c478bd9Sstevel@tonic-gate 25567c478bd9Sstevel@tonic-gate /* 25577c478bd9Sstevel@tonic-gate * Handle the suspend and card removal events 25587c478bd9Sstevel@tonic-gate * specially here so that the client can receive 25597c478bd9Sstevel@tonic-gate * these events at high-priority. 25607c478bd9Sstevel@tonic-gate */ 25617c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_PM_SUSPEND) { 25627c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 25637c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, CS_EVENT_PM_SUSPEND, 25647c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 25657c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 25667c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_PM_SUSPEND; 25677c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_PM_SUSPEND) */ 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_CARD_REMOVAL) { 25707c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 25717c478bd9Sstevel@tonic-gate client->flags &= ~(CLIENT_CARD_INSERTED | 25727c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 25737c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 25747c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 25757c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 25767c478bd9Sstevel@tonic-gate /* 25777c478bd9Sstevel@tonic-gate * Check to see if the client wants low priority 25787c478bd9Sstevel@tonic-gate * removal events as well. 25797c478bd9Sstevel@tonic-gate */ 25807c478bd9Sstevel@tonic-gate if ((client->event_mask | client->global_mask) & 25817c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL_LOWP) { 25827c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CARD_REMOVAL_LOWP; 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 25857c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_CARD_REMOVAL; 25867c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 25897c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 25907c478bd9Sstevel@tonic-gate client = client->prev; 25917c478bd9Sstevel@tonic-gate } else { 25927c478bd9Sstevel@tonic-gate client = client->next; 25937c478bd9Sstevel@tonic-gate } 25947c478bd9Sstevel@tonic-gate } /* while (client) */ 25957c478bd9Sstevel@tonic-gate 25967c478bd9Sstevel@tonic-gate ct = ct->next; 25977c478bd9Sstevel@tonic-gate } /* while (ct) */ 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate /* 26007c478bd9Sstevel@tonic-gate * Set the SOCKET_NEEDS_THREAD flag so that the soft interrupt 26017c478bd9Sstevel@tonic-gate * handler will wakeup this socket's event thread. 26027c478bd9Sstevel@tonic-gate */ 26037c478bd9Sstevel@tonic-gate if (sp->events) 26047c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_NEEDS_THREAD; 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate /* 26077c478bd9Sstevel@tonic-gate * Fire off a soft interrupt that will cause the socket thread 26087c478bd9Sstevel@tonic-gate * to be woken up and any remaining events to be sent to 26097c478bd9Sstevel@tonic-gate * the clients on this socket. 26107c478bd9Sstevel@tonic-gate */ 26117c478bd9Sstevel@tonic-gate if ((sp->init_state & SOCKET_INIT_STATE_SOFTINTR) && 26127c478bd9Sstevel@tonic-gate !(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) 26137c478bd9Sstevel@tonic-gate ddi_trigger_softintr(sp->softint_id); 26147c478bd9Sstevel@tonic-gate 26157c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 26187c478bd9Sstevel@tonic-gate } 26197c478bd9Sstevel@tonic-gate 26207c478bd9Sstevel@tonic-gate /* 26217c478bd9Sstevel@tonic-gate * cs_card_insertion - handle card insertion and card ready events 26227c478bd9Sstevel@tonic-gate * 26237c478bd9Sstevel@tonic-gate * We read the CIS, if present, and store it away, then tell SS that 26247c478bd9Sstevel@tonic-gate * we have read the CIS and it's ready to be parsed. Since card 26257c478bd9Sstevel@tonic-gate * insertion and card ready events are pretty closely intertwined, 26267c478bd9Sstevel@tonic-gate * we handle both here. For card ready events that are not the 26277c478bd9Sstevel@tonic-gate * result of a card insertion event, we expect that the caller has 26287c478bd9Sstevel@tonic-gate * already done the appropriate processing and that we will not be 26297c478bd9Sstevel@tonic-gate * called unless we received a card ready event right after a card 26307c478bd9Sstevel@tonic-gate * insertion event, i.e. that the SOCKET_WAIT_FOR_READY flag in 26317c478bd9Sstevel@tonic-gate * sp->thread_state was set or if we get a CARD_READY event right 26327c478bd9Sstevel@tonic-gate * after a CARD_INSERTION event. 26337c478bd9Sstevel@tonic-gate * 26347c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 26357c478bd9Sstevel@tonic-gate * event - event to handle, one of: 26367c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_INSERTION 26377c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_READY 26387c478bd9Sstevel@tonic-gate * CS_EVENT_SS_UPDATED 26397c478bd9Sstevel@tonic-gate */ 26407c478bd9Sstevel@tonic-gate static int 26417c478bd9Sstevel@tonic-gate cs_card_insertion(cs_socket_t *sp, event_t event) 26427c478bd9Sstevel@tonic-gate { 26437c478bd9Sstevel@tonic-gate int ret; 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate /* 26467c478bd9Sstevel@tonic-gate * Since we're only called while waiting for the card insertion 26477c478bd9Sstevel@tonic-gate * and card ready sequence to occur, we may have a pending 26487c478bd9Sstevel@tonic-gate * card ready timer that hasn't gone off yet if we got a 26497c478bd9Sstevel@tonic-gate * real card ready event. 26507c478bd9Sstevel@tonic-gate */ 26517c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 26527c478bd9Sstevel@tonic-gate 26537c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 26547c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 26557c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: event=0x%x, socket=0x%x\n", 26567c478bd9Sstevel@tonic-gate (int)event, sp->socket_num); 26577c478bd9Sstevel@tonic-gate } 26587c478bd9Sstevel@tonic-gate #endif 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate /* 26617c478bd9Sstevel@tonic-gate * Handle card insertion processing 26627c478bd9Sstevel@tonic-gate */ 26637c478bd9Sstevel@tonic-gate if (event & CS_EVENT_CARD_INSERTION) { 26647c478bd9Sstevel@tonic-gate set_socket_t set_socket; 26657c478bd9Sstevel@tonic-gate get_ss_status_t gs; 26667c478bd9Sstevel@tonic-gate 26677c478bd9Sstevel@tonic-gate /* 26687c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 26697c478bd9Sstevel@tonic-gate */ 26707c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 26717c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 26727c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d has no " 26737c478bd9Sstevel@tonic-gate "CIS window\n", 26747c478bd9Sstevel@tonic-gate sp->socket_num); 26757c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate /* 26797c478bd9Sstevel@tonic-gate * Apply power to the socket, enable card detect and card ready 26807c478bd9Sstevel@tonic-gate * events, then reset the socket. 26817c478bd9Sstevel@tonic-gate */ 26827c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 26837c478bd9Sstevel@tonic-gate sp->event_mask = (CS_EVENT_CARD_REMOVAL | 26847c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY); 26857c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 26867c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 26877c478bd9Sstevel@tonic-gate set_socket.SCIntMask = (SBM_CD | SBM_RDYBSY); 26887c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 26897c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 26907c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 26917c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VCC, 26947c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 26957c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP1, 26967c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 26977c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP2, 26987c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 26997c478bd9Sstevel@tonic-gate 27007c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 27017c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 27027c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failure %d\n", 27037c478bd9Sstevel@tonic-gate sp->socket_num, ret); 27047c478bd9Sstevel@tonic-gate return (ret); 27057c478bd9Sstevel@tonic-gate } 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate /* 27087c478bd9Sstevel@tonic-gate * Clear the ready and ready_timeout events since they are now 27097c478bd9Sstevel@tonic-gate * bogus since we're about to reset the socket. 27107c478bd9Sstevel@tonic-gate * XXX - should these be cleared right after the RESET?? 27117c478bd9Sstevel@tonic-gate */ 27127c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27137c478bd9Sstevel@tonic-gate 27147c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 27157c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 27167c478bd9Sstevel@tonic-gate 27177c478bd9Sstevel@tonic-gate SocketServices(SS_ResetSocket, sp->socket_num, 27187c478bd9Sstevel@tonic-gate RESET_MODE_CARD_ONLY); 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate /* 27217c478bd9Sstevel@tonic-gate * We are required by the PCMCIA spec to wait some number of 27227c478bd9Sstevel@tonic-gate * milliseconds after reset before we access the card, so 27237c478bd9Sstevel@tonic-gate * we set up a timer here that will wake us up and allow us 27247c478bd9Sstevel@tonic-gate * to continue with our card initialization. 27257c478bd9Sstevel@tonic-gate */ 27267c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27277c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_RESET_TIMER; 27287c478bd9Sstevel@tonic-gate (void) timeout(cs_ready_timeout, sp, 27297c478bd9Sstevel@tonic-gate drv_usectohz(cs_reset_timeout_time * 1000)); 27307c478bd9Sstevel@tonic-gate cv_wait(&sp->reset_cv, &sp->lock); 27317c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_RESET_TIMER; 27327c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 27337c478bd9Sstevel@tonic-gate 27347c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27357c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 27367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d out of RESET " 27377c478bd9Sstevel@tonic-gate "for %d mS sp->events 0x%x\n", 27387c478bd9Sstevel@tonic-gate sp->socket_num, cs_reset_timeout_time, (int)sp->events); 27397c478bd9Sstevel@tonic-gate } 27407c478bd9Sstevel@tonic-gate #endif 27417c478bd9Sstevel@tonic-gate 27427c478bd9Sstevel@tonic-gate /* 27437c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 27447c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 27457c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 27467c478bd9Sstevel@tonic-gate */ 27477c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 27487c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27497c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 27507c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d " 27517c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 27527c478bd9Sstevel@tonic-gate "terminating insertion " 27537c478bd9Sstevel@tonic-gate "processing\n", 27547c478bd9Sstevel@tonic-gate sp->socket_num); 27557c478bd9Sstevel@tonic-gate } 27567c478bd9Sstevel@tonic-gate #endif 27577c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 27587c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate /* 27617c478bd9Sstevel@tonic-gate * If we got a card ready event after the reset, then don't 27627c478bd9Sstevel@tonic-gate * bother setting up a card ready timer, since we'll blast 27637c478bd9Sstevel@tonic-gate * right on through to the card ready processing. 27647c478bd9Sstevel@tonic-gate * Get the current card status to see if it's ready; if it 27657c478bd9Sstevel@tonic-gate * is, we probably won't get a card ready event. 27667c478bd9Sstevel@tonic-gate */ 27677c478bd9Sstevel@tonic-gate gs.socket = sp->socket_num; 27687c478bd9Sstevel@tonic-gate gs.CardState = 0; 27697c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_GetStatus, &gs)) != SUCCESS) { 27707c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 27717c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetStatus failure %d\n", 27727c478bd9Sstevel@tonic-gate sp->socket_num, ret); 27737c478bd9Sstevel@tonic-gate return (ret); 27747c478bd9Sstevel@tonic-gate } 27757c478bd9Sstevel@tonic-gate 27767c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27777c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_READY) || 27787c478bd9Sstevel@tonic-gate (gs.CardState & SBM_RDYBSY)) { 27797c478bd9Sstevel@tonic-gate event = CS_EVENT_CARD_READY; 27807c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27817c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 27827c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d card " 27837c478bd9Sstevel@tonic-gate "READY\n", sp->socket_num); 27847c478bd9Sstevel@tonic-gate } 27857c478bd9Sstevel@tonic-gate #endif 27867c478bd9Sstevel@tonic-gate 27877c478bd9Sstevel@tonic-gate } else { 27887c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27897c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 27907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d setting " 27917c478bd9Sstevel@tonic-gate "READY timer\n", sp->socket_num); 27927c478bd9Sstevel@tonic-gate } 27937c478bd9Sstevel@tonic-gate #endif 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate sp->rdybsy_tmo_id = timeout(cs_ready_timeout, sp, 27967c478bd9Sstevel@tonic-gate READY_TIMEOUT_TIME); 27977c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_FOR_READY; 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 28027c478bd9Sstevel@tonic-gate 28037c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 28047c478bd9Sstevel@tonic-gate 28057c478bd9Sstevel@tonic-gate /* 28067c478bd9Sstevel@tonic-gate * Handle card ready processing. This is only card ready processing 28077c478bd9Sstevel@tonic-gate * for card ready events in conjunction with a card insertion. 28087c478bd9Sstevel@tonic-gate */ 28097c478bd9Sstevel@tonic-gate if (event == CS_EVENT_CARD_READY) { 28107c478bd9Sstevel@tonic-gate get_socket_t get_socket; 28117c478bd9Sstevel@tonic-gate set_socket_t set_socket; 28127c478bd9Sstevel@tonic-gate 28137c478bd9Sstevel@tonic-gate /* 28147c478bd9Sstevel@tonic-gate * The only events that we want to see now are card removal 28157c478bd9Sstevel@tonic-gate * events. 28167c478bd9Sstevel@tonic-gate */ 28177c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 28187c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_REMOVAL; 28197c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 28207c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 28217c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 28227c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 28237c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetSocket failed\n", 28247c478bd9Sstevel@tonic-gate sp->socket_num); 28257c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 28267c478bd9Sstevel@tonic-gate } 28277c478bd9Sstevel@tonic-gate 28287c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 28297c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 28307c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 28317c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 28327c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 28337c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 28347c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 28357c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 28367c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) to reset latched values */ 28377c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 28387c478bd9Sstevel@tonic-gate 28397c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 28407c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 28417c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failed\n", 28427c478bd9Sstevel@tonic-gate sp->socket_num); 28437c478bd9Sstevel@tonic-gate 28447c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 28457c478bd9Sstevel@tonic-gate } 28467c478bd9Sstevel@tonic-gate 28477c478bd9Sstevel@tonic-gate /* 28487c478bd9Sstevel@tonic-gate * Grab the cis_lock mutex to protect the CIS-to-be and 28497c478bd9Sstevel@tonic-gate * the CIS window, then fire off the CIS parser to 28507c478bd9Sstevel@tonic-gate * create a local copy of the card's CIS. 28517c478bd9Sstevel@tonic-gate */ 28527c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 28537c478bd9Sstevel@tonic-gate 28547c478bd9Sstevel@tonic-gate if ((ret = cs_create_cis(sp)) != CS_SUCCESS) { 28557c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28567c478bd9Sstevel@tonic-gate return (ret); 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate 28597c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28607c478bd9Sstevel@tonic-gate 28617c478bd9Sstevel@tonic-gate /* 28627c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 28637c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 28647c478bd9Sstevel@tonic-gate * insertion, so destroy the CIS and terminate this 28657c478bd9Sstevel@tonic-gate * processing. We'll get called back to handle the 28667c478bd9Sstevel@tonic-gate * insertion again later. 28677c478bd9Sstevel@tonic-gate */ 28687c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 28697c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 28707c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 28717c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28727c478bd9Sstevel@tonic-gate } else { 28737c478bd9Sstevel@tonic-gate /* 28747c478bd9Sstevel@tonic-gate * Schedule the call to the Socket Services work thread. 28757c478bd9Sstevel@tonic-gate */ 28767c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 28777c478bd9Sstevel@tonic-gate sp->ss_thread_state |= SOCKET_THREAD_CSCISInit; 28787c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 28797c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 28807c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 28817c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 28827c478bd9Sstevel@tonic-gate 28837c478bd9Sstevel@tonic-gate /* 28847c478bd9Sstevel@tonic-gate * Socket Services has parsed the CIS and has done any other 28857c478bd9Sstevel@tonic-gate * work to get the client driver loaded and attached if 28867c478bd9Sstevel@tonic-gate * necessary, so setup the per-client state. 28877c478bd9Sstevel@tonic-gate */ 28887c478bd9Sstevel@tonic-gate if (event == CS_EVENT_SS_UPDATED) { 28897c478bd9Sstevel@tonic-gate client_t *client; 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate /* 28927c478bd9Sstevel@tonic-gate * Now that we and SS are done handling the card insertion 28937c478bd9Sstevel@tonic-gate * semantics, go through each client on this socket and set 28947c478bd9Sstevel@tonic-gate * the CS_EVENT_CARD_INSERTION event in each client's event 28957c478bd9Sstevel@tonic-gate * field. We do this here instead of in cs_event so that 28967c478bd9Sstevel@tonic-gate * when a client gets a CS_EVENT_CARD_INSERTION event, the 28977c478bd9Sstevel@tonic-gate * card insertion and ready processing has already been done 28987c478bd9Sstevel@tonic-gate * and SocketServices has had a chance to create a dip for 28997c478bd9Sstevel@tonic-gate * the card in this socket. 29007c478bd9Sstevel@tonic-gate */ 29017c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 29027c478bd9Sstevel@tonic-gate client = sp->client_list; 29037c478bd9Sstevel@tonic-gate while (client) { 29047c478bd9Sstevel@tonic-gate client->events |= (CS_EVENT_CARD_INSERTION & 29057c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 29067c478bd9Sstevel@tonic-gate client = client->next; 29077c478bd9Sstevel@tonic-gate } /* while (client) */ 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 29147c478bd9Sstevel@tonic-gate } 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate /* 29177c478bd9Sstevel@tonic-gate * cs_card_removal - handle card removal events 29187c478bd9Sstevel@tonic-gate * 29197c478bd9Sstevel@tonic-gate * Destroy the CIS. 29207c478bd9Sstevel@tonic-gate * 29217c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 29227c478bd9Sstevel@tonic-gate * 29237c478bd9Sstevel@tonic-gate */ 29247c478bd9Sstevel@tonic-gate static int 29257c478bd9Sstevel@tonic-gate cs_card_removal(cs_socket_t *sp) 29267c478bd9Sstevel@tonic-gate { 29277c478bd9Sstevel@tonic-gate set_socket_t set_socket; 29287c478bd9Sstevel@tonic-gate int ret; 29297c478bd9Sstevel@tonic-gate 29307c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29317c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 29327c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d\n", sp->socket_num); 29337c478bd9Sstevel@tonic-gate } 29347c478bd9Sstevel@tonic-gate #endif 29357c478bd9Sstevel@tonic-gate 29367c478bd9Sstevel@tonic-gate /* 29377c478bd9Sstevel@tonic-gate * Remove any pending card ready timer 29387c478bd9Sstevel@tonic-gate */ 29397c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 29407c478bd9Sstevel@tonic-gate 29417c478bd9Sstevel@tonic-gate /* 29427c478bd9Sstevel@tonic-gate * Clear various flags so that everyone else knows that there's 29437c478bd9Sstevel@tonic-gate * nothing on this socket anymore. Note that we clear the 29447c478bd9Sstevel@tonic-gate * SOCKET_CARD_INSERTED and SOCKET_IS_IO flags in the 29457c478bd9Sstevel@tonic-gate * ss_to_cs_events event mapping function. 29467c478bd9Sstevel@tonic-gate */ 29477c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 29487c478bd9Sstevel@tonic-gate sp->thread_state &= ~(SOCKET_WAIT_FOR_READY | SOCKET_RESET_TIMER); 29497c478bd9Sstevel@tonic-gate 29507c478bd9Sstevel@tonic-gate /* 29517c478bd9Sstevel@tonic-gate * Turn off socket power and set the socket back to memory mode. 29527c478bd9Sstevel@tonic-gate * Disable all socket events except for CARD_INSERTION events. 29537c478bd9Sstevel@tonic-gate */ 29547c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 29557c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 29567c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 29577c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 29587c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 29597c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 29607c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 29617c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 29627c478bd9Sstevel@tonic-gate 29637c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 29647c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 29657c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 29667c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 29677c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 29687c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 29697c478bd9Sstevel@tonic-gate 29707c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 29717c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 29727c478bd9Sstevel@tonic-gate "cs_card_removal: socket %d SS_SetSocket failure %d\n", 29737c478bd9Sstevel@tonic-gate sp->socket_num, ret); 29747c478bd9Sstevel@tonic-gate return (ret); 29757c478bd9Sstevel@tonic-gate } 29767c478bd9Sstevel@tonic-gate 29777c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29787c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 29797c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d " 29807c478bd9Sstevel@tonic-gate "calling cs_destroy_cis\n", 29817c478bd9Sstevel@tonic-gate sp->socket_num); 29827c478bd9Sstevel@tonic-gate } 29837c478bd9Sstevel@tonic-gate #endif 29847c478bd9Sstevel@tonic-gate 29857c478bd9Sstevel@tonic-gate /* 29867c478bd9Sstevel@tonic-gate * Destroy the CIS and tell Socket Services that we're done 29877c478bd9Sstevel@tonic-gate * handling the card removal event. 29887c478bd9Sstevel@tonic-gate */ 29897c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 29907c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 29917c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 29927c478bd9Sstevel@tonic-gate 29937c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29947c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 29957c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: calling CSCardRemoved\n"); 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate #endif 29987c478bd9Sstevel@tonic-gate 29997c478bd9Sstevel@tonic-gate SocketServices(CSCardRemoved, sp->socket_num); 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 30027c478bd9Sstevel@tonic-gate } 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate /* 30057c478bd9Sstevel@tonic-gate * ss_to_cs_events - convert Socket Services events to Card Services event 30067c478bd9Sstevel@tonic-gate * masks; this function will not read the PRR if the 30077c478bd9Sstevel@tonic-gate * socket is in IO mode; this happens in cs_event_thread 30087c478bd9Sstevel@tonic-gate * 30097c478bd9Sstevel@tonic-gate * This function returns a bit mask of events. 30107c478bd9Sstevel@tonic-gate * 30117c478bd9Sstevel@tonic-gate * Note that we do some simple hysterious on card insertion and card removal 30127c478bd9Sstevel@tonic-gate * events to prevent spurious insertion and removal events from being 30137c478bd9Sstevel@tonic-gate * propogated down the chain. 30147c478bd9Sstevel@tonic-gate */ 30157c478bd9Sstevel@tonic-gate static event_t 30167c478bd9Sstevel@tonic-gate ss_to_cs_events(cs_socket_t *sp, event_t event) 30177c478bd9Sstevel@tonic-gate { 30187c478bd9Sstevel@tonic-gate event_t revent = 0; 30197c478bd9Sstevel@tonic-gate 30207c478bd9Sstevel@tonic-gate switch (event) { 30217c478bd9Sstevel@tonic-gate case PCE_CARD_STATUS_CHANGE: 30227c478bd9Sstevel@tonic-gate revent |= CS_EVENT_STATUS_CHANGE; 30237c478bd9Sstevel@tonic-gate break; 30247c478bd9Sstevel@tonic-gate case PCE_CARD_REMOVAL: 30257c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) { 30267c478bd9Sstevel@tonic-gate sp->flags &= ~(SOCKET_CARD_INSERTED | SOCKET_IS_IO); 30277c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_REMOVAL; 30287c478bd9Sstevel@tonic-gate /* 30297c478bd9Sstevel@tonic-gate * If we're processing a removal event, it makes 30307c478bd9Sstevel@tonic-gate * no sense to keep any insertion or ready events, 30317c478bd9Sstevel@tonic-gate * so nuke them here. This will not clear any 30327c478bd9Sstevel@tonic-gate * insertion events in the per-client event field. 30337c478bd9Sstevel@tonic-gate */ 30347c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_INSERTION | 30357c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY | 30367c478bd9Sstevel@tonic-gate CS_EVENT_READY_TIMEOUT); 30377c478bd9Sstevel@tonic-gate 30387c478bd9Sstevel@tonic-gate /* 30397c478bd9Sstevel@tonic-gate * We also don't need to wait for READY anymore since 30407c478bd9Sstevel@tonic-gate * it probably won't show up, or if it does, it will 30417c478bd9Sstevel@tonic-gate * be a bogus READY event as the card is sliding out 30427c478bd9Sstevel@tonic-gate * of the socket. Since we never do a cv_wait on the 30437c478bd9Sstevel@tonic-gate * card ready timer, it's OK for that timer to either 30447c478bd9Sstevel@tonic-gate * never go off (via an UNTIMEOUT in cs_card_removal) 30457c478bd9Sstevel@tonic-gate * or to go off but not do a cv_broadcast (since the 30467c478bd9Sstevel@tonic-gate * SOCKET_WAIT_FOR_READY flag is cleared here). 30477c478bd9Sstevel@tonic-gate */ 30487c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 30497c478bd9Sstevel@tonic-gate 30507c478bd9Sstevel@tonic-gate } 30517c478bd9Sstevel@tonic-gate break; 30527c478bd9Sstevel@tonic-gate case PCE_CARD_INSERT: 30537c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 30547c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_CARD_INSERTED; 30557c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_INSERTION; 30567c478bd9Sstevel@tonic-gate } 30577c478bd9Sstevel@tonic-gate break; 30587c478bd9Sstevel@tonic-gate case PCE_CARD_READY: 30597c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30607c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_READY; 30617c478bd9Sstevel@tonic-gate break; 30627c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_WARN: 30637c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30647c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_LOW; 30657c478bd9Sstevel@tonic-gate break; 30667c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_DEAD: 30677c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30687c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_DEAD; 30697c478bd9Sstevel@tonic-gate break; 30707c478bd9Sstevel@tonic-gate case PCE_CARD_WRITE_PROTECT: 30717c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30727c478bd9Sstevel@tonic-gate revent |= CS_EVENT_WRITE_PROTECT; 30737c478bd9Sstevel@tonic-gate break; 30747c478bd9Sstevel@tonic-gate case PCE_PM_RESUME: 30757c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_RESUME; 30767c478bd9Sstevel@tonic-gate break; 30777c478bd9Sstevel@tonic-gate case PCE_PM_SUSPEND: 30787c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_SUSPEND; 30797c478bd9Sstevel@tonic-gate break; 30807c478bd9Sstevel@tonic-gate default: 30817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ss_to_cs_events: unknown event 0x%x\n", 30827c478bd9Sstevel@tonic-gate (int)event); 30837c478bd9Sstevel@tonic-gate break; 30847c478bd9Sstevel@tonic-gate } /* switch(event) */ 30857c478bd9Sstevel@tonic-gate 30867c478bd9Sstevel@tonic-gate return (revent); 30877c478bd9Sstevel@tonic-gate } 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate /* 30907c478bd9Sstevel@tonic-gate * cs_ready_timeout - general purpose READY/BUSY and RESET timer 30917c478bd9Sstevel@tonic-gate * 30927c478bd9Sstevel@tonic-gate * Note that we really only expect one of the two events to be asserted when 30937c478bd9Sstevel@tonic-gate * we are called. XXX - Perhaps this might be a problem later on?? 30947c478bd9Sstevel@tonic-gate * 30957c478bd9Sstevel@tonic-gate * There is also the problem of cv_broadcast dropping the interrupt 30967c478bd9Sstevel@tonic-gate * priority, even though we have our high-priority mutex held. If 30977c478bd9Sstevel@tonic-gate * we hold our high-priority mutex (sp->lock) over a cv_broadcast, and 30987c478bd9Sstevel@tonic-gate * we get a high-priority interrupt during this time, the system will 30997c478bd9Sstevel@tonic-gate * deadlock or panic. Thanks to Andy Banta for finding this out in 31007c478bd9Sstevel@tonic-gate * the SPC/S (stc.c) driver. 31017c478bd9Sstevel@tonic-gate * 31027c478bd9Sstevel@tonic-gate * This callback routine can not grab the sp->client_lock mutex or deadlock 31037c478bd9Sstevel@tonic-gate * will result. 31047c478bd9Sstevel@tonic-gate */ 31057c478bd9Sstevel@tonic-gate void 31067c478bd9Sstevel@tonic-gate cs_ready_timeout(void *arg) 31077c478bd9Sstevel@tonic-gate { 31087c478bd9Sstevel@tonic-gate cs_socket_t *sp = arg; 31097c478bd9Sstevel@tonic-gate kcondvar_t *cvp = NULL; 31107c478bd9Sstevel@tonic-gate 31117c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 31127c478bd9Sstevel@tonic-gate 31137c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_RESET_TIMER) { 31147c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 31157c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 31167c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_RESET_TIMER socket %d\n", 31177c478bd9Sstevel@tonic-gate sp->socket_num); 31187c478bd9Sstevel@tonic-gate } 31197c478bd9Sstevel@tonic-gate #endif 31207c478bd9Sstevel@tonic-gate 31217c478bd9Sstevel@tonic-gate cvp = &sp->reset_cv; 31227c478bd9Sstevel@tonic-gate } 31237c478bd9Sstevel@tonic-gate 31247c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 31257c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_READY_TIMEOUT; 31267c478bd9Sstevel@tonic-gate cvp = &sp->thread_cv; 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 31297c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 31307c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_WAIT_FOR_READY " 31317c478bd9Sstevel@tonic-gate "socket %d\n", sp->socket_num); 31327c478bd9Sstevel@tonic-gate } 31337c478bd9Sstevel@tonic-gate #endif 31347c478bd9Sstevel@tonic-gate 31357c478bd9Sstevel@tonic-gate } 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 31387c478bd9Sstevel@tonic-gate 31397c478bd9Sstevel@tonic-gate if (cvp) 31407c478bd9Sstevel@tonic-gate cv_broadcast(cvp); 31417c478bd9Sstevel@tonic-gate } 31427c478bd9Sstevel@tonic-gate 31437c478bd9Sstevel@tonic-gate /* 31447c478bd9Sstevel@tonic-gate * cs_event_softintr_timeout - wrapper function to call cs_socket_event_softintr 31457c478bd9Sstevel@tonic-gate */ 31467c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31477c478bd9Sstevel@tonic-gate void 31487c478bd9Sstevel@tonic-gate cs_event_softintr_timeout(void *arg) 31497c478bd9Sstevel@tonic-gate { 31507c478bd9Sstevel@tonic-gate 31517c478bd9Sstevel@tonic-gate /* 31527c478bd9Sstevel@tonic-gate * If we're trying to unload this module, then don't do 31537c478bd9Sstevel@tonic-gate * anything but exit. 31547c478bd9Sstevel@tonic-gate * We acquire the cs_globals.global_lock mutex here so that 31557c478bd9Sstevel@tonic-gate * we can correctly synchronize with cs_deinit when it 31567c478bd9Sstevel@tonic-gate * is telling us to shut down. XXX - is this bogus?? 31577c478bd9Sstevel@tonic-gate */ 31587c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 31597c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) { 31607c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31617c478bd9Sstevel@tonic-gate (void) cs_socket_event_softintr(NULL); 31627c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 31637c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 31647c478bd9Sstevel@tonic-gate } else { 31657c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31667c478bd9Sstevel@tonic-gate } 31677c478bd9Sstevel@tonic-gate } 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate /* 31707c478bd9Sstevel@tonic-gate * cs_socket_event_softintr - This function just does a cv_broadcast on behalf 31717c478bd9Sstevel@tonic-gate * of the high-priority interrupt handler. 31727c478bd9Sstevel@tonic-gate * 31737c478bd9Sstevel@tonic-gate * Note: There is no calling argument. 31747c478bd9Sstevel@tonic-gate */ 31757c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 31767c478bd9Sstevel@tonic-gate uint32_t 31777c478bd9Sstevel@tonic-gate cs_socket_event_softintr(caddr_t notused) 31787c478bd9Sstevel@tonic-gate { 31797c478bd9Sstevel@tonic-gate cs_socket_t *sp; 31807c478bd9Sstevel@tonic-gate uint32_t sn; 31817c478bd9Sstevel@tonic-gate int ret = DDI_INTR_UNCLAIMED; 31827c478bd9Sstevel@tonic-gate 31837c478bd9Sstevel@tonic-gate /* 31847c478bd9Sstevel@tonic-gate * If the module is on it's way out, then don't bother 31857c478bd9Sstevel@tonic-gate * to do anything else except return. 31867c478bd9Sstevel@tonic-gate */ 31877c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 31887c478bd9Sstevel@tonic-gate if ((cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING) || 31897c478bd9Sstevel@tonic-gate (cs_globals.init_state & GLOBAL_IN_SOFTINTR)) { 31907c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31917c478bd9Sstevel@tonic-gate 31927c478bd9Sstevel@tonic-gate /* 31937c478bd9Sstevel@tonic-gate * Note that we return DDI_INTR_UNCLAIMED here 31947c478bd9Sstevel@tonic-gate * since we don't want to be constantly 31957c478bd9Sstevel@tonic-gate * called back. 31967c478bd9Sstevel@tonic-gate */ 31977c478bd9Sstevel@tonic-gate return (ret); 31987c478bd9Sstevel@tonic-gate } else { 31997c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_IN_SOFTINTR; 32007c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 32017c478bd9Sstevel@tonic-gate } 32027c478bd9Sstevel@tonic-gate 32037c478bd9Sstevel@tonic-gate /* 32047c478bd9Sstevel@tonic-gate * Go through each socket and dispatch the appropriate events. 32057c478bd9Sstevel@tonic-gate * We have to funnel everything through this one routine because 32067c478bd9Sstevel@tonic-gate * we can't do a cv_broadcast from a high level interrupt handler 32077c478bd9Sstevel@tonic-gate * and we also can't have more than one soft interrupt handler 32087c478bd9Sstevel@tonic-gate * on a single dip and using the same handler address. 32097c478bd9Sstevel@tonic-gate */ 32107c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 32117c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 32127c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_READY) { 32137c478bd9Sstevel@tonic-gate /* 32147c478bd9Sstevel@tonic-gate * If we're being asked to unload CS, then don't bother 32157c478bd9Sstevel@tonic-gate * waking up the socket event thread handler. 32167c478bd9Sstevel@tonic-gate */ 32177c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_UNLOAD_MODULE) && 32187c478bd9Sstevel@tonic-gate (sp->flags & SOCKET_NEEDS_THREAD)) { 32197c478bd9Sstevel@tonic-gate ret = DDI_INTR_CLAIMED; 32207c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 32217c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 32227c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 32237c478bd9Sstevel@tonic-gate } /* if (SOCKET_NEEDS_THREAD) */ 32247c478bd9Sstevel@tonic-gate } /* if (SOCKET_INIT_STATE_READY) */ 32257c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 32267c478bd9Sstevel@tonic-gate } /* for (sn) */ 32277c478bd9Sstevel@tonic-gate 32287c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 32297c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_IN_SOFTINTR; 32307c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 32317c478bd9Sstevel@tonic-gate 32327c478bd9Sstevel@tonic-gate return (ret); 32337c478bd9Sstevel@tonic-gate } 32347c478bd9Sstevel@tonic-gate 32357c478bd9Sstevel@tonic-gate /* 32367c478bd9Sstevel@tonic-gate * cs_event_thread - This is the per-socket event thread. 32377c478bd9Sstevel@tonic-gate */ 32387c478bd9Sstevel@tonic-gate static void 32397c478bd9Sstevel@tonic-gate cs_event_thread(uint32_t sn) 32407c478bd9Sstevel@tonic-gate { 32417c478bd9Sstevel@tonic-gate cs_socket_t *sp; 32427c478bd9Sstevel@tonic-gate client_t *client; 32437c478bd9Sstevel@tonic-gate client_types_t *ct; 32447c478bd9Sstevel@tonic-gate 32457c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 32467c478bd9Sstevel@tonic-gate return; 32477c478bd9Sstevel@tonic-gate 32487c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32497c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32507c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d thread started\n", 32517c478bd9Sstevel@tonic-gate sp->socket_num); 32527c478bd9Sstevel@tonic-gate } 32537c478bd9Sstevel@tonic-gate #endif 32547c478bd9Sstevel@tonic-gate 32557c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_cs, &sp->client_lock, 32567c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_event_thread"); 32577c478bd9Sstevel@tonic-gate 32587c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 32597c478bd9Sstevel@tonic-gate 32607c478bd9Sstevel@tonic-gate for (;;) { 32617c478bd9Sstevel@tonic-gate 32627c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_cs); 32637c478bd9Sstevel@tonic-gate cv_wait(&sp->thread_cv, &sp->client_lock); 32647c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_cs, &sp->client_lock); 32657c478bd9Sstevel@tonic-gate 32667c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 32677c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_NEEDS_THREAD; 32687c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate /* 32717c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations that 32727c478bd9Sstevel@tonic-gate * we are being asked to perform. 32737c478bd9Sstevel@tonic-gate */ 32747c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_THREAD_EXIT) { 32757c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32767c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32777c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 32787c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 32797c478bd9Sstevel@tonic-gate sp->socket_num); 32807c478bd9Sstevel@tonic-gate } 32817c478bd9Sstevel@tonic-gate #endif 32827c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_cs); 32837c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); /* wakes up cs_deinit */ 32847c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 32857c478bd9Sstevel@tonic-gate return; 32867c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 32877c478bd9Sstevel@tonic-gate 32887c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32897c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d sp->events 0x%x\n", 32917c478bd9Sstevel@tonic-gate sp->socket_num, 32927c478bd9Sstevel@tonic-gate (int)sp->events); 32937c478bd9Sstevel@tonic-gate } 32947c478bd9Sstevel@tonic-gate #endif 32957c478bd9Sstevel@tonic-gate 32967c478bd9Sstevel@tonic-gate /* 32977c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_INSERTION events 32987c478bd9Sstevel@tonic-gate */ 32997c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_INSERTION) { 33007c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33017c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_INSERTION; 33027c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33037c478bd9Sstevel@tonic-gate 33047c478bd9Sstevel@tonic-gate /* 33057c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 33067c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 33077c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 33087c478bd9Sstevel@tonic-gate */ 33097c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_REMOVAL) == 0) { 33107c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_INSERTION); 33117c478bd9Sstevel@tonic-gate } 33127c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 33137c478bd9Sstevel@tonic-gate else if (cs_debug > 0) { 33147c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 33157c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 33167c478bd9Sstevel@tonic-gate "terminating " 33177c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_INSERTION " 33187c478bd9Sstevel@tonic-gate "processing\n", sp->socket_num); 33197c478bd9Sstevel@tonic-gate } 33207c478bd9Sstevel@tonic-gate #endif 33217c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 33227c478bd9Sstevel@tonic-gate 33237c478bd9Sstevel@tonic-gate /* 33247c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_READY and CS_EVENT_READY_TIMEOUT events 33257c478bd9Sstevel@tonic-gate */ 33267c478bd9Sstevel@tonic-gate if (sp->events & (CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT)) { 33277c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33287c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 33297c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33307c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 33317c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33327c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 33337c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33347c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_READY); 33357c478bd9Sstevel@tonic-gate } /* if (SOCKET_WAIT_FOR_READY) */ 33367c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 33377c478bd9Sstevel@tonic-gate 33387c478bd9Sstevel@tonic-gate /* 33397c478bd9Sstevel@tonic-gate * Handle CS_EVENT_SS_UPDATED events 33407c478bd9Sstevel@tonic-gate */ 33417c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_SS_UPDATED) { 33427c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33437c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_SS_UPDATED; 33447c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33457c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_SS_UPDATED); 33467c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 33477c478bd9Sstevel@tonic-gate 33487c478bd9Sstevel@tonic-gate /* 33497c478bd9Sstevel@tonic-gate * Handle CS_EVENT_STATUS_CHANGE events 33507c478bd9Sstevel@tonic-gate */ 33517c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_STATUS_CHANGE) { 33527c478bd9Sstevel@tonic-gate event_t revent; 33537c478bd9Sstevel@tonic-gate 33547c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 33557c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33567c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_STATUS_CHANGE; 33577c478bd9Sstevel@tonic-gate 33587c478bd9Sstevel@tonic-gate /* 33597c478bd9Sstevel@tonic-gate * Go through each client and add any events that we saw to 33607c478bd9Sstevel@tonic-gate * the client's event list if the client has that event 33617c478bd9Sstevel@tonic-gate * enabled in their event mask. 33627c478bd9Sstevel@tonic-gate * Remove any events that may be pending for this client if 33637c478bd9Sstevel@tonic-gate * the client's event mask says that the client doesn't 33647c478bd9Sstevel@tonic-gate * want to see those events anymore. This handles the 33657c478bd9Sstevel@tonic-gate * case where the client had an event enabled in it's 33667c478bd9Sstevel@tonic-gate * event mask when the event came in but between that 33677c478bd9Sstevel@tonic-gate * time and the time we're called here the client 33687c478bd9Sstevel@tonic-gate * disabled that event. 33697c478bd9Sstevel@tonic-gate */ 33707c478bd9Sstevel@tonic-gate client = sp->client_list; 33717c478bd9Sstevel@tonic-gate 33727c478bd9Sstevel@tonic-gate while (client) { 33737c478bd9Sstevel@tonic-gate /* 33747c478bd9Sstevel@tonic-gate * Read the PRR (if it exists) and check for any events. 33757c478bd9Sstevel@tonic-gate * The PRR will only be read if the socket is in IO 33767c478bd9Sstevel@tonic-gate * mode, if there is a card in the socket, and if there 33777c478bd9Sstevel@tonic-gate * is a PRR. 33787c478bd9Sstevel@tonic-gate * We don't have to clear revent before we call the 33797c478bd9Sstevel@tonic-gate * cs_read_event_status function since it will 33807c478bd9Sstevel@tonic-gate * clear it before adding any current events. 33817c478bd9Sstevel@tonic-gate */ 33827c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 33837c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 33847c478bd9Sstevel@tonic-gate &revent, NULL, 0); 33857c478bd9Sstevel@tonic-gate 33867c478bd9Sstevel@tonic-gate client->events = ((client->events | revent) & 33877c478bd9Sstevel@tonic-gate (client->event_mask | 33887c478bd9Sstevel@tonic-gate client->global_mask)); 33897c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 33907c478bd9Sstevel@tonic-gate client = client->next; 33917c478bd9Sstevel@tonic-gate } /* while (client) */ 33927c478bd9Sstevel@tonic-gate 33937c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33947c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 33957c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_STATUS_CHANGE) */ 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate /* 33987c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 33997c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 34007c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 34017c478bd9Sstevel@tonic-gate * notified in the correct order. 34027c478bd9Sstevel@tonic-gate */ 34037c478bd9Sstevel@tonic-gate ct = &client_types[0]; 34047c478bd9Sstevel@tonic-gate while (ct) { 34057c478bd9Sstevel@tonic-gate /* 34067c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 34077c478bd9Sstevel@tonic-gate * through each client to set up the client events as well 34087c478bd9Sstevel@tonic-gate * as call the client's event handler directly if we have 34097c478bd9Sstevel@tonic-gate * a high priority event that we need to tell the client 34107c478bd9Sstevel@tonic-gate * about. 34117c478bd9Sstevel@tonic-gate */ 34127c478bd9Sstevel@tonic-gate client = sp->client_list; 34137c478bd9Sstevel@tonic-gate 34147c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 34157c478bd9Sstevel@tonic-gate client_t *clp = NULL; 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate while (client) { 34187c478bd9Sstevel@tonic-gate clp = client; 34197c478bd9Sstevel@tonic-gate client = client->next; 34207c478bd9Sstevel@tonic-gate } 34217c478bd9Sstevel@tonic-gate client = clp; 34227c478bd9Sstevel@tonic-gate } 34237c478bd9Sstevel@tonic-gate 34247c478bd9Sstevel@tonic-gate while (client) { 34257c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 34267c478bd9Sstevel@tonic-gate uint32_t bit = 0; 34277c478bd9Sstevel@tonic-gate event_t event; 34287c478bd9Sstevel@tonic-gate 34297c478bd9Sstevel@tonic-gate while (client->events) { 34307c478bd9Sstevel@tonic-gate 34317c478bd9Sstevel@tonic-gate switch (event = CS_BIT_GET(client->events, bit)) { 34327c478bd9Sstevel@tonic-gate /* 34337c478bd9Sstevel@tonic-gate * Clients always receive registration complete 34347c478bd9Sstevel@tonic-gate * events, even if there is no card of 34357c478bd9Sstevel@tonic-gate * their type currently in the socket. 34367c478bd9Sstevel@tonic-gate */ 34377c478bd9Sstevel@tonic-gate case CS_EVENT_REGISTRATION_COMPLETE: 34387c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 34397c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34407c478bd9Sstevel@tonic-gate break; 34417c478bd9Sstevel@tonic-gate /* 34427c478bd9Sstevel@tonic-gate * The client only gets a card insertion event 34437c478bd9Sstevel@tonic-gate * if there is currently a card in the 34447c478bd9Sstevel@tonic-gate * socket that the client can control. 34457c478bd9Sstevel@tonic-gate * The nexus determines this. We also 34467c478bd9Sstevel@tonic-gate * prevent the client from receiving 34477c478bd9Sstevel@tonic-gate * multiple CS_EVENT_CARD_INSERTION 34487c478bd9Sstevel@tonic-gate * events without receiving intervening 34497c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL events. 34507c478bd9Sstevel@tonic-gate */ 34517c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_INSERTION: 34527c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) { 34537c478bd9Sstevel@tonic-gate int send_insertion; 34547c478bd9Sstevel@tonic-gate 34557c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34567c478bd9Sstevel@tonic-gate send_insertion = client->flags; 34577c478bd9Sstevel@tonic-gate client->flags |= 34587c478bd9Sstevel@tonic-gate (CLIENT_CARD_INSERTED | 34597c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 34607c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34617c478bd9Sstevel@tonic-gate if (!(send_insertion & 34627c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION)) { 34637c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 34647c478bd9Sstevel@tonic-gate event, CS_EVENT_PRI_LOW); 34657c478bd9Sstevel@tonic-gate } /* if (!CLIENT_SENT_INSERTION) */ 34667c478bd9Sstevel@tonic-gate } 34677c478bd9Sstevel@tonic-gate break; 34687c478bd9Sstevel@tonic-gate /* 34697c478bd9Sstevel@tonic-gate * The CS_EVENT_CARD_REMOVAL_LOWP is a low 34707c478bd9Sstevel@tonic-gate * priority CS_EVENT_CARD_REMOVAL event. 34717c478bd9Sstevel@tonic-gate */ 34727c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL_LOWP: 34737c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34747c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_SENT_INSERTION; 34757c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34767c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 34777c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 34787c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34797c478bd9Sstevel@tonic-gate break; 34807c478bd9Sstevel@tonic-gate /* 34817c478bd9Sstevel@tonic-gate * The hardware card removal events are handed 34827c478bd9Sstevel@tonic-gate * to the client in cs_event at high 34837c478bd9Sstevel@tonic-gate * priority interrupt time; this card 34847c478bd9Sstevel@tonic-gate * removal event is a software-generated 34857c478bd9Sstevel@tonic-gate * event. 34867c478bd9Sstevel@tonic-gate */ 34877c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL: 34887c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 34897c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34907c478bd9Sstevel@tonic-gate client->flags &= 34917c478bd9Sstevel@tonic-gate ~(CLIENT_CARD_INSERTED | 34927c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 34937c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34947c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 34957c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34967c478bd9Sstevel@tonic-gate } 34977c478bd9Sstevel@tonic-gate break; 34987c478bd9Sstevel@tonic-gate /* 34997c478bd9Sstevel@tonic-gate * Write protect events require the info field 35007c478bd9Sstevel@tonic-gate * of the client's event callback args to 35017c478bd9Sstevel@tonic-gate * be zero if the card is not write 35027c478bd9Sstevel@tonic-gate * protected and one if it is. 35037c478bd9Sstevel@tonic-gate */ 35047c478bd9Sstevel@tonic-gate case CS_EVENT_WRITE_PROTECT: 35057c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 35067c478bd9Sstevel@tonic-gate get_ss_status_t gs; 35077c478bd9Sstevel@tonic-gate 35087c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 35097c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35107c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 35117c478bd9Sstevel@tonic-gate NULL, 35127c478bd9Sstevel@tonic-gate &gs, 0); 35137c478bd9Sstevel@tonic-gate if (gs.CardState & SBM_WP) { 35147c478bd9Sstevel@tonic-gate client->event_callback_args.info = 35157c478bd9Sstevel@tonic-gate (void *) 35167c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPON; 35177c478bd9Sstevel@tonic-gate } else { 35187c478bd9Sstevel@tonic-gate client->event_callback_args.info = 35197c478bd9Sstevel@tonic-gate (void *) 35207c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPOFF; 35217c478bd9Sstevel@tonic-gate } 35227c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35237c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 35247c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35257c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35267c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 35277c478bd9Sstevel@tonic-gate break; 35287c478bd9Sstevel@tonic-gate case CS_EVENT_CLIENT_INFO: 35297c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35307c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35317c478bd9Sstevel@tonic-gate break; 35327c478bd9Sstevel@tonic-gate case 0: 35337c478bd9Sstevel@tonic-gate break; 35347c478bd9Sstevel@tonic-gate default: 35357c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 35367c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35377c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35387c478bd9Sstevel@tonic-gate } 35397c478bd9Sstevel@tonic-gate break; 35407c478bd9Sstevel@tonic-gate } /* switch */ 35417c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35427c478bd9Sstevel@tonic-gate CS_BIT_CLEAR(client->events, bit); 35437c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35447c478bd9Sstevel@tonic-gate bit++; 35457c478bd9Sstevel@tonic-gate } /* while (client->events) */ 35467c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 35477c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 35487c478bd9Sstevel@tonic-gate client = client->prev; 35497c478bd9Sstevel@tonic-gate } else { 35507c478bd9Sstevel@tonic-gate client = client->next; 35517c478bd9Sstevel@tonic-gate } 35527c478bd9Sstevel@tonic-gate } /* while (client) */ 35537c478bd9Sstevel@tonic-gate 35547c478bd9Sstevel@tonic-gate ct = ct->next; 35557c478bd9Sstevel@tonic-gate } /* while (ct) */ 35567c478bd9Sstevel@tonic-gate 35577c478bd9Sstevel@tonic-gate /* 35587c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_REMOVAL events 35597c478bd9Sstevel@tonic-gate */ 35607c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 35617c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35627c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_REMOVAL; 35637c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35647c478bd9Sstevel@tonic-gate (void) cs_card_removal(sp); 35657c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 35667c478bd9Sstevel@tonic-gate 35677c478bd9Sstevel@tonic-gate /* 35687c478bd9Sstevel@tonic-gate * If someone is waiting for us to complete, signal them now. 35697c478bd9Sstevel@tonic-gate */ 35707c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_SYNC) { 35717c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35727c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_SYNC; 35737c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35747c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); 35757c478bd9Sstevel@tonic-gate } /* SOCKET_WAIT_SYNC */ 35767c478bd9Sstevel@tonic-gate 35777c478bd9Sstevel@tonic-gate } /* for (;;) */ 35787c478bd9Sstevel@tonic-gate } 35797c478bd9Sstevel@tonic-gate 35807c478bd9Sstevel@tonic-gate /* 35817c478bd9Sstevel@tonic-gate * cs_card_for_client - checks to see if a card that the client can control 35827c478bd9Sstevel@tonic-gate * is currently inserted in the socket. Socket Services 35837c478bd9Sstevel@tonic-gate * has to tell us if this is the case. 35847c478bd9Sstevel@tonic-gate */ 35857c478bd9Sstevel@tonic-gate static int 35867c478bd9Sstevel@tonic-gate cs_card_for_client(client_t *client) 35877c478bd9Sstevel@tonic-gate { 35887c478bd9Sstevel@tonic-gate 35897c478bd9Sstevel@tonic-gate /* 35907c478bd9Sstevel@tonic-gate * If the client has set the CS_EVENT_ALL_CLIENTS it means that they 35917c478bd9Sstevel@tonic-gate * want to get all events for all clients, irrespective of 35927c478bd9Sstevel@tonic-gate * whether or not there is a card in the socket. Such clients 35937c478bd9Sstevel@tonic-gate * have to be very careful if they touch the card hardware in 35947c478bd9Sstevel@tonic-gate * any way to prevent causing problems for other clients on the 35957c478bd9Sstevel@tonic-gate * same socket. This flag will typically only be set by the 35967c478bd9Sstevel@tonic-gate * "super-client" or CSI types of clients that wish to get 35977c478bd9Sstevel@tonic-gate * information on other clients or cards in the system. 35987c478bd9Sstevel@tonic-gate * Note that the CS_EVENT_ALL_CLIENTS must be set in either the 35997c478bd9Sstevel@tonic-gate * client's global event mask or client event mask. 36007c478bd9Sstevel@tonic-gate * The client must also have registered as a "super-client" or as a 36017c478bd9Sstevel@tonic-gate * CSI client for this socket. 36027c478bd9Sstevel@tonic-gate */ 36037c478bd9Sstevel@tonic-gate if ((client->flags & (CLIENT_SUPER_CLIENT | CLIENT_CSI_CLIENT)) && 36047c478bd9Sstevel@tonic-gate ((client->global_mask | client->event_mask) & 36057c478bd9Sstevel@tonic-gate CS_EVENT_ALL_CLIENTS)) 36067c478bd9Sstevel@tonic-gate return (1); 36077c478bd9Sstevel@tonic-gate 36087c478bd9Sstevel@tonic-gate /* 36097c478bd9Sstevel@tonic-gate * Look for the PCM_DEV_ACTIVE property on this client's dip; if 36107c478bd9Sstevel@tonic-gate * it's found, it means that this client can control the card 36117c478bd9Sstevel@tonic-gate * that is currently in the socket. This is a boolean 36127c478bd9Sstevel@tonic-gate * property managed by Socket Services. 36137c478bd9Sstevel@tonic-gate */ 36147c478bd9Sstevel@tonic-gate if (ddi_getprop(DDI_DEV_T_ANY, client->dip, (DDI_PROP_CANSLEEP | 36157c478bd9Sstevel@tonic-gate DDI_PROP_NOTPROM), 3616*c48c3045SToomas Soome PCM_DEV_ACTIVE, 0)) { 36177c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36187c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36197c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_for_client: client handle 0x%x " 36207c478bd9Sstevel@tonic-gate "driver [%s] says %s found\n", 36217c478bd9Sstevel@tonic-gate (int)client->client_handle, 36227c478bd9Sstevel@tonic-gate client->driver_name, 36237c478bd9Sstevel@tonic-gate PCM_DEV_ACTIVE); 36247c478bd9Sstevel@tonic-gate } 36257c478bd9Sstevel@tonic-gate #endif 36267c478bd9Sstevel@tonic-gate return (1); 36277c478bd9Sstevel@tonic-gate } 36287c478bd9Sstevel@tonic-gate 36297c478bd9Sstevel@tonic-gate return (0); 36307c478bd9Sstevel@tonic-gate } 36317c478bd9Sstevel@tonic-gate 36327c478bd9Sstevel@tonic-gate /* 36337c478bd9Sstevel@tonic-gate * cs_ss_thread - This is the Socket Services work thread. We fire off 36347c478bd9Sstevel@tonic-gate * any calls to Socket Services here that we want 36357c478bd9Sstevel@tonic-gate * to run on a thread that is seperate from the 36367c478bd9Sstevel@tonic-gate * per-socket event thread. 36377c478bd9Sstevel@tonic-gate */ 36387c478bd9Sstevel@tonic-gate static void 36397c478bd9Sstevel@tonic-gate cs_ss_thread(uint32_t sn) 36407c478bd9Sstevel@tonic-gate { 36417c478bd9Sstevel@tonic-gate cs_socket_t *sp; 36427c478bd9Sstevel@tonic-gate 36437c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 36447c478bd9Sstevel@tonic-gate return; 36457c478bd9Sstevel@tonic-gate 36467c478bd9Sstevel@tonic-gate /* 36477c478bd9Sstevel@tonic-gate * Tell CPR that we've started a new thread. 36487c478bd9Sstevel@tonic-gate */ 36497c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_ss, &sp->ss_thread_lock, 36507c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_ss_thread"); 36517c478bd9Sstevel@tonic-gate 36527c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 36537c478bd9Sstevel@tonic-gate 36547c478bd9Sstevel@tonic-gate for (;;) { 36557c478bd9Sstevel@tonic-gate 36567c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_ss); 36577c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_thread_cv, &sp->ss_thread_lock); 36587c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_ss, &sp->ss_thread_lock); 36597c478bd9Sstevel@tonic-gate 36607c478bd9Sstevel@tonic-gate /* 36617c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations 36627c478bd9Sstevel@tonic-gate * that we are being asked to perform. 36637c478bd9Sstevel@tonic-gate */ 36647c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_EXIT) { 36657c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36667c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36677c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 36687c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 36697c478bd9Sstevel@tonic-gate sp->socket_num); 36707c478bd9Sstevel@tonic-gate } 36717c478bd9Sstevel@tonic-gate #endif 36727c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_ss); 36737c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_caller_cv); /* wake up cs_deinit */ 36747c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 36757c478bd9Sstevel@tonic-gate return; 36767c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 36777c478bd9Sstevel@tonic-gate 36787c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36797c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36807c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 36817c478bd9Sstevel@tonic-gate "ss_thread_state = 0x%x\n", 36827c478bd9Sstevel@tonic-gate (int)sp->socket_num, 36837c478bd9Sstevel@tonic-gate (int)sp->ss_thread_state); 36847c478bd9Sstevel@tonic-gate } 36857c478bd9Sstevel@tonic-gate #endif 36867c478bd9Sstevel@tonic-gate 36877c478bd9Sstevel@tonic-gate /* 36887c478bd9Sstevel@tonic-gate * Call SocketServices(CSCISInit) to have SS parse the 36897c478bd9Sstevel@tonic-gate * CIS and load/attach any client drivers necessary. 36907c478bd9Sstevel@tonic-gate */ 36917c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_CSCISInit) { 36927c478bd9Sstevel@tonic-gate 36937c478bd9Sstevel@tonic-gate sp->ss_thread_state &= ~SOCKET_THREAD_CSCISInit; 36947c478bd9Sstevel@tonic-gate 36957c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 36967c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread %d " 36977c478bd9Sstevel@tonic-gate "card NOT inserted\n", 36987c478bd9Sstevel@tonic-gate sp->socket_num); 36997c478bd9Sstevel@tonic-gate } 37007c478bd9Sstevel@tonic-gate 37017c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 37027c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 37037c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d calling " 37047c478bd9Sstevel@tonic-gate "CSCISInit\n", sp->socket_num); 37057c478bd9Sstevel@tonic-gate } 37067c478bd9Sstevel@tonic-gate #endif 37077c478bd9Sstevel@tonic-gate 37087c478bd9Sstevel@tonic-gate /* 37097c478bd9Sstevel@tonic-gate * Tell SS that we have a complete CIS and that it can now 37107c478bd9Sstevel@tonic-gate * be parsed. 37117c478bd9Sstevel@tonic-gate * Note that in some cases the client driver may block in 37127c478bd9Sstevel@tonic-gate * their attach routine, causing this call to block until 37137c478bd9Sstevel@tonic-gate * the client completes their attach. 37147c478bd9Sstevel@tonic-gate */ 37157c478bd9Sstevel@tonic-gate SocketServices(CSCISInit, sp->socket_num); 37167c478bd9Sstevel@tonic-gate 37177c478bd9Sstevel@tonic-gate /* 37187c478bd9Sstevel@tonic-gate * Set the CS_EVENT_SS_UPDATED event for this socket so that the 37197c478bd9Sstevel@tonic-gate * event thread can continue any card insertion processing 37207c478bd9Sstevel@tonic-gate * that it has to do. 37217c478bd9Sstevel@tonic-gate */ 37227c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 37237c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_SS_UPDATED; 37247c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 37257c478bd9Sstevel@tonic-gate 37267c478bd9Sstevel@tonic-gate /* 37277c478bd9Sstevel@tonic-gate * Wake up this socket's event thread so that clients can 37287c478bd9Sstevel@tonic-gate * continue any card insertion or attach processing 37297c478bd9Sstevel@tonic-gate * that they need to do. 37307c478bd9Sstevel@tonic-gate */ 37317c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 37327c478bd9Sstevel@tonic-gate } /* if ST_CSCISInit */ 37337c478bd9Sstevel@tonic-gate 37347c478bd9Sstevel@tonic-gate } /* for (;;) */ 37357c478bd9Sstevel@tonic-gate } 37367c478bd9Sstevel@tonic-gate 37377c478bd9Sstevel@tonic-gate /* 37387c478bd9Sstevel@tonic-gate * cs_request_socket_mask - set the client's event mask as well as causes 37397c478bd9Sstevel@tonic-gate * any events pending from RegisterClient to 37407c478bd9Sstevel@tonic-gate * be scheduled to be sent to the client 37417c478bd9Sstevel@tonic-gate */ 37427c478bd9Sstevel@tonic-gate static int 37437c478bd9Sstevel@tonic-gate cs_request_socket_mask(client_handle_t client_handle, 37447c478bd9Sstevel@tonic-gate request_socket_mask_t *se) 37457c478bd9Sstevel@tonic-gate { 37467c478bd9Sstevel@tonic-gate cs_socket_t *sp; 37477c478bd9Sstevel@tonic-gate client_t *client; 37487c478bd9Sstevel@tonic-gate int error; 37497c478bd9Sstevel@tonic-gate int client_lock_acquired; 37507c478bd9Sstevel@tonic-gate 37517c478bd9Sstevel@tonic-gate /* 37527c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 37537c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 37547c478bd9Sstevel@tonic-gate */ 37557c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 37567c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 37577c478bd9Sstevel@tonic-gate 37587c478bd9Sstevel@tonic-gate /* 37597c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 37607c478bd9Sstevel@tonic-gate */ 37617c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 37627c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 37637c478bd9Sstevel@tonic-gate 37647c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 37657c478bd9Sstevel@tonic-gate 37667c478bd9Sstevel@tonic-gate /* 37677c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 37687c478bd9Sstevel@tonic-gate */ 37697c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 37707c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 37717c478bd9Sstevel@tonic-gate return (error); 37727c478bd9Sstevel@tonic-gate } 37737c478bd9Sstevel@tonic-gate 37747c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 37757c478bd9Sstevel@tonic-gate 37767c478bd9Sstevel@tonic-gate /* 37777c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 37787c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 37797c478bd9Sstevel@tonic-gate */ 37807c478bd9Sstevel@tonic-gate if (client->flags & REQ_SOCKET_MASK_DONE) { 37817c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 37827c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 37837c478bd9Sstevel@tonic-gate return (CS_IN_USE); 37847c478bd9Sstevel@tonic-gate } 37857c478bd9Sstevel@tonic-gate 37867c478bd9Sstevel@tonic-gate /* 37877c478bd9Sstevel@tonic-gate * Set up the event mask information; we copy this directly from 37887c478bd9Sstevel@tonic-gate * the client; since we are the only source of events, any 37897c478bd9Sstevel@tonic-gate * bogus bits that the client puts in here won't matter 37907c478bd9Sstevel@tonic-gate * because we'll never look at them. 37917c478bd9Sstevel@tonic-gate */ 37927c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 37937c478bd9Sstevel@tonic-gate 37947c478bd9Sstevel@tonic-gate /* 37957c478bd9Sstevel@tonic-gate * If RegisterClient left us some events to process, set these 37967c478bd9Sstevel@tonic-gate * events up here. 37977c478bd9Sstevel@tonic-gate */ 37987c478bd9Sstevel@tonic-gate if (client->pending_events) { 37997c478bd9Sstevel@tonic-gate client->events |= client->pending_events; 38007c478bd9Sstevel@tonic-gate client->pending_events = 0; 38017c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 38027c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 38037c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: client_handle = 0x%x " 38047c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 38057c478bd9Sstevel@tonic-gate (int)client->client_handle, 38067c478bd9Sstevel@tonic-gate client->driver_name, 38077c478bd9Sstevel@tonic-gate (int)client->events); 38087c478bd9Sstevel@tonic-gate } 38097c478bd9Sstevel@tonic-gate #endif 38107c478bd9Sstevel@tonic-gate } 38117c478bd9Sstevel@tonic-gate 38127c478bd9Sstevel@tonic-gate client->flags |= REQ_SOCKET_MASK_DONE; 38137c478bd9Sstevel@tonic-gate 38147c478bd9Sstevel@tonic-gate /* 38157c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 38167c478bd9Sstevel@tonic-gate * to generate the appropriate events. 38177c478bd9Sstevel@tonic-gate */ 38187c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 38197c478bd9Sstevel@tonic-gate 38207c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 38217c478bd9Sstevel@tonic-gate 38227c478bd9Sstevel@tonic-gate /* 38237c478bd9Sstevel@tonic-gate * Wakeup the event thread if there are any client events to process. 38247c478bd9Sstevel@tonic-gate */ 38257c478bd9Sstevel@tonic-gate if (client->events) { 38267c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 38277c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 38287c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 38297c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: did cv_broadcast for " 38307c478bd9Sstevel@tonic-gate "client_handle = 0x%x " 38317c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 38327c478bd9Sstevel@tonic-gate (int)client->client_handle, 38337c478bd9Sstevel@tonic-gate client->driver_name, 38347c478bd9Sstevel@tonic-gate (int)client->events); 38357c478bd9Sstevel@tonic-gate } 38367c478bd9Sstevel@tonic-gate #endif 38377c478bd9Sstevel@tonic-gate 38387c478bd9Sstevel@tonic-gate } 38397c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38407c478bd9Sstevel@tonic-gate 38417c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 38427c478bd9Sstevel@tonic-gate } 38437c478bd9Sstevel@tonic-gate 38447c478bd9Sstevel@tonic-gate /* 38457c478bd9Sstevel@tonic-gate * cs_release_socket_mask - clear the client's event mask 38467c478bd9Sstevel@tonic-gate * 38477c478bd9Sstevel@tonic-gate * Once this function returns, the client is guaranteed 38487c478bd9Sstevel@tonic-gate * not to get any more event callbacks. 38497c478bd9Sstevel@tonic-gate */ 38507c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 38517c478bd9Sstevel@tonic-gate static int 38527c478bd9Sstevel@tonic-gate cs_release_socket_mask(client_handle_t client_handle, 38537c478bd9Sstevel@tonic-gate release_socket_mask_t *rsm) 38547c478bd9Sstevel@tonic-gate { 38557c478bd9Sstevel@tonic-gate cs_socket_t *sp; 38567c478bd9Sstevel@tonic-gate client_t *client; 38577c478bd9Sstevel@tonic-gate int error; 38587c478bd9Sstevel@tonic-gate int client_lock_acquired; 38597c478bd9Sstevel@tonic-gate 38607c478bd9Sstevel@tonic-gate /* 38617c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 38627c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 38637c478bd9Sstevel@tonic-gate */ 38647c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 38657c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 38667c478bd9Sstevel@tonic-gate 38677c478bd9Sstevel@tonic-gate /* 38687c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 38697c478bd9Sstevel@tonic-gate */ 38707c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 38717c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 38727c478bd9Sstevel@tonic-gate 38737c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate /* 38767c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 38777c478bd9Sstevel@tonic-gate */ 38787c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 38797c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38807c478bd9Sstevel@tonic-gate return (error); 38817c478bd9Sstevel@tonic-gate } 38827c478bd9Sstevel@tonic-gate 38837c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate /* 38867c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 38877c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 38887c478bd9Sstevel@tonic-gate */ 38897c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 38907c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 38917c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38927c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 38937c478bd9Sstevel@tonic-gate } 38947c478bd9Sstevel@tonic-gate 38957c478bd9Sstevel@tonic-gate /* 38967c478bd9Sstevel@tonic-gate * Clear both the client event mask and the global event mask. 38977c478bd9Sstevel@tonic-gate * We clear both since the semantics of this function are 38987c478bd9Sstevel@tonic-gate * that once it returns, the client will not be called at 38997c478bd9Sstevel@tonic-gate * it's event handler for any events until RequestSocketMask 39007c478bd9Sstevel@tonic-gate * is called again. 39017c478bd9Sstevel@tonic-gate */ 39027c478bd9Sstevel@tonic-gate client->event_mask = 0; 39037c478bd9Sstevel@tonic-gate client->global_mask = 0; 39047c478bd9Sstevel@tonic-gate client->flags &= ~REQ_SOCKET_MASK_DONE; 39057c478bd9Sstevel@tonic-gate 39067c478bd9Sstevel@tonic-gate /* 39077c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 39087c478bd9Sstevel@tonic-gate * to generate the appropriate events. 39097c478bd9Sstevel@tonic-gate */ 39107c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 39117c478bd9Sstevel@tonic-gate 39127c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39137c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39147c478bd9Sstevel@tonic-gate 39157c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39167c478bd9Sstevel@tonic-gate } 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate /* 39197c478bd9Sstevel@tonic-gate * cs_get_event_mask - return the event mask for this client 39207c478bd9Sstevel@tonic-gate */ 39217c478bd9Sstevel@tonic-gate static int 39227c478bd9Sstevel@tonic-gate cs_get_event_mask(client_handle_t client_handle, sockevent_t *se) 39237c478bd9Sstevel@tonic-gate { 39247c478bd9Sstevel@tonic-gate cs_socket_t *sp; 39257c478bd9Sstevel@tonic-gate client_t *client; 39267c478bd9Sstevel@tonic-gate int error; 39277c478bd9Sstevel@tonic-gate int client_lock_acquired; 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate /* 39307c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 39317c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 39327c478bd9Sstevel@tonic-gate */ 39337c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 39347c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39357c478bd9Sstevel@tonic-gate 39367c478bd9Sstevel@tonic-gate /* 39377c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 39387c478bd9Sstevel@tonic-gate */ 39397c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 39407c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 39417c478bd9Sstevel@tonic-gate 39427c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 39437c478bd9Sstevel@tonic-gate 39447c478bd9Sstevel@tonic-gate /* 39457c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 39467c478bd9Sstevel@tonic-gate */ 39477c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 39487c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39497c478bd9Sstevel@tonic-gate return (error); 39507c478bd9Sstevel@tonic-gate } 39517c478bd9Sstevel@tonic-gate 39527c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 39537c478bd9Sstevel@tonic-gate 39547c478bd9Sstevel@tonic-gate #ifdef XXX 39557c478bd9Sstevel@tonic-gate /* 39567c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 39577c478bd9Sstevel@tonic-gate * for this client, then return an error. 39587c478bd9Sstevel@tonic-gate * XXX - how can a client get their event masks if their card 39597c478bd9Sstevel@tonic-gate * goes away? 39607c478bd9Sstevel@tonic-gate */ 39617c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 39627c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39637c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39647c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 39657c478bd9Sstevel@tonic-gate } 39667c478bd9Sstevel@tonic-gate #endif 39677c478bd9Sstevel@tonic-gate 39687c478bd9Sstevel@tonic-gate /* 39697c478bd9Sstevel@tonic-gate * We are only allowed to get the client event mask if a 39707c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 39717c478bd9Sstevel@tonic-gate * are allowed to get the global event mask at any 39727c478bd9Sstevel@tonic-gate * time. 39737c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 39747c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 39757c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 39767c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 39777c478bd9Sstevel@tonic-gate * GetEventMask. 39787c478bd9Sstevel@tonic-gate */ 39797c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 39807c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 39817c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39827c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39837c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 39847c478bd9Sstevel@tonic-gate } 39857c478bd9Sstevel@tonic-gate se->EventMask = client->event_mask; 39867c478bd9Sstevel@tonic-gate } else { 39877c478bd9Sstevel@tonic-gate se->EventMask = client->global_mask; 39887c478bd9Sstevel@tonic-gate } 39897c478bd9Sstevel@tonic-gate 39907c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39917c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39927c478bd9Sstevel@tonic-gate 39937c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39947c478bd9Sstevel@tonic-gate } 39957c478bd9Sstevel@tonic-gate 39967c478bd9Sstevel@tonic-gate /* 39977c478bd9Sstevel@tonic-gate * cs_set_event_mask - set the event mask for this client 39987c478bd9Sstevel@tonic-gate */ 39997c478bd9Sstevel@tonic-gate static int 40007c478bd9Sstevel@tonic-gate cs_set_event_mask(client_handle_t client_handle, sockevent_t *se) 40017c478bd9Sstevel@tonic-gate { 40027c478bd9Sstevel@tonic-gate cs_socket_t *sp; 40037c478bd9Sstevel@tonic-gate client_t *client; 40047c478bd9Sstevel@tonic-gate int error; 40057c478bd9Sstevel@tonic-gate int client_lock_acquired; 40067c478bd9Sstevel@tonic-gate 40077c478bd9Sstevel@tonic-gate /* 40087c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 40097c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 40107c478bd9Sstevel@tonic-gate */ 40117c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 40127c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 40137c478bd9Sstevel@tonic-gate 40147c478bd9Sstevel@tonic-gate /* 40157c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 40167c478bd9Sstevel@tonic-gate */ 40177c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 40187c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 40197c478bd9Sstevel@tonic-gate 40207c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 40217c478bd9Sstevel@tonic-gate 40227c478bd9Sstevel@tonic-gate /* 40237c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 40247c478bd9Sstevel@tonic-gate */ 40257c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 40267c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40277c478bd9Sstevel@tonic-gate return (error); 40287c478bd9Sstevel@tonic-gate } 40297c478bd9Sstevel@tonic-gate 40307c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 40317c478bd9Sstevel@tonic-gate 40327c478bd9Sstevel@tonic-gate #ifdef XXX 40337c478bd9Sstevel@tonic-gate /* 40347c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 40357c478bd9Sstevel@tonic-gate * for this client, then return an error. 40367c478bd9Sstevel@tonic-gate */ 40377c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 40387c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40397c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40407c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 40417c478bd9Sstevel@tonic-gate } 40427c478bd9Sstevel@tonic-gate #endif 40437c478bd9Sstevel@tonic-gate 40447c478bd9Sstevel@tonic-gate /* 40457c478bd9Sstevel@tonic-gate * We are only allowed to set the client event mask if a 40467c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 40477c478bd9Sstevel@tonic-gate * are allowed to set the global event mask at any 40487c478bd9Sstevel@tonic-gate * time. 40497c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 40507c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 40517c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 40527c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 40537c478bd9Sstevel@tonic-gate * GetEventMask. 40547c478bd9Sstevel@tonic-gate */ 40557c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 40567c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 40577c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40597c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 40607c478bd9Sstevel@tonic-gate } 40617c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 40627c478bd9Sstevel@tonic-gate } else { 40637c478bd9Sstevel@tonic-gate client->global_mask = se->EventMask; 40647c478bd9Sstevel@tonic-gate } 40657c478bd9Sstevel@tonic-gate 40667c478bd9Sstevel@tonic-gate /* 40677c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 40687c478bd9Sstevel@tonic-gate * to generate the appropriate events. 40697c478bd9Sstevel@tonic-gate */ 40707c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 40717c478bd9Sstevel@tonic-gate 40727c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40737c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40747c478bd9Sstevel@tonic-gate 40757c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 40767c478bd9Sstevel@tonic-gate } 40777c478bd9Sstevel@tonic-gate 40787c478bd9Sstevel@tonic-gate /* 40797c478bd9Sstevel@tonic-gate * cs_read_event_status - handles PRR events and returns card status 40807c478bd9Sstevel@tonic-gate * 40817c478bd9Sstevel@tonic-gate * calling: *sp - socket struct point 40827c478bd9Sstevel@tonic-gate * *client - client to check events on 40837c478bd9Sstevel@tonic-gate * *revent - pointer to event mask to update; if NULL, will 40847c478bd9Sstevel@tonic-gate * not be updated, if non-NULL, will be updated 40857c478bd9Sstevel@tonic-gate * with CS-format events; it is NOT necessary 40867c478bd9Sstevel@tonic-gate * to clear this value before calling this 40877c478bd9Sstevel@tonic-gate * function 40887c478bd9Sstevel@tonic-gate * *gs - pointer to a get_ss_status_t used for the SS GetStatus 40897c478bd9Sstevel@tonic-gate * call; it is not necessary to initialize any 40907c478bd9Sstevel@tonic-gate * members in this structure; set to NULL if 40917c478bd9Sstevel@tonic-gate * not used 40927c478bd9Sstevel@tonic-gate * flags - if CS_RES_IGNORE_NO_CARD is set, the check for a 40937c478bd9Sstevel@tonic-gate * card present will not be done 40947c478bd9Sstevel@tonic-gate * 40957c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 40967c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in the socket and the flags arg 40977c478bd9Sstevel@tonic-gate * is not set to CS_RES_IGNORE_NO_CARD 40987c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if the SS_GetStatus function returned an 40997c478bd9Sstevel@tonic-gate * error 41007c478bd9Sstevel@tonic-gate * 41017c478bd9Sstevel@tonic-gate * Note that if the client that configured this socket has told us that 41027c478bd9Sstevel@tonic-gate * the READY pin in the PRR isn't valid and the socket is in IO 41037c478bd9Sstevel@tonic-gate * mode, we always return that the card is READY. 41047c478bd9Sstevel@tonic-gate * 41057c478bd9Sstevel@tonic-gate * Note that if gs is not NULL, the current card state will be returned 41067c478bd9Sstevel@tonic-gate * in the gs->CardState member; this will always reflect the 41077c478bd9Sstevel@tonic-gate * current card state and the state will come from both the 41087c478bd9Sstevel@tonic-gate * SS_GetStatus call and the PRR, whichever is appropriate for 41097c478bd9Sstevel@tonic-gate * the mode that the socket is currently in. 41107c478bd9Sstevel@tonic-gate */ 41117c478bd9Sstevel@tonic-gate static int 41127c478bd9Sstevel@tonic-gate cs_read_event_status(cs_socket_t *sp, client_t *client, event_t *revent, 41137c478bd9Sstevel@tonic-gate get_ss_status_t *gs, int flags) 41147c478bd9Sstevel@tonic-gate { 41157c478bd9Sstevel@tonic-gate cfg_regs_t prrd = 0; 41167c478bd9Sstevel@tonic-gate 41177c478bd9Sstevel@tonic-gate /* 41187c478bd9Sstevel@tonic-gate * SOCKET_IS_IO will only be set if a RequestConfiguration 41197c478bd9Sstevel@tonic-gate * has been done by at least one client on this socket. 41207c478bd9Sstevel@tonic-gate * If there isn't a card in the socket or the caller wants to ignore 41217c478bd9Sstevel@tonic-gate * whether the card is in the socket or not, get the current 41227c478bd9Sstevel@tonic-gate * card status. 41237c478bd9Sstevel@tonic-gate */ 41247c478bd9Sstevel@tonic-gate if ((sp->flags & SOCKET_CARD_INSERTED) || 41257c478bd9Sstevel@tonic-gate (flags & CS_RES_IGNORE_NO_CARD)) { 41267c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 41277c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 41287c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 41297c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 41307c478bd9Sstevel@tonic-gate 41317c478bd9Sstevel@tonic-gate /* 41327c478bd9Sstevel@tonic-gate * Get a handle to the CIS window 41337c478bd9Sstevel@tonic-gate */ 41347c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 41357c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 41367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: socket %d " 41377c478bd9Sstevel@tonic-gate "can't init CIS window\n", 41387c478bd9Sstevel@tonic-gate sp->socket_num); 41397c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 41407c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 41417c478bd9Sstevel@tonic-gate 41427c478bd9Sstevel@tonic-gate prrd = csx_Get8(cis_handle, client->config_regs.prr_p); 41437c478bd9Sstevel@tonic-gate prrd &= client->pin; 41447c478bd9Sstevel@tonic-gate 41457c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 41467c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 41477c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: " 41487c478bd9Sstevel@tonic-gate "prrd 0x%x client->pin 0x%x\n", 41497c478bd9Sstevel@tonic-gate (int)prrd, 41507c478bd9Sstevel@tonic-gate client->pin); 41517c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR(1) = [%s%s%s%s%s%s%s%s]\n", 41527c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 41537c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 41547c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 41557c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 41567c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 41577c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 41587c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 41597c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 41607c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 41617c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 41627c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 41637c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 41647c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 41657c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 41667c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 41677c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 41687c478bd9Sstevel@tonic-gate } 41697c478bd9Sstevel@tonic-gate #endif 41707c478bd9Sstevel@tonic-gate 41717c478bd9Sstevel@tonic-gate /* 41727c478bd9Sstevel@tonic-gate * The caller wants the event changes sent back and 41737c478bd9Sstevel@tonic-gate * the PRR event change bits cleared. 41747c478bd9Sstevel@tonic-gate */ 41757c478bd9Sstevel@tonic-gate if (revent) { 41767c478bd9Sstevel@tonic-gate get_socket_t get_socket; 41777c478bd9Sstevel@tonic-gate set_socket_t set_socket; 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate /* 41807c478bd9Sstevel@tonic-gate * Bug ID: 1193636 - Card Services sends bogus 41817c478bd9Sstevel@tonic-gate * events on CS_EVENT_STATUS_CHANGE events 41827c478bd9Sstevel@tonic-gate * Clear this before we OR-in any values. 41837c478bd9Sstevel@tonic-gate */ 41847c478bd9Sstevel@tonic-gate *revent = 0; 41857c478bd9Sstevel@tonic-gate 41867c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_WP_EVENT, PRR_WP_STATUS, 41877c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT, *revent); 41887c478bd9Sstevel@tonic-gate 41897c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_READY_EVENT, PRR_READY_STATUS, 41907c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY, *revent); 41917c478bd9Sstevel@tonic-gate 41927c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD2_EVENT, PRR_BVD2_STATUS, 41937c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_LOW, *revent); 41947c478bd9Sstevel@tonic-gate 41957c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD1_EVENT, PRR_BVD1_STATUS, 41967c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_DEAD, *revent); 41977c478bd9Sstevel@tonic-gate 41987c478bd9Sstevel@tonic-gate 41997c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 42007c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 42017c478bd9Sstevel@tonic-gate 42027c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR() = [%s%s%s%s%s%s%s%s]\n", 42037c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 42047c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 42057c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 42067c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 42077c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 42087c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 42097c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 42107c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 42117c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 42127c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 42137c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 42147c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 42157c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 42167c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 42177c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 42187c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 42197c478bd9Sstevel@tonic-gate } 42207c478bd9Sstevel@tonic-gate #endif 42217c478bd9Sstevel@tonic-gate 42227c478bd9Sstevel@tonic-gate if (prrd) 42237c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, client->config_regs.prr_p, 42247c478bd9Sstevel@tonic-gate prrd); 42257c478bd9Sstevel@tonic-gate 42267c478bd9Sstevel@tonic-gate /* 42277c478bd9Sstevel@tonic-gate * We now have to reenable the status change interrupts 42287c478bd9Sstevel@tonic-gate * if there are any valid bits in the PRR. Since 42297c478bd9Sstevel@tonic-gate * the BVD1 signal becomes the STATUS_CHANGE 42307c478bd9Sstevel@tonic-gate * signal when the socket is in IO mode, we just 42317c478bd9Sstevel@tonic-gate * have to set the SBM_BVD1 enable bit in the 42327c478bd9Sstevel@tonic-gate * event mask. 42337c478bd9Sstevel@tonic-gate */ 42347c478bd9Sstevel@tonic-gate if (client->pin) { 42357c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 42367c478bd9Sstevel@tonic-gate SocketServices(SS_GetSocket, &get_socket); 42377c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 42387c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 42397c478bd9Sstevel@tonic-gate get_socket.SCIntMask | SBM_BVD1; 42407c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 42417c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 42427c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 42437c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 42447c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 42457c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 42467c478bd9Sstevel@tonic-gate set_socket.State = get_socket.state; 42477c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket); 42487c478bd9Sstevel@tonic-gate } /* if (client->pin) */ 42497c478bd9Sstevel@tonic-gate } /* if (revent) */ 42507c478bd9Sstevel@tonic-gate 42517c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 42527c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 42537c478bd9Sstevel@tonic-gate 42547c478bd9Sstevel@tonic-gate /* 42557c478bd9Sstevel@tonic-gate * The caller wants the current card state; we just read 42567c478bd9Sstevel@tonic-gate * it and return a copy of it but do not clear any of 42577c478bd9Sstevel@tonic-gate * the event changed bits (if we're reading the PRR). 42587c478bd9Sstevel@tonic-gate */ 42597c478bd9Sstevel@tonic-gate if (gs) { 42607c478bd9Sstevel@tonic-gate gs->socket = sp->socket_num; 42617c478bd9Sstevel@tonic-gate gs->CardState = 0; 42627c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, gs) != SUCCESS) 42637c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 42647c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 42657c478bd9Sstevel@tonic-gate /* 42667c478bd9Sstevel@tonic-gate * If the socket is in IO mode, then clear the 42677c478bd9Sstevel@tonic-gate * gs->CardState bits that are now in the PRR 42687c478bd9Sstevel@tonic-gate */ 42697c478bd9Sstevel@tonic-gate gs->CardState &= ~(SBM_WP | SBM_BVD1 | 42707c478bd9Sstevel@tonic-gate SBM_BVD2 | SBM_RDYBSY); 42717c478bd9Sstevel@tonic-gate 42727c478bd9Sstevel@tonic-gate /* 42737c478bd9Sstevel@tonic-gate * Convert PRR status to SS_GetStatus status 42747c478bd9Sstevel@tonic-gate */ 42757c478bd9Sstevel@tonic-gate if (prrd & PRR_WP_STATUS) 42767c478bd9Sstevel@tonic-gate gs->CardState |= SBM_WP; 42777c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD2_STATUS) 42787c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD2; 42797c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD1_STATUS) 42807c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD1; 42817c478bd9Sstevel@tonic-gate 42827c478bd9Sstevel@tonic-gate /* 42837c478bd9Sstevel@tonic-gate * If the client has indicated that there is no 42847c478bd9Sstevel@tonic-gate * PRR or that the READY bit in the PRR isn't 42857c478bd9Sstevel@tonic-gate * valid, then we simulate the READY bit by 42867c478bd9Sstevel@tonic-gate * always returning READY. 42877c478bd9Sstevel@tonic-gate */ 42887c478bd9Sstevel@tonic-gate if (!(client->present & CONFIG_PINREPL_REG_PRESENT) || 42897c478bd9Sstevel@tonic-gate ((client->present & CONFIG_PINREPL_REG_PRESENT) && 42907c478bd9Sstevel@tonic-gate !((client->pin & 42917c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) == 42927c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT))) || 42937c478bd9Sstevel@tonic-gate (prrd & PRR_READY_STATUS)) 42947c478bd9Sstevel@tonic-gate gs->CardState |= SBM_RDYBSY; 42957c478bd9Sstevel@tonic-gate 42967c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 42977c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 42987c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: prrd 0x%x " 42997c478bd9Sstevel@tonic-gate "client->pin 0x%x " 43007c478bd9Sstevel@tonic-gate "gs->CardState 0x%x\n", 43017c478bd9Sstevel@tonic-gate prrd, client->pin, gs->CardState); 43027c478bd9Sstevel@tonic-gate } 43037c478bd9Sstevel@tonic-gate #endif 43047c478bd9Sstevel@tonic-gate 43057c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 43067c478bd9Sstevel@tonic-gate } /* if (gs) */ 43077c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 43087c478bd9Sstevel@tonic-gate } /* if (SOCKET_CARD_INSERTED) */ 43097c478bd9Sstevel@tonic-gate 43107c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 43117c478bd9Sstevel@tonic-gate } 43127c478bd9Sstevel@tonic-gate 43137c478bd9Sstevel@tonic-gate /* 43147c478bd9Sstevel@tonic-gate * cs_get_status - gets live card status and latched card status changes 43157c478bd9Sstevel@tonic-gate * supports the GetStatus CS call 43167c478bd9Sstevel@tonic-gate * 43177c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 43187c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if the passed client handle is invalid 43197c478bd9Sstevel@tonic-gate * 43207c478bd9Sstevel@tonic-gate * Note: This function resets the latched status values maintained 43217c478bd9Sstevel@tonic-gate * by Socket Services 43227c478bd9Sstevel@tonic-gate */ 43237c478bd9Sstevel@tonic-gate static int 43247c478bd9Sstevel@tonic-gate cs_get_status(client_handle_t client_handle, get_status_t *gs) 43257c478bd9Sstevel@tonic-gate { 43267c478bd9Sstevel@tonic-gate cs_socket_t *sp; 43277c478bd9Sstevel@tonic-gate client_t *client; 43287c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 43297c478bd9Sstevel@tonic-gate get_socket_t get_socket; 43307c478bd9Sstevel@tonic-gate set_socket_t set_socket; 43317c478bd9Sstevel@tonic-gate int error; 43327c478bd9Sstevel@tonic-gate int client_lock_acquired; 43337c478bd9Sstevel@tonic-gate 43347c478bd9Sstevel@tonic-gate /* 43357c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 43367c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 43377c478bd9Sstevel@tonic-gate */ 43387c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 43397c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 43407c478bd9Sstevel@tonic-gate 43417c478bd9Sstevel@tonic-gate /* 43427c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 43437c478bd9Sstevel@tonic-gate */ 43447c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 43457c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 43467c478bd9Sstevel@tonic-gate 43477c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 43487c478bd9Sstevel@tonic-gate 43497c478bd9Sstevel@tonic-gate /* 43507c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 43517c478bd9Sstevel@tonic-gate */ 43527c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 43537c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43547c478bd9Sstevel@tonic-gate return (error); 43557c478bd9Sstevel@tonic-gate } 43567c478bd9Sstevel@tonic-gate 43577c478bd9Sstevel@tonic-gate /* 43587c478bd9Sstevel@tonic-gate * Get the current card status as well as the latched card 43597c478bd9Sstevel@tonic-gate * state. Set the CS_RES_IGNORE_NO_CARD so that even 43607c478bd9Sstevel@tonic-gate * if there is no card in the socket we'll still get 43617c478bd9Sstevel@tonic-gate * a valid status. 43627c478bd9Sstevel@tonic-gate * Note that it is not necessary to initialize any values 43637c478bd9Sstevel@tonic-gate * in the get_ss_status structure. 43647c478bd9Sstevel@tonic-gate */ 43657c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 43667c478bd9Sstevel@tonic-gate if ((error = cs_read_event_status(sp, client, NULL, &get_ss_status, 43677c478bd9Sstevel@tonic-gate CS_RES_IGNORE_NO_CARD)) != CS_SUCCESS) { 43687c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 43697c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43707c478bd9Sstevel@tonic-gate return (error); 43717c478bd9Sstevel@tonic-gate } 43727c478bd9Sstevel@tonic-gate 43737c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate gs->raw_CardState = cs_sbm2cse(get_ss_status.CardState); 43767c478bd9Sstevel@tonic-gate 43777c478bd9Sstevel@tonic-gate /* 43787c478bd9Sstevel@tonic-gate * Assign the "live" card state to the "real" card state. If there's 43797c478bd9Sstevel@tonic-gate * no card in the socket or the card in the socket is not 43807c478bd9Sstevel@tonic-gate * for this client, then we lie and tell the caller that the 43817c478bd9Sstevel@tonic-gate * card is not inserted. 43827c478bd9Sstevel@tonic-gate */ 43837c478bd9Sstevel@tonic-gate gs->CardState = gs->raw_CardState; 43847c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 43857c478bd9Sstevel@tonic-gate gs->CardState &= ~CS_EVENT_CARD_INSERTION; 43867c478bd9Sstevel@tonic-gate 43877c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43887c478bd9Sstevel@tonic-gate 43897c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 43907c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 43917c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 43927c478bd9Sstevel@tonic-gate 43937c478bd9Sstevel@tonic-gate gs->SocketState = cs_sbm2cse(get_socket.state); 43947c478bd9Sstevel@tonic-gate 43957c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 43967c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 43977c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 43987c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 43997c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 44007c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 44017c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 44027c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 44037c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 44047c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 44057c478bd9Sstevel@tonic-gate 44067c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 44077c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 44087c478bd9Sstevel@tonic-gate 44097c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 44107c478bd9Sstevel@tonic-gate } 44117c478bd9Sstevel@tonic-gate 44127c478bd9Sstevel@tonic-gate /* 44137c478bd9Sstevel@tonic-gate * cs_cse2sbm - converts a CS event mask to an SS (SBM_XXX) event mask 44147c478bd9Sstevel@tonic-gate */ 44157c478bd9Sstevel@tonic-gate static event_t 44167c478bd9Sstevel@tonic-gate cs_cse2sbm(event_t event_mask) 44177c478bd9Sstevel@tonic-gate { 44187c478bd9Sstevel@tonic-gate event_t sbm_event = 0; 44197c478bd9Sstevel@tonic-gate 44207c478bd9Sstevel@tonic-gate /* 44217c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 44227c478bd9Sstevel@tonic-gate */ 44237c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 44247c478bd9Sstevel@tonic-gate sbm_event |= SBM_WP; 44257c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 44267c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD1; 44277c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 44287c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD2; 44297c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 44307c478bd9Sstevel@tonic-gate sbm_event |= SBM_RDYBSY; 44317c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_LOCK) 44327c478bd9Sstevel@tonic-gate sbm_event |= SBM_LOCKED; 44337c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_EJECTION_REQUEST) 44347c478bd9Sstevel@tonic-gate sbm_event |= SBM_EJECT; 44357c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_INSERTION_REQUEST) 44367c478bd9Sstevel@tonic-gate sbm_event |= SBM_INSERT; 44377c478bd9Sstevel@tonic-gate if (event_mask & (CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL)) 44387c478bd9Sstevel@tonic-gate sbm_event |= SBM_CD; 44397c478bd9Sstevel@tonic-gate 44407c478bd9Sstevel@tonic-gate return (sbm_event); 44417c478bd9Sstevel@tonic-gate } 44427c478bd9Sstevel@tonic-gate 44437c478bd9Sstevel@tonic-gate /* 44447c478bd9Sstevel@tonic-gate * cs_sbm2cse - converts SBM_xxx state to CS event bits 44457c478bd9Sstevel@tonic-gate * 44467c478bd9Sstevel@tonic-gate * This function should never set any of the following bits: 44477c478bd9Sstevel@tonic-gate * 44487c478bd9Sstevel@tonic-gate * CS_EVENT_MTD_REQUEST 44497c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO 44507c478bd9Sstevel@tonic-gate * CS_EVENT_TIMER_EXPIRED 44517c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL 44527c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL_LOWP 44537c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 44547c478bd9Sstevel@tonic-gate * CS_EVENT_READY_TIMEOUT 44557c478bd9Sstevel@tonic-gate * 44567c478bd9Sstevel@tonic-gate * These bits are defined in the CS_STATUS_XXX series and are 44577c478bd9Sstevel@tonic-gate * used by GetStatus. 44587c478bd9Sstevel@tonic-gate */ 44597c478bd9Sstevel@tonic-gate static uint32_t 44607c478bd9Sstevel@tonic-gate cs_sbm2cse(uint32_t state) 44617c478bd9Sstevel@tonic-gate { 44627c478bd9Sstevel@tonic-gate uint32_t rstate = 0; 44637c478bd9Sstevel@tonic-gate 44647c478bd9Sstevel@tonic-gate /* 44657c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 44667c478bd9Sstevel@tonic-gate */ 44677c478bd9Sstevel@tonic-gate if (state & SBM_WP) 44687c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_WRITE_PROTECT; 44697c478bd9Sstevel@tonic-gate if (state & SBM_BVD1) 44707c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_DEAD; 44717c478bd9Sstevel@tonic-gate if (state & SBM_BVD2) 44727c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_LOW; 44737c478bd9Sstevel@tonic-gate if (state & SBM_RDYBSY) 44747c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_READY; 44757c478bd9Sstevel@tonic-gate if (state & SBM_LOCKED) 44767c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_LOCK; 44777c478bd9Sstevel@tonic-gate if (state & SBM_EJECT) 44787c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_EJECTION_REQUEST; 44797c478bd9Sstevel@tonic-gate if (state & SBM_INSERT) 44807c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_INSERTION_REQUEST; 44817c478bd9Sstevel@tonic-gate if (state & SBM_CD) 44827c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_INSERTION; 44837c478bd9Sstevel@tonic-gate 44847c478bd9Sstevel@tonic-gate return (rstate); 44857c478bd9Sstevel@tonic-gate } 44867c478bd9Sstevel@tonic-gate 44877c478bd9Sstevel@tonic-gate /* 44887c478bd9Sstevel@tonic-gate * cs_merge_event_masks - merge the CS global socket event mask with the 44897c478bd9Sstevel@tonic-gate * passed client's event masks 44907c478bd9Sstevel@tonic-gate */ 44917c478bd9Sstevel@tonic-gate static unsigned 44927c478bd9Sstevel@tonic-gate cs_merge_event_masks(cs_socket_t *sp, client_t *client) 44937c478bd9Sstevel@tonic-gate { 44947c478bd9Sstevel@tonic-gate unsigned SCIntMask; 44957c478bd9Sstevel@tonic-gate uint32_t event_mask; 44967c478bd9Sstevel@tonic-gate 44977c478bd9Sstevel@tonic-gate /* 44987c478bd9Sstevel@tonic-gate * We always want to see card detect and status change events. 44997c478bd9Sstevel@tonic-gate */ 45007c478bd9Sstevel@tonic-gate SCIntMask = SBM_CD; 45017c478bd9Sstevel@tonic-gate 45027c478bd9Sstevel@tonic-gate event_mask = client->event_mask | client->global_mask | 45037c478bd9Sstevel@tonic-gate sp->event_mask; 45047c478bd9Sstevel@tonic-gate 45057c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_IS_IO)) { 45067c478bd9Sstevel@tonic-gate SCIntMask |= cs_cse2sbm(event_mask); 45077c478bd9Sstevel@tonic-gate } else { 45087c478bd9Sstevel@tonic-gate /* 45097c478bd9Sstevel@tonic-gate * If the socket is in IO mode and there is a PRR present, 45107c478bd9Sstevel@tonic-gate * then we may need to enable PCE_CARD_STATUS_CHANGE 45117c478bd9Sstevel@tonic-gate * events. 45127c478bd9Sstevel@tonic-gate */ 45137c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 45147c478bd9Sstevel@tonic-gate 45157c478bd9Sstevel@tonic-gate SCIntMask |= (cs_cse2sbm(event_mask) & 45167c478bd9Sstevel@tonic-gate ~(SBM_WP | SBM_BVD1 | SBM_BVD2 | SBM_RDYBSY)); 45177c478bd9Sstevel@tonic-gate 45187c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_WP_STATUS | PRR_WP_EVENT)) == 45197c478bd9Sstevel@tonic-gate (PRR_WP_STATUS | PRR_WP_EVENT)) 45207c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 45217c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45227c478bd9Sstevel@tonic-gate 45237c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_READY_STATUS | PRR_READY_EVENT)) == 45247c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) 45257c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 45267c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45277c478bd9Sstevel@tonic-gate 45287c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) == 45297c478bd9Sstevel@tonic-gate (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) 45307c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 45317c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45327c478bd9Sstevel@tonic-gate 45337c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) == 45347c478bd9Sstevel@tonic-gate (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) 45357c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 45367c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45377c478bd9Sstevel@tonic-gate 45387c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 45397c478bd9Sstevel@tonic-gate } /* if (!SOCKET_IS_IO) */ 45407c478bd9Sstevel@tonic-gate 45417c478bd9Sstevel@tonic-gate return (SCIntMask); 45427c478bd9Sstevel@tonic-gate } 45437c478bd9Sstevel@tonic-gate 45447c478bd9Sstevel@tonic-gate /* 45457c478bd9Sstevel@tonic-gate * cs_set_socket_event_mask - set the event mask for the socket 45467c478bd9Sstevel@tonic-gate */ 45477c478bd9Sstevel@tonic-gate static int 45487c478bd9Sstevel@tonic-gate cs_set_socket_event_mask(cs_socket_t *sp, unsigned event_mask) 45497c478bd9Sstevel@tonic-gate { 45507c478bd9Sstevel@tonic-gate get_socket_t get_socket; 45517c478bd9Sstevel@tonic-gate set_socket_t set_socket; 45527c478bd9Sstevel@tonic-gate 45537c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 45547c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 45557c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 45567c478bd9Sstevel@tonic-gate 45577c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 45587c478bd9Sstevel@tonic-gate set_socket.SCIntMask = event_mask; 45597c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 45607c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 45617c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 45627c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 45637c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 45647c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 45657c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 45667c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 45677c478bd9Sstevel@tonic-gate 45687c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 45697c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 45707c478bd9Sstevel@tonic-gate 45717c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 45727c478bd9Sstevel@tonic-gate } 45737c478bd9Sstevel@tonic-gate 45747c478bd9Sstevel@tonic-gate /* 45757c478bd9Sstevel@tonic-gate * ==== MTD handling section ==== 45767c478bd9Sstevel@tonic-gate */ 45777c478bd9Sstevel@tonic-gate static int 45787c478bd9Sstevel@tonic-gate cs_deregister_mtd(client_handle_t client_handle) 45797c478bd9Sstevel@tonic-gate { 45807c478bd9Sstevel@tonic-gate 45817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deregister_mtd: client_handle 0x%x\n", 45827c478bd9Sstevel@tonic-gate (int)client_handle); 45837c478bd9Sstevel@tonic-gate 45847c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 45857c478bd9Sstevel@tonic-gate } 45867c478bd9Sstevel@tonic-gate 45877c478bd9Sstevel@tonic-gate /* 45887c478bd9Sstevel@tonic-gate * ==== memory window handling section ==== 45897c478bd9Sstevel@tonic-gate */ 45907c478bd9Sstevel@tonic-gate 45917c478bd9Sstevel@tonic-gate /* 45927c478bd9Sstevel@tonic-gate * cs_request_window - searches through window list for the socket to find a 45937c478bd9Sstevel@tonic-gate * memory window that matches the requested criteria; 45947c478bd9Sstevel@tonic-gate * this is RequestWindow 45957c478bd9Sstevel@tonic-gate * 45967c478bd9Sstevel@tonic-gate * calling: cs_request_window(client_handle_t, *window_handle_t, win_req_t *) 45977c478bd9Sstevel@tonic-gate * 45987c478bd9Sstevel@tonic-gate * On sucessful return, the window_handle_t * pointed to will 45997c478bd9Sstevel@tonic-gate * contain a valid window handle for this window. 46007c478bd9Sstevel@tonic-gate * 46017c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if window found 46027c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 46037c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 46047c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 46057c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 46067c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 46077c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 46087c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attrbute 46097c478bd9Sstevel@tonic-gate * flags are set 46107c478bd9Sstevel@tonic-gate */ 46117c478bd9Sstevel@tonic-gate static int 46127c478bd9Sstevel@tonic-gate cs_request_window(client_handle_t client_handle, 46137c478bd9Sstevel@tonic-gate window_handle_t *wh, 46147c478bd9Sstevel@tonic-gate win_req_t *rw) 46157c478bd9Sstevel@tonic-gate { 46167c478bd9Sstevel@tonic-gate cs_socket_t *sp; 46177c478bd9Sstevel@tonic-gate cs_window_t *cw; 46187c478bd9Sstevel@tonic-gate client_t *client; 46197c478bd9Sstevel@tonic-gate modify_win_t mw; 46207c478bd9Sstevel@tonic-gate inquire_window_t iw; 46217c478bd9Sstevel@tonic-gate uint32_t aw; 46227c478bd9Sstevel@tonic-gate int error; 46237c478bd9Sstevel@tonic-gate int client_lock_acquired; 46247c478bd9Sstevel@tonic-gate uint32_t socket_num; 46257c478bd9Sstevel@tonic-gate 46267c478bd9Sstevel@tonic-gate /* 46277c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 46287c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 46297c478bd9Sstevel@tonic-gate */ 46307c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 46317c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 46327c478bd9Sstevel@tonic-gate 46337c478bd9Sstevel@tonic-gate /* 46347c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported flags are set. 46357c478bd9Sstevel@tonic-gate */ 46367c478bd9Sstevel@tonic-gate if (rw->Attributes & (/* Compatability */ 46377c478bd9Sstevel@tonic-gate WIN_PAGED | 46387c478bd9Sstevel@tonic-gate WIN_SHARED | 46397c478bd9Sstevel@tonic-gate WIN_FIRST_SHARED | 46407c478bd9Sstevel@tonic-gate WIN_BINDING_SPECIFIC | 46417c478bd9Sstevel@tonic-gate /* CS internal */ 46427c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 46437c478bd9Sstevel@tonic-gate /* IO window flags */ 46447c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_IO | 46457c478bd9Sstevel@tonic-gate /* CardBus flags */ 46467c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_32 | 46477c478bd9Sstevel@tonic-gate WIN_PREFETCH_CACHE_MASK | 46487c478bd9Sstevel@tonic-gate WIN_BAR_MASK)) 46497c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 46507c478bd9Sstevel@tonic-gate 46517c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 46527c478bd9Sstevel@tonic-gate 46537c478bd9Sstevel@tonic-gate /* 46547c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 46557c478bd9Sstevel@tonic-gate */ 46567c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 46577c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 46587c478bd9Sstevel@tonic-gate 46597c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate /* 46627c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 46637c478bd9Sstevel@tonic-gate */ 46647c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 46657c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46667c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 46677c478bd9Sstevel@tonic-gate return (error); 46687c478bd9Sstevel@tonic-gate } 46697c478bd9Sstevel@tonic-gate 46707c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 46717c478bd9Sstevel@tonic-gate 46727c478bd9Sstevel@tonic-gate /* 46737c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 46747c478bd9Sstevel@tonic-gate * for this client, then return an error. 46757c478bd9Sstevel@tonic-gate */ 46767c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 46777c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 46787c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46797c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 46807c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 46817c478bd9Sstevel@tonic-gate } 46827c478bd9Sstevel@tonic-gate 46837c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 46847c478bd9Sstevel@tonic-gate 46857c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 46867c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 46877c478bd9Sstevel@tonic-gate 46887c478bd9Sstevel@tonic-gate 46897c478bd9Sstevel@tonic-gate /* 46907c478bd9Sstevel@tonic-gate * See if we can find a window that matches the caller's criteria. 46917c478bd9Sstevel@tonic-gate * If we can't, then thre's not much more that we can do except 46927c478bd9Sstevel@tonic-gate * for return an error. 46937c478bd9Sstevel@tonic-gate */ 46947c478bd9Sstevel@tonic-gate if ((error = cs_find_mem_window(sp->socket_num, rw, &aw)) != 46957c478bd9Sstevel@tonic-gate CS_SUCCESS) { 46967c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46977c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 46987c478bd9Sstevel@tonic-gate return (error); 46997c478bd9Sstevel@tonic-gate } 47007c478bd9Sstevel@tonic-gate 47017c478bd9Sstevel@tonic-gate /* 47027c478bd9Sstevel@tonic-gate * We got a window, now synthesize a new window handle for this 47037c478bd9Sstevel@tonic-gate * client and get a pointer to the global window structs 47047c478bd9Sstevel@tonic-gate * and assign this window to this client. 47057c478bd9Sstevel@tonic-gate * We don't have to check for errors from cs_create_window_handle 47067c478bd9Sstevel@tonic-gate * since that function always returns a valid window handle 47077c478bd9Sstevel@tonic-gate * if it is given a valid window number. 47087c478bd9Sstevel@tonic-gate */ 47097c478bd9Sstevel@tonic-gate *wh = cs_create_window_handle(aw); 47107c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(aw)) == NULL) { 47117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47127c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47137c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 47147c478bd9Sstevel@tonic-gate } 47157c478bd9Sstevel@tonic-gate 47167c478bd9Sstevel@tonic-gate cw->window_handle = *wh; 47177c478bd9Sstevel@tonic-gate cw->client_handle = client_handle; 47187c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 47197c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_MEM); 47207c478bd9Sstevel@tonic-gate 47217c478bd9Sstevel@tonic-gate mw.Attributes = ( 47227c478bd9Sstevel@tonic-gate rw->Attributes | 47237c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 47247c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID); 47257c478bd9Sstevel@tonic-gate mw.AccessSpeed = rw->win_params.AccessSpeed; 47267c478bd9Sstevel@tonic-gate 47277c478bd9Sstevel@tonic-gate if ((error = cs_modify_mem_window(*wh, &mw, rw, socket_num)) != 47287c478bd9Sstevel@tonic-gate CS_SUCCESS) { 47297c478bd9Sstevel@tonic-gate cw->state = 0; 47307c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47317c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47327c478bd9Sstevel@tonic-gate return (error); 47337c478bd9Sstevel@tonic-gate } 47347c478bd9Sstevel@tonic-gate 47357c478bd9Sstevel@tonic-gate /* 47367c478bd9Sstevel@tonic-gate * Get any required card offset and pass it back to the client. 47377c478bd9Sstevel@tonic-gate * This is not defined in the current PCMCIA spec. It is 47387c478bd9Sstevel@tonic-gate * an aid to clients that want to use it to generate an 47397c478bd9Sstevel@tonic-gate * optimum card offset. 47407c478bd9Sstevel@tonic-gate */ 47417c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(*wh); 47427c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 47437c478bd9Sstevel@tonic-gate 47447c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 47457c478bd9Sstevel@tonic-gate rw->ReqOffset = rw->Size; 47467c478bd9Sstevel@tonic-gate else 47477c478bd9Sstevel@tonic-gate rw->ReqOffset = iw.mem_win_char.ReqOffset; 47487c478bd9Sstevel@tonic-gate 47497c478bd9Sstevel@tonic-gate /* 47507c478bd9Sstevel@tonic-gate * Increment the client's memory window count; this is how we know 47517c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 47527c478bd9Sstevel@tonic-gate */ 47537c478bd9Sstevel@tonic-gate client->memwin_count++; 47547c478bd9Sstevel@tonic-gate 47557c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47567c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47577c478bd9Sstevel@tonic-gate 47587c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 47597c478bd9Sstevel@tonic-gate } 47607c478bd9Sstevel@tonic-gate 47617c478bd9Sstevel@tonic-gate /* 47627c478bd9Sstevel@tonic-gate * cs_release_window - deallocates the window associated with the passed 47637c478bd9Sstevel@tonic-gate * window handle; this is ReleaseWindow 47647c478bd9Sstevel@tonic-gate * 47657c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if window handle is valid and window was 47667c478bd9Sstevel@tonic-gate * sucessfully deallocated 47677c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if window handle is invalid or if window 47687c478bd9Sstevel@tonic-gate * handle is valid but window is not allocated 47697c478bd9Sstevel@tonic-gate */ 47707c478bd9Sstevel@tonic-gate static int 47717c478bd9Sstevel@tonic-gate cs_release_window(window_handle_t wh) 47727c478bd9Sstevel@tonic-gate { 47737c478bd9Sstevel@tonic-gate cs_socket_t *sp; 47747c478bd9Sstevel@tonic-gate cs_window_t *cw; 47757c478bd9Sstevel@tonic-gate client_t *client; 47767c478bd9Sstevel@tonic-gate int error; 47777c478bd9Sstevel@tonic-gate int client_lock_acquired; 47787c478bd9Sstevel@tonic-gate 47797c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 47807c478bd9Sstevel@tonic-gate 47817c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 47827c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47837c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 47847c478bd9Sstevel@tonic-gate } 47857c478bd9Sstevel@tonic-gate 47867c478bd9Sstevel@tonic-gate /* 47877c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 47887c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 47897c478bd9Sstevel@tonic-gate */ 47907c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(cw->client_handle)) { 47917c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47927c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 47937c478bd9Sstevel@tonic-gate } 47947c478bd9Sstevel@tonic-gate 47957c478bd9Sstevel@tonic-gate /* 47967c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 47977c478bd9Sstevel@tonic-gate */ 47987c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 47997c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 48007c478bd9Sstevel@tonic-gate 48017c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 48027c478bd9Sstevel@tonic-gate 48037c478bd9Sstevel@tonic-gate /* 48047c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 48057c478bd9Sstevel@tonic-gate */ 48067c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 48077c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48087c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48097c478bd9Sstevel@tonic-gate return (error); 48107c478bd9Sstevel@tonic-gate } 48117c478bd9Sstevel@tonic-gate 48127c478bd9Sstevel@tonic-gate /* 48137c478bd9Sstevel@tonic-gate * Mark this window as not in use anymore. 48147c478bd9Sstevel@tonic-gate */ 48157c478bd9Sstevel@tonic-gate cw->state &= ~CW_WIN_IN_USE; 48167c478bd9Sstevel@tonic-gate 48177c478bd9Sstevel@tonic-gate /* 48187c478bd9Sstevel@tonic-gate * Decrement the client's memory window count; this is how we know 48197c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 48207c478bd9Sstevel@tonic-gate */ 48217c478bd9Sstevel@tonic-gate if (!(--(client->memwin_count))) 48227c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_WIN_ALLOCATED; 48237c478bd9Sstevel@tonic-gate 48247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48257c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48267c478bd9Sstevel@tonic-gate 48277c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 48287c478bd9Sstevel@tonic-gate } 48297c478bd9Sstevel@tonic-gate 48307c478bd9Sstevel@tonic-gate /* 48317c478bd9Sstevel@tonic-gate * cs_modify_window - modifies a window's characteristics; this is ModifyWindow 48327c478bd9Sstevel@tonic-gate */ 48337c478bd9Sstevel@tonic-gate static int 48347c478bd9Sstevel@tonic-gate cs_modify_window(window_handle_t wh, modify_win_t *mw) 48357c478bd9Sstevel@tonic-gate { 48367c478bd9Sstevel@tonic-gate cs_socket_t *sp; 48377c478bd9Sstevel@tonic-gate cs_window_t *cw; 48387c478bd9Sstevel@tonic-gate client_t *client; 48397c478bd9Sstevel@tonic-gate int error; 48407c478bd9Sstevel@tonic-gate int client_lock_acquired; 48417c478bd9Sstevel@tonic-gate 48427c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 48437c478bd9Sstevel@tonic-gate 48447c478bd9Sstevel@tonic-gate /* 48457c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 48467c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 48477c478bd9Sstevel@tonic-gate * has allocated that window. 48487c478bd9Sstevel@tonic-gate */ 48497c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 48507c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48517c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 48527c478bd9Sstevel@tonic-gate } 48537c478bd9Sstevel@tonic-gate 48547c478bd9Sstevel@tonic-gate /* 48557c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 48567c478bd9Sstevel@tonic-gate */ 48577c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 48587c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 48597c478bd9Sstevel@tonic-gate 48607c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 48617c478bd9Sstevel@tonic-gate 48627c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 48637c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48647c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48657c478bd9Sstevel@tonic-gate return (error); 48667c478bd9Sstevel@tonic-gate } 48677c478bd9Sstevel@tonic-gate 48687c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 48697c478bd9Sstevel@tonic-gate 48707c478bd9Sstevel@tonic-gate /* 48717c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 48727c478bd9Sstevel@tonic-gate * for this client, then return an error. 48737c478bd9Sstevel@tonic-gate */ 48747c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 48757c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 48767c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48777c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48787c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 48797c478bd9Sstevel@tonic-gate } 48807c478bd9Sstevel@tonic-gate 48817c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 48827c478bd9Sstevel@tonic-gate 48837c478bd9Sstevel@tonic-gate mw->Attributes &= ( 48847c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_MASK | 48857c478bd9Sstevel@tonic-gate WIN_ENABLE | 48867c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID | 48877c478bd9Sstevel@tonic-gate WIN_ACC_ENDIAN_MASK | 48887c478bd9Sstevel@tonic-gate WIN_ACC_ORDER_MASK); 48897c478bd9Sstevel@tonic-gate 48907c478bd9Sstevel@tonic-gate mw->Attributes &= ~WIN_DATA_WIDTH_VALID; 48917c478bd9Sstevel@tonic-gate 4892*c48c3045SToomas Soome if ((error = cs_modify_mem_window(wh, mw, NULL, 0)) != CS_SUCCESS) { 48937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48947c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48957c478bd9Sstevel@tonic-gate return (error); 48967c478bd9Sstevel@tonic-gate } 48977c478bd9Sstevel@tonic-gate 48987c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48997c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 49007c478bd9Sstevel@tonic-gate 49017c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 49027c478bd9Sstevel@tonic-gate } 49037c478bd9Sstevel@tonic-gate 49047c478bd9Sstevel@tonic-gate /* 49057c478bd9Sstevel@tonic-gate * cs_modify_mem_window - modifies a window's characteristics; used internally 49067c478bd9Sstevel@tonic-gate * by Card Services 49077c478bd9Sstevel@tonic-gate * 49087c478bd9Sstevel@tonic-gate * If *wr is NULL, it means that we're being called by ModifyWindow 49097c478bd9Sstevel@tonic-gate * If *wr is non-NULL, it means that we are being called by RequestWindow 49107c478bd9Sstevel@tonic-gate * and so we can't use SS_GetWindow. 49117c478bd9Sstevel@tonic-gate */ 49127c478bd9Sstevel@tonic-gate static int 49137c478bd9Sstevel@tonic-gate cs_modify_mem_window(window_handle_t wh, modify_win_t *mw, 49147c478bd9Sstevel@tonic-gate win_req_t *wr, int sn) 49157c478bd9Sstevel@tonic-gate { 49167c478bd9Sstevel@tonic-gate get_window_t gw; 49177c478bd9Sstevel@tonic-gate set_window_t sw; 49187c478bd9Sstevel@tonic-gate set_page_t set_page; 49197c478bd9Sstevel@tonic-gate get_page_t get_page; 49207c478bd9Sstevel@tonic-gate 49217c478bd9Sstevel@tonic-gate /* 49227c478bd9Sstevel@tonic-gate * If the win_req_t struct pointer is NULL, it means that 49237c478bd9Sstevel@tonic-gate * we're being called by ModifyWindow, so get the 49247c478bd9Sstevel@tonic-gate * current window characteristics. 49257c478bd9Sstevel@tonic-gate */ 49267c478bd9Sstevel@tonic-gate if (!wr) { 49277c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 49287c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 49297c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49307c478bd9Sstevel@tonic-gate sw.state = gw.state; 49317c478bd9Sstevel@tonic-gate sw.socket = gw.socket; 49327c478bd9Sstevel@tonic-gate sw.WindowSize = gw.size; 49337c478bd9Sstevel@tonic-gate } else { 49347c478bd9Sstevel@tonic-gate sw.state = 0; 49357c478bd9Sstevel@tonic-gate sw.socket = sn; 49367c478bd9Sstevel@tonic-gate sw.WindowSize = wr->Size; 49377c478bd9Sstevel@tonic-gate } 49387c478bd9Sstevel@tonic-gate 49397c478bd9Sstevel@tonic-gate /* 49407c478bd9Sstevel@tonic-gate * If we're being called by RequestWindow, we must always have 49417c478bd9Sstevel@tonic-gate * WIN_ACCESS_SPEED_VALID set since get_window_t is not 49427c478bd9Sstevel@tonic-gate * defined. 49437c478bd9Sstevel@tonic-gate */ 49447c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ACCESS_SPEED_VALID) { 49457c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 49467c478bd9Sstevel@tonic-gate 49477c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_DEVSPEED_TO_NS; 49487c478bd9Sstevel@tonic-gate convert_speed.devspeed = mw->AccessSpeed; 49497c478bd9Sstevel@tonic-gate 49507c478bd9Sstevel@tonic-gate if (cs_convert_speed(&convert_speed) != CS_SUCCESS) 49517c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 49527c478bd9Sstevel@tonic-gate 49537c478bd9Sstevel@tonic-gate sw.speed = convert_speed.nS; 49547c478bd9Sstevel@tonic-gate } else { 49557c478bd9Sstevel@tonic-gate sw.speed = gw.speed; 49567c478bd9Sstevel@tonic-gate } 49577c478bd9Sstevel@tonic-gate 49587c478bd9Sstevel@tonic-gate if (!wr) { 49597c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 49607c478bd9Sstevel@tonic-gate get_page.page = 0; 49617c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetPage, &get_page) != SUCCESS) 49627c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49637c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 49647c478bd9Sstevel@tonic-gate set_page.offset = get_page.offset; 49657c478bd9Sstevel@tonic-gate } else { 49667c478bd9Sstevel@tonic-gate set_page.state = 0; 49677c478bd9Sstevel@tonic-gate set_page.offset = 0; 49687c478bd9Sstevel@tonic-gate } 49697c478bd9Sstevel@tonic-gate 49707c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ENABLE) { 49717c478bd9Sstevel@tonic-gate sw.state |= WS_ENABLED; 49727c478bd9Sstevel@tonic-gate set_page.state |= PS_ENABLED; 49737c478bd9Sstevel@tonic-gate } else { 49747c478bd9Sstevel@tonic-gate sw.state &= ~WS_ENABLED; 49757c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ENABLED; 49767c478bd9Sstevel@tonic-gate } 49777c478bd9Sstevel@tonic-gate 49787c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_VALID) { 49797c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_16) 49807c478bd9Sstevel@tonic-gate sw.state |= WS_16BIT; 49817c478bd9Sstevel@tonic-gate else 49827c478bd9Sstevel@tonic-gate sw.state &= ~WS_16BIT; 49837c478bd9Sstevel@tonic-gate } 49847c478bd9Sstevel@tonic-gate 49857c478bd9Sstevel@tonic-gate sw.window = GET_WINDOW_NUMBER(wh); 49867c478bd9Sstevel@tonic-gate sw.base = 0; 49877c478bd9Sstevel@tonic-gate 49887c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&sw, mw->Attributes); 49897c478bd9Sstevel@tonic-gate 49907c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) 49917c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49927c478bd9Sstevel@tonic-gate 49937c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_MEMORY_TYPE_AM) 49947c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 49957c478bd9Sstevel@tonic-gate else 49967c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ATTRIBUTE; 49977c478bd9Sstevel@tonic-gate 49987c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 49997c478bd9Sstevel@tonic-gate set_page.page = 0; 50007c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) 50017c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 50027c478bd9Sstevel@tonic-gate 50037c478bd9Sstevel@tonic-gate /* 50047c478bd9Sstevel@tonic-gate * Return the current base address of this window 50057c478bd9Sstevel@tonic-gate */ 50067c478bd9Sstevel@tonic-gate if (wr) { 50077c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 50087c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 50097c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 50107c478bd9Sstevel@tonic-gate 50117c478bd9Sstevel@tonic-gate wr->Base.handle = (acc_handle_t)gw.handle; 50127c478bd9Sstevel@tonic-gate } 50137c478bd9Sstevel@tonic-gate 50147c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 50157c478bd9Sstevel@tonic-gate } 50167c478bd9Sstevel@tonic-gate 50177c478bd9Sstevel@tonic-gate /* 50187c478bd9Sstevel@tonic-gate * cs_map_mem_page - sets the card offset of the mapped window 50197c478bd9Sstevel@tonic-gate */ 50207c478bd9Sstevel@tonic-gate static int 50217c478bd9Sstevel@tonic-gate cs_map_mem_page(window_handle_t wh, map_mem_page_t *mmp) 50227c478bd9Sstevel@tonic-gate { 50237c478bd9Sstevel@tonic-gate cs_socket_t *sp; 50247c478bd9Sstevel@tonic-gate cs_window_t *cw; 50257c478bd9Sstevel@tonic-gate client_t *client; 50267c478bd9Sstevel@tonic-gate inquire_window_t iw; 50277c478bd9Sstevel@tonic-gate get_window_t gw; 50287c478bd9Sstevel@tonic-gate set_page_t set_page; 50297c478bd9Sstevel@tonic-gate get_page_t get_page; 50307c478bd9Sstevel@tonic-gate int error; 50317c478bd9Sstevel@tonic-gate uint32_t size; 50327c478bd9Sstevel@tonic-gate int client_lock_acquired; 50337c478bd9Sstevel@tonic-gate 50347c478bd9Sstevel@tonic-gate /* 50357c478bd9Sstevel@tonic-gate * We don't support paged windows, so never allow a page number 50367c478bd9Sstevel@tonic-gate * of other than 0 50377c478bd9Sstevel@tonic-gate */ 50387c478bd9Sstevel@tonic-gate if (mmp->Page) 50397c478bd9Sstevel@tonic-gate return (CS_BAD_PAGE); 50407c478bd9Sstevel@tonic-gate 50417c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 50427c478bd9Sstevel@tonic-gate 50437c478bd9Sstevel@tonic-gate /* 50447c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 50457c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 50467c478bd9Sstevel@tonic-gate * has allocated that window. 50477c478bd9Sstevel@tonic-gate */ 50487c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 50497c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50507c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 50517c478bd9Sstevel@tonic-gate } 50527c478bd9Sstevel@tonic-gate 50537c478bd9Sstevel@tonic-gate /* 50547c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 50557c478bd9Sstevel@tonic-gate */ 50567c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 50577c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 50587c478bd9Sstevel@tonic-gate 50597c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 50607c478bd9Sstevel@tonic-gate 50617c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 50627c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50637c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50647c478bd9Sstevel@tonic-gate return (error); 50657c478bd9Sstevel@tonic-gate } 50667c478bd9Sstevel@tonic-gate 50677c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 50687c478bd9Sstevel@tonic-gate 50697c478bd9Sstevel@tonic-gate /* 50707c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 50717c478bd9Sstevel@tonic-gate * for this client, then return an error. 50727c478bd9Sstevel@tonic-gate */ 50737c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 50747c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 50757c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50767c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50777c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 50787c478bd9Sstevel@tonic-gate } 50797c478bd9Sstevel@tonic-gate 50807c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 50817c478bd9Sstevel@tonic-gate 50827c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 50837c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &gw); 50847c478bd9Sstevel@tonic-gate 50857c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(wh); 50867c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 50877c478bd9Sstevel@tonic-gate 50887c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 50897c478bd9Sstevel@tonic-gate size = gw.size; 50907c478bd9Sstevel@tonic-gate else 50917c478bd9Sstevel@tonic-gate size = iw.mem_win_char.ReqOffset; 50927c478bd9Sstevel@tonic-gate 50937c478bd9Sstevel@tonic-gate if (((mmp->CardOffset/size)*size) != mmp->CardOffset) { 50947c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50957c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50967c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 50977c478bd9Sstevel@tonic-gate } 50987c478bd9Sstevel@tonic-gate 50997c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 51007c478bd9Sstevel@tonic-gate get_page.page = 0; 51017c478bd9Sstevel@tonic-gate SocketServices(SS_GetPage, &get_page); 51027c478bd9Sstevel@tonic-gate 51037c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 51047c478bd9Sstevel@tonic-gate set_page.page = 0; 51057c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 51067c478bd9Sstevel@tonic-gate set_page.offset = mmp->CardOffset; 51077c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 51087c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 51097c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 51107c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 51117c478bd9Sstevel@tonic-gate } 51127c478bd9Sstevel@tonic-gate 51137c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 51147c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 51157c478bd9Sstevel@tonic-gate 51167c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 51177c478bd9Sstevel@tonic-gate } 51187c478bd9Sstevel@tonic-gate 51197c478bd9Sstevel@tonic-gate /* 51207c478bd9Sstevel@tonic-gate * cs_find_window - finds the window associated with the passed window 51217c478bd9Sstevel@tonic-gate * handle; if the window handle is invalid or no 51227c478bd9Sstevel@tonic-gate * windows match the passed window handle, NULL 51237c478bd9Sstevel@tonic-gate * is returned. Note that the window must be 51247c478bd9Sstevel@tonic-gate * allocated for this function to return a valid 51257c478bd9Sstevel@tonic-gate * window pointer. 51267c478bd9Sstevel@tonic-gate * 51277c478bd9Sstevel@tonic-gate * returns: cs_window_t * pointer to the found window 51287c478bd9Sstevel@tonic-gate * NULL if window handle invalid or window not allocated 51297c478bd9Sstevel@tonic-gate */ 51307c478bd9Sstevel@tonic-gate cs_window_t * 51317c478bd9Sstevel@tonic-gate cs_find_window(window_handle_t wh) 51327c478bd9Sstevel@tonic-gate { 51337c478bd9Sstevel@tonic-gate cs_window_t *cw; 51347c478bd9Sstevel@tonic-gate 51357c478bd9Sstevel@tonic-gate if ((GET_WINDOW_NUMBER(wh) > cs_globals.num_windows) || 51367c478bd9Sstevel@tonic-gate (GET_WINDOW_MAGIC(wh) != WINDOW_HANDLE_MAGIC)) 51377c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 51387c478bd9Sstevel@tonic-gate 51397c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(GET_WINDOW_NUMBER(wh))) == NULL) 51407c478bd9Sstevel@tonic-gate return (NULL); 51417c478bd9Sstevel@tonic-gate 51427c478bd9Sstevel@tonic-gate if ((cw->state & CW_ALLOCATED) && (cw->state & CW_MEM)) 51437c478bd9Sstevel@tonic-gate return (cw); 51447c478bd9Sstevel@tonic-gate 51457c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 51467c478bd9Sstevel@tonic-gate } 51477c478bd9Sstevel@tonic-gate 51487c478bd9Sstevel@tonic-gate /* 51497c478bd9Sstevel@tonic-gate * cs_create_window_handle - creates a unique window handle based on the 51507c478bd9Sstevel@tonic-gate * passed window number. 51517c478bd9Sstevel@tonic-gate */ 51527c478bd9Sstevel@tonic-gate static window_handle_t 51537c478bd9Sstevel@tonic-gate cs_create_window_handle(uint32_t aw) 51547c478bd9Sstevel@tonic-gate { 51557c478bd9Sstevel@tonic-gate return (WINDOW_HANDLE_MAGIC | (aw & WINDOW_HANDLE_MASK)); 51567c478bd9Sstevel@tonic-gate } 51577c478bd9Sstevel@tonic-gate 51587c478bd9Sstevel@tonic-gate /* 51597c478bd9Sstevel@tonic-gate * cs_find_mem_window - tries to find a memory window matching the caller's 51607c478bd9Sstevel@tonic-gate * criteria 51617c478bd9Sstevel@tonic-gate * 51627c478bd9Sstevel@tonic-gate * We return the first window that matches the requested criteria. 51637c478bd9Sstevel@tonic-gate * 51647c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if memory window found 51657c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 51667c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 51677c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 51687c478bd9Sstevel@tonic-gate */ 51697c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 51707c478bd9Sstevel@tonic-gate static int 51717c478bd9Sstevel@tonic-gate cs_find_mem_window(uint32_t sn, win_req_t *rw, uint32_t *assigned_window) 51727c478bd9Sstevel@tonic-gate { 51737c478bd9Sstevel@tonic-gate uint32_t wn; 51747c478bd9Sstevel@tonic-gate int error = CS_OUT_OF_RESOURCE; 51757c478bd9Sstevel@tonic-gate uint32_t window_num = PCMCIA_MAX_WINDOWS; 51767c478bd9Sstevel@tonic-gate uint32_t min_size = UINT_MAX; 51777c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 51787c478bd9Sstevel@tonic-gate uint32_t MinSize, MaxSize, ReqGran, MemWndCaps, WndCaps; 51797c478bd9Sstevel@tonic-gate uint32_t tws; 51807c478bd9Sstevel@tonic-gate 51817c478bd9Sstevel@tonic-gate iw = &inquire_window; 51827c478bd9Sstevel@tonic-gate 51837c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 51847c478bd9Sstevel@tonic-gate cs_window_t *cw; 51857c478bd9Sstevel@tonic-gate 51867c478bd9Sstevel@tonic-gate /* 51877c478bd9Sstevel@tonic-gate * If we can't get a pointer to this window, we should contine 51887c478bd9Sstevel@tonic-gate * with scanning the next window, since this window might have 51897c478bd9Sstevel@tonic-gate * been dropped. 51907c478bd9Sstevel@tonic-gate */ 51917c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 51927c478bd9Sstevel@tonic-gate iw->window = wn; 51937c478bd9Sstevel@tonic-gate 51947c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireWindow, iw) != SUCCESS) 51957c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 51967c478bd9Sstevel@tonic-gate 51977c478bd9Sstevel@tonic-gate MinSize = iw->mem_win_char.MinSize; 51987c478bd9Sstevel@tonic-gate MaxSize = iw->mem_win_char.MaxSize; 51997c478bd9Sstevel@tonic-gate ReqGran = iw->mem_win_char.ReqGran; 52007c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 52017c478bd9Sstevel@tonic-gate WndCaps = iw->WndCaps; 52027c478bd9Sstevel@tonic-gate 52037c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 52047c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_MEM(cw) && 52057c478bd9Sstevel@tonic-gate WndCaps & (WC_COMMON|WC_ATTRIBUTE)) { 52067c478bd9Sstevel@tonic-gate if ((error = cs_valid_window_speed(iw, rw->win_params.AccessSpeed)) == 52077c478bd9Sstevel@tonic-gate CS_SUCCESS) { 52087c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 52097c478bd9Sstevel@tonic-gate if (cs_memwin_space_and_map_ok(iw, rw)) { 52107c478bd9Sstevel@tonic-gate error = CS_BAD_SIZE; 52117c478bd9Sstevel@tonic-gate if (!rw->Size) { 52127c478bd9Sstevel@tonic-gate min_size = min(min_size, MinSize); 52137c478bd9Sstevel@tonic-gate window_num = wn; 52147c478bd9Sstevel@tonic-gate goto found_window; 52157c478bd9Sstevel@tonic-gate } else { 52167c478bd9Sstevel@tonic-gate if (!(MemWndCaps & WC_SIZE)) { 52177c478bd9Sstevel@tonic-gate if (rw->Size == MinSize) { 52187c478bd9Sstevel@tonic-gate min_size = MinSize; 52197c478bd9Sstevel@tonic-gate window_num = wn; 52207c478bd9Sstevel@tonic-gate goto found_window; 52217c478bd9Sstevel@tonic-gate } 52227c478bd9Sstevel@tonic-gate } else { /* WC_SIZE */ 52237c478bd9Sstevel@tonic-gate if (!ReqGran) { 52247c478bd9Sstevel@tonic-gate error = CS_BAD_WINDOW; 52257c478bd9Sstevel@tonic-gate } else { 52267c478bd9Sstevel@tonic-gate if ((rw->Size >= MinSize) && 52277c478bd9Sstevel@tonic-gate (rw->Size <= MaxSize)) { 52287c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_POW2) { 52297c478bd9Sstevel@tonic-gate unsigned rg = ReqGran; 52307c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 52317c478bd9Sstevel@tonic-gate rg = (rg<<1)) { 52327c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 52337c478bd9Sstevel@tonic-gate min_size = tws; 52347c478bd9Sstevel@tonic-gate window_num = wn; 52357c478bd9Sstevel@tonic-gate goto found_window; 52367c478bd9Sstevel@tonic-gate } 52377c478bd9Sstevel@tonic-gate tws += rg; 52387c478bd9Sstevel@tonic-gate } /* for (tws) */ 52397c478bd9Sstevel@tonic-gate } else { 52407c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 52417c478bd9Sstevel@tonic-gate tws += ReqGran) { 52427c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 52437c478bd9Sstevel@tonic-gate min_size = tws; 52447c478bd9Sstevel@tonic-gate window_num = wn; 52457c478bd9Sstevel@tonic-gate goto found_window; 52467c478bd9Sstevel@tonic-gate } 52477c478bd9Sstevel@tonic-gate } /* for (tws) */ 52487c478bd9Sstevel@tonic-gate } /* if (!WC_POW2) */ 52497c478bd9Sstevel@tonic-gate } /* if (Size >= MinSize) */ 52507c478bd9Sstevel@tonic-gate } /* if (!ReqGran) */ 52517c478bd9Sstevel@tonic-gate } /* if (WC_SIZE) */ 52527c478bd9Sstevel@tonic-gate } /* if (rw->Size) */ 52537c478bd9Sstevel@tonic-gate } /* if (cs_space_and_map_ok) */ 52547c478bd9Sstevel@tonic-gate } /* if (cs_valid_window_speed) */ 52557c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 52567c478bd9Sstevel@tonic-gate } /* if (cs_get_wp) */ 52577c478bd9Sstevel@tonic-gate } /* for (wn) */ 52587c478bd9Sstevel@tonic-gate 52597c478bd9Sstevel@tonic-gate /* 52607c478bd9Sstevel@tonic-gate * If we got here and the window_num wasn't set by any window 52617c478bd9Sstevel@tonic-gate * matches in the above code, it means that we didn't 52627c478bd9Sstevel@tonic-gate * find a window matching the caller's criteria. 52637c478bd9Sstevel@tonic-gate * If the error is CS_BAD_TYPE, it means that the last reason 52647c478bd9Sstevel@tonic-gate * that we couldn't match a window was because the caller's 52657c478bd9Sstevel@tonic-gate * requested speed was out of range of the last window that 52667c478bd9Sstevel@tonic-gate * we checked. We convert this error code to CS_OUT_OF_RESOURCE 52677c478bd9Sstevel@tonic-gate * to conform to the RequestWindow section of the PCMCIA 52687c478bd9Sstevel@tonic-gate * Card Services spec. 52697c478bd9Sstevel@tonic-gate */ 52707c478bd9Sstevel@tonic-gate if (window_num == PCMCIA_MAX_WINDOWS) { 52717c478bd9Sstevel@tonic-gate if (error == CS_BAD_TYPE) 52727c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 52737c478bd9Sstevel@tonic-gate return (error); 52747c478bd9Sstevel@tonic-gate } 52757c478bd9Sstevel@tonic-gate 52767c478bd9Sstevel@tonic-gate found_window: 52777c478bd9Sstevel@tonic-gate rw->Size = min_size; 52787c478bd9Sstevel@tonic-gate *assigned_window = window_num; 52797c478bd9Sstevel@tonic-gate iw->window = window_num; 52807c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 52817c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 52827c478bd9Sstevel@tonic-gate 52837c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_CALIGN) 52847c478bd9Sstevel@tonic-gate rw->Attributes |= WIN_OFFSET_SIZE; 52857c478bd9Sstevel@tonic-gate else 52867c478bd9Sstevel@tonic-gate rw->Attributes &= ~WIN_OFFSET_SIZE; 52877c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 52887c478bd9Sstevel@tonic-gate } 52897c478bd9Sstevel@tonic-gate /* END CSTYLED */ 52907c478bd9Sstevel@tonic-gate 52917c478bd9Sstevel@tonic-gate /* 52927c478bd9Sstevel@tonic-gate * cs_memwin_space_and_map_ok - checks to see if the passed window mapping 52937c478bd9Sstevel@tonic-gate * capabilities and window speeds are in the 52947c478bd9Sstevel@tonic-gate * range of the passed window. 52957c478bd9Sstevel@tonic-gate * 52967c478bd9Sstevel@tonic-gate * returns: 0 - if the capabilities are out of range 52977c478bd9Sstevel@tonic-gate * 1 - if the capabilities are in range 52987c478bd9Sstevel@tonic-gate */ 52997c478bd9Sstevel@tonic-gate static int 53007c478bd9Sstevel@tonic-gate cs_memwin_space_and_map_ok(inquire_window_t *iw, win_req_t *rw) 53017c478bd9Sstevel@tonic-gate { 53027c478bd9Sstevel@tonic-gate 53037c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 53047c478bd9Sstevel@tonic-gate if (cs_debug > 240) 53057c478bd9Sstevel@tonic-gate printf("-> s&m_ok: Attributes 0x%x AccessSpeed 0x%x " 53067c478bd9Sstevel@tonic-gate "WndCaps 0x%x MemWndCaps 0x%x\n", 53077c478bd9Sstevel@tonic-gate (int)rw->Attributes, 53087c478bd9Sstevel@tonic-gate (int)rw->win_params.AccessSpeed, 53097c478bd9Sstevel@tonic-gate iw->WndCaps, 53107c478bd9Sstevel@tonic-gate iw->mem_win_char.MemWndCaps); 53117c478bd9Sstevel@tonic-gate #endif 53127c478bd9Sstevel@tonic-gate 53137c478bd9Sstevel@tonic-gate if (rw->win_params.AccessSpeed & WIN_USE_WAIT) { 53147c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_WAIT)) 53157c478bd9Sstevel@tonic-gate return (0); 53167c478bd9Sstevel@tonic-gate } 53177c478bd9Sstevel@tonic-gate 53187c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_DATA_WIDTH_16) { 53197c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_16BIT)) 53207c478bd9Sstevel@tonic-gate return (0); 53217c478bd9Sstevel@tonic-gate } else { 53227c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_8BIT)) 53237c478bd9Sstevel@tonic-gate return (0); 53247c478bd9Sstevel@tonic-gate } 53257c478bd9Sstevel@tonic-gate 53267c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_AM) { 53277c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_ATTRIBUTE)) 53287c478bd9Sstevel@tonic-gate return (0); 53297c478bd9Sstevel@tonic-gate } 53307c478bd9Sstevel@tonic-gate 53317c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_CM) { 53327c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_COMMON)) 53337c478bd9Sstevel@tonic-gate return (0); 53347c478bd9Sstevel@tonic-gate } 53357c478bd9Sstevel@tonic-gate 53367c478bd9Sstevel@tonic-gate return (1); 53377c478bd9Sstevel@tonic-gate } 53387c478bd9Sstevel@tonic-gate 53397c478bd9Sstevel@tonic-gate /* 53407c478bd9Sstevel@tonic-gate * cs_valid_window_speed - checks to see if requested window speed 53417c478bd9Sstevel@tonic-gate * is in range of passed window 53427c478bd9Sstevel@tonic-gate * 53437c478bd9Sstevel@tonic-gate * The inquire_window_t struct gives us speeds in nS, and we 53447c478bd9Sstevel@tonic-gate * get speeds in the AccessSpeed variable as a devspeed code. 53457c478bd9Sstevel@tonic-gate * 53467c478bd9Sstevel@tonic-gate * returns: CS_BAD_SPEED - if AccessSpeed is invalid devspeed code 53477c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if AccessSpeed is not in range of valid 53487c478bd9Sstevel@tonic-gate * speed for this window 53497c478bd9Sstevel@tonic-gate * CS_SUCCESS - if window speed is in range 53507c478bd9Sstevel@tonic-gate */ 53517c478bd9Sstevel@tonic-gate static int 53527c478bd9Sstevel@tonic-gate cs_valid_window_speed(inquire_window_t *iw, uint32_t AccessSpeed) 53537c478bd9Sstevel@tonic-gate { 53547c478bd9Sstevel@tonic-gate convert_speed_t convert_speed, *cs; 53557c478bd9Sstevel@tonic-gate 53567c478bd9Sstevel@tonic-gate cs = &convert_speed; 53577c478bd9Sstevel@tonic-gate 53587c478bd9Sstevel@tonic-gate cs->Attributes = CONVERT_DEVSPEED_TO_NS; 53597c478bd9Sstevel@tonic-gate cs->devspeed = AccessSpeed; 53607c478bd9Sstevel@tonic-gate 53617c478bd9Sstevel@tonic-gate if (cs_convert_speed(cs) != CS_SUCCESS) 53627c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 53637c478bd9Sstevel@tonic-gate 53647c478bd9Sstevel@tonic-gate if ((cs->nS < iw->mem_win_char.Fastest) || 53657c478bd9Sstevel@tonic-gate (cs->nS > iw->mem_win_char.Slowest)) 53667c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 53677c478bd9Sstevel@tonic-gate 53687c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 53697c478bd9Sstevel@tonic-gate } 53707c478bd9Sstevel@tonic-gate 53717c478bd9Sstevel@tonic-gate /* 53727c478bd9Sstevel@tonic-gate * ==== IO window handling section ==== 53737c478bd9Sstevel@tonic-gate */ 53747c478bd9Sstevel@tonic-gate 53757c478bd9Sstevel@tonic-gate /* 53767c478bd9Sstevel@tonic-gate * cs_request_io - provides IO resources for clients; this is RequestIO 53777c478bd9Sstevel@tonic-gate * 53787c478bd9Sstevel@tonic-gate * calling: cs_request_io(client_handle_t, io_req_t *) 53797c478bd9Sstevel@tonic-gate * 53807c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources available for client 53817c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 53827c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 53837c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 53847c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 53857c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 53867c478bd9Sstevel@tonic-gate * flags are set 53877c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if either or both base port addresses 53887c478bd9Sstevel@tonic-gate * are invalid or out of range 53897c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 53907c478bd9Sstevel@tonic-gate * already been done 53917c478bd9Sstevel@tonic-gate * CS_IN_USE - IO ports already in use or function has 53927c478bd9Sstevel@tonic-gate * already been called 53937c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if failure while trying to set window 53947c478bd9Sstevel@tonic-gate * characteristics 53957c478bd9Sstevel@tonic-gate */ 53967c478bd9Sstevel@tonic-gate static int 53977c478bd9Sstevel@tonic-gate cs_request_io(client_handle_t client_handle, io_req_t *ior) 53987c478bd9Sstevel@tonic-gate { 53997c478bd9Sstevel@tonic-gate cs_socket_t *sp; 54007c478bd9Sstevel@tonic-gate client_t *client; 54017c478bd9Sstevel@tonic-gate int error; 54027c478bd9Sstevel@tonic-gate int client_lock_acquired; 54037c478bd9Sstevel@tonic-gate uint32_t socket_num; 54047c478bd9Sstevel@tonic-gate 54057c478bd9Sstevel@tonic-gate /* 54067c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 54077c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 54087c478bd9Sstevel@tonic-gate */ 54097c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 54107c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 54117c478bd9Sstevel@tonic-gate 54127c478bd9Sstevel@tonic-gate /* 54137c478bd9Sstevel@tonic-gate * If the client has only requested one IO range, then make sure 54147c478bd9Sstevel@tonic-gate * that the Attributes2 filed is clear. 54157c478bd9Sstevel@tonic-gate */ 54167c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 54177c478bd9Sstevel@tonic-gate ior->Attributes2 = 0; 54187c478bd9Sstevel@tonic-gate 54197c478bd9Sstevel@tonic-gate /* 54207c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 54217c478bd9Sstevel@tonic-gate */ 54227c478bd9Sstevel@tonic-gate if ((ior->Attributes1 | ior->Attributes2) & (IO_SHARED | 54237c478bd9Sstevel@tonic-gate IO_FIRST_SHARED | 54247c478bd9Sstevel@tonic-gate IO_FORCE_ALIAS_ACCESS | 54257c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 54267c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)) 54277c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 54287c478bd9Sstevel@tonic-gate 54297c478bd9Sstevel@tonic-gate /* 54307c478bd9Sstevel@tonic-gate * Make sure that we have a port count for the first region. 54317c478bd9Sstevel@tonic-gate */ 54327c478bd9Sstevel@tonic-gate if (!ior->NumPorts1) 54337c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 54347c478bd9Sstevel@tonic-gate 54357c478bd9Sstevel@tonic-gate /* 54367c478bd9Sstevel@tonic-gate * If we're being asked for multiple IO ranges, then both base port 54377c478bd9Sstevel@tonic-gate * members must be non-zero. 54387c478bd9Sstevel@tonic-gate */ 54397c478bd9Sstevel@tonic-gate if ((ior->NumPorts2) && !(ior->BasePort1.base && ior->BasePort2.base)) 54407c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 54417c478bd9Sstevel@tonic-gate 54427c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 54437c478bd9Sstevel@tonic-gate 54447c478bd9Sstevel@tonic-gate /* 54457c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 54467c478bd9Sstevel@tonic-gate */ 54477c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 54487c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 54497c478bd9Sstevel@tonic-gate 54507c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 54517c478bd9Sstevel@tonic-gate 54527c478bd9Sstevel@tonic-gate /* 54537c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 54547c478bd9Sstevel@tonic-gate */ 54557c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 54567c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54577c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54587c478bd9Sstevel@tonic-gate return (error); 54597c478bd9Sstevel@tonic-gate } 54607c478bd9Sstevel@tonic-gate 54617c478bd9Sstevel@tonic-gate /* 54627c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 54637c478bd9Sstevel@tonic-gate * this call. 54647c478bd9Sstevel@tonic-gate */ 54657c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 54667c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54677c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54687c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 54697c478bd9Sstevel@tonic-gate } 54707c478bd9Sstevel@tonic-gate 54717c478bd9Sstevel@tonic-gate /* 54727c478bd9Sstevel@tonic-gate * If RequestIO has already been done, we don't allow this call. 54737c478bd9Sstevel@tonic-gate */ 54747c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 54757c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54767c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54777c478bd9Sstevel@tonic-gate return (CS_IN_USE); 54787c478bd9Sstevel@tonic-gate } 54797c478bd9Sstevel@tonic-gate 54807c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate /* 54837c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 54847c478bd9Sstevel@tonic-gate * for this client, then return an error. 54857c478bd9Sstevel@tonic-gate */ 54867c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 54877c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 54887c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54897c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54907c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 54917c478bd9Sstevel@tonic-gate } 54927c478bd9Sstevel@tonic-gate 54937c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 54947c478bd9Sstevel@tonic-gate 54957c478bd9Sstevel@tonic-gate /* 54967c478bd9Sstevel@tonic-gate * If we're only being asked for one IO range, then set BasePort2 to 54977c478bd9Sstevel@tonic-gate * zero, since we use it later on. 54987c478bd9Sstevel@tonic-gate */ 54997c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 55007c478bd9Sstevel@tonic-gate ior->BasePort2.base = 0; 55017c478bd9Sstevel@tonic-gate 55027c478bd9Sstevel@tonic-gate /* 55037c478bd9Sstevel@tonic-gate * See if we can allow Card Services to select the base address 55047c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 55057c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 55067c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 55077c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 55087c478bd9Sstevel@tonic-gate * Note that if the client specifies that the card decodes zero 55097c478bd9Sstevel@tonic-gate * IO address lines, then we have to use the NumPortsX 55107c478bd9Sstevel@tonic-gate * values to figure out how many address lines the card 55117c478bd9Sstevel@tonic-gate * actually decodes, and we have to round the NumPortsX 55127c478bd9Sstevel@tonic-gate * values up to the closest power of two. 55137c478bd9Sstevel@tonic-gate */ 55147c478bd9Sstevel@tonic-gate if (ior->IOAddrLines) { 55157c478bd9Sstevel@tonic-gate ior->BasePort1.base = IOADDR_FROBNITZ(ior->BasePort1.base, 55167c478bd9Sstevel@tonic-gate ior->IOAddrLines); 55177c478bd9Sstevel@tonic-gate ior->BasePort2.base = IOADDR_FROBNITZ(ior->BasePort2.base, 55187c478bd9Sstevel@tonic-gate ior->IOAddrLines); 55197c478bd9Sstevel@tonic-gate } else { 55207c478bd9Sstevel@tonic-gate ior->BasePort1.base = ior->BasePort1.base & 55217c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 55227c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 55237c478bd9Sstevel@tonic-gate ior->BasePort2.base = ior->BasePort2.base & 55247c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 55257c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 55267c478bd9Sstevel@tonic-gate } 55277c478bd9Sstevel@tonic-gate 55287c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 55297c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 55307c478bd9Sstevel@tonic-gate 55317c478bd9Sstevel@tonic-gate 55327c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 55337c478bd9Sstevel@tonic-gate /* 55347c478bd9Sstevel@tonic-gate * Here is where the code diverges, depending on the type of IO windows 55357c478bd9Sstevel@tonic-gate * that this socket supports. If this socket supportes memory 55367c478bd9Sstevel@tonic-gate * mapped IO windows, as determined by cs_init allocating an 55377c478bd9Sstevel@tonic-gate * io_mmap_window_t structure on the socket structure, then we 55387c478bd9Sstevel@tonic-gate * use one IO window for all the clients on this socket. We can 55397c478bd9Sstevel@tonic-gate * do this safely since a memory mapped IO window implies that 55407c478bd9Sstevel@tonic-gate * only this socket shares the complete IO space of the card. 55417c478bd9Sstevel@tonic-gate * See the next major block of code for a description of what we do 55427c478bd9Sstevel@tonic-gate * if a socket doesn't support memory mapped IO windows. 55437c478bd9Sstevel@tonic-gate */ 55447c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 55457c478bd9Sstevel@tonic-gate cs_window_t *cw; 55467c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 55477c478bd9Sstevel@tonic-gate uint32_t offset; 55487c478bd9Sstevel@tonic-gate 55497c478bd9Sstevel@tonic-gate /* 55507c478bd9Sstevel@tonic-gate * If we haven't allocated an IO window yet, do it now. 55517c478bd9Sstevel@tonic-gate * Try to allocate the IO window that cs_init found for us; 55527c478bd9Sstevel@tonic-gate * if that fails, then call cs_find_io_win to find a window. 55537c478bd9Sstevel@tonic-gate */ 55547c478bd9Sstevel@tonic-gate if (!imw->count) { 55557c478bd9Sstevel@tonic-gate set_window_t set_window; 55567c478bd9Sstevel@tonic-gate 55577c478bd9Sstevel@tonic-gate if (!WINDOW_AVAILABLE_FOR_IO(imw->number)) { 55587c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 55597c478bd9Sstevel@tonic-gate 55607c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = (WC_IO_RANGE_PER_WINDOW | 55617c478bd9Sstevel@tonic-gate WC_8BIT | 55627c478bd9Sstevel@tonic-gate WC_16BIT); 55637c478bd9Sstevel@tonic-gate if ((error = cs_find_io_win(sp->socket_num, &iowin_char, 55647c478bd9Sstevel@tonic-gate &imw->number, &imw->size)) != CS_SUCCESS) { 55657c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 55667c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 55677c478bd9Sstevel@tonic-gate } /* cs_find_io_win */ 55687c478bd9Sstevel@tonic-gate } /* if (!WINDOW_AVAILABLE_FOR_IO) */ 55697c478bd9Sstevel@tonic-gate 55707c478bd9Sstevel@tonic-gate set_window.socket = socket_num; 55717c478bd9Sstevel@tonic-gate set_window.window = imw->number; 55727c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 55737c478bd9Sstevel@tonic-gate set_window.base.base = 0; 55747c478bd9Sstevel@tonic-gate set_window.WindowSize = imw->size; 55757c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_16BIT | 55767c478bd9Sstevel@tonic-gate WS_EXACT_MAPIN | WS_IO); 55777c478bd9Sstevel@tonic-gate 55787c478bd9Sstevel@tonic-gate /* XXX - what to d here? XXX */ 55797c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 55807c478bd9Sstevel@tonic-gate 55817c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) { 55827c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, 55837c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 55847c478bd9Sstevel@tonic-gate (IO_DEALLOCATE_WINDOW | 55857c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 55867c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 55877c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 55887c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 55897c478bd9Sstevel@tonic-gate } 55907c478bd9Sstevel@tonic-gate 55917c478bd9Sstevel@tonic-gate imw->handle = set_window.base.handle; 55927c478bd9Sstevel@tonic-gate imw->size = set_window.WindowSize; 55937c478bd9Sstevel@tonic-gate 55947c478bd9Sstevel@tonic-gate /* 55957c478bd9Sstevel@tonic-gate * Check the caller's port requirements to be sure that they 55967c478bd9Sstevel@tonic-gate * fit within our found IO window. 55977c478bd9Sstevel@tonic-gate */ 55987c478bd9Sstevel@tonic-gate if ((ior->BasePort1.base + ior->NumPorts1 + 55997c478bd9Sstevel@tonic-gate ior->BasePort2.base + ior->NumPorts2) > imw->size) { 56007c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56017c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56027c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 56037c478bd9Sstevel@tonic-gate } 56047c478bd9Sstevel@tonic-gate 56057c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(imw->number)) == NULL) { 56067c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56077c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56087c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW) 56097c478bd9Sstevel@tonic-gate } 56107c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_IO); 56117c478bd9Sstevel@tonic-gate 56127c478bd9Sstevel@tonic-gate } /* if (!imw->count) */ 56137c478bd9Sstevel@tonic-gate 56147c478bd9Sstevel@tonic-gate imw->count++; 56157c478bd9Sstevel@tonic-gate 56167c478bd9Sstevel@tonic-gate /* 56177c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 56187c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller. 56197c478bd9Sstevel@tonic-gate */ 56207c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 56217c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort1.handle, 0); 56227c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort1.handle, &offset); 56237c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort1.handle, 56247c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 56257c478bd9Sstevel@tonic-gate 56267c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 56277c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 56287c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort2.handle, 0); 56297c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort2.handle, &offset); 56307c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort2.handle, 56317c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 56327c478bd9Sstevel@tonic-gate } 56337c478bd9Sstevel@tonic-gate 56347c478bd9Sstevel@tonic-gate /* 56357c478bd9Sstevel@tonic-gate * We don't really use these two values if we've got a memory 56367c478bd9Sstevel@tonic-gate * mapped IO window since the assigned window number is stored 56377c478bd9Sstevel@tonic-gate * in imw->number. 56387c478bd9Sstevel@tonic-gate */ 56397c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = imw->number; 56407c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 56417c478bd9Sstevel@tonic-gate 56427c478bd9Sstevel@tonic-gate /* 56437c478bd9Sstevel@tonic-gate * This socket supports only IO port IO windows. 56447c478bd9Sstevel@tonic-gate */ 56457c478bd9Sstevel@tonic-gate } else { 56467c478bd9Sstevel@tonic-gate #else /* USE_IOMMAP_WINDOW */ 56477c478bd9Sstevel@tonic-gate { 56487c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 56497c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 56507c478bd9Sstevel@tonic-gate 56517c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort1.base; 56527c478bd9Sstevel@tonic-gate 56537c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, ior->Attributes1, 56547c478bd9Sstevel@tonic-gate &client->io_alloc.Window1)) != CS_SUCCESS) { 56557c478bd9Sstevel@tonic-gate 56567c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56577c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56587c478bd9Sstevel@tonic-gate return (error); 56597c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(1)) */ 56607c478bd9Sstevel@tonic-gate 56617c478bd9Sstevel@tonic-gate /* 56627c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 56637c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 56647c478bd9Sstevel@tonic-gate */ 56657c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 56667c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 56677c478bd9Sstevel@tonic-gate &baseaddru, 56687c478bd9Sstevel@tonic-gate &ior->NumPorts1, 56697c478bd9Sstevel@tonic-gate ior->IOAddrLines, 56707c478bd9Sstevel@tonic-gate ior->Attributes1)) != 56717c478bd9Sstevel@tonic-gate CS_SUCCESS) { 56727c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5673*c48c3045SToomas Soome NULL, NULL, 0, 56747c478bd9Sstevel@tonic-gate ( 56757c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 56767c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 56777c478bd9Sstevel@tonic-gate 56787c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56797c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56807c478bd9Sstevel@tonic-gate return (error); 56817c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(1)) */ 56827c478bd9Sstevel@tonic-gate 56837c478bd9Sstevel@tonic-gate ior->BasePort1.handle = (acc_handle_t)baseaddru.handle; 56847c478bd9Sstevel@tonic-gate ior->BasePort1.base = baseaddru.base; 56857c478bd9Sstevel@tonic-gate 56867c478bd9Sstevel@tonic-gate /* 56877c478bd9Sstevel@tonic-gate * See if the client wants two IO ranges. 56887c478bd9Sstevel@tonic-gate */ 56897c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 56907c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 56917c478bd9Sstevel@tonic-gate 56927c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort2.base; 56937c478bd9Sstevel@tonic-gate 56947c478bd9Sstevel@tonic-gate /* 56957c478bd9Sstevel@tonic-gate * If we fail to allocate this window, then we must deallocate 56967c478bd9Sstevel@tonic-gate * the previous IO window that is already allocated. 56977c478bd9Sstevel@tonic-gate */ 56987c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, 56997c478bd9Sstevel@tonic-gate ior->Attributes2, 57007c478bd9Sstevel@tonic-gate &client->io_alloc.Window2)) != 57017c478bd9Sstevel@tonic-gate CS_SUCCESS) { 57027c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57037c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 5704*c48c3045SToomas Soome NULL, NULL, 0, 57057c478bd9Sstevel@tonic-gate ( 57067c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57077c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57087c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57097c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57107c478bd9Sstevel@tonic-gate return (error); 57117c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(2)) */ 57127c478bd9Sstevel@tonic-gate /* 57137c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 57147c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 57157c478bd9Sstevel@tonic-gate */ 57167c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 57177c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 57187c478bd9Sstevel@tonic-gate &baseaddru, 57197c478bd9Sstevel@tonic-gate &ior->NumPorts2, 57207c478bd9Sstevel@tonic-gate ior->IOAddrLines, 57217c478bd9Sstevel@tonic-gate ior->Attributes2)) != 57227c478bd9Sstevel@tonic-gate CS_SUCCESS) { 57237c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57247c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 5725*c48c3045SToomas Soome NULL, NULL, 0, 57267c478bd9Sstevel@tonic-gate ( 57277c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57287c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57297c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57307c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 5731*c48c3045SToomas Soome NULL, NULL, 0, 57327c478bd9Sstevel@tonic-gate ( 57337c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57347c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57357c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57367c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57377c478bd9Sstevel@tonic-gate return (error); 57387c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(2)) */ 57397c478bd9Sstevel@tonic-gate 57407c478bd9Sstevel@tonic-gate ior->BasePort2.handle = (acc_handle_t)baseaddru.handle; 57417c478bd9Sstevel@tonic-gate ior->BasePort2.base = baseaddru.base; 57427c478bd9Sstevel@tonic-gate 57437c478bd9Sstevel@tonic-gate } else { 57447c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 57457c478bd9Sstevel@tonic-gate } /* if (ior->NumPorts2) */ 57467c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 57477c478bd9Sstevel@tonic-gate 57487c478bd9Sstevel@tonic-gate /* 57497c478bd9Sstevel@tonic-gate * Save a copy of the client's port information so that we 57507c478bd9Sstevel@tonic-gate * can use it in the RequestConfiguration call. We set 57517c478bd9Sstevel@tonic-gate * the IO window number(s) allocated in the respective 57527c478bd9Sstevel@tonic-gate * section of code, above. 57537c478bd9Sstevel@tonic-gate */ 57547c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.base = ior->BasePort1.base; 57557c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.handle = ior->BasePort1.handle; 57567c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts1 = ior->NumPorts1; 57577c478bd9Sstevel@tonic-gate client->io_alloc.Attributes1 = ior->Attributes1; 57587c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.base = ior->BasePort2.base; 57597c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.handle = ior->BasePort2.handle; 57607c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2 = ior->NumPorts2; 57617c478bd9Sstevel@tonic-gate client->io_alloc.Attributes2 = ior->Attributes2; 57627c478bd9Sstevel@tonic-gate client->io_alloc.IOAddrLines = ior->IOAddrLines; 57637c478bd9Sstevel@tonic-gate 57647c478bd9Sstevel@tonic-gate /* 57657c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIO call. 57667c478bd9Sstevel@tonic-gate */ 57677c478bd9Sstevel@tonic-gate client->flags |= (REQ_IO_DONE | CLIENT_IO_ALLOCATED); 57687c478bd9Sstevel@tonic-gate 57697c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57707c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57717c478bd9Sstevel@tonic-gate 57727c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 57737c478bd9Sstevel@tonic-gate } 57747c478bd9Sstevel@tonic-gate 57757c478bd9Sstevel@tonic-gate /* 57767c478bd9Sstevel@tonic-gate * cs_release_io - releases IO resources allocated by RequestIO; this is 57777c478bd9Sstevel@tonic-gate * ReleaseIO 57787c478bd9Sstevel@tonic-gate * 57797c478bd9Sstevel@tonic-gate * calling: cs_release_io(client_handle_t, io_req_t *) 57807c478bd9Sstevel@tonic-gate * 57817c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources sucessfully deallocated 57827c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 57837c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 57847c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 57857c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 57867c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIO has been done 57877c478bd9Sstevel@tonic-gate */ 57887c478bd9Sstevel@tonic-gate static int 57897c478bd9Sstevel@tonic-gate cs_release_io(client_handle_t client_handle, io_req_t *ior) 57907c478bd9Sstevel@tonic-gate { 57917c478bd9Sstevel@tonic-gate cs_socket_t *sp; 57927c478bd9Sstevel@tonic-gate client_t *client; 57937c478bd9Sstevel@tonic-gate int error; 57947c478bd9Sstevel@tonic-gate int client_lock_acquired; 57957c478bd9Sstevel@tonic-gate uint32_t socket_num; 57967c478bd9Sstevel@tonic-gate 57977c478bd9Sstevel@tonic-gate #ifdef lint 57987c478bd9Sstevel@tonic-gate ior = NULL; 57997c478bd9Sstevel@tonic-gate #endif 58007c478bd9Sstevel@tonic-gate 58017c478bd9Sstevel@tonic-gate /* 58027c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 58037c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 58047c478bd9Sstevel@tonic-gate */ 58057c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 58067c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 58077c478bd9Sstevel@tonic-gate 58087c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 58097c478bd9Sstevel@tonic-gate 58107c478bd9Sstevel@tonic-gate /* 58117c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 58127c478bd9Sstevel@tonic-gate */ 58137c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 58147c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 58157c478bd9Sstevel@tonic-gate 58167c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 58177c478bd9Sstevel@tonic-gate 58187c478bd9Sstevel@tonic-gate /* 58197c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 58207c478bd9Sstevel@tonic-gate */ 58217c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 58227c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58237c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58247c478bd9Sstevel@tonic-gate return (error); 58257c478bd9Sstevel@tonic-gate } 58267c478bd9Sstevel@tonic-gate 58277c478bd9Sstevel@tonic-gate /* 58287c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 58297c478bd9Sstevel@tonic-gate * this call. 58307c478bd9Sstevel@tonic-gate */ 58317c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 58327c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58337c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58347c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 58357c478bd9Sstevel@tonic-gate } 58367c478bd9Sstevel@tonic-gate 58377c478bd9Sstevel@tonic-gate /* 58387c478bd9Sstevel@tonic-gate * If RequestIO has not been done, we don't allow this call. 58397c478bd9Sstevel@tonic-gate */ 58407c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IO_DONE)) { 58417c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58427c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58437c478bd9Sstevel@tonic-gate return (CS_IN_USE); 58447c478bd9Sstevel@tonic-gate } 58457c478bd9Sstevel@tonic-gate 58467c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 58477c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 58487c478bd9Sstevel@tonic-gate 58497c478bd9Sstevel@tonic-gate #ifdef XXX 58507c478bd9Sstevel@tonic-gate /* 58517c478bd9Sstevel@tonic-gate * Check the passed IO allocation with the stored allocation; if 58527c478bd9Sstevel@tonic-gate * they don't match, then return an error. 58537c478bd9Sstevel@tonic-gate */ 58547c478bd9Sstevel@tonic-gate if ((client->io_alloc.BasePort1 != ior->BasePort1) || 58557c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts1 != ior->NumPorts1) || 58567c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes1 != ior->Attributes1) || 58577c478bd9Sstevel@tonic-gate (client->io_alloc.BasePort2 != ior->BasePort2) || 58587c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts2 != ior->NumPorts2) || 58597c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes2 != ior->Attributes2) || 58607c478bd9Sstevel@tonic-gate (client->io_alloc.IOAddrLines != ior->IOAddrLines)) { 58617c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58627c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58637c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 58647c478bd9Sstevel@tonic-gate } 58657c478bd9Sstevel@tonic-gate #endif 58667c478bd9Sstevel@tonic-gate 58677c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 58687c478bd9Sstevel@tonic-gate /* 58697c478bd9Sstevel@tonic-gate * The code diverges here depending on if this socket supports 58707c478bd9Sstevel@tonic-gate * memory mapped IO windows or not. See comments in the 58717c478bd9Sstevel@tonic-gate * cs_request_io function for a description of what's 58727c478bd9Sstevel@tonic-gate * going on here. 58737c478bd9Sstevel@tonic-gate */ 58747c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 58757c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 58767c478bd9Sstevel@tonic-gate 58777c478bd9Sstevel@tonic-gate /* 58787c478bd9Sstevel@tonic-gate * We should never see this; if we do, it's an internal 58797c478bd9Sstevel@tonic-gate * consistency error. 58807c478bd9Sstevel@tonic-gate */ 58817c478bd9Sstevel@tonic-gate if (!imw->count) { 58827c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_io: socket %d !imw->count\n", 58837c478bd9Sstevel@tonic-gate sp->socket_num); 58847c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58857c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58867c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 58877c478bd9Sstevel@tonic-gate } 58887c478bd9Sstevel@tonic-gate 58897c478bd9Sstevel@tonic-gate /* 58907c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 58917c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller, 58927c478bd9Sstevel@tonic-gate * so it's OK to unconditionally free the handle here. 58937c478bd9Sstevel@tonic-gate */ 58947c478bd9Sstevel@tonic-gate csx_FreeHandle(&ior->BasePort1.handle); 58957c478bd9Sstevel@tonic-gate 58967c478bd9Sstevel@tonic-gate /* 58977c478bd9Sstevel@tonic-gate * If the IO window referance count is zero, then deallocate 58987c478bd9Sstevel@tonic-gate * and disable this window. 58997c478bd9Sstevel@tonic-gate */ 59007c478bd9Sstevel@tonic-gate if (!--(imw->count)) { 59017c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, NULL, 59027c478bd9Sstevel@tonic-gate NULL, NULL, 59037c478bd9Sstevel@tonic-gate ( 59047c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59057c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59067c478bd9Sstevel@tonic-gate } /* if (imw->count) */ 59077c478bd9Sstevel@tonic-gate } else { 59087c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 59097c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 5910*c48c3045SToomas Soome NULL, NULL, 0, 59117c478bd9Sstevel@tonic-gate ( 59127c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59137c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59147c478bd9Sstevel@tonic-gate if (client->io_alloc.Window2 != PCMCIA_MAX_WINDOWS) 59157c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window2, 5916*c48c3045SToomas Soome NULL, NULL, 0, 59177c478bd9Sstevel@tonic-gate ( 59187c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59197c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59207c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 59217c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 59227c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 59237c478bd9Sstevel@tonic-gate 59247c478bd9Sstevel@tonic-gate /* 59257c478bd9Sstevel@tonic-gate * Mark the client as not having any IO resources allocated. 59267c478bd9Sstevel@tonic-gate */ 59277c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IO_DONE | CLIENT_IO_ALLOCATED); 59287c478bd9Sstevel@tonic-gate 59297c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 59307c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 59317c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 59327c478bd9Sstevel@tonic-gate } 59337c478bd9Sstevel@tonic-gate 59347c478bd9Sstevel@tonic-gate /* 59357c478bd9Sstevel@tonic-gate * cs_find_io_win - finds an IO window that matches the parameters specified 59367c478bd9Sstevel@tonic-gate * in the flags argument 59377c478bd9Sstevel@tonic-gate * 59387c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for IO window on 59397c478bd9Sstevel@tonic-gate * *iwc - other window characteristics to match 59407c478bd9Sstevel@tonic-gate * *assigned_window - pointer to where we return the assigned 59417c478bd9Sstevel@tonic-gate * window number if we found a window or 59427c478bd9Sstevel@tonic-gate * undefined otherwise 59437c478bd9Sstevel@tonic-gate * *size - if non-NULL, the found window size will be stored here 59447c478bd9Sstevel@tonic-gate * 59457c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO window found 59467c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 59477c478bd9Sstevel@tonic-gate */ 59487c478bd9Sstevel@tonic-gate static int 59497c478bd9Sstevel@tonic-gate cs_find_io_win(uint32_t sn, iowin_char_t *iwc, uint32_t *assigned_window, 59507c478bd9Sstevel@tonic-gate uint32_t *size) 59517c478bd9Sstevel@tonic-gate { 59527c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 59537c478bd9Sstevel@tonic-gate unsigned wn; 59547c478bd9Sstevel@tonic-gate 59557c478bd9Sstevel@tonic-gate iw = &inquire_window; 59567c478bd9Sstevel@tonic-gate 59577c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 59587c478bd9Sstevel@tonic-gate iowin_char_t *iowc; 59597c478bd9Sstevel@tonic-gate cs_window_t *cw; 59607c478bd9Sstevel@tonic-gate 59617c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 59627c478bd9Sstevel@tonic-gate 59637c478bd9Sstevel@tonic-gate iw->window = wn; 59647c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 59657c478bd9Sstevel@tonic-gate 59667c478bd9Sstevel@tonic-gate iowc = &iw->iowin_char; 59677c478bd9Sstevel@tonic-gate 59687c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 59697c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_IO(cw) && 59707c478bd9Sstevel@tonic-gate (iw->WndCaps & WC_IO) && 59717c478bd9Sstevel@tonic-gate ((iowc->IOWndCaps & iwc->IOWndCaps) == iwc->IOWndCaps)) { 59727c478bd9Sstevel@tonic-gate 59737c478bd9Sstevel@tonic-gate *assigned_window = wn; 59747c478bd9Sstevel@tonic-gate 59757c478bd9Sstevel@tonic-gate if (size) 59767c478bd9Sstevel@tonic-gate *size = iw->iowin_char.ReqGran; 59777c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 59787c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 59797c478bd9Sstevel@tonic-gate } /* cs_get_wp */ 59807c478bd9Sstevel@tonic-gate } /* for (wn) */ 59817c478bd9Sstevel@tonic-gate 59827c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 59837c478bd9Sstevel@tonic-gate } 59847c478bd9Sstevel@tonic-gate 59857c478bd9Sstevel@tonic-gate /* 59867c478bd9Sstevel@tonic-gate * cs_allocate_io_win - finds and allocates an IO window 59877c478bd9Sstevel@tonic-gate * 59887c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for window on 59897c478bd9Sstevel@tonic-gate * Attributes - window attributes in io_req_t.Attributes format 59907c478bd9Sstevel@tonic-gate * *assigned_window - pointer to return assigned window number 59917c478bd9Sstevel@tonic-gate * 59927c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - IO window found and allocated 59937c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if cs_find_io_win couldn't find a 59947c478bd9Sstevel@tonic-gate * window that matches the passed criteria 59957c478bd9Sstevel@tonic-gate * 59967c478bd9Sstevel@tonic-gate * Note: This fucntion will find and allocate an IO window. The caller is 59977c478bd9Sstevel@tonic-gate * responsible for deallocating the window. 59987c478bd9Sstevel@tonic-gate */ 59997c478bd9Sstevel@tonic-gate static int 60007c478bd9Sstevel@tonic-gate cs_allocate_io_win(uint32_t sn, uint32_t Attributes, uint32_t *assigned_window) 60017c478bd9Sstevel@tonic-gate { 60027c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 60037c478bd9Sstevel@tonic-gate cs_window_t *cw; 60047c478bd9Sstevel@tonic-gate 60057c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = 60067c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WC_16BIT:WC_8BIT); 60077c478bd9Sstevel@tonic-gate 60087c478bd9Sstevel@tonic-gate if (cs_find_io_win(sn, &iowin_char, assigned_window, NULL) == 60097c478bd9Sstevel@tonic-gate CS_SUCCESS) { 60107c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(*assigned_window)) == NULL) 60117c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 60127c478bd9Sstevel@tonic-gate 60137c478bd9Sstevel@tonic-gate cw->state = (cw->state & CW_WINDOW_VALID) | (CW_ALLOCATED | CW_IO); 60147c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 60157c478bd9Sstevel@tonic-gate } 60167c478bd9Sstevel@tonic-gate 60177c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 60187c478bd9Sstevel@tonic-gate } 60197c478bd9Sstevel@tonic-gate 60207c478bd9Sstevel@tonic-gate /* 60217c478bd9Sstevel@tonic-gate * cs_setup_io_win - setup and destroy an IO window 60227c478bd9Sstevel@tonic-gate * 60237c478bd9Sstevel@tonic-gate * calling: sn - socket number 60247c478bd9Sstevel@tonic-gate * wn - window number 60257c478bd9Sstevel@tonic-gate * XXX Base - pointer to XXX 60267c478bd9Sstevel@tonic-gate * *NumPorts - pointer to number of allocated ports to return 60277c478bd9Sstevel@tonic-gate * IOAddrLines - number of IO address lines decoded by this card 60287c478bd9Sstevel@tonic-gate * Attributes - either io_req_t attributes, or a combination of 60297c478bd9Sstevel@tonic-gate * the following flags: 60307c478bd9Sstevel@tonic-gate * IO_DEALLOCATE_WINDOW - deallocate the window 60317c478bd9Sstevel@tonic-gate * IO_DISABLE_WINDOW - disable the window 60327c478bd9Sstevel@tonic-gate * When either of these two flags are set, *Base 60337c478bd9Sstevel@tonic-gate * and NumPorts should be NULL. 60347c478bd9Sstevel@tonic-gate * 60357c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if no failure 60367c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if error while trying to configure window 60377c478bd9Sstevel@tonic-gate * 60387c478bd9Sstevel@tonic-gate * Note: We use the IOAddrLines value to determine what base address to pass 60397c478bd9Sstevel@tonic-gate * to Socket Services. 60407c478bd9Sstevel@tonic-gate */ 60417c478bd9Sstevel@tonic-gate static int 60427c478bd9Sstevel@tonic-gate cs_setup_io_win(uint32_t sn, uint32_t wn, baseaddru_t *Base, uint32_t *NumPorts, 60437c478bd9Sstevel@tonic-gate uint32_t IOAddrLines, uint32_t Attributes) 60447c478bd9Sstevel@tonic-gate { 60457c478bd9Sstevel@tonic-gate set_window_t set_window; 60467c478bd9Sstevel@tonic-gate 60477c478bd9Sstevel@tonic-gate if (Attributes & (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW)) { 60487c478bd9Sstevel@tonic-gate 60497c478bd9Sstevel@tonic-gate if (Attributes & IO_DEALLOCATE_WINDOW) { 60507c478bd9Sstevel@tonic-gate cs_window_t *cw; 60517c478bd9Sstevel@tonic-gate 60527c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) == NULL) 60537c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 60547c478bd9Sstevel@tonic-gate cw->state &= CW_WINDOW_VALID; 60557c478bd9Sstevel@tonic-gate 60567c478bd9Sstevel@tonic-gate } /* IO_DEALLOCATE_WINDOW */ 60577c478bd9Sstevel@tonic-gate 60587c478bd9Sstevel@tonic-gate if (Attributes & IO_DISABLE_WINDOW) { 60597c478bd9Sstevel@tonic-gate get_window_t get_window; 60607c478bd9Sstevel@tonic-gate 60617c478bd9Sstevel@tonic-gate get_window.window = wn; 60627c478bd9Sstevel@tonic-gate 60637c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &get_window); 60647c478bd9Sstevel@tonic-gate 60657c478bd9Sstevel@tonic-gate set_window.socket = get_window.socket; 60667c478bd9Sstevel@tonic-gate set_window.window = get_window.window; 60677c478bd9Sstevel@tonic-gate set_window.speed = get_window.speed; 60687c478bd9Sstevel@tonic-gate set_window.base = 0; 60697c478bd9Sstevel@tonic-gate set_window.WindowSize = get_window.size; 60707c478bd9Sstevel@tonic-gate set_window.state = get_window.state & ~WS_ENABLED; 60717c478bd9Sstevel@tonic-gate 60727c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 60737c478bd9Sstevel@tonic-gate 60747c478bd9Sstevel@tonic-gate SocketServices(SS_SetWindow, &set_window); 60757c478bd9Sstevel@tonic-gate } /* IO_DISABLE_WINDOW */ 60767c478bd9Sstevel@tonic-gate 60777c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 60787c478bd9Sstevel@tonic-gate 60797c478bd9Sstevel@tonic-gate } /* if (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW) */ 60807c478bd9Sstevel@tonic-gate 60817c478bd9Sstevel@tonic-gate /* 60827c478bd9Sstevel@tonic-gate * See if we can allow Socket Services to select the base address 60837c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 60847c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 60857c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 60867c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 60877c478bd9Sstevel@tonic-gate * XXX - Is this really correct in all cases? 60887c478bd9Sstevel@tonic-gate */ 60897c478bd9Sstevel@tonic-gate if (!IOAddrLines) 60907c478bd9Sstevel@tonic-gate Base->base = 0; 60917c478bd9Sstevel@tonic-gate else 60927c478bd9Sstevel@tonic-gate Base->base = IOADDR_FROBNITZ(Base->base, IOAddrLines); 60937c478bd9Sstevel@tonic-gate 60947c478bd9Sstevel@tonic-gate set_window.socket = sn; 60957c478bd9Sstevel@tonic-gate set_window.window = wn; 60967c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 60977c478bd9Sstevel@tonic-gate set_window.base = Base->base; 60987c478bd9Sstevel@tonic-gate set_window.WindowSize = *NumPorts; 60997c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_IO | 61007c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WS_16BIT:0)); 61017c478bd9Sstevel@tonic-gate 61027c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 61037c478bd9Sstevel@tonic-gate 61047c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) 61057c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 61067c478bd9Sstevel@tonic-gate 61077c478bd9Sstevel@tonic-gate Base->base = set_window.base; 61087c478bd9Sstevel@tonic-gate Base->handle = set_window.handle; 61097c478bd9Sstevel@tonic-gate *NumPorts = set_window.WindowSize; 61107c478bd9Sstevel@tonic-gate 61117c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 61127c478bd9Sstevel@tonic-gate } 61137c478bd9Sstevel@tonic-gate 61147c478bd9Sstevel@tonic-gate /* 61157c478bd9Sstevel@tonic-gate * ==== IRQ handling functions ==== 61167c478bd9Sstevel@tonic-gate */ 61177c478bd9Sstevel@tonic-gate 61187c478bd9Sstevel@tonic-gate /* 61197c478bd9Sstevel@tonic-gate * cs_request_irq - add's client's IRQ handler; supports RequestIRQ 61207c478bd9Sstevel@tonic-gate * 61217c478bd9Sstevel@tonic-gate * calling: irq_req_t.Attributes - must have the IRQ_TYPE_EXCLUSIVE 61227c478bd9Sstevel@tonic-gate * flag set, and all other flags clear, or 61237c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE will be returned 61247c478bd9Sstevel@tonic-gate * 61257c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources available for client 61267c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be allocated 61277c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 61287c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 61297c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 61307c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 61317c478bd9Sstevel@tonic-gate * flags are set 61327c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 61337c478bd9Sstevel@tonic-gate * already been done 61347c478bd9Sstevel@tonic-gate * CS_IN_USE - IRQ ports already in use or function has 61357c478bd9Sstevel@tonic-gate * already been called 61367c478bd9Sstevel@tonic-gate * 61377c478bd9Sstevel@tonic-gate * Note: We only allow level-mode interrupts. 61387c478bd9Sstevel@tonic-gate */ 61397c478bd9Sstevel@tonic-gate static int 61407c478bd9Sstevel@tonic-gate cs_request_irq(client_handle_t client_handle, irq_req_t *irqr) 61417c478bd9Sstevel@tonic-gate { 61427c478bd9Sstevel@tonic-gate cs_socket_t *sp; 61437c478bd9Sstevel@tonic-gate client_t *client; 61447c478bd9Sstevel@tonic-gate set_irq_handler_t set_irq_handler; 61457c478bd9Sstevel@tonic-gate int error; 61467c478bd9Sstevel@tonic-gate int client_lock_acquired; 61477c478bd9Sstevel@tonic-gate 61487c478bd9Sstevel@tonic-gate /* 61497c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 61507c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 61517c478bd9Sstevel@tonic-gate */ 61527c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 61537c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 61547c478bd9Sstevel@tonic-gate 61557c478bd9Sstevel@tonic-gate /* 61567c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 61577c478bd9Sstevel@tonic-gate */ 61587c478bd9Sstevel@tonic-gate if ((irqr->Attributes & (IRQ_TYPE_TIME | IRQ_TYPE_DYNAMIC_SHARING | 61597c478bd9Sstevel@tonic-gate IRQ_FIRST_SHARED | IRQ_PULSE_ALLOCATED | 61607c478bd9Sstevel@tonic-gate IRQ_FORCED_PULSE)) || 61617c478bd9Sstevel@tonic-gate !(irqr->Attributes & IRQ_TYPE_EXCLUSIVE)) 61627c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 61637c478bd9Sstevel@tonic-gate 61647c478bd9Sstevel@tonic-gate /* 61657c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 61667c478bd9Sstevel@tonic-gate */ 61677c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 61687c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 61697c478bd9Sstevel@tonic-gate 61707c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 61717c478bd9Sstevel@tonic-gate 61727c478bd9Sstevel@tonic-gate /* 61737c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 61747c478bd9Sstevel@tonic-gate */ 61757c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 61767c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61777c478bd9Sstevel@tonic-gate return (error); 61787c478bd9Sstevel@tonic-gate } 61797c478bd9Sstevel@tonic-gate 61807c478bd9Sstevel@tonic-gate /* 61817c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 61827c478bd9Sstevel@tonic-gate * this call. 61837c478bd9Sstevel@tonic-gate */ 61847c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 61857c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61867c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 61877c478bd9Sstevel@tonic-gate } 61887c478bd9Sstevel@tonic-gate 61897c478bd9Sstevel@tonic-gate /* 61907c478bd9Sstevel@tonic-gate * If RequestIRQ has already been done, we don't allow this call. 61917c478bd9Sstevel@tonic-gate */ 61927c478bd9Sstevel@tonic-gate if (client->flags & REQ_IRQ_DONE) { 61937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61947c478bd9Sstevel@tonic-gate return (CS_IN_USE); 61957c478bd9Sstevel@tonic-gate } 61967c478bd9Sstevel@tonic-gate 61977c478bd9Sstevel@tonic-gate /* 61987c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 61997c478bd9Sstevel@tonic-gate * for this client, then return an error. 62007c478bd9Sstevel@tonic-gate */ 62017c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 62027c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62037c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 62047c478bd9Sstevel@tonic-gate } 62057c478bd9Sstevel@tonic-gate 62067c478bd9Sstevel@tonic-gate /* 62077c478bd9Sstevel@tonic-gate * Set up the parameters and ask Socket Services to give us an IRQ 62087c478bd9Sstevel@tonic-gate * for this client. We don't really do much, since the IRQ 62097c478bd9Sstevel@tonic-gate * resources are managed by SS and the kernel. We also don't 62107c478bd9Sstevel@tonic-gate * care which IRQ level we are given. 62117c478bd9Sstevel@tonic-gate */ 62127c478bd9Sstevel@tonic-gate set_irq_handler.socket = 62137c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 62147c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 62157c478bd9Sstevel@tonic-gate set_irq_handler.irq = IRQ_ANY; 62167c478bd9Sstevel@tonic-gate 62177c478bd9Sstevel@tonic-gate set_irq_handler.handler_id = client_handle; 62187c478bd9Sstevel@tonic-gate set_irq_handler.handler = (f_t *)irqr->irq_handler; 62197c478bd9Sstevel@tonic-gate set_irq_handler.arg1 = irqr->irq_handler_arg; 62207c478bd9Sstevel@tonic-gate set_irq_handler.arg2 = NULL; 62217c478bd9Sstevel@tonic-gate 62227c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_SetIRQHandler, 62237c478bd9Sstevel@tonic-gate &set_irq_handler)) != SUCCESS) { 62247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62257c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 62267c478bd9Sstevel@tonic-gate } 62277c478bd9Sstevel@tonic-gate 62287c478bd9Sstevel@tonic-gate irqr->iblk_cookie = set_irq_handler.iblk_cookie; 62297c478bd9Sstevel@tonic-gate irqr->idev_cookie = set_irq_handler.idev_cookie; 62307c478bd9Sstevel@tonic-gate 62317c478bd9Sstevel@tonic-gate /* 62327c478bd9Sstevel@tonic-gate * Save the allocated IRQ information for this client. 62337c478bd9Sstevel@tonic-gate */ 62347c478bd9Sstevel@tonic-gate client->irq_alloc.Attributes = irqr->Attributes; 62357c478bd9Sstevel@tonic-gate client->irq_alloc.irq = set_irq_handler.irq; 62367c478bd9Sstevel@tonic-gate client->irq_alloc.handler_id = set_irq_handler.handler_id; 62377c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler = (f_t *)set_irq_handler.handler; 62387c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg1 = set_irq_handler.arg1; 62397c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg2 = set_irq_handler.arg2; 62407c478bd9Sstevel@tonic-gate 62417c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 62427c478bd9Sstevel@tonic-gate if (cs_debug > 0) 62437c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_irq: socket %d irqr->Attributes 0x%x " 62447c478bd9Sstevel@tonic-gate "set_irq_handler.irq 0x%x\n", 62457c478bd9Sstevel@tonic-gate sp->socket_num, 62467c478bd9Sstevel@tonic-gate (int)irqr->Attributes, 62477c478bd9Sstevel@tonic-gate set_irq_handler.irq); 62487c478bd9Sstevel@tonic-gate #endif 62497c478bd9Sstevel@tonic-gate 62507c478bd9Sstevel@tonic-gate /* 62517c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIRQ call. 62527c478bd9Sstevel@tonic-gate */ 62537c478bd9Sstevel@tonic-gate client->flags |= (REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 62547c478bd9Sstevel@tonic-gate 62557c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62567c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 62577c478bd9Sstevel@tonic-gate } 62587c478bd9Sstevel@tonic-gate 62597c478bd9Sstevel@tonic-gate /* 62607c478bd9Sstevel@tonic-gate * cs_release_irq - releases IRQ resources allocated by RequestIRQ; this is 62617c478bd9Sstevel@tonic-gate * ReleaseIRQ 62627c478bd9Sstevel@tonic-gate * 62637c478bd9Sstevel@tonic-gate * calling: cs_release_irq(client_handle_t, irq_req_t *) 62647c478bd9Sstevel@tonic-gate * 62657c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources sucessfully deallocated 62667c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be deallocated 62677c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 62687c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 62697c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 62707c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 62717c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIRQ has been done 62727c478bd9Sstevel@tonic-gate */ 62737c478bd9Sstevel@tonic-gate static int 62747c478bd9Sstevel@tonic-gate cs_release_irq(client_handle_t client_handle, irq_req_t *irqr) 62757c478bd9Sstevel@tonic-gate { 62767c478bd9Sstevel@tonic-gate cs_socket_t *sp; 62777c478bd9Sstevel@tonic-gate client_t *client; 62787c478bd9Sstevel@tonic-gate clear_irq_handler_t clear_irq_handler; 62797c478bd9Sstevel@tonic-gate int error; 62807c478bd9Sstevel@tonic-gate int client_lock_acquired; 62817c478bd9Sstevel@tonic-gate 62827c478bd9Sstevel@tonic-gate #ifdef lint 62837c478bd9Sstevel@tonic-gate irqr = NULL; 62847c478bd9Sstevel@tonic-gate #endif 62857c478bd9Sstevel@tonic-gate 62867c478bd9Sstevel@tonic-gate /* 62877c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 62887c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 62897c478bd9Sstevel@tonic-gate */ 62907c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 62917c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 62927c478bd9Sstevel@tonic-gate 62937c478bd9Sstevel@tonic-gate /* 62947c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 62957c478bd9Sstevel@tonic-gate */ 62967c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 62977c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 62987c478bd9Sstevel@tonic-gate 62997c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 63007c478bd9Sstevel@tonic-gate 63017c478bd9Sstevel@tonic-gate /* 63027c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 63037c478bd9Sstevel@tonic-gate */ 63047c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 63057c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63067c478bd9Sstevel@tonic-gate return (error); 63077c478bd9Sstevel@tonic-gate } 63087c478bd9Sstevel@tonic-gate 63097c478bd9Sstevel@tonic-gate /* 63107c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 63117c478bd9Sstevel@tonic-gate * this call. 63127c478bd9Sstevel@tonic-gate */ 63137c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 63147c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63157c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 63167c478bd9Sstevel@tonic-gate } 63177c478bd9Sstevel@tonic-gate 63187c478bd9Sstevel@tonic-gate /* 63197c478bd9Sstevel@tonic-gate * If RequestIRQ has not been done, we don't allow this call. 63207c478bd9Sstevel@tonic-gate */ 63217c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IRQ_DONE)) { 63227c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63237c478bd9Sstevel@tonic-gate return (CS_IN_USE); 63247c478bd9Sstevel@tonic-gate } 63257c478bd9Sstevel@tonic-gate 63267c478bd9Sstevel@tonic-gate /* 63277c478bd9Sstevel@tonic-gate * Tell Socket Services that we want to deregister this client's 63287c478bd9Sstevel@tonic-gate * IRQ handler. 63297c478bd9Sstevel@tonic-gate */ 63307c478bd9Sstevel@tonic-gate clear_irq_handler.socket = 63317c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 63327c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 63337c478bd9Sstevel@tonic-gate clear_irq_handler.handler_id = client->irq_alloc.handler_id; 63347c478bd9Sstevel@tonic-gate clear_irq_handler.handler = (f_t *)client->irq_alloc.irq_handler; 63357c478bd9Sstevel@tonic-gate 63367c478bd9Sstevel@tonic-gate /* 63377c478bd9Sstevel@tonic-gate * At this point, we should never fail this SS call; if we do, it 63387c478bd9Sstevel@tonic-gate * means that there is an internal consistancy error in either 63397c478bd9Sstevel@tonic-gate * Card Services or Socket Services. 63407c478bd9Sstevel@tonic-gate */ 63417c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_ClearIRQHandler, &clear_irq_handler)) != 63427c478bd9Sstevel@tonic-gate SUCCESS) { 63437c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63447c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 63457c478bd9Sstevel@tonic-gate } 63467c478bd9Sstevel@tonic-gate 63477c478bd9Sstevel@tonic-gate /* 63487c478bd9Sstevel@tonic-gate * Mark the client as not having any IRQ resources allocated. 63497c478bd9Sstevel@tonic-gate */ 63507c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 63517c478bd9Sstevel@tonic-gate 63527c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63537c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 63547c478bd9Sstevel@tonic-gate } 63557c478bd9Sstevel@tonic-gate 63567c478bd9Sstevel@tonic-gate /* 63577c478bd9Sstevel@tonic-gate * ==== configuration handling functions ==== 63587c478bd9Sstevel@tonic-gate */ 63597c478bd9Sstevel@tonic-gate 63607c478bd9Sstevel@tonic-gate /* 63617c478bd9Sstevel@tonic-gate * cs_request_configuration - sets up socket and card configuration on behalf 63627c478bd9Sstevel@tonic-gate * of the client; this is RequestConfiguration 63637c478bd9Sstevel@tonic-gate * 63647c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully set 63657c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 63667c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 63677c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 63687c478bd9Sstevel@tonic-gate * are set 63697c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if the socket doesn't support a mem and IO 63707c478bd9Sstevel@tonic-gate * interface (SOCKET_INTERFACE_MEMORY_AND_IO set) 63717c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 63727c478bd9Sstevel@tonic-gate * already been done 63737c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 63747c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 63757c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 63767c478bd9Sstevel@tonic-gate * 63777c478bd9Sstevel@tonic-gate * Bug ID: 1193637 - Card Services RequestConfiguration does not conform 63787c478bd9Sstevel@tonic-gate * to PCMCIA standard 63797c478bd9Sstevel@tonic-gate * We allow clients to do a RequestConfiguration even if they haven't 63807c478bd9Sstevel@tonic-gate * done a RequestIO or RequestIRQ. 63817c478bd9Sstevel@tonic-gate */ 63827c478bd9Sstevel@tonic-gate static int 63837c478bd9Sstevel@tonic-gate cs_request_configuration(client_handle_t client_handle, config_req_t *cr) 63847c478bd9Sstevel@tonic-gate { 63857c478bd9Sstevel@tonic-gate cs_socket_t *sp; 63867c478bd9Sstevel@tonic-gate client_t *client; 63877c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 63887c478bd9Sstevel@tonic-gate set_socket_t set_socket; 63897c478bd9Sstevel@tonic-gate get_socket_t get_socket; 63907c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 63917c478bd9Sstevel@tonic-gate int error; 63927c478bd9Sstevel@tonic-gate uint32_t newoffset; 63937c478bd9Sstevel@tonic-gate int client_lock_acquired; 63947c478bd9Sstevel@tonic-gate 63957c478bd9Sstevel@tonic-gate /* 63967c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 63977c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 63987c478bd9Sstevel@tonic-gate */ 63997c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 64007c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 64017c478bd9Sstevel@tonic-gate 64027c478bd9Sstevel@tonic-gate #ifdef XXX 64037c478bd9Sstevel@tonic-gate /* 64047c478bd9Sstevel@tonic-gate * If the client specifies Vcc = 0 and any non-zero value for 64057c478bd9Sstevel@tonic-gate * either of the Vpp members, that's an illegal condition. 64067c478bd9Sstevel@tonic-gate */ 64077c478bd9Sstevel@tonic-gate if (!(cr->Vcc) && (cr->Vpp1 || cr->Vpp2)) 64087c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 64097c478bd9Sstevel@tonic-gate #endif 64107c478bd9Sstevel@tonic-gate 64117c478bd9Sstevel@tonic-gate /* 64127c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 64137c478bd9Sstevel@tonic-gate */ 64147c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 64157c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64167c478bd9Sstevel@tonic-gate 64177c478bd9Sstevel@tonic-gate /* 64187c478bd9Sstevel@tonic-gate * If the client is asking for a memory and IO interface on this 64197c478bd9Sstevel@tonic-gate * socket, then check the socket capabilities to be sure that 64207c478bd9Sstevel@tonic-gate * this socket supports this configuration. 64217c478bd9Sstevel@tonic-gate */ 64227c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) { 64237c478bd9Sstevel@tonic-gate inquire_socket_t inquire_socket; 64247c478bd9Sstevel@tonic-gate 64257c478bd9Sstevel@tonic-gate inquire_socket.socket = sp->socket_num; 64267c478bd9Sstevel@tonic-gate 64277c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireSocket, &inquire_socket) != SUCCESS) 64287c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64297c478bd9Sstevel@tonic-gate 64307c478bd9Sstevel@tonic-gate if (!(inquire_socket.SocketCaps & IF_IO)) 64317c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 64327c478bd9Sstevel@tonic-gate 64337c478bd9Sstevel@tonic-gate } /* if (SOCKET_INTERFACE_MEMORY_AND_IO) */ 64347c478bd9Sstevel@tonic-gate 64357c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 64367c478bd9Sstevel@tonic-gate 64377c478bd9Sstevel@tonic-gate /* 64387c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 64397c478bd9Sstevel@tonic-gate */ 64407c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 64417c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64427c478bd9Sstevel@tonic-gate return (error); 64437c478bd9Sstevel@tonic-gate } 64447c478bd9Sstevel@tonic-gate 64457c478bd9Sstevel@tonic-gate /* 64467c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 64477c478bd9Sstevel@tonic-gate * this call. 64487c478bd9Sstevel@tonic-gate */ 64497c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 64507c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64517c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 64527c478bd9Sstevel@tonic-gate } 64537c478bd9Sstevel@tonic-gate 64547c478bd9Sstevel@tonic-gate /* 64557c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 64567c478bd9Sstevel@tonic-gate * for this client, then return an error. 64577c478bd9Sstevel@tonic-gate */ 64587c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 64597c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64607c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 64617c478bd9Sstevel@tonic-gate } 64627c478bd9Sstevel@tonic-gate 64637c478bd9Sstevel@tonic-gate /* 64647c478bd9Sstevel@tonic-gate * At this point, most of the client's calling parameters have been 64657c478bd9Sstevel@tonic-gate * validated, so we can go ahead and configure the socket and 64667c478bd9Sstevel@tonic-gate * the card. 64677c478bd9Sstevel@tonic-gate */ 64687c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 64697c478bd9Sstevel@tonic-gate 64707c478bd9Sstevel@tonic-gate /* 64717c478bd9Sstevel@tonic-gate * Configure the socket with the interface type and voltages requested 64727c478bd9Sstevel@tonic-gate * by the client. 64737c478bd9Sstevel@tonic-gate */ 64747c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 64757c478bd9Sstevel@tonic-gate 64767c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 64777c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 64787c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64797c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64807c478bd9Sstevel@tonic-gate } 64817c478bd9Sstevel@tonic-gate 64827c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 64837c478bd9Sstevel@tonic-gate if (cs_debug > 0) 64847c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d " 64857c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 64867c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 64877c478bd9Sstevel@tonic-gate sp->socket_num, 64887c478bd9Sstevel@tonic-gate (int)client->irq_alloc.irq, 64897c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 64907c478bd9Sstevel@tonic-gate #endif 64917c478bd9Sstevel@tonic-gate 64927c478bd9Sstevel@tonic-gate bzero(&set_socket, sizeof (set_socket)); 64937c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 64947c478bd9Sstevel@tonic-gate set_socket.IREQRouting = client->irq_alloc.irq & ~IRQ_ENABLE; 64957c478bd9Sstevel@tonic-gate 64967c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 64977c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 64987c478bd9Sstevel@tonic-gate 64997c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vcc, VCC, 65007c478bd9Sstevel@tonic-gate &set_socket.VccLevel) != CS_SUCCESS) { 65017c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65027c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65037c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 65047c478bd9Sstevel@tonic-gate } 65057c478bd9Sstevel@tonic-gate 65067c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp1, VPP1, 65077c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 65087c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65097c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65107c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 65117c478bd9Sstevel@tonic-gate } 65127c478bd9Sstevel@tonic-gate 65137c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp2, VPP2, 65147c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 65157c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65167c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65177c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 65187c478bd9Sstevel@tonic-gate } 65197c478bd9Sstevel@tonic-gate 65207c478bd9Sstevel@tonic-gate if (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) 65217c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 65227c478bd9Sstevel@tonic-gate else { 65237c478bd9Sstevel@tonic-gate set_socket.IFType = IF_IO; 65247c478bd9Sstevel@tonic-gate 65257c478bd9Sstevel@tonic-gate /* 65267c478bd9Sstevel@tonic-gate * The Cirrus Logic PD6710/672X/others? adapters will write 65277c478bd9Sstevel@tonic-gate * protect the CIS if the socket is in MEMORY mode and the 65287c478bd9Sstevel@tonic-gate * WP/IOCS16 pin is true. When this happens, the CIS registers 65297c478bd9Sstevel@tonic-gate * will fail to be written. Go ahead and set the socket, 65307c478bd9Sstevel@tonic-gate * even though the event mask isn't complete yet, so we can 65317c478bd9Sstevel@tonic-gate * configure the adapter. Afterwards, set the socket again 65327c478bd9Sstevel@tonic-gate * to make sure the event mask is correct. 65337c478bd9Sstevel@tonic-gate */ 65347c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 65357c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 65367c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65377c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65387c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 65397c478bd9Sstevel@tonic-gate } 65407c478bd9Sstevel@tonic-gate } 65417c478bd9Sstevel@tonic-gate 65427c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 65437c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 65447c478bd9Sstevel@tonic-gate 65457c478bd9Sstevel@tonic-gate /* 65467c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 65477c478bd9Sstevel@tonic-gate * registers. 65487c478bd9Sstevel@tonic-gate */ 65497c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 65507c478bd9Sstevel@tonic-gate client->config_regs_offset = cr->ConfigBase; 65517c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 65527c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 65537c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 65547c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 65557c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65567c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65577c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d can't init " 65587c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 65597c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 65607c478bd9Sstevel@tonic-gate } 65617c478bd9Sstevel@tonic-gate 65627c478bd9Sstevel@tonic-gate /* 65637c478bd9Sstevel@tonic-gate * Setup the config register pointers. 65647c478bd9Sstevel@tonic-gate * Note that these pointers are not the complete virtual address; 65657c478bd9Sstevel@tonic-gate * the complete address is constructed each time the registers 65667c478bd9Sstevel@tonic-gate * are accessed. 65677c478bd9Sstevel@tonic-gate */ 65687c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 65697c478bd9Sstevel@tonic-gate crt = &client->config_regs; 65707c478bd9Sstevel@tonic-gate client->present = cr->Present; 65717c478bd9Sstevel@tonic-gate 65727c478bd9Sstevel@tonic-gate bzero((char *)crt, sizeof (config_regs_t)); 65737c478bd9Sstevel@tonic-gate 65747c478bd9Sstevel@tonic-gate /* Configuration Option Register */ 65757c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 65767c478bd9Sstevel@tonic-gate crt->cor_p = (newoffset + CONFIG_OPTION_REG_OFFSET); 65777c478bd9Sstevel@tonic-gate 65787c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 65797c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) 65807c478bd9Sstevel@tonic-gate crt->ccsr_p = (newoffset + CONFIG_STATUS_REG_OFFSET); 65817c478bd9Sstevel@tonic-gate 65827c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 65837c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) 65847c478bd9Sstevel@tonic-gate crt->prr_p = (newoffset + CONFIG_PINREPL_REG_OFFSET); 65857c478bd9Sstevel@tonic-gate 65867c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 65877c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) 65887c478bd9Sstevel@tonic-gate crt->scr_p = (newoffset + CONFIG_COPY_REG_OFFSET); 65897c478bd9Sstevel@tonic-gate 65907c478bd9Sstevel@tonic-gate /* Extended Status Register */ 65917c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) 65927c478bd9Sstevel@tonic-gate crt->exstat_p = (newoffset + CONFIG_EXSTAT_REG_OFFSET); 65937c478bd9Sstevel@tonic-gate 65947c478bd9Sstevel@tonic-gate /* IO Base 0 Register */ 65957c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 65967c478bd9Sstevel@tonic-gate crt->iobase0_p = (newoffset + CONFIG_IOBASE0_REG_OFFSET); 65977c478bd9Sstevel@tonic-gate 65987c478bd9Sstevel@tonic-gate /* IO Base 1 Register */ 65997c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE1_REG_PRESENT) 66007c478bd9Sstevel@tonic-gate crt->iobase1_p = (newoffset + CONFIG_IOBASE1_REG_OFFSET); 66017c478bd9Sstevel@tonic-gate 66027c478bd9Sstevel@tonic-gate /* IO Base 2 Register */ 66037c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE2_REG_PRESENT) 66047c478bd9Sstevel@tonic-gate crt->iobase2_p = (newoffset + CONFIG_IOBASE2_REG_OFFSET); 66057c478bd9Sstevel@tonic-gate 66067c478bd9Sstevel@tonic-gate /* IO Base 3 Register */ 66077c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE3_REG_PRESENT) 66087c478bd9Sstevel@tonic-gate crt->iobase3_p = (newoffset + CONFIG_IOBASE3_REG_OFFSET); 66097c478bd9Sstevel@tonic-gate 66107c478bd9Sstevel@tonic-gate /* IO Limit Register */ 66117c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) 66127c478bd9Sstevel@tonic-gate crt->iolimit_p = (newoffset + CONFIG_IOLIMIT_REG_OFFSET); 66137c478bd9Sstevel@tonic-gate 66147c478bd9Sstevel@tonic-gate /* 66157c478bd9Sstevel@tonic-gate * Setup the bits in the PRR mask that are valid; this is easy, just 66167c478bd9Sstevel@tonic-gate * copy the Pin value that the client gave us. Note that for 66177c478bd9Sstevel@tonic-gate * this to work, the client must set both of the XXX_STATUS 66187c478bd9Sstevel@tonic-gate * and the XXX_EVENT bits in the Pin member. 66197c478bd9Sstevel@tonic-gate */ 66207c478bd9Sstevel@tonic-gate client->pin = cr->Pin; 66217c478bd9Sstevel@tonic-gate 66227c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 66237c478bd9Sstevel@tonic-gate if (cs_debug > 128) 66247c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: client->pin 0x%x " 66257c478bd9Sstevel@tonic-gate "client->config_regs_offset 0x%x newoffset 0x%x cor_p 0x%x " 66267c478bd9Sstevel@tonic-gate "ccsr_p 0x%x prr_p 0x%x scr_p 0x%x\n", 66277c478bd9Sstevel@tonic-gate client->pin, (int)client->config_regs_offset, newoffset, 66287c478bd9Sstevel@tonic-gate (int)crt->cor_p, (int)crt->ccsr_p, (int)crt->prr_p, 66297c478bd9Sstevel@tonic-gate (int)crt->scr_p); 66307c478bd9Sstevel@tonic-gate #endif 66317c478bd9Sstevel@tonic-gate 66327c478bd9Sstevel@tonic-gate /* 66337c478bd9Sstevel@tonic-gate * If the socket isn't in IO mode, WP is asserted, and we're going to 66347c478bd9Sstevel@tonic-gate * write any of the config registers, issue a warning. 66357c478bd9Sstevel@tonic-gate */ 66367c478bd9Sstevel@tonic-gate if ((client->present != 0) && 66377c478bd9Sstevel@tonic-gate (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) && 66387c478bd9Sstevel@tonic-gate (get_socket.state & SBM_WP)) { 66397c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!cs_request_configuration: attempting to " 66407c478bd9Sstevel@tonic-gate "write CIS config regs with WP set\n"); 66417c478bd9Sstevel@tonic-gate } 66427c478bd9Sstevel@tonic-gate 66437c478bd9Sstevel@tonic-gate /* 66447c478bd9Sstevel@tonic-gate * Write any configuration registers that the client tells us are 66457c478bd9Sstevel@tonic-gate * present to the card; save a copy of what we wrote so that we 66467c478bd9Sstevel@tonic-gate * can return them if the client calls GetConfigurationInfo. 66477c478bd9Sstevel@tonic-gate * The order in which we write the configuration registers is 66487c478bd9Sstevel@tonic-gate * specified by the PCMCIA spec; we must write the socket/copy 66497c478bd9Sstevel@tonic-gate * register first (if it exists), and then we can write the 66507c478bd9Sstevel@tonic-gate * registers in any arbitrary order. 66517c478bd9Sstevel@tonic-gate */ 66527c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 66537c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) { 66547c478bd9Sstevel@tonic-gate crt->scr = cr->Copy; 66557c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->scr_p, crt->scr); 66567c478bd9Sstevel@tonic-gate } 66577c478bd9Sstevel@tonic-gate 66587c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 66597c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 66607c478bd9Sstevel@tonic-gate crt->prr = cr->Pin; 66617c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->prr_p, crt->prr); 66627c478bd9Sstevel@tonic-gate } 66637c478bd9Sstevel@tonic-gate 66647c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 66657c478bd9Sstevel@tonic-gate /* XXX should we set CCSR_SIG_CHG in the CCSR? XXX */ 66667c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) { 66677c478bd9Sstevel@tonic-gate crt->ccsr = cr->Status; 66687c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->ccsr_p, crt->ccsr); 66697c478bd9Sstevel@tonic-gate } 66707c478bd9Sstevel@tonic-gate 66717c478bd9Sstevel@tonic-gate /* Extended Status Register */ 66727c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) { 66737c478bd9Sstevel@tonic-gate crt->exstat = cr->ExtendedStatus; 66747c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->exstat_p, crt->exstat); 66757c478bd9Sstevel@tonic-gate } 66767c478bd9Sstevel@tonic-gate 66777c478bd9Sstevel@tonic-gate /* 66787c478bd9Sstevel@tonic-gate * If any IO base and limit registers exist, and this client 66797c478bd9Sstevel@tonic-gate * has done a RequestIO, setup the IO Base and IO Limit 66807c478bd9Sstevel@tonic-gate * registers. 66817c478bd9Sstevel@tonic-gate */ 66827c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 66837c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) { 66847c478bd9Sstevel@tonic-gate uint32_t base = client->io_alloc.BasePort1.base; 66857c478bd9Sstevel@tonic-gate uint32_t present = (client->present & 66867c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_MASK) >> 66877c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_SHIFT; 66887c478bd9Sstevel@tonic-gate uint32_t reg = crt->iobase0_p; 66897c478bd9Sstevel@tonic-gate 66907c478bd9Sstevel@tonic-gate do { 66917c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, reg, base & 0x0ff); 66927c478bd9Sstevel@tonic-gate reg = reg + 2; 66937c478bd9Sstevel@tonic-gate base = base >> 8; 66947c478bd9Sstevel@tonic-gate present = present >> 1; 66957c478bd9Sstevel@tonic-gate } while (present); 66967c478bd9Sstevel@tonic-gate } /* CONFIG_IOBASE0_REG_PRESENT */ 66977c478bd9Sstevel@tonic-gate 66987c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) { 66997c478bd9Sstevel@tonic-gate uint32_t np = client->io_alloc.NumPorts1 + 67007c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2; 67017c478bd9Sstevel@tonic-gate uint32_t limit, do_bit = 0; 67027c478bd9Sstevel@tonic-gate int lm; 67037c478bd9Sstevel@tonic-gate 67047c478bd9Sstevel@tonic-gate limit = (IONUMPORTS_FROBNITZ(np) - 1); 67057c478bd9Sstevel@tonic-gate 67067c478bd9Sstevel@tonic-gate for (lm = 7; lm >= 0; lm--) { 67077c478bd9Sstevel@tonic-gate if (limit & (1 << lm)) 67087c478bd9Sstevel@tonic-gate do_bit = 1; 67097c478bd9Sstevel@tonic-gate if (do_bit) 67107c478bd9Sstevel@tonic-gate limit |= (1 << lm); 67117c478bd9Sstevel@tonic-gate } /* for */ 67127c478bd9Sstevel@tonic-gate 67137c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->iolimit_p, limit); 67147c478bd9Sstevel@tonic-gate } /* CONFIG_IOLIMIT_REG_PRESENT */ 67157c478bd9Sstevel@tonic-gate } /* REQ_IO_DONE */ 67167c478bd9Sstevel@tonic-gate 67177c478bd9Sstevel@tonic-gate /* 67187c478bd9Sstevel@tonic-gate * Mark the socket as being in IO mode. 67197c478bd9Sstevel@tonic-gate */ 67207c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) 67217c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_IS_IO; 67227c478bd9Sstevel@tonic-gate 67237c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 67247c478bd9Sstevel@tonic-gate 67257c478bd9Sstevel@tonic-gate /* 67267c478bd9Sstevel@tonic-gate * Enable the interrupt if needed 67277c478bd9Sstevel@tonic-gate */ 67287c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 67297c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 67307c478bd9Sstevel@tonic-gate 67317c478bd9Sstevel@tonic-gate /* 67327c478bd9Sstevel@tonic-gate * Now that we know if the PRR is present and if it is, which 67337c478bd9Sstevel@tonic-gate * bits in the PRR are valid, we can construct the correct 67347c478bd9Sstevel@tonic-gate * socket event mask. 67357c478bd9Sstevel@tonic-gate */ 67367c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 67377c478bd9Sstevel@tonic-gate 67387c478bd9Sstevel@tonic-gate /* 67397c478bd9Sstevel@tonic-gate * Configuration Option Register - we handle this specially since 67407c478bd9Sstevel@tonic-gate * we don't allow the client to manipulate the RESET or 67417c478bd9Sstevel@tonic-gate * INTERRUPT bits (although a client can manipulate these 67427c478bd9Sstevel@tonic-gate * bits via an AccessConfigurationRegister call - explain 67437c478bd9Sstevel@tonic-gate * THAT logic to me). 67447c478bd9Sstevel@tonic-gate * XXX - we force level-mode interrupts (COR_LEVEL_IRQ) 67457c478bd9Sstevel@tonic-gate * XXX - we always enable the function on a multi-function card 67467c478bd9Sstevel@tonic-gate */ 67477c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 67487c478bd9Sstevel@tonic-gate crt->cor = (cr->ConfigIndex & ~COR_SOFT_RESET) | COR_LEVEL_IRQ; 67497c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 67507c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_BASE_LIMIT; 67517c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 67527c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_FUNCTION; 67537c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 67547c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 67557c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 67567c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 67577c478bd9Sstevel@tonic-gate 67587c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 67597c478bd9Sstevel@tonic-gate if (cs_debug > 0) 67607c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration " 67617c478bd9Sstevel@tonic-gate "cor=x%x ConfigIndex=x%x Attributes=x%x flags=x%x\n" 67627c478bd9Sstevel@tonic-gate "present=x%x cis_handle=%p cor_p=x%x\n", 67637c478bd9Sstevel@tonic-gate crt->cor, cr->ConfigIndex, cr->Attributes, sp->cis_flags, 67647c478bd9Sstevel@tonic-gate client->present, cis_handle, crt->cor_p); 67657c478bd9Sstevel@tonic-gate #endif 67667c478bd9Sstevel@tonic-gate 67677c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 67687c478bd9Sstevel@tonic-gate } /* CONFIG_OPTION_REG_PRESENT */ 67697c478bd9Sstevel@tonic-gate 67707c478bd9Sstevel@tonic-gate if (cs_rc1_delay) 67717c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc1_delay * 1000); 67727c478bd9Sstevel@tonic-gate 67737c478bd9Sstevel@tonic-gate /* 67747c478bd9Sstevel@tonic-gate * Set the socket to the parameters that the client requested. 67757c478bd9Sstevel@tonic-gate */ 67767c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 67777c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 67787c478bd9Sstevel@tonic-gate crt->cor = 0; /* XXX is 0 the right thing here? */ 67797c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 67807c478bd9Sstevel@tonic-gate } 67817c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 67827c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 67837c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 67847c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 67857c478bd9Sstevel@tonic-gate } 67867c478bd9Sstevel@tonic-gate 67877c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 67887c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 67897c478bd9Sstevel@tonic-gate 67907c478bd9Sstevel@tonic-gate /* 67917c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestConfiguration 67927c478bd9Sstevel@tonic-gate * call. 67937c478bd9Sstevel@tonic-gate */ 67947c478bd9Sstevel@tonic-gate client->flags |= REQ_CONFIGURATION_DONE; 67957c478bd9Sstevel@tonic-gate 67967c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 67977c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 67987c478bd9Sstevel@tonic-gate 67997c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 68007c478bd9Sstevel@tonic-gate } 68017c478bd9Sstevel@tonic-gate 68027c478bd9Sstevel@tonic-gate /* 68037c478bd9Sstevel@tonic-gate * cs_release_configuration - releases configuration previously set via the 68047c478bd9Sstevel@tonic-gate * RequestConfiguration call; this is ReleaseConfiguration 68057c478bd9Sstevel@tonic-gate * 68067c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully released 68077c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 68087c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 68097c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 68107c478bd9Sstevel@tonic-gate */ 68117c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 68127c478bd9Sstevel@tonic-gate static int 68137c478bd9Sstevel@tonic-gate cs_release_configuration(client_handle_t client_handle, release_config_t *rcfg) 68147c478bd9Sstevel@tonic-gate { 68157c478bd9Sstevel@tonic-gate cs_socket_t *sp; 68167c478bd9Sstevel@tonic-gate client_t *client; 68177c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 68187c478bd9Sstevel@tonic-gate set_socket_t set_socket; 68197c478bd9Sstevel@tonic-gate get_socket_t get_socket; 68207c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 68217c478bd9Sstevel@tonic-gate int error; 68227c478bd9Sstevel@tonic-gate uint32_t newoffset; 68237c478bd9Sstevel@tonic-gate int client_lock_acquired; 68247c478bd9Sstevel@tonic-gate 68257c478bd9Sstevel@tonic-gate /* 68267c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 68277c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 68287c478bd9Sstevel@tonic-gate */ 68297c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 68307c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 68317c478bd9Sstevel@tonic-gate 68327c478bd9Sstevel@tonic-gate /* 68337c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 68347c478bd9Sstevel@tonic-gate */ 68357c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 68367c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 68377c478bd9Sstevel@tonic-gate 68387c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 68397c478bd9Sstevel@tonic-gate 68407c478bd9Sstevel@tonic-gate /* 68417c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 68427c478bd9Sstevel@tonic-gate */ 68437c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 68447c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68457c478bd9Sstevel@tonic-gate return (error); 68467c478bd9Sstevel@tonic-gate } 68477c478bd9Sstevel@tonic-gate 68487c478bd9Sstevel@tonic-gate /* 68497c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 68507c478bd9Sstevel@tonic-gate * this call. 68517c478bd9Sstevel@tonic-gate */ 68527c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 68537c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68547c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 68557c478bd9Sstevel@tonic-gate } 68567c478bd9Sstevel@tonic-gate 68577c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 68587c478bd9Sstevel@tonic-gate if (cs_debug > 0) 68597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: " 68607c478bd9Sstevel@tonic-gate "flags=0x%x CW_MULTI_FUNCTION_CIS =0x%x \n", 68617c478bd9Sstevel@tonic-gate sp->cis_flags, CW_MULTI_FUNCTION_CIS); 68627c478bd9Sstevel@tonic-gate 68637c478bd9Sstevel@tonic-gate #endif 68647c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 68657c478bd9Sstevel@tonic-gate 68667c478bd9Sstevel@tonic-gate /* 68677c478bd9Sstevel@tonic-gate * Set the card back to a memory-only interface byte writing a zero 68687c478bd9Sstevel@tonic-gate * to the COR. Note that we don't update our soft copy of the 68697c478bd9Sstevel@tonic-gate * COR state since the PCMCIA spec only requires us to maintain 68707c478bd9Sstevel@tonic-gate * the last value that was written to that register during a 68717c478bd9Sstevel@tonic-gate * call to RequestConfiguration. 68727c478bd9Sstevel@tonic-gate */ 68737c478bd9Sstevel@tonic-gate crt = &client->config_regs; 68747c478bd9Sstevel@tonic-gate 68757c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 68767c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 68777c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 68787c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 68797c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68807c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: socket %d can't init " 68817c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 68827c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 68837c478bd9Sstevel@tonic-gate } 68847c478bd9Sstevel@tonic-gate 68857c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 68867c478bd9Sstevel@tonic-gate /* 68877c478bd9Sstevel@tonic-gate * For the Multifunction cards do not reset the socket 68887c478bd9Sstevel@tonic-gate * to a memory only interface but do clear the 68897c478bd9Sstevel@tonic-gate * Configuration Option Register and mark this client 68907c478bd9Sstevel@tonic-gate * as not having a configuration by clearing the 68917c478bd9Sstevel@tonic-gate * REQ_CONFIGURATION_DONE flag. 68927c478bd9Sstevel@tonic-gate */ 68937c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 68947c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 68957c478bd9Sstevel@tonic-gate 68967c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 68977c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68987c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 68997c478bd9Sstevel@tonic-gate } 69007c478bd9Sstevel@tonic-gate 69017c478bd9Sstevel@tonic-gate /* 69027c478bd9Sstevel@tonic-gate * Set the socket back to a memory-only interface; don't change 69037c478bd9Sstevel@tonic-gate * any other parameter of the socket. 69047c478bd9Sstevel@tonic-gate */ 69057c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 69067c478bd9Sstevel@tonic-gate 69077c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 69087c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69097c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69107c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69117c478bd9Sstevel@tonic-gate } 69127c478bd9Sstevel@tonic-gate 69137c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 69147c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 69157c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 69167c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 69177c478bd9Sstevel@tonic-gate 69187c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 69197c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 69207c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 69217c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 69227c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 69237c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 69247c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 69257c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 69267c478bd9Sstevel@tonic-gate 69277c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 69287c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 69297c478bd9Sstevel@tonic-gate 69307c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 69317c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69327c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69337c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69347c478bd9Sstevel@tonic-gate } 69357c478bd9Sstevel@tonic-gate 69367c478bd9Sstevel@tonic-gate /* 69377c478bd9Sstevel@tonic-gate * Mark this client as not having a configuration. 69387c478bd9Sstevel@tonic-gate */ 69397c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 69407c478bd9Sstevel@tonic-gate 69417c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69427c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69437c478bd9Sstevel@tonic-gate 69447c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 69457c478bd9Sstevel@tonic-gate } 69467c478bd9Sstevel@tonic-gate 69477c478bd9Sstevel@tonic-gate /* 69487c478bd9Sstevel@tonic-gate * cs_modify_configuration - modifies a configuration established by 69497c478bd9Sstevel@tonic-gate * RequestConfiguration; this is ModifyConfiguration 69507c478bd9Sstevel@tonic-gate * 69517c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully modified 69527c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 69537c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 69547c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 69557c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 69567c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 69577c478bd9Sstevel@tonic-gate * are set 69587c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 69597c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 69607c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 69617c478bd9Sstevel@tonic-gate */ 69627c478bd9Sstevel@tonic-gate static int 69637c478bd9Sstevel@tonic-gate cs_modify_configuration(client_handle_t client_handle, modify_config_t *mc) 69647c478bd9Sstevel@tonic-gate { 69657c478bd9Sstevel@tonic-gate cs_socket_t *sp; 69667c478bd9Sstevel@tonic-gate client_t *client; 69677c478bd9Sstevel@tonic-gate set_socket_t set_socket; 69687c478bd9Sstevel@tonic-gate get_socket_t get_socket; 69697c478bd9Sstevel@tonic-gate int error; 69707c478bd9Sstevel@tonic-gate int client_lock_acquired; 69717c478bd9Sstevel@tonic-gate 69727c478bd9Sstevel@tonic-gate /* 69737c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 69747c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 69757c478bd9Sstevel@tonic-gate */ 69767c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 69777c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 69787c478bd9Sstevel@tonic-gate 69797c478bd9Sstevel@tonic-gate /* 69807c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 69817c478bd9Sstevel@tonic-gate */ 69827c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 69837c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69847c478bd9Sstevel@tonic-gate 69857c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 69867c478bd9Sstevel@tonic-gate 69877c478bd9Sstevel@tonic-gate /* 69887c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 69897c478bd9Sstevel@tonic-gate */ 69907c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 69917c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69927c478bd9Sstevel@tonic-gate return (error); 69937c478bd9Sstevel@tonic-gate } 69947c478bd9Sstevel@tonic-gate 69957c478bd9Sstevel@tonic-gate /* 69967c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 69977c478bd9Sstevel@tonic-gate * this call. 69987c478bd9Sstevel@tonic-gate */ 69997c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 70007c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70017c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 70027c478bd9Sstevel@tonic-gate } 70037c478bd9Sstevel@tonic-gate 70047c478bd9Sstevel@tonic-gate /* 70057c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 70067c478bd9Sstevel@tonic-gate * for this client, then return an error. 70077c478bd9Sstevel@tonic-gate */ 70087c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 70097c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70107c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 70117c478bd9Sstevel@tonic-gate } 70127c478bd9Sstevel@tonic-gate 70137c478bd9Sstevel@tonic-gate /* 70147c478bd9Sstevel@tonic-gate * Get the current socket parameters so that we can modify them. 70157c478bd9Sstevel@tonic-gate */ 70167c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 70177c478bd9Sstevel@tonic-gate 70187c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 70197c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70207c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 70217c478bd9Sstevel@tonic-gate } 70227c478bd9Sstevel@tonic-gate 70237c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 70247c478bd9Sstevel@tonic-gate if (cs_debug > 0) 70257c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration: socket %d " 70267c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 70277c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 70287c478bd9Sstevel@tonic-gate sp->socket_num, (int)client->irq_alloc.irq, 70297c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 70307c478bd9Sstevel@tonic-gate #endif 70317c478bd9Sstevel@tonic-gate 70327c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 70337c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 70347c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 70357c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 70367c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 70377c478bd9Sstevel@tonic-gate 70387c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 70397c478bd9Sstevel@tonic-gate 70407c478bd9Sstevel@tonic-gate /* 70417c478bd9Sstevel@tonic-gate * Modify the IRQ routing if the client wants it modified. 70427c478bd9Sstevel@tonic-gate */ 70437c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_IRQ_CHANGE_VALID) { 70447c478bd9Sstevel@tonic-gate set_socket.IREQRouting &= ~IRQ_ENABLE; 70457c478bd9Sstevel@tonic-gate 70467c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_MULTI_FUNCTION_CIS) && 70477c478bd9Sstevel@tonic-gate (client->present & CONFIG_OPTION_REG_PRESENT)) { 70487c478bd9Sstevel@tonic-gate config_regs_t *crt = &client->config_regs; 70497c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 70507c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 70517c478bd9Sstevel@tonic-gate 70527c478bd9Sstevel@tonic-gate /* 70537c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 70547c478bd9Sstevel@tonic-gate * registers. 70557c478bd9Sstevel@tonic-gate */ 70567c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 70577c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 70587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 70607c478bd9Sstevel@tonic-gate "cs_modify_configuration: socket %d can't init " 70617c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 70627c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 70637c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 70647c478bd9Sstevel@tonic-gate 70657c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 70667c478bd9Sstevel@tonic-gate 70677c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 70687c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 70697c478bd9Sstevel@tonic-gate 70707c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 70717c478bd9Sstevel@tonic-gate if (cs_debug > 0) 70727c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration:" 70737c478bd9Sstevel@tonic-gate " cor_p=0x%x cor=0x%x\n", 70747c478bd9Sstevel@tonic-gate crt->cor_p, crt->cor); 70757c478bd9Sstevel@tonic-gate #endif 70767c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 70777c478bd9Sstevel@tonic-gate 70787c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 70797c478bd9Sstevel@tonic-gate 70807c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 70817c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 70827c478bd9Sstevel@tonic-gate 70837c478bd9Sstevel@tonic-gate } /* CONF_IRQ_CHANGE_VALID */ 70847c478bd9Sstevel@tonic-gate 70857c478bd9Sstevel@tonic-gate /* 70867c478bd9Sstevel@tonic-gate * Modify the voltage levels that the client specifies. 70877c478bd9Sstevel@tonic-gate */ 70887c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 70897c478bd9Sstevel@tonic-gate 70907c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP1_CHANGE_VALID) { 70917c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp1, VPP1, 70927c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 70937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70947c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 70957c478bd9Sstevel@tonic-gate } 70967c478bd9Sstevel@tonic-gate } else { 70977c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 70987c478bd9Sstevel@tonic-gate } 70997c478bd9Sstevel@tonic-gate 71007c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP2_CHANGE_VALID) { 71017c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp2, VPP2, 71027c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 71037c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71047c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 71057c478bd9Sstevel@tonic-gate } 71067c478bd9Sstevel@tonic-gate } else { 71077c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 71087c478bd9Sstevel@tonic-gate } 71097c478bd9Sstevel@tonic-gate 71107c478bd9Sstevel@tonic-gate /* 71117c478bd9Sstevel@tonic-gate * Setup the modified socket configuration. 71127c478bd9Sstevel@tonic-gate */ 71137c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 71147c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71157c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 71167c478bd9Sstevel@tonic-gate } 71177c478bd9Sstevel@tonic-gate 71187c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71197c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 71207c478bd9Sstevel@tonic-gate } 71217c478bd9Sstevel@tonic-gate 71227c478bd9Sstevel@tonic-gate /* 71237c478bd9Sstevel@tonic-gate * cs_access_configuration_register - provides a client access to the card's 71247c478bd9Sstevel@tonic-gate * configuration registers; this is AccessConfigurationRegister 71257c478bd9Sstevel@tonic-gate * 71267c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if register accessed successfully 71277c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 71287c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if arguments are out of range 71297c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 71307c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if no config registers base address 71317c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_MODE - if no RequestConfiguration has 71327c478bd9Sstevel@tonic-gate * been done yet 71337c478bd9Sstevel@tonic-gate */ 71347c478bd9Sstevel@tonic-gate static int 71357c478bd9Sstevel@tonic-gate cs_access_configuration_register(client_handle_t client_handle, 71367c478bd9Sstevel@tonic-gate access_config_reg_t *acr) 71377c478bd9Sstevel@tonic-gate { 71387c478bd9Sstevel@tonic-gate cs_socket_t *sp; 71397c478bd9Sstevel@tonic-gate client_t *client; 71407c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 71417c478bd9Sstevel@tonic-gate int error; 71427c478bd9Sstevel@tonic-gate uint32_t newoffset; 71437c478bd9Sstevel@tonic-gate int client_lock_acquired; 71447c478bd9Sstevel@tonic-gate 71457c478bd9Sstevel@tonic-gate /* 71467c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 71477c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 71487c478bd9Sstevel@tonic-gate */ 71497c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 71507c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 71517c478bd9Sstevel@tonic-gate 71527c478bd9Sstevel@tonic-gate /* 71537c478bd9Sstevel@tonic-gate * Make sure that the specifed offset is in range. 71547c478bd9Sstevel@tonic-gate */ 71557c478bd9Sstevel@tonic-gate if (acr->Offset > ((CISTPL_CONFIG_MAX_CONFIG_REGS * 2) - 2)) 71567c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 71577c478bd9Sstevel@tonic-gate 71587c478bd9Sstevel@tonic-gate /* 71597c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 71607c478bd9Sstevel@tonic-gate */ 71617c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 71627c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 71637c478bd9Sstevel@tonic-gate 71647c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 71657c478bd9Sstevel@tonic-gate 71667c478bd9Sstevel@tonic-gate /* 71677c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 71687c478bd9Sstevel@tonic-gate */ 71697c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 71707c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71717c478bd9Sstevel@tonic-gate return (error); 71727c478bd9Sstevel@tonic-gate } 71737c478bd9Sstevel@tonic-gate 71747c478bd9Sstevel@tonic-gate /* 71757c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 71767c478bd9Sstevel@tonic-gate * for this client, then return an error. 71777c478bd9Sstevel@tonic-gate */ 71787c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 71797c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71807c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 71817c478bd9Sstevel@tonic-gate } 71827c478bd9Sstevel@tonic-gate 71837c478bd9Sstevel@tonic-gate /* 71847c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 71857c478bd9Sstevel@tonic-gate * this call. 71867c478bd9Sstevel@tonic-gate */ 71877c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 71887c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71897c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_MODE); 71907c478bd9Sstevel@tonic-gate } 71917c478bd9Sstevel@tonic-gate 71927c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 71937c478bd9Sstevel@tonic-gate 71947c478bd9Sstevel@tonic-gate /* 71957c478bd9Sstevel@tonic-gate * Get a pointer to the CIS window 71967c478bd9Sstevel@tonic-gate */ 71977c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset + acr->Offset; 71987c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 71997c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 72007c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 72017c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 72027c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: socket %d can't init CIS window\n", 72037c478bd9Sstevel@tonic-gate sp->socket_num); 72047c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 72057c478bd9Sstevel@tonic-gate } 72067c478bd9Sstevel@tonic-gate 72077c478bd9Sstevel@tonic-gate /* 72087c478bd9Sstevel@tonic-gate * Create the address for the config register that the client 72097c478bd9Sstevel@tonic-gate * wants to access. 72107c478bd9Sstevel@tonic-gate */ 72117c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 72127c478bd9Sstevel@tonic-gate 72137c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 72147c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 72157c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: config_regs_offset 0x%x " 72167c478bd9Sstevel@tonic-gate "Offset 0x%x newoffset 0x%x\n", 72177c478bd9Sstevel@tonic-gate (int)client->config_regs_offset, 72187c478bd9Sstevel@tonic-gate (int)acr->Offset, newoffset); 72197c478bd9Sstevel@tonic-gate } 72207c478bd9Sstevel@tonic-gate #endif 72217c478bd9Sstevel@tonic-gate 72227c478bd9Sstevel@tonic-gate /* 72237c478bd9Sstevel@tonic-gate * Determine what the client wants us to do. The client is 72247c478bd9Sstevel@tonic-gate * allowed to specify any valid offset, even if it would 72257c478bd9Sstevel@tonic-gate * cause an unimplemented configuration register to be 72267c478bd9Sstevel@tonic-gate * accessed. 72277c478bd9Sstevel@tonic-gate */ 72287c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 72297c478bd9Sstevel@tonic-gate switch (acr->Action) { 72307c478bd9Sstevel@tonic-gate case CONFIG_REG_READ: 72317c478bd9Sstevel@tonic-gate acr->Value = csx_Get8(cis_handle, newoffset); 72327c478bd9Sstevel@tonic-gate break; 72337c478bd9Sstevel@tonic-gate case CONFIG_REG_WRITE: 72347c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, newoffset, acr->Value); 72357c478bd9Sstevel@tonic-gate break; 72367c478bd9Sstevel@tonic-gate default: 72377c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; 72387c478bd9Sstevel@tonic-gate break; 72397c478bd9Sstevel@tonic-gate } /* switch */ 72407c478bd9Sstevel@tonic-gate 72417c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 72427c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 72437c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 72447c478bd9Sstevel@tonic-gate 72457c478bd9Sstevel@tonic-gate return (error); 72467c478bd9Sstevel@tonic-gate } 72477c478bd9Sstevel@tonic-gate 72487c478bd9Sstevel@tonic-gate /* 72497c478bd9Sstevel@tonic-gate * ==== RESET and general info functions ==== 72507c478bd9Sstevel@tonic-gate */ 72517c478bd9Sstevel@tonic-gate 72527c478bd9Sstevel@tonic-gate /* 72537c478bd9Sstevel@tonic-gate * cs_reset_function - RESET the requested function on the card; this 72547c478bd9Sstevel@tonic-gate * is ResetFunction 72557c478bd9Sstevel@tonic-gate * 72567c478bd9Sstevel@tonic-gate * Note: We don't support this functionality yet, and the standard 72577c478bd9Sstevel@tonic-gate * says it's OK to reutrn CS_IN_USE if we can't do this 72587c478bd9Sstevel@tonic-gate * operation. 72597c478bd9Sstevel@tonic-gate */ 72607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 72617c478bd9Sstevel@tonic-gate static int 72627c478bd9Sstevel@tonic-gate cs_reset_function(client_handle_t ch, reset_function_t *rf) 72637c478bd9Sstevel@tonic-gate { 72647c478bd9Sstevel@tonic-gate return (CS_IN_USE); 72657c478bd9Sstevel@tonic-gate } 72667c478bd9Sstevel@tonic-gate 72677c478bd9Sstevel@tonic-gate /* 72687c478bd9Sstevel@tonic-gate * cs_get_configuration_info - return configuration info for the passed 72697c478bd9Sstevel@tonic-gate * socket and function number to the caller; 72707c478bd9Sstevel@tonic-gate * this is GetConfigurationInfo 72717c478bd9Sstevel@tonic-gate */ 72727c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 72737c478bd9Sstevel@tonic-gate static int 72747c478bd9Sstevel@tonic-gate cs_get_configuration_info(client_handle_t *chp, get_configuration_info_t *gci) 72757c478bd9Sstevel@tonic-gate { 72767c478bd9Sstevel@tonic-gate cs_socket_t *sp; 72777c478bd9Sstevel@tonic-gate uint32_t fn; 72787c478bd9Sstevel@tonic-gate client_t *client; 72797c478bd9Sstevel@tonic-gate int client_lock_acquired; 72807c478bd9Sstevel@tonic-gate 72817c478bd9Sstevel@tonic-gate /* 72827c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 72837c478bd9Sstevel@tonic-gate */ 72847c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gci->Socket))) == NULL) 72857c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 72867c478bd9Sstevel@tonic-gate 72877c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 72887c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 72897c478bd9Sstevel@tonic-gate 72907c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(gci->Socket); 72917c478bd9Sstevel@tonic-gate 72927c478bd9Sstevel@tonic-gate client = sp->client_list; 72937c478bd9Sstevel@tonic-gate while (client) { 72947c478bd9Sstevel@tonic-gate 72957c478bd9Sstevel@tonic-gate if (GET_CLIENT_FUNCTION(client->client_handle) == fn) { 72967c478bd9Sstevel@tonic-gate 72977c478bd9Sstevel@tonic-gate /* 72987c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the 72997c478bd9Sstevel@tonic-gate * socket is not for this client, then return 73007c478bd9Sstevel@tonic-gate * an error. 73017c478bd9Sstevel@tonic-gate */ 73027c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 73037c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73047c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73057c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 73067c478bd9Sstevel@tonic-gate } 73077c478bd9Sstevel@tonic-gate 73087c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73097c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73107c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 73117c478bd9Sstevel@tonic-gate 73127c478bd9Sstevel@tonic-gate } /* GET_CLIENT_FUNCTION == fn */ 73137c478bd9Sstevel@tonic-gate 73147c478bd9Sstevel@tonic-gate client = client->next; 73157c478bd9Sstevel@tonic-gate } /* while (client) */ 73167c478bd9Sstevel@tonic-gate 73177c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73187c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73197c478bd9Sstevel@tonic-gate 73207c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 73217c478bd9Sstevel@tonic-gate } 73227c478bd9Sstevel@tonic-gate 73237c478bd9Sstevel@tonic-gate /* 73247c478bd9Sstevel@tonic-gate * cs_get_cardservices_info - return info about Card Services to the 73257c478bd9Sstevel@tonic-gate * caller; this is GetCardServicesInfo 73267c478bd9Sstevel@tonic-gate */ 73277c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 73287c478bd9Sstevel@tonic-gate static int 73297c478bd9Sstevel@tonic-gate cs_get_cardservices_info(client_handle_t ch, get_cardservices_info_t *gcsi) 73307c478bd9Sstevel@tonic-gate { 73317c478bd9Sstevel@tonic-gate gcsi->Signature[0] = 'C'; 73327c478bd9Sstevel@tonic-gate gcsi->Signature[1] = 'S'; 73337c478bd9Sstevel@tonic-gate gcsi->NumSockets = cs_globals.num_sockets; 73347c478bd9Sstevel@tonic-gate gcsi->Revision = CS_INTERNAL_REVISION_LEVEL; 73357c478bd9Sstevel@tonic-gate gcsi->CSLevel = CS_VERSION; 73367c478bd9Sstevel@tonic-gate gcsi->FuncsPerSocket = CIS_MAX_FUNCTIONS; 73377c478bd9Sstevel@tonic-gate (void) strncpy(gcsi->VendorString, 73387c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_VENDOR_STRING, 73397c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_MAX_VS_LEN); 73407c478bd9Sstevel@tonic-gate 73417c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 73427c478bd9Sstevel@tonic-gate } 73437c478bd9Sstevel@tonic-gate 73447c478bd9Sstevel@tonic-gate /* 73457c478bd9Sstevel@tonic-gate * cs_get_physical_adapter_info - returns information about the requested 73467c478bd9Sstevel@tonic-gate * physical adapter; this is 73477c478bd9Sstevel@tonic-gate * GetPhysicalAdapterInfo 73487c478bd9Sstevel@tonic-gate * 73497c478bd9Sstevel@tonic-gate * calling: client_handle_t: 73507c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 73517c478bd9Sstevel@tonic-gate * to specify logical socket number 73527c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 73537c478bd9Sstevel@tonic-gate * client_handle_t 73547c478bd9Sstevel@tonic-gate * 73557c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 73567c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 73577c478bd9Sstevel@tonic-gate * socket number is specified in 73587c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 73597c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 73607c478bd9Sstevel@tonic-gate * client handle is specified 73617c478bd9Sstevel@tonic-gate */ 73627c478bd9Sstevel@tonic-gate static int 73637c478bd9Sstevel@tonic-gate cs_get_physical_adapter_info(client_handle_t ch, 73647c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *gpai) 73657c478bd9Sstevel@tonic-gate { 73667c478bd9Sstevel@tonic-gate cs_socket_t *sp; 73677c478bd9Sstevel@tonic-gate int client_lock_acquired; 73687c478bd9Sstevel@tonic-gate 7369*c48c3045SToomas Soome if (ch == 0) 73707c478bd9Sstevel@tonic-gate gpai->PhySocket = CS_GET_SOCKET_NUMBER(gpai->LogSocket); 73717c478bd9Sstevel@tonic-gate else 73727c478bd9Sstevel@tonic-gate gpai->PhySocket = GET_CLIENT_SOCKET(ch); 73737c478bd9Sstevel@tonic-gate 73747c478bd9Sstevel@tonic-gate /* 73757c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 73767c478bd9Sstevel@tonic-gate */ 73777c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gpai->PhySocket))) == NULL) 7378*c48c3045SToomas Soome return ((ch == 0) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 73797c478bd9Sstevel@tonic-gate 73807c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 73817c478bd9Sstevel@tonic-gate 73827c478bd9Sstevel@tonic-gate /* 73837c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 73847c478bd9Sstevel@tonic-gate */ 7385*c48c3045SToomas Soome if (ch != 0) { 73867c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 73877c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73887c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 73897c478bd9Sstevel@tonic-gate } /* cs_find_client */ 73907c478bd9Sstevel@tonic-gate } /* ch != NULL */ 73917c478bd9Sstevel@tonic-gate 73927c478bd9Sstevel@tonic-gate gpai->flags = sp->adapter.flags; 73937c478bd9Sstevel@tonic-gate (void) strcpy(gpai->name, sp->adapter.name); 73947c478bd9Sstevel@tonic-gate gpai->major = sp->adapter.major; 73957c478bd9Sstevel@tonic-gate gpai->minor = sp->adapter.minor; 73967c478bd9Sstevel@tonic-gate gpai->instance = sp->adapter.instance; 73977c478bd9Sstevel@tonic-gate gpai->number = sp->adapter.number; 73987c478bd9Sstevel@tonic-gate gpai->num_sockets = sp->adapter.num_sockets; 73997c478bd9Sstevel@tonic-gate gpai->first_socket = sp->adapter.first_socket; 74007c478bd9Sstevel@tonic-gate 74017c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74027c478bd9Sstevel@tonic-gate 74037c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 74047c478bd9Sstevel@tonic-gate } 74057c478bd9Sstevel@tonic-gate 74067c478bd9Sstevel@tonic-gate /* 74077c478bd9Sstevel@tonic-gate * ==== general functions ==== 74087c478bd9Sstevel@tonic-gate */ 74097c478bd9Sstevel@tonic-gate 74107c478bd9Sstevel@tonic-gate /* 74117c478bd9Sstevel@tonic-gate * cs_map_log_socket - returns the physical socket number associated with 74127c478bd9Sstevel@tonic-gate * either the passed client handle or the passed 74137c478bd9Sstevel@tonic-gate * logical socket number; this is MapLogSocket 74147c478bd9Sstevel@tonic-gate * 74157c478bd9Sstevel@tonic-gate * calling: client_handle_t: 74167c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 74177c478bd9Sstevel@tonic-gate * to specify logical socket number 74187c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 74197c478bd9Sstevel@tonic-gate * client_handle_t 74207c478bd9Sstevel@tonic-gate * 74217c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 74227c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 74237c478bd9Sstevel@tonic-gate * socket number is specified in 74247c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 74257c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 74267c478bd9Sstevel@tonic-gate * client handle is specified 74277c478bd9Sstevel@tonic-gate * 74287c478bd9Sstevel@tonic-gate * Note: We provide this function since the instance number of a client 74297c478bd9Sstevel@tonic-gate * driver doesn't necessary correspond to the physical 74307c478bd9Sstevel@tonic-gate * socket number 74317c478bd9Sstevel@tonic-gate */ 74327c478bd9Sstevel@tonic-gate static int 74337c478bd9Sstevel@tonic-gate cs_map_log_socket(client_handle_t ch, map_log_socket_t *mls) 74347c478bd9Sstevel@tonic-gate { 74357c478bd9Sstevel@tonic-gate cs_socket_t *sp; 74367c478bd9Sstevel@tonic-gate int client_lock_acquired; 74377c478bd9Sstevel@tonic-gate 7438*c48c3045SToomas Soome if (ch == 0) 74397c478bd9Sstevel@tonic-gate mls->PhySocket = CS_GET_SOCKET_NUMBER(mls->LogSocket); 74407c478bd9Sstevel@tonic-gate else 74417c478bd9Sstevel@tonic-gate mls->PhySocket = GET_CLIENT_SOCKET(ch); 74427c478bd9Sstevel@tonic-gate 74437c478bd9Sstevel@tonic-gate /* 74447c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 74457c478bd9Sstevel@tonic-gate */ 74467c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(mls->PhySocket))) == NULL) 7447*c48c3045SToomas Soome return ((ch == 0) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 74487c478bd9Sstevel@tonic-gate 74497c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 74507c478bd9Sstevel@tonic-gate 74517c478bd9Sstevel@tonic-gate /* 74527c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 74537c478bd9Sstevel@tonic-gate */ 7454*c48c3045SToomas Soome if (ch != 0) { 74557c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 74567c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74577c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 74587c478bd9Sstevel@tonic-gate } /* cs_find_client */ 74597c478bd9Sstevel@tonic-gate } /* ch != NULL */ 74607c478bd9Sstevel@tonic-gate 74617c478bd9Sstevel@tonic-gate mls->PhyAdapter = sp->adapter.number; 74627c478bd9Sstevel@tonic-gate 74637c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74647c478bd9Sstevel@tonic-gate 74657c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 74667c478bd9Sstevel@tonic-gate } 74677c478bd9Sstevel@tonic-gate 74687c478bd9Sstevel@tonic-gate /* 74697c478bd9Sstevel@tonic-gate * cs_convert_speed - convers nS to devspeed and devspeed to nS 74707c478bd9Sstevel@tonic-gate * 74717c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 74727c478bd9Sstevel@tonic-gate * is only a wrapper. 74737c478bd9Sstevel@tonic-gate */ 74747c478bd9Sstevel@tonic-gate static int 74757c478bd9Sstevel@tonic-gate cs_convert_speed(convert_speed_t *cs) 74767c478bd9Sstevel@tonic-gate { 74777c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSPEED, cs)); 74787c478bd9Sstevel@tonic-gate } 74797c478bd9Sstevel@tonic-gate 74807c478bd9Sstevel@tonic-gate /* 74817c478bd9Sstevel@tonic-gate * cs_convert_size - converts a devsize value to a size in bytes value 74827c478bd9Sstevel@tonic-gate * or a size in bytes value to a devsize value 74837c478bd9Sstevel@tonic-gate * 74847c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 74857c478bd9Sstevel@tonic-gate * is only a wrapper. 74867c478bd9Sstevel@tonic-gate */ 74877c478bd9Sstevel@tonic-gate static int 74887c478bd9Sstevel@tonic-gate cs_convert_size(convert_size_t *cs) 74897c478bd9Sstevel@tonic-gate { 74907c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSIZE, cs)); 74917c478bd9Sstevel@tonic-gate } 74927c478bd9Sstevel@tonic-gate 74937c478bd9Sstevel@tonic-gate /* 74947c478bd9Sstevel@tonic-gate * cs_convert_powerlevel - converts a power level in tenths of a volt 74957c478bd9Sstevel@tonic-gate * to a power table entry for the specified socket 74967c478bd9Sstevel@tonic-gate * 74977c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if volts converted to a valid power level 74987c478bd9Sstevel@tonic-gate * CS_BAD_ADAPTER - if SS_InquireAdapter fails 74997c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if volts are not supported on this socket 75007c478bd9Sstevel@tonic-gate * and adapter 75017c478bd9Sstevel@tonic-gate */ 75027c478bd9Sstevel@tonic-gate static int 75037c478bd9Sstevel@tonic-gate cs_convert_powerlevel(uint32_t sn, uint32_t volts, uint32_t flags, unsigned *pl) 75047c478bd9Sstevel@tonic-gate { 75057c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 75067c478bd9Sstevel@tonic-gate int i; 75077c478bd9Sstevel@tonic-gate 75087c478bd9Sstevel@tonic-gate #ifdef lint 75097c478bd9Sstevel@tonic-gate if (sn == 0) 75107c478bd9Sstevel@tonic-gate panic("lint panic"); 75117c478bd9Sstevel@tonic-gate #endif 75127c478bd9Sstevel@tonic-gate 75137c478bd9Sstevel@tonic-gate *pl = 0; 75147c478bd9Sstevel@tonic-gate 75157c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireAdapter, &inquire_adapter) != SUCCESS) 75167c478bd9Sstevel@tonic-gate return (CS_BAD_ADAPTER); 75177c478bd9Sstevel@tonic-gate 75187c478bd9Sstevel@tonic-gate for (i = 0; (i < inquire_adapter.NumPower); i++) { 75197c478bd9Sstevel@tonic-gate if ((inquire_adapter.power_entry[i].ValidSignals & flags) && 75207c478bd9Sstevel@tonic-gate (inquire_adapter.power_entry[i].PowerLevel == volts)) { 75217c478bd9Sstevel@tonic-gate *pl = i; 75227c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75237c478bd9Sstevel@tonic-gate } 75247c478bd9Sstevel@tonic-gate } 75257c478bd9Sstevel@tonic-gate 75267c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 75277c478bd9Sstevel@tonic-gate } 75287c478bd9Sstevel@tonic-gate 75297c478bd9Sstevel@tonic-gate /* 75307c478bd9Sstevel@tonic-gate * cs_event2text - returns text string(s) associated with the event; this 75317c478bd9Sstevel@tonic-gate * function supports the Event2Text CS call. 75327c478bd9Sstevel@tonic-gate * 75337c478bd9Sstevel@tonic-gate * calling: event2text_t * - pointer to event2text struct 75347c478bd9Sstevel@tonic-gate * int event_source - specifies event type in event2text_t: 75357c478bd9Sstevel@tonic-gate * 0 - SS event 75367c478bd9Sstevel@tonic-gate * 1 - CS event 75377c478bd9Sstevel@tonic-gate * 75387c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 75397c478bd9Sstevel@tonic-gate */ 75407c478bd9Sstevel@tonic-gate static int 75417c478bd9Sstevel@tonic-gate cs_event2text(event2text_t *e2t, int event_source) 75427c478bd9Sstevel@tonic-gate { 75437c478bd9Sstevel@tonic-gate event_t event; 75447c478bd9Sstevel@tonic-gate char *sepchar = "|"; 75457c478bd9Sstevel@tonic-gate 75467c478bd9Sstevel@tonic-gate /* 75477c478bd9Sstevel@tonic-gate * If event_source is 0, this is a SS event 75487c478bd9Sstevel@tonic-gate */ 75497c478bd9Sstevel@tonic-gate if (!event_source) { 75507c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_SS_EVENTS; event++) { 75517c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].ss_event == e2t->event) { 75527c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[event].text); 75537c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75547c478bd9Sstevel@tonic-gate } 75557c478bd9Sstevel@tonic-gate } 75567c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[MAX_CS_EVENTS].text); 75577c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75587c478bd9Sstevel@tonic-gate } else { 75597c478bd9Sstevel@tonic-gate /* 75607c478bd9Sstevel@tonic-gate * This is a CS event 75617c478bd9Sstevel@tonic-gate */ 75627c478bd9Sstevel@tonic-gate e2t->text[0] = '\0'; 75637c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_CS_EVENTS; event++) { 75647c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].cs_event & e2t->event) { 75657c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, cs_ss_event_text[event].text); 75667c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, sepchar); 75677c478bd9Sstevel@tonic-gate } /* if (cs_ss_event_text) */ 75687c478bd9Sstevel@tonic-gate } /* for (event) */ 75697c478bd9Sstevel@tonic-gate if (e2t->text[0]) 7570*c48c3045SToomas Soome e2t->text[strlen(e2t->text)-1] = '\0'; 75717c478bd9Sstevel@tonic-gate } /* if (!event_source) */ 75727c478bd9Sstevel@tonic-gate 75737c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75747c478bd9Sstevel@tonic-gate } 75757c478bd9Sstevel@tonic-gate 75767c478bd9Sstevel@tonic-gate /* 75777c478bd9Sstevel@tonic-gate * cs_error2text - returns a pointer to a text string containing the name 75787c478bd9Sstevel@tonic-gate * of the passed Card Services function or return code 75797c478bd9Sstevel@tonic-gate * 75807c478bd9Sstevel@tonic-gate * This function supports the Error2Text CS call. 75817c478bd9Sstevel@tonic-gate */ 75827c478bd9Sstevel@tonic-gate static char * 75837c478bd9Sstevel@tonic-gate cs_error2text(int function, int type) 75847c478bd9Sstevel@tonic-gate { 75857c478bd9Sstevel@tonic-gate cs_csfunc2text_strings_t *cfs; 75867c478bd9Sstevel@tonic-gate int end_marker; 75877c478bd9Sstevel@tonic-gate 75887c478bd9Sstevel@tonic-gate if (type == CSFUN2TEXT_FUNCTION) { 75897c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_funcstrings; 75907c478bd9Sstevel@tonic-gate end_marker = CSFuncListEnd; 75917c478bd9Sstevel@tonic-gate } else { 75927c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_returnstrings; 75937c478bd9Sstevel@tonic-gate end_marker = CS_ERRORLIST_END; 75947c478bd9Sstevel@tonic-gate } 75957c478bd9Sstevel@tonic-gate 75967c478bd9Sstevel@tonic-gate while (cfs->item != end_marker) { 75977c478bd9Sstevel@tonic-gate if (cfs->item == function) 75987c478bd9Sstevel@tonic-gate return (cfs->text); 75997c478bd9Sstevel@tonic-gate cfs++; 76007c478bd9Sstevel@tonic-gate } 76017c478bd9Sstevel@tonic-gate 76027c478bd9Sstevel@tonic-gate return (cfs->text); 76037c478bd9Sstevel@tonic-gate } 76047c478bd9Sstevel@tonic-gate 76057c478bd9Sstevel@tonic-gate /* 76067c478bd9Sstevel@tonic-gate * cs_make_device_node - creates/removes device nodes on a client's behalf; 76077c478bd9Sstevel@tonic-gate * this is MakeDeviceNode and RemoveDeviceNode 76087c478bd9Sstevel@tonic-gate * 76097c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if all device nodes successfully created/removed 76107c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if NumDevNodes is not zero when Action 76117c478bd9Sstevel@tonic-gate * is REMOVAL_ALL_DEVICES 76127c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if an invalid Action code is specified 76137c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 76147c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if can't create/remove device node 76157c478bd9Sstevel@tonic-gate */ 76167c478bd9Sstevel@tonic-gate static int 76177c478bd9Sstevel@tonic-gate cs_make_device_node(client_handle_t client_handle, make_device_node_t *mdn) 76187c478bd9Sstevel@tonic-gate { 76197c478bd9Sstevel@tonic-gate cs_socket_t *sp; 76207c478bd9Sstevel@tonic-gate client_t *client; 76217c478bd9Sstevel@tonic-gate ss_make_device_node_t ss_make_device_node; 76227c478bd9Sstevel@tonic-gate int error, i; 76237c478bd9Sstevel@tonic-gate int client_lock_acquired; 76247c478bd9Sstevel@tonic-gate 76257c478bd9Sstevel@tonic-gate /* 76267c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 76277c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 76287c478bd9Sstevel@tonic-gate */ 76297c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 76307c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 76317c478bd9Sstevel@tonic-gate 76327c478bd9Sstevel@tonic-gate /* 76337c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 76347c478bd9Sstevel@tonic-gate */ 76357c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 76367c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 76377c478bd9Sstevel@tonic-gate 76387c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 76397c478bd9Sstevel@tonic-gate 76407c478bd9Sstevel@tonic-gate /* 76417c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 76427c478bd9Sstevel@tonic-gate */ 76437c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 76447c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76457c478bd9Sstevel@tonic-gate return (error); 76467c478bd9Sstevel@tonic-gate } 76477c478bd9Sstevel@tonic-gate 76487c478bd9Sstevel@tonic-gate #ifdef XXX 76497c478bd9Sstevel@tonic-gate /* 76507c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 76517c478bd9Sstevel@tonic-gate * for this client, then return an error. 76527c478bd9Sstevel@tonic-gate */ 76537c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 76547c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76557c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 76567c478bd9Sstevel@tonic-gate } 76577c478bd9Sstevel@tonic-gate #endif 76587c478bd9Sstevel@tonic-gate 76597c478bd9Sstevel@tonic-gate /* 76607c478bd9Sstevel@tonic-gate * Setup the client's dip, since we use it later on. 76617c478bd9Sstevel@tonic-gate */ 76627c478bd9Sstevel@tonic-gate ss_make_device_node.dip = client->dip; 76637c478bd9Sstevel@tonic-gate 76647c478bd9Sstevel@tonic-gate /* 76657c478bd9Sstevel@tonic-gate * Make sure that we're being given a valid Action. Set the default 76667c478bd9Sstevel@tonic-gate * error code as well. 76677c478bd9Sstevel@tonic-gate */ 76687c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; /* for default case */ 76697c478bd9Sstevel@tonic-gate switch (mdn->Action) { 76707c478bd9Sstevel@tonic-gate case CREATE_DEVICE_NODE: 76717c478bd9Sstevel@tonic-gate case REMOVE_DEVICE_NODE: 76727c478bd9Sstevel@tonic-gate break; 76737c478bd9Sstevel@tonic-gate case REMOVAL_ALL_DEVICE_NODES: 76747c478bd9Sstevel@tonic-gate if (mdn->NumDevNodes) { 76757c478bd9Sstevel@tonic-gate error = CS_BAD_ATTRIBUTE; 76767c478bd9Sstevel@tonic-gate } else { 76777c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 76787c478bd9Sstevel@tonic-gate ss_make_device_node.name = NULL; 76797c478bd9Sstevel@tonic-gate SocketServices(CSInitDev, &ss_make_device_node); 76807c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 76817c478bd9Sstevel@tonic-gate } 76826c125e4eSToomas Soome /* FALLTHROUGH */ 76837c478bd9Sstevel@tonic-gate default: 76847c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76857c478bd9Sstevel@tonic-gate return (error); 76867c478bd9Sstevel@tonic-gate /* NOTREACHED */ 76877c478bd9Sstevel@tonic-gate } /* switch */ 76887c478bd9Sstevel@tonic-gate 76897c478bd9Sstevel@tonic-gate /* 76907c478bd9Sstevel@tonic-gate * Loop through the device node descriptions and create or destroy 76917c478bd9Sstevel@tonic-gate * the device node. 76927c478bd9Sstevel@tonic-gate */ 76937c478bd9Sstevel@tonic-gate for (i = 0; i < mdn->NumDevNodes; i++) { 76947c478bd9Sstevel@tonic-gate devnode_desc_t *devnode_desc = &mdn->devnode_desc[i]; 76957c478bd9Sstevel@tonic-gate 76967c478bd9Sstevel@tonic-gate ss_make_device_node.name = devnode_desc->name; 76977c478bd9Sstevel@tonic-gate ss_make_device_node.spec_type = devnode_desc->spec_type; 76987c478bd9Sstevel@tonic-gate ss_make_device_node.minor_num = devnode_desc->minor_num; 76997c478bd9Sstevel@tonic-gate ss_make_device_node.node_type = devnode_desc->node_type; 77007c478bd9Sstevel@tonic-gate 77017c478bd9Sstevel@tonic-gate /* 77027c478bd9Sstevel@tonic-gate * Set the appropriate flag for the action that we want 77037c478bd9Sstevel@tonic-gate * SS to perform. Note that if we ever OR-in the flag 77047c478bd9Sstevel@tonic-gate * here, we need to be sure to clear the flags member 77057c478bd9Sstevel@tonic-gate * since we sometimes OR-in other flags below. 77067c478bd9Sstevel@tonic-gate */ 77077c478bd9Sstevel@tonic-gate if (mdn->Action == CREATE_DEVICE_NODE) { 77087c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_CREATE_DEVICE; 77097c478bd9Sstevel@tonic-gate } else { 77107c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 77117c478bd9Sstevel@tonic-gate } 77127c478bd9Sstevel@tonic-gate 77137c478bd9Sstevel@tonic-gate /* 77147c478bd9Sstevel@tonic-gate * If this is not the last device to process, then we need 77157c478bd9Sstevel@tonic-gate * to tell SS that more device process requests are on 77167c478bd9Sstevel@tonic-gate * their way after this one. 77177c478bd9Sstevel@tonic-gate */ 77187c478bd9Sstevel@tonic-gate if (i < (mdn->NumDevNodes - 1)) 77197c478bd9Sstevel@tonic-gate ss_make_device_node.flags |= SS_CSINITDEV_MORE_DEVICES; 77207c478bd9Sstevel@tonic-gate 77217c478bd9Sstevel@tonic-gate if (SocketServices(CSInitDev, &ss_make_device_node) != SUCCESS) { 77227c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 77237c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 77247c478bd9Sstevel@tonic-gate } /* CSInitDev */ 77257c478bd9Sstevel@tonic-gate } /* for (mdn->NumDevNodes) */ 77267c478bd9Sstevel@tonic-gate 77277c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 77287c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 77297c478bd9Sstevel@tonic-gate } 77307c478bd9Sstevel@tonic-gate 77317c478bd9Sstevel@tonic-gate /* 77327c478bd9Sstevel@tonic-gate * cs_remove_device_node - removes device nodes 77337c478bd9Sstevel@tonic-gate * 77347c478bd9Sstevel@tonic-gate * (see cs_make_device_node for a description of the calling 77357c478bd9Sstevel@tonic-gate * and return parameters) 77367c478bd9Sstevel@tonic-gate */ 77377c478bd9Sstevel@tonic-gate static int 77387c478bd9Sstevel@tonic-gate cs_remove_device_node(client_handle_t client_handle, remove_device_node_t *rdn) 77397c478bd9Sstevel@tonic-gate { 77407c478bd9Sstevel@tonic-gate 77417c478bd9Sstevel@tonic-gate /* 77427c478bd9Sstevel@tonic-gate * XXX - Note the assumption here that the make_device_node_t and 77437c478bd9Sstevel@tonic-gate * remove_device_node_t structures are identical. 77447c478bd9Sstevel@tonic-gate */ 77457c478bd9Sstevel@tonic-gate return (cs_make_device_node(client_handle, (make_device_node_t *)rdn)); 77467c478bd9Sstevel@tonic-gate } 77477c478bd9Sstevel@tonic-gate 77487c478bd9Sstevel@tonic-gate /* 77497c478bd9Sstevel@tonic-gate * cs_ddi_info - this function is used by clients that need to support 77507c478bd9Sstevel@tonic-gate * the xxx_getinfo function; this is CS_DDI_Info 77517c478bd9Sstevel@tonic-gate */ 77527c478bd9Sstevel@tonic-gate static int 77537c478bd9Sstevel@tonic-gate cs_ddi_info(cs_ddi_info_t *cdi) 77547c478bd9Sstevel@tonic-gate { 77557c478bd9Sstevel@tonic-gate cs_socket_t *sp; 77567c478bd9Sstevel@tonic-gate client_t *client; 77577c478bd9Sstevel@tonic-gate int client_lock_acquired; 77587c478bd9Sstevel@tonic-gate 77597c478bd9Sstevel@tonic-gate if (cdi->driver_name == NULL) 77607c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 77617c478bd9Sstevel@tonic-gate 77627c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 77637c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 77647c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s]\n", 77657c478bd9Sstevel@tonic-gate (int)cdi->Socket, cdi->driver_name); 77667c478bd9Sstevel@tonic-gate } 77677c478bd9Sstevel@tonic-gate #endif 77687c478bd9Sstevel@tonic-gate 77697c478bd9Sstevel@tonic-gate /* 77707c478bd9Sstevel@tonic-gate * Check to see if the socket number is in range - the system 77717c478bd9Sstevel@tonic-gate * framework may cause a client driver to call us with 77727c478bd9Sstevel@tonic-gate * a socket number that used to be present but isn't 77737c478bd9Sstevel@tonic-gate * anymore. This is not a bug, and it's OK to return 77747c478bd9Sstevel@tonic-gate * an error if the socket number is out of range. 77757c478bd9Sstevel@tonic-gate */ 77767c478bd9Sstevel@tonic-gate if (!CHECK_SOCKET_NUM(cdi->Socket, cs_globals.max_socket_num)) { 77777c478bd9Sstevel@tonic-gate 77787c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 77797c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 77807c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s] " 77817c478bd9Sstevel@tonic-gate "SOCKET IS OUT OF RANGE\n", 77827c478bd9Sstevel@tonic-gate (int)cdi->Socket, 77837c478bd9Sstevel@tonic-gate cdi->driver_name); 77847c478bd9Sstevel@tonic-gate } 77857c478bd9Sstevel@tonic-gate #endif 77867c478bd9Sstevel@tonic-gate 77877c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 77887c478bd9Sstevel@tonic-gate } /* if (!CHECK_SOCKET_NUM) */ 77897c478bd9Sstevel@tonic-gate 77907c478bd9Sstevel@tonic-gate /* 77917c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 77927c478bd9Sstevel@tonic-gate */ 77937c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(cdi->Socket)) == NULL) 77947c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 77957c478bd9Sstevel@tonic-gate 77967c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 77977c478bd9Sstevel@tonic-gate 77987c478bd9Sstevel@tonic-gate client = sp->client_list; 77997c478bd9Sstevel@tonic-gate while (client) { 78007c478bd9Sstevel@tonic-gate 78017c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 78027c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 78037c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d checking client [%s] " 78047c478bd9Sstevel@tonic-gate "handle 0x%x\n", 78057c478bd9Sstevel@tonic-gate (int)cdi->Socket, 78067c478bd9Sstevel@tonic-gate client->driver_name, 78077c478bd9Sstevel@tonic-gate (int)client->client_handle); 78087c478bd9Sstevel@tonic-gate } 78097c478bd9Sstevel@tonic-gate #endif 78107c478bd9Sstevel@tonic-gate 78117c478bd9Sstevel@tonic-gate if (client->driver_name != NULL) { 78127c478bd9Sstevel@tonic-gate if (!(strcmp(client->driver_name, cdi->driver_name))) { 78137c478bd9Sstevel@tonic-gate cdi->dip = client->dip; 78147c478bd9Sstevel@tonic-gate cdi->instance = client->instance; 78157c478bd9Sstevel@tonic-gate 78167c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 78177c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 78187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: found client [%s] " 78197c478bd9Sstevel@tonic-gate "instance %d handle 0x%x\n", 78207c478bd9Sstevel@tonic-gate client->driver_name, client->instance, 78217c478bd9Sstevel@tonic-gate (int)client->client_handle); 78227c478bd9Sstevel@tonic-gate } 78237c478bd9Sstevel@tonic-gate #endif 78247c478bd9Sstevel@tonic-gate 78257c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 78267c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 78277c478bd9Sstevel@tonic-gate } /* strcmp */ 78287c478bd9Sstevel@tonic-gate } /* driver_name != NULL */ 78297c478bd9Sstevel@tonic-gate client = client->next; 78307c478bd9Sstevel@tonic-gate } /* while (client) */ 78317c478bd9Sstevel@tonic-gate 78327c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 78337c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 78347c478bd9Sstevel@tonic-gate } 78357c478bd9Sstevel@tonic-gate 78367c478bd9Sstevel@tonic-gate /* 78377c478bd9Sstevel@tonic-gate * cs_sys_ctl - Card Services system control; this is CS_Sys_Ctl 78387c478bd9Sstevel@tonic-gate */ 78397c478bd9Sstevel@tonic-gate static int 78407c478bd9Sstevel@tonic-gate cs_sys_ctl(cs_sys_ctl_t *csc) 78417c478bd9Sstevel@tonic-gate { 78427c478bd9Sstevel@tonic-gate cs_socket_t *sp; 78437c478bd9Sstevel@tonic-gate client_t *cp; 78447c478bd9Sstevel@tonic-gate int sn, ret = CS_UNSUPPORTED_MODE; 78457c478bd9Sstevel@tonic-gate 78467c478bd9Sstevel@tonic-gate switch (csc->Action) { 78477c478bd9Sstevel@tonic-gate case CS_SYS_CTL_SEND_EVENT: 78487c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 78497c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(csc->Socket); 78507c478bd9Sstevel@tonic-gate else 78517c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(csc->client_handle); 78527c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 78537c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 78547c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 78557c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 78567c478bd9Sstevel@tonic-gate csc->Events &= CS_EVENT_CLIENT_EVENTS_MASK; 78577c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 78587c478bd9Sstevel@tonic-gate sp->events |= csc->Events; 78597c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_CLIENT) { 78607c478bd9Sstevel@tonic-gate if ((cp = cs_find_client(csc->client_handle, &ret)) == 78617c478bd9Sstevel@tonic-gate NULL) { 78627c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78637c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 78647c478bd9Sstevel@tonic-gate return (ret); 78657c478bd9Sstevel@tonic-gate } /* cs_find_client */ 78667c478bd9Sstevel@tonic-gate /* 78677c478bd9Sstevel@tonic-gate * Setup the events that we want to send to the client. 78687c478bd9Sstevel@tonic-gate */ 78697c478bd9Sstevel@tonic-gate cp->events |= (csc->Events & 78707c478bd9Sstevel@tonic-gate (cp->event_mask | cp->global_mask)); 78717c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_EVENT_CLIENT */ 78727c478bd9Sstevel@tonic-gate 78737c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_WAIT_SYNC) { 78747c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 78757c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78767c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 78777c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 78787c478bd9Sstevel@tonic-gate } else { 78797c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78807c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 78817c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_WAIT_SYNC */ 78827c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 78837c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 78847c478bd9Sstevel@tonic-gate break; 78857c478bd9Sstevel@tonic-gate default: 78867c478bd9Sstevel@tonic-gate break; 78877c478bd9Sstevel@tonic-gate } /* switch */ 78887c478bd9Sstevel@tonic-gate 78897c478bd9Sstevel@tonic-gate return (ret); 78907c478bd9Sstevel@tonic-gate } 78917c478bd9Sstevel@tonic-gate 78927c478bd9Sstevel@tonic-gate /* 78937c478bd9Sstevel@tonic-gate * cs_get_sp - returns pointer to per-socket structure for passed 78947c478bd9Sstevel@tonic-gate * socket number 78957c478bd9Sstevel@tonic-gate * 78967c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure 78977c478bd9Sstevel@tonic-gate * NULL - invalid socket number passed in 78987c478bd9Sstevel@tonic-gate */ 78997c478bd9Sstevel@tonic-gate static cs_socket_t * 79007c478bd9Sstevel@tonic-gate cs_get_sp(uint32_t sn) 79017c478bd9Sstevel@tonic-gate { 79027c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 79037c478bd9Sstevel@tonic-gate 79047c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 79057c478bd9Sstevel@tonic-gate return (NULL); 79067c478bd9Sstevel@tonic-gate 79077c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) 79087c478bd9Sstevel@tonic-gate return (NULL); 79097c478bd9Sstevel@tonic-gate 79107c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 79117c478bd9Sstevel@tonic-gate return (sp); 79127c478bd9Sstevel@tonic-gate 79137c478bd9Sstevel@tonic-gate return (NULL); 79147c478bd9Sstevel@tonic-gate } 79157c478bd9Sstevel@tonic-gate 79167c478bd9Sstevel@tonic-gate /* 79177c478bd9Sstevel@tonic-gate * cs_find_sp - searches socket list and returns pointer to passed socket 79187c478bd9Sstevel@tonic-gate * number 79197c478bd9Sstevel@tonic-gate * 79207c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure if found 79217c478bd9Sstevel@tonic-gate * NULL - socket not found 79227c478bd9Sstevel@tonic-gate */ 79237c478bd9Sstevel@tonic-gate static cs_socket_t * 79247c478bd9Sstevel@tonic-gate cs_find_sp(uint32_t sn) 79257c478bd9Sstevel@tonic-gate { 79267c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 79277c478bd9Sstevel@tonic-gate 79287c478bd9Sstevel@tonic-gate while (sp) { 79297c478bd9Sstevel@tonic-gate if (sp->socket_num == CS_GET_SOCKET_NUMBER(sn)) 79307c478bd9Sstevel@tonic-gate return (sp); 79317c478bd9Sstevel@tonic-gate sp = sp->next; 79327c478bd9Sstevel@tonic-gate } /* while */ 79337c478bd9Sstevel@tonic-gate 79347c478bd9Sstevel@tonic-gate return (NULL); 79357c478bd9Sstevel@tonic-gate } 79367c478bd9Sstevel@tonic-gate 79377c478bd9Sstevel@tonic-gate /* 79387c478bd9Sstevel@tonic-gate * cs_add_socket - add a socket 79397c478bd9Sstevel@tonic-gate * 79407c478bd9Sstevel@tonic-gate * call: sn - socket number to add 79417c478bd9Sstevel@tonic-gate * 79427c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 79437c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to add socket 79447c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - unable to get CIS window for socket 79457c478bd9Sstevel@tonic-gate * 79467c478bd9Sstevel@tonic-gate * We get called here once for each socket that the framework wants to 79477c478bd9Sstevel@tonic-gate * add. When we are called, the framework guarentees that until we 79487c478bd9Sstevel@tonic-gate * complete this routine, no other adapter instances will be allowed 79497c478bd9Sstevel@tonic-gate * to attach and thus no other PCE_ADD_SOCKET events will occur. 79507c478bd9Sstevel@tonic-gate * It is safe to call SS_InquireAdapter to get the number of 79517c478bd9Sstevel@tonic-gate * windows that the framework currently knows about. 79527c478bd9Sstevel@tonic-gate */ 79537c478bd9Sstevel@tonic-gate static uint32_t 79547c478bd9Sstevel@tonic-gate cs_add_socket(uint32_t sn) 79557c478bd9Sstevel@tonic-gate { 79567c478bd9Sstevel@tonic-gate cs_socket_t *sp; 79577c478bd9Sstevel@tonic-gate sservice_t sservice; 79587c478bd9Sstevel@tonic-gate get_cookies_and_dip_t *gcad; 79597c478bd9Sstevel@tonic-gate win_req_t win_req; 79607c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 79617c478bd9Sstevel@tonic-gate set_socket_t set_socket; 79627c478bd9Sstevel@tonic-gate cs_window_t *cw; 79637c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 79647c478bd9Sstevel@tonic-gate inquire_window_t inquire_window; 79657c478bd9Sstevel@tonic-gate int ret, added_windows; 79667c478bd9Sstevel@tonic-gate 79677c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 79687c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 79697c478bd9Sstevel@tonic-gate 79707c478bd9Sstevel@tonic-gate /* 79717c478bd9Sstevel@tonic-gate * See if this socket has already been added - if it has, we 79727c478bd9Sstevel@tonic-gate * fail this. If we can't find the socket, then allocate 79737c478bd9Sstevel@tonic-gate * a new socket structure. If we do find the socket, then 79747c478bd9Sstevel@tonic-gate * check to see if it's already added; if it is, then 79757c478bd9Sstevel@tonic-gate * this is an error and return CS_BAD_SOCKET; if not, 79767c478bd9Sstevel@tonic-gate * then traverse the socket structure list and add this 79777c478bd9Sstevel@tonic-gate * next socket strcture to the end of the list. 79787c478bd9Sstevel@tonic-gate * XXX What about locking this list while we update it? Is 79797c478bd9Sstevel@tonic-gate * that necessary since we're using the SOCKET_IS_VALID 79807c478bd9Sstevel@tonic-gate * flag and since we never delete a socket from the 79817c478bd9Sstevel@tonic-gate * list once it's been added? 79827c478bd9Sstevel@tonic-gate */ 79837c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) { 79847c478bd9Sstevel@tonic-gate cs_socket_t *spp = cs_globals.sp; 79857c478bd9Sstevel@tonic-gate 79867c478bd9Sstevel@tonic-gate sp = (cs_socket_t *)kmem_zalloc(sizeof (cs_socket_t), KM_SLEEP); 79877c478bd9Sstevel@tonic-gate 79887c478bd9Sstevel@tonic-gate if (cs_globals.sp == NULL) 79897c478bd9Sstevel@tonic-gate cs_globals.sp = sp; 79907c478bd9Sstevel@tonic-gate else 79917c478bd9Sstevel@tonic-gate while (spp) { 79927c478bd9Sstevel@tonic-gate if (spp->next == NULL) { 79937c478bd9Sstevel@tonic-gate spp->next = sp; 79947c478bd9Sstevel@tonic-gate break; 79957c478bd9Sstevel@tonic-gate } /* if */ 79967c478bd9Sstevel@tonic-gate spp = spp->next; 79977c478bd9Sstevel@tonic-gate } /* while */ 79987c478bd9Sstevel@tonic-gate 79997c478bd9Sstevel@tonic-gate } else { 80007c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 80017c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 80027c478bd9Sstevel@tonic-gate } /* cs_find_sp */ 80037c478bd9Sstevel@tonic-gate 80047c478bd9Sstevel@tonic-gate /* 80057c478bd9Sstevel@tonic-gate * Setup the socket number 80067c478bd9Sstevel@tonic-gate */ 80077c478bd9Sstevel@tonic-gate sp->socket_num = sn; 80087c478bd9Sstevel@tonic-gate 80097c478bd9Sstevel@tonic-gate /* 80107c478bd9Sstevel@tonic-gate * Find out how many windows the framework knows about 80117c478bd9Sstevel@tonic-gate * so far. If this number of windows is greater 80127c478bd9Sstevel@tonic-gate * than our current window count, bump up our 80137c478bd9Sstevel@tonic-gate * current window count. 80147c478bd9Sstevel@tonic-gate * XXX Note that there is a BIG assumption here and that 80157c478bd9Sstevel@tonic-gate * is that once the framework tells us that it has 80167c478bd9Sstevel@tonic-gate * a window (as reflected in the NumWindows 80177c478bd9Sstevel@tonic-gate * value) it can NEVER remove that window. 80187c478bd9Sstevel@tonic-gate * When we really get the drop socket and drop 80197c478bd9Sstevel@tonic-gate * window mechanism working correctly, we'll have 80207c478bd9Sstevel@tonic-gate * to revisit this. 80217c478bd9Sstevel@tonic-gate */ 80227c478bd9Sstevel@tonic-gate SocketServices(SS_InquireAdapter, &inquire_adapter); 80237c478bd9Sstevel@tonic-gate 80247c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 80257c478bd9Sstevel@tonic-gate added_windows = inquire_adapter.NumWindows - cs_globals.num_windows; 80267c478bd9Sstevel@tonic-gate if (added_windows > 0) { 80277c478bd9Sstevel@tonic-gate if (cs_add_windows(added_windows, 80287c478bd9Sstevel@tonic-gate cs_globals.num_windows) != CS_SUCCESS) { 80297c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80307c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80317c478bd9Sstevel@tonic-gate } /* cs_add_windows */ 80327c478bd9Sstevel@tonic-gate 80337c478bd9Sstevel@tonic-gate cs_globals.num_windows = inquire_adapter.NumWindows; 80347c478bd9Sstevel@tonic-gate 80357c478bd9Sstevel@tonic-gate } /* if (added_windows) */ 80367c478bd9Sstevel@tonic-gate 80377c478bd9Sstevel@tonic-gate /* 80387c478bd9Sstevel@tonic-gate * Find a window that we can use for this socket's CIS window. 80397c478bd9Sstevel@tonic-gate */ 80407c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 80417c478bd9Sstevel@tonic-gate 80427c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 80437c478bd9Sstevel@tonic-gate convert_speed.nS = CIS_DEFAULT_SPEED; 80447c478bd9Sstevel@tonic-gate (void) cs_convert_speed(&convert_speed); 80457c478bd9Sstevel@tonic-gate 80467c478bd9Sstevel@tonic-gate win_req.win_params.AccessSpeed = convert_speed.devspeed; 80477c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8); 80487c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_MEMORY_TYPE_CM); 80497c478bd9Sstevel@tonic-gate win_req.Base.base = 0; 80507c478bd9Sstevel@tonic-gate win_req.Size = 0; 80517c478bd9Sstevel@tonic-gate 80527c478bd9Sstevel@tonic-gate if ((ret = cs_find_mem_window(sp->socket_num, &win_req, 80537c478bd9Sstevel@tonic-gate &sp->cis_win_num)) != CS_SUCCESS) { 80547c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80557c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 80567c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't get CIS " 80577c478bd9Sstevel@tonic-gate "window - error 0x%x\n", 80587c478bd9Sstevel@tonic-gate sp->socket_num, ret); 80597c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80607c478bd9Sstevel@tonic-gate } /* cs_find_mem_window */ 80617c478bd9Sstevel@tonic-gate 80627c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) { 80637c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80647c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80657c478bd9Sstevel@tonic-gate } 80667c478bd9Sstevel@tonic-gate 80677c478bd9Sstevel@tonic-gate inquire_window.window = sp->cis_win_num; 80687c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &inquire_window); 80697c478bd9Sstevel@tonic-gate 80707c478bd9Sstevel@tonic-gate /* 80717c478bd9Sstevel@tonic-gate * If the CIS window is a variable sized window, then use 80727c478bd9Sstevel@tonic-gate * the size that cs_find_mem_window returned to us, 80737c478bd9Sstevel@tonic-gate * since this will be the minimum size that we can 80747c478bd9Sstevel@tonic-gate * set this window to. If the CIS window is a fixed 80757c478bd9Sstevel@tonic-gate * sized window, then use the system pagesize as the 80767c478bd9Sstevel@tonic-gate * CIS window size. 80777c478bd9Sstevel@tonic-gate */ 80787c478bd9Sstevel@tonic-gate if (inquire_window.mem_win_char.MemWndCaps & WC_SIZE) { 80797c478bd9Sstevel@tonic-gate sp->cis_win_size = win_req.Size; 80807c478bd9Sstevel@tonic-gate } else { 80817c478bd9Sstevel@tonic-gate sp->cis_win_size = PAGESIZE; 80827c478bd9Sstevel@tonic-gate } 80837c478bd9Sstevel@tonic-gate 80847c478bd9Sstevel@tonic-gate cw->state |= (CW_CIS | CW_ALLOCATED); 80857c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 80867c478bd9Sstevel@tonic-gate 80877c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80887c478bd9Sstevel@tonic-gate 80897c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 80907c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 80917c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d using CIS window %d " 80927c478bd9Sstevel@tonic-gate "size 0x%x\n", (int)sp->socket_num, 80937c478bd9Sstevel@tonic-gate (int)sp->cis_win_num, 80947c478bd9Sstevel@tonic-gate (int)sp->cis_win_size); 80957c478bd9Sstevel@tonic-gate } 80967c478bd9Sstevel@tonic-gate #endif 80977c478bd9Sstevel@tonic-gate 80987c478bd9Sstevel@tonic-gate /* 80997c478bd9Sstevel@tonic-gate * Get the adapter information associated with this socket so 81007c478bd9Sstevel@tonic-gate * that we can initialize the mutexes, condition variables, 81017c478bd9Sstevel@tonic-gate * soft interrupt handler and per-socket adapter info. 81027c478bd9Sstevel@tonic-gate */ 81037c478bd9Sstevel@tonic-gate gcad = &sservice.get_cookies; 81047c478bd9Sstevel@tonic-gate gcad->socket = sp->socket_num; 81057c478bd9Sstevel@tonic-gate if (SocketServices(CSGetCookiesAndDip, &sservice) != SUCCESS) { 81067c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d CSGetCookiesAndDip " 81077c478bd9Sstevel@tonic-gate "failure\n", sp->socket_num); 81087c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 81097c478bd9Sstevel@tonic-gate } /* CSGetCookiesAndDip */ 81107c478bd9Sstevel@tonic-gate 81117c478bd9Sstevel@tonic-gate /* 81127c478bd9Sstevel@tonic-gate * Save the iblock and idev cookies for RegisterClient 81137c478bd9Sstevel@tonic-gate */ 81147c478bd9Sstevel@tonic-gate sp->iblk = gcad->iblock; 81157c478bd9Sstevel@tonic-gate sp->idev = gcad->idevice; 81167c478bd9Sstevel@tonic-gate 81177c478bd9Sstevel@tonic-gate /* 81187c478bd9Sstevel@tonic-gate * Setup the per-socket adapter info 81197c478bd9Sstevel@tonic-gate */ 81207c478bd9Sstevel@tonic-gate sp->adapter.flags = 0; 81217c478bd9Sstevel@tonic-gate (void) strcpy(sp->adapter.name, gcad->adapter_info.name); 81227c478bd9Sstevel@tonic-gate sp->adapter.major = gcad->adapter_info.major; 81237c478bd9Sstevel@tonic-gate sp->adapter.minor = gcad->adapter_info.minor; 81247c478bd9Sstevel@tonic-gate sp->adapter.instance = ddi_get_instance(gcad->dip); 81257c478bd9Sstevel@tonic-gate sp->adapter.number = gcad->adapter_info.number; 81267c478bd9Sstevel@tonic-gate sp->adapter.num_sockets = gcad->adapter_info.num_sockets; 81277c478bd9Sstevel@tonic-gate sp->adapter.first_socket = gcad->adapter_info.first_socket; 81287c478bd9Sstevel@tonic-gate 81297c478bd9Sstevel@tonic-gate /* Setup for cs_event and cs_event_thread */ 81307c478bd9Sstevel@tonic-gate mutex_init(&sp->lock, NULL, MUTEX_DRIVER, *(gcad->iblock)); 81317c478bd9Sstevel@tonic-gate mutex_init(&sp->client_lock, NULL, MUTEX_DRIVER, NULL); 81327c478bd9Sstevel@tonic-gate mutex_init(&sp->cis_lock, NULL, MUTEX_DRIVER, NULL); 81337c478bd9Sstevel@tonic-gate 81347c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 81357c478bd9Sstevel@tonic-gate mutex_init(&sp->ss_thread_lock, NULL, MUTEX_DRIVER, NULL); 81367c478bd9Sstevel@tonic-gate 81377c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_MUTEX; 81387c478bd9Sstevel@tonic-gate 81397c478bd9Sstevel@tonic-gate /* Setup for cs_event_thread */ 81407c478bd9Sstevel@tonic-gate cv_init(&sp->thread_cv, NULL, CV_DRIVER, NULL); 81417c478bd9Sstevel@tonic-gate cv_init(&sp->caller_cv, NULL, CV_DRIVER, NULL); 81427c478bd9Sstevel@tonic-gate cv_init(&sp->reset_cv, NULL, CV_DRIVER, NULL); 81437c478bd9Sstevel@tonic-gate 81447c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 81457c478bd9Sstevel@tonic-gate cv_init(&sp->ss_thread_cv, NULL, CV_DRIVER, NULL); 81467c478bd9Sstevel@tonic-gate cv_init(&sp->ss_caller_cv, NULL, CV_DRIVER, NULL); 81477c478bd9Sstevel@tonic-gate 81487c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_CV; 81497c478bd9Sstevel@tonic-gate 81507c478bd9Sstevel@tonic-gate /* 81517c478bd9Sstevel@tonic-gate * If we haven't installed it yet, then install the soft interrupt 81527c478bd9Sstevel@tonic-gate * handler and save away the softint id. 81537c478bd9Sstevel@tonic-gate */ 81547c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR)) { 81557c478bd9Sstevel@tonic-gate if (ddi_add_softintr(gcad->dip, DDI_SOFTINT_HIGH, 81567c478bd9Sstevel@tonic-gate &sp->softint_id, 81577c478bd9Sstevel@tonic-gate NULL, NULL, 81587c478bd9Sstevel@tonic-gate cs_socket_event_softintr, 81597c478bd9Sstevel@tonic-gate (caddr_t)NULL) != DDI_SUCCESS) { 81607c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't add " 81617c478bd9Sstevel@tonic-gate "softintr\n", sp->socket_num); 81627c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 81637c478bd9Sstevel@tonic-gate } /* ddi_add_softintr */ 81647c478bd9Sstevel@tonic-gate 81657c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 81667c478bd9Sstevel@tonic-gate cs_globals.softint_id = sp->softint_id; 81677c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SOFTINTR; 81687c478bd9Sstevel@tonic-gate /* XXX this timer is hokey at best... */ 81697c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 81707c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 81717c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 81727c478bd9Sstevel@tonic-gate } else { 81737c478bd9Sstevel@tonic-gate /* 81747c478bd9Sstevel@tonic-gate * We've already added the soft interrupt handler, so just 81757c478bd9Sstevel@tonic-gate * store away the softint id. 81767c478bd9Sstevel@tonic-gate */ 81777c478bd9Sstevel@tonic-gate sp->softint_id = cs_globals.softint_id; 81787c478bd9Sstevel@tonic-gate } /* if (!GLOBAL_INIT_STATE_SOFTINTR) */ 81797c478bd9Sstevel@tonic-gate 81807c478bd9Sstevel@tonic-gate /* 81817c478bd9Sstevel@tonic-gate * While this next flag doesn't really describe a per-socket 81827c478bd9Sstevel@tonic-gate * resource, we still set it for each socket. When the soft 81837c478bd9Sstevel@tonic-gate * interrupt handler finally gets removed in cs_deinit, this 81847c478bd9Sstevel@tonic-gate * flag will get cleared. 81857c478bd9Sstevel@tonic-gate */ 81867c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_SOFTINTR; 81877c478bd9Sstevel@tonic-gate 81887c478bd9Sstevel@tonic-gate /* 81897c478bd9Sstevel@tonic-gate * Socket Services defaults all sockets to power off and 81907c478bd9Sstevel@tonic-gate * clears all event masks. We want to receive at least 81917c478bd9Sstevel@tonic-gate * card insertion events, so enable them. Turn off power 81927c478bd9Sstevel@tonic-gate * to the socket as well. We will turn it on again when 81937c478bd9Sstevel@tonic-gate * we get a card insertion event. 81947c478bd9Sstevel@tonic-gate */ 81957c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 81967c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 81977c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 81987c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 81997c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 82007c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 82017c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 82027c478bd9Sstevel@tonic-gate 82037c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 82047c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 82057c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 82067c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 82077c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 82087c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 82097c478bd9Sstevel@tonic-gate 82107c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 82117c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d SS_SetSocket " 82127c478bd9Sstevel@tonic-gate "failure %d\n", sp->socket_num, ret); 82137c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 82147c478bd9Sstevel@tonic-gate } /* SS_SetSocket */ 82157c478bd9Sstevel@tonic-gate 82167c478bd9Sstevel@tonic-gate /* 82177c478bd9Sstevel@tonic-gate * The various socket-specific variables are now set up, so 82187c478bd9Sstevel@tonic-gate * increment the global socket count and also mark the 82197c478bd9Sstevel@tonic-gate * socket as available. We need to set this before we 82207c478bd9Sstevel@tonic-gate * start any of the per-socket threads so that the threads 82217c478bd9Sstevel@tonic-gate * can get a valid socket pointer when they start. 82227c478bd9Sstevel@tonic-gate */ 82237c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 82247c478bd9Sstevel@tonic-gate cs_globals.num_sockets++; 82257c478bd9Sstevel@tonic-gate cs_globals.max_socket_num = 82267c478bd9Sstevel@tonic-gate max(cs_globals.max_socket_num, sp->socket_num + 1); 82277c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 82287c478bd9Sstevel@tonic-gate sp->flags = SOCKET_IS_VALID; 82297c478bd9Sstevel@tonic-gate 82307c478bd9Sstevel@tonic-gate /* 82317c478bd9Sstevel@tonic-gate * Create the per-socket event handler thread. 82327c478bd9Sstevel@tonic-gate */ 82337c478bd9Sstevel@tonic-gate sp->event_thread = CREATE_SOCKET_EVENT_THREAD(cs_event_thread, 82347c478bd9Sstevel@tonic-gate (uintptr_t)sn); 82357c478bd9Sstevel@tonic-gate 82367c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 82377c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_THREAD; 82387c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 82397c478bd9Sstevel@tonic-gate 82407c478bd9Sstevel@tonic-gate /* 82417c478bd9Sstevel@tonic-gate * Create the per-socket Socket Services work thread. 82427c478bd9Sstevel@tonic-gate */ 82437c478bd9Sstevel@tonic-gate sp->ss_thread = CREATE_SOCKET_EVENT_THREAD(cs_ss_thread, 82447c478bd9Sstevel@tonic-gate (uintptr_t)sn); 82457c478bd9Sstevel@tonic-gate 82467c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 82477c478bd9Sstevel@tonic-gate sp->init_state |= (SOCKET_INIT_STATE_SS_THREAD | 82487c478bd9Sstevel@tonic-gate SOCKET_INIT_STATE_READY); 82497c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 82507c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 82517c478bd9Sstevel@tonic-gate 82527c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 82537c478bd9Sstevel@tonic-gate } 82547c478bd9Sstevel@tonic-gate 82557c478bd9Sstevel@tonic-gate /* 82567c478bd9Sstevel@tonic-gate * cs_drop_socket - drop a socket 82577c478bd9Sstevel@tonic-gate * 82587c478bd9Sstevel@tonic-gate * call: sn - socket number to drop 82597c478bd9Sstevel@tonic-gate * 82607c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 82617c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to drop socket 82627c478bd9Sstevel@tonic-gate */ 82637c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 82647c478bd9Sstevel@tonic-gate static uint32_t 82657c478bd9Sstevel@tonic-gate cs_drop_socket(uint32_t sn) 82667c478bd9Sstevel@tonic-gate { 82677c478bd9Sstevel@tonic-gate #ifdef XXX 82687c478bd9Sstevel@tonic-gate cs_socket_t *sp; 82697c478bd9Sstevel@tonic-gate 82707c478bd9Sstevel@tonic-gate /* 82717c478bd9Sstevel@tonic-gate * Tell the socket event thread to exit and then wait for it 82727c478bd9Sstevel@tonic-gate * to do so. 82737c478bd9Sstevel@tonic-gate */ 82747c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 82757c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_THREAD_EXIT; 82767c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 82777c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 82787c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 82797c478bd9Sstevel@tonic-gate 82807c478bd9Sstevel@tonic-gate /* 82817c478bd9Sstevel@tonic-gate * Tell the socket SS thread to exit and then wait for it 82827c478bd9Sstevel@tonic-gate * to do so. 82837c478bd9Sstevel@tonic-gate */ 82847c478bd9Sstevel@tonic-gate 82857c478bd9Sstevel@tonic-gate /* 82867c478bd9Sstevel@tonic-gate * Mark the socket as dropped. 82877c478bd9Sstevel@tonic-gate */ 82887c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_VALID; 82897c478bd9Sstevel@tonic-gate 82907c478bd9Sstevel@tonic-gate #endif /* XXX */ 82917c478bd9Sstevel@tonic-gate 82927c478bd9Sstevel@tonic-gate /* XXX for now don't allow dropping sockets XXX */ 82937c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 82947c478bd9Sstevel@tonic-gate } 82957c478bd9Sstevel@tonic-gate 82967c478bd9Sstevel@tonic-gate /* 82977c478bd9Sstevel@tonic-gate * cs_get_socket - returns the socket and function numbers and a pointer 82987c478bd9Sstevel@tonic-gate * to the socket structure 82997c478bd9Sstevel@tonic-gate * 83007c478bd9Sstevel@tonic-gate * calling: client_handle_t client_handle - client handle to extract 83017c478bd9Sstevel@tonic-gate * socket number from 83027c478bd9Sstevel@tonic-gate * uint32_t *socket - pointer to socket number to use if 83037c478bd9Sstevel@tonic-gate * client_handle is for the SS client; 83047c478bd9Sstevel@tonic-gate * this value will be filled in on 83057c478bd9Sstevel@tonic-gate * return with the correct socket 83067c478bd9Sstevel@tonic-gate * and function numbers if we 83077c478bd9Sstevel@tonic-gate * return CS_SUCCESS 83087c478bd9Sstevel@tonic-gate * uint32_t *function - pointer to return function number into 83097c478bd9Sstevel@tonic-gate * if not NULL 83107c478bd9Sstevel@tonic-gate * cs_socket_t **sp - pointer to a pointer where a pointer 83117c478bd9Sstevel@tonic-gate * to the socket struct will be 83127c478bd9Sstevel@tonic-gate * placed if this is non-NULL 83137c478bd9Sstevel@tonic-gate * client_t **clp - pointer to a pointer where a pointer 83147c478bd9Sstevel@tonic-gate * to the client struct will be 83157c478bd9Sstevel@tonic-gate * placed if this is non-NULL 83167c478bd9Sstevel@tonic-gate * 83177c478bd9Sstevel@tonic-gate * The socket and function numbers are derived as follows: 83187c478bd9Sstevel@tonic-gate * 83197c478bd9Sstevel@tonic-gate * Client Type Socket Number Function Number 83207c478bd9Sstevel@tonic-gate * PC card client From client_handle From client_handle 83217c478bd9Sstevel@tonic-gate * Socket Services client From *socket From *socket 83227c478bd9Sstevel@tonic-gate * CSI client From client_handle From *socket 83237c478bd9Sstevel@tonic-gate */ 83247c478bd9Sstevel@tonic-gate static uint32_t 83257c478bd9Sstevel@tonic-gate cs_get_socket(client_handle_t client_handle, uint32_t *socket, 83267c478bd9Sstevel@tonic-gate uint32_t *function, cs_socket_t **csp, client_t **clp) 83277c478bd9Sstevel@tonic-gate { 83287c478bd9Sstevel@tonic-gate cs_socket_t *sp; 83297c478bd9Sstevel@tonic-gate client_t *client; 83307c478bd9Sstevel@tonic-gate uint32_t sn, fn; 83317c478bd9Sstevel@tonic-gate int ret; 83327c478bd9Sstevel@tonic-gate 83337c478bd9Sstevel@tonic-gate sn = *socket; 83347c478bd9Sstevel@tonic-gate 83357c478bd9Sstevel@tonic-gate /* 83367c478bd9Sstevel@tonic-gate * If this is the Socket Services client, then return the 83377c478bd9Sstevel@tonic-gate * socket and function numbers specified in the passed 83387c478bd9Sstevel@tonic-gate * socket number parameter, otherwise extract the socket 83397c478bd9Sstevel@tonic-gate * and function numbers from the client handle. 83407c478bd9Sstevel@tonic-gate */ 83417c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 83427c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(sn); 83437c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(sn); 83447c478bd9Sstevel@tonic-gate } else { 83457c478bd9Sstevel@tonic-gate fn = GET_CLIENT_FUNCTION(client_handle); 83467c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(client_handle); 83477c478bd9Sstevel@tonic-gate } 83487c478bd9Sstevel@tonic-gate 83497c478bd9Sstevel@tonic-gate /* 83507c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 83517c478bd9Sstevel@tonic-gate */ 83527c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(sn, cs_globals.max_socket_num))) 83537c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 83547c478bd9Sstevel@tonic-gate 83557c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 83567c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 83577c478bd9Sstevel@tonic-gate 83587c478bd9Sstevel@tonic-gate /* 83597c478bd9Sstevel@tonic-gate * If we were given a pointer, then fill it in with a pointer 83607c478bd9Sstevel@tonic-gate * to this socket. 83617c478bd9Sstevel@tonic-gate */ 83627c478bd9Sstevel@tonic-gate if (csp) 83637c478bd9Sstevel@tonic-gate *csp = sp; 83647c478bd9Sstevel@tonic-gate 83657c478bd9Sstevel@tonic-gate /* 83667c478bd9Sstevel@tonic-gate * Search for the client; if it's not found, return an error. 83677c478bd9Sstevel@tonic-gate */ 83687c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 83697c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &ret))) { 83707c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 83717c478bd9Sstevel@tonic-gate return (ret); 83727c478bd9Sstevel@tonic-gate } 83737c478bd9Sstevel@tonic-gate 83747c478bd9Sstevel@tonic-gate /* 83757c478bd9Sstevel@tonic-gate * If we're a CIS client, then extract the function number 83767c478bd9Sstevel@tonic-gate * from the socket number. 83777c478bd9Sstevel@tonic-gate */ 83787c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) 83797c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(*socket); 83807c478bd9Sstevel@tonic-gate 83817c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 83827c478bd9Sstevel@tonic-gate 83837c478bd9Sstevel@tonic-gate /* 83847c478bd9Sstevel@tonic-gate * Return the found client pointer if the caller wants it. 83857c478bd9Sstevel@tonic-gate */ 83867c478bd9Sstevel@tonic-gate if (clp) 83877c478bd9Sstevel@tonic-gate *clp = client; 83887c478bd9Sstevel@tonic-gate 83897c478bd9Sstevel@tonic-gate /* 83907c478bd9Sstevel@tonic-gate * Return a socket number that is made up of the socket number 83917c478bd9Sstevel@tonic-gate * and the function number. 83927c478bd9Sstevel@tonic-gate */ 83937c478bd9Sstevel@tonic-gate *socket = CS_MAKE_SOCKET_NUMBER(sn, fn); 83947c478bd9Sstevel@tonic-gate 83957c478bd9Sstevel@tonic-gate /* 83967c478bd9Sstevel@tonic-gate * Return the function number if the caller wants it. 83977c478bd9Sstevel@tonic-gate */ 83987c478bd9Sstevel@tonic-gate if (function) 83997c478bd9Sstevel@tonic-gate *function = fn; 84007c478bd9Sstevel@tonic-gate 84017c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 84027c478bd9Sstevel@tonic-gate } 84037c478bd9Sstevel@tonic-gate 84047c478bd9Sstevel@tonic-gate /* 84057c478bd9Sstevel@tonic-gate * cs_get_wp - returns pointer to passed window number 84067c478bd9Sstevel@tonic-gate * 84077c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 84087c478bd9Sstevel@tonic-gate * NULL - if invalid window number passed in 84097c478bd9Sstevel@tonic-gate */ 84107c478bd9Sstevel@tonic-gate static cs_window_t * 84117c478bd9Sstevel@tonic-gate cs_get_wp(uint32_t wn) 84127c478bd9Sstevel@tonic-gate { 84137c478bd9Sstevel@tonic-gate cs_window_t *cw; 84147c478bd9Sstevel@tonic-gate 84157c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 84167c478bd9Sstevel@tonic-gate return (NULL); 84177c478bd9Sstevel@tonic-gate 84187c478bd9Sstevel@tonic-gate if ((cw = cs_find_wp(wn)) == NULL) 84197c478bd9Sstevel@tonic-gate return (NULL); 84207c478bd9Sstevel@tonic-gate 84217c478bd9Sstevel@tonic-gate if (cw->state & CW_WINDOW_VALID) 84227c478bd9Sstevel@tonic-gate return (cw); 84237c478bd9Sstevel@tonic-gate 84247c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 84257c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 84267c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_wp(): wn=%d cw=%p\n", 84277c478bd9Sstevel@tonic-gate (int)wn, (void *)cw); 84287c478bd9Sstevel@tonic-gate } 84297c478bd9Sstevel@tonic-gate #endif 84307c478bd9Sstevel@tonic-gate 84317c478bd9Sstevel@tonic-gate return (NULL); 84327c478bd9Sstevel@tonic-gate } 84337c478bd9Sstevel@tonic-gate 84347c478bd9Sstevel@tonic-gate /* 84357c478bd9Sstevel@tonic-gate * cs_find_wp - searches window list and returns pointer to passed window 84367c478bd9Sstevel@tonic-gate * number 84377c478bd9Sstevel@tonic-gate * 84387c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 84397c478bd9Sstevel@tonic-gate * NULL - window not found 84407c478bd9Sstevel@tonic-gate */ 84417c478bd9Sstevel@tonic-gate static cs_window_t * 84427c478bd9Sstevel@tonic-gate cs_find_wp(uint32_t wn) 84437c478bd9Sstevel@tonic-gate { 84447c478bd9Sstevel@tonic-gate cs_window_t *cw = cs_globals.cw; 84457c478bd9Sstevel@tonic-gate 84467c478bd9Sstevel@tonic-gate while (cw) { 84477c478bd9Sstevel@tonic-gate if (cw->window_num == wn) 84487c478bd9Sstevel@tonic-gate return (cw); 84497c478bd9Sstevel@tonic-gate cw = cw->next; 84507c478bd9Sstevel@tonic-gate } /* while */ 84517c478bd9Sstevel@tonic-gate 84527c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 84537c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 84547c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_find_wp(): wn=%d window_num=%d cw=%p\n", 84557c478bd9Sstevel@tonic-gate (int)wn, (int)cw->window_num, (void *)cw); 84567c478bd9Sstevel@tonic-gate } 84577c478bd9Sstevel@tonic-gate #endif 84587c478bd9Sstevel@tonic-gate 84597c478bd9Sstevel@tonic-gate return (NULL); 84607c478bd9Sstevel@tonic-gate } 84617c478bd9Sstevel@tonic-gate 84627c478bd9Sstevel@tonic-gate /* 84637c478bd9Sstevel@tonic-gate * cs_add_windows - adds number of windows specified in "aw" to 84647c478bd9Sstevel@tonic-gate * the global window list; start the window 84657c478bd9Sstevel@tonic-gate * numbering at "bn" 84667c478bd9Sstevel@tonic-gate * 84677c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - if windows added sucessfully 84687c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if unable to add windows 84697c478bd9Sstevel@tonic-gate * 84707c478bd9Sstevel@tonic-gate * Note: The window list must be protected by a lock by the caller. 84717c478bd9Sstevel@tonic-gate */ 84727c478bd9Sstevel@tonic-gate static int 84737c478bd9Sstevel@tonic-gate cs_add_windows(int aw, uint32_t bn) 84747c478bd9Sstevel@tonic-gate { 84757c478bd9Sstevel@tonic-gate cs_window_t *cwp = cs_globals.cw; 84767c478bd9Sstevel@tonic-gate cs_window_t *cw, *cwpp; 84777c478bd9Sstevel@tonic-gate 84787c478bd9Sstevel@tonic-gate if (aw <= 0) 84797c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 84807c478bd9Sstevel@tonic-gate 84817c478bd9Sstevel@tonic-gate while (cwp) { 84827c478bd9Sstevel@tonic-gate cwpp = cwp; 84837c478bd9Sstevel@tonic-gate cwp = cwp->next; 84847c478bd9Sstevel@tonic-gate } 84857c478bd9Sstevel@tonic-gate 84867c478bd9Sstevel@tonic-gate while (aw--) { 84877c478bd9Sstevel@tonic-gate cw = (cs_window_t *)kmem_zalloc(sizeof (cs_window_t), KM_SLEEP); 84887c478bd9Sstevel@tonic-gate 84897c478bd9Sstevel@tonic-gate if (cs_globals.cw == NULL) { 84907c478bd9Sstevel@tonic-gate cs_globals.cw = cw; 84917c478bd9Sstevel@tonic-gate cwpp = cs_globals.cw; 84927c478bd9Sstevel@tonic-gate } else { 84937c478bd9Sstevel@tonic-gate cwpp->next = cw; 84947c478bd9Sstevel@tonic-gate cwpp = cwpp->next; 84957c478bd9Sstevel@tonic-gate } 84967c478bd9Sstevel@tonic-gate 84977c478bd9Sstevel@tonic-gate cwpp->window_num = bn++; 84987c478bd9Sstevel@tonic-gate cwpp->state = CW_WINDOW_VALID; 84997c478bd9Sstevel@tonic-gate 85007c478bd9Sstevel@tonic-gate } /* while (aw) */ 85017c478bd9Sstevel@tonic-gate 85027c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 85037c478bd9Sstevel@tonic-gate } 85047c478bd9Sstevel@tonic-gate 85057c478bd9Sstevel@tonic-gate /* 85067c478bd9Sstevel@tonic-gate * cs_ss_init - initialize CS items that need to wait until we receive 85077c478bd9Sstevel@tonic-gate * a PCE_SS_INIT_STATE/PCE_SS_STATE_INIT event 85087c478bd9Sstevel@tonic-gate * 85097c478bd9Sstevel@tonic-gate * return: CS_SUCESS - if sucessfully initialized 85107c478bd9Sstevel@tonic-gate * (various) if error initializing 85117c478bd9Sstevel@tonic-gate * 85127c478bd9Sstevel@tonic-gate * At this point, we expect that Socket Services has setup the 85137c478bd9Sstevel@tonic-gate * following global variables for us: 85147c478bd9Sstevel@tonic-gate * 85157c478bd9Sstevel@tonic-gate * cs_socket_services - Socket Services entry point 85167c478bd9Sstevel@tonic-gate * cis_parser - CIS parser entry point 85177c478bd9Sstevel@tonic-gate */ 85187c478bd9Sstevel@tonic-gate static uint32_t 85197c478bd9Sstevel@tonic-gate cs_ss_init() 85207c478bd9Sstevel@tonic-gate { 85217c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 85227c478bd9Sstevel@tonic-gate csregister_t csr; 85237c478bd9Sstevel@tonic-gate uint32_t ret; 85247c478bd9Sstevel@tonic-gate 85257c478bd9Sstevel@tonic-gate /* 85267c478bd9Sstevel@tonic-gate * Fill out the parameters for CISP_CIS_SETUP 85277c478bd9Sstevel@tonic-gate */ 85287c478bd9Sstevel@tonic-gate csr.cs_magic = PCCS_MAGIC; 85297c478bd9Sstevel@tonic-gate csr.cs_version = PCCS_VERSION; 85307c478bd9Sstevel@tonic-gate csr.cs_card_services = CardServices; 85317c478bd9Sstevel@tonic-gate csr.cs_event = NULL; 85327c478bd9Sstevel@tonic-gate 85337c478bd9Sstevel@tonic-gate /* 85347c478bd9Sstevel@tonic-gate * Call into the CIS module and tell it what the private 85357c478bd9Sstevel@tonic-gate * Card Services entry point is. The CIS module will 85367c478bd9Sstevel@tonic-gate * call us back at CardServices(CISRegister, ...) 85377c478bd9Sstevel@tonic-gate * with the address of various CIS-specific global 85387c478bd9Sstevel@tonic-gate * data structures. 85397c478bd9Sstevel@tonic-gate */ 85407c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_SETUP, &csr); 85417c478bd9Sstevel@tonic-gate 85427c478bd9Sstevel@tonic-gate /* 85437c478bd9Sstevel@tonic-gate * Register with the Card Services kernel stubs module 85447c478bd9Sstevel@tonic-gate */ 85457c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 85467c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_REGISTER; 85477c478bd9Sstevel@tonic-gate rcs.cardservices = CardServices; 85487c478bd9Sstevel@tonic-gate 85497c478bd9Sstevel@tonic-gate if ((ret = csx_register_cardservices(&rcs)) != CS_SUCCESS) { 85507c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_init: can't register with " 85517c478bd9Sstevel@tonic-gate "cs_stubs, retcode = 0x%x\n", ret); 85527c478bd9Sstevel@tonic-gate return (ret); 85537c478bd9Sstevel@tonic-gate } /* csx_register_cardservices */ 85547c478bd9Sstevel@tonic-gate 85557c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 85567c478bd9Sstevel@tonic-gate } 85577c478bd9Sstevel@tonic-gate 85587c478bd9Sstevel@tonic-gate /* 85597c478bd9Sstevel@tonic-gate * cs_create_cis - reads CIS on card in socket and creates CIS lists 85607c478bd9Sstevel@tonic-gate * 85617c478bd9Sstevel@tonic-gate * Most of the work is done in the CIS module in the CISP_CIS_LIST_CREATE 85627c478bd9Sstevel@tonic-gate * function. 85637c478bd9Sstevel@tonic-gate * 85647c478bd9Sstevel@tonic-gate * This function returns: 85657c478bd9Sstevel@tonic-gate * 85667c478bd9Sstevel@tonic-gate * CS_SUCCESS - if the CIS lists were created sucessfully 85677c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 85687c478bd9Sstevel@tonic-gate * not be setup 85697c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chains 85707c478bd9Sstevel@tonic-gate * CS_BAD_OFFSET - if the CIS parser tried to read past the 85717c478bd9Sstevel@tonic-gate * boundries of the allocated CIS window 85727c478bd9Sstevel@tonic-gate */ 85737c478bd9Sstevel@tonic-gate static int 85747c478bd9Sstevel@tonic-gate cs_create_cis(cs_socket_t *sp) 85757c478bd9Sstevel@tonic-gate { 85767c478bd9Sstevel@tonic-gate uint32_t ret; 85777c478bd9Sstevel@tonic-gate 85787c478bd9Sstevel@tonic-gate ret = (uint32_t)(uintptr_t)CIS_PARSER(CISP_CIS_LIST_CREATE, 85797c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, sp); 85807c478bd9Sstevel@tonic-gate 85817c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 85827c478bd9Sstevel@tonic-gate if (ret == CS_NO_CIS) { 85837c478bd9Sstevel@tonic-gate if (cs_debug > 0) 85847c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d has no CIS\n", 85857c478bd9Sstevel@tonic-gate sp->socket_num); 85867c478bd9Sstevel@tonic-gate } else if (ret != CS_SUCCESS) { 85877c478bd9Sstevel@tonic-gate if (cs_debug > 0) 85887c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d ERROR = 0x%x\n", 85897c478bd9Sstevel@tonic-gate sp->socket_num, ret); 85907c478bd9Sstevel@tonic-gate return (ret); 85917c478bd9Sstevel@tonic-gate } 85927c478bd9Sstevel@tonic-gate #else 85937c478bd9Sstevel@tonic-gate if (ret != CS_NO_CIS) 85947c478bd9Sstevel@tonic-gate if (ret != CS_SUCCESS) 85957c478bd9Sstevel@tonic-gate return (ret); 85967c478bd9Sstevel@tonic-gate #endif 85977c478bd9Sstevel@tonic-gate 85987c478bd9Sstevel@tonic-gate /* 85997c478bd9Sstevel@tonic-gate * If this card didn't have any CIS at all, there's not much 86007c478bd9Sstevel@tonic-gate * else for us to do. 86017c478bd9Sstevel@tonic-gate */ 86027c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_VALID_CIS)) 86037c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86047c478bd9Sstevel@tonic-gate 86057c478bd9Sstevel@tonic-gate /* 86067c478bd9Sstevel@tonic-gate * If this is a single-function card, we need to move the CIS list 86077c478bd9Sstevel@tonic-gate * that is currently on CS_GLOBAL_CIS to the function zero 86087c478bd9Sstevel@tonic-gate * CIS list. 86097c478bd9Sstevel@tonic-gate */ 86107c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_MULTI_FUNCTION_CIS)) { 86117c478bd9Sstevel@tonic-gate bcopy((caddr_t)&sp->cis[CS_GLOBAL_CIS], 86127c478bd9Sstevel@tonic-gate (caddr_t)&sp->cis[0], sizeof (cis_info_t)); 86137c478bd9Sstevel@tonic-gate bzero((caddr_t)&sp->cis[CS_GLOBAL_CIS], sizeof (cis_info_t)); 86147c478bd9Sstevel@tonic-gate } /* !CW_MULTI_FUNCTION_CIS */ 86157c478bd9Sstevel@tonic-gate 86167c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86177c478bd9Sstevel@tonic-gate } 86187c478bd9Sstevel@tonic-gate 86197c478bd9Sstevel@tonic-gate /* 86207c478bd9Sstevel@tonic-gate * cs_destroy_cis - destroys CIS list for socket 86217c478bd9Sstevel@tonic-gate */ 86227c478bd9Sstevel@tonic-gate static int 86237c478bd9Sstevel@tonic-gate cs_destroy_cis(cs_socket_t *sp) 86247c478bd9Sstevel@tonic-gate { 86257c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_LIST_DESTROY, sp); 86267c478bd9Sstevel@tonic-gate 86277c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86287c478bd9Sstevel@tonic-gate } 86297c478bd9Sstevel@tonic-gate 86307c478bd9Sstevel@tonic-gate /* 86317c478bd9Sstevel@tonic-gate * cs_get_client_info - This function is GetClientInfo. 86327c478bd9Sstevel@tonic-gate * 86337c478bd9Sstevel@tonic-gate * calling: client_handle_t - client handle to get client info on 86347c478bd9Sstevel@tonic-gate * client_info_t * - pointer to a client_info_t structure 86357c478bd9Sstevel@tonic-gate * to return client information in 86367c478bd9Sstevel@tonic-gate * 86377c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 86387c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 86397c478bd9Sstevel@tonic-gate * handle passed in 86407c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 86417c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 86427c478bd9Sstevel@tonic-gate * or if invalid client info 86437c478bd9Sstevel@tonic-gate * retreived from client 86447c478bd9Sstevel@tonic-gate */ 86457c478bd9Sstevel@tonic-gate static int 86467c478bd9Sstevel@tonic-gate cs_get_client_info(client_handle_t client_handle, client_info_t *ci) 86477c478bd9Sstevel@tonic-gate { 86487c478bd9Sstevel@tonic-gate cs_socket_t *sp; 86497c478bd9Sstevel@tonic-gate client_t *client; 86507c478bd9Sstevel@tonic-gate client_info_t *cinfo; 86517c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 86527c478bd9Sstevel@tonic-gate 86537c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 86547c478bd9Sstevel@tonic-gate ci->Attributes = (CS_CLIENT_INFO_SOCKET_SERVICES | 86557c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_VALID); 86567c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86577c478bd9Sstevel@tonic-gate } /* CLIENT_HANDLE_IS_SS */ 86587c478bd9Sstevel@tonic-gate 86597c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 86607c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 86617c478bd9Sstevel@tonic-gate 86627c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 86637c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 86647c478bd9Sstevel@tonic-gate 86657c478bd9Sstevel@tonic-gate if ((client = cs_find_client(client_handle, &ret)) == NULL) { 86667c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86677c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 86687c478bd9Sstevel@tonic-gate return (ret); 86697c478bd9Sstevel@tonic-gate } /* cs_find_client */ 86707c478bd9Sstevel@tonic-gate 86717c478bd9Sstevel@tonic-gate /* 86727c478bd9Sstevel@tonic-gate * If this client is not handling CS_EVENT_CLIENT_INFO events, 86737c478bd9Sstevel@tonic-gate * then don't bother to even wake up the event thread. 86747c478bd9Sstevel@tonic-gate */ 86757c478bd9Sstevel@tonic-gate if (!((client->event_mask | client->global_mask) & 86767c478bd9Sstevel@tonic-gate CS_EVENT_CLIENT_INFO)) { 86777c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86787c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 86797c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 86807c478bd9Sstevel@tonic-gate } /* !CS_EVENT_CLIENT_INFO */ 86817c478bd9Sstevel@tonic-gate 86827c478bd9Sstevel@tonic-gate cinfo = &client->event_callback_args.client_info; 86837c478bd9Sstevel@tonic-gate 86847c478bd9Sstevel@tonic-gate bzero((caddr_t)cinfo, sizeof (client_info_t)); 86857c478bd9Sstevel@tonic-gate cinfo->Attributes = (ci->Attributes & CS_CLIENT_INFO_SUBSVC_MASK); 86867c478bd9Sstevel@tonic-gate 86877c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CLIENT_INFO; 86887c478bd9Sstevel@tonic-gate 86897c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 86907c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86917c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 86927c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 86937c478bd9Sstevel@tonic-gate 86947c478bd9Sstevel@tonic-gate if (cinfo->Attributes & CS_CLIENT_INFO_VALID) { 86957c478bd9Sstevel@tonic-gate bcopy((caddr_t)cinfo, (caddr_t)ci, sizeof (client_info_t)); 86967c478bd9Sstevel@tonic-gate ci->Attributes &= (CS_CLIENT_INFO_FLAGS_MASK | 86977c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_SUBSVC_MASK); 86987c478bd9Sstevel@tonic-gate ci->Attributes &= ~(CS_CLIENT_INFO_CLIENT_MASK | 86997c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK | 87007c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_CLIENT_ACTIVE); 87017c478bd9Sstevel@tonic-gate ci->Attributes |= (client->flags & (CS_CLIENT_INFO_CLIENT_MASK | 87027c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK)); 87037c478bd9Sstevel@tonic-gate (void) strcpy(ci->DriverName, client->driver_name); 87047c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) 87057c478bd9Sstevel@tonic-gate ci->Attributes |= CS_CLIENT_INFO_CLIENT_ACTIVE; 87067c478bd9Sstevel@tonic-gate } else { 87077c478bd9Sstevel@tonic-gate ret = CS_NO_MORE_ITEMS; 87087c478bd9Sstevel@tonic-gate } /* CS_CLIENT_INFO_VALID */ 87097c478bd9Sstevel@tonic-gate 87107c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87117c478bd9Sstevel@tonic-gate 87127c478bd9Sstevel@tonic-gate return (ret); 87137c478bd9Sstevel@tonic-gate } 87147c478bd9Sstevel@tonic-gate 87157c478bd9Sstevel@tonic-gate /* 87167c478bd9Sstevel@tonic-gate * cs_get_firstnext_client - This function is GetFirstClient and 87177c478bd9Sstevel@tonic-gate * GetNextClient 87187c478bd9Sstevel@tonic-gate * 87197c478bd9Sstevel@tonic-gate * calling: get_firstnext_client_t * - pointer to a get_firstnext_client_t 87207c478bd9Sstevel@tonic-gate * structure to return client handle and 87217c478bd9Sstevel@tonic-gate * attributes in 87227c478bd9Sstevel@tonic-gate * flags - one of the following: 87237c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG - get first client handle 87247c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG - get next client handle 87257c478bd9Sstevel@tonic-gate * 87267c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 87277c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 87287c478bd9Sstevel@tonic-gate * handle passed in 87297c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 87307c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 87317c478bd9Sstevel@tonic-gate * or if invalid client info 87327c478bd9Sstevel@tonic-gate * retreived from client 87337c478bd9Sstevel@tonic-gate */ 87347c478bd9Sstevel@tonic-gate static int 87357c478bd9Sstevel@tonic-gate cs_get_firstnext_client(get_firstnext_client_t *fnc, uint32_t flags) 87367c478bd9Sstevel@tonic-gate { 87377c478bd9Sstevel@tonic-gate cs_socket_t *sp; 87387c478bd9Sstevel@tonic-gate client_t *client; 87397c478bd9Sstevel@tonic-gate uint32_t sn = 0; 87407c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 87417c478bd9Sstevel@tonic-gate 87427c478bd9Sstevel@tonic-gate switch (flags) { 87437c478bd9Sstevel@tonic-gate case CS_GET_FIRST_FLAG: 87447c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 87457c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 87467c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 87477c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87487c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 87497c478bd9Sstevel@tonic-gate break; 87507c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87517c478bd9Sstevel@tonic-gate } /* if */ 87527c478bd9Sstevel@tonic-gate sn++; 87537c478bd9Sstevel@tonic-gate } /* while */ 87547c478bd9Sstevel@tonic-gate 87557c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 87567c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 87577c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 87587c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 87597c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(fnc->Socket))) == 87607c478bd9Sstevel@tonic-gate NULL) 87617c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 87627c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87637c478bd9Sstevel@tonic-gate if ((client = sp->client_list) == NULL) { 87647c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87657c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 87667c478bd9Sstevel@tonic-gate } 87677c478bd9Sstevel@tonic-gate } else { 87687c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 87697c478bd9Sstevel@tonic-gate } 87707c478bd9Sstevel@tonic-gate 87717c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 87727c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 87737c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87747c478bd9Sstevel@tonic-gate break; 87757c478bd9Sstevel@tonic-gate case CS_GET_NEXT_FLAG: 87767c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 87777c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(fnc->client_handle); 87787c478bd9Sstevel@tonic-gate 87797c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 87807c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 87817c478bd9Sstevel@tonic-gate 87827c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87837c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 87847c478bd9Sstevel@tonic-gate &ret)) == NULL) { 87857c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87867c478bd9Sstevel@tonic-gate return (ret); 87877c478bd9Sstevel@tonic-gate } 87887c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 87897c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87907c478bd9Sstevel@tonic-gate sn++; 87917c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 87927c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 87937c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87947c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 87957c478bd9Sstevel@tonic-gate break; 87967c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87977c478bd9Sstevel@tonic-gate } /* if */ 87987c478bd9Sstevel@tonic-gate sn++; 87997c478bd9Sstevel@tonic-gate } /* while */ 88007c478bd9Sstevel@tonic-gate 88017c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 88027c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 88037c478bd9Sstevel@tonic-gate } /* client = client->next */ 88047c478bd9Sstevel@tonic-gate 88057c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 88067c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 88077c478bd9Sstevel@tonic-gate sp = cs_get_sp(GET_CLIENT_SOCKET(fnc->client_handle)); 88087c478bd9Sstevel@tonic-gate if (sp == NULL) 88097c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 88107c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 88117c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 88127c478bd9Sstevel@tonic-gate &ret)) == NULL) { 88137c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88147c478bd9Sstevel@tonic-gate return (ret); 88157c478bd9Sstevel@tonic-gate } 88167c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 88177c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88187c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 88197c478bd9Sstevel@tonic-gate } 88207c478bd9Sstevel@tonic-gate } else { 88217c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 88227c478bd9Sstevel@tonic-gate } 88237c478bd9Sstevel@tonic-gate 88247c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 88257c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 88267c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88277c478bd9Sstevel@tonic-gate break; 88287c478bd9Sstevel@tonic-gate default: 88297c478bd9Sstevel@tonic-gate ret = CS_BAD_ATTRIBUTE; 88307c478bd9Sstevel@tonic-gate break; 88317c478bd9Sstevel@tonic-gate 88327c478bd9Sstevel@tonic-gate } /* switch */ 88337c478bd9Sstevel@tonic-gate 88347c478bd9Sstevel@tonic-gate return (ret); 88357c478bd9Sstevel@tonic-gate } 88367c478bd9Sstevel@tonic-gate 88377c478bd9Sstevel@tonic-gate /* 88387c478bd9Sstevel@tonic-gate * cs_set_acc_attributes - converts Card Services endianness and 88397c478bd9Sstevel@tonic-gate * data ordering values to values 88407c478bd9Sstevel@tonic-gate * that Socket Services understands 88417c478bd9Sstevel@tonic-gate * 88427c478bd9Sstevel@tonic-gate * calling: *sw - pointer to a set_window_t to set attributes in 88437c478bd9Sstevel@tonic-gate * Attributes - CS attributes 88447c478bd9Sstevel@tonic-gate */ 88457c478bd9Sstevel@tonic-gate static void 88467c478bd9Sstevel@tonic-gate cs_set_acc_attributes(set_window_t *sw, uint32_t Attributes) 88477c478bd9Sstevel@tonic-gate { 88487c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 88497c478bd9Sstevel@tonic-gate 88507c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ENDIAN_MASK) { 88517c478bd9Sstevel@tonic-gate case WIN_ACC_LITTLE_ENDIAN: 88527c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 88537c478bd9Sstevel@tonic-gate break; 88547c478bd9Sstevel@tonic-gate case WIN_ACC_BIG_ENDIAN: 88557c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 88567c478bd9Sstevel@tonic-gate break; 88577c478bd9Sstevel@tonic-gate case WIN_ACC_NEVER_SWAP: 88587c478bd9Sstevel@tonic-gate default: 88597c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 88607c478bd9Sstevel@tonic-gate break; 88617c478bd9Sstevel@tonic-gate } /* switch */ 88627c478bd9Sstevel@tonic-gate 88637c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ORDER_MASK) { 88647c478bd9Sstevel@tonic-gate case WIN_ACC_UNORDERED_OK: 88657c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC; 88667c478bd9Sstevel@tonic-gate break; 88677c478bd9Sstevel@tonic-gate case WIN_ACC_MERGING_OK: 88687c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_MERGING_OK_ACC; 88697c478bd9Sstevel@tonic-gate break; 88707c478bd9Sstevel@tonic-gate case WIN_ACC_LOADCACHING_OK: 88717c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_LOADCACHING_OK_ACC; 88727c478bd9Sstevel@tonic-gate break; 88737c478bd9Sstevel@tonic-gate case WIN_ACC_STORECACHING_OK: 88747c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC; 88757c478bd9Sstevel@tonic-gate break; 88767c478bd9Sstevel@tonic-gate case WIN_ACC_STRICT_ORDER: 88777c478bd9Sstevel@tonic-gate default: 88787c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 88797c478bd9Sstevel@tonic-gate break; 88807c478bd9Sstevel@tonic-gate } /* switch */ 88817c478bd9Sstevel@tonic-gate } 8882