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

Cache object: 715fabc6f633af834b202a033de052cb


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