1 /* $Id: $ */ 2 /* isp_freebsd.c 1.13 */ 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(isp) 46 struct ispsoftc *isp; 47 { 48 struct ccb_setasync csa; 49 struct cam_devq *devq; 50 51 /* 52 * Create the device queue for our SIM. 53 */ 54 devq = cam_simq_alloc(MAXISPREQUEST); 55 if (devq == NULL) { 56 return; 57 } 58 59 /* 60 * Construct our SIM entry 61 */ 62 isp->isp_sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp, 63 isp->isp_unit, 1, MAXISPREQUEST, devq); 64 if (isp->isp_sim == NULL) { 65 cam_simq_free(devq); 66 return; 67 } 68 if (xpt_bus_register(isp->isp_sim, 0) != CAM_SUCCESS) { 69 cam_sim_free(isp->isp_sim, TRUE); 70 return; 71 } 72 73 if (xpt_create_path(&isp->isp_path, NULL, cam_sim_path(isp->isp_sim), 74 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 75 xpt_bus_deregister(cam_sim_path(isp->isp_sim)); 76 cam_sim_free(isp->isp_sim, TRUE); 77 return; 78 } 79 80 xpt_setup_ccb(&csa.ccb_h, isp->isp_path, 5); 81 csa.ccb_h.func_code = XPT_SASYNC_CB; 82 csa.event_enable = AC_LOST_DEVICE; 83 csa.callback = isp_async; 84 csa.callback_arg = isp->isp_sim; 85 xpt_action((union ccb *)&csa); 86 87 /* 88 * Set base transfer capabilities for Fibre Channel. 89 * Technically not correct because we don't know 90 * what media we're running on top of- but we'll 91 * look good if we always say 100MB/s. 92 */ 93 if (isp->isp_type & ISP_HA_FC) { 94 isp->isp_sim->base_transfer_speed = 100000; 95 } 96 isp->isp_state = ISP_RUNSTATE; 97 } 98 99 static void 100 isp_async(cbarg, code, path, arg) 101 void *cbarg; 102 u_int32_t code; 103 struct cam_path *path; 104 void *arg; 105 { 106 struct cam_sim *sim; 107 struct ispsoftc *isp; 108 109 sim = (struct cam_sim *)cbarg; 110 isp = (struct ispsoftc *) cam_sim_softc(sim); 111 switch (code) { 112 case AC_LOST_DEVICE: 113 if (isp->isp_type & ISP_HA_SCSI) { 114 u_int16_t oflags, nflags; 115 sdparam *sdp = isp->isp_param; 116 int s, tgt = xpt_path_target_id(path); 117 118 nflags = DPARM_SAFE_DFLT; 119 if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) { 120 nflags |= DPARM_NARROW | DPARM_ASYNC; 121 } 122 oflags = sdp->isp_devparam[tgt].dev_flags; 123 sdp->isp_devparam[tgt].dev_flags = nflags; 124 sdp->isp_devparam[tgt].dev_update = 1; 125 126 s = splcam(); 127 (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL); 128 (void) splx(s); 129 sdp->isp_devparam[tgt].dev_flags = oflags; 130 } 131 break; 132 default: 133 break; 134 } 135 } 136 137 static void 138 isp_poll(sim) 139 struct cam_sim *sim; 140 { 141 isp_intr((struct ispsoftc *) cam_sim_softc(sim)); 142 } 143 144 145 static void 146 isp_action(sim, ccb) 147 struct cam_sim *sim; 148 union ccb *ccb; 149 { 150 int s, tgt, error; 151 struct ispsoftc *isp; 152 struct ccb_trans_settings *cts; 153 154 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n")); 155 156 isp = (struct ispsoftc *)cam_sim_softc(sim); 157 ccb->ccb_h.sim_priv.entries[0].field = 0; 158 ccb->ccb_h.sim_priv.entries[1].ptr = isp; 159 160 IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name, 161 ccb->ccb_h.func_code)); 162 163 switch (ccb->ccb_h.func_code) { 164 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 165 /* 166 * Do a couple of preliminary checks... 167 */ 168 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 169 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { 170 ccb->ccb_h.status = CAM_REQ_INVALID; 171 xpt_done(ccb); 172 break; 173 } 174 } 175 176 177 if (isp->isp_type & ISP_HA_SCSI) { 178 if (ccb->ccb_h.target_id > (MAX_TARGETS-1)) { 179 ccb->ccb_h.status = CAM_PATH_INVALID; 180 } else if (isp->isp_fwrev >= ISP_FW_REV(7, 55)) { 181 /* 182 * Too much breakage. 183 */ 184 #if 0 185 if (ccb->ccb_h.target_lun > 31) { 186 ccb->ccb_h.status = CAM_PATH_INVALID; 187 } 188 #else 189 if (ccb->ccb_h.target_lun > 7) { 190 ccb->ccb_h.status = CAM_PATH_INVALID; 191 } 192 #endif 193 } else if (ccb->ccb_h.target_lun > 7) { 194 ccb->ccb_h.status = CAM_PATH_INVALID; 195 } 196 } else { 197 if (ccb->ccb_h.target_id > (MAX_FC_TARG-1)) { 198 ccb->ccb_h.status = CAM_PATH_INVALID; 199 #ifdef SCCLUN 200 } else if (ccb->ccb_h.target_lun > 15) { 201 ccb->ccb_h.status = CAM_PATH_INVALID; 202 #else 203 } else if (ccb->ccb_h.target_lun > 65535) { 204 ccb->ccb_h.status = CAM_PATH_INVALID; 205 #endif 206 } 207 } 208 if (ccb->ccb_h.status == CAM_PATH_INVALID) { 209 printf("%s: invalid tgt/lun (%d.%d) in XPT_SCSI_IO\n", 210 isp->isp_name, ccb->ccb_h.target_id, 211 ccb->ccb_h.target_lun); 212 xpt_done(ccb); 213 break; 214 } 215 216 s = splcam(); 217 switch (ispscsicmd((ISP_SCSI_XFER_T *) ccb)) { 218 case CMD_QUEUED: 219 ccb->ccb_h.status |= CAM_SIM_QUEUED; 220 break; 221 case CMD_EAGAIN: 222 if (isp->isp_osinfo.simqfrozen == 0) { 223 xpt_freeze_simq(sim, 1); 224 isp->isp_osinfo.simqfrozen = 1; 225 } 226 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 227 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 228 xpt_done(ccb); 229 break; 230 case CMD_COMPLETE: 231 /* 232 * Just make sure that we didn't get it returned 233 * as completed, but with the request still in 234 * progress. In theory, 'cannot happen'. 235 */ 236 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 237 CAM_REQ_INPROG) { 238 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 239 ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 240 } 241 xpt_done(ccb); 242 break; 243 } 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 = 65535; 489 #else 490 cpi->max_lun = 15; 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 = 31; 502 #else 503 cpi->max_lun = 7; 504 #endif 505 } else { 506 cpi->max_lun = 7; 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(sccb) 529 struct ccb_scsiio *sccb; 530 { 531 struct ispsoftc *isp = XS_ISP(sccb); 532 533 if (XS_NOERR(sccb)) 534 XS_SETERR(sccb, CAM_REQ_CMP); 535 sccb->ccb_h.status &= ~CAM_STATUS_MASK; 536 sccb->ccb_h.status |= sccb->ccb_h.spriv_field0; 537 if ((sccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && 538 (sccb->scsi_status != SCSI_STATUS_OK)) { 539 sccb->ccb_h.status &= ~CAM_STATUS_MASK; 540 sccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 541 } 542 if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 543 if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 544 IDPRINTF(3, ("%s: freeze devq %d.%d ccbstat 0x%x\n", 545 isp->isp_name, sccb->ccb_h.target_id, 546 sccb->ccb_h.target_lun, sccb->ccb_h.status)); 547 xpt_freeze_devq(sccb->ccb_h.path, 1); 548 sccb->ccb_h.status |= CAM_DEV_QFRZN; 549 } 550 } 551 if (isp->isp_osinfo.simqfrozen) { 552 sccb->ccb_h.status |= CAM_RELEASE_SIMQ; 553 isp->isp_osinfo.simqfrozen = 0; 554 } 555 sccb->ccb_h.status &= ~CAM_SIM_QUEUED; 556 if (CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB) && 557 (sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 558 xpt_print_path(sccb->ccb_h.path); 559 printf("cam completion status 0x%x\n", sccb->ccb_h.status); 560 } 561 xpt_done((union ccb *) sccb); 562 } 563 564 #else 565 566 static void ispminphys __P((struct buf *)); 567 static u_int32_t isp_adapter_info __P((int)); 568 static int ispcmd __P((ISP_SCSI_XFER_T *)); 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(isp) 584 struct ispsoftc *isp; 585 { 586 struct scsibus_data *scbus; 587 588 scbus = scsi_alloc_bus(); 589 if(!scbus) { 590 return; 591 } 592 isp->isp_state = ISP_RUNSTATE; 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(bp) 630 struct buf *bp; 631 { 632 /* 633 * Only the 10X0 has a 24 bit limit. 634 */ 635 if (bp->b_bcount >= (1 << 24)) { 636 bp->b_bcount = (1 << 24); 637 } 638 } 639 640 static u_int32_t 641 isp_adapter_info(unit) 642 int unit; 643 { 644 /* 645 * XXX: FIND ISP BASED UPON UNIT AND GET REAL QUEUE LIMIT FROM THAT 646 */ 647 return (2); 648 } 649 650 static int 651 ispcmd(xs) 652 ISP_SCSI_XFER_T *xs; 653 { 654 struct ispsoftc *isp; 655 int r; 656 ISP_LOCKVAL_DECL; 657 658 isp = XS_ISP(xs); 659 ISP_LOCK; 660 r = ispscsicmd(xs); 661 if (r != CMD_QUEUED || (xs->flags & SCSI_NOMASK) == 0) { 662 ISP_UNLOCK; 663 return (r); 664 } 665 666 /* 667 * If we can't use interrupts, poll on completion. 668 */ 669 if (isp_poll(isp, xs, XS_TIME(xs))) { 670 /* 671 * If no other error occurred but we didn't finish, 672 * something bad happened. 673 */ 674 if (XS_IS_CMD_DONE(xs) == 0) { 675 isp->isp_nactive--; 676 if (isp->isp_nactive < 0) 677 isp->isp_nactive = 0; 678 if (XS_NOERR(xs)) { 679 isp_lostcmd(isp, xs); 680 XS_SETERR(xs, HBA_BOTCH); 681 } 682 } 683 } 684 ISP_UNLOCK; 685 return (CMD_COMPLETE); 686 } 687 688 static int 689 isp_poll(isp, xs, mswait) 690 struct ispsoftc *isp; 691 ISP_SCSI_XFER_T *xs; 692 int mswait; 693 { 694 695 while (mswait) { 696 /* Try the interrupt handling routine */ 697 (void)isp_intr((void *)isp); 698 699 /* See if the xs is now done */ 700 if (XS_IS_CMD_DONE(xs)) 701 return (0); 702 SYS_DELAY(1000); /* wait one millisecond */ 703 mswait--; 704 } 705 return (1); 706 } 707 #endif 708