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