1 /*- 2 * Copyright (c) 1997-2009 by Matthew Jacob 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 /* 29 * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. 30 */ 31 /* 32 * Bug fixes gratefully acknowledged from: 33 * Oded Kedem <oded@kashya.com> 34 */ 35 /* 36 * Include header file appropriate for platform we're building on. 37 */ 38 39 #ifdef __NetBSD__ 40 #include <dev/ic/isp_netbsd.h> 41 #endif 42 #ifdef __FreeBSD__ 43 #include <sys/cdefs.h> 44 __FBSDID("$FreeBSD$"); 45 #include <dev/isp/isp_freebsd.h> 46 #endif 47 #ifdef __OpenBSD__ 48 #include <dev/ic/isp_openbsd.h> 49 #endif 50 #ifdef __linux__ 51 #include "isp_linux.h" 52 #endif 53 54 #ifdef ISP_TARGET_MODE 55 static const char atiocope[] = "ATIO returned for LUN %x because it was in the middle of Bus Device Reset on bus %d"; 56 static const char atior[] = "ATIO returned for LUN %x from handle 0x%x because a Bus Reset occurred on bus %d"; 57 static const char rqo[] = "%s: Request Queue Overflow"; 58 59 static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); 60 static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); 61 static void isp_handle_abts(ispsoftc_t *, abts_t *); 62 static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); 63 static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); 64 static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); 65 static void isp_handle_notify(ispsoftc_t *, in_fcentry_t *); 66 static void isp_handle_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *); 67 68 /* 69 * The Qlogic driver gets an interrupt to look at response queue entries. 70 * Some of these are status completions for initiatior mode commands, but 71 * if target mode is enabled, we get a whole wad of response queue entries 72 * to be handled here. 73 * 74 * Basically the split into 3 main groups: Lun Enable/Modification responses, 75 * SCSI Command processing, and Immediate Notification events. 76 * 77 * You start by writing a request queue entry to enable target mode (and 78 * establish some resource limitations which you can modify later). 79 * The f/w responds with a LUN ENABLE or LUN MODIFY response with 80 * the status of this action. If the enable was successful, you can expect... 81 * 82 * Response queue entries with SCSI commands encapsulate show up in an ATIO 83 * (Accept Target IO) type- sometimes with enough info to stop the command at 84 * this level. Ultimately the driver has to feed back to the f/w's request 85 * queue a sequence of CTIOs (continue target I/O) that describe data to 86 * be moved and/or status to be sent) and finally finishing with sending 87 * to the f/w's response queue an ATIO which then completes the handshake 88 * with the f/w for that command. There's a lot of variations on this theme, 89 * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel 90 * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic 91 * gist of it. 92 * 93 * The third group that can show up in the response queue are Immediate 94 * Notification events. These include things like notifications of SCSI bus 95 * resets, or Bus Device Reset messages or other messages received. This 96 * a classic oddbins area. It can get a little weird because you then turn 97 * around and acknowledge the Immediate Notify by writing an entry onto the 98 * request queue and then the f/w turns around and gives you an acknowledgement 99 * to *your* acknowledgement on the response queue (the idea being to let 100 * the f/w tell you when the event is *really* over I guess). 101 * 102 */ 103 104 105 /* 106 * A new response queue entry has arrived. The interrupt service code 107 * has already swizzled it into the platform dependent from canonical form. 108 * 109 * Because of the way this driver is designed, unfortunately most of the 110 * actual synchronization work has to be done in the platform specific 111 * code- we have no synchroniation primitives in the common code. 112 */ 113 114 int 115 isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) 116 { 117 union { 118 at2_entry_t *at2iop; 119 at2e_entry_t *at2eiop; 120 at7_entry_t *at7iop; 121 ct2_entry_t *ct2iop; 122 ct2e_entry_t *ct2eiop; 123 ct7_entry_t *ct7iop; 124 lun_entry_t *lunenp; 125 in_fcentry_t *inot_fcp; 126 in_fcentry_e_t *inote_fcp; 127 in_fcentry_24xx_t *inot_24xx; 128 na_fcentry_t *nack_fcp; 129 na_fcentry_e_t *nacke_fcp; 130 na_fcentry_24xx_t *nack_24xx; 131 isphdr_t *hp; 132 abts_t *abts; 133 abts_rsp_t *abts_rsp; 134 els_t *els; 135 void * *vp; 136 #define at2iop unp.at2iop 137 #define at2eiop unp.at2eiop 138 #define at7iop unp.at7iop 139 #define ct2iop unp.ct2iop 140 #define ct2eiop unp.ct2eiop 141 #define ct7iop unp.ct7iop 142 #define lunenp unp.lunenp 143 #define inot_fcp unp.inot_fcp 144 #define inote_fcp unp.inote_fcp 145 #define inot_24xx unp.inot_24xx 146 #define nack_fcp unp.nack_fcp 147 #define nacke_fcp unp.nacke_fcp 148 #define nack_24xx unp.nack_24xx 149 #define abts unp.abts 150 #define abts_rsp unp.abts_rsp 151 #define els unp.els 152 #define hdrp unp.hp 153 } unp; 154 uint8_t local[QENTRY_LEN]; 155 int type, len, level, rval = 1; 156 157 type = isp_get_response_type(isp, (isphdr_t *)vptr); 158 unp.vp = vptr; 159 160 ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr); 161 162 switch (type) { 163 case RQSTYPE_ATIO: 164 isp_get_atio7(isp, at7iop, (at7_entry_t *) local); 165 at7iop = (at7_entry_t *) local; 166 /* 167 * Check for and do something with commands whose 168 * IULEN extends past a single queue entry. 169 */ 170 len = at7iop->at_ta_len & 0x0fff; 171 if (len > (QENTRY_LEN - 8)) { 172 len -= (QENTRY_LEN - 8); 173 isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len); 174 while (len > 0) { 175 *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp)); 176 len -= QENTRY_LEN; 177 } 178 } 179 /* 180 * Check for a task management function 181 */ 182 if (at7iop->at_cmnd.fcp_cmnd_task_management) { 183 isp_got_tmf_24xx(isp, at7iop); 184 break; 185 } 186 /* 187 * Just go straight to outer layer for this one. 188 */ 189 isp_async(isp, ISPASYNC_TARGET_ACTION, local); 190 break; 191 192 case RQSTYPE_ATIO2: 193 if (ISP_CAP_2KLOGIN(isp)) { 194 isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); 195 } else { 196 isp_get_atio2(isp, at2iop, (at2_entry_t *) local); 197 } 198 isp_handle_atio2(isp, (at2_entry_t *) local); 199 break; 200 201 case RQSTYPE_CTIO3: 202 case RQSTYPE_CTIO2: 203 if (ISP_CAP_2KLOGIN(isp)) { 204 isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); 205 } else { 206 isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); 207 } 208 isp_handle_ctio2(isp, (ct2_entry_t *) local); 209 break; 210 211 case RQSTYPE_CTIO7: 212 isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); 213 isp_handle_ctio7(isp, (ct7_entry_t *) local); 214 break; 215 216 case RQSTYPE_NOTIFY: 217 if (IS_24XX(isp)) { 218 isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local); 219 isp_handle_notify_24xx(isp, (in_fcentry_24xx_t *)local); 220 break; 221 } 222 if (ISP_CAP_2KLOGIN(isp)) 223 isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local); 224 else 225 isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local); 226 isp_handle_notify(isp, (in_fcentry_t *)local); 227 break; 228 229 case RQSTYPE_NOTIFY_ACK: 230 /* 231 * The ISP is acknowledging our acknowledgement of an 232 * Immediate Notify entry for some asynchronous event. 233 */ 234 if (IS_24XX(isp)) { 235 isp_get_notify_ack_24xx(isp, nack_24xx, (na_fcentry_24xx_t *) local); 236 nack_24xx = (na_fcentry_24xx_t *) local; 237 if (nack_24xx->na_status != NA_OK) { 238 level = ISP_LOGINFO; 239 } else { 240 level = ISP_LOGTDEBUG1; 241 } 242 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); 243 } else { 244 if (ISP_CAP_2KLOGIN(isp)) { 245 isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local); 246 } else { 247 isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local); 248 } 249 nack_fcp = (na_fcentry_t *)local; 250 if (nack_fcp->na_status != NA_OK) { 251 level = ISP_LOGINFO; 252 } else { 253 level = ISP_LOGTDEBUG1; 254 } 255 isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid); 256 } 257 break; 258 259 case RQSTYPE_ABTS_RCVD: 260 isp_get_abts(isp, abts, (abts_t *)local); 261 isp_handle_abts(isp, (abts_t *)local); 262 break; 263 case RQSTYPE_ABTS_RSP: 264 isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); 265 abts_rsp = (abts_rsp_t *) local; 266 if (abts_rsp->abts_rsp_status) { 267 level = ISP_LOGINFO; 268 } else { 269 level = ISP_LOGTDEBUG0; 270 } 271 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, 272 abts_rsp->abts_rsp_payload.rsp.subcode1, abts_rsp->abts_rsp_payload.rsp.subcode2); 273 break; 274 default: 275 isp_prt(isp, ISP_LOGERR, "%s: unknown entry type 0x%x", __func__, type); 276 rval = 0; 277 break; 278 } 279 #undef atiop 280 #undef at2iop 281 #undef at2eiop 282 #undef at7iop 283 #undef ctiop 284 #undef ct2iop 285 #undef ct2eiop 286 #undef ct7iop 287 #undef lunenp 288 #undef inotp 289 #undef inot_fcp 290 #undef inote_fcp 291 #undef inot_24xx 292 #undef nackp 293 #undef nack_fcp 294 #undef nacke_fcp 295 #undef hack_24xx 296 #undef abts 297 #undef abts_rsp 298 #undef els 299 #undef hdrp 300 return (rval); 301 } 302 303 int 304 isp_target_put_entry(ispsoftc_t *isp, void *ap) 305 { 306 void *outp; 307 uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; 308 309 outp = isp_getrqentry(isp); 310 if (outp == NULL) { 311 isp_prt(isp, ISP_LOGWARN, rqo, __func__); 312 return (-1); 313 } 314 switch (etype) { 315 case RQSTYPE_NOTIFY_ACK: 316 if (IS_24XX(isp)) 317 isp_put_notify_24xx_ack(isp, (na_fcentry_24xx_t *)ap, 318 (na_fcentry_24xx_t *)outp); 319 else if (ISP_CAP_2KLOGIN(isp)) 320 isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *)ap, 321 (na_fcentry_e_t *)outp); 322 else 323 isp_put_notify_ack_fc(isp, ap, (na_fcentry_t *)outp); 324 break; 325 case RQSTYPE_ATIO2: 326 if (ISP_CAP_2KLOGIN(isp)) 327 isp_put_atio2e(isp, (at2e_entry_t *)ap, 328 (at2e_entry_t *)outp); 329 else 330 isp_put_atio2(isp, (at2_entry_t *)ap, 331 (at2_entry_t *)outp); 332 break; 333 case RQSTYPE_CTIO2: 334 if (ISP_CAP_2KLOGIN(isp)) 335 isp_put_ctio2e(isp, (ct2e_entry_t *)ap, 336 (ct2e_entry_t *)outp); 337 else 338 isp_put_ctio2(isp, (ct2_entry_t *)ap, 339 (ct2_entry_t *)outp); 340 break; 341 case RQSTYPE_CTIO7: 342 isp_put_ctio7(isp, (ct7_entry_t *)ap, (ct7_entry_t *)outp); 343 break; 344 case RQSTYPE_ABTS_RSP: 345 isp_put_abts_rsp(isp, (abts_rsp_t *)ap, (abts_rsp_t *)outp); 346 break; 347 default: 348 isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype); 349 return (-1); 350 } 351 ISP_TDQE(isp, __func__, isp->isp_reqidx, ap); 352 ISP_SYNC_REQUEST(isp); 353 return (0); 354 } 355 356 int 357 isp_target_put_atio(ispsoftc_t *isp, void *arg) 358 { 359 at2_entry_t *aep = arg; 360 union { 361 at2_entry_t _atio2; 362 at2e_entry_t _atio2e; 363 } atun; 364 365 ISP_MEMZERO(&atun, sizeof atun); 366 atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; 367 atun._atio2.at_header.rqs_entry_count = 1; 368 if (ISP_CAP_SCCFW(isp)) { 369 atun._atio2.at_scclun = aep->at_scclun; 370 } else { 371 atun._atio2.at_lun = (uint8_t) aep->at_lun; 372 } 373 if (ISP_CAP_2KLOGIN(isp)) { 374 atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; 375 } else { 376 atun._atio2.at_iid = aep->at_iid; 377 } 378 atun._atio2.at_rxid = aep->at_rxid; 379 atun._atio2.at_status = CT_OK; 380 return (isp_target_put_entry(isp, &atun)); 381 } 382 383 /* 384 * Command completion- both for handling cases of no resources or 385 * no blackhole driver, or other cases where we have to, inline, 386 * finish the command sanely, or for normal command completion. 387 * 388 * The 'completion' code value has the scsi status byte in the low 8 bits. 389 * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have 390 * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC 391 * values. 392 * 393 * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't 394 * NB: inline SCSI sense reporting. As such, we lose this information. XXX. 395 * 396 * For both parallel && fibre channel, we use the feature that does 397 * an automatic resource autoreplenish so we don't have then later do 398 * put of an atio to replenish the f/w's resource count. 399 */ 400 401 int 402 isp_endcmd(ispsoftc_t *isp, ...) 403 { 404 uint32_t code, hdl; 405 uint8_t sts; 406 union { 407 ct2_entry_t _ctio2; 408 ct2e_entry_t _ctio2e; 409 ct7_entry_t _ctio7; 410 } un; 411 va_list ap; 412 int vpidx, nphdl; 413 414 ISP_MEMZERO(&un, sizeof un); 415 416 if (IS_24XX(isp)) { 417 at7_entry_t *aep; 418 ct7_entry_t *cto = &un._ctio7; 419 420 va_start(ap, isp); 421 aep = va_arg(ap, at7_entry_t *); 422 nphdl = va_arg(ap, int); 423 /* 424 * Note that vpidx may equal 0xff (unknown) here 425 */ 426 vpidx = va_arg(ap, int); 427 code = va_arg(ap, uint32_t); 428 hdl = va_arg(ap, uint32_t); 429 va_end(ap); 430 isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] chan %d code %x", __func__, aep->at_rxid, vpidx, code); 431 432 sts = code & 0xff; 433 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 434 cto->ct_header.rqs_entry_count = 1; 435 cto->ct_nphdl = nphdl; 436 cto->ct_rxid = aep->at_rxid; 437 cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2]; 438 cto->ct_iid_hi = aep->at_hdr.s_id[0]; 439 cto->ct_oxid = aep->at_hdr.ox_id; 440 cto->ct_scsi_status = sts; 441 cto->ct_vpidx = vpidx; 442 cto->ct_flags = CT7_NOACK; 443 if (code & ECMD_TERMINATE) { 444 cto->ct_flags |= CT7_TERMINATE; 445 } else if (code & ECMD_SVALID) { 446 cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS; 447 cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8); 448 cto->ct_senselen = min(16, MAXRESPLEN_24XX); 449 ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp)); 450 cto->rsp.m1.ct_resp[0] = 0xf0; 451 cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 452 cto->rsp.m1.ct_resp[7] = 8; 453 cto->rsp.m1.ct_resp[12] = (code >> 16) & 0xff; 454 cto->rsp.m1.ct_resp[13] = (code >> 24) & 0xff; 455 } else if (code & ECMD_RVALID) { 456 cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS; 457 cto->ct_scsi_status |= (FCP_RSPLEN_VALID << 8); 458 cto->rsp.m1.ct_resplen = 4; 459 ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp)); 460 cto->rsp.m1.ct_resp[0] = (code >> 12) & 0xf; 461 cto->rsp.m1.ct_resp[1] = (code >> 16) & 0xff; 462 cto->rsp.m1.ct_resp[2] = (code >> 24) & 0xff; 463 cto->rsp.m1.ct_resp[3] = 0; 464 } else { 465 cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS; 466 } 467 if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl != 0) { 468 cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; 469 cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8); 470 } 471 cto->ct_syshandle = hdl; 472 } else { 473 at2_entry_t *aep; 474 ct2_entry_t *cto = &un._ctio2; 475 476 va_start(ap, isp); 477 aep = va_arg(ap, at2_entry_t *); 478 /* nphdl and vpidx are unused here. */ 479 nphdl = va_arg(ap, int); 480 vpidx = va_arg(ap, int); 481 code = va_arg(ap, uint32_t); 482 hdl = va_arg(ap, uint32_t); 483 va_end(ap); 484 485 isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] code %x", __func__, aep->at_rxid, code); 486 487 sts = code & 0xff; 488 cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 489 cto->ct_header.rqs_entry_count = 1; 490 if (ISP_CAP_SCCFW(isp) == 0) { 491 cto->ct_lun = aep->at_lun; 492 } 493 if (ISP_CAP_2KLOGIN(isp)) { 494 un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; 495 } else { 496 cto->ct_iid = aep->at_iid; 497 } 498 cto->ct_rxid = aep->at_rxid; 499 cto->rsp.m1.ct_scsi_status = sts; 500 cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; 501 if (hdl == 0) { 502 cto->ct_flags |= CT2_CCINCR; 503 } 504 if (aep->at_datalen) { 505 cto->ct_resid = aep->at_datalen; 506 cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; 507 } 508 if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { 509 cto->rsp.m1.ct_resp[0] = 0xf0; 510 cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 511 cto->rsp.m1.ct_resp[7] = 8; 512 cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 513 cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 514 cto->rsp.m1.ct_senselen = 16; 515 cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; 516 } 517 cto->ct_syshandle = hdl; 518 } 519 return (isp_target_put_entry(isp, &un)); 520 } 521 522 /* 523 * These are either broadcast events or specifically CTIO fast completion 524 */ 525 526 void 527 isp_target_async(ispsoftc_t *isp, int bus, int event) 528 { 529 isp_notify_t notify; 530 531 ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 532 notify.nt_hba = isp; 533 notify.nt_wwn = INI_ANY; 534 notify.nt_nphdl = NIL_HANDLE; 535 notify.nt_sid = PORT_ANY; 536 notify.nt_did = PORT_ANY; 537 notify.nt_tgt = TGT_ANY; 538 notify.nt_channel = bus; 539 notify.nt_lun = LUN_ANY; 540 notify.nt_tagval = TAG_ANY; 541 notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 542 543 switch (event) { 544 case ASYNC_LOOP_UP: 545 case ASYNC_PTPMODE: 546 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP UP", __func__); 547 notify.nt_ncode = NT_LINK_UP; 548 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 549 break; 550 case ASYNC_LOOP_DOWN: 551 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP DOWN", __func__); 552 notify.nt_ncode = NT_LINK_DOWN; 553 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 554 break; 555 case ASYNC_LIP_ERROR: 556 case ASYNC_LIP_NOS_OLS_RECV: 557 case ASYNC_LIP_OCCURRED: 558 case ASYNC_LOOP_RESET: 559 isp_prt(isp, ISP_LOGTDEBUG0, "%s: LIP RESET", __func__); 560 notify.nt_ncode = NT_LIP_RESET; 561 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 562 break; 563 case ASYNC_BUS_RESET: 564 case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ 565 isp_prt(isp, ISP_LOGTDEBUG0, "%s: BUS RESET", __func__); 566 notify.nt_ncode = NT_BUS_RESET; 567 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 568 break; 569 case ASYNC_DEVICE_RESET: 570 isp_prt(isp, ISP_LOGTDEBUG0, "%s: DEVICE RESET", __func__); 571 notify.nt_ncode = NT_TARGET_RESET; 572 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 573 break; 574 case ASYNC_CTIO_DONE: 575 { 576 uint8_t storage[QENTRY_LEN]; 577 isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO DONE", __func__); 578 memset(storage, 0, QENTRY_LEN); 579 if (IS_24XX(isp)) { 580 ct7_entry_t *ct = (ct7_entry_t *) storage; 581 ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 582 ct->ct_nphdl = CT7_OK; 583 ct->ct_syshandle = bus; 584 ct->ct_flags = CT7_SENDSTATUS; 585 } else { 586 /* This should also suffice for 2K login code */ 587 ct2_entry_t *ct = (ct2_entry_t *) storage; 588 ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 589 ct->ct_status = CT_OK; 590 ct->ct_syshandle = bus; 591 ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; 592 } 593 isp_async(isp, ISPASYNC_TARGET_ACTION, storage); 594 break; 595 } 596 default: 597 isp_prt(isp, ISP_LOGERR, "%s: unknown event 0x%x", __func__, event); 598 break; 599 } 600 } 601 602 /* 603 * Synthesize a message from the task management flags in a FCP_CMND_IU. 604 */ 605 static void 606 isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) 607 { 608 isp_notify_t notify; 609 static const char f1[] = "%s from N-port handle 0x%x lun %jx seq 0x%x"; 610 static const char f2[] = "unknown %s 0x%x lun %jx N-Port handle 0x%x task flags 0x%x seq 0x%x\n"; 611 uint16_t seqid, nphdl; 612 613 ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 614 notify.nt_hba = isp; 615 notify.nt_wwn = INI_ANY; 616 if (ISP_CAP_2KLOGIN(isp)) { 617 notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid; 618 nphdl = ((in_fcentry_e_t *)inp)->in_iid; 619 seqid = ((in_fcentry_e_t *)inp)->in_seqid; 620 } else { 621 notify.nt_nphdl = inp->in_iid; 622 nphdl = inp->in_iid; 623 seqid = inp->in_seqid; 624 } 625 notify.nt_sid = PORT_ANY; 626 notify.nt_did = PORT_ANY; 627 628 /* nt_tgt set in outer layers */ 629 if (ISP_CAP_SCCFW(isp)) { 630 notify.nt_lun = inp->in_scclun; 631 } else { 632 notify.nt_lun = inp->in_lun; 633 } 634 notify.nt_tagval = seqid; 635 notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 636 notify.nt_need_ack = 1; 637 notify.nt_lreserved = inp; 638 639 if (inp->in_status != IN_MSG_RECEIVED) { 640 isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags, inp->in_seqid); 641 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); 642 return; 643 } 644 645 if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { 646 isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", nphdl, notify.nt_lun, inp->in_seqid); 647 notify.nt_ncode = NT_ABORT_TASK_SET; 648 } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { 649 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", nphdl, notify.nt_lun, inp->in_seqid); 650 notify.nt_ncode = NT_CLEAR_TASK_SET; 651 } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { 652 isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", nphdl, notify.nt_lun, inp->in_seqid); 653 notify.nt_ncode = NT_LUN_RESET; 654 } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { 655 isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", nphdl, notify.nt_lun, inp->in_seqid); 656 notify.nt_ncode = NT_TARGET_RESET; 657 } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { 658 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", nphdl, notify.nt_lun, inp->in_seqid); 659 notify.nt_ncode = NT_CLEAR_ACA; 660 } else { 661 isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags, inp->in_seqid); 662 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); 663 return; 664 } 665 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 666 } 667 668 static void 669 isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) 670 { 671 isp_notify_t notify; 672 static const char f1[] = "%s from PortID 0x%06x lun %jx seq 0x%08x"; 673 static const char f2[] = "unknown Task Flag 0x%x lun %jx PortID 0x%x tag 0x%08x"; 674 fcportdb_t *lp; 675 uint16_t chan; 676 uint32_t sid, did; 677 678 ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 679 notify.nt_hba = isp; 680 notify.nt_wwn = INI_ANY; 681 notify.nt_lun = CAM_EXTLUN_BYTE_SWIZZLE(be64dec(aep->at_cmnd.fcp_cmnd_lun)); 682 notify.nt_tagval = aep->at_rxid; 683 notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 684 notify.nt_lreserved = aep; 685 sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2]; 686 did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2]; 687 if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) { 688 /* Channel has to be derived from D_ID */ 689 isp_find_chan_by_did(isp, did, &chan); 690 if (chan == ISP_NOCHAN) { 691 isp_prt(isp, ISP_LOGWARN, 692 "%s: D_ID 0x%x not found on any channel", 693 __func__, did); 694 isp_endcmd(isp, aep, NIL_HANDLE, ISP_NOCHAN, 695 ECMD_TERMINATE, 0); 696 return; 697 } 698 } else { 699 chan = 0; 700 } 701 if (isp_find_pdb_by_portid(isp, chan, sid, &lp)) 702 notify.nt_nphdl = lp->handle; 703 else 704 notify.nt_nphdl = NIL_HANDLE; 705 notify.nt_sid = sid; 706 notify.nt_did = did; 707 notify.nt_channel = chan; 708 if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_QUERY_TASK_SET) { 709 isp_prt(isp, ISP_LOGINFO, f1, "QUERY TASK SET", sid, notify.nt_lun, aep->at_rxid); 710 notify.nt_ncode = NT_QUERY_TASK_SET; 711 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_ABORT_TASK_SET) { 712 isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", sid, notify.nt_lun, aep->at_rxid); 713 notify.nt_ncode = NT_ABORT_TASK_SET; 714 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_TASK_SET) { 715 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", sid, notify.nt_lun, aep->at_rxid); 716 notify.nt_ncode = NT_CLEAR_TASK_SET; 717 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_QUERY_ASYNC_EVENT) { 718 isp_prt(isp, ISP_LOGINFO, f1, "QUERY ASYNC EVENT", sid, notify.nt_lun, aep->at_rxid); 719 notify.nt_ncode = NT_QUERY_ASYNC_EVENT; 720 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_LUN_RESET) { 721 isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", sid, notify.nt_lun, aep->at_rxid); 722 notify.nt_ncode = NT_LUN_RESET; 723 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_TGT_RESET) { 724 isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", sid, notify.nt_lun, aep->at_rxid); 725 notify.nt_ncode = NT_TARGET_RESET; 726 } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_ACA) { 727 isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", sid, notify.nt_lun, aep->at_rxid); 728 notify.nt_ncode = NT_CLEAR_ACA; 729 } else { 730 isp_prt(isp, ISP_LOGWARN, f2, aep->at_cmnd.fcp_cmnd_task_management, notify.nt_lun, sid, aep->at_rxid); 731 notify.nt_ncode = NT_UNKNOWN; 732 isp_endcmd(isp, aep, notify.nt_nphdl, chan, ECMD_RVALID | (0x4 << 12), 0); 733 return; 734 } 735 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 736 } 737 738 int 739 isp_notify_ack(ispsoftc_t *isp, void *arg) 740 { 741 char storage[QENTRY_LEN]; 742 743 /* 744 * This is in case a Task Management Function ends up here. 745 */ 746 if (IS_24XX(isp) && ((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO) { 747 at7_entry_t *aep = arg; 748 return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0)); 749 } 750 751 ISP_MEMZERO(storage, QENTRY_LEN); 752 if (IS_24XX(isp)) { 753 in_fcentry_24xx_t *in = arg; 754 na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; 755 756 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 757 na->na_header.rqs_entry_count = 1; 758 na->na_nphdl = in->in_nphdl; 759 na->na_flags = in->in_flags; 760 na->na_status = in->in_status; 761 na->na_status_subcode = in->in_status_subcode; 762 na->na_fwhandle = in->in_fwhandle; 763 na->na_rxid = in->in_rxid; 764 na->na_oxid = in->in_oxid; 765 na->na_vpidx = in->in_vpidx; 766 if (in->in_status == IN24XX_SRR_RCVD) { 767 na->na_srr_rxid = in->in_srr_rxid; 768 na->na_srr_reloff_hi = in->in_srr_reloff_hi; 769 na->na_srr_reloff_lo = in->in_srr_reloff_lo; 770 na->na_srr_iu = in->in_srr_iu; 771 /* 772 * Whether we're accepting the SRR or rejecting 773 * it is determined by looking at the in_reserved 774 * field in the original notify structure. 775 */ 776 if (in->in_reserved) { 777 na->na_srr_flags = 1; 778 na->na_srr_reject_vunique = 0; 779 /* Unable to perform this command at this time. */ 780 na->na_srr_reject_code = 9; 781 /* Unable to supply the requested data. */ 782 na->na_srr_reject_explanation = 0x2a; 783 } 784 } 785 } else { 786 in_fcentry_t *in = arg; 787 na_fcentry_t *na = (na_fcentry_t *) storage; 788 int iid; 789 790 ISP_MEMCPY(storage, arg, sizeof (isphdr_t)); 791 if (ISP_CAP_2KLOGIN(isp)) { 792 iid = ((in_fcentry_e_t *)in)->in_iid; 793 ((na_fcentry_e_t *)na)->na_iid = iid; 794 } else { 795 iid = in->in_iid; 796 na->na_iid = iid; 797 } 798 na->na_task_flags = in->in_task_flags & TASK_FLAGS_RESERVED_MASK; 799 na->na_seqid = in->in_seqid; 800 na->na_status = in->in_status; 801 na->na_flags = NAFC_RCOUNT; 802 /* We do not modify resource counts for LIP resets */ 803 if (in->in_status == IN_RESET) 804 na->na_flags = NAFC_RST_CLRD; 805 if (in->in_status == IN_MSG_RECEIVED) { 806 na->na_flags |= NAFC_TVALID; 807 na->na_response = 0; /* XXX SUCCEEDED XXX */ 808 } 809 na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 810 na->na_header.rqs_entry_count = 1; 811 isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x seqid %x flags %x tflags %x response %x", iid, na->na_seqid, 812 na->na_flags, na->na_task_flags, na->na_response); 813 } 814 return (isp_target_put_entry(isp, &storage)); 815 } 816 817 int 818 isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno) 819 { 820 char storage[QENTRY_LEN]; 821 uint16_t tmpw; 822 uint8_t tmpb; 823 abts_t *abts = arg; 824 abts_rsp_t *rsp = (abts_rsp_t *) storage; 825 826 if (!IS_24XX(isp)) { 827 isp_prt(isp, ISP_LOGERR, "%s: called for non-24XX card", __func__); 828 return (0); 829 } 830 831 if (abts->abts_header.rqs_entry_type != RQSTYPE_ABTS_RCVD) { 832 isp_prt(isp, ISP_LOGERR, "%s: called for non-ABTS entry (0x%x)", __func__, abts->abts_header.rqs_entry_type); 833 return (0); 834 } 835 836 ISP_MEMCPY(rsp, abts, QENTRY_LEN); 837 rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP; 838 839 /* 840 * Swap destination and source for response. 841 */ 842 rsp->abts_rsp_r_ctl = BA_ACC; 843 tmpw = rsp->abts_rsp_did_lo; 844 tmpb = rsp->abts_rsp_did_hi; 845 rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo; 846 rsp->abts_rsp_did_hi = rsp->abts_rsp_sid_hi; 847 rsp->abts_rsp_sid_lo = tmpw; 848 rsp->abts_rsp_sid_hi = tmpb; 849 850 rsp->abts_rsp_f_ctl_hi ^= 0x80; /* invert Exchange Context */ 851 rsp->abts_rsp_f_ctl_hi &= ~0x7f; /* clear Sequence Initiator and other bits */ 852 rsp->abts_rsp_f_ctl_hi |= 0x10; /* abort the whole exchange */ 853 rsp->abts_rsp_f_ctl_hi |= 0x8; /* last data frame of sequence */ 854 rsp->abts_rsp_f_ctl_hi |= 0x1; /* transfer Sequence Initiative */ 855 rsp->abts_rsp_f_ctl_lo = 0; 856 857 if (errno == 0) { 858 uint16_t rx_id, ox_id; 859 860 rx_id = rsp->abts_rsp_rx_id; 861 ox_id = rsp->abts_rsp_ox_id; 862 ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc)); 863 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); 864 rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id; 865 rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id; 866 rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff; 867 } else { 868 ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc)); 869 switch (errno) { 870 case ENOMEM: 871 rsp->abts_rsp_payload.ba_rjt.reason = 5; /* Logical Unit Busy */ 872 break; 873 default: 874 rsp->abts_rsp_payload.ba_rjt.reason = 9; /* Unable to perform command request */ 875 break; 876 } 877 } 878 return (isp_target_put_entry(isp, rsp)); 879 } 880 881 static void 882 isp_handle_abts(ispsoftc_t *isp, abts_t *abts) 883 { 884 isp_notify_t notify, *nt = ¬ify; 885 fcportdb_t *lp; 886 uint16_t chan; 887 uint32_t sid, did; 888 889 did = (abts->abts_did_hi << 16) | abts->abts_did_lo; 890 sid = (abts->abts_sid_hi << 16) | abts->abts_sid_lo; 891 ISP_MEMZERO(nt, sizeof (isp_notify_t)); 892 893 nt->nt_hba = isp; 894 nt->nt_did = did; 895 nt->nt_nphdl = abts->abts_nphdl; 896 nt->nt_sid = sid; 897 if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) { 898 /* Channel has to be derived from D_ID */ 899 isp_find_chan_by_did(isp, did, &chan); 900 if (chan == ISP_NOCHAN) { 901 isp_prt(isp, ISP_LOGWARN, 902 "%s: D_ID 0x%x not found on any channel", 903 __func__, did); 904 isp_acknak_abts(isp, abts, ENXIO); 905 return; 906 } 907 } else 908 chan = 0; 909 nt->nt_tgt = FCPARAM(isp, chan)->isp_wwpn; 910 if (isp_find_pdb_by_handle(isp, chan, abts->abts_nphdl, &lp)) 911 nt->nt_wwn = lp->port_wwn; 912 else 913 nt->nt_wwn = INI_ANY; 914 nt->nt_lun = LUN_ANY; 915 nt->nt_need_ack = 1; 916 nt->nt_tagval = abts->abts_rxid_task; 917 nt->nt_tagval |= (((uint64_t) abts->abts_rxid_abts) << 32); 918 isp_prt(isp, ISP_LOGTINFO, "[0x%x] ABTS from N-Port handle 0x%x" 919 " Port 0x%06x for task 0x%x (rx_id 0x%04x ox_id 0x%04x)", 920 abts->abts_rxid_abts, abts->abts_nphdl, sid, abts->abts_rxid_task, 921 abts->abts_rx_id, abts->abts_ox_id); 922 nt->nt_channel = chan; 923 nt->nt_ncode = NT_ABORT_TASK; 924 nt->nt_lreserved = abts; 925 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 926 } 927 928 static void 929 isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) 930 { 931 fcportdb_t *lp; 932 int lun, iid; 933 934 if (ISP_CAP_SCCFW(isp)) { 935 lun = aep->at_scclun; 936 } else { 937 lun = aep->at_lun; 938 } 939 940 if (ISP_CAP_2KLOGIN(isp)) { 941 iid = ((at2e_entry_t *)aep)->at_iid; 942 } else { 943 iid = aep->at_iid; 944 } 945 946 /* 947 * The firmware status (except for the QLTM_SVALID bit) indicates 948 * why this ATIO was sent to us. 949 * 950 * If QLTM_SVALID is set, the firware has recommended Sense Data. 951 * 952 * If the DISCONNECTS DISABLED bit is set in the flags field, 953 * we're still connected on the SCSI bus - i.e. the initiator 954 * did not set DiscPriv in the identify message. We don't care 955 * about this so it's ignored. 956 */ 957 958 switch (aep->at_status & ~QLTM_SVALID) { 959 case AT_PATH_INVALID: 960 /* 961 * ATIO rejected by the firmware due to disabled lun. 962 */ 963 isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for disabled lun %x", lun); 964 break; 965 case AT_NOCAP: 966 /* 967 * Requested Capability not available 968 * We sent an ATIO that overflowed the firmware's 969 * command resource count. 970 */ 971 isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for lun %x- command count overflow", lun); 972 break; 973 974 case AT_BDR_MSG: 975 /* 976 * If we send an ATIO to the firmware to increment 977 * its command resource count, and the firmware is 978 * recovering from a Bus Device Reset, it returns 979 * the ATIO with this status. We set the command 980 * resource count in the Enable Lun entry and no 981 * not increment it. Therefore we should never get 982 * this status here. 983 */ 984 isp_prt(isp, ISP_LOGERR, atiocope, lun, 0); 985 break; 986 987 case AT_CDB: /* Got a CDB */ 988 989 /* Make sure we have this inititor in port database. */ 990 if (!IS_2100(isp) && 991 (isp_find_pdb_by_handle(isp, 0, iid, &lp) == 0 || 992 lp->state == FC_PORTDB_STATE_ZOMBIE)) { 993 fcparam *fcp = FCPARAM(isp, 0); 994 uint64_t wwpn = 995 (((uint64_t) aep->at_wwpn[0]) << 48) | 996 (((uint64_t) aep->at_wwpn[1]) << 32) | 997 (((uint64_t) aep->at_wwpn[2]) << 16) | 998 (((uint64_t) aep->at_wwpn[3]) << 0); 999 isp_add_wwn_entry(isp, 0, wwpn, INI_NONE, 1000 iid, PORT_ANY, 0); 1001 if (fcp->isp_loopstate > LOOP_LTEST_DONE) 1002 fcp->isp_loopstate = LOOP_LTEST_DONE; 1003 isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 0, 1004 ISPASYNC_CHANGE_PDB, iid, 0x06, 0xff); 1005 } 1006 1007 /* Punt to platform specific layer. */ 1008 isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 1009 break; 1010 1011 case AT_RESET: 1012 /* 1013 * A bus reset came along an blew away this command. Why 1014 * they do this in addition the async event code stuff, 1015 * I dunno. 1016 * 1017 * Ignore it because the async event will clear things 1018 * up for us. 1019 */ 1020 isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); 1021 break; 1022 1023 1024 default: 1025 isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from handle %d for lun %x", aep->at_status, iid, lun); 1026 (void) isp_target_put_atio(isp, aep); 1027 break; 1028 } 1029 } 1030 1031 static void 1032 isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) 1033 { 1034 void *xs; 1035 int pl = ISP_LOGTDEBUG2; 1036 char *fmsg = NULL; 1037 1038 if (ct->ct_syshandle) { 1039 xs = isp_find_xs(isp, ct->ct_syshandle); 1040 if (xs == NULL) { 1041 pl = ISP_LOGALL; 1042 } 1043 } else { 1044 xs = NULL; 1045 } 1046 1047 switch (ct->ct_status & ~QLTM_SVALID) { 1048 case CT_BUS_ERROR: 1049 isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 1050 /* FALL Through */ 1051 case CT_DATA_OVER: 1052 case CT_DATA_UNDER: 1053 case CT_OK: 1054 /* 1055 * There are generally 2 possibilities as to why we'd get 1056 * this condition: 1057 * We sent or received data. 1058 * We sent status & command complete. 1059 */ 1060 1061 break; 1062 1063 case CT_BDR_MSG: 1064 /* 1065 * Target Reset function received. 1066 * 1067 * The firmware generates an async mailbox interrupt to 1068 * notify us of this and returns outstanding CTIOs with this 1069 * status. These CTIOs are handled in that same way as 1070 * CT_ABORTED ones, so just fall through here. 1071 */ 1072 fmsg = "TARGET RESET"; 1073 /*FALLTHROUGH*/ 1074 case CT_RESET: 1075 if (fmsg == NULL) 1076 fmsg = "LIP Reset"; 1077 /*FALLTHROUGH*/ 1078 case CT_ABORTED: 1079 /* 1080 * When an Abort message is received the firmware goes to 1081 * Bus Free and returns all outstanding CTIOs with the status 1082 * set, then sends us an Immediate Notify entry. 1083 */ 1084 if (fmsg == NULL) { 1085 fmsg = "ABORT"; 1086 } 1087 1088 isp_prt(isp, ISP_LOGTDEBUG0, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 1089 break; 1090 1091 case CT_INVAL: 1092 /* 1093 * CTIO rejected by the firmware - invalid data direction. 1094 */ 1095 isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction"); 1096 break; 1097 1098 case CT_RSELTMO: 1099 fmsg = "failure to reconnect to initiator"; 1100 /*FALLTHROUGH*/ 1101 case CT_TIMEOUT: 1102 if (fmsg == NULL) 1103 fmsg = "command"; 1104 isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); 1105 break; 1106 1107 case CT_ERR: 1108 fmsg = "Completed with Error"; 1109 /*FALLTHROUGH*/ 1110 case CT_LOGOUT: 1111 if (fmsg == NULL) 1112 fmsg = "Port Logout"; 1113 /*FALLTHROUGH*/ 1114 case CT_PORTUNAVAIL: 1115 if (fmsg == NULL) 1116 fmsg = "Port not available"; 1117 /*FALLTHROUGH*/ 1118 case CT_PORTCHANGED: 1119 if (fmsg == NULL) 1120 fmsg = "Port Changed"; 1121 /*FALLTHROUGH*/ 1122 case CT_NOACK: 1123 if (fmsg == NULL) 1124 fmsg = "unacknowledged Immediate Notify pending"; 1125 isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 1126 break; 1127 1128 case CT_INVRXID: 1129 /* 1130 * CTIO rejected by the firmware because an invalid RX_ID. 1131 * Just print a message. 1132 */ 1133 isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1134 break; 1135 1136 default: 1137 isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", ct->ct_status & ~QLTM_SVALID); 1138 break; 1139 } 1140 1141 if (xs == NULL) { 1142 /* 1143 * There may be more than one CTIO for a data transfer, 1144 * or this may be a status CTIO we're not monitoring. 1145 * 1146 * The assumption is that they'll all be returned in the 1147 * order we got them. 1148 */ 1149 if (ct->ct_syshandle == 0) { 1150 if ((ct->ct_flags & CT2_SENDSTATUS) == 0) { 1151 isp_prt(isp, pl, "intermediate CTIO completed ok"); 1152 } else { 1153 isp_prt(isp, pl, "unmonitored CTIO completed ok"); 1154 } 1155 } else { 1156 isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1157 } 1158 } else { 1159 if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { 1160 ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1161 } 1162 if (ct->ct_flags & CT2_SENDSTATUS) { 1163 /* 1164 * Sent status and command complete. 1165 * 1166 * We're now really done with this command, so we 1167 * punt to the platform dependent layers because 1168 * only there can we do the appropriate command 1169 * complete thread synchronization. 1170 */ 1171 isp_prt(isp, pl, "status CTIO complete"); 1172 } else { 1173 /* 1174 * Final CTIO completed. Release DMA resources and 1175 * notify platform dependent layers. 1176 */ 1177 isp_prt(isp, pl, "data CTIO complete"); 1178 } 1179 isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1180 /* 1181 * The platform layer will destroy the handle if appropriate. 1182 */ 1183 } 1184 } 1185 1186 static void 1187 isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) 1188 { 1189 void *xs; 1190 int pl = ISP_LOGTDEBUG2; 1191 char *fmsg = NULL; 1192 1193 if (ct->ct_syshandle) { 1194 xs = isp_find_xs(isp, ct->ct_syshandle); 1195 if (xs == NULL) { 1196 pl = ISP_LOGALL; 1197 } 1198 } else { 1199 xs = NULL; 1200 } 1201 1202 switch (ct->ct_nphdl) { 1203 case CT7_BUS_ERROR: 1204 isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 1205 /* FALL Through */ 1206 case CT7_DATA_OVER: 1207 case CT7_DATA_UNDER: 1208 case CT7_OK: 1209 /* 1210 * There are generally 2 possibilities as to why we'd get 1211 * this condition: 1212 * We sent or received data. 1213 * We sent status & command complete. 1214 */ 1215 1216 break; 1217 1218 case CT7_RESET: 1219 if (fmsg == NULL) { 1220 fmsg = "LIP Reset"; 1221 } 1222 /*FALLTHROUGH*/ 1223 case CT7_ABORTED: 1224 /* 1225 * When an Abort message is received the firmware goes to 1226 * Bus Free and returns all outstanding CTIOs with the status 1227 * set, then sends us an Immediate Notify entry. 1228 */ 1229 if (fmsg == NULL) { 1230 fmsg = "ABORT"; 1231 } 1232 isp_prt(isp, ISP_LOGTDEBUG0, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 1233 break; 1234 1235 case CT7_TIMEOUT: 1236 if (fmsg == NULL) { 1237 fmsg = "command"; 1238 } 1239 isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); 1240 break; 1241 1242 case CT7_ERR: 1243 fmsg = "Completed with Error"; 1244 /*FALLTHROUGH*/ 1245 case CT7_LOGOUT: 1246 if (fmsg == NULL) { 1247 fmsg = "Port Logout"; 1248 } 1249 /*FALLTHROUGH*/ 1250 case CT7_PORTUNAVAIL: 1251 if (fmsg == NULL) { 1252 fmsg = "Port not available"; 1253 } 1254 /*FALLTHROUGH*/ 1255 case CT7_PORTCHANGED: 1256 if (fmsg == NULL) { 1257 fmsg = "Port Changed"; 1258 } 1259 isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 1260 break; 1261 1262 case CT7_INVRXID: 1263 /* 1264 * CTIO rejected by the firmware because an invalid RX_ID. 1265 * Just print a message. 1266 */ 1267 isp_prt(isp, ISP_LOGWARN, "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1268 break; 1269 1270 case CT7_REASSY_ERR: 1271 isp_prt(isp, ISP_LOGWARN, "reassembly error"); 1272 break; 1273 1274 case CT7_SRR: 1275 isp_prt(isp, ISP_LOGTDEBUG0, "SRR received"); 1276 break; 1277 1278 default: 1279 isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", ct->ct_nphdl); 1280 break; 1281 } 1282 1283 if (xs == NULL) { 1284 /* 1285 * There may be more than one CTIO for a data transfer, 1286 * or this may be a status CTIO we're not monitoring. 1287 * 1288 * The assumption is that they'll all be returned in the 1289 * order we got them. 1290 */ 1291 if (ct->ct_syshandle == 0) { 1292 if (ct->ct_flags & CT7_TERMINATE) { 1293 isp_prt(isp, ISP_LOGINFO, "termination of [RX_ID 0x%x] complete", ct->ct_rxid); 1294 } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) { 1295 isp_prt(isp, pl, "intermediate CTIO completed ok"); 1296 } else { 1297 isp_prt(isp, pl, "unmonitored CTIO completed ok"); 1298 } 1299 } else { 1300 isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_nphdl); 1301 } 1302 } else { 1303 if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) { 1304 ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1305 } 1306 if (ct->ct_flags & CT7_SENDSTATUS) { 1307 /* 1308 * Sent status and command complete. 1309 * 1310 * We're now really done with this command, so we 1311 * punt to the platform dependent layers because 1312 * only there can we do the appropriate command 1313 * complete thread synchronization. 1314 */ 1315 isp_prt(isp, pl, "status CTIO complete"); 1316 } else { 1317 /* 1318 * Final CTIO completed. Release DMA resources and 1319 * notify platform dependent layers. 1320 */ 1321 isp_prt(isp, pl, "data CTIO complete"); 1322 } 1323 isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1324 /* 1325 * The platform layer will destroy the handle if appropriate. 1326 */ 1327 } 1328 } 1329 1330 static void 1331 isp_handle_notify(ispsoftc_t *isp, in_fcentry_t *inp) 1332 { 1333 fcportdb_t *lp; 1334 uint64_t wwn; 1335 uint32_t sid; 1336 uint16_t nphdl, status; 1337 isp_notify_t notify; 1338 1339 status = inp->in_status; 1340 isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify, status=0x%x seqid=0x%x", 1341 status, inp->in_seqid); 1342 switch (status) { 1343 case IN_MSG_RECEIVED: 1344 case IN_IDE_RECEIVED: 1345 isp_got_msg_fc(isp, inp); 1346 return; 1347 case IN_RSRC_UNAVAIL: 1348 isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); 1349 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); 1350 return; 1351 } 1352 1353 if (ISP_CAP_2KLOGIN(isp)) 1354 nphdl = ((in_fcentry_e_t *)inp)->in_iid; 1355 else 1356 nphdl = inp->in_iid; 1357 if (isp_find_pdb_by_handle(isp, 0, nphdl, &lp)) { 1358 wwn = lp->port_wwn; 1359 sid = lp->portid; 1360 } else { 1361 wwn = INI_ANY; 1362 sid = PORT_ANY; 1363 } 1364 1365 ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 1366 notify.nt_hba = isp; 1367 notify.nt_wwn = wwn; 1368 notify.nt_tgt = FCPARAM(isp, 0)->isp_wwpn; 1369 notify.nt_nphdl = nphdl; 1370 notify.nt_sid = sid; 1371 notify.nt_did = PORT_ANY; 1372 if (ISP_CAP_SCCFW(isp)) 1373 notify.nt_lun = inp->in_scclun; 1374 else 1375 notify.nt_lun = inp->in_lun; 1376 notify.nt_tagval = inp->in_seqid; 1377 notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 1378 notify.nt_need_ack = 1; 1379 notify.nt_channel = 0; 1380 notify.nt_lreserved = inp; 1381 1382 switch (status) { 1383 case IN_RESET: 1384 notify.nt_ncode = NT_BUS_RESET; 1385 break; 1386 case IN_PORT_LOGOUT: 1387 notify.nt_ncode = NT_LOGOUT; 1388 break; 1389 case IN_ABORT_TASK: 1390 notify.nt_ncode = NT_ABORT_TASK; 1391 break; 1392 case IN_GLOBAL_LOGO: 1393 notify.nt_ncode = NT_GLOBAL_LOGOUT; 1394 break; 1395 case IN_PORT_CHANGED: 1396 notify.nt_ncode = NT_CHANGED; 1397 break; 1398 default: 1399 isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x)", 1400 __func__, status); 1401 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp); 1402 return; 1403 } 1404 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 1405 } 1406 1407 static void 1408 isp_handle_notify_24xx(ispsoftc_t *isp, in_fcentry_24xx_t *inot) 1409 { 1410 uint8_t chan; 1411 uint16_t nphdl, prli_options = 0; 1412 uint32_t portid; 1413 fcportdb_t *lp; 1414 char *msg = NULL; 1415 uint8_t *ptr = (uint8_t *)inot; 1416 uint64_t wwpn = INI_NONE, wwnn = INI_NONE; 1417 isp_notify_t notify; 1418 char buf[16]; 1419 1420 nphdl = inot->in_nphdl; 1421 if (nphdl != NIL_HANDLE) { 1422 portid = inot->in_portid_hi << 16 | inot->in_portid_lo; 1423 } else { 1424 portid = PORT_ANY; 1425 } 1426 1427 chan = ISP_GET_VPIDX(isp, inot->in_vpidx); 1428 if (chan >= isp->isp_nchan && 1429 inot->in_status != IN24XX_LIP_RESET && 1430 inot->in_status != IN24XX_LINK_RESET && 1431 inot->in_status != IN24XX_LINK_FAILED) { 1432 isp_prt(isp, ISP_LOGWARN, "%s: Received INOT with status %x on VP %x", 1433 __func__, inot->in_status, chan); 1434 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); 1435 return; 1436 } 1437 1438 switch (inot->in_status) { 1439 case IN24XX_ELS_RCVD: 1440 { 1441 /* 1442 * Note that we're just getting notification that an ELS was 1443 * received (possibly with some associated information sent 1444 * upstream). This is *not* the same as being given the ELS 1445 * frame to accept or reject. 1446 */ 1447 switch (inot->in_status_subcode) { 1448 case LOGO: 1449 msg = "LOGO"; 1450 wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]); 1451 isp_del_wwn_entry(isp, chan, wwpn, nphdl, portid); 1452 break; 1453 case PRLO: 1454 msg = "PRLO"; 1455 break; 1456 case PLOGI: 1457 msg = "PLOGI"; 1458 wwnn = be64dec(&ptr[IN24XX_PLOGI_WWNN_OFF]); 1459 wwpn = be64dec(&ptr[IN24XX_PLOGI_WWPN_OFF]); 1460 isp_add_wwn_entry(isp, chan, wwpn, wwnn, 1461 nphdl, portid, prli_options); 1462 break; 1463 case PRLI: 1464 msg = "PRLI"; 1465 prli_options = inot->in_prli_options; 1466 if (inot->in_flags & IN24XX_FLAG_PN_NN_VALID) 1467 wwnn = be64dec(&ptr[IN24XX_PRLI_WWNN_OFF]); 1468 wwpn = be64dec(&ptr[IN24XX_PRLI_WWPN_OFF]); 1469 isp_add_wwn_entry(isp, chan, wwpn, wwnn, 1470 nphdl, portid, prli_options); 1471 break; 1472 case PDISC: 1473 msg = "PDISC"; 1474 break; 1475 case ADISC: 1476 msg = "ADISC"; 1477 break; 1478 default: 1479 ISP_SNPRINTF(buf, sizeof (buf), "ELS 0x%x", 1480 inot->in_status_subcode); 1481 msg = buf; 1482 break; 1483 } 1484 if (inot->in_flags & IN24XX_FLAG_PUREX_IOCB) { 1485 isp_prt(isp, ISP_LOGERR, "%s Chan %d ELS N-port handle %x" 1486 " PortID 0x%06x marked as needing a PUREX response", 1487 msg, chan, nphdl, portid); 1488 break; 1489 } 1490 isp_prt(isp, ISP_LOGTDEBUG0, "%s Chan %d ELS N-port handle %x" 1491 " PortID 0x%06x RX_ID 0x%x OX_ID 0x%x", msg, chan, nphdl, 1492 portid, inot->in_rxid, inot->in_oxid); 1493 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); 1494 break; 1495 } 1496 1497 case IN24XX_PORT_LOGOUT: 1498 msg = "PORT LOGOUT"; 1499 if (isp_find_pdb_by_handle(isp, chan, nphdl, &lp)) 1500 isp_del_wwn_entry(isp, chan, lp->port_wwn, nphdl, lp->portid); 1501 /* FALLTHROUGH */ 1502 case IN24XX_PORT_CHANGED: 1503 if (msg == NULL) 1504 msg = "PORT CHANGED"; 1505 /* FALLTHROUGH */ 1506 case IN24XX_LIP_RESET: 1507 if (msg == NULL) 1508 msg = "LIP RESET"; 1509 isp_prt(isp, ISP_LOGINFO, "Chan %d %s (sub-status 0x%x) for " 1510 "N-port handle 0x%x", 1511 chan, msg, inot->in_status_subcode, nphdl); 1512 1513 /* 1514 * All subcodes here are irrelevant. What is relevant 1515 * is that we need to terminate all active commands from 1516 * this initiator (known by N-port handle). 1517 */ 1518 /* XXX IMPLEMENT XXX */ 1519 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); 1520 break; 1521 1522 case IN24XX_SRR_RCVD: 1523 #ifdef ISP_TARGET_MODE 1524 ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 1525 notify.nt_hba = isp; 1526 notify.nt_wwn = INI_ANY; 1527 notify.nt_tgt = FCPARAM(isp, chan)->isp_wwpn; 1528 notify.nt_nphdl = nphdl; 1529 notify.nt_sid = portid; 1530 notify.nt_did = PORT_ANY; 1531 notify.nt_lun = LUN_ANY; 1532 notify.nt_tagval = inot->in_rxid; 1533 notify.nt_tagval |= ((uint64_t)inot->in_srr_rxid << 32); 1534 notify.nt_need_ack = 1; 1535 notify.nt_channel = chan; 1536 notify.nt_lreserved = inot; 1537 notify.nt_ncode = NT_SRR; 1538 isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 1539 break; 1540 #else 1541 if (msg == NULL) 1542 msg = "SRR RCVD"; 1543 /* FALLTHROUGH */ 1544 #endif 1545 case IN24XX_LINK_RESET: 1546 if (msg == NULL) 1547 msg = "LINK RESET"; 1548 case IN24XX_LINK_FAILED: 1549 if (msg == NULL) 1550 msg = "LINK FAILED"; 1551 default: 1552 isp_prt(isp, ISP_LOGWARN, "Chan %d %s", chan, msg); 1553 isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); 1554 break; 1555 } 1556 } 1557 #endif 1558