1 -/* $NetBSD: isp_target.c,v 1.32 2008/06/30 00:50:30 perry Exp $ */
3 * Copyright (c) 1997-2008 by Matthew Jacob
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Alternatively, this software may be distributed under the terms of the
30 * the GNU Public License ("GPL") with platforms where the prevalant license
31 * is the GNU Public License:
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of The Version 2 GNU General Public License as published
35 * by the Free Software Foundation.
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
42 * You should have received a copy of the GNU General Public License
43 * along with this program; if not, write to the Free Software
44 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
50 * Menlo Park, CA 94025
56 * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
59 * Bug fixes gratefully acknowledged from:
60 * Oded Kedem <oded@kashya.com>
63 * Include header file appropriate for platform we're building on.
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: isp_target.c,v 1.32 2008/06/30 00:50:30 perry Exp $");
69 #include <dev/ic/isp_netbsd.h>
72 #include <sys/cdefs.h>
73 __FBSDID("$FreeBSD:$");
74 #include <dev/isp/isp_freebsd.h>
77 #include <dev/ic/isp_openbsd.h>
80 #include "isp_linux.h"
83 #ifdef ISP_TARGET_MODE
84 static const char atiocope
[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset on bus %d";
85 static const char atior
[] = "ATIO returned on for lun %d on from loopid %d because a Bus Reset occurred on bus %d";
86 static const char rqo
[] = "%s: Request Queue Overflow";
88 static void isp_got_msg(ispsoftc_t
*, in_entry_t
*);
89 static void isp_got_msg_fc(ispsoftc_t
*, in_fcentry_t
*);
90 static void isp_got_tmf_24xx(ispsoftc_t
*, at7_entry_t
*);
91 static void isp_handle_atio(ispsoftc_t
*, at_entry_t
*);
92 static void isp_handle_atio2(ispsoftc_t
*, at2_entry_t
*);
93 static void isp_handle_ctio(ispsoftc_t
*, ct_entry_t
*);
94 static void isp_handle_ctio2(ispsoftc_t
*, ct2_entry_t
*);
95 static void isp_handle_ctio7(ispsoftc_t
*, ct7_entry_t
*);
96 static void isp_handle_24xx_inotify(ispsoftc_t
*, in_fcentry_24xx_t
*);
99 * The Qlogic driver gets an interrupt to look at response queue entries.
100 * Some of these are status completions for initiatior mode commands, but
101 * if target mode is enabled, we get a whole wad of response queue entries
102 * to be handled here.
104 * Basically the split into 3 main groups: Lun Enable/Modification responses,
105 * SCSI Command processing, and Immediate Notification events.
107 * You start by writing a request queue entry to enable target mode (and
108 * establish some resource limitations which you can modify later).
109 * The f/w responds with a LUN ENABLE or LUN MODIFY response with
110 * the status of this action. If the enable was successful, you can expect...
112 * Response queue entries with SCSI commands encapsulate show up in an ATIO
113 * (Accept Target IO) type- sometimes with enough info to stop the command at
114 * this level. Ultimately the driver has to feed back to the f/w's request
115 * queue a sequence of CTIOs (continue target I/O) that describe data to
116 * be moved and/or status to be sent) and finally finishing with sending
117 * to the f/w's response queue an ATIO which then completes the handshake
118 * with the f/w for that command. There's a lot of variations on this theme,
119 * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
120 * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
123 * The third group that can show up in the response queue are Immediate
124 * Notification events. These include things like notifications of SCSI bus
125 * resets, or Bus Device Reset messages or other messages received. This
126 * a classic oddbins area. It can get a little weird because you then turn
127 * around and acknowledge the Immediate Notify by writing an entry onto the
128 * request queue and then the f/w turns around and gives you an acknowledgement
129 * to *your* acknowledgement on the response queue (the idea being to let
130 * the f/w tell you when the event is *really* over I guess).
136 * A new response queue entry has arrived. The interrupt service code
137 * has already swizzled it into the platform dependent from canonical form.
139 * Because of the way this driver is designed, unfortunately most of the
140 * actual synchronization work has to be done in the platform specific
141 * code- we have no synchroniation primitives in the common code.
145 isp_target_notify(ispsoftc_t
*isp
, void *vptr
, uint32_t *optrp
)
152 at2e_entry_t
*at2eiop
;
156 ct2e_entry_t
*ct2eiop
;
160 in_fcentry_t
*inot_fcp
;
161 in_fcentry_e_t
*inote_fcp
;
162 in_fcentry_24xx_t
*inot_24xx
;
164 na_fcentry_t
*nack_fcp
;
165 na_fcentry_e_t
*nacke_fcp
;
166 na_fcentry_24xx_t
*nack_24xx
;
169 abts_rsp_t
*abts_rsp
;
172 #define atiop unp.atiop
173 #define at2iop unp.at2iop
174 #define at2eiop unp.at2eiop
175 #define at7iop unp.at7iop
176 #define ctiop unp.ctiop
177 #define ct2iop unp.ct2iop
178 #define ct2eiop unp.ct2eiop
179 #define ct7iop unp.ct7iop
180 #define lunenp unp.lunenp
181 #define inotp unp.inotp
182 #define inot_fcp unp.inot_fcp
183 #define inote_fcp unp.inote_fcp
184 #define inot_24xx unp.inot_24xx
185 #define nackp unp.nackp
186 #define nack_fcp unp.nack_fcp
187 #define nacke_fcp unp.nacke_fcp
188 #define nack_24xx unp.nack_24xx
189 #define abts unp.abts
190 #define abts_rsp unp.abts_rsp
194 uint8_t local
[QENTRY_LEN
];
196 int bus
, type
, level
, rval
= 1;
199 type
= isp_get_response_type(isp
, (isphdr_t
*)vptr
);
202 ISP_TDQE(isp
, "isp_target_notify", (int) *optrp
, vptr
);
209 isp_get_atio7(isp
, at7iop
, (at7_entry_t
*) local
);
210 at7iop
= (at7_entry_t
*) local
;
212 * Check for and do something with commands whose
213 * IULEN extends past a single queue entry.
215 len
= at7iop
->at_ta_len
& 0xfffff;
216 if (len
> (QENTRY_LEN
- 8)) {
217 len
-= (QENTRY_LEN
- 8);
218 isp_prt(isp
, ISP_LOGINFO
, "long IU length (%d) ignored", len
);
220 *optrp
= ISP_NXT_QENTRY(*optrp
, RESULT_QUEUE_LEN(isp
));
225 * Check for a task management function
227 if (at7iop
->at_cmnd
.fcp_cmnd_task_management
) {
228 isp_got_tmf_24xx(isp
, at7iop
);
232 * Just go straight to outer layer for this one.
234 isp_async(isp
, ISPASYNC_TARGET_ACTION
, local
);
236 isp_get_atio(isp
, atiop
, (at_entry_t
*) local
);
237 isp_handle_atio(isp
, (at_entry_t
*) local
);
242 isp_get_ctio(isp
, ctiop
, (ct_entry_t
*) local
);
243 isp_handle_ctio(isp
, (ct_entry_t
*) local
);
247 if (ISP_CAP_2KLOGIN(isp
)) {
248 isp_get_atio2e(isp
, at2eiop
, (at2e_entry_t
*) local
);
250 isp_get_atio2(isp
, at2iop
, (at2_entry_t
*) local
);
252 isp_handle_atio2(isp
, (at2_entry_t
*) local
);
257 if (ISP_CAP_2KLOGIN(isp
)) {
258 isp_get_ctio2e(isp
, ct2eiop
, (ct2e_entry_t
*) local
);
260 isp_get_ctio2(isp
, ct2iop
, (ct2_entry_t
*) local
);
262 isp_handle_ctio2(isp
, (ct2_entry_t
*) local
);
266 isp_get_ctio7(isp
, ct7iop
, (ct7_entry_t
*) local
);
267 isp_handle_ctio7(isp
, (ct7_entry_t
*) local
);
270 case RQSTYPE_ENABLE_LUN
:
271 case RQSTYPE_MODIFY_LUN
:
272 isp_get_enable_lun(isp
, lunenp
, (lun_entry_t
*) local
);
273 isp_async(isp
, ISPASYNC_TARGET_ACTION
, local
);
279 isp_get_notify_24xx(isp
, inot_24xx
, (in_fcentry_24xx_t
*)local
);
280 inot_24xx
= (in_fcentry_24xx_t
*) local
;
281 isp_handle_24xx_inotify(isp
, inot_24xx
);
285 if (ISP_CAP_2KLOGIN(isp
)) {
286 in_fcentry_e_t
*ecp
= (in_fcentry_e_t
*)local
;
287 isp_get_notify_fc_e(isp
, inote_fcp
, ecp
);
289 status
= ecp
->in_status
;
290 seqid
= ecp
->in_seqid
;
292 in_fcentry_t
*fcp
= (in_fcentry_t
*)local
;
293 isp_get_notify_fc(isp
, inot_fcp
, fcp
);
295 status
= fcp
->in_status
;
296 seqid
= fcp
->in_seqid
;
299 in_entry_t
*inp
= (in_entry_t
*)local
;
300 isp_get_notify(isp
, inotp
, inp
);
301 status
= inp
->in_status
& 0xff;
302 seqid
= inp
->in_seqid
;
304 if (IS_DUALBUS(isp
)) {
305 bus
= GET_BUS_VAL(inp
->in_iid
);
306 SET_BUS_VAL(inp
->in_iid
, 0);
310 isp_prt(isp
, ISP_LOGTDEBUG0
, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus
, status
, seqid
);
313 case IN_MSG_RECEIVED
:
314 case IN_IDE_RECEIVED
:
316 isp_got_msg_fc(isp
, (in_fcentry_t
*)local
);
318 isp_got_msg(isp
, (in_entry_t
*)local
);
321 case IN_RSRC_UNAVAIL
:
322 isp_prt(isp
, ISP_LOGINFO
, "Firmware out of ATIOs");
323 (void) isp_notify_ack(isp
, local
);
327 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
329 notify
.nt_wwn
= INI_ANY
;
330 notify
.nt_tgt
= TGT_ANY
;
331 notify
.nt_nphdl
= iid
;
332 notify
.nt_sid
= PORT_ANY
;
333 notify
.nt_did
= PORT_ANY
;
334 notify
.nt_lun
= LUN_ANY
;
335 notify
.nt_tagval
= TAG_ANY
;
336 notify
.nt_tagval
|= (((uint64_t)(isp
->isp_serno
++)) << 32);
337 notify
.nt_ncode
= NT_BUS_RESET
;
338 notify
.nt_need_ack
= 1;
339 notify
.nt_lreserved
= local
;
340 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
344 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
346 notify
.nt_wwn
= INI_ANY
;
347 notify
.nt_nphdl
= iid
;
348 notify
.nt_sid
= PORT_ANY
;
349 notify
.nt_did
= PORT_ANY
;
350 notify
.nt_ncode
= NT_LOGOUT
;
351 notify
.nt_need_ack
= 1;
352 notify
.nt_lreserved
= local
;
353 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
357 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
359 notify
.nt_wwn
= INI_ANY
;
360 notify
.nt_nphdl
= iid
;
361 notify
.nt_sid
= PORT_ANY
;
362 notify
.nt_did
= PORT_ANY
;
363 notify
.nt_ncode
= NT_ABORT_TASK
;
364 notify
.nt_need_ack
= 1;
365 notify
.nt_lreserved
= local
;
366 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
370 isp_prt(isp
, ISP_LOGTINFO
, "%s: all ports logged out", __func__
);
371 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
373 notify
.nt_wwn
= INI_ANY
;
374 notify
.nt_nphdl
= NIL_HANDLE
;
375 notify
.nt_sid
= PORT_ANY
;
376 notify
.nt_did
= PORT_ANY
;
377 notify
.nt_ncode
= NT_GLOBAL_LOGOUT
;
378 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
379 (void) isp_notify_ack(isp
, local
);
382 case IN_PORT_CHANGED
:
383 isp_prt(isp
, ISP_LOGTINFO
, "%s: port changed", __func__
);
384 (void) isp_notify_ack(isp
, local
);
388 ISP_SNPRINTF(local
, sizeof local
, "%s: unknown status to RQSTYPE_NOTIFY (0x%x)", __func__
, status
);
389 isp_print_bytes(isp
, local
, QENTRY_LEN
, vptr
);
390 (void) isp_notify_ack(isp
, local
);
395 case RQSTYPE_NOTIFY_ACK
:
397 * The ISP is acknowledging our acknowledgement of an
398 * Immediate Notify entry for some asynchronous event.
401 isp_get_notify_ack_24xx(isp
, nack_24xx
, (na_fcentry_24xx_t
*) local
);
402 nack_24xx
= (na_fcentry_24xx_t
*) local
;
403 if (nack_24xx
->na_status
!= NA_OK
) {
406 level
= ISP_LOGTDEBUG1
;
408 isp_prt(isp
, level
, "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", nack_24xx
->na_status
, nack_24xx
->na_status_subcode
, nack_24xx
->na_rxid
);
409 } else if (IS_FC(isp
)) {
410 if (ISP_CAP_2KLOGIN(isp
)) {
411 isp_get_notify_ack_fc_e(isp
, nacke_fcp
, (na_fcentry_e_t
*)local
);
413 isp_get_notify_ack_fc(isp
, nack_fcp
, (na_fcentry_t
*)local
);
415 nack_fcp
= (na_fcentry_t
*)local
;
416 if (nack_fcp
->na_status
!= NA_OK
) {
419 level
= ISP_LOGTDEBUG1
;
421 isp_prt(isp
, level
, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp
->na_status
, nack_fcp
->na_seqid
);
423 isp_get_notify_ack(isp
, nackp
, (na_entry_t
*)local
);
424 nackp
= (na_entry_t
*)local
;
425 if (nackp
->na_status
!= NA_OK
) {
428 level
= ISP_LOGTDEBUG1
;
430 isp_prt(isp
, level
, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp
->na_event
, nackp
->na_status
, nackp
->na_seqid
);
434 case RQSTYPE_ABTS_RCVD
:
435 isp_get_abts(isp
, abts
, (abts_t
*)local
);
436 isp_async(isp
, ISPASYNC_TARGET_ACTION
, &local
);
438 case RQSTYPE_ABTS_RSP
:
439 isp_get_abts_rsp(isp
, abts_rsp
, (abts_rsp_t
*)local
);
440 abts_rsp
= (abts_rsp_t
*) local
;
441 if (abts_rsp
->abts_rsp_status
) {
444 level
= ISP_LOGTDEBUG0
;
446 isp_prt(isp
, level
, "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", abts_rsp
->abts_rsp_rxid_task
, abts_rsp
->abts_rsp_status
,
447 abts_rsp
->abts_rsp_payload
.rsp
.subcode1
, abts_rsp
->abts_rsp_payload
.rsp
.subcode2
);
450 isp_prt(isp
, ISP_LOGERR
, "%s: unknown entry type 0x%x", __func__
, type
);
480 * Toggle (on/off) target mode for bus/target/lun.
482 * The caller has checked for overlap and legality.
484 * Note that not all of bus, target or lun can be paid attention to.
485 * Note also that this action will not be complete until the f/w writes
486 * a response entry. The caller is responsible for synchronizing with this.
489 isp_lun_cmd(ispsoftc_t
*isp
, int cmd
, int bus
, int lun
, int cmd_cnt
, int inot_cnt
)
494 ISP_MEMZERO(&el
, sizeof (el
));
495 if (IS_DUALBUS(isp
)) {
496 el
.le_rsvd
= (bus
& 0x1) << 7;
498 el
.le_cmd_count
= cmd_cnt
;
499 el
.le_in_count
= inot_cnt
;
500 if (cmd
== RQSTYPE_ENABLE_LUN
) {
502 el
.le_flags
= LUN_TQAE
|LUN_DISAD
;
506 } else if (cmd
== -RQSTYPE_ENABLE_LUN
) {
507 cmd
= RQSTYPE_ENABLE_LUN
;
510 } else if (cmd
== -RQSTYPE_MODIFY_LUN
) {
511 cmd
= RQSTYPE_MODIFY_LUN
;
512 el
.le_ops
= LUN_CCDECR
| LUN_INDECR
;
514 el
.le_ops
= LUN_CCINCR
| LUN_ININCR
;
516 el
.le_header
.rqs_entry_type
= cmd
;
517 el
.le_header
.rqs_entry_count
= 1;
519 el
.le_tgt
= SDPARAM(isp
, bus
)->isp_initiator_id
;
521 } else if (ISP_CAP_SCCFW(isp
) == 0) {
526 outp
= isp_getrqentry(isp
);
528 isp_prt(isp
, ISP_LOGERR
, rqo
, __func__
);
531 isp_put_enable_lun(isp
, &el
, outp
);
532 ISP_TDQE(isp
, "isp_lun_cmd", isp
->isp_reqidx
, &el
);
533 ISP_SYNC_REQUEST(isp
);
538 isp_target_put_entry(ispsoftc_t
*isp
, void *ap
)
541 uint8_t etype
= ((isphdr_t
*) ap
)->rqs_entry_type
;
543 outp
= isp_getrqentry(isp
);
545 isp_prt(isp
, ISP_LOGWARN
, rqo
, __func__
);
550 isp_put_atio(isp
, (at_entry_t
*) ap
, (at_entry_t
*) outp
);
553 if (ISP_CAP_2KLOGIN(isp
)) {
554 isp_put_atio2e(isp
, (at2e_entry_t
*) ap
, (at2e_entry_t
*) outp
);
556 isp_put_atio2(isp
, (at2_entry_t
*) ap
, (at2_entry_t
*) outp
);
560 isp_put_ctio(isp
, (ct_entry_t
*) ap
, (ct_entry_t
*) outp
);
563 if (ISP_CAP_2KLOGIN(isp
)) {
564 isp_put_ctio2e(isp
, (ct2e_entry_t
*) ap
, (ct2e_entry_t
*) outp
);
566 isp_put_ctio2(isp
, (ct2_entry_t
*) ap
, (ct2_entry_t
*) outp
);
570 isp_put_ctio7(isp
, (ct7_entry_t
*) ap
, (ct7_entry_t
*) outp
);
573 isp_prt(isp
, ISP_LOGERR
, "%s: Unknown type 0x%x", __func__
, etype
);
576 ISP_TDQE(isp
, __func__
, isp
->isp_reqidx
, ap
);
577 ISP_SYNC_REQUEST(isp
);
582 isp_target_put_atio(ispsoftc_t
*isp
, void *arg
)
587 at2e_entry_t _atio2e
;
590 ISP_MEMZERO(&atun
, sizeof atun
);
592 at2_entry_t
*aep
= arg
;
593 atun
._atio2
.at_header
.rqs_entry_type
= RQSTYPE_ATIO2
;
594 atun
._atio2
.at_header
.rqs_entry_count
= 1;
595 if (ISP_CAP_SCCFW(isp
)) {
596 atun
._atio2
.at_scclun
= aep
->at_scclun
;
598 atun
._atio2
.at_lun
= (uint8_t) aep
->at_lun
;
600 if (ISP_CAP_2KLOGIN(isp
)) {
601 atun
._atio2e
.at_iid
= ((at2e_entry_t
*)aep
)->at_iid
;
603 atun
._atio2
.at_iid
= aep
->at_iid
;
605 atun
._atio2
.at_rxid
= aep
->at_rxid
;
606 atun
._atio2
.at_status
= CT_OK
;
608 at_entry_t
*aep
= arg
;
609 atun
._atio
.at_header
.rqs_entry_type
= RQSTYPE_ATIO
;
610 atun
._atio
.at_header
.rqs_entry_count
= 1;
611 atun
._atio
.at_handle
= aep
->at_handle
;
612 atun
._atio
.at_iid
= aep
->at_iid
;
613 atun
._atio
.at_tgt
= aep
->at_tgt
;
614 atun
._atio
.at_lun
= aep
->at_lun
;
615 atun
._atio
.at_tag_type
= aep
->at_tag_type
;
616 atun
._atio
.at_tag_val
= aep
->at_tag_val
;
617 atun
._atio
.at_status
= (aep
->at_flags
& AT_TQAE
);
618 atun
._atio
.at_status
|= CT_OK
;
620 return (isp_target_put_entry(isp
, &atun
));
624 * Command completion- both for handling cases of no resources or
625 * no blackhole driver, or other cases where we have to, inline,
626 * finish the command sanely, or for normal command completion.
628 * The 'completion' code value has the scsi status byte in the low 8 bits.
629 * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have
630 * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC
633 * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
634 * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
636 * For both parallel && fibre channel, we use the feature that does
637 * an automatic resource autoreplenish so we don't have then later do
638 * put of an atio to replenish the f/w's resource count.
642 isp_endcmd(ispsoftc_t
*isp
, ...)
649 ct2e_entry_t _ctio2e
;
654 ISP_MEMZERO(&un
, sizeof un
);
659 ct7_entry_t
*cto
= &un
._ctio7
;
662 aep
= va_arg(ap
, at7_entry_t
*);
663 nphdl
= va_arg(ap
, int);
665 * Note that vpidx may equal 0xff (unknown) here
667 vpidx
= va_arg(ap
, int);
668 code
= va_arg(ap
, uint32_t);
669 hdl
= va_arg(ap
, uint32_t);
671 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: [RX_ID 0x%x] chan %d code %x", __func__
, aep
->at_rxid
, vpidx
, code
);
674 cto
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO7
;
675 cto
->ct_header
.rqs_entry_count
= 1;
676 cto
->ct_nphdl
= nphdl
;
677 cto
->ct_rxid
= aep
->at_rxid
;
678 cto
->ct_iid_lo
= (aep
->at_hdr
.s_id
[1] << 8) | aep
->at_hdr
.s_id
[2];
679 cto
->ct_iid_hi
= aep
->at_hdr
.s_id
[0];
680 cto
->ct_oxid
= aep
->at_hdr
.ox_id
;
681 cto
->ct_scsi_status
= sts
;
682 cto
->ct_vpidx
= vpidx
;
683 cto
->ct_flags
= CT7_NOACK
;
684 if (code
& ECMD_TERMINATE
) {
685 cto
->ct_flags
|= CT7_TERMINATE
;
686 } else if (code
& ECMD_SVALID
) {
687 cto
->ct_flags
|= CT7_FLAG_MODE1
| CT7_SENDSTATUS
;
688 cto
->ct_scsi_status
|= (FCP_SNSLEN_VALID
<< 8);
689 cto
->rsp
.m1
.ct_resplen
= cto
->ct_senselen
= min(16, MAXRESPLEN_24XX
);
690 ISP_MEMZERO(cto
->rsp
.m1
.ct_resp
, sizeof (cto
->rsp
.m1
.ct_resp
));
691 cto
->rsp
.m1
.ct_resp
[0] = 0xf0;
692 cto
->rsp
.m1
.ct_resp
[2] = (code
>> 12) & 0xf;
693 cto
->rsp
.m1
.ct_resp
[7] = 8;
694 cto
->rsp
.m1
.ct_resp
[12] = (code
>> 24) & 0xff;
695 cto
->rsp
.m1
.ct_resp
[13] = (code
>> 16) & 0xff;
697 cto
->ct_flags
|= CT7_FLAG_MODE1
| CT7_SENDSTATUS
;
699 if (aep
->at_cmnd
.cdb_dl
.sf
.fcp_cmnd_dl
) {
700 cto
->ct_resid
= aep
->at_cmnd
.cdb_dl
.sf
.fcp_cmnd_dl
;
701 if (cto
->ct_resid
< 0) {
702 cto
->ct_scsi_status
|= (FCP_RESID_OVERFLOW
<< 8);
703 } else if (cto
->ct_resid
> 0) {
704 cto
->ct_scsi_status
|= (FCP_RESID_UNDERFLOW
<< 8);
707 cto
->ct_syshandle
= hdl
;
708 } else if (IS_FC(isp
)) {
710 ct2_entry_t
*cto
= &un
._ctio2
;
713 aep
= va_arg(ap
, at2_entry_t
*);
714 code
= va_arg(ap
, uint32_t);
715 hdl
= va_arg(ap
, uint32_t);
718 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: [RX_ID 0x%x] code %x", __func__
, aep
->at_rxid
, code
);
721 cto
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO2
;
722 cto
->ct_header
.rqs_entry_count
= 1;
723 if (ISP_CAP_SCCFW(isp
) == 0) {
724 cto
->ct_lun
= aep
->at_lun
;
726 if (ISP_CAP_2KLOGIN(isp
)) {
727 un
._ctio2e
.ct_iid
= ((at2e_entry_t
*)aep
)->at_iid
;
729 cto
->ct_iid
= aep
->at_iid
;
731 cto
->ct_rxid
= aep
->at_rxid
;
732 cto
->rsp
.m1
.ct_scsi_status
= sts
;
733 cto
->ct_flags
= CT2_SENDSTATUS
| CT2_NO_DATA
| CT2_FLAG_MODE1
;
735 cto
->ct_flags
|= CT2_CCINCR
;
737 if (aep
->at_datalen
) {
738 cto
->ct_resid
= aep
->at_datalen
;
739 cto
->rsp
.m1
.ct_scsi_status
|= CT2_DATA_UNDER
;
741 if (sts
== SCSI_CHECK
&& (code
& ECMD_SVALID
)) {
742 cto
->rsp
.m1
.ct_resp
[0] = 0xf0;
743 cto
->rsp
.m1
.ct_resp
[2] = (code
>> 12) & 0xf;
744 cto
->rsp
.m1
.ct_resp
[7] = 8;
745 cto
->rsp
.m1
.ct_resp
[12] = (code
>> 24) & 0xff;
746 cto
->rsp
.m1
.ct_resp
[13] = (code
>> 16) & 0xff;
747 cto
->rsp
.m1
.ct_senselen
= 16;
748 cto
->rsp
.m1
.ct_scsi_status
|= CT2_SNSLEN_VALID
;
750 cto
->ct_syshandle
= hdl
;
753 ct_entry_t
*cto
= &un
._ctio
;
756 aep
= va_arg(ap
, at_entry_t
*);
757 code
= va_arg(ap
, uint32_t);
758 hdl
= va_arg(ap
, uint32_t);
760 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: [IID %d] code %x", __func__
, aep
->at_iid
, code
);
763 cto
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO
;
764 cto
->ct_header
.rqs_entry_count
= 1;
765 cto
->ct_fwhandle
= aep
->at_handle
;
766 cto
->ct_iid
= aep
->at_iid
;
767 cto
->ct_tgt
= aep
->at_tgt
;
768 cto
->ct_lun
= aep
->at_lun
;
769 cto
->ct_tag_type
= aep
->at_tag_type
;
770 cto
->ct_tag_val
= aep
->at_tag_val
;
771 if (aep
->at_flags
& AT_TQAE
) {
772 cto
->ct_flags
|= CT_TQAE
;
774 cto
->ct_flags
= CT_SENDSTATUS
| CT_NO_DATA
;
776 cto
->ct_flags
|= CT_CCINCR
;
778 cto
->ct_scsi_status
= sts
;
779 cto
->ct_syshandle
= hdl
;
781 return (isp_target_put_entry(isp
, &un
));
785 * These are either broadcast events or specifically CTIO fast completion
789 isp_target_async(ispsoftc_t
*isp
, int bus
, int event
)
793 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
795 notify
.nt_wwn
= INI_ANY
;
796 notify
.nt_nphdl
= NIL_HANDLE
;
797 notify
.nt_sid
= PORT_ANY
;
798 notify
.nt_did
= PORT_ANY
;
799 notify
.nt_tgt
= TGT_ANY
;
800 notify
.nt_channel
= bus
;
801 notify
.nt_lun
= LUN_ANY
;
802 notify
.nt_tagval
= TAG_ANY
;
803 notify
.nt_tagval
|= (((uint64_t)(isp
->isp_serno
++)) << 32);
808 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: LOOP UP", __func__
);
809 notify
.nt_ncode
= NT_LINK_UP
;
810 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
812 case ASYNC_LOOP_DOWN
:
813 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: LOOP DOWN", __func__
);
814 notify
.nt_ncode
= NT_LINK_DOWN
;
815 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
817 case ASYNC_LIP_ERROR
:
819 case ASYNC_LIP_OCCURRED
:
820 case ASYNC_LOOP_RESET
:
821 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: LIP RESET", __func__
);
822 notify
.nt_ncode
= NT_LIP_RESET
;
823 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
825 case ASYNC_BUS_RESET
:
826 case ASYNC_TIMEOUT_RESET
: /* XXX: where does this come from ? */
827 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: BUS RESET", __func__
);
828 notify
.nt_ncode
= NT_BUS_RESET
;
829 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
831 case ASYNC_DEVICE_RESET
:
832 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: DEVICE RESET", __func__
);
833 notify
.nt_ncode
= NT_TARGET_RESET
;
834 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
836 case ASYNC_CTIO_DONE
:
838 uint8_t storage
[QENTRY_LEN
];
839 isp_prt(isp
, ISP_LOGTDEBUG0
, "%s: CTIO DONE", __func__
);
840 memset(storage
, 0, QENTRY_LEN
);
842 ct7_entry_t
*ct
= (ct7_entry_t
*) storage
;
843 ct
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO7
;
844 ct
->ct_nphdl
= CT7_OK
;
845 ct
->ct_syshandle
= bus
;
846 ct
->ct_flags
= CT7_SENDSTATUS
;
847 } else if (IS_FC(isp
)) {
848 /* This should also suffice for 2K login code */
849 ct2_entry_t
*ct
= (ct2_entry_t
*) storage
;
850 ct
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO2
;
851 ct
->ct_status
= CT_OK
;
852 ct
->ct_syshandle
= bus
;
853 ct
->ct_flags
= CT2_SENDSTATUS
|CT2_FASTPOST
;
855 ct_entry_t
*ct
= (ct_entry_t
*) storage
;
856 ct
->ct_header
.rqs_entry_type
= RQSTYPE_CTIO
;
857 ct
->ct_status
= CT_OK
;
858 ct
->ct_fwhandle
= bus
;
859 ct
->ct_flags
= CT_SENDSTATUS
;
861 isp_async(isp
, ISPASYNC_TARGET_ACTION
, storage
);
865 isp_prt(isp
, ISP_LOGERR
, "%s: unknown event 0x%x", __func__
, event
);
866 if (isp
->isp_state
== ISP_RUNSTATE
) {
867 (void) isp_notify_ack(isp
, NULL
);
876 * Process a received message.
877 * The ISP firmware can handle most messages, there are only
878 * a few that we need to deal with:
879 * - abort: clean up the current command
880 * - abort tag and clear queue
884 isp_got_msg(ispsoftc_t
*isp
, in_entry_t
*inp
)
887 uint8_t status
= inp
->in_status
& ~QLTM_SVALID
;
889 ISP_MEMZERO(¬ify
, sizeof (notify
));
891 notify
.nt_wwn
= INI_ANY
;
892 notify
.nt_nphdl
= GET_IID_VAL(inp
->in_iid
);
893 notify
.nt_sid
= PORT_ANY
;
894 notify
.nt_did
= PORT_ANY
;
895 notify
.nt_channel
= GET_BUS_VAL(inp
->in_iid
);
896 notify
.nt_tgt
= inp
->in_tgt
;
897 notify
.nt_lun
= inp
->in_lun
;
898 IN_MAKE_TAGID(notify
.nt_tagval
, inp
);
899 notify
.nt_tagval
|= (((uint64_t)(isp
->isp_serno
++)) << 32);
900 notify
.nt_lreserved
= inp
;
902 if (status
== IN_IDE_RECEIVED
|| status
== IN_MSG_RECEIVED
) {
903 switch (inp
->in_msg
[0]) {
905 notify
.nt_ncode
= NT_ABORT_TASK_SET
;
907 case MSG_BUS_DEV_RESET
:
908 notify
.nt_ncode
= NT_TARGET_RESET
;
911 notify
.nt_ncode
= NT_ABORT_TASK
;
913 case MSG_CLEAR_QUEUE
:
914 notify
.nt_ncode
= NT_CLEAR_TASK_SET
;
916 case MSG_REL_RECOVERY
:
917 notify
.nt_ncode
= NT_CLEAR_ACA
;
919 case MSG_TERM_IO_PROC
:
920 notify
.nt_ncode
= NT_ABORT_TASK
;
923 notify
.nt_ncode
= NT_LUN_RESET
;
926 isp_prt(isp
, ISP_LOGERR
, "%s: unhandled message 0x%x", __func__
, inp
->in_msg
[0]);
927 (void) isp_notify_ack(isp
, inp
);
930 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
932 isp_prt(isp
, ISP_LOGERR
, "%s: unknown immediate notify status 0x%x", __func__
, inp
->in_status
);
933 (void) isp_notify_ack(isp
, inp
);
938 * Synthesize a message from the task management flags in a FCP_CMND_IU.
941 isp_got_msg_fc(ispsoftc_t
*isp
, in_fcentry_t
*inp
)
944 static const char f1
[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
945 static const char f2
[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
946 uint16_t seqid
, loopid
;
948 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
950 notify
.nt_wwn
= INI_ANY
;
951 if (ISP_CAP_2KLOGIN(isp
)) {
952 notify
.nt_nphdl
= ((in_fcentry_e_t
*)inp
)->in_iid
;
953 loopid
= ((in_fcentry_e_t
*)inp
)->in_iid
;
954 seqid
= ((in_fcentry_e_t
*)inp
)->in_seqid
;
956 notify
.nt_nphdl
= inp
->in_iid
;
957 loopid
= inp
->in_iid
;
958 seqid
= inp
->in_seqid
;
960 notify
.nt_sid
= PORT_ANY
;
961 notify
.nt_did
= PORT_ANY
;
963 /* nt_tgt set in outer layers */
964 if (ISP_CAP_SCCFW(isp
)) {
965 notify
.nt_lun
= inp
->in_scclun
;
967 notify
.nt_lun
= inp
->in_lun
;
969 notify
.nt_tagval
= seqid
;
970 notify
.nt_tagval
|= (((uint64_t)(isp
->isp_serno
++)) << 32);
971 notify
.nt_need_ack
= 1;
972 notify
.nt_lreserved
= inp
;
974 if (inp
->in_status
!= IN_MSG_RECEIVED
) {
975 isp_prt(isp
, ISP_LOGINFO
, f2
, "immediate notify status", inp
->in_status
, notify
.nt_lun
, loopid
, inp
->in_task_flags
, inp
->in_seqid
);
976 (void) isp_notify_ack(isp
, inp
);
980 if (inp
->in_task_flags
& TASK_FLAGS_ABORT_TASK_SET
) {
981 isp_prt(isp
, ISP_LOGINFO
, f1
, "ABORT TASK SET", loopid
, notify
.nt_lun
, inp
->in_seqid
);
982 notify
.nt_ncode
= NT_ABORT_TASK_SET
;
983 } else if (inp
->in_task_flags
& TASK_FLAGS_CLEAR_TASK_SET
) {
984 isp_prt(isp
, ISP_LOGINFO
, f1
, "CLEAR TASK SET", loopid
, notify
.nt_lun
, inp
->in_seqid
);
985 notify
.nt_ncode
= NT_CLEAR_TASK_SET
;
986 } else if (inp
->in_task_flags
& TASK_FLAGS_LUN_RESET
) {
987 isp_prt(isp
, ISP_LOGINFO
, f1
, "LUN RESET", loopid
, notify
.nt_lun
, inp
->in_seqid
);
988 notify
.nt_ncode
= NT_LUN_RESET
;
989 } else if (inp
->in_task_flags
& TASK_FLAGS_TARGET_RESET
) {
990 isp_prt(isp
, ISP_LOGINFO
, f1
, "TARGET RESET", loopid
, notify
.nt_lun
, inp
->in_seqid
);
991 notify
.nt_ncode
= NT_TARGET_RESET
;
992 } else if (inp
->in_task_flags
& TASK_FLAGS_CLEAR_ACA
) {
993 isp_prt(isp
, ISP_LOGINFO
, f1
, "CLEAR ACA", loopid
, notify
.nt_lun
, inp
->in_seqid
);
994 notify
.nt_ncode
= NT_CLEAR_ACA
;
996 isp_prt(isp
, ISP_LOGWARN
, f2
, "task flag", inp
->in_status
, notify
.nt_lun
, loopid
, inp
->in_task_flags
, inp
->in_seqid
);
997 (void) isp_notify_ack(isp
, inp
);
1000 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
1004 isp_got_tmf_24xx(ispsoftc_t
*isp
, at7_entry_t
*aep
)
1006 isp_notify_t notify
;
1007 static const char f1
[] = "%s from PortID 0x%06x lun %d seq 0x%08x";
1008 static const char f2
[] = "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x";
1012 ISP_MEMZERO(¬ify
, sizeof (isp_notify_t
));
1013 notify
.nt_hba
= isp
;
1014 notify
.nt_wwn
= INI_ANY
;
1015 notify
.nt_lun
= (aep
->at_cmnd
.fcp_cmnd_lun
[0] << 8) | (aep
->at_cmnd
.fcp_cmnd_lun
[1]);
1016 notify
.nt_tagval
= aep
->at_rxid
;
1017 notify
.nt_tagval
|= (((uint64_t)(isp
->isp_serno
++)) << 32);
1018 notify
.nt_lreserved
= aep
;
1019 sid
= (aep
->at_hdr
.s_id
[0] << 16) | (aep
->at_hdr
.s_id
[1] << 8) | (aep
->at_hdr
.s_id
[2]);
1021 /* Channel has to derived from D_ID */
1022 did
= (aep
->at_hdr
.d_id
[0] << 16) | (aep
->at_hdr
.d_id
[1] << 8) | aep
->at_hdr
.d_id
[2];
1023 for (chan
= 0; chan
< isp
->isp_nchan
; chan
++) {
1024 if (FCPARAM(isp
, chan
)->isp_portid
== did
) {
1028 if (chan
== isp
->isp_nchan
) {
1029 isp_prt(isp
, ISP_LOGWARN
, "%s: D_ID 0x%x not found on any channel", __func__
, did
);
1030 /* just drop on the floor */
1033 notify
.nt_nphdl
= NIL_HANDLE
; /* unknown here */
1034 notify
.nt_sid
= sid
;
1035 notify
.nt_did
= did
;
1036 notify
.nt_channel
= chan
;
1037 if (aep
->at_cmnd
.fcp_cmnd_task_management
& FCP_CMND_TMF_ABORT_TASK_SET
) {
1038 isp_prt(isp
, ISP_LOGINFO
, f1
, "ABORT TASK SET", sid
, notify
.nt_lun
, aep
->at_rxid
);
1039 notify
.nt_ncode
= NT_ABORT_TASK_SET
;
1040 } else if (aep
->at_cmnd
.fcp_cmnd_task_management
& FCP_CMND_TMF_CLEAR_TASK_SET
) {
1041 isp_prt(isp
, ISP_LOGINFO
, f1
, "CLEAR TASK SET", sid
, notify
.nt_lun
, aep
->at_rxid
);
1042 notify
.nt_ncode
= NT_CLEAR_TASK_SET
;
1043 } else if (aep
->at_cmnd
.fcp_cmnd_task_management
& FCP_CMND_TMF_LUN_RESET
) {
1044 isp_prt(isp
, ISP_LOGINFO
, f1
, "LUN RESET", sid
, notify
.nt_lun
, aep
->at_rxid
);
1045 notify
.nt_ncode
= NT_LUN_RESET
;
1046 } else if (aep
->at_cmnd
.fcp_cmnd_task_management
& FCP_CMND_TMF_TGT_RESET
) {
1047 isp_prt(isp
, ISP_LOGINFO
, f1
, "TARGET RESET", sid
, notify
.nt_lun
, aep
->at_rxid
);
1048 notify
.nt_ncode
= NT_TARGET_RESET
;
1049 } else if (aep
->at_cmnd
.fcp_cmnd_task_management
& FCP_CMND_TMF_CLEAR_ACA
) {
1050 isp_prt(isp
, ISP_LOGINFO
, f1
, "CLEAR ACA", sid
, notify
.nt_lun
, aep
->at_rxid
);
1051 notify
.nt_ncode
= NT_CLEAR_ACA
;
1053 isp_prt(isp
, ISP_LOGWARN
, f2
, aep
->at_cmnd
.fcp_cmnd_task_management
, notify
.nt_lun
, sid
, aep
->at_rxid
);
1054 notify
.nt_ncode
= NT_UNKNOWN
;
1057 isp_async(isp
, ISPASYNC_TARGET_NOTIFY
, ¬ify
);
1061 isp_notify_ack(ispsoftc_t
*isp
, void *arg
)
1063 char storage
[QENTRY_LEN
];
1067 * This is in case a Task Management Function ends up here.
1069 if (IS_24XX(isp
) && arg
!= NULL
&& (((isphdr_t
*)arg
)->rqs_entry_type
== RQSTYPE_ATIO
)) {
1070 at7_entry_t
*aep
= arg
;
1071 return (isp_endcmd(isp
, aep
, NIL_HANDLE
, 0, 0, 0));
1074 outp
= isp_getrqentry(isp
);
1076 isp_prt(isp
, ISP_LOGWARN
, rqo
, __func__
);
1080 ISP_MEMZERO(storage
, QENTRY_LEN
);
1083 na_fcentry_24xx_t
*na
= (na_fcentry_24xx_t
*) storage
;
1085 in_fcentry_24xx_t
*in
= arg
;
1086 na
->na_nphdl
= in
->in_nphdl
;
1087 na
->na_flags
= in
->in_flags
& IN24XX_FLAG_PUREX_IOCB
;
1088 na
->na_status
= in
->in_status
;
1089 na
->na_status_subcode
= in
->in_status_subcode
;
1090 na
->na_rxid
= in
->in_rxid
;
1091 na
->na_oxid
= in
->in_oxid
;
1092 na
->na_vpidx
= in
->in_vpidx
;
1093 if (in
->in_status
== IN24XX_SRR_RCVD
) {
1094 na
->na_srr_rxid
= in
->in_srr_rxid
;
1095 na
->na_srr_reloff_hi
= in
->in_srr_reloff_hi
;
1096 na
->na_srr_reloff_lo
= in
->in_srr_reloff_lo
;
1097 na
->na_srr_iu
= in
->in_srr_iu
;
1098 na
->na_srr_flags
= 1;
1099 na
->na_srr_reject_vunique
= 0;
1100 na
->na_srr_reject_explanation
= 1;
1101 na
->na_srr_reject_code
= 1;
1104 na
->na_header
.rqs_entry_type
= RQSTYPE_NOTIFY_ACK
;
1105 na
->na_header
.rqs_entry_count
= 1;
1106 isp_put_notify_24xx_ack(isp
, na
, (na_fcentry_24xx_t
*)outp
);
1107 } else if (IS_FC(isp
)) {
1108 na_fcentry_t
*na
= (na_fcentry_t
*) storage
;
1112 in_fcentry_t
*inp
= arg
;
1113 ISP_MEMCPY(storage
, arg
, sizeof (isphdr_t
));
1114 if (ISP_CAP_2KLOGIN(isp
)) {
1115 ((na_fcentry_e_t
*)na
)->na_iid
= ((in_fcentry_e_t
*)inp
)->in_iid
;
1116 iid
= ((na_fcentry_e_t
*)na
)->na_iid
;
1118 na
->na_iid
= inp
->in_iid
;
1121 na
->na_task_flags
= inp
->in_task_flags
& TASK_FLAGS_RESERVED_MASK
;
1122 na
->na_seqid
= inp
->in_seqid
;
1123 na
->na_flags
= NAFC_RCOUNT
;
1124 na
->na_status
= inp
->in_status
;
1125 if (inp
->in_status
== IN_RESET
) {
1126 na
->na_flags
|= NAFC_RST_CLRD
;
1128 if (inp
->in_status
== IN_MSG_RECEIVED
) {
1129 na
->na_flags
|= NAFC_TVALID
;
1130 na
->na_response
= 0; /* XXX SUCCEEDED XXX */
1133 na
->na_flags
= NAFC_RST_CLRD
;
1135 na
->na_header
.rqs_entry_type
= RQSTYPE_NOTIFY_ACK
;
1136 na
->na_header
.rqs_entry_count
= 1;
1137 if (ISP_CAP_2KLOGIN(isp
)) {
1138 isp_put_notify_ack_fc_e(isp
, (na_fcentry_e_t
*) na
, (na_fcentry_e_t
*)outp
);
1140 isp_put_notify_ack_fc(isp
, na
, (na_fcentry_t
*)outp
);
1142 isp_prt(isp
, ISP_LOGTDEBUG0
, "notify ack loopid %u seqid %x flags %x tflags %x response %x", iid
, na
->na_seqid
,
1143 na
->na_flags
, na
->na_task_flags
, na
->na_response
);
1145 na_entry_t
*na
= (na_entry_t
*) storage
;
1147 in_entry_t
*inp
= arg
;
1148 ISP_MEMCPY(storage
, arg
, sizeof (isphdr_t
));
1149 na
->na_iid
= inp
->in_iid
;
1150 na
->na_lun
= inp
->in_lun
;
1151 na
->na_tgt
= inp
->in_tgt
;
1152 na
->na_seqid
= inp
->in_seqid
;
1153 if (inp
->in_status
== IN_RESET
) {
1154 na
->na_event
= NA_RST_CLRD
;
1157 na
->na_event
= NA_RST_CLRD
;
1159 na
->na_header
.rqs_entry_type
= RQSTYPE_NOTIFY_ACK
;
1160 na
->na_header
.rqs_entry_count
= 1;
1161 isp_put_notify_ack(isp
, na
, (na_entry_t
*)outp
);
1162 isp_prt(isp
, ISP_LOGTDEBUG0
, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na
->na_iid
, na
->na_lun
, na
->na_tgt
, na
->na_seqid
, na
->na_event
);
1164 ISP_TDQE(isp
, "isp_notify_ack", isp
->isp_reqidx
, storage
);
1165 ISP_SYNC_REQUEST(isp
);
1170 isp_acknak_abts(ispsoftc_t
*isp
, void *arg
, int errno
)
1172 char storage
[QENTRY_LEN
];
1176 abts_rsp_t
*rsp
= (abts_rsp_t
*) storage
;
1179 if (!IS_24XX(isp
)) {
1180 isp_prt(isp
, ISP_LOGERR
, "%s: called for non-24XX card", __func__
);
1184 if (abts
->abts_header
.rqs_entry_type
!= RQSTYPE_ABTS_RCVD
) {
1185 isp_prt(isp
, ISP_LOGERR
, "%s: called for non-ABTS entry (0x%x)", __func__
, abts
->abts_header
.rqs_entry_type
);
1189 outp
= isp_getrqentry(isp
);
1191 isp_prt(isp
, ISP_LOGWARN
, rqo
, __func__
);
1195 ISP_MEMCPY(rsp
, abts
, QENTRY_LEN
);
1196 rsp
->abts_rsp_header
.rqs_entry_type
= RQSTYPE_ABTS_RSP
;
1199 * Swap destination and source for response.
1201 rsp
->abts_rsp_r_ctl
= BA_ACC
;
1202 tmpw
= rsp
->abts_rsp_did_lo
;
1203 tmpb
= rsp
->abts_rsp_did_hi
;
1204 rsp
->abts_rsp_did_lo
= rsp
->abts_rsp_sid_lo
;
1205 rsp
->abts_rsp_did_hi
= rsp
->abts_rsp_sid_hi
;
1206 rsp
->abts_rsp_sid_lo
= tmpw
;
1207 rsp
->abts_rsp_sid_hi
= tmpb
;
1209 rsp
->abts_rsp_f_ctl_hi
^= 0x80; /* invert Exchange Context */
1210 rsp
->abts_rsp_f_ctl_hi
&= ~0x7f; /* clear Sequence Initiator and other bits */
1211 rsp
->abts_rsp_f_ctl_hi
|= 0x10; /* abort the whole exchange */
1212 rsp
->abts_rsp_f_ctl_hi
|= 0x8; /* last data frame of sequence */
1213 rsp
->abts_rsp_f_ctl_hi
|= 0x1; /* transfer Sequence Initiative */
1214 rsp
->abts_rsp_f_ctl_lo
= 0;
1217 uint16_t rx_id
, ox_id
;
1219 rx_id
= rsp
->abts_rsp_rx_id
;
1220 ox_id
= rsp
->abts_rsp_ox_id
;
1221 ISP_MEMZERO(&rsp
->abts_rsp_payload
.ba_acc
, sizeof (rsp
->abts_rsp_payload
.ba_acc
));
1222 isp_prt(isp
, ISP_LOGTINFO
, "[0x%x] ABTS of 0x%x being BA_ACC'd", rsp
->abts_rsp_rxid_abts
, rsp
->abts_rsp_rxid_task
);
1223 rsp
->abts_rsp_payload
.ba_acc
.aborted_rx_id
= rx_id
;
1224 rsp
->abts_rsp_payload
.ba_acc
.aborted_ox_id
= ox_id
;
1225 rsp
->abts_rsp_payload
.ba_acc
.high_seq_cnt
= 0xffff;
1227 ISP_MEMZERO(&rsp
->abts_rsp_payload
.ba_rjt
, sizeof (rsp
->abts_rsp_payload
.ba_acc
));
1230 rsp
->abts_rsp_payload
.ba_rjt
.reason
= 5; /* Logical Busy */
1233 rsp
->abts_rsp_payload
.ba_rjt
.reason
= 9; /* Unable to perform command request */
1239 * The caller will have set response values as appropriate
1240 * in the ABTS structure just before calling us.
1242 isp_put_abts_rsp(isp
, rsp
, (abts_rsp_t
*)outp
);
1243 ISP_TDQE(isp
, "isp_acknak_abts", isp
->isp_reqidx
, storage
);
1244 ISP_SYNC_REQUEST(isp
);
1249 isp_handle_atio(ispsoftc_t
*isp
, at_entry_t
*aep
)
1254 * The firmware status (except for the QLTM_SVALID bit) indicates
1255 * why this ATIO was sent to us.
1257 * If QLTM_SVALID is set, the firware has recommended Sense Data.
1259 * If the DISCONNECTS DISABLED bit is set in the flags field,
1260 * we're still connected on the SCSI bus - i.e. the initiator
1261 * did not set DiscPriv in the identify message. We don't care
1262 * about this so it's ignored.
1265 switch (aep
->at_status
& ~QLTM_SVALID
) {
1266 case AT_PATH_INVALID
:
1268 * ATIO rejected by the firmware due to disabled lun.
1270 isp_prt(isp
, ISP_LOGERR
, "rejected ATIO for disabled lun %d", lun
);
1274 * Requested Capability not available
1275 * We sent an ATIO that overflowed the firmware's
1276 * command resource count.
1278 isp_prt(isp
, ISP_LOGERR
, "rejected ATIO for lun %d because of command count overflow", lun
);
1283 * If we send an ATIO to the firmware to increment
1284 * its command resource count, and the firmware is
1285 * recovering from a Bus Device Reset, it returns
1286 * the ATIO with this status. We set the command
1287 * resource count in the Enable Lun entry and do
1288 * not increment it. Therefore we should never get
1291 isp_prt(isp
, ISP_LOGERR
, atiocope
, lun
, GET_BUS_VAL(aep
->at_iid
));
1294 case AT_CDB
: /* Got a CDB */
1295 case AT_PHASE_ERROR
: /* Bus Phase Sequence Error */
1297 * Punt to platform specific layer.
1299 isp_async(isp
, ISPASYNC_TARGET_ACTION
, aep
);
1304 * A bus reset came along and blew away this command. Why
1305 * they do this in addition the async event code stuff,
1308 * Ignore it because the async event will clear things
1311 isp_prt(isp
, ISP_LOGWARN
, atior
, lun
, GET_IID_VAL(aep
->at_iid
), GET_BUS_VAL(aep
->at_iid
));
1316 isp_prt(isp
, ISP_LOGERR
, "Unknown ATIO status 0x%x from loopid %d for lun %d", aep
->at_status
, aep
->at_iid
, lun
);
1317 (void) isp_target_put_atio(isp
, aep
);
1323 isp_handle_atio2(ispsoftc_t
*isp
, at2_entry_t
*aep
)
1327 if (ISP_CAP_SCCFW(isp
)) {
1328 lun
= aep
->at_scclun
;
1333 if (ISP_CAP_2KLOGIN(isp
)) {
1334 iid
= ((at2e_entry_t
*)aep
)->at_iid
;
1340 * The firmware status (except for the QLTM_SVALID bit) indicates
1341 * why this ATIO was sent to us.
1343 * If QLTM_SVALID is set, the firware has recommended Sense Data.
1345 * If the DISCONNECTS DISABLED bit is set in the flags field,
1346 * we're still connected on the SCSI bus - i.e. the initiator
1347 * did not set DiscPriv in the identify message. We don't care
1348 * about this so it's ignored.
1351 switch (aep
->at_status
& ~QLTM_SVALID
) {
1352 case AT_PATH_INVALID
:
1354 * ATIO rejected by the firmware due to disabled lun.
1356 isp_prt(isp
, ISP_LOGERR
, "rejected ATIO2 for disabled lun %d", lun
);
1360 * Requested Capability not available
1361 * We sent an ATIO that overflowed the firmware's
1362 * command resource count.
1364 isp_prt(isp
, ISP_LOGERR
, "rejected ATIO2 for lun %d- command count overflow", lun
);
1369 * If we send an ATIO to the firmware to increment
1370 * its command resource count, and the firmware is
1371 * recovering from a Bus Device Reset, it returns
1372 * the ATIO with this status. We set the command
1373 * resource count in the Enable Lun entry and no
1374 * not increment it. Therefore we should never get
1377 isp_prt(isp
, ISP_LOGERR
, atiocope
, lun
, 0);
1380 case AT_CDB
: /* Got a CDB */
1382 * Punt to platform specific layer.
1384 isp_async(isp
, ISPASYNC_TARGET_ACTION
, aep
);
1389 * A bus reset came along an blew away this command. Why
1390 * they do this in addition the async event code stuff,
1393 * Ignore it because the async event will clear things
1396 isp_prt(isp
, ISP_LOGERR
, atior
, lun
, iid
, 0);
1401 isp_prt(isp
, ISP_LOGERR
, "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep
->at_status
, iid
, lun
);
1402 (void) isp_target_put_atio(isp
, aep
);
1408 isp_handle_ctio(ispsoftc_t
*isp
, ct_entry_t
*ct
)
1411 int pl
= ISP_LOGTDEBUG2
;
1414 if (ct
->ct_syshandle
) {
1415 xs
= isp_find_xs_tgt(isp
, ct
->ct_syshandle
);
1423 switch (ct
->ct_status
& ~QLTM_SVALID
) {
1426 * There are generally 3 possibilities as to why we'd get
1428 * We disconnected after receiving a CDB.
1429 * We sent or received data.
1430 * We sent status & command complete.
1433 if (ct
->ct_flags
& CT_SENDSTATUS
) {
1435 } else if ((ct
->ct_flags
& CT_DATAMASK
) == CT_NO_DATA
) {
1437 * Nothing to do in this case.
1439 isp_prt(isp
, pl
, "CTIO- iid %d disconnected OK", ct
->ct_iid
);
1446 * Bus Device Reset message received or the SCSI Bus has
1447 * been Reset; the firmware has gone to Bus Free.
1449 * The firmware generates an async mailbox interrupt to
1450 * notify us of this and returns outstanding CTIOs with this
1451 * status. These CTIOs are handled in that same way as
1452 * CT_ABORTED ones, so just fall through here.
1454 fmsg
= "Bus Device Reset";
1462 * When an Abort message is received the firmware goes to
1463 * Bus Free and returns all outstanding CTIOs with the status
1464 * set, then sends us an Immediate Notify entry.
1467 fmsg
= "ABORT TAG message sent by Initiator";
1468 isp_prt(isp
, ISP_LOGTDEBUG0
, "CTIO destroyed by %s", fmsg
);
1473 * CTIO rejected by the firmware due to disabled lun.
1476 isp_prt(isp
, ISP_LOGERR
, "Firmware rejected CTIO for disabled lun %d", ct
->ct_lun
);
1481 * CTIO rejected by the firmware due "no path for the
1482 * nondisconnecting nexus specified". This means that
1483 * we tried to access the bus while a non-disconnecting
1484 * command is in process.
1486 isp_prt(isp
, ISP_LOGERR
, "Firmware rejected CTIO for bad nexus %d/%d/%d", ct
->ct_iid
, ct
->ct_tgt
, ct
->ct_lun
);
1490 fmsg
= "Reselection";
1495 isp_prt(isp
, ISP_LOGWARN
, "Firmware timed out on %s", fmsg
);
1500 fmsg
= "Unrecoverable Error";
1504 fmsg
= "Completed with Error";
1506 case CT_PHASE_ERROR
:
1508 fmsg
= "Phase Sequence Error";
1512 fmsg
= "terminated by TERMINATE TRANSFER";
1516 fmsg
= "unacknowledged Immediate Notify pending";
1517 isp_prt(isp
, ISP_LOGERR
, "CTIO returned by f/w- %s", fmsg
);
1520 isp_prt(isp
, ISP_LOGERR
, "Unknown CTIO status 0x%x", ct
->ct_status
& ~QLTM_SVALID
);
1526 * There may be more than one CTIO for a data transfer,
1527 * or this may be a status CTIO we're not monitoring.
1529 * The assumption is that they'll all be returned in the
1530 * order we got them.
1532 if (ct
->ct_syshandle
== 0) {
1533 if ((ct
->ct_flags
& CT_SENDSTATUS
) == 0) {
1534 isp_prt(isp
, pl
, "intermediate CTIO completed ok");
1536 isp_prt(isp
, pl
, "unmonitored CTIO completed ok");
1539 isp_prt(isp
, pl
, "NO xs for CTIO (handle 0x%x) status 0x%x", ct
->ct_syshandle
, ct
->ct_status
& ~QLTM_SVALID
);
1543 * Final CTIO completed. Release DMA resources and
1544 * notify platform dependent layers.
1546 if ((ct
->ct_flags
& CT_DATAMASK
) != CT_NO_DATA
) {
1547 ISP_DMAFREE(isp
, xs
, ct
->ct_syshandle
);
1549 isp_prt(isp
, pl
, "final CTIO complete");
1551 * The platform layer will destroy the handle if appropriate.
1553 isp_async(isp
, ISPASYNC_TARGET_ACTION
, ct
);
1558 isp_handle_ctio2(ispsoftc_t
*isp
, ct2_entry_t
*ct
)
1561 int pl
= ISP_LOGTDEBUG2
;
1564 if (ct
->ct_syshandle
) {
1565 xs
= isp_find_xs_tgt(isp
, ct
->ct_syshandle
);
1573 switch (ct
->ct_status
& ~QLTM_SVALID
) {
1575 isp_prt(isp
, ISP_LOGERR
, "PCI DMA Bus Error");
1581 * There are generally 2 possibilities as to why we'd get
1583 * We sent or received data.
1584 * We sent status & command complete.
1591 * Target Reset function received.
1593 * The firmware generates an async mailbox interrupt to
1594 * notify us of this and returns outstanding CTIOs with this
1595 * status. These CTIOs are handled in that same way as
1596 * CT_ABORTED ones, so just fall through here.
1598 fmsg
= "TARGET RESET";
1606 * When an Abort message is received the firmware goes to
1607 * Bus Free and returns all outstanding CTIOs with the status
1608 * set, then sends us an Immediate Notify entry.
1614 isp_prt(isp
, ISP_LOGTDEBUG0
, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg
, ct
->ct_rxid
);
1619 * CTIO rejected by the firmware - invalid data direction.
1621 isp_prt(isp
, ISP_LOGERR
, "CTIO2 had wrong data direction");
1625 fmsg
= "failure to reconnect to initiator";
1630 isp_prt(isp
, ISP_LOGWARN
, "Firmware timed out on %s", fmsg
);
1634 fmsg
= "Completed with Error";
1638 fmsg
= "Port Logout";
1640 case CT_PORTUNAVAIL
:
1642 fmsg
= "Port not available";
1644 case CT_PORTCHANGED
:
1646 fmsg
= "Port Changed";
1650 fmsg
= "unacknowledged Immediate Notify pending";
1651 isp_prt(isp
, ISP_LOGWARN
, "CTIO returned by f/w- %s", fmsg
);
1656 * CTIO rejected by the firmware because an invalid RX_ID.
1657 * Just print a message.
1659 isp_prt(isp
, ISP_LOGWARN
, "CTIO2 completed with Invalid RX_ID 0x%x", ct
->ct_rxid
);
1663 isp_prt(isp
, ISP_LOGERR
, "Unknown CTIO2 status 0x%x", ct
->ct_status
& ~QLTM_SVALID
);
1669 * There may be more than one CTIO for a data transfer,
1670 * or this may be a status CTIO we're not monitoring.
1672 * The assumption is that they'll all be returned in the
1673 * order we got them.
1675 if (ct
->ct_syshandle
== 0) {
1676 if ((ct
->ct_flags
& CT2_SENDSTATUS
) == 0) {
1677 isp_prt(isp
, pl
, "intermediate CTIO completed ok");
1679 isp_prt(isp
, pl
, "unmonitored CTIO completed ok");
1682 isp_prt(isp
, pl
, "NO xs for CTIO (handle 0x%x) status 0x%x", ct
->ct_syshandle
, ct
->ct_status
& ~QLTM_SVALID
);
1685 if ((ct
->ct_flags
& CT2_DATAMASK
) != CT2_NO_DATA
) {
1686 ISP_DMAFREE(isp
, xs
, ct
->ct_syshandle
);
1688 if (ct
->ct_flags
& CT2_SENDSTATUS
) {
1690 * Sent status and command complete.
1692 * We're now really done with this command, so we
1693 * punt to the platform dependent layers because
1694 * only there can we do the appropriate command
1695 * complete thread synchronization.
1697 isp_prt(isp
, pl
, "status CTIO complete");
1700 * Final CTIO completed. Release DMA resources and
1701 * notify platform dependent layers.
1703 isp_prt(isp
, pl
, "data CTIO complete");
1705 isp_async(isp
, ISPASYNC_TARGET_ACTION
, ct
);
1707 * The platform layer will destroy the handle if appropriate.
1713 isp_handle_ctio7(ispsoftc_t
*isp
, ct7_entry_t
*ct
)
1716 int pl
= ISP_LOGTDEBUG2
;
1719 if (ct
->ct_syshandle
) {
1720 xs
= isp_find_xs_tgt(isp
, ct
->ct_syshandle
);
1728 switch (ct
->ct_nphdl
) {
1730 isp_prt(isp
, ISP_LOGERR
, "PCI DMA Bus Error");
1733 case CT7_DATA_UNDER
:
1736 * There are generally 2 possibilities as to why we'd get
1738 * We sent or received data.
1739 * We sent status & command complete.
1751 * When an Abort message is received the firmware goes to
1752 * Bus Free and returns all outstanding CTIOs with the status
1753 * set, then sends us an Immediate Notify entry.
1758 isp_prt(isp
, ISP_LOGTDEBUG0
, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg
, ct
->ct_rxid
);
1765 isp_prt(isp
, ISP_LOGWARN
, "Firmware timed out on %s", fmsg
);
1769 fmsg
= "Completed with Error";
1773 fmsg
= "Port Logout";
1776 case CT7_PORTUNAVAIL
:
1778 fmsg
= "Port not available";
1781 case CT7_PORTCHANGED
:
1783 fmsg
= "Port Changed";
1785 isp_prt(isp
, ISP_LOGWARN
, "CTIO returned by f/w- %s", fmsg
);
1790 * CTIO rejected by the firmware because an invalid RX_ID.
1791 * Just print a message.
1793 isp_prt(isp
, ISP_LOGWARN
, "CTIO7 completed with Invalid RX_ID 0x%x", ct
->ct_rxid
);
1796 case CT7_REASSY_ERR
:
1797 isp_prt(isp
, ISP_LOGWARN
, "reassembly error");
1801 isp_prt(isp
, ISP_LOGWARN
, "SRR received");
1805 isp_prt(isp
, ISP_LOGERR
, "Unknown CTIO7 status 0x%x", ct
->ct_nphdl
);
1811 * There may be more than one CTIO for a data transfer,
1812 * or this may be a status CTIO we're not monitoring.
1814 * The assumption is that they'll all be returned in the
1815 * order we got them.
1817 if (ct
->ct_syshandle
== 0) {
1818 if (ct
->ct_flags
& CT7_TERMINATE
) {
1819 isp_prt(isp
, ISP_LOGINFO
, "termination of 0x%x complete", ct
->ct_rxid
);
1820 } else if ((ct
->ct_flags
& CT7_SENDSTATUS
) == 0) {
1821 isp_prt(isp
, pl
, "intermediate CTIO completed ok");
1823 isp_prt(isp
, pl
, "unmonitored CTIO completed ok");
1826 isp_prt(isp
, pl
, "NO xs for CTIO (handle 0x%x) status 0x%x", ct
->ct_syshandle
, ct
->ct_nphdl
);
1829 if ((ct
->ct_flags
& CT7_DATAMASK
) != CT7_NO_DATA
) {
1830 ISP_DMAFREE(isp
, xs
, ct
->ct_syshandle
);
1832 if (ct
->ct_flags
& CT7_SENDSTATUS
) {
1834 * Sent status and command complete.
1836 * We're now really done with this command, so we
1837 * punt to the platform dependent layers because
1838 * only there can we do the appropriate command
1839 * complete thread synchronization.
1841 isp_prt(isp
, pl
, "status CTIO complete");
1844 * Final CTIO completed. Release DMA resources and
1845 * notify platform dependent layers.
1847 isp_prt(isp
, pl
, "data CTIO complete");
1849 isp_async(isp
, ISPASYNC_TARGET_ACTION
, ct
);
1851 * The platform layer will destroy the handle if appropriate.
1857 isp_handle_24xx_inotify(ispsoftc_t
*isp
, in_fcentry_24xx_t
*inot_24xx
)
1859 uint8_t ochan
, chan
, lochan
, hichan
;
1862 * Check to see whether we got a wildcard channel.
1863 * If so, we have to iterate over all channels.
1865 ochan
= chan
= ISP_GET_VPIDX(isp
, inot_24xx
->in_vpidx
);
1868 hichan
= isp
->isp_nchan
;
1870 if (chan
>= isp
->isp_nchan
) {
1872 ISP_SNPRINTF(buf
, sizeof buf
, "%s: bad channel %d for status 0x%x", __func__
, chan
, inot_24xx
->in_status
);
1873 isp_print_bytes(isp
, buf
, QENTRY_LEN
, inot_24xx
);
1874 (void) isp_notify_ack(isp
, inot_24xx
);
1880 isp_prt(isp
, ISP_LOGTDEBUG1
, "%s: Immediate Notify Channels %d..%d status=0x%x seqid=0x%x", __func__
, lochan
, hichan
-1, inot_24xx
->in_status
, inot_24xx
->in_rxid
);
1881 for (chan
= lochan
; chan
< hichan
; chan
++) {
1882 switch (inot_24xx
->in_status
) {
1883 case IN24XX_LIP_RESET
:
1884 case IN24XX_LINK_RESET
:
1885 case IN24XX_PORT_LOGOUT
:
1886 case IN24XX_PORT_CHANGED
:
1887 case IN24XX_LINK_FAILED
:
1888 case IN24XX_SRR_RCVD
:
1889 case IN24XX_ELS_RCVD
:
1890 inot_24xx
->in_vpidx
= chan
;
1891 isp_async(isp
, ISPASYNC_TARGET_ACTION
, inot_24xx
);
1894 isp_prt(isp
, ISP_LOGINFO
, "%s: unhandled status (0x%x) for chan %d", __func__
, inot_24xx
->in_status
, chan
);
1895 (void) isp_notify_ack(isp
, inot_24xx
);
1899 inot_24xx
->in_vpidx
= ochan
;