1 /*- 2 * Copyright (c) 2002 Adaptec, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/dev/aac/aac_cam.c,v 1.40 2010/12/06 17:06:21 jhb Exp $ 27 */ 28 29 /* 30 * CAM front-end for communicating with non-DASD devices 31 */ 32 33 #include "opt_aac.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/sysctl.h> 39 #include <sys/lock.h> 40 #include <sys/malloc.h> 41 #include <sys/module.h> 42 43 #include <bus/cam/cam.h> 44 #include <bus/cam/cam_ccb.h> 45 #include <bus/cam/cam_debug.h> 46 #include <bus/cam/cam_periph.h> 47 #include <bus/cam/cam_sim.h> 48 #include <bus/cam/cam_xpt_periph.h> 49 #include <bus/cam/cam_xpt_sim.h> 50 #include <bus/cam/scsi/scsi_all.h> 51 #include <bus/cam/scsi/scsi_message.h> 52 53 #include <sys/bus.h> 54 #include <sys/conf.h> 55 #include <sys/disk.h> 56 57 #include <machine/md_var.h> 58 #include <sys/rman.h> 59 60 #include <vm/vm.h> 61 #include <vm/pmap.h> 62 63 #include <dev/raid/aac/aacreg.h> 64 #include <dev/raid/aac/aac_ioctl.h> 65 #include <dev/raid/aac/aacvar.h> 66 67 struct aac_cam { 68 device_t dev; 69 struct aac_sim *inf; 70 struct cam_sim *sim; 71 struct cam_path *path; 72 }; 73 74 static int aac_cam_probe(device_t dev); 75 static int aac_cam_attach(device_t dev); 76 static int aac_cam_detach(device_t dev); 77 static void aac_cam_action(struct cam_sim *, union ccb *); 78 static void aac_cam_poll(struct cam_sim *); 79 static void aac_cam_complete(struct aac_command *); 80 static void aac_cam_rescan(struct aac_softc *sc, uint32_t channel, 81 uint32_t target_id); 82 static void aac_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); 83 84 static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *); 85 static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *); 86 static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *); 87 88 static devclass_t aac_pass_devclass; 89 90 static device_method_t aac_pass_methods[] = { 91 DEVMETHOD(device_probe, aac_cam_probe), 92 DEVMETHOD(device_attach, aac_cam_attach), 93 DEVMETHOD(device_detach, aac_cam_detach), 94 { 0, 0 } 95 }; 96 97 static driver_t aac_pass_driver = { 98 "aacp", 99 aac_pass_methods, 100 sizeof(struct aac_cam) 101 }; 102 103 DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, NULL, NULL); 104 MODULE_DEPEND(aacp, cam, 1, 1, 1); 105 106 MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info"); 107 108 static void 109 aac_cam_rescan(struct aac_softc *sc, uint32_t channel, uint32_t target_id) 110 { 111 union ccb *ccb; 112 struct aac_sim *sim; 113 struct aac_cam *camsc; 114 115 if (target_id == AAC_CAM_TARGET_WILDCARD) 116 target_id = CAM_TARGET_WILDCARD; 117 118 TAILQ_FOREACH(sim, &sc->aac_sim_tqh, sim_link) { 119 camsc = sim->aac_cam; 120 if (camsc == NULL || camsc->inf == NULL || 121 camsc->inf->BusNumber != channel) 122 continue; 123 124 ccb = xpt_alloc_ccb(); 125 if (ccb == NULL) { 126 device_printf(sc->aac_dev, 127 "Cannot allocate ccb for bus rescan.\n"); 128 return; 129 } 130 131 if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, 132 cam_sim_path(camsc->sim), 133 target_id, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 134 xpt_free_ccb(ccb); 135 device_printf(sc->aac_dev, 136 "Cannot create path for bus rescan.\n"); 137 return; 138 } 139 xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/); 140 ccb->ccb_h.func_code = XPT_SCAN_BUS; 141 ccb->ccb_h.cbfcnp = aac_bus_scan_cb; 142 ccb->crcn.flags = CAM_FLAG_NONE; 143 xpt_action(ccb); 144 break; 145 } 146 } 147 148 static void 149 aac_bus_scan_cb(struct cam_periph *periph, union ccb *ccb) 150 { 151 if (ccb->ccb_h.status != CAM_REQ_CMP) 152 kprintf("cam_scan_callback: failure status = %x\n", 153 ccb->ccb_h.status); 154 155 xpt_free_path(ccb->ccb_h.path); 156 kfree(ccb, M_TEMP); 157 } 158 159 static void 160 aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg) 161 { 162 union ccb *ccb; 163 struct aac_cam *camsc; 164 165 switch (event->ev_type) { 166 case AAC_EVENT_CMFREE: 167 ccb = arg; 168 camsc = ccb->ccb_h.sim_priv.entries[0].ptr; 169 kfree(event, M_AACCAM); 170 xpt_release_simq(camsc->sim, 1); 171 ccb->ccb_h.status = CAM_REQUEUE_REQ; 172 xpt_done(ccb); 173 break; 174 default: 175 device_printf(sc->aac_dev, "unknown event %d in aac_cam\n", 176 event->ev_type); 177 break; 178 } 179 180 return; 181 } 182 183 static int 184 aac_cam_probe(device_t dev) 185 { 186 fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); 187 188 return (0); 189 } 190 191 static int 192 aac_cam_detach(device_t dev) 193 { 194 struct aac_softc *sc; 195 struct aac_cam *camsc; 196 fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); 197 198 camsc = (struct aac_cam *)device_get_softc(dev); 199 sc = camsc->inf->aac_sc; 200 camsc->inf->aac_cam = NULL; 201 202 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); 203 204 xpt_async(AC_LOST_DEVICE, camsc->path, NULL); 205 xpt_free_path(camsc->path); 206 xpt_bus_deregister(cam_sim_path(camsc->sim)); 207 cam_sim_free(camsc->sim); 208 209 sc->cam_rescan_cb = NULL; 210 211 lockmgr(&sc->aac_io_lock, LK_RELEASE); 212 213 return (0); 214 } 215 216 /* 217 * Register the driver as a CAM SIM 218 */ 219 static int 220 aac_cam_attach(device_t dev) 221 { 222 struct cam_devq *devq; 223 struct cam_sim *sim; 224 struct cam_path *path; 225 struct aac_cam *camsc; 226 struct aac_sim *inf; 227 228 fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); 229 230 camsc = (struct aac_cam *)device_get_softc(dev); 231 inf = (struct aac_sim *)device_get_ivars(dev); 232 camsc->inf = inf; 233 camsc->inf->aac_cam = camsc; 234 235 devq = cam_simq_alloc(inf->TargetsPerBus); 236 if (devq == NULL) 237 return (EIO); 238 239 sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc, 240 device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq); 241 cam_simq_release(devq); 242 if (sim == NULL) 243 return (EIO); 244 245 /* Since every bus has it's own sim, every bus 'appears' as bus 0 */ 246 lockmgr(&inf->aac_sc->aac_io_lock, LK_EXCLUSIVE); 247 if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { 248 cam_sim_free(sim); 249 lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); 250 return (EIO); 251 } 252 253 if (xpt_create_path(&path, NULL, cam_sim_path(sim), 254 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 255 xpt_bus_deregister(cam_sim_path(sim)); 256 cam_sim_free(sim); 257 lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); 258 return (EIO); 259 } 260 inf->aac_sc->cam_rescan_cb = aac_cam_rescan; 261 lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); 262 263 camsc->sim = sim; 264 camsc->path = path; 265 266 return (0); 267 } 268 269 static void 270 aac_cam_action(struct cam_sim *sim, union ccb *ccb) 271 { 272 struct aac_cam *camsc; 273 struct aac_softc *sc; 274 struct aac_srb *srb; 275 struct aac_fib *fib; 276 struct aac_command *cm; 277 278 camsc = (struct aac_cam *)cam_sim_softc(sim); 279 sc = camsc->inf->aac_sc; 280 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); 281 282 /* Synchronous ops, and ops that don't require communication with the 283 * controller */ 284 switch(ccb->ccb_h.func_code) { 285 case XPT_SCSI_IO: 286 case XPT_RESET_DEV: 287 /* These are handled down below */ 288 break; 289 case XPT_CALC_GEOMETRY: 290 { 291 struct ccb_calc_geometry *ccg; 292 u_int32_t size_mb; 293 u_int32_t secs_per_cylinder; 294 295 ccg = &ccb->ccg; 296 size_mb = ccg->volume_size / 297 ((1024L * 1024L) / ccg->block_size); 298 if (size_mb >= (2 * 1024)) { /* 2GB */ 299 ccg->heads = 255; 300 ccg->secs_per_track = 63; 301 } else if (size_mb >= (1 * 1024)) { /* 1GB */ 302 ccg->heads = 128; 303 ccg->secs_per_track = 32; 304 } else { 305 ccg->heads = 64; 306 ccg->secs_per_track = 32; 307 } 308 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 309 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 310 311 ccb->ccb_h.status = CAM_REQ_CMP; 312 xpt_done(ccb); 313 return; 314 } 315 case XPT_PATH_INQ: 316 { 317 struct ccb_pathinq *cpi = &ccb->cpi; 318 319 cpi->version_num = 1; 320 cpi->hba_inquiry = PI_WIDE_16; 321 cpi->target_sprt = 0; 322 323 /* 324 * Resetting via the passthrough or parallel bus scan 325 * causes problems. 326 */ 327 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN; 328 cpi->hba_eng_cnt = 0; 329 cpi->max_target = camsc->inf->TargetsPerBus; 330 cpi->max_lun = 8; /* Per the controller spec */ 331 cpi->initiator_id = camsc->inf->InitiatorBusId; 332 cpi->bus_id = camsc->inf->BusNumber; 333 cpi->base_transfer_speed = 3300; 334 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 335 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 336 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 337 cpi->unit_number = cam_sim_unit(sim); 338 cpi->transport = XPORT_SPI; 339 cpi->transport_version = 2; 340 cpi->protocol = PROTO_SCSI; 341 cpi->protocol_version = SCSI_REV_2; 342 ccb->ccb_h.status = CAM_REQ_CMP; 343 xpt_done(ccb); 344 return; 345 } 346 case XPT_GET_TRAN_SETTINGS: 347 { 348 struct ccb_trans_settings_scsi *scsi = 349 &ccb->cts.proto_specific.scsi; 350 struct ccb_trans_settings_spi *spi = 351 &ccb->cts.xport_specific.spi; 352 ccb->cts.protocol = PROTO_SCSI; 353 ccb->cts.protocol_version = SCSI_REV_2; 354 ccb->cts.transport = XPORT_SPI; 355 ccb->cts.transport_version = 2; 356 if (ccb->ccb_h.target_lun != CAM_LUN_WILDCARD) { 357 scsi->valid = CTS_SCSI_VALID_TQ; 358 spi->valid |= CTS_SPI_VALID_DISC; 359 } else { 360 scsi->valid = 0; 361 } 362 ccb->ccb_h.status = CAM_REQ_CMP; 363 xpt_done(ccb); 364 return; 365 } 366 case XPT_SET_TRAN_SETTINGS: 367 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 368 xpt_done(ccb); 369 return; 370 case XPT_RESET_BUS: 371 if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) { 372 ccb->ccb_h.status = aac_cam_reset_bus(sim, ccb); 373 } else { 374 ccb->ccb_h.status = CAM_REQ_CMP; 375 } 376 xpt_done(ccb); 377 return; 378 case XPT_ABORT: 379 ccb->ccb_h.status = aac_cam_abort_ccb(sim, ccb); 380 xpt_done(ccb); 381 return; 382 case XPT_TERM_IO: 383 ccb->ccb_h.status = aac_cam_term_io(sim, ccb); 384 xpt_done(ccb); 385 return; 386 default: 387 device_printf(sc->aac_dev, "Unsupported command 0x%x\n", 388 ccb->ccb_h.func_code); 389 ccb->ccb_h.status = CAM_PROVIDE_FAIL; 390 xpt_done(ccb); 391 return; 392 } 393 394 /* Async ops that require communcation with the controller */ 395 396 if (aac_alloc_command(sc, &cm)) { 397 struct aac_event *event; 398 399 xpt_freeze_simq(sim, 1); 400 ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 401 ccb->ccb_h.sim_priv.entries[0].ptr = camsc; 402 event = kmalloc(sizeof(struct aac_event), M_AACCAM, 403 M_INTWAIT | M_ZERO); 404 event->ev_callback = aac_cam_event; 405 event->ev_arg = ccb; 406 event->ev_type = AAC_EVENT_CMFREE; 407 aac_add_event(sc, event); 408 return; 409 } 410 411 fib = cm->cm_fib; 412 srb = (struct aac_srb *)&fib->data[0]; 413 cm->cm_datalen = 0; 414 415 switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 416 case CAM_DIR_IN: 417 srb->flags = AAC_SRB_FLAGS_DATA_IN; 418 cm->cm_flags |= AAC_CMD_DATAIN; 419 break; 420 case CAM_DIR_OUT: 421 srb->flags = AAC_SRB_FLAGS_DATA_OUT; 422 cm->cm_flags |= AAC_CMD_DATAOUT; 423 break; 424 case CAM_DIR_NONE: 425 srb->flags = AAC_SRB_FLAGS_NO_DATA_XFER; 426 break; 427 default: 428 srb->flags = AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION; 429 cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT; 430 break; 431 } 432 433 switch(ccb->ccb_h.func_code) { 434 case XPT_SCSI_IO: 435 { 436 struct ccb_scsiio *csio = &ccb->csio; 437 438 srb->function = AAC_SRB_FUNC_EXECUTE_SCSI; 439 440 /* 441 * Copy the CDB into the SRB. It's only 6-16 bytes, 442 * so a copy is not too expensive. 443 */ 444 srb->cdb_len = csio->cdb_len; 445 if (ccb->ccb_h.flags & CAM_CDB_POINTER) 446 bcopy(csio->cdb_io.cdb_ptr, (u_int8_t *)&srb->cdb[0], 447 srb->cdb_len); 448 else 449 bcopy(csio->cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0], 450 srb->cdb_len); 451 452 /* Set command */ 453 fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ? 454 ScsiPortCommandU64 : ScsiPortCommand; 455 456 /* Map the s/g list. XXX 32bit addresses only! */ 457 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 458 if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 459 srb->data_len = csio->dxfer_len; 460 if (ccb->ccb_h.flags & CAM_DATA_PHYS) { 461 /* Send a 32bit command */ 462 fib->Header.Command = ScsiPortCommand; 463 srb->sg_map.SgCount = 1; 464 srb->sg_map.SgEntry[0].SgAddress = 465 (uint32_t)(uintptr_t)csio->data_ptr; 466 srb->sg_map.SgEntry[0].SgByteCount = 467 csio->dxfer_len; 468 } else { 469 /* 470 * Arrange things so that the S/G 471 * map will get set up automagically 472 */ 473 cm->cm_data = (void *)csio->data_ptr; 474 cm->cm_datalen = csio->dxfer_len; 475 cm->cm_sgtable = &srb->sg_map; 476 } 477 } else { 478 /* XXX Need to handle multiple s/g elements */ 479 panic("aac_cam: multiple s/g elements"); 480 } 481 } else { 482 srb->sg_map.SgCount = 0; 483 srb->sg_map.SgEntry[0].SgByteCount = 0; 484 srb->data_len = 0; 485 } 486 487 break; 488 } 489 case XPT_RESET_DEV: 490 if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) { 491 srb->function = AAC_SRB_FUNC_RESET_DEVICE; 492 break; 493 } else { 494 ccb->ccb_h.status = CAM_REQ_CMP; 495 xpt_done(ccb); 496 return; 497 } 498 default: 499 break; 500 } 501 502 srb->bus = camsc->inf->BusNumber; /* Bus number relative to the card */ 503 srb->target = ccb->ccb_h.target_id; 504 srb->lun = ccb->ccb_h.target_lun; 505 srb->timeout = ccb->ccb_h.timeout; /* XXX */ 506 srb->retry_limit = 0; 507 508 cm->cm_complete = aac_cam_complete; 509 cm->cm_private = ccb; 510 cm->cm_timestamp = time_second; 511 512 fib->Header.XferState = 513 AAC_FIBSTATE_HOSTOWNED | 514 AAC_FIBSTATE_INITIALISED | 515 AAC_FIBSTATE_FROMHOST | 516 AAC_FIBSTATE_REXPECTED | 517 AAC_FIBSTATE_NORM; 518 fib->Header.Size = sizeof(struct aac_fib_header) + 519 sizeof(struct aac_srb); 520 521 aac_enqueue_ready(cm); 522 aac_startio(cm->cm_sc); 523 524 return; 525 } 526 527 static void 528 aac_cam_poll(struct cam_sim *sim) 529 { 530 /* 531 * Pinging the interrupt routine isn't very safe, nor is it 532 * really necessary. Do nothing. 533 */ 534 } 535 536 static void 537 aac_cam_complete(struct aac_command *cm) 538 { 539 union ccb *ccb; 540 struct aac_srb_response *srbr; 541 struct aac_softc *sc; 542 543 sc = cm->cm_sc; 544 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); 545 ccb = cm->cm_private; 546 srbr = (struct aac_srb_response *)&cm->cm_fib->data[0]; 547 548 if (srbr->fib_status != 0) { 549 device_printf(sc->aac_dev, "Passthru FIB failed!\n"); 550 ccb->ccb_h.status = CAM_REQ_ABORTED; 551 } else { 552 /* 553 * The SRB error codes just happen to match the CAM error 554 * codes. How convienient! 555 */ 556 ccb->ccb_h.status = srbr->srb_status; 557 558 /* Take care of SCSI_IO ops. */ 559 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 560 u_int8_t command, device; 561 562 ccb->csio.scsi_status = srbr->scsi_status; 563 564 /* Take care of autosense */ 565 if (srbr->sense_len) { 566 int sense_len, scsi_sense_len; 567 568 scsi_sense_len = sizeof(struct scsi_sense_data); 569 bzero(&ccb->csio.sense_data, scsi_sense_len); 570 sense_len = (srbr->sense_len > 571 scsi_sense_len) ? scsi_sense_len : 572 srbr->sense_len; 573 bcopy(&srbr->sense[0], &ccb->csio.sense_data, 574 srbr->sense_len); 575 ccb->csio.sense_len = sense_len; 576 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 577 // scsi_sense_print(&ccb->csio); 578 } 579 580 /* If this is an inquiry command, fake things out */ 581 if (ccb->ccb_h.flags & CAM_CDB_POINTER) 582 command = ccb->csio.cdb_io.cdb_ptr[0]; 583 else 584 command = ccb->csio.cdb_io.cdb_bytes[0]; 585 586 if (command == INQUIRY) { 587 if (ccb->ccb_h.status == CAM_REQ_CMP) { 588 device = ccb->csio.data_ptr[0] & 0x1f; 589 /* 590 * We want DASD and PROC devices to only be 591 * visible through the pass device. 592 */ 593 if ((device == T_DIRECT) || 594 (device == T_PROCESSOR) || 595 (sc->flags & AAC_FLAGS_CAM_PASSONLY)) 596 ccb->csio.data_ptr[0] = 597 ((ccb->csio.data_ptr[0] & 0xe0) | 598 T_NODEVICE); 599 } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT && 600 ccb->ccb_h.target_lun != 0) { 601 /* fix for INQUIRYs on Lun>0 */ 602 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 603 } 604 } 605 } 606 } 607 608 aac_release_command(cm); 609 xpt_done(ccb); 610 611 return; 612 } 613 614 static u_int32_t 615 aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb) 616 { 617 struct aac_fib *fib; 618 struct aac_softc *sc; 619 struct aac_cam *camsc; 620 struct aac_vmioctl *vmi; 621 struct aac_resetbus *rbc; 622 int e; 623 624 camsc = (struct aac_cam *)cam_sim_softc(sim); 625 sc = camsc->inf->aac_sc; 626 627 if (sc == NULL) { 628 kprintf("aac: Null sc?\n"); 629 return (CAM_REQ_ABORTED); 630 } 631 632 aac_alloc_sync_fib(sc, &fib); 633 634 vmi = (struct aac_vmioctl *)&fib->data[0]; 635 bzero(vmi, sizeof(struct aac_vmioctl)); 636 637 vmi->Command = VM_Ioctl; 638 vmi->ObjType = FT_DRIVE; 639 vmi->MethId = sc->scsi_method_id; 640 vmi->ObjId = 0; 641 vmi->IoctlCmd = ResetBus; 642 643 rbc = (struct aac_resetbus *)&vmi->IoctlBuf[0]; 644 rbc->BusNumber = camsc->inf->BusNumber; 645 646 e = aac_sync_fib(sc, ContainerCommand, 0, fib, 647 sizeof(struct aac_vmioctl)); 648 if (e) { 649 device_printf(sc->aac_dev,"Error %d sending ResetBus command\n", 650 e); 651 aac_release_sync_fib(sc); 652 return (CAM_REQ_ABORTED); 653 } 654 655 aac_release_sync_fib(sc); 656 return (CAM_REQ_CMP); 657 } 658 659 static u_int32_t 660 aac_cam_abort_ccb(struct cam_sim *sim, union ccb *ccb) 661 { 662 return (CAM_UA_ABORT); 663 } 664 665 static u_int32_t 666 aac_cam_term_io(struct cam_sim *sim, union ccb *ccb) 667 { 668 return (CAM_UA_TERMIO); 669 } 670