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