xref: /titanic_41/usr/src/uts/common/pcmcia/nexus/pcmcia.c (revision 3125ebfc35130d243e775dc38a6a59be4df0b137)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * PCMCIA NEXUS
30  *	The PCMCIA module is a generalized interface for
31  *	implementing PCMCIA nexus drivers.  It preserves
32  *	the logical socket name space while allowing multiple
33  *	instances of the hardware to be properly represented
34  *	in the device tree.
35  *
36  *	The nexus also exports events to an event manager
37  *	driver if it has registered.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/systm.h>
42 #include <sys/user.h>
43 #include <sys/buf.h>
44 #include <sys/file.h>
45 #include <sys/uio.h>
46 #include <sys/conf.h>
47 #include <sys/stat.h>
48 #include <sys/autoconf.h>
49 #include <sys/vtoc.h>
50 #include <sys/dkio.h>
51 #include <sys/ddi.h>
52 #include <sys/debug.h>
53 #include <sys/sunddi.h>
54 #include <sys/sunndi.h>
55 #include <sys/cred.h>
56 #include <sys/kstat.h>
57 #include <sys/kmem.h>
58 #include <sys/modctl.h>
59 #include <sys/kobj.h>
60 #include <sys/callb.h>
61 #include <sys/param.h>
62 #include <sys/thread.h>
63 #include <sys/proc.h>
64 
65 #include <sys/pctypes.h>
66 #include <sys/pcmcia.h>
67 #include <sys/sservice.h>
68 #include <pcmcia/sys/cs_types.h>
69 #include <pcmcia/sys/cis.h>
70 #include <pcmcia/sys/cis_handlers.h>
71 #include <pcmcia/sys/cs.h>
72 #include <pcmcia/sys/cs_priv.h>
73 
74 #ifdef sparc
75 #include <sys/ddi_subrdefs.h>
76 
77 #elif defined(__x86) || defined(__amd64)
78 #include <sys/mach_intr.h>
79 #endif
80 
81 #undef SocketServices
82 
83 /* some bus specific stuff */
84 
85 /* need PCI regspec size for worst case at present */
86 #include <sys/pci.h>
87 
88 typedef struct pcmcia_logical_socket {
89 	int			ls_socket; /* adapter's socket number */
90 	uint32_t		ls_flags;
91 	struct pcmcia_adapter	*ls_adapter;
92 	pcmcia_if_t		*ls_if;
93 	dev_info_t		*ls_sockdrv;
94 	dev_info_t		*ls_dip[PCMCIA_MAX_FUNCTIONS];
95 	dev_info_t		*ls_mfintr_dip;
96 	int			ls_functions;
97 	uint32_t		ls_cs_events;
98 	uint32_t		ls_intr_pri;
99 	uint32_t		ls_intr_vec;
100 	int			ls_intrrefs;
101 	struct intrspec		ls_intrspec; /* MFC intrspec */
102 	inthandler_t		*ls_inthandlers; /* for multifunction cards */
103 	ddi_iblock_cookie_t	ls_iblk;
104 	ddi_idevice_cookie_t	ls_idev;
105 	kmutex_t		ls_ilock;
106 	int			ls_error; /* error for CS return */
107 } pcmcia_logical_socket_t;
108 
109 /*
110  * entry points used by the true nexus
111  */
112 int pcmcia_detach(dev_info_t *, ddi_detach_cmd_t);
113 int pcmcia_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
114 int pcmcia_prop_op(dev_t, dev_info_t *, dev_info_t *, ddi_prop_op_t,
115 			int, char *, caddr_t, int *);
116 void pcmcia_set_assigned(dev_info_t *, int, ra_return_t *);
117 int pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
118     ddi_intr_handle_impl_t *hdlp, void *result);
119 
120 /*
121  * prototypes used internally by the nexus and sometimes Card Services
122  */
123 int SocketServices(int function, ...);
124 
125 
126 void *CISParser(int function, ...);
127 extern void *(*cis_parser)(int, ...);
128 
129 struct regspec *pcmcia_cons_regspec(dev_info_t *, int, uchar_t *,
130 					ra_return_t *);
131 
132 static int (*pcmcia_card_services)(int, ...) = NULL;
133 
134 /*
135  * variables used in the logical/physical mappings
136  * that the nexus common code maintains.
137  */
138 struct pcmcia_adapter *pcmcia_adapters[PCMCIA_MAX_ADAPTERS];
139 int    pcmcia_num_adapters;
140 pcmcia_logical_socket_t *pcmcia_sockets[PCMCIA_MAX_SOCKETS];
141 int    pcmcia_num_sockets;
142 pcmcia_logical_window_t *pcmcia_windows[PCMCIA_MAX_WINDOWS];
143 int    pcmcia_num_windows;
144 struct power_entry pcmcia_power_table[PCMCIA_MAX_POWER];
145 int	pcmcia_num_power;
146 
147 struct pcmcia_mif *pcmcia_mif_handlers = NULL;
148 pcm_dev_node_t *pcmcia_devnodes = NULL;
149 
150 kmutex_t pcmcia_global_lock;
151 kcondvar_t pcmcia_condvar;
152 kmutex_t pcmcia_enum_lock;
153 
154 /*
155  * Mapping of the device "type" to names acceptable to
156  * the DDI
157  */
158 static char *pcmcia_dev_type[] = {
159 	"multifunction",
160 	"byte",
161 	"serial",
162 	"parallel",
163 	"block",
164 	"display",
165 	"network",
166 	"block",
167 	"byte"
168 };
169 
170 char *pcmcia_default_pm_mode = "parental-suspend-resume";
171 
172 /*
173  * generic names from the approved list:
174  *	disk tape pci sbus scsi token-ring isa keyboard display mouse
175  *	audio ethernet timer memory parallel serial rtc nvram scanner
176  *	floppy(controller) fddi isdn atm ide pccard video-in video-out
177  * in some cases there will need to be device class dependent names.
178  * network -> ethernet, token-ring, etc.
179  * this list is a first guess and is used when all else fails.
180  */
181 
182 char *pcmcia_generic_names[] = {
183 	"multifunction",
184 	"memory",
185 	"serial",
186 	"parallel",
187 	"disk",
188 	"video",		/* no spec for video-out yet */
189 	"network",
190 	"aims",
191 	"scsi",
192 	"security"
193 };
194 
195 #define	PCM_GENNAME_SIZE	(sizeof (pcmcia_generic_names) / \
196 					sizeof (char *))
197 #define	PCMCIA_MAP_IO	0x0
198 #define	PCMCIA_MAP_MEM	0x1
199 
200 /*
201  * The following should be 2^^n - 1
202  */
203 #define	PCMCIA_SOCKET_BITS	0x7f
204 
205 #ifdef PCMCIA_DEBUG
206 int pcmcia_debug = 0x0;
207 static void pcmcia_dump_minors(dev_info_t *);
208 #endif
209 
210 static f_tt *pcmcia_cs_event = NULL;
211 int pcmcia_timer_id;
212 dev_info_t	*pcmcia_dip;
213 /*
214  * XXX - See comments in cs.c
215  */
216 static f_tt *pcmcia_cis_parser = NULL;
217 
218 extern struct pc_socket_services pc_socket_services;
219 
220 /* some function declarations */
221 static int pcm_adapter_callback(dev_info_t *, int, int, int);
222 extern void pcmcia_init_adapter(anp_t *, dev_info_t *);
223 extern void pcmcia_find_cards(anp_t *);
224 extern void pcmcia_merge_power(struct power_entry *);
225 extern void pcmcia_do_resume(int, pcmcia_logical_socket_t *);
226 extern void pcmcia_resume(int, pcmcia_logical_socket_t *);
227 extern void pcmcia_do_suspend(int, pcmcia_logical_socket_t *);
228 extern void pcm_event_manager(int, int, void *);
229 static void pcmcia_create_dev_info(int);
230 static int pcmcia_create_device(ss_make_device_node_t *);
231 static void pcmcia_init_devinfo(dev_info_t *, struct pcm_device_info *);
232 void pcmcia_fix_string(char *str);
233 dev_info_t *pcmcia_number_socket(dev_info_t *, int);
234 static int pcmcia_merge_conf(dev_info_t *);
235 static uint32_t pcmcia_mfc_intr(caddr_t, caddr_t);
236 void pcmcia_free_resources(dev_info_t *);
237 static void pcmcia_ppd_free(struct pcmcia_parent_private *ppd);
238 int pcmcia_get_intr(dev_info_t *, int);
239 int pcmcia_return_intr(dev_info_t *, int);
240 int pcmcia_ra_alloc(dev_info_t *, ndi_ra_request_t *, ra_return_t *, char *);
241 int pcmcia_ra_free(dev_info_t *, ra_return_t *, char *);
242 
243 extern int cs_init(void);
244 extern int cs_deinit(void);
245 extern void cisp_init(void);
246 extern void cis_deinit(void);
247 
248 /*
249  * non-DDI compliant functions are listed here
250  * some will be declared while others that have
251  * entries in .h files. All will be commented on.
252  *
253  * with declarations:
254  *	ddi_add_child
255  *	ddi_binding_name
256  *	ddi_bus_prop_op
257  *	ddi_ctlops
258  *	ddi_find_devinfo
259  *	ddi_get_name_addr
260  *	ddi_get_parent_data
261  *	ddi_hold_installed_driver
262  *	ddi_name_to_major
263  *	ddi_node_name
264  *	ddi_pathname
265  *	ddi_rele_driver
266  *	ddi_set_name_addr
267  *	ddi_set_parent_data
268  *	ddi_unorphan_devs
269  *	i_ddi_bind_node_to_driver
270  *	i_ddi_bind_node_to_driver
271  *	i_ddi_bus_map
272  *	i_ddi_map_fault
273  *	i_ddi_mem_alloc
274  *	i_ddi_mem_alloc
275  *	i_ddi_mem_free
276  *	i_ddi_mem_free
277  *	modload
278  *	modunload
279  */
280 
281 extern void ddi_unorphan_devs(major_t);
282 
283 /* Card&Socket Services entry points */
284 static int GetCookiesAndDip(sservice_t *);
285 static int SSGetAdapter(get_adapter_t *);
286 static int SSGetPage(get_page_t *);
287 static int SSGetSocket(get_socket_t *);
288 static int SSGetStatus(get_ss_status_t *);
289 static int SSGetWindow(get_window_t *);
290 static int SSInquireAdapter(inquire_adapter_t *);
291 static int SSInquireSocket(inquire_socket_t *);
292 static int SSInquireWindow(inquire_window_t *);
293 static int SSResetSocket(int, int);
294 static int SSSetPage(set_page_t *);
295 static int SSSetSocket(set_socket_t *);
296 static int SSSetWindow(set_window_t *);
297 static int SSSetIRQHandler(set_irq_handler_t *);
298 static int SSClearIRQHandler(clear_irq_handler_t *);
299 
300 static struct modldrv modlmisc = {
301 	&mod_miscops,		/* Type of module. This one is a driver */
302 	"PCMCIA Nexus Support %I%", /* Name of the module. */
303 };
304 
305 static struct modlinkage modlinkage = {
306 	MODREV_1, (void *)&modlmisc, NULL
307 };
308 
309 int
310 _init()
311 {
312 	int	ret;
313 
314 	cisp_init();
315 
316 	if (cs_init() != CS_SUCCESS) {
317 	    if (cs_deinit() != CS_SUCCESS)
318 		cmn_err(CE_CONT, "pcmcia: _init cs_deinit error\n");
319 	    return (-1);
320 	}
321 
322 	mutex_init(&pcmcia_global_lock, NULL, MUTEX_DEFAULT, NULL);
323 	cv_init(&pcmcia_condvar, NULL, CV_DRIVER, NULL);
324 	mutex_init(&pcmcia_enum_lock, NULL, MUTEX_DEFAULT, NULL);
325 
326 	if ((ret = mod_install(&modlinkage)) != 0) {
327 		mutex_destroy(&pcmcia_global_lock);
328 		cv_destroy(&pcmcia_condvar);
329 		mutex_destroy(&pcmcia_enum_lock);
330 	}
331 	return (ret);
332 }
333 
334 int
335 _fini()
336 {
337 	int	ret;
338 
339 	if ((ret = mod_remove(&modlinkage)) == 0) {
340 		mutex_destroy(&pcmcia_global_lock);
341 		cv_destroy(&pcmcia_condvar);
342 		mutex_destroy(&pcmcia_enum_lock);
343 		cis_deinit();
344 		if (cs_deinit() != CS_SUCCESS) {
345 			cmn_err(CE_CONT, "pcmcia: _fini cs_deinit error\n");
346 		}
347 	}
348 	return (ret);
349 }
350 
351 int
352 _info(struct modinfo *modinfop)
353 {
354 	return (mod_info(&modlinkage, modinfop));
355 }
356 
357 extern pri_t minclsyspri;
358 
359 /*
360  * pcmcia_attach()
361  *	the attach routine must make sure that everything needed is present
362  *	including real hardware.  The sequence of events is:
363  *		attempt to load all adapter drivers
364  *		attempt to load Card Services (which _depends_on pcmcia)
365  *		initialize logical sockets
366  *		report the nexus exists
367  */
368 
369 int
370 pcmcia_attach(dev_info_t *dip, anp_t *adapter)
371 {
372 	int count, done, i;
373 
374 #if defined(PCMCIA_DEBUG)
375 	if (pcmcia_debug) {
376 		cmn_err(CE_CONT, "pcmcia_attach: dip=0x%p adapter=0x%p\n",
377 		    (void *)dip, (void *)adapter);
378 	}
379 #endif
380 
381 	pcmcia_dip = dip;
382 
383 	mutex_enter(&pcmcia_enum_lock);
384 	mutex_enter(&pcmcia_global_lock);
385 	if (pcmcia_num_adapters == 0) {
386 		pcmcia_cis_parser = (f_tt *)CISParser;
387 		cis_parser = (void *(*)(int, ...)) CISParser;
388 		pcmcia_cs_event = (f_tt *)cs_event;
389 		cs_socket_services = SocketServices;
390 		/* tell CS we are up with basic init level */
391 		(void) cs_event(PCE_SS_INIT_STATE, PCE_SS_STATE_INIT, 0);
392 	}
393 
394 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
395 	    PCM_DEVICETYPE, "pccard");
396 
397 	ddi_report_dev(dip);	/* directory/device naming */
398 
399 	/*
400 	 * now setup any power management stuff necessary.
401 	 * we do it here in order to ensure that all PC Card nexi
402 	 * implement it.
403 	 */
404 
405 	if (pm_create_components(dip, 1) != DDI_SUCCESS) {
406 		cmn_err(CE_WARN, "%s: not power managed\n",
407 			ddi_get_name_addr(dip));
408 	} else {
409 		pm_set_normal_power(dip, 0, 1);
410 	}
411 
412 	/*
413 	 * setup the info necessary for Card Services/SocketServices
414 	 * and notify CS when ready.
415 	 */
416 
417 	pcmcia_free_resources(dip);
418 	pcmcia_init_adapter(adapter, dip);
419 	/* exit mutex so CS can run for any cards found */
420 	mutex_exit(&pcmcia_global_lock);
421 
422 	/*
423 	 * make sure the devices are identified before
424 	 * returning.  We do this by checking each socket to see if
425 	 * a card is present.  If there is one, and there isn't a dip,
426 	 * we can't be done.  We scan the list of sockets doing the
427 	 * check. if we aren't done, wait for a condition variable to
428 	 * wakeup.
429 	 * Because we can miss a wakeup and because things can
430 	 * take time, we do eventually give up and have a timeout.
431 	 */
432 
433 	for (count = 0, done = 0;
434 	    done == 0 && count < max(pcmcia_num_sockets, 16);
435 	    count++) {
436 		done = 1;
437 		/* block CS while checking so we don't miss anything */
438 		mutex_enter(&pcmcia_global_lock);
439 		for (i = 0; i < pcmcia_num_sockets; i++) {
440 			get_ss_status_t status;
441 			if (pcmcia_sockets[i] == NULL)
442 				continue;
443 			bzero(&status, sizeof (status));
444 			status.socket = i;
445 			if (SSGetStatus(&status) == SUCCESS) {
446 				if (status.CardState & SBM_CD &&
447 				    pcmcia_sockets[i]->ls_dip[0] == NULL) {
448 					done = 0;
449 				}
450 			}
451 		}
452 		/* only wait if we aren't done with this set */
453 		if (!done) {
454 			mutex_exit(&pcmcia_global_lock);
455 			delay(10); /* give up CPU for a time */
456 			mutex_enter(&pcmcia_global_lock);
457 		}
458 		mutex_exit(&pcmcia_global_lock);
459 	}
460 
461 	mutex_exit(&pcmcia_enum_lock);
462 	return (DDI_SUCCESS);
463 }
464 
465 /*
466  * pcmcia_detach
467  *	unload everything and then detach the nexus
468  */
469 /* ARGSUSED */
470 int
471 pcmcia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
472 {
473 	switch (cmd) {
474 	case DDI_DETACH:
475 		pm_destroy_components(dip);
476 		return (DDI_SUCCESS);
477 
478 	/*
479 	 * resume from a checkpoint
480 	 * We don't do anything special here since the adapter
481 	 * driver will generate resume events that we intercept
482 	 * and convert to insert events.
483 	 */
484 	case DDI_SUSPEND:
485 	case DDI_PM_SUSPEND:
486 		return (DDI_SUCCESS);
487 
488 	default:
489 		return (DDI_FAILURE);
490 	}
491 }
492 
493 /*
494  * card_services_error()
495  *	used to make 2.4/2.5 drivers get an error when
496  *	they try to initialize.
497  */
498 static int
499 card_services_error()
500 {
501 	return (CS_BAD_VERSION);
502 }
503 static int (*cs_error_ptr)() = card_services_error;
504 
505 /*
506  * pcmcia_ctlops
507  *	handle the nexus control operations for the cases where
508  *	a PC Card driver gets called and we need to modify the
509  *	devinfo structure or otherwise do bus specific operations
510  */
511 int
512 pcmcia_ctlops(dev_info_t *dip, dev_info_t *rdip,
513 	ddi_ctl_enum_t ctlop, void *arg, void *result)
514 {
515 	int e;
516 	char name[64];
517 	struct pcmcia_parent_private *ppd;
518 	power_req_t *pm;
519 
520 #if defined(PCMCIA_DEBUG)
521 	if (pcmcia_debug) {
522 		cmn_err(CE_CONT, "pcmcia_ctlops(%p, %p, %d, %p, %p)\n",
523 			(void *)dip, (void *)rdip, ctlop, (void *)arg,
524 			(void *)result);
525 		if (rdip != NULL && ddi_get_name(rdip) != NULL)
526 			cmn_err(CE_CONT, "\t[%s]\n", ddi_get_name(rdip));
527 	}
528 #endif
529 
530 	switch (ctlop) {
531 	case DDI_CTLOPS_REPORTDEV:
532 		if (rdip == (dev_info_t *)0)
533 			return (DDI_FAILURE);
534 
535 		if (strcmp("pcs", ddi_node_name(rdip)) == 0)
536 			cmn_err(CE_CONT, "?PCCard socket %d at %s@%s\n",
537 				ddi_get_instance(rdip),
538 				ddi_driver_name(dip), ddi_get_name_addr(dip));
539 		else
540 			cmn_err(CE_CONT, "?%s%d at %s@%s in socket %d\n",
541 				ddi_driver_name(rdip),
542 				ddi_get_instance(rdip),
543 				ddi_driver_name(dip),
544 				ddi_get_name_addr(dip),
545 				CS_GET_SOCKET_NUMBER(
546 				    ddi_getprop(DDI_DEV_T_NONE, rdip,
547 				    DDI_PROP_DONTPASS,
548 				    PCM_DEV_SOCKET, -1)));
549 
550 		return (DDI_SUCCESS);
551 
552 	case DDI_CTLOPS_INITCHILD:
553 		/*
554 		 * we get control here before the child is called.
555 		 * we can change things if necessary.  This is where
556 		 * the CardServices hook gets planted.
557 		 */
558 #if defined(PCMCIA_DEBUG)
559 		if (pcmcia_debug) {
560 			cmn_err(CE_CONT, "pcmcia: init child: %s(%d) @%p\n",
561 				ddi_node_name(arg), ddi_get_instance(arg),
562 				(void *)arg);
563 			if (DEVI(arg)->devi_binding_name != NULL)
564 				cmn_err(CE_CONT, "\tbinding_name=%s\n",
565 					DEVI(arg)->devi_binding_name);
566 			if (DEVI(arg)->devi_node_name != NULL)
567 				cmn_err(CE_CONT, "\tnode_name=%s\n",
568 					DEVI(arg)->devi_node_name);
569 		}
570 #endif
571 
572 		ppd = (struct pcmcia_parent_private *)
573 			ddi_get_parent_data((dev_info_t *)arg);
574 		if (ppd == NULL)
575 			return (DDI_FAILURE);
576 
577 		if (strcmp("pcs", ddi_node_name((dev_info_t *)arg)) == 0) {
578 			if (ppd == NULL)
579 				return (DDI_FAILURE);
580 			(void) sprintf(name, "%x",
581 			    (int)ppd->ppd_reg[0].phys_hi);
582 			ddi_set_name_addr((dev_info_t *)arg, name);
583 			return (DDI_SUCCESS);
584 		}
585 
586 		/*
587 		 * We don't want driver.conf files that stay in
588 		 * pseudo device form.	It is acceptable to have
589 		 * .conf files add properties only.
590 		 */
591 		if (ndi_dev_is_persistent_node((dev_info_t *)arg) == 0) {
592 			(void) pcmcia_merge_conf((dev_info_t *)arg);
593 			cmn_err(CE_WARN, "%s%d: %s.conf invalid",
594 				ddi_get_name((dev_info_t *)arg),
595 				ddi_get_instance((dev_info_t *)arg),
596 				ddi_get_name((dev_info_t *)arg));
597 			return (DDI_FAILURE);
598 		}
599 
600 
601 #if defined(PCMCIA_DEBUG)
602 		if (pcmcia_debug && ppd != NULL) {
603 			cmn_err(CE_CONT, "\tnreg=%x, intr=%x, socket=%x,"
604 				" function=%x, active=%x, flags=%x\n",
605 				ppd->ppd_nreg, ppd->ppd_intr,
606 				ppd->ppd_socket, ppd->ppd_function,
607 				ppd->ppd_active, ppd->ppd_flags);
608 		}
609 #endif
610 
611 		/*
612 		 * make sure names are relative to socket number
613 		 */
614 		if (ppd->ppd_function > 0) {
615 			int sock;
616 			int func;
617 			sock = ppd->ppd_socket;
618 			func = ppd->ppd_function;
619 			(void) sprintf(name, "%x,%x", sock, func);
620 		} else {
621 			(void) sprintf(name, "%x", ppd->ppd_socket);
622 		}
623 		ddi_set_name_addr((dev_info_t *)arg, name);
624 
625 #if defined(PCMCIA_DEBUG)
626 		if (pcmcia_debug)
627 			cmn_err(CE_CONT, "pcmcia: system init done for %s [%s] "
628 				"nodeid: %x @%s\n",
629 				ddi_get_name(arg), ddi_get_name_addr(arg),
630 				DEVI(arg)->devi_nodeid, name);
631 		if (pcmcia_debug > 1)
632 			pcmcia_dump_minors((dev_info_t *)arg);
633 #endif
634 
635 		return (DDI_SUCCESS);
636 
637 	case DDI_CTLOPS_UNINITCHILD:
638 
639 #if defined(PCMCIA_DEBUG)
640 		if (pcmcia_debug) {
641 			cmn_err(CE_CONT, "pcmcia: uninit child: %s(%d) @%p\n",
642 				ddi_node_name(arg), ddi_get_instance(arg),
643 				(void *)arg);
644 			if (DEVI(arg)->devi_binding_name != NULL)
645 				cmn_err(CE_CONT, "\tbinding_name=%s\n",
646 					DEVI(arg)->devi_binding_name);
647 			if (DEVI(arg)->devi_node_name != NULL)
648 				cmn_err(CE_CONT, "\tnode_name=%s\n",
649 					DEVI(arg)->devi_node_name);
650 		}
651 #endif
652 
653 		ddi_set_name_addr((dev_info_t *)arg, NULL);
654 		ddi_remove_minor_node((dev_info_t *)arg, NULL);
655 		return (DDI_SUCCESS);
656 
657 	case DDI_CTLOPS_SLAVEONLY:
658 		/* PCMCIA devices can't ever be busmaster until CardBus */
659 		ppd = (struct pcmcia_parent_private *)
660 			ddi_get_parent_data(rdip);
661 		if (ppd != NULL && ppd->ppd_flags & PPD_CB_BUSMASTER)
662 			return (DDI_FAILURE); /* at most */
663 		return (DDI_SUCCESS);
664 
665 	case DDI_CTLOPS_SIDDEV:
666 		/* in general this is true. */
667 		return (DDI_SUCCESS);
668 
669 	case DDI_CTLOPS_NREGS:
670 		ppd = (struct pcmcia_parent_private *)
671 			ddi_get_parent_data(rdip);
672 		if (ppd != NULL)
673 			*((uint32_t *)result) = (ppd->ppd_nreg);
674 		else
675 			*((uint32_t *)result) = 0;
676 		return (DDI_SUCCESS);
677 
678 	case DDI_CTLOPS_REGSIZE:
679 		ppd = (struct pcmcia_parent_private *)
680 			ddi_get_parent_data(rdip);
681 		if (ppd != NULL && ppd->ppd_nreg > 0)
682 			*((off_t *)result) =  sizeof (struct pcm_regs);
683 		else
684 			*((off_t *)result) = 0;
685 		return (DDI_SUCCESS);
686 
687 	case DDI_CTLOPS_POWER:
688 		ppd = (struct pcmcia_parent_private *)
689 			ddi_get_parent_data(rdip);
690 
691 		if (ppd == NULL)
692 			return (DDI_FAILURE);
693 		/*
694 		 * if this is not present, don't bother (claim success)
695 		 * since it is already in the right state.  Don't
696 		 * do any resume either since the card insertion will
697 		 * happen independently.
698 		 */
699 		if (!ppd->ppd_active)
700 			return (DDI_SUCCESS);
701 		for (e = 0; e < pcmcia_num_adapters; e++)
702 			if (pcmcia_adapters[e] ==
703 			    pcmcia_sockets[ppd->ppd_socket]->ls_adapter)
704 				break;
705 		if (e == pcmcia_num_adapters)
706 			return (DDI_FAILURE);
707 		pm = (power_req_t *)arg;
708 #if defined(PCMCIA_DEBUG)
709 		if (pcmcia_debug) {
710 			cmn_err(CE_WARN, "power: %d: %p, %d, %d [%s]\n",
711 				pm->request_type,
712 				(void *)pm->req.set_power_req.who,
713 				pm->req.set_power_req.cmpt,
714 				pm->req.set_power_req.level,
715 				ddi_get_name_addr(rdip));
716 		}
717 #endif
718 		e = ppd->ppd_socket;
719 		switch (pm->request_type) {
720 		case PMR_SUSPEND:
721 			if (!(pcmcia_sockets[e]->ls_flags &
722 			    PCS_SUSPENDED)) {
723 				pcmcia_do_suspend(ppd->ppd_socket,
724 				    pcmcia_sockets[e]);
725 			}
726 			ppd->ppd_flags |= PPD_SUSPENDED;
727 			return (DDI_SUCCESS);
728 		case PMR_RESUME:
729 			/* for now, we just succeed since the rest is done */
730 			return (DDI_SUCCESS);
731 		case PMR_SET_POWER:
732 			/*
733 			 * not sure how to handle power control
734 			 * for now, we let the child handle it itself
735 			 */
736 			(void) pcmcia_power(pm->req.set_power_req.who,
737 				pm->req.set_power_req.cmpt,
738 				pm->req.set_power_req.level);
739 			break;
740 		default:
741 			break;
742 		}
743 		return (DDI_FAILURE);
744 		/* These CTLOPS will need to be implemented for new form */
745 		/* let CardServices know about this */
746 
747 	default:
748 		/* if we don't understand, pass up the tree */
749 		/* most things default to general ops */
750 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
751 	}
752 }
753 
754 struct pcmcia_props {
755 	char *name;
756 	int   len;
757 	int   prop;
758 } pcmcia_internal_props[] = {
759 	{ PCM_DEV_ACTIVE, 0, PCMCIA_PROP_ACTIVE },
760 	{ PCM_DEV_R2TYPE, 0, PCMCIA_PROP_R2TYPE },
761 	{ PCM_DEV_CARDBUS, 0, PCMCIA_PROP_CARDBUS },
762 	{ CS_PROP, sizeof (void *), PCMCIA_PROP_OLDCS },
763 	{ "reg", 0, PCMCIA_PROP_REG },
764 	{ "interrupts", sizeof (int), PCMCIA_PROP_INTR },
765 	{ "pm-hardware-state", 0, PCMCIA_PROP_DEFAULT_PM },
766 };
767 
768 /*
769  * pcmcia_prop_decode(name)
770  *	decode the name and determine if this is a property
771  *	we construct on the fly, one we have on the prop list
772  *	or one that requires calling the CIS code.
773  */
774 static int
775 pcmcia_prop_decode(char *name)
776 {
777 	int i;
778 	if (strncmp(name, "cistpl_", 7) == 0)
779 		return (PCMCIA_PROP_CIS);
780 
781 	for (i = 0; i < (sizeof (pcmcia_internal_props) /
782 	    sizeof (struct pcmcia_props)); i++) {
783 		if (strcmp(name, pcmcia_internal_props[i].name) == 0)
784 			return (i);
785 	}
786 
787 	return (PCMCIA_PROP_UNKNOWN);
788 }
789 
790 /*
791  * pcmcia_prop_op()
792  *	we don't have properties in PROM per se so look for them
793  *	only in the devinfo node.  Future may allow us to find
794  *	certain CIS tuples via this interface if a user asks for
795  *	a property of the form "cistpl-<tuplename>" but not yet.
796  *
797  *	The addition of 1275 properties adds to the necessity.
798  */
799 int
800 pcmcia_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
801     ddi_prop_op_t prop_op, int mod_flags,
802     char *name, caddr_t valuep, int *lengthp)
803 {
804 	int len, proplen, which, flags;
805 	caddr_t buff, propptr;
806 	struct pcmcia_parent_private *ppd;
807 
808 	len = *lengthp;
809 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(ch_dip);
810 
811 	switch (which = pcmcia_prop_decode(name)) {
812 	default:
813 		if (ppd == NULL)
814 			return (DDI_PROP_NOT_FOUND);
815 
816 		/* note that proplen may get modified */
817 		proplen = pcmcia_internal_props[which].len;
818 		switch (pcmcia_internal_props[which].prop) {
819 		case PCMCIA_PROP_DEFAULT_PM:
820 			propptr = pcmcia_default_pm_mode;
821 			proplen = strlen(propptr) + 1;
822 			break;
823 		case PCMCIA_PROP_OLDCS:
824 			propptr = (caddr_t)&cs_error_ptr;
825 			break;
826 		case PCMCIA_PROP_REG:
827 			propptr = (caddr_t)ppd->ppd_reg;
828 			proplen = ppd->ppd_nreg * sizeof (struct pcm_regs);
829 			break;
830 		case PCMCIA_PROP_INTR:
831 			propptr = (caddr_t)&ppd->ppd_intr;
832 			break;
833 
834 		/* the next set are boolean values */
835 		case PCMCIA_PROP_ACTIVE:
836 			propptr = NULL;
837 			if (!ppd->ppd_active) {
838 				return (DDI_PROP_NOT_FOUND);
839 			}
840 			break;
841 		case PCMCIA_PROP_R2TYPE:
842 			propptr = NULL;
843 			if (ppd->ppd_flags & PPD_CARD_CARDBUS)
844 				return (DDI_PROP_NOT_FOUND);
845 			break;
846 		case PCMCIA_PROP_CARDBUS:
847 			propptr = NULL;
848 			if (!(ppd->ppd_flags * PPD_CARD_CARDBUS))
849 				return (DDI_PROP_NOT_FOUND);
850 			break;
851 		}
852 
853 		break;
854 
855 	case PCMCIA_PROP_CIS:
856 		/*
857 		 * once we have the lookup code in place
858 		 * it is sufficient to break out of the switch
859 		 * once proplen and propptr are set.
860 		 * The common prop_op code deals with the rest.
861 		 */
862 	case PCMCIA_PROP_UNKNOWN:
863 		return (ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
864 		    mod_flags | DDI_PROP_NOTPROM,
865 		    name, valuep, lengthp));
866 	}
867 
868 	if (prop_op == PROP_LEN) {
869 		/* just the length */
870 		*lengthp = proplen;
871 		return (DDI_PROP_SUCCESS);
872 	}
873 	switch (prop_op) {
874 	case PROP_LEN_AND_VAL_ALLOC:
875 		if (mod_flags & DDI_PROP_CANSLEEP)
876 			flags = KM_SLEEP;
877 		else
878 			flags = KM_NOSLEEP;
879 		buff = kmem_alloc((size_t)proplen, flags);
880 		if (buff == NULL)
881 			return (DDI_PROP_NO_MEMORY);
882 		*(caddr_t *)valuep = (caddr_t)buff;
883 		break;
884 	case PROP_LEN_AND_VAL_BUF:
885 		buff = (caddr_t)valuep;
886 		if (len < proplen)
887 			return (DDI_PROP_BUF_TOO_SMALL);
888 		break;
889 	default:
890 		break;
891 	}
892 
893 	if (proplen > 0)
894 		bcopy(propptr, buff, proplen);
895 	*lengthp = proplen;
896 	return (DDI_PROP_SUCCESS);
897 }
898 
899 
900 struct regspec *
901 pcmcia_rnum_to_regspec(dev_info_t *dip, int rnumber)
902 {
903 	struct pcmcia_parent_private *ppd;
904 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
905 	if (ppd->ppd_nreg < rnumber)
906 		return (NULL);
907 	return ((struct regspec *)&ppd->ppd_reg[rnumber]);
908 }
909 
910 struct regspec *
911 pcmcia_rnum_to_mapped(dev_info_t *dip, int rnumber)
912 {
913 	struct pcmcia_parent_private *ppd;
914 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
915 	if (ppd->ppd_nreg < rnumber)
916 		return (NULL);
917 	if (ppd->ppd_assigned == NULL)
918 		return (NULL);
919 	if (ppd->ppd_assigned[rnumber].phys_len == 0)
920 		return (NULL);
921 	else
922 		return ((struct regspec *)&ppd->ppd_assigned[rnumber]);
923 }
924 
925 int
926 pcmcia_find_rnum(dev_info_t *dip, struct regspec *reg)
927 {
928 	struct pcmcia_parent_private *ppd;
929 	struct regspec *regp;
930 	int i;
931 
932 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
933 	if (ppd == NULL)
934 		return (-1);
935 	for (regp = (struct regspec *)ppd->ppd_reg, i = 0;
936 	    i < ppd->ppd_nreg; i++, regp++) {
937 		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
938 			return (i);
939 	}
940 	for (regp = (struct regspec *)ppd->ppd_assigned, i = 0;
941 	    i < ppd->ppd_nreg; i++, regp++) {
942 		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
943 			return (i);
944 	}
945 
946 	return (-1);
947 }
948 
949 int
950 pcmcia_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
951 	off_t offset, off_t len, caddr_t *vaddrp)
952 {
953 	struct pcm_regs *regs, *mregs = NULL, tmp_reg;
954 	ddi_map_req_t mr = *mp;
955 	ra_return_t ret;
956 	int check, rnum = -1;
957 	uint32_t base;
958 	uchar_t regbuf[sizeof (pci_regspec_t)];
959 
960 	mp = &mr;		/* a copy of original request */
961 
962 	/* check for register number */
963 	switch (mp->map_type) {
964 	case DDI_MT_REGSPEC:
965 		regs = (struct pcm_regs *)mp->map_obj.rp;
966 		mregs = (struct pcm_regs *)mp->map_obj.rp;
967 		/*
968 		 * when using regspec, must not be relocatable
969 		 * and should be from assigned space.
970 		 */
971 		if (!PC_REG_RELOC(regs->phys_hi))
972 			return (DDI_FAILURE);
973 		rnum = pcmcia_find_rnum(rdip, (struct regspec *)mregs);
974 		break;
975 	case DDI_MT_RNUMBER:
976 		regs = (struct pcm_regs *)
977 			pcmcia_rnum_to_regspec(rdip, mp->map_obj.rnumber);
978 		mregs = (struct pcm_regs *)
979 			pcmcia_rnum_to_mapped(rdip, mp->map_obj.rnumber);
980 		rnum = mp->map_obj.rnumber;
981 		if (regs == NULL)
982 			return (DDI_FAILURE);
983 		mp->map_type = DDI_MT_REGSPEC;
984 		mp->map_obj.rp = (struct regspec *)mregs;
985 		break;
986 	default:
987 		return (DDI_ME_INVAL);
988 	}
989 
990 	/* basic sanity checks */
991 	switch (mp->map_op) {
992 	default:
993 		return (DDI_ME_UNIMPLEMENTED);
994 	case DDI_MO_UNMAP:
995 		if (mregs == NULL)
996 			return (DDI_FAILURE);
997 		regs = mregs;
998 		break;
999 	case DDI_MO_MAP_LOCKED:
1000 	case DDI_MO_MAP_HANDLE:
1001 		panic("unsupported bus operation");
1002 		/*NOTREACHED*/
1003 	}
1004 
1005 	/*
1006 	 * we need a private copy for manipulation and
1007 	 * calculation of the correct ranges
1008 	 */
1009 	tmp_reg = *regs;
1010 	mp->map_obj.rp = (struct regspec *)(regs = &tmp_reg);
1011 	base = regs->phys_lo;
1012 	if (base == 0 && offset != 0) {
1013 		/*
1014 		 * for now this is an error.  What does it really mean
1015 		 * to ask for an offset from an address that hasn't
1016 		 * been allocated yet.
1017 		 */
1018 		return (DDI_ME_INVAL);
1019 	}
1020 	regs->phys_lo += (uint32_t)offset;
1021 	if (len != 0) {
1022 		if (len > regs->phys_len) {
1023 			return (DDI_ME_INVAL);
1024 		}
1025 		regs->phys_len = len;
1026 	}
1027 
1028 	/*
1029 	 * basic sanity is checked so now make sure
1030 	 * we can actually allocate something for this
1031 	 * request and then convert to a "standard"
1032 	 * regspec for the next layer up (pci/isa/rootnex/etc.)
1033 	 */
1034 
1035 	switch (PC_GET_REG_TYPE(regs->phys_hi)) {
1036 	case PC_REG_SPACE_IO:
1037 		check = PCA_RES_NEED_IO;
1038 		break;
1039 	case PC_REG_SPACE_MEMORY:
1040 		check = PCA_RES_NEED_MEM;
1041 		break;
1042 	default:
1043 		/* not a valid register type */
1044 		return (DDI_FAILURE);
1045 	}
1046 
1047 	mr.map_type = DDI_MT_REGSPEC;
1048 	ret.ra_addr_hi = 0;
1049 	ret.ra_addr_lo = regs->phys_lo;
1050 	ret.ra_len = regs->phys_len;
1051 	mr.map_obj.rp = pcmcia_cons_regspec(dip,
1052 	    (check == PCA_RES_NEED_IO) ?
1053 	    PCMCIA_MAP_IO : PCMCIA_MAP_MEM,
1054 	    regbuf, &ret);
1055 	switch (mp->map_op) {
1056 	case DDI_MO_UNMAP:
1057 		pcmcia_set_assigned(rdip, rnum, NULL);
1058 		break;
1059 	default:
1060 		break;
1061 	}
1062 	return (ddi_map(dip, &mr, (off_t)0, (off_t)0, vaddrp));
1063 }
1064 
1065 /*
1066  * pcmcia_cons_regspec()
1067  * based on parent's bus type, construct a regspec that is usable
1068  * by that parent to map the resource into the system.
1069  */
1070 #define	PTYPE_PCI	1
1071 #define	PTYPE_ISA	0
1072 struct regspec *
1073 pcmcia_cons_regspec(dev_info_t *dip, int type, uchar_t *buff, ra_return_t *ret)
1074 {
1075 	int ptype = -1, len, bus;
1076 	char device_type[MODMAXNAMELEN + 1];
1077 	dev_info_t *pdip;
1078 	struct regspec *defreg;
1079 	pci_regspec_t *pcireg;
1080 
1081 	pdip = ddi_get_parent(dip);
1082 	if (pdip != ddi_root_node()) {
1083 		/* we're not a child of root so find out what */
1084 		len = sizeof (device_type);
1085 		if (ddi_prop_op(DDI_DEV_T_ANY, pdip, PROP_LEN_AND_VAL_BUF, 0,
1086 			"device_type", (caddr_t)device_type, &len) ==
1087 		    DDI_PROP_SUCCESS) {
1088 			/* check things out */
1089 			if (strcmp(device_type, "pci") == 0)
1090 				ptype = PTYPE_PCI;
1091 			else if (strcmp(device_type, "isa") == 0)
1092 				ptype = PTYPE_ISA;
1093 		}
1094 	}
1095 	switch (ptype) {
1096 	case PTYPE_PCI:
1097 		/* XXX need to look at carefully */
1098 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1099 			"reg", (caddr_t)&pcireg, &len) == DDI_SUCCESS) {
1100 			bus = PCI_REG_BUS_G(pcireg->pci_phys_hi);
1101 			kmem_free(pcireg, len);
1102 		} else {
1103 			bus = 0;
1104 		}
1105 		pcireg = (pci_regspec_t *)buff;
1106 		pcireg->pci_phys_hi = (type == PCMCIA_MAP_IO ? PCI_ADDR_IO :
1107 			PCI_ADDR_MEM32) | PCI_RELOCAT_B | (bus << 16);
1108 		pcireg->pci_phys_mid = ret->ra_addr_hi;
1109 		pcireg->pci_phys_low = ret->ra_addr_lo;
1110 		if (type == PCMCIA_MAP_IO)
1111 			pcireg->pci_phys_low &= 0xFFFF;
1112 		pcireg->pci_size_hi = 0;
1113 		pcireg->pci_size_low = ret->ra_len;
1114 		break;
1115 	default:
1116 		/* default case is to use struct regspec */
1117 		defreg = (struct regspec *)buff;
1118 		defreg->regspec_bustype = type == PCMCIA_MAP_IO ? 1 : 0;
1119 		defreg->regspec_addr = ret->ra_addr_lo;
1120 		defreg->regspec_size = ret->ra_len;
1121 		break;
1122 	}
1123 	return ((struct regspec *)buff);
1124 }
1125 
1126 /*
1127  * pcmcia_init_adapter
1128  *	Initialize the per-adapter structures and check to see if
1129  *	there are possible other instances coming.
1130  */
1131 void
1132 pcmcia_init_adapter(anp_t *adapter, dev_info_t *dip)
1133 {
1134 	int i, n;
1135 	pcmcia_if_t *ls_if;
1136 
1137 	i = pcmcia_num_adapters++;
1138 	pcmcia_adapters[i] = kmem_zalloc(sizeof (struct pcmcia_adapter),
1139 	    KM_SLEEP);
1140 	pcmcia_adapters[i]->pca_dip = dip;
1141 	/* should this be pca_winshift??? */
1142 	pcmcia_adapters[i]->pca_module = ddi_name_to_major(ddi_get_name(dip));
1143 	pcmcia_adapters[i]->pca_unit = ddi_get_instance(dip);
1144 	pcmcia_adapters[i]->pca_iblock = adapter->an_iblock;
1145 	pcmcia_adapters[i]->pca_idev = adapter->an_idev;
1146 	pcmcia_adapters[i]->pca_if = ls_if = adapter->an_if;
1147 	pcmcia_adapters[i]->pca_number = i;
1148 	(void) strcpy(pcmcia_adapters[i]->pca_name, ddi_get_name(dip));
1149 	pcmcia_adapters[i]->
1150 		pca_name[sizeof (pcmcia_adapters[i]->pca_name) - 1] = NULL;
1151 
1152 	if (ls_if != NULL) {
1153 		inquire_adapter_t conf;
1154 		int sock, win;
1155 
1156 		if (ls_if->pcif_inquire_adapter != NULL)
1157 			GET_CONFIG(ls_if, dip, &conf);
1158 
1159 		/* resources - assume worst case and fix from there */
1160 		pcmcia_adapters[i]->pca_flags = PCA_RES_NEED_IRQ |
1161 			PCA_RES_NEED_IO | PCA_RES_NEED_MEM;
1162 		/* indicate first socket not initialized */
1163 		pcmcia_adapters[i]->pca_first_socket = -1;
1164 
1165 		if (conf.ResourceFlags & RES_OWN_IRQ)
1166 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IRQ;
1167 		if (conf.ResourceFlags & RES_OWN_IO)
1168 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IO;
1169 		if (conf.ResourceFlags & RES_OWN_MEM)
1170 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_MEM;
1171 		if (conf.ResourceFlags & RES_IRQ_SHAREABLE)
1172 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SHAREABLE;
1173 		if (conf.ResourceFlags & RES_IRQ_NEXUS)
1174 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SMI_SHARE;
1175 
1176 		/* need to know interrupt limitations */
1177 		if (conf.ActiveLow) {
1178 			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveLow;
1179 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_ISA;
1180 		} else
1181 			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveHigh;
1182 
1183 		/* power entries for adapter */
1184 		pcmcia_adapters[i]->pca_power =
1185 			conf.power_entry;
1186 		pcmcia_adapters[i]->pca_numpower =
1187 			conf.NumPower;
1188 
1189 		for (n = 0; n < conf.NumPower; n++)
1190 			pcmcia_merge_power(&conf.power_entry[n]);
1191 
1192 		/* now setup the per socket info */
1193 		for (sock = 0; sock < conf.NumSockets;
1194 		    sock++) {
1195 			dev_info_t *sockdrv = NULL;
1196 			sockdrv = pcmcia_number_socket(dip, sock);
1197 			if (sockdrv == NULL)
1198 				n = sock + pcmcia_num_sockets;
1199 			else {
1200 				n = ddi_get_instance(sockdrv);
1201 			}
1202 			/* make sure we know first socket on adapter */
1203 			if (pcmcia_adapters[i]->pca_first_socket == -1)
1204 				pcmcia_adapters[i]->pca_first_socket = n;
1205 
1206 			/*
1207 			 * the number of sockets is weird.
1208 			 * we might have only two sockets but
1209 			 * due to persistence of instances we
1210 			 * will need to call them something other
1211 			 * than 0 and 1.  So, we use the largest
1212 			 * instance number as the number and
1213 			 * have some that just don't get used.
1214 			 */
1215 			if (n >= pcmcia_num_sockets)
1216 				pcmcia_num_sockets = n + 1;
1217 #if defined(PCMCIA_DEBUG)
1218 			if (pcmcia_debug) {
1219 				cmn_err(CE_CONT,
1220 					"pcmcia_init: new socket added %d "
1221 					"(%d)\n",
1222 					n, pcmcia_num_sockets);
1223 			}
1224 #endif
1225 
1226 			pcmcia_sockets[n] =
1227 				kmem_zalloc(sizeof (pcmcia_logical_socket_t),
1228 				KM_SLEEP);
1229 			pcmcia_sockets[n]->ls_socket = sock;
1230 			pcmcia_sockets[n]->ls_if = ls_if;
1231 			pcmcia_sockets[n]->ls_adapter =
1232 				pcmcia_adapters[i];
1233 			pcmcia_sockets[n]->ls_cs_events = 0L;
1234 			pcmcia_sockets[n]->ls_sockdrv = sockdrv;
1235 			/* Prototype of intrspec */
1236 			pcmcia_sockets[n]->ls_intr_pri =
1237 				adapter->an_ipl;
1238 #if defined(PCMCIA_DEBUG)
1239 			if (pcmcia_debug)
1240 				cmn_err(CE_CONT,
1241 					"phys sock %d, log sock %d\n",
1242 					sock, n);
1243 #endif
1244 			mutex_init(&pcmcia_sockets[n]->ls_ilock, NULL,
1245 				MUTEX_DRIVER, *adapter->an_iblock);
1246 		}
1247 
1248 		pcmcia_adapters[i]->pca_numsockets = conf.NumSockets;
1249 		/* now setup the per window information */
1250 		for (win = 0; win < conf.NumWindows; win++) {
1251 			n = win + pcmcia_num_windows;
1252 			pcmcia_windows[n] =
1253 				kmem_zalloc(sizeof (pcmcia_logical_window_t),
1254 				    KM_SLEEP);
1255 			pcmcia_windows[n]->lw_window = win;
1256 			pcmcia_windows[n]->lw_if = ls_if;
1257 			pcmcia_windows[n]->lw_adapter =
1258 				pcmcia_adapters[i];
1259 		}
1260 		pcmcia_num_windows += conf.NumWindows;
1261 		SET_CALLBACK(ls_if, dip,
1262 		    pcm_adapter_callback, i);
1263 
1264 		/* now tell CS about each socket */
1265 		for (sock = 0; sock < pcmcia_num_sockets; sock++) {
1266 #if defined(PCMCIA_DEBUG)
1267 			if (pcmcia_debug) {
1268 				cmn_err(CE_CONT,
1269 					"pcmcia_init: notify CS socket %d "
1270 					"sockp=%p\n",
1271 					sock, (void *)pcmcia_sockets[sock]);
1272 			}
1273 #endif
1274 			if (pcmcia_sockets[sock] == NULL ||
1275 			    (pcmcia_sockets[sock]->ls_flags &
1276 				PCS_SOCKET_ADDED)) {
1277 				/* skip the ones that are done already */
1278 				continue;
1279 			}
1280 			pcmcia_sockets[sock]->ls_flags |= PCS_SOCKET_ADDED;
1281 			if (cs_event(PCE_ADD_SOCKET, sock, 0) !=
1282 			    CS_SUCCESS) {
1283 				/* flag socket as broken */
1284 				pcmcia_sockets[sock]->ls_flags = 0;
1285 			} else {
1286 				pcm_event_manager(PCE_ADD_SOCKET,
1287 				    sock, NULL);
1288 			}
1289 		}
1290 
1291 	}
1292 #if defined(PCMCIA_DEBUG)
1293 	if (pcmcia_debug) {
1294 		cmn_err(CE_CONT, "logical sockets:\n");
1295 		for (i = 0; i < pcmcia_num_sockets; i++) {
1296 			if (pcmcia_sockets[i] == NULL)
1297 				continue;
1298 			cmn_err(CE_CONT,
1299 				"\t%d: phys sock=%d, if=%p, adapt=%p\n",
1300 				i, pcmcia_sockets[i]->ls_socket,
1301 				(void *)pcmcia_sockets[i]->ls_if,
1302 				(void *)pcmcia_sockets[i]->ls_adapter);
1303 		}
1304 		cmn_err(CE_CONT, "logical windows:\n");
1305 		for (i = 0; i < pcmcia_num_windows; i++) {
1306 			cmn_err(CE_CONT,
1307 				"\t%d: phys_window=%d, if=%p, adapt=%p\n",
1308 				i, pcmcia_windows[i]->lw_window,
1309 				(void *)pcmcia_windows[i]->lw_if,
1310 				(void *)pcmcia_windows[i]->lw_adapter);
1311 		}
1312 		cmn_err(CE_CONT, "\tpcmcia_num_power=%d\n", pcmcia_num_power);
1313 		for (n = 0; n < pcmcia_num_power; n++)
1314 			cmn_err(CE_CONT,
1315 				"\t\tPowerLevel: %d\tValidSignals: %x\n",
1316 				pcmcia_power_table[n].PowerLevel,
1317 				pcmcia_power_table[n].ValidSignals);
1318 	}
1319 #endif
1320 }
1321 
1322 /*
1323  * pcmcia_find_cards()
1324  *	check the adapter to see if there are cards present at
1325  *	driver attach time.  If there are, generate an artificial
1326  *	card insertion event to get CS running and the PC Card ultimately
1327  *	identified.
1328  */
1329 void
1330 pcmcia_find_cards(anp_t *adapt)
1331 {
1332 	int i;
1333 	get_ss_status_t status;
1334 	for (i = 0; i < pcmcia_num_sockets; i++) {
1335 		if (pcmcia_sockets[i] &&
1336 		    pcmcia_sockets[i]->ls_if == adapt->an_if) {
1337 			/* check the status */
1338 			status.socket = i;
1339 			if (SSGetStatus(&status) == SUCCESS &&
1340 			    status.IFType != IF_CARDBUS &&
1341 			    status.CardState & SBM_CD &&
1342 			    pcmcia_sockets[i]->ls_dip[0] == NULL) {
1343 				(void) cs_event(PCE_CARD_INSERT, i, 0);
1344 				delay(1);
1345 			}
1346 		}
1347 	}
1348 }
1349 
1350 /*
1351  * pcmcia_number_socket(dip, adapt)
1352  *	we determine socket number by creating a driver for each
1353  *	socket on the adapter and then forcing it to attach.  This
1354  *	results in an instance being assigned which becomes the
1355  *	logical socket number.	If it fails, then we are the first
1356  *	set of sockets and renumbering occurs later.  We do this
1357  *	one socket at a time and return the dev_info_t so the
1358  *	instance number can be used.
1359  */
1360 dev_info_t *
1361 pcmcia_number_socket(dev_info_t *dip, int localsocket)
1362 {
1363 	dev_info_t *child = NULL;
1364 	struct pcmcia_parent_private *ppd;
1365 
1366 	if (ndi_devi_alloc(dip, "pcs", (pnode_t)DEVI_SID_NODEID,
1367 	    &child) == NDI_SUCCESS) {
1368 		ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private),
1369 		    KM_SLEEP);
1370 		ppd->ppd_reg = kmem_zalloc(sizeof (struct pcm_regs), KM_SLEEP);
1371 		ppd->ppd_nreg = 1;
1372 		ppd->ppd_reg[0].phys_hi = localsocket;
1373 		ddi_set_parent_data(child, (caddr_t)ppd);
1374 		if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
1375 			kmem_free(ppd->ppd_reg, sizeof (struct pcm_regs));
1376 			kmem_free(ppd, sizeof (struct pcmcia_parent_private));
1377 			(void) ndi_devi_free(child);
1378 			child = NULL;
1379 		}
1380 	}
1381 	return (child);
1382 }
1383 
1384 /*
1385  * pcm_phys_to_log_socket()
1386  *	from an adapter and socket number return the logical socket
1387  */
1388 int
1389 pcm_phys_to_log_socket(struct pcmcia_adapter *adapt, int socket)
1390 {
1391 	register pcmcia_logical_socket_t *sockp;
1392 	int i;
1393 
1394 	for (i = 0, sockp = pcmcia_sockets[0];
1395 		i < pcmcia_num_sockets; i++, sockp = pcmcia_sockets[i]) {
1396 		if (sockp == NULL)
1397 			continue;
1398 		if (sockp->ls_socket == socket && sockp->ls_adapter == adapt)
1399 			break;
1400 	}
1401 	if (i >= pcmcia_num_sockets) {
1402 #if defined(PCMCIA_DEBUG)
1403 		if (pcmcia_debug)
1404 			cmn_err(CE_CONT,
1405 				"\tbad socket/adapter: %x/%p != %x/%x\n",
1406 				socket, (void *)adapt, pcmcia_num_sockets,
1407 				pcmcia_num_adapters);
1408 #endif
1409 		return (-1);
1410 	}
1411 
1412 	return (i);		/* want logical socket */
1413 }
1414 
1415 /*
1416  * pcm_adapter_callback()
1417  *	this function is called back by the adapter driver at interrupt time.
1418  *	It is here that events should get generated for the event manager if it
1419  *	is present.  It would also be the time where a device information
1420  *	tree could be constructed for a card that was added in if we
1421  *	choose to create them dynamically.
1422  */
1423 
1424 #if defined(PCMCIA_DEBUG)
1425 char *cblist[] = {
1426 	"removal",
1427 	"insert",
1428 	"ready",
1429 	"battery-warn",
1430 	"battery-dead",
1431 	"status-change",
1432 	"write-protect", "reset", "unlock", "client-info", "eject-complete",
1433 	"eject-request", "erase-complete", "exclusive-complete",
1434 	"exclusive-request", "insert-complete", "insert-request",
1435 	"reset-complete", "reset-request", "timer-expired",
1436 	"resume", "suspend"
1437 };
1438 #endif
1439 
1440 /*ARGSUSED*/
1441 static int
1442 pcm_adapter_callback(dev_info_t *dip, int adapter, int event, int socket)
1443 {
1444 	pcmcia_logical_socket_t *sockp;
1445 
1446 #if defined(PCMCIA_DEBUG)
1447 	if (pcmcia_debug) {
1448 		cmn_err(CE_CONT, "pcm_adapter_callback: %p %x %x %x: ",
1449 			(void *)dip, adapter, event, socket);
1450 		cmn_err(CE_CONT, "[%s]\n", cblist[event]);
1451 	}
1452 #endif
1453 
1454 	if (adapter >= pcmcia_num_adapters || adapter < 0) {
1455 #if defined(PCMCIA_DEBUG)
1456 		if (pcmcia_debug)
1457 			cmn_err(CE_CONT, "\tbad adapter number: %d : %d\n",
1458 				adapter, pcmcia_num_adapters);
1459 #endif
1460 		return (1);
1461 	}
1462 
1463 	/* get the logical socket since that is what CS knows */
1464 	socket = pcm_phys_to_log_socket(pcmcia_adapters[adapter], socket);
1465 	if (socket == -1) {
1466 		cmn_err(CE_WARN, "pcmcia callback - bad logical socket\n");
1467 		return (0);
1468 	}
1469 	sockp = pcmcia_sockets[socket];
1470 	switch (event) {
1471 	case -1:		/* special case of adapter going away */
1472 	case PCE_CARD_INSERT:
1473 		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
1474 			PCE_E2M(PCE_CARD_REMOVAL);
1475 		break;
1476 	case PCE_CARD_REMOVAL:
1477 				/* disable interrupts at this point */
1478 		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
1479 			PCE_E2M(PCE_CARD_REMOVAL);
1480 		/* remove children that never attached */
1481 
1482 		break;
1483 	case PCE_PM_RESUME:
1484 		pcmcia_do_resume(socket, sockp);
1485 		/* event = PCE_CARD_INSERT; */
1486 		break;
1487 	case PCE_PM_SUSPEND:
1488 		pcmcia_do_suspend(socket, sockp);
1489 		/* event = PCE_CARD_REMOVAL; */
1490 		break;
1491 	default:
1492 		/* nothing to do */
1493 		break;
1494 	}
1495 
1496 #if defined(PCMCIA_DEBUG)
1497 	if (pcmcia_debug) {
1498 		cmn_err(CE_CONT,
1499 			"\tevent %d, event mask=%x, match=%x (log socket=%d)\n",
1500 			event,
1501 			(int)sockp->ls_cs_events,
1502 			(int)(sockp->ls_cs_events & PCE_E2M(event)), socket);
1503 	}
1504 #endif
1505 
1506 	if (pcmcia_cs_event && sockp->ls_cs_events & (1 << event)) {
1507 #if defined(PCMCIA_DEBUG)
1508 		if (pcmcia_debug)
1509 			cmn_err(CE_CONT, "\tcalling CS event handler (%p) "
1510 				"with event=%d\n",
1511 				(void *)pcmcia_cs_event, event);
1512 #endif
1513 		CS_EVENT(event, socket, 0);
1514 	}
1515 
1516 	/* let the event manager(s) know about the event */
1517 	pcm_event_manager(event, socket, NULL);
1518 
1519 	return (0);
1520 }
1521 
1522 /*
1523  * pcm_event_manager()
1524  *	checks for registered management driver callback handlers
1525  *	if there are any, call them if the event warrants it
1526  */
1527 void
1528 pcm_event_manager(int event, int socket, void *arg)
1529 {
1530 	struct pcmcia_mif *mif;
1531 
1532 	for (mif = pcmcia_mif_handlers; mif != NULL; mif = mif->mif_next) {
1533 #if defined(PCMCIA_DEBUG)
1534 		if (pcmcia_debug)
1535 			cmn_err(CE_CONT,
1536 				"pcm_event_manager: event=%d, mif_events=%x"
1537 				" (tst:%d)\n",
1538 				event, (int)*(uint32_t *)mif->mif_events,
1539 				PR_GET(mif->mif_events, event));
1540 #endif
1541 		if (PR_GET(mif->mif_events, event)) {
1542 			mif->mif_function(mif->mif_id, event, socket, arg);
1543 		}
1544 	}
1545 
1546 }
1547 
1548 /*
1549  * pcm_search_devinfo(dev_info_t *, pcm_device_info *, int)
1550  * search for an immediate child node to the nexus and not siblings of nexus
1551  * and not grandchildren.  We follow the same sequence that name binding
1552  * follows so we match same class of device (modem == modem) and don't
1553  * have to depend on features that might not exist.
1554  */
1555 dev_info_t *
1556 pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket)
1557 {
1558 	char bf[256];
1559 	struct pcmcia_parent_private *ppd;
1560 	dev_info_t *dip;
1561 	int circular;
1562 
1563 #if defined(PCMCIA_DEBUG)
1564 	if (pcmcia_debug)
1565 		cmn_err(CE_CONT,
1566 		    "pcm_search_devinfo: socket=%x [%s|%s|%s] pd_flags=%x\n",
1567 		    socket, info->pd_bind_name, info->pd_generic_name,
1568 		    info->pd_vers1_name, info->pd_flags);
1569 #endif
1570 
1571 	ndi_devi_enter(self, &circular);
1572 	/* do searches in compatible property order */
1573 	for (dip = (dev_info_t *)DEVI(self)->devi_child;
1574 	    dip != NULL;
1575 	    dip = (dev_info_t *)DEVI(dip)->devi_sibling) {
1576 		int ppd_socket;
1577 		ppd = (struct pcmcia_parent_private *)
1578 			ddi_get_parent_data(dip);
1579 		if (ppd == NULL) {
1580 #if defined(PCMCIA_DEBUG)
1581 			cmn_err(CE_WARN, "No parent private data\n");
1582 #endif
1583 			continue;
1584 		}
1585 		ppd_socket = CS_MAKE_SOCKET_NUMBER(ppd->ppd_socket,
1586 		    ppd->ppd_function);
1587 #if defined(PCMCIA_DEBUG)
1588 		if (pcmcia_debug) {
1589 			cmn_err(CE_CONT, "\tbind=[%s], node=[%s]\n",
1590 				DEVI(dip)->devi_binding_name,
1591 				DEVI(dip)->devi_node_name);
1592 		}
1593 #endif
1594 		if (info->pd_flags & PCM_NAME_VERS1) {
1595 			(void) strcpy(bf, info->pd_vers1_name);
1596 			pcmcia_fix_string(bf);
1597 			if (DEVI(dip)->devi_binding_name &&
1598 			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
1599 			    socket == ppd_socket)
1600 				break;
1601 		}
1602 		if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) ==
1603 		    (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) {
1604 			(void) sprintf(bf, "%s,%x", info->pd_bind_name,
1605 				info->pd_function);
1606 			if (strcmp(bf, DEVI(dip)->devi_binding_name) == 0 &&
1607 			    socket == ppd->ppd_socket)
1608 				break;
1609 		}
1610 		if (info->pd_flags & PCM_NAME_1275) {
1611 			if (DEVI(dip)->devi_binding_name &&
1612 			    strcmp(DEVI(dip)->devi_binding_name,
1613 				info->pd_bind_name) == 0 &&
1614 			    socket == ppd_socket)
1615 				break;
1616 		}
1617 		if (info->pd_flags & PCM_NAME_GENERIC) {
1618 			(void) sprintf(bf, "%s,%s", PCMDEV_NAMEPREF,
1619 				info->pd_generic_name);
1620 			if (DEVI(dip)->devi_binding_name &&
1621 			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
1622 			    socket == ppd_socket)
1623 				break;
1624 		}
1625 		if (info->pd_flags & PCM_NAME_GENERIC) {
1626 			if (DEVI(dip)->devi_binding_name &&
1627 			    strcmp(DEVI(dip)->devi_binding_name,
1628 				info->pd_generic_name) == 0 &&
1629 			    socket == ppd_socket)
1630 				break;
1631 		}
1632 		if (info->pd_flags & PCM_NO_CONFIG) {
1633 			if (DEVI(dip)->devi_binding_name &&
1634 			    strcmp(DEVI(dip)->devi_binding_name,
1635 					"pccard,memory") == 0 &&
1636 			    socket == ppd_socket)
1637 				break;
1638 		}
1639 	}
1640 	ndi_devi_exit(self, circular);
1641 	return (dip);
1642 }
1643 
1644 /*
1645  * pcm_find_devinfo()
1646  *	this is a wrapper around DDI calls to "find" any
1647  *	devinfo node and then from there find the one associated
1648  *	with the socket
1649  */
1650 dev_info_t *
1651 pcm_find_devinfo(dev_info_t *pdip, struct pcm_device_info *info, int socket)
1652 {
1653 	dev_info_t *dip;
1654 
1655 	dip = pcm_search_devinfo(pdip, info, socket);
1656 	if (dip == NULL)
1657 		return (NULL);
1658 	/*
1659 	 * we have at least a base level dip
1660 	 * see if there is one (this or a sibling)
1661 	 * that has the correct socket number
1662 	 * if there is, return that one else
1663 	 * NULL so a new one is created
1664 	 */
1665 #if defined(PCMCIA_DEBUG)
1666 	if (pcmcia_debug)
1667 		cmn_err(CE_CONT, "find: initial dip = %p, socket=%d, name=%s "
1668 			"(instance=%d, socket=%d, name=%s)\n",
1669 			(void *)dip, socket, info->pd_bind_name,
1670 			ddi_get_instance(dip),
1671 			ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1672 			PCM_DEV_SOCKET, -1),
1673 			ddi_get_name(dip));
1674 #endif
1675 
1676 #if defined(PCMCIA_DEBUG)
1677 	if (pcmcia_debug && dip != NULL)
1678 		cmn_err(CE_CONT, "\treturning non-NULL dip (%s)\n",
1679 			ddi_get_name(dip));
1680 #endif
1681 	return (dip);
1682 }
1683 
1684 /*
1685  * pcm_find_parent_dip(socket)
1686  *	find the correct parent dip for this logical socket
1687  */
1688 dev_info_t *
1689 pcm_find_parent_dip(int socket)
1690 {
1691 	if ((socket < 0 || socket >= pcmcia_num_sockets) ||
1692 	    pcmcia_sockets[socket] == NULL)
1693 		return (NULL);
1694 	return (pcmcia_sockets[socket]->ls_adapter->pca_dip);
1695 }
1696 
1697 /*
1698  * pcmcia_set_em_handler()
1699  *	This is called by the management and event driver to tell
1700  *	the nexus what to call.	 Multiple drivers are allowed
1701  *	but normally only one will exist.
1702  */
1703 int
1704 pcmcia_set_em_handler(int (*handler)(), caddr_t events, int elen,
1705 			uint32_t id, void **cs, void **ss)
1706 {
1707 	struct pcmcia_mif *mif, *tmp;
1708 
1709 	if (handler == NULL) {
1710 		/* NULL means remove the handler based on the ID */
1711 		if (pcmcia_mif_handlers == NULL)
1712 			return (0);
1713 		mutex_enter(&pcmcia_global_lock);
1714 		if (pcmcia_mif_handlers->mif_id == id) {
1715 			mif = pcmcia_mif_handlers;
1716 			pcmcia_mif_handlers = mif->mif_next;
1717 			kmem_free(mif, sizeof (struct pcmcia_mif));
1718 		} else {
1719 			for (mif = pcmcia_mif_handlers;
1720 			    mif->mif_next != NULL &&
1721 			    mif->mif_next->mif_id != id;
1722 			    mif = mif->mif_next)
1723 				;
1724 			if (mif->mif_next != NULL &&
1725 			    mif->mif_next->mif_id == id) {
1726 				tmp = mif->mif_next;
1727 				mif->mif_next = tmp->mif_next;
1728 				kmem_free(tmp, sizeof (struct pcmcia_mif));
1729 			}
1730 		}
1731 		mutex_exit(&pcmcia_global_lock);
1732 	} else {
1733 
1734 		if (pcmcia_num_adapters == 0) {
1735 			return (ENXIO);
1736 		}
1737 		if (elen > EM_EVENTSIZE)
1738 			return (EINVAL);
1739 
1740 		mif = (struct pcmcia_mif *)
1741 			kmem_zalloc(sizeof (struct pcmcia_mif),
1742 			    KM_NOSLEEP);
1743 		if (mif == NULL)
1744 			return (ENOSPC);
1745 
1746 		mif->mif_function = (void (*)())handler;
1747 		bcopy(events, mif->mif_events, elen);
1748 		mif->mif_id = id;
1749 		mutex_enter(&pcmcia_global_lock);
1750 		mif->mif_next = pcmcia_mif_handlers;
1751 		pcmcia_mif_handlers = mif;
1752 		if (cs != NULL)
1753 			*cs = (void *)pcmcia_card_services;
1754 		if (ss != NULL) {
1755 			*ss = (void *)SocketServices;
1756 		}
1757 
1758 		mutex_exit(&pcmcia_global_lock);
1759 	}
1760 	return (0);
1761 }
1762 
1763 /*
1764  * pcm_fix_bits(uchar_t *data, int num, int dir)
1765  *	shift socket bits left(0) or right(0)
1766  *	This is used when mapping logical and physical
1767  */
1768 void
1769 pcm_fix_bits(socket_enum_t src, socket_enum_t dst, int num, int dir)
1770 {
1771 	int i;
1772 
1773 	PR_ZERO(dst);
1774 
1775 	if (dir == 0) {
1776 				/* LEFT */
1777 		for (i = 0; i <= (sizeof (dst) * PR_WORDSIZE) - num; i++) {
1778 			if (PR_GET(src, i))
1779 				PR_SET(dst, i + num);
1780 		}
1781 	} else {
1782 				/* RIGHT */
1783 		for (i = num; i < sizeof (dst) * PR_WORDSIZE; i++) {
1784 			if (PR_GET(src, i))
1785 			    PR_SET(dst, i - num);
1786 		}
1787 	}
1788 }
1789 
1790 uint32_t
1791 genmask(int len)
1792 {
1793 	uint32_t mask;
1794 	for (mask = 0; len > 0; len--) {
1795 		mask |= 1 << (len - 1);
1796 	}
1797 	return (mask);
1798 }
1799 
1800 int
1801 genp2(int val)
1802 {
1803 	int i;
1804 	if (val == 0)
1805 		return (0);
1806 	for (i = 0; i < 32; i++)
1807 		if (val > (1 << i))
1808 			return (i);
1809 	return (0);
1810 }
1811 
1812 #if defined(PCMCIA_DEBUG)
1813 char *ssfuncs[128] = {
1814 	"GetAdapter", "GetPage", "GetSocket", "GetStatus", "GetWindow",
1815 	"InquireAdapter", "InquireSocket", "InquireWindow", "ResetSocket",
1816 	"SetPage", "SetAdapter", "SetSocket", "SetWindow", "SetIRQHandler",
1817 	"ClearIRQHandler",
1818 	/* 15 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1819 	/* 25 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1820 	/* 35 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1821 	/* 45 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1822 	/* 55 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1823 	/* 65 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1824 	/* 75 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1825 	/* 85 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1826 	/* 95 */ NULL, NULL, NULL,
1827 	"CSIsActiveDip",
1828 	"CSInitDev", "CSRegister", "CSCISInit", "CSUnregister",
1829 	"CISGetAddress", "CISSetAddress", "CSCardRemoved", "CSGetCookiesAndDip"
1830 };
1831 #endif
1832 
1833 /*
1834  * SocketServices
1835  *	general entrypoint for Card Services to find
1836  *	Socket Services.  Finding the entry requires
1837  *	a _depends_on[] relationship.
1838  *
1839  *	In some cases, the work is done locally but usually
1840  *	the parameters are adjusted and the adapter driver
1841  *	code asked to do the work.
1842  */
1843 int
1844 SocketServices(int function, ...)
1845 {
1846 	va_list arglist;
1847 	uint32_t args[16];
1848 	csregister_t *reg;
1849 	sservice_t *serv;
1850 	dev_info_t *dip;
1851 	int socket, func;
1852 	int error = SUCCESS;
1853 	pcmcia_logical_socket_t *sockp;
1854 
1855 	va_start(arglist, function);
1856 
1857 #if defined(PCMCIA_DEBUG)
1858 	if (pcmcia_debug > 1)
1859 		cmn_err(CE_CONT, "SocketServices called for function %d [%s]\n",
1860 			function,
1861 			((function < 128) && ssfuncs[function] != NULL) ?
1862 			ssfuncs[function] : "UNKNOWN");
1863 #endif
1864 	switch (function) {
1865 	case CSRegister:
1866 	case CISGetAddress:
1867 	case CISSetAddress:
1868 
1869 		reg = va_arg(arglist, csregister_t *);
1870 
1871 		if (reg->cs_magic != PCCS_MAGIC ||
1872 		    reg->cs_version != PCCS_VERSION) {
1873 			cmn_err(CE_WARN,
1874 				"pcmcia: CSRegister (%x, %x, %p, %p) *ERROR*",
1875 				reg->cs_magic, reg->cs_version,
1876 				(void *)reg->cs_card_services,
1877 				(void *)reg->cs_event);
1878 			error = BAD_FUNCTION;
1879 			break;
1880 		}
1881 
1882 		switch (function) {
1883 		case CISGetAddress:
1884 			reg->cs_event = pcmcia_cis_parser;
1885 			break;
1886 		case CISSetAddress:
1887 			pcmcia_cis_parser = reg->cs_event;
1888 			break;
1889 		case CSRegister:
1890 			break;
1891 		}
1892 		break;
1893 
1894 	case CSUnregister:
1895 		break;
1896 
1897 	case CSCISInit:
1898 		args[0] = va_arg(arglist, int);
1899 #if defined(PCMCIA_DEBUG)
1900 		if (pcmcia_debug)
1901 			cmn_err(CE_CONT,
1902 				"CSCISInit: CIS is initialized on socket %d\n",
1903 				(int)args[0]);
1904 #endif
1905 		/*
1906 		 * now that the CIS has been parsed (there may not
1907 		 * be one but the work is done) we can create the
1908 		 * device information structures.
1909 		 *
1910 		 * we serialize the node creation to avoid problems
1911 		 * with initial probe/attach of nexi.
1912 		 */
1913 
1914 		mutex_enter(&pcmcia_global_lock);
1915 		pcmcia_create_dev_info(args[0]);
1916 		cv_broadcast(&pcmcia_condvar); /* wakeup the nexus attach */
1917 		mutex_exit(&pcmcia_global_lock);
1918 		break;
1919 
1920 	case CSInitDev:
1921 #if defined(PCMCIA_DEBUG)
1922 		if (pcmcia_debug)
1923 			cmn_err(CE_CONT, "CSInitDev: initialize device\n");
1924 #endif
1925 		/*
1926 		 * this is where we create the /devices entries
1927 		 * that let us out into the world
1928 		 */
1929 
1930 		(void) pcmcia_create_device(va_arg(arglist,
1931 		    ss_make_device_node_t *));
1932 		break;
1933 
1934 	case CSCardRemoved:
1935 		args[0] = va_arg(arglist, uint32_t);
1936 		socket = CS_GET_SOCKET_NUMBER(args[0]);
1937 		func = CS_GET_FUNCTION_NUMBER(args[0]);
1938 #if defined(PCMCIA_DEBUG)
1939 		if (pcmcia_debug)
1940 			cmn_err(CE_CONT,
1941 				"CSCardRemoved! (socket=%d)\n", (int)args[0]);
1942 #endif
1943 		if (socket >= pcmcia_num_sockets)
1944 			break;
1945 
1946 		sockp = pcmcia_sockets[socket];
1947 		if (sockp == NULL) {
1948 			cmn_err(CE_WARN,
1949 			    "pcmcia: bad socket = %x", socket);
1950 			break;
1951 		}
1952 
1953 		for (func = 0; func < sockp->ls_functions; func++) {
1954 			/*
1955 			 * break the association of dip and socket
1956 			 * for all functions on that socket
1957 			 */
1958 			dip = sockp->ls_dip[func];
1959 			sockp->ls_dip[func] = NULL;
1960 			if (dip != NULL) {
1961 				struct pcmcia_parent_private *ppd;
1962 				ppd = (struct pcmcia_parent_private *)
1963 				    ddi_get_parent_data(dip);
1964 				ppd->ppd_active = 0;
1965 				(void) ndi_devi_offline(dip,
1966 				    NDI_DEVI_REMOVE);
1967 
1968 				pcmcia_ppd_free(ppd);
1969 			}
1970 #if defined(PCMCIA_DEBUG)
1971 			else {
1972 				if (pcmcia_debug)
1973 					cmn_err(CE_CONT,
1974 					    "CardRemoved: no "
1975 					    "dip present "
1976 					    "on socket %d!\n",
1977 					    (int)args[0]);
1978 			}
1979 #endif
1980 		}
1981 		if (sockp->ls_flags & PCS_SUSPENDED) {
1982 			mutex_enter(&pcmcia_global_lock);
1983 			sockp->ls_flags &= ~PCS_SUSPENDED;
1984 			cv_broadcast(&pcmcia_condvar);
1985 			mutex_exit(&pcmcia_global_lock);
1986 		}
1987 		break;
1988 
1989 	case CSGetCookiesAndDip:
1990 		serv = va_arg(arglist, sservice_t *);
1991 		if (serv != NULL)
1992 			error = GetCookiesAndDip(serv);
1993 		else
1994 			error = BAD_SOCKET;
1995 		break;
1996 
1997 	case CSGetActiveDip:
1998 		/*
1999 		 * get the dip associated with the card currently
2000 		 * in the specified socket
2001 		 */
2002 		args[0] = va_arg(arglist, uint32_t);
2003 		socket = CS_GET_SOCKET_NUMBER(args[0]);
2004 		func = CS_GET_FUNCTION_NUMBER(args[0]);
2005 		error = (long)pcmcia_sockets[socket]->ls_dip[func];
2006 		break;
2007 
2008 		/*
2009 		 * the remaining entries are SocketServices calls
2010 		 */
2011 	case SS_GetAdapter:
2012 		error = SSGetAdapter(va_arg(arglist, get_adapter_t *));
2013 		break;
2014 	case SS_GetPage:
2015 		error = SSGetPage(va_arg(arglist, get_page_t *));
2016 		break;
2017 	case SS_GetSocket:
2018 		error = SSGetSocket(va_arg(arglist, get_socket_t *));
2019 		break;
2020 	case SS_GetStatus:
2021 		error = SSGetStatus(va_arg(arglist, get_ss_status_t *));
2022 		break;
2023 	case SS_GetWindow:
2024 		error = SSGetWindow(va_arg(arglist, get_window_t *));
2025 		break;
2026 	case SS_InquireAdapter:
2027 		error = SSInquireAdapter(va_arg(arglist, inquire_adapter_t *));
2028 		break;
2029 	case SS_InquireSocket:
2030 		error = SSInquireSocket(va_arg(arglist, inquire_socket_t *));
2031 		break;
2032 	case SS_InquireWindow:
2033 		error = SSInquireWindow(va_arg(arglist, inquire_window_t *));
2034 		break;
2035 	case SS_ResetSocket:
2036 		args[0] = va_arg(arglist, uint32_t);
2037 		args[1] = va_arg(arglist, int);
2038 		error = SSResetSocket(args[0], args[1]);
2039 		break;
2040 	case SS_SetPage:
2041 		error = SSSetPage(va_arg(arglist, set_page_t *));
2042 		break;
2043 	case SS_SetSocket:
2044 		error = SSSetSocket(va_arg(arglist, set_socket_t *));
2045 		break;
2046 	case SS_SetWindow:
2047 		error = SSSetWindow(va_arg(arglist, set_window_t *));
2048 		break;
2049 	case SS_SetIRQHandler:
2050 		error = SSSetIRQHandler(va_arg(arglist, set_irq_handler_t *));
2051 		break;
2052 	case SS_ClearIRQHandler:
2053 		error = SSClearIRQHandler(va_arg(arglist,
2054 		    clear_irq_handler_t *));
2055 		break;
2056 	default:
2057 		error = BAD_FUNCTION;
2058 		break;
2059 	}
2060 	va_end(arglist);
2061 	return (error);
2062 }
2063 
2064 /*
2065  * pcmcia_merge_power()
2066  *	The adapters may have different power tables so it
2067  *	is necessary to construct a single power table that
2068  *	can be used throughout the system.  The result is
2069  *	a merger of all capabilities.  The nexus adds
2070  *	power table entries one at a time.
2071  */
2072 void
2073 pcmcia_merge_power(struct power_entry *power)
2074 {
2075 	int i;
2076 	struct power_entry pwr;
2077 
2078 	pwr = *power;
2079 
2080 	for (i = 0; i < pcmcia_num_power; i++) {
2081 		if (pwr.PowerLevel == pcmcia_power_table[i].PowerLevel) {
2082 			if (pwr.ValidSignals ==
2083 				pcmcia_power_table[i].ValidSignals) {
2084 				return;
2085 			} else {
2086 				/* partial match */
2087 				pwr.ValidSignals &=
2088 					~pcmcia_power_table[i].ValidSignals;
2089 			}
2090 		}
2091 	}
2092 	/* what's left becomes a new entry */
2093 	if (pcmcia_num_power == PCMCIA_MAX_POWER)
2094 		return;
2095 	pcmcia_power_table[pcmcia_num_power++] = pwr;
2096 }
2097 
2098 /*
2099  * pcmcia_do_suspend()
2100  *	tell CS that a suspend has happened by passing a
2101  *	card removal event.  Then cleanup the socket state
2102  *	to fake the cards being removed so resume works
2103  */
2104 void
2105 pcmcia_do_suspend(int socket, pcmcia_logical_socket_t *sockp)
2106 {
2107 	get_ss_status_t stat;
2108 	struct pcmcia_adapter *adapt;
2109 	pcmcia_if_t *ls_if;
2110 	dev_info_t *dip;
2111 	int i;
2112 
2113 #ifdef	XXX
2114 	if (pcmcia_cs_event == NULL) {
2115 		return;
2116 	}
2117 #endif
2118 
2119 	ls_if = sockp->ls_if;
2120 	adapt = sockp->ls_adapter;
2121 
2122 	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
2123 		return;
2124 	}
2125 
2126 	stat.socket = socket;
2127 #if defined(PCMCIA_DEBUG)
2128 	if (pcmcia_debug) {
2129 		cmn_err(CE_CONT,
2130 			"pcmcia_do_suspend(%d, %p)\n", socket, (void *)sockp);
2131 	}
2132 #endif
2133 
2134 	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) != SUCCESS)
2135 		return;
2136 
2137 	/*
2138 	 * If there is a card in the socket, then we need to send
2139 	 *	everyone a PCE_CARD_REMOVAL event, and remove the
2140 	 *	card active property.
2141 	 */
2142 
2143 	for (i = 0; i < sockp->ls_functions; i++) {
2144 		struct pcmcia_parent_private *ppd;
2145 		dip = sockp->ls_dip[i];
2146 		if (dip != NULL) {
2147 			ppd = (struct pcmcia_parent_private *)
2148 				ddi_get_parent_data(dip);
2149 			ppd->ppd_flags |= PPD_SUSPENDED;
2150 		}
2151 #if 0
2152 		sockp->ls_dip[i] = NULL;
2153 #endif
2154 	}
2155 	sockp->ls_flags |= PCS_SUSPENDED;
2156 
2157 	if (pcmcia_cs_event &&
2158 	    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
2159 		CS_EVENT(PCE_PM_SUSPEND, socket, 0);
2160 	}
2161 	pcm_event_manager(PCE_PM_SUSPEND, socket, NULL);
2162 }
2163 
2164 /*
2165  * pcmcia_do_resume()
2166  *	tell CS that a suspend has happened by passing a
2167  *	card removal event.  Then cleanup the socket state
2168  *	to fake the cards being removed so resume works
2169  */
2170 void
2171 pcmcia_do_resume(int socket, pcmcia_logical_socket_t *sockp)
2172 {
2173 	get_ss_status_t stat;
2174 	struct pcmcia_adapter *adapt;
2175 	pcmcia_if_t *ls_if;
2176 
2177 #ifdef	XXX
2178 	if (pcmcia_cs_event == NULL) {
2179 		return;
2180 	}
2181 #endif
2182 
2183 	ls_if = sockp->ls_if;
2184 	adapt = sockp->ls_adapter;
2185 
2186 	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
2187 		return;
2188 	}
2189 
2190 	stat.socket = socket;
2191 #if defined(PCMCIA_DEBUG)
2192 	if (pcmcia_debug) {
2193 		cmn_err(CE_CONT,
2194 			"pcmcia_do_resume(%d, %p)\n", socket, (void *)sockp);
2195 	}
2196 #endif
2197 	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) ==
2198 	    SUCCESS) {
2199 
2200 #if defined(PCMCIA_DEBUG)
2201 		if (pcmcia_debug)
2202 			cmn_err(CE_CONT, "\tsocket=%x, CardState=%x\n",
2203 				socket, stat.CardState);
2204 #endif
2205 #if 0
2206 		/* now have socket info -- do we have events? */
2207 		if ((stat.CardState & SBM_CD) == SBM_CD) {
2208 			if (pcmcia_cs_event &&
2209 			    (sockp->ls_cs_events & (1 << PCE_CARD_INSERT))) {
2210 				CS_EVENT(PCE_CARD_INSERT, socket, 0);
2211 			}
2212 
2213 			/* we should have card removed from CS soon */
2214 			pcm_event_manager(PCE_CARD_INSERT, socket, NULL);
2215 		}
2216 #else
2217 		if (pcmcia_cs_event &&
2218 		    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
2219 			CS_EVENT(PCE_PM_RESUME, socket, 0);
2220 			CS_EVENT(PCE_CARD_REMOVAL, socket, 0);
2221 			if ((stat.CardState & SBM_CD) == SBM_CD)
2222 				CS_EVENT(PCE_CARD_INSERT, socket, 0);
2223 		}
2224 #endif
2225 	}
2226 }
2227 
2228 /*
2229  * pcmcia_map_power_set()
2230  *	Given a power table entry and level, find it in the
2231  *	master table and return the index in the adapter table.
2232  */
2233 static int
2234 pcmcia_map_power_set(struct pcmcia_adapter *adapt, int level, int which)
2235 {
2236 	int plevel, i;
2237 	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
2238 	plevel = pcmcia_power_table[level].PowerLevel;
2239 	/* mask = pcmcia_power_table[level].ValidSignals; */
2240 	for (i = 0; i < adapt->pca_numpower; i++)
2241 		if (plevel == pwr[i].PowerLevel &&
2242 		    pwr[i].ValidSignals & which)
2243 			return (i);
2244 	return (0);
2245 }
2246 
2247 /*
2248  * pcmcia_map_power_get()
2249  *	Given an adapter power entry, find the appropriate index
2250  *	in the master table.
2251  */
2252 static int
2253 pcmcia_map_power_get(struct pcmcia_adapter *adapt, int level, int which)
2254 {
2255 	int plevel, i;
2256 	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
2257 	plevel = pwr[level].PowerLevel;
2258 	/* mask = pwr[level].ValidSignals; */
2259 	for (i = 0; i < pcmcia_num_power; i++)
2260 		if (plevel == pcmcia_power_table[i].PowerLevel &&
2261 		    pcmcia_power_table[i].ValidSignals & which)
2262 			return (i);
2263 	return (0);
2264 }
2265 
2266 /*
2267  * XXX - SS really needs a way to allow the caller to express
2268  *	interest in PCE_CARD_STATUS_CHANGE events.
2269  */
2270 static uint32_t
2271 pcm_event_map[32] = {
2272 	PCE_E2M(PCE_CARD_WRITE_PROTECT)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2273 	PCE_E2M(PCE_CARD_UNLOCK)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2274 	PCE_E2M(PCE_EJECTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2275 	PCE_E2M(PCE_INSERTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2276 	PCE_E2M(PCE_CARD_BATTERY_WARN)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2277 	PCE_E2M(PCE_CARD_BATTERY_DEAD)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2278 	PCE_E2M(PCE_CARD_READY)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2279 	PCE_E2M(PCE_CARD_REMOVAL)|PCE_E2M(PCE_CARD_INSERT)|
2280 					PCE_E2M(PCE_CARD_STATUS_CHANGE),
2281 	PCE_E2M(PCE_PM_SUSPEND)|PCE_E2M(PCE_PM_RESUME),
2282 };
2283 
2284 static int
2285 pcm_mapevents(uint32_t eventmask)
2286 {
2287 	uint32_t mask;
2288 	int i;
2289 
2290 	for (i = 0, mask = 0; eventmask && i < 32; i++) {
2291 		if (eventmask & (1 << i)) {
2292 			mask |= pcm_event_map[i];
2293 			eventmask &= ~(1 << i);
2294 		}
2295 	}
2296 	return (mask);
2297 }
2298 
2299 
2300 /*
2301  * PCMCIA Generic Naming Support
2302  *
2303  * With 2.6, PCMCIA naming moves to the 1275 and generic naming model.
2304  * Consequently, the whole naming mechanism is to be changed.  This is
2305  * not backward compatible with the current names but that isn't a problem
2306  * due to so few drivers existing.
2307  *
2308  * For cards with a device_id tuple, a generic name will be used.
2309  * if there is no device_id, then the 1275 name will be used if possible.
2310  * The 1275 name is of the form pccardNNNN,MMMM from the manfid tuple.
2311  * if there is not manfid tuple, an attempt will be made to bind the
2312  * node to the version_1 strings.
2313  *
2314  * In all cases, a "compatible" property is created with a number
2315  * of names.  The most generic name will be last in the list.
2316  */
2317 
2318 /*
2319  * pcmcia_fix_string()
2320  * want to avoid special characters in alias strings so convert
2321  * to something innocuous
2322  */
2323 
2324 void
2325 pcmcia_fix_string(char *str)
2326 {
2327 	for (; str && *str; str++) {
2328 		switch (*str) {
2329 			case ' ':
2330 			case '\t':
2331 				*str = '_';
2332 				break;
2333 		}
2334 	}
2335 }
2336 
2337 void
2338 pcmcia_1275_name(int socket, struct pcm_device_info *info,
2339 			client_handle_t handle)
2340 {
2341 	cistpl_manfid_t manfid;
2342 	cistpl_jedec_t jedec;
2343 	tuple_t tuple;
2344 	int i;
2345 
2346 	tuple.Socket = socket;
2347 
2348 	/* get MANFID if it exists -- this is most important form */
2349 	tuple.DesiredTuple = CISTPL_MANFID;
2350 	tuple.Attributes = 0;
2351 	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2352 	    SUCCESS) {
2353 		i = csx_Parse_CISTPL_MANFID(handle, &tuple,
2354 		    &manfid);
2355 		if (i == SUCCESS) {
2356 			(void) sprintf(info->pd_bind_name, "%s%x,%x",
2357 				PCMDEV_NAMEPREF,
2358 				manfid.manf, manfid.card);
2359 			info->pd_flags |= PCM_NAME_1275;
2360 		}
2361 	} else {
2362 		tuple.Attributes = 0;
2363 		tuple.DesiredTuple = CISTPL_JEDEC_A;
2364 		if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2365 		    SUCCESS) {
2366 			i = csx_Parse_CISTPL_JEDEC_A(handle, &tuple,
2367 			    &jedec);
2368 			if (i == SUCCESS) {
2369 				(void) sprintf(info->pd_bind_name, "%s%x,%x",
2370 					PCMDEV_NAMEPREF,
2371 					jedec.jid[0].id, jedec.jid[0].info);
2372 				info->pd_flags |= PCM_NAME_1275;
2373 			}
2374 		}
2375 	}
2376 }
2377 
2378 void
2379 pcmcia_vers1_name(int socket, struct pcm_device_info *info,
2380 			client_handle_t handle)
2381 {
2382 	cistpl_vers_1_t vers1;
2383 	tuple_t tuple;
2384 	int which = 0;
2385 	int i, len, space;
2386 
2387 	tuple.Socket = socket;
2388 	info->pd_vers1_name[0] = '\0';
2389 
2390 	/* Version 1 strings */
2391 	tuple.DesiredTuple = CISTPL_VERS_1;
2392 	tuple.Attributes = 0;
2393 	if (!which &&
2394 	    (i = csx_GetFirstTuple(handle, &tuple)) ==
2395 		SUCCESS) {
2396 		i = csx_Parse_CISTPL_VERS_1(handle, &tuple, &vers1);
2397 		if (i == SUCCESS) {
2398 			for (i = 0, len = 0, space = 0; i < vers1.ns; i++) {
2399 			    if ((space + len + strlen(info->pd_vers1_name)) >=
2400 				sizeof (info->pd_vers1_name))
2401 				    break;
2402 			    if (space) {
2403 				    info->pd_vers1_name[len++] = ',';
2404 			    }
2405 			    (void) strcpy(info->pd_vers1_name + len,
2406 				(char *)vers1.pi[i]);
2407 			    len += strlen((char *)vers1.pi[i]);
2408 			    /* strip trailing spaces off of string */
2409 			    while (info->pd_vers1_name[len - 1] == ' ' &&
2410 				    len > 0)
2411 				    len--;
2412 			    space = 1;
2413 			}
2414 			info->pd_vers1_name[len] = '\0';
2415 			info->pd_flags |= PCM_NAME_VERS1;
2416 		}
2417 	}
2418 }
2419 
2420 
2421 int
2422 pcmcia_get_funce(client_handle_t handle, tuple_t *tuple)
2423 {
2424 	int ret = 0;
2425 
2426 	tuple->Attributes = 0;
2427 	while (csx_GetNextTuple(handle, tuple) == SUCCESS) {
2428 		if (tuple->TupleCode == CISTPL_FUNCID) {
2429 			break;
2430 		}
2431 		if (tuple->TupleCode == CISTPL_FUNCE) {
2432 			ret = 1;
2433 			break;
2434 		}
2435 		tuple->Attributes = 0;
2436 	}
2437 	return (ret);
2438 }
2439 
2440 char *pcmcia_lan_types[] = {
2441 	"arcnet",
2442 	"ethernet",
2443 	"token-ring",
2444 	"localtalk",
2445 	"fddi",
2446 	"atm",
2447 	"wireless",
2448 	"reserved"
2449 };
2450 
2451 void
2452 pcmcia_generic_name(int socket, struct pcm_device_info *info,
2453 			client_handle_t handle)
2454 {
2455 	cistpl_funcid_t funcid;
2456 	cistpl_funce_t funce;
2457 	tuple_t tuple;
2458 	int which = 0;
2459 	int i;
2460 
2461 	tuple.Socket = socket;
2462 
2463 	tuple.DesiredTuple = CISTPL_FUNCID;
2464 	tuple.Attributes = 0;
2465 	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2466 	    SUCCESS) {
2467 		/*
2468 		 * need to make sure that CISTPL_FUNCID is not
2469 		 * present in both a global and local CIS for MF
2470 		 * cards.  3COM seems to do this erroneously
2471 		 */
2472 
2473 		if (info->pd_flags & PCM_MULTI_FUNCTION &&
2474 		    tuple.Flags & CISTPLF_GLOBAL_CIS) {
2475 			tuple_t ltuple;
2476 			ltuple = tuple;
2477 			ltuple.DesiredTuple = CISTPL_FUNCID;
2478 			ltuple.Attributes = 0;
2479 			if ((i = csx_GetNextTuple(handle, &ltuple)) ==
2480 			    SUCCESS) {
2481 				/* this is the per-function funcid */
2482 				tuple = ltuple;
2483 			}
2484 		}
2485 
2486 		i = csx_Parse_CISTPL_FUNCID(handle, &tuple, &funcid);
2487 		if (i == SUCCESS) {
2488 			/* in case no function extension */
2489 			if (funcid.function < PCM_GENNAME_SIZE)
2490 				(void) strcpy(info->pd_generic_name,
2491 				    pcmcia_generic_names[funcid.function]);
2492 			else
2493 				(void) sprintf(info->pd_generic_name,
2494 					"class,%x",
2495 					funcid.function);
2496 		}
2497 		info->pd_type = funcid.function;
2498 		switch (funcid.function) {
2499 		case TPLFUNC_LAN:
2500 			which = pcmcia_get_funce(handle, &tuple);
2501 			if (which) {
2502 				i = csx_Parse_CISTPL_FUNCE(handle,
2503 				    &tuple,
2504 				    &funce, TPLFUNC_LAN);
2505 				if (i == SUCCESS) {
2506 					i = funce.data.lan.tech;
2507 					if (i > sizeof (pcmcia_lan_types) /
2508 					    sizeof (char *)) {
2509 						break;
2510 					}
2511 					(void) strcpy(info->pd_generic_name,
2512 						pcmcia_lan_types[i]);
2513 				}
2514 			}
2515 			break;
2516 		case TPLFUNC_VIDEO:
2517 #ifdef future_pcmcia_spec
2518 			which = pcmcia_get_funce(handle, &tuple);
2519 			if (which) {
2520 				i = csx_Parse_CISTPL_FUNCE(handle,
2521 				    &tuple,
2522 				    &funce, TPLFUNC_VIDEO);
2523 				if (i == SUCCESS) {
2524 					i = funce.video.tech;
2525 					if (i > sizeof (pcmcia_lan_types) /
2526 					    sizeof (char *)) {
2527 						break;
2528 					}
2529 					(void) strcpy(info->pd_generic_names,
2530 						pcmcia_lan_types[i]);
2531 				}
2532 			}
2533 #endif
2534 			break;
2535 		}
2536 		info->pd_flags |= PCM_NAME_GENERIC;
2537 	} else {
2538 		/* if no FUNCID, do we have CONFIG */
2539 		tuple.DesiredTuple = CISTPL_CONFIG;
2540 		tuple.Attributes = 0;
2541 		if (csx_GetFirstTuple(handle, &tuple) != SUCCESS) {
2542 			info->pd_flags |= PCM_NO_CONFIG | PCM_NAME_GENERIC;
2543 			(void) strcpy(info->pd_generic_name,
2544 				pcmcia_generic_names[PCM_TYPE_MEMORY]);
2545 			info->pd_type = PCM_TYPE_MEMORY;
2546 		}
2547 	}
2548 }
2549 
2550 
2551 /*
2552  * pcmcia_add_compatible()
2553  * add the cached compatible property list.
2554  */
2555 void
2556 pcmcia_add_compatible(dev_info_t *dip, struct pcm_device_info *info)
2557 {
2558 	int length = 0, i;
2559 	char buff[MAXNAMELEN];
2560 	char *compat_name[8];
2561 	int ci = 0;
2562 
2563 	bzero(compat_name, sizeof (compat_name));
2564 
2565 	if (info->pd_flags & PCM_NAME_VERS1) {
2566 		(void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF,
2567 		    info->pd_vers1_name);
2568 		pcmcia_fix_string(buff); /* don't want spaces */
2569 		length = strlen(buff) + 1;
2570 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2571 		(void) strcpy(compat_name[ci++], buff);
2572 	}
2573 
2574 	if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) ==
2575 	    (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) {
2576 		(void) sprintf(buff, "%s,%x", info->pd_bind_name,
2577 		    info->pd_function);
2578 		length = strlen(buff) + 1;
2579 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2580 		(void) strcpy(compat_name[ci++], buff);
2581 	}
2582 
2583 	if (info->pd_flags & PCM_NAME_1275) {
2584 		length = strlen(info->pd_bind_name) + 1;
2585 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2586 		(void) strcpy(compat_name[ci++], info->pd_bind_name);
2587 	}
2588 
2589 	if (info->pd_flags & PCM_NAME_GENERIC) {
2590 		if (strncmp(info->pd_generic_name, "class,", 6) == 0) {
2591 			/* no generic without "pccard" */
2592 			(void) sprintf(buff, "%s%s", PCMDEV_NAMEPREF,
2593 				info->pd_generic_name);
2594 		} else {
2595 			/* first pccard,generic-name */
2596 			(void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF,
2597 				info->pd_generic_name);
2598 		}
2599 		length = strlen(buff) + 1;
2600 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2601 		(void) strcpy(compat_name[ci++], buff);
2602 
2603 		/* now the simple generic name */
2604 		length = strlen(info->pd_generic_name) + 1;
2605 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2606 		(void) strcpy(compat_name[ci++], info->pd_generic_name);
2607 	}
2608 
2609 	if (info->pd_flags & PCM_NO_CONFIG) {
2610 		char *mem = "pccard,memory";
2611 		/*
2612 		 * I/O cards are required to have a config tuple.
2613 		 * there are some that violate the spec and don't
2614 		 * but it is most likely that this is a memory card
2615 		 * so tag it as such.  "memory" is more general
2616 		 * than other things so needs to come last.
2617 		 */
2618 		length = strlen(mem) + 1;
2619 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2620 		(void) strcpy(compat_name[ci++], mem);
2621 	}
2622 
2623 	if (ci == 0)
2624 		return;
2625 
2626 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
2627 	    "compatible", (char **)compat_name, ci) != DDI_PROP_SUCCESS)
2628 		cmn_err(CE_WARN, "pcmcia: unable to create compatible prop");
2629 
2630 	for (i = 0; i < ci; i++)
2631 		kmem_free(compat_name[i], strlen(compat_name[i]) + 1);
2632 }
2633 /*
2634  * CIS parsing and other PC Card specific code
2635  */
2636 
2637 /*
2638  * pcmcia_get_mem_regs()
2639  */
2640 static int
2641 pcmcia_get_mem_regs(struct pcm_regs *regs, struct pcm_device_info *info,
2642 			int type, int pctype)
2643 {
2644 	int num_regs = 0;
2645 	tuple_t tuple;
2646 	cistpl_device_t device;
2647 	uint32_t curr_base;
2648 	int ret, len;
2649 	int space;
2650 
2651 	/*
2652 	 * current plan for reg spec:
2653 	 * device_a will be accumulated to determine max size of
2654 	 * attribute memory.  device for common.  Then config
2655 	 * tuples to get a worst case I/O size.
2656 	 */
2657 	bzero(&tuple, sizeof (tuple));
2658 	tuple.Socket = info->pd_socket;
2659 
2660 	tuple.DesiredTuple = (cisdata_t)type;
2661 
2662 	space = (type == CISTPL_DEVICE_A) ? PC_REG_SPACE_ATTRIBUTE :
2663 		PC_REG_SPACE_MEMORY;
2664 	if ((ret = csx_GetFirstTuple(info->pd_handle, &tuple)) == CS_SUCCESS) {
2665 		bzero(&device, sizeof (device));
2666 
2667 		if (type == CISTPL_DEVICE)
2668 			ret = csx_Parse_CISTPL_DEVICE(info->pd_handle, &tuple,
2669 			    &device);
2670 		else
2671 			ret = csx_Parse_CISTPL_DEVICE_A(info->pd_handle, &tuple,
2672 			    &device);
2673 
2674 		if (ret == CS_SUCCESS) {
2675 		    curr_base = 0;
2676 		    for (ret = 0; ret < device.num_devices;
2677 			ret++) {
2678 			    /* need to order these for real mem first */
2679 			    if (device.devnode[ret].type !=
2680 				CISTPL_DEVICE_DTYPE_NULL) {
2681 				    /* how to represent types??? */
2682 				    regs[num_regs].phys_hi =
2683 					PC_REG_PHYS_HI(0, 0,
2684 					    pctype,
2685 					    space,
2686 					    info->pd_socket,
2687 					    info->pd_function,
2688 					    0);
2689 				    regs[num_regs].phys_lo = curr_base;
2690 				    len = device.devnode[ret].size_in_bytes;
2691 				    curr_base += len;
2692 				    regs[num_regs].phys_len = len;
2693 				    num_regs++;
2694 			    } else {
2695 				/*
2696 				 * NULL device is a "hole"
2697 				 */
2698 				    curr_base +=
2699 					    device.devnode[ret].size_in_bytes;
2700 			    }
2701 			}
2702 	    }
2703 	}
2704 	return (num_regs);
2705 }
2706 
2707 /*
2708  *
2709  */
2710 static int
2711 pcmcia_get_io_regs(struct pcm_regs *regs, struct pcm_device_info *info,
2712 		    int pctype)
2713 {
2714 	int num_regs = 0;
2715 	tuple_t tuple;
2716 	uint32_t curr_base;
2717 	int len, curr, i, curr_len;
2718 	cistpl_config_t config;
2719 	cistpl_cftable_entry_t cftable;
2720 	struct pcm_regs tmp[16];
2721 	int found = 0;
2722 
2723 	bzero(&tuple, sizeof (tuple));
2724 	tuple.DesiredTuple = CISTPL_CONFIG;
2725 	tuple.Socket = info->pd_socket;
2726 	tuple.Attributes = 0;
2727 	curr_base = 0;
2728 	len = 0;
2729 
2730 	if (csx_GetFirstTuple(info->pd_handle, &tuple) == CS_SUCCESS) {
2731 	    if (csx_Parse_CISTPL_CONFIG(info->pd_handle,
2732 					&tuple, &config) != CS_SUCCESS) {
2733 		info->pd_flags |= PCM_NO_CONFIG; /* must be memory */
2734 		return (0);
2735 	}
2736 	curr = 0;
2737 
2738 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
2739 	tuple.Socket = info->pd_socket;
2740 	tuple.Attributes = 0;
2741 	bzero(tmp, sizeof (tmp));
2742 	while (csx_GetNextTuple(info->pd_handle,
2743 				&tuple) == CS_SUCCESS) {
2744 	    bzero(&cftable, sizeof (cftable));
2745 	    if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle,
2746 						&tuple, &cftable) ==
2747 		CS_SUCCESS) {
2748 		if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IO) {
2749 		    /* we have an I/O entry */
2750 		    if (cftable.io.flags &
2751 			CISTPL_CFTABLE_TPCE_FS_IO_RANGE) {
2752 			len = cftable.io.addr_lines;
2753 			if (len != 0)
2754 				len = 1 << len;
2755 			for (i = 0; i < cftable.io.ranges && curr < 16; i++) {
2756 			    curr_base = cftable.io.range[i].addr;
2757 			    curr_len = cftable.io.range[i].length;
2758 			    if (curr_len == 0)
2759 				    curr_len = len;
2760 			    if (len != 0 || cftable.io.addr_lines == 0) {
2761 				/* we have potential relocation */
2762 				int mask;
2763 				mask = cftable.io.addr_lines ?
2764 						cftable.io.addr_lines :
2765 							genp2(len);
2766 				mask = genmask(mask);
2767 				if ((mask & curr_base) == 0) {
2768 					/* more accurate length */
2769 					regs->phys_len = curr_len;
2770 					regs->phys_lo = 0;
2771 					regs->phys_hi =
2772 					    PC_REG_PHYS_HI(0,
2773 						0,
2774 						pctype,
2775 						PC_REG_SPACE_IO,
2776 						info->pd_socket,
2777 						info->pd_function,
2778 						0);
2779 					num_regs++;
2780 					found = 2;
2781 					break;
2782 				}
2783 			    }
2784 			    tmp[curr].phys_len = curr_len;
2785 			    tmp[curr].phys_lo = curr_base;
2786 			    curr++;
2787 			    found = 1;
2788 			}
2789 			if (found == 2)
2790 				break;
2791 		    } else {
2792 			/* no I/O range so just a mask */
2793 			regs->phys_len = 1 << cftable.io.addr_lines;
2794 			regs->phys_hi =
2795 				PC_REG_PHYS_HI(0,
2796 						0,
2797 						pctype,
2798 						PC_REG_SPACE_IO,
2799 						info->pd_socket,
2800 						info->pd_function,
2801 						0);
2802 			regs->phys_lo = 0;
2803 			num_regs++;
2804 			regs++;
2805 			/* quit on "good" entry */
2806 			break;
2807 		    }
2808 		    /* was this the last CFTABLE Entry? */
2809 		    if (config.last == cftable.index)
2810 			    break;
2811 		}
2812 	    }
2813 	}
2814 	if (found == 1) {
2815 		/*
2816 		 * have some non-relocatable values
2817 		 * so we include them all for now
2818 		 */
2819 		for (i = 0; i < curr && num_regs < 8; i++) {
2820 		    regs->phys_len = tmp[i].phys_len;
2821 		    regs->phys_lo = tmp[i].phys_lo;
2822 		    regs->phys_hi = PC_REG_PHYS_HI(1, 0, pctype,
2823 			    PC_REG_SPACE_IO, info->pd_socket,
2824 			    info->pd_function, 0);
2825 		    regs++;
2826 		    num_regs++;
2827 		}
2828 	    }
2829 	}
2830 	return (num_regs);
2831 }
2832 
2833 /*
2834  * pcmcia_create_regs()
2835  *	create a valid set of regspecs for the card
2836  *	The first one is always for CIS access and naming
2837  */
2838 /*ARGSUSED*/
2839 static void
2840 pcmcia_find_regs(dev_info_t *dip, struct pcm_device_info *info,
2841 			struct pcmcia_parent_private *ppd)
2842 {
2843 	struct pcm_regs regs[32]; /* assume worst case */
2844 	int num_regs = 0;
2845 	int len;
2846 	int bustype;
2847 
2848 	if (ppd->ppd_flags & PPD_CARD_CARDBUS) {
2849 		/* always have a CIS map */
2850 		regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_CARDBUS,
2851 						PC_REG_SPACE_CONFIG,
2852 						info->pd_socket,
2853 						info->pd_function, 0);
2854 		bustype = PC_REG_TYPE_CARDBUS;
2855 	} else {
2856 		/* always have a CIS map */
2857 		regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT,
2858 						PC_REG_SPACE_ATTRIBUTE,
2859 						info->pd_socket,
2860 						info->pd_function, 0);
2861 		bustype = PC_REG_TYPE_16BIT;
2862 	}
2863 	regs[0].phys_lo = 0;	/* always starts at zero */
2864 	regs[0].phys_len = 0;
2865 	num_regs++;
2866 	/*
2867 	 * need to search CIS for other memory instances
2868 	 */
2869 
2870 	if (info->pd_flags & PCM_OTHER_NOCIS) {
2871 		/* special case of memory only card without CIS */
2872 		regs[1].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT,
2873 						PC_REG_SPACE_MEMORY,
2874 						info->pd_socket,
2875 						info->pd_function, 0);
2876 		regs[1].phys_lo = 0;
2877 		regs[1].phys_len = PCM_MAX_R2_MEM;
2878 		num_regs++;
2879 	} else {
2880 		/*
2881 		 * want to get any other memory and/or I/O regions
2882 		 * on the card and represent them here.
2883 		 */
2884 		num_regs += pcmcia_get_mem_regs(&regs[num_regs], info,
2885 						CISTPL_DEVICE_A, bustype);
2886 		num_regs += pcmcia_get_mem_regs(&regs[num_regs], info,
2887 						CISTPL_DEVICE, bustype);
2888 
2889 		/* now look for an I/O space to configure */
2890 		num_regs += pcmcia_get_io_regs(&regs[num_regs], info,
2891 						bustype);
2892 
2893 	}
2894 
2895 	len = num_regs * sizeof (uint32_t) * 3;
2896 	ppd->ppd_nreg = num_regs;
2897 	ppd->ppd_reg = kmem_alloc(len, KM_SLEEP);
2898 	bcopy(regs, ppd->ppd_reg, len);
2899 	len = sizeof (struct pcm_regs) * ppd->ppd_nreg;
2900 	ppd->ppd_assigned = kmem_zalloc(len, KM_SLEEP);
2901 }
2902 
2903 
2904 /*
2905  * pcmcia_need_intr()
2906  *	check to see if an interrupt tuple exists.
2907  *	existence means we need one in the intrspec.
2908  */
2909 static int
2910 pcmcia_need_intr(int socket, struct pcm_device_info *info)
2911 {
2912 	cistpl_config_t config;
2913 	cistpl_cftable_entry_t cftable;
2914 	tuple_t tuple;
2915 	int i;
2916 
2917 	bzero(&tuple, sizeof (tuple));
2918 	tuple.DesiredTuple = CISTPL_CONFIG;
2919 	tuple.Socket = socket;
2920 	tuple.Attributes = 0;
2921 	if (csx_GetFirstTuple(info->pd_handle, &tuple) != CS_SUCCESS) {
2922 		return (0);
2923 	}
2924 #if defined(PCMCIA_DEBUG)
2925 	if (pcmcia_debug) {
2926 		cmn_err(CE_CONT, "pcmcia_need_intr: have config tuple\n");
2927 	}
2928 #endif
2929 	bzero(&config, sizeof (config));
2930 	if (csx_Parse_CISTPL_CONFIG(info->pd_handle,
2931 	    &tuple, &config) != CS_SUCCESS) {
2932 		cmn_err(CE_WARN, "pcmcia: config failed to parse\n");
2933 		return (0);
2934 	}
2935 
2936 	for (cftable.index = (int)-1, i = -1;
2937 		i != config.last; i = cftable.index) {
2938 		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
2939 		tuple.Attributes = 0;
2940 		if (csx_GetNextTuple(info->pd_handle,
2941 		    &tuple) != CS_SUCCESS) {
2942 			cmn_err(CE_WARN, "pcmcia: get cftable failed\n");
2943 			break;
2944 		}
2945 		bzero(&cftable, sizeof (cftable));
2946 		if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle,
2947 		    &tuple, &cftable) !=
2948 		    CS_SUCCESS) {
2949 			cmn_err(CE_WARN, "pcmcia: parse cftable failed\n");
2950 			break;
2951 		}
2952 #if defined(PCMCIA_DEBUG)
2953 		if (pcmcia_debug)
2954 			cmn_err(CE_CONT, "\t%x: flags=%x (%x)\n",
2955 				i, cftable.flags,
2956 				cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ);
2957 #endif
2958 		if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ)
2959 			return (1);
2960 	}
2961 	return (0);
2962 
2963 }
2964 
2965 /*
2966  * pcmcia_num_funcs()
2967  *	look for a CISTPL_LONGLINK_MFC
2968  *	if there is one, return the number of functions
2969  *	if there isn't one, then there is one function
2970  */
2971 static int
2972 pcmcia_num_funcs(int socket, client_handle_t handle)
2973 {
2974 	int count = 1;
2975 	cistpl_longlink_mfc_t mfc;
2976 	tuple_t tuple;
2977 
2978 	bzero(&tuple, sizeof (tuple_t));
2979 	tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
2980 	tuple.Socket = socket;
2981 	tuple.Attributes = 0;
2982 	if (csx_GetFirstTuple(handle, &tuple) == CS_SUCCESS) {
2983 		/* this is a multifunction card */
2984 		if (csx_ParseTuple(handle, &tuple, (cisparse_t *)&mfc,
2985 		    CISTPL_LONGLINK_MFC) == CS_SUCCESS) {
2986 			count = mfc.nfuncs;
2987 		}
2988 	}
2989 	return (count);
2990 }
2991 
2992 client_handle_t pcmcia_cs_handle;
2993 
2994 /*
2995  * pcmcia_create_dev_info(socket)
2996  *	either find or create the device information structure
2997  *	for the card(s) just inserted.	We don't care about removal yet.
2998  *	In any case, we will only do this at CS request
2999  */
3000 static void
3001 pcmcia_create_dev_info(int socket)
3002 {
3003 	struct pcm_device_info card_info;
3004 	client_reg_t reg;
3005 	cisinfo_t cisinfo;
3006 	int i;
3007 	dev_info_t *pdip;
3008 	static int handle_def = 0;
3009 
3010 #if defined(PCMCIA_DEBUG)
3011 	if (pcmcia_debug)
3012 		cmn_err(CE_CONT, "create dev_info_t for device in socket %d\n",
3013 			socket);
3014 #endif
3015 
3016 	/*
3017 	 * before we can do anything else, we need the parent
3018 	 * devinfo of the socket.  This gets things in the right
3019 	 * place in the device tree.
3020 	 */
3021 
3022 	pdip = pcm_find_parent_dip(socket);
3023 	if (pdip == NULL)
3024 		return;
3025 
3026 	/* Card Services calls needed to get CIS info */
3027 	reg.dip = NULL;
3028 	reg.Attributes = INFO_SOCKET_SERVICES;
3029 	reg.EventMask = 0;
3030 	reg.event_handler = NULL;
3031 	reg.Version = CS_VERSION;
3032 
3033 	bzero(&card_info, sizeof (card_info));
3034 
3035 	if (handle_def == 0) {
3036 		if (csx_RegisterClient(&pcmcia_cs_handle,
3037 		    &reg) != CS_SUCCESS) {
3038 #if defined(PCMCIA_DEBUG)
3039 			if (pcmcia_debug)
3040 				cmn_err(CE_CONT,
3041 					"pcmcia: RegisterClient failed\n");
3042 #endif
3043 			return;
3044 		}
3045 		handle_def++;
3046 	}
3047 	card_info.pd_handle = pcmcia_cs_handle;
3048 
3049 #if defined(PCMCIA_DEBUG)
3050 	if (pcmcia_debug)
3051 		cmn_err(CE_CONT,
3052 			"pcmcia_create_dev_info: handle = %x\n",
3053 			(int)card_info.pd_handle);
3054 #endif
3055 	card_info.pd_type = -1; /* no type to start */
3056 	card_info.pd_socket = socket;
3057 	card_info.pd_function = 0;
3058 	pcmcia_sockets[socket]->ls_functions = 1; /* default */
3059 
3060 	cisinfo.Socket = socket;
3061 
3062 	if ((i = csx_ValidateCIS(card_info.pd_handle,
3063 	    &cisinfo)) != SUCCESS ||
3064 	    cisinfo.Tuples == 0) {
3065 		/* no CIS means memory */
3066 		(void) strcpy(card_info.pd_generic_name, "memory");
3067 		card_info.pd_flags |= PCM_NAME_GENERIC |
3068 			PCM_OTHER_NOCIS | PCM_NAME_1275;
3069 		(void) strcpy(card_info.pd_bind_name, "pccard,memory");
3070 		(void) strcpy(card_info.pd_generic_name, "memory");
3071 		card_info.pd_type = PCM_TYPE_MEMORY;
3072 	} else {
3073 		int functions, lsocket;
3074 		card_info.pd_tuples = cisinfo.Tuples;
3075 
3076 		/*
3077 		 * how many functions on the card?
3078 		 * we need to know and then we do one
3079 		 * child node for each function using
3080 		 * the function specific tuples.
3081 		 */
3082 		lsocket = CS_MAKE_SOCKET_NUMBER(socket, CS_GLOBAL_CIS);
3083 		functions = pcmcia_num_funcs(lsocket,
3084 		    card_info.pd_handle);
3085 		pcmcia_sockets[socket]->ls_functions = functions;
3086 		if (functions > 1) {
3087 			card_info.pd_flags |= PCM_MULTI_FUNCTION;
3088 		}
3089 		for (i = 0; i < functions; i++) {
3090 		    register int flags;
3091 		    lsocket = CS_MAKE_SOCKET_NUMBER(socket, i);
3092 		    card_info.pd_socket = socket;
3093 		    card_info.pd_function = i;
3094 			/*
3095 			 * new name construction
3096 			 */
3097 		    if (functions != 1) {
3098 			    /* need per function handle */
3099 			    card_info.pd_function = i;
3100 			    /* get new handle */
3101 		    }
3102 		    pcmcia_1275_name(lsocket, &card_info,
3103 			card_info.pd_handle);
3104 		    pcmcia_vers1_name(lsocket, &card_info,
3105 			card_info.pd_handle);
3106 		    pcmcia_generic_name(lsocket, &card_info,
3107 			card_info.pd_handle);
3108 		    flags = card_info.pd_flags;
3109 		    if (!(flags & PCM_NAME_1275)) {
3110 			if (flags & PCM_NAME_VERS1) {
3111 			    (void) strcpy(card_info.pd_bind_name,
3112 				PCMDEV_NAMEPREF);
3113 			    card_info.pd_bind_name[sizeof (PCMDEV_NAMEPREF)] =
3114 				',';
3115 			    (void) strncpy(card_info.pd_bind_name +
3116 				sizeof (PCMDEV_NAMEPREF),
3117 				card_info.pd_vers1_name,
3118 				MODMAXNAMELEN -
3119 				sizeof (PCMDEV_NAMEPREF));
3120 			    pcmcia_fix_string(card_info.pd_bind_name);
3121 			} else {
3122 				/*
3123 				 * have a CIS but not the right info
3124 				 * so treat as generic "pccard"
3125 				 */
3126 				(void) strcpy(card_info.pd_generic_name,
3127 					"pccard,memory");
3128 				card_info.pd_flags |= PCM_NAME_GENERIC;
3129 				(void) strcpy(card_info.pd_bind_name,
3130 					"pccard,memory");
3131 			}
3132 		    }
3133 		    pcmcia_init_devinfo(pdip, &card_info);
3134 		}
3135 		return;
3136 	}
3137 
3138 	pcmcia_init_devinfo(pdip, &card_info);
3139 }
3140 
3141 /*
3142  * pcmcia_init_devinfo()
3143  *	if there isn't a device info structure, create one
3144  *	if there is, we don't do much.
3145  *
3146  *	Note: this will need updating as 1275 finalizes their spec.
3147  */
3148 static void
3149 pcmcia_init_devinfo(dev_info_t *pdip, struct pcm_device_info *info)
3150 {
3151 	int unit;
3152 	dev_info_t *dip;
3153 	char *name;
3154 	struct pcmcia_parent_private *ppd;
3155 
3156 #if defined(PCMCIA_DEBUG)
3157 	if (pcmcia_debug)
3158 		cmn_err(CE_CONT, "init_devinfo(%s, %d)\n", info->pd_bind_name,
3159 			info->pd_socket);
3160 #endif
3161 
3162 	/*
3163 	 * find out if there is already an instance of this
3164 	 * device.  We don't want to create a new one unnecessarily
3165 	 */
3166 	unit = CS_MAKE_SOCKET_NUMBER(info->pd_socket, info->pd_function);
3167 
3168 	dip = pcm_find_devinfo(pdip, info, unit);
3169 	if ((dip != NULL) && (ddi_getprop(DDI_DEV_T_NONE, dip,
3170 	    DDI_PROP_DONTPASS, PCM_DEV_SOCKET, -1) != -1)) {
3171 		/* it already exist but isn't a .conf file */
3172 
3173 #if defined(PCMCIA_DEBUG)
3174 		if (pcmcia_debug)
3175 			cmn_err(CE_CONT, "\tfound existing device node (%s)\n",
3176 				ddi_get_name(dip));
3177 #endif
3178 		if (strlen(info->pd_vers1_name) > 0)
3179 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
3180 			    dip, PCM_DEV_MODEL, info->pd_vers1_name);
3181 
3182 		ppd = (struct pcmcia_parent_private *)
3183 			ddi_get_parent_data(dip);
3184 
3185 		pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] =
3186 		    dip;
3187 
3188 		ppd->ppd_active = 1;
3189 
3190 		if (ndi_devi_online(dip, 0) == NDI_FAILURE) {
3191 			pcmcia_sockets[info->pd_socket]-> \
3192 			    ls_dip[info->pd_function] = NULL;
3193 			ppd->ppd_active = 0;
3194 		}
3195 	} else {
3196 
3197 		char *dtype;
3198 
3199 #if defined(PCMCIA_DEBUG)
3200 		if (pcmcia_debug)
3201 			cmn_err(CE_CONT, "pcmcia: create child [%s](%d): %s\n",
3202 			    info->pd_bind_name, info->pd_socket,
3203 			    info->pd_generic_name);
3204 #endif
3205 
3206 		if (info->pd_flags & PCM_NAME_GENERIC)
3207 			name = info->pd_generic_name;
3208 		else
3209 			name = info->pd_bind_name;
3210 
3211 		if (ndi_devi_alloc(pdip, name, (pnode_t)DEVI_SID_NODEID,
3212 		    &dip) !=
3213 		    NDI_SUCCESS) {
3214 			cmn_err(CE_WARN,
3215 			    "pcmcia: unable to create device [%s](%d)\n",
3216 			    name, info->pd_socket);
3217 			return;
3218 		}
3219 		/*
3220 		 * construct the "compatible" property if the device
3221 		 * has a generic name
3222 		 */
3223 		pcmcia_add_compatible(dip, info);
3224 
3225 		ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private),
3226 			    KM_SLEEP);
3227 
3228 		ppd->ppd_socket = info->pd_socket;
3229 		ppd->ppd_function = info->pd_function;
3230 
3231 		/*
3232 		 * add the "socket" property
3233 		 * the value of this property contains the logical PCMCIA
3234 		 * socket number the device has been inserted in, along
3235 		 * with the function # if the device is part of a
3236 		 * multi-function device.
3237 		 */
3238 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3239 		    PCM_DEV_SOCKET, unit);
3240 
3241 		if (info->pd_flags & PCM_MULTI_FUNCTION)
3242 			ppd->ppd_flags |= PPD_CARD_MULTI;
3243 
3244 		/*
3245 		 * determine all the properties we need for PPD
3246 		 * then create the properties
3247 		 */
3248 		/* socket is unique */
3249 		pcmcia_find_regs(dip, info, ppd);
3250 
3251 		ppd->ppd_intr = pcmcia_need_intr(unit, info);
3252 
3253 		if (ppd->ppd_nreg > 0)
3254 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3255 			    "reg", (int *)ppd->ppd_reg, ppd->ppd_nreg *
3256 			    sizeof (struct pcm_regs) / sizeof (int));
3257 		if (ppd->ppd_intr) {
3258 			(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
3259 			    "interrupts", ppd->ppd_intr);
3260 			ppd->ppd_intrspec =
3261 			    kmem_zalloc(sizeof (struct intrspec), KM_SLEEP);
3262 		}
3263 
3264 		/* set parent private - our own format */
3265 		ddi_set_parent_data(dip, (caddr_t)ppd);
3266 
3267 		/* init the device type */
3268 		if (info->pd_type >= 0 &&
3269 		    info->pd_type < (sizeof (pcmcia_dev_type) /
3270 		    (sizeof (char *))))
3271 			dtype = pcmcia_dev_type[info->pd_type];
3272 		else
3273 			dtype = "unknown";
3274 
3275 		if (strlen(info->pd_vers1_name) > 0)
3276 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
3277 			    dip, PCM_DEV_MODEL, info->pd_vers1_name);
3278 
3279 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3280 		    PCM_DEVICETYPE, dtype);
3281 
3282 		/* set PC Card as active and present in socket */
3283 		pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] =
3284 			dip;
3285 
3286 		ppd->ppd_active = 1;
3287 
3288 		/*
3289 		 * We should not call ndi_devi_online here if
3290 		 * pcmcia attach is in progress. This causes a deadlock.
3291 		 */
3292 		if (pcmcia_dip != dip) {
3293 			if (ndi_devi_online_async(dip, 0)
3294 			    != NDI_SUCCESS) {
3295 				pcmcia_sockets[info->pd_socket]->\
3296 				ls_dip[info->pd_function] = NULL;
3297 				pcmcia_ppd_free(ppd);
3298 				(void) ndi_devi_free(dip);
3299 				return;
3300 			}
3301 		}
3302 
3303 #if defined(PCMCIA_DEBUG)
3304 	if (pcmcia_debug)
3305 		cmn_err(CE_CONT, "\tjust added \"active\" to %s in %d\n",
3306 			ddi_get_name(dip), info->pd_socket);
3307 #endif
3308 	}
3309 
3310 	/*
3311 	 * inform the event manager that a child was added
3312 	 * to the device tree.
3313 	 */
3314 	pcm_event_manager(PCE_DEV_IDENT, unit, ddi_get_name(dip));
3315 
3316 #if defined(PCMCIA_DEBUG)
3317 	if (pcmcia_debug > 1) {
3318 		pcmcia_dump_minors(dip);
3319 	}
3320 #endif
3321 }
3322 
3323 /*
3324  * free any allocated parent-private data
3325  */
3326 static void
3327 pcmcia_ppd_free(struct pcmcia_parent_private *ppd)
3328 {
3329 	size_t len;
3330 
3331 	if (ppd->ppd_nreg != 0) {
3332 		len = ppd->ppd_nreg * sizeof (uint32_t) * 3;
3333 		kmem_free(ppd->ppd_reg, len);
3334 		len = sizeof (struct pcm_regs) * ppd->ppd_nreg;
3335 		kmem_free(ppd->ppd_assigned, len);
3336 	}
3337 
3338 	/*
3339 	 * pcmcia only allocates 1 intrspec today
3340 	 */
3341 	if (ppd->ppd_intr != 0) {
3342 		len = sizeof (struct intrspec) * ppd->ppd_intr;
3343 		kmem_free(ppd->ppd_intrspec, len);
3344 	}
3345 
3346 	kmem_free(ppd, sizeof (*ppd));
3347 }
3348 
3349 
3350 /*
3351  * pcmcia_get_devinfo(socket)
3352  *	entry point to allow finding the device info structure
3353  *	for a given logical socket.  Used by event manager
3354  */
3355 dev_info_t *
3356 pcmcia_get_devinfo(int socket)
3357 {
3358 	int func = CS_GET_FUNCTION_NUMBER(socket);
3359 	socket = CS_GET_SOCKET_NUMBER(socket);
3360 	if (pcmcia_sockets[socket])
3361 		return (pcmcia_sockets[socket]->ls_dip[func]);
3362 	return ((dev_info_t *)NULL);
3363 }
3364 
3365 /*
3366  * CSGetCookiesAndDip()
3367  *	get info needed by CS to setup soft interrupt handler and provide
3368  *		socket-specific adapter information
3369  */
3370 static int
3371 GetCookiesAndDip(sservice_t *serv)
3372 {
3373 	pcmcia_logical_socket_t *socket;
3374 	csss_adapter_info_t *ai;
3375 	int sock;
3376 
3377 	sock = CS_GET_SOCKET_NUMBER(serv->get_cookies.socket);
3378 
3379 	if (sock >= pcmcia_num_sockets ||
3380 	    (int)serv->get_cookies.socket < 0)
3381 		return (BAD_SOCKET);
3382 
3383 	socket = pcmcia_sockets[sock];
3384 	ai = &serv->get_cookies.adapter_info;
3385 	serv->get_cookies.dip = socket->ls_adapter->pca_dip;
3386 	serv->get_cookies.iblock = socket->ls_adapter->pca_iblock;
3387 	serv->get_cookies.idevice = socket->ls_adapter->pca_idev;
3388 
3389 	/*
3390 	 * Setup the adapter info for Card Services
3391 	 */
3392 	(void) strcpy(ai->name, socket->ls_adapter->pca_name);
3393 	ai->major = socket->ls_adapter->pca_module;
3394 	ai->minor = socket->ls_adapter->pca_unit;
3395 	ai->number = socket->ls_adapter->pca_number;
3396 	ai->num_sockets = socket->ls_adapter->pca_numsockets;
3397 	ai->first_socket = socket->ls_adapter->pca_first_socket;
3398 
3399 	return (SUCCESS);
3400 }
3401 
3402 /*
3403  * Note:
3404  *	The following functions that start with 'SS'
3405  *	implement SocketServices interfaces.  They
3406  *	simply map the socket and/or window number to
3407  *	the adapter specific number based on the general
3408  *	value that CardServices uses.
3409  *
3410  *	See the descriptions in SocketServices for
3411  *	details.  Also refer to specific adapter drivers
3412  *	for implementation reference.
3413  */
3414 
3415 static int
3416 SSGetAdapter(get_adapter_t *adapter)
3417 {
3418 	int n;
3419 	get_adapter_t info;
3420 
3421 	adapter->state = (unsigned)0xFFFFFFFF;
3422 	adapter->SCRouting = 0xFFFFFFFF;
3423 
3424 	for (n = 0; n < pcmcia_num_adapters; n++) {
3425 		GET_ADAPTER(pcmcia_adapters[n]->pca_if,
3426 			pcmcia_adapters[n]->pca_dip, &info);
3427 		adapter->state &= info.state;
3428 		adapter->SCRouting &= info.SCRouting;
3429 	}
3430 
3431 	return (SUCCESS);
3432 }
3433 
3434 static int
3435 SSGetPage(get_page_t *page)
3436 {
3437 	pcmcia_logical_window_t *window;
3438 	get_page_t newpage;
3439 	int retval, win;
3440 
3441 	if (page->window > pcmcia_num_windows) {
3442 		return (BAD_WINDOW);
3443 	}
3444 
3445 	window = pcmcia_windows[page->window];
3446 	newpage = *page;
3447 	win = newpage.window = window->lw_window; /* real window */
3448 
3449 	retval = GET_PAGE(window->lw_if, window->lw_adapter->pca_dip,
3450 		&newpage);
3451 	if (retval == SUCCESS) {
3452 		*page = newpage;
3453 		page->window = win;
3454 	}
3455 	return (retval);
3456 }
3457 
3458 static int
3459 SSGetSocket(get_socket_t *socket)
3460 {
3461 	int retval, sock;
3462 	get_socket_t newsocket;
3463 	pcmcia_logical_socket_t *sockp;
3464 
3465 	sock = socket->socket;
3466 	if (sock > pcmcia_num_sockets ||
3467 		(sockp = pcmcia_sockets[sock]) == NULL) {
3468 		return (BAD_SOCKET);
3469 	}
3470 
3471 	newsocket = *socket;
3472 	newsocket.socket = sockp->ls_socket;
3473 	retval = GET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip,
3474 	    &newsocket);
3475 	if (retval == SUCCESS) {
3476 		newsocket.VccLevel = pcmcia_map_power_get(sockp->ls_adapter,
3477 		    newsocket.VccLevel,
3478 		    VCC);
3479 		newsocket.Vpp1Level = pcmcia_map_power_get(sockp->ls_adapter,
3480 		    newsocket.Vpp1Level,
3481 		    VPP1);
3482 		newsocket.Vpp2Level = pcmcia_map_power_get(sockp->ls_adapter,
3483 		    newsocket.Vpp2Level,
3484 		    VPP2);
3485 		*socket = newsocket;
3486 		socket->socket = sock;
3487 	}
3488 
3489 	return (retval);
3490 }
3491 
3492 static int
3493 SSGetStatus(get_ss_status_t *status)
3494 {
3495 	get_ss_status_t newstat;
3496 	int sock, retval;
3497 	pcmcia_logical_socket_t *sockp;
3498 
3499 	sock = status->socket;
3500 	if (sock > pcmcia_num_sockets ||
3501 		(sockp = pcmcia_sockets[sock]) == NULL) {
3502 		return (BAD_SOCKET);
3503 	}
3504 
3505 	newstat = *status;
3506 	newstat.socket = sockp->ls_socket;
3507 	retval = GET_STATUS(sockp->ls_if, sockp->ls_adapter->pca_dip,
3508 	    &newstat);
3509 	if (retval == SUCCESS) {
3510 		*status = newstat;
3511 		status->socket = sock;
3512 	}
3513 
3514 	return (retval);
3515 }
3516 
3517 static int
3518 SSGetWindow(get_window_t *window)
3519 {
3520 	int win, retval;
3521 	get_window_t newwin;
3522 	pcmcia_logical_window_t *winp;
3523 
3524 	win = window->window;
3525 	winp = pcmcia_windows[win];
3526 	newwin = *window;
3527 	newwin.window = winp->lw_window;
3528 
3529 	retval = GET_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip,
3530 	    &newwin);
3531 	if (retval == SUCCESS) {
3532 		newwin.socket = winp->lw_socket;
3533 		newwin.window = win;
3534 		*window = newwin;
3535 	}
3536 	return (retval);
3537 }
3538 
3539 /*
3540  * SSInquireAdapter()
3541  *	Get the capabilities of the "generic" adapter
3542  *	we are exporting to CS.
3543  */
3544 static int
3545 SSInquireAdapter(inquire_adapter_t *adapter)
3546 {
3547 	adapter->NumSockets = pcmcia_num_sockets;
3548 	adapter->NumWindows = pcmcia_num_windows;
3549 	adapter->NumEDCs = 0;
3550 	/*
3551 	 * notes: Adapter Capabilities are going to be difficult to
3552 	 * determine with reliability.	Fortunately, most of them
3553 	 * don't matter under Solaris or can be handled transparently
3554 	 */
3555 	adapter->AdpCaps = 0;	/* need to fix these */
3556 	/*
3557 	 * interrupts need a little work.  For x86, the valid IRQs will
3558 	 * be restricted to those that the system has exported to the nexus.
3559 	 * for SPARC, it will be the DoRight values.
3560 	 */
3561 	adapter->ActiveHigh = 0;
3562 	adapter->ActiveLow = 0;
3563 	adapter->power_entry = pcmcia_power_table; /* until we resolve this */
3564 	adapter->NumPower = pcmcia_num_power;
3565 	return (SUCCESS);
3566 }
3567 
3568 static int
3569 SSInquireSocket(inquire_socket_t *socket)
3570 {
3571 	int retval, sock;
3572 	inquire_socket_t newsocket;
3573 	pcmcia_logical_socket_t *sockp;
3574 
3575 	sock = socket->socket;
3576 	if (sock > pcmcia_num_sockets ||
3577 		(sockp = pcmcia_sockets[sock]) == NULL)
3578 		return (BAD_SOCKET);
3579 	newsocket = *socket;
3580 	newsocket.socket = sockp->ls_socket;
3581 	retval = INQUIRE_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip,
3582 	    &newsocket);
3583 	if (retval == SUCCESS) {
3584 		*socket = newsocket;
3585 		socket->socket = sock;
3586 	}
3587 	return (retval);
3588 }
3589 
3590 static int
3591 SSInquireWindow(inquire_window_t *window)
3592 {
3593 	int retval, win;
3594 	pcmcia_logical_window_t *winp;
3595 	inquire_window_t newwin;
3596 	int slide;
3597 
3598 	win = window->window;
3599 	if (win > pcmcia_num_windows)
3600 		return (BAD_WINDOW);
3601 
3602 	winp = pcmcia_windows[win];
3603 	newwin = *window;
3604 	newwin.window = winp->lw_window;
3605 	retval = INQUIRE_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip,
3606 	    &newwin);
3607 #if defined(PCMCIA_DEBUG)
3608 		if (pcmcia_debug > 1)
3609 			cmn_err(CE_CONT, "SSInquireWindow: win=%d, pwin=%d\n",
3610 				win, newwin.window);
3611 #endif
3612 	if (retval == SUCCESS) {
3613 		*window = newwin;
3614 		/* just in case */
3615 		window->iowin_char.IOWndCaps &= ~WC_BASE;
3616 		slide = winp->lw_adapter->pca_first_socket;
3617 		/*
3618 		 * note that sockets are relative to the adapter.
3619 		 * we have to adjust the bits to show a logical
3620 		 * version.
3621 		 */
3622 
3623 		pcm_fix_bits(newwin.Sockets, window->Sockets, slide, 0);
3624 
3625 #if defined(PCMCIA_DEBUG)
3626 		if (pcmcia_debug > 1) {
3627 			cmn_err(CE_CONT, "iw: orig bits=%x, new bits=%x\n",
3628 				(int)*(uint32_t *)newwin.Sockets,
3629 				(int)*(uint32_t *)window->Sockets);
3630 			cmn_err(CE_CONT, "\t%x.%x.%x\n", window->WndCaps,
3631 				window->mem_win_char.MemWndCaps,
3632 				window->mem_win_char.MinSize);
3633 		}
3634 #endif
3635 		window->window = win;
3636 	}
3637 	return (retval);
3638 }
3639 
3640 static int
3641 SSResetSocket(int socket, int mode)
3642 {
3643 	pcmcia_logical_socket_t *sockp;
3644 
3645 	if (socket >= pcmcia_num_sockets ||
3646 		(sockp = pcmcia_sockets[socket]) == NULL)
3647 		return (BAD_SOCKET);
3648 
3649 	return (RESET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip,
3650 	    sockp->ls_socket, mode));
3651 }
3652 
3653 static int
3654 SSSetPage(set_page_t *page)
3655 {
3656 	int window, retval;
3657 	set_page_t newpage;
3658 	pcmcia_logical_window_t *winp;
3659 
3660 	window = page->window;
3661 	if (window > pcmcia_num_windows) {
3662 #if defined(PCMCIA_DEBUG)
3663 		if (pcmcia_debug > 1)
3664 			cmn_err(CE_CONT, "SSSetPage: window=%d (of %d)\n",
3665 				window, pcmcia_num_windows);
3666 #endif
3667 		return (BAD_WINDOW);
3668 	}
3669 
3670 	winp = pcmcia_windows[window];
3671 	newpage = *page;
3672 	newpage.window = winp->lw_window;
3673 	retval = SET_PAGE(winp->lw_if, winp->lw_adapter->pca_dip, &newpage);
3674 	if (retval == SUCCESS) {
3675 		newpage.window = window;
3676 		*page = newpage;
3677 	}
3678 #if defined(PCMCIA_DEBUG)
3679 	if ((pcmcia_debug > 1) && retval != SUCCESS)
3680 		cmn_err(CE_CONT, "\tSetPage: returning error %x\n", retval);
3681 #endif
3682 	return (retval);
3683 }
3684 
3685 static int
3686 SSSetWindow(set_window_t *win)
3687 {
3688 	int socket, window, retval, func;
3689 	set_window_t newwin;
3690 	pcmcia_logical_window_t *winp;
3691 	pcmcia_logical_socket_t *sockp;
3692 
3693 	window = win->window;
3694 	if (window > pcmcia_num_windows)
3695 		return (BAD_WINDOW);
3696 
3697 	socket = CS_GET_SOCKET_NUMBER(win->socket);
3698 	func = CS_GET_FUNCTION_NUMBER(win->socket);
3699 
3700 	if (socket > pcmcia_num_sockets ||
3701 		(sockp = pcmcia_sockets[socket]) == NULL) {
3702 		return (BAD_SOCKET);
3703 	}
3704 
3705 	winp = pcmcia_windows[window];
3706 	winp->lw_socket = win->socket; /* reverse map */
3707 	newwin = *win;
3708 	newwin.window = winp->lw_window;
3709 	newwin.socket = sockp->ls_socket;
3710 	newwin.child = sockp->ls_dip[func]; /* so we carry the dip around */
3711 
3712 	retval = SET_WINDOW(winp->lw_if, winp->lw_adapter->pca_dip, &newwin);
3713 	if (retval == SUCCESS) {
3714 		newwin.window = window;
3715 		newwin.socket = winp->lw_socket;
3716 		*win = newwin;
3717 	}
3718 	return (retval);
3719 }
3720 
3721 static int
3722 SSSetSocket(set_socket_t *socket)
3723 {
3724 	int sock, retval;
3725 	pcmcia_logical_socket_t *sockp;
3726 	set_socket_t newsock;
3727 
3728 	sock = socket->socket;
3729 	if (sock > pcmcia_num_sockets ||
3730 		(sockp = pcmcia_sockets[sock]) == NULL) {
3731 		return (BAD_SOCKET);
3732 	}
3733 
3734 	newsock = *socket;
3735 	/* note: we force CS to always get insert/removal events */
3736 	sockp->ls_cs_events = pcm_mapevents(newsock.SCIntMask) |
3737 		PCE_E2M(PCE_CARD_INSERT) | PCE_E2M(PCE_CARD_REMOVAL);
3738 #if defined(PCMCIA_DEBUG)
3739 	if (pcmcia_debug > 1)
3740 		cmn_err(CE_CONT,
3741 			"SetSocket: SCIntMask = %x\n", newsock.SCIntMask);
3742 #endif
3743 	newsock.socket = sockp->ls_socket;
3744 	newsock.VccLevel = pcmcia_map_power_set(sockp->ls_adapter,
3745 	    newsock.VccLevel, VCC);
3746 	newsock.Vpp1Level = pcmcia_map_power_set(sockp->ls_adapter,
3747 	    newsock.Vpp1Level, VPP1);
3748 	newsock.Vpp2Level = pcmcia_map_power_set(sockp->ls_adapter,
3749 	    newsock.Vpp2Level, VPP2);
3750 	retval = SET_SOCKET(sockp->ls_if, sockp->ls_adapter->pca_dip,
3751 	    &newsock);
3752 	if (retval == SUCCESS) {
3753 		newsock.socket = sock;
3754 		newsock.VccLevel = pcmcia_map_power_get(sockp->ls_adapter,
3755 		    newsock.VccLevel,
3756 		    VCC);
3757 		newsock.Vpp1Level = pcmcia_map_power_get(sockp->ls_adapter,
3758 		    newsock.Vpp1Level,
3759 		    VPP1);
3760 		newsock.Vpp2Level = pcmcia_map_power_get(sockp->ls_adapter,
3761 		    newsock.Vpp2Level,
3762 		    VPP2);
3763 		*socket = newsock;
3764 		if (socket->IREQRouting & IRQ_ENABLE) {
3765 			sockp->ls_flags |= PCS_IRQ_ENABLED;
3766 		} else {
3767 			sockp->ls_flags &= ~PCS_IRQ_ENABLED;
3768 		}
3769 	}
3770 	return (retval);
3771 }
3772 
3773 /*
3774  * SSSetIRQHandler()
3775  *	arrange for IRQ to be allocated if appropriate and always
3776  *	arrange that PC Card interrupt handlers get called.
3777  */
3778 static int
3779 SSSetIRQHandler(set_irq_handler_t *handler)
3780 {
3781 	int sock, retval, func;
3782 	pcmcia_logical_socket_t *sockp;
3783 	struct pcmcia_parent_private *ppd;
3784 	dev_info_t *dip;
3785 	ddi_iblock_cookie_t iblk;
3786 	ddi_idevice_cookie_t idev;
3787 
3788 	sock = CS_GET_SOCKET_NUMBER(handler->socket);
3789 	func = CS_GET_FUNCTION_NUMBER(handler->socket);
3790 	if (sock > pcmcia_num_sockets ||
3791 		(sockp = pcmcia_sockets[sock]) == NULL) {
3792 		return (BAD_SOCKET);
3793 	}
3794 #if defined(PCMCIA_DEBUG)
3795 	if (pcmcia_debug) {
3796 
3797 		cmn_err(CE_CONT, "SSSetIRQHandler: socket=%x, function=%x\n",
3798 			sock, func);
3799 		cmn_err(CE_CONT, "\thandler(%p): socket=%x, irq=%x, id=%x\n",
3800 			(void *)handler->handler, handler->socket, handler->irq,
3801 			handler->handler_id);
3802 	}
3803 #endif
3804 	dip = sockp->ls_dip[func];
3805 
3806 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
3807 
3808 	handler->iblk_cookie = &iblk;
3809 	handler->idev_cookie = &idev;
3810 
3811 	retval = ddi_add_intr(dip, 0, handler->iblk_cookie,
3812 	    handler->idev_cookie,
3813 	    (uint32_t(*)(caddr_t)) handler->handler,
3814 	    handler->arg1);
3815 
3816 	if (retval == DDI_SUCCESS) {
3817 		handler->iblk_cookie = &sockp->ls_iblk;
3818 		handler->idev_cookie = &sockp->ls_idev;
3819 		handler->irq = ppd->ppd_intrspec->intrspec_vec;
3820 		retval = SUCCESS;
3821 	} else {
3822 		retval = sockp->ls_error;
3823 	}
3824 	return (retval);
3825 }
3826 
3827 /*
3828  * SSClearIRQHandler()
3829  *	Arrange to have the interrupt handler specified removed
3830  *	from the interrupt list.
3831  */
3832 static int
3833 SSClearIRQHandler(clear_irq_handler_t *handler)
3834 {
3835 	int sock, func;
3836 	pcmcia_logical_socket_t *sockp;
3837 	dev_info_t *dip;
3838 
3839 	sock = CS_GET_SOCKET_NUMBER(handler->socket);
3840 	func = CS_GET_FUNCTION_NUMBER(handler->socket);
3841 
3842 #if defined(PCMCIA_DEBUG)
3843 	if (pcmcia_debug) {
3844 
3845 		cmn_err(CE_CONT,
3846 			"SSClearIRQHandler: socket=%x, function=%x\n",
3847 			sock, func);
3848 		cmn_err(CE_CONT,
3849 			"\thandler(%p): socket=%x, id=%x\n",
3850 			(void *)handler, handler->socket,
3851 			handler->handler_id);
3852 	}
3853 #endif
3854 
3855 	if (sock > pcmcia_num_sockets ||
3856 		(sockp = pcmcia_sockets[sock]) == NULL) {
3857 		return (BAD_SOCKET);
3858 	}
3859 	dip = sockp->ls_dip[func];
3860 	if (dip) {
3861 		ddi_remove_intr(dip, 0, NULL);
3862 		return (SUCCESS);
3863 	}
3864 	return (BAD_SOCKET);
3865 }
3866 
3867 
3868 /*
3869  * pcm_pathname()
3870  *	make a partial path from dip.
3871  *	used to mknods relative to /devices/pcmcia/
3872  *
3873  * XXX - we now use ddi_get_name_addr to get the "address" portion
3874  *	of the name; that way, we only have to modify the name creation
3875  *	algorithm in one place
3876  */
3877 static void
3878 pcm_pathname(dev_info_t *dip, char *name, char *path)
3879 {
3880 	(void) sprintf(path, "%s@%s:%s", ddi_node_name(dip),
3881 	    ddi_get_name_addr(dip), name);
3882 }
3883 
3884 /*
3885  * pcmcia_create_device()
3886  *	create the /devices entries for the driver
3887  *	it is assumed that the PC Card driver will do a
3888  *	RegisterClient for each subdevice.
3889  *	The device type string is encoded here to match
3890  *	the standardized names when possible.
3891  * XXX - note that we may need to provide a way for the
3892  *	caller to specify the complete name string that
3893  *	we pass to ddi_set_name_addr
3894  */
3895 static int
3896 pcmcia_create_device(ss_make_device_node_t *init)
3897 {
3898 	int err = SUCCESS;
3899 	struct pcm_make_dev device;
3900 	struct dev_ops *ops;
3901 	major_t major;
3902 
3903 	/*
3904 	 * Now that we have the name, create it.
3905 	 */
3906 
3907 	bzero(&device, sizeof (device));
3908 	if (init->flags & SS_CSINITDEV_CREATE_DEVICE) {
3909 		if ((err = ddi_create_minor_node(init->dip,
3910 		    init->name,
3911 		    init->spec_type,
3912 		    init->minor_num,
3913 		    init->node_type,
3914 		    0)) != DDI_SUCCESS) {
3915 #if defined(PCMCIA_DEBUG)
3916 			if (pcmcia_debug)
3917 				cmn_err(CE_CONT,
3918 					"pcmcia_create_device: failed "
3919 					"create\n");
3920 #endif
3921 			return (BAD_ATTRIBUTE);
3922 		}
3923 
3924 		major = ddi_name_to_major(ddi_binding_name(init->dip));
3925 		ops = ddi_get_driver(init->dip);
3926 		LOCK_DEV_OPS(&devnamesp[major].dn_lock);
3927 		INCR_DEV_OPS_REF(ops);
3928 		(void) ddi_pathname(init->dip, device.path);
3929 		DECR_DEV_OPS_REF(ops);
3930 		UNLOCK_DEV_OPS(&devnamesp[major].dn_lock);
3931 		(void) sprintf(device.path + strlen(device.path), ":%s",
3932 		    init->name);
3933 
3934 		(void) strcpy(device.driver, ddi_binding_name(init->dip));
3935 #if defined(PCMCIA_DEBUG)
3936 		if (pcmcia_debug)
3937 			cmn_err(CE_CONT,
3938 				"pcmcia_create_device: created %s "
3939 				"from %s [%s]\n",
3940 				device.path, init->name, device.driver);
3941 #endif
3942 		device.dev =
3943 		    makedevice(ddi_name_to_major(ddi_get_name(init->dip)),
3944 		    init->minor_num);
3945 		device.flags |= (init->flags & SS_CSINITDEV_MORE_DEVICES) ?
3946 		    PCM_EVENT_MORE : 0;
3947 		device.type = init->spec_type;
3948 		device.op = SS_CSINITDEV_CREATE_DEVICE;
3949 		device.socket = ddi_getprop(DDI_DEV_T_ANY, init->dip,
3950 		    DDI_PROP_CANSLEEP, PCM_DEV_SOCKET,
3951 		    -1);
3952 	} else if (init->flags & SS_CSINITDEV_REMOVE_DEVICE) {
3953 		device.op = SS_CSINITDEV_REMOVE_DEVICE;
3954 		device.socket = ddi_getprop(DDI_DEV_T_ANY, init->dip,
3955 		    DDI_PROP_CANSLEEP, PCM_DEV_SOCKET,
3956 		    -1);
3957 		if (init->name != NULL)
3958 			(void) strcpy(device.path, init->name);
3959 		device.dev =
3960 		    makedevice(ddi_name_to_major(ddi_get_name(init->dip)),
3961 		    0);
3962 		ddi_remove_minor_node(init->dip, init->name);
3963 	}
3964 
3965 	/*
3966 	 *	we send an event for ALL devices created.
3967 	 *	To do otherwise ties us to using drvconfig
3968 	 *	forever.  There are relatively few devices
3969 	 *	ever created so no need to do otherwise.
3970 	 *	The existence of the event manager must never
3971 	 *	be visible to a PCMCIA device driver.
3972 	 */
3973 	pcm_event_manager(PCE_INIT_DEV, device.socket, &device);
3974 
3975 	return (err);
3976 }
3977 
3978 /*
3979  * pcmcia_get_minors()
3980  *	We need to traverse the minor node list of the
3981  *	dip if there are any.  This takes two passes;
3982  *	one to get the count and buffer size and the
3983  *	other to actually copy the data into the buffer.
3984  *	The framework requires that the dip be locked
3985  *	during this time to avoid breakage as well as the
3986  *	driver being locked.
3987  */
3988 int
3989 pcmcia_get_minors(dev_info_t *dip, struct pcm_make_dev **minors)
3990 {
3991 	int count = 0;
3992 	struct ddi_minor_data *dp;
3993 	struct pcm_make_dev *md;
3994 	int socket;
3995 	major_t major;
3996 	struct dev_ops *ops;
3997 
3998 	socket = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3999 	    PCM_DEV_SOCKET, -1);
4000 	mutex_enter(&(DEVI(dip)->devi_lock));
4001 	if (DEVI(dip)->devi_minor != (struct ddi_minor_data *)NULL) {
4002 		for (dp = DEVI(dip)->devi_minor;
4003 			dp != (struct ddi_minor_data *)NULL;
4004 			dp = dp->next) {
4005 			count++; /* have one more */
4006 		}
4007 		/* we now know how many nodes to allocate */
4008 		md = kmem_zalloc(count * sizeof (struct pcm_make_dev),
4009 		    KM_NOSLEEP);
4010 		if (md != NULL) {
4011 			*minors = md;
4012 			for (dp = DEVI(dip)->devi_minor;
4013 				dp != (struct ddi_minor_data *)NULL;
4014 				dp = dp->next, md++) {
4015 #if defined(PCMCIA_DEBUG)
4016 				if (pcmcia_debug > 1) {
4017 					cmn_err(CE_CONT,
4018 						"pcmcia_get_minors: name=%s,"
4019 						"socket=%d, stype=%x, "
4020 						"ntype=%s, dev_t=%x",
4021 						dp->ddm_name,
4022 						socket,
4023 						dp->ddm_spec_type,
4024 						dp->ddm_node_type,
4025 						(int)dp->ddm_dev);
4026 					cmn_err(CE_CONT,
4027 						"\tbind name = %s\n",
4028 						ddi_binding_name(dip));
4029 				}
4030 #endif
4031 				md->socket = socket;
4032 				md->op = SS_CSINITDEV_CREATE_DEVICE;
4033 				md->dev = dp->ddm_dev;
4034 				md->type = dp->ddm_spec_type;
4035 				(void) strcpy(md->driver,
4036 				    ddi_binding_name(dip));
4037 				major = ddi_name_to_major(md->driver);
4038 				ops = ddi_get_driver(dip);
4039 				LOCK_DEV_OPS(&devnamesp[major].dn_lock);
4040 				pcm_pathname(dip, dp->ddm_name, md->path);
4041 				INCR_DEV_OPS_REF(ops);
4042 				(void) ddi_pathname(dip, md->path);
4043 				DECR_DEV_OPS_REF(ops);
4044 				UNLOCK_DEV_OPS(&devnamesp[major].dn_lock);
4045 				(void) sprintf(md->path + strlen(md->path),
4046 					":%s", dp->ddm_name);
4047 				if (dp->next == NULL)
4048 					/* no more */
4049 					md->flags |= PCM_EVENT_MORE;
4050 			}
4051 		} else {
4052 			count = 0;
4053 		}
4054 	}
4055 	mutex_exit(&(DEVI(dip)->devi_lock));
4056 	return (count);
4057 }
4058 
4059 #if defined(PCMCIA_DEBUG)
4060 static char *ddmtypes[] = { "minor", "alias", "default", "internal" };
4061 
4062 static void
4063 pcmcia_dump_minors(dev_info_t *dip)
4064 {
4065 	int count = 0;
4066 	struct ddi_minor_data *dp;
4067 	int unit, major;
4068 	dev_info_t *np;
4069 
4070 	unit = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
4071 	    PCM_DEV_SOCKET, -1);
4072 	cmn_err(CE_CONT,
4073 		"pcmcia_dump_minors: dip=%p, socket=%d\n", (void *)dip, unit);
4074 
4075 	major = ddi_driver_major(dip);
4076 	if (major != -1) {
4077 		for (np = devnamesp[major].dn_head; np != NULL;
4078 		    np = (dev_info_t *)DEVI(np)->devi_next) {
4079 			char *cf2 = "";
4080 			char *cur = "";
4081 			if (i_ddi_node_state(np) == DS_READY)
4082 				cf2 = "DS_READY";
4083 			if (np == dip)
4084 				cur = "CUR";
4085 			cmn_err(CE_CONT, "\tsibs: %s %s %s\n",
4086 				ddi_binding_name(np), cf2, cur);
4087 
4088 			mutex_enter(&(DEVI(np)->devi_lock));
4089 			if (DEVI(np)->devi_minor !=
4090 			    (struct ddi_minor_data *)NULL) {
4091 				for (dp = DEVI(np)->devi_minor;
4092 				    dp != (struct ddi_minor_data *)NULL;
4093 				    dp = dp->next) {
4094 					count++; /* have one more */
4095 				}
4096 				for (dp = DEVI(dip)->devi_minor;
4097 				    dp != (struct ddi_minor_data *)NULL;
4098 				    dp = dp->next) {
4099 					cmn_err(CE_CONT, "\ttype=%s, name=%s,"
4100 						"socket=%d, stype=%x, "
4101 						"ntype=%s, dev_t=%x",
4102 						ddmtypes[dp->type],
4103 						dp->ddm_name,
4104 						unit,
4105 						dp->ddm_spec_type,
4106 						dp->ddm_node_type,
4107 						(int)dp->ddm_dev);
4108 					cmn_err(CE_CONT, "\tbind name = %s\n",
4109 						ddi_binding_name(np));
4110 				}
4111 			}
4112 			mutex_exit(&(DEVI(np)->devi_lock));
4113 		}
4114 	}
4115 }
4116 #endif
4117 
4118 /*
4119  * experimental merging code
4120  * what are the things that we should merge on?
4121  *	match something by name in the "compatible" property
4122  *	restrict to a specific "socket"
4123  *	restrict to a specific "instance"
4124  */
4125 /*ARGSUSED*/
4126 static int
4127 pcmcia_merge_conf(dev_info_t *dip)
4128 {
4129 	return (0);		/* merge failed */
4130 }
4131 
4132 /*
4133  * pcmcia_mfc_intr()
4134  *	Multifunction Card interrupt handler
4135  *	While some adapters share interrupts at the lowest
4136  *	level, some can't.  In order to be consistent, we
4137  *	split multifunction cards out with this intercept and
4138  *	allow the low level to do what is best for it.
4139  *	the arg is a pcmcia_socket structure and all interrupts
4140  *	are per-socket in this case.  We also have the option
4141  *	to optimize if the cards support it.  It also means
4142  *	that we can use the INTRACK mode if it proves desirable
4143  */
4144 /*ARGSUSED*/
4145 static uint32_t
4146 pcmcia_mfc_intr(caddr_t arg1, caddr_t arg2)
4147 {
4148 	pcmcia_logical_socket_t *sockp;
4149 	inthandler_t *intr, *first;
4150 	int done, result;
4151 
4152 	sockp = (pcmcia_logical_socket_t *)arg1;
4153 
4154 #if defined(PCMCIA_DEBUG)
4155 	if (pcmcia_debug > 1) {
4156 		cmn_err(CE_CONT, "pcmcia_mfc_intr sockp=%p"
4157 		    " ls_inthandlers=%p\n"
4158 		    "\t ls_flags=0x%x PCS_IRQ_ENABLED=0x%x \n",
4159 		    (void *) sockp, (void *) sockp->ls_inthandlers,
4160 		    sockp->ls_flags, PCS_IRQ_ENABLED);
4161 	}
4162 #endif
4163 
4164 	if (sockp == NULL || sockp->ls_inthandlers == NULL ||
4165 	    !(sockp->ls_flags & PCS_IRQ_ENABLED))
4166 		return (DDI_INTR_UNCLAIMED);
4167 
4168 	mutex_enter(&sockp->ls_ilock);
4169 	for (done = 0, result = 0, first = intr = sockp->ls_inthandlers;
4170 		intr != NULL && !done; intr = intr->next) {
4171 		result |= intr->intr(intr->arg1, intr->arg2);
4172 		if (intr->next == first)
4173 			done++;
4174 	}
4175 	if (intr == NULL) {
4176 		cmn_err(CE_WARN, "pcmcia_mfc_intr: bad MFC handler list");
4177 	}
4178 	if (sockp->ls_inthandlers)
4179 		sockp->ls_inthandlers = sockp->ls_inthandlers->next;
4180 
4181 	mutex_exit(&sockp->ls_ilock);
4182 	return (result ? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
4183 }
4184 
4185 /*
4186  * pcmcia_power(dip)
4187  *	control power for nexus and children
4188  */
4189 int
4190 pcmcia_power(dev_info_t *dip, int component, int level)
4191 {
4192 #if 0
4193 	anp_t *anp = (anp_t *)ddi_get_driver_private(dip);
4194 	int i;
4195 	/*
4196 	 * for now, we only have one component.  Should there be one per-socket?
4197 	 * the level is only one (power on or off)
4198 	 */
4199 	if (component != 0 || level > 1)
4200 		return (DDI_FAILURE);
4201 
4202 	for (i = 0; i < pcic->pc_numsockets; i++) {
4203 		if (pcic->pc_callback)
4204 			PC_CALLBACK(dip, pcic->pc_cb_arg,
4205 			    (level == 0) ? PCE_PM_SUSPEND :
4206 			    PCE_PM_RESUME,
4207 			    i);
4208 	}
4209 #else
4210 	cmn_err(CE_WARN, "pcmcia_power: component=%d, level=%d for %s",
4211 		component, level, ddi_get_name_addr(dip));
4212 	return (DDI_FAILURE);
4213 #endif
4214 }
4215 
4216 void
4217 pcmcia_begin_resume(dev_info_t *dip)
4218 {
4219 	int i;
4220 	struct pcmcia_adapter *adapt = NULL;
4221 	for (i = 0; i < pcmcia_num_adapters; i++) {
4222 		if (pcmcia_adapters[i]->pca_dip == dip) {
4223 			adapt = pcmcia_adapters[i];
4224 			break;
4225 		}
4226 	}
4227 	if (adapt == NULL)
4228 		return;
4229 
4230 	for (i = 0; i < adapt->pca_numsockets; i++) {
4231 		int s;
4232 		s = adapt->pca_first_socket + i;
4233 		if (pcmcia_sockets[s]->ls_flags & PCS_SUSPENDED) {
4234 			if (pcmcia_sockets[s]->ls_flags &
4235 			    (1 << PCE_PM_RESUME)) {
4236 				(void) cs_event(PCE_PM_RESUME, s, 0);
4237 				pcm_event_manager(PCE_PM_RESUME, s, NULL);
4238 			}
4239 			(void) cs_event(PCE_CARD_REMOVAL, s, 0);
4240 			pcm_event_manager(PCE_CARD_REMOVAL, s, NULL);
4241 		}
4242 	}
4243 }
4244 
4245 void
4246 pcmcia_wait_insert(dev_info_t *dip)
4247 {
4248 	int i, f, tries, done;
4249 	clock_t tm;
4250 	struct pcmcia_adapter *adapt = NULL;
4251 	anp_t *nexus;
4252 
4253 	for (i = 0; i < pcmcia_num_adapters; i++) {
4254 		if (pcmcia_adapters[i]->pca_dip == dip) {
4255 			adapt = pcmcia_adapters[i];
4256 			break;
4257 		}
4258 	}
4259 	if (adapt == NULL)
4260 		return;
4261 
4262 	for (tries = adapt->pca_numsockets * 10; tries > 0; tries--) {
4263 		done = 1;
4264 		mutex_enter(&pcmcia_global_lock);
4265 		for (i = 0; i < adapt->pca_numsockets; i++) {
4266 			int s;
4267 			s = adapt->pca_first_socket + i;
4268 			for (f = 0; f < PCMCIA_MAX_FUNCTIONS; f++)
4269 				if (pcmcia_sockets[s] &&
4270 				    pcmcia_sockets[s]->ls_flags &
4271 				    PCS_SUSPENDED) {
4272 					done = 0;
4273 					break;
4274 				}
4275 		}
4276 		if (!done) {
4277 			tm = ddi_get_lbolt();
4278 			(void) cv_timedwait(&pcmcia_condvar,
4279 			    &pcmcia_global_lock,
4280 			    tm + drv_usectohz(100000));
4281 		} else {
4282 			tries = 0;
4283 		}
4284 		mutex_exit(&pcmcia_global_lock);
4285 	}
4286 
4287 	nexus = (anp_t *)ddi_get_driver_private(dip);
4288 	pcmcia_find_cards(nexus);
4289 }
4290 
4291 int
4292 pcmcia_map_reg(dev_info_t *pdip, dev_info_t *dip, ra_return_t *ra,
4293 		uint32_t state, caddr_t *base,
4294 		ddi_acc_handle_t *handle, ddi_device_acc_attr_t *attrib,
4295 		uint32_t req_base)
4296 {
4297 	struct pcmcia_parent_private *ppd;
4298 	int rnum = 0, type = PCMCIA_MAP_MEM;
4299 	ddi_map_req_t mr;
4300 	ddi_acc_hdl_t *hp;
4301 	int result;
4302 	struct regspec *reg;
4303 	ddi_device_acc_attr_t attr;
4304 
4305 	if (dip != NULL) {
4306 		ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
4307 		if (ppd == NULL)
4308 			return (DDI_FAILURE);
4309 		for (rnum = 1; rnum < ppd->ppd_nreg; rnum++) {
4310 			struct pcm_regs *p;
4311 			p = &ppd->ppd_reg[rnum];
4312 			if (state & WS_IO) {
4313 				/* need I/O */
4314 				type = PCMCIA_MAP_IO;
4315 				/*
4316 				 * We want to find an IO regspec. When we
4317 				 *	find one, it either has to match
4318 				 *	the caller's requested base address
4319 				 *	or it has to be relocatable.
4320 				 * We match on the requested base address
4321 				 *	rather than the allocated base
4322 				 *	address so that we handle the case
4323 				 *	of adapters that have IO window base
4324 				 *	relocation registers.
4325 				 */
4326 				if ((p->phys_hi &
4327 				    PC_REG_SPACE(PC_REG_SPACE_IO)) &&
4328 					((req_base == p->phys_lo) ||
4329 					!(p->phys_hi & PC_REG_RELOC(1))))
4330 				    break;
4331 			} else {
4332 				/* need memory */
4333 				type = PCMCIA_MAP_MEM;
4334 				if (p->phys_hi &
4335 				    PC_REG_SPACE(PC_REG_SPACE_MEMORY|
4336 				    PC_REG_SPACE_ATTRIBUTE))
4337 					break;
4338 			}
4339 		}
4340 		if (rnum >= ppd->ppd_nreg)
4341 			return (DDI_FAILURE);
4342 	} else if (state & WS_IO) {
4343 		return (DDI_FAILURE);
4344 	}
4345 
4346 	reg = kmem_zalloc(sizeof (pci_regspec_t), KM_SLEEP);
4347 	reg = pcmcia_cons_regspec(pdip, type, (uchar_t *)reg, ra);
4348 
4349 	if (attrib == NULL ||
4350 	    attrib->devacc_attr_version != DDI_DEVICE_ATTR_V0) {
4351 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
4352 		attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
4353 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
4354 	} else {
4355 		attr = *attrib;
4356 	}
4357 	/*
4358 	 * Allocate and initialize the common elements of data access handle.
4359 	 */
4360 	*handle = impl_acc_hdl_alloc(KM_SLEEP, NULL);
4361 	hp = impl_acc_hdl_get(*handle);
4362 	hp->ah_vers = VERS_ACCHDL;
4363 	hp->ah_dip = dip != NULL ? dip : pdip;
4364 	hp->ah_rnumber = rnum;
4365 	hp->ah_offset = 0;
4366 	hp->ah_len = ra->ra_len;
4367 	hp->ah_acc = attr;
4368 
4369 	/*
4370 	 * Set up the mapping request and call to parent.
4371 	 */
4372 	mr.map_op = DDI_MO_MAP_LOCKED;
4373 	mr.map_type = DDI_MT_REGSPEC;
4374 	mr.map_obj.rp = reg;
4375 	mr.map_prot = PROT_READ | PROT_WRITE;
4376 	mr.map_flags = DDI_MF_KERNEL_MAPPING;
4377 	mr.map_handlep = hp;
4378 	mr.map_vers = DDI_MAP_VERSION;
4379 
4380 	result = ddi_map(pdip, &mr, 0, ra->ra_len, base);
4381 	if (result != DDI_SUCCESS) {
4382 		impl_acc_hdl_free(*handle);
4383 		*handle = (ddi_acc_handle_t)NULL;
4384 	} else {
4385 		hp->ah_addr = *base;
4386 		if (mr.map_op == DDI_MO_UNMAP)
4387 			ra = NULL;
4388 		if (dip != NULL)
4389 			pcmcia_set_assigned(dip, rnum, ra);
4390 	}
4391 
4392 	kmem_free(reg, sizeof (pci_regspec_t));
4393 
4394 	return (result);
4395 }
4396 
4397 struct pcmcia_adapter *
4398 pcmcia_get_adapter(dev_info_t *dip)
4399 {
4400 	int i;
4401 
4402 	for (i = 0; i < pcmcia_num_adapters; i++) {
4403 		if (pcmcia_adapters[i] &&
4404 		    pcmcia_adapters[i]->pca_dip == dip) {
4405 			return (pcmcia_adapters[i]);
4406 		}
4407 	}
4408 	return (NULL);
4409 }
4410 
4411 
4412 void
4413 pcmcia_set_assigned(dev_info_t *dip, int rnum, ra_return_t *ret)
4414 {
4415 	struct pcmcia_parent_private *ppd;
4416 	struct pcm_regs *reg, *assign;
4417 
4418 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
4419 	if (ppd) {
4420 		reg = &ppd->ppd_reg[rnum];
4421 		assign = &ppd->ppd_assigned[rnum];
4422 		if (ret) {
4423 			if (assign->phys_hi == 0) {
4424 				assign->phys_hi = reg->phys_hi;
4425 				assign->phys_lo = ret->ra_addr_lo;
4426 				assign->phys_len = ret->ra_len;
4427 			} else if (assign->phys_lo != ret->ra_addr_lo) {
4428 #ifdef PCMCIA_DEBUG
4429 				cmn_err(CE_WARN, "pcmcia: bad address:"
4430 					"%s=<%x,%x>",
4431 					ddi_get_name_addr(dip),
4432 					ret->ra_addr_lo, assign->phys_lo);
4433 #else
4434 				cmn_err(CE_WARN, "!pcmcia: bad address:"
4435 					"%s=<%x,%x>",
4436 					ddi_get_name_addr(dip),
4437 					ret->ra_addr_lo, (int)assign->phys_lo);
4438 #endif
4439 			}
4440 			assign->phys_hi = PC_INCR_REFCNT(assign->phys_hi);
4441 		} else {
4442 			int i;
4443 			assign->phys_hi = PC_DECR_REFCNT(assign->phys_hi);
4444 			i = PC_GET_REG_REFCNT(assign->phys_hi);
4445 			if (i == 0) {
4446 				assign->phys_hi = 0;
4447 				assign->phys_lo = 0;
4448 				assign->phys_len = 0;
4449 			}
4450 		}
4451 	}
4452 }
4453 
4454 int
4455 pcmcia_alloc_mem(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret)
4456 {
4457 	return (pcmcia_ra_alloc(dip, req, ret, NDI_RA_TYPE_MEM));
4458 }
4459 
4460 int
4461 pcmcia_alloc_io(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret)
4462 {
4463 	return (pcmcia_ra_alloc(dip, req, ret, NDI_RA_TYPE_IO));
4464 }
4465 
4466 int
4467 pcmcia_ra_alloc(dev_info_t *dip, ndi_ra_request_t *req, ra_return_t *ret,
4468 		char *type)
4469 {
4470 	int rval;
4471 	uint64_t base = 0;
4472 	uint64_t len = 0;
4473 
4474 	/*
4475 	 * Allocate space from busra resource list
4476 	 * should not return an address > 32 bits
4477 	 */
4478 
4479 	if ((ndi_ra_alloc(dip, req, &base, &len, type, NDI_RA_PASS)
4480 							== NDI_FAILURE) ||
4481 	    ((base >> 32) != 0)) {
4482 		ret->ra_addr_lo = 0;
4483 		ret->ra_len = 0;
4484 		rval = DDI_FAILURE;
4485 	} else {
4486 		ret->ra_addr_lo =  base & 0xffffffff;
4487 		ret->ra_len = len;
4488 		rval = DDI_SUCCESS;
4489 	}
4490 	ret->ra_addr_hi = 0;
4491 	return (rval);
4492 }
4493 
4494 int
4495 pcmcia_free_mem(dev_info_t *dip, ra_return_t *ret)
4496 {
4497 	return (pcmcia_ra_free(dip, ret, NDI_RA_TYPE_MEM));
4498 }
4499 
4500 int
4501 pcmcia_free_io(dev_info_t *dip, ra_return_t *ret)
4502 {
4503 	return (pcmcia_ra_free(dip, ret, NDI_RA_TYPE_IO));
4504 }
4505 
4506 int
4507 pcmcia_ra_free(dev_info_t *dip, ra_return_t *ret, char *type)
4508 {
4509 	if (ndi_ra_free(dip, (uint64_t)ret->ra_addr_lo, (uint64_t)ret->ra_len,
4510 	    type, NDI_RA_PASS) == NDI_SUCCESS) {
4511 		return (DDI_SUCCESS);
4512 	} else {
4513 		return (DDI_FAILURE);
4514 	}
4515 }
4516 
4517 
4518 /*
4519  * when the low level device configuration does resource assignment
4520  * (devconf) then free the allocated resources so we can reassign them
4521  * later.  Walk the child list to get them.
4522  */
4523 void
4524 pcmcia_free_resources(dev_info_t *self)
4525 {
4526 	struct regspec *assigned;
4527 	int len;
4528 	dev_info_t *dip;
4529 	int circular;
4530 
4531 	ndi_devi_enter(self, &circular);
4532 	/* do searches in compatible property order */
4533 	for (dip = (dev_info_t *)DEVI(self)->devi_child;
4534 	    dip != NULL;
4535 	    dip = (dev_info_t *)DEVI(dip)->devi_sibling) {
4536 		len = 0;
4537 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
4538 		    DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP,
4539 		    "assigned-addresses",
4540 		    (caddr_t)&assigned,
4541 		    &len) == DDI_PROP_SUCCESS) {
4542 			/*
4543 			 * if there are assigned resources at this point,
4544 			 * then the OBP or devconf have assigned them and
4545 			 * they need to be freed.
4546 			 */
4547 			kmem_free(assigned, len);
4548 		}
4549 	}
4550 	ndi_devi_exit(self, circular);
4551 }
4552 
4553 /*
4554  * this is the equivalent of pcm_get_intr using ra_allocs.
4555  * returns -1 if failed, otherwise returns the allocated irq.
4556  * The input request, if less than zero it means not a specific
4557  * irq requested. If larger then 0 then we are requesting that specific
4558  * irq
4559  */
4560 int
4561 pcmcia_get_intr(dev_info_t *dip, int request)
4562 {
4563 	ndi_ra_request_t req;
4564 	uint64_t base;
4565 	uint64_t len;
4566 	int err;
4567 
4568 	bzero(&req, sizeof (req));
4569 	base = 0;
4570 	len = 1;
4571 	if (request >= 0) {
4572 		req.ra_flags = NDI_RA_ALLOC_SPECIFIED;
4573 		req.ra_len = 1;
4574 		req.ra_addr = (uint64_t)request;
4575 	}
4576 
4577 	req.ra_boundbase = 0;
4578 	req.ra_boundlen = 0xffffffffUL;
4579 	req.ra_flags |= NDI_RA_ALLOC_BOUNDED;
4580 
4581 	err = ndi_ra_alloc(dip, &req, &base, &len, NDI_RA_TYPE_INTR,
4582 	    NDI_RA_PASS);
4583 
4584 	if (err == NDI_FAILURE) {
4585 		return (-1);
4586 	} else {
4587 		return ((int)base);
4588 	}
4589 }
4590 
4591 
4592 int
4593 pcmcia_return_intr(dev_info_t *dip, int request)
4594 {
4595 	if ((ndi_ra_free(dip, (uint64_t)request, 1, NDI_RA_TYPE_INTR,
4596 	    NDI_RA_PASS)) == NDI_SUCCESS) {
4597 		return (0);
4598 	} else
4599 		return (-1);
4600 
4601 }
4602 
4603 #ifdef sparc
4604 
4605 int
4606 pcmcia_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
4607     ddi_intr_handle_impl_t *hdlp)
4608 {
4609 
4610 	struct pcmcia_parent_private *ppd;
4611 	pcmcia_logical_socket_t *sockp;
4612 	int socket, ret;
4613 	struct pcmcia_adapter *adapt;
4614 	set_irq_handler_t handler;
4615 	struct intrspec *pispec;
4616 
4617 #if defined(PCMCIA_DEBUG)
4618 	if (pcmcia_debug) {
4619 		cmn_err(CE_CONT,
4620 		    "pcmcia_add_intr_impl() entered "
4621 		    "dip=%p rdip=%p hdlp=%p \n",
4622 		    (void *)dip, (void *)rdip, (void *)hdlp);
4623 	}
4624 #endif
4625 
4626 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
4627 	socket = ppd->ppd_socket;
4628 	sockp = pcmcia_sockets[socket];
4629 	adapt = sockp->ls_adapter;
4630 
4631 #if defined(PCMCIA_DEBUG)
4632 	if (pcmcia_debug) {
4633 		cmn_err(CE_CONT, "pcmcia_add_intr_impl()"
4634 		    " ppd_flags=0X%x PPD_CARD_MULTI=0X%x\n"
4635 		    " ppd_intrspec=%p ls_inthandlers=%p\n",
4636 		    ppd->ppd_flags, PPD_CARD_MULTI,
4637 		    (void *) ppd->ppd_intrspec,
4638 		    (void *)sockp->ls_inthandlers);
4639 	}
4640 #endif
4641 
4642 	/*
4643 	 * calculate IPL level when we support multiple levels
4644 	 */
4645 	pispec = ppd->ppd_intrspec;
4646 	if (pispec == NULL) {
4647 		sockp->ls_error = BAD_IRQ;
4648 		return (DDI_FAILURE);
4649 	}
4650 
4651 	handler.socket = sockp->ls_socket;
4652 	handler.irq = 0;	/* default case */
4653 	handler.handler = (f_tt *)hdlp->ih_cb_func;
4654 	handler.arg1 = hdlp->ih_cb_arg1;
4655 	handler.arg2 = hdlp->ih_cb_arg2;
4656 	handler.handler_id = (uint32_t)(uintptr_t)rdip;
4657 
4658 	/*
4659 	 * check if multifunction and do the right thing
4660 	 * we put an intercept in between the mfc handler and
4661 	 * us so we can catch and process.  We might be able
4662 	 * to optimize this depending on the card features
4663 	 * (a future option).
4664 	 */
4665 	if (ppd->ppd_flags & PPD_CARD_MULTI) {
4666 		inthandler_t *intr;
4667 		/*
4668 		 * note that the first function is a special
4669 		 * case since it sets things up.  We fall through
4670 		 * to the lower code and get the hardware set up.
4671 		 * subsequent times we just lock the list and insert
4672 		 * the handler and all is well.
4673 		 */
4674 		intr = kmem_zalloc(sizeof (inthandler_t), KM_NOSLEEP);
4675 		if (intr == NULL) {
4676 			sockp->ls_error = BAD_IRQ;
4677 			return (DDI_FAILURE);
4678 		}
4679 		intr->intr = hdlp->ih_cb_func;
4680 		intr->handler_id = (uint_t)(uintptr_t)rdip;
4681 		intr->arg1 = hdlp->ih_cb_arg1;
4682 		intr->arg2 = hdlp->ih_cb_arg2;
4683 		intr->socket = socket;
4684 
4685 		mutex_enter(&sockp->ls_ilock);
4686 		if (sockp->ls_inthandlers == NULL) {
4687 			intr->next = intr->prev = intr;
4688 			sockp->ls_inthandlers = intr;
4689 			sockp->ls_mfintr_dip = rdip;
4690 			mutex_exit(&sockp->ls_ilock);
4691 
4692 			/*
4693 			 * replace first function handler with
4694 			 * the mfc handler
4695 			 */
4696 			handler.handler =  (f_tt *)pcmcia_mfc_intr;
4697 			handler.arg1 = (caddr_t)sockp;
4698 			handler.arg2 = NULL;
4699 		} else {
4700 			insque(intr, sockp->ls_inthandlers);
4701 			mutex_exit(&sockp->ls_ilock);
4702 
4703 			pispec->intrspec_vec = sockp->ls_intr_vec;
4704 			pispec->intrspec_pri = sockp->ls_intr_pri;
4705 			hdlp->ih_pri = sockp->ls_intr_pri;
4706 
4707 			return (DDI_SUCCESS);
4708 		}
4709 	}
4710 
4711 #if defined(PCMCIA_DEBUG)
4712 	if (pcmcia_debug) {
4713 		cmn_err(CE_CONT, "pcmcia_add_intr_impl() let adapter do it\n");
4714 	}
4715 #endif
4716 	pispec->intrspec_func = (uint32_t (*)())handler.handler;
4717 
4718 	/* set default IPL then check for override */
4719 
4720 	pispec->intrspec_pri = sockp->ls_intr_pri;
4721 	hdlp->ih_pri = pispec->intrspec_pri;
4722 
4723 #if defined(PCMCIA_DEBUG)
4724 	if (pcmcia_debug) {
4725 		cmn_err(CE_CONT, "pcmcia_add_intr_impl() socket=%d irq=%d"
4726 		    " handler_id=0X%x handler=%p arg1=%p arg2=%p\n",
4727 		    handler.socket, handler.irq,
4728 		    handler.handler_id, (void *)handler.handler, handler.arg1,
4729 		    handler.arg2);
4730 	}
4731 #endif
4732 
4733 	if ((ret = SET_IRQ(sockp->ls_if, adapt->pca_dip, &handler)) !=
4734 	    SUCCESS) {
4735 		sockp->ls_error = ret;
4736 		return (DDI_FAILURE);
4737 	}
4738 
4739 #if defined(PCMCIA_DEBUG)
4740 	if (pcmcia_debug) {
4741 		cmn_err(CE_CONT, "pcmcia_add_intr_impl()"
4742 		    " iblk_cookie=%p idev_cookie=%p\n"
4743 		    " ls_flags=0X%x PCS_COOKIES_VALID=0X%x\n",
4744 		    (void *)handler.iblk_cookie,
4745 		    (void *)handler.idev_cookie,
4746 		    sockp->ls_flags, PCS_COOKIES_VALID);
4747 	}
4748 #endif
4749 
4750 	if (!(sockp->ls_flags & PCS_COOKIES_VALID)) {
4751 		hdlp->ih_pri = (uint_t)(uintptr_t)*handler.iblk_cookie;
4752 		sockp->ls_iblk = *handler.iblk_cookie;
4753 		sockp->ls_idev = *handler.idev_cookie;
4754 		sockp->ls_flags |= PCS_COOKIES_VALID;
4755 	}
4756 
4757 	return (DDI_SUCCESS);
4758 }
4759 
4760 void
4761 pcmcia_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
4762     ddi_intr_handle_impl_t *hdlp)
4763 {
4764 
4765 	struct pcmcia_parent_private *ppd;
4766 	pcmcia_logical_socket_t *sockp;
4767 	clear_irq_handler_t handler;
4768 	struct intrspec *pispec;
4769 	int socket;
4770 
4771 #if defined(PCMCIA_DEBUG)
4772 	if (pcmcia_debug) {
4773 		cmn_err(CE_CONT, "pcmcia_remove_intr_impl() entered"
4774 		    " dip=%p rdip=%p hdlp=%p\n",
4775 		    (void *)dip, (void *)rdip, (void *)hdlp);
4776 	}
4777 #endif
4778 
4779 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
4780 	socket = ppd->ppd_socket;
4781 	sockp = pcmcia_sockets[socket];
4782 	pispec = ppd->ppd_intrspec;
4783 
4784 #if defined(PCMCIA_DEBUG)
4785 	if (pcmcia_debug) {
4786 		cmn_err(CE_CONT, "pcmcia_remove_intr_impl()"
4787 		    " ls_inthandlers=%p ls_intrspec=%p\n",
4788 		    (void *)sockp->ls_inthandlers,
4789 		    (void *)&sockp->ls_intrspec);
4790 	}
4791 #endif
4792 
4793 	/* first handle the multifunction case since it is simple */
4794 	mutex_enter(&sockp->ls_ilock);
4795 	if (sockp->ls_inthandlers != NULL) {
4796 		/* we must be MFC */
4797 		inthandler_t *intr;
4798 		int remhandler = 0;
4799 		intr = sockp->ls_inthandlers;
4800 
4801 		/* Check if there is only one handler left */
4802 		if ((intr->next == intr) && (intr->prev == intr)) {
4803 			if (intr->handler_id == (unsigned)(uintptr_t)rdip) {
4804 				sockp->ls_inthandlers = NULL;
4805 				remhandler++;
4806 				kmem_free(intr, sizeof (inthandler_t));
4807 			}
4808 		} else {
4809 			inthandler_t *first;
4810 			int done;
4811 
4812 			for (done = 0, first = intr; !done; intr = intr->next) {
4813 				if (intr->next == first)
4814 					done++;
4815 				if (intr->handler_id ==
4816 				    (unsigned)(uintptr_t)rdip) {
4817 					done++;
4818 
4819 					/*
4820 					 * If we're about to remove the
4821 					 *	handler at the head of
4822 					 *	the list, make the next
4823 					 *	handler in line the head.
4824 					 */
4825 					if (sockp->ls_inthandlers == intr)
4826 						sockp->ls_inthandlers =
4827 						    intr->next;
4828 
4829 					remque(intr);
4830 					kmem_free(intr, sizeof (inthandler_t));
4831 					break;
4832 				} /* handler_id */
4833 			} /* for */
4834 		} /* intr->next */
4835 
4836 		if (!remhandler) {
4837 			mutex_exit(&sockp->ls_ilock);
4838 			return;
4839 		}
4840 
4841 		/* need to get the dip that was used to add the handler */
4842 		rdip = sockp->ls_mfintr_dip;
4843 	}
4844 
4845 	mutex_exit(&sockp->ls_ilock);
4846 
4847 #if defined(PCMCIA_DEBUG)
4848 	if (pcmcia_debug) {
4849 		cmn_err(CE_CONT, "pcmcia_remove_intr_impl()"
4850 		    " pispec=%p rdip=%p\n",
4851 		    (void *)pispec, (void *)rdip);
4852 	}
4853 #endif
4854 
4855 	handler.socket = sockp->ls_socket;
4856 	handler.handler_id = (uint32_t)(uintptr_t)rdip;
4857 	handler.handler = (f_tt *)pispec->intrspec_func;
4858 	CLEAR_IRQ(sockp->ls_if, dip, &handler);
4859 }
4860 
4861 
4862 /* Consolidated interrupt processing interface */
4863 /*ARGSUSED*/
4864 int
4865 pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
4866     ddi_intr_handle_impl_t *hdlp, void *result)
4867 {
4868 	int	ret = DDI_SUCCESS;
4869 
4870 #if defined(PCMCIA_DEBUG)
4871 	if (pcmcia_debug) {
4872 		cmn_err(CE_CONT, "pcmcia_intr_ops() intr_op=%d\n",
4873 		    (int)intr_op);
4874 	}
4875 #endif
4876 
4877 	switch (intr_op) {
4878 	case DDI_INTROP_GETCAP:
4879 		*(int *)result = DDI_INTR_FLAG_LEVEL;
4880 		break;
4881 	case DDI_INTROP_SETCAP:
4882 		ret = DDI_ENOTSUP;
4883 		break;
4884 	case DDI_INTROP_ALLOC:
4885 		*(int *)result = hdlp->ih_scratch1;
4886 		break;
4887 	case DDI_INTROP_FREE:
4888 		break;
4889 	case DDI_INTROP_GETPRI:
4890 		if (pcmcia_add_intr_impl(dip, rdip, hdlp) != DDI_SUCCESS)
4891 			return (DDI_FAILURE);
4892 		*(int *)result = hdlp->ih_pri;
4893 		pcmcia_remove_intr_impl(dip, rdip, hdlp);
4894 		break;
4895 	case DDI_INTROP_SETPRI:
4896 		break;
4897 	case DDI_INTROP_ADDISR:
4898 		ret = pcmcia_add_intr_impl(dip, rdip, hdlp);
4899 		break;
4900 	case DDI_INTROP_REMISR:
4901 		pcmcia_remove_intr_impl(dip, rdip, hdlp);
4902 		break;
4903 	case DDI_INTROP_ENABLE:
4904 	case DDI_INTROP_DISABLE:
4905 		break;
4906 	case DDI_INTROP_NINTRS:
4907 	case DDI_INTROP_NAVAIL:
4908 		*(int *)result = i_ddi_get_intx_nintrs(rdip);
4909 		break;
4910 	case DDI_INTROP_SUPPORTED_TYPES:
4911 		/* PCI nexus driver supports only fixed interrupts */
4912 		*(int *)result = i_ddi_get_intx_nintrs(rdip) ?
4913 		    DDI_INTR_TYPE_FIXED : 0;
4914 		break;
4915 	default:
4916 		ret = DDI_ENOTSUP;
4917 		break;
4918 	}
4919 
4920 	return (ret);
4921 }
4922 
4923 #elif defined(__x86) || defined(__amd64)
4924 
4925 static struct intrspec	*pcmcia_intr_get_ispec(dev_info_t *, int,
4926 			    pcmcia_logical_socket_t **);
4927 static struct intrspec	*pcmcia_intr_add_isr(dev_info_t *, dev_info_t *,
4928 			    ddi_intr_handle_impl_t *);
4929 static int		pcmcia_intr_enable_isr(dev_info_t *, dev_info_t *,
4930 			    ddi_intr_handle_impl_t *);
4931 static void		pcmcia_intr_remove_isr(dev_info_t *, dev_info_t *,
4932 			    ddi_intr_handle_impl_t *);
4933 static void		pcmcia_intr_disable_isr(dev_info_t *, dev_info_t *,
4934 			    ddi_intr_handle_impl_t *);
4935 
4936 /*
4937  * pcmcia_intr_get_ispec:
4938  *	This is mostly copied from older 'pcmcia_get_intrspec' function
4939  */
4940 static struct intrspec *
4941 pcmcia_intr_get_ispec(dev_info_t *rdip, int inum,
4942     pcmcia_logical_socket_t **sockp)
4943 {
4944 	int				socket;
4945 	struct intrspec			*intrspec;
4946 	struct pcmcia_parent_private	*ppd;
4947 
4948 	if ((int)inum > 0 || (ddi_getprop(DDI_DEV_T_ANY, rdip,
4949 	    DDI_PROP_DONTPASS, "interrupts", -1) < 0))
4950 		return (NULL);
4951 
4952 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
4953 	if (ppd == NULL || ppd->ppd_intrspec == NULL)
4954 		return (NULL);
4955 
4956 	if ((socket = ppd->ppd_socket) < 0)
4957 		return (NULL);
4958 
4959 	if ((*sockp = pcmcia_sockets[socket]) == NULL)
4960 		return (NULL);
4961 
4962 	intrspec = ppd->ppd_intrspec;
4963 	if (intrspec->intrspec_vec == 0 && (*sockp)->ls_intr_vec != 0)
4964 		intrspec->intrspec_vec = (*sockp)->ls_intr_vec;
4965 
4966 	return (intrspec);
4967 }
4968 
4969 static struct intrspec *
4970 pcmcia_intr_add_isr(dev_info_t *dip, dev_info_t *rdip,
4971     ddi_intr_handle_impl_t *hdlp)
4972 {
4973 	int				socket;
4974 	struct intrspec			*ispecp;
4975 	struct pcmcia_adapter		*adapt;
4976 	pcmcia_logical_socket_t		*sockp;
4977 	struct pcmcia_parent_private	*ppd;
4978 
4979 #if defined(PCMCIA_DEBUG)
4980 	if (pcmcia_debug)
4981 		cmn_err(CE_CONT, "pcmcia_intr_add_isr: "
4982 		    "dip=0x%p rdip=0x%p hdlp=0x%p\n",
4983 		    (void *)dip, (void *)rdip, (void *)hdlp);
4984 #endif	/* PCMCIA_DEBUG */
4985 
4986 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
4987 	socket = ppd->ppd_socket;
4988 	sockp = pcmcia_sockets[socket];
4989 	adapt = sockp->ls_adapter;
4990 
4991 	ispecp = ppd->ppd_intrspec;
4992 	if (ispecp == NULL) {
4993 		sockp->ls_error = BAD_IRQ;
4994 		return (ispecp);
4995 	}
4996 
4997 	/*
4998 	 * check if multifunction and do the right thing
4999 	 * we put an intercept in between the mfc handler and us so we can
5000 	 * catch and process. We might be able to optimize this depending
5001 	 * on the card features (a future option).
5002 	 */
5003 	if (ppd->ppd_flags & PPD_CARD_MULTI &&
5004 	    hdlp->ih_cb_func != pcmcia_mfc_intr) {
5005 		inthandler_t *intr;
5006 
5007 		/*
5008 		 * note that the first function is a special case since it
5009 		 * sets things up.  We fall through to the lower code and
5010 		 * get the hardware set up. Subsequent times we just lock
5011 		 * the list and insert the handler and all is well.
5012 		 */
5013 		intr = kmem_zalloc(sizeof (inthandler_t), KM_NOSLEEP);
5014 		if (intr == NULL) {
5015 			sockp->ls_error = BAD_IRQ;
5016 			return (NULL);
5017 		}
5018 
5019 		intr->intr = (uint32_t (*)())hdlp->ih_cb_func;
5020 		intr->handler_id = (uint32_t)(uintptr_t)rdip;
5021 		intr->arg1 = hdlp->ih_cb_arg1;
5022 		intr->arg2 = hdlp->ih_cb_arg2;
5023 		intr->socket = socket;
5024 		mutex_enter(&sockp->ls_ilock);
5025 		if (sockp->ls_inthandlers == NULL) {
5026 			intr->next = intr->prev = intr;
5027 			sockp->ls_inthandlers = intr;
5028 			sockp->ls_mfintr_dip = rdip;
5029 		} else {
5030 			insque(intr, sockp->ls_inthandlers);
5031 		}
5032 		mutex_exit(&sockp->ls_ilock);
5033 		return (ispecp);
5034 	}
5035 
5036 	/*
5037 	 * Do we need to allocate an IRQ at this point or not?
5038 	 */
5039 	if (adapt->pca_flags & PCA_RES_NEED_IRQ) {
5040 		int i, irq;
5041 
5042 		/*
5043 		 * this adapter needs IRQ allocations
5044 		 * this is only necessary if it is the first function on the
5045 		 * card being setup. The socket will keep the allocation info
5046 		 */
5047 		/* all functions use same intrspec except mfc handler */
5048 		if (hdlp->ih_cb_func == pcmcia_mfc_intr) {
5049 			/*
5050 			 * We treat this special in order to allow things to
5051 			 * work properly for MFC cards. The intrspec for the
5052 			 * mfc dispatcher is intercepted and taken from the
5053 			 * logical socket in order to not be trying to
5054 			 * multiplex the meaning when ENABLE is called.
5055 			 */
5056 			ispecp = &sockp->ls_intrspec;
5057 			((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp;
5058 		}
5059 
5060 		if (adapt->pca_flags & PCA_IRQ_ISA) {
5061 			for (irq = -1, i = 1; irq == -1 && i < 16; i++) {
5062 				/* find available and usable IRQ level */
5063 				if (adapt->pca_avail_intr & (1 << i))
5064 					irq = pcmcia_get_intr(dip, i);
5065 			}
5066 		}
5067 		if (irq < 0) {
5068 			sockp->ls_error = NO_RESOURCE;
5069 			return (NULL);
5070 		}
5071 		hdlp->ih_vector = sockp->ls_intr_vec = irq;
5072 
5073 
5074 #if defined(PCMCIA_DEBUG)
5075 		if (pcmcia_debug)
5076 			cmn_err(CE_CONT, "allocated irq=%x\n", irq);
5077 #endif	/* PCMCIA_DEBUG */
5078 
5079 		ispecp->intrspec_vec = sockp->ls_intr_vec;
5080 		ispecp->intrspec_pri = sockp->ls_intr_pri;
5081 		return (ispecp);
5082 	}
5083 
5084 	if (ispecp->intrspec_func != NULL)
5085 		ispecp->intrspec_func = hdlp->ih_cb_func;
5086 
5087 	/* set default IPL then check for override */
5088 	ispecp->intrspec_pri = sockp->ls_intr_pri;
5089 	return (ispecp);
5090 }
5091 
5092 
5093 static int
5094 pcmcia_intr_enable_isr(dev_info_t *dip, dev_info_t *rdip,
5095     ddi_intr_handle_impl_t *hdlp)
5096 {
5097 	int				socket, ret;
5098 	int				irq = 0;	/* default case */
5099 	dev_info_t			*parent = ddi_root_node();
5100 	struct intrspec			*ispecp;
5101 	set_irq_handler_t		handler;
5102 	struct pcmcia_adapter		*adapt;
5103 	pcmcia_logical_socket_t		*sockp;
5104 	struct pcmcia_parent_private	*ppd;
5105 
5106 #if defined(PCMCIA_DEBUG)
5107 	if (pcmcia_debug)
5108 		cmn_err(CE_CONT, "pcmcia_intr_enable_isr: "
5109 		    "dip=0x%p rdip=0x%p hdlp=0x%p\n",
5110 		    (void *)dip, (void *)rdip, (void *)hdlp);
5111 #endif	/* PCMCIA_DEBUG */
5112 
5113 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
5114 	socket = ppd->ppd_socket;
5115 	sockp = pcmcia_sockets[socket];
5116 	adapt = sockp->ls_adapter;
5117 
5118 	ispecp = ppd->ppd_intrspec;
5119 	ASSERT(ispecp);
5120 
5121 	mutex_enter(&sockp->ls_ilock);
5122 	if ((sockp->ls_inthandlers != NULL) &&
5123 	    ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp !=
5124 	    &sockp->ls_intrspec) {
5125 		inthandler_t *intr = sockp->ls_inthandlers;
5126 
5127 		ASSERT(ppd->ppd_flags & PPD_CARD_MULTI);
5128 
5129 		/* Only one handler. So, call ddi_add_intr on it */
5130 		if ((intr->next == intr) && (intr->prev == intr)) {
5131 			hdlp->ih_cb_func = pcmcia_mfc_intr;
5132 			hdlp->ih_cb_arg1 = (caddr_t)sockp;
5133 			hdlp->ih_cb_arg2 = NULL;
5134 
5135 			ret = (*(DEVI(parent)->devi_ops->devo_bus_ops->
5136 			    bus_intr_op))(parent, rdip, DDI_INTROP_ENABLE,
5137 			    hdlp, NULL);
5138 
5139 			if (ret == DDI_FAILURE) {
5140 				sockp->ls_inthandlers = NULL;
5141 				kmem_free(intr, sizeof (inthandler_t));
5142 				sockp->ls_error = BAD_IRQ;
5143 				mutex_exit(&sockp->ls_ilock);
5144 				return (ret);
5145 			}
5146 		}
5147 		mutex_exit(&sockp->ls_ilock);
5148 		hdlp->ih_vector = ispecp->intrspec_vec = sockp->ls_intr_vec;
5149 		hdlp->ih_pri = sockp->ls_intr_pri;
5150 		sockp->ls_iblk = (ddi_iblock_cookie_t)(uintptr_t)
5151 		    sockp->ls_intr_pri;
5152 		sockp->ls_idev.idev_vector = (ushort_t)hdlp->ih_vector;
5153 		sockp->ls_idev.idev_priority = (ushort_t)sockp->ls_intr_pri;
5154 		return (DDI_SUCCESS);
5155 	}
5156 	mutex_exit(&sockp->ls_ilock);
5157 
5158 	if (adapt->pca_flags & PCA_RES_NEED_IRQ) {
5159 		if (hdlp->ih_cb_func == pcmcia_mfc_intr)
5160 			ispecp = (struct intrspec *)&sockp->ls_intrspec;
5161 
5162 		/* XXX: remove it later as this is done in _add_isr as well */
5163 		ispecp->intrspec_vec = sockp->ls_intr_vec;
5164 		ispecp->intrspec_pri = sockp->ls_intr_pri;
5165 
5166 		/* Enable interrupts */
5167 		ret = (*(DEVI(parent)->devi_ops->devo_bus_ops->bus_intr_op))(
5168 		    parent, rdip, DDI_INTROP_ENABLE, hdlp, NULL);
5169 
5170 		sockp->ls_iblk = (ddi_iblock_cookie_t)(uintptr_t)
5171 		    sockp->ls_intr_pri;
5172 		sockp->ls_idev.idev_vector = (ushort_t)sockp->ls_intr_vec;
5173 		sockp->ls_idev.idev_priority = (ushort_t)sockp->ls_intr_pri;
5174 
5175 		if (ret != DDI_SUCCESS)
5176 			sockp->ls_error = BAD_IRQ;
5177 		return (ret);
5178 	}
5179 
5180 #if defined(PCMCIA_DEBUG)
5181 	if (pcmcia_debug)
5182 		cmn_err(CE_CONT, "pcmcia_intr_enable_isr; let adapter do it\n");
5183 #endif	/* PCMCIA_DEBUG */
5184 
5185 	handler.socket = sockp->ls_socket;
5186 	handler.irq = irq;
5187 	handler.handler = (f_tt *)hdlp->ih_cb_func;
5188 	handler.arg1 = hdlp->ih_cb_arg1;
5189 	handler.arg2 = hdlp->ih_cb_arg2;
5190 	handler.handler_id = (uint32_t)(uintptr_t)rdip;
5191 	if (ispecp->intrspec_func != NULL)
5192 		ispecp->intrspec_func = hdlp->ih_cb_func;
5193 
5194 	/* set default IPL then check for override */
5195 	ispecp->intrspec_pri = sockp->ls_intr_pri;
5196 
5197 	if ((ret = SET_IRQ(sockp->ls_if, adapt->pca_dip, &handler)) !=
5198 	    SUCCESS) {
5199 		sockp->ls_error = ret;
5200 		return (DDI_FAILURE);
5201 	}
5202 	ispecp->intrspec_func = hdlp->ih_cb_func;
5203 	if (!(sockp->ls_flags & PCS_COOKIES_VALID)) {
5204 		sockp->ls_iblk = *handler.iblk_cookie;
5205 		sockp->ls_idev = *handler.idev_cookie;
5206 		sockp->ls_flags |= PCS_COOKIES_VALID;
5207 	}
5208 	return (DDI_SUCCESS);
5209 }
5210 
5211 /* ARGSUSED */
5212 static void
5213 pcmcia_intr_remove_isr(dev_info_t *dip, dev_info_t *rdip,
5214     ddi_intr_handle_impl_t *hdlp)
5215 {
5216 	int				done, remhandler = 0;
5217 	inthandler_t			*intr, *first;
5218 	struct intrspec			*ispecp;
5219 	pcmcia_logical_socket_t		*sockp;
5220 
5221 #if defined(PCMCIA_DEBUG)
5222 	if (pcmcia_debug)
5223 		cmn_err(CE_CONT, "pcmcia_intr_remove_isr: "
5224 		    "dip=0x%p rdip=0x%p hdlp=0x%p\n",
5225 		    (void *)dip, (void *)rdip, (void *)hdlp);
5226 #endif	/* PCMCIA_DEBUG */
5227 
5228 	ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp);
5229 	ASSERT(ispecp);
5230 
5231 	/* first handle the multifunction case since it is simple */
5232 	mutex_enter(&sockp->ls_ilock);
5233 	if (sockp->ls_inthandlers != NULL &&
5234 	    ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp !=
5235 	    &sockp->ls_intrspec) {
5236 
5237 		intr = sockp->ls_inthandlers;
5238 
5239 		/* Check if there is only one handler left */
5240 		if ((intr->next == intr) && (intr->prev == intr)) {
5241 			if (intr->handler_id == (uint32_t)(uintptr_t)rdip) {
5242 				sockp->ls_inthandlers = NULL;
5243 				remhandler++;
5244 				kmem_free(intr, sizeof (inthandler_t));
5245 			}
5246 
5247 		} else {
5248 			for (done = 0, first = intr; !done; intr = intr->next) {
5249 				if (intr->next == first)
5250 					done++;
5251 				if (intr->handler_id ==
5252 				    (uint32_t)(uintptr_t)rdip) {
5253 					done++;
5254 
5255 					/*
5256 					 * If we're about to remove the handler
5257 					 * at the head of the list, make the
5258 					 * next handler in line the head.
5259 					 */
5260 					if (sockp->ls_inthandlers == intr)
5261 					    sockp->ls_inthandlers = intr->next;
5262 
5263 					remque(intr);
5264 					kmem_free(intr, sizeof (inthandler_t));
5265 					break;
5266 				} /* handler_id */
5267 			} /* end of for */
5268 		} /* end of if intr->next */
5269 
5270 		if (!remhandler) {
5271 			mutex_exit(&sockp->ls_ilock);
5272 			return;
5273 		}
5274 	}
5275 	mutex_exit(&sockp->ls_ilock);
5276 
5277 	if (sockp->ls_adapter->pca_flags & PCA_RES_NEED_IRQ) {
5278 		sockp->ls_intr_vec = 0;
5279 		ispecp->intrspec_vec = 0;
5280 	}
5281 }
5282 
5283 
5284 static void
5285 pcmcia_intr_disable_isr(dev_info_t *dip, dev_info_t *rdip,
5286     ddi_intr_handle_impl_t *hdlp)
5287 {
5288 	int				socket, ret;
5289 	dev_info_t			*parent;
5290 	struct intrspec			*ispecp;
5291 	clear_irq_handler_t		handler;
5292 	struct pcmcia_adapter		*adapt;
5293 	pcmcia_logical_socket_t		*sockp;
5294 	struct pcmcia_parent_private	*ppd;
5295 	ihdl_plat_t			*ihdl_plat_datap =
5296 					    (ihdl_plat_t *)hdlp->ih_private;
5297 
5298 #if defined(PCMCIA_DEBUG)
5299 	if (pcmcia_debug)
5300 		cmn_err(CE_CONT, "pcmcia_intr_disable_isr: "
5301 		    "dip=0x%p rdip=0x%p hdlp=0x%p\n",
5302 		    (void *)dip, (void *)rdip, (void *)hdlp);
5303 #endif	/* PCMCIA_DEBUG */
5304 
5305 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(rdip);
5306 	socket = ppd->ppd_socket;
5307 	sockp = pcmcia_sockets[socket];
5308 	adapt = sockp->ls_adapter;
5309 	ispecp = ppd->ppd_intrspec;
5310 	ASSERT(ispecp);
5311 
5312 	mutex_enter(&sockp->ls_ilock);
5313 	if (sockp->ls_inthandlers != NULL &&
5314 	    ihdl_plat_datap->ip_ispecp != &sockp->ls_intrspec) {
5315 		inthandler_t	*intr = sockp->ls_inthandlers;
5316 
5317 		/* Check if there is only one handler left */
5318 		if ((intr->next == intr) && (intr->prev == intr)) {
5319 			if (intr->handler_id != (uint32_t)(uintptr_t)rdip)
5320 				/*
5321 				 * need to get the dip that was
5322 				 * used to add the handler
5323 				 */
5324 				rdip = sockp->ls_mfintr_dip;
5325 				ispecp = (struct intrspec *)&sockp->ls_intrspec;
5326 		} else {
5327 			/* Don't call cleanup if list still has members */
5328 			mutex_exit(&sockp->ls_ilock);
5329 			return;
5330 		}
5331 	}
5332 	mutex_exit(&sockp->ls_ilock);
5333 
5334 	if (ihdl_plat_datap->ip_ispecp ==
5335 	    (struct intrspec *)&sockp->ls_intrspec)
5336 		ispecp = ihdl_plat_datap->ip_ispecp;
5337 
5338 	if (adapt->pca_flags & PCA_RES_NEED_IRQ) {
5339 		ret = ispecp->intrspec_vec;
5340 		parent = ddi_root_node();
5341 		ret = (*(DEVI(parent)->devi_ops->devo_bus_ops->bus_intr_op))(
5342 		    parent, rdip, DDI_INTROP_DISABLE, hdlp, NULL);
5343 		(void) pcmcia_return_intr(dip, hdlp->ih_vector);
5344 #if defined(PCMCIA_DEBUG)
5345 		if (pcmcia_debug)
5346 			cmn_err(CE_CONT, "pcmcia_intr_disable_isr: "
5347 			    "INTROP_DISABLE returned %x\n", ret);
5348 #endif	/* PCMCIA_DEBUG */
5349 	} else {
5350 		handler.socket = sockp->ls_socket;
5351 		handler.handler_id = (uint32_t)(uintptr_t)rdip;
5352 		handler.handler = (f_tt *)ispecp->intrspec_func;
5353 		ret = CLEAR_IRQ(sockp->ls_if, dip, &handler);
5354 #if defined(PCMCIA_DEBUG)
5355 		if (pcmcia_debug)
5356 			cmn_err(CE_CONT, "pcmcia_intr_disable_isr: "
5357 			    "CLEAR_IRQ returned %x\n", ret);
5358 #endif	/* PCMCIA_DEBUG */
5359 	}
5360 }
5361 
5362 /* Consolidated interrupt processing interface */
5363 int
5364 pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
5365     ddi_intr_handle_impl_t *hdlp, void *result)
5366 {
5367 	struct intrspec		*ispecp;
5368 	pcmcia_logical_socket_t	*sockp;
5369 
5370 #if defined(PCMCIA_DEBUG)
5371 	if (pcmcia_debug)
5372 		cmn_err(CE_CONT, "pcmcia_intr_ops: "
5373 		    "dip=0x%p rdip=0x%p op=0x%x hdlp=0x%p\n",
5374 		    (void *)dip, (void *)rdip, intr_op, (void *)hdlp);
5375 #endif	/* PCMCIA_DEBUG */
5376 
5377 	switch (intr_op) {
5378 	case DDI_INTROP_SUPPORTED_TYPES:
5379 		if (ddi_get_parent_data(rdip) == NULL) {
5380 			*(int *)result = 0;
5381 			return (DDI_FAILURE);
5382 		}
5383 		*(int *)result = DDI_INTR_TYPE_FIXED;
5384 		break;
5385 	case DDI_INTROP_GETCAP:
5386 		*(int *)result = DDI_INTR_FLAG_LEVEL;
5387 		break;
5388 	case DDI_INTROP_NINTRS:
5389 	case DDI_INTROP_NAVAIL:
5390 		if (i_ddi_get_intx_nintrs(rdip) == 0) {
5391 			*(int *)result = 0;
5392 			return (DDI_FAILURE);
5393 		}
5394 		*(int *)result = 1;	/* for PCMCIA there is only one intr */
5395 		break;
5396 	case DDI_INTROP_ALLOC:
5397 		if ((ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum,
5398 		    &sockp)) == NULL)
5399 			return (DDI_FAILURE);
5400 		*(int *)result = hdlp->ih_scratch1;
5401 		break;
5402 	case DDI_INTROP_FREE:
5403 		break;
5404 	case DDI_INTROP_GETPRI:
5405 		ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp);
5406 		if (ispecp == NULL) {
5407 			*(int *)result = 0;
5408 			return (DDI_FAILURE);
5409 		}
5410 
5411 		*(int *)result = ispecp->intrspec_pri = sockp->ls_intr_pri;
5412 		break;
5413 	case DDI_INTROP_SETPRI:
5414 		if (*(int *)result > LOCK_LEVEL)
5415 			return (DDI_FAILURE);
5416 		ispecp = pcmcia_intr_get_ispec(rdip, hdlp->ih_inum, &sockp);
5417 		ASSERT(ispecp);
5418 		ispecp->intrspec_pri = sockp->ls_intr_pri = *(int *)result;
5419 		break;
5420 	case DDI_INTROP_ADDISR:
5421 		if ((ispecp = pcmcia_intr_add_isr(dip, rdip, hdlp)) == NULL)
5422 			return (DDI_FAILURE);
5423 		((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp;
5424 		break;
5425 	case DDI_INTROP_REMISR:
5426 		pcmcia_intr_remove_isr(dip, rdip, hdlp);
5427 		break;
5428 	case DDI_INTROP_ENABLE:
5429 		if (pcmcia_intr_enable_isr(dip, rdip, hdlp) != DDI_SUCCESS)
5430 			return (DDI_FAILURE);
5431 		break;
5432 	case DDI_INTROP_DISABLE:
5433 		pcmcia_intr_disable_isr(dip, rdip, hdlp);
5434 		break;
5435 	default:
5436 		return (DDI_ENOTSUP);
5437 	}
5438 
5439 	return (DDI_SUCCESS);
5440 }
5441 #endif
5442