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

Cache object: 7e4b506715413f7b5abbe28d2136f281


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