998 obsolete DMA driver interfaces should be removed
[unleashed.git] / usr / src / uts / sun4 / io / ebus.c
blob19001588d5d5b17b320fe31dc33e708f494c0c12
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
31 #include <sys/conf.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/ddi_impldefs.h>
35 #include <sys/ddi_subrdefs.h>
36 #include <sys/pci.h>
37 #include <sys/autoconf.h>
38 #include <sys/cmn_err.h>
39 #include <sys/errno.h>
40 #include <sys/kmem.h>
41 #include <sys/debug.h>
42 #include <sys/sysmacros.h>
43 #include <sys/ebus.h>
44 #include <sys/open.h>
45 #include <sys/stat.h>
46 #include <sys/file.h>
47 #include <sys/sunndi.h>
49 #ifdef DEBUG
50 uint64_t ebus_debug_flags = 0;
51 #endif
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:
65 static int
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);
68 static int
69 ebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
70 ddi_ctl_enum_t op, void *arg, void *result);
71 static int
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 */
105 nodev, /* print */
106 nodev, /* dump */
107 nodev, /* read */
108 nodev, /* write */
109 ebus_ioctl, /* ioctl */
110 nodev, /* devmap */
111 nodev, /* mmap */
112 nodev, /* segmap */
113 nochpoll, /* poll */
114 ddi_prop_op, /* cb_prop_op */
115 NULL, /* streamtab */
116 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
117 CB_REV, /* rev */
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 = {
126 BUSO_REV,
127 ebus_map,
128 NULL,
129 NULL,
130 NULL,
131 i_ddi_map_fault,
132 NULL,
133 ddi_dma_allochdl,
134 ddi_dma_freehdl,
135 ddi_dma_bindhdl,
136 ddi_dma_unbindhdl,
137 ddi_dma_flush,
138 ddi_dma_win,
139 ddi_dma_mctl,
140 ebus_ctlops,
141 ddi_bus_prop_op,
142 ndi_busop_get_eventcookie,
143 ndi_busop_add_eventcall,
144 ndi_busop_remove_eventcall,
145 ndi_post_event,
154 ebus_intr_ops
157 static struct dev_ops ebus_ops = {
158 DEVO_REV,
160 ebus_info,
161 nulldev,
162 nulldev,
163 ebus_attach,
164 ebus_detach,
165 nodev,
166 &ebus_cb_ops,
167 &ebus_bus_ops,
168 NULL,
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 */
195 _init(void)
197 int e;
200 * Initialize per-ebus soft state pointer.
202 e = ddi_soft_state_init(&per_ebus_state, sizeof (ebus_devstate_t), 1);
203 if (e != 0)
204 return (e);
207 * Install the module.
209 e = mod_install(&modlinkage);
210 if (e != 0)
211 ddi_soft_state_fini(&per_ebus_state);
212 return (e);
216 _fini(void)
218 int e;
221 * Remove the module.
223 e = mod_remove(&modlinkage);
224 if (e != 0)
225 return (e);
228 * Free the soft state info.
230 ddi_soft_state_fini(&per_ebus_state);
231 return (e);
235 _info(struct modinfo *modinfop)
237 return (mod_info(&modlinkage, modinfop));
240 /* device driver entry points */
242 /*ARGSUSED*/
243 static int
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 */
247 int instance;
249 instance = getminor((dev_t)arg);
250 ebus_p = get_ebus_soft_state(instance);
252 switch (infocmd) {
253 case DDI_INFO_DEVT2INSTANCE:
254 *result = (void *)(uintptr_t)instance;
255 break;
256 case DDI_INFO_DEVT2DEVINFO:
257 if (ebus_p == NULL)
258 return (DDI_FAILURE);
259 *result = (void *)ebus_p->dip;
260 break;
261 default:
262 return (DDI_FAILURE);
265 return (DDI_SUCCESS);
269 * attach entry point:
271 * normal attach:
273 * create soft state structure (dip, reg, nreg and state fields)
274 * map in configuration header
275 * make sure device is properly configured
276 * report device
278 static int
279 ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
281 ebus_devstate_t *ebus_p; /* per ebus state pointer */
282 int instance;
284 DBG1(D_ATTACH, NULL, "dip=%p\n", dip);
286 switch (cmd) {
287 case DDI_ATTACH:
290 * Allocate soft state for this instance.
292 instance = ddi_get_instance(dip);
293 if (ddi_soft_state_zalloc(per_ebus_state, instance)
294 != DDI_SUCCESS) {
295 DBG(D_ATTACH, NULL, "failed to alloc soft state\n");
296 return (DDI_FAILURE);
298 ebus_p = get_ebus_soft_state(instance);
299 ebus_p->dip = dip;
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) {
309 goto attach_fail;
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) {
317 goto attach_fail;
320 if (ebus_config(ebus_p) != DDI_SUCCESS) {
321 ddi_remove_minor_node(dip, "devctl");
322 goto attach_fail;
326 * Make the pci_report_pmcap() call only for RIO
327 * implementations.
329 if (IS_RIO(dip)) {
330 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED,
331 (void *)EBUS_4MHZ);
335 * Make the state as attached and report the device.
337 ebus_p->state = ATTACHED;
338 ddi_report_dev(dip);
339 DBG(D_ATTACH, ebus_p, "returning\n");
340 break;
342 case DDI_RESUME:
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;
350 break;
353 return (DDI_SUCCESS);
355 attach_fail:
356 mutex_destroy(&ebus_p->ebus_mutex);
357 free_ebus_soft_state(instance);
358 return (DDI_FAILURE);
362 * detach entry point:
364 static int
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);
370 switch (cmd) {
371 case DDI_DETACH:
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);
379 break;
380 case DDI_SUSPEND:
381 DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
382 ebus_p->state = SUSPENDED;
383 break;
384 default:
385 DBG(D_ATTACH, NULL,
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)
398 != DDI_SUCCESS) {
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);
417 static void
418 ebus_get_cells_prop(ebus_devstate_t *ebus_p)
420 dev_info_t *dip = ebus_p->dip;
421 dev_info_t *pdip;
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
458 static int
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;
464 vregspec_t vreg;
465 ddi_map_req_t p_map_request;
466 int rnumber, i, n;
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) {
475 case DDI_MT_REGSPEC:
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),
484 mp->map_handlep);
485 ebus_rp = (ebus_regspec_t *)mp->map_obj.rp;
486 break;
488 case DDI_MT_RNUMBER:
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];
511 break;
513 default:
514 return (DDI_ME_INVAL);
518 /* Adjust our reg property with offset and length */
519 ebus_rp->addr_low += off;
520 if (len)
521 ebus_rp->size = len;
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)
529 return (rval);
531 p_map_request = *mp;
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);
538 return (rval);
542 * ebus_apply_range generically relocates child's regspec to
543 * parent's format according to ebus' range spec
545 * Assumptions:
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.
552 static int
553 ebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
554 ebus_regspec_t *ebus_rp, vregspec_t *rp) {
555 int b, i;
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)
580 continue;
582 /* Detect whether request entirely fits within a range */
583 if (req_addr < rng_caddr_low)
584 continue;
586 if ((req_addr + ebus_rp->size - 1)
587 > (rng_caddr_low + rng_sz - 1))
588 continue;
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++)
594 preg_cell_p[i] = 0;
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;
602 /* Copy the size */
603 preg_cell_p[preg_rec_sz-1] = min(ebus_rp->size,
604 rng_sz - addr_offset);
606 #ifdef DEBUG
607 ebus_vreg_dump(ebus_p, (vregspec_t *)preg_cell_p);
608 #endif /* DEBUG */
610 break;
613 if (b == nrange) {
614 cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
615 return (DDI_ME_REGSPEC_RANGE);
618 return (DDI_SUCCESS);
621 static int
622 ebus_name_child(dev_info_t *child, char *name, int namelen)
624 ebus_regspec_t *ebus_rp;
625 int reglen;
628 * Get the address portion of the node name based on the
629 * address/offset.
631 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
632 "reg", (caddr_t)&ebus_rp, &reglen) != DDI_SUCCESS) {
633 return (DDI_FAILURE);
636 (void) snprintf(name, namelen, "%x,%x", ebus_rp->addr_hi,
637 ebus_rp->addr_low);
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
650 * DDI_CTLOPS_REGSIZE
651 * DDI_CTLOPS_NREGS
653 * All others passed to parent.
655 static int
656 ebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
657 ddi_ctl_enum_t op, void *arg, void *result)
659 #ifdef DEBUG
660 ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
661 #endif
662 ebus_regspec_t *ebus_rp;
663 int i, n;
664 char name[10];
666 switch (op) {
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
671 * address/offset.
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 {
745 int8_t *string;
746 uint32_t pil;
749 static struct ebus_string_to_pil ebus_name_to_pil[] = {{"SUNW,CS4231", 9},
750 {"audio", 9},
751 {"fdthree", 8},
752 {"floppy", 8},
753 {"ecpp", 3},
754 {"parallel", 3},
755 {"su", 12},
756 {"se", 12},
757 {"serial", 12},
758 {"power", 14}};
760 static struct ebus_string_to_pil ebus_device_type_to_pil[] = {{"serial", 12},
761 {"block", 8}};
763 static int
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)
767 #ifdef DEBUG
768 ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
769 #endif
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.
779 switch (intr_op) {
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);
792 default:
793 break;
796 if (hdlp->ih_pri)
797 goto done;
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;
816 goto done;
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;
834 break;
838 kmem_free(device_type_p, len);
842 * If we get here, we need to set a default value
843 * for the PIL.
845 if (hdlp->ih_pri == 0) {
846 hdlp->ih_pri = 1;
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));
854 done:
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
863 static int
864 ebus_config(ebus_devstate_t *ebus_p)
866 ddi_acc_handle_t conf_handle;
867 uint16_t comm;
868 dev_info_t *dip = ebus_p->dip;
869 char *devtype_str;
870 int devtype_len;
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);
884 if (comm)
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),
895 #ifdef DEBUG
896 DBG1(D_MAP, ebus_p, "command register was 0x%x\n", comm);
897 #endif
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),
901 #ifdef DEBUG
902 DBG1(D_MAP, ebus_p, "command register is now 0x%x\n", comm);
903 #endif
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);
912 #ifdef DEBUG
913 extern void prom_printf(const char *, ...);
915 static void
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)
919 char *s;
921 if (ebus_debug_flags & flag) {
922 switch (flag) {
923 case D_ATTACH:
924 s = "attach"; break;
925 case D_DETACH:
926 s = "detach"; break;
927 case D_MAP:
928 s = "map"; break;
929 case D_CTLOPS:
930 s = "ctlops"; break;
931 case D_INTR:
932 s = "intr"; break;
934 if (ebus_p)
935 cmn_err(CE_CONT, "%s%d: %s: ",
936 ddi_get_name(ebus_p->dip),
937 ddi_get_instance(ebus_p->dip), s);
938 else
939 cmn_err(CE_CONT, "ebus: ");
940 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
944 static void
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);
961 #endif /* DEBUG */
963 /* ARGSUSED3 */
964 static int
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)
973 return (EINVAL);
976 * Get the soft state structure for the device.
978 ebus_p = get_ebus_soft_state(getminor(*devp));
979 if (ebus_p == NULL)
980 return (ENXIO);
983 * Handle the open by tracking the device state.
985 mutex_enter(&ebus_p->ebus_mutex);
986 if (flags & FEXCL) {
987 if (ebus_p->ebus_soft_state != EBUS_SOFT_STATE_CLOSED) {
988 mutex_exit(&ebus_p->ebus_mutex);
989 return (EBUSY);
991 ebus_p->ebus_soft_state = EBUS_SOFT_STATE_OPEN_EXCL;
992 } else {
993 if (ebus_p->ebus_soft_state == EBUS_SOFT_STATE_OPEN_EXCL) {
994 mutex_exit(&ebus_p->ebus_mutex);
995 return (EBUSY);
997 ebus_p->ebus_soft_state = EBUS_SOFT_STATE_OPEN;
999 mutex_exit(&ebus_p->ebus_mutex);
1000 return (0);
1004 /* ARGSUSED */
1005 static int
1006 ebus_close(dev_t dev, int flags, int otyp, cred_t *credp)
1008 ebus_devstate_t *ebus_p;
1010 if (otyp != OTYP_CHR)
1011 return (EINVAL);
1013 ebus_p = get_ebus_soft_state(getminor(dev));
1014 if (ebus_p == NULL)
1015 return (ENXIO);
1017 mutex_enter(&ebus_p->ebus_mutex);
1018 ebus_p->ebus_soft_state = EBUS_SOFT_STATE_CLOSED;
1019 mutex_exit(&ebus_p->ebus_mutex);
1020 return (0);
1025 * ebus_ioctl: devctl hotplug controls
1027 /* ARGSUSED */
1028 static int
1029 ebus_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1030 int *rvalp)
1032 ebus_devstate_t *ebus_p;
1033 dev_info_t *self;
1034 struct devctl_iocdata *dcp;
1035 uint_t bus_state;
1036 int rv = 0;
1038 ebus_p = get_ebus_soft_state(getminor(dev));
1039 if (ebus_p == NULL)
1040 return (ENXIO);
1042 self = ebus_p->dip;
1045 * We can use the generic implementation for these ioctls
1047 switch (cmd) {
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)
1059 return (EFAULT);
1061 switch (cmd) {
1063 case DEVCTL_DEVICE_RESET:
1064 rv = ENOTSUP;
1065 break;
1067 case DEVCTL_BUS_QUIESCE:
1068 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1069 if (bus_state == BUS_QUIESCED)
1070 break;
1071 (void) ndi_set_bus_state(self, BUS_QUIESCED);
1072 break;
1074 case DEVCTL_BUS_UNQUIESCE:
1075 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS)
1076 if (bus_state == BUS_ACTIVE)
1077 break;
1078 (void) ndi_set_bus_state(self, BUS_ACTIVE);
1079 break;
1081 case DEVCTL_BUS_RESET:
1082 rv = ENOTSUP;
1083 break;
1085 case DEVCTL_BUS_RESETALL:
1086 rv = ENOTSUP;
1087 break;
1089 default:
1090 rv = ENOTTY;
1093 ndi_dc_freehdl(dcp);
1094 return (rv);