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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
30 #include <sys/types.h>
33 #include <sys/sunddi.h>
34 #include <sys/ddi_impldefs.h>
35 #include <sys/ddi_subrdefs.h>
37 #include <sys/autoconf.h>
38 #include <sys/cmn_err.h>
39 #include <sys/errno.h>
41 #include <sys/debug.h>
42 #include <sys/sysmacros.h>
47 #include <sys/sunndi.h>
50 uint64_t ebus_debug_flags
= 0;
54 * The values of the following variables are used to initialize
55 * the cache line size and latency timer registers in the ebus
56 * configuration header. Variables are used instead of constants
57 * to allow tuning from the /etc/system file.
59 static uint8_t ebus_cache_line_size
= 0x10; /* 64 bytes */
60 static uint8_t ebus_latency_timer
= 0x40; /* 64 PCI cycles */
63 * function prototypes for bus ops routines:
66 ebus_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
67 off_t offset
, off_t len
, caddr_t
*addrp
);
69 ebus_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
70 ddi_ctl_enum_t op
, void *arg
, void *result
);
72 ebus_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
73 ddi_intr_handle_impl_t
*hdlp
, void *result
);
76 * function prototypes for dev ops routines:
78 static int ebus_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
79 static int ebus_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
80 static int ebus_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
,
81 void *arg
, void **result
);
84 * general function prototypes:
86 static int ebus_config(ebus_devstate_t
*ebus_p
);
87 static int ebus_apply_range(ebus_devstate_t
*ebus_p
, dev_info_t
*rdip
,
88 ebus_regspec_t
*ebus_rp
, vregspec_t
*rp
);
89 int ebus_get_ranges_prop(ebus_devstate_t
*ebus_p
);
90 static void ebus_get_cells_prop(ebus_devstate_t
*ebus_p
);
91 static void ebus_vreg_dump(ebus_devstate_t
*ebus_p
, vregspec_t
*rp
);
93 #define getprop(dip, name, addr, intp) \
94 ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
95 (name), (caddr_t)(addr), (intp))
97 static int ebus_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
);
98 static int ebus_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
);
99 static int ebus_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
,
100 cred_t
*credp
, int *rvalp
);
101 struct cb_ops ebus_cb_ops
= {
102 ebus_open
, /* open */
103 ebus_close
, /* close */
104 nodev
, /* strategy */
109 ebus_ioctl
, /* ioctl */
114 ddi_prop_op
, /* cb_prop_op */
115 NULL
, /* streamtab */
116 D_NEW
| D_MP
| D_HOTPLUG
, /* Driver compatibility flag */
118 nodev
, /* int (*cb_aread)() */
119 nodev
/* int (*cb_awrite)() */
123 * bus ops and dev ops structures:
125 static struct bus_ops ebus_bus_ops
= {
142 ndi_busop_get_eventcookie
,
143 ndi_busop_add_eventcall
,
144 ndi_busop_remove_eventcall
,
157 static struct dev_ops ebus_ops
= {
169 ddi_quiesce_not_supported
, /* devo_quiesce */
173 * module definitions:
175 #include <sys/modctl.h>
176 extern struct mod_ops mod_driverops
;
178 static struct modldrv modldrv
= {
179 &mod_driverops
, /* Type of module. This one is a driver */
180 "ebus nexus driver", /* Name of module. */
181 &ebus_ops
, /* driver ops */
184 static struct modlinkage modlinkage
= {
185 MODREV_1
, (void *)&modldrv
, NULL
189 * driver global data:
191 static void *per_ebus_state
; /* per-ebus soft state pointer */
200 * Initialize per-ebus soft state pointer.
202 e
= ddi_soft_state_init(&per_ebus_state
, sizeof (ebus_devstate_t
), 1);
207 * Install the module.
209 e
= mod_install(&modlinkage
);
211 ddi_soft_state_fini(&per_ebus_state
);
223 e
= mod_remove(&modlinkage
);
228 * Free the soft state info.
230 ddi_soft_state_fini(&per_ebus_state
);
235 _info(struct modinfo
*modinfop
)
237 return (mod_info(&modlinkage
, modinfop
));
240 /* device driver entry points */
244 ebus_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
246 ebus_devstate_t
*ebus_p
; /* per ebus state pointer */
249 instance
= getminor((dev_t
)arg
);
250 ebus_p
= get_ebus_soft_state(instance
);
253 case DDI_INFO_DEVT2INSTANCE
:
254 *result
= (void *)(uintptr_t)instance
;
256 case DDI_INFO_DEVT2DEVINFO
:
258 return (DDI_FAILURE
);
259 *result
= (void *)ebus_p
->dip
;
262 return (DDI_FAILURE
);
265 return (DDI_SUCCESS
);
269 * attach entry point:
273 * create soft state structure (dip, reg, nreg and state fields)
274 * map in configuration header
275 * make sure device is properly configured
279 ebus_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
281 ebus_devstate_t
*ebus_p
; /* per ebus state pointer */
284 DBG1(D_ATTACH
, NULL
, "dip=%p\n", dip
);
290 * Allocate soft state for this instance.
292 instance
= ddi_get_instance(dip
);
293 if (ddi_soft_state_zalloc(per_ebus_state
, instance
)
295 DBG(D_ATTACH
, NULL
, "failed to alloc soft state\n");
296 return (DDI_FAILURE
);
298 ebus_p
= get_ebus_soft_state(instance
);
300 mutex_init(&ebus_p
->ebus_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
301 ebus_p
->ebus_soft_state
= EBUS_SOFT_STATE_CLOSED
;
303 ebus_get_cells_prop(ebus_p
);
305 (void) ddi_prop_create(DDI_DEV_T_NONE
, dip
,
306 DDI_PROP_CANSLEEP
, "no-dma-interrupt-sync", NULL
, 0);
307 /* Get our ranges property for mapping child registers. */
308 if (ebus_get_ranges_prop(ebus_p
) != DDI_SUCCESS
) {
313 * create minor node for devctl interfaces
315 if (ddi_create_minor_node(dip
, "devctl", S_IFCHR
, instance
,
316 DDI_NT_NEXUS
, 0) != DDI_SUCCESS
) {
320 if (ebus_config(ebus_p
) != DDI_SUCCESS
) {
321 ddi_remove_minor_node(dip
, "devctl");
326 * Make the pci_report_pmcap() call only for RIO
330 (void) pci_report_pmcap(dip
, PCI_PM_IDLESPEED
,
335 * Make the state as attached and report the device.
337 ebus_p
->state
= ATTACHED
;
339 DBG(D_ATTACH
, ebus_p
, "returning\n");
344 instance
= ddi_get_instance(dip
);
345 ebus_p
= get_ebus_soft_state(instance
);
347 (void) ebus_config(ebus_p
);
349 ebus_p
->state
= RESUMED
;
353 return (DDI_SUCCESS
);
356 mutex_destroy(&ebus_p
->ebus_mutex
);
357 free_ebus_soft_state(instance
);
358 return (DDI_FAILURE
);
362 * detach entry point:
365 ebus_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
367 int instance
= ddi_get_instance(dip
);
368 ebus_devstate_t
*ebus_p
= get_ebus_soft_state(instance
);
372 DBG1(D_DETACH
, ebus_p
, "DDI_DETACH dip=%p\n", dip
);
374 kmem_free(ebus_p
->vrangep
, ebus_p
->vrange_len
);
376 ddi_remove_minor_node(dip
, "devctl");
377 mutex_destroy(&ebus_p
->ebus_mutex
);
378 free_ebus_soft_state(instance
);
381 DBG1(D_DETACH
, ebus_p
, "DDI_SUSPEND dip=%p\n", dip
);
382 ebus_p
->state
= SUSPENDED
;
386 "failed to recognize ebus detach command\n");
387 return (DDI_FAILURE
);
389 return (DDI_SUCCESS
);
394 ebus_get_ranges_prop(ebus_devstate_t
*ebus_p
)
396 if (ddi_getlongprop(DDI_DEV_T_ANY
, ebus_p
->dip
, DDI_PROP_DONTPASS
,
397 "ranges", (caddr_t
)&ebus_p
->vrangep
, &ebus_p
->vrange_len
)
399 cmn_err(CE_WARN
, "Can't get %s ranges property",
400 ddi_get_name(ebus_p
->dip
));
401 return (DDI_ME_REGSPEC_RANGE
);
404 ebus_p
->vrange_cnt
= ebus_p
->vrange_len
/
405 (ebus_p
->ebus_paddr_cells
+ ebus_p
->ebus_addr_cells
+
406 ebus_p
->ebus_psz_cells
);
408 if (ebus_p
->vrange_cnt
== 0) {
409 kmem_free(ebus_p
->vrangep
, ebus_p
->vrange_len
);
410 DBG(D_ATTACH
, NULL
, "range is equal to zero\n");
411 return (DDI_FAILURE
);
414 return (DDI_SUCCESS
);
418 ebus_get_cells_prop(ebus_devstate_t
*ebus_p
)
420 dev_info_t
*dip
= ebus_p
->dip
;
423 ebus_p
->ebus_addr_cells
= ddi_getprop(DDI_DEV_T_ANY
,
424 dip
, DDI_PROP_DONTPASS
, "#address-cells", 2);
426 pdip
= ddi_get_parent(dip
);
427 ebus_p
->ebus_paddr_cells
= ddi_getprop(DDI_DEV_T_ANY
,
428 pdip
, DDI_PROP_DONTPASS
, "#address-cells", 2);
430 ASSERT((ebus_p
->ebus_paddr_cells
== 3) ||
431 (ebus_p
->ebus_paddr_cells
== 2));
433 ebus_p
->ebus_sz_cells
= ddi_getprop(DDI_DEV_T_ANY
,
434 dip
, DDI_PROP_DONTPASS
, "#size-cells", 2);
435 ebus_p
->ebus_psz_cells
= ddi_getprop(DDI_DEV_T_ANY
,
436 pdip
, DDI_PROP_DONTPASS
, "#size-cells", 1);
438 /* XXX rootnex assumes 1 cell and does not respect #size-cells */
439 if (ddi_root_node() == pdip
)
440 ebus_p
->ebus_psz_cells
= 1;
442 ASSERT((ebus_p
->ebus_psz_cells
== 2) ||
443 (ebus_p
->ebus_psz_cells
== 1));
447 /* bus driver entry points */
450 * bus map entry point:
452 * if map request is for an rnumber
453 * get the corresponding regspec from device node
454 * build a new regspec in our parent's format
455 * build a new map_req with the new regspec
456 * call up the tree to complete the mapping
459 ebus_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
460 off_t off
, off_t len
, caddr_t
*addrp
)
462 ebus_devstate_t
*ebus_p
= get_ebus_soft_state(ddi_get_instance(dip
));
463 ebus_regspec_t
*ebus_rp
, *ebus_regs
;
465 ddi_map_req_t p_map_request
;
467 int rval
= DDI_SUCCESS
;
470 * Handle the mapping according to its type.
472 DBG4(D_MAP
, ebus_p
, "rdip=%s%d: off=%x len=%x\n",
473 ddi_get_name(rdip
), ddi_get_instance(rdip
), off
, len
);
474 switch (mp
->map_type
) {
478 * We assume the register specification is in ebus format.
479 * We must convert it into a PCI format regspec and pass
480 * the request to our parent.
482 DBG3(D_MAP
, ebus_p
, "rdip=%s%d: REGSPEC - handlep=%p\n",
483 ddi_get_name(rdip
), ddi_get_instance(rdip
),
485 ebus_rp
= (ebus_regspec_t
*)mp
->map_obj
.rp
;
491 * Get the "reg" property from the device node and convert
492 * it to our parent's format.
494 rnumber
= mp
->map_obj
.rnumber
;
495 DBG4(D_MAP
, ebus_p
, "rdip=%s%d: rnumber=%x handlep=%p\n",
496 ddi_get_name(rdip
), ddi_get_instance(rdip
),
497 rnumber
, mp
->map_handlep
);
499 if (getprop(rdip
, "reg", &ebus_regs
, &i
) != DDI_SUCCESS
) {
500 DBG(D_MAP
, ebus_p
, "can't get reg property\n");
501 return (DDI_ME_RNUMBER_RANGE
);
504 n
= i
/ sizeof (ebus_regspec_t
);
506 if (rnumber
< 0 || rnumber
>= n
) {
507 DBG(D_MAP
, ebus_p
, "rnumber out of range\n");
508 return (DDI_ME_RNUMBER_RANGE
);
510 ebus_rp
= &ebus_regs
[rnumber
];
514 return (DDI_ME_INVAL
);
518 /* Adjust our reg property with offset and length */
519 ebus_rp
->addr_low
+= off
;
523 rval
= ebus_apply_range(ebus_p
, rdip
, ebus_rp
, &vreg
);
525 if (mp
->map_type
== DDI_MT_RNUMBER
)
526 kmem_free(ebus_regs
, i
);
528 if (rval
!= DDI_SUCCESS
)
532 p_map_request
.map_type
= DDI_MT_REGSPEC
;
534 p_map_request
.map_obj
.rp
= (struct regspec
*)&vreg
;
536 rval
= ddi_map(dip
, &p_map_request
, 0, 0, addrp
);
537 DBG1(D_MAP
, ebus_p
, "parent returned %x\n", rval
);
542 * ebus_apply_range generically relocates child's regspec to
543 * parent's format according to ebus' range spec
546 * - rng_caddr_hi is the space type
547 * - rng_caddr_low is the base address
548 * - ebus address is 32 bit and ebus entirely lives between 0-4G of
549 * parent space, so maths on preg/rng_cell_p[ebus_p->ebus_paddr_cells - 1],
550 * preg_cell_p[i], rng_caddr_low and ebus_rp->size are sufficient.
553 ebus_apply_range(ebus_devstate_t
*ebus_p
, dev_info_t
*rdip
,
554 ebus_regspec_t
*ebus_rp
, vregspec_t
*rp
) {
556 int nrange
= ebus_p
->vrange_cnt
;
557 uint32_t addr_offset
, rng_caddr_hi
, rng_caddr_low
, rng_sz
;
558 uint32_t req_addr
= ebus_rp
->addr_low
;
560 uint32_t *rng_cell_p
= (uint32_t *)ebus_p
->vrangep
;
561 int rng_rec_sz
= ebus_p
->ebus_paddr_cells
+ ebus_p
->ebus_addr_cells
+
562 ebus_p
->ebus_sz_cells
;
563 uint32_t *preg_cell_p
= (uint32_t *)rp
;
564 int preg_rec_sz
= ebus_p
->ebus_paddr_cells
+ ebus_p
->ebus_psz_cells
;
566 static char out_of_range
[] =
567 "Out of range register specification from device node <%s>";
569 DBG3(D_MAP
, ebus_p
, "Range Matching Addr 0x%x.%x size 0x%x\n",
570 ebus_rp
->addr_hi
, req_addr
, ebus_rp
->size
);
572 for (b
= 0; b
< nrange
; b
++, rng_cell_p
+= rng_rec_sz
) {
574 rng_caddr_hi
= rng_cell_p
[0];
575 rng_caddr_low
= rng_cell_p
[1];
576 rng_sz
= rng_cell_p
[rng_rec_sz
-1];
578 /* Check for correct space */
579 if (ebus_rp
->addr_hi
!= rng_caddr_hi
)
582 /* Detect whether request entirely fits within a range */
583 if (req_addr
< rng_caddr_low
)
586 if ((req_addr
+ ebus_rp
->size
- 1)
587 > (rng_caddr_low
+ rng_sz
- 1))
590 addr_offset
= req_addr
- rng_caddr_low
;
592 /* parent addr = child addr + offset from ranges */
593 for (i
= 0; i
< preg_rec_sz
; i
++)
596 /* Copy the physical address */
597 for (i
= 0; i
< ebus_p
->ebus_paddr_cells
; i
++)
598 preg_cell_p
[i
] = rng_cell_p
[ebus_p
->ebus_addr_cells
+i
];
600 preg_cell_p
[ebus_p
->ebus_paddr_cells
-1] += addr_offset
;
603 preg_cell_p
[preg_rec_sz
-1] = min(ebus_rp
->size
,
604 rng_sz
- addr_offset
);
607 ebus_vreg_dump(ebus_p
, (vregspec_t
*)preg_cell_p
);
614 cmn_err(CE_WARN
, out_of_range
, ddi_get_name(rdip
));
615 return (DDI_ME_REGSPEC_RANGE
);
618 return (DDI_SUCCESS
);
622 ebus_name_child(dev_info_t
*child
, char *name
, int namelen
)
624 ebus_regspec_t
*ebus_rp
;
628 * Get the address portion of the node name based on the
631 if (ddi_getlongprop(DDI_DEV_T_ANY
, child
, DDI_PROP_DONTPASS
,
632 "reg", (caddr_t
)&ebus_rp
, ®len
) != DDI_SUCCESS
) {
633 return (DDI_FAILURE
);
636 (void) snprintf(name
, namelen
, "%x,%x", ebus_rp
->addr_hi
,
638 kmem_free(ebus_rp
, reglen
);
640 return (DDI_SUCCESS
);
644 * control ops entry point:
646 * Requests handled completely:
647 * DDI_CTLOPS_INITCHILD
648 * DDI_CTLOPS_UNINITCHILD
649 * DDI_CTLOPS_REPORTDEV
653 * All others passed to parent.
656 ebus_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
657 ddi_ctl_enum_t op
, void *arg
, void *result
)
660 ebus_devstate_t
*ebus_p
= get_ebus_soft_state(ddi_get_instance(dip
));
662 ebus_regspec_t
*ebus_rp
;
667 case DDI_CTLOPS_INITCHILD
: {
668 dev_info_t
*child
= (dev_info_t
*)arg
;
670 * Set the address portion of the node name based on the
673 DBG2(D_CTLOPS
, ebus_p
, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
674 ddi_get_name(child
), ddi_get_instance(child
));
676 if (ebus_name_child(child
, name
, 10) != DDI_SUCCESS
) {
677 DBG(D_CTLOPS
, ebus_p
, "can't name child\n");
678 return (DDI_FAILURE
);
681 ddi_set_name_addr(child
, name
);
682 ddi_set_parent_data(child
, NULL
);
683 return (DDI_SUCCESS
);
686 case DDI_CTLOPS_UNINITCHILD
:
687 DBG2(D_CTLOPS
, ebus_p
, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
688 ddi_get_name((dev_info_t
*)arg
),
689 ddi_get_instance((dev_info_t
*)arg
));
690 ddi_set_name_addr((dev_info_t
*)arg
, NULL
);
691 ddi_remove_minor_node((dev_info_t
*)arg
, NULL
);
692 impl_rem_dev_props((dev_info_t
*)arg
);
693 return (DDI_SUCCESS
);
695 case DDI_CTLOPS_REPORTDEV
:
697 DBG2(D_CTLOPS
, ebus_p
, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
698 ddi_get_name(rdip
), ddi_get_instance(rdip
));
699 cmn_err(CE_CONT
, "?%s%d at %s%d: offset %s\n",
700 ddi_driver_name(rdip
), ddi_get_instance(rdip
),
701 ddi_driver_name(dip
), ddi_get_instance(dip
),
702 ddi_get_name_addr(rdip
));
703 return (DDI_SUCCESS
);
705 case DDI_CTLOPS_REGSIZE
:
707 DBG2(D_CTLOPS
, ebus_p
, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
708 ddi_get_name(rdip
), ddi_get_instance(rdip
));
709 if (getprop(rdip
, "reg", &ebus_rp
, &i
) != DDI_SUCCESS
) {
710 DBG(D_CTLOPS
, ebus_p
, "can't get reg property\n");
711 return (DDI_FAILURE
);
713 n
= i
/ sizeof (ebus_regspec_t
);
714 if (*(int *)arg
< 0 || *(int *)arg
>= n
) {
715 DBG(D_MAP
, ebus_p
, "rnumber out of range\n");
716 kmem_free(ebus_rp
, i
);
717 return (DDI_FAILURE
);
719 *((off_t
*)result
) = ebus_rp
[*(int *)arg
].size
;
720 kmem_free(ebus_rp
, i
);
721 return (DDI_SUCCESS
);
723 case DDI_CTLOPS_NREGS
:
725 DBG2(D_CTLOPS
, ebus_p
, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
726 ddi_get_name(rdip
), ddi_get_instance(rdip
));
727 if (getprop(rdip
, "reg", &ebus_rp
, &i
) != DDI_SUCCESS
) {
728 DBG(D_CTLOPS
, ebus_p
, "can't get reg property\n");
729 return (DDI_FAILURE
);
731 *((uint_t
*)result
) = i
/ sizeof (ebus_regspec_t
);
732 kmem_free(ebus_rp
, i
);
733 return (DDI_SUCCESS
);
737 * Now pass the request up to our parent.
739 DBG2(D_CTLOPS
, ebus_p
, "passing request to parent: rdip=%s%d\n",
740 ddi_get_name(rdip
), ddi_get_instance(rdip
));
741 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
744 struct ebus_string_to_pil
{
749 static struct ebus_string_to_pil ebus_name_to_pil
[] = {{"SUNW,CS4231", 9},
760 static struct ebus_string_to_pil ebus_device_type_to_pil
[] = {{"serial", 12},
764 ebus_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
765 ddi_intr_handle_impl_t
*hdlp
, void *result
)
768 ebus_devstate_t
*ebus_p
= get_ebus_soft_state(ddi_get_instance(dip
));
770 int32_t i
, max_children
, max_device_types
, len
;
771 char *name_p
, *device_type_p
;
773 DBG1(D_INTR
, ebus_p
, "ebus_p 0x%p\n", ebus_p
);
776 * NOTE: These ops below will never be supported in this nexus
777 * driver, hence they always return immediately.
780 case DDI_INTROP_GETCAP
:
781 *(int *)result
= DDI_INTR_FLAG_LEVEL
;
782 return (DDI_SUCCESS
);
783 case DDI_INTROP_SUPPORTED_TYPES
:
784 *(int *)result
= i_ddi_get_intx_nintrs(rdip
) ?
785 DDI_INTR_TYPE_FIXED
: 0;
786 return (DDI_SUCCESS
);
787 case DDI_INTROP_SETCAP
:
788 case DDI_INTROP_SETMASK
:
789 case DDI_INTROP_CLRMASK
:
790 case DDI_INTROP_GETPENDING
:
791 return (DDI_ENOTSUP
);
800 * This is a hack to set the PIL for the devices under ebus.
801 * We first look up a device by it's specific name, if we can't
802 * match the name, we try and match it's device_type property.
803 * Lastly we default a PIL level of 1.
805 name_p
= ddi_node_name(rdip
);
806 max_children
= sizeof (ebus_name_to_pil
) /
807 sizeof (struct ebus_string_to_pil
);
809 for (i
= 0; i
< max_children
; i
++) {
810 if (strcmp(ebus_name_to_pil
[i
].string
, name_p
) == 0) {
811 DBG2(D_INTR
, ebus_p
, "child name %s; match PIL %d\n",
812 ebus_name_to_pil
[i
].string
,
813 ebus_name_to_pil
[i
].pil
);
815 hdlp
->ih_pri
= ebus_name_to_pil
[i
].pil
;
820 if (ddi_getlongprop(DDI_DEV_T_ANY
, rdip
, DDI_PROP_DONTPASS
,
821 "device_type", (caddr_t
)&device_type_p
, &len
) == DDI_SUCCESS
) {
823 max_device_types
= sizeof (ebus_device_type_to_pil
) /
824 sizeof (struct ebus_string_to_pil
);
826 for (i
= 0; i
< max_device_types
; i
++) {
827 if (strcmp(ebus_device_type_to_pil
[i
].string
,
828 device_type_p
) == 0) {
829 DBG2(D_INTR
, ebus_p
, "Device type %s; match "
830 "PIL %d\n", ebus_device_type_to_pil
[i
].
831 string
, ebus_device_type_to_pil
[i
].pil
);
833 hdlp
->ih_pri
= ebus_device_type_to_pil
[i
].pil
;
838 kmem_free(device_type_p
, len
);
842 * If we get here, we need to set a default value
845 if (hdlp
->ih_pri
== 0) {
848 cmn_err(CE_WARN
, "%s%d assigning default interrupt level %d "
849 "for device %s%d", ddi_driver_name(dip
),
850 ddi_get_instance(dip
), hdlp
->ih_pri
, ddi_driver_name(rdip
),
851 ddi_get_instance(rdip
));
855 /* Pass up the request to our parent. */
856 return (i_ddi_intr_ops(dip
, rdip
, intr_op
, hdlp
, result
));
860 * ebus_config: setup pci config space registers:
861 * enable bus mastering, memory access and error reporting
864 ebus_config(ebus_devstate_t
*ebus_p
)
866 ddi_acc_handle_t conf_handle
;
868 dev_info_t
*dip
= ebus_p
->dip
;
872 if (ddi_getlongprop(DDI_DEV_T_ANY
, ddi_get_parent(dip
),
873 DDI_PROP_DONTPASS
, "device_type", (caddr_t
)&devtype_str
,
874 &devtype_len
) != DDI_SUCCESS
) {
875 cmn_err(CE_WARN
, "Can't get %s device_type property",
876 ddi_get_name(ddi_get_parent(dip
)));
878 return (DDI_FAILURE
);
881 comm
= strcmp(devtype_str
, "pci");
882 kmem_free(devtype_str
, devtype_len
);
885 return (DDI_SUCCESS
);
888 * Make sure the master enable and memory access enable
889 * bits are set in the config command register.
891 if (pci_config_setup(ebus_p
->dip
, &conf_handle
) != DDI_SUCCESS
)
892 return (DDI_FAILURE
);
894 comm
= pci_config_get16(conf_handle
, PCI_CONF_COMM
),
896 DBG1(D_MAP
, ebus_p
, "command register was 0x%x\n", comm
);
898 comm
|= (PCI_COMM_ME
|PCI_COMM_MAE
|PCI_COMM_SERR_ENABLE
|
899 PCI_COMM_PARITY_DETECT
);
900 pci_config_put16(conf_handle
, PCI_CONF_COMM
, comm
),
902 DBG1(D_MAP
, ebus_p
, "command register is now 0x%x\n", comm
);
904 pci_config_put8(conf_handle
, PCI_CONF_CACHE_LINESZ
,
905 (uchar_t
)ebus_cache_line_size
);
906 pci_config_put8(conf_handle
, PCI_CONF_LATENCY_TIMER
,
907 (uchar_t
)ebus_latency_timer
);
908 pci_config_teardown(&conf_handle
);
909 return (DDI_SUCCESS
);
913 extern void prom_printf(const char *, ...);
916 ebus_debug(uint_t flag
, ebus_devstate_t
*ebus_p
, char *fmt
,
917 uintptr_t a1
, uintptr_t a2
, uintptr_t a3
, uintptr_t a4
, uintptr_t a5
)
921 if (ebus_debug_flags
& flag
) {
935 cmn_err(CE_CONT
, "%s%d: %s: ",
936 ddi_get_name(ebus_p
->dip
),
937 ddi_get_instance(ebus_p
->dip
), s
);
939 cmn_err(CE_CONT
, "ebus: ");
940 cmn_err(CE_CONT
, fmt
, a1
, a2
, a3
, a4
, a5
);
945 ebus_vreg_dump(ebus_devstate_t
*ebus_p
, vregspec_t
*rp
)
947 if (ebus_p
->ebus_paddr_cells
== 3) {
948 DBG5(D_MAP
, ebus_p
, "(%x,%x,%x)(%x,%x)\n",
949 rp
->pci_regspec
.pci_phys_hi
,
950 rp
->pci_regspec
.pci_phys_mid
,
951 rp
->pci_regspec
.pci_phys_low
,
952 rp
->pci_regspec
.pci_size_hi
,
953 rp
->pci_regspec
.pci_size_low
);
954 } else if (ebus_p
->ebus_paddr_cells
== 2) {
955 DBG3(D_MAP
, ebus_p
, "%x,%x,%x\n",
956 rp
->jbus_regspec
.regspec_bustype
,
957 rp
->jbus_regspec
.regspec_addr
,
958 rp
->jbus_regspec
.regspec_size
);
965 ebus_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
967 ebus_devstate_t
*ebus_p
;
970 * Make sure the open is for the right file type.
972 if (otyp
!= OTYP_CHR
)
976 * Get the soft state structure for the device.
978 ebus_p
= get_ebus_soft_state(getminor(*devp
));
983 * Handle the open by tracking the device state.
985 mutex_enter(&ebus_p
->ebus_mutex
);
987 if (ebus_p
->ebus_soft_state
!= EBUS_SOFT_STATE_CLOSED
) {
988 mutex_exit(&ebus_p
->ebus_mutex
);
991 ebus_p
->ebus_soft_state
= EBUS_SOFT_STATE_OPEN_EXCL
;
993 if (ebus_p
->ebus_soft_state
== EBUS_SOFT_STATE_OPEN_EXCL
) {
994 mutex_exit(&ebus_p
->ebus_mutex
);
997 ebus_p
->ebus_soft_state
= EBUS_SOFT_STATE_OPEN
;
999 mutex_exit(&ebus_p
->ebus_mutex
);
1006 ebus_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
)
1008 ebus_devstate_t
*ebus_p
;
1010 if (otyp
!= OTYP_CHR
)
1013 ebus_p
= get_ebus_soft_state(getminor(dev
));
1017 mutex_enter(&ebus_p
->ebus_mutex
);
1018 ebus_p
->ebus_soft_state
= EBUS_SOFT_STATE_CLOSED
;
1019 mutex_exit(&ebus_p
->ebus_mutex
);
1025 * ebus_ioctl: devctl hotplug controls
1029 ebus_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
1032 ebus_devstate_t
*ebus_p
;
1034 struct devctl_iocdata
*dcp
;
1038 ebus_p
= get_ebus_soft_state(getminor(dev
));
1045 * We can use the generic implementation for these ioctls
1048 case DEVCTL_DEVICE_GETSTATE
:
1049 case DEVCTL_DEVICE_ONLINE
:
1050 case DEVCTL_DEVICE_OFFLINE
:
1051 case DEVCTL_BUS_GETSTATE
:
1052 return (ndi_devctl_ioctl(self
, cmd
, arg
, mode
, 0));
1056 * read devctl ioctl data
1058 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
)
1063 case DEVCTL_DEVICE_RESET
:
1067 case DEVCTL_BUS_QUIESCE
:
1068 if (ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
)
1069 if (bus_state
== BUS_QUIESCED
)
1071 (void) ndi_set_bus_state(self
, BUS_QUIESCED
);
1074 case DEVCTL_BUS_UNQUIESCE
:
1075 if (ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
)
1076 if (bus_state
== BUS_ACTIVE
)
1078 (void) ndi_set_bus_state(self
, BUS_ACTIVE
);
1081 case DEVCTL_BUS_RESET
:
1085 case DEVCTL_BUS_RESETALL
:
1093 ndi_dc_freehdl(dcp
);