17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5a9fb0aerw * Common Development and Distribution License (the "License").
6a9fb0aerw * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
22582c04drui wang - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*
277c478bdstevel@tonic-gate * PCMCIA NEXUS
287c478bdstevel@tonic-gate *	The PCMCIA module is a generalized interface for
297c478bdstevel@tonic-gate *	implementing PCMCIA nexus drivers.  It preserves
307c478bdstevel@tonic-gate *	the logical socket name space while allowing multiple
317c478bdstevel@tonic-gate *	instances of the hardware to be properly represented
327c478bdstevel@tonic-gate *	in the device tree.
337c478bdstevel@tonic-gate *
347c478bdstevel@tonic-gate *	The nexus also exports events to an event manager
357c478bdstevel@tonic-gate *	driver if it has registered.
367c478bdstevel@tonic-gate */
377c478bdstevel@tonic-gate
387c478bdstevel@tonic-gate#include <sys/types.h>
397c478bdstevel@tonic-gate#include <sys/systm.h>
407c478bdstevel@tonic-gate#include <sys/user.h>
417c478bdstevel@tonic-gate#include <sys/buf.h>
427c478bdstevel@tonic-gate#include <sys/file.h>
437c478bdstevel@tonic-gate#include <sys/uio.h>
447c478bdstevel@tonic-gate#include <sys/conf.h>
457c478bdstevel@tonic-gate#include <sys/stat.h>
467c478bdstevel@tonic-gate#include <sys/autoconf.h>
477c478bdstevel@tonic-gate#include <sys/vtoc.h>
487c478bdstevel@tonic-gate#include <sys/dkio.h>
497c478bdstevel@tonic-gate#include <sys/ddi.h>
507c478bdstevel@tonic-gate#include <sys/debug.h>
517c478bdstevel@tonic-gate#include <sys/sunddi.h>
527c478bdstevel@tonic-gate#include <sys/sunndi.h>
537c478bdstevel@tonic-gate#include <sys/cred.h>
547c478bdstevel@tonic-gate#include <sys/kstat.h>
557c478bdstevel@tonic-gate#include <sys/kmem.h>
567c478bdstevel@tonic-gate#include <sys/modctl.h>
577c478bdstevel@tonic-gate#include <sys/kobj.h>
587c478bdstevel@tonic-gate#include <sys/callb.h>
597c478bdstevel@tonic-gate#include <sys/param.h>
607c478bdstevel@tonic-gate#include <sys/thread.h>
617c478bdstevel@tonic-gate#include <sys/proc.h>
627c478bdstevel@tonic-gate
637c478bdstevel@tonic-gate#include <sys/pctypes.h>
647c478bdstevel@tonic-gate#include <sys/pcmcia.h>
657c478bdstevel@tonic-gate#include <sys/sservice.h>
667c478bdstevel@tonic-gate#include <pcmcia/sys/cs_types.h>
677c478bdstevel@tonic-gate#include <pcmcia/sys/cis.h>
687c478bdstevel@tonic-gate#include <pcmcia/sys/cis_handlers.h>
697c478bdstevel@tonic-gate#include <pcmcia/sys/cs.h>
707c478bdstevel@tonic-gate#include <pcmcia/sys/cs_priv.h>
717c478bdstevel@tonic-gate
727c478bdstevel@tonic-gate#ifdef sparc
737c478bdstevel@tonic-gate#include <sys/ddi_subrdefs.h>
747a364d2schwartz
757a364d2schwartz#elif defined(__x86) || defined(__amd64)
767a364d2schwartz#include <sys/mach_intr.h>
777c478bdstevel@tonic-gate#endif
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate#undef SocketServices
807c478bdstevel@tonic-gate
817c478bdstevel@tonic-gate/* some bus specific stuff */
827c478bdstevel@tonic-gate
837c478bdstevel@tonic-gate/* need PCI regspec size for worst case at present */
847c478bdstevel@tonic-gate#include <sys/pci.h>
857c478bdstevel@tonic-gate
867c478bdstevel@tonic-gatetypedef struct pcmcia_logical_socket {
877c478bdstevel@tonic-gate	int			ls_socket; /* adapter's socket number */
887c478bdstevel@tonic-gate	uint32_t		ls_flags;
897c478bdstevel@tonic-gate	struct pcmcia_adapter	*ls_adapter;
907c478bdstevel@tonic-gate	pcmcia_if_t		*ls_if;
917c478bdstevel@tonic-gate	dev_info_t		*ls_sockdrv;
927c478bdstevel@tonic-gate	dev_info_t		*ls_dip[PCMCIA_MAX_FUNCTIONS];
937c478bdstevel@tonic-gate	dev_info_t		*ls_mfintr_dip;
947c478bdstevel@tonic-gate	int			ls_functions;
957c478bdstevel@tonic-gate	uint32_t		ls_cs_events;
967c478bdstevel@tonic-gate	uint32_t		ls_intr_pri;
977c478bdstevel@tonic-gate	uint32_t		ls_intr_vec;
987c478bdstevel@tonic-gate	int			ls_intrrefs;
997c478bdstevel@tonic-gate	struct intrspec		ls_intrspec; /* MFC intrspec */
1007c478bdstevel@tonic-gate	inthandler_t		*ls_inthandlers; /* for multifunction cards */
1017c478bdstevel@tonic-gate	ddi_iblock_cookie_t	ls_iblk;
1027c478bdstevel@tonic-gate	ddi_idevice_cookie_t	ls_idev;
1037c478bdstevel@tonic-gate	kmutex_t		ls_ilock;
1047c478bdstevel@tonic-gate	int			ls_error; /* error for CS return */
1057c478bdstevel@tonic-gate} pcmcia_logical_socket_t;
1067c478bdstevel@tonic-gate
1077c478bdstevel@tonic-gate/*
1087c478bdstevel@tonic-gate * entry points used by the true nexus
1097c478bdstevel@tonic-gate */
1107c478bdstevel@tonic-gateint pcmcia_detach(dev_info_t *, ddi_detach_cmd_t);
1117c478bdstevel@tonic-gateint pcmcia_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
1127c478bdstevel@tonic-gateint pcmcia_prop_op(dev_t, dev_info_t *, dev_info_t *, ddi_prop_op_t,
1137c478bdstevel@tonic-gate			int, char *, caddr_t, int *);
1147c478bdstevel@tonic-gatevoid pcmcia_set_assigned(dev_info_t *, int, ra_return_t *);
1157c478bdstevel@tonic-gateint pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
1167c478bdstevel@tonic-gate    ddi_intr_handle_impl_t *hdlp, void *result);
1177c478bdstevel@tonic-gate
1187c478bdstevel@tonic-gate/*
1197c478bdstevel@tonic-gate * prototypes used internally by the nexus and sometimes Card Services
1207c478bdstevel@tonic-gate */
1217c478bdstevel@tonic-gateint SocketServices(int function, ...);
1227c478bdstevel@tonic-gate
1237c478bdstevel@tonic-gate
1247c478bdstevel@tonic-gatevoid *CISParser(int function, ...);
1257c478bdstevel@tonic-gateextern void *(*cis_parser)(int, ...);
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gatestruct regspec *pcmcia_cons_regspec(dev_info_t *, int, uchar_t *,
1287c478bdstevel@tonic-gate					ra_return_t *);
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gatestatic int (*pcmcia_card_services)(int, ...) = NULL;
1317c478bdstevel@tonic-gate
1327c478bdstevel@tonic-gate/*
1337c478bdstevel@tonic-gate * variables used in the logical/physical mappings
1347c478bdstevel@tonic-gate * that the nexus common code maintains.
1357c478bdstevel@tonic-gate */
1367c478bdstevel@tonic-gatestruct pcmcia_adapter *pcmcia_adapters[PCMCIA_MAX_ADAPTERS];
1377c478bdstevel@tonic-gateint    pcmcia_num_adapters;
1387c478bdstevel@tonic-gatepcmcia_logical_socket_t *pcmcia_sockets[PCMCIA_MAX_SOCKETS];
1397c478bdstevel@tonic-gateint    pcmcia_num_sockets;
1407c478bdstevel@tonic-gatepcmcia_logical_window_t *pcmcia_windows[PCMCIA_MAX_WINDOWS];
1417c478bdstevel@tonic-gateint    pcmcia_num_windows;
1427c478bdstevel@tonic-gatestruct power_entry pcmcia_power_table[PCMCIA_MAX_POWER];
1437c478bdstevel@tonic-gateint	pcmcia_num_power;
1447c478bdstevel@tonic-gate
1457c478bdstevel@tonic-gatestruct pcmcia_mif *pcmcia_mif_handlers = NULL;
1467c478bdstevel@tonic-gatepcm_dev_node_t *pcmcia_devnodes = NULL;
1477c478bdstevel@tonic-gate
1487c478bdstevel@tonic-gatekmutex_t pcmcia_global_lock;
1497c478bdstevel@tonic-gatekcondvar_t pcmcia_condvar;
1507c478bdstevel@tonic-gatekmutex_t pcmcia_enum_lock;
1517c478bdstevel@tonic-gate
1527c478bdstevel@tonic-gate/*
1537c478bdstevel@tonic-gate * Mapping of the device "type" to names acceptable to
1547c478bdstevel@tonic-gate * the DDI
1557c478bdstevel@tonic-gate */
1567c478bdstevel@tonic-gatestatic char *pcmcia_dev_type[] = {
1577c478bdstevel@tonic-gate	"multifunction",
1587c478bdstevel@tonic-gate	"byte",
1597c478bdstevel@tonic-gate	"serial",
1607c478bdstevel@tonic-gate	"parallel",
1617c478bdstevel@tonic-gate	"block",
1627c478bdstevel@tonic-gate	"display",
1637c478bdstevel@tonic-gate	"network",
1647c478bdstevel@tonic-gate	"block",
1657c478bdstevel@tonic-gate	"byte"
1667c478bdstevel@tonic-gate};
1677c478bdstevel@tonic-gate
1687c478bdstevel@tonic-gatechar *pcmcia_default_pm_mode = "parental-suspend-resume";
1697c478bdstevel@tonic-gate
1707c478bdstevel@tonic-gate/*
1717c478bdstevel@tonic-gate * generic names from the approved list:
1727c478bdstevel@tonic-gate *	disk tape pci sbus scsi token-ring isa keyboard display mouse
1737c478bdstevel@tonic-gate *	audio ethernet timer memory parallel serial rtc nvram scanner
1747c478bdstevel@tonic-gate *	floppy(controller) fddi isdn atm ide pccard video-in video-out
1757c478bdstevel@tonic-gate * in some cases there will need to be device class dependent names.
1767c478bdstevel@tonic-gate * network -> ethernet, token-ring, etc.
1777c478bdstevel@tonic-gate * this list is a first guess and is used when all else fails.
1787c478bdstevel@tonic-gate */
1797c478bdstevel@tonic-gate
1807c478bdstevel@tonic-gatechar *pcmcia_generic_names[] = {
1817c478bdstevel@tonic-gate	"multifunction",
1827c478bdstevel@tonic-gate	"memory",
1837c478bdstevel@tonic-gate	"serial",
1847c478bdstevel@tonic-gate	"parallel",
1857c478bdstevel@tonic-gate	"disk",
1867c478bdstevel@tonic-gate	"video",		/* no spec for video-out yet */
1877c478bdstevel@tonic-gate	"network",
1887c478bdstevel@tonic-gate	"aims",
1897c478bdstevel@tonic-gate	"scsi",
1907c478bdstevel@tonic-gate	"security"
1917c478bdstevel@tonic-gate};
1927c478bdstevel@tonic-gate
1937c478bdstevel@tonic-gate#define	PCM_GENNAME_SIZE	(sizeof (pcmcia_generic_names) / \
1947c478bdstevel@tonic-gate					sizeof (char *))
1957c478bdstevel@tonic-gate#define	PCMCIA_MAP_IO	0x0
1967c478bdstevel@tonic-gate#define	PCMCIA_MAP_MEM	0x1
1978134ee0rw#define	PPB_SUBTRACTIVE	((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8) | \
1988134ee0rw		(PCI_BRIDGE_PCI_IF_SUBDECODE))
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate/*
2017c478bdstevel@tonic-gate * The following should be 2^^n - 1
2027c478bdstevel@tonic-gate */
2037c478bdstevel@tonic-gate#define	PCMCIA_SOCKET_BITS	0x7f
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate#ifdef PCMCIA_DEBUG
2067c478bdstevel@tonic-gateint pcmcia_debug = 0x0;
2077c478bdstevel@tonic-gatestatic void pcmcia_dump_minors(dev_info_t *);
2087c478bdstevel@tonic-gate#endif
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gatestatic f_tt *pcmcia_cs_event = NULL;
2117c478bdstevel@tonic-gateint pcmcia_timer_id;
2127c478bdstevel@tonic-gatedev_info_t	*pcmcia_dip;
2137c478bdstevel@tonic-gate/*
2147c478bdstevel@tonic-gate * XXX - See comments in cs.c
2157c478bdstevel@tonic-gate */
2167c478bdstevel@tonic-gatestatic f_tt *pcmcia_cis_parser = NULL;
2177c478bdstevel@tonic-gate
2187c478bdstevel@tonic-gateextern struct pc_socket_services pc_socket_services;
2197c478bdstevel@tonic-gate
2207c478bdstevel@tonic-gate/* some function declarations */
2217c478bdstevel@tonic-gatestatic int pcm_adapter_callback(dev_info_t *, int, int, int);
2227c478bdstevel@tonic-gateextern void pcmcia_init_adapter(anp_t *, dev_info_t *);
2237c478bdstevel@tonic-gateextern void pcmcia_find_cards(anp_t *);
2247c478bdstevel@tonic-gateextern void pcmcia_merge_power(struct power_entry *);
2257c478bdstevel@tonic-gateextern void pcmcia_do_resume(int, pcmcia_logical_socket_t *);
2267c478bdstevel@tonic-gateextern void pcmcia_resume(int, pcmcia_logical_socket_t *);
2277c478bdstevel@tonic-gateextern void pcmcia_do_suspend(int, pcmcia_logical_socket_t *);
2287c478bdstevel@tonic-gateextern void pcm_event_manager(int, int, void *);
2297c478bdstevel@tonic-gatestatic void pcmcia_create_dev_info(int);
2307c478bdstevel@tonic-gatestatic int pcmcia_create_device(ss_make_device_node_t *);
2317c478bdstevel@tonic-gatestatic void pcmcia_init_devinfo(dev_info_t *, struct pcm_device_info *);
2327c478bdstevel@tonic-gatevoid pcmcia_fix_string(char *str);
2337c478bdstevel@tonic-gatedev_info_t *pcmcia_number_socket(dev_info_t *, int);
2347c478bdstevel@tonic-gatestatic int pcmcia_merge_conf(dev_info_t *);
2357c478bdstevel@tonic-gatestatic uint32_t pcmcia_mfc_intr(caddr_t, caddr_t);
2367c478bdstevel@tonic-gatevoid pcmcia_free_resources(dev_info_t *);
2377c478bdstevel@tonic-gatestatic void pcmcia_ppd_free(struct pcmcia_parent_private *ppd);
2387c478bdstevel@tonic-gateint pcmcia_get_intr(dev_info_t *, int);
2397c478bdstevel@tonic-gateint pcmcia_return_intr(dev_info_t *, int);
2408134ee0rwint pcmcia_ra_alloc(dev_info_t *, ndi_ra_request_t *, ra_return_t *, char *,
2418134ee0rw		dev_info_t **);
2427c478bdstevel@tonic-gateint pcmcia_ra_free(dev_info_t *, ra_return_t *, char *);
2437c478bdstevel@tonic-gate
2447c478bdstevel@tonic-gateextern int cs_init(void);
2457c478bdstevel@tonic-gateextern int cs_deinit(void);
2467c478bdstevel@tonic-gateextern void cisp_init(void);
2477c478bdstevel@tonic-gateextern void cis_deinit(void);
2487c478bdstevel@tonic-gate
2497c478bdstevel@tonic-gate/*
2507c478bdstevel@tonic-gate * non-DDI compliant functions are listed here
2517c478bdstevel@tonic-gate * some will be declared while others that have
2527c478bdstevel@tonic-gate * entries in .h files. All will be commented on.
2537c478bdstevel@tonic-gate *
2547c478bdstevel@tonic-gate * with declarations:
2557c478bdstevel@tonic-gate *	ddi_add_child
2567c478bdstevel@tonic-gate *	ddi_binding_name
2577c478bdstevel@tonic-gate *	ddi_bus_prop_op
2587c478bdstevel@tonic-gate *	ddi_ctlops
2597c478bdstevel@tonic-gate *	ddi_find_devinfo
2607c478bdstevel@tonic-gate *	ddi_get_name_addr
2617c478bdstevel@tonic-gate *	ddi_get_parent_data
2627c478bdstevel@tonic-gate *	ddi_hold_installed_driver
2637c478bdstevel@tonic-gate *	ddi_name_to_major
2647c478bdstevel@tonic-gate *	ddi_node_name
2657c478bdstevel@tonic-gate *	ddi_pathname
2667c478bdstevel@tonic-gate *	ddi_rele_driver
2677c478bdstevel@tonic-gate *	ddi_set_name_addr
2687c478bdstevel@tonic-gate *	ddi_set_parent_data
2697c478bdstevel@tonic-gate *	ddi_unorphan_devs
2707c478bdstevel@tonic-gate *	i_ddi_bind_node_to_driver
2717c478bdstevel@tonic-gate *	i_ddi_bind_node_to_driver
2727c478bdstevel@tonic-gate *	i_ddi_bus_map
2737c478bdstevel@tonic-gate *	i_ddi_map_fault
2747c478bdstevel@tonic-gate *	i_ddi_mem_alloc
2757c478bdstevel@tonic-gate *	i_ddi_mem_alloc
2767c478bdstevel@tonic-gate *	i_ddi_mem_free
2777c478bdstevel@tonic-gate *	i_ddi_mem_free
2787c478bdstevel@tonic-gate *	modload
2797c478bdstevel@tonic-gate *	modunload
2807c478bdstevel@tonic-gate */
2817c478bdstevel@tonic-gate
2827c478bdstevel@tonic-gateextern void ddi_unorphan_devs(major_t);
2837c478bdstevel@tonic-gate
2847c478bdstevel@tonic-gate/* Card&Socket Services entry points */
2857c478bdstevel@tonic-gatestatic int GetCookiesAndDip(sservice_t *);
2867c478bdstevel@tonic-gatestatic int SSGetAdapter(get_adapter_t *);
2877c478bdstevel@tonic-gatestatic int SSGetPage(get_page_t *);
2887c478bdstevel@tonic-gatestatic int SSGetSocket(get_socket_t *);
2897c478bdstevel@tonic-gatestatic int SSGetStatus(get_ss_status_t *);
2907c478bdstevel@tonic-gatestatic int SSGetWindow(get_window_t *);
2917c478bdstevel@tonic-gatestatic int SSInquireAdapter(inquire_adapter_t *);
2927c478bdstevel@tonic-gatestatic int SSInquireSocket(inquire_socket_t *);
2937c478bdstevel@tonic-gatestatic int SSInquireWindow(inquire_window_t *);
2947c478bdstevel@tonic-gatestatic int SSResetSocket(int, int);
2957c478bdstevel@tonic-gatestatic int SSSetPage(set_page_t *);
2967c478bdstevel@tonic-gatestatic int SSSetSocket(set_socket_t *);
2977c478bdstevel@tonic-gatestatic int SSSetWindow(set_window_t *);
2987c478bdstevel@tonic-gatestatic int SSSetIRQHandler(set_irq_handler_t *);
2997c478bdstevel@tonic-gatestatic int SSClearIRQHandler(clear_irq_handler_t *);
3007c478bdstevel@tonic-gate
3017c478bdstevel@tonic-gatestatic struct modldrv modlmisc = {
3027c478bdstevel@tonic-gate	&mod_miscops,		/* Type of module. This one is a driver */
30339b361bRichard Bean	"PCMCIA Nexus Support", /* Name of the module. */
3047c478bdstevel@tonic-gate};
3057c478bdstevel@tonic-gate
3067c478bdstevel@tonic-gatestatic struct modlinkage modlinkage = {
3077c478bdstevel@tonic-gate	MODREV_1, (void *)&modlmisc, NULL
3087c478bdstevel@tonic-gate};
3097c478bdstevel@tonic-gate
3107c478bdstevel@tonic-gateint
3117c478bdstevel@tonic-gate_init()
3127c478bdstevel@tonic-gate{
3137c478bdstevel@tonic-gate	int	ret;
3147c478bdstevel@tonic-gate
3157c478bdstevel@tonic-gate	cisp_init();
3167c478bdstevel@tonic-gate
3177c478bdstevel@tonic-gate	if (cs_init() != CS_SUCCESS) {
3185c066ecJerry Gilliam		if (cs_deinit() != CS_SUCCESS)
3195c066ecJerry Gilliam			cmn_err(CE_CONT, "pcmcia: _init cs_deinit error\n");
3205c066ecJerry Gilliam		return (-1);
3217c478bdstevel@tonic-gate	}
3227c478bdstevel@tonic-gate
3237c478bdstevel@tonic-gate	mutex_init(&pcmcia_global_lock, NULL, MUTEX_DEFAULT, NULL);
3247c478bdstevel@tonic-gate	cv_init(&pcmcia_condvar, NULL, CV_DRIVER, NULL);
3257c478bdstevel@tonic-gate	mutex_init(&pcmcia_enum_lock, NULL, MUTEX_DEFAULT, NULL);
3267c478bdstevel@tonic-gate
3277c478bdstevel@tonic-gate	if ((ret = mod_install(&modlinkage)) != 0) {
3287c478bdstevel@tonic-gate		mutex_destroy(&pcmcia_global_lock);
3297c478bdstevel@tonic-gate		cv_destroy(&pcmcia_condvar);
3307c478bdstevel@tonic-gate		mutex_destroy(&pcmcia_enum_lock);
3317c478bdstevel@tonic-gate	}
3327c478bdstevel@tonic-gate	return (ret);
3337c478bdstevel@tonic-gate}
3347c478bdstevel@tonic-gate
3357c478bdstevel@tonic-gateint
3367c478bdstevel@tonic-gate_fini()
3377c478bdstevel@tonic-gate{
3387c478bdstevel@tonic-gate	int	ret;
3397c478bdstevel@tonic-gate
3407c478bdstevel@tonic-gate	if ((ret = mod_remove(&modlinkage)) == 0) {
3417c478bdstevel@tonic-gate		mutex_destroy(&pcmcia_global_lock);
3427c478bdstevel@tonic-gate		cv_destroy(&pcmcia_condvar);
3437c478bdstevel@tonic-gate		mutex_destroy(&pcmcia_enum_lock);
3447c478bdstevel@tonic-gate		cis_deinit();
3457c478bdstevel@tonic-gate		if (cs_deinit() != CS_SUCCESS) {
3467c478bdstevel@tonic-gate			cmn_err(CE_CONT, "pcmcia: _fini cs_deinit error\n");
3477c478bdstevel@tonic-gate		}
3487c478bdstevel@tonic-gate	}
3497c478bdstevel@tonic-gate	return (ret);
3507c478bdstevel@tonic-gate}
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gateint
3537c478bdstevel@tonic-gate_info(struct modinfo *modinfop)
3547c478bdstevel@tonic-gate{
3557c478bdstevel@tonic-gate	return (mod_info(&modlinkage, modinfop));
3567c478bdstevel@tonic-gate}
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gateextern pri_t minclsyspri;
3597c478bdstevel@tonic-gate
3607c478bdstevel@tonic-gate/*
3617c478bdstevel@tonic-gate * pcmcia_attach()
3627c478bdstevel@tonic-gate *	the attach routine must make sure that everything needed is present
3637c478bdstevel@tonic-gate *	including real hardware.  The sequence of events is:
3647c478bdstevel@tonic-gate *		attempt to load all adapter drivers
36589b4368Bayard Bell *		attempt to load Card Services
3667c478bdstevel@tonic-gate *		initialize logical sockets
3677c478bdstevel@tonic-gate *		report the nexus exists
3687c478bdstevel@tonic-gate */
3697c478bdstevel@tonic-gate
3707c478bdstevel@tonic-gateint
3717c478bdstevel@tonic-gatepcmcia_attach(dev_info_t *dip, anp_t *adapter)
3727c478bdstevel@tonic-gate{
3737c478bdstevel@tonic-gate	int count, done, i;
3747c478bdstevel@tonic-gate
3757c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
3767c478bdstevel@tonic-gate	if (pcmcia_debug) {
3777c478bdstevel@tonic-gate		cmn_err(CE_CONT, "pcmcia_attach: dip=0x%p adapter=0x%p\n",
3787c478bdstevel@tonic-gate		    (void *)dip, (void *)adapter);
3797c478bdstevel@tonic-gate	}
3807c478bdstevel@tonic-gate#endif
3817c478bdstevel@tonic-gate
3827c478bdstevel@tonic-gate	pcmcia_dip = dip;
3837c478bdstevel@tonic-gate
3847c478bdstevel@tonic-gate	mutex_enter(&pcmcia_enum_lock);
3857c478bdstevel@tonic-gate	mutex_enter(&pcmcia_global_lock);
3867c478bdstevel@tonic-gate	if (pcmcia_num_adapters == 0) {
387ebf3735Toomas Soome		pcmcia_cis_parser = (f_tt *)(uintptr_t)CISParser;
3887c478bdstevel@tonic-gate		cis_parser = (void *(*)(int, ...)) CISParser;
3897c478bdstevel@tonic-gate		pcmcia_cs_event = (f_tt *)cs_event;
3907c478bdstevel@tonic-gate		cs_socket_services = SocketServices;
3917c478bdstevel@tonic-gate		/* tell CS we are up with basic init level */
3927c478bdstevel@tonic-gate		(void) cs_event(PCE_SS_INIT_STATE, PCE_SS_STATE_INIT, 0);
3937c478bdstevel@tonic-gate	}
3947c478bdstevel@tonic-gate
3957c478bdstevel@tonic-gate	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
3967c478bdstevel@tonic-gate	    PCM_DEVICETYPE, "pccard");
3977c478bdstevel@tonic-gate
3987c478bdstevel@tonic-gate	ddi_report_dev(dip);	/* directory/device naming */
3997c478bdstevel@tonic-gate
4007c478bdstevel@tonic-gate	/*
4017c478bdstevel@tonic-gate	 * now setup any power management stuff necessary.
4027c478bdstevel@tonic-gate	 * we do it here in order to ensure that all PC Card nexi
4037c478bdstevel@tonic-gate	 * implement it.
4047c478bdstevel@tonic-gate	 */
4057c478bdstevel@tonic-gate
4067c478bdstevel@tonic-gate	if (pm_create_components(dip, 1) != DDI_SUCCESS) {
4077c478bdstevel@tonic-gate		cmn_err(CE_WARN, "%s: not power managed\n",
4085c066ecJerry Gilliam		    ddi_get_name_addr(dip));
4097c478bdstevel@tonic-gate	} else {
4107c478bdstevel@tonic-gate		pm_set_normal_power(dip, 0, 1);
4117c478bdstevel@tonic-gate	}
4127c478bdstevel@tonic-gate
4137c478bdstevel@tonic-gate	/*
4147c478bdstevel@tonic-gate	 * setup the info necessary for Card Services/SocketServices
4157c478bdstevel@tonic-gate	 * and notify CS when ready.
4167c478bdstevel@tonic-gate	 */
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate	pcmcia_free_resources(dip);
4197c478bdstevel@tonic-gate	pcmcia_init_adapter(adapter, dip);
4207c478bdstevel@tonic-gate	/* exit mutex so CS can run for any cards found */
4217c478bdstevel@tonic-gate	mutex_exit(&pcmcia_global_lock);
4227c478bdstevel@tonic-gate
4237c478bdstevel@tonic-gate	/*
4247c478bdstevel@tonic-gate	 * make sure the devices are identified before
4257c478bdstevel@tonic-gate	 * returning.  We do this by checking each socket to see if
4267c478bdstevel@tonic-gate	 * a card is present.  If there is one, and there isn't a dip,
4277c478bdstevel@tonic-gate	 * we can't be done.  We scan the list of sockets doing the
4287c478bdstevel@tonic-gate	 * check. if we aren't done, wait for a condition variable to
4297c478bdstevel@tonic-gate	 * wakeup.
4307c478bdstevel@tonic-gate	 * Because we can miss a wakeup and because things can
4317c478bdstevel@tonic-gate	 * take time, we do eventually give up and have a timeout.
4327c478bdstevel@tonic-gate	 */
4337c478bdstevel@tonic-gate
4347c478bdstevel@tonic-gate	for (count = 0, done = 0;
4357c478bdstevel@tonic-gate	    done == 0 && count < max(pcmcia_num_sockets, 16);
4367c478bdstevel@tonic-gate	    count++) {
4377c478bdstevel@tonic-gate		done = 1;
4387c478bdstevel@tonic-gate		/* block CS while checking so we don't miss anything */
4397c478bdstevel@tonic-gate		mutex_enter(&pcmcia_global_lock);
4407c478bdstevel@tonic-gate		for (i = 0; i < pcmcia_num_sockets; i++) {
4417c478bdstevel@tonic-gate			get_ss_status_t status;
4427c478bdstevel@tonic-gate			if (pcmcia_sockets[i] == NULL)
4437c478bdstevel@tonic-gate				continue;
4447c478bdstevel@tonic-gate			bzero(&status, sizeof (status));
4457c478bdstevel@tonic-gate			status.socket = i;
4467c478bdstevel@tonic-gate			if (SSGetStatus(&status) == SUCCESS) {
4477c478bdstevel@tonic-gate				if (status.CardState & SBM_CD &&
4487c478bdstevel@tonic-gate				    pcmcia_sockets[i]->ls_dip[0] == NULL) {
4497c478bdstevel@tonic-gate					done = 0;
4507c478bdstevel@tonic-gate				}
4517c478bdstevel@tonic-gate			}
4527c478bdstevel@tonic-gate		}
4537c478bdstevel@tonic-gate		/* only wait if we aren't done with this set */
4547c478bdstevel@tonic-gate		if (!done) {
4557c478bdstevel@tonic-gate			mutex_exit(&pcmcia_global_lock);
4567c478bdstevel@tonic-gate			delay(10); /* give up CPU for a time */
4577c478bdstevel@tonic-gate			mutex_enter(&pcmcia_global_lock);
4587c478bdstevel@tonic-gate		}
4597c478bdstevel@tonic-gate		mutex_exit(&pcmcia_global_lock);
4607c478bdstevel@tonic-gate	}
4617c478bdstevel@tonic-gate
4627c478bdstevel@tonic-gate	mutex_exit(&pcmcia_enum_lock);
4637c478bdstevel@tonic-gate	return (DDI_SUCCESS);
4647c478bdstevel@tonic-gate}
4657c478bdstevel@tonic-gate
4667c478bdstevel@tonic-gate/*
4677c478bdstevel@tonic-gate * pcmcia_detach
4687c478bdstevel@tonic-gate *	unload everything and then detach the nexus
4697c478bdstevel@tonic-gate */
4707c478bdstevel@tonic-gate/* ARGSUSED */
4717c478bdstevel@tonic-gateint
4727c478bdstevel@tonic-gatepcmcia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4737c478bdstevel@tonic-gate{
4747c478bdstevel@tonic-gate	switch (cmd) {
4757c478bdstevel@tonic-gate	case DDI_DETACH:
4767c478bdstevel@tonic-gate		pm_destroy_components(dip);
4777c478bdstevel@tonic-gate		return (DDI_SUCCESS);
4787c478bdstevel@tonic-gate
4797c478bdstevel@tonic-gate	/*
4807c478bdstevel@tonic-gate	 * resume from a checkpoint
4817c478bdstevel@tonic-gate	 * We don't do anything special here since the adapter
4827c478bdstevel@tonic-gate	 * driver will generate resume events that we intercept
4837c478bdstevel@tonic-gate	 * and convert to insert events.
4847c478bdstevel@tonic-gate	 */
4857c478bdstevel@tonic-gate	case DDI_SUSPEND:
4867c478bdstevel@tonic-gate	case DDI_PM_SUSPEND:
4877c478bdstevel@tonic-gate		return (DDI_SUCCESS);
4887c478bdstevel@tonic-gate
4897c478bdstevel@tonic-gate	default:
4907c478bdstevel@tonic-gate		return (DDI_FAILURE);
4917c478bdstevel@tonic-gate	}
4927c478bdstevel@tonic-gate}
4937c478bdstevel@tonic-gate
4947c478bdstevel@tonic-gate/*
4957c478bdstevel@tonic-gate * card_services_error()
4967c478bdstevel@tonic-gate *	used to make 2.4/2.5 drivers get an error when
4977c478bdstevel@tonic-gate *	they try to initialize.
4987c478bdstevel@tonic-gate */
4997c478bdstevel@tonic-gatestatic int
5007c478bdstevel@tonic-gatecard_services_error()
5017c478bdstevel@tonic-gate{
5027c478bdstevel@tonic-gate	return (CS_BAD_VERSION);
5037c478bdstevel@tonic-gate}
5047c478bdstevel@tonic-gatestatic int (*cs_error_ptr)() = card_services_error;
5057c478bdstevel@tonic-gate
5067c478bdstevel@tonic-gate/*
5077c478bdstevel@tonic-gate * pcmcia_ctlops
5087c478bdstevel@tonic-gate *	handle the nexus control operations for the cases where
5097c478bdstevel@tonic-gate *	a PC Card driver gets called and we need to modify the
5107c478bdstevel@tonic-gate *	devinfo structure or otherwise do bus specific operations
5117c478bdstevel@tonic-gate */
5127c478bdstevel@tonic-gateint
5137c478bdstevel@tonic-gatepcmcia_ctlops(dev_info_t *dip, dev_info_t *rdip,
5143f068ebToomas Soome    ddi_ctl_enum_t ctlop, void *arg, void *result)
5157c478bdstevel@tonic-gate{
5167c478bdstevel@tonic-gate	int e;
5177c478bdstevel@tonic-gate	char name[64];
5187c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
5197c478bdstevel@tonic-gate	power_req_t *pm;
5207c478bdstevel@tonic-gate
5217c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
5227c478bdstevel@tonic-gate	if (pcmcia_debug) {
5237c478bdstevel@tonic-gate		cmn_err(CE_CONT, "pcmcia_ctlops(%p, %p, %d, %p, %p)\n",
5245c066ecJerry Gilliam		    (void *)dip, (void *)rdip, ctlop, (void *)arg,
5255c066ecJerry Gilliam		    (void *)result);
5267c478bdstevel@tonic-gate		if (rdip != NULL && ddi_get_name(rdip) != NULL)
5277c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\t[%s]\n", ddi_get_name(rdip));
5287c478bdstevel@tonic-gate	}
5297c478bdstevel@tonic-gate#endif
5307c478bdstevel@tonic-gate
5317c478bdstevel@tonic-gate	switch (ctlop) {
5327c478bdstevel@tonic-gate	case DDI_CTLOPS_REPORTDEV:
5337c478bdstevel@tonic-gate		if (rdip == (dev_info_t *)0)
5347c478bdstevel@tonic-gate			return (DDI_FAILURE);
5357c478bdstevel@tonic-gate
5367c478bdstevel@tonic-gate		if (strcmp("pcs", ddi_node_name(rdip)) == 0)
5377c478bdstevel@tonic-gate			cmn_err(CE_CONT, "?PCCard socket %d at %s@%s\n",
5385c066ecJerry Gilliam			    ddi_get_instance(rdip),
5395c066ecJerry Gilliam			    ddi_driver_name(dip), ddi_get_name_addr(dip));
5407c478bdstevel@tonic-gate		else
5417c478bdstevel@tonic-gate			cmn_err(CE_CONT, "?%s%d at %s@%s in socket %d\n",
5425c066ecJerry Gilliam			    ddi_driver_name(rdip),
5435c066ecJerry Gilliam			    ddi_get_instance(rdip),
5445c066ecJerry Gilliam			    ddi_driver_name(dip),
5455c066ecJerry Gilliam			    ddi_get_name_addr(dip),
5465c066ecJerry Gilliam			    CS_GET_SOCKET_NUMBER(
5475c066ecJerry Gilliam			    ddi_getprop(DDI_DEV_T_NONE, rdip,
5485c066ecJerry Gilliam			    DDI_PROP_DONTPASS,
5495c066ecJerry Gilliam			    PCM_DEV_SOCKET, -1)));
5507c478bdstevel@tonic-gate
5517c478bdstevel@tonic-gate		return (DDI_SUCCESS);
5527c478bdstevel@tonic-gate
5537c478bdstevel@tonic-gate	case DDI_CTLOPS_INITCHILD:
5547c478bdstevel@tonic-gate		/*
5557c478bdstevel@tonic-gate		 * we get control here before the child is called.
5567c478bdstevel@tonic-gate		 * we can change things if necessary.  This is where
5577c478bdstevel@tonic-gate		 * the CardServices hook gets planted.
5587c478bdstevel@tonic-gate		 */
5597c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
5607c478bdstevel@tonic-gate		if (pcmcia_debug) {
5617c478bdstevel@tonic-gate			cmn_err(CE_CONT, "pcmcia: init child: %s(%d) @%p\n",
5625c066ecJerry Gilliam			    ddi_node_name(arg), ddi_get_instance(arg),
5635c066ecJerry Gilliam			    (void *)arg);
5647c478bdstevel@tonic-gate			if (DEVI(arg)->devi_binding_name != NULL)
5657c478bdstevel@tonic-gate				cmn_err(CE_CONT, "\tbinding_name=%s\n",
5665c066ecJerry Gilliam				    DEVI(arg)->devi_binding_name);
5677c478bdstevel@tonic-gate			if (DEVI(arg)->devi_node_name != NULL)
5687c478bdstevel@tonic-gate				cmn_err(CE_CONT, "\tnode_name=%s\n",
5695c066ecJerry Gilliam				    DEVI(arg)->devi_node_name);
5707c478bdstevel@tonic-gate		}
5717c478bdstevel@tonic-gate#endif
5727c478bdstevel@tonic-gate
5737c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
5745c066ecJerry Gilliam		    ddi_get_parent_data((dev_info_t *)arg);
5757c478bdstevel@tonic-gate		if (ppd == NULL)
5767c478bdstevel@tonic-gate			return (DDI_FAILURE);
5777c478bdstevel@tonic-gate
5787c478bdstevel@tonic-gate		if (strcmp("pcs", ddi_node_name((dev_info_t *)arg)) == 0) {
5797c478bdstevel@tonic-gate			if (ppd == NULL)
5807c478bdstevel@tonic-gate				return (DDI_FAILURE);
5817c478bdstevel@tonic-gate			(void) sprintf(name, "%x",
5827c478bdstevel@tonic-gate			    (int)ppd->ppd_reg[0].phys_hi);
5837c478bdstevel@tonic-gate			ddi_set_name_addr((dev_info_t *)arg, name);
5847c478bdstevel@tonic-gate			return (DDI_SUCCESS);
5857c478bdstevel@tonic-gate		}
5867c478bdstevel@tonic-gate
5877c478bdstevel@tonic-gate		/*
5887c478bdstevel@tonic-gate		 * We don't want driver.conf files that stay in
5897c478bdstevel@tonic-gate		 * pseudo device form.	It is acceptable to have
5907c478bdstevel@tonic-gate		 * .conf files add properties only.
5917c478bdstevel@tonic-gate		 */
5927c478bdstevel@tonic-gate		if (ndi_dev_is_persistent_node((dev_info_t *)arg) == 0) {
5937c478bdstevel@tonic-gate			(void) pcmcia_merge_conf((dev_info_t *)arg);
5947c478bdstevel@tonic-gate			cmn_err(CE_WARN, "%s%d: %s.conf invalid",
5955c066ecJerry Gilliam			    ddi_get_name((dev_info_t *)arg),
5965c066ecJerry Gilliam			    ddi_get_instance((dev_info_t *)arg),
5975c066ecJerry Gilliam			    ddi_get_name((dev_info_t *)arg));
5987c478bdstevel@tonic-gate			return (DDI_FAILURE);
5997c478bdstevel@tonic-gate		}
6007c478bdstevel@tonic-gate
6017c478bdstevel@tonic-gate
6027c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
6037c478bdstevel@tonic-gate		if (pcmcia_debug && ppd != NULL) {
6047c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\tnreg=%x, intr=%x, socket=%x,"
6055c066ecJerry Gilliam			    " function=%x, active=%x, flags=%x\n",
6065c066ecJerry Gilliam			    ppd->ppd_nreg, ppd->ppd_intr,
6075c066ecJerry Gilliam			    ppd->ppd_socket, ppd->ppd_function,
6085c066ecJerry Gilliam			    ppd->ppd_active, ppd->ppd_flags);
6097c478bdstevel@tonic-gate		}
6107c478bdstevel@tonic-gate#endif
6117c478bdstevel@tonic-gate
6127c478bdstevel@tonic-gate		/*
6137c478bdstevel@tonic-gate		 * make sure names are relative to socket number
6147c478bdstevel@tonic-gate		 */
6157c478bdstevel@tonic-gate		if (ppd->ppd_function > 0) {
6167c478bdstevel@tonic-gate			int sock;
6177c478bdstevel@tonic-gate			int func;
6187c478bdstevel@tonic-gate			sock = ppd->ppd_socket;
6197c478bdstevel@tonic-gate			func = ppd->ppd_function;
6207c478bdstevel@tonic-gate			(void) sprintf(name, "%x,%x", sock, func);
6217c478bdstevel@tonic-gate		} else {
6227c478bdstevel@tonic-gate			(void) sprintf(name, "%x", ppd->ppd_socket);
6237c478bdstevel@tonic-gate		}
6247c478bdstevel@tonic-gate		ddi_set_name_addr((dev_info_t *)arg, name);
6257c478bdstevel@tonic-gate
6267c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
6277c478bdstevel@tonic-gate		if (pcmcia_debug)
6287c478bdstevel@tonic-gate			cmn_err(CE_CONT, "pcmcia: system init done for %s [%s] "
6295c066ecJerry Gilliam			    "nodeid: %x @%s\n",
6305c066ecJerry Gilliam			    ddi_get_name(arg), ddi_get_name_addr(arg),
6315c066ecJerry Gilliam			    DEVI(arg)->devi_nodeid, name);
6327c478bdstevel@tonic-gate		if (pcmcia_debug > 1)
6337c478bdstevel@tonic-gate			pcmcia_dump_minors((dev_info_t *)arg);
6347c478bdstevel@tonic-gate#endif
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6377c478bdstevel@tonic-gate
6387c478bdstevel@tonic-gate	case DDI_CTLOPS_UNINITCHILD:
6397c478bdstevel@tonic-gate
6407c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
6417c478bdstevel@tonic-gate		if (pcmcia_debug) {
6427c478bdstevel@tonic-gate			cmn_err(CE_CONT, "pcmcia: uninit child: %s(%d) @%p\n",
6435c066ecJerry Gilliam			    ddi_node_name(arg), ddi_get_instance(arg),
6445c066ecJerry Gilliam			    (void *)arg);
6457c478bdstevel@tonic-gate			if (DEVI(arg)->devi_binding_name != NULL)
6467c478bdstevel@tonic-gate				cmn_err(CE_CONT, "\tbinding_name=%s\n",
6475c066ecJerry Gilliam				    DEVI(arg)->devi_binding_name);
6487c478bdstevel@tonic-gate			if (DEVI(arg)->devi_node_name != NULL)
6497c478bdstevel@tonic-gate				cmn_err(CE_CONT, "\tnode_name=%s\n",
6505c066ecJerry Gilliam				    DEVI(arg)->devi_node_name);
6517c478bdstevel@tonic-gate		}
6527c478bdstevel@tonic-gate#endif
6537c478bdstevel@tonic-gate
6547c478bdstevel@tonic-gate		ddi_set_name_addr((dev_info_t *)arg, NULL);
6557c478bdstevel@tonic-gate		ddi_remove_minor_node((dev_info_t *)arg, NULL);
6567c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6577c478bdstevel@tonic-gate
6587c478bdstevel@tonic-gate	case DDI_CTLOPS_SLAVEONLY:
6597c478bdstevel@tonic-gate		/* PCMCIA devices can't ever be busmaster until CardBus */
6607c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
6615c066ecJerry Gilliam		    ddi_get_parent_data(rdip);
6627c478bdstevel@tonic-gate		if (ppd != NULL && ppd->ppd_flags & PPD_CB_BUSMASTER)
6637c478bdstevel@tonic-gate			return (DDI_FAILURE); /* at most */
6647c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6657c478bdstevel@tonic-gate
6667c478bdstevel@tonic-gate	case DDI_CTLOPS_SIDDEV:
6677c478bdstevel@tonic-gate		/* in general this is true. */
6687c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6697c478bdstevel@tonic-gate
6707c478bdstevel@tonic-gate	case DDI_CTLOPS_NREGS:
6717c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
6725c066ecJerry Gilliam		    ddi_get_parent_data(rdip);
6737c478bdstevel@tonic-gate		if (ppd != NULL)
6747c478bdstevel@tonic-gate			*((uint32_t *)result) = (ppd->ppd_nreg);
6757c478bdstevel@tonic-gate		else
6767c478bdstevel@tonic-gate			*((uint32_t *)result) = 0;
6777c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6787c478bdstevel@tonic-gate
6797c478bdstevel@tonic-gate	case DDI_CTLOPS_REGSIZE:
6807c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
6815c066ecJerry Gilliam		    ddi_get_parent_data(rdip);
6827c478bdstevel@tonic-gate		if (ppd != NULL && ppd->ppd_nreg > 0)
6837c478bdstevel@tonic-gate			*((off_t *)result) =  sizeof (struct pcm_regs);
6847c478bdstevel@tonic-gate		else
6857c478bdstevel@tonic-gate			*((off_t *)result) = 0;
6867c478bdstevel@tonic-gate		return (DDI_SUCCESS);
6877c478bdstevel@tonic-gate
6887c478bdstevel@tonic-gate	case DDI_CTLOPS_POWER:
6897c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
6905c066ecJerry Gilliam		    ddi_get_parent_data(rdip);
6917c478bdstevel@tonic-gate
6927c478bdstevel@tonic-gate		if (ppd == NULL)
6937c478bdstevel@tonic-gate			return (DDI_FAILURE);
6947c478bdstevel@tonic-gate		/*
6957c478bdstevel@tonic-gate		 * if this is not present, don't bother (claim success)
6967c478bdstevel@tonic-gate		 * since it is already in the right state.  Don't
6977c478bdstevel@tonic-gate		 * do any resume either since the card insertion will
6987c478bdstevel@tonic-gate		 * happen independently.
6997c478bdstevel@tonic-gate		 */
7007c478bdstevel@tonic-gate		if (!ppd->ppd_active)
7017c478bdstevel@tonic-gate			return (DDI_SUCCESS);
7027c478bdstevel@tonic-gate		for (e = 0; e < pcmcia_num_adapters; e++)
7037c478bdstevel@tonic-gate			if (pcmcia_adapters[e] ==
7047c478bdstevel@tonic-gate			    pcmcia_sockets[ppd->ppd_socket]->ls_adapter)
7057c478bdstevel@tonic-gate				break;
7067c478bdstevel@tonic-gate		if (e == pcmcia_num_adapters)
7077c478bdstevel@tonic-gate			return (DDI_FAILURE);
7087c478bdstevel@tonic-gate		pm = (power_req_t *)arg;
7097c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
7107c478bdstevel@tonic-gate		if (pcmcia_debug) {
7117c478bdstevel@tonic-gate			cmn_err(CE_WARN, "power: %d: %p, %d, %d [%s]\n",
7125c066ecJerry Gilliam			    pm->request_type,
7135c066ecJerry Gilliam			    (void *)pm->req.set_power_req.who,
7145c066ecJerry Gilliam			    pm->req.set_power_req.cmpt,
7155c066ecJerry Gilliam			    pm->req.set_power_req.level,
7165c066ecJerry Gilliam			    ddi_get_name_addr(rdip));
7177c478bdstevel@tonic-gate		}
7187c478bdstevel@tonic-gate#endif
7197c478bdstevel@tonic-gate		e = ppd->ppd_socket;
7207c478bdstevel@tonic-gate		switch (pm->request_type) {
7217c478bdstevel@tonic-gate		case PMR_SUSPEND:
7227c478bdstevel@tonic-gate			if (!(pcmcia_sockets[e]->ls_flags &
7237c478bdstevel@tonic-gate			    PCS_SUSPENDED)) {
7247c478bdstevel@tonic-gate				pcmcia_do_suspend(ppd->ppd_socket,
7257c478bdstevel@tonic-gate				    pcmcia_sockets[e]);
7267c478bdstevel@tonic-gate			}
7277c478bdstevel@tonic-gate			ppd->ppd_flags |= PPD_SUSPENDED;
7287c478bdstevel@tonic-gate			return (DDI_SUCCESS);
7297c478bdstevel@tonic-gate		case PMR_RESUME:
7307c478bdstevel@tonic-gate			/* for now, we just succeed since the rest is done */
7317c478bdstevel@tonic-gate			return (DDI_SUCCESS);
7327c478bdstevel@tonic-gate		case PMR_SET_POWER:
7337c478bdstevel@tonic-gate			/*
7347c478bdstevel@tonic-gate			 * not sure how to handle power control
7357c478bdstevel@tonic-gate			 * for now, we let the child handle it itself
7367c478bdstevel@tonic-gate			 */
7377c478bdstevel@tonic-gate			(void) pcmcia_power(pm->req.set_power_req.who,
7385c066ecJerry Gilliam			    pm->req.set_power_req.cmpt,
7395c066ecJerry Gilliam			    pm->req.set_power_req.level);
7407c478bdstevel@tonic-gate			break;
7417c478bdstevel@tonic-gate		default:
7427c478bdstevel@tonic-gate			break;
7437c478bdstevel@tonic-gate		}
7447c478bdstevel@tonic-gate		return (DDI_FAILURE);
7457c478bdstevel@tonic-gate		/* These CTLOPS will need to be implemented for new form */
7467c478bdstevel@tonic-gate		/* let CardServices know about this */
74711c2b4crw	case DDI_CTLOPS_DETACH:
74811c2b4crw		return (DDI_SUCCESS);
74911c2b4crw	case DDI_CTLOPS_ATTACH:
75011c2b4crw		return (DDI_SUCCESS);
7517c478bdstevel@tonic-gate
7527c478bdstevel@tonic-gate	default:
7537c478bdstevel@tonic-gate		/* if we don't understand, pass up the tree */
7547c478bdstevel@tonic-gate		/* most things default to general ops */
7557c478bdstevel@tonic-gate		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
7567c478bdstevel@tonic-gate	}
7577c478bdstevel@tonic-gate}
7587c478bdstevel@tonic-gate
7597c478bdstevel@tonic-gatestruct pcmcia_props {
7607c478bdstevel@tonic-gate	char *name;
7617c478bdstevel@tonic-gate	int   len;
7627c478bdstevel@tonic-gate	int   prop;
7637c478bdstevel@tonic-gate} pcmcia_internal_props[] = {
7647c478bdstevel@tonic-gate	{ PCM_DEV_ACTIVE, 0, PCMCIA_PROP_ACTIVE },
7657c478bdstevel@tonic-gate	{ PCM_DEV_R2TYPE, 0, PCMCIA_PROP_R2TYPE },
7667c478bdstevel@tonic-gate	{ PCM_DEV_CARDBUS, 0, PCMCIA_PROP_CARDBUS },
7677c478bdstevel@tonic-gate	{ CS_PROP, sizeof (void *), PCMCIA_PROP_OLDCS },
7687c478bdstevel@tonic-gate	{ "reg", 0, PCMCIA_PROP_REG },
7697c478bdstevel@tonic-gate	{ "interrupts", sizeof (int), PCMCIA_PROP_INTR },
7707c478bdstevel@tonic-gate	{ "pm-hardware-state", 0, PCMCIA_PROP_DEFAULT_PM },
7717c478bdstevel@tonic-gate};
7727c478bdstevel@tonic-gate
7737c478bdstevel@tonic-gate/*
7747c478bdstevel@tonic-gate * pcmcia_prop_decode(name)
7757c478bdstevel@tonic-gate *	decode the name and determine if this is a property
7767c478bdstevel@tonic-gate *	we construct on the fly, one we have on the prop list
7777c478bdstevel@tonic-gate *	or one that requires calling the CIS code.
7787c478bdstevel@tonic-gate */
7797c478bdstevel@tonic-gatestatic int
7807c478bdstevel@tonic-gatepcmcia_prop_decode(char *name)
7817c478bdstevel@tonic-gate{
7827c478bdstevel@tonic-gate	int i;
7837c478bdstevel@tonic-gate	if (strncmp(name, "cistpl_", 7) == 0)
7847c478bdstevel@tonic-gate		return (PCMCIA_PROP_CIS);
7857c478bdstevel@tonic-gate
7867c478bdstevel@tonic-gate	for (i = 0; i < (sizeof (pcmcia_internal_props) /
7877c478bdstevel@tonic-gate	    sizeof (struct pcmcia_props)); i++) {
7887c478bdstevel@tonic-gate		if (strcmp(name, pcmcia_internal_props[i].name) == 0)
7897c478bdstevel@tonic-gate			return (i);
7907c478bdstevel@tonic-gate	}
7917c478bdstevel@tonic-gate
7927c478bdstevel@tonic-gate	return (PCMCIA_PROP_UNKNOWN);
7937c478bdstevel@tonic-gate}
7947c478bdstevel@tonic-gate
7957c478bdstevel@tonic-gate/*
7967c478bdstevel@tonic-gate * pcmcia_prop_op()
7977c478bdstevel@tonic-gate *	we don't have properties in PROM per se so look for them
7987c478bdstevel@tonic-gate *	only in the devinfo node.  Future may allow us to find
7997c478bdstevel@tonic-gate *	certain CIS tuples via this interface if a user asks for
8007c478bdstevel@tonic-gate *	a property of the form "cistpl-<tuplename>" but not yet.
8017c478bdstevel@tonic-gate *
8027c478bdstevel@tonic-gate *	The addition of 1275 properties adds to the necessity.
8037c478bdstevel@tonic-gate */
8047c478bdstevel@tonic-gateint
8057c478bdstevel@tonic-gatepcmcia_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
8067c478bdstevel@tonic-gate    ddi_prop_op_t prop_op, int mod_flags,
8077c478bdstevel@tonic-gate    char *name, caddr_t valuep, int *lengthp)
8087c478bdstevel@tonic-gate{
8097c478bdstevel@tonic-gate	int len, proplen, which, flags;
8107c478bdstevel@tonic-gate	caddr_t buff, propptr;
8117c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
8127c478bdstevel@tonic-gate
8137c478bdstevel@tonic-gate	len = *lengthp;
8147c478bdstevel@tonic-gate	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(ch_dip);
8157c478bdstevel@tonic-gate
8167c478bdstevel@tonic-gate	switch (which = pcmcia_prop_decode(name)) {
8177c478bdstevel@tonic-gate	default:
8187c478bdstevel@tonic-gate		if (ppd == NULL)
8197c478bdstevel@tonic-gate			return (DDI_PROP_NOT_FOUND);
8207c478bdstevel@tonic-gate
8217c478bdstevel@tonic-gate		/* note that proplen may get modified */
8227c478bdstevel@tonic-gate		proplen = pcmcia_internal_props[which].len;
8237c478bdstevel@tonic-gate		switch (pcmcia_internal_props[which].prop) {
8247c478bdstevel@tonic-gate		case PCMCIA_PROP_DEFAULT_PM:
8257c478bdstevel@tonic-gate			propptr = pcmcia_default_pm_mode;
8267c478bdstevel@tonic-gate			proplen = strlen(propptr) + 1;
8277c478bdstevel@tonic-gate			break;
8287c478bdstevel@tonic-gate		case PCMCIA_PROP_OLDCS:
8297c478bdstevel@tonic-gate			propptr = (caddr_t)&cs_error_ptr;
8307c478bdstevel@tonic-gate			break;
8317c478bdstevel@tonic-gate		case PCMCIA_PROP_REG:
8327c478bdstevel@tonic-gate			propptr = (caddr_t)ppd->ppd_reg;
8337c478bdstevel@tonic-gate			proplen = ppd->ppd_nreg * sizeof (struct pcm_regs);
8347c478bdstevel@tonic-gate			break;
8357c478bdstevel@tonic-gate		case PCMCIA_PROP_INTR:
8367c478bdstevel@tonic-gate			propptr = (caddr_t)&ppd->ppd_intr;
8377c478bdstevel@tonic-gate			break;
8387c478bdstevel@tonic-gate
8397c478bdstevel@tonic-gate		/* the next set are boolean values */
8407c478bdstevel@tonic-gate		case PCMCIA_PROP_ACTIVE:
8417c478bdstevel@tonic-gate			propptr = NULL;
8427c478bdstevel@tonic-gate			if (!ppd->ppd_active) {
8437c478bdstevel@tonic-gate				return (DDI_PROP_NOT_FOUND);
8447c478bdstevel@tonic-gate			}
8457c478bdstevel@tonic-gate			break;
8467c478bdstevel@tonic-gate		case PCMCIA_PROP_R2TYPE:
8477c478bdstevel@tonic-gate			propptr = NULL;
8487c478bdstevel@tonic-gate			if (ppd->ppd_flags & PPD_CARD_CARDBUS)
8497c478bdstevel@tonic-gate				return (DDI_PROP_NOT_FOUND);
8507c478bdstevel@tonic-gate			break;
8517c478bdstevel@tonic-gate		case PCMCIA_PROP_CARDBUS:
8527c478bdstevel@tonic-gate			propptr = NULL;
8532990a17Toomas Soome			if ((ppd->ppd_flags & PPD_CARD_CARDBUS) == 0)
8547c478bdstevel@tonic-gate				return (DDI_PROP_NOT_FOUND);
8557c478bdstevel@tonic-gate			break;
8567c478bdstevel@tonic-gate		}
8577c478bdstevel@tonic-gate
8587c478bdstevel@tonic-gate		break;
8597c478bdstevel@tonic-gate
8607c478bdstevel@tonic-gate	case PCMCIA_PROP_CIS:
8617c478bdstevel@tonic-gate		/*
8627c478bdstevel@tonic-gate		 * once we have the lookup code in place
8637c478bdstevel@tonic-gate		 * it is sufficient to break out of the switch
8647c478bdstevel@tonic-gate		 * once proplen and propptr are set.
8657c478bdstevel@tonic-gate		 * The common prop_op code deals with the rest.
8667c478bdstevel@tonic-gate		 */
8677c478bdstevel@tonic-gate	case PCMCIA_PROP_UNKNOWN:
8687c478bdstevel@tonic-gate		return (ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
8697c478bdstevel@tonic-gate		    mod_flags | DDI_PROP_NOTPROM,
8707c478bdstevel@tonic-gate		    name, valuep, lengthp));
8717c478bdstevel@tonic-gate	}
8727c478bdstevel@tonic-gate
8737c478bdstevel@tonic-gate	if (prop_op == PROP_LEN) {
8747c478bdstevel@tonic-gate		/* just the length */
8757c478bdstevel@tonic-gate		*lengthp = proplen;
8767c478bdstevel@tonic-gate		return (DDI_PROP_SUCCESS);
8777c478bdstevel@tonic-gate	}
8787c478bdstevel@tonic-gate	switch (prop_op) {
8797c478bdstevel@tonic-gate	case PROP_LEN_AND_VAL_ALLOC:
8807c478bdstevel@tonic-gate		if (mod_flags & DDI_PROP_CANSLEEP)
8817c478bdstevel@tonic-gate			flags = KM_SLEEP;
8827c478bdstevel@tonic-gate		else
8837c478bdstevel@tonic-gate			flags = KM_NOSLEEP;
8847c478bdstevel@tonic-gate		buff = kmem_alloc((size_t)proplen, flags);
8857c478bdstevel@tonic-gate		if (buff == NULL)
8867c478bdstevel@tonic-gate			return (DDI_PROP_NO_MEMORY);
8877c478bdstevel@tonic-gate		*(caddr_t *)valuep = (caddr_t)buff;
8887c478bdstevel@tonic-gate		break;
8897c478bdstevel@tonic-gate	case PROP_LEN_AND_VAL_BUF:
8907c478bdstevel@tonic-gate		buff = (caddr_t)valuep;
8917c478bdstevel@tonic-gate		if (len < proplen)
8927c478bdstevel@tonic-gate			return (DDI_PROP_BUF_TOO_SMALL);
8937c478bdstevel@tonic-gate		break;
8947c478bdstevel@tonic-gate	default:
8957c478bdstevel@tonic-gate		break;
8967c478bdstevel@tonic-gate	}
8977c478bdstevel@tonic-gate
8987c478bdstevel@tonic-gate	if (proplen > 0)
8997c478bdstevel@tonic-gate		bcopy(propptr, buff, proplen);
9007c478bdstevel@tonic-gate	*lengthp = proplen;
9017c478bdstevel@tonic-gate	return (DDI_PROP_SUCCESS);
9027c478bdstevel@tonic-gate}
9037c478bdstevel@tonic-gate
9047c478bdstevel@tonic-gate
9057c478bdstevel@tonic-gatestruct regspec *
9067c478bdstevel@tonic-gatepcmcia_rnum_to_regspec(dev_info_t *dip, int rnumber)
9077c478bdstevel@tonic-gate{
9087c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
9097c478bdstevel@tonic-gate	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
9107c478bdstevel@tonic-gate	if (ppd->ppd_nreg < rnumber)
9117c478bdstevel@tonic-gate		return (NULL);
9127c478bdstevel@tonic-gate	return ((struct regspec *)&ppd->ppd_reg[rnumber]);
9137c478bdstevel@tonic-gate}
9147c478bdstevel@tonic-gate
9157c478bdstevel@tonic-gatestruct regspec *
9167c478bdstevel@tonic-gatepcmcia_rnum_to_mapped(dev_info_t *dip, int rnumber)
9177c478bdstevel@tonic-gate{
9187c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
9197c478bdstevel@tonic-gate	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
9207c478bdstevel@tonic-gate	if (ppd->ppd_nreg < rnumber)
9217c478bdstevel@tonic-gate		return (NULL);
9220d282d1rw	if (ppd->ppd_assigned == NULL)
9230d282d1rw		return (NULL);
9247c478bdstevel@tonic-gate	if (ppd->ppd_assigned[rnumber].phys_len == 0)
9257c478bdstevel@tonic-gate		return (NULL);
9267c478bdstevel@tonic-gate	else
9277c478bdstevel@tonic-gate		return ((struct regspec *)&ppd->ppd_assigned[rnumber]);
9287c478bdstevel@tonic-gate}
9297c478bdstevel@tonic-gate
9307c478bdstevel@tonic-gateint
9317c478bdstevel@tonic-gatepcmcia_find_rnum(dev_info_t *dip, struct regspec *reg)
9327c478bdstevel@tonic-gate{
9337c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
9347c478bdstevel@tonic-gate	struct regspec *regp;
9357c478bdstevel@tonic-gate	int i;
9367c478bdstevel@tonic-gate
9377c478bdstevel@tonic-gate	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
9387c478bdstevel@tonic-gate	if (ppd == NULL)
9397c478bdstevel@tonic-gate		return (-1);
9407c478bdstevel@tonic-gate	for (regp = (struct regspec *)ppd->ppd_reg, i = 0;
9417c478bdstevel@tonic-gate	    i < ppd->ppd_nreg; i++, regp++) {
9427c478bdstevel@tonic-gate		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
9437c478bdstevel@tonic-gate			return (i);
9447c478bdstevel@tonic-gate	}
9457c478bdstevel@tonic-gate	for (regp = (struct regspec *)ppd->ppd_assigned, i = 0;
9467c478bdstevel@tonic-gate	    i < ppd->ppd_nreg; i++, regp++) {
9477c478bdstevel@tonic-gate		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
9487c478bdstevel@tonic-gate			return (i);
9497c478bdstevel@tonic-gate	}
9507c478bdstevel@tonic-gate
9517c478bdstevel@tonic-gate	return (-1);
9527c478bdstevel@tonic-gate}
9537c478bdstevel@tonic-gate
9547c478bdstevel@tonic-gateint
9557c478bdstevel@tonic-gatepcmcia_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
9563f068ebToomas Soome    off_t offset, off_t len, caddr_t *vaddrp)
9577c478bdstevel@tonic-gate{
9587c478bdstevel@tonic-gate	struct pcm_regs *regs, *mregs = NULL, tmp_reg;
9597c478bdstevel@tonic-gate	ddi_map_req_t mr = *mp;
9607c478bdstevel@tonic-gate	ra_return_t ret;
9617c478bdstevel@tonic-gate	int check, rnum = -1;
9627c478bdstevel@tonic-gate	uint32_t base;
9637c478bdstevel@tonic-gate	uchar_t regbuf[sizeof (pci_regspec_t)];
9647c478bdstevel@tonic-gate
9657c478bdstevel@tonic-gate	mp = &mr;		/* a copy of original request */
9667c478bdstevel@tonic-gate
9677c478bdstevel@tonic-gate	/* check for register number */
9687c478bdstevel@tonic-gate	switch (mp->map_type) {
9697c478bdstevel@tonic-gate	case DDI_MT_REGSPEC:
9707c478bdstevel@tonic-gate		regs = (struct pcm_regs *)mp->map_obj.rp;
9717c478bdstevel@tonic-gate		mregs = (struct pcm_regs *)mp->map_obj.rp;
9727c478bdstevel@tonic-gate		/*
9737c478bdstevel@tonic-gate		 * when using regspec, must not be relocatable
9747c478bdstevel@tonic-gate		 * and should be from assigned space.
9757c478bdstevel@tonic-gate		 */
9767c478bdstevel@tonic-gate		if (!PC_REG_RELOC(regs->phys_hi))
9777c478bdstevel@tonic-gate			return (DDI_FAILURE);
9787c478bdstevel@tonic-gate		rnum = pcmcia_find_rnum(rdip, (struct regspec *)mregs);
9797c478bdstevel@tonic-gate		break;
9807c478bdstevel@tonic-gate	case DDI_MT_RNUMBER:
9817c478bdstevel@tonic-gate		regs = (struct pcm_regs *)
9825c066ecJerry Gilliam		    pcmcia_rnum_to_regspec(rdip, mp->map_obj.rnumber);
9837c478bdstevel@tonic-gate		mregs = (struct pcm_regs *)
9845c066ecJerry Gilliam		    pcmcia_rnum_to_mapped(rdip, mp->map_obj.rnumber);
9857c478bdstevel@tonic-gate		rnum = mp->map_obj.rnumber;
9867c478bdstevel@tonic-gate		if (regs == NULL)
9877c478bdstevel@tonic-gate			return (DDI_FAILURE);
9887c478bdstevel@tonic-gate		mp->map_type = DDI_MT_REGSPEC;
9897c478bdstevel@tonic-gate		mp->map_obj.rp = (struct regspec *)mregs;
9907c478bdstevel@tonic-gate		break;
9917c478bdstevel@tonic-gate	default:
9927c478bdstevel@tonic-gate		return (DDI_ME_INVAL);
9937c478bdstevel@tonic-gate	}
9947c478bdstevel@tonic-gate
9957c478bdstevel@tonic-gate	/* basic sanity checks */
9967c478bdstevel@tonic-gate	switch (mp->map_op) {
9977c478bdstevel@tonic-gate	default:
9987c478bdstevel@tonic-gate		return (DDI_ME_UNIMPLEMENTED);
9997c478bdstevel@tonic-gate	case DDI_MO_UNMAP:
10007c478bdstevel@tonic-gate		if (mregs == NULL)
10017c478bdstevel@tonic-gate			return (DDI_FAILURE);
10027c478bdstevel@tonic-gate		regs = mregs;
10037c478bdstevel@tonic-gate		break;
10047c478bdstevel@tonic-gate	case DDI_MO_MAP_LOCKED:
10057c478bdstevel@tonic-gate	case DDI_MO_MAP_HANDLE:
10067c478bdstevel@tonic-gate		panic("unsupported bus operation");
10077c478bdstevel@tonic-gate		/*NOTREACHED*/
10087c478bdstevel@tonic-gate	}
10097c478bdstevel@tonic-gate
10107c478bdstevel@tonic-gate	/*
10117c478bdstevel@tonic-gate	 * we need a private copy for manipulation and
10127c478bdstevel@tonic-gate	 * calculation of the correct ranges
10137c478bdstevel@tonic-gate	 */
10147c478bdstevel@tonic-gate	tmp_reg = *regs;
10157c478bdstevel@tonic-gate	mp->map_obj.rp = (struct regspec *)(regs = &tmp_reg);
10167c478bdstevel@tonic-gate	base = regs->phys_lo;
10177c478bdstevel@tonic-gate	if (base == 0 && offset != 0) {
10187c478bdstevel@tonic-gate		/*
10197c478bdstevel@tonic-gate		 * for now this is an error.  What does it really mean
10207c478bdstevel@tonic-gate		 * to ask for an offset from an address that hasn't
10217c478bdstevel@tonic-gate		 * been allocated yet.
10227c478bdstevel@tonic-gate		 */
10237c478bdstevel@tonic-gate		return (DDI_ME_INVAL);
10247c478bdstevel@tonic-gate	}
10257c478bdstevel@tonic-gate	regs->phys_lo += (uint32_t)offset;
10267c478bdstevel@tonic-gate	if (len != 0) {
10277c478bdstevel@tonic-gate		if (len > regs->phys_len) {
10287c478bdstevel@tonic-gate			return (DDI_ME_INVAL);
10297c478bdstevel@tonic-gate		}
10307c478bdstevel@tonic-gate		regs->phys_len = len;
10317c478bdstevel@tonic-gate	}
10327c478bdstevel@tonic-gate
10337c478bdstevel@tonic-gate	/*
10347c478bdstevel@tonic-gate	 * basic sanity is checked so now make sure
10357c478bdstevel@tonic-gate	 * we can actually allocate something for this
10367c478bdstevel@tonic-gate	 * request and then convert to a "standard"
10377c478bdstevel@tonic-gate	 * regspec for the next layer up (pci/isa/rootnex/etc.)
10387c478bdstevel@tonic-gate	 */
10397c478bdstevel@tonic-gate
10407c478bdstevel@tonic-gate	switch (PC_GET_REG_TYPE(regs->phys_hi)) {
10417c478bdstevel@tonic-gate	case PC_REG_SPACE_IO:
10427c478bdstevel@tonic-gate		check = PCA_RES_NEED_IO;
10437c478bdstevel@tonic-gate		break;
10447c478bdstevel@tonic-gate	case PC_REG_SPACE_MEMORY:
10457c478bdstevel@tonic-gate		check = PCA_RES_NEED_MEM;
10467c478bdstevel@tonic-gate		break;
10477c478bdstevel@tonic-gate	default:
10487c478bdstevel@tonic-gate		/* not a valid register type */
10497c478bdstevel@tonic-gate		return (DDI_FAILURE);
10507c478bdstevel@tonic-gate	}
10517c478bdstevel@tonic-gate
10527c478bdstevel@tonic-gate	mr.map_type = DDI_MT_REGSPEC;
10537c478bdstevel@tonic-gate	ret.ra_addr_hi = 0;
10547c478bdstevel@tonic-gate	ret.ra_addr_lo = regs->phys_lo;
10557c478bdstevel@tonic-gate	ret.ra_len = regs->phys_len;
10567c478bdstevel@tonic-gate	mr.map_obj.rp = pcmcia_cons_regspec(dip,
10577c478bdstevel@tonic-gate	    (check == PCA_RES_NEED_IO) ?
10587c478bdstevel@tonic-gate	    PCMCIA_MAP_IO : PCMCIA_MAP_MEM,
10597c478bdstevel@tonic-gate	    regbuf, &ret);
10607c478bdstevel@tonic-gate	switch (mp->map_op) {
10617c478bdstevel@tonic-gate	case DDI_MO_UNMAP:
10627c478bdstevel@tonic-gate		pcmcia_set_assigned(rdip, rnum, NULL);
10637c478bdstevel@tonic-gate		break;
10647c478bdstevel@tonic-gate	default:
10657c478bdstevel@tonic-gate		break;
10667c478bdstevel@tonic-gate	}
10677c478bdstevel@tonic-gate	return (ddi_map(dip, &mr, (off_t)0, (off_t)0, vaddrp));
10687c478bdstevel@tonic-gate}
10697c478bdstevel@tonic-gate
10707c478bdstevel@tonic-gate/*
10717c478bdstevel@tonic-gate * pcmcia_cons_regspec()
10727c478bdstevel@tonic-gate * based on parent's bus type, construct a regspec that is usable
10737c478bdstevel@tonic-gate * by that parent to map the resource into the system.
10747c478bdstevel@tonic-gate */
10757c478bdstevel@tonic-gate#define	PTYPE_PCI	1
10767c478bdstevel@tonic-gate#define	PTYPE_ISA	0
10777c478bdstevel@tonic-gatestruct regspec *
10787c478bdstevel@tonic-gatepcmcia_cons_regspec(dev_info_t *dip, int type, uchar_t *buff, ra_return_t *ret)
10797c478bdstevel@tonic-gate{
10807c478bdstevel@tonic-gate	int ptype = -1, len, bus;
10817c478bdstevel@tonic-gate	char device_type[MODMAXNAMELEN + 1];
10827c478bdstevel@tonic-gate	dev_info_t *pdip;
10837c478bdstevel@tonic-gate	struct regspec *defreg;
10847c478bdstevel@tonic-gate	pci_regspec_t *pcireg;
10857c478bdstevel@tonic-gate
10867c478bdstevel@tonic-gate	pdip = ddi_get_parent(dip);
10877c478bdstevel@tonic-gate	if (pdip != ddi_root_node()) {
10887c478bdstevel@tonic-gate		/* we're not a child of root so find out what */
10897c478bdstevel@tonic-gate		len = sizeof (device_type);
10907c478bdstevel@tonic-gate		if (ddi_prop_op(DDI_DEV_T_ANY, pdip, PROP_LEN_AND_VAL_BUF, 0,
10915c066ecJerry Gilliam		    "device_type", (caddr_t)device_type, &len) ==
10927c478bdstevel@tonic-gate		    DDI_PROP_SUCCESS) {
10937c478bdstevel@tonic-gate			/* check things out */
10947c478bdstevel@tonic-gate			if (strcmp(device_type, "pci") == 0)
10957c478bdstevel@tonic-gate				ptype = PTYPE_PCI;
10967c478bdstevel@tonic-gate			else if (strcmp(device_type, "isa") == 0)
10977c478bdstevel@tonic-gate				ptype = PTYPE_ISA;
10987c478bdstevel@tonic-gate		}
10997c478bdstevel@tonic-gate	}
11007c478bdstevel@tonic-gate	switch (ptype) {
11017c478bdstevel@tonic-gate	case PTYPE_PCI:
11027c478bdstevel@tonic-gate		/* XXX need to look at carefully */
1103a328289cth		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
11045c066ecJerry Gilliam		    "reg", (caddr_t)&pcireg, &len) == DDI_SUCCESS) {
11057c478bdstevel@tonic-gate			bus = PCI_REG_BUS_G(pcireg->pci_phys_hi);
11067c478bdstevel@tonic-gate			kmem_free(pcireg, len);
11077c478bdstevel@tonic-gate		} else {
11087c478bdstevel@tonic-gate			bus = 0;
11097c478bdstevel@tonic-gate		}
11107c478bdstevel@tonic-gate		pcireg = (pci_regspec_t *)buff;
11117c478bdstevel@tonic-gate		pcireg->pci_phys_hi = (type == PCMCIA_MAP_IO ? PCI_ADDR_IO :
11125c066ecJerry Gilliam		    PCI_ADDR_MEM32) | PCI_RELOCAT_B | (bus << 16);
11137c478bdstevel@tonic-gate		pcireg->pci_phys_mid = ret->ra_addr_hi;
11147c478bdstevel@tonic-gate		pcireg->pci_phys_low = ret->ra_addr_lo;
11157c478bdstevel@tonic-gate		if (type == PCMCIA_MAP_IO)
11167c478bdstevel@tonic-gate			pcireg->pci_phys_low &= 0xFFFF;
11177c478bdstevel@tonic-gate		pcireg->pci_size_hi = 0;
11187c478bdstevel@tonic-gate		pcireg->pci_size_low = ret->ra_len;
11197c478bdstevel@tonic-gate		break;
11207c478bdstevel@tonic-gate	default:
11217c478bdstevel@tonic-gate		/* default case is to use struct regspec */
11227c478bdstevel@tonic-gate		defreg = (struct regspec *)buff;
11237c478bdstevel@tonic-gate		defreg->regspec_bustype = type == PCMCIA_MAP_IO ? 1 : 0;
11247c478bdstevel@tonic-gate		defreg->regspec_addr = ret->ra_addr_lo;
11257c478bdstevel@tonic-gate		defreg->regspec_size = ret->ra_len;
11267c478bdstevel@tonic-gate		break;
11277c478bdstevel@tonic-gate	}
11287c478bdstevel@tonic-gate	return ((struct regspec *)buff);
11297c478bdstevel@tonic-gate}
11307c478bdstevel@tonic-gate
11317c478bdstevel@tonic-gate/*
11327c478bdstevel@tonic-gate * pcmcia_init_adapter
11337c478bdstevel@tonic-gate *	Initialize the per-adapter structures and check to see if
11347c478bdstevel@tonic-gate *	there are possible other instances coming.
11357c478bdstevel@tonic-gate */
11367c478bdstevel@tonic-gatevoid
11377c478bdstevel@tonic-gatepcmcia_init_adapter(anp_t *adapter, dev_info_t *dip)
11387c478bdstevel@tonic-gate{
11397c478bdstevel@tonic-gate	int i, n;
11407c478bdstevel@tonic-gate	pcmcia_if_t *ls_if;
11417c478bdstevel@tonic-gate
11427c478bdstevel@tonic-gate	i = pcmcia_num_adapters++;
11437c478bdstevel@tonic-gate	pcmcia_adapters[i] = kmem_zalloc(sizeof (struct pcmcia_adapter),
11447c478bdstevel@tonic-gate	    KM_SLEEP);
11457c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_dip = dip;
11467c478bdstevel@tonic-gate	/* should this be pca_winshift??? */
11475c066ecJerry Gilliam	pcmcia_adapters[i]->pca_module = ddi_driver_major(dip);
11487c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_unit = ddi_get_instance(dip);
11497c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_iblock = adapter->an_iblock;
11507c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_idev = adapter->an_idev;
11517c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_if = ls_if = adapter->an_if;
11527c478bdstevel@tonic-gate	pcmcia_adapters[i]->pca_number = i;
11537c478bdstevel@tonic-gate	(void) strcpy(pcmcia_adapters[i]->pca_name, ddi_get_name(dip));
11547c478bdstevel@tonic-gate	pcmcia_adapters[i]->
1155c48c304Toomas Soome	    pca_name[sizeof (pcmcia_adapters[i]->pca_name) - 1] = '\0';
11567c478bdstevel@tonic-gate
11577c478bdstevel@tonic-gate	if (ls_if != NULL) {
11587c478bdstevel@tonic-gate		inquire_adapter_t conf;
11597c478bdstevel@tonic-gate		int sock, win;
11607c478bdstevel@tonic-gate
11617c478bdstevel@tonic-gate		if (ls_if->pcif_inquire_adapter != NULL)
11627c478bdstevel@tonic-gate			GET_CONFIG(ls_if, dip, &conf);
11637c478bdstevel@tonic-gate
11647c478bdstevel@tonic-gate		/* resources - assume worst case and fix from there */
11657c478bdstevel@tonic-gate		pcmcia_adapters[i]->pca_flags = PCA_RES_NEED_IRQ |
11665c066ecJerry Gilliam		    PCA_RES_NEED_IO | PCA_RES_NEED_MEM;
11677c478bdstevel@tonic-gate		/* indicate first socket not initialized */
11687c478bdstevel@tonic-gate		pcmcia_adapters[i]->pca_first_socket = -1;
11697c478bdstevel@tonic-gate
11707c478bdstevel@tonic-gate		if (conf.ResourceFlags & RES_OWN_IRQ)
11717c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IRQ;
11727c478bdstevel@tonic-gate		if (conf.ResourceFlags & RES_OWN_IO)
11737c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IO;
11747c478bdstevel@tonic-gate		if (conf.ResourceFlags & RES_OWN_MEM)
11757c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_MEM;
11767c478bdstevel@tonic-gate		if (conf.ResourceFlags & RES_IRQ_SHAREABLE)
11777c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SHAREABLE;
11787c478bdstevel@tonic-gate		if (conf.ResourceFlags & RES_IRQ_NEXUS)
11797c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SMI_SHARE;
11807c478bdstevel@tonic-gate
11817c478bdstevel@tonic-gate		/* need to know interrupt limitations */
11827c478bdstevel@tonic-gate		if (conf.ActiveLow) {
11837c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveLow;
11847c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_ISA;
11857c478bdstevel@tonic-gate		} else
11867c478bdstevel@tonic-gate			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveHigh;
11877c478bdstevel@tonic-gate
11887c478bdstevel@tonic-gate		/* power entries for adapter */
11895c066ecJerry Gilliam		pcmcia_adapters[i]->pca_power = conf.power_entry;
11905c066ecJerry Gilliam		pcmcia_adapters[i]->pca_numpower = conf.NumPower;
11917c478bdstevel@tonic-gate
11927c478bdstevel@tonic-gate		for (n = 0; n < conf.NumPower; n++)
11937c478bdstevel@tonic-gate			pcmcia_merge_power(&conf.power_entry[n]);
11947c478bdstevel@tonic-gate
11957c478bdstevel@tonic-gate		/* now setup the per socket info */
11967c478bdstevel@tonic-gate		for (sock = 0; sock < conf.NumSockets;
11977c478bdstevel@tonic-gate		    sock++) {
11987c478bdstevel@tonic-gate			dev_info_t *sockdrv = NULL;
11997c478bdstevel@tonic-gate			sockdrv = pcmcia_number_socket(dip, sock);
12007c478bdstevel@tonic-gate			if (sockdrv == NULL)
12017c478bdstevel@tonic-gate				n = sock + pcmcia_num_sockets;
12027c478bdstevel@tonic-gate			else {
12037c478bdstevel@tonic-gate				n = ddi_get_instance(sockdrv);
12047c478bdstevel@tonic-gate			}
12057c478bdstevel@tonic-gate			/* make sure we know first socket on adapter */
12067c478bdstevel@tonic-gate			if (pcmcia_adapters[i]->pca_first_socket == -1)
12077c478bdstevel@tonic-gate				pcmcia_adapters[i]->pca_first_socket = n;
12087c478bdstevel@tonic-gate
12097c478bdstevel@tonic-gate			/*
12107c478bdstevel@tonic-gate			 * the number of sockets is weird.
12117c478bdstevel@tonic-gate			 * we might have only two sockets but
12127c478bdstevel@tonic-gate			 * due to persistence of instances we
12137c478bdstevel@tonic-gate			 * will need to call them something other
12147c478bdstevel@tonic-gate			 * than 0 and 1.  So, we use the largest
12157c478bdstevel@tonic-gate			 * instance number as the number and
12167c478bdstevel@tonic-gate			 * have some that just don't get used.
12177c478bdstevel@tonic-gate			 */
12187c478bdstevel@tonic-gate			if (n >= pcmcia_num_sockets)
12197c478bdstevel@tonic-gate				pcmcia_num_sockets = n + 1;
12207c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
12217c478bdstevel@tonic-gate			if (pcmcia_debug) {
12227c478bdstevel@tonic-gate				cmn_err(CE_CONT,
12235c066ecJerry Gilliam				    "pcmcia_init: new socket added %d "
12245c066ecJerry Gilliam				    "(%d)\n",
12255c066ecJerry Gilliam				    n, pcmcia_num_sockets);
12267c478bdstevel@tonic-gate			}
12277c478bdstevel@tonic-gate#endif
12287c478bdstevel@tonic-gate
12297c478bdstevel@tonic-gate			pcmcia_sockets[n] =
12305c066ecJerry Gilliam			    kmem_zalloc(sizeof (pcmcia_logical_socket_t),
12315c066ecJerry Gilliam			    KM_SLEEP);
12327c478bdstevel@tonic-gate			pcmcia_sockets[n]->ls_socket = sock;
12337c478bdstevel@tonic-gate			pcmcia_sockets[n]->ls_if = ls_if;
12347c478bdstevel@tonic-gate			pcmcia_sockets[n]->ls_adapter =
12355c066ecJerry Gilliam			    pcmcia_adapters[i];
12367c478bdstevel@tonic-gate			pcmcia_sockets[n]->ls_cs_events = 0L;
12377c478bdstevel@tonic-gate			pcmcia_sockets[n]->ls_sockdrv = sockdrv;
12387c478bdstevel@tonic-gate			/* Prototype of intrspec */
12395c066ecJerry Gilliam			pcmcia_sockets[n]->ls_intr_pri = adapter->an_ipl;
12407c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
12417c478bdstevel@tonic-gate			if (pcmcia_debug)
12427c478bdstevel@tonic-gate				cmn_err(CE_CONT,
12435c066ecJerry Gilliam				    "phys sock %d, log sock %d\n",
12445c066ecJerry Gilliam				    sock, n);
12457c478bdstevel@tonic-gate#endif
12467c478bdstevel@tonic-gate			mutex_init(&pcmcia_sockets[n]->ls_ilock, NULL,
12475c066ecJerry Gilliam			    MUTEX_DRIVER, *adapter->an_iblock);
12487c478bdstevel@tonic-gate		}
12497c478bdstevel@tonic-gate
12507c478bdstevel@tonic-gate		pcmcia_adapters[i]->pca_numsockets = conf.NumSockets;
12517c478bdstevel@tonic-gate		/* now setup the per window information */
12527c478bdstevel@tonic-gate		for (win = 0; win < conf.NumWindows; win++) {
12537c478bdstevel@tonic-gate			n = win + pcmcia_num_windows;
12547c478bdstevel@tonic-gate			pcmcia_windows[n] =
12555c066ecJerry Gilliam			    kmem_zalloc(sizeof (pcmcia_logical_window_t),
12565c066ecJerry Gilliam			    KM_SLEEP);
12577c478bdstevel@tonic-gate			pcmcia_windows[n]->lw_window = win;
12587c478bdstevel@tonic-gate			pcmcia_windows[n]->lw_if = ls_if;
12597c478bdstevel@tonic-gate			pcmcia_windows[n]->lw_adapter =
12605c066ecJerry Gilliam			    pcmcia_adapters[i];
12617c478bdstevel@tonic-gate		}
12627c478bdstevel@tonic-gate		pcmcia_num_windows += conf.NumWindows;
12637c478bdstevel@tonic-gate		SET_CALLBACK(ls_if, dip,
12647c478bdstevel@tonic-gate		    pcm_adapter_callback, i);
12657c478bdstevel@tonic-gate
12667c478bdstevel@tonic-gate		/* now tell CS about each socket */
12677c478bdstevel@tonic-gate		for (sock = 0; sock < pcmcia_num_sockets; sock++) {
12687c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
12697c478bdstevel@tonic-gate			if (pcmcia_debug) {
12707c478bdstevel@tonic-gate				cmn_err(CE_CONT,
12715c066ecJerry Gilliam				    "pcmcia_init: notify CS socket %d "
12725c066ecJerry Gilliam				    "sockp=%p\n",
12735c066ecJerry Gilliam				    sock, (void *)pcmcia_sockets[sock]);
12747c478bdstevel@tonic-gate			}
12757c478bdstevel@tonic-gate#endif
12767c478bdstevel@tonic-gate			if (pcmcia_sockets[sock] == NULL ||
12777c478bdstevel@tonic-gate			    (pcmcia_sockets[sock]->ls_flags &
12785c066ecJerry Gilliam			    PCS_SOCKET_ADDED)) {
12797c478bdstevel@tonic-gate				/* skip the ones that are done already */
12807c478bdstevel@tonic-gate				continue;
12817c478bdstevel@tonic-gate			}
12827c478bdstevel@tonic-gate			pcmcia_sockets[sock]->ls_flags |= PCS_SOCKET_ADDED;
12837c478bdstevel@tonic-gate			if (cs_event(PCE_ADD_SOCKET, sock, 0) !=
12847c478bdstevel@tonic-gate			    CS_SUCCESS) {
12857c478bdstevel@tonic-gate				/* flag socket as broken */
12867c478bdstevel@tonic-gate				pcmcia_sockets[sock]->ls_flags = 0;
12877c478bdstevel@tonic-gate			} else {
12887c478bdstevel@tonic-gate				pcm_event_manager(PCE_ADD_SOCKET,
12897c478bdstevel@tonic-gate				    sock, NULL);
12907c478bdstevel@tonic-gate			}
12917c478bdstevel@tonic-gate		}
12927c478bdstevel@tonic-gate
12937c478bdstevel@tonic-gate	}
12947c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
12957c478bdstevel@tonic-gate	if (pcmcia_debug) {
12967c478bdstevel@tonic-gate		cmn_err(CE_CONT, "logical sockets:\n");
12977c478bdstevel@tonic-gate		for (i = 0; i < pcmcia_num_sockets; i++) {
12987c478bdstevel@tonic-gate			if (pcmcia_sockets[i] == NULL)
12997c478bdstevel@tonic-gate				continue;
13007c478bdstevel@tonic-gate			cmn_err(CE_CONT,
13015c066ecJerry Gilliam			    "\t%d: phys sock=%d, if=%p, adapt=%p\n",
13025c066ecJerry Gilliam			    i, pcmcia_sockets[i]->ls_socket,
13035c066ecJerry Gilliam			    (void *)pcmcia_sockets[i]->ls_if,
13045c066ecJerry Gilliam			    (void *)pcmcia_sockets[i]->ls_adapter);
13057c478bdstevel@tonic-gate		}
13067c478bdstevel@tonic-gate		cmn_err(CE_CONT, "logical windows:\n");
13077c478bdstevel@tonic-gate		for (i = 0; i < pcmcia_num_windows; i++) {
13087c478bdstevel@tonic-gate			cmn_err(CE_CONT,
13095c066ecJerry Gilliam			    "\t%d: phys_window=%d, if=%p, adapt=%p\n",
13105c066ecJerry Gilliam			    i, pcmcia_windows[i]->lw_window,
13115c066ecJerry Gilliam			    (void *)pcmcia_windows[i]->lw_if,
13125c066ecJerry Gilliam			    (void *)pcmcia_windows[i]->lw_adapter);
13137c478bdstevel@tonic-gate		}
13147c478bdstevel@tonic-gate		cmn_err(CE_CONT, "\tpcmcia_num_power=%d\n", pcmcia_num_power);
13157c478bdstevel@tonic-gate		for (n = 0; n < pcmcia_num_power; n++)
13167c478bdstevel@tonic-gate			cmn_err(CE_CONT,
13175c066ecJerry Gilliam			    "\t\tPowerLevel: %d\tValidSignals: %x\n",
13185c066ecJerry Gilliam			    pcmcia_power_table[n].PowerLevel,
13195c066ecJerry Gilliam			    pcmcia_power_table[n].ValidSignals);
13207c478bdstevel@tonic-gate	}
13217c478bdstevel@tonic-gate#endif
13227c478bdstevel@tonic-gate}
13237c478bdstevel@tonic-gate
13247c478bdstevel@tonic-gate/*
13257c478bdstevel@tonic-gate * pcmcia_find_cards()
13267c478bdstevel@tonic-gate *	check the adapter to see if there are cards present at
13277c478bdstevel@tonic-gate *	driver attach time.  If there are, generate an artificial
13287c478bdstevel@tonic-gate *	card insertion event to get CS running and the PC Card ultimately
13297c478bdstevel@tonic-gate *	identified.
13307c478bdstevel@tonic-gate */
13317c478bdstevel@tonic-gatevoid
13327c478bdstevel@tonic-gatepcmcia_find_cards(anp_t *adapt)
13337c478bdstevel@tonic-gate{
13347c478bdstevel@tonic-gate	int i;
13357c478bdstevel@tonic-gate	get_ss_status_t status;
13367c478bdstevel@tonic-gate	for (i = 0; i < pcmcia_num_sockets; i++) {
13377c478bdstevel@tonic-gate		if (pcmcia_sockets[i] &&
13387c478bdstevel@tonic-gate		    pcmcia_sockets[i]->ls_if == adapt->an_if) {
13397c478bdstevel@tonic-gate			/* check the status */
13407c478bdstevel@tonic-gate			status.socket = i;
13417c478bdstevel@tonic-gate			if (SSGetStatus(&status) == SUCCESS &&
1342a9fb0aerw			    status.IFType != IF_CARDBUS &&
13437c478bdstevel@tonic-gate			    status.CardState & SBM_CD &&
13447c478bdstevel@tonic-gate			    pcmcia_sockets[i]->ls_dip[0] == NULL) {
13457c478bdstevel@tonic-gate				(void) cs_event(PCE_CARD_INSERT, i, 0);
13467c478bdstevel@tonic-gate				delay(1);
13477c478bdstevel@tonic-gate			}
13487c478bdstevel@tonic-gate		}
13497c478bdstevel@tonic-gate	}
13507c478bdstevel@tonic-gate}
13517c478bdstevel@tonic-gate
13527c478bdstevel@tonic-gate/*
13537c478bdstevel@tonic-gate * pcmcia_number_socket(dip, adapt)
13547c478bdstevel@tonic-gate *	we determine socket number by creating a driver for each
13557c478bdstevel@tonic-gate *	socket on the adapter and then forcing it to attach.  This
13567c478bdstevel@tonic-gate *	results in an instance being assigned which becomes the
13577c478bdstevel@tonic-gate *	logical socket number.	If it fails, then we are the first
13587c478bdstevel@tonic-gate *	set of sockets and renumbering occurs later.  We do this
13597c478bdstevel@tonic-gate *	one socket at a time and return the dev_info_t so the
13607c478bdstevel@tonic-gate *	instance number can be used.
13617c478bdstevel@tonic-gate */
13627c478bdstevel@tonic-gatedev_info_t *
13637c478bdstevel@tonic-gatepcmcia_number_socket(dev_info_t *dip, int localsocket)
13647c478bdstevel@tonic-gate{
13657c478bdstevel@tonic-gate	dev_info_t *child = NULL;
13667c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
13677c478bdstevel@tonic-gate
1368fa9e406ahrens	if (ndi_devi_alloc(dip, "pcs", (pnode_t)DEVI_SID_NODEID,
13697c478bdstevel@tonic-gate	    &child) == NDI_SUCCESS) {
13707c478bdstevel@tonic-gate		ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private),
13717c478bdstevel@tonic-gate		    KM_SLEEP);
13727c478bdstevel@tonic-gate		ppd->ppd_reg = kmem_zalloc(sizeof (struct pcm_regs), KM_SLEEP);
13737c478bdstevel@tonic-gate		ppd->ppd_nreg = 1;
13747c478bdstevel@tonic-gate		ppd->ppd_reg[0].phys_hi = localsocket;
13757c478bdstevel@tonic-gate		ddi_set_parent_data(child, (caddr_t)ppd);
13767c478bdstevel@tonic-gate		if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
1377981012arw			kmem_free(ppd->ppd_reg, sizeof (struct pcm_regs));
1378981012arw			kmem_free(ppd, sizeof (struct pcmcia_parent_private));
13797c478bdstevel@tonic-gate			(void) ndi_devi_free(child);
13807c478bdstevel@tonic-gate			child = NULL;
13817c478bdstevel@tonic-gate		}
13827c478bdstevel@tonic-gate	}
13837c478bdstevel@tonic-gate	return (child);
13847c478bdstevel@tonic-gate}
13857c478bdstevel@tonic-gate
13867c478bdstevel@tonic-gate/*
13877c478bdstevel@tonic-gate * pcm_phys_to_log_socket()
13887c478bdstevel@tonic-gate *	from an adapter and socket number return the logical socket
13897c478bdstevel@tonic-gate */
13907c478bdstevel@tonic-gateint
13917c478bdstevel@tonic-gatepcm_phys_to_log_socket(struct pcmcia_adapter *adapt, int socket)
13927c478bdstevel@tonic-gate{
13937c478bdstevel@tonic-gate	register pcmcia_logical_socket_t *sockp;
13947c478bdstevel@tonic-gate	int i;
13957c478bdstevel@tonic-gate
13967c478bdstevel@tonic-gate	for (i = 0, sockp = pcmcia_sockets[0];
13975c066ecJerry Gilliam	    i < pcmcia_num_sockets; i++, sockp = pcmcia_sockets[i]) {
13987c478bdstevel@tonic-gate		if (sockp == NULL)
13997c478bdstevel@tonic-gate			continue;
14007c478bdstevel@tonic-gate		if (sockp->ls_socket == socket && sockp->ls_adapter == adapt)
14017c478bdstevel@tonic-gate			break;
14027c478bdstevel@tonic-gate	}
14037c478bdstevel@tonic-gate	if (i >= pcmcia_num_sockets) {
14047c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
14057c478bdstevel@tonic-gate		if (pcmcia_debug)
14067c478bdstevel@tonic-gate			cmn_err(CE_CONT,
14075c066ecJerry Gilliam			    "\tbad socket/adapter: %x/%p != %x/%x\n",
14085c066ecJerry Gilliam			    socket, (void *)adapt, pcmcia_num_sockets,
14095c066ecJerry Gilliam			    pcmcia_num_adapters);
14107c478bdstevel@tonic-gate#endif
14117c478bdstevel@tonic-gate		return (-1);
14127c478bdstevel@tonic-gate	}
14137c478bdstevel@tonic-gate
14147c478bdstevel@tonic-gate	return (i);		/* want logical socket */
14157c478bdstevel@tonic-gate}
14167c478bdstevel@tonic-gate
14177c478bdstevel@tonic-gate/*
14187c478bdstevel@tonic-gate * pcm_adapter_callback()
14197c478bdstevel@tonic-gate *	this function is called back by the adapter driver at interrupt time.
14207c478bdstevel@tonic-gate *	It is here that events should get generated for the event manager if it
14217c478bdstevel@tonic-gate *	is present.  It would also be the time where a device information
14227c478bdstevel@tonic-gate *	tree could be constructed for a card that was added in if we
14237c478bdstevel@tonic-gate *	choose to create them dynamically.
14247c478bdstevel@tonic-gate */
14257c478bdstevel@tonic-gate
14267c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
14277c478bdstevel@tonic-gatechar *cblist[] = {
14287c478bdstevel@tonic-gate	"removal",
14297c478bdstevel@tonic-gate	"insert",
14307c478bdstevel@tonic-gate	"ready",
14317c478bdstevel@tonic-gate	"battery-warn",
14327c478bdstevel@tonic-gate	"battery-dead",
14337c478bdstevel@tonic-gate	"status-change",
14347c478bdstevel@tonic-gate	"write-protect", "reset", "unlock", "client-info", "eject-complete",
14357c478bdstevel@tonic-gate	"eject-request", "erase-complete", "exclusive-complete",
14367c478bdstevel@tonic-gate	"exclusive-request", "insert-complete", "insert-request",
14377c478bdstevel@tonic-gate	"reset-complete", "reset-request", "timer-expired",
14387c478bdstevel@tonic-gate	"resume", "suspend"
14397c478bdstevel@tonic-gate};
14407c478bdstevel@tonic-gate#endif
14417c478bdstevel@tonic-gate
14427c478bdstevel@tonic-gate/*ARGSUSED*/
14437c478bdstevel@tonic-gatestatic int
14447c478bdstevel@tonic-gatepcm_adapter_callback(dev_info_t *dip, int adapter, int event, int socket)
14457c478bdstevel@tonic-gate{
14467c478bdstevel@tonic-gate	pcmcia_logical_socket_t *sockp;
14477c478bdstevel@tonic-gate
14487c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
14497c478bdstevel@tonic-gate	if (pcmcia_debug) {
14507c478bdstevel@tonic-gate		cmn_err(CE_CONT, "pcm_adapter_callback: %p %x %x %x: ",
14515c066ecJerry Gilliam		    (void *)dip, adapter, event, socket);
14527c478bdstevel@tonic-gate		cmn_err(CE_CONT, "[%s]\n", cblist[event]);
14537c478bdstevel@tonic-gate	}
14547c478bdstevel@tonic-gate#endif
14557c478bdstevel@tonic-gate
14567c478bdstevel@tonic-gate	if (adapter >= pcmcia_num_adapters || adapter < 0) {
14577c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
14587c478bdstevel@tonic-gate		if (pcmcia_debug)
14597c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\tbad adapter number: %d : %d\n",
14605c066ecJerry Gilliam			    adapter, pcmcia_num_adapters);
14617c478bdstevel@tonic-gate#endif
14627c478bdstevel@tonic-gate		return (1);
14637c478bdstevel@tonic-gate	}
14647c478bdstevel@tonic-gate
14657c478bdstevel@tonic-gate	/* get the logical socket since that is what CS knows */
14667c478bdstevel@tonic-gate	socket = pcm_phys_to_log_socket(pcmcia_adapters[adapter], socket);
14677c478bdstevel@tonic-gate	if (socket == -1) {
14687c478bdstevel@tonic-gate		cmn_err(CE_WARN, "pcmcia callback - bad logical socket\n");
14697c478bdstevel@tonic-gate		return (0);
14707c478bdstevel@tonic-gate	}
14717c478bdstevel@tonic-gate	sockp = pcmcia_sockets[socket];
14727c478bdstevel@tonic-gate	switch (event) {
14737c478bdstevel@tonic-gate	case -1:		/* special case of adapter going away */
14747c478bdstevel@tonic-gate	case PCE_CARD_INSERT:
14757c478bdstevel@tonic-gate		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
14765c066ecJerry Gilliam		    PCE_E2M(PCE_CARD_REMOVAL);
14777c478bdstevel@tonic-gate		break;
14787c478bdstevel@tonic-gate	case PCE_CARD_REMOVAL:
14797c478bdstevel@tonic-gate				/* disable interrupts at this point */
14807c478bdstevel@tonic-gate		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
14815c066ecJerry Gilliam		    PCE_E2M(PCE_CARD_REMOVAL);
14827c478bdstevel@tonic-gate		/* remove children that never attached */
14837c478bdstevel@tonic-gate
14847c478bdstevel@tonic-gate		break;
14857c478bdstevel@tonic-gate	case PCE_PM_RESUME:
14867c478bdstevel@tonic-gate		pcmcia_do_resume(socket, sockp);
14877c478bdstevel@tonic-gate		/* event = PCE_CARD_INSERT; */
14887c478bdstevel@tonic-gate		break;
14897c478bdstevel@tonic-gate	case PCE_PM_SUSPEND:
14907c478bdstevel@tonic-gate		pcmcia_do_suspend(socket, sockp);
14917c478bdstevel@tonic-gate		/* event = PCE_CARD_REMOVAL; */
14927c478bdstevel@tonic-gate		break;
14937c478bdstevel@tonic-gate	default:
14947c478bdstevel@tonic-gate		/* nothing to do */
14957c478bdstevel@tonic-gate		break;
14967c478bdstevel@tonic-gate	}
14977c478bdstevel@tonic-gate
14987c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
14997c478bdstevel@tonic-gate	if (pcmcia_debug) {
15007c478bdstevel@tonic-gate		cmn_err(CE_CONT,
15015c066ecJerry Gilliam		    "\tevent %d, event mask=%x, match=%x (log socket=%d)\n",
15025c066ecJerry Gilliam		    event,
15035c066ecJerry Gilliam		    (int)sockp->ls_cs_events,
15045c066ecJerry Gilliam		    (int)(sockp->ls_cs_events & PCE_E2M(event)), socket);
15057c478bdstevel@tonic-gate	}
15067c478bdstevel@tonic-gate#endif
15077c478bdstevel@tonic-gate
15087c478bdstevel@tonic-gate	if (pcmcia_cs_event && sockp->ls_cs_events & (1 << event)) {
15097c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
15107c478bdstevel@tonic-gate		if (pcmcia_debug)
15117c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\tcalling CS event handler (%p) "
15125c066ecJerry Gilliam			    "with event=%d\n",
15135c066ecJerry Gilliam			    (void *)pcmcia_cs_event, event);
15147c478bdstevel@tonic-gate#endif
15157c478bdstevel@tonic-gate		CS_EVENT(event, socket, 0);
15167c478bdstevel@tonic-gate	}
15177c478bdstevel@tonic-gate
15187c478bdstevel@tonic-gate	/* let the event manager(s) know about the event */
15197c478bdstevel@tonic-gate	pcm_event_manager(event, socket, NULL);
15207c478bdstevel@tonic-gate
15217c478bdstevel@tonic-gate	return (0);
15227c478bdstevel@tonic-gate}
15237c478bdstevel@tonic-gate
15247c478bdstevel@tonic-gate/*
15257c478bdstevel@tonic-gate * pcm_event_manager()
15267c478bdstevel@tonic-gate *	checks for registered management driver callback handlers
15277c478bdstevel@tonic-gate *	if there are any, call them if the event warrants it
15287c478bdstevel@tonic-gate */
15297c478bdstevel@tonic-gatevoid
15307c478bdstevel@tonic-gatepcm_event_manager(int event, int socket, void *arg)
15317c478bdstevel@tonic-gate{
15327c478bdstevel@tonic-gate	struct pcmcia_mif *mif;
15337c478bdstevel@tonic-gate
15347c478bdstevel@tonic-gate	for (mif = pcmcia_mif_handlers; mif != NULL; mif = mif->mif_next) {
15357c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
15367c478bdstevel@tonic-gate		if (pcmcia_debug)
15377c478bdstevel@tonic-gate			cmn_err(CE_CONT,
15385c066ecJerry Gilliam			    "pcm_event_manager: event=%d, mif_events=%x"
15395c066ecJerry Gilliam			    " (tst:%d)\n",
15405c066ecJerry Gilliam			    event, (int)*(uint32_t *)mif->mif_events,
15415c066ecJerry Gilliam			    PR_GET(mif->mif_events, event));
15427c478bdstevel@tonic-gate#endif
15437c478bdstevel@tonic-gate		if (PR_GET(mif->mif_events, event)) {
15447c478bdstevel@tonic-gate			mif->mif_function(mif->mif_id, event, socket, arg);
15457c478bdstevel@tonic-gate		}
15467c478bdstevel@tonic-gate	}
15477c478bdstevel@tonic-gate
15487c478bdstevel@tonic-gate}
15497c478bdstevel@tonic-gate
15507c478bdstevel@tonic-gate/*
15517c478bdstevel@tonic-gate * pcm_search_devinfo(dev_info_t *, pcm_device_info *, int)
15527c478bdstevel@tonic-gate * search for an immediate child node to the nexus and not siblings of nexus
15537c478bdstevel@tonic-gate * and not grandchildren.  We follow the same sequence that name binding
15547c478bdstevel@tonic-gate * follows so we match same class of device (modem == modem) and don't
15557c478bdstevel@tonic-gate * have to depend on features that might not exist.
15567c478bdstevel@tonic-gate */
15577c478bdstevel@tonic-gatedev_info_t *
15587c478bdstevel@tonic-gatepcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket)
15597c478bdstevel@tonic-gate{
15607c478bdstevel@tonic-gate	char bf[256];
15617c478bdstevel@tonic-gate	struct pcmcia_parent_private *ppd;
15627c478bdstevel@tonic-gate	dev_info_t *dip;
1563b9ccdc5cth	int circ;
15647c478bdstevel@tonic-gate
15657c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
15667c478bdstevel@tonic-gate	if (pcmcia_debug)
15677c478bdstevel@tonic-gate		cmn_err(CE_CONT,
15687c478bdstevel@tonic-gate		    "pcm_search_devinfo: socket=%x [%s|%s|%s] pd_flags=%x\n",
15697c478bdstevel@tonic-gate		    socket, info->pd_bind_name, info->pd_generic_name,
15707c478bdstevel@tonic-gate		    info->pd_vers1_name, info->pd_flags);
15717c478bdstevel@tonic-gate#endif
15727c478bdstevel@tonic-gate
1573b9ccdc5cth	ndi_devi_enter(self, &circ);
15747c478bdstevel@tonic-gate	/* do searches in compatible property order */
15757c478bdstevel@tonic-gate	for (dip = (dev_info_t *)DEVI(self)->devi_child;
15767c478bdstevel@tonic-gate	    dip != NULL;
15777c478bdstevel@tonic-gate	    dip = (dev_info_t *)DEVI(dip)->devi_sibling) {
15787c478bdstevel@tonic-gate		int ppd_socket;
15797c478bdstevel@tonic-gate		ppd = (struct pcmcia_parent_private *)
15805c066ecJerry Gilliam		    ddi_get_parent_data(dip);
15817c478bdstevel@tonic-gate		if (ppd == NULL) {
15827c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
15837c478bdstevel@tonic-gate			cmn_err(CE_WARN, "No parent private data\n");
15847c478bdstevel@tonic-gate#endif
15857c478bdstevel@tonic-gate			continue;
15867c478bdstevel@tonic-gate		}
15877c478bdstevel@tonic-gate		ppd_socket = CS_MAKE_SOCKET_NUMBER(ppd->ppd_socket,
15887c478bdstevel@tonic-gate		    ppd->ppd_function);
15897c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
15907c478bdstevel@tonic-gate		if (pcmcia_debug) {
15917c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\tbind=[%s], node=[%s]\n",
15925c066ecJerry Gilliam			    DEVI(dip)->devi_binding_name,
15935c066ecJerry Gilliam			    DEVI(dip)->devi_node_name);
15947c478bdstevel@tonic-gate		}
15957c478bdstevel@tonic-gate#endif
15967c478bdstevel@tonic-gate		if (info->pd_flags & PCM_NAME_VERS1) {
15977c478bdstevel@tonic-gate			(void) strcpy(bf, info->pd_vers1_name);
15987c478bdstevel@tonic-gate			pcmcia_fix_string(bf);
15997c478bdstevel@tonic-gate			if (DEVI(dip)->devi_binding_name &&
16007c478bdstevel@tonic-gate			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
16017c478bdstevel@tonic-gate			    socket == ppd_socket)
16027c478bdstevel@tonic-gate				break;
16037c478bdstevel@tonic-gate		}
16047c478bdstevel@tonic-gate		if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) ==
16057c478bdstevel@tonic-gate		    (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) {
16067c478bdstevel@tonic-gate			(void) sprintf(bf, "%s,%x", info->pd_bind_name,
16075c066ecJerry Gilliam			    info->pd_function);
16087c478bdstevel@tonic-gate			if (strcmp(bf, DEVI(dip)->devi_binding_name) == 0 &&
16097c478bdstevel@tonic-gate			    socket == ppd->ppd_socket)
16107c478bdstevel@tonic-gate				break;
16117c478bdstevel@tonic-gate		}
16127c478bdstevel@tonic-gate		if (info->pd_flags & PCM_NAME_1275) {
16137c478bdstevel@tonic-gate			if (DEVI(dip)->devi_binding_name &&
16147c478bdstevel@tonic-gate			    strcmp(DEVI(dip)->devi_binding_name,
16155c066ecJerry Gilliam			    info->pd_bind_name) == 0 &&
16167c478bdstevel@tonic-gate			    socket == ppd_socket)
16177c478bdstevel@tonic-gate				break;
16187c478bdstevel@tonic-gate		}
16197c478bdstevel@tonic-gate		if (info->pd_flags & PCM_NAME_GENERIC) {
16207c478bdstevel@tonic-gate			(void) sprintf(bf, "%s,%s", PCMDEV_NAMEPREF,
16215c066ecJerry Gilliam			    info->pd_generic_name);
16227c478bdstevel@tonic-gate			if (DEVI(dip)->devi_binding_name &&
16237c478bdstevel@tonic-gate			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
16247c478bdstevel@tonic-gate			    socket == ppd_socket)
16257c478bdstevel@tonic-gate				break;
16267c478bdstevel@tonic-gate		}
16277c478bdstevel@tonic-gate		if (info->pd_flags & PCM_NAME_GENERIC) {
16287c478bdstevel@tonic-gate			if (DEVI(dip)->devi_binding_name &&
16297c478bdstevel@tonic-gate			    strcmp(DEVI(dip)->devi_binding_name,
16305c066ecJerry Gilliam			    info->pd_generic_name) == 0 &&
16317c478bdstevel@tonic-gate			    socket == ppd_socket)
16327c478bdstevel@tonic-gate				break;
16337c478bdstevel@tonic-gate		}
16347c478bdstevel@tonic-gate		if (info->pd_flags & PCM_NO_CONFIG) {
16357c478bdstevel@tonic-gate			if (DEVI(dip)->devi_binding_name &&
16367c478bdstevel@tonic-gate			    strcmp(DEVI(dip)->devi_binding_name,
16375c066ecJerry Gilliam			    "pccard,memory") == 0 &&
16387c478bdstevel@tonic-gate			    socket == ppd_socket)
16397c478bdstevel@tonic-gate				break;
16407c478bdstevel@tonic-gate		}
16417c478bdstevel@tonic-gate	}
1642b9ccdc5cth	ndi_devi_exit(self, circ);
16437c478bdstevel@tonic-gate	return (dip);
16447c478bdstevel@tonic-gate}
16457c478bdstevel@tonic-gate
16467c478bdstevel@tonic-gate/*
16477c478bdstevel@tonic-gate * pcm_find_devinfo()
16487c478bdstevel@tonic-gate *	this is a wrapper around DDI calls to "find" any
16497c478bdstevel@tonic-gate *	devinfo node and then from there find the one associated
16507c478bdstevel@tonic-gate *	with the socket
16517c478bdstevel@tonic-gate */
16527c478bdstevel@tonic-gatedev_info_t *
16537c478bdstevel@tonic-gatepcm_find_devinfo(dev_info_t *pdip, struct pcm_device_info *info, int socket)
16547c478bdstevel@tonic-gate{
16557c478bdstevel@tonic-gate	dev_info_t *dip;
16567c478bdstevel@tonic-gate
16577c478bdstevel@tonic-gate	dip = pcm_search_devinfo(pdip, info, socket);
16587c478bdstevel@tonic-gate	if (dip == NULL)
16597c478bdstevel@tonic-gate		return (NULL);
16607c478bdstevel@tonic-gate	/*
16617c478bdstevel@tonic-gate	 * we have at least a base level dip
16627c478bdstevel@tonic-gate	 * see if there is one (this or a sibling)
16637c478bdstevel@tonic-gate	 * that has the correct socket number
16647c478bdstevel@tonic-gate	 * if there is, return that one else
16657c478bdstevel@tonic-gate	 * NULL so a new one is created
16667c478bdstevel@tonic-gate	 */
16677c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
16687c478bdstevel@tonic-gate	if (pcmcia_debug)
16697c478bdstevel@tonic-gate		cmn_err(CE_CONT, "find: initial dip = %p, socket=%d, name=%s "
16705c066ecJerry Gilliam		    "(instance=%d, socket=%d, name=%s)\n",
16715c066ecJerry Gilliam		    (void *)dip, socket, info->pd_bind_name,
16725c066ecJerry Gilliam		    ddi_get_instance(dip),
16735c066ecJerry Gilliam		    ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
16745c066ecJerry Gilliam		    PCM_DEV_SOCKET, -1),
16755c066ecJerry Gilliam		    ddi_get_name(dip));
16767c478bdstevel@tonic-gate#endif
16777c478bdstevel@tonic-gate
16787c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
16797c478bdstevel@tonic-gate	if (pcmcia_debug && dip != NULL)
16807c478bdstevel@tonic-gate		cmn_err(CE_CONT, "\treturning non-NULL dip (%s)\n",
16815c066ecJerry Gilliam		    ddi_get_name(dip));
16827c478bdstevel@tonic-gate#endif
16837c478bdstevel@tonic-gate	return (dip);
16847c478bdstevel@tonic-gate}
16857c478bdstevel@tonic-gate
16867c478bdstevel@tonic-gate/*
16877c478bdstevel@tonic-gate * pcm_find_parent_dip(socket)
16887c478bdstevel@tonic-gate *	find the correct parent dip for this logical socket
16897c478bdstevel@tonic-gate */
16907c478bdstevel@tonic-gatedev_info_t *
16917c478bdstevel@tonic-gatepcm_find_parent_dip(int socket)
16927c478bdstevel@tonic-gate{
16937c478bdstevel@tonic-gate	if ((socket < 0 || socket >= pcmcia_num_sockets) ||
16947c478bdstevel@tonic-gate	    pcmcia_sockets[socket] == NULL)
16957c478bdstevel@tonic-gate		return (NULL);
16967c478bdstevel@tonic-gate	return (pcmcia_sockets[socket]->ls_adapter->pca_dip);
16977c478bdstevel@tonic-gate}
16987c478bdstevel@tonic-gate
16997c478bdstevel@tonic-gate/*
17007c478bdstevel@tonic-gate * pcmcia_set_em_handler()
17017c478bdstevel@tonic-gate *	This is called by the management and event driver to tell
17027c478bdstevel@tonic-gate *	the nexus what to call.	 Multiple drivers are allowed
17037c478bdstevel@tonic-gate *	but normally only one will exist.
17047c478bdstevel@tonic-gate */
17057c478bdstevel@tonic-gateint
17067c478bdstevel@tonic-gatepcmcia_set_em_handler(int (*handler)(), caddr_t events, int elen,
17073f068ebToomas Soome    uint32_t id, void **cs, void **ss)
17087c478bdstevel@tonic-gate{
17097c478bdstevel@tonic-gate	struct pcmcia_mif *mif, *tmp;
17107c478bdstevel@tonic-gate
17117c478bdstevel@tonic-gate	if (handler == NULL) {
17127c478bdstevel@tonic-gate		/* NULL means remove the handler based on the ID */
17137c478bdstevel@tonic-gate		if (pcmcia_mif_handlers == NULL)
17147c478bdstevel@tonic-gate			return (0);
17157c478bdstevel@tonic-gate		mutex_enter(&pcmcia_global_lock);
17167c478bdstevel@tonic-gate		if (pcmcia_mif_handlers->mif_id == id) {
17177c478bdstevel@tonic-gate			mif = pcmcia_mif_handlers;
17187c478bdstevel@tonic-gate			pcmcia_mif_handlers = mif->mif_next;
17197c478bdstevel@tonic-gate			kmem_free(mif, sizeof (struct pcmcia_mif));
17207c478bdstevel@tonic-gate		} else {
17217c478bdstevel@tonic-gate			for (mif = pcmcia_mif_handlers;
17227c478bdstevel@tonic-gate			    mif->mif_next != NULL &&
17237c478bdstevel@tonic-gate			    mif->mif_next->mif_id != id;
17247c478bdstevel@tonic-gate			    mif = mif->mif_next)
17257c478bdstevel@tonic-gate				;
17267c478bdstevel@tonic-gate			if (mif->mif_next != NULL &&
17277c478bdstevel@tonic-gate			    mif->mif_next->mif_id == id) {
17287c478bdstevel@tonic-gate				tmp = mif->mif_next;
17297c478bdstevel@tonic-gate				mif->mif_next = tmp->mif_next;
17307c478bdstevel@tonic-gate				kmem_free(tmp, sizeof (struct pcmcia_mif));
17317c478bdstevel@tonic-gate			}
17327c478bdstevel@tonic-gate		}
17337c478bdstevel@tonic-gate		mutex_exit(&pcmcia_global_lock);
17347c478bdstevel@tonic-gate	} else {
17357c478bdstevel@tonic-gate
17367c478bdstevel@tonic-gate		if (pcmcia_num_adapters == 0) {
17377c478bdstevel@tonic-gate			return (ENXIO);
17387c478bdstevel@tonic-gate		}
17397c478bdstevel@tonic-gate		if (elen > EM_EVENTSIZE)
17407c478bdstevel@tonic-gate			return (EINVAL);
17417c478bdstevel@tonic-gate
17427c478bdstevel@tonic-gate		mif = (struct pcmcia_mif *)
17435c066ecJerry Gilliam		    kmem_zalloc(sizeof (struct pcmcia_mif), KM_NOSLEEP);
17447c478bdstevel@tonic-gate		if (mif == NULL)
17457c478bdstevel@tonic-gate			return (ENOSPC);
17467c478bdstevel@tonic-gate
1747ebf3735Toomas Soome		mif->mif_function = (void (*)())(uintptr_t)handler;
17487c478bdstevel@tonic-gate		bcopy(events, mif->mif_events, elen);
17497c478bdstevel@tonic-gate		mif->mif_id = id;
17507c478bdstevel@tonic-gate		mutex_enter(&pcmcia_global_lock);
17517c478bdstevel@tonic-gate		mif->mif_next = pcmcia_mif_handlers;
17527c478bdstevel@tonic-gate		pcmcia_mif_handlers = mif;
17537c478bdstevel@tonic-gate		if (cs != NULL)
17547c478bdstevel@tonic-gate			*cs = (void *)pcmcia_card_services;
17557c478bdstevel@tonic-gate		if (ss != NULL) {
17567c478bdstevel@tonic-gate			*ss = (void *)SocketServices;
17577c478bdstevel@tonic-gate		}
17587c478bdstevel@tonic-gate
17597c478bdstevel@tonic-gate		mutex_exit(&pcmcia_global_lock);
17607c478bdstevel@tonic-gate	}
17617c478bdstevel@tonic-gate	return (0);
17627c478bdstevel@tonic-gate}
17637c478bdstevel@tonic-gate
17647c478bdstevel@tonic-gate/*
17657c478bdstevel@tonic-gate * pcm_fix_bits(uchar_t *data, int num, int dir)
17667c478bdstevel@tonic-gate *	shift socket bits left(0) or right(0)
17677c478bdstevel@tonic-gate *	This is used when mapping logical and physical
17687c478bdstevel@tonic-gate */
17697c478bdstevel@tonic-gatevoid
17707c478bdstevel@tonic-gatepcm_fix_bits(socket_enum_t src, socket_enum_t dst, int num, int dir)
17717c478bdstevel@tonic-gate{
17727c478bdstevel@tonic-gate	int i;
17737c478bdstevel@tonic-gate
17747c478bdstevel@tonic-gate	PR_ZERO(dst);
17757c478bdstevel@tonic-gate
17767c478bdstevel@tonic-gate	if (dir == 0) {
17777c478bdstevel@tonic-gate				/* LEFT */
177824a150cToomas Soome		for (i = 0; i <= PCMCIA_MAX_SOCKETS - num; i++) {
17797c478bdstevel@tonic-gate			if (PR_GET(src, i))
17807c478bdstevel@tonic-gate				PR_SET(dst, i + num);
17817c478bdstevel@tonic-gate		}
17827c478bdstevel@tonic-gate	} else {
17837c478bdstevel@tonic-gate				/* RIGHT */
178424a150cToomas Soome		for (i = num; i < PCMCIA_MAX_SOCKETS; i++) {
17857c478bdstevel@tonic-gate			if (PR_GET(src, i))
17865c066ecJerry Gilliam				PR_SET(dst, i - num);
17877c478bdstevel@tonic-gate		}
17887c478bdstevel@tonic-gate	}
17897c478bdstevel@tonic-gate}
17907c478bdstevel@tonic-gate
17917c478bdstevel@tonic-gateuint32_t
17927c478bdstevel@tonic-gategenmask(int len)
17937c478bdstevel@tonic-gate{
17947c478bdstevel@tonic-gate	uint32_t mask;
17957c478bdstevel@tonic-gate	for (mask = 0; len > 0; len--) {
17967c478bdstevel@tonic-gate		mask |= 1 << (len - 1);
17977c478bdstevel@tonic-gate	}
17987c478bdstevel@tonic-gate	return (mask);
17997c478bdstevel@tonic-gate}
18007c478bdstevel@tonic-gate
18017c478bdstevel@tonic-gateint
18027c478bdstevel@tonic-gategenp2(int val)
18037c478bdstevel@tonic-gate{
18047c478bdstevel@tonic-gate	int i;
18057c478bdstevel@tonic-gate	if (val == 0)
18067c478bdstevel@tonic-gate		return (0);
18077c478bdstevel@tonic-gate	for (i = 0; i < 32; i++)
18087c478bdstevel@tonic-gate		if (val > (1 << i))
18097c478bdstevel@tonic-gate			return (i);
18107c478bdstevel@tonic-gate	return (0);
18117c478bdstevel@tonic-gate}
18127c478bdstevel@tonic-gate
18137c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
18147c478bdstevel@tonic-gatechar *ssfuncs[128] = {
18157c478bdstevel@tonic-gate	"GetAdapter", "GetPage", "GetSocket", "GetStatus", "GetWindow",
18167c478bdstevel@tonic-gate	"InquireAdapter", "InquireSocket", "InquireWindow", "ResetSocket",
18177c478bdstevel@tonic-gate	"SetPage", "SetAdapter", "SetSocket", "SetWindow", "SetIRQHandler",
18187c478bdstevel@tonic-gate	"ClearIRQHandler",
18197c478bdstevel@tonic-gate	/* 15 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18207c478bdstevel@tonic-gate	/* 25 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18217c478bdstevel@tonic-gate	/* 35 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18227c478bdstevel@tonic-gate	/* 45 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18237c478bdstevel@tonic-gate	/* 55 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18247c478bdstevel@tonic-gate	/* 65 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18257c478bdstevel@tonic-gate	/* 75 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18267c478bdstevel@tonic-gate	/* 85 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
18277c478bdstevel@tonic-gate	/* 95 */ NULL, NULL, NULL,
18287c478bdstevel@tonic-gate	"CSIsActiveDip",
18297c478bdstevel@tonic-gate	"CSInitDev", "CSRegister", "CSCISInit", "CSUnregister",
18307c478bdstevel@tonic-gate	"CISGetAddress", "CISSetAddress", "CSCardRemoved", "CSGetCookiesAndDip"
18317c478bdstevel@tonic-gate};
18327c478bdstevel@tonic-gate#endif
18337c478bdstevel@tonic-gate
18347c478bdstevel@tonic-gate/*
18357c478bdstevel@tonic-gate * SocketServices
18367c478bdstevel@tonic-gate *	general entrypoint for Card Services to find
18377c478bdstevel@tonic-gate *	Socket Services.  Finding the entry requires
18387c478bdstevel@tonic-gate *	a _depends_on[] relationship.
18397c478bdstevel@tonic-gate *
18407c478bdstevel@tonic-gate *	In some cases, the work is done locally but usually
18417c478bdstevel@tonic-gate *	the parameters are adjusted and the adapter driver
18427c478bdstevel@tonic-gate *	code asked to do the work.
18437c478bdstevel@tonic-gate */
18447c478bdstevel@tonic-gateint
18457c478bdstevel@tonic-gateSocketServices(int function, ...)
18467c478bdstevel@tonic-gate{
18477c478bdstevel@tonic-gate	va_list arglist;
18487c478bdstevel@tonic-gate	uint32_t args[16];
18497c478bdstevel@tonic-gate	csregister_t *reg;
18507c478bdstevel@tonic-gate	sservice_t *serv;
18517c478bdstevel@tonic-gate	dev_info_t *dip;
18527c478bdstevel@tonic-gate	int socket, func;
18537c478bdstevel@tonic-gate	int error = SUCCESS;
18547c478bdstevel@tonic-gate	pcmcia_logical_socket_t *sockp;
18557c478bdstevel@tonic-gate
18567c478bdstevel@tonic-gate	va_start(arglist, function);
18577c478bdstevel@tonic-gate
18587c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
18597c478bdstevel@tonic-gate	if (pcmcia_debug > 1)
18607c478bdstevel@tonic-gate		cmn_err(CE_CONT, "SocketServices called for function %d [%s]\n",
18615c066ecJerry Gilliam		    function,
18625c066ecJerry Gilliam		    ((function < 128) && ssfuncs[function] != NULL) ?
18635c066ecJerry Gilliam		    ssfuncs[function] : "UNKNOWN");
18647c478bdstevel@tonic-gate#endif
18657c478bdstevel@tonic-gate	switch (function) {
18667c478bdstevel@tonic-gate	case CSRegister:
18677c478bdstevel@tonic-gate	case CISGetAddress:
18687c478bdstevel@tonic-gate	case CISSetAddress:
18697c478bdstevel@tonic-gate
18707c478bdstevel@tonic-gate		reg = va_arg(arglist, csregister_t *);
18717c478bdstevel@tonic-gate
18727c478bdstevel@tonic-gate		if (reg->cs_magic != PCCS_MAGIC ||
18737c478bdstevel@tonic-gate		    reg->cs_version != PCCS_VERSION) {
18747c478bdstevel@tonic-gate			cmn_err(CE_WARN,
18755c066ecJerry Gilliam			    "pcmcia: CSRegister (%x, %x, %p, %p) *ERROR*",
18765c066ecJerry Gilliam			    reg->cs_magic, reg->cs_version,
18775c066ecJerry Gilliam			    (void *)reg->cs_card_services,
18785c066ecJerry Gilliam			    (void *)reg->cs_event);
18797c478bdstevel@tonic-gate			error = BAD_FUNCTION;
18807c478bdstevel@tonic-gate			break;
18817c478bdstevel@tonic-gate		}
18827c478bdstevel@tonic-gate
18837c478bdstevel@tonic-gate		switch (function) {
18847c478bdstevel@tonic-gate		case CISGetAddress:
18857c478bdstevel@tonic-gate			reg->cs_event = pcmcia_cis_parser;
18867c478bdstevel@tonic-gate			break;
18877c478bdstevel@tonic-gate		case CISSetAddress:
18887c478bdstevel@tonic-gate			pcmcia_cis_parser = reg->cs_event;
18897c478bdstevel@tonic-gate			break;
18907c478bdstevel@tonic-gate		case CSRegister:
18917c478bdstevel@tonic-gate			break;
18927c478bdstevel@tonic-gate		}
18937c478bdstevel@tonic-gate		break;
18947c478bdstevel@tonic-gate
18957c478bdstevel@tonic-gate	case CSUnregister:
18967c478bdstevel@tonic-gate		break;
18977c478bdstevel@tonic-gate
18987c478bdstevel@tonic-gate	case CSCISInit:
18997c478bdstevel@tonic-gate		args[0] = va_arg(arglist, int);
19007c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
19017c478bdstevel@tonic-gate		if (pcmcia_debug)
19027c478bdstevel@tonic-gate			cmn_err(CE_CONT,
19035c066ecJerry Gilliam			    "CSCISInit: CIS is initialized on socket %d\n",
19045c066ecJerry Gilliam			    (int)args[0]);
19057c478bdstevel@tonic-gate#endif
19067c478bdstevel@tonic-gate		/*
19077c478bdstevel@tonic-gate		 * now that the CIS has been parsed (there may not
19087c478bdstevel@tonic-gate		 * be one but the work is done) we can create the
19097c478bdstevel@tonic-gate		 * device information structures.
19107c478bdstevel@tonic-gate		 *
19117c478bdstevel@tonic-gate		 * we serialize the node creation to avoid problems
19127c478bdstevel@tonic-gate		 * with initial probe/attach of nexi.
19137c478bdstevel@tonic-gate		 */
19147c478bdstevel@tonic-gate
19157c478bdstevel@tonic-gate		mutex_enter(&pcmcia_global_lock);
19167c478bdstevel@tonic-gate		pcmcia_create_dev_info(args[0]);
19177c478bdstevel@tonic-gate		cv_broadcast(&pcmcia_condvar); /* wakeup the nexus attach */
19187c478bdstevel@tonic-gate		mutex_exit(&pcmcia_global_lock);
19197c478bdstevel@tonic-gate		break;
19207c478bdstevel@tonic-gate
19217c478bdstevel@tonic-gate	case CSInitDev:
19227c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
19237c478bdstevel@tonic-gate		if (pcmcia_debug)
19247c478bdstevel@tonic-gate			cmn_err(CE_CONT, "CSInitDev: initialize device\n");
19257c478bdstevel@tonic-gate#endif
19267c478bdstevel@tonic-gate		/*
19277c478bdstevel@tonic-gate		 * this is where we create the /devices entries
19287c478bdstevel@tonic-gate		 * that let us out into the world
19297c478bdstevel@tonic-gate		 */
19307c478bdstevel@tonic-gate
19317c478bdstevel@tonic-gate		(void) pcmcia_create_device(va_arg(arglist,
19327c478bdstevel@tonic-gate		    ss_make_device_node_t *));
19337c478bdstevel@tonic-gate		break;
19347c478bdstevel@tonic-gate
19357c478bdstevel@tonic-gate	case CSCardRemoved:
19367c478bdstevel@tonic-gate		args[0] = va_arg(arglist, uint32_t);
19377c478bdstevel@tonic-gate		socket = CS_GET_SOCKET_NUMBER(args[0]);
19387c478bdstevel@tonic-gate		func = CS_GET_FUNCTION_NUMBER(args[0]);
19397c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
19407c478bdstevel@tonic-gate		if (pcmcia_debug)
19417c478bdstevel@tonic-gate			cmn_err(CE_CONT,
19425c066ecJerry Gilliam			    "CSCardRemoved! (socket=%d)\n", (int)args[0]);
19437c478bdstevel@tonic-gate#endif
19447c478bdstevel@tonic-gate		if (socket >= pcmcia_num_sockets)
19457c478bdstevel@tonic-gate			break;
19467c478bdstevel@tonic-gate
19477c478bdstevel@tonic-gate		sockp = pcmcia_sockets[socket];
19487c478bdstevel@tonic-gate		if (sockp == NULL) {
19497c478bdstevel@tonic-gate			cmn_err(CE_WARN,
19507c478bdstevel@tonic-gate			    "pcmcia: bad socket = %x", socket);
19517c478bdstevel@tonic-gate			break;
19527c478bdstevel@tonic-gate		}
19537c478bdstevel@tonic-gate
195411c2b4crw		if (!(sockp->ls_flags & PCS_SUSPENDED)) {
195511c2b4crw			for (func = 0; func < sockp->ls_functions; func++) {
195611c2b4crw				/*
195711c2b4crw				 * break the association of dip and socket
195811c2b4crw				 * for all functions on that socket
195911c2b4crw				 */
196011c2b4crw				dip = sockp->ls_dip[func];
196111c2b4crw				sockp->ls_dip[func] = NULL;
196211c2b4crw				if (dip != NULL) {
196311c2b4crw					struct pcmcia_parent_private *ppd;
196411c2b4crw					ppd = (struct pcmcia_parent_private *)
196511c2b4crw					    ddi_get_parent_data(dip);
196611c2b4crw					ppd->ppd_active = 0;
196711c2b4crw					(void) ndi_devi_offline(dip,
196811c2b4crw					    NDI_DEVI_REMOVE);
196911c2b4crw
197011c2b4crw					pcmcia_ppd_free(ppd);
197111c2b4crw				}
19727c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
197311c2b4crw				else {
197411c2b4crw					if (pcmcia_debug)
197511c2b4crw						cmn_err(CE_CONT,
197611c2b4crw						    "CardRemoved: no "
197711c2b4crw						    "dip present "
197811c2b4crw						    "on socket %d!\n",
197911c2b4crw						    (int)args[0]);
198011c2b4crw				}
19817c478bdstevel@tonic-gate#endif
198211c2b4crw			}
198311c2b4crw		} else {
19847c478bdstevel@tonic-gate			mutex_enter(&pcmcia_global_lock);
19857c478bdstevel@tonic-gate			sockp->ls_flags &= ~PCS_SUSPENDED;
19867c478bdstevel@tonic-gate			cv_broadcast(&pcmcia_condvar);
19877c478bdstevel@tonic-gate			mutex_exit(&pcmcia_global_lock);
19887c478bdstevel@tonic-gate		}
19897c478bdstevel@tonic-gate		break;
19907c478bdstevel@tonic-gate
19917c478bdstevel@tonic-gate	case CSGetCookiesAndDip:
19927c478bdstevel@tonic-gate		serv = va_arg(arglist, sservice_t *);
19937c478bdstevel@tonic-gate		if (serv != NULL)
19947c478bdstevel@tonic-gate			error = GetCookiesAndDip(serv);
19957c478bdstevel@tonic-gate		else
19967c478bdstevel@tonic-gate			error = BAD_SOCKET;
19977c478bdstevel@tonic-gate		break;
19987c478bdstevel@tonic-gate
19997c478bdstevel@tonic-gate	case CSGetActiveDip:
20007c478bdstevel@tonic-gate		/*
20017c478bdstevel@tonic-gate		 * get the dip associated with the card currently
20027c478bdstevel@tonic-gate		 * in the specified socket
20037c478bdstevel@tonic-gate		 */
20047c478bdstevel@tonic-gate		args[0] = va_arg(arglist, uint32_t);
20057c478bdstevel@tonic-gate		socket = CS_GET_SOCKET_NUMBER(args[0]);
20067c478bdstevel@tonic-gate		func = CS_GET_FUNCTION_NUMBER(args[0]);
20077c478bdstevel@tonic-gate		error = (long)pcmcia_sockets[socket]->ls_dip[func];
20087c478bdstevel@tonic-gate		break;
20097c478bdstevel@tonic-gate
20107c478bdstevel@tonic-gate		/*
20117c478bdstevel@tonic-gate		 * the remaining entries are SocketServices calls
20127c478bdstevel@tonic-gate		 */
20137c478bdstevel@tonic-gate	case SS_GetAdapter:
20147c478bdstevel@tonic-gate		error = SSGetAdapter(va_arg(arglist, get_adapter_t *));
20157c478bdstevel@tonic-gate		break;
20167c478bdstevel@tonic-gate	case SS_GetPage:
20177c478bdstevel@tonic-gate		error = SSGetPage(va_arg(arglist, get_page_t *));
20187c478bdstevel@tonic-gate		break;
20197c478bdstevel@tonic-gate	case SS_GetSocket:
20207c478bdstevel@tonic-gate		error = SSGetSocket(va_arg(arglist, get_socket_t *));
20217c478bdstevel@tonic-gate		break;
20227c478bdstevel@tonic-gate	case SS_GetStatus:
20237c478bdstevel@tonic-gate		error = SSGetStatus(va_arg(arglist, get_ss_status_t *));
20247c478bdstevel@tonic-gate		break;
20257c478bdstevel@tonic-gate	case SS_GetWindow:
20267c478bdstevel@tonic-gate		error = SSGetWindow(va_arg(arglist, get_window_t *));
20277c478bdstevel@tonic-gate		break;
20287c478bdstevel@tonic-gate	case SS_InquireAdapter:
20297c478bdstevel@tonic-gate		error = SSInquireAdapter(va_arg(arglist, inquire_adapter_t *));
20307c478bdstevel@tonic-gate		break;
20317c478bdstevel@tonic-gate	case SS_InquireSocket:
20327c478bdstevel@tonic-gate		error = SSInquireSocket(va_arg(arglist, inquire_socket_t *));
20337c478bdstevel@tonic-gate		break;
20347c478bdstevel@tonic-gate	case SS_InquireWindow:
20357c478bdstevel@tonic-gate		error = SSInquireWindow(va_arg(arglist, inquire_window_t *));
20367c478bdstevel@tonic-gate		break;
20377c478bdstevel@tonic-gate	case SS_ResetSocket:
20387c478bdstevel@tonic-gate		args[0] = va_arg(arglist, uint32_t);
20397c478bdstevel@tonic-gate		args[1] = va_arg(arglist, int);
20407c478bdstevel@tonic-gate		error = SSResetSocket(args[0], args[1]);
20417c478bdstevel@tonic-gate		break;
20427c478bdstevel@tonic-gate	case SS_SetPage:
20437c478bdstevel@tonic-gate		error = SSSetPage(va_arg(arglist, set_page_t *));
20447c478bdstevel@tonic-gate		break;
20457c478bdstevel@tonic-gate	case SS_SetSocket:
20467c478bdstevel@tonic-gate		error = SSSetSocket(va_arg(arglist, set_socket_t *));
20477c478bdstevel@tonic-gate		break;
20487c478bdstevel@tonic-gate	case SS_SetWindow:
20497c478bdstevel@tonic-gate		error = SSSetWindow(va_arg(arglist, set_window_t *));
20507c478bdstevel@tonic-gate		break;
20517c478bdstevel@tonic-gate	case SS_SetIRQHandler:
20527c478bdstevel@tonic-gate		error = SSSetIRQHandler(va_arg(arglist, set_irq_handler_t *));
20537c478bdstevel@tonic-gate		break;
20547c478bdstevel@tonic-gate	case SS_ClearIRQHandler:
20557c478bdstevel@tonic-gate		error = SSClearIRQHandler(va_arg(arglist,
20567c478bdstevel@tonic-gate		    clear_irq_handler_t *));
20577c478bdstevel@tonic-gate		break;
20587c478bdstevel@tonic-gate	default:
20597c478bdstevel@tonic-gate		error = BAD_FUNCTION;
20607c478bdstevel@tonic-gate		break;
20617c478bdstevel@tonic-gate	}
20627c478bdstevel@tonic-gate	va_end(arglist);
20637c478bdstevel@tonic-gate	return (error);
20647c478bdstevel@tonic-gate}
20657c478bdstevel@tonic-gate
20667c478bdstevel@tonic-gate/*
20677c478bdstevel@tonic-gate * pcmcia_merge_power()
20687c478bdstevel@tonic-gate *	The adapters may have different power tables so it
20697c478bdstevel@tonic-gate *	is necessary to construct a single power table that
20707c478bdstevel@tonic-gate *	can be used throughout the system.  The result is
20717c478bdstevel@tonic-gate *	a merger of all capabilities.  The nexus adds
20727c478bdstevel@tonic-gate *	power table entries one at a time.
20737c478bdstevel@tonic-gate */
20747c478bdstevel@tonic-gatevoid
20757c478bdstevel@tonic-gatepcmcia_merge_power(struct power_entry *power)
20767c478bdstevel@tonic-gate{
20777c478bdstevel@tonic-gate	int i;
20787c478bdstevel@tonic-gate	struct power_entry pwr;
20797c478bdstevel@tonic-gate
20807c478bdstevel@tonic-gate	pwr = *power;
20817c478bdstevel@tonic-gate
20827c478bdstevel@tonic-gate	for (i = 0; i < pcmcia_num_power; i++) {
20837c478bdstevel@tonic-gate		if (pwr.PowerLevel == pcmcia_power_table[i].PowerLevel) {
20847c478bdstevel@tonic-gate			if (pwr.ValidSignals ==
20855c066ecJerry Gilliam			    pcmcia_power_table[i].ValidSignals) {
20867c478bdstevel@tonic-gate				return;
20877c478bdstevel@tonic-gate			} else {
20887c478bdstevel@tonic-gate				/* partial match */
20897c478bdstevel@tonic-gate				pwr.ValidSignals &=
20905c066ecJerry Gilliam				    ~pcmcia_power_table[i].ValidSignals;
20917c478bdstevel@tonic-gate			}
20927c478bdstevel@tonic-gate		}
20937c478bdstevel@tonic-gate	}
20947c478bdstevel@tonic-gate	/* what's left becomes a new entry */
20957c478bdstevel@tonic-gate	if (pcmcia_num_power == PCMCIA_MAX_POWER)
20967c478bdstevel@tonic-gate		return;
20977c478bdstevel@tonic-gate	pcmcia_power_table[pcmcia_num_power++] = pwr;
20987c478bdstevel@tonic-gate}
20997c478bdstevel@tonic-gate
21007c478bdstevel@tonic-gate/*
21017c478bdstevel@tonic-gate * pcmcia_do_suspend()
21027c478bdstevel@tonic-gate *	tell CS that a suspend has happened by passing a
21037c478bdstevel@tonic-gate *	card removal event.  Then cleanup the socket state
21047c478bdstevel@tonic-gate *	to fake the cards being removed so resume works
21057c478bdstevel@tonic-gate */
21067c478bdstevel@tonic-gatevoid
21077c478bdstevel@tonic-gatepcmcia_do_suspend(int socket, pcmcia_logical_socket_t *sockp)
21087c478bdstevel@tonic-gate{
21097c478bdstevel@tonic-gate	get_ss_status_t stat;
21107c478bdstevel@tonic-gate	struct pcmcia_adapter *adapt;
21117c478bdstevel@tonic-gate	pcmcia_if_t *ls_if;
21127c478bdstevel@tonic-gate	dev_info_t *dip;
21137c478bdstevel@tonic-gate	int i;
21147c478bdstevel@tonic-gate
21157c478bdstevel@tonic-gate#ifdef	XXX
21167c478bdstevel@tonic-gate	if (pcmcia_cs_event == NULL) {
21177c478bdstevel@tonic-gate		return;
21187c478bdstevel@tonic-gate	}
21197c478bdstevel@tonic-gate#endif
21207c478bdstevel@tonic-gate
21217c478bdstevel@tonic-gate	ls_if = sockp->ls_if;
21227c478bdstevel@tonic-gate	adapt = sockp->ls_adapter;
21237c478bdstevel@tonic-gate
21247c478bdstevel@tonic-gate	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
21257c478bdstevel@tonic-gate		return;
21267c478bdstevel@tonic-gate	}
21277c478bdstevel@tonic-gate
21287c478bdstevel@tonic-gate	stat.socket = socket;
21297c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
21307c478bdstevel@tonic-gate	if (pcmcia_debug) {
21317c478bdstevel@tonic-gate		cmn_err(CE_CONT,
21325c066ecJerry Gilliam		    "pcmcia_do_suspend(%d, %p)\n", socket, (void *)sockp);
21337c478bdstevel@tonic-gate	}
21347c478bdstevel@tonic-gate#endif
21357c478bdstevel@tonic-gate
21367c478bdstevel@tonic-gate	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) != SUCCESS)
21377c478bdstevel@tonic-gate		return;
21387c478bdstevel@tonic-gate
21397c478bdstevel@tonic-gate	/*
21407c478bdstevel@tonic-gate	 * If there is a card in the socket, then we need to send
21417c478bdstevel@tonic-gate	 *	everyone a PCE_CARD_REMOVAL event, and remove the
21427c478bdstevel@tonic-gate	 *	card active property.
21437c478bdstevel@tonic-gate	 */
21447c478bdstevel@tonic-gate
21457c478bdstevel@tonic-gate	for (i = 0; i < sockp->ls_functions; i++) {
21467c478bdstevel@tonic-gate		struct pcmcia_parent_private *ppd;
21477c478bdstevel@tonic-gate		dip = sockp->ls_dip[i];
21487c478bdstevel@tonic-gate		if (dip != NULL) {
21497c478bdstevel@tonic-gate			ppd = (struct pcmcia_parent_private *)
21505c066ecJerry Gilliam			    ddi_get_parent_data(dip);
21517c478bdstevel@tonic-gate			ppd->ppd_flags |= PPD_SUSPENDED;
21527c478bdstevel@tonic-gate		}
21537c478bdstevel@tonic-gate#if 0
21547c478bdstevel@tonic-gate		sockp->ls_dip[i] = NULL;
21557c478bdstevel@tonic-gate#endif
21567c478bdstevel@tonic-gate	}
21577c478bdstevel@tonic-gate	sockp->ls_flags |= PCS_SUSPENDED;
21587c478bdstevel@tonic-gate
21597c478bdstevel@tonic-gate	if (pcmcia_cs_event &&
21607c478bdstevel@tonic-gate	    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
21617c478bdstevel@tonic-gate		CS_EVENT(PCE_PM_SUSPEND, socket, 0);
21627c478bdstevel@tonic-gate	}
21637c478bdstevel@tonic-gate	pcm_event_manager(PCE_PM_SUSPEND, socket, NULL);
21647c478bdstevel@tonic-gate}
21657c478bdstevel@tonic-gate
21667c478bdstevel@tonic-gate/*
21677c478bdstevel@tonic-gate * pcmcia_do_resume()
21687c478bdstevel@tonic-gate *	tell CS that a suspend has happened by passing a
21697c478bdstevel@tonic-gate *	card removal event.  Then cleanup the socket state
21707c478bdstevel@tonic-gate *	to fake the cards being removed so resume works
21717c478bdstevel@tonic-gate */
21727c478bdstevel@tonic-gatevoid
21737c478bdstevel@tonic-gatepcmcia_do_resume(int socket, pcmcia_logical_socket_t *sockp)
21747c478bdstevel@tonic-gate{
21757c478bdstevel@tonic-gate	get_ss_status_t stat;
21767c478bdstevel@tonic-gate	struct pcmcia_adapter *adapt;
21777c478bdstevel@tonic-gate	pcmcia_if_t *ls_if;
21787c478bdstevel@tonic-gate
21797c478bdstevel@tonic-gate#ifdef	XXX
21807c478bdstevel@tonic-gate	if (pcmcia_cs_event == NULL) {
21817c478bdstevel@tonic-gate		return;
21827c478bdstevel@tonic-gate	}
21837c478bdstevel@tonic-gate#endif
21847c478bdstevel@tonic-gate
21857c478bdstevel@tonic-gate	ls_if = sockp->ls_if;
21867c478bdstevel@tonic-gate	adapt = sockp->ls_adapter;
21877c478bdstevel@tonic-gate
21887c478bdstevel@tonic-gate	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
21897c478bdstevel@tonic-gate		return;
21907c478bdstevel@tonic-gate	}
21917c478bdstevel@tonic-gate
21927c478bdstevel@tonic-gate	stat.socket = socket;
21937c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
21947c478bdstevel@tonic-gate	if (pcmcia_debug) {
21957c478bdstevel@tonic-gate		cmn_err(CE_CONT,
21965c066ecJerry Gilliam		    "pcmcia_do_resume(%d, %p)\n", socket, (void *)sockp);
21977c478bdstevel@tonic-gate	}
21987c478bdstevel@tonic-gate#endif
21997c478bdstevel@tonic-gate	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) ==
22007c478bdstevel@tonic-gate	    SUCCESS) {
22017c478bdstevel@tonic-gate
22027c478bdstevel@tonic-gate#if defined(PCMCIA_DEBUG)
22037c478bdstevel@tonic-gate		if (pcmcia_debug)
22047c478bdstevel@tonic-gate			cmn_err(CE_CONT, "\tsocket=%x, CardState=%x\n",
22055c066ecJerry Gilliam			    socket, stat.CardState);
22067c478bdstevel@tonic-gate#endif
22077c478bdstevel@tonic-gate#if 0
22087c478bdstevel@tonic-gate		/* now have socket info -- do we have events? */
22097c478bdstevel@tonic-gate		if ((stat.CardState & SBM_CD) == SBM_CD) {
22107c478bdstevel@tonic-gate			if (pcmcia_cs_event &&
22117c478bdstevel@tonic-gate			    (sockp->ls_cs_events & (1 << PCE_CARD_INSERT))) {
22127c478bdstevel@tonic-gate				CS_EVENT(PCE_CARD_INSERT, socket, 0);
22137c478bdstevel@tonic-gate			}
22147c478bdstevel@tonic-gate
22157c478bdstevel@tonic-gate			/* we should have card removed from CS soon */
22167c478bdstevel@tonic-gate			pcm_event_manager(PCE_CARD_INSERT, socket, NULL);
22177c478bdstevel@tonic-gate		}
22187c478bdstevel@tonic-gate#else
22197c478bdstevel@tonic-gate		if (pcmcia_cs_event &&
22207c478bdstevel@tonic-gate		    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
22217c478bdstevel@tonic-gate			CS_EVENT(PCE_PM_RESUME, socket, 0);
22227c478bdstevel@tonic-gate			CS_EVENT(PCE_CARD_REMOVAL, socket, 0);
22237c478bdstevel@tonic-gate			if ((stat.CardState & SBM_CD) == SBM_CD)
22247c478bdstevel@tonic-gate				CS_EVENT(PCE_CARD_INSERT, socket, 0);
22257c478bdstevel@tonic-gate		}
22267c478bdstevel@tonic-gate#endif
22277c478bdstevel@tonic-gate	}
22287c478bdstevel@tonic-gate}
22297c478bdstevel@tonic-gate
22307c478bdstevel@tonic-gate/*
22317c478bdstevel@tonic-gate * pcmcia_map_power_set()
22327c478bdstevel@tonic-gate *	Given a power table entry and level, find it in the
22337c478bdstevel@tonic-gate *	master table and return the index in the adapter table.
22347c478bdstevel@tonic-gate */
22357c478bdstevel@tonic-gatestatic int
22367c478bdstevel@tonic-gatepcmcia_map_power_set(struct pcmcia_adapter *adapt, int level, int which)
22377c478bdstevel@tonic-gate{
22387c478bdstevel@tonic-gate	int plevel, i;
22397c478bdstevel@tonic-gate	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
22407c478bdstevel@tonic-gate	plevel = pcmcia_power_table[level].PowerLevel;
22417c478bdstevel@tonic-gate	/* mask = pcmcia_power_table[level].ValidSignals; */
22427c478bdstevel@tonic-gate	for (i = 0; i < adapt->pca_numpower; i++)
22437c478bdstevel@tonic-gate		if (plevel == pwr[i].PowerLevel &&
22447c478bdstevel@tonic-gate		    pwr[i].ValidSignals & which)
22457c478bdstevel@tonic-gate			return (i);
22467c478bdstevel@tonic-gate	return (0);
22477c478bdstevel@tonic-gate}
22487c478bdstevel@tonic-gate
22497c478bdstevel@tonic-gate/*
22507c478bdstevel@tonic-gate * pcmcia_map_power_get()
22517c478bdstevel@tonic-gate *	Given an adapter power entry, find the appropriate index
22527c478bdstevel@tonic-gate *	in the master table.
22537c478bdstevel@tonic-gate */
22547c478bdstevel@tonic-gatestatic int
22557c478bdstevel@tonic-gatepcmcia_map_power_get(struct pcmcia_adapter *adapt, int level, int which)
22567c478bdstevel@tonic-gate{
22577c478bdstevel@tonic-gate	int plevel, i;
22587c478bdstevel@tonic-gate	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
22597c478bdstevel@tonic-gate	plevel = pwr[level].PowerLevel;
22607c478bdstevel@tonic-gate	/* mask = pwr[level].ValidSignals; */
22617c478bdstevel@tonic-gate	for (i = 0; i < pcmcia_num_power; i++)
22627c478bdstevel@tonic-gate		if (plevel == pcmcia_power_table[i].PowerLevel &&
22637c478bdstevel@tonic-gate		    pcmcia_power_table[i].ValidSignals & which)
22647c478bdstevel@tonic-gate			return (i);
22657c478bdstevel@tonic-gate	return (0);
22667c478bdstevel@tonic-gate}
22677c478bdstevel@tonic-gate
22687c478bdstevel@tonic-gate/*
22697c478bdstevel@tonic-gate * XXX - SS really needs a way to allow the caller to express
22707c478bdstevel@tonic-gate *	interest in PCE_CARD_STATUS_CHANGE events.
22717c478bdstevel@tonic-gate */
22727c478bdstevel@tonic-gatestatic uint32_t
22737c478bdstevel@tonic-gatepcm_event_map[32] = {
22747c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_WRITE_PROTECT)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22757c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_UNLOCK)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22767c478bdstevel@tonic-gate	PCE_E2M(PCE_EJECTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22777c478bdstevel@tonic-gate	PCE_E2M(PCE_INSERTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22787c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_BATTERY_WARN)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22797c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_BATTERY_DEAD)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22807c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_READY)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
22817c478bdstevel@tonic-gate	PCE_E2M(PCE_CARD_REMOVAL)|PCE_E2M(PCE_CARD_INSERT)|
22827c478bdstevel@tonic-gate					PCE_E2M(PCE_CARD_STATUS_CHANGE),
22837c478bdstevel@tonic-gate	PCE_E2M(PCE_PM_SUSPEND)|PCE_E2M(PCE_PM_RESUME),
22847c478bdstevel@tonic-gate};
22857c478bdstevel@tonic-gate
22867c478bdstevel@tonic-gatestatic int
22877c478bdstevel@tonic-gatepcm_mapevents(uint32_t eventmask)
22887c478bdstevel@tonic-gate{
22897c478bdstevel@tonic-gate	uint32_t mask;
22907c478bdstevel@tonic-gate	int i;
22917c478bdstevel@tonic-gate
22927c478bdstevel@tonic-gate	for (i = 0, mask = 0; eventmask && i < 32; i++) {
22937c478bdstevel@tonic-gate		if (eventmask & (1 << i)) {
22947c478bdstevel@tonic-gate			mask |= pcm_event_map[i];
22957c478bdstevel@tonic-gate			eventmask &= ~(1 << i);
22967c478bdstevel@tonic-gate		}
22977c478bdstevel@tonic-gate	}
22987c478bdstevel@tonic-gate	return (mask);
22997c478bdstevel@tonic-gate}
23007c478bdstevel@tonic-gate
23017c478bdstevel@tonic-gate
23027c478bdstevel@tonic-gate/*
23037c478bdstevel@tonic-gate * PCMCIA Generic Naming Support
23047c478bdstevel@tonic-gate *
23057c478bdstevel@tonic-gate * With 2.6, PCMCIA naming moves to the 1275 and generic naming model.
23067c478bdstevel@tonic-gate * Consequently, the whole naming mechanism is to be changed.  This is
23077c478bdstevel@tonic-gate * not backward compatible with the current names but that isn't a problem
23087c478bdstevel@tonic-gate * due to so few drivers existing.
23097c478bdstevel@tonic-gate *
23107c478bdstevel@tonic-gate * For cards with a device_id tuple, a generic name will be used.
23117c478bdstevel@tonic-gate * if there is no device_id, then the 1275 name will be used if possible.
23127c478bdstevel@tonic-gate * The 1275 name is of the form pccardNNNN,MMMM from the manfid tuple.
23137c478bdstevel@tonic-gate * if there is not manfid tuple, an attempt will be made to bind the
23147c478bdstevel@tonic-gate * node to the version_1 strings.
23157c478bdstevel@tonic-gate *
23167c478bdstevel@tonic-gate * In all cases, a "compatible" property is created with a number
23177c478bdstevel@tonic-gate * of names.  The most generic name will be last in the list.
23187c478bdstevel@tonic-gate */
23197c478bdstevel@tonic-gate
23207c478bdstevel@tonic-gate/*
23217c478bdstevel@tonic-gate * pcmcia_fix_string()
23227c478bdstevel@tonic-gate * want to avoid special characters in alias strings so convert
23237c478bdstevel@tonic-gate * to something innocuous
23247c478bdstevel@tonic-gate */
23257c478bdstevel@tonic-gate
23267c478bdstevel@tonic-gatevoid
23277c478bdstevel@tonic-gatepcmcia_fix_string(char *str)
23287c478bdstevel@tonic-gate{
23297c478bdstevel@tonic-gate	for (; str && *str; str++) {
23307c478bdstevel@tonic-gate		switch (*str) {
23317c478bdstevel@tonic-gate			case ' ':
23327c478bdstevel@tonic-gate			case '\t':
23337c478bdstevel@tonic-gate				*str = '_';
23347c478bdstevel@tonic-gate				break;
23357c478bdstevel@tonic-gate		}
23367c478bdstevel@tonic-gate	}
23377c478bdstevel@tonic-gate}
23387c478bdstevel@tonic-gate
23397c478bdstevel@tonic-gatevoid
23407c478bdstevel@tonic-gatepcmcia_1275_name(int socket, struct pcm_device_info *info,
23413f068ebToomas Soome    client_handle_t handle)
23427c478bdstevel@tonic-gate{
23437c478bdstevel@tonic-gate	cistpl_manfid_t manfid;
23447c478bdstevel@tonic-gate	cistpl_jedec_t jedec;
23457c478bdstevel@tonic-gate	tuple_t tuple;
23467c478bdstevel@tonic-gate	int i;
23477c478bdstevel@tonic-gate
23487c478bdstevel@tonic-gate	tuple.Socket = socket;
23497c478bdstevel@tonic-gate
23507c478bdstevel@tonic-gate	/* get MANFID if it exists -- this is most important form */
23517c478bdstevel@tonic-gate	tuple.DesiredTuple = CISTPL_MANFID;
23527c478bdstevel@tonic-gate	tuple.Attributes = 0;
23537c478bdstevel@tonic-gate	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
23547c478bdstevel@tonic-gate	    SUCCESS) {
23557c478bdstevel@tonic-gate		i = csx_Parse_CISTPL_MANFID(handle, &tuple,
23567c478bdstevel@tonic-gate		    &manfid);
23577c478bdstevel@tonic-gate		if (i == SUCCESS) {
23587c478bdstevel@tonic-gate			(void) sprintf(info->pd_bind_name, "%s%x,%x",
23595c066ecJerry Gilliam			    PCMDEV_NAMEPREF,
23605c066ecJerry Gilliam			    manfid.manf, manfid.card);
23617c478bdstevel@tonic-gate			info->pd_flags |= PCM_NAME_1275;
23627c478bdstevel@tonic-gate		}
23637c478bdstevel@tonic-gate	} else {
23647c478bdstevel@tonic-gate		tuple.Attributes = 0;
23657c478bdstevel@tonic-gate		tuple.DesiredTuple = CISTPL_JEDEC_A;
23667c478bdstevel@tonic-gate		if ((i = csx_GetFirstTuple(handle, &tuple)) ==
23677c478bdstevel@tonic-gate		    SUCCESS) {
23687c478bdstevel@tonic-gate			i = csx_Parse_CISTPL_JEDEC_A(handle, &tuple,
23697c478bdstevel@tonic-gate			    &jedec);
23707c478bdstevel@tonic-gate			if (i == SUCCESS) {
23717c478bdstevel@tonic-gate				(void) sprintf(info->pd_bind_name, "%s%x,%x",
23725c066ecJerry Gilliam				    PCMDEV_NAMEPREF,
23735c066ecJerry Gilliam				    jedec.jid[0].id, jedec.jid[0].info);
23747c478bdstevel@tonic-gate				info->pd_flags |= PCM_NAME_1275;
23757c478bdstevel@tonic-gate			}
23767c478bdstevel@tonic-gate		}
23777c478bdstevel@tonic-gate	}
23787c478bdstevel@tonic-gate}
23797c478bdstevel@tonic-gate
23807c478bdstevel@tonic-gatevoid
23817c478bdstevel@tonic-gatepcmcia_vers1_name(int socket, struct pcm_device_info *info,
2382d3d5073Rafael Vanoni    client_handle_t handle)
23837c478bdstevel@tonic-gate{
23847c478bdstevel@tonic-gate	cistpl_vers_1_t vers1;
23857c478bdstevel@tonic-gate	tuple_t tuple;
23867c478bdstevel@tonic-gate	int which = 0;
23877c478bdstevel@tonic-gate	int i, len, space;
23887c478bdstevel@tonic-gate
23897c478bdstevel@tonic-gate	tuple.Socket = socket;
23907c478bdstevel@tonic-gate	info->pd_vers1_name[0] = '\0';
23917c478bdstevel@tonic-gate
23927c478bdstevel@tonic-gate	/* Version 1 strings */
23937c478bdstevel@tonic-gate	tuple.DesiredTuple = CISTPL_VERS_1;
23947c478bdstevel@tonic-gate	tuple.Attributes = 0;
23957c478bdstevel@tonic-gate	if (!which &&
23965c066ecJerry Gilliam	    (i = csx_GetFirstTuple(handle, &tuple)) == SUCCESS) {
23977c478bdstevel@tonic-gate		i = csx_Parse_CISTPL_VERS_1(handle, &tuple, &vers1);
23987c478bdstevel@tonic-gate		if (i == SUCCESS) {
2399d3d5073Rafael Vanoni			/* BEGIN CSTYLED */
24007c478bdstevel@tonic-gate			for (i = 0, len = 0, space = 0; i < vers1.ns; i++) {
24017c478bdstevel@tonic-gate			    if ((space + len + strlen(info->pd_vers1_name)) >=
24027c478bdstevel@tonic-gate				sizeof (info->pd_vers1_name))
24037c478bdstevel@tonic-gate				    break;
24047c478bdstevel@tonic-gate			    if (space) {
24057c478bdstevel@tonic-gate				    info->pd_vers1_name[len++] = ',';
24067c478bdstevel@tonic-gate			    }
24077c478bdstevel@tonic-gate			    (void) strcpy(info->pd_vers1_name + len,
24087c478bdstevel@tonic-gate				(char *)vers1.pi[i]);
24097c478bdstevel@tonic-gate			    len += strlen((char *)vers1.pi[i]);
24107c478bdstevel@tonic-gate			    /* strip trailing spaces off of string */
24117c478bdstevel@tonic-gate			    while (info->pd_vers1_name[len - 1] == ' ' &&
24127c478bdstevel@tonic-gate				    len > 0)
24137c478bdstevel@tonic-gate				    len--;
24147c478bdstevel@tonic-gate			    space = 1;
24157c478bdstevel@tonic-gate			}
2416d3d5073Rafael Vanoni			/* END CSTYLED */
24177c478bdstevel@tonic-gate			info->pd_vers1_name[len] = '\0';
24187c478bdstevel@tonic-gate			info->pd_flags |= PCM_NAME_VERS1;
24197c478bdstevel@tonic-gate		}
24207c478bdstevel@tonic-gate	}
24217c478bdstevel@tonic-gate}
24227c478bdstevel@tonic-gate
24237c478bdstevel@tonic-gate
24247c478bdstevel@tonic-gateint
24257c478bdstevel@tonic-gatepcmcia_get_funce(client_handle_t handle, tuple_t *tuple)
24267c478bdstevel@tonic-gate{
24277c478bdstevel@tonic-gate	int ret = 0;
24287c478bdstevel@tonic-gate
24297c478bdstevel@tonic-gate	tuple->Attributes = 0;
24307c478bdstevel@tonic-gate	while (csx_GetNextTuple(handle, tuple) == SUCCESS) {
24317c478bdstevel@tonic-gate		if (tuple->TupleCode == CISTPL_FUNCID) {
24327c478bdstevel@tonic-gate			break;
24337c478bdstevel@tonic-gate		}
24347c478bdstevel@tonic-gate		if (tuple->TupleCode == CISTPL_FUNCE) {
24357c478bdstevel@tonic-gate			ret = 1;
24367c478bdstevel@tonic-gate			break;
24377c478bdstevel@tonic-gate		}
24387c478bdstevel@tonic-gate		tuple->Attributes = 0;
24397c478bdstevel@tonic-gate	}
24407c478bdstevel@tonic-gate	return (ret);
24417c478bdstevel@tonic-gate}
24427c478bdstevel@tonic-gate
24437c478bdstevel@tonic-gatechar *pcmcia_lan_types[] = {
24447c478bdstevel@tonic-gate	"arcnet",
24457c478bdstevel@tonic-gate	"ethernet",
24467c478bdstevel@tonic-gate	"token-ring",
24477c478bdstevel@tonic-gate	"localtalk",
24487c478bdstevel@tonic-gate	"fddi",
24497c478bdstevel@tonic-gate	"atm",
24507c478bdstevel@tonic-gate	"wireless",
24517c478bdstevel@tonic-gate	"reserved"
24527c478bdstevel@tonic-gate};
24537c478bdstevel@tonic-gate
24547c478bdstevel@tonic-gatevoid
24557c478bdstevel@tonic-gatepcmcia_generic_name(int socket, struct pcm_device_info *info,
24563f068ebToomas Soome    client_handle_t handle)
24577c478bdstevel@tonic-gate{
24587c478bdstevel@tonic-gate	cistpl_funcid_t funcid;
24597c478bdstevel@tonic-gate	cistpl_funce_t funce;
24607c478bdstevel@tonic-gate	tuple_t tuple;
24617c478bdstevel@tonic-gate	int which = 0;
24627c478bdstevel@tonic-gate	int i;
24637c478bdstevel@tonic-gate
24647c478bdstevel@tonic-gate	tuple.Socket = socket;
24657c478bdstevel@tonic-gate
24667c478bdstevel@tonic-gate	tuple.DesiredTuple = CISTPL_FUNCID;
24677c478bdstevel@tonic-gate	tuple.Attributes = 0;
24687c478bdstevel@tonic-gate	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
24697c478bdstevel@tonic-gate	    SUCCESS) {
24707c478bdstevel@tonic-gate		/*
24717c478bdstevel@tonic-gate		 * need to make