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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: adv.c,v 1.38 2006/08/17 17:11:27 christos 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.38 2006/08/17 17:11:27 christos 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 <machine/bus.h>
   56 #include <machine/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                 printf("%s: unable to allocate control structures,"
  121                        " error = %d\n", sc->sc_dev.dv_xname, 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                            (caddr_t *) & sc->sc_control,
  127                            BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
  128                 printf("%s: unable to map control structures, error = %d\n",
  129                        sc->sc_dev.dv_xname, 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                 printf("%s: unable to create control DMA map, error = %d\n",
  139                        sc->sc_dev.dv_xname, 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                 printf("%s: unable to load control DMA map, error = %d\n",
  146                        sc->sc_dev.dv_xname, 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, (caddr_t) 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                         printf("%s: unable to initialize ccb, error = %d\n",
  192                                sc->sc_dev.dv_xname, 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);
  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                 printf("%s: unable to create DMA map, error = %d\n",
  246                        sc->sc_dev.dv_xname, 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("%s -get: ", sc->sc_dev.dv_xname);
  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("%s -set: ", sc->sc_dev.dv_xname);
  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", sc->sc_dev.dv_xname);
  452                 break;
  453 
  454         case 2:
  455                 panic("%s: unable to load MicroCode",
  456                       sc->sc_dev.dv_xname);
  457                 break;
  458 
  459         case 3:
  460                 panic("%s: unable to initialize MicroCode",
  461                       sc->sc_dev.dv_xname);
  462                 break;
  463 
  464         default:
  465                 panic("%s: unable to initialize board RISC chip",
  466                       sc->sc_dev.dv_xname);
  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("%s: unable to create control blocks\n",
  507                        sc->sc_dev.dv_xname);
  508                 return; /* (ENOMEM) */ ;
  509         } else if (i != ADV_MAX_CCB) {
  510                 aprint_error(
  511                     "%s: WARNING: only %d of %d control blocks created\n",
  512                     sc->sc_dev.dv_xname, i, ADV_MAX_CCB);
  513         }
  514 
  515         adapt->adapt_openings = i;
  516         adapt->adapt_max_periph = adapt->adapt_openings;
  517 
  518         sc->sc_child = config_found(&sc->sc_dev, chan, scsiprint);
  519 }
  520 
  521 int
  522 adv_detach(sc, flags)
  523         ASC_SOFTC *sc;
  524         int flags;
  525 {
  526         int rv = 0;
  527 
  528         if (sc->sc_child != NULL)
  529                 rv = config_detach(sc->sc_child, flags);
  530 
  531         adv_free_control_data(sc);
  532 
  533         return (rv);
  534 }
  535 
  536 static void
  537 advminphys(bp)
  538         struct buf     *bp;
  539 {
  540 
  541         if (bp->b_bcount > ((ASC_MAX_SG_LIST - 1) * PAGE_SIZE))
  542                 bp->b_bcount = ((ASC_MAX_SG_LIST - 1) * PAGE_SIZE);
  543         minphys(bp);
  544 }
  545 
  546 
  547 /*
  548  * start a scsi operation given the command and the data address.  Also needs
  549  * the unit, target and lu.
  550  */
  551 
  552 static void
  553 adv_scsipi_request(chan, req, arg)
  554         struct scsipi_channel *chan;
  555         scsipi_adapter_req_t req;
  556         void *arg;
  557 {
  558         struct scsipi_xfer *xs;
  559         struct scsipi_periph *periph;
  560         ASC_SOFTC      *sc = (void *)chan->chan_adapter->adapt_dev;
  561         bus_dma_tag_t   dmat = sc->sc_dmat;
  562         ADV_CCB        *ccb;
  563         int             s, flags, error, nsegs;
  564 
  565         switch (req) {
  566         case ADAPTER_REQ_RUN_XFER:
  567                 xs = arg;
  568                 periph = xs->xs_periph;
  569                 flags = xs->xs_control;
  570 
  571                 /*
  572                  * Get a CCB to use.
  573                  */
  574                 ccb = adv_get_ccb(sc);
  575 #ifdef DIAGNOSTIC
  576                 /*
  577                  * This should never happen as we track the resources
  578                  * in the mid-layer.
  579                  */
  580                 if (ccb == NULL) {
  581                         scsipi_printaddr(periph);
  582                         printf("unable to allocate ccb\n");
  583                         panic("adv_scsipi_request");
  584                 }
  585 #endif
  586 
  587                 ccb->xs = xs;
  588                 ccb->timeout = xs->timeout;
  589 
  590                 /*
  591                  * Build up the request
  592                  */
  593                 memset(&ccb->scsiq, 0, sizeof(ASC_SCSI_Q));
  594 
  595                 ccb->scsiq.q2.ccb_ptr =
  596                     sc->sc_dmamap_control->dm_segs[0].ds_addr +
  597                     ADV_CCB_OFF(ccb);
  598 
  599                 ccb->scsiq.cdbptr = &xs->cmd->opcode;
  600                 ccb->scsiq.q2.cdb_len = xs->cmdlen;
  601                 ccb->scsiq.q1.target_id =
  602                     ASC_TID_TO_TARGET_ID(periph->periph_target);
  603                 ccb->scsiq.q1.target_lun = periph->periph_lun;
  604                 ccb->scsiq.q2.target_ix =
  605                     ASC_TIDLUN_TO_IX(periph->periph_target,
  606                     periph->periph_lun);
  607                 ccb->scsiq.q1.sense_addr =
  608                     sc->sc_dmamap_control->dm_segs[0].ds_addr +
  609                     ADV_CCB_OFF(ccb) + offsetof(struct adv_ccb, scsi_sense);
  610                 ccb->scsiq.q1.sense_len = sizeof(struct scsi_sense_data);
  611 
  612                 /*
  613                  * If there are any outstanding requests for the current
  614                  * target, then every 255th request send an ORDERED request.
  615                  * This heuristic tries to retain the benefit of request
  616                  * sorting while preventing request starvation. 255 is the
  617                  * max number of tags or pending commands a device may have
  618                  * outstanding.
  619                  */
  620                 sc->reqcnt[periph->periph_target]++;
  621                 if (((sc->reqcnt[periph->periph_target] > 0) &&
  622                     (sc->reqcnt[periph->periph_target] % 255) == 0) ||
  623                     xs->bp == NULL || (xs->bp->b_flags & B_ASYNC) == 0) {
  624                         ccb->scsiq.q2.tag_code = M2_QTAG_MSG_ORDERED;
  625                 } else {
  626                         ccb->scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
  627                 }
  628 
  629                 if (xs->datalen) {
  630                         /*
  631                          * Map the DMA transfer.
  632                          */
  633 #ifdef TFS
  634                         if (flags & SCSI_DATA_UIO) {
  635                                 error = bus_dmamap_load_uio(dmat,
  636                                     ccb->dmamap_xfer, (struct uio *) xs->data,
  637                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
  638                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
  639                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
  640                                       BUS_DMA_WRITE));
  641                         } else
  642 #endif /* TFS */
  643                         {
  644                                 error = bus_dmamap_load(dmat, ccb->dmamap_xfer,
  645                                     xs->data, xs->datalen, NULL,
  646                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
  647                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
  648                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
  649                                       BUS_DMA_WRITE));
  650                         }
  651 
  652                         switch (error) {
  653                         case 0:
  654                                 break;
  655 
  656 
  657                         case ENOMEM:
  658                         case EAGAIN:
  659                                 xs->error = XS_RESOURCE_SHORTAGE;
  660                                 goto out_bad;
  661 
  662                         default:
  663                                 xs->error = XS_DRIVER_STUFFUP;
  664                                 if (error == EFBIG) {
  665                                         printf("%s: adv_scsi_cmd, more than %d"
  666                                             " DMA segments\n",
  667                                             sc->sc_dev.dv_xname,
  668                                             ASC_MAX_SG_LIST);
  669                                 } else {
  670                                         printf("%s: adv_scsi_cmd, error %d"
  671                                             " loading DMA map\n",
  672                                             sc->sc_dev.dv_xname, error);
  673                                 }
  674 
  675 out_bad:
  676                                 adv_free_ccb(sc, ccb);
  677                                 scsipi_done(xs);
  678                                 return;
  679                         }
  680                         bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
  681                             ccb->dmamap_xfer->dm_mapsize,
  682                             (flags & XS_CTL_DATA_IN) ?
  683                              BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  684 
  685                         memset(&ccb->sghead, 0, sizeof(ASC_SG_HEAD));
  686 
  687                         for (nsegs = 0;
  688                              nsegs < ccb->dmamap_xfer->dm_nsegs; nsegs++) {
  689                                 ccb->sghead.sg_list[nsegs].addr =
  690                                     ccb->dmamap_xfer->dm_segs[nsegs].ds_addr;
  691                                 ccb->sghead.sg_list[nsegs].bytes =
  692                                     ccb->dmamap_xfer->dm_segs[nsegs].ds_len;
  693                         }
  694 
  695                         ccb->sghead.entry_cnt = ccb->scsiq.q1.sg_queue_cnt =
  696                             ccb->dmamap_xfer->dm_nsegs;
  697 
  698                         ccb->scsiq.q1.cntl |= ASC_QC_SG_HEAD;
  699                         ccb->scsiq.sg_head = &ccb->sghead;
  700                         ccb->scsiq.q1.data_addr = 0;
  701                         ccb->scsiq.q1.data_cnt = 0;
  702                 } else {
  703                         /*
  704                          * No data xfer, use non S/G values.
  705                          */
  706                         ccb->scsiq.q1.data_addr = 0;
  707                         ccb->scsiq.q1.data_cnt = 0;
  708                 }
  709 
  710 #ifdef ASC_DEBUG
  711                 printf("id = %d, lun = %d, cmd = %d, ccb = 0x%lX\n",
  712                     periph->periph_target,
  713                     periph->periph_lun, xs->cmd->opcode,
  714                     (unsigned long)ccb);
  715 #endif
  716                 s = splbio();
  717                 adv_queue_ccb(sc, ccb);
  718                 splx(s);
  719 
  720                 if ((flags & XS_CTL_POLL) == 0)
  721                         return;
  722 
  723                 /* Not allowed to use interrupts, poll for completion. */
  724                 if (adv_poll(sc, xs, ccb->timeout)) {
  725                         adv_timeout(ccb);
  726                         if (adv_poll(sc, xs, ccb->timeout))
  727                                 adv_timeout(ccb);
  728                 }
  729                 return;
  730 
  731         case ADAPTER_REQ_GROW_RESOURCES:
  732                 /* XXX Not supported. */
  733                 return;
  734 
  735         case ADAPTER_REQ_SET_XFER_MODE:
  736             {
  737                 /*
  738                  * We can't really set the mode, but we know how to
  739                  * query what the firmware negotiated.
  740                  */
  741                 struct scsipi_xfer_mode *xm = arg;
  742                 u_int8_t sdtr_data;
  743                 ASC_SCSI_BIT_ID_TYPE tid_bit;
  744 
  745                 tid_bit = ASC_TIX_TO_TARGET_ID(xm->xm_target);
  746 
  747                 xm->xm_mode = 0;
  748                 xm->xm_period = 0;
  749                 xm->xm_offset = 0;
  750 
  751                 if (sc->init_sdtr & tid_bit) {
  752                         xm->xm_mode |= PERIPH_CAP_SYNC;
  753                         sdtr_data = sc->sdtr_data[xm->xm_target];
  754                         xm->xm_period =
  755                             sc->sdtr_period_tbl[(sdtr_data >> 4) &
  756                             (sc->max_sdtr_index - 1)];
  757                         xm->xm_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
  758                 }
  759 
  760                 if (sc->use_tagged_qng & tid_bit)
  761                         xm->xm_mode |= PERIPH_CAP_TQING;
  762 
  763                 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
  764                 return;
  765             }
  766         }
  767 }
  768 
  769 int
  770 adv_intr(arg)
  771         void           *arg;
  772 {
  773         ASC_SOFTC      *sc = arg;
  774 
  775 #ifdef ASC_DEBUG
  776         int int_pend = FALSE;
  777 
  778         if(ASC_IS_INT_PENDING(sc->sc_iot, sc->sc_ioh))
  779         {
  780                 int_pend = TRUE;
  781                 printf("ISR - ");
  782         }
  783 #endif
  784         AscISR(sc);
  785 #ifdef ASC_DEBUG
  786         if(int_pend)
  787                 printf("\n");
  788 #endif
  789 
  790         return (1);
  791 }
  792 
  793 
  794 /*
  795  * Poll a particular unit, looking for a particular xs
  796  */
  797 static int
  798 adv_poll(sc, xs, count)
  799         ASC_SOFTC      *sc;
  800         struct scsipi_xfer *xs;
  801         int             count;
  802 {
  803 
  804         /* timeouts are in msec, so we loop in 1000 usec cycles */
  805         while (count) {
  806                 adv_intr(sc);
  807                 if (xs->xs_status & XS_STS_DONE)
  808                         return (0);
  809                 delay(1000);    /* only happens in boot so ok */
  810                 count--;
  811         }
  812         return (1);
  813 }
  814 
  815 
  816 static void
  817 adv_timeout(arg)
  818         void           *arg;
  819 {
  820         ADV_CCB        *ccb = arg;
  821         struct scsipi_xfer *xs = ccb->xs;
  822         struct scsipi_periph *periph = xs->xs_periph;
  823         ASC_SOFTC      *sc =
  824             (void *)periph->periph_channel->chan_adapter->adapt_dev;
  825         int             s;
  826 
  827         scsipi_printaddr(periph);
  828         printf("timed out");
  829 
  830         s = splbio();
  831 
  832         /*
  833          * If it has been through before, then a previous abort has failed,
  834          * don't try abort again, reset the bus instead.
  835          */
  836         if (ccb->flags & CCB_ABORT) {
  837                 /* abort timed out */
  838                 printf(" AGAIN. Resetting Bus\n");
  839                 /* Lets try resetting the bus! */
  840                 if (AscResetBus(sc) == ASC_ERROR) {
  841                         ccb->timeout = sc->scsi_reset_wait;
  842                         adv_queue_ccb(sc, ccb);
  843                 }
  844         } else {
  845                 /* abort the operation that has timed out */
  846                 printf("\n");
  847                 AscAbortCCB(sc, ccb);
  848                 ccb->xs->error = XS_TIMEOUT;
  849                 ccb->timeout = ADV_ABORT_TIMEOUT;
  850                 ccb->flags |= CCB_ABORT;
  851                 adv_queue_ccb(sc, ccb);
  852         }
  853 
  854         splx(s);
  855 }
  856 
  857 
  858 static void
  859 adv_watchdog(arg)
  860         void           *arg;
  861 {
  862         ADV_CCB        *ccb = arg;
  863         struct scsipi_xfer *xs = ccb->xs;
  864         struct scsipi_periph *periph = xs->xs_periph;
  865         ASC_SOFTC      *sc =
  866             (void *)periph->periph_channel->chan_adapter->adapt_dev;
  867         int             s;
  868 
  869         s = splbio();
  870 
  871         ccb->flags &= ~CCB_WATCHDOG;
  872         adv_start_ccbs(sc);
  873 
  874         splx(s);
  875 }
  876 
  877 
  878 /******************************************************************************/
  879 /*                      NARROW boards Interrupt callbacks                     */
  880 /******************************************************************************/
  881 
  882 
  883 /*
  884  * adv_narrow_isr_callback() - Second Level Interrupt Handler called by AscISR()
  885  *
  886  * Interrupt callback function for the Narrow SCSI Asc Library.
  887  */
  888 static void
  889 adv_narrow_isr_callback(sc, qdonep)
  890         ASC_SOFTC      *sc;
  891         ASC_QDONE_INFO *qdonep;
  892 {
  893         bus_dma_tag_t   dmat = sc->sc_dmat;
  894         ADV_CCB        *ccb;
  895         struct scsipi_xfer *xs;
  896         struct scsi_sense_data *s1, *s2;
  897 
  898 
  899         ccb = adv_ccb_phys_kv(sc, qdonep->d2.ccb_ptr);
  900         xs = ccb->xs;
  901 
  902 #ifdef ASC_DEBUG
  903         printf(" - ccb=0x%lx, id=%d, lun=%d, cmd=%d, ",
  904                         (unsigned long)ccb,
  905                         xs->xs_periph->periph_target,
  906                         xs->xs_periph->periph_lun, xs->cmd->opcode);
  907 #endif
  908         callout_stop(&ccb->xs->xs_callout);
  909 
  910         /*
  911          * If we were a data transfer, unload the map that described
  912          * the data buffer.
  913          */
  914         if (xs->datalen) {
  915                 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
  916                                 ccb->dmamap_xfer->dm_mapsize,
  917                          (xs->xs_control & XS_CTL_DATA_IN) ?
  918                          BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  919                 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
  920         }
  921         if ((ccb->flags & CCB_ALLOC) == 0) {
  922                 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
  923                 Debugger();
  924                 return;
  925         }
  926         /*
  927          * 'qdonep' contains the command's ending status.
  928          */
  929 #ifdef ASC_DEBUG
  930         printf("d_s=%d, h_s=%d", qdonep->d3.done_stat, qdonep->d3.host_stat);
  931 #endif
  932         switch (qdonep->d3.done_stat) {
  933         case ASC_QD_NO_ERROR:
  934                 switch (qdonep->d3.host_stat) {
  935                 case ASC_QHSTA_NO_ERROR:
  936                         xs->error = XS_NOERROR;
  937                         xs->resid = 0;
  938                         break;
  939 
  940                 default:
  941                         /* QHSTA error occurred */
  942                         xs->error = XS_DRIVER_STUFFUP;
  943                         break;
  944                 }
  945 
  946                 /*
  947                  * If an INQUIRY command completed successfully, then call
  948                  * the AscInquiryHandling() function to patch bugged boards.
  949                  */
  950                 if ((xs->cmd->opcode == SCSICMD_Inquiry) &&
  951                     (xs->xs_periph->periph_lun == 0) &&
  952                     (xs->datalen - qdonep->remain_bytes) >= 8) {
  953                         AscInquiryHandling(sc,
  954                                       xs->xs_periph->periph_target & 0x7,
  955                                            (ASC_SCSI_INQUIRY *) xs->data);
  956                 }
  957                 break;
  958 
  959         case ASC_QD_WITH_ERROR:
  960                 switch (qdonep->d3.host_stat) {
  961                 case ASC_QHSTA_NO_ERROR:
  962                         if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) {
  963                                 s1 = &ccb->scsi_sense;
  964                                 s2 = &xs->sense.scsi_sense;
  965                                 *s2 = *s1;
  966                                 xs->error = XS_SENSE;
  967                         } else {
  968                                 xs->error = XS_DRIVER_STUFFUP;
  969                         }
  970                         break;
  971 
  972                 case ASC_QHSTA_M_SEL_TIMEOUT:
  973                         xs->error = XS_SELTIMEOUT;
  974                         break;
  975 
  976                 default:
  977                         /* QHSTA error occurred */
  978                         xs->error = XS_DRIVER_STUFFUP;
  979                         break;
  980                 }
  981                 break;
  982 
  983         case ASC_QD_ABORTED_BY_HOST:
  984         default:
  985                 xs->error = XS_DRIVER_STUFFUP;
  986                 break;
  987         }
  988 
  989 
  990         adv_free_ccb(sc, ccb);
  991         scsipi_done(xs);
  992 }

Cache object: 9e1fc609bad84611291f6d28d715bc3f


[ 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.