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