Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/tphci.c
+++ new/usr/src/uts/common/io/tphci.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 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * The tphci driver can be used to exercise the mpxio framework together
29 29 * with tvhci/tclient.
30 30 */
31 31
32 32 #include <sys/conf.h>
33 33 #include <sys/file.h>
34 34 #include <sys/open.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/modctl.h>
37 37 #include <sys/ddi.h>
38 38 #include <sys/sunddi.h>
39 39 #include <sys/sunndi.h>
40 40 #include <sys/sunmdi.h>
41 41 #include <sys/disp.h>
42 42
43 43 /* cb_ops entry points */
44 44 static int tphci_open(dev_t *, int, int, cred_t *);
45 45 static int tphci_close(dev_t, int, int, cred_t *);
46 46 static int tphci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
47 47 static int tphci_attach(dev_info_t *, ddi_attach_cmd_t);
48 48 static int tphci_detach(dev_info_t *, ddi_detach_cmd_t);
49 49 static int tphci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
50 50
51 51 /* bus_ops entry points */
52 52 static int tphci_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
53 53 void *);
54 54 static int tphci_initchild(dev_info_t *, dev_info_t *);
55 55 static int tphci_uninitchild(dev_info_t *, dev_info_t *);
56 56 static int tphci_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *,
57 57 dev_info_t **);
58 58 static int tphci_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
59 59 void *);
60 60 static int tphci_intr_op(dev_info_t *dip, dev_info_t *rdip,
61 61 ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp, void *result);
62 62
63 63
64 64 static void *tphci_state;
65 65 struct tphci_state {
66 66 dev_info_t *dip;
67 67 };
68 68
69 69 static struct cb_ops tphci_cb_ops = {
70 70 tphci_open, /* open */
71 71 tphci_close, /* close */
72 72 nodev, /* strategy */
73 73 nodev, /* print */
74 74 nodev, /* dump */
75 75 nodev, /* read */
76 76 nodev, /* write */
77 77 tphci_ioctl, /* ioctl */
78 78 nodev, /* devmap */
79 79 nodev, /* mmap */
80 80 nodev, /* segmap */
81 81 nochpoll, /* chpoll */
82 82 ddi_prop_op, /* cb_prop_op */
83 83 0, /* streamtab */
84 84 D_NEW | D_MP, /* cb_flag */
85 85 CB_REV, /* rev */
86 86 nodev, /* aread */
87 87 nodev /* awrite */
88 88 };
89 89
90 90 static struct bus_ops tphci_bus_ops = {
91 91 BUSO_REV, /* busops_rev */
92 92 nullbusmap, /* bus_map */
93 93 NULL, /* bus_get_intrspec */
94 94 NULL, /* bus_add_interspec */
95 95 NULL, /* bus_remove_interspec */
96 96 i_ddi_map_fault, /* bus_map_fault */
97 97 ddi_no_dma_map, /* bus_dma_map */
98 98 ddi_no_dma_allochdl, /* bus_dma_allochdl */
99 99 NULL, /* bus_dma_freehdl */
100 100 NULL, /* bus_dma_bindhdl */
101 101 NULL, /* bus_dma_unbindhdl */
102 102 NULL, /* bus_dma_flush */
103 103 NULL, /* bus_dma_win */
104 104 NULL, /* bus_dma_ctl */
105 105 tphci_ctl, /* bus_ctl */
106 106 ddi_bus_prop_op, /* bus_prop_op */
107 107 NULL, /* bus_get_eventcookie */
108 108 NULL, /* bus_add_eventcall */
109 109 NULL, /* bus_remove_event */
110 110 NULL, /* bus_post_event */
111 111 NULL, /* bus_intr_ctl */
112 112 tphci_bus_config, /* bus_config */
113 113 tphci_bus_unconfig, /* bus_unconfig */
114 114 NULL, /* bus_fm_init */
115 115 NULL, /* bus_fm_fini */
116 116 NULL, /* bus_fm_access_enter */
117 117 NULL, /* bus_fm_access_exit */
118 118 NULL, /* bus_power */
119 119 tphci_intr_op /* bus_intr_op */
120 120 };
121 121
122 122 static struct dev_ops tphci_ops = {
123 123 DEVO_REV,
124 124 0,
125 125 tphci_getinfo,
126 126 nulldev, /* identify */
127 127 nulldev, /* probe */
128 128 tphci_attach, /* attach and detach are mandatory */
129 129 tphci_detach,
130 130 nodev, /* reset */
131 131 &tphci_cb_ops, /* cb_ops */
132 132 &tphci_bus_ops, /* bus_ops */
133 133 NULL, /* power */
134 134 ddi_quiesce_not_needed, /* quiesce */
135 135 };
136 136
↓ open down ↓ |
136 lines elided |
↑ open up ↑ |
137 137 extern struct mod_ops mod_driverops;
138 138
139 139 static struct modldrv modldrv = {
140 140 &mod_driverops,
141 141 "test phci driver",
142 142 &tphci_ops
143 143 };
144 144
145 145 static struct modlinkage modlinkage = {
146 146 MODREV_1,
147 - &modldrv,
148 - NULL
147 + { &modldrv, NULL }
149 148 };
150 149
151 150 int
152 151 _init(void)
153 152 {
154 153 int rval;
155 154
156 155 if ((rval = ddi_soft_state_init(&tphci_state,
157 156 sizeof (struct tphci_state), 2)) != 0) {
158 157 return (rval);
159 158 }
160 159
161 160 if ((rval = mod_install(&modlinkage)) != 0) {
162 161 ddi_soft_state_fini(&tphci_state);
163 162 }
164 163 return (rval);
165 164 }
166 165
167 166
168 167 int
169 168 _fini(void)
170 169 {
171 170 int rval;
172 171
173 172 /*
174 173 * don't start cleaning up until we know that the module remove
175 174 * has worked -- if this works, then we know that each instance
176 175 * has successfully been detached
177 176 */
178 177 if ((rval = mod_remove(&modlinkage)) != 0) {
179 178 return (rval);
180 179 }
181 180
182 181 ddi_soft_state_fini(&tphci_state);
183 182
184 183 return (rval);
185 184 }
186 185
187 186 int
188 187 _info(struct modinfo *modinfop)
189 188 {
190 189 return (mod_info(&modlinkage, modinfop));
191 190 }
192 191
193 192 /* ARGSUSED */
194 193 static int
195 194 tphci_open(dev_t *devp, int flag, int otype, cred_t *credp)
196 195 {
197 196 struct tphci_state *phci;
198 197
199 198 if (otype != OTYP_CHR) {
200 199 return (EINVAL);
201 200 }
202 201
203 202 phci = ddi_get_soft_state(tphci_state, getminor(*devp));
204 203 if (phci == NULL) {
205 204 return (ENXIO);
206 205 }
207 206
208 207 return (0);
209 208 }
210 209
211 210
212 211 /* ARGSUSED */
213 212 static int
214 213 tphci_close(dev_t dev, int flag, int otype, cred_t *credp)
215 214 {
216 215 struct tphci_state *phci;
217 216 if (otype != OTYP_CHR) {
218 217 return (EINVAL);
219 218 }
220 219
221 220 phci = ddi_get_soft_state(tphci_state, getminor(dev));
222 221 if (phci == NULL) {
223 222 return (ENXIO);
224 223 }
225 224
226 225 return (0);
227 226 }
228 227
229 228 /* ARGSUSED */
230 229 static int
231 230 tphci_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
232 231 cred_t *credp, int *rval)
233 232 {
234 233 return (0);
235 234 }
236 235
237 236 /*
238 237 * attach the module
239 238 */
240 239 static int
241 240 tphci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
242 241 {
243 242 char *vclass;
244 243 int instance, phci_regis = 0;
245 244 struct tphci_state *phci = NULL;
246 245
247 246 instance = ddi_get_instance(dip);
248 247
249 248 switch (cmd) {
250 249 case DDI_ATTACH:
251 250 break;
252 251
253 252 case DDI_RESUME:
254 253 case DDI_PM_RESUME:
255 254 return (0); /* nothing to do */
256 255
257 256 default:
258 257 return (DDI_FAILURE);
259 258 }
260 259
261 260 /*
262 261 * Allocate phci data structure.
263 262 */
264 263 if (ddi_soft_state_zalloc(tphci_state, instance) != DDI_SUCCESS) {
265 264 return (DDI_FAILURE);
266 265 }
267 266
268 267 phci = ddi_get_soft_state(tphci_state, instance);
269 268 ASSERT(phci != NULL);
270 269 phci->dip = dip;
271 270
272 271 /* bus_addr has the form #,<vhci_class> */
273 272 vclass = strchr(ddi_get_name_addr(dip), ',');
274 273 if (vclass == NULL || vclass[1] == '\0') {
275 274 cmn_err(CE_NOTE, "tphci invalid bus_addr %s",
276 275 ddi_get_name_addr(dip));
277 276 goto attach_fail;
278 277 }
279 278
280 279 /*
281 280 * Attach this instance with the mpxio framework
282 281 */
283 282 if (mdi_phci_register(vclass + 1, dip, 0) != MDI_SUCCESS) {
284 283 cmn_err(CE_WARN, "%s mdi_phci_register failed",
285 284 ddi_node_name(dip));
286 285 goto attach_fail;
287 286 }
288 287 phci_regis++;
289 288
290 289 if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
291 290 instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
292 291 cmn_err(CE_NOTE, "%s ddi_create_minor_node failed",
293 292 ddi_node_name(dip));
294 293 goto attach_fail;
295 294 }
296 295
297 296 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
298 297 ddi_report_dev(dip);
299 298 return (DDI_SUCCESS);
300 299
301 300 attach_fail:
302 301 if (phci_regis)
303 302 (void) mdi_phci_unregister(dip, 0);
304 303
305 304 ddi_soft_state_free(tphci_state, instance);
306 305 return (DDI_FAILURE);
307 306 }
308 307
309 308
310 309 /*ARGSUSED*/
311 310 static int
312 311 tphci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
313 312 {
314 313 int instance = ddi_get_instance(dip);
315 314
316 315 switch (cmd) {
317 316 case DDI_DETACH:
318 317 break;
319 318
320 319 case DDI_SUSPEND:
321 320 case DDI_PM_SUSPEND:
322 321 return (0); /* nothing to do */
323 322
324 323 default:
325 324 return (DDI_FAILURE);
326 325 }
327 326
328 327 if (mdi_phci_unregister(dip, 0) != MDI_SUCCESS)
329 328 return (DDI_FAILURE);
330 329
331 330 ddi_remove_minor_node(dip, NULL);
332 331 ddi_soft_state_free(tphci_state, instance);
333 332
334 333 return (DDI_SUCCESS);
335 334 }
336 335
337 336 /*
338 337 * tphci_getinfo()
339 338 * Given the device number, return the devinfo pointer or the
340 339 * instance number.
341 340 * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach.
342 341 */
343 342
344 343 /*ARGSUSED*/
345 344 static int
346 345 tphci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
347 346 {
348 347 struct tphci_state *phci;
349 348 int instance = getminor((dev_t)arg);
350 349
351 350 switch (cmd) {
352 351 case DDI_INFO_DEVT2DEVINFO:
353 352 phci = ddi_get_soft_state(tphci_state, instance);
354 353 if (phci != NULL)
355 354 *result = phci->dip;
356 355 else {
357 356 *result = NULL;
358 357 return (DDI_FAILURE);
359 358 }
360 359 break;
361 360
362 361 case DDI_INFO_DEVT2INSTANCE:
363 362 *result = (void *)(uintptr_t)instance;
364 363 break;
365 364
366 365 default:
367 366 return (DDI_FAILURE);
368 367 }
369 368
370 369 return (DDI_SUCCESS);
371 370 }
372 371
373 372 /*
374 373 * Interrupt stuff. NO OP for pseudo drivers.
375 374 */
376 375 /*ARGSUSED*/
377 376 static int
378 377 tphci_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
379 378 ddi_intr_handle_impl_t *hdlp, void *result)
380 379 {
381 380 return (DDI_FAILURE);
382 381 }
383 382
384 383 static int
385 384 tphci_ctl(dev_info_t *dip, dev_info_t *rdip,
386 385 ddi_ctl_enum_t ctlop, void *arg, void *result)
387 386 {
388 387 switch (ctlop) {
389 388 case DDI_CTLOPS_REPORTDEV:
390 389 if (rdip == (dev_info_t *)0)
391 390 return (DDI_FAILURE);
392 391 cmn_err(CE_CONT, "?tphci-device: %s%d\n",
393 392 ddi_get_name(rdip), ddi_get_instance(rdip));
394 393 return (DDI_SUCCESS);
395 394
396 395 case DDI_CTLOPS_INITCHILD:
397 396 {
398 397 dev_info_t *child = (dev_info_t *)arg;
399 398 return (tphci_initchild(dip, child));
400 399 }
401 400
402 401 case DDI_CTLOPS_UNINITCHILD:
403 402 {
404 403 dev_info_t *child = (dev_info_t *)arg;
405 404 return (tphci_uninitchild(dip, child));
406 405 }
407 406
408 407 case DDI_CTLOPS_DMAPMAPC:
409 408 case DDI_CTLOPS_REPORTINT:
410 409 case DDI_CTLOPS_REGSIZE:
411 410 case DDI_CTLOPS_NREGS:
412 411 case DDI_CTLOPS_SIDDEV:
413 412 case DDI_CTLOPS_SLAVEONLY:
414 413 case DDI_CTLOPS_AFFINITY:
415 414 case DDI_CTLOPS_POKE:
416 415 case DDI_CTLOPS_PEEK:
417 416 /*
418 417 * These ops correspond to functions that "shouldn't" be called
419 418 * by a pseudo driver. So we whine when we're called.
420 419 */
421 420 cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d\n",
422 421 ddi_get_name(dip), ddi_get_instance(dip),
423 422 ctlop, ddi_get_name(rdip), ddi_get_instance(rdip));
424 423 return (DDI_FAILURE);
425 424
426 425 case DDI_CTLOPS_ATTACH:
427 426 case DDI_CTLOPS_BTOP:
428 427 case DDI_CTLOPS_BTOPR:
429 428 case DDI_CTLOPS_DETACH:
430 429 case DDI_CTLOPS_DVMAPAGESIZE:
431 430 case DDI_CTLOPS_IOMIN:
432 431 case DDI_CTLOPS_POWER:
433 432 case DDI_CTLOPS_PTOB:
434 433 default:
435 434 /*
436 435 * The ops that we pass up (default). We pass up memory
437 436 * allocation oriented ops that we receive - these may be
438 437 * associated with pseudo HBA drivers below us with target
439 438 * drivers below them that use ddi memory allocation
440 439 * interfaces like scsi_alloc_consistent_buf.
441 440 */
442 441 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
443 442 }
444 443 }
445 444
446 445 static int
447 446 tphci_initchild(dev_info_t *dip, dev_info_t *child)
448 447 {
449 448 _NOTE(ARGUNUSED(dip))
450 449 ddi_set_name_addr(child, "0");
451 450 return (DDI_SUCCESS);
452 451 }
453 452
454 453 /*ARGSUSED*/
455 454 static int
456 455 tphci_uninitchild(dev_info_t *dip, dev_info_t *child)
457 456 {
458 457 ddi_set_name_addr(child, NULL);
459 458 return (DDI_SUCCESS);
460 459 }
461 460
462 461 static int
463 462 tp_decode_name(char *devnm, char **cname, char **paddr, char **guid)
464 463 {
465 464 char *tmp;
466 465
467 466 i_ddi_parse_name(devnm, cname, paddr, NULL);
468 467 if ((strcmp(*cname, "tclient") != 0) &&
469 468 (strcmp(*cname, "tphci") != 0) || *paddr == NULL)
470 469 return (-1);
471 470
472 471 tmp = strchr(*paddr, ',');
473 472 if (tmp == NULL || tmp[1] == '\0')
474 473 return (-1);
475 474
476 475 *guid = tmp + 1;
477 476 return (0);
478 477 }
479 478
480 479 static int
481 480 tphci_bus_config(dev_info_t *parent, uint_t flags,
482 481 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
483 482 {
484 483 _NOTE(ARGUNUSED(flags))
485 484 char *cname, *paddr, *guid, *devnm;
486 485 mdi_pathinfo_t *pip;
487 486 int len, circ, rval;
488 487
489 488 switch (op) {
490 489 case BUS_CONFIG_ONE:
491 490 break;
492 491 case BUS_CONFIG_DRIVER: /* no direct children to configure */
493 492 case BUS_CONFIG_ALL:
494 493 return (NDI_SUCCESS);
495 494 default:
496 495 return (NDI_FAILURE);
497 496 }
498 497
499 498 /* only implement BUS_CONFIG_ONE */
500 499 devnm = i_ddi_strdup((char *)arg, KM_SLEEP);
501 500 len = strlen(devnm) + 1;
502 501
503 502 /* caddr is hardcoded in the form *,<guid> */
504 503 if (tp_decode_name(devnm, &cname, &paddr, &guid) != 0) {
505 504 cmn_err(CE_NOTE, "tphci_bus_config -- invalid device %s",
506 505 (char *)arg);
507 506 kmem_free(devnm, len);
508 507 return (NDI_FAILURE);
509 508 }
510 509
511 510 mdi_devi_enter(parent, &circ);
512 511 rval = mdi_pi_alloc(parent, cname, guid, paddr, 0, &pip);
513 512 kmem_free(devnm, len);
514 513 if (rval != MDI_SUCCESS) {
515 514 cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_alloc failed");
516 515 mdi_devi_exit(parent, circ);
517 516 return (NDI_FAILURE);
518 517 }
519 518
520 519 /*
521 520 * Hold the path and exit the pHCI while calling mdi_pi_online
522 521 * to avoid deadlock with power management of pHCI.
523 522 */
524 523 mdi_hold_path(pip);
525 524 mdi_devi_exit_phci(parent, circ);
526 525 rval = mdi_pi_online(pip, 0);
527 526 mdi_devi_enter_phci(parent, &circ);
528 527 mdi_rele_path(pip);
529 528
530 529 if (rval != MDI_SUCCESS) {
531 530 cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_online failed");
532 531 (void) mdi_pi_free(pip, 0);
533 532 mdi_devi_exit(parent, circ);
534 533 return (NDI_FAILURE);
535 534 }
536 535
537 536 if (childp) {
538 537 *childp = mdi_pi_get_client(pip);
539 538 ndi_hold_devi(*childp);
540 539 }
541 540 mdi_devi_exit(parent, circ);
542 541
543 542 return (NDI_SUCCESS);
544 543 }
545 544
546 545 static int
547 546 tphci_bus_unconfig(dev_info_t *parent, uint_t flags,
548 547 ddi_bus_config_op_t op, void *arg)
549 548 {
550 549 int rval = MDI_SUCCESS;
551 550 int circ;
552 551 mdi_pathinfo_t *pip, *next;
553 552 char *devnm, *cname, *caddr;
554 553
555 554 switch (op) {
556 555 case BUS_UNCONFIG_ONE:
557 556 devnm = (char *)arg;
558 557 i_ddi_parse_name(devnm, &cname, &caddr, NULL);
559 558 if (strcmp(cname, "tclient") != 0)
560 559 return (NDI_SUCCESS); /* no such device */
561 560
562 561 mdi_devi_enter(parent, &circ);
563 562 pip = mdi_pi_find(parent, NULL, caddr);
564 563 if (pip) {
565 564 mdi_hold_path(pip);
566 565 mdi_devi_exit_phci(parent, circ);
567 566 rval = mdi_pi_offline(pip, NDI_DEVI_REMOVE);
568 567 mdi_devi_enter_phci(parent, &circ);
569 568 mdi_rele_path(pip);
570 569
571 570 if (rval == MDI_SUCCESS)
572 571 (void) mdi_pi_free(pip, 0);
573 572 }
574 573 mdi_devi_exit(parent, circ);
575 574 return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
576 575
577 576 case BUS_UNCONFIG_ALL:
578 577 if (flags & NDI_AUTODETACH)
579 578 return (NDI_FAILURE);
580 579
581 580 mdi_devi_enter(parent, &circ);
582 581 next = mdi_get_next_client_path(parent, NULL);
583 582 while ((pip = next) != NULL) {
584 583 next = mdi_get_next_client_path(parent, pip);
585 584
586 585 mdi_hold_path(pip);
587 586 mdi_devi_exit_phci(parent, circ);
588 587 rval = mdi_pi_offline(pip, NDI_DEVI_REMOVE);
589 588 mdi_devi_enter_phci(parent, &circ);
590 589 mdi_rele_path(pip);
591 590
592 591 if (rval != MDI_SUCCESS)
593 592 break;
594 593 (void) mdi_pi_free(pip, 0);
595 594 }
596 595 mdi_devi_exit(parent, circ);
597 596 return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
598 597
599 598 case BUS_UNCONFIG_DRIVER: /* nothing to do */
600 599 return (NDI_SUCCESS);
601 600
602 601 default:
603 602 return (NDI_FAILURE);
604 603 }
605 604 /*NOTREACHED*/
606 605 }
↓ open down ↓ |
448 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX