isp_target.c revision 1.20 1 /* $NetBSD: isp_target.c,v 1.20 2002/10/18 23:33:14 mjacob Exp $ */
2 /*
3 * This driver, which is contained in NetBSD in the files:
4 *
5 * sys/dev/ic/isp.c
6 * sys/dev/ic/isp_inline.h
7 * sys/dev/ic/isp_netbsd.c
8 * sys/dev/ic/isp_netbsd.h
9 * sys/dev/ic/isp_target.c
10 * sys/dev/ic/isp_target.h
11 * sys/dev/ic/isp_tpublic.h
12 * sys/dev/ic/ispmbox.h
13 * sys/dev/ic/ispreg.h
14 * sys/dev/ic/ispvar.h
15 * sys/microcode/isp/asm_sbus.h
16 * sys/microcode/isp/asm_1040.h
17 * sys/microcode/isp/asm_1080.h
18 * sys/microcode/isp/asm_12160.h
19 * sys/microcode/isp/asm_2100.h
20 * sys/microcode/isp/asm_2200.h
21 * sys/pci/isp_pci.c
22 * sys/sbus/isp_sbus.c
23 *
24 * Is being actively maintained by Matthew Jacob (mjacob (at) netbsd.org).
25 * This driver also is shared source with FreeBSD, OpenBSD, Linux, Solaris,
26 * Linux versions. This tends to be an interesting maintenance problem.
27 *
28 * Please coordinate with Matthew Jacob on changes you wish to make here.
29 */
30 /*
31 * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters.
32 *
33 * Copyright (c) 1999, 2000, 2001 by Matthew Jacob
34 * All rights reserved.
35 * mjacob (at) feral.com
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice immediately at the beginning of the file, without modification,
42 * this list of conditions, and the following disclaimer.
43 * 2. The name of the author may not be used to endorse or promote products
44 * derived from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 */
58
59 /*
60 * Bug fixes gratefully acknowledged from:
61 * Oded Kedem <oded (at) kashya.com>
62 */
63 /*
64 * Include header file appropriate for platform we're building on.
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: isp_target.c,v 1.20 2002/10/18 23:33:14 mjacob Exp $");
69
70 #ifdef __NetBSD__
71 #include <dev/ic/isp_netbsd.h>
72 #endif
73 #ifdef __FreeBSD__
74 #include <dev/isp/isp_freebsd.h>
75 #endif
76 #ifdef __OpenBSD__
77 #include <dev/ic/isp_openbsd.h>
78 #endif
79 #ifdef __linux__
80 #include "isp_linux.h"
81 #endif
82
83 #ifdef ISP_TARGET_MODE
84 static const char atiocope[] =
85 "ATIO returned for lun %d because it was in the middle of Bus Device Reset "
86 "on bus %d";
87 static const char atior[] =
88 "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred "
89 "on bus %d";
90
91 static void isp_got_msg(struct ispsoftc *, int, in_entry_t *);
92 static void isp_got_msg_fc(struct ispsoftc *, int, in_fcentry_t *);
93 static void isp_notify_ack(struct ispsoftc *, void *);
94 static void isp_handle_atio(struct ispsoftc *, at_entry_t *);
95 static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *);
96 static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *);
97 static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *);
98
99 /*
100 * The Qlogic driver gets an interrupt to look at response queue entries.
101 * Some of these are status completions for initiatior mode commands, but
102 * if target mode is enabled, we get a whole wad of response queue entries
103 * to be handled here.
104 *
105 * Basically the split into 3 main groups: Lun Enable/Modification responses,
106 * SCSI Command processing, and Immediate Notification events.
107 *
108 * You start by writing a request queue entry to enable target mode (and
109 * establish some resource limitations which you can modify later).
110 * The f/w responds with a LUN ENABLE or LUN MODIFY response with
111 * the status of this action. If the enable was successful, you can expect...
112 *
113 * Response queue entries with SCSI commands encapsulate show up in an ATIO
114 * (Accept Target IO) type- sometimes with enough info to stop the command at
115 * this level. Ultimately the driver has to feed back to the f/w's request
116 * queue a sequence of CTIOs (continue target I/O) that describe data to
117 * be moved and/or status to be sent) and finally finishing with sending
118 * to the f/w's response queue an ATIO which then completes the handshake
119 * with the f/w for that command. There's a lot of variations on this theme,
120 * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel
121 * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic
122 * gist of it.
123 *
124 * The third group that can show up in the response queue are Immediate
125 * Notification events. These include things like notifications of SCSI bus
126 * resets, or Bus Device Reset messages or other messages received. This
127 * a classic oddbins area. It can get a little weird because you then turn
128 * around and acknowledge the Immediate Notify by writing an entry onto the
129 * request queue and then the f/w turns around and gives you an acknowledgement
130 * to *your* acknowledgement on the response queue (the idea being to let
131 * the f/w tell you when the event is *really* over I guess).
132 *
133 */
134
135
136 /*
137 * A new response queue entry has arrived. The interrupt service code
138 * has already swizzled it into the platform dependent from canonical form.
139 *
140 * Because of the way this driver is designed, unfortunately most of the
141 * actual synchronization work has to be done in the platform specific
142 * code- we have no synchroniation primitives in the common code.
143 */
144
145 int
146 isp_target_notify(struct ispsoftc *isp, void *vptr, u_int16_t *optrp)
147 {
148 u_int16_t status, seqid;
149 union {
150 at_entry_t *atiop;
151 at2_entry_t *at2iop;
152 ct_entry_t *ctiop;
153 ct2_entry_t *ct2iop;
154 lun_entry_t *lunenp;
155 in_entry_t *inotp;
156 in_fcentry_t *inot_fcp;
157 na_entry_t *nackp;
158 na_fcentry_t *nack_fcp;
159 isphdr_t *hp;
160 void * *vp;
161 #define atiop unp.atiop
162 #define at2iop unp.at2iop
163 #define ctiop unp.ctiop
164 #define ct2iop unp.ct2iop
165 #define lunenp unp.lunenp
166 #define inotp unp.inotp
167 #define inot_fcp unp.inot_fcp
168 #define nackp unp.nackp
169 #define nack_fcp unp.nack_fcp
170 #define hdrp unp.hp
171 } unp;
172 u_int8_t local[QENTRY_LEN];
173 int bus, type, rval = 1;
174
175 type = isp_get_response_type(isp, (isphdr_t *)vptr);
176 unp.vp = vptr;
177
178 ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr);
179
180 switch(type) {
181 case RQSTYPE_ATIO:
182 isp_get_atio(isp, atiop, (at_entry_t *) local);
183 isp_handle_atio(isp, (at_entry_t *) local);
184 break;
185 case RQSTYPE_CTIO:
186 isp_get_ctio(isp, ctiop, (ct_entry_t *) local);
187 isp_handle_ctio(isp, (ct_entry_t *) local);
188 break;
189 case RQSTYPE_ATIO2:
190 isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
191 isp_handle_atio2(isp, (at2_entry_t *) local);
192 break;
193 case RQSTYPE_CTIO2:
194 isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
195 isp_handle_ctio2(isp, (ct2_entry_t *) local);
196 break;
197 case RQSTYPE_ENABLE_LUN:
198 case RQSTYPE_MODIFY_LUN:
199 isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
200 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
201 break;
202
203 case RQSTYPE_NOTIFY:
204 /*
205 * Either the ISP received a SCSI message it can't
206 * handle, or it's returning an Immed. Notify entry
207 * we sent. We can send Immed. Notify entries to
208 * increment the firmware's resource count for them
209 * (we set this initially in the Enable Lun entry).
210 */
211 bus = 0;
212 if (IS_FC(isp)) {
213 isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local);
214 inot_fcp = (in_fcentry_t *) local;
215 status = inot_fcp->in_status;
216 seqid = inot_fcp->in_seqid;
217 } else {
218 isp_get_notify(isp, inotp, (in_entry_t *)local);
219 inotp = (in_entry_t *) local;
220 status = inotp->in_status & 0xff;
221 seqid = inotp->in_seqid;
222 if (IS_DUALBUS(isp)) {
223 bus = GET_BUS_VAL(inotp->in_iid);
224 SET_BUS_VAL(inotp->in_iid, 0);
225 }
226 }
227 isp_prt(isp, ISP_LOGTDEBUG0,
228 "Immediate Notify On Bus %d, status=0x%x seqid=0x%x",
229 bus, status, seqid);
230
231 /*
232 * ACK it right away.
233 */
234 isp_notify_ack(isp, (status == IN_RESET)? NULL : local);
235 switch (status) {
236 case IN_RESET:
237 (void) isp_async(isp, ISPASYNC_BUS_RESET, &bus);
238 break;
239 case IN_MSG_RECEIVED:
240 case IN_IDE_RECEIVED:
241 if (IS_FC(isp)) {
242 isp_got_msg_fc(isp, bus, (in_fcentry_t *)local);
243 } else {
244 isp_got_msg(isp, bus, (in_entry_t *)local);
245 }
246 break;
247 case IN_RSRC_UNAVAIL:
248 isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs");
249 break;
250 case IN_PORT_LOGOUT:
251 case IN_ABORT_TASK:
252 case IN_PORT_CHANGED:
253 case IN_GLOBAL_LOGO:
254 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
255 break;
256 default:
257 isp_prt(isp, ISP_LOGERR,
258 "bad status (0x%x) in isp_target_notify", status);
259 break;
260 }
261 break;
262
263 case RQSTYPE_NOTIFY_ACK:
264 /*
265 * The ISP is acknowledging our acknowledgement of an
266 * Immediate Notify entry for some asynchronous event.
267 */
268 if (IS_FC(isp)) {
269 isp_get_notify_ack_fc(isp, nack_fcp,
270 (na_fcentry_t *)local);
271 nack_fcp = (na_fcentry_t *)local;
272 isp_prt(isp, ISP_LOGTDEBUG1,
273 "Notify Ack status=0x%x seqid 0x%x",
274 nack_fcp->na_status, nack_fcp->na_seqid);
275 } else {
276 isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
277 nackp = (na_entry_t *)local;
278 isp_prt(isp, ISP_LOGTDEBUG1,
279 "Notify Ack event 0x%x status=0x%x seqid 0x%x",
280 nackp->na_event, nackp->na_status, nackp->na_seqid);
281 }
282 break;
283 default:
284 isp_prt(isp, ISP_LOGERR,
285 "Unknown entry type 0x%x in isp_target_notify", type);
286 rval = 0;
287 break;
288 }
289 #undef atiop
290 #undef at2iop
291 #undef ctiop
292 #undef ct2iop
293 #undef lunenp
294 #undef inotp
295 #undef inot_fcp
296 #undef nackp
297 #undef nack_fcp
298 #undef hdrp
299 return (rval);
300 }
301
302
303 /*
304 * Toggle (on/off) target mode for bus/target/lun
305 *
306 * The caller has checked for overlap and legality.
307 *
308 * Note that not all of bus, target or lun can be paid attention to.
309 * Note also that this action will not be complete until the f/w writes
310 * response entry. The caller is responsible for synchronizing this.
311 */
312 int
313 isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun,
314 int cmd_cnt, int inot_cnt, u_int32_t opaque)
315 {
316 lun_entry_t el;
317 u_int16_t nxti, optr;
318 void *outp;
319
320
321 MEMZERO(&el, sizeof (el));
322 if (IS_DUALBUS(isp)) {
323 el.le_rsvd = (bus & 0x1) << 7;
324 }
325 el.le_cmd_count = cmd_cnt;
326 el.le_in_count = inot_cnt;
327 if (cmd == RQSTYPE_ENABLE_LUN) {
328 if (IS_SCSI(isp)) {
329 el.le_flags = LUN_TQAE|LUN_DISAD;
330 el.le_cdb6len = 12;
331 el.le_cdb7len = 12;
332 }
333 } else if (cmd == -RQSTYPE_ENABLE_LUN) {
334 cmd = RQSTYPE_ENABLE_LUN;
335 el.le_cmd_count = 0;
336 el.le_in_count = 0;
337 } else if (cmd == -RQSTYPE_MODIFY_LUN) {
338 cmd = RQSTYPE_MODIFY_LUN;
339 el.le_ops = LUN_CCDECR | LUN_INDECR;
340 } else {
341 el.le_ops = LUN_CCINCR | LUN_ININCR;
342 }
343 el.le_header.rqs_entry_type = cmd;
344 el.le_header.rqs_entry_count = 1;
345 el.le_reserved = opaque;
346 if (IS_SCSI(isp)) {
347 el.le_tgt = tgt;
348 el.le_lun = lun;
349 } else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
350 el.le_lun = lun;
351 }
352 el.le_timeout = 2;
353
354 if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
355 isp_prt(isp, ISP_LOGERR,
356 "Request Queue Overflow in isp_lun_cmd");
357 return (-1);
358 }
359 ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el);
360 isp_put_enable_lun(isp, &el, outp);
361 ISP_ADD_REQUEST(isp, nxti);
362 return (0);
363 }
364
365
366 int
367 isp_target_put_entry(struct ispsoftc *isp, void *ap)
368 {
369 void *outp;
370 u_int16_t nxti, optr;
371 u_int8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
372
373 if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
374 isp_prt(isp, ISP_LOGWARN,
375 "Request Queue Overflow in isp_target_put_entry");
376 return (-1);
377 }
378 switch (etype) {
379 case RQSTYPE_ATIO:
380 isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
381 break;
382 case RQSTYPE_ATIO2:
383 isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
384 break;
385 case RQSTYPE_CTIO:
386 isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
387 break;
388 case RQSTYPE_CTIO2:
389 isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
390 break;
391 default:
392 isp_prt(isp, ISP_LOGERR,
393 "Unknown type 0x%x in isp_put_entry", etype);
394 return (-1);
395 }
396
397 ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap);;
398 ISP_ADD_REQUEST(isp, nxti);
399 return (0);
400 }
401
402 int
403 isp_target_put_atio(struct ispsoftc *isp, void *arg)
404 {
405 union {
406 at_entry_t _atio;
407 at2_entry_t _atio2;
408 } atun;
409
410 MEMZERO(&atun, sizeof atun);
411 if (IS_FC(isp)) {
412 at2_entry_t *aep = arg;
413 atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
414 atun._atio2.at_header.rqs_entry_count = 1;
415 if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
416 atun._atio2.at_scclun = (u_int16_t) aep->at_scclun;
417 } else {
418 atun._atio2.at_lun = (u_int8_t) aep->at_lun;
419 }
420 atun._atio2.at_status = CT_OK;
421 } else {
422 at_entry_t *aep = arg;
423 atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO;
424 atun._atio.at_header.rqs_entry_count = 1;
425 atun._atio.at_handle = aep->at_handle;
426 atun._atio.at_iid = aep->at_iid;
427 atun._atio.at_tgt = aep->at_tgt;
428 atun._atio.at_lun = aep->at_lun;
429 atun._atio.at_tag_type = aep->at_tag_type;
430 atun._atio.at_tag_val = aep->at_tag_val;
431 atun._atio.at_status = (aep->at_flags & AT_TQAE);
432 atun._atio.at_status |= CT_OK;
433 }
434 return (isp_target_put_entry(isp, &atun));
435 }
436
437 /*
438 * Command completion- both for handling cases of no resources or
439 * no blackhole driver, or other cases where we have to, inline,
440 * finish the command sanely, or for normal command completion.
441 *
442 * The 'completion' code value has the scsi status byte in the low 8 bits.
443 * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have
444 * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC
445 * values.
446 *
447 * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't
448 * NB: inline SCSI sense reporting. As such, we lose this information. XXX.
449 *
450 * For both parallel && fibre channel, we use the feature that does
451 * an automatic resource autoreplenish so we don't have then later do
452 * put of an atio to replenish the f/w's resource count.
453 */
454
455 int
456 isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int16_t hdl)
457 {
458 int sts;
459 union {
460 ct_entry_t _ctio;
461 ct2_entry_t _ctio2;
462 } un;
463
464 MEMZERO(&un, sizeof un);
465 sts = code & 0xff;
466
467 if (IS_FC(isp)) {
468 at2_entry_t *aep = arg;
469 ct2_entry_t *cto = &un._ctio2;
470
471 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
472 cto->ct_header.rqs_entry_count = 1;
473 cto->ct_iid = aep->at_iid;
474 if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
475 cto->ct_lun = aep->at_lun;
476 }
477 cto->ct_rxid = aep->at_rxid;
478 cto->rsp.m1.ct_scsi_status = sts & 0xff;
479 cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1;
480 if (hdl == 0) {
481 cto->ct_flags |= CT2_CCINCR;
482 }
483 if (aep->at_datalen) {
484 cto->ct_resid = aep->at_datalen;
485 cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
486 }
487 if ((sts & 0xff) == SCSI_CHECK && (sts & ECMD_SVALID)) {
488 cto->rsp.m1.ct_resp[0] = 0xf0;
489 cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
490 cto->rsp.m1.ct_resp[7] = 8;
491 cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
492 cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
493 cto->rsp.m1.ct_senselen = 16;
494 cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
495 }
496 cto->ct_syshandle = hdl;
497 } else {
498 at_entry_t *aep = arg;
499 ct_entry_t *cto = &un._ctio;
500
501 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
502 cto->ct_header.rqs_entry_count = 1;
503 cto->ct_fwhandle = aep->at_handle;
504 cto->ct_iid = aep->at_iid;
505 cto->ct_tgt = aep->at_tgt;
506 cto->ct_lun = aep->at_lun;
507 cto->ct_tag_type = aep->at_tag_type;
508 cto->ct_tag_val = aep->at_tag_val;
509 if (aep->at_flags & AT_TQAE) {
510 cto->ct_flags |= CT_TQAE;
511 }
512 cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA;
513 if (hdl == 0) {
514 cto->ct_flags |= CT_CCINCR;
515 }
516 cto->ct_scsi_status = sts;
517 cto->ct_syshandle = hdl;
518 }
519 return (isp_target_put_entry(isp, &un));
520 }
521
522 int
523 isp_target_async(struct ispsoftc *isp, int bus, int event)
524 {
525 tmd_event_t evt;
526 tmd_msg_t msg;
527
528 switch (event) {
529 /*
530 * These three we handle here to propagate an effective bus reset
531 * upstream, but these do not require any immediate notify actions
532 * so we return when done.
533 */
534 case ASYNC_LIP_F8:
535 case ASYNC_LIP_OCCURRED:
536 case ASYNC_LOOP_UP:
537 case ASYNC_LOOP_DOWN:
538 case ASYNC_LOOP_RESET:
539 case ASYNC_PTPMODE:
540 /*
541 * These don't require any immediate notify actions. We used
542 * treat them like SCSI Bus Resets, but that was just plain
543 * wrong. Let the normal CTIO completion report what occurred.
544 */
545 return (0);
546
547 case ASYNC_BUS_RESET:
548 case ASYNC_TIMEOUT_RESET:
549 if (IS_FC(isp)) {
550 return (0); /* we'll be getting an inotify instead */
551 }
552 evt.ev_bus = bus;
553 evt.ev_event = event;
554 (void) isp_async(isp, ISPASYNC_TARGET_EVENT, &evt);
555 break;
556 case ASYNC_DEVICE_RESET:
557 /*
558 * Bus Device Reset resets a specific target, so
559 * we pass this as a synthesized message.
560 */
561 MEMZERO(&msg, sizeof msg);
562 if (IS_FC(isp)) {
563 msg.nt_iid = FCPARAM(isp)->isp_loopid;
564 } else {
565 msg.nt_iid = SDPARAM(isp)->isp_initiator_id;
566 }
567 msg.nt_bus = bus;
568 msg.nt_msg[0] = MSG_BUS_DEV_RESET;
569 (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
570 break;
571 default:
572 isp_prt(isp, ISP_LOGERR,
573 "isp_target_async: unknown event 0x%x", event);
574 break;
575 }
576 if (isp->isp_state == ISP_RUNSTATE)
577 isp_notify_ack(isp, NULL);
578 return(0);
579 }
580
581
582 /*
583 * Process a received message.
584 * The ISP firmware can handle most messages, there are only
585 * a few that we need to deal with:
586 * - abort: clean up the current command
587 * - abort tag and clear queue
588 */
589
590 static void
591 isp_got_msg(struct ispsoftc *isp, int bus, in_entry_t *inp)
592 {
593 u_int8_t status = inp->in_status & ~QLTM_SVALID;
594
595 if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {
596 tmd_msg_t msg;
597
598 MEMZERO(&msg, sizeof (msg));
599 msg.nt_bus = bus;
600 msg.nt_iid = inp->in_iid;
601 msg.nt_tgt = inp->in_tgt;
602 msg.nt_lun = inp->in_lun;
603 msg.nt_tagtype = inp->in_tag_type;
604 msg.nt_tagval = inp->in_tag_val;
605 MEMCPY(msg.nt_msg, inp->in_msg, IN_MSGLEN);
606 (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
607 } else {
608 isp_prt(isp, ISP_LOGERR,
609 "unknown immediate notify status 0x%x", inp->in_status);
610 }
611 }
612
613 /*
614 * Synthesize a message from the task management flags in a FCP_CMND_IU.
615 */
616 static void
617 isp_got_msg_fc(struct ispsoftc *isp, int bus, in_fcentry_t *inp)
618 {
619 int lun;
620 static const char f1[] = "%s from iid %d lun %d seq 0x%x";
621 static const char f2[] =
622 "unknown %s 0x%x lun %d iid %d task flags 0x%x seq 0x%x\n";
623
624 if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
625 lun = inp->in_scclun;
626 } else {
627 lun = inp->in_lun;
628 }
629
630 if (inp->in_status != IN_MSG_RECEIVED) {
631 isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status",
632 inp->in_status, lun, inp->in_iid,
633 inp->in_task_flags, inp->in_seqid);
634 } else {
635 tmd_msg_t msg;
636
637 MEMZERO(&msg, sizeof (msg));
638 msg.nt_bus = bus;
639 msg.nt_iid = inp->in_iid;
640 msg.nt_tagval = inp->in_seqid;
641 msg.nt_lun = lun;
642
643 if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) {
644 isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK",
645 inp->in_iid, lun, inp->in_seqid);
646 msg.nt_msg[0] = MSG_ABORT_TAG;
647 } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
648 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
649 inp->in_iid, lun, inp->in_seqid);
650 msg.nt_msg[0] = MSG_CLEAR_QUEUE;
651 } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
652 isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
653 inp->in_iid, lun, inp->in_seqid);
654 msg.nt_msg[0] = MSG_BUS_DEV_RESET;
655 } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
656 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
657 inp->in_iid, lun, inp->in_seqid);
658 /* ???? */
659 msg.nt_msg[0] = MSG_REL_RECOVERY;
660 } else if (inp->in_task_flags & TASK_FLAGS_TERMINATE_TASK) {
661 isp_prt(isp, ISP_LOGINFO, f1, "TERMINATE TASK",
662 inp->in_iid, lun, inp->in_seqid);
663 msg.nt_msg[0] = MSG_TERM_IO_PROC;
664 } else {
665 isp_prt(isp, ISP_LOGWARN, f2, "task flag",
666 inp->in_status, lun, inp->in_iid,
667 inp->in_task_flags, inp->in_seqid);
668 }
669 if (msg.nt_msg[0]) {
670 (void) isp_async(isp, ISPASYNC_TARGET_MESSAGE, &msg);
671 }
672 }
673 }
674
675 static void
676 isp_notify_ack(struct ispsoftc *isp, void *arg)
677 {
678 char storage[QENTRY_LEN];
679 u_int16_t nxti, optr;
680 void *outp;
681
682 if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
683 isp_prt(isp, ISP_LOGWARN,
684 "Request Queue Overflow For isp_notify_ack");
685 return;
686 }
687
688 MEMZERO(storage, QENTRY_LEN);
689
690 if (IS_FC(isp)) {
691 na_fcentry_t *na = (na_fcentry_t *) storage;
692 if (arg) {
693 in_fcentry_t *inp = arg;
694 MEMCPY(storage, arg, sizeof (isphdr_t));
695 na->na_iid = inp->in_iid;
696 if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
697 na->na_lun = inp->in_scclun;
698 } else {
699 na->na_lun = inp->in_lun;
700 }
701 na->na_task_flags = inp->in_task_flags;
702 na->na_seqid = inp->in_seqid;
703 na->na_flags = NAFC_RCOUNT;
704 na->na_status = inp->in_status;
705 if (inp->in_status == IN_RESET) {
706 na->na_flags |= NAFC_RST_CLRD;
707 }
708 } else {
709 na->na_flags = NAFC_RST_CLRD;
710 }
711 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
712 na->na_header.rqs_entry_count = 1;
713 isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
714 } else {
715 na_entry_t *na = (na_entry_t *) storage;
716 if (arg) {
717 in_entry_t *inp = arg;
718 MEMCPY(storage, arg, sizeof (isphdr_t));
719 na->na_iid = inp->in_iid;
720 na->na_lun = inp->in_lun;
721 na->na_tgt = inp->in_tgt;
722 na->na_seqid = inp->in_seqid;
723 if (inp->in_status == IN_RESET) {
724 na->na_event = NA_RST_CLRD;
725 }
726 } else {
727 na->na_event = NA_RST_CLRD;
728 }
729 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
730 na->na_header.rqs_entry_count = 1;
731 isp_put_notify_ack(isp, na, (na_entry_t *)outp);
732 }
733 ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
734 ISP_ADD_REQUEST(isp, nxti);
735 }
736
737 static void
738 isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep)
739 {
740 int lun;
741 lun = aep->at_lun;
742 /*
743 * The firmware status (except for the QLTM_SVALID bit) indicates
744 * why this ATIO was sent to us.
745 *
746 * If QLTM_SVALID is set, the firware has recommended Sense Data.
747 *
748 * If the DISCONNECTS DISABLED bit is set in the flags field,
749 * we're still connected on the SCSI bus - i.e. the initiator
750 * did not set DiscPriv in the identify message. We don't care
751 * about this so it's ignored.
752 */
753
754 switch(aep->at_status & ~QLTM_SVALID) {
755 case AT_PATH_INVALID:
756 /*
757 * ATIO rejected by the firmware due to disabled lun.
758 */
759 isp_prt(isp, ISP_LOGERR,
760 "rejected ATIO for disabled lun %d", lun);
761 break;
762 case AT_NOCAP:
763 /*
764 * Requested Capability not available
765 * We sent an ATIO that overflowed the firmware's
766 * command resource count.
767 */
768 isp_prt(isp, ISP_LOGERR,
769 "rejected ATIO for lun %d because of command count"
770 " overflow", lun);
771 break;
772
773 case AT_BDR_MSG:
774 /*
775 * If we send an ATIO to the firmware to increment
776 * its command resource count, and the firmware is
777 * recovering from a Bus Device Reset, it returns
778 * the ATIO with this status. We set the command
779 * resource count in the Enable Lun entry and do
780 * not increment it. Therefore we should never get
781 * this status here.
782 */
783 isp_prt(isp, ISP_LOGERR, atiocope, lun,
784 GET_BUS_VAL(aep->at_iid));
785 break;
786
787 case AT_CDB: /* Got a CDB */
788 case AT_PHASE_ERROR: /* Bus Phase Sequence Error */
789 /*
790 * Punt to platform specific layer.
791 */
792 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
793 break;
794
795 case AT_RESET:
796 /*
797 * A bus reset came along an blew away this command. Why
798 * they do this in addition the async event code stuff,
799 * I dunno.
800 *
801 * Ignore it because the async event will clear things
802 * up for us.
803 */
804 isp_prt(isp, ISP_LOGWARN, atior, lun,
805 GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid));
806 break;
807
808
809 default:
810 isp_prt(isp, ISP_LOGERR,
811 "Unknown ATIO status 0x%x from initiator %d for lun %d",
812 aep->at_status, aep->at_iid, lun);
813 (void) isp_target_put_atio(isp, aep);
814 break;
815 }
816 }
817
818 static void
819 isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep)
820 {
821 int lun;
822
823 if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
824 lun = aep->at_scclun;
825 } else {
826 lun = aep->at_lun;
827 }
828
829 /*
830 * The firmware status (except for the QLTM_SVALID bit) indicates
831 * why this ATIO was sent to us.
832 *
833 * If QLTM_SVALID is set, the firware has recommended Sense Data.
834 *
835 * If the DISCONNECTS DISABLED bit is set in the flags field,
836 * we're still connected on the SCSI bus - i.e. the initiator
837 * did not set DiscPriv in the identify message. We don't care
838 * about this so it's ignored.
839 */
840
841 switch(aep->at_status & ~QLTM_SVALID) {
842 case AT_PATH_INVALID:
843 /*
844 * ATIO rejected by the firmware due to disabled lun.
845 */
846 isp_prt(isp, ISP_LOGERR,
847 "rejected ATIO2 for disabled lun %d", lun);
848 break;
849 case AT_NOCAP:
850 /*
851 * Requested Capability not available
852 * We sent an ATIO that overflowed the firmware's
853 * command resource count.
854 */
855 isp_prt(isp, ISP_LOGERR,
856 "rejected ATIO2 for lun %d- command count overflow", lun);
857 break;
858
859 case AT_BDR_MSG:
860 /*
861 * If we send an ATIO to the firmware to increment
862 * its command resource count, and the firmware is
863 * recovering from a Bus Device Reset, it returns
864 * the ATIO with this status. We set the command
865 * resource count in the Enable Lun entry and no
866 * not increment it. Therefore we should never get
867 * this status here.
868 */
869 isp_prt(isp, ISP_LOGERR, atiocope, lun, 0);
870 break;
871
872 case AT_CDB: /* Got a CDB */
873 /*
874 * Punt to platform specific layer.
875 */
876 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep);
877 break;
878
879 case AT_RESET:
880 /*
881 * A bus reset came along an blew away this command. Why
882 * they do this in addition the async event code stuff,
883 * I dunno.
884 *
885 * Ignore it because the async event will clear things
886 * up for us.
887 */
888 isp_prt(isp, ISP_LOGERR, atior, lun, aep->at_iid, 0);
889 break;
890
891
892 default:
893 isp_prt(isp, ISP_LOGERR,
894 "Unknown ATIO2 status 0x%x from initiator %d for lun %d",
895 aep->at_status, aep->at_iid, lun);
896 (void) isp_target_put_atio(isp, aep);
897 break;
898 }
899 }
900
901 static void
902 isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct)
903 {
904 void *xs;
905 int pl = ISP_LOGTDEBUG2;
906 char *fmsg = NULL;
907
908 if (ct->ct_syshandle) {
909 xs = isp_find_xs(isp, ct->ct_syshandle);
910 if (xs == NULL)
911 pl = ISP_LOGALL;
912 } else {
913 xs = NULL;
914 }
915
916 switch(ct->ct_status & ~QLTM_SVALID) {
917 case CT_OK:
918 /*
919 * There are generally 3 possibilities as to why we'd get
920 * this condition:
921 * We disconnected after receiving a CDB.
922 * We sent or received data.
923 * We sent status & command complete.
924 */
925
926 if (ct->ct_flags & CT_SENDSTATUS) {
927 break;
928 } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) {
929 /*
930 * Nothing to do in this case.
931 */
932 isp_prt(isp, pl, "CTIO- iid %d disconnected OK",
933 ct->ct_iid);
934 return;
935 }
936 break;
937
938 case CT_BDR_MSG:
939 /*
940 * Bus Device Reset message received or the SCSI Bus has
941 * been Reset; the firmware has gone to Bus Free.
942 *
943 * The firmware generates an async mailbox interupt to
944 * notify us of this and returns outstanding CTIOs with this
945 * status. These CTIOs are handled in that same way as
946 * CT_ABORTED ones, so just fall through here.
947 */
948 fmsg = "Bus Device Reset";
949 /*FALLTHROUGH*/
950 case CT_RESET:
951 if (fmsg == NULL)
952 fmsg = "Bus Reset";
953 /*FALLTHROUGH*/
954 case CT_ABORTED:
955 /*
956 * When an Abort message is received the firmware goes to
957 * Bus Free and returns all outstanding CTIOs with the status
958 * set, then sends us an Immediate Notify entry.
959 */
960 if (fmsg == NULL)
961 fmsg = "ABORT TAG message sent by Initiator";
962
963 isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg);
964 break;
965
966 case CT_INVAL:
967 /*
968 * CTIO rejected by the firmware due to disabled lun.
969 * "Cannot Happen".
970 */
971 isp_prt(isp, ISP_LOGERR,
972 "Firmware rejected CTIO for disabled lun %d",
973 ct->ct_lun);
974 break;
975
976 case CT_NOPATH:
977 /*
978 * CTIO rejected by the firmware due "no path for the
979 * nondisconnecting nexus specified". This means that
980 * we tried to access the bus while a non-disconnecting
981 * command is in process.
982 */
983 isp_prt(isp, ISP_LOGERR,
984 "Firmware rejected CTIO for bad nexus %d/%d/%d",
985 ct->ct_iid, ct->ct_tgt, ct->ct_lun);
986 break;
987
988 case CT_RSELTMO:
989 fmsg = "Reselection";
990 /*FALLTHROUGH*/
991 case CT_TIMEOUT:
992 if (fmsg == NULL)
993 fmsg = "Command";
994 isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
995 break;
996
997 case CT_PANIC:
998 if (fmsg == NULL)
999 fmsg = "Unrecoverable Error";
1000 /*FALLTHROUGH*/
1001 case CT_ERR:
1002 if (fmsg == NULL)
1003 fmsg = "Completed with Error";
1004 /*FALLTHROUGH*/
1005 case CT_PHASE_ERROR:
1006 if (fmsg == NULL)
1007 fmsg = "Phase Sequence Error";
1008 /*FALLTHROUGH*/
1009 case CT_TERMINATED:
1010 if (fmsg == NULL)
1011 fmsg = "terminated by TERMINATE TRANSFER";
1012 /*FALLTHROUGH*/
1013 case CT_NOACK:
1014 if (fmsg == NULL)
1015 fmsg = "unacknowledged Immediate Notify pending";
1016 isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
1017 break;
1018 default:
1019 isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x",
1020 ct->ct_status & ~QLTM_SVALID);
1021 break;
1022 }
1023
1024 if (xs == NULL) {
1025 /*
1026 * There may be more than one CTIO for a data transfer,
1027 * or this may be a status CTIO we're not monitoring.
1028 *
1029 * The assumption is that they'll all be returned in the
1030 * order we got them.
1031 */
1032 if (ct->ct_syshandle == 0) {
1033 if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
1034 isp_prt(isp, pl,
1035 "intermediate CTIO completed ok");
1036 } else {
1037 isp_prt(isp, pl,
1038 "unmonitored CTIO completed ok");
1039 }
1040 } else {
1041 isp_prt(isp, pl,
1042 "NO xs for CTIO (handle 0x%x) status 0x%x",
1043 ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
1044 }
1045 } else {
1046 /*
1047 * Final CTIO completed. Release DMA resources and
1048 * notify platform dependent layers.
1049 */
1050 if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) {
1051 ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1052 }
1053 isp_prt(isp, pl, "final CTIO complete");
1054 /*
1055 * The platform layer will destroy the handle if appropriate.
1056 */
1057 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1058 }
1059 }
1060
1061 static void
1062 isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct)
1063 {
1064 XS_T *xs;
1065 int pl = ISP_LOGTDEBUG2;
1066 char *fmsg = NULL;
1067
1068 if (ct->ct_syshandle) {
1069 xs = isp_find_xs(isp, ct->ct_syshandle);
1070 if (xs == NULL)
1071 pl = ISP_LOGALL;
1072 } else {
1073 xs = NULL;
1074 }
1075
1076 switch(ct->ct_status & ~QLTM_SVALID) {
1077 case CT_BUS_ERROR:
1078 isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
1079 /* FALL Through */
1080 case CT_DATA_OVER:
1081 case CT_DATA_UNDER:
1082 case CT_OK:
1083 /*
1084 * There are generally 2 possibilities as to why we'd get
1085 * this condition:
1086 * We sent or received data.
1087 * We sent status & command complete.
1088 */
1089
1090 break;
1091
1092 case CT_BDR_MSG:
1093 /*
1094 * Target Reset function received.
1095 *
1096 * The firmware generates an async mailbox interupt to
1097 * notify us of this and returns outstanding CTIOs with this
1098 * status. These CTIOs are handled in that same way as
1099 * CT_ABORTED ones, so just fall through here.
1100 */
1101 fmsg = "TARGET RESET Task Management Function Received";
1102 /*FALLTHROUGH*/
1103 case CT_RESET:
1104 if (fmsg == NULL)
1105 fmsg = "LIP Reset";
1106 /*FALLTHROUGH*/
1107 case CT_ABORTED:
1108 /*
1109 * When an Abort message is received the firmware goes to
1110 * Bus Free and returns all outstanding CTIOs with the status
1111 * set, then sends us an Immediate Notify entry.
1112 */
1113 if (fmsg == NULL)
1114 fmsg = "ABORT Task Management Function Received";
1115
1116 isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg);
1117 break;
1118
1119 case CT_INVAL:
1120 /*
1121 * CTIO rejected by the firmware - invalid data direction.
1122 */
1123 isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data directiond");
1124 break;
1125
1126 case CT_RSELTMO:
1127 fmsg = "failure to reconnect to initiator";
1128 /*FALLTHROUGH*/
1129 case CT_TIMEOUT:
1130 if (fmsg == NULL)
1131 fmsg = "command";
1132 isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
1133 break;
1134
1135 case CT_ERR:
1136 fmsg = "Completed with Error";
1137 /*FALLTHROUGH*/
1138 case CT_LOGOUT:
1139 if (fmsg == NULL)
1140 fmsg = "Port Logout";
1141 /*FALLTHROUGH*/
1142 case CT_PORTNOTAVAIL:
1143 if (fmsg == NULL)
1144 fmsg = "Port not available";
1145 case CT_PORTCHANGED:
1146 if (fmsg == NULL)
1147 fmsg = "Port Changed";
1148 case CT_NOACK:
1149 if (fmsg == NULL)
1150 fmsg = "unacknowledged Immediate Notify pending";
1151 isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
1152 break;
1153
1154 case CT_INVRXID:
1155 /*
1156 * CTIO rejected by the firmware because an invalid RX_ID.
1157 * Just print a message.
1158 */
1159 isp_prt(isp, ISP_LOGERR,
1160 "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
1161 break;
1162
1163 default:
1164 isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x",
1165 ct->ct_status & ~QLTM_SVALID);
1166 break;
1167 }
1168
1169 if (xs == NULL) {
1170 /*
1171 * There may be more than one CTIO for a data transfer,
1172 * or this may be a status CTIO we're not monitoring.
1173 *
1174 * The assumption is that they'll all be returned in the
1175 * order we got them.
1176 */
1177 if (ct->ct_syshandle == 0) {
1178 if ((ct->ct_flags & CT_SENDSTATUS) == 0) {
1179 isp_prt(isp, pl,
1180 "intermediate CTIO completed ok");
1181 } else {
1182 isp_prt(isp, pl,
1183 "unmonitored CTIO completed ok");
1184 }
1185 } else {
1186 isp_prt(isp, pl,
1187 "NO xs for CTIO (handle 0x%x) status 0x%x",
1188 ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID);
1189 }
1190 } else {
1191 if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
1192 ISP_DMAFREE(isp, xs, ct->ct_syshandle);
1193 }
1194 if (ct->ct_flags & CT_SENDSTATUS) {
1195 /*
1196 * Sent status and command complete.
1197 *
1198 * We're now really done with this command, so we
1199 * punt to the platform dependent layers because
1200 * only there can we do the appropriate command
1201 * complete thread synchronization.
1202 */
1203 isp_prt(isp, pl, "status CTIO complete");
1204 } else {
1205 /*
1206 * Final CTIO completed. Release DMA resources and
1207 * notify platform dependent layers.
1208 */
1209 isp_prt(isp, pl, "data CTIO complete");
1210 }
1211 (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
1212 /*
1213 * The platform layer will destroy the handle if appropriate.
1214 */
1215 }
1216 }
1217 #endif
1218