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