1 1.38 rillig -/* $NetBSD: isp_target.c,v 1.38 2024/09/08 09:36:50 rillig Exp $ */ 2 1.30 mjacob /*- 3 1.31 mjacob * Copyright (c) 1997-2008 by Matthew Jacob 4 1.31 mjacob * All rights reserved. 5 1.31 mjacob * 6 1.31 mjacob * Redistribution and use in source and binary forms, with or without 7 1.31 mjacob * modification, are permitted provided that the following conditions 8 1.31 mjacob * are met: 9 1.31 mjacob * 10 1.31 mjacob * 1. Redistributions of source code must retain the above copyright 11 1.31 mjacob * notice, this list of conditions and the following disclaimer. 12 1.31 mjacob * 2. Redistributions in binary form must reproduce the above copyright 13 1.31 mjacob * notice, this list of conditions and the following disclaimer in the 14 1.31 mjacob * documentation and/or other materials provided with the distribution. 15 1.31 mjacob * 16 1.31 mjacob * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.31 mjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.31 mjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.31 mjacob * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.31 mjacob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.31 mjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.31 mjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.31 mjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.31 mjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.31 mjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.31 mjacob * SUCH DAMAGE. 27 1.31 mjacob * 28 1.31 mjacob * 29 1.31 mjacob * Alternatively, this software may be distributed under the terms of the 30 1.31 mjacob * the GNU Public License ("GPL") with platforms where the prevalant license 31 1.31 mjacob * is the GNU Public License: 32 1.31 mjacob * 33 1.31 mjacob * This program is free software; you can redistribute it and/or modify 34 1.31 mjacob * it under the terms of The Version 2 GNU General Public License as published 35 1.31 mjacob * by the Free Software Foundation. 36 1.31 mjacob * 37 1.31 mjacob * This program is distributed in the hope that it will be useful, 38 1.31 mjacob * but WITHOUT ANY WARRANTY; without even the implied warranty of 39 1.31 mjacob * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 40 1.31 mjacob * GNU General Public License for more details. 41 1.31 mjacob * 42 1.31 mjacob * You should have received a copy of the GNU General Public License 43 1.31 mjacob * along with this program; if not, write to the Free Software 44 1.31 mjacob * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 45 1.31 mjacob * 46 1.30 mjacob * 47 1.31 mjacob * Matthew Jacob 48 1.31 mjacob * Feral Software 49 1.31 mjacob * 421 Laurel Avenue 50 1.31 mjacob * Menlo Park, CA 94025 51 1.31 mjacob * USA 52 1.30 mjacob * 53 1.31 mjacob * gplbsd at feral com 54 1.1 mjacob */ 55 1.30 mjacob /* 56 1.30 mjacob * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. 57 1.30 mjacob */ 58 1.1 mjacob /* 59 1.18 mjacob * Bug fixes gratefully acknowledged from: 60 1.30 mjacob * Oded Kedem <oded (at) kashya.com> 61 1.18 mjacob */ 62 1.18 mjacob /* 63 1.1 mjacob * Include header file appropriate for platform we're building on. 64 1.1 mjacob */ 65 1.16 lukem 66 1.1 mjacob #ifdef __NetBSD__ 67 1.30 mjacob #include <sys/cdefs.h> 68 1.38 rillig __KERNEL_RCSID(0, "$NetBSD: isp_target.c,v 1.38 2024/09/08 09:36:50 rillig Exp $"); 69 1.1 mjacob #include <dev/ic/isp_netbsd.h> 70 1.1 mjacob #endif 71 1.1 mjacob #ifdef __FreeBSD__ 72 1.30 mjacob #include <sys/cdefs.h> 73 1.30 mjacob __FBSDID("$FreeBSD:$"); 74 1.1 mjacob #include <dev/isp/isp_freebsd.h> 75 1.1 mjacob #endif 76 1.1 mjacob #ifdef __OpenBSD__ 77 1.1 mjacob #include <dev/ic/isp_openbsd.h> 78 1.1 mjacob #endif 79 1.1 mjacob #ifdef __linux__ 80 1.1 mjacob #include "isp_linux.h" 81 1.1 mjacob #endif 82 1.1 mjacob 83 1.1 mjacob #ifdef ISP_TARGET_MODE 84 1.33 mjacob static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset on bus %d"; 85 1.33 mjacob static const char atior[] = "ATIO returned on for lun %d on from loopid %d because a Bus Reset occurred on bus %d"; 86 1.33 mjacob static const char rqo[] = "%s: Request Queue Overflow"; 87 1.1 mjacob 88 1.30 mjacob static void isp_got_msg(ispsoftc_t *, in_entry_t *); 89 1.30 mjacob static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); 90 1.30 mjacob static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); 91 1.30 mjacob static void isp_handle_atio(ispsoftc_t *, at_entry_t *); 92 1.30 mjacob static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); 93 1.30 mjacob static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *); 94 1.30 mjacob static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); 95 1.30 mjacob static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); 96 1.31 mjacob static void isp_handle_24xx_inotify(ispsoftc_t *, in_fcentry_24xx_t *); 97 1.1 mjacob 98 1.1 mjacob /* 99 1.1 mjacob * The Qlogic driver gets an interrupt to look at response queue entries. 100 1.37 andvar * Some of these are status completions for initiator mode commands, but 101 1.1 mjacob * if target mode is enabled, we get a whole wad of response queue entries 102 1.1 mjacob * to be handled here. 103 1.1 mjacob * 104 1.1 mjacob * Basically the split into 3 main groups: Lun Enable/Modification responses, 105 1.1 mjacob * SCSI Command processing, and Immediate Notification events. 106 1.1 mjacob * 107 1.1 mjacob * You start by writing a request queue entry to enable target mode (and 108 1.1 mjacob * establish some resource limitations which you can modify later). 109 1.1 mjacob * The f/w responds with a LUN ENABLE or LUN MODIFY response with 110 1.1 mjacob * the status of this action. If the enable was successful, you can expect... 111 1.1 mjacob * 112 1.1 mjacob * Response queue entries with SCSI commands encapsulate show up in an ATIO 113 1.1 mjacob * (Accept Target IO) type- sometimes with enough info to stop the command at 114 1.1 mjacob * this level. Ultimately the driver has to feed back to the f/w's request 115 1.1 mjacob * queue a sequence of CTIOs (continue target I/O) that describe data to 116 1.1 mjacob * be moved and/or status to be sent) and finally finishing with sending 117 1.1 mjacob * to the f/w's response queue an ATIO which then completes the handshake 118 1.1 mjacob * with the f/w for that command. There's a lot of variations on this theme, 119 1.1 mjacob * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel 120 1.1 mjacob * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic 121 1.1 mjacob * gist of it. 122 1.1 mjacob * 123 1.1 mjacob * The third group that can show up in the response queue are Immediate 124 1.1 mjacob * Notification events. These include things like notifications of SCSI bus 125 1.1 mjacob * resets, or Bus Device Reset messages or other messages received. This 126 1.37 andvar * a classic oddbins area. It can get a little weird because you then turn 127 1.1 mjacob * around and acknowledge the Immediate Notify by writing an entry onto the 128 1.1 mjacob * request queue and then the f/w turns around and gives you an acknowledgement 129 1.1 mjacob * to *your* acknowledgement on the response queue (the idea being to let 130 1.1 mjacob * the f/w tell you when the event is *really* over I guess). 131 1.1 mjacob * 132 1.1 mjacob */ 133 1.1 mjacob 134 1.1 mjacob 135 1.1 mjacob /* 136 1.1 mjacob * A new response queue entry has arrived. The interrupt service code 137 1.1 mjacob * has already swizzled it into the platform dependent from canonical form. 138 1.1 mjacob * 139 1.1 mjacob * Because of the way this driver is designed, unfortunately most of the 140 1.1 mjacob * actual synchronization work has to be done in the platform specific 141 1.37 andvar * code- we have no synchronization primitives in the common code. 142 1.1 mjacob */ 143 1.1 mjacob 144 1.1 mjacob int 145 1.30 mjacob isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) 146 1.1 mjacob { 147 1.30 mjacob uint16_t status; 148 1.30 mjacob uint32_t seqid; 149 1.1 mjacob union { 150 1.1 mjacob at_entry_t *atiop; 151 1.1 mjacob at2_entry_t *at2iop; 152 1.30 mjacob at2e_entry_t *at2eiop; 153 1.30 mjacob at7_entry_t *at7iop; 154 1.1 mjacob ct_entry_t *ctiop; 155 1.1 mjacob ct2_entry_t *ct2iop; 156 1.30 mjacob ct2e_entry_t *ct2eiop; 157 1.30 mjacob ct7_entry_t *ct7iop; 158 1.1 mjacob lun_entry_t *lunenp; 159 1.1 mjacob in_entry_t *inotp; 160 1.1 mjacob in_fcentry_t *inot_fcp; 161 1.30 mjacob in_fcentry_e_t *inote_fcp; 162 1.30 mjacob in_fcentry_24xx_t *inot_24xx; 163 1.1 mjacob na_entry_t *nackp; 164 1.1 mjacob na_fcentry_t *nack_fcp; 165 1.30 mjacob na_fcentry_e_t *nacke_fcp; 166 1.30 mjacob na_fcentry_24xx_t *nack_24xx; 167 1.1 mjacob isphdr_t *hp; 168 1.30 mjacob abts_t *abts; 169 1.30 mjacob abts_rsp_t *abts_rsp; 170 1.30 mjacob els_t *els; 171 1.1 mjacob void * *vp; 172 1.1 mjacob #define atiop unp.atiop 173 1.1 mjacob #define at2iop unp.at2iop 174 1.30 mjacob #define at2eiop unp.at2eiop 175 1.30 mjacob #define at7iop unp.at7iop 176 1.1 mjacob #define ctiop unp.ctiop 177 1.1 mjacob #define ct2iop unp.ct2iop 178 1.30 mjacob #define ct2eiop unp.ct2eiop 179 1.30 mjacob #define ct7iop unp.ct7iop 180 1.1 mjacob #define lunenp unp.lunenp 181 1.1 mjacob #define inotp unp.inotp 182 1.1 mjacob #define inot_fcp unp.inot_fcp 183 1.30 mjacob #define inote_fcp unp.inote_fcp 184 1.30 mjacob #define inot_24xx unp.inot_24xx 185 1.1 mjacob #define nackp unp.nackp 186 1.1 mjacob #define nack_fcp unp.nack_fcp 187 1.30 mjacob #define nacke_fcp unp.nacke_fcp 188 1.30 mjacob #define nack_24xx unp.nack_24xx 189 1.30 mjacob #define abts unp.abts 190 1.30 mjacob #define abts_rsp unp.abts_rsp 191 1.30 mjacob #define els unp.els 192 1.1 mjacob #define hdrp unp.hp 193 1.1 mjacob } unp; 194 1.30 mjacob uint8_t local[QENTRY_LEN]; 195 1.33 mjacob uint16_t iid; 196 1.30 mjacob int bus, type, level, rval = 1; 197 1.33 mjacob isp_notify_t notify; 198 1.1 mjacob 199 1.17 mjacob type = isp_get_response_type(isp, (isphdr_t *)vptr); 200 1.1 mjacob unp.vp = vptr; 201 1.1 mjacob 202 1.1 mjacob ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr); 203 1.1 mjacob 204 1.33 mjacob switch (type) { 205 1.1 mjacob case RQSTYPE_ATIO: 206 1.30 mjacob if (IS_24XX(isp)) { 207 1.30 mjacob int len; 208 1.30 mjacob 209 1.30 mjacob isp_get_atio7(isp, at7iop, (at7_entry_t *) local); 210 1.30 mjacob at7iop = (at7_entry_t *) local; 211 1.30 mjacob /* 212 1.33 mjacob * Check for and do something with commands whose 213 1.33 mjacob * IULEN extends past a single queue entry. 214 1.30 mjacob */ 215 1.30 mjacob len = at7iop->at_ta_len & 0xfffff; 216 1.30 mjacob if (len > (QENTRY_LEN - 8)) { 217 1.30 mjacob len -= (QENTRY_LEN - 8); 218 1.33 mjacob isp_prt(isp, ISP_LOGINFO, "long IU length (%d) ignored", len); 219 1.30 mjacob while (len > 0) { 220 1.33 mjacob *optrp = ISP_NXT_QENTRY(*optrp, RESULT_QUEUE_LEN(isp)); 221 1.30 mjacob len -= QENTRY_LEN; 222 1.30 mjacob } 223 1.30 mjacob } 224 1.30 mjacob /* 225 1.30 mjacob * Check for a task management function 226 1.30 mjacob */ 227 1.30 mjacob if (at7iop->at_cmnd.fcp_cmnd_task_management) { 228 1.30 mjacob isp_got_tmf_24xx(isp, at7iop); 229 1.30 mjacob break; 230 1.30 mjacob } 231 1.30 mjacob /* 232 1.30 mjacob * Just go straight to outer layer for this one. 233 1.30 mjacob */ 234 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, local); 235 1.30 mjacob } else { 236 1.30 mjacob isp_get_atio(isp, atiop, (at_entry_t *) local); 237 1.30 mjacob isp_handle_atio(isp, (at_entry_t *) local); 238 1.30 mjacob } 239 1.1 mjacob break; 240 1.30 mjacob 241 1.1 mjacob case RQSTYPE_CTIO: 242 1.17 mjacob isp_get_ctio(isp, ctiop, (ct_entry_t *) local); 243 1.17 mjacob isp_handle_ctio(isp, (ct_entry_t *) local); 244 1.1 mjacob break; 245 1.30 mjacob 246 1.1 mjacob case RQSTYPE_ATIO2: 247 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 248 1.30 mjacob isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); 249 1.30 mjacob } else { 250 1.30 mjacob isp_get_atio2(isp, at2iop, (at2_entry_t *) local); 251 1.30 mjacob } 252 1.17 mjacob isp_handle_atio2(isp, (at2_entry_t *) local); 253 1.1 mjacob break; 254 1.30 mjacob 255 1.30 mjacob case RQSTYPE_CTIO3: 256 1.1 mjacob case RQSTYPE_CTIO2: 257 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 258 1.30 mjacob isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); 259 1.30 mjacob } else { 260 1.30 mjacob isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); 261 1.30 mjacob } 262 1.17 mjacob isp_handle_ctio2(isp, (ct2_entry_t *) local); 263 1.1 mjacob break; 264 1.30 mjacob 265 1.30 mjacob case RQSTYPE_CTIO7: 266 1.30 mjacob isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); 267 1.30 mjacob isp_handle_ctio7(isp, (ct7_entry_t *) local); 268 1.30 mjacob break; 269 1.30 mjacob 270 1.1 mjacob case RQSTYPE_ENABLE_LUN: 271 1.1 mjacob case RQSTYPE_MODIFY_LUN: 272 1.17 mjacob isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); 273 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, local); 274 1.1 mjacob break; 275 1.1 mjacob 276 1.1 mjacob case RQSTYPE_NOTIFY: 277 1.3 mjacob bus = 0; 278 1.30 mjacob if (IS_24XX(isp)) { 279 1.33 mjacob isp_get_notify_24xx(isp, inot_24xx, (in_fcentry_24xx_t *)local); 280 1.30 mjacob inot_24xx = (in_fcentry_24xx_t *) local; 281 1.31 mjacob isp_handle_24xx_inotify(isp, inot_24xx); 282 1.30 mjacob break; 283 1.33 mjacob } 284 1.33 mjacob if (IS_FC(isp)) { 285 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 286 1.33 mjacob in_fcentry_e_t *ecp = (in_fcentry_e_t *)local; 287 1.33 mjacob isp_get_notify_fc_e(isp, inote_fcp, ecp); 288 1.33 mjacob iid = ecp->in_iid; 289 1.33 mjacob status = ecp->in_status; 290 1.33 mjacob seqid = ecp->in_seqid; 291 1.30 mjacob } else { 292 1.33 mjacob in_fcentry_t *fcp = (in_fcentry_t *)local; 293 1.33 mjacob isp_get_notify_fc(isp, inot_fcp, fcp); 294 1.33 mjacob iid = fcp->in_iid; 295 1.33 mjacob status = fcp->in_status; 296 1.33 mjacob seqid = fcp->in_seqid; 297 1.30 mjacob } 298 1.33 mjacob } else { 299 1.33 mjacob in_entry_t *inp = (in_entry_t *)local; 300 1.33 mjacob isp_get_notify(isp, inotp, inp); 301 1.33 mjacob status = inp->in_status & 0xff; 302 1.33 mjacob seqid = inp->in_seqid; 303 1.33 mjacob iid = inp->in_iid; 304 1.3 mjacob if (IS_DUALBUS(isp)) { 305 1.33 mjacob bus = GET_BUS_VAL(inp->in_iid); 306 1.33 mjacob SET_BUS_VAL(inp->in_iid, 0); 307 1.3 mjacob } 308 1.1 mjacob } 309 1.30 mjacob 310 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", bus, status, seqid); 311 1.15 mjacob 312 1.1 mjacob switch (status) { 313 1.1 mjacob case IN_MSG_RECEIVED: 314 1.1 mjacob case IN_IDE_RECEIVED: 315 1.1 mjacob if (IS_FC(isp)) { 316 1.30 mjacob isp_got_msg_fc(isp, (in_fcentry_t *)local); 317 1.1 mjacob } else { 318 1.30 mjacob isp_got_msg(isp, (in_entry_t *)local); 319 1.1 mjacob } 320 1.1 mjacob break; 321 1.1 mjacob case IN_RSRC_UNAVAIL: 322 1.30 mjacob isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); 323 1.33 mjacob (void) isp_notify_ack(isp, local); 324 1.1 mjacob break; 325 1.33 mjacob 326 1.30 mjacob case IN_RESET: 327 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 328 1.30 mjacob notify.nt_hba = isp; 329 1.33 mjacob notify.nt_wwn = INI_ANY; 330 1.33 mjacob notify.nt_tgt = TGT_ANY; 331 1.33 mjacob notify.nt_nphdl = iid; 332 1.33 mjacob notify.nt_sid = PORT_ANY; 333 1.33 mjacob notify.nt_did = PORT_ANY; 334 1.30 mjacob notify.nt_lun = LUN_ANY; 335 1.30 mjacob notify.nt_tagval = TAG_ANY; 336 1.33 mjacob notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 337 1.30 mjacob notify.nt_ncode = NT_BUS_RESET; 338 1.30 mjacob notify.nt_need_ack = 1; 339 1.33 mjacob notify.nt_lreserved = local; 340 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 341 1.30 mjacob break; 342 1.33 mjacob 343 1.19 mjacob case IN_PORT_LOGOUT: 344 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 345 1.33 mjacob notify.nt_hba = isp; 346 1.33 mjacob notify.nt_wwn = INI_ANY; 347 1.33 mjacob notify.nt_nphdl = iid; 348 1.33 mjacob notify.nt_sid = PORT_ANY; 349 1.33 mjacob notify.nt_did = PORT_ANY; 350 1.33 mjacob notify.nt_ncode = NT_LOGOUT; 351 1.33 mjacob notify.nt_need_ack = 1; 352 1.33 mjacob notify.nt_lreserved = local; 353 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 354 1.33 mjacob break; 355 1.33 mjacob 356 1.1 mjacob case IN_ABORT_TASK: 357 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 358 1.33 mjacob notify.nt_hba = isp; 359 1.33 mjacob notify.nt_wwn = INI_ANY; 360 1.33 mjacob notify.nt_nphdl = iid; 361 1.33 mjacob notify.nt_sid = PORT_ANY; 362 1.33 mjacob notify.nt_did = PORT_ANY; 363 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK; 364 1.33 mjacob notify.nt_need_ack = 1; 365 1.33 mjacob notify.nt_lreserved = local; 366 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 367 1.33 mjacob break; 368 1.33 mjacob 369 1.33 mjacob case IN_GLOBAL_LOGO: 370 1.33 mjacob isp_prt(isp, ISP_LOGTINFO, "%s: all ports logged out", __func__); 371 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 372 1.33 mjacob notify.nt_hba = isp; 373 1.33 mjacob notify.nt_wwn = INI_ANY; 374 1.33 mjacob notify.nt_nphdl = NIL_HANDLE; 375 1.33 mjacob notify.nt_sid = PORT_ANY; 376 1.33 mjacob notify.nt_did = PORT_ANY; 377 1.33 mjacob notify.nt_ncode = NT_GLOBAL_LOGOUT; 378 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 379 1.33 mjacob (void) isp_notify_ack(isp, local); 380 1.33 mjacob break; 381 1.33 mjacob 382 1.1 mjacob case IN_PORT_CHANGED: 383 1.33 mjacob isp_prt(isp, ISP_LOGTINFO, "%s: port changed", __func__); 384 1.33 mjacob (void) isp_notify_ack(isp, local); 385 1.1 mjacob break; 386 1.33 mjacob 387 1.1 mjacob default: 388 1.33 mjacob ISP_SNPRINTF(local, sizeof local, "%s: unknown status to RQSTYPE_NOTIFY (0x%x)", __func__, status); 389 1.33 mjacob isp_print_bytes(isp, local, QENTRY_LEN, vptr); 390 1.33 mjacob (void) isp_notify_ack(isp, local); 391 1.1 mjacob break; 392 1.1 mjacob } 393 1.1 mjacob break; 394 1.1 mjacob 395 1.1 mjacob case RQSTYPE_NOTIFY_ACK: 396 1.1 mjacob /* 397 1.1 mjacob * The ISP is acknowledging our acknowledgement of an 398 1.1 mjacob * Immediate Notify entry for some asynchronous event. 399 1.1 mjacob */ 400 1.30 mjacob if (IS_24XX(isp)) { 401 1.33 mjacob isp_get_notify_ack_24xx(isp, nack_24xx, (na_fcentry_24xx_t *) local); 402 1.30 mjacob nack_24xx = (na_fcentry_24xx_t *) local; 403 1.30 mjacob if (nack_24xx->na_status != NA_OK) { 404 1.30 mjacob level = ISP_LOGINFO; 405 1.30 mjacob } else { 406 1.30 mjacob level = ISP_LOGTDEBUG1; 407 1.30 mjacob } 408 1.33 mjacob 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 1.30 mjacob } else if (IS_FC(isp)) { 410 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 411 1.33 mjacob isp_get_notify_ack_fc_e(isp, nacke_fcp, (na_fcentry_e_t *)local); 412 1.30 mjacob } else { 413 1.33 mjacob isp_get_notify_ack_fc(isp, nack_fcp, (na_fcentry_t *)local); 414 1.30 mjacob } 415 1.17 mjacob nack_fcp = (na_fcentry_t *)local; 416 1.30 mjacob if (nack_fcp->na_status != NA_OK) { 417 1.30 mjacob level = ISP_LOGINFO; 418 1.30 mjacob } else { 419 1.30 mjacob level = ISP_LOGTDEBUG1; 420 1.30 mjacob } 421 1.33 mjacob isp_prt(isp, level, "Notify Ack Status=0x%x seqid 0x%x", nack_fcp->na_status, nack_fcp->na_seqid); 422 1.1 mjacob } else { 423 1.17 mjacob isp_get_notify_ack(isp, nackp, (na_entry_t *)local); 424 1.17 mjacob nackp = (na_entry_t *)local; 425 1.30 mjacob if (nackp->na_status != NA_OK) { 426 1.30 mjacob level = ISP_LOGINFO; 427 1.30 mjacob } else { 428 1.30 mjacob level = ISP_LOGTDEBUG1; 429 1.30 mjacob } 430 1.33 mjacob isp_prt(isp, level, "Notify Ack event 0x%x status=0x%x seqid 0x%x", nackp->na_event, nackp->na_status, nackp->na_seqid); 431 1.1 mjacob } 432 1.1 mjacob break; 433 1.30 mjacob 434 1.30 mjacob case RQSTYPE_ABTS_RCVD: 435 1.30 mjacob isp_get_abts(isp, abts, (abts_t *)local); 436 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, &local); 437 1.30 mjacob break; 438 1.30 mjacob case RQSTYPE_ABTS_RSP: 439 1.30 mjacob isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); 440 1.30 mjacob abts_rsp = (abts_rsp_t *) local; 441 1.30 mjacob if (abts_rsp->abts_rsp_status) { 442 1.30 mjacob level = ISP_LOGINFO; 443 1.30 mjacob } else { 444 1.30 mjacob level = ISP_LOGTDEBUG0; 445 1.30 mjacob } 446 1.33 mjacob 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 1.33 mjacob abts_rsp->abts_rsp_payload.rsp.subcode1, abts_rsp->abts_rsp_payload.rsp.subcode2); 448 1.30 mjacob break; 449 1.1 mjacob default: 450 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: unknown entry type 0x%x", __func__, type); 451 1.19 mjacob rval = 0; 452 1.1 mjacob break; 453 1.1 mjacob } 454 1.1 mjacob #undef atiop 455 1.1 mjacob #undef at2iop 456 1.30 mjacob #undef at2eiop 457 1.30 mjacob #undef at7iop 458 1.1 mjacob #undef ctiop 459 1.1 mjacob #undef ct2iop 460 1.30 mjacob #undef ct2eiop 461 1.30 mjacob #undef ct7iop 462 1.1 mjacob #undef lunenp 463 1.1 mjacob #undef inotp 464 1.1 mjacob #undef inot_fcp 465 1.30 mjacob #undef inote_fcp 466 1.30 mjacob #undef inot_24xx 467 1.1 mjacob #undef nackp 468 1.1 mjacob #undef nack_fcp 469 1.30 mjacob #undef nacke_fcp 470 1.30 mjacob #undef hack_24xx 471 1.30 mjacob #undef abts 472 1.30 mjacob #undef abts_rsp 473 1.30 mjacob #undef els 474 1.1 mjacob #undef hdrp 475 1.1 mjacob return (rval); 476 1.1 mjacob } 477 1.1 mjacob 478 1.33 mjacob 479 1.1 mjacob /* 480 1.31 mjacob * Toggle (on/off) target mode for bus/target/lun. 481 1.1 mjacob * 482 1.1 mjacob * The caller has checked for overlap and legality. 483 1.1 mjacob * 484 1.1 mjacob * Note that not all of bus, target or lun can be paid attention to. 485 1.1 mjacob * Note also that this action will not be complete until the f/w writes 486 1.33 mjacob * a response entry. The caller is responsible for synchronizing with this. 487 1.1 mjacob */ 488 1.1 mjacob int 489 1.31 mjacob isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cnt) 490 1.1 mjacob { 491 1.1 mjacob lun_entry_t el; 492 1.1 mjacob void *outp; 493 1.1 mjacob 494 1.33 mjacob ISP_MEMZERO(&el, sizeof (el)); 495 1.3 mjacob if (IS_DUALBUS(isp)) { 496 1.3 mjacob el.le_rsvd = (bus & 0x1) << 7; 497 1.3 mjacob } 498 1.14 mjacob el.le_cmd_count = cmd_cnt; 499 1.14 mjacob el.le_in_count = inot_cnt; 500 1.1 mjacob if (cmd == RQSTYPE_ENABLE_LUN) { 501 1.1 mjacob if (IS_SCSI(isp)) { 502 1.5 mjacob el.le_flags = LUN_TQAE|LUN_DISAD; 503 1.1 mjacob el.le_cdb6len = 12; 504 1.1 mjacob el.le_cdb7len = 12; 505 1.1 mjacob } 506 1.1 mjacob } else if (cmd == -RQSTYPE_ENABLE_LUN) { 507 1.1 mjacob cmd = RQSTYPE_ENABLE_LUN; 508 1.1 mjacob el.le_cmd_count = 0; 509 1.1 mjacob el.le_in_count = 0; 510 1.1 mjacob } else if (cmd == -RQSTYPE_MODIFY_LUN) { 511 1.1 mjacob cmd = RQSTYPE_MODIFY_LUN; 512 1.1 mjacob el.le_ops = LUN_CCDECR | LUN_INDECR; 513 1.1 mjacob } else { 514 1.1 mjacob el.le_ops = LUN_CCINCR | LUN_ININCR; 515 1.1 mjacob } 516 1.1 mjacob el.le_header.rqs_entry_type = cmd; 517 1.1 mjacob el.le_header.rqs_entry_count = 1; 518 1.1 mjacob if (IS_SCSI(isp)) { 519 1.31 mjacob el.le_tgt = SDPARAM(isp, bus)->isp_initiator_id; 520 1.1 mjacob el.le_lun = lun; 521 1.31 mjacob } else if (ISP_CAP_SCCFW(isp) == 0) { 522 1.1 mjacob el.le_lun = lun; 523 1.1 mjacob } 524 1.30 mjacob el.le_timeout = 30; 525 1.1 mjacob 526 1.33 mjacob outp = isp_getrqentry(isp); 527 1.33 mjacob if (outp == NULL) { 528 1.33 mjacob isp_prt(isp, ISP_LOGERR, rqo, __func__); 529 1.1 mjacob return (-1); 530 1.1 mjacob } 531 1.17 mjacob isp_put_enable_lun(isp, &el, outp); 532 1.33 mjacob ISP_TDQE(isp, "isp_lun_cmd", isp->isp_reqidx, &el); 533 1.33 mjacob ISP_SYNC_REQUEST(isp); 534 1.1 mjacob return (0); 535 1.1 mjacob } 536 1.1 mjacob 537 1.1 mjacob int 538 1.30 mjacob isp_target_put_entry(ispsoftc_t *isp, void *ap) 539 1.1 mjacob { 540 1.1 mjacob void *outp; 541 1.30 mjacob uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; 542 1.1 mjacob 543 1.33 mjacob outp = isp_getrqentry(isp); 544 1.33 mjacob if (outp == NULL) { 545 1.33 mjacob isp_prt(isp, ISP_LOGWARN, rqo, __func__); 546 1.1 mjacob return (-1); 547 1.1 mjacob } 548 1.1 mjacob switch (etype) { 549 1.1 mjacob case RQSTYPE_ATIO: 550 1.17 mjacob isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); 551 1.1 mjacob break; 552 1.1 mjacob case RQSTYPE_ATIO2: 553 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 554 1.33 mjacob isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp); 555 1.30 mjacob } else { 556 1.33 mjacob isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); 557 1.30 mjacob } 558 1.1 mjacob break; 559 1.1 mjacob case RQSTYPE_CTIO: 560 1.17 mjacob isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); 561 1.1 mjacob break; 562 1.1 mjacob case RQSTYPE_CTIO2: 563 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 564 1.33 mjacob isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp); 565 1.30 mjacob } else { 566 1.33 mjacob isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp); 567 1.30 mjacob } 568 1.30 mjacob break; 569 1.30 mjacob case RQSTYPE_CTIO7: 570 1.30 mjacob isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp); 571 1.1 mjacob break; 572 1.1 mjacob default: 573 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype); 574 1.1 mjacob return (-1); 575 1.1 mjacob } 576 1.33 mjacob ISP_TDQE(isp, __func__, isp->isp_reqidx, ap); 577 1.33 mjacob ISP_SYNC_REQUEST(isp); 578 1.1 mjacob return (0); 579 1.1 mjacob } 580 1.1 mjacob 581 1.1 mjacob int 582 1.30 mjacob isp_target_put_atio(ispsoftc_t *isp, void *arg) 583 1.1 mjacob { 584 1.1 mjacob union { 585 1.1 mjacob at_entry_t _atio; 586 1.1 mjacob at2_entry_t _atio2; 587 1.30 mjacob at2e_entry_t _atio2e; 588 1.1 mjacob } atun; 589 1.1 mjacob 590 1.33 mjacob ISP_MEMZERO(&atun, sizeof atun); 591 1.1 mjacob if (IS_FC(isp)) { 592 1.13 mjacob at2_entry_t *aep = arg; 593 1.1 mjacob atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; 594 1.1 mjacob atun._atio2.at_header.rqs_entry_count = 1; 595 1.31 mjacob if (ISP_CAP_SCCFW(isp)) { 596 1.30 mjacob atun._atio2.at_scclun = aep->at_scclun; 597 1.5 mjacob } else { 598 1.30 mjacob atun._atio2.at_lun = (uint8_t) aep->at_lun; 599 1.30 mjacob } 600 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 601 1.30 mjacob atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; 602 1.30 mjacob } else { 603 1.30 mjacob atun._atio2.at_iid = aep->at_iid; 604 1.5 mjacob } 605 1.23 mjacob atun._atio2.at_rxid = aep->at_rxid; 606 1.1 mjacob atun._atio2.at_status = CT_OK; 607 1.1 mjacob } else { 608 1.13 mjacob at_entry_t *aep = arg; 609 1.1 mjacob atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO; 610 1.1 mjacob atun._atio.at_header.rqs_entry_count = 1; 611 1.13 mjacob atun._atio.at_handle = aep->at_handle; 612 1.13 mjacob atun._atio.at_iid = aep->at_iid; 613 1.13 mjacob atun._atio.at_tgt = aep->at_tgt; 614 1.13 mjacob atun._atio.at_lun = aep->at_lun; 615 1.13 mjacob atun._atio.at_tag_type = aep->at_tag_type; 616 1.13 mjacob atun._atio.at_tag_val = aep->at_tag_val; 617 1.13 mjacob atun._atio.at_status = (aep->at_flags & AT_TQAE); 618 1.13 mjacob atun._atio.at_status |= CT_OK; 619 1.1 mjacob } 620 1.1 mjacob return (isp_target_put_entry(isp, &atun)); 621 1.1 mjacob } 622 1.1 mjacob 623 1.1 mjacob /* 624 1.1 mjacob * Command completion- both for handling cases of no resources or 625 1.1 mjacob * no blackhole driver, or other cases where we have to, inline, 626 1.1 mjacob * finish the command sanely, or for normal command completion. 627 1.1 mjacob * 628 1.1 mjacob * The 'completion' code value has the scsi status byte in the low 8 bits. 629 1.1 mjacob * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have 630 1.1 mjacob * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC 631 1.1 mjacob * values. 632 1.1 mjacob * 633 1.1 mjacob * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't 634 1.13 mjacob * NB: inline SCSI sense reporting. As such, we lose this information. XXX. 635 1.1 mjacob * 636 1.1 mjacob * For both parallel && fibre channel, we use the feature that does 637 1.1 mjacob * an automatic resource autoreplenish so we don't have then later do 638 1.1 mjacob * put of an atio to replenish the f/w's resource count. 639 1.1 mjacob */ 640 1.1 mjacob 641 1.1 mjacob int 642 1.31 mjacob isp_endcmd(ispsoftc_t *isp, ...) 643 1.1 mjacob { 644 1.31 mjacob uint32_t code, hdl; 645 1.31 mjacob uint8_t sts; 646 1.1 mjacob union { 647 1.1 mjacob ct_entry_t _ctio; 648 1.1 mjacob ct2_entry_t _ctio2; 649 1.30 mjacob ct2e_entry_t _ctio2e; 650 1.30 mjacob ct7_entry_t _ctio7; 651 1.1 mjacob } un; 652 1.31 mjacob va_list ap; 653 1.1 mjacob 654 1.33 mjacob ISP_MEMZERO(&un, sizeof un); 655 1.1 mjacob 656 1.30 mjacob if (IS_24XX(isp)) { 657 1.31 mjacob int vpidx, nphdl; 658 1.31 mjacob at7_entry_t *aep; 659 1.30 mjacob ct7_entry_t *cto = &un._ctio7; 660 1.30 mjacob 661 1.31 mjacob va_start(ap, isp); 662 1.31 mjacob aep = va_arg(ap, at7_entry_t *); 663 1.31 mjacob nphdl = va_arg(ap, int); 664 1.33 mjacob /* 665 1.33 mjacob * Note that vpidx may equal 0xff (unknown) here 666 1.33 mjacob */ 667 1.31 mjacob vpidx = va_arg(ap, int); 668 1.31 mjacob code = va_arg(ap, uint32_t); 669 1.31 mjacob hdl = va_arg(ap, uint32_t); 670 1.31 mjacob va_end(ap); 671 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] chan %d code %x", __func__, aep->at_rxid, vpidx, code); 672 1.31 mjacob 673 1.33 mjacob sts = code & 0xff; 674 1.30 mjacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 675 1.30 mjacob cto->ct_header.rqs_entry_count = 1; 676 1.31 mjacob cto->ct_nphdl = nphdl; 677 1.30 mjacob cto->ct_rxid = aep->at_rxid; 678 1.33 mjacob cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2]; 679 1.30 mjacob cto->ct_iid_hi = aep->at_hdr.s_id[0]; 680 1.30 mjacob cto->ct_oxid = aep->at_hdr.ox_id; 681 1.30 mjacob cto->ct_scsi_status = sts; 682 1.33 mjacob cto->ct_vpidx = vpidx; 683 1.33 mjacob cto->ct_flags = CT7_NOACK; 684 1.33 mjacob if (code & ECMD_TERMINATE) { 685 1.33 mjacob cto->ct_flags |= CT7_TERMINATE; 686 1.33 mjacob } else if (code & ECMD_SVALID) { 687 1.33 mjacob cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS; 688 1.33 mjacob cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8); 689 1.35 riastrad cto->rsp.m1.ct_resplen = cto->ct_senselen = uimin(16, MAXRESPLEN_24XX); 690 1.33 mjacob ISP_MEMZERO(cto->rsp.m1.ct_resp, sizeof (cto->rsp.m1.ct_resp)); 691 1.30 mjacob cto->rsp.m1.ct_resp[0] = 0xf0; 692 1.30 mjacob cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 693 1.30 mjacob cto->rsp.m1.ct_resp[7] = 8; 694 1.30 mjacob cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 695 1.30 mjacob cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 696 1.33 mjacob } else { 697 1.33 mjacob cto->ct_flags |= CT7_FLAG_MODE1 | CT7_SENDSTATUS; 698 1.30 mjacob } 699 1.30 mjacob if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) { 700 1.30 mjacob cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; 701 1.33 mjacob if (cto->ct_resid < 0) { 702 1.33 mjacob cto->ct_scsi_status |= (FCP_RESID_OVERFLOW << 8); 703 1.33 mjacob } else if (cto->ct_resid > 0) { 704 1.33 mjacob cto->ct_scsi_status |= (FCP_RESID_UNDERFLOW << 8); 705 1.33 mjacob } 706 1.30 mjacob } 707 1.30 mjacob cto->ct_syshandle = hdl; 708 1.30 mjacob } else if (IS_FC(isp)) { 709 1.31 mjacob at2_entry_t *aep; 710 1.1 mjacob ct2_entry_t *cto = &un._ctio2; 711 1.1 mjacob 712 1.31 mjacob va_start(ap, isp); 713 1.31 mjacob aep = va_arg(ap, at2_entry_t *); 714 1.31 mjacob code = va_arg(ap, uint32_t); 715 1.31 mjacob hdl = va_arg(ap, uint32_t); 716 1.31 mjacob va_end(ap); 717 1.31 mjacob 718 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: [RX_ID 0x%x] code %x", __func__, aep->at_rxid, code); 719 1.33 mjacob 720 1.33 mjacob sts = code & 0xff; 721 1.1 mjacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 722 1.1 mjacob cto->ct_header.rqs_entry_count = 1; 723 1.31 mjacob if (ISP_CAP_SCCFW(isp) == 0) { 724 1.5 mjacob cto->ct_lun = aep->at_lun; 725 1.5 mjacob } 726 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 727 1.30 mjacob un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; 728 1.30 mjacob } else { 729 1.30 mjacob cto->ct_iid = aep->at_iid; 730 1.30 mjacob } 731 1.1 mjacob cto->ct_rxid = aep->at_rxid; 732 1.30 mjacob cto->rsp.m1.ct_scsi_status = sts; 733 1.1 mjacob cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; 734 1.1 mjacob if (hdl == 0) { 735 1.1 mjacob cto->ct_flags |= CT2_CCINCR; 736 1.1 mjacob } 737 1.1 mjacob if (aep->at_datalen) { 738 1.1 mjacob cto->ct_resid = aep->at_datalen; 739 1.14 mjacob cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; 740 1.1 mjacob } 741 1.30 mjacob if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { 742 1.1 mjacob cto->rsp.m1.ct_resp[0] = 0xf0; 743 1.1 mjacob cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 744 1.1 mjacob cto->rsp.m1.ct_resp[7] = 8; 745 1.1 mjacob cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 746 1.1 mjacob cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 747 1.1 mjacob cto->rsp.m1.ct_senselen = 16; 748 1.14 mjacob cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; 749 1.1 mjacob } 750 1.11 mjacob cto->ct_syshandle = hdl; 751 1.1 mjacob } else { 752 1.31 mjacob at_entry_t *aep; 753 1.1 mjacob ct_entry_t *cto = &un._ctio; 754 1.1 mjacob 755 1.31 mjacob va_start(ap, isp); 756 1.31 mjacob aep = va_arg(ap, at_entry_t *); 757 1.31 mjacob code = va_arg(ap, uint32_t); 758 1.31 mjacob hdl = va_arg(ap, uint32_t); 759 1.31 mjacob va_end(ap); 760 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: [IID %d] code %x", __func__, aep->at_iid, code); 761 1.31 mjacob sts = code; 762 1.31 mjacob 763 1.1 mjacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 764 1.1 mjacob cto->ct_header.rqs_entry_count = 1; 765 1.11 mjacob cto->ct_fwhandle = aep->at_handle; 766 1.1 mjacob cto->ct_iid = aep->at_iid; 767 1.1 mjacob cto->ct_tgt = aep->at_tgt; 768 1.1 mjacob cto->ct_lun = aep->at_lun; 769 1.1 mjacob cto->ct_tag_type = aep->at_tag_type; 770 1.1 mjacob cto->ct_tag_val = aep->at_tag_val; 771 1.13 mjacob if (aep->at_flags & AT_TQAE) { 772 1.13 mjacob cto->ct_flags |= CT_TQAE; 773 1.13 mjacob } 774 1.1 mjacob cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA; 775 1.1 mjacob if (hdl == 0) { 776 1.1 mjacob cto->ct_flags |= CT_CCINCR; 777 1.1 mjacob } 778 1.1 mjacob cto->ct_scsi_status = sts; 779 1.11 mjacob cto->ct_syshandle = hdl; 780 1.1 mjacob } 781 1.1 mjacob return (isp_target_put_entry(isp, &un)); 782 1.1 mjacob } 783 1.1 mjacob 784 1.30 mjacob /* 785 1.30 mjacob * These are either broadcast events or specifically CTIO fast completion 786 1.30 mjacob */ 787 1.33 mjacob 788 1.19 mjacob int 789 1.30 mjacob isp_target_async(ispsoftc_t *isp, int bus, int event) 790 1.1 mjacob { 791 1.33 mjacob isp_notify_t notify; 792 1.30 mjacob 793 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 794 1.30 mjacob notify.nt_hba = isp; 795 1.33 mjacob notify.nt_wwn = INI_ANY; 796 1.33 mjacob notify.nt_nphdl = NIL_HANDLE; 797 1.33 mjacob notify.nt_sid = PORT_ANY; 798 1.33 mjacob notify.nt_did = PORT_ANY; 799 1.33 mjacob notify.nt_tgt = TGT_ANY; 800 1.33 mjacob notify.nt_channel = bus; 801 1.30 mjacob notify.nt_lun = LUN_ANY; 802 1.30 mjacob notify.nt_tagval = TAG_ANY; 803 1.33 mjacob notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 804 1.1 mjacob 805 1.1 mjacob switch (event) { 806 1.30 mjacob case ASYNC_LOOP_UP: 807 1.30 mjacob case ASYNC_PTPMODE: 808 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP UP", __func__); 809 1.30 mjacob notify.nt_ncode = NT_LINK_UP; 810 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 811 1.30 mjacob break; 812 1.30 mjacob case ASYNC_LOOP_DOWN: 813 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: LOOP DOWN", __func__); 814 1.30 mjacob notify.nt_ncode = NT_LINK_DOWN; 815 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 816 1.30 mjacob break; 817 1.30 mjacob case ASYNC_LIP_ERROR: 818 1.15 mjacob case ASYNC_LIP_F8: 819 1.1 mjacob case ASYNC_LIP_OCCURRED: 820 1.15 mjacob case ASYNC_LOOP_RESET: 821 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: LIP RESET", __func__); 822 1.30 mjacob notify.nt_ncode = NT_LIP_RESET; 823 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 824 1.30 mjacob break; 825 1.1 mjacob case ASYNC_BUS_RESET: 826 1.30 mjacob case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ 827 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: BUS RESET", __func__); 828 1.30 mjacob notify.nt_ncode = NT_BUS_RESET; 829 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 830 1.1 mjacob break; 831 1.1 mjacob case ASYNC_DEVICE_RESET: 832 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: DEVICE RESET", __func__); 833 1.30 mjacob notify.nt_ncode = NT_TARGET_RESET; 834 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 835 1.30 mjacob break; 836 1.30 mjacob case ASYNC_CTIO_DONE: 837 1.30 mjacob { 838 1.30 mjacob uint8_t storage[QENTRY_LEN]; 839 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO DONE", __func__); 840 1.30 mjacob memset(storage, 0, QENTRY_LEN); 841 1.30 mjacob if (IS_24XX(isp)) { 842 1.30 mjacob ct7_entry_t *ct = (ct7_entry_t *) storage; 843 1.30 mjacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 844 1.30 mjacob ct->ct_nphdl = CT7_OK; 845 1.30 mjacob ct->ct_syshandle = bus; 846 1.31 mjacob ct->ct_flags = CT7_SENDSTATUS; 847 1.30 mjacob } else if (IS_FC(isp)) { 848 1.30 mjacob /* This should also suffice for 2K login code */ 849 1.30 mjacob ct2_entry_t *ct = (ct2_entry_t *) storage; 850 1.30 mjacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 851 1.30 mjacob ct->ct_status = CT_OK; 852 1.30 mjacob ct->ct_syshandle = bus; 853 1.30 mjacob ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; 854 1.1 mjacob } else { 855 1.30 mjacob ct_entry_t *ct = (ct_entry_t *) storage; 856 1.30 mjacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; 857 1.30 mjacob ct->ct_status = CT_OK; 858 1.34 mjacob ct->ct_syshandle = bus; 859 1.34 mjacob /* we skip fwhandle here */ 860 1.34 mjacob ct->ct_fwhandle = 0; 861 1.30 mjacob ct->ct_flags = CT_SENDSTATUS; 862 1.1 mjacob } 863 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, storage); 864 1.1 mjacob break; 865 1.30 mjacob } 866 1.1 mjacob default: 867 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: unknown event 0x%x", __func__, event); 868 1.30 mjacob if (isp->isp_state == ISP_RUNSTATE) { 869 1.33 mjacob (void) isp_notify_ack(isp, NULL); 870 1.30 mjacob } 871 1.1 mjacob break; 872 1.1 mjacob } 873 1.30 mjacob return (0); 874 1.1 mjacob } 875 1.1 mjacob 876 1.1 mjacob 877 1.1 mjacob /* 878 1.1 mjacob * Process a received message. 879 1.1 mjacob * The ISP firmware can handle most messages, there are only 880 1.1 mjacob * a few that we need to deal with: 881 1.1 mjacob * - abort: clean up the current command 882 1.1 mjacob * - abort tag and clear queue 883 1.1 mjacob */ 884 1.1 mjacob 885 1.1 mjacob static void 886 1.30 mjacob isp_got_msg(ispsoftc_t *isp, in_entry_t *inp) 887 1.1 mjacob { 888 1.33 mjacob isp_notify_t notify; 889 1.30 mjacob uint8_t status = inp->in_status & ~QLTM_SVALID; 890 1.30 mjacob 891 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (notify)); 892 1.33 mjacob notify.nt_hba = isp; 893 1.33 mjacob notify.nt_wwn = INI_ANY; 894 1.33 mjacob notify.nt_nphdl = GET_IID_VAL(inp->in_iid); 895 1.33 mjacob notify.nt_sid = PORT_ANY; 896 1.33 mjacob notify.nt_did = PORT_ANY; 897 1.33 mjacob notify.nt_channel = GET_BUS_VAL(inp->in_iid); 898 1.33 mjacob notify.nt_tgt = inp->in_tgt; 899 1.33 mjacob notify.nt_lun = inp->in_lun; 900 1.33 mjacob IN_MAKE_TAGID(notify.nt_tagval, inp); 901 1.33 mjacob notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 902 1.33 mjacob notify.nt_lreserved = inp; 903 1.1 mjacob 904 1.1 mjacob if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { 905 1.30 mjacob switch (inp->in_msg[0]) { 906 1.30 mjacob case MSG_ABORT: 907 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK_SET; 908 1.30 mjacob break; 909 1.30 mjacob case MSG_BUS_DEV_RESET: 910 1.33 mjacob notify.nt_ncode = NT_TARGET_RESET; 911 1.30 mjacob break; 912 1.30 mjacob case MSG_ABORT_TAG: 913 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK; 914 1.30 mjacob break; 915 1.30 mjacob case MSG_CLEAR_QUEUE: 916 1.33 mjacob notify.nt_ncode = NT_CLEAR_TASK_SET; 917 1.30 mjacob break; 918 1.30 mjacob case MSG_REL_RECOVERY: 919 1.33 mjacob notify.nt_ncode = NT_CLEAR_ACA; 920 1.30 mjacob break; 921 1.30 mjacob case MSG_TERM_IO_PROC: 922 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK; 923 1.30 mjacob break; 924 1.30 mjacob case MSG_LUN_RESET: 925 1.33 mjacob notify.nt_ncode = NT_LUN_RESET; 926 1.30 mjacob break; 927 1.30 mjacob default: 928 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: unhandled message 0x%x", __func__, inp->in_msg[0]); 929 1.33 mjacob (void) isp_notify_ack(isp, inp); 930 1.30 mjacob return; 931 1.30 mjacob } 932 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 933 1.1 mjacob } else { 934 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: unknown immediate notify status 0x%x", __func__, inp->in_status); 935 1.33 mjacob (void) isp_notify_ack(isp, inp); 936 1.1 mjacob } 937 1.1 mjacob } 938 1.1 mjacob 939 1.1 mjacob /* 940 1.1 mjacob * Synthesize a message from the task management flags in a FCP_CMND_IU. 941 1.1 mjacob */ 942 1.1 mjacob static void 943 1.30 mjacob isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) 944 1.1 mjacob { 945 1.33 mjacob isp_notify_t notify; 946 1.30 mjacob static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x"; 947 1.33 mjacob static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n"; 948 1.30 mjacob uint16_t seqid, loopid; 949 1.30 mjacob 950 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 951 1.33 mjacob notify.nt_hba = isp; 952 1.33 mjacob notify.nt_wwn = INI_ANY; 953 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 954 1.33 mjacob notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid; 955 1.30 mjacob loopid = ((in_fcentry_e_t *)inp)->in_iid; 956 1.30 mjacob seqid = ((in_fcentry_e_t *)inp)->in_seqid; 957 1.30 mjacob } else { 958 1.33 mjacob notify.nt_nphdl = inp->in_iid; 959 1.30 mjacob loopid = inp->in_iid; 960 1.30 mjacob seqid = inp->in_seqid; 961 1.30 mjacob } 962 1.33 mjacob notify.nt_sid = PORT_ANY; 963 1.33 mjacob notify.nt_did = PORT_ANY; 964 1.33 mjacob 965 1.30 mjacob /* nt_tgt set in outer layers */ 966 1.31 mjacob if (ISP_CAP_SCCFW(isp)) { 967 1.33 mjacob notify.nt_lun = inp->in_scclun; 968 1.15 mjacob } else { 969 1.33 mjacob notify.nt_lun = inp->in_lun; 970 1.15 mjacob } 971 1.33 mjacob notify.nt_tagval = seqid; 972 1.33 mjacob notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 973 1.33 mjacob notify.nt_need_ack = 1; 974 1.33 mjacob notify.nt_lreserved = inp; 975 1.15 mjacob 976 1.1 mjacob if (inp->in_status != IN_MSG_RECEIVED) { 977 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid); 978 1.33 mjacob (void) isp_notify_ack(isp, inp); 979 1.30 mjacob return; 980 1.30 mjacob } 981 1.30 mjacob 982 1.30 mjacob if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { 983 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", loopid, notify.nt_lun, inp->in_seqid); 984 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK_SET; 985 1.30 mjacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { 986 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", loopid, notify.nt_lun, inp->in_seqid); 987 1.33 mjacob notify.nt_ncode = NT_CLEAR_TASK_SET; 988 1.30 mjacob } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { 989 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", loopid, notify.nt_lun, inp->in_seqid); 990 1.33 mjacob notify.nt_ncode = NT_LUN_RESET; 991 1.30 mjacob } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { 992 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", loopid, notify.nt_lun, inp->in_seqid); 993 1.33 mjacob notify.nt_ncode = NT_TARGET_RESET; 994 1.30 mjacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { 995 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", loopid, notify.nt_lun, inp->in_seqid); 996 1.33 mjacob notify.nt_ncode = NT_CLEAR_ACA; 997 1.1 mjacob } else { 998 1.33 mjacob isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid); 999 1.33 mjacob (void) isp_notify_ack(isp, inp); 1000 1.30 mjacob return; 1001 1.30 mjacob } 1002 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 1003 1.30 mjacob } 1004 1.1 mjacob 1005 1.30 mjacob static void 1006 1.30 mjacob isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) 1007 1.30 mjacob { 1008 1.33 mjacob isp_notify_t notify; 1009 1.33 mjacob static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%08x"; 1010 1.33 mjacob static const char f2[] = "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x"; 1011 1.31 mjacob uint16_t chan; 1012 1.31 mjacob uint32_t sid, did; 1013 1.30 mjacob 1014 1.33 mjacob ISP_MEMZERO(¬ify, sizeof (isp_notify_t)); 1015 1.33 mjacob notify.nt_hba = isp; 1016 1.33 mjacob notify.nt_wwn = INI_ANY; 1017 1.33 mjacob notify.nt_lun = (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | (aep->at_cmnd.fcp_cmnd_lun[1]); 1018 1.33 mjacob notify.nt_tagval = aep->at_rxid; 1019 1.33 mjacob notify.nt_tagval |= (((uint64_t)(isp->isp_serno++)) << 32); 1020 1.33 mjacob notify.nt_lreserved = aep; 1021 1.33 mjacob sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | (aep->at_hdr.s_id[2]); 1022 1.30 mjacob 1023 1.31 mjacob /* Channel has to derived from D_ID */ 1024 1.31 mjacob did = (aep->at_hdr.d_id[0] << 16) | (aep->at_hdr.d_id[1] << 8) | aep->at_hdr.d_id[2]; 1025 1.31 mjacob for (chan = 0; chan < isp->isp_nchan; chan++) { 1026 1.31 mjacob if (FCPARAM(isp, chan)->isp_portid == did) { 1027 1.33 mjacob break; 1028 1.31 mjacob } 1029 1.31 mjacob } 1030 1.31 mjacob if (chan == isp->isp_nchan) { 1031 1.33 mjacob isp_prt(isp, ISP_LOGWARN, "%s: D_ID 0x%x not found on any channel", __func__, did); 1032 1.31 mjacob /* just drop on the floor */ 1033 1.31 mjacob return; 1034 1.31 mjacob } 1035 1.33 mjacob notify.nt_nphdl = NIL_HANDLE; /* unknown here */ 1036 1.33 mjacob notify.nt_sid = sid; 1037 1.33 mjacob notify.nt_did = did; 1038 1.33 mjacob notify.nt_channel = chan; 1039 1.33 mjacob if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_ABORT_TASK_SET) { 1040 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", sid, notify.nt_lun, aep->at_rxid); 1041 1.33 mjacob notify.nt_ncode = NT_ABORT_TASK_SET; 1042 1.33 mjacob } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_TASK_SET) { 1043 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", sid, notify.nt_lun, aep->at_rxid); 1044 1.33 mjacob notify.nt_ncode = NT_CLEAR_TASK_SET; 1045 1.33 mjacob } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_LUN_RESET) { 1046 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", sid, notify.nt_lun, aep->at_rxid); 1047 1.33 mjacob notify.nt_ncode = NT_LUN_RESET; 1048 1.33 mjacob } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_TGT_RESET) { 1049 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", sid, notify.nt_lun, aep->at_rxid); 1050 1.33 mjacob notify.nt_ncode = NT_TARGET_RESET; 1051 1.33 mjacob } else if (aep->at_cmnd.fcp_cmnd_task_management & FCP_CMND_TMF_CLEAR_ACA) { 1052 1.33 mjacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", sid, notify.nt_lun, aep->at_rxid); 1053 1.33 mjacob notify.nt_ncode = NT_CLEAR_ACA; 1054 1.30 mjacob } else { 1055 1.33 mjacob isp_prt(isp, ISP_LOGWARN, f2, aep->at_cmnd.fcp_cmnd_task_management, notify.nt_lun, sid, aep->at_rxid); 1056 1.33 mjacob notify.nt_ncode = NT_UNKNOWN; 1057 1.30 mjacob return; 1058 1.1 mjacob } 1059 1.33 mjacob isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 1060 1.1 mjacob } 1061 1.1 mjacob 1062 1.33 mjacob int 1063 1.30 mjacob isp_notify_ack(ispsoftc_t *isp, void *arg) 1064 1.1 mjacob { 1065 1.1 mjacob char storage[QENTRY_LEN]; 1066 1.1 mjacob void *outp; 1067 1.1 mjacob 1068 1.33 mjacob /* 1069 1.33 mjacob * This is in case a Task Management Function ends up here. 1070 1.33 mjacob */ 1071 1.33 mjacob if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) { 1072 1.33 mjacob at7_entry_t *aep = arg; 1073 1.33 mjacob return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0)); 1074 1.33 mjacob } 1075 1.33 mjacob 1076 1.33 mjacob outp = isp_getrqentry(isp); 1077 1.33 mjacob if (outp == NULL) { 1078 1.33 mjacob isp_prt(isp, ISP_LOGWARN, rqo, __func__); 1079 1.33 mjacob return (1); 1080 1.1 mjacob } 1081 1.1 mjacob 1082 1.33 mjacob ISP_MEMZERO(storage, QENTRY_LEN); 1083 1.1 mjacob 1084 1.33 mjacob if (IS_24XX(isp)) { 1085 1.30 mjacob na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; 1086 1.30 mjacob if (arg) { 1087 1.30 mjacob in_fcentry_24xx_t *in = arg; 1088 1.30 mjacob na->na_nphdl = in->in_nphdl; 1089 1.33 mjacob na->na_flags = in->in_flags & IN24XX_FLAG_PUREX_IOCB; 1090 1.30 mjacob na->na_status = in->in_status; 1091 1.30 mjacob na->na_status_subcode = in->in_status_subcode; 1092 1.30 mjacob na->na_rxid = in->in_rxid; 1093 1.30 mjacob na->na_oxid = in->in_oxid; 1094 1.33 mjacob na->na_vpidx = in->in_vpidx; 1095 1.30 mjacob if (in->in_status == IN24XX_SRR_RCVD) { 1096 1.33 mjacob na->na_srr_rxid = in->in_srr_rxid; 1097 1.33 mjacob na->na_srr_reloff_hi = in->in_srr_reloff_hi; 1098 1.33 mjacob na->na_srr_reloff_lo = in->in_srr_reloff_lo; 1099 1.33 mjacob na->na_srr_iu = in->in_srr_iu; 1100 1.30 mjacob na->na_srr_flags = 1; 1101 1.30 mjacob na->na_srr_reject_vunique = 0; 1102 1.30 mjacob na->na_srr_reject_explanation = 1; 1103 1.30 mjacob na->na_srr_reject_code = 1; 1104 1.30 mjacob } 1105 1.30 mjacob } 1106 1.30 mjacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 1107 1.30 mjacob na->na_header.rqs_entry_count = 1; 1108 1.30 mjacob isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); 1109 1.30 mjacob } else if (IS_FC(isp)) { 1110 1.1 mjacob na_fcentry_t *na = (na_fcentry_t *) storage; 1111 1.30 mjacob int iid = 0; 1112 1.30 mjacob 1113 1.1 mjacob if (arg) { 1114 1.1 mjacob in_fcentry_t *inp = arg; 1115 1.33 mjacob ISP_MEMCPY(storage, arg, sizeof (isphdr_t)); 1116 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 1117 1.33 mjacob ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid; 1118 1.30 mjacob iid = ((na_fcentry_e_t *)na)->na_iid; 1119 1.5 mjacob } else { 1120 1.30 mjacob na->na_iid = inp->in_iid; 1121 1.30 mjacob iid = na->na_iid; 1122 1.5 mjacob } 1123 1.33 mjacob na->na_task_flags = inp->in_task_flags & TASK_FLAGS_RESERVED_MASK; 1124 1.1 mjacob na->na_seqid = inp->in_seqid; 1125 1.1 mjacob na->na_flags = NAFC_RCOUNT; 1126 1.18 mjacob na->na_status = inp->in_status; 1127 1.1 mjacob if (inp->in_status == IN_RESET) { 1128 1.1 mjacob na->na_flags |= NAFC_RST_CLRD; 1129 1.1 mjacob } 1130 1.30 mjacob if (inp->in_status == IN_MSG_RECEIVED) { 1131 1.30 mjacob na->na_flags |= NAFC_TVALID; 1132 1.30 mjacob na->na_response = 0; /* XXX SUCCEEDED XXX */ 1133 1.30 mjacob } 1134 1.1 mjacob } else { 1135 1.1 mjacob na->na_flags = NAFC_RST_CLRD; 1136 1.1 mjacob } 1137 1.4 he na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 1138 1.4 he na->na_header.rqs_entry_count = 1; 1139 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 1140 1.33 mjacob isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp); 1141 1.30 mjacob } else { 1142 1.30 mjacob isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); 1143 1.30 mjacob } 1144 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x flags %x tflags %x response %x", iid, na->na_seqid, 1145 1.30 mjacob na->na_flags, na->na_task_flags, na->na_response); 1146 1.1 mjacob } else { 1147 1.1 mjacob na_entry_t *na = (na_entry_t *) storage; 1148 1.1 mjacob if (arg) { 1149 1.1 mjacob in_entry_t *inp = arg; 1150 1.33 mjacob ISP_MEMCPY(storage, arg, sizeof (isphdr_t)); 1151 1.1 mjacob na->na_iid = inp->in_iid; 1152 1.1 mjacob na->na_lun = inp->in_lun; 1153 1.1 mjacob na->na_tgt = inp->in_tgt; 1154 1.1 mjacob na->na_seqid = inp->in_seqid; 1155 1.1 mjacob if (inp->in_status == IN_RESET) { 1156 1.4 he na->na_event = NA_RST_CLRD; 1157 1.1 mjacob } 1158 1.1 mjacob } else { 1159 1.4 he na->na_event = NA_RST_CLRD; 1160 1.1 mjacob } 1161 1.4 he na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 1162 1.4 he na->na_header.rqs_entry_count = 1; 1163 1.17 mjacob isp_put_notify_ack(isp, na, (na_entry_t *)outp); 1164 1.33 mjacob 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); 1165 1.1 mjacob } 1166 1.33 mjacob ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage); 1167 1.33 mjacob ISP_SYNC_REQUEST(isp); 1168 1.33 mjacob return (0); 1169 1.33 mjacob } 1170 1.33 mjacob 1171 1.33 mjacob int 1172 1.33 mjacob isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno) 1173 1.33 mjacob { 1174 1.33 mjacob char storage[QENTRY_LEN]; 1175 1.33 mjacob uint16_t tmpw; 1176 1.33 mjacob uint8_t tmpb; 1177 1.33 mjacob abts_t *abts = arg; 1178 1.33 mjacob abts_rsp_t *rsp = (abts_rsp_t *) storage; 1179 1.33 mjacob void *outp; 1180 1.33 mjacob 1181 1.33 mjacob if (!IS_24XX(isp)) { 1182 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: called for non-24XX card", __func__); 1183 1.33 mjacob return (0); 1184 1.33 mjacob } 1185 1.33 mjacob 1186 1.33 mjacob if (abts->abts_header.rqs_entry_type != RQSTYPE_ABTS_RCVD) { 1187 1.33 mjacob isp_prt(isp, ISP_LOGERR, "%s: called for non-ABTS entry (0x%x)", __func__, abts->abts_header.rqs_entry_type); 1188 1.33 mjacob return (0); 1189 1.33 mjacob } 1190 1.33 mjacob 1191 1.33 mjacob outp = isp_getrqentry(isp); 1192 1.33 mjacob if (outp == NULL) { 1193 1.33 mjacob isp_prt(isp, ISP_LOGWARN, rqo, __func__); 1194 1.33 mjacob return (1); 1195 1.33 mjacob } 1196 1.33 mjacob 1197 1.33 mjacob ISP_MEMCPY(rsp, abts, QENTRY_LEN); 1198 1.33 mjacob rsp->abts_rsp_header.rqs_entry_type = RQSTYPE_ABTS_RSP; 1199 1.33 mjacob 1200 1.33 mjacob /* 1201 1.33 mjacob * Swap destination and source for response. 1202 1.33 mjacob */ 1203 1.33 mjacob rsp->abts_rsp_r_ctl = BA_ACC; 1204 1.33 mjacob tmpw = rsp->abts_rsp_did_lo; 1205 1.33 mjacob tmpb = rsp->abts_rsp_did_hi; 1206 1.33 mjacob rsp->abts_rsp_did_lo = rsp->abts_rsp_sid_lo; 1207 1.33 mjacob rsp->abts_rsp_did_hi = rsp->abts_rsp_sid_hi; 1208 1.33 mjacob rsp->abts_rsp_sid_lo = tmpw; 1209 1.33 mjacob rsp->abts_rsp_sid_hi = tmpb; 1210 1.33 mjacob 1211 1.33 mjacob rsp->abts_rsp_f_ctl_hi ^= 0x80; /* invert Exchange Context */ 1212 1.33 mjacob rsp->abts_rsp_f_ctl_hi &= ~0x7f; /* clear Sequence Initiator and other bits */ 1213 1.33 mjacob rsp->abts_rsp_f_ctl_hi |= 0x10; /* abort the whole exchange */ 1214 1.33 mjacob rsp->abts_rsp_f_ctl_hi |= 0x8; /* last data frame of sequence */ 1215 1.33 mjacob rsp->abts_rsp_f_ctl_hi |= 0x1; /* transfer Sequence Initiative */ 1216 1.33 mjacob rsp->abts_rsp_f_ctl_lo = 0; 1217 1.33 mjacob 1218 1.33 mjacob if (errno == 0) { 1219 1.33 mjacob uint16_t rx_id, ox_id; 1220 1.33 mjacob 1221 1.33 mjacob rx_id = rsp->abts_rsp_rx_id; 1222 1.33 mjacob ox_id = rsp->abts_rsp_ox_id; 1223 1.33 mjacob ISP_MEMZERO(&rsp->abts_rsp_payload.ba_acc, sizeof (rsp->abts_rsp_payload.ba_acc)); 1224 1.33 mjacob 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); 1225 1.33 mjacob rsp->abts_rsp_payload.ba_acc.aborted_rx_id = rx_id; 1226 1.33 mjacob rsp->abts_rsp_payload.ba_acc.aborted_ox_id = ox_id; 1227 1.33 mjacob rsp->abts_rsp_payload.ba_acc.high_seq_cnt = 0xffff; 1228 1.33 mjacob } else { 1229 1.33 mjacob ISP_MEMZERO(&rsp->abts_rsp_payload.ba_rjt, sizeof (rsp->abts_rsp_payload.ba_acc)); 1230 1.33 mjacob switch (errno) { 1231 1.33 mjacob case ENOMEM: 1232 1.33 mjacob rsp->abts_rsp_payload.ba_rjt.reason = 5; /* Logical Busy */ 1233 1.33 mjacob break; 1234 1.33 mjacob default: 1235 1.33 mjacob rsp->abts_rsp_payload.ba_rjt.reason = 9; /* Unable to perform command request */ 1236 1.33 mjacob break; 1237 1.33 mjacob } 1238 1.33 mjacob } 1239 1.33 mjacob 1240 1.33 mjacob /* 1241 1.33 mjacob * The caller will have set response values as appropriate 1242 1.33 mjacob * in the ABTS structure just before calling us. 1243 1.33 mjacob */ 1244 1.33 mjacob isp_put_abts_rsp(isp, rsp, (abts_rsp_t *)outp); 1245 1.33 mjacob ISP_TDQE(isp, "isp_acknak_abts", isp->isp_reqidx, storage); 1246 1.33 mjacob ISP_SYNC_REQUEST(isp); 1247 1.33 mjacob return (0); 1248 1.1 mjacob } 1249 1.1 mjacob 1250 1.1 mjacob static void 1251 1.30 mjacob isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) 1252 1.1 mjacob { 1253 1.1 mjacob int lun; 1254 1.1 mjacob lun = aep->at_lun; 1255 1.1 mjacob /* 1256 1.1 mjacob * The firmware status (except for the QLTM_SVALID bit) indicates 1257 1.1 mjacob * why this ATIO was sent to us. 1258 1.1 mjacob * 1259 1.36 andvar * If QLTM_SVALID is set, the firmware has recommended Sense Data. 1260 1.1 mjacob * 1261 1.1 mjacob * If the DISCONNECTS DISABLED bit is set in the flags field, 1262 1.1 mjacob * we're still connected on the SCSI bus - i.e. the initiator 1263 1.1 mjacob * did not set DiscPriv in the identify message. We don't care 1264 1.1 mjacob * about this so it's ignored. 1265 1.1 mjacob */ 1266 1.1 mjacob 1267 1.33 mjacob switch (aep->at_status & ~QLTM_SVALID) { 1268 1.1 mjacob case AT_PATH_INVALID: 1269 1.1 mjacob /* 1270 1.1 mjacob * ATIO rejected by the firmware due to disabled lun. 1271 1.1 mjacob */ 1272 1.33 mjacob isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %d", lun); 1273 1.1 mjacob break; 1274 1.1 mjacob case AT_NOCAP: 1275 1.1 mjacob /* 1276 1.1 mjacob * Requested Capability not available 1277 1.1 mjacob * We sent an ATIO that overflowed the firmware's 1278 1.1 mjacob * command resource count. 1279 1.1 mjacob */ 1280 1.33 mjacob isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %d because of command count overflow", lun); 1281 1.1 mjacob break; 1282 1.1 mjacob 1283 1.1 mjacob case AT_BDR_MSG: 1284 1.1 mjacob /* 1285 1.1 mjacob * If we send an ATIO to the firmware to increment 1286 1.1 mjacob * its command resource count, and the firmware is 1287 1.1 mjacob * recovering from a Bus Device Reset, it returns 1288 1.1 mjacob * the ATIO with this status. We set the command 1289 1.17 mjacob * resource count in the Enable Lun entry and do 1290 1.1 mjacob * not increment it. Therefore we should never get 1291 1.1 mjacob * this status here. 1292 1.1 mjacob */ 1293 1.33 mjacob isp_prt(isp, ISP_LOGERR, atiocope, lun, GET_BUS_VAL(aep->at_iid)); 1294 1.1 mjacob break; 1295 1.1 mjacob 1296 1.1 mjacob case AT_CDB: /* Got a CDB */ 1297 1.1 mjacob case AT_PHASE_ERROR: /* Bus Phase Sequence Error */ 1298 1.1 mjacob /* 1299 1.1 mjacob * Punt to platform specific layer. 1300 1.1 mjacob */ 1301 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 1302 1.1 mjacob break; 1303 1.1 mjacob 1304 1.1 mjacob case AT_RESET: 1305 1.1 mjacob /* 1306 1.23 mjacob * A bus reset came along and blew away this command. Why 1307 1.1 mjacob * they do this in addition the async event code stuff, 1308 1.1 mjacob * I dunno. 1309 1.1 mjacob * 1310 1.1 mjacob * Ignore it because the async event will clear things 1311 1.1 mjacob * up for us. 1312 1.1 mjacob */ 1313 1.33 mjacob isp_prt(isp, ISP_LOGWARN, atior, lun, GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid)); 1314 1.1 mjacob break; 1315 1.1 mjacob 1316 1.1 mjacob 1317 1.1 mjacob default: 1318 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun); 1319 1.13 mjacob (void) isp_target_put_atio(isp, aep); 1320 1.1 mjacob break; 1321 1.1 mjacob } 1322 1.1 mjacob } 1323 1.1 mjacob 1324 1.1 mjacob static void 1325 1.30 mjacob isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) 1326 1.1 mjacob { 1327 1.30 mjacob int lun, iid; 1328 1.5 mjacob 1329 1.31 mjacob if (ISP_CAP_SCCFW(isp)) { 1330 1.5 mjacob lun = aep->at_scclun; 1331 1.5 mjacob } else { 1332 1.5 mjacob lun = aep->at_lun; 1333 1.5 mjacob } 1334 1.5 mjacob 1335 1.31 mjacob if (ISP_CAP_2KLOGIN(isp)) { 1336 1.30 mjacob iid = ((at2e_entry_t *)aep)->at_iid; 1337 1.30 mjacob } else { 1338 1.30 mjacob iid = aep->at_iid; 1339 1.30 mjacob } 1340 1.30 mjacob 1341 1.1 mjacob /* 1342 1.1 mjacob * The firmware status (except for the QLTM_SVALID bit) indicates 1343 1.1 mjacob * why this ATIO was sent to us. 1344 1.1 mjacob * 1345 1.36 andvar * If QLTM_SVALID is set, the firmware has recommended Sense Data. 1346 1.1 mjacob * 1347 1.1 mjacob * If the DISCONNECTS DISABLED bit is set in the flags field, 1348 1.1 mjacob * we're still connected on the SCSI bus - i.e. the initiator 1349 1.1 mjacob * did not set DiscPriv in the identify message. We don't care 1350 1.1 mjacob * about this so it's ignored. 1351 1.1 mjacob */ 1352 1.1 mjacob 1353 1.33 mjacob switch (aep->at_status & ~QLTM_SVALID) { 1354 1.1 mjacob case AT_PATH_INVALID: 1355 1.1 mjacob /* 1356 1.1 mjacob * ATIO rejected by the firmware due to disabled lun. 1357 1.1 mjacob */ 1358 1.33 mjacob isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for disabled lun %d", lun); 1359 1.1 mjacob break; 1360 1.1 mjacob case AT_NOCAP: 1361 1.1 mjacob /* 1362 1.1 mjacob * Requested Capability not available 1363 1.1 mjacob * We sent an ATIO that overflowed the firmware's 1364 1.1 mjacob * command resource count. 1365 1.1 mjacob */ 1366 1.33 mjacob isp_prt(isp, ISP_LOGERR, "rejected ATIO2 for lun %d- command count overflow", lun); 1367 1.1 mjacob break; 1368 1.1 mjacob 1369 1.1 mjacob case AT_BDR_MSG: 1370 1.1 mjacob /* 1371 1.1 mjacob * If we send an ATIO to the firmware to increment 1372 1.1 mjacob * its command resource count, and the firmware is 1373 1.1 mjacob * recovering from a Bus Device Reset, it returns 1374 1.1 mjacob * the ATIO with this status. We set the command 1375 1.1 mjacob * resource count in the Enable Lun entry and no 1376 1.1 mjacob * not increment it. Therefore we should never get 1377 1.1 mjacob * this status here. 1378 1.1 mjacob */ 1379 1.15 mjacob isp_prt(isp, ISP_LOGERR, atiocope, lun, 0); 1380 1.1 mjacob break; 1381 1.1 mjacob 1382 1.1 mjacob case AT_CDB: /* Got a CDB */ 1383 1.1 mjacob /* 1384 1.1 mjacob * Punt to platform specific layer. 1385 1.1 mjacob */ 1386 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 1387 1.1 mjacob break; 1388 1.1 mjacob 1389 1.1 mjacob case AT_RESET: 1390 1.1 mjacob /* 1391 1.38 rillig * A bus reset came along and blew away this command. Why 1392 1.38 rillig * they do this in addition to the async event code stuff, 1393 1.1 mjacob * I dunno. 1394 1.1 mjacob * 1395 1.1 mjacob * Ignore it because the async event will clear things 1396 1.1 mjacob * up for us. 1397 1.1 mjacob */ 1398 1.30 mjacob isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); 1399 1.1 mjacob break; 1400 1.1 mjacob 1401 1.1 mjacob 1402 1.1 mjacob default: 1403 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from loopid %d for lun %d", aep->at_status, iid, lun); 1404 1.13 mjacob (void) isp_target_put_atio(isp, aep); 1405 1.1 mjacob break; 1406 1.1 mjacob } 1407 1.1 mjacob } 1408 1.1 mjacob 1409 1.1 mjacob static void 1410 1.30 mjacob isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) 1411 1.1 mjacob { 1412 1.11 mjacob void *xs; 1413 1.7 mjacob int pl = ISP_LOGTDEBUG2; 1414 1.30 mjacob char *fmsg = NULL; 1415 1.1 mjacob 1416 1.11 mjacob if (ct->ct_syshandle) { 1417 1.30 mjacob xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 1418 1.30 mjacob if (xs == NULL) { 1419 1.7 mjacob pl = ISP_LOGALL; 1420 1.30 mjacob } 1421 1.1 mjacob } else { 1422 1.1 mjacob xs = NULL; 1423 1.1 mjacob } 1424 1.1 mjacob 1425 1.33 mjacob switch (ct->ct_status & ~QLTM_SVALID) { 1426 1.1 mjacob case CT_OK: 1427 1.1 mjacob /* 1428 1.1 mjacob * There are generally 3 possibilities as to why we'd get 1429 1.1 mjacob * this condition: 1430 1.1 mjacob * We disconnected after receiving a CDB. 1431 1.1 mjacob * We sent or received data. 1432 1.1 mjacob * We sent status & command complete. 1433 1.1 mjacob */ 1434 1.1 mjacob 1435 1.4 he if (ct->ct_flags & CT_SENDSTATUS) { 1436 1.4 he break; 1437 1.4 he } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { 1438 1.1 mjacob /* 1439 1.1 mjacob * Nothing to do in this case. 1440 1.1 mjacob */ 1441 1.33 mjacob isp_prt(isp, pl, "CTIO- iid %d disconnected OK", ct->ct_iid); 1442 1.1 mjacob return; 1443 1.1 mjacob } 1444 1.1 mjacob break; 1445 1.1 mjacob 1446 1.1 mjacob case CT_BDR_MSG: 1447 1.1 mjacob /* 1448 1.1 mjacob * Bus Device Reset message received or the SCSI Bus has 1449 1.1 mjacob * been Reset; the firmware has gone to Bus Free. 1450 1.1 mjacob * 1451 1.31 mjacob * The firmware generates an async mailbox interrupt to 1452 1.1 mjacob * notify us of this and returns outstanding CTIOs with this 1453 1.1 mjacob * status. These CTIOs are handled in that same way as 1454 1.1 mjacob * CT_ABORTED ones, so just fall through here. 1455 1.1 mjacob */ 1456 1.1 mjacob fmsg = "Bus Device Reset"; 1457 1.1 mjacob /*FALLTHROUGH*/ 1458 1.1 mjacob case CT_RESET: 1459 1.1 mjacob if (fmsg == NULL) 1460 1.1 mjacob fmsg = "Bus Reset"; 1461 1.1 mjacob /*FALLTHROUGH*/ 1462 1.1 mjacob case CT_ABORTED: 1463 1.1 mjacob /* 1464 1.1 mjacob * When an Abort message is received the firmware goes to 1465 1.1 mjacob * Bus Free and returns all outstanding CTIOs with the status 1466 1.1 mjacob * set, then sends us an Immediate Notify entry. 1467 1.1 mjacob */ 1468 1.1 mjacob if (fmsg == NULL) 1469 1.15 mjacob fmsg = "ABORT TAG message sent by Initiator"; 1470 1.30 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); 1471 1.1 mjacob break; 1472 1.1 mjacob 1473 1.1 mjacob case CT_INVAL: 1474 1.1 mjacob /* 1475 1.1 mjacob * CTIO rejected by the firmware due to disabled lun. 1476 1.1 mjacob * "Cannot Happen". 1477 1.1 mjacob */ 1478 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %d", ct->ct_lun); 1479 1.1 mjacob break; 1480 1.1 mjacob 1481 1.1 mjacob case CT_NOPATH: 1482 1.1 mjacob /* 1483 1.1 mjacob * CTIO rejected by the firmware due "no path for the 1484 1.1 mjacob * nondisconnecting nexus specified". This means that 1485 1.1 mjacob * we tried to access the bus while a non-disconnecting 1486 1.1 mjacob * command is in process. 1487 1.1 mjacob */ 1488 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%d", ct->ct_iid, ct->ct_tgt, ct->ct_lun); 1489 1.1 mjacob break; 1490 1.1 mjacob 1491 1.1 mjacob case CT_RSELTMO: 1492 1.1 mjacob fmsg = "Reselection"; 1493 1.1 mjacob /*FALLTHROUGH*/ 1494 1.1 mjacob case CT_TIMEOUT: 1495 1.1 mjacob if (fmsg == NULL) 1496 1.1 mjacob fmsg = "Command"; 1497 1.31 mjacob isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); 1498 1.1 mjacob break; 1499 1.1 mjacob 1500 1.13 mjacob case CT_PANIC: 1501 1.13 mjacob if (fmsg == NULL) 1502 1.13 mjacob fmsg = "Unrecoverable Error"; 1503 1.13 mjacob /*FALLTHROUGH*/ 1504 1.1 mjacob case CT_ERR: 1505 1.13 mjacob if (fmsg == NULL) 1506 1.13 mjacob fmsg = "Completed with Error"; 1507 1.1 mjacob /*FALLTHROUGH*/ 1508 1.1 mjacob case CT_PHASE_ERROR: 1509 1.1 mjacob if (fmsg == NULL) 1510 1.1 mjacob fmsg = "Phase Sequence Error"; 1511 1.1 mjacob /*FALLTHROUGH*/ 1512 1.1 mjacob case CT_TERMINATED: 1513 1.1 mjacob if (fmsg == NULL) 1514 1.1 mjacob fmsg = "terminated by TERMINATE TRANSFER"; 1515 1.1 mjacob /*FALLTHROUGH*/ 1516 1.1 mjacob case CT_NOACK: 1517 1.1 mjacob if (fmsg == NULL) 1518 1.1 mjacob fmsg = "unacknowledged Immediate Notify pending"; 1519 1.7 mjacob isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); 1520 1.1 mjacob break; 1521 1.1 mjacob default: 1522 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", ct->ct_status & ~QLTM_SVALID); 1523 1.1 mjacob break; 1524 1.1 mjacob } 1525 1.1 mjacob 1526 1.1 mjacob if (xs == NULL) { 1527 1.1 mjacob /* 1528 1.1 mjacob * There may be more than one CTIO for a data transfer, 1529 1.1 mjacob * or this may be a status CTIO we're not monitoring. 1530 1.1 mjacob * 1531 1.1 mjacob * The assumption is that they'll all be returned in the 1532 1.1 mjacob * order we got them. 1533 1.1 mjacob */ 1534 1.11 mjacob if (ct->ct_syshandle == 0) { 1535 1.1 mjacob if ((ct->ct_flags & CT_SENDSTATUS) == 0) { 1536 1.33 mjacob isp_prt(isp, pl, "intermediate CTIO completed ok"); 1537 1.1 mjacob } else { 1538 1.33 mjacob isp_prt(isp, pl, "unmonitored CTIO completed ok"); 1539 1.1 mjacob } 1540 1.1 mjacob } else { 1541 1.33 mjacob isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1542 1.1 mjacob } 1543 1.1 mjacob } else { 1544 1.14 mjacob /* 1545 1.14 mjacob * Final CTIO completed. Release DMA resources and 1546 1.14 mjacob * notify platform dependent layers. 1547 1.14 mjacob */ 1548 1.14 mjacob if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { 1549 1.11 mjacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1550 1.1 mjacob } 1551 1.13 mjacob isp_prt(isp, pl, "final CTIO complete"); 1552 1.1 mjacob /* 1553 1.1 mjacob * The platform layer will destroy the handle if appropriate. 1554 1.1 mjacob */ 1555 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1556 1.1 mjacob } 1557 1.1 mjacob } 1558 1.1 mjacob 1559 1.1 mjacob static void 1560 1.30 mjacob isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) 1561 1.1 mjacob { 1562 1.30 mjacob void *xs; 1563 1.7 mjacob int pl = ISP_LOGTDEBUG2; 1564 1.30 mjacob char *fmsg = NULL; 1565 1.1 mjacob 1566 1.11 mjacob if (ct->ct_syshandle) { 1567 1.30 mjacob xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 1568 1.30 mjacob if (xs == NULL) { 1569 1.7 mjacob pl = ISP_LOGALL; 1570 1.30 mjacob } 1571 1.1 mjacob } else { 1572 1.1 mjacob xs = NULL; 1573 1.1 mjacob } 1574 1.1 mjacob 1575 1.33 mjacob switch (ct->ct_status & ~QLTM_SVALID) { 1576 1.14 mjacob case CT_BUS_ERROR: 1577 1.14 mjacob isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 1578 1.14 mjacob /* FALL Through */ 1579 1.14 mjacob case CT_DATA_OVER: 1580 1.14 mjacob case CT_DATA_UNDER: 1581 1.1 mjacob case CT_OK: 1582 1.1 mjacob /* 1583 1.1 mjacob * There are generally 2 possibilities as to why we'd get 1584 1.1 mjacob * this condition: 1585 1.1 mjacob * We sent or received data. 1586 1.1 mjacob * We sent status & command complete. 1587 1.1 mjacob */ 1588 1.1 mjacob 1589 1.1 mjacob break; 1590 1.1 mjacob 1591 1.1 mjacob case CT_BDR_MSG: 1592 1.1 mjacob /* 1593 1.14 mjacob * Target Reset function received. 1594 1.1 mjacob * 1595 1.31 mjacob * The firmware generates an async mailbox interrupt to 1596 1.1 mjacob * notify us of this and returns outstanding CTIOs with this 1597 1.1 mjacob * status. These CTIOs are handled in that same way as 1598 1.1 mjacob * CT_ABORTED ones, so just fall through here. 1599 1.1 mjacob */ 1600 1.30 mjacob fmsg = "TARGET RESET"; 1601 1.1 mjacob /*FALLTHROUGH*/ 1602 1.1 mjacob case CT_RESET: 1603 1.1 mjacob if (fmsg == NULL) 1604 1.14 mjacob fmsg = "LIP Reset"; 1605 1.1 mjacob /*FALLTHROUGH*/ 1606 1.1 mjacob case CT_ABORTED: 1607 1.1 mjacob /* 1608 1.1 mjacob * When an Abort message is received the firmware goes to 1609 1.1 mjacob * Bus Free and returns all outstanding CTIOs with the status 1610 1.1 mjacob * set, then sends us an Immediate Notify entry. 1611 1.1 mjacob */ 1612 1.30 mjacob if (fmsg == NULL) { 1613 1.30 mjacob fmsg = "ABORT"; 1614 1.30 mjacob } 1615 1.1 mjacob 1616 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 1617 1.1 mjacob break; 1618 1.1 mjacob 1619 1.1 mjacob case CT_INVAL: 1620 1.1 mjacob /* 1621 1.2 mjacob * CTIO rejected by the firmware - invalid data direction. 1622 1.1 mjacob */ 1623 1.30 mjacob isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction"); 1624 1.1 mjacob break; 1625 1.1 mjacob 1626 1.1 mjacob case CT_RSELTMO: 1627 1.14 mjacob fmsg = "failure to reconnect to initiator"; 1628 1.1 mjacob /*FALLTHROUGH*/ 1629 1.1 mjacob case CT_TIMEOUT: 1630 1.1 mjacob if (fmsg == NULL) 1631 1.14 mjacob fmsg = "command"; 1632 1.31 mjacob isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); 1633 1.1 mjacob break; 1634 1.1 mjacob 1635 1.1 mjacob case CT_ERR: 1636 1.1 mjacob fmsg = "Completed with Error"; 1637 1.1 mjacob /*FALLTHROUGH*/ 1638 1.1 mjacob case CT_LOGOUT: 1639 1.1 mjacob if (fmsg == NULL) 1640 1.1 mjacob fmsg = "Port Logout"; 1641 1.1 mjacob /*FALLTHROUGH*/ 1642 1.30 mjacob case CT_PORTUNAVAIL: 1643 1.1 mjacob if (fmsg == NULL) 1644 1.1 mjacob fmsg = "Port not available"; 1645 1.24 mjacob /*FALLTHROUGH*/ 1646 1.14 mjacob case CT_PORTCHANGED: 1647 1.14 mjacob if (fmsg == NULL) 1648 1.14 mjacob fmsg = "Port Changed"; 1649 1.24 mjacob /*FALLTHROUGH*/ 1650 1.1 mjacob case CT_NOACK: 1651 1.1 mjacob if (fmsg == NULL) 1652 1.1 mjacob fmsg = "unacknowledged Immediate Notify pending"; 1653 1.30 mjacob isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 1654 1.1 mjacob break; 1655 1.1 mjacob 1656 1.1 mjacob case CT_INVRXID: 1657 1.1 mjacob /* 1658 1.1 mjacob * CTIO rejected by the firmware because an invalid RX_ID. 1659 1.1 mjacob * Just print a message. 1660 1.1 mjacob */ 1661 1.33 mjacob isp_prt(isp, ISP_LOGWARN, "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1662 1.1 mjacob break; 1663 1.1 mjacob 1664 1.1 mjacob default: 1665 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", ct->ct_status & ~QLTM_SVALID); 1666 1.1 mjacob break; 1667 1.1 mjacob } 1668 1.1 mjacob 1669 1.1 mjacob if (xs == NULL) { 1670 1.1 mjacob /* 1671 1.1 mjacob * There may be more than one CTIO for a data transfer, 1672 1.1 mjacob * or this may be a status CTIO we're not monitoring. 1673 1.1 mjacob * 1674 1.1 mjacob * The assumption is that they'll all be returned in the 1675 1.1 mjacob * order we got them. 1676 1.1 mjacob */ 1677 1.11 mjacob if (ct->ct_syshandle == 0) { 1678 1.30 mjacob if ((ct->ct_flags & CT2_SENDSTATUS) == 0) { 1679 1.33 mjacob isp_prt(isp, pl, "intermediate CTIO completed ok"); 1680 1.1 mjacob } else { 1681 1.33 mjacob isp_prt(isp, pl, "unmonitored CTIO completed ok"); 1682 1.1 mjacob } 1683 1.1 mjacob } else { 1684 1.33 mjacob isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1685 1.1 mjacob } 1686 1.1 mjacob } else { 1687 1.14 mjacob if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { 1688 1.14 mjacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1689 1.14 mjacob } 1690 1.30 mjacob if (ct->ct_flags & CT2_SENDSTATUS) { 1691 1.30 mjacob /* 1692 1.30 mjacob * Sent status and command complete. 1693 1.30 mjacob * 1694 1.30 mjacob * We're now really done with this command, so we 1695 1.30 mjacob * punt to the platform dependent layers because 1696 1.30 mjacob * only there can we do the appropriate command 1697 1.30 mjacob * complete thread synchronization. 1698 1.30 mjacob */ 1699 1.30 mjacob isp_prt(isp, pl, "status CTIO complete"); 1700 1.30 mjacob } else { 1701 1.30 mjacob /* 1702 1.30 mjacob * Final CTIO completed. Release DMA resources and 1703 1.30 mjacob * notify platform dependent layers. 1704 1.30 mjacob */ 1705 1.30 mjacob isp_prt(isp, pl, "data CTIO complete"); 1706 1.30 mjacob } 1707 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1708 1.30 mjacob /* 1709 1.30 mjacob * The platform layer will destroy the handle if appropriate. 1710 1.30 mjacob */ 1711 1.30 mjacob } 1712 1.30 mjacob } 1713 1.30 mjacob 1714 1.30 mjacob static void 1715 1.30 mjacob isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) 1716 1.30 mjacob { 1717 1.30 mjacob void *xs; 1718 1.30 mjacob int pl = ISP_LOGTDEBUG2; 1719 1.30 mjacob char *fmsg = NULL; 1720 1.30 mjacob 1721 1.30 mjacob if (ct->ct_syshandle) { 1722 1.30 mjacob xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 1723 1.30 mjacob if (xs == NULL) { 1724 1.30 mjacob pl = ISP_LOGALL; 1725 1.30 mjacob } 1726 1.30 mjacob } else { 1727 1.30 mjacob xs = NULL; 1728 1.30 mjacob } 1729 1.30 mjacob 1730 1.33 mjacob switch (ct->ct_nphdl) { 1731 1.30 mjacob case CT7_BUS_ERROR: 1732 1.30 mjacob isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 1733 1.30 mjacob /* FALL Through */ 1734 1.30 mjacob case CT7_DATA_OVER: 1735 1.30 mjacob case CT7_DATA_UNDER: 1736 1.30 mjacob case CT7_OK: 1737 1.30 mjacob /* 1738 1.30 mjacob * There are generally 2 possibilities as to why we'd get 1739 1.30 mjacob * this condition: 1740 1.30 mjacob * We sent or received data. 1741 1.30 mjacob * We sent status & command complete. 1742 1.30 mjacob */ 1743 1.30 mjacob 1744 1.30 mjacob break; 1745 1.30 mjacob 1746 1.30 mjacob case CT7_RESET: 1747 1.30 mjacob if (fmsg == NULL) { 1748 1.30 mjacob fmsg = "LIP Reset"; 1749 1.30 mjacob } 1750 1.30 mjacob /*FALLTHROUGH*/ 1751 1.30 mjacob case CT7_ABORTED: 1752 1.30 mjacob /* 1753 1.30 mjacob * When an Abort message is received the firmware goes to 1754 1.30 mjacob * Bus Free and returns all outstanding CTIOs with the status 1755 1.30 mjacob * set, then sends us an Immediate Notify entry. 1756 1.30 mjacob */ 1757 1.30 mjacob if (fmsg == NULL) { 1758 1.30 mjacob fmsg = "ABORT"; 1759 1.30 mjacob } 1760 1.33 mjacob isp_prt(isp, ISP_LOGTDEBUG0, "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 1761 1.30 mjacob break; 1762 1.30 mjacob 1763 1.30 mjacob case CT7_TIMEOUT: 1764 1.30 mjacob if (fmsg == NULL) { 1765 1.30 mjacob fmsg = "command"; 1766 1.30 mjacob } 1767 1.31 mjacob isp_prt(isp, ISP_LOGWARN, "Firmware timed out on %s", fmsg); 1768 1.30 mjacob break; 1769 1.30 mjacob 1770 1.30 mjacob case CT7_ERR: 1771 1.30 mjacob fmsg = "Completed with Error"; 1772 1.30 mjacob /*FALLTHROUGH*/ 1773 1.30 mjacob case CT7_LOGOUT: 1774 1.30 mjacob if (fmsg == NULL) { 1775 1.30 mjacob fmsg = "Port Logout"; 1776 1.30 mjacob } 1777 1.30 mjacob /*FALLTHROUGH*/ 1778 1.30 mjacob case CT7_PORTUNAVAIL: 1779 1.30 mjacob if (fmsg == NULL) { 1780 1.30 mjacob fmsg = "Port not available"; 1781 1.30 mjacob } 1782 1.30 mjacob /*FALLTHROUGH*/ 1783 1.30 mjacob case CT7_PORTCHANGED: 1784 1.30 mjacob if (fmsg == NULL) { 1785 1.30 mjacob fmsg = "Port Changed"; 1786 1.30 mjacob } 1787 1.30 mjacob isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 1788 1.30 mjacob break; 1789 1.30 mjacob 1790 1.30 mjacob case CT7_INVRXID: 1791 1.30 mjacob /* 1792 1.30 mjacob * CTIO rejected by the firmware because an invalid RX_ID. 1793 1.30 mjacob * Just print a message. 1794 1.30 mjacob */ 1795 1.33 mjacob isp_prt(isp, ISP_LOGWARN, "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1796 1.30 mjacob break; 1797 1.30 mjacob 1798 1.30 mjacob case CT7_REASSY_ERR: 1799 1.30 mjacob isp_prt(isp, ISP_LOGWARN, "reassembly error"); 1800 1.30 mjacob break; 1801 1.30 mjacob 1802 1.30 mjacob case CT7_SRR: 1803 1.30 mjacob isp_prt(isp, ISP_LOGWARN, "SRR received"); 1804 1.30 mjacob break; 1805 1.30 mjacob 1806 1.30 mjacob default: 1807 1.33 mjacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", ct->ct_nphdl); 1808 1.30 mjacob break; 1809 1.30 mjacob } 1810 1.30 mjacob 1811 1.30 mjacob if (xs == NULL) { 1812 1.30 mjacob /* 1813 1.30 mjacob * There may be more than one CTIO for a data transfer, 1814 1.30 mjacob * or this may be a status CTIO we're not monitoring. 1815 1.30 mjacob * 1816 1.30 mjacob * The assumption is that they'll all be returned in the 1817 1.30 mjacob * order we got them. 1818 1.30 mjacob */ 1819 1.30 mjacob if (ct->ct_syshandle == 0) { 1820 1.30 mjacob if (ct->ct_flags & CT7_TERMINATE) { 1821 1.33 mjacob isp_prt(isp, ISP_LOGINFO, "termination of 0x%x complete", ct->ct_rxid); 1822 1.30 mjacob } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) { 1823 1.33 mjacob isp_prt(isp, pl, "intermediate CTIO completed ok"); 1824 1.30 mjacob } else { 1825 1.33 mjacob isp_prt(isp, pl, "unmonitored CTIO completed ok"); 1826 1.30 mjacob } 1827 1.30 mjacob } else { 1828 1.33 mjacob isp_prt(isp, pl, "NO xs for CTIO (handle 0x%x) status 0x%x", ct->ct_syshandle, ct->ct_nphdl); 1829 1.30 mjacob } 1830 1.30 mjacob } else { 1831 1.33 mjacob if ((ct->ct_flags & CT7_DATAMASK) != CT7_NO_DATA) { 1832 1.30 mjacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1833 1.30 mjacob } 1834 1.33 mjacob if (ct->ct_flags & CT7_SENDSTATUS) { 1835 1.1 mjacob /* 1836 1.1 mjacob * Sent status and command complete. 1837 1.1 mjacob * 1838 1.1 mjacob * We're now really done with this command, so we 1839 1.1 mjacob * punt to the platform dependent layers because 1840 1.1 mjacob * only there can we do the appropriate command 1841 1.1 mjacob * complete thread synchronization. 1842 1.1 mjacob */ 1843 1.7 mjacob isp_prt(isp, pl, "status CTIO complete"); 1844 1.1 mjacob } else { 1845 1.1 mjacob /* 1846 1.1 mjacob * Final CTIO completed. Release DMA resources and 1847 1.1 mjacob * notify platform dependent layers. 1848 1.1 mjacob */ 1849 1.7 mjacob isp_prt(isp, pl, "data CTIO complete"); 1850 1.1 mjacob } 1851 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1852 1.1 mjacob /* 1853 1.1 mjacob * The platform layer will destroy the handle if appropriate. 1854 1.1 mjacob */ 1855 1.1 mjacob } 1856 1.1 mjacob } 1857 1.31 mjacob 1858 1.31 mjacob static void 1859 1.31 mjacob isp_handle_24xx_inotify(ispsoftc_t *isp, in_fcentry_24xx_t *inot_24xx) 1860 1.31 mjacob { 1861 1.31 mjacob uint8_t ochan, chan, lochan, hichan; 1862 1.31 mjacob 1863 1.31 mjacob /* 1864 1.31 mjacob * Check to see whether we got a wildcard channel. 1865 1.31 mjacob * If so, we have to iterate over all channels. 1866 1.31 mjacob */ 1867 1.33 mjacob ochan = chan = ISP_GET_VPIDX(isp, inot_24xx->in_vpidx); 1868 1.31 mjacob if (chan == 0xff) { 1869 1.31 mjacob lochan = 0; 1870 1.31 mjacob hichan = isp->isp_nchan; 1871 1.31 mjacob } else { 1872 1.33 mjacob if (chan >= isp->isp_nchan) { 1873 1.33 mjacob char buf[64]; 1874 1.33 mjacob ISP_SNPRINTF(buf, sizeof buf, "%s: bad channel %d for status 0x%x", __func__, chan, inot_24xx->in_status); 1875 1.33 mjacob isp_print_bytes(isp, buf, QENTRY_LEN, inot_24xx); 1876 1.33 mjacob (void) isp_notify_ack(isp, inot_24xx); 1877 1.31 mjacob return; 1878 1.31 mjacob } 1879 1.31 mjacob lochan = chan; 1880 1.31 mjacob hichan = chan + 1; 1881 1.31 mjacob } 1882 1.33 mjacob 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); 1883 1.31 mjacob for (chan = lochan; chan < hichan; chan++) { 1884 1.31 mjacob switch (inot_24xx->in_status) { 1885 1.31 mjacob case IN24XX_LIP_RESET: 1886 1.31 mjacob case IN24XX_LINK_RESET: 1887 1.31 mjacob case IN24XX_PORT_LOGOUT: 1888 1.31 mjacob case IN24XX_PORT_CHANGED: 1889 1.31 mjacob case IN24XX_LINK_FAILED: 1890 1.31 mjacob case IN24XX_SRR_RCVD: 1891 1.31 mjacob case IN24XX_ELS_RCVD: 1892 1.33 mjacob inot_24xx->in_vpidx = chan; 1893 1.31 mjacob isp_async(isp, ISPASYNC_TARGET_ACTION, inot_24xx); 1894 1.31 mjacob break; 1895 1.31 mjacob default: 1896 1.33 mjacob isp_prt(isp, ISP_LOGINFO, "%s: unhandled status (0x%x) for chan %d", __func__, inot_24xx->in_status, chan); 1897 1.33 mjacob (void) isp_notify_ack(isp, inot_24xx); 1898 1.31 mjacob break; 1899 1.31 mjacob } 1900 1.31 mjacob } 1901 1.33 mjacob inot_24xx->in_vpidx = ochan; 1902 1.31 mjacob } 1903 1.1 mjacob #endif 1904