Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/targets/sgen.c
+++ new/usr/src/uts/common/io/scsi/targets/sgen.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 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Copyright Siemens 1999
29 29 * All rights reserved.
30 30 */
31 31
32 32
33 33 /*
34 34 * sgen - SCSI generic device driver
35 35 *
36 36 * The sgen driver provides user programs access to SCSI devices that
37 37 * are not supported by other drivers by providing the USCSI(7I) interface.
38 38 */
39 39
40 40 #include <sys/modctl.h>
41 41 #include <sys/file.h>
42 42 #include <sys/scsi/scsi.h>
43 43 #include <sys/scsi/targets/sgendef.h>
44 44
45 45 /* The name of the driver, established from the module name in _init. */
46 46 static char *sgen_label = NULL;
47 47
48 48 #define DDI_NT_SGEN "ddi_generic:scsi"
49 49
50 50 static char *sgen_devtypes[] = {
51 51 "direct", /* 0x00 -- disks */
52 52 "sequential", /* 0x01 */
53 53 "printer", /* 0x02 */
54 54 "processor", /* 0x03 */
55 55 "worm", /* 0x04 */
56 56 "rodirect", /* 0x05 */
57 57 "scanner", /* 0x06 */
58 58 "optical", /* 0x07 */
59 59 "changer", /* 0x08 */
60 60 "comm", /* 0x09 */
61 61 "prepress1", /* 0x0a -- reserved for prepress (ASC IT8) */
62 62 "prepress2", /* 0x0b -- reserved for prepress (ASC IT8) */
63 63 "array_ctrl", /* 0x0c -- storage array */
64 64 "ses", /* 0x0d -- enclosure services */
65 65 "rbc", /* 0x0e -- simplified block */
66 66 "ocrw", /* 0x0f -- optical card read/write */
67 67 "bridge", /* 0x10 -- reserved for bridging expanders */
68 68 "type_0x11", /* 0x11 */
69 69 "type_0x12", /* 0x12 */
70 70 "type_0x13", /* 0x13 */
71 71 "type_0x14", /* 0x14 */
72 72 "type_0x15", /* 0x15 */
73 73 "type_0x16", /* 0x16 */
74 74 "type_0x17", /* 0x17 */
75 75 "type_0x18", /* 0x18 */
76 76 "type_0x19", /* 0x19 */
77 77 "type_0x1a", /* 0x1a */
78 78 "type_0x1b", /* 0x1b */
79 79 "type_0x1c", /* 0x1c */
80 80 "type_0x1d", /* 0x1d */
81 81 "type_0x1e", /* 0x1e */
82 82 "type_unknown" /* 0x1f is "no device type" or "unknown" */
83 83 };
84 84
85 85 #define SGEN_NDEVTYPES ((sizeof (sgen_devtypes) / sizeof (char *)))
86 86
87 87 #define SGEN_INQSTRLEN 24
88 88 #define SGEN_VENDID_MAX 8
89 89 #define SGEN_PRODID_MAX 16
90 90
91 91 #define FILL_SCSI1_LUN(devp, pkt) \
92 92 if ((devp)->sd_inq->inq_ansi == 0x1) { \
93 93 int _lun; \
94 94 _lun = ddi_prop_get_int(DDI_DEV_T_ANY, (devp)->sd_dev, \
95 95 DDI_PROP_DONTPASS, SCSI_ADDR_PROP_LUN, 0); \
96 96 if (_lun > 0) { \
97 97 ((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = \
98 98 _lun; \
99 99 } \
100 100 }
101 101
102 102 #define SGEN_DO_ERRSTATS(sg_state, x) \
103 103 if (sg_state->sgen_kstats) { \
104 104 struct sgen_errstats *sp; \
105 105 sp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data; \
106 106 sp->x.value.ui32++; \
107 107 }
108 108
109 109 #define SCBP_C(pkt) ((*(pkt)->pkt_scbp) & STATUS_MASK)
110 110
111 111 /*
112 112 * Standard entrypoints
113 113 */
114 114 static int sgen_attach(dev_info_t *, ddi_attach_cmd_t);
115 115 static int sgen_detach(dev_info_t *, ddi_detach_cmd_t);
116 116 static int sgen_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
117 117 static int sgen_probe(dev_info_t *);
118 118 static int sgen_open(dev_t *, int, int, cred_t *);
119 119 static int sgen_close(dev_t, int, int, cred_t *);
120 120 static int sgen_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
121 121
122 122 /*
123 123 * Configuration routines
124 124 */
125 125 static int sgen_do_attach(dev_info_t *);
126 126 static int sgen_setup_sense(sgen_state_t *);
127 127 static void sgen_create_errstats(sgen_state_t *, int);
128 128 static int sgen_do_suspend(dev_info_t *);
129 129 static int sgen_do_detach(dev_info_t *);
130 130 static void sgen_setup_binddb(dev_info_t *);
131 131 static void sgen_cleanup_binddb();
132 132
133 133 /*
134 134 * Packet transport routines
135 135 */
136 136 static int sgen_uscsi_cmd(dev_t, struct uscsi_cmd *, int);
137 137 static int sgen_start(struct buf *);
138 138 static int sgen_hold_cmdbuf(sgen_state_t *);
139 139 static void sgen_rele_cmdbuf(sgen_state_t *);
140 140 static int sgen_make_uscsi_cmd(sgen_state_t *, struct buf *);
141 141 static void sgen_restart(void *);
142 142 static void sgen_callback(struct scsi_pkt *);
143 143 static int sgen_handle_autosense(sgen_state_t *, struct scsi_pkt *);
144 144 static int sgen_handle_sense(sgen_state_t *);
145 145 static int sgen_handle_incomplete(sgen_state_t *, struct scsi_pkt *);
146 146 static int sgen_check_error(sgen_state_t *, struct buf *);
147 147 static int sgen_initiate_sense(sgen_state_t *, int);
148 148 static int sgen_scsi_transport(struct scsi_pkt *);
149 149 static int sgen_tur(dev_t);
150 150
151 151 /*
152 152 * Logging/debugging routines
153 153 */
154 154 static void sgen_log(sgen_state_t *, int, const char *, ...);
155 155 static int sgen_diag_ok(sgen_state_t *, int);
156 156 static void sgen_dump_cdb(sgen_state_t *, const char *, union scsi_cdb *, int);
157 157 static void sgen_dump_sense(sgen_state_t *, size_t, uchar_t *);
158 158
159 159 int sgen_diag = 0;
160 160 int sgen_sporadic_failures = 0;
161 161 int sgen_force_manual_sense = 0;
162 162 struct sgen_binddb sgen_binddb;
163 163
164 164 static struct cb_ops sgen_cb_ops = {
165 165 sgen_open, /* open */
166 166 sgen_close, /* close */
167 167 nodev, /* strategy */
168 168 nodev, /* print */
169 169 nodev, /* dump */
170 170 nodev, /* read */
171 171 nodev, /* write */
172 172 sgen_ioctl, /* ioctl */
173 173 nodev, /* devmap */
174 174 nodev, /* mmap */
175 175 nodev, /* segmap */
176 176 nochpoll, /* poll */
177 177 ddi_prop_op, /* cb_prop_op */
178 178 0, /* streamtab */
179 179 D_MP | D_NEW | D_HOTPLUG /* Driver compatibility flag */
180 180 };
181 181
182 182 static struct dev_ops sgen_dev_ops = {
183 183 DEVO_REV, /* devo_rev, */
184 184 0, /* refcnt */
185 185 sgen_getinfo, /* info */
186 186 nodev, /* identify */
187 187 sgen_probe, /* probe */
188 188 sgen_attach, /* attach */
189 189 sgen_detach, /* detach */
190 190 nodev, /* reset */
191 191 &sgen_cb_ops, /* driver operations */
192 192 (struct bus_ops *)0, /* bus operations */
193 193 NULL, /* power */
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
194 194 ddi_quiesce_not_supported, /* devo_quiesce */
195 195 };
196 196
197 197 static void *sgen_soft_state = NULL;
198 198
199 199 static struct modldrv modldrv = {
200 200 &mod_driverops, "SCSI generic driver", &sgen_dev_ops
201 201 };
202 202
203 203 static struct modlinkage modlinkage = {
204 - MODREV_1, &modldrv, NULL
204 + MODREV_1, { &modldrv, NULL }
205 205 };
206 206
207 207 int
208 208 _init(void)
209 209 {
210 210 int err;
211 211
212 212 /* establish driver name from module name */
213 213 sgen_label = (char *)mod_modname(&modlinkage);
214 214
215 215 sgen_log(NULL, SGEN_DIAG2, "in sgen_init()");
216 216 if ((err = ddi_soft_state_init(&sgen_soft_state,
217 217 sizeof (sgen_state_t), SGEN_ESTIMATED_NUM_DEVS)) != 0) {
218 218 goto done;
219 219 }
220 220
221 221 if ((err = mod_install(&modlinkage)) != 0) {
222 222 ddi_soft_state_fini(&sgen_soft_state);
223 223 goto done;
224 224 }
225 225
226 226 done:
227 227 sgen_log(NULL, SGEN_DIAG2, "%s sgen_init()", err ? "failed" : "done");
228 228 return (err);
229 229 }
230 230
231 231 int
232 232 _fini(void)
233 233 {
234 234 int err;
235 235 sgen_log(NULL, SGEN_DIAG2, "in sgen_fini()");
236 236
237 237 if ((err = mod_remove(&modlinkage)) != 0) {
238 238 goto done;
239 239 }
240 240
241 241 ddi_soft_state_fini(&sgen_soft_state);
242 242 sgen_cleanup_binddb();
243 243
244 244 done:
245 245 sgen_log(NULL, SGEN_DIAG2, "%s sgen_fini()", err ? "failed" : "done");
246 246 return (err);
247 247 }
248 248
249 249 int
250 250 _info(struct modinfo *modinfop)
251 251 {
252 252 return (mod_info(&modlinkage, modinfop));
253 253 }
254 254
255 255 /*
256 256 * sgen_typename()
257 257 * return a device type's name by looking it up in the sgen_devtypes table.
258 258 */
259 259 static char *
260 260 sgen_typename(uchar_t typeno)
261 261 {
262 262 if (typeno >= SGEN_NDEVTYPES)
263 263 return ("type_unknown");
264 264 return (sgen_devtypes[typeno]);
265 265 }
266 266
267 267 /*
268 268 * sgen_typenum()
269 269 * return a device type's number by looking it up in the sgen_devtypes
270 270 * table.
271 271 */
272 272 static int
273 273 sgen_typenum(const char *typename, uchar_t *typenum)
274 274 {
275 275 int i;
276 276 for (i = 0; i < SGEN_NDEVTYPES; i++) {
277 277 if (strcasecmp(sgen_devtypes[i], typename) == 0) {
278 278 *typenum = (uchar_t)i;
279 279 return (0);
280 280 }
281 281 }
282 282 return (-1);
283 283 }
284 284
285 285 /*
286 286 * sgen_setup_binddb()
287 287 * initialize a data structure which stores all of the information about
288 288 * which devices and device types the driver should bind to.
289 289 */
290 290 static void
291 291 sgen_setup_binddb(dev_info_t *dip)
292 292 {
293 293 char **strs = NULL, *cp, *pcp, *vcp;
294 294 uint_t nelems, pcplen, vcplen, idx;
295 295
296 296 ASSERT(sgen_binddb.sdb_init == 0);
297 297 ASSERT(MUTEX_HELD(&sgen_binddb.sdb_lock));
298 298
299 299 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
300 300 "device-type-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
301 301 /*
302 302 * for each device type specifier make a copy and put it into a
303 303 * node in the binddb.
304 304 */
305 305 for (idx = 0; idx < nelems; idx++) {
306 306 sgen_type_node_t *nodep;
307 307 uchar_t devtype;
308 308 cp = strs[idx];
309 309 if (sgen_typenum(cp, &devtype) != 0) {
310 310 sgen_log(NULL, CE_WARN,
311 311 "unknown device type '%s', "
312 312 "device unit-address @%s",
313 313 cp, ddi_get_name_addr(dip));
314 314 continue;
315 315 }
316 316 nodep = kmem_zalloc(sizeof (sgen_type_node_t),
317 317 KM_SLEEP);
318 318 nodep->node_type = devtype;
319 319 nodep->node_next = sgen_binddb.sdb_type_nodes;
320 320 sgen_binddb.sdb_type_nodes = nodep;
321 321
322 322 sgen_log(NULL, SGEN_DIAG2, "found device type "
323 323 "'%s' in device-type-config-list, "
324 324 "device unit-address @%s",
325 325 cp, ddi_get_name_addr(dip));
326 326 }
327 327 ddi_prop_free(strs);
328 328 }
329 329
330 330 /*
331 331 * for each Vendor/Product inquiry pair, build a node and put it
332 332 * into the the binddb.
333 333 */
334 334 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
335 335 "inquiry-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
336 336
337 337 if (nelems % 2 == 1) {
338 338 sgen_log(NULL, CE_WARN, "inquiry-config-list must "
339 339 "contain Vendor/Product pairs, "
340 340 "device unit-address @%s",
341 341 ddi_get_name_addr(dip));
342 342 nelems--;
343 343 }
344 344 for (idx = 0; idx < nelems; idx += 2) {
345 345 sgen_inq_node_t *nodep;
346 346 /*
347 347 * Grab vendor and product ID.
348 348 */
349 349 vcp = strs[idx];
350 350 vcplen = strlen(vcp);
351 351 if (vcplen == 0 || vcplen > SGEN_VENDID_MAX) {
352 352 sgen_log(NULL, CE_WARN,
353 353 "Invalid vendor ID '%s', "
354 354 "device unit-address @%s",
355 355 vcp, ddi_get_name_addr(dip));
356 356 continue;
357 357 }
358 358
359 359 pcp = strs[idx + 1];
360 360 pcplen = strlen(pcp);
361 361 if (pcplen == 0 || pcplen > SGEN_PRODID_MAX) {
362 362 sgen_log(NULL, CE_WARN,
363 363 "Invalid product ID '%s', "
364 364 "device unit-address @%s",
365 365 pcp, ddi_get_name_addr(dip));
366 366 continue;
367 367 }
368 368
369 369 nodep = kmem_zalloc(sizeof (sgen_inq_node_t),
370 370 KM_SLEEP);
371 371 nodep->node_vendor = kmem_alloc(vcplen + 1, KM_SLEEP);
372 372 (void) strcpy(nodep->node_vendor, vcp);
373 373 nodep->node_product = kmem_alloc(pcplen + 1, KM_SLEEP);
374 374 (void) strcpy(nodep->node_product, pcp);
375 375
376 376 nodep->node_next = sgen_binddb.sdb_inq_nodes;
377 377 sgen_binddb.sdb_inq_nodes = nodep;
378 378
379 379 sgen_log(NULL, SGEN_DIAG2, "found inquiry string "
380 380 "'%s' '%s' in device-type-config-list, "
381 381 "device unit-address @%s",
382 382 nodep->node_vendor, nodep->node_product,
383 383 ddi_get_name_addr(dip));
384 384 }
385 385 ddi_prop_free(strs);
386 386 }
387 387
388 388 sgen_binddb.sdb_init = 1;
389 389 }
390 390
391 391 /*
392 392 * sgen_cleanup_binddb()
393 393 * deallocate data structures for binding database.
394 394 */
395 395 static void
396 396 sgen_cleanup_binddb()
397 397 {
398 398 sgen_inq_node_t *inqp, *inqnextp;
399 399 sgen_type_node_t *typep, *typenextp;
400 400
401 401 mutex_enter(&sgen_binddb.sdb_lock);
402 402 if (sgen_binddb.sdb_init == 0) {
403 403 mutex_exit(&sgen_binddb.sdb_lock);
404 404 return;
405 405 }
406 406
407 407 for (inqp = sgen_binddb.sdb_inq_nodes; inqp != NULL; inqp = inqnextp) {
408 408 inqnextp = inqp->node_next;
409 409 ASSERT(inqp->node_vendor && inqp->node_product);
410 410 kmem_free(inqp->node_vendor,
411 411 strlen(inqp->node_vendor) + 1);
412 412 kmem_free(inqp->node_product,
413 413 strlen(inqp->node_product) + 1);
414 414 kmem_free(inqp, sizeof (sgen_inq_node_t));
415 415 }
416 416
417 417 for (typep = sgen_binddb.sdb_type_nodes; typep != NULL;
418 418 typep = typenextp) {
419 419 typenextp = typep->node_next;
420 420 kmem_free(typep, sizeof (sgen_type_node_t));
421 421 }
422 422 mutex_exit(&sgen_binddb.sdb_lock);
423 423 }
424 424
425 425 /*
426 426 * sgen_bind_byinq()
427 427 * lookup a device in the binding database by its inquiry data.
428 428 */
429 429 static int
430 430 sgen_bind_byinq(dev_info_t *dip)
431 431 {
432 432 sgen_inq_node_t *nodep;
433 433 char vend_str[SGEN_VENDID_MAX+1];
434 434 char prod_str[SGEN_PRODID_MAX+1];
435 435 struct scsi_device *scsidevp;
436 436
437 437 scsidevp = ddi_get_driver_private(dip);
438 438
439 439 /*
440 440 * inq_vid and inq_pid are laid out by the protocol in order in the
441 441 * inquiry structure, and are not delimited by \0.
442 442 */
443 443 bcopy(scsidevp->sd_inq->inq_vid, vend_str, SGEN_VENDID_MAX);
444 444 vend_str[SGEN_VENDID_MAX] = '\0';
445 445 bcopy(scsidevp->sd_inq->inq_pid, prod_str, SGEN_PRODID_MAX);
446 446 prod_str[SGEN_PRODID_MAX] = '\0';
447 447
448 448 for (nodep = sgen_binddb.sdb_inq_nodes; nodep != NULL;
449 449 nodep = nodep->node_next) {
450 450 /*
451 451 * Allow the "*" wildcard to match all vendor IDs.
452 452 */
453 453 if (strcmp(nodep->node_vendor, "*") != 0) {
454 454 if (strncasecmp(nodep->node_vendor, vend_str,
455 455 strlen(nodep->node_vendor)) != 0) {
456 456 continue;
457 457 }
458 458 }
459 459
460 460 /*
461 461 * Using strncasecmp() with the key length allows substring
462 462 * matching for product data.
463 463 */
464 464 if (strncasecmp(nodep->node_product, prod_str,
465 465 strlen(nodep->node_product)) == 0) {
466 466 return (0);
467 467 }
468 468 }
469 469 return (-1);
470 470 }
471 471
472 472 /*
473 473 * sgen_bind_bytype()
474 474 * lookup a device type in the binding database; if found, return a
475 475 * format string corresponding to the string in the .conf file.
476 476 */
477 477 static int
478 478 sgen_bind_bytype(dev_info_t *dip)
479 479 {
480 480 sgen_type_node_t *nodep;
481 481 struct scsi_device *scsidevp;
482 482
483 483 scsidevp = ddi_get_driver_private(dip);
484 484
485 485 for (nodep = sgen_binddb.sdb_type_nodes; nodep != NULL;
486 486 nodep = nodep->node_next) {
487 487 if (nodep->node_type == scsidevp->sd_inq->inq_dtype) {
488 488 return (0);
489 489 }
490 490 }
491 491 return (-1);
492 492 }
493 493
494 494 /*
495 495 * sgen_get_binding()
496 496 * Check to see if the device in question matches the criteria for
497 497 * sgen to bind.
498 498 *
499 499 * Either the .conf file must specify a device_type entry which
500 500 * matches the SCSI device type of this device, or the inquiry
501 501 * string provided by the device must match an inquiry string specified
502 502 * in the .conf file. Inquiry data is matched first.
503 503 */
504 504 static int
505 505 sgen_get_binding(dev_info_t *dip)
506 506 {
507 507 int retval = 0;
508 508
509 509 mutex_enter(&sgen_binddb.sdb_lock);
510 510 if (sgen_binddb.sdb_init == 0)
511 511 sgen_setup_binddb(dip);
512 512 mutex_exit(&sgen_binddb.sdb_lock);
513 513
514 514
515 515 /*
516 516 * Check device-type-config-list for a match by device type.
517 517 */
518 518 if (sgen_bind_bytype(dip) == 0)
519 519 goto done;
520 520
521 521 /*
522 522 * Check inquiry-config-list for a match by Vendor/Product ID.
523 523 */
524 524 if (sgen_bind_byinq(dip) == 0)
525 525 goto done;
526 526
527 527 retval = -1;
528 528 done:
529 529 return (retval);
530 530 }
531 531
532 532 /*
533 533 * sgen_attach()
534 534 * attach(9e) entrypoint.
535 535 */
536 536 static int
537 537 sgen_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
538 538 {
539 539 int err;
540 540
541 541 sgen_log(NULL, SGEN_DIAG2, "in sgen_attach(), device unit-address @%s",
542 542 ddi_get_name_addr(dip));
543 543
544 544 switch (cmd) {
545 545 case DDI_ATTACH:
546 546 err = sgen_do_attach(dip);
547 547 break;
548 548 case DDI_RESUME:
549 549 err = DDI_SUCCESS;
550 550 break;
551 551 case DDI_PM_RESUME:
552 552 default:
553 553 err = DDI_FAILURE;
554 554 break;
555 555 }
556 556
557 557 done:
558 558 sgen_log(NULL, SGEN_DIAG2, "%s sgen_attach(), device unit-address @%s",
559 559 err == DDI_SUCCESS ? "done" : "failed", ddi_get_name_addr(dip));
560 560 return (err);
561 561 }
562 562
563 563 /*
564 564 * sgen_do_attach()
565 565 * handle the nitty details of attach.
566 566 */
567 567 static int
568 568 sgen_do_attach(dev_info_t *dip)
569 569 {
570 570 int instance;
571 571 struct scsi_device *scsidevp;
572 572 sgen_state_t *sg_state;
573 573 uchar_t devtype;
574 574 struct scsi_inquiry *inq;
575 575
576 576 instance = ddi_get_instance(dip);
577 577
578 578 scsidevp = ddi_get_driver_private(dip);
579 579 ASSERT(scsidevp);
580 580
581 581 sgen_log(NULL, SGEN_DIAG2, "sgen_do_attach: instance = %d, "
582 582 "device unit-address @%s", instance, ddi_get_name_addr(dip));
583 583
584 584 /*
585 585 * Probe the device in order to get its device type to name the minor
586 586 * node.
587 587 */
588 588 if (scsi_probe(scsidevp, NULL_FUNC) != SCSIPROBE_EXISTS) {
589 589 scsi_unprobe(scsidevp);
590 590 return (DDI_FAILURE);
591 591 }
592 592
593 593 if (ddi_soft_state_zalloc(sgen_soft_state, instance) != DDI_SUCCESS) {
594 594 sgen_log(NULL, SGEN_DIAG1,
595 595 "sgen_do_attach: failed to allocate softstate, "
596 596 "device unit-address @%s", ddi_get_name_addr(dip));
597 597 scsi_unprobe(scsidevp);
598 598 return (DDI_FAILURE);
599 599 }
600 600
601 601 inq = scsidevp->sd_inq; /* valid while device is probed... */
602 602 devtype = inq->inq_dtype;
603 603
604 604 sg_state = ddi_get_soft_state(sgen_soft_state, instance);
605 605 sg_state->sgen_scsidev = scsidevp;
606 606 scsidevp->sd_dev = dip;
607 607
608 608 /*
609 609 * Now that sg_state->sgen_scsidev is initialized, it's ok to
610 610 * call sgen_log with sg_state instead of NULL.
611 611 */
612 612
613 613 /*
614 614 * If the user specified the sgen_diag property, override the global
615 615 * sgen_diag setting by setting sg_state's sgen_diag value. If the
616 616 * user gave a value out of range, default to '0'.
617 617 */
618 618 sg_state->sgen_diag = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
619 619 "sgen-diag", -1);
620 620
621 621 if (sg_state->sgen_diag != -1) {
622 622 if (sg_state->sgen_diag < 0 || sg_state->sgen_diag > 3)
623 623 sg_state->sgen_diag = 0;
624 624 }
625 625
626 626 sgen_log(sg_state, SGEN_DIAG2,
627 627 "sgen_do_attach: sgen_soft_state=0x%p, instance=%d, "
628 628 "device unit-address @%s",
629 629 sgen_soft_state, instance, ddi_get_name_addr(dip));
630 630
631 631 /*
632 632 * For simplicity, the minor number == the instance number
633 633 */
634 634 if (ddi_create_minor_node(dip, sgen_typename(devtype), S_IFCHR,
635 635 instance, DDI_NT_SGEN, NULL) == DDI_FAILURE) {
636 636 scsi_unprobe(scsidevp);
637 637 ddi_prop_remove_all(dip);
638 638 sgen_log(sg_state, SGEN_DIAG1,
639 639 "sgen_do_attach: minor node creation failed, "
640 640 "device unit-address @%s", ddi_get_name_addr(dip));
641 641 ddi_soft_state_free(sgen_soft_state, instance);
642 642 return (DDI_FAILURE);
643 643 }
644 644
645 645 /*
646 646 * Allocate the command buffer, then create a condition variable for
647 647 * managing it; mark the command buffer as free.
648 648 */
649 649 sg_state->sgen_cmdbuf = getrbuf(KM_SLEEP);
650 650 cv_init(&sg_state->sgen_cmdbuf_cv, NULL, CV_DRIVER, NULL);
651 651
652 652 SGEN_CLR_BUSY(sg_state);
653 653 SGEN_CLR_OPEN(sg_state);
654 654 SGEN_CLR_SUSP(sg_state);
655 655
656 656 /*
657 657 * If the hba and the target both support wide xfers, enable them.
658 658 */
659 659 if (scsi_ifgetcap(&sg_state->sgen_scsiaddr, "wide-xfer", 1) != -1) {
660 660 int wide = 0;
661 661 if ((inq->inq_rdf == RDF_SCSI2) &&
662 662 (inq->inq_wbus16 || inq->inq_wbus32))
663 663 wide = 1;
664 664 if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "wide-xfer",
665 665 wide, 1) == 1) {
666 666 sgen_log(sg_state, SGEN_DIAG1,
667 667 "sgen_attach: wide xfer %s, "
668 668 "device unit-address @%s",
669 669 wide ? "enabled" : "disabled",
670 670 ddi_get_name_addr(dip));
671 671 }
672 672 }
673 673
674 674 /*
675 675 * This is a little debugging code-- since the codepath for auto-sense
676 676 * and 'manual' sense is split, toggling this variable will make
677 677 * sgen act as though the adapter in question can't do auto-sense.
678 678 */
679 679 if (sgen_force_manual_sense) {
680 680 if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "auto-rqsense",
681 681 0, 1) == 1) {
682 682 sg_state->sgen_arq_enabled = 0;
683 683 } else {
684 684 sg_state->sgen_arq_enabled = 1;
685 685 }
686 686 } else {
687 687 /*
688 688 * Enable autorequest sense, if supported
689 689 */
690 690 if (scsi_ifgetcap(&sg_state->sgen_scsiaddr,
691 691 "auto-rqsense", 1) != 1) {
692 692 if (scsi_ifsetcap(&sg_state->sgen_scsiaddr,
693 693 "auto-rqsense", 1, 1) == 1) {
694 694 sg_state->sgen_arq_enabled = 1;
695 695 sgen_log(sg_state, SGEN_DIAG1,
696 696 "sgen_attach: auto-request-sense enabled, "
697 697 "device unit-address @%s",
698 698 ddi_get_name_addr(dip));
699 699 } else {
700 700 sg_state->sgen_arq_enabled = 0;
701 701 sgen_log(sg_state, SGEN_DIAG1,
702 702 "sgen_attach: auto-request-sense disabled, "
703 703 "device unit-address @%s",
704 704 ddi_get_name_addr(dip));
705 705 }
706 706 } else {
707 707 sg_state->sgen_arq_enabled = 1; /* already enabled */
708 708 sgen_log(sg_state, SGEN_DIAG1,
709 709 "sgen_attach: auto-request-sense enabled, "
710 710 "device unit-address @%s", ddi_get_name_addr(dip));
711 711 }
712 712 }
713 713
714 714 /*
715 715 * Allocate plumbing for manually fetching sense.
716 716 */
717 717 if (sgen_setup_sense(sg_state) != 0) {
718 718 freerbuf(sg_state->sgen_cmdbuf);
719 719 ddi_prop_remove_all(dip);
720 720 ddi_remove_minor_node(dip, NULL);
721 721 scsi_unprobe(scsidevp);
722 722 sgen_log(sg_state, SGEN_DIAG1,
723 723 "sgen_do_attach: failed to setup request-sense, "
724 724 "device unit-address @%s", ddi_get_name_addr(dip));
725 725 ddi_soft_state_free(sgen_soft_state, instance);
726 726 return (DDI_FAILURE);
727 727 }
728 728
729 729 sgen_create_errstats(sg_state, instance);
730 730
731 731 ddi_report_dev(dip);
732 732
733 733 return (DDI_SUCCESS);
734 734 }
735 735
736 736 /*
737 737 * sgen_setup_sense()
738 738 * Allocate a request sense packet so that if sgen needs to fetch sense
739 739 * data for the user, it will have a pkt ready to send.
740 740 */
741 741 static int
742 742 sgen_setup_sense(sgen_state_t *sg_state)
743 743 {
744 744 struct buf *bp;
745 745 struct scsi_pkt *rqpkt;
746 746
747 747 if ((bp = scsi_alloc_consistent_buf(&sg_state->sgen_scsiaddr, NULL,
748 748 MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) {
749 749 return (-1);
750 750 }
751 751
752 752 if ((rqpkt = scsi_init_pkt(&sg_state->sgen_scsiaddr, NULL, bp,
753 753 CDB_GROUP0, 1, 0, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) {
754 754 scsi_free_consistent_buf(bp);
755 755 return (-1);
756 756 }
757 757
758 758 /*
759 759 * Make the results of running a SENSE available by filling out the
760 760 * sd_sense field of the scsi device (sgen_sense is just an alias).
761 761 */
762 762 sg_state->sgen_sense = (struct scsi_extended_sense *)bp->b_un.b_addr;
763 763
764 764 (void) scsi_setup_cdb((union scsi_cdb *)rqpkt->pkt_cdbp,
765 765 SCMD_REQUEST_SENSE, 0, MAX_SENSE_LENGTH, 0);
766 766 FILL_SCSI1_LUN(sg_state->sgen_scsidev, rqpkt);
767 767
768 768 rqpkt->pkt_comp = sgen_callback;
769 769 rqpkt->pkt_time = SGEN_IO_TIME;
770 770 rqpkt->pkt_flags |= FLAG_SENSING;
771 771 rqpkt->pkt_private = sg_state;
772 772
773 773 sg_state->sgen_rqspkt = rqpkt;
774 774 sg_state->sgen_rqsbuf = bp;
775 775
776 776 return (0);
777 777 }
778 778
779 779 /*
780 780 * sgen_create_errstats()
781 781 * create named kstats for tracking occurrence of errors.
782 782 */
783 783 static void
784 784 sgen_create_errstats(sgen_state_t *sg_state, int instance)
785 785 {
786 786 char kstatname[KSTAT_STRLEN];
787 787 struct sgen_errstats *stp;
788 788
789 789 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,err",
790 790 sgen_label, instance);
791 791 sg_state->sgen_kstats = kstat_create("sgenerr", instance,
792 792 kstatname, "device_error", KSTAT_TYPE_NAMED,
793 793 sizeof (struct sgen_errstats) / sizeof (kstat_named_t),
794 794 KSTAT_FLAG_PERSISTENT);
795 795
796 796 if (sg_state->sgen_kstats == NULL)
797 797 return;
798 798
799 799 stp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data;
800 800 kstat_named_init(&stp->sgen_trans_err, "transport_errors",
801 801 KSTAT_DATA_UINT32);
802 802 kstat_named_init(&stp->sgen_restart, "command_restarts",
803 803 KSTAT_DATA_UINT32);
804 804 kstat_named_init(&stp->sgen_incmp_err, "incomplete_commands",
805 805 KSTAT_DATA_UINT32);
806 806 kstat_named_init(&stp->sgen_autosen_rcv, "autosense_occurred",
807 807 KSTAT_DATA_UINT32);
808 808 kstat_named_init(&stp->sgen_autosen_bad, "autosense_undecipherable",
809 809 KSTAT_DATA_UINT32);
810 810 kstat_named_init(&stp->sgen_sense_rcv, "sense_fetches",
811 811 KSTAT_DATA_UINT32);
812 812 kstat_named_init(&stp->sgen_sense_bad, "sense_data_undecipherable",
813 813 KSTAT_DATA_UINT32);
814 814 kstat_named_init(&stp->sgen_recov_err, "recoverable_error",
815 815 KSTAT_DATA_UINT32);
816 816 kstat_named_init(&stp->sgen_nosen_err, "NO_SENSE_sense_key",
817 817 KSTAT_DATA_UINT32);
818 818 kstat_named_init(&stp->sgen_unrecov_err, "unrecoverable_sense_error",
819 819 KSTAT_DATA_UINT32);
820 820 sg_state->sgen_kstats->ks_private = sg_state;
821 821 sg_state->sgen_kstats->ks_update = nulldev;
822 822 kstat_install(sg_state->sgen_kstats);
823 823 }
824 824
825 825 /*
826 826 * sgen_detach()
827 827 * detach(9E) entrypoint
828 828 */
829 829 static int
830 830 sgen_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
831 831 {
832 832 int instance;
833 833 sgen_state_t *sg_state;
834 834
835 835 instance = ddi_get_instance(dip);
836 836 sg_state = ddi_get_soft_state(sgen_soft_state, instance);
837 837
838 838 sgen_log(sg_state, SGEN_DIAG2, "in sgen_detach(), "
839 839 "device unit-address @%s", ddi_get_name_addr(dip));
840 840
841 841 if (sg_state == NULL) {
842 842 sgen_log(NULL, SGEN_DIAG1,
843 843 "sgen_detach: failed, no softstate found (%d), "
844 844 "device unit-address @%s",
845 845 instance, ddi_get_name_addr(dip));
846 846 return (DDI_FAILURE);
847 847 }
848 848
849 849 switch (cmd) {
850 850 case DDI_DETACH:
851 851 return (sgen_do_detach(dip));
852 852 case DDI_SUSPEND:
853 853 return (sgen_do_suspend(dip));
854 854 case DDI_PM_SUSPEND:
855 855 default:
856 856 return (DDI_FAILURE);
857 857 }
858 858 }
859 859
860 860 /*
861 861 * sgen_do_detach()
862 862 * detach the driver, tearing down resources.
863 863 */
864 864 static int
865 865 sgen_do_detach(dev_info_t *dip)
866 866 {
867 867 int instance;
868 868 sgen_state_t *sg_state;
869 869 struct scsi_device *devp;
870 870
871 871 instance = ddi_get_instance(dip);
872 872 sg_state = ddi_get_soft_state(sgen_soft_state, instance);
873 873 ASSERT(sg_state);
874 874
875 875 sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_detach(), "
876 876 "device unit-address @%s", ddi_get_name_addr(dip));
877 877 devp = ddi_get_driver_private(dip);
878 878
879 879 mutex_enter(&sg_state->sgen_mutex);
880 880 if (SGEN_IS_BUSY(sg_state)) {
881 881 mutex_exit(&sg_state->sgen_mutex);
882 882 sgen_log(sg_state, SGEN_DIAG1, "sgen_do_detach: failed because "
883 883 "device is busy, device unit-address @%s",
884 884 ddi_get_name_addr(dip));
885 885 return (DDI_FAILURE);
886 886 }
887 887 mutex_exit(&sg_state->sgen_mutex);
888 888
889 889 /*
890 890 * Final approach for detach. Free data allocated by scsi_probe()
891 891 * in attach.
892 892 */
893 893 if (sg_state->sgen_restart_timeid)
894 894 (void) untimeout(sg_state->sgen_restart_timeid);
895 895 sg_state->sgen_restart_timeid = 0;
896 896 scsi_unprobe(devp);
897 897
898 898 /*
899 899 * Free auto-request plumbing.
900 900 */
901 901 scsi_free_consistent_buf(sg_state->sgen_rqsbuf);
902 902 scsi_destroy_pkt(sg_state->sgen_rqspkt);
903 903
904 904 if (sg_state->sgen_kstats) {
905 905 kstat_delete(sg_state->sgen_kstats);
906 906 sg_state->sgen_kstats = NULL;
907 907 }
908 908
909 909 /*
910 910 * Free command buffer and clean up
911 911 */
912 912 freerbuf(sg_state->sgen_cmdbuf);
913 913 cv_destroy(&sg_state->sgen_cmdbuf_cv);
914 914
915 915 sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_detach(), "
916 916 "device unit-address @%s", ddi_get_name_addr(dip));
917 917
918 918 ddi_soft_state_free(sgen_soft_state, instance);
919 919 ddi_prop_remove_all(dip);
920 920 ddi_remove_minor_node(dip, NULL);
921 921 return (DDI_SUCCESS);
922 922 }
923 923
924 924 /*
925 925 * sgen_do_suspend()
926 926 * suspend the driver. This sets the "suspend" bit for this target if it
927 927 * is currently open; once resumed, the suspend bit will cause
928 928 * subsequent I/Os to fail. We want user programs to close and
929 929 * reopen the device to acknowledge that they need to reexamine its
930 930 * state and do the right thing.
931 931 */
932 932 static int
933 933 sgen_do_suspend(dev_info_t *dip)
934 934 {
935 935 int instance;
936 936 sgen_state_t *sg_state;
937 937
938 938 instance = ddi_get_instance(dip);
939 939 sg_state = ddi_get_soft_state(sgen_soft_state, instance);
940 940 ASSERT(sg_state);
941 941
942 942 sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_suspend(), "
943 943 "device unit-address @%s", ddi_get_name_addr(dip));
944 944
945 945 if (sg_state->sgen_restart_timeid) {
946 946 (void) untimeout(sg_state->sgen_restart_timeid);
947 947 }
948 948 sg_state->sgen_restart_timeid = 0;
949 949
950 950 mutex_enter(&sg_state->sgen_mutex);
951 951 if (SGEN_IS_OPEN(sg_state))
952 952 SGEN_SET_SUSP(sg_state);
953 953 mutex_exit(&sg_state->sgen_mutex);
954 954
955 955 sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_suspend(), "
956 956 "device unit-address @%s", ddi_get_name_addr(dip));
957 957 return (DDI_SUCCESS);
958 958 }
959 959
960 960 /*
961 961 * sgen_getinfo()
962 962 * getinfo(9e) entrypoint.
963 963 */
964 964 /*ARGSUSED*/
965 965 static int
966 966 sgen_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
967 967 {
968 968 dev_t dev;
969 969 sgen_state_t *sg_state;
970 970 int instance, error;
971 971 switch (infocmd) {
972 972 case DDI_INFO_DEVT2DEVINFO:
973 973 dev = (dev_t)arg;
974 974 instance = getminor(dev);
975 975 if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance))
976 976 == NULL)
977 977 return (DDI_FAILURE);
978 978 *result = (void *) sg_state->sgen_scsidev->sd_dev;
979 979 error = DDI_SUCCESS;
980 980 break;
981 981 case DDI_INFO_DEVT2INSTANCE:
982 982 dev = (dev_t)arg;
983 983 instance = getminor(dev);
984 984 *result = (void *)(uintptr_t)instance;
985 985 error = DDI_SUCCESS;
986 986 break;
987 987 default:
988 988 error = DDI_FAILURE;
989 989 }
990 990 return (error);
991 991 }
992 992
993 993 /*
994 994 * sgen_probe()
995 995 * probe(9e) entrypoint. sgen *never* returns DDI_PROBE_PARTIAL, in
996 996 * order to avoid leaving around extra devinfos. If sgen's binding
997 997 * rules indicate that it should bind, it returns DDI_PROBE_SUCCESS.
998 998 */
999 999 static int
1000 1000 sgen_probe(dev_info_t *dip)
1001 1001 {
1002 1002 struct scsi_device *scsidevp;
1003 1003 int instance;
1004 1004 int rval;
1005 1005
1006 1006 scsidevp = ddi_get_driver_private(dip);
1007 1007 instance = ddi_get_instance(dip);
1008 1008 sgen_log(NULL, SGEN_DIAG2, "in sgen_probe(): instance = %d, "
1009 1009 "device unit-address @%s", instance, ddi_get_name_addr(dip));
1010 1010
1011 1011 if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
1012 1012 return (DDI_PROBE_DONTCARE);
1013 1013
1014 1014 if (ddi_get_soft_state(sgen_soft_state, instance) != NULL)
1015 1015 return (DDI_PROBE_FAILURE);
1016 1016
1017 1017 mutex_enter(&sgen_binddb.sdb_lock);
1018 1018 if (sgen_binddb.sdb_init == 0) {
1019 1019 sgen_setup_binddb(dip);
1020 1020 }
1021 1021 mutex_exit(&sgen_binddb.sdb_lock);
1022 1022
1023 1023 /*
1024 1024 * A small optimization: if it's impossible for sgen to bind to
1025 1025 * any devices, don't bother probing, just fail.
1026 1026 */
1027 1027 if ((sgen_binddb.sdb_inq_nodes == NULL) &&
1028 1028 (sgen_binddb.sdb_type_nodes == NULL)) {
1029 1029 return (DDI_PROBE_FAILURE);
1030 1030 }
1031 1031
1032 1032 if (scsi_probe(scsidevp, NULL_FUNC) == SCSIPROBE_EXISTS) {
1033 1033 if (sgen_get_binding(dip) == 0) {
1034 1034 rval = DDI_PROBE_SUCCESS;
1035 1035 }
1036 1036 } else {
1037 1037 rval = DDI_PROBE_FAILURE;
1038 1038 }
1039 1039 scsi_unprobe(scsidevp);
1040 1040
1041 1041 sgen_log(NULL, SGEN_DIAG2, "sgen_probe() %s, device unit-address @%s",
1042 1042 rval == DDI_PROBE_SUCCESS ? "succeeded" : "failed",
1043 1043 ddi_get_name_addr(dip));
1044 1044 return (rval);
1045 1045 }
1046 1046
1047 1047 /*
1048 1048 * sgen_open()
1049 1049 * open(9e) entrypoint. sgen enforces a strict exclusive open policy per
1050 1050 * target.
1051 1051 */
1052 1052 /*ARGSUSED1*/
1053 1053 static int
1054 1054 sgen_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
1055 1055 {
1056 1056 dev_t dev = *dev_p;
1057 1057 sgen_state_t *sg_state;
1058 1058 int instance;
1059 1059
1060 1060 instance = getminor(dev);
1061 1061
1062 1062 if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1063 1063 return (ENXIO);
1064 1064
1065 1065 sgen_log(sg_state, SGEN_DIAG2, "in sgen_open(): instance = %d",
1066 1066 instance);
1067 1067
1068 1068 mutex_enter(&sg_state->sgen_mutex);
1069 1069
1070 1070 /*
1071 1071 * Don't allow new opens of a suspended device until the last close has
1072 1072 * happened. This is rather simplistic, but keeps the implementation
1073 1073 * straightforward.
1074 1074 */
1075 1075 if (SGEN_IS_SUSP(sg_state)) {
1076 1076 mutex_exit(&sg_state->sgen_mutex);
1077 1077 return (EIO);
1078 1078 }
1079 1079
1080 1080 /*
1081 1081 * Enforce exclusive access.
1082 1082 */
1083 1083 if (SGEN_IS_EXCL(sg_state) ||
1084 1084 (SGEN_IS_OPEN(sg_state) && (flag & FEXCL))) {
1085 1085 mutex_exit(&sg_state->sgen_mutex);
1086 1086 return (EBUSY);
1087 1087 }
1088 1088
1089 1089 if (flag & FEXCL)
1090 1090 SGEN_SET_EXCL(sg_state);
1091 1091
1092 1092 SGEN_SET_OPEN(sg_state);
1093 1093
1094 1094 mutex_exit(&sg_state->sgen_mutex);
1095 1095
1096 1096 return (0);
1097 1097 }
1098 1098
1099 1099 /*
1100 1100 * sgen_close()
1101 1101 * close(9e) entrypoint.
1102 1102 */
1103 1103 /*ARGSUSED1*/
1104 1104 static int
1105 1105 sgen_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
1106 1106 {
1107 1107 sgen_state_t *sg_state;
1108 1108 int instance;
1109 1109
1110 1110 instance = getminor(dev);
1111 1111
1112 1112 if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1113 1113 return (ENXIO);
1114 1114
1115 1115 sgen_log(sg_state, SGEN_DIAG2, "in sgen_close(): instance = %d",
1116 1116 instance);
1117 1117
1118 1118 mutex_enter(&sg_state->sgen_mutex);
1119 1119 SGEN_CLR_OPEN(sg_state);
1120 1120 SGEN_CLR_EXCL(sg_state);
1121 1121 SGEN_CLR_SUSP(sg_state); /* closing clears the 'I was suspended' bit */
1122 1122 mutex_exit(&sg_state->sgen_mutex);
1123 1123
1124 1124 sgen_log(sg_state, SGEN_DIAG2, "done sgen_close()");
1125 1125
1126 1126 return (0);
1127 1127 }
1128 1128
1129 1129 /*
1130 1130 * sgen_ioctl()
1131 1131 * sgen supports the USCSI(7I) ioctl interface.
1132 1132 */
1133 1133 /*ARGSUSED4*/
1134 1134 static int
1135 1135 sgen_ioctl(dev_t dev,
1136 1136 int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
1137 1137 {
1138 1138 int retval = 0;
1139 1139 sgen_state_t *sg_state;
1140 1140 int instance;
1141 1141
1142 1142 instance = getminor(dev);
1143 1143
1144 1144 if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1145 1145 return (ENXIO);
1146 1146
1147 1147 sgen_log(sg_state, SGEN_DIAG2, "in sgen_ioctl(): instance = %d",
1148 1148 instance);
1149 1149
1150 1150 /*
1151 1151 * If the driver has been suspended since the last open, fail all
1152 1152 * subsequent IO's so that the userland consumer reinitializes state.
1153 1153 */
1154 1154 mutex_enter(&sg_state->sgen_mutex);
1155 1155 if (SGEN_IS_SUSP(sg_state)) {
1156 1156 mutex_exit(&sg_state->sgen_mutex);
1157 1157 sgen_log(sg_state, SGEN_DIAG1, "sgen_ioctl: returning EIO: "
1158 1158 "driver instance %d was previously suspended", instance);
1159 1159 return (EIO);
1160 1160 }
1161 1161 mutex_exit(&sg_state->sgen_mutex);
1162 1162
1163 1163 switch (cmd) {
1164 1164 case SGEN_IOC_DIAG: {
1165 1165 if (arg > 3) {
1166 1166 arg = 0;
1167 1167 }
1168 1168 sg_state->sgen_diag = (int)arg;
1169 1169 retval = 0;
1170 1170 break;
1171 1171 }
1172 1172
1173 1173 case SGEN_IOC_READY: {
1174 1174 if (sgen_tur(dev) != 0) {
1175 1175 retval = EIO;
1176 1176 } else {
1177 1177 retval = 0;
1178 1178 }
1179 1179 break;
1180 1180 }
1181 1181
1182 1182 case USCSICMD:
1183 1183 retval = sgen_uscsi_cmd(dev, (struct uscsi_cmd *)arg, flag);
1184 1184 break;
1185 1185
1186 1186 default:
1187 1187 retval = ENOTTY;
1188 1188 }
1189 1189
1190 1190 sgen_log(sg_state, SGEN_DIAG2, "done sgen_ioctl(), returning %d",
1191 1191 retval);
1192 1192
1193 1193 return (retval);
1194 1194 }
1195 1195
1196 1196 /*
1197 1197 * sgen_uscsi_cmd()
1198 1198 * Setup, configuration and teardown for a uscsi(7I) command
1199 1199 */
1200 1200 /*ARGSUSED*/
1201 1201 static int
1202 1202 sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
1203 1203 {
1204 1204 struct uscsi_cmd *uscmd;
1205 1205 struct buf *bp;
1206 1206 sgen_state_t *sg_state;
1207 1207 enum uio_seg uioseg;
1208 1208 int instance;
1209 1209 int flags;
1210 1210 int err;
1211 1211
1212 1212 instance = getminor(dev);
1213 1213
1214 1214 sg_state = ddi_get_soft_state(sgen_soft_state, instance);
1215 1215 ASSERT(sg_state);
1216 1216
1217 1217 sgen_log(sg_state, SGEN_DIAG2, "in sgen_uscsi_cmd(): instance = %d",
1218 1218 instance);
1219 1219
1220 1220 /*
1221 1221 * At this point, we start affecting state relevant to the target,
1222 1222 * so access needs to be serialized.
1223 1223 */
1224 1224 if (sgen_hold_cmdbuf(sg_state) != 0) {
1225 1225 sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: interrupted");
1226 1226 return (EINTR);
1227 1227 }
1228 1228
1229 1229 err = scsi_uscsi_alloc_and_copyin((intptr_t)ucmd, flag,
1230 1230 &sg_state->sgen_scsiaddr, &uscmd);
1231 1231 if (err != 0) {
1232 1232 sgen_rele_cmdbuf(sg_state);
1233 1233 sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: "
1234 1234 "scsi_uscsi_alloc_and_copyin failed\n");
1235 1235 return (err);
1236 1236 }
1237 1237
1238 1238 /*
1239 1239 * Clear out undesirable command flags
1240 1240 */
1241 1241 flags = (uscmd->uscsi_flags & ~(USCSI_NOINTR | USCSI_NOPARITY |
1242 1242 USCSI_OTAG | USCSI_HTAG | USCSI_HEAD));
1243 1243 if (flags != uscmd->uscsi_flags) {
1244 1244 sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: cleared "
1245 1245 "unsafe uscsi_flags 0x%x", uscmd->uscsi_flags & ~flags);
1246 1246 uscmd->uscsi_flags = flags;
1247 1247 }
1248 1248
1249 1249 if (uscmd->uscsi_cdb != NULL) {
1250 1250 sgen_dump_cdb(sg_state, "sgen_uscsi_cmd: ",
1251 1251 (union scsi_cdb *)uscmd->uscsi_cdb, uscmd->uscsi_cdblen);
1252 1252 }
1253 1253
1254 1254 /*
1255 1255 * Stash the sense buffer into sgen_rqs_sen for convenience.
1256 1256 */
1257 1257 sg_state->sgen_rqs_sen = uscmd->uscsi_rqbuf;
1258 1258
1259 1259 bp = sg_state->sgen_cmdbuf;
1260 1260 bp->av_back = NULL;
1261 1261 bp->av_forw = NULL;
1262 1262 bp->b_private = (struct buf *)uscmd;
1263 1263 uioseg = (flag & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
1264 1264
1265 1265 err = scsi_uscsi_handle_cmd(dev, uioseg, uscmd, sgen_start, bp, NULL);
1266 1266
1267 1267 if (sg_state->sgen_cmdpkt != NULL) {
1268 1268 uscmd->uscsi_status = SCBP_C(sg_state->sgen_cmdpkt);
1269 1269 } else {
1270 1270 uscmd->uscsi_status = 0;
1271 1271 }
1272 1272
1273 1273 sgen_log(sg_state, SGEN_DIAG3, "sgen_uscsi_cmd: awake from waiting "
1274 1274 "for command. Status is 0x%x", uscmd->uscsi_status);
1275 1275
1276 1276 if (uscmd->uscsi_rqbuf != NULL) {
1277 1277 int rqlen = uscmd->uscsi_rqlen - uscmd->uscsi_rqresid;
1278 1278 sgen_dump_sense(sg_state, rqlen,
1279 1279 (uchar_t *)uscmd->uscsi_rqbuf);
1280 1280 }
1281 1281
1282 1282 (void) scsi_uscsi_copyout_and_free((intptr_t)ucmd, uscmd);
1283 1283
1284 1284 if (sg_state->sgen_cmdpkt != NULL) {
1285 1285 scsi_destroy_pkt(sg_state->sgen_cmdpkt);
1286 1286 sg_state->sgen_cmdpkt = NULL;
1287 1287 }
1288 1288
1289 1289 /*
1290 1290 * After this point, we can't touch per-target state.
1291 1291 */
1292 1292 sgen_rele_cmdbuf(sg_state);
1293 1293
1294 1294 sgen_log(sg_state, SGEN_DIAG2, "done sgen_uscsi_cmd()");
1295 1295
1296 1296 return (err);
1297 1297 }
1298 1298
1299 1299 /*
1300 1300 * sgen_hold_cmdbuf()
1301 1301 * Acquire a lock on the command buffer for the given target. Returns
1302 1302 * non-zero if interrupted.
1303 1303 */
1304 1304 static int
1305 1305 sgen_hold_cmdbuf(sgen_state_t *sg_state)
1306 1306 {
1307 1307 mutex_enter(&sg_state->sgen_mutex);
1308 1308 while (SGEN_IS_BUSY(sg_state)) {
1309 1309 if (!cv_wait_sig(&sg_state->sgen_cmdbuf_cv,
1310 1310 &sg_state->sgen_mutex)) {
1311 1311 mutex_exit(&sg_state->sgen_mutex);
1312 1312 return (-1);
1313 1313 }
1314 1314 }
1315 1315 SGEN_SET_BUSY(sg_state);
1316 1316 mutex_exit(&sg_state->sgen_mutex);
1317 1317 return (0);
1318 1318 }
1319 1319
1320 1320 /*
1321 1321 * sgen_rele_cmdbuf()
1322 1322 * release the command buffer for a particular target.
1323 1323 */
1324 1324 static void
1325 1325 sgen_rele_cmdbuf(sgen_state_t *sg_state)
1326 1326 {
1327 1327 mutex_enter(&sg_state->sgen_mutex);
1328 1328 SGEN_CLR_BUSY(sg_state);
1329 1329 cv_signal(&sg_state->sgen_cmdbuf_cv);
1330 1330 mutex_exit(&sg_state->sgen_mutex);
1331 1331 }
1332 1332
1333 1333 /*
1334 1334 * sgen_start()
1335 1335 * Transport a uscsi command; this is invoked by physio() or directly
1336 1336 * by sgen_uscsi_cmd().
1337 1337 */
1338 1338 static int
1339 1339 sgen_start(struct buf *bp)
1340 1340 {
1341 1341 sgen_state_t *sg_state;
1342 1342 dev_t dev = bp->b_edev;
1343 1343 int trans_err;
1344 1344
1345 1345 if ((sg_state = ddi_get_soft_state(sgen_soft_state,
1346 1346 getminor(dev))) == NULL) {
1347 1347 bp->b_resid = bp->b_bcount;
1348 1348 bioerror(bp, ENXIO);
1349 1349 biodone(bp);
1350 1350 return (ENXIO);
1351 1351 }
1352 1352
1353 1353 /*
1354 1354 * Sanity checks - command should not be complete, no packet should
1355 1355 * be allocated, and there ought to be a uscsi cmd in b_private
1356 1356 */
1357 1357 ASSERT(bp == sg_state->sgen_cmdbuf && sg_state->sgen_cmdpkt == NULL);
1358 1358 ASSERT((bp->b_flags & B_DONE) == 0);
1359 1359 ASSERT(bp->b_private);
1360 1360 if (sgen_make_uscsi_cmd(sg_state, bp) != 0) {
1361 1361 bp->b_resid = bp->b_bcount;
1362 1362 bioerror(bp, EFAULT);
1363 1363 biodone(bp);
1364 1364 return (EFAULT);
1365 1365 }
1366 1366
1367 1367 ASSERT(sg_state->sgen_cmdpkt != NULL);
1368 1368
1369 1369 /*
1370 1370 * Clear out the residual and error fields
1371 1371 */
1372 1372 bp->b_resid = 0;
1373 1373 bp->b_error = 0;
1374 1374
1375 1375 trans_err = sgen_scsi_transport(sg_state->sgen_cmdpkt);
1376 1376 switch (trans_err) {
1377 1377 case TRAN_ACCEPT:
1378 1378 break;
1379 1379 case TRAN_BUSY:
1380 1380 sgen_log(sg_state, SGEN_DIAG2,
1381 1381 "sgen_start: scsi_transport() returned TRAN_BUSY");
1382 1382 sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1383 1383 SGEN_BSY_TIMEOUT);
1384 1384 break;
1385 1385 default:
1386 1386 /*
1387 1387 * Indicate there has been an I/O transfer error.
1388 1388 * Be done with the command.
1389 1389 */
1390 1390 mutex_enter(&sg_state->sgen_mutex);
1391 1391 SGEN_DO_ERRSTATS(sg_state, sgen_trans_err);
1392 1392 mutex_exit(&sg_state->sgen_mutex);
1393 1393 sgen_log(sg_state, SGEN_DIAG2, "sgen_start: scsi_transport() "
1394 1394 "returned %d", trans_err);
1395 1395 bioerror(bp, EIO);
1396 1396 biodone(bp);
1397 1397 return (EIO);
1398 1398 }
1399 1399 sgen_log(sg_state, SGEN_DIAG2, "sgen_start: b_flags 0x%x", bp->b_flags);
1400 1400 return (0);
1401 1401 }
1402 1402
1403 1403 /*
1404 1404 * sgen_scsi_transport()
1405 1405 * a simple scsi_transport() wrapper which can be configured to inject
1406 1406 * sporadic errors for testing.
1407 1407 */
1408 1408 static int
1409 1409 sgen_scsi_transport(struct scsi_pkt *pkt)
1410 1410 {
1411 1411 int trans_err;
1412 1412 static int cnt = 0;
1413 1413 sgen_state_t *sg_state = pkt->pkt_private;
1414 1414
1415 1415 if (sgen_sporadic_failures == 0) {
1416 1416 return (scsi_transport(pkt));
1417 1417 }
1418 1418
1419 1419 cnt = (cnt * 2416 + 374441) % 1771875; /* borrowed from kmem.c */
1420 1420 if (cnt % 40 == 1) {
1421 1421 sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1422 1422 "injecting sporadic BUSY");
1423 1423 trans_err = TRAN_BUSY;
1424 1424 } else if (cnt % 40 == 2) {
1425 1425 sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1426 1426 "injecting sporadic BADPKT");
1427 1427 trans_err = TRAN_BADPKT;
1428 1428 } else {
1429 1429 /*
1430 1430 * Most of the time we take the normal path
1431 1431 */
1432 1432 trans_err = scsi_transport(pkt);
1433 1433 }
1434 1434 return (trans_err);
1435 1435 }
1436 1436
1437 1437 /*
1438 1438 * sgen_make_uscsi_cmd()
1439 1439 * Initialize a SCSI packet usable for USCSI.
1440 1440 */
1441 1441 static int
1442 1442 sgen_make_uscsi_cmd(sgen_state_t *sg_state, struct buf *bp)
1443 1443 {
1444 1444 struct scsi_pkt *pkt;
1445 1445 struct uscsi_cmd *ucmd;
1446 1446 int stat_size = 1;
1447 1447 int flags = 0;
1448 1448
1449 1449 ASSERT(bp);
1450 1450
1451 1451 sgen_log(sg_state, SGEN_DIAG2, "in sgen_make_uscsi_cmd()");
1452 1452
1453 1453 ucmd = (struct uscsi_cmd *)bp->b_private;
1454 1454
1455 1455 if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1456 1456 if (ucmd->uscsi_rqlen > SENSE_LENGTH) {
1457 1457 stat_size = (int)(ucmd->uscsi_rqlen) +
1458 1458 sizeof (struct scsi_arq_status) -
1459 1459 sizeof (struct scsi_extended_sense);
1460 1460 flags = PKT_XARQ;
1461 1461 } else {
1462 1462 stat_size = sizeof (struct scsi_arq_status);
1463 1463 }
1464 1464 }
1465 1465
1466 1466 sgen_log(sg_state, SGEN_DIAG3, "sgen_make_uscsi_cmd: b_bcount = %ld",
1467 1467 bp->b_bcount);
1468 1468 pkt = scsi_init_pkt(&sg_state->sgen_scsiaddr,
1469 1469 NULL, /* in_pkt - null so it'll be alloc'd */
1470 1470 bp->b_bcount ? bp : NULL, /* buf structure for data xfer */
1471 1471 ucmd->uscsi_cdblen, /* cmdlen */
1472 1472 stat_size, /* statuslen */
1473 1473 0, /* privatelen */
1474 1474 flags, /* flags */
1475 1475 SLEEP_FUNC, /* callback */
1476 1476 (caddr_t)sg_state); /* callback_arg */
1477 1477
1478 1478 if (pkt == NULL) {
1479 1479 sgen_log(sg_state, SGEN_DIAG2, "failed sgen_make_uscsi_cmd()");
1480 1480 return (-1);
1481 1481 }
1482 1482
1483 1483 pkt->pkt_comp = sgen_callback;
1484 1484 pkt->pkt_private = sg_state;
1485 1485 sg_state->sgen_cmdpkt = pkt;
1486 1486
1487 1487 /*
1488 1488 * We *don't* call scsi_setup_cdb here, as is customary, since the
1489 1489 * user could specify a command from one group, but pass cdblen
1490 1490 * as something totally different. If cdblen is smaller than expected,
1491 1491 * this results in scsi_setup_cdb writing past the end of the cdb.
1492 1492 */
1493 1493 bcopy(ucmd->uscsi_cdb, pkt->pkt_cdbp, ucmd->uscsi_cdblen);
1494 1494 if (ucmd->uscsi_cdblen >= CDB_GROUP0) {
1495 1495 FILL_SCSI1_LUN(sg_state->sgen_scsidev, pkt);
1496 1496 }
1497 1497
1498 1498 if (ucmd->uscsi_timeout > 0)
1499 1499 pkt->pkt_time = ucmd->uscsi_timeout;
1500 1500 else
1501 1501 pkt->pkt_time = SGEN_IO_TIME;
1502 1502
1503 1503 /*
1504 1504 * Set packet options
1505 1505 */
1506 1506 if (ucmd->uscsi_flags & USCSI_SILENT)
1507 1507 pkt->pkt_flags |= FLAG_SILENT;
1508 1508 if (ucmd->uscsi_flags & USCSI_ISOLATE)
1509 1509 pkt->pkt_flags |= FLAG_ISOLATE;
1510 1510 if (ucmd->uscsi_flags & USCSI_DIAGNOSE)
1511 1511 pkt->pkt_flags |= FLAG_DIAGNOSE;
1512 1512 if (ucmd->uscsi_flags & USCSI_RENEGOT) {
1513 1513 pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
1514 1514 }
1515 1515
1516 1516 /* Transfer uscsi information to scsi_pkt */
1517 1517 (void) scsi_uscsi_pktinit(ucmd, pkt);
1518 1518
1519 1519 sgen_log(sg_state, SGEN_DIAG2, "done sgen_make_uscsi_cmd()");
1520 1520 return (0);
1521 1521 }
1522 1522
1523 1523
1524 1524 /*
1525 1525 * sgen_restart()
1526 1526 * sgen_restart() is called after a timeout, when a command has been
1527 1527 * postponed due to a TRAN_BUSY response from the HBA.
1528 1528 */
1529 1529 static void
1530 1530 sgen_restart(void *arg)
1531 1531 {
1532 1532 sgen_state_t *sg_state = (sgen_state_t *)arg;
1533 1533 struct scsi_pkt *pkt;
1534 1534 struct buf *bp;
1535 1535
1536 1536 sgen_log(sg_state, SGEN_DIAG2, "in sgen_restart()");
1537 1537
1538 1538 bp = sg_state->sgen_cmdbuf;
1539 1539 pkt = sg_state->sgen_cmdpkt;
1540 1540 ASSERT(bp && pkt);
1541 1541
1542 1542 SGEN_DO_ERRSTATS(sg_state, sgen_restart);
1543 1543
1544 1544 /*
1545 1545 * If the packet is marked with the sensing flag, sgen is off running
1546 1546 * a request sense, and *that packet* is what needs to be restarted.
1547 1547 */
1548 1548 if (pkt->pkt_flags & FLAG_SENSING) {
1549 1549 sgen_log(sg_state, SGEN_DIAG3,
1550 1550 "sgen_restart: restarting REQUEST SENSE");
1551 1551 pkt = sg_state->sgen_rqspkt;
1552 1552 }
1553 1553
1554 1554 if (sgen_scsi_transport(pkt) != TRAN_ACCEPT) {
1555 1555 bp->b_resid = bp->b_bcount;
1556 1556 bioerror(bp, EIO);
1557 1557 biodone(bp);
1558 1558 }
1559 1559 }
1560 1560
1561 1561 /*
1562 1562 * sgen_callback()
1563 1563 * Command completion processing
1564 1564 *
1565 1565 * sgen's completion processing is very pessimistic-- it does not retry
1566 1566 * failed commands; instead, it allows the user application to make
1567 1567 * decisions about what has gone wrong.
1568 1568 */
1569 1569 static void
1570 1570 sgen_callback(struct scsi_pkt *pkt)
1571 1571 {
1572 1572 sgen_state_t *sg_state;
1573 1573 struct uscsi_cmd *ucmd;
1574 1574 struct buf *bp;
1575 1575 int action;
1576 1576
1577 1577 sg_state = pkt->pkt_private;
1578 1578 /*
1579 1579 * bp should always be the command buffer regardless of whether
1580 1580 * this is a command completion or a request-sense completion.
1581 1581 * This is because there is no need to biodone() the sense buf
1582 1582 * when it completes-- we want to biodone() the actual command buffer!
1583 1583 */
1584 1584 bp = sg_state->sgen_cmdbuf;
1585 1585 if (pkt->pkt_flags & FLAG_SENSING) {
1586 1586 ASSERT(pkt == sg_state->sgen_rqspkt);
1587 1587 sgen_log(sg_state, SGEN_DIAG2,
1588 1588 "in sgen_callback() (SENSE completion callback)");
1589 1589 } else {
1590 1590 ASSERT(pkt == sg_state->sgen_cmdpkt);
1591 1591 sgen_log(sg_state, SGEN_DIAG2,
1592 1592 "in sgen_callback() (command completion callback)");
1593 1593 }
1594 1594 ucmd = (struct uscsi_cmd *)bp->b_private;
1595 1595
1596 1596 sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: reason=0x%x resid=%ld "
1597 1597 "state=0x%x", pkt->pkt_reason, pkt->pkt_resid, pkt->pkt_state);
1598 1598
1599 1599 /* Transfer scsi_pkt information to uscsi */
1600 1600 (void) scsi_uscsi_pktfini(pkt, ucmd);
1601 1601
1602 1602 if (pkt->pkt_reason != CMD_CMPLT) {
1603 1603 /*
1604 1604 * The command did not complete.
1605 1605 */
1606 1606 sgen_log(sg_state, SGEN_DIAG3,
1607 1607 "sgen_callback: command did not complete");
1608 1608 action = sgen_handle_incomplete(sg_state, pkt);
1609 1609 } else if (sg_state->sgen_arq_enabled &&
1610 1610 (pkt->pkt_state & STATE_ARQ_DONE)) {
1611 1611 /*
1612 1612 * The auto-rqsense happened, and the packet has a filled-in
1613 1613 * scsi_arq_status structure, pointed to by pkt_scbp.
1614 1614 */
1615 1615 sgen_log(sg_state, SGEN_DIAG3,
1616 1616 "sgen_callback: received auto-requested sense");
1617 1617 action = sgen_handle_autosense(sg_state, pkt);
1618 1618 ASSERT(action != FETCH_SENSE);
1619 1619 } else if (pkt->pkt_flags & FLAG_SENSING) {
1620 1620 /*
1621 1621 * sgen was running a REQUEST SENSE. Decode the sense data and
1622 1622 * decide what to do next.
1623 1623 *
1624 1624 * Clear FLAG_SENSING on the original packet for completeness.
1625 1625 */
1626 1626 sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: received sense");
1627 1627 sg_state->sgen_cmdpkt->pkt_flags &= ~FLAG_SENSING;
1628 1628 action = sgen_handle_sense(sg_state);
1629 1629 ASSERT(action != FETCH_SENSE);
1630 1630 } else {
1631 1631 /*
1632 1632 * Command completed and we're not getting sense. Check for
1633 1633 * errors and decide what to do next.
1634 1634 */
1635 1635 sgen_log(sg_state, SGEN_DIAG3,
1636 1636 "sgen_callback: command appears complete");
1637 1637 action = sgen_check_error(sg_state, bp);
1638 1638 }
1639 1639
1640 1640 switch (action) {
1641 1641 case FETCH_SENSE:
1642 1642 /*
1643 1643 * If there is sense to fetch, break out to prevent biodone'ing
1644 1644 * until the sense fetch is complete.
1645 1645 */
1646 1646 if (sgen_initiate_sense(sg_state,
1647 1647 scsi_pkt_allocated_correctly(pkt) ?
1648 1648 pkt->pkt_path_instance : 0) == 0)
1649 1649 break;
1650 1650 /*FALLTHROUGH*/
1651 1651 case COMMAND_DONE_ERROR:
1652 1652 bp->b_resid = bp->b_bcount;
1653 1653 bioerror(bp, EIO);
1654 1654 /*FALLTHROUGH*/
1655 1655 case COMMAND_DONE:
1656 1656 biodone(bp);
1657 1657 break;
1658 1658 default:
1659 1659 ASSERT(0);
1660 1660 break;
1661 1661 }
1662 1662
1663 1663 sgen_log(sg_state, SGEN_DIAG2, "done sgen_callback()");
1664 1664 }
1665 1665
1666 1666 /*
1667 1667 * sgen_initiate_sense()
1668 1668 * Send the sgen_rqspkt to the target, thereby requesting sense data.
1669 1669 */
1670 1670 static int
1671 1671 sgen_initiate_sense(sgen_state_t *sg_state, int path_instance)
1672 1672 {
1673 1673 /* use same path_instance as command */
1674 1674 if (scsi_pkt_allocated_correctly(sg_state->sgen_rqspkt))
1675 1675 sg_state->sgen_rqspkt->pkt_path_instance = path_instance;
1676 1676
1677 1677 switch (sgen_scsi_transport(sg_state->sgen_rqspkt)) {
1678 1678 case TRAN_ACCEPT:
1679 1679 sgen_log(sg_state, SGEN_DIAG3, "sgen_initiate_sense: "
1680 1680 "sense fetch transport accepted.");
1681 1681 return (0);
1682 1682 case TRAN_BUSY:
1683 1683 sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1684 1684 "sense fetch transport busy, setting timeout.");
1685 1685 sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1686 1686 SGEN_BSY_TIMEOUT);
1687 1687 return (0);
1688 1688 default:
1689 1689 sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1690 1690 "sense fetch transport failed or busy.");
1691 1691 return (-1);
1692 1692 }
1693 1693 }
1694 1694
1695 1695 /*
1696 1696 * sgen_handle_incomplete()
1697 1697 * sgen is pessimistic, but also careful-- it doesn't try to retry
1698 1698 * incomplete commands, but it also doesn't go resetting devices;
1699 1699 * it is hard to tell if the device will be tolerant of that sort
1700 1700 * of prodding.
1701 1701 *
1702 1702 * This routine has been left as a guide for the future--- the
1703 1703 * current administration's hands-off policy may need modification.
1704 1704 */
1705 1705 /*ARGSUSED*/
1706 1706 static int
1707 1707 sgen_handle_incomplete(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1708 1708 {
1709 1709 SGEN_DO_ERRSTATS(sg_state, sgen_incmp_err);
1710 1710 return (COMMAND_DONE_ERROR);
1711 1711 }
1712 1712
1713 1713 /*
1714 1714 * sgen_handle_autosense()
1715 1715 * Deal with SENSE data acquired automatically via the auto-request-sense
1716 1716 * facility.
1717 1717 *
1718 1718 * Sgen takes a pessimistic view of things-- it doesn't retry commands,
1719 1719 * and unless the device recovered from the problem, this routine returns
1720 1720 * COMMAND_DONE_ERROR.
1721 1721 */
1722 1722 static int
1723 1723 sgen_handle_autosense(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1724 1724 {
1725 1725 struct scsi_arq_status *arqstat;
1726 1726 struct uscsi_cmd *ucmd =
1727 1727 (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1728 1728 int amt;
1729 1729
1730 1730 arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp);
1731 1731
1732 1732 SGEN_DO_ERRSTATS(sg_state, sgen_autosen_rcv);
1733 1733
1734 1734 if (arqstat->sts_rqpkt_reason != CMD_CMPLT) {
1735 1735 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: ARQ"
1736 1736 "failed to complete.");
1737 1737 SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1738 1738 return (COMMAND_DONE_ERROR);
1739 1739 }
1740 1740
1741 1741 if (pkt->pkt_state & STATE_XARQ_DONE) {
1742 1742 amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1743 1743 } else {
1744 1744 if (arqstat->sts_rqpkt_resid > SENSE_LENGTH) {
1745 1745 amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1746 1746 } else {
1747 1747 amt = SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1748 1748 }
1749 1749 }
1750 1750
1751 1751 if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1752 1752 ucmd->uscsi_rqstatus = *((char *)&arqstat->sts_rqpkt_status);
1753 1753 uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1754 1754 ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1755 1755 ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1756 1756 bcopy(&(arqstat->sts_sensedata), sg_state->sgen_rqs_sen, rqlen);
1757 1757 sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_autosense: "
1758 1758 "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1759 1759 ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1760 1760 }
1761 1761
1762 1762 if (arqstat->sts_rqpkt_status.sts_chk) {
1763 1763 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1764 1764 "check condition on auto request sense!");
1765 1765 SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1766 1766 return (COMMAND_DONE_ERROR);
1767 1767 }
1768 1768
1769 1769 if (((arqstat->sts_rqpkt_state & STATE_XFERRED_DATA) == 0) ||
1770 1770 (amt == 0)) {
1771 1771 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1772 1772 "auto-sense, but it contains no data!");
1773 1773 SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1774 1774 return (COMMAND_DONE_ERROR);
1775 1775 }
1776 1776
1777 1777 /*
1778 1778 * Stuff the sense data pointer into sgen_sense for later retrieval
1779 1779 */
1780 1780 sg_state->sgen_sense = &arqstat->sts_sensedata;
1781 1781
1782 1782 /*
1783 1783 * Now, check to see whether we got enough sense data to make any
1784 1784 * sense out if it (heh-heh).
1785 1785 */
1786 1786 if (amt < SUN_MIN_SENSE_LENGTH) {
1787 1787 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: not "
1788 1788 "enough auto sense data");
1789 1789 return (COMMAND_DONE_ERROR);
1790 1790 }
1791 1791
1792 1792 switch (arqstat->sts_sensedata.es_key) {
1793 1793 case KEY_RECOVERABLE_ERROR:
1794 1794 SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1795 1795 break;
1796 1796 case KEY_NO_SENSE:
1797 1797 SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1798 1798 break;
1799 1799 default:
1800 1800 SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1801 1801 break;
1802 1802 }
1803 1803
1804 1804 return (COMMAND_DONE);
1805 1805 }
1806 1806
1807 1807 /*
1808 1808 * sgen_handle_sense()
1809 1809 * Examine sense data that was manually fetched from the target.
1810 1810 */
1811 1811 static int
1812 1812 sgen_handle_sense(sgen_state_t *sg_state)
1813 1813 {
1814 1814 struct scsi_pkt *rqpkt = sg_state->sgen_rqspkt;
1815 1815 struct scsi_status *rqstatus = (struct scsi_status *)rqpkt->pkt_scbp;
1816 1816 struct uscsi_cmd *ucmd =
1817 1817 (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1818 1818 int amt;
1819 1819
1820 1820 SGEN_DO_ERRSTATS(sg_state, sgen_sense_rcv);
1821 1821
1822 1822 amt = MAX_SENSE_LENGTH - rqpkt->pkt_resid;
1823 1823
1824 1824 if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1825 1825 ucmd->uscsi_rqstatus = *((char *)rqstatus);
1826 1826 uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1827 1827 ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1828 1828 ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1829 1829 bcopy(sg_state->sgen_sense, sg_state->sgen_rqs_sen, rqlen);
1830 1830 sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_sense: "
1831 1831 "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1832 1832 ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1833 1833 }
1834 1834
1835 1835 if (rqstatus->sts_busy) {
1836 1836 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got busy "
1837 1837 "on request sense");
1838 1838 SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1839 1839 return (COMMAND_DONE_ERROR);
1840 1840 }
1841 1841
1842 1842 if (rqstatus->sts_chk) {
1843 1843 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got check "
1844 1844 "condition on request sense!");
1845 1845 SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1846 1846 return (COMMAND_DONE_ERROR);
1847 1847 }
1848 1848
1849 1849 if ((rqpkt->pkt_state & STATE_XFERRED_DATA) == 0 || amt == 0) {
1850 1850 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got "
1851 1851 "sense, but it contains no data");
1852 1852 SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1853 1853 return (COMMAND_DONE_ERROR);
1854 1854 }
1855 1855
1856 1856 /*
1857 1857 * Now, check to see whether we got enough sense data to make any
1858 1858 * sense out if it (heh-heh).
1859 1859 */
1860 1860 if (amt < SUN_MIN_SENSE_LENGTH) {
1861 1861 sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: not "
1862 1862 "enough sense data");
1863 1863 SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1864 1864 return (COMMAND_DONE_ERROR);
1865 1865 }
1866 1866
1867 1867 /*
1868 1868 * Decode the sense data-- this was deposited here for us by the
1869 1869 * setup in sgen_do_attach(). (note that sgen_sense is an alias for
1870 1870 * the sd_sense field in the scsi_device).
1871 1871 */
1872 1872 sgen_log(sg_state, SGEN_DIAG1, "Sense key is %s [0x%x]",
1873 1873 scsi_sname(sg_state->sgen_sense->es_key),
1874 1874 sg_state->sgen_sense->es_key);
1875 1875 switch (sg_state->sgen_sense->es_key) {
1876 1876 case KEY_RECOVERABLE_ERROR:
1877 1877 SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1878 1878 break;
1879 1879 case KEY_NO_SENSE:
1880 1880 SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1881 1881 break;
1882 1882 default:
1883 1883 SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1884 1884 break;
1885 1885 }
1886 1886
1887 1887 return (COMMAND_DONE);
1888 1888 }
1889 1889
1890 1890 /*
1891 1891 * sgen_check_error()
1892 1892 * examine the command packet for abnormal completion.
1893 1893 *
1894 1894 * sgen_check_error should only be called at the completion of the
1895 1895 * command packet.
1896 1896 */
1897 1897 static int
1898 1898 sgen_check_error(sgen_state_t *sg_state, struct buf *bp)
1899 1899 {
1900 1900 struct scsi_pkt *pkt = sg_state->sgen_cmdpkt;
1901 1901 struct scsi_status *status = (struct scsi_status *)pkt->pkt_scbp;
1902 1902 struct uscsi_cmd *ucmd =
1903 1903 (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1904 1904
1905 1905 if (status->sts_busy) {
1906 1906 sgen_log(sg_state, SGEN_DIAG1,
1907 1907 "sgen_check_error: target is busy");
1908 1908 return (COMMAND_DONE_ERROR);
1909 1909 }
1910 1910
1911 1911 /*
1912 1912 * pkt_resid will reflect, at this point, a residual of how many bytes
1913 1913 * were not transferred; a non-zero pkt_resid is an error.
1914 1914 */
1915 1915 if (pkt->pkt_resid) {
1916 1916 bp->b_resid += pkt->pkt_resid;
1917 1917 }
1918 1918
1919 1919 if (status->sts_chk) {
1920 1920 if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1921 1921 if (sg_state->sgen_arq_enabled) {
1922 1922 sgen_log(sg_state, SGEN_DIAG1,
1923 1923 "sgen_check_error: strange: target "
1924 1924 "indicates CHECK CONDITION with auto-sense "
1925 1925 "enabled.");
1926 1926 }
1927 1927 sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1928 1928 "target ready for sense fetch");
1929 1929 return (FETCH_SENSE);
1930 1930 } else {
1931 1931 sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1932 1932 "target indicates CHECK CONDITION");
1933 1933 }
1934 1934 }
1935 1935
1936 1936 return (COMMAND_DONE);
1937 1937 }
1938 1938
1939 1939 /*
1940 1940 * sgen_tur()
1941 1941 * test if a target is ready to operate by sending it a TUR command.
1942 1942 */
1943 1943 static int
1944 1944 sgen_tur(dev_t dev)
1945 1945 {
1946 1946 char cmdblk[CDB_GROUP0];
1947 1947 struct uscsi_cmd scmd;
1948 1948
1949 1949 bzero(&scmd, sizeof (scmd));
1950 1950 scmd.uscsi_bufaddr = 0;
1951 1951 scmd.uscsi_buflen = 0;
1952 1952 bzero(cmdblk, CDB_GROUP0);
1953 1953 cmdblk[0] = (char)SCMD_TEST_UNIT_READY;
1954 1954 scmd.uscsi_flags = USCSI_DIAGNOSE | USCSI_SILENT | USCSI_WRITE;
1955 1955 scmd.uscsi_cdb = cmdblk;
1956 1956 scmd.uscsi_cdblen = CDB_GROUP0;
1957 1957
1958 1958 return (sgen_uscsi_cmd(dev, &scmd, FKIOCTL));
1959 1959 }
1960 1960
1961 1961 /*
1962 1962 * sgen_diag_ok()
1963 1963 * given an sg_state and a desired diagnostic level, return true if
1964 1964 * it is acceptable to output a message.
1965 1965 */
1966 1966 /*ARGSUSED*/
1967 1967 static int
1968 1968 sgen_diag_ok(sgen_state_t *sg_state, int level)
1969 1969 {
1970 1970 int diag_lvl;
1971 1971
1972 1972 switch (level) {
1973 1973 case CE_WARN:
1974 1974 case CE_NOTE:
1975 1975 case CE_CONT:
1976 1976 case CE_PANIC:
1977 1977 return (1);
1978 1978 case SGEN_DIAG1:
1979 1979 case SGEN_DIAG2:
1980 1980 case SGEN_DIAG3:
1981 1981 if (sg_state) {
1982 1982 /*
1983 1983 * Check to see if user overrode the diagnostics level
1984 1984 * for this instance (either via SGEN_IOC_DIAG or via
1985 1985 * .conf file). If not, fall back to the global diag
1986 1986 * level.
1987 1987 */
1988 1988 if (sg_state->sgen_diag != -1)
1989 1989 diag_lvl = sg_state->sgen_diag;
1990 1990 else
1991 1991 diag_lvl = sgen_diag;
1992 1992 } else {
1993 1993 diag_lvl = sgen_diag;
1994 1994 }
1995 1995 if (((diag_lvl << 8) | CE_CONT) >= level) {
1996 1996 return (1);
1997 1997 } else {
1998 1998 return (0);
1999 1999 }
2000 2000 default:
2001 2001 return (1);
2002 2002 }
2003 2003 }
2004 2004
2005 2005 /*PRINTFLIKE3*/
2006 2006 static void
2007 2007 sgen_log(sgen_state_t *sg_state, int level, const char *fmt, ...)
2008 2008 {
2009 2009 va_list ap;
2010 2010 char buf[256];
2011 2011
2012 2012 if (!sgen_diag_ok(sg_state, level))
2013 2013 return;
2014 2014
2015 2015 va_start(ap, fmt);
2016 2016 (void) vsnprintf(buf, sizeof (buf), fmt, ap);
2017 2017 va_end(ap);
2018 2018
2019 2019 switch (level) {
2020 2020 case CE_NOTE:
2021 2021 case CE_CONT:
2022 2022 case CE_WARN:
2023 2023 case CE_PANIC:
2024 2024 if (sg_state == (sgen_state_t *)NULL) {
2025 2025 cmn_err(level, "%s", buf);
2026 2026 } else {
2027 2027 scsi_log(sg_state->sgen_devinfo, sgen_label, level,
2028 2028 "%s", buf);
2029 2029 }
2030 2030 break;
2031 2031 case SGEN_DIAG1:
2032 2032 case SGEN_DIAG2:
2033 2033 case SGEN_DIAG3:
2034 2034 default:
2035 2035 if (sg_state == (sgen_state_t *)NULL) {
2036 2036 scsi_log(NULL, sgen_label, CE_CONT, "%s", buf);
2037 2037 } else {
2038 2038 scsi_log(sg_state->sgen_devinfo, sgen_label, CE_CONT,
2039 2039 "%s", buf);
2040 2040 }
2041 2041 }
2042 2042 }
2043 2043
2044 2044 /*
2045 2045 * sgen_dump_cdb()
2046 2046 * dump out the contents of a cdb. Take care that 'label' is not too
2047 2047 * large, or 'buf' could overflow.
2048 2048 */
2049 2049 static void
2050 2050 sgen_dump_cdb(sgen_state_t *sg_state, const char *label,
2051 2051 union scsi_cdb *cdb, int cdblen)
2052 2052 {
2053 2053 static char hex[] = "0123456789abcdef";
2054 2054 char *buf, *p;
2055 2055 size_t nbytes;
2056 2056 int i;
2057 2057 uchar_t *cdbp = (uchar_t *)cdb;
2058 2058
2059 2059 /*
2060 2060 * fastpath-- if we're not able to print out, don't do all of this
2061 2061 * extra work.
2062 2062 */
2063 2063 if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2064 2064 return;
2065 2065
2066 2066 /*
2067 2067 * 3 characters for each byte (because of the ' '), plus the size of
2068 2068 * the label, plus the trailing ']' and the null character.
2069 2069 */
2070 2070 nbytes = 3 * cdblen + strlen(label) + strlen(" CDB = [") + 2;
2071 2071 buf = kmem_alloc(nbytes, KM_SLEEP);
2072 2072 (void) sprintf(buf, "%s CDB = [", label);
2073 2073 p = &buf[strlen(buf)];
2074 2074 for (i = 0; i < cdblen; i++, cdbp++) {
2075 2075 if (i > 0)
2076 2076 *p++ = ' ';
2077 2077 *p++ = hex[(*cdbp >> 4) & 0x0f];
2078 2078 *p++ = hex[*cdbp & 0x0f];
2079 2079 }
2080 2080 *p++ = ']';
2081 2081 *p = 0;
2082 2082 sgen_log(sg_state, SGEN_DIAG3, buf);
2083 2083 kmem_free(buf, nbytes);
2084 2084 }
2085 2085
2086 2086 static void
2087 2087 sgen_dump_sense(sgen_state_t *sg_state, size_t rqlen, uchar_t *rqbuf)
2088 2088 {
2089 2089 static char hex[] = "0123456789abcdef";
2090 2090 char *buf, *p;
2091 2091 size_t nbytes;
2092 2092 int i;
2093 2093
2094 2094 /*
2095 2095 * fastpath-- if we're not able to print out, don't do all of this
2096 2096 * extra work.
2097 2097 */
2098 2098 if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2099 2099 return;
2100 2100
2101 2101 /*
2102 2102 * 3 characters for each byte (because of the ' '), plus the size of
2103 2103 * the label, plus the trailing ']' and the null character.
2104 2104 */
2105 2105 nbytes = 3 * rqlen + strlen(" SENSE = [") + 2;
2106 2106 buf = kmem_alloc(nbytes, KM_SLEEP);
2107 2107 (void) sprintf(buf, "SENSE = [");
2108 2108 p = &buf[strlen(buf)];
2109 2109 for (i = 0; i < rqlen; i++, rqbuf++) {
2110 2110 if (i > 0)
2111 2111 *p++ = ' ';
2112 2112 *p++ = hex[(*rqbuf >> 4) & 0x0f];
2113 2113 *p++ = hex[*rqbuf & 0x0f];
2114 2114 }
2115 2115 *p++ = ']';
2116 2116 *p = 0;
2117 2117 sgen_log(sg_state, SGEN_DIAG3, buf);
2118 2118 kmem_free(buf, nbytes);
2119 2119 }
↓ open down ↓ |
1905 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX