1 /* $OpenBSD: aic7xxx_openbsd.c,v 1.71 2020/09/22 19:32:52 krw Exp $ */ 2 /* $NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $ */ 3 4 /* 5 * Bus independent OpenBSD shim for the aic7xxx based adaptec SCSI controllers 6 * 7 * Copyright (c) 1994-2001 Justin T. Gibbs. 8 * Copyright (c) 2001-2002 Steve Murphree, Jr. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * Alternatively, this software may be distributed under the terms of the 21 * GNU Public License ("GPL"). 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#12 $ 36 * 37 * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_osm.c,v 1.31 2002/11/30 19:08:58 scottl Exp $ 38 */ 39 /* 40 * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003 41 */ 42 43 #include <dev/ic/aic7xxx_openbsd.h> 44 #include <dev/ic/aic7xxx_inline.h> 45 46 #ifndef AHC_TMODE_ENABLE 47 #define AHC_TMODE_ENABLE 0 48 #endif 49 50 51 void ahc_action(struct scsi_xfer *); 52 void ahc_execute_scb(void *, bus_dma_segment_t *, int); 53 int ahc_poll(struct ahc_softc *, int); 54 void ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *); 55 56 void ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *); 57 58 59 struct cfdriver ahc_cd = { 60 NULL, "ahc", DV_DULL 61 }; 62 63 static struct scsi_adapter ahc_switch = { 64 ahc_action, NULL, NULL, NULL, NULL 65 }; 66 67 /* 68 * Attach all the sub-devices we can find 69 */ 70 int 71 ahc_attach(struct ahc_softc *ahc) 72 { 73 struct scsibus_attach_args saa; 74 int s; 75 76 s = splbio(); 77 78 #ifndef DEBUG 79 if (bootverbose) { 80 char ahc_info[256]; 81 ahc_controller_info(ahc, ahc_info, sizeof ahc_info); 82 printf("%s: %s\n", ahc->sc_dev.dv_xname, ahc_info); 83 } 84 #endif 85 86 ahc_intr_enable(ahc, TRUE); 87 88 if (ahc->flags & AHC_RESET_BUS_A) 89 ahc_reset_channel(ahc, 'A', TRUE); 90 if ((ahc->features & AHC_TWIN) && ahc->flags & AHC_RESET_BUS_B) 91 ahc_reset_channel(ahc, 'B', TRUE); 92 93 saa.saa_adapter_buswidth = (ahc->features & AHC_WIDE) ? 16 :8; 94 saa.saa_adapter_softc = ahc; 95 saa.saa_adapter = &ahc_switch; 96 saa.saa_luns = saa.saa_adapter_buswidth = 8; 97 saa.saa_openings = 16; 98 saa.saa_pool = &ahc->sc_iopool; 99 saa.saa_quirks = saa.saa_flags = 0; 100 saa.saa_wwpn = saa.saa_wwnn = 0; 101 if ((ahc->flags & AHC_PRIMARY_CHANNEL) == 0) { 102 saa.saa_adapter_target = ahc->our_id; 103 ahc->sc_child = (struct scsibus_softc *)config_found( 104 (void *)&ahc->sc_dev, &saa, scsiprint); 105 if (ahc->features & AHC_TWIN) { 106 saa.saa_adapter_target = ahc->our_id_b; 107 ahc->sc_child_b = (struct scsibus_softc *)config_found( 108 (void *)&ahc->sc_dev, &saa, scsiprint); 109 } 110 } else { 111 if (ahc->features & AHC_TWIN) { 112 saa.saa_adapter_target = ahc->our_id_b; 113 ahc->sc_child = (struct scsibus_softc *)config_found( 114 (void *)&ahc->sc_dev, &saa, scsiprint); 115 } 116 saa.saa_adapter_target = ahc->our_id; 117 ahc->sc_child_b = (struct scsibus_softc *)config_found( 118 (void *)&ahc->sc_dev, &saa, scsiprint); 119 } 120 121 splx(s); 122 return (1); 123 } 124 125 /* 126 * Catch an interrupt from the adapter 127 */ 128 int 129 ahc_platform_intr(void *arg) 130 { 131 struct ahc_softc *ahc = (struct ahc_softc *)arg; 132 133 bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap, 134 0, ahc->scb_data->hscb_dmamap->dm_mapsize, 135 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 136 137 return ahc_intr(ahc); 138 } 139 140 /* 141 * We have an scb which has been processed by the 142 * adaptor, now we look to see how the operation 143 * went. 144 */ 145 void 146 ahc_done(struct ahc_softc *ahc, struct scb *scb) 147 { 148 struct scsi_xfer *xs = scb->xs; 149 150 bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap, 151 0, ahc->scb_data->hscb_dmamap->dm_mapsize, 152 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 153 154 LIST_REMOVE(scb, pending_links); 155 if ((scb->flags & SCB_UNTAGGEDQ) != 0) { 156 struct scb_tailq *untagged_q; 157 int target_offset; 158 159 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 160 untagged_q = &ahc->untagged_queues[target_offset]; 161 TAILQ_REMOVE(untagged_q, scb, links.tqe); 162 scb->flags &= ~SCB_UNTAGGEDQ; 163 ahc_run_untagged_queue(ahc, untagged_q); 164 } 165 166 timeout_del(&xs->stimeout); 167 168 if (xs->datalen) { 169 int op; 170 171 if ((xs->flags & SCSI_DATA_IN) != 0) 172 op = BUS_DMASYNC_POSTREAD; 173 else 174 op = BUS_DMASYNC_POSTWRITE; 175 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0, 176 scb->dmamap->dm_mapsize, op); 177 bus_dmamap_unload(ahc->parent_dmat, scb->dmamap); 178 } 179 180 /* Translate the CAM status code to a SCSI error code. */ 181 switch (xs->error) { 182 case CAM_SCSI_STATUS_ERROR: 183 case CAM_REQ_INPROG: 184 case CAM_REQ_CMP: 185 switch (xs->status) { 186 case SCSI_TASKSET_FULL: 187 case SCSI_BUSY: 188 xs->error = XS_BUSY; 189 break; 190 case SCSI_CHECK: 191 case SCSI_TERMINATED: 192 if ((scb->flags & SCB_SENSE) == 0) { 193 /* CHECK on CHECK? */ 194 xs->error = XS_DRIVER_STUFFUP; 195 } else 196 xs->error = XS_NOERROR; 197 break; 198 default: 199 xs->error = XS_NOERROR; 200 break; 201 } 202 break; 203 case CAM_REQUEUE_REQ: 204 case CAM_BUSY: 205 xs->error = XS_BUSY; 206 break; 207 case CAM_CMD_TIMEOUT: 208 xs->error = XS_TIMEOUT; 209 break; 210 case CAM_BDR_SENT: 211 case CAM_SCSI_BUS_RESET: 212 xs->error = XS_RESET; 213 break; 214 case CAM_SEL_TIMEOUT: 215 xs->error = XS_SELTIMEOUT; 216 break; 217 default: 218 xs->error = XS_DRIVER_STUFFUP; 219 break; 220 } 221 222 /* Don't clobber any existing error state */ 223 if (xs->error != XS_NOERROR) { 224 /* Don't clobber any existing error state */ 225 } else if ((scb->flags & SCB_SENSE) != 0) { 226 /* 227 * We performed autosense retrieval. 228 * 229 * Zero any sense not transferred by the 230 * device. The SCSI spec mandates that any 231 * untransferred data should be assumed to be 232 * zero. Complete the 'bounce' of sense information 233 * through buffers accessible via bus-space by 234 * copying it into the clients csio. 235 */ 236 memset(&xs->sense, 0, sizeof(struct scsi_sense_data)); 237 memcpy(&xs->sense, ahc_get_sense_buf(ahc, scb), 238 aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK); 239 xs->error = XS_SENSE; 240 } 241 242 scsi_done(xs); 243 } 244 245 void 246 ahc_action(struct scsi_xfer *xs) 247 { 248 struct ahc_softc *ahc; 249 struct scb *scb; 250 struct hardware_scb *hscb; 251 u_int target_id; 252 u_int our_id; 253 254 #ifdef AHC_DEBUG 255 printf("%s: ahc_action\n", ahc_name(ahc)); 256 #endif 257 ahc = xs->sc_link->bus->sb_adapter_softc; 258 259 target_id = xs->sc_link->target; 260 our_id = SCSI_SCSI_ID(ahc, xs->sc_link); 261 262 /* 263 * get the scb to use. 264 */ 265 scb = xs->io; 266 267 /* Clean up for the next user */ 268 scb->flags = SCB_FLAG_NONE; 269 270 hscb = scb->hscb; 271 hscb->control = 0; 272 ahc->scb_data->scbindex[hscb->tag] = NULL; 273 274 #ifdef AHC_DEBUG 275 printf("%s: start scb(%p)\n", ahc_name(ahc), scb); 276 #endif 277 scb->xs = xs; 278 timeout_set(&xs->stimeout, ahc_timeout, scb); 279 280 /* 281 * Put all the arguments for the xfer in the scb 282 */ 283 hscb->control = 0; 284 hscb->scsiid = BUILD_SCSIID(ahc, xs->sc_link, target_id, our_id); 285 hscb->lun = xs->sc_link->lun; 286 if (xs->xs_control & XS_CTL_RESET) { 287 hscb->cdb_len = 0; 288 scb->flags |= SCB_DEVICE_RESET; 289 hscb->control |= MK_MESSAGE; 290 ahc_execute_scb(scb, NULL, 0); 291 return; 292 } 293 294 ahc_setup_data(ahc, xs, scb); 295 } 296 297 void 298 ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments) 299 { 300 struct scb *scb; 301 struct scsi_xfer *xs; 302 struct ahc_softc *ahc; 303 struct ahc_initiator_tinfo *tinfo; 304 struct ahc_tmode_tstate *tstate; 305 306 u_int mask; 307 int s; 308 309 scb = (struct scb *)arg; 310 xs = scb->xs; 311 xs->error = CAM_REQ_INPROG; 312 xs->status = 0; 313 ahc = xs->sc_link->bus->sb_adapter_softc; 314 315 if (nsegments != 0) { 316 struct ahc_dma_seg *sg; 317 bus_dma_segment_t *end_seg; 318 int op; 319 320 end_seg = dm_segs + nsegments; 321 322 /* Copy the segments into our SG list */ 323 sg = scb->sg_list; 324 while (dm_segs < end_seg) { 325 uint32_t len; 326 327 sg->addr = aic_htole32(dm_segs->ds_addr); 328 len = dm_segs->ds_len 329 | ((dm_segs->ds_addr >> 8) & 0x7F000000); 330 sg->len = aic_htole32(len); 331 sg++; 332 dm_segs++; 333 } 334 335 /* 336 * Note where to find the SG entries in bus space. 337 * We also set the full residual flag which the 338 * sequencer will clear as soon as a data transfer 339 * occurs. 340 */ 341 scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID); 342 343 if ((xs->flags & SCSI_DATA_IN) != 0) 344 op = BUS_DMASYNC_PREREAD; 345 else 346 op = BUS_DMASYNC_PREWRITE; 347 348 bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0, 349 scb->dmamap->dm_mapsize, op); 350 351 sg--; 352 sg->len |= aic_htole32(AHC_DMA_LAST_SEG); 353 354 bus_dmamap_sync(ahc->parent_dmat, scb->sg_map->sg_dmamap, 355 0, scb->sg_map->sg_dmamap->dm_mapsize, 356 BUS_DMASYNC_PREWRITE); 357 358 /* Copy the first SG into the "current" data pointer area */ 359 scb->hscb->dataptr = scb->sg_list->addr; 360 scb->hscb->datacnt = scb->sg_list->len; 361 } else { 362 scb->hscb->sgptr = aic_htole32(SG_LIST_NULL); 363 scb->hscb->dataptr = 0; 364 scb->hscb->datacnt = 0; 365 } 366 367 scb->sg_count = nsegments; 368 369 s = splbio(); 370 371 tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid), 372 SCSIID_OUR_ID(scb->hscb->scsiid), 373 SCSIID_TARGET(ahc, scb->hscb->scsiid), 374 &tstate); 375 376 mask = SCB_GET_TARGET_MASK(ahc, scb); 377 scb->hscb->scsirate = tinfo->scsirate; 378 scb->hscb->scsioffset = tinfo->curr.offset; 379 380 if ((tstate->ultraenb & mask) != 0) 381 scb->hscb->control |= ULTRAENB; 382 383 if ((tstate->discenable & mask) != 0) 384 scb->hscb->control |= DISCENB; 385 386 if ((tstate->auto_negotiate & mask) != 0) { 387 scb->flags |= SCB_AUTO_NEGOTIATE; 388 scb->hscb->control |= MK_MESSAGE; 389 } 390 391 if ((tstate->tagenable & mask) != 0) 392 scb->hscb->control |= TAG_ENB; 393 394 bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap, 395 0, ahc->scb_data->hscb_dmamap->dm_mapsize, 396 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 397 398 LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 399 400 if (!(xs->flags & SCSI_POLL)) 401 timeout_add_msec(&xs->stimeout, xs->timeout); 402 403 /* 404 * We only allow one untagged transaction 405 * per target in the initiator role unless 406 * we are storing a full busy target *lun* 407 * table in SCB space. 408 * 409 * This really should not be of any 410 * concern, as we take care to avoid this 411 * in ahc_done(). XXX smurph 412 */ 413 if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 414 && (ahc->flags & AHC_SCB_BTT) == 0) { 415 struct scb_tailq *untagged_q; 416 int target_offset; 417 418 target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 419 untagged_q = &(ahc->untagged_queues[target_offset]); 420 TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 421 scb->flags |= SCB_UNTAGGEDQ; 422 if (TAILQ_FIRST(untagged_q) != scb) { 423 if (xs->flags & SCSI_POLL) 424 goto poll; 425 else { 426 splx(s); 427 return; 428 } 429 } 430 } 431 scb->flags |= SCB_ACTIVE; 432 433 if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 434 /* Define a mapping from our tag to the SCB. */ 435 ahc->scb_data->scbindex[scb->hscb->tag] = scb; 436 ahc_pause(ahc); 437 if ((ahc->flags & AHC_PAGESCBS) == 0) 438 ahc_outb(ahc, SCBPTR, scb->hscb->tag); 439 ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag); 440 ahc_unpause(ahc); 441 } else { 442 ahc_queue_scb(ahc, scb); 443 } 444 445 if (!(xs->flags & SCSI_POLL)) { 446 if (ahc->inited_target[xs->sc_link->target] == 0) { 447 struct ahc_devinfo devinfo; 448 449 ahc_adapter_req_set_xfer_mode(ahc, scb); 450 ahc_scb_devinfo(ahc, &devinfo, scb); 451 ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, 452 AHC_NEG_IF_NON_ASYNC); 453 454 ahc->inited_target[xs->sc_link->target] = 1; 455 } 456 splx(s); 457 return; 458 } 459 460 /* 461 * If we can't use interrupts, poll for completion 462 */ 463 poll: 464 #ifdef AHC_DEBUG 465 printf("%s: cmd_poll\n", ahc_name(ahc)); 466 #endif 467 468 do { 469 if (ahc_poll(ahc, xs->timeout)) { 470 if (!(xs->flags & SCSI_SILENT)) 471 printf("cmd fail\n"); 472 ahc_timeout(scb); 473 break; 474 } 475 } while (!(xs->flags & ITSDONE)); 476 477 splx(s); 478 } 479 480 int 481 ahc_poll(struct ahc_softc *ahc, int wait) 482 { 483 while (--wait) { 484 DELAY(1000); 485 if (ahc_inb(ahc, INTSTAT) & INT_PEND) 486 break; 487 } 488 489 if (wait == 0) { 490 printf("%s: board is not responding\n", ahc_name(ahc)); 491 return (EIO); 492 } 493 494 ahc_intr((void *)ahc); 495 return (0); 496 } 497 498 void 499 ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs, 500 struct scb *scb) 501 { 502 struct hardware_scb *hscb; 503 504 hscb = scb->hscb; 505 xs->resid = xs->status = 0; 506 xs->error = CAM_REQ_INPROG; 507 508 hscb->cdb_len = xs->cmdlen; 509 if (hscb->cdb_len > sizeof(hscb->cdb32)) { 510 xs->error = XS_DRIVER_STUFFUP; 511 scsi_done(xs); 512 return; 513 } 514 515 if (hscb->cdb_len > 12) { 516 memcpy(hscb->cdb32, &xs->cmd, hscb->cdb_len); 517 scb->flags |= SCB_CDB32_PTR; 518 } else { 519 memcpy(hscb->shared_data.cdb, &xs->cmd, hscb->cdb_len); 520 } 521 522 /* Only use S/G if there is a transfer */ 523 if (xs->datalen) { 524 int error; 525 526 error = bus_dmamap_load(ahc->parent_dmat, 527 scb->dmamap, xs->data, 528 xs->datalen, NULL, 529 (xs->flags & SCSI_NOSLEEP) ? 530 BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 531 if (error) { 532 #ifdef AHC_DEBUG 533 printf("%s: in ahc_setup_data(): bus_dmamap_load() " 534 "= %d\n", 535 ahc_name(ahc), error); 536 #endif 537 xs->error = XS_DRIVER_STUFFUP; 538 scsi_done(xs); 539 return; 540 } 541 ahc_execute_scb(scb, scb->dmamap->dm_segs, 542 scb->dmamap->dm_nsegs); 543 } else { 544 ahc_execute_scb(scb, NULL, 0); 545 } 546 } 547 548 void 549 ahc_timeout(void *arg) 550 { 551 struct scb *scb, *list_scb; 552 struct ahc_softc *ahc; 553 int s; 554 int found; 555 char channel; 556 557 scb = arg; 558 ahc = scb->xs->sc_link->bus->sb_adapter_softc; 559 560 s = splbio(); 561 562 #ifdef AHC_DEBUG 563 printf("%s: SCB %d timed out\n", ahc_name(ahc), scb->hscb->tag); 564 ahc_dump_card_state(ahc); 565 #endif 566 567 ahc_pause(ahc); 568 569 if (scb->flags & SCB_ACTIVE) { 570 channel = SCB_GET_CHANNEL(ahc, scb); 571 ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 572 /* 573 * Go through all of our pending SCBs and remove 574 * any scheduled timeouts for them. They're about to be 575 * aborted so no need for them to timeout. 576 */ 577 LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 578 if (list_scb->xs) 579 timeout_del(&list_scb->xs->stimeout); 580 } 581 found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); 582 #ifdef AHC_DEBUG 583 printf("%s: Issued Channel %c Bus Reset %d SCBs aborted\n", 584 ahc_name(ahc), channel, found); 585 #endif 586 } 587 588 ahc_unpause(ahc); 589 splx(s); 590 } 591 592 593 void 594 ahc_platform_set_tags(struct ahc_softc *ahc, 595 struct ahc_devinfo *devinfo, int alg) 596 { 597 struct ahc_tmode_tstate *tstate; 598 599 ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 600 devinfo->target, &tstate); 601 602 /* XXXX Need to check quirks before doing this! XXXX */ 603 604 switch (alg) { 605 case AHC_QUEUE_BASIC: 606 case AHC_QUEUE_TAGGED: 607 tstate->tagenable |= devinfo->target_mask; 608 break; 609 case AHC_QUEUE_NONE: 610 tstate->tagenable &= ~devinfo->target_mask; 611 break; 612 } 613 } 614 615 int 616 ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 617 { 618 return (0); 619 } 620 621 void 622 ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun, 623 ac_code code, void *opt_arg) 624 { 625 /* Nothing to do here for OpenBSD */ 626 } 627 628 void 629 ahc_adapter_req_set_xfer_mode(struct ahc_softc *ahc, struct scb *scb) 630 { 631 struct ahc_initiator_tinfo *tinfo; 632 struct ahc_tmode_tstate *tstate; 633 struct ahc_syncrate *syncrate; 634 struct ahc_devinfo devinfo; 635 u_int16_t quirks; 636 u_int width, ppr_options, period, offset; 637 int s; 638 639 s = splbio(); 640 641 ahc_scb_devinfo(ahc, &devinfo, scb); 642 quirks = scb->xs->sc_link->quirks; 643 tinfo = ahc_fetch_transinfo(ahc, devinfo.channel, 644 devinfo.our_scsiid, devinfo.target, &tstate); 645 646 tstate->discenable |= (ahc->user_discenable & devinfo.target_mask); 647 648 if (quirks & SDEV_NOTAGS) 649 tstate->tagenable &= ~devinfo.target_mask; 650 else if (ahc->user_tagenable & devinfo.target_mask) 651 tstate->tagenable |= devinfo.target_mask; 652 653 if (quirks & SDEV_NOWIDE) 654 width = MSG_EXT_WDTR_BUS_8_BIT; 655 else 656 width = MSG_EXT_WDTR_BUS_16_BIT; 657 658 ahc_validate_width(ahc, NULL, &width, ROLE_UNKNOWN); 659 if (width > tinfo->user.width) 660 width = tinfo->user.width; 661 ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); 662 663 if (quirks & SDEV_NOSYNC) { 664 period = 0; 665 offset = 0; 666 } else { 667 period = tinfo->user.period; 668 offset = tinfo->user.offset; 669 } 670 671 /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */ 672 ppr_options = tinfo->user.ppr_options; 673 /* XXX Other reasons to avoid ppr? XXX */ 674 if (width < MSG_EXT_WDTR_BUS_16_BIT) 675 ppr_options = 0; 676 677 if ((tstate->discenable & devinfo.target_mask) == 0 || 678 (tstate->tagenable & devinfo.target_mask) == 0) 679 ppr_options &= ~MSG_EXT_PPR_PROT_IUS; 680 681 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, 682 AHC_SYNCRATE_MAX); 683 ahc_validate_offset(ahc, NULL, syncrate, &offset, width, 684 ROLE_UNKNOWN); 685 686 if (offset == 0) { 687 period = 0; 688 ppr_options = 0; 689 } 690 691 if (ppr_options != 0 && tinfo->user.transport_version >= 3) { 692 tinfo->goal.transport_version = tinfo->user.transport_version; 693 tinfo->curr.transport_version = tinfo->user.transport_version; 694 } 695 696 ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, ppr_options, 697 AHC_TRANS_GOAL, FALSE); 698 699 splx(s); 700 } 701 702 /* 703 * Get a free scb. If there are none, see if we can allocate a new SCB. 704 */ 705 void * 706 ahc_scb_alloc(void *xahc) 707 { 708 struct ahc_softc *ahc = xahc; 709 struct scb *scb; 710 711 mtx_enter(&ahc->sc_scb_mtx); 712 scb = SLIST_FIRST(&ahc->scb_data->free_scbs); 713 714 if (scb != NULL) 715 SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle); 716 717 mtx_leave(&ahc->sc_scb_mtx); 718 719 return (scb); 720 } 721 722 /* 723 * Return an SCB resource to the free list. 724 */ 725 void 726 ahc_scb_free(void *xahc, void *io) 727 { 728 struct ahc_softc *ahc = xahc; 729 struct scb *scb = io; 730 struct hardware_scb *hscb; 731 732 hscb = scb->hscb; 733 /* Clean up for the next user */ 734 ahc->scb_data->scbindex[hscb->tag] = NULL; 735 scb->flags = SCB_FLAG_NONE; 736 hscb->control = 0; 737 738 mtx_enter(&ahc->sc_scb_mtx); 739 SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); 740 mtx_leave(&ahc->sc_scb_mtx); 741 742 /* Notify the OSM that a resource is now available. */ 743 ahc_platform_scb_free(ahc, scb); 744 } 745