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