1 /* $OpenBSD: aic79xx_openbsd.c,v 1.46 2017/12/12 12:33:36 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_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) 555 { 556 /* We don't sort softcs under OpenBSD so report equal always */ 557 return (0); 558 } 559 560 int 561 ahd_detach(struct device *self, int flags) 562 { 563 int rv = 0; 564 565 struct ahd_softc *ahd = (struct ahd_softc*)self; 566 567 if (ahd->sc_child != NULL) 568 rv = config_detach((void *)ahd->sc_child, flags); 569 570 ahd_free(ahd); 571 572 return rv; 573 } 574 575 void 576 ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb) 577 { 578 struct ahd_initiator_tinfo *tinfo; 579 struct ahd_tmode_tstate *tstate; 580 int target_id, our_id; 581 struct ahd_devinfo devinfo; 582 u_int16_t quirks; 583 u_int width, ppr_options, period, offset; 584 int s; 585 586 target_id = scb->xs->sc_link->target; 587 our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link); 588 589 s = splbio(); 590 591 quirks = scb->xs->sc_link->quirks; 592 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate); 593 ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A', 594 ROLE_INITIATOR); 595 596 tstate->discenable |= (ahd->user_discenable & devinfo.target_mask); 597 598 if (quirks & SDEV_NOTAGS) 599 tstate->tagenable &= ~devinfo.target_mask; 600 else if (ahd->user_tagenable & devinfo.target_mask) 601 tstate->tagenable |= devinfo.target_mask; 602 603 if (quirks & SDEV_NOWIDE) 604 width = MSG_EXT_WDTR_BUS_8_BIT; 605 else 606 width = MSG_EXT_WDTR_BUS_16_BIT; 607 608 ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN); 609 if (width > tinfo->user.width) 610 width = tinfo->user.width; 611 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE); 612 613 if (quirks & SDEV_NOSYNC) { 614 period = 0; 615 offset = 0; 616 } else { 617 period = tinfo->user.period; 618 offset = tinfo->user.offset; 619 } 620 621 /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */ 622 ppr_options = tinfo->user.ppr_options; 623 /* XXX Other reasons to avoid ppr? XXX */ 624 if (width < MSG_EXT_WDTR_BUS_16_BIT) 625 ppr_options = 0; 626 627 if ((tstate->discenable & devinfo.target_mask) == 0 || 628 (tstate->tagenable & devinfo.target_mask) == 0) 629 ppr_options &= ~MSG_EXT_PPR_PROT_IUS; 630 631 ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX); 632 ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN); 633 634 if (offset == 0) { 635 period = 0; 636 ppr_options = 0; 637 } 638 639 if (ppr_options != 0 && tinfo->user.transport_version >= 3) { 640 tinfo->goal.transport_version = tinfo->user.transport_version; 641 tinfo->curr.transport_version = tinfo->user.transport_version; 642 } 643 644 ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options, 645 AHD_TRANS_GOAL, FALSE); 646 647 splx(s); 648 } 649 650 void 651 aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func, 652 void *arg) 653 { 654 uint64_t nticks; 655 656 nticks = msec; 657 nticks *= hz; 658 nticks /= 1000; 659 callout_reset(timer, nticks, func, arg); 660 } 661 662 void 663 aic_scb_timer_reset(struct scb *scb, u_int msec) 664 { 665 uint64_t nticks; 666 667 nticks = msec; 668 nticks *= hz; 669 nticks /= 1000; 670 if (!(scb->xs->xs_control & XS_CTL_POLL)) 671 callout_reset(&scb->xs->xs_callout, nticks, ahd_timeout, scb); 672 } 673 674 void 675 ahd_flush_device_writes(struct ahd_softc *ahd) 676 { 677 /* XXX Is this sufficient for all architectures??? */ 678 ahd_inb(ahd, INTSTAT); 679 } 680 681 void 682 aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) 683 { 684 int s; 685 686 ahd_lock(ahd, &s); 687 688 if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) { 689 ahd->flags &= ~AHD_RESOURCE_SHORTAGE; 690 } 691 692 if (!cold) { 693 /* we are no longer in autoconf */ 694 timeout_del(&scb->xs->stimeout); 695 } 696 697 ahd_unlock(ahd, &s); 698 } 699 700 void 701 ahd_print_path(struct ahd_softc *ahd, struct scb *scb) 702 { 703 sc_print_addr(scb->xs->sc_link); 704 } 705 706 void 707 ahd_platform_dump_card_state(struct ahd_softc *ahd) 708 { 709 /* Nothing to do here for OpenBSD */ 710 printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n", 711 ahd->features, ahd->flags, ahd->chip, ahd->bugs); 712 } 713 714