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