root/dev/ic/aic79xx_openbsd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ahd_attach
  2. ahd_platform_intr
  3. ahd_done
  4. ahd_minphys
  5. ahd_action
  6. ahd_execute_scb
  7. ahd_poll
  8. ahd_setup_data
  9. ahd_platform_set_tags
  10. ahd_platform_alloc
  11. ahd_platform_free
  12. ahd_softc_comp
  13. ahd_detach
  14. ahd_adapter_req_set_xfer_mode
  15. aic_timer_reset
  16. aic_scb_timer_reset
  17. ahd_flush_device_writes
  18. aic_platform_scb_free
  19. ahd_print_path
  20. ahd_platform_dump_card_state
  21. ahd_platform_flushwork

    1 /*      $OpenBSD: aic79xx_openbsd.c,v 1.26 2006/11/28 23:59:45 dlg 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 <sys/cdefs.h>
   64 /*
   65 __FBSDID("$FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.16 2003/12/17 00:02:09 gibbs Exp $");
   66 */
   67 
   68 #include <dev/ic/aic79xx_openbsd.h>
   69 #include <dev/ic/aic79xx_inline.h>
   70 #include <dev/ic/aic79xx.h>
   71 
   72 #ifndef AHD_TMODE_ENABLE
   73 #define AHD_TMODE_ENABLE 0
   74 #endif
   75 
   76 /* XXX milos add ahd_ioctl */
   77 int     ahd_action(struct scsi_xfer *);
   78 int     ahd_execute_scb(void *, bus_dma_segment_t *, int);
   79 int     ahd_poll(struct ahd_softc *, int);
   80 int     ahd_setup_data(struct ahd_softc *, struct scsi_xfer *, 
   81                     struct scb *);
   82 
   83 void    ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *);
   84 void    ahd_minphys(struct buf *);
   85 
   86 struct cfdriver ahd_cd = {
   87         NULL, "ahd", DV_DULL
   88 };
   89 
   90 static struct scsi_adapter ahd_switch =
   91 {
   92         ahd_action,
   93         ahd_minphys,
   94         0,
   95         0,
   96 };
   97 
   98 /* the below structure is so we have a default dev struct for our link struct */
   99 static struct scsi_device ahd_dev =
  100 {
  101         NULL, /* Use default error handler */
  102         NULL, /* have a queue, served by this */
  103         NULL, /* have no async handler */
  104         NULL, /* Use default 'done' routine */
  105 };
  106 
  107 /*
  108  * Attach all the sub-devices we can find
  109  */
  110 int
  111 ahd_attach(struct ahd_softc *ahd)
  112 {
  113         struct scsibus_attach_args saa;
  114         char   ahd_info[256];
  115         int     s;
  116 
  117         ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
  118         printf("%s\n", ahd_info);
  119         ahd_lock(ahd, &s);
  120 
  121         /*
  122          * fill in the prototype scsi_links.
  123          */
  124         ahd->sc_channel.adapter_target = ahd->our_id;
  125         if (ahd->features & AHD_WIDE)
  126                 ahd->sc_channel.adapter_buswidth = 16;
  127         ahd->sc_channel.adapter_softc = ahd;
  128         ahd->sc_channel.adapter = &ahd_switch;
  129         ahd->sc_channel.openings = 16;
  130         ahd->sc_channel.device = &ahd_dev;
  131 
  132         if (bootverbose) {
  133                 ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
  134                 printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
  135         }
  136 
  137         ahd_intr_enable(ahd, TRUE);
  138 
  139         if (ahd->flags & AHD_RESET_BUS_A)
  140                 ahd_reset_channel(ahd, 'A', TRUE);
  141 
  142         bzero(&saa, sizeof(saa));
  143         saa.saa_sc_link = &ahd->sc_channel;
  144 
  145         ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint);
  146 
  147         ahd_unlock(ahd, &s);
  148 
  149         return (1);
  150 
  151 }
  152 
  153 /*
  154  * Catch an interrupt from the adapter
  155  */
  156 int
  157 ahd_platform_intr(void *arg)
  158 {
  159         struct  ahd_softc *ahd;
  160 
  161         /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
  162 
  163         ahd = (struct ahd_softc *)arg; 
  164         return ahd_intr(ahd);
  165 }
  166 
  167 /*
  168  * We have an scb which has been processed by the
  169  * adaptor, now we look to see how the operation
  170  * went.
  171  */
  172 void
  173 ahd_done(struct ahd_softc *ahd, struct scb *scb)
  174 {
  175         struct scsi_xfer *xs = scb->xs;
  176         int s;
  177 
  178         /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
  179 
  180         LIST_REMOVE(scb, pending_links);
  181 
  182         timeout_del(&xs->stimeout);
  183 
  184         if (xs->datalen) {
  185                 int op;
  186 
  187                 if ((xs->flags & SCSI_DATA_IN) != 0)
  188                         op = BUS_DMASYNC_POSTREAD;
  189                 else
  190                         op = BUS_DMASYNC_POSTWRITE;
  191                 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
  192                     scb->dmamap->dm_mapsize, op);
  193                 bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
  194         }
  195 
  196         /* Translate the CAM status code to a SCSI error code. */
  197         switch (xs->error) {
  198         case CAM_SCSI_STATUS_ERROR:
  199         case CAM_REQ_INPROG:
  200         case CAM_REQ_CMP:
  201                 switch (xs->status) {
  202                 case SCSI_TASKSET_FULL:
  203                         /* SCSI Layer won't requeue, so we force infinite
  204                          * retries until queue space is available. XS_BUSY
  205                          * is dangerous because if the NOSLEEP flag is set
  206                          * it can cause the I/O to return EIO. XS_BUSY code
  207                          * falls through to XS_TIMEOUT anyway.
  208                          */ 
  209                         xs->error = XS_TIMEOUT;
  210                         xs->retries++;
  211                         break;
  212                 case SCSI_BUSY:
  213                         xs->error = XS_BUSY;
  214                         break;
  215                 case SCSI_CHECK:
  216                 case SCSI_TERMINATED:
  217                         if ((scb->flags & SCB_SENSE) == 0) {
  218                                 /* CHECK on CHECK? */
  219                                 xs->error = XS_DRIVER_STUFFUP;
  220                         } else
  221                                 xs->error = XS_NOERROR;
  222                         break;
  223                 default:
  224                         xs->error = XS_NOERROR;
  225                         break;
  226                 }
  227                 break;
  228         case CAM_BUSY:
  229                 xs->error = XS_BUSY;
  230                 break;
  231         case CAM_CMD_TIMEOUT:
  232                 xs->error = XS_TIMEOUT;
  233                 break;
  234         case CAM_BDR_SENT:
  235         case CAM_SCSI_BUS_RESET:
  236                 xs->error = XS_RESET;
  237                 break;
  238         case CAM_REQUEUE_REQ:
  239                 xs->error = XS_TIMEOUT;
  240                 xs->retries++;
  241                 break;
  242         case CAM_SEL_TIMEOUT:
  243                 xs->error = XS_SELTIMEOUT;
  244                 break;
  245         default:
  246                 xs->error = XS_DRIVER_STUFFUP;
  247                 break;
  248         }
  249 
  250         if (xs->error != XS_NOERROR) {
  251                 /* Don't clobber any existing error state */
  252         } else if ((scb->flags & SCB_SENSE) != 0) {
  253                 /*
  254                  * We performed autosense retrieval.
  255                  *
  256                  * Zero any sense not transferred by the
  257                  * device.  The SCSI spec mandates that any
  258                  * untransfered data should be assumed to be
  259                  * zero.  Complete the 'bounce' of sense information
  260                  * through buffers accessible via bus-space by
  261                  * copying it into the clients csio.
  262                  */
  263                 memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
  264                 memcpy(&xs->sense, ahd_get_sense_buf(ahd, scb),
  265                     sizeof(struct scsi_sense_data));
  266                 xs->error = XS_SENSE;
  267         } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
  268                 struct scsi_status_iu_header *siu;
  269                 u_int32_t len;
  270 
  271                 siu = (struct scsi_status_iu_header *)scb->sense_data;
  272                 len = SIU_SENSE_LENGTH(siu);
  273                 memset(&xs->sense, 0, sizeof(xs->sense));
  274                 memcpy(&xs->sense, SIU_SENSE_DATA(siu),
  275                     ulmin(len, sizeof(xs->sense)));
  276                 xs->error = XS_SENSE;
  277         }
  278 
  279         ahd_lock(ahd, &s);
  280         ahd_free_scb(ahd, scb);
  281         ahd_unlock(ahd, &s);
  282 
  283         xs->flags |= ITSDONE;
  284         scsi_done(xs);
  285 }
  286 
  287 void
  288 ahd_minphys(struct buf *bp)
  289 {
  290         /*
  291          * Even though the card can transfer up to 16megs per command
  292          * we are limited by the number of segments in the dma segment
  293          * list that we can hold.  The worst case is that all pages are
  294          * discontinuous physically, hence the "page per segment" limit
  295          * enforced here.
  296          */
  297         if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) {
  298                 bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE);
  299         }
  300         minphys(bp);
  301 }
  302 
  303 int32_t
  304 ahd_action(struct scsi_xfer *xs)
  305 {
  306         struct  ahd_softc *ahd;
  307         struct scb *scb;
  308         struct hardware_scb *hscb;
  309         u_int   target_id;
  310         u_int   our_id;
  311         int     s;
  312         int     dontqueue = 0;
  313         struct  ahd_initiator_tinfo *tinfo;
  314         struct  ahd_tmode_tstate *tstate;
  315         u_int   col_idx;
  316         u_int16_t quirks;
  317 
  318         SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
  319         ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
  320 
  321         /* determine safety of software queueing */
  322         dontqueue = xs->flags & SCSI_POLL;
  323 
  324         target_id = xs->sc_link->target;
  325         our_id = SCSI_SCSI_ID(ahd, xs->sc_link);
  326         
  327         if ((ahd->flags & AHD_INITIATORROLE) == 0) {
  328                 xs->error = XS_DRIVER_STUFFUP;
  329                 xs->flags |= ITSDONE;
  330                 scsi_done(xs);
  331                 return (COMPLETE);
  332                 /* return       ccb->ccb_h.status = CAM_PROVIDE_FAIL; */
  333         }
  334         /*
  335          * get an scb to use.
  336          */
  337         ahd_lock(ahd, &s);
  338         tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
  339 
  340         quirks = xs->sc_link->quirks;
  341 
  342         if ((quirks & SDEV_NOTAGS) != 0 || 
  343             (tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0)
  344                 col_idx = AHD_NEVER_COL_IDX;
  345         else
  346                 col_idx = AHD_BUILD_COL_IDX(target_id, xs->sc_link->lun);
  347 
  348         if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
  349                 ahd->flags |= AHD_RESOURCE_SHORTAGE;
  350                 ahd_unlock(ahd, &s);
  351                 return (TRY_AGAIN_LATER);
  352         }
  353         ahd_unlock(ahd, &s);
  354                 
  355         hscb = scb->hscb;
  356                 
  357         SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
  358 
  359         scb->xs = xs;
  360         timeout_set(&xs->stimeout, ahd_timeout, scb);
  361 
  362         /*
  363          * Put all the arguments for the xfer in the scb
  364          */
  365         hscb->control = 0;
  366         hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
  367         hscb->lun = xs->sc_link->lun;
  368         if (xs->xs_control & XS_CTL_RESET) {
  369                 hscb->cdb_len = 0;
  370                 scb->flags |= SCB_DEVICE_RESET;
  371                 hscb->control |= MK_MESSAGE;
  372                 hscb->task_management = SIU_TASKMGMT_LUN_RESET;
  373                 return (ahd_execute_scb(scb, NULL, 0));
  374         } else {
  375                 hscb->task_management = 0;
  376                 return (ahd_setup_data(ahd, xs, scb));
  377         }
  378 }
  379 
  380 int
  381 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
  382 {
  383         struct  scb *scb;
  384         struct  scsi_xfer *xs;
  385         struct  ahd_softc *ahd;
  386         struct  ahd_initiator_tinfo *tinfo;
  387         struct  ahd_tmode_tstate *tstate;
  388         u_int   mask;
  389         int     s;
  390 
  391         scb = (struct scb *)arg;
  392         xs = scb->xs;
  393         xs->error = CAM_REQ_INPROG;
  394         xs->status = 0;
  395         ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
  396 
  397         if (nsegments != 0) {
  398                 void *sg;
  399                 int op;
  400                 u_int i;
  401 
  402                 ahd_setup_data_scb(ahd, scb);
  403 
  404                 /* Copy the segments into our SG list */
  405                 for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
  406 
  407                         sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
  408                                           dm_segs->ds_len,
  409                                           /*last*/i == 1);
  410                         dm_segs++;
  411                 }
  412                 
  413                 if ((xs->flags & SCSI_DATA_IN) != 0)
  414                         op = BUS_DMASYNC_PREREAD;
  415                 else
  416                         op = BUS_DMASYNC_PREWRITE;
  417 
  418                 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
  419                                 scb->dmamap->dm_mapsize, op);
  420 
  421         }
  422 
  423         ahd_lock(ahd, &s);
  424 
  425         /*
  426          * Last time we need to check if this SCB needs to
  427          * be aborted.
  428          */
  429         if (xs->flags & ITSDONE) {
  430                 if (nsegments != 0)
  431                         bus_dmamap_unload(ahd->parent_dmat,
  432                                           scb->dmamap);
  433                 ahd_free_scb(ahd, scb);
  434                 ahd_unlock(ahd, &s);
  435                 return (COMPLETE);
  436         }
  437 
  438         tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
  439                                     SCSIID_OUR_ID(scb->hscb->scsiid),
  440                                     SCSIID_TARGET(ahd, scb->hscb->scsiid),
  441                                     &tstate);
  442 
  443         mask = SCB_GET_TARGET_MASK(ahd, scb);
  444 
  445         if ((tstate->discenable & mask) != 0)
  446                 scb->hscb->control |= DISCENB;
  447 
  448         if ((tstate->tagenable & mask) != 0)
  449                 scb->hscb->control |= TAG_ENB;
  450 
  451         if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
  452                 scb->flags |= SCB_PACKETIZED;
  453                 if (scb->hscb->task_management != 0)
  454                         scb->hscb->control &= ~MK_MESSAGE;
  455         }
  456 
  457         if ((tstate->auto_negotiate & mask) != 0) {
  458                 scb->flags |= SCB_AUTO_NEGOTIATE;
  459                 scb->hscb->control |= MK_MESSAGE;
  460         }
  461 
  462         /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */
  463 
  464         LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
  465 
  466         if (!(xs->flags & SCSI_POLL))
  467                 timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
  468 
  469         scb->flags |= SCB_ACTIVE;
  470 
  471         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
  472                 /* Define a mapping from our tag to the SCB. */
  473                 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
  474                 ahd_pause(ahd);
  475                 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
  476                 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
  477                 ahd_unpause(ahd);
  478         } else {
  479                 ahd_queue_scb(ahd, scb);
  480         }
  481 
  482         if (!(xs->flags & SCSI_POLL)) {
  483                 int target = xs->sc_link->target;
  484                 int lun = SCB_GET_LUN(scb);
  485 
  486                 if (ahd->inited_target[target] == 0) {
  487                         struct  ahd_devinfo devinfo;
  488 
  489                         ahd_adapter_req_set_xfer_mode(ahd, scb);
  490                         ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
  491                             'A', /*XXX milos*/ROLE_UNKNOWN);
  492                         ahd_scb_devinfo(ahd, &devinfo, scb);
  493                         ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
  494                                 AHD_NEG_IF_NON_ASYNC);
  495                         ahd->inited_target[target] = 1;
  496                 }
  497 
  498                 ahd_unlock(ahd, &s);
  499                 return (SUCCESSFULLY_QUEUED);
  500         }
  501 
  502         /*
  503          * If we can't use interrupts, poll for completion
  504          */
  505         SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
  506 
  507         do {
  508                 if (ahd_poll(ahd, xs->timeout)) {
  509                         if (!(xs->flags & SCSI_SILENT))
  510                                 printf("cmd fail\n");
  511                         ahd_timeout(scb);
  512                         break;
  513                 }
  514         } while (!(xs->flags & ITSDONE));
  515 
  516         ahd_unlock(ahd, &s);
  517         return (COMPLETE);
  518 }
  519 
  520 int
  521 ahd_poll(struct ahd_softc *ahd, int wait)
  522 {
  523         while (--wait) {
  524                 DELAY(1000);
  525                 if (ahd_inb(ahd, INTSTAT) & INT_PEND)
  526                         break;
  527         }
  528 
  529         if (wait == 0) {
  530                 printf("%s: board is not responding\n", ahd_name(ahd));
  531                 return (EIO);
  532         }
  533 
  534         ahd_intr((void *)ahd);
  535         return (0);
  536 }
  537 
  538 int
  539 ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs,
  540                struct scb *scb)
  541 {
  542         struct hardware_scb *hscb;
  543         int s;
  544 
  545         hscb = scb->hscb;
  546         xs->resid = xs->status = 0;
  547         xs->error = CAM_REQ_INPROG;
  548         
  549         hscb->cdb_len = xs->cmdlen;
  550         if (hscb->cdb_len > MAX_CDB_LEN) {
  551                 ahd_lock(ahd, &s);
  552                 ahd_free_scb(ahd, scb);
  553                 ahd_unlock(ahd, &s);
  554                 xs->error = XS_DRIVER_STUFFUP;
  555                 xs->flags |= ITSDONE;
  556                 scsi_done(xs);
  557                 return (COMPLETE);
  558         }
  559 
  560         memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
  561                 
  562         /* Only use S/G if there is a transfer */
  563         if (xs->datalen) {
  564                 int error;
  565 
  566                 error = bus_dmamap_load(ahd->parent_dmat,
  567                                         scb->dmamap, xs->data,
  568                                         xs->datalen, NULL,
  569                                         ((xs->flags & SCSI_NOSLEEP) ?
  570                                         BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
  571                                         BUS_DMA_STREAMING |
  572                                         ((xs->flags & XS_CTL_DATA_IN) ?
  573                                         BUS_DMA_READ : BUS_DMA_WRITE));
  574                 if (error) {
  575 #ifdef AHD_DEBUG
  576                         printf("%s: in ahd_setup_data(): bus_dmamap_load() "
  577                             "= %d\n", ahd_name(ahd), error);
  578 #endif
  579                         ahd_lock(ahd, &s);
  580                         ahd_free_scb(ahd, scb);
  581                         ahd_unlock(ahd, &s);
  582                         return (TRY_AGAIN_LATER);       /* XXX fvdl */
  583                 }
  584                 error = ahd_execute_scb(scb, scb->dmamap->dm_segs,
  585                     scb->dmamap->dm_nsegs);
  586                 return error;
  587         } else {
  588                 return ahd_execute_scb(scb, NULL, 0);
  589         }
  590 }
  591 
  592 void
  593 ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
  594     ahd_queue_alg alg)
  595 {
  596         struct ahd_tmode_tstate *tstate;
  597 
  598         ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
  599             devinfo->target, &tstate);
  600 
  601         if (alg != AHD_QUEUE_NONE) 
  602                 tstate->tagenable |= devinfo->target_mask;
  603         else
  604                 tstate->tagenable &= ~devinfo->target_mask;
  605 }
  606 
  607 int
  608 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
  609 {
  610         if (sizeof(struct ahd_platform_data) > 0) {
  611                 ahd->platform_data = malloc(sizeof(struct ahd_platform_data),
  612                     M_DEVBUF, M_NOWAIT);
  613                 if (ahd->platform_data == NULL)
  614                         return (ENOMEM);
  615                 bzero(ahd->platform_data, sizeof(struct ahd_platform_data));
  616         }       
  617 
  618         return (0);
  619 }
  620 
  621 void
  622 ahd_platform_free(struct ahd_softc *ahd)
  623 {
  624         if (sizeof(struct ahd_platform_data) > 0)
  625                 free(ahd->platform_data, M_DEVBUF);
  626 }
  627 
  628 int
  629 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
  630 {
  631         /* We don't sort softcs under OpenBSD so report equal always */
  632         return (0);
  633 }
  634 
  635 int
  636 ahd_detach(struct device *self, int flags)
  637 {
  638         int rv = 0;
  639 
  640         struct ahd_softc *ahd = (struct ahd_softc*)self;
  641 
  642         if (ahd->sc_child != NULL)
  643                 rv = config_detach((void *)ahd->sc_child, flags);
  644 
  645         if (ahd->shutdown_hook != NULL)
  646                 shutdownhook_disestablish(ahd->shutdown_hook);
  647 
  648         ahd_free(ahd);
  649 
  650         return rv;
  651 }
  652 
  653 void
  654 ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
  655 {
  656         struct ahd_initiator_tinfo *tinfo;
  657         struct ahd_tmode_tstate *tstate;
  658         int target_id, our_id;
  659         struct ahd_devinfo devinfo;
  660         u_int16_t quirks;
  661         u_int width, ppr_options, period, offset;
  662         int s;
  663 
  664         target_id = scb->xs->sc_link->target;
  665         our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);
  666 
  667         s = splbio();
  668 
  669         quirks = scb->xs->sc_link->quirks;
  670         tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
  671         ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
  672             ROLE_INITIATOR);
  673 
  674         tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);
  675 
  676         if (quirks & SDEV_NOTAGS)
  677                 tstate->tagenable &= ~devinfo.target_mask;
  678         else if (ahd->user_tagenable & devinfo.target_mask)
  679                 tstate->tagenable |= devinfo.target_mask;
  680 
  681         if (quirks & SDEV_NOWIDE)
  682                 width = MSG_EXT_WDTR_BUS_8_BIT;
  683         else
  684                 width = MSG_EXT_WDTR_BUS_16_BIT;
  685 
  686         ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
  687         if (width > tinfo->user.width)
  688                 width = tinfo->user.width;
  689         ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
  690 
  691         if (quirks & SDEV_NOSYNC) {
  692                 period = 0;
  693                 offset = 0;
  694         } else {
  695                 period = tinfo->user.period;
  696                 offset = tinfo->user.offset;
  697         }
  698 
  699         /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
  700         ppr_options = tinfo->user.ppr_options;
  701         /* XXX Other reasons to avoid ppr? XXX */
  702         if (width < MSG_EXT_WDTR_BUS_16_BIT)
  703                 ppr_options = 0;
  704 
  705         if ((tstate->discenable & devinfo.target_mask) == 0 ||
  706             (tstate->tagenable & devinfo.target_mask) == 0)
  707                 ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
  708 
  709         ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
  710         ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);
  711 
  712         if (offset == 0) {
  713                 period = 0;
  714                 ppr_options = 0;
  715         }
  716 
  717         if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
  718                 tinfo->goal.transport_version = tinfo->user.transport_version;
  719                 tinfo->curr.transport_version = tinfo->user.transport_version;
  720         }
  721 
  722         ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
  723                 AHD_TRANS_GOAL, FALSE);
  724 
  725         splx(s);
  726 }
  727 
  728 void
  729 aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func,
  730     void *arg)
  731 {
  732         uint64_t ticks;
  733 
  734         ticks = msec;
  735         ticks *= hz;
  736         ticks /= 1000;
  737         callout_reset(timer, ticks, func, arg);
  738 }
  739 
  740 void
  741 aic_scb_timer_reset(struct scb *scb, u_int msec)
  742 {
  743         uint64_t ticks;
  744 
  745         ticks = msec;
  746         ticks *= hz;
  747         ticks /= 1000;
  748         if (!(scb->xs->xs_control & XS_CTL_POLL))
  749                 callout_reset(&scb->xs->xs_callout, ticks, ahd_timeout, scb);
  750 }
  751 
  752 void
  753 ahd_flush_device_writes(struct ahd_softc *ahd)
  754 {
  755         /* XXX Is this sufficient for all architectures??? */
  756         ahd_inb(ahd, INTSTAT);
  757 }
  758 
  759 void
  760 aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
  761 {
  762         int s;
  763 
  764         ahd_lock(ahd, &s);
  765 
  766         if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) {
  767                 ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
  768         }
  769 
  770         if (!cold) {
  771                 /* we are no longer in autoconf */
  772                 timeout_del(&scb->xs->stimeout);
  773         }
  774 
  775         ahd_unlock(ahd, &s);
  776 }
  777 
  778 void
  779 ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
  780 {
  781         sc_print_addr(scb->xs->sc_link);
  782 }
  783 
  784 void
  785 ahd_platform_dump_card_state(struct ahd_softc *ahd)
  786 {
  787         /* Nothing to do here for OpenBSD */
  788         printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n",
  789                 ahd->features, ahd->flags, ahd->chip, ahd->bugs);
  790 }
  791 
  792 void
  793 ahd_platform_flushwork(struct ahd_softc *ahd)
  794 {
  795 }

/* [<][>][^][v][top][bottom][index][help] */