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