xref: /titanic_44/usr/src/uts/sun4u/io/pci/simba.c (revision 587032cf0967234b39ccb50adca936a367841063)
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 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  *	PCI to PCI bus bridge nexus driver
30  */
31 
32 #include <sys/conf.h>
33 #include <sys/kmem.h>
34 #include <sys/debug.h>
35 #include <sys/modctl.h>
36 #include <sys/autoconf.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/ddi_subrdefs.h>
39 #include <sys/ddifm.h>
40 #include <sys/fm/util.h>
41 #include <sys/fm/protocol.h>
42 #include <sys/fm/io/pci.h>
43 #include <sys/pci.h>
44 #include <sys/pci/pci_nexus.h>
45 #include <sys/pci/pci_regs.h>
46 #include <sys/pci/pci_simba.h>
47 #include <sys/ddi.h>
48 #include <sys/sunddi.h>
49 #include <sys/sunndi.h>
50 #include <sys/promif.h>		/* prom_printf */
51 #include <sys/open.h>
52 #include <sys/stat.h>
53 #include <sys/file.h>
54 
55 #if defined(DEBUG) && !defined(lint)
56 static uint_t simba_debug_flags = 0;
57 #define	D_IDENTIFY	0x00000001
58 #define	D_ATTACH	0x00000002
59 #define	D_DETACH	0x00000004
60 #define	D_MAP		0x00000008
61 #define	D_CTLOPS	0x00000010
62 #define	D_G_ISPEC	0x00000020
63 #define	D_A_ISPEC	0x00000040
64 #define	D_INIT_CLD	0x00400000
65 #define	D_FAULT		0x00000080
66 
67 #define	DEBUG0(f, s) if ((f)& simba_debug_flags) \
68 	prom_printf("simba: " s "\n")
69 
70 #define	DEBUG1(f, s, a) if ((f)& simba_debug_flags) \
71 	prom_printf("simba: " s "\n", a)
72 
73 #define	DEBUG2(f, s, a, b) if ((f)& simba_debug_flags) \
74 	prom_printf("simba: " s "\n", a, b)
75 
76 #define	DEBUG3(f, s, a, b, c) if ((f)& simba_debug_flags) \
77 	prom_printf("simba: " s "\n", a, b, c)
78 
79 #define	DEBUG4(f, s, a, b, c, d) if ((f)& simba_debug_flags) \
80 	prom_printf("simba: " s "\n", a, b, c, d)
81 
82 #define	DEBUG5(f, s, a, b, c, d, e) if ((f)& simba_debug_flags) \
83 	prom_printf("simba: " s "\n", a, b, c, d, e)
84 
85 #define	DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& simba_debug_flags) \
86 	prom_printf("simba: " s "\n", a, b, c, d, e, ff)
87 
88 #else
89 
90 #define	DEBUG0(f, s)
91 #define	DEBUG1(f, s, a)
92 #define	DEBUG2(f, s, a, b)
93 #define	DEBUG3(f, s, a, b, c)
94 #define	DEBUG4(f, s, a, b, c, d)
95 #define	DEBUG5(f, s, a, b, c, d, e)
96 #define	DEBUG6(f, s, a, b, c, d, e, ff)
97 
98 #endif
99 
100 /*
101  * The variable controls the default setting of the command register
102  * for pci devices.  See simba_initchild() for details.
103  */
104 static ushort_t simba_command_default = PCI_COMM_SERR_ENABLE |
105 					PCI_COMM_WAIT_CYC_ENAB |
106 					PCI_COMM_PARITY_DETECT |
107 					PCI_COMM_ME |
108 					PCI_COMM_MAE |
109 					PCI_COMM_IO;
110 
111 static int simba_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
112 	off_t, off_t, caddr_t *);
113 static int simba_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
114 	void *, void *);
115 static int simba_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
116 		ddi_iblock_cookie_t *ibc);
117 static void simba_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle);
118 static void simba_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle);
119 
120 struct bus_ops simba_bus_ops = {
121 	BUSO_REV,
122 	simba_bus_map,
123 	0,
124 	0,
125 	0,
126 	i_ddi_map_fault,
127 	ddi_dma_map,
128 	ddi_dma_allochdl,
129 	ddi_dma_freehdl,
130 	ddi_dma_bindhdl,
131 	ddi_dma_unbindhdl,
132 	ddi_dma_flush,
133 	ddi_dma_win,
134 	ddi_dma_mctl,
135 	simba_ctlops,
136 	ddi_bus_prop_op,
137 	ndi_busop_get_eventcookie,
138 	ndi_busop_add_eventcall,
139 	ndi_busop_remove_eventcall,
140 	ndi_post_event,
141 	0,
142 	0,
143 	0,
144 	simba_fm_init_child,
145 	NULL,
146 	simba_bus_enter,
147 	simba_bus_exit,
148 	0,
149 	i_ddi_intr_ops
150 };
151 
152 static int simba_open(dev_t *devp, int flags, int otyp, cred_t *credp);
153 static int simba_close(dev_t dev, int flags, int otyp, cred_t *credp);
154 static int simba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
155     cred_t *credp, int *rvalp);
156 
157 static struct cb_ops simba_cb_ops = {
158 	simba_open,			/* open */
159 	simba_close,			/* close */
160 	nulldev,			/* strategy */
161 	nulldev,			/* print */
162 	nulldev,			/* dump */
163 	nulldev,			/* read */
164 	nulldev,			/* write */
165 	simba_ioctl,			/* ioctl */
166 	nodev,				/* devmap */
167 	nodev,				/* mmap */
168 	nodev,				/* segmap */
169 	nochpoll,			/* poll */
170 	ddi_prop_op,			/* cb_prop_op */
171 	NULL,				/* streamtab */
172 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
173 	CB_REV,				/* rev */
174 	nodev,				/* int (*cb_aread)() */
175 	nodev				/* int (*cb_awrite)() */
176 };
177 
178 static int simba_probe(dev_info_t *);
179 static int simba_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
180 static int simba_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
181 static int simba_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
182 	void *arg, void **result);
183 
184 struct dev_ops simba_ops = {
185 	DEVO_REV,		/* devo_rev */
186 	0,			/* refcnt  */
187 	simba_info,		/* info */
188 	nulldev,		/* identify */
189 	simba_probe,		/* probe */
190 	simba_attach,		/* attach */
191 	simba_detach,		/* detach */
192 	nulldev,		/* reset */
193 	&simba_cb_ops,		/* driver operations */
194 	&simba_bus_ops		/* bus operations */
195 
196 };
197 
198 /*
199  * Module linkage information for the kernel.
200  */
201 
202 static struct modldrv modldrv = {
203 	&mod_driverops, /* Type of module */
204 	"SIMBA PCI to PCI bridge nexus driver %I%",
205 	&simba_ops,	/* driver ops */
206 };
207 
208 static struct modlinkage modlinkage = {
209 	MODREV_1,
210 	(void *)&modldrv,
211 	NULL
212 };
213 
214 /*
215  * Simba specific error state structure
216  */
217 struct simba_errstate {
218 	char *error;
219 	ushort_t pci_cfg_stat;
220 	ushort_t pci_cfg_sec_stat;
221 	uint64_t afsr;
222 	uint64_t afar;
223 	int bridge_secondary;
224 };
225 
226 struct simba_cfg_state {
227 	dev_info_t *dip;
228 	ushort_t command;
229 	uchar_t cache_line_size;
230 	uchar_t latency_timer;
231 	uchar_t header_type;
232 	uchar_t bus_number;
233 	uchar_t sec_bus_number;
234 	uchar_t sub_bus_number;
235 	uchar_t sec_latency_timer;
236 	ushort_t bridge_control;
237 };
238 
239 /*
240  * soft state pointer and structure template:
241  */
242 static void *simba_state;
243 
244 typedef struct {
245 
246 	dev_info_t *dip;
247 
248 	/*
249 	 * configuration register state for the bus:
250 	 */
251 	ddi_acc_handle_t config_handle;
252 	uchar_t simba_cache_line_size;
253 	uchar_t simba_latency_timer;
254 
255 	/*
256 	 * cpr support:
257 	 */
258 	uint_t config_state_index;
259 	struct simba_cfg_state *simba_config_state_p;
260 	ddi_iblock_cookie_t fm_ibc;
261 	int fm_cap;
262 	kmutex_t simba_mutex;
263 	uint_t simba_soft_state;
264 #define	SIMBA_SOFT_STATE_CLOSED		0x00
265 #define	SIMBA_SOFT_STATE_OPEN		0x01
266 #define	SIMBA_SOFT_STATE_OPEN_EXCL	0x02
267 } simba_devstate_t;
268 
269 /*
270  * The following variable enables a workaround for the following obp bug:
271  *
272  *	1234181 - obp should set latency timer registers in pci
273  *		configuration header
274  *
275  * Until this bug gets fixed in the obp, the following workaround should
276  * be enabled.
277  */
278 static uint_t simba_set_latency_timer_register = 1;
279 
280 /*
281  * The following variable enables a workaround for an obp bug to be
282  * submitted.  A bug requesting a workaround fof this problem has
283  * been filed:
284  *
285  *	1235094 - need workarounds on positron nexus drivers to set cache
286  *		line size registers
287  *
288  * Until this bug gets fixed in the obp, the following workaround should
289  * be enabled.
290  */
291 static uint_t simba_set_cache_line_size_register = 1;
292 
293 
294 /*
295  * forward function declarations:
296  */
297 static void simba_uninitchild(dev_info_t *);
298 static int simba_initchild(dev_info_t *child);
299 static void simba_save_config_regs(simba_devstate_t *simba_p);
300 static void simba_restore_config_regs(simba_devstate_t *simba_p);
301 static int simba_err_callback(dev_info_t *dip, ddi_fm_error_t *derr,
302 		const void *impl_data);
303 
304 int
305 _init(void)
306 {
307 	int e;
308 
309 	DEBUG0(D_ATTACH, "_init() installing module...\n");
310 	if ((e = ddi_soft_state_init(&simba_state, sizeof (simba_devstate_t),
311 	    1)) == 0 && (e = mod_install(&modlinkage)) != 0)
312 		ddi_soft_state_fini(&simba_state);
313 
314 	DEBUG0(D_ATTACH, "_init() module installed\n");
315 	return (e);
316 }
317 
318 int
319 _fini(void)
320 {
321 	int e;
322 	DEBUG0(D_ATTACH, "_fini() removing module...\n");
323 	if ((e = mod_remove(&modlinkage)) == 0)
324 		ddi_soft_state_fini(&simba_state);
325 	return (e);
326 }
327 
328 int
329 _info(struct modinfo *modinfop)
330 {
331 	DEBUG0(D_ATTACH, "_info() called.\n");
332 	return (mod_info(&modlinkage, modinfop));
333 }
334 
335 /*ARGSUSED*/
336 static int
337 simba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
338 {
339 	simba_devstate_t *simba_p;	/* per simba state pointer */
340 	int instance;
341 
342 	instance = getminor((dev_t)arg);
343 	simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state,
344 	    instance);
345 
346 	switch (infocmd) {
347 	default:
348 		return (DDI_FAILURE);
349 
350 	case DDI_INFO_DEVT2INSTANCE:
351 		*result = (void *)(uintptr_t)instance;
352 		return (DDI_SUCCESS);
353 
354 	case DDI_INFO_DEVT2DEVINFO:
355 		if (simba_p == NULL)
356 			return (DDI_FAILURE);
357 		*result = (void *)simba_p->dip;
358 		return (DDI_SUCCESS);
359 	}
360 }
361 
362 /*ARGSUSED*/
363 static int
364 simba_probe(register dev_info_t *devi)
365 {
366 	DEBUG0(D_ATTACH, "simba_probe() called.\n");
367 	return (DDI_PROBE_SUCCESS);
368 }
369 
370 /*ARGSUSED*/
371 static int
372 simba_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
373 {
374 	int instance;
375 	simba_devstate_t *simba;
376 
377 	switch (cmd) {
378 	case DDI_ATTACH:
379 
380 		DEBUG1(D_ATTACH, "attach(%p) ATTACH\n", devi);
381 
382 		/*
383 		 * Make sure the "device_type" property exists.
384 		 */
385 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
386 			"device_type", "pci");
387 
388 		/*
389 		 * Allocate and get soft state structure.
390 		 */
391 		instance = ddi_get_instance(devi);
392 		if (ddi_soft_state_zalloc(simba_state, instance) != DDI_SUCCESS)
393 			return (DDI_FAILURE);
394 		simba = (simba_devstate_t *)ddi_get_soft_state(simba_state,
395 		    instance);
396 		simba->dip = devi;
397 		mutex_init(&simba->simba_mutex, NULL, MUTEX_DRIVER, NULL);
398 		simba->simba_soft_state = SIMBA_SOFT_STATE_CLOSED;
399 
400 		/*
401 		 * create minor node for devctl interfaces
402 		 */
403 		if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance,
404 		    DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
405 			mutex_destroy(&simba->simba_mutex);
406 			ddi_soft_state_free(simba_state, instance);
407 			return (DDI_FAILURE);
408 		}
409 
410 		if (pci_config_setup(devi, &simba->config_handle) !=
411 		    DDI_SUCCESS) {
412 			ddi_remove_minor_node(devi, "devctl");
413 			mutex_destroy(&simba->simba_mutex);
414 			ddi_soft_state_free(simba_state, instance);
415 			return (DDI_FAILURE);
416 		}
417 
418 		/*
419 		 * Simba cache line size is 64 bytes and hardwired.
420 		 */
421 		simba->simba_cache_line_size =
422 		    pci_config_get8(simba->config_handle,
423 			PCI_CONF_CACHE_LINESZ);
424 		simba->simba_latency_timer =
425 		    pci_config_get8(simba->config_handle,
426 			PCI_CONF_LATENCY_TIMER);
427 
428 		/* simba specific, clears up the pri/sec status registers */
429 		pci_config_put16(simba->config_handle, 0x6, 0xffff);
430 		pci_config_put16(simba->config_handle, 0x1e, 0xffff);
431 
432 		DEBUG2(D_ATTACH, "simba_attach(): clsz=%x, lt=%x\n",
433 			simba->simba_cache_line_size,
434 			simba->simba_latency_timer);
435 
436 		/*
437 		 * Initialize FMA support
438 		 */
439 		simba->fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
440 			DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
441 
442 		/*
443 		 * Call parent to get it's capablity
444 		 */
445 		ddi_fm_init(devi, &simba->fm_cap, &simba->fm_ibc);
446 
447 		ASSERT((simba->fm_cap & DDI_FM_ERRCB_CAPABLE) &&
448 		    (simba->fm_cap & DDI_FM_EREPORT_CAPABLE));
449 
450 		pci_ereport_setup(devi);
451 
452 		ddi_fm_handler_register(devi, simba_err_callback, simba);
453 
454 		ddi_report_dev(devi);
455 		DEBUG0(D_ATTACH, "attach(): ATTACH done\n");
456 		return (DDI_SUCCESS);
457 
458 	case DDI_RESUME:
459 
460 		/*
461 		 * Get the soft state structure for the bridge.
462 		 */
463 		simba = (simba_devstate_t *)
464 			ddi_get_soft_state(simba_state, ddi_get_instance(devi));
465 		simba_restore_config_regs(simba);
466 		return (DDI_SUCCESS);
467 	}
468 	return (DDI_FAILURE);
469 }
470 
471 /*ARGSUSED*/
472 static int
473 simba_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
474 {
475 	simba_devstate_t *simba;
476 	simba = (simba_devstate_t *)
477 		ddi_get_soft_state(simba_state, ddi_get_instance(devi));
478 
479 	switch (cmd) {
480 	case DDI_DETACH:
481 		DEBUG0(D_DETACH, "detach() called\n");
482 		ddi_fm_handler_unregister(devi);
483 		pci_ereport_teardown(devi);
484 		ddi_fm_fini(devi);
485 		pci_config_teardown(&simba->config_handle);
486 		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");
487 		ddi_remove_minor_node(devi, "devctl");
488 		mutex_destroy(&simba->simba_mutex);
489 		ddi_soft_state_free(simba_state, ddi_get_instance(devi));
490 		return (DDI_SUCCESS);
491 
492 	case DDI_SUSPEND:
493 		simba_save_config_regs(simba);
494 		return (DDI_SUCCESS);
495 	}
496 	return (DDI_FAILURE);
497 }
498 
499 /*ARGSUSED*/
500 static int
501 simba_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
502 	off_t offset, off_t len, caddr_t *vaddrp)
503 {
504 	register dev_info_t *pdip;
505 
506 	DEBUG3(D_MAP, "simba_bus_map(): dip=%p, rdip=%p, mp=%p", dip, rdip, mp);
507 	DEBUG3(D_MAP, "simba_bus_map(): offset=%lx, len=%lx, vaddrp=%p",
508 	    offset, len, vaddrp);
509 
510 	pdip = (dev_info_t *)DEVI(dip)->devi_parent;
511 	return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
512 	    (pdip, rdip, mp, offset, len, vaddrp));
513 }
514 
515 /*
516  * Registered error handling callback with our parent
517  */
518 static int
519 simba_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
520 {
521 	simba_devstate_t *simba = (simba_devstate_t *)impl_data;
522 	struct simba_errstate simba_err;
523 	int ret = 0;
524 
525 	bzero(&simba_err, sizeof (struct simba_errstate));
526 	simba_err.afsr = pci_config_get64(simba->config_handle, 0xe8);
527 	simba_err.afar = pci_config_get64(simba->config_handle, 0xf0);
528 	derr->fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
529 
530 	pci_ereport_post(dip, derr, NULL);
531 	ret = derr->fme_status;
532 
533 	DEBUG6(D_FAULT, "%s-%d: cleaning up fault bits %x %x %x.%8x\n",
534 	    ddi_driver_name(simba->dip), ddi_get_instance(simba->dip),
535 	    simba_err.pci_cfg_stat, simba_err.pci_cfg_sec_stat,
536 	    (uint_t)(simba_err.afsr >> 32), (uint_t)simba_err.afsr);
537 	pci_config_put64(simba->config_handle, 0xe8, simba_err.afsr);
538 
539 	return (ret);
540 }
541 
542 #if defined(DEBUG) && !defined(lint)
543 static char *ops[] =
544 {
545 	"DDI_CTLOPS_DMAPMAPC",
546 	"DDI_CTLOPS_INITCHILD",
547 	"DDI_CTLOPS_UNINITCHILD",
548 	"DDI_CTLOPS_REPORTDEV",
549 	"DDI_CTLOPS_REPORTINT",
550 	"DDI_CTLOPS_REGSIZE",
551 	"DDI_CTLOPS_NREGS",
552 	"DDI_CTLOPS_RESERVED0",
553 	"DDI_CTLOPS_SIDDEV",
554 	"DDI_CTLOPS_SLAVEONLY",
555 	"DDI_CTLOPS_AFFINITY",
556 	"DDI_CTLOPS_IOMIN",
557 	"DDI_CTLOPS_PTOB",
558 	"DDI_CTLOPS_BTOP",
559 	"DDI_CTLOPS_BTOPR",
560 	"DDI_CTLOPS_RESERVED1",
561 	"DDI_CTLOPS_RESERVED2",
562 	"DDI_CTLOPS_RESERVED3",
563 	"DDI_CTLOPS_RESERVED4",
564 	"DDI_CTLOPS_RESERVED5",
565 	"DDI_CTLOPS_DVMAPAGESIZE",
566 	"DDI_CTLOPS_POWER",
567 	"DDI_CTLOPS_ATTACH",
568 	"DDI_CTLOPS_DETACH",
569 	"DDI_CTLOPS_POKE",
570 	"DDI_CTLOPS_PEEK"
571 };
572 #endif
573 
574 /*ARGSUSED*/
575 static int
576 simba_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
577 	void *arg, void *result)
578 {
579 	int reglen;
580 	int rn;
581 	int totreg;
582 	pci_regspec_t *drv_regp;
583 
584 	DEBUG6(D_CTLOPS,
585 		"simba_ctlops(): dip=%p rdip=%p ctlop=%x-%s arg=%p result=%p",
586 		dip, rdip, ctlop, ctlop < (sizeof (ops) / sizeof (ops[0])) ?
587 		ops[ctlop] : "Unknown", arg, result);
588 
589 	switch (ctlop) {
590 	case DDI_CTLOPS_REPORTDEV:
591 		if (rdip == (dev_info_t *)0)
592 			return (DDI_FAILURE);
593 		cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
594 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
595 		    ddi_driver_name(rdip),
596 		    ddi_get_instance(rdip));
597 		return (DDI_SUCCESS);
598 
599 	case DDI_CTLOPS_INITCHILD:
600 		return (simba_initchild((dev_info_t *)arg));
601 
602 	case DDI_CTLOPS_UNINITCHILD:
603 		simba_uninitchild((dev_info_t *)arg);
604 		return (DDI_SUCCESS);
605 
606 	case DDI_CTLOPS_SIDDEV:
607 		return (DDI_SUCCESS);
608 
609 	case DDI_CTLOPS_REGSIZE:
610 	case DDI_CTLOPS_NREGS:
611 		if (rdip == (dev_info_t *)0)
612 			return (DDI_FAILURE);
613 		break;
614 
615 	default:
616 		DEBUG0(D_CTLOPS, "simba_ctlops(): calling ddi_ctlops()");
617 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
618 	}
619 
620 	*(int *)result = 0;
621 	if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
622 		DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
623 		(caddr_t)&drv_regp, &reglen) != DDI_SUCCESS)
624 		return (DDI_FAILURE);
625 
626 	totreg = reglen / sizeof (pci_regspec_t);
627 	if (ctlop == DDI_CTLOPS_NREGS)
628 		*(int *)result = totreg;
629 	else if (ctlop == DDI_CTLOPS_REGSIZE) {
630 		rn = *(int *)arg;
631 		if (rn >= totreg) {
632 			kmem_free(drv_regp, reglen);
633 			return (DDI_FAILURE);
634 		}
635 		*(off_t *)result = drv_regp[rn].pci_size_low |
636 			((uint64_t)drv_regp[rn].pci_size_hi << 32);
637 	}
638 
639 	kmem_free(drv_regp, reglen);
640 	DEBUG1(D_CTLOPS, "simba_ctlops(): *result=%lx\n", *(off_t *)result);
641 	return (DDI_SUCCESS);
642 }
643 
644 static int
645 simba_name_child(dev_info_t *child, char *name, int namelen)
646 {
647 	uint_t n, slot, func;
648 	pci_regspec_t *pci_rp;
649 
650 	if (ndi_dev_is_persistent_node(child) == 0) {
651 		char **unit_addr;
652 
653 		/* name .conf nodes by "unit-address" property" */
654 		if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
655 		    DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
656 		    DDI_PROP_SUCCESS) {
657 			cmn_err(CE_WARN, "cannot name node from %s.conf",
658 			    ddi_driver_name(child));
659 			return (DDI_FAILURE);
660 		}
661 		if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
662 			cmn_err(CE_WARN, "unit-address property in %s.conf"
663 			    " not well-formed", ddi_driver_name(child));
664 			ddi_prop_free(unit_addr);
665 			return (DDI_FAILURE);
666 		}
667 
668 		(void) snprintf(name, namelen, "%s", *unit_addr);
669 		ddi_prop_free(unit_addr);
670 		return (DDI_SUCCESS);
671 	}
672 
673 	/* name hardware nodes by "reg" property */
674 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 0, "reg",
675 	    (int **)&pci_rp, &n) != DDI_SUCCESS)
676 		return (DDI_FAILURE);
677 
678 	/* get the device identifications */
679 	slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
680 	func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
681 
682 	if (func != 0)
683 		(void) snprintf(name, namelen, "%x,%x", slot, func);
684 	else
685 		(void) snprintf(name, namelen, "%x", slot);
686 
687 	ddi_prop_free(pci_rp);
688 	return (DDI_SUCCESS);
689 }
690 
691 static int
692 simba_initchild(dev_info_t *child)
693 {
694 	char name[MAXNAMELEN];
695 	int i;
696 	ddi_acc_handle_t config_handle;
697 	ushort_t command_preserve, command;
698 	uchar_t header_type;
699 	uchar_t min_gnt, latency_timer;
700 	simba_devstate_t *simba;
701 	uint_t n;
702 
703 	DEBUG1(D_INIT_CLD, "simba_initchild(): child=%p\n", child);
704 
705 	/*
706 	 * Pseudo nodes indicate a prototype node with per-instance
707 	 * properties to be merged into the real h/w device node.
708 	 * The interpretation of the unit-address is DD[,F]
709 	 * where DD is the device id and F is the function.
710 	 */
711 	if (ndi_dev_is_persistent_node(child) == 0) {
712 		extern int pci_allow_pseudo_children;
713 		pci_regspec_t *pci_rp;
714 
715 		if (ddi_getlongprop(DDI_DEV_T_ANY, child,
716 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, &i) ==
717 		    DDI_SUCCESS) {
718 			cmn_err(CE_WARN,
719 			    "cannot merge prototype from %s.conf",
720 			    ddi_driver_name(child));
721 			kmem_free(pci_rp, i);
722 			return (DDI_NOT_WELL_FORMED);
723 		}
724 
725 		if (simba_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
726 			return (DDI_NOT_WELL_FORMED);
727 
728 		ddi_set_name_addr(child, name);
729 		ddi_set_parent_data(child, NULL);
730 
731 		/*
732 		 * Try to merge the properties from this prototype
733 		 * node into real h/w nodes.
734 		 */
735 		if (ndi_merge_node(child, simba_name_child) == DDI_SUCCESS) {
736 			/*
737 			 * Merged ok - return failure to remove the node.
738 			 */
739 			simba_uninitchild(child);
740 			return (DDI_FAILURE);
741 		}
742 
743 		/* workaround for ddivs to run under PCI */
744 		if (pci_allow_pseudo_children)
745 			return (DDI_SUCCESS);
746 
747 		/*
748 		 * The child was not merged into a h/w node,
749 		 * but there's not much we can do with it other
750 		 * than return failure to cause the node to be removed.
751 		 */
752 		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
753 		    ddi_driver_name(child), ddi_get_name_addr(child),
754 		    ddi_driver_name(child));
755 		simba_uninitchild(child);
756 		return (DDI_NOT_WELL_FORMED);
757 	}
758 
759 	/*
760 	 * Initialize real h/w nodes
761 	 */
762 	if (simba_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
763 		return (DDI_FAILURE);
764 
765 	ddi_set_name_addr(child, name);
766 	ddi_set_parent_data(child, NULL);
767 
768 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
769 		simba_uninitchild(child);
770 		return (DDI_FAILURE);
771 	}
772 
773 	DEBUG0(D_INIT_CLD, "simba_initchild(): pci_config_setup success!\n");
774 
775 	/*
776 	 * Determine the configuration header type.
777 	 */
778 	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
779 
780 	/*
781 	 * Support for the "command-preserve" property.
782 	 */
783 	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
784 	    DDI_PROP_DONTPASS, "command-preserve", 0);
785 	command = pci_config_get16(config_handle, PCI_CONF_COMM);
786 	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
787 	command |= (simba_command_default & ~command_preserve);
788 	pci_config_put16(config_handle, PCI_CONF_COMM, command);
789 
790 	/* clean up all PCI child devices status register */
791 	pci_config_put16(config_handle, PCI_CONF_STAT, 0xffff);
792 
793 	/*
794 	 * If the device has a primary bus control register then program it
795 	 * based on the settings in the command register.
796 	 */
797 	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
798 		ushort_t bcr =
799 		    pci_config_get16(config_handle, PCI_BCNF_BCNTRL);
800 		if (simba_command_default & PCI_COMM_PARITY_DETECT)
801 			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
802 		if (simba_command_default & PCI_COMM_SERR_ENABLE)
803 			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
804 		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
805 		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
806 	}
807 
808 	simba = (simba_devstate_t *)ddi_get_soft_state(simba_state,
809 		ddi_get_instance(ddi_get_parent(child)));
810 	/*
811 	 * Initialize cache-line-size configuration register if needed.
812 	 */
813 	if (simba_set_cache_line_size_register &&
814 	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
815 		"cache-line-size", 0) == 0) {
816 		pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
817 		    simba->simba_cache_line_size);
818 		n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
819 		if (n != 0)
820 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
821 				"cache-line-size", n);
822 	}
823 
824 	/*
825 	 * Initialize latency timer configuration registers if needed.
826 	 */
827 	if (simba_set_latency_timer_register &&
828 	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
829 		"latency-timer", 0) == 0) {
830 
831 		if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
832 			latency_timer = simba->simba_latency_timer;
833 			pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
834 			    simba->simba_latency_timer);
835 		} else {
836 			min_gnt = pci_config_get8(config_handle,
837 			    PCI_CONF_MIN_G);
838 			latency_timer = min_gnt * 8;
839 		}
840 		pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
841 		    latency_timer);
842 		n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
843 		if (n != 0)
844 			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
845 			    "latency-timer", n);
846 	}
847 
848 	pci_config_teardown(&config_handle);
849 	DEBUG0(D_INIT_CLD, "simba_initchild(): pci_config_teardown called\n");
850 	return (DDI_SUCCESS);
851 }
852 
853 static void
854 simba_uninitchild(dev_info_t *dip)
855 {
856 	ddi_set_name_addr(dip, NULL);
857 
858 	/*
859 	 * Strip the node to properly convert it back to prototype form
860 	 */
861 	impl_rem_dev_props(dip);
862 }
863 
864 /*
865  * simba_save_config_regs
866  *
867  * This routine saves the state of the configuration registers of all
868  * the child nodes of each PBM.
869  *
870  * used by: simba_detach() on suspends
871  *
872  * return value: none
873  */
874 static void
875 simba_save_config_regs(simba_devstate_t *simba_p)
876 {
877 	int i;
878 	dev_info_t *dip;
879 	ddi_acc_handle_t ch;
880 	struct simba_cfg_state *statep;
881 
882 	for (i = 0, dip = ddi_get_child(simba_p->dip); dip != NULL;
883 		dip = ddi_get_next_sibling(dip)) {
884 		if (i_ddi_devi_attached(dip))
885 			i++;
886 	}
887 	if (!i)
888 		return;
889 	simba_p->simba_config_state_p =
890 		kmem_zalloc(i * sizeof (struct simba_cfg_state), KM_NOSLEEP);
891 	if (!simba_p->simba_config_state_p) {
892 		cmn_err(CE_WARN, "not enough memrory to save simba child\n");
893 		return;
894 	}
895 	simba_p->config_state_index = i;
896 
897 	for (statep = simba_p->simba_config_state_p,
898 		dip = ddi_get_child(simba_p->dip);
899 		dip != NULL;
900 		dip = ddi_get_next_sibling(dip)) {
901 
902 		if (!i_ddi_devi_attached(dip)) {
903 			DEBUG4(D_DETACH, "%s%d: skipping unattached %s%d\n",
904 				ddi_driver_name(simba_p->dip),
905 				ddi_get_instance(simba_p->dip),
906 				ddi_driver_name(dip),
907 				ddi_get_instance(dip));
908 			continue;
909 		}
910 
911 		DEBUG4(D_DETACH, "%s%d: saving regs for %s%d\n",
912 			ddi_driver_name(simba_p->dip),
913 			ddi_get_instance(simba_p->dip),
914 			ddi_driver_name(dip),
915 			ddi_get_instance(dip));
916 
917 		if (pci_config_setup(dip, &ch) != DDI_SUCCESS) {
918 			DEBUG4(D_DETACH, "%s%d: can't config space for %s%d\n",
919 				ddi_driver_name(simba_p->dip),
920 				ddi_get_instance(simba_p->dip),
921 				ddi_driver_name(dip),
922 				ddi_get_instance(dip));
923 			continue;
924 		}
925 
926 		DEBUG3(D_DETACH, "%s%d: saving child dip=%p\n",
927 			ddi_driver_name(simba_p->dip),
928 			ddi_get_instance(simba_p->dip),
929 			dip);
930 
931 		statep->dip = dip;
932 		statep->command = pci_config_get16(ch, PCI_CONF_COMM);
933 		statep->header_type = pci_config_get8(ch, PCI_CONF_HEADER);
934 		if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
935 			statep->bridge_control =
936 			    pci_config_get16(ch, PCI_BCNF_BCNTRL);
937 		statep->cache_line_size =
938 			pci_config_get8(ch, PCI_CONF_CACHE_LINESZ);
939 		statep->latency_timer =
940 			pci_config_get8(ch, PCI_CONF_LATENCY_TIMER);
941 		if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
942 			statep->sec_latency_timer =
943 				pci_config_get8(ch, PCI_BCNF_LATENCY_TIMER);
944 		/*
945 		 * Simba specific.
946 		 */
947 		if (pci_config_get16(ch, PCI_CONF_VENID) == PCI_SIMBA_VENID &&
948 		    pci_config_get16(ch, PCI_CONF_DEVID) == PCI_SIMBA_DEVID) {
949 
950 			statep->bus_number =
951 				pci_config_get8(ch, PCI_BCNF_PRIBUS);
952 			statep->sec_bus_number =
953 				pci_config_get8(ch, PCI_BCNF_SECBUS);
954 			statep->sub_bus_number =
955 				pci_config_get8(ch, PCI_BCNF_SUBBUS);
956 			statep->bridge_control =
957 				pci_config_get16(ch, PCI_BCNF_BCNTRL);
958 		}
959 		pci_config_teardown(&ch);
960 		statep++;
961 	}
962 }
963 
964 
965 /*
966  * simba_restore_config_regs
967  *
968  * This routine restores the state of the configuration registers of all
969  * the child nodes of each PBM.
970  *
971  * used by: simba_attach() on resume
972  *
973  * return value: none
974  */
975 static void
976 simba_restore_config_regs(simba_devstate_t *simba_p)
977 {
978 	int i;
979 	dev_info_t *dip;
980 	ddi_acc_handle_t ch;
981 	struct simba_cfg_state *statep = simba_p->simba_config_state_p;
982 	if (!simba_p->config_state_index)
983 		return;
984 
985 	for (i = 0; i < simba_p->config_state_index; i++, statep++) {
986 		dip = statep->dip;
987 		if (!dip) {
988 			cmn_err(CE_WARN,
989 				"%s%d: skipping bad dev info (%d)\n",
990 				ddi_driver_name(simba_p->dip),
991 				ddi_get_instance(simba_p->dip),
992 				i);
993 			continue;
994 		}
995 
996 		DEBUG5(D_ATTACH, "%s%d: restoring regs for %p-%s%d\n",
997 			ddi_driver_name(simba_p->dip),
998 			ddi_get_instance(simba_p->dip),
999 			dip,
1000 			ddi_driver_name(dip),
1001 			ddi_get_instance(dip));
1002 
1003 		if (pci_config_setup(dip, &ch) != DDI_SUCCESS) {
1004 			DEBUG4(D_ATTACH, "%s%d: can't config space for %s%d\n",
1005 				ddi_driver_name(simba_p->dip),
1006 				ddi_get_instance(simba_p->dip),
1007 				ddi_driver_name(dip),
1008 				ddi_get_instance(dip));
1009 			continue;
1010 		}
1011 		pci_config_put16(ch, PCI_CONF_COMM, statep->command);
1012 		if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
1013 			pci_config_put16(ch, PCI_BCNF_BCNTRL,
1014 				statep->bridge_control);
1015 		/*
1016 		 * Simba specific.
1017 		 */
1018 		if (pci_config_get16(ch, PCI_CONF_VENID) == PCI_SIMBA_VENID &&
1019 		    pci_config_get16(ch, PCI_CONF_DEVID) == PCI_SIMBA_DEVID) {
1020 			pci_config_put8(ch, PCI_BCNF_PRIBUS,
1021 				statep->bus_number);
1022 			pci_config_put8(ch, PCI_BCNF_SECBUS,
1023 				statep->sec_bus_number);
1024 			pci_config_put8(ch, PCI_BCNF_SUBBUS,
1025 				statep->sub_bus_number);
1026 			pci_config_put16(ch, PCI_BCNF_BCNTRL,
1027 				statep->bridge_control);
1028 		}
1029 
1030 		pci_config_put8(ch, PCI_CONF_CACHE_LINESZ,
1031 			statep->cache_line_size);
1032 		pci_config_put8(ch, PCI_CONF_LATENCY_TIMER,
1033 			statep->latency_timer);
1034 		if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE)
1035 			pci_config_put8(ch, PCI_BCNF_LATENCY_TIMER,
1036 				statep->sec_latency_timer);
1037 		pci_config_teardown(&ch);
1038 	}
1039 
1040 	kmem_free(simba_p->simba_config_state_p,
1041 		simba_p->config_state_index * sizeof (struct simba_cfg_state));
1042 	simba_p->simba_config_state_p = NULL;
1043 	simba_p->config_state_index = 0;
1044 }
1045 
1046 /* ARGSUSED */
1047 static int
1048 simba_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1049 {
1050 	simba_devstate_t *simba_p;
1051 
1052 	/*
1053 	 * Make sure the open is for the right file type.
1054 	 */
1055 	if (otyp != OTYP_CHR)
1056 		return (EINVAL);
1057 
1058 	/*
1059 	 * Get the soft state structure for the device.
1060 	 */
1061 	simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state,
1062 	    getminor(*devp));
1063 	if (simba_p == NULL)
1064 		return (ENXIO);
1065 
1066 	/*
1067 	 * Handle the open by tracking the device state.
1068 	 */
1069 	mutex_enter(&simba_p->simba_mutex);
1070 	if (flags & FEXCL) {
1071 		if (simba_p->simba_soft_state != SIMBA_SOFT_STATE_CLOSED) {
1072 			mutex_exit(&simba_p->simba_mutex);
1073 			return (EBUSY);
1074 		}
1075 		simba_p->simba_soft_state = SIMBA_SOFT_STATE_OPEN_EXCL;
1076 	} else {
1077 		if (simba_p->simba_soft_state == SIMBA_SOFT_STATE_OPEN_EXCL) {
1078 			mutex_exit(&simba_p->simba_mutex);
1079 			return (EBUSY);
1080 		}
1081 		simba_p->simba_soft_state = SIMBA_SOFT_STATE_OPEN;
1082 	}
1083 	mutex_exit(&simba_p->simba_mutex);
1084 	return (0);
1085 }
1086 
1087 
1088 /* ARGSUSED */
1089 static int
1090 simba_close(dev_t dev, int flags, int otyp, cred_t *credp)
1091 {
1092 	simba_devstate_t *simba_p;
1093 
1094 	if (otyp != OTYP_CHR)
1095 		return (EINVAL);
1096 
1097 	simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state,
1098 	    getminor(dev));
1099 	if (simba_p == NULL)
1100 		return (ENXIO);
1101 
1102 	mutex_enter(&simba_p->simba_mutex);
1103 	simba_p->simba_soft_state = SIMBA_SOFT_STATE_CLOSED;
1104 	mutex_exit(&simba_p->simba_mutex);
1105 	return (0);
1106 }
1107 
1108 
1109 /*
1110  * simba_ioctl: devctl hotplug controls
1111  */
1112 /* ARGSUSED */
1113 static int
1114 simba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1115 	int *rvalp)
1116 {
1117 	simba_devstate_t *simba_p;
1118 	dev_info_t *self;
1119 	struct devctl_iocdata *dcp;
1120 	uint_t bus_state;
1121 	int rv = 0;
1122 
1123 	simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state,
1124 	    getminor(dev));
1125 	if (simba_p == NULL)
1126 		return (ENXIO);
1127 
1128 	self = simba_p->dip;
1129 
1130 	/*
1131 	 * We can use the generic implementation for these ioctls
1132 	 */
1133 	switch (cmd) {
1134 	case DEVCTL_DEVICE_GETSTATE:
1135 	case DEVCTL_DEVICE_ONLINE:
1136 	case DEVCTL_DEVICE_OFFLINE:
1137 	case DEVCTL_BUS_GETSTATE:
1138 		return (ndi_devctl_ioctl(self, cmd, arg, mode, 0));
1139 	}
1140 
1141 	/*
1142 	 * read devctl ioctl data
1143 	 */
1144 	if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
1145 		return (EFAULT);
1146 
1147 	switch (cmd) {
1148 
1149 	case DEVCTL_DEVICE_RESET:
1150 		rv = ENOTSUP;
1151 		break;
1152 
1153 
1154 	case DEVCTL_BUS_QUIESCE:
1155 		if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1156 			if (bus_state == BUS_QUIESCED)
1157 				break;
1158 		(void) ndi_set_bus_state(self, BUS_QUIESCED);
1159 		break;
1160 
1161 	case DEVCTL_BUS_UNQUIESCE:
1162 		if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1163 			if (bus_state == BUS_ACTIVE)
1164 				break;
1165 		(void) ndi_set_bus_state(self, BUS_ACTIVE);
1166 		break;
1167 
1168 	case DEVCTL_BUS_RESET:
1169 		rv = ENOTSUP;
1170 		break;
1171 
1172 	case DEVCTL_BUS_RESETALL:
1173 		rv = ENOTSUP;
1174 		break;
1175 
1176 	default:
1177 		rv = ENOTTY;
1178 	}
1179 
1180 	ndi_dc_freehdl(dcp);
1181 	return (rv);
1182 }
1183 
1184 /*
1185  * Initialize FMA resources for children devices. Called when
1186  * child calls ddi_fm_init().
1187  */
1188 /*ARGSUSED*/
1189 static int
1190 simba_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
1191 		ddi_iblock_cookie_t *ibc)
1192 {
1193 	simba_devstate_t *simba_p = ddi_get_soft_state(simba_state,
1194 			ddi_get_instance(dip));
1195 
1196 	*ibc = simba_p->fm_ibc;
1197 	return (simba_p->fm_cap);
1198 }
1199 
1200 static void
1201 simba_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle)
1202 {
1203 	i_ndi_busop_access_enter(dip, handle);
1204 }
1205 
1206 /* ARGSUSED */
1207 static void
1208 simba_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle)
1209 {
1210 	i_ndi_busop_access_exit(dip, handle);
1211 }
1212