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/aha.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: aha.c,v 1.43 2003/11/02 11:07:44 wiz Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
    9  * Simulation Facility, NASA Ames Research Center.
   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 /*
   41  * Originally written by Julian Elischer (julian@tfs.com)
   42  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   43  *
   44  * TRW Financial Systems, in accordance with their agreement with Carnegie
   45  * Mellon University, makes this software available to CMU to distribute
   46  * or use in any manner that they see fit as long as this message is kept with
   47  * the software. For this reason TFS also grants any other persons or
   48  * organisations permission to use or modify this software.
   49  *
   50  * TFS supplies this software to be publicly redistributed
   51  * on the understanding that TFS is not responsible for the correct
   52  * functioning of this software in any circumstances.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __KERNEL_RCSID(0, "$NetBSD: aha.c,v 1.43 2003/11/02 11:07:44 wiz Exp $");
   57 
   58 #include "opt_ddb.h"
   59 
   60 #undef AHADIAG
   61 #ifdef DDB
   62 #define integrate
   63 #else
   64 #define integrate       static inline
   65 #endif
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/callout.h>
   70 #include <sys/kernel.h>
   71 #include <sys/errno.h>
   72 #include <sys/ioctl.h>
   73 #include <sys/device.h>
   74 #include <sys/malloc.h>
   75 #include <sys/buf.h>
   76 #include <sys/proc.h>
   77 #include <sys/user.h>
   78 
   79 #include <uvm/uvm_extern.h>
   80 
   81 #include <machine/bus.h>
   82 #include <machine/intr.h>
   83 
   84 #include <dev/scsipi/scsi_all.h>
   85 #include <dev/scsipi/scsipi_all.h>
   86 #include <dev/scsipi/scsiconf.h>
   87 
   88 #include <dev/ic/ahareg.h>
   89 #include <dev/ic/ahavar.h>
   90 
   91 #ifndef DDB
   92 #define Debugger() panic("should call debugger here (aha1542.c)")
   93 #endif /* ! DDB */
   94 
   95 #define AHA_MAXXFER     ((AHA_NSEG - 1) << PGSHIFT)
   96 
   97 #ifdef AHADEBUG
   98 int     aha_debug = 1;
   99 #endif /* AHADEBUG */
  100 
  101 int aha_cmd __P((bus_space_tag_t, bus_space_handle_t, struct aha_softc *, int,
  102     u_char *, int, u_char *));
  103 integrate void aha_finish_ccbs __P((struct aha_softc *));
  104 integrate void aha_reset_ccb __P((struct aha_softc *, struct aha_ccb *));
  105 void aha_free_ccb __P((struct aha_softc *, struct aha_ccb *));
  106 integrate int aha_init_ccb __P((struct aha_softc *, struct aha_ccb *));
  107 struct aha_ccb *aha_get_ccb __P((struct aha_softc *));
  108 struct aha_ccb *aha_ccb_phys_kv __P((struct aha_softc *, u_long));
  109 void aha_queue_ccb __P((struct aha_softc *, struct aha_ccb *));
  110 void aha_collect_mbo __P((struct aha_softc *));
  111 void aha_start_ccbs __P((struct aha_softc *));
  112 void aha_done __P((struct aha_softc *, struct aha_ccb *));
  113 int aha_init __P((struct aha_softc *));
  114 void aha_inquire_setup_information __P((struct aha_softc *));
  115 void ahaminphys __P((struct buf *));
  116 void aha_scsipi_request __P((struct scsipi_channel *,
  117     scsipi_adapter_req_t, void *));
  118 int aha_poll __P((struct aha_softc *, struct scsipi_xfer *, int));
  119 void aha_timeout __P((void *arg));
  120 int aha_create_ccbs __P((struct aha_softc *, struct aha_ccb *, int));
  121 
  122 #define AHA_RESET_TIMEOUT       2000    /* time to wait for reset (mSec) */
  123 #define AHA_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
  124 
  125 /*
  126  * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
  127  *
  128  * Activate Adapter command
  129  *    icnt:   number of args (outbound bytes including opcode)
  130  *    ibuf:   argument buffer
  131  *    ocnt:   number of expected returned bytes
  132  *    obuf:   result buffer
  133  *    wait:   number of seconds to wait for response
  134  *
  135  * Performs an adapter command through the ports.  Not to be confused with a
  136  * scsi command, which is read in via the DMA; one of the adapter commands
  137  * tells it to read in a scsi command.
  138  */
  139 int
  140 aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
  141         bus_space_tag_t iot;
  142         bus_space_handle_t ioh;
  143         struct aha_softc *sc;
  144         int icnt, ocnt;
  145         u_char *ibuf, *obuf;
  146 {
  147         const char *name;
  148         int i;
  149         int wait;
  150         u_char sts;
  151         u_char opcode = ibuf[0];
  152 
  153         if (sc != NULL)
  154                 name = sc->sc_dev.dv_xname;
  155         else
  156                 name = "(aha probe)";
  157 
  158         /*
  159          * Calculate a reasonable timeout for the command.
  160          */
  161         switch (opcode) {
  162         case AHA_INQUIRE_DEVICES:
  163                 wait = 90 * 20000;
  164                 break;
  165         default:
  166                 wait = 1 * 20000;
  167                 break;
  168         }
  169 
  170         /*
  171          * Wait for the adapter to go idle, unless it's one of
  172          * the commands which don't need this
  173          */
  174         if (opcode != AHA_MBO_INTR_EN) {
  175                 for (i = 20000; i; i--) {       /* 1 sec? */
  176                         sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
  177                         if (sts & AHA_STAT_IDLE)
  178                                 break;
  179                         delay(50);
  180                 }
  181                 if (!i) {
  182                         printf("%s: aha_cmd, host not idle(0x%x)\n",
  183                             name, sts);
  184                         return (1);
  185                 }
  186         }
  187         /*
  188          * Now that it is idle, if we expect output, preflush the
  189          * queue feeding to us.
  190          */
  191         if (ocnt) {
  192                 while ((bus_space_read_1(iot, ioh, AHA_STAT_PORT)) & AHA_STAT_DF)
  193                         bus_space_read_1(iot, ioh, AHA_DATA_PORT);
  194         }
  195         /*
  196          * Output the command and the number of arguments given
  197          * for each byte, first check the port is empty.
  198          */
  199         while (icnt--) {
  200                 for (i = wait; i; i--) {
  201                         sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
  202                         if (!(sts & AHA_STAT_CDF))
  203                                 break;
  204                         delay(50);
  205                 }
  206                 if (!i) {
  207                         if (opcode != AHA_INQUIRE_REVISION)
  208                                 printf("%s: aha_cmd, cmd/data port full\n", name);
  209                         bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST);
  210                         return (1);
  211                 }
  212                 bus_space_write_1(iot, ioh, AHA_CMD_PORT, *ibuf++);
  213         }
  214         /*
  215          * If we expect input, loop that many times, each time,
  216          * looking for the data register to have valid data
  217          */
  218         while (ocnt--) {
  219                 for (i = wait; i; i--) {
  220                         sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
  221                         if (sts & AHA_STAT_DF)
  222                                 break;
  223                         delay(50);
  224                 }
  225                 if (!i) {
  226                         if (opcode != AHA_INQUIRE_REVISION)
  227                                 printf("%s: aha_cmd, cmd/data port empty %d\n",
  228                                     name, ocnt);
  229                         bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_SRST);
  230                         return (1);
  231                 }
  232                 *obuf++ = bus_space_read_1(iot, ioh, AHA_DATA_PORT);
  233         }
  234         /*
  235          * Wait for the board to report a finished instruction.
  236          * We may get an extra interrupt for the HACC signal, but this is
  237          * unimportant.
  238          */
  239         if (opcode != AHA_MBO_INTR_EN) {
  240                 for (i = 20000; i; i--) {       /* 1 sec? */
  241                         sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT);
  242                         /* XXX Need to save this in the interrupt handler? */
  243                         if (sts & AHA_INTR_HACC)
  244                                 break;
  245                         delay(50);
  246                 }
  247                 if (!i) {
  248                         printf("%s: aha_cmd, host not finished(0x%x)\n",
  249                             name, sts);
  250                         return (1);
  251                 }
  252         }
  253         bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST);
  254         return (0);
  255 }
  256 
  257 void
  258 aha_attach(sc, apd)
  259         struct aha_softc *sc;
  260         struct aha_probe_data *apd;
  261 {
  262         struct scsipi_adapter *adapt = &sc->sc_adapter;
  263         struct scsipi_channel *chan = &sc->sc_channel;
  264 
  265         TAILQ_INIT(&sc->sc_free_ccb);
  266         TAILQ_INIT(&sc->sc_waiting_ccb);
  267 
  268         /*
  269          * Fill in the scsipi_adapter.
  270          */
  271         memset(adapt, 0, sizeof(*adapt));
  272         adapt->adapt_dev = &sc->sc_dev;
  273         adapt->adapt_nchannels = 1;
  274         /* adapt_openings initialized below */
  275         /* adapt_max_periph initialized below */
  276         adapt->adapt_request = aha_scsipi_request;
  277         adapt->adapt_minphys = ahaminphys;
  278 
  279         /*
  280          * Fill in the scsipi_channel.
  281          */
  282         memset(chan, 0, sizeof(*chan));
  283         chan->chan_adapter = adapt;
  284         chan->chan_bustype = &scsi_bustype;
  285         chan->chan_channel = 0;
  286         chan->chan_ntargets = 8;
  287         chan->chan_nluns = 8;
  288         chan->chan_id = apd->sc_scsi_dev;
  289 
  290         aha_inquire_setup_information(sc);
  291         if (aha_init(sc) != 0) {
  292                 /* Error during initialization! */
  293                 return;
  294         }
  295 
  296         /*
  297          * ask the adapter what subunits are present
  298          */
  299         config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
  300 }
  301 
  302 integrate void
  303 aha_finish_ccbs(sc)
  304         struct aha_softc *sc;
  305 {
  306         struct aha_mbx_in *wmbi;
  307         struct aha_ccb *ccb;
  308         int i;
  309 
  310         wmbi = wmbx->tmbi;
  311 
  312         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  313             AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in),
  314             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  315 
  316         if (wmbi->stat == AHA_MBI_FREE) {
  317                 for (i = 0; i < AHA_MBX_SIZE; i++) {
  318                         if (wmbi->stat != AHA_MBI_FREE) {
  319                                 printf("%s: mbi not in round-robin order\n",
  320                                     sc->sc_dev.dv_xname);
  321                                 goto AGAIN;
  322                         }
  323                         aha_nextmbx(wmbi, wmbx, mbi);
  324                         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  325                             AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in),
  326                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  327                 }
  328 #ifdef AHADIAGnot
  329                 printf("%s: mbi interrupt with no full mailboxes\n",
  330                     sc->sc_dev.dv_xname);
  331 #endif
  332                 return;
  333         }
  334 
  335 AGAIN:
  336         do {
  337                 ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
  338                 if (!ccb) {
  339                         printf("%s: bad mbi ccb pointer; skipping\n",
  340                             sc->sc_dev.dv_xname);
  341                         goto next;
  342                 }
  343 
  344                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  345                     AHA_CCB_OFF(ccb), sizeof(struct aha_ccb),
  346                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  347 
  348 #ifdef AHADEBUG
  349                 if (aha_debug) {
  350                         u_char *cp = &ccb->scsi_cmd;
  351                         printf("op=%x %x %x %x %x %x\n",
  352                             cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  353                         printf("stat %x for mbi addr = 0x%08x, ",
  354                             wmbi->stat, wmbi);
  355                         printf("ccb addr = 0x%x\n", ccb);
  356                 }
  357 #endif /* AHADEBUG */
  358 
  359                 switch (wmbi->stat) {
  360                 case AHA_MBI_OK:
  361                 case AHA_MBI_ERROR:
  362                         if ((ccb->flags & CCB_ABORT) != 0) {
  363                                 /*
  364                                  * If we already started an abort, wait for it
  365                                  * to complete before clearing the CCB.  We
  366                                  * could instead just clear CCB_SENDING, but
  367                                  * what if the mailbox was already received?
  368                                  * The worst that happens here is that we clear
  369                                  * the CCB a bit later than we need to.  BFD.
  370                                  */
  371                                 goto next;
  372                         }
  373                         break;
  374 
  375                 case AHA_MBI_ABORT:
  376                 case AHA_MBI_UNKNOWN:
  377                         /*
  378                          * Even if the CCB wasn't found, we clear it anyway.
  379                          * See preceding comment.
  380                          */
  381                         break;
  382 
  383                 default:
  384                         printf("%s: bad mbi status %02x; skipping\n",
  385                             sc->sc_dev.dv_xname, wmbi->stat);
  386                         goto next;
  387                 }
  388 
  389                 callout_stop(&ccb->xs->xs_callout);
  390                 aha_done(sc, ccb);
  391 
  392         next:
  393                 wmbi->stat = AHA_MBI_FREE;
  394                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  395                     AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in),
  396                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  397                 aha_nextmbx(wmbi, wmbx, mbi);
  398                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  399                     AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in), 
  400                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  401         } while (wmbi->stat != AHA_MBI_FREE);
  402 
  403         wmbx->tmbi = wmbi;
  404 }
  405 
  406 /*
  407  * Catch an interrupt from the adaptor
  408  */
  409 int
  410 aha_intr(arg)
  411         void *arg;
  412 {
  413         struct aha_softc *sc = arg;
  414         bus_space_tag_t iot = sc->sc_iot;
  415         bus_space_handle_t ioh = sc->sc_ioh;
  416         u_char sts;
  417 
  418 #ifdef AHADEBUG
  419         printf("%s: aha_intr ", sc->sc_dev.dv_xname);
  420 #endif /*AHADEBUG */
  421 
  422         /*
  423          * First acknowledge the interrupt, Then if it's not telling about
  424          * a completed operation just return.
  425          */
  426         sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT);
  427         if ((sts & AHA_INTR_ANYINTR) == 0)
  428                 return (0);
  429         bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST);
  430 
  431 #ifdef AHADIAG
  432         /* Make sure we clear CCB_SENDING before finishing a CCB. */
  433         aha_collect_mbo(sc);
  434 #endif
  435 
  436         /* Mail box out empty? */
  437         if (sts & AHA_INTR_MBOA) {
  438                 struct aha_toggle toggle;
  439 
  440                 toggle.cmd.opcode = AHA_MBO_INTR_EN;
  441                 toggle.cmd.enable = 0;
  442                 aha_cmd(iot, ioh, sc,
  443                     sizeof(toggle.cmd), (u_char *)&toggle.cmd,
  444                     0, (u_char *)0);
  445                 aha_start_ccbs(sc);
  446         }
  447 
  448         /* Mail box in full? */
  449         if (sts & AHA_INTR_MBIF)
  450                 aha_finish_ccbs(sc);
  451 
  452         return (1);
  453 }
  454 
  455 integrate void
  456 aha_reset_ccb(sc, ccb)
  457         struct aha_softc *sc;
  458         struct aha_ccb *ccb;
  459 {
  460 
  461         ccb->flags = 0;
  462 }
  463 
  464 /*
  465  * A ccb is put onto the free list.
  466  */
  467 void
  468 aha_free_ccb(sc, ccb)
  469         struct aha_softc *sc;
  470         struct aha_ccb *ccb;
  471 {
  472         int s;
  473 
  474         s = splbio();
  475         aha_reset_ccb(sc, ccb);
  476         TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
  477         splx(s);
  478 }
  479 
  480 integrate int
  481 aha_init_ccb(sc, ccb)
  482         struct aha_softc *sc;
  483         struct aha_ccb *ccb;
  484 {
  485         bus_dma_tag_t dmat = sc->sc_dmat;
  486         int hashnum, error;
  487 
  488         /*
  489          * Create the DMA map for this CCB.
  490          */
  491         error = bus_dmamap_create(dmat, AHA_MAXXFER, AHA_NSEG, AHA_MAXXFER,
  492             0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer);
  493         if (error) {
  494                 printf("%s: unable to create ccb DMA map, error = %d\n",
  495                     sc->sc_dev.dv_xname, error);
  496                 return (error);
  497         }
  498 
  499         /*
  500          * put in the phystokv hash table
  501          * Never gets taken out.
  502          */
  503         ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
  504             AHA_CCB_OFF(ccb);
  505         hashnum = CCB_HASH(ccb->hashkey);
  506         ccb->nexthash = sc->sc_ccbhash[hashnum];
  507         sc->sc_ccbhash[hashnum] = ccb;
  508         aha_reset_ccb(sc, ccb);
  509         return (0);
  510 }
  511 
  512 /*
  513  * Create a set of ccbs and add them to the free list.  Called once
  514  * by aha_init().  We return the number of CCBs successfully created.
  515  */
  516 int
  517 aha_create_ccbs(sc, ccbstore, count)
  518         struct aha_softc *sc;
  519         struct aha_ccb *ccbstore;
  520         int count;
  521 {
  522         struct aha_ccb *ccb;
  523         int i, error;
  524 
  525         memset(ccbstore, 0, sizeof(struct aha_ccb) * count);
  526         for (i = 0; i < count; i++) {
  527                 ccb = &ccbstore[i];
  528                 if ((error = aha_init_ccb(sc, ccb)) != 0) {
  529                         printf("%s: unable to initialize ccb, error = %d\n",
  530                             sc->sc_dev.dv_xname, error);
  531                         goto out;
  532                 }
  533                 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
  534         }
  535  out:
  536         return (i);
  537 }
  538 
  539 /*
  540  * Get a free ccb
  541  *
  542  * If there are none, see if we can allocate a new one.  If so, put it in
  543  * the hash table too otherwise either return an error or sleep.
  544  */
  545 struct aha_ccb *
  546 aha_get_ccb(sc)
  547         struct aha_softc *sc;
  548 {
  549         struct aha_ccb *ccb;
  550         int s;
  551 
  552         s = splbio();
  553         ccb = TAILQ_FIRST(&sc->sc_free_ccb);
  554         if (ccb != NULL) {
  555                 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
  556                 ccb->flags |= CCB_ALLOC;
  557         }
  558         splx(s);
  559         return (ccb);
  560 }
  561 
  562 /*
  563  * Given a physical address, find the ccb that it corresponds to.
  564  */
  565 struct aha_ccb *
  566 aha_ccb_phys_kv(sc, ccb_phys)
  567         struct aha_softc *sc;
  568         u_long ccb_phys;
  569 {
  570         int hashnum = CCB_HASH(ccb_phys);
  571         struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
  572 
  573         while (ccb) {
  574                 if (ccb->hashkey == ccb_phys)
  575                         break;
  576                 ccb = ccb->nexthash;
  577         }
  578         return (ccb);
  579 }
  580 
  581 /*
  582  * Queue a CCB to be sent to the controller, and send it if possible.
  583  */
  584 void
  585 aha_queue_ccb(sc, ccb)
  586         struct aha_softc *sc;
  587         struct aha_ccb *ccb;
  588 {
  589 
  590         TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
  591         aha_start_ccbs(sc);
  592 }
  593 
  594 /*
  595  * Garbage collect mailboxes that are no longer in use.
  596  */
  597 void
  598 aha_collect_mbo(sc)
  599         struct aha_softc *sc;
  600 {
  601         struct aha_mbx_out *wmbo;       /* Mail Box Out pointer */
  602 #ifdef AHADIAG
  603         struct aha_ccb *ccb;
  604 #endif
  605 
  606         wmbo = wmbx->cmbo;
  607 
  608         while (sc->sc_mbofull > 0) {
  609                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  610                     AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out),
  611                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  612                 if (wmbo->cmd != AHA_MBO_FREE)
  613                         break;
  614 
  615 #ifdef AHADIAG
  616                 ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
  617                 ccb->flags &= ~CCB_SENDING;
  618 #endif
  619 
  620                 --sc->sc_mbofull;
  621                 aha_nextmbx(wmbo, wmbx, mbo);
  622         }
  623 
  624         wmbx->cmbo = wmbo;
  625 }
  626 
  627 /*
  628  * Send as many CCBs as we have empty mailboxes for.
  629  */
  630 void
  631 aha_start_ccbs(sc)
  632         struct aha_softc *sc;
  633 {
  634         bus_space_tag_t iot = sc->sc_iot;
  635         bus_space_handle_t ioh = sc->sc_ioh;
  636         struct aha_mbx_out *wmbo;       /* Mail Box Out pointer */
  637         struct aha_ccb *ccb;
  638 
  639         wmbo = wmbx->tmbo;
  640 
  641         while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) {
  642                 if (sc->sc_mbofull >= AHA_MBX_SIZE) {
  643                         aha_collect_mbo(sc);
  644                         if (sc->sc_mbofull >= AHA_MBX_SIZE) {
  645                                 struct aha_toggle toggle;
  646 
  647                                 toggle.cmd.opcode = AHA_MBO_INTR_EN;
  648                                 toggle.cmd.enable = 1;
  649                                 aha_cmd(iot, ioh, sc,
  650                                     sizeof(toggle.cmd), (u_char *)&toggle.cmd,
  651                                     0, (u_char *)0);
  652                                 break;
  653                         }
  654                 }
  655 
  656                 TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
  657 #ifdef AHADIAG
  658                 ccb->flags |= CCB_SENDING;
  659 #endif
  660 
  661                 /* Link ccb to mbo. */
  662                 ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
  663                     AHA_CCB_OFF(ccb), wmbo->ccb_addr);
  664                 if (ccb->flags & CCB_ABORT)
  665                         wmbo->cmd = AHA_MBO_ABORT;
  666                 else
  667                         wmbo->cmd = AHA_MBO_START;
  668 
  669                  bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
  670                      AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out),
  671                      BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  672 
  673                 /* Tell the card to poll immediately. */
  674                 bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI);
  675 
  676                 if ((ccb->xs->xs_control & XS_CTL_POLL) == 0)
  677                         callout_reset(&ccb->xs->xs_callout,
  678                             mstohz(ccb->timeout), aha_timeout, ccb);
  679 
  680                 ++sc->sc_mbofull;
  681                 aha_nextmbx(wmbo, wmbx, mbo);
  682         }
  683 
  684         wmbx->tmbo = wmbo;
  685 }
  686 
  687 /*
  688  * We have a ccb which has been processed by the
  689  * adaptor, now we look to see how the operation
  690  * went. Wake up the owner if waiting
  691  */
  692 void
  693 aha_done(sc, ccb)
  694         struct aha_softc *sc;
  695         struct aha_ccb *ccb;
  696 {
  697         bus_dma_tag_t dmat = sc->sc_dmat;
  698         struct scsipi_sense_data *s1, *s2;
  699         struct scsipi_xfer *xs = ccb->xs;
  700 
  701         SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("aha_done\n"));
  702 
  703         /*
  704          * If we were a data transfer, unload the map that described
  705          * the data buffer.
  706          */
  707         if (xs->datalen) {
  708                 bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
  709                     ccb->dmamap_xfer->dm_mapsize,
  710                     (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
  711                     BUS_DMASYNC_POSTWRITE);
  712                 bus_dmamap_unload(dmat, ccb->dmamap_xfer);
  713         }
  714 
  715         /*
  716          * Otherwise, put the results of the operation
  717          * into the xfer and call whoever started it
  718          */
  719 #ifdef AHADIAG
  720         if (ccb->flags & CCB_SENDING) {
  721                 printf("%s: exiting ccb still in transit!\n", sc->sc_dev.dv_xname);
  722                 Debugger();
  723                 return;
  724         }
  725 #endif
  726         if ((ccb->flags & CCB_ALLOC) == 0) {
  727                 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
  728                 Debugger();
  729                 return;
  730         }
  731         if (xs->error == XS_NOERROR) {
  732                 if (ccb->host_stat != AHA_OK) {
  733                         switch (ccb->host_stat) {
  734                         case AHA_SEL_TIMEOUT:   /* No response */
  735                                 xs->error = XS_SELTIMEOUT;
  736                                 break;
  737                         default:        /* Other scsi protocol messes */
  738                                 printf("%s: host_stat %x\n",
  739                                     sc->sc_dev.dv_xname, ccb->host_stat);
  740                                 xs->error = XS_DRIVER_STUFFUP;
  741                                 break;
  742                         }
  743                 } else if (ccb->target_stat != SCSI_OK) {
  744                         switch (ccb->target_stat) {
  745                         case SCSI_CHECK:
  746                                 s1 = (struct scsipi_sense_data *) (((char *) (&ccb->scsi_cmd)) +
  747                                     ccb->scsi_cmd_length);
  748                                 s2 = &xs->sense.scsi_sense;
  749                                 *s2 = *s1;
  750                                 xs->error = XS_SENSE;
  751                                 break;
  752                         case SCSI_BUSY:
  753                                 xs->error = XS_BUSY;
  754                                 break;
  755                         default:
  756                                 printf("%s: target_stat %x\n",
  757                                     sc->sc_dev.dv_xname, ccb->target_stat);
  758                                 xs->error = XS_DRIVER_STUFFUP;
  759                                 break;
  760                         }
  761                 } else
  762                         xs->resid = 0;
  763         }
  764         aha_free_ccb(sc, ccb);
  765         scsipi_done(xs);
  766 }
  767 
  768 /*
  769  * Find the board and find its irq/drq
  770  */
  771 int
  772 aha_find(iot, ioh, sc)
  773         bus_space_tag_t iot;
  774         bus_space_handle_t ioh;
  775         struct aha_probe_data *sc;
  776 {
  777         int i;
  778         u_char sts;
  779         struct aha_config config;
  780         int irq, drq;
  781 
  782         /*
  783          * reset board, If it doesn't respond, assume
  784          * that it's not there.. good for the probe
  785          */
  786 
  787         bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
  788 
  789         delay(100);
  790         for (i = AHA_RESET_TIMEOUT; i; i--) {
  791                 sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
  792                 if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
  793                         break;
  794                 delay(1000);    /* calibrated in msec */
  795         }
  796         if (!i) {
  797 #ifdef AHADEBUG
  798                 if (aha_debug)
  799                         printf("aha_find: No answer from adaptec board\n");
  800 #endif /* AHADEBUG */
  801                 return (0);
  802         }
  803 
  804         /*
  805          * setup DMA channel from jumpers and save int
  806          * level
  807          */
  808         delay(1000);            /* for Bustek 545 */
  809         config.cmd.opcode = AHA_INQUIRE_CONFIG;
  810         aha_cmd(iot, ioh, (struct aha_softc *)0,
  811             sizeof(config.cmd), (u_char *)&config.cmd,
  812             sizeof(config.reply), (u_char *)&config.reply);
  813         switch (config.reply.chan) {
  814         case EISADMA:
  815                 drq = -1;
  816                 break;
  817         case CHAN0:
  818                 drq = 0;
  819                 break;
  820         case CHAN5:
  821                 drq = 5;
  822                 break;
  823         case CHAN6:
  824                 drq = 6;
  825                 break;
  826         case CHAN7:
  827                 drq = 7;
  828                 break;
  829         default:
  830                 printf("aha_find: illegal drq setting %x\n", config.reply.chan);
  831                 return (0);
  832         }
  833 
  834         switch (config.reply.intr) {
  835         case INT9:
  836                 irq = 9;
  837                 break;
  838         case INT10:
  839                 irq = 10;
  840                 break;
  841         case INT11:
  842                 irq = 11;
  843                 break;
  844         case INT12:
  845                 irq = 12;
  846                 break;
  847         case INT14:
  848                 irq = 14;
  849                 break;
  850         case INT15:
  851                 irq = 15;
  852                 break;
  853         default:
  854                 printf("aha_find: illegal irq setting %x\n", config.reply.intr);
  855                 return (0);
  856         }
  857 
  858         if (sc) {
  859                 sc->sc_irq = irq;
  860                 sc->sc_drq = drq;
  861                 sc->sc_scsi_dev = config.reply.scsi_dev;
  862         }
  863 
  864         return (1);
  865 }
  866 
  867 /*
  868  * Start the board, ready for normal operation
  869  */
  870 int
  871 aha_init(sc)
  872         struct aha_softc *sc;
  873 {
  874         bus_space_tag_t iot = sc->sc_iot;
  875         bus_space_handle_t ioh = sc->sc_ioh;
  876         bus_dma_segment_t seg;
  877         struct aha_devices devices;
  878         struct aha_setup setup;
  879         struct aha_mailbox mailbox;
  880         int error, i, j, initial_ccbs, rseg;
  881 
  882         /*
  883          * XXX
  884          * If we are a 1542C or later, disable the extended BIOS so that the
  885          * mailbox interface is unlocked.
  886          * No need to check the extended BIOS flags as some of the
  887          * extensions that cause us problems are not flagged in that byte.
  888          */
  889         if (!strncmp(sc->sc_model, "1542C", 5)) {
  890                 struct aha_extbios extbios;
  891                 struct aha_unlock unlock;
  892 
  893                 printf("%s: unlocking mailbox interface\n", sc->sc_dev.dv_xname);
  894                 extbios.cmd.opcode = AHA_EXT_BIOS;
  895                 aha_cmd(iot, ioh, sc,
  896                     sizeof(extbios.cmd), (u_char *)&extbios.cmd,
  897                     sizeof(extbios.reply), (u_char *)&extbios.reply);
  898 
  899 #ifdef AHADEBUG
  900                 printf("%s: flags=%02x, mailboxlock=%02x\n",
  901                     sc->sc_dev.dv_xname,
  902                     extbios.reply.flags, extbios.reply.mailboxlock);
  903 #endif /* AHADEBUG */
  904 
  905                 unlock.cmd.opcode = AHA_MBX_ENABLE;
  906                 unlock.cmd.junk = 0;
  907                 unlock.cmd.magic = extbios.reply.mailboxlock;
  908                 aha_cmd(iot, ioh, sc,
  909                     sizeof(unlock.cmd), (u_char *)&unlock.cmd,
  910                     0, (u_char *)0);
  911         }
  912 
  913 #if 0
  914         /*
  915          * Change the bus on/off times to not clash with other DMA users.
  916          */
  917         aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
  918         aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
  919 #endif
  920 
  921         /* Inquire Installed Devices (to force synchronous negotiation). */
  922         devices.cmd.opcode = AHA_INQUIRE_DEVICES;
  923         aha_cmd(iot, ioh, sc,
  924             sizeof(devices.cmd), (u_char *)&devices.cmd,
  925             sizeof(devices.reply), (u_char *)&devices.reply);
  926 
  927         /* Count installed units */
  928         initial_ccbs = 0;
  929         for (i = 0; i < 8; i++) {
  930                 for (j = 0; j < 8; j++) {
  931                         if (((devices.reply.lun_map[i] >> j) & 1) == 1)
  932                                 initial_ccbs += 1;
  933                 }
  934         }
  935         initial_ccbs *= 2;
  936         if (initial_ccbs > AHA_CCB_MAX)
  937                 initial_ccbs = AHA_CCB_MAX;
  938         if (initial_ccbs == 0)  /* yes, this can happen */
  939                 initial_ccbs = 2;
  940 
  941         /* Obtain setup information from. */
  942         setup.cmd.opcode = AHA_INQUIRE_SETUP;
  943         setup.cmd.len = sizeof(setup.reply);
  944         aha_cmd(iot, ioh, sc,
  945             sizeof(setup.cmd), (u_char *)&setup.cmd,
  946             sizeof(setup.reply), (u_char *)&setup.reply);
  947 
  948         printf("%s: %s, %s\n",
  949             sc->sc_dev.dv_xname,
  950             setup.reply.sync_neg ? "sync" : "async",
  951             setup.reply.parity ? "parity" : "no parity");
  952 
  953         for (i = 0; i < 8; i++) {
  954                 if (!setup.reply.sync[i].valid ||
  955                     (!setup.reply.sync[i].offset && !setup.reply.sync[i].period))
  956                         continue;
  957                 printf("%s targ %d: sync, offset %d, period %dnsec\n",
  958                     sc->sc_dev.dv_xname, i,
  959                     setup.reply.sync[i].offset, setup.reply.sync[i].period * 50 + 200);
  960         }
  961 
  962         /*
  963          * Allocate the mailbox and control blocks.
  964          */
  965         if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct aha_control),
  966             PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
  967                 printf("%s: unable to allocate control structures, "
  968                     "error = %d\n", sc->sc_dev.dv_xname, error);
  969                 return (error);
  970         }
  971         if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
  972             sizeof(struct aha_control), (caddr_t *)&sc->sc_control,
  973             BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
  974                 printf("%s: unable to map control structures, error = %d\n",
  975                     sc->sc_dev.dv_xname, error);
  976                 return (error);
  977         }
  978 
  979         /*
  980          * Create and load the DMA map used for the mailbox and
  981          * control blocks.
  982          */
  983         if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_control),
  984             1, sizeof(struct aha_control), 0, BUS_DMA_NOWAIT,
  985             &sc->sc_dmamap_control)) != 0) {
  986                 printf("%s: unable to create control DMA map, error = %d\n",
  987                     sc->sc_dev.dv_xname, error);
  988                 return (error);
  989         }
  990         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,
  991             sc->sc_control, sizeof(struct aha_control), NULL,
  992             BUS_DMA_NOWAIT)) != 0) {
  993                 printf("%s: unable to load control DMA map, error = %d\n",
  994                     sc->sc_dev.dv_xname, error);
  995                 return (error);
  996         }
  997 
  998         /*
  999          * Initialize the control blocks.
 1000          */
 1001         i = aha_create_ccbs(sc, sc->sc_control->ac_ccbs, initial_ccbs);
 1002         if (i == 0) {
 1003                 printf("%s: unable to create control blocks\n",
 1004                     sc->sc_dev.dv_xname);
 1005                 return (ENOMEM);
 1006         } else if (i != initial_ccbs) {
 1007                 printf("%s: WARNING: only %d of %d control blocks created\n",
 1008                     sc->sc_dev.dv_xname, i, initial_ccbs);
 1009         }
 1010 
 1011         sc->sc_adapter.adapt_openings = i;
 1012         sc->sc_adapter.adapt_max_periph = sc->sc_adapter.adapt_openings;
 1013 
 1014         /*
 1015          * Set up initial mail box for round-robin operation.
 1016          */
 1017         for (i = 0; i < AHA_MBX_SIZE; i++) {
 1018                 wmbx->mbo[i].cmd = AHA_MBO_FREE;
 1019                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
 1020                     AHA_MBO_OFF(&wmbx->mbo[i]), sizeof(struct aha_mbx_out),
 1021                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 1022                 wmbx->mbi[i].stat = AHA_MBI_FREE;
 1023                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
 1024                     AHA_MBI_OFF(&wmbx->mbi[i]), sizeof(struct aha_mbx_in),
 1025                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 1026         }
 1027         wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
 1028         wmbx->tmbi = &wmbx->mbi[0];
 1029         sc->sc_mbofull = 0;
 1030 
 1031         /* Initialize mail box. */
 1032         mailbox.cmd.opcode = AHA_MBX_INIT;
 1033         mailbox.cmd.nmbx = AHA_MBX_SIZE;
 1034         ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
 1035             offsetof(struct aha_control, ac_mbx), mailbox.cmd.addr);
 1036         aha_cmd(iot, ioh, sc,
 1037             sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
 1038             0, (u_char *)0);
 1039         return (0);
 1040 }
 1041 
 1042 void
 1043 aha_inquire_setup_information(sc)
 1044         struct aha_softc *sc;
 1045 {
 1046         bus_space_tag_t iot = sc->sc_iot;
 1047         bus_space_handle_t ioh = sc->sc_ioh;
 1048         struct aha_revision revision;
 1049         u_char sts;
 1050         int i;
 1051         char *p;
 1052 
 1053         strcpy(sc->sc_model, "unknown");
 1054 
 1055         /*
 1056          * Assume we have a board at this stage, do an adapter inquire
 1057          * to find out what type of controller it is.  If the command
 1058          * fails, we assume it's either a crusty board or an old 1542
 1059          * clone, and skip the board-specific stuff.
 1060          */
 1061         revision.cmd.opcode = AHA_INQUIRE_REVISION;
 1062         if (aha_cmd(iot, ioh, sc,
 1063             sizeof(revision.cmd), (u_char *)&revision.cmd,
 1064             sizeof(revision.reply), (u_char *)&revision.reply)) {
 1065                 /*
 1066                  * aha_cmd() already started the reset.  It's not clear we
 1067                  * even need to bother here.
 1068                  */
 1069                 for (i = AHA_RESET_TIMEOUT; i; i--) {
 1070                         sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT);
 1071                         if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
 1072                                 break;
 1073                         delay(1000);
 1074                 }
 1075                 if (!i) {
 1076 #ifdef AHADEBUG
 1077                         printf("aha_init: soft reset failed\n");
 1078 #endif /* AHADEBUG */
 1079                         return;
 1080                 }
 1081 #ifdef AHADEBUG
 1082                 printf("aha_init: inquire command failed\n");
 1083 #endif /* AHADEBUG */
 1084                 goto noinquire;
 1085         }
 1086 
 1087 #ifdef AHADEBUG
 1088         printf("%s: inquire %x, %x, %x, %x\n",
 1089             sc->sc_dev.dv_xname,
 1090             revision.reply.boardid, revision.reply.spec_opts,
 1091             revision.reply.revision_1, revision.reply.revision_2);
 1092 #endif /* AHADEBUG */
 1093 
 1094         switch (revision.reply.boardid) {
 1095         case BOARD_1540_16HEAD_BIOS:
 1096         case BOARD_1540_64HEAD_BIOS:
 1097         case BOARD_1540:
 1098                 strcpy(sc->sc_model, "1540");
 1099                 break;
 1100         case BOARD_1542:
 1101                 strcpy(sc->sc_model, "1540A/1542A/1542B");
 1102                 break;
 1103         case BOARD_1640:
 1104                 strcpy(sc->sc_model, "1640");
 1105                 break;
 1106         case BOARD_1740:
 1107                 strcpy(sc->sc_model, "1740");
 1108                 break;
 1109         case BOARD_1542C:
 1110                 strcpy(sc->sc_model, "1542C");
 1111                 break;
 1112         case BOARD_1542CF:
 1113                 strcpy(sc->sc_model, "1542CF");
 1114                 break;
 1115         case BOARD_1542CP:
 1116                 strcpy(sc->sc_model, "1542CP");
 1117                 break;
 1118         }
 1119 
 1120         p = sc->sc_firmware;
 1121         *p++ = revision.reply.revision_1;
 1122         *p++ = '.';
 1123         *p++ = revision.reply.revision_2;
 1124         *p = '\0';
 1125 
 1126 noinquire:
 1127         printf("%s: model AHA-%s, firmware %s\n",
 1128                sc->sc_dev.dv_xname,
 1129                sc->sc_model, sc->sc_firmware);
 1130 }
 1131 
 1132 void
 1133 ahaminphys(bp)
 1134         struct buf *bp;
 1135 {
 1136 
 1137         if (bp->b_bcount > AHA_MAXXFER)
 1138                 bp->b_bcount = AHA_MAXXFER;
 1139         minphys(bp);
 1140 }
 1141 
 1142 /*
 1143  * start a scsi operation given the command and the data address. Also needs
 1144  * the unit, target and lu.
 1145  */
 1146 
 1147 void
 1148 aha_scsipi_request(chan, req, arg)
 1149         struct scsipi_channel *chan;
 1150         scsipi_adapter_req_t req;
 1151         void *arg;
 1152 {
 1153         struct scsipi_xfer *xs;
 1154         struct scsipi_periph *periph;
 1155         struct aha_softc *sc = (void *)chan->chan_adapter->adapt_dev;
 1156         bus_dma_tag_t dmat = sc->sc_dmat;
 1157         struct aha_ccb *ccb;
 1158         int error, seg, flags, s;
 1159 
 1160 
 1161         switch (req) {
 1162         case ADAPTER_REQ_RUN_XFER:
 1163                 xs = arg;
 1164                 periph = xs->xs_periph;
 1165                 flags = xs->xs_control;
 1166 
 1167                 SC_DEBUG(periph, SCSIPI_DB2, ("aha_scsipi_request\n"));
 1168 
 1169                 /* Get a CCB to use. */
 1170                 ccb = aha_get_ccb(sc);
 1171 #ifdef DIAGNOSTIC
 1172                 /*
 1173                  * This should never happen as we track the resources
 1174                  * in the mid-layer.
 1175                  */
 1176                 if (ccb == NULL) {
 1177                         scsipi_printaddr(periph);
 1178                         printf("unable to allocate ccb\n");
 1179                         panic("aha_scsipi_request");
 1180                 }
 1181 #endif
 1182 
 1183                 ccb->xs = xs;
 1184                 ccb->timeout = xs->timeout;
 1185 
 1186                 /*
 1187                  * Put all the arguments for the xfer in the ccb
 1188                  */
 1189                 if (flags & XS_CTL_RESET) {
 1190                         ccb->opcode = AHA_RESET_CCB;
 1191                         ccb->scsi_cmd_length = 0;
 1192                 } else {
 1193                         /* can't use S/G if zero length */
 1194                         ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB
 1195                                                    : AHA_INITIATOR_CCB);
 1196                         memcpy(&ccb->scsi_cmd, xs->cmd,
 1197                             ccb->scsi_cmd_length = xs->cmdlen);
 1198                 }
 1199 
 1200                 if (xs->datalen) {
 1201                         /*
 1202                          * Map the DMA transfer.
 1203                          */
 1204 #ifdef TFS
 1205                         if (flags & XS_CTL_DATA_UIO) {
 1206                                 error = bus_dmamap_load_uio(dmat,
 1207                                     ccb->dmamap_xfer, (struct uio *)xs->data,
 1208                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
 1209                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
 1210                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
 1211                                       BUS_DMA_WRITE));
 1212                         } else
 1213 #endif
 1214                         {
 1215                                 error = bus_dmamap_load(dmat,
 1216                                     ccb->dmamap_xfer, xs->data, xs->datalen,
 1217                                     NULL,
 1218                                     ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT :
 1219                                      BUS_DMA_WAITOK) | BUS_DMA_STREAMING |
 1220                                      ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ :
 1221                                       BUS_DMA_WRITE));
 1222                         }
 1223 
 1224                         switch (error) {
 1225                         case 0:
 1226                                 break;
 1227 
 1228                         case ENOMEM:
 1229                         case EAGAIN:
 1230                                 xs->error = XS_RESOURCE_SHORTAGE;
 1231                                 goto out_bad;
 1232 
 1233                         default:
 1234                                 xs->error = XS_DRIVER_STUFFUP;
 1235                                 if (error == EFBIG) {
 1236                                         printf("%s: aha_scsi_cmd, more than %d"
 1237                                             " DMA segments\n",
 1238                                             sc->sc_dev.dv_xname, AHA_NSEG);
 1239                                 } else {
 1240                                         printf("%s: error %d loading DMA map\n",
 1241                                             sc->sc_dev.dv_xname, error);
 1242                                 }
 1243 out_bad:
 1244                                 aha_free_ccb(sc, ccb);
 1245                                 scsipi_done(xs);
 1246                                 return;
 1247                         }
 1248 
 1249                         bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0,
 1250                             ccb->dmamap_xfer->dm_mapsize,
 1251                             (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
 1252                             BUS_DMASYNC_PREWRITE);
 1253 
 1254                         /*
 1255                          * Load the hardware scatter/gather map with the
 1256                          * contents of the DMA map.
 1257                          */
 1258                         for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
 1259                                 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
 1260                                     ccb->scat_gath[seg].seg_addr);
 1261                                 ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
 1262                                     ccb->scat_gath[seg].seg_len);
 1263                         }
 1264 
 1265                         ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
 1266                             AHA_CCB_OFF(ccb) +
 1267                             offsetof(struct aha_ccb, scat_gath),
 1268                             ccb->data_addr);
 1269                         ltophys(ccb->dmamap_xfer->dm_nsegs *
 1270                             sizeof(struct aha_scat_gath), ccb->data_length);
 1271                 } else {
 1272                         /*
 1273                          * No data xfer, use non S/G values.
 1274                          */
 1275                         ltophys(0, ccb->data_addr);
 1276                         ltophys(0, ccb->data_length);
 1277                 }
 1278 
 1279                 ccb->data_out = 0;
 1280                 ccb->data_in = 0;
 1281                 ccb->target = periph->periph_target;
 1282                 ccb->lun = periph->periph_lun;
 1283                 ccb->req_sense_length = sizeof(ccb->scsi_sense);
 1284                 ccb->host_stat = 0x00;
 1285                 ccb->target_stat = 0x00;
 1286                 ccb->link_id = 0;
 1287                 ltophys(0, ccb->link_addr);
 1288 
 1289                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
 1290                     AHA_CCB_OFF(ccb), sizeof(struct aha_ccb),
 1291                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 1292 
 1293                 s = splbio();
 1294                 aha_queue_ccb(sc, ccb);
 1295                 splx(s);
 1296 
 1297                 SC_DEBUG(periph, SCSIPI_DB3, ("cmd_sent\n"));
 1298                 if ((flags & XS_CTL_POLL) == 0)
 1299                         return;
 1300 
 1301                 /* Not allowed to use interrupts, poll for completion. */
 1302                 if (aha_poll(sc, xs, ccb->timeout)) {
 1303                         aha_timeout(ccb);
 1304                         if (aha_poll(sc, xs, ccb->timeout))
 1305                                 aha_timeout(ccb);
 1306                 }
 1307                 return;
 1308 
 1309         case ADAPTER_REQ_GROW_RESOURCES:
 1310                 /* XXX Not supported. */
 1311                 return;
 1312 
 1313         case ADAPTER_REQ_SET_XFER_MODE:
 1314                 /*
 1315                  * Can't really do this on the Adaptec; it has
 1316                  * its own config mechanism, but we do know how
 1317                  * to query what the firmware negotiated.
 1318                  */
 1319                 /* XXX XXX XXX */
 1320                 return;
 1321         }
 1322 }
 1323 
 1324 /*
 1325  * Poll a particular unit, looking for a particular xs
 1326  */
 1327 int
 1328 aha_poll(sc, xs, count)
 1329         struct aha_softc *sc;
 1330         struct scsipi_xfer *xs;
 1331         int count;
 1332 {
 1333         bus_space_tag_t iot = sc->sc_iot;
 1334         bus_space_handle_t ioh = sc->sc_ioh;
 1335 
 1336         /* timeouts are in msec, so we loop in 1000 usec cycles */
 1337         while (count) {
 1338                 /*
 1339                  * If we had interrupts enabled, would we
 1340                  * have got an interrupt?
 1341                  */
 1342                 if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) & AHA_INTR_ANYINTR)
 1343                         aha_intr(sc);
 1344                 if (xs->xs_status & XS_STS_DONE)
 1345                         return (0);
 1346                 delay(1000);    /* only happens in boot so ok */
 1347                 count--;
 1348         }
 1349         return (1);
 1350 }
 1351 
 1352 void
 1353 aha_timeout(arg)
 1354         void *arg;
 1355 {
 1356         struct aha_ccb *ccb = arg;
 1357         struct scsipi_xfer *xs = ccb->xs;
 1358         struct scsipi_periph *periph = xs->xs_periph;
 1359         struct aha_softc *sc =
 1360             (void *)periph->periph_channel->chan_adapter->adapt_dev;
 1361         int s;
 1362 
 1363         scsipi_printaddr(periph);
 1364         printf("timed out");
 1365 
 1366         s = splbio();
 1367 
 1368 #ifdef AHADIAG
 1369         /*
 1370          * If The ccb's mbx is not free, then the board has gone south?
 1371          */
 1372         aha_collect_mbo(sc);
 1373         if (ccb->flags & CCB_SENDING) {
 1374                 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
 1375                 Debugger();
 1376         }
 1377 #endif
 1378 
 1379         /*
 1380          * If it has been through before, then
 1381          * a previous abort has failed, don't
 1382          * try abort again
 1383          */
 1384         if (ccb->flags & CCB_ABORT) {
 1385                 /* abort timed out */
 1386                 printf(" AGAIN\n");
 1387                 /* XXX Must reset! */
 1388         } else {
 1389                 /* abort the operation that has timed out */
 1390                 printf("\n");
 1391                 ccb->xs->error = XS_TIMEOUT;
 1392                 ccb->timeout = AHA_ABORT_TIMEOUT;
 1393                 ccb->flags |= CCB_ABORT;
 1394                 aha_queue_ccb(sc, ccb);
 1395         }
 1396 
 1397         splx(s);
 1398 }

Cache object: fda1dafb0c3de179da94e61e20ab758e


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