xref: /titanic_44/usr/src/uts/common/io/pcic.c (revision 3db86aab554edbb4244c8d1a1c90f152eee768af)
1*3db86aabSstevel /*
2*3db86aabSstevel  * CDDL HEADER START
3*3db86aabSstevel  *
4*3db86aabSstevel  * The contents of this file are subject to the terms of the
5*3db86aabSstevel  * Common Development and Distribution License (the "License").
6*3db86aabSstevel  * You may not use this file except in compliance with the License.
7*3db86aabSstevel  *
8*3db86aabSstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3db86aabSstevel  * or http://www.opensolaris.org/os/licensing.
10*3db86aabSstevel  * See the License for the specific language governing permissions
11*3db86aabSstevel  * and limitations under the License.
12*3db86aabSstevel  *
13*3db86aabSstevel  * When distributing Covered Code, include this CDDL HEADER in each
14*3db86aabSstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3db86aabSstevel  * If applicable, add the following below this CDDL HEADER, with the
16*3db86aabSstevel  * fields enclosed by brackets "[]" replaced with your own identifying
17*3db86aabSstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3db86aabSstevel  *
19*3db86aabSstevel  * CDDL HEADER END
20*3db86aabSstevel  */
21*3db86aabSstevel 
22*3db86aabSstevel /*
23*3db86aabSstevel  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*3db86aabSstevel  * Use is subject to license terms.
25*3db86aabSstevel  */
26*3db86aabSstevel 
27*3db86aabSstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*3db86aabSstevel 
29*3db86aabSstevel /*
30*3db86aabSstevel  * PCIC device/interrupt handler
31*3db86aabSstevel  *	The "pcic" driver handles the Intel 82365SL, Cirrus Logic
32*3db86aabSstevel  *	and Toshiba (and possibly other clones) PCMCIA adapter chip
33*3db86aabSstevel  *	sets.  It implements a subset of Socket Services as defined
34*3db86aabSstevel  *	in the Solaris PCMCIA design documents
35*3db86aabSstevel  */
36*3db86aabSstevel 
37*3db86aabSstevel /*
38*3db86aabSstevel  * currently defined "properties"
39*3db86aabSstevel  *
40*3db86aabSstevel  * clock-frequency		bus clock frequency
41*3db86aabSstevel  * smi				system management interrupt override
42*3db86aabSstevel  * need-mult-irq		need status IRQ for each pair of sockets
43*3db86aabSstevel  * disable-audio		don't route audio signal to speaker
44*3db86aabSstevel  */
45*3db86aabSstevel 
46*3db86aabSstevel 
47*3db86aabSstevel #include <sys/types.h>
48*3db86aabSstevel #include <sys/inttypes.h>
49*3db86aabSstevel #include <sys/param.h>
50*3db86aabSstevel #include <sys/systm.h>
51*3db86aabSstevel #include <sys/user.h>
52*3db86aabSstevel #include <sys/buf.h>
53*3db86aabSstevel #include <sys/file.h>
54*3db86aabSstevel #include <sys/uio.h>
55*3db86aabSstevel #include <sys/conf.h>
56*3db86aabSstevel #include <sys/stat.h>
57*3db86aabSstevel #include <sys/autoconf.h>
58*3db86aabSstevel #include <sys/vtoc.h>
59*3db86aabSstevel #include <sys/dkio.h>
60*3db86aabSstevel #include <sys/ddi.h>
61*3db86aabSstevel #include <sys/sunddi.h>
62*3db86aabSstevel #include <sys/sunndi.h>
63*3db86aabSstevel #include <sys/var.h>
64*3db86aabSstevel #include <sys/callb.h>
65*3db86aabSstevel #include <sys/open.h>
66*3db86aabSstevel #include <sys/ddidmareq.h>
67*3db86aabSstevel #include <sys/dma_engine.h>
68*3db86aabSstevel #include <sys/kstat.h>
69*3db86aabSstevel #include <sys/kmem.h>
70*3db86aabSstevel #include <sys/modctl.h>
71*3db86aabSstevel #include <sys/pci.h>
72*3db86aabSstevel #include <sys/pci_impl.h>
73*3db86aabSstevel 
74*3db86aabSstevel #include <sys/pctypes.h>
75*3db86aabSstevel #include <sys/pcmcia.h>
76*3db86aabSstevel #include <sys/sservice.h>
77*3db86aabSstevel 
78*3db86aabSstevel #include <sys/note.h>
79*3db86aabSstevel 
80*3db86aabSstevel #include <sys/pcic_reg.h>
81*3db86aabSstevel #include <sys/pcic_var.h>
82*3db86aabSstevel 
83*3db86aabSstevel #if defined(__sparc)
84*3db86aabSstevel #include <sys/pci/pci_nexus.h>
85*3db86aabSstevel #endif
86*3db86aabSstevel 
87*3db86aabSstevel #include <sys/syshw.h>
88*3db86aabSstevel #include "cardbus/cardbus.h"
89*3db86aabSstevel 
90*3db86aabSstevel #define	SOFTC_SIZE	(sizeof (anp_t))
91*3db86aabSstevel 
92*3db86aabSstevel static int pcic_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
93*3db86aabSstevel static int pcic_attach(dev_info_t *, ddi_attach_cmd_t);
94*3db86aabSstevel static int pcic_detach(dev_info_t *, ddi_detach_cmd_t);
95*3db86aabSstevel static uint_t pcic_intr(caddr_t, caddr_t);
96*3db86aabSstevel static int pcic_do_io_intr(pcicdev_t *, uint32_t);
97*3db86aabSstevel static int pcic_probe(dev_info_t *);
98*3db86aabSstevel 
99*3db86aabSstevel static int pcic_open(dev_t *, int, int, cred_t *);
100*3db86aabSstevel static int pcic_close(dev_t, int, int, cred_t *);
101*3db86aabSstevel static int pcic_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
102*3db86aabSstevel 
103*3db86aabSstevel typedef struct pcm_regs pcm_regs_t;
104*3db86aabSstevel 
105*3db86aabSstevel static void pcic_init_assigned(dev_info_t *);
106*3db86aabSstevel static int pcic_apply_avail_ranges(dev_info_t *, pcm_regs_t *,
107*3db86aabSstevel 	pci_regspec_t *, int);
108*3db86aabSstevel int pci_resource_setup_avail(dev_info_t *, pci_regspec_t *, int);
109*3db86aabSstevel 
110*3db86aabSstevel /*
111*3db86aabSstevel  * On x86 platforms the ddi_iobp_alloc(9F) and ddi_mem_alloc(9F) calls
112*3db86aabSstevel  * are xlated into DMA ctlops. To make this nexus work on x86, we
113*3db86aabSstevel  * need to have the default ddi_dma_mctl ctlops in the bus_ops
114*3db86aabSstevel  * structure, just to pass the request to the parent. The correct
115*3db86aabSstevel  * ctlops should be ddi_no_dma_mctl because so far we don't do DMA.
116*3db86aabSstevel  */
117*3db86aabSstevel static
118*3db86aabSstevel struct bus_ops pcmciabus_ops = {
119*3db86aabSstevel 	BUSO_REV,
120*3db86aabSstevel 	pcmcia_bus_map,
121*3db86aabSstevel 	NULL,
122*3db86aabSstevel 	NULL,
123*3db86aabSstevel 	NULL,
124*3db86aabSstevel 	i_ddi_map_fault,
125*3db86aabSstevel 	ddi_no_dma_map,
126*3db86aabSstevel 	ddi_no_dma_allochdl,
127*3db86aabSstevel 	ddi_no_dma_freehdl,
128*3db86aabSstevel 	ddi_no_dma_bindhdl,
129*3db86aabSstevel 	ddi_no_dma_unbindhdl,
130*3db86aabSstevel 	ddi_no_dma_flush,
131*3db86aabSstevel 	ddi_no_dma_win,
132*3db86aabSstevel 	ddi_dma_mctl,
133*3db86aabSstevel 	pcmcia_ctlops,
134*3db86aabSstevel 	pcmcia_prop_op,
135*3db86aabSstevel 	NULL,				/* (*bus_get_eventcookie)();	*/
136*3db86aabSstevel 	NULL,				/* (*bus_add_eventcall)();	*/
137*3db86aabSstevel 	NULL,				/* (*bus_remove_eventcall)();	*/
138*3db86aabSstevel 	NULL,				/* (*bus_post_event)();		*/
139*3db86aabSstevel 	NULL,				/* (*bus_intr_ctl)();		*/
140*3db86aabSstevel 	NULL,				/* (*bus_config)(); 		*/
141*3db86aabSstevel 	NULL,				/* (*bus_unconfig)(); 		*/
142*3db86aabSstevel 	NULL,				/* (*bus_fm_init)(); 		*/
143*3db86aabSstevel 	NULL,				/* (*bus_fm_fini)(); 		*/
144*3db86aabSstevel 	NULL,				/* (*bus_enter)()		*/
145*3db86aabSstevel 	NULL,				/* (*bus_exit)()		*/
146*3db86aabSstevel 	NULL,				/* (*bus_power)()		*/
147*3db86aabSstevel 	pcmcia_intr_ops			/* (*bus_intr_op)(); 		*/
148*3db86aabSstevel };
149*3db86aabSstevel 
150*3db86aabSstevel static struct cb_ops pcic_cbops = {
151*3db86aabSstevel 	pcic_open,
152*3db86aabSstevel 	pcic_close,
153*3db86aabSstevel 	nodev,
154*3db86aabSstevel 	nodev,
155*3db86aabSstevel 	nodev,
156*3db86aabSstevel 	nodev,
157*3db86aabSstevel 	nodev,
158*3db86aabSstevel 	pcic_ioctl,
159*3db86aabSstevel 	nodev,
160*3db86aabSstevel 	nodev,
161*3db86aabSstevel 	nodev,
162*3db86aabSstevel 	nochpoll,
163*3db86aabSstevel 	ddi_prop_op,
164*3db86aabSstevel 	NULL,
165*3db86aabSstevel #ifdef CARDBUS
166*3db86aabSstevel 	D_NEW | D_MP | D_HOTPLUG
167*3db86aabSstevel #else
168*3db86aabSstevel 	D_NEW | D_MP
169*3db86aabSstevel #endif
170*3db86aabSstevel };
171*3db86aabSstevel 
172*3db86aabSstevel static struct dev_ops pcic_devops = {
173*3db86aabSstevel 	DEVO_REV,
174*3db86aabSstevel 	0,
175*3db86aabSstevel 	pcic_getinfo,
176*3db86aabSstevel 	nulldev,
177*3db86aabSstevel 	pcic_probe,
178*3db86aabSstevel 	pcic_attach,
179*3db86aabSstevel 	pcic_detach,
180*3db86aabSstevel 	nulldev,
181*3db86aabSstevel 	&pcic_cbops,
182*3db86aabSstevel 	&pcmciabus_ops,
183*3db86aabSstevel 	NULL
184*3db86aabSstevel };
185*3db86aabSstevel 
186*3db86aabSstevel void *pcic_soft_state_p = NULL;
187*3db86aabSstevel static int pcic_maxinst = -1;
188*3db86aabSstevel static timeout_id_t pcic_delayed_resume_toid;
189*3db86aabSstevel 
190*3db86aabSstevel int pcic_do_insertion = 1;
191*3db86aabSstevel int pcic_do_removal = 1;
192*3db86aabSstevel 
193*3db86aabSstevel struct irqmap {
194*3db86aabSstevel 	int irq;
195*3db86aabSstevel 	int count;
196*3db86aabSstevel } pcic_irq_map[16];
197*3db86aabSstevel 
198*3db86aabSstevel 
199*3db86aabSstevel int pcic_debug = 0x0;
200*3db86aabSstevel static  void    pcic_err(dev_info_t *dip, int level, const char *fmt, ...);
201*3db86aabSstevel extern void cardbus_dump_pci_config(dev_info_t *dip);
202*3db86aabSstevel extern void cardbus_dump_socket(dev_info_t *dip);
203*3db86aabSstevel extern int cardbus_validate_iline(dev_info_t *dip, ddi_acc_handle_t handle);
204*3db86aabSstevel static void pcic_dump_debqueue(char *msg);
205*3db86aabSstevel 
206*3db86aabSstevel #if defined(PCIC_DEBUG)
207*3db86aabSstevel static void xxdmp_all_regs(pcicdev_t *, int, uint32_t);
208*3db86aabSstevel 
209*3db86aabSstevel #define	pcic_mutex_enter(a)	\
210*3db86aabSstevel 	{ \
211*3db86aabSstevel 		pcic_err(NULL, 10, "Set lock at %d\n", __LINE__); \
212*3db86aabSstevel 		mutex_enter(a); \
213*3db86aabSstevel 	};
214*3db86aabSstevel 
215*3db86aabSstevel #define	pcic_mutex_exit(a)	\
216*3db86aabSstevel 	{ \
217*3db86aabSstevel 		pcic_err(NULL, 10, "Clear lock at %d\n", __LINE__); \
218*3db86aabSstevel 		mutex_exit(a); \
219*3db86aabSstevel 	};
220*3db86aabSstevel 
221*3db86aabSstevel #else
222*3db86aabSstevel #define	pcic_mutex_enter(a)	mutex_enter(a)
223*3db86aabSstevel #define	pcic_mutex_exit(a)	mutex_exit(a)
224*3db86aabSstevel #endif
225*3db86aabSstevel 
226*3db86aabSstevel #define	PCIC_VCC_3VLEVEL	1
227*3db86aabSstevel #define	PCIC_VCC_5VLEVEL	2
228*3db86aabSstevel #define	PCIC_VCC_12LEVEL	3
229*3db86aabSstevel 
230*3db86aabSstevel /* bit patterns to select voltage levels */
231*3db86aabSstevel int pcic_vpp_levels[13] = {
232*3db86aabSstevel 	0, 0, 0,
233*3db86aabSstevel 	1,	/* 3.3V */
234*3db86aabSstevel 	0,
235*3db86aabSstevel 	1,	/* 5V */
236*3db86aabSstevel 	0, 0, 0, 0, 0, 0,
237*3db86aabSstevel 	2	/* 12V */
238*3db86aabSstevel };
239*3db86aabSstevel 
240*3db86aabSstevel uint8_t pcic_cbv_levels[13] = {
241*3db86aabSstevel 	0, 0, 0,
242*3db86aabSstevel 	3,			/* 3.3V */
243*3db86aabSstevel 	0,
244*3db86aabSstevel 	2,			/* 5V */
245*3db86aabSstevel 	0, 0, 0, 0, 0, 0,
246*3db86aabSstevel 	1			/* 12V */
247*3db86aabSstevel };
248*3db86aabSstevel 
249*3db86aabSstevel struct power_entry pcic_power[4] = {
250*3db86aabSstevel 	{
251*3db86aabSstevel 		0, VCC|VPP1|VPP2
252*3db86aabSstevel 	},
253*3db86aabSstevel 	{
254*3db86aabSstevel 		33,		/* 3.3Volt */
255*3db86aabSstevel 		VCC|VPP1|VPP2
256*3db86aabSstevel 	},
257*3db86aabSstevel 	{
258*3db86aabSstevel 		5*10,		/* 5Volt */
259*3db86aabSstevel 		VCC|VPP1|VPP2	/* currently only know about this */
260*3db86aabSstevel 	},
261*3db86aabSstevel 	{
262*3db86aabSstevel 		12*10,		/* 12Volt */
263*3db86aabSstevel 		VPP1|VPP2
264*3db86aabSstevel 	}
265*3db86aabSstevel };
266*3db86aabSstevel 
267*3db86aabSstevel /*
268*3db86aabSstevel  * Base used to allocate ranges of PCI memory on x86 systems
269*3db86aabSstevel  * Each instance gets a chunk above the base that is used to map
270*3db86aabSstevel  * in the memory and I/O windows for that device.
271*3db86aabSstevel  * Pages below the base are also allocated for the EXCA registers,
272*3db86aabSstevel  * one per instance.
273*3db86aabSstevel  */
274*3db86aabSstevel #define	PCIC_PCI_MEMCHUNK	0x1000000
275*3db86aabSstevel 
276*3db86aabSstevel static int pcic_wait_insert_time = 5000000;	/* In micro-seconds */
277*3db86aabSstevel static int pcic_debounce_time = 200000; /* In micro-seconds */
278*3db86aabSstevel 
279*3db86aabSstevel struct debounce {
280*3db86aabSstevel 	pcic_socket_t *pcs;
281*3db86aabSstevel 	clock_t expire;
282*3db86aabSstevel 	struct debounce *next;
283*3db86aabSstevel };
284*3db86aabSstevel 
285*3db86aabSstevel static syshw_t pcic_syshw = {
286*3db86aabSstevel 	0, "PC Card Socket 0", SH_CONNECTION,
287*3db86aabSstevel 	SYSHW_CAN_SIGNAL_CHANGE|SYSHW_STATE_VALID|SYSHW_VAL0_VALID,
288*3db86aabSstevel 	B_FALSE, {2, 0, 0, 0}
289*3db86aabSstevel };
290*3db86aabSstevel 
291*3db86aabSstevel static struct debounce *pcic_deb_queue = NULL;
292*3db86aabSstevel static kmutex_t pcic_deb_mtx;
293*3db86aabSstevel static kcondvar_t pcic_deb_cv;
294*3db86aabSstevel static kthread_t *pcic_deb_threadid;
295*3db86aabSstevel 
296*3db86aabSstevel static inthandler_t *pcic_handlers;
297*3db86aabSstevel 
298*3db86aabSstevel static void pcic_setup_adapter(pcicdev_t *);
299*3db86aabSstevel static int pcic_change(pcicdev_t *, int);
300*3db86aabSstevel static int pcic_ll_reset(pcicdev_t *, int);
301*3db86aabSstevel static void pcic_mswait(pcicdev_t *, int, int);
302*3db86aabSstevel static boolean_t pcic_check_ready(pcicdev_t *, int);
303*3db86aabSstevel static void pcic_set_cdtimers(pcicdev_t *, int, uint32_t, int);
304*3db86aabSstevel static void pcic_ready_wait(pcicdev_t *, int);
305*3db86aabSstevel extern int pcmcia_get_intr(dev_info_t *, int);
306*3db86aabSstevel extern int pcmcia_return_intr(dev_info_t *, int);
307*3db86aabSstevel 
308*3db86aabSstevel static int pcic_callback(dev_info_t *, int (*)(), int);
309*3db86aabSstevel static int pcic_inquire_adapter(dev_info_t *, inquire_adapter_t *);
310*3db86aabSstevel static int pcic_get_adapter(dev_info_t *, get_adapter_t *);
311*3db86aabSstevel static int pcic_get_page(dev_info_t *, get_page_t *);
312*3db86aabSstevel static int pcic_get_socket(dev_info_t *, get_socket_t *);
313*3db86aabSstevel static int pcic_get_status(dev_info_t *, get_ss_status_t *);
314*3db86aabSstevel static int pcic_get_window(dev_info_t *, get_window_t *);
315*3db86aabSstevel static int pcic_inquire_socket(dev_info_t *, inquire_socket_t *);
316*3db86aabSstevel static int pcic_inquire_window(dev_info_t *, inquire_window_t *);
317*3db86aabSstevel static int pcic_reset_socket(dev_info_t *, int, int);
318*3db86aabSstevel static int pcic_set_page(dev_info_t *, set_page_t *);
319*3db86aabSstevel static int pcic_set_window(dev_info_t *, set_window_t *);
320*3db86aabSstevel static int pcic_set_socket(dev_info_t *, set_socket_t *);
321*3db86aabSstevel static int pcic_set_interrupt(dev_info_t *, set_irq_handler_t *);
322*3db86aabSstevel static int pcic_clear_interrupt(dev_info_t *, clear_irq_handler_t *);
323*3db86aabSstevel static void pcic_pm_detection(void *);
324*3db86aabSstevel static void pcic_iomem_pci_ctl(ddi_acc_handle_t, uchar_t *, unsigned);
325*3db86aabSstevel static int clext_reg_read(pcicdev_t *, int, uchar_t);
326*3db86aabSstevel static void clext_reg_write(pcicdev_t *, int, uchar_t, uchar_t);
327*3db86aabSstevel static int pcic_calc_speed(pcicdev_t *, uint32_t);
328*3db86aabSstevel static int pcic_card_state(pcicdev_t *, pcic_socket_t *);
329*3db86aabSstevel static int pcic_find_pci_type(pcicdev_t *);
330*3db86aabSstevel static void pcic_82092_smiirq_ctl(pcicdev_t *, int, int, int);
331*3db86aabSstevel static void pcic_handle_cd_change(pcicdev_t *, pcic_socket_t *, uint8_t);
332*3db86aabSstevel static uint_t pcic_cd_softint(caddr_t, caddr_t);
333*3db86aabSstevel static uint8_t pcic_getb(pcicdev_t *, int, int);
334*3db86aabSstevel static void pcic_putb(pcicdev_t *, int, int, int8_t);
335*3db86aabSstevel static int pcic_set_vcc_level(pcicdev_t *, set_socket_t *);
336*3db86aabSstevel static uint_t pcic_softintr(caddr_t, caddr_t);
337*3db86aabSstevel 
338*3db86aabSstevel static void pcic_debounce(pcic_socket_t *);
339*3db86aabSstevel static void pcic_delayed_resume(void *);
340*3db86aabSstevel static void *pcic_add_debqueue(pcic_socket_t *, int);
341*3db86aabSstevel static void pcic_rm_debqueue(void *);
342*3db86aabSstevel static void pcic_deb_thread();
343*3db86aabSstevel 
344*3db86aabSstevel static boolean_t pcic_load_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp);
345*3db86aabSstevel static void pcic_unload_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp);
346*3db86aabSstevel static uint32_t pcic_getcb(pcicdev_t *pcic, int reg);
347*3db86aabSstevel static void pcic_putcb(pcicdev_t *pcic, int reg, uint32_t value);
348*3db86aabSstevel static void pcic_cb_enable_intr(dev_info_t *);
349*3db86aabSstevel static void pcic_cb_disable_intr(dev_info_t *);
350*3db86aabSstevel static void pcic_enable_io_intr(pcicdev_t *pcic, int socket, int irq);
351*3db86aabSstevel static void pcic_disable_io_intr(pcicdev_t *pcic, int socket);
352*3db86aabSstevel 
353*3db86aabSstevel static cb_nexus_cb_t pcic_cbnexus_ops = {
354*3db86aabSstevel 	pcic_cb_enable_intr,
355*3db86aabSstevel 	pcic_cb_disable_intr
356*3db86aabSstevel };
357*3db86aabSstevel 
358*3db86aabSstevel static int pcic_exca_powerctl(pcicdev_t *pcic, int socket, int powerlevel);
359*3db86aabSstevel static int pcic_cbus_powerctl(pcicdev_t *pcic, int socket);
360*3db86aabSstevel 
361*3db86aabSstevel static void pcic_syshw_cardstate(syshw_t *, void *);
362*3db86aabSstevel 
363*3db86aabSstevel #if defined(__sparc)
364*3db86aabSstevel static int pcic_fault(enum pci_fault_ops op, void *arg);
365*3db86aabSstevel #endif
366*3db86aabSstevel 
367*3db86aabSstevel /*
368*3db86aabSstevel  * Default to support for Voyager IIi if sparc is defined.
369*3db86aabSstevel  * Appart from the PCI base addresses this only effect the TI1250.
370*3db86aabSstevel  */
371*3db86aabSstevel #if defined(sparc)
372*3db86aabSstevel #define	VOYAGER
373*3db86aabSstevel #endif
374*3db86aabSstevel 
375*3db86aabSstevel 
376*3db86aabSstevel /*
377*3db86aabSstevel  * pcmcia_attach() uses 0 and 128 upwards for the initpcmcia and devctl
378*3db86aabSstevel  * interfaces so we use 254.
379*3db86aabSstevel  */
380*3db86aabSstevel #define	SYSHW_MINOR	254
381*3db86aabSstevel 
382*3db86aabSstevel /*
383*3db86aabSstevel  * Forward declarations for syshw interface (See end of file).
384*3db86aabSstevel  */
385*3db86aabSstevel static void syshw_attach(pcicdev_t *);
386*3db86aabSstevel static void syshw_detach(pcicdev_t *);
387*3db86aabSstevel static void syshw_resume(pcicdev_t *);
388*3db86aabSstevel 
389*3db86aabSstevel #ifdef VOYAGER
390*3db86aabSstevel static uint_t syshw_intr(caddr_t);
391*3db86aabSstevel static uint_t syshw_intr_hi(pcicdev_t *);
392*3db86aabSstevel #endif
393*3db86aabSstevel 
394*3db86aabSstevel static int syshw_open(dev_t *, int, int, cred_t *);
395*3db86aabSstevel static int syshw_close(dev_t, int, int, cred_t *);
396*3db86aabSstevel static int syshw_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
397*3db86aabSstevel static uint32_t syshw_add2map(syshw_t *, void (*)(syshw_t *, void *), void *);
398*3db86aabSstevel static void syshw_send_signal(int);
399*3db86aabSstevel 
400*3db86aabSstevel /*
401*3db86aabSstevel  * pcmcia interface operations structure
402*3db86aabSstevel  * this is the private interface that is exported to the nexus
403*3db86aabSstevel  */
404*3db86aabSstevel pcmcia_if_t pcic_if_ops = {
405*3db86aabSstevel 	PCIF_MAGIC,
406*3db86aabSstevel 	PCIF_VERSION,
407*3db86aabSstevel 	pcic_callback,
408*3db86aabSstevel 	pcic_get_adapter,
409*3db86aabSstevel 	pcic_get_page,
410*3db86aabSstevel 	pcic_get_socket,
411*3db86aabSstevel 	pcic_get_status,
412*3db86aabSstevel 	pcic_get_window,
413*3db86aabSstevel 	pcic_inquire_adapter,
414*3db86aabSstevel 	pcic_inquire_socket,
415*3db86aabSstevel 	pcic_inquire_window,
416*3db86aabSstevel 	pcic_reset_socket,
417*3db86aabSstevel 	pcic_set_page,
418*3db86aabSstevel 	pcic_set_window,
419*3db86aabSstevel 	pcic_set_socket,
420*3db86aabSstevel 	pcic_set_interrupt,
421*3db86aabSstevel 	pcic_clear_interrupt,
422*3db86aabSstevel 	NULL,
423*3db86aabSstevel };
424*3db86aabSstevel 
425*3db86aabSstevel /*
426*3db86aabSstevel  * chip type identification routines
427*3db86aabSstevel  * this list of functions is searched until one of them succeeds
428*3db86aabSstevel  * or all fail.  i82365SL is assumed if failed.
429*3db86aabSstevel  */
430*3db86aabSstevel static int pcic_ci_cirrus(pcicdev_t *);
431*3db86aabSstevel static int pcic_ci_vadem(pcicdev_t *);
432*3db86aabSstevel static int pcic_ci_ricoh(pcicdev_t *);
433*3db86aabSstevel 
434*3db86aabSstevel int (*pcic_ci_funcs[])(pcicdev_t *) = {
435*3db86aabSstevel 	pcic_ci_cirrus,
436*3db86aabSstevel 	pcic_ci_vadem,
437*3db86aabSstevel 	pcic_ci_ricoh,
438*3db86aabSstevel 	NULL
439*3db86aabSstevel };
440*3db86aabSstevel 
441*3db86aabSstevel static struct modldrv modldrv = {
442*3db86aabSstevel 	&mod_driverops,		/* Type of module. This one is a driver */
443*3db86aabSstevel 	"PCIC PCMCIA adapter driver %I%",	/* Name of the module. */
444*3db86aabSstevel 	&pcic_devops,		/* driver ops */
445*3db86aabSstevel };
446*3db86aabSstevel 
447*3db86aabSstevel static struct modlinkage modlinkage = {
448*3db86aabSstevel 	MODREV_1, (void *)&modldrv, NULL
449*3db86aabSstevel };
450*3db86aabSstevel 
451*3db86aabSstevel int
452*3db86aabSstevel _init()
453*3db86aabSstevel {
454*3db86aabSstevel 	int stat;
455*3db86aabSstevel 
456*3db86aabSstevel 	/* Allocate soft state */
457*3db86aabSstevel 	if ((stat = ddi_soft_state_init(&pcic_soft_state_p,
458*3db86aabSstevel 	    SOFTC_SIZE, 2)) != DDI_SUCCESS)
459*3db86aabSstevel 		return (stat);
460*3db86aabSstevel 
461*3db86aabSstevel 	if ((stat = mod_install(&modlinkage)) != 0)
462*3db86aabSstevel 		ddi_soft_state_fini(&pcic_soft_state_p);
463*3db86aabSstevel 
464*3db86aabSstevel 	return (stat);
465*3db86aabSstevel }
466*3db86aabSstevel 
467*3db86aabSstevel int
468*3db86aabSstevel _fini()
469*3db86aabSstevel {
470*3db86aabSstevel 	int stat = 0;
471*3db86aabSstevel 
472*3db86aabSstevel 	if ((stat = mod_remove(&modlinkage)) != 0)
473*3db86aabSstevel 		return (stat);
474*3db86aabSstevel 
475*3db86aabSstevel 	if (pcic_deb_threadid) {
476*3db86aabSstevel 		mutex_enter(&pcic_deb_mtx);
477*3db86aabSstevel 		pcic_deb_threadid = 0;
478*3db86aabSstevel 		while (!pcic_deb_threadid)
479*3db86aabSstevel 			cv_wait(&pcic_deb_cv, &pcic_deb_mtx);
480*3db86aabSstevel 		pcic_deb_threadid = 0;
481*3db86aabSstevel 		mutex_exit(&pcic_deb_mtx);
482*3db86aabSstevel 
483*3db86aabSstevel 		mutex_destroy(&pcic_deb_mtx);
484*3db86aabSstevel 		cv_destroy(&pcic_deb_cv);
485*3db86aabSstevel 	}
486*3db86aabSstevel 
487*3db86aabSstevel 	ddi_soft_state_fini(&pcic_soft_state_p);
488*3db86aabSstevel 
489*3db86aabSstevel 	return (stat);
490*3db86aabSstevel }
491*3db86aabSstevel 
492*3db86aabSstevel int
493*3db86aabSstevel _info(struct modinfo *modinfop)
494*3db86aabSstevel {
495*3db86aabSstevel 	return (mod_info(&modlinkage, modinfop));
496*3db86aabSstevel }
497*3db86aabSstevel 
498*3db86aabSstevel /*
499*3db86aabSstevel  * pcic_getinfo()
500*3db86aabSstevel  *	provide instance/device information about driver
501*3db86aabSstevel  */
502*3db86aabSstevel /*ARGSUSED*/
503*3db86aabSstevel static int
504*3db86aabSstevel pcic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
505*3db86aabSstevel {
506*3db86aabSstevel 	anp_t *anp;
507*3db86aabSstevel 	int error = DDI_SUCCESS;
508*3db86aabSstevel 	minor_t minor;
509*3db86aabSstevel 
510*3db86aabSstevel 	switch (cmd) {
511*3db86aabSstevel 	    case DDI_INFO_DEVT2DEVINFO:
512*3db86aabSstevel 		minor = getminor((dev_t)arg);
513*3db86aabSstevel 		if (minor == SYSHW_MINOR)
514*3db86aabSstevel 			minor = 0;
515*3db86aabSstevel 		else
516*3db86aabSstevel 			minor &= 0x7f;
517*3db86aabSstevel 		if (!(anp = ddi_get_soft_state(pcic_soft_state_p, minor)))
518*3db86aabSstevel 			*result = NULL;
519*3db86aabSstevel 		else
520*3db86aabSstevel 			*result = anp->an_dip;
521*3db86aabSstevel 		break;
522*3db86aabSstevel 	    case DDI_INFO_DEVT2INSTANCE:
523*3db86aabSstevel 		minor = getminor((dev_t)arg);
524*3db86aabSstevel 		if (minor == SYSHW_MINOR)
525*3db86aabSstevel 			minor = 0;
526*3db86aabSstevel 		else
527*3db86aabSstevel 			minor &= 0x7f;
528*3db86aabSstevel 		*result = (void *)((long)minor);
529*3db86aabSstevel 		break;
530*3db86aabSstevel 	    default:
531*3db86aabSstevel 		error = DDI_FAILURE;
532*3db86aabSstevel 		break;
533*3db86aabSstevel 	}
534*3db86aabSstevel 	return (error);
535*3db86aabSstevel }
536*3db86aabSstevel 
537*3db86aabSstevel static int
538*3db86aabSstevel pcic_probe(dev_info_t *dip)
539*3db86aabSstevel {
540*3db86aabSstevel 	int value;
541*3db86aabSstevel 	ddi_device_acc_attr_t attr;
542*3db86aabSstevel 	ddi_acc_handle_t handle;
543*3db86aabSstevel 	uchar_t *index, *data;
544*3db86aabSstevel 
545*3db86aabSstevel 	if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
546*3db86aabSstevel 	    return (DDI_PROBE_DONTCARE);
547*3db86aabSstevel 
548*3db86aabSstevel 	/*
549*3db86aabSstevel 	 * find a PCIC device (any vendor)
550*3db86aabSstevel 	 * while there can be up to 4 such devices in
551*3db86aabSstevel 	 * a system, we currently only look for 1
552*3db86aabSstevel 	 * per probe.  There will be up to 2 chips per
553*3db86aabSstevel 	 * instance since they share I/O space
554*3db86aabSstevel 	 */
555*3db86aabSstevel 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
556*3db86aabSstevel 	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
557*3db86aabSstevel 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
558*3db86aabSstevel 
559*3db86aabSstevel 	if (ddi_regs_map_setup(dip, PCIC_ISA_CONTROL_REG_NUM,
560*3db86aabSstevel 				(caddr_t *)&index,
561*3db86aabSstevel 				PCIC_ISA_CONTROL_REG_OFFSET,
562*3db86aabSstevel 				PCIC_ISA_CONTROL_REG_LENGTH,
563*3db86aabSstevel 				&attr, &handle) != DDI_SUCCESS)
564*3db86aabSstevel 	    return (DDI_PROBE_FAILURE);
565*3db86aabSstevel 
566*3db86aabSstevel 	data = index + 1;
567*3db86aabSstevel 
568*3db86aabSstevel #if defined(PCIC_DEBUG)
569*3db86aabSstevel 	if (pcic_debug)
570*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_probe: entered\n");
571*3db86aabSstevel 	if (pcic_debug)
572*3db86aabSstevel 		cmn_err(CE_CONT, "\tindex=%p\n", (void *)index);
573*3db86aabSstevel #endif
574*3db86aabSstevel 	ddi_put8(handle, index, PCIC_CHIP_REVISION);
575*3db86aabSstevel 	ddi_put8(handle, data, 0);
576*3db86aabSstevel 	value = ddi_get8(handle, data);
577*3db86aabSstevel #if defined(PCIC_DEBUG)
578*3db86aabSstevel 	if (pcic_debug)
579*3db86aabSstevel 		cmn_err(CE_CONT, "\tchip revision register = %x\n", value);
580*3db86aabSstevel #endif
581*3db86aabSstevel 	if ((value & PCIC_REV_MASK) >= PCIC_REV_LEVEL_LOW &&
582*3db86aabSstevel 	    (value & 0x30) == 0) {
583*3db86aabSstevel 		/*
584*3db86aabSstevel 		 * we probably have a PCIC chip in the system
585*3db86aabSstevel 		 * do a little more checking.  If we find one,
586*3db86aabSstevel 		 * reset everything in case of softboot
587*3db86aabSstevel 		 */
588*3db86aabSstevel 		ddi_put8(handle, index, PCIC_MAPPING_ENABLE);
589*3db86aabSstevel 		ddi_put8(handle, data, 0);
590*3db86aabSstevel 		value = ddi_get8(handle, data);
591*3db86aabSstevel #if defined(PCIC_DEBUG)
592*3db86aabSstevel 		if (pcic_debug)
593*3db86aabSstevel 			cmn_err(CE_CONT, "\tzero test = %x\n", value);
594*3db86aabSstevel #endif
595*3db86aabSstevel 		/* should read back as zero */
596*3db86aabSstevel 		if (value == 0) {
597*3db86aabSstevel 			/*
598*3db86aabSstevel 			 * we do have one and it is off the bus
599*3db86aabSstevel 			 */
600*3db86aabSstevel #if defined(PCIC_DEBUG)
601*3db86aabSstevel 			if (pcic_debug)
602*3db86aabSstevel 				cmn_err(CE_CONT, "pcic_probe: success\n");
603*3db86aabSstevel #endif
604*3db86aabSstevel 			ddi_regs_map_free(&handle);
605*3db86aabSstevel 			return (DDI_PROBE_SUCCESS);
606*3db86aabSstevel 		}
607*3db86aabSstevel 	}
608*3db86aabSstevel #if defined(PCIC_DEBUG)
609*3db86aabSstevel 	if (pcic_debug)
610*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_probe: failed\n");
611*3db86aabSstevel #endif
612*3db86aabSstevel 	ddi_regs_map_free(&handle);
613*3db86aabSstevel 	return (DDI_PROBE_FAILURE);
614*3db86aabSstevel }
615*3db86aabSstevel 
616*3db86aabSstevel /*
617*3db86aabSstevel  * These are just defaults they can also be changed via a property in the
618*3db86aabSstevel  * conf file.
619*3db86aabSstevel  */
620*3db86aabSstevel static int pci_config_reg_num = PCIC_PCI_CONFIG_REG_NUM;
621*3db86aabSstevel static int pci_control_reg_num = PCIC_PCI_CONTROL_REG_NUM;
622*3db86aabSstevel static int pcic_do_pcmcia_sr = 0;
623*3db86aabSstevel static int pcic_use_cbpwrctl = PCF_CBPWRCTL;
624*3db86aabSstevel 
625*3db86aabSstevel /*
626*3db86aabSstevel  * enable insertion/removal interrupt for 32bit cards
627*3db86aabSstevel  */
628*3db86aabSstevel static int
629*3db86aabSstevel cardbus_enable_cd_intr(dev_info_t *dip)
630*3db86aabSstevel {
631*3db86aabSstevel 	ddi_acc_handle_t	iohandle;
632*3db86aabSstevel 	caddr_t	ioaddr;
633*3db86aabSstevel 	ddi_device_acc_attr_t attr;
634*3db86aabSstevel 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
635*3db86aabSstevel 	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
636*3db86aabSstevel 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
637*3db86aabSstevel 	(void) ddi_regs_map_setup(dip, 1,
638*3db86aabSstevel 				(caddr_t *)&ioaddr,
639*3db86aabSstevel 				0,
640*3db86aabSstevel 				4096,
641*3db86aabSstevel 				&attr, &iohandle);
642*3db86aabSstevel 
643*3db86aabSstevel 	/* CSC Interrupt: Card detect interrupt on */
644*3db86aabSstevel 	ddi_put32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_MASK),
645*3db86aabSstevel 		ddi_get32(iohandle,
646*3db86aabSstevel 		(uint32_t *)(ioaddr+CB_STATUS_MASK)) | CB_SE_CCDMASK);
647*3db86aabSstevel 
648*3db86aabSstevel 	ddi_put32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_EVENT),
649*3db86aabSstevel 		ddi_get32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_EVENT)));
650*3db86aabSstevel 
651*3db86aabSstevel 	ddi_regs_map_free(&iohandle);
652*3db86aabSstevel 	return (1);
653*3db86aabSstevel }
654*3db86aabSstevel 
655*3db86aabSstevel /*
656*3db86aabSstevel  * pcic_attach()
657*3db86aabSstevel  *	attach the PCIC (Intel 82365SL/CirrusLogic/Toshiba) driver
658*3db86aabSstevel  *	to the system.  This is a child of "sysbus" since that is where
659*3db86aabSstevel  *	the hardware lives, but it provides services to the "pcmcia"
660*3db86aabSstevel  *	nexus driver.  It gives a pointer back via its private data
661*3db86aabSstevel  *	structure which contains both the dip and socket services entry
662*3db86aabSstevel  *	points
663*3db86aabSstevel  */
664*3db86aabSstevel static int
665*3db86aabSstevel pcic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
666*3db86aabSstevel {
667*3db86aabSstevel 	anp_t *pcic_nexus;
668*3db86aabSstevel 	pcicdev_t *pcic;
669*3db86aabSstevel 	int irqlevel, value;
670*3db86aabSstevel 	int pci_cfrn, pci_ctrn;
671*3db86aabSstevel 	int i, j, smi, actual;
672*3db86aabSstevel 	char *typename;
673*3db86aabSstevel 	char bus_type[16] = "(unknown)";
674*3db86aabSstevel 	int len = sizeof (bus_type);
675*3db86aabSstevel 	ddi_device_acc_attr_t attr;
676*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
677*3db86aabSstevel 	uint_t	pri;
678*3db86aabSstevel 	syshw_t *shwp;
679*3db86aabSstevel 
680*3db86aabSstevel #if defined(PCIC_DEBUG)
681*3db86aabSstevel 	if (pcic_debug) {
682*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_attach: entered\n");
683*3db86aabSstevel 	}
684*3db86aabSstevel #endif
685*3db86aabSstevel 	switch (cmd) {
686*3db86aabSstevel 	case DDI_ATTACH:
687*3db86aabSstevel 		break;
688*3db86aabSstevel 	case DDI_RESUME:
689*3db86aabSstevel 		pcic = anp->an_private;
690*3db86aabSstevel 		/*
691*3db86aabSstevel 		 * for now, this is a simulated resume.
692*3db86aabSstevel 		 * a real one may need different things.
693*3db86aabSstevel 		 */
694*3db86aabSstevel 		if (pcic != NULL && pcic->pc_flags & PCF_SUSPENDED) {
695*3db86aabSstevel 			mutex_enter(&pcic->pc_lock);
696*3db86aabSstevel 			/* should probe for new sockets showing up */
697*3db86aabSstevel 			pcic_setup_adapter(pcic);
698*3db86aabSstevel 			syshw_resume(pcic);
699*3db86aabSstevel 			pcic->pc_flags &= ~PCF_SUSPENDED;
700*3db86aabSstevel 			mutex_exit(&pcic->pc_lock);
701*3db86aabSstevel 			(void) pcmcia_begin_resume(dip);
702*3db86aabSstevel 			/*
703*3db86aabSstevel 			 * this will do the CARD_INSERTION
704*3db86aabSstevel 			 * due to needing time for threads to
705*3db86aabSstevel 			 * run, it must be delayed for a short amount
706*3db86aabSstevel 			 * of time.  pcmcia_wait_insert checks for all
707*3db86aabSstevel 			 * children to be removed and then triggers insert.
708*3db86aabSstevel 			 */
709*3db86aabSstevel 			/*
710*3db86aabSstevel 			 * The reason for having a single timeout here
711*3db86aabSstevel 			 * rather than seperate timeout()s for each instance
712*3db86aabSstevel 			 * is due to the limited number (2) of callout threads
713*3db86aabSstevel 			 * available in Solaris 2.6. A single 1250A ends up
714*3db86aabSstevel 			 * as two instances of the interface with one slot each.
715*3db86aabSstevel 			 * The pcic_delayed_resume() function ends by calling
716*3db86aabSstevel 			 * pcmcia_wait_insert() which at one point does a
717*3db86aabSstevel 			 * delay(). delay() is implemented with a timeout()
718*3db86aabSstevel 			 * call so you end up with both the callout()
719*3db86aabSstevel 			 * threads waiting to be woken up by another callout().
720*3db86aabSstevel 			 * This situation locks up the machine hence the
721*3db86aabSstevel 			 * convolution here to only use one timeout.
722*3db86aabSstevel 			 */
723*3db86aabSstevel 			if (!pcic_delayed_resume_toid)
724*3db86aabSstevel 				pcic_delayed_resume_toid =
725*3db86aabSstevel 				    timeout(pcic_delayed_resume, (caddr_t)0,
726*3db86aabSstevel 				    drv_usectohz(pcic_wait_insert_time));
727*3db86aabSstevel 
728*3db86aabSstevel 			/*
729*3db86aabSstevel 			 * for complete implementation need END_RESUME (later)
730*3db86aabSstevel 			 */
731*3db86aabSstevel 			return (DDI_SUCCESS);
732*3db86aabSstevel 
733*3db86aabSstevel 		}
734*3db86aabSstevel 		return (DDI_SUCCESS);
735*3db86aabSstevel 	default:
736*3db86aabSstevel 		return (DDI_FAILURE);
737*3db86aabSstevel 	}
738*3db86aabSstevel 
739*3db86aabSstevel 	/*
740*3db86aabSstevel 	 * Allocate soft state associated with this instance.
741*3db86aabSstevel 	 */
742*3db86aabSstevel 	if (ddi_soft_state_zalloc(pcic_soft_state_p,
743*3db86aabSstevel 				ddi_get_instance(dip)) != DDI_SUCCESS) {
744*3db86aabSstevel 		cmn_err(CE_CONT, "pcic%d: Unable to alloc state\n",
745*3db86aabSstevel 			ddi_get_instance(dip));
746*3db86aabSstevel 		return (DDI_FAILURE);
747*3db86aabSstevel 	}
748*3db86aabSstevel 
749*3db86aabSstevel 	pcic_nexus = ddi_get_soft_state(pcic_soft_state_p,
750*3db86aabSstevel 	    ddi_get_instance(dip));
751*3db86aabSstevel 
752*3db86aabSstevel 	pcic = kmem_zalloc(sizeof (pcicdev_t), KM_SLEEP);
753*3db86aabSstevel 
754*3db86aabSstevel 	pcic->dip = dip;
755*3db86aabSstevel 	pcic_nexus->an_dip = dip;
756*3db86aabSstevel 	pcic_nexus->an_if = &pcic_if_ops;
757*3db86aabSstevel 	pcic_nexus->an_private = pcic;
758*3db86aabSstevel 	pcic->pc_numpower = sizeof (pcic_power)/sizeof (pcic_power[0]);
759*3db86aabSstevel 	pcic->pc_power = pcic_power;
760*3db86aabSstevel 
761*3db86aabSstevel 	pci_ctrn = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
762*3db86aabSstevel 	    "pci-control-reg-number", pci_control_reg_num);
763*3db86aabSstevel 	pci_cfrn = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
764*3db86aabSstevel 	    "pci-config-reg-number", pci_config_reg_num);
765*3db86aabSstevel 
766*3db86aabSstevel 	ddi_set_driver_private(dip, pcic_nexus);
767*3db86aabSstevel 
768*3db86aabSstevel 	/*
769*3db86aabSstevel 	 * pcic->pc_irq is really the IPL level we want to run at
770*3db86aabSstevel 	 * set the default values here and override from intr spec
771*3db86aabSstevel 	 */
772*3db86aabSstevel 	pcic->pc_irq = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
773*3db86aabSstevel 					"interrupt-priorities", -1);
774*3db86aabSstevel 
775*3db86aabSstevel 	if (pcic->pc_irq == -1) {
776*3db86aabSstevel 		int			actual;
777*3db86aabSstevel 		uint_t			pri;
778*3db86aabSstevel 		ddi_intr_handle_t	hdl;
779*3db86aabSstevel 
780*3db86aabSstevel 		/* see if intrspec tells us different */
781*3db86aabSstevel 		if (ddi_intr_alloc(dip, &hdl, DDI_INTR_TYPE_FIXED,
782*3db86aabSstevel 		    0, 1, &actual, DDI_INTR_ALLOC_NORMAL) == DDI_SUCCESS) {
783*3db86aabSstevel 			if (ddi_intr_get_pri(hdl, &pri) == DDI_SUCCESS)
784*3db86aabSstevel 				pcic->pc_irq = pri;
785*3db86aabSstevel 			else
786*3db86aabSstevel 				pcic->pc_irq = LOCK_LEVEL + 1;
787*3db86aabSstevel 			(void) ddi_intr_free(hdl);
788*3db86aabSstevel 		}
789*3db86aabSstevel 	}
790*3db86aabSstevel 	pcic_nexus->an_ipl = pcic->pc_irq;
791*3db86aabSstevel 
792*3db86aabSstevel 	/*
793*3db86aabSstevel 	 * Check our parent bus type. We do different things based on which
794*3db86aabSstevel 	 * bus we're on.
795*3db86aabSstevel 	 */
796*3db86aabSstevel 	if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
797*3db86aabSstevel 				PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP,
798*3db86aabSstevel 				"device_type", (caddr_t)&bus_type[0], &len) !=
799*3db86aabSstevel 							DDI_PROP_SUCCESS) {
800*3db86aabSstevel 		if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
801*3db86aabSstevel 				PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP,
802*3db86aabSstevel 				"bus-type", (caddr_t)&bus_type[0], &len) !=
803*3db86aabSstevel 							DDI_PROP_SUCCESS) {
804*3db86aabSstevel 
805*3db86aabSstevel 			cmn_err(CE_CONT,
806*3db86aabSstevel 				"pcic%d: can't find parent bus type\n",
807*3db86aabSstevel 				ddi_get_instance(dip));
808*3db86aabSstevel 
809*3db86aabSstevel 			kmem_free(pcic, sizeof (pcicdev_t));
810*3db86aabSstevel 			return (DDI_FAILURE);
811*3db86aabSstevel 		}
812*3db86aabSstevel 	} /* ddi_prop_op("device_type") */
813*3db86aabSstevel 
814*3db86aabSstevel 	if (strcmp(bus_type, DEVI_PCI_NEXNAME) == 0) {
815*3db86aabSstevel 		pcic->pc_flags = PCF_PCIBUS;
816*3db86aabSstevel 	} else {
817*3db86aabSstevel #if defined(__sparc)
818*3db86aabSstevel 		cmn_err(CE_CONT, "pcic%d: unsupported parent bus type: [%s]\n",
819*3db86aabSstevel 			ddi_get_instance(dip), bus_type);
820*3db86aabSstevel 
821*3db86aabSstevel 		kmem_free(pcic, sizeof (pcicdev_t));
822*3db86aabSstevel 		return (DDI_FAILURE);
823*3db86aabSstevel #else
824*3db86aabSstevel 		pcic->pc_flags = 0;
825*3db86aabSstevel #endif
826*3db86aabSstevel 	}
827*3db86aabSstevel 
828*3db86aabSstevel 	if ((pcic->bus_speed = ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(dip),
829*3db86aabSstevel 						DDI_PROP_CANSLEEP,
830*3db86aabSstevel 						"clock-frequency", 0)) == 0) {
831*3db86aabSstevel 		if (pcic->pc_flags & PCF_PCIBUS)
832*3db86aabSstevel 			pcic->bus_speed = PCIC_PCI_DEF_SYSCLK;
833*3db86aabSstevel 		else
834*3db86aabSstevel 			pcic->bus_speed = PCIC_ISA_DEF_SYSCLK;
835*3db86aabSstevel 	} else {
836*3db86aabSstevel 		/*
837*3db86aabSstevel 		 * OBP can declare the speed in Hz...
838*3db86aabSstevel 		 */
839*3db86aabSstevel 		if (pcic->bus_speed > 1000000)
840*3db86aabSstevel 			pcic->bus_speed /= 1000000;
841*3db86aabSstevel 	} /* ddi_prop_op("clock-frequency") */
842*3db86aabSstevel 
843*3db86aabSstevel 	pcic->pc_io_type = PCIC_IO_TYPE_82365SL; /* default mode */
844*3db86aabSstevel 
845*3db86aabSstevel #ifdef	PCIC_DEBUG
846*3db86aabSstevel 	if (pcic_debug) {
847*3db86aabSstevel 		cmn_err(CE_CONT,
848*3db86aabSstevel 			"pcic%d: parent bus type = [%s], speed = %d MHz\n",
849*3db86aabSstevel 			ddi_get_instance(dip),
850*3db86aabSstevel 			bus_type, pcic->bus_speed);
851*3db86aabSstevel 	}
852*3db86aabSstevel #endif
853*3db86aabSstevel 
854*3db86aabSstevel 	/*
855*3db86aabSstevel 	 * The reg properties on a PCI node are different than those
856*3db86aabSstevel 	 *	on a non-PCI node. Handle that difference here.
857*3db86aabSstevel 	 *	If it turns out to be a CardBus chip, we have even more
858*3db86aabSstevel 	 *	differences.
859*3db86aabSstevel 	 */
860*3db86aabSstevel 	if (pcic->pc_flags & PCF_PCIBUS) {
861*3db86aabSstevel 		int class_code;
862*3db86aabSstevel #if defined(__i386) || defined(__amd64)
863*3db86aabSstevel 		pcic->pc_base = 0x1000000;
864*3db86aabSstevel 		pcic->pc_bound = (uint32_t)~0;
865*3db86aabSstevel 		pcic->pc_iobase = 0x1000;
866*3db86aabSstevel 		pcic->pc_iobound = 0xefff;
867*3db86aabSstevel #elif defined(__sparc)
868*3db86aabSstevel 		pcic->pc_base = 0x0;
869*3db86aabSstevel 		pcic->pc_bound = (uint32_t)~0;
870*3db86aabSstevel 		pcic->pc_iobase = 0x00000;
871*3db86aabSstevel 		pcic->pc_iobound = 0xffff;
872*3db86aabSstevel #endif
873*3db86aabSstevel 
874*3db86aabSstevel 		/* usually need to get at config space so map first */
875*3db86aabSstevel 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
876*3db86aabSstevel 		attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
877*3db86aabSstevel 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
878*3db86aabSstevel 
879*3db86aabSstevel 		if (ddi_regs_map_setup(dip, pci_cfrn,
880*3db86aabSstevel 					(caddr_t *)&pcic->cfgaddr,
881*3db86aabSstevel 					PCIC_PCI_CONFIG_REG_OFFSET,
882*3db86aabSstevel 					PCIC_PCI_CONFIG_REG_LENGTH,
883*3db86aabSstevel 					&attr,
884*3db86aabSstevel 					&pcic->cfg_handle) !=
885*3db86aabSstevel 		    DDI_SUCCESS) {
886*3db86aabSstevel 			cmn_err(CE_CONT,
887*3db86aabSstevel 				"pcic%d: unable to map config space"
888*3db86aabSstevel 				"regs\n",
889*3db86aabSstevel 				ddi_get_instance(dip));
890*3db86aabSstevel 
891*3db86aabSstevel 			kmem_free(pcic, sizeof (pcicdev_t));
892*3db86aabSstevel 			return (DDI_FAILURE);
893*3db86aabSstevel 		} /* ddi_regs_map_setup */
894*3db86aabSstevel 
895*3db86aabSstevel 		class_code = ddi_getprop(DDI_DEV_T_ANY, dip,
896*3db86aabSstevel 					DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
897*3db86aabSstevel 					"class-code", -1);
898*3db86aabSstevel #ifdef  PCIC_DEBUG
899*3db86aabSstevel 		if (pcic_debug) {
900*3db86aabSstevel 			cmn_err(CE_CONT, "pcic_attach class_code=%x\n",
901*3db86aabSstevel 			    class_code);
902*3db86aabSstevel 		}
903*3db86aabSstevel #endif
904*3db86aabSstevel 
905*3db86aabSstevel 		switch (class_code) {
906*3db86aabSstevel 		case PCIC_PCI_CARDBUS:
907*3db86aabSstevel 			pcic->pc_flags |= PCF_CARDBUS;
908*3db86aabSstevel 			pcic->pc_io_type = PCIC_IO_TYPE_YENTA;
909*3db86aabSstevel 			/*
910*3db86aabSstevel 			 * Get access to the adapter registers on the
911*3db86aabSstevel 			 * PCI bus.  A 4K memory page
912*3db86aabSstevel 			 */
913*3db86aabSstevel #if defined(PCIC_DEBUG)
914*3db86aabSstevel 			pcic_err(dip, 8, "Is Cardbus device\n");
915*3db86aabSstevel 			if (pcic_debug) {
916*3db86aabSstevel 				int nr;
917*3db86aabSstevel 				long rs;
918*3db86aabSstevel 				(void) ddi_dev_nregs(dip, &nr);
919*3db86aabSstevel 				pcic_err(dip, 9, "\tdev, cfgaddr 0x%p,"
920*3db86aabSstevel 				    "cfghndl 0x%p nregs %d",
921*3db86aabSstevel 				    (void *)pcic->cfgaddr,
922*3db86aabSstevel 				    (void *)pcic->cfg_handle, nr);
923*3db86aabSstevel 
924*3db86aabSstevel 				(void) ddi_dev_regsize(dip,
925*3db86aabSstevel 				    PCIC_PCI_CONTROL_REG_NUM, &rs);
926*3db86aabSstevel 
927*3db86aabSstevel 				pcic_err(dip, 9, "\tsize of reg %d is 0x%x\n",
928*3db86aabSstevel 				    PCIC_PCI_CONTROL_REG_NUM, (int)rs);
929*3db86aabSstevel 			}
930*3db86aabSstevel #endif
931*3db86aabSstevel 			attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
932*3db86aabSstevel 			attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
933*3db86aabSstevel 			attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
934*3db86aabSstevel 
935*3db86aabSstevel 			if (ddi_regs_map_setup(dip, pci_ctrn,
936*3db86aabSstevel 						(caddr_t *)&pcic->ioaddr,
937*3db86aabSstevel 						PCIC_PCI_CONTROL_REG_OFFSET,
938*3db86aabSstevel 						PCIC_CB_CONTROL_REG_LENGTH,
939*3db86aabSstevel 						&attr, &pcic->handle) !=
940*3db86aabSstevel 			    DDI_SUCCESS) {
941*3db86aabSstevel 				cmn_err(CE_CONT,
942*3db86aabSstevel 					"pcic%d: unable to map PCI regs\n",
943*3db86aabSstevel 					ddi_get_instance(dip));
944*3db86aabSstevel 				ddi_regs_map_free(&pcic->cfg_handle);
945*3db86aabSstevel 				kmem_free(pcic, sizeof (pcicdev_t));
946*3db86aabSstevel 				return (DDI_FAILURE);
947*3db86aabSstevel 			} /* ddi_regs_map_setup */
948*3db86aabSstevel 
949*3db86aabSstevel 			/*
950*3db86aabSstevel 			 * Find out the chip type - If we're on a PCI bus,
951*3db86aabSstevel 			 *	the adapter has that information in the PCI
952*3db86aabSstevel 			 *	config space.
953*3db86aabSstevel 			 * Note that we call pcic_find_pci_type here since
954*3db86aabSstevel 			 *	it needs a valid mapped pcic->handle to
955*3db86aabSstevel 			 *	access some of the adapter registers in
956*3db86aabSstevel 			 *	some cases.
957*3db86aabSstevel 			 */
958*3db86aabSstevel 			if (pcic_find_pci_type(pcic) != DDI_SUCCESS) {
959*3db86aabSstevel 				ddi_regs_map_free(&pcic->handle);
960*3db86aabSstevel 				ddi_regs_map_free(&pcic->cfg_handle);
961*3db86aabSstevel 				kmem_free(pcic, sizeof (pcicdev_t));
962*3db86aabSstevel 				cmn_err(CE_WARN, "pcic: %s: unsupported "
963*3db86aabSstevel 								"bridge\n",
964*3db86aabSstevel 							ddi_get_name_addr(dip));
965*3db86aabSstevel 				return (DDI_FAILURE);
966*3db86aabSstevel 			}
967*3db86aabSstevel 			break;
968*3db86aabSstevel 
969*3db86aabSstevel 		default:
970*3db86aabSstevel 		case PCIC_PCI_PCMCIA:
971*3db86aabSstevel 			/*
972*3db86aabSstevel 			 * Get access to the adapter IO registers on the
973*3db86aabSstevel 			 * PCI bus config space.
974*3db86aabSstevel 			 */
975*3db86aabSstevel 			attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
976*3db86aabSstevel 			attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
977*3db86aabSstevel 			attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
978*3db86aabSstevel 
979*3db86aabSstevel 			/*
980*3db86aabSstevel 			 * We need a default mapping to the adapter's IO
981*3db86aabSstevel 			 *	control register space. For most adapters
982*3db86aabSstevel 			 *	that are of class PCIC_PCI_PCMCIA (or of
983*3db86aabSstevel 			 *	a default class) the control registers
984*3db86aabSstevel 			 *	will be using the 82365-type control/data
985*3db86aabSstevel 			 *	format.
986*3db86aabSstevel 			 */
987*3db86aabSstevel 			if (ddi_regs_map_setup(dip, pci_ctrn,
988*3db86aabSstevel 						(caddr_t *)&pcic->ioaddr,
989*3db86aabSstevel 						PCIC_PCI_CONTROL_REG_OFFSET,
990*3db86aabSstevel 						PCIC_PCI_CONTROL_REG_LENGTH,
991*3db86aabSstevel 						&attr,
992*3db86aabSstevel 						&pcic->handle) != DDI_SUCCESS) {
993*3db86aabSstevel 				cmn_err(CE_CONT,
994*3db86aabSstevel 					"pcic%d: unable to map PCI regs\n",
995*3db86aabSstevel 					ddi_get_instance(dip));
996*3db86aabSstevel 				ddi_regs_map_free(&pcic->cfg_handle);
997*3db86aabSstevel 				kmem_free(pcic, sizeof (pcicdev_t));
998*3db86aabSstevel 				return (DDI_FAILURE);
999*3db86aabSstevel 			} /* ddi_regs_map_setup */
1000*3db86aabSstevel 
1001*3db86aabSstevel 			/*
1002*3db86aabSstevel 			 * Find out the chip type - If we're on a PCI bus,
1003*3db86aabSstevel 			 *	the adapter has that information in the PCI
1004*3db86aabSstevel 			 *	config space.
1005*3db86aabSstevel 			 * Note that we call pcic_find_pci_type here since
1006*3db86aabSstevel 			 *	it needs a valid mapped pcic->handle to
1007*3db86aabSstevel 			 *	access some of the adapter registers in
1008*3db86aabSstevel 			 *	some cases.
1009*3db86aabSstevel 			 */
1010*3db86aabSstevel 			if (pcic_find_pci_type(pcic) != DDI_SUCCESS) {
1011*3db86aabSstevel 				ddi_regs_map_free(&pcic->handle);
1012*3db86aabSstevel 				ddi_regs_map_free(&pcic->cfg_handle);
1013*3db86aabSstevel 				kmem_free(pcic, sizeof (pcicdev_t));
1014*3db86aabSstevel 				cmn_err(CE_WARN, "pcic: %s: unsupported "
1015*3db86aabSstevel 								"bridge\n",
1016*3db86aabSstevel 							ddi_get_name_addr(dip));
1017*3db86aabSstevel 				return (DDI_FAILURE);
1018*3db86aabSstevel 			}
1019*3db86aabSstevel 
1020*3db86aabSstevel 			/*
1021*3db86aabSstevel 			 * Some PCI-PCMCIA(R2) adapters are Yenta-compliant
1022*3db86aabSstevel 			 *	for extended registers even though they are
1023*3db86aabSstevel 			 *	not CardBus adapters. For those adapters,
1024*3db86aabSstevel 			 *	re-map pcic->handle to be large enough to
1025*3db86aabSstevel 			 *	encompass the Yenta registers.
1026*3db86aabSstevel 			 */
1027*3db86aabSstevel 			switch (pcic->pc_type) {
1028*3db86aabSstevel 			    case PCIC_TI_PCI1031:
1029*3db86aabSstevel 				ddi_regs_map_free(&pcic->handle);
1030*3db86aabSstevel 
1031*3db86aabSstevel 				if (ddi_regs_map_setup(dip,
1032*3db86aabSstevel 						PCIC_PCI_CONTROL_REG_NUM,
1033*3db86aabSstevel 						(caddr_t *)&pcic->ioaddr,
1034*3db86aabSstevel 						PCIC_PCI_CONTROL_REG_OFFSET,
1035*3db86aabSstevel 						PCIC_CB_CONTROL_REG_LENGTH,
1036*3db86aabSstevel 						&attr,
1037*3db86aabSstevel 						&pcic->handle) != DDI_SUCCESS) {
1038*3db86aabSstevel 					cmn_err(CE_CONT,
1039*3db86aabSstevel 						"pcic%d: unable to map "
1040*3db86aabSstevel 								"PCI regs\n",
1041*3db86aabSstevel 						ddi_get_instance(dip));
1042*3db86aabSstevel 					ddi_regs_map_free(&pcic->cfg_handle);
1043*3db86aabSstevel 					kmem_free(pcic, sizeof (pcicdev_t));
1044*3db86aabSstevel 					return (DDI_FAILURE);
1045*3db86aabSstevel 				} /* ddi_regs_map_setup */
1046*3db86aabSstevel 				break;
1047*3db86aabSstevel 			    default:
1048*3db86aabSstevel 				break;
1049*3db86aabSstevel 			} /* switch (pcic->pc_type) */
1050*3db86aabSstevel 			break;
1051*3db86aabSstevel 		} /* switch (class_code) */
1052*3db86aabSstevel 	} else {
1053*3db86aabSstevel 		/*
1054*3db86aabSstevel 		 * We're not on a PCI bus, so assume an ISA bus type
1055*3db86aabSstevel 		 * register property. Get access to the adapter IO
1056*3db86aabSstevel 		 * registers on a non-PCI bus.
1057*3db86aabSstevel 		 */
1058*3db86aabSstevel 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1059*3db86aabSstevel 		attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
1060*3db86aabSstevel 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1061*3db86aabSstevel 		pcic->mem_reg_num = PCIC_ISA_MEM_REG_NUM;
1062*3db86aabSstevel 		pcic->io_reg_num = PCIC_ISA_IO_REG_NUM;
1063*3db86aabSstevel 
1064*3db86aabSstevel 		if (ddi_regs_map_setup(dip, PCIC_ISA_CONTROL_REG_NUM,
1065*3db86aabSstevel 					(caddr_t *)&pcic->ioaddr,
1066*3db86aabSstevel 					PCIC_ISA_CONTROL_REG_OFFSET,
1067*3db86aabSstevel 					PCIC_ISA_CONTROL_REG_LENGTH,
1068*3db86aabSstevel 					&attr,
1069*3db86aabSstevel 					&pcic->handle) != DDI_SUCCESS) {
1070*3db86aabSstevel 			cmn_err(CE_CONT,
1071*3db86aabSstevel 				"pcic%d: unable to map ISA registers\n",
1072*3db86aabSstevel 				ddi_get_instance(dip));
1073*3db86aabSstevel 
1074*3db86aabSstevel 			kmem_free(pcic, sizeof (pcicdev_t));
1075*3db86aabSstevel 			return (DDI_FAILURE);
1076*3db86aabSstevel 		} /* ddi_regs_map_setup */
1077*3db86aabSstevel 
1078*3db86aabSstevel 		/* ISA bus is limited to 24-bits, but not first 640K */
1079*3db86aabSstevel 		pcic->pc_base = 0xd0000;
1080*3db86aabSstevel 		pcic->pc_bound = (uint32_t)~0;
1081*3db86aabSstevel 		pcic->pc_iobase = 0x1000;
1082*3db86aabSstevel 		pcic->pc_iobound = 0xefff;
1083*3db86aabSstevel 	} /* !PCF_PCIBUS */
1084*3db86aabSstevel 
1085*3db86aabSstevel #ifdef  PCIC_DEBUG
1086*3db86aabSstevel 	if (pcic_debug) {
1087*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_attach pc_flags=%x pc_type=%x\n",
1088*3db86aabSstevel 		    pcic->pc_flags, pcic->pc_type);
1089*3db86aabSstevel 	}
1090*3db86aabSstevel #endif
1091*3db86aabSstevel 
1092*3db86aabSstevel 	/*
1093*3db86aabSstevel 	 * Setup various adapter registers for the PCI case. For the
1094*3db86aabSstevel 	 * non-PCI case, find out the chip type.
1095*3db86aabSstevel 	 */
1096*3db86aabSstevel 	if (pcic->pc_flags & PCF_PCIBUS) {
1097*3db86aabSstevel 		int iline;
1098*3db86aabSstevel #if defined(__sparc)
1099*3db86aabSstevel 		iline = 0;
1100*3db86aabSstevel #else
1101*3db86aabSstevel 		iline = cardbus_validate_iline(dip, pcic->cfg_handle);
1102*3db86aabSstevel #endif
1103*3db86aabSstevel 
1104*3db86aabSstevel 		/* set flags and socket counts based on chip type */
1105*3db86aabSstevel 		switch (pcic->pc_type) {
1106*3db86aabSstevel 			uint32_t cfg;
1107*3db86aabSstevel 		case PCIC_INTEL_i82092:
1108*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1109*3db86aabSstevel 					pcic->cfgaddr + PCIC_82092_PCICON);
1110*3db86aabSstevel 			/* we can only support 4 Socket version */
1111*3db86aabSstevel 			if (cfg & PCIC_82092_4_SOCKETS) {
1112*3db86aabSstevel 			    pcic->pc_numsockets = 4;
1113*3db86aabSstevel 			    pcic->pc_type = PCIC_INTEL_i82092;
1114*3db86aabSstevel 			    if (iline != 0xFF)
1115*3db86aabSstevel 				    pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1116*3db86aabSstevel 			    else
1117*3db86aabSstevel 				    pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
1118*3db86aabSstevel 			} else {
1119*3db86aabSstevel 			    cmn_err(CE_CONT,
1120*3db86aabSstevel 				    "pcic%d: Intel 82092 adapter "
1121*3db86aabSstevel 				    "in unsupported configuration: 0x%x",
1122*3db86aabSstevel 				    ddi_get_instance(pcic->dip), cfg);
1123*3db86aabSstevel 			    pcic->pc_numsockets = 0;
1124*3db86aabSstevel 			} /* PCIC_82092_4_SOCKETS */
1125*3db86aabSstevel 			break;
1126*3db86aabSstevel 		case PCIC_CL_PD6730:
1127*3db86aabSstevel 		case PCIC_CL_PD6729:
1128*3db86aabSstevel 			pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1129*3db86aabSstevel 			cfg = ddi_getprop(DDI_DEV_T_ANY, dip,
1130*3db86aabSstevel 						DDI_PROP_CANSLEEP,
1131*3db86aabSstevel 						"interrupts", 0);
1132*3db86aabSstevel 			/* if not interrupt pin then must use ISA style IRQs */
1133*3db86aabSstevel 			if (cfg == 0 || iline == 0xFF)
1134*3db86aabSstevel 				pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
1135*3db86aabSstevel 			else {
1136*3db86aabSstevel 				/*
1137*3db86aabSstevel 				 * we have the option to use PCI interrupts.
1138*3db86aabSstevel 				 * this might not be optimal but in some cases
1139*3db86aabSstevel 				 * is the only thing possible (sparc case).
1140*3db86aabSstevel 				 * we now deterine what is possible.
1141*3db86aabSstevel 				 */
1142*3db86aabSstevel 				pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1143*3db86aabSstevel 			}
1144*3db86aabSstevel 			pcic->pc_numsockets = 2;
1145*3db86aabSstevel 			pcic->pc_flags |= PCF_IO_REMAP;
1146*3db86aabSstevel 			break;
1147*3db86aabSstevel 		case PCIC_TI_PCI1031:
1148*3db86aabSstevel 			/* this chip doesn't do CardBus but looks like one */
1149*3db86aabSstevel 			pcic->pc_flags &= ~PCF_CARDBUS;
1150*3db86aabSstevel 			/* FALLTHROUGH */
1151*3db86aabSstevel 		default:
1152*3db86aabSstevel 			pcic->pc_flags |= PCF_IO_REMAP;
1153*3db86aabSstevel 			/* FALLTHROUGH */
1154*3db86aabSstevel 			/* indicate feature even if not supported */
1155*3db86aabSstevel 			pcic->pc_flags |= PCF_DMA | PCF_ZV;
1156*3db86aabSstevel 			/* Not sure if these apply to all these chips */
1157*3db86aabSstevel 			pcic->pc_flags |= (PCF_VPPX|PCF_33VCAP);
1158*3db86aabSstevel 			pcic->pc_flags |= pcic_use_cbpwrctl;
1159*3db86aabSstevel 
1160*3db86aabSstevel 			pcic->pc_numsockets = 1; /* one per function */
1161*3db86aabSstevel 			if (iline != 0xFF) {
1162*3db86aabSstevel 				uint8_t cfg;
1163*3db86aabSstevel 				pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1164*3db86aabSstevel 
1165*3db86aabSstevel 				cfg = ddi_get8(pcic->cfg_handle,
1166*3db86aabSstevel 					(pcic->cfgaddr + PCIC_BRIDGE_CTL_REG));
1167*3db86aabSstevel 				cfg &= (~PCIC_FUN_INT_MOD_ISA);
1168*3db86aabSstevel 				ddi_put8(pcic->cfg_handle, (pcic->cfgaddr +
1169*3db86aabSstevel 					PCIC_BRIDGE_CTL_REG), cfg);
1170*3db86aabSstevel 			}
1171*3db86aabSstevel 			else
1172*3db86aabSstevel 				pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
1173*3db86aabSstevel 			pcic->pc_io_type = PCIC_IOTYPE_YENTA;
1174*3db86aabSstevel 			break;
1175*3db86aabSstevel 		}
1176*3db86aabSstevel 	} else {
1177*3db86aabSstevel 		/*
1178*3db86aabSstevel 		 * We're not on a PCI bus so do some more
1179*3db86aabSstevel 		 *	checking for adapter type here.
1180*3db86aabSstevel 		 * For the non-PCI bus case:
1181*3db86aabSstevel 		 * It could be any one of a number of different chips
1182*3db86aabSstevel 		 * If we can't determine anything else, it is assumed
1183*3db86aabSstevel 		 * to be an Intel 82365SL.  The Cirrus Logic PD6710
1184*3db86aabSstevel 		 * has an extension register that provides unique
1185*3db86aabSstevel 		 * identification. Toshiba chip isn't detailed as yet.
1186*3db86aabSstevel 		 */
1187*3db86aabSstevel 
1188*3db86aabSstevel 		/* Init the CL id mode */
1189*3db86aabSstevel 		pcic_putb(pcic, 0, PCIC_CHIP_INFO, 0);
1190*3db86aabSstevel 		value = pcic_getb(pcic, 0, PCIC_CHIP_INFO);
1191*3db86aabSstevel 
1192*3db86aabSstevel 		/* default to Intel i82365SL and then refine */
1193*3db86aabSstevel 		pcic->pc_type = PCIC_I82365SL;
1194*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_I82365SL;
1195*3db86aabSstevel 		for (value = 0; pcic_ci_funcs[value] != NULL; value++) {
1196*3db86aabSstevel 			/* go until one succeeds or none left */
1197*3db86aabSstevel 			if (pcic_ci_funcs[value](pcic))
1198*3db86aabSstevel 				break;
1199*3db86aabSstevel 		}
1200*3db86aabSstevel 
1201*3db86aabSstevel 		/* any chip specific flags get set here */
1202*3db86aabSstevel 		switch (pcic->pc_type) {
1203*3db86aabSstevel 		case PCIC_CL_PD6722:
1204*3db86aabSstevel 			pcic->pc_flags |= PCF_DMA;
1205*3db86aabSstevel 		}
1206*3db86aabSstevel 
1207*3db86aabSstevel 		for (i = 0; i < PCIC_MAX_SOCKETS; i++) {
1208*3db86aabSstevel 			/*
1209*3db86aabSstevel 			 * look for total number of sockets.
1210*3db86aabSstevel 			 * basically check each possible socket for
1211*3db86aabSstevel 			 * presence like in probe
1212*3db86aabSstevel 			 */
1213*3db86aabSstevel 
1214*3db86aabSstevel 			/* turn all windows off */
1215*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1216*3db86aabSstevel 			value = pcic_getb(pcic, i, PCIC_MAPPING_ENABLE);
1217*3db86aabSstevel 
1218*3db86aabSstevel 			/*
1219*3db86aabSstevel 			 * if a zero is read back, then this socket
1220*3db86aabSstevel 			 * might be present. It would be except for
1221*3db86aabSstevel 			 * some systems that map the secondary PCIC
1222*3db86aabSstevel 			 * chip space back to the first.
1223*3db86aabSstevel 			 */
1224*3db86aabSstevel 			if (value != 0) {
1225*3db86aabSstevel 				/* definitely not so skip */
1226*3db86aabSstevel 				/* note: this is for Compaq support */
1227*3db86aabSstevel 				continue;
1228*3db86aabSstevel 			}
1229*3db86aabSstevel 
1230*3db86aabSstevel 			/* further tests */
1231*3db86aabSstevel 			value = pcic_getb(pcic, i, PCIC_CHIP_REVISION) &
1232*3db86aabSstevel 				PCIC_REV_MASK;
1233*3db86aabSstevel 			if (!(value >= PCIC_REV_LEVEL_LOW &&
1234*3db86aabSstevel 				value <= PCIC_REV_LEVEL_HI))
1235*3db86aabSstevel 				break;
1236*3db86aabSstevel 
1237*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_SYSMEM_0_STARTLOW, 0xaa);
1238*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_SYSMEM_1_STARTLOW, 0x55);
1239*3db86aabSstevel 			value = pcic_getb(pcic, i, PCIC_SYSMEM_0_STARTLOW);
1240*3db86aabSstevel 
1241*3db86aabSstevel 			j = pcic_getb(pcic, i, PCIC_SYSMEM_1_STARTLOW);
1242*3db86aabSstevel 			if (value != 0xaa || j != 0x55)
1243*3db86aabSstevel 				break;
1244*3db86aabSstevel 
1245*3db86aabSstevel 			/*
1246*3db86aabSstevel 			 * at this point we know if we have hardware
1247*3db86aabSstevel 			 * of some type and not just the bus holding
1248*3db86aabSstevel 			 * a pattern for us. We still have to determine
1249*3db86aabSstevel 			 * the case where more than 2 sockets are
1250*3db86aabSstevel 			 * really the same due to peculiar mappings of
1251*3db86aabSstevel 			 * hardware.
1252*3db86aabSstevel 			 */
1253*3db86aabSstevel 			j = pcic->pc_numsockets++;
1254*3db86aabSstevel 			pcic->pc_sockets[j].pcs_flags = 0;
1255*3db86aabSstevel 			pcic->pc_sockets[j].pcs_io = pcic->ioaddr;
1256*3db86aabSstevel 			pcic->pc_sockets[j].pcs_socket = i;
1257*3db86aabSstevel 
1258*3db86aabSstevel 			/* put PC Card into RESET, just in case */
1259*3db86aabSstevel 			value = pcic_getb(pcic, i, PCIC_INTERRUPT);
1260*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_INTERRUPT,
1261*3db86aabSstevel 					value & ~PCIC_RESET);
1262*3db86aabSstevel 		}
1263*3db86aabSstevel 
1264*3db86aabSstevel #if defined(PCIC_DEBUG)
1265*3db86aabSstevel 		if (pcic_debug)
1266*3db86aabSstevel 			cmn_err(CE_CONT, "num sockets = %d\n",
1267*3db86aabSstevel 				pcic->pc_numsockets);
1268*3db86aabSstevel #endif
1269*3db86aabSstevel 		if (pcic->pc_numsockets == 0) {
1270*3db86aabSstevel 			ddi_regs_map_free(&pcic->handle);
1271*3db86aabSstevel 			kmem_free(pcic, sizeof (pcicdev_t));
1272*3db86aabSstevel 			return (DDI_FAILURE);
1273*3db86aabSstevel 		}
1274*3db86aabSstevel 
1275*3db86aabSstevel 		/*
1276*3db86aabSstevel 		 * need to think this through again in light of
1277*3db86aabSstevel 		 * Compaq not following the model that all the
1278*3db86aabSstevel 		 * chip vendors recommend.  IBM 755 seems to be
1279*3db86aabSstevel 		 * afflicted as well.  Basically, if the vendor
1280*3db86aabSstevel 		 * wired things wrong, socket 0 responds for socket 2
1281*3db86aabSstevel 		 * accesses, etc.
1282*3db86aabSstevel 		 */
1283*3db86aabSstevel 		if (pcic->pc_numsockets > 2) {
1284*3db86aabSstevel 			int count = pcic->pc_numsockets / 4;
1285*3db86aabSstevel 			for (i = 0; i < count; i++) {
1286*3db86aabSstevel 				/* put pattern into socket 0 */
1287*3db86aabSstevel 				pcic_putb(pcic, i,
1288*3db86aabSstevel 						PCIC_SYSMEM_0_STARTLOW, 0x11);
1289*3db86aabSstevel 
1290*3db86aabSstevel 				/* put pattern into socket 2 */
1291*3db86aabSstevel 				pcic_putb(pcic, i + 2,
1292*3db86aabSstevel 						PCIC_SYSMEM_0_STARTLOW, 0x33);
1293*3db86aabSstevel 
1294*3db86aabSstevel 				/* read back socket 0 */
1295*3db86aabSstevel 				value = pcic_getb(pcic, i,
1296*3db86aabSstevel 						    PCIC_SYSMEM_0_STARTLOW);
1297*3db86aabSstevel 
1298*3db86aabSstevel 				/* read back chip 1 socket 0 */
1299*3db86aabSstevel 				j = pcic_getb(pcic, i + 2,
1300*3db86aabSstevel 						PCIC_SYSMEM_0_STARTLOW);
1301*3db86aabSstevel 				if (j == value) {
1302*3db86aabSstevel 					pcic->pc_numsockets -= 2;
1303*3db86aabSstevel 				}
1304*3db86aabSstevel 			}
1305*3db86aabSstevel 		}
1306*3db86aabSstevel 
1307*3db86aabSstevel 		smi = 0xff;	/* no more override */
1308*3db86aabSstevel 
1309*3db86aabSstevel 		if (ddi_getprop(DDI_DEV_T_NONE, dip,
1310*3db86aabSstevel 				DDI_PROP_DONTPASS, "need-mult-irq",
1311*3db86aabSstevel 				0xffff) != 0xffff)
1312*3db86aabSstevel 			pcic->pc_flags |= PCF_MULT_IRQ;
1313*3db86aabSstevel 
1314*3db86aabSstevel 	} /* !PCF_PCIBUS */
1315*3db86aabSstevel 
1316*3db86aabSstevel 	/*
1317*3db86aabSstevel 	 * some platforms/busses need to have resources setup
1318*3db86aabSstevel 	 * this is temporary until a real resource allocator is
1319*3db86aabSstevel 	 * implemented.
1320*3db86aabSstevel 	 */
1321*3db86aabSstevel 
1322*3db86aabSstevel 	pcic_init_assigned(dip);
1323*3db86aabSstevel 
1324*3db86aabSstevel 	typename = pcic->pc_chipname;
1325*3db86aabSstevel 
1326*3db86aabSstevel #ifdef	PCIC_DEBUG
1327*3db86aabSstevel 	if (pcic_debug) {
1328*3db86aabSstevel 		int nregs, nintrs;
1329*3db86aabSstevel 
1330*3db86aabSstevel 		if (ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS)
1331*3db86aabSstevel 			nregs = 0;
1332*3db86aabSstevel 
1333*3db86aabSstevel 		if (ddi_dev_nintrs(dip, &nintrs) != DDI_SUCCESS)
1334*3db86aabSstevel 			nintrs = 0;
1335*3db86aabSstevel 
1336*3db86aabSstevel 		cmn_err(CE_CONT,
1337*3db86aabSstevel 			"pcic%d: %d register sets, %d interrupts\n",
1338*3db86aabSstevel 			ddi_get_instance(dip), nregs, nintrs);
1339*3db86aabSstevel 
1340*3db86aabSstevel 		nintrs = 0;
1341*3db86aabSstevel 		while (nregs--) {
1342*3db86aabSstevel 			off_t size;
1343*3db86aabSstevel 
1344*3db86aabSstevel 			if (ddi_dev_regsize(dip, nintrs, &size) ==
1345*3db86aabSstevel 			    DDI_SUCCESS) {
1346*3db86aabSstevel 				cmn_err(CE_CONT,
1347*3db86aabSstevel 					"\tregnum %d size %ld (0x%lx)"
1348*3db86aabSstevel 					"bytes",
1349*3db86aabSstevel 					nintrs, size, size);
1350*3db86aabSstevel 				if (nintrs ==
1351*3db86aabSstevel 				    (pcic->pc_io_type == PCIC_IO_TYPE_82365SL ?
1352*3db86aabSstevel 				    PCIC_ISA_CONTROL_REG_NUM :
1353*3db86aabSstevel 				    PCIC_PCI_CONTROL_REG_NUM))
1354*3db86aabSstevel 					cmn_err(CE_CONT,
1355*3db86aabSstevel 						" mapped at: 0x%p\n",
1356*3db86aabSstevel 						(void *)pcic->ioaddr);
1357*3db86aabSstevel 				else
1358*3db86aabSstevel 					cmn_err(CE_CONT, "\n");
1359*3db86aabSstevel 			} else {
1360*3db86aabSstevel 				cmn_err(CE_CONT,
1361*3db86aabSstevel 					"\tddi_dev_regsize(rnumber"
1362*3db86aabSstevel 					"= %d) returns DDI_FAILURE\n",
1363*3db86aabSstevel 					nintrs);
1364*3db86aabSstevel 			}
1365*3db86aabSstevel 			nintrs++;
1366*3db86aabSstevel 		} /* while */
1367*3db86aabSstevel 	} /* if (pcic_debug) */
1368*3db86aabSstevel #endif
1369*3db86aabSstevel 
1370*3db86aabSstevel 	cv_init(&pcic->pm_cv, NULL, CV_DRIVER, NULL);
1371*3db86aabSstevel 
1372*3db86aabSstevel 	if (!ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
1373*3db86aabSstevel 						"disable-audio", 0))
1374*3db86aabSstevel 		pcic->pc_flags |= PCF_AUDIO;
1375*3db86aabSstevel 
1376*3db86aabSstevel 	if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
1377*3db86aabSstevel 	    "disable-cardbus", 0))
1378*3db86aabSstevel 		pcic->pc_flags &= ~PCF_CARDBUS;
1379*3db86aabSstevel 
1380*3db86aabSstevel 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, PCICPROP_CTL,
1381*3db86aabSstevel 	    typename);
1382*3db86aabSstevel 
1383*3db86aabSstevel 	/*
1384*3db86aabSstevel 	 * Init all socket SMI levels to 0 (no SMI)
1385*3db86aabSstevel 	 */
1386*3db86aabSstevel 	for (i = 0; i < PCIC_MAX_SOCKETS; i++) {
1387*3db86aabSstevel 	    pcic->pc_sockets[i].pcs_smi = 0;
1388*3db86aabSstevel 	    pcic->pc_sockets[i].pcs_debounce_id = 0;
1389*3db86aabSstevel 	    pcic->pc_sockets[i].pcs_pcic = pcic;
1390*3db86aabSstevel 	}
1391*3db86aabSstevel 	pcic->pc_lastreg = -1; /* just to make sure we are in sync */
1392*3db86aabSstevel 
1393*3db86aabSstevel 	/*
1394*3db86aabSstevel 	 * Setup the IRQ handler(s)
1395*3db86aabSstevel 	 */
1396*3db86aabSstevel 	switch (pcic->pc_intr_mode) {
1397*3db86aabSstevel 		int xx;
1398*3db86aabSstevel 	case PCIC_INTR_MODE_ISA:
1399*3db86aabSstevel 	/*
1400*3db86aabSstevel 	 * On a non-PCI bus, we just use whatever SMI IRQ level was
1401*3db86aabSstevel 	 *	specified above, and the IO IRQ levels are allocated
1402*3db86aabSstevel 	 *	dynamically.
1403*3db86aabSstevel 	 */
1404*3db86aabSstevel 		for (xx = 15, smi = 0; xx >= 0; xx--) {
1405*3db86aabSstevel 			if (PCIC_IRQ(xx) &
1406*3db86aabSstevel 			    PCIC_AVAIL_IRQS) {
1407*3db86aabSstevel 				smi = pcmcia_get_intr(dip, xx);
1408*3db86aabSstevel 				if (smi >= 0)
1409*3db86aabSstevel 					break;
1410*3db86aabSstevel 			}
1411*3db86aabSstevel 		}
1412*3db86aabSstevel #if defined(PCIC_DEBUG)
1413*3db86aabSstevel 		if (pcic_debug)
1414*3db86aabSstevel 			cmn_err(CE_NOTE, "\tselected IRQ %d as SMI\n", smi);
1415*3db86aabSstevel #endif
1416*3db86aabSstevel 		/* init to same so share is easy */
1417*3db86aabSstevel 		for (i = 0; i < pcic->pc_numsockets; i++)
1418*3db86aabSstevel 			pcic->pc_sockets[i].pcs_smi = smi;
1419*3db86aabSstevel 		/* any special handling of IRQ levels */
1420*3db86aabSstevel 		if (pcic->pc_flags & PCF_MULT_IRQ) {
1421*3db86aabSstevel 			for (i = 2; i < pcic->pc_numsockets; i++) {
1422*3db86aabSstevel 				if ((i & 1) == 0) {
1423*3db86aabSstevel 					int xx;
1424*3db86aabSstevel 					for (xx = 15, smi = 0; xx >= 0; xx--) {
1425*3db86aabSstevel 						if (PCIC_IRQ(xx) &
1426*3db86aabSstevel 						    PCIC_AVAIL_IRQS) {
1427*3db86aabSstevel 							smi =
1428*3db86aabSstevel 							    pcmcia_get_intr(dip,
1429*3db86aabSstevel 									    xx);
1430*3db86aabSstevel 							if (smi >= 0)
1431*3db86aabSstevel 								break;
1432*3db86aabSstevel 						}
1433*3db86aabSstevel 					}
1434*3db86aabSstevel 				}
1435*3db86aabSstevel 				if (smi >= 0)
1436*3db86aabSstevel 					pcic->pc_sockets[i].pcs_smi = smi;
1437*3db86aabSstevel 			}
1438*3db86aabSstevel 		}
1439*3db86aabSstevel 		pcic->pc_intr_htblp = kmem_alloc(pcic->pc_numsockets *
1440*3db86aabSstevel 		    sizeof (ddi_intr_handle_t), KM_SLEEP);
1441*3db86aabSstevel 		for (i = 0, irqlevel = -1; i < pcic->pc_numsockets; i++) {
1442*3db86aabSstevel 			struct intrspec *ispecp;
1443*3db86aabSstevel 			struct ddi_parent_private_data *pdp;
1444*3db86aabSstevel 
1445*3db86aabSstevel 			if (irqlevel == pcic->pc_sockets[i].pcs_smi)
1446*3db86aabSstevel 				continue;
1447*3db86aabSstevel 			else {
1448*3db86aabSstevel 				irqlevel = pcic->pc_sockets[i].pcs_smi;
1449*3db86aabSstevel 			}
1450*3db86aabSstevel 			/*
1451*3db86aabSstevel 			 * now convert the allocated IRQ into an intrspec
1452*3db86aabSstevel 			 * and ask our parent to add it.  Don't use
1453*3db86aabSstevel 			 * the ddi_add_intr since we don't have a
1454*3db86aabSstevel 			 * default intrspec in all cases.
1455*3db86aabSstevel 			 *
1456*3db86aabSstevel 			 * note: this sort of violates DDI but we don't
1457*3db86aabSstevel 			 *	 get hardware intrspecs for many of the devices.
1458*3db86aabSstevel 			 *	 at the same time, we know how to allocate them
1459*3db86aabSstevel 			 *	 so we do the right thing.
1460*3db86aabSstevel 			 */
1461*3db86aabSstevel 			if (ddi_intr_alloc(dip, &pcic->pc_intr_htblp[i],
1462*3db86aabSstevel 			    DDI_INTR_TYPE_FIXED, 0, 1, &actual,
1463*3db86aabSstevel 			    DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) {
1464*3db86aabSstevel 				cmn_err(CE_WARN, "%s: ddi_intr_alloc failed",
1465*3db86aabSstevel 				    ddi_get_name(dip));
1466*3db86aabSstevel 				goto isa_exit1;
1467*3db86aabSstevel 			}
1468*3db86aabSstevel 
1469*3db86aabSstevel 			/*
1470*3db86aabSstevel 			 * See earlier note:
1471*3db86aabSstevel 			 * Since some devices don't have 'intrspec'
1472*3db86aabSstevel 			 * we make one up in rootnex.
1473*3db86aabSstevel 			 *
1474*3db86aabSstevel 			 * However, it is not properly initialized as
1475*3db86aabSstevel 			 * the data it needs is present in this driver
1476*3db86aabSstevel 			 * and there is no interface to pass that up.
1477*3db86aabSstevel 			 * Specially 'irqlevel' is very important and
1478*3db86aabSstevel 			 * it is part of pcic struct.
1479*3db86aabSstevel 			 *
1480*3db86aabSstevel 			 * Set 'intrspec' up here; otherwise adding the
1481*3db86aabSstevel 			 * interrupt will fail.
1482*3db86aabSstevel 			 */
1483*3db86aabSstevel 			pdp = ddi_get_parent_data(dip);
1484*3db86aabSstevel 			ispecp = (struct intrspec *)&pdp->par_intr[0];
1485*3db86aabSstevel 			ispecp->intrspec_vec = irqlevel;
1486*3db86aabSstevel 			ispecp->intrspec_pri = pcic->pc_irq;
1487*3db86aabSstevel 
1488*3db86aabSstevel 			/* Stay compatible w/ PCMCIA */
1489*3db86aabSstevel 			pcic->pc_pri = (ddi_iblock_cookie_t)
1490*3db86aabSstevel 			    (uintptr_t)pcic->pc_irq;
1491*3db86aabSstevel 			pcic->pc_dcookie.idev_priority =
1492*3db86aabSstevel 			    (uintptr_t)pcic->pc_pri;
1493*3db86aabSstevel 			pcic->pc_dcookie.idev_vector = (ushort_t)irqlevel;
1494*3db86aabSstevel 
1495*3db86aabSstevel 			(void) ddi_intr_set_pri(pcic->pc_intr_htblp[i],
1496*3db86aabSstevel 			    pcic->pc_irq);
1497*3db86aabSstevel 
1498*3db86aabSstevel 			if (i == 0) {
1499*3db86aabSstevel 				mutex_init(&pcic->intr_lock, NULL, MUTEX_DRIVER,
1500*3db86aabSstevel 				    DDI_INTR_PRI(pcic->pc_irq));
1501*3db86aabSstevel 				mutex_init(&pcic->pc_lock, NULL, MUTEX_DRIVER,
1502*3db86aabSstevel 				    NULL);
1503*3db86aabSstevel 			}
1504*3db86aabSstevel 
1505*3db86aabSstevel 			if (ddi_intr_add_handler(pcic->pc_intr_htblp[i],
1506*3db86aabSstevel 			    pcic_intr, (caddr_t)pcic, NULL)) {
1507*3db86aabSstevel 				cmn_err(CE_WARN,
1508*3db86aabSstevel 				    "%s: ddi_intr_add_handler failed",
1509*3db86aabSstevel 				    ddi_get_name(dip));
1510*3db86aabSstevel 				goto isa_exit2;
1511*3db86aabSstevel 			}
1512*3db86aabSstevel 
1513*3db86aabSstevel 			if (ddi_intr_enable(pcic->pc_intr_htblp[i])) {
1514*3db86aabSstevel 				cmn_err(CE_WARN, "%s: ddi_intr_enable failed",
1515*3db86aabSstevel 				    ddi_get_name(dip));
1516*3db86aabSstevel 				for (j = i; j < 0; j--)
1517*3db86aabSstevel 					(void) ddi_intr_remove_handler(
1518*3db86aabSstevel 					    pcic->pc_intr_htblp[j]);
1519*3db86aabSstevel 				goto isa_exit2;
1520*3db86aabSstevel 			}
1521*3db86aabSstevel 		}
1522*3db86aabSstevel 		break;
1523*3db86aabSstevel 	case PCIC_INTR_MODE_PCI_1:
1524*3db86aabSstevel 	case PCIC_INTR_MODE_PCI:
1525*3db86aabSstevel 		/*
1526*3db86aabSstevel 		 * If we're on a PCI bus, we route all interrupts, both SMI
1527*3db86aabSstevel 		 * and IO interrupts, through a single interrupt line.
1528*3db86aabSstevel 		 * Assign the SMI IRQ level to the IO IRQ level here.
1529*3db86aabSstevel 		 */
1530*3db86aabSstevel 		pcic->pc_pci_intr_hdlp = kmem_alloc(sizeof (ddi_intr_handle_t),
1531*3db86aabSstevel 		    KM_SLEEP);
1532*3db86aabSstevel 		if (ddi_intr_alloc(dip, pcic->pc_pci_intr_hdlp,
1533*3db86aabSstevel 		    DDI_INTR_TYPE_FIXED, 0, 1, &actual,
1534*3db86aabSstevel 		    DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS)
1535*3db86aabSstevel 			goto pci_exit1;
1536*3db86aabSstevel 
1537*3db86aabSstevel 		if (ddi_intr_get_pri(pcic->pc_pci_intr_hdlp[0],
1538*3db86aabSstevel 		    &pri) != DDI_SUCCESS) {
1539*3db86aabSstevel 			(void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1540*3db86aabSstevel 			goto pci_exit1;
1541*3db86aabSstevel 		}
1542*3db86aabSstevel 
1543*3db86aabSstevel 		pcic->pc_pri = (void *)(uintptr_t)pri;
1544*3db86aabSstevel 		mutex_init(&pcic->intr_lock, NULL, MUTEX_DRIVER, pcic->pc_pri);
1545*3db86aabSstevel 		mutex_init(&pcic->pc_lock, NULL, MUTEX_DRIVER, NULL);
1546*3db86aabSstevel 
1547*3db86aabSstevel 		if (ddi_intr_add_handler(pcic->pc_pci_intr_hdlp[0],
1548*3db86aabSstevel 		    pcic_intr, (caddr_t)pcic, NULL))
1549*3db86aabSstevel 			goto pci_exit2;
1550*3db86aabSstevel 
1551*3db86aabSstevel 		if (ddi_intr_enable(pcic->pc_pci_intr_hdlp[0])) {
1552*3db86aabSstevel 			(void) ddi_intr_remove_handler(
1553*3db86aabSstevel 			    pcic->pc_pci_intr_hdlp[0]);
1554*3db86aabSstevel 			goto pci_exit2;
1555*3db86aabSstevel 		}
1556*3db86aabSstevel 
1557*3db86aabSstevel 		/* Stay compatible w/ PCMCIA */
1558*3db86aabSstevel 		pcic->pc_dcookie.idev_priority = (ushort_t)pri;
1559*3db86aabSstevel 
1560*3db86aabSstevel 		/* init to same (PCI) so share is easy */
1561*3db86aabSstevel 		for (i = 0; i < pcic->pc_numsockets; i++)
1562*3db86aabSstevel 			pcic->pc_sockets[i].pcs_smi = 0xF; /* any valid */
1563*3db86aabSstevel 		break;
1564*3db86aabSstevel 	}
1565*3db86aabSstevel 
1566*3db86aabSstevel 	/*
1567*3db86aabSstevel 	 * Setup the adapter hardware to some reasonable defaults.
1568*3db86aabSstevel 	 */
1569*3db86aabSstevel 	mutex_enter(&pcic->pc_lock);
1570*3db86aabSstevel 	/* mark the driver state as attached */
1571*3db86aabSstevel 	pcic->pc_flags |= PCF_ATTACHED;
1572*3db86aabSstevel 	pcic_setup_adapter(pcic);
1573*3db86aabSstevel 
1574*3db86aabSstevel 	for (j = 0; j < pcic->pc_numsockets; j++)
1575*3db86aabSstevel 		if (ddi_intr_add_softint(dip,
1576*3db86aabSstevel 		    &pcic->pc_sockets[j].pcs_cd_softint_hdl,
1577*3db86aabSstevel 		    PCIC_SOFTINT_PRI_VAL, pcic_cd_softint,
1578*3db86aabSstevel 		    (caddr_t)&pcic->pc_sockets[j]) != DDI_SUCCESS)
1579*3db86aabSstevel 			goto pci_exit2;
1580*3db86aabSstevel 
1581*3db86aabSstevel #if defined(PCIC_DEBUG)
1582*3db86aabSstevel 	if (pcic_debug)
1583*3db86aabSstevel 		cmn_err(CE_CONT, "type = %s sockets = %d\n", typename,
1584*3db86aabSstevel 						pcic->pc_numsockets);
1585*3db86aabSstevel #endif
1586*3db86aabSstevel 
1587*3db86aabSstevel 	pcic_nexus->an_iblock = &pcic->pc_pri;
1588*3db86aabSstevel 	pcic_nexus->an_idev = &pcic->pc_dcookie;
1589*3db86aabSstevel 
1590*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
1591*3db86aabSstevel 
1592*3db86aabSstevel #ifdef CARDBUS
1593*3db86aabSstevel 	(void) cardbus_enable_cd_intr(dip);
1594*3db86aabSstevel 	if (pcic_debug) {
1595*3db86aabSstevel 
1596*3db86aabSstevel 		cardbus_dump_pci_config(dip);
1597*3db86aabSstevel 		cardbus_dump_socket(dip);
1598*3db86aabSstevel 	}
1599*3db86aabSstevel 
1600*3db86aabSstevel 	/*
1601*3db86aabSstevel 	 * Give the Cardbus misc module a chance to do it's per-adapter
1602*3db86aabSstevel 	 * instance setup. Note that there is no corresponding detach()
1603*3db86aabSstevel 	 * call.
1604*3db86aabSstevel 	 */
1605*3db86aabSstevel 	if (pcic->pc_flags & PCF_CARDBUS)
1606*3db86aabSstevel 		if (cardbus_attach(dip, &pcic_cbnexus_ops) != DDI_SUCCESS) {
1607*3db86aabSstevel 			cmn_err(CE_CONT,
1608*3db86aabSstevel 			    "pcic_attach: cardbus_attach failed\n");
1609*3db86aabSstevel 			goto pci_exit2;
1610*3db86aabSstevel 		}
1611*3db86aabSstevel #endif
1612*3db86aabSstevel 
1613*3db86aabSstevel 	/*
1614*3db86aabSstevel 	 * Give the PCMCIA misc module a chance to do it's per-adapter
1615*3db86aabSstevel 	 *	instance setup.
1616*3db86aabSstevel 	 */
1617*3db86aabSstevel 	if ((i = pcmcia_attach(dip, pcic_nexus)) != DDI_SUCCESS)
1618*3db86aabSstevel 		goto pci_exit2;
1619*3db86aabSstevel 
1620*3db86aabSstevel 	syshw_attach(pcic);
1621*3db86aabSstevel 	if (pcic_maxinst == -1) {
1622*3db86aabSstevel 		/* This assumes that all instances run at the same IPL. */
1623*3db86aabSstevel 		mutex_init(&pcic_deb_mtx, NULL, MUTEX_DRIVER, NULL);
1624*3db86aabSstevel 		cv_init(&pcic_deb_cv, NULL, CV_DRIVER, NULL);
1625*3db86aabSstevel 		pcic_deb_threadid = thread_create((caddr_t)NULL, 0,
1626*3db86aabSstevel 		    pcic_deb_thread, (caddr_t)NULL, 0, &p0, TS_RUN,
1627*3db86aabSstevel 		    v.v_maxsyspri - 2);
1628*3db86aabSstevel 	}
1629*3db86aabSstevel 	pcic_maxinst = max(pcic_maxinst, ddi_get_instance(dip));
1630*3db86aabSstevel 	/*
1631*3db86aabSstevel 	 * Setup a debounce timeout to do an initial card detect
1632*3db86aabSstevel 	 * and enable interrupts.
1633*3db86aabSstevel 	 */
1634*3db86aabSstevel 	for (j = 0; j < pcic->pc_numsockets; j++) {
1635*3db86aabSstevel 		shwp = kmem_alloc(sizeof (syshw_t), KM_SLEEP);
1636*3db86aabSstevel 		if (shwp) {
1637*3db86aabSstevel 			bcopy(&pcic_syshw, shwp, sizeof (pcic_syshw));
1638*3db86aabSstevel 			pcic_syshw.id_string[15]++;
1639*3db86aabSstevel 			pcic->pc_sockets[j].pcs_syshwsig =
1640*3db86aabSstevel 			    syshw_add2map(shwp, pcic_syshw_cardstate,
1641*3db86aabSstevel 				&pcic->pc_sockets[j]);
1642*3db86aabSstevel 		}
1643*3db86aabSstevel 		pcic->pc_sockets[j].pcs_debounce_id =
1644*3db86aabSstevel 		    pcic_add_debqueue(&pcic->pc_sockets[j],
1645*3db86aabSstevel 			drv_usectohz(pcic_debounce_time));
1646*3db86aabSstevel 	}
1647*3db86aabSstevel 
1648*3db86aabSstevel 	return (i);
1649*3db86aabSstevel 
1650*3db86aabSstevel isa_exit2:
1651*3db86aabSstevel 	mutex_destroy(&pcic->intr_lock);
1652*3db86aabSstevel 	mutex_destroy(&pcic->pc_lock);
1653*3db86aabSstevel 	for (j = i; j < 0; j--)
1654*3db86aabSstevel 		(void) ddi_intr_free(pcic->pc_intr_htblp[j]);
1655*3db86aabSstevel isa_exit1:
1656*3db86aabSstevel 	(void) pcmcia_return_intr(dip, pcic->pc_sockets[i].pcs_smi);
1657*3db86aabSstevel 	ddi_regs_map_free(&pcic->handle);
1658*3db86aabSstevel 	if (pcic->pc_flags & PCF_PCIBUS)
1659*3db86aabSstevel 		ddi_regs_map_free(&pcic->cfg_handle);
1660*3db86aabSstevel 	kmem_free(pcic->pc_intr_htblp, pcic->pc_numsockets *
1661*3db86aabSstevel 	    sizeof (ddi_intr_handle_t));
1662*3db86aabSstevel 	kmem_free(pcic, sizeof (pcicdev_t));
1663*3db86aabSstevel 		return (DDI_FAILURE);
1664*3db86aabSstevel 
1665*3db86aabSstevel pci_exit2:
1666*3db86aabSstevel 	mutex_destroy(&pcic->intr_lock);
1667*3db86aabSstevel 	mutex_destroy(&pcic->pc_lock);
1668*3db86aabSstevel 	(void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1669*3db86aabSstevel pci_exit1:
1670*3db86aabSstevel 	ddi_regs_map_free(&pcic->handle);
1671*3db86aabSstevel 	if (pcic->pc_flags & PCF_PCIBUS)
1672*3db86aabSstevel 		ddi_regs_map_free(&pcic->cfg_handle);
1673*3db86aabSstevel 	kmem_free(pcic->pc_pci_intr_hdlp, sizeof (ddi_intr_handle_t));
1674*3db86aabSstevel 	kmem_free(pcic, sizeof (pcicdev_t));
1675*3db86aabSstevel 	return (DDI_FAILURE);
1676*3db86aabSstevel }
1677*3db86aabSstevel 
1678*3db86aabSstevel /*
1679*3db86aabSstevel  * pcic_detach()
1680*3db86aabSstevel  *	request to detach from the system
1681*3db86aabSstevel  */
1682*3db86aabSstevel static int
1683*3db86aabSstevel pcic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1684*3db86aabSstevel {
1685*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
1686*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
1687*3db86aabSstevel 	int i;
1688*3db86aabSstevel 
1689*3db86aabSstevel 	switch (cmd) {
1690*3db86aabSstevel 	case DDI_DETACH:
1691*3db86aabSstevel 		/* don't detach if the nexus still talks to us */
1692*3db86aabSstevel 		if (pcic->pc_callback != NULL)
1693*3db86aabSstevel 			return (DDI_FAILURE);
1694*3db86aabSstevel 		syshw_detach(pcic);
1695*3db86aabSstevel 
1696*3db86aabSstevel 		/* kill off the pm simulation */
1697*3db86aabSstevel 		if (pcic->pc_pmtimer)
1698*3db86aabSstevel 			(void) untimeout(pcic->pc_pmtimer);
1699*3db86aabSstevel 
1700*3db86aabSstevel 		/* turn everything off for all sockets and chips */
1701*3db86aabSstevel 		for (i = 0; i < pcic->pc_numsockets; i++) {
1702*3db86aabSstevel 			if (pcic->pc_sockets[i].pcs_debounce_id)
1703*3db86aabSstevel 				pcic_rm_debqueue(
1704*3db86aabSstevel 				    pcic->pc_sockets[i].pcs_debounce_id);
1705*3db86aabSstevel 			pcic->pc_sockets[i].pcs_debounce_id = 0;
1706*3db86aabSstevel 
1707*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_MANAGEMENT_INT, 0);
1708*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_CARD_DETECT, 0);
1709*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1710*3db86aabSstevel 			/* disable interrupts and put card into RESET */
1711*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_INTERRUPT, 0);
1712*3db86aabSstevel 		}
1713*3db86aabSstevel 		(void) ddi_intr_disable(pcic->pc_pci_intr_hdlp[0]);
1714*3db86aabSstevel 		(void) ddi_intr_remove_handler(pcic->pc_pci_intr_hdlp[0]);
1715*3db86aabSstevel 		(void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1716*3db86aabSstevel 		kmem_free(pcic->pc_pci_intr_hdlp, sizeof (ddi_intr_handle_t));
1717*3db86aabSstevel 		pcic->pc_flags = 0;
1718*3db86aabSstevel 		mutex_destroy(&pcic->pc_lock);
1719*3db86aabSstevel 		mutex_destroy(&pcic->intr_lock);
1720*3db86aabSstevel 		cv_destroy(&pcic->pm_cv);
1721*3db86aabSstevel 		if (pcic->pc_flags & PCF_PCIBUS)
1722*3db86aabSstevel 		    ddi_regs_map_free(&pcic->cfg_handle);
1723*3db86aabSstevel 		if (pcic->handle)
1724*3db86aabSstevel 		    ddi_regs_map_free(&pcic->handle);
1725*3db86aabSstevel 		kmem_free(pcic, sizeof (pcicdev_t));
1726*3db86aabSstevel 		ddi_soft_state_free(pcic_soft_state_p, ddi_get_instance(dip));
1727*3db86aabSstevel 		return (DDI_SUCCESS);
1728*3db86aabSstevel 
1729*3db86aabSstevel 	case DDI_SUSPEND:
1730*3db86aabSstevel 	case DDI_PM_SUSPEND:
1731*3db86aabSstevel 		/*
1732*3db86aabSstevel 		 * we got a suspend event (either real or imagined)
1733*3db86aabSstevel 		 * so notify the nexus proper that all existing cards
1734*3db86aabSstevel 		 * should go away.
1735*3db86aabSstevel 		 */
1736*3db86aabSstevel 		mutex_enter(&pcic->pc_lock);
1737*3db86aabSstevel #ifdef CARDBUS
1738*3db86aabSstevel 		if (pcic->pc_flags & PCF_CARDBUS)
1739*3db86aabSstevel 			for (i = 0; i < pcic->pc_numsockets; i++)
1740*3db86aabSstevel 				if ((pcic->pc_sockets[i].pcs_flags &
1741*3db86aabSstevel 				    (PCS_CARD_PRESENT|PCS_CARD_ISCARDBUS)) ==
1742*3db86aabSstevel 				    (PCS_CARD_PRESENT|PCS_CARD_ISCARDBUS))
1743*3db86aabSstevel 					if (!cardbus_can_suspend(dip)) {
1744*3db86aabSstevel 						mutex_exit(&pcic->pc_lock);
1745*3db86aabSstevel 						cmn_err(CE_WARN,
1746*3db86aabSstevel 						    "Please unconfigure all "
1747*3db86aabSstevel 						    "CardBus devices before "
1748*3db86aabSstevel 						    "attempting to suspend\n");
1749*3db86aabSstevel 						return (DDI_FAILURE);
1750*3db86aabSstevel 					}
1751*3db86aabSstevel #endif
1752*3db86aabSstevel 		/* turn everything off for all sockets and chips */
1753*3db86aabSstevel 		for (i = 0; i < pcic->pc_numsockets; i++) {
1754*3db86aabSstevel 			if (pcic->pc_sockets[i].pcs_debounce_id)
1755*3db86aabSstevel 				pcic_rm_debqueue(
1756*3db86aabSstevel 				    pcic->pc_sockets[i].pcs_debounce_id);
1757*3db86aabSstevel 			pcic->pc_sockets[i].pcs_debounce_id = 0;
1758*3db86aabSstevel 
1759*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_MANAGEMENT_INT, 0);
1760*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_CARD_DETECT, 0);
1761*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1762*3db86aabSstevel 			/* disable interrupts and put card into RESET */
1763*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_INTERRUPT, 0);
1764*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_POWER_CONTROL, 0);
1765*3db86aabSstevel 			if (pcic->pc_flags & PCF_CBPWRCTL)
1766*3db86aabSstevel 				pcic_putcb(pcic, CB_CONTROL, 0);
1767*3db86aabSstevel 
1768*3db86aabSstevel 			if (pcic->pc_sockets[i].pcs_flags & PCS_CARD_PRESENT) {
1769*3db86aabSstevel 				pcic->pc_sockets[i].pcs_flags = PCS_STARTING;
1770*3db86aabSstevel 				/*
1771*3db86aabSstevel 				 * Because we are half way through a save
1772*3db86aabSstevel 				 * all this does is schedule a removal event
1773*3db86aabSstevel 				 * to cs for when the system comes back.
1774*3db86aabSstevel 				 * This doesn't actually matter.
1775*3db86aabSstevel 				 */
1776*3db86aabSstevel 				if (!pcic_do_pcmcia_sr && pcic_do_removal &&
1777*3db86aabSstevel 				    pcic->pc_callback) {
1778*3db86aabSstevel 					PC_CALLBACK(pcic->dip, pcic->pc_cb_arg,
1779*3db86aabSstevel 					    PCE_CARD_REMOVAL,
1780*3db86aabSstevel 					    pcic->pc_sockets[i].pcs_socket);
1781*3db86aabSstevel 				}
1782*3db86aabSstevel 			}
1783*3db86aabSstevel 		}
1784*3db86aabSstevel 
1785*3db86aabSstevel 		pcic->pc_flags |= PCF_SUSPENDED;
1786*3db86aabSstevel 		mutex_exit(&pcic->pc_lock);
1787*3db86aabSstevel 		pcic_delayed_resume_toid = 0;
1788*3db86aabSstevel 
1789*3db86aabSstevel 		/*
1790*3db86aabSstevel 		 * when true power management exists, save the adapter
1791*3db86aabSstevel 		 * state here to enable a recovery.  For the emulation
1792*3db86aabSstevel 		 * condition, the state is gone
1793*3db86aabSstevel 		 */
1794*3db86aabSstevel 		return (DDI_SUCCESS);
1795*3db86aabSstevel 
1796*3db86aabSstevel 	default:
1797*3db86aabSstevel 		return (EINVAL);
1798*3db86aabSstevel 	}
1799*3db86aabSstevel }
1800*3db86aabSstevel 
1801*3db86aabSstevel static uint32_t pcic_tisysctl_onbits = ((1<<27) | (1<<15) | (1<<14));
1802*3db86aabSstevel static uint32_t pcic_tisysctl_offbits = 0;
1803*3db86aabSstevel static uint32_t pcic_default_latency = 0x40;
1804*3db86aabSstevel 
1805*3db86aabSstevel static void
1806*3db86aabSstevel pcic_setup_adapter(pcicdev_t *pcic)
1807*3db86aabSstevel {
1808*3db86aabSstevel 	int i;
1809*3db86aabSstevel 	int value, flags;
1810*3db86aabSstevel 
1811*3db86aabSstevel 	if (pcic->pc_flags & PCF_PCIBUS) {
1812*3db86aabSstevel 		/*
1813*3db86aabSstevel 		 * all PCI-to-PCMCIA bus bridges need memory and I/O enabled
1814*3db86aabSstevel 		 */
1815*3db86aabSstevel 		flags = (PCIC_ENABLE_IO | PCIC_ENABLE_MEM);
1816*3db86aabSstevel 		pcic_iomem_pci_ctl(pcic->cfg_handle, pcic->cfgaddr, flags);
1817*3db86aabSstevel 	}
1818*3db86aabSstevel 	/* enable each socket */
1819*3db86aabSstevel 	for (i = 0; i < pcic->pc_numsockets; i++) {
1820*3db86aabSstevel 		pcic->pc_sockets[i].pcs_flags = 0;
1821*3db86aabSstevel 		/* find out the socket capabilities (I/O vs memory) */
1822*3db86aabSstevel 		value = pcic_getb(pcic, i,
1823*3db86aabSstevel 					PCIC_CHIP_REVISION) & PCIC_REV_ID_MASK;
1824*3db86aabSstevel 		if (value == PCIC_REV_ID_IO || value == PCIC_REV_ID_BOTH)
1825*3db86aabSstevel 			pcic->pc_sockets[i].pcs_flags |= PCS_SOCKET_IO;
1826*3db86aabSstevel 
1827*3db86aabSstevel 		/* disable all windows just in case */
1828*3db86aabSstevel 		pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1829*3db86aabSstevel 
1830*3db86aabSstevel 		switch (pcic->pc_type) {
1831*3db86aabSstevel 			uint32_t cfg32;
1832*3db86aabSstevel 			uint16_t cfg16;
1833*3db86aabSstevel 			uint8_t cfg;
1834*3db86aabSstevel 
1835*3db86aabSstevel 		    /* enable extended registers for Vadem */
1836*3db86aabSstevel 		    case PCIC_VADEM_VG469:
1837*3db86aabSstevel 		    case PCIC_VADEM:
1838*3db86aabSstevel 
1839*3db86aabSstevel 			/* enable card status change interrupt for socket */
1840*3db86aabSstevel 			break;
1841*3db86aabSstevel 
1842*3db86aabSstevel 		    case PCIC_I82365SL:
1843*3db86aabSstevel 			break;
1844*3db86aabSstevel 
1845*3db86aabSstevel 		    case PCIC_CL_PD6710:
1846*3db86aabSstevel 			pcic_putb(pcic, 0, PCIC_MISC_CTL_2, PCIC_LED_ENABLE);
1847*3db86aabSstevel 			break;
1848*3db86aabSstevel 
1849*3db86aabSstevel 			/*
1850*3db86aabSstevel 			 * On the CL_6730, we need to set up the interrupt
1851*3db86aabSstevel 			 * signalling mode (PCI mode) and set the SMI and
1852*3db86aabSstevel 			 * IRQ interrupt lines to PCI/level-mode.
1853*3db86aabSstevel 			 */
1854*3db86aabSstevel 		    case PCIC_CL_PD6730:
1855*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
1856*3db86aabSstevel 			case PCIC_INTR_MODE_PCI_1:
1857*3db86aabSstevel 				clext_reg_write(pcic, i, PCIC_CLEXT_MISC_CTL_3,
1858*3db86aabSstevel 						((clext_reg_read(pcic, i,
1859*3db86aabSstevel 						PCIC_CLEXT_MISC_CTL_3) &
1860*3db86aabSstevel 						~PCIC_CLEXT_INT_PCI) |
1861*3db86aabSstevel 						PCIC_CLEXT_INT_PCI));
1862*3db86aabSstevel 				clext_reg_write(pcic, i, PCIC_CLEXT_EXT_CTL_1,
1863*3db86aabSstevel 						(PCIC_CLEXT_IRQ_LVL_MODE |
1864*3db86aabSstevel 						PCIC_CLEXT_SMI_LVL_MODE));
1865*3db86aabSstevel 				cfg = PCIC_CL_LP_DYN_MODE;
1866*3db86aabSstevel 				pcic_putb(pcic, i, PCIC_MISC_CTL_2, cfg);
1867*3db86aabSstevel 				break;
1868*3db86aabSstevel 			case PCIC_INTR_MODE_ISA:
1869*3db86aabSstevel 				break;
1870*3db86aabSstevel 			}
1871*3db86aabSstevel 			break;
1872*3db86aabSstevel 			/*
1873*3db86aabSstevel 			 * On the CL_6729, we set the SMI and IRQ interrupt
1874*3db86aabSstevel 			 *	lines to PCI/level-mode. as well as program the
1875*3db86aabSstevel 			 *	correct clock speed divider bit.
1876*3db86aabSstevel 			 */
1877*3db86aabSstevel 		    case PCIC_CL_PD6729:
1878*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
1879*3db86aabSstevel 			case PCIC_INTR_MODE_PCI_1:
1880*3db86aabSstevel 				clext_reg_write(pcic, i, PCIC_CLEXT_EXT_CTL_1,
1881*3db86aabSstevel 						(PCIC_CLEXT_IRQ_LVL_MODE |
1882*3db86aabSstevel 						PCIC_CLEXT_SMI_LVL_MODE));
1883*3db86aabSstevel 
1884*3db86aabSstevel 				break;
1885*3db86aabSstevel 			case PCIC_INTR_MODE_ISA:
1886*3db86aabSstevel 				break;
1887*3db86aabSstevel 			}
1888*3db86aabSstevel 			if (pcic->bus_speed > PCIC_PCI_25MHZ && i == 0) {
1889*3db86aabSstevel 				cfg = 0;
1890*3db86aabSstevel 				cfg |= PCIC_CL_TIMER_CLK_DIV;
1891*3db86aabSstevel 				pcic_putb(pcic, i, PCIC_MISC_CTL_2, cfg);
1892*3db86aabSstevel 			}
1893*3db86aabSstevel 			break;
1894*3db86aabSstevel 		    case PCIC_INTEL_i82092:
1895*3db86aabSstevel 			cfg = PCIC_82092_EN_TIMING;
1896*3db86aabSstevel 			if (pcic->bus_speed < PCIC_SYSCLK_33MHZ)
1897*3db86aabSstevel 			    cfg |= PCIC_82092_PCICLK_25MHZ;
1898*3db86aabSstevel 			ddi_put8(pcic->cfg_handle, pcic->cfgaddr +
1899*3db86aabSstevel 						PCIC_82092_PCICON, cfg);
1900*3db86aabSstevel 			break;
1901*3db86aabSstevel 		    case PCIC_TI_PCI1130:
1902*3db86aabSstevel 		    case PCIC_TI_PCI1131:
1903*3db86aabSstevel 		    case PCIC_TI_PCI1250:
1904*3db86aabSstevel 		    case PCIC_TI_PCI1031:
1905*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1906*3db86aabSstevel 					pcic->cfgaddr + PCIC_DEVCTL_REG);
1907*3db86aabSstevel 			cfg &= ~PCIC_DEVCTL_INTR_MASK;
1908*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
1909*3db86aabSstevel 			case PCIC_INTR_MODE_ISA:
1910*3db86aabSstevel 				cfg |= PCIC_DEVCTL_INTR_ISA;
1911*3db86aabSstevel 				break;
1912*3db86aabSstevel 			}
1913*3db86aabSstevel #ifdef PCIC_DEBUG
1914*3db86aabSstevel 			if (pcic_debug) {
1915*3db86aabSstevel 				cmn_err(CE_CONT, "pcic_setup_adapter: "
1916*3db86aabSstevel 				    "write reg 0x%x=%x \n",
1917*3db86aabSstevel 				    PCIC_DEVCTL_REG, cfg);
1918*3db86aabSstevel 			}
1919*3db86aabSstevel #endif
1920*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
1921*3db86aabSstevel 					pcic->cfgaddr + PCIC_DEVCTL_REG,
1922*3db86aabSstevel 					cfg);
1923*3db86aabSstevel 
1924*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1925*3db86aabSstevel 					pcic->cfgaddr + PCIC_CRDCTL_REG);
1926*3db86aabSstevel 			cfg &= ~(PCIC_CRDCTL_PCIINTR|PCIC_CRDCTL_PCICSC|
1927*3db86aabSstevel 					PCIC_CRDCTL_PCIFUNC);
1928*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
1929*3db86aabSstevel 			case PCIC_INTR_MODE_PCI_1:
1930*3db86aabSstevel 				cfg |= PCIC_CRDCTL_PCIINTR |
1931*3db86aabSstevel 					PCIC_CRDCTL_PCICSC |
1932*3db86aabSstevel 					PCIC_CRDCTL_PCIFUNC;
1933*3db86aabSstevel 				pcic->pc_flags |= PCF_USE_SMI;
1934*3db86aabSstevel 				break;
1935*3db86aabSstevel 			}
1936*3db86aabSstevel #ifdef PCIC_DEBUG
1937*3db86aabSstevel 			if (pcic_debug) {
1938*3db86aabSstevel 				cmn_err(CE_CONT, "pcic_setup_adapter: "
1939*3db86aabSstevel 				    " write reg 0x%x=%x \n",
1940*3db86aabSstevel 				    PCIC_CRDCTL_REG, cfg);
1941*3db86aabSstevel 			}
1942*3db86aabSstevel #endif
1943*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
1944*3db86aabSstevel 					pcic->cfgaddr + PCIC_CRDCTL_REG,
1945*3db86aabSstevel 					cfg);
1946*3db86aabSstevel 			break;
1947*3db86aabSstevel 		    case PCIC_TI_PCI1221:
1948*3db86aabSstevel 		    case PCIC_TI_PCI1225:
1949*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1950*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DEVCTL_REG);
1951*3db86aabSstevel 			cfg |= (PCIC_DEVCTL_INTR_DFLT | PCIC_DEVCTL_3VCAPABLE);
1952*3db86aabSstevel #ifdef PCIC_DEBUG
1953*3db86aabSstevel 			if (pcic_debug) {
1954*3db86aabSstevel 				cmn_err(CE_CONT, "pcic_setup_adapter: "
1955*3db86aabSstevel 				    " write reg 0x%x=%x \n",
1956*3db86aabSstevel 				    PCIC_DEVCTL_REG, cfg);
1957*3db86aabSstevel 			}
1958*3db86aabSstevel #endif
1959*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
1960*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DEVCTL_REG, cfg);
1961*3db86aabSstevel 
1962*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1963*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG);
1964*3db86aabSstevel 			if (pcic->pc_type == PCIC_TI_PCI1225) {
1965*3db86aabSstevel 				cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
1966*3db86aabSstevel 			} else {
1967*3db86aabSstevel 				cfg |= PCIC_DIAG_ASYNC;
1968*3db86aabSstevel 			}
1969*3db86aabSstevel 			pcic->pc_flags |= PCF_USE_SMI;
1970*3db86aabSstevel #ifdef PCIC_DEBUG
1971*3db86aabSstevel 			if (pcic_debug) {
1972*3db86aabSstevel 				cmn_err(CE_CONT, "pcic_setup_adapter: "
1973*3db86aabSstevel 				    " write reg 0x%x=%x \n",
1974*3db86aabSstevel 				    PCIC_DIAG_REG, cfg);
1975*3db86aabSstevel 			}
1976*3db86aabSstevel #endif
1977*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
1978*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG, cfg);
1979*3db86aabSstevel 			break;
1980*3db86aabSstevel 		    case PCIC_TI_PCI1520:
1981*3db86aabSstevel 		    case PCIC_TI_VENDOR:
1982*3db86aabSstevel 			if (pcic->pc_intr_mode == PCIC_INTR_MODE_ISA) {
1983*3db86aabSstevel 				cfg = ddi_get8(pcic->cfg_handle,
1984*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
1985*3db86aabSstevel 				cfg |= PCIC_FUN_INT_MOD_ISA;
1986*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
1987*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
1988*3db86aabSstevel 					cfg);
1989*3db86aabSstevel 			}
1990*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
1991*3db86aabSstevel 					pcic->cfgaddr + PCIC_DEVCTL_REG);
1992*3db86aabSstevel 			cfg &= ~PCIC_DEVCTL_INTR_MASK;
1993*3db86aabSstevel 			if (pcic->pc_intr_mode == PCIC_INTR_MODE_ISA)
1994*3db86aabSstevel 				cfg |= PCIC_DEVCTL_INTR_ISA;
1995*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
1996*3db86aabSstevel 					pcic->cfgaddr + PCIC_DEVCTL_REG,
1997*3db86aabSstevel 					cfg);
1998*3db86aabSstevel 
1999*3db86aabSstevel 			/* tie INTA and INTB together */
2000*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
2001*3db86aabSstevel 				(pcic->cfgaddr + PCIC_SYSCTL_REG + 3));
2002*3db86aabSstevel 			cfg |= PCIC_SYSCTL_INTRTIE;
2003*3db86aabSstevel 			ddi_put8(pcic->cfg_handle, (pcic->cfgaddr +
2004*3db86aabSstevel 				PCIC_SYSCTL_REG + 3), cfg);
2005*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
2006*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG);
2007*3db86aabSstevel 			cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
2008*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
2009*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG, cfg);
2010*3db86aabSstevel 			break;
2011*3db86aabSstevel 		    case PCIC_TI_PCI1410:
2012*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle,
2013*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG);
2014*3db86aabSstevel 			cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
2015*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
2016*3db86aabSstevel 			    pcic->cfgaddr + PCIC_DIAG_REG, cfg);
2017*3db86aabSstevel 			break;
2018*3db86aabSstevel 		    case PCIC_TOSHIBA_TOPIC100:
2019*3db86aabSstevel 		    case PCIC_TOSHIBA_TOPIC95:
2020*3db86aabSstevel 		    case PCIC_TOSHIBA_VENDOR:
2021*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle, pcic->cfgaddr +
2022*3db86aabSstevel 				PCIC_TOSHIBA_SLOT_CTL_REG);
2023*3db86aabSstevel 			cfg |= (PCIC_TOSHIBA_SCR_SLOTON |
2024*3db86aabSstevel 				PCIC_TOSHIBA_SCR_SLOTEN);
2025*3db86aabSstevel 			cfg &= (~PCIC_TOSHIBA_SCR_PRT_MASK);
2026*3db86aabSstevel 			cfg |= PCIC_TOSHIBA_SCR_PRT_3E2;
2027*3db86aabSstevel 			ddi_put8(pcic->cfg_handle, pcic->cfgaddr +
2028*3db86aabSstevel 				PCIC_TOSHIBA_SLOT_CTL_REG, cfg);
2029*3db86aabSstevel 			cfg = ddi_get8(pcic->cfg_handle, pcic->cfgaddr +
2030*3db86aabSstevel 				PCIC_TOSHIBA_INTR_CTL_REG);
2031*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
2032*3db86aabSstevel 			case PCIC_INTR_MODE_ISA:
2033*3db86aabSstevel 				cfg &= ~PCIC_TOSHIBA_ICR_SRC;
2034*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
2035*3db86aabSstevel 					pcic->cfgaddr +
2036*3db86aabSstevel 					PCIC_TOSHIBA_INTR_CTL_REG, cfg);
2037*3db86aabSstevel 
2038*3db86aabSstevel 				cfg = ddi_get8(pcic->cfg_handle,
2039*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
2040*3db86aabSstevel 				cfg |= PCIC_FUN_INT_MOD_ISA;
2041*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
2042*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2043*3db86aabSstevel 					cfg);
2044*3db86aabSstevel 				break;
2045*3db86aabSstevel 			case PCIC_INTR_MODE_PCI_1:
2046*3db86aabSstevel 				cfg |= PCIC_TOSHIBA_ICR_SRC;
2047*3db86aabSstevel 				cfg &= (~PCIC_TOSHIBA_ICR_PIN_MASK);
2048*3db86aabSstevel 				cfg |= PCIC_TOSHIBA_ICR_PIN_INTA;
2049*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
2050*3db86aabSstevel 					pcic->cfgaddr +
2051*3db86aabSstevel 					PCIC_TOSHIBA_INTR_CTL_REG, cfg);
2052*3db86aabSstevel 				break;
2053*3db86aabSstevel 			}
2054*3db86aabSstevel 			break;
2055*3db86aabSstevel 		    case PCIC_O2MICRO_VENDOR:
2056*3db86aabSstevel 			cfg32 = ddi_get32(pcic->cfg_handle,
2057*3db86aabSstevel 				(uint32_t *)(pcic->cfgaddr +
2058*3db86aabSstevel 				PCIC_O2MICRO_MISC_CTL));
2059*3db86aabSstevel 			switch (pcic->pc_intr_mode) {
2060*3db86aabSstevel 			case PCIC_INTR_MODE_ISA:
2061*3db86aabSstevel 				cfg32 |= (PCIC_O2MICRO_ISA_LEGACY |
2062*3db86aabSstevel 					PCIC_O2MICRO_INT_MOD_PCI);
2063*3db86aabSstevel 				ddi_put32(pcic->cfg_handle,
2064*3db86aabSstevel 					(uint32_t *)(pcic->cfgaddr +
2065*3db86aabSstevel 					PCIC_O2MICRO_MISC_CTL),
2066*3db86aabSstevel 					cfg32);
2067*3db86aabSstevel 				cfg = ddi_get8(pcic->cfg_handle,
2068*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
2069*3db86aabSstevel 				cfg |= PCIC_FUN_INT_MOD_ISA;
2070*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
2071*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2072*3db86aabSstevel 					cfg);
2073*3db86aabSstevel 				break;
2074*3db86aabSstevel 			case PCIC_INTR_MODE_PCI_1:
2075*3db86aabSstevel 				cfg32 &= ~PCIC_O2MICRO_ISA_LEGACY;
2076*3db86aabSstevel 				cfg32 |= PCIC_O2MICRO_INT_MOD_PCI;
2077*3db86aabSstevel 				ddi_put32(pcic->cfg_handle,
2078*3db86aabSstevel 					(uint32_t *)(pcic->cfgaddr +
2079*3db86aabSstevel 					PCIC_O2MICRO_MISC_CTL),
2080*3db86aabSstevel 					cfg32);
2081*3db86aabSstevel 				break;
2082*3db86aabSstevel 			}
2083*3db86aabSstevel 			break;
2084*3db86aabSstevel 		    case PCIC_RICOH_VENDOR:
2085*3db86aabSstevel 			if (pcic->pc_intr_mode == PCIC_INTR_MODE_ISA) {
2086*3db86aabSstevel 				cfg16 = ddi_get16(pcic->cfg_handle,
2087*3db86aabSstevel 					(uint16_t *)(pcic->cfgaddr +
2088*3db86aabSstevel 					PCIC_RICOH_MISC_CTL_2));
2089*3db86aabSstevel 				cfg16 |= (PCIC_RICOH_CSC_INT_MOD |
2090*3db86aabSstevel 					PCIC_RICOH_FUN_INT_MOD);
2091*3db86aabSstevel 				ddi_put16(pcic->cfg_handle,
2092*3db86aabSstevel 					(uint16_t *)(pcic->cfgaddr +
2093*3db86aabSstevel 					PCIC_RICOH_MISC_CTL_2),
2094*3db86aabSstevel 					cfg16);
2095*3db86aabSstevel 
2096*3db86aabSstevel 				cfg16 = ddi_get16(pcic->cfg_handle,
2097*3db86aabSstevel 					(uint16_t *)(pcic->cfgaddr +
2098*3db86aabSstevel 					PCIC_RICOH_MISC_CTL));
2099*3db86aabSstevel 				cfg16 |= PCIC_RICOH_SIRQ_EN;
2100*3db86aabSstevel 				ddi_put16(pcic->cfg_handle,
2101*3db86aabSstevel 					(uint16_t *)(pcic->cfgaddr +
2102*3db86aabSstevel 					PCIC_RICOH_MISC_CTL),
2103*3db86aabSstevel 					cfg16);
2104*3db86aabSstevel 
2105*3db86aabSstevel 				cfg = ddi_get8(pcic->cfg_handle,
2106*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
2107*3db86aabSstevel 				cfg |= PCIC_FUN_INT_MOD_ISA;
2108*3db86aabSstevel 				ddi_put8(pcic->cfg_handle,
2109*3db86aabSstevel 					pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2110*3db86aabSstevel 					cfg);
2111*3db86aabSstevel 			}
2112*3db86aabSstevel 			break;
2113*3db86aabSstevel 		    default:
2114*3db86aabSstevel 			break;
2115*3db86aabSstevel 		} /* switch */
2116*3db86aabSstevel 
2117*3db86aabSstevel 		/* setup general card status change interrupt */
2118*3db86aabSstevel 		switch (pcic->pc_type) {
2119*3db86aabSstevel 			case PCIC_TI_PCI1225:
2120*3db86aabSstevel 			case PCIC_TI_PCI1221:
2121*3db86aabSstevel 			case PCIC_TI_PCI1031:
2122*3db86aabSstevel 			case PCIC_TI_PCI1520:
2123*3db86aabSstevel 			case PCIC_TI_PCI1410:
2124*3db86aabSstevel 				pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
2125*3db86aabSstevel 				    PCIC_CHANGE_DEFAULT);
2126*3db86aabSstevel 				break;
2127*3db86aabSstevel 			default:
2128*3db86aabSstevel 				if (pcic->pc_intr_mode ==
2129*3db86aabSstevel 					PCIC_INTR_MODE_PCI_1) {
2130*3db86aabSstevel 					pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
2131*3db86aabSstevel 						PCIC_CHANGE_DEFAULT);
2132*3db86aabSstevel 					break;
2133*3db86aabSstevel 				} else {
2134*3db86aabSstevel 					pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
2135*3db86aabSstevel 						PCIC_CHANGE_DEFAULT |
2136*3db86aabSstevel 					(pcic->pc_sockets[i].pcs_smi << 4));
2137*3db86aabSstevel 					break;
2138*3db86aabSstevel 				}
2139*3db86aabSstevel 		}
2140*3db86aabSstevel 
2141*3db86aabSstevel 		pcic->pc_flags |= PCF_INTRENAB;
2142*3db86aabSstevel 
2143*3db86aabSstevel 		/* take card out of RESET */
2144*3db86aabSstevel 		pcic_putb(pcic, i, PCIC_INTERRUPT, PCIC_RESET);
2145*3db86aabSstevel 		/* turn power off and let CS do this */
2146*3db86aabSstevel 		pcic_putb(pcic, i, PCIC_POWER_CONTROL, 0);
2147*3db86aabSstevel 
2148*3db86aabSstevel 		/* final chip specific initialization */
2149*3db86aabSstevel 		switch (pcic->pc_type) {
2150*3db86aabSstevel 		    case PCIC_VADEM:
2151*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_VG_CONTROL,
2152*3db86aabSstevel 					PCIC_VC_DELAYENABLE);
2153*3db86aabSstevel 			pcic->pc_flags |= PCF_DEBOUNCE;
2154*3db86aabSstevel 			/* FALLTHROUGH */
2155*3db86aabSstevel 		    case PCIC_I82365SL:
2156*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_GLOBAL_CONTROL,
2157*3db86aabSstevel 					PCIC_GC_CSC_WRITE);
2158*3db86aabSstevel 			/* clear any pending interrupts */
2159*3db86aabSstevel 			value = pcic_getb(pcic, i, PCIC_CARD_STATUS_CHANGE);
2160*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_CARD_STATUS_CHANGE, value);
2161*3db86aabSstevel 			break;
2162*3db86aabSstevel 		    /* The 82092 uses PCI config space to enable interrupts */
2163*3db86aabSstevel 		    case PCIC_INTEL_i82092:
2164*3db86aabSstevel 			pcic_82092_smiirq_ctl(pcic, i, PCIC_82092_CTL_SMI,
2165*3db86aabSstevel 							PCIC_82092_INT_ENABLE);
2166*3db86aabSstevel 			break;
2167*3db86aabSstevel 		    case PCIC_CL_PD6729:
2168*3db86aabSstevel 			if (pcic->bus_speed >= PCIC_PCI_DEF_SYSCLK && i == 0) {
2169*3db86aabSstevel 				value = pcic_getb(pcic, i, PCIC_MISC_CTL_2);
2170*3db86aabSstevel 				pcic_putb(pcic, i, PCIC_MISC_CTL_2,
2171*3db86aabSstevel 						value | PCIC_CL_TIMER_CLK_DIV);
2172*3db86aabSstevel 			}
2173*3db86aabSstevel 			break;
2174*3db86aabSstevel 		} /* switch */
2175*3db86aabSstevel 
2176*3db86aabSstevel #if defined(PCIC_DEBUG)
2177*3db86aabSstevel 		if (pcic_debug)
2178*3db86aabSstevel 			cmn_err(CE_CONT,
2179*3db86aabSstevel 				"socket %d value=%x, flags = %x (%s)\n",
2180*3db86aabSstevel 				i, value, pcic->pc_sockets[i].pcs_flags,
2181*3db86aabSstevel 				(pcic->pc_sockets[i].pcs_flags &
2182*3db86aabSstevel 					PCS_CARD_PRESENT) ?
2183*3db86aabSstevel 						"card present" : "no card");
2184*3db86aabSstevel #endif
2185*3db86aabSstevel 	}
2186*3db86aabSstevel }
2187*3db86aabSstevel 
2188*3db86aabSstevel /*
2189*3db86aabSstevel  * pcic_intr(caddr_t, caddr_t)
2190*3db86aabSstevel  *	interrupt handler for the PCIC style adapter
2191*3db86aabSstevel  *	handles all basic interrupts and also checks
2192*3db86aabSstevel  *	for status changes and notifies the nexus if
2193*3db86aabSstevel  *	necessary
2194*3db86aabSstevel  *
2195*3db86aabSstevel  *	On PCI bus adapters, also handles all card
2196*3db86aabSstevel  *	IO interrupts.
2197*3db86aabSstevel  */
2198*3db86aabSstevel /*ARGSUSED*/
2199*3db86aabSstevel uint32_t
2200*3db86aabSstevel pcic_intr(caddr_t arg1, caddr_t arg2)
2201*3db86aabSstevel {
2202*3db86aabSstevel 	pcicdev_t *pcic = (pcicdev_t *)arg1;
2203*3db86aabSstevel 	int value = 0, i, ret = DDI_INTR_UNCLAIMED;
2204*3db86aabSstevel 	uint8_t status;
2205*3db86aabSstevel 	uint_t io_ints;
2206*3db86aabSstevel 
2207*3db86aabSstevel #if defined(PCIC_DEBUG)
2208*3db86aabSstevel 	pcic_err(pcic->dip, 0xf,
2209*3db86aabSstevel 		"pcic_intr: enter pc_flags=0x%x PCF_ATTACHED=0x%x"
2210*3db86aabSstevel 		" pc_numsockets=%d \n",
2211*3db86aabSstevel 		pcic->pc_flags, PCF_ATTACHED, pcic->pc_numsockets);
2212*3db86aabSstevel #endif
2213*3db86aabSstevel 
2214*3db86aabSstevel 	if (!(pcic->pc_flags & PCF_ATTACHED))
2215*3db86aabSstevel 	    return (DDI_INTR_UNCLAIMED);
2216*3db86aabSstevel 
2217*3db86aabSstevel 	mutex_enter(&pcic->intr_lock);
2218*3db86aabSstevel 
2219*3db86aabSstevel 	if (pcic->pc_flags & PCF_SUSPENDED) {
2220*3db86aabSstevel 		mutex_exit(&pcic->intr_lock);
2221*3db86aabSstevel 		return (ret);
2222*3db86aabSstevel 	}
2223*3db86aabSstevel 
2224*3db86aabSstevel 	/*
2225*3db86aabSstevel 	 * need to change to only ACK and touch the slot that
2226*3db86aabSstevel 	 * actually caused the interrupt.  Currently everything
2227*3db86aabSstevel 	 * is acked
2228*3db86aabSstevel 	 *
2229*3db86aabSstevel 	 * we need to look at all known sockets to determine
2230*3db86aabSstevel 	 * what might have happened, so step through the list
2231*3db86aabSstevel 	 * of them
2232*3db86aabSstevel 	 */
2233*3db86aabSstevel #ifdef VOYAGER
2234*3db86aabSstevel 	ret = syshw_intr_hi(pcic);
2235*3db86aabSstevel #endif
2236*3db86aabSstevel 
2237*3db86aabSstevel 	/*
2238*3db86aabSstevel 	 * Set the bitmask for IO interrupts to initially include all sockets
2239*3db86aabSstevel 	 */
2240*3db86aabSstevel 	io_ints = (1 << pcic->pc_numsockets) - 1;
2241*3db86aabSstevel 
2242*3db86aabSstevel 	for (i = 0; i < pcic->pc_numsockets; i++) {
2243*3db86aabSstevel 		int card_type;
2244*3db86aabSstevel 		pcic_socket_t *sockp;
2245*3db86aabSstevel 		int value_cb = 0;
2246*3db86aabSstevel 
2247*3db86aabSstevel 		sockp = &pcic->pc_sockets[i];
2248*3db86aabSstevel 		/* get the socket's I/O addresses */
2249*3db86aabSstevel 
2250*3db86aabSstevel 		if (sockp->pcs_flags & PCS_WAITING) {
2251*3db86aabSstevel 			io_ints &= ~(1 << i);
2252*3db86aabSstevel 			continue;
2253*3db86aabSstevel 		}
2254*3db86aabSstevel 
2255*3db86aabSstevel 		if (sockp->pcs_flags & PCS_CARD_IO)
2256*3db86aabSstevel 			card_type = IF_IO;
2257*3db86aabSstevel 		else
2258*3db86aabSstevel 			card_type = IF_MEMORY;
2259*3db86aabSstevel 
2260*3db86aabSstevel 		if (pcic->pc_io_type == PCIC_IO_TYPE_YENTA)
2261*3db86aabSstevel 			value_cb = pcic_getcb(pcic, CB_STATUS_EVENT);
2262*3db86aabSstevel 
2263*3db86aabSstevel 		value = pcic_change(pcic, i);
2264*3db86aabSstevel 
2265*3db86aabSstevel 		if ((value != 0) || (value_cb != 0)) {
2266*3db86aabSstevel 			int x = pcic->pc_cb_arg;
2267*3db86aabSstevel 
2268*3db86aabSstevel 			ret = DDI_INTR_CLAIMED;
2269*3db86aabSstevel 
2270*3db86aabSstevel #if defined(PCIC_DEBUG)
2271*3db86aabSstevel 			pcic_err(pcic->dip, 0x9,
2272*3db86aabSstevel 			    "card_type = %d, value_cb = 0x%x\n",
2273*3db86aabSstevel 			    card_type,
2274*3db86aabSstevel 			    value_cb ? value_cb :
2275*3db86aabSstevel 				pcic_getcb(pcic, CB_STATUS_EVENT));
2276*3db86aabSstevel 			if (pcic_debug)
2277*3db86aabSstevel 				cmn_err(CE_CONT,
2278*3db86aabSstevel 					"\tchange on socket %d (%x)\n", i,
2279*3db86aabSstevel 					value);
2280*3db86aabSstevel #endif
2281*3db86aabSstevel 			/* find out what happened */
2282*3db86aabSstevel 			status = pcic_getb(pcic, i, PCIC_INTERFACE_STATUS);
2283*3db86aabSstevel 
2284*3db86aabSstevel 			/* acknowledge the interrupt */
2285*3db86aabSstevel 			if (value_cb)
2286*3db86aabSstevel 				pcic_putcb(pcic, CB_STATUS_EVENT, value_cb);
2287*3db86aabSstevel 
2288*3db86aabSstevel 			if (value)
2289*3db86aabSstevel 				pcic_putb(pcic, i, PCIC_CARD_STATUS_CHANGE,
2290*3db86aabSstevel 				    value);
2291*3db86aabSstevel 
2292*3db86aabSstevel 			if (pcic->pc_callback == NULL) {
2293*3db86aabSstevel 				/* if not callback handler, nothing to do */
2294*3db86aabSstevel 				continue;
2295*3db86aabSstevel 			}
2296*3db86aabSstevel 
2297*3db86aabSstevel 			/* Card Detect */
2298*3db86aabSstevel 			if (value & PCIC_CD_DETECT ||
2299*3db86aabSstevel 			    value_cb & CB_PS_CCDMASK) {
2300*3db86aabSstevel 				uint8_t irq;
2301*3db86aabSstevel #if defined(PCIC_DEBUG)
2302*3db86aabSstevel 				if (pcic_debug)
2303*3db86aabSstevel 					cmn_err(CE_CONT,
2304*3db86aabSstevel 						"\tcd_detect: status=%x,"
2305*3db86aabSstevel 						" flags=%x\n",
2306*3db86aabSstevel 						status, sockp->pcs_flags);
2307*3db86aabSstevel #else
2308*3db86aabSstevel #ifdef lint
2309*3db86aabSstevel 				if (status == 0)
2310*3db86aabSstevel 				    status++;
2311*3db86aabSstevel #endif
2312*3db86aabSstevel #endif
2313*3db86aabSstevel 				/*
2314*3db86aabSstevel 				 * Turn off all interrupts for this socket here.
2315*3db86aabSstevel 				 */
2316*3db86aabSstevel 				irq = pcic_getb(pcic, sockp->pcs_socket,
2317*3db86aabSstevel 				    PCIC_MANAGEMENT_INT);
2318*3db86aabSstevel 				irq &= ~PCIC_CHANGE_MASK;
2319*3db86aabSstevel 				pcic_putb(pcic, sockp->pcs_socket,
2320*3db86aabSstevel 				    PCIC_MANAGEMENT_INT, irq);
2321*3db86aabSstevel 
2322*3db86aabSstevel 				pcic_putcb(pcic, CB_STATUS_MASK, 0x0);
2323*3db86aabSstevel 
2324*3db86aabSstevel 				if (!sockp->pcs_cd_softint_flg) {
2325*3db86aabSstevel 					sockp->pcs_cd_softint_flg = 1;
2326*3db86aabSstevel 					(void) ddi_intr_trigger_softint(
2327*3db86aabSstevel 					    sockp->pcs_cd_softint_hdl, NULL);
2328*3db86aabSstevel 				}
2329*3db86aabSstevel 
2330*3db86aabSstevel 				io_ints &= ~(1 << i);
2331*3db86aabSstevel 			} /* PCIC_CD_DETECT */
2332*3db86aabSstevel 
2333*3db86aabSstevel 			/* Ready/Change Detect */
2334*3db86aabSstevel 			sockp->pcs_state ^= SBM_RDYBSY;
2335*3db86aabSstevel 			if (card_type == IF_MEMORY && value & PCIC_RD_DETECT) {
2336*3db86aabSstevel 				sockp->pcs_flags |= PCS_READY;
2337*3db86aabSstevel 				PC_CALLBACK(pcic->dip, x, PCE_CARD_READY, i);
2338*3db86aabSstevel 			}
2339*3db86aabSstevel 
2340*3db86aabSstevel 			/* Battery Warn Detect */
2341*3db86aabSstevel 			if (card_type == IF_MEMORY &&
2342*3db86aabSstevel 			    value & PCIC_BW_DETECT &&
2343*3db86aabSstevel 			    !(sockp->pcs_state & SBM_BVD2)) {
2344*3db86aabSstevel 				sockp->pcs_state |= SBM_BVD2;
2345*3db86aabSstevel 				PC_CALLBACK(pcic->dip, x,
2346*3db86aabSstevel 						PCE_CARD_BATTERY_WARN, i);
2347*3db86aabSstevel 			}
2348*3db86aabSstevel 
2349*3db86aabSstevel 			/* Battery Dead Detect */
2350*3db86aabSstevel 			if (value & PCIC_BD_DETECT) {
2351*3db86aabSstevel 				/*
2352*3db86aabSstevel 				 * need to work out event if RI not enabled
2353*3db86aabSstevel 				 * and card_type == IF_IO
2354*3db86aabSstevel 				 */
2355*3db86aabSstevel 				if (card_type == IF_MEMORY &&
2356*3db86aabSstevel 					!(sockp->pcs_state & SBM_BVD1)) {
2357*3db86aabSstevel 					sockp->pcs_state |= SBM_BVD1;
2358*3db86aabSstevel 					PC_CALLBACK(pcic->dip, x,
2359*3db86aabSstevel 							PCE_CARD_BATTERY_DEAD,
2360*3db86aabSstevel 							i);
2361*3db86aabSstevel 				} else {
2362*3db86aabSstevel 					/*
2363*3db86aabSstevel 					 * information in pin replacement
2364*3db86aabSstevel 					 * register if one is available
2365*3db86aabSstevel 					 */
2366*3db86aabSstevel 					PC_CALLBACK(pcic->dip, x,
2367*3db86aabSstevel 							PCE_CARD_STATUS_CHANGE,
2368*3db86aabSstevel 							i);
2369*3db86aabSstevel 				} /* IF_MEMORY */
2370*3db86aabSstevel 			} /* PCIC_BD_DETECT */
2371*3db86aabSstevel 		} /* if pcic_change */
2372*3db86aabSstevel 		/*
2373*3db86aabSstevel 		 * for any controllers that we can detect whether a socket
2374*3db86aabSstevel 		 * had an interrupt for the PC Card, we should sort that out
2375*3db86aabSstevel 		 * here.
2376*3db86aabSstevel 		 */
2377*3db86aabSstevel 	} /* for pc_numsockets */
2378*3db86aabSstevel 
2379*3db86aabSstevel 	/*
2380*3db86aabSstevel 	 * If we're on a PCI bus, we may need to cycle through each IO
2381*3db86aabSstevel 	 *	interrupt handler that is registered since they all
2382*3db86aabSstevel 	 *	share the same interrupt line.
2383*3db86aabSstevel 	 */
2384*3db86aabSstevel 
2385*3db86aabSstevel 
2386*3db86aabSstevel #if defined(PCIC_DEBUG)
2387*3db86aabSstevel 	pcic_err(pcic->dip, 0xf,
2388*3db86aabSstevel 	    "pcic_intr: pc_intr_mode=%d pc_type=%x io_ints=0x%x\n",
2389*3db86aabSstevel 	    pcic->pc_intr_mode, pcic->pc_type, io_ints);
2390*3db86aabSstevel #endif
2391*3db86aabSstevel 
2392*3db86aabSstevel 	switch (pcic->pc_intr_mode) {
2393*3db86aabSstevel 	case PCIC_INTR_MODE_PCI_1:
2394*3db86aabSstevel 		value = ~0;
2395*3db86aabSstevel 		/* fix value if adapter can tell us about I/O intrs */
2396*3db86aabSstevel 		switch (pcic->pc_type) {
2397*3db86aabSstevel 
2398*3db86aabSstevel 		case PCIC_TI_PCI1031:
2399*3db86aabSstevel 		case PCIC_TI_PCI1130:
2400*3db86aabSstevel 		case PCIC_TI_PCI1131:
2401*3db86aabSstevel 		case PCIC_TI_PCI1250:
2402*3db86aabSstevel 		case PCIC_TI_PCI1225:
2403*3db86aabSstevel 		case PCIC_TI_PCI1221:
2404*3db86aabSstevel 		case PCIC_TI_PCI1520:
2405*3db86aabSstevel 		case PCIC_TI_PCI1410:
2406*3db86aabSstevel 		case PCIC_TI_VENDOR:
2407*3db86aabSstevel 			i = ddi_get8(pcic->cfg_handle,
2408*3db86aabSstevel 					pcic->cfgaddr + PCIC_CRDCTL_REG);
2409*3db86aabSstevel 			if (i & PCIC_CRDCTL_IFG)
2410*3db86aabSstevel 				value = 1;
2411*3db86aabSstevel 			else
2412*3db86aabSstevel 				value = 0;
2413*3db86aabSstevel 			i |= PCIC_CRDCTL_IFG;
2414*3db86aabSstevel 			/* clear the condition */
2415*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
2416*3db86aabSstevel 					pcic->cfgaddr + PCIC_CRDCTL_REG, i);
2417*3db86aabSstevel 			break;
2418*3db86aabSstevel 		case PCIC_TOSHIBA_TOPIC100:
2419*3db86aabSstevel 		case PCIC_TOSHIBA_TOPIC95:
2420*3db86aabSstevel 		case PCIC_TOSHIBA_VENDOR:
2421*3db86aabSstevel 		case PCIC_RICOH_VENDOR:
2422*3db86aabSstevel 		case PCIC_O2MICRO_VENDOR:
2423*3db86aabSstevel 		default:
2424*3db86aabSstevel 			value = 1;
2425*3db86aabSstevel 			break;
2426*3db86aabSstevel 		}
2427*3db86aabSstevel 		if (value && pcic_do_io_intr(pcic, value) == DDI_INTR_CLAIMED)
2428*3db86aabSstevel 			ret = DDI_INTR_CLAIMED;
2429*3db86aabSstevel 		break;
2430*3db86aabSstevel 	default:
2431*3db86aabSstevel 		break;
2432*3db86aabSstevel 	}
2433*3db86aabSstevel 
2434*3db86aabSstevel 	mutex_exit(&pcic->intr_lock);
2435*3db86aabSstevel 
2436*3db86aabSstevel #if defined(PCIC_DEBUG)
2437*3db86aabSstevel 	pcic_err(pcic->dip, 0xf,
2438*3db86aabSstevel 	    "pcic_intr: ret=%d value=%d DDI_INTR_CLAIMED=%d\n",
2439*3db86aabSstevel 	    ret, value, DDI_INTR_CLAIMED);
2440*3db86aabSstevel #endif
2441*3db86aabSstevel 
2442*3db86aabSstevel 	return (ret);
2443*3db86aabSstevel }
2444*3db86aabSstevel 
2445*3db86aabSstevel /*
2446*3db86aabSstevel  * pcic_change()
2447*3db86aabSstevel  *	check to see if this socket had a change in state
2448*3db86aabSstevel  *	by checking the status change register
2449*3db86aabSstevel  */
2450*3db86aabSstevel static int
2451*3db86aabSstevel pcic_change(pcicdev_t *pcic, int socket)
2452*3db86aabSstevel {
2453*3db86aabSstevel 	return (pcic_getb(pcic, socket, PCIC_CARD_STATUS_CHANGE));
2454*3db86aabSstevel }
2455*3db86aabSstevel 
2456*3db86aabSstevel /*
2457*3db86aabSstevel  * pcic_do_io_intr - calls client interrupt handlers
2458*3db86aabSstevel  */
2459*3db86aabSstevel static int
2460*3db86aabSstevel pcic_do_io_intr(pcicdev_t *pcic, uint32_t sockets)
2461*3db86aabSstevel {
2462*3db86aabSstevel 	inthandler_t *tmp;
2463*3db86aabSstevel 	int ret = DDI_INTR_UNCLAIMED;
2464*3db86aabSstevel 
2465*3db86aabSstevel #if defined(PCIC_DEBUG)
2466*3db86aabSstevel 	pcic_err(pcic->dip, 0xf,
2467*3db86aabSstevel 		"pcic_do_io_intr: pcic=%p sockets=%d irq_top=%p\n",
2468*3db86aabSstevel 		(void *)pcic, (int)sockets, (void *)pcic->irq_top);
2469*3db86aabSstevel #endif
2470*3db86aabSstevel 
2471*3db86aabSstevel 	if (pcic->irq_top != NULL) {
2472*3db86aabSstevel 	    tmp = pcic->irq_current;
2473*3db86aabSstevel 
2474*3db86aabSstevel 	    do {
2475*3db86aabSstevel 		int cur = pcic->irq_current->socket;
2476*3db86aabSstevel 		pcic_socket_t *sockp =
2477*3db86aabSstevel 				&pcic->pc_sockets[cur];
2478*3db86aabSstevel 
2479*3db86aabSstevel #if defined(PCIC_DEBUG)
2480*3db86aabSstevel 		pcic_err(pcic->dip, 0xf,
2481*3db86aabSstevel 		    "\t pcs_flags=0x%x PCS_CARD_PRESENT=0x%x\n",
2482*3db86aabSstevel 		    sockp->pcs_flags, PCS_CARD_PRESENT);
2483*3db86aabSstevel 		pcic_err(pcic->dip, 0xf,
2484*3db86aabSstevel 		    "\t sockets=%d cur=%d intr=%p arg1=%p "
2485*3db86aabSstevel 		    "arg2=%p\n",
2486*3db86aabSstevel 		    sockets, cur, (void *)pcic->irq_current->intr,
2487*3db86aabSstevel 		    pcic->irq_current->arg1,
2488*3db86aabSstevel 		    pcic->irq_current->arg2);
2489*3db86aabSstevel #endif
2490*3db86aabSstevel 		if (sockp->pcs_flags & PCS_CARD_PRESENT &&
2491*3db86aabSstevel 		    sockets & (1 << cur)) {
2492*3db86aabSstevel 
2493*3db86aabSstevel 			if ((*pcic->irq_current->intr)(pcic->irq_current->arg1,
2494*3db86aabSstevel 			    pcic->irq_current->arg2) == DDI_INTR_CLAIMED)
2495*3db86aabSstevel 				ret = DDI_INTR_CLAIMED;
2496*3db86aabSstevel 
2497*3db86aabSstevel #if defined(PCIC_DEBUG)
2498*3db86aabSstevel 			pcic_err(pcic->dip, 0xf,
2499*3db86aabSstevel 			    "\t ret=%d DDI_INTR_CLAIMED=%d\n",
2500*3db86aabSstevel 			    ret, DDI_INTR_CLAIMED);
2501*3db86aabSstevel #endif
2502*3db86aabSstevel 		}
2503*3db86aabSstevel 
2504*3db86aabSstevel 
2505*3db86aabSstevel 		if ((pcic->irq_current = pcic->irq_current->next) == NULL)
2506*3db86aabSstevel 					pcic->irq_current = pcic->irq_top;
2507*3db86aabSstevel 
2508*3db86aabSstevel 	    } while (pcic->irq_current != tmp);
2509*3db86aabSstevel 
2510*3db86aabSstevel 	    if ((pcic->irq_current = pcic->irq_current->next) == NULL)
2511*3db86aabSstevel 					pcic->irq_current = pcic->irq_top;
2512*3db86aabSstevel 
2513*3db86aabSstevel 	} else {
2514*3db86aabSstevel 		ret = DDI_INTR_UNCLAIMED;
2515*3db86aabSstevel 	}
2516*3db86aabSstevel 
2517*3db86aabSstevel #if defined(PCIC_DEBUG)
2518*3db86aabSstevel 	pcic_err(pcic->dip, 0xf,
2519*3db86aabSstevel 		"pcic_do_io_intr: exit ret=%d DDI_INTR_CLAIMED=%d\n",
2520*3db86aabSstevel 		ret, DDI_INTR_CLAIMED);
2521*3db86aabSstevel #endif
2522*3db86aabSstevel 
2523*3db86aabSstevel 	return (ret);
2524*3db86aabSstevel 
2525*3db86aabSstevel }
2526*3db86aabSstevel 
2527*3db86aabSstevel /*
2528*3db86aabSstevel  * pcic_inquire_adapter()
2529*3db86aabSstevel  *	SocketServices InquireAdapter function
2530*3db86aabSstevel  *	get characteristics of the physical adapter
2531*3db86aabSstevel  */
2532*3db86aabSstevel /*ARGSUSED*/
2533*3db86aabSstevel static int
2534*3db86aabSstevel pcic_inquire_adapter(dev_info_t *dip, inquire_adapter_t *config)
2535*3db86aabSstevel {
2536*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
2537*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
2538*3db86aabSstevel 
2539*3db86aabSstevel 	config->NumSockets = pcic->pc_numsockets;
2540*3db86aabSstevel 	config->NumWindows = pcic->pc_numsockets * PCIC_NUMWINSOCK;
2541*3db86aabSstevel 	config->NumEDCs = 0;
2542*3db86aabSstevel 	config->AdpCaps = 0;
2543*3db86aabSstevel 	config->ActiveHigh = 0;
2544*3db86aabSstevel 	config->ActiveLow = PCIC_AVAIL_IRQS;
2545*3db86aabSstevel 	config->NumPower = pcic->pc_numpower;
2546*3db86aabSstevel 	config->power_entry = pcic->pc_power; /* until we resolve this */
2547*3db86aabSstevel #if defined(PCIC_DEBUG)
2548*3db86aabSstevel 	if (pcic_debug) {
2549*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_inquire_adapter:\n");
2550*3db86aabSstevel 		cmn_err(CE_CONT, "\tNumSockets=%d\n", config->NumSockets);
2551*3db86aabSstevel 		cmn_err(CE_CONT, "\tNumWindows=%d\n", config->NumWindows);
2552*3db86aabSstevel 	}
2553*3db86aabSstevel #endif
2554*3db86aabSstevel 	config->ResourceFlags = 0;
2555*3db86aabSstevel 	switch (pcic->pc_intr_mode) {
2556*3db86aabSstevel 	case PCIC_INTR_MODE_PCI_1:
2557*3db86aabSstevel 		config->ResourceFlags |= RES_OWN_IRQ | RES_IRQ_NEXUS |
2558*3db86aabSstevel 			RES_IRQ_SHAREABLE;
2559*3db86aabSstevel 		break;
2560*3db86aabSstevel 	}
2561*3db86aabSstevel 	return (SUCCESS);
2562*3db86aabSstevel }
2563*3db86aabSstevel 
2564*3db86aabSstevel /*
2565*3db86aabSstevel  * pcic_callback()
2566*3db86aabSstevel  *	The PCMCIA nexus calls us via this function
2567*3db86aabSstevel  *	in order to set the callback function we are
2568*3db86aabSstevel  *	to call the nexus with
2569*3db86aabSstevel  */
2570*3db86aabSstevel /*ARGSUSED*/
2571*3db86aabSstevel static int
2572*3db86aabSstevel pcic_callback(dev_info_t *dip, int (*handler)(), int arg)
2573*3db86aabSstevel {
2574*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
2575*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
2576*3db86aabSstevel 
2577*3db86aabSstevel 	if (handler != NULL) {
2578*3db86aabSstevel 		pcic->pc_callback = handler;
2579*3db86aabSstevel 		pcic->pc_cb_arg  = arg;
2580*3db86aabSstevel 		pcic->pc_flags |= PCF_CALLBACK;
2581*3db86aabSstevel 	} else {
2582*3db86aabSstevel 		pcic->pc_callback = NULL;
2583*3db86aabSstevel 		pcic->pc_cb_arg = 0;
2584*3db86aabSstevel 		pcic->pc_flags &= ~PCF_CALLBACK;
2585*3db86aabSstevel 	}
2586*3db86aabSstevel 	/*
2587*3db86aabSstevel 	 * we're now registered with the nexus
2588*3db86aabSstevel 	 * it is acceptable to do callbacks at this point.
2589*3db86aabSstevel 	 * don't call back from here though since it could block
2590*3db86aabSstevel 	 */
2591*3db86aabSstevel 	return (PC_SUCCESS);
2592*3db86aabSstevel }
2593*3db86aabSstevel 
2594*3db86aabSstevel /*
2595*3db86aabSstevel  * pcic_calc_speed (pcicdev_t *pcic, uint32_t speed)
2596*3db86aabSstevel  *	calculate the speed bits from the specified memory speed
2597*3db86aabSstevel  *	there may be more to do here
2598*3db86aabSstevel  */
2599*3db86aabSstevel 
2600*3db86aabSstevel static int
2601*3db86aabSstevel pcic_calc_speed(pcicdev_t *pcic, uint32_t speed)
2602*3db86aabSstevel {
2603*3db86aabSstevel 	uint32_t wspeed = 1;	/* assume 1 wait state when unknown */
2604*3db86aabSstevel 	uint32_t bspeed = PCIC_ISA_DEF_SYSCLK;
2605*3db86aabSstevel 
2606*3db86aabSstevel 	switch (pcic->pc_type) {
2607*3db86aabSstevel 	    case PCIC_I82365SL:
2608*3db86aabSstevel 	    case PCIC_VADEM:
2609*3db86aabSstevel 	    case PCIC_VADEM_VG469:
2610*3db86aabSstevel 	    default:
2611*3db86aabSstevel 		/* Intel chip wants it in waitstates */
2612*3db86aabSstevel 		wspeed = mhztons(PCIC_ISA_DEF_SYSCLK) * 3;
2613*3db86aabSstevel 		if (speed <= wspeed)
2614*3db86aabSstevel 			wspeed = 0;
2615*3db86aabSstevel 		else if (speed <= (wspeed += mhztons(bspeed)))
2616*3db86aabSstevel 			wspeed = 1;
2617*3db86aabSstevel 		else if (speed <= (wspeed += mhztons(bspeed)))
2618*3db86aabSstevel 			wspeed = 2;
2619*3db86aabSstevel 		else
2620*3db86aabSstevel 			wspeed = 3;
2621*3db86aabSstevel 		wspeed <<= 6; /* put in right bit positions */
2622*3db86aabSstevel 		break;
2623*3db86aabSstevel 
2624*3db86aabSstevel 	    case PCIC_INTEL_i82092:
2625*3db86aabSstevel 		wspeed = SYSMEM_82092_80NS;
2626*3db86aabSstevel 		if (speed > 80)
2627*3db86aabSstevel 		    wspeed = SYSMEM_82092_100NS;
2628*3db86aabSstevel 		if (speed > 100)
2629*3db86aabSstevel 		    wspeed = SYSMEM_82092_150NS;
2630*3db86aabSstevel 		if (speed > 150)
2631*3db86aabSstevel 		    wspeed = SYSMEM_82092_200NS;
2632*3db86aabSstevel 		if (speed > 200)
2633*3db86aabSstevel 		    wspeed = SYSMEM_82092_250NS;
2634*3db86aabSstevel 		if (speed > 250)
2635*3db86aabSstevel 		    wspeed = SYSMEM_82092_600NS;
2636*3db86aabSstevel 		wspeed <<= 5;	/* put in right bit positions */
2637*3db86aabSstevel 		break;
2638*3db86aabSstevel 
2639*3db86aabSstevel 	} /* switch */
2640*3db86aabSstevel 
2641*3db86aabSstevel 	return (wspeed);
2642*3db86aabSstevel }
2643*3db86aabSstevel 
2644*3db86aabSstevel /*
2645*3db86aabSstevel  * These values are taken from the PC Card Standard Electrical Specification.
2646*3db86aabSstevel  * Generally the larger value is taken if 2 are possible.
2647*3db86aabSstevel  */
2648*3db86aabSstevel static struct pcic_card_times {
2649*3db86aabSstevel 	uint16_t cycle;	/* Speed as found in the atribute space of he card. */
2650*3db86aabSstevel 	uint16_t setup;	/* Corresponding address setup time. */
2651*3db86aabSstevel 	uint16_t width;	/* Corresponding width, OE or WE. */
2652*3db86aabSstevel 	uint16_t hold;	/* Corresponding data or address hold time. */
2653*3db86aabSstevel } pcic_card_times[] = {
2654*3db86aabSstevel 
2655*3db86aabSstevel /*
2656*3db86aabSstevel  * Note: The rounded up times for 250, 200 & 150 have been increased
2657*3db86aabSstevel  * due to problems with the 3-Com ethernet cards (pcelx) on UBIIi.
2658*3db86aabSstevel  * See BugID 00663.
2659*3db86aabSstevel  */
2660*3db86aabSstevel 
2661*3db86aabSstevel /*
2662*3db86aabSstevel  * Rounded up times           Original times from
2663*3db86aabSstevel  * that add up to the         the PCMCIA Spec.
2664*3db86aabSstevel  * cycle time.
2665*3db86aabSstevel  */
2666*3db86aabSstevel 	{600, 180, 370, 140},	/* 100, 300,  70 */
2667*3db86aabSstevel 	{400, 120, 300, 90},	/* Made this one up */
2668*3db86aabSstevel 	{250, 100, 190, 70},	/*  30, 150,  30 */
2669*3db86aabSstevel 	{200, 80, 170, 70},	/*  20, 120,  30 */
2670*3db86aabSstevel 	{150, 50, 110, 40},	/*  20,  80,  20 */
2671*3db86aabSstevel 	{100, 40, 80, 40},	/*  10,  60,  15 */
2672*3db86aabSstevel 	{0, 10, 60, 15}		/*  10,  60,  15 */
2673*3db86aabSstevel };
2674*3db86aabSstevel 
2675*3db86aabSstevel /*
2676*3db86aabSstevel  * pcic_set_cdtimers
2677*3db86aabSstevel  *	This is specific to several Cirrus Logic chips
2678*3db86aabSstevel  */
2679*3db86aabSstevel static void
2680*3db86aabSstevel pcic_set_cdtimers(pcicdev_t *pcic, int socket, uint32_t speed, int tset)
2681*3db86aabSstevel {
2682*3db86aabSstevel 	int cmd, set, rec, offset, clk_pulse;
2683*3db86aabSstevel 	struct pcic_card_times *ctp;
2684*3db86aabSstevel 
2685*3db86aabSstevel 	if ((tset == IOMEM_CLTIMER_SET_1) || (tset == SYSMEM_CLTIMER_SET_1))
2686*3db86aabSstevel 		offset = 3;
2687*3db86aabSstevel 	else
2688*3db86aabSstevel 		offset = 0;
2689*3db86aabSstevel 
2690*3db86aabSstevel 	clk_pulse = mhztons(pcic->bus_speed);
2691*3db86aabSstevel 	for (ctp = pcic_card_times; speed < ctp->cycle; ctp++);
2692*3db86aabSstevel 
2693*3db86aabSstevel 	/*
2694*3db86aabSstevel 	 * Add (clk_pulse/2) and an extra 1 to account for rounding errors.
2695*3db86aabSstevel 	 */
2696*3db86aabSstevel 	set = ((ctp->setup + 10 + 1 + (clk_pulse/2))/clk_pulse) - 1;
2697*3db86aabSstevel 	if (set < 0)
2698*3db86aabSstevel 		set = 0;
2699*3db86aabSstevel 
2700*3db86aabSstevel 	cmd = ((ctp->width + 10 + 1 + (clk_pulse/2))/clk_pulse) - 1;
2701*3db86aabSstevel 	if (cmd < 0)
2702*3db86aabSstevel 		cmd = 0;
2703*3db86aabSstevel 
2704*3db86aabSstevel 	rec = ((ctp->hold + 10 + 1 + (clk_pulse/2))/clk_pulse) - 2;
2705*3db86aabSstevel 	if (rec < 0)
2706*3db86aabSstevel 		rec = 0;
2707*3db86aabSstevel 
2708*3db86aabSstevel #if defined(PCIC_DEBUG)
2709*3db86aabSstevel 	pcic_err(pcic->dip, 8, "pcic_set_cdtimers(%d, Timer Set %d)\n"
2710*3db86aabSstevel 	    "ct=%d, cp=%d, cmd=0x%x, setup=0x%x, rec=0x%x\n",
2711*3db86aabSstevel 	    (unsigned)speed, offset == 3 ? 1 : 0,
2712*3db86aabSstevel 	    ctp->cycle, clk_pulse, cmd, set, rec);
2713*3db86aabSstevel #endif
2714*3db86aabSstevel 
2715*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_TIME_COMMAND_0 + offset, cmd);
2716*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_TIME_SETUP_0 + offset, set);
2717*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_TIME_RECOVER_0 + offset, rec);
2718*3db86aabSstevel }
2719*3db86aabSstevel 
2720*3db86aabSstevel /*
2721*3db86aabSstevel  * pcic_set_window
2722*3db86aabSstevel  *	essentially the same as the Socket Services specification
2723*3db86aabSstevel  *	We use socket and not adapter since they are identifiable
2724*3db86aabSstevel  *	but the rest is the same
2725*3db86aabSstevel  *
2726*3db86aabSstevel  *	dip	pcic driver's device information
2727*3db86aabSstevel  *	window	parameters for the request
2728*3db86aabSstevel  */
2729*3db86aabSstevel static int
2730*3db86aabSstevel pcic_set_window(dev_info_t *dip, set_window_t *window)
2731*3db86aabSstevel {
2732*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
2733*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
2734*3db86aabSstevel 	int select;
2735*3db86aabSstevel 	int socket, pages, which, ret;
2736*3db86aabSstevel 	pcic_socket_t *sockp = &pcic->pc_sockets[window->socket];
2737*3db86aabSstevel 	ra_return_t res;
2738*3db86aabSstevel 	ndi_ra_request_t req;
2739*3db86aabSstevel 	uint32_t base = window->base;
2740*3db86aabSstevel 
2741*3db86aabSstevel #if defined(PCIC_DEBUG)
2742*3db86aabSstevel 	if (pcic_debug) {
2743*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_set_window: entered\n");
2744*3db86aabSstevel 		cmn_err(CE_CONT,
2745*3db86aabSstevel 			"\twindow=%d, socket=%d, WindowSize=%d, speed=%d\n",
2746*3db86aabSstevel 			window->window, window->socket, window->WindowSize,
2747*3db86aabSstevel 			window->speed);
2748*3db86aabSstevel 		cmn_err(CE_CONT,
2749*3db86aabSstevel 			"\tbase=%x, state=%x\n", (unsigned)window->base,
2750*3db86aabSstevel 			(unsigned)window->state);
2751*3db86aabSstevel 	}
2752*3db86aabSstevel #endif
2753*3db86aabSstevel 
2754*3db86aabSstevel 	/*
2755*3db86aabSstevel 	 * do some basic sanity checking on what we support
2756*3db86aabSstevel 	 * we don't do paged mode
2757*3db86aabSstevel 	 */
2758*3db86aabSstevel 	if (window->state & WS_PAGED) {
2759*3db86aabSstevel 		cmn_err(CE_WARN, "pcic_set_window: BAD_ATTRIBUTE\n");
2760*3db86aabSstevel 		return (BAD_ATTRIBUTE);
2761*3db86aabSstevel 	}
2762*3db86aabSstevel 
2763*3db86aabSstevel 	/*
2764*3db86aabSstevel 	 * we don't care about previous mappings.
2765*3db86aabSstevel 	 * Card Services will deal with that so don't
2766*3db86aabSstevel 	 * even check
2767*3db86aabSstevel 	 */
2768*3db86aabSstevel 
2769*3db86aabSstevel 	socket = window->socket;
2770*3db86aabSstevel 
2771*3db86aabSstevel 	if (!(window->state & WS_IO)) {
2772*3db86aabSstevel 		int win, tmp;
2773*3db86aabSstevel 		pcs_memwin_t *memp;
2774*3db86aabSstevel #if defined(PCIC_DEBUG)
2775*3db86aabSstevel 		if (pcic_debug)
2776*3db86aabSstevel 			cmn_err(CE_CONT, "\twindow type is memory\n");
2777*3db86aabSstevel #endif
2778*3db86aabSstevel 		/* this is memory window mapping */
2779*3db86aabSstevel 		win = window->window % PCIC_NUMWINSOCK;
2780*3db86aabSstevel 		tmp = window->window / PCIC_NUMWINSOCK;
2781*3db86aabSstevel 
2782*3db86aabSstevel 		/* only windows 2-6 can do memory mapping */
2783*3db86aabSstevel 		if (tmp != window->socket || win < PCIC_IOWINDOWS) {
2784*3db86aabSstevel 			cmn_err(CE_CONT,
2785*3db86aabSstevel 				"\tattempt to map to non-mem window\n");
2786*3db86aabSstevel 			return (BAD_WINDOW);
2787*3db86aabSstevel 		}
2788*3db86aabSstevel 
2789*3db86aabSstevel 		if (window->WindowSize == 0)
2790*3db86aabSstevel 			window->WindowSize = MEM_MIN;
2791*3db86aabSstevel 		else if ((window->WindowSize & (PCIC_PAGE-1)) != 0) {
2792*3db86aabSstevel 			cmn_err(CE_WARN, "pcic_set_window: BAD_SIZE\n");
2793*3db86aabSstevel 			return (BAD_SIZE);
2794*3db86aabSstevel 		}
2795*3db86aabSstevel 
2796*3db86aabSstevel 		mutex_enter(&pcic->pc_lock); /* protect the registers */
2797*3db86aabSstevel 
2798*3db86aabSstevel 		memp = &sockp->pcs_windows[win].mem;
2799*3db86aabSstevel 		memp->pcw_speed = window->speed;
2800*3db86aabSstevel 
2801*3db86aabSstevel 		win -= PCIC_IOWINDOWS; /* put in right range */
2802*3db86aabSstevel 
2803*3db86aabSstevel 		if (window->WindowSize != memp->pcw_len)
2804*3db86aabSstevel 			which = memp->pcw_len;
2805*3db86aabSstevel 		else
2806*3db86aabSstevel 			which = 0;
2807*3db86aabSstevel 
2808*3db86aabSstevel 		if (window->state & WS_ENABLED) {
2809*3db86aabSstevel 			uint32_t wspeed;
2810*3db86aabSstevel #if defined(PCIC_DEBUG)
2811*3db86aabSstevel 			if (pcic_debug) {
2812*3db86aabSstevel 				cmn_err(CE_CONT,
2813*3db86aabSstevel 					"\tbase=%x, win=%d\n", (unsigned)base,
2814*3db86aabSstevel 					win);
2815*3db86aabSstevel 				if (which)
2816*3db86aabSstevel 					cmn_err(CE_CONT,
2817*3db86aabSstevel 						"\tneed to remap window\n");
2818*3db86aabSstevel 			}
2819*3db86aabSstevel #endif
2820*3db86aabSstevel 
2821*3db86aabSstevel 			if (which && (memp->pcw_status & PCW_MAPPED)) {
2822*3db86aabSstevel 				ddi_regs_map_free(&memp->pcw_handle);
2823*3db86aabSstevel 				res.ra_addr_lo = memp->pcw_base;
2824*3db86aabSstevel 				res.ra_len = memp->pcw_len;
2825*3db86aabSstevel 				(void) pcmcia_free_mem(dip, &res);
2826*3db86aabSstevel 				memp->pcw_status &= ~(PCW_MAPPED|PCW_ENABLED);
2827*3db86aabSstevel 				memp->pcw_hostmem = NULL;
2828*3db86aabSstevel 				memp->pcw_base = NULL;
2829*3db86aabSstevel 				memp->pcw_len = 0;
2830*3db86aabSstevel 			}
2831*3db86aabSstevel 
2832*3db86aabSstevel 			which = window->WindowSize >> PAGE_SHIFT;
2833*3db86aabSstevel 
2834*3db86aabSstevel 			if (!(memp->pcw_status & PCW_MAPPED)) {
2835*3db86aabSstevel 				ret = 0;
2836*3db86aabSstevel 
2837*3db86aabSstevel 				memp->pcw_base = base;
2838*3db86aabSstevel 				bzero(&req, sizeof (req));
2839*3db86aabSstevel 				req.ra_len = which << PAGE_SHIFT;
2840*3db86aabSstevel 				req.ra_addr = (uint64_t)memp->pcw_base;
2841*3db86aabSstevel 				req.ra_boundbase = pcic->pc_base;
2842*3db86aabSstevel 				req.ra_boundlen  = pcic->pc_bound;
2843*3db86aabSstevel 				req.ra_flags = (memp->pcw_base ?
2844*3db86aabSstevel 					NDI_RA_ALLOC_SPECIFIED : 0) |
2845*3db86aabSstevel 					NDI_RA_ALLOC_BOUNDED;
2846*3db86aabSstevel 				req.ra_align_mask =
2847*3db86aabSstevel 					(PAGESIZE - 1) | (PCIC_PAGE - 1);
2848*3db86aabSstevel #if defined(PCIC_DEBUG)
2849*3db86aabSstevel 				    pcic_err(dip, 8,
2850*3db86aabSstevel 					    "\tlen 0x%"PRIx64
2851*3db86aabSstevel 					    "addr 0x%"PRIx64"bbase 0x%"PRIx64
2852*3db86aabSstevel 					    " blen 0x%"PRIx64" flags 0x%x"
2853*3db86aabSstevel 					    " algn 0x%"PRIx64"\n",
2854*3db86aabSstevel 					    req.ra_len, req.ra_addr,
2855*3db86aabSstevel 					    req.ra_boundbase,
2856*3db86aabSstevel 					    req.ra_boundlen, req.ra_flags,
2857*3db86aabSstevel 					    req.ra_align_mask);
2858*3db86aabSstevel #endif
2859*3db86aabSstevel 
2860*3db86aabSstevel 				ret = pcmcia_alloc_mem(dip, &req, &res);
2861*3db86aabSstevel 				if (ret == DDI_FAILURE) {
2862*3db86aabSstevel 					mutex_exit(&pcic->pc_lock);
2863*3db86aabSstevel 					cmn_err(CE_WARN,
2864*3db86aabSstevel 					"\tpcmcia_alloc_mem() failed\n");
2865*3db86aabSstevel 					return (BAD_SIZE);
2866*3db86aabSstevel 				}
2867*3db86aabSstevel 				memp->pcw_base = res.ra_addr_lo;
2868*3db86aabSstevel 				base = memp->pcw_base;
2869*3db86aabSstevel 
2870*3db86aabSstevel #if defined(PCIC_DEBUG)
2871*3db86aabSstevel 				if (pcic_debug)
2872*3db86aabSstevel 					cmn_err(CE_CONT,
2873*3db86aabSstevel 						"\tsetwindow: new base=%x\n",
2874*3db86aabSstevel 						(unsigned)memp->pcw_base);
2875*3db86aabSstevel #endif
2876*3db86aabSstevel 				memp->pcw_len = window->WindowSize;
2877*3db86aabSstevel 
2878*3db86aabSstevel 				which = pcmcia_map_reg(pcic->dip,
2879*3db86aabSstevel 						window->child,
2880*3db86aabSstevel 						&res,
2881*3db86aabSstevel 						(uint32_t)(window->state &
2882*3db86aabSstevel 						    0xffff) |
2883*3db86aabSstevel 						    (window->socket << 16),
2884*3db86aabSstevel 						(caddr_t *)&memp->pcw_hostmem,
2885*3db86aabSstevel 						&memp->pcw_handle,
2886*3db86aabSstevel 						&window->attr, NULL);
2887*3db86aabSstevel 
2888*3db86aabSstevel 				if (which != DDI_SUCCESS) {
2889*3db86aabSstevel 
2890*3db86aabSstevel 					cmn_err(CE_WARN, "\tpcmcia_map_reg() "
2891*3db86aabSstevel 						"failed\n");
2892*3db86aabSstevel 
2893*3db86aabSstevel 				    res.ra_addr_lo = memp->pcw_base;
2894*3db86aabSstevel 				    res.ra_len = memp->pcw_len;
2895*3db86aabSstevel 				    (void) pcmcia_free_mem(pcic->dip, &res);
2896*3db86aabSstevel 
2897*3db86aabSstevel 				    mutex_exit(&pcic->pc_lock);
2898*3db86aabSstevel 
2899*3db86aabSstevel 				    return (BAD_WINDOW);
2900*3db86aabSstevel 				}
2901*3db86aabSstevel 				memp->pcw_status |= PCW_MAPPED;
2902*3db86aabSstevel #if defined(PCIC_DEBUG)
2903*3db86aabSstevel 				if (pcic_debug)
2904*3db86aabSstevel 					cmn_err(CE_CONT,
2905*3db86aabSstevel 						"\tmap=%x, hostmem=%p\n",
2906*3db86aabSstevel 						which,
2907*3db86aabSstevel 						(void *)memp->pcw_hostmem);
2908*3db86aabSstevel #endif
2909*3db86aabSstevel 			} else {
2910*3db86aabSstevel 				base = memp->pcw_base;
2911*3db86aabSstevel 			}
2912*3db86aabSstevel 
2913*3db86aabSstevel 			/* report the handle back to caller */
2914*3db86aabSstevel 			window->handle = memp->pcw_handle;
2915*3db86aabSstevel 
2916*3db86aabSstevel #if defined(PCIC_DEBUG)
2917*3db86aabSstevel 			if (pcic_debug) {
2918*3db86aabSstevel 				cmn_err(CE_CONT,
2919*3db86aabSstevel 					"\twindow mapped to %x@%x len=%d\n",
2920*3db86aabSstevel 					(unsigned)window->base,
2921*3db86aabSstevel 					(unsigned)memp->pcw_base,
2922*3db86aabSstevel 					memp->pcw_len);
2923*3db86aabSstevel 			}
2924*3db86aabSstevel #endif
2925*3db86aabSstevel 
2926*3db86aabSstevel 			/* find the register set offset */
2927*3db86aabSstevel 			select = win * PCIC_MEM_1_OFFSET;
2928*3db86aabSstevel #if defined(PCIC_DEBUG)
2929*3db86aabSstevel 			if (pcic_debug)
2930*3db86aabSstevel 				cmn_err(CE_CONT, "\tselect=%x\n", select);
2931*3db86aabSstevel #endif
2932*3db86aabSstevel 
2933*3db86aabSstevel 			/*
2934*3db86aabSstevel 			 * at this point, the register window indicator has
2935*3db86aabSstevel 			 * been converted to be an offset from the first
2936*3db86aabSstevel 			 * set of registers that are used for programming
2937*3db86aabSstevel 			 * the window mapping and the offset used to select
2938*3db86aabSstevel 			 * the correct set of registers to access the
2939*3db86aabSstevel 			 * specified socket.  This allows basing everything
2940*3db86aabSstevel 			 * off the _0 window
2941*3db86aabSstevel 			 */
2942*3db86aabSstevel 
2943*3db86aabSstevel 			/* map the physical page base address */
2944*3db86aabSstevel 			which = (window->state & WS_16BIT) ? SYSMEM_DATA_16 : 0;
2945*3db86aabSstevel 			which |= (window->speed <= MEM_SPEED_MIN) ?
2946*3db86aabSstevel 				SYSMEM_ZERO_WAIT : 0;
2947*3db86aabSstevel 
2948*3db86aabSstevel 			/* need to select register set */
2949*3db86aabSstevel 			select = PCIC_MEM_1_OFFSET * win;
2950*3db86aabSstevel 
2951*3db86aabSstevel 			pcic_putb(pcic, socket,
2952*3db86aabSstevel 					PCIC_SYSMEM_0_STARTLOW + select,
2953*3db86aabSstevel 					SYSMEM_LOW(base));
2954*3db86aabSstevel 			pcic_putb(pcic, socket,
2955*3db86aabSstevel 					PCIC_SYSMEM_0_STARTHI + select,
2956*3db86aabSstevel 					SYSMEM_HIGH(base) | which);
2957*3db86aabSstevel 
2958*3db86aabSstevel 			/*
2959*3db86aabSstevel 			 * Some adapters can decode window addresses greater
2960*3db86aabSstevel 			 * than 16-bits worth, so handle them here.
2961*3db86aabSstevel 			 */
2962*3db86aabSstevel 			switch (pcic->pc_type) {
2963*3db86aabSstevel 			case PCIC_INTEL_i82092:
2964*3db86aabSstevel 				pcic_putb(pcic, socket,
2965*3db86aabSstevel 						PCIC_82092_CPAGE,
2966*3db86aabSstevel 						SYSMEM_EXT(base));
2967*3db86aabSstevel 				break;
2968*3db86aabSstevel 			case PCIC_CL_PD6729:
2969*3db86aabSstevel 			case PCIC_CL_PD6730:
2970*3db86aabSstevel 				clext_reg_write(pcic, socket,
2971*3db86aabSstevel 						PCIC_CLEXT_MMAP0_UA + win,
2972*3db86aabSstevel 						SYSMEM_EXT(base));
2973*3db86aabSstevel 				break;
2974*3db86aabSstevel 			case PCIC_TI_PCI1130:
2975*3db86aabSstevel 				/*
2976*3db86aabSstevel 				 * Note that the TI chip has one upper byte
2977*3db86aabSstevel 				 * per socket so all windows get bound to a
2978*3db86aabSstevel 				 * 16MB segment.  This must be detected and
2979*3db86aabSstevel 				 * handled appropriately.  We can detect that
2980*3db86aabSstevel 				 * it is done by seeing if the pc_base has
2981*3db86aabSstevel 				 * changed and changing when the register
2982*3db86aabSstevel 				 * is first set.  This will force the bounds
2983*3db86aabSstevel 				 * to be correct.
2984*3db86aabSstevel 				 */
2985*3db86aabSstevel 				if (pcic->pc_bound == 0xffffffff) {
2986*3db86aabSstevel 					pcic_putb(pcic, socket,
2987*3db86aabSstevel 						    PCIC_TI_WINDOW_PAGE_PCI,
2988*3db86aabSstevel 						    SYSMEM_EXT(base));
2989*3db86aabSstevel 					pcic->pc_base = SYSMEM_EXT(base) << 24;
2990*3db86aabSstevel 					pcic->pc_bound = 0x1000000;
2991*3db86aabSstevel 				}
2992*3db86aabSstevel 				break;
2993*3db86aabSstevel 			case PCIC_TI_PCI1031:
2994*3db86aabSstevel 			case PCIC_TI_PCI1131:
2995*3db86aabSstevel 			case PCIC_TI_PCI1250:
2996*3db86aabSstevel 			case PCIC_TI_PCI1225:
2997*3db86aabSstevel 			case PCIC_TI_PCI1221:
2998*3db86aabSstevel 			case PCIC_SMC_34C90:
2999*3db86aabSstevel 			case PCIC_CL_PD6832:
3000*3db86aabSstevel 			case PCIC_RICOH_RL5C466:
3001*3db86aabSstevel 			case PCIC_TI_PCI1410:
3002*3db86aabSstevel 			case PCIC_ENE_1410:
3003*3db86aabSstevel 			case PCIC_TI_PCI1510:
3004*3db86aabSstevel 			case PCIC_TI_PCI1520:
3005*3db86aabSstevel 			case PCIC_O2_OZ6912:
3006*3db86aabSstevel 			case PCIC_TI_PCI1420:
3007*3db86aabSstevel 			case PCIC_ENE_1420:
3008*3db86aabSstevel 			case PCIC_TI_VENDOR:
3009*3db86aabSstevel 			case PCIC_TOSHIBA_TOPIC100:
3010*3db86aabSstevel 			case PCIC_TOSHIBA_TOPIC95:
3011*3db86aabSstevel 			case PCIC_TOSHIBA_VENDOR:
3012*3db86aabSstevel 			case PCIC_RICOH_VENDOR:
3013*3db86aabSstevel 			case PCIC_O2MICRO_VENDOR:
3014*3db86aabSstevel 				pcic_putb(pcic, socket,
3015*3db86aabSstevel 						PCIC_YENTA_MEM_PAGE + win,
3016*3db86aabSstevel 						SYSMEM_EXT(base));
3017*3db86aabSstevel 				break;
3018*3db86aabSstevel 			default:
3019*3db86aabSstevel 				cmn_err(CE_NOTE, "pcic_set_window: unknown "
3020*3db86aabSstevel 						"cardbus vendor:0x%X\n",
3021*3db86aabSstevel 						pcic->pc_type);
3022*3db86aabSstevel 				pcic_putb(pcic, socket,
3023*3db86aabSstevel 						PCIC_YENTA_MEM_PAGE + win,
3024*3db86aabSstevel 						SYSMEM_EXT(base));
3025*3db86aabSstevel 
3026*3db86aabSstevel 				break;
3027*3db86aabSstevel 			} /* switch */
3028*3db86aabSstevel 
3029*3db86aabSstevel 			/*
3030*3db86aabSstevel 			 * specify the length of the mapped range
3031*3db86aabSstevel 			 * we convert to pages (rounding up) so that
3032*3db86aabSstevel 			 * the hardware gets the right thing
3033*3db86aabSstevel 			 */
3034*3db86aabSstevel 			pages = (window->WindowSize+PCIC_PAGE-1)/PCIC_PAGE;
3035*3db86aabSstevel 
3036*3db86aabSstevel 			/*
3037*3db86aabSstevel 			 * Setup this window's timing.
3038*3db86aabSstevel 			 */
3039*3db86aabSstevel 			switch (pcic->pc_type) {
3040*3db86aabSstevel 			case PCIC_CL_PD6729:
3041*3db86aabSstevel 			case PCIC_CL_PD6730:
3042*3db86aabSstevel 			case PCIC_CL_PD6710:
3043*3db86aabSstevel 			case PCIC_CL_PD6722:
3044*3db86aabSstevel 				wspeed = SYSMEM_CLTIMER_SET_0;
3045*3db86aabSstevel 				pcic_set_cdtimers(pcic, socket,
3046*3db86aabSstevel 							window->speed,
3047*3db86aabSstevel 							wspeed);
3048*3db86aabSstevel 				break;
3049*3db86aabSstevel 
3050*3db86aabSstevel 			case PCIC_INTEL_i82092:
3051*3db86aabSstevel 			default:
3052*3db86aabSstevel 				wspeed = pcic_calc_speed(pcic, window->speed);
3053*3db86aabSstevel 				break;
3054*3db86aabSstevel 			} /* switch */
3055*3db86aabSstevel 
3056*3db86aabSstevel #if defined(PCIC_DEBUG)
3057*3db86aabSstevel 			if (pcic_debug)
3058*3db86aabSstevel 				cmn_err(CE_CONT,
3059*3db86aabSstevel 					"\twindow %d speed bits = %x for "
3060*3db86aabSstevel 					"%dns\n",
3061*3db86aabSstevel 					win, (unsigned)wspeed, window->speed);
3062*3db86aabSstevel #endif
3063*3db86aabSstevel 
3064*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_SYSMEM_0_STOPLOW + select,
3065*3db86aabSstevel 					SYSMEM_LOW(base +
3066*3db86aabSstevel 						    (pages * PCIC_PAGE)-1));
3067*3db86aabSstevel 
3068*3db86aabSstevel 			wspeed |= SYSMEM_HIGH(base + (pages * PCIC_PAGE)-1);
3069*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_SYSMEM_0_STOPHI + select,
3070*3db86aabSstevel 					wspeed);
3071*3db86aabSstevel 
3072*3db86aabSstevel 			/*
3073*3db86aabSstevel 			 * now map the card's memory pages - we start with page
3074*3db86aabSstevel 			 * 0
3075*3db86aabSstevel 			 * we also default to AM -- set page might change it
3076*3db86aabSstevel 			 */
3077*3db86aabSstevel 			base = memp->pcw_base;
3078*3db86aabSstevel 			pcic_putb(pcic, socket,
3079*3db86aabSstevel 					PCIC_CARDMEM_0_LOW + select,
3080*3db86aabSstevel 					CARDMEM_LOW(0 - (uint32_t)base));
3081*3db86aabSstevel 
3082*3db86aabSstevel 			pcic_putb(pcic, socket,
3083*3db86aabSstevel 					PCIC_CARDMEM_0_HI + select,
3084*3db86aabSstevel 					CARDMEM_HIGH(0 - (uint32_t)base) |
3085*3db86aabSstevel 					CARDMEM_REG_ACTIVE);
3086*3db86aabSstevel 
3087*3db86aabSstevel 			/*
3088*3db86aabSstevel 			 * enable the window even though redundant
3089*3db86aabSstevel 			 * and SetPage may do it again.
3090*3db86aabSstevel 			 */
3091*3db86aabSstevel 			select = pcic_getb(pcic, socket,
3092*3db86aabSstevel 					PCIC_MAPPING_ENABLE);
3093*3db86aabSstevel 			select |= SYSMEM_WINDOW(win);
3094*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE, select);
3095*3db86aabSstevel 			memp->pcw_offset = 0;
3096*3db86aabSstevel 			memp->pcw_status |= PCW_ENABLED;
3097*3db86aabSstevel 		} else {
3098*3db86aabSstevel 			/*
3099*3db86aabSstevel 			 * not only do we unmap the memory, the
3100*3db86aabSstevel 			 * window has been turned off.
3101*3db86aabSstevel 			 */
3102*3db86aabSstevel 			if (which && memp->pcw_status & PCW_MAPPED) {
3103*3db86aabSstevel 				ddi_regs_map_free(&memp->pcw_handle);
3104*3db86aabSstevel 				res.ra_addr_lo = memp->pcw_base;
3105*3db86aabSstevel 				res.ra_len = memp->pcw_len;
3106*3db86aabSstevel 				(void) pcmcia_free_mem(pcic->dip, &res);
3107*3db86aabSstevel 				memp->pcw_hostmem = NULL;
3108*3db86aabSstevel 				memp->pcw_status &= ~PCW_MAPPED;
3109*3db86aabSstevel 			}
3110*3db86aabSstevel 
3111*3db86aabSstevel 			/* disable current mapping */
3112*3db86aabSstevel 			select = pcic_getb(pcic, socket, PCIC_MAPPING_ENABLE);
3113*3db86aabSstevel 			select &= ~SYSMEM_WINDOW(win);
3114*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE, select);
3115*3db86aabSstevel 			memp->pcw_status &= ~PCW_ENABLED;
3116*3db86aabSstevel 		}
3117*3db86aabSstevel 		memp->pcw_len = window->WindowSize;
3118*3db86aabSstevel 		window->handle = memp->pcw_handle;
3119*3db86aabSstevel #if defined(PCIC_DEBUG)
3120*3db86aabSstevel 		if (pcic_debug)
3121*3db86aabSstevel 			xxdmp_all_regs(pcic, window->socket, -1);
3122*3db86aabSstevel #endif
3123*3db86aabSstevel 	} else {
3124*3db86aabSstevel 		/*
3125*3db86aabSstevel 		 * This is a request for an IO window
3126*3db86aabSstevel 		 */
3127*3db86aabSstevel 		int win, tmp;
3128*3db86aabSstevel 		pcs_iowin_t *winp;
3129*3db86aabSstevel 				/* I/O windows */
3130*3db86aabSstevel #if defined(PCIC_DEBUG)
3131*3db86aabSstevel 		if (pcic_debug)
3132*3db86aabSstevel 			cmn_err(CE_CONT, "\twindow type is I/O\n");
3133*3db86aabSstevel #endif
3134*3db86aabSstevel 
3135*3db86aabSstevel 		/* only windows 0 and 1 can do I/O */
3136*3db86aabSstevel 		win = window->window % PCIC_NUMWINSOCK;
3137*3db86aabSstevel 		tmp = window->window / PCIC_NUMWINSOCK;
3138*3db86aabSstevel 
3139*3db86aabSstevel 		if (win >= PCIC_IOWINDOWS || tmp != window->socket) {
3140*3db86aabSstevel 			cmn_err(CE_WARN,
3141*3db86aabSstevel 				"\twindow is out of range (%d)\n",
3142*3db86aabSstevel 				window->window);
3143*3db86aabSstevel 			return (BAD_WINDOW);
3144*3db86aabSstevel 		}
3145*3db86aabSstevel 
3146*3db86aabSstevel 		mutex_enter(&pcic->pc_lock); /* protect the registers */
3147*3db86aabSstevel 
3148*3db86aabSstevel 		winp = &sockp->pcs_windows[win].io;
3149*3db86aabSstevel 		winp->pcw_speed = window->speed;
3150*3db86aabSstevel 		if (window->WindowSize != 1 && window->WindowSize & 1) {
3151*3db86aabSstevel 			/* we don't want an odd-size window */
3152*3db86aabSstevel 			window->WindowSize++;
3153*3db86aabSstevel 		}
3154*3db86aabSstevel 		winp->pcw_len = window->WindowSize;
3155*3db86aabSstevel 
3156*3db86aabSstevel 		if (window->state & WS_ENABLED) {
3157*3db86aabSstevel 			if (winp->pcw_status & PCW_MAPPED) {
3158*3db86aabSstevel 				ddi_regs_map_free(&winp->pcw_handle);
3159*3db86aabSstevel 				res.ra_addr_lo = winp->pcw_base;
3160*3db86aabSstevel 				res.ra_len = winp->pcw_len;
3161*3db86aabSstevel 				(void) pcmcia_free_io(pcic->dip, &res);
3162*3db86aabSstevel 				winp->pcw_status &= ~(PCW_MAPPED|PCW_ENABLED);
3163*3db86aabSstevel 			}
3164*3db86aabSstevel 
3165*3db86aabSstevel 			/*
3166*3db86aabSstevel 			 * if the I/O address wasn't allocated, allocate
3167*3db86aabSstevel 			 *	it now. If it was allocated, it better
3168*3db86aabSstevel 			 *	be free to use.
3169*3db86aabSstevel 			 * The winp->pcw_offset value is set and used
3170*3db86aabSstevel 			 *	later on if the particular adapter
3171*3db86aabSstevel 			 *	that we're running on has the ability
3172*3db86aabSstevel 			 *	to translate IO accesses to the card
3173*3db86aabSstevel 			 *	(such as some adapters  in the Cirrus
3174*3db86aabSstevel 			 *	Logic family).
3175*3db86aabSstevel 			 */
3176*3db86aabSstevel 			winp->pcw_offset = 0;
3177*3db86aabSstevel 
3178*3db86aabSstevel 			/*
3179*3db86aabSstevel 			 * Setup the request parameters for the
3180*3db86aabSstevel 			 *	requested base and length. If
3181*3db86aabSstevel 			 *	we're on an adapter that has
3182*3db86aabSstevel 			 *	IO window offset registers, then
3183*3db86aabSstevel 			 *	we don't need a specific base
3184*3db86aabSstevel 			 *	address, just a length, and then
3185*3db86aabSstevel 			 *	we'll cause the correct IO address
3186*3db86aabSstevel 			 *	to be generated on the socket by
3187*3db86aabSstevel 			 *	setting up the IO window offset
3188*3db86aabSstevel 			 *	registers.
3189*3db86aabSstevel 			 * For adapters that support this capability, we
3190*3db86aabSstevel 			 *	always use the IO window offset registers,
3191*3db86aabSstevel 			 *	even if the passed base/length would be in
3192*3db86aabSstevel 			 *	range.
3193*3db86aabSstevel 			 */
3194*3db86aabSstevel 			base = window->base;
3195*3db86aabSstevel 			bzero(&req, sizeof (req));
3196*3db86aabSstevel 			req.ra_len = window->WindowSize;
3197*3db86aabSstevel 
3198*3db86aabSstevel 			req.ra_addr = (uint64_t)
3199*3db86aabSstevel 				((pcic->pc_flags & PCF_IO_REMAP) ? 0 : base);
3200*3db86aabSstevel 			req.ra_flags = (req.ra_addr) ?
3201*3db86aabSstevel 						NDI_RA_ALLOC_SPECIFIED : 0;
3202*3db86aabSstevel 
3203*3db86aabSstevel 			req.ra_flags |= NDI_RA_ALIGN_SIZE;
3204*3db86aabSstevel 			/* need to rethink this */
3205*3db86aabSstevel 			req.ra_boundbase = pcic->pc_iobase;
3206*3db86aabSstevel 			req.ra_boundlen = pcic->pc_iobound;
3207*3db86aabSstevel 			req.ra_flags |= NDI_RA_ALLOC_BOUNDED;
3208*3db86aabSstevel 
3209*3db86aabSstevel #if defined(PCIC_DEBUG)
3210*3db86aabSstevel 			    pcic_err(dip, 8,
3211*3db86aabSstevel 					"\tlen 0x%"PRIx64" addr 0x%"PRIx64
3212*3db86aabSstevel 					"bbase 0x%"PRIx64
3213*3db86aabSstevel 					"blen 0x%"PRIx64" flags 0x%x algn 0x%"
3214*3db86aabSstevel 					PRIx64"\n",
3215*3db86aabSstevel 					req.ra_len, (uint64_t)req.ra_addr,
3216*3db86aabSstevel 					req.ra_boundbase,
3217*3db86aabSstevel 					req.ra_boundlen, req.ra_flags,
3218*3db86aabSstevel 					req.ra_align_mask);
3219*3db86aabSstevel #endif
3220*3db86aabSstevel 
3221*3db86aabSstevel 			/*
3222*3db86aabSstevel 			 * Try to allocate the space. If we fail this,
3223*3db86aabSstevel 			 *	return the appropriate error depending
3224*3db86aabSstevel 			 *	on whether the caller specified a
3225*3db86aabSstevel 			 *	specific base address or not.
3226*3db86aabSstevel 			 */
3227*3db86aabSstevel 			if (pcmcia_alloc_io(dip, &req, &res) == DDI_FAILURE) {
3228*3db86aabSstevel 				winp->pcw_status &= ~PCW_ENABLED;
3229*3db86aabSstevel 				mutex_exit(&pcic->pc_lock);
3230*3db86aabSstevel 				cmn_err(CE_WARN, "Failed to alloc I/O:\n"
3231*3db86aabSstevel 					"\tlen 0x%" PRIx64 " addr 0x%" PRIx64
3232*3db86aabSstevel 					"bbase 0x%" PRIx64
3233*3db86aabSstevel 					"blen 0x%" PRIx64 "flags 0x%x"
3234*3db86aabSstevel 					"algn 0x%" PRIx64 "\n",
3235*3db86aabSstevel 					req.ra_len, req.ra_addr,
3236*3db86aabSstevel 					req.ra_boundbase,
3237*3db86aabSstevel 					req.ra_boundlen, req.ra_flags,
3238*3db86aabSstevel 					req.ra_align_mask);
3239*3db86aabSstevel 
3240*3db86aabSstevel 				return (base?BAD_BASE:BAD_SIZE);
3241*3db86aabSstevel 			} /* pcmcia_alloc_io */
3242*3db86aabSstevel 
3243*3db86aabSstevel 			/*
3244*3db86aabSstevel 			 * Don't change the original base. Either we use
3245*3db86aabSstevel 			 * the offset registers below (PCF_IO_REMAP is set)
3246*3db86aabSstevel 			 * or it was allocated correctly anyway.
3247*3db86aabSstevel 			 */
3248*3db86aabSstevel 			winp->pcw_base = res.ra_addr_lo;
3249*3db86aabSstevel 
3250*3db86aabSstevel #if defined(PCIC_DEBUG)
3251*3db86aabSstevel 			    pcic_err(dip, 8,
3252*3db86aabSstevel 				    "\tsetwindow: new base=%x orig base 0x%x\n",
3253*3db86aabSstevel 				    (unsigned)winp->pcw_base, base);
3254*3db86aabSstevel #endif
3255*3db86aabSstevel 
3256*3db86aabSstevel 			if ((which = pcmcia_map_reg(pcic->dip,
3257*3db86aabSstevel 						window->child,
3258*3db86aabSstevel 						&res,
3259*3db86aabSstevel 						(uint32_t)(window->state &
3260*3db86aabSstevel 						    0xffff) |
3261*3db86aabSstevel 						    (window->socket << 16),
3262*3db86aabSstevel 						(caddr_t *)&winp->pcw_hostmem,
3263*3db86aabSstevel 						&winp->pcw_handle,
3264*3db86aabSstevel 						&window->attr,
3265*3db86aabSstevel 						base)) != DDI_SUCCESS) {
3266*3db86aabSstevel 
3267*3db86aabSstevel 					cmn_err(CE_WARN, "pcmcia_map_reg()"
3268*3db86aabSstevel 						"failed\n");
3269*3db86aabSstevel 
3270*3db86aabSstevel 				    res.ra_addr_lo = winp->pcw_base;
3271*3db86aabSstevel 				    res.ra_len = winp->pcw_len;
3272*3db86aabSstevel 				    (void) pcmcia_free_io(pcic->dip, &res);
3273*3db86aabSstevel 
3274*3db86aabSstevel 				    mutex_exit(&pcic->pc_lock);
3275*3db86aabSstevel 				    return (BAD_WINDOW);
3276*3db86aabSstevel 			}
3277*3db86aabSstevel 
3278*3db86aabSstevel 			window->handle = winp->pcw_handle;
3279*3db86aabSstevel 			winp->pcw_status |= PCW_MAPPED;
3280*3db86aabSstevel 
3281*3db86aabSstevel 			/* find the register set offset */
3282*3db86aabSstevel 			select = win * PCIC_IO_OFFSET;
3283*3db86aabSstevel 
3284*3db86aabSstevel #if defined(PCIC_DEBUG)
3285*3db86aabSstevel 			if (pcic_debug) {
3286*3db86aabSstevel 				cmn_err(CE_CONT,
3287*3db86aabSstevel 					"\tenable: window=%d, select=%x, "
3288*3db86aabSstevel 					"base=%x, handle=%p\n",
3289*3db86aabSstevel 					win, select,
3290*3db86aabSstevel 					(unsigned)window->base,
3291*3db86aabSstevel 					(void *)window->handle);
3292*3db86aabSstevel 			}
3293*3db86aabSstevel #endif
3294*3db86aabSstevel 			/*
3295*3db86aabSstevel 			 * at this point, the register window indicator has
3296*3db86aabSstevel 			 * been converted to be an offset from the first
3297*3db86aabSstevel 			 * set of registers that are used for programming
3298*3db86aabSstevel 			 * the window mapping and the offset used to select
3299*3db86aabSstevel 			 * the correct set of registers to access the
3300*3db86aabSstevel 			 * specified socket.  This allows basing everything
3301*3db86aabSstevel 			 * off the _0 window
3302*3db86aabSstevel 			 */
3303*3db86aabSstevel 
3304*3db86aabSstevel 			/* map the I/O base in */
3305*3db86aabSstevel 			pcic_putb(pcic, socket,
3306*3db86aabSstevel 					PCIC_IO_ADDR_0_STARTLOW + select,
3307*3db86aabSstevel 					LOW_BYTE((uint32_t)winp->pcw_base));
3308*3db86aabSstevel 			pcic_putb(pcic, socket,
3309*3db86aabSstevel 					PCIC_IO_ADDR_0_STARTHI + select,
3310*3db86aabSstevel 					HIGH_BYTE((uint32_t)winp->pcw_base));
3311*3db86aabSstevel 
3312*3db86aabSstevel 			pcic_putb(pcic, socket,
3313*3db86aabSstevel 					PCIC_IO_ADDR_0_STOPLOW + select,
3314*3db86aabSstevel 					LOW_BYTE((uint32_t)winp->pcw_base +
3315*3db86aabSstevel 						window->WindowSize - 1));
3316*3db86aabSstevel 			pcic_putb(pcic, socket,
3317*3db86aabSstevel 					PCIC_IO_ADDR_0_STOPHI + select,
3318*3db86aabSstevel 					HIGH_BYTE((uint32_t)winp->pcw_base +
3319*3db86aabSstevel 						window->WindowSize - 1));
3320*3db86aabSstevel 
3321*3db86aabSstevel 			/*
3322*3db86aabSstevel 			 * We've got the requested IO space, now see if we
3323*3db86aabSstevel 			 *	need to adjust the IO window offset registers
3324*3db86aabSstevel 			 *	so that the correct IO address is generated
3325*3db86aabSstevel 			 *	at the socket. If this window doesn't have
3326*3db86aabSstevel 			 *	this capability, then we're all done setting
3327*3db86aabSstevel 			 *	up the IO resources.
3328*3db86aabSstevel 			 */
3329*3db86aabSstevel 			if (pcic->pc_flags & PCF_IO_REMAP) {
3330*3db86aabSstevel 
3331*3db86aabSstevel 
3332*3db86aabSstevel 				/*
3333*3db86aabSstevel 				 * Note that only 16 bits are used to program
3334*3db86aabSstevel 				 * the registers but leave 32 bits on pcw_offset
3335*3db86aabSstevel 				 * so that we can generate the original base
3336*3db86aabSstevel 				 * in get_window()
3337*3db86aabSstevel 				 */
3338*3db86aabSstevel 				winp->pcw_offset = (base - winp->pcw_base);
3339*3db86aabSstevel 
3340*3db86aabSstevel 				pcic_putb(pcic, socket,
3341*3db86aabSstevel 					PCIC_IO_OFFSET_LOW +
3342*3db86aabSstevel 					(win * PCIC_IO_OFFSET_OFFSET),
3343*3db86aabSstevel 					winp->pcw_offset & 0x0ff);
3344*3db86aabSstevel 				pcic_putb(pcic, socket,
3345*3db86aabSstevel 					PCIC_IO_OFFSET_HI +
3346*3db86aabSstevel 					(win * PCIC_IO_OFFSET_OFFSET),
3347*3db86aabSstevel 					(winp->pcw_offset >> 8) & 0x0ff);
3348*3db86aabSstevel 
3349*3db86aabSstevel 			} /* PCF_IO_REMAP */
3350*3db86aabSstevel 
3351*3db86aabSstevel 			/* now get the other details (size, etc) right */
3352*3db86aabSstevel 
3353*3db86aabSstevel 			/*
3354*3db86aabSstevel 			 * Set the data size control bits here. Most of the
3355*3db86aabSstevel 			 *	adapters will ignore IOMEM_16BIT when
3356*3db86aabSstevel 			 *	IOMEM_IOCS16 is set, except for the Intel
3357*3db86aabSstevel 			 *	82092, which only pays attention to the
3358*3db86aabSstevel 			 *	IOMEM_16BIT bit. Sigh... Intel can't even
3359*3db86aabSstevel 			 *	make a proper clone of their own chip.
3360*3db86aabSstevel 			 * The 82092 also apparently can't set the timing
3361*3db86aabSstevel 			 *	of I/O windows.
3362*3db86aabSstevel 			 */
3363*3db86aabSstevel 			which = (window->state & WS_16BIT) ?
3364*3db86aabSstevel 					(IOMEM_16BIT | IOMEM_IOCS16) : 0;
3365*3db86aabSstevel 
3366*3db86aabSstevel 			switch (pcic->pc_type) {
3367*3db86aabSstevel 			case PCIC_CL_PD6729:
3368*3db86aabSstevel 			case PCIC_CL_PD6730:
3369*3db86aabSstevel 			case PCIC_CL_PD6710:
3370*3db86aabSstevel 			case PCIC_CL_PD6722:
3371*3db86aabSstevel 			case PCIC_CL_PD6832:
3372*3db86aabSstevel 				/*
3373*3db86aabSstevel 				 * Select Timer Set 1 - this will take
3374*3db86aabSstevel 				 *	effect when the PCIC_IO_CONTROL
3375*3db86aabSstevel 				 *	register is written to later on;
3376*3db86aabSstevel 				 *	the call to pcic_set_cdtimers
3377*3db86aabSstevel 				 *	just sets up the timer itself.
3378*3db86aabSstevel 				 */
3379*3db86aabSstevel 				which |= IOMEM_CLTIMER_SET_1;
3380*3db86aabSstevel 				pcic_set_cdtimers(pcic, socket,
3381*3db86aabSstevel 							window->speed,
3382*3db86aabSstevel 							IOMEM_CLTIMER_SET_1);
3383*3db86aabSstevel 				which |= IOMEM_IOCS16;
3384*3db86aabSstevel 				break;
3385*3db86aabSstevel 			case PCIC_TI_PCI1031:
3386*3db86aabSstevel 
3387*3db86aabSstevel 				if (window->state & WS_16BIT)
3388*3db86aabSstevel 				    which |= IOMEM_WAIT16;
3389*3db86aabSstevel 
3390*3db86aabSstevel 				break;
3391*3db86aabSstevel 			case PCIC_TI_PCI1130:
3392*3db86aabSstevel 
3393*3db86aabSstevel 				if (window->state & WS_16BIT)
3394*3db86aabSstevel 				    which |= IOMEM_WAIT16;
3395*3db86aabSstevel 
3396*3db86aabSstevel 				break;
3397*3db86aabSstevel 			case PCIC_INTEL_i82092:
3398*3db86aabSstevel 				break;
3399*3db86aabSstevel 			default:
3400*3db86aabSstevel 				if (window->speed >
3401*3db86aabSstevel 						mhztons(pcic->bus_speed) * 3)
3402*3db86aabSstevel 				    which |= IOMEM_WAIT16;
3403*3db86aabSstevel #ifdef notdef
3404*3db86aabSstevel 				if (window->speed <
3405*3db86aabSstevel 						mhztons(pcic->bus_speed) * 6)
3406*3db86aabSstevel 				    which |= IOMEM_ZERO_WAIT;
3407*3db86aabSstevel #endif
3408*3db86aabSstevel 				break;
3409*3db86aabSstevel 			} /* switch (pc_type) */
3410*3db86aabSstevel 
3411*3db86aabSstevel 			/*
3412*3db86aabSstevel 			 * Setup the data width and timing
3413*3db86aabSstevel 			 */
3414*3db86aabSstevel 			select = pcic_getb(pcic, socket, PCIC_IO_CONTROL);
3415*3db86aabSstevel 			select &= ~(PCIC_IO_WIN_MASK << (win * 4));
3416*3db86aabSstevel 			select |= IOMEM_SETWIN(win, which);
3417*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_IO_CONTROL, select);
3418*3db86aabSstevel 
3419*3db86aabSstevel 			/*
3420*3db86aabSstevel 			 * Enable the IO window
3421*3db86aabSstevel 			 */
3422*3db86aabSstevel 			select = pcic_getb(pcic, socket, PCIC_MAPPING_ENABLE);
3423*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE,
3424*3db86aabSstevel 						select | IOMEM_WINDOW(win));
3425*3db86aabSstevel 
3426*3db86aabSstevel 			winp->pcw_status |= PCW_ENABLED;
3427*3db86aabSstevel 
3428*3db86aabSstevel #if defined(PCIC_DEBUG)
3429*3db86aabSstevel 			if (pcic_debug) {
3430*3db86aabSstevel 				cmn_err(CE_CONT,
3431*3db86aabSstevel 					"\twhich = %x, select = %x (%x)\n",
3432*3db86aabSstevel 					which, select,
3433*3db86aabSstevel 					IOMEM_SETWIN(win, which));
3434*3db86aabSstevel 				xxdmp_all_regs(pcic, window->socket * 0x40, 24);
3435*3db86aabSstevel 			}
3436*3db86aabSstevel #endif
3437*3db86aabSstevel 		} else {
3438*3db86aabSstevel 			/*
3439*3db86aabSstevel 			 * not only do we unmap the IO space, the
3440*3db86aabSstevel 			 * window has been turned off.
3441*3db86aabSstevel 			 */
3442*3db86aabSstevel 			if (winp->pcw_status & PCW_MAPPED) {
3443*3db86aabSstevel 				ddi_regs_map_free(&winp->pcw_handle);
3444*3db86aabSstevel 				res.ra_addr_lo = winp->pcw_base;
3445*3db86aabSstevel 				res.ra_len = winp->pcw_len;
3446*3db86aabSstevel 				(void) pcmcia_free_io(pcic->dip, &res);
3447*3db86aabSstevel 				winp->pcw_status &= ~PCW_MAPPED;
3448*3db86aabSstevel 			}
3449*3db86aabSstevel 
3450*3db86aabSstevel 			/* disable current mapping */
3451*3db86aabSstevel 			select = pcic_getb(pcic, socket,
3452*3db86aabSstevel 						PCIC_MAPPING_ENABLE);
3453*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE,
3454*3db86aabSstevel 					select &= ~IOMEM_WINDOW(win));
3455*3db86aabSstevel 			winp->pcw_status &= ~PCW_ENABLED;
3456*3db86aabSstevel 
3457*3db86aabSstevel 			winp->pcw_base = 0;
3458*3db86aabSstevel 			winp->pcw_len = 0;
3459*3db86aabSstevel 			winp->pcw_offset = 0;
3460*3db86aabSstevel 			window->base = 0;
3461*3db86aabSstevel 			/* now make sure we don't accidentally re-enable */
3462*3db86aabSstevel 			/* find the register set offset */
3463*3db86aabSstevel 			select = win * PCIC_IO_OFFSET;
3464*3db86aabSstevel 			pcic_putb(pcic, socket,
3465*3db86aabSstevel 					PCIC_IO_ADDR_0_STARTLOW + select, 0);
3466*3db86aabSstevel 			pcic_putb(pcic, socket,
3467*3db86aabSstevel 					PCIC_IO_ADDR_0_STARTHI + select, 0);
3468*3db86aabSstevel 			pcic_putb(pcic, socket,
3469*3db86aabSstevel 					PCIC_IO_ADDR_0_STOPLOW + select, 0);
3470*3db86aabSstevel 			pcic_putb(pcic, socket,
3471*3db86aabSstevel 					PCIC_IO_ADDR_0_STOPHI + select, 0);
3472*3db86aabSstevel 		}
3473*3db86aabSstevel 	}
3474*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
3475*3db86aabSstevel 
3476*3db86aabSstevel 	return (SUCCESS);
3477*3db86aabSstevel }
3478*3db86aabSstevel 
3479*3db86aabSstevel /*
3480*3db86aabSstevel  * pcic_card_state()
3481*3db86aabSstevel  *	compute the instantaneous Card State information
3482*3db86aabSstevel  */
3483*3db86aabSstevel static int
3484*3db86aabSstevel pcic_card_state(pcicdev_t *pcic, pcic_socket_t *sockp)
3485*3db86aabSstevel {
3486*3db86aabSstevel 	int value, result;
3487*3db86aabSstevel #if defined(PCIC_DEBUG)
3488*3db86aabSstevel 	int orig_value;
3489*3db86aabSstevel #endif
3490*3db86aabSstevel 
3491*3db86aabSstevel 	mutex_enter(&pcic->pc_lock); /* protect the registers */
3492*3db86aabSstevel 
3493*3db86aabSstevel 	value = pcic_getb(pcic, sockp->pcs_socket, PCIC_INTERFACE_STATUS);
3494*3db86aabSstevel 
3495*3db86aabSstevel #if defined(PCIC_DEBUG)
3496*3db86aabSstevel 	orig_value = value;
3497*3db86aabSstevel 	if (pcic_debug >= 8)
3498*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_card_state(%p) if status = %b for %d\n",
3499*3db86aabSstevel 			(void *)sockp,
3500*3db86aabSstevel 			value,
3501*3db86aabSstevel 			"\020\1BVD1\2BVD2\3CD1\4CD2\5WP\6RDY\7PWR\10~GPI",
3502*3db86aabSstevel 			sockp->pcs_socket);
3503*3db86aabSstevel #endif
3504*3db86aabSstevel 	/*
3505*3db86aabSstevel 	 * Lie to socket services if we are not ready.
3506*3db86aabSstevel 	 * This is when we are starting up or during debounce timeouts
3507*3db86aabSstevel 	 * or if the card is a cardbus card.
3508*3db86aabSstevel 	 */
3509*3db86aabSstevel 	if (!(sockp->pcs_flags & (PCS_STARTING|PCS_CARD_ISCARDBUS)) &&
3510*3db86aabSstevel 	    !sockp->pcs_debounce_id &&
3511*3db86aabSstevel 	    (value & PCIC_ISTAT_CD_MASK) == PCIC_CD_PRESENT_OK) {
3512*3db86aabSstevel 		result = SBM_CD;
3513*3db86aabSstevel 
3514*3db86aabSstevel 		if (value & PCIC_WRITE_PROTECT || !(value & PCIC_POWER_ON))
3515*3db86aabSstevel 			result |= SBM_WP;
3516*3db86aabSstevel 		if (value & PCIC_POWER_ON) {
3517*3db86aabSstevel 			if (value & PCIC_READY)
3518*3db86aabSstevel 				result |= SBM_RDYBSY;
3519*3db86aabSstevel 			value = (~value) & (PCIC_BVD1 | PCIC_BVD2);
3520*3db86aabSstevel 			if (value & PCIC_BVD1)
3521*3db86aabSstevel 				result |= SBM_BVD1;
3522*3db86aabSstevel 			if (value & PCIC_BVD2)
3523*3db86aabSstevel 				result |= SBM_BVD2;
3524*3db86aabSstevel 		}
3525*3db86aabSstevel 	} else
3526*3db86aabSstevel 		result = 0;
3527*3db86aabSstevel 
3528*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
3529*3db86aabSstevel 
3530*3db86aabSstevel #if defined(PCIC_DEBUG)
3531*3db86aabSstevel 	pcic_err(pcic->dip, 8,
3532*3db86aabSstevel 	    "pcic_card_state(%p) if status = %b for %d (rval=0x%x)\n",
3533*3db86aabSstevel 	    (void *) sockp, orig_value,
3534*3db86aabSstevel 	    "\020\1BVD1\2BVD2\3CD1\4CD2\5WP\6RDY\7PWR\10~GPI",
3535*3db86aabSstevel 	    sockp->pcs_socket, result);
3536*3db86aabSstevel #endif
3537*3db86aabSstevel 
3538*3db86aabSstevel 	return (result);
3539*3db86aabSstevel }
3540*3db86aabSstevel 
3541*3db86aabSstevel /*
3542*3db86aabSstevel  * pcic_set_page()
3543*3db86aabSstevel  *	SocketServices SetPage function
3544*3db86aabSstevel  *	set the page of PC Card memory that should be in the mapped
3545*3db86aabSstevel  *	window
3546*3db86aabSstevel  */
3547*3db86aabSstevel /*ARGSUSED*/
3548*3db86aabSstevel static int
3549*3db86aabSstevel pcic_set_page(dev_info_t *dip, set_page_t *page)
3550*3db86aabSstevel {
3551*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
3552*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
3553*3db86aabSstevel 	int select;
3554*3db86aabSstevel 	int which, socket, window;
3555*3db86aabSstevel 	uint32_t base;
3556*3db86aabSstevel 	pcs_memwin_t *memp;
3557*3db86aabSstevel 
3558*3db86aabSstevel 	/* get real socket/window numbers */
3559*3db86aabSstevel 	window = page->window % PCIC_NUMWINSOCK;
3560*3db86aabSstevel 	socket = page->window / PCIC_NUMWINSOCK;
3561*3db86aabSstevel 
3562*3db86aabSstevel #if defined(PCIC_DEBUG)
3563*3db86aabSstevel 	if (pcic_debug) {
3564*3db86aabSstevel 		cmn_err(CE_CONT,
3565*3db86aabSstevel 			"pcic_set_page: window=%d, socket=%d, page=%d\n",
3566*3db86aabSstevel 			window, socket, page->page);
3567*3db86aabSstevel 	}
3568*3db86aabSstevel #endif
3569*3db86aabSstevel 	/* only windows 2-6 work on memory */
3570*3db86aabSstevel 	if (window < PCIC_IOWINDOWS)
3571*3db86aabSstevel 		return (BAD_WINDOW);
3572*3db86aabSstevel 
3573*3db86aabSstevel 	/* only one page supported (but any size) */
3574*3db86aabSstevel 	if (page->page != 0)
3575*3db86aabSstevel 		return (BAD_PAGE);
3576*3db86aabSstevel 
3577*3db86aabSstevel 	mutex_enter(&pcic->pc_lock); /* protect the registers */
3578*3db86aabSstevel 
3579*3db86aabSstevel 	memp = &pcic->pc_sockets[socket].pcs_windows[window].mem;
3580*3db86aabSstevel 	window -= PCIC_IOWINDOWS;
3581*3db86aabSstevel 
3582*3db86aabSstevel #if defined(PCIC_DEBUG)
3583*3db86aabSstevel 	if (pcic_debug)
3584*3db86aabSstevel 		cmn_err(CE_CONT, "\tpcw_base=%x, pcw_hostmem=%p, pcw_len=%x\n",
3585*3db86aabSstevel 			(uint32_t)memp->pcw_base,
3586*3db86aabSstevel 			(void *)memp->pcw_hostmem, memp->pcw_len);
3587*3db86aabSstevel #endif
3588*3db86aabSstevel 
3589*3db86aabSstevel 	/* window must be enabled */
3590*3db86aabSstevel 	if (!(memp->pcw_status & PCW_ENABLED))
3591*3db86aabSstevel 		return (BAD_ATTRIBUTE);
3592*3db86aabSstevel 
3593*3db86aabSstevel 	/* find the register set offset */
3594*3db86aabSstevel 	select = window * PCIC_MEM_1_OFFSET;
3595*3db86aabSstevel #if defined(PCIC_DEBUG)
3596*3db86aabSstevel 	if (pcic_debug)
3597*3db86aabSstevel 		cmn_err(CE_CONT, "\tselect=%x\n", select);
3598*3db86aabSstevel #endif
3599*3db86aabSstevel 
3600*3db86aabSstevel 	/*
3601*3db86aabSstevel 	 * now map the card's memory pages - we start with page 0
3602*3db86aabSstevel 	 */
3603*3db86aabSstevel 
3604*3db86aabSstevel 	which = 0;		/* assume simple case */
3605*3db86aabSstevel 	if (page->state & PS_ATTRIBUTE) {
3606*3db86aabSstevel 		which |= CARDMEM_REG_ACTIVE;
3607*3db86aabSstevel 		memp->pcw_status |= PCW_ATTRIBUTE;
3608*3db86aabSstevel 	} else {
3609*3db86aabSstevel 		memp->pcw_status &= ~PCW_ATTRIBUTE;
3610*3db86aabSstevel 	}
3611*3db86aabSstevel 
3612*3db86aabSstevel 	/*
3613*3db86aabSstevel 	 * if caller says Write Protect, enforce it.
3614*3db86aabSstevel 	 */
3615*3db86aabSstevel 	if (page->state & PS_WP) {
3616*3db86aabSstevel 		which |= CARDMEM_WRITE_PROTECT;
3617*3db86aabSstevel 		memp->pcw_status |= PCW_WP;
3618*3db86aabSstevel 	} else {
3619*3db86aabSstevel 		memp->pcw_status &= ~PCW_WP;
3620*3db86aabSstevel 	}
3621*3db86aabSstevel #if defined(PCIC_DEBUG)
3622*3db86aabSstevel 	if (pcic_debug) {
3623*3db86aabSstevel 		cmn_err(CE_CONT, "\tmemory type = %s\n",
3624*3db86aabSstevel 			(which & CARDMEM_REG_ACTIVE) ? "attribute" : "common");
3625*3db86aabSstevel 		if (which & CARDMEM_WRITE_PROTECT)
3626*3db86aabSstevel 			cmn_err(CE_CONT, "\twrite protect\n");
3627*3db86aabSstevel 		cmn_err(CE_CONT, "\tpage offset=%x pcw_base=%x (%x)\n",
3628*3db86aabSstevel 			(unsigned)page->offset,
3629*3db86aabSstevel 			(unsigned)memp->pcw_base,
3630*3db86aabSstevel 			(int)page->offset - (int)memp->pcw_base & 0xffffff);
3631*3db86aabSstevel 	}
3632*3db86aabSstevel #endif
3633*3db86aabSstevel 	/* address computation based on 64MB range and not larger */
3634*3db86aabSstevel 	base = (uint32_t)memp->pcw_base & 0x3ffffff;
3635*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_CARDMEM_0_LOW + select,
3636*3db86aabSstevel 	    CARDMEM_LOW((int)page->offset - (int)base));
3637*3db86aabSstevel 	(void) pcic_getb(pcic, socket, PCIC_CARDMEM_0_LOW + select);
3638*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_CARDMEM_0_HI + select,
3639*3db86aabSstevel 	    CARDMEM_HIGH((int)page->offset - base) | which);
3640*3db86aabSstevel 	(void) pcic_getb(pcic, socket, PCIC_CARDMEM_0_HI + select);
3641*3db86aabSstevel 
3642*3db86aabSstevel 	/*
3643*3db86aabSstevel 	 * while not really necessary, this just makes sure
3644*3db86aabSstevel 	 * nothing turned the window off behind our backs
3645*3db86aabSstevel 	 */
3646*3db86aabSstevel 	which = pcic_getb(pcic, socket, PCIC_MAPPING_ENABLE);
3647*3db86aabSstevel 	which |= SYSMEM_WINDOW(window);
3648*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE, which);
3649*3db86aabSstevel 	(void) pcic_getb(pcic, socket, PCIC_MAPPING_ENABLE);
3650*3db86aabSstevel 
3651*3db86aabSstevel 	memp->pcw_offset = (off_t)page->offset;
3652*3db86aabSstevel 
3653*3db86aabSstevel #if defined(PCIC_DEBUG)
3654*3db86aabSstevel 	if (pcic_debug) {
3655*3db86aabSstevel 		cmn_err(CE_CONT, "\tbase=%p, *base=%x\n",
3656*3db86aabSstevel 			(void *)memp->pcw_hostmem,
3657*3db86aabSstevel 			(uint32_t)*memp->pcw_hostmem);
3658*3db86aabSstevel 
3659*3db86aabSstevel 		xxdmp_all_regs(pcic, socket, -1);
3660*3db86aabSstevel 
3661*3db86aabSstevel 		cmn_err(CE_CONT, "\tbase=%p, *base=%x\n",
3662*3db86aabSstevel 			(void *)memp->pcw_hostmem,
3663*3db86aabSstevel 			(uint32_t)*memp->pcw_hostmem);
3664*3db86aabSstevel 	}
3665*3db86aabSstevel #endif
3666*3db86aabSstevel 
3667*3db86aabSstevel 	if (which & PCW_ATTRIBUTE)
3668*3db86aabSstevel 		pcic_mswait(pcic, socket, 2);
3669*3db86aabSstevel 
3670*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
3671*3db86aabSstevel 
3672*3db86aabSstevel 	return (SUCCESS);
3673*3db86aabSstevel }
3674*3db86aabSstevel 
3675*3db86aabSstevel /*
3676*3db86aabSstevel  * pcic_set_vcc_level()
3677*3db86aabSstevel  *
3678*3db86aabSstevel  *	set voltage based on adapter information
3679*3db86aabSstevel  *
3680*3db86aabSstevel  *	this routine implements a limited solution for support of 3.3v cards.
3681*3db86aabSstevel  *	the general solution, which would fully support the pcmcia spec
3682*3db86aabSstevel  *	as far as allowing client drivers to request which voltage levels
3683*3db86aabSstevel  *	to be set, requires more framework support and driver changes - ess
3684*3db86aabSstevel  */
3685*3db86aabSstevel static int
3686*3db86aabSstevel pcic_set_vcc_level(pcicdev_t *pcic, set_socket_t *socket)
3687*3db86aabSstevel {
3688*3db86aabSstevel 	uint32_t socket_present_state;
3689*3db86aabSstevel 
3690*3db86aabSstevel #if defined(PCIC_DEBUG)
3691*3db86aabSstevel 	if (pcic_debug) {
3692*3db86aabSstevel 		cmn_err(CE_CONT,
3693*3db86aabSstevel 			"pcic_set_vcc_level(pcic=%p, VccLevel=%d)\n",
3694*3db86aabSstevel 			(void *)pcic, socket->VccLevel);
3695*3db86aabSstevel 	}
3696*3db86aabSstevel #endif
3697*3db86aabSstevel 
3698*3db86aabSstevel 	/*
3699*3db86aabSstevel 	 * check VccLevel
3700*3db86aabSstevel 	 * if this is zero, power is being turned off
3701*3db86aabSstevel 	 * if it is non-zero, power is being turned on.
3702*3db86aabSstevel 	 */
3703*3db86aabSstevel 	if (socket->VccLevel == 0) {
3704*3db86aabSstevel 		return (0);
3705*3db86aabSstevel 	}
3706*3db86aabSstevel 
3707*3db86aabSstevel 	/*
3708*3db86aabSstevel 	 * range checking for sanity's sake
3709*3db86aabSstevel 	 */
3710*3db86aabSstevel 	if (socket->VccLevel >= pcic->pc_numpower) {
3711*3db86aabSstevel 		return (BAD_VCC);
3712*3db86aabSstevel 	}
3713*3db86aabSstevel 
3714*3db86aabSstevel 	switch (pcic->pc_io_type) {
3715*3db86aabSstevel 	/*
3716*3db86aabSstevel 	 * Yenta-compliant adapters have vcc info in the extended registers
3717*3db86aabSstevel 	 * Other adapters can be added as needed, but the 'default' case
3718*3db86aabSstevel 	 * has been left as it was previously so as not to break existing
3719*3db86aabSstevel 	 * adapters.
3720*3db86aabSstevel 	 */
3721*3db86aabSstevel 	case PCIC_IO_TYPE_YENTA:
3722*3db86aabSstevel 		/*
3723*3db86aabSstevel 		 * Here we ignore the VccLevel passed in and read the
3724*3db86aabSstevel 		 * card type from the adapter socket present state register
3725*3db86aabSstevel 		 */
3726*3db86aabSstevel 		socket_present_state =
3727*3db86aabSstevel 			ddi_get32(pcic->handle, (uint32_t *)(pcic->ioaddr +
3728*3db86aabSstevel 				PCIC_PRESENT_STATE_REG));
3729*3db86aabSstevel #if defined(PCIC_DEBUG)
3730*3db86aabSstevel 		if (pcic_debug) {
3731*3db86aabSstevel 			cmn_err(CE_CONT,
3732*3db86aabSstevel 				"socket present state = 0x%x\n",
3733*3db86aabSstevel 				socket_present_state);
3734*3db86aabSstevel 		}
3735*3db86aabSstevel #endif
3736*3db86aabSstevel 		switch (socket_present_state & PCIC_VCC_MASK) {
3737*3db86aabSstevel 			case PCIC_VCC_3VCARD:
3738*3db86aabSstevel 				/* fall through */
3739*3db86aabSstevel 			case PCIC_VCC_3VCARD|PCIC_VCC_5VCARD:
3740*3db86aabSstevel 				socket->VccLevel = PCIC_VCC_3VLEVEL;
3741*3db86aabSstevel 				return
3742*3db86aabSstevel 				    (POWER_3VCARD_ENABLE|POWER_OUTPUT_ENABLE);
3743*3db86aabSstevel 			case PCIC_VCC_5VCARD:
3744*3db86aabSstevel 				socket->VccLevel = PCIC_VCC_5VLEVEL;
3745*3db86aabSstevel 				return
3746*3db86aabSstevel 				    (POWER_CARD_ENABLE|POWER_OUTPUT_ENABLE);
3747*3db86aabSstevel 			default:
3748*3db86aabSstevel 				/*
3749*3db86aabSstevel 				 * if no card is present, this can be the
3750*3db86aabSstevel 				 * case of a client making a SetSocket call
3751*3db86aabSstevel 				 * after card removal. In this case we return
3752*3db86aabSstevel 				 * the current power level
3753*3db86aabSstevel 				 */
3754*3db86aabSstevel 				return ((unsigned)ddi_get8(pcic->handle,
3755*3db86aabSstevel 				    pcic->ioaddr + CB_R2_OFFSET +
3756*3db86aabSstevel 					PCIC_POWER_CONTROL));
3757*3db86aabSstevel 		}
3758*3db86aabSstevel 
3759*3db86aabSstevel 	default:
3760*3db86aabSstevel 
3761*3db86aabSstevel 		switch (socket->VccLevel) {
3762*3db86aabSstevel 		case PCIC_VCC_3VLEVEL:
3763*3db86aabSstevel 			return (BAD_VCC);
3764*3db86aabSstevel 		case PCIC_VCC_5VLEVEL:
3765*3db86aabSstevel 			/* enable Vcc */
3766*3db86aabSstevel 			return (POWER_CARD_ENABLE|POWER_OUTPUT_ENABLE);
3767*3db86aabSstevel 		default:
3768*3db86aabSstevel 			return (BAD_VCC);
3769*3db86aabSstevel 		}
3770*3db86aabSstevel 	}
3771*3db86aabSstevel }
3772*3db86aabSstevel 
3773*3db86aabSstevel 
3774*3db86aabSstevel /*
3775*3db86aabSstevel  * pcic_set_socket()
3776*3db86aabSstevel  *	Socket Services SetSocket call
3777*3db86aabSstevel  *	sets basic socket configuration
3778*3db86aabSstevel  */
3779*3db86aabSstevel static int
3780*3db86aabSstevel pcic_set_socket(dev_info_t *dip, set_socket_t *socket)
3781*3db86aabSstevel {
3782*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
3783*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
3784*3db86aabSstevel 	pcic_socket_t *sockp = &pcic->pc_sockets[socket->socket];
3785*3db86aabSstevel 	int irq, interrupt, mirq;
3786*3db86aabSstevel 	int powerlevel = 0;
3787*3db86aabSstevel 	int ind, value, orig_pwrctl;
3788*3db86aabSstevel 
3789*3db86aabSstevel #if defined(PCIC_DEBUG)
3790*3db86aabSstevel 	if (pcic_debug) {
3791*3db86aabSstevel 		cmn_err(CE_CONT,
3792*3db86aabSstevel 		    "pcic_set_socket(dip=%p, socket=%d)"
3793*3db86aabSstevel 		    " Vcc=%d Vpp1=%d Vpp2=%d\n", (void *)dip,
3794*3db86aabSstevel 		    socket->socket, socket->VccLevel, socket->Vpp1Level,
3795*3db86aabSstevel 		    socket->Vpp2Level);
3796*3db86aabSstevel 	}
3797*3db86aabSstevel #endif
3798*3db86aabSstevel 	/*
3799*3db86aabSstevel 	 * check VccLevel, etc. before setting mutex
3800*3db86aabSstevel 	 * if this is zero, power is being turned off
3801*3db86aabSstevel 	 * if it is non-zero, power is being turned on.
3802*3db86aabSstevel 	 * the default case is to assume Vcc only.
3803*3db86aabSstevel 	 */
3804*3db86aabSstevel 
3805*3db86aabSstevel 	/* this appears to be very implementation specific */
3806*3db86aabSstevel 
3807*3db86aabSstevel 	if (socket->Vpp1Level != socket->Vpp2Level)
3808*3db86aabSstevel 		return (BAD_VPP);
3809*3db86aabSstevel 
3810*3db86aabSstevel 	if (socket->VccLevel == 0 || !(sockp->pcs_flags & PCS_CARD_PRESENT)) {
3811*3db86aabSstevel 		powerlevel = 0;
3812*3db86aabSstevel 		sockp->pcs_vcc = 0;
3813*3db86aabSstevel 		sockp->pcs_vpp1 = 0;
3814*3db86aabSstevel 		sockp->pcs_vpp2 = 0;
3815*3db86aabSstevel 	} else {
3816*3db86aabSstevel #if defined(PCIC_DEBUG)
3817*3db86aabSstevel 		pcic_err(dip, 9, "\tVcc=%d Vpp1Level=%d, Vpp2Level=%d\n",
3818*3db86aabSstevel 		    socket->VccLevel, socket->Vpp1Level, socket->Vpp2Level);
3819*3db86aabSstevel #endif
3820*3db86aabSstevel 		/* valid Vcc power level? */
3821*3db86aabSstevel 		if (socket->VccLevel >= pcic->pc_numpower)
3822*3db86aabSstevel 			return (BAD_VCC);
3823*3db86aabSstevel 
3824*3db86aabSstevel 		switch (pcic_power[socket->VccLevel].PowerLevel) {
3825*3db86aabSstevel 		case 33:	/* 3.3V */
3826*3db86aabSstevel 		case 60:	/* for bad CIS in Option GPRS card */
3827*3db86aabSstevel 			if (!(pcic->pc_flags & PCF_33VCAP)) {
3828*3db86aabSstevel 				cmn_err(CE_WARN,
3829*3db86aabSstevel 				    "%s%d: Bad Request for 3.3V "
3830*3db86aabSstevel 				    "(Controller incapable)\n",
3831*3db86aabSstevel 				    ddi_get_name(pcic->dip),
3832*3db86aabSstevel 				    ddi_get_instance(pcic->dip));
3833*3db86aabSstevel 				return (BAD_VCC);
3834*3db86aabSstevel 			}
3835*3db86aabSstevel 			/* FALLTHROUGH */
3836*3db86aabSstevel 		case 50:	/* 5V */
3837*3db86aabSstevel 			if ((pcic->pc_io_type == PCIC_IO_TYPE_YENTA) &&
3838*3db86aabSstevel 			    pcic_getcb(pcic, CB_PRESENT_STATE) &
3839*3db86aabSstevel 			    CB_PS_33VCARD) {
3840*3db86aabSstevel 				/*
3841*3db86aabSstevel 				 * This is actually a 3.3V card.
3842*3db86aabSstevel 				 * Solaris Card Services
3843*3db86aabSstevel 				 * doesn't understand 3.3V
3844*3db86aabSstevel 				 * so we cheat and change
3845*3db86aabSstevel 				 * the setting to the one appropriate to 3.3V.
3846*3db86aabSstevel 				 * Note that this is the entry number
3847*3db86aabSstevel 				 * in the pcic_power[] array.
3848*3db86aabSstevel 				 */
3849*3db86aabSstevel 				sockp->pcs_vcc = PCIC_VCC_3VLEVEL;
3850*3db86aabSstevel 			} else
3851*3db86aabSstevel 				sockp->pcs_vcc = socket->VccLevel;
3852*3db86aabSstevel 			break;
3853*3db86aabSstevel 		default:
3854*3db86aabSstevel 			return (BAD_VCC);
3855*3db86aabSstevel 		}
3856*3db86aabSstevel 
3857*3db86aabSstevel 		/* enable Vcc */
3858*3db86aabSstevel 		powerlevel = POWER_CARD_ENABLE;
3859*3db86aabSstevel 
3860*3db86aabSstevel #if defined(PCIC_DEBUG)
3861*3db86aabSstevel 		if (pcic_debug) {
3862*3db86aabSstevel 			cmn_err(CE_CONT, "\tVcc=%d powerlevel=%x\n",
3863*3db86aabSstevel 			    socket->VccLevel, powerlevel);
3864*3db86aabSstevel 		}
3865*3db86aabSstevel #endif
3866*3db86aabSstevel 		ind = 0;		/* default index to 0 power */
3867*3db86aabSstevel 		if ((int)socket->Vpp1Level >= 0 &&
3868*3db86aabSstevel 		    socket->Vpp1Level < pcic->pc_numpower) {
3869*3db86aabSstevel 			if (!(pcic_power[socket->Vpp1Level].ValidSignals
3870*3db86aabSstevel 			    & VPP1)) {
3871*3db86aabSstevel 				return (BAD_VPP);
3872*3db86aabSstevel 			}
3873*3db86aabSstevel 			ind = pcic_power[socket->Vpp1Level].PowerLevel/10;
3874*3db86aabSstevel 			powerlevel |= pcic_vpp_levels[ind];
3875*3db86aabSstevel 			sockp->pcs_vpp1 = socket->Vpp1Level;
3876*3db86aabSstevel 		}
3877*3db86aabSstevel 		if ((int)socket->Vpp2Level >= 0 &&
3878*3db86aabSstevel 		    socket->Vpp2Level < pcic->pc_numpower) {
3879*3db86aabSstevel 			if (!(pcic_power[socket->Vpp2Level].ValidSignals
3880*3db86aabSstevel 			    & VPP2)) {
3881*3db86aabSstevel 				return (BAD_VPP);
3882*3db86aabSstevel 			}
3883*3db86aabSstevel 			ind = pcic_power[socket->Vpp2Level].PowerLevel/10;
3884*3db86aabSstevel 			powerlevel |= (pcic_vpp_levels[ind] << 2);
3885*3db86aabSstevel 			sockp->pcs_vpp2 = socket->Vpp2Level;
3886*3db86aabSstevel 		}
3887*3db86aabSstevel 
3888*3db86aabSstevel 		if (pcic->pc_flags & PCF_VPPX) {
3889*3db86aabSstevel 			/*
3890*3db86aabSstevel 			 * this adapter doesn't allow separate Vpp1/Vpp2
3891*3db86aabSstevel 			 * if one is turned on, both are turned on and only
3892*3db86aabSstevel 			 * the Vpp1 bits should be set
3893*3db86aabSstevel 			 */
3894*3db86aabSstevel 			if (sockp->pcs_vpp2 != sockp->pcs_vpp1) {
3895*3db86aabSstevel 				/* must be the same if one not zero */
3896*3db86aabSstevel 				if (sockp->pcs_vpp1 != 0 &&
3897*3db86aabSstevel 				    sockp->pcs_vpp2 != 0) {
3898*3db86aabSstevel 					cmn_err(CE_WARN,
3899*3db86aabSstevel 					    "%s%d: Bad Power Request "
3900*3db86aabSstevel 					    "(Vpp1/2 not the same)\n",
3901*3db86aabSstevel 					    ddi_get_name(pcic->dip),
3902*3db86aabSstevel 					    ddi_get_instance(pcic->dip));
3903*3db86aabSstevel 					return (BAD_VPP);
3904*3db86aabSstevel 				}
3905*3db86aabSstevel 			}
3906*3db86aabSstevel 			powerlevel &= ~(3<<2);
3907*3db86aabSstevel 		}
3908*3db86aabSstevel 
3909*3db86aabSstevel #if defined(PCIC_DEBUG)
3910*3db86aabSstevel 		if (pcic_debug) {
3911*3db86aabSstevel 			cmn_err(CE_CONT, "\tpowerlevel=%x, ind=%x\n",
3912*3db86aabSstevel 			    powerlevel, ind);
3913*3db86aabSstevel 		}
3914*3db86aabSstevel #endif
3915*3db86aabSstevel 	}
3916*3db86aabSstevel 	mutex_enter(&pcic->pc_lock); /* protect the registers */
3917*3db86aabSstevel 
3918*3db86aabSstevel 	/* turn socket->IREQRouting off while programming */
3919*3db86aabSstevel 	interrupt = pcic_getb(pcic, socket->socket, PCIC_INTERRUPT);
3920*3db86aabSstevel 	interrupt &= ~PCIC_INTR_MASK;
3921*3db86aabSstevel 	if (pcic->pc_flags & PCF_USE_SMI)
3922*3db86aabSstevel 		interrupt |= PCIC_INTR_ENABLE;
3923*3db86aabSstevel 	pcic_putb(pcic, socket->socket, PCIC_INTERRUPT, interrupt);
3924*3db86aabSstevel 
3925*3db86aabSstevel 	switch (pcic->pc_type) {
3926*3db86aabSstevel 	    case PCIC_INTEL_i82092:
3927*3db86aabSstevel 		pcic_82092_smiirq_ctl(pcic, socket->socket, PCIC_82092_CTL_IRQ,
3928*3db86aabSstevel 						PCIC_82092_INT_DISABLE);
3929*3db86aabSstevel 		break;
3930*3db86aabSstevel 	    default:
3931*3db86aabSstevel 		break;
3932*3db86aabSstevel 	} /* switch */
3933*3db86aabSstevel 
3934*3db86aabSstevel 	/* the SCIntMask specifies events to detect */
3935*3db86aabSstevel 	mirq = pcic_getb(pcic, socket->socket, PCIC_MANAGEMENT_INT);
3936*3db86aabSstevel 
3937*3db86aabSstevel #if defined(PCIC_DEBUG)
3938*3db86aabSstevel 	if (pcic_debug)
3939*3db86aabSstevel 		cmn_err(CE_CONT,
3940*3db86aabSstevel 			"\tSCIntMask=%x, interrupt=%x, mirq=%x\n",
3941*3db86aabSstevel 			socket->SCIntMask, interrupt, mirq);
3942*3db86aabSstevel #endif
3943*3db86aabSstevel 	mirq &= ~(PCIC_BD_DETECT|PCIC_BW_DETECT|PCIC_RD_DETECT);
3944*3db86aabSstevel 	pcic_putb(pcic, socket->socket, PCIC_MANAGEMENT_INT,
3945*3db86aabSstevel 	    mirq & ~PCIC_CHANGE_MASK);
3946*3db86aabSstevel 
3947*3db86aabSstevel 	/* save the mask we want to use */
3948*3db86aabSstevel 	sockp->pcs_intmask = socket->SCIntMask;
3949*3db86aabSstevel 
3950*3db86aabSstevel 	/*
3951*3db86aabSstevel 	 * Until there is a card present it's not worth enabling
3952*3db86aabSstevel 	 * any interrupts except "Card detect". This is done
3953*3db86aabSstevel 	 * elsewhere in the driver so don't change things if
3954*3db86aabSstevel 	 * there is no card!
3955*3db86aabSstevel 	 */
3956*3db86aabSstevel 	if (sockp->pcs_flags & PCS_CARD_PRESENT) {
3957*3db86aabSstevel 
3958*3db86aabSstevel 		/* now update the hardware to reflect events desired */
3959*3db86aabSstevel 		if (sockp->pcs_intmask & SBM_BVD1 || socket->IFType == IF_IO)
3960*3db86aabSstevel 			mirq |= PCIC_BD_DETECT;
3961*3db86aabSstevel 
3962*3db86aabSstevel 		if (sockp->pcs_intmask & SBM_BVD2)
3963*3db86aabSstevel 			mirq |= PCIC_BW_DETECT;
3964*3db86aabSstevel 
3965*3db86aabSstevel 		if (sockp->pcs_intmask & SBM_RDYBSY)
3966*3db86aabSstevel 			mirq |= PCIC_RD_DETECT;
3967*3db86aabSstevel 
3968*3db86aabSstevel 		if (sockp->pcs_intmask & SBM_CD)
3969*3db86aabSstevel 			mirq |= PCIC_CD_DETECT;
3970*3db86aabSstevel 	}
3971*3db86aabSstevel 
3972*3db86aabSstevel 	if (sockp->pcs_flags & PCS_READY) {
3973*3db86aabSstevel 		/*
3974*3db86aabSstevel 		 * card just came ready.
3975*3db86aabSstevel 		 * make sure enough time elapses
3976*3db86aabSstevel 		 * before touching it.
3977*3db86aabSstevel 		 */
3978*3db86aabSstevel 		sockp->pcs_flags &= ~PCS_READY;
3979*3db86aabSstevel 		pcic_mswait(pcic, socket->socket, 10);
3980*3db86aabSstevel 	}
3981*3db86aabSstevel 
3982*3db86aabSstevel #if defined(PCIC_DEBUG)
3983*3db86aabSstevel 	if (pcic_debug) {
3984*3db86aabSstevel 		cmn_err(CE_CONT, "\tstatus change set to %x\n", mirq);
3985*3db86aabSstevel 	}
3986*3db86aabSstevel #endif
3987*3db86aabSstevel 
3988*3db86aabSstevel 	switch (pcic->pc_type) {
3989*3db86aabSstevel 	    case PCIC_I82365SL:
3990*3db86aabSstevel 	    case PCIC_VADEM:
3991*3db86aabSstevel 	    case PCIC_VADEM_VG469:
3992*3db86aabSstevel 		/*
3993*3db86aabSstevel 		 * The Intel version has different options. This is a
3994*3db86aabSstevel 		 * special case of GPI which might be used for eject
3995*3db86aabSstevel 		 */
3996*3db86aabSstevel 
3997*3db86aabSstevel 		irq = pcic_getb(pcic, socket->socket, PCIC_CARD_DETECT);
3998*3db86aabSstevel 		if (sockp->pcs_intmask & (SBM_EJECT|SBM_INSERT) &&
3999*3db86aabSstevel 		    pcic->pc_flags & PCF_GPI_EJECT) {
4000*3db86aabSstevel 			irq |= PCIC_GPI_ENABLE;
4001*3db86aabSstevel 		} else {
4002*3db86aabSstevel 			irq &= ~PCIC_GPI_ENABLE;
4003*3db86aabSstevel 		}
4004*3db86aabSstevel 		pcic_putb(pcic, socket->socket, PCIC_CARD_DETECT, irq);
4005*3db86aabSstevel 		break;
4006*3db86aabSstevel 	    case PCIC_CL_PD6710:
4007*3db86aabSstevel 	    case PCIC_CL_PD6722:
4008*3db86aabSstevel 		if (socket->IFType == IF_IO) {
4009*3db86aabSstevel 			pcic_putb(pcic, socket->socket, PCIC_MISC_CTL_2, 0x0);
4010*3db86aabSstevel 			value = pcic_getb(pcic, socket->socket,
4011*3db86aabSstevel 						PCIC_MISC_CTL_1);
4012*3db86aabSstevel 			if (pcic->pc_flags & PCF_AUDIO)
4013*3db86aabSstevel 				value |= PCIC_MC_SPEAKER_ENB;
4014*3db86aabSstevel 			pcic_putb(pcic, socket->socket, PCIC_MISC_CTL_1,
4015*3db86aabSstevel 					value);
4016*3db86aabSstevel 		} else {
4017*3db86aabSstevel 			value = pcic_getb(pcic, socket->socket,
4018*3db86aabSstevel 						PCIC_MISC_CTL_1);
4019*3db86aabSstevel 			value &= ~PCIC_MC_SPEAKER_ENB;
4020*3db86aabSstevel 			pcic_putb(pcic, socket->socket, PCIC_MISC_CTL_1,
4021*3db86aabSstevel 					value);
4022*3db86aabSstevel 		}
4023*3db86aabSstevel 		break;
4024*3db86aabSstevel 	    case PCIC_CL_PD6729:
4025*3db86aabSstevel 	    case PCIC_CL_PD6730:
4026*3db86aabSstevel 	    case PCIC_CL_PD6832:
4027*3db86aabSstevel 		value = pcic_getb(pcic, socket->socket, PCIC_MISC_CTL_1);
4028*3db86aabSstevel 		if ((socket->IFType == IF_IO) && (pcic->pc_flags & PCF_AUDIO)) {
4029*3db86aabSstevel 		    value |= PCIC_MC_SPEAKER_ENB;
4030*3db86aabSstevel 		} else {
4031*3db86aabSstevel 		    value &= ~PCIC_MC_SPEAKER_ENB;
4032*3db86aabSstevel 		}
4033*3db86aabSstevel 
4034*3db86aabSstevel 		if (pcic_power[sockp->pcs_vcc].PowerLevel == 33)
4035*3db86aabSstevel 			value |= PCIC_MC_3VCC;
4036*3db86aabSstevel 		else
4037*3db86aabSstevel 			value &= ~PCIC_MC_3VCC;
4038*3db86aabSstevel 
4039*3db86aabSstevel 		pcic_putb(pcic, socket->socket, PCIC_MISC_CTL_1, value);
4040*3db86aabSstevel 		break;
4041*3db86aabSstevel 
4042*3db86aabSstevel 	    case PCIC_O2_OZ6912:
4043*3db86aabSstevel 		value = pcic_getcb(pcic, CB_MISCCTRL);
4044*3db86aabSstevel 		if ((socket->IFType == IF_IO) && (pcic->pc_flags & PCF_AUDIO))
4045*3db86aabSstevel 			value |= (1<<25);
4046*3db86aabSstevel 		else
4047*3db86aabSstevel 			value &= ~(1<<25);
4048*3db86aabSstevel 		pcic_putcb(pcic, CB_MISCCTRL, value);
4049*3db86aabSstevel 		if (pcic_power[sockp->pcs_vcc].PowerLevel == 33)
4050*3db86aabSstevel 			powerlevel |= 0x08;
4051*3db86aabSstevel 		break;
4052*3db86aabSstevel 
4053*3db86aabSstevel 	    case PCIC_TI_PCI1250:
4054*3db86aabSstevel 	    case PCIC_TI_PCI1221:
4055*3db86aabSstevel 	    case PCIC_TI_PCI1225:
4056*3db86aabSstevel 	    case PCIC_TI_PCI1410:
4057*3db86aabSstevel 	    case PCIC_ENE_1410:
4058*3db86aabSstevel 	    case PCIC_TI_PCI1510:
4059*3db86aabSstevel 	    case PCIC_TI_PCI1520:
4060*3db86aabSstevel 	    case PCIC_TI_PCI1420:
4061*3db86aabSstevel 	    case PCIC_ENE_1420:
4062*3db86aabSstevel 		value = ddi_get8(pcic->cfg_handle,
4063*3db86aabSstevel 		    pcic->cfgaddr + PCIC_CRDCTL_REG);
4064*3db86aabSstevel 		if ((socket->IFType == IF_IO) && (pcic->pc_flags & PCF_AUDIO)) {
4065*3db86aabSstevel 			value |= PCIC_CRDCTL_SPKR_ENBL;
4066*3db86aabSstevel 		} else {
4067*3db86aabSstevel 			value &= ~PCIC_CRDCTL_SPKR_ENBL;
4068*3db86aabSstevel 		}
4069*3db86aabSstevel 		ddi_put8(pcic->cfg_handle,
4070*3db86aabSstevel 		    pcic->cfgaddr + PCIC_CRDCTL_REG, value);
4071*3db86aabSstevel 		if (pcic_power[sockp->pcs_vcc].PowerLevel == 33)
4072*3db86aabSstevel 			powerlevel |= 0x08;
4073*3db86aabSstevel 		break;
4074*3db86aabSstevel 	}
4075*3db86aabSstevel 
4076*3db86aabSstevel 	/*
4077*3db86aabSstevel 	 * ctlind processing -- we can ignore this
4078*3db86aabSstevel 	 * there aren't any outputs on the chip for this and
4079*3db86aabSstevel 	 * the GUI will display what it thinks is correct
4080*3db86aabSstevel 	 */
4081*3db86aabSstevel 
4082*3db86aabSstevel 	/*
4083*3db86aabSstevel 	 * If outputs are enabled and the power is going off
4084*3db86aabSstevel 	 * turn off outputs first.
4085*3db86aabSstevel 	 */
4086*3db86aabSstevel 
4087*3db86aabSstevel 	/* power setup -- if necessary */
4088*3db86aabSstevel 	orig_pwrctl = pcic_getb(pcic, socket->socket, PCIC_POWER_CONTROL);
4089*3db86aabSstevel 	if ((orig_pwrctl & POWER_OUTPUT_ENABLE) && sockp->pcs_vcc == 0) {
4090*3db86aabSstevel 		orig_pwrctl &= ~POWER_OUTPUT_ENABLE;
4091*3db86aabSstevel 		pcic_putb(pcic, socket->socket,
4092*3db86aabSstevel 		    PCIC_POWER_CONTROL, orig_pwrctl);
4093*3db86aabSstevel 		(void) pcic_getb(pcic, socket->socket, PCIC_POWER_CONTROL);
4094*3db86aabSstevel 	}
4095*3db86aabSstevel 
4096*3db86aabSstevel 	if (pcic->pc_flags & PCF_CBPWRCTL) {
4097*3db86aabSstevel 		value = pcic_cbus_powerctl(pcic, socket->socket);
4098*3db86aabSstevel 		powerlevel = 0;
4099*3db86aabSstevel 	} else
4100*3db86aabSstevel 		value = pcic_exca_powerctl(pcic, socket->socket, powerlevel);
4101*3db86aabSstevel 
4102*3db86aabSstevel 	if (value != SUCCESS) {
4103*3db86aabSstevel 		mutex_exit(&pcic->pc_lock);
4104*3db86aabSstevel 		return (value);
4105*3db86aabSstevel 	}
4106*3db86aabSstevel 
4107*3db86aabSstevel 	/*
4108*3db86aabSstevel 	 * If outputs were disabled and the power is going on
4109*3db86aabSstevel 	 * turn on outputs afterwards.
4110*3db86aabSstevel 	 */
4111*3db86aabSstevel 	if (!(orig_pwrctl & POWER_OUTPUT_ENABLE) && sockp->pcs_vcc != 0) {
4112*3db86aabSstevel 		orig_pwrctl = pcic_getb(pcic, socket->socket,
4113*3db86aabSstevel 		    PCIC_POWER_CONTROL);
4114*3db86aabSstevel 		orig_pwrctl |= POWER_OUTPUT_ENABLE;
4115*3db86aabSstevel 		pcic_putb(pcic, socket->socket,
4116*3db86aabSstevel 		    PCIC_POWER_CONTROL, orig_pwrctl);
4117*3db86aabSstevel 		(void) pcic_getb(pcic, socket->socket, PCIC_POWER_CONTROL);
4118*3db86aabSstevel 	}
4119*3db86aabSstevel 
4120*3db86aabSstevel 	/*
4121*3db86aabSstevel 	 * Once we have done the power stuff can re-enable management
4122*3db86aabSstevel 	 * interrupts.
4123*3db86aabSstevel 	 */
4124*3db86aabSstevel 	pcic_putb(pcic, socket->socket, PCIC_MANAGEMENT_INT, mirq);
4125*3db86aabSstevel 
4126*3db86aabSstevel #if defined(PCIC_DEBUG)
4127*3db86aabSstevel 	pcic_err(dip, 8, "\tmanagement int set to %x pwrctl to 0x%x "
4128*3db86aabSstevel 	    "cbctl 0x%x\n",
4129*3db86aabSstevel 	    mirq, pcic_getb(pcic, socket->socket, PCIC_POWER_CONTROL),
4130*3db86aabSstevel 	    pcic_getcb(pcic, CB_CONTROL));
4131*3db86aabSstevel #endif
4132*3db86aabSstevel 
4133*3db86aabSstevel 	/* irq processing */
4134*3db86aabSstevel 	if (socket->IFType == IF_IO) {
4135*3db86aabSstevel 		/* IRQ only for I/O */
4136*3db86aabSstevel 		irq = socket->IREQRouting & PCIC_INTR_MASK;
4137*3db86aabSstevel 		value = pcic_getb(pcic, socket->socket, PCIC_INTERRUPT);
4138*3db86aabSstevel 		value &= ~PCIC_INTR_MASK;
4139*3db86aabSstevel 
4140*3db86aabSstevel 		/* to enable I/O operation */
4141*3db86aabSstevel 		value |= PCIC_IO_CARD | PCIC_RESET;
4142*3db86aabSstevel 		sockp->pcs_flags |= PCS_CARD_IO;
4143*3db86aabSstevel 		if (irq != sockp->pcs_irq) {
4144*3db86aabSstevel 			if (sockp->pcs_irq != 0)
4145*3db86aabSstevel 				cmn_err(CE_CONT,
4146*3db86aabSstevel 					"SetSocket: IRQ mismatch %x != %x!\n",
4147*3db86aabSstevel 					irq, sockp->pcs_irq);
4148*3db86aabSstevel 			else
4149*3db86aabSstevel 				sockp->pcs_irq = irq;
4150*3db86aabSstevel 		}
4151*3db86aabSstevel 		irq = sockp->pcs_irq;
4152*3db86aabSstevel 
4153*3db86aabSstevel 		pcic_putb(pcic, socket->socket, PCIC_INTERRUPT, value);
4154*3db86aabSstevel 		if (socket->IREQRouting & IRQ_ENABLE) {
4155*3db86aabSstevel 			pcic_enable_io_intr(pcic, socket->socket, irq);
4156*3db86aabSstevel 			sockp->pcs_flags |= PCS_IRQ_ENABLED;
4157*3db86aabSstevel 		} else {
4158*3db86aabSstevel 			pcic_disable_io_intr(pcic, socket->socket);
4159*3db86aabSstevel 			sockp->pcs_flags &= ~PCS_IRQ_ENABLED;
4160*3db86aabSstevel 		}
4161*3db86aabSstevel #if defined(PCIC_DEBUG)
4162*3db86aabSstevel 		if (pcic_debug) {
4163*3db86aabSstevel 			cmn_err(CE_CONT,
4164*3db86aabSstevel 				"\tsocket type is I/O and irq %x is %s\n", irq,
4165*3db86aabSstevel 				(socket->IREQRouting & IRQ_ENABLE) ?
4166*3db86aabSstevel 				"enabled" : "not enabled");
4167*3db86aabSstevel 			xxdmp_all_regs(pcic, socket->socket, 20);
4168*3db86aabSstevel 		}
4169*3db86aabSstevel #endif
4170*3db86aabSstevel 	} else {
4171*3db86aabSstevel 		/* make sure I/O mode is off */
4172*3db86aabSstevel 
4173*3db86aabSstevel 		sockp->pcs_irq = 0;
4174*3db86aabSstevel 
4175*3db86aabSstevel 		value = pcic_getb(pcic, socket->socket, PCIC_INTERRUPT);
4176*3db86aabSstevel 		value &= ~PCIC_IO_CARD;
4177*3db86aabSstevel 		pcic_putb(pcic, socket->socket, PCIC_INTERRUPT, value);
4178*3db86aabSstevel 		pcic_disable_io_intr(pcic, socket->socket);
4179*3db86aabSstevel 		sockp->pcs_flags &= ~(PCS_CARD_IO|PCS_IRQ_ENABLED);
4180*3db86aabSstevel 	}
4181*3db86aabSstevel 
4182*3db86aabSstevel 	sockp->pcs_state &= ~socket->State;
4183*3db86aabSstevel 
4184*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
4185*3db86aabSstevel 	return (SUCCESS);
4186*3db86aabSstevel }
4187*3db86aabSstevel 
4188*3db86aabSstevel /*
4189*3db86aabSstevel  * pcic_inquire_socket()
4190*3db86aabSstevel  *	SocketServices InquireSocket function
4191*3db86aabSstevel  *	returns basic characteristics of the socket
4192*3db86aabSstevel  */
4193*3db86aabSstevel /*ARGSUSED*/
4194*3db86aabSstevel static int
4195*3db86aabSstevel pcic_inquire_socket(dev_info_t *dip, inquire_socket_t *socket)
4196*3db86aabSstevel {
4197*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4198*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4199*3db86aabSstevel 	int value;
4200*3db86aabSstevel 
4201*3db86aabSstevel 	socket->SCIntCaps = PCIC_DEFAULT_INT_CAPS;
4202*3db86aabSstevel 	socket->SCRptCaps = PCIC_DEFAULT_RPT_CAPS;
4203*3db86aabSstevel 	socket->CtlIndCaps = PCIC_DEFAULT_CTL_CAPS;
4204*3db86aabSstevel 	value = pcic->pc_sockets[socket->socket].pcs_flags;
4205*3db86aabSstevel 	socket->SocketCaps = (value & PCS_SOCKET_IO) ? IF_IO : IF_MEMORY;
4206*3db86aabSstevel 	socket->ActiveHigh = 0;
4207*3db86aabSstevel 	/* these are the usable IRQs */
4208*3db86aabSstevel 	socket->ActiveLow = 0xfff0;
4209*3db86aabSstevel 	return (SUCCESS);
4210*3db86aabSstevel }
4211*3db86aabSstevel 
4212*3db86aabSstevel /*
4213*3db86aabSstevel  * pcic_inquire_window()
4214*3db86aabSstevel  *	SocketServices InquireWindow function
4215*3db86aabSstevel  *	returns detailed characteristics of the window
4216*3db86aabSstevel  *	this is where windows get tied to sockets
4217*3db86aabSstevel  */
4218*3db86aabSstevel /*ARGSUSED*/
4219*3db86aabSstevel static int
4220*3db86aabSstevel pcic_inquire_window(dev_info_t *dip, inquire_window_t *window)
4221*3db86aabSstevel {
4222*3db86aabSstevel 	int type, socket;
4223*3db86aabSstevel 
4224*3db86aabSstevel 	type = window->window % PCIC_NUMWINSOCK;
4225*3db86aabSstevel 	socket = window->window / PCIC_NUMWINSOCK;
4226*3db86aabSstevel 
4227*3db86aabSstevel #if defined(PCIC_DEBUG)
4228*3db86aabSstevel 	if (pcic_debug >= 8)
4229*3db86aabSstevel 		cmn_err(CE_CONT,
4230*3db86aabSstevel 			"pcic_inquire_window: window = %d/%d socket=%d\n",
4231*3db86aabSstevel 			window->window, type, socket);
4232*3db86aabSstevel #endif
4233*3db86aabSstevel 	if (type < PCIC_IOWINDOWS) {
4234*3db86aabSstevel 		window->WndCaps = WC_IO|WC_WAIT;
4235*3db86aabSstevel 		type = IF_IO;
4236*3db86aabSstevel 	} else {
4237*3db86aabSstevel 		window->WndCaps = WC_COMMON|WC_ATTRIBUTE|WC_WAIT;
4238*3db86aabSstevel 		type = IF_MEMORY;
4239*3db86aabSstevel 	}
4240*3db86aabSstevel 
4241*3db86aabSstevel 	/* initialize the socket map - one socket per window */
4242*3db86aabSstevel 	PR_ZERO(window->Sockets);
4243*3db86aabSstevel 	PR_SET(window->Sockets, socket);
4244*3db86aabSstevel 
4245*3db86aabSstevel 	if (type == IF_IO) {
4246*3db86aabSstevel 		iowin_char_t *io;
4247*3db86aabSstevel 		io = &window->iowin_char;
4248*3db86aabSstevel 		io->IOWndCaps = WC_BASE|WC_SIZE|WC_WENABLE|WC_8BIT|
4249*3db86aabSstevel 			WC_16BIT;
4250*3db86aabSstevel 		io->FirstByte = (baseaddr_t)IOMEM_FIRST;
4251*3db86aabSstevel 		io->LastByte = (baseaddr_t)IOMEM_LAST;
4252*3db86aabSstevel 		io->MinSize = IOMEM_MIN;
4253*3db86aabSstevel 		io->MaxSize = IOMEM_MAX;
4254*3db86aabSstevel 		io->ReqGran = IOMEM_GRAN;
4255*3db86aabSstevel 		io->AddrLines = IOMEM_DECODE;
4256*3db86aabSstevel 		io->EISASlot = 0;
4257*3db86aabSstevel 	} else {
4258*3db86aabSstevel 		mem_win_char_t *mem;
4259*3db86aabSstevel 		mem = &window->mem_win_char;
4260*3db86aabSstevel 		mem->MemWndCaps = WC_BASE|WC_SIZE|WC_WENABLE|WC_8BIT|
4261*3db86aabSstevel 			WC_16BIT|WC_WP;
4262*3db86aabSstevel 
4263*3db86aabSstevel 		mem->FirstByte = (baseaddr_t)MEM_FIRST;
4264*3db86aabSstevel 		mem->LastByte = (baseaddr_t)MEM_LAST;
4265*3db86aabSstevel 
4266*3db86aabSstevel 		mem->MinSize = MEM_MIN;
4267*3db86aabSstevel 		mem->MaxSize = MEM_MAX;
4268*3db86aabSstevel 		mem->ReqGran = PCIC_PAGE;
4269*3db86aabSstevel 		mem->ReqBase = 0;
4270*3db86aabSstevel 		mem->ReqOffset = PCIC_PAGE;
4271*3db86aabSstevel 		mem->Slowest = MEM_SPEED_MAX;
4272*3db86aabSstevel 		mem->Fastest = MEM_SPEED_MIN;
4273*3db86aabSstevel 	}
4274*3db86aabSstevel 	return (SUCCESS);
4275*3db86aabSstevel }
4276*3db86aabSstevel 
4277*3db86aabSstevel /*
4278*3db86aabSstevel  * pcic_get_adapter()
4279*3db86aabSstevel  *	SocketServices GetAdapter function
4280*3db86aabSstevel  *	this is nearly a no-op.
4281*3db86aabSstevel  */
4282*3db86aabSstevel /*ARGSUSED*/
4283*3db86aabSstevel static int
4284*3db86aabSstevel pcic_get_adapter(dev_info_t *dip, get_adapter_t *adapt)
4285*3db86aabSstevel {
4286*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4287*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4288*3db86aabSstevel 
4289*3db86aabSstevel 	if (pcic->pc_flags & PCF_INTRENAB)
4290*3db86aabSstevel 		adapt->SCRouting = IRQ_ENABLE;
4291*3db86aabSstevel 	adapt->state = 0;
4292*3db86aabSstevel 	return (SUCCESS);
4293*3db86aabSstevel }
4294*3db86aabSstevel 
4295*3db86aabSstevel /*
4296*3db86aabSstevel  * pcic_get_page()
4297*3db86aabSstevel  *	SocketServices GetPage function
4298*3db86aabSstevel  *	returns info about the window
4299*3db86aabSstevel  */
4300*3db86aabSstevel /*ARGSUSED*/
4301*3db86aabSstevel static int
4302*3db86aabSstevel pcic_get_page(dev_info_t *dip, get_page_t *page)
4303*3db86aabSstevel {
4304*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4305*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4306*3db86aabSstevel 	int socket, window;
4307*3db86aabSstevel 	pcs_memwin_t *winp;
4308*3db86aabSstevel 
4309*3db86aabSstevel 	socket = page->window / PCIC_NUMWINSOCK;
4310*3db86aabSstevel 	window = page->window % PCIC_NUMWINSOCK;
4311*3db86aabSstevel 
4312*3db86aabSstevel 	/* I/O windows are the first two */
4313*3db86aabSstevel 	if (window < PCIC_IOWINDOWS || socket >= pcic->pc_numsockets) {
4314*3db86aabSstevel 		return (BAD_WINDOW);
4315*3db86aabSstevel 	}
4316*3db86aabSstevel 
4317*3db86aabSstevel 	winp = &pcic->pc_sockets[socket].pcs_windows[window].mem;
4318*3db86aabSstevel 
4319*3db86aabSstevel 	if (page->page != 0)
4320*3db86aabSstevel 		return (BAD_PAGE);
4321*3db86aabSstevel 
4322*3db86aabSstevel 	page->state = 0;
4323*3db86aabSstevel 	if (winp->pcw_status & PCW_ENABLED)
4324*3db86aabSstevel 		page->state |= PS_ENABLED;
4325*3db86aabSstevel 	if (winp->pcw_status & PCW_ATTRIBUTE)
4326*3db86aabSstevel 		page->state |= PS_ATTRIBUTE;
4327*3db86aabSstevel 	if (winp->pcw_status & PCW_WP)
4328*3db86aabSstevel 		page->state |= PS_WP;
4329*3db86aabSstevel 
4330*3db86aabSstevel 	page->offset = (off_t)winp->pcw_offset;
4331*3db86aabSstevel 
4332*3db86aabSstevel 	return (SUCCESS);
4333*3db86aabSstevel }
4334*3db86aabSstevel 
4335*3db86aabSstevel /*
4336*3db86aabSstevel  * pcic_get_socket()
4337*3db86aabSstevel  *	SocketServices GetSocket
4338*3db86aabSstevel  *	returns information about the current socket setting
4339*3db86aabSstevel  */
4340*3db86aabSstevel /*ARGSUSED*/
4341*3db86aabSstevel static int
4342*3db86aabSstevel pcic_get_socket(dev_info_t *dip, get_socket_t *socket)
4343*3db86aabSstevel {
4344*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4345*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4346*3db86aabSstevel 	int socknum, irq_enabled;
4347*3db86aabSstevel 	pcic_socket_t *sockp;
4348*3db86aabSstevel 
4349*3db86aabSstevel 	socknum = socket->socket;
4350*3db86aabSstevel 	sockp = &pcic->pc_sockets[socknum];
4351*3db86aabSstevel 
4352*3db86aabSstevel 	socket->SCIntMask = sockp->pcs_intmask;
4353*3db86aabSstevel 	sockp->pcs_state = pcic_card_state(pcic, sockp);
4354*3db86aabSstevel 
4355*3db86aabSstevel 	socket->state = sockp->pcs_state;
4356*3db86aabSstevel 	if (socket->state & SBM_CD) {
4357*3db86aabSstevel 		socket->VccLevel = sockp->pcs_vcc;
4358*3db86aabSstevel 		socket->Vpp1Level = sockp->pcs_vpp1;
4359*3db86aabSstevel 		socket->Vpp2Level = sockp->pcs_vpp2;
4360*3db86aabSstevel 		irq_enabled = (sockp->pcs_flags & PCS_IRQ_ENABLED) ?
4361*3db86aabSstevel 		    IRQ_ENABLE : 0;
4362*3db86aabSstevel 		socket->IRQRouting = sockp->pcs_irq | irq_enabled;
4363*3db86aabSstevel 		socket->IFType = (sockp->pcs_flags & PCS_CARD_IO) ?
4364*3db86aabSstevel 		    IF_IO : IF_MEMORY;
4365*3db86aabSstevel 	} else {
4366*3db86aabSstevel 		socket->VccLevel = 0;
4367*3db86aabSstevel 		socket->Vpp1Level = 0;
4368*3db86aabSstevel 		socket->Vpp2Level = 0;
4369*3db86aabSstevel 		socket->IRQRouting = 0;
4370*3db86aabSstevel 		socket->IFType = IF_MEMORY;
4371*3db86aabSstevel 	}
4372*3db86aabSstevel 	socket->CtlInd = 0;	/* no indicators */
4373*3db86aabSstevel 
4374*3db86aabSstevel 	return (SUCCESS);
4375*3db86aabSstevel }
4376*3db86aabSstevel 
4377*3db86aabSstevel /*
4378*3db86aabSstevel  * pcic_get_status()
4379*3db86aabSstevel  *	SocketServices GetStatus
4380*3db86aabSstevel  *	returns status information about the PC Card in
4381*3db86aabSstevel  *	the selected socket
4382*3db86aabSstevel  */
4383*3db86aabSstevel /*ARGSUSED*/
4384*3db86aabSstevel static int
4385*3db86aabSstevel pcic_get_status(dev_info_t *dip, get_ss_status_t *status)
4386*3db86aabSstevel {
4387*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4388*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4389*3db86aabSstevel 	int socknum, irq_enabled;
4390*3db86aabSstevel 	pcic_socket_t *sockp;
4391*3db86aabSstevel 
4392*3db86aabSstevel 	socknum = status->socket;
4393*3db86aabSstevel 	sockp = &pcic->pc_sockets[socknum];
4394*3db86aabSstevel 
4395*3db86aabSstevel 	status->CardState = pcic_card_state(pcic, sockp);
4396*3db86aabSstevel 	status->SocketState = sockp->pcs_state;
4397*3db86aabSstevel 	status->CtlInd = 0;	/* no indicators */
4398*3db86aabSstevel 
4399*3db86aabSstevel 	if (sockp->pcs_flags & PCS_CARD_PRESENT)
4400*3db86aabSstevel 		status->SocketState |= SBM_CD;
4401*3db86aabSstevel 	if (status->CardState & SBM_CD) {
4402*3db86aabSstevel 		irq_enabled = (sockp->pcs_flags & PCS_CARD_ENABLED) ?
4403*3db86aabSstevel 		    IRQ_ENABLE : 0;
4404*3db86aabSstevel 		status->IRQRouting = sockp->pcs_irq | irq_enabled;
4405*3db86aabSstevel 		status->IFType = (sockp->pcs_flags & PCS_CARD_IO) ?
4406*3db86aabSstevel 		    IF_IO : IF_MEMORY;
4407*3db86aabSstevel 	} else {
4408*3db86aabSstevel 		status->IRQRouting = 0;
4409*3db86aabSstevel 		status->IFType = IF_MEMORY;
4410*3db86aabSstevel 	}
4411*3db86aabSstevel 
4412*3db86aabSstevel #if defined(PCIC_DEBUG)
4413*3db86aabSstevel 	if (pcic_debug >= 8)
4414*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_get_status: socket=%d, CardState=%x,"
4415*3db86aabSstevel 			"SocketState=%x\n",
4416*3db86aabSstevel 			socknum, status->CardState, status->SocketState);
4417*3db86aabSstevel #endif
4418*3db86aabSstevel 	switch (pcic->pc_type) {
4419*3db86aabSstevel 	uint32_t present_state;
4420*3db86aabSstevel 	case PCIC_TI_PCI1410:
4421*3db86aabSstevel 	case PCIC_TI_PCI1520:
4422*3db86aabSstevel 	case PCIC_TI_PCI1420:
4423*3db86aabSstevel 	case PCIC_ENE_1420:
4424*3db86aabSstevel 	case PCIC_TOSHIBA_TOPIC100:
4425*3db86aabSstevel 	case PCIC_TOSHIBA_TOPIC95:
4426*3db86aabSstevel 	case PCIC_TOSHIBA_VENDOR:
4427*3db86aabSstevel 	case PCIC_O2MICRO_VENDOR:
4428*3db86aabSstevel 	case PCIC_TI_VENDOR:
4429*3db86aabSstevel 	case PCIC_RICOH_VENDOR:
4430*3db86aabSstevel 		present_state = pcic_getcb(pcic, CB_PRESENT_STATE);
4431*3db86aabSstevel 		if (present_state & PCIC_CB_CARD)
4432*3db86aabSstevel 			status->IFType = IF_CARDBUS;
4433*3db86aabSstevel #if defined(PCIC_DEBUG)
4434*3db86aabSstevel 		if (pcic_debug >= 8)
4435*3db86aabSstevel 		    cmn_err(CE_CONT, "pcic_get_status: present_state=0x%x\n",
4436*3db86aabSstevel 			present_state);
4437*3db86aabSstevel #endif
4438*3db86aabSstevel 		break;
4439*3db86aabSstevel 	default:
4440*3db86aabSstevel 		break;
4441*3db86aabSstevel 	}
4442*3db86aabSstevel 
4443*3db86aabSstevel 	return (SUCCESS);
4444*3db86aabSstevel }
4445*3db86aabSstevel 
4446*3db86aabSstevel /*
4447*3db86aabSstevel  * pcic_get_window()
4448*3db86aabSstevel  *	SocketServices GetWindow function
4449*3db86aabSstevel  *	returns state information about the specified window
4450*3db86aabSstevel  */
4451*3db86aabSstevel /*ARGSUSED*/
4452*3db86aabSstevel static int
4453*3db86aabSstevel pcic_get_window(dev_info_t *dip, get_window_t *window)
4454*3db86aabSstevel {
4455*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4456*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4457*3db86aabSstevel 	int socket, win;
4458*3db86aabSstevel 	pcic_socket_t *sockp;
4459*3db86aabSstevel 	pcs_memwin_t *winp;
4460*3db86aabSstevel 
4461*3db86aabSstevel 	socket = window->window / PCIC_NUMWINSOCK;
4462*3db86aabSstevel 	win = window->window % PCIC_NUMWINSOCK;
4463*3db86aabSstevel #if defined(PCIC_DEBUG)
4464*3db86aabSstevel 	if (pcic_debug) {
4465*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_get_window(socket=%d, window=%d)\n",
4466*3db86aabSstevel 			socket, win);
4467*3db86aabSstevel 	}
4468*3db86aabSstevel #endif
4469*3db86aabSstevel 
4470*3db86aabSstevel 	if (socket > pcic->pc_numsockets)
4471*3db86aabSstevel 		return (BAD_WINDOW);
4472*3db86aabSstevel 
4473*3db86aabSstevel 	sockp = &pcic->pc_sockets[socket];
4474*3db86aabSstevel 	winp = &sockp->pcs_windows[win].mem;
4475*3db86aabSstevel 
4476*3db86aabSstevel 	window->socket = socket;
4477*3db86aabSstevel 	window->size = winp->pcw_len;
4478*3db86aabSstevel 	window->speed = winp->pcw_speed;
4479*3db86aabSstevel 	window->handle = (ddi_acc_handle_t)winp->pcw_handle;
4480*3db86aabSstevel 	window->base = (uint32_t)winp->pcw_base + winp->pcw_offset;
4481*3db86aabSstevel 
4482*3db86aabSstevel 	if (win >= PCIC_IOWINDOWS) {
4483*3db86aabSstevel 		window->state = 0;
4484*3db86aabSstevel 	} else {
4485*3db86aabSstevel 		window->state = WS_IO;
4486*3db86aabSstevel 	}
4487*3db86aabSstevel 	if (winp->pcw_status & PCW_ENABLED)
4488*3db86aabSstevel 		window->state |= WS_ENABLED;
4489*3db86aabSstevel 
4490*3db86aabSstevel 	if (winp->pcw_status & PCS_CARD_16BIT)
4491*3db86aabSstevel 		window->state |= WS_16BIT;
4492*3db86aabSstevel #if defined(PCIC_DEBUG)
4493*3db86aabSstevel 	if (pcic_debug)
4494*3db86aabSstevel 		cmn_err(CE_CONT, "\tsize=%d, speed=%d, base=%p, state=%x\n",
4495*3db86aabSstevel 			window->size, (unsigned)window->speed,
4496*3db86aabSstevel 			(void *)window->handle, window->state);
4497*3db86aabSstevel #endif
4498*3db86aabSstevel 
4499*3db86aabSstevel 	return (SUCCESS);
4500*3db86aabSstevel }
4501*3db86aabSstevel 
4502*3db86aabSstevel /*
4503*3db86aabSstevel  * pcic_ll_reset
4504*3db86aabSstevel  *	low level reset
4505*3db86aabSstevel  *	separated out so it can be called when already locked
4506*3db86aabSstevel  *
4507*3db86aabSstevel  *	There are two variables that control the RESET timing:
4508*3db86aabSstevel  *		pcic_prereset_time - time in mS before asserting RESET
4509*3db86aabSstevel  *		pcic_reset_time - time in mS to assert RESET
4510*3db86aabSstevel  *
4511*3db86aabSstevel  */
4512*3db86aabSstevel int pcic_prereset_time = 1;
4513*3db86aabSstevel int pcic_reset_time = 10;
4514*3db86aabSstevel int pcic_postreset_time = 20;
4515*3db86aabSstevel int pcic_vpp_is_vcc_during_reset = 0;
4516*3db86aabSstevel 
4517*3db86aabSstevel static int
4518*3db86aabSstevel pcic_ll_reset(pcicdev_t *pcic, int socket)
4519*3db86aabSstevel {
4520*3db86aabSstevel 	int windowbits, iobits;
4521*3db86aabSstevel 	uint32_t pwr;
4522*3db86aabSstevel 
4523*3db86aabSstevel 	/* save windows that were on */
4524*3db86aabSstevel 	windowbits = pcic_getb(pcic, socket, PCIC_MAPPING_ENABLE);
4525*3db86aabSstevel 	if (pcic_reset_time == 0)
4526*3db86aabSstevel 	    return (windowbits);
4527*3db86aabSstevel 	/* turn all windows off */
4528*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE, 0);
4529*3db86aabSstevel 
4530*3db86aabSstevel #if defined(PCIC_DEBUG)
4531*3db86aabSstevel 	pcic_err(pcic->dip, 6,
4532*3db86aabSstevel 		"pcic_ll_reset(socket %d) powerlevel=%x cbctl 0x%x cbps 0x%x\n",
4533*3db86aabSstevel 		socket, pcic_getb(pcic, socket, PCIC_POWER_CONTROL),
4534*3db86aabSstevel 		pcic_getcb(pcic, CB_CONTROL),
4535*3db86aabSstevel 		pcic_getcb(pcic, CB_PRESENT_STATE));
4536*3db86aabSstevel #endif
4537*3db86aabSstevel 
4538*3db86aabSstevel 	if (pcic_vpp_is_vcc_during_reset) {
4539*3db86aabSstevel 
4540*3db86aabSstevel 	/*
4541*3db86aabSstevel 	 * Set VPP to VCC for the duration of the reset - for aironet
4542*3db86aabSstevel 	 * card.
4543*3db86aabSstevel 	 */
4544*3db86aabSstevel 	    if (pcic->pc_flags & PCF_CBPWRCTL) {
4545*3db86aabSstevel 		pwr = pcic_getcb(pcic, CB_CONTROL);
4546*3db86aabSstevel 		pcic_putcb(pcic, CB_CONTROL, (pwr&~CB_C_VPPMASK)|CB_C_VPPVCC);
4547*3db86aabSstevel 		(void) pcic_getcb(pcic, CB_CONTROL);
4548*3db86aabSstevel 	    } else {
4549*3db86aabSstevel 		pwr = pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
4550*3db86aabSstevel 		pcic_putb(pcic, socket, PCIC_POWER_CONTROL,
4551*3db86aabSstevel 		    pwr | 1);
4552*3db86aabSstevel 		(void) pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
4553*3db86aabSstevel 	    }
4554*3db86aabSstevel 	}
4555*3db86aabSstevel 
4556*3db86aabSstevel 	if (pcic_prereset_time > 0) {
4557*3db86aabSstevel 		pcic_err(pcic->dip, 8, "pcic_ll_reset pre_wait %d mS\n",
4558*3db86aabSstevel 		    pcic_prereset_time);
4559*3db86aabSstevel 		pcic_mswait(pcic, socket, pcic_prereset_time);
4560*3db86aabSstevel 	}
4561*3db86aabSstevel 
4562*3db86aabSstevel 	/* turn interrupts off and start a reset */
4563*3db86aabSstevel 	pcic_err(pcic->dip, 8,
4564*3db86aabSstevel 		"pcic_ll_reset turn interrupts off and start a reset\n");
4565*3db86aabSstevel 	iobits = pcic_getb(pcic, socket, PCIC_INTERRUPT);
4566*3db86aabSstevel 	iobits &= ~(PCIC_INTR_MASK | PCIC_RESET);
4567*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_INTERRUPT, iobits);
4568*3db86aabSstevel 	(void) pcic_getb(pcic, socket, PCIC_INTERRUPT);
4569*3db86aabSstevel 
4570*3db86aabSstevel 	switch (pcic->pc_type) {
4571*3db86aabSstevel 	    case PCIC_INTEL_i82092:
4572*3db86aabSstevel 		pcic_82092_smiirq_ctl(pcic, socket, PCIC_82092_CTL_IRQ,
4573*3db86aabSstevel 						PCIC_82092_INT_DISABLE);
4574*3db86aabSstevel 		break;
4575*3db86aabSstevel 	    default:
4576*3db86aabSstevel 		break;
4577*3db86aabSstevel 	} /* switch */
4578*3db86aabSstevel 
4579*3db86aabSstevel 	pcic->pc_sockets[socket].pcs_state = 0;
4580*3db86aabSstevel 
4581*3db86aabSstevel 	if (pcic_reset_time > 0) {
4582*3db86aabSstevel 		pcic_err(pcic->dip, 8, "pcic_ll_reset reset_wait %d mS\n",
4583*3db86aabSstevel 		    pcic_reset_time);
4584*3db86aabSstevel 		pcic_mswait(pcic, socket, pcic_reset_time);
4585*3db86aabSstevel 	}
4586*3db86aabSstevel 
4587*3db86aabSstevel 	pcic_err(pcic->dip, 8, "pcic_ll_reset take it out of reset now\n");
4588*3db86aabSstevel 
4589*3db86aabSstevel 	/* take it out of RESET now */
4590*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_INTERRUPT, PCIC_RESET | iobits);
4591*3db86aabSstevel 	(void) pcic_getb(pcic, socket, PCIC_INTERRUPT);
4592*3db86aabSstevel 
4593*3db86aabSstevel 	/*
4594*3db86aabSstevel 	 * can't access the card for 20ms, but we really don't
4595*3db86aabSstevel 	 * want to sit around that long. The pcic is still usable.
4596*3db86aabSstevel 	 * memory accesses must wait for RDY to come up.
4597*3db86aabSstevel 	 */
4598*3db86aabSstevel 	if (pcic_postreset_time > 0) {
4599*3db86aabSstevel 		pcic_err(pcic->dip, 8, "pcic_ll_reset post_wait %d mS\n",
4600*3db86aabSstevel 		    pcic_postreset_time);
4601*3db86aabSstevel 		pcic_mswait(pcic, socket, pcic_postreset_time);
4602*3db86aabSstevel 	}
4603*3db86aabSstevel 
4604*3db86aabSstevel 	if (pcic_vpp_is_vcc_during_reset > 1) {
4605*3db86aabSstevel 
4606*3db86aabSstevel 	/*
4607*3db86aabSstevel 	 * Return VPP power to whatever it was before.
4608*3db86aabSstevel 	 */
4609*3db86aabSstevel 	    if (pcic->pc_flags & PCF_CBPWRCTL) {
4610*3db86aabSstevel 		pcic_putcb(pcic, CB_CONTROL, pwr);
4611*3db86aabSstevel 		(void) pcic_getcb(pcic, CB_CONTROL);
4612*3db86aabSstevel 	    } else {
4613*3db86aabSstevel 		pcic_putb(pcic, socket, PCIC_POWER_CONTROL, pwr);
4614*3db86aabSstevel 		(void) pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
4615*3db86aabSstevel 	    }
4616*3db86aabSstevel 	}
4617*3db86aabSstevel 
4618*3db86aabSstevel 	pcic_err(pcic->dip, 7, "pcic_ll_reset returning 0x%x\n", windowbits);
4619*3db86aabSstevel 
4620*3db86aabSstevel 	return (windowbits);
4621*3db86aabSstevel }
4622*3db86aabSstevel 
4623*3db86aabSstevel /*
4624*3db86aabSstevel  * pcic_reset_socket()
4625*3db86aabSstevel  *	SocketServices ResetSocket function
4626*3db86aabSstevel  *	puts the PC Card in the socket into the RESET state
4627*3db86aabSstevel  *	and then takes it out after the the cycle time
4628*3db86aabSstevel  *	The socket is back to initial state when done
4629*3db86aabSstevel  */
4630*3db86aabSstevel static int
4631*3db86aabSstevel pcic_reset_socket(dev_info_t *dip, int socket, int mode)
4632*3db86aabSstevel {
4633*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4634*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4635*3db86aabSstevel 	int value;
4636*3db86aabSstevel 	int i, mint;
4637*3db86aabSstevel 	pcic_socket_t *sockp;
4638*3db86aabSstevel 
4639*3db86aabSstevel #if defined(PCIC_DEBUG)
4640*3db86aabSstevel 	if (pcic_debug >= 8)
4641*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_reset_socket(%p, %d, %d/%s)\n",
4642*3db86aabSstevel 		    (void *)dip, socket, mode,
4643*3db86aabSstevel 			mode == RESET_MODE_FULL ? "full" : "partial");
4644*3db86aabSstevel #endif
4645*3db86aabSstevel 
4646*3db86aabSstevel 	mutex_enter(&pcic->pc_lock); /* protect the registers */
4647*3db86aabSstevel 
4648*3db86aabSstevel 	/* Turn off management interupts. */
4649*3db86aabSstevel 	mint = pcic_getb(pcic, socket, PCIC_MANAGEMENT_INT);
4650*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_MANAGEMENT_INT, mint & ~PCIC_CHANGE_MASK);
4651*3db86aabSstevel 
4652*3db86aabSstevel 	sockp = &pcic->pc_sockets[socket];
4653*3db86aabSstevel 
4654*3db86aabSstevel 	value = pcic_ll_reset(pcic, socket);
4655*3db86aabSstevel 	if (mode == RESET_MODE_FULL) {
4656*3db86aabSstevel 		/* disable and unmap all mapped windows */
4657*3db86aabSstevel 		for (i = 0; i < PCIC_NUMWINSOCK; i++) {
4658*3db86aabSstevel 			if (i < PCIC_IOWINDOWS) {
4659*3db86aabSstevel 				if (sockp->pcs_windows[i].io.pcw_status &
4660*3db86aabSstevel 				    PCW_MAPPED) {
4661*3db86aabSstevel 					pcs_iowin_t *io;
4662*3db86aabSstevel 					io = &sockp->pcs_windows[i].io;
4663*3db86aabSstevel 					io->pcw_status &= ~PCW_ENABLED;
4664*3db86aabSstevel 				}
4665*3db86aabSstevel 			} else {
4666*3db86aabSstevel 				if (sockp->pcs_windows[i].mem.pcw_status &
4667*3db86aabSstevel 				    PCW_MAPPED) {
4668*3db86aabSstevel 					pcs_memwin_t *mem;
4669*3db86aabSstevel 					mem = &sockp->pcs_windows[i].mem;
4670*3db86aabSstevel 					mem->pcw_status &= ~PCW_ENABLED;
4671*3db86aabSstevel 				}
4672*3db86aabSstevel 			}
4673*3db86aabSstevel 		}
4674*3db86aabSstevel 	} else {
4675*3db86aabSstevel 				/* turn windows back on */
4676*3db86aabSstevel 		pcic_putb(pcic, socket, PCIC_MAPPING_ENABLE, value);
4677*3db86aabSstevel 		/* wait the rest of the time here */
4678*3db86aabSstevel 		pcic_mswait(pcic, socket, 10);
4679*3db86aabSstevel 	}
4680*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_MANAGEMENT_INT, mint);
4681*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
4682*3db86aabSstevel 	return (SUCCESS);
4683*3db86aabSstevel }
4684*3db86aabSstevel 
4685*3db86aabSstevel /*
4686*3db86aabSstevel  * pcic_set_interrupt()
4687*3db86aabSstevel  *	SocketServices SetInterrupt function
4688*3db86aabSstevel  */
4689*3db86aabSstevel static int
4690*3db86aabSstevel pcic_set_interrupt(dev_info_t *dip, set_irq_handler_t *handler)
4691*3db86aabSstevel {
4692*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4693*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4694*3db86aabSstevel 	int value = DDI_SUCCESS;
4695*3db86aabSstevel 	inthandler_t *intr;
4696*3db86aabSstevel 
4697*3db86aabSstevel #if defined(PCIC_DEBUG)
4698*3db86aabSstevel 	if (pcic_debug) {
4699*3db86aabSstevel 		cmn_err(CE_CONT,
4700*3db86aabSstevel 			"pcic_set_interrupt: entered pc_intr_mode=0x%x\n",
4701*3db86aabSstevel 			pcic->pc_intr_mode);
4702*3db86aabSstevel 		cmn_err(CE_CONT,
4703*3db86aabSstevel 			"\t irq_top=%p handler=%p handler_id=%x\n",
4704*3db86aabSstevel 			(void *)pcic->irq_top, (void *)handler->handler,
4705*3db86aabSstevel 			handler->handler_id);
4706*3db86aabSstevel 	}
4707*3db86aabSstevel #endif
4708*3db86aabSstevel 
4709*3db86aabSstevel 	/*
4710*3db86aabSstevel 	 * If we're on a PCI bus, we route all IO IRQs through a single
4711*3db86aabSstevel 	 *	PCI interrupt (typically INT A#) so we don't have to do
4712*3db86aabSstevel 	 *	much other than add the caller to general interrupt handler
4713*3db86aabSstevel 	 *	and set some state.
4714*3db86aabSstevel 	 */
4715*3db86aabSstevel 
4716*3db86aabSstevel 	intr = kmem_zalloc(sizeof (inthandler_t), KM_NOSLEEP);
4717*3db86aabSstevel 	if (intr == NULL)
4718*3db86aabSstevel 		return (NO_RESOURCE);
4719*3db86aabSstevel 
4720*3db86aabSstevel 	switch (pcic->pc_intr_mode) {
4721*3db86aabSstevel 	case PCIC_INTR_MODE_PCI_1:
4722*3db86aabSstevel 		/*
4723*3db86aabSstevel 		 * We only allow above-lock-level IO IRQ handlers
4724*3db86aabSstevel 		 *	in the PCI bus case.
4725*3db86aabSstevel 		 */
4726*3db86aabSstevel 
4727*3db86aabSstevel 		mutex_enter(&pcic->intr_lock);
4728*3db86aabSstevel 
4729*3db86aabSstevel 		if (pcic->irq_top == NULL) {
4730*3db86aabSstevel 		    pcic->irq_top = intr;
4731*3db86aabSstevel 		    pcic->irq_current = pcic->irq_top;
4732*3db86aabSstevel 		} else {
4733*3db86aabSstevel 		    while (pcic->irq_current->next != NULL)
4734*3db86aabSstevel 			pcic->irq_current = pcic->irq_current->next;
4735*3db86aabSstevel 		    pcic->irq_current->next = intr;
4736*3db86aabSstevel 		    pcic->irq_current = pcic->irq_current->next;
4737*3db86aabSstevel 		}
4738*3db86aabSstevel 
4739*3db86aabSstevel 		pcic->irq_current->intr =
4740*3db86aabSstevel 		    (ddi_intr_handler_t *)handler->handler;
4741*3db86aabSstevel 		pcic->irq_current->handler_id = handler->handler_id;
4742*3db86aabSstevel 		pcic->irq_current->arg1 = handler->arg1;
4743*3db86aabSstevel 		pcic->irq_current->arg2 = handler->arg2;
4744*3db86aabSstevel 		pcic->irq_current->socket = handler->socket;
4745*3db86aabSstevel 
4746*3db86aabSstevel 		mutex_exit(&pcic->intr_lock);
4747*3db86aabSstevel 
4748*3db86aabSstevel 		handler->iblk_cookie = &pcic->pc_pri;
4749*3db86aabSstevel 		handler->idev_cookie = &pcic->pc_dcookie;
4750*3db86aabSstevel 		break;
4751*3db86aabSstevel 
4752*3db86aabSstevel 	default:
4753*3db86aabSstevel 		intr->intr = (ddi_intr_handler_t *)handler->handler;
4754*3db86aabSstevel 		intr->handler_id = handler->handler_id;
4755*3db86aabSstevel 		intr->arg1 = handler->arg1;
4756*3db86aabSstevel 		intr->arg2 = handler->arg2;
4757*3db86aabSstevel 		intr->socket = handler->socket;
4758*3db86aabSstevel 		intr->irq = handler->irq;
4759*3db86aabSstevel 
4760*3db86aabSstevel 		/*
4761*3db86aabSstevel 		 * need to revisit this to see if interrupts can be
4762*3db86aabSstevel 		 * shared someday. Note that IRQ is set in the common
4763*3db86aabSstevel 		 * code.
4764*3db86aabSstevel 		 */
4765*3db86aabSstevel 		mutex_enter(&pcic->pc_lock);
4766*3db86aabSstevel 		if (pcic->pc_handlers == NULL) {
4767*3db86aabSstevel 			pcic->pc_handlers = intr;
4768*3db86aabSstevel 			intr->next = intr->prev = intr;
4769*3db86aabSstevel 		} else {
4770*3db86aabSstevel 			insque(intr, pcic->pc_handlers);
4771*3db86aabSstevel 		}
4772*3db86aabSstevel 		mutex_exit(&pcic->pc_lock);
4773*3db86aabSstevel 
4774*3db86aabSstevel 		break;
4775*3db86aabSstevel 	}
4776*3db86aabSstevel 
4777*3db86aabSstevel 	/*
4778*3db86aabSstevel 	 * need to fill in cookies in event of multiple high priority
4779*3db86aabSstevel 	 * interrupt handlers on same IRQ
4780*3db86aabSstevel 	 */
4781*3db86aabSstevel 
4782*3db86aabSstevel #if defined(PCIC_DEBUG)
4783*3db86aabSstevel 	if (pcic_debug) {
4784*3db86aabSstevel 		cmn_err(CE_CONT,
4785*3db86aabSstevel 			"pcic_set_interrupt: exit irq_top=%p value=%d\n",
4786*3db86aabSstevel 			(void *)pcic->irq_top, value);
4787*3db86aabSstevel 	}
4788*3db86aabSstevel #endif
4789*3db86aabSstevel 
4790*3db86aabSstevel 	if (value == DDI_SUCCESS) {
4791*3db86aabSstevel 		return (SUCCESS);
4792*3db86aabSstevel 	} else {
4793*3db86aabSstevel 		return (BAD_IRQ);
4794*3db86aabSstevel 	}
4795*3db86aabSstevel }
4796*3db86aabSstevel 
4797*3db86aabSstevel /*
4798*3db86aabSstevel  * pcic_clear_interrupt()
4799*3db86aabSstevel  *	SocketServices ClearInterrupt function
4800*3db86aabSstevel  *
4801*3db86aabSstevel  *	Interrupts for PCIC are complicated by the fact that we must
4802*3db86aabSstevel  *	follow several different models for interrupts.
4803*3db86aabSstevel  *	ISA: there is an interrupt per adapter and per socket and
4804*3db86aabSstevel  *		they can't be shared.
4805*3db86aabSstevel  *	PCI: some adapters have one PCI interrupt available while others
4806*3db86aabSstevel  *		have up to 4.  Solaris may or may not allow us to use more
4807*3db86aabSstevel  *		than 1 so we essentially share them all at this point.
4808*3db86aabSstevel  *	Hybrid: PCI bridge but interrupts wired to host interrupt controller.
4809*3db86aabSstevel  *		This is like ISA but we have to fudge and create an intrspec
4810*3db86aabSstevel  *		that PCI's parent understands and bypass the PCI nexus.
4811*3db86aabSstevel  *	multifunction: this requires sharing the interrupts on a per-socket
4812*3db86aabSstevel  *		basis.
4813*3db86aabSstevel  */
4814*3db86aabSstevel static int
4815*3db86aabSstevel pcic_clear_interrupt(dev_info_t *dip, clear_irq_handler_t *handler)
4816*3db86aabSstevel {
4817*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
4818*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
4819*3db86aabSstevel 	inthandler_t *intr, *prev, *current;
4820*3db86aabSstevel 	int i;
4821*3db86aabSstevel 
4822*3db86aabSstevel 	/*
4823*3db86aabSstevel 	 * If we're on a PCI bus, we route all IO IRQs through a single
4824*3db86aabSstevel 	 *	PCI interrupt (typically INT A#) so we don't have to do
4825*3db86aabSstevel 	 *	much other than remove the caller from the general
4826*3db86aabSstevel 	 *	interrupt handler callout list.
4827*3db86aabSstevel 	 */
4828*3db86aabSstevel 
4829*3db86aabSstevel #if defined(PCIC_DEBUG)
4830*3db86aabSstevel 	if (pcic_debug) {
4831*3db86aabSstevel 		cmn_err(CE_CONT,
4832*3db86aabSstevel 			"pcic_clear_interrupt: entered pc_intr_mode=0x%x\n",
4833*3db86aabSstevel 			pcic->pc_intr_mode);
4834*3db86aabSstevel 		cmn_err(CE_CONT,
4835*3db86aabSstevel 			"\t irq_top=%p handler=%p handler_id=%x\n",
4836*3db86aabSstevel 			(void *)pcic->irq_top, (void *)handler->handler,
4837*3db86aabSstevel 			handler->handler_id);
4838*3db86aabSstevel 	}
4839*3db86aabSstevel #endif
4840*3db86aabSstevel 
4841*3db86aabSstevel 	switch (pcic->pc_intr_mode) {
4842*3db86aabSstevel 	case PCIC_INTR_MODE_PCI_1:
4843*3db86aabSstevel 
4844*3db86aabSstevel 		mutex_enter(&pcic->intr_lock);
4845*3db86aabSstevel 		if (pcic->irq_top == NULL) {
4846*3db86aabSstevel 			mutex_exit(&pcic->intr_lock);
4847*3db86aabSstevel 			return (BAD_IRQ);
4848*3db86aabSstevel 		}
4849*3db86aabSstevel 
4850*3db86aabSstevel 		intr = NULL;
4851*3db86aabSstevel 		pcic->irq_current = pcic->irq_top;
4852*3db86aabSstevel 
4853*3db86aabSstevel 		while ((pcic->irq_current != NULL) &&
4854*3db86aabSstevel 				(pcic->irq_current->handler_id !=
4855*3db86aabSstevel 						handler->handler_id)) {
4856*3db86aabSstevel 			intr = pcic->irq_current;
4857*3db86aabSstevel 			pcic->irq_current = pcic->irq_current->next;
4858*3db86aabSstevel 		}
4859*3db86aabSstevel 
4860*3db86aabSstevel 		if (pcic->irq_current == NULL) {
4861*3db86aabSstevel 			mutex_exit(&pcic->intr_lock);
4862*3db86aabSstevel 			return (BAD_IRQ);
4863*3db86aabSstevel 		}
4864*3db86aabSstevel 
4865*3db86aabSstevel 		if (intr != NULL) {
4866*3db86aabSstevel 			intr->next = pcic->irq_current->next;
4867*3db86aabSstevel 		} else {
4868*3db86aabSstevel 			pcic->irq_top = pcic->irq_current->next;
4869*3db86aabSstevel 		}
4870*3db86aabSstevel 
4871*3db86aabSstevel 		current = pcic->irq_current;
4872*3db86aabSstevel 		pcic->irq_current = pcic->irq_top;
4873*3db86aabSstevel 		mutex_exit(&pcic->intr_lock);
4874*3db86aabSstevel 		kmem_free(current, sizeof (inthandler_t));
4875*3db86aabSstevel 
4876*3db86aabSstevel 		break;
4877*3db86aabSstevel 
4878*3db86aabSstevel 	default:
4879*3db86aabSstevel 
4880*3db86aabSstevel 		mutex_enter(&pcic->pc_lock);
4881*3db86aabSstevel 		intr = pcic_handlers;
4882*3db86aabSstevel 		prev = (inthandler_t *)&pcic_handlers;
4883*3db86aabSstevel 
4884*3db86aabSstevel 		while (intr != NULL) {
4885*3db86aabSstevel 		    if (intr->handler_id == handler->handler_id) {
4886*3db86aabSstevel 			i = intr->irq & PCIC_INTR_MASK;
4887*3db86aabSstevel 			if (--pcic_irq_map[i].count == 0) {
4888*3db86aabSstevel 				/* multi-handler form */
4889*3db86aabSstevel 				(void) ddi_intr_disable(pcic->pc_intr_htblp[i]);
4890*3db86aabSstevel 				(void) ddi_intr_remove_handler(
4891*3db86aabSstevel 				    pcic->pc_intr_htblp[i]);
4892*3db86aabSstevel 				(void) ddi_intr_free(pcic->pc_intr_htblp[i]);
4893*3db86aabSstevel 				(void) pcmcia_return_intr(pcic->dip, i);
4894*3db86aabSstevel #if defined(PCIC_DEBUG)
4895*3db86aabSstevel 				if (pcic_debug) {
4896*3db86aabSstevel 					cmn_err(CE_CONT,
4897*3db86aabSstevel 						"removing interrupt %d at %s "
4898*3db86aabSstevel 						"priority\n", i, "high");
4899*3db86aabSstevel 					cmn_err(CE_CONT,
4900*3db86aabSstevel 						"ddi_remove_intr(%p, %x, %p)\n",
4901*3db86aabSstevel 						(void *)dip,
4902*3db86aabSstevel 						0,
4903*3db86aabSstevel 						(void *)intr->iblk_cookie);
4904*3db86aabSstevel 				}
4905*3db86aabSstevel #endif
4906*3db86aabSstevel 			}
4907*3db86aabSstevel 			prev->next = intr->next;
4908*3db86aabSstevel 			kmem_free(intr, sizeof (inthandler_t));
4909*3db86aabSstevel 			intr = prev->next;
4910*3db86aabSstevel 		    } else {
4911*3db86aabSstevel 			prev = intr;
4912*3db86aabSstevel 			intr = intr->next;
4913*3db86aabSstevel 		    } /* if (handler_id) */
4914*3db86aabSstevel 		} /* while */
4915*3db86aabSstevel 
4916*3db86aabSstevel 		mutex_exit(&pcic->pc_lock);
4917*3db86aabSstevel 	}
4918*3db86aabSstevel 
4919*3db86aabSstevel #if defined(PCIC_DEBUG)
4920*3db86aabSstevel 	if (pcic_debug) {
4921*3db86aabSstevel 		cmn_err(CE_CONT,
4922*3db86aabSstevel 		"pcic_clear_interrupt: exit irq_top=%p\n",
4923*3db86aabSstevel 		(void *)pcic->irq_top);
4924*3db86aabSstevel 	}
4925*3db86aabSstevel #endif
4926*3db86aabSstevel 
4927*3db86aabSstevel 
4928*3db86aabSstevel 	return (SUCCESS);
4929*3db86aabSstevel }
4930*3db86aabSstevel 
4931*3db86aabSstevel struct intel_regs {
4932*3db86aabSstevel 	char *name;
4933*3db86aabSstevel 	int   off;
4934*3db86aabSstevel 	char *fmt;
4935*3db86aabSstevel } iregs[] = {
4936*3db86aabSstevel 	{"ident     ", 0},
4937*3db86aabSstevel 	{"if-status ", 1, "\020\1BVD1\2BVD2\3CD1\4CD2\5WP\6RDY\7PWR\10~GPI"},
4938*3db86aabSstevel 	{"power     ", 2, "\020\1Vpp1c0\2Vpp1c1\3Vpp2c0\4Vpp2c1\5PE\6AUTO"
4939*3db86aabSstevel 		"\7DRD\10OE"},
4940*3db86aabSstevel 	{"cardstatus", 4, "\020\1BD\2BW\3RC\4CD\5GPI\6R1\7R2\010R3"},
4941*3db86aabSstevel 	{"enable    ", 6, "\020\1MW0\2MW1\3MW2\4MW3\5MW4\6MEM16\7IO0\10IO1"},
4942*3db86aabSstevel 	{"cd-gcr    ", 0x16, "\020\1MDI16\2CRE\3GPIE\4GPIT\5CDR\6S/W"},
4943*3db86aabSstevel 	{"GCR       ", 0x1e, "\020\1PD\2LEVEL\3WCSC\4PLS14"},
4944*3db86aabSstevel 	{"int-gcr   ", 3, "\020\5INTR\6IO\7~RST\10RI"},
4945*3db86aabSstevel 	{"management", 5, "\020\1BDE\2BWE\3RE\4CDE"},
4946*3db86aabSstevel 	{"volt-sense", 0x1f, "\020\1A_VS1\2A_VS2\3B_VS1\4B_VS2"},
4947*3db86aabSstevel 	{"volt-sel  ", 0x2f, "\020\5EXTCONF\6BUSSELECT\7MIXEDV\10ISAV"},
4948*3db86aabSstevel 	{"VG ext A  ", 0x3c, "\20\3IVS\4CABLE\5CSTEP\6TEST\7RIO"},
4949*3db86aabSstevel 	{"io-ctrl   ", 7, "\020\1DS0\2IOCS0\3ZWS0\4WS0\5DS1\6IOS1\7ZWS1\10WS1"},
4950*3db86aabSstevel 	{"io0-slow  ", 8},
4951*3db86aabSstevel 	{"io0-shi   ", 9},
4952*3db86aabSstevel 	{"io0-elow  ", 0xa},
4953*3db86aabSstevel 	{"io0-ehi   ", 0xb},
4954*3db86aabSstevel 	{"io1-slow  ", 0xc},
4955*3db86aabSstevel 	{"io1-shi   ", 0xd},
4956*3db86aabSstevel 	{"io1-elow  ", 0xe},
4957*3db86aabSstevel 	{"io1-ehi   ", 0xf},
4958*3db86aabSstevel 	{"mem0-slow ", 0x10},
4959*3db86aabSstevel 	{"mem0-shi  ", 0x11, "\020\7ZW\10DS"},
4960*3db86aabSstevel 	{"mem0-elow ", 0x12},
4961*3db86aabSstevel 	{"mem0-ehi  ", 0x13, "\020\7WS0\10WS1"},
4962*3db86aabSstevel 	{"card0-low ", 0x14},
4963*3db86aabSstevel 	{"card0-hi  ", 0x15, "\020\7AM\10WP"},
4964*3db86aabSstevel 	{"mem1-slow ", 0x18},
4965*3db86aabSstevel 	{"mem1-shi  ", 0x19, "\020\7ZW\10DS"},
4966*3db86aabSstevel 	{"mem1-elow ", 0x1a},
4967*3db86aabSstevel 	{"mem1-ehi  ", 0x1b, "\020\7WS0\10WS1"},
4968*3db86aabSstevel 	{"card1-low ", 0x1c},
4969*3db86aabSstevel 	{"card1-hi  ", 0x1d, "\020\7AM\10WP"},
4970*3db86aabSstevel 	{"mem2-slow ", 0x20},
4971*3db86aabSstevel 	{"mem2-shi  ", 0x21, "\020\7ZW\10DS"},
4972*3db86aabSstevel 	{"mem2-elow ", 0x22},
4973*3db86aabSstevel 	{"mem2-ehi  ", 0x23, "\020\7WS0\10WS1"},
4974*3db86aabSstevel 	{"card2-low ", 0x24},
4975*3db86aabSstevel 	{"card2-hi  ", 0x25, "\020\7AM\10WP"},
4976*3db86aabSstevel 	{"mem3-slow ", 0x28},
4977*3db86aabSstevel 	{"mem3-shi  ", 0x29, "\020\7ZW\10DS"},
4978*3db86aabSstevel 	{"mem3-elow ", 0x2a},
4979*3db86aabSstevel 	{"mem3-ehi  ", 0x2b, "\020\7WS0\10WS1"},
4980*3db86aabSstevel 	{"card3-low ", 0x2c},
4981*3db86aabSstevel 	{"card3-hi  ", 0x2d, "\020\7AM\10WP"},
4982*3db86aabSstevel 
4983*3db86aabSstevel 	{"mem4-slow ", 0x30},
4984*3db86aabSstevel 	{"mem4-shi  ", 0x31, "\020\7ZW\10DS"},
4985*3db86aabSstevel 	{"mem4-elow ", 0x32},
4986*3db86aabSstevel 	{"mem4-ehi  ", 0x33, "\020\7WS0\10WS1"},
4987*3db86aabSstevel 	{"card4-low ", 0x34},
4988*3db86aabSstevel 	{"card4-hi  ", 0x35, "\020\7AM\10WP"},
4989*3db86aabSstevel 	{"mpage0    ", 0x40},
4990*3db86aabSstevel 	{"mpage1    ", 0x41},
4991*3db86aabSstevel 	{"mpage2    ", 0x42},
4992*3db86aabSstevel 	{"mpage3    ", 0x43},
4993*3db86aabSstevel 	{"mpage4    ", 0x44},
4994*3db86aabSstevel 	{NULL},
4995*3db86aabSstevel };
4996*3db86aabSstevel 
4997*3db86aabSstevel static struct intel_regs cregs[] = {
4998*3db86aabSstevel 	{"misc-ctl1 ", 0x16, "\20\2VCC3\3PMI\4PSI\5SPKR\10INPACK"},
4999*3db86aabSstevel 	{"fifo      ", 0x17, "\20\6DIOP\7DMEMP\10EMPTY"},
5000*3db86aabSstevel 	{"misc-ctl2 ", 0x1e, "\20\1XCLK\2LOW\3SUSP\4CORE5V\5TCD\10RIOUT"},
5001*3db86aabSstevel 	{"chip-info ", 0x1f, "\20\6DUAL"},
5002*3db86aabSstevel 	{"IO-offlow0", 0x36},
5003*3db86aabSstevel 	{"IO-offhi0 ", 0x37},
5004*3db86aabSstevel 	{"IO-offlow1", 0x38},
5005*3db86aabSstevel 	{"IO-offhi1 ", 0x39},
5006*3db86aabSstevel 	NULL,
5007*3db86aabSstevel };
5008*3db86aabSstevel 
5009*3db86aabSstevel static struct intel_regs cxregs[] = {
5010*3db86aabSstevel 	{"ext-ctl-1 ", 0x03,
5011*3db86aabSstevel 		"\20\1VCCLCK\2AUTOCLR\3LED\4INVIRQC\5INVIRQM\6PUC"},
5012*3db86aabSstevel 	{"misc-ctl3 ", 0x25, "\20\5HWSUSP"},
5013*3db86aabSstevel 	{"mem0-up   ", 0x05},
5014*3db86aabSstevel 	{"mem1-up   ", 0x06},
5015*3db86aabSstevel 	{"mem2-up   ", 0x07},
5016*3db86aabSstevel 	{"mem3-up   ", 0x08},
5017*3db86aabSstevel 	{"mem4-up   ", 0x09},
5018*3db86aabSstevel 	{NULL}
5019*3db86aabSstevel };
5020*3db86aabSstevel 
5021*3db86aabSstevel void
5022*3db86aabSstevel xxdmp_cl_regs(pcicdev_t *pcic, int socket, uint32_t len)
5023*3db86aabSstevel {
5024*3db86aabSstevel 	int i, value, j;
5025*3db86aabSstevel 	char buff[256];
5026*3db86aabSstevel 	char *fmt;
5027*3db86aabSstevel 
5028*3db86aabSstevel 	cmn_err(CE_CONT, "--------- Cirrus Logic Registers --------\n");
5029*3db86aabSstevel 	for (buff[0] = '\0', i = 0; cregs[i].name != NULL && len-- != 0; i++) {
5030*3db86aabSstevel 		int sval;
5031*3db86aabSstevel 		if (cregs[i].off == PCIC_MISC_CTL_2)
5032*3db86aabSstevel 			sval = 0;
5033*3db86aabSstevel 		else
5034*3db86aabSstevel 			sval = socket;
5035*3db86aabSstevel 		value = pcic_getb(pcic, sval, cregs[i].off);
5036*3db86aabSstevel 		if (i & 1) {
5037*3db86aabSstevel 			if (cregs[i].fmt)
5038*3db86aabSstevel 				fmt = "%s\t%s\t%b\n";
5039*3db86aabSstevel 			else
5040*3db86aabSstevel 				fmt = "%s\t%s\t%x\n";
5041*3db86aabSstevel 			cmn_err(CE_CONT, fmt, buff,
5042*3db86aabSstevel 				cregs[i].name, value, cregs[i].fmt);
5043*3db86aabSstevel 			buff[0] = '\0';
5044*3db86aabSstevel 		} else {
5045*3db86aabSstevel 			if (cregs[i].fmt)
5046*3db86aabSstevel 				fmt = "\t%s\t%b";
5047*3db86aabSstevel 			else
5048*3db86aabSstevel 				fmt = "\t%s\t%x";
5049*3db86aabSstevel 			(void) sprintf(buff, fmt,
5050*3db86aabSstevel 				cregs[i].name, value, cregs[i].fmt);
5051*3db86aabSstevel 			for (j = strlen(buff); j < 40; j++)
5052*3db86aabSstevel 				buff[j] = ' ';
5053*3db86aabSstevel 			buff[40] = '\0';
5054*3db86aabSstevel 		}
5055*3db86aabSstevel 	}
5056*3db86aabSstevel 	cmn_err(CE_CONT, "%s\n", buff);
5057*3db86aabSstevel 
5058*3db86aabSstevel 	i = pcic_getb(pcic, socket, PCIC_TIME_SETUP_0);
5059*3db86aabSstevel 	j = pcic_getb(pcic, socket, PCIC_TIME_SETUP_1);
5060*3db86aabSstevel 	cmn_err(CE_CONT, "\tsetup-tim0\t%x\tsetup-tim1\t%x\n", i, j);
5061*3db86aabSstevel 
5062*3db86aabSstevel 	i = pcic_getb(pcic, socket, PCIC_TIME_COMMAND_0);
5063*3db86aabSstevel 	j = pcic_getb(pcic, socket, PCIC_TIME_COMMAND_1);
5064*3db86aabSstevel 	cmn_err(CE_CONT, "\tcmd-tim0  \t%x\tcmd-tim1  \t%x\n", i, j);
5065*3db86aabSstevel 
5066*3db86aabSstevel 	i = pcic_getb(pcic, socket, PCIC_TIME_RECOVER_0);
5067*3db86aabSstevel 	j = pcic_getb(pcic, socket, PCIC_TIME_RECOVER_1);
5068*3db86aabSstevel 	cmn_err(CE_CONT, "\trcvr-tim0 \t%x\trcvr-tim1 \t%x\n", i, j);
5069*3db86aabSstevel 
5070*3db86aabSstevel 	cmn_err(CE_CONT, "--------- Extended Registers  --------\n");
5071*3db86aabSstevel 
5072*3db86aabSstevel 	for (buff[0] = '\0', i = 0; cxregs[i].name != NULL && len-- != 0; i++) {
5073*3db86aabSstevel 		value = clext_reg_read(pcic, socket, cxregs[i].off);
5074*3db86aabSstevel 		if (i & 1) {
5075*3db86aabSstevel 			if (cxregs[i].fmt)
5076*3db86aabSstevel 				fmt = "%s\t%s\t%b\n";
5077*3db86aabSstevel 			else
5078*3db86aabSstevel 				fmt = "%s\t%s\t%x\n";
5079*3db86aabSstevel 			cmn_err(CE_CONT, fmt, buff,
5080*3db86aabSstevel 				cxregs[i].name, value, cxregs[i].fmt);
5081*3db86aabSstevel 			buff[0] = '\0';
5082*3db86aabSstevel 		} else {
5083*3db86aabSstevel 			if (cxregs[i].fmt)
5084*3db86aabSstevel 				fmt = "\t%s\t%b";
5085*3db86aabSstevel 			else
5086*3db86aabSstevel 				fmt = "\t%s\t%x";
5087*3db86aabSstevel 			(void) sprintf(buff, fmt,
5088*3db86aabSstevel 				cxregs[i].name, value, cxregs[i].fmt);
5089*3db86aabSstevel 			for (j = strlen(buff); j < 40; j++)
5090*3db86aabSstevel 				buff[j] = ' ';
5091*3db86aabSstevel 			buff[40] = '\0';
5092*3db86aabSstevel 		}
5093*3db86aabSstevel 	}
5094*3db86aabSstevel }
5095*3db86aabSstevel 
5096*3db86aabSstevel #if defined(PCIC_DEBUG)
5097*3db86aabSstevel static void
5098*3db86aabSstevel xxdmp_all_regs(pcicdev_t *pcic, int socket, uint32_t len)
5099*3db86aabSstevel {
5100*3db86aabSstevel 	int i, value, j;
5101*3db86aabSstevel 	char buff[256];
5102*3db86aabSstevel 	char *fmt;
5103*3db86aabSstevel 
5104*3db86aabSstevel #if defined(PCIC_DEBUG)
5105*3db86aabSstevel 	if (pcic_debug < 2)
5106*3db86aabSstevel 		return;
5107*3db86aabSstevel #endif
5108*3db86aabSstevel 	cmn_err(CE_CONT,
5109*3db86aabSstevel 		"----------- PCIC Registers for socket %d---------\n",
5110*3db86aabSstevel 		socket);
5111*3db86aabSstevel 	cmn_err(CE_CONT,
5112*3db86aabSstevel 		"\tname       value                        name       value\n");
5113*3db86aabSstevel 
5114*3db86aabSstevel 	for (buff[0] = '\0', i = 0; iregs[i].name != NULL && len-- != 0; i++) {
5115*3db86aabSstevel 		value = pcic_getb(pcic, socket, iregs[i].off);
5116*3db86aabSstevel 		if (i & 1) {
5117*3db86aabSstevel 			if (iregs[i].fmt)
5118*3db86aabSstevel 				fmt = "%s\t%s\t%b\n";
5119*3db86aabSstevel 			else
5120*3db86aabSstevel 				fmt = "%s\t%s\t%x\n";
5121*3db86aabSstevel 			cmn_err(CE_CONT, fmt, buff,
5122*3db86aabSstevel 				iregs[i].name, value, iregs[i].fmt);
5123*3db86aabSstevel 			buff[0] = '\0';
5124*3db86aabSstevel 		} else {
5125*3db86aabSstevel 			if (iregs[i].fmt)
5126*3db86aabSstevel 				fmt = "\t%s\t%b";
5127*3db86aabSstevel 			else
5128*3db86aabSstevel 				fmt = "\t%s\t%x";
5129*3db86aabSstevel 			(void) sprintf(buff, fmt,
5130*3db86aabSstevel 				iregs[i].name, value, iregs[i].fmt);
5131*3db86aabSstevel 			for (j = strlen(buff); j < 40; j++)
5132*3db86aabSstevel 				buff[j] = ' ';
5133*3db86aabSstevel 			buff[40] = '\0';
5134*3db86aabSstevel 		}
5135*3db86aabSstevel 	}
5136*3db86aabSstevel 	switch (pcic->pc_type) {
5137*3db86aabSstevel 	case PCIC_CL_PD6710:
5138*3db86aabSstevel 	case PCIC_CL_PD6722:
5139*3db86aabSstevel 	case PCIC_CL_PD6729:
5140*3db86aabSstevel 	case PCIC_CL_PD6832:
5141*3db86aabSstevel 		(void) xxdmp_cl_regs(pcic, socket, 0xFFFF);
5142*3db86aabSstevel 		break;
5143*3db86aabSstevel 	}
5144*3db86aabSstevel 	cmn_err(CE_CONT, "%s\n", buff);
5145*3db86aabSstevel }
5146*3db86aabSstevel #endif
5147*3db86aabSstevel 
5148*3db86aabSstevel /*
5149*3db86aabSstevel  * pcic_mswait(ms)
5150*3db86aabSstevel  *	sleep ms milliseconds
5151*3db86aabSstevel  *	call drv_usecwait once for each ms
5152*3db86aabSstevel  */
5153*3db86aabSstevel static void
5154*3db86aabSstevel pcic_mswait(pcicdev_t *pcic, int socket, int ms)
5155*3db86aabSstevel {
5156*3db86aabSstevel 	if (ms) {
5157*3db86aabSstevel 		pcic->pc_sockets[socket].pcs_flags |= PCS_WAITING;
5158*3db86aabSstevel 		pcic_mutex_exit(&pcic->pc_lock);
5159*3db86aabSstevel 		delay(drv_usectohz(ms*1000));
5160*3db86aabSstevel 		pcic_mutex_enter(&pcic->pc_lock);
5161*3db86aabSstevel 		pcic->pc_sockets[socket].pcs_flags &= ~PCS_WAITING;
5162*3db86aabSstevel 	}
5163*3db86aabSstevel }
5164*3db86aabSstevel 
5165*3db86aabSstevel /*
5166*3db86aabSstevel  * pcic_check_ready(pcic, index, off)
5167*3db86aabSstevel  *      Wait for card to come ready
5168*3db86aabSstevel  *      We only wait if the card is NOT in RESET
5169*3db86aabSstevel  *      and power is on.
5170*3db86aabSstevel  */
5171*3db86aabSstevel static boolean_t
5172*3db86aabSstevel pcic_check_ready(pcicdev_t *pcic, int socket)
5173*3db86aabSstevel {
5174*3db86aabSstevel 	int ifstate, intstate;
5175*3db86aabSstevel 
5176*3db86aabSstevel 	intstate = pcic_getb(pcic, socket, PCIC_INTERRUPT);
5177*3db86aabSstevel 	ifstate = pcic_getb(pcic, socket, PCIC_INTERFACE_STATUS);
5178*3db86aabSstevel 
5179*3db86aabSstevel 	if ((intstate & PCIC_RESET) &&
5180*3db86aabSstevel 	    ((ifstate & (PCIC_READY|PCIC_POWER_ON|PCIC_ISTAT_CD_MASK)) ==
5181*3db86aabSstevel 	    (PCIC_READY|PCIC_POWER_ON|PCIC_CD_PRESENT_OK)))
5182*3db86aabSstevel 		return (B_TRUE);
5183*3db86aabSstevel 
5184*3db86aabSstevel #ifdef  PCIC_DEBUG
5185*3db86aabSstevel 	pcic_err(NULL, 5, "pcic_check_read: Card not ready, intstate = 0x%x, "
5186*3db86aabSstevel 	    "ifstate = 0x%x\n", intstate, ifstate);
5187*3db86aabSstevel 	if (pcic_debug) {
5188*3db86aabSstevel 		pcic_debug += 4;
5189*3db86aabSstevel 		xxdmp_all_regs(pcic, socket, -1);
5190*3db86aabSstevel 		pcic_debug -= 4;
5191*3db86aabSstevel 	}
5192*3db86aabSstevel #endif
5193*3db86aabSstevel 	return (B_FALSE);
5194*3db86aabSstevel }
5195*3db86aabSstevel 
5196*3db86aabSstevel /*
5197*3db86aabSstevel  * Cirrus Logic extended register read/write routines
5198*3db86aabSstevel  */
5199*3db86aabSstevel static int
5200*3db86aabSstevel clext_reg_read(pcicdev_t *pcic, int sn, uchar_t ext_reg)
5201*3db86aabSstevel {
5202*3db86aabSstevel 	int val;
5203*3db86aabSstevel 
5204*3db86aabSstevel 	switch (pcic->pc_io_type) {
5205*3db86aabSstevel 	case PCIC_IO_TYPE_YENTA:
5206*3db86aabSstevel 		val = ddi_get8(pcic->handle,
5207*3db86aabSstevel 		    pcic->ioaddr + CB_CLEXT_OFFSET + ext_reg);
5208*3db86aabSstevel 		break;
5209*3db86aabSstevel 	default:
5210*3db86aabSstevel 		pcic_putb(pcic, sn, PCIC_CL_EXINDEX, ext_reg);
5211*3db86aabSstevel 		val = pcic_getb(pcic, sn, PCIC_CL_EXINDEX + 1);
5212*3db86aabSstevel 		break;
5213*3db86aabSstevel 	}
5214*3db86aabSstevel 
5215*3db86aabSstevel 	return (val);
5216*3db86aabSstevel }
5217*3db86aabSstevel 
5218*3db86aabSstevel static void
5219*3db86aabSstevel clext_reg_write(pcicdev_t *pcic, int sn, uchar_t ext_reg, uchar_t value)
5220*3db86aabSstevel {
5221*3db86aabSstevel 	switch (pcic->pc_io_type) {
5222*3db86aabSstevel 	case PCIC_IO_TYPE_YENTA:
5223*3db86aabSstevel 		ddi_put8(pcic->handle,
5224*3db86aabSstevel 		    pcic->ioaddr + CB_CLEXT_OFFSET + ext_reg, value);
5225*3db86aabSstevel 		break;
5226*3db86aabSstevel 	default:
5227*3db86aabSstevel 		pcic_putb(pcic, sn, PCIC_CL_EXINDEX, ext_reg);
5228*3db86aabSstevel 		pcic_putb(pcic, sn, PCIC_CL_EXINDEX + 1, value);
5229*3db86aabSstevel 		break;
5230*3db86aabSstevel 	}
5231*3db86aabSstevel }
5232*3db86aabSstevel 
5233*3db86aabSstevel /*
5234*3db86aabSstevel  * Misc PCI functions
5235*3db86aabSstevel  */
5236*3db86aabSstevel static void
5237*3db86aabSstevel pcic_iomem_pci_ctl(ddi_acc_handle_t handle, uchar_t *cfgaddr, unsigned flags)
5238*3db86aabSstevel {
5239*3db86aabSstevel 	unsigned cmd;
5240*3db86aabSstevel 
5241*3db86aabSstevel 	if (flags & (PCIC_ENABLE_IO | PCIC_ENABLE_MEM)) {
5242*3db86aabSstevel 		cmd = ddi_get16(handle, (ushort_t *)(cfgaddr + 4));
5243*3db86aabSstevel 		if ((cmd & (PCI_COMM_IO|PCI_COMM_MAE)) ==
5244*3db86aabSstevel 		    (PCI_COMM_IO|PCI_COMM_MAE))
5245*3db86aabSstevel 			return;
5246*3db86aabSstevel 
5247*3db86aabSstevel 		if (flags & PCIC_ENABLE_IO)
5248*3db86aabSstevel 		    cmd |= PCI_COMM_IO;
5249*3db86aabSstevel 
5250*3db86aabSstevel 		if (flags & PCIC_ENABLE_MEM)
5251*3db86aabSstevel 		    cmd |= PCI_COMM_MAE;
5252*3db86aabSstevel 
5253*3db86aabSstevel 		ddi_put16(handle, (ushort_t *)(cfgaddr + 4), cmd);
5254*3db86aabSstevel 	} /* if (PCIC_ENABLE_IO | PCIC_ENABLE_MEM) */
5255*3db86aabSstevel }
5256*3db86aabSstevel 
5257*3db86aabSstevel /*
5258*3db86aabSstevel  * pcic_find_pci_type - Find and return PCI-PCMCIA adapter type
5259*3db86aabSstevel  */
5260*3db86aabSstevel static int
5261*3db86aabSstevel pcic_find_pci_type(pcicdev_t *pcic)
5262*3db86aabSstevel {
5263*3db86aabSstevel 	uint32_t vend, device;
5264*3db86aabSstevel 
5265*3db86aabSstevel 	vend = ddi_getprop(DDI_DEV_T_ANY, pcic->dip,
5266*3db86aabSstevel 				DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
5267*3db86aabSstevel 				"vendor-id", -1);
5268*3db86aabSstevel 	device = ddi_getprop(DDI_DEV_T_ANY, pcic->dip,
5269*3db86aabSstevel 				DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
5270*3db86aabSstevel 				"device-id", -1);
5271*3db86aabSstevel 
5272*3db86aabSstevel 	device = PCI_ID(vend, device);
5273*3db86aabSstevel 	pcic->pc_type = device;
5274*3db86aabSstevel 	pcic->pc_chipname = "PCI:unknown";
5275*3db86aabSstevel 
5276*3db86aabSstevel 	switch (device) {
5277*3db86aabSstevel 	case PCIC_INTEL_i82092:
5278*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_i82092;
5279*3db86aabSstevel 		break;
5280*3db86aabSstevel 	case PCIC_CL_PD6729:
5281*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PD6729;
5282*3db86aabSstevel 		/*
5283*3db86aabSstevel 		 * Some 6730's incorrectly identify themselves
5284*3db86aabSstevel 		 *	as a 6729, so we need to do some more tests
5285*3db86aabSstevel 		 *	here to see if the device that's claiming
5286*3db86aabSstevel 		 *	to be a 6729 is really a 6730.
5287*3db86aabSstevel 		 */
5288*3db86aabSstevel 		if ((clext_reg_read(pcic, 0, PCIC_CLEXT_MISC_CTL_3) &
5289*3db86aabSstevel 			PCIC_CLEXT_MISC_CTL_3_REV_MASK) ==
5290*3db86aabSstevel 				0) {
5291*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_PD6730;
5292*3db86aabSstevel 			pcic->pc_type = PCIC_CL_PD6730;
5293*3db86aabSstevel 		}
5294*3db86aabSstevel 		break;
5295*3db86aabSstevel 	case PCIC_CL_PD6730:
5296*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PD6730;
5297*3db86aabSstevel 		break;
5298*3db86aabSstevel 	case PCIC_CL_PD6832:
5299*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PD6832;
5300*3db86aabSstevel 		break;
5301*3db86aabSstevel 	case PCIC_SMC_34C90:
5302*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_34C90;
5303*3db86aabSstevel 		break;
5304*3db86aabSstevel 	case PCIC_TOSHIBA_TOPIC95:
5305*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_TOPIC95;
5306*3db86aabSstevel 		break;
5307*3db86aabSstevel 	case PCIC_TOSHIBA_TOPIC100:
5308*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_TOPIC100;
5309*3db86aabSstevel 		break;
5310*3db86aabSstevel 	case PCIC_TI_PCI1031:
5311*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1031;
5312*3db86aabSstevel 		break;
5313*3db86aabSstevel 	case PCIC_TI_PCI1130:
5314*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1130;
5315*3db86aabSstevel 		break;
5316*3db86aabSstevel 	case PCIC_TI_PCI1131:
5317*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1131;
5318*3db86aabSstevel 		break;
5319*3db86aabSstevel 	case PCIC_TI_PCI1250:
5320*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1250;
5321*3db86aabSstevel 		break;
5322*3db86aabSstevel 	case PCIC_TI_PCI1225:
5323*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1225;
5324*3db86aabSstevel 		break;
5325*3db86aabSstevel 	case PCIC_TI_PCI1410:
5326*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1410;
5327*3db86aabSstevel 		break;
5328*3db86aabSstevel 	case PCIC_TI_PCI1510:
5329*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1510;
5330*3db86aabSstevel 		break;
5331*3db86aabSstevel 	case PCIC_TI_PCI1520:
5332*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1520;
5333*3db86aabSstevel 		break;
5334*3db86aabSstevel 	case PCIC_TI_PCI1221:
5335*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1221;
5336*3db86aabSstevel 		break;
5337*3db86aabSstevel 	case PCIC_TI_PCI1050:
5338*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1050;
5339*3db86aabSstevel 		break;
5340*3db86aabSstevel 	case PCIC_ENE_1410:
5341*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_1410;
5342*3db86aabSstevel 		break;
5343*3db86aabSstevel 	case PCIC_O2_OZ6912:
5344*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_OZ6912;
5345*3db86aabSstevel 		break;
5346*3db86aabSstevel 	case PCIC_RICOH_RL5C466:
5347*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_RL5C466;
5348*3db86aabSstevel 		break;
5349*3db86aabSstevel 	case PCIC_TI_PCI1420:
5350*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_PCI1420;
5351*3db86aabSstevel 		break;
5352*3db86aabSstevel 	case PCIC_ENE_1420:
5353*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_1420;
5354*3db86aabSstevel 		break;
5355*3db86aabSstevel 	default:
5356*3db86aabSstevel 		switch (PCI_ID(vend, (uint32_t)0)) {
5357*3db86aabSstevel 		case PCIC_TOSHIBA_VENDOR:
5358*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_TOSHIBA;
5359*3db86aabSstevel 			pcic->pc_type = PCIC_TOSHIBA_VENDOR;
5360*3db86aabSstevel 			break;
5361*3db86aabSstevel 		case PCIC_TI_VENDOR:
5362*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_TI;
5363*3db86aabSstevel 			pcic->pc_type = PCIC_TI_VENDOR;
5364*3db86aabSstevel 			break;
5365*3db86aabSstevel 		case PCIC_O2MICRO_VENDOR:
5366*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_O2MICRO;
5367*3db86aabSstevel 			pcic->pc_type = PCIC_O2MICRO_VENDOR;
5368*3db86aabSstevel 			break;
5369*3db86aabSstevel 		case PCIC_RICOH_VENDOR:
5370*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_RICOH;
5371*3db86aabSstevel 			pcic->pc_type = PCIC_RICOH_VENDOR;
5372*3db86aabSstevel 			break;
5373*3db86aabSstevel 		default:
5374*3db86aabSstevel 			if (!(pcic->pc_flags & PCF_CARDBUS))
5375*3db86aabSstevel 				return (DDI_FAILURE);
5376*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_YENTA;
5377*3db86aabSstevel 			break;
5378*3db86aabSstevel 		}
5379*3db86aabSstevel 	}
5380*3db86aabSstevel 	return (DDI_SUCCESS);
5381*3db86aabSstevel }
5382*3db86aabSstevel 
5383*3db86aabSstevel static void
5384*3db86aabSstevel pcic_82092_smiirq_ctl(pcicdev_t *pcic, int socket, int intr, int state)
5385*3db86aabSstevel {
5386*3db86aabSstevel 	uchar_t ppirr = ddi_get8(pcic->cfg_handle,
5387*3db86aabSstevel 					pcic->cfgaddr + PCIC_82092_PPIRR);
5388*3db86aabSstevel 	uchar_t val;
5389*3db86aabSstevel 
5390*3db86aabSstevel 	if (intr == PCIC_82092_CTL_SMI) {
5391*3db86aabSstevel 		val = PCIC_82092_SMI_CTL(socket,
5392*3db86aabSstevel 						PCIC_82092_INT_DISABLE);
5393*3db86aabSstevel 		ppirr &= ~val;
5394*3db86aabSstevel 		val = PCIC_82092_SMI_CTL(socket, state);
5395*3db86aabSstevel 		ppirr |= val;
5396*3db86aabSstevel 	} else {
5397*3db86aabSstevel 		val = PCIC_82092_IRQ_CTL(socket,
5398*3db86aabSstevel 						PCIC_82092_INT_DISABLE);
5399*3db86aabSstevel 		ppirr &= ~val;
5400*3db86aabSstevel 		val = PCIC_82092_IRQ_CTL(socket, state);
5401*3db86aabSstevel 		ppirr |= val;
5402*3db86aabSstevel 	}
5403*3db86aabSstevel 	ddi_put8(pcic->cfg_handle, pcic->cfgaddr + PCIC_82092_PPIRR,
5404*3db86aabSstevel 			ppirr);
5405*3db86aabSstevel }
5406*3db86aabSstevel 
5407*3db86aabSstevel static uint_t
5408*3db86aabSstevel pcic_cd_softint(caddr_t arg1, caddr_t arg2)
5409*3db86aabSstevel {
5410*3db86aabSstevel 	pcic_socket_t *sockp = (pcic_socket_t *)arg1;
5411*3db86aabSstevel 	uint_t rc = DDI_INTR_UNCLAIMED;
5412*3db86aabSstevel 
5413*3db86aabSstevel 	_NOTE(ARGUNUSED(arg2))
5414*3db86aabSstevel 
5415*3db86aabSstevel 	mutex_enter(&sockp->pcs_pcic->pc_lock);
5416*3db86aabSstevel 	if (sockp->pcs_cd_softint_flg) {
5417*3db86aabSstevel 		uint8_t status;
5418*3db86aabSstevel 		sockp->pcs_cd_softint_flg = 0;
5419*3db86aabSstevel 		rc = DDI_INTR_CLAIMED;
5420*3db86aabSstevel 		status = pcic_getb(sockp->pcs_pcic, sockp->pcs_socket,
5421*3db86aabSstevel 			PCIC_INTERFACE_STATUS);
5422*3db86aabSstevel 		pcic_handle_cd_change(sockp->pcs_pcic, sockp, status);
5423*3db86aabSstevel 	}
5424*3db86aabSstevel 	mutex_exit(&sockp->pcs_pcic->pc_lock);
5425*3db86aabSstevel 	return (rc);
5426*3db86aabSstevel }
5427*3db86aabSstevel 
5428*3db86aabSstevel int pcic_debounce_cnt = PCIC_REM_DEBOUNCE_CNT;
5429*3db86aabSstevel int pcic_debounce_intr_time = PCIC_REM_DEBOUNCE_TIME;
5430*3db86aabSstevel int pcic_debounce_cnt_ok = PCIC_DEBOUNCE_OK_CNT;
5431*3db86aabSstevel 
5432*3db86aabSstevel #ifdef CARDBUS
5433*3db86aabSstevel static uint32_t pcic_cbps_on = 0;
5434*3db86aabSstevel static uint32_t pcic_cbps_off = CB_PS_NOTACARD | CB_PS_CCDMASK |
5435*3db86aabSstevel 				CB_PS_XVCARD | CB_PS_YVCARD;
5436*3db86aabSstevel #else
5437*3db86aabSstevel static uint32_t pcic_cbps_on = CB_PS_16BITCARD;
5438*3db86aabSstevel static uint32_t pcic_cbps_off = CB_PS_NOTACARD | CB_PS_CCDMASK |
5439*3db86aabSstevel 				CB_PS_CBCARD |
5440*3db86aabSstevel 				CB_PS_XVCARD | CB_PS_YVCARD;
5441*3db86aabSstevel #endif
5442*3db86aabSstevel static void
5443*3db86aabSstevel pcic_handle_cd_change(pcicdev_t *pcic, pcic_socket_t *sockp, uint8_t status)
5444*3db86aabSstevel {
5445*3db86aabSstevel 	boolean_t	do_debounce = B_FALSE;
5446*3db86aabSstevel 	int		debounce_time = drv_usectohz(pcic_debounce_time);
5447*3db86aabSstevel 	uint8_t		irq;
5448*3db86aabSstevel 	timeout_id_t	debounce;
5449*3db86aabSstevel 
5450*3db86aabSstevel 	/*
5451*3db86aabSstevel 	 * Always reset debounce but may need to check original state later.
5452*3db86aabSstevel 	 */
5453*3db86aabSstevel 	debounce = sockp->pcs_debounce_id;
5454*3db86aabSstevel 	sockp->pcs_debounce_id = 0;
5455*3db86aabSstevel 
5456*3db86aabSstevel 	/*
5457*3db86aabSstevel 	 * Check to see whether a card is present or not. There are
5458*3db86aabSstevel 	 *	only two states that we are concerned with - the state
5459*3db86aabSstevel 	 *	where both CD pins are asserted, which means that the
5460*3db86aabSstevel 	 *	card is fully seated, and the state where neither CD
5461*3db86aabSstevel 	 *	pin is asserted, which means that the card is not
5462*3db86aabSstevel 	 *	present.
5463*3db86aabSstevel 	 * The CD signals are generally very noisy and cause a lot of
5464*3db86aabSstevel 	 *	contact bounce as the card is being inserted and
5465*3db86aabSstevel 	 *	removed, so we need to do some software debouncing.
5466*3db86aabSstevel 	 */
5467*3db86aabSstevel 
5468*3db86aabSstevel #ifdef PCIC_DEBUG
5469*3db86aabSstevel 	    pcic_err(pcic->dip, 6,
5470*3db86aabSstevel 		    "pcic%d handle_cd_change: socket %d card status 0x%x"
5471*3db86aabSstevel 		    " deb 0x%p\n", ddi_get_instance(pcic->dip),
5472*3db86aabSstevel 		    sockp->pcs_socket, status, debounce);
5473*3db86aabSstevel #endif
5474*3db86aabSstevel 	switch (status & PCIC_ISTAT_CD_MASK) {
5475*3db86aabSstevel 	case PCIC_CD_PRESENT_OK:
5476*3db86aabSstevel 	    sockp->pcs_flags &= ~(PCS_CARD_REMOVED|PCS_CARD_CBREM);
5477*3db86aabSstevel 	    if (!(sockp->pcs_flags & PCS_CARD_PRESENT)) {
5478*3db86aabSstevel 		uint32_t cbps;
5479*3db86aabSstevel #ifdef PCIC_DEBUG
5480*3db86aabSstevel 		pcic_err(pcic->dip, 8, "New card (0x%x)\n", sockp->pcs_flags);
5481*3db86aabSstevel #endif
5482*3db86aabSstevel 		cbps = pcic_getcb(pcic, CB_PRESENT_STATE);
5483*3db86aabSstevel #ifdef PCIC_DEBUG
5484*3db86aabSstevel 		pcic_err(pcic->dip, 8, "CBus PS (0x%x)\n", cbps);
5485*3db86aabSstevel #endif
5486*3db86aabSstevel 		/*
5487*3db86aabSstevel 		 * Check the CB bits are sane.
5488*3db86aabSstevel 		 */
5489*3db86aabSstevel 		if ((cbps & pcic_cbps_on) != pcic_cbps_on ||
5490*3db86aabSstevel 		    cbps & pcic_cbps_off) {
5491*3db86aabSstevel 		    cmn_err(CE_WARN,
5492*3db86aabSstevel 			    "%s%d: Odd Cardbus Present State 0x%x\n",
5493*3db86aabSstevel 			    ddi_get_name(pcic->dip),
5494*3db86aabSstevel 			    ddi_get_instance(pcic->dip),
5495*3db86aabSstevel 			    cbps);
5496*3db86aabSstevel 		    pcic_putcb(pcic, CB_EVENT_FORCE, CB_EF_CVTEST);
5497*3db86aabSstevel 		    debounce = 0;
5498*3db86aabSstevel 		    debounce_time = drv_usectohz(1000000);
5499*3db86aabSstevel 		}
5500*3db86aabSstevel 		if (debounce) {
5501*3db86aabSstevel 		    sockp->pcs_flags |= PCS_CARD_PRESENT;
5502*3db86aabSstevel 		    if (pcic_do_insertion) {
5503*3db86aabSstevel 
5504*3db86aabSstevel 			cbps = pcic_getcb(pcic, CB_PRESENT_STATE);
5505*3db86aabSstevel 
5506*3db86aabSstevel 			if (cbps & CB_PS_16BITCARD) {
5507*3db86aabSstevel 			    pcic_err(pcic->dip, 8, "16 bit card inserted\n");
5508*3db86aabSstevel 			    sockp->pcs_flags |= PCS_CARD_IS16BIT;
5509*3db86aabSstevel 			    /* calls pcm_adapter_callback() */
5510*3db86aabSstevel 			    if (pcic->pc_callback) {
5511*3db86aabSstevel 
5512*3db86aabSstevel 				(void) ddi_prop_update_string(DDI_DEV_T_NONE,
5513*3db86aabSstevel 					pcic->dip, PCM_DEVICETYPE,
5514*3db86aabSstevel 					"pccard");
5515*3db86aabSstevel 				PC_CALLBACK(pcic->dip, pcic->pc_cb_arg,
5516*3db86aabSstevel 					    PCE_CARD_INSERT,
5517*3db86aabSstevel 					    sockp->pcs_socket);
5518*3db86aabSstevel 			    }
5519*3db86aabSstevel 			} else if (cbps & CB_PS_CBCARD) {
5520*3db86aabSstevel 			    pcic_err(pcic->dip, 8, "32 bit card inserted\n");
5521*3db86aabSstevel 
5522*3db86aabSstevel 			    if (pcic->pc_flags & PCF_CARDBUS) {
5523*3db86aabSstevel 				sockp->pcs_flags |= PCS_CARD_ISCARDBUS;
5524*3db86aabSstevel #ifdef CARDBUS
5525*3db86aabSstevel 				if (!pcic_load_cardbus(pcic, sockp)) {
5526*3db86aabSstevel 				    pcic_unload_cardbus(pcic, sockp);
5527*3db86aabSstevel 				}
5528*3db86aabSstevel 
5529*3db86aabSstevel #else
5530*3db86aabSstevel 				cmn_err(CE_NOTE,
5531*3db86aabSstevel 					"32 bit Cardbus not supported in"
5532*3db86aabSstevel 					" this device driver\n");
5533*3db86aabSstevel #endif
5534*3db86aabSstevel 			    } else {
5535*3db86aabSstevel 				/*
5536*3db86aabSstevel 				 * Ignore the card
5537*3db86aabSstevel 				 */
5538*3db86aabSstevel 				cmn_err(CE_NOTE,
5539*3db86aabSstevel 					"32 bit Cardbus not supported on this"
5540*3db86aabSstevel 					" device\n");
5541*3db86aabSstevel 			    }
5542*3db86aabSstevel 			} else {
5543*3db86aabSstevel 			    cmn_err(CE_NOTE,
5544*3db86aabSstevel 				"Unsupported PCMCIA card inserted\n");
5545*3db86aabSstevel 			}
5546*3db86aabSstevel 		    }
5547*3db86aabSstevel 		    syshw_send_signal(sockp->pcs_syshwsig);
5548*3db86aabSstevel 		} else {
5549*3db86aabSstevel 		    do_debounce = B_TRUE;
5550*3db86aabSstevel 		}
5551*3db86aabSstevel 	    } else {
5552*3db86aabSstevel 		/*
5553*3db86aabSstevel 		 * It is possible to come through here if the system
5554*3db86aabSstevel 		 * starts up with cards already inserted. Do nothing
5555*3db86aabSstevel 		 * and don't worry about it.
5556*3db86aabSstevel 		 */
5557*3db86aabSstevel #ifdef PCIC_DEBUG
5558*3db86aabSstevel 		pcic_err(pcic->dip, 5,
5559*3db86aabSstevel 			"pcic%d: Odd card insertion indication on socket %d\n",
5560*3db86aabSstevel 			ddi_get_instance(pcic->dip),
5561*3db86aabSstevel 			sockp->pcs_socket);
5562*3db86aabSstevel #endif
5563*3db86aabSstevel 	    }
5564*3db86aabSstevel 	    break;
5565*3db86aabSstevel 
5566*3db86aabSstevel 	default:
5567*3db86aabSstevel 	    if (!(sockp->pcs_flags & PCS_CARD_PRESENT)) {
5568*3db86aabSstevel 		/*
5569*3db86aabSstevel 		 * Someone has started to insert a card so delay a while.
5570*3db86aabSstevel 		 */
5571*3db86aabSstevel 		do_debounce = B_TRUE;
5572*3db86aabSstevel 		break;
5573*3db86aabSstevel 	    }
5574*3db86aabSstevel 		/*
5575*3db86aabSstevel 		 * Otherwise this is basically the same as not present
5576*3db86aabSstevel 		 * so fall through.
5577*3db86aabSstevel 		 */
5578*3db86aabSstevel 
5579*3db86aabSstevel 		/* FALLTHRU */
5580*3db86aabSstevel 	case 0:
5581*3db86aabSstevel 	    if (sockp->pcs_flags & PCS_CARD_PRESENT) {
5582*3db86aabSstevel 		if (pcic->pc_flags & PCF_CBPWRCTL) {
5583*3db86aabSstevel 		    pcic_putcb(pcic, CB_CONTROL, 0);
5584*3db86aabSstevel 		} else {
5585*3db86aabSstevel 		    pcic_putb(pcic, sockp->pcs_socket, PCIC_POWER_CONTROL, 0);
5586*3db86aabSstevel 		    (void) pcic_getb(pcic, sockp->pcs_socket,
5587*3db86aabSstevel 			PCIC_POWER_CONTROL);
5588*3db86aabSstevel 		}
5589*3db86aabSstevel #ifdef PCIC_DEBUG
5590*3db86aabSstevel 		pcic_err(pcic->dip, 8, "Card removed\n");
5591*3db86aabSstevel #endif
5592*3db86aabSstevel 		sockp->pcs_flags &= ~PCS_CARD_PRESENT;
5593*3db86aabSstevel 
5594*3db86aabSstevel 		if (sockp->pcs_flags & PCS_CARD_IS16BIT) {
5595*3db86aabSstevel 		    sockp->pcs_flags &= ~PCS_CARD_IS16BIT;
5596*3db86aabSstevel 		    if (pcic_do_removal && pcic->pc_callback) {
5597*3db86aabSstevel 			PC_CALLBACK(pcic->dip, pcic->pc_cb_arg,
5598*3db86aabSstevel 				    PCE_CARD_REMOVAL, sockp->pcs_socket);
5599*3db86aabSstevel 		    }
5600*3db86aabSstevel 		}
5601*3db86aabSstevel 		if (sockp->pcs_flags & PCS_CARD_ISCARDBUS) {
5602*3db86aabSstevel 		    sockp->pcs_flags &= ~PCS_CARD_ISCARDBUS;
5603*3db86aabSstevel 		    sockp->pcs_flags |= PCS_CARD_CBREM;
5604*3db86aabSstevel 		}
5605*3db86aabSstevel 		sockp->pcs_flags |= PCS_CARD_REMOVED;
5606*3db86aabSstevel 
5607*3db86aabSstevel 		do_debounce = B_TRUE;
5608*3db86aabSstevel 	    }
5609*3db86aabSstevel 	    if (debounce && (sockp->pcs_flags & PCS_CARD_REMOVED)) {
5610*3db86aabSstevel 		if (sockp->pcs_flags & PCS_CARD_CBREM) {
5611*3db86aabSstevel 		/*
5612*3db86aabSstevel 		 * Ensure that we do the unloading in the
5613*3db86aabSstevel 		 * debounce handler, that way we're not doing
5614*3db86aabSstevel 		 * nasty things in an interrupt handler. e.g.
5615*3db86aabSstevel 		 * a USB device will wait for data which will
5616*3db86aabSstevel 		 * obviously never come because we've
5617*3db86aabSstevel 		 * unplugged the device, but the wait will
5618*3db86aabSstevel 		 * wait forever because no interrupts can
5619*3db86aabSstevel 		 * come in...
5620*3db86aabSstevel 		 */
5621*3db86aabSstevel #ifdef CARDBUS
5622*3db86aabSstevel 		    pcic_unload_cardbus(pcic, sockp);
5623*3db86aabSstevel 		    /* pcic_dump_all(pcic); */
5624*3db86aabSstevel #endif
5625*3db86aabSstevel 		    sockp->pcs_flags &= ~PCS_CARD_CBREM;
5626*3db86aabSstevel 		}
5627*3db86aabSstevel 		syshw_send_signal(sockp->pcs_syshwsig);
5628*3db86aabSstevel 		sockp->pcs_flags &= ~PCS_CARD_REMOVED;
5629*3db86aabSstevel 	    }
5630*3db86aabSstevel 	    break;
5631*3db86aabSstevel 	} /* switch */
5632*3db86aabSstevel 
5633*3db86aabSstevel 	if (do_debounce) {
5634*3db86aabSstevel 	/*
5635*3db86aabSstevel 	 * Delay doing
5636*3db86aabSstevel 	 * anything for a while so that things can settle
5637*3db86aabSstevel 	 * down a little. Interrupts are already disabled.
5638*3db86aabSstevel 	 * Reset the state and we'll reevaluate the
5639*3db86aabSstevel 	 * whole kit 'n kaboodle when the timeout fires
5640*3db86aabSstevel 	 */
5641*3db86aabSstevel #ifdef PCIC_DEBUG
5642*3db86aabSstevel 		pcic_err(pcic->dip, 8, "Queueing up debounce timeout for "
5643*3db86aabSstevel 			"socket %d.%d\n",
5644*3db86aabSstevel 			ddi_get_instance(pcic->dip),
5645*3db86aabSstevel 			sockp->pcs_socket);
5646*3db86aabSstevel #endif
5647*3db86aabSstevel 	    sockp->pcs_debounce_id = pcic_add_debqueue(sockp, debounce_time);
5648*3db86aabSstevel 
5649*3db86aabSstevel 	/*
5650*3db86aabSstevel 	 * We bug out here without re-enabling interrupts. They will
5651*3db86aabSstevel 	 * be re-enabled when the debounce timeout swings through
5652*3db86aabSstevel 	 * here.
5653*3db86aabSstevel 	 */
5654*3db86aabSstevel 	    return;
5655*3db86aabSstevel 	}
5656*3db86aabSstevel 
5657*3db86aabSstevel 	/*
5658*3db86aabSstevel 	 * Turn on Card detect interrupts. Other interrupts will be
5659*3db86aabSstevel 	 * enabled during set_socket calls.
5660*3db86aabSstevel 	 *
5661*3db86aabSstevel 	 * Note that set_socket only changes interrupt settings when there
5662*3db86aabSstevel 	 * is a card present.
5663*3db86aabSstevel 	 */
5664*3db86aabSstevel 	irq = pcic_getb(pcic, sockp->pcs_socket, PCIC_MANAGEMENT_INT);
5665*3db86aabSstevel 	irq |= PCIC_CD_DETECT;
5666*3db86aabSstevel 	pcic_putb(pcic, sockp->pcs_socket, PCIC_MANAGEMENT_INT, irq);
5667*3db86aabSstevel 
5668*3db86aabSstevel 	pcic_err(pcic->dip, 7, "Leaving pcic_handle_cd_change\n");
5669*3db86aabSstevel }
5670*3db86aabSstevel 
5671*3db86aabSstevel /*
5672*3db86aabSstevel  * pcic_getb()
5673*3db86aabSstevel  *	get an I/O byte based on the yardware decode method
5674*3db86aabSstevel  */
5675*3db86aabSstevel static uint8_t
5676*3db86aabSstevel pcic_getb(pcicdev_t *pcic, int socket, int reg)
5677*3db86aabSstevel {
5678*3db86aabSstevel 	int work;
5679*3db86aabSstevel 
5680*3db86aabSstevel #if defined(PCIC_DEBUG)
5681*3db86aabSstevel 	if (pcic_debug == 0x7fff) {
5682*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_getb0: pcic=%p socket=%d reg=%d\n",
5683*3db86aabSstevel 			(void *)pcic, socket, reg);
5684*3db86aabSstevel 		cmn_err(CE_CONT, "pcic_getb1: type=%d handle=%p ioaddr=%p \n",
5685*3db86aabSstevel 			pcic->pc_io_type, (void *)pcic->handle,
5686*3db86aabSstevel 			(void *)pcic->ioaddr);
5687*3db86aabSstevel 	}
5688*3db86aabSstevel #endif
5689*3db86aabSstevel 
5690*3db86aabSstevel 	switch (pcic->pc_io_type) {
5691*3db86aabSstevel 	case PCIC_IO_TYPE_YENTA:
5692*3db86aabSstevel 		return (ddi_get8(pcic->handle,
5693*3db86aabSstevel 		    pcic->ioaddr + CB_R2_OFFSET + reg));
5694*3db86aabSstevel 	default:
5695*3db86aabSstevel 		work = (socket * PCIC_SOCKET_1) | reg;
5696*3db86aabSstevel 		ddi_put8(pcic->handle, pcic->ioaddr, work);
5697*3db86aabSstevel 		return (ddi_get8(pcic->handle, pcic->ioaddr + 1));
5698*3db86aabSstevel 	}
5699*3db86aabSstevel }
5700*3db86aabSstevel 
5701*3db86aabSstevel static void
5702*3db86aabSstevel pcic_putb(pcicdev_t *pcic, int socket, int reg, int8_t value)
5703*3db86aabSstevel {
5704*3db86aabSstevel 	int work;
5705*3db86aabSstevel 
5706*3db86aabSstevel #if defined(PCIC_DEBUG)
5707*3db86aabSstevel 	if (pcic_debug == 0x7fff) {
5708*3db86aabSstevel 		cmn_err(CE_CONT,
5709*3db86aabSstevel 			"pcic_putb0: pcic=%p socket=%d reg=%d value=%x \n",
5710*3db86aabSstevel 			(void *)pcic, socket, reg, value);
5711*3db86aabSstevel 		cmn_err(CE_CONT,
5712*3db86aabSstevel 			"pcic_putb1: type=%d handle=%p ioaddr=%p \n",
5713*3db86aabSstevel 			pcic->pc_io_type, (void *)pcic->handle,
5714*3db86aabSstevel 			(void *)pcic->ioaddr);
5715*3db86aabSstevel 	}
5716*3db86aabSstevel #endif
5717*3db86aabSstevel 
5718*3db86aabSstevel 
5719*3db86aabSstevel 	switch (pcic->pc_io_type) {
5720*3db86aabSstevel 	case PCIC_IO_TYPE_YENTA:
5721*3db86aabSstevel 		ddi_put8(pcic->handle, pcic->ioaddr + CB_R2_OFFSET + reg,
5722*3db86aabSstevel 				value);
5723*3db86aabSstevel 		break;
5724*3db86aabSstevel 	default:
5725*3db86aabSstevel 		work = (socket * PCIC_SOCKET_1) | reg;
5726*3db86aabSstevel 		ddi_put8(pcic->handle, pcic->ioaddr, work);
5727*3db86aabSstevel 		ddi_put8(pcic->handle, pcic->ioaddr + 1, value);
5728*3db86aabSstevel 		break;
5729*3db86aabSstevel 	}
5730*3db86aabSstevel }
5731*3db86aabSstevel 
5732*3db86aabSstevel /*
5733*3db86aabSstevel  * chip identification functions
5734*3db86aabSstevel  */
5735*3db86aabSstevel 
5736*3db86aabSstevel /*
5737*3db86aabSstevel  * chip identification: Cirrus Logic PD6710/6720/6722
5738*3db86aabSstevel  */
5739*3db86aabSstevel static int
5740*3db86aabSstevel pcic_ci_cirrus(pcicdev_t *pcic)
5741*3db86aabSstevel {
5742*3db86aabSstevel 	int value1, value2;
5743*3db86aabSstevel 
5744*3db86aabSstevel 	/* Init the CL id mode */
5745*3db86aabSstevel 	value1 = pcic_getb(pcic, 0, PCIC_CHIP_INFO);
5746*3db86aabSstevel 	pcic_putb(pcic, 0, PCIC_CHIP_INFO, 0);
5747*3db86aabSstevel 	value1 = pcic_getb(pcic, 0, PCIC_CHIP_INFO);
5748*3db86aabSstevel 	value2 = pcic_getb(pcic, 0, PCIC_CHIP_INFO);
5749*3db86aabSstevel 
5750*3db86aabSstevel 	if ((value1 & PCIC_CI_ID) == PCIC_CI_ID &&
5751*3db86aabSstevel 	    (value2 & PCIC_CI_ID) == 0) {
5752*3db86aabSstevel 		/* chip is a Cirrus Logic and not Intel */
5753*3db86aabSstevel 		pcic->pc_type = PCIC_CL_PD6710;
5754*3db86aabSstevel 		if (value1 & PCIC_CI_SLOTS)
5755*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_PD6720;
5756*3db86aabSstevel 		else
5757*3db86aabSstevel 			pcic->pc_chipname = PCIC_TYPE_PD6710;
5758*3db86aabSstevel 		/* now fine tune things just in case a 6722 */
5759*3db86aabSstevel 		value1 = clext_reg_read(pcic, 0, PCIC_CLEXT_DMASK_0);
5760*3db86aabSstevel 		if (value1 == 0) {
5761*3db86aabSstevel 			clext_reg_write(pcic, 0, PCIC_CLEXT_SCRATCH, 0x55);
5762*3db86aabSstevel 			value1 = clext_reg_read(pcic, 0, PCIC_CLEXT_SCRATCH);
5763*3db86aabSstevel 			if (value1 == 0x55) {
5764*3db86aabSstevel 				pcic->pc_chipname = PCIC_TYPE_PD6722;
5765*3db86aabSstevel 				pcic->pc_type = PCIC_CL_PD6722;
5766*3db86aabSstevel 				clext_reg_write(pcic, 0, PCIC_CLEXT_SCRATCH, 0);
5767*3db86aabSstevel 			}
5768*3db86aabSstevel 		}
5769*3db86aabSstevel 		return (1);
5770*3db86aabSstevel 	}
5771*3db86aabSstevel 	return (0);
5772*3db86aabSstevel }
5773*3db86aabSstevel 
5774*3db86aabSstevel /*
5775*3db86aabSstevel  * chip identification: Vadem (VG365/465/468/469)
5776*3db86aabSstevel  */
5777*3db86aabSstevel 
5778*3db86aabSstevel static void
5779*3db86aabSstevel pcic_vadem_enable(pcicdev_t *pcic)
5780*3db86aabSstevel {
5781*3db86aabSstevel 	ddi_put8(pcic->handle, pcic->ioaddr, PCIC_VADEM_P1);
5782*3db86aabSstevel 	ddi_put8(pcic->handle, pcic->ioaddr, PCIC_VADEM_P2);
5783*3db86aabSstevel 	ddi_put8(pcic->handle, pcic->ioaddr, pcic->pc_lastreg);
5784*3db86aabSstevel }
5785*3db86aabSstevel 
5786*3db86aabSstevel static int
5787*3db86aabSstevel pcic_ci_vadem(pcicdev_t *pcic)
5788*3db86aabSstevel {
5789*3db86aabSstevel 	int value;
5790*3db86aabSstevel 
5791*3db86aabSstevel 	pcic_vadem_enable(pcic);
5792*3db86aabSstevel 	value = pcic_getb(pcic, 0, PCIC_CHIP_REVISION);
5793*3db86aabSstevel 	pcic_putb(pcic, 0, PCIC_CHIP_REVISION, 0xFF);
5794*3db86aabSstevel 	if (pcic_getb(pcic, 0, PCIC_CHIP_REVISION) ==
5795*3db86aabSstevel 	    (value | PCIC_VADEM_D3) ||
5796*3db86aabSstevel 	    (pcic_getb(pcic, 0, PCIC_CHIP_REVISION) & PCIC_REV_MASK) ==
5797*3db86aabSstevel 	    PCIC_VADEM_469) {
5798*3db86aabSstevel 		int vadem, new;
5799*3db86aabSstevel 		pcic_vadem_enable(pcic);
5800*3db86aabSstevel 		vadem = pcic_getb(pcic, 0, PCIC_VG_DMA) &
5801*3db86aabSstevel 			~(PCIC_V_UNLOCK | PCIC_V_VADEMREV);
5802*3db86aabSstevel 		new = vadem | (PCIC_V_VADEMREV|PCIC_V_UNLOCK);
5803*3db86aabSstevel 		pcic_putb(pcic, 0, PCIC_VG_DMA, new);
5804*3db86aabSstevel 		value = pcic_getb(pcic, 0, PCIC_CHIP_REVISION);
5805*3db86aabSstevel 
5806*3db86aabSstevel 		/* want to lock but leave mouse or other on */
5807*3db86aabSstevel 		pcic_putb(pcic, 0, PCIC_VG_DMA, vadem);
5808*3db86aabSstevel 		switch (value & PCIC_REV_MASK) {
5809*3db86aabSstevel 		case PCIC_VADEM_365:
5810*3db86aabSstevel 			pcic->pc_chipname = PCIC_VG_365;
5811*3db86aabSstevel 			pcic->pc_type = PCIC_VADEM;
5812*3db86aabSstevel 			break;
5813*3db86aabSstevel 		case PCIC_VADEM_465:
5814*3db86aabSstevel 			pcic->pc_chipname = PCIC_VG_465;
5815*3db86aabSstevel 			pcic->pc_type = PCIC_VADEM;
5816*3db86aabSstevel 			pcic->pc_flags |= PCF_1SOCKET;
5817*3db86aabSstevel 			break;
5818*3db86aabSstevel 		case PCIC_VADEM_468:
5819*3db86aabSstevel 			pcic->pc_chipname = PCIC_VG_468;
5820*3db86aabSstevel 			pcic->pc_type = PCIC_VADEM;
5821*3db86aabSstevel 			break;
5822*3db86aabSstevel 		case PCIC_VADEM_469:
5823*3db86aabSstevel 			pcic->pc_chipname = PCIC_VG_469;
5824*3db86aabSstevel 			pcic->pc_type = PCIC_VADEM_VG469;
5825*3db86aabSstevel 			break;
5826*3db86aabSstevel 		}
5827*3db86aabSstevel 		return (1);
5828*3db86aabSstevel 	}
5829*3db86aabSstevel 	return (0);
5830*3db86aabSstevel }
5831*3db86aabSstevel 
5832*3db86aabSstevel /*
5833*3db86aabSstevel  * chip identification: Ricoh
5834*3db86aabSstevel  */
5835*3db86aabSstevel static int
5836*3db86aabSstevel pcic_ci_ricoh(pcicdev_t *pcic)
5837*3db86aabSstevel {
5838*3db86aabSstevel 	int value;
5839*3db86aabSstevel 
5840*3db86aabSstevel 	value = pcic_getb(pcic, 0, PCIC_RF_CHIP_IDENT);
5841*3db86aabSstevel 	switch (value) {
5842*3db86aabSstevel 	case PCIC_RF_296:
5843*3db86aabSstevel 		pcic->pc_type = PCIC_RICOH;
5844*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_RF5C296;
5845*3db86aabSstevel 		return (1);
5846*3db86aabSstevel 	case PCIC_RF_396:
5847*3db86aabSstevel 		pcic->pc_type = PCIC_RICOH;
5848*3db86aabSstevel 		pcic->pc_chipname = PCIC_TYPE_RF5C396;
5849*3db86aabSstevel 		return (1);
5850*3db86aabSstevel 	}
5851*3db86aabSstevel 	return (0);
5852*3db86aabSstevel }
5853*3db86aabSstevel 
5854*3db86aabSstevel 
5855*3db86aabSstevel /*
5856*3db86aabSstevel  * set up available address spaces in busra
5857*3db86aabSstevel  */
5858*3db86aabSstevel static void
5859*3db86aabSstevel pcic_init_assigned(dev_info_t *dip)
5860*3db86aabSstevel {
5861*3db86aabSstevel 	pcm_regs_t *pcic_avail_p;
5862*3db86aabSstevel 	pci_regspec_t *pci_avail_p, *regs;
5863*3db86aabSstevel 	int len, entries, rlen;
5864*3db86aabSstevel 	dev_info_t *pdip;
5865*3db86aabSstevel 
5866*3db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
5867*3db86aabSstevel 	    "available", (caddr_t)&pcic_avail_p, &len) == DDI_PROP_SUCCESS) {
5868*3db86aabSstevel 		/*
5869*3db86aabSstevel 		 * found "available" property at the cardbus/pcmcia node
5870*3db86aabSstevel 		 * need to translate address space entries from pcmcia
5871*3db86aabSstevel 		 * format to pci format
5872*3db86aabSstevel 		 */
5873*3db86aabSstevel 		entries = len / sizeof (pcm_regs_t);
5874*3db86aabSstevel 		pci_avail_p = kmem_alloc(sizeof (pci_regspec_t) * entries,
5875*3db86aabSstevel 			KM_SLEEP);
5876*3db86aabSstevel 		if (pcic_apply_avail_ranges(dip, pcic_avail_p, pci_avail_p,
5877*3db86aabSstevel 		    entries) == DDI_SUCCESS)
5878*3db86aabSstevel 			(void) pci_resource_setup_avail(dip, pci_avail_p,
5879*3db86aabSstevel 				entries);
5880*3db86aabSstevel 		kmem_free(pcic_avail_p, len);
5881*3db86aabSstevel 		kmem_free(pci_avail_p, entries * sizeof (pci_regspec_t));
5882*3db86aabSstevel 		return;
5883*3db86aabSstevel 	}
5884*3db86aabSstevel 
5885*3db86aabSstevel 	/*
5886*3db86aabSstevel 	 * "legacy" platforms will have "available" property in pci node
5887*3db86aabSstevel 	 */
5888*3db86aabSstevel 	for (pdip = ddi_get_parent(dip); pdip; pdip = ddi_get_parent(pdip)) {
5889*3db86aabSstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
5890*3db86aabSstevel 		    "available", (caddr_t)&pci_avail_p, &len) ==
5891*3db86aabSstevel 		    DDI_PROP_SUCCESS) {
5892*3db86aabSstevel 			/* (void) pci_resource_setup(pdip); */
5893*3db86aabSstevel 			kmem_free(pci_avail_p, len);
5894*3db86aabSstevel 			break;
5895*3db86aabSstevel 		}
5896*3db86aabSstevel 	}
5897*3db86aabSstevel 
5898*3db86aabSstevel 	if (pdip == NULL) {
5899*3db86aabSstevel 		int len;
5900*3db86aabSstevel 		char bus_type[16] = "(unknown)";
5901*3db86aabSstevel 		dev_info_t *par;
5902*3db86aabSstevel 
5903*3db86aabSstevel 		cmn_err(CE_CONT,
5904*3db86aabSstevel 		    "?pcic_init_assigned: no available property for pcmcia\n");
5905*3db86aabSstevel 
5906*3db86aabSstevel 		/*
5907*3db86aabSstevel 		 * This code is taken from pci_resource_setup() but does
5908*3db86aabSstevel 		 * not attempt to use the "available" property to populate
5909*3db86aabSstevel 		 * the ndi maps that are created.
5910*3db86aabSstevel 		 * The fact that we will actually
5911*3db86aabSstevel 		 * free some resource below (that was allocated by OBP)
5912*3db86aabSstevel 		 * should be enough to be going on with.
5913*3db86aabSstevel 		 */
5914*3db86aabSstevel 		for (par = dip; par != NULL; par = ddi_get_parent(par)) {
5915*3db86aabSstevel 			len = sizeof (bus_type);
5916*3db86aabSstevel 
5917*3db86aabSstevel 			if ((ddi_prop_op(DDI_DEV_T_ANY, par,
5918*3db86aabSstevel 			    PROP_LEN_AND_VAL_BUF,
5919*3db86aabSstevel 			    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
5920*3db86aabSstevel 			    "device_type",
5921*3db86aabSstevel 			    (caddr_t)&bus_type, &len) == DDI_SUCCESS) &&
5922*3db86aabSstevel 			    (strcmp(bus_type, "pci") == 0))
5923*3db86aabSstevel 				break;
5924*3db86aabSstevel 		}
5925*3db86aabSstevel 		if (par != NULL &&
5926*3db86aabSstevel 		    (ndi_ra_map_setup(par, NDI_RA_TYPE_MEM) != NDI_SUCCESS ||
5927*3db86aabSstevel 		    ndi_ra_map_setup(par, NDI_RA_TYPE_IO) != NDI_SUCCESS))
5928*3db86aabSstevel 			par = NULL;
5929*3db86aabSstevel 	} else {
5930*3db86aabSstevel #ifdef CARDBUS
5931*3db86aabSstevel 		cardbus_bus_range_t *bus_range;
5932*3db86aabSstevel 		int k;
5933*3db86aabSstevel 
5934*3db86aabSstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, 0, "bus-range",
5935*3db86aabSstevel 		    (caddr_t)&bus_range, &k) == DDI_PROP_SUCCESS) {
5936*3db86aabSstevel 			if (bus_range->lo != bus_range->hi)
5937*3db86aabSstevel 				pcic_err(pdip, 9, "allowable bus range is "
5938*3db86aabSstevel 				    "%u->%u\n", bus_range->lo, bus_range->hi);
5939*3db86aabSstevel 			else {
5940*3db86aabSstevel 				pcic_err(pdip, 0,
5941*3db86aabSstevel 				    "!No spare PCI bus numbers, range is "
5942*3db86aabSstevel 				    "%u->%u, cardbus isn't usable\n",
5943*3db86aabSstevel 				    bus_range->lo, bus_range->hi);
5944*3db86aabSstevel 			}
5945*3db86aabSstevel 			kmem_free(bus_range, k);
5946*3db86aabSstevel 		} else
5947*3db86aabSstevel 			pcic_err(pdip, 0, "!No bus-range property seems to "
5948*3db86aabSstevel 			    "have been set up\n");
5949*3db86aabSstevel #endif
5950*3db86aabSstevel 		/*
5951*3db86aabSstevel 		 * Have a valid parent with the "available" property
5952*3db86aabSstevel 		 */
5953*3db86aabSstevel 		(void) pci_resource_setup(pdip);
5954*3db86aabSstevel 	}
5955*3db86aabSstevel 
5956*3db86aabSstevel 	if ((strcmp(ddi_get_name(dip), "pcma") == 0) &&
5957*3db86aabSstevel 	    ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
5958*3db86aabSstevel 	    "assigned-addresses",
5959*3db86aabSstevel 	    (caddr_t)&regs, &rlen) == DDI_SUCCESS) {
5960*3db86aabSstevel 		ra_return_t ra;
5961*3db86aabSstevel 
5962*3db86aabSstevel 		/*
5963*3db86aabSstevel 		 * On the UltraBook IIi the ranges are assigned under
5964*3db86aabSstevel 		 * openboot. If we don't free them here the first I/O
5965*3db86aabSstevel 		 * space that can be used is up above 0x10000 which
5966*3db86aabSstevel 		 * doesn't work for this driver due to restrictions
5967*3db86aabSstevel 		 * on the PCI I/O addresses the controllers can cope with.
5968*3db86aabSstevel 		 * They are never going to be used by anything else
5969*3db86aabSstevel 		 * so free them up to the general pool. AG.
5970*3db86aabSstevel 		 */
5971*3db86aabSstevel 		pcic_err(dip, 1, "Free assigned addresses\n");
5972*3db86aabSstevel 
5973*3db86aabSstevel 		if ((PCI_REG_ADDR_G(regs[0].pci_phys_hi) ==
5974*3db86aabSstevel 		    PCI_REG_ADDR_G(PCI_ADDR_MEM32)) &&
5975*3db86aabSstevel 		    regs[0].pci_size_low == 0x1000000) {
5976*3db86aabSstevel 			ra.ra_addr_lo = regs[0].pci_phys_low;
5977*3db86aabSstevel 			ra.ra_len = regs[0].pci_size_low;
5978*3db86aabSstevel 			(void) pcmcia_free_mem(dip, &ra);
5979*3db86aabSstevel 		}
5980*3db86aabSstevel 		if ((PCI_REG_ADDR_G(regs[1].pci_phys_hi) ==
5981*3db86aabSstevel 		    PCI_REG_ADDR_G(PCI_ADDR_IO)) &&
5982*3db86aabSstevel 		    (regs[1].pci_size_low == 0x8000 ||
5983*3db86aabSstevel 		    regs[1].pci_size_low == 0x4000))   /* UB-IIi || UB-I */
5984*3db86aabSstevel 		{
5985*3db86aabSstevel 			ra.ra_addr_lo = regs[1].pci_phys_low;
5986*3db86aabSstevel 			ra.ra_len = regs[1].pci_size_low;
5987*3db86aabSstevel 			(void) pcmcia_free_io(dip, &ra);
5988*3db86aabSstevel 		}
5989*3db86aabSstevel 		kmem_free((caddr_t)regs, rlen);
5990*3db86aabSstevel 	}
5991*3db86aabSstevel }
5992*3db86aabSstevel 
5993*3db86aabSstevel /*
5994*3db86aabSstevel  * translate "available" from pcmcia format to pci format
5995*3db86aabSstevel  */
5996*3db86aabSstevel static int
5997*3db86aabSstevel pcic_apply_avail_ranges(dev_info_t *dip, pcm_regs_t *pcic_p,
5998*3db86aabSstevel     pci_regspec_t *pci_p, int entries)
5999*3db86aabSstevel {
6000*3db86aabSstevel 	int i, range_len, range_entries;
6001*3db86aabSstevel 	pcic_ranges_t *pcic_range_p;
6002*3db86aabSstevel 
6003*3db86aabSstevel 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
6004*3db86aabSstevel 		    (caddr_t)&pcic_range_p, &range_len) != DDI_PROP_SUCCESS) {
6005*3db86aabSstevel 		cmn_err(CE_CONT, "?pcic_apply_avail_ranges: "
6006*3db86aabSstevel 			"no ranges property for pcmcia\n");
6007*3db86aabSstevel 		return (DDI_FAILURE);
6008*3db86aabSstevel 	}
6009*3db86aabSstevel 
6010*3db86aabSstevel 	range_entries = range_len / sizeof (pcic_ranges_t);
6011*3db86aabSstevel 
6012*3db86aabSstevel 	/* for each "available" entry to be translated */
6013*3db86aabSstevel 	for (i = 0; i < entries; i++, pcic_p++, pci_p++) {
6014*3db86aabSstevel 		int j;
6015*3db86aabSstevel 		pcic_ranges_t *range_p = pcic_range_p;
6016*3db86aabSstevel 		pci_p->pci_phys_hi = -1u; /* default invalid value */
6017*3db86aabSstevel 
6018*3db86aabSstevel 		/* for each "ranges" entry to be searched */
6019*3db86aabSstevel 		for (j = 0; j < range_entries; j++, range_p++) {
6020*3db86aabSstevel 			uint64_t range_end = range_p->pcic_range_caddrlo +
6021*3db86aabSstevel 				range_p->pcic_range_size;
6022*3db86aabSstevel 			uint64_t avail_end = pcic_p->phys_lo + pcic_p->phys_len;
6023*3db86aabSstevel 
6024*3db86aabSstevel 			if ((range_p->pcic_range_caddrhi != pcic_p->phys_hi) ||
6025*3db86aabSstevel 			    (range_p->pcic_range_caddrlo > pcic_p->phys_lo) ||
6026*3db86aabSstevel 			    (range_end < avail_end))
6027*3db86aabSstevel 				continue;
6028*3db86aabSstevel 
6029*3db86aabSstevel 			pci_p->pci_phys_hi = range_p->pcic_range_paddrhi;
6030*3db86aabSstevel 			pci_p->pci_phys_mid = range_p->pcic_range_paddrmid;
6031*3db86aabSstevel 			pci_p->pci_phys_low = range_p->pcic_range_paddrlo
6032*3db86aabSstevel 			    + (pcic_p->phys_lo - range_p->pcic_range_caddrlo);
6033*3db86aabSstevel 			pci_p->pci_size_hi = 0;
6034*3db86aabSstevel 			pci_p->pci_size_low = pcic_p->phys_len;
6035*3db86aabSstevel 		}
6036*3db86aabSstevel 	}
6037*3db86aabSstevel 	kmem_free(pcic_range_p, range_len);
6038*3db86aabSstevel 	return (DDI_SUCCESS);
6039*3db86aabSstevel }
6040*3db86aabSstevel 
6041*3db86aabSstevel static int
6042*3db86aabSstevel pcic_open(dev_t *dev, int flag, int otyp, cred_t *cred)
6043*3db86aabSstevel {
6044*3db86aabSstevel 	if (getminor(*dev) == SYSHW_MINOR)
6045*3db86aabSstevel 		return (syshw_open(dev, flag, otyp, cred));
6046*3db86aabSstevel #ifdef CARDBUS
6047*3db86aabSstevel 	if (cardbus_is_cb_minor(*dev))
6048*3db86aabSstevel 		return (cardbus_open(dev, flag, otyp, cred));
6049*3db86aabSstevel #endif
6050*3db86aabSstevel 	return (EINVAL);
6051*3db86aabSstevel }
6052*3db86aabSstevel 
6053*3db86aabSstevel static int
6054*3db86aabSstevel pcic_close(dev_t dev, int flag, int otyp, cred_t *cred)
6055*3db86aabSstevel {
6056*3db86aabSstevel 	if (getminor(dev) == SYSHW_MINOR)
6057*3db86aabSstevel 		return (syshw_close(dev, flag, otyp, cred));
6058*3db86aabSstevel #ifdef CARDBUS
6059*3db86aabSstevel 	if (cardbus_is_cb_minor(dev))
6060*3db86aabSstevel 		return (cardbus_close(dev, flag, otyp, cred));
6061*3db86aabSstevel #endif
6062*3db86aabSstevel 	return (EINVAL);
6063*3db86aabSstevel }
6064*3db86aabSstevel 
6065*3db86aabSstevel static int
6066*3db86aabSstevel pcic_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred,
6067*3db86aabSstevel 	int *rval)
6068*3db86aabSstevel {
6069*3db86aabSstevel 	if (getminor(dev) == SYSHW_MINOR)
6070*3db86aabSstevel 		return (syshw_ioctl(dev, cmd, arg, mode, cred, rval));
6071*3db86aabSstevel #ifdef CARDBUS
6072*3db86aabSstevel 	if (cardbus_is_cb_minor(dev))
6073*3db86aabSstevel 		return (cardbus_ioctl(dev, cmd, arg, mode, cred, rval));
6074*3db86aabSstevel #endif
6075*3db86aabSstevel 	return (EINVAL);
6076*3db86aabSstevel }
6077*3db86aabSstevel 
6078*3db86aabSstevel 
6079*3db86aabSstevel static boolean_t
6080*3db86aabSstevel pcic_load_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp)
6081*3db86aabSstevel {
6082*3db86aabSstevel 	uint32_t present_state;
6083*3db86aabSstevel 	dev_info_t *dip = pcic->dip;
6084*3db86aabSstevel 	set_socket_t s;
6085*3db86aabSstevel 	get_socket_t g;
6086*3db86aabSstevel 	boolean_t retval;
6087*3db86aabSstevel 	unsigned vccLevel;
6088*3db86aabSstevel 
6089*3db86aabSstevel 	pcic_err(dip, 8, "entering pcic_load_cardbus\n");
6090*3db86aabSstevel 
6091*3db86aabSstevel 	pcic_mutex_exit(&pcic->pc_lock);
6092*3db86aabSstevel 
6093*3db86aabSstevel 	bzero(&s, sizeof (set_socket_t));
6094*3db86aabSstevel 	s.socket = sockp->pcs_socket;
6095*3db86aabSstevel 	s.SCIntMask = SBM_CD|SBM_RDYBSY;
6096*3db86aabSstevel 	s.IFType = IF_CARDBUS;
6097*3db86aabSstevel 	s.State = (unsigned)~0;
6098*3db86aabSstevel 
6099*3db86aabSstevel 	present_state = pcic_getcb(pcic, CB_PRESENT_STATE);
6100*3db86aabSstevel 	if (present_state & PCIC_VCC_3VCARD)
6101*3db86aabSstevel 		s.VccLevel = PCIC_VCC_3VLEVEL;
6102*3db86aabSstevel 	else if (present_state & PCIC_VCC_5VCARD)
6103*3db86aabSstevel 		s.VccLevel = PCIC_VCC_5VLEVEL;
6104*3db86aabSstevel 	else {
6105*3db86aabSstevel 		cmn_err(CE_CONT,
6106*3db86aabSstevel 		    "pcic_load_cardbus: unsupported card voltage\n");
6107*3db86aabSstevel 		goto failure;
6108*3db86aabSstevel 	}
6109*3db86aabSstevel 	vccLevel = s.VccLevel;
6110*3db86aabSstevel 	s.Vpp1Level = s.Vpp2Level = 0;
6111*3db86aabSstevel 
6112*3db86aabSstevel 	if (pcic_set_socket(dip, &s) != SUCCESS)
6113*3db86aabSstevel 		goto failure;
6114*3db86aabSstevel 
6115*3db86aabSstevel 	if (pcic_reset_socket(dip, sockp->pcs_socket,
6116*3db86aabSstevel 	    RESET_MODE_CARD_ONLY) != SUCCESS)
6117*3db86aabSstevel 		goto failure;
6118*3db86aabSstevel 
6119*3db86aabSstevel 	bzero(&g, sizeof (get_socket_t));
6120*3db86aabSstevel 	g.socket = sockp->pcs_socket;
6121*3db86aabSstevel 	if (pcic_get_socket(dip, &g) != SUCCESS)
6122*3db86aabSstevel 		goto failure;
6123*3db86aabSstevel 
6124*3db86aabSstevel 	bzero(&s, sizeof (set_socket_t));
6125*3db86aabSstevel 	s.socket = sockp->pcs_socket;
6126*3db86aabSstevel 	s.SCIntMask = SBM_CD;
6127*3db86aabSstevel 	s.IREQRouting = g.IRQRouting;
6128*3db86aabSstevel 	s.IFType = g.IFType;
6129*3db86aabSstevel 	s.CtlInd = g.CtlInd;
6130*3db86aabSstevel 	s.State = (unsigned)~0;
6131*3db86aabSstevel 	s.VccLevel = vccLevel;
6132*3db86aabSstevel 	s.Vpp1Level = s.Vpp2Level = 0;
6133*3db86aabSstevel 
6134*3db86aabSstevel 	if (pcic_set_socket(dip, &s) != SUCCESS)
6135*3db86aabSstevel 		goto failure;
6136*3db86aabSstevel 
6137*3db86aabSstevel 	retval = cardbus_load_cardbus(dip, sockp->pcs_socket, pcic->pc_base);
6138*3db86aabSstevel 	goto exit;
6139*3db86aabSstevel 
6140*3db86aabSstevel failure:
6141*3db86aabSstevel 	retval = B_FALSE;
6142*3db86aabSstevel 
6143*3db86aabSstevel exit:
6144*3db86aabSstevel 	pcic_mutex_enter(&pcic->pc_lock);
6145*3db86aabSstevel 	pcic_err(dip, 8, "exit pcic_load_cardbus (%s)\n",
6146*3db86aabSstevel 	    retval ? "success" : "failure");
6147*3db86aabSstevel 	return (retval);
6148*3db86aabSstevel }
6149*3db86aabSstevel 
6150*3db86aabSstevel static void
6151*3db86aabSstevel pcic_unload_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp)
6152*3db86aabSstevel {
6153*3db86aabSstevel 	dev_info_t *dip = pcic->dip;
6154*3db86aabSstevel 	set_socket_t s;
6155*3db86aabSstevel 
6156*3db86aabSstevel 	pcic_mutex_exit(&pcic->pc_lock);
6157*3db86aabSstevel 
6158*3db86aabSstevel 	cardbus_unload_cardbus(dip);
6159*3db86aabSstevel 
6160*3db86aabSstevel 	bzero(&s, sizeof (set_socket_t));
6161*3db86aabSstevel 	s.socket = sockp->pcs_socket;
6162*3db86aabSstevel 	s.SCIntMask = SBM_CD|SBM_RDYBSY;
6163*3db86aabSstevel 	s.IREQRouting = 0;
6164*3db86aabSstevel 	s.IFType = IF_MEMORY;
6165*3db86aabSstevel 	s.CtlInd = 0;
6166*3db86aabSstevel 	s.State = 0;
6167*3db86aabSstevel 	s.VccLevel = s.Vpp1Level = s.Vpp2Level = 0;
6168*3db86aabSstevel 
6169*3db86aabSstevel 	(void) pcic_set_socket(dip, &s);
6170*3db86aabSstevel 
6171*3db86aabSstevel 	pcic_mutex_enter(&pcic->pc_lock);
6172*3db86aabSstevel }
6173*3db86aabSstevel 
6174*3db86aabSstevel static uint32_t
6175*3db86aabSstevel pcic_getcb(pcicdev_t *pcic, int reg)
6176*3db86aabSstevel {
6177*3db86aabSstevel 	ASSERT(pcic->pc_io_type == PCIC_IO_TYPE_YENTA);
6178*3db86aabSstevel 
6179*3db86aabSstevel 	return (ddi_get32(pcic->handle,
6180*3db86aabSstevel 	    (uint32_t *)(pcic->ioaddr + CB_CB_OFFSET + reg)));
6181*3db86aabSstevel }
6182*3db86aabSstevel 
6183*3db86aabSstevel static void
6184*3db86aabSstevel pcic_putcb(pcicdev_t *pcic, int reg, uint32_t value)
6185*3db86aabSstevel {
6186*3db86aabSstevel 	ASSERT(pcic->pc_io_type == PCIC_IO_TYPE_YENTA);
6187*3db86aabSstevel 
6188*3db86aabSstevel 	ddi_put32(pcic->handle,
6189*3db86aabSstevel 	    (uint32_t *)(pcic->ioaddr + CB_CB_OFFSET + reg), value);
6190*3db86aabSstevel }
6191*3db86aabSstevel 
6192*3db86aabSstevel static void
6193*3db86aabSstevel pcic_enable_io_intr(pcicdev_t *pcic, int socket, int irq)
6194*3db86aabSstevel {
6195*3db86aabSstevel 	uint8_t value;
6196*3db86aabSstevel 	uint16_t brdgctl;
6197*3db86aabSstevel 
6198*3db86aabSstevel 	value = pcic_getb(pcic, socket, PCIC_INTERRUPT) & ~PCIC_INTR_MASK;
6199*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_INTERRUPT, value | irq);
6200*3db86aabSstevel 
6201*3db86aabSstevel 	switch (pcic->pc_type) {
6202*3db86aabSstevel 	case PCIC_INTEL_i82092:
6203*3db86aabSstevel 		pcic_82092_smiirq_ctl(pcic, socket, PCIC_82092_CTL_IRQ,
6204*3db86aabSstevel 		    PCIC_82092_INT_ENABLE);
6205*3db86aabSstevel 		break;
6206*3db86aabSstevel 	case PCIC_O2_OZ6912:
6207*3db86aabSstevel 		value = pcic_getb(pcic, 0, PCIC_CENTDMA);
6208*3db86aabSstevel 		value |= 0x8;
6209*3db86aabSstevel 		pcic_putb(pcic, 0, PCIC_CENTDMA, value);
6210*3db86aabSstevel 		break;
6211*3db86aabSstevel 	case PCIC_CL_PD6832:
6212*3db86aabSstevel 	case PCIC_TI_PCI1250:
6213*3db86aabSstevel 	case PCIC_TI_PCI1221:
6214*3db86aabSstevel 	case PCIC_TI_PCI1225:
6215*3db86aabSstevel 	case PCIC_TI_PCI1410:
6216*3db86aabSstevel 	case PCIC_ENE_1410:
6217*3db86aabSstevel 	case PCIC_TI_PCI1510:
6218*3db86aabSstevel 	case PCIC_TI_PCI1520:
6219*3db86aabSstevel 	case PCIC_TI_PCI1420:
6220*3db86aabSstevel 	case PCIC_ENE_1420:
6221*3db86aabSstevel 		/* route card functional interrupts to PCI interrupts */
6222*3db86aabSstevel 		brdgctl = ddi_get16(pcic->cfg_handle,
6223*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL));
6224*3db86aabSstevel 		pcic_err(NULL, 1,
6225*3db86aabSstevel 		    "pcic_enable_io_intr brdgctl(0x%x) was: 0x%x\n",
6226*3db86aabSstevel 		    PCI_CBUS_BRIDGE_CTRL, brdgctl);
6227*3db86aabSstevel 		brdgctl &= ~PCIC_BRDGCTL_INTR_MASK;
6228*3db86aabSstevel 		ddi_put16(pcic->cfg_handle,
6229*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL),
6230*3db86aabSstevel 		    brdgctl);
6231*3db86aabSstevel 		/* Flush the write */
6232*3db86aabSstevel 		(void) ddi_get16(pcic->cfg_handle,
6233*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL));
6234*3db86aabSstevel 		break;
6235*3db86aabSstevel 	default:
6236*3db86aabSstevel 		break;
6237*3db86aabSstevel 	}
6238*3db86aabSstevel }
6239*3db86aabSstevel 
6240*3db86aabSstevel static void
6241*3db86aabSstevel pcic_disable_io_intr(pcicdev_t *pcic, int socket)
6242*3db86aabSstevel {
6243*3db86aabSstevel 	uint8_t value;
6244*3db86aabSstevel 	uint16_t brdgctl;
6245*3db86aabSstevel 
6246*3db86aabSstevel 	value = pcic_getb(pcic, socket, PCIC_INTERRUPT) & ~PCIC_INTR_MASK;
6247*3db86aabSstevel 	pcic_putb(pcic, socket, PCIC_INTERRUPT, value);
6248*3db86aabSstevel 
6249*3db86aabSstevel 	switch (pcic->pc_type) {
6250*3db86aabSstevel 	case PCIC_INTEL_i82092:
6251*3db86aabSstevel 		pcic_82092_smiirq_ctl(pcic, socket, PCIC_82092_CTL_IRQ,
6252*3db86aabSstevel 		    PCIC_82092_INT_DISABLE);
6253*3db86aabSstevel 		break;
6254*3db86aabSstevel 	case PCIC_O2_OZ6912:
6255*3db86aabSstevel 		value = pcic_getb(pcic, 0, PCIC_CENTDMA);
6256*3db86aabSstevel 		value &= ~0x8;
6257*3db86aabSstevel 		pcic_putb(pcic, 0, PCIC_CENTDMA, value);
6258*3db86aabSstevel 		/* Flush the write */
6259*3db86aabSstevel 		(void) pcic_getb(pcic, 0, PCIC_CENTDMA);
6260*3db86aabSstevel 		break;
6261*3db86aabSstevel 	case PCIC_CL_PD6832:
6262*3db86aabSstevel 	case PCIC_TI_PCI1250:
6263*3db86aabSstevel 	case PCIC_TI_PCI1221:
6264*3db86aabSstevel 	case PCIC_TI_PCI1225:
6265*3db86aabSstevel 	case PCIC_TI_PCI1410:
6266*3db86aabSstevel 	case PCIC_ENE_1410:
6267*3db86aabSstevel 	case PCIC_TI_PCI1510:
6268*3db86aabSstevel 	case PCIC_TI_PCI1520:
6269*3db86aabSstevel 	case PCIC_TI_PCI1420:
6270*3db86aabSstevel 	case PCIC_ENE_1420:
6271*3db86aabSstevel 		/*
6272*3db86aabSstevel 		 * This maps I/O interrupts to ExCA which
6273*3db86aabSstevel 		 * have been turned off by the write to
6274*3db86aabSstevel 		 * PCIC_INTERRUPT above. It would appear to
6275*3db86aabSstevel 		 * be the only way to actually turn I/O Ints off
6276*3db86aabSstevel 		 * while retaining CS Ints.
6277*3db86aabSstevel 		 */
6278*3db86aabSstevel 		brdgctl = ddi_get16(pcic->cfg_handle,
6279*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL));
6280*3db86aabSstevel 		pcic_err(NULL, 1,
6281*3db86aabSstevel 		    "pcic_disable_io_intr brdgctl(0x%x) was: 0x%x\n",
6282*3db86aabSstevel 		    PCI_CBUS_BRIDGE_CTRL, brdgctl);
6283*3db86aabSstevel 		brdgctl |= PCIC_BRDGCTL_INTR_MASK;
6284*3db86aabSstevel 		ddi_put16(pcic->cfg_handle,
6285*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL),
6286*3db86aabSstevel 		    brdgctl);
6287*3db86aabSstevel 		/* Flush the write */
6288*3db86aabSstevel 		(void) ddi_get16(pcic->cfg_handle,
6289*3db86aabSstevel 		    (uint16_t *)(pcic->cfgaddr + PCI_CBUS_BRIDGE_CTRL));
6290*3db86aabSstevel 		break;
6291*3db86aabSstevel 	default:
6292*3db86aabSstevel 		break;
6293*3db86aabSstevel 	}
6294*3db86aabSstevel }
6295*3db86aabSstevel 
6296*3db86aabSstevel static void
6297*3db86aabSstevel pcic_cb_enable_intr(dev_info_t *dip)
6298*3db86aabSstevel {
6299*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
6300*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
6301*3db86aabSstevel 
6302*3db86aabSstevel 	mutex_enter(&pcic->pc_lock);
6303*3db86aabSstevel 	pcic_enable_io_intr(pcic, 0, pcic->pc_sockets[0].pcs_irq);
6304*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
6305*3db86aabSstevel }
6306*3db86aabSstevel 
6307*3db86aabSstevel static void
6308*3db86aabSstevel pcic_cb_disable_intr(dev_info_t *dip)
6309*3db86aabSstevel {
6310*3db86aabSstevel 	anp_t *anp = ddi_get_driver_private(dip);
6311*3db86aabSstevel 	pcicdev_t *pcic = anp->an_private;
6312*3db86aabSstevel 
6313*3db86aabSstevel 	mutex_enter(&pcic->pc_lock);
6314*3db86aabSstevel 	pcic_disable_io_intr(pcic, 0);
6315*3db86aabSstevel 	mutex_exit(&pcic->pc_lock);
6316*3db86aabSstevel }
6317*3db86aabSstevel 
6318*3db86aabSstevel static int
6319*3db86aabSstevel log_pci_cfg_err(ushort_t e, int bridge_secondary)
6320*3db86aabSstevel {
6321*3db86aabSstevel 	int	nerr = 0;
6322*3db86aabSstevel 	if (e & PCI_STAT_PERROR) {
6323*3db86aabSstevel 		nerr++;
6324*3db86aabSstevel 		cmn_err(CE_CONT, "detected parity error.\n");
6325*3db86aabSstevel 	}
6326*3db86aabSstevel 	if (e & PCI_STAT_S_SYSERR) {
6327*3db86aabSstevel 		nerr++;
6328*3db86aabSstevel 		if (bridge_secondary)
6329*3db86aabSstevel 			cmn_err(CE_CONT, "received system error.\n");
6330*3db86aabSstevel 		else
6331*3db86aabSstevel 			cmn_err(CE_CONT, "signalled system error.\n");
6332*3db86aabSstevel 	}
6333*3db86aabSstevel 	if (e & PCI_STAT_R_MAST_AB) {
6334*3db86aabSstevel 		nerr++;
6335*3db86aabSstevel 		cmn_err(CE_CONT, "received master abort.\n");
6336*3db86aabSstevel 	}
6337*3db86aabSstevel 	if (e & PCI_STAT_R_TARG_AB)
6338*3db86aabSstevel 		cmn_err(CE_CONT, "received target abort.\n");
6339*3db86aabSstevel 	if (e & PCI_STAT_S_TARG_AB)
6340*3db86aabSstevel 		cmn_err(CE_CONT, "signalled target abort\n");
6341*3db86aabSstevel 	if (e & PCI_STAT_S_PERROR) {
6342*3db86aabSstevel 		nerr++;
6343*3db86aabSstevel 		cmn_err(CE_CONT, "signalled parity error\n");
6344*3db86aabSstevel 	}
6345*3db86aabSstevel 	return (nerr);
6346*3db86aabSstevel }
6347*3db86aabSstevel 
6348*3db86aabSstevel #if defined(__sparc)
6349*3db86aabSstevel static int
6350*3db86aabSstevel pcic_fault(enum pci_fault_ops op, void *arg)
6351*3db86aabSstevel {
6352*3db86aabSstevel 	pcicdev_t *pcic = (pcicdev_t *)arg;
6353*3db86aabSstevel 	ushort_t pci_cfg_stat =
6354*3db86aabSstevel 	    pci_config_get16(pcic->cfg_handle, PCI_CONF_STAT);
6355*3db86aabSstevel 	ushort_t pci_cfg_sec_stat =
6356*3db86aabSstevel 	    pci_config_get16(pcic->cfg_handle, 0x16);
6357*3db86aabSstevel 	char	nm[24];
6358*3db86aabSstevel 	int	nerr = 0;
6359*3db86aabSstevel 
6360*3db86aabSstevel 	cardbus_dump_pci_config(pcic->dip);
6361*3db86aabSstevel 
6362*3db86aabSstevel 	switch (op) {
6363*3db86aabSstevel 	case FAULT_LOG:
6364*3db86aabSstevel 		(void) sprintf(nm, "%s-%d", ddi_driver_name(pcic->dip),
6365*3db86aabSstevel 		    ddi_get_instance(pcic->dip));
6366*3db86aabSstevel 
6367*3db86aabSstevel 		cmn_err(CE_WARN, "%s: PCIC fault log start:\n", nm);
6368*3db86aabSstevel 		cmn_err(CE_WARN, "%s: primary err (%x):\n", nm, pci_cfg_stat);
6369*3db86aabSstevel 		nerr += log_pci_cfg_err(pci_cfg_stat, 0);
6370*3db86aabSstevel 		cmn_err(CE_WARN, "%s: sec err (%x):\n", nm, pci_cfg_sec_stat);
6371*3db86aabSstevel 		nerr += log_pci_cfg_err(pci_cfg_sec_stat, 1);
6372*3db86aabSstevel 		cmn_err(CE_CONT, "%s: PCI fault log end.\n", nm);
6373*3db86aabSstevel 		return (nerr);
6374*3db86aabSstevel 	case FAULT_POKEFINI:
6375*3db86aabSstevel 	case FAULT_RESET:
6376*3db86aabSstevel 		pci_config_put16(pcic->cfg_handle,
6377*3db86aabSstevel 		    PCI_CONF_STAT, pci_cfg_stat);
6378*3db86aabSstevel 		pci_config_put16(pcic->cfg_handle, 0x16, pci_cfg_sec_stat);
6379*3db86aabSstevel 		break;
6380*3db86aabSstevel 	case FAULT_POKEFLT:
6381*3db86aabSstevel 		if (!(pci_cfg_stat & PCI_STAT_S_SYSERR))
6382*3db86aabSstevel 			return (1);
6383*3db86aabSstevel 		if (!(pci_cfg_sec_stat & PCI_STAT_R_MAST_AB))
6384*3db86aabSstevel 			return (1);
6385*3db86aabSstevel 		break;
6386*3db86aabSstevel 	default:
6387*3db86aabSstevel 		break;
6388*3db86aabSstevel 	}
6389*3db86aabSstevel 	return (DDI_SUCCESS);
6390*3db86aabSstevel }
6391*3db86aabSstevel #endif
6392*3db86aabSstevel 
6393*3db86aabSstevel static void
6394*3db86aabSstevel pcic_delayed_resume(void *arg)
6395*3db86aabSstevel {
6396*3db86aabSstevel 	int	i, j, interrupt;
6397*3db86aabSstevel 	anp_t *pcic_nexus;
6398*3db86aabSstevel 	pcicdev_t *pcic;
6399*3db86aabSstevel 
6400*3db86aabSstevel 	_NOTE(ARGUNUSED(arg))
6401*3db86aabSstevel 
6402*3db86aabSstevel #if defined(PCIC_DEBUG)
6403*3db86aabSstevel 	pcic_err(NULL, 6, "pcic_delayed_resume(): entered\n");
6404*3db86aabSstevel #endif
6405*3db86aabSstevel 	for (j = 0; j <= pcic_maxinst; j++) {
6406*3db86aabSstevel 
6407*3db86aabSstevel 		pcic_nexus = ddi_get_soft_state(pcic_soft_state_p, j);
6408*3db86aabSstevel 		if (!pcic_nexus)
6409*3db86aabSstevel 			continue;
6410*3db86aabSstevel 		pcic = (pcicdev_t *)pcic_nexus->an_private;
6411*3db86aabSstevel 		if (!pcic)
6412*3db86aabSstevel 			continue;
6413*3db86aabSstevel 
6414*3db86aabSstevel 		pcic_mutex_enter(&pcic->pc_lock); /* protect the registers */
6415*3db86aabSstevel 		for (i = 0; i < pcic->pc_numsockets; i++) {
6416*3db86aabSstevel 			/* Enable interrupts  on PCI if needs be */
6417*3db86aabSstevel 			interrupt = pcic_getb(pcic, i, PCIC_INTERRUPT);
6418*3db86aabSstevel 			if (pcic->pc_flags & PCF_USE_SMI)
6419*3db86aabSstevel 				interrupt |= PCIC_INTR_ENABLE;
6420*3db86aabSstevel 			pcic_putb(pcic, i, PCIC_INTERRUPT,
6421*3db86aabSstevel 			    PCIC_RESET | interrupt);
6422*3db86aabSstevel 			pcic->pc_sockets[i].pcs_debounce_id =
6423*3db86aabSstevel 			    pcic_add_debqueue(&pcic->pc_sockets[i],
6424*3db86aabSstevel 			    drv_usectohz(pcic_debounce_time));
6425*3db86aabSstevel 		}
6426*3db86aabSstevel 		pcic_mutex_exit(&pcic->pc_lock); /* protect the registers */
6427*3db86aabSstevel 		if (pcic_do_pcmcia_sr)
6428*3db86aabSstevel 			(void) pcmcia_wait_insert(pcic->dip);
6429*3db86aabSstevel 	}
6430*3db86aabSstevel }
6431*3db86aabSstevel 
6432*3db86aabSstevel static void
6433*3db86aabSstevel pcic_debounce(pcic_socket_t *pcs)
6434*3db86aabSstevel {
6435*3db86aabSstevel 	uint8_t status, stschng;
6436*3db86aabSstevel 
6437*3db86aabSstevel 	pcic_mutex_enter(&pcs->pcs_pcic->pc_lock);
6438*3db86aabSstevel 	pcs->pcs_flags &= ~PCS_STARTING;
6439*3db86aabSstevel 	stschng = pcic_getb(pcs->pcs_pcic, pcs->pcs_socket,
6440*3db86aabSstevel 	    PCIC_CARD_STATUS_CHANGE);
6441*3db86aabSstevel 	status = pcic_getb(pcs->pcs_pcic, pcs->pcs_socket,
6442*3db86aabSstevel 	    PCIC_INTERFACE_STATUS);
6443*3db86aabSstevel #ifdef PCIC_DEBUG
6444*3db86aabSstevel 	pcic_err(pcs->pcs_pcic->dip, 8,
6445*3db86aabSstevel 	    "pcic_debounce(0x%p, dip=0x%p) socket %d st 0x%x "
6446*3db86aabSstevel 	    "chg 0x%x flg 0x%x\n",
6447*3db86aabSstevel 	    (void *)pcs, (void *) pcs->pcs_pcic->dip, pcs->pcs_socket,
6448*3db86aabSstevel 	    status, stschng, pcs->pcs_flags);
6449*3db86aabSstevel #endif
6450*3db86aabSstevel 
6451*3db86aabSstevel 	pcic_putb(pcs->pcs_pcic, pcs->pcs_socket, PCIC_CARD_STATUS_CHANGE,
6452*3db86aabSstevel 	    PCIC_CD_DETECT);
6453*3db86aabSstevel 	pcic_handle_cd_change(pcs->pcs_pcic, pcs, status);
6454*3db86aabSstevel 	pcic_mutex_exit(&pcs->pcs_pcic->pc_lock);
6455*3db86aabSstevel }
6456*3db86aabSstevel 
6457*3db86aabSstevel static void
6458*3db86aabSstevel pcic_deb_thread()
6459*3db86aabSstevel {
6460*3db86aabSstevel 	callb_cpr_t cprinfo;
6461*3db86aabSstevel 	struct debounce *debp;
6462*3db86aabSstevel 	clock_t lastt;
6463*3db86aabSstevel 
6464*3db86aabSstevel 	CALLB_CPR_INIT(&cprinfo, &pcic_deb_mtx,
6465*3db86aabSstevel 	    callb_generic_cpr, "pcic debounce thread");
6466*3db86aabSstevel 	mutex_enter(&pcic_deb_mtx);
6467*3db86aabSstevel 	while (pcic_deb_threadid) {
6468*3db86aabSstevel 		while (pcic_deb_queue) {
6469*3db86aabSstevel #ifdef PCIC_DEBUG
6470*3db86aabSstevel 			pcic_dump_debqueue("Thread");
6471*3db86aabSstevel #endif
6472*3db86aabSstevel 			debp = pcic_deb_queue;
6473*3db86aabSstevel 			(void) drv_getparm(LBOLT, &lastt);
6474*3db86aabSstevel 			if (lastt >= debp->expire) {
6475*3db86aabSstevel 				pcic_deb_queue = debp->next;
6476*3db86aabSstevel 				mutex_exit(&pcic_deb_mtx);
6477*3db86aabSstevel 				pcic_debounce(debp->pcs);
6478*3db86aabSstevel 				mutex_enter(&pcic_deb_mtx);
6479*3db86aabSstevel 				kmem_free(debp, sizeof (*debp));
6480*3db86aabSstevel 			} else {
6481*3db86aabSstevel 				(void) cv_timedwait(&pcic_deb_cv,
6482*3db86aabSstevel 				    &pcic_deb_mtx, debp->expire);
6483*3db86aabSstevel 			}
6484*3db86aabSstevel 		}
6485*3db86aabSstevel 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
6486*3db86aabSstevel 		cv_wait(&pcic_deb_cv, &pcic_deb_mtx);
6487*3db86aabSstevel 		CALLB_CPR_SAFE_END(&cprinfo, &pcic_deb_mtx);
6488*3db86aabSstevel 	}
6489*3db86aabSstevel 	pcic_deb_threadid = (kthread_t *)1;
6490*3db86aabSstevel 	cv_signal(&pcic_deb_cv);
6491*3db86aabSstevel 	CALLB_CPR_EXIT(&cprinfo);	/* Also exits the mutex */
6492*3db86aabSstevel 	thread_exit();
6493*3db86aabSstevel }
6494*3db86aabSstevel 
6495*3db86aabSstevel static void *
6496*3db86aabSstevel pcic_add_debqueue(pcic_socket_t *pcs, int clocks)
6497*3db86aabSstevel {
6498*3db86aabSstevel 	clock_t lbolt;
6499*3db86aabSstevel 	struct debounce *dbp, **dbpp = &pcic_deb_queue;
6500*3db86aabSstevel 
6501*3db86aabSstevel 	(void) drv_getparm(LBOLT, &lbolt);
6502*3db86aabSstevel 	dbp = kmem_alloc(sizeof (struct debounce), KM_NOSLEEP);
6503*3db86aabSstevel 
6504*3db86aabSstevel 	dbp->expire = lbolt + clocks;
6505*3db86aabSstevel 	dbp->pcs = pcs;
6506*3db86aabSstevel 	mutex_enter(&pcic_deb_mtx);
6507*3db86aabSstevel 	while (*dbpp) {
6508*3db86aabSstevel 		if (dbp->expire > (*dbpp)->expire)
6509*3db86aabSstevel 			dbpp = &((*dbpp)->next);
6510*3db86aabSstevel 		else
6511*3db86aabSstevel 			break;
6512*3db86aabSstevel 	}
6513*3db86aabSstevel 	dbp->next = *dbpp;
6514*3db86aabSstevel 	*dbpp = dbp;
6515*3db86aabSstevel #ifdef PCIC_DEBUG
6516*3db86aabSstevel 	pcic_dump_debqueue("Add");
6517*3db86aabSstevel #endif
6518*3db86aabSstevel 	cv_signal(&pcic_deb_cv);
6519*3db86aabSstevel 	mutex_exit(&pcic_deb_mtx);
6520*3db86aabSstevel 	return (dbp);
6521*3db86aabSstevel }
6522*3db86aabSstevel 
6523*3db86aabSstevel static void
6524*3db86aabSstevel pcic_rm_debqueue(void *id)
6525*3db86aabSstevel {
6526*3db86aabSstevel 	struct debounce *dbp, **dbpp = &pcic_deb_queue;
6527*3db86aabSstevel 
6528*3db86aabSstevel 	dbp = (struct debounce *)id;
6529*3db86aabSstevel 	mutex_enter(&pcic_deb_mtx);
6530*3db86aabSstevel 	while (*dbpp) {
6531*3db86aabSstevel 		if (*dbpp == dbp) {
6532*3db86aabSstevel 			*dbpp = dbp->next;
6533*3db86aabSstevel 			kmem_free(dbp, sizeof (*dbp));
6534*3db86aabSstevel #ifdef PCIC_DEBUG
6535*3db86aabSstevel 			pcic_dump_debqueue("Remove");
6536*3db86aabSstevel #endif
6537*3db86aabSstevel 			cv_signal(&pcic_deb_cv);
6538*3db86aabSstevel 			mutex_exit(&pcic_deb_mtx);
6539*3db86aabSstevel 			return;
6540*3db86aabSstevel 		}
6541*3db86aabSstevel 		dbpp = &((*dbpp)->next);
6542*3db86aabSstevel 	}
6543*3db86aabSstevel 	pcic_err(NULL, 6, "pcic: Failed to find debounce id 0x%p\n", id);
6544*3db86aabSstevel 	mutex_exit(&pcic_deb_mtx);
6545*3db86aabSstevel }
6546*3db86aabSstevel 
6547*3db86aabSstevel 
6548*3db86aabSstevel static int	pcic_powerdelay = 0;
6549*3db86aabSstevel 
6550*3db86aabSstevel static int
6551*3db86aabSstevel pcic_exca_powerctl(pcicdev_t *pcic, int socket, int powerlevel)
6552*3db86aabSstevel {
6553*3db86aabSstevel 	int	ind, value, orig_pwrctl;
6554*3db86aabSstevel 
6555*3db86aabSstevel 	/* power setup -- if necessary */
6556*3db86aabSstevel 	orig_pwrctl = pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
6557*3db86aabSstevel 
6558*3db86aabSstevel #if defined(PCIC_DEBUG)
6559*3db86aabSstevel 	pcic_err(pcic->dip, 6,
6560*3db86aabSstevel 	    "pcic_exca_powerctl(socket %d) powerlevel=%x orig 0x%x\n",
6561*3db86aabSstevel 	    socket, powerlevel, orig_pwrctl);
6562*3db86aabSstevel #endif
6563*3db86aabSstevel 	/* Preserve the PCIC_OUTPUT_ENABLE (control lines output enable) bit. */
6564*3db86aabSstevel 	powerlevel = (powerlevel & ~POWER_OUTPUT_ENABLE) |
6565*3db86aabSstevel 	    (orig_pwrctl & POWER_OUTPUT_ENABLE);
6566*3db86aabSstevel 	if (powerlevel != orig_pwrctl) {
6567*3db86aabSstevel 		if (powerlevel & ~POWER_OUTPUT_ENABLE) {
6568*3db86aabSstevel 			int	ifs;
6569*3db86aabSstevel 			/*
6570*3db86aabSstevel 			 * set power to socket
6571*3db86aabSstevel 			 * note that the powerlevel was calculated earlier
6572*3db86aabSstevel 			 */
6573*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_POWER_CONTROL, powerlevel);
6574*3db86aabSstevel 			(void) pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
6575*3db86aabSstevel 
6576*3db86aabSstevel 			/*
6577*3db86aabSstevel 			 * this second write to the power control register
6578*3db86aabSstevel 			 * is needed to resolve a problem on
6579*3db86aabSstevel 			 * the IBM ThinkPad 750
6580*3db86aabSstevel 			 * where the first write doesn't latch.
6581*3db86aabSstevel 			 * The second write appears to always work and
6582*3db86aabSstevel 			 * doesn't hurt the operation of other chips
6583*3db86aabSstevel 			 * so we can just use it -- this is good since we can't
6584*3db86aabSstevel 			 * determine what chip the 750 actually uses
6585*3db86aabSstevel 			 * (I suspect an early Ricoh).
6586*3db86aabSstevel 			 */
6587*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_POWER_CONTROL, powerlevel);
6588*3db86aabSstevel 
6589*3db86aabSstevel 			value = pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
6590*3db86aabSstevel 			pcic_mswait(pcic, socket, pcic_powerdelay);
6591*3db86aabSstevel #if defined(PCIC_DEBUG)
6592*3db86aabSstevel 			pcic_err(pcic->dip, 8,
6593*3db86aabSstevel 			    "\tpowerlevel reg = %x (ifs %x)\n",
6594*3db86aabSstevel 			    value, pcic_getb(pcic, socket,
6595*3db86aabSstevel 			    PCIC_INTERFACE_STATUS));
6596*3db86aabSstevel 			pcic_err(pcic->dip, 8,
6597*3db86aabSstevel 			    "CBus regs: PS 0x%x, Control 0x%x\n",
6598*3db86aabSstevel 			    pcic_getcb(pcic, CB_PRESENT_STATE),
6599*3db86aabSstevel 			    pcic_getcb(pcic, CB_CONTROL));
6600*3db86aabSstevel #endif
6601*3db86aabSstevel 			/*
6602*3db86aabSstevel 			 * since power was touched, make sure it says it
6603*3db86aabSstevel 			 * is on.  This lets it become stable.
6604*3db86aabSstevel 			 */
6605*3db86aabSstevel 			for (ind = 0; ind < 20; ind++) {
6606*3db86aabSstevel 				ifs = pcic_getb(pcic, socket,
6607*3db86aabSstevel 				    PCIC_INTERFACE_STATUS);
6608*3db86aabSstevel 				if (ifs & PCIC_POWER_ON)
6609*3db86aabSstevel 					break;
6610*3db86aabSstevel 				else {
6611*3db86aabSstevel 					pcic_putb(pcic, socket,
6612*3db86aabSstevel 					    PCIC_POWER_CONTROL, 0);
6613*3db86aabSstevel 					(void) pcic_getb(pcic, socket,
6614*3db86aabSstevel 					    PCIC_POWER_CONTROL);
6615*3db86aabSstevel 					pcic_mswait(pcic, socket, 40);
6616*3db86aabSstevel 					if (ind == 10) {
6617*3db86aabSstevel 						pcic_putcb(pcic, CB_EVENT_FORCE,
6618*3db86aabSstevel 						    CB_EF_CVTEST);
6619*3db86aabSstevel 						pcic_mswait(pcic, socket, 100);
6620*3db86aabSstevel 					}
6621*3db86aabSstevel 					pcic_putb(pcic, socket,
6622*3db86aabSstevel 					    PCIC_POWER_CONTROL,
6623*3db86aabSstevel 					    powerlevel & ~POWER_OUTPUT_ENABLE);
6624*3db86aabSstevel 					(void) pcic_getb(pcic, socket,
6625*3db86aabSstevel 					    PCIC_POWER_CONTROL);
6626*3db86aabSstevel 					pcic_mswait(pcic, socket,
6627*3db86aabSstevel 					    pcic_powerdelay);
6628*3db86aabSstevel 					pcic_putb(pcic, socket,
6629*3db86aabSstevel 					    PCIC_POWER_CONTROL, powerlevel);
6630*3db86aabSstevel 					(void) pcic_getb(pcic, socket,
6631*3db86aabSstevel 					    PCIC_POWER_CONTROL);
6632*3db86aabSstevel 					pcic_mswait(pcic, socket,
6633*3db86aabSstevel 					    pcic_powerdelay);
6634*3db86aabSstevel 				}
6635*3db86aabSstevel 			}
6636*3db86aabSstevel 
6637*3db86aabSstevel 			if (!(ifs & PCIC_POWER_ON)) {
6638*3db86aabSstevel 				cmn_err(CE_WARN,
6639*3db86aabSstevel 				    "pcic socket %d: Power didn't get turned"
6640*3db86aabSstevel 				    "on!\nif status 0x%x pwrc 0x%x(x%x) "
6641*3db86aabSstevel 				    "misc1 0x%x igc 0x%x ind %d\n",
6642*3db86aabSstevel 				    socket, ifs,
6643*3db86aabSstevel 				    pcic_getb(pcic, socket, PCIC_POWER_CONTROL),
6644*3db86aabSstevel 				    orig_pwrctl,
6645*3db86aabSstevel 				    pcic_getb(pcic, socket, PCIC_MISC_CTL_1),
6646*3db86aabSstevel 				    pcic_getb(pcic, socket, PCIC_INTERRUPT),
6647*3db86aabSstevel 				    ind);
6648*3db86aabSstevel 				return (BAD_VCC);
6649*3db86aabSstevel 			}
6650*3db86aabSstevel #if defined(PCIC_DEBUG)
6651*3db86aabSstevel 			pcic_err(pcic->dip, 8,
6652*3db86aabSstevel 			    "\tind = %d, if status %x pwrc 0x%x "
6653*3db86aabSstevel 			    "misc1 0x%x igc 0x%x\n",
6654*3db86aabSstevel 			    ind, ifs,
6655*3db86aabSstevel 			    pcic_getb(pcic, socket, PCIC_POWER_CONTROL),
6656*3db86aabSstevel 			    pcic_getb(pcic, socket, PCIC_MISC_CTL_1),
6657*3db86aabSstevel 			    pcic_getb(pcic, socket, PCIC_INTERRUPT));
6658*3db86aabSstevel #endif
6659*3db86aabSstevel 		} else {
6660*3db86aabSstevel 			/* explicitly turned off the power */
6661*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_POWER_CONTROL, powerlevel);
6662*3db86aabSstevel 			(void) pcic_getb(pcic, socket, PCIC_POWER_CONTROL);
6663*3db86aabSstevel 		}
6664*3db86aabSstevel 	}
6665*3db86aabSstevel 	return (SUCCESS);
6666*3db86aabSstevel }
6667*3db86aabSstevel 
6668*3db86aabSstevel static int pcic_cbdoreset_during_poweron = 1;
6669*3db86aabSstevel static int
6670*3db86aabSstevel pcic_cbus_powerctl(pcicdev_t *pcic, int socket)
6671*3db86aabSstevel {
6672*3db86aabSstevel 	uint32_t cbctl = 0, orig_cbctl, cbstev, cbps;
6673*3db86aabSstevel 	int ind, iobits;
6674*3db86aabSstevel 	pcic_socket_t *sockp = &pcic->pc_sockets[socket];
6675*3db86aabSstevel 
6676*3db86aabSstevel 	pcic_putcb(pcic, CB_STATUS_EVENT, CB_SE_POWER_CYCLE);
6677*3db86aabSstevel 
6678*3db86aabSstevel 	ind = pcic_power[sockp->pcs_vpp1].PowerLevel/10;
6679*3db86aabSstevel 	cbctl |= pcic_cbv_levels[ind];
6680*3db86aabSstevel 
6681*3db86aabSstevel 	ind = pcic_power[sockp->pcs_vcc].PowerLevel/10;
6682*3db86aabSstevel 	cbctl |= (pcic_cbv_levels[ind]<<4);
6683*3db86aabSstevel 
6684*3db86aabSstevel 	orig_cbctl = pcic_getcb(pcic, CB_CONTROL);
6685*3db86aabSstevel 
6686*3db86aabSstevel #if defined(PCIC_DEBUG)
6687*3db86aabSstevel 	pcic_err(pcic->dip, 6,
6688*3db86aabSstevel 	    "pcic_cbus_powerctl(socket %d) vcc %d vpp1 %d "
6689*3db86aabSstevel 	    "cbctl 0x%x->0x%x\n",
6690*3db86aabSstevel 	    socket, sockp->pcs_vcc, sockp->pcs_vpp1, orig_cbctl, cbctl);
6691*3db86aabSstevel #endif
6692*3db86aabSstevel 	if (cbctl != orig_cbctl) {
6693*3db86aabSstevel 	    if (pcic_cbdoreset_during_poweron &&
6694*3db86aabSstevel 		(orig_cbctl & (CB_C_VCCMASK|CB_C_VPPMASK)) == 0) {
6695*3db86aabSstevel 		iobits = pcic_getb(pcic, socket, PCIC_INTERRUPT);
6696*3db86aabSstevel 		pcic_putb(pcic, socket, PCIC_INTERRUPT, iobits & ~PCIC_RESET);
6697*3db86aabSstevel 	    }
6698*3db86aabSstevel 	    pcic_putcb(pcic, CB_CONTROL, cbctl);
6699*3db86aabSstevel 
6700*3db86aabSstevel 	    if ((cbctl & CB_C_VCCMASK) == (orig_cbctl & CB_C_VCCMASK)) {
6701*3db86aabSstevel 		pcic_mswait(pcic, socket, pcic_powerdelay);
6702*3db86aabSstevel 		return (SUCCESS);
6703*3db86aabSstevel 	    }
6704*3db86aabSstevel 	    for (ind = 0; ind < 20; ind++) {
6705*3db86aabSstevel 		cbstev = pcic_getcb(pcic, CB_STATUS_EVENT);
6706*3db86aabSstevel 
6707*3db86aabSstevel 		if (cbstev & CB_SE_POWER_CYCLE) {
6708*3db86aabSstevel 
6709*3db86aabSstevel 		/*
6710*3db86aabSstevel 		 * delay 400 ms: though the standard defines that the Vcc
6711*3db86aabSstevel 		 * set-up time is 20 ms, some PC-Card bridge requires longer
6712*3db86aabSstevel 		 * duration.
6713*3db86aabSstevel 		 * Note: We should check the status AFTER the delay to give time
6714*3db86aabSstevel 		 * for things to stabilize.
6715*3db86aabSstevel 		 */
6716*3db86aabSstevel 		    pcic_mswait(pcic, socket, 400);
6717*3db86aabSstevel 
6718*3db86aabSstevel 		    cbps = pcic_getcb(pcic, CB_PRESENT_STATE);
6719*3db86aabSstevel 		    if (cbctl && !(cbps & CB_PS_POWER_CYCLE)) {
6720*3db86aabSstevel 			/* break; */
6721*3db86aabSstevel 			cmn_err(CE_WARN, "cbus_powerctl: power off??\n");
6722*3db86aabSstevel 		    }
6723*3db86aabSstevel 		    if (cbctl & CB_PS_BADVCC) {
6724*3db86aabSstevel 			cmn_err(CE_WARN, "cbus_powerctl: bad power request\n");
6725*3db86aabSstevel 			break;
6726*3db86aabSstevel 		    }
6727*3db86aabSstevel 
6728*3db86aabSstevel #if defined(PCIC_DEBUG)
6729*3db86aabSstevel 		    pcic_err(pcic->dip, 8,
6730*3db86aabSstevel 			"cbstev = 0x%x cbps = 0x%x cbctl 0x%x(0x%x)",
6731*3db86aabSstevel 			cbstev, pcic_getcb(pcic, CB_PRESENT_STATE),
6732*3db86aabSstevel 			cbctl, orig_cbctl);
6733*3db86aabSstevel #endif
6734*3db86aabSstevel 		    if (pcic_cbdoreset_during_poweron &&
6735*3db86aabSstevel 			(orig_cbctl & (CB_C_VCCMASK|CB_C_VPPMASK)) == 0) {
6736*3db86aabSstevel 			pcic_putb(pcic, socket, PCIC_INTERRUPT, iobits);
6737*3db86aabSstevel 		    }
6738*3db86aabSstevel 		    return (SUCCESS);
6739*3db86aabSstevel 		}
6740*3db86aabSstevel 		pcic_mswait(pcic, socket, 40);
6741*3db86aabSstevel 	    }
6742*3db86aabSstevel 	    if (pcic_cbdoreset_during_poweron &&
6743*3db86aabSstevel 		(orig_cbctl & (CB_C_VCCMASK|CB_C_VPPMASK)) == 0) {
6744*3db86aabSstevel 		pcic_putb(pcic, socket, PCIC_INTERRUPT, iobits);
6745*3db86aabSstevel 	    }
6746*3db86aabSstevel 	    cmn_err(CE_WARN,
6747*3db86aabSstevel 		    "pcic socket %d: Power didn't get turned on/off!\n"
6748*3db86aabSstevel 		    "cbstev = 0x%x cbps = 0x%x cbctl 0x%x(0x%x) "
6749*3db86aabSstevel 		    "vcc %d vpp1 %d", socket, cbstev,
6750*3db86aabSstevel 		    pcic_getcb(pcic, CB_PRESENT_STATE),
6751*3db86aabSstevel 		    cbctl, orig_cbctl, sockp->pcs_vcc, sockp->pcs_vpp1);
6752*3db86aabSstevel 	    return (BAD_VCC);
6753*3db86aabSstevel 	}
6754*3db86aabSstevel 	return (SUCCESS);
6755*3db86aabSstevel }
6756*3db86aabSstevel 
6757*3db86aabSstevel static int	pcic_do_pprintf = 0;
6758*3db86aabSstevel 
6759*3db86aabSstevel static void
6760*3db86aabSstevel pcic_dump_debqueue(char *msg)
6761*3db86aabSstevel {
6762*3db86aabSstevel 	struct debounce *debp = pcic_deb_queue;
6763*3db86aabSstevel 	clock_t lbolt;
6764*3db86aabSstevel 
6765*3db86aabSstevel 	(void) drv_getparm(LBOLT, &lbolt);
6766*3db86aabSstevel 	pcic_err(NULL, 6, debp ? "pcic debounce list (%s) lbolt 0x%x:\n" :
6767*3db86aabSstevel 	    "pcic debounce_list (%s) EMPTY lbolt 0x%x\n", msg, lbolt);
6768*3db86aabSstevel 	while (debp) {
6769*3db86aabSstevel 		pcic_err(NULL, 6, "%p: exp 0x%x next 0x%p id 0x%p\n",
6770*3db86aabSstevel 		    (void *) debp, (int)debp->expire, (void *) debp->next,
6771*3db86aabSstevel 		    debp->pcs->pcs_debounce_id);
6772*3db86aabSstevel 		debp = debp->next;
6773*3db86aabSstevel 	}
6774*3db86aabSstevel }
6775*3db86aabSstevel 
6776*3db86aabSstevel 
6777*3db86aabSstevel /* PRINTFLIKE3 */
6778*3db86aabSstevel static void
6779*3db86aabSstevel pcic_err(dev_info_t *dip, int level, const char *fmt, ...)
6780*3db86aabSstevel {
6781*3db86aabSstevel 	if (pcic_debug && (level <= pcic_debug)) {
6782*3db86aabSstevel 		va_list adx;
6783*3db86aabSstevel 		int	instance;
6784*3db86aabSstevel 		char	buf[256];
6785*3db86aabSstevel 		const char	*name;
6786*3db86aabSstevel #if !defined(PCIC_DEBUG)
6787*3db86aabSstevel 		int	ce;
6788*3db86aabSstevel 		char	qmark = 0;
6789*3db86aabSstevel 
6790*3db86aabSstevel 		if (level <= 3)
6791*3db86aabSstevel 			ce = CE_WARN;
6792*3db86aabSstevel 		else
6793*3db86aabSstevel 			ce = CE_CONT;
6794*3db86aabSstevel 		if (level == 4)
6795*3db86aabSstevel 			qmark = 1;
6796*3db86aabSstevel #endif
6797*3db86aabSstevel 
6798*3db86aabSstevel 		if (dip) {
6799*3db86aabSstevel 			instance = ddi_get_instance(dip);
6800*3db86aabSstevel 			/* name = ddi_binding_name(dip); */
6801*3db86aabSstevel 			name = ddi_driver_name(dip);
6802*3db86aabSstevel 		} else {
6803*3db86aabSstevel 			instance = 0;
6804*3db86aabSstevel 			name = "";
6805*3db86aabSstevel 		}
6806*3db86aabSstevel 
6807*3db86aabSstevel 		va_start(adx, fmt);
6808*3db86aabSstevel 		(void) vsprintf(buf, fmt, adx);
6809*3db86aabSstevel 		va_end(adx);
6810*3db86aabSstevel 
6811*3db86aabSstevel #if defined(PCIC_DEBUG)
6812*3db86aabSstevel 		if (pcic_do_pprintf) {
6813*3db86aabSstevel 			if (dip) {
6814*3db86aabSstevel 				if (instance >= 0)
6815*3db86aabSstevel 					prom_printf("%s(%d),0x%p: %s", name,
6816*3db86aabSstevel 					    instance, dip, buf);
6817*3db86aabSstevel 				else
6818*3db86aabSstevel 					prom_printf("%s,0x%p: %s",
6819*3db86aabSstevel 					    name, dip, buf);
6820*3db86aabSstevel 			} else
6821*3db86aabSstevel 				prom_printf(buf);
6822*3db86aabSstevel 		} else {
6823*3db86aabSstevel 			if (dip) {
6824*3db86aabSstevel 				if (instance >= 0)
6825*3db86aabSstevel 					cmn_err(CE_CONT, "%s(%d),0x%p: %s",
6826*3db86aabSstevel 					    name, instance, (void *) dip, buf);
6827*3db86aabSstevel 				else
6828*3db86aabSstevel 					cmn_err(CE_CONT, "%s,0x%p: %s",
6829*3db86aabSstevel 					    name, (void *) dip, buf);
6830*3db86aabSstevel 			} else
6831*3db86aabSstevel 				cmn_err(CE_CONT, buf);
6832*3db86aabSstevel 		}
6833*3db86aabSstevel #else
6834*3db86aabSstevel 		if (dip)
6835*3db86aabSstevel 			cmn_err(ce, qmark ? "?%s%d: %s" : "%s%d: %s", name,
6836*3db86aabSstevel 			    instance, buf);
6837*3db86aabSstevel 		else
6838*3db86aabSstevel 			cmn_err(ce, qmark ? "?%s" : buf, buf);
6839*3db86aabSstevel #endif
6840*3db86aabSstevel 	}
6841*3db86aabSstevel }
6842*3db86aabSstevel 
6843*3db86aabSstevel 
6844*3db86aabSstevel static void
6845*3db86aabSstevel pcic_syshw_cardstate(syshw_t *item, void *arg)
6846*3db86aabSstevel {
6847*3db86aabSstevel 	pcic_socket_t *pcs = (pcic_socket_t *)arg;
6848*3db86aabSstevel 
6849*3db86aabSstevel 	if (pcs->pcs_flags & PCS_CARD_PRESENT) {
6850*3db86aabSstevel 		item->state = B_TRUE;
6851*3db86aabSstevel 		if (pcs->pcs_flags & PCS_CARD_IS16BIT)
6852*3db86aabSstevel 			item->values[0] = 1;
6853*3db86aabSstevel 		else if (pcs->pcs_flags & PCS_CARD_ISCARDBUS)
6854*3db86aabSstevel 			item->values[0] = 2;
6855*3db86aabSstevel 		else
6856*3db86aabSstevel 			item->values[0] = 0;
6857*3db86aabSstevel 	} else {
6858*3db86aabSstevel 		item->state = B_FALSE;
6859*3db86aabSstevel 		item->values[0] = 0;
6860*3db86aabSstevel 	}
6861*3db86aabSstevel }
6862*3db86aabSstevel 
6863*3db86aabSstevel /*
6864*3db86aabSstevel  * Tadpole additional for the syshw interface used to control the
6865*3db86aabSstevel  * start/stop switch which is physically linked to the GPIO1 pin
6866*3db86aabSstevel  * on the 1250a.
6867*3db86aabSstevel  */
6868*3db86aabSstevel 
6869*3db86aabSstevel #define	CLIENT_CALLED	0x8000000
6870*3db86aabSstevel #define	NCE_EVENT_MASK	0xffff
6871*3db86aabSstevel 
6872*3db86aabSstevel typedef struct _client {
6873*3db86aabSstevel 	pid_t	pid;		/* set by kernel */
6874*3db86aabSstevel 	int	flags;		/* NCE_REGISTER...  */
6875*3db86aabSstevel 	int	priority;	/* >100 unless root */
6876*3db86aabSstevel 	int	events;		/* pending event flags */
6877*3db86aabSstevel 	int	event_sig;	/* SIG... etc */
6878*3db86aabSstevel 	struct _client *next;	/* set by kernel */
6879*3db86aabSstevel 	struct _client *prev;	/* set by kernel */
6880*3db86aabSstevel } client_data;
6881*3db86aabSstevel 
6882*3db86aabSstevel static client_data	*cl_data;
6883*3db86aabSstevel static int	n_clients;
6884*3db86aabSstevel static kmutex_t	client_mtx, intr_mtx;
6885*3db86aabSstevel 
6886*3db86aabSstevel static void	delete_client(int);
6887*3db86aabSstevel 
6888*3db86aabSstevel #ifdef VOYAGER
6889*3db86aabSstevel static uint32_t	runstop_sig;
6890*3db86aabSstevel static ddi_softintr_t	softint_id;
6891*3db86aabSstevel static uchar_t	softint_flag;
6892*3db86aabSstevel static int	switch_debounce_time = 100;	/* in milliseconds */
6893*3db86aabSstevel static timeout_id_t	switch_to_id;
6894*3db86aabSstevel 
6895*3db86aabSstevel static syshw_t syshw_run_stop = {
6896*3db86aabSstevel 	    0, "Run/Stop", SH_SWITCH,
6897*3db86aabSstevel 	    SYSHW_CAN_SIGNAL_CHANGE|SYSHW_STATE_VALID,
6898*3db86aabSstevel 	    B_FALSE, { 0 } };
6899*3db86aabSstevel 
6900*3db86aabSstevel static void
6901*3db86aabSstevel syshw_get_run_stop(syshw_t *item, void *arg)
6902*3db86aabSstevel {
6903*3db86aabSstevel 	pcicdev_t *pcic = (pcicdev_t *)arg;
6904*3db86aabSstevel 
6905*3db86aabSstevel 	if (ddi_get8(pcic->cfg_handle,
6906*3db86aabSstevel 	    pcic->cfgaddr + PCIC_GPIO1_REG) & PCIC_GPIO_DIN)
6907*3db86aabSstevel 		item->state = B_TRUE;
6908*3db86aabSstevel 	else
6909*3db86aabSstevel 		item->state = B_FALSE;
6910*3db86aabSstevel }
6911*3db86aabSstevel 
6912*3db86aabSstevel 
6913*3db86aabSstevel #endif
6914*3db86aabSstevel 
6915*3db86aabSstevel static void
6916*3db86aabSstevel syshw_attach(pcicdev_t *pcic)
6917*3db86aabSstevel {
6918*3db86aabSstevel 	if (ddi_get_instance(pcic->dip) != 0)
6919*3db86aabSstevel 		return;
6920*3db86aabSstevel 
6921*3db86aabSstevel #ifdef VOYAGER
6922*3db86aabSstevel 	if (pcic->pc_type == PCIC_TI_PCI1250) {
6923*3db86aabSstevel 
6924*3db86aabSstevel 		/*
6925*3db86aabSstevel 		 * Only setup run/stop on a Voyager.
6926*3db86aabSstevel 		 * This is currently defined as
6927*3db86aabSstevel 		 * a TI1250 on a SPARC architecture. May have to make this a
6928*3db86aabSstevel 		 * property definition in the future.
6929*3db86aabSstevel 		 */
6930*3db86aabSstevel 		if (ddi_add_softintr(pcic->dip,
6931*3db86aabSstevel 		    DDI_SOFTINT_LOW, &softint_id,
6932*3db86aabSstevel 		    NULL, NULL, syshw_intr,
6933*3db86aabSstevel 		    (caddr_t)pcic) == DDI_SUCCESS) {
6934*3db86aabSstevel 			runstop_sig = syshw_add2map(&syshw_run_stop,
6935*3db86aabSstevel 			    syshw_get_run_stop, pcic);
6936*3db86aabSstevel 			mutex_init(&intr_mtx, NULL, MUTEX_DRIVER,
6937*3db86aabSstevel 			    pcic->pc_pri);
6938*3db86aabSstevel 			ddi_put8(pcic->cfg_handle,
6939*3db86aabSstevel 			    pcic->cfgaddr + PCIC_GPIO1_REG,
6940*3db86aabSstevel 			    PCIC_GPIO_FINPUT | PCIC_GPIO_INTENBL |
6941*3db86aabSstevel 			    PCIC_GPIO_DELTA);
6942*3db86aabSstevel 		}
6943*3db86aabSstevel 	}
6944*3db86aabSstevel #endif
6945*3db86aabSstevel 	mutex_init(&client_mtx, "syshw client", MUTEX_DRIVER, NULL);
6946*3db86aabSstevel 	(void) ddi_create_minor_node(pcic->dip, "syshw", S_IFCHR,
6947*3db86aabSstevel 	    SYSHW_MINOR, NULL, NULL);
6948*3db86aabSstevel }
6949*3db86aabSstevel 
6950*3db86aabSstevel static void
6951*3db86aabSstevel syshw_detach(pcicdev_t *pcic)
6952*3db86aabSstevel {
6953*3db86aabSstevel #ifdef VOYAGER
6954*3db86aabSstevel 	if (pcic->pc_type == PCIC_TI_PCI1250) {
6955*3db86aabSstevel 		pcic_mutex_enter(&intr_mtx);
6956*3db86aabSstevel 
6957*3db86aabSstevel 		/*
6958*3db86aabSstevel 		 * Turn off this interrupt.
6959*3db86aabSstevel 		 */
6960*3db86aabSstevel 		ddi_put8(pcic->cfg_handle, pcic->cfgaddr + PCIC_GPIO1_REG,
6961*3db86aabSstevel 		    PCIC_GPIO_FINPUT);
6962*3db86aabSstevel 
6963*3db86aabSstevel 		if (switch_to_id)
6964*3db86aabSstevel 			(void) untimeout(switch_to_id);
6965*3db86aabSstevel 		switch_to_id = 0;
6966*3db86aabSstevel 		softint_flag = 0;
6967*3db86aabSstevel 
6968*3db86aabSstevel 		pcic_mutex_exit(&intr_mtx);
6969*3db86aabSstevel 		ddi_remove_softintr(softint_id);
6970*3db86aabSstevel 		mutex_destroy(&intr_mtx);
6971*3db86aabSstevel 	}
6972*3db86aabSstevel #endif
6973*3db86aabSstevel 
6974*3db86aabSstevel 	ddi_remove_minor_node(pcic->dip, NULL);
6975*3db86aabSstevel 	mutex_destroy(&client_mtx);
6976*3db86aabSstevel }
6977*3db86aabSstevel 
6978*3db86aabSstevel static void
6979*3db86aabSstevel syshw_resume(pcicdev_t *pcic)
6980*3db86aabSstevel {
6981*3db86aabSstevel #ifdef VOYAGER
6982*3db86aabSstevel 	if (pcic->pc_type == PCIC_TI_PCI1250) {
6983*3db86aabSstevel 		ddi_put8(pcic->cfg_handle, pcic->cfgaddr + PCIC_GPIO1_REG,
6984*3db86aabSstevel 		    PCIC_GPIO_FINPUT | PCIC_GPIO_INTENBL | PCIC_GPIO_DELTA);
6985*3db86aabSstevel 	}
6986*3db86aabSstevel #else
6987*3db86aabSstevel 	_NOTE(ARGUNUSED(pcic))
6988*3db86aabSstevel #endif
6989*3db86aabSstevel }
6990*3db86aabSstevel 
6991*3db86aabSstevel #ifdef VOYAGER
6992*3db86aabSstevel static uint_t
6993*3db86aabSstevel syshw_intr_hi(pcicdev_t *pcic)
6994*3db86aabSstevel {
6995*3db86aabSstevel 	uchar_t regval;
6996*3db86aabSstevel 
6997*3db86aabSstevel 	if (pcic->pc_type != PCIC_TI_PCI1250)
6998*3db86aabSstevel 		return (DDI_INTR_UNCLAIMED);
6999*3db86aabSstevel 
7000*3db86aabSstevel 	regval = ddi_get8(pcic->cfg_handle, pcic->cfgaddr + PCIC_GPIO1_REG);
7001*3db86aabSstevel 	if (regval & PCIC_GPIO_DELTA) {
7002*3db86aabSstevel 		pcic_mutex_enter(&intr_mtx);
7003*3db86aabSstevel 		if (softint_flag == 0 && switch_to_id == 0) {
7004*3db86aabSstevel 			softint_flag = 1;
7005*3db86aabSstevel 			ddi_trigger_softintr(softint_id);
7006*3db86aabSstevel 		}
7007*3db86aabSstevel 		ddi_put8(pcic->cfg_handle, pcic->cfgaddr + PCIC_GPIO1_REG,
7008*3db86aabSstevel 		    regval);
7009*3db86aabSstevel 		pcic_mutex_exit(&intr_mtx);
7010*3db86aabSstevel 		return (DDI_INTR_CLAIMED);
7011*3db86aabSstevel 	}
7012*3db86aabSstevel 
7013*3db86aabSstevel 	return (DDI_INTR_UNCLAIMED);
7014*3db86aabSstevel }
7015*3db86aabSstevel 
7016*3db86aabSstevel /*
7017*3db86aabSstevel  * Don't deliver the signal until the debounce period has expired.
7018*3db86aabSstevel  * Unfortuately this means it end up as a three tier interrupt just
7019*3db86aabSstevel  * to indicate a bit change.
7020*3db86aabSstevel  */
7021*3db86aabSstevel static void
7022*3db86aabSstevel syshw_debounce_to(void *arg)
7023*3db86aabSstevel {
7024*3db86aabSstevel 	_NOTE(ARGUNUSED(arg))
7025*3db86aabSstevel 
7026*3db86aabSstevel 	if (switch_to_id) {
7027*3db86aabSstevel 		pcic_mutex_enter(&intr_mtx);
7028*3db86aabSstevel 		switch_to_id = 0;
7029*3db86aabSstevel 		pcic_mutex_exit(&intr_mtx);
7030*3db86aabSstevel 		syshw_send_signal(runstop_sig);
7031*3db86aabSstevel 		return;
7032*3db86aabSstevel 	}
7033*3db86aabSstevel }
7034*3db86aabSstevel 
7035*3db86aabSstevel static uint_t
7036*3db86aabSstevel syshw_intr(caddr_t arg)
7037*3db86aabSstevel {
7038*3db86aabSstevel 	_NOTE(ARGUNUSED(arg))
7039*3db86aabSstevel 
7040*3db86aabSstevel 	if (softint_flag) {
7041*3db86aabSstevel 		pcic_mutex_enter(&intr_mtx);
7042*3db86aabSstevel 		softint_flag = 0;
7043*3db86aabSstevel 		if (!switch_to_id)
7044*3db86aabSstevel 			switch_to_id = timeout(syshw_debounce_to, arg,
7045*3db86aabSstevel 			    drv_usectohz(switch_debounce_time * 1000));
7046*3db86aabSstevel 		pcic_mutex_exit(&intr_mtx);
7047*3db86aabSstevel 		return (DDI_INTR_CLAIMED);
7048*3db86aabSstevel 	}
7049*3db86aabSstevel 	return (DDI_INTR_UNCLAIMED);
7050*3db86aabSstevel }
7051*3db86aabSstevel #endif
7052*3db86aabSstevel 
7053*3db86aabSstevel /*
7054*3db86aabSstevel  * Send signals to the registered clients
7055*3db86aabSstevel  */
7056*3db86aabSstevel static void
7057*3db86aabSstevel syshw_send_signal(int events)
7058*3db86aabSstevel {
7059*3db86aabSstevel 	client_data *ptr;
7060*3db86aabSstevel 	proc_t	*pr;
7061*3db86aabSstevel 	int	done_flag;
7062*3db86aabSstevel 
7063*3db86aabSstevel 	ptr = cl_data;
7064*3db86aabSstevel 	while (ptr != NULL) {
7065*3db86aabSstevel 		done_flag = CLIENT_CALLED;
7066*3db86aabSstevel 
7067*3db86aabSstevel 		if ((ptr->flags & events) &&
7068*3db86aabSstevel 		    (ptr->event_sig != 0) &&
7069*3db86aabSstevel 		    ((ptr->flags & done_flag) == 0)) {
7070*3db86aabSstevel 
7071*3db86aabSstevel 			/*
7072*3db86aabSstevel 			 * only call the process if:
7073*3db86aabSstevel 			 * it has not already received the nce signal
7074*3db86aabSstevel 			 * its signal was not zero (just in case)
7075*3db86aabSstevel 			 * and it is registered to receive this signal
7076*3db86aabSstevel 			 */
7077*3db86aabSstevel 			pcic_mutex_enter(&pidlock);
7078*3db86aabSstevel 			pr = prfind(ptr->pid);
7079*3db86aabSstevel 			pcic_mutex_exit(&pidlock);
7080*3db86aabSstevel 			if (pr == NULL) {
7081*3db86aabSstevel 				/*
7082*3db86aabSstevel 				 * This process has died,
7083*3db86aabSstevel 				 * so we free its memory and move on
7084*3db86aabSstevel 				 * start at the begining again:
7085*3db86aabSstevel 				 * a waste of cycles but it makes things easy..
7086*3db86aabSstevel 				 */
7087*3db86aabSstevel 				delete_client(ptr->pid);
7088*3db86aabSstevel 				ptr = cl_data;
7089*3db86aabSstevel 			} else {
7090*3db86aabSstevel 				ptr->events |= (events & ptr->flags &
7091*3db86aabSstevel 				    NCE_EVENT_MASK);
7092*3db86aabSstevel 				psignal(pr, ptr->event_sig);
7093*3db86aabSstevel 				ptr->flags |= done_flag;
7094*3db86aabSstevel 				ptr = ptr->next;
7095*3db86aabSstevel 			}
7096*3db86aabSstevel 		} else {
7097*3db86aabSstevel 			ptr = ptr->next;
7098*3db86aabSstevel 		}
7099*3db86aabSstevel 	}
7100*3db86aabSstevel 
7101*3db86aabSstevel 	ptr = cl_data;
7102*3db86aabSstevel 	while (ptr != NULL) {
7103*3db86aabSstevel 		ptr->flags &= ~done_flag;
7104*3db86aabSstevel 		ptr = ptr->next;
7105*3db86aabSstevel 	}
7106*3db86aabSstevel }
7107*3db86aabSstevel 
7108*3db86aabSstevel static int
7109*3db86aabSstevel syshw_open(dev_t *dev, int flag, int otyp, cred_t *cred)
7110*3db86aabSstevel {
7111*3db86aabSstevel 	_NOTE(ARGUNUSED(dev, flag, cred))
7112*3db86aabSstevel 
7113*3db86aabSstevel 	if (otyp != OTYP_CHR)
7114*3db86aabSstevel 		return (EINVAL);
7115*3db86aabSstevel 
7116*3db86aabSstevel 	return (0);
7117*3db86aabSstevel }
7118*3db86aabSstevel 
7119*3db86aabSstevel static int
7120*3db86aabSstevel syshw_close(dev_t dev, int flag, int otyp, cred_t *cred)
7121*3db86aabSstevel {
7122*3db86aabSstevel 	_NOTE(ARGUNUSED(dev, flag, otyp, cred))
7123*3db86aabSstevel 
7124*3db86aabSstevel 	return (0);
7125*3db86aabSstevel }
7126*3db86aabSstevel 
7127*3db86aabSstevel /*
7128*3db86aabSstevel  * Add a client to the list of interested processes
7129*3db86aabSstevel  */
7130*3db86aabSstevel static void
7131*3db86aabSstevel add_client(client_data *new)
7132*3db86aabSstevel {
7133*3db86aabSstevel 	client_data * ptr;
7134*3db86aabSstevel 
7135*3db86aabSstevel 	n_clients++;
7136*3db86aabSstevel 	if (cl_data == NULL) {
7137*3db86aabSstevel 		cl_data = new;
7138*3db86aabSstevel 		return;
7139*3db86aabSstevel 	}
7140*3db86aabSstevel 
7141*3db86aabSstevel 	ptr = cl_data;
7142*3db86aabSstevel 	while ((ptr->next != NULL) && (ptr->priority <= new->priority))
7143*3db86aabSstevel 		ptr = ptr->next;
7144*3db86aabSstevel 
7145*3db86aabSstevel 	if (ptr == cl_data) {
7146*3db86aabSstevel 		/* at head of the list */
7147*3db86aabSstevel 		cl_data = new;
7148*3db86aabSstevel 		new->next = ptr;
7149*3db86aabSstevel 		new->prev = NULL;
7150*3db86aabSstevel 		if (ptr != NULL)
7151*3db86aabSstevel 			ptr->prev = new;
7152*3db86aabSstevel 	} else {
7153*3db86aabSstevel 		/* somewhere else in the list - insert after */
7154*3db86aabSstevel 		new->next = ptr->next;
7155*3db86aabSstevel 		ptr->next = new;
7156*3db86aabSstevel 		new->prev = ptr;
7157*3db86aabSstevel 		if (new->next != NULL)
7158*3db86aabSstevel 			(new->next)->prev = new;
7159*3db86aabSstevel 	}
7160*3db86aabSstevel }
7161*3db86aabSstevel 
7162*3db86aabSstevel /*
7163*3db86aabSstevel  * Locate a client data structure in the client list by looking for a PID match.
7164*3db86aabSstevel  */
7165*3db86aabSstevel static client_data *
7166*3db86aabSstevel locate_client(pid_t pid)
7167*3db86aabSstevel {
7168*3db86aabSstevel 	client_data * ptr = cl_data;
7169*3db86aabSstevel 
7170*3db86aabSstevel 	while ((ptr != NULL) && (ptr->pid != pid))
7171*3db86aabSstevel 		ptr = ptr->next;
7172*3db86aabSstevel 
7173*3db86aabSstevel 	return (ptr);
7174*3db86aabSstevel }
7175*3db86aabSstevel 
7176*3db86aabSstevel /*
7177*3db86aabSstevel  * Remove a client record from the client list
7178*3db86aabSstevel  */
7179*3db86aabSstevel static void
7180*3db86aabSstevel delete_client(pid_t pid)
7181*3db86aabSstevel {
7182*3db86aabSstevel 	client_data * ptr;
7183*3db86aabSstevel 
7184*3db86aabSstevel 	ptr = locate_client(pid);
7185*3db86aabSstevel 	if (ptr == NULL)
7186*3db86aabSstevel 		return;	/* hmmm!! */
7187*3db86aabSstevel 
7188*3db86aabSstevel 	n_clients--;
7189*3db86aabSstevel 
7190*3db86aabSstevel 	if (ptr == cl_data) {
7191*3db86aabSstevel 		/* remove the head of the list */
7192*3db86aabSstevel 		cl_data = ptr->next;
7193*3db86aabSstevel 	}
7194*3db86aabSstevel 	if (ptr->prev != NULL)
7195*3db86aabSstevel 		(ptr->prev)->next = ptr->next;
7196*3db86aabSstevel 	if (ptr->next != NULL)
7197*3db86aabSstevel 		(ptr->next)->prev = ptr->prev;
7198*3db86aabSstevel 
7199*3db86aabSstevel 	kmem_free(ptr, sizeof (client_data));
7200*3db86aabSstevel }
7201*3db86aabSstevel 
7202*3db86aabSstevel static void
7203*3db86aabSstevel unregister_event_client()
7204*3db86aabSstevel {
7205*3db86aabSstevel 	pcic_mutex_enter(&client_mtx);
7206*3db86aabSstevel 	delete_client(ddi_get_pid());
7207*3db86aabSstevel 	pcic_mutex_exit(&client_mtx);
7208*3db86aabSstevel }
7209*3db86aabSstevel 
7210*3db86aabSstevel static int
7211*3db86aabSstevel register_event_client(client_data *u_client)
7212*3db86aabSstevel {
7213*3db86aabSstevel 	int	error;
7214*3db86aabSstevel 	client_data * client;
7215*3db86aabSstevel 
7216*3db86aabSstevel 	pcic_mutex_enter(&client_mtx);
7217*3db86aabSstevel 	client = locate_client(ddi_get_pid());
7218*3db86aabSstevel 	if (client) {
7219*3db86aabSstevel 		/*
7220*3db86aabSstevel 		 * we are re-registering ourself
7221*3db86aabSstevel 		 * so we delete the previous entry
7222*3db86aabSstevel 		 */
7223*3db86aabSstevel 		delete_client(ddi_get_pid());
7224*3db86aabSstevel 	}
7225*3db86aabSstevel 
7226*3db86aabSstevel 	client = (client_data *)kmem_alloc(sizeof (client_data), KM_SLEEP);
7227*3db86aabSstevel 
7228*3db86aabSstevel 	if (client) {
7229*3db86aabSstevel 		client->pid = ddi_get_pid();
7230*3db86aabSstevel 		client->priority = u_client->priority;
7231*3db86aabSstevel 		client->flags = u_client->flags & NCE_EVENT_MASK;
7232*3db86aabSstevel 		client->events = 0;
7233*3db86aabSstevel 		client->event_sig = u_client->event_sig;
7234*3db86aabSstevel 		client->next = NULL;
7235*3db86aabSstevel 		client->prev = NULL;
7236*3db86aabSstevel 		add_client(client);
7237*3db86aabSstevel 		error = 0;
7238*3db86aabSstevel 	} else
7239*3db86aabSstevel 		error = EIO;
7240*3db86aabSstevel 
7241*3db86aabSstevel 	pcic_mutex_exit(&client_mtx);
7242*3db86aabSstevel 	return (error);
7243*3db86aabSstevel }
7244*3db86aabSstevel 
7245*3db86aabSstevel /*
7246*3db86aabSstevel  * Read the currently pending event flags for the process in question
7247*3db86aabSstevel  */
7248*3db86aabSstevel static int
7249*3db86aabSstevel check_events_pending(caddr_t data)
7250*3db86aabSstevel {
7251*3db86aabSstevel 	client_data * client;
7252*3db86aabSstevel 	int	error = 0;
7253*3db86aabSstevel 
7254*3db86aabSstevel 	pcic_mutex_enter(&client_mtx);
7255*3db86aabSstevel 	client = locate_client(ddi_get_pid());
7256*3db86aabSstevel 	if (client) {
7257*3db86aabSstevel 		if (copyout((caddr_t)&client->events, data, sizeof (int)))
7258*3db86aabSstevel 			error = EFAULT;
7259*3db86aabSstevel 		else
7260*3db86aabSstevel 			client->events = 0;
7261*3db86aabSstevel 	} else
7262*3db86aabSstevel 		error = EINVAL;
7263*3db86aabSstevel 
7264*3db86aabSstevel 	pcic_mutex_exit(&client_mtx);
7265*3db86aabSstevel 	return (error);
7266*3db86aabSstevel }
7267*3db86aabSstevel 
7268*3db86aabSstevel 
7269*3db86aabSstevel #define	MAXITEMS	8
7270*3db86aabSstevel static syshw_t *syshw_map[MAXITEMS];
7271*3db86aabSstevel static void	(*syshw_getfuncs[MAXITEMS])(syshw_t *, void *);
7272*3db86aabSstevel static void	*syshw_getfunc_args[MAXITEMS];
7273*3db86aabSstevel static int	nsyshw_items = 0;
7274*3db86aabSstevel #define	NSYSHW_ITEMS	nsyshw_items
7275*3db86aabSstevel 
7276*3db86aabSstevel static uint32_t
7277*3db86aabSstevel syshw_add2map(syshw_t *item, void (*getfunc)(syshw_t *, void *), void *getarg)
7278*3db86aabSstevel {
7279*3db86aabSstevel 	uint32_t rval = (1 << nsyshw_items);
7280*3db86aabSstevel 	if (nsyshw_items == MAXITEMS)
7281*3db86aabSstevel 		return (0);
7282*3db86aabSstevel 	item->hw_id = nsyshw_items;
7283*3db86aabSstevel 	syshw_map[nsyshw_items] = item;
7284*3db86aabSstevel 	syshw_getfuncs[nsyshw_items] = getfunc;
7285*3db86aabSstevel 	syshw_getfunc_args[nsyshw_items] = getarg;
7286*3db86aabSstevel 	nsyshw_items++;
7287*3db86aabSstevel 	return (rval);
7288*3db86aabSstevel }
7289*3db86aabSstevel 
7290*3db86aabSstevel static int
7291*3db86aabSstevel syshw_ioctl(dev_t dev, int cmd, intptr_t ioctldata, int mode,
7292*3db86aabSstevel cred_t *cred, int *rval)
7293*3db86aabSstevel {
7294*3db86aabSstevel 	caddr_t data = (caddr_t)ioctldata;
7295*3db86aabSstevel 	syshw_t sh;
7296*3db86aabSstevel 	hwev_t hwev;
7297*3db86aabSstevel 	client_data dummy_client;
7298*3db86aabSstevel 	int	rc = 0, i;
7299*3db86aabSstevel 
7300*3db86aabSstevel 	_NOTE(ARGUNUSED(dev, mode, cred, rval))
7301*3db86aabSstevel 
7302*3db86aabSstevel 	switch (cmd) {
7303*3db86aabSstevel 	default:
7304*3db86aabSstevel 		rc = EINVAL;
7305*3db86aabSstevel 		break;
7306*3db86aabSstevel 
7307*3db86aabSstevel 	case SYSHW_GET_ITEM:
7308*3db86aabSstevel 	case SYSHW_GET_ITEM_MAXVALUES:
7309*3db86aabSstevel 		if (copyin(data, (caddr_t)&sh, sizeof (sh))) {
7310*3db86aabSstevel 			rc = EFAULT;
7311*3db86aabSstevel 			break;
7312*3db86aabSstevel 		}
7313*3db86aabSstevel 
7314*3db86aabSstevel 		if (sh.hw_id >= NSYSHW_ITEMS) {
7315*3db86aabSstevel 			rc = EINVAL;
7316*3db86aabSstevel 			break;
7317*3db86aabSstevel 		}
7318*3db86aabSstevel 
7319*3db86aabSstevel 		sh = *syshw_map[sh.hw_id];
7320*3db86aabSstevel 		if (!sh.id_string[0]) {
7321*3db86aabSstevel 			rc = ENOTTY;
7322*3db86aabSstevel 			break;
7323*3db86aabSstevel 		}
7324*3db86aabSstevel 		if (cmd == SYSHW_GET_ITEM) {
7325*3db86aabSstevel 			if (syshw_getfuncs[sh.hw_id])
7326*3db86aabSstevel 				syshw_getfuncs[sh.hw_id](&sh,
7327*3db86aabSstevel 				    syshw_getfunc_args[sh.hw_id]);
7328*3db86aabSstevel 			else
7329*3db86aabSstevel 				rc = ENOTTY;
7330*3db86aabSstevel 		}
7331*3db86aabSstevel 
7332*3db86aabSstevel 		if (copyout((caddr_t)&sh, data, sizeof (sh))) {
7333*3db86aabSstevel 			rc = EFAULT;
7334*3db86aabSstevel 			break;
7335*3db86aabSstevel 		}
7336*3db86aabSstevel 		break;
7337*3db86aabSstevel 
7338*3db86aabSstevel 	case SYSHW_SET_ITEM:
7339*3db86aabSstevel 		if (copyin(data, (caddr_t)&sh, sizeof (sh))) {
7340*3db86aabSstevel 			rc = EFAULT;
7341*3db86aabSstevel 			break;
7342*3db86aabSstevel 		}
7343*3db86aabSstevel 
7344*3db86aabSstevel 		if (sh.hw_id >= NSYSHW_ITEMS ||
7345*3db86aabSstevel 		    !syshw_map[sh.hw_id]->id_string[0] ||
7346*3db86aabSstevel 		    !(syshw_map[sh.hw_id]->capabilities &
7347*3db86aabSstevel 		    (SYSHW_STATE_MODIFY | SYSHW_VAL0_MODIFY |
7348*3db86aabSstevel 		    SYSHW_VAL1_MODIFY | SYSHW_VAL2_MODIFY |
7349*3db86aabSstevel 		    SYSHW_VAL3_MODIFY))) {
7350*3db86aabSstevel 			rc = EINVAL;
7351*3db86aabSstevel 			break;
7352*3db86aabSstevel 		}
7353*3db86aabSstevel 
7354*3db86aabSstevel 		switch (sh.hw_id) {
7355*3db86aabSstevel 		default:
7356*3db86aabSstevel 			rc = EINVAL;
7357*3db86aabSstevel 			break;
7358*3db86aabSstevel 		}
7359*3db86aabSstevel 		break;
7360*3db86aabSstevel 
7361*3db86aabSstevel 	case SYSHW_EVREG:
7362*3db86aabSstevel 		if (copyin(data, (caddr_t)&hwev, sizeof (hwev))) {
7363*3db86aabSstevel 			rc = EFAULT;
7364*3db86aabSstevel 			break;
7365*3db86aabSstevel 		}
7366*3db86aabSstevel 
7367*3db86aabSstevel 		for (i = 0; i < NSYSHW_ITEMS; i++) {
7368*3db86aabSstevel 			if (hwev.events & (1 << i) &&
7369*3db86aabSstevel 			    !(syshw_map[i]->capabilities &
7370*3db86aabSstevel 			    SYSHW_CAN_SIGNAL_CHANGE)) {
7371*3db86aabSstevel 				rc = EINVAL;
7372*3db86aabSstevel 				break;
7373*3db86aabSstevel 			}
7374*3db86aabSstevel 		}
7375*3db86aabSstevel 		if (hwev.event_sig != SIGUSR1 && hwev.event_sig != SIGUSR2)
7376*3db86aabSstevel 			rc = EINVAL;
7377*3db86aabSstevel 
7378*3db86aabSstevel 		if (!rc) {
7379*3db86aabSstevel 			dummy_client.priority = 100;
7380*3db86aabSstevel 			dummy_client.flags = hwev.events;
7381*3db86aabSstevel 			dummy_client.event_sig = hwev.event_sig;
7382*3db86aabSstevel 			rc = register_event_client(&dummy_client);
7383*3db86aabSstevel 		}
7384*3db86aabSstevel 		break;
7385*3db86aabSstevel 
7386*3db86aabSstevel 	case SYSHW_EVUNREG:
7387*3db86aabSstevel 		unregister_event_client();
7388*3db86aabSstevel 		break;
7389*3db86aabSstevel 
7390*3db86aabSstevel 	case SYSHW_CHKEV:
7391*3db86aabSstevel 		rc = check_events_pending(data);
7392*3db86aabSstevel 		break;
7393*3db86aabSstevel 	}
7394*3db86aabSstevel 	return (rc);
7395*3db86aabSstevel }
7396