1 /* $OpenBSD: aic79xx_openbsd.c,v 1.45 2016/08/17 01:16:11 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 /* 31 * Bus independent OpenBSD shim for the aic79xx based Adaptec SCSI controllers 32 * 33 * Copyright (c) 1994-2002 Justin T. Gibbs. 34 * Copyright (c) 2001-2002 Adaptec Inc. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions, and the following disclaimer, 42 * without modification. 43 * 2. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * Alternatively, this software may be distributed under the terms of the 47 * GNU Public License ("GPL"). 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 53 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 */ 62 63 #include <dev/ic/aic79xx_openbsd.h> 64 #include <dev/ic/aic79xx_inline.h> 65 #include <dev/ic/aic79xx.h> 66 67 #ifndef AHD_TMODE_ENABLE 68 #define AHD_TMODE_ENABLE 0 69 #endif 70 71 /* XXX milos add ahd_ioctl */ 72 void ahd_action(struct scsi_xfer *); 73 void ahd_execute_scb(void *, bus_dma_segment_t *, int); 74 int ahd_poll(struct ahd_softc *, int); 75 void ahd_setup_data(struct ahd_softc *, struct scsi_xfer *, 76 struct scb *); 77 78 void ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *); 79 void ahd_minphys(struct buf *, struct scsi_link *); 80 81 struct cfdriver ahd_cd = { 82 NULL, "ahd", DV_DULL 83 }; 84 85 static struct scsi_adapter ahd_switch = 86 { 87 ahd_action, 88 ahd_minphys, 89 0, 90 0, 91 }; 92 93 /* 94 * Attach all the sub-devices we can find 95 */ 96 int 97 ahd_attach(struct ahd_softc *ahd) 98 { 99 struct scsibus_attach_args saa; 100 char ahd_info[256]; 101 int s; 102 103 ahd_controller_info(ahd, ahd_info, sizeof ahd_info); 104 printf("%s\n", ahd_info); 105 ahd_lock(ahd, &s); 106 107 /* 108 * fill in the prototype scsi_links. 109 */ 110 ahd->sc_channel.adapter_target = ahd->our_id; 111 if (ahd->features & AHD_WIDE) 112 ahd->sc_channel.adapter_buswidth = 16; 113 ahd->sc_channel.adapter_softc = ahd; 114 ahd->sc_channel.adapter = &ahd_switch; 115 ahd->sc_channel.openings = 16; /* Must ALWAYS be < 256!! */ 116 ahd->sc_channel.pool = &ahd->sc_iopool; 117 118 if (bootverbose) { 119 ahd_controller_info(ahd, ahd_info, sizeof ahd_info); 120 printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info); 121 } 122 123 ahd_intr_enable(ahd, TRUE); 124 125 if (ahd->flags & AHD_RESET_BUS_A) 126 ahd_reset_channel(ahd, 'A', TRUE); 127 128 bzero(&saa, sizeof(saa)); 129 saa.saa_sc_link = &ahd->sc_channel; 130 131 ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint); 132 133 ahd_unlock(ahd, &s); 134 135 return (1); 136 137 } 138 139 /* 140 * Catch an interrupt from the adapter 141 */ 142 int 143 ahd_platform_intr(void *arg) 144 { 145 struct ahd_softc *ahd; 146 147 /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */ 148 149 ahd = (struct ahd_softc *)arg; 150 return ahd_intr(ahd); 151 } 152 153 /* 154 * We have an scb which has been processed by the 155 * adaptor, now we look to see how the operation 156 * went. 157 */ 158 void 159 ahd_done(struct ahd_softc *ahd, struct scb *scb) 160 { 161 struct scsi_xfer *xs = scb->xs; 162 163 /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */ 164 165 TAILQ_REMOVE(&ahd->pending_scbs, scb, next); 166 167 timeout_del(&xs->stimeout); 168 169 if (xs->datalen) { 170 int op; 171 172 if ((xs->flags & SCSI_DATA_IN) != 0) 173 op = BUS_DMASYNC_POSTREAD; 174 else 175 op = BUS_DMASYNC_POSTWRITE; 176 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0, 177 scb->dmamap->dm_mapsize, op); 178 bus_dmamap_unload(ahd->parent_dmat, scb->dmamap); 179 } 180 181 /* Translate the CAM status code to a SCSI error code. */ 182 switch (xs->error) { 183 case CAM_SCSI_STATUS_ERROR: 184 case CAM_REQ_INPROG: 185 case CAM_REQ_CMP: 186 switch (xs->status) { 187 case SCSI_TASKSET_FULL: 188 case SCSI_BUSY: 189 xs->error = XS_BUSY; 190 break; 191 case SCSI_CHECK: 192 case SCSI_TERMINATED: 193 if ((scb->flags & SCB_SENSE) == 0) { 194 /* CHECK on CHECK? */ 195 xs->error = XS_DRIVER_STUFFUP; 196 } else 197 xs->error = XS_NOERROR; 198 break; 199 default: 200 xs->error = XS_NOERROR; 201 break; 202 } 203 break; 204 case CAM_BUSY: 205 case CAM_REQUEUE_REQ: 206 xs->error = XS_BUSY; 207 break; 208 case CAM_CMD_TIMEOUT: 209 xs->error = XS_TIMEOUT; 210 break; 211 case CAM_BDR_SENT: 212 case CAM_SCSI_BUS_RESET: 213 xs->error = XS_RESET; 214 break; 215 case CAM_SEL_TIMEOUT: 216 xs->error = XS_SELTIMEOUT; 217 break; 218 default: 219 xs->error = XS_DRIVER_STUFFUP; 220 break; 221 } 222 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, ahd_get_sense_buf(ahd, scb), 238 sizeof(struct scsi_sense_data)); 239 xs->error = XS_SENSE; 240 } else if ((scb->flags & SCB_PKT_SENSE) != 0) { 241 struct scsi_status_iu_header *siu; 242 u_int32_t len; 243 244 siu = (struct scsi_status_iu_header *)scb->sense_data; 245 len = SIU_SENSE_LENGTH(siu); 246 memset(&xs->sense, 0, sizeof(xs->sense)); 247 memcpy(&xs->sense, SIU_SENSE_DATA(siu), 248 ulmin(len, sizeof(xs->sense))); 249 xs->error = XS_SENSE; 250 } 251 252 scsi_done(xs); 253 } 254 255 void 256 ahd_minphys(struct buf *bp, struct scsi_link *sl) 257 { 258 /* 259 * Even though the card can transfer up to 16megs per command 260 * we are limited by the number of segments in the dma segment 261 * list that we can hold. The worst case is that all pages are 262 * discontinuous physically, hence the "page per segment" limit 263 * enforced here. 264 */ 265 if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) { 266 bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE); 267 } 268 minphys(bp); 269 } 270 271 void 272 ahd_action(struct scsi_xfer *xs) 273 { 274 struct ahd_softc *ahd; 275 struct scb *scb; 276 struct hardware_scb *hscb; 277 u_int target_id; 278 u_int our_id; 279 int s; 280 struct ahd_initiator_tinfo *tinfo; 281 struct ahd_tmode_tstate *tstate; 282 u_int16_t quirks; 283 284 SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n")); 285 ahd = (struct ahd_softc *)xs->sc_link->adapter_softc; 286 287 target_id = xs->sc_link->target; 288 our_id = SCSI_SCSI_ID(ahd, xs->sc_link); 289 290 ahd_lock(ahd, &s); 291 if ((ahd->flags & AHD_INITIATORROLE) == 0) { 292 xs->error = XS_DRIVER_STUFFUP; 293 scsi_done(xs); 294 ahd_unlock(ahd, &s); 295 return; 296 } 297 /* 298 * get an scb to use. 299 */ 300 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate); 301 302 quirks = xs->sc_link->quirks; 303 304 ahd_unlock(ahd, &s); 305 306 scb = xs->io; 307 hscb = scb->hscb; 308 scb->flags = SCB_FLAG_NONE; 309 scb->hscb->control = 0; 310 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL; 311 312 SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb)); 313 314 scb->xs = xs; 315 timeout_set(&xs->stimeout, ahd_timeout, scb); 316 317 /* 318 * Put all the arguments for the xfer in the scb 319 */ 320 hscb->control = 0; 321 hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id); 322 hscb->lun = xs->sc_link->lun; 323 if (xs->xs_control & XS_CTL_RESET) { 324 hscb->cdb_len = 0; 325 scb->flags |= SCB_DEVICE_RESET; 326 hscb->control |= MK_MESSAGE; 327 hscb->task_management = SIU_TASKMGMT_LUN_RESET; 328 ahd_execute_scb(scb, NULL, 0); 329 } else { 330 hscb->task_management = 0; 331 ahd_setup_data(ahd, xs, scb); 332 } 333 } 334 335 void 336 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments) 337 { 338 struct scb *scb; 339 struct scsi_xfer *xs; 340 struct ahd_softc *ahd; 341 struct ahd_initiator_tinfo *tinfo; 342 struct ahd_tmode_tstate *tstate; 343 u_int mask; 344 int s; 345 346 scb = (struct scb *)arg; 347 xs = scb->xs; 348 xs->error = CAM_REQ_INPROG; 349 xs->status = 0; 350 ahd = (struct ahd_softc *)xs->sc_link->adapter_softc; 351 352 if (nsegments != 0) { 353 void *sg; 354 int op; 355 u_int i; 356 357 ahd_setup_data_scb(ahd, scb); 358 359 /* Copy the segments into our SG list */ 360 for (i = nsegments, sg = scb->sg_list; i > 0; i--) { 361 362 sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr, 363 dm_segs->ds_len, 364 /*last*/i == 1); 365 dm_segs++; 366 } 367 368 if ((xs->flags & SCSI_DATA_IN) != 0) 369 op = BUS_DMASYNC_PREREAD; 370 else 371 op = BUS_DMASYNC_PREWRITE; 372 373 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0, 374 scb->dmamap->dm_mapsize, op); 375 376 } 377 378 ahd_lock(ahd, &s); 379 380 /* 381 * Last time we need to check if this SCB needs to 382 * be aborted. 383 */ 384 if (xs->flags & ITSDONE) { 385 if (nsegments != 0) 386 bus_dmamap_unload(ahd->parent_dmat, 387 scb->dmamap); 388 ahd_unlock(ahd, &s); 389 return; 390 } 391 392 tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid), 393 SCSIID_OUR_ID(scb->hscb->scsiid), 394 SCSIID_TARGET(ahd, scb->hscb->scsiid), 395 &tstate); 396 397 mask = SCB_GET_TARGET_MASK(ahd, scb); 398 399 if ((tstate->discenable & mask) != 0) 400 scb->hscb->control |= DISCENB; 401 402 if ((tstate->tagenable & mask) != 0) 403 scb->hscb->control |= TAG_ENB; 404 405 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) { 406 scb->flags |= SCB_PACKETIZED; 407 if (scb->hscb->task_management != 0) 408 scb->hscb->control &= ~MK_MESSAGE; 409 } 410 411 if ((tstate->auto_negotiate & mask) != 0) { 412 scb->flags |= SCB_AUTO_NEGOTIATE; 413 scb->hscb->control |= MK_MESSAGE; 414 } 415 416 /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */ 417 418 TAILQ_INSERT_HEAD(&ahd->pending_scbs, scb, next); 419 420 if (!(xs->flags & SCSI_POLL)) 421 timeout_add_msec(&xs->stimeout, xs->timeout); 422 423 scb->flags |= SCB_ACTIVE; 424 425 if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 426 /* Define a mapping from our tag to the SCB. */ 427 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; 428 ahd_pause(ahd); 429 ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); 430 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG); 431 ahd_unpause(ahd); 432 } else { 433 ahd_queue_scb(ahd, scb); 434 } 435 436 if (!(xs->flags & SCSI_POLL)) { 437 int target = xs->sc_link->target; 438 int lun = SCB_GET_LUN(scb); 439 440 if (ahd->inited_target[target] == 0) { 441 struct ahd_devinfo devinfo; 442 443 ahd_adapter_req_set_xfer_mode(ahd, scb); 444 ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun, 445 'A', /*XXX milos*/ROLE_UNKNOWN); 446 ahd_scb_devinfo(ahd, &devinfo, scb); 447 ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, 448 AHD_NEG_IF_NON_ASYNC); 449 ahd->inited_target[target] = 1; 450 } 451 452 ahd_unlock(ahd, &s); 453 return; 454 } 455 456 /* 457 * If we can't use interrupts, poll for completion 458 */ 459 SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n")); 460 461 do { 462 if (ahd_poll(ahd, xs->timeout)) { 463 if (!(xs->flags & SCSI_SILENT)) 464 printf("cmd fail\n"); 465 ahd_timeout(scb); 466 break; 467 } 468 } while (!(xs->flags & ITSDONE)); 469 470 ahd_unlock(ahd, &s); 471 } 472 473 int 474 ahd_poll(struct ahd_softc *ahd, int wait) 475 { 476 while (--wait) { 477 DELAY(1000); 478 if (ahd_inb(ahd, INTSTAT) & INT_PEND) 479 break; 480 } 481 482 if (wait == 0) { 483 printf("%s: board is not responding\n", ahd_name(ahd)); 484 return (EIO); 485 } 486 487 ahd_intr((void *)ahd); 488 return (0); 489 } 490 491 void 492 ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs, 493 struct scb *scb) 494 { 495 struct hardware_scb *hscb; 496 497 hscb = scb->hscb; 498 xs->resid = xs->status = 0; 499 xs->error = CAM_REQ_INPROG; 500 501 hscb->cdb_len = xs->cmdlen; 502 if (hscb->cdb_len > MAX_CDB_LEN) { 503 xs->error = XS_DRIVER_STUFFUP; 504 scsi_done(xs); 505 return; 506 } 507 508 memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len); 509 510 /* Only use S/G if there is a transfer */ 511 if (xs->datalen) { 512 int error; 513 514 error = bus_dmamap_load(ahd->parent_dmat, 515 scb->dmamap, xs->data, 516 xs->datalen, NULL, 517 ((xs->flags & SCSI_NOSLEEP) ? 518 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | 519 BUS_DMA_STREAMING | 520 ((xs->flags & XS_CTL_DATA_IN) ? 521 BUS_DMA_READ : BUS_DMA_WRITE)); 522 if (error) { 523 #ifdef AHD_DEBUG 524 printf("%s: in ahd_setup_data(): bus_dmamap_load() " 525 "= %d\n", ahd_name(ahd), error); 526 #endif 527 xs->error = XS_DRIVER_STUFFUP; 528 scsi_done(xs); 529 return; 530 } 531 ahd_execute_scb(scb, scb->dmamap->dm_segs, 532 scb->dmamap->dm_nsegs); 533 } else { 534 ahd_execute_scb(scb, NULL, 0); 535 } 536 } 537 538 void 539 ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, 540 ahd_queue_alg alg) 541 { 542 struct ahd_tmode_tstate *tstate; 543 544 ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, 545 devinfo->target, &tstate); 546 547 if (alg != AHD_QUEUE_NONE) 548 tstate->tagenable |= devinfo->target_mask; 549 else 550 tstate->tagenable &= ~devinfo->target_mask; 551 } 552 553 int 554 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) 555 { 556 if (sizeof(struct ahd_platform_data) > 0) { 557 ahd->platform_data = malloc(sizeof(struct ahd_platform_data), 558 M_DEVBUF, M_NOWAIT | M_ZERO); 559 if (ahd->platform_data == NULL) 560 return (ENOMEM); 561 } 562 563 return (0); 564 } 565 566 void 567 ahd_platform_free(struct ahd_softc *ahd) 568 { 569 if (sizeof(struct ahd_platform_data) > 0) 570 free(ahd->platform_data, M_DEVBUF, 0); 571 } 572 573 int 574 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) 575 { 576 /* We don't sort softcs under OpenBSD so report equal always */ 577 return (0); 578 } 579 580 int 581 ahd_detach(struct device *self, int flags) 582 { 583 int rv = 0; 584 585 struct ahd_softc *ahd = (struct ahd_softc*)self; 586 587 if (ahd->sc_child != NULL) 588 rv = config_detach((void *)ahd->sc_child, flags); 589 590 ahd_free(ahd); 591 592 return rv; 593 } 594 595 void 596 ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb) 597 { 598 struct ahd_initiator_tinfo *tinfo; 599 struct ahd_tmode_tstate *tstate; 600 int target_id, our_id; 601 struct ahd_devinfo devinfo; 602 u_int16_t quirks; 603 u_int width, ppr_options, period, offset; 604 int s; 605 606 target_id = scb->xs->sc_link->target; 607 our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link); 608 609 s = splbio(); 610 611 quirks = scb->xs->sc_link->quirks; 612 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate); 613 ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A', 614 ROLE_INITIATOR); 615 616 tstate->discenable |= (ahd->user_discenable & devinfo.target_mask); 617 618 if (quirks & SDEV_NOTAGS) 619 tstate->tagenable &= ~devinfo.target_mask; 620 else if (ahd->user_tagenable & devinfo.target_mask) 621 tstate->tagenable |= devinfo.target_mask; 622 623 if (quirks & SDEV_NOWIDE) 624 width = MSG_EXT_WDTR_BUS_8_BIT; 625 else 626 width = MSG_EXT_WDTR_BUS_16_BIT; 627 628 ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN); 629 if (width > tinfo->user.width) 630 width = tinfo->user.width; 631 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE); 632 633 if (quirks & SDEV_NOSYNC) { 634 period = 0; 635 offset = 0; 636 } else { 637 period = tinfo->user.period; 638 offset = tinfo->user.offset; 639 } 640 641 /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */ 642 ppr_options = tinfo->user.ppr_options; 643 /* XXX Other reasons to avoid ppr? XXX */ 644 if (width < MSG_EXT_WDTR_BUS_16_BIT) 645 ppr_options = 0; 646 647 if ((tstate->discenable & devinfo.target_mask) == 0 || 648 (tstate->tagenable & devinfo.target_mask) == 0) 649 ppr_options &= ~MSG_EXT_PPR_PROT_IUS; 650 651 ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX); 652 ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN); 653 654 if (offset == 0) { 655 period = 0; 656 ppr_options = 0; 657 } 658 659 if (ppr_options != 0 && tinfo->user.transport_version >= 3) { 660 tinfo->goal.transport_version = tinfo->user.transport_version; 661 tinfo->curr.transport_version = tinfo->user.transport_version; 662 } 663 664 ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, 665 AHD_TRANS_GOAL, FALSE); 666 667 splx(s); 668 } 669 670 void 671 aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func, 672 void *arg) 673 { 674 uint64_t nticks; 675 676 nticks = msec; 677 nticks *= hz; 678 nticks /= 1000; 679 callout_reset(timer, nticks, func, arg); 680 } 681 682 void 683 aic_scb_timer_reset(struct scb *scb, u_int msec) 684 { 685 uint64_t nticks; 686 687 nticks = msec; 688 nticks *= hz; 689 nticks /= 1000; 690 if (!(scb->xs->xs_control & XS_CTL_POLL)) 691 callout_reset(&scb->xs->xs_callout, nticks, ahd_timeout, scb); 692 } 693 694 void 695 ahd_flush_device_writes(struct ahd_softc *ahd) 696 { 697 /* XXX Is this sufficient for all architectures??? */ 698 ahd_inb(ahd, INTSTAT); 699 } 700 701 void 702 aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) 703 { 704 int s; 705 706 ahd_lock(ahd, &s); 707 708 if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) { 709 ahd->flags &= ~AHD_RESOURCE_SHORTAGE; 710 } 711 712 if (!cold) { 713 /* we are no longer in autoconf */ 714 timeout_del(&scb->xs->stimeout); 715 } 716 717 ahd_unlock(ahd, &s); 718 } 719 720 void 721 ahd_print_path(struct ahd_softc *ahd, struct scb *scb) 722 { 723 sc_print_addr(scb->xs->sc_link); 724 } 725 726 void 727 ahd_platform_dump_card_state(struct ahd_softc *ahd) 728 { 729 /* Nothing to do here for OpenBSD */ 730 printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n", 731 ahd->features, ahd->flags, ahd->chip, ahd->bugs); 732 } 733 734 void 735 ahd_platform_flushwork(struct ahd_softc *ahd) 736 { 737 } 738