xref: /illumos-gate/usr/src/uts/common/pcmcia/cs/cs.c (revision c48c3045)
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