1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
27 * Copyright 2016 Joyent, Inc.
28 */
29
30 /*
31 * Host to PCI local bus driver
32 */
33
34 #include <sys/conf.h>
35 #include <sys/modctl.h>
36 #include <sys/pci.h>
37 #include <sys/pci_impl.h>
38 #include <sys/sysmacros.h>
39 #include <sys/sunndi.h>
40 #include <sys/ddifm.h>
41 #include <sys/ndifm.h>
42 #include <sys/fm/protocol.h>
43 #include <sys/hotplug/pci/pcihp.h>
44 #include <io/pci/pci_common.h>
45 #include <io/pci/pci_tools_ext.h>
46
47 /* Save minimal state. */
48 void *pci_statep;
49
50 /*
51 * Bus Operation functions
52 */
53 static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
54 off_t, off_t, caddr_t *);
55 static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
56 void *, void *);
57 static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
58 ddi_intr_handle_impl_t *, void *);
59 static int pci_fm_init(dev_info_t *, dev_info_t *, int,
60 ddi_iblock_cookie_t *);
61 static int pci_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
62
63 struct bus_ops pci_bus_ops = {
64 BUSO_REV,
65 pci_bus_map,
66 NULL,
67 NULL,
68 NULL,
69 i_ddi_map_fault,
70 NULL,
71 ddi_dma_allochdl,
72 ddi_dma_freehdl,
73 ddi_dma_bindhdl,
74 ddi_dma_unbindhdl,
75 ddi_dma_flush,
76 ddi_dma_win,
77 ddi_dma_mctl,
78 pci_ctlops,
79 ddi_bus_prop_op,
80 0, /* (*bus_get_eventcookie)(); */
81 0, /* (*bus_add_eventcall)(); */
82 0, /* (*bus_remove_eventcall)(); */
83 0, /* (*bus_post_event)(); */
84 0, /* (*bus_intr_ctl)(); */
85 0, /* (*bus_config)(); */
86 0, /* (*bus_unconfig)(); */
87 pci_fm_init, /* (*bus_fm_init)(); */
88 NULL, /* (*bus_fm_fini)(); */
89 NULL, /* (*bus_fm_access_enter)(); */
90 NULL, /* (*bus_fm_access_exit)(); */
91 NULL, /* (*bus_power)(); */
92 pci_intr_ops /* (*bus_intr_op)(); */
93 };
94
95 /*
96 * One goal here is to leverage off of the pcihp.c source without making
97 * changes to it. Call into it's cb_ops directly if needed, piggybacking
98 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
99 * will be opening PCI nexus driver file descriptors.
100 */
101 static int pci_open(dev_t *, int, int, cred_t *);
102 static int pci_close(dev_t, int, int, cred_t *);
103 static int pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
104 static int pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
105 caddr_t, int *);
106 static int pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
107 static void pci_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
108
109 struct cb_ops pci_cb_ops = {
110 pci_open, /* open */
111 pci_close, /* close */
112 nodev, /* strategy */
113 nodev, /* print */
114 nodev, /* dump */
115 nodev, /* read */
116 nodev, /* write */
117 pci_ioctl, /* ioctl */
118 nodev, /* devmap */
119 nodev, /* mmap */
120 nodev, /* segmap */
121 nochpoll, /* poll */
122 pci_prop_op, /* cb_prop_op */
123 NULL, /* streamtab */
124 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
125 CB_REV, /* rev */
126 nodev, /* int (*cb_aread)() */
127 nodev /* int (*cb_awrite)() */
128 };
129
130 /*
131 * Device Node Operation functions
132 */
133 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
134 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
135
136 struct dev_ops pci_ops = {
137 DEVO_REV, /* devo_rev */
138 0, /* refcnt */
139 pci_info, /* info */
140 nulldev, /* identify */
141 nulldev, /* probe */
142 pci_attach, /* attach */
143 pci_detach, /* detach */
144 nulldev, /* reset */
145 &pci_cb_ops, /* driver operations */
146 &pci_bus_ops, /* bus operations */
147 NULL, /* power */
148 ddi_quiesce_not_needed /* quiesce */
149 };
150
151 /*
152 * This variable controls the default setting of the command register
153 * for pci devices. See pci_initchild() for details.
154 */
155 static ushort_t pci_command_default = PCI_COMM_ME |
156 PCI_COMM_MAE |
157 PCI_COMM_IO;
158
159 /*
160 * Internal routines in support of particular pci_ctlops.
161 */
162 static int pci_removechild(dev_info_t *child);
163 static int pci_initchild(dev_info_t *child);
164
165 /*
166 * Module linkage information for the kernel.
167 */
168
169 static struct modldrv modldrv = {
170 &mod_driverops, /* Type of module */
171 "x86 Host to PCI nexus driver", /* Name of module */
172 &pci_ops, /* driver ops */
173 };
174
175 static struct modlinkage modlinkage = {
176 MODREV_1,
177 (void *)&modldrv,
178 NULL
179 };
180
181 int
_init(void)182 _init(void)
183 {
184 int e;
185
186 /*
187 * Initialize per-pci bus soft state pointer.
188 */
189 e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
190 if (e != 0)
191 return (e);
192
193 if ((e = mod_install(&modlinkage)) != 0)
194 ddi_soft_state_fini(&pci_statep);
195
196 return (e);
197 }
198
199 int
_fini(void)200 _fini(void)
201 {
202 int rc;
203
204 rc = mod_remove(&modlinkage);
205 if (rc != 0)
206 return (rc);
207
208 ddi_soft_state_fini(&pci_statep);
209
210 return (rc);
211 }
212
213 int
_info(struct modinfo * modinfop)214 _info(struct modinfo *modinfop)
215 {
216 return (mod_info(&modlinkage, modinfop));
217 }
218
219 /*ARGSUSED*/
220 static int
pci_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)221 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
222 {
223 /*
224 * Use the minor number as constructed by pcihp, as the index value to
225 * ddi_soft_state_zalloc.
226 */
227 int instance = ddi_get_instance(devi);
228 pci_state_t *pcip = NULL;
229 switch (cmd) {
230 case DDI_ATTACH:
231 break;
232
233 case DDI_RESUME:
234 return (DDI_SUCCESS);
235
236 default:
237 return (DDI_FAILURE);
238 }
239
240 if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
241 != DDI_PROP_SUCCESS) {
242 cmn_err(CE_WARN, "pci: 'device_type' prop create failed");
243 }
244
245 if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
246 pcip = ddi_get_soft_state(pci_statep, instance);
247 }
248
249 if (pcip == NULL) {
250 goto bad_soft_state;
251 }
252
253 pcip->pci_dip = devi;
254 pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED;
255
256 /*
257 * Initialize hotplug support on this bus. At minimum
258 * (for non hotplug bus) this would create ":devctl" minor
259 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
260 * to this bus.
261 */
262 if (pcihp_init(devi) != DDI_SUCCESS) {
263 cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
264 goto bad_pcihp_init;
265 }
266
267 /* Second arg: initialize for pci, not pci_express */
268 if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
269 goto bad_pcitool_init;
270 }
271
272 pcip->pci_fmcap = DDI_FM_ERRCB_CAPABLE |
273 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
274 ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc);
275 mutex_init(&pcip->pci_mutex, NULL, MUTEX_DRIVER, NULL);
276 mutex_init(&pcip->pci_err_mutex, NULL, MUTEX_DRIVER,
277 (void *)pcip->pci_fm_ibc);
278 mutex_init(&pcip->pci_peek_poke_mutex, NULL, MUTEX_DRIVER,
279 (void *)pcip->pci_fm_ibc);
280 if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
281 pci_ereport_setup(devi);
282 ddi_fm_handler_register(devi, pci_fm_callback, NULL);
283 }
284
285 ddi_report_dev(devi);
286
287 return (DDI_SUCCESS);
288
289 bad_pcitool_init:
290 (void) pcihp_uninit(devi);
291 bad_pcihp_init:
292 ddi_soft_state_free(pci_statep, instance);
293 bad_soft_state:
294 return (DDI_FAILURE);
295 }
296
297 /*ARGSUSED*/
298 static int
pci_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)299 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
300 {
301 int instance = ddi_get_instance(devi);
302 pci_state_t *pcip;
303
304 pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(devi));
305
306
307 switch (cmd) {
308 case DDI_DETACH:
309 if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
310 ddi_fm_handler_unregister(devi);
311 pci_ereport_teardown(devi);
312 }
313 mutex_destroy(&pcip->pci_peek_poke_mutex);
314 mutex_destroy(&pcip->pci_err_mutex);
315 mutex_destroy(&pcip->pci_mutex);
316 ddi_fm_fini(devi); /* Uninitialize pcitool support. */
317 pcitool_uninit(devi);
318
319 /* Uninitialize hotplug support on this bus. */
320 (void) pcihp_uninit(devi);
321
322 ddi_soft_state_free(pci_statep, instance);
323
324 return (DDI_SUCCESS);
325 case DDI_SUSPEND:
326 return (DDI_SUCCESS);
327 default:
328 return (DDI_FAILURE);
329 }
330 }
331
332 static int
pci_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)333 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
334 off_t offset, off_t len, caddr_t *vaddrp)
335 {
336 struct regspec64 reg;
337 ddi_map_req_t mr;
338 ddi_acc_hdl_t *hp;
339 ddi_acc_impl_t *hdlp;
340 pci_regspec_t pci_reg;
341 pci_regspec_t *pci_rp;
342 int rnumber;
343 uint64_t pci_rlength;
344 uint_t nelems;
345 pci_acc_cfblk_t *cfp;
346 int space;
347 pci_state_t *pcip;
348
349 mr = *mp; /* Get private copy of request */
350 mp = &mr;
351
352 if (mp->map_handlep != NULL) {
353 pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
354 hdlp = (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
355 hdlp->ahi_err_mutexp = &pcip->pci_err_mutex;
356 hdlp->ahi_peekpoke_mutexp = &pcip->pci_peek_poke_mutex;
357 hdlp->ahi_scan_dip = dip;
358 hdlp->ahi_scan = pci_peekpoke_cb;
359 }
360
361 /*
362 * check for register number
363 */
364 switch (mp->map_type) {
365 case DDI_MT_REGSPEC:
366 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
367 pci_rp = &pci_reg;
368 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
369 return (DDI_FAILURE);
370 break;
371 case DDI_MT_RNUMBER:
372 rnumber = mp->map_obj.rnumber;
373 /*
374 * get ALL "reg" properties for dip, select the one of
375 * of interest. In x86, "assigned-addresses" property
376 * is identical to the "reg" property, so there is no
377 * need to cross check the two to determine the physical
378 * address of the registers.
379 * This routine still performs some validity checks to
380 * make sure that everything is okay.
381 */
382 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
383 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &nelems) !=
384 DDI_PROP_SUCCESS)
385 return (DDI_FAILURE);
386
387 /*
388 * validate the register number.
389 */
390 nelems /= (sizeof (pci_regspec_t) / sizeof (int));
391 if (rnumber >= nelems) {
392 ddi_prop_free(pci_rp);
393 return (DDI_FAILURE);
394 }
395
396 /*
397 * copy the required entry.
398 */
399 pci_reg = pci_rp[rnumber];
400
401 /*
402 * free the memory allocated by ddi_prop_lookup_int_array
403 */
404 ddi_prop_free(pci_rp);
405
406 pci_rp = &pci_reg;
407 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
408 return (DDI_FAILURE);
409 mp->map_type = DDI_MT_REGSPEC;
410 break;
411 default:
412 return (DDI_ME_INVAL);
413 }
414
415 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
416
417 /*
418 * check for unmap and unlock of address space
419 */
420 if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
421 switch (space) {
422 case PCI_ADDR_CONFIG:
423 /* No work required on unmap of Config space */
424 return (DDI_SUCCESS);
425
426 case PCI_ADDR_IO:
427 reg.regspec_bustype = 1;
428 break;
429
430 case PCI_ADDR_MEM64:
431 case PCI_ADDR_MEM32:
432 reg.regspec_bustype = 0;
433 break;
434
435 default:
436 return (DDI_FAILURE);
437 }
438
439 reg.regspec_addr = (uint64_t)pci_rp->pci_phys_mid << 32 |
440 (uint64_t)pci_rp->pci_phys_low;
441 reg.regspec_size = (uint64_t)pci_rp->pci_size_hi << 32 |
442 (uint64_t)pci_rp->pci_size_low;
443
444 /*
445 * Adjust offset and length
446 * A non-zero length means override the one in the regspec.
447 */
448 if (reg.regspec_addr + offset < MAX(reg.regspec_addr, offset))
449 return (DDI_FAILURE);
450 reg.regspec_addr += offset;
451 if (len != 0)
452 reg.regspec_size = len;
453
454 mp->map_obj.rp = (struct regspec *)®
455 mp->map_flags |= DDI_MF_EXT_REGSPEC;
456 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
457
458 }
459
460 /* check for user mapping request - not legal for Config */
461 if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
462 return (DDI_FAILURE);
463 }
464
465 /*
466 * check for config space
467 * On x86, CONFIG is not mapped via MMU and there is
468 * no endian-ness issues. Set the attr field in the handle to
469 * indicate that the common routines to call the nexus driver.
470 */
471 if (space == PCI_ADDR_CONFIG) {
472 /* Can't map config space without a handle */
473 hp = (ddi_acc_hdl_t *)mp->map_handlep;
474 if (hp == NULL)
475 return (DDI_FAILURE);
476
477 /* record the device address for future reference */
478 cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
479 cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
480 cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
481 cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
482
483 *vaddrp = (caddr_t)offset;
484 return (pci_fm_acc_setup(hp, offset, len));
485 }
486
487 /*
488 * range check
489 */
490 pci_rlength = (uint64_t)pci_rp->pci_size_low |
491 (uint64_t)pci_rp->pci_size_hi << 32;
492 if ((offset >= pci_rlength) || (len > pci_rlength) ||
493 (offset + len > pci_rlength) || (offset + len < MAX(offset, len))) {
494 return (DDI_FAILURE);
495 }
496
497 /*
498 * convert the pci regsec into the generic regspec used by the
499 * parent root nexus driver.
500 */
501 switch (space) {
502 case PCI_ADDR_IO:
503 reg.regspec_bustype = 1;
504 break;
505 case PCI_ADDR_MEM64:
506 case PCI_ADDR_MEM32:
507 reg.regspec_bustype = 0;
508 break;
509 default:
510 return (DDI_FAILURE);
511 }
512
513 reg.regspec_addr = (uint64_t)pci_rp->pci_phys_mid << 32 |
514 (uint64_t)pci_rp->pci_phys_low;
515 reg.regspec_size = pci_rlength;
516
517 /*
518 * Adjust offset and length
519 * A non-zero length means override the one in the regspec.
520 */
521 if (reg.regspec_addr + offset < MAX(reg.regspec_addr, offset))
522 return (DDI_FAILURE);
523 reg.regspec_addr += offset;
524 if (len != 0)
525 reg.regspec_size = len;
526
527 mp->map_obj.rp = (struct regspec *)®
528 mp->map_flags |= DDI_MF_EXT_REGSPEC;
529 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
530 }
531
532
533 /*ARGSUSED*/
534 static int
pci_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)535 pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
536 ddi_ctl_enum_t ctlop, void *arg, void *result)
537 {
538 pci_regspec_t *drv_regp;
539 uint_t reglen;
540 int totreg;
541 pci_state_t *pcip;
542 struct attachspec *asp;
543 struct detachspec *dsp;
544
545 switch (ctlop) {
546 case DDI_CTLOPS_REPORTDEV:
547 if (rdip == (dev_info_t *)0)
548 return (DDI_FAILURE);
549 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
550 ddi_node_name(rdip), ddi_get_name_addr(rdip),
551 ddi_driver_name(rdip),
552 ddi_get_instance(rdip));
553 return (DDI_SUCCESS);
554
555 case DDI_CTLOPS_INITCHILD:
556 return (pci_initchild((dev_info_t *)arg));
557
558 case DDI_CTLOPS_UNINITCHILD:
559 return (pci_removechild((dev_info_t *)arg));
560
561 case DDI_CTLOPS_SIDDEV:
562 return (DDI_SUCCESS);
563
564 case DDI_CTLOPS_REGSIZE:
565 case DDI_CTLOPS_NREGS:
566 if (rdip == (dev_info_t *)0)
567 return (DDI_FAILURE);
568
569 *(int *)result = 0;
570 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
571 DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
572 ®len) != DDI_PROP_SUCCESS) {
573 return (DDI_FAILURE);
574 }
575
576 totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
577 if (ctlop == DDI_CTLOPS_NREGS)
578 *(int *)result = totreg;
579 else if (ctlop == DDI_CTLOPS_REGSIZE) {
580 uint64_t val;
581 int rn;
582
583 rn = *(int *)arg;
584 if (rn >= totreg) {
585 ddi_prop_free(drv_regp);
586 return (DDI_FAILURE);
587 }
588 val = drv_regp[rn].pci_size_low |
589 (uint64_t)drv_regp[rn].pci_size_hi << 32;
590 if (val > OFF_MAX) {
591 int ce = CE_NOTE;
592 #ifdef DEBUG
593 ce = CE_WARN;
594 #endif
595 dev_err(rdip, ce, "failed to get register "
596 "size, value larger than OFF_MAX: 0x%"
597 PRIx64 "\n", val);
598 return (DDI_FAILURE);
599 }
600 *(off_t *)result = (off_t)val;
601 }
602 ddi_prop_free(drv_regp);
603
604 return (DDI_SUCCESS);
605
606 case DDI_CTLOPS_POWER: {
607 power_req_t *reqp = (power_req_t *)arg;
608 /*
609 * We currently understand reporting of PCI_PM_IDLESPEED
610 * capability. Everything else is passed up.
611 */
612 if ((reqp->request_type == PMR_REPORT_PMCAP) &&
613 (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED)) {
614
615 return (DDI_SUCCESS);
616 }
617 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
618 }
619
620 case DDI_CTLOPS_PEEK:
621 case DDI_CTLOPS_POKE:
622 pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
623 return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
624 pci_common_peekpoke, &pcip->pci_err_mutex,
625 &pcip->pci_peek_poke_mutex, pci_peekpoke_cb));
626
627 /* for now only X86 systems support PME wakeup from suspended state */
628 case DDI_CTLOPS_ATTACH:
629 asp = (struct attachspec *)arg;
630 if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
631 if (pci_pre_resume(rdip) != DDI_SUCCESS)
632 return (DDI_FAILURE);
633 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
634
635 case DDI_CTLOPS_DETACH:
636 dsp = (struct detachspec *)arg;
637 if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
638 if (pci_post_suspend(rdip) != DDI_SUCCESS)
639 return (DDI_FAILURE);
640 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
641
642 default:
643 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
644 }
645
646 /* NOTREACHED */
647
648 }
649
650 /*
651 * pci_intr_ops
652 */
653 static int
pci_intr_ops(dev_info_t * pdip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)654 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
655 ddi_intr_handle_impl_t *hdlp, void *result)
656 {
657 return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
658 }
659
660
661 static int
pci_initchild(dev_info_t * child)662 pci_initchild(dev_info_t *child)
663 {
664 char name[80];
665 ddi_acc_handle_t config_handle;
666 ushort_t command_preserve, command;
667
668 if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
669 return (DDI_FAILURE);
670 }
671 ddi_set_name_addr(child, name);
672
673 /*
674 * Pseudo nodes indicate a prototype node with per-instance
675 * properties to be merged into the real h/w device node.
676 * The interpretation of the unit-address is DD[,F]
677 * where DD is the device id and F is the function.
678 */
679 if (ndi_dev_is_persistent_node(child) == 0) {
680 extern int pci_allow_pseudo_children;
681
682 ddi_set_parent_data(child, NULL);
683
684 /*
685 * Try to merge the properties from this prototype
686 * node into real h/w nodes.
687 */
688 if (ndi_merge_node(child, pci_common_name_child) ==
689 DDI_SUCCESS) {
690 /*
691 * Merged ok - return failure to remove the node.
692 */
693 ddi_set_name_addr(child, NULL);
694 return (DDI_FAILURE);
695 }
696
697 /* workaround for ddivs to run under PCI */
698 if (pci_allow_pseudo_children) {
699 /*
700 * If the "interrupts" property doesn't exist,
701 * this must be the ddivs no-intr case, and it returns
702 * DDI_SUCCESS instead of DDI_FAILURE.
703 */
704 if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
705 DDI_PROP_DONTPASS, "interrupts", -1) == -1)
706 return (DDI_SUCCESS);
707 /*
708 * Create the ddi_parent_private_data for a pseudo
709 * child.
710 */
711 pci_common_set_parent_private_data(child);
712 return (DDI_SUCCESS);
713 }
714
715 /*
716 * The child was not merged into a h/w node,
717 * but there's not much we can do with it other
718 * than return failure to cause the node to be removed.
719 */
720 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
721 ddi_get_name(child), ddi_get_name_addr(child),
722 ddi_get_name(child));
723 ddi_set_name_addr(child, NULL);
724 return (DDI_NOT_WELL_FORMED);
725 }
726
727 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
728 "interrupts", -1) != -1)
729 pci_common_set_parent_private_data(child);
730 else
731 ddi_set_parent_data(child, NULL);
732
733 /*
734 * initialize command register
735 */
736 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
737 return (DDI_FAILURE);
738
739 /*
740 * Support for the "command-preserve" property.
741 */
742 command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
743 DDI_PROP_DONTPASS, "command-preserve", 0);
744 command = pci_config_get16(config_handle, PCI_CONF_COMM);
745 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
746 command |= (pci_command_default & ~command_preserve);
747 pci_config_put16(config_handle, PCI_CONF_COMM, command);
748
749 pci_config_teardown(&config_handle);
750 return (DDI_SUCCESS);
751 }
752
753 static int
pci_removechild(dev_info_t * dip)754 pci_removechild(dev_info_t *dip)
755 {
756 struct ddi_parent_private_data *pdptr;
757
758 if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
759 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
760 ddi_set_parent_data(dip, NULL);
761 }
762 ddi_set_name_addr(dip, NULL);
763
764 /*
765 * Strip the node to properly convert it back to prototype form
766 */
767 ddi_remove_minor_node(dip, NULL);
768
769 impl_rem_dev_props(dip);
770
771 return (DDI_SUCCESS);
772 }
773
774
775 /*
776 * When retrofitting this module for pci_tools, functions such as open, close,
777 * and ioctl are now pulled into this module. Before this, the functions in
778 * the pcihp module were referenced directly. Now they are called or
779 * referenced through the pcihp cb_ops structure from functions in this module.
780 */
781
782 static int
pci_open(dev_t * devp,int flags,int otyp,cred_t * credp)783 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
784 {
785 return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
786 }
787
788 static int
pci_close(dev_t dev,int flags,int otyp,cred_t * credp)789 pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
790 {
791 return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
792 }
793
794 static int
pci_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)795 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
796 {
797 minor_t minor = getminor(dev);
798 int instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
799 pci_state_t *pci_p = ddi_get_soft_state(pci_statep, instance);
800 int ret = ENOTTY;
801
802 if (pci_p == NULL)
803 return (ENXIO);
804
805 switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
806 case PCI_TOOL_REG_MINOR_NUM:
807 case PCI_TOOL_INTR_MINOR_NUM:
808 /* To handle pcitool related ioctls */
809 ret = pci_common_ioctl(pci_p->pci_dip, dev, cmd, arg, mode,
810 credp, rvalp);
811 break;
812 default:
813 /* To handle devctl and hotplug related ioctls */
814 ret = (pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode,
815 credp, rvalp);
816 break;
817 }
818
819 return (ret);
820 }
821
822
823 static int
pci_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int flags,char * name,caddr_t valuep,int * lengthp)824 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
825 int flags, char *name, caddr_t valuep, int *lengthp)
826 {
827 return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
828 name, valuep, lengthp));
829 }
830
831 static int
pci_info(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)832 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
833 {
834 return (pcihp_info(dip, cmd, arg, result));
835 }
836
pci_peekpoke_cb(dev_info_t * dip,ddi_fm_error_t * derr)837 void pci_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
838 (void) pci_ereport_post(dip, derr, NULL);
839 }
840
841 /*ARGSUSED*/
842 static int
pci_fm_init(dev_info_t * dip,dev_info_t * tdip,int cap,ddi_iblock_cookie_t * ibc)843 pci_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
844 ddi_iblock_cookie_t *ibc)
845 {
846 pci_state_t *pcip = ddi_get_soft_state(pci_statep,
847 ddi_get_instance(dip));
848
849 ASSERT(ibc != NULL);
850 *ibc = pcip->pci_fm_ibc;
851
852 return (pcip->pci_fmcap);
853 }
854
855 /*ARGSUSED*/
856 static int
pci_fm_callback(dev_info_t * dip,ddi_fm_error_t * derr,const void * no_used)857 pci_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
858 {
859 pci_state_t *pcip = ddi_get_soft_state(pci_statep,
860 ddi_get_instance(dip));
861
862 mutex_enter(&pcip->pci_err_mutex);
863 pci_ereport_post(dip, derr, NULL);
864 mutex_exit(&pcip->pci_err_mutex);
865 return (derr->fme_status);
866 }
867