1 /* $FreeBSD$ */ 2 /* 3 * Platform (FreeBSD) dependent common attachment code for Qlogic adapters. 4 * 5 *--------------------------------------- 6 * Copyright (c) 1997, 1998, 1999 by Matthew Jacob 7 * NASA/Ames Research Center 8 * All rights reserved. 9 *--------------------------------------- 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice immediately at the beginning of the file, without modification, 16 * this list of conditions, and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 #include <dev/isp/isp_freebsd.h> 36 37 static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *); 38 static void isp_poll(struct cam_sim *); 39 static void isp_action(struct cam_sim *, union ccb *); 40 static void isp_relsim(void *); 41 42 /* #define ISP_LUN0_ONLY 1 */ 43 #ifdef CAMDEBUG 44 int isp_debug = 1; 45 #else 46 int isp_debug = 0; 47 #endif 48 49 void 50 isp_attach(struct ispsoftc *isp) 51 { 52 int primary, secondary; 53 struct ccb_setasync csa; 54 struct cam_devq *devq; 55 struct cam_sim *sim; 56 struct cam_path *path; 57 58 /* 59 * Establish (in case of 12X0) which bus is the primary. 60 */ 61 62 primary = 0; 63 secondary = 1; 64 65 /* 66 * Create the device queue for our SIM(s). 67 */ 68 devq = cam_simq_alloc(isp->isp_maxcmds); 69 if (devq == NULL) { 70 return; 71 } 72 73 /* 74 * Construct our SIM entry. 75 */ 76 sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, 77 isp->isp_unit, 1, isp->isp_maxcmds, devq); 78 if (sim == NULL) { 79 cam_simq_free(devq); 80 return; 81 } 82 if (xpt_bus_register(sim, primary) != CAM_SUCCESS) { 83 cam_sim_free(sim, TRUE); 84 return; 85 } 86 87 if (xpt_create_path(&path, NULL, cam_sim_path(sim), 88 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 89 xpt_bus_deregister(cam_sim_path(sim)); 90 cam_sim_free(sim, TRUE); 91 return; 92 } 93 94 xpt_setup_ccb(&csa.ccb_h, path, 5); 95 csa.ccb_h.func_code = XPT_SASYNC_CB; 96 csa.event_enable = AC_LOST_DEVICE; 97 csa.callback = isp_cam_async; 98 csa.callback_arg = sim; 99 xpt_action((union ccb *)&csa); 100 isp->isp_sim = sim; 101 isp->isp_path = path; 102 103 /* 104 * If we have a second channel, construct SIM entry for that. 105 */ 106 if (IS_12X0(isp)) { 107 sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, 108 isp->isp_unit, 1, isp->isp_maxcmds, devq); 109 if (sim == NULL) { 110 xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 111 xpt_free_path(isp->isp_path); 112 cam_simq_free(devq); 113 return; 114 } 115 if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) { 116 xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 117 xpt_free_path(isp->isp_path); 118 cam_sim_free(sim, TRUE); 119 return; 120 } 121 122 if (xpt_create_path(&path, NULL, cam_sim_path(sim), 123 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 124 xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 125 xpt_free_path(isp->isp_path); 126 xpt_bus_deregister(cam_sim_path(sim)); 127 cam_sim_free(sim, TRUE); 128 return; 129 } 130 131 xpt_setup_ccb(&csa.ccb_h, path, 5); 132 csa.ccb_h.func_code = XPT_SASYNC_CB; 133 csa.event_enable = AC_LOST_DEVICE; 134 csa.callback = isp_cam_async; 135 csa.callback_arg = sim; 136 xpt_action((union ccb *)&csa); 137 isp->isp_sim2 = sim; 138 isp->isp_path2 = path; 139 } 140 if (isp->isp_state == ISP_INITSTATE) { 141 isp->isp_state = ISP_RUNSTATE; 142 } 143 } 144 145 static void 146 isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg) 147 { 148 struct cam_sim *sim; 149 struct ispsoftc *isp; 150 151 sim = (struct cam_sim *)cbarg; 152 isp = (struct ispsoftc *) cam_sim_softc(sim); 153 switch (code) { 154 case AC_LOST_DEVICE: 155 if (IS_SCSI(isp)) { 156 u_int16_t oflags, nflags; 157 sdparam *sdp = isp->isp_param; 158 int s, tgt = xpt_path_target_id(path); 159 160 s = splcam(); 161 sdp += cam_sim_bus(sim); 162 isp->isp_update |= (1 << cam_sim_bus(sim)); 163 nflags = DPARM_SAFE_DFLT; 164 if (ISP_FW_REVX(isp->isp_fwrev) >= 165 ISP_FW_REV(7, 55, 0)) { 166 nflags |= DPARM_NARROW | DPARM_ASYNC; 167 } 168 oflags = sdp->isp_devparam[tgt].dev_flags; 169 sdp->isp_devparam[tgt].dev_flags = nflags; 170 sdp->isp_devparam[tgt].dev_update = 1; 171 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); 172 sdp->isp_devparam[tgt].dev_flags = oflags; 173 (void) splx(s); 174 } 175 break; 176 default: 177 printf("%s: isp_attach Async Code 0x%x\n", isp->isp_name, code); 178 break; 179 } 180 } 181 182 static void 183 isp_poll(struct cam_sim *sim) 184 { 185 isp_intr((struct ispsoftc *) cam_sim_softc(sim)); 186 } 187 188 static void 189 isp_relsim(void *arg) 190 { 191 struct ispsoftc *isp = arg; 192 int s = splcam(); 193 if (isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED) { 194 int wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED; 195 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_TIMED; 196 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { 197 xpt_release_simq(isp->isp_sim, 1); 198 IDPRINTF(3, ("%s: timed relsimq\n", isp->isp_name)); 199 } 200 } 201 splx(s); 202 } 203 204 static void 205 isp_action(struct cam_sim *sim, union ccb *ccb) 206 { 207 int s, bus, tgt, error; 208 struct ispsoftc *isp; 209 struct ccb_trans_settings *cts; 210 211 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); 212 213 isp = (struct ispsoftc *)cam_sim_softc(sim); 214 ccb->ccb_h.sim_priv.entries[0].field = 0; 215 ccb->ccb_h.sim_priv.entries[1].ptr = isp; 216 if (isp->isp_state != ISP_RUNSTATE && 217 ccb->ccb_h.func_code == XPT_SCSI_IO) { 218 s = splcam(); 219 DISABLE_INTS(isp); 220 isp_init(isp); 221 if (isp->isp_state != ISP_INITSTATE) { 222 (void) splx(s); 223 /* 224 * Lie. Say it was a selection timeout. 225 */ 226 ccb->ccb_h.status = CAM_SEL_TIMEOUT; 227 ccb->ccb_h.status |= CAM_DEV_QFRZN; 228 xpt_freeze_devq(ccb->ccb_h.path, 1); 229 xpt_done(ccb); 230 return; 231 } 232 isp->isp_state = ISP_RUNSTATE; 233 ENABLE_INTS(isp); 234 (void) splx(s); 235 } 236 IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name, 237 ccb->ccb_h.func_code)); 238 239 switch (ccb->ccb_h.func_code) { 240 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 241 /* 242 * Do a couple of preliminary checks... 243 */ 244 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 245 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { 246 ccb->ccb_h.status = CAM_REQ_INVALID; 247 xpt_done(ccb); 248 break; 249 } 250 } 251 #ifdef DIAGNOSTIC 252 if (ccb->ccb_h.target_id > (ISP_MAX_TARGETS(isp) - 1)) { 253 ccb->ccb_h.status = CAM_PATH_INVALID; 254 } else if (ccb->ccb_h.target_lun > (ISP_MAX_LUNS(isp) - 1)) { 255 ccb->ccb_h.status = CAM_PATH_INVALID; 256 } 257 if (ccb->ccb_h.status == CAM_PATH_INVALID) { 258 printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n", 259 isp->isp_name, ccb->ccb_h.target_id, 260 ccb->ccb_h.target_lun); 261 xpt_done(ccb); 262 break; 263 } 264 #endif 265 ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK; 266 s = splcam(); 267 DISABLE_INTS(isp); 268 error = ispscsicmd((ISP_SCSI_XFER_T *) ccb); 269 ENABLE_INTS(isp); 270 splx(s); 271 switch (error) { 272 case CMD_QUEUED: 273 ccb->ccb_h.status |= CAM_SIM_QUEUED; 274 break; 275 case CMD_RQLATER: 276 if (isp->isp_osinfo.simqfrozen == 0) { 277 IDPRINTF(3, ("%s: RQLATER freeze simq\n", 278 isp->isp_name)); 279 isp->isp_osinfo.simqfrozen |= SIMQFRZ_TIMED; 280 timeout(isp_relsim, isp, 500); 281 xpt_freeze_simq(sim, 1); 282 } 283 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 284 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 285 xpt_done(ccb); 286 break; 287 case CMD_EAGAIN: 288 if (isp->isp_osinfo.simqfrozen == 0) { 289 xpt_freeze_simq(sim, 1); 290 IDPRINTF(3, ("%s: EAGAIN freeze simq\n", 291 isp->isp_name)); 292 } 293 isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; 294 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 295 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 296 xpt_done(ccb); 297 break; 298 case CMD_COMPLETE: 299 isp_done((struct ccb_scsiio *) ccb); 300 break; 301 default: 302 printf("%s: What's this? 0x%x at %d in file %s\n", 303 isp->isp_name, error, __LINE__, __FILE__); 304 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 305 ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 306 xpt_done(ccb); 307 } 308 break; 309 310 case XPT_EN_LUN: /* Enable LUN as a target */ 311 case XPT_TARGET_IO: /* Execute target I/O request */ 312 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 313 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 314 ccb->ccb_h.status = CAM_REQ_INVALID; 315 xpt_done(ccb); 316 break; 317 318 case XPT_RESET_DEV: /* BDR the specified SCSI device */ 319 tgt = ccb->ccb_h.target_id; /* XXX: Which Bus? */ 320 s = splcam(); 321 error = isp_control(isp, ISPCTL_RESET_DEV, &tgt); 322 (void) splx(s); 323 if (error) { 324 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 325 } else { 326 ccb->ccb_h.status = CAM_REQ_CMP; 327 } 328 xpt_done(ccb); 329 break; 330 case XPT_ABORT: /* Abort the specified CCB */ 331 s = splcam(); 332 error = isp_control(isp, ISPCTL_ABORT_CMD, ccb); 333 (void) splx(s); 334 if (error) { 335 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 336 } else { 337 ccb->ccb_h.status = CAM_REQ_CMP; 338 } 339 xpt_done(ccb); 340 break; 341 342 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ 343 344 cts = &ccb->cts; 345 tgt = cts->ccb_h.target_id; 346 s = splcam(); 347 if (IS_SCSI(isp)) { 348 sdparam *sdp = isp->isp_param; 349 u_int16_t *dptr; 350 int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); 351 352 sdp += bus; 353 #if 0 354 if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) 355 dptr = &sdp->isp_devparam[tgt].cur_dflags; 356 else 357 dptr = &sdp->isp_devparam[tgt].dev_flags; 358 #else 359 /* 360 * We always update (internally) from dev_flags 361 * so any request to change settings just gets 362 * vectored to that location. 363 */ 364 dptr = &sdp->isp_devparam[tgt].dev_flags; 365 #endif 366 367 /* 368 * Note that these operations affect the 369 * the goal flags (dev_flags)- not 370 * the current state flags. Then we mark 371 * things so that the next operation to 372 * this HBA will cause the update to occur. 373 */ 374 if (cts->valid & CCB_TRANS_DISC_VALID) { 375 if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) { 376 *dptr |= DPARM_DISC; 377 } else { 378 *dptr &= ~DPARM_DISC; 379 } 380 } 381 if (cts->valid & CCB_TRANS_TQ_VALID) { 382 if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) { 383 *dptr |= DPARM_TQING; 384 } else { 385 *dptr &= ~DPARM_TQING; 386 } 387 } 388 if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { 389 switch (cts->bus_width) { 390 case MSG_EXT_WDTR_BUS_16_BIT: 391 *dptr |= DPARM_WIDE; 392 break; 393 default: 394 *dptr &= ~DPARM_WIDE; 395 } 396 } 397 /* 398 * Any SYNC RATE of nonzero and SYNC_OFFSET 399 * of nonzero will cause us to go to the 400 * selected (from NVRAM) maximum value for 401 * this device. At a later point, we'll 402 * allow finer control. 403 */ 404 if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && 405 (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) && 406 (cts->sync_offset > 0)) { 407 *dptr |= DPARM_SYNC; 408 } else { 409 *dptr &= ~DPARM_SYNC; 410 } 411 *dptr |= DPARM_SAFE_DFLT; 412 if (bootverbose || isp->isp_dblev >= 3) 413 printf("%s: %d.%d set %s period 0x%x offset " 414 "0x%x flags 0x%x\n", isp->isp_name, bus, 415 tgt, 416 (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? 417 "current" : "user", 418 sdp->isp_devparam[tgt].sync_period, 419 sdp->isp_devparam[tgt].sync_offset, 420 sdp->isp_devparam[tgt].dev_flags); 421 sdp->isp_devparam[tgt].dev_update = 1; 422 isp->isp_update |= (1 << bus); 423 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); 424 } 425 (void) splx(s); 426 ccb->ccb_h.status = CAM_REQ_CMP; 427 xpt_done(ccb); 428 break; 429 430 case XPT_GET_TRAN_SETTINGS: 431 432 cts = &ccb->cts; 433 tgt = cts->ccb_h.target_id; 434 if (IS_FC(isp)) { 435 /* 436 * a lot of normal SCSI things don't make sense. 437 */ 438 cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB; 439 cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 440 /* 441 * How do you measure the width of a high 442 * speed serial bus? Well, in bytes. 443 * 444 * Offset and period make no sense, though, so we set 445 * (above) a 'base' transfer speed to be gigabit. 446 */ 447 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 448 } else { 449 sdparam *sdp = isp->isp_param; 450 u_int16_t dval, pval, oval; 451 int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); 452 453 sdp += bus; 454 if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) { 455 s = splcam(); 456 /* 457 * First do a refresh to see if things 458 * have changed recently! 459 */ 460 sdp->isp_devparam[tgt].dev_refresh = 1; 461 isp->isp_update |= (1 << bus); 462 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, 463 NULL); 464 (void) splx(s); 465 dval = sdp->isp_devparam[tgt].cur_dflags; 466 oval = sdp->isp_devparam[tgt].cur_offset; 467 pval = sdp->isp_devparam[tgt].cur_period; 468 } else { 469 dval = sdp->isp_devparam[tgt].dev_flags; 470 oval = sdp->isp_devparam[tgt].sync_offset; 471 pval = sdp->isp_devparam[tgt].sync_period; 472 } 473 474 s = splcam(); 475 cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); 476 477 if (dval & DPARM_DISC) { 478 cts->flags |= CCB_TRANS_DISC_ENB; 479 } 480 if (dval & DPARM_TQING) { 481 cts->flags |= CCB_TRANS_TAG_ENB; 482 } 483 if (dval & DPARM_WIDE) { 484 cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 485 } else { 486 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 487 } 488 cts->valid = CCB_TRANS_BUS_WIDTH_VALID | 489 CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 490 491 if ((dval & DPARM_SYNC) && oval != 0) { 492 cts->sync_period = pval; 493 cts->sync_offset = oval; 494 cts->valid |= 495 CCB_TRANS_SYNC_RATE_VALID | 496 CCB_TRANS_SYNC_OFFSET_VALID; 497 } 498 splx(s); 499 if (bootverbose || isp->isp_dblev >= 3) 500 printf("%s: %d.%d get %s period 0x%x offset " 501 "0x%x flags 0x%x\n", isp->isp_name, bus, 502 tgt, 503 (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? 504 "current" : "user", pval, oval, dval); 505 } 506 ccb->ccb_h.status = CAM_REQ_CMP; 507 xpt_done(ccb); 508 break; 509 510 case XPT_CALC_GEOMETRY: 511 { 512 struct ccb_calc_geometry *ccg; 513 u_int32_t secs_per_cylinder; 514 u_int32_t size_mb; 515 516 ccg = &ccb->ccg; 517 if (ccg->block_size == 0) { 518 printf("%s: %d.%d XPT_CALC_GEOMETRY block size 0?\n", 519 isp->isp_name, ccg->ccb_h.target_id, 520 ccg->ccb_h.target_lun); 521 ccb->ccb_h.status = CAM_REQ_INVALID; 522 xpt_done(ccb); 523 break; 524 } 525 size_mb = ccg->volume_size /((1024L * 1024L) / ccg->block_size); 526 if (size_mb > 1024) { 527 ccg->heads = 255; 528 ccg->secs_per_track = 63; 529 } else { 530 ccg->heads = 64; 531 ccg->secs_per_track = 32; 532 } 533 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 534 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 535 ccb->ccb_h.status = CAM_REQ_CMP; 536 xpt_done(ccb); 537 break; 538 } 539 case XPT_RESET_BUS: /* Reset the specified bus */ 540 bus = cam_sim_bus(sim); 541 s = splcam(); 542 error = isp_control(isp, ISPCTL_RESET_BUS, &bus); 543 (void) splx(s); 544 if (error) 545 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 546 else { 547 if (cam_sim_bus(sim) && isp->isp_path2 != NULL) 548 xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); 549 else if (isp->isp_path != NULL) 550 xpt_async(AC_BUS_RESET, isp->isp_path, NULL); 551 ccb->ccb_h.status = CAM_REQ_CMP; 552 } 553 xpt_done(ccb); 554 break; 555 556 case XPT_TERM_IO: /* Terminate the I/O process */ 557 /* Does this need to be implemented? */ 558 ccb->ccb_h.status = CAM_REQ_INVALID; 559 xpt_done(ccb); 560 break; 561 562 case XPT_PATH_INQ: /* Path routing inquiry */ 563 { 564 struct ccb_pathinq *cpi = &ccb->cpi; 565 566 cpi->version_num = 1; 567 cpi->target_sprt = 0; 568 cpi->hba_eng_cnt = 0; 569 cpi->max_target = ISP_MAX_TARGETS(isp) - 1; 570 cpi->max_lun = ISP_MAX_LUNS(isp) - 1; 571 cpi->bus_id = cam_sim_bus(sim); 572 if (IS_FC(isp)) { 573 cpi->hba_misc = PIM_NOBUSRESET; 574 /* 575 * Because our loop ID can shift from time to time, 576 * make our initiator ID out of range of our bus. 577 */ 578 cpi->initiator_id = cpi->max_target + 1; 579 580 /* 581 * Set base transfer capabilities for Fibre Channel. 582 * Technically not correct because we don't know 583 * what media we're running on top of- but we'll 584 * look good if we always say 100MB/s. 585 */ 586 cpi->base_transfer_speed = 100000; 587 cpi->hba_inquiry = PI_TAG_ABLE; 588 } else { 589 sdparam *sdp = isp->isp_param; 590 sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path)); 591 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 592 cpi->hba_misc = 0; 593 cpi->initiator_id = sdp->isp_initiator_id; 594 cpi->base_transfer_speed = 3300; 595 } 596 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 597 strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN); 598 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 599 cpi->unit_number = cam_sim_unit(sim); 600 cpi->ccb_h.status = CAM_REQ_CMP; 601 xpt_done(ccb); 602 break; 603 } 604 default: 605 ccb->ccb_h.status = CAM_REQ_INVALID; 606 xpt_done(ccb); 607 break; 608 } 609 } 610 611 #define ISPDDB (CAM_DEBUG_INFO|CAM_DEBUG_TRACE|CAM_DEBUG_CDB) 612 void 613 isp_done(struct ccb_scsiio *sccb) 614 { 615 struct ispsoftc *isp = XS_ISP(sccb); 616 617 if (XS_NOERR(sccb)) 618 XS_SETERR(sccb, CAM_REQ_CMP); 619 sccb->ccb_h.status &= ~CAM_STATUS_MASK; 620 sccb->ccb_h.status |= sccb->ccb_h.spriv_field0; 621 if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && 622 (sccb->scsi_status != SCSI_STATUS_OK)) { 623 sccb->ccb_h.status &= ~CAM_STATUS_MASK; 624 sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 625 } 626 sccb->ccb_h.status &= ~CAM_SIM_QUEUED; 627 if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 628 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 629 sccb->ccb_h.status |= CAM_DEV_QFRZN; 630 xpt_freeze_devq(sccb->ccb_h.path, 1); 631 if (sccb->scsi_status != SCSI_STATUS_OK) 632 IDPRINTF(3, ("%s: fdevq %d.%d %x %x\n", 633 isp->isp_name, sccb->ccb_h.target_id, 634 sccb->ccb_h.target_lun, sccb->ccb_h.status, 635 sccb->scsi_status)); 636 } 637 } 638 /* 639 * If we were frozen waiting resources, clear that we were frozen 640 * waiting for resources. If we are no longer frozen, and the devq 641 * isn't frozen, mark the completing CCB to have the XPT layer 642 * release the simq. 643 */ 644 if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) { 645 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE; 646 if (isp->isp_osinfo.simqfrozen == 0) { 647 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 648 IDPRINTF(3, ("%s: isp_done -> relsimq\n", 649 isp->isp_name)); 650 sccb->ccb_h.status |= CAM_RELEASE_SIMQ; 651 } else { 652 IDPRINTF(3, ("%s: isp_done -> devq frozen\n", 653 isp->isp_name)); 654 } 655 } else { 656 IDPRINTF(3, ("%s: isp_done -> simqfrozen = %x\n", 657 isp->isp_name, isp->isp_osinfo.simqfrozen)); 658 } 659 } 660 if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) && 661 (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 662 xpt_print_path(sccb->ccb_h.path); 663 printf("cam completion status 0x%x\n", sccb->ccb_h.status); 664 } 665 xpt_done((union ccb *) sccb); 666 } 667 668 int 669 isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) 670 { 671 int bus, rv = 0; 672 switch (cmd) { 673 case ISPASYNC_NEW_TGT_PARAMS: 674 { 675 int flags, tgt; 676 sdparam *sdp = isp->isp_param; 677 struct ccb_trans_settings neg; 678 struct cam_path *tmppath; 679 680 tgt = *((int *)arg); 681 bus = (tgt >> 16) & 0xffff; 682 tgt &= 0xffff; 683 sdp += bus; 684 if (xpt_create_path(&tmppath, NULL, 685 cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim), 686 tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 687 xpt_print_path(isp->isp_path); 688 printf("isp_async cannot make temp path for " 689 "target %d bus %d\n", tgt, bus); 690 rv = -1; 691 break; 692 } 693 flags = sdp->isp_devparam[tgt].cur_dflags; 694 neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 695 if (flags & DPARM_DISC) { 696 neg.flags |= CCB_TRANS_DISC_ENB; 697 } 698 if (flags & DPARM_TQING) { 699 neg.flags |= CCB_TRANS_TAG_ENB; 700 } 701 neg.valid |= CCB_TRANS_BUS_WIDTH_VALID; 702 neg.bus_width = (flags & DPARM_WIDE)? 703 MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT; 704 neg.sync_period = sdp->isp_devparam[tgt].cur_period; 705 neg.sync_offset = sdp->isp_devparam[tgt].cur_offset; 706 if (flags & DPARM_SYNC) { 707 neg.valid |= 708 CCB_TRANS_SYNC_RATE_VALID | 709 CCB_TRANS_SYNC_OFFSET_VALID; 710 } 711 IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period " 712 "0x%x offset 0x%x flags 0x%x\n", isp->isp_name, 713 bus, tgt, neg.sync_period, neg.sync_offset, flags)); 714 xpt_setup_ccb(&neg.ccb_h, tmppath, 1); 715 xpt_async(AC_TRANSFER_NEG, tmppath, &neg); 716 xpt_free_path(tmppath); 717 break; 718 } 719 case ISPASYNC_BUS_RESET: 720 bus = *((int *)arg); 721 printf("%s: SCSI bus reset on bus %d detected\n", 722 isp->isp_name, bus); 723 if (bus > 0 && isp->isp_path2) { 724 xpt_async(AC_BUS_RESET, isp->isp_path2, NULL); 725 } else if (isp->isp_path) { 726 xpt_async(AC_BUS_RESET, isp->isp_path, NULL); 727 } 728 break; 729 case ISPASYNC_LOOP_DOWN: 730 if (isp->isp_path) { 731 if (isp->isp_osinfo.simqfrozen == 0) { 732 IDPRINTF(3, ("%s: loop down freeze simq\n", 733 isp->isp_name)); 734 xpt_freeze_simq(isp->isp_sim, 1); 735 } 736 isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN; 737 } 738 printf("%s: Loop DOWN\n", isp->isp_name); 739 break; 740 case ISPASYNC_LOOP_UP: 741 if (isp->isp_path) { 742 int wasfrozen = 743 isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN; 744 isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN; 745 if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) { 746 xpt_release_simq(isp->isp_sim, 1); 747 IDPRINTF(3, ("%s: loop up release simq\n", 748 isp->isp_name)); 749 } 750 } 751 printf("%s: Loop UP\n", isp->isp_name); 752 break; 753 case ISPASYNC_PDB_CHANGED: 754 { 755 const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x " 756 "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n"; 757 const static char *roles[4] = { 758 "(none)", "Target", "Initiator", "Target/Initiator" 759 }; 760 char *ptr; 761 fcparam *fcp = isp->isp_param; 762 int tgt = *((int *) arg); 763 struct lportdb *lp = &fcp->portdb[tgt]; 764 765 if (lp->valid) { 766 ptr = "arrived"; 767 } else { 768 ptr = "disappeared"; 769 } 770 printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid, 771 roles[lp->roles & 0x3], ptr, 772 (u_int32_t) (lp->port_wwn >> 32), 773 (u_int32_t) (lp->port_wwn & 0xffffffffLL), 774 (u_int32_t) (lp->node_wwn >> 32), 775 (u_int32_t) (lp->node_wwn & 0xffffffffLL)); 776 break; 777 } 778 case ISPASYNC_CHANGE_NOTIFY: 779 printf("%s: Name Server Database Changed\n", isp->isp_name); 780 break; 781 #ifdef ISP2100_FABRIC 782 case ISPASYNC_FABRIC_DEV: 783 { 784 int target; 785 struct lportdb *lp; 786 sns_scrsp_t *resp = (sns_scrsp_t *) arg; 787 u_int32_t portid; 788 u_int64_t wwn; 789 fcparam *fcp = isp->isp_param; 790 791 rv = -1; 792 793 portid = 794 (((u_int32_t) resp->snscb_port_id[0]) << 16) | 795 (((u_int32_t) resp->snscb_port_id[1]) << 8) | 796 (((u_int32_t) resp->snscb_port_id[2])); 797 wwn = 798 (((u_int64_t)resp->snscb_portname[0]) << 56) | 799 (((u_int64_t)resp->snscb_portname[1]) << 48) | 800 (((u_int64_t)resp->snscb_portname[2]) << 40) | 801 (((u_int64_t)resp->snscb_portname[3]) << 32) | 802 (((u_int64_t)resp->snscb_portname[4]) << 24) | 803 (((u_int64_t)resp->snscb_portname[5]) << 16) | 804 (((u_int64_t)resp->snscb_portname[6]) << 8) | 805 (((u_int64_t)resp->snscb_portname[7])); 806 printf("%s: type 0x%x@portid 0x%x 0x%08x%08x\n", isp->isp_name, 807 resp->snscb_port_type, portid, 808 ((u_int32_t) (wwn >> 32)), ((u_int32_t) wwn)); 809 if (resp->snscb_port_type != 2) { 810 rv = 0; 811 break; 812 } 813 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { 814 lp = &fcp->portdb[target]; 815 if (lp->port_wwn == wwn) 816 break; 817 } 818 if (target < MAX_FC_TARG) { 819 rv = 0; 820 break; 821 } 822 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { 823 lp = &fcp->portdb[target]; 824 if (lp->port_wwn == 0) 825 break; 826 } 827 if (target == MAX_FC_TARG) { 828 printf("%s: no more space for fabric devices\n", 829 isp->isp_name); 830 break; 831 } 832 lp->port_wwn = lp->node_wwn = wwn; 833 lp->portid = portid; 834 rv = 0; 835 break; 836 } 837 #endif 838 default: 839 rv = -1; 840 break; 841 } 842 return (rv); 843 } 844 845 846 /* 847 * Locks are held before coming here. 848 */ 849 void 850 isp_uninit(struct ispsoftc *isp) 851 { 852 ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); 853 DISABLE_INTS(isp); 854 } 855