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