1 /* $Id: $ */ 2 /* release_12_28_98_A */ 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_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_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_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 #else 564 565 static void ispminphys __P((struct buf *)); 566 static u_int32_t isp_adapter_info __P((int)); 567 static int ispcmd __P((ISP_SCSI_XFER_T *)); 568 static void isp_watch __P((void *arg)); 569 570 static struct scsi_adapter isp_switch = { 571 ispcmd, ispminphys, 0, 0, isp_adapter_info, "isp", { 0, 0 } 572 }; 573 static struct scsi_device isp_dev = { 574 NULL, NULL, NULL, NULL, "isp", 0, { 0, 0 } 575 }; 576 static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int)); 577 578 579 /* 580 * Complete attachment of hardware, include subdevices. 581 */ 582 void 583 isp_attach(struct ispsoftc *isp) 584 { 585 struct scsibus_data *scbus; 586 587 scbus = scsi_alloc_bus(); 588 if(!scbus) { 589 return; 590 } 591 isp->isp_state = ISP_RUNSTATE; 592 START_WATCHDOG(isp); 593 594 isp->isp_osinfo._link.adapter_unit = isp->isp_osinfo.unit; 595 isp->isp_osinfo._link.adapter_softc = isp; 596 isp->isp_osinfo._link.adapter = &isp_switch; 597 isp->isp_osinfo._link.device = &isp_dev; 598 isp->isp_osinfo._link.flags = 0; 599 if (isp->isp_type & ISP_HA_FC) { 600 isp->isp_osinfo._link.adapter_targ = 601 ((fcparam *)isp->isp_param)->isp_loopid; 602 scbus->maxtarg = MAX_FC_TARG-1; 603 } else { 604 isp->isp_osinfo._link.adapter_targ = 605 ((sdparam *)isp->isp_param)->isp_initiator_id; 606 scbus->maxtarg = MAX_TARGETS-1; 607 } 608 /* 609 * Prepare the scsibus_data area for the upperlevel scsi code. 610 */ 611 scbus->adapter_link = &isp->isp_osinfo._link; 612 613 /* 614 * ask the adapter what subunits are present 615 */ 616 scsi_attachdevs(scbus); 617 } 618 619 620 /* 621 * minphys our xfers 622 * 623 * Unfortunately, the buffer pointer describes the target device- not the 624 * adapter device, so we can't use the pointer to find out what kind of 625 * adapter we are and adjust accordingly. 626 */ 627 628 static void 629 ispminphys(struct buf *bp) 630 { 631 /* 632 * Only the 10X0 has a 24 bit limit. 633 */ 634 if (bp->b_bcount >= (1 << 24)) { 635 bp->b_bcount = (1 << 24); 636 } 637 } 638 639 static u_int32_t 640 isp_adapter_info(int unit) 641 { 642 /* 643 * XXX: FIND ISP BASED UPON UNIT AND GET REAL QUEUE LIMIT FROM THAT 644 */ 645 return (2); 646 } 647 648 static int 649 ispcmd(ISP_SCSI_XFER_T *xs) 650 { 651 struct ispsoftc *isp; 652 int r; 653 ISP_LOCKVAL_DECL; 654 655 isp = XS_ISP(xs); 656 ISP_LOCK; 657 r = ispscsicmd(xs); 658 if (r != CMD_QUEUED || (xs->flags & SCSI_NOMASK) == 0) { 659 ISP_UNLOCK; 660 return (r); 661 } 662 663 /* 664 * If we can't use interrupts, poll on completion. 665 */ 666 if (isp_poll(isp, xs, XS_TIME(xs))) { 667 /* 668 * If no other error occurred but we didn't finish, 669 * something bad happened. 670 */ 671 if (XS_IS_CMD_DONE(xs) == 0) { 672 isp->isp_nactive--; 673 if (isp->isp_nactive < 0) 674 isp->isp_nactive = 0; 675 if (XS_NOERR(xs)) { 676 isp_lostcmd(isp, xs); 677 XS_SETERR(xs, HBA_BOTCH); 678 } 679 } 680 } 681 ISP_UNLOCK; 682 return (CMD_COMPLETE); 683 } 684 685 static int 686 isp_poll(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs, int mswait) 687 { 688 689 while (mswait) { 690 /* Try the interrupt handling routine */ 691 (void)isp_intr((void *)isp); 692 693 /* See if the xs is now done */ 694 if (XS_IS_CMD_DONE(xs)) 695 return (0); 696 SYS_DELAY(1000); /* wait one millisecond */ 697 mswait--; 698 } 699 return (1); 700 } 701 702 static void 703 isp_watch(void *arg) 704 { 705 int i; 706 struct ispsoftc *isp = arg; 707 ISP_SCSI_XFER_T *xs; 708 ISP_ILOCKVAL_DECL; 709 710 /* 711 * Look for completely dead commands (but not polled ones). 712 */ 713 ISP_ILOCK(isp); 714 for (i = 0; i < RQUEST_QUEUE_LEN; i++) { 715 if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) { 716 continue; 717 } 718 if (XS_TIME(xs) == 0) { 719 continue; 720 } 721 XS_TIME(xs) -= (WATCH_INTERVAL * 1000); 722 /* 723 * Avoid later thinking that this 724 * transaction is not being timed. 725 * Then give ourselves to watchdog 726 * periods of grace. 727 */ 728 if (XS_TIME(xs) == 0) 729 XS_TIME(xs) = 1; 730 else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) { 731 continue; 732 } 733 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { 734 printf("%s: isp_watch failed to abort command\n", 735 isp->isp_name); 736 isp_restart(isp); 737 break; 738 } 739 } 740 RESTART_WATCHDOG(isp_watch, arg); 741 ISP_IUNLOCK(isp); 742 } 743 #endif 744 745 /* 746 * Free any associated resources prior to decommissioning and 747 * set the card to a known state (so it doesn't wake up and kick 748 * us when we aren't expecting it to). 749 * 750 * Locks are held before coming here. 751 */ 752 void 753 isp_uninit(struct ispsoftc *isp) 754 { 755 ISP_ILOCKVAL_DECL; 756 ISP_ILOCK(isp); 757 /* 758 * Leave with interrupts disabled. 759 */ 760 DISABLE_INTS(isp); 761 762 /* 763 * Turn off the watchdog (if active). 764 */ 765 STOP_WATCHDOG(isp_watch, isp); 766 767 /* 768 * And out... 769 */ 770 ISP_IUNLOCK(isp); 771 } 772