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