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