1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * PCMCIA NEXUS
28  *	The PCMCIA module is a generalized interface for
29  *	implementing PCMCIA nexus drivers.  It preserves
30  *	the logical socket name space while allowing multiple
31  *	instances of the hardware to be properly represented
32  *	in the device tree.
33  *
34  *	The nexus also exports events to an event manager
35  *	driver if it has registered.
36  */
37 
38 #include <sys/types.h>
39 #include <sys/systm.h>
40 #include <sys/user.h>
41 #include <sys/buf.h>
42 #include <sys/file.h>
43 #include <sys/uio.h>
44 #include <sys/conf.h>
45 #include <sys/stat.h>
46 #include <sys/autoconf.h>
47 #include <sys/vtoc.h>
48 #include <sys/dkio.h>
49 #include <sys/ddi.h>
50 #include <sys/debug.h>
51 #include <sys/sunddi.h>
52 #include <sys/sunndi.h>
53 #include <sys/cred.h>
54 #include <sys/kstat.h>
55 #include <sys/kmem.h>
56 #include <sys/modctl.h>
57 #include <sys/kobj.h>
58 #include <sys/callb.h>
59 #include <sys/param.h>
60 #include <sys/thread.h>
61 #include <sys/proc.h>
62 
63 #include <sys/pctypes.h>
64 #include <sys/pcmcia.h>
65 #include <sys/sservice.h>
66 #include <pcmcia/sys/cs_types.h>
67 #include <pcmcia/sys/cis.h>
68 #include <pcmcia/sys/cis_handlers.h>
69 #include <pcmcia/sys/cs.h>
70 #include <pcmcia/sys/cs_priv.h>
71 
72 #ifdef sparc
73 #include <sys/ddi_subrdefs.h>
74 
75 #elif defined(__x86)
76 #include <sys/mach_intr.h>
77 #endif
78 
79 #undef SocketServices
80 
81 /* some bus specific stuff */
82 
83 /* need PCI regspec size for worst case at present */
84 #include <sys/pci.h>
85 
86 typedef struct pcmcia_logical_socket {
87 	int			ls_socket; /* adapter's socket number */
88 	uint32_t		ls_flags;
89 	struct pcmcia_adapter	*ls_adapter;
90 	pcmcia_if_t		*ls_if;
91 	dev_info_t		*ls_sockdrv;
92 	dev_info_t		*ls_dip[PCMCIA_MAX_FUNCTIONS];
93 	dev_info_t		*ls_mfintr_dip;
94 	int			ls_functions;
95 	uint32_t		ls_cs_events;
96 	uint32_t		ls_intr_pri;
97 	uint32_t		ls_intr_vec;
98 	int			ls_intrrefs;
99 	struct intrspec		ls_intrspec; /* MFC intrspec */
100 	inthandler_t		*ls_inthandlers; /* for multifunction cards */
101 	ddi_iblock_cookie_t	ls_iblk;
102 	ddi_idevice_cookie_t	ls_idev;
103 	kmutex_t		ls_ilock;
104 	int			ls_error; /* error for CS return */
105 } pcmcia_logical_socket_t;
106 
107 /*
108  * entry points used by the true nexus
109  */
110 int pcmcia_detach(dev_info_t *, ddi_detach_cmd_t);
111 int pcmcia_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
112 int pcmcia_prop_op(dev_t, dev_info_t *, dev_info_t *, ddi_prop_op_t,
113 			int, char *, caddr_t, int *);
114 void pcmcia_set_assigned(dev_info_t *, int, ra_return_t *);
115 int pcmcia_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
116     ddi_intr_handle_impl_t *hdlp, void *result);
117 
118 /*
119  * prototypes used internally by the nexus and sometimes Card Services
120  */
121 int SocketServices(int function, ...);
122 
123 
124 void *CISParser(int function, ...);
125 extern void *(*cis_parser)(int, ...);
126 
127 struct regspec *pcmcia_cons_regspec(dev_info_t *, int, uchar_t *,
128 					ra_return_t *);
129 
130 static int (*pcmcia_card_services)(int, ...) = NULL;
131 
132 /*
133  * variables used in the logical/physical mappings
134  * that the nexus common code maintains.
135  */
136 struct pcmcia_adapter *pcmcia_adapters[PCMCIA_MAX_ADAPTERS];
137 int    pcmcia_num_adapters;
138 pcmcia_logical_socket_t *pcmcia_sockets[PCMCIA_MAX_SOCKETS];
139 int    pcmcia_num_sockets;
140 pcmcia_logical_window_t *pcmcia_windows[PCMCIA_MAX_WINDOWS];
141 int    pcmcia_num_windows;
142 struct power_entry pcmcia_power_table[PCMCIA_MAX_POWER];
143 int	pcmcia_num_power;
144 
145 struct pcmcia_mif *pcmcia_mif_handlers = NULL;
146 pcm_dev_node_t *pcmcia_devnodes = NULL;
147 
148 kmutex_t pcmcia_global_lock;
149 kcondvar_t pcmcia_condvar;
150 kmutex_t pcmcia_enum_lock;
151 
152 /*
153  * Mapping of the device "type" to names acceptable to
154  * the DDI
155  */
156 static char *pcmcia_dev_type[] = {
157 	"multifunction",
158 	"byte",
159 	"serial",
160 	"parallel",
161 	"block",
162 	"display",
163 	"network",
164 	"block",
165 	"byte"
166 };
167 
168 char *pcmcia_default_pm_mode = "parental-suspend-resume";
169 
170 /*
171  * generic names from the approved list:
172  *	disk tape pci sbus scsi token-ring isa keyboard display mouse
173  *	audio ethernet timer memory parallel serial rtc nvram scanner
174  *	floppy(controller) fddi isdn atm ide pccard video-in video-out
175  * in some cases there will need to be device class dependent names.
176  * network -> ethernet, token-ring, etc.
177  * this list is a first guess and is used when all else fails.
178  */
179 
180 char *pcmcia_generic_names[] = {
181 	"multifunction",
182 	"memory",
183 	"serial",
184 	"parallel",
185 	"disk",
186 	"video",		/* no spec for video-out yet */
187 	"network",
188 	"aims",
189 	"scsi",
190 	"security"
191 };
192 
193 #define	PCM_GENNAME_SIZE	(sizeof (pcmcia_generic_names) / \
194 					sizeof (char *))
195 #define	PCMCIA_MAP_IO	0x0
196 #define	PCMCIA_MAP_MEM	0x1
197 #define	PPB_SUBTRACTIVE	((PCI_CLASS_BRIDGE << 16) | (PCI_BRIDGE_PCI << 8) | \
198 		(PCI_BRIDGE_PCI_IF_SUBDECODE))
199 
200 /*
201  * The following should be 2^^n - 1
202  */
203 #define	PCMCIA_SOCKET_BITS	0x7f
204 
205 #ifdef PCMCIA_DEBUG
206 int pcmcia_debug = 0x0;
207 static void pcmcia_dump_minors(dev_info_t *);
208 #endif
209 
210 static f_tt *pcmcia_cs_event = NULL;
211 int pcmcia_timer_id;
212 dev_info_t	*pcmcia_dip;
213 /*
214  * XXX - See comments in cs.c
215  */
216 static f_tt *pcmcia_cis_parser = NULL;
217 
218 extern struct pc_socket_services pc_socket_services;
219 
220 /* some function declarations */
221 static int pcm_adapter_callback(dev_info_t *, int, int, int);
222 extern void pcmcia_init_adapter(anp_t *, dev_info_t *);
223 extern void pcmcia_find_cards(anp_t *);
224 extern void pcmcia_merge_power(struct power_entry *);
225 extern void pcmcia_do_resume(int, pcmcia_logical_socket_t *);
226 extern void pcmcia_resume(int, pcmcia_logical_socket_t *);
227 extern void pcmcia_do_suspend(int, pcmcia_logical_socket_t *);
228 extern void pcm_event_manager(int, int, void *);
229 static void pcmcia_create_dev_info(int);
230 static int pcmcia_create_device(ss_make_device_node_t *);
231 static void pcmcia_init_devinfo(dev_info_t *, struct pcm_device_info *);
232 void pcmcia_fix_string(char *str);
233 dev_info_t *pcmcia_number_socket(dev_info_t *, int);
234 static int pcmcia_merge_conf(dev_info_t *);
235 static uint32_t pcmcia_mfc_intr(caddr_t, caddr_t);
236 void pcmcia_free_resources(dev_info_t *);
237 static void pcmcia_ppd_free(struct pcmcia_parent_private *ppd);
238 int pcmcia_get_intr(dev_info_t *, int);
239 int pcmcia_return_intr(dev_info_t *, int);
240 int pcmcia_ra_alloc(dev_info_t *, ndi_ra_request_t *, ra_return_t *, char *,
241 		dev_info_t **);
242 int pcmcia_ra_free(dev_info_t *, ra_return_t *, char *);
243 
244 extern int cs_init(void);
245 extern int cs_deinit(void);
246 extern void cisp_init(void);
247 extern void cis_deinit(void);
248 
249 /*
250  * non-DDI compliant functions are listed here
251  * some will be declared while others that have
252  * entries in .h files. All will be commented on.
253  *
254  * with declarations:
255  *	ddi_add_child
256  *	ddi_binding_name
257  *	ddi_bus_prop_op
258  *	ddi_ctlops
259  *	ddi_find_devinfo
260  *	ddi_get_name_addr
261  *	ddi_get_parent_data
262  *	ddi_hold_installed_driver
263  *	ddi_name_to_major
264  *	ddi_node_name
265  *	ddi_pathname
266  *	ddi_rele_driver
267  *	ddi_set_name_addr
268  *	ddi_set_parent_data
269  *	ddi_unorphan_devs
270  *	i_ddi_bind_node_to_driver
271  *	i_ddi_bind_node_to_driver
272  *	i_ddi_bus_map
273  *	i_ddi_map_fault
274  *	i_ddi_mem_alloc
275  *	i_ddi_mem_alloc
276  *	i_ddi_mem_free
277  *	i_ddi_mem_free
278  *	modload
279  *	modunload
280  */
281 
282 extern void ddi_unorphan_devs(major_t);
283 
284 /* Card&Socket Services entry points */
285 static int GetCookiesAndDip(sservice_t *);
286 static int SSGetAdapter(get_adapter_t *);
287 static int SSGetPage(get_page_t *);
288 static int SSGetSocket(get_socket_t *);
289 static int SSGetStatus(get_ss_status_t *);
290 static int SSGetWindow(get_window_t *);
291 static int SSInquireAdapter(inquire_adapter_t *);
292 static int SSInquireSocket(inquire_socket_t *);
293 static int SSInquireWindow(inquire_window_t *);
294 static int SSResetSocket(int, int);
295 static int SSSetPage(set_page_t *);
296 static int SSSetSocket(set_socket_t *);
297 static int SSSetWindow(set_window_t *);
298 static int SSSetIRQHandler(set_irq_handler_t *);
299 static int SSClearIRQHandler(clear_irq_handler_t *);
300 
301 static struct modldrv modlmisc = {
302 	&mod_miscops,		/* Type of module. This one is a driver */
303 	"PCMCIA Nexus Support", /* Name of the module. */
304 };
305 
306 static struct modlinkage modlinkage = {
307 	MODREV_1, (void *)&modlmisc, NULL
308 };
309 
310 int
_init()311 _init()
312 {
313 	int	ret;
314 
315 	cisp_init();
316 
317 	if (cs_init() != CS_SUCCESS) {
318 		if (cs_deinit() != CS_SUCCESS)
319 			cmn_err(CE_CONT, "pcmcia: _init cs_deinit error\n");
320 		return (-1);
321 	}
322 
323 	mutex_init(&pcmcia_global_lock, NULL, MUTEX_DEFAULT, NULL);
324 	cv_init(&pcmcia_condvar, NULL, CV_DRIVER, NULL);
325 	mutex_init(&pcmcia_enum_lock, NULL, MUTEX_DEFAULT, NULL);
326 
327 	if ((ret = mod_install(&modlinkage)) != 0) {
328 		mutex_destroy(&pcmcia_global_lock);
329 		cv_destroy(&pcmcia_condvar);
330 		mutex_destroy(&pcmcia_enum_lock);
331 	}
332 	return (ret);
333 }
334 
335 int
_fini()336 _fini()
337 {
338 	int	ret;
339 
340 	if ((ret = mod_remove(&modlinkage)) == 0) {
341 		mutex_destroy(&pcmcia_global_lock);
342 		cv_destroy(&pcmcia_condvar);
343 		mutex_destroy(&pcmcia_enum_lock);
344 		cis_deinit();
345 		if (cs_deinit() != CS_SUCCESS) {
346 			cmn_err(CE_CONT, "pcmcia: _fini cs_deinit error\n");
347 		}
348 	}
349 	return (ret);
350 }
351 
352 int
_info(struct modinfo * modinfop)353 _info(struct modinfo *modinfop)
354 {
355 	return (mod_info(&modlinkage, modinfop));
356 }
357 
358 extern pri_t minclsyspri;
359 
360 /*
361  * pcmcia_attach()
362  *	the attach routine must make sure that everything needed is present
363  *	including real hardware.  The sequence of events is:
364  *		attempt to load all adapter drivers
365  *		attempt to load Card Services
366  *		initialize logical sockets
367  *		report the nexus exists
368  */
369 
370 int
pcmcia_attach(dev_info_t * dip,anp_t * adapter)371 pcmcia_attach(dev_info_t *dip, anp_t *adapter)
372 {
373 	int count, done, i;
374 
375 #if defined(PCMCIA_DEBUG)
376 	if (pcmcia_debug) {
377 		cmn_err(CE_CONT, "pcmcia_attach: dip=0x%p adapter=0x%p\n",
378 		    (void *)dip, (void *)adapter);
379 	}
380 #endif
381 
382 	pcmcia_dip = dip;
383 
384 	mutex_enter(&pcmcia_enum_lock);
385 	mutex_enter(&pcmcia_global_lock);
386 	if (pcmcia_num_adapters == 0) {
387 		pcmcia_cis_parser = (f_tt *)(uintptr_t)CISParser;
388 		cis_parser = (void *(*)(int, ...)) CISParser;
389 		pcmcia_cs_event = (f_tt *)cs_event;
390 		cs_socket_services = SocketServices;
391 		/* tell CS we are up with basic init level */
392 		(void) cs_event(PCE_SS_INIT_STATE, PCE_SS_STATE_INIT, 0);
393 	}
394 
395 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
396 	    PCM_DEVICETYPE, "pccard");
397 
398 	ddi_report_dev(dip);	/* directory/device naming */
399 
400 	/*
401 	 * now setup any power management stuff necessary.
402 	 * we do it here in order to ensure that all PC Card nexi
403 	 * implement it.
404 	 */
405 
406 	if (pm_create_components(dip, 1) != DDI_SUCCESS) {
407 		cmn_err(CE_WARN, "%s: not power managed\n",
408 		    ddi_get_name_addr(dip));
409 	} else {
410 		pm_set_normal_power(dip, 0, 1);
411 	}
412 
413 	/*
414 	 * setup the info necessary for Card Services/SocketServices
415 	 * and notify CS when ready.
416 	 */
417 
418 	pcmcia_free_resources(dip);
419 	pcmcia_init_adapter(adapter, dip);
420 	/* exit mutex so CS can run for any cards found */
421 	mutex_exit(&pcmcia_global_lock);
422 
423 	/*
424 	 * make sure the devices are identified before
425 	 * returning.  We do this by checking each socket to see if
426 	 * a card is present.  If there is one, and there isn't a dip,
427 	 * we can't be done.  We scan the list of sockets doing the
428 	 * check. if we aren't done, wait for a condition variable to
429 	 * wakeup.
430 	 * Because we can miss a wakeup and because things can
431 	 * take time, we do eventually give up and have a timeout.
432 	 */
433 
434 	for (count = 0, done = 0;
435 	    done == 0 && count < max(pcmcia_num_sockets, 16);
436 	    count++) {
437 		done = 1;
438 		/* block CS while checking so we don't miss anything */
439 		mutex_enter(&pcmcia_global_lock);
440 		for (i = 0; i < pcmcia_num_sockets; i++) {
441 			get_ss_status_t status;
442 			if (pcmcia_sockets[i] == NULL)
443 				continue;
444 			bzero(&status, sizeof (status));
445 			status.socket = i;
446 			if (SSGetStatus(&status) == SUCCESS) {
447 				if (status.CardState & SBM_CD &&
448 				    pcmcia_sockets[i]->ls_dip[0] == NULL) {
449 					done = 0;
450 				}
451 			}
452 		}
453 		/* only wait if we aren't done with this set */
454 		if (!done) {
455 			mutex_exit(&pcmcia_global_lock);
456 			delay(10); /* give up CPU for a time */
457 			mutex_enter(&pcmcia_global_lock);
458 		}
459 		mutex_exit(&pcmcia_global_lock);
460 	}
461 
462 	mutex_exit(&pcmcia_enum_lock);
463 	return (DDI_SUCCESS);
464 }
465 
466 /*
467  * pcmcia_detach
468  *	unload everything and then detach the nexus
469  */
470 /* ARGSUSED */
471 int
pcmcia_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)472 pcmcia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
473 {
474 	switch (cmd) {
475 	case DDI_DETACH:
476 		pm_destroy_components(dip);
477 		return (DDI_SUCCESS);
478 
479 	/*
480 	 * resume from a checkpoint
481 	 * We don't do anything special here since the adapter
482 	 * driver will generate resume events that we intercept
483 	 * and convert to insert events.
484 	 */
485 	case DDI_SUSPEND:
486 	case DDI_PM_SUSPEND:
487 		return (DDI_SUCCESS);
488 
489 	default:
490 		return (DDI_FAILURE);
491 	}
492 }
493 
494 /*
495  * card_services_error()
496  *	used to make 2.4/2.5 drivers get an error when
497  *	they try to initialize.
498  */
499 static int
card_services_error()500 card_services_error()
501 {
502 	return (CS_BAD_VERSION);
503 }
504 static int (*cs_error_ptr)() = card_services_error;
505 
506 /*
507  * pcmcia_ctlops
508  *	handle the nexus control operations for the cases where
509  *	a PC Card driver gets called and we need to modify the
510  *	devinfo structure or otherwise do bus specific operations
511  */
512 int
pcmcia_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)513 pcmcia_ctlops(dev_info_t *dip, dev_info_t *rdip,
514     ddi_ctl_enum_t ctlop, void *arg, void *result)
515 {
516 	int e;
517 	char name[64];
518 	struct pcmcia_parent_private *ppd;
519 	power_req_t *pm;
520 
521 #if defined(PCMCIA_DEBUG)
522 	if (pcmcia_debug) {
523 		cmn_err(CE_CONT, "pcmcia_ctlops(%p, %p, %d, %p, %p)\n",
524 		    (void *)dip, (void *)rdip, ctlop, (void *)arg,
525 		    (void *)result);
526 		if (rdip != NULL && ddi_get_name(rdip) != NULL)
527 			cmn_err(CE_CONT, "\t[%s]\n", ddi_get_name(rdip));
528 	}
529 #endif
530 
531 	switch (ctlop) {
532 	case DDI_CTLOPS_REPORTDEV:
533 		if (rdip == (dev_info_t *)0)
534 			return (DDI_FAILURE);
535 
536 		if (strcmp("pcs", ddi_node_name(rdip)) == 0)
537 			cmn_err(CE_CONT, "?PCCard socket %d at %s@%s\n",
538 			    ddi_get_instance(rdip),
539 			    ddi_driver_name(dip), ddi_get_name_addr(dip));
540 		else
541 			cmn_err(CE_CONT, "?%s%d at %s@%s in socket %d\n",
542 			    ddi_driver_name(rdip),
543 			    ddi_get_instance(rdip),
544 			    ddi_driver_name(dip),
545 			    ddi_get_name_addr(dip),
546 			    CS_GET_SOCKET_NUMBER(
547 			    ddi_getprop(DDI_DEV_T_NONE, rdip,
548 			    DDI_PROP_DONTPASS,
549 			    PCM_DEV_SOCKET, -1)));
550 
551 		return (DDI_SUCCESS);
552 
553 	case DDI_CTLOPS_INITCHILD:
554 		/*
555 		 * we get control here before the child is called.
556 		 * we can change things if necessary.  This is where
557 		 * the CardServices hook gets planted.
558 		 */
559 #if defined(PCMCIA_DEBUG)
560 		if (pcmcia_debug) {
561 			cmn_err(CE_CONT, "pcmcia: init child: %s(%d) @%p\n",
562 			    ddi_node_name(arg), ddi_get_instance(arg),
563 			    (void *)arg);
564 			if (DEVI(arg)->devi_binding_name != NULL)
565 				cmn_err(CE_CONT, "\tbinding_name=%s\n",
566 				    DEVI(arg)->devi_binding_name);
567 			if (DEVI(arg)->devi_node_name != NULL)
568 				cmn_err(CE_CONT, "\tnode_name=%s\n",
569 				    DEVI(arg)->devi_node_name);
570 		}
571 #endif
572 
573 		ppd = (struct pcmcia_parent_private *)
574 		    ddi_get_parent_data((dev_info_t *)arg);
575 		if (ppd == NULL)
576 			return (DDI_FAILURE);
577 
578 		if (strcmp("pcs", ddi_node_name((dev_info_t *)arg)) == 0) {
579 			if (ppd == NULL)
580 				return (DDI_FAILURE);
581 			(void) sprintf(name, "%x",
582 			    (int)ppd->ppd_reg[0].phys_hi);
583 			ddi_set_name_addr((dev_info_t *)arg, name);
584 			return (DDI_SUCCESS);
585 		}
586 
587 		/*
588 		 * We don't want driver.conf files that stay in
589 		 * pseudo device form.	It is acceptable to have
590 		 * .conf files add properties only.
591 		 */
592 		if (ndi_dev_is_persistent_node((dev_info_t *)arg) == 0) {
593 			(void) pcmcia_merge_conf((dev_info_t *)arg);
594 			cmn_err(CE_WARN, "%s%d: %s.conf invalid",
595 			    ddi_get_name((dev_info_t *)arg),
596 			    ddi_get_instance((dev_info_t *)arg),
597 			    ddi_get_name((dev_info_t *)arg));
598 			return (DDI_FAILURE);
599 		}
600 
601 
602 #if defined(PCMCIA_DEBUG)
603 		if (pcmcia_debug && ppd != NULL) {
604 			cmn_err(CE_CONT, "\tnreg=%x, intr=%x, socket=%x,"
605 			    " function=%x, active=%x, flags=%x\n",
606 			    ppd->ppd_nreg, ppd->ppd_intr,
607 			    ppd->ppd_socket, ppd->ppd_function,
608 			    ppd->ppd_active, ppd->ppd_flags);
609 		}
610 #endif
611 
612 		/*
613 		 * make sure names are relative to socket number
614 		 */
615 		if (ppd->ppd_function > 0) {
616 			int sock;
617 			int func;
618 			sock = ppd->ppd_socket;
619 			func = ppd->ppd_function;
620 			(void) sprintf(name, "%x,%x", sock, func);
621 		} else {
622 			(void) sprintf(name, "%x", ppd->ppd_socket);
623 		}
624 		ddi_set_name_addr((dev_info_t *)arg, name);
625 
626 #if defined(PCMCIA_DEBUG)
627 		if (pcmcia_debug)
628 			cmn_err(CE_CONT, "pcmcia: system init done for %s [%s] "
629 			    "nodeid: %x @%s\n",
630 			    ddi_get_name(arg), ddi_get_name_addr(arg),
631 			    DEVI(arg)->devi_nodeid, name);
632 		if (pcmcia_debug > 1)
633 			pcmcia_dump_minors((dev_info_t *)arg);
634 #endif
635 
636 		return (DDI_SUCCESS);
637 
638 	case DDI_CTLOPS_UNINITCHILD:
639 
640 #if defined(PCMCIA_DEBUG)
641 		if (pcmcia_debug) {
642 			cmn_err(CE_CONT, "pcmcia: uninit child: %s(%d) @%p\n",
643 			    ddi_node_name(arg), ddi_get_instance(arg),
644 			    (void *)arg);
645 			if (DEVI(arg)->devi_binding_name != NULL)
646 				cmn_err(CE_CONT, "\tbinding_name=%s\n",
647 				    DEVI(arg)->devi_binding_name);
648 			if (DEVI(arg)->devi_node_name != NULL)
649 				cmn_err(CE_CONT, "\tnode_name=%s\n",
650 				    DEVI(arg)->devi_node_name);
651 		}
652 #endif
653 
654 		ddi_set_name_addr((dev_info_t *)arg, NULL);
655 		ddi_remove_minor_node((dev_info_t *)arg, NULL);
656 		return (DDI_SUCCESS);
657 
658 	case DDI_CTLOPS_SLAVEONLY:
659 		/* PCMCIA devices can't ever be busmaster until CardBus */
660 		ppd = (struct pcmcia_parent_private *)
661 		    ddi_get_parent_data(rdip);
662 		if (ppd != NULL && ppd->ppd_flags & PPD_CB_BUSMASTER)
663 			return (DDI_FAILURE); /* at most */
664 		return (DDI_SUCCESS);
665 
666 	case DDI_CTLOPS_SIDDEV:
667 		/* in general this is true. */
668 		return (DDI_SUCCESS);
669 
670 	case DDI_CTLOPS_NREGS:
671 		ppd = (struct pcmcia_parent_private *)
672 		    ddi_get_parent_data(rdip);
673 		if (ppd != NULL)
674 			*((uint32_t *)result) = (ppd->ppd_nreg);
675 		else
676 			*((uint32_t *)result) = 0;
677 		return (DDI_SUCCESS);
678 
679 	case DDI_CTLOPS_REGSIZE:
680 		ppd = (struct pcmcia_parent_private *)
681 		    ddi_get_parent_data(rdip);
682 		if (ppd != NULL && ppd->ppd_nreg > 0)
683 			*((off_t *)result) =  sizeof (struct pcm_regs);
684 		else
685 			*((off_t *)result) = 0;
686 		return (DDI_SUCCESS);
687 
688 	case DDI_CTLOPS_POWER:
689 		ppd = (struct pcmcia_parent_private *)
690 		    ddi_get_parent_data(rdip);
691 
692 		if (ppd == NULL)
693 			return (DDI_FAILURE);
694 		/*
695 		 * if this is not present, don't bother (claim success)
696 		 * since it is already in the right state.  Don't
697 		 * do any resume either since the card insertion will
698 		 * happen independently.
699 		 */
700 		if (!ppd->ppd_active)
701 			return (DDI_SUCCESS);
702 		for (e = 0; e < pcmcia_num_adapters; e++)
703 			if (pcmcia_adapters[e] ==
704 			    pcmcia_sockets[ppd->ppd_socket]->ls_adapter)
705 				break;
706 		if (e == pcmcia_num_adapters)
707 			return (DDI_FAILURE);
708 		pm = (power_req_t *)arg;
709 #if defined(PCMCIA_DEBUG)
710 		if (pcmcia_debug) {
711 			cmn_err(CE_WARN, "power: %d: %p, %d, %d [%s]\n",
712 			    pm->request_type,
713 			    (void *)pm->req.set_power_req.who,
714 			    pm->req.set_power_req.cmpt,
715 			    pm->req.set_power_req.level,
716 			    ddi_get_name_addr(rdip));
717 		}
718 #endif
719 		e = ppd->ppd_socket;
720 		switch (pm->request_type) {
721 		case PMR_SUSPEND:
722 			if (!(pcmcia_sockets[e]->ls_flags &
723 			    PCS_SUSPENDED)) {
724 				pcmcia_do_suspend(ppd->ppd_socket,
725 				    pcmcia_sockets[e]);
726 			}
727 			ppd->ppd_flags |= PPD_SUSPENDED;
728 			return (DDI_SUCCESS);
729 		case PMR_RESUME:
730 			/* for now, we just succeed since the rest is done */
731 			return (DDI_SUCCESS);
732 		case PMR_SET_POWER:
733 			/*
734 			 * not sure how to handle power control
735 			 * for now, we let the child handle it itself
736 			 */
737 			(void) pcmcia_power(pm->req.set_power_req.who,
738 			    pm->req.set_power_req.cmpt,
739 			    pm->req.set_power_req.level);
740 			break;
741 		default:
742 			break;
743 		}
744 		return (DDI_FAILURE);
745 		/* These CTLOPS will need to be implemented for new form */
746 		/* let CardServices know about this */
747 	case DDI_CTLOPS_DETACH:
748 		return (DDI_SUCCESS);
749 	case DDI_CTLOPS_ATTACH:
750 		return (DDI_SUCCESS);
751 
752 	default:
753 		/* if we don't understand, pass up the tree */
754 		/* most things default to general ops */
755 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
756 	}
757 }
758 
759 struct pcmcia_props {
760 	char *name;
761 	int   len;
762 	int   prop;
763 } pcmcia_internal_props[] = {
764 	{ PCM_DEV_ACTIVE, 0, PCMCIA_PROP_ACTIVE },
765 	{ PCM_DEV_R2TYPE, 0, PCMCIA_PROP_R2TYPE },
766 	{ PCM_DEV_CARDBUS, 0, PCMCIA_PROP_CARDBUS },
767 	{ CS_PROP, sizeof (void *), PCMCIA_PROP_OLDCS },
768 	{ "reg", 0, PCMCIA_PROP_REG },
769 	{ "interrupts", sizeof (int), PCMCIA_PROP_INTR },
770 	{ "pm-hardware-state", 0, PCMCIA_PROP_DEFAULT_PM },
771 };
772 
773 /*
774  * pcmcia_prop_decode(name)
775  *	decode the name and determine if this is a property
776  *	we construct on the fly, one we have on the prop list
777  *	or one that requires calling the CIS code.
778  */
779 static int
pcmcia_prop_decode(char * name)780 pcmcia_prop_decode(char *name)
781 {
782 	int i;
783 	if (strncmp(name, "cistpl_", 7) == 0)
784 		return (PCMCIA_PROP_CIS);
785 
786 	for (i = 0; i < (sizeof (pcmcia_internal_props) /
787 	    sizeof (struct pcmcia_props)); i++) {
788 		if (strcmp(name, pcmcia_internal_props[i].name) == 0)
789 			return (i);
790 	}
791 
792 	return (PCMCIA_PROP_UNKNOWN);
793 }
794 
795 /*
796  * pcmcia_prop_op()
797  *	we don't have properties in PROM per se so look for them
798  *	only in the devinfo node.  Future may allow us to find
799  *	certain CIS tuples via this interface if a user asks for
800  *	a property of the form "cistpl-<tuplename>" but not yet.
801  *
802  *	The addition of 1275 properties adds to the necessity.
803  */
804 int
pcmcia_prop_op(dev_t dev,dev_info_t * dip,dev_info_t * ch_dip,ddi_prop_op_t prop_op,int mod_flags,char * name,caddr_t valuep,int * lengthp)805 pcmcia_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip,
806     ddi_prop_op_t prop_op, int mod_flags,
807     char *name, caddr_t valuep, int *lengthp)
808 {
809 	int len, proplen, which, flags;
810 	caddr_t buff, propptr;
811 	struct pcmcia_parent_private *ppd;
812 
813 	len = *lengthp;
814 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(ch_dip);
815 
816 	switch (which = pcmcia_prop_decode(name)) {
817 	default:
818 		if (ppd == NULL)
819 			return (DDI_PROP_NOT_FOUND);
820 
821 		/* note that proplen may get modified */
822 		proplen = pcmcia_internal_props[which].len;
823 		switch (pcmcia_internal_props[which].prop) {
824 		case PCMCIA_PROP_DEFAULT_PM:
825 			propptr = pcmcia_default_pm_mode;
826 			proplen = strlen(propptr) + 1;
827 			break;
828 		case PCMCIA_PROP_OLDCS:
829 			propptr = (caddr_t)&cs_error_ptr;
830 			break;
831 		case PCMCIA_PROP_REG:
832 			propptr = (caddr_t)ppd->ppd_reg;
833 			proplen = ppd->ppd_nreg * sizeof (struct pcm_regs);
834 			break;
835 		case PCMCIA_PROP_INTR:
836 			propptr = (caddr_t)&ppd->ppd_intr;
837 			break;
838 
839 		/* the next set are boolean values */
840 		case PCMCIA_PROP_ACTIVE:
841 			propptr = NULL;
842 			if (!ppd->ppd_active) {
843 				return (DDI_PROP_NOT_FOUND);
844 			}
845 			break;
846 		case PCMCIA_PROP_R2TYPE:
847 			propptr = NULL;
848 			if (ppd->ppd_flags & PPD_CARD_CARDBUS)
849 				return (DDI_PROP_NOT_FOUND);
850 			break;
851 		case PCMCIA_PROP_CARDBUS:
852 			propptr = NULL;
853 			if ((ppd->ppd_flags & PPD_CARD_CARDBUS) == 0)
854 				return (DDI_PROP_NOT_FOUND);
855 			break;
856 		}
857 
858 		break;
859 
860 	case PCMCIA_PROP_CIS:
861 		/*
862 		 * once we have the lookup code in place
863 		 * it is sufficient to break out of the switch
864 		 * once proplen and propptr are set.
865 		 * The common prop_op code deals with the rest.
866 		 */
867 	case PCMCIA_PROP_UNKNOWN:
868 		return (ddi_bus_prop_op(dev, dip, ch_dip, prop_op,
869 		    mod_flags | DDI_PROP_NOTPROM,
870 		    name, valuep, lengthp));
871 	}
872 
873 	if (prop_op == PROP_LEN) {
874 		/* just the length */
875 		*lengthp = proplen;
876 		return (DDI_PROP_SUCCESS);
877 	}
878 	switch (prop_op) {
879 	case PROP_LEN_AND_VAL_ALLOC:
880 		if (mod_flags & DDI_PROP_CANSLEEP)
881 			flags = KM_SLEEP;
882 		else
883 			flags = KM_NOSLEEP;
884 		buff = kmem_alloc((size_t)proplen, flags);
885 		if (buff == NULL)
886 			return (DDI_PROP_NO_MEMORY);
887 		*(caddr_t *)valuep = (caddr_t)buff;
888 		break;
889 	case PROP_LEN_AND_VAL_BUF:
890 		buff = (caddr_t)valuep;
891 		if (len < proplen)
892 			return (DDI_PROP_BUF_TOO_SMALL);
893 		break;
894 	default:
895 		break;
896 	}
897 
898 	if (proplen > 0)
899 		bcopy(propptr, buff, proplen);
900 	*lengthp = proplen;
901 	return (DDI_PROP_SUCCESS);
902 }
903 
904 
905 struct regspec *
pcmcia_rnum_to_regspec(dev_info_t * dip,int rnumber)906 pcmcia_rnum_to_regspec(dev_info_t *dip, int rnumber)
907 {
908 	struct pcmcia_parent_private *ppd;
909 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
910 	if (ppd->ppd_nreg < rnumber)
911 		return (NULL);
912 	return ((struct regspec *)&ppd->ppd_reg[rnumber]);
913 }
914 
915 struct regspec *
pcmcia_rnum_to_mapped(dev_info_t * dip,int rnumber)916 pcmcia_rnum_to_mapped(dev_info_t *dip, int rnumber)
917 {
918 	struct pcmcia_parent_private *ppd;
919 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
920 	if (ppd->ppd_nreg < rnumber)
921 		return (NULL);
922 	if (ppd->ppd_assigned == NULL)
923 		return (NULL);
924 	if (ppd->ppd_assigned[rnumber].phys_len == 0)
925 		return (NULL);
926 	else
927 		return ((struct regspec *)&ppd->ppd_assigned[rnumber]);
928 }
929 
930 int
pcmcia_find_rnum(dev_info_t * dip,struct regspec * reg)931 pcmcia_find_rnum(dev_info_t *dip, struct regspec *reg)
932 {
933 	struct pcmcia_parent_private *ppd;
934 	struct regspec *regp;
935 	int i;
936 
937 	ppd = (struct pcmcia_parent_private *)ddi_get_parent_data(dip);
938 	if (ppd == NULL)
939 		return (-1);
940 	for (regp = (struct regspec *)ppd->ppd_reg, i = 0;
941 	    i < ppd->ppd_nreg; i++, regp++) {
942 		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
943 			return (i);
944 	}
945 	for (regp = (struct regspec *)ppd->ppd_assigned, i = 0;
946 	    i < ppd->ppd_nreg; i++, regp++) {
947 		if (bcmp(reg, regp, sizeof (struct regspec)) == 0)
948 			return (i);
949 	}
950 
951 	return (-1);
952 }
953 
954 int
pcmcia_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)955 pcmcia_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
956     off_t offset, off_t len, caddr_t *vaddrp)
957 {
958 	struct pcm_regs *regs, *mregs = NULL, tmp_reg;
959 	ddi_map_req_t mr = *mp;
960 	ra_return_t ret;
961 	int check, rnum = -1;
962 	uint32_t base;
963 	uchar_t regbuf[sizeof (pci_regspec_t)];
964 
965 	mp = &mr;		/* a copy of original request */
966 
967 	/* check for register number */
968 	switch (mp->map_type) {
969 	case DDI_MT_REGSPEC:
970 		regs = (struct pcm_regs *)mp->map_obj.rp;
971 		mregs = (struct pcm_regs *)mp->map_obj.rp;
972 		/*
973 		 * when using regspec, must not be relocatable
974 		 * and should be from assigned space.
975 		 */
976 		if (!PC_REG_RELOC(regs->phys_hi))
977 			return (DDI_FAILURE);
978 		rnum = pcmcia_find_rnum(rdip, (struct regspec *)mregs);
979 		break;
980 	case DDI_MT_RNUMBER:
981 		regs = (struct pcm_regs *)
982 		    pcmcia_rnum_to_regspec(rdip, mp->map_obj.rnumber);
983 		mregs = (struct pcm_regs *)
984 		    pcmcia_rnum_to_mapped(rdip, mp->map_obj.rnumber);
985 		rnum = mp->map_obj.rnumber;
986 		if (regs == NULL)
987 			return (DDI_FAILURE);
988 		mp->map_type = DDI_MT_REGSPEC;
989 		mp->map_obj.rp = (struct regspec *)mregs;
990 		break;
991 	default:
992 		return (DDI_ME_INVAL);
993 	}
994 
995 	/* basic sanity checks */
996 	switch (mp->map_op) {
997 	default:
998 		return (DDI_ME_UNIMPLEMENTED);
999 	case DDI_MO_UNMAP:
1000 		if (mregs == NULL)
1001 			return (DDI_FAILURE);
1002 		regs = mregs;
1003 		break;
1004 	case DDI_MO_MAP_LOCKED:
1005 	case DDI_MO_MAP_HANDLE:
1006 		panic("unsupported bus operation");
1007 		/*NOTREACHED*/
1008 	}
1009 
1010 	/*
1011 	 * we need a private copy for manipulation and
1012 	 * calculation of the correct ranges
1013 	 */
1014 	tmp_reg = *regs;
1015 	mp->map_obj.rp = (struct regspec *)(regs = &tmp_reg);
1016 	base = regs->phys_lo;
1017 	if (base == 0 && offset != 0) {
1018 		/*
1019 		 * for now this is an error.  What does it really mean
1020 		 * to ask for an offset from an address that hasn't
1021 		 * been allocated yet.
1022 		 */
1023 		return (DDI_ME_INVAL);
1024 	}
1025 	regs->phys_lo += (uint32_t)offset;
1026 	if (len != 0) {
1027 		if (len > regs->phys_len) {
1028 			return (DDI_ME_INVAL);
1029 		}
1030 		regs->phys_len = len;
1031 	}
1032 
1033 	/*
1034 	 * basic sanity is checked so now make sure
1035 	 * we can actually allocate something for this
1036 	 * request and then convert to a "standard"
1037 	 * regspec for the next layer up (pci/isa/rootnex/etc.)
1038 	 */
1039 
1040 	switch (PC_GET_REG_TYPE(regs->phys_hi)) {
1041 	case PC_REG_SPACE_IO:
1042 		check = PCA_RES_NEED_IO;
1043 		break;
1044 	case PC_REG_SPACE_MEMORY:
1045 		check = PCA_RES_NEED_MEM;
1046 		break;
1047 	default:
1048 		/* not a valid register type */
1049 		return (DDI_FAILURE);
1050 	}
1051 
1052 	mr.map_type = DDI_MT_REGSPEC;
1053 	ret.ra_addr_hi = 0;
1054 	ret.ra_addr_lo = regs->phys_lo;
1055 	ret.ra_len = regs->phys_len;
1056 	mr.map_obj.rp = pcmcia_cons_regspec(dip,
1057 	    (check == PCA_RES_NEED_IO) ?
1058 	    PCMCIA_MAP_IO : PCMCIA_MAP_MEM,
1059 	    regbuf, &ret);
1060 	switch (mp->map_op) {
1061 	case DDI_MO_UNMAP:
1062 		pcmcia_set_assigned(rdip, rnum, NULL);
1063 		break;
1064 	default:
1065 		break;
1066 	}
1067 	return (ddi_map(dip, &mr, (off_t)0, (off_t)0, vaddrp));
1068 }
1069 
1070 /*
1071  * pcmcia_cons_regspec()
1072  * based on parent's bus type, construct a regspec that is usable
1073  * by that parent to map the resource into the system.
1074  */
1075 #define	PTYPE_PCI	1
1076 #define	PTYPE_ISA	0
1077 struct regspec *
pcmcia_cons_regspec(dev_info_t * dip,int type,uchar_t * buff,ra_return_t * ret)1078 pcmcia_cons_regspec(dev_info_t *dip, int type, uchar_t *buff, ra_return_t *ret)
1079 {
1080 	int ptype = -1, len, bus;
1081 	char device_type[MODMAXNAMELEN + 1];
1082 	dev_info_t *pdip;
1083 	struct regspec *defreg;
1084 	pci_regspec_t *pcireg;
1085 
1086 	pdip = ddi_get_parent(dip);
1087 	if (pdip != ddi_root_node()) {
1088 		/* we're not a child of root so find out what */
1089 		len = sizeof (device_type);
1090 		if (ddi_prop_op(DDI_DEV_T_ANY, pdip, PROP_LEN_AND_VAL_BUF, 0,
1091 		    "device_type", (caddr_t)device_type, &len) ==
1092 		    DDI_PROP_SUCCESS) {
1093 			/* check things out */
1094 			if (strcmp(device_type, "pci") == 0)
1095 				ptype = PTYPE_PCI;
1096 			else if (strcmp(device_type, "isa") == 0)
1097 				ptype = PTYPE_ISA;
1098 		}
1099 	}
1100 	switch (ptype) {
1101 	case PTYPE_PCI:
1102 		/* XXX need to look at carefully */
1103 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1104 		    "reg", (caddr_t)&pcireg, &len) == DDI_SUCCESS) {
1105 			bus = PCI_REG_BUS_G(pcireg->pci_phys_hi);
1106 			kmem_free(pcireg, len);
1107 		} else {
1108 			bus = 0;
1109 		}
1110 		pcireg = (pci_regspec_t *)buff;
1111 		pcireg->pci_phys_hi = (type == PCMCIA_MAP_IO ? PCI_ADDR_IO :
1112 		    PCI_ADDR_MEM32) | PCI_RELOCAT_B | (bus << 16);
1113 		pcireg->pci_phys_mid = ret->ra_addr_hi;
1114 		pcireg->pci_phys_low = ret->ra_addr_lo;
1115 		if (type == PCMCIA_MAP_IO)
1116 			pcireg->pci_phys_low &= 0xFFFF;
1117 		pcireg->pci_size_hi = 0;
1118 		pcireg->pci_size_low = ret->ra_len;
1119 		break;
1120 	default:
1121 		/* default case is to use struct regspec */
1122 		defreg = (struct regspec *)buff;
1123 		defreg->regspec_bustype = type == PCMCIA_MAP_IO ? 1 : 0;
1124 		defreg->regspec_addr = ret->ra_addr_lo;
1125 		defreg->regspec_size = ret->ra_len;
1126 		break;
1127 	}
1128 	return ((struct regspec *)buff);
1129 }
1130 
1131 /*
1132  * pcmcia_init_adapter
1133  *	Initialize the per-adapter structures and check to see if
1134  *	there are possible other instances coming.
1135  */
1136 void
pcmcia_init_adapter(anp_t * adapter,dev_info_t * dip)1137 pcmcia_init_adapter(anp_t *adapter, dev_info_t *dip)
1138 {
1139 	int i, n;
1140 	pcmcia_if_t *ls_if;
1141 
1142 	i = pcmcia_num_adapters++;
1143 	pcmcia_adapters[i] = kmem_zalloc(sizeof (struct pcmcia_adapter),
1144 	    KM_SLEEP);
1145 	pcmcia_adapters[i]->pca_dip = dip;
1146 	/* should this be pca_winshift??? */
1147 	pcmcia_adapters[i]->pca_module = ddi_driver_major(dip);
1148 	pcmcia_adapters[i]->pca_unit = ddi_get_instance(dip);
1149 	pcmcia_adapters[i]->pca_iblock = adapter->an_iblock;
1150 	pcmcia_adapters[i]->pca_idev = adapter->an_idev;
1151 	pcmcia_adapters[i]->pca_if = ls_if = adapter->an_if;
1152 	pcmcia_adapters[i]->pca_number = i;
1153 	(void) strcpy(pcmcia_adapters[i]->pca_name, ddi_get_name(dip));
1154 	pcmcia_adapters[i]->
1155 	    pca_name[sizeof (pcmcia_adapters[i]->pca_name) - 1] = '\0';
1156 
1157 	if (ls_if != NULL) {
1158 		inquire_adapter_t conf;
1159 		int sock, win;
1160 
1161 		if (ls_if->pcif_inquire_adapter != NULL)
1162 			GET_CONFIG(ls_if, dip, &conf);
1163 
1164 		/* resources - assume worst case and fix from there */
1165 		pcmcia_adapters[i]->pca_flags = PCA_RES_NEED_IRQ |
1166 		    PCA_RES_NEED_IO | PCA_RES_NEED_MEM;
1167 		/* indicate first socket not initialized */
1168 		pcmcia_adapters[i]->pca_first_socket = -1;
1169 
1170 		if (conf.ResourceFlags & RES_OWN_IRQ)
1171 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IRQ;
1172 		if (conf.ResourceFlags & RES_OWN_IO)
1173 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_IO;
1174 		if (conf.ResourceFlags & RES_OWN_MEM)
1175 			pcmcia_adapters[i]->pca_flags &= ~PCA_RES_NEED_MEM;
1176 		if (conf.ResourceFlags & RES_IRQ_SHAREABLE)
1177 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SHAREABLE;
1178 		if (conf.ResourceFlags & RES_IRQ_NEXUS)
1179 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_SMI_SHARE;
1180 
1181 		/* need to know interrupt limitations */
1182 		if (conf.ActiveLow) {
1183 			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveLow;
1184 			pcmcia_adapters[i]->pca_flags |= PCA_IRQ_ISA;
1185 		} else
1186 			pcmcia_adapters[i]->pca_avail_intr = conf.ActiveHigh;
1187 
1188 		/* power entries for adapter */
1189 		pcmcia_adapters[i]->pca_power = conf.power_entry;
1190 		pcmcia_adapters[i]->pca_numpower = conf.NumPower;
1191 
1192 		for (n = 0; n < conf.NumPower; n++)
1193 			pcmcia_merge_power(&conf.power_entry[n]);
1194 
1195 		/* now setup the per socket info */
1196 		for (sock = 0; sock < conf.NumSockets;
1197 		    sock++) {
1198 			dev_info_t *sockdrv = NULL;
1199 			sockdrv = pcmcia_number_socket(dip, sock);
1200 			if (sockdrv == NULL)
1201 				n = sock + pcmcia_num_sockets;
1202 			else {
1203 				n = ddi_get_instance(sockdrv);
1204 			}
1205 			/* make sure we know first socket on adapter */
1206 			if (pcmcia_adapters[i]->pca_first_socket == -1)
1207 				pcmcia_adapters[i]->pca_first_socket = n;
1208 
1209 			/*
1210 			 * the number of sockets is weird.
1211 			 * we might have only two sockets but
1212 			 * due to persistence of instances we
1213 			 * will need to call them something other
1214 			 * than 0 and 1.  So, we use the largest
1215 			 * instance number as the number and
1216 			 * have some that just don't get used.
1217 			 */
1218 			if (n >= pcmcia_num_sockets)
1219 				pcmcia_num_sockets = n + 1;
1220 #if defined(PCMCIA_DEBUG)
1221 			if (pcmcia_debug) {
1222 				cmn_err(CE_CONT,
1223 				    "pcmcia_init: new socket added %d "
1224 				    "(%d)\n",
1225 				    n, pcmcia_num_sockets);
1226 			}
1227 #endif
1228 
1229 			pcmcia_sockets[n] =
1230 			    kmem_zalloc(sizeof (pcmcia_logical_socket_t),
1231 			    KM_SLEEP);
1232 			pcmcia_sockets[n]->ls_socket = sock;
1233 			pcmcia_sockets[n]->ls_if = ls_if;
1234 			pcmcia_sockets[n]->ls_adapter =
1235 			    pcmcia_adapters[i];
1236 			pcmcia_sockets[n]->ls_cs_events = 0L;
1237 			pcmcia_sockets[n]->ls_sockdrv = sockdrv;
1238 			/* Prototype of intrspec */
1239 			pcmcia_sockets[n]->ls_intr_pri = adapter->an_ipl;
1240 #if defined(PCMCIA_DEBUG)
1241 			if (pcmcia_debug)
1242 				cmn_err(CE_CONT,
1243 				    "phys sock %d, log sock %d\n",
1244 				    sock, n);
1245 #endif
1246 			mutex_init(&pcmcia_sockets[n]->ls_ilock, NULL,
1247 			    MUTEX_DRIVER, *adapter->an_iblock);
1248 		}
1249 
1250 		pcmcia_adapters[i]->pca_numsockets = conf.NumSockets;
1251 		/* now setup the per window information */
1252 		for (win = 0; win < conf.NumWindows; win++) {
1253 			n = win + pcmcia_num_windows;
1254 			pcmcia_windows[n] =
1255 			    kmem_zalloc(sizeof (pcmcia_logical_window_t),
1256 			    KM_SLEEP);
1257 			pcmcia_windows[n]->lw_window = win;
1258 			pcmcia_windows[n]->lw_if = ls_if;
1259 			pcmcia_windows[n]->lw_adapter =
1260 			    pcmcia_adapters[i];
1261 		}
1262 		pcmcia_num_windows += conf.NumWindows;
1263 		SET_CALLBACK(ls_if, dip,
1264 		    pcm_adapter_callback, i);
1265 
1266 		/* now tell CS about each socket */
1267 		for (sock = 0; sock < pcmcia_num_sockets; sock++) {
1268 #if defined(PCMCIA_DEBUG)
1269 			if (pcmcia_debug) {
1270 				cmn_err(CE_CONT,
1271 				    "pcmcia_init: notify CS socket %d "
1272 				    "sockp=%p\n",
1273 				    sock, (void *)pcmcia_sockets[sock]);
1274 			}
1275 #endif
1276 			if (pcmcia_sockets[sock] == NULL ||
1277 			    (pcmcia_sockets[sock]->ls_flags &
1278 			    PCS_SOCKET_ADDED)) {
1279 				/* skip the ones that are done already */
1280 				continue;
1281 			}
1282 			pcmcia_sockets[sock]->ls_flags |= PCS_SOCKET_ADDED;
1283 			if (cs_event(PCE_ADD_SOCKET, sock, 0) !=
1284 			    CS_SUCCESS) {
1285 				/* flag socket as broken */
1286 				pcmcia_sockets[sock]->ls_flags = 0;
1287 			} else {
1288 				pcm_event_manager(PCE_ADD_SOCKET,
1289 				    sock, NULL);
1290 			}
1291 		}
1292 
1293 	}
1294 #if defined(PCMCIA_DEBUG)
1295 	if (pcmcia_debug) {
1296 		cmn_err(CE_CONT, "logical sockets:\n");
1297 		for (i = 0; i < pcmcia_num_sockets; i++) {
1298 			if (pcmcia_sockets[i] == NULL)
1299 				continue;
1300 			cmn_err(CE_CONT,
1301 			    "\t%d: phys sock=%d, if=%p, adapt=%p\n",
1302 			    i, pcmcia_sockets[i]->ls_socket,
1303 			    (void *)pcmcia_sockets[i]->ls_if,
1304 			    (void *)pcmcia_sockets[i]->ls_adapter);
1305 		}
1306 		cmn_err(CE_CONT, "logical windows:\n");
1307 		for (i = 0; i < pcmcia_num_windows; i++) {
1308 			cmn_err(CE_CONT,
1309 			    "\t%d: phys_window=%d, if=%p, adapt=%p\n",
1310 			    i, pcmcia_windows[i]->lw_window,
1311 			    (void *)pcmcia_windows[i]->lw_if,
1312 			    (void *)pcmcia_windows[i]->lw_adapter);
1313 		}
1314 		cmn_err(CE_CONT, "\tpcmcia_num_power=%d\n", pcmcia_num_power);
1315 		for (n = 0; n < pcmcia_num_power; n++)
1316 			cmn_err(CE_CONT,
1317 			    "\t\tPowerLevel: %d\tValidSignals: %x\n",
1318 			    pcmcia_power_table[n].PowerLevel,
1319 			    pcmcia_power_table[n].ValidSignals);
1320 	}
1321 #endif
1322 }
1323 
1324 /*
1325  * pcmcia_find_cards()
1326  *	check the adapter to see if there are cards present at
1327  *	driver attach time.  If there are, generate an artificial
1328  *	card insertion event to get CS running and the PC Card ultimately
1329  *	identified.
1330  */
1331 void
pcmcia_find_cards(anp_t * adapt)1332 pcmcia_find_cards(anp_t *adapt)
1333 {
1334 	int i;
1335 	get_ss_status_t status;
1336 	for (i = 0; i < pcmcia_num_sockets; i++) {
1337 		if (pcmcia_sockets[i] &&
1338 		    pcmcia_sockets[i]->ls_if == adapt->an_if) {
1339 			/* check the status */
1340 			status.socket = i;
1341 			if (SSGetStatus(&status) == SUCCESS &&
1342 			    status.IFType != IF_CARDBUS &&
1343 			    status.CardState & SBM_CD &&
1344 			    pcmcia_sockets[i]->ls_dip[0] == NULL) {
1345 				(void) cs_event(PCE_CARD_INSERT, i, 0);
1346 				delay(1);
1347 			}
1348 		}
1349 	}
1350 }
1351 
1352 /*
1353  * pcmcia_number_socket(dip, adapt)
1354  *	we determine socket number by creating a driver for each
1355  *	socket on the adapter and then forcing it to attach.  This
1356  *	results in an instance being assigned which becomes the
1357  *	logical socket number.	If it fails, then we are the first
1358  *	set of sockets and renumbering occurs later.  We do this
1359  *	one socket at a time and return the dev_info_t so the
1360  *	instance number can be used.
1361  */
1362 dev_info_t *
pcmcia_number_socket(dev_info_t * dip,int localsocket)1363 pcmcia_number_socket(dev_info_t *dip, int localsocket)
1364 {
1365 	dev_info_t *child = NULL;
1366 	struct pcmcia_parent_private *ppd;
1367 
1368 	if (ndi_devi_alloc(dip, "pcs", (pnode_t)DEVI_SID_NODEID,
1369 	    &child) == NDI_SUCCESS) {
1370 		ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private),
1371 		    KM_SLEEP);
1372 		ppd->ppd_reg = kmem_zalloc(sizeof (struct pcm_regs), KM_SLEEP);
1373 		ppd->ppd_nreg = 1;
1374 		ppd->ppd_reg[0].phys_hi = localsocket;
1375 		ddi_set_parent_data(child, (caddr_t)ppd);
1376 		if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
1377 			kmem_free(ppd->ppd_reg, sizeof (struct pcm_regs));
1378 			kmem_free(ppd, sizeof (struct pcmcia_parent_private));
1379 			(void) ndi_devi_free(child);
1380 			child = NULL;
1381 		}
1382 	}
1383 	return (child);
1384 }
1385 
1386 /*
1387  * pcm_phys_to_log_socket()
1388  *	from an adapter and socket number return the logical socket
1389  */
1390 int
pcm_phys_to_log_socket(struct pcmcia_adapter * adapt,int socket)1391 pcm_phys_to_log_socket(struct pcmcia_adapter *adapt, int socket)
1392 {
1393 	register pcmcia_logical_socket_t *sockp;
1394 	int i;
1395 
1396 	for (i = 0, sockp = pcmcia_sockets[0];
1397 	    i < pcmcia_num_sockets; i++, sockp = pcmcia_sockets[i]) {
1398 		if (sockp == NULL)
1399 			continue;
1400 		if (sockp->ls_socket == socket && sockp->ls_adapter == adapt)
1401 			break;
1402 	}
1403 	if (i >= pcmcia_num_sockets) {
1404 #if defined(PCMCIA_DEBUG)
1405 		if (pcmcia_debug)
1406 			cmn_err(CE_CONT,
1407 			    "\tbad socket/adapter: %x/%p != %x/%x\n",
1408 			    socket, (void *)adapt, pcmcia_num_sockets,
1409 			    pcmcia_num_adapters);
1410 #endif
1411 		return (-1);
1412 	}
1413 
1414 	return (i);		/* want logical socket */
1415 }
1416 
1417 /*
1418  * pcm_adapter_callback()
1419  *	this function is called back by the adapter driver at interrupt time.
1420  *	It is here that events should get generated for the event manager if it
1421  *	is present.  It would also be the time where a device information
1422  *	tree could be constructed for a card that was added in if we
1423  *	choose to create them dynamically.
1424  */
1425 
1426 #if defined(PCMCIA_DEBUG)
1427 char *cblist[] = {
1428 	"removal",
1429 	"insert",
1430 	"ready",
1431 	"battery-warn",
1432 	"battery-dead",
1433 	"status-change",
1434 	"write-protect", "reset", "unlock", "client-info", "eject-complete",
1435 	"eject-request", "erase-complete", "exclusive-complete",
1436 	"exclusive-request", "insert-complete", "insert-request",
1437 	"reset-complete", "reset-request", "timer-expired",
1438 	"resume", "suspend"
1439 };
1440 #endif
1441 
1442 /*ARGSUSED*/
1443 static int
pcm_adapter_callback(dev_info_t * dip,int adapter,int event,int socket)1444 pcm_adapter_callback(dev_info_t *dip, int adapter, int event, int socket)
1445 {
1446 	pcmcia_logical_socket_t *sockp;
1447 
1448 #if defined(PCMCIA_DEBUG)
1449 	if (pcmcia_debug) {
1450 		cmn_err(CE_CONT, "pcm_adapter_callback: %p %x %x %x: ",
1451 		    (void *)dip, adapter, event, socket);
1452 		cmn_err(CE_CONT, "[%s]\n", cblist[event]);
1453 	}
1454 #endif
1455 
1456 	if (adapter >= pcmcia_num_adapters || adapter < 0) {
1457 #if defined(PCMCIA_DEBUG)
1458 		if (pcmcia_debug)
1459 			cmn_err(CE_CONT, "\tbad adapter number: %d : %d\n",
1460 			    adapter, pcmcia_num_adapters);
1461 #endif
1462 		return (1);
1463 	}
1464 
1465 	/* get the logical socket since that is what CS knows */
1466 	socket = pcm_phys_to_log_socket(pcmcia_adapters[adapter], socket);
1467 	if (socket == -1) {
1468 		cmn_err(CE_WARN, "pcmcia callback - bad logical socket\n");
1469 		return (0);
1470 	}
1471 	sockp = pcmcia_sockets[socket];
1472 	switch (event) {
1473 	case -1:		/* special case of adapter going away */
1474 	case PCE_CARD_INSERT:
1475 		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
1476 		    PCE_E2M(PCE_CARD_REMOVAL);
1477 		break;
1478 	case PCE_CARD_REMOVAL:
1479 				/* disable interrupts at this point */
1480 		sockp->ls_cs_events |= PCE_E2M(PCE_CARD_INSERT) |
1481 		    PCE_E2M(PCE_CARD_REMOVAL);
1482 		/* remove children that never attached */
1483 
1484 		break;
1485 	case PCE_PM_RESUME:
1486 		pcmcia_do_resume(socket, sockp);
1487 		/* event = PCE_CARD_INSERT; */
1488 		break;
1489 	case PCE_PM_SUSPEND:
1490 		pcmcia_do_suspend(socket, sockp);
1491 		/* event = PCE_CARD_REMOVAL; */
1492 		break;
1493 	default:
1494 		/* nothing to do */
1495 		break;
1496 	}
1497 
1498 #if defined(PCMCIA_DEBUG)
1499 	if (pcmcia_debug) {
1500 		cmn_err(CE_CONT,
1501 		    "\tevent %d, event mask=%x, match=%x (log socket=%d)\n",
1502 		    event,
1503 		    (int)sockp->ls_cs_events,
1504 		    (int)(sockp->ls_cs_events & PCE_E2M(event)), socket);
1505 	}
1506 #endif
1507 
1508 	if (pcmcia_cs_event && sockp->ls_cs_events & (1 << event)) {
1509 #if defined(PCMCIA_DEBUG)
1510 		if (pcmcia_debug)
1511 			cmn_err(CE_CONT, "\tcalling CS event handler (%p) "
1512 			    "with event=%d\n",
1513 			    (void *)pcmcia_cs_event, event);
1514 #endif
1515 		CS_EVENT(event, socket, 0);
1516 	}
1517 
1518 	/* let the event manager(s) know about the event */
1519 	pcm_event_manager(event, socket, NULL);
1520 
1521 	return (0);
1522 }
1523 
1524 /*
1525  * pcm_event_manager()
1526  *	checks for registered management driver callback handlers
1527  *	if there are any, call them if the event warrants it
1528  */
1529 void
pcm_event_manager(int event,int socket,void * arg)1530 pcm_event_manager(int event, int socket, void *arg)
1531 {
1532 	struct pcmcia_mif *mif;
1533 
1534 	for (mif = pcmcia_mif_handlers; mif != NULL; mif = mif->mif_next) {
1535 #if defined(PCMCIA_DEBUG)
1536 		if (pcmcia_debug)
1537 			cmn_err(CE_CONT,
1538 			    "pcm_event_manager: event=%d, mif_events=%x"
1539 			    " (tst:%d)\n",
1540 			    event, (int)*(uint32_t *)mif->mif_events,
1541 			    PR_GET(mif->mif_events, event));
1542 #endif
1543 		if (PR_GET(mif->mif_events, event)) {
1544 			mif->mif_function(mif->mif_id, event, socket, arg);
1545 		}
1546 	}
1547 
1548 }
1549 
1550 /*
1551  * pcm_search_devinfo(dev_info_t *, pcm_device_info *, int)
1552  * search for an immediate child node to the nexus and not siblings of nexus
1553  * and not grandchildren.  We follow the same sequence that name binding
1554  * follows so we match same class of device (modem == modem) and don't
1555  * have to depend on features that might not exist.
1556  */
1557 dev_info_t *
pcm_search_devinfo(dev_info_t * self,struct pcm_device_info * info,int socket)1558 pcm_search_devinfo(dev_info_t *self, struct pcm_device_info *info, int socket)
1559 {
1560 	char bf[256];
1561 	struct pcmcia_parent_private *ppd;
1562 	dev_info_t *dip;
1563 	int circ;
1564 
1565 #if defined(PCMCIA_DEBUG)
1566 	if (pcmcia_debug)
1567 		cmn_err(CE_CONT,
1568 		    "pcm_search_devinfo: socket=%x [%s|%s|%s] pd_flags=%x\n",
1569 		    socket, info->pd_bind_name, info->pd_generic_name,
1570 		    info->pd_vers1_name, info->pd_flags);
1571 #endif
1572 
1573 	ndi_devi_enter(self, &circ);
1574 	/* do searches in compatible property order */
1575 	for (dip = (dev_info_t *)DEVI(self)->devi_child;
1576 	    dip != NULL;
1577 	    dip = (dev_info_t *)DEVI(dip)->devi_sibling) {
1578 		int ppd_socket;
1579 		ppd = (struct pcmcia_parent_private *)
1580 		    ddi_get_parent_data(dip);
1581 		if (ppd == NULL) {
1582 #if defined(PCMCIA_DEBUG)
1583 			cmn_err(CE_WARN, "No parent private data\n");
1584 #endif
1585 			continue;
1586 		}
1587 		ppd_socket = CS_MAKE_SOCKET_NUMBER(ppd->ppd_socket,
1588 		    ppd->ppd_function);
1589 #if defined(PCMCIA_DEBUG)
1590 		if (pcmcia_debug) {
1591 			cmn_err(CE_CONT, "\tbind=[%s], node=[%s]\n",
1592 			    DEVI(dip)->devi_binding_name,
1593 			    DEVI(dip)->devi_node_name);
1594 		}
1595 #endif
1596 		if (info->pd_flags & PCM_NAME_VERS1) {
1597 			(void) strcpy(bf, info->pd_vers1_name);
1598 			pcmcia_fix_string(bf);
1599 			if (DEVI(dip)->devi_binding_name &&
1600 			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
1601 			    socket == ppd_socket)
1602 				break;
1603 		}
1604 		if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) ==
1605 		    (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) {
1606 			(void) sprintf(bf, "%s,%x", info->pd_bind_name,
1607 			    info->pd_function);
1608 			if (strcmp(bf, DEVI(dip)->devi_binding_name) == 0 &&
1609 			    socket == ppd->ppd_socket)
1610 				break;
1611 		}
1612 		if (info->pd_flags & PCM_NAME_1275) {
1613 			if (DEVI(dip)->devi_binding_name &&
1614 			    strcmp(DEVI(dip)->devi_binding_name,
1615 			    info->pd_bind_name) == 0 &&
1616 			    socket == ppd_socket)
1617 				break;
1618 		}
1619 		if (info->pd_flags & PCM_NAME_GENERIC) {
1620 			(void) sprintf(bf, "%s,%s", PCMDEV_NAMEPREF,
1621 			    info->pd_generic_name);
1622 			if (DEVI(dip)->devi_binding_name &&
1623 			    strcmp(DEVI(dip)->devi_binding_name, bf) == 0 &&
1624 			    socket == ppd_socket)
1625 				break;
1626 		}
1627 		if (info->pd_flags & PCM_NAME_GENERIC) {
1628 			if (DEVI(dip)->devi_binding_name &&
1629 			    strcmp(DEVI(dip)->devi_binding_name,
1630 			    info->pd_generic_name) == 0 &&
1631 			    socket == ppd_socket)
1632 				break;
1633 		}
1634 		if (info->pd_flags & PCM_NO_CONFIG) {
1635 			if (DEVI(dip)->devi_binding_name &&
1636 			    strcmp(DEVI(dip)->devi_binding_name,
1637 			    "pccard,memory") == 0 &&
1638 			    socket == ppd_socket)
1639 				break;
1640 		}
1641 	}
1642 	ndi_devi_exit(self, circ);
1643 	return (dip);
1644 }
1645 
1646 /*
1647  * pcm_find_devinfo()
1648  *	this is a wrapper around DDI calls to "find" any
1649  *	devinfo node and then from there find the one associated
1650  *	with the socket
1651  */
1652 dev_info_t *
pcm_find_devinfo(dev_info_t * pdip,struct pcm_device_info * info,int socket)1653 pcm_find_devinfo(dev_info_t *pdip, struct pcm_device_info *info, int socket)
1654 {
1655 	dev_info_t *dip;
1656 
1657 	dip = pcm_search_devinfo(pdip, info, socket);
1658 	if (dip == NULL)
1659 		return (NULL);
1660 	/*
1661 	 * we have at least a base level dip
1662 	 * see if there is one (this or a sibling)
1663 	 * that has the correct socket number
1664 	 * if there is, return that one else
1665 	 * NULL so a new one is created
1666 	 */
1667 #if defined(PCMCIA_DEBUG)
1668 	if (pcmcia_debug)
1669 		cmn_err(CE_CONT, "find: initial dip = %p, socket=%d, name=%s "
1670 		    "(instance=%d, socket=%d, name=%s)\n",
1671 		    (void *)dip, socket, info->pd_bind_name,
1672 		    ddi_get_instance(dip),
1673 		    ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1674 		    PCM_DEV_SOCKET, -1),
1675 		    ddi_get_name(dip));
1676 #endif
1677 
1678 #if defined(PCMCIA_DEBUG)
1679 	if (pcmcia_debug && dip != NULL)
1680 		cmn_err(CE_CONT, "\treturning non-NULL dip (%s)\n",
1681 		    ddi_get_name(dip));
1682 #endif
1683 	return (dip);
1684 }
1685 
1686 /*
1687  * pcm_find_parent_dip(socket)
1688  *	find the correct parent dip for this logical socket
1689  */
1690 dev_info_t *
pcm_find_parent_dip(int socket)1691 pcm_find_parent_dip(int socket)
1692 {
1693 	if ((socket < 0 || socket >= pcmcia_num_sockets) ||
1694 	    pcmcia_sockets[socket] == NULL)
1695 		return (NULL);
1696 	return (pcmcia_sockets[socket]->ls_adapter->pca_dip);
1697 }
1698 
1699 /*
1700  * pcmcia_set_em_handler()
1701  *	This is called by the management and event driver to tell
1702  *	the nexus what to call.	 Multiple drivers are allowed
1703  *	but normally only one will exist.
1704  */
1705 int
pcmcia_set_em_handler(int (* handler)(),caddr_t events,int elen,uint32_t id,void ** cs,void ** ss)1706 pcmcia_set_em_handler(int (*handler)(), caddr_t events, int elen,
1707     uint32_t id, void **cs, void **ss)
1708 {
1709 	struct pcmcia_mif *mif, *tmp;
1710 
1711 	if (handler == NULL) {
1712 		/* NULL means remove the handler based on the ID */
1713 		if (pcmcia_mif_handlers == NULL)
1714 			return (0);
1715 		mutex_enter(&pcmcia_global_lock);
1716 		if (pcmcia_mif_handlers->mif_id == id) {
1717 			mif = pcmcia_mif_handlers;
1718 			pcmcia_mif_handlers = mif->mif_next;
1719 			kmem_free(mif, sizeof (struct pcmcia_mif));
1720 		} else {
1721 			for (mif = pcmcia_mif_handlers;
1722 			    mif->mif_next != NULL &&
1723 			    mif->mif_next->mif_id != id;
1724 			    mif = mif->mif_next)
1725 				;
1726 			if (mif->mif_next != NULL &&
1727 			    mif->mif_next->mif_id == id) {
1728 				tmp = mif->mif_next;
1729 				mif->mif_next = tmp->mif_next;
1730 				kmem_free(tmp, sizeof (struct pcmcia_mif));
1731 			}
1732 		}
1733 		mutex_exit(&pcmcia_global_lock);
1734 	} else {
1735 
1736 		if (pcmcia_num_adapters == 0) {
1737 			return (ENXIO);
1738 		}
1739 		if (elen > EM_EVENTSIZE)
1740 			return (EINVAL);
1741 
1742 		mif = (struct pcmcia_mif *)
1743 		    kmem_zalloc(sizeof (struct pcmcia_mif), KM_NOSLEEP);
1744 		if (mif == NULL)
1745 			return (ENOSPC);
1746 
1747 		mif->mif_function = (void (*)())(uintptr_t)handler;
1748 		bcopy(events, mif->mif_events, elen);
1749 		mif->mif_id = id;
1750 		mutex_enter(&pcmcia_global_lock);
1751 		mif->mif_next = pcmcia_mif_handlers;
1752 		pcmcia_mif_handlers = mif;
1753 		if (cs != NULL)
1754 			*cs = (void *)pcmcia_card_services;
1755 		if (ss != NULL) {
1756 			*ss = (void *)SocketServices;
1757 		}
1758 
1759 		mutex_exit(&pcmcia_global_lock);
1760 	}
1761 	return (0);
1762 }
1763 
1764 /*
1765  * pcm_fix_bits(uchar_t *data, int num, int dir)
1766  *	shift socket bits left(0) or right(0)
1767  *	This is used when mapping logical and physical
1768  */
1769 void
pcm_fix_bits(socket_enum_t src,socket_enum_t dst,int num,int dir)1770 pcm_fix_bits(socket_enum_t src, socket_enum_t dst, int num, int dir)
1771 {
1772 	int i;
1773 
1774 	PR_ZERO(dst);
1775 
1776 	if (dir == 0) {
1777 				/* LEFT */
1778 		for (i = 0; i <= PCMCIA_MAX_SOCKETS - num; i++) {
1779 			if (PR_GET(src, i))
1780 				PR_SET(dst, i + num);
1781 		}
1782 	} else {
1783 				/* RIGHT */
1784 		for (i = num; i < PCMCIA_MAX_SOCKETS; i++) {
1785 			if (PR_GET(src, i))
1786 				PR_SET(dst, i - num);
1787 		}
1788 	}
1789 }
1790 
1791 uint32_t
genmask(int len)1792 genmask(int len)
1793 {
1794 	uint32_t mask;
1795 	for (mask = 0; len > 0; len--) {
1796 		mask |= 1 << (len - 1);
1797 	}
1798 	return (mask);
1799 }
1800 
1801 int
genp2(int val)1802 genp2(int val)
1803 {
1804 	int i;
1805 	if (val == 0)
1806 		return (0);
1807 	for (i = 0; i < 32; i++)
1808 		if (val > (1 << i))
1809 			return (i);
1810 	return (0);
1811 }
1812 
1813 #if defined(PCMCIA_DEBUG)
1814 char *ssfuncs[128] = {
1815 	"GetAdapter", "GetPage", "GetSocket", "GetStatus", "GetWindow",
1816 	"InquireAdapter", "InquireSocket", "InquireWindow", "ResetSocket",
1817 	"SetPage", "SetAdapter", "SetSocket", "SetWindow", "SetIRQHandler",
1818 	"ClearIRQHandler",
1819 	/* 15 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1820 	/* 25 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1821 	/* 35 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1822 	/* 45 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1823 	/* 55 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1824 	/* 65 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1825 	/* 75 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1826 	/* 85 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1827 	/* 95 */ NULL, NULL, NULL,
1828 	"CSIsActiveDip",
1829 	"CSInitDev", "CSRegister", "CSCISInit", "CSUnregister",
1830 	"CISGetAddress", "CISSetAddress", "CSCardRemoved", "CSGetCookiesAndDip"
1831 };
1832 #endif
1833 
1834 /*
1835  * SocketServices
1836  *	general entrypoint for Card Services to find
1837  *	Socket Services.  Finding the entry requires
1838  *	a _depends_on[] relationship.
1839  *
1840  *	In some cases, the work is done locally but usually
1841  *	the parameters are adjusted and the adapter driver
1842  *	code asked to do the work.
1843  */
1844 int
SocketServices(int function,...)1845 SocketServices(int function, ...)
1846 {
1847 	va_list arglist;
1848 	uint32_t args[16];
1849 	csregister_t *reg;
1850 	sservice_t *serv;
1851 	dev_info_t *dip;
1852 	int socket, func;
1853 	int error = SUCCESS;
1854 	pcmcia_logical_socket_t *sockp;
1855 
1856 	va_start(arglist, function);
1857 
1858 #if defined(PCMCIA_DEBUG)
1859 	if (pcmcia_debug > 1)
1860 		cmn_err(CE_CONT, "SocketServices called for function %d [%s]\n",
1861 		    function,
1862 		    ((function < 128) && ssfuncs[function] != NULL) ?
1863 		    ssfuncs[function] : "UNKNOWN");
1864 #endif
1865 	switch (function) {
1866 	case CSRegister:
1867 	case CISGetAddress:
1868 	case CISSetAddress:
1869 
1870 		reg = va_arg(arglist, csregister_t *);
1871 
1872 		if (reg->cs_magic != PCCS_MAGIC ||
1873 		    reg->cs_version != PCCS_VERSION) {
1874 			cmn_err(CE_WARN,
1875 			    "pcmcia: CSRegister (%x, %x, %p, %p) *ERROR*",
1876 			    reg->cs_magic, reg->cs_version,
1877 			    (void *)reg->cs_card_services,
1878 			    (void *)reg->cs_event);
1879 			error = BAD_FUNCTION;
1880 			break;
1881 		}
1882 
1883 		switch (function) {
1884 		case CISGetAddress:
1885 			reg->cs_event = pcmcia_cis_parser;
1886 			break;
1887 		case CISSetAddress:
1888 			pcmcia_cis_parser = reg->cs_event;
1889 			break;
1890 		case CSRegister:
1891 			break;
1892 		}
1893 		break;
1894 
1895 	case CSUnregister:
1896 		break;
1897 
1898 	case CSCISInit:
1899 		args[0] = va_arg(arglist, int);
1900 #if defined(PCMCIA_DEBUG)
1901 		if (pcmcia_debug)
1902 			cmn_err(CE_CONT,
1903 			    "CSCISInit: CIS is initialized on socket %d\n",
1904 			    (int)args[0]);
1905 #endif
1906 		/*
1907 		 * now that the CIS has been parsed (there may not
1908 		 * be one but the work is done) we can create the
1909 		 * device information structures.
1910 		 *
1911 		 * we serialize the node creation to avoid problems
1912 		 * with initial probe/attach of nexi.
1913 		 */
1914 
1915 		mutex_enter(&pcmcia_global_lock);
1916 		pcmcia_create_dev_info(args[0]);
1917 		cv_broadcast(&pcmcia_condvar); /* wakeup the nexus attach */
1918 		mutex_exit(&pcmcia_global_lock);
1919 		break;
1920 
1921 	case CSInitDev:
1922 #if defined(PCMCIA_DEBUG)
1923 		if (pcmcia_debug)
1924 			cmn_err(CE_CONT, "CSInitDev: initialize device\n");
1925 #endif
1926 		/*
1927 		 * this is where we create the /devices entries
1928 		 * that let us out into the world
1929 		 */
1930 
1931 		(void) pcmcia_create_device(va_arg(arglist,
1932 		    ss_make_device_node_t *));
1933 		break;
1934 
1935 	case CSCardRemoved:
1936 		args[0] = va_arg(arglist, uint32_t);
1937 		socket = CS_GET_SOCKET_NUMBER(args[0]);
1938 		func = CS_GET_FUNCTION_NUMBER(args[0]);
1939 #if defined(PCMCIA_DEBUG)
1940 		if (pcmcia_debug)
1941 			cmn_err(CE_CONT,
1942 			    "CSCardRemoved! (socket=%d)\n", (int)args[0]);
1943 #endif
1944 		if (socket >= pcmcia_num_sockets)
1945 			break;
1946 
1947 		sockp = pcmcia_sockets[socket];
1948 		if (sockp == NULL) {
1949 			cmn_err(CE_WARN,
1950 			    "pcmcia: bad socket = %x", socket);
1951 			break;
1952 		}
1953 
1954 		if (!(sockp->ls_flags & PCS_SUSPENDED)) {
1955 			for (func = 0; func < sockp->ls_functions; func++) {
1956 				/*
1957 				 * break the association of dip and socket
1958 				 * for all functions on that socket
1959 				 */
1960 				dip = sockp->ls_dip[func];
1961 				sockp->ls_dip[func] = NULL;
1962 				if (dip != NULL) {
1963 					struct pcmcia_parent_private *ppd;
1964 					ppd = (struct pcmcia_parent_private *)
1965 					    ddi_get_parent_data(dip);
1966 					ppd->ppd_active = 0;
1967 					(void) ndi_devi_offline(dip,
1968 					    NDI_DEVI_REMOVE);
1969 
1970 					pcmcia_ppd_free(ppd);
1971 				}
1972 #if defined(PCMCIA_DEBUG)
1973 				else {
1974 					if (pcmcia_debug)
1975 						cmn_err(CE_CONT,
1976 						    "CardRemoved: no "
1977 						    "dip present "
1978 						    "on socket %d!\n",
1979 						    (int)args[0]);
1980 				}
1981 #endif
1982 			}
1983 		} else {
1984 			mutex_enter(&pcmcia_global_lock);
1985 			sockp->ls_flags &= ~PCS_SUSPENDED;
1986 			cv_broadcast(&pcmcia_condvar);
1987 			mutex_exit(&pcmcia_global_lock);
1988 		}
1989 		break;
1990 
1991 	case CSGetCookiesAndDip:
1992 		serv = va_arg(arglist, sservice_t *);
1993 		if (serv != NULL)
1994 			error = GetCookiesAndDip(serv);
1995 		else
1996 			error = BAD_SOCKET;
1997 		break;
1998 
1999 	case CSGetActiveDip:
2000 		/*
2001 		 * get the dip associated with the card currently
2002 		 * in the specified socket
2003 		 */
2004 		args[0] = va_arg(arglist, uint32_t);
2005 		socket = CS_GET_SOCKET_NUMBER(args[0]);
2006 		func = CS_GET_FUNCTION_NUMBER(args[0]);
2007 		error = (long)pcmcia_sockets[socket]->ls_dip[func];
2008 		break;
2009 
2010 		/*
2011 		 * the remaining entries are SocketServices calls
2012 		 */
2013 	case SS_GetAdapter:
2014 		error = SSGetAdapter(va_arg(arglist, get_adapter_t *));
2015 		break;
2016 	case SS_GetPage:
2017 		error = SSGetPage(va_arg(arglist, get_page_t *));
2018 		break;
2019 	case SS_GetSocket:
2020 		error = SSGetSocket(va_arg(arglist, get_socket_t *));
2021 		break;
2022 	case SS_GetStatus:
2023 		error = SSGetStatus(va_arg(arglist, get_ss_status_t *));
2024 		break;
2025 	case SS_GetWindow:
2026 		error = SSGetWindow(va_arg(arglist, get_window_t *));
2027 		break;
2028 	case SS_InquireAdapter:
2029 		error = SSInquireAdapter(va_arg(arglist, inquire_adapter_t *));
2030 		break;
2031 	case SS_InquireSocket:
2032 		error = SSInquireSocket(va_arg(arglist, inquire_socket_t *));
2033 		break;
2034 	case SS_InquireWindow:
2035 		error = SSInquireWindow(va_arg(arglist, inquire_window_t *));
2036 		break;
2037 	case SS_ResetSocket:
2038 		args[0] = va_arg(arglist, uint32_t);
2039 		args[1] = va_arg(arglist, int);
2040 		error = SSResetSocket(args[0], args[1]);
2041 		break;
2042 	case SS_SetPage:
2043 		error = SSSetPage(va_arg(arglist, set_page_t *));
2044 		break;
2045 	case SS_SetSocket:
2046 		error = SSSetSocket(va_arg(arglist, set_socket_t *));
2047 		break;
2048 	case SS_SetWindow:
2049 		error = SSSetWindow(va_arg(arglist, set_window_t *));
2050 		break;
2051 	case SS_SetIRQHandler:
2052 		error = SSSetIRQHandler(va_arg(arglist, set_irq_handler_t *));
2053 		break;
2054 	case SS_ClearIRQHandler:
2055 		error = SSClearIRQHandler(va_arg(arglist,
2056 		    clear_irq_handler_t *));
2057 		break;
2058 	default:
2059 		error = BAD_FUNCTION;
2060 		break;
2061 	}
2062 	va_end(arglist);
2063 	return (error);
2064 }
2065 
2066 /*
2067  * pcmcia_merge_power()
2068  *	The adapters may have different power tables so it
2069  *	is necessary to construct a single power table that
2070  *	can be used throughout the system.  The result is
2071  *	a merger of all capabilities.  The nexus adds
2072  *	power table entries one at a time.
2073  */
2074 void
pcmcia_merge_power(struct power_entry * power)2075 pcmcia_merge_power(struct power_entry *power)
2076 {
2077 	int i;
2078 	struct power_entry pwr;
2079 
2080 	pwr = *power;
2081 
2082 	for (i = 0; i < pcmcia_num_power; i++) {
2083 		if (pwr.PowerLevel == pcmcia_power_table[i].PowerLevel) {
2084 			if (pwr.ValidSignals ==
2085 			    pcmcia_power_table[i].ValidSignals) {
2086 				return;
2087 			} else {
2088 				/* partial match */
2089 				pwr.ValidSignals &=
2090 				    ~pcmcia_power_table[i].ValidSignals;
2091 			}
2092 		}
2093 	}
2094 	/* what's left becomes a new entry */
2095 	if (pcmcia_num_power == PCMCIA_MAX_POWER)
2096 		return;
2097 	pcmcia_power_table[pcmcia_num_power++] = pwr;
2098 }
2099 
2100 /*
2101  * pcmcia_do_suspend()
2102  *	tell CS that a suspend has happened by passing a
2103  *	card removal event.  Then cleanup the socket state
2104  *	to fake the cards being removed so resume works
2105  */
2106 void
pcmcia_do_suspend(int socket,pcmcia_logical_socket_t * sockp)2107 pcmcia_do_suspend(int socket, pcmcia_logical_socket_t *sockp)
2108 {
2109 	get_ss_status_t stat;
2110 	struct pcmcia_adapter *adapt;
2111 	pcmcia_if_t *ls_if;
2112 	dev_info_t *dip;
2113 	int i;
2114 
2115 #ifdef	XXX
2116 	if (pcmcia_cs_event == NULL) {
2117 		return;
2118 	}
2119 #endif
2120 
2121 	ls_if = sockp->ls_if;
2122 	adapt = sockp->ls_adapter;
2123 
2124 	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
2125 		return;
2126 	}
2127 
2128 	stat.socket = socket;
2129 #if defined(PCMCIA_DEBUG)
2130 	if (pcmcia_debug) {
2131 		cmn_err(CE_CONT,
2132 		    "pcmcia_do_suspend(%d, %p)\n", socket, (void *)sockp);
2133 	}
2134 #endif
2135 
2136 	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) != SUCCESS)
2137 		return;
2138 
2139 	/*
2140 	 * If there is a card in the socket, then we need to send
2141 	 *	everyone a PCE_CARD_REMOVAL event, and remove the
2142 	 *	card active property.
2143 	 */
2144 
2145 	for (i = 0; i < sockp->ls_functions; i++) {
2146 		struct pcmcia_parent_private *ppd;
2147 		dip = sockp->ls_dip[i];
2148 		if (dip != NULL) {
2149 			ppd = (struct pcmcia_parent_private *)
2150 			    ddi_get_parent_data(dip);
2151 			ppd->ppd_flags |= PPD_SUSPENDED;
2152 		}
2153 #if 0
2154 		sockp->ls_dip[i] = NULL;
2155 #endif
2156 	}
2157 	sockp->ls_flags |= PCS_SUSPENDED;
2158 
2159 	if (pcmcia_cs_event &&
2160 	    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
2161 		CS_EVENT(PCE_PM_SUSPEND, socket, 0);
2162 	}
2163 	pcm_event_manager(PCE_PM_SUSPEND, socket, NULL);
2164 }
2165 
2166 /*
2167  * pcmcia_do_resume()
2168  *	tell CS that a suspend has happened by passing a
2169  *	card removal event.  Then cleanup the socket state
2170  *	to fake the cards being removed so resume works
2171  */
2172 void
pcmcia_do_resume(int socket,pcmcia_logical_socket_t * sockp)2173 pcmcia_do_resume(int socket, pcmcia_logical_socket_t *sockp)
2174 {
2175 	get_ss_status_t stat;
2176 	struct pcmcia_adapter *adapt;
2177 	pcmcia_if_t *ls_if;
2178 
2179 #ifdef	XXX
2180 	if (pcmcia_cs_event == NULL) {
2181 		return;
2182 	}
2183 #endif
2184 
2185 	ls_if = sockp->ls_if;
2186 	adapt = sockp->ls_adapter;
2187 
2188 	if (ls_if == NULL || ls_if->pcif_get_status == NULL) {
2189 		return;
2190 	}
2191 
2192 	stat.socket = socket;
2193 #if defined(PCMCIA_DEBUG)
2194 	if (pcmcia_debug) {
2195 		cmn_err(CE_CONT,
2196 		    "pcmcia_do_resume(%d, %p)\n", socket, (void *)sockp);
2197 	}
2198 #endif
2199 	if (GET_STATUS(ls_if, adapt->pca_dip, &stat) ==
2200 	    SUCCESS) {
2201 
2202 #if defined(PCMCIA_DEBUG)
2203 		if (pcmcia_debug)
2204 			cmn_err(CE_CONT, "\tsocket=%x, CardState=%x\n",
2205 			    socket, stat.CardState);
2206 #endif
2207 #if 0
2208 		/* now have socket info -- do we have events? */
2209 		if ((stat.CardState & SBM_CD) == SBM_CD) {
2210 			if (pcmcia_cs_event &&
2211 			    (sockp->ls_cs_events & (1 << PCE_CARD_INSERT))) {
2212 				CS_EVENT(PCE_CARD_INSERT, socket, 0);
2213 			}
2214 
2215 			/* we should have card removed from CS soon */
2216 			pcm_event_manager(PCE_CARD_INSERT, socket, NULL);
2217 		}
2218 #else
2219 		if (pcmcia_cs_event &&
2220 		    (sockp->ls_cs_events & (1 << PCE_PM_SUSPEND))) {
2221 			CS_EVENT(PCE_PM_RESUME, socket, 0);
2222 			CS_EVENT(PCE_CARD_REMOVAL, socket, 0);
2223 			if ((stat.CardState & SBM_CD) == SBM_CD)
2224 				CS_EVENT(PCE_CARD_INSERT, socket, 0);
2225 		}
2226 #endif
2227 	}
2228 }
2229 
2230 /*
2231  * pcmcia_map_power_set()
2232  *	Given a power table entry and level, find it in the
2233  *	master table and return the index in the adapter table.
2234  */
2235 static int
pcmcia_map_power_set(struct pcmcia_adapter * adapt,int level,int which)2236 pcmcia_map_power_set(struct pcmcia_adapter *adapt, int level, int which)
2237 {
2238 	int plevel, i;
2239 	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
2240 	plevel = pcmcia_power_table[level].PowerLevel;
2241 	/* mask = pcmcia_power_table[level].ValidSignals; */
2242 	for (i = 0; i < adapt->pca_numpower; i++)
2243 		if (plevel == pwr[i].PowerLevel &&
2244 		    pwr[i].ValidSignals & which)
2245 			return (i);
2246 	return (0);
2247 }
2248 
2249 /*
2250  * pcmcia_map_power_get()
2251  *	Given an adapter power entry, find the appropriate index
2252  *	in the master table.
2253  */
2254 static int
pcmcia_map_power_get(struct pcmcia_adapter * adapt,int level,int which)2255 pcmcia_map_power_get(struct pcmcia_adapter *adapt, int level, int which)
2256 {
2257 	int plevel, i;
2258 	struct power_entry *pwr = (struct power_entry *)adapt->pca_power;
2259 	plevel = pwr[level].PowerLevel;
2260 	/* mask = pwr[level].ValidSignals; */
2261 	for (i = 0; i < pcmcia_num_power; i++)
2262 		if (plevel == pcmcia_power_table[i].PowerLevel &&
2263 		    pcmcia_power_table[i].ValidSignals & which)
2264 			return (i);
2265 	return (0);
2266 }
2267 
2268 /*
2269  * XXX - SS really needs a way to allow the caller to express
2270  *	interest in PCE_CARD_STATUS_CHANGE events.
2271  */
2272 static uint32_t
2273 pcm_event_map[32] = {
2274 	PCE_E2M(PCE_CARD_WRITE_PROTECT)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2275 	PCE_E2M(PCE_CARD_UNLOCK)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2276 	PCE_E2M(PCE_EJECTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2277 	PCE_E2M(PCE_INSERTION_REQUEST)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2278 	PCE_E2M(PCE_CARD_BATTERY_WARN)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2279 	PCE_E2M(PCE_CARD_BATTERY_DEAD)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2280 	PCE_E2M(PCE_CARD_READY)|PCE_E2M(PCE_CARD_STATUS_CHANGE),
2281 	PCE_E2M(PCE_CARD_REMOVAL)|PCE_E2M(PCE_CARD_INSERT)|
2282 					PCE_E2M(PCE_CARD_STATUS_CHANGE),
2283 	PCE_E2M(PCE_PM_SUSPEND)|PCE_E2M(PCE_PM_RESUME),
2284 };
2285 
2286 static int
pcm_mapevents(uint32_t eventmask)2287 pcm_mapevents(uint32_t eventmask)
2288 {
2289 	uint32_t mask;
2290 	int i;
2291 
2292 	for (i = 0, mask = 0; eventmask && i < 32; i++) {
2293 		if (eventmask & (1 << i)) {
2294 			mask |= pcm_event_map[i];
2295 			eventmask &= ~(1 << i);
2296 		}
2297 	}
2298 	return (mask);
2299 }
2300 
2301 
2302 /*
2303  * PCMCIA Generic Naming Support
2304  *
2305  * With 2.6, PCMCIA naming moves to the 1275 and generic naming model.
2306  * Consequently, the whole naming mechanism is to be changed.  This is
2307  * not backward compatible with the current names but that isn't a problem
2308  * due to so few drivers existing.
2309  *
2310  * For cards with a device_id tuple, a generic name will be used.
2311  * if there is no device_id, then the 1275 name will be used if possible.
2312  * The 1275 name is of the form pccardNNNN,MMMM from the manfid tuple.
2313  * if there is not manfid tuple, an attempt will be made to bind the
2314  * node to the version_1 strings.
2315  *
2316  * In all cases, a "compatible" property is created with a number
2317  * of names.  The most generic name will be last in the list.
2318  */
2319 
2320 /*
2321  * pcmcia_fix_string()
2322  * want to avoid special characters in alias strings so convert
2323  * to something innocuous
2324  */
2325 
2326 void
pcmcia_fix_string(char * str)2327 pcmcia_fix_string(char *str)
2328 {
2329 	for (; str && *str; str++) {
2330 		switch (*str) {
2331 			case ' ':
2332 			case '\t':
2333 				*str = '_';
2334 				break;
2335 		}
2336 	}
2337 }
2338 
2339 void
pcmcia_1275_name(int socket,struct pcm_device_info * info,client_handle_t handle)2340 pcmcia_1275_name(int socket, struct pcm_device_info *info,
2341     client_handle_t handle)
2342 {
2343 	cistpl_manfid_t manfid;
2344 	cistpl_jedec_t jedec;
2345 	tuple_t tuple;
2346 	int i;
2347 
2348 	tuple.Socket = socket;
2349 
2350 	/* get MANFID if it exists -- this is most important form */
2351 	tuple.DesiredTuple = CISTPL_MANFID;
2352 	tuple.Attributes = 0;
2353 	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2354 	    SUCCESS) {
2355 		i = csx_Parse_CISTPL_MANFID(handle, &tuple,
2356 		    &manfid);
2357 		if (i == SUCCESS) {
2358 			(void) sprintf(info->pd_bind_name, "%s%x,%x",
2359 			    PCMDEV_NAMEPREF,
2360 			    manfid.manf, manfid.card);
2361 			info->pd_flags |= PCM_NAME_1275;
2362 		}
2363 	} else {
2364 		tuple.Attributes = 0;
2365 		tuple.DesiredTuple = CISTPL_JEDEC_A;
2366 		if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2367 		    SUCCESS) {
2368 			i = csx_Parse_CISTPL_JEDEC_A(handle, &tuple,
2369 			    &jedec);
2370 			if (i == SUCCESS) {
2371 				(void) sprintf(info->pd_bind_name, "%s%x,%x",
2372 				    PCMDEV_NAMEPREF,
2373 				    jedec.jid[0].id, jedec.jid[0].info);
2374 				info->pd_flags |= PCM_NAME_1275;
2375 			}
2376 		}
2377 	}
2378 }
2379 
2380 void
pcmcia_vers1_name(int socket,struct pcm_device_info * info,client_handle_t handle)2381 pcmcia_vers1_name(int socket, struct pcm_device_info *info,
2382     client_handle_t handle)
2383 {
2384 	cistpl_vers_1_t vers1;
2385 	tuple_t tuple;
2386 	int which = 0;
2387 	int i, len, space;
2388 
2389 	tuple.Socket = socket;
2390 	info->pd_vers1_name[0] = '\0';
2391 
2392 	/* Version 1 strings */
2393 	tuple.DesiredTuple = CISTPL_VERS_1;
2394 	tuple.Attributes = 0;
2395 	if (!which &&
2396 	    (i = csx_GetFirstTuple(handle, &tuple)) == SUCCESS) {
2397 		i = csx_Parse_CISTPL_VERS_1(handle, &tuple, &vers1);
2398 		if (i == SUCCESS) {
2399 			/* BEGIN CSTYLED */
2400 			for (i = 0, len = 0, space = 0; i < vers1.ns; i++) {
2401 			    if ((space + len + strlen(info->pd_vers1_name)) >=
2402 				sizeof (info->pd_vers1_name))
2403 				    break;
2404 			    if (space) {
2405 				    info->pd_vers1_name[len++] = ',';
2406 			    }
2407 			    (void) strcpy(info->pd_vers1_name + len,
2408 				(char *)vers1.pi[i]);
2409 			    len += strlen((char *)vers1.pi[i]);
2410 			    /* strip trailing spaces off of string */
2411 			    while (info->pd_vers1_name[len - 1] == ' ' &&
2412 				    len > 0)
2413 				    len--;
2414 			    space = 1;
2415 			}
2416 			/* END CSTYLED */
2417 			info->pd_vers1_name[len] = '\0';
2418 			info->pd_flags |= PCM_NAME_VERS1;
2419 		}
2420 	}
2421 }
2422 
2423 
2424 int
pcmcia_get_funce(client_handle_t handle,tuple_t * tuple)2425 pcmcia_get_funce(client_handle_t handle, tuple_t *tuple)
2426 {
2427 	int ret = 0;
2428 
2429 	tuple->Attributes = 0;
2430 	while (csx_GetNextTuple(handle, tuple) == SUCCESS) {
2431 		if (tuple->TupleCode == CISTPL_FUNCID) {
2432 			break;
2433 		}
2434 		if (tuple->TupleCode == CISTPL_FUNCE) {
2435 			ret = 1;
2436 			break;
2437 		}
2438 		tuple->Attributes = 0;
2439 	}
2440 	return (ret);
2441 }
2442 
2443 char *pcmcia_lan_types[] = {
2444 	"arcnet",
2445 	"ethernet",
2446 	"token-ring",
2447 	"localtalk",
2448 	"fddi",
2449 	"atm",
2450 	"wireless",
2451 	"reserved"
2452 };
2453 
2454 void
pcmcia_generic_name(int socket,struct pcm_device_info * info,client_handle_t handle)2455 pcmcia_generic_name(int socket, struct pcm_device_info *info,
2456     client_handle_t handle)
2457 {
2458 	cistpl_funcid_t funcid;
2459 	cistpl_funce_t funce;
2460 	tuple_t tuple;
2461 	int which = 0;
2462 	int i;
2463 
2464 	tuple.Socket = socket;
2465 
2466 	tuple.DesiredTuple = CISTPL_FUNCID;
2467 	tuple.Attributes = 0;
2468 	if ((i = csx_GetFirstTuple(handle, &tuple)) ==
2469 	    SUCCESS) {
2470 		/*
2471 		 * need to make sure that CISTPL_FUNCID is not
2472 		 * present in both a global and local CIS for MF
2473 		 * cards.  3COM seems to do this erroneously
2474 		 */
2475 
2476 		if (info->pd_flags & PCM_MULTI_FUNCTION &&
2477 		    tuple.Flags & CISTPLF_GLOBAL_CIS) {
2478 			tuple_t ltuple;
2479 			ltuple = tuple;
2480 			ltuple.DesiredTuple = CISTPL_FUNCID;
2481 			ltuple.Attributes = 0;
2482 			if ((i = csx_GetNextTuple(handle, &ltuple)) ==
2483 			    SUCCESS) {
2484 				/* this is the per-function funcid */
2485 				tuple = ltuple;
2486 			}
2487 		}
2488 
2489 		i = csx_Parse_CISTPL_FUNCID(handle, &tuple, &funcid);
2490 		if (i == SUCCESS) {
2491 			/* in case no function extension */
2492 			if (funcid.function < PCM_GENNAME_SIZE)
2493 				(void) strcpy(info->pd_generic_name,
2494 				    pcmcia_generic_names[funcid.function]);
2495 			else
2496 				(void) sprintf(info->pd_generic_name,
2497 				    "class,%x",
2498 				    funcid.function);
2499 		}
2500 		info->pd_type = funcid.function;
2501 		switch (funcid.function) {
2502 		case TPLFUNC_LAN:
2503 			which = pcmcia_get_funce(handle, &tuple);
2504 			if (which) {
2505 				i = csx_Parse_CISTPL_FUNCE(handle,
2506 				    &tuple,
2507 				    &funce, TPLFUNC_LAN);
2508 				if (i == SUCCESS) {
2509 					i = funce.data.lan.tech;
2510 					if (i >= sizeof (pcmcia_lan_types) /
2511 					    sizeof (char *)) {
2512 						break;
2513 					}
2514 					(void) strcpy(info->pd_generic_name,
2515 					    pcmcia_lan_types[i]);
2516 				}
2517 			}
2518 			break;
2519 		case TPLFUNC_VIDEO:
2520 #ifdef future_pcmcia_spec
2521 			which = pcmcia_get_funce(handle, &tuple);
2522 			if (which) {
2523 				i = csx_Parse_CISTPL_FUNCE(handle,
2524 				    &tuple,
2525 				    &funce, TPLFUNC_VIDEO);
2526 				if (i == SUCCESS) {
2527 					i = funce.video.tech;
2528 					if (i > sizeof (pcmcia_lan_types) /
2529 					    sizeof (char *)) {
2530 						break;
2531 					}
2532 					(void) strcpy(info->pd_generic_names,
2533 					    pcmcia_lan_types[i]);
2534 				}
2535 			}
2536 #endif
2537 			break;
2538 		}
2539 		info->pd_flags |= PCM_NAME_GENERIC;
2540 	} else {
2541 		/* if no FUNCID, do we have CONFIG */
2542 		tuple.DesiredTuple = CISTPL_CONFIG;
2543 		tuple.Attributes = 0;
2544 		if (csx_GetFirstTuple(handle, &tuple) != SUCCESS) {
2545 			info->pd_flags |= PCM_NO_CONFIG | PCM_NAME_GENERIC;
2546 			(void) strcpy(info->pd_generic_name,
2547 			    pcmcia_generic_names[PCM_TYPE_MEMORY]);
2548 			info->pd_type = PCM_TYPE_MEMORY;
2549 		}
2550 	}
2551 }
2552 
2553 
2554 /*
2555  * pcmcia_add_compatible()
2556  * add the cached compatible property list.
2557  */
2558 void
pcmcia_add_compatible(dev_info_t * dip,struct pcm_device_info * info)2559 pcmcia_add_compatible(dev_info_t *dip, struct pcm_device_info *info)
2560 {
2561 	int length = 0, i;
2562 	char buff[MAXNAMELEN];
2563 	char *compat_name[8];
2564 	int ci = 0;
2565 
2566 	bzero(compat_name, sizeof (compat_name));
2567 
2568 	if (info->pd_flags & PCM_NAME_VERS1) {
2569 		(void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF,
2570 		    info->pd_vers1_name);
2571 		pcmcia_fix_string(buff); /* don't want spaces */
2572 		length = strlen(buff) + 1;
2573 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2574 		(void) strcpy(compat_name[ci++], buff);
2575 	}
2576 
2577 	if ((info->pd_flags & (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) ==
2578 	    (PCM_NAME_1275 | PCM_MULTI_FUNCTION)) {
2579 		(void) sprintf(buff, "%s,%x", info->pd_bind_name,
2580 		    info->pd_function);
2581 		length = strlen(buff) + 1;
2582 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2583 		(void) strcpy(compat_name[ci++], buff);
2584 	}
2585 
2586 	if (info->pd_flags & PCM_NAME_1275) {
2587 		length = strlen(info->pd_bind_name) + 1;
2588 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2589 		(void) strcpy(compat_name[ci++], info->pd_bind_name);
2590 	}
2591 
2592 	if (info->pd_flags & PCM_NAME_GENERIC) {
2593 		if (strncmp(info->pd_generic_name, "class,", 6) == 0) {
2594 			/* no generic without "pccard" */
2595 			(void) sprintf(buff, "%s%s", PCMDEV_NAMEPREF,
2596 			    info->pd_generic_name);
2597 		} else {
2598 			/* first pccard,generic-name */
2599 			(void) sprintf(buff, "%s,%s", PCMDEV_NAMEPREF,
2600 			    info->pd_generic_name);
2601 		}
2602 		length = strlen(buff) + 1;
2603 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2604 		(void) strcpy(compat_name[ci++], buff);
2605 
2606 		/* now the simple generic name */
2607 		length = strlen(info->pd_generic_name) + 1;
2608 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2609 		(void) strcpy(compat_name[ci++], info->pd_generic_name);
2610 	}
2611 
2612 	if (info->pd_flags & PCM_NO_CONFIG) {
2613 		char *mem = "pccard,memory";
2614 		/*
2615 		 * I/O cards are required to have a config tuple.
2616 		 * there are some that violate the spec and don't
2617 		 * but it is most likely that this is a memory card
2618 		 * so tag it as such.  "memory" is more general
2619 		 * than other things so needs to come last.
2620 		 */
2621 		length = strlen(mem) + 1;
2622 		compat_name[ci] = kmem_alloc(length, KM_SLEEP);
2623 		(void) strcpy(compat_name[ci++], mem);
2624 	}
2625 
2626 	if (ci == 0)
2627 		return;
2628 
2629 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
2630 	    "compatible", (char **)compat_name, ci) != DDI_PROP_SUCCESS)
2631 		cmn_err(CE_WARN, "pcmcia: unable to create compatible prop");
2632 
2633 	for (i = 0; i < ci; i++)
2634 		kmem_free(compat_name[i], strlen(compat_name[i]) + 1);
2635 }
2636 /*
2637  * CIS parsing and other PC Card specific code
2638  */
2639 
2640 /*
2641  * pcmcia_get_mem_regs()
2642  */
2643 static int
pcmcia_get_mem_regs(struct pcm_regs * regs,struct pcm_device_info * info,int type,int pctype)2644 pcmcia_get_mem_regs(struct pcm_regs *regs, struct pcm_device_info *info,
2645     int type, int pctype)
2646 {
2647 	int num_regs = 0;
2648 	tuple_t tuple;
2649 	cistpl_device_t device;
2650 	uint32_t curr_base;
2651 	int ret, len;
2652 	int space;
2653 
2654 	/*
2655 	 * current plan for reg spec:
2656 	 * device_a will be accumulated to determine max size of
2657 	 * attribute memory.  device for common.  Then config
2658 	 * tuples to get a worst case I/O size.
2659 	 */
2660 	bzero(&tuple, sizeof (tuple));
2661 	tuple.Socket = info->pd_socket;
2662 
2663 	tuple.DesiredTuple = (cisdata_t)type;
2664 
2665 	space = (type == CISTPL_DEVICE_A) ? PC_REG_SPACE_ATTRIBUTE :
2666 	    PC_REG_SPACE_MEMORY;
2667 	if ((ret = csx_GetFirstTuple(info->pd_handle, &tuple)) == CS_SUCCESS) {
2668 		bzero(&device, sizeof (device));
2669 
2670 		if (type == CISTPL_DEVICE)
2671 			ret = csx_Parse_CISTPL_DEVICE(info->pd_handle, &tuple,
2672 			    &device);
2673 		else
2674 			ret = csx_Parse_CISTPL_DEVICE_A(info->pd_handle, &tuple,
2675 			    &device);
2676 
2677 		if (ret == CS_SUCCESS) {
2678 			curr_base = 0;
2679 			for (ret = 0; ret < device.num_devices; ret++) {
2680 				/* need to order these for real mem first */
2681 				if (device.devnode[ret].type !=
2682 				    CISTPL_DEVICE_DTYPE_NULL) {
2683 					/* how to represent types??? */
2684 					regs[num_regs].phys_hi =
2685 					    PC_REG_PHYS_HI(0, 0,
2686 					    pctype,
2687 					    space,
2688 					    info->pd_socket,
2689 					    info->pd_function,
2690 					    0);
2691 					regs[num_regs].phys_lo = curr_base;
2692 					len = device.devnode[ret].size_in_bytes;
2693 					curr_base += len;
2694 					regs[num_regs].phys_len = len;
2695 					num_regs++;
2696 				} else {
2697 					/*
2698 					 * NULL device is a "hole"
2699 					 */
2700 					curr_base +=
2701 					    device.devnode[ret].size_in_bytes;
2702 				}
2703 			}
2704 		}
2705 	}
2706 	return (num_regs);
2707 }
2708 
2709 /*
2710  *
2711  */
2712 static int
pcmcia_get_io_regs(struct pcm_regs * regs,struct pcm_device_info * info,int pctype)2713 pcmcia_get_io_regs(struct pcm_regs *regs, struct pcm_device_info *info,
2714     int pctype)
2715 {
2716 	int num_regs = 0;
2717 	tuple_t tuple;
2718 	uint32_t curr_base;
2719 	int len, curr, i, curr_len;
2720 	cistpl_config_t config;
2721 	cistpl_cftable_entry_t cftable;
2722 	struct pcm_regs tmp[16];
2723 	int found = 0;
2724 
2725 	bzero(&tuple, sizeof (tuple));
2726 	tuple.DesiredTuple = CISTPL_CONFIG;
2727 	tuple.Socket = info->pd_socket;
2728 	tuple.Attributes = 0;
2729 	curr_base = 0;
2730 	len = 0;
2731 
2732 	if (csx_GetFirstTuple(info->pd_handle, &tuple) == CS_SUCCESS) {
2733 		if (csx_Parse_CISTPL_CONFIG(info->pd_handle,
2734 		    &tuple, &config) != CS_SUCCESS) {
2735 			info->pd_flags |= PCM_NO_CONFIG; /* must be memory */
2736 			return (0);
2737 		}
2738 		curr = 0;
2739 
2740 		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
2741 		tuple.Socket = info->pd_socket;
2742 		tuple.Attributes = 0;
2743 		bzero(tmp, sizeof (tmp));
2744 
2745 	while (csx_GetNextTuple(info->pd_handle, &tuple) == CS_SUCCESS) {
2746 		bzero(&cftable, sizeof (cftable));
2747 
2748 		if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle,
2749 		    &tuple, &cftable) == CS_SUCCESS) {
2750 
2751 		/* BEGIN CSTYLED */
2752 		if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IO) {
2753 		    /* we have an I/O entry */
2754 		    if (cftable.io.flags &
2755 			CISTPL_CFTABLE_TPCE_FS_IO_RANGE) {
2756 			len = cftable.io.addr_lines;
2757 			if (len != 0)
2758 				len = 1 << len;
2759 			for (i = 0; i < cftable.io.ranges && curr < 16; i++) {
2760 			    curr_base = cftable.io.range[i].addr;
2761 			    curr_len = cftable.io.range[i].length;
2762 			    if (curr_len == 0)
2763 				    curr_len = len;
2764 			    if (len != 0 || cftable.io.addr_lines == 0) {
2765 				/* we have potential relocation */
2766 				int mask;
2767 				mask = cftable.io.addr_lines ?
2768 				    cftable.io.addr_lines : genp2(len);
2769 				mask = genmask(mask);
2770 				if ((mask & curr_base) == 0) {
2771 					/* more accurate length */
2772 					regs->phys_len = curr_len;
2773 					regs->phys_lo = 0;
2774 					regs->phys_hi =
2775 					    PC_REG_PHYS_HI(0,
2776 					    0,
2777 					    pctype,
2778 					    PC_REG_SPACE_IO,
2779 					    info->pd_socket,
2780 					    info->pd_function,
2781 					    0);
2782 					num_regs++;
2783 					found = 2;
2784 					break;
2785 				}
2786 			    }
2787 			    tmp[curr].phys_len = curr_len;
2788 			    tmp[curr].phys_lo = curr_base;
2789 			    curr++;
2790 			    found = 1;
2791 			}
2792 			if (found == 2)
2793 				break;
2794 		    } else {
2795 			/* no I/O range so just a mask */
2796 			regs->phys_len = 1 << cftable.io.addr_lines;
2797 			regs->phys_hi =
2798 			    PC_REG_PHYS_HI(0,
2799 			    0,
2800 			    pctype,
2801 			    PC_REG_SPACE_IO,
2802 			    info->pd_socket,
2803 			    info->pd_function,
2804 			    0);
2805 			regs->phys_lo = 0;
2806 			num_regs++;
2807 			regs++;
2808 			/* quit on "good" entry */
2809 			break;
2810 		    }
2811 		    /* was this the last CFTABLE Entry? */
2812 		    if (config.last == cftable.index)
2813 			    break;
2814 		}
2815 		/* END CSTYLE */
2816 		}
2817 	}
2818 	if (found == 1) {
2819 		/*
2820 		 * have some non-relocatable values
2821 		 * so we include them all for now
2822 		 */
2823 		for (i = 0; i < curr && num_regs < 8; i++) {
2824 		    regs->phys_len = tmp[i].phys_len;
2825 		    regs->phys_lo = tmp[i].phys_lo;
2826 		    regs->phys_hi = PC_REG_PHYS_HI(1, 0, pctype,
2827 			    PC_REG_SPACE_IO, info->pd_socket,
2828 			    info->pd_function, 0);
2829 		    regs++;
2830 		    num_regs++;
2831 		}
2832 	    }
2833 	}
2834 	return (num_regs);
2835 }
2836 
2837 /*
2838  * pcmcia_create_regs()
2839  *	create a valid set of regspecs for the card
2840  *	The first one is always for CIS access and naming
2841  */
2842 /*ARGSUSED*/
2843 static void
pcmcia_find_regs(dev_info_t * dip,struct pcm_device_info * info,struct pcmcia_parent_private * ppd)2844 pcmcia_find_regs(dev_info_t *dip, struct pcm_device_info *info,
2845 			struct pcmcia_parent_private *ppd)
2846 {
2847 	struct pcm_regs regs[32]; /* assume worst case */
2848 	int num_regs = 0;
2849 	int len;
2850 	int bustype;
2851 
2852 	if (ppd->ppd_flags & PPD_CARD_CARDBUS) {
2853 		/* always have a CIS map */
2854 		regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_CARDBUS,
2855 		    PC_REG_SPACE_CONFIG,
2856 		    info->pd_socket,
2857 		    info->pd_function, 0);
2858 		bustype = PC_REG_TYPE_CARDBUS;
2859 	} else {
2860 		/* always have a CIS map */
2861 		regs[0].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT,
2862 		    PC_REG_SPACE_ATTRIBUTE,
2863 		    info->pd_socket,
2864 		    info->pd_function, 0);
2865 		bustype = PC_REG_TYPE_16BIT;
2866 	}
2867 	regs[0].phys_lo = 0;	/* always starts at zero */
2868 	regs[0].phys_len = 0;
2869 	num_regs++;
2870 	/*
2871 	 * need to search CIS for other memory instances
2872 	 */
2873 
2874 	if (info->pd_flags & PCM_OTHER_NOCIS) {
2875 		/* special case of memory only card without CIS */
2876 		regs[1].phys_hi = PC_REG_PHYS_HI(0, 0, PC_REG_TYPE_16BIT,
2877 		    PC_REG_SPACE_MEMORY,
2878 		    info->pd_socket,
2879 		    info->pd_function, 0);
2880 		regs[1].phys_lo = 0;
2881 		regs[1].phys_len = PCM_MAX_R2_MEM;
2882 		num_regs++;
2883 	} else {
2884 		/*
2885 		 * want to get any other memory and/or I/O regions
2886 		 * on the card and represent them here.
2887 		 */
2888 		num_regs += pcmcia_get_mem_regs(&regs[num_regs], info,
2889 		    CISTPL_DEVICE_A, bustype);
2890 		num_regs += pcmcia_get_mem_regs(&regs[num_regs], info,
2891 		    CISTPL_DEVICE, bustype);
2892 
2893 		/* now look for an I/O space to configure */
2894 		num_regs += pcmcia_get_io_regs(&regs[num_regs], info,
2895 		    bustype);
2896 
2897 	}
2898 
2899 	len = num_regs * sizeof (uint32_t) * 3;
2900 	ppd->ppd_nreg = num_regs;
2901 	ppd->ppd_reg = kmem_alloc(len, KM_SLEEP);
2902 	bcopy(regs, ppd->ppd_reg, len);
2903 	len = sizeof (struct pcm_regs) * ppd->ppd_nreg;
2904 	ppd->ppd_assigned = kmem_zalloc(len, KM_SLEEP);
2905 }
2906 
2907 
2908 /*
2909  * pcmcia_need_intr()
2910  *	check to see if an interrupt tuple exists.
2911  *	existence means we need one in the intrspec.
2912  */
2913 static int
pcmcia_need_intr(int socket,struct pcm_device_info * info)2914 pcmcia_need_intr(int socket, struct pcm_device_info *info)
2915 {
2916 	cistpl_config_t config;
2917 	cistpl_cftable_entry_t cftable;
2918 	tuple_t tuple;
2919 	int i;
2920 
2921 	bzero(&tuple, sizeof (tuple));
2922 	tuple.DesiredTuple = CISTPL_CONFIG;
2923 	tuple.Socket = socket;
2924 	tuple.Attributes = 0;
2925 	if (csx_GetFirstTuple(info->pd_handle, &tuple) != CS_SUCCESS) {
2926 		return (0);
2927 	}
2928 #if defined(PCMCIA_DEBUG)
2929 	if (pcmcia_debug) {
2930 		cmn_err(CE_CONT, "pcmcia_need_intr: have config tuple\n");
2931 	}
2932 #endif
2933 	bzero(&config, sizeof (config));
2934 	if (csx_Parse_CISTPL_CONFIG(info->pd_handle,
2935 	    &tuple, &config) != CS_SUCCESS) {
2936 		cmn_err(CE_WARN, "pcmcia: config failed to parse\n");
2937 		return (0);
2938 	}
2939 
2940 	for (cftable.index = (int)-1, i = -1;
2941 	    i != config.last; i = cftable.index) {
2942 		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
2943 		tuple.Attributes = 0;
2944 		if (csx_GetNextTuple(info->pd_handle,
2945 		    &tuple) != CS_SUCCESS) {
2946 			cmn_err(CE_WARN, "pcmcia: get cftable failed\n");
2947 			break;
2948 		}
2949 		bzero(&cftable, sizeof (cftable));
2950 		if (csx_Parse_CISTPL_CFTABLE_ENTRY(info->pd_handle,
2951 		    &tuple, &cftable) !=
2952 		    CS_SUCCESS) {
2953 			cmn_err(CE_WARN, "pcmcia: parse cftable failed\n");
2954 			break;
2955 		}
2956 #if defined(PCMCIA_DEBUG)
2957 		if (pcmcia_debug)
2958 			cmn_err(CE_CONT, "\t%x: flags=%x (%x)\n",
2959 			    i, cftable.flags,
2960 			    cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ);
2961 #endif
2962 		if (cftable.flags & CISTPL_CFTABLE_TPCE_FS_IRQ)
2963 			return (1);
2964 	}
2965 	return (0);
2966 
2967 }
2968 
2969 /*
2970  * pcmcia_num_funcs()
2971  *	look for a CISTPL_LONGLINK_MFC
2972  *	if there is one, return the number of functions
2973  *	if there isn't one, then there is one function
2974  */
2975 static int
pcmcia_num_funcs(int socket,client_handle_t handle)2976 pcmcia_num_funcs(int socket, client_handle_t handle)
2977 {
2978 	int count = 1;
2979 	cistpl_longlink_mfc_t mfc;
2980 	tuple_t tuple;
2981 
2982 	bzero(&tuple, sizeof (tuple_t));
2983 	tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
2984 	tuple.Socket = socket;
2985 	tuple.Attributes = 0;
2986 	if (csx_GetFirstTuple(handle, &tuple) == CS_SUCCESS) {
2987 		/* this is a multifunction card */
2988 		if (csx_ParseTuple(handle, &tuple, (cisparse_t *)&mfc,
2989 		    CISTPL_LONGLINK_MFC) == CS_SUCCESS) {
2990 			count = mfc.nfuncs;
2991 		}
2992 	}
2993 	return (count);
2994 }
2995 
2996 client_handle_t pcmcia_cs_handle;
2997 
2998 /*
2999  * pcmcia_create_dev_info(socket)
3000  *	either find or create the device information structure
3001  *	for the card(s) just inserted.	We don't care about removal yet.
3002  *	In any case, we will only do this at CS request
3003  */
3004 static void
pcmcia_create_dev_info(int socket)3005 pcmcia_create_dev_info(int socket)
3006 {
3007 	struct pcm_device_info card_info;
3008 	client_reg_t reg;
3009 	cisinfo_t cisinfo;
3010 	int i;
3011 	dev_info_t *pdip;
3012 	static int handle_def = 0;
3013 
3014 #if defined(PCMCIA_DEBUG)
3015 	if (pcmcia_debug)
3016 		cmn_err(CE_CONT, "create dev_info_t for device in socket %d\n",
3017 		    socket);
3018 #endif
3019 
3020 	/*
3021 	 * before we can do anything else, we need the parent
3022 	 * devinfo of the socket.  This gets things in the right
3023 	 * place in the device tree.
3024 	 */
3025 
3026 	pdip = pcm_find_parent_dip(socket);
3027 	if (pdip == NULL)
3028 		return;
3029 
3030 	/* Card Services calls needed to get CIS info */
3031 	reg.dip = NULL;
3032 	reg.Attributes = INFO_SOCKET_SERVICES;
3033 	reg.EventMask = 0;
3034 	reg.event_handler = NULL;
3035 	reg.Version = CS_VERSION;
3036 
3037 	bzero(&card_info, sizeof (card_info));
3038 
3039 	if (handle_def == 0) {
3040 		if (csx_RegisterClient(&pcmcia_cs_handle,
3041 		    &reg) != CS_SUCCESS) {
3042 #if defined(PCMCIA_DEBUG)
3043 			if (pcmcia_debug)
3044 				cmn_err(CE_CONT,
3045 				    "pcmcia: RegisterClient failed\n");
3046 #endif
3047 			return;
3048 		}
3049 		handle_def++;
3050 	}
3051 	card_info.pd_handle = pcmcia_cs_handle;
3052 
3053 #if defined(PCMCIA_DEBUG)
3054 	if (pcmcia_debug)
3055 		cmn_err(CE_CONT,
3056 		    "pcmcia_create_dev_info: handle = %x\n",
3057 		    (int)card_info.pd_handle);
3058 #endif
3059 	card_info.pd_type = -1; /* no type to start */
3060 	card_info.pd_socket = socket;
3061 	card_info.pd_function = 0;
3062 	pcmcia_sockets[socket]->ls_functions = 1; /* default */
3063 
3064 	cisinfo.Socket = socket;
3065 
3066 	if ((i = csx_ValidateCIS(card_info.pd_handle,
3067 	    &cisinfo)) != SUCCESS ||
3068 	    cisinfo.Tuples == 0) {
3069 		/* no CIS means memory */
3070 		(void) strcpy(card_info.pd_generic_name, "memory");
3071 		card_info.pd_flags |= PCM_NAME_GENERIC |
3072 		    PCM_OTHER_NOCIS | PCM_NAME_1275;
3073 		(void) strcpy(card_info.pd_bind_name, "pccard,memory");
3074 		(void) strcpy(card_info.pd_generic_name, "memory");
3075 		card_info.pd_type = PCM_TYPE_MEMORY;
3076 	} else {
3077 		int functions, lsocket;
3078 		card_info.pd_tuples = cisinfo.Tuples;
3079 
3080 		/*
3081 		 * how many functions on the card?
3082 		 * we need to know and then we do one
3083 		 * child node for each function using
3084 		 * the function specific tuples.
3085 		 */
3086 		lsocket = CS_MAKE_SOCKET_NUMBER(socket, CS_GLOBAL_CIS);
3087 		functions = pcmcia_num_funcs(lsocket,
3088 		    card_info.pd_handle);
3089 		pcmcia_sockets[socket]->ls_functions = functions;
3090 		if (functions > 1) {
3091 			card_info.pd_flags |= PCM_MULTI_FUNCTION;
3092 		}
3093 		for (i = 0; i < functions; i++) {
3094 			register int flags;
3095 			lsocket = CS_MAKE_SOCKET_NUMBER(socket, i);
3096 			card_info.pd_socket = socket;
3097 			card_info.pd_function = i;
3098 			/*
3099 			 * new name construction
3100 			 */
3101 			if (functions != 1) {
3102 				/* need per function handle */
3103 				card_info.pd_function = i;
3104 				/* get new handle */
3105 			}
3106 			pcmcia_1275_name(lsocket, &card_info,
3107 			card_info.pd_handle);
3108 			pcmcia_vers1_name(lsocket, &card_info,
3109 			card_info.pd_handle);
3110 			pcmcia_generic_name(lsocket, &card_info,
3111 			card_info.pd_handle);
3112 			flags = card_info.pd_flags;
3113 			if (!(flags & PCM_NAME_1275)) {
3114 				if (flags & PCM_NAME_VERS1) {
3115 				    (void) strcpy(card_info.pd_bind_name,
3116 					PCMDEV_NAMEPREF);
3117 				    card_info.pd_bind_name[
3118 				        sizeof (PCMDEV_NAMEPREF)] = ',';
3119 				    (void) strncpy(card_info.pd_bind_name +
3120 					sizeof (PCMDEV_NAMEPREF),
3121 					card_info.pd_vers1_name,
3122 					MODMAXNAMELEN -
3123 					sizeof (PCMDEV_NAMEPREF));
3124 				    pcmcia_fix_string(card_info.pd_bind_name);
3125 				} else {
3126 					/*
3127 					 * have a CIS but not the right info
3128 					 * so treat as generic "pccard"
3129 					 */
3130 					(void) strcpy(card_info.pd_generic_name,
3131 					    "pccard,memory");
3132 					card_info.pd_flags |= PCM_NAME_GENERIC;
3133 					(void) strcpy(card_info.pd_bind_name,
3134 					    "pccard,memory");
3135 				}
3136 			}
3137 			pcmcia_init_devinfo(pdip, &card_info);
3138 		}
3139 		return;
3140 	}
3141 
3142 	pcmcia_init_devinfo(pdip, &card_info);
3143 }
3144 
3145 /*
3146  * pcmcia_init_devinfo()
3147  *	if there isn't a device info structure, create one
3148  *	if there is, we don't do much.
3149  *
3150  *	Note: this will need updating as 1275 finalizes their spec.
3151  */
3152 static void
pcmcia_init_devinfo(dev_info_t * pdip,struct pcm_device_info * info)3153 pcmcia_init_devinfo(dev_info_t *pdip, struct pcm_device_info *info)
3154 {
3155 	int unit;
3156 	dev_info_t *dip;
3157 	char *name;
3158 	struct pcmcia_parent_private *ppd;
3159 
3160 #if defined(PCMCIA_DEBUG)
3161 	if (pcmcia_debug)
3162 		cmn_err(CE_CONT, "init_devinfo(%s, %d)\n", info->pd_bind_name,
3163 		    info->pd_socket);
3164 #endif
3165 
3166 	/*
3167 	 * find out if there is already an instance of this
3168 	 * device.  We don't want to create a new one unnecessarily
3169 	 */
3170 	unit = CS_MAKE_SOCKET_NUMBER(info->pd_socket, info->pd_function);
3171 
3172 	dip = pcm_find_devinfo(pdip, info, unit);
3173 	if ((dip != NULL) && (ddi_getprop(DDI_DEV_T_NONE, dip,
3174 	    DDI_PROP_DONTPASS, PCM_DEV_SOCKET, -1) != -1)) {
3175 		/* it already exist but isn't a .conf file */
3176 
3177 #if defined(PCMCIA_DEBUG)
3178 		if (pcmcia_debug)
3179 			cmn_err(CE_CONT, "\tfound existing device node (%s)\n",
3180 			    ddi_get_name(dip));
3181 #endif
3182 		if (strlen(info->pd_vers1_name) > 0)
3183 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
3184 			    dip, PCM_DEV_MODEL, info->pd_vers1_name);
3185 
3186 		ppd = (struct pcmcia_parent_private *)
3187 		    ddi_get_parent_data(dip);
3188 
3189 		pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] =
3190 		    dip;
3191 
3192 		ppd->ppd_active = 1;
3193 
3194 		if (ndi_devi_online(dip, 0) == NDI_FAILURE) {
3195 			pcmcia_sockets[info->pd_socket]-> \
3196 			    ls_dip[info->pd_function] = NULL;
3197 			ppd->ppd_active = 0;
3198 		}
3199 	} else {
3200 
3201 		char *dtype;
3202 
3203 #if defined(PCMCIA_DEBUG)
3204 		if (pcmcia_debug)
3205 			cmn_err(CE_CONT, "pcmcia: create child [%s](%d): %s\n",
3206 			    info->pd_bind_name, info->pd_socket,
3207 			    info->pd_generic_name);
3208 #endif
3209 
3210 		if (info->pd_flags & PCM_NAME_GENERIC)
3211 			name = info->pd_generic_name;
3212 		else
3213 			name = info->pd_bind_name;
3214 
3215 		if (ndi_devi_alloc(pdip, name, (pnode_t)DEVI_SID_NODEID,
3216 		    &dip) !=
3217 		    NDI_SUCCESS) {
3218 			cmn_err(CE_WARN,
3219 			    "pcmcia: unable to create device [%s](%d)\n",
3220 			    name, info->pd_socket);
3221 			return;
3222 		}
3223 		/*
3224 		 * construct the "compatible" property if the device
3225 		 * has a generic name
3226 		 */
3227 		pcmcia_add_compatible(dip, info);
3228 
3229 		ppd = kmem_zalloc(sizeof (struct pcmcia_parent_private),
3230 		    KM_SLEEP);
3231 
3232 		ppd->ppd_socket = info->pd_socket;
3233 		ppd->ppd_function = info->pd_function;
3234 
3235 		/*
3236 		 * add the "socket" property
3237 		 * the value of this property contains the logical PCMCIA
3238 		 * socket number the device has been inserted in, along
3239 		 * with the function # if the device is part of a
3240 		 * multi-function device.
3241 		 */
3242 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
3243 		    PCM_DEV_SOCKET, unit);
3244 
3245 		if (info->pd_flags & PCM_MULTI_FUNCTION)
3246 			ppd->ppd_flags |= PPD_CARD_MULTI;
3247 
3248 		/*
3249 		 * determine all the properties we need for PPD
3250 		 * then create the properties
3251 		 */
3252 		/* socket is unique */
3253 		pcmcia_find_regs(dip, info, ppd);
3254 
3255 		ppd->ppd_intr = pcmcia_need_intr(unit, info);
3256 
3257 		if (ppd->ppd_nreg > 0)
3258 			(void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
3259 			    "reg", (int *)ppd->ppd_reg, ppd->ppd_nreg *
3260 			    sizeof (struct pcm_regs) / sizeof (int));
3261 		if (ppd->ppd_intr) {
3262 			(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip,
3263 			    "interrupts", ppd->ppd_intr);
3264 			ppd->ppd_intrspec =
3265 			    kmem_zalloc(sizeof (struct intrspec), KM_SLEEP);
3266 		}
3267 
3268 		/* set parent private - our own format */
3269 		ddi_set_parent_data(dip, (caddr_t)ppd);
3270 
3271 		/* init the device type */
3272 		if (info->pd_type >= 0 &&
3273 		    info->pd_type < (sizeof (pcmcia_dev_type) /
3274 		    (sizeof (char *))))
3275 			dtype = pcmcia_dev_type[info->pd_type];
3276 		else
3277 			dtype = "unknown";
3278 
3279 		if (strlen(info->pd_vers1_name) > 0)
3280 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
3281 			    dip, PCM_DEV_MODEL, info->pd_vers1_name);
3282 
3283 		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
3284 		    PCM_DEVICETYPE, dtype);
3285 
3286 		/* set PC Card as active and present in socket */
3287 		pcmcia_sockets[info->pd_socket]->ls_dip[info->pd_function] =
3288 		    dip;
3289 
3290 		ppd->ppd_active = 1;
3291 
3292 		/*
3293 		 * We should not call ndi_devi_online here if
3294 		 * pcmcia attach is in progress. This causes a deadlock.
3295 		 */
3296 		if (pcmcia_dip != dip) {
3297 			if (ndi_devi_online_async(dip, 0)
3298 			    != NDI_SUCCESS) {
3299 				pcmcia_sockets[info->pd_socket]->\
3300 				    ls_dip[info->pd_function] = NULL;
3301 				pcmcia_ppd_free(ppd);
3302 				(void) ndi_devi_free(dip);
3303 				return;
3304 			}
3305 		}
3306 
3307 #if defined(PCMCIA_DEBUG)
3308 	if (pcmcia_debug)
3309 		cmn_err(CE_CONT, "\tjust added \"active\" to %s in %d\n",
3310 		    ddi_get_name(dip), info->pd_socket);
3311 #endif
3312 	}
3313 
3314 	/*
3315 	 * inform the event manager that a child was added
3316 	 * to the device tree.
3317 	 */
3318 	pcm_event_manager(PCE_DEV_IDENT, unit, ddi_get_name(dip));
3319 
3320 #if defined(PCMCIA_DEBUG)
3321 	if (pcmcia_debug > 1) {
3322 		pcmcia_dump_minors(dip);
3323 	}
3324 #endif
3325 }
3326 
3327 /*
3328  * free any allocated parent-private data
3329  */
3330 static void
pcmcia_ppd_free(struct pcmcia_parent_private * ppd)3331 pcmcia_ppd_free(struct pcmcia_parent_private *ppd)
3332 {
3333 	size_t len;
3334 
3335 	if (ppd->ppd_nreg != 0) {
3336 		len = ppd->ppd_nreg * sizeof (uint32_t) * 3;
3337 		kmem_free(ppd->ppd_reg, len);
3338 		len = sizeof (struct pcm_regs) * ppd->ppd_nreg;
3339 		kmem_free(ppd->ppd_assigned, len);
3340 	}
3341 
3342 	/*
3343 	 * pcmcia only allocates 1 intrspec today
3344 	 */
3345 	if (ppd->ppd_intr != 0) {
3346 		len = sizeof (struct intrspec) * ppd->ppd_intr;
3347 		kmem_free(ppd->ppd_intrspec, len);
3348 	}
3349 
3350 	kmem_free(ppd, sizeof (*ppd));
3351 }
3352 
3353 
3354 /*
3355  * pcmcia_get_devinfo(socket)
3356  *	entry point to allow finding the device info structure
3357  *	for a given logical socket.  Used by event manager
3358  */
3359 dev_info_t *
pcmcia_get_devinfo(int socket)3360 pcmcia_get_devinfo(int socket)
3361 {
3362 	int func = CS_GET_FUNCTION_NUMBER(socket);
3363 	socket = CS_GET_SOCKET_NUMBER(socket);
3364 	if (pcmcia_sockets[socket])
3365 		return (pcmcia_sockets[socket]->ls_dip[func]);
3366 	return ((dev_info_t *)NULL);
3367 }
3368 
3369 /*
3370  * CSGetCookiesAndDip()
3371  *	get info needed by CS to setup soft interrupt handler and provide
3372  *		socket-specific adapter information
3373  */
3374 static int
GetCookiesAndDip(sservice_t * serv)3375 GetCookiesAndDip(sservice_t *serv)
3376 {
3377 	pcmcia_logical_socket_t *socket;
3378 	csss_adapter_info_t *ai;
3379 	int sock;
3380 
3381 	sock = CS_GET_SOCKET_NUMBER(serv->get_cookies.socket);
3382 
3383 	if (sock >= pcmcia_num_sockets ||
3384 	    (int)serv->get_cookies.socket < 0)
3385 		return (BAD_SOCKET);
3386 
3387 	socket = pcmcia_sockets[sock];
3388 	ai = &serv->get_cookies.adapter_info;
3389 	serv->get_cookies.dip = socket->ls_adapter->pca_dip;
3390 	serv->get_cookies.iblock = socket->ls_adapter->pca_iblock;
3391 	serv->get_cookies.idevice = socket->ls_adapter->pca_idev;
3392 
3393 	/*
3394 	 * Setup the adapter info for Card Services
3395 	 */
3396 	(void) strcpy(ai->name, socket->ls_adapter->pca_name);
3397 	ai->major = socket->ls_adapter->pca_module;
3398 	ai->minor = socket->ls_adapter->pca_unit;
3399 	ai->number = socket->ls_adapter->pca_number;
3400 	ai->num_sockets = socket->ls_adapter->pca_numsockets;
3401 	ai->first_socket = socket->ls_adapter->pca_first_socket;
3402 
3403 	return (SUCCESS);
3404 }
3405 
3406 /*
3407  * Note:
3408  *	The following functions that start with 'SS'
3409  *	implement SocketServices interfaces.  They
3410  *	simply map the socket and/or window number to
3411  *	the adapter specific number based on the general
3412  *	value that CardServices uses.
3413  *
3414  *	See the descriptions in SocketServices for
3415  *	details.  Also refer to specific adapter drivers
3416  *	for implementation reference.
3417  */
3418 
3419 static int
SSGetAdapter(get_adapter_t * adapter)3420 SSGetAdapter(get_adapter_t *adapter)
3421 {
3422 	int n;
3423 	get_adapter_t info;
3424 
3425 	adapter->state = (unsigned)0xFFFFFFFF;
3426 	adapter->SCRouting = 0xFFFFFFFF;
3427 
3428 	for (n = 0; n < pcmcia_num_adapters; n++) {
3429 		GET_ADAPTER(pcmcia_adapters[n]->pca_if,
3430 		    pcmcia_adapters[n]->pca_dip, &info);
3431 		adapter->state &= info.state;
3432 		adapter->SCRouting &= info.SCRouting;
3433 	}
3434 
3435 	return (SUCCESS);
3436 }
3437 
3438 static int
SSGetPage(get_page_t * page)3439 SSGetPage(get_page_t *page)
3440 {
3441 	pcmcia_logical_window_t *window;
3442 	get_page_t newpage;
3443 	int retval, win;
3444 
3445 	if (page->window > pcmcia_num_windows) {
3446 		return (BAD_WINDOW);
3447 	}
3448 
3449 	window = pcmcia_windows[page->window];
3450 	newpage = *page;
3451 	win = newpage.window = window->lw_window; /* real window */
3452 
3453 	retval = GET_PAGE(window->lw_if, window->lw_adapter->pca_dip,
3454 	    &newpage);
3455 	if (retval == SUCCESS) {
3456 		*page = newpage;
3457 		page->window = win;
3458 	}
3459 	return (retval);
3460 }
3461 
3462 static int
SSGetSocket(get_socket_t * socket)3463 SSGetSocket(get_socket_t *socket)
3464 {
3465 	int retval, sock;
3466 	get_socket_t newsocket;
3467 	pcmcia_logical_socket_t *sockp;
3468 
3469 	sock = socket->socket;
3470 	if (sock > pcmcia_num_sockets ||
3471 	    (sockp = pcmcia_sockets[sock]) == NULL) {
3472 		return (BAD_SOCKET);
3473 	}
3474 
3475 	newsocket = *socket;
3476 	newsocket.socket = sockp->ls_socket;
3477 	retval = GET_SOCKET(sockp->