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 /* 23*5f9e250aShx147065 * 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 #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * PCMCIA Card Services 317c478bd9Sstevel@tonic-gate * The PCMCIA Card Services is a loadable module which 327c478bd9Sstevel@tonic-gate * presents the Card Services interface to client device 337c478bd9Sstevel@tonic-gate * drivers. 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * Card Services uses Socket Services-like calls into the 367c478bd9Sstevel@tonic-gate * PCMCIA nexus driver to manipulate socket and adapter 377c478bd9Sstevel@tonic-gate * resources. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * Note that a bunch of comments are not indented correctly with the 407c478bd9Sstevel@tonic-gate * code that they are commenting on. This is because cstyle is 417c478bd9Sstevel@tonic-gate * is inflexible concerning 4-column indenting. 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #if defined(DEBUG) 457c478bd9Sstevel@tonic-gate #define CS_DEBUG 467c478bd9Sstevel@tonic-gate #endif 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <sys/types.h> 497c478bd9Sstevel@tonic-gate #include <sys/systm.h> 507c478bd9Sstevel@tonic-gate #include <sys/user.h> 517c478bd9Sstevel@tonic-gate #include <sys/buf.h> 527c478bd9Sstevel@tonic-gate #include <sys/file.h> 537c478bd9Sstevel@tonic-gate #include <sys/uio.h> 547c478bd9Sstevel@tonic-gate #include <sys/conf.h> 557c478bd9Sstevel@tonic-gate #include <sys/stat.h> 567c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 577c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 587c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 597c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 607c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 617c478bd9Sstevel@tonic-gate #include <sys/debug.h> 627c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 637c478bd9Sstevel@tonic-gate #include <sys/var.h> 647c478bd9Sstevel@tonic-gate #include <sys/proc.h> 657c478bd9Sstevel@tonic-gate #include <sys/thread.h> 667c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 677c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 687c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 697c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 707c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 717c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 727c478bd9Sstevel@tonic-gate #include <sys/callb.h> 737c478bd9Sstevel@tonic-gate #include <sys/time.h> 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #include <sys/pctypes.h> 767c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_types.h> 777c478bd9Sstevel@tonic-gate #include <sys/pcmcia.h> 787c478bd9Sstevel@tonic-gate #include <sys/sservice.h> 797c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis.h> 807c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cis_handlers.h> 817c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs.h> 827c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_priv.h> 837c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_stubs.h> 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * The cs_strings header file is where all of the major strings that 877c478bd9Sstevel@tonic-gate * Card Services uses are located. 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate #include <pcmcia/sys/cs_strings.h> 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Function declarations 947c478bd9Sstevel@tonic-gate * 957c478bd9Sstevel@tonic-gate * The main Card Services entry point 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate int CardServices(int function, ...); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * functions and globals used by Socket Services 1017c478bd9Sstevel@tonic-gate * 1027c478bd9Sstevel@tonic-gate * WAS: void *(*cis_parser)(int, ...) = NULL; 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate void *(*cis_parser)(int, ...) = NULL; 1057c478bd9Sstevel@tonic-gate csfunction_t *cs_socket_services = NULL; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * event handling functions 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate static event_t ss_to_cs_events(cs_socket_t *, event_t); 1117c478bd9Sstevel@tonic-gate static event_t cs_cse2sbm(event_t); 1127c478bd9Sstevel@tonic-gate static void cs_event_thread(uint32_t); 1137c478bd9Sstevel@tonic-gate static int cs_card_insertion(cs_socket_t *, event_t); 1147c478bd9Sstevel@tonic-gate static int cs_card_removal(cs_socket_t *); 1157c478bd9Sstevel@tonic-gate static void cs_ss_thread(uint32_t); 1167c478bd9Sstevel@tonic-gate void cs_ready_timeout(void *); 1177c478bd9Sstevel@tonic-gate static int cs_card_for_client(client_t *); 1187c478bd9Sstevel@tonic-gate static int cs_request_socket_mask(client_handle_t, request_socket_mask_t *); 1197c478bd9Sstevel@tonic-gate static int cs_release_socket_mask(client_handle_t, release_socket_mask_t *); 1207c478bd9Sstevel@tonic-gate static int cs_get_event_mask(client_handle_t, sockevent_t *); 1217c478bd9Sstevel@tonic-gate static int cs_set_event_mask(client_handle_t, sockevent_t *); 1227c478bd9Sstevel@tonic-gate static int cs_event2text(event2text_t *, int); 1237c478bd9Sstevel@tonic-gate static int cs_read_event_status(cs_socket_t *, client_t *, event_t *, 1247c478bd9Sstevel@tonic-gate get_ss_status_t *, int); 1257c478bd9Sstevel@tonic-gate uint32_t cs_socket_event_softintr(caddr_t); 1267c478bd9Sstevel@tonic-gate void cs_event_softintr_timeout(void *); 1277c478bd9Sstevel@tonic-gate static int cs_get_status(client_handle_t, get_status_t *); 1287c478bd9Sstevel@tonic-gate static uint32_t cs_sbm2cse(uint32_t); 1297c478bd9Sstevel@tonic-gate static unsigned cs_merge_event_masks(cs_socket_t *, client_t *); 1307c478bd9Sstevel@tonic-gate static int cs_set_socket_event_mask(cs_socket_t *, unsigned); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * SS<->CS communication and internal socket and window handling functions 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate static uint32_t cs_add_socket(uint32_t); 1367c478bd9Sstevel@tonic-gate static uint32_t cs_drop_socket(uint32_t); 1377c478bd9Sstevel@tonic-gate static cs_socket_t *cs_get_sp(uint32_t); 1387c478bd9Sstevel@tonic-gate static cs_socket_t *cs_find_sp(uint32_t); 1397c478bd9Sstevel@tonic-gate static cs_window_t *cs_get_wp(uint32_t); 1407c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_wp(uint32_t); 1417c478bd9Sstevel@tonic-gate static int cs_add_windows(int, uint32_t); 1427c478bd9Sstevel@tonic-gate static uint32_t cs_ss_init(); 1437c478bd9Sstevel@tonic-gate static void cs_set_acc_attributes(set_window_t *, uint32_t); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * CIS handling functions 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate cistpl_callout_t *cis_cistpl_std_callout; 1497c478bd9Sstevel@tonic-gate static int cs_parse_tuple(client_handle_t, tuple_t *, cisparse_t *, cisdata_t); 1507c478bd9Sstevel@tonic-gate static int cs_get_tuple_data(client_handle_t, tuple_t *); 1517c478bd9Sstevel@tonic-gate static int cs_validate_cis(client_handle_t, cisinfo_t *); 1527c478bd9Sstevel@tonic-gate static int cs_get_firstnext_tuple(client_handle_t, tuple_t *, uint32_t); 1537c478bd9Sstevel@tonic-gate static int cs_create_cis(cs_socket_t *); 1547c478bd9Sstevel@tonic-gate static int cs_destroy_cis(cs_socket_t *); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * client handling functions 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate unsigned cs_create_next_client_minor(unsigned, unsigned); 1607c478bd9Sstevel@tonic-gate static client_t *cs_find_client(client_handle_t, int *); 1617c478bd9Sstevel@tonic-gate static client_handle_t cs_create_client_handle(unsigned, client_t *); 1627c478bd9Sstevel@tonic-gate static int cs_destroy_client_handle(client_handle_t); 1637c478bd9Sstevel@tonic-gate static int cs_register_client(client_handle_t *, client_reg_t *); 1647c478bd9Sstevel@tonic-gate static int cs_deregister_client(client_handle_t); 1657c478bd9Sstevel@tonic-gate static int cs_deregister_mtd(client_handle_t); 1667c478bd9Sstevel@tonic-gate static void cs_clear_superclient_lock(int); 1677c478bd9Sstevel@tonic-gate static int cs_add_client_to_socket(unsigned, client_handle_t *, 1687c478bd9Sstevel@tonic-gate client_reg_t *, int); 1697c478bd9Sstevel@tonic-gate static int cs_get_client_info(client_handle_t, client_info_t *); 1707c478bd9Sstevel@tonic-gate static int cs_get_firstnext_client(get_firstnext_client_t *, uint32_t); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * window handling functions 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate static int cs_request_window(client_handle_t, window_handle_t *, win_req_t *); 1767c478bd9Sstevel@tonic-gate static int cs_release_window(window_handle_t); 1777c478bd9Sstevel@tonic-gate static int cs_modify_window(window_handle_t, modify_win_t *); 1787c478bd9Sstevel@tonic-gate static int cs_modify_mem_window(window_handle_t, modify_win_t *, win_req_t *, 1797c478bd9Sstevel@tonic-gate int); 1807c478bd9Sstevel@tonic-gate static int cs_map_mem_page(window_handle_t, map_mem_page_t *); 1817c478bd9Sstevel@tonic-gate static int cs_find_mem_window(uint32_t, win_req_t *, uint32_t *); 1827c478bd9Sstevel@tonic-gate static int cs_memwin_space_and_map_ok(inquire_window_t *, win_req_t *); 1837c478bd9Sstevel@tonic-gate static int cs_valid_window_speed(inquire_window_t *, uint32_t); 1847c478bd9Sstevel@tonic-gate static window_handle_t cs_create_window_handle(uint32_t); 1857c478bd9Sstevel@tonic-gate static cs_window_t *cs_find_window(window_handle_t); 1867c478bd9Sstevel@tonic-gate static int cs_find_io_win(uint32_t, iowin_char_t *, uint32_t *, uint32_t *); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * IO, IRQ and configuration handling functions 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate static int cs_request_io(client_handle_t, io_req_t *); 1927c478bd9Sstevel@tonic-gate static int cs_release_io(client_handle_t, io_req_t *); 1937c478bd9Sstevel@tonic-gate static int cs_allocate_io_win(uint32_t, uint32_t, uint32_t *); 1947c478bd9Sstevel@tonic-gate static int cs_setup_io_win(uint32_t, uint32_t, baseaddru_t *, 1957c478bd9Sstevel@tonic-gate uint32_t *, uint32_t, uint32_t); 1967c478bd9Sstevel@tonic-gate static int cs_request_irq(client_handle_t, irq_req_t *); 1977c478bd9Sstevel@tonic-gate static int cs_release_irq(client_handle_t, irq_req_t *); 1987c478bd9Sstevel@tonic-gate static int cs_request_configuration(client_handle_t, config_req_t *); 1997c478bd9Sstevel@tonic-gate static int cs_release_configuration(client_handle_t, release_config_t *); 2007c478bd9Sstevel@tonic-gate static int cs_modify_configuration(client_handle_t, modify_config_t *); 2017c478bd9Sstevel@tonic-gate static int cs_access_configuration_register(client_handle_t, 2027c478bd9Sstevel@tonic-gate access_config_reg_t *); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * RESET and general info functions 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate static int cs_reset_function(client_handle_t, reset_function_t *); 2087c478bd9Sstevel@tonic-gate static int cs_get_configuration_info(client_handle_t *, 2097c478bd9Sstevel@tonic-gate get_configuration_info_t *); 2107c478bd9Sstevel@tonic-gate static int cs_get_cardservices_info(client_handle_t, 2117c478bd9Sstevel@tonic-gate get_cardservices_info_t *); 2127c478bd9Sstevel@tonic-gate static int cs_get_physical_adapter_info(client_handle_t, 2137c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * general functions 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate static uint32_t cs_get_socket(client_handle_t, uint32_t *, uint32_t *, 2197c478bd9Sstevel@tonic-gate cs_socket_t **, client_t **); 2207c478bd9Sstevel@tonic-gate static int cs_convert_speed(convert_speed_t *); 2217c478bd9Sstevel@tonic-gate static int cs_convert_size(convert_size_t *); 2227c478bd9Sstevel@tonic-gate static char *cs_error2text(int, int); 2237c478bd9Sstevel@tonic-gate static int cs_map_log_socket(client_handle_t, map_log_socket_t *); 2247c478bd9Sstevel@tonic-gate static int cs_convert_powerlevel(uint32_t, uint32_t, uint32_t, unsigned *); 2257c478bd9Sstevel@tonic-gate static int cs_make_device_node(client_handle_t, make_device_node_t *); 2267c478bd9Sstevel@tonic-gate static int cs_remove_device_node(client_handle_t, remove_device_node_t *); 2277c478bd9Sstevel@tonic-gate static int cs_ddi_info(cs_ddi_info_t *); 2287c478bd9Sstevel@tonic-gate static int cs_init_cis_window(cs_socket_t *, uint32_t *, acc_handle_t *, 2297c478bd9Sstevel@tonic-gate uint32_t); 2307c478bd9Sstevel@tonic-gate static int cs_sys_ctl(cs_sys_ctl_t *); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * global variables 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate static int cs_max_client_handles = CS_MAX_CLIENTS; 2367c478bd9Sstevel@tonic-gate static client_t cs_socket_services_client; /* global SS client */ 2377c478bd9Sstevel@tonic-gate static client_types_t client_types[MAX_CLIENT_TYPES]; 2387c478bd9Sstevel@tonic-gate static cs_globals_t cs_globals; 2397c478bd9Sstevel@tonic-gate int cs_reset_timeout_time = RESET_TIMEOUT_TIME; 2407c478bd9Sstevel@tonic-gate int cs_rc1_delay = CS_RC1_DELAY; 2417c478bd9Sstevel@tonic-gate int cs_rc2_delay = CS_RC2_DELAY; 2427c478bd9Sstevel@tonic-gate int cs_rq_delay = CS_RQ_DELAY; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 2457c478bd9Sstevel@tonic-gate int cs_debug = 0; 2467c478bd9Sstevel@tonic-gate #endif 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * cs_init - Initialize CS internal structures, databases, and state, 2507c478bd9Sstevel@tonic-gate * and register with SS 2517c478bd9Sstevel@tonic-gate * 2527c478bd9Sstevel@tonic-gate * XXX - Need to make sure that if we fail at any point that we free 2537c478bd9Sstevel@tonic-gate * any resources that we allocated, as well as kill any 2547c478bd9Sstevel@tonic-gate * threads that may have been started. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate int 2577c478bd9Sstevel@tonic-gate cs_init() 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate client_types_t *ct; 2607c478bd9Sstevel@tonic-gate client_t *client; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Initialize the CS global structure 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate bzero((caddr_t)&cs_globals, sizeof (cs_globals_t)); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.global_lock, NULL, MUTEX_DRIVER, NULL); 2687c478bd9Sstevel@tonic-gate mutex_init(&cs_globals.window_lock, NULL, MUTEX_DRIVER, NULL); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate cs_globals.init_state = GLOBAL_INIT_STATE_MUTEX; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * Set up the global Socket Services client, since we're going to 2747c478bd9Sstevel@tonic-gate * need it once we register with SS. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate client = &cs_socket_services_client; 2777c478bd9Sstevel@tonic-gate bzero((caddr_t)client, sizeof (client_t)); 2787c478bd9Sstevel@tonic-gate client->client_handle = CS_SS_CLIENT_HANDLE; 2797c478bd9Sstevel@tonic-gate client->flags |= (INFO_SOCKET_SERVICES | CLIENT_CARD_INSERTED); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Setup the client type structure - this is used in the socket event 2837c478bd9Sstevel@tonic-gate * thread to sequence the delivery of events to all clients on 2847c478bd9Sstevel@tonic-gate * the socket. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate ct = &client_types[0]; 2877c478bd9Sstevel@tonic-gate ct->type = INFO_IO_CLIENT; 2887c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_LIFO; 2897c478bd9Sstevel@tonic-gate ct->next = &client_types[1]; 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate ct = ct->next; 2927c478bd9Sstevel@tonic-gate ct->type = INFO_MTD_CLIENT; 2937c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 2947c478bd9Sstevel@tonic-gate ct->next = &client_types[2]; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate ct = ct->next; 2977c478bd9Sstevel@tonic-gate ct->type = INFO_MEM_CLIENT; 2987c478bd9Sstevel@tonic-gate ct->order = CLIENT_EVENTS_FIFO; 2997c478bd9Sstevel@tonic-gate ct->next = NULL; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * cs_deinit - Deinitialize CS 3067c478bd9Sstevel@tonic-gate * 3077c478bd9Sstevel@tonic-gate * This function cleans up any allocated resources, stops any running threads, 3087c478bd9Sstevel@tonic-gate * destroys any mutexes and condition variables, and finally frees up the 3097c478bd9Sstevel@tonic-gate * global socket and window structure arrays. 3107c478bd9Sstevel@tonic-gate */ 3117c478bd9Sstevel@tonic-gate int 3127c478bd9Sstevel@tonic-gate cs_deinit() 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate cs_socket_t *sp; 3157c478bd9Sstevel@tonic-gate int sn, have_clients = 0, have_sockets = 0; 3167c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 3197c478bd9Sstevel@tonic-gate if (cs_debug > 1) 3207c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: cs_deinit\n"); 3217c478bd9Sstevel@tonic-gate #endif 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Deregister with the Card Services kernel stubs module 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 3277c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_DEREGISTER; 3287c478bd9Sstevel@tonic-gate (void) csx_register_cardservices(&rcs); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Set the GLOBAL_INIT_STATE_NO_CLIENTS flag to prevent new clients 3327c478bd9Sstevel@tonic-gate * from registering. 3337c478bd9Sstevel@tonic-gate */ 3347c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3357c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_NO_CLIENTS; 3367c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * Go through each socket and make sure that there are no clients 3407c478bd9Sstevel@tonic-gate * on any of the sockets. If there are, we can't deinit until 3417c478bd9Sstevel@tonic-gate * all the clients for every socket are gone. 3427c478bd9Sstevel@tonic-gate */ 3437c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3447c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 3457c478bd9Sstevel@tonic-gate have_sockets++; 3467c478bd9Sstevel@tonic-gate if (sp->client_list) { 3477c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deinit: cannot unload module since " 3487c478bd9Sstevel@tonic-gate "socket %d has registered clients\n", sn); 3497c478bd9Sstevel@tonic-gate have_clients++; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate /* 3557c478bd9Sstevel@tonic-gate * We don't allow unload if there are any clients registered 3567c478bd9Sstevel@tonic-gate * or if there are still sockets that are active. 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate if ((have_clients > 0) || (have_sockets > 0)) 3597c478bd9Sstevel@tonic-gate return (BAD_FUNCTION); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate #ifdef XXX 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * If one or more sockets have been added, we need to deallocate 3647c478bd9Sstevel@tonic-gate * the resources associated with those sockets. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * First, tell Socket Services that we're leaving, so that we 3697c478bd9Sstevel@tonic-gate * don't get any more event callbacks. 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate SocketServices(CSUnregister); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * Wait for the soft int timer to tell us it's done 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3777c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_UNLOADING; 3787c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3797c478bd9Sstevel@tonic-gate UNTIMEOUT(cs_globals.sotfint_tmo); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Remove the soft interrupt handler. 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 3857c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR) { 3867c478bd9Sstevel@tonic-gate ddi_remove_softintr(cs_globals.softint_id); 3877c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SOFTINTR; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * Go through each socket and free any resource allocated to that 3957c478bd9Sstevel@tonic-gate * socket, as well as any mutexs and condition variables. 3967c478bd9Sstevel@tonic-gate */ 3977c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 3987c478bd9Sstevel@tonic-gate set_socket_t set_socket; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * untimeout possible pending ready/busy timer 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4087c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 4097c478bd9Sstevel@tonic-gate sp->flags = SOCKET_UNLOAD_MODULE; 4107c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SOFTINTR) 4117c478bd9Sstevel@tonic-gate sp->init_state &= ~SOCKET_INIT_STATE_SOFTINTR; 4127c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4137c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4167c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 4177c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 4187c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4197c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * Tell the event handler thread that we want it to exit, then 4237c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4267c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 4277c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_THREAD) { 4287c478bd9Sstevel@tonic-gate sp->thread_state = SOCKET_THREAD_EXIT; 4297c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 4307c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4337c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate * Tell the SS work thread that we want it to exit, then 4377c478bd9Sstevel@tonic-gate * wait around until it tells us that it has exited. 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4407c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 4417c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_SS_THREAD) { 4427c478bd9Sstevel@tonic-gate sp->ss_thread_state = SOCKET_THREAD_EXIT; 4437c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 4447c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_caller_cv, &sp->ss_thread_lock); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) 4487c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Free the mutexii and condition variables that we used. 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_MUTEX) { 4547c478bd9Sstevel@tonic-gate mutex_destroy(&sp->lock); 4557c478bd9Sstevel@tonic-gate mutex_destroy(&sp->client_lock); 4567c478bd9Sstevel@tonic-gate mutex_destroy(&sp->cis_lock); 4577c478bd9Sstevel@tonic-gate mutex_destroy(&sp->ss_thread_lock); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_CV) { 4617c478bd9Sstevel@tonic-gate cv_destroy(&sp->thread_cv); 4627c478bd9Sstevel@tonic-gate cv_destroy(&sp->caller_cv); 4637c478bd9Sstevel@tonic-gate cv_destroy(&sp->reset_cv); 4647c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_thread_cv); 4657c478bd9Sstevel@tonic-gate cv_destroy(&sp->ss_caller_cv); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Free the memory-mapped IO structure if we allocated one. 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) 4737c478bd9Sstevel@tonic-gate kmem_free(sp->io_mmap_window, sizeof (io_mmap_window_t)); 4747c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * Return the socket to memory-only mode and turn off the 4787c478bd9Sstevel@tonic-gate * socket power. 4797c478bd9Sstevel@tonic-gate */ 4807c478bd9Sstevel@tonic-gate sp->event_mask = 0; 4817c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 4827c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 0; 4837c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 4847c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 4857c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 4867c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 4897c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 4907c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 4917c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 4927c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 4937c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * If we fail this call, there's not much we can do, so 4977c478bd9Sstevel@tonic-gate * just continue with the resource deallocation. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate if ((ret = 5007c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 5017c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 5027c478bd9Sstevel@tonic-gate "cs_deinit: socket %d SS_SetSocket failure %d\n", 5037c478bd9Sstevel@tonic-gate sp->socket_num, ret); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 5067c478bd9Sstevel@tonic-gate } /* for (sn) */ 5077c478bd9Sstevel@tonic-gate #endif /* XXX */ 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * Destroy the global mutexii. 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.global_lock); 5137c478bd9Sstevel@tonic-gate mutex_destroy(&cs_globals.window_lock); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate #ifdef XXX 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * Free the global "super-client" structure 5187c478bd9Sstevel@tonic-gate */ 5197c478bd9Sstevel@tonic-gate if (cs_globals.sclient_list) 5207c478bd9Sstevel@tonic-gate kmem_free(cs_globals.sclient_list, 5217c478bd9Sstevel@tonic-gate (cs_globals.num_sockets * sizeof (struct sclient_list_t))); 5227c478bd9Sstevel@tonic-gate cs_globals.sclient_list = NULL; 5237c478bd9Sstevel@tonic-gate #endif /* XXX */ 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * ==== drip, drip, drip - the Card Services waterfall :-) ==== 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * CardServices - general Card Services entry point for CS clients 5347c478bd9Sstevel@tonic-gate * and Socket Services; the address of this 5357c478bd9Sstevel@tonic-gate * function is handed to SS via the CSRegister 5367c478bd9Sstevel@tonic-gate * SS call 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate int 5397c478bd9Sstevel@tonic-gate CardServices(int function, ...) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate va_list arglist; 5427c478bd9Sstevel@tonic-gate int retcode = CS_UNSUPPORTED_FUNCTION; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate cs_socket_t *socp; 5457c478bd9Sstevel@tonic-gate uint32_t *offp; 5467c478bd9Sstevel@tonic-gate acc_handle_t *hp; 5477c478bd9Sstevel@tonic-gate client_handle_t ch; 5487c478bd9Sstevel@tonic-gate client_handle_t *chp; 5497c478bd9Sstevel@tonic-gate window_handle_t wh; 5507c478bd9Sstevel@tonic-gate window_handle_t *whp; 5517c478bd9Sstevel@tonic-gate tuple_t *tuple; 5527c478bd9Sstevel@tonic-gate cisparse_t *cisparse; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 5557c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 5567c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: called for function %s (0x%x)\n", 5577c478bd9Sstevel@tonic-gate cs_error2text(function, CSFUN2TEXT_FUNCTION), 5587c478bd9Sstevel@tonic-gate function); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate #endif 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate va_start(arglist, function); 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* 5657c478bd9Sstevel@tonic-gate * Here's the Card Services waterfall 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate switch (function) { 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * We got here as a result of the CIS module calling us 5707c478bd9Sstevel@tonic-gate * in response to cs_ss_init() calling the CIS module 5717c478bd9Sstevel@tonic-gate * at CIS_PARSER(CISP_CIS_SETUP, ...) 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate case CISRegister: { 5747c478bd9Sstevel@tonic-gate cisregister_t *cisr; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate cisr = va_arg(arglist, cisregister_t *); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if (cisr->cis_magic != PCCS_MAGIC || 5797c478bd9Sstevel@tonic-gate cisr->cis_version != PCCS_VERSION) { 5807c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5817c478bd9Sstevel@tonic-gate "CS: CISRegister (%lx, %lx, %lx, %lx) *ERROR*", 5827c478bd9Sstevel@tonic-gate (long)cisr->cis_magic, 5837c478bd9Sstevel@tonic-gate (long)cisr->cis_version, 5847c478bd9Sstevel@tonic-gate (long)cisr->cis_parser, 5857c478bd9Sstevel@tonic-gate (long)cisr->cistpl_std_callout); 5867c478bd9Sstevel@tonic-gate retcode = CS_BAD_ARGS; 5877c478bd9Sstevel@tonic-gate } else { 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * Replace the CIS Parser entry point if 5907c478bd9Sstevel@tonic-gate * necessary. 5917c478bd9Sstevel@tonic-gate */ 5927c478bd9Sstevel@tonic-gate if (cisr->cis_parser != NULL) 5937c478bd9Sstevel@tonic-gate cis_parser = cisr->cis_parser; 5947c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = cisr->cistpl_std_callout; 5957c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate break; 5997c478bd9Sstevel@tonic-gate case CISUnregister: /* XXX - should we do some more checking */ 6007c478bd9Sstevel@tonic-gate /* XXX - need to protect this by a mutex */ 6017c478bd9Sstevel@tonic-gate cis_parser = NULL; 6027c478bd9Sstevel@tonic-gate cis_cistpl_std_callout = NULL; 6037c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate case InitCISWindow: 6067c478bd9Sstevel@tonic-gate socp = va_arg(arglist, cs_socket_t *); 6077c478bd9Sstevel@tonic-gate offp = va_arg(arglist, uint32_t *); 6087c478bd9Sstevel@tonic-gate hp = va_arg(arglist, acc_handle_t *); 6097c478bd9Sstevel@tonic-gate retcode = cs_init_cis_window(socp, offp, hp, 6107c478bd9Sstevel@tonic-gate va_arg(arglist, uint32_t)); 6117c478bd9Sstevel@tonic-gate break; 6127c478bd9Sstevel@tonic-gate case RegisterClient: 6137c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *), 6147c478bd9Sstevel@tonic-gate retcode = cs_register_client(chp, 6157c478bd9Sstevel@tonic-gate va_arg(arglist, client_reg_t *)); 6167c478bd9Sstevel@tonic-gate break; 6177c478bd9Sstevel@tonic-gate case DeregisterClient: 6187c478bd9Sstevel@tonic-gate retcode = cs_deregister_client( 6197c478bd9Sstevel@tonic-gate va_arg(arglist, client_handle_t)); 6207c478bd9Sstevel@tonic-gate break; 6217c478bd9Sstevel@tonic-gate case GetStatus: 6227c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6237c478bd9Sstevel@tonic-gate retcode = cs_get_status(ch, 6247c478bd9Sstevel@tonic-gate va_arg(arglist, get_status_t *)); 6257c478bd9Sstevel@tonic-gate break; 6267c478bd9Sstevel@tonic-gate case ResetFunction: 6277c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6287c478bd9Sstevel@tonic-gate retcode = cs_reset_function(ch, 6297c478bd9Sstevel@tonic-gate va_arg(arglist, reset_function_t *)); 6307c478bd9Sstevel@tonic-gate break; 6317c478bd9Sstevel@tonic-gate case SetEventMask: 6327c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6337c478bd9Sstevel@tonic-gate retcode = cs_set_event_mask(ch, 6347c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 6357c478bd9Sstevel@tonic-gate break; 6367c478bd9Sstevel@tonic-gate case GetEventMask: 6377c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6387c478bd9Sstevel@tonic-gate retcode = cs_get_event_mask(ch, 6397c478bd9Sstevel@tonic-gate va_arg(arglist, sockevent_t *)); 6407c478bd9Sstevel@tonic-gate break; 6417c478bd9Sstevel@tonic-gate case RequestIO: 6427c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6437c478bd9Sstevel@tonic-gate retcode = cs_request_io(ch, 6447c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 6457c478bd9Sstevel@tonic-gate break; 6467c478bd9Sstevel@tonic-gate case ReleaseIO: 6477c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6487c478bd9Sstevel@tonic-gate retcode = cs_release_io(ch, 6497c478bd9Sstevel@tonic-gate va_arg(arglist, io_req_t *)); 6507c478bd9Sstevel@tonic-gate break; 6517c478bd9Sstevel@tonic-gate case RequestIRQ: 6527c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6537c478bd9Sstevel@tonic-gate retcode = cs_request_irq(ch, 6547c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 6557c478bd9Sstevel@tonic-gate break; 6567c478bd9Sstevel@tonic-gate case ReleaseIRQ: 6577c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6587c478bd9Sstevel@tonic-gate retcode = cs_release_irq(ch, 6597c478bd9Sstevel@tonic-gate va_arg(arglist, irq_req_t *)); 6607c478bd9Sstevel@tonic-gate break; 6617c478bd9Sstevel@tonic-gate case RequestWindow: 6627c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6637c478bd9Sstevel@tonic-gate whp = va_arg(arglist, window_handle_t *); 6647c478bd9Sstevel@tonic-gate retcode = cs_request_window(ch, whp, 6657c478bd9Sstevel@tonic-gate va_arg(arglist, win_req_t *)); 6667c478bd9Sstevel@tonic-gate break; 6677c478bd9Sstevel@tonic-gate case ReleaseWindow: 6687c478bd9Sstevel@tonic-gate retcode = cs_release_window( 6697c478bd9Sstevel@tonic-gate va_arg(arglist, window_handle_t)); 6707c478bd9Sstevel@tonic-gate break; 6717c478bd9Sstevel@tonic-gate case ModifyWindow: 6727c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 6737c478bd9Sstevel@tonic-gate retcode = cs_modify_window(wh, 6747c478bd9Sstevel@tonic-gate va_arg(arglist, modify_win_t *)); 6757c478bd9Sstevel@tonic-gate break; 6767c478bd9Sstevel@tonic-gate case MapMemPage: 6777c478bd9Sstevel@tonic-gate wh = va_arg(arglist, window_handle_t); 6787c478bd9Sstevel@tonic-gate retcode = cs_map_mem_page(wh, 6797c478bd9Sstevel@tonic-gate va_arg(arglist, map_mem_page_t *)); 6807c478bd9Sstevel@tonic-gate break; 6817c478bd9Sstevel@tonic-gate case RequestSocketMask: 6827c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6837c478bd9Sstevel@tonic-gate retcode = cs_request_socket_mask(ch, 6847c478bd9Sstevel@tonic-gate va_arg(arglist, request_socket_mask_t *)); 6857c478bd9Sstevel@tonic-gate break; 6867c478bd9Sstevel@tonic-gate case ReleaseSocketMask: 6877c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6887c478bd9Sstevel@tonic-gate retcode = cs_release_socket_mask(ch, 6897c478bd9Sstevel@tonic-gate va_arg(arglist, release_socket_mask_t *)); 6907c478bd9Sstevel@tonic-gate break; 6917c478bd9Sstevel@tonic-gate case RequestConfiguration: 6927c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6937c478bd9Sstevel@tonic-gate retcode = cs_request_configuration(ch, 6947c478bd9Sstevel@tonic-gate va_arg(arglist, config_req_t *)); 6957c478bd9Sstevel@tonic-gate break; 6967c478bd9Sstevel@tonic-gate case GetPhysicalAdapterInfo: 6977c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 6987c478bd9Sstevel@tonic-gate retcode = cs_get_physical_adapter_info(ch, 6997c478bd9Sstevel@tonic-gate va_arg(arglist, get_physical_adapter_info_t *)); 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate case GetCardServicesInfo: 7027c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7037c478bd9Sstevel@tonic-gate retcode = cs_get_cardservices_info(ch, 7047c478bd9Sstevel@tonic-gate va_arg(arglist, get_cardservices_info_t *)); 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate case GetConfigurationInfo: 7077c478bd9Sstevel@tonic-gate chp = va_arg(arglist, client_handle_t *); 7087c478bd9Sstevel@tonic-gate retcode = cs_get_configuration_info(chp, 7097c478bd9Sstevel@tonic-gate va_arg(arglist, get_configuration_info_t *)); 7107c478bd9Sstevel@tonic-gate break; 7117c478bd9Sstevel@tonic-gate case ModifyConfiguration: 7127c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7137c478bd9Sstevel@tonic-gate retcode = cs_modify_configuration(ch, 7147c478bd9Sstevel@tonic-gate va_arg(arglist, modify_config_t *)); 7157c478bd9Sstevel@tonic-gate break; 7167c478bd9Sstevel@tonic-gate case AccessConfigurationRegister: 7177c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7187c478bd9Sstevel@tonic-gate retcode = cs_access_configuration_register(ch, 7197c478bd9Sstevel@tonic-gate va_arg(arglist, access_config_reg_t *)); 7207c478bd9Sstevel@tonic-gate break; 7217c478bd9Sstevel@tonic-gate case ReleaseConfiguration: 7227c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7237c478bd9Sstevel@tonic-gate retcode = cs_release_configuration(ch, 7247c478bd9Sstevel@tonic-gate va_arg(arglist, release_config_t *)); 7257c478bd9Sstevel@tonic-gate break; 7267c478bd9Sstevel@tonic-gate case OpenMemory: 7277c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: OpenMemory\n"); 7287c478bd9Sstevel@tonic-gate break; 7297c478bd9Sstevel@tonic-gate case ReadMemory: 7307c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReadMemory\n"); 7317c478bd9Sstevel@tonic-gate break; 7327c478bd9Sstevel@tonic-gate case WriteMemory: 7337c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: WriteMemory\n"); 7347c478bd9Sstevel@tonic-gate break; 7357c478bd9Sstevel@tonic-gate case CopyMemory: 7367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CopyMemory\n"); 7377c478bd9Sstevel@tonic-gate break; 7387c478bd9Sstevel@tonic-gate case RegisterEraseQueue: 7397c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterEraseQueue\n"); 7407c478bd9Sstevel@tonic-gate break; 7417c478bd9Sstevel@tonic-gate case CheckEraseQueue: 7427c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CheckEraseQueue\n"); 7437c478bd9Sstevel@tonic-gate break; 7447c478bd9Sstevel@tonic-gate case DeregisterEraseQueue: 7457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: DeregisterEraseQueue\n"); 7467c478bd9Sstevel@tonic-gate break; 7477c478bd9Sstevel@tonic-gate case CloseMemory: 7487c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: CloseMemory\n"); 7497c478bd9Sstevel@tonic-gate break; 7507c478bd9Sstevel@tonic-gate case GetFirstRegion: 7517c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstRegion\n"); 7527c478bd9Sstevel@tonic-gate break; 7537c478bd9Sstevel@tonic-gate case GetNextRegion: 7547c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextRegion\n"); 7557c478bd9Sstevel@tonic-gate break; 7567c478bd9Sstevel@tonic-gate case GetFirstPartition: 7577c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetFirstPartition\n"); 7587c478bd9Sstevel@tonic-gate break; 7597c478bd9Sstevel@tonic-gate case GetNextPartition: 7607c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: GetNextPartition\n"); 7617c478bd9Sstevel@tonic-gate break; 7627c478bd9Sstevel@tonic-gate case ReturnSSEntry: 7637c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReturnSSEntry\n"); 7647c478bd9Sstevel@tonic-gate break; 7657c478bd9Sstevel@tonic-gate case MapLogSocket: 7667c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 7677c478bd9Sstevel@tonic-gate retcode = cs_map_log_socket(ch, 7687c478bd9Sstevel@tonic-gate va_arg(arglist, map_log_socket_t *)); 7697c478bd9Sstevel@tonic-gate break; 7707c478bd9Sstevel@tonic-gate case MapPhySocket: 7717c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhySocket\n"); 7727c478bd9Sstevel@tonic-gate break; 7737c478bd9Sstevel@tonic-gate case MapLogWindow: 7747c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapLogWindow\n"); 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate case MapPhyWindow: 7777c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: MapPhyWindow\n"); 7787c478bd9Sstevel@tonic-gate break; 7797c478bd9Sstevel@tonic-gate case RegisterMTD: 7807c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterMTD\n"); 7817c478bd9Sstevel@tonic-gate break; 7827c478bd9Sstevel@tonic-gate case RegisterTimer: 7837c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RegisterTimer\n"); 7847c478bd9Sstevel@tonic-gate break; 7857c478bd9Sstevel@tonic-gate case SetRegion: 7867c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: SetRegion\n"); 7877c478bd9Sstevel@tonic-gate break; 7887c478bd9Sstevel@tonic-gate case RequestExclusive: 7897c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: RequestExclusive\n"); 7907c478bd9Sstevel@tonic-gate break; 7917c478bd9Sstevel@tonic-gate case ReleaseExclusive: 7927c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReleaseExclusive\n"); 7937c478bd9Sstevel@tonic-gate break; 7947c478bd9Sstevel@tonic-gate case GetFirstClient: 7957c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 7967c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 7977c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 7987c478bd9Sstevel@tonic-gate break; 7997c478bd9Sstevel@tonic-gate case GetNextClient: 8007c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_client( 8017c478bd9Sstevel@tonic-gate va_arg(arglist, get_firstnext_client_t *), 8027c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 8037c478bd9Sstevel@tonic-gate break; 8047c478bd9Sstevel@tonic-gate case GetClientInfo: 8057c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8067c478bd9Sstevel@tonic-gate retcode = cs_get_client_info(ch, 8077c478bd9Sstevel@tonic-gate va_arg(arglist, client_info_t *)); 8087c478bd9Sstevel@tonic-gate break; 8097c478bd9Sstevel@tonic-gate case AddSocketServices: 8107c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AddSocketServices\n"); 8117c478bd9Sstevel@tonic-gate break; 8127c478bd9Sstevel@tonic-gate case ReplaceSocketServices: 8137c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: ReplaceSocketServices\n"); 8147c478bd9Sstevel@tonic-gate break; 8157c478bd9Sstevel@tonic-gate case VendorSpecific: 8167c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: VendorSpecific\n"); 8177c478bd9Sstevel@tonic-gate break; 8187c478bd9Sstevel@tonic-gate case AdjustResourceInfo: 8197c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: AdjustResourceInfo\n"); 8207c478bd9Sstevel@tonic-gate break; 8217c478bd9Sstevel@tonic-gate case ValidateCIS: 8227c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8237c478bd9Sstevel@tonic-gate retcode = cs_validate_cis(ch, 8247c478bd9Sstevel@tonic-gate va_arg(arglist, cisinfo_t *)); 8257c478bd9Sstevel@tonic-gate break; 8267c478bd9Sstevel@tonic-gate case GetFirstTuple: 8277c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8287c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 8297c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 8307c478bd9Sstevel@tonic-gate CS_GET_FIRST_FLAG); 8317c478bd9Sstevel@tonic-gate break; 8327c478bd9Sstevel@tonic-gate case GetNextTuple: 8337c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8347c478bd9Sstevel@tonic-gate retcode = cs_get_firstnext_tuple(ch, 8357c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *), 8367c478bd9Sstevel@tonic-gate CS_GET_NEXT_FLAG); 8377c478bd9Sstevel@tonic-gate break; 8387c478bd9Sstevel@tonic-gate case GetTupleData: 8397c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8407c478bd9Sstevel@tonic-gate retcode = cs_get_tuple_data(ch, 8417c478bd9Sstevel@tonic-gate va_arg(arglist, tuple_t *)); 8427c478bd9Sstevel@tonic-gate break; 8437c478bd9Sstevel@tonic-gate case ParseTuple: 8447c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8457c478bd9Sstevel@tonic-gate tuple = va_arg(arglist, tuple_t *); 8467c478bd9Sstevel@tonic-gate cisparse = va_arg(arglist, cisparse_t *); 8477c478bd9Sstevel@tonic-gate retcode = cs_parse_tuple(ch, tuple, cisparse, 8487c478bd9Sstevel@tonic-gate va_arg(arglist, uint_t)); 8497c478bd9Sstevel@tonic-gate break; 8507c478bd9Sstevel@tonic-gate case MakeDeviceNode: 8517c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8527c478bd9Sstevel@tonic-gate retcode = cs_make_device_node(ch, 8537c478bd9Sstevel@tonic-gate va_arg(arglist, make_device_node_t *)); 8547c478bd9Sstevel@tonic-gate break; 8557c478bd9Sstevel@tonic-gate case RemoveDeviceNode: 8567c478bd9Sstevel@tonic-gate ch = va_arg(arglist, client_handle_t); 8577c478bd9Sstevel@tonic-gate retcode = cs_remove_device_node(ch, 8587c478bd9Sstevel@tonic-gate va_arg(arglist, remove_device_node_t *)); 8597c478bd9Sstevel@tonic-gate break; 8607c478bd9Sstevel@tonic-gate case ConvertSpeed: 8617c478bd9Sstevel@tonic-gate retcode = cs_convert_speed( 8627c478bd9Sstevel@tonic-gate va_arg(arglist, convert_speed_t *)); 8637c478bd9Sstevel@tonic-gate break; 8647c478bd9Sstevel@tonic-gate case ConvertSize: 8657c478bd9Sstevel@tonic-gate retcode = cs_convert_size( 8667c478bd9Sstevel@tonic-gate va_arg(arglist, convert_size_t *)); 8677c478bd9Sstevel@tonic-gate break; 8687c478bd9Sstevel@tonic-gate case Event2Text: 8697c478bd9Sstevel@tonic-gate retcode = cs_event2text( 8707c478bd9Sstevel@tonic-gate va_arg(arglist, event2text_t *), 1); 8717c478bd9Sstevel@tonic-gate break; 8727c478bd9Sstevel@tonic-gate case Error2Text: { 8737c478bd9Sstevel@tonic-gate error2text_t *cft; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate cft = va_arg(arglist, error2text_t *); 8767c478bd9Sstevel@tonic-gate (void) strcpy(cft->text, 8777c478bd9Sstevel@tonic-gate cs_error2text(cft->item, CSFUN2TEXT_RETURN)); 8787c478bd9Sstevel@tonic-gate retcode = CS_SUCCESS; 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate break; 8817c478bd9Sstevel@tonic-gate case CS_DDI_Info: 8827c478bd9Sstevel@tonic-gate retcode = cs_ddi_info(va_arg(arglist, cs_ddi_info_t *)); 8837c478bd9Sstevel@tonic-gate break; 8847c478bd9Sstevel@tonic-gate case CS_Sys_Ctl: 8857c478bd9Sstevel@tonic-gate retcode = cs_sys_ctl(va_arg(arglist, cs_sys_ctl_t *)); 8867c478bd9Sstevel@tonic-gate break; 8877c478bd9Sstevel@tonic-gate default: 8887c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CS: {unknown function %d}\n", function); 8897c478bd9Sstevel@tonic-gate break; 8907c478bd9Sstevel@tonic-gate } /* switch(function) */ 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate va_end(arglist); 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 8957c478bd9Sstevel@tonic-gate if (cs_debug > 127) { 8967c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "CardServices: returning %s (0x%x)\n", 8977c478bd9Sstevel@tonic-gate cs_error2text(retcode, CSFUN2TEXT_RETURN), 8987c478bd9Sstevel@tonic-gate retcode); 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate #endif 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate return (retcode); 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate /* 9067c478bd9Sstevel@tonic-gate * ==== tuple and CIS handling section ==== 9077c478bd9Sstevel@tonic-gate */ 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate /* 9107c478bd9Sstevel@tonic-gate * cs_parse_tuple - This function supports the CS ParseTuple function call. 9117c478bd9Sstevel@tonic-gate * 9127c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if tuple parsed sucessfully 9137c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 9147c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if passed CIS list pointer is NULL 9157c478bd9Sstevel@tonic-gate * CS_UNKNOWN_TUPLE - if unknown tuple passed to CIS parser 9167c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if generic parser error 9177c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for card/function 9187c478bd9Sstevel@tonic-gate * 9197c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate static int 9227c478bd9Sstevel@tonic-gate cs_parse_tuple(client_handle_t client_handle, tuple_t *tuple, 9237c478bd9Sstevel@tonic-gate cisparse_t *cisparse, cisdata_t cisdata) 9247c478bd9Sstevel@tonic-gate { 9257c478bd9Sstevel@tonic-gate cs_socket_t *sp; 9267c478bd9Sstevel@tonic-gate client_t *client; 9277c478bd9Sstevel@tonic-gate uint32_t fn; 9287c478bd9Sstevel@tonic-gate int ret; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, 9317c478bd9Sstevel@tonic-gate &fn, &sp, &client)) != CS_SUCCESS) 9327c478bd9Sstevel@tonic-gate return (ret); 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* 9357c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 9367c478bd9Sstevel@tonic-gate * for this client, then return an error. 9377c478bd9Sstevel@tonic-gate */ 9387c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 9397c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * Sanity check to be sure that we've got a non-NULL CIS list 9437c478bd9Sstevel@tonic-gate * pointer. 9447c478bd9Sstevel@tonic-gate */ 9457c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) 9467c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* 9517c478bd9Sstevel@tonic-gate * Check to see if there is a valid CIS for this function. 9527c478bd9Sstevel@tonic-gate * There is an implicit assumption here that if this 9537c478bd9Sstevel@tonic-gate * is a multi-function CIS and the specified function 9547c478bd9Sstevel@tonic-gate * number is not CS_GLOBAL_CIS that in order for there 9557c478bd9Sstevel@tonic-gate * to be a valid function-specific CIS, there also must 9567c478bd9Sstevel@tonic-gate * be a valid global CIS. This means that we don't need 9577c478bd9Sstevel@tonic-gate * to know whether this tuple came from the global CIS 9587c478bd9Sstevel@tonic-gate * or from the function-specific CIS. 9597c478bd9Sstevel@tonic-gate */ 9607c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 9617c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 9627c478bd9Sstevel@tonic-gate ret = (int)(uintptr_t)CIS_PARSER(CISP_CIS_PARSE_TUPLE, 9637c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, 9647c478bd9Sstevel@tonic-gate tuple->CISOffset, 9657c478bd9Sstevel@tonic-gate (tuple->Attributes & TUPLE_RETURN_NAME)? 9667c478bd9Sstevel@tonic-gate HANDTPL_RETURN_NAME: 9677c478bd9Sstevel@tonic-gate HANDTPL_PARSE_LTUPLE, 9687c478bd9Sstevel@tonic-gate cisparse, cisdata); 9697c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 9707c478bd9Sstevel@tonic-gate if (ret == CISTPLF_UNKNOWN) 9717c478bd9Sstevel@tonic-gate return (CS_UNKNOWN_TUPLE); 9727c478bd9Sstevel@tonic-gate if (ret != CISTPLF_NOERROR) 9737c478bd9Sstevel@tonic-gate return (CS_BAD_CIS); 9747c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 9757c478bd9Sstevel@tonic-gate } else { 9767c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 9777c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 9787c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate return (ret); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate /* 9847c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple - returns the first/next tuple of the specified type 9857c478bd9Sstevel@tonic-gate * this is to support the GetFirstTuple and 9867c478bd9Sstevel@tonic-gate * GetNextTuple function call 9877c478bd9Sstevel@tonic-gate * 9887c478bd9Sstevel@tonic-gate * flags - one of: 9897c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG causes function to support GetFirstTuple 9907c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG causes function to support GetNextTuple 9917c478bd9Sstevel@tonic-gate * 9927c478bd9Sstevel@tonic-gate * tuple_t->Attributes flags: 9937c478bd9Sstevel@tonic-gate * TUPLE_RETURN_LINK - XXX Not implemented, see notes below. 9947c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES - return tuples with 9957c478bd9Sstevel@tonic-gate * CISTPLF_IGNORE_TUPLE set in the 9967c478bd9Sstevel@tonic-gate * cistpl_t->flags member. 9977c478bd9Sstevel@tonic-gate * 9987c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 9997c478bd9Sstevel@tonic-gate * 10007c478bd9Sstevel@tonic-gate * On a single-function card, the caller will get back all the tuples in 10017c478bd9Sstevel@tonic-gate * the CIS. 10027c478bd9Sstevel@tonic-gate * 10037c478bd9Sstevel@tonic-gate * On a multi-function card, the caller will get the tuples from the 10047c478bd9Sstevel@tonic-gate * global CIS followed by the tuples in the function-specific CIS. The 10057c478bd9Sstevel@tonic-gate * caller will not get any tuples from a function-specific CIS that 10067c478bd9Sstevel@tonic-gate * does not belong to the caller's function. 10077c478bd9Sstevel@tonic-gate * 10087c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 10097c478bd9Sstevel@tonic-gate * 10107c478bd9Sstevel@tonic-gate * On a single-function card, the operation is the same as for regular 10117c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 10127c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS this function will return CS_NO_CIS. 10137c478bd9Sstevel@tonic-gate * 10147c478bd9Sstevel@tonic-gate * On a multi-function card, the operation is the same as for regular 10157c478bd9Sstevel@tonic-gate * PC card driver callers with the addition that if the function number 10167c478bd9Sstevel@tonic-gate * is set to CS_GLOBAL_CIS the caller will only get tuples from the 10177c478bd9Sstevel@tonic-gate * global CIS. If a particular function nubmer does not exist, this 10187c478bd9Sstevel@tonic-gate * function will return CS_NO_CIS for that function. 10197c478bd9Sstevel@tonic-gate * 10207c478bd9Sstevel@tonic-gate * General notes: 10217c478bd9Sstevel@tonic-gate * 10227c478bd9Sstevel@tonic-gate * On both a single-function card and a multi-function card, if the tuple 10237c478bd9Sstevel@tonic-gate * comes from the global CIS chain, the CISTPLF_GLOBAL_CIS flag will be 10247c478bd9Sstevel@tonic-gate * set in the tuple_t->flags member. 10257c478bd9Sstevel@tonic-gate * 10267c478bd9Sstevel@tonic-gate * On a multi-function card, if the tuple comes from the function-specific 10277c478bd9Sstevel@tonic-gate * CIS chain, the CISTPLF_MF_CIS flag will be set in the tuple_t->flags 10287c478bd9Sstevel@tonic-gate * member. 10297c478bd9Sstevel@tonic-gate * 10307c478bd9Sstevel@tonic-gate * For other flags that are set in the tuple_t->flags member, see the 10317c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 10327c478bd9Sstevel@tonic-gate * 10337c478bd9Sstevel@tonic-gate * The CIS parser may not include all the tuples that are in the CIS in 10347c478bd9Sstevel@tonic-gate * the private CIS list that it creates and maintains. See the CIS 10357c478bd9Sstevel@tonic-gate * parser documentation for a list of tuples that the parser does not 10367c478bd9Sstevel@tonic-gate * include in the list. 10377c478bd9Sstevel@tonic-gate * 10387c478bd9Sstevel@tonic-gate * If a tuple has the CISTPLF_IGNORE_TUPLE flag set and the flags 10397c478bd9Sstevel@tonic-gate * parameter CIS_GET_LTUPLE_IGNORE is not set, that tuple will not 10407c478bd9Sstevel@tonic-gate * be returned to the caller. Instead, the next tuple that matches 10417c478bd9Sstevel@tonic-gate * the calling criteria will be returned (or NULL if no other tuples 10427c478bd9Sstevel@tonic-gate * match the calling criteria). If CIS_GET_LTUPLE_IGNORE is set in 10437c478bd9Sstevel@tonic-gate * the flags paramter, tuples in the CIS list that match the calling 10447c478bd9Sstevel@tonic-gate * criteria will be returned. 10457c478bd9Sstevel@tonic-gate * 10467c478bd9Sstevel@tonic-gate * XXX The PC Card 95 Standard says that if the TUPLE_RETURN_LINK flag in 10477c478bd9Sstevel@tonic-gate * the tuple_t->Attributes member is not set, then we don't return 10487c478bd9Sstevel@tonic-gate * any of the link tuples. This function ignores this flag and always 10497c478bd9Sstevel@tonic-gate * returns link tuples. 10507c478bd9Sstevel@tonic-gate * 10517c478bd9Sstevel@tonic-gate * Return codes: 10527c478bd9Sstevel@tonic-gate * CS_SUCCESS - if tuple sucessfully found and returned 10537c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card inserted 10547c478bd9Sstevel@tonic-gate * CS_NO_CIS - if no CIS for the specified card/function 10557c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if tuple not found or no more tuples 10567c478bd9Sstevel@tonic-gate * to return 10577c478bd9Sstevel@tonic-gate * 10587c478bd9Sstevel@tonic-gate * See notes for cs_get_socket for a description of valid client, socket 10597c478bd9Sstevel@tonic-gate * and function number combinations. 10607c478bd9Sstevel@tonic-gate */ 10617c478bd9Sstevel@tonic-gate static int 10627c478bd9Sstevel@tonic-gate cs_get_firstnext_tuple(client_handle_t client_handle, 10637c478bd9Sstevel@tonic-gate tuple_t *tuple, uint32_t flags) 10647c478bd9Sstevel@tonic-gate { 10657c478bd9Sstevel@tonic-gate cs_socket_t *sp; 10667c478bd9Sstevel@tonic-gate client_t *client; 10677c478bd9Sstevel@tonic-gate uint32_t fn; 10687c478bd9Sstevel@tonic-gate int ret; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 10717c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 10727c478bd9Sstevel@tonic-gate return (ret); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate /* 10757c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 10767c478bd9Sstevel@tonic-gate * for this client, then return an error. 10777c478bd9Sstevel@tonic-gate */ 10787c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 10797c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* 10847c478bd9Sstevel@tonic-gate * If there's no CIS on this card or no CIS for the specified 10857c478bd9Sstevel@tonic-gate * function, then we can't do much. 10867c478bd9Sstevel@tonic-gate */ 10877c478bd9Sstevel@tonic-gate if ((!(sp->cis_flags & CW_VALID_CIS)) || 10887c478bd9Sstevel@tonic-gate (!(sp->cis[fn].flags & CW_VALID_CIS))) { 10897c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 10907c478bd9Sstevel@tonic-gate return (CS_NO_CIS); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate /* 10947c478bd9Sstevel@tonic-gate * This will set the CIS_GET_LTUPLE_IGNORE flag if the 10957c478bd9Sstevel@tonic-gate * TUPLE_RETURN_IGNORED_TUPLES flag is set. The 10967c478bd9Sstevel@tonic-gate * assumption here is that the CIS_GET_LTUPLE_IGNORE 10977c478bd9Sstevel@tonic-gate * flag and the TUPLE_RETURN_IGNORED_TUPLES flag 10987c478bd9Sstevel@tonic-gate * shares the same bit position. If this ever changes, 10997c478bd9Sstevel@tonic-gate * we'll ahve to re-work this section of code. 11007c478bd9Sstevel@tonic-gate */ 11017c478bd9Sstevel@tonic-gate if (tuple->Attributes & TUPLE_RETURN_IGNORED_TUPLES) 11027c478bd9Sstevel@tonic-gate flags |= CIS_GET_LTUPLE_IGNORE; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate /* 11057c478bd9Sstevel@tonic-gate * Are we GetFirstTuple or GetNextTuple? 11067c478bd9Sstevel@tonic-gate */ 11077c478bd9Sstevel@tonic-gate if ((flags & CIS_GET_LTUPLE_OPMASK) & CS_GET_FIRST_FLAG) { 11087c478bd9Sstevel@tonic-gate /* 11097c478bd9Sstevel@tonic-gate * Initialize the tuple structure; we need this information when 11107c478bd9Sstevel@tonic-gate * we have to process a GetNextTuple or ParseTuple call. 11117c478bd9Sstevel@tonic-gate * If this card has a multi-function CIS, then we always start out 11127c478bd9Sstevel@tonic-gate * delivering tuples from the global CIS chain. If this card does 11137c478bd9Sstevel@tonic-gate * not have a multi-function CIS, then the function 0 CIS chain 11147c478bd9Sstevel@tonic-gate * will contain the complete CIS list. 11157c478bd9Sstevel@tonic-gate * If this is a multi-function card, then use the GET_FIRST_LTUPLE 11167c478bd9Sstevel@tonic-gate * macro to return the first tuple in the CIS list - we do this 11177c478bd9Sstevel@tonic-gate * since we don't want to return tuples with CISTPLF_IGNORE_TUPLE 11187c478bd9Sstevel@tonic-gate * set unless CIS_GET_LTUPLE_IGNORE is set in the flags parameter. 11197c478bd9Sstevel@tonic-gate * Note that we don't have to cross over into the fucntion-specific 11207c478bd9Sstevel@tonic-gate * CIS chain if GET_FIRST_LTUPLE returns NULL, since a MF CIS will 11217c478bd9Sstevel@tonic-gate * always have at least a CISTPL_LONGLINK_MFC tuple in the global 11227c478bd9Sstevel@tonic-gate * CIS chain - the test for NULL is just a sanity check. 11237c478bd9Sstevel@tonic-gate */ 11247c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11257c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = 11267c478bd9Sstevel@tonic-gate GET_FIRST_LTUPLE(sp->cis[CS_GLOBAL_CIS].cis, 11277c478bd9Sstevel@tonic-gate flags)) == NULL) { 11287c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11297c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11307c478bd9Sstevel@tonic-gate } /* GET_FIRST_LTUPLE */ 11317c478bd9Sstevel@tonic-gate } else { 11327c478bd9Sstevel@tonic-gate tuple->CISOffset = sp->cis[0].cis; 11337c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11347c478bd9Sstevel@tonic-gate } else { 11357c478bd9Sstevel@tonic-gate cistpl_t *tp; 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate /* 11387c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL tuple list pointer. 11397c478bd9Sstevel@tonic-gate * This is necessary in the case where the caller calls us 11407c478bd9Sstevel@tonic-gate * with get next tuple requests but we don't have any more 11417c478bd9Sstevel@tonic-gate * tuples to give back. 11427c478bd9Sstevel@tonic-gate */ 11437c478bd9Sstevel@tonic-gate if (tuple->CISOffset == NULL) { 11447c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11457c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate /* 11497c478bd9Sstevel@tonic-gate * Point to the next tuple in the list. If we're searching for 11507c478bd9Sstevel@tonic-gate * a particular tuple, FIND_LTUPLE_FWD will find it. 11517c478bd9Sstevel@tonic-gate * 11527c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain that we're looking 11537c478bd9Sstevel@tonic-gate * at, then if we're looking at the global portion of a 11547c478bd9Sstevel@tonic-gate * multi-function CIS, switch to the function-specific list 11557c478bd9Sstevel@tonic-gate * and start looking there. 11567c478bd9Sstevel@tonic-gate */ 11577c478bd9Sstevel@tonic-gate if ((tp = GET_NEXT_TUPLE(tuple->CISOffset, flags)) == NULL) { 11587c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11597c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 11607c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 11617c478bd9Sstevel@tonic-gate tp = GET_FIRST_LTUPLE(sp->cis[fn].cis, flags); 11627c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 11637c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11647c478bd9Sstevel@tonic-gate } /* GET_NEXT_TUPLE */ 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* 11677c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 11687c478bd9Sstevel@tonic-gate */ 11697c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 11707c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 11717c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate } /* CS_GET_FIRST_FLAG */ 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate /* 11767c478bd9Sstevel@tonic-gate * Check if we want to get the first of a particular type of tuple 11777c478bd9Sstevel@tonic-gate * or just the first tuple in the chain. 11787c478bd9Sstevel@tonic-gate * If there are no more tuples of the type we're searching for in 11797c478bd9Sstevel@tonic-gate * the chain that we're looking at, then if we're looking at 11807c478bd9Sstevel@tonic-gate * the global portion of a multi-function CIS, switch to the 11817c478bd9Sstevel@tonic-gate * function-specific list and start looking there. 11827c478bd9Sstevel@tonic-gate */ 11837c478bd9Sstevel@tonic-gate if (tuple->DesiredTuple != RETURN_FIRST_TUPLE) { 11847c478bd9Sstevel@tonic-gate cistpl_t *tp; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate if ((tp = FIND_LTUPLE_FWD(tuple->CISOffset, 11877c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags)) == NULL) { 11887c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 11897c478bd9Sstevel@tonic-gate if ((tuple->CISOffset->flags & CISTPLF_GLOBAL_CIS) && 11907c478bd9Sstevel@tonic-gate (fn != CS_GLOBAL_CIS)) { 11917c478bd9Sstevel@tonic-gate tp = FIND_FIRST_LTUPLE(sp->cis[fn].cis, 11927c478bd9Sstevel@tonic-gate tuple->DesiredTuple, flags); 11937c478bd9Sstevel@tonic-gate } /* CISTPLF_GLOBAL_CIS */ 11947c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 11957c478bd9Sstevel@tonic-gate } /* FIND_LTUPLE_FWD */ 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate /* 11987c478bd9Sstevel@tonic-gate * If there are no more tuples in the chain, then return. 11997c478bd9Sstevel@tonic-gate */ 12007c478bd9Sstevel@tonic-gate if ((tuple->CISOffset = tp) == NULL) { 12017c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12027c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate } /* !RETURN_FIRST_TUPLE */ 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate /* 12077c478bd9Sstevel@tonic-gate * We've got a tuple, now fill out the rest of the tuple_t 12087c478bd9Sstevel@tonic-gate * structure. Callers can use the flags member to 12097c478bd9Sstevel@tonic-gate * determine whether or not the tuple data was copied 12107c478bd9Sstevel@tonic-gate * to the linked list or if it's still on the card. 12117c478bd9Sstevel@tonic-gate */ 12127c478bd9Sstevel@tonic-gate tuple->Flags = tuple->CISOffset->flags; 12137c478bd9Sstevel@tonic-gate tuple->TupleCode = tuple->CISOffset->type; 12147c478bd9Sstevel@tonic-gate tuple->TupleLink = tuple->CISOffset->len; 12157c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->CISOffset->len; 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate /* 12237c478bd9Sstevel@tonic-gate * cs_get_tuple_data - get the data portion of a tuple; this is to 12247c478bd9Sstevel@tonic-gate * support the GetTupleData function call. 12257c478bd9Sstevel@tonic-gate * 12267c478bd9Sstevel@tonic-gate * Note that if the data body of a tuple was not read from the CIS, 12277c478bd9Sstevel@tonic-gate * then this function will return CS_NO_MORE_ITEMS. 12287c478bd9Sstevel@tonic-gate * 12297c478bd9Sstevel@tonic-gate * For flags that are set in the tuple_t->flags member, see the 12307c478bd9Sstevel@tonic-gate * comments for the cis_list_lcreate function in the cis.c file. 12317c478bd9Sstevel@tonic-gate * These flags are copied into the tuple_t->flags member by the 12327c478bd9Sstevel@tonic-gate * cs_get_firstnext_tuple function call. 12337c478bd9Sstevel@tonic-gate * 12347c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 12357c478bd9Sstevel@tonic-gate */ 12367c478bd9Sstevel@tonic-gate static int 12377c478bd9Sstevel@tonic-gate cs_get_tuple_data(client_handle_t client_handle, tuple_t *tuple) 12387c478bd9Sstevel@tonic-gate { 12397c478bd9Sstevel@tonic-gate cs_socket_t *sp; 12407c478bd9Sstevel@tonic-gate client_t *client; 12417c478bd9Sstevel@tonic-gate int ret, nbytes; 12427c478bd9Sstevel@tonic-gate uint32_t fn, flags; 12437c478bd9Sstevel@tonic-gate cisdata_t *tsd, *tdd; 12447c478bd9Sstevel@tonic-gate uint32_t newoffset; 12457c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &tuple->Socket, &fn, 12487c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 12497c478bd9Sstevel@tonic-gate return (ret); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* 12527c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 12537c478bd9Sstevel@tonic-gate * for this client, then return an error. 12547c478bd9Sstevel@tonic-gate */ 12557c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 12567c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 12617c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate /* 12647c478bd9Sstevel@tonic-gate * Check to be sure that we have a non-NULL pointer to 12657c478bd9Sstevel@tonic-gate * a CIS list. 12667c478bd9Sstevel@tonic-gate */ 12677c478bd9Sstevel@tonic-gate if (!(tuple->CISOffset)) { 12687c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12697c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate /* 12737c478bd9Sstevel@tonic-gate * Since the tuple data buffer that the caller calls us with 12747c478bd9Sstevel@tonic-gate * is preallocated in the tuple_t structure, we ignore any 12757c478bd9Sstevel@tonic-gate * TupleDataMax value that the caller has setup and use the 12767c478bd9Sstevel@tonic-gate * actual size of the tuple data buffer in the structure. 12777c478bd9Sstevel@tonic-gate */ 12787c478bd9Sstevel@tonic-gate tuple->TupleDataMax = sizeof (tuple->TupleData); 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate /* 12817c478bd9Sstevel@tonic-gate * Make sure the requested offset is not past the end of the 12827c478bd9Sstevel@tonic-gate * tuple data body nor past the end of the user-supplied 12837c478bd9Sstevel@tonic-gate * buffer. 12847c478bd9Sstevel@tonic-gate */ 12857c478bd9Sstevel@tonic-gate if ((int)tuple->TupleOffset >= min((int)tuple->TupleLink, 12867c478bd9Sstevel@tonic-gate (int)tuple->TupleDataMax)) { 12877c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12887c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate tuple->TupleDataLen = tuple->TupleLink; 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate if ((nbytes = min((int)tuple->TupleDataMax - 12947c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset, 12957c478bd9Sstevel@tonic-gate (int)tuple->TupleDataLen - 12967c478bd9Sstevel@tonic-gate (int)tuple->TupleOffset)) < 1) { 12977c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 12987c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate /* 13027c478bd9Sstevel@tonic-gate * The tuple data destination is always the tuple_t->TupleData 13037c478bd9Sstevel@tonic-gate * buffer in the tuple_t structure no matter where we read the 13047c478bd9Sstevel@tonic-gate * tuple data from. 13057c478bd9Sstevel@tonic-gate */ 13067c478bd9Sstevel@tonic-gate tdd = tuple->TupleData; 13077c478bd9Sstevel@tonic-gate bzero((caddr_t)tdd, sizeof (tuple->TupleData)); 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate /* 13107c478bd9Sstevel@tonic-gate * Do we have a copy of the tuple data? If not, we have to 13117c478bd9Sstevel@tonic-gate * get a pointer to the CIS and read the tuple data from the 13127c478bd9Sstevel@tonic-gate * card itself. 13137c478bd9Sstevel@tonic-gate */ 13147c478bd9Sstevel@tonic-gate switch (tuple->CISOffset->flags & CISTPLF_SPACE_MASK) { 13157c478bd9Sstevel@tonic-gate case CISTPLF_LM_SPACE: 13167c478bd9Sstevel@tonic-gate tsd = (tuple->CISOffset->data + 13177c478bd9Sstevel@tonic-gate (unsigned)tuple->TupleOffset); 13187c478bd9Sstevel@tonic-gate while (nbytes--) 13197c478bd9Sstevel@tonic-gate *tdd++ = *tsd++; 13207c478bd9Sstevel@tonic-gate break; 13217c478bd9Sstevel@tonic-gate case CISTPLF_AM_SPACE: 13227c478bd9Sstevel@tonic-gate case CISTPLF_CM_SPACE: 13237c478bd9Sstevel@tonic-gate newoffset = tuple->CISOffset->offset; 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate /* 13267c478bd9Sstevel@tonic-gate * Setup the proper space flags as well as setup the 13277c478bd9Sstevel@tonic-gate * address offset to point to the start of the tuple 13287c478bd9Sstevel@tonic-gate * data area; we need to do the latter since the 13297c478bd9Sstevel@tonic-gate * cis_store_cis_addr function in cis.c sets up the 13307c478bd9Sstevel@tonic-gate * tuple->CISOffset->offset offset to point to the 13317c478bd9Sstevel@tonic-gate * start of the tuple. 13327c478bd9Sstevel@tonic-gate */ 13337c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) { 13347c478bd9Sstevel@tonic-gate flags = CISTPLF_AM_SPACE; 13357c478bd9Sstevel@tonic-gate newoffset += ((tuple->TupleOffset * 2) + 4); 13367c478bd9Sstevel@tonic-gate } else { 13377c478bd9Sstevel@tonic-gate flags = CISTPLF_CM_SPACE; 13387c478bd9Sstevel@tonic-gate newoffset += (tuple->TupleOffset + 2); 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 13427c478bd9Sstevel@tonic-gate flags) != CS_SUCCESS) { 13437c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13447c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_tuple_data: socket %d " 13457c478bd9Sstevel@tonic-gate "can't init CIS window\n", 13467c478bd9Sstevel@tonic-gate sp->socket_num); 13477c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 13487c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 13497c478bd9Sstevel@tonic-gate while (nbytes--) { 13507c478bd9Sstevel@tonic-gate *tdd++ = csx_Get8(cis_handle, newoffset++); 13517c478bd9Sstevel@tonic-gate if (tuple->CISOffset->flags & CISTPLF_AM_SPACE) 13527c478bd9Sstevel@tonic-gate newoffset++; 13537c478bd9Sstevel@tonic-gate } /* while */ 13547c478bd9Sstevel@tonic-gate break; 13557c478bd9Sstevel@tonic-gate default: 13567c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13577c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 13587c478bd9Sstevel@tonic-gate } /* switch */ 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 13617c478bd9Sstevel@tonic-gate } else { 13627c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 13637c478bd9Sstevel@tonic-gate } /* if (CW_VALID_CIS) */ 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate return (ret); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * cs_validate_cis - validates the CIS on a card in the given socket; this 13727c478bd9Sstevel@tonic-gate * is to support the ValidateCIS function call. 13737c478bd9Sstevel@tonic-gate * 13747c478bd9Sstevel@tonic-gate * Notes for regular PC card driver callers: 13757c478bd9Sstevel@tonic-gate * 13767c478bd9Sstevel@tonic-gate * Regular PC card drivers calling ValidateCIS will get the meaning of 13777c478bd9Sstevel@tonic-gate * the structure members as specified in the standard. 13787c478bd9Sstevel@tonic-gate * 13797c478bd9Sstevel@tonic-gate * Notes for Socket Services, the "super-client" or CSI driver callers: 13807c478bd9Sstevel@tonic-gate * 13817c478bd9Sstevel@tonic-gate * with: Function Number = CS_GLOBAL_CIS 13827c478bd9Sstevel@tonic-gate * 13837c478bd9Sstevel@tonic-gate * For a single-function card, CS_NO_CIS will be returned and the 13847c478bd9Sstevel@tonic-gate * cisinfo_t->Chains and cisinfo_t->Tuples members will be set to 0. 13857c478bd9Sstevel@tonic-gate * 13867c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 13877c478bd9Sstevel@tonic-gate * the number of CIS chains in the global portion of the CIS, and 13887c478bd9Sstevel@tonic-gate * cisinfo_t->Tuples will contain a count of the number of tuples in 13897c478bd9Sstevel@tonic-gate * the global portion of the CIS. 13907c478bd9Sstevel@tonic-gate * 13917c478bd9Sstevel@tonic-gate * with: 0 <= Function Number < CIS_MAX_FUNCTIONS 13927c478bd9Sstevel@tonic-gate * 13937c478bd9Sstevel@tonic-gate * For a single-function card, if the function number is equal to 0 and 13947c478bd9Sstevel@tonic-gate * has a CIS, cisinfo_t->Chains will contain a count of the number of 13957c478bd9Sstevel@tonic-gate * CIS chains in the CIS, and cisinfo_t->Tuples will contain a count of 13967c478bd9Sstevel@tonic-gate * the number of tuples in the CIS. If the card does not have a CIS, or 13977c478bd9Sstevel@tonic-gate * if the function number is not equal to 0, CS_NO_CIS will be returned 13987c478bd9Sstevel@tonic-gate * and the cisinfo_t->Chains and cisinfo_t->Tuples members will be set 13997c478bd9Sstevel@tonic-gate * to 0. 14007c478bd9Sstevel@tonic-gate * 14017c478bd9Sstevel@tonic-gate * For a multi-function card, cisinfo_t->Chains will contain a count of 14027c478bd9Sstevel@tonic-gate * the number of CIS chains in the global and function-specific 14037c478bd9Sstevel@tonic-gate * portions of the CIS, and cisinfo_t->Tuples will contain a count of 14047c478bd9Sstevel@tonic-gate * the number of tuples in the global and function-specific portions of 14057c478bd9Sstevel@tonic-gate * the CIS. If the function does not exist or has no CIS, CS_NO_CIS 14067c478bd9Sstevel@tonic-gate * will be returned and the cisinfo_t->Chains and cisinfo_t->Tuples 14077c478bd9Sstevel@tonic-gate * members will be set to 0. 14087c478bd9Sstevel@tonic-gate * 14097c478bd9Sstevel@tonic-gate * General notes: 14107c478bd9Sstevel@tonic-gate * 14117c478bd9Sstevel@tonic-gate * If the card does not have a CIS, or if the function does not exist 14127c478bd9Sstevel@tonic-gate * or has no CIS, CS_NO_CIS will be returned and the cisinfo_t->Chains 14137c478bd9Sstevel@tonic-gate * and cisinfo_t->Tuples members will be set to 0. 14147c478bd9Sstevel@tonic-gate * 14157c478bd9Sstevel@tonic-gate * Most of the work of validating the CIS has already been done by the 14167c478bd9Sstevel@tonic-gate * CIS parser module, so we don't have to do much here except for 14177c478bd9Sstevel@tonic-gate * looking at the various flags and tuple/chain counts that were already 14187c478bd9Sstevel@tonic-gate * setup by the CIS parser. 14197c478bd9Sstevel@tonic-gate * 14207c478bd9Sstevel@tonic-gate * See notes for the cs_get_firstnext_tuple function. 14217c478bd9Sstevel@tonic-gate */ 14227c478bd9Sstevel@tonic-gate static int 14237c478bd9Sstevel@tonic-gate cs_validate_cis(client_handle_t client_handle, cisinfo_t *cisinfo) 14247c478bd9Sstevel@tonic-gate { 14257c478bd9Sstevel@tonic-gate cs_socket_t *sp; 14267c478bd9Sstevel@tonic-gate client_t *client; 14277c478bd9Sstevel@tonic-gate uint32_t fn; 14287c478bd9Sstevel@tonic-gate int ret; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate if ((ret = cs_get_socket(client_handle, &cisinfo->Socket, &fn, 14317c478bd9Sstevel@tonic-gate &sp, &client)) != CS_SUCCESS) 14327c478bd9Sstevel@tonic-gate return (ret); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 14367c478bd9Sstevel@tonic-gate * for this client, then return an error. 14377c478bd9Sstevel@tonic-gate */ 14387c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 14397c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 14427c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_VALID_CIS) && 14437c478bd9Sstevel@tonic-gate (sp->cis[fn].flags & CW_VALID_CIS)) { 14447c478bd9Sstevel@tonic-gate cisinfo->Chains = sp->cis[fn].nchains; 14457c478bd9Sstevel@tonic-gate cisinfo->Tuples = sp->cis[fn].ntuples; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if ((fn != CS_GLOBAL_CIS) && 14487c478bd9Sstevel@tonic-gate (sp->cis[CS_GLOBAL_CIS].flags & CW_VALID_CIS)) { 14497c478bd9Sstevel@tonic-gate cisinfo->Chains += sp->cis[CS_GLOBAL_CIS].nchains; 14507c478bd9Sstevel@tonic-gate cisinfo->Tuples += sp->cis[CS_GLOBAL_CIS].ntuples; 14517c478bd9Sstevel@tonic-gate } /* !CS_GLOBAL_CIS */ 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 14547c478bd9Sstevel@tonic-gate } else { 14557c478bd9Sstevel@tonic-gate cisinfo->Chains = 0; 14567c478bd9Sstevel@tonic-gate cisinfo->Tuples = 0; 14577c478bd9Sstevel@tonic-gate ret = CS_NO_CIS; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate return (ret); 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate /* 14657c478bd9Sstevel@tonic-gate * cs_init_cis_window - initializes the CIS window for the passed socket 14667c478bd9Sstevel@tonic-gate * 14677c478bd9Sstevel@tonic-gate * calling: *sp - pointer to the per-socket structure 14687c478bd9Sstevel@tonic-gate * *offset - offset from start of AM or CM space 14697c478bd9Sstevel@tonic-gate * *hp - pointer to acc_handle_t to store modified 14707c478bd9Sstevel@tonic-gate * window access handle in 14717c478bd9Sstevel@tonic-gate * flags - one of: 14727c478bd9Sstevel@tonic-gate * CISTPLF_AM_SPACE - set window to AM space 14737c478bd9Sstevel@tonic-gate * CISTPLF_CM_SPACE - set window to CM space 14747c478bd9Sstevel@tonic-gate * 14757c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if CIS window was set up 14767c478bd9Sstevel@tonic-gate * *offset - contains adjusted offset to use to access 14777c478bd9Sstevel@tonic-gate * requested space 14787c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW if CIS window could not be setup 14797c478bd9Sstevel@tonic-gate * CS_GENERAL_FAILURE if socket has a CIS window number 14807c478bd9Sstevel@tonic-gate * but the window flags are wrong 14817c478bd9Sstevel@tonic-gate * 14827c478bd9Sstevel@tonic-gate * Note: This function will check to be sure that there is a valid 14837c478bd9Sstevel@tonic-gate * CIS window allocated to this socket. 14847c478bd9Sstevel@tonic-gate * If there is an error in setting up the window hardware, the 14857c478bd9Sstevel@tonic-gate * CIS window information for this socket is cleared. 14867c478bd9Sstevel@tonic-gate * This function is also used by routines that need to get 14877c478bd9Sstevel@tonic-gate * a pointer to the base of AM space to access the card's 14887c478bd9Sstevel@tonic-gate * configuration registers. 14897c478bd9Sstevel@tonic-gate * The passed offset is the un-window-size-aligned offset. 14907c478bd9Sstevel@tonic-gate */ 14917c478bd9Sstevel@tonic-gate int 14927c478bd9Sstevel@tonic-gate cs_init_cis_window(cs_socket_t *sp, uint32_t *offset, 14937c478bd9Sstevel@tonic-gate acc_handle_t *hp, uint32_t flags) 14947c478bd9Sstevel@tonic-gate { 14957c478bd9Sstevel@tonic-gate set_window_t sw; 14967c478bd9Sstevel@tonic-gate get_window_t gw; 14977c478bd9Sstevel@tonic-gate inquire_window_t iw; 14987c478bd9Sstevel@tonic-gate set_page_t set_page; 14997c478bd9Sstevel@tonic-gate cs_window_t *cw; 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate /* 15027c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 15037c478bd9Sstevel@tonic-gate */ 15047c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 15057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15067c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d has no CIS window\n", 15077c478bd9Sstevel@tonic-gate sp->socket_num); 15087c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate /* 15127c478bd9Sstevel@tonic-gate * Check to be sure that this window is allocated for CIS use 15137c478bd9Sstevel@tonic-gate */ 15147c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) 15157c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (!(cw->state & CW_CIS)) { 15187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15197c478bd9Sstevel@tonic-gate "cs_init_cis_window: socket %d invalid CIS window state 0x%x\n", 15207c478bd9Sstevel@tonic-gate sp->socket_num, cw->state); 15217c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * Get the characteristics of this window - we use this to 15267c478bd9Sstevel@tonic-gate * determine whether we need to re-map the window or 15277c478bd9Sstevel@tonic-gate * just move the window offset on the card. 15287c478bd9Sstevel@tonic-gate */ 15297c478bd9Sstevel@tonic-gate iw.window = sp->cis_win_num; 15307c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate /* 15337c478bd9Sstevel@tonic-gate * We've got a window, now set up the hardware. If we've got 15347c478bd9Sstevel@tonic-gate * a variable sized window, then all we need to do is to 15357c478bd9Sstevel@tonic-gate * get a valid mapping to the base of the window using 15367c478bd9Sstevel@tonic-gate * the current window size; if we've got a fixed-size 15377c478bd9Sstevel@tonic-gate * window, then we need to get a mapping to the window 15387c478bd9Sstevel@tonic-gate * starting at offset zero of the window. 15397c478bd9Sstevel@tonic-gate */ 15407c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_SIZE) { 15417c478bd9Sstevel@tonic-gate sw.WindowSize = sp->cis_win_size; 15427c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / sp->cis_win_size) * 15437c478bd9Sstevel@tonic-gate sp->cis_win_size); 15447c478bd9Sstevel@tonic-gate } else { 15457c478bd9Sstevel@tonic-gate set_page.offset = ((*offset / iw.mem_win_char.MinSize) * 15467c478bd9Sstevel@tonic-gate iw.mem_win_char.MinSize); 15477c478bd9Sstevel@tonic-gate sw.WindowSize = (((*offset & ~(PAGESIZE - 1)) & 15487c478bd9Sstevel@tonic-gate (set_page.offset - 1)) + PAGESIZE); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate /* 15527c478bd9Sstevel@tonic-gate * Return a normalized base offset; this takes care of the case 15537c478bd9Sstevel@tonic-gate * where the required offset is greater than the window size. 15547c478bd9Sstevel@tonic-gate * BugID 1236404 15557c478bd9Sstevel@tonic-gate * code was: 15567c478bd9Sstevel@tonic-gate * *offset = *offset & (set_page.offset - 1); 15577c478bd9Sstevel@tonic-gate */ 15587c478bd9Sstevel@tonic-gate *offset = *offset - set_page.offset; 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 15617c478bd9Sstevel@tonic-gate if (cs_debug > 1) 15627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_init_cis_window: WindowSize 0x%x " 15637c478bd9Sstevel@tonic-gate "offset 0x%x\n", 15647c478bd9Sstevel@tonic-gate (int)sw.WindowSize, 15657c478bd9Sstevel@tonic-gate (int)set_page.offset); 15667c478bd9Sstevel@tonic-gate if (cs_debug > 1) 15677c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\t*offset = 0x%x space = %s\n", 15687c478bd9Sstevel@tonic-gate (int)*offset, 15697c478bd9Sstevel@tonic-gate (flags & CISTPLF_AM_SPACE)? 15707c478bd9Sstevel@tonic-gate "CISTPLF_AM_SPACE":"CISTPLF_CM_SPACE"); 15717c478bd9Sstevel@tonic-gate #endif 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate sw.window = sp->cis_win_num; 15747c478bd9Sstevel@tonic-gate sw.socket = sp->socket_num; 15757c478bd9Sstevel@tonic-gate sw.state = (WS_ENABLED | WS_EXACT_MAPIN); 15767c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 15777c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 15787c478bd9Sstevel@tonic-gate sw.attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate /* 15817c478bd9Sstevel@tonic-gate * The PCMCIA SS spec specifies this be expressed in 15827c478bd9Sstevel@tonic-gate * a device speed format per 5.2.7.1.3 but 15837c478bd9Sstevel@tonic-gate * our implementation of SS_SetWindow uses 15847c478bd9Sstevel@tonic-gate * actual nanoseconds. 15857c478bd9Sstevel@tonic-gate */ 15867c478bd9Sstevel@tonic-gate sw.speed = CIS_DEFAULT_SPEED; 15877c478bd9Sstevel@tonic-gate sw.base = 0; 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * Set up the window - if this fails, then just set the 15907c478bd9Sstevel@tonic-gate * CIS window number back to it's initialized value so 15917c478bd9Sstevel@tonic-gate * that we'll fail when we break out of the loop. 15927c478bd9Sstevel@tonic-gate */ 15937c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) { 15947c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 15957c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 15967c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 15977c478bd9Sstevel@tonic-gate } else { 15987c478bd9Sstevel@tonic-gate set_page.window = sp->cis_win_num; 15997c478bd9Sstevel@tonic-gate set_page.page = 0; 16007c478bd9Sstevel@tonic-gate set_page.state = PS_ENABLED; 16017c478bd9Sstevel@tonic-gate if (flags & CISTPLF_AM_SPACE) 16027c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 16057c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 16067c478bd9Sstevel@tonic-gate cw->state = 0; /* XXX do we really want to do this? */ 16077c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 16087c478bd9Sstevel@tonic-gate } /* if (SS_SetPage) */ 16097c478bd9Sstevel@tonic-gate } /* if (SS_SetWindow) */ 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * Get the window information for the CIS window for this socket. 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate gw.window = sp->cis_win_num; 16157c478bd9Sstevel@tonic-gate gw.socket = sp->socket_num; /* XXX - SS_GetWindow should set this */ 16167c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 16177c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate *hp = (acc_handle_t)gw.handle; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate /* 16257c478bd9Sstevel@tonic-gate * ==== client registration/deregistration section ==== 16267c478bd9Sstevel@tonic-gate */ 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate /* 16297c478bd9Sstevel@tonic-gate * cs_register_client - This supports the RegisterClient call. 16307c478bd9Sstevel@tonic-gate * 16317c478bd9Sstevel@tonic-gate * Upon successful registration, the client_handle_t * handle argument will 16327c478bd9Sstevel@tonic-gate * contain the new client handle and we return CS_SUCCESS. 16337c478bd9Sstevel@tonic-gate */ 16347c478bd9Sstevel@tonic-gate static int 16357c478bd9Sstevel@tonic-gate cs_register_client(client_handle_t *ch, client_reg_t *cr) 16367c478bd9Sstevel@tonic-gate { 16377c478bd9Sstevel@tonic-gate uint32_t sn; 16387c478bd9Sstevel@tonic-gate int super_client = 0; 16397c478bd9Sstevel@tonic-gate sclient_reg_t *scr = cr->priv; 16407c478bd9Sstevel@tonic-gate struct sclient_list_t *scli; 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate /* 16437c478bd9Sstevel@tonic-gate * See if we're not supposed to register any new clients. 16447c478bd9Sstevel@tonic-gate */ 16457c478bd9Sstevel@tonic-gate if (cs_globals.init_state & GLOBAL_INIT_STATE_NO_CLIENTS) 16467c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate /* 16497c478bd9Sstevel@tonic-gate * Do a version check - if the client expects a later version of 16507c478bd9Sstevel@tonic-gate * Card Services than what we are, return CS_BAD_VERSION. 16517c478bd9Sstevel@tonic-gate * XXX - How do we specify just a PARTICULAR version of CS?? 16527c478bd9Sstevel@tonic-gate */ 16537c478bd9Sstevel@tonic-gate if (CS_VERSION < cr->Version) 16547c478bd9Sstevel@tonic-gate return (CS_BAD_VERSION); 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * Check to be sure that the client has given us a valid set of 16587c478bd9Sstevel@tonic-gate * client type flags. We also use this opportunity to see 16597c478bd9Sstevel@tonic-gate * if the registering client is Socket Services or is a 16607c478bd9Sstevel@tonic-gate * "super-client" or a CSI client. 16617c478bd9Sstevel@tonic-gate * 16627c478bd9Sstevel@tonic-gate * Note that SS can not set any flag in the Attributes field other 16637c478bd9Sstevel@tonic-gate * than the INFO_SOCKET_SERVICES flag. 16647c478bd9Sstevel@tonic-gate * 16657c478bd9Sstevel@tonic-gate * Valid combinations of cr->Attributes and cr->EventMask flags: 16667c478bd9Sstevel@tonic-gate * 16677c478bd9Sstevel@tonic-gate * for Socket Services: 16687c478bd9Sstevel@tonic-gate * cr->Attributes: 16697c478bd9Sstevel@tonic-gate * set: 16707c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 16717c478bd9Sstevel@tonic-gate * clear: 16727c478bd9Sstevel@tonic-gate * {all other flags} 16737c478bd9Sstevel@tonic-gate * cr->EventMask: 16747c478bd9Sstevel@tonic-gate * don't care: 16757c478bd9Sstevel@tonic-gate * {all flags} 16767c478bd9Sstevel@tonic-gate * 16777c478bd9Sstevel@tonic-gate * for regular clients: 16787c478bd9Sstevel@tonic-gate * cr->Attributes: 16797c478bd9Sstevel@tonic-gate * only one of: 16807c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 16817c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 16827c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 16837c478bd9Sstevel@tonic-gate * don't care: 16847c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 16857c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 16867c478bd9Sstevel@tonic-gate * cr->EventMask: 16877c478bd9Sstevel@tonic-gate * clear: 16887c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 16897c478bd9Sstevel@tonic-gate * don't care: 16907c478bd9Sstevel@tonic-gate * {all other flags} 16917c478bd9Sstevel@tonic-gate * 16927c478bd9Sstevel@tonic-gate * for CSI clients: 16937c478bd9Sstevel@tonic-gate * cr->Attributes: 16947c478bd9Sstevel@tonic-gate * set: 16957c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 16967c478bd9Sstevel@tonic-gate * INFO_CSI_CLIENT 16977c478bd9Sstevel@tonic-gate * clear: 16987c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 16997c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 17007c478bd9Sstevel@tonic-gate * don't care: 17017c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 17027c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 17037c478bd9Sstevel@tonic-gate * cr->EventMask: 17047c478bd9Sstevel@tonic-gate * don't care: 17057c478bd9Sstevel@tonic-gate * {all flags} 17067c478bd9Sstevel@tonic-gate * 17077c478bd9Sstevel@tonic-gate * for "super-clients": 17087c478bd9Sstevel@tonic-gate * cr->Attributes: 17097c478bd9Sstevel@tonic-gate * set: 17107c478bd9Sstevel@tonic-gate * INFO_IO_CLIENT 17117c478bd9Sstevel@tonic-gate * INFO_MTD_CLIENT 17127c478bd9Sstevel@tonic-gate * INFO_SOCKET_SERVICES 17137c478bd9Sstevel@tonic-gate * INFO_CARD_SHARE 17147c478bd9Sstevel@tonic-gate * clear: 17157c478bd9Sstevel@tonic-gate * INFO_MEM_CLIENT 17167c478bd9Sstevel@tonic-gate * INFO_CARD_EXCL 17177c478bd9Sstevel@tonic-gate * cr->EventMask: 17187c478bd9Sstevel@tonic-gate * don't care: 17197c478bd9Sstevel@tonic-gate * {all flags} 17207c478bd9Sstevel@tonic-gate */ 17217c478bd9Sstevel@tonic-gate switch (cr->Attributes & INFO_CLIENT_TYPE_MASK) { 17227c478bd9Sstevel@tonic-gate /* 17237c478bd9Sstevel@tonic-gate * Check first to see if this is Socket Services registering; if 17247c478bd9Sstevel@tonic-gate * so, we don't do anything but return the client handle that is 17257c478bd9Sstevel@tonic-gate * in the global SS client. 17267c478bd9Sstevel@tonic-gate */ 17277c478bd9Sstevel@tonic-gate case INFO_SOCKET_SERVICES: 17287c478bd9Sstevel@tonic-gate *ch = cs_socket_services_client.client_handle; 17297c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 17307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 17317c478bd9Sstevel@tonic-gate /* CSI clients */ 17327c478bd9Sstevel@tonic-gate case (INFO_CSI_CLIENT | INFO_IO_CLIENT): 17337c478bd9Sstevel@tonic-gate break; 17347c478bd9Sstevel@tonic-gate /* regular clients */ 17357c478bd9Sstevel@tonic-gate case INFO_IO_CLIENT: 17367c478bd9Sstevel@tonic-gate case INFO_MTD_CLIENT: 17377c478bd9Sstevel@tonic-gate case INFO_MEM_CLIENT: 17387c478bd9Sstevel@tonic-gate if (cr->EventMask & CS_EVENT_ALL_CLIENTS) 17397c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17407c478bd9Sstevel@tonic-gate break; 17417c478bd9Sstevel@tonic-gate /* "super-client" clients */ 17427c478bd9Sstevel@tonic-gate case (INFO_IO_CLIENT | INFO_MTD_CLIENT | INFO_SOCKET_SERVICES): 17437c478bd9Sstevel@tonic-gate if ((!(cr->Attributes & INFO_CARD_SHARE)) || 17447c478bd9Sstevel@tonic-gate (cr->Attributes & INFO_CARD_EXCL)) 17457c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17467c478bd9Sstevel@tonic-gate /* 17477c478bd9Sstevel@tonic-gate * We only allow one "super-client" per system. 17487c478bd9Sstevel@tonic-gate */ 17497c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 17507c478bd9Sstevel@tonic-gate if (cs_globals.flags & GLOBAL_SUPER_CLIENT_REGISTERED) { 17517c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 17527c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate cs_globals.flags |= GLOBAL_SUPER_CLIENT_REGISTERED; 17557c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 17567c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 17577c478bd9Sstevel@tonic-gate break; 17587c478bd9Sstevel@tonic-gate default: 17597c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 17607c478bd9Sstevel@tonic-gate } /* switch (cr->Attributes) */ 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate /* 17637c478bd9Sstevel@tonic-gate * Now, actually create the client node on the socket; this will 17647c478bd9Sstevel@tonic-gate * also return the new client handle if there were no errors 17657c478bd9Sstevel@tonic-gate * creating the client node. 17667c478bd9Sstevel@tonic-gate * The DIP2SOCKET_NUM macro will return the socket and function 17677c478bd9Sstevel@tonic-gate * number using the encoding specified in the cs_priv.h file. 17687c478bd9Sstevel@tonic-gate */ 17697c478bd9Sstevel@tonic-gate if (super_client != CLIENT_SUPER_CLIENT) { 17707c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 17717c478bd9Sstevel@tonic-gate sn = (uint32_t)(uintptr_t)cr->priv; 17727c478bd9Sstevel@tonic-gate else 17737c478bd9Sstevel@tonic-gate sn = DIP2SOCKET_NUM(cr->dip); 17747c478bd9Sstevel@tonic-gate return (cs_add_client_to_socket(sn, ch, cr, super_client)); 17757c478bd9Sstevel@tonic-gate } /* CLIENT_SUPER_CLIENT */ 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate /* 17787c478bd9Sstevel@tonic-gate * This registering client is a "super-client", so we create one 17797c478bd9Sstevel@tonic-gate * client node for each socket in the system. We use the 17807c478bd9Sstevel@tonic-gate * client_reg_t.priv structure member to point to a struct 17817c478bd9Sstevel@tonic-gate * that the "super-client" client knows about. The client 17827c478bd9Sstevel@tonic-gate * handle pointer is not used in this case. 17837c478bd9Sstevel@tonic-gate * We return CS_SUCCESS if at least one client node could be 17847c478bd9Sstevel@tonic-gate * created. The client must check the error codes in the 17857c478bd9Sstevel@tonic-gate * error code array to determine which clients could not 17867c478bd9Sstevel@tonic-gate * be created on which sockets. 17877c478bd9Sstevel@tonic-gate * We return CS_BAD_HANDLE if no client nodes could be created. 17887c478bd9Sstevel@tonic-gate */ 17897c478bd9Sstevel@tonic-gate scr->num_clients = 0; 17907c478bd9Sstevel@tonic-gate scr->max_socket_num = cs_globals.max_socket_num; 17917c478bd9Sstevel@tonic-gate scr->num_sockets = cs_globals.num_sockets; 17927c478bd9Sstevel@tonic-gate scr->num_windows = cs_globals.num_windows; 17937c478bd9Sstevel@tonic-gate 17947c478bd9Sstevel@tonic-gate *(scr->sclient_list) = cs_globals.sclient_list; 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate for (sn = 0; sn < scr->num_sockets; sn++) { 17977c478bd9Sstevel@tonic-gate scli = scr->sclient_list[sn]; 17987c478bd9Sstevel@tonic-gate if ((scli->error = cs_add_client_to_socket(sn, &scli->client_handle, 17997c478bd9Sstevel@tonic-gate cr, super_client)) == CS_SUCCESS) { 18007c478bd9Sstevel@tonic-gate scr->num_clients++; 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate /* 18057c478bd9Sstevel@tonic-gate * If we couldn't create any client nodes at all, then 18067c478bd9Sstevel@tonic-gate * return an error. 18077c478bd9Sstevel@tonic-gate */ 18087c478bd9Sstevel@tonic-gate if (!scr->num_clients) { 18097c478bd9Sstevel@tonic-gate /* 18107c478bd9Sstevel@tonic-gate * XXX - The global superclient lock now gets 18117c478bd9Sstevel@tonic-gate * cleared in cs_deregister_client 18127c478bd9Sstevel@tonic-gate */ 18137c478bd9Sstevel@tonic-gate /* cs_clear_superclient_lock(super_client); */ 18147c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 18187c478bd9Sstevel@tonic-gate } 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate /* 18217c478bd9Sstevel@tonic-gate * cs_add_client_to_socket - this function creates the client node on the 18227c478bd9Sstevel@tonic-gate * requested socket. 18237c478bd9Sstevel@tonic-gate * 18247c478bd9Sstevel@tonic-gate * Note that if we return an error, there is no state that can be cleaned 18257c478bd9Sstevel@tonic-gate * up. The only way that we can return an error with allocated resources 18267c478bd9Sstevel@tonic-gate * would be if one of the client handle functions had an internal error. 18277c478bd9Sstevel@tonic-gate * Since we wouldn't get a valid client handle in this case anyway, there 18287c478bd9Sstevel@tonic-gate * would be no way to find out what was allocated and what wasn't. 18297c478bd9Sstevel@tonic-gate */ 18307c478bd9Sstevel@tonic-gate static int 18317c478bd9Sstevel@tonic-gate cs_add_client_to_socket(unsigned sn, client_handle_t *ch, 18327c478bd9Sstevel@tonic-gate client_reg_t *cr, int super_client) 18337c478bd9Sstevel@tonic-gate { 18347c478bd9Sstevel@tonic-gate cs_socket_t *sp; 18357c478bd9Sstevel@tonic-gate client_t *client, *cclp; 18367c478bd9Sstevel@tonic-gate int error, cie = 1; 18377c478bd9Sstevel@tonic-gate int client_lock_acquired; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate if (cr->event_handler == NULL) 18407c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 18417c478bd9Sstevel@tonic-gate 18427c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 18437c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate /* 18487c478bd9Sstevel@tonic-gate * Run through all of the registered clients and compare the passed 18497c478bd9Sstevel@tonic-gate * dip to the dip of each client to make sure that this client 18507c478bd9Sstevel@tonic-gate * is not trying to register more than once. If they are, then 18517c478bd9Sstevel@tonic-gate * display a message and return an error. 18527c478bd9Sstevel@tonic-gate * XXX - we should really check all the sockets in case the client 18537c478bd9Sstevel@tonic-gate * manipulates the instance number in the dip. 18547c478bd9Sstevel@tonic-gate * XXX - if we check each socket, we ned to also check for the 18557c478bd9Sstevel@tonic-gate * "super-client" since it will use the same dip for all 18567c478bd9Sstevel@tonic-gate * of it's client nodes. 18577c478bd9Sstevel@tonic-gate */ 18587c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 18597c478bd9Sstevel@tonic-gate client = sp->client_list; 18607c478bd9Sstevel@tonic-gate while (client) { 18617c478bd9Sstevel@tonic-gate if (!(cr->Attributes & INFO_CSI_CLIENT) && 18627c478bd9Sstevel@tonic-gate (client->dip == cr->dip)) { 18637c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18647c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 18657c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d " 18667c478bd9Sstevel@tonic-gate "function 0x%x\n" 18677c478bd9Sstevel@tonic-gate "\tclient already registered with " 18687c478bd9Sstevel@tonic-gate "handle 0x%x\n", 18697c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 18707c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 18717c478bd9Sstevel@tonic-gate (int)client->client_handle); 18727c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 18737c478bd9Sstevel@tonic-gate } 18747c478bd9Sstevel@tonic-gate client = client->next; 18757c478bd9Sstevel@tonic-gate } /* while (client) */ 18767c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate /* 18797c478bd9Sstevel@tonic-gate * Create a unique client handle then make sure that we can find it. 18807c478bd9Sstevel@tonic-gate * This has the side effect of getting us a pointer to the 18817c478bd9Sstevel@tonic-gate * client structure as well. 18827c478bd9Sstevel@tonic-gate * Create a client list entry - cs_create_client_handle will use this 18837c478bd9Sstevel@tonic-gate * as the new client node. 18847c478bd9Sstevel@tonic-gate * We do it here so that we can grab the sp->lock mutex for the 18857c478bd9Sstevel@tonic-gate * duration of our manipulation of the client list. 18867c478bd9Sstevel@tonic-gate * If this function fails, then it will not have added the newly 18877c478bd9Sstevel@tonic-gate * allocated client node to the client list on this socket, 18887c478bd9Sstevel@tonic-gate * so we have to free the node that we allocated. 18897c478bd9Sstevel@tonic-gate */ 18907c478bd9Sstevel@tonic-gate cclp = (client_t *)kmem_zalloc(sizeof (client_t), KM_SLEEP); 18917c478bd9Sstevel@tonic-gate 18927c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 18937c478bd9Sstevel@tonic-gate if (!(*ch = cs_create_client_handle(sn, cclp))) { 18947c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 18957c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 18967c478bd9Sstevel@tonic-gate kmem_free(cclp, sizeof (client_t)); 18977c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate /* 19017c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. We should never 19027c478bd9Sstevel@tonic-gate * fail this since we just got a valid client handle. 19037c478bd9Sstevel@tonic-gate * If this fails, then we have an internal error so don't bother 19047c478bd9Sstevel@tonic-gate * trying to clean up the allocated client handle since the 19057c478bd9Sstevel@tonic-gate * whole system is probably hosed anyway and will shortly 19067c478bd9Sstevel@tonic-gate * esplode. 19077c478bd9Sstevel@tonic-gate * It doesn't make sense to call cs_deregister_client at this point 19087c478bd9Sstevel@tonic-gate * to clean up this broken client since the deregistration 19097c478bd9Sstevel@tonic-gate * code will also call cs_find_client and most likely fail. 19107c478bd9Sstevel@tonic-gate */ 19117c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(*ch, &error))) { 19127c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 19137c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 19147c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_client_to_socket: socket %d function 0x%x " 19157c478bd9Sstevel@tonic-gate "invalid client handle created handle 0x%x\n", 19167c478bd9Sstevel@tonic-gate (int)CS_GET_SOCKET_NUMBER(sn), 19177c478bd9Sstevel@tonic-gate (int)CS_GET_FUNCTION_NUMBER(sn), 19187c478bd9Sstevel@tonic-gate (int)*ch); 19197c478bd9Sstevel@tonic-gate return (error); 19207c478bd9Sstevel@tonic-gate } 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate /* 19237c478bd9Sstevel@tonic-gate * Save the DDI information. 19247c478bd9Sstevel@tonic-gate */ 19257c478bd9Sstevel@tonic-gate client->dip = cr->dip; 19267c478bd9Sstevel@tonic-gate cr->driver_name[MODMAXNAMELEN - 1] = NULL; 19277c478bd9Sstevel@tonic-gate client->driver_name = (char *)kmem_zalloc(strlen(cr->driver_name) + 1, 19287c478bd9Sstevel@tonic-gate KM_SLEEP); 19297c478bd9Sstevel@tonic-gate (void) strcpy(client->driver_name, cr->driver_name); 19307c478bd9Sstevel@tonic-gate client->instance = ddi_get_instance(cr->dip); 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* 19337c478bd9Sstevel@tonic-gate * Copy over the interesting items that the client gave us. 19347c478bd9Sstevel@tonic-gate */ 19357c478bd9Sstevel@tonic-gate client->flags = (cr->Attributes & INFO_CLIENT_TYPE_MASK); 19367c478bd9Sstevel@tonic-gate client->event_callback_handler = cr->event_handler; 19377c478bd9Sstevel@tonic-gate bcopy((caddr_t)&cr->event_callback_args, 19387c478bd9Sstevel@tonic-gate (caddr_t)&client->event_callback_args, 19397c478bd9Sstevel@tonic-gate sizeof (event_callback_args_t)); 19407c478bd9Sstevel@tonic-gate /* 19417c478bd9Sstevel@tonic-gate * Set the client handle since the client needs a client handle 19427c478bd9Sstevel@tonic-gate * when they call us for their event handler. 19437c478bd9Sstevel@tonic-gate */ 19447c478bd9Sstevel@tonic-gate client->event_callback_args.client_handle = *ch; 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate /* 19477c478bd9Sstevel@tonic-gate * Initialize the IO window numbers; if an IO window number is equal 19487c478bd9Sstevel@tonic-gate * to PCMCIA_MAX_WINDOWS it means that IO range is not in use. 19497c478bd9Sstevel@tonic-gate */ 19507c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = PCMCIA_MAX_WINDOWS; 19517c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate /* 19547c478bd9Sstevel@tonic-gate * Give the client the iblock and idevice cookies to use in 19557c478bd9Sstevel@tonic-gate * the client's event handler high priority mutex. 19567c478bd9Sstevel@tonic-gate */ 19577c478bd9Sstevel@tonic-gate cr->iblk_cookie = sp->iblk; 19587c478bd9Sstevel@tonic-gate cr->idev_cookie = sp->idev; 19597c478bd9Sstevel@tonic-gate 19607c478bd9Sstevel@tonic-gate /* 19617c478bd9Sstevel@tonic-gate * Set up the global event mask information; we copy this directly 19627c478bd9Sstevel@tonic-gate * from the client; since we are the only source of events, 19637c478bd9Sstevel@tonic-gate * any bogus bits that the client puts in here won't matter 19647c478bd9Sstevel@tonic-gate * because we'll never look at them. 19657c478bd9Sstevel@tonic-gate */ 19667c478bd9Sstevel@tonic-gate client->global_mask = cr->EventMask; 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate /* 19697c478bd9Sstevel@tonic-gate * If this client registered as a CSI client, set the appropriate 19707c478bd9Sstevel@tonic-gate * flag in the client's flags area. 19717c478bd9Sstevel@tonic-gate */ 19727c478bd9Sstevel@tonic-gate if (cr->Attributes & INFO_CSI_CLIENT) 19737c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CSI_CLIENT; 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate /* 19767c478bd9Sstevel@tonic-gate * If this client registered as a "super-client" set the appropriate 19777c478bd9Sstevel@tonic-gate * flag in the client's flags area. 19787c478bd9Sstevel@tonic-gate */ 19797c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) 19807c478bd9Sstevel@tonic-gate client->flags |= CLIENT_SUPER_CLIENT; 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate /* 19837c478bd9Sstevel@tonic-gate * Save other misc information that this client gave us - it is 19847c478bd9Sstevel@tonic-gate * used in the GetClientInfo function. 19857c478bd9Sstevel@tonic-gate */ 19867c478bd9Sstevel@tonic-gate client->flags |= (cr->Attributes & INFO_CARD_FLAGS_MASK); 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate /* 19897c478bd9Sstevel@tonic-gate * Determine if we should give artificial card insertion events and 19907c478bd9Sstevel@tonic-gate * a registration complete event. Since we don't differentiate 19917c478bd9Sstevel@tonic-gate * between sharable and exclusive use cards when giving clients 19927c478bd9Sstevel@tonic-gate * event notification, we modify the definition of the share/excl 19937c478bd9Sstevel@tonic-gate * flags as follows: 19947c478bd9Sstevel@tonic-gate * 19957c478bd9Sstevel@tonic-gate * If either INFO_CARD_SHARE or INFO_CARD_EXCL is set, 19967c478bd9Sstevel@tonic-gate * the client will receive artificial card insertion 19977c478bd9Sstevel@tonic-gate * events (if the client's card is currently in the 19987c478bd9Sstevel@tonic-gate * socket) and a registration complete event. 19997c478bd9Sstevel@tonic-gate * 20007c478bd9Sstevel@tonic-gate * If neither of the INFO_CARD_SHARE or INFO_CARD_EXCL is 20017c478bd9Sstevel@tonic-gate * set, the client will not receive an artificial card 20027c478bd9Sstevel@tonic-gate * insertion event nor a registration complete event 20037c478bd9Sstevel@tonic-gate * due to the client's call to register client. 20047c478bd9Sstevel@tonic-gate * 20057c478bd9Sstevel@tonic-gate * The client's event mask is not affected by the setting 20067c478bd9Sstevel@tonic-gate * of these two bits. 20077c478bd9Sstevel@tonic-gate */ 20087c478bd9Sstevel@tonic-gate if (cr->Attributes & (INFO_CARD_SHARE | INFO_CARD_EXCL)) 20097c478bd9Sstevel@tonic-gate client->pending_events = CS_EVENT_REGISTRATION_COMPLETE; 20107c478bd9Sstevel@tonic-gate 20117c478bd9Sstevel@tonic-gate /* 20127c478bd9Sstevel@tonic-gate * Check to see if the card for this client is currently in 20137c478bd9Sstevel@tonic-gate * the socket. If it is, then set CLIENT_CARD_INSERTED 20147c478bd9Sstevel@tonic-gate * since clients that are calling GetStatus at attach 20157c478bd9Sstevel@tonic-gate * time will typically check to see if their card is 20167c478bd9Sstevel@tonic-gate * currently installed. 20177c478bd9Sstevel@tonic-gate * If this is the CSI client, we also need to check to see 20187c478bd9Sstevel@tonic-gate * if there is any card inserted in the socket, since 20197c478bd9Sstevel@tonic-gate * the cs_card_for_client function will always return 20207c478bd9Sstevel@tonic-gate * TRUE for a CSI client. 20217c478bd9Sstevel@tonic-gate * XXX What about super-clients? 20227c478bd9Sstevel@tonic-gate */ 20237c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) { 20247c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate get_ss_status.socket = sp->socket_num; 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, &get_ss_status) != SUCCESS) { 20297c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 20307c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20317c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 20327c478bd9Sstevel@tonic-gate } /* SS_GetStatus */ 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate if (!(cs_sbm2cse(get_ss_status.CardState) & 20357c478bd9Sstevel@tonic-gate CS_EVENT_CARD_INSERTION)) 20367c478bd9Sstevel@tonic-gate cie = 0; 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate } /* CLIENT_CSI_CLIENT */ 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate if (cs_card_for_client(client) && (cie != 0)) { 20417c478bd9Sstevel@tonic-gate client->pending_events |= CS_EVENT_CARD_INSERTION; 20427c478bd9Sstevel@tonic-gate client->flags |= CLIENT_CARD_INSERTED; 20437c478bd9Sstevel@tonic-gate } /* cs_card_for_client */ 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate sp->num_clients++; 20467c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 20477c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20487c478bd9Sstevel@tonic-gate 20497c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 20507c478bd9Sstevel@tonic-gate } 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate /* 20537c478bd9Sstevel@tonic-gate * cs_deregister_client - This supports the DeregisterClient call. 20547c478bd9Sstevel@tonic-gate */ 20557c478bd9Sstevel@tonic-gate static int 20567c478bd9Sstevel@tonic-gate cs_deregister_client(client_handle_t client_handle) 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate cs_socket_t *sp; 20597c478bd9Sstevel@tonic-gate client_t *client; 20607c478bd9Sstevel@tonic-gate int error, super_client = 0; 20617c478bd9Sstevel@tonic-gate int client_lock_acquired; 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate /* 20647c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 20657c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 20667c478bd9Sstevel@tonic-gate */ 20677c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 20687c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate /* 20717c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 20727c478bd9Sstevel@tonic-gate */ 20737c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 20747c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate /* 20797c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 20807c478bd9Sstevel@tonic-gate */ 20817c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 20827c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20837c478bd9Sstevel@tonic-gate return (error); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate /* 20877c478bd9Sstevel@tonic-gate * Make sure that any resources allocated by this client are 20887c478bd9Sstevel@tonic-gate * not still allocated, and that if this is an MTD that 20897c478bd9Sstevel@tonic-gate * no MTD operations are still in progress. 20907c478bd9Sstevel@tonic-gate */ 20917c478bd9Sstevel@tonic-gate if (client->flags & (CLIENT_IO_ALLOCATED | 20927c478bd9Sstevel@tonic-gate CLIENT_IRQ_ALLOCATED | 20937c478bd9Sstevel@tonic-gate CLIENT_WIN_ALLOCATED | 20947c478bd9Sstevel@tonic-gate REQ_CONFIGURATION_DONE | 20957c478bd9Sstevel@tonic-gate REQ_SOCKET_MASK_DONE | 20967c478bd9Sstevel@tonic-gate REQ_IO_DONE | 20977c478bd9Sstevel@tonic-gate REQ_IRQ_DONE)) { 20987c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 20997c478bd9Sstevel@tonic-gate return (CS_BUSY); 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_MTD_IN_PROGRESS) { 21037c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 21047c478bd9Sstevel@tonic-gate return (CS_IN_USE); 21057c478bd9Sstevel@tonic-gate } 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate /* 21087c478bd9Sstevel@tonic-gate * Any previously allocated resources are not allocated anymore, and 21097c478bd9Sstevel@tonic-gate * no MTD operations are in progress, so if this is an MTD client 21107c478bd9Sstevel@tonic-gate * then do any MTD-specific client deregistration, and then 21117c478bd9Sstevel@tonic-gate * nuke this client. 21127c478bd9Sstevel@tonic-gate * We expect cs_deregister_mtd to never fail. 21137c478bd9Sstevel@tonic-gate */ 21147c478bd9Sstevel@tonic-gate if (client->flags & INFO_MTD_CLIENT) 21157c478bd9Sstevel@tonic-gate (void) cs_deregister_mtd(client_handle); 21167c478bd9Sstevel@tonic-gate 21177c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_SUPER_CLIENT) 21187c478bd9Sstevel@tonic-gate super_client = CLIENT_SUPER_CLIENT; 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate kmem_free(client->driver_name, strlen(client->driver_name) + 1); 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate error = cs_destroy_client_handle(client_handle); 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 21257c478bd9Sstevel@tonic-gate 21267c478bd9Sstevel@tonic-gate /* 21277c478bd9Sstevel@tonic-gate * If this was the "super-client" deregistering, then this 21287c478bd9Sstevel@tonic-gate * will clear the global "super-client" lock. 21297c478bd9Sstevel@tonic-gate * XXX - move this outside the per-socket code. 21307c478bd9Sstevel@tonic-gate */ 21317c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(super_client); 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate return (error); 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate /* 21377c478bd9Sstevel@tonic-gate * cs_create_next_client_minor - returns the next available client minor 21387c478bd9Sstevel@tonic-gate * number or 0 if none available 21397c478bd9Sstevel@tonic-gate * 21407c478bd9Sstevel@tonic-gate * Note that cs_find_client will always return a valid pointer to the 21417c478bd9Sstevel@tonic-gate * global Socket Services client which has a client minor number 21427c478bd9Sstevel@tonic-gate * of 0; this means that this function can never return a 0 as the 21437c478bd9Sstevel@tonic-gate * next valid available client minor number. 21447c478bd9Sstevel@tonic-gate */ 21457c478bd9Sstevel@tonic-gate unsigned 21467c478bd9Sstevel@tonic-gate cs_create_next_client_minor(unsigned socket_num, unsigned next_minor) 21477c478bd9Sstevel@tonic-gate { 21487c478bd9Sstevel@tonic-gate unsigned max_client_handles = cs_max_client_handles; 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate do { 21517c478bd9Sstevel@tonic-gate next_minor &= CS_MAX_CLIENTS_MASK; 21527c478bd9Sstevel@tonic-gate if (!cs_find_client(MAKE_CLIENT_HANDLE( 21537c478bd9Sstevel@tonic-gate CS_GET_SOCKET_NUMBER(socket_num), 21547c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 21557c478bd9Sstevel@tonic-gate next_minor), NULL)) { 21567c478bd9Sstevel@tonic-gate return (next_minor); 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate next_minor++; 21597c478bd9Sstevel@tonic-gate } while (max_client_handles--); 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate return (0); 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate /* 21657c478bd9Sstevel@tonic-gate * cs_find_client - finds the client pointer associated with the client handle 21667c478bd9Sstevel@tonic-gate * or NULL if client not found 21677c478bd9Sstevel@tonic-gate * 21687c478bd9Sstevel@tonic-gate * returns: (client_t *)NULL - if client not found or an error occured 21697c478bd9Sstevel@tonic-gate * If the error argument is not NULL, 21707c478bd9Sstevel@tonic-gate * it is set to: 21717c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - socket number in client_handle_t is 21727c478bd9Sstevel@tonic-gate * invalid 21737c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client not found 21747c478bd9Sstevel@tonic-gate * If no error, the error argument is not modified. 21757c478bd9Sstevel@tonic-gate * (client_t *) - pointer to client_t structure 21767c478bd9Sstevel@tonic-gate * 21777c478bd9Sstevel@tonic-gate * Note that each socket always has a pseudo client with a client minor number 21787c478bd9Sstevel@tonic-gate * of 0; this client minor number is used for Socket Services access to 21797c478bd9Sstevel@tonic-gate * Card Services functions. The client pointer returned for client minor 21807c478bd9Sstevel@tonic-gate * number 0 is the global Socket Services client pointer. 21817c478bd9Sstevel@tonic-gate */ 21827c478bd9Sstevel@tonic-gate static client_t * 21837c478bd9Sstevel@tonic-gate cs_find_client(client_handle_t client_handle, int *error) 21847c478bd9Sstevel@tonic-gate { 21857c478bd9Sstevel@tonic-gate cs_socket_t *sp; 21867c478bd9Sstevel@tonic-gate client_t *clp; 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate /* 21897c478bd9Sstevel@tonic-gate * If we are being asked to see if a client with a minor number 21907c478bd9Sstevel@tonic-gate * of 0 exists, always return a pointer to the global Socket 21917c478bd9Sstevel@tonic-gate * Services client, since this client always exists, and is 21927c478bd9Sstevel@tonic-gate * only for use by Socket Services. There is no socket 21937c478bd9Sstevel@tonic-gate * associated with this special client handle. 21947c478bd9Sstevel@tonic-gate */ 21957c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 21967c478bd9Sstevel@tonic-gate return (&cs_socket_services_client); 21977c478bd9Sstevel@tonic-gate 21987c478bd9Sstevel@tonic-gate /* 21997c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 22007c478bd9Sstevel@tonic-gate */ 22017c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(GET_CLIENT_SOCKET(client_handle), 22027c478bd9Sstevel@tonic-gate cs_globals.max_socket_num))) { 22037c478bd9Sstevel@tonic-gate if (error) 22047c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 22057c478bd9Sstevel@tonic-gate return (NULL); 22067c478bd9Sstevel@tonic-gate } 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) { 22097c478bd9Sstevel@tonic-gate if (error) 22107c478bd9Sstevel@tonic-gate *error = CS_BAD_SOCKET; 22117c478bd9Sstevel@tonic-gate return (NULL); 22127c478bd9Sstevel@tonic-gate } 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate clp = sp->client_list; 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate while (clp) { 22177c478bd9Sstevel@tonic-gate if (clp->client_handle == client_handle) 22187c478bd9Sstevel@tonic-gate return (clp); 22197c478bd9Sstevel@tonic-gate clp = clp->next; 22207c478bd9Sstevel@tonic-gate } 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate if (error) 22237c478bd9Sstevel@tonic-gate *error = CS_BAD_HANDLE; 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate return (NULL); 22267c478bd9Sstevel@tonic-gate } 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate /* 22297c478bd9Sstevel@tonic-gate * cs_destroy_client_handle - destroys client handle and client structure of 22307c478bd9Sstevel@tonic-gate * passed client handle 22317c478bd9Sstevel@tonic-gate * 22327c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client handle sucessfully destroyed 22337c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client handle is invalid or if trying 22347c478bd9Sstevel@tonic-gate * to destroy global SS client 22357c478bd9Sstevel@tonic-gate * {other errors} - other errors from cs_find_client() 22367c478bd9Sstevel@tonic-gate */ 22377c478bd9Sstevel@tonic-gate static int 22387c478bd9Sstevel@tonic-gate cs_destroy_client_handle(client_handle_t client_handle) 22397c478bd9Sstevel@tonic-gate { 22407c478bd9Sstevel@tonic-gate client_t *clp; 22417c478bd9Sstevel@tonic-gate cs_socket_t *sp; 22427c478bd9Sstevel@tonic-gate int error = CS_BAD_HANDLE; 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate /* 22457c478bd9Sstevel@tonic-gate * See if we were passed a valid client handle or if we're being asked 22467c478bd9Sstevel@tonic-gate * to destroy the Socket Services client 22477c478bd9Sstevel@tonic-gate */ 22487c478bd9Sstevel@tonic-gate if ((!(clp = cs_find_client(client_handle, &error))) || 22497c478bd9Sstevel@tonic-gate (CLIENT_HANDLE_IS_SS(client_handle))) 22507c478bd9Sstevel@tonic-gate return (error); 22517c478bd9Sstevel@tonic-gate 22527c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 22537c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate /* 22567c478bd9Sstevel@tonic-gate * Recycle this client's minor number. This will most likely 22577c478bd9Sstevel@tonic-gate * be the next client minor number we use, but it is also 22587c478bd9Sstevel@tonic-gate * a hint to cs_create_client_handle, and that function 22597c478bd9Sstevel@tonic-gate * may actually create a new client handle using a minor 22607c478bd9Sstevel@tonic-gate * number different that this number. 22617c478bd9Sstevel@tonic-gate */ 22627c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 22637c478bd9Sstevel@tonic-gate sp->next_cl_minor = GET_CLIENT_MINOR(client_handle); 22647c478bd9Sstevel@tonic-gate 22657c478bd9Sstevel@tonic-gate /* 22667c478bd9Sstevel@tonic-gate * See if we're the first or not in the client list; if we're 22677c478bd9Sstevel@tonic-gate * not first, then just adjust the client behind us to 22687c478bd9Sstevel@tonic-gate * point to the client ahead of us; this could be NULL 22697c478bd9Sstevel@tonic-gate * if we're the last client in the list. 22707c478bd9Sstevel@tonic-gate */ 22717c478bd9Sstevel@tonic-gate if (clp->prev) { 22727c478bd9Sstevel@tonic-gate clp->prev->next = clp->next; 22737c478bd9Sstevel@tonic-gate } else { 22747c478bd9Sstevel@tonic-gate /* 22757c478bd9Sstevel@tonic-gate * We are first, so adjust the client list head pointer 22767c478bd9Sstevel@tonic-gate * in the socket to point to the client structure that 22777c478bd9Sstevel@tonic-gate * follows us; this could turn out to be NULL if we're 22787c478bd9Sstevel@tonic-gate * the only client on this socket. 22797c478bd9Sstevel@tonic-gate */ 22807c478bd9Sstevel@tonic-gate sp->client_list = clp->next; 22817c478bd9Sstevel@tonic-gate } 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate /* 22847c478bd9Sstevel@tonic-gate * If we're not the last client in the list, point the next 22857c478bd9Sstevel@tonic-gate * client to the client behind us; this could turn out 22867c478bd9Sstevel@tonic-gate * to be NULL if we're the first client on this socket. 22877c478bd9Sstevel@tonic-gate */ 22887c478bd9Sstevel@tonic-gate if (clp->next) 22897c478bd9Sstevel@tonic-gate clp->next->prev = clp->prev; 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate sp->num_clients--; 22927c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 22937c478bd9Sstevel@tonic-gate 22947c478bd9Sstevel@tonic-gate /* 22957c478bd9Sstevel@tonic-gate * Free this client's memory. 22967c478bd9Sstevel@tonic-gate */ 22977c478bd9Sstevel@tonic-gate kmem_free(clp, sizeof (client_t)); 22987c478bd9Sstevel@tonic-gate 22997c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 23007c478bd9Sstevel@tonic-gate } 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate /* 23037c478bd9Sstevel@tonic-gate * cs_create_client_handle - create a new client handle for the passed 23047c478bd9Sstevel@tonic-gate * socket and function number 23057c478bd9Sstevel@tonic-gate * 23067c478bd9Sstevel@tonic-gate * returns: 0 - if can't create client for some reason 23077c478bd9Sstevel@tonic-gate * client_handle_t - new client handle 23087c478bd9Sstevel@tonic-gate */ 23097c478bd9Sstevel@tonic-gate static client_handle_t 23107c478bd9Sstevel@tonic-gate cs_create_client_handle(unsigned socket_num, client_t *cclp) 23117c478bd9Sstevel@tonic-gate { 23127c478bd9Sstevel@tonic-gate client_t *clp; 23137c478bd9Sstevel@tonic-gate cs_socket_t *sp; 23147c478bd9Sstevel@tonic-gate unsigned next_minor; 23157c478bd9Sstevel@tonic-gate client_handle_t client_handle; 23167c478bd9Sstevel@tonic-gate 23177c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(socket_num)) == NULL) 23187c478bd9Sstevel@tonic-gate return (0); 23197c478bd9Sstevel@tonic-gate 23207c478bd9Sstevel@tonic-gate /* 23217c478bd9Sstevel@tonic-gate * Get the next available minor number that we can use. We use the 23227c478bd9Sstevel@tonic-gate * next_cl_minor number as a hint to cs_create_next_client_minor 23237c478bd9Sstevel@tonic-gate * and in most cases this will be the minor number we get back. 23247c478bd9Sstevel@tonic-gate * If for some reason we can't get a minor number, return an error. 23257c478bd9Sstevel@tonic-gate * The only way we could get an error would be if there are 23267c478bd9Sstevel@tonic-gate * already the maximum number of clients for this socket. Since 23277c478bd9Sstevel@tonic-gate * the maximum number of clients per socket is pretty large, 23287c478bd9Sstevel@tonic-gate * this error is unlikely to occur. 23297c478bd9Sstevel@tonic-gate */ 23307c478bd9Sstevel@tonic-gate if (!(next_minor = 23317c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor))) 23327c478bd9Sstevel@tonic-gate return (0); 23337c478bd9Sstevel@tonic-gate 23347c478bd9Sstevel@tonic-gate /* 23357c478bd9Sstevel@tonic-gate * Got a new client minor number, now create a new client handle. 23367c478bd9Sstevel@tonic-gate */ 23377c478bd9Sstevel@tonic-gate client_handle = MAKE_CLIENT_HANDLE(CS_GET_SOCKET_NUMBER(socket_num), 23387c478bd9Sstevel@tonic-gate CS_GET_FUNCTION_NUMBER(socket_num), 23397c478bd9Sstevel@tonic-gate next_minor); 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate /* 23427c478bd9Sstevel@tonic-gate * If this client handle exists, then we have an internal 23437c478bd9Sstevel@tonic-gate * error; this should never happen, BTW. This is really 23447c478bd9Sstevel@tonic-gate * a double-check on the cs_create_next_client_minor 23457c478bd9Sstevel@tonic-gate * function, which also calls cs_find_client. 23467c478bd9Sstevel@tonic-gate */ 23477c478bd9Sstevel@tonic-gate if (cs_find_client(client_handle, NULL)) { 23487c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 23497c478bd9Sstevel@tonic-gate "cs_create_client_handle: duplicate client handle 0x%x\n", 23507c478bd9Sstevel@tonic-gate (int)client_handle); 23517c478bd9Sstevel@tonic-gate return (0); 23527c478bd9Sstevel@tonic-gate } 23537c478bd9Sstevel@tonic-gate 23547c478bd9Sstevel@tonic-gate /* 23557c478bd9Sstevel@tonic-gate * If we don't have any clients on this socket yet, create 23567c478bd9Sstevel@tonic-gate * a new client and hang it on the socket client list. 23577c478bd9Sstevel@tonic-gate */ 23587c478bd9Sstevel@tonic-gate if (!sp->client_list) { 23597c478bd9Sstevel@tonic-gate sp->client_list = cclp; 23607c478bd9Sstevel@tonic-gate clp = sp->client_list; 23617c478bd9Sstevel@tonic-gate } else { 23627c478bd9Sstevel@tonic-gate /* 23637c478bd9Sstevel@tonic-gate * There are other clients on this socket, so look for 23647c478bd9Sstevel@tonic-gate * the last client and add our new client after it. 23657c478bd9Sstevel@tonic-gate */ 23667c478bd9Sstevel@tonic-gate clp = sp->client_list; 23677c478bd9Sstevel@tonic-gate while (clp->next) { 23687c478bd9Sstevel@tonic-gate clp = clp->next; 23697c478bd9Sstevel@tonic-gate } 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate clp->next = cclp; 23727c478bd9Sstevel@tonic-gate clp->next->prev = clp; 23737c478bd9Sstevel@tonic-gate clp = clp->next; 23747c478bd9Sstevel@tonic-gate } /* if (!sp->client_list) */ 23757c478bd9Sstevel@tonic-gate 23767c478bd9Sstevel@tonic-gate /* 23777c478bd9Sstevel@tonic-gate * Assign the new client handle to this new client structure. 23787c478bd9Sstevel@tonic-gate */ 23797c478bd9Sstevel@tonic-gate clp->client_handle = client_handle; 23807c478bd9Sstevel@tonic-gate 23817c478bd9Sstevel@tonic-gate /* 23827c478bd9Sstevel@tonic-gate * Create the next available client minor number for this socket 23837c478bd9Sstevel@tonic-gate * and save it away. 23847c478bd9Sstevel@tonic-gate */ 23857c478bd9Sstevel@tonic-gate sp->next_cl_minor = 23867c478bd9Sstevel@tonic-gate cs_create_next_client_minor(socket_num, sp->next_cl_minor); 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate return (client_handle); 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate /* 23927c478bd9Sstevel@tonic-gate * cs_clear_superclient_lock - clears the global "super-client" lock 23937c478bd9Sstevel@tonic-gate * 23947c478bd9Sstevel@tonic-gate * Note: this function uses the cs_globals.global_lock so observe proper 23957c478bd9Sstevel@tonic-gate * nexting of locks!! 23967c478bd9Sstevel@tonic-gate */ 23977c478bd9Sstevel@tonic-gate static void 23987c478bd9Sstevel@tonic-gate cs_clear_superclient_lock(int super_client) 23997c478bd9Sstevel@tonic-gate { 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate /* 24027c478bd9Sstevel@tonic-gate * If this was a "super-client" registering then we need 24037c478bd9Sstevel@tonic-gate * to clear the GLOBAL_SUPER_CLIENT_REGISTERED flag 24047c478bd9Sstevel@tonic-gate * so that other "super-clients" can register. 24057c478bd9Sstevel@tonic-gate */ 24067c478bd9Sstevel@tonic-gate if (super_client == CLIENT_SUPER_CLIENT) { 24077c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 24087c478bd9Sstevel@tonic-gate cs_globals.flags &= ~GLOBAL_SUPER_CLIENT_REGISTERED; 24097c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 24107c478bd9Sstevel@tonic-gate } 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate /* 24147c478bd9Sstevel@tonic-gate * ==== event handling section ==== 24157c478bd9Sstevel@tonic-gate */ 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate /* 24187c478bd9Sstevel@tonic-gate * cs_event - CS event hi-priority callback handler 24197c478bd9Sstevel@tonic-gate * 24207c478bd9Sstevel@tonic-gate * This function gets called by SS and is passed the event type in 24217c478bd9Sstevel@tonic-gate * the "event" argument, and the socket number in the "sn" 24227c478bd9Sstevel@tonic-gate * argument. The "sn" argument is a valid logical socket 24237c478bd9Sstevel@tonic-gate * number for all events except the PCE_SS_READY event. 24247c478bd9Sstevel@tonic-gate * 24257c478bd9Sstevel@tonic-gate * The PCE_SS_INIT_STATE, PCE_ADD_SOCKET and PCE_DROP_SOCKET events 24267c478bd9Sstevel@tonic-gate * are never called at high priority. These events return 24277c478bd9Sstevel@tonic-gate * the following return codes: 24287c478bd9Sstevel@tonic-gate * 24297c478bd9Sstevel@tonic-gate * CS_SUCCESS - operation sucessful 24307c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to complete operation 24317c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - bad subfunction of 24327c478bd9Sstevel@tonic-gate * PCE_SS_INIT_STATE 24337c478bd9Sstevel@tonic-gate * 24347c478bd9Sstevel@tonic-gate * The caller MUST look at these return codes! 24357c478bd9Sstevel@tonic-gate * 24367c478bd9Sstevel@tonic-gate * This function is called at high-priority interrupt time for standard 24377c478bd9Sstevel@tonic-gate * Card Services events, and the only standard Card Services 24387c478bd9Sstevel@tonic-gate * event that it handles directly is the CS_EVENT_CARD_REMOVAL 24397c478bd9Sstevel@tonic-gate * event, which gets shuttled right into the client's event 24407c478bd9Sstevel@tonic-gate * handler. All other events are just queued up and the socket 24417c478bd9Sstevel@tonic-gate * event thread is woken up via the soft interrupt handler. 24427c478bd9Sstevel@tonic-gate * Note that CS_EVENT_CARD_INSERTION events are not set in the clients' 24437c478bd9Sstevel@tonic-gate * event field, since the CS card insertion/card ready processing 24447c478bd9Sstevel@tonic-gate * code is responsible for setting this event in a client's 24457c478bd9Sstevel@tonic-gate * event field. 24467c478bd9Sstevel@tonic-gate * 24477c478bd9Sstevel@tonic-gate */ 24487c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 24497c478bd9Sstevel@tonic-gate uint32_t 24507c478bd9Sstevel@tonic-gate cs_event(event_t event, uint32_t sn, uint32_t arg) 24517c478bd9Sstevel@tonic-gate { 24527c478bd9Sstevel@tonic-gate client_t *client; 24537c478bd9Sstevel@tonic-gate cs_socket_t *sp; 24547c478bd9Sstevel@tonic-gate client_types_t *ct; 24557c478bd9Sstevel@tonic-gate uint32_t ret = CS_SUCCESS; 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate /* 24587c478bd9Sstevel@tonic-gate * Handle special SS<->CS events 24597c478bd9Sstevel@tonic-gate */ 24607c478bd9Sstevel@tonic-gate switch (event) { 24617c478bd9Sstevel@tonic-gate case PCE_SS_INIT_STATE: 24627c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 24637c478bd9Sstevel@tonic-gate switch (sn) { 24647c478bd9Sstevel@tonic-gate case PCE_SS_STATE_INIT: 24657c478bd9Sstevel@tonic-gate if ((ret = cs_ss_init()) == CS_SUCCESS) 24667c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SS_READY; 24677c478bd9Sstevel@tonic-gate break; 24687c478bd9Sstevel@tonic-gate case PCE_SS_STATE_DEINIT: 24697c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_INIT_STATE_SS_READY; 24707c478bd9Sstevel@tonic-gate break; 24717c478bd9Sstevel@tonic-gate default: 24727c478bd9Sstevel@tonic-gate ret = CS_UNSUPPORTED_FUNCTION; 24737c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: PCE_SS_INIT_STATE invalid " 24747c478bd9Sstevel@tonic-gate "directive: 0x%x\n", sn); 24757c478bd9Sstevel@tonic-gate break; 24767c478bd9Sstevel@tonic-gate } /* switch (sn) */ 24777c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 24787c478bd9Sstevel@tonic-gate return (ret); 24797c478bd9Sstevel@tonic-gate case PCE_ADD_SOCKET: 24807c478bd9Sstevel@tonic-gate return (cs_add_socket(sn)); 24817c478bd9Sstevel@tonic-gate case PCE_DROP_SOCKET: 24827c478bd9Sstevel@tonic-gate return (cs_drop_socket(sn)); 24837c478bd9Sstevel@tonic-gate } /* switch (event) */ 24847c478bd9Sstevel@tonic-gate 24857c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 24867c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate /* 24897c478bd9Sstevel@tonic-gate * Check to see if CS wants to unload - we do this since it's possible 24907c478bd9Sstevel@tonic-gate * to disable certain sockets. Do NOT acquire any locks yet. 24917c478bd9Sstevel@tonic-gate */ 24927c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_UNLOAD_MODULE) { 24937c478bd9Sstevel@tonic-gate if (event == PCE_CARD_INSERT) 24947c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PCMCIA: socket %d disabled - please " 24957c478bd9Sstevel@tonic-gate "remove card\n", sn); 24967c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 24977c478bd9Sstevel@tonic-gate } 24987c478bd9Sstevel@tonic-gate 24997c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 25027c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 25037c478bd9Sstevel@tonic-gate event2text_t event2text; 25047c478bd9Sstevel@tonic-gate 25057c478bd9Sstevel@tonic-gate event2text.event = event; 25067c478bd9Sstevel@tonic-gate (void) cs_event2text(&event2text, 0); 25077c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: event=%s (x%x), socket=0x%x\n", 25087c478bd9Sstevel@tonic-gate event2text.text, (int)event, (int)sn); 25097c478bd9Sstevel@tonic-gate } 25107c478bd9Sstevel@tonic-gate #endif 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate /* 25137c478bd9Sstevel@tonic-gate * Convert SS events to CS events; handle the PRR if necessary. 25147c478bd9Sstevel@tonic-gate */ 25157c478bd9Sstevel@tonic-gate sp->events |= ss_to_cs_events(sp, event); 25167c478bd9Sstevel@tonic-gate 25177c478bd9Sstevel@tonic-gate /* 25187c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 25197c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 25207c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 25217c478bd9Sstevel@tonic-gate * notified in the correct order of any high-priority 25227c478bd9Sstevel@tonic-gate * events. 25237c478bd9Sstevel@tonic-gate */ 25247c478bd9Sstevel@tonic-gate ct = &client_types[0]; 25257c478bd9Sstevel@tonic-gate while (ct) { 25267c478bd9Sstevel@tonic-gate /* 25277c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 25287c478bd9Sstevel@tonic-gate * through each client to set up the client events as well as 25297c478bd9Sstevel@tonic-gate * call the client's event handler directly if we have a high 25307c478bd9Sstevel@tonic-gate * priority event that we need to tell the client about. 25317c478bd9Sstevel@tonic-gate */ 25327c478bd9Sstevel@tonic-gate client = sp->client_list; 25337c478bd9Sstevel@tonic-gate 25347c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 25357c478bd9Sstevel@tonic-gate client_t *clp = NULL; 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate while (client) { 25387c478bd9Sstevel@tonic-gate clp = client; 25397c478bd9Sstevel@tonic-gate client = client->next; 25407c478bd9Sstevel@tonic-gate } 25417c478bd9Sstevel@tonic-gate client = clp; 25427c478bd9Sstevel@tonic-gate } 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate while (client) { 25457c478bd9Sstevel@tonic-gate client->events |= ((sp->events & ~CS_EVENT_CARD_INSERTION) & 25467c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 25477c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 25487c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 25497c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 25507c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event: socket %d client [%s] " 25517c478bd9Sstevel@tonic-gate "events 0x%x flags 0x%x\n", 25527c478bd9Sstevel@tonic-gate sn, client->driver_name, 25537c478bd9Sstevel@tonic-gate (int)client->events, 25547c478bd9Sstevel@tonic-gate (int)client->flags); 25557c478bd9Sstevel@tonic-gate } 25567c478bd9Sstevel@tonic-gate #endif 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate /* 25597c478bd9Sstevel@tonic-gate * Handle the suspend and card removal events 25607c478bd9Sstevel@tonic-gate * specially here so that the client can receive 25617c478bd9Sstevel@tonic-gate * these events at high-priority. 25627c478bd9Sstevel@tonic-gate */ 25637c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_PM_SUSPEND) { 25647c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 25657c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, CS_EVENT_PM_SUSPEND, 25667c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 25677c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 25687c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_PM_SUSPEND; 25697c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_PM_SUSPEND) */ 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate if (client->events & CS_EVENT_CARD_REMOVAL) { 25727c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 25737c478bd9Sstevel@tonic-gate client->flags &= ~(CLIENT_CARD_INSERTED | 25747c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 25757c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 25767c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 25777c478bd9Sstevel@tonic-gate CS_EVENT_PRI_HIGH); 25787c478bd9Sstevel@tonic-gate /* 25797c478bd9Sstevel@tonic-gate * Check to see if the client wants low priority 25807c478bd9Sstevel@tonic-gate * removal events as well. 25817c478bd9Sstevel@tonic-gate */ 25827c478bd9Sstevel@tonic-gate if ((client->event_mask | client->global_mask) & 25837c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL_LOWP) { 25847c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CARD_REMOVAL_LOWP; 25857c478bd9Sstevel@tonic-gate } 25867c478bd9Sstevel@tonic-gate } /* if (CLIENT_CARD_INSERTED) */ 25877c478bd9Sstevel@tonic-gate client->events &= ~CS_EVENT_CARD_REMOVAL; 25887c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 25917c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 25927c478bd9Sstevel@tonic-gate client = client->prev; 25937c478bd9Sstevel@tonic-gate } else { 25947c478bd9Sstevel@tonic-gate client = client->next; 25957c478bd9Sstevel@tonic-gate } 25967c478bd9Sstevel@tonic-gate } /* while (client) */ 25977c478bd9Sstevel@tonic-gate 25987c478bd9Sstevel@tonic-gate ct = ct->next; 25997c478bd9Sstevel@tonic-gate } /* while (ct) */ 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate /* 26027c478bd9Sstevel@tonic-gate * Set the SOCKET_NEEDS_THREAD flag so that the soft interrupt 26037c478bd9Sstevel@tonic-gate * handler will wakeup this socket's event thread. 26047c478bd9Sstevel@tonic-gate */ 26057c478bd9Sstevel@tonic-gate if (sp->events) 26067c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_NEEDS_THREAD; 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate /* 26097c478bd9Sstevel@tonic-gate * Fire off a soft interrupt that will cause the socket thread 26107c478bd9Sstevel@tonic-gate * to be woken up and any remaining events to be sent to 26117c478bd9Sstevel@tonic-gate * the clients on this socket. 26127c478bd9Sstevel@tonic-gate */ 26137c478bd9Sstevel@tonic-gate if ((sp->init_state & SOCKET_INIT_STATE_SOFTINTR) && 26147c478bd9Sstevel@tonic-gate !(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) 26157c478bd9Sstevel@tonic-gate ddi_trigger_softintr(sp->softint_id); 26167c478bd9Sstevel@tonic-gate 26177c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 26207c478bd9Sstevel@tonic-gate } 26217c478bd9Sstevel@tonic-gate 26227c478bd9Sstevel@tonic-gate /* 26237c478bd9Sstevel@tonic-gate * cs_card_insertion - handle card insertion and card ready events 26247c478bd9Sstevel@tonic-gate * 26257c478bd9Sstevel@tonic-gate * We read the CIS, if present, and store it away, then tell SS that 26267c478bd9Sstevel@tonic-gate * we have read the CIS and it's ready to be parsed. Since card 26277c478bd9Sstevel@tonic-gate * insertion and card ready events are pretty closely intertwined, 26287c478bd9Sstevel@tonic-gate * we handle both here. For card ready events that are not the 26297c478bd9Sstevel@tonic-gate * result of a card insertion event, we expect that the caller has 26307c478bd9Sstevel@tonic-gate * already done the appropriate processing and that we will not be 26317c478bd9Sstevel@tonic-gate * called unless we received a card ready event right after a card 26327c478bd9Sstevel@tonic-gate * insertion event, i.e. that the SOCKET_WAIT_FOR_READY flag in 26337c478bd9Sstevel@tonic-gate * sp->thread_state was set or if we get a CARD_READY event right 26347c478bd9Sstevel@tonic-gate * after a CARD_INSERTION event. 26357c478bd9Sstevel@tonic-gate * 26367c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 26377c478bd9Sstevel@tonic-gate * event - event to handle, one of: 26387c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_INSERTION 26397c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_READY 26407c478bd9Sstevel@tonic-gate * CS_EVENT_SS_UPDATED 26417c478bd9Sstevel@tonic-gate */ 26427c478bd9Sstevel@tonic-gate static int 26437c478bd9Sstevel@tonic-gate cs_card_insertion(cs_socket_t *sp, event_t event) 26447c478bd9Sstevel@tonic-gate { 26457c478bd9Sstevel@tonic-gate int ret; 26467c478bd9Sstevel@tonic-gate 26477c478bd9Sstevel@tonic-gate /* 26487c478bd9Sstevel@tonic-gate * Since we're only called while waiting for the card insertion 26497c478bd9Sstevel@tonic-gate * and card ready sequence to occur, we may have a pending 26507c478bd9Sstevel@tonic-gate * card ready timer that hasn't gone off yet if we got a 26517c478bd9Sstevel@tonic-gate * real card ready event. 26527c478bd9Sstevel@tonic-gate */ 26537c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 26547c478bd9Sstevel@tonic-gate 26557c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 26567c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 26577c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: event=0x%x, socket=0x%x\n", 26587c478bd9Sstevel@tonic-gate (int)event, sp->socket_num); 26597c478bd9Sstevel@tonic-gate } 26607c478bd9Sstevel@tonic-gate #endif 26617c478bd9Sstevel@tonic-gate 26627c478bd9Sstevel@tonic-gate /* 26637c478bd9Sstevel@tonic-gate * Handle card insertion processing 26647c478bd9Sstevel@tonic-gate */ 26657c478bd9Sstevel@tonic-gate if (event & CS_EVENT_CARD_INSERTION) { 26667c478bd9Sstevel@tonic-gate set_socket_t set_socket; 26677c478bd9Sstevel@tonic-gate get_ss_status_t gs; 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate /* 26707c478bd9Sstevel@tonic-gate * Check to be sure that we have a valid CIS window 26717c478bd9Sstevel@tonic-gate */ 26727c478bd9Sstevel@tonic-gate if (!SOCKET_HAS_CIS_WINDOW(sp)) { 26737c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 26747c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d has no " 26757c478bd9Sstevel@tonic-gate "CIS window\n", 26767c478bd9Sstevel@tonic-gate sp->socket_num); 26777c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 26787c478bd9Sstevel@tonic-gate } 26797c478bd9Sstevel@tonic-gate 26807c478bd9Sstevel@tonic-gate /* 26817c478bd9Sstevel@tonic-gate * Apply power to the socket, enable card detect and card ready 26827c478bd9Sstevel@tonic-gate * events, then reset the socket. 26837c478bd9Sstevel@tonic-gate */ 26847c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 26857c478bd9Sstevel@tonic-gate sp->event_mask = (CS_EVENT_CARD_REMOVAL | 26867c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY); 26877c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 26887c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 26897c478bd9Sstevel@tonic-gate set_socket.SCIntMask = (SBM_CD | SBM_RDYBSY); 26907c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 26917c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 26927c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 26937c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VCC, 26967c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 26977c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP1, 26987c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 26997c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 50, VPP2, 27007c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 27017c478bd9Sstevel@tonic-gate 27027c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 27037c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 27047c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failure %d\n", 27057c478bd9Sstevel@tonic-gate sp->socket_num, ret); 27067c478bd9Sstevel@tonic-gate return (ret); 27077c478bd9Sstevel@tonic-gate } 27087c478bd9Sstevel@tonic-gate 27097c478bd9Sstevel@tonic-gate /* 27107c478bd9Sstevel@tonic-gate * Clear the ready and ready_timeout events since they are now 27117c478bd9Sstevel@tonic-gate * bogus since we're about to reset the socket. 27127c478bd9Sstevel@tonic-gate * XXX - should these be cleared right after the RESET?? 27137c478bd9Sstevel@tonic-gate */ 27147c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 27177c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate SocketServices(SS_ResetSocket, sp->socket_num, 27207c478bd9Sstevel@tonic-gate RESET_MODE_CARD_ONLY); 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate /* 27237c478bd9Sstevel@tonic-gate * We are required by the PCMCIA spec to wait some number of 27247c478bd9Sstevel@tonic-gate * milliseconds after reset before we access the card, so 27257c478bd9Sstevel@tonic-gate * we set up a timer here that will wake us up and allow us 27267c478bd9Sstevel@tonic-gate * to continue with our card initialization. 27277c478bd9Sstevel@tonic-gate */ 27287c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27297c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_RESET_TIMER; 27307c478bd9Sstevel@tonic-gate (void) timeout(cs_ready_timeout, sp, 27317c478bd9Sstevel@tonic-gate drv_usectohz(cs_reset_timeout_time * 1000)); 27327c478bd9Sstevel@tonic-gate cv_wait(&sp->reset_cv, &sp->lock); 27337c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_RESET_TIMER; 27347c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27377c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 27387c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d out of RESET " 27397c478bd9Sstevel@tonic-gate "for %d mS sp->events 0x%x\n", 27407c478bd9Sstevel@tonic-gate sp->socket_num, cs_reset_timeout_time, (int)sp->events); 27417c478bd9Sstevel@tonic-gate } 27427c478bd9Sstevel@tonic-gate #endif 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate /* 27457c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 27467c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 27477c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 27487c478bd9Sstevel@tonic-gate */ 27497c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 27507c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27517c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 27527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d " 27537c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 27547c478bd9Sstevel@tonic-gate "terminating insertion " 27557c478bd9Sstevel@tonic-gate "processing\n", 27567c478bd9Sstevel@tonic-gate sp->socket_num); 27577c478bd9Sstevel@tonic-gate } 27587c478bd9Sstevel@tonic-gate #endif 27597c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 27607c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 27617c478bd9Sstevel@tonic-gate 27627c478bd9Sstevel@tonic-gate /* 27637c478bd9Sstevel@tonic-gate * If we got a card ready event after the reset, then don't 27647c478bd9Sstevel@tonic-gate * bother setting up a card ready timer, since we'll blast 27657c478bd9Sstevel@tonic-gate * right on through to the card ready processing. 27667c478bd9Sstevel@tonic-gate * Get the current card status to see if it's ready; if it 27677c478bd9Sstevel@tonic-gate * is, we probably won't get a card ready event. 27687c478bd9Sstevel@tonic-gate */ 27697c478bd9Sstevel@tonic-gate gs.socket = sp->socket_num; 27707c478bd9Sstevel@tonic-gate gs.CardState = 0; 27717c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_GetStatus, &gs)) != SUCCESS) { 27727c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 27737c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetStatus failure %d\n", 27747c478bd9Sstevel@tonic-gate sp->socket_num, ret); 27757c478bd9Sstevel@tonic-gate return (ret); 27767c478bd9Sstevel@tonic-gate } 27777c478bd9Sstevel@tonic-gate 27787c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 27797c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_READY) || 27807c478bd9Sstevel@tonic-gate (gs.CardState & SBM_RDYBSY)) { 27817c478bd9Sstevel@tonic-gate event = CS_EVENT_CARD_READY; 27827c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27837c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 27847c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d card " 27857c478bd9Sstevel@tonic-gate "READY\n", sp->socket_num); 27867c478bd9Sstevel@tonic-gate } 27877c478bd9Sstevel@tonic-gate #endif 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate } else { 27907c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 27917c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 27927c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_insertion: socket %d setting " 27937c478bd9Sstevel@tonic-gate "READY timer\n", sp->socket_num); 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate #endif 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate sp->rdybsy_tmo_id = timeout(cs_ready_timeout, sp, 27987c478bd9Sstevel@tonic-gate READY_TIMEOUT_TIME); 27997c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_FOR_READY; 28007c478bd9Sstevel@tonic-gate 28017c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 28027c478bd9Sstevel@tonic-gate 28037c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 28047c478bd9Sstevel@tonic-gate 28057c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 28067c478bd9Sstevel@tonic-gate 28077c478bd9Sstevel@tonic-gate /* 28087c478bd9Sstevel@tonic-gate * Handle card ready processing. This is only card ready processing 28097c478bd9Sstevel@tonic-gate * for card ready events in conjunction with a card insertion. 28107c478bd9Sstevel@tonic-gate */ 28117c478bd9Sstevel@tonic-gate if (event == CS_EVENT_CARD_READY) { 28127c478bd9Sstevel@tonic-gate get_socket_t get_socket; 28137c478bd9Sstevel@tonic-gate set_socket_t set_socket; 28147c478bd9Sstevel@tonic-gate 28157c478bd9Sstevel@tonic-gate /* 28167c478bd9Sstevel@tonic-gate * The only events that we want to see now are card removal 28177c478bd9Sstevel@tonic-gate * events. 28187c478bd9Sstevel@tonic-gate */ 28197c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 28207c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_REMOVAL; 28217c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 28227c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 28237c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 28247c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 28257c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_GetSocket failed\n", 28267c478bd9Sstevel@tonic-gate sp->socket_num); 28277c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 28287c478bd9Sstevel@tonic-gate } 28297c478bd9Sstevel@tonic-gate 28307c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 28317c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 28327c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 28337c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 28347c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 28357c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 28367c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 28377c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 28387c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) to reset latched values */ 28397c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 28427c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 28437c478bd9Sstevel@tonic-gate "cs_card_insertion: socket %d SS_SetSocket failed\n", 28447c478bd9Sstevel@tonic-gate sp->socket_num); 28457c478bd9Sstevel@tonic-gate 28467c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 28477c478bd9Sstevel@tonic-gate } 28487c478bd9Sstevel@tonic-gate 28497c478bd9Sstevel@tonic-gate /* 28507c478bd9Sstevel@tonic-gate * Grab the cis_lock mutex to protect the CIS-to-be and 28517c478bd9Sstevel@tonic-gate * the CIS window, then fire off the CIS parser to 28527c478bd9Sstevel@tonic-gate * create a local copy of the card's CIS. 28537c478bd9Sstevel@tonic-gate */ 28547c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 28557c478bd9Sstevel@tonic-gate 28567c478bd9Sstevel@tonic-gate if ((ret = cs_create_cis(sp)) != CS_SUCCESS) { 28577c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28587c478bd9Sstevel@tonic-gate return (ret); 28597c478bd9Sstevel@tonic-gate } 28607c478bd9Sstevel@tonic-gate 28617c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28627c478bd9Sstevel@tonic-gate 28637c478bd9Sstevel@tonic-gate /* 28647c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 28657c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 28667c478bd9Sstevel@tonic-gate * insertion, so destroy the CIS and terminate this 28677c478bd9Sstevel@tonic-gate * processing. We'll get called back to handle the 28687c478bd9Sstevel@tonic-gate * insertion again later. 28697c478bd9Sstevel@tonic-gate */ 28707c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 28717c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 28727c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 28737c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 28747c478bd9Sstevel@tonic-gate } else { 28757c478bd9Sstevel@tonic-gate /* 28767c478bd9Sstevel@tonic-gate * Schedule the call to the Socket Services work thread. 28777c478bd9Sstevel@tonic-gate */ 28787c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 28797c478bd9Sstevel@tonic-gate sp->ss_thread_state |= SOCKET_THREAD_CSCISInit; 28807c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_thread_cv); 28817c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 28827c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 28837c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate /* 28867c478bd9Sstevel@tonic-gate * Socket Services has parsed the CIS and has done any other 28877c478bd9Sstevel@tonic-gate * work to get the client driver loaded and attached if 28887c478bd9Sstevel@tonic-gate * necessary, so setup the per-client state. 28897c478bd9Sstevel@tonic-gate */ 28907c478bd9Sstevel@tonic-gate if (event == CS_EVENT_SS_UPDATED) { 28917c478bd9Sstevel@tonic-gate client_t *client; 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /* 28947c478bd9Sstevel@tonic-gate * Now that we and SS are done handling the card insertion 28957c478bd9Sstevel@tonic-gate * semantics, go through each client on this socket and set 28967c478bd9Sstevel@tonic-gate * the CS_EVENT_CARD_INSERTION event in each client's event 28977c478bd9Sstevel@tonic-gate * field. We do this here instead of in cs_event so that 28987c478bd9Sstevel@tonic-gate * when a client gets a CS_EVENT_CARD_INSERTION event, the 28997c478bd9Sstevel@tonic-gate * card insertion and ready processing has already been done 29007c478bd9Sstevel@tonic-gate * and SocketServices has had a chance to create a dip for 29017c478bd9Sstevel@tonic-gate * the card in this socket. 29027c478bd9Sstevel@tonic-gate */ 29037c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 29047c478bd9Sstevel@tonic-gate client = sp->client_list; 29057c478bd9Sstevel@tonic-gate while (client) { 29067c478bd9Sstevel@tonic-gate client->events |= (CS_EVENT_CARD_INSERTION & 29077c478bd9Sstevel@tonic-gate (client->event_mask | client->global_mask)); 29087c478bd9Sstevel@tonic-gate client = client->next; 29097c478bd9Sstevel@tonic-gate } /* while (client) */ 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 29147c478bd9Sstevel@tonic-gate 29157c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 29167c478bd9Sstevel@tonic-gate } 29177c478bd9Sstevel@tonic-gate 29187c478bd9Sstevel@tonic-gate /* 29197c478bd9Sstevel@tonic-gate * cs_card_removal - handle card removal events 29207c478bd9Sstevel@tonic-gate * 29217c478bd9Sstevel@tonic-gate * Destroy the CIS. 29227c478bd9Sstevel@tonic-gate * 29237c478bd9Sstevel@tonic-gate * calling: sp - pointer to socket structure 29247c478bd9Sstevel@tonic-gate * 29257c478bd9Sstevel@tonic-gate */ 29267c478bd9Sstevel@tonic-gate static int 29277c478bd9Sstevel@tonic-gate cs_card_removal(cs_socket_t *sp) 29287c478bd9Sstevel@tonic-gate { 29297c478bd9Sstevel@tonic-gate set_socket_t set_socket; 29307c478bd9Sstevel@tonic-gate int ret; 29317c478bd9Sstevel@tonic-gate 29327c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29337c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 29347c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d\n", sp->socket_num); 29357c478bd9Sstevel@tonic-gate } 29367c478bd9Sstevel@tonic-gate #endif 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate /* 29397c478bd9Sstevel@tonic-gate * Remove any pending card ready timer 29407c478bd9Sstevel@tonic-gate */ 29417c478bd9Sstevel@tonic-gate UNTIMEOUT(sp->rdybsy_tmo_id); 29427c478bd9Sstevel@tonic-gate 29437c478bd9Sstevel@tonic-gate /* 29447c478bd9Sstevel@tonic-gate * Clear various flags so that everyone else knows that there's 29457c478bd9Sstevel@tonic-gate * nothing on this socket anymore. Note that we clear the 29467c478bd9Sstevel@tonic-gate * SOCKET_CARD_INSERTED and SOCKET_IS_IO flags in the 29477c478bd9Sstevel@tonic-gate * ss_to_cs_events event mapping function. 29487c478bd9Sstevel@tonic-gate */ 29497c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 29507c478bd9Sstevel@tonic-gate sp->thread_state &= ~(SOCKET_WAIT_FOR_READY | SOCKET_RESET_TIMER); 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate /* 29537c478bd9Sstevel@tonic-gate * Turn off socket power and set the socket back to memory mode. 29547c478bd9Sstevel@tonic-gate * Disable all socket events except for CARD_INSERTION events. 29557c478bd9Sstevel@tonic-gate */ 29567c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 29577c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 29587c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 29597c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 29607c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 29617c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 29627c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 29637c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 29647c478bd9Sstevel@tonic-gate 29657c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 29667c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 29677c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 29687c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 29697c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 29707c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 29717c478bd9Sstevel@tonic-gate 29727c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 29737c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 29747c478bd9Sstevel@tonic-gate "cs_card_removal: socket %d SS_SetSocket failure %d\n", 29757c478bd9Sstevel@tonic-gate sp->socket_num, ret); 29767c478bd9Sstevel@tonic-gate return (ret); 29777c478bd9Sstevel@tonic-gate } 29787c478bd9Sstevel@tonic-gate 29797c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29807c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 29817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: socket %d " 29827c478bd9Sstevel@tonic-gate "calling cs_destroy_cis\n", 29837c478bd9Sstevel@tonic-gate sp->socket_num); 29847c478bd9Sstevel@tonic-gate } 29857c478bd9Sstevel@tonic-gate #endif 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate /* 29887c478bd9Sstevel@tonic-gate * Destroy the CIS and tell Socket Services that we're done 29897c478bd9Sstevel@tonic-gate * handling the card removal event. 29907c478bd9Sstevel@tonic-gate */ 29917c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 29927c478bd9Sstevel@tonic-gate (void) cs_destroy_cis(sp); 29937c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 29967c478bd9Sstevel@tonic-gate if (cs_debug > 2) { 29977c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_removal: calling CSCardRemoved\n"); 29987c478bd9Sstevel@tonic-gate } 29997c478bd9Sstevel@tonic-gate #endif 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate SocketServices(CSCardRemoved, sp->socket_num); 30027c478bd9Sstevel@tonic-gate 30037c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 30047c478bd9Sstevel@tonic-gate } 30057c478bd9Sstevel@tonic-gate 30067c478bd9Sstevel@tonic-gate /* 30077c478bd9Sstevel@tonic-gate * ss_to_cs_events - convert Socket Services events to Card Services event 30087c478bd9Sstevel@tonic-gate * masks; this function will not read the PRR if the 30097c478bd9Sstevel@tonic-gate * socket is in IO mode; this happens in cs_event_thread 30107c478bd9Sstevel@tonic-gate * 30117c478bd9Sstevel@tonic-gate * This function returns a bit mask of events. 30127c478bd9Sstevel@tonic-gate * 30137c478bd9Sstevel@tonic-gate * Note that we do some simple hysterious on card insertion and card removal 30147c478bd9Sstevel@tonic-gate * events to prevent spurious insertion and removal events from being 30157c478bd9Sstevel@tonic-gate * propogated down the chain. 30167c478bd9Sstevel@tonic-gate */ 30177c478bd9Sstevel@tonic-gate static event_t 30187c478bd9Sstevel@tonic-gate ss_to_cs_events(cs_socket_t *sp, event_t event) 30197c478bd9Sstevel@tonic-gate { 30207c478bd9Sstevel@tonic-gate event_t revent = 0; 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate switch (event) { 30237c478bd9Sstevel@tonic-gate case PCE_CARD_STATUS_CHANGE: 30247c478bd9Sstevel@tonic-gate revent |= CS_EVENT_STATUS_CHANGE; 30257c478bd9Sstevel@tonic-gate break; 30267c478bd9Sstevel@tonic-gate case PCE_CARD_REMOVAL: 30277c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) { 30287c478bd9Sstevel@tonic-gate sp->flags &= ~(SOCKET_CARD_INSERTED | SOCKET_IS_IO); 30297c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_REMOVAL; 30307c478bd9Sstevel@tonic-gate /* 30317c478bd9Sstevel@tonic-gate * If we're processing a removal event, it makes 30327c478bd9Sstevel@tonic-gate * no sense to keep any insertion or ready events, 30337c478bd9Sstevel@tonic-gate * so nuke them here. This will not clear any 30347c478bd9Sstevel@tonic-gate * insertion events in the per-client event field. 30357c478bd9Sstevel@tonic-gate */ 30367c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_INSERTION | 30377c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY | 30387c478bd9Sstevel@tonic-gate CS_EVENT_READY_TIMEOUT); 30397c478bd9Sstevel@tonic-gate 30407c478bd9Sstevel@tonic-gate /* 30417c478bd9Sstevel@tonic-gate * We also don't need to wait for READY anymore since 30427c478bd9Sstevel@tonic-gate * it probably won't show up, or if it does, it will 30437c478bd9Sstevel@tonic-gate * be a bogus READY event as the card is sliding out 30447c478bd9Sstevel@tonic-gate * of the socket. Since we never do a cv_wait on the 30457c478bd9Sstevel@tonic-gate * card ready timer, it's OK for that timer to either 30467c478bd9Sstevel@tonic-gate * never go off (via an UNTIMEOUT in cs_card_removal) 30477c478bd9Sstevel@tonic-gate * or to go off but not do a cv_broadcast (since the 30487c478bd9Sstevel@tonic-gate * SOCKET_WAIT_FOR_READY flag is cleared here). 30497c478bd9Sstevel@tonic-gate */ 30507c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 30517c478bd9Sstevel@tonic-gate 30527c478bd9Sstevel@tonic-gate } 30537c478bd9Sstevel@tonic-gate break; 30547c478bd9Sstevel@tonic-gate case PCE_CARD_INSERT: 30557c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 30567c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_CARD_INSERTED; 30577c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_INSERTION; 30587c478bd9Sstevel@tonic-gate } 30597c478bd9Sstevel@tonic-gate break; 30607c478bd9Sstevel@tonic-gate case PCE_CARD_READY: 30617c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30627c478bd9Sstevel@tonic-gate revent |= CS_EVENT_CARD_READY; 30637c478bd9Sstevel@tonic-gate break; 30647c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_WARN: 30657c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30667c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_LOW; 30677c478bd9Sstevel@tonic-gate break; 30687c478bd9Sstevel@tonic-gate case PCE_CARD_BATTERY_DEAD: 30697c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30707c478bd9Sstevel@tonic-gate revent |= CS_EVENT_BATTERY_DEAD; 30717c478bd9Sstevel@tonic-gate break; 30727c478bd9Sstevel@tonic-gate case PCE_CARD_WRITE_PROTECT: 30737c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_CARD_INSERTED) 30747c478bd9Sstevel@tonic-gate revent |= CS_EVENT_WRITE_PROTECT; 30757c478bd9Sstevel@tonic-gate break; 30767c478bd9Sstevel@tonic-gate case PCE_PM_RESUME: 30777c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_RESUME; 30787c478bd9Sstevel@tonic-gate break; 30797c478bd9Sstevel@tonic-gate case PCE_PM_SUSPEND: 30807c478bd9Sstevel@tonic-gate revent |= CS_EVENT_PM_SUSPEND; 30817c478bd9Sstevel@tonic-gate break; 30827c478bd9Sstevel@tonic-gate default: 30837c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "ss_to_cs_events: unknown event 0x%x\n", 30847c478bd9Sstevel@tonic-gate (int)event); 30857c478bd9Sstevel@tonic-gate break; 30867c478bd9Sstevel@tonic-gate } /* switch(event) */ 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate return (revent); 30897c478bd9Sstevel@tonic-gate } 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate /* 30927c478bd9Sstevel@tonic-gate * cs_ready_timeout - general purpose READY/BUSY and RESET timer 30937c478bd9Sstevel@tonic-gate * 30947c478bd9Sstevel@tonic-gate * Note that we really only expect one of the two events to be asserted when 30957c478bd9Sstevel@tonic-gate * we are called. XXX - Perhaps this might be a problem later on?? 30967c478bd9Sstevel@tonic-gate * 30977c478bd9Sstevel@tonic-gate * There is also the problem of cv_broadcast dropping the interrupt 30987c478bd9Sstevel@tonic-gate * priority, even though we have our high-priority mutex held. If 30997c478bd9Sstevel@tonic-gate * we hold our high-priority mutex (sp->lock) over a cv_broadcast, and 31007c478bd9Sstevel@tonic-gate * we get a high-priority interrupt during this time, the system will 31017c478bd9Sstevel@tonic-gate * deadlock or panic. Thanks to Andy Banta for finding this out in 31027c478bd9Sstevel@tonic-gate * the SPC/S (stc.c) driver. 31037c478bd9Sstevel@tonic-gate * 31047c478bd9Sstevel@tonic-gate * This callback routine can not grab the sp->client_lock mutex or deadlock 31057c478bd9Sstevel@tonic-gate * will result. 31067c478bd9Sstevel@tonic-gate */ 31077c478bd9Sstevel@tonic-gate void 31087c478bd9Sstevel@tonic-gate cs_ready_timeout(void *arg) 31097c478bd9Sstevel@tonic-gate { 31107c478bd9Sstevel@tonic-gate cs_socket_t *sp = arg; 31117c478bd9Sstevel@tonic-gate kcondvar_t *cvp = NULL; 31127c478bd9Sstevel@tonic-gate 31137c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 31147c478bd9Sstevel@tonic-gate 31157c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_RESET_TIMER) { 31167c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 31177c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 31187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_RESET_TIMER socket %d\n", 31197c478bd9Sstevel@tonic-gate sp->socket_num); 31207c478bd9Sstevel@tonic-gate } 31217c478bd9Sstevel@tonic-gate #endif 31227c478bd9Sstevel@tonic-gate 31237c478bd9Sstevel@tonic-gate cvp = &sp->reset_cv; 31247c478bd9Sstevel@tonic-gate } 31257c478bd9Sstevel@tonic-gate 31267c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 31277c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_READY_TIMEOUT; 31287c478bd9Sstevel@tonic-gate cvp = &sp->thread_cv; 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 31317c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 31327c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ready_timeout: SOCKET_WAIT_FOR_READY " 31337c478bd9Sstevel@tonic-gate "socket %d\n", sp->socket_num); 31347c478bd9Sstevel@tonic-gate } 31357c478bd9Sstevel@tonic-gate #endif 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate } 31387c478bd9Sstevel@tonic-gate 31397c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 31407c478bd9Sstevel@tonic-gate 31417c478bd9Sstevel@tonic-gate if (cvp) 31427c478bd9Sstevel@tonic-gate cv_broadcast(cvp); 31437c478bd9Sstevel@tonic-gate } 31447c478bd9Sstevel@tonic-gate 31457c478bd9Sstevel@tonic-gate /* 31467c478bd9Sstevel@tonic-gate * cs_event_softintr_timeout - wrapper function to call cs_socket_event_softintr 31477c478bd9Sstevel@tonic-gate */ 31487c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31497c478bd9Sstevel@tonic-gate void 31507c478bd9Sstevel@tonic-gate cs_event_softintr_timeout(void *arg) 31517c478bd9Sstevel@tonic-gate { 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate /* 31547c478bd9Sstevel@tonic-gate * If we're trying to unload this module, then don't do 31557c478bd9Sstevel@tonic-gate * anything but exit. 31567c478bd9Sstevel@tonic-gate * We acquire the cs_globals.global_lock mutex here so that 31577c478bd9Sstevel@tonic-gate * we can correctly synchronize with cs_deinit when it 31587c478bd9Sstevel@tonic-gate * is telling us to shut down. XXX - is this bogus?? 31597c478bd9Sstevel@tonic-gate */ 31607c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 31617c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING)) { 31627c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31637c478bd9Sstevel@tonic-gate (void) cs_socket_event_softintr(NULL); 31647c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 31657c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 31667c478bd9Sstevel@tonic-gate } else { 31677c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31687c478bd9Sstevel@tonic-gate } 31697c478bd9Sstevel@tonic-gate } 31707c478bd9Sstevel@tonic-gate 31717c478bd9Sstevel@tonic-gate /* 31727c478bd9Sstevel@tonic-gate * cs_socket_event_softintr - This function just does a cv_broadcast on behalf 31737c478bd9Sstevel@tonic-gate * of the high-priority interrupt handler. 31747c478bd9Sstevel@tonic-gate * 31757c478bd9Sstevel@tonic-gate * Note: There is no calling argument. 31767c478bd9Sstevel@tonic-gate */ 31777c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 31787c478bd9Sstevel@tonic-gate uint32_t 31797c478bd9Sstevel@tonic-gate cs_socket_event_softintr(caddr_t notused) 31807c478bd9Sstevel@tonic-gate { 31817c478bd9Sstevel@tonic-gate cs_socket_t *sp; 31827c478bd9Sstevel@tonic-gate uint32_t sn; 31837c478bd9Sstevel@tonic-gate int ret = DDI_INTR_UNCLAIMED; 31847c478bd9Sstevel@tonic-gate 31857c478bd9Sstevel@tonic-gate /* 31867c478bd9Sstevel@tonic-gate * If the module is on it's way out, then don't bother 31877c478bd9Sstevel@tonic-gate * to do anything else except return. 31887c478bd9Sstevel@tonic-gate */ 31897c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 31907c478bd9Sstevel@tonic-gate if ((cs_globals.init_state & GLOBAL_INIT_STATE_UNLOADING) || 31917c478bd9Sstevel@tonic-gate (cs_globals.init_state & GLOBAL_IN_SOFTINTR)) { 31927c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 31937c478bd9Sstevel@tonic-gate 31947c478bd9Sstevel@tonic-gate /* 31957c478bd9Sstevel@tonic-gate * Note that we return DDI_INTR_UNCLAIMED here 31967c478bd9Sstevel@tonic-gate * since we don't want to be constantly 31977c478bd9Sstevel@tonic-gate * called back. 31987c478bd9Sstevel@tonic-gate */ 31997c478bd9Sstevel@tonic-gate return (ret); 32007c478bd9Sstevel@tonic-gate } else { 32017c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_IN_SOFTINTR; 32027c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 32037c478bd9Sstevel@tonic-gate } 32047c478bd9Sstevel@tonic-gate 32057c478bd9Sstevel@tonic-gate /* 32067c478bd9Sstevel@tonic-gate * Go through each socket and dispatch the appropriate events. 32077c478bd9Sstevel@tonic-gate * We have to funnel everything through this one routine because 32087c478bd9Sstevel@tonic-gate * we can't do a cv_broadcast from a high level interrupt handler 32097c478bd9Sstevel@tonic-gate * and we also can't have more than one soft interrupt handler 32107c478bd9Sstevel@tonic-gate * on a single dip and using the same handler address. 32117c478bd9Sstevel@tonic-gate */ 32127c478bd9Sstevel@tonic-gate for (sn = 0; sn < cs_globals.max_socket_num; sn++) { 32137c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 32147c478bd9Sstevel@tonic-gate if (sp->init_state & SOCKET_INIT_STATE_READY) { 32157c478bd9Sstevel@tonic-gate /* 32167c478bd9Sstevel@tonic-gate * If we're being asked to unload CS, then don't bother 32177c478bd9Sstevel@tonic-gate * waking up the socket event thread handler. 32187c478bd9Sstevel@tonic-gate */ 32197c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_UNLOAD_MODULE) && 32207c478bd9Sstevel@tonic-gate (sp->flags & SOCKET_NEEDS_THREAD)) { 32217c478bd9Sstevel@tonic-gate ret = DDI_INTR_CLAIMED; 32227c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 32237c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 32247c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 32257c478bd9Sstevel@tonic-gate } /* if (SOCKET_NEEDS_THREAD) */ 32267c478bd9Sstevel@tonic-gate } /* if (SOCKET_INIT_STATE_READY) */ 32277c478bd9Sstevel@tonic-gate } /* cs_get_sp */ 32287c478bd9Sstevel@tonic-gate } /* for (sn) */ 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 32317c478bd9Sstevel@tonic-gate cs_globals.init_state &= ~GLOBAL_IN_SOFTINTR; 32327c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 32337c478bd9Sstevel@tonic-gate 32347c478bd9Sstevel@tonic-gate return (ret); 32357c478bd9Sstevel@tonic-gate } 32367c478bd9Sstevel@tonic-gate 32377c478bd9Sstevel@tonic-gate /* 32387c478bd9Sstevel@tonic-gate * cs_event_thread - This is the per-socket event thread. 32397c478bd9Sstevel@tonic-gate */ 32407c478bd9Sstevel@tonic-gate static void 32417c478bd9Sstevel@tonic-gate cs_event_thread(uint32_t sn) 32427c478bd9Sstevel@tonic-gate { 32437c478bd9Sstevel@tonic-gate cs_socket_t *sp; 32447c478bd9Sstevel@tonic-gate client_t *client; 32457c478bd9Sstevel@tonic-gate client_types_t *ct; 32467c478bd9Sstevel@tonic-gate 32477c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 32487c478bd9Sstevel@tonic-gate return; 32497c478bd9Sstevel@tonic-gate 32507c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32517c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d thread started\n", 32537c478bd9Sstevel@tonic-gate sp->socket_num); 32547c478bd9Sstevel@tonic-gate } 32557c478bd9Sstevel@tonic-gate #endif 32567c478bd9Sstevel@tonic-gate 32577c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_cs, &sp->client_lock, 32587c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_event_thread"); 32597c478bd9Sstevel@tonic-gate 32607c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 32617c478bd9Sstevel@tonic-gate 32627c478bd9Sstevel@tonic-gate for (;;) { 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_cs); 32657c478bd9Sstevel@tonic-gate cv_wait(&sp->thread_cv, &sp->client_lock); 32667c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_cs, &sp->client_lock); 32677c478bd9Sstevel@tonic-gate 32687c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 32697c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_NEEDS_THREAD; 32707c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 32717c478bd9Sstevel@tonic-gate 32727c478bd9Sstevel@tonic-gate /* 32737c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations that 32747c478bd9Sstevel@tonic-gate * we are being asked to perform. 32757c478bd9Sstevel@tonic-gate */ 32767c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_THREAD_EXIT) { 32777c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32787c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32797c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 32807c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 32817c478bd9Sstevel@tonic-gate sp->socket_num); 32827c478bd9Sstevel@tonic-gate } 32837c478bd9Sstevel@tonic-gate #endif 32847c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_cs); 32857c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); /* wakes up cs_deinit */ 32867c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 32877c478bd9Sstevel@tonic-gate return; 32887c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 32897c478bd9Sstevel@tonic-gate 32907c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 32917c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 32927c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d sp->events 0x%x\n", 32937c478bd9Sstevel@tonic-gate sp->socket_num, 32947c478bd9Sstevel@tonic-gate (int)sp->events); 32957c478bd9Sstevel@tonic-gate } 32967c478bd9Sstevel@tonic-gate #endif 32977c478bd9Sstevel@tonic-gate 32987c478bd9Sstevel@tonic-gate /* 32997c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_INSERTION events 33007c478bd9Sstevel@tonic-gate */ 33017c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_INSERTION) { 33027c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33037c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_INSERTION; 33047c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33057c478bd9Sstevel@tonic-gate 33067c478bd9Sstevel@tonic-gate /* 33077c478bd9Sstevel@tonic-gate * If we have a pending CS_EVENT_CARD_REMOVAL event it 33087c478bd9Sstevel@tonic-gate * means that we likely got CD line bounce on the 33097c478bd9Sstevel@tonic-gate * insertion, so terminate this processing. 33107c478bd9Sstevel@tonic-gate */ 33117c478bd9Sstevel@tonic-gate if ((sp->events & CS_EVENT_CARD_REMOVAL) == 0) { 33127c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_INSERTION); 33137c478bd9Sstevel@tonic-gate } 33147c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 33157c478bd9Sstevel@tonic-gate else if (cs_debug > 0) { 33167c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_event_thread: socket %d " 33177c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_REMOVAL event " 33187c478bd9Sstevel@tonic-gate "terminating " 33197c478bd9Sstevel@tonic-gate "CS_EVENT_CARD_INSERTION " 33207c478bd9Sstevel@tonic-gate "processing\n", sp->socket_num); 33217c478bd9Sstevel@tonic-gate } 33227c478bd9Sstevel@tonic-gate #endif 33237c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_INSERTION) */ 33247c478bd9Sstevel@tonic-gate 33257c478bd9Sstevel@tonic-gate /* 33267c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_READY and CS_EVENT_READY_TIMEOUT events 33277c478bd9Sstevel@tonic-gate */ 33287c478bd9Sstevel@tonic-gate if (sp->events & (CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT)) { 33297c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33307c478bd9Sstevel@tonic-gate sp->events &= ~(CS_EVENT_CARD_READY | CS_EVENT_READY_TIMEOUT); 33317c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33327c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_FOR_READY) { 33337c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33347c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_FOR_READY; 33357c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33367c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_CARD_READY); 33377c478bd9Sstevel@tonic-gate } /* if (SOCKET_WAIT_FOR_READY) */ 33387c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_READY) */ 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gate /* 33417c478bd9Sstevel@tonic-gate * Handle CS_EVENT_SS_UPDATED events 33427c478bd9Sstevel@tonic-gate */ 33437c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_SS_UPDATED) { 33447c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33457c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_SS_UPDATED; 33467c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33477c478bd9Sstevel@tonic-gate (void) cs_card_insertion(sp, CS_EVENT_SS_UPDATED); 33487c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_SS_UPDATED) */ 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate /* 33517c478bd9Sstevel@tonic-gate * Handle CS_EVENT_STATUS_CHANGE events 33527c478bd9Sstevel@tonic-gate */ 33537c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_STATUS_CHANGE) { 33547c478bd9Sstevel@tonic-gate event_t revent; 33557c478bd9Sstevel@tonic-gate 33567c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 33577c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 33587c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_STATUS_CHANGE; 33597c478bd9Sstevel@tonic-gate 33607c478bd9Sstevel@tonic-gate /* 33617c478bd9Sstevel@tonic-gate * Go through each client and add any events that we saw to 33627c478bd9Sstevel@tonic-gate * the client's event list if the client has that event 33637c478bd9Sstevel@tonic-gate * enabled in their event mask. 33647c478bd9Sstevel@tonic-gate * Remove any events that may be pending for this client if 33657c478bd9Sstevel@tonic-gate * the client's event mask says that the client doesn't 33667c478bd9Sstevel@tonic-gate * want to see those events anymore. This handles the 33677c478bd9Sstevel@tonic-gate * case where the client had an event enabled in it's 33687c478bd9Sstevel@tonic-gate * event mask when the event came in but between that 33697c478bd9Sstevel@tonic-gate * time and the time we're called here the client 33707c478bd9Sstevel@tonic-gate * disabled that event. 33717c478bd9Sstevel@tonic-gate */ 33727c478bd9Sstevel@tonic-gate client = sp->client_list; 33737c478bd9Sstevel@tonic-gate 33747c478bd9Sstevel@tonic-gate while (client) { 33757c478bd9Sstevel@tonic-gate /* 33767c478bd9Sstevel@tonic-gate * Read the PRR (if it exists) and check for any events. 33777c478bd9Sstevel@tonic-gate * The PRR will only be read if the socket is in IO 33787c478bd9Sstevel@tonic-gate * mode, if there is a card in the socket, and if there 33797c478bd9Sstevel@tonic-gate * is a PRR. 33807c478bd9Sstevel@tonic-gate * We don't have to clear revent before we call the 33817c478bd9Sstevel@tonic-gate * cs_read_event_status function since it will 33827c478bd9Sstevel@tonic-gate * clear it before adding any current events. 33837c478bd9Sstevel@tonic-gate */ 33847c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 33857c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 33867c478bd9Sstevel@tonic-gate &revent, NULL, 0); 33877c478bd9Sstevel@tonic-gate 33887c478bd9Sstevel@tonic-gate client->events = ((client->events | revent) & 33897c478bd9Sstevel@tonic-gate (client->event_mask | 33907c478bd9Sstevel@tonic-gate client->global_mask)); 33917c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 33927c478bd9Sstevel@tonic-gate client = client->next; 33937c478bd9Sstevel@tonic-gate } /* while (client) */ 33947c478bd9Sstevel@tonic-gate 33957c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 33967c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 33977c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_STATUS_CHANGE) */ 33987c478bd9Sstevel@tonic-gate 33997c478bd9Sstevel@tonic-gate /* 34007c478bd9Sstevel@tonic-gate * We want to maintain the required event dispatching order as 34017c478bd9Sstevel@tonic-gate * specified in the PCMCIA spec, so we cycle through all 34027c478bd9Sstevel@tonic-gate * clients on this socket to make sure that they are 34037c478bd9Sstevel@tonic-gate * notified in the correct order. 34047c478bd9Sstevel@tonic-gate */ 34057c478bd9Sstevel@tonic-gate ct = &client_types[0]; 34067c478bd9Sstevel@tonic-gate while (ct) { 34077c478bd9Sstevel@tonic-gate /* 34087c478bd9Sstevel@tonic-gate * Point to the head of the client list for this socket, and go 34097c478bd9Sstevel@tonic-gate * through each client to set up the client events as well 34107c478bd9Sstevel@tonic-gate * as call the client's event handler directly if we have 34117c478bd9Sstevel@tonic-gate * a high priority event that we need to tell the client 34127c478bd9Sstevel@tonic-gate * about. 34137c478bd9Sstevel@tonic-gate */ 34147c478bd9Sstevel@tonic-gate client = sp->client_list; 34157c478bd9Sstevel@tonic-gate 34167c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 34177c478bd9Sstevel@tonic-gate client_t *clp = NULL; 34187c478bd9Sstevel@tonic-gate 34197c478bd9Sstevel@tonic-gate while (client) { 34207c478bd9Sstevel@tonic-gate clp = client; 34217c478bd9Sstevel@tonic-gate client = client->next; 34227c478bd9Sstevel@tonic-gate } 34237c478bd9Sstevel@tonic-gate client = clp; 34247c478bd9Sstevel@tonic-gate } 34257c478bd9Sstevel@tonic-gate 34267c478bd9Sstevel@tonic-gate while (client) { 34277c478bd9Sstevel@tonic-gate if (client->flags & ct->type) { 34287c478bd9Sstevel@tonic-gate uint32_t bit = 0; 34297c478bd9Sstevel@tonic-gate event_t event; 34307c478bd9Sstevel@tonic-gate 34317c478bd9Sstevel@tonic-gate while (client->events) { 34327c478bd9Sstevel@tonic-gate 34337c478bd9Sstevel@tonic-gate switch (event = CS_BIT_GET(client->events, bit)) { 34347c478bd9Sstevel@tonic-gate /* 34357c478bd9Sstevel@tonic-gate * Clients always receive registration complete 34367c478bd9Sstevel@tonic-gate * events, even if there is no card of 34377c478bd9Sstevel@tonic-gate * their type currently in the socket. 34387c478bd9Sstevel@tonic-gate */ 34397c478bd9Sstevel@tonic-gate case CS_EVENT_REGISTRATION_COMPLETE: 34407c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 34417c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34427c478bd9Sstevel@tonic-gate break; 34437c478bd9Sstevel@tonic-gate /* 34447c478bd9Sstevel@tonic-gate * The client only gets a card insertion event 34457c478bd9Sstevel@tonic-gate * if there is currently a card in the 34467c478bd9Sstevel@tonic-gate * socket that the client can control. 34477c478bd9Sstevel@tonic-gate * The nexus determines this. We also 34487c478bd9Sstevel@tonic-gate * prevent the client from receiving 34497c478bd9Sstevel@tonic-gate * multiple CS_EVENT_CARD_INSERTION 34507c478bd9Sstevel@tonic-gate * events without receiving intervening 34517c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL events. 34527c478bd9Sstevel@tonic-gate */ 34537c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_INSERTION: 34547c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) { 34557c478bd9Sstevel@tonic-gate int send_insertion; 34567c478bd9Sstevel@tonic-gate 34577c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34587c478bd9Sstevel@tonic-gate send_insertion = client->flags; 34597c478bd9Sstevel@tonic-gate client->flags |= 34607c478bd9Sstevel@tonic-gate (CLIENT_CARD_INSERTED | 34617c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 34627c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34637c478bd9Sstevel@tonic-gate if (!(send_insertion & 34647c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION)) { 34657c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 34667c478bd9Sstevel@tonic-gate event, CS_EVENT_PRI_LOW); 34677c478bd9Sstevel@tonic-gate } /* if (!CLIENT_SENT_INSERTION) */ 34687c478bd9Sstevel@tonic-gate } 34697c478bd9Sstevel@tonic-gate break; 34707c478bd9Sstevel@tonic-gate /* 34717c478bd9Sstevel@tonic-gate * The CS_EVENT_CARD_REMOVAL_LOWP is a low 34727c478bd9Sstevel@tonic-gate * priority CS_EVENT_CARD_REMOVAL event. 34737c478bd9Sstevel@tonic-gate */ 34747c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL_LOWP: 34757c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34767c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_SENT_INSERTION; 34777c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34787c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, 34797c478bd9Sstevel@tonic-gate CS_EVENT_CARD_REMOVAL, 34807c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34817c478bd9Sstevel@tonic-gate break; 34827c478bd9Sstevel@tonic-gate /* 34837c478bd9Sstevel@tonic-gate * The hardware card removal events are handed 34847c478bd9Sstevel@tonic-gate * to the client in cs_event at high 34857c478bd9Sstevel@tonic-gate * priority interrupt time; this card 34867c478bd9Sstevel@tonic-gate * removal event is a software-generated 34877c478bd9Sstevel@tonic-gate * event. 34887c478bd9Sstevel@tonic-gate */ 34897c478bd9Sstevel@tonic-gate case CS_EVENT_CARD_REMOVAL: 34907c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 34917c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 34927c478bd9Sstevel@tonic-gate client->flags &= 34937c478bd9Sstevel@tonic-gate ~(CLIENT_CARD_INSERTED | 34947c478bd9Sstevel@tonic-gate CLIENT_SENT_INSERTION); 34957c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 34967c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 34977c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 34987c478bd9Sstevel@tonic-gate } 34997c478bd9Sstevel@tonic-gate break; 35007c478bd9Sstevel@tonic-gate /* 35017c478bd9Sstevel@tonic-gate * Write protect events require the info field 35027c478bd9Sstevel@tonic-gate * of the client's event callback args to 35037c478bd9Sstevel@tonic-gate * be zero if the card is not write 35047c478bd9Sstevel@tonic-gate * protected and one if it is. 35057c478bd9Sstevel@tonic-gate */ 35067c478bd9Sstevel@tonic-gate case CS_EVENT_WRITE_PROTECT: 35077c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 35087c478bd9Sstevel@tonic-gate get_ss_status_t gs; 35097c478bd9Sstevel@tonic-gate 35107c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 35117c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35127c478bd9Sstevel@tonic-gate (void) cs_read_event_status(sp, client, 35137c478bd9Sstevel@tonic-gate NULL, 35147c478bd9Sstevel@tonic-gate &gs, 0); 35157c478bd9Sstevel@tonic-gate if (gs.CardState & SBM_WP) { 35167c478bd9Sstevel@tonic-gate client->event_callback_args.info = 35177c478bd9Sstevel@tonic-gate (void *) 35187c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPON; 35197c478bd9Sstevel@tonic-gate } else { 35207c478bd9Sstevel@tonic-gate client->event_callback_args.info = 35217c478bd9Sstevel@tonic-gate (void *) 35227c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT_WPOFF; 35237c478bd9Sstevel@tonic-gate } 35247c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35257c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 35267c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35277c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35287c478bd9Sstevel@tonic-gate } /* CLIENT_CARD_INSERTED */ 35297c478bd9Sstevel@tonic-gate break; 35307c478bd9Sstevel@tonic-gate case CS_EVENT_CLIENT_INFO: 35317c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35327c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35337c478bd9Sstevel@tonic-gate break; 35347c478bd9Sstevel@tonic-gate case 0: 35357c478bd9Sstevel@tonic-gate break; 35367c478bd9Sstevel@tonic-gate default: 35377c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CARD_INSERTED) { 35387c478bd9Sstevel@tonic-gate CLIENT_EVENT_CALLBACK(client, event, 35397c478bd9Sstevel@tonic-gate CS_EVENT_PRI_LOW); 35407c478bd9Sstevel@tonic-gate } 35417c478bd9Sstevel@tonic-gate break; 35427c478bd9Sstevel@tonic-gate } /* switch */ 35437c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35447c478bd9Sstevel@tonic-gate CS_BIT_CLEAR(client->events, bit); 35457c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35467c478bd9Sstevel@tonic-gate bit++; 35477c478bd9Sstevel@tonic-gate } /* while (client->events) */ 35487c478bd9Sstevel@tonic-gate } /* if (ct->type) */ 35497c478bd9Sstevel@tonic-gate if (ct->order & CLIENT_EVENTS_LIFO) { 35507c478bd9Sstevel@tonic-gate client = client->prev; 35517c478bd9Sstevel@tonic-gate } else { 35527c478bd9Sstevel@tonic-gate client = client->next; 35537c478bd9Sstevel@tonic-gate } 35547c478bd9Sstevel@tonic-gate } /* while (client) */ 35557c478bd9Sstevel@tonic-gate 35567c478bd9Sstevel@tonic-gate ct = ct->next; 35577c478bd9Sstevel@tonic-gate } /* while (ct) */ 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate /* 35607c478bd9Sstevel@tonic-gate * Handle CS_EVENT_CARD_REMOVAL events 35617c478bd9Sstevel@tonic-gate */ 35627c478bd9Sstevel@tonic-gate if (sp->events & CS_EVENT_CARD_REMOVAL) { 35637c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35647c478bd9Sstevel@tonic-gate sp->events &= ~CS_EVENT_CARD_REMOVAL; 35657c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35667c478bd9Sstevel@tonic-gate (void) cs_card_removal(sp); 35677c478bd9Sstevel@tonic-gate } /* if (CS_EVENT_CARD_REMOVAL) */ 35687c478bd9Sstevel@tonic-gate 35697c478bd9Sstevel@tonic-gate /* 35707c478bd9Sstevel@tonic-gate * If someone is waiting for us to complete, signal them now. 35717c478bd9Sstevel@tonic-gate */ 35727c478bd9Sstevel@tonic-gate if (sp->thread_state & SOCKET_WAIT_SYNC) { 35737c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 35747c478bd9Sstevel@tonic-gate sp->thread_state &= ~SOCKET_WAIT_SYNC; 35757c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 35767c478bd9Sstevel@tonic-gate cv_broadcast(&sp->caller_cv); 35777c478bd9Sstevel@tonic-gate } /* SOCKET_WAIT_SYNC */ 35787c478bd9Sstevel@tonic-gate 35797c478bd9Sstevel@tonic-gate } /* for (;;) */ 35807c478bd9Sstevel@tonic-gate } 35817c478bd9Sstevel@tonic-gate 35827c478bd9Sstevel@tonic-gate /* 35837c478bd9Sstevel@tonic-gate * cs_card_for_client - checks to see if a card that the client can control 35847c478bd9Sstevel@tonic-gate * is currently inserted in the socket. Socket Services 35857c478bd9Sstevel@tonic-gate * has to tell us if this is the case. 35867c478bd9Sstevel@tonic-gate */ 35877c478bd9Sstevel@tonic-gate static int 35887c478bd9Sstevel@tonic-gate cs_card_for_client(client_t *client) 35897c478bd9Sstevel@tonic-gate { 35907c478bd9Sstevel@tonic-gate 35917c478bd9Sstevel@tonic-gate /* 35927c478bd9Sstevel@tonic-gate * If the client has set the CS_EVENT_ALL_CLIENTS it means that they 35937c478bd9Sstevel@tonic-gate * want to get all events for all clients, irrespective of 35947c478bd9Sstevel@tonic-gate * whether or not there is a card in the socket. Such clients 35957c478bd9Sstevel@tonic-gate * have to be very careful if they touch the card hardware in 35967c478bd9Sstevel@tonic-gate * any way to prevent causing problems for other clients on the 35977c478bd9Sstevel@tonic-gate * same socket. This flag will typically only be set by the 35987c478bd9Sstevel@tonic-gate * "super-client" or CSI types of clients that wish to get 35997c478bd9Sstevel@tonic-gate * information on other clients or cards in the system. 36007c478bd9Sstevel@tonic-gate * Note that the CS_EVENT_ALL_CLIENTS must be set in either the 36017c478bd9Sstevel@tonic-gate * client's global event mask or client event mask. 36027c478bd9Sstevel@tonic-gate * The client must also have registered as a "super-client" or as a 36037c478bd9Sstevel@tonic-gate * CSI client for this socket. 36047c478bd9Sstevel@tonic-gate */ 36057c478bd9Sstevel@tonic-gate if ((client->flags & (CLIENT_SUPER_CLIENT | CLIENT_CSI_CLIENT)) && 36067c478bd9Sstevel@tonic-gate ((client->global_mask | client->event_mask) & 36077c478bd9Sstevel@tonic-gate CS_EVENT_ALL_CLIENTS)) 36087c478bd9Sstevel@tonic-gate return (1); 36097c478bd9Sstevel@tonic-gate 36107c478bd9Sstevel@tonic-gate /* 36117c478bd9Sstevel@tonic-gate * Look for the PCM_DEV_ACTIVE property on this client's dip; if 36127c478bd9Sstevel@tonic-gate * it's found, it means that this client can control the card 36137c478bd9Sstevel@tonic-gate * that is currently in the socket. This is a boolean 36147c478bd9Sstevel@tonic-gate * property managed by Socket Services. 36157c478bd9Sstevel@tonic-gate */ 36167c478bd9Sstevel@tonic-gate if (ddi_getprop(DDI_DEV_T_ANY, client->dip, (DDI_PROP_CANSLEEP | 36177c478bd9Sstevel@tonic-gate DDI_PROP_NOTPROM), 36187c478bd9Sstevel@tonic-gate PCM_DEV_ACTIVE, NULL)) { 36197c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36207c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36217c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_card_for_client: client handle 0x%x " 36227c478bd9Sstevel@tonic-gate "driver [%s] says %s found\n", 36237c478bd9Sstevel@tonic-gate (int)client->client_handle, 36247c478bd9Sstevel@tonic-gate client->driver_name, 36257c478bd9Sstevel@tonic-gate PCM_DEV_ACTIVE); 36267c478bd9Sstevel@tonic-gate } 36277c478bd9Sstevel@tonic-gate #endif 36287c478bd9Sstevel@tonic-gate return (1); 36297c478bd9Sstevel@tonic-gate } 36307c478bd9Sstevel@tonic-gate 36317c478bd9Sstevel@tonic-gate return (0); 36327c478bd9Sstevel@tonic-gate } 36337c478bd9Sstevel@tonic-gate 36347c478bd9Sstevel@tonic-gate /* 36357c478bd9Sstevel@tonic-gate * cs_ss_thread - This is the Socket Services work thread. We fire off 36367c478bd9Sstevel@tonic-gate * any calls to Socket Services here that we want 36377c478bd9Sstevel@tonic-gate * to run on a thread that is seperate from the 36387c478bd9Sstevel@tonic-gate * per-socket event thread. 36397c478bd9Sstevel@tonic-gate */ 36407c478bd9Sstevel@tonic-gate static void 36417c478bd9Sstevel@tonic-gate cs_ss_thread(uint32_t sn) 36427c478bd9Sstevel@tonic-gate { 36437c478bd9Sstevel@tonic-gate cs_socket_t *sp; 36447c478bd9Sstevel@tonic-gate 36457c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 36467c478bd9Sstevel@tonic-gate return; 36477c478bd9Sstevel@tonic-gate 36487c478bd9Sstevel@tonic-gate /* 36497c478bd9Sstevel@tonic-gate * Tell CPR that we've started a new thread. 36507c478bd9Sstevel@tonic-gate */ 36517c478bd9Sstevel@tonic-gate CALLB_CPR_INIT(&sp->cprinfo_ss, &sp->ss_thread_lock, 36527c478bd9Sstevel@tonic-gate callb_generic_cpr, "cs_ss_thread"); 36537c478bd9Sstevel@tonic-gate 36547c478bd9Sstevel@tonic-gate mutex_enter(&sp->ss_thread_lock); 36557c478bd9Sstevel@tonic-gate 36567c478bd9Sstevel@tonic-gate for (;;) { 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_BEGIN(&sp->cprinfo_ss); 36597c478bd9Sstevel@tonic-gate cv_wait(&sp->ss_thread_cv, &sp->ss_thread_lock); 36607c478bd9Sstevel@tonic-gate CALLB_CPR_SAFE_END(&sp->cprinfo_ss, &sp->ss_thread_lock); 36617c478bd9Sstevel@tonic-gate 36627c478bd9Sstevel@tonic-gate /* 36637c478bd9Sstevel@tonic-gate * Check to see if there are any special thread operations 36647c478bd9Sstevel@tonic-gate * that we are being asked to perform. 36657c478bd9Sstevel@tonic-gate */ 36667c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_EXIT) { 36677c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36687c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36697c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 36707c478bd9Sstevel@tonic-gate "SOCKET_THREAD_EXIT\n", 36717c478bd9Sstevel@tonic-gate sp->socket_num); 36727c478bd9Sstevel@tonic-gate } 36737c478bd9Sstevel@tonic-gate #endif 36747c478bd9Sstevel@tonic-gate CALLB_CPR_EXIT(&sp->cprinfo_ss); 36757c478bd9Sstevel@tonic-gate cv_broadcast(&sp->ss_caller_cv); /* wake up cs_deinit */ 36767c478bd9Sstevel@tonic-gate mutex_exit(&sp->ss_thread_lock); 36777c478bd9Sstevel@tonic-gate return; 36787c478bd9Sstevel@tonic-gate } /* if (SOCKET_THREAD_EXIT) */ 36797c478bd9Sstevel@tonic-gate 36807c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 36817c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 36827c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d " 36837c478bd9Sstevel@tonic-gate "ss_thread_state = 0x%x\n", 36847c478bd9Sstevel@tonic-gate (int)sp->socket_num, 36857c478bd9Sstevel@tonic-gate (int)sp->ss_thread_state); 36867c478bd9Sstevel@tonic-gate } 36877c478bd9Sstevel@tonic-gate #endif 36887c478bd9Sstevel@tonic-gate 36897c478bd9Sstevel@tonic-gate /* 36907c478bd9Sstevel@tonic-gate * Call SocketServices(CSCISInit) to have SS parse the 36917c478bd9Sstevel@tonic-gate * CIS and load/attach any client drivers necessary. 36927c478bd9Sstevel@tonic-gate */ 36937c478bd9Sstevel@tonic-gate if (sp->ss_thread_state & SOCKET_THREAD_CSCISInit) { 36947c478bd9Sstevel@tonic-gate 36957c478bd9Sstevel@tonic-gate sp->ss_thread_state &= ~SOCKET_THREAD_CSCISInit; 36967c478bd9Sstevel@tonic-gate 36977c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_CARD_INSERTED)) { 36987c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread %d " 36997c478bd9Sstevel@tonic-gate "card NOT inserted\n", 37007c478bd9Sstevel@tonic-gate sp->socket_num); 37017c478bd9Sstevel@tonic-gate } 37027c478bd9Sstevel@tonic-gate 37037c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 37047c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 37057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_thread: socket %d calling " 37067c478bd9Sstevel@tonic-gate "CSCISInit\n", sp->socket_num); 37077c478bd9Sstevel@tonic-gate } 37087c478bd9Sstevel@tonic-gate #endif 37097c478bd9Sstevel@tonic-gate 37107c478bd9Sstevel@tonic-gate /* 37117c478bd9Sstevel@tonic-gate * Tell SS that we have a complete CIS and that it can now 37127c478bd9Sstevel@tonic-gate * be parsed. 37137c478bd9Sstevel@tonic-gate * Note that in some cases the client driver may block in 37147c478bd9Sstevel@tonic-gate * their attach routine, causing this call to block until 37157c478bd9Sstevel@tonic-gate * the client completes their attach. 37167c478bd9Sstevel@tonic-gate */ 37177c478bd9Sstevel@tonic-gate SocketServices(CSCISInit, sp->socket_num); 37187c478bd9Sstevel@tonic-gate 37197c478bd9Sstevel@tonic-gate /* 37207c478bd9Sstevel@tonic-gate * Set the CS_EVENT_SS_UPDATED event for this socket so that the 37217c478bd9Sstevel@tonic-gate * event thread can continue any card insertion processing 37227c478bd9Sstevel@tonic-gate * that it has to do. 37237c478bd9Sstevel@tonic-gate */ 37247c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 37257c478bd9Sstevel@tonic-gate sp->events |= CS_EVENT_SS_UPDATED; 37267c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 37277c478bd9Sstevel@tonic-gate 37287c478bd9Sstevel@tonic-gate /* 37297c478bd9Sstevel@tonic-gate * Wake up this socket's event thread so that clients can 37307c478bd9Sstevel@tonic-gate * continue any card insertion or attach processing 37317c478bd9Sstevel@tonic-gate * that they need to do. 37327c478bd9Sstevel@tonic-gate */ 37337c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 37347c478bd9Sstevel@tonic-gate } /* if ST_CSCISInit */ 37357c478bd9Sstevel@tonic-gate 37367c478bd9Sstevel@tonic-gate } /* for (;;) */ 37377c478bd9Sstevel@tonic-gate } 37387c478bd9Sstevel@tonic-gate 37397c478bd9Sstevel@tonic-gate /* 37407c478bd9Sstevel@tonic-gate * cs_request_socket_mask - set the client's event mask as well as causes 37417c478bd9Sstevel@tonic-gate * any events pending from RegisterClient to 37427c478bd9Sstevel@tonic-gate * be scheduled to be sent to the client 37437c478bd9Sstevel@tonic-gate */ 37447c478bd9Sstevel@tonic-gate static int 37457c478bd9Sstevel@tonic-gate cs_request_socket_mask(client_handle_t client_handle, 37467c478bd9Sstevel@tonic-gate request_socket_mask_t *se) 37477c478bd9Sstevel@tonic-gate { 37487c478bd9Sstevel@tonic-gate cs_socket_t *sp; 37497c478bd9Sstevel@tonic-gate client_t *client; 37507c478bd9Sstevel@tonic-gate int error; 37517c478bd9Sstevel@tonic-gate int client_lock_acquired; 37527c478bd9Sstevel@tonic-gate 37537c478bd9Sstevel@tonic-gate /* 37547c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 37557c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 37567c478bd9Sstevel@tonic-gate */ 37577c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 37587c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 37597c478bd9Sstevel@tonic-gate 37607c478bd9Sstevel@tonic-gate /* 37617c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 37627c478bd9Sstevel@tonic-gate */ 37637c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 37647c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 37657c478bd9Sstevel@tonic-gate 37667c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 37677c478bd9Sstevel@tonic-gate 37687c478bd9Sstevel@tonic-gate /* 37697c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 37707c478bd9Sstevel@tonic-gate */ 37717c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 37727c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 37737c478bd9Sstevel@tonic-gate return (error); 37747c478bd9Sstevel@tonic-gate } 37757c478bd9Sstevel@tonic-gate 37767c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 37777c478bd9Sstevel@tonic-gate 37787c478bd9Sstevel@tonic-gate /* 37797c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 37807c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 37817c478bd9Sstevel@tonic-gate */ 37827c478bd9Sstevel@tonic-gate if (client->flags & REQ_SOCKET_MASK_DONE) { 37837c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 37847c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 37857c478bd9Sstevel@tonic-gate return (CS_IN_USE); 37867c478bd9Sstevel@tonic-gate } 37877c478bd9Sstevel@tonic-gate 37887c478bd9Sstevel@tonic-gate /* 37897c478bd9Sstevel@tonic-gate * Set up the event mask information; we copy this directly from 37907c478bd9Sstevel@tonic-gate * the client; since we are the only source of events, any 37917c478bd9Sstevel@tonic-gate * bogus bits that the client puts in here won't matter 37927c478bd9Sstevel@tonic-gate * because we'll never look at them. 37937c478bd9Sstevel@tonic-gate */ 37947c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 37957c478bd9Sstevel@tonic-gate 37967c478bd9Sstevel@tonic-gate /* 37977c478bd9Sstevel@tonic-gate * If RegisterClient left us some events to process, set these 37987c478bd9Sstevel@tonic-gate * events up here. 37997c478bd9Sstevel@tonic-gate */ 38007c478bd9Sstevel@tonic-gate if (client->pending_events) { 38017c478bd9Sstevel@tonic-gate client->events |= client->pending_events; 38027c478bd9Sstevel@tonic-gate client->pending_events = 0; 38037c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 38047c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 38057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: client_handle = 0x%x " 38067c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 38077c478bd9Sstevel@tonic-gate (int)client->client_handle, 38087c478bd9Sstevel@tonic-gate client->driver_name, 38097c478bd9Sstevel@tonic-gate (int)client->events); 38107c478bd9Sstevel@tonic-gate } 38117c478bd9Sstevel@tonic-gate #endif 38127c478bd9Sstevel@tonic-gate } 38137c478bd9Sstevel@tonic-gate 38147c478bd9Sstevel@tonic-gate client->flags |= REQ_SOCKET_MASK_DONE; 38157c478bd9Sstevel@tonic-gate 38167c478bd9Sstevel@tonic-gate /* 38177c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 38187c478bd9Sstevel@tonic-gate * to generate the appropriate events. 38197c478bd9Sstevel@tonic-gate */ 38207c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 38217c478bd9Sstevel@tonic-gate 38227c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 38237c478bd9Sstevel@tonic-gate 38247c478bd9Sstevel@tonic-gate /* 38257c478bd9Sstevel@tonic-gate * Wakeup the event thread if there are any client events to process. 38267c478bd9Sstevel@tonic-gate */ 38277c478bd9Sstevel@tonic-gate if (client->events) { 38287c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 38297c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 38307c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 38317c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_socket_mask: did cv_broadcast for " 38327c478bd9Sstevel@tonic-gate "client_handle = 0x%x " 38337c478bd9Sstevel@tonic-gate "driver_name = [%s] events = 0x%x\n", 38347c478bd9Sstevel@tonic-gate (int)client->client_handle, 38357c478bd9Sstevel@tonic-gate client->driver_name, 38367c478bd9Sstevel@tonic-gate (int)client->events); 38377c478bd9Sstevel@tonic-gate } 38387c478bd9Sstevel@tonic-gate #endif 38397c478bd9Sstevel@tonic-gate 38407c478bd9Sstevel@tonic-gate } 38417c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38427c478bd9Sstevel@tonic-gate 38437c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 38447c478bd9Sstevel@tonic-gate } 38457c478bd9Sstevel@tonic-gate 38467c478bd9Sstevel@tonic-gate /* 38477c478bd9Sstevel@tonic-gate * cs_release_socket_mask - clear the client's event mask 38487c478bd9Sstevel@tonic-gate * 38497c478bd9Sstevel@tonic-gate * Once this function returns, the client is guaranteed 38507c478bd9Sstevel@tonic-gate * not to get any more event callbacks. 38517c478bd9Sstevel@tonic-gate */ 38527c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 38537c478bd9Sstevel@tonic-gate static int 38547c478bd9Sstevel@tonic-gate cs_release_socket_mask(client_handle_t client_handle, 38557c478bd9Sstevel@tonic-gate release_socket_mask_t *rsm) 38567c478bd9Sstevel@tonic-gate { 38577c478bd9Sstevel@tonic-gate cs_socket_t *sp; 38587c478bd9Sstevel@tonic-gate client_t *client; 38597c478bd9Sstevel@tonic-gate int error; 38607c478bd9Sstevel@tonic-gate int client_lock_acquired; 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate /* 38637c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 38647c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 38657c478bd9Sstevel@tonic-gate */ 38667c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 38677c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 38687c478bd9Sstevel@tonic-gate 38697c478bd9Sstevel@tonic-gate /* 38707c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 38717c478bd9Sstevel@tonic-gate */ 38727c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 38737c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 38767c478bd9Sstevel@tonic-gate 38777c478bd9Sstevel@tonic-gate /* 38787c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 38797c478bd9Sstevel@tonic-gate */ 38807c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 38817c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38827c478bd9Sstevel@tonic-gate return (error); 38837c478bd9Sstevel@tonic-gate } 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 38867c478bd9Sstevel@tonic-gate 38877c478bd9Sstevel@tonic-gate /* 38887c478bd9Sstevel@tonic-gate * If this client has already done a RequestSocketMask without 38897c478bd9Sstevel@tonic-gate * a corresponding ReleaseSocketMask, then return an error. 38907c478bd9Sstevel@tonic-gate */ 38917c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 38927c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 38937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 38947c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 38957c478bd9Sstevel@tonic-gate } 38967c478bd9Sstevel@tonic-gate 38977c478bd9Sstevel@tonic-gate /* 38987c478bd9Sstevel@tonic-gate * Clear both the client event mask and the global event mask. 38997c478bd9Sstevel@tonic-gate * We clear both since the semantics of this function are 39007c478bd9Sstevel@tonic-gate * that once it returns, the client will not be called at 39017c478bd9Sstevel@tonic-gate * it's event handler for any events until RequestSocketMask 39027c478bd9Sstevel@tonic-gate * is called again. 39037c478bd9Sstevel@tonic-gate */ 39047c478bd9Sstevel@tonic-gate client->event_mask = 0; 39057c478bd9Sstevel@tonic-gate client->global_mask = 0; 39067c478bd9Sstevel@tonic-gate client->flags &= ~REQ_SOCKET_MASK_DONE; 39077c478bd9Sstevel@tonic-gate 39087c478bd9Sstevel@tonic-gate /* 39097c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 39107c478bd9Sstevel@tonic-gate * to generate the appropriate events. 39117c478bd9Sstevel@tonic-gate */ 39127c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 39137c478bd9Sstevel@tonic-gate 39147c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39157c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39167c478bd9Sstevel@tonic-gate 39177c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39187c478bd9Sstevel@tonic-gate } 39197c478bd9Sstevel@tonic-gate 39207c478bd9Sstevel@tonic-gate /* 39217c478bd9Sstevel@tonic-gate * cs_get_event_mask - return the event mask for this client 39227c478bd9Sstevel@tonic-gate */ 39237c478bd9Sstevel@tonic-gate static int 39247c478bd9Sstevel@tonic-gate cs_get_event_mask(client_handle_t client_handle, sockevent_t *se) 39257c478bd9Sstevel@tonic-gate { 39267c478bd9Sstevel@tonic-gate cs_socket_t *sp; 39277c478bd9Sstevel@tonic-gate client_t *client; 39287c478bd9Sstevel@tonic-gate int error; 39297c478bd9Sstevel@tonic-gate int client_lock_acquired; 39307c478bd9Sstevel@tonic-gate 39317c478bd9Sstevel@tonic-gate /* 39327c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 39337c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 39347c478bd9Sstevel@tonic-gate */ 39357c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 39367c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39377c478bd9Sstevel@tonic-gate 39387c478bd9Sstevel@tonic-gate /* 39397c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 39407c478bd9Sstevel@tonic-gate */ 39417c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 39427c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 39437c478bd9Sstevel@tonic-gate 39447c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 39457c478bd9Sstevel@tonic-gate 39467c478bd9Sstevel@tonic-gate /* 39477c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 39487c478bd9Sstevel@tonic-gate */ 39497c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 39507c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39517c478bd9Sstevel@tonic-gate return (error); 39527c478bd9Sstevel@tonic-gate } 39537c478bd9Sstevel@tonic-gate 39547c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 39557c478bd9Sstevel@tonic-gate 39567c478bd9Sstevel@tonic-gate #ifdef XXX 39577c478bd9Sstevel@tonic-gate /* 39587c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 39597c478bd9Sstevel@tonic-gate * for this client, then return an error. 39607c478bd9Sstevel@tonic-gate * XXX - how can a client get their event masks if their card 39617c478bd9Sstevel@tonic-gate * goes away? 39627c478bd9Sstevel@tonic-gate */ 39637c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 39647c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39657c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39667c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 39677c478bd9Sstevel@tonic-gate } 39687c478bd9Sstevel@tonic-gate #endif 39697c478bd9Sstevel@tonic-gate 39707c478bd9Sstevel@tonic-gate /* 39717c478bd9Sstevel@tonic-gate * We are only allowed to get the client event mask if a 39727c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 39737c478bd9Sstevel@tonic-gate * are allowed to get the global event mask at any 39747c478bd9Sstevel@tonic-gate * time. 39757c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 39767c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 39777c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 39787c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 39797c478bd9Sstevel@tonic-gate * GetEventMask. 39807c478bd9Sstevel@tonic-gate */ 39817c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 39827c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 39837c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39847c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39857c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 39867c478bd9Sstevel@tonic-gate } 39877c478bd9Sstevel@tonic-gate se->EventMask = client->event_mask; 39887c478bd9Sstevel@tonic-gate } else { 39897c478bd9Sstevel@tonic-gate se->EventMask = client->global_mask; 39907c478bd9Sstevel@tonic-gate } 39917c478bd9Sstevel@tonic-gate 39927c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 39937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 39947c478bd9Sstevel@tonic-gate 39957c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 39967c478bd9Sstevel@tonic-gate } 39977c478bd9Sstevel@tonic-gate 39987c478bd9Sstevel@tonic-gate /* 39997c478bd9Sstevel@tonic-gate * cs_set_event_mask - set the event mask for this client 40007c478bd9Sstevel@tonic-gate */ 40017c478bd9Sstevel@tonic-gate static int 40027c478bd9Sstevel@tonic-gate cs_set_event_mask(client_handle_t client_handle, sockevent_t *se) 40037c478bd9Sstevel@tonic-gate { 40047c478bd9Sstevel@tonic-gate cs_socket_t *sp; 40057c478bd9Sstevel@tonic-gate client_t *client; 40067c478bd9Sstevel@tonic-gate int error; 40077c478bd9Sstevel@tonic-gate int client_lock_acquired; 40087c478bd9Sstevel@tonic-gate 40097c478bd9Sstevel@tonic-gate /* 40107c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 40117c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 40127c478bd9Sstevel@tonic-gate */ 40137c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 40147c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 40157c478bd9Sstevel@tonic-gate 40167c478bd9Sstevel@tonic-gate /* 40177c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 40187c478bd9Sstevel@tonic-gate */ 40197c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 40207c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 40217c478bd9Sstevel@tonic-gate 40227c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 40237c478bd9Sstevel@tonic-gate 40247c478bd9Sstevel@tonic-gate /* 40257c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 40267c478bd9Sstevel@tonic-gate */ 40277c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 40287c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40297c478bd9Sstevel@tonic-gate return (error); 40307c478bd9Sstevel@tonic-gate } 40317c478bd9Sstevel@tonic-gate 40327c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 40337c478bd9Sstevel@tonic-gate 40347c478bd9Sstevel@tonic-gate #ifdef XXX 40357c478bd9Sstevel@tonic-gate /* 40367c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 40377c478bd9Sstevel@tonic-gate * for this client, then return an error. 40387c478bd9Sstevel@tonic-gate */ 40397c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 40407c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40417c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40427c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 40437c478bd9Sstevel@tonic-gate } 40447c478bd9Sstevel@tonic-gate #endif 40457c478bd9Sstevel@tonic-gate 40467c478bd9Sstevel@tonic-gate /* 40477c478bd9Sstevel@tonic-gate * We are only allowed to set the client event mask if a 40487c478bd9Sstevel@tonic-gate * RequestSocketMask has been called previously. We 40497c478bd9Sstevel@tonic-gate * are allowed to set the global event mask at any 40507c478bd9Sstevel@tonic-gate * time. 40517c478bd9Sstevel@tonic-gate * The global event mask is initially set by the client 40527c478bd9Sstevel@tonic-gate * in the call to RegisterClient. The client event 40537c478bd9Sstevel@tonic-gate * mask is set by the client in calls to SetEventMask 40547c478bd9Sstevel@tonic-gate * and RequestSocketMask and gotten in calls to 40557c478bd9Sstevel@tonic-gate * GetEventMask. 40567c478bd9Sstevel@tonic-gate */ 40577c478bd9Sstevel@tonic-gate if (se->Attributes & CONF_EVENT_MASK_CLIENT) { 40587c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_SOCKET_MASK_DONE)) { 40597c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40607c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40617c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 40627c478bd9Sstevel@tonic-gate } 40637c478bd9Sstevel@tonic-gate client->event_mask = se->EventMask; 40647c478bd9Sstevel@tonic-gate } else { 40657c478bd9Sstevel@tonic-gate client->global_mask = se->EventMask; 40667c478bd9Sstevel@tonic-gate } 40677c478bd9Sstevel@tonic-gate 40687c478bd9Sstevel@tonic-gate /* 40697c478bd9Sstevel@tonic-gate * Merge all the clients' event masks and set the socket 40707c478bd9Sstevel@tonic-gate * to generate the appropriate events. 40717c478bd9Sstevel@tonic-gate */ 40727c478bd9Sstevel@tonic-gate (void) cs_set_socket_event_mask(sp, cs_merge_event_masks(sp, client)); 40737c478bd9Sstevel@tonic-gate 40747c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 40757c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 40767c478bd9Sstevel@tonic-gate 40777c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 40787c478bd9Sstevel@tonic-gate } 40797c478bd9Sstevel@tonic-gate 40807c478bd9Sstevel@tonic-gate /* 40817c478bd9Sstevel@tonic-gate * cs_read_event_status - handles PRR events and returns card status 40827c478bd9Sstevel@tonic-gate * 40837c478bd9Sstevel@tonic-gate * calling: *sp - socket struct point 40847c478bd9Sstevel@tonic-gate * *client - client to check events on 40857c478bd9Sstevel@tonic-gate * *revent - pointer to event mask to update; if NULL, will 40867c478bd9Sstevel@tonic-gate * not be updated, if non-NULL, will be updated 40877c478bd9Sstevel@tonic-gate * with CS-format events; it is NOT necessary 40887c478bd9Sstevel@tonic-gate * to clear this value before calling this 40897c478bd9Sstevel@tonic-gate * function 40907c478bd9Sstevel@tonic-gate * *gs - pointer to a get_ss_status_t used for the SS GetStatus 40917c478bd9Sstevel@tonic-gate * call; it is not necessary to initialize any 40927c478bd9Sstevel@tonic-gate * members in this structure; set to NULL if 40937c478bd9Sstevel@tonic-gate * not used 40947c478bd9Sstevel@tonic-gate * flags - if CS_RES_IGNORE_NO_CARD is set, the check for a 40957c478bd9Sstevel@tonic-gate * card present will not be done 40967c478bd9Sstevel@tonic-gate * 40977c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 40987c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in the socket and the flags arg 40997c478bd9Sstevel@tonic-gate * is not set to CS_RES_IGNORE_NO_CARD 41007c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if the SS_GetStatus function returned an 41017c478bd9Sstevel@tonic-gate * error 41027c478bd9Sstevel@tonic-gate * 41037c478bd9Sstevel@tonic-gate * Note that if the client that configured this socket has told us that 41047c478bd9Sstevel@tonic-gate * the READY pin in the PRR isn't valid and the socket is in IO 41057c478bd9Sstevel@tonic-gate * mode, we always return that the card is READY. 41067c478bd9Sstevel@tonic-gate * 41077c478bd9Sstevel@tonic-gate * Note that if gs is not NULL, the current card state will be returned 41087c478bd9Sstevel@tonic-gate * in the gs->CardState member; this will always reflect the 41097c478bd9Sstevel@tonic-gate * current card state and the state will come from both the 41107c478bd9Sstevel@tonic-gate * SS_GetStatus call and the PRR, whichever is appropriate for 41117c478bd9Sstevel@tonic-gate * the mode that the socket is currently in. 41127c478bd9Sstevel@tonic-gate */ 41137c478bd9Sstevel@tonic-gate static int 41147c478bd9Sstevel@tonic-gate cs_read_event_status(cs_socket_t *sp, client_t *client, event_t *revent, 41157c478bd9Sstevel@tonic-gate get_ss_status_t *gs, int flags) 41167c478bd9Sstevel@tonic-gate { 41177c478bd9Sstevel@tonic-gate cfg_regs_t prrd = 0; 41187c478bd9Sstevel@tonic-gate 41197c478bd9Sstevel@tonic-gate /* 41207c478bd9Sstevel@tonic-gate * SOCKET_IS_IO will only be set if a RequestConfiguration 41217c478bd9Sstevel@tonic-gate * has been done by at least one client on this socket. 41227c478bd9Sstevel@tonic-gate * If there isn't a card in the socket or the caller wants to ignore 41237c478bd9Sstevel@tonic-gate * whether the card is in the socket or not, get the current 41247c478bd9Sstevel@tonic-gate * card status. 41257c478bd9Sstevel@tonic-gate */ 41267c478bd9Sstevel@tonic-gate if ((sp->flags & SOCKET_CARD_INSERTED) || 41277c478bd9Sstevel@tonic-gate (flags & CS_RES_IGNORE_NO_CARD)) { 41287c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 41297c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 41307c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 41317c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 41327c478bd9Sstevel@tonic-gate 41337c478bd9Sstevel@tonic-gate /* 41347c478bd9Sstevel@tonic-gate * Get a handle to the CIS window 41357c478bd9Sstevel@tonic-gate */ 41367c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 41377c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 41387c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: socket %d " 41397c478bd9Sstevel@tonic-gate "can't init CIS window\n", 41407c478bd9Sstevel@tonic-gate sp->socket_num); 41417c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 41427c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 41437c478bd9Sstevel@tonic-gate 41447c478bd9Sstevel@tonic-gate prrd = csx_Get8(cis_handle, client->config_regs.prr_p); 41457c478bd9Sstevel@tonic-gate prrd &= client->pin; 41467c478bd9Sstevel@tonic-gate 41477c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 41487c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 41497c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: " 41507c478bd9Sstevel@tonic-gate "prrd 0x%x client->pin 0x%x\n", 41517c478bd9Sstevel@tonic-gate (int)prrd, 41527c478bd9Sstevel@tonic-gate client->pin); 41537c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR(1) = [%s%s%s%s%s%s%s%s]\n", 41547c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 41557c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 41567c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 41577c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 41587c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 41597c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 41607c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 41617c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 41627c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 41637c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 41647c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 41657c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 41667c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 41677c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 41687c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 41697c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 41707c478bd9Sstevel@tonic-gate } 41717c478bd9Sstevel@tonic-gate #endif 41727c478bd9Sstevel@tonic-gate 41737c478bd9Sstevel@tonic-gate /* 41747c478bd9Sstevel@tonic-gate * The caller wants the event changes sent back and 41757c478bd9Sstevel@tonic-gate * the PRR event change bits cleared. 41767c478bd9Sstevel@tonic-gate */ 41777c478bd9Sstevel@tonic-gate if (revent) { 41787c478bd9Sstevel@tonic-gate get_socket_t get_socket; 41797c478bd9Sstevel@tonic-gate set_socket_t set_socket; 41807c478bd9Sstevel@tonic-gate 41817c478bd9Sstevel@tonic-gate /* 41827c478bd9Sstevel@tonic-gate * Bug ID: 1193636 - Card Services sends bogus 41837c478bd9Sstevel@tonic-gate * events on CS_EVENT_STATUS_CHANGE events 41847c478bd9Sstevel@tonic-gate * Clear this before we OR-in any values. 41857c478bd9Sstevel@tonic-gate */ 41867c478bd9Sstevel@tonic-gate *revent = 0; 41877c478bd9Sstevel@tonic-gate 41887c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_WP_EVENT, PRR_WP_STATUS, 41897c478bd9Sstevel@tonic-gate CS_EVENT_WRITE_PROTECT, *revent); 41907c478bd9Sstevel@tonic-gate 41917c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_READY_EVENT, PRR_READY_STATUS, 41927c478bd9Sstevel@tonic-gate CS_EVENT_CARD_READY, *revent); 41937c478bd9Sstevel@tonic-gate 41947c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD2_EVENT, PRR_BVD2_STATUS, 41957c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_LOW, *revent); 41967c478bd9Sstevel@tonic-gate 41977c478bd9Sstevel@tonic-gate PRR_EVENT(prrd, PRR_BVD1_EVENT, PRR_BVD1_STATUS, 41987c478bd9Sstevel@tonic-gate CS_EVENT_BATTERY_DEAD, *revent); 41997c478bd9Sstevel@tonic-gate 42007c478bd9Sstevel@tonic-gate 42017c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 42027c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 42037c478bd9Sstevel@tonic-gate 42047c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "PRR() = [%s%s%s%s%s%s%s%s]\n", 42057c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_STATUS)? 42067c478bd9Sstevel@tonic-gate "PRR_WP_STATUS ":""), 42077c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_STATUS)? 42087c478bd9Sstevel@tonic-gate "PRR_READY_STATUS ":""), 42097c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_STATUS)? 42107c478bd9Sstevel@tonic-gate "PRR_BVD2_STATUS ":""), 42117c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_STATUS)? 42127c478bd9Sstevel@tonic-gate "PRR_BVD1_STATUS ":""), 42137c478bd9Sstevel@tonic-gate ((prrd & PRR_WP_EVENT)? 42147c478bd9Sstevel@tonic-gate "PRR_WP_EVENT ":""), 42157c478bd9Sstevel@tonic-gate ((prrd & PRR_READY_EVENT)? 42167c478bd9Sstevel@tonic-gate "PRR_READY_EVENT ":""), 42177c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD2_EVENT)? 42187c478bd9Sstevel@tonic-gate "PRR_BVD2_EVENT ":""), 42197c478bd9Sstevel@tonic-gate ((prrd & PRR_BVD1_EVENT)? 42207c478bd9Sstevel@tonic-gate "PRR_BVD1_EVENT ":"")); 42217c478bd9Sstevel@tonic-gate } 42227c478bd9Sstevel@tonic-gate #endif 42237c478bd9Sstevel@tonic-gate 42247c478bd9Sstevel@tonic-gate if (prrd) 42257c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, client->config_regs.prr_p, 42267c478bd9Sstevel@tonic-gate prrd); 42277c478bd9Sstevel@tonic-gate 42287c478bd9Sstevel@tonic-gate /* 42297c478bd9Sstevel@tonic-gate * We now have to reenable the status change interrupts 42307c478bd9Sstevel@tonic-gate * if there are any valid bits in the PRR. Since 42317c478bd9Sstevel@tonic-gate * the BVD1 signal becomes the STATUS_CHANGE 42327c478bd9Sstevel@tonic-gate * signal when the socket is in IO mode, we just 42337c478bd9Sstevel@tonic-gate * have to set the SBM_BVD1 enable bit in the 42347c478bd9Sstevel@tonic-gate * event mask. 42357c478bd9Sstevel@tonic-gate */ 42367c478bd9Sstevel@tonic-gate if (client->pin) { 42377c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 42387c478bd9Sstevel@tonic-gate SocketServices(SS_GetSocket, &get_socket); 42397c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 42407c478bd9Sstevel@tonic-gate set_socket.SCIntMask = 42417c478bd9Sstevel@tonic-gate get_socket.SCIntMask | SBM_BVD1; 42427c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 42437c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 42447c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 42457c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 42467c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 42477c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 42487c478bd9Sstevel@tonic-gate set_socket.State = get_socket.state; 42497c478bd9Sstevel@tonic-gate SocketServices(SS_SetSocket, &set_socket); 42507c478bd9Sstevel@tonic-gate } /* if (client->pin) */ 42517c478bd9Sstevel@tonic-gate } /* if (revent) */ 42527c478bd9Sstevel@tonic-gate 42537c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 42547c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 42557c478bd9Sstevel@tonic-gate 42567c478bd9Sstevel@tonic-gate /* 42577c478bd9Sstevel@tonic-gate * The caller wants the current card state; we just read 42587c478bd9Sstevel@tonic-gate * it and return a copy of it but do not clear any of 42597c478bd9Sstevel@tonic-gate * the event changed bits (if we're reading the PRR). 42607c478bd9Sstevel@tonic-gate */ 42617c478bd9Sstevel@tonic-gate if (gs) { 42627c478bd9Sstevel@tonic-gate gs->socket = sp->socket_num; 42637c478bd9Sstevel@tonic-gate gs->CardState = 0; 42647c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetStatus, gs) != SUCCESS) 42657c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 42667c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_IO) { 42677c478bd9Sstevel@tonic-gate /* 42687c478bd9Sstevel@tonic-gate * If the socket is in IO mode, then clear the 42697c478bd9Sstevel@tonic-gate * gs->CardState bits that are now in the PRR 42707c478bd9Sstevel@tonic-gate */ 42717c478bd9Sstevel@tonic-gate gs->CardState &= ~(SBM_WP | SBM_BVD1 | 42727c478bd9Sstevel@tonic-gate SBM_BVD2 | SBM_RDYBSY); 42737c478bd9Sstevel@tonic-gate 42747c478bd9Sstevel@tonic-gate /* 42757c478bd9Sstevel@tonic-gate * Convert PRR status to SS_GetStatus status 42767c478bd9Sstevel@tonic-gate */ 42777c478bd9Sstevel@tonic-gate if (prrd & PRR_WP_STATUS) 42787c478bd9Sstevel@tonic-gate gs->CardState |= SBM_WP; 42797c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD2_STATUS) 42807c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD2; 42817c478bd9Sstevel@tonic-gate if (prrd & PRR_BVD1_STATUS) 42827c478bd9Sstevel@tonic-gate gs->CardState |= SBM_BVD1; 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate /* 42857c478bd9Sstevel@tonic-gate * If the client has indicated that there is no 42867c478bd9Sstevel@tonic-gate * PRR or that the READY bit in the PRR isn't 42877c478bd9Sstevel@tonic-gate * valid, then we simulate the READY bit by 42887c478bd9Sstevel@tonic-gate * always returning READY. 42897c478bd9Sstevel@tonic-gate */ 42907c478bd9Sstevel@tonic-gate if (!(client->present & CONFIG_PINREPL_REG_PRESENT) || 42917c478bd9Sstevel@tonic-gate ((client->present & CONFIG_PINREPL_REG_PRESENT) && 42927c478bd9Sstevel@tonic-gate !((client->pin & 42937c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) == 42947c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT))) || 42957c478bd9Sstevel@tonic-gate (prrd & PRR_READY_STATUS)) 42967c478bd9Sstevel@tonic-gate gs->CardState |= SBM_RDYBSY; 42977c478bd9Sstevel@tonic-gate 42987c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 42997c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 43007c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_read_event_status: prrd 0x%x " 43017c478bd9Sstevel@tonic-gate "client->pin 0x%x " 43027c478bd9Sstevel@tonic-gate "gs->CardState 0x%x\n", 43037c478bd9Sstevel@tonic-gate prrd, client->pin, gs->CardState); 43047c478bd9Sstevel@tonic-gate } 43057c478bd9Sstevel@tonic-gate #endif 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate } /* if (SOCKET_IS_IO) */ 43087c478bd9Sstevel@tonic-gate } /* if (gs) */ 43097c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 43107c478bd9Sstevel@tonic-gate } /* if (SOCKET_CARD_INSERTED) */ 43117c478bd9Sstevel@tonic-gate 43127c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 43137c478bd9Sstevel@tonic-gate } 43147c478bd9Sstevel@tonic-gate 43157c478bd9Sstevel@tonic-gate /* 43167c478bd9Sstevel@tonic-gate * cs_get_status - gets live card status and latched card status changes 43177c478bd9Sstevel@tonic-gate * supports the GetStatus CS call 43187c478bd9Sstevel@tonic-gate * 43197c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 43207c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if the passed client handle is invalid 43217c478bd9Sstevel@tonic-gate * 43227c478bd9Sstevel@tonic-gate * Note: This function resets the latched status values maintained 43237c478bd9Sstevel@tonic-gate * by Socket Services 43247c478bd9Sstevel@tonic-gate */ 43257c478bd9Sstevel@tonic-gate static int 43267c478bd9Sstevel@tonic-gate cs_get_status(client_handle_t client_handle, get_status_t *gs) 43277c478bd9Sstevel@tonic-gate { 43287c478bd9Sstevel@tonic-gate cs_socket_t *sp; 43297c478bd9Sstevel@tonic-gate client_t *client; 43307c478bd9Sstevel@tonic-gate get_ss_status_t get_ss_status; 43317c478bd9Sstevel@tonic-gate get_socket_t get_socket; 43327c478bd9Sstevel@tonic-gate set_socket_t set_socket; 43337c478bd9Sstevel@tonic-gate int error; 43347c478bd9Sstevel@tonic-gate int client_lock_acquired; 43357c478bd9Sstevel@tonic-gate 43367c478bd9Sstevel@tonic-gate /* 43377c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 43387c478bd9Sstevel@tonic-gate * is, we don't do anything except for return success. 43397c478bd9Sstevel@tonic-gate */ 43407c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 43417c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 43427c478bd9Sstevel@tonic-gate 43437c478bd9Sstevel@tonic-gate /* 43447c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 43457c478bd9Sstevel@tonic-gate */ 43467c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 43477c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 43487c478bd9Sstevel@tonic-gate 43497c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 43507c478bd9Sstevel@tonic-gate 43517c478bd9Sstevel@tonic-gate /* 43527c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 43537c478bd9Sstevel@tonic-gate */ 43547c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 43557c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43567c478bd9Sstevel@tonic-gate return (error); 43577c478bd9Sstevel@tonic-gate } 43587c478bd9Sstevel@tonic-gate 43597c478bd9Sstevel@tonic-gate /* 43607c478bd9Sstevel@tonic-gate * Get the current card status as well as the latched card 43617c478bd9Sstevel@tonic-gate * state. Set the CS_RES_IGNORE_NO_CARD so that even 43627c478bd9Sstevel@tonic-gate * if there is no card in the socket we'll still get 43637c478bd9Sstevel@tonic-gate * a valid status. 43647c478bd9Sstevel@tonic-gate * Note that it is not necessary to initialize any values 43657c478bd9Sstevel@tonic-gate * in the get_ss_status structure. 43667c478bd9Sstevel@tonic-gate */ 43677c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 43687c478bd9Sstevel@tonic-gate if ((error = cs_read_event_status(sp, client, NULL, &get_ss_status, 43697c478bd9Sstevel@tonic-gate CS_RES_IGNORE_NO_CARD)) != CS_SUCCESS) { 43707c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 43717c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43727c478bd9Sstevel@tonic-gate return (error); 43737c478bd9Sstevel@tonic-gate } 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 43767c478bd9Sstevel@tonic-gate 43777c478bd9Sstevel@tonic-gate gs->raw_CardState = cs_sbm2cse(get_ss_status.CardState); 43787c478bd9Sstevel@tonic-gate 43797c478bd9Sstevel@tonic-gate /* 43807c478bd9Sstevel@tonic-gate * Assign the "live" card state to the "real" card state. If there's 43817c478bd9Sstevel@tonic-gate * no card in the socket or the card in the socket is not 43827c478bd9Sstevel@tonic-gate * for this client, then we lie and tell the caller that the 43837c478bd9Sstevel@tonic-gate * card is not inserted. 43847c478bd9Sstevel@tonic-gate */ 43857c478bd9Sstevel@tonic-gate gs->CardState = gs->raw_CardState; 43867c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) 43877c478bd9Sstevel@tonic-gate gs->CardState &= ~CS_EVENT_CARD_INSERTION; 43887c478bd9Sstevel@tonic-gate 43897c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 43907c478bd9Sstevel@tonic-gate 43917c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 43927c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 43937c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 43947c478bd9Sstevel@tonic-gate 43957c478bd9Sstevel@tonic-gate gs->SocketState = cs_sbm2cse(get_socket.state); 43967c478bd9Sstevel@tonic-gate 43977c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 43987c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 43997c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 44007c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 44017c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 44027c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 44037c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 44047c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 44057c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 44067c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 44077c478bd9Sstevel@tonic-gate 44087c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 44097c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 44107c478bd9Sstevel@tonic-gate 44117c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 44127c478bd9Sstevel@tonic-gate } 44137c478bd9Sstevel@tonic-gate 44147c478bd9Sstevel@tonic-gate /* 44157c478bd9Sstevel@tonic-gate * cs_cse2sbm - converts a CS event mask to an SS (SBM_XXX) event mask 44167c478bd9Sstevel@tonic-gate */ 44177c478bd9Sstevel@tonic-gate static event_t 44187c478bd9Sstevel@tonic-gate cs_cse2sbm(event_t event_mask) 44197c478bd9Sstevel@tonic-gate { 44207c478bd9Sstevel@tonic-gate event_t sbm_event = 0; 44217c478bd9Sstevel@tonic-gate 44227c478bd9Sstevel@tonic-gate /* 44237c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 44247c478bd9Sstevel@tonic-gate */ 44257c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 44267c478bd9Sstevel@tonic-gate sbm_event |= SBM_WP; 44277c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 44287c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD1; 44297c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 44307c478bd9Sstevel@tonic-gate sbm_event |= SBM_BVD2; 44317c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 44327c478bd9Sstevel@tonic-gate sbm_event |= SBM_RDYBSY; 44337c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_LOCK) 44347c478bd9Sstevel@tonic-gate sbm_event |= SBM_LOCKED; 44357c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_EJECTION_REQUEST) 44367c478bd9Sstevel@tonic-gate sbm_event |= SBM_EJECT; 44377c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_INSERTION_REQUEST) 44387c478bd9Sstevel@tonic-gate sbm_event |= SBM_INSERT; 44397c478bd9Sstevel@tonic-gate if (event_mask & (CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL)) 44407c478bd9Sstevel@tonic-gate sbm_event |= SBM_CD; 44417c478bd9Sstevel@tonic-gate 44427c478bd9Sstevel@tonic-gate return (sbm_event); 44437c478bd9Sstevel@tonic-gate } 44447c478bd9Sstevel@tonic-gate 44457c478bd9Sstevel@tonic-gate /* 44467c478bd9Sstevel@tonic-gate * cs_sbm2cse - converts SBM_xxx state to CS event bits 44477c478bd9Sstevel@tonic-gate * 44487c478bd9Sstevel@tonic-gate * This function should never set any of the following bits: 44497c478bd9Sstevel@tonic-gate * 44507c478bd9Sstevel@tonic-gate * CS_EVENT_MTD_REQUEST 44517c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO 44527c478bd9Sstevel@tonic-gate * CS_EVENT_TIMER_EXPIRED 44537c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL 44547c478bd9Sstevel@tonic-gate * CS_EVENT_CARD_REMOVAL_LOWP 44557c478bd9Sstevel@tonic-gate * CS_EVENT_ALL_CLIENTS 44567c478bd9Sstevel@tonic-gate * CS_EVENT_READY_TIMEOUT 44577c478bd9Sstevel@tonic-gate * 44587c478bd9Sstevel@tonic-gate * These bits are defined in the CS_STATUS_XXX series and are 44597c478bd9Sstevel@tonic-gate * used by GetStatus. 44607c478bd9Sstevel@tonic-gate */ 44617c478bd9Sstevel@tonic-gate static uint32_t 44627c478bd9Sstevel@tonic-gate cs_sbm2cse(uint32_t state) 44637c478bd9Sstevel@tonic-gate { 44647c478bd9Sstevel@tonic-gate uint32_t rstate = 0; 44657c478bd9Sstevel@tonic-gate 44667c478bd9Sstevel@tonic-gate /* 44677c478bd9Sstevel@tonic-gate * XXX - we need to handle PM_CHANGE and RESET here as well 44687c478bd9Sstevel@tonic-gate */ 44697c478bd9Sstevel@tonic-gate if (state & SBM_WP) 44707c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_WRITE_PROTECT; 44717c478bd9Sstevel@tonic-gate if (state & SBM_BVD1) 44727c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_DEAD; 44737c478bd9Sstevel@tonic-gate if (state & SBM_BVD2) 44747c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_BATTERY_LOW; 44757c478bd9Sstevel@tonic-gate if (state & SBM_RDYBSY) 44767c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_READY; 44777c478bd9Sstevel@tonic-gate if (state & SBM_LOCKED) 44787c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_LOCK; 44797c478bd9Sstevel@tonic-gate if (state & SBM_EJECT) 44807c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_EJECTION_REQUEST; 44817c478bd9Sstevel@tonic-gate if (state & SBM_INSERT) 44827c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_INSERTION_REQUEST; 44837c478bd9Sstevel@tonic-gate if (state & SBM_CD) 44847c478bd9Sstevel@tonic-gate rstate |= CS_EVENT_CARD_INSERTION; 44857c478bd9Sstevel@tonic-gate 44867c478bd9Sstevel@tonic-gate return (rstate); 44877c478bd9Sstevel@tonic-gate } 44887c478bd9Sstevel@tonic-gate 44897c478bd9Sstevel@tonic-gate /* 44907c478bd9Sstevel@tonic-gate * cs_merge_event_masks - merge the CS global socket event mask with the 44917c478bd9Sstevel@tonic-gate * passed client's event masks 44927c478bd9Sstevel@tonic-gate */ 44937c478bd9Sstevel@tonic-gate static unsigned 44947c478bd9Sstevel@tonic-gate cs_merge_event_masks(cs_socket_t *sp, client_t *client) 44957c478bd9Sstevel@tonic-gate { 44967c478bd9Sstevel@tonic-gate unsigned SCIntMask; 44977c478bd9Sstevel@tonic-gate uint32_t event_mask; 44987c478bd9Sstevel@tonic-gate 44997c478bd9Sstevel@tonic-gate /* 45007c478bd9Sstevel@tonic-gate * We always want to see card detect and status change events. 45017c478bd9Sstevel@tonic-gate */ 45027c478bd9Sstevel@tonic-gate SCIntMask = SBM_CD; 45037c478bd9Sstevel@tonic-gate 45047c478bd9Sstevel@tonic-gate event_mask = client->event_mask | client->global_mask | 45057c478bd9Sstevel@tonic-gate sp->event_mask; 45067c478bd9Sstevel@tonic-gate 45077c478bd9Sstevel@tonic-gate if (!(sp->flags & SOCKET_IS_IO)) { 45087c478bd9Sstevel@tonic-gate SCIntMask |= cs_cse2sbm(event_mask); 45097c478bd9Sstevel@tonic-gate } else { 45107c478bd9Sstevel@tonic-gate /* 45117c478bd9Sstevel@tonic-gate * If the socket is in IO mode and there is a PRR present, 45127c478bd9Sstevel@tonic-gate * then we may need to enable PCE_CARD_STATUS_CHANGE 45137c478bd9Sstevel@tonic-gate * events. 45147c478bd9Sstevel@tonic-gate */ 45157c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 45167c478bd9Sstevel@tonic-gate 45177c478bd9Sstevel@tonic-gate SCIntMask |= (cs_cse2sbm(event_mask) & 45187c478bd9Sstevel@tonic-gate ~(SBM_WP | SBM_BVD1 | SBM_BVD2 | SBM_RDYBSY)); 45197c478bd9Sstevel@tonic-gate 45207c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_WP_STATUS | PRR_WP_EVENT)) == 45217c478bd9Sstevel@tonic-gate (PRR_WP_STATUS | PRR_WP_EVENT)) 45227c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_WRITE_PROTECT) 45237c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45247c478bd9Sstevel@tonic-gate 45257c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_READY_STATUS | PRR_READY_EVENT)) == 45267c478bd9Sstevel@tonic-gate (PRR_READY_STATUS | PRR_READY_EVENT)) 45277c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_CARD_READY) 45287c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45297c478bd9Sstevel@tonic-gate 45307c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) == 45317c478bd9Sstevel@tonic-gate (PRR_BVD2_STATUS | PRR_BVD2_EVENT)) 45327c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_LOW) 45337c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45347c478bd9Sstevel@tonic-gate 45357c478bd9Sstevel@tonic-gate if ((client->pin & (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) == 45367c478bd9Sstevel@tonic-gate (PRR_BVD1_STATUS | PRR_BVD1_EVENT)) 45377c478bd9Sstevel@tonic-gate if (event_mask & CS_EVENT_BATTERY_DEAD) 45387c478bd9Sstevel@tonic-gate SCIntMask |= SBM_BVD1; 45397c478bd9Sstevel@tonic-gate 45407c478bd9Sstevel@tonic-gate } /* if (CONFIG_PINREPL_REG_PRESENT) */ 45417c478bd9Sstevel@tonic-gate } /* if (!SOCKET_IS_IO) */ 45427c478bd9Sstevel@tonic-gate 45437c478bd9Sstevel@tonic-gate return (SCIntMask); 45447c478bd9Sstevel@tonic-gate } 45457c478bd9Sstevel@tonic-gate 45467c478bd9Sstevel@tonic-gate /* 45477c478bd9Sstevel@tonic-gate * cs_set_socket_event_mask - set the event mask for the socket 45487c478bd9Sstevel@tonic-gate */ 45497c478bd9Sstevel@tonic-gate static int 45507c478bd9Sstevel@tonic-gate cs_set_socket_event_mask(cs_socket_t *sp, unsigned event_mask) 45517c478bd9Sstevel@tonic-gate { 45527c478bd9Sstevel@tonic-gate get_socket_t get_socket; 45537c478bd9Sstevel@tonic-gate set_socket_t set_socket; 45547c478bd9Sstevel@tonic-gate 45557c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 45567c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) 45577c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 45587c478bd9Sstevel@tonic-gate 45597c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 45607c478bd9Sstevel@tonic-gate set_socket.SCIntMask = event_mask; 45617c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 45627c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 45637c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 45647c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 45657c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 45667c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 45677c478bd9Sstevel@tonic-gate /* XXX (is ~0 correct here?) reset latched values */ 45687c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; 45697c478bd9Sstevel@tonic-gate 45707c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) 45717c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 45727c478bd9Sstevel@tonic-gate 45737c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 45747c478bd9Sstevel@tonic-gate } 45757c478bd9Sstevel@tonic-gate 45767c478bd9Sstevel@tonic-gate /* 45777c478bd9Sstevel@tonic-gate * ==== MTD handling section ==== 45787c478bd9Sstevel@tonic-gate */ 45797c478bd9Sstevel@tonic-gate static int 45807c478bd9Sstevel@tonic-gate cs_deregister_mtd(client_handle_t client_handle) 45817c478bd9Sstevel@tonic-gate { 45827c478bd9Sstevel@tonic-gate 45837c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_deregister_mtd: client_handle 0x%x\n", 45847c478bd9Sstevel@tonic-gate (int)client_handle); 45857c478bd9Sstevel@tonic-gate 45867c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 45877c478bd9Sstevel@tonic-gate } 45887c478bd9Sstevel@tonic-gate 45897c478bd9Sstevel@tonic-gate /* 45907c478bd9Sstevel@tonic-gate * ==== memory window handling section ==== 45917c478bd9Sstevel@tonic-gate */ 45927c478bd9Sstevel@tonic-gate 45937c478bd9Sstevel@tonic-gate /* 45947c478bd9Sstevel@tonic-gate * cs_request_window - searches through window list for the socket to find a 45957c478bd9Sstevel@tonic-gate * memory window that matches the requested criteria; 45967c478bd9Sstevel@tonic-gate * this is RequestWindow 45977c478bd9Sstevel@tonic-gate * 45987c478bd9Sstevel@tonic-gate * calling: cs_request_window(client_handle_t, *window_handle_t, win_req_t *) 45997c478bd9Sstevel@tonic-gate * 46007c478bd9Sstevel@tonic-gate * On sucessful return, the window_handle_t * pointed to will 46017c478bd9Sstevel@tonic-gate * contain a valid window handle for this window. 46027c478bd9Sstevel@tonic-gate * 46037c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if window found 46047c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 46057c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 46067c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 46077c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 46087c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 46097c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 46107c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attrbute 46117c478bd9Sstevel@tonic-gate * flags are set 46127c478bd9Sstevel@tonic-gate */ 46137c478bd9Sstevel@tonic-gate static int 46147c478bd9Sstevel@tonic-gate cs_request_window(client_handle_t client_handle, 46157c478bd9Sstevel@tonic-gate window_handle_t *wh, 46167c478bd9Sstevel@tonic-gate win_req_t *rw) 46177c478bd9Sstevel@tonic-gate { 46187c478bd9Sstevel@tonic-gate cs_socket_t *sp; 46197c478bd9Sstevel@tonic-gate cs_window_t *cw; 46207c478bd9Sstevel@tonic-gate client_t *client; 46217c478bd9Sstevel@tonic-gate modify_win_t mw; 46227c478bd9Sstevel@tonic-gate inquire_window_t iw; 46237c478bd9Sstevel@tonic-gate uint32_t aw; 46247c478bd9Sstevel@tonic-gate int error; 46257c478bd9Sstevel@tonic-gate int client_lock_acquired; 46267c478bd9Sstevel@tonic-gate uint32_t socket_num; 46277c478bd9Sstevel@tonic-gate 46287c478bd9Sstevel@tonic-gate /* 46297c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 46307c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 46317c478bd9Sstevel@tonic-gate */ 46327c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 46337c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 46347c478bd9Sstevel@tonic-gate 46357c478bd9Sstevel@tonic-gate /* 46367c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported flags are set. 46377c478bd9Sstevel@tonic-gate */ 46387c478bd9Sstevel@tonic-gate if (rw->Attributes & (/* Compatability */ 46397c478bd9Sstevel@tonic-gate WIN_PAGED | 46407c478bd9Sstevel@tonic-gate WIN_SHARED | 46417c478bd9Sstevel@tonic-gate WIN_FIRST_SHARED | 46427c478bd9Sstevel@tonic-gate WIN_BINDING_SPECIFIC | 46437c478bd9Sstevel@tonic-gate /* CS internal */ 46447c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 46457c478bd9Sstevel@tonic-gate /* IO window flags */ 46467c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_IO | 46477c478bd9Sstevel@tonic-gate /* CardBus flags */ 46487c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_32 | 46497c478bd9Sstevel@tonic-gate WIN_PREFETCH_CACHE_MASK | 46507c478bd9Sstevel@tonic-gate WIN_BAR_MASK)) 46517c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 46527c478bd9Sstevel@tonic-gate 46537c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 46547c478bd9Sstevel@tonic-gate 46557c478bd9Sstevel@tonic-gate /* 46567c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 46577c478bd9Sstevel@tonic-gate */ 46587c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 46597c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 46607c478bd9Sstevel@tonic-gate 46617c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 46627c478bd9Sstevel@tonic-gate 46637c478bd9Sstevel@tonic-gate /* 46647c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 46657c478bd9Sstevel@tonic-gate */ 46667c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 46677c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46687c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 46697c478bd9Sstevel@tonic-gate return (error); 46707c478bd9Sstevel@tonic-gate } 46717c478bd9Sstevel@tonic-gate 46727c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 46737c478bd9Sstevel@tonic-gate 46747c478bd9Sstevel@tonic-gate /* 46757c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 46767c478bd9Sstevel@tonic-gate * for this client, then return an error. 46777c478bd9Sstevel@tonic-gate */ 46787c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 46797c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 46807c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46817c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 46827c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 46837c478bd9Sstevel@tonic-gate } 46847c478bd9Sstevel@tonic-gate 46857c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 46867c478bd9Sstevel@tonic-gate 46877c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 46887c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 46897c478bd9Sstevel@tonic-gate 46907c478bd9Sstevel@tonic-gate 46917c478bd9Sstevel@tonic-gate /* 46927c478bd9Sstevel@tonic-gate * See if we can find a window that matches the caller's criteria. 46937c478bd9Sstevel@tonic-gate * If we can't, then thre's not much more that we can do except 46947c478bd9Sstevel@tonic-gate * for return an error. 46957c478bd9Sstevel@tonic-gate */ 46967c478bd9Sstevel@tonic-gate if ((error = cs_find_mem_window(sp->socket_num, rw, &aw)) != 46977c478bd9Sstevel@tonic-gate CS_SUCCESS) { 46987c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 46997c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47007c478bd9Sstevel@tonic-gate return (error); 47017c478bd9Sstevel@tonic-gate } 47027c478bd9Sstevel@tonic-gate 47037c478bd9Sstevel@tonic-gate /* 47047c478bd9Sstevel@tonic-gate * We got a window, now synthesize a new window handle for this 47057c478bd9Sstevel@tonic-gate * client and get a pointer to the global window structs 47067c478bd9Sstevel@tonic-gate * and assign this window to this client. 47077c478bd9Sstevel@tonic-gate * We don't have to check for errors from cs_create_window_handle 47087c478bd9Sstevel@tonic-gate * since that function always returns a valid window handle 47097c478bd9Sstevel@tonic-gate * if it is given a valid window number. 47107c478bd9Sstevel@tonic-gate */ 47117c478bd9Sstevel@tonic-gate *wh = cs_create_window_handle(aw); 47127c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(aw)) == NULL) { 47137c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47147c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47157c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 47167c478bd9Sstevel@tonic-gate } 47177c478bd9Sstevel@tonic-gate 47187c478bd9Sstevel@tonic-gate cw->window_handle = *wh; 47197c478bd9Sstevel@tonic-gate cw->client_handle = client_handle; 47207c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 47217c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_MEM); 47227c478bd9Sstevel@tonic-gate 47237c478bd9Sstevel@tonic-gate mw.Attributes = ( 47247c478bd9Sstevel@tonic-gate rw->Attributes | 47257c478bd9Sstevel@tonic-gate WIN_DATA_WIDTH_VALID | 47267c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID); 47277c478bd9Sstevel@tonic-gate mw.AccessSpeed = rw->win_params.AccessSpeed; 47287c478bd9Sstevel@tonic-gate 47297c478bd9Sstevel@tonic-gate if ((error = cs_modify_mem_window(*wh, &mw, rw, socket_num)) != 47307c478bd9Sstevel@tonic-gate CS_SUCCESS) { 47317c478bd9Sstevel@tonic-gate cw->state = 0; 47327c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47337c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47347c478bd9Sstevel@tonic-gate return (error); 47357c478bd9Sstevel@tonic-gate } 47367c478bd9Sstevel@tonic-gate 47377c478bd9Sstevel@tonic-gate /* 47387c478bd9Sstevel@tonic-gate * Get any required card offset and pass it back to the client. 47397c478bd9Sstevel@tonic-gate * This is not defined in the current PCMCIA spec. It is 47407c478bd9Sstevel@tonic-gate * an aid to clients that want to use it to generate an 47417c478bd9Sstevel@tonic-gate * optimum card offset. 47427c478bd9Sstevel@tonic-gate */ 47437c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(*wh); 47447c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 47457c478bd9Sstevel@tonic-gate 47467c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 47477c478bd9Sstevel@tonic-gate rw->ReqOffset = rw->Size; 47487c478bd9Sstevel@tonic-gate else 47497c478bd9Sstevel@tonic-gate rw->ReqOffset = iw.mem_win_char.ReqOffset; 47507c478bd9Sstevel@tonic-gate 47517c478bd9Sstevel@tonic-gate /* 47527c478bd9Sstevel@tonic-gate * Increment the client's memory window count; this is how we know 47537c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 47547c478bd9Sstevel@tonic-gate */ 47557c478bd9Sstevel@tonic-gate client->memwin_count++; 47567c478bd9Sstevel@tonic-gate 47577c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 47587c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47597c478bd9Sstevel@tonic-gate 47607c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 47617c478bd9Sstevel@tonic-gate } 47627c478bd9Sstevel@tonic-gate 47637c478bd9Sstevel@tonic-gate /* 47647c478bd9Sstevel@tonic-gate * cs_release_window - deallocates the window associated with the passed 47657c478bd9Sstevel@tonic-gate * window handle; this is ReleaseWindow 47667c478bd9Sstevel@tonic-gate * 47677c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS if window handle is valid and window was 47687c478bd9Sstevel@tonic-gate * sucessfully deallocated 47697c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE if window handle is invalid or if window 47707c478bd9Sstevel@tonic-gate * handle is valid but window is not allocated 47717c478bd9Sstevel@tonic-gate */ 47727c478bd9Sstevel@tonic-gate static int 47737c478bd9Sstevel@tonic-gate cs_release_window(window_handle_t wh) 47747c478bd9Sstevel@tonic-gate { 47757c478bd9Sstevel@tonic-gate cs_socket_t *sp; 47767c478bd9Sstevel@tonic-gate cs_window_t *cw; 47777c478bd9Sstevel@tonic-gate client_t *client; 47787c478bd9Sstevel@tonic-gate int error; 47797c478bd9Sstevel@tonic-gate int client_lock_acquired; 47807c478bd9Sstevel@tonic-gate 47817c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 47827c478bd9Sstevel@tonic-gate 47837c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 47847c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47857c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 47867c478bd9Sstevel@tonic-gate } 47877c478bd9Sstevel@tonic-gate 47887c478bd9Sstevel@tonic-gate /* 47897c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 47907c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 47917c478bd9Sstevel@tonic-gate */ 47927c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(cw->client_handle)) { 47937c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 47947c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 47957c478bd9Sstevel@tonic-gate } 47967c478bd9Sstevel@tonic-gate 47977c478bd9Sstevel@tonic-gate /* 47987c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 47997c478bd9Sstevel@tonic-gate */ 48007c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 48017c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 48027c478bd9Sstevel@tonic-gate 48037c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 48047c478bd9Sstevel@tonic-gate 48057c478bd9Sstevel@tonic-gate /* 48067c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 48077c478bd9Sstevel@tonic-gate */ 48087c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 48097c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48107c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48117c478bd9Sstevel@tonic-gate return (error); 48127c478bd9Sstevel@tonic-gate } 48137c478bd9Sstevel@tonic-gate 48147c478bd9Sstevel@tonic-gate /* 48157c478bd9Sstevel@tonic-gate * Mark this window as not in use anymore. 48167c478bd9Sstevel@tonic-gate */ 48177c478bd9Sstevel@tonic-gate cw->state &= ~CW_WIN_IN_USE; 48187c478bd9Sstevel@tonic-gate 48197c478bd9Sstevel@tonic-gate /* 48207c478bd9Sstevel@tonic-gate * Decrement the client's memory window count; this is how we know 48217c478bd9Sstevel@tonic-gate * when a client has any allocated memory windows. 48227c478bd9Sstevel@tonic-gate */ 48237c478bd9Sstevel@tonic-gate if (!(--(client->memwin_count))) 48247c478bd9Sstevel@tonic-gate client->flags &= ~CLIENT_WIN_ALLOCATED; 48257c478bd9Sstevel@tonic-gate 48267c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48277c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48287c478bd9Sstevel@tonic-gate 48297c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 48307c478bd9Sstevel@tonic-gate } 48317c478bd9Sstevel@tonic-gate 48327c478bd9Sstevel@tonic-gate /* 48337c478bd9Sstevel@tonic-gate * cs_modify_window - modifies a window's characteristics; this is ModifyWindow 48347c478bd9Sstevel@tonic-gate */ 48357c478bd9Sstevel@tonic-gate static int 48367c478bd9Sstevel@tonic-gate cs_modify_window(window_handle_t wh, modify_win_t *mw) 48377c478bd9Sstevel@tonic-gate { 48387c478bd9Sstevel@tonic-gate cs_socket_t *sp; 48397c478bd9Sstevel@tonic-gate cs_window_t *cw; 48407c478bd9Sstevel@tonic-gate client_t *client; 48417c478bd9Sstevel@tonic-gate int error; 48427c478bd9Sstevel@tonic-gate int client_lock_acquired; 48437c478bd9Sstevel@tonic-gate 48447c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 48457c478bd9Sstevel@tonic-gate 48467c478bd9Sstevel@tonic-gate /* 48477c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 48487c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 48497c478bd9Sstevel@tonic-gate * has allocated that window. 48507c478bd9Sstevel@tonic-gate */ 48517c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 48527c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48537c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 48547c478bd9Sstevel@tonic-gate } 48557c478bd9Sstevel@tonic-gate 48567c478bd9Sstevel@tonic-gate /* 48577c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 48587c478bd9Sstevel@tonic-gate */ 48597c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 48607c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 48617c478bd9Sstevel@tonic-gate 48627c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 48637c478bd9Sstevel@tonic-gate 48647c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 48657c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48667c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48677c478bd9Sstevel@tonic-gate return (error); 48687c478bd9Sstevel@tonic-gate } 48697c478bd9Sstevel@tonic-gate 48707c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 48717c478bd9Sstevel@tonic-gate 48727c478bd9Sstevel@tonic-gate /* 48737c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 48747c478bd9Sstevel@tonic-gate * for this client, then return an error. 48757c478bd9Sstevel@tonic-gate */ 48767c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 48777c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 48787c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48797c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48807c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 48817c478bd9Sstevel@tonic-gate } 48827c478bd9Sstevel@tonic-gate 48837c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 48847c478bd9Sstevel@tonic-gate 48857c478bd9Sstevel@tonic-gate mw->Attributes &= ( 48867c478bd9Sstevel@tonic-gate WIN_MEMORY_TYPE_MASK | 48877c478bd9Sstevel@tonic-gate WIN_ENABLE | 48887c478bd9Sstevel@tonic-gate WIN_ACCESS_SPEED_VALID | 48897c478bd9Sstevel@tonic-gate WIN_ACC_ENDIAN_MASK | 48907c478bd9Sstevel@tonic-gate WIN_ACC_ORDER_MASK); 48917c478bd9Sstevel@tonic-gate 48927c478bd9Sstevel@tonic-gate mw->Attributes &= ~WIN_DATA_WIDTH_VALID; 48937c478bd9Sstevel@tonic-gate 48947c478bd9Sstevel@tonic-gate if ((error = cs_modify_mem_window(wh, mw, NULL, NULL)) != CS_SUCCESS) { 48957c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 48967c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 48977c478bd9Sstevel@tonic-gate return (error); 48987c478bd9Sstevel@tonic-gate } 48997c478bd9Sstevel@tonic-gate 49007c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 49017c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 49027c478bd9Sstevel@tonic-gate 49037c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 49047c478bd9Sstevel@tonic-gate } 49057c478bd9Sstevel@tonic-gate 49067c478bd9Sstevel@tonic-gate /* 49077c478bd9Sstevel@tonic-gate * cs_modify_mem_window - modifies a window's characteristics; used internally 49087c478bd9Sstevel@tonic-gate * by Card Services 49097c478bd9Sstevel@tonic-gate * 49107c478bd9Sstevel@tonic-gate * If *wr is NULL, it means that we're being called by ModifyWindow 49117c478bd9Sstevel@tonic-gate * If *wr is non-NULL, it means that we are being called by RequestWindow 49127c478bd9Sstevel@tonic-gate * and so we can't use SS_GetWindow. 49137c478bd9Sstevel@tonic-gate */ 49147c478bd9Sstevel@tonic-gate static int 49157c478bd9Sstevel@tonic-gate cs_modify_mem_window(window_handle_t wh, modify_win_t *mw, 49167c478bd9Sstevel@tonic-gate win_req_t *wr, int sn) 49177c478bd9Sstevel@tonic-gate { 49187c478bd9Sstevel@tonic-gate get_window_t gw; 49197c478bd9Sstevel@tonic-gate set_window_t sw; 49207c478bd9Sstevel@tonic-gate set_page_t set_page; 49217c478bd9Sstevel@tonic-gate get_page_t get_page; 49227c478bd9Sstevel@tonic-gate 49237c478bd9Sstevel@tonic-gate /* 49247c478bd9Sstevel@tonic-gate * If the win_req_t struct pointer is NULL, it means that 49257c478bd9Sstevel@tonic-gate * we're being called by ModifyWindow, so get the 49267c478bd9Sstevel@tonic-gate * current window characteristics. 49277c478bd9Sstevel@tonic-gate */ 49287c478bd9Sstevel@tonic-gate if (!wr) { 49297c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 49307c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 49317c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49327c478bd9Sstevel@tonic-gate sw.state = gw.state; 49337c478bd9Sstevel@tonic-gate sw.socket = gw.socket; 49347c478bd9Sstevel@tonic-gate sw.WindowSize = gw.size; 49357c478bd9Sstevel@tonic-gate } else { 49367c478bd9Sstevel@tonic-gate sw.state = 0; 49377c478bd9Sstevel@tonic-gate sw.socket = sn; 49387c478bd9Sstevel@tonic-gate sw.WindowSize = wr->Size; 49397c478bd9Sstevel@tonic-gate } 49407c478bd9Sstevel@tonic-gate 49417c478bd9Sstevel@tonic-gate /* 49427c478bd9Sstevel@tonic-gate * If we're being called by RequestWindow, we must always have 49437c478bd9Sstevel@tonic-gate * WIN_ACCESS_SPEED_VALID set since get_window_t is not 49447c478bd9Sstevel@tonic-gate * defined. 49457c478bd9Sstevel@tonic-gate */ 49467c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ACCESS_SPEED_VALID) { 49477c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 49487c478bd9Sstevel@tonic-gate 49497c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_DEVSPEED_TO_NS; 49507c478bd9Sstevel@tonic-gate convert_speed.devspeed = mw->AccessSpeed; 49517c478bd9Sstevel@tonic-gate 49527c478bd9Sstevel@tonic-gate if (cs_convert_speed(&convert_speed) != CS_SUCCESS) 49537c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 49547c478bd9Sstevel@tonic-gate 49557c478bd9Sstevel@tonic-gate sw.speed = convert_speed.nS; 49567c478bd9Sstevel@tonic-gate } else { 49577c478bd9Sstevel@tonic-gate sw.speed = gw.speed; 49587c478bd9Sstevel@tonic-gate } 49597c478bd9Sstevel@tonic-gate 49607c478bd9Sstevel@tonic-gate if (!wr) { 49617c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 49627c478bd9Sstevel@tonic-gate get_page.page = 0; 49637c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetPage, &get_page) != SUCCESS) 49647c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49657c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 49667c478bd9Sstevel@tonic-gate set_page.offset = get_page.offset; 49677c478bd9Sstevel@tonic-gate } else { 49687c478bd9Sstevel@tonic-gate set_page.state = 0; 49697c478bd9Sstevel@tonic-gate set_page.offset = 0; 49707c478bd9Sstevel@tonic-gate } 49717c478bd9Sstevel@tonic-gate 49727c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_ENABLE) { 49737c478bd9Sstevel@tonic-gate sw.state |= WS_ENABLED; 49747c478bd9Sstevel@tonic-gate set_page.state |= PS_ENABLED; 49757c478bd9Sstevel@tonic-gate } else { 49767c478bd9Sstevel@tonic-gate sw.state &= ~WS_ENABLED; 49777c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ENABLED; 49787c478bd9Sstevel@tonic-gate } 49797c478bd9Sstevel@tonic-gate 49807c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_VALID) { 49817c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_DATA_WIDTH_16) 49827c478bd9Sstevel@tonic-gate sw.state |= WS_16BIT; 49837c478bd9Sstevel@tonic-gate else 49847c478bd9Sstevel@tonic-gate sw.state &= ~WS_16BIT; 49857c478bd9Sstevel@tonic-gate } 49867c478bd9Sstevel@tonic-gate 49877c478bd9Sstevel@tonic-gate sw.window = GET_WINDOW_NUMBER(wh); 49887c478bd9Sstevel@tonic-gate sw.base = 0; 49897c478bd9Sstevel@tonic-gate 49907c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&sw, mw->Attributes); 49917c478bd9Sstevel@tonic-gate 49927c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &sw) != SUCCESS) 49937c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 49947c478bd9Sstevel@tonic-gate 49957c478bd9Sstevel@tonic-gate if (mw->Attributes & WIN_MEMORY_TYPE_AM) 49967c478bd9Sstevel@tonic-gate set_page.state |= PS_ATTRIBUTE; 49977c478bd9Sstevel@tonic-gate else 49987c478bd9Sstevel@tonic-gate set_page.state &= ~PS_ATTRIBUTE; 49997c478bd9Sstevel@tonic-gate 50007c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 50017c478bd9Sstevel@tonic-gate set_page.page = 0; 50027c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) 50037c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 50047c478bd9Sstevel@tonic-gate 50057c478bd9Sstevel@tonic-gate /* 50067c478bd9Sstevel@tonic-gate * Return the current base address of this window 50077c478bd9Sstevel@tonic-gate */ 50087c478bd9Sstevel@tonic-gate if (wr) { 50097c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 50107c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetWindow, &gw) != SUCCESS) 50117c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 50127c478bd9Sstevel@tonic-gate 50137c478bd9Sstevel@tonic-gate wr->Base.handle = (acc_handle_t)gw.handle; 50147c478bd9Sstevel@tonic-gate } 50157c478bd9Sstevel@tonic-gate 50167c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 50177c478bd9Sstevel@tonic-gate } 50187c478bd9Sstevel@tonic-gate 50197c478bd9Sstevel@tonic-gate /* 50207c478bd9Sstevel@tonic-gate * cs_map_mem_page - sets the card offset of the mapped window 50217c478bd9Sstevel@tonic-gate */ 50227c478bd9Sstevel@tonic-gate static int 50237c478bd9Sstevel@tonic-gate cs_map_mem_page(window_handle_t wh, map_mem_page_t *mmp) 50247c478bd9Sstevel@tonic-gate { 50257c478bd9Sstevel@tonic-gate cs_socket_t *sp; 50267c478bd9Sstevel@tonic-gate cs_window_t *cw; 50277c478bd9Sstevel@tonic-gate client_t *client; 50287c478bd9Sstevel@tonic-gate inquire_window_t iw; 50297c478bd9Sstevel@tonic-gate get_window_t gw; 50307c478bd9Sstevel@tonic-gate set_page_t set_page; 50317c478bd9Sstevel@tonic-gate get_page_t get_page; 50327c478bd9Sstevel@tonic-gate int error; 50337c478bd9Sstevel@tonic-gate uint32_t size; 50347c478bd9Sstevel@tonic-gate int client_lock_acquired; 50357c478bd9Sstevel@tonic-gate 50367c478bd9Sstevel@tonic-gate /* 50377c478bd9Sstevel@tonic-gate * We don't support paged windows, so never allow a page number 50387c478bd9Sstevel@tonic-gate * of other than 0 50397c478bd9Sstevel@tonic-gate */ 50407c478bd9Sstevel@tonic-gate if (mmp->Page) 50417c478bd9Sstevel@tonic-gate return (CS_BAD_PAGE); 50427c478bd9Sstevel@tonic-gate 50437c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 50447c478bd9Sstevel@tonic-gate 50457c478bd9Sstevel@tonic-gate /* 50467c478bd9Sstevel@tonic-gate * Do some sanity checking - make sure that we can find a pointer 50477c478bd9Sstevel@tonic-gate * to the window structure, and if we can, get the client that 50487c478bd9Sstevel@tonic-gate * has allocated that window. 50497c478bd9Sstevel@tonic-gate */ 50507c478bd9Sstevel@tonic-gate if (!(cw = cs_find_window(wh))) { 50517c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50527c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 50537c478bd9Sstevel@tonic-gate } 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate /* 50567c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 50577c478bd9Sstevel@tonic-gate */ 50587c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(cw->client_handle))) == NULL) 50597c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 50607c478bd9Sstevel@tonic-gate 50617c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 50627c478bd9Sstevel@tonic-gate 50637c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(cw->client_handle, &error))) { 50647c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50657c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50667c478bd9Sstevel@tonic-gate return (error); 50677c478bd9Sstevel@tonic-gate } 50687c478bd9Sstevel@tonic-gate 50697c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 50707c478bd9Sstevel@tonic-gate 50717c478bd9Sstevel@tonic-gate /* 50727c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 50737c478bd9Sstevel@tonic-gate * for this client, then return an error. 50747c478bd9Sstevel@tonic-gate */ 50757c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 50767c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 50777c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50787c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50797c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 50807c478bd9Sstevel@tonic-gate } 50817c478bd9Sstevel@tonic-gate 50827c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 50837c478bd9Sstevel@tonic-gate 50847c478bd9Sstevel@tonic-gate gw.window = GET_WINDOW_NUMBER(wh); 50857c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &gw); 50867c478bd9Sstevel@tonic-gate 50877c478bd9Sstevel@tonic-gate iw.window = GET_WINDOW_NUMBER(wh); 50887c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &iw); 50897c478bd9Sstevel@tonic-gate 50907c478bd9Sstevel@tonic-gate if (iw.mem_win_char.MemWndCaps & WC_CALIGN) 50917c478bd9Sstevel@tonic-gate size = gw.size; 50927c478bd9Sstevel@tonic-gate else 50937c478bd9Sstevel@tonic-gate size = iw.mem_win_char.ReqOffset; 50947c478bd9Sstevel@tonic-gate 50957c478bd9Sstevel@tonic-gate if (((mmp->CardOffset/size)*size) != mmp->CardOffset) { 50967c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 50977c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 50987c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 50997c478bd9Sstevel@tonic-gate } 51007c478bd9Sstevel@tonic-gate 51017c478bd9Sstevel@tonic-gate get_page.window = GET_WINDOW_NUMBER(wh); 51027c478bd9Sstevel@tonic-gate get_page.page = 0; 51037c478bd9Sstevel@tonic-gate SocketServices(SS_GetPage, &get_page); 51047c478bd9Sstevel@tonic-gate 51057c478bd9Sstevel@tonic-gate set_page.window = GET_WINDOW_NUMBER(wh); 51067c478bd9Sstevel@tonic-gate set_page.page = 0; 51077c478bd9Sstevel@tonic-gate set_page.state = get_page.state; 51087c478bd9Sstevel@tonic-gate set_page.offset = mmp->CardOffset; 51097c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetPage, &set_page) != SUCCESS) { 51107c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 51117c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 51127c478bd9Sstevel@tonic-gate return (CS_BAD_OFFSET); 51137c478bd9Sstevel@tonic-gate } 51147c478bd9Sstevel@tonic-gate 51157c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 51167c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 51177c478bd9Sstevel@tonic-gate 51187c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 51197c478bd9Sstevel@tonic-gate } 51207c478bd9Sstevel@tonic-gate 51217c478bd9Sstevel@tonic-gate /* 51227c478bd9Sstevel@tonic-gate * cs_find_window - finds the window associated with the passed window 51237c478bd9Sstevel@tonic-gate * handle; if the window handle is invalid or no 51247c478bd9Sstevel@tonic-gate * windows match the passed window handle, NULL 51257c478bd9Sstevel@tonic-gate * is returned. Note that the window must be 51267c478bd9Sstevel@tonic-gate * allocated for this function to return a valid 51277c478bd9Sstevel@tonic-gate * window pointer. 51287c478bd9Sstevel@tonic-gate * 51297c478bd9Sstevel@tonic-gate * returns: cs_window_t * pointer to the found window 51307c478bd9Sstevel@tonic-gate * NULL if window handle invalid or window not allocated 51317c478bd9Sstevel@tonic-gate */ 51327c478bd9Sstevel@tonic-gate cs_window_t * 51337c478bd9Sstevel@tonic-gate cs_find_window(window_handle_t wh) 51347c478bd9Sstevel@tonic-gate { 51357c478bd9Sstevel@tonic-gate cs_window_t *cw; 51367c478bd9Sstevel@tonic-gate 51377c478bd9Sstevel@tonic-gate if ((GET_WINDOW_NUMBER(wh) > cs_globals.num_windows) || 51387c478bd9Sstevel@tonic-gate (GET_WINDOW_MAGIC(wh) != WINDOW_HANDLE_MAGIC)) 51397c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 51407c478bd9Sstevel@tonic-gate 51417c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(GET_WINDOW_NUMBER(wh))) == NULL) 51427c478bd9Sstevel@tonic-gate return (NULL); 51437c478bd9Sstevel@tonic-gate 51447c478bd9Sstevel@tonic-gate if ((cw->state & CW_ALLOCATED) && (cw->state & CW_MEM)) 51457c478bd9Sstevel@tonic-gate return (cw); 51467c478bd9Sstevel@tonic-gate 51477c478bd9Sstevel@tonic-gate return ((cs_window_t *)NULL); 51487c478bd9Sstevel@tonic-gate } 51497c478bd9Sstevel@tonic-gate 51507c478bd9Sstevel@tonic-gate /* 51517c478bd9Sstevel@tonic-gate * cs_create_window_handle - creates a unique window handle based on the 51527c478bd9Sstevel@tonic-gate * passed window number. 51537c478bd9Sstevel@tonic-gate */ 51547c478bd9Sstevel@tonic-gate static window_handle_t 51557c478bd9Sstevel@tonic-gate cs_create_window_handle(uint32_t aw) 51567c478bd9Sstevel@tonic-gate { 51577c478bd9Sstevel@tonic-gate return (WINDOW_HANDLE_MAGIC | (aw & WINDOW_HANDLE_MASK)); 51587c478bd9Sstevel@tonic-gate } 51597c478bd9Sstevel@tonic-gate 51607c478bd9Sstevel@tonic-gate /* 51617c478bd9Sstevel@tonic-gate * cs_find_mem_window - tries to find a memory window matching the caller's 51627c478bd9Sstevel@tonic-gate * criteria 51637c478bd9Sstevel@tonic-gate * 51647c478bd9Sstevel@tonic-gate * We return the first window that matches the requested criteria. 51657c478bd9Sstevel@tonic-gate * 51667c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if memory window found 51677c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 51687c478bd9Sstevel@tonic-gate * CS_BAD_SIZE - if requested size can not be met 51697c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if an internal error occured 51707c478bd9Sstevel@tonic-gate */ 51717c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 51727c478bd9Sstevel@tonic-gate static int 51737c478bd9Sstevel@tonic-gate cs_find_mem_window(uint32_t sn, win_req_t *rw, uint32_t *assigned_window) 51747c478bd9Sstevel@tonic-gate { 51757c478bd9Sstevel@tonic-gate uint32_t wn; 51767c478bd9Sstevel@tonic-gate int error = CS_OUT_OF_RESOURCE; 51777c478bd9Sstevel@tonic-gate uint32_t window_num = PCMCIA_MAX_WINDOWS; 51787c478bd9Sstevel@tonic-gate uint32_t min_size = UINT_MAX; 51797c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 51807c478bd9Sstevel@tonic-gate uint32_t MinSize, MaxSize, ReqGran, MemWndCaps, WndCaps; 51817c478bd9Sstevel@tonic-gate uint32_t tws; 51827c478bd9Sstevel@tonic-gate 51837c478bd9Sstevel@tonic-gate iw = &inquire_window; 51847c478bd9Sstevel@tonic-gate 51857c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 51867c478bd9Sstevel@tonic-gate cs_window_t *cw; 51877c478bd9Sstevel@tonic-gate 51887c478bd9Sstevel@tonic-gate /* 51897c478bd9Sstevel@tonic-gate * If we can't get a pointer to this window, we should contine 51907c478bd9Sstevel@tonic-gate * with scanning the next window, since this window might have 51917c478bd9Sstevel@tonic-gate * been dropped. 51927c478bd9Sstevel@tonic-gate */ 51937c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 51947c478bd9Sstevel@tonic-gate iw->window = wn; 51957c478bd9Sstevel@tonic-gate 51967c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireWindow, iw) != SUCCESS) 51977c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 51987c478bd9Sstevel@tonic-gate 51997c478bd9Sstevel@tonic-gate MinSize = iw->mem_win_char.MinSize; 52007c478bd9Sstevel@tonic-gate MaxSize = iw->mem_win_char.MaxSize; 52017c478bd9Sstevel@tonic-gate ReqGran = iw->mem_win_char.ReqGran; 52027c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 52037c478bd9Sstevel@tonic-gate WndCaps = iw->WndCaps; 52047c478bd9Sstevel@tonic-gate 52057c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 52067c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_MEM(cw) && 52077c478bd9Sstevel@tonic-gate WndCaps & (WC_COMMON|WC_ATTRIBUTE)) { 52087c478bd9Sstevel@tonic-gate if ((error = cs_valid_window_speed(iw, rw->win_params.AccessSpeed)) == 52097c478bd9Sstevel@tonic-gate CS_SUCCESS) { 52107c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 52117c478bd9Sstevel@tonic-gate if (cs_memwin_space_and_map_ok(iw, rw)) { 52127c478bd9Sstevel@tonic-gate error = CS_BAD_SIZE; 52137c478bd9Sstevel@tonic-gate if (!rw->Size) { 52147c478bd9Sstevel@tonic-gate min_size = min(min_size, MinSize); 52157c478bd9Sstevel@tonic-gate window_num = wn; 52167c478bd9Sstevel@tonic-gate goto found_window; 52177c478bd9Sstevel@tonic-gate } else { 52187c478bd9Sstevel@tonic-gate if (!(MemWndCaps & WC_SIZE)) { 52197c478bd9Sstevel@tonic-gate if (rw->Size == MinSize) { 52207c478bd9Sstevel@tonic-gate min_size = MinSize; 52217c478bd9Sstevel@tonic-gate window_num = wn; 52227c478bd9Sstevel@tonic-gate goto found_window; 52237c478bd9Sstevel@tonic-gate } 52247c478bd9Sstevel@tonic-gate } else { /* WC_SIZE */ 52257c478bd9Sstevel@tonic-gate if (!ReqGran) { 52267c478bd9Sstevel@tonic-gate error = CS_BAD_WINDOW; 52277c478bd9Sstevel@tonic-gate } else { 52287c478bd9Sstevel@tonic-gate if ((rw->Size >= MinSize) && 52297c478bd9Sstevel@tonic-gate (rw->Size <= MaxSize)) { 52307c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_POW2) { 52317c478bd9Sstevel@tonic-gate unsigned rg = ReqGran; 52327c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 52337c478bd9Sstevel@tonic-gate rg = (rg<<1)) { 52347c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 52357c478bd9Sstevel@tonic-gate min_size = tws; 52367c478bd9Sstevel@tonic-gate window_num = wn; 52377c478bd9Sstevel@tonic-gate goto found_window; 52387c478bd9Sstevel@tonic-gate } 52397c478bd9Sstevel@tonic-gate tws += rg; 52407c478bd9Sstevel@tonic-gate } /* for (tws) */ 52417c478bd9Sstevel@tonic-gate } else { 52427c478bd9Sstevel@tonic-gate for (tws = MinSize; tws <= MaxSize; 52437c478bd9Sstevel@tonic-gate tws += ReqGran) { 52447c478bd9Sstevel@tonic-gate if (rw->Size == tws) { 52457c478bd9Sstevel@tonic-gate min_size = tws; 52467c478bd9Sstevel@tonic-gate window_num = wn; 52477c478bd9Sstevel@tonic-gate goto found_window; 52487c478bd9Sstevel@tonic-gate } 52497c478bd9Sstevel@tonic-gate } /* for (tws) */ 52507c478bd9Sstevel@tonic-gate } /* if (!WC_POW2) */ 52517c478bd9Sstevel@tonic-gate } /* if (Size >= MinSize) */ 52527c478bd9Sstevel@tonic-gate } /* if (!ReqGran) */ 52537c478bd9Sstevel@tonic-gate } /* if (WC_SIZE) */ 52547c478bd9Sstevel@tonic-gate } /* if (rw->Size) */ 52557c478bd9Sstevel@tonic-gate } /* if (cs_space_and_map_ok) */ 52567c478bd9Sstevel@tonic-gate } /* if (cs_valid_window_speed) */ 52577c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 52587c478bd9Sstevel@tonic-gate } /* if (cs_get_wp) */ 52597c478bd9Sstevel@tonic-gate } /* for (wn) */ 52607c478bd9Sstevel@tonic-gate 52617c478bd9Sstevel@tonic-gate /* 52627c478bd9Sstevel@tonic-gate * If we got here and the window_num wasn't set by any window 52637c478bd9Sstevel@tonic-gate * matches in the above code, it means that we didn't 52647c478bd9Sstevel@tonic-gate * find a window matching the caller's criteria. 52657c478bd9Sstevel@tonic-gate * If the error is CS_BAD_TYPE, it means that the last reason 52667c478bd9Sstevel@tonic-gate * that we couldn't match a window was because the caller's 52677c478bd9Sstevel@tonic-gate * requested speed was out of range of the last window that 52687c478bd9Sstevel@tonic-gate * we checked. We convert this error code to CS_OUT_OF_RESOURCE 52697c478bd9Sstevel@tonic-gate * to conform to the RequestWindow section of the PCMCIA 52707c478bd9Sstevel@tonic-gate * Card Services spec. 52717c478bd9Sstevel@tonic-gate */ 52727c478bd9Sstevel@tonic-gate if (window_num == PCMCIA_MAX_WINDOWS) { 52737c478bd9Sstevel@tonic-gate if (error == CS_BAD_TYPE) 52747c478bd9Sstevel@tonic-gate error = CS_OUT_OF_RESOURCE; 52757c478bd9Sstevel@tonic-gate return (error); 52767c478bd9Sstevel@tonic-gate } 52777c478bd9Sstevel@tonic-gate 52787c478bd9Sstevel@tonic-gate found_window: 52797c478bd9Sstevel@tonic-gate rw->Size = min_size; 52807c478bd9Sstevel@tonic-gate *assigned_window = window_num; 52817c478bd9Sstevel@tonic-gate iw->window = window_num; 52827c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 52837c478bd9Sstevel@tonic-gate MemWndCaps = iw->mem_win_char.MemWndCaps; 52847c478bd9Sstevel@tonic-gate 52857c478bd9Sstevel@tonic-gate if (MemWndCaps & WC_CALIGN) 52867c478bd9Sstevel@tonic-gate rw->Attributes |= WIN_OFFSET_SIZE; 52877c478bd9Sstevel@tonic-gate else 52887c478bd9Sstevel@tonic-gate rw->Attributes &= ~WIN_OFFSET_SIZE; 52897c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 52907c478bd9Sstevel@tonic-gate } 52917c478bd9Sstevel@tonic-gate /* END CSTYLED */ 52927c478bd9Sstevel@tonic-gate 52937c478bd9Sstevel@tonic-gate /* 52947c478bd9Sstevel@tonic-gate * cs_memwin_space_and_map_ok - checks to see if the passed window mapping 52957c478bd9Sstevel@tonic-gate * capabilities and window speeds are in the 52967c478bd9Sstevel@tonic-gate * range of the passed window. 52977c478bd9Sstevel@tonic-gate * 52987c478bd9Sstevel@tonic-gate * returns: 0 - if the capabilities are out of range 52997c478bd9Sstevel@tonic-gate * 1 - if the capabilities are in range 53007c478bd9Sstevel@tonic-gate */ 53017c478bd9Sstevel@tonic-gate static int 53027c478bd9Sstevel@tonic-gate cs_memwin_space_and_map_ok(inquire_window_t *iw, win_req_t *rw) 53037c478bd9Sstevel@tonic-gate { 53047c478bd9Sstevel@tonic-gate 53057c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 53067c478bd9Sstevel@tonic-gate if (cs_debug > 240) 53077c478bd9Sstevel@tonic-gate printf("-> s&m_ok: Attributes 0x%x AccessSpeed 0x%x " 53087c478bd9Sstevel@tonic-gate "WndCaps 0x%x MemWndCaps 0x%x\n", 53097c478bd9Sstevel@tonic-gate (int)rw->Attributes, 53107c478bd9Sstevel@tonic-gate (int)rw->win_params.AccessSpeed, 53117c478bd9Sstevel@tonic-gate iw->WndCaps, 53127c478bd9Sstevel@tonic-gate iw->mem_win_char.MemWndCaps); 53137c478bd9Sstevel@tonic-gate #endif 53147c478bd9Sstevel@tonic-gate 53157c478bd9Sstevel@tonic-gate if (rw->win_params.AccessSpeed & WIN_USE_WAIT) { 53167c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_WAIT)) 53177c478bd9Sstevel@tonic-gate return (0); 53187c478bd9Sstevel@tonic-gate } 53197c478bd9Sstevel@tonic-gate 53207c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_DATA_WIDTH_16) { 53217c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_16BIT)) 53227c478bd9Sstevel@tonic-gate return (0); 53237c478bd9Sstevel@tonic-gate } else { 53247c478bd9Sstevel@tonic-gate if (!(iw->mem_win_char.MemWndCaps & WC_8BIT)) 53257c478bd9Sstevel@tonic-gate return (0); 53267c478bd9Sstevel@tonic-gate } 53277c478bd9Sstevel@tonic-gate 53287c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_AM) { 53297c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_ATTRIBUTE)) 53307c478bd9Sstevel@tonic-gate return (0); 53317c478bd9Sstevel@tonic-gate } 53327c478bd9Sstevel@tonic-gate 53337c478bd9Sstevel@tonic-gate if (rw->Attributes & WIN_MEMORY_TYPE_CM) { 53347c478bd9Sstevel@tonic-gate if (!(iw->WndCaps & WC_COMMON)) 53357c478bd9Sstevel@tonic-gate return (0); 53367c478bd9Sstevel@tonic-gate } 53377c478bd9Sstevel@tonic-gate 53387c478bd9Sstevel@tonic-gate return (1); 53397c478bd9Sstevel@tonic-gate } 53407c478bd9Sstevel@tonic-gate 53417c478bd9Sstevel@tonic-gate /* 53427c478bd9Sstevel@tonic-gate * cs_valid_window_speed - checks to see if requested window speed 53437c478bd9Sstevel@tonic-gate * is in range of passed window 53447c478bd9Sstevel@tonic-gate * 53457c478bd9Sstevel@tonic-gate * The inquire_window_t struct gives us speeds in nS, and we 53467c478bd9Sstevel@tonic-gate * get speeds in the AccessSpeed variable as a devspeed code. 53477c478bd9Sstevel@tonic-gate * 53487c478bd9Sstevel@tonic-gate * returns: CS_BAD_SPEED - if AccessSpeed is invalid devspeed code 53497c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if AccessSpeed is not in range of valid 53507c478bd9Sstevel@tonic-gate * speed for this window 53517c478bd9Sstevel@tonic-gate * CS_SUCCESS - if window speed is in range 53527c478bd9Sstevel@tonic-gate */ 53537c478bd9Sstevel@tonic-gate static int 53547c478bd9Sstevel@tonic-gate cs_valid_window_speed(inquire_window_t *iw, uint32_t AccessSpeed) 53557c478bd9Sstevel@tonic-gate { 53567c478bd9Sstevel@tonic-gate convert_speed_t convert_speed, *cs; 53577c478bd9Sstevel@tonic-gate 53587c478bd9Sstevel@tonic-gate cs = &convert_speed; 53597c478bd9Sstevel@tonic-gate 53607c478bd9Sstevel@tonic-gate cs->Attributes = CONVERT_DEVSPEED_TO_NS; 53617c478bd9Sstevel@tonic-gate cs->devspeed = AccessSpeed; 53627c478bd9Sstevel@tonic-gate 53637c478bd9Sstevel@tonic-gate if (cs_convert_speed(cs) != CS_SUCCESS) 53647c478bd9Sstevel@tonic-gate return (CS_BAD_SPEED); 53657c478bd9Sstevel@tonic-gate 53667c478bd9Sstevel@tonic-gate if ((cs->nS < iw->mem_win_char.Fastest) || 53677c478bd9Sstevel@tonic-gate (cs->nS > iw->mem_win_char.Slowest)) 53687c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 53697c478bd9Sstevel@tonic-gate 53707c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 53717c478bd9Sstevel@tonic-gate } 53727c478bd9Sstevel@tonic-gate 53737c478bd9Sstevel@tonic-gate /* 53747c478bd9Sstevel@tonic-gate * ==== IO window handling section ==== 53757c478bd9Sstevel@tonic-gate */ 53767c478bd9Sstevel@tonic-gate 53777c478bd9Sstevel@tonic-gate /* 53787c478bd9Sstevel@tonic-gate * cs_request_io - provides IO resources for clients; this is RequestIO 53797c478bd9Sstevel@tonic-gate * 53807c478bd9Sstevel@tonic-gate * calling: cs_request_io(client_handle_t, io_req_t *) 53817c478bd9Sstevel@tonic-gate * 53827c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources available for client 53837c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 53847c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 53857c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 53867c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 53877c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 53887c478bd9Sstevel@tonic-gate * flags are set 53897c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if either or both base port addresses 53907c478bd9Sstevel@tonic-gate * are invalid or out of range 53917c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 53927c478bd9Sstevel@tonic-gate * already been done 53937c478bd9Sstevel@tonic-gate * CS_IN_USE - IO ports already in use or function has 53947c478bd9Sstevel@tonic-gate * already been called 53957c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if failure while trying to set window 53967c478bd9Sstevel@tonic-gate * characteristics 53977c478bd9Sstevel@tonic-gate */ 53987c478bd9Sstevel@tonic-gate static int 53997c478bd9Sstevel@tonic-gate cs_request_io(client_handle_t client_handle, io_req_t *ior) 54007c478bd9Sstevel@tonic-gate { 54017c478bd9Sstevel@tonic-gate cs_socket_t *sp; 54027c478bd9Sstevel@tonic-gate client_t *client; 54037c478bd9Sstevel@tonic-gate int error; 54047c478bd9Sstevel@tonic-gate int client_lock_acquired; 54057c478bd9Sstevel@tonic-gate uint32_t socket_num; 54067c478bd9Sstevel@tonic-gate 54077c478bd9Sstevel@tonic-gate /* 54087c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 54097c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 54107c478bd9Sstevel@tonic-gate */ 54117c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 54127c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 54137c478bd9Sstevel@tonic-gate 54147c478bd9Sstevel@tonic-gate /* 54157c478bd9Sstevel@tonic-gate * If the client has only requested one IO range, then make sure 54167c478bd9Sstevel@tonic-gate * that the Attributes2 filed is clear. 54177c478bd9Sstevel@tonic-gate */ 54187c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 54197c478bd9Sstevel@tonic-gate ior->Attributes2 = 0; 54207c478bd9Sstevel@tonic-gate 54217c478bd9Sstevel@tonic-gate /* 54227c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 54237c478bd9Sstevel@tonic-gate */ 54247c478bd9Sstevel@tonic-gate if ((ior->Attributes1 | ior->Attributes2) & (IO_SHARED | 54257c478bd9Sstevel@tonic-gate IO_FIRST_SHARED | 54267c478bd9Sstevel@tonic-gate IO_FORCE_ALIAS_ACCESS | 54277c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 54287c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)) 54297c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 54307c478bd9Sstevel@tonic-gate 54317c478bd9Sstevel@tonic-gate /* 54327c478bd9Sstevel@tonic-gate * Make sure that we have a port count for the first region. 54337c478bd9Sstevel@tonic-gate */ 54347c478bd9Sstevel@tonic-gate if (!ior->NumPorts1) 54357c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 54367c478bd9Sstevel@tonic-gate 54377c478bd9Sstevel@tonic-gate /* 54387c478bd9Sstevel@tonic-gate * If we're being asked for multiple IO ranges, then both base port 54397c478bd9Sstevel@tonic-gate * members must be non-zero. 54407c478bd9Sstevel@tonic-gate */ 54417c478bd9Sstevel@tonic-gate if ((ior->NumPorts2) && !(ior->BasePort1.base && ior->BasePort2.base)) 54427c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 54437c478bd9Sstevel@tonic-gate 54447c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 54457c478bd9Sstevel@tonic-gate 54467c478bd9Sstevel@tonic-gate /* 54477c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 54487c478bd9Sstevel@tonic-gate */ 54497c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 54507c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 54517c478bd9Sstevel@tonic-gate 54527c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 54537c478bd9Sstevel@tonic-gate 54547c478bd9Sstevel@tonic-gate /* 54557c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 54567c478bd9Sstevel@tonic-gate */ 54577c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 54587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54597c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54607c478bd9Sstevel@tonic-gate return (error); 54617c478bd9Sstevel@tonic-gate } 54627c478bd9Sstevel@tonic-gate 54637c478bd9Sstevel@tonic-gate /* 54647c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 54657c478bd9Sstevel@tonic-gate * this call. 54667c478bd9Sstevel@tonic-gate */ 54677c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 54687c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54697c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54707c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 54717c478bd9Sstevel@tonic-gate } 54727c478bd9Sstevel@tonic-gate 54737c478bd9Sstevel@tonic-gate /* 54747c478bd9Sstevel@tonic-gate * If RequestIO has already been done, we don't allow this call. 54757c478bd9Sstevel@tonic-gate */ 54767c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 54777c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54787c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54797c478bd9Sstevel@tonic-gate return (CS_IN_USE); 54807c478bd9Sstevel@tonic-gate } 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 54837c478bd9Sstevel@tonic-gate 54847c478bd9Sstevel@tonic-gate /* 54857c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 54867c478bd9Sstevel@tonic-gate * for this client, then return an error. 54877c478bd9Sstevel@tonic-gate */ 54887c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 54897c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 54907c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 54917c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 54927c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 54937c478bd9Sstevel@tonic-gate } 54947c478bd9Sstevel@tonic-gate 54957c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 54967c478bd9Sstevel@tonic-gate 54977c478bd9Sstevel@tonic-gate /* 54987c478bd9Sstevel@tonic-gate * If we're only being asked for one IO range, then set BasePort2 to 54997c478bd9Sstevel@tonic-gate * zero, since we use it later on. 55007c478bd9Sstevel@tonic-gate */ 55017c478bd9Sstevel@tonic-gate if (!ior->NumPorts2) 55027c478bd9Sstevel@tonic-gate ior->BasePort2.base = 0; 55037c478bd9Sstevel@tonic-gate 55047c478bd9Sstevel@tonic-gate /* 55057c478bd9Sstevel@tonic-gate * See if we can allow Card Services to select the base address 55067c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 55077c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 55087c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 55097c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 55107c478bd9Sstevel@tonic-gate * Note that if the client specifies that the card decodes zero 55117c478bd9Sstevel@tonic-gate * IO address lines, then we have to use the NumPortsX 55127c478bd9Sstevel@tonic-gate * values to figure out how many address lines the card 55137c478bd9Sstevel@tonic-gate * actually decodes, and we have to round the NumPortsX 55147c478bd9Sstevel@tonic-gate * values up to the closest power of two. 55157c478bd9Sstevel@tonic-gate */ 55167c478bd9Sstevel@tonic-gate if (ior->IOAddrLines) { 55177c478bd9Sstevel@tonic-gate ior->BasePort1.base = IOADDR_FROBNITZ(ior->BasePort1.base, 55187c478bd9Sstevel@tonic-gate ior->IOAddrLines); 55197c478bd9Sstevel@tonic-gate ior->BasePort2.base = IOADDR_FROBNITZ(ior->BasePort2.base, 55207c478bd9Sstevel@tonic-gate ior->IOAddrLines); 55217c478bd9Sstevel@tonic-gate } else { 55227c478bd9Sstevel@tonic-gate ior->BasePort1.base = ior->BasePort1.base & 55237c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 55247c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 55257c478bd9Sstevel@tonic-gate ior->BasePort2.base = ior->BasePort2.base & 55267c478bd9Sstevel@tonic-gate ((IONUMPORTS_FROBNITZ(ior->NumPorts1) + 55277c478bd9Sstevel@tonic-gate IONUMPORTS_FROBNITZ(ior->NumPorts2)) - 1); 55287c478bd9Sstevel@tonic-gate } 55297c478bd9Sstevel@tonic-gate 55307c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 55317c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 55327c478bd9Sstevel@tonic-gate 55337c478bd9Sstevel@tonic-gate 55347c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 55357c478bd9Sstevel@tonic-gate /* 55367c478bd9Sstevel@tonic-gate * Here is where the code diverges, depending on the type of IO windows 55377c478bd9Sstevel@tonic-gate * that this socket supports. If this socket supportes memory 55387c478bd9Sstevel@tonic-gate * mapped IO windows, as determined by cs_init allocating an 55397c478bd9Sstevel@tonic-gate * io_mmap_window_t structure on the socket structure, then we 55407c478bd9Sstevel@tonic-gate * use one IO window for all the clients on this socket. We can 55417c478bd9Sstevel@tonic-gate * do this safely since a memory mapped IO window implies that 55427c478bd9Sstevel@tonic-gate * only this socket shares the complete IO space of the card. 55437c478bd9Sstevel@tonic-gate * See the next major block of code for a description of what we do 55447c478bd9Sstevel@tonic-gate * if a socket doesn't support memory mapped IO windows. 55457c478bd9Sstevel@tonic-gate */ 55467c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 55477c478bd9Sstevel@tonic-gate cs_window_t *cw; 55487c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 55497c478bd9Sstevel@tonic-gate uint32_t offset; 55507c478bd9Sstevel@tonic-gate 55517c478bd9Sstevel@tonic-gate /* 55527c478bd9Sstevel@tonic-gate * If we haven't allocated an IO window yet, do it now. 55537c478bd9Sstevel@tonic-gate * Try to allocate the IO window that cs_init found for us; 55547c478bd9Sstevel@tonic-gate * if that fails, then call cs_find_io_win to find a window. 55557c478bd9Sstevel@tonic-gate */ 55567c478bd9Sstevel@tonic-gate if (!imw->count) { 55577c478bd9Sstevel@tonic-gate set_window_t set_window; 55587c478bd9Sstevel@tonic-gate 55597c478bd9Sstevel@tonic-gate if (!WINDOW_AVAILABLE_FOR_IO(imw->number)) { 55607c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 55617c478bd9Sstevel@tonic-gate 55627c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = (WC_IO_RANGE_PER_WINDOW | 55637c478bd9Sstevel@tonic-gate WC_8BIT | 55647c478bd9Sstevel@tonic-gate WC_16BIT); 55657c478bd9Sstevel@tonic-gate if ((error = cs_find_io_win(sp->socket_num, &iowin_char, 55667c478bd9Sstevel@tonic-gate &imw->number, &imw->size)) != CS_SUCCESS) { 55677c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 55687c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 55697c478bd9Sstevel@tonic-gate } /* cs_find_io_win */ 55707c478bd9Sstevel@tonic-gate } /* if (!WINDOW_AVAILABLE_FOR_IO) */ 55717c478bd9Sstevel@tonic-gate 55727c478bd9Sstevel@tonic-gate set_window.socket = socket_num; 55737c478bd9Sstevel@tonic-gate set_window.window = imw->number; 55747c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 55757c478bd9Sstevel@tonic-gate set_window.base.base = 0; 55767c478bd9Sstevel@tonic-gate set_window.WindowSize = imw->size; 55777c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_16BIT | 55787c478bd9Sstevel@tonic-gate WS_EXACT_MAPIN | WS_IO); 55797c478bd9Sstevel@tonic-gate 55807c478bd9Sstevel@tonic-gate /* XXX - what to d here? XXX */ 55817c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 55827c478bd9Sstevel@tonic-gate 55837c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) { 55847c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, 55857c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 55867c478bd9Sstevel@tonic-gate (IO_DEALLOCATE_WINDOW | 55877c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 55887c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 55897c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 55907c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 55917c478bd9Sstevel@tonic-gate } 55927c478bd9Sstevel@tonic-gate 55937c478bd9Sstevel@tonic-gate imw->handle = set_window.base.handle; 55947c478bd9Sstevel@tonic-gate imw->size = set_window.WindowSize; 55957c478bd9Sstevel@tonic-gate 55967c478bd9Sstevel@tonic-gate /* 55977c478bd9Sstevel@tonic-gate * Check the caller's port requirements to be sure that they 55987c478bd9Sstevel@tonic-gate * fit within our found IO window. 55997c478bd9Sstevel@tonic-gate */ 56007c478bd9Sstevel@tonic-gate if ((ior->BasePort1.base + ior->NumPorts1 + 56017c478bd9Sstevel@tonic-gate ior->BasePort2.base + ior->NumPorts2) > imw->size) { 56027c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56037c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56047c478bd9Sstevel@tonic-gate return (CS_BAD_BASE); 56057c478bd9Sstevel@tonic-gate } 56067c478bd9Sstevel@tonic-gate 56077c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(imw->number)) == NULL) { 56087c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56097c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56107c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW) 56117c478bd9Sstevel@tonic-gate } 56127c478bd9Sstevel@tonic-gate cw->state |= (CW_ALLOCATED | CW_IO); 56137c478bd9Sstevel@tonic-gate 56147c478bd9Sstevel@tonic-gate } /* if (!imw->count) */ 56157c478bd9Sstevel@tonic-gate 56167c478bd9Sstevel@tonic-gate imw->count++; 56177c478bd9Sstevel@tonic-gate 56187c478bd9Sstevel@tonic-gate /* 56197c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 56207c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller. 56217c478bd9Sstevel@tonic-gate */ 56227c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 56237c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort1.handle, 0); 56247c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort1.handle, &offset); 56257c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort1.handle, 56267c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 56277c478bd9Sstevel@tonic-gate 56287c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 56297c478bd9Sstevel@tonic-gate /* XXX need to set endianess and data ordering flags */ 56307c478bd9Sstevel@tonic-gate csx_DupHandle(imw->handle, &ior->BasePort2.handle, 0); 56317c478bd9Sstevel@tonic-gate csx_GetHandleOffset(ior->BasePort2.handle, &offset); 56327c478bd9Sstevel@tonic-gate csx_SetHandleOffset(ior->BasePort2.handle, 56337c478bd9Sstevel@tonic-gate ior->BasePort1.base + offset); 56347c478bd9Sstevel@tonic-gate } 56357c478bd9Sstevel@tonic-gate 56367c478bd9Sstevel@tonic-gate /* 56377c478bd9Sstevel@tonic-gate * We don't really use these two values if we've got a memory 56387c478bd9Sstevel@tonic-gate * mapped IO window since the assigned window number is stored 56397c478bd9Sstevel@tonic-gate * in imw->number. 56407c478bd9Sstevel@tonic-gate */ 56417c478bd9Sstevel@tonic-gate client->io_alloc.Window1 = imw->number; 56427c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 56437c478bd9Sstevel@tonic-gate 56447c478bd9Sstevel@tonic-gate /* 56457c478bd9Sstevel@tonic-gate * This socket supports only IO port IO windows. 56467c478bd9Sstevel@tonic-gate */ 56477c478bd9Sstevel@tonic-gate } else { 56487c478bd9Sstevel@tonic-gate #else /* USE_IOMMAP_WINDOW */ 56497c478bd9Sstevel@tonic-gate { 56507c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 56517c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 56527c478bd9Sstevel@tonic-gate 56537c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort1.base; 56547c478bd9Sstevel@tonic-gate 56557c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, ior->Attributes1, 56567c478bd9Sstevel@tonic-gate &client->io_alloc.Window1)) != CS_SUCCESS) { 56577c478bd9Sstevel@tonic-gate 56587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56597c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56607c478bd9Sstevel@tonic-gate return (error); 56617c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(1)) */ 56627c478bd9Sstevel@tonic-gate 56637c478bd9Sstevel@tonic-gate /* 56647c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 56657c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 56667c478bd9Sstevel@tonic-gate */ 56677c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 56687c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 56697c478bd9Sstevel@tonic-gate &baseaddru, 56707c478bd9Sstevel@tonic-gate &ior->NumPorts1, 56717c478bd9Sstevel@tonic-gate ior->IOAddrLines, 56727c478bd9Sstevel@tonic-gate ior->Attributes1)) != 56737c478bd9Sstevel@tonic-gate CS_SUCCESS) { 56747c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 56757c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 56767c478bd9Sstevel@tonic-gate ( 56777c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 56787c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 56797c478bd9Sstevel@tonic-gate 56807c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 56817c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 56827c478bd9Sstevel@tonic-gate return (error); 56837c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(1)) */ 56847c478bd9Sstevel@tonic-gate 56857c478bd9Sstevel@tonic-gate ior->BasePort1.handle = (acc_handle_t)baseaddru.handle; 56867c478bd9Sstevel@tonic-gate ior->BasePort1.base = baseaddru.base; 56877c478bd9Sstevel@tonic-gate 56887c478bd9Sstevel@tonic-gate /* 56897c478bd9Sstevel@tonic-gate * See if the client wants two IO ranges. 56907c478bd9Sstevel@tonic-gate */ 56917c478bd9Sstevel@tonic-gate if (ior->NumPorts2) { 56927c478bd9Sstevel@tonic-gate baseaddru_t baseaddru; 56937c478bd9Sstevel@tonic-gate 56947c478bd9Sstevel@tonic-gate baseaddru.base = ior->BasePort2.base; 56957c478bd9Sstevel@tonic-gate 56967c478bd9Sstevel@tonic-gate /* 56977c478bd9Sstevel@tonic-gate * If we fail to allocate this window, then we must deallocate 56987c478bd9Sstevel@tonic-gate * the previous IO window that is already allocated. 56997c478bd9Sstevel@tonic-gate */ 57007c478bd9Sstevel@tonic-gate if ((error = cs_allocate_io_win(sp->socket_num, 57017c478bd9Sstevel@tonic-gate ior->Attributes2, 57027c478bd9Sstevel@tonic-gate &client->io_alloc.Window2)) != 57037c478bd9Sstevel@tonic-gate CS_SUCCESS) { 57047c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57057c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 57067c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 57077c478bd9Sstevel@tonic-gate ( 57087c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57097c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57107c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57117c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57127c478bd9Sstevel@tonic-gate return (error); 57137c478bd9Sstevel@tonic-gate } /* if (cs_allocate_io_win(2)) */ 57147c478bd9Sstevel@tonic-gate /* 57157c478bd9Sstevel@tonic-gate * Setup the window hardware; if this fails, then we need to 57167c478bd9Sstevel@tonic-gate * deallocate the previously allocated window. 57177c478bd9Sstevel@tonic-gate */ 57187c478bd9Sstevel@tonic-gate if ((error = cs_setup_io_win(socket_num, 57197c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 57207c478bd9Sstevel@tonic-gate &baseaddru, 57217c478bd9Sstevel@tonic-gate &ior->NumPorts2, 57227c478bd9Sstevel@tonic-gate ior->IOAddrLines, 57237c478bd9Sstevel@tonic-gate ior->Attributes2)) != 57247c478bd9Sstevel@tonic-gate CS_SUCCESS) { 57257c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57267c478bd9Sstevel@tonic-gate client->io_alloc.Window1, 57277c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 57287c478bd9Sstevel@tonic-gate ( 57297c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57307c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57317c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, 57327c478bd9Sstevel@tonic-gate client->io_alloc.Window2, 57337c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 57347c478bd9Sstevel@tonic-gate ( 57357c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 57367c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 57377c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57387c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57397c478bd9Sstevel@tonic-gate return (error); 57407c478bd9Sstevel@tonic-gate } /* if (cs_setup_io_win(2)) */ 57417c478bd9Sstevel@tonic-gate 57427c478bd9Sstevel@tonic-gate ior->BasePort2.handle = (acc_handle_t)baseaddru.handle; 57437c478bd9Sstevel@tonic-gate ior->BasePort2.base = baseaddru.base; 57447c478bd9Sstevel@tonic-gate 57457c478bd9Sstevel@tonic-gate } else { 57467c478bd9Sstevel@tonic-gate client->io_alloc.Window2 = PCMCIA_MAX_WINDOWS; 57477c478bd9Sstevel@tonic-gate } /* if (ior->NumPorts2) */ 57487c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 57497c478bd9Sstevel@tonic-gate 57507c478bd9Sstevel@tonic-gate /* 57517c478bd9Sstevel@tonic-gate * Save a copy of the client's port information so that we 57527c478bd9Sstevel@tonic-gate * can use it in the RequestConfiguration call. We set 57537c478bd9Sstevel@tonic-gate * the IO window number(s) allocated in the respective 57547c478bd9Sstevel@tonic-gate * section of code, above. 57557c478bd9Sstevel@tonic-gate */ 57567c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.base = ior->BasePort1.base; 57577c478bd9Sstevel@tonic-gate client->io_alloc.BasePort1.handle = ior->BasePort1.handle; 57587c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts1 = ior->NumPorts1; 57597c478bd9Sstevel@tonic-gate client->io_alloc.Attributes1 = ior->Attributes1; 57607c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.base = ior->BasePort2.base; 57617c478bd9Sstevel@tonic-gate client->io_alloc.BasePort2.handle = ior->BasePort2.handle; 57627c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2 = ior->NumPorts2; 57637c478bd9Sstevel@tonic-gate client->io_alloc.Attributes2 = ior->Attributes2; 57647c478bd9Sstevel@tonic-gate client->io_alloc.IOAddrLines = ior->IOAddrLines; 57657c478bd9Sstevel@tonic-gate 57667c478bd9Sstevel@tonic-gate /* 57677c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIO call. 57687c478bd9Sstevel@tonic-gate */ 57697c478bd9Sstevel@tonic-gate client->flags |= (REQ_IO_DONE | CLIENT_IO_ALLOCATED); 57707c478bd9Sstevel@tonic-gate 57717c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 57727c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 57737c478bd9Sstevel@tonic-gate 57747c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 57757c478bd9Sstevel@tonic-gate } 57767c478bd9Sstevel@tonic-gate 57777c478bd9Sstevel@tonic-gate /* 57787c478bd9Sstevel@tonic-gate * cs_release_io - releases IO resources allocated by RequestIO; this is 57797c478bd9Sstevel@tonic-gate * ReleaseIO 57807c478bd9Sstevel@tonic-gate * 57817c478bd9Sstevel@tonic-gate * calling: cs_release_io(client_handle_t, io_req_t *) 57827c478bd9Sstevel@tonic-gate * 57837c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO resources sucessfully deallocated 57847c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 57857c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 57867c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 57877c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 57887c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIO has been done 57897c478bd9Sstevel@tonic-gate */ 57907c478bd9Sstevel@tonic-gate static int 57917c478bd9Sstevel@tonic-gate cs_release_io(client_handle_t client_handle, io_req_t *ior) 57927c478bd9Sstevel@tonic-gate { 57937c478bd9Sstevel@tonic-gate cs_socket_t *sp; 57947c478bd9Sstevel@tonic-gate client_t *client; 57957c478bd9Sstevel@tonic-gate int error; 57967c478bd9Sstevel@tonic-gate int client_lock_acquired; 57977c478bd9Sstevel@tonic-gate uint32_t socket_num; 57987c478bd9Sstevel@tonic-gate 57997c478bd9Sstevel@tonic-gate #ifdef lint 58007c478bd9Sstevel@tonic-gate ior = NULL; 58017c478bd9Sstevel@tonic-gate #endif 58027c478bd9Sstevel@tonic-gate 58037c478bd9Sstevel@tonic-gate /* 58047c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 58057c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 58067c478bd9Sstevel@tonic-gate */ 58077c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 58087c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 58097c478bd9Sstevel@tonic-gate 58107c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 58117c478bd9Sstevel@tonic-gate 58127c478bd9Sstevel@tonic-gate /* 58137c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 58147c478bd9Sstevel@tonic-gate */ 58157c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 58167c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 58177c478bd9Sstevel@tonic-gate 58187c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 58197c478bd9Sstevel@tonic-gate 58207c478bd9Sstevel@tonic-gate /* 58217c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 58227c478bd9Sstevel@tonic-gate */ 58237c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 58247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58257c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58267c478bd9Sstevel@tonic-gate return (error); 58277c478bd9Sstevel@tonic-gate } 58287c478bd9Sstevel@tonic-gate 58297c478bd9Sstevel@tonic-gate /* 58307c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 58317c478bd9Sstevel@tonic-gate * this call. 58327c478bd9Sstevel@tonic-gate */ 58337c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 58347c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58357c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58367c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 58377c478bd9Sstevel@tonic-gate } 58387c478bd9Sstevel@tonic-gate 58397c478bd9Sstevel@tonic-gate /* 58407c478bd9Sstevel@tonic-gate * If RequestIO has not been done, we don't allow this call. 58417c478bd9Sstevel@tonic-gate */ 58427c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IO_DONE)) { 58437c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58447c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58457c478bd9Sstevel@tonic-gate return (CS_IN_USE); 58467c478bd9Sstevel@tonic-gate } 58477c478bd9Sstevel@tonic-gate 58487c478bd9Sstevel@tonic-gate socket_num = CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 58497c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 58507c478bd9Sstevel@tonic-gate 58517c478bd9Sstevel@tonic-gate #ifdef XXX 58527c478bd9Sstevel@tonic-gate /* 58537c478bd9Sstevel@tonic-gate * Check the passed IO allocation with the stored allocation; if 58547c478bd9Sstevel@tonic-gate * they don't match, then return an error. 58557c478bd9Sstevel@tonic-gate */ 58567c478bd9Sstevel@tonic-gate if ((client->io_alloc.BasePort1 != ior->BasePort1) || 58577c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts1 != ior->NumPorts1) || 58587c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes1 != ior->Attributes1) || 58597c478bd9Sstevel@tonic-gate (client->io_alloc.BasePort2 != ior->BasePort2) || 58607c478bd9Sstevel@tonic-gate (client->io_alloc.NumPorts2 != ior->NumPorts2) || 58617c478bd9Sstevel@tonic-gate (client->io_alloc.Attributes2 != ior->Attributes2) || 58627c478bd9Sstevel@tonic-gate (client->io_alloc.IOAddrLines != ior->IOAddrLines)) { 58637c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58647c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58657c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 58667c478bd9Sstevel@tonic-gate } 58677c478bd9Sstevel@tonic-gate #endif 58687c478bd9Sstevel@tonic-gate 58697c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 58707c478bd9Sstevel@tonic-gate /* 58717c478bd9Sstevel@tonic-gate * The code diverges here depending on if this socket supports 58727c478bd9Sstevel@tonic-gate * memory mapped IO windows or not. See comments in the 58737c478bd9Sstevel@tonic-gate * cs_request_io function for a description of what's 58747c478bd9Sstevel@tonic-gate * going on here. 58757c478bd9Sstevel@tonic-gate */ 58767c478bd9Sstevel@tonic-gate if (sp->io_mmap_window) { 58777c478bd9Sstevel@tonic-gate io_mmap_window_t *imw = sp->io_mmap_window; 58787c478bd9Sstevel@tonic-gate 58797c478bd9Sstevel@tonic-gate /* 58807c478bd9Sstevel@tonic-gate * We should never see this; if we do, it's an internal 58817c478bd9Sstevel@tonic-gate * consistency error. 58827c478bd9Sstevel@tonic-gate */ 58837c478bd9Sstevel@tonic-gate if (!imw->count) { 58847c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_io: socket %d !imw->count\n", 58857c478bd9Sstevel@tonic-gate sp->socket_num); 58867c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 58877c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 58887c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 58897c478bd9Sstevel@tonic-gate } 58907c478bd9Sstevel@tonic-gate 58917c478bd9Sstevel@tonic-gate /* 58927c478bd9Sstevel@tonic-gate * All common access handles for this type of adapter are 58937c478bd9Sstevel@tonic-gate * duped. We never give the original back to the caller, 58947c478bd9Sstevel@tonic-gate * so it's OK to unconditionally free the handle here. 58957c478bd9Sstevel@tonic-gate */ 58967c478bd9Sstevel@tonic-gate csx_FreeHandle(&ior->BasePort1.handle); 58977c478bd9Sstevel@tonic-gate 58987c478bd9Sstevel@tonic-gate /* 58997c478bd9Sstevel@tonic-gate * If the IO window referance count is zero, then deallocate 59007c478bd9Sstevel@tonic-gate * and disable this window. 59017c478bd9Sstevel@tonic-gate */ 59027c478bd9Sstevel@tonic-gate if (!--(imw->count)) { 59037c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, imw->number, NULL, 59047c478bd9Sstevel@tonic-gate NULL, NULL, 59057c478bd9Sstevel@tonic-gate ( 59067c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59077c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59087c478bd9Sstevel@tonic-gate } /* if (imw->count) */ 59097c478bd9Sstevel@tonic-gate } else { 59107c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 59117c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window1, 59127c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 59137c478bd9Sstevel@tonic-gate ( 59147c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59157c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59167c478bd9Sstevel@tonic-gate if (client->io_alloc.Window2 != PCMCIA_MAX_WINDOWS) 59177c478bd9Sstevel@tonic-gate (void) cs_setup_io_win(socket_num, client->io_alloc.Window2, 59187c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 59197c478bd9Sstevel@tonic-gate ( 59207c478bd9Sstevel@tonic-gate IO_DEALLOCATE_WINDOW | 59217c478bd9Sstevel@tonic-gate IO_DISABLE_WINDOW)); 59227c478bd9Sstevel@tonic-gate #ifdef USE_IOMMAP_WINDOW 59237c478bd9Sstevel@tonic-gate } /* if (sp->io_mmap_window) */ 59247c478bd9Sstevel@tonic-gate #endif /* USE_IOMMAP_WINDOW */ 59257c478bd9Sstevel@tonic-gate 59267c478bd9Sstevel@tonic-gate /* 59277c478bd9Sstevel@tonic-gate * Mark the client as not having any IO resources allocated. 59287c478bd9Sstevel@tonic-gate */ 59297c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IO_DONE | CLIENT_IO_ALLOCATED); 59307c478bd9Sstevel@tonic-gate 59317c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 59327c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 59337c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 59347c478bd9Sstevel@tonic-gate } 59357c478bd9Sstevel@tonic-gate 59367c478bd9Sstevel@tonic-gate /* 59377c478bd9Sstevel@tonic-gate * cs_find_io_win - finds an IO window that matches the parameters specified 59387c478bd9Sstevel@tonic-gate * in the flags argument 59397c478bd9Sstevel@tonic-gate * 59407c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for IO window on 59417c478bd9Sstevel@tonic-gate * *iwc - other window characteristics to match 59427c478bd9Sstevel@tonic-gate * *assigned_window - pointer to where we return the assigned 59437c478bd9Sstevel@tonic-gate * window number if we found a window or 59447c478bd9Sstevel@tonic-gate * undefined otherwise 59457c478bd9Sstevel@tonic-gate * *size - if non-NULL, the found window size will be stored here 59467c478bd9Sstevel@tonic-gate * 59477c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IO window found 59487c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if no windows match requirements 59497c478bd9Sstevel@tonic-gate */ 59507c478bd9Sstevel@tonic-gate static int 59517c478bd9Sstevel@tonic-gate cs_find_io_win(uint32_t sn, iowin_char_t *iwc, uint32_t *assigned_window, 59527c478bd9Sstevel@tonic-gate uint32_t *size) 59537c478bd9Sstevel@tonic-gate { 59547c478bd9Sstevel@tonic-gate inquire_window_t inquire_window, *iw; 59557c478bd9Sstevel@tonic-gate unsigned wn; 59567c478bd9Sstevel@tonic-gate 59577c478bd9Sstevel@tonic-gate iw = &inquire_window; 59587c478bd9Sstevel@tonic-gate 59597c478bd9Sstevel@tonic-gate for (wn = 0; wn < cs_globals.num_windows; wn++) { 59607c478bd9Sstevel@tonic-gate iowin_char_t *iowc; 59617c478bd9Sstevel@tonic-gate cs_window_t *cw; 59627c478bd9Sstevel@tonic-gate 59637c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) != NULL) { 59647c478bd9Sstevel@tonic-gate 59657c478bd9Sstevel@tonic-gate iw->window = wn; 59667c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, iw); 59677c478bd9Sstevel@tonic-gate 59687c478bd9Sstevel@tonic-gate iowc = &iw->iowin_char; 59697c478bd9Sstevel@tonic-gate 59707c478bd9Sstevel@tonic-gate if (WINDOW_FOR_SOCKET(iw->Sockets, sn) && 59717c478bd9Sstevel@tonic-gate WINDOW_AVAILABLE_FOR_IO(cw) && 59727c478bd9Sstevel@tonic-gate (iw->WndCaps & WC_IO) && 59737c478bd9Sstevel@tonic-gate ((iowc->IOWndCaps & iwc->IOWndCaps) == iwc->IOWndCaps)) { 59747c478bd9Sstevel@tonic-gate 59757c478bd9Sstevel@tonic-gate *assigned_window = wn; 59767c478bd9Sstevel@tonic-gate 59777c478bd9Sstevel@tonic-gate if (size) 59787c478bd9Sstevel@tonic-gate *size = iw->iowin_char.ReqGran; 59797c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 59807c478bd9Sstevel@tonic-gate } /* if (WINDOW_FOR_SOCKET) */ 59817c478bd9Sstevel@tonic-gate } /* cs_get_wp */ 59827c478bd9Sstevel@tonic-gate } /* for (wn) */ 59837c478bd9Sstevel@tonic-gate 59847c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 59857c478bd9Sstevel@tonic-gate } 59867c478bd9Sstevel@tonic-gate 59877c478bd9Sstevel@tonic-gate /* 59887c478bd9Sstevel@tonic-gate * cs_allocate_io_win - finds and allocates an IO window 59897c478bd9Sstevel@tonic-gate * 59907c478bd9Sstevel@tonic-gate * calling: sn - socket number to look for window on 59917c478bd9Sstevel@tonic-gate * Attributes - window attributes in io_req_t.Attributes format 59927c478bd9Sstevel@tonic-gate * *assigned_window - pointer to return assigned window number 59937c478bd9Sstevel@tonic-gate * 59947c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - IO window found and allocated 59957c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if cs_find_io_win couldn't find a 59967c478bd9Sstevel@tonic-gate * window that matches the passed criteria 59977c478bd9Sstevel@tonic-gate * 59987c478bd9Sstevel@tonic-gate * Note: This fucntion will find and allocate an IO window. The caller is 59997c478bd9Sstevel@tonic-gate * responsible for deallocating the window. 60007c478bd9Sstevel@tonic-gate */ 60017c478bd9Sstevel@tonic-gate static int 60027c478bd9Sstevel@tonic-gate cs_allocate_io_win(uint32_t sn, uint32_t Attributes, uint32_t *assigned_window) 60037c478bd9Sstevel@tonic-gate { 60047c478bd9Sstevel@tonic-gate iowin_char_t iowin_char; 60057c478bd9Sstevel@tonic-gate cs_window_t *cw; 60067c478bd9Sstevel@tonic-gate 60077c478bd9Sstevel@tonic-gate iowin_char.IOWndCaps = 60087c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WC_16BIT:WC_8BIT); 60097c478bd9Sstevel@tonic-gate 60107c478bd9Sstevel@tonic-gate if (cs_find_io_win(sn, &iowin_char, assigned_window, NULL) == 60117c478bd9Sstevel@tonic-gate CS_SUCCESS) { 60127c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(*assigned_window)) == NULL) 60137c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 60147c478bd9Sstevel@tonic-gate 60157c478bd9Sstevel@tonic-gate cw->state = (cw->state & CW_WINDOW_VALID) | (CW_ALLOCATED | CW_IO); 60167c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 60177c478bd9Sstevel@tonic-gate } 60187c478bd9Sstevel@tonic-gate 60197c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 60207c478bd9Sstevel@tonic-gate } 60217c478bd9Sstevel@tonic-gate 60227c478bd9Sstevel@tonic-gate /* 60237c478bd9Sstevel@tonic-gate * cs_setup_io_win - setup and destroy an IO window 60247c478bd9Sstevel@tonic-gate * 60257c478bd9Sstevel@tonic-gate * calling: sn - socket number 60267c478bd9Sstevel@tonic-gate * wn - window number 60277c478bd9Sstevel@tonic-gate * XXX Base - pointer to XXX 60287c478bd9Sstevel@tonic-gate * *NumPorts - pointer to number of allocated ports to return 60297c478bd9Sstevel@tonic-gate * IOAddrLines - number of IO address lines decoded by this card 60307c478bd9Sstevel@tonic-gate * Attributes - either io_req_t attributes, or a combination of 60317c478bd9Sstevel@tonic-gate * the following flags: 60327c478bd9Sstevel@tonic-gate * IO_DEALLOCATE_WINDOW - deallocate the window 60337c478bd9Sstevel@tonic-gate * IO_DISABLE_WINDOW - disable the window 60347c478bd9Sstevel@tonic-gate * When either of these two flags are set, *Base 60357c478bd9Sstevel@tonic-gate * and NumPorts should be NULL. 60367c478bd9Sstevel@tonic-gate * 60377c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if no failure 60387c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if error while trying to configure window 60397c478bd9Sstevel@tonic-gate * 60407c478bd9Sstevel@tonic-gate * Note: We use the IOAddrLines value to determine what base address to pass 60417c478bd9Sstevel@tonic-gate * to Socket Services. 60427c478bd9Sstevel@tonic-gate */ 60437c478bd9Sstevel@tonic-gate static int 60447c478bd9Sstevel@tonic-gate cs_setup_io_win(uint32_t sn, uint32_t wn, baseaddru_t *Base, uint32_t *NumPorts, 60457c478bd9Sstevel@tonic-gate uint32_t IOAddrLines, uint32_t Attributes) 60467c478bd9Sstevel@tonic-gate { 60477c478bd9Sstevel@tonic-gate set_window_t set_window; 60487c478bd9Sstevel@tonic-gate 60497c478bd9Sstevel@tonic-gate if (Attributes & (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW)) { 60507c478bd9Sstevel@tonic-gate 60517c478bd9Sstevel@tonic-gate if (Attributes & IO_DEALLOCATE_WINDOW) { 60527c478bd9Sstevel@tonic-gate cs_window_t *cw; 60537c478bd9Sstevel@tonic-gate 60547c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(wn)) == NULL) 60557c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 60567c478bd9Sstevel@tonic-gate cw->state &= CW_WINDOW_VALID; 60577c478bd9Sstevel@tonic-gate 60587c478bd9Sstevel@tonic-gate } /* IO_DEALLOCATE_WINDOW */ 60597c478bd9Sstevel@tonic-gate 60607c478bd9Sstevel@tonic-gate if (Attributes & IO_DISABLE_WINDOW) { 60617c478bd9Sstevel@tonic-gate get_window_t get_window; 60627c478bd9Sstevel@tonic-gate 60637c478bd9Sstevel@tonic-gate get_window.window = wn; 60647c478bd9Sstevel@tonic-gate 60657c478bd9Sstevel@tonic-gate SocketServices(SS_GetWindow, &get_window); 60667c478bd9Sstevel@tonic-gate 60677c478bd9Sstevel@tonic-gate set_window.socket = get_window.socket; 60687c478bd9Sstevel@tonic-gate set_window.window = get_window.window; 60697c478bd9Sstevel@tonic-gate set_window.speed = get_window.speed; 60707c478bd9Sstevel@tonic-gate set_window.base = 0; 60717c478bd9Sstevel@tonic-gate set_window.WindowSize = get_window.size; 60727c478bd9Sstevel@tonic-gate set_window.state = get_window.state & ~WS_ENABLED; 60737c478bd9Sstevel@tonic-gate 60747c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 60757c478bd9Sstevel@tonic-gate 60767c478bd9Sstevel@tonic-gate SocketServices(SS_SetWindow, &set_window); 60777c478bd9Sstevel@tonic-gate } /* IO_DISABLE_WINDOW */ 60787c478bd9Sstevel@tonic-gate 60797c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 60807c478bd9Sstevel@tonic-gate 60817c478bd9Sstevel@tonic-gate } /* if (IO_DEALLOCATE_WINDOW | IO_DISABLE_WINDOW) */ 60827c478bd9Sstevel@tonic-gate 60837c478bd9Sstevel@tonic-gate /* 60847c478bd9Sstevel@tonic-gate * See if we can allow Socket Services to select the base address 60857c478bd9Sstevel@tonic-gate * value for this card; if the client has specified a non-zero 60867c478bd9Sstevel@tonic-gate * base IO address but the card doesn't decode enough IO 60877c478bd9Sstevel@tonic-gate * address lines to uniquely use that address, then we have 60887c478bd9Sstevel@tonic-gate * the flexibility to choose an alternative base address. 60897c478bd9Sstevel@tonic-gate * XXX - Is this really correct in all cases? 60907c478bd9Sstevel@tonic-gate */ 60917c478bd9Sstevel@tonic-gate if (!IOAddrLines) 60927c478bd9Sstevel@tonic-gate Base->base = 0; 60937c478bd9Sstevel@tonic-gate else 60947c478bd9Sstevel@tonic-gate Base->base = IOADDR_FROBNITZ(Base->base, IOAddrLines); 60957c478bd9Sstevel@tonic-gate 60967c478bd9Sstevel@tonic-gate set_window.socket = sn; 60977c478bd9Sstevel@tonic-gate set_window.window = wn; 60987c478bd9Sstevel@tonic-gate set_window.speed = IO_WIN_SPEED; 60997c478bd9Sstevel@tonic-gate set_window.base = Base->base; 61007c478bd9Sstevel@tonic-gate set_window.WindowSize = *NumPorts; 61017c478bd9Sstevel@tonic-gate set_window.state = (WS_ENABLED | WS_IO | 61027c478bd9Sstevel@tonic-gate ((Attributes & IO_DATA_PATH_WIDTH_16)?WS_16BIT:0)); 61037c478bd9Sstevel@tonic-gate 61047c478bd9Sstevel@tonic-gate cs_set_acc_attributes(&set_window, Attributes); 61057c478bd9Sstevel@tonic-gate 61067c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetWindow, &set_window) != SUCCESS) 61077c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 61087c478bd9Sstevel@tonic-gate 61097c478bd9Sstevel@tonic-gate Base->base = set_window.base; 61107c478bd9Sstevel@tonic-gate Base->handle = set_window.handle; 61117c478bd9Sstevel@tonic-gate *NumPorts = set_window.WindowSize; 61127c478bd9Sstevel@tonic-gate 61137c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 61147c478bd9Sstevel@tonic-gate } 61157c478bd9Sstevel@tonic-gate 61167c478bd9Sstevel@tonic-gate /* 61177c478bd9Sstevel@tonic-gate * ==== IRQ handling functions ==== 61187c478bd9Sstevel@tonic-gate */ 61197c478bd9Sstevel@tonic-gate 61207c478bd9Sstevel@tonic-gate /* 61217c478bd9Sstevel@tonic-gate * cs_request_irq - add's client's IRQ handler; supports RequestIRQ 61227c478bd9Sstevel@tonic-gate * 61237c478bd9Sstevel@tonic-gate * calling: irq_req_t.Attributes - must have the IRQ_TYPE_EXCLUSIVE 61247c478bd9Sstevel@tonic-gate * flag set, and all other flags clear, or 61257c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE will be returned 61267c478bd9Sstevel@tonic-gate * 61277c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources available for client 61287c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be allocated 61297c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 61307c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 61317c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card is in socket 61327c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any of the unsupported Attribute 61337c478bd9Sstevel@tonic-gate * flags are set 61347c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 61357c478bd9Sstevel@tonic-gate * already been done 61367c478bd9Sstevel@tonic-gate * CS_IN_USE - IRQ ports already in use or function has 61377c478bd9Sstevel@tonic-gate * already been called 61387c478bd9Sstevel@tonic-gate * 61397c478bd9Sstevel@tonic-gate * Note: We only allow level-mode interrupts. 61407c478bd9Sstevel@tonic-gate */ 61417c478bd9Sstevel@tonic-gate static int 61427c478bd9Sstevel@tonic-gate cs_request_irq(client_handle_t client_handle, irq_req_t *irqr) 61437c478bd9Sstevel@tonic-gate { 61447c478bd9Sstevel@tonic-gate cs_socket_t *sp; 61457c478bd9Sstevel@tonic-gate client_t *client; 61467c478bd9Sstevel@tonic-gate set_irq_handler_t set_irq_handler; 61477c478bd9Sstevel@tonic-gate int error; 61487c478bd9Sstevel@tonic-gate int client_lock_acquired; 61497c478bd9Sstevel@tonic-gate 61507c478bd9Sstevel@tonic-gate /* 61517c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 61527c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 61537c478bd9Sstevel@tonic-gate */ 61547c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 61557c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 61567c478bd9Sstevel@tonic-gate 61577c478bd9Sstevel@tonic-gate /* 61587c478bd9Sstevel@tonic-gate * Make sure that none of the unsupported or reserved flags are set. 61597c478bd9Sstevel@tonic-gate */ 61607c478bd9Sstevel@tonic-gate if ((irqr->Attributes & (IRQ_TYPE_TIME | IRQ_TYPE_DYNAMIC_SHARING | 61617c478bd9Sstevel@tonic-gate IRQ_FIRST_SHARED | IRQ_PULSE_ALLOCATED | 61627c478bd9Sstevel@tonic-gate IRQ_FORCED_PULSE)) || 61637c478bd9Sstevel@tonic-gate !(irqr->Attributes & IRQ_TYPE_EXCLUSIVE)) 61647c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 61657c478bd9Sstevel@tonic-gate 61667c478bd9Sstevel@tonic-gate /* 61677c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 61687c478bd9Sstevel@tonic-gate */ 61697c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 61707c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 61717c478bd9Sstevel@tonic-gate 61727c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 61737c478bd9Sstevel@tonic-gate 61747c478bd9Sstevel@tonic-gate /* 61757c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 61767c478bd9Sstevel@tonic-gate */ 61777c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 61787c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61797c478bd9Sstevel@tonic-gate return (error); 61807c478bd9Sstevel@tonic-gate } 61817c478bd9Sstevel@tonic-gate 61827c478bd9Sstevel@tonic-gate /* 61837c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 61847c478bd9Sstevel@tonic-gate * this call. 61857c478bd9Sstevel@tonic-gate */ 61867c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 61877c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61887c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 61897c478bd9Sstevel@tonic-gate } 61907c478bd9Sstevel@tonic-gate 61917c478bd9Sstevel@tonic-gate /* 61927c478bd9Sstevel@tonic-gate * If RequestIRQ has already been done, we don't allow this call. 61937c478bd9Sstevel@tonic-gate */ 61947c478bd9Sstevel@tonic-gate if (client->flags & REQ_IRQ_DONE) { 61957c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 61967c478bd9Sstevel@tonic-gate return (CS_IN_USE); 61977c478bd9Sstevel@tonic-gate } 61987c478bd9Sstevel@tonic-gate 61997c478bd9Sstevel@tonic-gate /* 62007c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 62017c478bd9Sstevel@tonic-gate * for this client, then return an error. 62027c478bd9Sstevel@tonic-gate */ 62037c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 62047c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62057c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 62067c478bd9Sstevel@tonic-gate } 62077c478bd9Sstevel@tonic-gate 62087c478bd9Sstevel@tonic-gate /* 62097c478bd9Sstevel@tonic-gate * Set up the parameters and ask Socket Services to give us an IRQ 62107c478bd9Sstevel@tonic-gate * for this client. We don't really do much, since the IRQ 62117c478bd9Sstevel@tonic-gate * resources are managed by SS and the kernel. We also don't 62127c478bd9Sstevel@tonic-gate * care which IRQ level we are given. 62137c478bd9Sstevel@tonic-gate */ 62147c478bd9Sstevel@tonic-gate set_irq_handler.socket = 62157c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 62167c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 62177c478bd9Sstevel@tonic-gate set_irq_handler.irq = IRQ_ANY; 62187c478bd9Sstevel@tonic-gate 62197c478bd9Sstevel@tonic-gate set_irq_handler.handler_id = client_handle; 62207c478bd9Sstevel@tonic-gate set_irq_handler.handler = (f_t *)irqr->irq_handler; 62217c478bd9Sstevel@tonic-gate set_irq_handler.arg1 = irqr->irq_handler_arg; 62227c478bd9Sstevel@tonic-gate set_irq_handler.arg2 = NULL; 62237c478bd9Sstevel@tonic-gate 62247c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_SetIRQHandler, 62257c478bd9Sstevel@tonic-gate &set_irq_handler)) != SUCCESS) { 62267c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62277c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 62287c478bd9Sstevel@tonic-gate } 62297c478bd9Sstevel@tonic-gate 62307c478bd9Sstevel@tonic-gate irqr->iblk_cookie = set_irq_handler.iblk_cookie; 62317c478bd9Sstevel@tonic-gate irqr->idev_cookie = set_irq_handler.idev_cookie; 62327c478bd9Sstevel@tonic-gate 62337c478bd9Sstevel@tonic-gate /* 62347c478bd9Sstevel@tonic-gate * Save the allocated IRQ information for this client. 62357c478bd9Sstevel@tonic-gate */ 62367c478bd9Sstevel@tonic-gate client->irq_alloc.Attributes = irqr->Attributes; 62377c478bd9Sstevel@tonic-gate client->irq_alloc.irq = set_irq_handler.irq; 62387c478bd9Sstevel@tonic-gate client->irq_alloc.handler_id = set_irq_handler.handler_id; 62397c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler = (f_t *)set_irq_handler.handler; 62407c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg1 = set_irq_handler.arg1; 62417c478bd9Sstevel@tonic-gate client->irq_alloc.irq_handler_arg2 = set_irq_handler.arg2; 62427c478bd9Sstevel@tonic-gate 62437c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 62447c478bd9Sstevel@tonic-gate if (cs_debug > 0) 62457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_irq: socket %d irqr->Attributes 0x%x " 62467c478bd9Sstevel@tonic-gate "set_irq_handler.irq 0x%x\n", 62477c478bd9Sstevel@tonic-gate sp->socket_num, 62487c478bd9Sstevel@tonic-gate (int)irqr->Attributes, 62497c478bd9Sstevel@tonic-gate set_irq_handler.irq); 62507c478bd9Sstevel@tonic-gate #endif 62517c478bd9Sstevel@tonic-gate 62527c478bd9Sstevel@tonic-gate /* 62537c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestIRQ call. 62547c478bd9Sstevel@tonic-gate */ 62557c478bd9Sstevel@tonic-gate client->flags |= (REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 62567c478bd9Sstevel@tonic-gate 62577c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 62587c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 62597c478bd9Sstevel@tonic-gate } 62607c478bd9Sstevel@tonic-gate 62617c478bd9Sstevel@tonic-gate /* 62627c478bd9Sstevel@tonic-gate * cs_release_irq - releases IRQ resources allocated by RequestIRQ; this is 62637c478bd9Sstevel@tonic-gate * ReleaseIRQ 62647c478bd9Sstevel@tonic-gate * 62657c478bd9Sstevel@tonic-gate * calling: cs_release_irq(client_handle_t, irq_req_t *) 62667c478bd9Sstevel@tonic-gate * 62677c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if IRQ resources sucessfully deallocated 62687c478bd9Sstevel@tonic-gate * CS_BAD_IRQ - if IRQ can not be deallocated 62697c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - client handle is invalid 62707c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 62717c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has been 62727c478bd9Sstevel@tonic-gate * done without a ReleaseConfiguration 62737c478bd9Sstevel@tonic-gate * CS_IN_USE - no RequestIRQ has been done 62747c478bd9Sstevel@tonic-gate */ 62757c478bd9Sstevel@tonic-gate static int 62767c478bd9Sstevel@tonic-gate cs_release_irq(client_handle_t client_handle, irq_req_t *irqr) 62777c478bd9Sstevel@tonic-gate { 62787c478bd9Sstevel@tonic-gate cs_socket_t *sp; 62797c478bd9Sstevel@tonic-gate client_t *client; 62807c478bd9Sstevel@tonic-gate clear_irq_handler_t clear_irq_handler; 62817c478bd9Sstevel@tonic-gate int error; 62827c478bd9Sstevel@tonic-gate int client_lock_acquired; 62837c478bd9Sstevel@tonic-gate 62847c478bd9Sstevel@tonic-gate #ifdef lint 62857c478bd9Sstevel@tonic-gate irqr = NULL; 62867c478bd9Sstevel@tonic-gate #endif 62877c478bd9Sstevel@tonic-gate 62887c478bd9Sstevel@tonic-gate /* 62897c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 62907c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 62917c478bd9Sstevel@tonic-gate */ 62927c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 62937c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 62947c478bd9Sstevel@tonic-gate 62957c478bd9Sstevel@tonic-gate /* 62967c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 62977c478bd9Sstevel@tonic-gate */ 62987c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 62997c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 63007c478bd9Sstevel@tonic-gate 63017c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 63027c478bd9Sstevel@tonic-gate 63037c478bd9Sstevel@tonic-gate /* 63047c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 63057c478bd9Sstevel@tonic-gate */ 63067c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 63077c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63087c478bd9Sstevel@tonic-gate return (error); 63097c478bd9Sstevel@tonic-gate } 63107c478bd9Sstevel@tonic-gate 63117c478bd9Sstevel@tonic-gate /* 63127c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 63137c478bd9Sstevel@tonic-gate * this call. 63147c478bd9Sstevel@tonic-gate */ 63157c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 63167c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63177c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 63187c478bd9Sstevel@tonic-gate } 63197c478bd9Sstevel@tonic-gate 63207c478bd9Sstevel@tonic-gate /* 63217c478bd9Sstevel@tonic-gate * If RequestIRQ has not been done, we don't allow this call. 63227c478bd9Sstevel@tonic-gate */ 63237c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_IRQ_DONE)) { 63247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63257c478bd9Sstevel@tonic-gate return (CS_IN_USE); 63267c478bd9Sstevel@tonic-gate } 63277c478bd9Sstevel@tonic-gate 63287c478bd9Sstevel@tonic-gate /* 63297c478bd9Sstevel@tonic-gate * Tell Socket Services that we want to deregister this client's 63307c478bd9Sstevel@tonic-gate * IRQ handler. 63317c478bd9Sstevel@tonic-gate */ 63327c478bd9Sstevel@tonic-gate clear_irq_handler.socket = 63337c478bd9Sstevel@tonic-gate CS_MAKE_SOCKET_NUMBER(GET_CLIENT_SOCKET(client_handle), 63347c478bd9Sstevel@tonic-gate GET_CLIENT_FUNCTION(client_handle)); 63357c478bd9Sstevel@tonic-gate clear_irq_handler.handler_id = client->irq_alloc.handler_id; 63367c478bd9Sstevel@tonic-gate clear_irq_handler.handler = (f_t *)client->irq_alloc.irq_handler; 63377c478bd9Sstevel@tonic-gate 63387c478bd9Sstevel@tonic-gate /* 63397c478bd9Sstevel@tonic-gate * At this point, we should never fail this SS call; if we do, it 63407c478bd9Sstevel@tonic-gate * means that there is an internal consistancy error in either 63417c478bd9Sstevel@tonic-gate * Card Services or Socket Services. 63427c478bd9Sstevel@tonic-gate */ 63437c478bd9Sstevel@tonic-gate if ((error = SocketServices(SS_ClearIRQHandler, &clear_irq_handler)) != 63447c478bd9Sstevel@tonic-gate SUCCESS) { 63457c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63467c478bd9Sstevel@tonic-gate return (CS_BAD_IRQ); 63477c478bd9Sstevel@tonic-gate } 63487c478bd9Sstevel@tonic-gate 63497c478bd9Sstevel@tonic-gate /* 63507c478bd9Sstevel@tonic-gate * Mark the client as not having any IRQ resources allocated. 63517c478bd9Sstevel@tonic-gate */ 63527c478bd9Sstevel@tonic-gate client->flags &= ~(REQ_IRQ_DONE | CLIENT_IRQ_ALLOCATED); 63537c478bd9Sstevel@tonic-gate 63547c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 63557c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 63567c478bd9Sstevel@tonic-gate } 63577c478bd9Sstevel@tonic-gate 63587c478bd9Sstevel@tonic-gate /* 63597c478bd9Sstevel@tonic-gate * ==== configuration handling functions ==== 63607c478bd9Sstevel@tonic-gate */ 63617c478bd9Sstevel@tonic-gate 63627c478bd9Sstevel@tonic-gate /* 63637c478bd9Sstevel@tonic-gate * cs_request_configuration - sets up socket and card configuration on behalf 63647c478bd9Sstevel@tonic-gate * of the client; this is RequestConfiguration 63657c478bd9Sstevel@tonic-gate * 63667c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully set 63677c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 63687c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 63697c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 63707c478bd9Sstevel@tonic-gate * are set 63717c478bd9Sstevel@tonic-gate * CS_BAD_TYPE - if the socket doesn't support a mem and IO 63727c478bd9Sstevel@tonic-gate * interface (SOCKET_INTERFACE_MEMORY_AND_IO set) 63737c478bd9Sstevel@tonic-gate * CS_CONFIGURATION_LOCKED - a RequestConfiguration has 63747c478bd9Sstevel@tonic-gate * already been done 63757c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 63767c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 63777c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 63787c478bd9Sstevel@tonic-gate * 63797c478bd9Sstevel@tonic-gate * Bug ID: 1193637 - Card Services RequestConfiguration does not conform 63807c478bd9Sstevel@tonic-gate * to PCMCIA standard 63817c478bd9Sstevel@tonic-gate * We allow clients to do a RequestConfiguration even if they haven't 63827c478bd9Sstevel@tonic-gate * done a RequestIO or RequestIRQ. 63837c478bd9Sstevel@tonic-gate */ 63847c478bd9Sstevel@tonic-gate static int 63857c478bd9Sstevel@tonic-gate cs_request_configuration(client_handle_t client_handle, config_req_t *cr) 63867c478bd9Sstevel@tonic-gate { 63877c478bd9Sstevel@tonic-gate cs_socket_t *sp; 63887c478bd9Sstevel@tonic-gate client_t *client; 63897c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 63907c478bd9Sstevel@tonic-gate set_socket_t set_socket; 63917c478bd9Sstevel@tonic-gate get_socket_t get_socket; 63927c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 63937c478bd9Sstevel@tonic-gate int error; 63947c478bd9Sstevel@tonic-gate uint32_t newoffset; 63957c478bd9Sstevel@tonic-gate int client_lock_acquired; 63967c478bd9Sstevel@tonic-gate 63977c478bd9Sstevel@tonic-gate /* 63987c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 63997c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 64007c478bd9Sstevel@tonic-gate */ 64017c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 64027c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 64037c478bd9Sstevel@tonic-gate 64047c478bd9Sstevel@tonic-gate #ifdef XXX 64057c478bd9Sstevel@tonic-gate /* 64067c478bd9Sstevel@tonic-gate * If the client specifies Vcc = 0 and any non-zero value for 64077c478bd9Sstevel@tonic-gate * either of the Vpp members, that's an illegal condition. 64087c478bd9Sstevel@tonic-gate */ 64097c478bd9Sstevel@tonic-gate if (!(cr->Vcc) && (cr->Vpp1 || cr->Vpp2)) 64107c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 64117c478bd9Sstevel@tonic-gate #endif 64127c478bd9Sstevel@tonic-gate 64137c478bd9Sstevel@tonic-gate /* 64147c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 64157c478bd9Sstevel@tonic-gate */ 64167c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 64177c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64187c478bd9Sstevel@tonic-gate 64197c478bd9Sstevel@tonic-gate /* 64207c478bd9Sstevel@tonic-gate * If the client is asking for a memory and IO interface on this 64217c478bd9Sstevel@tonic-gate * socket, then check the socket capabilities to be sure that 64227c478bd9Sstevel@tonic-gate * this socket supports this configuration. 64237c478bd9Sstevel@tonic-gate */ 64247c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) { 64257c478bd9Sstevel@tonic-gate inquire_socket_t inquire_socket; 64267c478bd9Sstevel@tonic-gate 64277c478bd9Sstevel@tonic-gate inquire_socket.socket = sp->socket_num; 64287c478bd9Sstevel@tonic-gate 64297c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireSocket, &inquire_socket) != SUCCESS) 64307c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64317c478bd9Sstevel@tonic-gate 64327c478bd9Sstevel@tonic-gate if (!(inquire_socket.SocketCaps & IF_IO)) 64337c478bd9Sstevel@tonic-gate return (CS_BAD_TYPE); 64347c478bd9Sstevel@tonic-gate 64357c478bd9Sstevel@tonic-gate } /* if (SOCKET_INTERFACE_MEMORY_AND_IO) */ 64367c478bd9Sstevel@tonic-gate 64377c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 64387c478bd9Sstevel@tonic-gate 64397c478bd9Sstevel@tonic-gate /* 64407c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 64417c478bd9Sstevel@tonic-gate */ 64427c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 64437c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64447c478bd9Sstevel@tonic-gate return (error); 64457c478bd9Sstevel@tonic-gate } 64467c478bd9Sstevel@tonic-gate 64477c478bd9Sstevel@tonic-gate /* 64487c478bd9Sstevel@tonic-gate * If RequestConfiguration has already been done, we don't allow 64497c478bd9Sstevel@tonic-gate * this call. 64507c478bd9Sstevel@tonic-gate */ 64517c478bd9Sstevel@tonic-gate if (client->flags & REQ_CONFIGURATION_DONE) { 64527c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64537c478bd9Sstevel@tonic-gate return (CS_CONFIGURATION_LOCKED); 64547c478bd9Sstevel@tonic-gate } 64557c478bd9Sstevel@tonic-gate 64567c478bd9Sstevel@tonic-gate /* 64577c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 64587c478bd9Sstevel@tonic-gate * for this client, then return an error. 64597c478bd9Sstevel@tonic-gate */ 64607c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 64617c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64627c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 64637c478bd9Sstevel@tonic-gate } 64647c478bd9Sstevel@tonic-gate 64657c478bd9Sstevel@tonic-gate /* 64667c478bd9Sstevel@tonic-gate * At this point, most of the client's calling parameters have been 64677c478bd9Sstevel@tonic-gate * validated, so we can go ahead and configure the socket and 64687c478bd9Sstevel@tonic-gate * the card. 64697c478bd9Sstevel@tonic-gate */ 64707c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 64717c478bd9Sstevel@tonic-gate 64727c478bd9Sstevel@tonic-gate /* 64737c478bd9Sstevel@tonic-gate * Configure the socket with the interface type and voltages requested 64747c478bd9Sstevel@tonic-gate * by the client. 64757c478bd9Sstevel@tonic-gate */ 64767c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 64777c478bd9Sstevel@tonic-gate 64787c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 64797c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 64807c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 64817c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 64827c478bd9Sstevel@tonic-gate } 64837c478bd9Sstevel@tonic-gate 64847c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 64857c478bd9Sstevel@tonic-gate if (cs_debug > 0) 64867c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d " 64877c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 64887c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 64897c478bd9Sstevel@tonic-gate sp->socket_num, 64907c478bd9Sstevel@tonic-gate (int)client->irq_alloc.irq, 64917c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 64927c478bd9Sstevel@tonic-gate #endif 64937c478bd9Sstevel@tonic-gate 64947c478bd9Sstevel@tonic-gate bzero(&set_socket, sizeof (set_socket)); 64957c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 64967c478bd9Sstevel@tonic-gate set_socket.IREQRouting = client->irq_alloc.irq & ~IRQ_ENABLE; 64977c478bd9Sstevel@tonic-gate 64987c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 64997c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 65007c478bd9Sstevel@tonic-gate 65017c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vcc, VCC, 65027c478bd9Sstevel@tonic-gate &set_socket.VccLevel) != CS_SUCCESS) { 65037c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65047c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65057c478bd9Sstevel@tonic-gate return (CS_BAD_VCC); 65067c478bd9Sstevel@tonic-gate } 65077c478bd9Sstevel@tonic-gate 65087c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp1, VPP1, 65097c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 65107c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65127c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 65137c478bd9Sstevel@tonic-gate } 65147c478bd9Sstevel@tonic-gate 65157c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, cr->Vpp2, VPP2, 65167c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 65177c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65187c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65197c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 65207c478bd9Sstevel@tonic-gate } 65217c478bd9Sstevel@tonic-gate 65227c478bd9Sstevel@tonic-gate if (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) 65237c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 65247c478bd9Sstevel@tonic-gate else { 65257c478bd9Sstevel@tonic-gate set_socket.IFType = IF_IO; 65267c478bd9Sstevel@tonic-gate 65277c478bd9Sstevel@tonic-gate /* 65287c478bd9Sstevel@tonic-gate * The Cirrus Logic PD6710/672X/others? adapters will write 65297c478bd9Sstevel@tonic-gate * protect the CIS if the socket is in MEMORY mode and the 65307c478bd9Sstevel@tonic-gate * WP/IOCS16 pin is true. When this happens, the CIS registers 65317c478bd9Sstevel@tonic-gate * will fail to be written. Go ahead and set the socket, 65327c478bd9Sstevel@tonic-gate * even though the event mask isn't complete yet, so we can 65337c478bd9Sstevel@tonic-gate * configure the adapter. Afterwards, set the socket again 65347c478bd9Sstevel@tonic-gate * to make sure the event mask is correct. 65357c478bd9Sstevel@tonic-gate */ 65367c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 65377c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 65387c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65397c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65407c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 65417c478bd9Sstevel@tonic-gate } 65427c478bd9Sstevel@tonic-gate } 65437c478bd9Sstevel@tonic-gate 65447c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 65457c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 65467c478bd9Sstevel@tonic-gate 65477c478bd9Sstevel@tonic-gate /* 65487c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 65497c478bd9Sstevel@tonic-gate * registers. 65507c478bd9Sstevel@tonic-gate */ 65517c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 65527c478bd9Sstevel@tonic-gate client->config_regs_offset = cr->ConfigBase; 65537c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 65547c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 65557c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 65567c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 65577c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 65587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 65597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: socket %d can't init " 65607c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 65617c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 65627c478bd9Sstevel@tonic-gate } 65637c478bd9Sstevel@tonic-gate 65647c478bd9Sstevel@tonic-gate /* 65657c478bd9Sstevel@tonic-gate * Setup the config register pointers. 65667c478bd9Sstevel@tonic-gate * Note that these pointers are not the complete virtual address; 65677c478bd9Sstevel@tonic-gate * the complete address is constructed each time the registers 65687c478bd9Sstevel@tonic-gate * are accessed. 65697c478bd9Sstevel@tonic-gate */ 65707c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 65717c478bd9Sstevel@tonic-gate crt = &client->config_regs; 65727c478bd9Sstevel@tonic-gate client->present = cr->Present; 65737c478bd9Sstevel@tonic-gate 65747c478bd9Sstevel@tonic-gate bzero((char *)crt, sizeof (config_regs_t)); 65757c478bd9Sstevel@tonic-gate 65767c478bd9Sstevel@tonic-gate /* Configuration Option Register */ 65777c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 65787c478bd9Sstevel@tonic-gate crt->cor_p = (newoffset + CONFIG_OPTION_REG_OFFSET); 65797c478bd9Sstevel@tonic-gate 65807c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 65817c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) 65827c478bd9Sstevel@tonic-gate crt->ccsr_p = (newoffset + CONFIG_STATUS_REG_OFFSET); 65837c478bd9Sstevel@tonic-gate 65847c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 65857c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) 65867c478bd9Sstevel@tonic-gate crt->prr_p = (newoffset + CONFIG_PINREPL_REG_OFFSET); 65877c478bd9Sstevel@tonic-gate 65887c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 65897c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) 65907c478bd9Sstevel@tonic-gate crt->scr_p = (newoffset + CONFIG_COPY_REG_OFFSET); 65917c478bd9Sstevel@tonic-gate 65927c478bd9Sstevel@tonic-gate /* Extended Status Register */ 65937c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) 65947c478bd9Sstevel@tonic-gate crt->exstat_p = (newoffset + CONFIG_EXSTAT_REG_OFFSET); 65957c478bd9Sstevel@tonic-gate 65967c478bd9Sstevel@tonic-gate /* IO Base 0 Register */ 65977c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 65987c478bd9Sstevel@tonic-gate crt->iobase0_p = (newoffset + CONFIG_IOBASE0_REG_OFFSET); 65997c478bd9Sstevel@tonic-gate 66007c478bd9Sstevel@tonic-gate /* IO Base 1 Register */ 66017c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE1_REG_PRESENT) 66027c478bd9Sstevel@tonic-gate crt->iobase1_p = (newoffset + CONFIG_IOBASE1_REG_OFFSET); 66037c478bd9Sstevel@tonic-gate 66047c478bd9Sstevel@tonic-gate /* IO Base 2 Register */ 66057c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE2_REG_PRESENT) 66067c478bd9Sstevel@tonic-gate crt->iobase2_p = (newoffset + CONFIG_IOBASE2_REG_OFFSET); 66077c478bd9Sstevel@tonic-gate 66087c478bd9Sstevel@tonic-gate /* IO Base 3 Register */ 66097c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE3_REG_PRESENT) 66107c478bd9Sstevel@tonic-gate crt->iobase3_p = (newoffset + CONFIG_IOBASE3_REG_OFFSET); 66117c478bd9Sstevel@tonic-gate 66127c478bd9Sstevel@tonic-gate /* IO Limit Register */ 66137c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) 66147c478bd9Sstevel@tonic-gate crt->iolimit_p = (newoffset + CONFIG_IOLIMIT_REG_OFFSET); 66157c478bd9Sstevel@tonic-gate 66167c478bd9Sstevel@tonic-gate /* 66177c478bd9Sstevel@tonic-gate * Setup the bits in the PRR mask that are valid; this is easy, just 66187c478bd9Sstevel@tonic-gate * copy the Pin value that the client gave us. Note that for 66197c478bd9Sstevel@tonic-gate * this to work, the client must set both of the XXX_STATUS 66207c478bd9Sstevel@tonic-gate * and the XXX_EVENT bits in the Pin member. 66217c478bd9Sstevel@tonic-gate */ 66227c478bd9Sstevel@tonic-gate client->pin = cr->Pin; 66237c478bd9Sstevel@tonic-gate 66247c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 66257c478bd9Sstevel@tonic-gate if (cs_debug > 128) 66267c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration: client->pin 0x%x " 66277c478bd9Sstevel@tonic-gate "client->config_regs_offset 0x%x newoffset 0x%x cor_p 0x%x " 66287c478bd9Sstevel@tonic-gate "ccsr_p 0x%x prr_p 0x%x scr_p 0x%x\n", 66297c478bd9Sstevel@tonic-gate client->pin, (int)client->config_regs_offset, newoffset, 66307c478bd9Sstevel@tonic-gate (int)crt->cor_p, (int)crt->ccsr_p, (int)crt->prr_p, 66317c478bd9Sstevel@tonic-gate (int)crt->scr_p); 66327c478bd9Sstevel@tonic-gate #endif 66337c478bd9Sstevel@tonic-gate 66347c478bd9Sstevel@tonic-gate /* 66357c478bd9Sstevel@tonic-gate * If the socket isn't in IO mode, WP is asserted, and we're going to 66367c478bd9Sstevel@tonic-gate * write any of the config registers, issue a warning. 66377c478bd9Sstevel@tonic-gate */ 66387c478bd9Sstevel@tonic-gate if ((client->present != 0) && 66397c478bd9Sstevel@tonic-gate (!(cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO)) && 66407c478bd9Sstevel@tonic-gate (get_socket.state & SBM_WP)) { 66417c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!cs_request_configuration: attempting to " 66427c478bd9Sstevel@tonic-gate "write CIS config regs with WP set\n"); 66437c478bd9Sstevel@tonic-gate } 66447c478bd9Sstevel@tonic-gate 66457c478bd9Sstevel@tonic-gate /* 66467c478bd9Sstevel@tonic-gate * Write any configuration registers that the client tells us are 66477c478bd9Sstevel@tonic-gate * present to the card; save a copy of what we wrote so that we 66487c478bd9Sstevel@tonic-gate * can return them if the client calls GetConfigurationInfo. 66497c478bd9Sstevel@tonic-gate * The order in which we write the configuration registers is 66507c478bd9Sstevel@tonic-gate * specified by the PCMCIA spec; we must write the socket/copy 66517c478bd9Sstevel@tonic-gate * register first (if it exists), and then we can write the 66527c478bd9Sstevel@tonic-gate * registers in any arbitrary order. 66537c478bd9Sstevel@tonic-gate */ 66547c478bd9Sstevel@tonic-gate /* Socket and Copy Register */ 66557c478bd9Sstevel@tonic-gate if (client->present & CONFIG_COPY_REG_PRESENT) { 66567c478bd9Sstevel@tonic-gate crt->scr = cr->Copy; 66577c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->scr_p, crt->scr); 66587c478bd9Sstevel@tonic-gate } 66597c478bd9Sstevel@tonic-gate 66607c478bd9Sstevel@tonic-gate /* Pin Replacement Register */ 66617c478bd9Sstevel@tonic-gate if (client->present & CONFIG_PINREPL_REG_PRESENT) { 66627c478bd9Sstevel@tonic-gate crt->prr = cr->Pin; 66637c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->prr_p, crt->prr); 66647c478bd9Sstevel@tonic-gate } 66657c478bd9Sstevel@tonic-gate 66667c478bd9Sstevel@tonic-gate /* Configuration and Status Register */ 66677c478bd9Sstevel@tonic-gate /* XXX should we set CCSR_SIG_CHG in the CCSR? XXX */ 66687c478bd9Sstevel@tonic-gate if (client->present & CONFIG_STATUS_REG_PRESENT) { 66697c478bd9Sstevel@tonic-gate crt->ccsr = cr->Status; 66707c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->ccsr_p, crt->ccsr); 66717c478bd9Sstevel@tonic-gate } 66727c478bd9Sstevel@tonic-gate 66737c478bd9Sstevel@tonic-gate /* Extended Status Register */ 66747c478bd9Sstevel@tonic-gate if (client->present & CONFIG_EXSTAT_REG_PRESENT) { 66757c478bd9Sstevel@tonic-gate crt->exstat = cr->ExtendedStatus; 66767c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->exstat_p, crt->exstat); 66777c478bd9Sstevel@tonic-gate } 66787c478bd9Sstevel@tonic-gate 66797c478bd9Sstevel@tonic-gate /* 66807c478bd9Sstevel@tonic-gate * If any IO base and limit registers exist, and this client 66817c478bd9Sstevel@tonic-gate * has done a RequestIO, setup the IO Base and IO Limit 66827c478bd9Sstevel@tonic-gate * registers. 66837c478bd9Sstevel@tonic-gate */ 66847c478bd9Sstevel@tonic-gate if (client->flags & REQ_IO_DONE) { 66857c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) { 66867c478bd9Sstevel@tonic-gate uint32_t base = client->io_alloc.BasePort1.base; 66877c478bd9Sstevel@tonic-gate uint32_t present = (client->present & 66887c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_MASK) >> 66897c478bd9Sstevel@tonic-gate CONFIG_IOBASE_REG_SHIFT; 66907c478bd9Sstevel@tonic-gate uint32_t reg = crt->iobase0_p; 66917c478bd9Sstevel@tonic-gate 66927c478bd9Sstevel@tonic-gate do { 66937c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, reg, base & 0x0ff); 66947c478bd9Sstevel@tonic-gate reg = reg + 2; 66957c478bd9Sstevel@tonic-gate base = base >> 8; 66967c478bd9Sstevel@tonic-gate present = present >> 1; 66977c478bd9Sstevel@tonic-gate } while (present); 66987c478bd9Sstevel@tonic-gate } /* CONFIG_IOBASE0_REG_PRESENT */ 66997c478bd9Sstevel@tonic-gate 67007c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOLIMIT_REG_PRESENT) { 67017c478bd9Sstevel@tonic-gate uint32_t np = client->io_alloc.NumPorts1 + 67027c478bd9Sstevel@tonic-gate client->io_alloc.NumPorts2; 67037c478bd9Sstevel@tonic-gate uint32_t limit, do_bit = 0; 67047c478bd9Sstevel@tonic-gate int lm; 67057c478bd9Sstevel@tonic-gate 67067c478bd9Sstevel@tonic-gate limit = (IONUMPORTS_FROBNITZ(np) - 1); 67077c478bd9Sstevel@tonic-gate 67087c478bd9Sstevel@tonic-gate for (lm = 7; lm >= 0; lm--) { 67097c478bd9Sstevel@tonic-gate if (limit & (1 << lm)) 67107c478bd9Sstevel@tonic-gate do_bit = 1; 67117c478bd9Sstevel@tonic-gate if (do_bit) 67127c478bd9Sstevel@tonic-gate limit |= (1 << lm); 67137c478bd9Sstevel@tonic-gate } /* for */ 67147c478bd9Sstevel@tonic-gate 67157c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->iolimit_p, limit); 67167c478bd9Sstevel@tonic-gate } /* CONFIG_IOLIMIT_REG_PRESENT */ 67177c478bd9Sstevel@tonic-gate } /* REQ_IO_DONE */ 67187c478bd9Sstevel@tonic-gate 67197c478bd9Sstevel@tonic-gate /* 67207c478bd9Sstevel@tonic-gate * Mark the socket as being in IO mode. 67217c478bd9Sstevel@tonic-gate */ 67227c478bd9Sstevel@tonic-gate if (cr->IntType & SOCKET_INTERFACE_MEMORY_AND_IO) 67237c478bd9Sstevel@tonic-gate sp->flags |= SOCKET_IS_IO; 67247c478bd9Sstevel@tonic-gate 67257c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 67267c478bd9Sstevel@tonic-gate 67277c478bd9Sstevel@tonic-gate /* 67287c478bd9Sstevel@tonic-gate * Enable the interrupt if needed 67297c478bd9Sstevel@tonic-gate */ 67307c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 67317c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 67327c478bd9Sstevel@tonic-gate 67337c478bd9Sstevel@tonic-gate /* 67347c478bd9Sstevel@tonic-gate * Now that we know if the PRR is present and if it is, which 67357c478bd9Sstevel@tonic-gate * bits in the PRR are valid, we can construct the correct 67367c478bd9Sstevel@tonic-gate * socket event mask. 67377c478bd9Sstevel@tonic-gate */ 67387c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 67397c478bd9Sstevel@tonic-gate 67407c478bd9Sstevel@tonic-gate /* 67417c478bd9Sstevel@tonic-gate * Configuration Option Register - we handle this specially since 67427c478bd9Sstevel@tonic-gate * we don't allow the client to manipulate the RESET or 67437c478bd9Sstevel@tonic-gate * INTERRUPT bits (although a client can manipulate these 67447c478bd9Sstevel@tonic-gate * bits via an AccessConfigurationRegister call - explain 67457c478bd9Sstevel@tonic-gate * THAT logic to me). 67467c478bd9Sstevel@tonic-gate * XXX - we force level-mode interrupts (COR_LEVEL_IRQ) 67477c478bd9Sstevel@tonic-gate * XXX - we always enable the function on a multi-function card 67487c478bd9Sstevel@tonic-gate */ 67497c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 67507c478bd9Sstevel@tonic-gate crt->cor = (cr->ConfigIndex & ~COR_SOFT_RESET) | COR_LEVEL_IRQ; 67517c478bd9Sstevel@tonic-gate if (client->present & CONFIG_IOBASE0_REG_PRESENT) 67527c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_BASE_LIMIT; 67537c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 67547c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_FUNCTION; 67557c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 67567c478bd9Sstevel@tonic-gate if (cr->Attributes & CONF_ENABLE_IRQ_STEERING) 67577c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 67587c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 67597c478bd9Sstevel@tonic-gate 67607c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 67617c478bd9Sstevel@tonic-gate if (cs_debug > 0) 67627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_request_configuration " 67637c478bd9Sstevel@tonic-gate "cor=x%x ConfigIndex=x%x Attributes=x%x flags=x%x\n" 67647c478bd9Sstevel@tonic-gate "present=x%x cis_handle=%p cor_p=x%x\n", 67657c478bd9Sstevel@tonic-gate crt->cor, cr->ConfigIndex, cr->Attributes, sp->cis_flags, 67667c478bd9Sstevel@tonic-gate client->present, cis_handle, crt->cor_p); 67677c478bd9Sstevel@tonic-gate #endif 67687c478bd9Sstevel@tonic-gate 67697c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 67707c478bd9Sstevel@tonic-gate } /* CONFIG_OPTION_REG_PRESENT */ 67717c478bd9Sstevel@tonic-gate 67727c478bd9Sstevel@tonic-gate if (cs_rc1_delay) 67737c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc1_delay * 1000); 67747c478bd9Sstevel@tonic-gate 67757c478bd9Sstevel@tonic-gate /* 67767c478bd9Sstevel@tonic-gate * Set the socket to the parameters that the client requested. 67777c478bd9Sstevel@tonic-gate */ 67787c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 67797c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) { 67807c478bd9Sstevel@tonic-gate crt->cor = 0; /* XXX is 0 the right thing here? */ 67817c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 67827c478bd9Sstevel@tonic-gate } 67837c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 67847c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 67857c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 67867c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 67877c478bd9Sstevel@tonic-gate } 67887c478bd9Sstevel@tonic-gate 67897c478bd9Sstevel@tonic-gate if (cs_rc2_delay) 67907c478bd9Sstevel@tonic-gate drv_usecwait(cs_rc2_delay * 1000); 67917c478bd9Sstevel@tonic-gate 67927c478bd9Sstevel@tonic-gate /* 67937c478bd9Sstevel@tonic-gate * Mark this client as having done a successful RequestConfiguration 67947c478bd9Sstevel@tonic-gate * call. 67957c478bd9Sstevel@tonic-gate */ 67967c478bd9Sstevel@tonic-gate client->flags |= REQ_CONFIGURATION_DONE; 67977c478bd9Sstevel@tonic-gate 67987c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 67997c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68007c478bd9Sstevel@tonic-gate 68017c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 68027c478bd9Sstevel@tonic-gate } 68037c478bd9Sstevel@tonic-gate 68047c478bd9Sstevel@tonic-gate /* 68057c478bd9Sstevel@tonic-gate * cs_release_configuration - releases configuration previously set via the 68067c478bd9Sstevel@tonic-gate * RequestConfiguration call; this is ReleaseConfiguration 68077c478bd9Sstevel@tonic-gate * 68087c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully released 68097c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 68107c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 68117c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 68127c478bd9Sstevel@tonic-gate */ 68137c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 68147c478bd9Sstevel@tonic-gate static int 68157c478bd9Sstevel@tonic-gate cs_release_configuration(client_handle_t client_handle, release_config_t *rcfg) 68167c478bd9Sstevel@tonic-gate { 68177c478bd9Sstevel@tonic-gate cs_socket_t *sp; 68187c478bd9Sstevel@tonic-gate client_t *client; 68197c478bd9Sstevel@tonic-gate volatile config_regs_t *crt; 68207c478bd9Sstevel@tonic-gate set_socket_t set_socket; 68217c478bd9Sstevel@tonic-gate get_socket_t get_socket; 68227c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 68237c478bd9Sstevel@tonic-gate int error; 68247c478bd9Sstevel@tonic-gate uint32_t newoffset; 68257c478bd9Sstevel@tonic-gate int client_lock_acquired; 68267c478bd9Sstevel@tonic-gate 68277c478bd9Sstevel@tonic-gate /* 68287c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 68297c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 68307c478bd9Sstevel@tonic-gate */ 68317c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 68327c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 68337c478bd9Sstevel@tonic-gate 68347c478bd9Sstevel@tonic-gate /* 68357c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 68367c478bd9Sstevel@tonic-gate */ 68377c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 68387c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 68397c478bd9Sstevel@tonic-gate 68407c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 68417c478bd9Sstevel@tonic-gate 68427c478bd9Sstevel@tonic-gate /* 68437c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 68447c478bd9Sstevel@tonic-gate */ 68457c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 68467c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68477c478bd9Sstevel@tonic-gate return (error); 68487c478bd9Sstevel@tonic-gate } 68497c478bd9Sstevel@tonic-gate 68507c478bd9Sstevel@tonic-gate /* 68517c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 68527c478bd9Sstevel@tonic-gate * this call. 68537c478bd9Sstevel@tonic-gate */ 68547c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 68557c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68567c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 68577c478bd9Sstevel@tonic-gate } 68587c478bd9Sstevel@tonic-gate 68597c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 68607c478bd9Sstevel@tonic-gate if (cs_debug > 0) 68617c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: " 68627c478bd9Sstevel@tonic-gate "flags=0x%x CW_MULTI_FUNCTION_CIS =0x%x \n", 68637c478bd9Sstevel@tonic-gate sp->cis_flags, CW_MULTI_FUNCTION_CIS); 68647c478bd9Sstevel@tonic-gate 68657c478bd9Sstevel@tonic-gate #endif 68667c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 68677c478bd9Sstevel@tonic-gate 68687c478bd9Sstevel@tonic-gate /* 68697c478bd9Sstevel@tonic-gate * Set the card back to a memory-only interface byte writing a zero 68707c478bd9Sstevel@tonic-gate * to the COR. Note that we don't update our soft copy of the 68717c478bd9Sstevel@tonic-gate * COR state since the PCMCIA spec only requires us to maintain 68727c478bd9Sstevel@tonic-gate * the last value that was written to that register during a 68737c478bd9Sstevel@tonic-gate * call to RequestConfiguration. 68747c478bd9Sstevel@tonic-gate */ 68757c478bd9Sstevel@tonic-gate crt = &client->config_regs; 68767c478bd9Sstevel@tonic-gate 68777c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset; 68787c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 68797c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 68807c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 68817c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 68827c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_release_configuration: socket %d can't init " 68837c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 68847c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 68857c478bd9Sstevel@tonic-gate } 68867c478bd9Sstevel@tonic-gate 68877c478bd9Sstevel@tonic-gate if (sp->cis_flags & CW_MULTI_FUNCTION_CIS) { 68887c478bd9Sstevel@tonic-gate /* 68897c478bd9Sstevel@tonic-gate * For the Multifunction cards do not reset the socket 68907c478bd9Sstevel@tonic-gate * to a memory only interface but do clear the 68917c478bd9Sstevel@tonic-gate * Configuration Option Register and mark this client 68927c478bd9Sstevel@tonic-gate * as not having a configuration by clearing the 68937c478bd9Sstevel@tonic-gate * REQ_CONFIGURATION_DONE flag. 68947c478bd9Sstevel@tonic-gate */ 68957c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 68967c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 68977c478bd9Sstevel@tonic-gate 68987c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 68997c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69007c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 69017c478bd9Sstevel@tonic-gate } 69027c478bd9Sstevel@tonic-gate 69037c478bd9Sstevel@tonic-gate /* 69047c478bd9Sstevel@tonic-gate * Set the socket back to a memory-only interface; don't change 69057c478bd9Sstevel@tonic-gate * any other parameter of the socket. 69067c478bd9Sstevel@tonic-gate */ 69077c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 69087c478bd9Sstevel@tonic-gate 69097c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 69107c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69127c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69137c478bd9Sstevel@tonic-gate } 69147c478bd9Sstevel@tonic-gate 69157c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 69167c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_IO; 69177c478bd9Sstevel@tonic-gate set_socket.SCIntMask = cs_merge_event_masks(sp, client); 69187c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 69197c478bd9Sstevel@tonic-gate 69207c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 69217c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 69227c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 69237c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 69247c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 69257c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 69267c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 69277c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 69287c478bd9Sstevel@tonic-gate 69297c478bd9Sstevel@tonic-gate if (client->present & CONFIG_OPTION_REG_PRESENT) 69307c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, 0); 69317c478bd9Sstevel@tonic-gate 69327c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 69337c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69347c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69357c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69367c478bd9Sstevel@tonic-gate } 69377c478bd9Sstevel@tonic-gate 69387c478bd9Sstevel@tonic-gate /* 69397c478bd9Sstevel@tonic-gate * Mark this client as not having a configuration. 69407c478bd9Sstevel@tonic-gate */ 69417c478bd9Sstevel@tonic-gate client->flags &= ~REQ_CONFIGURATION_DONE; 69427c478bd9Sstevel@tonic-gate 69437c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 69447c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69457c478bd9Sstevel@tonic-gate 69467c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 69477c478bd9Sstevel@tonic-gate } 69487c478bd9Sstevel@tonic-gate 69497c478bd9Sstevel@tonic-gate /* 69507c478bd9Sstevel@tonic-gate * cs_modify_configuration - modifies a configuration established by 69517c478bd9Sstevel@tonic-gate * RequestConfiguration; this is ModifyConfiguration 69527c478bd9Sstevel@tonic-gate * 69537c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if configuration sucessfully modified 69547c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if Socket Services returns an error 69557c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 69567c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - a RequestConfiguration has not been done 69577c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 69587c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if any unsupported or reserved flags 69597c478bd9Sstevel@tonic-gate * are set 69607c478bd9Sstevel@tonic-gate * CS_BAD_VCC - if Vcc value is not supported by socket 69617c478bd9Sstevel@tonic-gate * CS_BAD_VPP1 - if Vpp1 value is not supported by socket 69627c478bd9Sstevel@tonic-gate * CS_BAD_VPP2 - if Vpp2 value is not supported by socket 69637c478bd9Sstevel@tonic-gate */ 69647c478bd9Sstevel@tonic-gate static int 69657c478bd9Sstevel@tonic-gate cs_modify_configuration(client_handle_t client_handle, modify_config_t *mc) 69667c478bd9Sstevel@tonic-gate { 69677c478bd9Sstevel@tonic-gate cs_socket_t *sp; 69687c478bd9Sstevel@tonic-gate client_t *client; 69697c478bd9Sstevel@tonic-gate set_socket_t set_socket; 69707c478bd9Sstevel@tonic-gate get_socket_t get_socket; 69717c478bd9Sstevel@tonic-gate int error; 69727c478bd9Sstevel@tonic-gate int client_lock_acquired; 69737c478bd9Sstevel@tonic-gate 69747c478bd9Sstevel@tonic-gate /* 69757c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 69767c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 69777c478bd9Sstevel@tonic-gate */ 69787c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 69797c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 69807c478bd9Sstevel@tonic-gate 69817c478bd9Sstevel@tonic-gate /* 69827c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 69837c478bd9Sstevel@tonic-gate */ 69847c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 69857c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 69867c478bd9Sstevel@tonic-gate 69877c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 69887c478bd9Sstevel@tonic-gate 69897c478bd9Sstevel@tonic-gate /* 69907c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 69917c478bd9Sstevel@tonic-gate */ 69927c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 69937c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 69947c478bd9Sstevel@tonic-gate return (error); 69957c478bd9Sstevel@tonic-gate } 69967c478bd9Sstevel@tonic-gate 69977c478bd9Sstevel@tonic-gate /* 69987c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 69997c478bd9Sstevel@tonic-gate * this call. 70007c478bd9Sstevel@tonic-gate */ 70017c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 70027c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70037c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 70047c478bd9Sstevel@tonic-gate } 70057c478bd9Sstevel@tonic-gate 70067c478bd9Sstevel@tonic-gate /* 70077c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 70087c478bd9Sstevel@tonic-gate * for this client, then return an error. 70097c478bd9Sstevel@tonic-gate */ 70107c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 70117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70127c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 70137c478bd9Sstevel@tonic-gate } 70147c478bd9Sstevel@tonic-gate 70157c478bd9Sstevel@tonic-gate /* 70167c478bd9Sstevel@tonic-gate * Get the current socket parameters so that we can modify them. 70177c478bd9Sstevel@tonic-gate */ 70187c478bd9Sstevel@tonic-gate get_socket.socket = sp->socket_num; 70197c478bd9Sstevel@tonic-gate 70207c478bd9Sstevel@tonic-gate if (SocketServices(SS_GetSocket, &get_socket) != SUCCESS) { 70217c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70227c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 70237c478bd9Sstevel@tonic-gate } 70247c478bd9Sstevel@tonic-gate 70257c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 70267c478bd9Sstevel@tonic-gate if (cs_debug > 0) 70277c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration: socket %d " 70287c478bd9Sstevel@tonic-gate "client->irq_alloc.irq 0x%x " 70297c478bd9Sstevel@tonic-gate "get_socket.IRQRouting 0x%x\n", 70307c478bd9Sstevel@tonic-gate sp->socket_num, (int)client->irq_alloc.irq, 70317c478bd9Sstevel@tonic-gate get_socket.IRQRouting); 70327c478bd9Sstevel@tonic-gate #endif 70337c478bd9Sstevel@tonic-gate 70347c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 70357c478bd9Sstevel@tonic-gate set_socket.SCIntMask = get_socket.SCIntMask; 70367c478bd9Sstevel@tonic-gate set_socket.CtlInd = get_socket.CtlInd; 70377c478bd9Sstevel@tonic-gate set_socket.State = 0; /* don't reset latched values */ 70387c478bd9Sstevel@tonic-gate set_socket.IFType = get_socket.IFType; 70397c478bd9Sstevel@tonic-gate 70407c478bd9Sstevel@tonic-gate set_socket.IREQRouting = get_socket.IRQRouting; 70417c478bd9Sstevel@tonic-gate 70427c478bd9Sstevel@tonic-gate /* 70437c478bd9Sstevel@tonic-gate * Modify the IRQ routing if the client wants it modified. 70447c478bd9Sstevel@tonic-gate */ 70457c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_IRQ_CHANGE_VALID) { 70467c478bd9Sstevel@tonic-gate set_socket.IREQRouting &= ~IRQ_ENABLE; 70477c478bd9Sstevel@tonic-gate 70487c478bd9Sstevel@tonic-gate if ((sp->cis_flags & CW_MULTI_FUNCTION_CIS) && 70497c478bd9Sstevel@tonic-gate (client->present & CONFIG_OPTION_REG_PRESENT)) { 70507c478bd9Sstevel@tonic-gate config_regs_t *crt = &client->config_regs; 70517c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 70527c478bd9Sstevel@tonic-gate uint32_t newoffset = client->config_regs_offset; 70537c478bd9Sstevel@tonic-gate 70547c478bd9Sstevel@tonic-gate /* 70557c478bd9Sstevel@tonic-gate * Get a pointer to a window that contains the configuration 70567c478bd9Sstevel@tonic-gate * registers. 70577c478bd9Sstevel@tonic-gate */ 70587c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 70597c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 70607c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70617c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 70627c478bd9Sstevel@tonic-gate "cs_modify_configuration: socket %d can't init " 70637c478bd9Sstevel@tonic-gate "CIS window\n", sp->socket_num); 70647c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 70657c478bd9Sstevel@tonic-gate } /* cs_init_cis_window */ 70667c478bd9Sstevel@tonic-gate 70677c478bd9Sstevel@tonic-gate crt->cor &= ~COR_ENABLE_IREQ_ROUTING; 70687c478bd9Sstevel@tonic-gate 70697c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 70707c478bd9Sstevel@tonic-gate crt->cor |= COR_ENABLE_IREQ_ROUTING; 70717c478bd9Sstevel@tonic-gate 70727c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 70737c478bd9Sstevel@tonic-gate if (cs_debug > 0) 70747c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_modify_configuration:" 70757c478bd9Sstevel@tonic-gate " cor_p=0x%x cor=0x%x\n", 70767c478bd9Sstevel@tonic-gate crt->cor_p, crt->cor); 70777c478bd9Sstevel@tonic-gate #endif 70787c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, crt->cor_p, crt->cor); 70797c478bd9Sstevel@tonic-gate 70807c478bd9Sstevel@tonic-gate } /* CW_MULTI_FUNCTION_CIS */ 70817c478bd9Sstevel@tonic-gate 70827c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_ENABLE_IRQ_STEERING) 70837c478bd9Sstevel@tonic-gate set_socket.IREQRouting |= IRQ_ENABLE; 70847c478bd9Sstevel@tonic-gate 70857c478bd9Sstevel@tonic-gate } /* CONF_IRQ_CHANGE_VALID */ 70867c478bd9Sstevel@tonic-gate 70877c478bd9Sstevel@tonic-gate /* 70887c478bd9Sstevel@tonic-gate * Modify the voltage levels that the client specifies. 70897c478bd9Sstevel@tonic-gate */ 70907c478bd9Sstevel@tonic-gate set_socket.VccLevel = get_socket.VccLevel; 70917c478bd9Sstevel@tonic-gate 70927c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP1_CHANGE_VALID) { 70937c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp1, VPP1, 70947c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level) != CS_SUCCESS) { 70957c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 70967c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 70977c478bd9Sstevel@tonic-gate } 70987c478bd9Sstevel@tonic-gate } else { 70997c478bd9Sstevel@tonic-gate set_socket.Vpp1Level = get_socket.Vpp1Level; 71007c478bd9Sstevel@tonic-gate } 71017c478bd9Sstevel@tonic-gate 71027c478bd9Sstevel@tonic-gate if (mc->Attributes & CONF_VPP2_CHANGE_VALID) { 71037c478bd9Sstevel@tonic-gate if (cs_convert_powerlevel(sp->socket_num, mc->Vpp2, VPP2, 71047c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level) != CS_SUCCESS) { 71057c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71067c478bd9Sstevel@tonic-gate return (CS_BAD_VPP); 71077c478bd9Sstevel@tonic-gate } 71087c478bd9Sstevel@tonic-gate } else { 71097c478bd9Sstevel@tonic-gate set_socket.Vpp2Level = get_socket.Vpp2Level; 71107c478bd9Sstevel@tonic-gate } 71117c478bd9Sstevel@tonic-gate 71127c478bd9Sstevel@tonic-gate /* 71137c478bd9Sstevel@tonic-gate * Setup the modified socket configuration. 71147c478bd9Sstevel@tonic-gate */ 71157c478bd9Sstevel@tonic-gate if (SocketServices(SS_SetSocket, &set_socket) != SUCCESS) { 71167c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71177c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 71187c478bd9Sstevel@tonic-gate } 71197c478bd9Sstevel@tonic-gate 71207c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71217c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 71227c478bd9Sstevel@tonic-gate } 71237c478bd9Sstevel@tonic-gate 71247c478bd9Sstevel@tonic-gate /* 71257c478bd9Sstevel@tonic-gate * cs_access_configuration_register - provides a client access to the card's 71267c478bd9Sstevel@tonic-gate * configuration registers; this is AccessConfigurationRegister 71277c478bd9Sstevel@tonic-gate * 71287c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if register accessed successfully 71297c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 71307c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if arguments are out of range 71317c478bd9Sstevel@tonic-gate * CS_NO_CARD - if no card in socket 71327c478bd9Sstevel@tonic-gate * CS_BAD_BASE - if no config registers base address 71337c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_MODE - if no RequestConfiguration has 71347c478bd9Sstevel@tonic-gate * been done yet 71357c478bd9Sstevel@tonic-gate */ 71367c478bd9Sstevel@tonic-gate static int 71377c478bd9Sstevel@tonic-gate cs_access_configuration_register(client_handle_t client_handle, 71387c478bd9Sstevel@tonic-gate access_config_reg_t *acr) 71397c478bd9Sstevel@tonic-gate { 71407c478bd9Sstevel@tonic-gate cs_socket_t *sp; 71417c478bd9Sstevel@tonic-gate client_t *client; 71427c478bd9Sstevel@tonic-gate acc_handle_t cis_handle; 71437c478bd9Sstevel@tonic-gate int error; 71447c478bd9Sstevel@tonic-gate uint32_t newoffset; 71457c478bd9Sstevel@tonic-gate int client_lock_acquired; 71467c478bd9Sstevel@tonic-gate 71477c478bd9Sstevel@tonic-gate /* 71487c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 71497c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 71507c478bd9Sstevel@tonic-gate */ 71517c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 71527c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 71537c478bd9Sstevel@tonic-gate 71547c478bd9Sstevel@tonic-gate /* 71557c478bd9Sstevel@tonic-gate * Make sure that the specifed offset is in range. 71567c478bd9Sstevel@tonic-gate */ 71577c478bd9Sstevel@tonic-gate if (acr->Offset > ((CISTPL_CONFIG_MAX_CONFIG_REGS * 2) - 2)) 71587c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 71597c478bd9Sstevel@tonic-gate 71607c478bd9Sstevel@tonic-gate /* 71617c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 71627c478bd9Sstevel@tonic-gate */ 71637c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 71647c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 71657c478bd9Sstevel@tonic-gate 71667c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 71677c478bd9Sstevel@tonic-gate 71687c478bd9Sstevel@tonic-gate /* 71697c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 71707c478bd9Sstevel@tonic-gate */ 71717c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 71727c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71737c478bd9Sstevel@tonic-gate return (error); 71747c478bd9Sstevel@tonic-gate } 71757c478bd9Sstevel@tonic-gate 71767c478bd9Sstevel@tonic-gate /* 71777c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 71787c478bd9Sstevel@tonic-gate * for this client, then return an error. 71797c478bd9Sstevel@tonic-gate */ 71807c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 71817c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71827c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 71837c478bd9Sstevel@tonic-gate } 71847c478bd9Sstevel@tonic-gate 71857c478bd9Sstevel@tonic-gate /* 71867c478bd9Sstevel@tonic-gate * If RequestConfiguration has not been done, we don't allow 71877c478bd9Sstevel@tonic-gate * this call. 71887c478bd9Sstevel@tonic-gate */ 71897c478bd9Sstevel@tonic-gate if (!(client->flags & REQ_CONFIGURATION_DONE)) { 71907c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 71917c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_MODE); 71927c478bd9Sstevel@tonic-gate } 71937c478bd9Sstevel@tonic-gate 71947c478bd9Sstevel@tonic-gate mutex_enter(&sp->cis_lock); 71957c478bd9Sstevel@tonic-gate 71967c478bd9Sstevel@tonic-gate /* 71977c478bd9Sstevel@tonic-gate * Get a pointer to the CIS window 71987c478bd9Sstevel@tonic-gate */ 71997c478bd9Sstevel@tonic-gate newoffset = client->config_regs_offset + acr->Offset; 72007c478bd9Sstevel@tonic-gate if (cs_init_cis_window(sp, &newoffset, &cis_handle, 72017c478bd9Sstevel@tonic-gate CISTPLF_AM_SPACE) != CS_SUCCESS) { 72027c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 72037c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 72047c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: socket %d can't init CIS window\n", 72057c478bd9Sstevel@tonic-gate sp->socket_num); 72067c478bd9Sstevel@tonic-gate return (CS_GENERAL_FAILURE); 72077c478bd9Sstevel@tonic-gate } 72087c478bd9Sstevel@tonic-gate 72097c478bd9Sstevel@tonic-gate /* 72107c478bd9Sstevel@tonic-gate * Create the address for the config register that the client 72117c478bd9Sstevel@tonic-gate * wants to access. 72127c478bd9Sstevel@tonic-gate */ 72137c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 72147c478bd9Sstevel@tonic-gate 72157c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 72167c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 72177c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ACR: config_regs_offset 0x%x " 72187c478bd9Sstevel@tonic-gate "Offset 0x%x newoffset 0x%x\n", 72197c478bd9Sstevel@tonic-gate (int)client->config_regs_offset, 72207c478bd9Sstevel@tonic-gate (int)acr->Offset, newoffset); 72217c478bd9Sstevel@tonic-gate } 72227c478bd9Sstevel@tonic-gate #endif 72237c478bd9Sstevel@tonic-gate 72247c478bd9Sstevel@tonic-gate /* 72257c478bd9Sstevel@tonic-gate * Determine what the client wants us to do. The client is 72267c478bd9Sstevel@tonic-gate * allowed to specify any valid offset, even if it would 72277c478bd9Sstevel@tonic-gate * cause an unimplemented configuration register to be 72287c478bd9Sstevel@tonic-gate * accessed. 72297c478bd9Sstevel@tonic-gate */ 72307c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 72317c478bd9Sstevel@tonic-gate switch (acr->Action) { 72327c478bd9Sstevel@tonic-gate case CONFIG_REG_READ: 72337c478bd9Sstevel@tonic-gate acr->Value = csx_Get8(cis_handle, newoffset); 72347c478bd9Sstevel@tonic-gate break; 72357c478bd9Sstevel@tonic-gate case CONFIG_REG_WRITE: 72367c478bd9Sstevel@tonic-gate csx_Put8(cis_handle, newoffset, acr->Value); 72377c478bd9Sstevel@tonic-gate break; 72387c478bd9Sstevel@tonic-gate default: 72397c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; 72407c478bd9Sstevel@tonic-gate break; 72417c478bd9Sstevel@tonic-gate } /* switch */ 72427c478bd9Sstevel@tonic-gate 72437c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 72447c478bd9Sstevel@tonic-gate mutex_exit(&sp->cis_lock); 72457c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 72467c478bd9Sstevel@tonic-gate 72477c478bd9Sstevel@tonic-gate return (error); 72487c478bd9Sstevel@tonic-gate } 72497c478bd9Sstevel@tonic-gate 72507c478bd9Sstevel@tonic-gate /* 72517c478bd9Sstevel@tonic-gate * ==== RESET and general info functions ==== 72527c478bd9Sstevel@tonic-gate */ 72537c478bd9Sstevel@tonic-gate 72547c478bd9Sstevel@tonic-gate /* 72557c478bd9Sstevel@tonic-gate * cs_reset_function - RESET the requested function on the card; this 72567c478bd9Sstevel@tonic-gate * is ResetFunction 72577c478bd9Sstevel@tonic-gate * 72587c478bd9Sstevel@tonic-gate * Note: We don't support this functionality yet, and the standard 72597c478bd9Sstevel@tonic-gate * says it's OK to reutrn CS_IN_USE if we can't do this 72607c478bd9Sstevel@tonic-gate * operation. 72617c478bd9Sstevel@tonic-gate */ 72627c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 72637c478bd9Sstevel@tonic-gate static int 72647c478bd9Sstevel@tonic-gate cs_reset_function(client_handle_t ch, reset_function_t *rf) 72657c478bd9Sstevel@tonic-gate { 72667c478bd9Sstevel@tonic-gate return (CS_IN_USE); 72677c478bd9Sstevel@tonic-gate } 72687c478bd9Sstevel@tonic-gate 72697c478bd9Sstevel@tonic-gate /* 72707c478bd9Sstevel@tonic-gate * cs_get_configuration_info - return configuration info for the passed 72717c478bd9Sstevel@tonic-gate * socket and function number to the caller; 72727c478bd9Sstevel@tonic-gate * this is GetConfigurationInfo 72737c478bd9Sstevel@tonic-gate */ 72747c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 72757c478bd9Sstevel@tonic-gate static int 72767c478bd9Sstevel@tonic-gate cs_get_configuration_info(client_handle_t *chp, get_configuration_info_t *gci) 72777c478bd9Sstevel@tonic-gate { 72787c478bd9Sstevel@tonic-gate cs_socket_t *sp; 72797c478bd9Sstevel@tonic-gate uint32_t fn; 72807c478bd9Sstevel@tonic-gate client_t *client; 72817c478bd9Sstevel@tonic-gate int client_lock_acquired; 72827c478bd9Sstevel@tonic-gate 72837c478bd9Sstevel@tonic-gate /* 72847c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 72857c478bd9Sstevel@tonic-gate */ 72867c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gci->Socket))) == NULL) 72877c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 72887c478bd9Sstevel@tonic-gate 72897c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 72907c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 72917c478bd9Sstevel@tonic-gate 72927c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(gci->Socket); 72937c478bd9Sstevel@tonic-gate 72947c478bd9Sstevel@tonic-gate client = sp->client_list; 72957c478bd9Sstevel@tonic-gate while (client) { 72967c478bd9Sstevel@tonic-gate 72977c478bd9Sstevel@tonic-gate if (GET_CLIENT_FUNCTION(client->client_handle) == fn) { 72987c478bd9Sstevel@tonic-gate 72997c478bd9Sstevel@tonic-gate /* 73007c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the 73017c478bd9Sstevel@tonic-gate * socket is not for this client, then return 73027c478bd9Sstevel@tonic-gate * an error. 73037c478bd9Sstevel@tonic-gate */ 73047c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 73057c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73067c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73077c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 73087c478bd9Sstevel@tonic-gate } 73097c478bd9Sstevel@tonic-gate 73107c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73117c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73127c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 73137c478bd9Sstevel@tonic-gate 73147c478bd9Sstevel@tonic-gate } /* GET_CLIENT_FUNCTION == fn */ 73157c478bd9Sstevel@tonic-gate 73167c478bd9Sstevel@tonic-gate client = client->next; 73177c478bd9Sstevel@tonic-gate } /* while (client) */ 73187c478bd9Sstevel@tonic-gate 73197c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 73207c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73217c478bd9Sstevel@tonic-gate 73227c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 73237c478bd9Sstevel@tonic-gate } 73247c478bd9Sstevel@tonic-gate 73257c478bd9Sstevel@tonic-gate /* 73267c478bd9Sstevel@tonic-gate * cs_get_cardservices_info - return info about Card Services to the 73277c478bd9Sstevel@tonic-gate * caller; this is GetCardServicesInfo 73287c478bd9Sstevel@tonic-gate */ 73297c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 73307c478bd9Sstevel@tonic-gate static int 73317c478bd9Sstevel@tonic-gate cs_get_cardservices_info(client_handle_t ch, get_cardservices_info_t *gcsi) 73327c478bd9Sstevel@tonic-gate { 73337c478bd9Sstevel@tonic-gate gcsi->Signature[0] = 'C'; 73347c478bd9Sstevel@tonic-gate gcsi->Signature[1] = 'S'; 73357c478bd9Sstevel@tonic-gate gcsi->NumSockets = cs_globals.num_sockets; 73367c478bd9Sstevel@tonic-gate gcsi->Revision = CS_INTERNAL_REVISION_LEVEL; 73377c478bd9Sstevel@tonic-gate gcsi->CSLevel = CS_VERSION; 73387c478bd9Sstevel@tonic-gate gcsi->FuncsPerSocket = CIS_MAX_FUNCTIONS; 73397c478bd9Sstevel@tonic-gate (void) strncpy(gcsi->VendorString, 73407c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_VENDOR_STRING, 73417c478bd9Sstevel@tonic-gate CS_GET_CARDSERVICES_INFO_MAX_VS_LEN); 73427c478bd9Sstevel@tonic-gate 73437c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 73447c478bd9Sstevel@tonic-gate } 73457c478bd9Sstevel@tonic-gate 73467c478bd9Sstevel@tonic-gate /* 73477c478bd9Sstevel@tonic-gate * cs_get_physical_adapter_info - returns information about the requested 73487c478bd9Sstevel@tonic-gate * physical adapter; this is 73497c478bd9Sstevel@tonic-gate * GetPhysicalAdapterInfo 73507c478bd9Sstevel@tonic-gate * 73517c478bd9Sstevel@tonic-gate * calling: client_handle_t: 73527c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 73537c478bd9Sstevel@tonic-gate * to specify logical socket number 73547c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 73557c478bd9Sstevel@tonic-gate * client_handle_t 73567c478bd9Sstevel@tonic-gate * 73577c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 73587c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 73597c478bd9Sstevel@tonic-gate * socket number is specified in 73607c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 73617c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 73627c478bd9Sstevel@tonic-gate * client handle is specified 73637c478bd9Sstevel@tonic-gate */ 73647c478bd9Sstevel@tonic-gate static int 73657c478bd9Sstevel@tonic-gate cs_get_physical_adapter_info(client_handle_t ch, 73667c478bd9Sstevel@tonic-gate get_physical_adapter_info_t *gpai) 73677c478bd9Sstevel@tonic-gate { 73687c478bd9Sstevel@tonic-gate cs_socket_t *sp; 73697c478bd9Sstevel@tonic-gate int client_lock_acquired; 73707c478bd9Sstevel@tonic-gate 73717c478bd9Sstevel@tonic-gate if (ch == NULL) 73727c478bd9Sstevel@tonic-gate gpai->PhySocket = CS_GET_SOCKET_NUMBER(gpai->LogSocket); 73737c478bd9Sstevel@tonic-gate else 73747c478bd9Sstevel@tonic-gate gpai->PhySocket = GET_CLIENT_SOCKET(ch); 73757c478bd9Sstevel@tonic-gate 73767c478bd9Sstevel@tonic-gate /* 73777c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 73787c478bd9Sstevel@tonic-gate */ 73797c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(gpai->PhySocket))) == NULL) 73807c478bd9Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 73817c478bd9Sstevel@tonic-gate 73827c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 73837c478bd9Sstevel@tonic-gate 73847c478bd9Sstevel@tonic-gate /* 73857c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 73867c478bd9Sstevel@tonic-gate */ 73877c478bd9Sstevel@tonic-gate if (ch != NULL) { 73887c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 73897c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 73907c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 73917c478bd9Sstevel@tonic-gate } /* cs_find_client */ 73927c478bd9Sstevel@tonic-gate } /* ch != NULL */ 73937c478bd9Sstevel@tonic-gate 73947c478bd9Sstevel@tonic-gate gpai->flags = sp->adapter.flags; 73957c478bd9Sstevel@tonic-gate (void) strcpy(gpai->name, sp->adapter.name); 73967c478bd9Sstevel@tonic-gate gpai->major = sp->adapter.major; 73977c478bd9Sstevel@tonic-gate gpai->minor = sp->adapter.minor; 73987c478bd9Sstevel@tonic-gate gpai->instance = sp->adapter.instance; 73997c478bd9Sstevel@tonic-gate gpai->number = sp->adapter.number; 74007c478bd9Sstevel@tonic-gate gpai->num_sockets = sp->adapter.num_sockets; 74017c478bd9Sstevel@tonic-gate gpai->first_socket = sp->adapter.first_socket; 74027c478bd9Sstevel@tonic-gate 74037c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74047c478bd9Sstevel@tonic-gate 74057c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 74067c478bd9Sstevel@tonic-gate } 74077c478bd9Sstevel@tonic-gate 74087c478bd9Sstevel@tonic-gate /* 74097c478bd9Sstevel@tonic-gate * ==== general functions ==== 74107c478bd9Sstevel@tonic-gate */ 74117c478bd9Sstevel@tonic-gate 74127c478bd9Sstevel@tonic-gate /* 74137c478bd9Sstevel@tonic-gate * cs_map_log_socket - returns the physical socket number associated with 74147c478bd9Sstevel@tonic-gate * either the passed client handle or the passed 74157c478bd9Sstevel@tonic-gate * logical socket number; this is MapLogSocket 74167c478bd9Sstevel@tonic-gate * 74177c478bd9Sstevel@tonic-gate * calling: client_handle_t: 74187c478bd9Sstevel@tonic-gate * NULL - use map_log_socket_t->LogSocket member 74197c478bd9Sstevel@tonic-gate * to specify logical socket number 74207c478bd9Sstevel@tonic-gate * !NULL - extract logical socket number from 74217c478bd9Sstevel@tonic-gate * client_handle_t 74227c478bd9Sstevel@tonic-gate * 74237c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 74247c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - if client_handle_t is NULL and invalid 74257c478bd9Sstevel@tonic-gate * socket number is specified in 74267c478bd9Sstevel@tonic-gate * map_log_socket_t->LogSocket 74277c478bd9Sstevel@tonic-gate * CS_BAD_HANDLE - if client_handle_t is !NULL and invalid 74287c478bd9Sstevel@tonic-gate * client handle is specified 74297c478bd9Sstevel@tonic-gate * 74307c478bd9Sstevel@tonic-gate * Note: We provide this function since the instance number of a client 74317c478bd9Sstevel@tonic-gate * driver doesn't necessary correspond to the physical 74327c478bd9Sstevel@tonic-gate * socket number 74337c478bd9Sstevel@tonic-gate */ 74347c478bd9Sstevel@tonic-gate static int 74357c478bd9Sstevel@tonic-gate cs_map_log_socket(client_handle_t ch, map_log_socket_t *mls) 74367c478bd9Sstevel@tonic-gate { 74377c478bd9Sstevel@tonic-gate cs_socket_t *sp; 74387c478bd9Sstevel@tonic-gate int client_lock_acquired; 74397c478bd9Sstevel@tonic-gate 74407c478bd9Sstevel@tonic-gate if (ch == NULL) 74417c478bd9Sstevel@tonic-gate mls->PhySocket = CS_GET_SOCKET_NUMBER(mls->LogSocket); 74427c478bd9Sstevel@tonic-gate else 74437c478bd9Sstevel@tonic-gate mls->PhySocket = GET_CLIENT_SOCKET(ch); 74447c478bd9Sstevel@tonic-gate 74457c478bd9Sstevel@tonic-gate /* 74467c478bd9Sstevel@tonic-gate * Determine if the passed socket number is valid or not. 74477c478bd9Sstevel@tonic-gate */ 74487c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(mls->PhySocket))) == NULL) 74497c478bd9Sstevel@tonic-gate return ((ch == NULL) ? CS_BAD_SOCKET : CS_BAD_HANDLE); 74507c478bd9Sstevel@tonic-gate 74517c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 74527c478bd9Sstevel@tonic-gate 74537c478bd9Sstevel@tonic-gate /* 74547c478bd9Sstevel@tonic-gate * If we were passed a client handle, determine if it's valid or not. 74557c478bd9Sstevel@tonic-gate */ 74567c478bd9Sstevel@tonic-gate if (ch != NULL) { 74577c478bd9Sstevel@tonic-gate if (cs_find_client(ch, NULL) == NULL) { 74587c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74597c478bd9Sstevel@tonic-gate return (CS_BAD_HANDLE); 74607c478bd9Sstevel@tonic-gate } /* cs_find_client */ 74617c478bd9Sstevel@tonic-gate } /* ch != NULL */ 74627c478bd9Sstevel@tonic-gate 74637c478bd9Sstevel@tonic-gate mls->PhyAdapter = sp->adapter.number; 74647c478bd9Sstevel@tonic-gate 74657c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 74667c478bd9Sstevel@tonic-gate 74677c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 74687c478bd9Sstevel@tonic-gate } 74697c478bd9Sstevel@tonic-gate 74707c478bd9Sstevel@tonic-gate /* 74717c478bd9Sstevel@tonic-gate * cs_convert_speed - convers nS to devspeed and devspeed to nS 74727c478bd9Sstevel@tonic-gate * 74737c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 74747c478bd9Sstevel@tonic-gate * is only a wrapper. 74757c478bd9Sstevel@tonic-gate */ 74767c478bd9Sstevel@tonic-gate static int 74777c478bd9Sstevel@tonic-gate cs_convert_speed(convert_speed_t *cs) 74787c478bd9Sstevel@tonic-gate { 74797c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSPEED, cs)); 74807c478bd9Sstevel@tonic-gate } 74817c478bd9Sstevel@tonic-gate 74827c478bd9Sstevel@tonic-gate /* 74837c478bd9Sstevel@tonic-gate * cs_convert_size - converts a devsize value to a size in bytes value 74847c478bd9Sstevel@tonic-gate * or a size in bytes value to a devsize value 74857c478bd9Sstevel@tonic-gate * 74867c478bd9Sstevel@tonic-gate * The actual function is is in the CIS parser module; this 74877c478bd9Sstevel@tonic-gate * is only a wrapper. 74887c478bd9Sstevel@tonic-gate */ 74897c478bd9Sstevel@tonic-gate static int 74907c478bd9Sstevel@tonic-gate cs_convert_size(convert_size_t *cs) 74917c478bd9Sstevel@tonic-gate { 74927c478bd9Sstevel@tonic-gate return ((int)(uintptr_t)CIS_PARSER(CISP_CIS_CONV_DEVSIZE, cs)); 74937c478bd9Sstevel@tonic-gate } 74947c478bd9Sstevel@tonic-gate 74957c478bd9Sstevel@tonic-gate /* 74967c478bd9Sstevel@tonic-gate * cs_convert_powerlevel - converts a power level in tenths of a volt 74977c478bd9Sstevel@tonic-gate * to a power table entry for the specified socket 74987c478bd9Sstevel@tonic-gate * 74997c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if volts converted to a valid power level 75007c478bd9Sstevel@tonic-gate * CS_BAD_ADAPTER - if SS_InquireAdapter fails 75017c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if volts are not supported on this socket 75027c478bd9Sstevel@tonic-gate * and adapter 75037c478bd9Sstevel@tonic-gate */ 75047c478bd9Sstevel@tonic-gate static int 75057c478bd9Sstevel@tonic-gate cs_convert_powerlevel(uint32_t sn, uint32_t volts, uint32_t flags, unsigned *pl) 75067c478bd9Sstevel@tonic-gate { 75077c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 75087c478bd9Sstevel@tonic-gate int i; 75097c478bd9Sstevel@tonic-gate 75107c478bd9Sstevel@tonic-gate #ifdef lint 75117c478bd9Sstevel@tonic-gate if (sn == 0) 75127c478bd9Sstevel@tonic-gate panic("lint panic"); 75137c478bd9Sstevel@tonic-gate #endif 75147c478bd9Sstevel@tonic-gate 75157c478bd9Sstevel@tonic-gate *pl = 0; 75167c478bd9Sstevel@tonic-gate 75177c478bd9Sstevel@tonic-gate if (SocketServices(SS_InquireAdapter, &inquire_adapter) != SUCCESS) 75187c478bd9Sstevel@tonic-gate return (CS_BAD_ADAPTER); 75197c478bd9Sstevel@tonic-gate 75207c478bd9Sstevel@tonic-gate for (i = 0; (i < inquire_adapter.NumPower); i++) { 75217c478bd9Sstevel@tonic-gate if ((inquire_adapter.power_entry[i].ValidSignals & flags) && 75227c478bd9Sstevel@tonic-gate (inquire_adapter.power_entry[i].PowerLevel == volts)) { 75237c478bd9Sstevel@tonic-gate *pl = i; 75247c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75257c478bd9Sstevel@tonic-gate } 75267c478bd9Sstevel@tonic-gate } 75277c478bd9Sstevel@tonic-gate 75287c478bd9Sstevel@tonic-gate return (CS_BAD_ARGS); 75297c478bd9Sstevel@tonic-gate } 75307c478bd9Sstevel@tonic-gate 75317c478bd9Sstevel@tonic-gate /* 75327c478bd9Sstevel@tonic-gate * cs_event2text - returns text string(s) associated with the event; this 75337c478bd9Sstevel@tonic-gate * function supports the Event2Text CS call. 75347c478bd9Sstevel@tonic-gate * 75357c478bd9Sstevel@tonic-gate * calling: event2text_t * - pointer to event2text struct 75367c478bd9Sstevel@tonic-gate * int event_source - specifies event type in event2text_t: 75377c478bd9Sstevel@tonic-gate * 0 - SS event 75387c478bd9Sstevel@tonic-gate * 1 - CS event 75397c478bd9Sstevel@tonic-gate * 75407c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS 75417c478bd9Sstevel@tonic-gate */ 75427c478bd9Sstevel@tonic-gate static int 75437c478bd9Sstevel@tonic-gate cs_event2text(event2text_t *e2t, int event_source) 75447c478bd9Sstevel@tonic-gate { 75457c478bd9Sstevel@tonic-gate event_t event; 75467c478bd9Sstevel@tonic-gate char *sepchar = "|"; 75477c478bd9Sstevel@tonic-gate 75487c478bd9Sstevel@tonic-gate /* 75497c478bd9Sstevel@tonic-gate * If event_source is 0, this is a SS event 75507c478bd9Sstevel@tonic-gate */ 75517c478bd9Sstevel@tonic-gate if (!event_source) { 75527c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_SS_EVENTS; event++) { 75537c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].ss_event == e2t->event) { 75547c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[event].text); 75557c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75567c478bd9Sstevel@tonic-gate } 75577c478bd9Sstevel@tonic-gate } 75587c478bd9Sstevel@tonic-gate (void) strcpy(e2t->text, cs_ss_event_text[MAX_CS_EVENTS].text); 75597c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75607c478bd9Sstevel@tonic-gate } else { 75617c478bd9Sstevel@tonic-gate /* 75627c478bd9Sstevel@tonic-gate * This is a CS event 75637c478bd9Sstevel@tonic-gate */ 75647c478bd9Sstevel@tonic-gate e2t->text[0] = '\0'; 75657c478bd9Sstevel@tonic-gate for (event = 0; event < MAX_CS_EVENTS; event++) { 75667c478bd9Sstevel@tonic-gate if (cs_ss_event_text[event].cs_event & e2t->event) { 75677c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, cs_ss_event_text[event].text); 75687c478bd9Sstevel@tonic-gate (void) strcat(e2t->text, sepchar); 75697c478bd9Sstevel@tonic-gate } /* if (cs_ss_event_text) */ 75707c478bd9Sstevel@tonic-gate } /* for (event) */ 75717c478bd9Sstevel@tonic-gate if (e2t->text[0]) 75727c478bd9Sstevel@tonic-gate e2t->text[strlen(e2t->text)-1] = NULL; 75737c478bd9Sstevel@tonic-gate } /* if (!event_source) */ 75747c478bd9Sstevel@tonic-gate 75757c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 75767c478bd9Sstevel@tonic-gate } 75777c478bd9Sstevel@tonic-gate 75787c478bd9Sstevel@tonic-gate /* 75797c478bd9Sstevel@tonic-gate * cs_error2text - returns a pointer to a text string containing the name 75807c478bd9Sstevel@tonic-gate * of the passed Card Services function or return code 75817c478bd9Sstevel@tonic-gate * 75827c478bd9Sstevel@tonic-gate * This function supports the Error2Text CS call. 75837c478bd9Sstevel@tonic-gate */ 75847c478bd9Sstevel@tonic-gate static char * 75857c478bd9Sstevel@tonic-gate cs_error2text(int function, int type) 75867c478bd9Sstevel@tonic-gate { 75877c478bd9Sstevel@tonic-gate cs_csfunc2text_strings_t *cfs; 75887c478bd9Sstevel@tonic-gate int end_marker; 75897c478bd9Sstevel@tonic-gate 75907c478bd9Sstevel@tonic-gate if (type == CSFUN2TEXT_FUNCTION) { 75917c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_funcstrings; 75927c478bd9Sstevel@tonic-gate end_marker = CSFuncListEnd; 75937c478bd9Sstevel@tonic-gate } else { 75947c478bd9Sstevel@tonic-gate cfs = cs_csfunc2text_returnstrings; 75957c478bd9Sstevel@tonic-gate end_marker = CS_ERRORLIST_END; 75967c478bd9Sstevel@tonic-gate } 75977c478bd9Sstevel@tonic-gate 75987c478bd9Sstevel@tonic-gate while (cfs->item != end_marker) { 75997c478bd9Sstevel@tonic-gate if (cfs->item == function) 76007c478bd9Sstevel@tonic-gate return (cfs->text); 76017c478bd9Sstevel@tonic-gate cfs++; 76027c478bd9Sstevel@tonic-gate } 76037c478bd9Sstevel@tonic-gate 76047c478bd9Sstevel@tonic-gate return (cfs->text); 76057c478bd9Sstevel@tonic-gate } 76067c478bd9Sstevel@tonic-gate 76077c478bd9Sstevel@tonic-gate /* 76087c478bd9Sstevel@tonic-gate * cs_make_device_node - creates/removes device nodes on a client's behalf; 76097c478bd9Sstevel@tonic-gate * this is MakeDeviceNode and RemoveDeviceNode 76107c478bd9Sstevel@tonic-gate * 76117c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if all device nodes successfully created/removed 76127c478bd9Sstevel@tonic-gate * CS_BAD_ATTRIBUTE - if NumDevNodes is not zero when Action 76137c478bd9Sstevel@tonic-gate * is REMOVAL_ALL_DEVICES 76147c478bd9Sstevel@tonic-gate * CS_BAD_ARGS - if an invalid Action code is specified 76157c478bd9Sstevel@tonic-gate * CS_UNSUPPORTED_FUNCTION - if SS is trying to call us 76167c478bd9Sstevel@tonic-gate * CS_OUT_OF_RESOURCE - if can't create/remove device node 76177c478bd9Sstevel@tonic-gate */ 76187c478bd9Sstevel@tonic-gate static int 76197c478bd9Sstevel@tonic-gate cs_make_device_node(client_handle_t client_handle, make_device_node_t *mdn) 76207c478bd9Sstevel@tonic-gate { 76217c478bd9Sstevel@tonic-gate cs_socket_t *sp; 76227c478bd9Sstevel@tonic-gate client_t *client; 76237c478bd9Sstevel@tonic-gate ss_make_device_node_t ss_make_device_node; 76247c478bd9Sstevel@tonic-gate int error, i; 76257c478bd9Sstevel@tonic-gate int client_lock_acquired; 76267c478bd9Sstevel@tonic-gate 76277c478bd9Sstevel@tonic-gate /* 76287c478bd9Sstevel@tonic-gate * Check to see if this is the Socket Services client handle; if it 76297c478bd9Sstevel@tonic-gate * is, we don't support SS using this call. 76307c478bd9Sstevel@tonic-gate */ 76317c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) 76327c478bd9Sstevel@tonic-gate return (CS_UNSUPPORTED_FUNCTION); 76337c478bd9Sstevel@tonic-gate 76347c478bd9Sstevel@tonic-gate /* 76357c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 76367c478bd9Sstevel@tonic-gate */ 76377c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 76387c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 76397c478bd9Sstevel@tonic-gate 76407c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 76417c478bd9Sstevel@tonic-gate 76427c478bd9Sstevel@tonic-gate /* 76437c478bd9Sstevel@tonic-gate * Make sure that this is a valid client handle. 76447c478bd9Sstevel@tonic-gate */ 76457c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &error))) { 76467c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76477c478bd9Sstevel@tonic-gate return (error); 76487c478bd9Sstevel@tonic-gate } 76497c478bd9Sstevel@tonic-gate 76507c478bd9Sstevel@tonic-gate #ifdef XXX 76517c478bd9Sstevel@tonic-gate /* 76527c478bd9Sstevel@tonic-gate * If there's no card in the socket or the card in the socket is not 76537c478bd9Sstevel@tonic-gate * for this client, then return an error. 76547c478bd9Sstevel@tonic-gate */ 76557c478bd9Sstevel@tonic-gate if (!(client->flags & CLIENT_CARD_INSERTED)) { 76567c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76577c478bd9Sstevel@tonic-gate return (CS_NO_CARD); 76587c478bd9Sstevel@tonic-gate } 76597c478bd9Sstevel@tonic-gate #endif 76607c478bd9Sstevel@tonic-gate 76617c478bd9Sstevel@tonic-gate /* 76627c478bd9Sstevel@tonic-gate * Setup the client's dip, since we use it later on. 76637c478bd9Sstevel@tonic-gate */ 76647c478bd9Sstevel@tonic-gate ss_make_device_node.dip = client->dip; 76657c478bd9Sstevel@tonic-gate 76667c478bd9Sstevel@tonic-gate /* 76677c478bd9Sstevel@tonic-gate * Make sure that we're being given a valid Action. Set the default 76687c478bd9Sstevel@tonic-gate * error code as well. 76697c478bd9Sstevel@tonic-gate */ 76707c478bd9Sstevel@tonic-gate error = CS_BAD_ARGS; /* for default case */ 76717c478bd9Sstevel@tonic-gate switch (mdn->Action) { 76727c478bd9Sstevel@tonic-gate case CREATE_DEVICE_NODE: 76737c478bd9Sstevel@tonic-gate case REMOVE_DEVICE_NODE: 76747c478bd9Sstevel@tonic-gate break; 76757c478bd9Sstevel@tonic-gate case REMOVAL_ALL_DEVICE_NODES: 76767c478bd9Sstevel@tonic-gate if (mdn->NumDevNodes) { 76777c478bd9Sstevel@tonic-gate error = CS_BAD_ATTRIBUTE; 76787c478bd9Sstevel@tonic-gate } else { 76797c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 76807c478bd9Sstevel@tonic-gate ss_make_device_node.name = NULL; 76817c478bd9Sstevel@tonic-gate SocketServices(CSInitDev, &ss_make_device_node); 76827c478bd9Sstevel@tonic-gate error = CS_SUCCESS; 76837c478bd9Sstevel@tonic-gate } 76847c478bd9Sstevel@tonic-gate /* fall-through case */ 76857c478bd9Sstevel@tonic-gate default: 76867c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 76877c478bd9Sstevel@tonic-gate return (error); 76887c478bd9Sstevel@tonic-gate /* NOTREACHED */ 76897c478bd9Sstevel@tonic-gate } /* switch */ 76907c478bd9Sstevel@tonic-gate 76917c478bd9Sstevel@tonic-gate /* 76927c478bd9Sstevel@tonic-gate * Loop through the device node descriptions and create or destroy 76937c478bd9Sstevel@tonic-gate * the device node. 76947c478bd9Sstevel@tonic-gate */ 76957c478bd9Sstevel@tonic-gate for (i = 0; i < mdn->NumDevNodes; i++) { 76967c478bd9Sstevel@tonic-gate devnode_desc_t *devnode_desc = &mdn->devnode_desc[i]; 76977c478bd9Sstevel@tonic-gate 76987c478bd9Sstevel@tonic-gate ss_make_device_node.name = devnode_desc->name; 76997c478bd9Sstevel@tonic-gate ss_make_device_node.spec_type = devnode_desc->spec_type; 77007c478bd9Sstevel@tonic-gate ss_make_device_node.minor_num = devnode_desc->minor_num; 77017c478bd9Sstevel@tonic-gate ss_make_device_node.node_type = devnode_desc->node_type; 77027c478bd9Sstevel@tonic-gate 77037c478bd9Sstevel@tonic-gate /* 77047c478bd9Sstevel@tonic-gate * Set the appropriate flag for the action that we want 77057c478bd9Sstevel@tonic-gate * SS to perform. Note that if we ever OR-in the flag 77067c478bd9Sstevel@tonic-gate * here, we need to be sure to clear the flags member 77077c478bd9Sstevel@tonic-gate * since we sometimes OR-in other flags below. 77087c478bd9Sstevel@tonic-gate */ 77097c478bd9Sstevel@tonic-gate if (mdn->Action == CREATE_DEVICE_NODE) { 77107c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_CREATE_DEVICE; 77117c478bd9Sstevel@tonic-gate } else { 77127c478bd9Sstevel@tonic-gate ss_make_device_node.flags = SS_CSINITDEV_REMOVE_DEVICE; 77137c478bd9Sstevel@tonic-gate } 77147c478bd9Sstevel@tonic-gate 77157c478bd9Sstevel@tonic-gate /* 77167c478bd9Sstevel@tonic-gate * If this is not the last device to process, then we need 77177c478bd9Sstevel@tonic-gate * to tell SS that more device process requests are on 77187c478bd9Sstevel@tonic-gate * their way after this one. 77197c478bd9Sstevel@tonic-gate */ 77207c478bd9Sstevel@tonic-gate if (i < (mdn->NumDevNodes - 1)) 77217c478bd9Sstevel@tonic-gate ss_make_device_node.flags |= SS_CSINITDEV_MORE_DEVICES; 77227c478bd9Sstevel@tonic-gate 77237c478bd9Sstevel@tonic-gate if (SocketServices(CSInitDev, &ss_make_device_node) != SUCCESS) { 77247c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 77257c478bd9Sstevel@tonic-gate return (CS_OUT_OF_RESOURCE); 77267c478bd9Sstevel@tonic-gate } /* CSInitDev */ 77277c478bd9Sstevel@tonic-gate } /* for (mdn->NumDevNodes) */ 77287c478bd9Sstevel@tonic-gate 77297c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 77307c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 77317c478bd9Sstevel@tonic-gate } 77327c478bd9Sstevel@tonic-gate 77337c478bd9Sstevel@tonic-gate /* 77347c478bd9Sstevel@tonic-gate * cs_remove_device_node - removes device nodes 77357c478bd9Sstevel@tonic-gate * 77367c478bd9Sstevel@tonic-gate * (see cs_make_device_node for a description of the calling 77377c478bd9Sstevel@tonic-gate * and return parameters) 77387c478bd9Sstevel@tonic-gate */ 77397c478bd9Sstevel@tonic-gate static int 77407c478bd9Sstevel@tonic-gate cs_remove_device_node(client_handle_t client_handle, remove_device_node_t *rdn) 77417c478bd9Sstevel@tonic-gate { 77427c478bd9Sstevel@tonic-gate 77437c478bd9Sstevel@tonic-gate /* 77447c478bd9Sstevel@tonic-gate * XXX - Note the assumption here that the make_device_node_t and 77457c478bd9Sstevel@tonic-gate * remove_device_node_t structures are identical. 77467c478bd9Sstevel@tonic-gate */ 77477c478bd9Sstevel@tonic-gate return (cs_make_device_node(client_handle, (make_device_node_t *)rdn)); 77487c478bd9Sstevel@tonic-gate } 77497c478bd9Sstevel@tonic-gate 77507c478bd9Sstevel@tonic-gate /* 77517c478bd9Sstevel@tonic-gate * cs_ddi_info - this function is used by clients that need to support 77527c478bd9Sstevel@tonic-gate * the xxx_getinfo function; this is CS_DDI_Info 77537c478bd9Sstevel@tonic-gate */ 77547c478bd9Sstevel@tonic-gate static int 77557c478bd9Sstevel@tonic-gate cs_ddi_info(cs_ddi_info_t *cdi) 77567c478bd9Sstevel@tonic-gate { 77577c478bd9Sstevel@tonic-gate cs_socket_t *sp; 77587c478bd9Sstevel@tonic-gate client_t *client; 77597c478bd9Sstevel@tonic-gate int client_lock_acquired; 77607c478bd9Sstevel@tonic-gate 77617c478bd9Sstevel@tonic-gate if (cdi->driver_name == NULL) 77627c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 77637c478bd9Sstevel@tonic-gate 77647c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 77657c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 77667c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s]\n", 77677c478bd9Sstevel@tonic-gate (int)cdi->Socket, cdi->driver_name); 77687c478bd9Sstevel@tonic-gate } 77697c478bd9Sstevel@tonic-gate #endif 77707c478bd9Sstevel@tonic-gate 77717c478bd9Sstevel@tonic-gate /* 77727c478bd9Sstevel@tonic-gate * Check to see if the socket number is in range - the system 77737c478bd9Sstevel@tonic-gate * framework may cause a client driver to call us with 77747c478bd9Sstevel@tonic-gate * a socket number that used to be present but isn't 77757c478bd9Sstevel@tonic-gate * anymore. This is not a bug, and it's OK to return 77767c478bd9Sstevel@tonic-gate * an error if the socket number is out of range. 77777c478bd9Sstevel@tonic-gate */ 77787c478bd9Sstevel@tonic-gate if (!CHECK_SOCKET_NUM(cdi->Socket, cs_globals.max_socket_num)) { 77797c478bd9Sstevel@tonic-gate 77807c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 77817c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 77827c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d client [%s] " 77837c478bd9Sstevel@tonic-gate "SOCKET IS OUT OF RANGE\n", 77847c478bd9Sstevel@tonic-gate (int)cdi->Socket, 77857c478bd9Sstevel@tonic-gate cdi->driver_name); 77867c478bd9Sstevel@tonic-gate } 77877c478bd9Sstevel@tonic-gate #endif 77887c478bd9Sstevel@tonic-gate 77897c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 77907c478bd9Sstevel@tonic-gate } /* if (!CHECK_SOCKET_NUM) */ 77917c478bd9Sstevel@tonic-gate 77927c478bd9Sstevel@tonic-gate /* 77937c478bd9Sstevel@tonic-gate * Get a pointer to this client's socket structure. 77947c478bd9Sstevel@tonic-gate */ 77957c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(cdi->Socket)) == NULL) 77967c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 77977c478bd9Sstevel@tonic-gate 77987c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_ENTER(client_lock_acquired, sp); 77997c478bd9Sstevel@tonic-gate 78007c478bd9Sstevel@tonic-gate client = sp->client_list; 78017c478bd9Sstevel@tonic-gate while (client) { 78027c478bd9Sstevel@tonic-gate 78037c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 78047c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 78057c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: socket %d checking client [%s] " 78067c478bd9Sstevel@tonic-gate "handle 0x%x\n", 78077c478bd9Sstevel@tonic-gate (int)cdi->Socket, 78087c478bd9Sstevel@tonic-gate client->driver_name, 78097c478bd9Sstevel@tonic-gate (int)client->client_handle); 78107c478bd9Sstevel@tonic-gate } 78117c478bd9Sstevel@tonic-gate #endif 78127c478bd9Sstevel@tonic-gate 78137c478bd9Sstevel@tonic-gate if (client->driver_name != NULL) { 78147c478bd9Sstevel@tonic-gate if (!(strcmp(client->driver_name, cdi->driver_name))) { 78157c478bd9Sstevel@tonic-gate cdi->dip = client->dip; 78167c478bd9Sstevel@tonic-gate cdi->instance = client->instance; 78177c478bd9Sstevel@tonic-gate 78187c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 78197c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 78207c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ddi_info: found client [%s] " 78217c478bd9Sstevel@tonic-gate "instance %d handle 0x%x\n", 78227c478bd9Sstevel@tonic-gate client->driver_name, client->instance, 78237c478bd9Sstevel@tonic-gate (int)client->client_handle); 78247c478bd9Sstevel@tonic-gate } 78257c478bd9Sstevel@tonic-gate #endif 78267c478bd9Sstevel@tonic-gate 78277c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 78287c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 78297c478bd9Sstevel@tonic-gate } /* strcmp */ 78307c478bd9Sstevel@tonic-gate } /* driver_name != NULL */ 78317c478bd9Sstevel@tonic-gate client = client->next; 78327c478bd9Sstevel@tonic-gate } /* while (client) */ 78337c478bd9Sstevel@tonic-gate 78347c478bd9Sstevel@tonic-gate EVENT_THREAD_MUTEX_EXIT(client_lock_acquired, sp); 78357c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 78367c478bd9Sstevel@tonic-gate } 78377c478bd9Sstevel@tonic-gate 78387c478bd9Sstevel@tonic-gate /* 78397c478bd9Sstevel@tonic-gate * cs_sys_ctl - Card Services system control; this is CS_Sys_Ctl 78407c478bd9Sstevel@tonic-gate */ 78417c478bd9Sstevel@tonic-gate static int 78427c478bd9Sstevel@tonic-gate cs_sys_ctl(cs_sys_ctl_t *csc) 78437c478bd9Sstevel@tonic-gate { 78447c478bd9Sstevel@tonic-gate cs_socket_t *sp; 78457c478bd9Sstevel@tonic-gate client_t *cp; 78467c478bd9Sstevel@tonic-gate int sn, ret = CS_UNSUPPORTED_MODE; 78477c478bd9Sstevel@tonic-gate 78487c478bd9Sstevel@tonic-gate switch (csc->Action) { 78497c478bd9Sstevel@tonic-gate case CS_SYS_CTL_SEND_EVENT: 78507c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 78517c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(csc->Socket); 78527c478bd9Sstevel@tonic-gate else 78537c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(csc->client_handle); 78547c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 78557c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 78567c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 78577c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 78587c478bd9Sstevel@tonic-gate csc->Events &= CS_EVENT_CLIENT_EVENTS_MASK; 78597c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_SOCKET) 78607c478bd9Sstevel@tonic-gate sp->events |= csc->Events; 78617c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_EVENT_CLIENT) { 78627c478bd9Sstevel@tonic-gate if ((cp = cs_find_client(csc->client_handle, &ret)) == 78637c478bd9Sstevel@tonic-gate NULL) { 78647c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78657c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 78667c478bd9Sstevel@tonic-gate return (ret); 78677c478bd9Sstevel@tonic-gate } /* cs_find_client */ 78687c478bd9Sstevel@tonic-gate /* 78697c478bd9Sstevel@tonic-gate * Setup the events that we want to send to the client. 78707c478bd9Sstevel@tonic-gate */ 78717c478bd9Sstevel@tonic-gate cp->events |= (csc->Events & 78727c478bd9Sstevel@tonic-gate (cp->event_mask | cp->global_mask)); 78737c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_EVENT_CLIENT */ 78747c478bd9Sstevel@tonic-gate 78757c478bd9Sstevel@tonic-gate if (csc->Flags & CS_SYS_CTL_WAIT_SYNC) { 78767c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 78777c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78787c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 78797c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 78807c478bd9Sstevel@tonic-gate } else { 78817c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 78827c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 78837c478bd9Sstevel@tonic-gate } /* CS_SYS_CTL_WAIT_SYNC */ 78847c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 78857c478bd9Sstevel@tonic-gate ret = CS_SUCCESS; 78867c478bd9Sstevel@tonic-gate break; 78877c478bd9Sstevel@tonic-gate default: 78887c478bd9Sstevel@tonic-gate break; 78897c478bd9Sstevel@tonic-gate } /* switch */ 78907c478bd9Sstevel@tonic-gate 78917c478bd9Sstevel@tonic-gate return (ret); 78927c478bd9Sstevel@tonic-gate } 78937c478bd9Sstevel@tonic-gate 78947c478bd9Sstevel@tonic-gate /* 78957c478bd9Sstevel@tonic-gate * cs_get_sp - returns pointer to per-socket structure for passed 78967c478bd9Sstevel@tonic-gate * socket number 78977c478bd9Sstevel@tonic-gate * 78987c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure 78997c478bd9Sstevel@tonic-gate * NULL - invalid socket number passed in 79007c478bd9Sstevel@tonic-gate */ 79017c478bd9Sstevel@tonic-gate static cs_socket_t * 79027c478bd9Sstevel@tonic-gate cs_get_sp(uint32_t sn) 79037c478bd9Sstevel@tonic-gate { 79047c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 79057c478bd9Sstevel@tonic-gate 79067c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 79077c478bd9Sstevel@tonic-gate return (NULL); 79087c478bd9Sstevel@tonic-gate 79097c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) 79107c478bd9Sstevel@tonic-gate return (NULL); 79117c478bd9Sstevel@tonic-gate 79127c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 79137c478bd9Sstevel@tonic-gate return (sp); 79147c478bd9Sstevel@tonic-gate 79157c478bd9Sstevel@tonic-gate return (NULL); 79167c478bd9Sstevel@tonic-gate } 79177c478bd9Sstevel@tonic-gate 79187c478bd9Sstevel@tonic-gate /* 79197c478bd9Sstevel@tonic-gate * cs_find_sp - searches socket list and returns pointer to passed socket 79207c478bd9Sstevel@tonic-gate * number 79217c478bd9Sstevel@tonic-gate * 79227c478bd9Sstevel@tonic-gate * return: (cs_socket_t *) - pointer to socket structure if found 79237c478bd9Sstevel@tonic-gate * NULL - socket not found 79247c478bd9Sstevel@tonic-gate */ 79257c478bd9Sstevel@tonic-gate static cs_socket_t * 79267c478bd9Sstevel@tonic-gate cs_find_sp(uint32_t sn) 79277c478bd9Sstevel@tonic-gate { 79287c478bd9Sstevel@tonic-gate cs_socket_t *sp = cs_globals.sp; 79297c478bd9Sstevel@tonic-gate 79307c478bd9Sstevel@tonic-gate while (sp) { 79317c478bd9Sstevel@tonic-gate if (sp->socket_num == CS_GET_SOCKET_NUMBER(sn)) 79327c478bd9Sstevel@tonic-gate return (sp); 79337c478bd9Sstevel@tonic-gate sp = sp->next; 79347c478bd9Sstevel@tonic-gate } /* while */ 79357c478bd9Sstevel@tonic-gate 79367c478bd9Sstevel@tonic-gate return (NULL); 79377c478bd9Sstevel@tonic-gate } 79387c478bd9Sstevel@tonic-gate 79397c478bd9Sstevel@tonic-gate /* 79407c478bd9Sstevel@tonic-gate * cs_add_socket - add a socket 79417c478bd9Sstevel@tonic-gate * 79427c478bd9Sstevel@tonic-gate * call: sn - socket number to add 79437c478bd9Sstevel@tonic-gate * 79447c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 79457c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to add socket 79467c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - unable to get CIS window for socket 79477c478bd9Sstevel@tonic-gate * 79487c478bd9Sstevel@tonic-gate * We get called here once for each socket that the framework wants to 79497c478bd9Sstevel@tonic-gate * add. When we are called, the framework guarentees that until we 79507c478bd9Sstevel@tonic-gate * complete this routine, no other adapter instances will be allowed 79517c478bd9Sstevel@tonic-gate * to attach and thus no other PCE_ADD_SOCKET events will occur. 79527c478bd9Sstevel@tonic-gate * It is safe to call SS_InquireAdapter to get the number of 79537c478bd9Sstevel@tonic-gate * windows that the framework currently knows about. 79547c478bd9Sstevel@tonic-gate */ 79557c478bd9Sstevel@tonic-gate static uint32_t 79567c478bd9Sstevel@tonic-gate cs_add_socket(uint32_t sn) 79577c478bd9Sstevel@tonic-gate { 79587c478bd9Sstevel@tonic-gate cs_socket_t *sp; 79597c478bd9Sstevel@tonic-gate sservice_t sservice; 79607c478bd9Sstevel@tonic-gate get_cookies_and_dip_t *gcad; 79617c478bd9Sstevel@tonic-gate win_req_t win_req; 79627c478bd9Sstevel@tonic-gate convert_speed_t convert_speed; 79637c478bd9Sstevel@tonic-gate set_socket_t set_socket; 79647c478bd9Sstevel@tonic-gate cs_window_t *cw; 79657c478bd9Sstevel@tonic-gate inquire_adapter_t inquire_adapter; 79667c478bd9Sstevel@tonic-gate inquire_window_t inquire_window; 79677c478bd9Sstevel@tonic-gate int ret, added_windows; 79687c478bd9Sstevel@tonic-gate 79697c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 79707c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 79717c478bd9Sstevel@tonic-gate 79727c478bd9Sstevel@tonic-gate /* 79737c478bd9Sstevel@tonic-gate * See if this socket has already been added - if it has, we 79747c478bd9Sstevel@tonic-gate * fail this. If we can't find the socket, then allocate 79757c478bd9Sstevel@tonic-gate * a new socket structure. If we do find the socket, then 79767c478bd9Sstevel@tonic-gate * check to see if it's already added; if it is, then 79777c478bd9Sstevel@tonic-gate * this is an error and return CS_BAD_SOCKET; if not, 79787c478bd9Sstevel@tonic-gate * then traverse the socket structure list and add this 79797c478bd9Sstevel@tonic-gate * next socket strcture to the end of the list. 79807c478bd9Sstevel@tonic-gate * XXX What about locking this list while we update it? Is 79817c478bd9Sstevel@tonic-gate * that necessary since we're using the SOCKET_IS_VALID 79827c478bd9Sstevel@tonic-gate * flag and since we never delete a socket from the 79837c478bd9Sstevel@tonic-gate * list once it's been added? 79847c478bd9Sstevel@tonic-gate */ 79857c478bd9Sstevel@tonic-gate if ((sp = cs_find_sp(sn)) == NULL) { 79867c478bd9Sstevel@tonic-gate cs_socket_t *spp = cs_globals.sp; 79877c478bd9Sstevel@tonic-gate 79887c478bd9Sstevel@tonic-gate sp = (cs_socket_t *)kmem_zalloc(sizeof (cs_socket_t), KM_SLEEP); 79897c478bd9Sstevel@tonic-gate 79907c478bd9Sstevel@tonic-gate if (cs_globals.sp == NULL) 79917c478bd9Sstevel@tonic-gate cs_globals.sp = sp; 79927c478bd9Sstevel@tonic-gate else 79937c478bd9Sstevel@tonic-gate while (spp) { 79947c478bd9Sstevel@tonic-gate if (spp->next == NULL) { 79957c478bd9Sstevel@tonic-gate spp->next = sp; 79967c478bd9Sstevel@tonic-gate break; 79977c478bd9Sstevel@tonic-gate } /* if */ 79987c478bd9Sstevel@tonic-gate spp = spp->next; 79997c478bd9Sstevel@tonic-gate } /* while */ 80007c478bd9Sstevel@tonic-gate 80017c478bd9Sstevel@tonic-gate } else { 80027c478bd9Sstevel@tonic-gate if (sp->flags & SOCKET_IS_VALID) 80037c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 80047c478bd9Sstevel@tonic-gate } /* cs_find_sp */ 80057c478bd9Sstevel@tonic-gate 80067c478bd9Sstevel@tonic-gate /* 80077c478bd9Sstevel@tonic-gate * Setup the socket number 80087c478bd9Sstevel@tonic-gate */ 80097c478bd9Sstevel@tonic-gate sp->socket_num = sn; 80107c478bd9Sstevel@tonic-gate 80117c478bd9Sstevel@tonic-gate /* 80127c478bd9Sstevel@tonic-gate * Find out how many windows the framework knows about 80137c478bd9Sstevel@tonic-gate * so far. If this number of windows is greater 80147c478bd9Sstevel@tonic-gate * than our current window count, bump up our 80157c478bd9Sstevel@tonic-gate * current window count. 80167c478bd9Sstevel@tonic-gate * XXX Note that there is a BIG assumption here and that 80177c478bd9Sstevel@tonic-gate * is that once the framework tells us that it has 80187c478bd9Sstevel@tonic-gate * a window (as reflected in the NumWindows 80197c478bd9Sstevel@tonic-gate * value) it can NEVER remove that window. 80207c478bd9Sstevel@tonic-gate * When we really get the drop socket and drop 80217c478bd9Sstevel@tonic-gate * window mechanism working correctly, we'll have 80227c478bd9Sstevel@tonic-gate * to revisit this. 80237c478bd9Sstevel@tonic-gate */ 80247c478bd9Sstevel@tonic-gate SocketServices(SS_InquireAdapter, &inquire_adapter); 80257c478bd9Sstevel@tonic-gate 80267c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.window_lock); 80277c478bd9Sstevel@tonic-gate added_windows = inquire_adapter.NumWindows - cs_globals.num_windows; 80287c478bd9Sstevel@tonic-gate if (added_windows > 0) { 80297c478bd9Sstevel@tonic-gate if (cs_add_windows(added_windows, 80307c478bd9Sstevel@tonic-gate cs_globals.num_windows) != CS_SUCCESS) { 80317c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80327c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80337c478bd9Sstevel@tonic-gate } /* cs_add_windows */ 80347c478bd9Sstevel@tonic-gate 80357c478bd9Sstevel@tonic-gate cs_globals.num_windows = inquire_adapter.NumWindows; 80367c478bd9Sstevel@tonic-gate 80377c478bd9Sstevel@tonic-gate } /* if (added_windows) */ 80387c478bd9Sstevel@tonic-gate 80397c478bd9Sstevel@tonic-gate /* 80407c478bd9Sstevel@tonic-gate * Find a window that we can use for this socket's CIS window. 80417c478bd9Sstevel@tonic-gate */ 80427c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 80437c478bd9Sstevel@tonic-gate 80447c478bd9Sstevel@tonic-gate convert_speed.Attributes = CONVERT_NS_TO_DEVSPEED; 80457c478bd9Sstevel@tonic-gate convert_speed.nS = CIS_DEFAULT_SPEED; 80467c478bd9Sstevel@tonic-gate (void) cs_convert_speed(&convert_speed); 80477c478bd9Sstevel@tonic-gate 80487c478bd9Sstevel@tonic-gate win_req.win_params.AccessSpeed = convert_speed.devspeed; 80497c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8); 80507c478bd9Sstevel@tonic-gate win_req.Attributes = (WIN_MEMORY_TYPE_AM | WIN_MEMORY_TYPE_CM); 80517c478bd9Sstevel@tonic-gate win_req.Base.base = 0; 80527c478bd9Sstevel@tonic-gate win_req.Size = 0; 80537c478bd9Sstevel@tonic-gate 80547c478bd9Sstevel@tonic-gate if ((ret = cs_find_mem_window(sp->socket_num, &win_req, 80557c478bd9Sstevel@tonic-gate &sp->cis_win_num)) != CS_SUCCESS) { 80567c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80577c478bd9Sstevel@tonic-gate sp->cis_win_num = PCMCIA_MAX_WINDOWS; 80587c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't get CIS " 80597c478bd9Sstevel@tonic-gate "window - error 0x%x\n", 80607c478bd9Sstevel@tonic-gate sp->socket_num, ret); 80617c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80627c478bd9Sstevel@tonic-gate } /* cs_find_mem_window */ 80637c478bd9Sstevel@tonic-gate 80647c478bd9Sstevel@tonic-gate if ((cw = cs_get_wp(sp->cis_win_num)) == NULL) { 80657c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80667c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 80677c478bd9Sstevel@tonic-gate } 80687c478bd9Sstevel@tonic-gate 80697c478bd9Sstevel@tonic-gate inquire_window.window = sp->cis_win_num; 80707c478bd9Sstevel@tonic-gate SocketServices(SS_InquireWindow, &inquire_window); 80717c478bd9Sstevel@tonic-gate 80727c478bd9Sstevel@tonic-gate /* 80737c478bd9Sstevel@tonic-gate * If the CIS window is a variable sized window, then use 80747c478bd9Sstevel@tonic-gate * the size that cs_find_mem_window returned to us, 80757c478bd9Sstevel@tonic-gate * since this will be the minimum size that we can 80767c478bd9Sstevel@tonic-gate * set this window to. If the CIS window is a fixed 80777c478bd9Sstevel@tonic-gate * sized window, then use the system pagesize as the 80787c478bd9Sstevel@tonic-gate * CIS window size. 80797c478bd9Sstevel@tonic-gate */ 80807c478bd9Sstevel@tonic-gate if (inquire_window.mem_win_char.MemWndCaps & WC_SIZE) { 80817c478bd9Sstevel@tonic-gate sp->cis_win_size = win_req.Size; 80827c478bd9Sstevel@tonic-gate } else { 80837c478bd9Sstevel@tonic-gate sp->cis_win_size = PAGESIZE; 80847c478bd9Sstevel@tonic-gate } 80857c478bd9Sstevel@tonic-gate 80867c478bd9Sstevel@tonic-gate cw->state |= (CW_CIS | CW_ALLOCATED); 80877c478bd9Sstevel@tonic-gate cw->socket_num = sp->socket_num; 80887c478bd9Sstevel@tonic-gate 80897c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.window_lock); 80907c478bd9Sstevel@tonic-gate 80917c478bd9Sstevel@tonic-gate #if defined(CS_DEBUG) 80927c478bd9Sstevel@tonic-gate if (cs_debug > 1) { 80937c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d using CIS window %d " 80947c478bd9Sstevel@tonic-gate "size 0x%x\n", (int)sp->socket_num, 80957c478bd9Sstevel@tonic-gate (int)sp->cis_win_num, 80967c478bd9Sstevel@tonic-gate (int)sp->cis_win_size); 80977c478bd9Sstevel@tonic-gate } 80987c478bd9Sstevel@tonic-gate #endif 80997c478bd9Sstevel@tonic-gate 81007c478bd9Sstevel@tonic-gate /* 81017c478bd9Sstevel@tonic-gate * Get the adapter information associated with this socket so 81027c478bd9Sstevel@tonic-gate * that we can initialize the mutexes, condition variables, 81037c478bd9Sstevel@tonic-gate * soft interrupt handler and per-socket adapter info. 81047c478bd9Sstevel@tonic-gate */ 81057c478bd9Sstevel@tonic-gate gcad = &sservice.get_cookies; 81067c478bd9Sstevel@tonic-gate gcad->socket = sp->socket_num; 81077c478bd9Sstevel@tonic-gate if (SocketServices(CSGetCookiesAndDip, &sservice) != SUCCESS) { 81087c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d CSGetCookiesAndDip " 81097c478bd9Sstevel@tonic-gate "failure\n", sp->socket_num); 81107c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 81117c478bd9Sstevel@tonic-gate } /* CSGetCookiesAndDip */ 81127c478bd9Sstevel@tonic-gate 81137c478bd9Sstevel@tonic-gate /* 81147c478bd9Sstevel@tonic-gate * Save the iblock and idev cookies for RegisterClient 81157c478bd9Sstevel@tonic-gate */ 81167c478bd9Sstevel@tonic-gate sp->iblk = gcad->iblock; 81177c478bd9Sstevel@tonic-gate sp->idev = gcad->idevice; 81187c478bd9Sstevel@tonic-gate 81197c478bd9Sstevel@tonic-gate /* 81207c478bd9Sstevel@tonic-gate * Setup the per-socket adapter info 81217c478bd9Sstevel@tonic-gate */ 81227c478bd9Sstevel@tonic-gate sp->adapter.flags = 0; 81237c478bd9Sstevel@tonic-gate (void) strcpy(sp->adapter.name, gcad->adapter_info.name); 81247c478bd9Sstevel@tonic-gate sp->adapter.major = gcad->adapter_info.major; 81257c478bd9Sstevel@tonic-gate sp->adapter.minor = gcad->adapter_info.minor; 81267c478bd9Sstevel@tonic-gate sp->adapter.instance = ddi_get_instance(gcad->dip); 81277c478bd9Sstevel@tonic-gate sp->adapter.number = gcad->adapter_info.number; 81287c478bd9Sstevel@tonic-gate sp->adapter.num_sockets = gcad->adapter_info.num_sockets; 81297c478bd9Sstevel@tonic-gate sp->adapter.first_socket = gcad->adapter_info.first_socket; 81307c478bd9Sstevel@tonic-gate 81317c478bd9Sstevel@tonic-gate /* Setup for cs_event and cs_event_thread */ 81327c478bd9Sstevel@tonic-gate mutex_init(&sp->lock, NULL, MUTEX_DRIVER, *(gcad->iblock)); 81337c478bd9Sstevel@tonic-gate mutex_init(&sp->client_lock, NULL, MUTEX_DRIVER, NULL); 81347c478bd9Sstevel@tonic-gate mutex_init(&sp->cis_lock, NULL, MUTEX_DRIVER, NULL); 81357c478bd9Sstevel@tonic-gate 81367c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 81377c478bd9Sstevel@tonic-gate mutex_init(&sp->ss_thread_lock, NULL, MUTEX_DRIVER, NULL); 81387c478bd9Sstevel@tonic-gate 81397c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_MUTEX; 81407c478bd9Sstevel@tonic-gate 81417c478bd9Sstevel@tonic-gate /* Setup for cs_event_thread */ 81427c478bd9Sstevel@tonic-gate cv_init(&sp->thread_cv, NULL, CV_DRIVER, NULL); 81437c478bd9Sstevel@tonic-gate cv_init(&sp->caller_cv, NULL, CV_DRIVER, NULL); 81447c478bd9Sstevel@tonic-gate cv_init(&sp->reset_cv, NULL, CV_DRIVER, NULL); 81457c478bd9Sstevel@tonic-gate 81467c478bd9Sstevel@tonic-gate /* Setup for Socket Services work thread */ 81477c478bd9Sstevel@tonic-gate cv_init(&sp->ss_thread_cv, NULL, CV_DRIVER, NULL); 81487c478bd9Sstevel@tonic-gate cv_init(&sp->ss_caller_cv, NULL, CV_DRIVER, NULL); 81497c478bd9Sstevel@tonic-gate 81507c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_CV; 81517c478bd9Sstevel@tonic-gate 81527c478bd9Sstevel@tonic-gate /* 81537c478bd9Sstevel@tonic-gate * If we haven't installed it yet, then install the soft interrupt 81547c478bd9Sstevel@tonic-gate * handler and save away the softint id. 81557c478bd9Sstevel@tonic-gate */ 81567c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SOFTINTR)) { 81577c478bd9Sstevel@tonic-gate if (ddi_add_softintr(gcad->dip, DDI_SOFTINT_HIGH, 81587c478bd9Sstevel@tonic-gate &sp->softint_id, 81597c478bd9Sstevel@tonic-gate NULL, NULL, 81607c478bd9Sstevel@tonic-gate cs_socket_event_softintr, 81617c478bd9Sstevel@tonic-gate (caddr_t)NULL) != DDI_SUCCESS) { 81627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d can't add " 81637c478bd9Sstevel@tonic-gate "softintr\n", sp->socket_num); 81647c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 81657c478bd9Sstevel@tonic-gate } /* ddi_add_softintr */ 81667c478bd9Sstevel@tonic-gate 81677c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 81687c478bd9Sstevel@tonic-gate cs_globals.softint_id = sp->softint_id; 81697c478bd9Sstevel@tonic-gate cs_globals.init_state |= GLOBAL_INIT_STATE_SOFTINTR; 81707c478bd9Sstevel@tonic-gate /* XXX this timer is hokey at best... */ 81717c478bd9Sstevel@tonic-gate cs_globals.sotfint_tmo = timeout(cs_event_softintr_timeout, 81727c478bd9Sstevel@tonic-gate NULL, SOFTINT_TIMEOUT_TIME); 81737c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 81747c478bd9Sstevel@tonic-gate } else { 81757c478bd9Sstevel@tonic-gate /* 81767c478bd9Sstevel@tonic-gate * We've already added the soft interrupt handler, so just 81777c478bd9Sstevel@tonic-gate * store away the softint id. 81787c478bd9Sstevel@tonic-gate */ 81797c478bd9Sstevel@tonic-gate sp->softint_id = cs_globals.softint_id; 81807c478bd9Sstevel@tonic-gate } /* if (!GLOBAL_INIT_STATE_SOFTINTR) */ 81817c478bd9Sstevel@tonic-gate 81827c478bd9Sstevel@tonic-gate /* 81837c478bd9Sstevel@tonic-gate * While this next flag doesn't really describe a per-socket 81847c478bd9Sstevel@tonic-gate * resource, we still set it for each socket. When the soft 81857c478bd9Sstevel@tonic-gate * interrupt handler finally gets removed in cs_deinit, this 81867c478bd9Sstevel@tonic-gate * flag will get cleared. 81877c478bd9Sstevel@tonic-gate */ 81887c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_SOFTINTR; 81897c478bd9Sstevel@tonic-gate 81907c478bd9Sstevel@tonic-gate /* 81917c478bd9Sstevel@tonic-gate * Socket Services defaults all sockets to power off and 81927c478bd9Sstevel@tonic-gate * clears all event masks. We want to receive at least 81937c478bd9Sstevel@tonic-gate * card insertion events, so enable them. Turn off power 81947c478bd9Sstevel@tonic-gate * to the socket as well. We will turn it on again when 81957c478bd9Sstevel@tonic-gate * we get a card insertion event. 81967c478bd9Sstevel@tonic-gate */ 81977c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 81987c478bd9Sstevel@tonic-gate set_socket.socket = sp->socket_num; 81997c478bd9Sstevel@tonic-gate set_socket.SCIntMask = SBM_CD; 82007c478bd9Sstevel@tonic-gate set_socket.IREQRouting = 0; 82017c478bd9Sstevel@tonic-gate set_socket.IFType = IF_MEMORY; 82027c478bd9Sstevel@tonic-gate set_socket.CtlInd = 0; /* turn off controls and indicators */ 82037c478bd9Sstevel@tonic-gate set_socket.State = (unsigned)~0; /* clear latched state bits */ 82047c478bd9Sstevel@tonic-gate 82057c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VCC, 82067c478bd9Sstevel@tonic-gate &set_socket.VccLevel); 82077c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP1, 82087c478bd9Sstevel@tonic-gate &set_socket.Vpp1Level); 82097c478bd9Sstevel@tonic-gate (void) cs_convert_powerlevel(sp->socket_num, 0, VPP2, 82107c478bd9Sstevel@tonic-gate &set_socket.Vpp2Level); 82117c478bd9Sstevel@tonic-gate 82127c478bd9Sstevel@tonic-gate if ((ret = SocketServices(SS_SetSocket, &set_socket)) != SUCCESS) { 82137c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_add_socket: socket %d SS_SetSocket " 82147c478bd9Sstevel@tonic-gate "failure %d\n", sp->socket_num, ret); 82157c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 82167c478bd9Sstevel@tonic-gate } /* SS_SetSocket */ 82177c478bd9Sstevel@tonic-gate 82187c478bd9Sstevel@tonic-gate /* 82197c478bd9Sstevel@tonic-gate * The various socket-specific variables are now set up, so 82207c478bd9Sstevel@tonic-gate * increment the global socket count and also mark the 82217c478bd9Sstevel@tonic-gate * socket as available. We need to set this before we 82227c478bd9Sstevel@tonic-gate * start any of the per-socket threads so that the threads 82237c478bd9Sstevel@tonic-gate * can get a valid socket pointer when they start. 82247c478bd9Sstevel@tonic-gate */ 82257c478bd9Sstevel@tonic-gate mutex_enter(&cs_globals.global_lock); 82267c478bd9Sstevel@tonic-gate cs_globals.num_sockets++; 82277c478bd9Sstevel@tonic-gate cs_globals.max_socket_num = 82287c478bd9Sstevel@tonic-gate max(cs_globals.max_socket_num, sp->socket_num + 1); 82297c478bd9Sstevel@tonic-gate mutex_exit(&cs_globals.global_lock); 82307c478bd9Sstevel@tonic-gate sp->flags = SOCKET_IS_VALID; 82317c478bd9Sstevel@tonic-gate 82327c478bd9Sstevel@tonic-gate /* 82337c478bd9Sstevel@tonic-gate * Create the per-socket event handler thread. 82347c478bd9Sstevel@tonic-gate */ 82357c478bd9Sstevel@tonic-gate sp->event_thread = CREATE_SOCKET_EVENT_THREAD(cs_event_thread, 82367c478bd9Sstevel@tonic-gate (uintptr_t)sn); 82377c478bd9Sstevel@tonic-gate 82387c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 82397c478bd9Sstevel@tonic-gate sp->init_state |= SOCKET_INIT_STATE_THREAD; 82407c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 82417c478bd9Sstevel@tonic-gate 82427c478bd9Sstevel@tonic-gate /* 82437c478bd9Sstevel@tonic-gate * Create the per-socket Socket Services work thread. 82447c478bd9Sstevel@tonic-gate */ 82457c478bd9Sstevel@tonic-gate sp->ss_thread = CREATE_SOCKET_EVENT_THREAD(cs_ss_thread, 82467c478bd9Sstevel@tonic-gate (uintptr_t)sn); 82477c478bd9Sstevel@tonic-gate 82487c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 82497c478bd9Sstevel@tonic-gate sp->init_state |= (SOCKET_INIT_STATE_SS_THREAD | 82507c478bd9Sstevel@tonic-gate SOCKET_INIT_STATE_READY); 82517c478bd9Sstevel@tonic-gate sp->event_mask = CS_EVENT_CARD_INSERTION; 82527c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 82537c478bd9Sstevel@tonic-gate 82547c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 82557c478bd9Sstevel@tonic-gate } 82567c478bd9Sstevel@tonic-gate 82577c478bd9Sstevel@tonic-gate /* 82587c478bd9Sstevel@tonic-gate * cs_drop_socket - drop a socket 82597c478bd9Sstevel@tonic-gate * 82607c478bd9Sstevel@tonic-gate * call: sn - socket number to drop 82617c478bd9Sstevel@tonic-gate * 82627c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - operation sucessful 82637c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET - unable to drop socket 82647c478bd9Sstevel@tonic-gate */ 82657c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 82667c478bd9Sstevel@tonic-gate static uint32_t 82677c478bd9Sstevel@tonic-gate cs_drop_socket(uint32_t sn) 82687c478bd9Sstevel@tonic-gate { 82697c478bd9Sstevel@tonic-gate #ifdef XXX 82707c478bd9Sstevel@tonic-gate cs_socket_t *sp; 82717c478bd9Sstevel@tonic-gate 82727c478bd9Sstevel@tonic-gate /* 82737c478bd9Sstevel@tonic-gate * Tell the socket event thread to exit and then wait for it 82747c478bd9Sstevel@tonic-gate * to do so. 82757c478bd9Sstevel@tonic-gate */ 82767c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 82777c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_THREAD_EXIT; 82787c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 82797c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 82807c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 82817c478bd9Sstevel@tonic-gate 82827c478bd9Sstevel@tonic-gate /* 82837c478bd9Sstevel@tonic-gate * Tell the socket SS thread to exit and then wait for it 82847c478bd9Sstevel@tonic-gate * to do so. 82857c478bd9Sstevel@tonic-gate */ 82867c478bd9Sstevel@tonic-gate 82877c478bd9Sstevel@tonic-gate /* 82887c478bd9Sstevel@tonic-gate * Mark the socket as dropped. 82897c478bd9Sstevel@tonic-gate */ 82907c478bd9Sstevel@tonic-gate sp->flags &= ~SOCKET_IS_VALID; 82917c478bd9Sstevel@tonic-gate 82927c478bd9Sstevel@tonic-gate #endif /* XXX */ 82937c478bd9Sstevel@tonic-gate 82947c478bd9Sstevel@tonic-gate /* XXX for now don't allow dropping sockets XXX */ 82957c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 82967c478bd9Sstevel@tonic-gate } 82977c478bd9Sstevel@tonic-gate 82987c478bd9Sstevel@tonic-gate /* 82997c478bd9Sstevel@tonic-gate * cs_get_socket - returns the socket and function numbers and a pointer 83007c478bd9Sstevel@tonic-gate * to the socket structure 83017c478bd9Sstevel@tonic-gate * 83027c478bd9Sstevel@tonic-gate * calling: client_handle_t client_handle - client handle to extract 83037c478bd9Sstevel@tonic-gate * socket number from 83047c478bd9Sstevel@tonic-gate * uint32_t *socket - pointer to socket number to use if 83057c478bd9Sstevel@tonic-gate * client_handle is for the SS client; 83067c478bd9Sstevel@tonic-gate * this value will be filled in on 83077c478bd9Sstevel@tonic-gate * return with the correct socket 83087c478bd9Sstevel@tonic-gate * and function numbers if we 83097c478bd9Sstevel@tonic-gate * return CS_SUCCESS 83107c478bd9Sstevel@tonic-gate * uint32_t *function - pointer to return function number into 83117c478bd9Sstevel@tonic-gate * if not NULL 83127c478bd9Sstevel@tonic-gate * cs_socket_t **sp - pointer to a pointer where a pointer 83137c478bd9Sstevel@tonic-gate * to the socket struct will be 83147c478bd9Sstevel@tonic-gate * placed if this is non-NULL 83157c478bd9Sstevel@tonic-gate * client_t **clp - pointer to a pointer where a pointer 83167c478bd9Sstevel@tonic-gate * to the client struct will be 83177c478bd9Sstevel@tonic-gate * placed if this is non-NULL 83187c478bd9Sstevel@tonic-gate * 83197c478bd9Sstevel@tonic-gate * The socket and function numbers are derived as follows: 83207c478bd9Sstevel@tonic-gate * 83217c478bd9Sstevel@tonic-gate * Client Type Socket Number Function Number 83227c478bd9Sstevel@tonic-gate * PC card client From client_handle From client_handle 83237c478bd9Sstevel@tonic-gate * Socket Services client From *socket From *socket 83247c478bd9Sstevel@tonic-gate * CSI client From client_handle From *socket 83257c478bd9Sstevel@tonic-gate */ 83267c478bd9Sstevel@tonic-gate static uint32_t 83277c478bd9Sstevel@tonic-gate cs_get_socket(client_handle_t client_handle, uint32_t *socket, 83287c478bd9Sstevel@tonic-gate uint32_t *function, cs_socket_t **csp, client_t **clp) 83297c478bd9Sstevel@tonic-gate { 83307c478bd9Sstevel@tonic-gate cs_socket_t *sp; 83317c478bd9Sstevel@tonic-gate client_t *client; 83327c478bd9Sstevel@tonic-gate uint32_t sn, fn; 83337c478bd9Sstevel@tonic-gate int ret; 83347c478bd9Sstevel@tonic-gate 83357c478bd9Sstevel@tonic-gate sn = *socket; 83367c478bd9Sstevel@tonic-gate 83377c478bd9Sstevel@tonic-gate /* 83387c478bd9Sstevel@tonic-gate * If this is the Socket Services client, then return the 83397c478bd9Sstevel@tonic-gate * socket and function numbers specified in the passed 83407c478bd9Sstevel@tonic-gate * socket number parameter, otherwise extract the socket 83417c478bd9Sstevel@tonic-gate * and function numbers from the client handle. 83427c478bd9Sstevel@tonic-gate */ 83437c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 83447c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(sn); 83457c478bd9Sstevel@tonic-gate sn = CS_GET_SOCKET_NUMBER(sn); 83467c478bd9Sstevel@tonic-gate } else { 83477c478bd9Sstevel@tonic-gate fn = GET_CLIENT_FUNCTION(client_handle); 83487c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(client_handle); 83497c478bd9Sstevel@tonic-gate } 83507c478bd9Sstevel@tonic-gate 83517c478bd9Sstevel@tonic-gate /* 83527c478bd9Sstevel@tonic-gate * Check to be sure that the socket number is in range 83537c478bd9Sstevel@tonic-gate */ 83547c478bd9Sstevel@tonic-gate if (!(CHECK_SOCKET_NUM(sn, cs_globals.max_socket_num))) 83557c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 83567c478bd9Sstevel@tonic-gate 83577c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 83587c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 83597c478bd9Sstevel@tonic-gate 83607c478bd9Sstevel@tonic-gate /* 83617c478bd9Sstevel@tonic-gate * If we were given a pointer, then fill it in with a pointer 83627c478bd9Sstevel@tonic-gate * to this socket. 83637c478bd9Sstevel@tonic-gate */ 83647c478bd9Sstevel@tonic-gate if (csp) 83657c478bd9Sstevel@tonic-gate *csp = sp; 83667c478bd9Sstevel@tonic-gate 83677c478bd9Sstevel@tonic-gate /* 83687c478bd9Sstevel@tonic-gate * Search for the client; if it's not found, return an error. 83697c478bd9Sstevel@tonic-gate */ 83707c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 83717c478bd9Sstevel@tonic-gate if (!(client = cs_find_client(client_handle, &ret))) { 83727c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 83737c478bd9Sstevel@tonic-gate return (ret); 83747c478bd9Sstevel@tonic-gate } 83757c478bd9Sstevel@tonic-gate 83767c478bd9Sstevel@tonic-gate /* 83777c478bd9Sstevel@tonic-gate * If we're a CIS client, then extract the function number 83787c478bd9Sstevel@tonic-gate * from the socket number. 83797c478bd9Sstevel@tonic-gate */ 83807c478bd9Sstevel@tonic-gate if (client->flags & CLIENT_CSI_CLIENT) 83817c478bd9Sstevel@tonic-gate fn = CS_GET_FUNCTION_NUMBER(*socket); 83827c478bd9Sstevel@tonic-gate 83837c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 83847c478bd9Sstevel@tonic-gate 83857c478bd9Sstevel@tonic-gate /* 83867c478bd9Sstevel@tonic-gate * Return the found client pointer if the caller wants it. 83877c478bd9Sstevel@tonic-gate */ 83887c478bd9Sstevel@tonic-gate if (clp) 83897c478bd9Sstevel@tonic-gate *clp = client; 83907c478bd9Sstevel@tonic-gate 83917c478bd9Sstevel@tonic-gate /* 83927c478bd9Sstevel@tonic-gate * Return a socket number that is made up of the socket number 83937c478bd9Sstevel@tonic-gate * and the function number. 83947c478bd9Sstevel@tonic-gate */ 83957c478bd9Sstevel@tonic-gate *socket = CS_MAKE_SOCKET_NUMBER(sn, fn); 83967c478bd9Sstevel@tonic-gate 83977c478bd9Sstevel@tonic-gate /* 83987c478bd9Sstevel@tonic-gate * Return the function number if the caller wants it. 83997c478bd9Sstevel@tonic-gate */ 84007c478bd9Sstevel@tonic-gate if (function) 84017c478bd9Sstevel@tonic-gate *function = fn; 84027c478bd9Sstevel@tonic-gate 84037c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 84047c478bd9Sstevel@tonic-gate } 84057c478bd9Sstevel@tonic-gate 84067c478bd9Sstevel@tonic-gate /* 84077c478bd9Sstevel@tonic-gate * cs_get_wp - returns pointer to passed window number 84087c478bd9Sstevel@tonic-gate * 84097c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 84107c478bd9Sstevel@tonic-gate * NULL - if invalid window number passed in 84117c478bd9Sstevel@tonic-gate */ 84127c478bd9Sstevel@tonic-gate static cs_window_t * 84137c478bd9Sstevel@tonic-gate cs_get_wp(uint32_t wn) 84147c478bd9Sstevel@tonic-gate { 84157c478bd9Sstevel@tonic-gate cs_window_t *cw; 84167c478bd9Sstevel@tonic-gate 84177c478bd9Sstevel@tonic-gate if (!(cs_globals.init_state & GLOBAL_INIT_STATE_SS_READY)) 84187c478bd9Sstevel@tonic-gate return (NULL); 84197c478bd9Sstevel@tonic-gate 84207c478bd9Sstevel@tonic-gate if ((cw = cs_find_wp(wn)) == NULL) 84217c478bd9Sstevel@tonic-gate return (NULL); 84227c478bd9Sstevel@tonic-gate 84237c478bd9Sstevel@tonic-gate if (cw->state & CW_WINDOW_VALID) 84247c478bd9Sstevel@tonic-gate return (cw); 84257c478bd9Sstevel@tonic-gate 84267c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 84277c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 84287c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_get_wp(): wn=%d cw=%p\n", 84297c478bd9Sstevel@tonic-gate (int)wn, (void *)cw); 84307c478bd9Sstevel@tonic-gate } 84317c478bd9Sstevel@tonic-gate #endif 84327c478bd9Sstevel@tonic-gate 84337c478bd9Sstevel@tonic-gate return (NULL); 84347c478bd9Sstevel@tonic-gate } 84357c478bd9Sstevel@tonic-gate 84367c478bd9Sstevel@tonic-gate /* 84377c478bd9Sstevel@tonic-gate * cs_find_wp - searches window list and returns pointer to passed window 84387c478bd9Sstevel@tonic-gate * number 84397c478bd9Sstevel@tonic-gate * 84407c478bd9Sstevel@tonic-gate * return: (cs_window_t *) - pointer to window structure 84417c478bd9Sstevel@tonic-gate * NULL - window not found 84427c478bd9Sstevel@tonic-gate */ 84437c478bd9Sstevel@tonic-gate static cs_window_t * 84447c478bd9Sstevel@tonic-gate cs_find_wp(uint32_t wn) 84457c478bd9Sstevel@tonic-gate { 84467c478bd9Sstevel@tonic-gate cs_window_t *cw = cs_globals.cw; 84477c478bd9Sstevel@tonic-gate 84487c478bd9Sstevel@tonic-gate while (cw) { 84497c478bd9Sstevel@tonic-gate if (cw->window_num == wn) 84507c478bd9Sstevel@tonic-gate return (cw); 84517c478bd9Sstevel@tonic-gate cw = cw->next; 84527c478bd9Sstevel@tonic-gate } /* while */ 84537c478bd9Sstevel@tonic-gate 84547c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 84557c478bd9Sstevel@tonic-gate if (cs_debug > 0) { 84567c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_find_wp(): wn=%d window_num=%d cw=%p\n", 84577c478bd9Sstevel@tonic-gate (int)wn, (int)cw->window_num, (void *)cw); 84587c478bd9Sstevel@tonic-gate } 84597c478bd9Sstevel@tonic-gate #endif 84607c478bd9Sstevel@tonic-gate 84617c478bd9Sstevel@tonic-gate return (NULL); 84627c478bd9Sstevel@tonic-gate } 84637c478bd9Sstevel@tonic-gate 84647c478bd9Sstevel@tonic-gate /* 84657c478bd9Sstevel@tonic-gate * cs_add_windows - adds number of windows specified in "aw" to 84667c478bd9Sstevel@tonic-gate * the global window list; start the window 84677c478bd9Sstevel@tonic-gate * numbering at "bn" 84687c478bd9Sstevel@tonic-gate * 84697c478bd9Sstevel@tonic-gate * return: CS_SUCCESS - if windows added sucessfully 84707c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW - if unable to add windows 84717c478bd9Sstevel@tonic-gate * 84727c478bd9Sstevel@tonic-gate * Note: The window list must be protected by a lock by the caller. 84737c478bd9Sstevel@tonic-gate */ 84747c478bd9Sstevel@tonic-gate static int 84757c478bd9Sstevel@tonic-gate cs_add_windows(int aw, uint32_t bn) 84767c478bd9Sstevel@tonic-gate { 84777c478bd9Sstevel@tonic-gate cs_window_t *cwp = cs_globals.cw; 84787c478bd9Sstevel@tonic-gate cs_window_t *cw, *cwpp; 84797c478bd9Sstevel@tonic-gate 84807c478bd9Sstevel@tonic-gate if (aw <= 0) 84817c478bd9Sstevel@tonic-gate return (CS_BAD_WINDOW); 84827c478bd9Sstevel@tonic-gate 84837c478bd9Sstevel@tonic-gate while (cwp) { 84847c478bd9Sstevel@tonic-gate cwpp = cwp; 84857c478bd9Sstevel@tonic-gate cwp = cwp->next; 84867c478bd9Sstevel@tonic-gate } 84877c478bd9Sstevel@tonic-gate 84887c478bd9Sstevel@tonic-gate while (aw--) { 84897c478bd9Sstevel@tonic-gate cw = (cs_window_t *)kmem_zalloc(sizeof (cs_window_t), KM_SLEEP); 84907c478bd9Sstevel@tonic-gate 84917c478bd9Sstevel@tonic-gate if (cs_globals.cw == NULL) { 84927c478bd9Sstevel@tonic-gate cs_globals.cw = cw; 84937c478bd9Sstevel@tonic-gate cwpp = cs_globals.cw; 84947c478bd9Sstevel@tonic-gate } else { 84957c478bd9Sstevel@tonic-gate cwpp->next = cw; 84967c478bd9Sstevel@tonic-gate cwpp = cwpp->next; 84977c478bd9Sstevel@tonic-gate } 84987c478bd9Sstevel@tonic-gate 84997c478bd9Sstevel@tonic-gate cwpp->window_num = bn++; 85007c478bd9Sstevel@tonic-gate cwpp->state = CW_WINDOW_VALID; 85017c478bd9Sstevel@tonic-gate 85027c478bd9Sstevel@tonic-gate } /* while (aw) */ 85037c478bd9Sstevel@tonic-gate 85047c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 85057c478bd9Sstevel@tonic-gate } 85067c478bd9Sstevel@tonic-gate 85077c478bd9Sstevel@tonic-gate /* 85087c478bd9Sstevel@tonic-gate * cs_ss_init - initialize CS items that need to wait until we receive 85097c478bd9Sstevel@tonic-gate * a PCE_SS_INIT_STATE/PCE_SS_STATE_INIT event 85107c478bd9Sstevel@tonic-gate * 85117c478bd9Sstevel@tonic-gate * return: CS_SUCESS - if sucessfully initialized 85127c478bd9Sstevel@tonic-gate * (various) if error initializing 85137c478bd9Sstevel@tonic-gate * 85147c478bd9Sstevel@tonic-gate * At this point, we expect that Socket Services has setup the 85157c478bd9Sstevel@tonic-gate * following global variables for us: 85167c478bd9Sstevel@tonic-gate * 85177c478bd9Sstevel@tonic-gate * cs_socket_services - Socket Services entry point 85187c478bd9Sstevel@tonic-gate * cis_parser - CIS parser entry point 85197c478bd9Sstevel@tonic-gate */ 85207c478bd9Sstevel@tonic-gate static uint32_t 85217c478bd9Sstevel@tonic-gate cs_ss_init() 85227c478bd9Sstevel@tonic-gate { 85237c478bd9Sstevel@tonic-gate cs_register_cardservices_t rcs; 85247c478bd9Sstevel@tonic-gate csregister_t csr; 85257c478bd9Sstevel@tonic-gate uint32_t ret; 85267c478bd9Sstevel@tonic-gate 85277c478bd9Sstevel@tonic-gate /* 85287c478bd9Sstevel@tonic-gate * Fill out the parameters for CISP_CIS_SETUP 85297c478bd9Sstevel@tonic-gate */ 85307c478bd9Sstevel@tonic-gate csr.cs_magic = PCCS_MAGIC; 85317c478bd9Sstevel@tonic-gate csr.cs_version = PCCS_VERSION; 85327c478bd9Sstevel@tonic-gate csr.cs_card_services = CardServices; 85337c478bd9Sstevel@tonic-gate csr.cs_event = NULL; 85347c478bd9Sstevel@tonic-gate 85357c478bd9Sstevel@tonic-gate /* 85367c478bd9Sstevel@tonic-gate * Call into the CIS module and tell it what the private 85377c478bd9Sstevel@tonic-gate * Card Services entry point is. The CIS module will 85387c478bd9Sstevel@tonic-gate * call us back at CardServices(CISRegister, ...) 85397c478bd9Sstevel@tonic-gate * with the address of various CIS-specific global 85407c478bd9Sstevel@tonic-gate * data structures. 85417c478bd9Sstevel@tonic-gate */ 85427c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_SETUP, &csr); 85437c478bd9Sstevel@tonic-gate 85447c478bd9Sstevel@tonic-gate /* 85457c478bd9Sstevel@tonic-gate * Register with the Card Services kernel stubs module 85467c478bd9Sstevel@tonic-gate */ 85477c478bd9Sstevel@tonic-gate rcs.magic = CS_STUBS_MAGIC; 85487c478bd9Sstevel@tonic-gate rcs.function = CS_ENTRY_REGISTER; 85497c478bd9Sstevel@tonic-gate rcs.cardservices = CardServices; 85507c478bd9Sstevel@tonic-gate 85517c478bd9Sstevel@tonic-gate if ((ret = csx_register_cardservices(&rcs)) != CS_SUCCESS) { 85527c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_ss_init: can't register with " 85537c478bd9Sstevel@tonic-gate "cs_stubs, retcode = 0x%x\n", ret); 85547c478bd9Sstevel@tonic-gate return (ret); 85557c478bd9Sstevel@tonic-gate } /* csx_register_cardservices */ 85567c478bd9Sstevel@tonic-gate 85577c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 85587c478bd9Sstevel@tonic-gate } 85597c478bd9Sstevel@tonic-gate 85607c478bd9Sstevel@tonic-gate /* 85617c478bd9Sstevel@tonic-gate * cs_create_cis - reads CIS on card in socket and creates CIS lists 85627c478bd9Sstevel@tonic-gate * 85637c478bd9Sstevel@tonic-gate * Most of the work is done in the CIS module in the CISP_CIS_LIST_CREATE 85647c478bd9Sstevel@tonic-gate * function. 85657c478bd9Sstevel@tonic-gate * 85667c478bd9Sstevel@tonic-gate * This function returns: 85677c478bd9Sstevel@tonic-gate * 85687c478bd9Sstevel@tonic-gate * CS_SUCCESS - if the CIS lists were created sucessfully 85697c478bd9Sstevel@tonic-gate * CS_BAD_WINDOW or CS_GENERAL_FAILURE - if CIS window could 85707c478bd9Sstevel@tonic-gate * not be setup 85717c478bd9Sstevel@tonic-gate * CS_BAD_CIS - if error creating CIS chains 85727c478bd9Sstevel@tonic-gate * CS_BAD_OFFSET - if the CIS parser tried to read past the 85737c478bd9Sstevel@tonic-gate * boundries of the allocated CIS window 85747c478bd9Sstevel@tonic-gate */ 85757c478bd9Sstevel@tonic-gate static int 85767c478bd9Sstevel@tonic-gate cs_create_cis(cs_socket_t *sp) 85777c478bd9Sstevel@tonic-gate { 85787c478bd9Sstevel@tonic-gate uint32_t ret; 85797c478bd9Sstevel@tonic-gate 85807c478bd9Sstevel@tonic-gate ret = (uint32_t)(uintptr_t)CIS_PARSER(CISP_CIS_LIST_CREATE, 85817c478bd9Sstevel@tonic-gate cis_cistpl_std_callout, sp); 85827c478bd9Sstevel@tonic-gate 85837c478bd9Sstevel@tonic-gate #ifdef CS_DEBUG 85847c478bd9Sstevel@tonic-gate if (ret == CS_NO_CIS) { 85857c478bd9Sstevel@tonic-gate if (cs_debug > 0) 85867c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d has no CIS\n", 85877c478bd9Sstevel@tonic-gate sp->socket_num); 85887c478bd9Sstevel@tonic-gate } else if (ret != CS_SUCCESS) { 85897c478bd9Sstevel@tonic-gate if (cs_debug > 0) 85907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cs_create_cis: socket %d ERROR = 0x%x\n", 85917c478bd9Sstevel@tonic-gate sp->socket_num, ret); 85927c478bd9Sstevel@tonic-gate return (ret); 85937c478bd9Sstevel@tonic-gate } 85947c478bd9Sstevel@tonic-gate #else 85957c478bd9Sstevel@tonic-gate if (ret != CS_NO_CIS) 85967c478bd9Sstevel@tonic-gate if (ret != CS_SUCCESS) 85977c478bd9Sstevel@tonic-gate return (ret); 85987c478bd9Sstevel@tonic-gate #endif 85997c478bd9Sstevel@tonic-gate 86007c478bd9Sstevel@tonic-gate /* 86017c478bd9Sstevel@tonic-gate * If this card didn't have any CIS at all, there's not much 86027c478bd9Sstevel@tonic-gate * else for us to do. 86037c478bd9Sstevel@tonic-gate */ 86047c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_VALID_CIS)) 86057c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86067c478bd9Sstevel@tonic-gate 86077c478bd9Sstevel@tonic-gate /* 86087c478bd9Sstevel@tonic-gate * If this is a single-function card, we need to move the CIS list 86097c478bd9Sstevel@tonic-gate * that is currently on CS_GLOBAL_CIS to the function zero 86107c478bd9Sstevel@tonic-gate * CIS list. 86117c478bd9Sstevel@tonic-gate */ 86127c478bd9Sstevel@tonic-gate if (!(sp->cis_flags & CW_MULTI_FUNCTION_CIS)) { 86137c478bd9Sstevel@tonic-gate bcopy((caddr_t)&sp->cis[CS_GLOBAL_CIS], 86147c478bd9Sstevel@tonic-gate (caddr_t)&sp->cis[0], sizeof (cis_info_t)); 86157c478bd9Sstevel@tonic-gate bzero((caddr_t)&sp->cis[CS_GLOBAL_CIS], sizeof (cis_info_t)); 86167c478bd9Sstevel@tonic-gate } /* !CW_MULTI_FUNCTION_CIS */ 86177c478bd9Sstevel@tonic-gate 86187c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86197c478bd9Sstevel@tonic-gate } 86207c478bd9Sstevel@tonic-gate 86217c478bd9Sstevel@tonic-gate /* 86227c478bd9Sstevel@tonic-gate * cs_destroy_cis - destroys CIS list for socket 86237c478bd9Sstevel@tonic-gate */ 86247c478bd9Sstevel@tonic-gate static int 86257c478bd9Sstevel@tonic-gate cs_destroy_cis(cs_socket_t *sp) 86267c478bd9Sstevel@tonic-gate { 86277c478bd9Sstevel@tonic-gate CIS_PARSER(CISP_CIS_LIST_DESTROY, sp); 86287c478bd9Sstevel@tonic-gate 86297c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86307c478bd9Sstevel@tonic-gate } 86317c478bd9Sstevel@tonic-gate 86327c478bd9Sstevel@tonic-gate /* 86337c478bd9Sstevel@tonic-gate * cs_get_client_info - This function is GetClientInfo. 86347c478bd9Sstevel@tonic-gate * 86357c478bd9Sstevel@tonic-gate * calling: client_handle_t - client handle to get client info on 86367c478bd9Sstevel@tonic-gate * client_info_t * - pointer to a client_info_t structure 86377c478bd9Sstevel@tonic-gate * to return client information in 86387c478bd9Sstevel@tonic-gate * 86397c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 86407c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 86417c478bd9Sstevel@tonic-gate * handle passed in 86427c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 86437c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 86447c478bd9Sstevel@tonic-gate * or if invalid client info 86457c478bd9Sstevel@tonic-gate * retreived from client 86467c478bd9Sstevel@tonic-gate */ 86477c478bd9Sstevel@tonic-gate static int 86487c478bd9Sstevel@tonic-gate cs_get_client_info(client_handle_t client_handle, client_info_t *ci) 86497c478bd9Sstevel@tonic-gate { 86507c478bd9Sstevel@tonic-gate cs_socket_t *sp; 86517c478bd9Sstevel@tonic-gate client_t *client; 86527c478bd9Sstevel@tonic-gate client_info_t *cinfo; 86537c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 86547c478bd9Sstevel@tonic-gate 86557c478bd9Sstevel@tonic-gate if (CLIENT_HANDLE_IS_SS(client_handle)) { 86567c478bd9Sstevel@tonic-gate ci->Attributes = (CS_CLIENT_INFO_SOCKET_SERVICES | 86577c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_VALID); 86587c478bd9Sstevel@tonic-gate return (CS_SUCCESS); 86597c478bd9Sstevel@tonic-gate } /* CLIENT_HANDLE_IS_SS */ 86607c478bd9Sstevel@tonic-gate 86617c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(GET_CLIENT_SOCKET(client_handle))) == NULL) 86627c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 86637c478bd9Sstevel@tonic-gate 86647c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 86657c478bd9Sstevel@tonic-gate mutex_enter(&sp->lock); 86667c478bd9Sstevel@tonic-gate 86677c478bd9Sstevel@tonic-gate if ((client = cs_find_client(client_handle, &ret)) == NULL) { 86687c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86697c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 86707c478bd9Sstevel@tonic-gate return (ret); 86717c478bd9Sstevel@tonic-gate } /* cs_find_client */ 86727c478bd9Sstevel@tonic-gate 86737c478bd9Sstevel@tonic-gate /* 86747c478bd9Sstevel@tonic-gate * If this client is not handling CS_EVENT_CLIENT_INFO events, 86757c478bd9Sstevel@tonic-gate * then don't bother to even wake up the event thread. 86767c478bd9Sstevel@tonic-gate */ 86777c478bd9Sstevel@tonic-gate if (!((client->event_mask | client->global_mask) & 86787c478bd9Sstevel@tonic-gate CS_EVENT_CLIENT_INFO)) { 86797c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86807c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 86817c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 86827c478bd9Sstevel@tonic-gate } /* !CS_EVENT_CLIENT_INFO */ 86837c478bd9Sstevel@tonic-gate 86847c478bd9Sstevel@tonic-gate cinfo = &client->event_callback_args.client_info; 86857c478bd9Sstevel@tonic-gate 86867c478bd9Sstevel@tonic-gate bzero((caddr_t)cinfo, sizeof (client_info_t)); 86877c478bd9Sstevel@tonic-gate cinfo->Attributes = (ci->Attributes & CS_CLIENT_INFO_SUBSVC_MASK); 86887c478bd9Sstevel@tonic-gate 86897c478bd9Sstevel@tonic-gate client->events |= CS_EVENT_CLIENT_INFO; 86907c478bd9Sstevel@tonic-gate 86917c478bd9Sstevel@tonic-gate sp->thread_state |= SOCKET_WAIT_SYNC; 86927c478bd9Sstevel@tonic-gate mutex_exit(&sp->lock); 86937c478bd9Sstevel@tonic-gate cv_broadcast(&sp->thread_cv); 86947c478bd9Sstevel@tonic-gate cv_wait(&sp->caller_cv, &sp->client_lock); 86957c478bd9Sstevel@tonic-gate 86967c478bd9Sstevel@tonic-gate if (cinfo->Attributes & CS_CLIENT_INFO_VALID) { 86977c478bd9Sstevel@tonic-gate bcopy((caddr_t)cinfo, (caddr_t)ci, sizeof (client_info_t)); 86987c478bd9Sstevel@tonic-gate ci->Attributes &= (CS_CLIENT_INFO_FLAGS_MASK | 86997c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_SUBSVC_MASK); 87007c478bd9Sstevel@tonic-gate ci->Attributes &= ~(CS_CLIENT_INFO_CLIENT_MASK | 87017c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK | 87027c478bd9Sstevel@tonic-gate CS_CLIENT_INFO_CLIENT_ACTIVE); 87037c478bd9Sstevel@tonic-gate ci->Attributes |= (client->flags & (CS_CLIENT_INFO_CLIENT_MASK | 87047c478bd9Sstevel@tonic-gate INFO_CARD_FLAGS_MASK)); 87057c478bd9Sstevel@tonic-gate (void) strcpy(ci->DriverName, client->driver_name); 87067c478bd9Sstevel@tonic-gate if (cs_card_for_client(client)) 87077c478bd9Sstevel@tonic-gate ci->Attributes |= CS_CLIENT_INFO_CLIENT_ACTIVE; 87087c478bd9Sstevel@tonic-gate } else { 87097c478bd9Sstevel@tonic-gate ret = CS_NO_MORE_ITEMS; 87107c478bd9Sstevel@tonic-gate } /* CS_CLIENT_INFO_VALID */ 87117c478bd9Sstevel@tonic-gate 87127c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87137c478bd9Sstevel@tonic-gate 87147c478bd9Sstevel@tonic-gate return (ret); 87157c478bd9Sstevel@tonic-gate } 87167c478bd9Sstevel@tonic-gate 87177c478bd9Sstevel@tonic-gate /* 87187c478bd9Sstevel@tonic-gate * cs_get_firstnext_client - This function is GetFirstClient and 87197c478bd9Sstevel@tonic-gate * GetNextClient 87207c478bd9Sstevel@tonic-gate * 87217c478bd9Sstevel@tonic-gate * calling: get_firstnext_client_t * - pointer to a get_firstnext_client_t 87227c478bd9Sstevel@tonic-gate * structure to return client handle and 87237c478bd9Sstevel@tonic-gate * attributes in 87247c478bd9Sstevel@tonic-gate * flags - one of the following: 87257c478bd9Sstevel@tonic-gate * CS_GET_FIRST_FLAG - get first client handle 87267c478bd9Sstevel@tonic-gate * CS_GET_NEXT_FLAG - get next client handle 87277c478bd9Sstevel@tonic-gate * 87287c478bd9Sstevel@tonic-gate * returns: CS_SUCCESS - if client info retreived from client 87297c478bd9Sstevel@tonic-gate * CS_BAD_SOCKET, CS_BAD_HANDLE - if invalid client 87307c478bd9Sstevel@tonic-gate * handle passed in 87317c478bd9Sstevel@tonic-gate * CS_NO_MORE_ITEMS - if client does not handle the 87327c478bd9Sstevel@tonic-gate * CS_EVENT_CLIENT_INFO event 87337c478bd9Sstevel@tonic-gate * or if invalid client info 87347c478bd9Sstevel@tonic-gate * retreived from client 87357c478bd9Sstevel@tonic-gate */ 87367c478bd9Sstevel@tonic-gate static int 87377c478bd9Sstevel@tonic-gate cs_get_firstnext_client(get_firstnext_client_t *fnc, uint32_t flags) 87387c478bd9Sstevel@tonic-gate { 87397c478bd9Sstevel@tonic-gate cs_socket_t *sp; 87407c478bd9Sstevel@tonic-gate client_t *client; 87417c478bd9Sstevel@tonic-gate uint32_t sn = 0; 87427c478bd9Sstevel@tonic-gate int ret = CS_SUCCESS; 87437c478bd9Sstevel@tonic-gate 87447c478bd9Sstevel@tonic-gate switch (flags) { 87457c478bd9Sstevel@tonic-gate case CS_GET_FIRST_FLAG: 87467c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 87477c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 87487c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 87497c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87507c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 87517c478bd9Sstevel@tonic-gate break; 87527c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87537c478bd9Sstevel@tonic-gate } /* if */ 87547c478bd9Sstevel@tonic-gate sn++; 87557c478bd9Sstevel@tonic-gate } /* while */ 87567c478bd9Sstevel@tonic-gate 87577c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 87587c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 87597c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 87607c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 87617c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(CS_GET_SOCKET_NUMBER(fnc->Socket))) == 87627c478bd9Sstevel@tonic-gate NULL) 87637c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 87647c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87657c478bd9Sstevel@tonic-gate if ((client = sp->client_list) == NULL) { 87667c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87677c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 87687c478bd9Sstevel@tonic-gate } 87697c478bd9Sstevel@tonic-gate } else { 87707c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 87717c478bd9Sstevel@tonic-gate } 87727c478bd9Sstevel@tonic-gate 87737c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 87747c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 87757c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87767c478bd9Sstevel@tonic-gate break; 87777c478bd9Sstevel@tonic-gate case CS_GET_NEXT_FLAG: 87787c478bd9Sstevel@tonic-gate if (fnc->Attributes & CS_GET_FIRSTNEXT_CLIENT_ALL_CLIENTS) { 87797c478bd9Sstevel@tonic-gate sn = GET_CLIENT_SOCKET(fnc->client_handle); 87807c478bd9Sstevel@tonic-gate 87817c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) == NULL) 87827c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 87837c478bd9Sstevel@tonic-gate 87847c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87857c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 87867c478bd9Sstevel@tonic-gate &ret)) == NULL) { 87877c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87887c478bd9Sstevel@tonic-gate return (ret); 87897c478bd9Sstevel@tonic-gate } 87907c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 87917c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87927c478bd9Sstevel@tonic-gate sn++; 87937c478bd9Sstevel@tonic-gate while (sn < cs_globals.max_socket_num) { 87947c478bd9Sstevel@tonic-gate if ((sp = cs_get_sp(sn)) != NULL) { 87957c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 87967c478bd9Sstevel@tonic-gate if ((client = sp->client_list) != NULL) 87977c478bd9Sstevel@tonic-gate break; 87987c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 87997c478bd9Sstevel@tonic-gate } /* if */ 88007c478bd9Sstevel@tonic-gate sn++; 88017c478bd9Sstevel@tonic-gate } /* while */ 88027c478bd9Sstevel@tonic-gate 88037c478bd9Sstevel@tonic-gate if (sn == cs_globals.max_socket_num) 88047c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 88057c478bd9Sstevel@tonic-gate } /* client = client->next */ 88067c478bd9Sstevel@tonic-gate 88077c478bd9Sstevel@tonic-gate } else if (fnc->Attributes & 88087c478bd9Sstevel@tonic-gate CS_GET_FIRSTNEXT_CLIENT_SOCKET_ONLY) { 88097c478bd9Sstevel@tonic-gate sp = cs_get_sp(GET_CLIENT_SOCKET(fnc->client_handle)); 88107c478bd9Sstevel@tonic-gate if (sp == NULL) 88117c478bd9Sstevel@tonic-gate return (CS_BAD_SOCKET); 88127c478bd9Sstevel@tonic-gate mutex_enter(&sp->client_lock); 88137c478bd9Sstevel@tonic-gate if ((client = cs_find_client(fnc->client_handle, 88147c478bd9Sstevel@tonic-gate &ret)) == NULL) { 88157c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88167c478bd9Sstevel@tonic-gate return (ret); 88177c478bd9Sstevel@tonic-gate } 88187c478bd9Sstevel@tonic-gate if ((client = client->next) == NULL) { 88197c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88207c478bd9Sstevel@tonic-gate return (CS_NO_MORE_ITEMS); 88217c478bd9Sstevel@tonic-gate } 88227c478bd9Sstevel@tonic-gate } else { 88237c478bd9Sstevel@tonic-gate return (CS_BAD_ATTRIBUTE); 88247c478bd9Sstevel@tonic-gate } 88257c478bd9Sstevel@tonic-gate 88267c478bd9Sstevel@tonic-gate fnc->client_handle = client->client_handle; 88277c478bd9Sstevel@tonic-gate fnc->num_clients = sp->num_clients; 88287c478bd9Sstevel@tonic-gate mutex_exit(&sp->client_lock); 88297c478bd9Sstevel@tonic-gate break; 88307c478bd9Sstevel@tonic-gate default: 88317c478bd9Sstevel@tonic-gate ret = CS_BAD_ATTRIBUTE; 88327c478bd9Sstevel@tonic-gate break; 88337c478bd9Sstevel@tonic-gate 88347c478bd9Sstevel@tonic-gate } /* switch */ 88357c478bd9Sstevel@tonic-gate 88367c478bd9Sstevel@tonic-gate return (ret); 88377c478bd9Sstevel@tonic-gate } 88387c478bd9Sstevel@tonic-gate 88397c478bd9Sstevel@tonic-gate /* 88407c478bd9Sstevel@tonic-gate * cs_set_acc_attributes - converts Card Services endianness and 88417c478bd9Sstevel@tonic-gate * data ordering values to values 88427c478bd9Sstevel@tonic-gate * that Socket Services understands 88437c478bd9Sstevel@tonic-gate * 88447c478bd9Sstevel@tonic-gate * calling: *sw - pointer to a set_window_t to set attributes in 88457c478bd9Sstevel@tonic-gate * Attributes - CS attributes 88467c478bd9Sstevel@tonic-gate */ 88477c478bd9Sstevel@tonic-gate static void 88487c478bd9Sstevel@tonic-gate cs_set_acc_attributes(set_window_t *sw, uint32_t Attributes) 88497c478bd9Sstevel@tonic-gate { 88507c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 88517c478bd9Sstevel@tonic-gate 88527c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ENDIAN_MASK) { 88537c478bd9Sstevel@tonic-gate case WIN_ACC_LITTLE_ENDIAN: 88547c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 88557c478bd9Sstevel@tonic-gate break; 88567c478bd9Sstevel@tonic-gate case WIN_ACC_BIG_ENDIAN: 88577c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC; 88587c478bd9Sstevel@tonic-gate break; 88597c478bd9Sstevel@tonic-gate case WIN_ACC_NEVER_SWAP: 88607c478bd9Sstevel@tonic-gate default: 88617c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 88627c478bd9Sstevel@tonic-gate break; 88637c478bd9Sstevel@tonic-gate } /* switch */ 88647c478bd9Sstevel@tonic-gate 88657c478bd9Sstevel@tonic-gate switch (Attributes & WIN_ACC_ORDER_MASK) { 88667c478bd9Sstevel@tonic-gate case WIN_ACC_UNORDERED_OK: 88677c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC; 88687c478bd9Sstevel@tonic-gate break; 88697c478bd9Sstevel@tonic-gate case WIN_ACC_MERGING_OK: 88707c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_MERGING_OK_ACC; 88717c478bd9Sstevel@tonic-gate break; 88727c478bd9Sstevel@tonic-gate case WIN_ACC_LOADCACHING_OK: 88737c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_LOADCACHING_OK_ACC; 88747c478bd9Sstevel@tonic-gate break; 88757c478bd9Sstevel@tonic-gate case WIN_ACC_STORECACHING_OK: 88767c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STORECACHING_OK_ACC; 88777c478bd9Sstevel@tonic-gate break; 88787c478bd9Sstevel@tonic-gate case WIN_ACC_STRICT_ORDER: 88797c478bd9Sstevel@tonic-gate default: 88807c478bd9Sstevel@tonic-gate sw->attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 88817c478bd9Sstevel@tonic-gate break; 88827c478bd9Sstevel@tonic-gate } /* switch */ 88837c478bd9Sstevel@tonic-gate } 8884