1 /*- 2 * Bus independent FreeBSD shim for the aic79xx based Adaptec SCSI controllers 3 * 4 * Copyright (c) 1994-2002, 2004 Justin T. Gibbs. 5 * Copyright (c) 2001-2002 Adaptec Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU Public License ("GPL"). 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#35 $ 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <dev/aic7xxx/aic79xx_osm.h> 39 #include <dev/aic7xxx/aic79xx_inline.h> 40 41 #include <sys/kthread.h> 42 43 #include "opt_ddb.h" 44 #ifdef DDB 45 #include <ddb/ddb.h> 46 #endif 47 48 #ifndef AHD_TMODE_ENABLE 49 #define AHD_TMODE_ENABLE 0 50 #endif 51 52 #include <dev/aic7xxx/aic_osm_lib.c> 53 54 #define ccb_scb_ptr spriv_ptr0 55 56 #if 0 57 static void ahd_dump_targcmd(struct target_cmd *cmd); 58 #endif 59 static int ahd_modevent(module_t mod, int type, void *data); 60 static void ahd_action(struct cam_sim *sim, union ccb *ccb); 61 static void ahd_set_tran_settings(struct ahd_softc *ahd, 62 int our_id, char channel, 63 struct ccb_trans_settings *cts); 64 static void ahd_get_tran_settings(struct ahd_softc *ahd, 65 int our_id, char channel, 66 struct ccb_trans_settings *cts); 67 static void ahd_async(void *callback_arg, uint32_t code, 68 struct cam_path *path, void *arg); 69 static void ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, 70 int nsegments, int error); 71 static void ahd_poll(struct cam_sim *sim); 72 static void ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, 73 struct ccb_scsiio *csio, struct scb *scb); 74 static void ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, 75 union ccb *ccb); 76 static int ahd_create_path(struct ahd_softc *ahd, 77 char channel, u_int target, u_int lun, 78 struct cam_path **path); 79 80 static const char *ahd_sysctl_node_elements[] = { 81 "root", 82 "summary", 83 "debug" 84 }; 85 86 #ifndef NO_SYSCTL_DESCR 87 static const char *ahd_sysctl_node_descriptions[] = { 88 "root error collection for aic79xx controllers", 89 "summary collection for aic79xx controllers", 90 "debug collection for aic79xx controllers" 91 }; 92 #endif 93 94 static const char *ahd_sysctl_errors_elements[] = { 95 "Cerrors", 96 "Uerrors", 97 "Ferrors" 98 }; 99 100 #ifndef NO_SYSCTL_DESCR 101 static const char *ahd_sysctl_errors_descriptions[] = { 102 "Correctable errors", 103 "Uncorrectable errors", 104 "Fatal errors" 105 }; 106 #endif 107 108 static int 109 ahd_set_debugcounters(SYSCTL_HANDLER_ARGS) 110 { 111 struct ahd_softc *sc; 112 int error, tmpv; 113 114 tmpv = 0; 115 sc = arg1; 116 error = sysctl_handle_int(oidp, &tmpv, 0, req); 117 if (error != 0 || req->newptr == NULL) 118 return (error); 119 if (tmpv < 0 || tmpv >= AHD_ERRORS_NUMBER) 120 return (EINVAL); 121 sc->summerr[arg2] = tmpv; 122 return (0); 123 } 124 125 static int 126 ahd_clear_allcounters(SYSCTL_HANDLER_ARGS) 127 { 128 struct ahd_softc *sc; 129 int error, tmpv; 130 131 tmpv = 0; 132 sc = arg1; 133 error = sysctl_handle_int(oidp, &tmpv, 0, req); 134 if (error != 0 || req->newptr == NULL) 135 return (error); 136 if (tmpv != 0) 137 bzero(sc->summerr, sizeof(sc->summerr)); 138 return (0); 139 } 140 141 static int 142 ahd_create_path(struct ahd_softc *ahd, char channel, u_int target, 143 u_int lun, struct cam_path **path) 144 { 145 path_id_t path_id; 146 147 path_id = cam_sim_path(ahd->platform_data->sim); 148 return (xpt_create_path(path, /*periph*/NULL, 149 path_id, target, lun)); 150 } 151 152 void 153 ahd_sysctl(struct ahd_softc *ahd) 154 { 155 u_int i; 156 157 for (i = 0; i < AHD_SYSCTL_NUMBER; i++) 158 sysctl_ctx_init(&ahd->sysctl_ctx[i]); 159 160 ahd->sysctl_tree[AHD_SYSCTL_ROOT] = 161 SYSCTL_ADD_NODE(&ahd->sysctl_ctx[AHD_SYSCTL_ROOT], 162 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 163 device_get_nameunit(ahd->dev_softc), 164 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 165 ahd_sysctl_node_descriptions[AHD_SYSCTL_ROOT]); 166 SYSCTL_ADD_PROC(&ahd->sysctl_ctx[AHD_SYSCTL_ROOT], 167 SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_ROOT]), OID_AUTO, 168 "clear", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, ahd, 169 0, ahd_clear_allcounters, "IU", "Clear all counters"); 170 171 for (i = AHD_SYSCTL_SUMMARY; i < AHD_SYSCTL_NUMBER; i++) 172 ahd->sysctl_tree[i] = 173 SYSCTL_ADD_NODE(&ahd->sysctl_ctx[i], 174 SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_ROOT]), 175 OID_AUTO, ahd_sysctl_node_elements[i], 176 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 177 ahd_sysctl_node_descriptions[i]); 178 179 for (i = AHD_ERRORS_CORRECTABLE; i < AHD_ERRORS_NUMBER; i++) { 180 SYSCTL_ADD_UINT(&ahd->sysctl_ctx[AHD_SYSCTL_SUMMARY], 181 SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_SUMMARY]), 182 OID_AUTO, ahd_sysctl_errors_elements[i], 183 CTLFLAG_RD, &ahd->summerr[i], i, 184 ahd_sysctl_errors_descriptions[i]); 185 SYSCTL_ADD_PROC(&ahd->sysctl_ctx[AHD_SYSCTL_DEBUG], 186 SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_DEBUG]), 187 OID_AUTO, ahd_sysctl_errors_elements[i], 188 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, ahd, i, 189 ahd_set_debugcounters, "IU", 190 ahd_sysctl_errors_descriptions[i]); 191 } 192 } 193 194 int 195 ahd_map_int(struct ahd_softc *ahd) 196 { 197 int error; 198 199 /* Hook up our interrupt handler */ 200 error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq, 201 INTR_TYPE_CAM|INTR_MPSAFE, NULL, 202 ahd_platform_intr, ahd, &ahd->platform_data->ih); 203 if (error != 0) 204 device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n", 205 error); 206 return (error); 207 } 208 209 /* 210 * Attach all the sub-devices we can find 211 */ 212 int 213 ahd_attach(struct ahd_softc *ahd) 214 { 215 char ahd_info[256]; 216 struct ccb_setasync csa; 217 struct cam_devq *devq; 218 struct cam_sim *sim; 219 struct cam_path *path; 220 int count; 221 222 count = 0; 223 devq = NULL; 224 sim = NULL; 225 path = NULL; 226 227 /* 228 * Create a thread to perform all recovery. 229 */ 230 if (ahd_spawn_recovery_thread(ahd) != 0) 231 goto fail; 232 233 ahd_controller_info(ahd, ahd_info); 234 printf("%s\n", ahd_info); 235 ahd_lock(ahd); 236 237 /* 238 * Create the device queue for our SIM(s). 239 */ 240 devq = cam_simq_alloc(AHD_MAX_QUEUE); 241 if (devq == NULL) 242 goto fail; 243 244 /* 245 * Construct our SIM entry 246 */ 247 sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd, 248 device_get_unit(ahd->dev_softc), 249 &ahd->platform_data->mtx, 1, /*XXX*/256, devq); 250 if (sim == NULL) { 251 cam_simq_free(devq); 252 goto fail; 253 } 254 255 if (xpt_bus_register(sim, ahd->dev_softc, /*bus_id*/0) != CAM_SUCCESS) { 256 cam_sim_free(sim, /*free_devq*/TRUE); 257 sim = NULL; 258 goto fail; 259 } 260 261 if (xpt_create_path(&path, /*periph*/NULL, 262 cam_sim_path(sim), CAM_TARGET_WILDCARD, 263 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 264 xpt_bus_deregister(cam_sim_path(sim)); 265 cam_sim_free(sim, /*free_devq*/TRUE); 266 sim = NULL; 267 goto fail; 268 } 269 270 memset(&csa, 0, sizeof(csa)); 271 xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); 272 csa.ccb_h.func_code = XPT_SASYNC_CB; 273 csa.event_enable = AC_LOST_DEVICE; 274 csa.callback = ahd_async; 275 csa.callback_arg = sim; 276 xpt_action((union ccb *)&csa); 277 count++; 278 279 fail: 280 ahd->platform_data->sim = sim; 281 ahd->platform_data->path = path; 282 ahd_unlock(ahd); 283 if (count != 0) { 284 /* We have to wait until after any system dumps... */ 285 ahd->platform_data->eh = 286 EVENTHANDLER_REGISTER(shutdown_final, ahd_shutdown, 287 ahd, SHUTDOWN_PRI_DEFAULT); 288 ahd_intr_enable(ahd, TRUE); 289 } 290 291 return (count); 292 } 293 294 /* 295 * Catch an interrupt from the adapter 296 */ 297 void 298 ahd_platform_intr(void *arg) 299 { 300 struct ahd_softc *ahd; 301 302 ahd = (struct ahd_softc *)arg; 303 ahd_lock(ahd); 304 ahd_intr(ahd); 305 ahd_unlock(ahd); 306 } 307 308 /* 309 * We have an scb which has been processed by the 310 * adaptor, now we look to see how the operation 311 * went. 312 */ 313 void 314 ahd_done(struct ahd_softc *ahd, struct scb *scb) 315 { 316 union ccb *ccb; 317 318 CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE, 319 ("ahd_done - scb %d\n", SCB_GET_TAG(scb))); 320 321 ccb = scb->io_ctx; 322 LIST_REMOVE(scb, pending_links); 323 if ((scb->flags & SCB_TIMEDOUT) != 0) 324 LIST_REMOVE(scb, timedout_links); 325 326 callout_stop(&scb->io_timer); 327 328 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 329 bus_dmasync_op_t op; 330 331 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 332 op = BUS_DMASYNC_POSTREAD; 333 else 334 op = BUS_DMASYNC_POSTWRITE; 335 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op); 336 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); 337 } 338 339 #ifdef AHD_TARGET_MODE 340 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 341 struct cam_path *ccb_path; 342 343 /* 344 * If we have finally disconnected, clean up our 345 * pending device state. 346 * XXX - There may be error states that cause where 347 * we will remain connected. 348 */ 349 ccb_path = ccb->ccb_h.path; 350 if (ahd->pending_device != NULL 351 && xpt_path_comp(ahd->pending_device->path, ccb_path) == 0) { 352 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 353 ahd->pending_device = NULL; 354 } else { 355 xpt_print_path(ccb->ccb_h.path); 356 printf("Still disconnected\n"); 357 ahd_freeze_ccb(ccb); 358 } 359 } 360 361 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) 362 ccb->ccb_h.status |= CAM_REQ_CMP; 363 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 364 ahd_free_scb(ahd, scb); 365 xpt_done(ccb); 366 return; 367 } 368 #endif 369 370 if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 371 struct scb *list_scb; 372 373 ahd->scb_data.recovery_scbs--; 374 375 if (aic_get_transaction_status(scb) == CAM_BDR_SENT 376 || aic_get_transaction_status(scb) == CAM_REQ_ABORTED) 377 aic_set_transaction_status(scb, CAM_CMD_TIMEOUT); 378 379 if (ahd->scb_data.recovery_scbs == 0) { 380 /* 381 * All recovery actions have completed successfully, 382 * so reinstate the timeouts for all other pending 383 * commands. 384 */ 385 LIST_FOREACH(list_scb, 386 &ahd->pending_scbs, pending_links) { 387 aic_scb_timer_reset(list_scb, 388 aic_get_timeout(scb)); 389 } 390 391 ahd_print_path(ahd, scb); 392 printf("no longer in timeout, status = %x\n", 393 ccb->ccb_h.status); 394 } 395 } 396 397 /* Don't clobber any existing error state */ 398 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) { 399 ccb->ccb_h.status |= CAM_REQ_CMP; 400 } else if ((scb->flags & SCB_SENSE) != 0) { 401 /* 402 * We performed autosense retrieval. 403 * 404 * Zero any sense not transferred by the 405 * device. The SCSI spec mandates that any 406 * untransfered data should be assumed to be 407 * zero. Complete the 'bounce' of sense information 408 * through buffers accessible via bus-space by 409 * copying it into the clients csio. 410 */ 411 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 412 memcpy(&ccb->csio.sense_data, 413 ahd_get_sense_buf(ahd, scb), 414 /* XXX What size do we want to use??? */ 415 sizeof(ccb->csio.sense_data) 416 - ccb->csio.sense_resid); 417 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 418 } else if ((scb->flags & SCB_PKT_SENSE) != 0) { 419 struct scsi_status_iu_header *siu; 420 u_int sense_len; 421 422 /* 423 * Copy only the sense data into the provided buffer. 424 */ 425 siu = (struct scsi_status_iu_header *)scb->sense_data; 426 sense_len = MIN(scsi_4btoul(siu->sense_length), 427 sizeof(ccb->csio.sense_data)); 428 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data)); 429 memcpy(&ccb->csio.sense_data, 430 ahd_get_sense_buf(ahd, scb) + SIU_SENSE_OFFSET(siu), 431 sense_len); 432 #ifdef AHD_DEBUG 433 if ((ahd_debug & AHD_SHOW_SENSE) != 0) { 434 uint8_t *sense_data = (uint8_t *)&ccb->csio.sense_data; 435 u_int i; 436 437 printf("Copied %d bytes of sense data offset %d:", 438 sense_len, SIU_SENSE_OFFSET(siu)); 439 for (i = 0; i < sense_len; i++) 440 printf(" 0x%x", *sense_data++); 441 printf("\n"); 442 } 443 #endif 444 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID; 445 } 446 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 447 ahd_free_scb(ahd, scb); 448 xpt_done(ccb); 449 } 450 451 static void 452 ahd_action(struct cam_sim *sim, union ccb *ccb) 453 { 454 struct ahd_softc *ahd; 455 #ifdef AHD_TARGET_MODE 456 struct ahd_tmode_lstate *lstate; 457 #endif 458 u_int target_id; 459 u_int our_id; 460 461 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n")); 462 463 ahd = (struct ahd_softc *)cam_sim_softc(sim); 464 465 target_id = ccb->ccb_h.target_id; 466 our_id = SIM_SCSI_ID(ahd, sim); 467 468 switch (ccb->ccb_h.func_code) { 469 /* Common cases first */ 470 #ifdef AHD_TARGET_MODE 471 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 472 case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/ 473 { 474 struct ahd_tmode_tstate *tstate; 475 cam_status status; 476 477 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, 478 &lstate, TRUE); 479 480 if (status != CAM_REQ_CMP) { 481 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 482 /* Response from the black hole device */ 483 tstate = NULL; 484 lstate = ahd->black_hole; 485 } else { 486 ccb->ccb_h.status = status; 487 xpt_done(ccb); 488 break; 489 } 490 } 491 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { 492 SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h, 493 sim_links.sle); 494 ccb->ccb_h.status = CAM_REQ_INPROG; 495 if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0) 496 ahd_run_tqinfifo(ahd, /*paused*/FALSE); 497 break; 498 } 499 500 /* 501 * The target_id represents the target we attempt to 502 * select. In target mode, this is the initiator of 503 * the original command. 504 */ 505 our_id = target_id; 506 target_id = ccb->csio.init_id; 507 /* FALLTHROUGH */ 508 } 509 #endif 510 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 511 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 512 { 513 struct scb *scb; 514 struct hardware_scb *hscb; 515 struct ahd_initiator_tinfo *tinfo; 516 struct ahd_tmode_tstate *tstate; 517 u_int col_idx; 518 519 if ((ahd->flags & AHD_INITIATORROLE) == 0 520 && (ccb->ccb_h.func_code == XPT_SCSI_IO 521 || ccb->ccb_h.func_code == XPT_RESET_DEV)) { 522 ccb->ccb_h.status = CAM_PROVIDE_FAIL; 523 xpt_done(ccb); 524 return; 525 } 526 527 /* 528 * get an scb to use. 529 */ 530 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, 531 target_id, &tstate); 532 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0 533 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0 534 || ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 535 col_idx = AHD_NEVER_COL_IDX; 536 } else { 537 col_idx = AHD_BUILD_COL_IDX(target_id, 538 ccb->ccb_h.target_lun); 539 } 540 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) { 541 xpt_freeze_simq(sim, /*count*/1); 542 ahd->flags |= AHD_RESOURCE_SHORTAGE; 543 ccb->ccb_h.status = CAM_REQUEUE_REQ; 544 xpt_done(ccb); 545 return; 546 } 547 548 hscb = scb->hscb; 549 550 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, 551 ("start scb(%p)\n", scb)); 552 scb->io_ctx = ccb; 553 /* 554 * So we can find the SCB when an abort is requested 555 */ 556 ccb->ccb_h.ccb_scb_ptr = scb; 557 558 /* 559 * Put all the arguments for the xfer in the scb 560 */ 561 hscb->control = 0; 562 hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id); 563 hscb->lun = ccb->ccb_h.target_lun; 564 if (ccb->ccb_h.func_code == XPT_RESET_DEV) { 565 hscb->cdb_len = 0; 566 scb->flags |= SCB_DEVICE_RESET; 567 hscb->control |= MK_MESSAGE; 568 hscb->task_management = SIU_TASKMGMT_LUN_RESET; 569 ahd_execute_scb(scb, NULL, 0, 0); 570 } else { 571 #ifdef AHD_TARGET_MODE 572 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 573 struct target_data *tdata; 574 575 tdata = &hscb->shared_data.tdata; 576 if (ahd->pending_device == lstate) 577 scb->flags |= SCB_TARGET_IMMEDIATE; 578 hscb->control |= TARGET_SCB; 579 tdata->target_phases = 0; 580 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) { 581 tdata->target_phases |= SPHASE_PENDING; 582 tdata->scsi_status = 583 ccb->csio.scsi_status; 584 } 585 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) 586 tdata->target_phases |= NO_DISCONNECT; 587 588 tdata->initiator_tag = 589 ahd_htole16(ccb->csio.tag_id); 590 } 591 #endif 592 hscb->task_management = 0; 593 if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) 594 hscb->control |= ccb->csio.tag_action; 595 596 ahd_setup_data(ahd, sim, &ccb->csio, scb); 597 } 598 break; 599 } 600 #ifdef AHD_TARGET_MODE 601 case XPT_NOTIFY_ACKNOWLEDGE: 602 case XPT_IMMEDIATE_NOTIFY: 603 { 604 struct ahd_tmode_tstate *tstate; 605 struct ahd_tmode_lstate *lstate; 606 cam_status status; 607 608 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, 609 &lstate, TRUE); 610 611 if (status != CAM_REQ_CMP) { 612 ccb->ccb_h.status = status; 613 xpt_done(ccb); 614 break; 615 } 616 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h, 617 sim_links.sle); 618 ccb->ccb_h.status = CAM_REQ_INPROG; 619 ahd_send_lstate_events(ahd, lstate); 620 break; 621 } 622 case XPT_EN_LUN: /* Enable LUN as a target */ 623 ahd_handle_en_lun(ahd, sim, ccb); 624 xpt_done(ccb); 625 break; 626 #endif 627 case XPT_ABORT: /* Abort the specified CCB */ 628 { 629 ahd_abort_ccb(ahd, sim, ccb); 630 break; 631 } 632 case XPT_SET_TRAN_SETTINGS: 633 { 634 ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), 635 SIM_CHANNEL(ahd, sim), &ccb->cts); 636 xpt_done(ccb); 637 break; 638 } 639 case XPT_GET_TRAN_SETTINGS: 640 /* Get default/user set transfer settings for the target */ 641 { 642 ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim), 643 SIM_CHANNEL(ahd, sim), &ccb->cts); 644 xpt_done(ccb); 645 break; 646 } 647 case XPT_CALC_GEOMETRY: 648 { 649 aic_calc_geometry(&ccb->ccg, ahd->flags & AHD_EXTENDED_TRANS_A); 650 xpt_done(ccb); 651 break; 652 } 653 case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 654 { 655 int found; 656 657 found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim), 658 /*initiate reset*/TRUE); 659 if (bootverbose) { 660 xpt_print_path(SIM_PATH(ahd, sim)); 661 printf("SCSI bus reset delivered. " 662 "%d SCBs aborted.\n", found); 663 } 664 ccb->ccb_h.status = CAM_REQ_CMP; 665 xpt_done(ccb); 666 break; 667 } 668 case XPT_TERM_IO: /* Terminate the I/O process */ 669 /* XXX Implement */ 670 ccb->ccb_h.status = CAM_REQ_INVALID; 671 xpt_done(ccb); 672 break; 673 case XPT_PATH_INQ: /* Path routing inquiry */ 674 { 675 struct ccb_pathinq *cpi = &ccb->cpi; 676 677 cpi->version_num = 1; /* XXX??? */ 678 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 679 if ((ahd->features & AHD_WIDE) != 0) 680 cpi->hba_inquiry |= PI_WIDE_16; 681 if ((ahd->features & AHD_TARGETMODE) != 0) { 682 cpi->target_sprt = PIT_PROCESSOR 683 | PIT_DISCONNECT 684 | PIT_TERM_IO; 685 } else { 686 cpi->target_sprt = 0; 687 } 688 cpi->hba_misc = 0; 689 cpi->hba_eng_cnt = 0; 690 cpi->max_target = (ahd->features & AHD_WIDE) ? 15 : 7; 691 cpi->max_lun = AHD_NUM_LUNS_NONPKT - 1; 692 cpi->initiator_id = ahd->our_id; 693 if ((ahd->flags & AHD_RESET_BUS_A) == 0) { 694 cpi->hba_misc |= PIM_NOBUSRESET; 695 } 696 cpi->bus_id = cam_sim_bus(sim); 697 cpi->base_transfer_speed = 3300; 698 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 699 strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 700 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 701 cpi->unit_number = cam_sim_unit(sim); 702 cpi->protocol = PROTO_SCSI; 703 cpi->protocol_version = SCSI_REV_2; 704 cpi->transport = XPORT_SPI; 705 cpi->transport_version = 4; 706 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_DT_ST 707 | SID_SPI_IUS 708 | SID_SPI_QAS; 709 cpi->ccb_h.status = CAM_REQ_CMP; 710 xpt_done(ccb); 711 break; 712 } 713 default: 714 ccb->ccb_h.status = CAM_PROVIDE_FAIL; 715 xpt_done(ccb); 716 break; 717 } 718 } 719 720 static void 721 ahd_set_tran_settings(struct ahd_softc *ahd, int our_id, char channel, 722 struct ccb_trans_settings *cts) 723 { 724 struct ahd_devinfo devinfo; 725 struct ccb_trans_settings_scsi *scsi; 726 struct ccb_trans_settings_spi *spi; 727 struct ahd_initiator_tinfo *tinfo; 728 struct ahd_tmode_tstate *tstate; 729 uint16_t *discenable; 730 uint16_t *tagenable; 731 u_int update_type; 732 733 scsi = &cts->proto_specific.scsi; 734 spi = &cts->xport_specific.spi; 735 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim), 736 cts->ccb_h.target_id, 737 cts->ccb_h.target_lun, 738 SIM_CHANNEL(ahd, sim), 739 ROLE_UNKNOWN); 740 tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, 741 devinfo.our_scsiid, 742 devinfo.target, &tstate); 743 update_type = 0; 744 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { 745 update_type |= AHD_TRANS_GOAL; 746 discenable = &tstate->discenable; 747 tagenable = &tstate->tagenable; 748 tinfo->curr.protocol_version = cts->protocol_version; 749 tinfo->curr.transport_version = cts->transport_version; 750 tinfo->goal.protocol_version = cts->protocol_version; 751 tinfo->goal.transport_version = cts->transport_version; 752 } else if (cts->type == CTS_TYPE_USER_SETTINGS) { 753 update_type |= AHD_TRANS_USER; 754 discenable = &ahd->user_discenable; 755 tagenable = &ahd->user_tagenable; 756 tinfo->user.protocol_version = cts->protocol_version; 757 tinfo->user.transport_version = cts->transport_version; 758 } else { 759 cts->ccb_h.status = CAM_REQ_INVALID; 760 return; 761 } 762 763 if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { 764 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) 765 *discenable |= devinfo.target_mask; 766 else 767 *discenable &= ~devinfo.target_mask; 768 } 769 770 if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { 771 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) 772 *tagenable |= devinfo.target_mask; 773 else 774 *tagenable &= ~devinfo.target_mask; 775 } 776 777 if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { 778 ahd_validate_width(ahd, /*tinfo limit*/NULL, 779 &spi->bus_width, ROLE_UNKNOWN); 780 ahd_set_width(ahd, &devinfo, spi->bus_width, 781 update_type, /*paused*/FALSE); 782 } 783 784 if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) { 785 if (update_type == AHD_TRANS_USER) 786 spi->ppr_options = tinfo->user.ppr_options; 787 else 788 spi->ppr_options = tinfo->goal.ppr_options; 789 } 790 791 if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) { 792 if (update_type == AHD_TRANS_USER) 793 spi->sync_offset = tinfo->user.offset; 794 else 795 spi->sync_offset = tinfo->goal.offset; 796 } 797 798 if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) { 799 if (update_type == AHD_TRANS_USER) 800 spi->sync_period = tinfo->user.period; 801 else 802 spi->sync_period = tinfo->goal.period; 803 } 804 805 if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) 806 || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { 807 u_int maxsync; 808 809 maxsync = AHD_SYNCRATE_MAX; 810 811 if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT) 812 spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ; 813 814 if ((*discenable & devinfo.target_mask) == 0) 815 spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ; 816 817 ahd_find_syncrate(ahd, &spi->sync_period, 818 &spi->ppr_options, maxsync); 819 ahd_validate_offset(ahd, /*tinfo limit*/NULL, 820 spi->sync_period, &spi->sync_offset, 821 spi->bus_width, ROLE_UNKNOWN); 822 823 /* We use a period of 0 to represent async */ 824 if (spi->sync_offset == 0) { 825 spi->sync_period = 0; 826 spi->ppr_options = 0; 827 } 828 829 ahd_set_syncrate(ahd, &devinfo, spi->sync_period, 830 spi->sync_offset, spi->ppr_options, 831 update_type, /*paused*/FALSE); 832 } 833 cts->ccb_h.status = CAM_REQ_CMP; 834 } 835 836 static void 837 ahd_get_tran_settings(struct ahd_softc *ahd, int our_id, char channel, 838 struct ccb_trans_settings *cts) 839 { 840 struct ahd_devinfo devinfo; 841 struct ccb_trans_settings_scsi *scsi; 842 struct ccb_trans_settings_spi *spi; 843 struct ahd_initiator_tinfo *targ_info; 844 struct ahd_tmode_tstate *tstate; 845 struct ahd_transinfo *tinfo; 846 847 scsi = &cts->proto_specific.scsi; 848 spi = &cts->xport_specific.spi; 849 ahd_compile_devinfo(&devinfo, our_id, 850 cts->ccb_h.target_id, 851 cts->ccb_h.target_lun, 852 channel, ROLE_UNKNOWN); 853 targ_info = ahd_fetch_transinfo(ahd, devinfo.channel, 854 devinfo.our_scsiid, 855 devinfo.target, &tstate); 856 857 if (cts->type == CTS_TYPE_CURRENT_SETTINGS) 858 tinfo = &targ_info->curr; 859 else 860 tinfo = &targ_info->user; 861 862 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 863 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 864 if (cts->type == CTS_TYPE_USER_SETTINGS) { 865 if ((ahd->user_discenable & devinfo.target_mask) != 0) 866 spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 867 868 if ((ahd->user_tagenable & devinfo.target_mask) != 0) 869 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 870 } else { 871 if ((tstate->discenable & devinfo.target_mask) != 0) 872 spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 873 874 if ((tstate->tagenable & devinfo.target_mask) != 0) 875 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 876 } 877 cts->protocol_version = tinfo->protocol_version; 878 cts->transport_version = tinfo->transport_version; 879 880 spi->sync_period = tinfo->period; 881 spi->sync_offset = tinfo->offset; 882 spi->bus_width = tinfo->width; 883 spi->ppr_options = tinfo->ppr_options; 884 885 cts->protocol = PROTO_SCSI; 886 cts->transport = XPORT_SPI; 887 spi->valid = CTS_SPI_VALID_SYNC_RATE 888 | CTS_SPI_VALID_SYNC_OFFSET 889 | CTS_SPI_VALID_BUS_WIDTH 890 | CTS_SPI_VALID_PPR_OPTIONS; 891 892 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 893 scsi->valid = CTS_SCSI_VALID_TQ; 894 spi->valid |= CTS_SPI_VALID_DISC; 895 } else { 896 scsi->valid = 0; 897 } 898 899 cts->ccb_h.status = CAM_REQ_CMP; 900 } 901 902 static void 903 ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) 904 { 905 struct ahd_softc *ahd; 906 struct cam_sim *sim; 907 908 sim = (struct cam_sim *)callback_arg; 909 ahd = (struct ahd_softc *)cam_sim_softc(sim); 910 switch (code) { 911 case AC_LOST_DEVICE: 912 { 913 struct ahd_devinfo devinfo; 914 915 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim), 916 xpt_path_target_id(path), 917 xpt_path_lun_id(path), 918 SIM_CHANNEL(ahd, sim), 919 ROLE_UNKNOWN); 920 921 /* 922 * Revert to async/narrow transfers 923 * for the next device. 924 */ 925 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, 926 AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE); 927 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, 928 /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR, 929 /*paused*/FALSE); 930 break; 931 } 932 default: 933 break; 934 } 935 } 936 937 static void 938 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments, 939 int error) 940 { 941 struct scb *scb; 942 union ccb *ccb; 943 struct ahd_softc *ahd; 944 struct ahd_initiator_tinfo *tinfo; 945 struct ahd_tmode_tstate *tstate; 946 u_int mask; 947 948 scb = (struct scb *)arg; 949 ccb = scb->io_ctx; 950 ahd = scb->ahd_softc; 951 952 if (error != 0) { 953 if (error == EFBIG) 954 aic_set_transaction_status(scb, CAM_REQ_TOO_BIG); 955 else 956 aic_set_transaction_status(scb, CAM_REQ_CMP_ERR); 957 if (nsegments != 0) 958 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap); 959 ahd_free_scb(ahd, scb); 960 xpt_done(ccb); 961 return; 962 } 963 scb->sg_count = 0; 964 if (nsegments != 0) { 965 void *sg; 966 bus_dmasync_op_t op; 967 u_int i; 968 969 /* Copy the segments into our SG list */ 970 for (i = nsegments, sg = scb->sg_list; i > 0; i--) { 971 sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr, 972 dm_segs->ds_len, 973 /*last*/i == 1); 974 dm_segs++; 975 } 976 977 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 978 op = BUS_DMASYNC_PREREAD; 979 else 980 op = BUS_DMASYNC_PREWRITE; 981 982 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op); 983 984 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) { 985 struct target_data *tdata; 986 987 tdata = &scb->hscb->shared_data.tdata; 988 tdata->target_phases |= DPHASE_PENDING; 989 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 990 tdata->data_phase = P_DATAOUT; 991 else 992 tdata->data_phase = P_DATAIN; 993 } 994 } 995 996 /* 997 * Last time we need to check if this SCB needs to 998 * be aborted. 999 */ 1000 if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) { 1001 if (nsegments != 0) 1002 bus_dmamap_unload(ahd->buffer_dmat, 1003 scb->dmamap); 1004 ahd_free_scb(ahd, scb); 1005 xpt_done(ccb); 1006 return; 1007 } 1008 1009 tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid), 1010 SCSIID_OUR_ID(scb->hscb->scsiid), 1011 SCSIID_TARGET(ahd, scb->hscb->scsiid), 1012 &tstate); 1013 1014 mask = SCB_GET_TARGET_MASK(ahd, scb); 1015 1016 if ((tstate->discenable & mask) != 0 1017 && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0) 1018 scb->hscb->control |= DISCENB; 1019 1020 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { 1021 scb->flags |= SCB_PACKETIZED; 1022 if (scb->hscb->task_management != 0) 1023 scb->hscb->control &= ~MK_MESSAGE; 1024 } 1025 1026 if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0 1027 && (tinfo->goal.width != 0 1028 || tinfo->goal.period != 0 1029 || tinfo->goal.ppr_options != 0)) { 1030 scb->flags |= SCB_NEGOTIATE; 1031 scb->hscb->control |= MK_MESSAGE; 1032 } else if ((tstate->auto_negotiate & mask) != 0) { 1033 scb->flags |= SCB_AUTO_NEGOTIATE; 1034 scb->hscb->control |= MK_MESSAGE; 1035 } 1036 1037 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); 1038 1039 ccb->ccb_h.status |= CAM_SIM_QUEUED; 1040 1041 aic_scb_timer_start(scb); 1042 1043 if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 1044 /* Define a mapping from our tag to the SCB. */ 1045 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; 1046 ahd_pause(ahd); 1047 ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); 1048 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG); 1049 ahd_unpause(ahd); 1050 } else { 1051 ahd_queue_scb(ahd, scb); 1052 } 1053 1054 } 1055 1056 static void 1057 ahd_poll(struct cam_sim *sim) 1058 { 1059 ahd_intr(cam_sim_softc(sim)); 1060 } 1061 1062 static void 1063 ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, 1064 struct ccb_scsiio *csio, struct scb *scb) 1065 { 1066 struct hardware_scb *hscb; 1067 struct ccb_hdr *ccb_h; 1068 int error; 1069 1070 hscb = scb->hscb; 1071 ccb_h = &csio->ccb_h; 1072 1073 csio->resid = 0; 1074 csio->sense_resid = 0; 1075 if (ccb_h->func_code == XPT_SCSI_IO) { 1076 hscb->cdb_len = csio->cdb_len; 1077 if ((ccb_h->flags & CAM_CDB_POINTER) != 0) { 1078 if (hscb->cdb_len > MAX_CDB_LEN 1079 && (ccb_h->flags & CAM_CDB_PHYS) == 0) { 1080 /* 1081 * Should CAM start to support CDB sizes 1082 * greater than 16 bytes, we could use 1083 * the sense buffer to store the CDB. 1084 */ 1085 aic_set_transaction_status(scb, 1086 CAM_REQ_INVALID); 1087 ahd_free_scb(ahd, scb); 1088 xpt_done((union ccb *)csio); 1089 return; 1090 } 1091 if ((ccb_h->flags & CAM_CDB_PHYS) != 0) { 1092 hscb->shared_data.idata.cdb_from_host.cdbptr = 1093 aic_htole64((uintptr_t)csio->cdb_io.cdb_ptr); 1094 hscb->shared_data.idata.cdb_from_host.cdblen = 1095 csio->cdb_len; 1096 hscb->cdb_len |= SCB_CDB_LEN_PTR; 1097 } else { 1098 memcpy(hscb->shared_data.idata.cdb, 1099 csio->cdb_io.cdb_ptr, 1100 hscb->cdb_len); 1101 } 1102 } else { 1103 if (hscb->cdb_len > MAX_CDB_LEN) { 1104 aic_set_transaction_status(scb, 1105 CAM_REQ_INVALID); 1106 ahd_free_scb(ahd, scb); 1107 xpt_done((union ccb *)csio); 1108 return; 1109 } 1110 memcpy(hscb->shared_data.idata.cdb, 1111 csio->cdb_io.cdb_bytes, hscb->cdb_len); 1112 } 1113 } 1114 1115 error = bus_dmamap_load_ccb(ahd->buffer_dmat, 1116 scb->dmamap, 1117 (union ccb *)csio, 1118 ahd_execute_scb, 1119 scb, /*flags*/0); 1120 if (error == EINPROGRESS) { 1121 /* 1122 * So as to maintain ordering, freeze the controller queue 1123 * until our mapping is returned. 1124 */ 1125 xpt_freeze_simq(sim, /*count*/1); 1126 scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; 1127 } 1128 } 1129 1130 static void 1131 ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) 1132 { 1133 union ccb *abort_ccb; 1134 1135 abort_ccb = ccb->cab.abort_ccb; 1136 switch (abort_ccb->ccb_h.func_code) { 1137 #ifdef AHD_TARGET_MODE 1138 case XPT_ACCEPT_TARGET_IO: 1139 case XPT_IMMEDIATE_NOTIFY: 1140 case XPT_CONT_TARGET_IO: 1141 { 1142 struct ahd_tmode_tstate *tstate; 1143 struct ahd_tmode_lstate *lstate; 1144 struct ccb_hdr_slist *list; 1145 cam_status status; 1146 1147 status = ahd_find_tmode_devs(ahd, sim, abort_ccb, &tstate, 1148 &lstate, TRUE); 1149 1150 if (status != CAM_REQ_CMP) { 1151 ccb->ccb_h.status = status; 1152 break; 1153 } 1154 1155 if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) 1156 list = &lstate->accept_tios; 1157 else if (abort_ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) 1158 list = &lstate->immed_notifies; 1159 else 1160 list = NULL; 1161 1162 if (list != NULL) { 1163 struct ccb_hdr *curelm; 1164 int found; 1165 1166 curelm = SLIST_FIRST(list); 1167 found = 0; 1168 if (curelm == &abort_ccb->ccb_h) { 1169 found = 1; 1170 SLIST_REMOVE_HEAD(list, sim_links.sle); 1171 } else { 1172 while(curelm != NULL) { 1173 struct ccb_hdr *nextelm; 1174 1175 nextelm = 1176 SLIST_NEXT(curelm, sim_links.sle); 1177 1178 if (nextelm == &abort_ccb->ccb_h) { 1179 found = 1; 1180 SLIST_NEXT(curelm, 1181 sim_links.sle) = 1182 SLIST_NEXT(nextelm, 1183 sim_links.sle); 1184 break; 1185 } 1186 curelm = nextelm; 1187 } 1188 } 1189 1190 if (found) { 1191 abort_ccb->ccb_h.status = CAM_REQ_ABORTED; 1192 xpt_done(abort_ccb); 1193 ccb->ccb_h.status = CAM_REQ_CMP; 1194 } else { 1195 xpt_print_path(abort_ccb->ccb_h.path); 1196 printf("Not found\n"); 1197 ccb->ccb_h.status = CAM_PATH_INVALID; 1198 } 1199 break; 1200 } 1201 /* FALLTHROUGH */ 1202 } 1203 #endif 1204 case XPT_SCSI_IO: 1205 /* XXX Fully implement the hard ones */ 1206 ccb->ccb_h.status = CAM_UA_ABORT; 1207 break; 1208 default: 1209 ccb->ccb_h.status = CAM_REQ_INVALID; 1210 break; 1211 } 1212 xpt_done(ccb); 1213 } 1214 1215 void 1216 ahd_send_async(struct ahd_softc *ahd, char channel, u_int target, 1217 u_int lun, ac_code code, void *opt_arg) 1218 { 1219 struct ccb_trans_settings cts; 1220 struct cam_path *path; 1221 void *arg; 1222 int error; 1223 1224 arg = NULL; 1225 error = ahd_create_path(ahd, channel, target, lun, &path); 1226 1227 if (error != CAM_REQ_CMP) 1228 return; 1229 1230 switch (code) { 1231 case AC_TRANSFER_NEG: 1232 { 1233 struct ccb_trans_settings_scsi *scsi; 1234 1235 cts.type = CTS_TYPE_CURRENT_SETTINGS; 1236 scsi = &cts.proto_specific.scsi; 1237 cts.ccb_h.path = path; 1238 cts.ccb_h.target_id = target; 1239 cts.ccb_h.target_lun = lun; 1240 ahd_get_tran_settings(ahd, ahd->our_id, channel, &cts); 1241 arg = &cts; 1242 scsi->valid &= ~CTS_SCSI_VALID_TQ; 1243 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 1244 if (opt_arg == NULL) 1245 break; 1246 if (*((ahd_queue_alg *)opt_arg) == AHD_QUEUE_TAGGED) 1247 scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB; 1248 scsi->valid |= CTS_SCSI_VALID_TQ; 1249 break; 1250 } 1251 case AC_SENT_BDR: 1252 case AC_BUS_RESET: 1253 break; 1254 default: 1255 panic("ahd_send_async: Unexpected async event"); 1256 } 1257 xpt_async(code, path, arg); 1258 xpt_free_path(path); 1259 } 1260 1261 void 1262 ahd_platform_set_tags(struct ahd_softc *ahd, 1263 struct ahd_devinfo *devinfo, int enable) 1264 { 1265 } 1266 1267 int 1268 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) 1269 { 1270 ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF, 1271 M_NOWAIT | M_ZERO); 1272 if (ahd->platform_data == NULL) 1273 return (ENOMEM); 1274 return (0); 1275 } 1276 1277 void 1278 ahd_platform_free(struct ahd_softc *ahd) 1279 { 1280 struct ahd_platform_data *pdata; 1281 1282 pdata = ahd->platform_data; 1283 if (pdata != NULL) { 1284 if (pdata->regs[0] != NULL) 1285 bus_release_resource(ahd->dev_softc, 1286 pdata->regs_res_type[0], 1287 pdata->regs_res_id[0], 1288 pdata->regs[0]); 1289 1290 if (pdata->regs[1] != NULL) 1291 bus_release_resource(ahd->dev_softc, 1292 pdata->regs_res_type[1], 1293 pdata->regs_res_id[1], 1294 pdata->regs[1]); 1295 1296 if (pdata->irq != NULL) 1297 bus_release_resource(ahd->dev_softc, 1298 pdata->irq_res_type, 1299 0, pdata->irq); 1300 1301 if (pdata->sim != NULL) { 1302 xpt_async(AC_LOST_DEVICE, pdata->path, NULL); 1303 xpt_free_path(pdata->path); 1304 xpt_bus_deregister(cam_sim_path(pdata->sim)); 1305 cam_sim_free(pdata->sim, /*free_devq*/TRUE); 1306 } 1307 if (pdata->eh != NULL) 1308 EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh); 1309 free(ahd->platform_data, M_DEVBUF); 1310 } 1311 } 1312 1313 int 1314 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) 1315 { 1316 /* We don't sort softcs under FreeBSD so report equal always */ 1317 return (0); 1318 } 1319 1320 int 1321 ahd_detach(device_t dev) 1322 { 1323 struct ahd_softc *ahd; 1324 1325 device_printf(dev, "detaching device\n"); 1326 ahd = device_get_softc(dev); 1327 ahd_lock(ahd); 1328 TAILQ_REMOVE(&ahd_tailq, ahd, links); 1329 ahd_intr_enable(ahd, FALSE); 1330 bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih); 1331 ahd_unlock(ahd); 1332 ahd_free(ahd); 1333 return (0); 1334 } 1335 1336 #if 0 1337 static void 1338 ahd_dump_targcmd(struct target_cmd *cmd) 1339 { 1340 uint8_t *byte; 1341 uint8_t *last_byte; 1342 int i; 1343 1344 byte = &cmd->initiator_channel; 1345 /* Debugging info for received commands */ 1346 last_byte = &cmd[1].initiator_channel; 1347 1348 i = 0; 1349 while (byte < last_byte) { 1350 if (i == 0) 1351 printf("\t"); 1352 printf("%#x", *byte++); 1353 i++; 1354 if (i == 8) { 1355 printf("\n"); 1356 i = 0; 1357 } else { 1358 printf(", "); 1359 } 1360 } 1361 } 1362 #endif 1363 1364 static int 1365 ahd_modevent(module_t mod, int type, void *data) 1366 { 1367 /* XXX Deal with busy status on unload. */ 1368 /* XXX Deal with unknown events */ 1369 return 0; 1370 } 1371 1372 static moduledata_t ahd_mod = { 1373 "ahd", 1374 ahd_modevent, 1375 NULL 1376 }; 1377 1378 /********************************** DDB Hooks *********************************/ 1379 #ifdef DDB 1380 static struct ahd_softc *ahd_ddb_softc; 1381 static int ahd_ddb_paused; 1382 static int ahd_ddb_paused_on_entry; 1383 DB_COMMAND(ahd_sunit, ahd_ddb_sunit) 1384 { 1385 struct ahd_softc *list_ahd; 1386 1387 ahd_ddb_softc = NULL; 1388 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { 1389 if (list_ahd->unit == addr) 1390 ahd_ddb_softc = list_ahd; 1391 } 1392 if (ahd_ddb_softc == NULL) 1393 db_error("No matching softc found!\n"); 1394 } 1395 1396 DB_COMMAND(ahd_pause, ahd_ddb_pause) 1397 { 1398 if (ahd_ddb_softc == NULL) { 1399 db_error("Must set unit with ahd_sunit first!\n"); 1400 return; 1401 } 1402 if (ahd_ddb_paused == 0) { 1403 ahd_ddb_paused++; 1404 if (ahd_is_paused(ahd_ddb_softc)) { 1405 ahd_ddb_paused_on_entry++; 1406 return; 1407 } 1408 ahd_pause(ahd_ddb_softc); 1409 } 1410 } 1411 1412 DB_COMMAND(ahd_unpause, ahd_ddb_unpause) 1413 { 1414 if (ahd_ddb_softc == NULL) { 1415 db_error("Must set unit with ahd_sunit first!\n"); 1416 return; 1417 } 1418 if (ahd_ddb_paused != 0) { 1419 ahd_ddb_paused = 0; 1420 if (ahd_ddb_paused_on_entry) 1421 return; 1422 ahd_unpause(ahd_ddb_softc); 1423 } else if (ahd_ddb_paused_on_entry != 0) { 1424 /* Two unpauses to clear a paused on entry. */ 1425 ahd_ddb_paused_on_entry = 0; 1426 ahd_unpause(ahd_ddb_softc); 1427 } 1428 } 1429 1430 DB_COMMAND(ahd_in, ahd_ddb_in) 1431 { 1432 int c; 1433 int size; 1434 1435 if (ahd_ddb_softc == NULL) { 1436 db_error("Must set unit with ahd_sunit first!\n"); 1437 return; 1438 } 1439 if (have_addr == 0) 1440 return; 1441 1442 size = 1; 1443 while ((c = *modif++) != '\0') { 1444 switch (c) { 1445 case 'b': 1446 size = 1; 1447 break; 1448 case 'w': 1449 size = 2; 1450 break; 1451 case 'l': 1452 size = 4; 1453 break; 1454 } 1455 } 1456 1457 if (count <= 0) 1458 count = 1; 1459 while (--count >= 0) { 1460 db_printf("%04lx (M)%x: \t", (u_long)addr, 1461 ahd_inb(ahd_ddb_softc, MODE_PTR)); 1462 switch (size) { 1463 case 1: 1464 db_printf("%02x\n", ahd_inb(ahd_ddb_softc, addr)); 1465 break; 1466 case 2: 1467 db_printf("%04x\n", ahd_inw(ahd_ddb_softc, addr)); 1468 break; 1469 case 4: 1470 db_printf("%08x\n", ahd_inl(ahd_ddb_softc, addr)); 1471 break; 1472 } 1473 } 1474 } 1475 1476 DB_COMMAND_FLAGS(ahd_out, ahd_ddb_out, CS_MORE) 1477 { 1478 db_expr_t old_value; 1479 db_expr_t new_value; 1480 int size; 1481 1482 if (ahd_ddb_softc == NULL) { 1483 db_error("Must set unit with ahd_sunit first!\n"); 1484 return; 1485 } 1486 1487 switch (modif[0]) { 1488 case '\0': 1489 case 'b': 1490 size = 1; 1491 break; 1492 case 'h': 1493 size = 2; 1494 break; 1495 case 'l': 1496 size = 4; 1497 break; 1498 default: 1499 db_error("Unknown size\n"); 1500 return; 1501 } 1502 1503 while (db_expression(&new_value)) { 1504 switch (size) { 1505 default: 1506 case 1: 1507 old_value = ahd_inb(ahd_ddb_softc, addr); 1508 ahd_outb(ahd_ddb_softc, addr, new_value); 1509 break; 1510 case 2: 1511 old_value = ahd_inw(ahd_ddb_softc, addr); 1512 ahd_outw(ahd_ddb_softc, addr, new_value); 1513 break; 1514 case 4: 1515 old_value = ahd_inl(ahd_ddb_softc, addr); 1516 ahd_outl(ahd_ddb_softc, addr, new_value); 1517 break; 1518 } 1519 db_printf("%04lx (M)%x: \t0x%lx\t=\t0x%lx", 1520 (u_long)addr, ahd_inb(ahd_ddb_softc, MODE_PTR), 1521 (u_long)old_value, (u_long)new_value); 1522 addr += size; 1523 } 1524 db_skip_to_eol(); 1525 } 1526 1527 DB_COMMAND(ahd_dump, ahd_ddb_dump) 1528 { 1529 if (ahd_ddb_softc == NULL) { 1530 db_error("Must set unit with ahd_sunit first!\n"); 1531 return; 1532 } 1533 ahd_dump_card_state(ahd_ddb_softc); 1534 } 1535 1536 #endif 1537 1538 DECLARE_MODULE(ahd, ahd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 1539 MODULE_DEPEND(ahd, cam, 1, 1, 1); 1540 MODULE_VERSION(ahd, 1); 1541