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