The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/adv.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: adv.c,v 1.42 2008/04/08 12:07:25 cegger Exp $  */
    2 
    3 /*
    4  * Generic driver for the Advanced Systems Inc. Narrow SCSI controllers
    5  *
    6  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * Author: Baldassare Dante Profeta <dante@mclink.it>
   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  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: adv.c,v 1.42 2008/04/08 12:07:25 cegger Exp $");
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/callout.h>
   46 #include <sys/kernel.h>
   47 #include <sys/errno.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/device.h>
   50 #include <sys/malloc.h>
   51 #include <sys/buf.h>
   52 #include <sys/proc.h>
   53 #include <sys/user.h>
   54 
   55 #include <sys/bus.h>
   56 #include <sys/intr.h>
   57 
   58 #include <uvm/uvm_extern.h>
   59 
   60 #include <dev/scsipi/scsi_all.h>
   61 #include <dev/scsipi/scsipi_all.h>
   62 #include <dev/scsipi/scsiconf.h>
   63 
   64 #include <dev/ic/advlib.h>
   65 #include <dev/ic/adv.h>
   66 
   67 #ifndef DDB
   68 #define Debugger()      panic("should call debugger here (adv.c)")
   69 #endif /* ! DDB */
   70 
   71 
   72 /* #define ASC_DEBUG */
   73 
   74 /******************************************************************************/
   75 
   76 
   77 static int adv_alloc_control_data(ASC_SOFTC *);
   78 static void adv_free_control_data(ASC_SOFTC *);
   79 static int adv_create_ccbs(ASC_SOFTC *, ADV_CCB *, int);
   80 static void adv_free_ccb(ASC_SOFTC *, ADV_CCB *);
   81 static void adv_reset_ccb(ADV_CCB *);
   82 static int adv_init_ccb(ASC_SOFTC *, ADV_CCB *);
   83 static ADV_CCB *adv_get_ccb(ASC_SOFTC *);
   84 static void adv_queue_ccb(ASC_SOFTC *, ADV_CCB *);
   85 static void adv_start_ccbs(ASC_SOFTC *);
   86 
   87 
   88 static void adv_scsipi_request(struct scsipi_channel *,
   89         scsipi_adapter_req_t, void *);
   90 static void advminphys(struct buf *);
   91 static void adv_narrow_isr_callback(ASC_SOFTC *, ASC_QDONE_INFO *);
   92 
   93 static int adv_poll(ASC_SOFTC *, struct scsipi_xfer *, int);
   94 static void adv_timeout(void *);
   95 static void adv_watchdog(void *);
   96 
   97 
   98 /******************************************************************************/
   99 
  100 #define ADV_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
  101 #define ADV_WATCH_TIMEOUT       1000    /* time to wait for watchdog (mSec) */
  102 
  103 /******************************************************************************/
  104 /*                             Control Blocks routines                        */
  105 /******************************************************************************/
  106 
  107 
  108 static int
  109 adv_alloc_control_data(sc)
  110         ASC_SOFTC      *sc;
  111 {
  112         int error;
  113 
  114         /*
  115         * Allocate the control blocks.
  116          */
  117         if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct adv_control),
  118                            PAGE_SIZE, 0, &sc->sc_control_seg, 1,
  119                            &sc->sc_control_nsegs, BUS_DMA_NOWAIT)) != 0) {
  120                 aprint_error_dev(&sc->sc_dev, "unable to allocate control structures,"
  121                        " error = %d\n", error);
  122                 return (error);
  123         }
  124         if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_control_seg,
  125                            sc->sc_control_nsegs, sizeof(struct adv_control),
  126                            (void **) & sc->sc_control,
  127                            BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
  128                 aprint_error_dev(&sc->sc_dev, "unable to map control structures, error = %d\n",
  129                        error);
  130                 return (error);
  131         }
  132         /*
  133          * Create and load the DMA map used for the control blocks.
  134          */
  135         if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct adv_control),
  136                            1, sizeof(struct adv_control), 0, BUS_DMA_NOWAIT,
  137                                        &sc->sc_dmamap_control)) != 0) {
  138                 aprint_error_dev(&sc->sc_dev, "unable to create control DMA map, error = %d\n",
  139                        error);
  140                 return (error);
  141         }
  142         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,
  143                            sc->sc_control, sizeof(struct adv_control), NULL,
  144                                      BUS_DMA_NOWAIT)) != 0) {
  145                 aprint_error_dev(&sc->sc_dev, "unable to load control DMA map, error = %d\n",
  146                        error);
  147                 return (error);
  148         }
  149 
  150         /*
  151          * Initialize the overrun_buf address.
  152          */
  153         sc->overrun_buf = sc->sc_dmamap_control->dm_segs[0].ds_addr +
  154             offsetof(struct adv_control, overrun_buf);
  155 
  156         return (0);
  157 }
  158 
  159 static void
  160 adv_free_control_data(sc)
  161         ASC_SOFTC *sc;
  162 {
  163 
  164         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap_control);
  165         bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap_control);
  166         sc->sc_dmamap_control = NULL;
  167 
  168         bus_dmamem_unmap(sc->sc_dmat, (void *) sc->sc_control,
  169             sizeof(struct adv_control));
  170         bus_dmamem_free(sc->sc_dmat, &sc->sc_control_seg,
  171             sc->sc_control_nsegs);
  172 }
  173 
  174 /*
  175  * Create a set of ccbs and add them to the free list.  Called once
  176  * by adv_init().  We return the number of CCBs successfully created.
  177  */
  178 static int
  179 adv_create_ccbs(sc, ccbstore, count)
  180         ASC_SOFTC      *sc;
  181         ADV_CCB        *ccbstore;
  182         int             count;
  183 {
  184         ADV_CCB        *ccb;
  185         int             i, error;
  186 
  187         memset(ccbstore, 0, sizeof(ADV_CCB) * count);
  188         for (i = 0; i < count; i++) {
  189                 ccb = &ccbstore[i];
  190                 if ((error = adv_init_ccb(sc, ccb)) != 0) {
  191                         aprint_error_dev(&sc->sc_dev, "unable to initialize ccb, error = %d\n",
  192                                error);
  193                         return (i);
  194                 }
  195                 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
  196         }
  197 
  198         return (i);
  199 }
  200 
  201 
  202 /*
  203  * A ccb is put onto the free list.
  204  */
  205 static void
  206 adv_free_ccb(sc, ccb)
  207         ASC_SOFTC      *sc;
  208         ADV_CCB        *ccb;
  209 {
  210         int             s;
  211 
  212         s = splbio();
  213         adv_reset_ccb(ccb);
  214         TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
  215         splx(s);
  216 }
  217 
  218 
  219 static void
  220 adv_reset_ccb(ccb)
  221         ADV_CCB        *ccb;
  222 {
  223 
  224         ccb->flags = 0;
  225 }
  226 
  227 
  228 static int
  229 adv_init_ccb(sc, ccb)
  230         ASC_SOFTC      *sc;
  231         ADV_CCB        *ccb;
  232 {
  233         int     hashnum, error;
  234 
  235         callout_init(&ccb->ccb_watchdog, 0);
  236 
  237         /*
  238          * Create the DMA map for this CCB.
  239          */
  240         error = bus_dmamap_create(sc->sc_dmat,
  241                                   (ASC_MAX_SG_LIST - 1) * PAGE_SIZE,
  242                          ASC_MAX_SG_LIST, (ASC_MAX_SG_LIST - 1) * PAGE_SIZE,
  243                    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer);
  244         if (error) {
  245                 aprint_error_dev(&sc->sc_dev, "unable to create DMA map, error = %d\n",
  246                        error);
  247                 return (error);
  248         }
  249 
  250         /*
  251          * put in the phystokv hash table
  252          * Never gets taken out.
  253          */
  254         ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
  255             ADV_CCB_OFF(ccb);
  256         hashnum = CCB_HASH(ccb->hashkey);
  257         ccb->nexthash = sc->sc_ccbhash[hashnum];
  258         sc->sc_ccbhash[hashnum] = ccb;
  259 
  260         adv_reset_ccb(ccb);
  261         return (0);
  262 }
  263 
  264 
  265 /*
  266  * Get a free ccb
  267  *
  268  * If there are none, see if we can allocate a new one
  269  */
  270 static ADV_CCB *
  271 adv_get_ccb(sc)
  272         ASC_SOFTC      *sc;
  273 {
  274         ADV_CCB        *ccb = 0;
  275         int             s;
  276 
  277         s = splbio();
  278         ccb = TAILQ_FIRST(&sc->sc_free_ccb);
  279         if (ccb != NULL) {
  280                 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
  281                 ccb->flags |= CCB_ALLOC;
  282         }
  283         splx(s);
  284         return (ccb);
  285 }
  286 
  287 
  288 /*
  289  * Given a physical address, find the ccb that it corresponds to.
  290  */
  291 ADV_CCB *
  292 adv_ccb_phys_kv(sc, ccb_phys)
  293         ASC_SOFTC       *sc;
  294         u_long          ccb_phys;
  295 {
  296         int hashnum = CCB_HASH(ccb_phys);
  297         ADV_CCB *ccb = sc->sc_ccbhash[hashnum];
  298 
  299         while (ccb) {
  300                 if (ccb->hashkey == ccb_phys)
  301                         break;
  302                 ccb = ccb->nexthash;
  303         }
  304         return (ccb);
  305 }
  306 
  307 
  308 /*
  309  * Queue a CCB to be sent to the controller, and send it if possible.
  310  */
  311 static void
  312 adv_queue_ccb(sc, ccb)
  313         ASC_SOFTC      *sc;
  314         ADV_CCB        *ccb;
  315 {
  316 
  317         TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
  318 
  319         adv_start_ccbs(sc);
  320 }
  321 
  322 
  323 static void
  324 adv_start_ccbs(sc)
  325         ASC_SOFTC      *sc;
  326 {
  327         ADV_CCB        *ccb;
  328 
  329         while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
  330                 if (ccb->flags & CCB_WATCHDOG)
  331                         callout_stop(&ccb->ccb_watchdog);
  332 
  333                 if (AscExeScsiQueue(sc, &ccb->scsiq) == ASC_BUSY) {
  334                         ccb->flags |= CCB_WATCHDOG;
  335                         callout_reset(&ccb->ccb_watchdog,
  336                             (ADV_WATCH_TIMEOUT * hz) / 1000,
  337                             adv_watchdog, ccb);
  338                         break;
  339                 }
  340                 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
  341 
  342                 if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
  343                         callout_reset(&ccb->xs->xs_callout,
  344                             mstohz(ccb->timeout), adv_timeout, ccb);
  345         }
  346 }
  347 
  348 
  349 /******************************************************************************/
  350 /*                         SCSI layer interfacing routines                    */
  351 /******************************************************************************/
  352 
  353 
  354 int
  355 adv_init(sc)
  356         ASC_SOFTC      *sc;
  357 {
  358         int             warn;
  359 
  360         if (!AscFindSignature(sc->sc_iot, sc->sc_ioh)) {
  361                 aprint_error("adv_init: failed to find signature\n");
  362                 return (1);
  363         }
  364 
  365         /*
  366          * Read the board configuration
  367          */
  368         AscInitASC_SOFTC(sc);
  369         warn = AscInitFromEEP(sc);
  370         if (warn) {
  371                 aprint_error_dev(&sc->sc_dev, "-get: ");
  372                 switch (warn) {
  373                 case -1:
  374                         aprint_normal("Chip is not halted\n");
  375                         break;
  376 
  377                 case -2:
  378                         aprint_normal("Couldn't get MicroCode Start"
  379                                " address\n");
  380                         break;
  381 
  382                 case ASC_WARN_IO_PORT_ROTATE:
  383                         aprint_normal("I/O port address modified\n");
  384                         break;
  385 
  386                 case ASC_WARN_AUTO_CONFIG:
  387                         aprint_normal("I/O port increment switch enabled\n");
  388                         break;
  389 
  390                 case ASC_WARN_EEPROM_CHKSUM:
  391                         aprint_normal("EEPROM checksum error\n");
  392                         break;
  393 
  394                 case ASC_WARN_IRQ_MODIFIED:
  395                         aprint_normal("IRQ modified\n");
  396                         break;
  397 
  398                 case ASC_WARN_CMD_QNG_CONFLICT:
  399                         aprint_normal("tag queuing enabled w/o disconnects\n");
  400                         break;
  401 
  402                 default:
  403                         aprint_normal("unknown warning %d\n", warn);
  404                 }
  405         }
  406         if (sc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
  407                 sc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
  408 
  409         /*
  410          * Modify the board configuration
  411          */
  412         warn = AscInitFromASC_SOFTC(sc);
  413         if (warn) {
  414                 aprint_error_dev(&sc->sc_dev, "-set: ");
  415                 switch (warn) {
  416                 case ASC_WARN_CMD_QNG_CONFLICT:
  417                         aprint_normal("tag queuing enabled w/o disconnects\n");
  418                         break;
  419 
  420                 case ASC_WARN_AUTO_CONFIG:
  421                         aprint_normal("I/O port increment switch enabled\n");
  422                         break;
  423 
  424                 default:
  425                         aprint_normal("unknown warning %d\n", warn);
  426                 }
  427         }
  428         sc->isr_callback = (ASC_CALLBACK) adv_narrow_isr_callback;
  429 
  430         return (0);
  431 }
  432 
  433 
  434 void
  435 adv_attach(sc)
  436         ASC_SOFTC      *sc;
  437 {
  438         struct scsipi_adapter *adapt = &sc->sc_adapter;
  439         struct scsipi_channel *chan = &sc->sc_channel;
  440         int             i, error;
  441 
  442         /*
  443          * Initialize board RISC chip and enable interrupts.
  444          */
  445         switch (AscInitDriver(sc)) {
  446         case 0:
  447                 /* AllOK */
  448                 break;
  449 
  450         case 1:
  451                 panic("%s: bad signature", device_xname(&sc->sc_dev));
  452                 break;
  453 
  454         case 2:
  455                 panic("%s: unable to load MicroCode",
  456                       device_xname(&sc->sc_dev));
  457                 break;
  458 
  459         case 3:
  460                 panic("%s: unable to initialize MicroCode",
  461                       device_xname(&sc->sc_dev));
  462                 break;
  463 
  464         default:
  465                 panic("%s: unable to initialize board RISC chip",
  466                       device_xname(&sc->sc_dev));
  467         }
  468 
  469         /*
  470          * Fill in the scsipi_adapter.
  471          */
  472         memset(adapt, 0, sizeof(*adapt));
  473         adapt->adapt_dev = &sc->sc_dev;
  474         adapt->adapt_nchannels = 1;
  475         /* adapt_openings initialized below */
  476         /* adapt_max_periph initialized below */
  477         adapt->adapt_request = adv_scsipi_request;
  478         adapt->adapt_minphys = advminphys;
  479 
  480         /*
  481          * Fill in the scsipi_channel.
  482          */
  483         memset(chan, 0, sizeof(*chan));
  484         chan->chan_adapter = adapt;
  485         chan->chan_bustype = &scsi_bustype;
  486         chan->chan_channel = 0;
  487         chan->chan_ntargets = 8;
  488         chan->chan_nluns = 8;
  489         chan->chan_id = sc->chip_scsi_id;
  490 
  491         TAILQ_INIT(&sc->sc_free_ccb);
  492         TAILQ_INIT(&sc->sc_waiting_ccb);
  493 
  494         /*
  495          * Allocate the Control Blocks and the overrun buffer.
  496          */
  497         error = adv_alloc_control_data(sc);
  498         if (error)
  499                 return; /* (error) */
  500 
  501         /*
  502          * Create and initialize the Control Blocks.
  503          */
  504         i = adv_create_ccbs(sc, sc->sc_control->ccbs, ADV_MAX_CCB);
  505         if (i == 0) {
  506                 aprint_error_dev(&sc->sc_dev, "unable to create control blocks\n");
  507                 return; /* (ENOMEM) */ ;
  508         } else if (i != ADV_MAX_CCB) {
  509                 aprint_error_dev(&sc->sc_dev, 
  510                     "WARNING: only %d of %d control blocks created\n",
  511                     i, ADV_MAX_CCB);
  512         }
  513 
  514         adapt->adapt_openings = i;
  515         adapt->adapt_max_periph = adapt->adapt_openings;
  516 
  517         sc->sc_child = config_found(&sc->sc_dev, chan, scsiprint);
  518 }
  519 
  520 int
  521 adv_detach(sc, flags)
  522         ASC_SOFTC *sc;
  523         int flags;
  524 {
  525         int rv = 0;
  526 
  527         if (sc->sc_child != NULL)
  528                 rv = config_detach(sc->sc_child, flags);
  529 
  530         adv_free_control_data(sc);
  531 
  532         return (rv);
  533 }
  534 
  535 static void
  536 advminphys(bp)
  537         struct buf     *bp;
  538 {
  539 
  540         if (bp->b_bcount > ((ASC_MAX_SG_LIST - 1) * PAGE_SIZE))
  541                 bp->b_bcount = ((ASC_MAX_SG_LIST - 1) * PAGE_SIZE);
  542         minphys(bp);
  543 }
  544 
  545 
  546 /*
  547  * start a scsi operation given the command and the data address.  Also needs
  548  * the unit, target and lu.
  549  */
  550 
  551 static void
  552 adv_scsipi_request(chan, req, arg)
  553         struct scsipi_channel *chan;
  554         scsipi_adapter_req_t req;
  555         void *arg;
  556 {
  557         struct scsipi_xfer *xs;
  558         struct scsipi_periph *periph;
  559         ASC_SOFTC      *sc = (void *)chan->chan_adapter->adapt_dev;
  560         bus_dma_tag_t   dmat = sc->sc_dmat;
  561         ADV_CCB        *ccb;
  562         int             s, flags, error, nsegs;
  563 
  564         switch (req) {
  565         case ADAPTER_REQ_RUN_XFER:
  566                 xs = arg;
  567                 periph = xs->xs_periph;
  568                 flags = xs->xs_control;
  569 
  570                 /*
  571                  * Get a CCB to use.
  572                  */
  573                 ccb = adv_get_ccb(sc);
  574 #ifdef DIAGNOSTIC
  575                 /*
  576                  * This should never happen as we track the resources
  577                  * in the mid-layer.
  578                  */
  579                 if (ccb == NULL) {
  580                         scsipi_printaddr(periph);
  581                         printf("unable to allocate ccb\n");
  582                         panic("adv_scsipi_request");
  583                 }
  584 #endif
  585 
  586                 ccb->xs = xs;
  587                 ccb->timeout = xs->timeout;
  588 
  589                 /*
  590                  * Build up the request
  591                  */
  592                 memset(&ccb->scsiq, 0, sizeof(ASC_SCSI_Q));
  593 
  594                 ccb->scsiq.q2.ccb_ptr =
  595                     sc->sc_dmamap_control->dm_segs[0].ds_addr +
  596                     ADV_CCB_OFF(ccb);
  597 
  598                 ccb->scsiq.cdbptr = &xs->cmd->opcode;
  599                 ccb->scsiq.q2.cdb_len = xs->cmdlen;
  600                 ccb->scsiq.q1.target_id =
  601                     ASC_TID_TO_TARGET_ID(periph->periph_target);
  602                 ccb->scsiq.q1.target_lun = periph->periph_lun;
  603                 ccb->scsiq.q2.target_ix =
  604                     ASC_TIDLUN_TO_IX(periph->periph_target,
  605                     periph->periph_lun);
  606                 ccb->scsiq.q1.sense_addr =
  607                     sc->sc_dmamap_control->dm_segs[0].ds_addr +
  608                     ADV_CCB_OFF(ccb) + offsetof(struct adv_ccb, scsi_sense);
  609                 ccb->scsiq.q1.sense_len = sizeof(struct scsi_sense_data);
  610 
  611                 /*
  612                  * If there are any outstanding requests for the current
  613                  * target, then every 255th request send an ORDERED request.
  614                  * This heuristic tries to retain the benefit of request
  615                  * sorting while preventing request starvation. 255 is the
  616                  * max number of tags or pending commands a device may have
  617                  * outstanding.
  618                  */
  619                 sc->reqcnt[periph->periph_target]++;
  620                 if (((sc->reqcnt[periph->periph_target] > 0) &&
  621                     (sc->reqcnt[periph->periph_target] % 255) == 0) ||
  622                     xs->bp == NULL || (xs->bp->b_flags & B_ASYNC) == 0) {
  623                         ccb->scsiq.q2.tag_code = M2_QTAG_MSG_ORDERED;
  624                 } else {
  625                         ccb->scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
  626                 }
  627 
  628                 if (xs->datalen) {
  629                         /*
  630                          * Map the DMA transfer.
  631                          */
  632 #ifdef TFS
  633                         if (flags & SCSI_DATA_UIO) {
  634                                 error = bus_dmamap_load_uio(dmat,
  635                                     ccb->dmamap_xfer, (struct uio *) xs->data,
  636                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
  637                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
  638                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
  639                                       BUS_DMA_WRITE));
  640                         } else
  641 #endif /* TFS */
  642                         {
  643                                 error = bus_dmamap_load(dmat, ccb->dmamap_xfer,
  644                                     xs->data, xs->datalen, NULL,
  645                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
  646                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
  647                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
  648                                       BUS_DMA_WRITE));
  649                         }
  650 
  651                         switch (error) {
  652                         case 0:
  653                                 break;
  654 
  655 
  656                         case ENOMEM:
  657                         case EAGAIN:
  658                                 xs->error = XS_RESOURCE_SHORTAGE;
  659                                 goto out_bad;
  660 
  661                         default:
  662                                 xs->error = XS_DRIVER_STUFFUP;
  663                                 if (error == EFBIG) {
  664                                         aprint_error_dev(&sc->sc_dev, "adv_scsi_cmd, more than %d"
  665                                             " DMA segments\n",
  666                                             ASC_MAX_SG_LIST);
  667                                 } else {
  668                                         aprint_error_dev(&sc->sc_dev, "adv_scsi_cmd, error %d"
  669                                             " loading DMA map\n",
  670                                             error);
  671                                 }
  672 
  673 out_bad:
  674                                 adv_free_ccb(sc, ccb);
  675                                 scsipi_done(xs);
  676                                 return;
  677                         }
  678                         bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
  679                             ccb->dmamap_xfer->dm_mapsize,
  680                             (flags & XS_CTL_DATA_IN) ?
  681                              BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  682 
  683                         memset(&ccb->sghead, 0, sizeof(ASC_SG_HEAD));
  684 
  685                         for (nsegs = 0;
  686                              nsegs < ccb->dmamap_xfer->dm_nsegs; nsegs++) {
  687                                 ccb->sghead.sg_list[nsegs].addr =
  688                                     ccb->dmamap_xfer->dm_segs[nsegs].ds_addr;
  689                                 ccb->sghead.sg_list[nsegs].bytes =
  690                                     ccb->dmamap_xfer->dm_segs[nsegs].ds_len;
  691                         }
  692 
  693                         ccb->sghead.entry_cnt = ccb->scsiq.q1.sg_queue_cnt =
  694                             ccb->dmamap_xfer->dm_nsegs;
  695 
  696                         ccb->scsiq.q1.cntl |= ASC_QC_SG_HEAD;
  697                         ccb->scsiq.sg_head = &ccb->sghead;
  698                         ccb->scsiq.q1.data_addr = 0;
  699                         ccb->scsiq.q1.data_cnt = 0;
  700                 } else {
  701                         /*
  702                          * No data xfer, use non S/G values.
  703                          */
  704                         ccb->scsiq.q1.data_addr = 0;
  705                         ccb->scsiq.q1.data_cnt = 0;
  706                 }
  707 
  708 #ifdef ASC_DEBUG
  709                 printf("id = %d, lun = %d, cmd = %d, ccb = 0x%lX\n",
  710                     periph->periph_target,
  711                     periph->periph_lun, xs->cmd->opcode,
  712                     (unsigned long)ccb);
  713 #endif
  714                 s = splbio();
  715                 adv_queue_ccb(sc, ccb);
  716                 splx(s);
  717 
  718                 if ((flags & XS_CTL_POLL) == 0)
  719                         return;
  720 
  721                 /* Not allowed to use interrupts, poll for completion. */
  722                 if (adv_poll(sc, xs, ccb->timeout)) {
  723                         adv_timeout(ccb);
  724                         if (adv_poll(sc, xs, ccb->timeout))
  725                                 adv_timeout(ccb);
  726                 }
  727                 return;
  728 
  729         case ADAPTER_REQ_GROW_RESOURCES:
  730                 /* XXX Not supported. */
  731                 return;
  732 
  733         case ADAPTER_REQ_SET_XFER_MODE:
  734             {
  735                 /*
  736                  * We can't really set the mode, but we know how to
  737                  * query what the firmware negotiated.
  738                  */
  739                 struct scsipi_xfer_mode *xm = arg;
  740                 u_int8_t sdtr_data;
  741                 ASC_SCSI_BIT_ID_TYPE tid_bit;
  742 
  743                 tid_bit = ASC_TIX_TO_TARGET_ID(xm->xm_target);
  744 
  745                 xm->xm_mode = 0;
  746                 xm->xm_period = 0;
  747                 xm->xm_offset = 0;
  748 
  749                 if (sc->init_sdtr & tid_bit) {
  750                         xm->xm_mode |= PERIPH_CAP_SYNC;
  751                         sdtr_data = sc->sdtr_data[xm->xm_target];
  752                         xm->xm_period =
  753                             sc->sdtr_period_tbl[(sdtr_data >> 4) &
  754                             (sc->max_sdtr_index - 1)];
  755                         xm->xm_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
  756                 }
  757 
  758                 if (sc->use_tagged_qng & tid_bit)
  759                         xm->xm_mode |= PERIPH_CAP_TQING;
  760 
  761                 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
  762                 return;
  763             }
  764         }
  765 }
  766 
  767 int
  768 adv_intr(arg)
  769         void           *arg;
  770 {
  771         ASC_SOFTC      *sc = arg;
  772 
  773 #ifdef ASC_DEBUG
  774         int int_pend = FALSE;
  775 
  776         if(ASC_IS_INT_PENDING(sc->sc_iot, sc->sc_ioh))
  777         {
  778                 int_pend = TRUE;
  779                 printf("ISR - ");
  780         }
  781 #endif
  782         AscISR(sc);
  783 #ifdef ASC_DEBUG
  784         if(int_pend)
  785                 printf("\n");
  786 #endif
  787 
  788         return (1);
  789 }
  790 
  791 
  792 /*
  793  * Poll a particular unit, looking for a particular xs
  794  */
  795 static int
  796 adv_poll(sc, xs, count)
  797         ASC_SOFTC      *sc;
  798         struct scsipi_xfer *xs;
  799         int             count;
  800 {
  801 
  802         /* timeouts are in msec, so we loop in 1000 usec cycles */
  803         while (count) {
  804                 adv_intr(sc);
  805                 if (xs->xs_status & XS_STS_DONE)
  806                         return (0);
  807                 delay(1000);    /* only happens in boot so ok */
  808                 count--;
  809         }
  810         return (1);
  811 }
  812 
  813 
  814 static void
  815 adv_timeout(arg)
  816         void           *arg;
  817 {
  818         ADV_CCB        *ccb = arg;
  819         struct scsipi_xfer *xs = ccb->xs;
  820         struct scsipi_periph *periph = xs->xs_periph;
  821         ASC_SOFTC      *sc =
  822             (void *)periph->periph_channel->chan_adapter->adapt_dev;
  823         int             s;
  824 
  825         scsipi_printaddr(periph);
  826         printf("timed out");
  827 
  828         s = splbio();
  829 
  830         /*
  831          * If it has been through before, then a previous abort has failed,
  832          * don't try abort again, reset the bus instead.
  833          */
  834         if (ccb->flags & CCB_ABORT) {
  835                 /* abort timed out */
  836                 printf(" AGAIN. Resetting Bus\n");
  837                 /* Lets try resetting the bus! */
  838                 if (AscResetBus(sc) == ASC_ERROR) {
  839                         ccb->timeout = sc->scsi_reset_wait;
  840                         adv_queue_ccb(sc, ccb);
  841                 }
  842         } else {
  843                 /* abort the operation that has timed out */
  844                 printf("\n");
  845                 AscAbortCCB(sc, ccb);
  846                 ccb->xs->error = XS_TIMEOUT;
  847                 ccb->timeout = ADV_ABORT_TIMEOUT;
  848                 ccb->flags |= CCB_ABORT;
  849                 adv_queue_ccb(sc, ccb);
  850         }
  851 
  852         splx(s);
  853 }
  854 
  855 
  856 static void
  857 adv_watchdog(arg)
  858         void           *arg;
  859 {
  860         ADV_CCB        *ccb = arg;
  861         struct scsipi_xfer *xs = ccb->xs;
  862         struct scsipi_periph *periph = xs->xs_periph;
  863         ASC_SOFTC      *sc =
  864             (void *)periph->periph_channel->chan_adapter->adapt_dev;
  865         int             s;
  866 
  867         s = splbio();
  868 
  869         ccb->flags &= ~CCB_WATCHDOG;
  870         adv_start_ccbs(sc);
  871 
  872         splx(s);
  873 }
  874 
  875 
  876 /******************************************************************************/
  877 /*                      NARROW boards Interrupt callbacks                     */
  878 /******************************************************************************/
  879 
  880 
  881 /*
  882  * adv_narrow_isr_callback() - Second Level Interrupt Handler called by AscISR()
  883  *
  884  * Interrupt callback function for the Narrow SCSI Asc Library.
  885  */
  886 static void
  887 adv_narrow_isr_callback(sc, qdonep)
  888         ASC_SOFTC      *sc;
  889         ASC_QDONE_INFO *qdonep;
  890 {
  891         bus_dma_tag_t   dmat = sc->sc_dmat;
  892         ADV_CCB        *ccb;
  893         struct scsipi_xfer *xs;
  894         struct scsi_sense_data *s1, *s2;
  895 
  896 
  897         ccb = adv_ccb_phys_kv(sc, qdonep->d2.ccb_ptr);
  898         xs = ccb->xs;
  899 
  900 #ifdef ASC_DEBUG
  901         printf(" - ccb=0x%lx, id=%d, lun=%d, cmd=%d, ",
  902                         (unsigned long)ccb,
  903                         xs->xs_periph->periph_target,
  904                         xs->xs_periph->periph_lun, xs->cmd->opcode);
  905 #endif
  906         callout_stop(&ccb->xs->xs_callout);
  907 
  908         /*
  909          * If we were a data transfer, unload the map that described
  910          * the data buffer.
  911          */
  912         if (xs->datalen) {
  913                 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
  914                                 ccb->dmamap_xfer->dm_mapsize,
  915                          (xs->xs_control & XS_CTL_DATA_IN) ?
  916                          BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  917                 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
  918         }
  919         if ((ccb->flags & CCB_ALLOC) == 0) {
  920                 aprint_error_dev(&sc->sc_dev, "exiting ccb not allocated!\n");
  921                 Debugger();
  922                 return;
  923         }
  924         /*
  925          * 'qdonep' contains the command's ending status.
  926          */
  927 #ifdef ASC_DEBUG
  928         printf("d_s=%d, h_s=%d", qdonep->d3.done_stat, qdonep->d3.host_stat);
  929 #endif
  930         switch (qdonep->d3.done_stat) {
  931         case ASC_QD_NO_ERROR:
  932                 switch (qdonep->d3.host_stat) {
  933                 case ASC_QHSTA_NO_ERROR:
  934                         xs->error = XS_NOERROR;
  935                         xs->resid = 0;
  936                         break;
  937 
  938                 default:
  939                         /* QHSTA error occurred */
  940                         xs->error = XS_DRIVER_STUFFUP;
  941                         break;
  942                 }
  943 
  944                 /*
  945                  * If an INQUIRY command completed successfully, then call
  946                  * the AscInquiryHandling() function to patch bugged boards.
  947                  */
  948                 if ((xs->cmd->opcode == SCSICMD_Inquiry) &&
  949                     (xs->xs_periph->periph_lun == 0) &&
  950                     (xs->datalen - qdonep->remain_bytes) >= 8) {
  951                         AscInquiryHandling(sc,
  952                                       xs->xs_periph->periph_target & 0x7,
  953                                            (ASC_SCSI_INQUIRY *) xs->data);
  954                 }
  955                 break;
  956 
  957         case ASC_QD_WITH_ERROR:
  958                 switch (qdonep->d3.host_stat) {
  959                 case ASC_QHSTA_NO_ERROR:
  960                         if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
  961                                 s1 = &ccb->scsi_sense;
  962                                 s2 = &xs->sense.scsi_sense;
  963                                 *s2 = *s1;
  964                                 xs->error = XS_SENSE;
  965                         } else {
  966                                 xs->error = XS_DRIVER_STUFFUP;
  967                         }
  968                         break;
  969 
  970                 case ASC_QHSTA_M_SEL_TIMEOUT:
  971                         xs->error = XS_SELTIMEOUT;
  972                         break;
  973 
  974                 default:
  975                         /* QHSTA error occurred */
  976                         xs->error = XS_DRIVER_STUFFUP;
  977                         break;
  978                 }
  979                 break;
  980 
  981         case ASC_QD_ABORTED_BY_HOST:
  982         default:
  983                 xs->error = XS_DRIVER_STUFFUP;
  984                 break;
  985         }
  986 
  987 
  988         adv_free_ccb(sc, ccb);
  989         scsipi_done(xs);
  990 }

Cache object: 66e4062fc277e689e61f1b4cc7f550f8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.