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