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