pci.c (d4476ccb) pci.c (70025d76)
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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *

--- 17 unchanged lines hidden (view full) ---

26
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29/*
30 * Host to PCI local bus driver
31 */
32
33#include <sys/conf.h>
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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *

--- 17 unchanged lines hidden (view full) ---

26
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29/*
30 * Host to PCI local bus driver
31 */
32
33#include <sys/conf.h>
34#include <sys/kmem.h>
35#include <sys/debug.h>
36#include <sys/modctl.h>
34#include <sys/modctl.h>
37#include <sys/autoconf.h>
38#include <sys/ddi_impldefs.h>
39#include <sys/ddi_subrdefs.h>
40#include <sys/pci.h>
41#include <sys/pci_impl.h>
35#include <sys/pci.h>
36#include <sys/pci_impl.h>
42#include <sys/ddi.h>
43#include <sys/sunddi.h>
37#include <sys/sysmacros.h>
44#include <sys/sunndi.h>
45#include <sys/hotplug/pci/pcihp.h>
46#include <sys/pci_cfgspace.h>
38#include <sys/sunndi.h>
39#include <sys/hotplug/pci/pcihp.h>
40#include <sys/pci_cfgspace.h>
47#include <sys/avintr.h>
48#include <sys/psm.h>
49#include <sys/pci_intr_lib.h>
50#include <sys/policy.h>
51#include <sys/pci_tools.h>
52#include "pci_tools_ext.h"
53#include "pci_var.h"
41#include <io/pci/pci_common.h>
42#include <io/pci/pci_tools_ext.h>
43#include <io/pci/pci_var.h>
54
55/* Save minimal state. */
56void *pci_statep;
57
58/*
59 * Bus Operation functions
60 */
61static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
62 off_t, off_t, caddr_t *);
63static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
64 void *, void *);
65static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
66 ddi_intr_handle_impl_t *, void *);
44
45/* Save minimal state. */
46void *pci_statep;
47
48/*
49 * Bus Operation functions
50 */
51static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
52 off_t, off_t, caddr_t *);
53static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
54 void *, void *);
55static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
56 ddi_intr_handle_impl_t *, void *);
67static int pci_get_priority(dev_info_t *, int, int *);
68static int pci_get_nintrs(dev_info_t *, int, int *);
69static int pci_enable_intr(dev_info_t *, dev_info_t *,
70 ddi_intr_handle_impl_t *, uint32_t);
71static void pci_disable_intr(dev_info_t *, dev_info_t *,
72 ddi_intr_handle_impl_t *, uint32_t);
73
57
74/* Extern decalrations */
75extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
76 psm_intr_op_t, int *);
77
78struct bus_ops pci_bus_ops = {
79 BUSO_REV,
80 pci_bus_map,
81 NULL,
82 NULL,
83 NULL,
84 i_ddi_map_fault,
85 ddi_dma_map,

--- 16 unchanged lines hidden (view full) ---

102 NULL, /* (*bus_fm_init)(); */
103 NULL, /* (*bus_fm_fini)(); */
104 NULL, /* (*bus_fm_access_enter)(); */
105 NULL, /* (*bus_fm_access_exit)(); */
106 NULL, /* (*bus_power)(); */
107 pci_intr_ops /* (*bus_intr_op)(); */
108};
109
58struct bus_ops pci_bus_ops = {
59 BUSO_REV,
60 pci_bus_map,
61 NULL,
62 NULL,
63 NULL,
64 i_ddi_map_fault,
65 ddi_dma_map,

--- 16 unchanged lines hidden (view full) ---

82 NULL, /* (*bus_fm_init)(); */
83 NULL, /* (*bus_fm_fini)(); */
84 NULL, /* (*bus_fm_access_enter)(); */
85 NULL, /* (*bus_fm_access_exit)(); */
86 NULL, /* (*bus_power)(); */
87 pci_intr_ops /* (*bus_intr_op)(); */
88};
89
110static int pci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
111static int pci_close(dev_t dev, int flags, int otyp, cred_t *credp);
112static int pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
113 int *rvalp);
114static int pci_prop_op(dev_t dev, dev_info_t *devi, ddi_prop_op_t prop_op,
115 int flags, char *name, caddr_t valuep, int *lengthp);
116
117/*
118 * One goal here is to leverage off of the pcihp.c source without making
119 * changes to it. Call into it's cb_ops directly if needed, piggybacking
120 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
121 * will be opening PCI nexus driver file descriptors.
122 */
90/*
91 * One goal here is to leverage off of the pcihp.c source without making
92 * changes to it. Call into it's cb_ops directly if needed, piggybacking
93 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
94 * will be opening PCI nexus driver file descriptors.
95 */
96static int pci_open(dev_t *, int, int, cred_t *);
97static int pci_close(dev_t, int, int, cred_t *);
98static int pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
99static int pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
100 caddr_t, int *);
101static int pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
123
124struct cb_ops pci_cb_ops = {
125 pci_open, /* open */
126 pci_close, /* close */
127 nodev, /* strategy */
128 nodev, /* print */
129 nodev, /* dump */
130 nodev, /* read */

--- 9 unchanged lines hidden (view full) ---

140 CB_REV, /* rev */
141 nodev, /* int (*cb_aread)() */
142 nodev /* int (*cb_awrite)() */
143};
144
145/*
146 * Device Node Operation functions
147 */
102
103struct cb_ops pci_cb_ops = {
104 pci_open, /* open */
105 pci_close, /* close */
106 nodev, /* strategy */
107 nodev, /* print */
108 nodev, /* dump */
109 nodev, /* read */

--- 9 unchanged lines hidden (view full) ---

119 CB_REV, /* rev */
120 nodev, /* int (*cb_aread)() */
121 nodev /* int (*cb_awrite)() */
122};
123
124/*
125 * Device Node Operation functions
126 */
148static int pci_info(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg,
149 void **result);
150static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
151static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
152
153struct dev_ops pci_ops = {
154 DEVO_REV, /* devo_rev */
155 0, /* refcnt */
156 pci_info, /* info */
157 nulldev, /* identify */

--- 15 unchanged lines hidden (view full) ---

173
174/*
175 * Internal routines in support of particular pci_ctlops.
176 */
177static int pci_removechild(dev_info_t *child);
178static int pci_initchild(dev_info_t *child);
179
180/*
127static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
128static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
129
130struct dev_ops pci_ops = {
131 DEVO_REV, /* devo_rev */
132 0, /* refcnt */
133 pci_info, /* info */
134 nulldev, /* identify */

--- 15 unchanged lines hidden (view full) ---

150
151/*
152 * Internal routines in support of particular pci_ctlops.
153 */
154static int pci_removechild(dev_info_t *child);
155static int pci_initchild(dev_info_t *child);
156
157/*
181 * Miscellaneous internal functions
182 */
183static int pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp);
184
185/*
186 * These are the access routines. The pci_bus_map sets the handle
187 * to point to these.
188 */
189static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr);
190static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr);
191static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr);
192static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr);
193

--- 143 unchanged lines hidden (view full) ---

337 (void) pcihp_uninit(devi);
338
339 ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi));
340
341 return (DDI_SUCCESS);
342}
343
344static int
158 * These are the access routines. The pci_bus_map sets the handle
159 * to point to these.
160 */
161static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr);
162static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr);
163static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr);
164static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr);
165

--- 143 unchanged lines hidden (view full) ---

309 (void) pcihp_uninit(devi);
310
311 ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi));
312
313 return (DDI_SUCCESS);
314}
315
316static int
345pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp)
346{
347 pci_regspec_t *assigned_addr;
348 int assigned_addr_len;
349 uint_t phys_hi;
350 int i;
351 int rc;
352 int number;
353
354 phys_hi = pci_rp->pci_phys_hi;
355 if (((phys_hi & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) ||
356 (phys_hi & PCI_RELOCAT_B))
357 return (DDI_SUCCESS);
358
359 /*
360 * the "reg" property specifies relocatable, get and interpret the
361 * "assigned-addresses" property.
362 */
363 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
364 DDI_PROP_DONTPASS, "assigned-addresses",
365 (int **)&assigned_addr, (uint_t *)&assigned_addr_len);
366 if (rc != DDI_PROP_SUCCESS)
367 return (DDI_FAILURE);
368
369 /*
370 * Scan the "assigned-addresses" for one that matches the specified
371 * "reg" property entry.
372 */
373 phys_hi &= PCI_CONF_ADDR_MASK;
374 number = assigned_addr_len / (sizeof (pci_regspec_t) / sizeof (int));
375 for (i = 0; i < number; i++) {
376 if ((assigned_addr[i].pci_phys_hi & PCI_CONF_ADDR_MASK) ==
377 phys_hi) {
378 pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid;
379 pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low;
380 ddi_prop_free(assigned_addr);
381 return (DDI_SUCCESS);
382 }
383 }
384
385 ddi_prop_free(assigned_addr);
386 return (DDI_FAILURE);
387}
388
389static int
390pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
391 off_t offset, off_t len, caddr_t *vaddrp)
392{
393 struct regspec reg;
394 ddi_map_req_t mr;
395 ddi_acc_hdl_t *hp;
396 ddi_acc_impl_t *ap;
397 pci_regspec_t pci_reg;
398 pci_regspec_t *pci_rp;
399 int rnumber;
400 int length;
317pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
318 off_t offset, off_t len, caddr_t *vaddrp)
319{
320 struct regspec reg;
321 ddi_map_req_t mr;
322 ddi_acc_hdl_t *hp;
323 ddi_acc_impl_t *ap;
324 pci_regspec_t pci_reg;
325 pci_regspec_t *pci_rp;
326 int rnumber;
327 int length;
401 int rc;
402 pci_acc_cfblk_t *cfp;
403 int space;
404
405
406 mr = *mp; /* Get private copy of request */
407 mp = &mr;
408
409 /*
410 * check for register number
411 */
412 switch (mp->map_type) {
413 case DDI_MT_REGSPEC:
414 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
415 pci_rp = &pci_reg;
328 pci_acc_cfblk_t *cfp;
329 int space;
330
331
332 mr = *mp; /* Get private copy of request */
333 mp = &mr;
334
335 /*
336 * check for register number
337 */
338 switch (mp->map_type) {
339 case DDI_MT_REGSPEC:
340 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
341 pci_rp = &pci_reg;
416 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
342 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
417 return (DDI_FAILURE);
418 break;
419 case DDI_MT_RNUMBER:
420 rnumber = mp->map_obj.rnumber;
421 /*
422 * get ALL "reg" properties for dip, select the one of
423 * of interest. In x86, "assigned-addresses" property
424 * is identical to the "reg" property, so there is no
425 * need to cross check the two to determine the physical
426 * address of the registers.
427 * This routine still performs some validity checks to
428 * make sure that everything is okay.
429 */
343 return (DDI_FAILURE);
344 break;
345 case DDI_MT_RNUMBER:
346 rnumber = mp->map_obj.rnumber;
347 /*
348 * get ALL "reg" properties for dip, select the one of
349 * of interest. In x86, "assigned-addresses" property
350 * is identical to the "reg" property, so there is no
351 * need to cross check the two to determine the physical
352 * address of the registers.
353 * This routine still performs some validity checks to
354 * make sure that everything is okay.
355 */
430 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
431 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
432 (uint_t *)&length);
433 if (rc != DDI_PROP_SUCCESS) {
356 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
357 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
358 (uint_t *)&length) != DDI_PROP_SUCCESS)
434 return (DDI_FAILURE);
359 return (DDI_FAILURE);
435 }
436
437 /*
438 * validate the register number.
439 */
440 length /= (sizeof (pci_regspec_t) / sizeof (int));
441 if (rnumber >= length) {
442 ddi_prop_free(pci_rp);
443 return (DDI_FAILURE);

--- 5 unchanged lines hidden (view full) ---

449 pci_reg = pci_rp[rnumber];
450
451 /*
452 * free the memory allocated by ddi_prop_lookup_int_array
453 */
454 ddi_prop_free(pci_rp);
455
456 pci_rp = &pci_reg;
360
361 /*
362 * validate the register number.
363 */
364 length /= (sizeof (pci_regspec_t) / sizeof (int));
365 if (rnumber >= length) {
366 ddi_prop_free(pci_rp);
367 return (DDI_FAILURE);

--- 5 unchanged lines hidden (view full) ---

373 pci_reg = pci_rp[rnumber];
374
375 /*
376 * free the memory allocated by ddi_prop_lookup_int_array
377 */
378 ddi_prop_free(pci_rp);
379
380 pci_rp = &pci_reg;
457 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
381 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
458 return (DDI_FAILURE);
459 mp->map_type = DDI_MT_REGSPEC;
460 break;
461 default:
462 return (DDI_ME_INVAL);
463 }
464
465 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;

--- 51 unchanged lines hidden (view full) ---

517 * check for config space
518 * On x86, CONFIG is not mapped via MMU and there is
519 * no endian-ness issues. Set the attr field in the handle to
520 * indicate that the common routines to call the nexus driver.
521 */
522 if (space == PCI_ADDR_CONFIG) {
523 hp = (ddi_acc_hdl_t *)mp->map_handlep;
524
382 return (DDI_FAILURE);
383 mp->map_type = DDI_MT_REGSPEC;
384 break;
385 default:
386 return (DDI_ME_INVAL);
387 }
388
389 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;

--- 51 unchanged lines hidden (view full) ---

441 * check for config space
442 * On x86, CONFIG is not mapped via MMU and there is
443 * no endian-ness issues. Set the attr field in the handle to
444 * indicate that the common routines to call the nexus driver.
445 */
446 if (space == PCI_ADDR_CONFIG) {
447 hp = (ddi_acc_hdl_t *)mp->map_handlep;
448
525 if (hp == NULL) {
526 /* Can't map config space without a handle */
449 /* Can't map config space without a handle */
450 if (hp == NULL)
527 return (DDI_FAILURE);
451 return (DDI_FAILURE);
528 }
529
530 ap = (ddi_acc_impl_t *)hp->ah_platform_private;
531
532 /* endian-ness check */
533 if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
534 return (DDI_FAILURE);
535
536 /*

--- 82 unchanged lines hidden (view full) ---

619 reg.regspec_addr = pci_rp->pci_phys_low;
620 reg.regspec_size = pci_rp->pci_size_low;
621
622 mp->map_obj.rp = &reg;
623 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
624}
625
626
452
453 ap = (ddi_acc_impl_t *)hp->ah_platform_private;
454
455 /* endian-ness check */
456 if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC)
457 return (DDI_FAILURE);
458
459 /*

--- 82 unchanged lines hidden (view full) ---

542 reg.regspec_addr = pci_rp->pci_phys_low;
543 reg.regspec_size = pci_rp->pci_size_low;
544
545 mp->map_obj.rp = &reg;
546 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
547}
548
549
627/*
628 * pci_get_priority:
629 * Figure out the priority of the device
630 */
631static int
632pci_get_priority(dev_info_t *dip, int inum, int *pri)
633{
634 struct intrspec *ispec;
635
636 DDI_INTR_NEXDBG((CE_CONT, "pci_get_priority: dip = 0x%p\n",
637 (void *)dip));
638
639 if ((ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip, inum)) ==
640 NULL)
641 return (DDI_FAILURE);
642
643 *pri = ispec->intrspec_pri;
644
645 return (DDI_SUCCESS);
646}
647
648
649/*
650 * pci_get_nintrs:
651 * Figure out how many interrupts the device supports
652 */
653static int
654pci_get_nintrs(dev_info_t *dip, int type, int *nintrs)
655{
656 int ret;
657
658 *nintrs = 0;
659
660 if (DDI_INTR_IS_MSI_OR_MSIX(type))
661 ret = pci_msi_get_nintrs(dip, type, nintrs);
662 else {
663 ret = DDI_FAILURE;
664 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
665 "interrupts", -1) != -1) {
666 *nintrs = 1;
667 ret = DDI_SUCCESS;
668 }
669 }
670
671 return (ret);
672}
673
674
675/*
676 * pci_intr_ops: bus_intr_op() function for interrupt support
677 */
678/* ARGSUSED */
679static int
680pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
681 ddi_intr_handle_impl_t *hdlp, void *result)
682{
683 int priority = 0;
684 int psm_status = 0;
685 int pci_status = 0;
686 int pci_rval, psm_rval = PSM_FAILURE;
687 int types = 0;
688 int i, j;
689 int behavior;
690 ddi_intrspec_t isp;
691 struct intrspec *ispec;
692 ddi_intr_handle_impl_t tmp_hdl;
693 ddi_intr_msix_t *msix_p;
694
695 DDI_INTR_NEXDBG((CE_CONT,
696 "pci_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
697 (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
698
699 /* Process the request */
700 switch (intr_op) {
701 case DDI_INTROP_SUPPORTED_TYPES:
702 /* Fixed supported by default */
703 *(int *)result = DDI_INTR_TYPE_FIXED;
704
705 /* Figure out if MSI or MSI-X is supported? */
706 if (pci_msi_get_supported_type(rdip, &types) != DDI_SUCCESS)
707 return (DDI_SUCCESS);
708
709 if (psm_intr_ops != NULL) {
710 /* MSI or MSI-X is supported, OR it in */
711 *(int *)result |= types;
712
713 tmp_hdl.ih_type = *(int *)result;
714 (void) (*psm_intr_ops)(rdip, &tmp_hdl,
715 PSM_INTR_OP_CHECK_MSI, result);
716 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: rdip: 0x%p "
717 "supported types: 0x%x\n", (void *)rdip,
718 *(int *)result));
719 }
720 break;
721 case DDI_INTROP_NINTRS:
722 if (pci_get_nintrs(rdip, hdlp->ih_type, result) != DDI_SUCCESS)
723 return (DDI_FAILURE);
724 break;
725 case DDI_INTROP_ALLOC:
726 /*
727 * MSI or MSIX (figure out number of vectors available)
728 * FIXED interrupts: just return available interrupts
729 */
730 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
731 (psm_intr_ops != NULL) &&
732 (pci_get_priority(rdip, hdlp->ih_inum,
733 &priority) == DDI_SUCCESS)) {
734 hdlp->ih_pri = priority;
735 behavior = hdlp->ih_scratch2;
736 (void) (*psm_intr_ops)(rdip, hdlp,
737 PSM_INTR_OP_ALLOC_VECTORS, result);
738
739 /* verify behavior flag and take appropriate action */
740 if ((behavior == DDI_INTR_ALLOC_STRICT) &&
741 (*(int *)result < hdlp->ih_scratch1)) {
742 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: "
743 "behavior %x, couldn't get enough intrs\n",
744 behavior));
745 hdlp->ih_scratch1 = *(int *)result;
746 (void) (*psm_intr_ops)(rdip, hdlp,
747 PSM_INTR_OP_FREE_VECTORS, NULL);
748 return (DDI_EAGAIN);
749 }
750
751 if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
752 if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) {
753 msix_p = pci_msix_init(hdlp->ih_dip);
754 if (msix_p)
755 i_ddi_set_msix(hdlp->ih_dip,
756 msix_p);
757 }
758 msix_p->msix_intrs_in_use += *(int *)result;
759 }
760
761 } else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) {
762 /* Figure out if this device supports MASKING */
763 pci_rval = pci_intx_get_cap(rdip, &pci_status);
764 if (pci_rval == DDI_SUCCESS && pci_status)
765 hdlp->ih_cap |= pci_status;
766 *(int *)result = 1; /* DDI_INTR_TYPE_FIXED */
767 } else
768 return (DDI_FAILURE);
769 break;
770 case DDI_INTROP_FREE:
771 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
772 (psm_intr_ops != NULL)) {
773 (void) (*psm_intr_ops)(rdip, hdlp,
774 PSM_INTR_OP_FREE_VECTORS, NULL);
775
776 if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
777 msix_p = i_ddi_get_msix(hdlp->ih_dip);
778 if (msix_p &&
779 --msix_p->msix_intrs_in_use == 0) {
780 pci_msix_fini(msix_p);
781 i_ddi_set_msix(hdlp->ih_dip, NULL);
782 }
783 }
784 }
785 break;
786 case DDI_INTROP_GETPRI:
787 if (pci_get_priority(rdip, hdlp->ih_inum, &priority) !=
788 DDI_SUCCESS) /* Get the priority */
789 return (DDI_FAILURE);
790 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: priority = 0x%x\n",
791 priority));
792 *(int *)result = priority;
793 break;
794 case DDI_INTROP_SETPRI:
795 /* Validate the interrupt priority passed */
796 if (*(int *)result > LOCK_LEVEL)
797 return (DDI_FAILURE);
798
799 /* Ensure that PSM is all initialized */
800 if (psm_intr_ops == NULL)
801 return (DDI_FAILURE);
802
803 /* Change the priority */
804 if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) ==
805 PSM_FAILURE)
806 return (DDI_FAILURE);
807
808 /* update ispec */
809 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
810 ispec = (struct intrspec *)isp;
811 ispec->intrspec_pri = *(int *)result;
812 break;
813 case DDI_INTROP_ADDISR:
814 /* update ispec */
815 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
816 ispec = (struct intrspec *)isp;
817 ispec->intrspec_func = hdlp->ih_cb_func;
818 break;
819 case DDI_INTROP_REMISR:
820 /* Get the interrupt structure pointer */
821 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum);
822 ispec = (struct intrspec *)isp;
823 ispec->intrspec_func = (uint_t (*)()) 0;
824 break;
825 case DDI_INTROP_GETCAP:
826 /*
827 * First check the config space and/or
828 * MSI capability register(s)
829 */
830 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
831 pci_rval = pci_msi_get_cap(rdip, hdlp->ih_type,
832 &pci_status);
833 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
834 pci_rval = pci_intx_get_cap(rdip, &pci_status);
835
836 /* next check with pcplusmp */
837 if (psm_intr_ops != NULL)
838 psm_rval = (*psm_intr_ops)(rdip, hdlp,
839 PSM_INTR_OP_GET_CAP, &psm_status);
840
841 DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned psm_rval = %x, "
842 "psm_status = %x, pci_rval = %x, pci_status = %x\n",
843 psm_rval, psm_status, pci_rval, pci_status));
844
845 if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
846 *(int *)result = 0;
847 return (DDI_FAILURE);
848 }
849
850 if (psm_rval == PSM_SUCCESS)
851 *(int *)result = psm_status;
852
853 if (pci_rval == DDI_SUCCESS)
854 *(int *)result |= pci_status;
855
856 DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned = %x\n",
857 *(int *)result));
858 break;
859 case DDI_INTROP_SETCAP:
860 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: SETCAP cap=0x%x\n",
861 *(int *)result));
862 if (psm_intr_ops == NULL)
863 return (DDI_FAILURE);
864
865 if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) {
866 DDI_INTR_NEXDBG((CE_CONT, "GETCAP: psm_intr_ops"
867 " returned failure\n"));
868 return (DDI_FAILURE);
869 }
870 break;
871 case DDI_INTROP_ENABLE:
872 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE\n"));
873 if (psm_intr_ops == NULL)
874 return (DDI_FAILURE);
875
876 if (pci_enable_intr(pdip, rdip, hdlp, hdlp->ih_inum) !=
877 DDI_SUCCESS)
878 return (DDI_FAILURE);
879
880 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE vector=0x%x\n",
881 hdlp->ih_vector));
882 break;
883 case DDI_INTROP_DISABLE:
884 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE\n"));
885 if (psm_intr_ops == NULL)
886 return (DDI_FAILURE);
887
888 pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum);
889 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE vector = %x\n",
890 hdlp->ih_vector));
891 break;
892 case DDI_INTROP_BLOCKENABLE:
893 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE\n"));
894 if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
895 DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: not MSI\n"));
896 return (DDI_FAILURE);
897 }
898
899 /* Check if psm_intr_ops is NULL? */
900 if (psm_intr_ops == NULL)
901 return (DDI_FAILURE);
902
903 for (i = 0; i < hdlp->ih_scratch1; i++) {
904 if (pci_enable_intr(pdip, rdip, hdlp,
905 hdlp->ih_inum + i) != DDI_SUCCESS) {
906 DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: "
907 "pci_enable_intr failed for %d\n", i));
908 for (j = 0; j < i; j++)
909 pci_disable_intr(pdip, rdip, hdlp,
910 hdlp->ih_inum + j);
911 return (DDI_FAILURE);
912 }
913 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE "
914 "inum %x done\n", hdlp->ih_inum + i));
915 }
916 break;
917 case DDI_INTROP_BLOCKDISABLE:
918 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE\n"));
919 if (hdlp->ih_type != DDI_INTR_TYPE_MSI) {
920 DDI_INTR_NEXDBG((CE_CONT, "BLOCKDISABLE: not MSI\n"));
921 return (DDI_FAILURE);
922 }
923
924 /* Check if psm_intr_ops is present */
925 if (psm_intr_ops == NULL)
926 return (DDI_FAILURE);
927
928 for (i = 0; i < hdlp->ih_scratch1; i++) {
929 pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum + i);
930 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE "
931 "inum %x done\n", hdlp->ih_inum + i));
932 }
933 break;
934 case DDI_INTROP_SETMASK:
935 case DDI_INTROP_CLRMASK:
936 /*
937 * First handle in the config space
938 */
939 if (intr_op == DDI_INTROP_SETMASK) {
940 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
941 pci_status = pci_msi_set_mask(rdip,
942 hdlp->ih_type, hdlp->ih_inum);
943 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
944 pci_status = pci_intx_set_mask(rdip);
945 } else {
946 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
947 pci_status = pci_msi_clr_mask(rdip,
948 hdlp->ih_type, hdlp->ih_inum);
949 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
950 pci_status = pci_intx_clr_mask(rdip);
951 }
952
953 /* For MSI/X; no need to check with pcplusmp */
954 if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
955 return (pci_status);
956
957 /* For fixed interrupts only: handle config space first */
958 if (hdlp->ih_type == DDI_INTR_TYPE_FIXED &&
959 pci_status == DDI_SUCCESS)
960 break;
961
962 /* For fixed interrupts only: confer with pcplusmp next */
963 if (psm_intr_ops != NULL) {
964 /* If interrupt is shared; do nothing */
965 psm_rval = (*psm_intr_ops)(rdip, hdlp,
966 PSM_INTR_OP_GET_SHARED, &psm_status);
967
968 if (psm_rval == PSM_FAILURE || psm_status == 1)
969 return (pci_status);
970
971 /* Now, pcplusmp should try to set/clear the mask */
972 if (intr_op == DDI_INTROP_SETMASK)
973 psm_rval = (*psm_intr_ops)(rdip, hdlp,
974 PSM_INTR_OP_SET_MASK, NULL);
975 else
976 psm_rval = (*psm_intr_ops)(rdip, hdlp,
977 PSM_INTR_OP_CLEAR_MASK, NULL);
978 }
979 return ((psm_rval == PSM_FAILURE) ? DDI_FAILURE : DDI_SUCCESS);
980 case DDI_INTROP_GETPENDING:
981 /*
982 * First check the config space and/or
983 * MSI capability register(s)
984 */
985 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
986 pci_rval = pci_msi_get_pending(rdip, hdlp->ih_type,
987 hdlp->ih_inum, &pci_status);
988 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED)
989 pci_rval = pci_intx_get_pending(rdip, &pci_status);
990
991 /* On failure; next try with pcplusmp */
992 if (pci_rval != DDI_SUCCESS && psm_intr_ops != NULL)
993 psm_rval = (*psm_intr_ops)(rdip, hdlp,
994 PSM_INTR_OP_GET_PENDING, &psm_status);
995
996 DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned "
997 "psm_rval = %x, psm_status = %x, pci_rval = %x, "
998 "pci_status = %x\n", psm_rval, psm_status, pci_rval,
999 pci_status));
1000 if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) {
1001 *(int *)result = 0;
1002 return (DDI_FAILURE);
1003 }
1004
1005 if (psm_rval != PSM_FAILURE)
1006 *(int *)result = psm_status;
1007 else if (pci_rval != DDI_FAILURE)
1008 *(int *)result = pci_status;
1009 DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned = %x\n",
1010 *(int *)result));
1011 break;
1012 case DDI_INTROP_NAVAIL:
1013 if ((psm_intr_ops != NULL) && (pci_get_priority(rdip,
1014 hdlp->ih_inum, &priority) == DDI_SUCCESS)) {
1015 /* Priority in the handle not initialized yet */
1016 hdlp->ih_pri = priority;
1017 (void) (*psm_intr_ops)(rdip, hdlp,
1018 PSM_INTR_OP_NAVAIL_VECTORS, result);
1019 } else {
1020 *(int *)result = 1;
1021 }
1022 DDI_INTR_NEXDBG((CE_CONT, "pci: NAVAIL returned = %x\n",
1023 *(int *)result));
1024 break;
1025 default:
1026 return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
1027 }
1028
1029 return (DDI_SUCCESS);
1030}
1031
1032
1033static int
1034pci_enable_intr(dev_info_t *pdip, dev_info_t *rdip,
1035 ddi_intr_handle_impl_t *hdlp, uint32_t inum)
1036{
1037 int vector;
1038 struct intrspec *ispec;
1039
1040 DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: hdlp %p inum %x\n",
1041 (void *)hdlp, inum));
1042
1043 /* Translate the interrupt if needed */
1044 ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
1045 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
1046 ispec->intrspec_vec = inum;
1047 hdlp->ih_private = (void *)ispec;
1048
1049 /* translate the interrupt if needed */
1050 (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector);
1051 DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x vector=%x\n",
1052 hdlp->ih_pri, vector));
1053
1054 /* Add the interrupt handler */
1055 if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func,
1056 DEVI(rdip)->devi_name, vector, hdlp->ih_cb_arg1,
1057 hdlp->ih_cb_arg2, rdip))
1058 return (DDI_FAILURE);
1059
1060 return (DDI_SUCCESS);
1061}
1062
1063
1064static void
1065pci_disable_intr(dev_info_t *pdip, dev_info_t *rdip,
1066 ddi_intr_handle_impl_t *hdlp, uint32_t inum)
1067{
1068 int vector;
1069 struct intrspec *ispec;
1070
1071 DDI_INTR_NEXDBG((CE_CONT, "pci_disable_intr: \n"));
1072 ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum);
1073 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type))
1074 ispec->intrspec_vec = inum;
1075 hdlp->ih_private = (void *)ispec;
1076
1077 /* translate the interrupt if needed */
1078 (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector);
1079
1080 /* Disable the interrupt handler */
1081 rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, vector);
1082}
1083
1084
1085/*ARGSUSED*/
1086static int
1087pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
1088 ddi_ctl_enum_t ctlop, void *arg, void *result)
1089{
1090 pci_regspec_t *drv_regp;
1091 uint_t reglen;
1092 int rn;

--- 63 unchanged lines hidden (view full) ---

1156 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
1157 }
1158
1159 /* NOTREACHED */
1160
1161}
1162
1163/*
550/*ARGSUSED*/
551static int
552pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
553 ddi_ctl_enum_t ctlop, void *arg, void *result)
554{
555 pci_regspec_t *drv_regp;
556 uint_t reglen;
557 int rn;

--- 63 unchanged lines hidden (view full) ---

621 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
622 }
623
624 /* NOTREACHED */
625
626}
627
628/*
1164 * Assign the address portion of the node name
629 * pci_intr_ops
1165 */
1166static int
630 */
631static int
1167pci_name_child(dev_info_t *child, char *name, int namelen)
632pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
633 ddi_intr_handle_impl_t *hdlp, void *result)
1168{
634{
1169 pci_regspec_t *pci_rp;
1170 char **unit_addr;
1171 int dev, func, length;
1172 uint_t n;
1173
1174 if (ndi_dev_is_persistent_node(child) == 0) {
1175 /*
1176 * For .conf node, use "unit-address" property
1177 */
1178 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
1179 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
1180 DDI_PROP_SUCCESS) {
1181 cmn_err(CE_WARN,
1182 "cannot find unit-address in %s.conf",
1183 ddi_get_name(child));
1184 return (DDI_FAILURE);
1185 }
1186 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
1187 cmn_err(CE_WARN, "unit-address property in %s.conf"
1188 " not well-formed", ddi_get_name(child));
1189 ddi_prop_free(unit_addr);
1190 return (DDI_FAILURE);
1191 }
1192 (void) snprintf(name, namelen, "%s", *unit_addr);
1193 ddi_prop_free(unit_addr);
1194 return (DDI_SUCCESS);
1195 }
1196
1197 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1198 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
1199 (uint_t *)&length) != DDI_PROP_SUCCESS) {
1200 cmn_err(CE_WARN, "cannot find reg property in %s",
1201 ddi_get_name(child));
1202 return (DDI_FAILURE);
1203 }
1204
1205 /* copy the device identifications */
1206 dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
1207 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
1208
1209 /*
1210 * free the memory allocated by ddi_prop_lookup_int_array
1211 */
1212 ddi_prop_free(pci_rp);
1213
1214 if (func != 0) {
1215 (void) snprintf(name, namelen, "%x,%x", dev, func);
1216 } else {
1217 (void) snprintf(name, namelen, "%x", dev);
1218 }
1219
1220 return (DDI_SUCCESS);
635 return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
1221}
1222
636}
637
638
1223static int
1224pci_initchild(dev_info_t *child)
1225{
639static int
640pci_initchild(dev_info_t *child)
641{
1226 struct ddi_parent_private_data *pdptr;
1227 char name[80];
1228 ddi_acc_handle_t config_handle;
1229 ushort_t command_preserve, command;
1230
642 char name[80];
643 ddi_acc_handle_t config_handle;
644 ushort_t command_preserve, command;
645
1231 if (pci_name_child(child, name, 80) != DDI_SUCCESS) {
646 if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
1232 return (DDI_FAILURE);
1233 }
1234 ddi_set_name_addr(child, name);
1235
1236 /*
1237 * Pseudo nodes indicate a prototype node with per-instance
1238 * properties to be merged into the real h/w device node.
1239 * The interpretation of the unit-address is DD[,F]
1240 * where DD is the device id and F is the function.
1241 */
1242 if (ndi_dev_is_persistent_node(child) == 0) {
1243 extern int pci_allow_pseudo_children;
1244
1245 ddi_set_parent_data(child, NULL);
1246
1247 /*
1248 * Try to merge the properties from this prototype
1249 * node into real h/w nodes.
1250 */
647 return (DDI_FAILURE);
648 }
649 ddi_set_name_addr(child, name);
650
651 /*
652 * Pseudo nodes indicate a prototype node with per-instance
653 * properties to be merged into the real h/w device node.
654 * The interpretation of the unit-address is DD[,F]
655 * where DD is the device id and F is the function.
656 */
657 if (ndi_dev_is_persistent_node(child) == 0) {
658 extern int pci_allow_pseudo_children;
659
660 ddi_set_parent_data(child, NULL);
661
662 /*
663 * Try to merge the properties from this prototype
664 * node into real h/w nodes.
665 */
1251 if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) {
666 if (ndi_merge_node(child, pci_common_name_child) ==
667 DDI_SUCCESS) {
1252 /*
1253 * Merged ok - return failure to remove the node.
1254 */
1255 ddi_set_name_addr(child, NULL);
1256 return (DDI_FAILURE);
1257 }
1258
1259 /* workaround for ddivs to run under PCI */

--- 5 unchanged lines hidden (view full) ---

1265 */
1266 if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
1267 DDI_PROP_DONTPASS, "interrupts", -1) == -1)
1268 return (DDI_SUCCESS);
1269 /*
1270 * Create the ddi_parent_private_data for a pseudo
1271 * child.
1272 */
668 /*
669 * Merged ok - return failure to remove the node.
670 */
671 ddi_set_name_addr(child, NULL);
672 return (DDI_FAILURE);
673 }
674
675 /* workaround for ddivs to run under PCI */

--- 5 unchanged lines hidden (view full) ---

681 */
682 if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
683 DDI_PROP_DONTPASS, "interrupts", -1) == -1)
684 return (DDI_SUCCESS);
685 /*
686 * Create the ddi_parent_private_data for a pseudo
687 * child.
688 */
1273 pdptr = (struct ddi_parent_private_data *)kmem_zalloc(
1274 (sizeof (struct ddi_parent_private_data) +
1275 sizeof (struct intrspec)), KM_SLEEP);
1276 pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1277 pdptr->par_nintr = 1;
1278 ddi_set_parent_data(child, pdptr);
689 pci_common_set_parent_private_data(child);
1279 return (DDI_SUCCESS);
1280 }
1281
1282 /*
1283 * The child was not merged into a h/w node,
1284 * but there's not much we can do with it other
1285 * than return failure to cause the node to be removed.
1286 */
1287 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
1288 ddi_get_name(child), ddi_get_name_addr(child),
1289 ddi_get_name(child));
1290 ddi_set_name_addr(child, NULL);
1291 return (DDI_NOT_WELL_FORMED);
1292 }
1293
1294 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
690 return (DDI_SUCCESS);
691 }
692
693 /*
694 * The child was not merged into a h/w node,
695 * but there's not much we can do with it other
696 * than return failure to cause the node to be removed.
697 */
698 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
699 ddi_get_name(child), ddi_get_name_addr(child),
700 ddi_get_name(child));
701 ddi_set_name_addr(child, NULL);
702 return (DDI_NOT_WELL_FORMED);
703 }
704
705 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
1295 "interrupts", -1) != -1) {
1296 pdptr = (struct ddi_parent_private_data *)
1297 kmem_zalloc((sizeof (struct ddi_parent_private_data) +
1298 sizeof (struct intrspec)), KM_SLEEP);
1299 pdptr->par_intr = (struct intrspec *)(pdptr + 1);
1300 pdptr->par_nintr = 1;
1301 ddi_set_parent_data(child, pdptr);
1302 } else
706 "interrupts", -1) != -1)
707 pci_common_set_parent_private_data(child);
708 else
1303 ddi_set_parent_data(child, NULL);
1304
1305 /*
1306 * initialize command register
1307 */
1308 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
1309 return (DDI_FAILURE);
1310

--- 308 unchanged lines hidden (view full) ---

1619 for (; repcount; repcount--)
1620 pci_config_wr64(hdlp, host_addr++, *dev_addr++);
1621 } else {
1622 for (; repcount; repcount--)
1623 pci_config_wr64(hdlp, host_addr++, *dev_addr);
1624 }
1625}
1626
709 ddi_set_parent_data(child, NULL);
710
711 /*
712 * initialize command register
713 */
714 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
715 return (DDI_FAILURE);
716

--- 308 unchanged lines hidden (view full) ---

1025 for (; repcount; repcount--)
1026 pci_config_wr64(hdlp, host_addr++, *dev_addr++);
1027 } else {
1028 for (; repcount; repcount--)
1029 pci_config_wr64(hdlp, host_addr++, *dev_addr);
1030 }
1031}
1032
1033
1627/*
1628 * When retrofitting this module for pci_tools, functions such as open, close,
1629 * and ioctl are now pulled into this module. Before this, the functions in
1630 * the pcihp module were referenced directly. Now they are called or
1631 * referenced through the pcihp cb_ops structure from functions in this module.
1632 */
1633
1634static int
1635pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1636{
1034/*
1035 * When retrofitting this module for pci_tools, functions such as open, close,
1036 * and ioctl are now pulled into this module. Before this, the functions in
1037 * the pcihp module were referenced directly. Now they are called or
1038 * referenced through the pcihp cb_ops structure from functions in this module.
1039 */
1040
1041static int
1042pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1043{
1637 return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp));
1044 return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
1638}
1639
1640static int
1641pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
1642{
1045}
1046
1047static int
1048pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
1049{
1643 return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp));
1050 return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
1644}
1645
1646static int
1051}
1052
1053static int
1647pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1648 int *rvalp)
1054pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
1649{
1650 minor_t minor = getminor(dev);
1651 int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
1652 pci_state_t *pci_p = ddi_get_soft_state(pci_statep, instance);
1055{
1056 minor_t minor = getminor(dev);
1057 int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor);
1058 pci_state_t *pci_p = ddi_get_soft_state(pci_statep, instance);
1653 dev_info_t *dip = pci_p->pci_dip;
1654 int rv = ENOTTY;
1655
1059
1656 switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
1657 case PCI_TOOL_REG_MINOR_NUM:
1060 if (pci_p == NULL)
1061 return (ENXIO);
1658
1062
1659 switch (cmd) {
1660 case PCITOOL_DEVICE_SET_REG:
1661 case PCITOOL_DEVICE_GET_REG:
1662
1663 /* Require full privileges. */
1664 if (secpolicy_kmdb(credp))
1665 rv = EPERM;
1666 else
1667 rv = pcitool_dev_reg_ops(
1668 dip, (void *)arg, cmd, mode);
1669 break;
1670
1671 case PCITOOL_NEXUS_SET_REG:
1672 case PCITOOL_NEXUS_GET_REG:
1673
1674 /* Require full privileges. */
1675 if (secpolicy_kmdb(credp))
1676 rv = EPERM;
1677 else
1678 rv = pcitool_bus_reg_ops(
1679 dip, (void *)arg, cmd, mode);
1680 break;
1681 }
1682 break;
1683
1684 case PCI_TOOL_INTR_MINOR_NUM:
1685
1686 switch (cmd) {
1687 case PCITOOL_DEVICE_SET_INTR:
1688
1689 /* Require PRIV_SYS_RES_CONFIG, same as psradm */
1690 if (secpolicy_ponline(credp)) {
1691 rv = EPERM;
1692 break;
1693 }
1694
1695 /*FALLTHRU*/
1696 /* These require no special privileges. */
1697 case PCITOOL_DEVICE_GET_INTR:
1698 case PCITOOL_DEVICE_NUM_INTR:
1699 rv = pcitool_intr_admn(dip, (void *)arg, cmd, mode);
1700 break;
1701 }
1702 break;
1703
1704 /*
1705 * All non-PCItool ioctls go through here, including:
1706 * devctl ioctls with minor number PCIHP_DEVCTL_MINOR and
1707 * those for attachment points with where minor number is the
1708 * device number.
1709 */
1710 default:
1711 rv = (pcihp_cb_ops.cb_ioctl)(dev, cmd, arg, mode,
1712 credp, rvalp);
1713 break;
1714 }
1715
1716 return (rv);
1063 return (pci_common_ioctl(pci_p->pci_dip,
1064 dev, cmd, arg, mode, credp, rvalp));
1717}
1718
1065}
1066
1067
1719static int
1720pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1721 int flags, char *name, caddr_t valuep, int *lengthp)
1722{
1068static int
1069pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
1070 int flags, char *name, caddr_t valuep, int *lengthp)
1071{
1723 return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags,
1072 return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
1724 name, valuep, lengthp));
1725}
1726
1727static int
1728pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1729{
1730 return (pcihp_info(dip, cmd, arg, result));
1731}
1073 name, valuep, lengthp));
1074}
1075
1076static int
1077pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1078{
1079 return (pcihp_info(dip, cmd, arg, result));
1080}