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