1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 *
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * SATA midlayer interface for PMC drier.
27 */
28
29 #include <sys/scsi/adapters/pmcs/pmcs.h>
30
31 static void
SATAcopy(pmcs_cmd_t * sp,void * kbuf,uint32_t amt)32 SATAcopy(pmcs_cmd_t *sp, void *kbuf, uint32_t amt)
33 {
34 struct buf *bp = scsi_pkt2bp(CMD2PKT(sp));
35
36 bp_mapin(scsi_pkt2bp(CMD2PKT(sp)));
37 /* There is only one direction currently */
38 (void) memcpy(bp->b_un.b_addr, kbuf, amt);
39 CMD2PKT(sp)->pkt_resid -= amt;
40 CMD2PKT(sp)->pkt_state |= STATE_XFERRED_DATA;
41 bp_mapout(scsi_pkt2bp(CMD2PKT(sp)));
42 }
43
44 /*
45 * Run a non block-io command. Some commands are interpreted
46 * out of extant data. Some imply actually running a SATA command.
47 *
48 * Returns zero if we were able to run.
49 *
50 * Returns -1 only if other commands are active, either another
51 * command here or regular I/O active.
52 *
53 * Called with PHY lock and xp statlock held.
54 */
55 #define SRESPSZ 128
56
57 static int
pmcs_sata_special_work(pmcs_hw_t * pwp,pmcs_xscsi_t * xp)58 pmcs_sata_special_work(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
59 {
60 int i;
61 int saq;
62 pmcs_cmd_t *sp;
63 struct scsi_pkt *pkt;
64 pmcs_phy_t *pptr;
65 uint8_t rp[SRESPSZ];
66 ata_identify_t *id;
67 uint32_t amt = 0;
68 uint8_t key = 0x05; /* illegal command */
69 uint8_t asc = 0;
70 uint8_t ascq = 0;
71 uint8_t status = STATUS_GOOD;
72
73 if (xp->actv_cnt) {
74 pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, xp,
75 "%s: target %p actv count %u",
76 __func__, (void *)xp, xp->actv_cnt);
77 return (-1);
78 }
79 if (xp->special_running) {
80 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
81 "%s: target %p special running already",
82 __func__, (void *)xp);
83 return (-1);
84 }
85 xp->special_needed = 0;
86
87 /*
88 * We're now running special.
89 */
90 xp->special_running = 1;
91 pptr = xp->phy;
92
93 sp = STAILQ_FIRST(&xp->sq);
94 if (sp == NULL) {
95 xp->special_running = 0;
96 return (0);
97 }
98
99 pkt = CMD2PKT(sp);
100 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
101 "%s: target %p cmd %p cdb0 %x with actv_cnt %u",
102 __func__, (void *)xp, (void *)sp, pkt->pkt_cdbp[0], xp->actv_cnt);
103
104 if (pkt->pkt_cdbp[0] == SCMD_INQUIRY ||
105 pkt->pkt_cdbp[0] == SCMD_READ_CAPACITY) {
106 int retval;
107
108 if (pmcs_acquire_scratch(pwp, B_FALSE)) {
109 xp->special_running = 0;
110 return (-1);
111 }
112 saq = 1;
113
114 mutex_exit(&xp->statlock);
115 retval = pmcs_sata_identify(pwp, pptr);
116 mutex_enter(&xp->statlock);
117
118 if (retval) {
119 pmcs_release_scratch(pwp);
120 xp->special_running = 0;
121
122 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
123 "%s: target %p identify failed %x",
124 __func__, (void *)xp, retval);
125 /*
126 * If the failure is due to not being
127 * able to get resources, return such
128 * that we'll try later. Otherwise,
129 * fail current command.
130 */
131 if (retval == ENOMEM) {
132 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
133 "%s: sata identify failed (ENOMEM) for "
134 "cmd %p", __func__, (void *)sp);
135 return (-1);
136 }
137 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
138 STATE_SENT_CMD;
139 if (retval == ETIMEDOUT) {
140 pkt->pkt_reason = CMD_TIMEOUT;
141 pkt->pkt_statistics |= STAT_TIMEOUT;
142 } else {
143 pkt->pkt_reason = CMD_TRAN_ERR;
144 }
145 goto out;
146 }
147
148 id = pwp->scratch;
149
150 /*
151 * Check to see if this device is an NCQ capable device.
152 * Yes, we'll end up doing this check for every INQUIRY
153 * if indeed we *are* only a pio device, but this is so
154 * infrequent that it's not really worth an extra bitfield.
155 *
156 * Note that PIO mode here means that the PMCS firmware
157 * performs PIO- not us.
158 */
159 if (xp->ncq == 0) {
160 /*
161 * Reset existing stuff.
162 */
163 xp->pio = 0;
164 xp->qdepth = 1;
165 xp->tagmap = 0;
166
167 if (id->word76 != 0 && id->word76 != 0xffff &&
168 (LE_16(id->word76) & (1 << 8))) {
169 xp->ncq = 1;
170 xp->qdepth = (LE_16(id->word75) & 0x1f) + 1;
171 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
172 "%s: device %s supports NCQ %u deep",
173 __func__, xp->phy->path, xp->qdepth);
174 } else {
175 /*
176 * Default back to PIO.
177 *
178 * Note that non-FPDMA would still be possible,
179 * but for this specific configuration, if it's
180 * not NCQ it's safest to assume PIO.
181 */
182 xp->pio = 1;
183 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
184 "%s: device %s assumed PIO",
185 __func__, xp->phy->path);
186 }
187 }
188 } else {
189 saq = 0;
190 id = NULL;
191 }
192
193 bzero(rp, SRESPSZ);
194
195 switch (pkt->pkt_cdbp[0]) {
196 case SCMD_INQUIRY:
197 {
198 struct scsi_inquiry *inqp;
199 uint16_t *a, *b;
200
201 /* Check for illegal bits */
202 if ((pkt->pkt_cdbp[1] & 0xfc) || pkt->pkt_cdbp[5]) {
203 status = STATUS_CHECK;
204 asc = 0x24; /* invalid field in cdb */
205 break;
206 }
207 if (pkt->pkt_cdbp[1] & 0x1) {
208 switch (pkt->pkt_cdbp[2]) {
209 case 0x0:
210 rp[3] = 3;
211 rp[5] = 0x80;
212 rp[6] = 0x83;
213 amt = 7;
214 break;
215 case 0x80:
216 rp[1] = 0x80;
217 rp[3] = 0x14;
218 a = (void *) &rp[4];
219 b = id->model_number;
220 for (i = 0; i < 5; i++) {
221 *a = ddi_swap16(*b);
222 a++;
223 b++;
224 }
225 amt = 24;
226 break;
227 case 0x83:
228 rp[1] = 0x83;
229 if ((LE_16(id->word87) & 0x100) &&
230 (LE_16(id->word108) >> 12) == 5) {
231 rp[3] = 12;
232 rp[4] = 1;
233 rp[5] = 3;
234 rp[7] = 8;
235 rp[8] = LE_16(id->word108) >> 8;
236 rp[9] = LE_16(id->word108);
237 rp[10] = LE_16(id->word109) >> 8;
238 rp[11] = LE_16(id->word109);
239 rp[12] = LE_16(id->word110) >> 8;
240 rp[13] = LE_16(id->word110);
241 rp[14] = LE_16(id->word111) >> 8;
242 rp[15] = LE_16(id->word111);
243 amt = 16;
244 } else {
245 rp[3] = 64;
246 rp[4] = 2;
247 rp[5] = 1;
248 rp[7] = 60;
249 rp[8] = 'A';
250 rp[9] = 'T';
251 rp[10] = 'A';
252 rp[11] = ' ';
253 rp[12] = ' ';
254 rp[13] = ' ';
255 rp[14] = ' ';
256 rp[15] = ' ';
257 a = (void *) &rp[16];
258 b = id->model_number;
259 for (i = 0; i < 20; i++) {
260 *a = ddi_swap16(*b);
261 a++;
262 b++;
263 }
264 a = (void *) &rp[40];
265 b = id->serial_number;
266 for (i = 0; i < 10; i++) {
267 *a = ddi_swap16(*b);
268 a++;
269 b++;
270 }
271 amt = 68;
272 }
273 break;
274 default:
275 status = STATUS_CHECK;
276 asc = 0x24; /* invalid field in cdb */
277 break;
278 }
279 } else {
280 inqp = (struct scsi_inquiry *)rp;
281 inqp->inq_qual = 0;
282 inqp->inq_ansi = 5; /* spc3 */
283 inqp->inq_rdf = 2; /* response format 2 */
284 inqp->inq_len = 32;
285
286 if (xp->ncq && (xp->qdepth > 1)) {
287 inqp->inq_cmdque = 1;
288 }
289
290 (void) memcpy(inqp->inq_vid, "ATA ", 8);
291
292 a = (void *)inqp->inq_pid;
293 b = id->model_number;
294 for (i = 0; i < 8; i++) {
295 *a = ddi_swap16(*b);
296 a++;
297 b++;
298 }
299 if (id->firmware_revision[2] == 0x2020 &&
300 id->firmware_revision[3] == 0x2020) {
301 inqp->inq_revision[0] =
302 ddi_swap16(id->firmware_revision[0]) >> 8;
303 inqp->inq_revision[1] =
304 ddi_swap16(id->firmware_revision[0]);
305 inqp->inq_revision[2] =
306 ddi_swap16(id->firmware_revision[1]) >> 8;
307 inqp->inq_revision[3] =
308 ddi_swap16(id->firmware_revision[1]);
309 } else {
310 inqp->inq_revision[0] =
311 ddi_swap16(id->firmware_revision[2]) >> 8;
312 inqp->inq_revision[1] =
313 ddi_swap16(id->firmware_revision[2]);
314 inqp->inq_revision[2] =
315 ddi_swap16(id->firmware_revision[3]) >> 8;
316 inqp->inq_revision[3] =
317 ddi_swap16(id->firmware_revision[3]);
318 }
319 amt = 36;
320 }
321 amt = pmcs_set_resid(pkt, amt, pkt->pkt_cdbp[4]);
322 if (amt) {
323 if (xp->actv_cnt) {
324 xp->special_needed = 1;
325 xp->special_running = 0;
326 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
327 "%s: @ line %d", __func__, __LINE__);
328 if (saq) {
329 pmcs_release_scratch(pwp);
330 }
331 return (-1);
332 }
333 SATAcopy(sp, rp, amt);
334 }
335 break;
336 }
337 case SCMD_READ_CAPACITY:
338 {
339 uint64_t last_block;
340 uint32_t block_size = 512; /* XXXX */
341
342 xp->capacity = LBA_CAPACITY(id);
343 last_block = xp->capacity - 1;
344 /* Check for illegal bits */
345 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[6] ||
346 (pkt->pkt_cdbp[8] & 0xfe) || pkt->pkt_cdbp[7] ||
347 pkt->pkt_cdbp[9]) {
348 status = STATUS_CHECK;
349 asc = 0x24; /* invalid field in cdb */
350 break;
351 }
352 for (i = 1; i < 10; i++) {
353 if (pkt->pkt_cdbp[i]) {
354 status = STATUS_CHECK;
355 asc = 0x24; /* invalid field in cdb */
356 break;
357 }
358 }
359 if (status != STATUS_GOOD) {
360 break;
361 }
362 if (last_block > 0xffffffffULL) {
363 last_block = 0xffffffffULL;
364 }
365 rp[0] = (last_block >> 24) & 0xff;
366 rp[1] = (last_block >> 16) & 0xff;
367 rp[2] = (last_block >> 8) & 0xff;
368 rp[3] = (last_block) & 0xff;
369 rp[4] = (block_size >> 24) & 0xff;
370 rp[5] = (block_size >> 16) & 0xff;
371 rp[6] = (block_size >> 8) & 0xff;
372 rp[7] = (block_size) & 0xff;
373 amt = 8;
374 amt = pmcs_set_resid(pkt, amt, 8);
375 if (amt) {
376 if (xp->actv_cnt) {
377 xp->special_needed = 1;
378 xp->special_running = 0;
379 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
380 "%s: @ line %d", __func__, __LINE__);
381 if (saq) {
382 pmcs_release_scratch(pwp);
383 }
384 return (-1);
385 }
386 SATAcopy(sp, rp, amt);
387 }
388 break;
389 }
390 case SCMD_REPORT_LUNS: {
391 int rl_len;
392
393 /* Check for illegal bits */
394 if (pkt->pkt_cdbp[1] || pkt->pkt_cdbp[3] || pkt->pkt_cdbp[4] ||
395 pkt->pkt_cdbp[5] || pkt->pkt_cdbp[10] ||
396 pkt->pkt_cdbp[11]) {
397 status = STATUS_CHECK;
398 asc = 0x24; /* invalid field in cdb */
399 break;
400 }
401
402 rp[3] = 8;
403 rl_len = 16; /* list length (4) + reserved (4) + 1 LUN (8) */
404 amt = rl_len;
405 amt = pmcs_set_resid(pkt, amt, rl_len);
406
407 if (amt) {
408 if (xp->actv_cnt) {
409 xp->special_needed = 1;
410 xp->special_running = 0;
411 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
412 "%s: @ line %d", __func__, __LINE__);
413 if (saq) {
414 pmcs_release_scratch(pwp);
415 }
416 return (-1);
417 }
418 SATAcopy(sp, rp, rl_len);
419 }
420 break;
421 }
422
423 case SCMD_REQUEST_SENSE:
424 /* Check for illegal bits */
425 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[2] ||
426 pkt->pkt_cdbp[3] || pkt->pkt_cdbp[5]) {
427 status = STATUS_CHECK;
428 asc = 0x24; /* invalid field in cdb */
429 break;
430 }
431 rp[0] = 0xf0;
432 amt = 18;
433 amt = pmcs_set_resid(pkt, amt, pkt->pkt_cdbp[4]);
434 if (amt) {
435 if (xp->actv_cnt) {
436 xp->special_needed = 1;
437 xp->special_running = 0;
438 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
439 "%s: @ line %d", __func__, __LINE__);
440 if (saq) {
441 pmcs_release_scratch(pwp);
442 }
443 return (-1);
444 }
445 SATAcopy(sp, rp, 18);
446 }
447 break;
448 case SCMD_START_STOP:
449 /* Check for illegal bits */
450 if ((pkt->pkt_cdbp[1] & 0xfe) || pkt->pkt_cdbp[2] ||
451 (pkt->pkt_cdbp[3] & 0xf0) || (pkt->pkt_cdbp[4] & 0x08) ||
452 pkt->pkt_cdbp[5]) {
453 status = STATUS_CHECK;
454 asc = 0x24; /* invalid field in cdb */
455 break;
456 }
457 break;
458 case SCMD_SYNCHRONIZE_CACHE:
459 /* Check for illegal bits */
460 if ((pkt->pkt_cdbp[1] & 0xf8) || (pkt->pkt_cdbp[6] & 0xe0) ||
461 pkt->pkt_cdbp[9]) {
462 status = STATUS_CHECK;
463 asc = 0x24; /* invalid field in cdb */
464 break;
465 }
466 break;
467 case SCMD_TEST_UNIT_READY:
468 /* Check for illegal bits */
469 if (pkt->pkt_cdbp[1] || pkt->pkt_cdbp[2] || pkt->pkt_cdbp[3] ||
470 pkt->pkt_cdbp[4] || pkt->pkt_cdbp[5]) {
471 status = STATUS_CHECK;
472 asc = 0x24; /* invalid field in cdb */
473 break;
474 }
475 if (xp->ca) {
476 status = STATUS_CHECK;
477 key = 0x6;
478 asc = 0x28;
479 xp->ca = 0;
480 }
481 break;
482 default:
483 asc = 0x20; /* invalid operation command code */
484 status = STATUS_CHECK;
485 break;
486 }
487 if (status != STATUS_GOOD) {
488 bzero(rp, 18);
489 rp[0] = 0xf0;
490 rp[2] = key;
491 rp[12] = asc;
492 rp[13] = ascq;
493 pmcs_latch_status(pwp, sp, status, rp, 18, pptr->path);
494 } else {
495 pmcs_latch_status(pwp, sp, status, NULL, 0, pptr->path);
496 }
497
498 out:
499 STAILQ_REMOVE_HEAD(&xp->sq, cmd_next);
500 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
501 "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
502 __func__, (void *)pkt, xp->target_num, pkt->pkt_reason,
503 pkt->pkt_state, pkt->pkt_resid, status);
504
505 if (saq) {
506 pmcs_release_scratch(pwp);
507 }
508
509 if (xp->draining) {
510 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
511 "%s: waking up drain waiters", __func__);
512 cv_signal(&pwp->drain_cv);
513 }
514
515 mutex_exit(&xp->statlock);
516 mutex_enter(&pwp->cq_lock);
517 STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
518 PMCS_CQ_RUN_LOCKED(pwp);
519 mutex_exit(&pwp->cq_lock);
520 mutex_enter(&xp->statlock);
521 xp->special_running = 0;
522 return (0);
523 }
524
525 /*
526 * Run all special commands queued up for a SATA device.
527 * We're only called if the caller knows we have work to do.
528 *
529 * We can't run them if things are still active for the device,
530 * return saying we didn't run anything.
531 *
532 * When we finish, wake up anyone waiting for active commands
533 * to go to zero.
534 *
535 * Called with PHY lock and xp statlock held.
536 */
537 int
pmcs_run_sata_special(pmcs_hw_t * pwp,pmcs_xscsi_t * xp)538 pmcs_run_sata_special(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
539 {
540 while (!STAILQ_EMPTY(&xp->sq)) {
541 if (pmcs_sata_special_work(pwp, xp)) {
542 return (-1);
543 }
544 }
545 return (0);
546 }
547
548 /*
549 * Search for SATA special commands to run and run them.
550 * If we succeed in running the special command(s), kick
551 * the normal commands into operation again. Call completion
552 * for any commands that were completed while we were here.
553 *
554 * Called unlocked.
555 */
556 void
pmcs_sata_work(pmcs_hw_t * pwp)557 pmcs_sata_work(pmcs_hw_t *pwp)
558 {
559 pmcs_xscsi_t *xp;
560 int spinagain = 0;
561 uint16_t target;
562
563 for (target = 0; target < pwp->max_dev; target++) {
564 xp = pwp->targets[target];
565 if ((xp == NULL) || (xp->phy == NULL)) {
566 continue;
567 }
568 pmcs_lock_phy(xp->phy);
569 mutex_enter(&xp->statlock);
570 if (STAILQ_EMPTY(&xp->sq)) {
571 mutex_exit(&xp->statlock);
572 pmcs_unlock_phy(xp->phy);
573 continue;
574 }
575 if (xp->actv_cnt) {
576 xp->special_needed = 1;
577 pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, xp,
578 "%s: deferring until drained", __func__);
579 spinagain++;
580 } else {
581 if (pmcs_run_sata_special(pwp, xp)) {
582 spinagain++;
583 }
584 }
585 mutex_exit(&xp->statlock);
586 pmcs_unlock_phy(xp->phy);
587 }
588
589 if (spinagain) {
590 SCHEDULE_WORK(pwp, PMCS_WORK_SATA_RUN);
591 } else {
592 SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
593 }
594
595 /*
596 * Run completion on any commands ready for it.
597 */
598 PMCS_CQ_RUN(pwp);
599 }
600
601 /*
602 * Called with PHY lock held and scratch acquired
603 */
604 int
pmcs_sata_identify(pmcs_hw_t * pwp,pmcs_phy_t * pptr)605 pmcs_sata_identify(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
606 {
607 fis_t fis;
608 fis[0] = (IDENTIFY_DEVICE << 16) | (1 << 15) | FIS_REG_H2DEV;
609 fis[1] = 0;
610 fis[2] = 0;
611 fis[3] = 0;
612 fis[4] = 0;
613 return (pmcs_run_sata_cmd(pwp, pptr, fis, SATA_PROTOCOL_PIO,
614 PMCIN_DATADIR_2_INI, sizeof (ata_identify_t)));
615 }
616
617 /*
618 * Called with PHY lock held and scratch held
619 */
620 int
pmcs_run_sata_cmd(pmcs_hw_t * pwp,pmcs_phy_t * pptr,fis_t fis,uint32_t mode,uint32_t ddir,uint32_t dlen)621 pmcs_run_sata_cmd(pmcs_hw_t *pwp, pmcs_phy_t *pptr, fis_t fis, uint32_t mode,
622 uint32_t ddir, uint32_t dlen)
623 {
624 struct pmcwork *pwrk;
625 uint32_t *ptr, msg[PMCS_MSG_SIZE];
626 uint32_t iq, htag, status;
627 int i, result = 0;
628
629 pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
630 if (pwrk == NULL) {
631 return (ENOMEM);
632 }
633
634 msg[0] = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE,
635 PMCIN_SATA_HOST_IO_START));
636 htag = pwrk->htag;
637 pwrk->arg = msg;
638 pwrk->dtype = SATA;
639 msg[1] = LE_32(pwrk->htag);
640 msg[2] = LE_32(pptr->device_id);
641 msg[3] = LE_32(dlen);
642 msg[4] = LE_32(mode | ddir);
643 if (dlen) {
644 if (ddir == PMCIN_DATADIR_2_DEV) {
645 if (ddi_dma_sync(pwp->cip_handles, 0, 0,
646 DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) {
647 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
648 "Condition check failed at %s():%d",
649 __func__, __LINE__);
650 }
651 }
652 msg[12] = LE_32(DWORD0(pwp->scratch_dma));
653 msg[13] = LE_32(DWORD1(pwp->scratch_dma));
654 msg[14] = LE_32(dlen);
655 msg[15] = 0;
656 } else {
657 msg[12] = 0;
658 msg[13] = 0;
659 msg[14] = 0;
660 msg[15] = 0;
661 }
662 for (i = 0; i < 5; i++) {
663 msg[5+i] = LE_32(fis[i]);
664 }
665 msg[10] = 0;
666 msg[11] = 0;
667 GET_IO_IQ_ENTRY(pwp, ptr, pptr->device_id, iq);
668 if (ptr == NULL) {
669 pmcs_pwork(pwp, pwrk);
670 return (ENOMEM);
671 }
672 COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
673 pwrk->state = PMCS_WORK_STATE_ONCHIP;
674 INC_IQ_ENTRY(pwp, iq);
675
676 pmcs_unlock_phy(pptr);
677 WAIT_FOR(pwrk, 1000, result);
678 pmcs_pwork(pwp, pwrk);
679 pmcs_lock_phy(pptr);
680
681 if (result) {
682 pmcs_timed_out(pwp, htag, __func__);
683 if (pmcs_abort(pwp, pptr, htag, 0, 1)) {
684 pptr->abort_pending = 1;
685 SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
686 }
687 return (ETIMEDOUT);
688 }
689
690 status = LE_32(msg[2]);
691
692 if (status != PMCOUT_STATUS_OK) {
693 if (status == PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY) {
694 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
695 "%s: Potential affiliation active on 0x%" PRIx64,
696 __func__, pmcs_barray2wwn(pptr->sas_address));
697 } else {
698 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, pptr->target,
699 "%s: SATA I/O returned with IOMB status 0x%x",
700 __func__, status);
701 }
702 return (EIO);
703 }
704
705 if (LE_32(ptr[3]) != 0) {
706 size_t j, amt = LE_32(ptr[3]);
707 if (amt > sizeof (fis_t)) {
708 amt = sizeof (fis_t);
709 }
710 amt >>= 2;
711 for (j = 0; j < amt; j++) {
712 fis[j] = LE_32(msg[4 + j]);
713 }
714 }
715 if (dlen && ddir == PMCIN_DATADIR_2_INI) {
716 if (ddi_dma_sync(pwp->cip_handles, 0, 0,
717 DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) {
718 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
719 "Condition check failed at %s():%d",
720 __func__, __LINE__);
721 }
722 }
723 return (0);
724 }
725