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/eisa/ahb.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: ahb.c,v 1.39 2003/11/02 09:57:58 wiz Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
    9  * Simulation Facility, NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Originally written by Julian Elischer (julian@tfs.com)
   42  * for TRW Financial Systems for use under the MACH(2.5) operating system.
   43  *
   44  * TRW Financial Systems, in accordance with their agreement with Carnegie
   45  * Mellon University, makes this software available to CMU to distribute
   46  * or use in any manner that they see fit as long as this message is kept with
   47  * the software. For this reason TFS also grants any other persons or
   48  * organisations permission to use or modify this software.
   49  *
   50  * TFS supplies this software to be publicly redistributed
   51  * on the understanding that TFS is not responsible for the correct
   52  * functioning of this software in any circumstances.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __KERNEL_RCSID(0, "$NetBSD: ahb.c,v 1.39 2003/11/02 09:57:58 wiz Exp $");
   57 
   58 #include "opt_ddb.h"
   59 
   60 #undef  AHBDEBUG
   61 #ifdef DDB
   62 #define integrate
   63 #else
   64 #define integrate       static inline
   65 #endif
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/kernel.h>
   70 #include <sys/errno.h>
   71 #include <sys/ioctl.h>
   72 #include <sys/device.h>
   73 #include <sys/malloc.h>
   74 #include <sys/buf.h>
   75 #include <sys/proc.h>
   76 #include <sys/user.h>
   77 
   78 #include <uvm/uvm_extern.h>
   79 
   80 #include <machine/bus.h>
   81 #include <machine/intr.h>
   82 
   83 #include <dev/scsipi/scsi_all.h>
   84 #include <dev/scsipi/scsipi_all.h>
   85 #include <dev/scsipi/scsiconf.h>
   86 
   87 #include <dev/eisa/eisareg.h>
   88 #include <dev/eisa/eisavar.h>
   89 #include <dev/eisa/eisadevs.h>
   90 #include <dev/eisa/ahbreg.h>
   91 
   92 #ifndef DDB
   93 #define Debugger() panic("should call debugger here (aha1742.c)")
   94 #endif /* ! DDB */
   95 
   96 #define AHB_ECB_MAX     32      /* store up to 32 ECBs at one time */
   97 #define ECB_HASH_SIZE   32      /* hash table size for phystokv */
   98 #define ECB_HASH_SHIFT  9
   99 #define ECB_HASH(x)     ((((long)(x))>>ECB_HASH_SHIFT) & (ECB_HASH_SIZE - 1))
  100 
  101 #define AHB_MAXXFER     ((AHB_NSEG - 1) << PGSHIFT)
  102 
  103 struct ahb_softc {
  104         struct device sc_dev;
  105 
  106         bus_space_tag_t sc_iot;
  107         bus_space_handle_t sc_ioh;
  108         bus_dma_tag_t sc_dmat;
  109         void *sc_ih;
  110 
  111         bus_dmamap_t sc_dmamap_ecb;     /* maps the ecbs */
  112         struct ahb_ecb *sc_ecbs;        /* all our ecbs */
  113 
  114         struct ahb_ecb *sc_ecbhash[ECB_HASH_SIZE];
  115         TAILQ_HEAD(, ahb_ecb) sc_free_ecb;
  116         struct ahb_ecb *sc_immed_ecb;   /* an outstanding immediete command */
  117         int sc_numecbs;
  118 
  119         struct scsipi_adapter sc_adapter;
  120         struct scsipi_channel sc_channel;
  121 };
  122 
  123 /*
  124  * Offset of an ECB from the beginning of the ECB DMA mapping.
  125  */
  126 #define AHB_ECB_OFF(e)  (((u_long)(e)) - ((u_long)&sc->sc_ecbs[0]))
  127 
  128 struct ahb_probe_data {
  129         int sc_irq;
  130         int sc_scsi_dev;
  131 };
  132 
  133 void    ahb_send_mbox __P((struct ahb_softc *, int, struct ahb_ecb *));
  134 void    ahb_send_immed __P((struct ahb_softc *, u_int32_t, struct ahb_ecb *));
  135 int     ahbintr __P((void *));
  136 void    ahb_free_ecb __P((struct ahb_softc *, struct ahb_ecb *));
  137 struct  ahb_ecb *ahb_get_ecb __P((struct ahb_softc *));
  138 struct  ahb_ecb *ahb_ecb_phys_kv __P((struct ahb_softc *, physaddr));
  139 void    ahb_done __P((struct ahb_softc *, struct ahb_ecb *));
  140 int     ahb_find __P((bus_space_tag_t, bus_space_handle_t, struct ahb_probe_data *));
  141 int     ahb_init __P((struct ahb_softc *));
  142 void    ahbminphys __P((struct buf *));
  143 void    ahb_scsipi_request __P((struct scsipi_channel *,
  144             scsipi_adapter_req_t, void *));
  145 int     ahb_poll __P((struct ahb_softc *, struct scsipi_xfer *, int));
  146 void    ahb_timeout __P((void *));
  147 int     ahb_create_ecbs __P((struct ahb_softc *, struct ahb_ecb *, int));
  148 
  149 integrate void ahb_reset_ecb __P((struct ahb_softc *, struct ahb_ecb *));
  150 integrate int ahb_init_ecb __P((struct ahb_softc *, struct ahb_ecb *));
  151 
  152 int     ahbmatch __P((struct device *, struct cfdata *, void *));
  153 void    ahbattach __P((struct device *, struct device *, void *));
  154 
  155 CFATTACH_DECL(ahb, sizeof(struct ahb_softc),
  156     ahbmatch, ahbattach, NULL, NULL);
  157 
  158 #define AHB_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
  159 
  160 /*
  161  * Check the slots looking for a board we recognise
  162  * If we find one, note it's address (slot) and call
  163  * the actual probe routine to check it out.
  164  */
  165 int
  166 ahbmatch(parent, match, aux)
  167         struct device *parent;
  168         struct cfdata *match;
  169         void *aux;
  170 {
  171         struct eisa_attach_args *ea = aux;
  172         bus_space_tag_t iot = ea->ea_iot;
  173         bus_space_handle_t ioh;
  174         int rv;
  175 
  176         /* must match one of our known ID strings */
  177         if (strcmp(ea->ea_idstring, "ADP0000") &&
  178             strcmp(ea->ea_idstring, "ADP0001") &&
  179             strcmp(ea->ea_idstring, "ADP0002") &&
  180             strcmp(ea->ea_idstring, "ADP0400"))
  181                 return (0);
  182 
  183         if (bus_space_map(iot,
  184             EISA_SLOT_ADDR(ea->ea_slot) + AHB_EISA_SLOT_OFFSET, AHB_EISA_IOSIZE,
  185             0, &ioh))
  186                 return (0);
  187 
  188         rv = !ahb_find(iot, ioh, NULL);
  189 
  190         bus_space_unmap(iot, ioh, AHB_EISA_IOSIZE);
  191 
  192         return (rv);
  193 }
  194 
  195 /*
  196  * Attach all the sub-devices we can find
  197  */
  198 void
  199 ahbattach(parent, self, aux)
  200         struct device *parent, *self;
  201         void *aux;
  202 {
  203         struct eisa_attach_args *ea = aux;
  204         struct ahb_softc *sc = (void *)self;
  205         bus_space_tag_t iot = ea->ea_iot;
  206         bus_space_handle_t ioh;
  207         eisa_chipset_tag_t ec = ea->ea_ec;
  208         eisa_intr_handle_t ih;
  209         const char *model, *intrstr;
  210         struct ahb_probe_data apd;
  211         struct scsipi_adapter *adapt = &sc->sc_adapter;
  212         struct scsipi_channel *chan = &sc->sc_channel;
  213 
  214         if (!strcmp(ea->ea_idstring, "ADP0000"))
  215                 model = EISA_PRODUCT_ADP0000;
  216         else if (!strcmp(ea->ea_idstring, "ADP0001"))
  217                 model = EISA_PRODUCT_ADP0001;
  218         else if (!strcmp(ea->ea_idstring, "ADP0002"))
  219                 model = EISA_PRODUCT_ADP0002;
  220         else if (!strcmp(ea->ea_idstring, "ADP0400"))
  221                 model = EISA_PRODUCT_ADP0400;
  222         else
  223                 model = "unknown model!";
  224         printf(": %s\n", model);
  225 
  226         if (bus_space_map(iot,
  227             EISA_SLOT_ADDR(ea->ea_slot) + AHB_EISA_SLOT_OFFSET, AHB_EISA_IOSIZE,
  228             0, &ioh))
  229                 panic("ahbattach: could not map I/O addresses");
  230 
  231         sc->sc_iot = iot;
  232         sc->sc_ioh = ioh;
  233         sc->sc_dmat = ea->ea_dmat;
  234         if (ahb_find(iot, ioh, &apd))
  235                 panic("ahbattach: ahb_find failed!");
  236 
  237         TAILQ_INIT(&sc->sc_free_ecb);
  238 
  239         /*
  240          * Fill in the scsipi_adapter.
  241          */
  242         memset(adapt, 0, sizeof(*adapt));
  243         adapt->adapt_dev = &sc->sc_dev;
  244         adapt->adapt_nchannels = 1;
  245         /* adapt_openings initialized below */
  246         adapt->adapt_max_periph = 4;            /* XXX arbitrary? */
  247         adapt->adapt_request = ahb_scsipi_request;
  248         adapt->adapt_minphys = ahbminphys;
  249 
  250         /*
  251          * Fill in the scsipi_channel.
  252          */
  253         memset(chan, 0, sizeof(*chan));
  254         chan->chan_adapter = adapt;
  255         chan->chan_bustype = &scsi_bustype;
  256         chan->chan_channel = 0;
  257         chan->chan_ntargets = 8;
  258         chan->chan_nluns = 8;
  259         chan->chan_id = apd.sc_scsi_dev;
  260 
  261         if (ahb_init(sc) != 0) {
  262                 /* Error during initialization! */
  263                 return;
  264         }
  265 
  266         if (eisa_intr_map(ec, apd.sc_irq, &ih)) {
  267                 printf("%s: couldn't map interrupt (%d)\n",
  268                     sc->sc_dev.dv_xname, apd.sc_irq);
  269                 return;
  270         }
  271         intrstr = eisa_intr_string(ec, ih);
  272         sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
  273             ahbintr, sc);
  274         if (sc->sc_ih == NULL) {
  275                 printf("%s: couldn't establish interrupt",
  276                     sc->sc_dev.dv_xname);
  277                 if (intrstr != NULL)
  278                         printf(" at %s", intrstr);
  279                 printf("\n");
  280                 return;
  281         }
  282         if (intrstr != NULL)
  283                 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
  284                     intrstr);
  285 
  286         /*
  287          * ask the adapter what subunits are present
  288          */
  289         config_found(self, &sc->sc_channel, scsiprint);
  290 }
  291 
  292 /*
  293  * Function to send a command out through a mailbox
  294  */
  295 void
  296 ahb_send_mbox(sc, opcode, ecb)
  297         struct ahb_softc *sc;
  298         int opcode;
  299         struct ahb_ecb *ecb;
  300 {
  301         bus_space_tag_t iot = sc->sc_iot;
  302         bus_space_handle_t ioh = sc->sc_ioh;
  303         int wait = 300; /* 1ms should be enough */
  304 
  305         while (--wait) {
  306                 if ((bus_space_read_1(iot, ioh, G2STAT) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
  307                     == (G2STAT_MBOX_EMPTY))
  308                         break;
  309                 delay(10);
  310         }
  311         if (!wait) {
  312                 printf("%s: board not responding\n", sc->sc_dev.dv_xname);
  313                 Debugger();
  314         }
  315 
  316         /*
  317          * don't know if this will work.
  318          * XXX WHAT DOES THIS COMMENT MEAN?!  --thorpej
  319          */
  320         bus_space_write_4(iot, ioh, MBOXOUT0,
  321             sc->sc_dmamap_ecb->dm_segs[0].ds_addr + AHB_ECB_OFF(ecb));
  322         bus_space_write_1(iot, ioh, ATTN, opcode |
  323                 ecb->xs->xs_periph->periph_target);
  324 
  325         if ((ecb->xs->xs_control & XS_CTL_POLL) == 0)
  326                 callout_reset(&ecb->xs->xs_callout,
  327                     mstohz(ecb->timeout), ahb_timeout, ecb);
  328 }
  329 
  330 /*
  331  * Function to  send an immediate type command to the adapter
  332  */
  333 void
  334 ahb_send_immed(sc, cmd, ecb)
  335         struct ahb_softc *sc;
  336         u_int32_t cmd;
  337         struct ahb_ecb *ecb;
  338 {
  339         bus_space_tag_t iot = sc->sc_iot;
  340         bus_space_handle_t ioh = sc->sc_ioh;
  341         int wait = 100; /* 1 ms enough? */
  342 
  343         while (--wait) {
  344                 if ((bus_space_read_1(iot, ioh, G2STAT) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY))
  345                     == (G2STAT_MBOX_EMPTY))
  346                         break;
  347                 delay(10);
  348         }
  349         if (!wait) {
  350                 printf("%s: board not responding\n", sc->sc_dev.dv_xname);
  351                 Debugger();
  352         }
  353 
  354         bus_space_write_4(iot, ioh, MBOXOUT0, cmd);     /* don't know this will work */
  355         bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_SET_HOST_READY);
  356         bus_space_write_1(iot, ioh, ATTN, OP_IMMED |
  357                 ecb->xs->xs_periph->periph_target);
  358 
  359         if ((ecb->xs->xs_control & XS_CTL_POLL) == 0)
  360                 callout_reset(&ecb->xs->xs_callout,
  361                     mstohz(ecb->timeout), ahb_timeout, ecb);
  362 }
  363 
  364 /*
  365  * Catch an interrupt from the adaptor
  366  */
  367 int
  368 ahbintr(arg)
  369         void *arg;
  370 {
  371         struct ahb_softc *sc = arg;
  372         bus_space_tag_t iot = sc->sc_iot;
  373         bus_space_handle_t ioh = sc->sc_ioh;
  374         struct ahb_ecb *ecb;
  375         u_char ahbstat;
  376         u_int32_t mboxval;
  377 
  378 #ifdef  AHBDEBUG
  379         printf("%s: ahbintr ", sc->sc_dev.dv_xname);
  380 #endif /* AHBDEBUG */
  381 
  382         if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) == 0)
  383                 return 0;
  384 
  385         for (;;) {
  386                 /*
  387                  * First get all the information and then
  388                  * acknowledge the interrupt
  389                  */
  390                 ahbstat = bus_space_read_1(iot, ioh, G2INTST);
  391                 mboxval = bus_space_read_4(iot, ioh, MBOXIN0);
  392                 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
  393 
  394 #ifdef  AHBDEBUG
  395                 printf("status = 0x%x ", ahbstat);
  396 #endif /* AHBDEBUG */
  397 
  398                 /*
  399                  * Process the completed operation
  400                  */
  401                 switch (ahbstat & G2INTST_INT_STAT) {
  402                 case AHB_ECB_OK:
  403                 case AHB_ECB_RECOVERED:
  404                 case AHB_ECB_ERR:
  405                         ecb = ahb_ecb_phys_kv(sc, mboxval);
  406                         if (!ecb) {
  407                                 printf("%s: BAD ECB RETURNED!\n",
  408                                     sc->sc_dev.dv_xname);
  409                                 goto next;      /* whatever it was, it'll timeout */
  410                         }
  411                         break;
  412 
  413                 case AHB_IMMED_ERR:
  414                         ecb = sc->sc_immed_ecb;
  415                         sc->sc_immed_ecb = 0;
  416                         ecb->flags |= ECB_IMMED_FAIL;
  417                         break;
  418 
  419                 case AHB_IMMED_OK:
  420                         ecb = sc->sc_immed_ecb;
  421                         sc->sc_immed_ecb = 0;
  422                         break;
  423 
  424                 default:
  425                         printf("%s: unexpected interrupt %x\n",
  426                             sc->sc_dev.dv_xname, ahbstat);
  427                         goto next;
  428                 }
  429 
  430                 callout_stop(&ecb->xs->xs_callout);
  431                 ahb_done(sc, ecb);
  432 
  433         next:
  434                 if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) == 0)
  435                         return 1;
  436         }
  437 }
  438 
  439 integrate void
  440 ahb_reset_ecb(sc, ecb)
  441         struct ahb_softc *sc;
  442         struct ahb_ecb *ecb;
  443 {
  444 
  445         ecb->flags = 0;
  446 }
  447 
  448 /*
  449  * A ecb (and hence a mbx-out is put onto the
  450  * free list.
  451  */
  452 void
  453 ahb_free_ecb(sc, ecb)
  454         struct ahb_softc *sc;
  455         struct ahb_ecb *ecb;
  456 {
  457         int s;
  458 
  459         s = splbio();
  460         ahb_reset_ecb(sc, ecb);
  461         TAILQ_INSERT_HEAD(&sc->sc_free_ecb, ecb, chain);
  462         splx(s);
  463 }
  464 
  465 /*
  466  * Create a set of ecbs and add them to the free list.
  467  */
  468 integrate int
  469 ahb_init_ecb(sc, ecb)
  470         struct ahb_softc *sc;
  471         struct ahb_ecb *ecb;
  472 {
  473         bus_dma_tag_t dmat = sc->sc_dmat;
  474         int hashnum, error;
  475 
  476         /*
  477          * Create the DMA map for this ECB.
  478          */
  479         error = bus_dmamap_create(dmat, AHB_MAXXFER, AHB_NSEG, AHB_MAXXFER,
  480             0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ecb->dmamap_xfer);
  481         if (error) {
  482                 printf("%s: can't create ecb dmamap_xfer\n",
  483                     sc->sc_dev.dv_xname);
  484                 return (error);
  485         }
  486 
  487         /*
  488          * put in the phystokv hash table
  489          * Never gets taken out.
  490          */
  491         ecb->hashkey = sc->sc_dmamap_ecb->dm_segs[0].ds_addr +
  492             AHB_ECB_OFF(ecb);
  493         hashnum = ECB_HASH(ecb->hashkey);
  494         ecb->nexthash = sc->sc_ecbhash[hashnum];
  495         sc->sc_ecbhash[hashnum] = ecb;
  496         ahb_reset_ecb(sc, ecb);
  497         return (0);
  498 }
  499 
  500 int
  501 ahb_create_ecbs(sc, ecbstore, count)
  502         struct ahb_softc *sc;
  503         struct ahb_ecb *ecbstore;
  504         int count;
  505 {
  506         struct ahb_ecb *ecb;
  507         int i, error;
  508 
  509         bzero(ecbstore, sizeof(struct ahb_ecb) * count);
  510         for (i = 0; i < count; i++) {
  511                 ecb = &ecbstore[i];
  512                 if ((error = ahb_init_ecb(sc, ecb)) != 0) {
  513                         printf("%s: unable to initialize ecb, error = %d\n",
  514                             sc->sc_dev.dv_xname, error);
  515                         goto out;
  516                 }
  517                 TAILQ_INSERT_TAIL(&sc->sc_free_ecb, ecb, chain);
  518         }
  519  out:
  520         return (i);
  521 }
  522 
  523 /*
  524  * Get a free ecb
  525  *
  526  * If there are none, see if we can allocate a new one. If so, put it in the
  527  * hash table too otherwise either return an error or sleep.
  528  */
  529 struct ahb_ecb *
  530 ahb_get_ecb(sc)
  531         struct ahb_softc *sc;
  532 {
  533         struct ahb_ecb *ecb;
  534         int s;
  535 
  536         s = splbio();
  537         ecb = TAILQ_FIRST(&sc->sc_free_ecb);
  538         if (ecb != NULL) {
  539                 TAILQ_REMOVE(&sc->sc_free_ecb, ecb, chain);
  540                 ecb->flags |= ECB_ALLOC;
  541         }
  542         splx(s);
  543         return (ecb);
  544 }
  545 
  546 /*
  547  * given a physical address, find the ecb that it corresponds to.
  548  */
  549 struct ahb_ecb *
  550 ahb_ecb_phys_kv(sc, ecb_phys)
  551         struct ahb_softc *sc;
  552         physaddr ecb_phys;
  553 {
  554         int hashnum = ECB_HASH(ecb_phys);
  555         struct ahb_ecb *ecb = sc->sc_ecbhash[hashnum];
  556 
  557         while (ecb) {
  558                 if (ecb->hashkey == ecb_phys)
  559                         break;
  560                 ecb = ecb->nexthash;
  561         }
  562         return ecb;
  563 }
  564 
  565 /*
  566  * We have a ecb which has been processed by the adaptor, now we look to see
  567  * how the operation went.
  568  */
  569 void
  570 ahb_done(sc, ecb)
  571         struct ahb_softc *sc;
  572         struct ahb_ecb *ecb;
  573 {
  574         bus_dma_tag_t dmat = sc->sc_dmat;
  575         struct scsipi_sense_data *s1, *s2;
  576         struct scsipi_xfer *xs = ecb->xs;
  577 
  578         SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("ahb_done\n"));
  579 
  580         bus_dmamap_sync(dmat, sc->sc_dmamap_ecb,
  581             AHB_ECB_OFF(ecb), sizeof(struct ahb_ecb),
  582             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  583 
  584         /*
  585          * If we were a data transfer, unload the map that described
  586          * the data buffer.
  587          */
  588         if (xs->datalen) {
  589                 bus_dmamap_sync(dmat, ecb->dmamap_xfer, 0,
  590                     ecb->dmamap_xfer->dm_mapsize,
  591                     (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
  592                     BUS_DMASYNC_POSTWRITE);
  593                 bus_dmamap_unload(dmat, ecb->dmamap_xfer);
  594         }
  595 
  596         /*
  597          * Otherwise, put the results of the operation
  598          * into the xfer and call whoever started it
  599          */
  600         if ((ecb->flags & ECB_ALLOC) == 0) {
  601                 printf("%s: exiting ecb not allocated!\n", sc->sc_dev.dv_xname);
  602                 Debugger();
  603         }
  604         if (ecb->flags & ECB_IMMED) {
  605                 if (ecb->flags & ECB_IMMED_FAIL)
  606                         xs->error = XS_DRIVER_STUFFUP;
  607                 goto done;
  608         }
  609         if (xs->error == XS_NOERROR) {
  610                 if (ecb->ecb_status.host_stat != HS_OK) {
  611                         switch (ecb->ecb_status.host_stat) {
  612                         case HS_TIMED_OUT:      /* No response */
  613                                 xs->error = XS_SELTIMEOUT;
  614                                 break;
  615                         default:        /* Other scsi protocol messes */
  616                                 printf("%s: host_stat %x\n",
  617                                     sc->sc_dev.dv_xname, ecb->ecb_status.host_stat);
  618                                 xs->error = XS_DRIVER_STUFFUP;
  619                         }
  620                 } else if (ecb->ecb_status.target_stat != SCSI_OK) {
  621                         switch (ecb->ecb_status.target_stat) {
  622                         case SCSI_CHECK:
  623                                 s1 = &ecb->ecb_sense;
  624                                 s2 = &xs->sense.scsi_sense;
  625                                 *s2 = *s1;
  626                                 xs->error = XS_SENSE;
  627                                 break;
  628                         case SCSI_BUSY:
  629                                 xs->error = XS_BUSY;
  630                                 break;
  631                         default:
  632                                 printf("%s: target_stat %x\n",
  633                                     sc->sc_dev.dv_xname, ecb->ecb_status.target_stat);
  634                                 xs->error = XS_DRIVER_STUFFUP;
  635                         }
  636                 } else
  637                         xs->resid = 0;
  638         }
  639 done:
  640         ahb_free_ecb(sc, ecb);
  641         scsipi_done(xs);
  642 }
  643 
  644 /*
  645  * Start the board, ready for normal operation
  646  */
  647 int
  648 ahb_find(iot, ioh, sc)
  649         bus_space_tag_t iot;
  650         bus_space_handle_t ioh;
  651         struct ahb_probe_data *sc;
  652 {
  653         u_char intdef;
  654         int i, irq, busid;
  655         int wait = 1000;        /* 1 sec enough? */
  656 
  657         bus_space_write_1(iot, ioh, PORTADDR, PORTADDR_ENHANCED);
  658 
  659 #define NO_NO 1
  660 #ifdef NO_NO
  661         /*
  662          * reset board, If it doesn't respond, assume
  663          * that it's not there.. good for the probe
  664          */
  665         bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_HARD_RESET);
  666         delay(1000);
  667         bus_space_write_1(iot, ioh, G2CNTRL, 0);
  668         delay(10000);
  669         while (--wait) {
  670                 if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_BUSY) == 0)
  671                         break;
  672                 delay(1000);
  673         }
  674         if (!wait) {
  675 #ifdef  AHBDEBUG
  676                 printf("ahb_find: No answer from aha1742 board\n");
  677 #endif /* AHBDEBUG */
  678                 return ENXIO;
  679         }
  680         i = bus_space_read_1(iot, ioh, MBOXIN0);
  681         if (i) {
  682                 printf("self test failed, val = 0x%x\n", i);
  683                 return EIO;
  684         }
  685 
  686         /* Set it again, just to be sure. */
  687         bus_space_write_1(iot, ioh, PORTADDR, PORTADDR_ENHANCED);
  688 #endif
  689 
  690         while (bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) {
  691                 printf(".");
  692                 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
  693                 delay(10000);
  694         }
  695 
  696         intdef = bus_space_read_1(iot, ioh, INTDEF);
  697         switch (intdef & 0x07) {
  698         case INT9:
  699                 irq = 9;
  700                 break;
  701         case INT10:
  702                 irq = 10;
  703                 break;
  704         case INT11:
  705                 irq = 11;
  706                 break;
  707         case INT12:
  708                 irq = 12;
  709                 break;
  710         case INT14:
  711                 irq = 14;
  712                 break;
  713         case INT15:
  714                 irq = 15;
  715                 break;
  716         default:
  717                 printf("illegal int setting %x\n", intdef);
  718                 return EIO;
  719         }
  720 
  721         bus_space_write_1(iot, ioh, INTDEF, (intdef | INTEN));  /* make sure we can interrupt */
  722 
  723         /* who are we on the scsi bus? */
  724         busid = (bus_space_read_1(iot, ioh, SCSIDEF) & HSCSIID);
  725 
  726         /* if we want to return data, do so now */
  727         if (sc) {
  728                 sc->sc_irq = irq;
  729                 sc->sc_scsi_dev = busid;
  730         }
  731 
  732         /*
  733          * Note that we are going and return (to probe)
  734          */
  735         return 0;
  736 }
  737 
  738 int
  739 ahb_init(sc)
  740         struct ahb_softc *sc;
  741 {
  742         bus_dma_segment_t seg;
  743         int i, error, rseg;
  744 
  745 #define ECBSIZE         (AHB_ECB_MAX * sizeof(struct ahb_ecb))
  746 
  747         /*
  748          * Allocate the ECBs.
  749          */
  750         if ((error = bus_dmamem_alloc(sc->sc_dmat, ECBSIZE,
  751             PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
  752                 printf("%s: unable to allocate ecbs, error = %d\n",
  753                     sc->sc_dev.dv_xname, error);
  754                 return (error);
  755         }
  756         if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
  757             ECBSIZE, (caddr_t *)&sc->sc_ecbs,
  758             BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
  759                 printf("%s: unable to map ecbs, error = %d\n",
  760                     sc->sc_dev.dv_xname, error);
  761                 return (error);
  762         }
  763 
  764         /*
  765          * Create and load the DMA map used for the ecbs.
  766          */
  767         if ((error = bus_dmamap_create(sc->sc_dmat, ECBSIZE,
  768             1, ECBSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_ecb)) != 0) {
  769                 printf("%s: unable to create ecb DMA map, error = %d\n",
  770                     sc->sc_dev.dv_xname, error);
  771                 return (error);
  772         }
  773         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_ecb,
  774             sc->sc_ecbs, ECBSIZE, NULL, BUS_DMA_NOWAIT)) != 0) {
  775                 printf("%s: unable to load ecb DMA map, error = %d\n",
  776                     sc->sc_dev.dv_xname, error);
  777                 return (error);
  778         }
  779 
  780 #undef ECBSIZE
  781 
  782         /*
  783          * Initialize the ecbs.
  784          */
  785         i = ahb_create_ecbs(sc, sc->sc_ecbs, AHB_ECB_MAX);
  786         if (i == 0) {
  787                 printf("%s: unable to create ecbs\n",
  788                     sc->sc_dev.dv_xname);
  789                 return (ENOMEM);
  790         } else if (i != AHB_ECB_MAX) {
  791                 printf("%s: WARNING: only %d of %d ecbs created\n",
  792                     sc->sc_dev.dv_xname, i, AHB_ECB_MAX);
  793         }
  794 
  795         sc->sc_adapter.adapt_openings = i;
  796 
  797         return (0);
  798 }
  799 
  800 void
  801 ahbminphys(bp)
  802         struct buf *bp;
  803 {
  804 
  805         if (bp->b_bcount > AHB_MAXXFER)
  806                 bp->b_bcount = AHB_MAXXFER;
  807         minphys(bp);
  808 }
  809 
  810 /*
  811  * start a scsi operation given the command and the data address.  Also needs
  812  * the unit, target and lu.
  813  */
  814 void
  815 ahb_scsipi_request(chan, req, arg)
  816         struct scsipi_channel *chan;
  817         scsipi_adapter_req_t req;
  818         void *arg;
  819 {
  820         struct scsipi_xfer *xs;
  821         struct scsipi_periph *periph;
  822         struct ahb_softc *sc = (void *)chan->chan_adapter->adapt_dev;
  823         bus_dma_tag_t dmat = sc->sc_dmat;
  824         struct ahb_ecb *ecb;
  825         int error, seg, flags, s;
  826 
  827         switch (req) {
  828         case ADAPTER_REQ_RUN_XFER:
  829                 xs = arg;
  830                 periph = xs->xs_periph;
  831                 flags = xs->xs_control;
  832 
  833                 SC_DEBUG(periph, SCSIPI_DB2, ("ahb_scsipi_request\n"));
  834 
  835                 /* Get an ECB to use. */
  836                 ecb = ahb_get_ecb(sc);
  837 #ifdef DIAGNOSTIC
  838                 /*
  839                  * This should never happen as we track the resources
  840                  * in the mid-layer.
  841                  */
  842                 if (ecb == NULL) {
  843                         scsipi_printaddr(periph);
  844                         printf("unable to allocate ecb\n");
  845                         panic("ahb_scsipi_request");
  846                 }
  847 #endif
  848 
  849                 ecb->xs = xs;
  850                 ecb->timeout = xs->timeout;
  851 
  852                 /*
  853                  * If it's a reset, we need to do an 'immediate'
  854                  * command, and store its ecb for later
  855                  * if there is already an immediate waiting,
  856                  * then WE must wait
  857                  */
  858                 if (flags & XS_CTL_RESET) {
  859                         ecb->flags |= ECB_IMMED;
  860                         if (sc->sc_immed_ecb) {
  861                                 ahb_free_ecb(sc, ecb);
  862                                 xs->error = XS_BUSY;
  863                                 scsipi_done(xs);
  864                                 return;
  865                         }
  866                         sc->sc_immed_ecb = ecb;
  867 
  868                         s = splbio();
  869                         ahb_send_immed(sc, AHB_TARG_RESET, ecb);
  870                         splx(s);
  871 
  872                         if ((flags & XS_CTL_POLL) == 0)
  873                                 return;
  874 
  875                         /*
  876                          * If we can't use interrupts, poll on completion
  877                          */
  878                         if (ahb_poll(sc, xs, ecb->timeout))
  879                                 ahb_timeout(ecb);
  880                         return;
  881                 }
  882 
  883                 /*
  884                  * Put all the arguments for the xfer in the ecb
  885                  */
  886                 ecb->opcode = ECB_SCSI_OP;
  887                 ecb->opt1 = ECB_SES /*| ECB_DSB*/ | ECB_ARS;
  888                 ecb->opt2 = periph->periph_lun | ECB_NRB;
  889                 bcopy(xs->cmd, &ecb->scsi_cmd,
  890                     ecb->scsi_cmd_length = xs->cmdlen);
  891                 ecb->sense_ptr = sc->sc_dmamap_ecb->dm_segs[0].ds_addr +
  892                     AHB_ECB_OFF(ecb) + offsetof(struct ahb_ecb, ecb_sense);
  893                 ecb->req_sense_length = sizeof(ecb->ecb_sense);
  894                 ecb->status = sc->sc_dmamap_ecb->dm_segs[0].ds_addr +
  895                     AHB_ECB_OFF(ecb) + offsetof(struct ahb_ecb, ecb_status);
  896                 ecb->ecb_status.host_stat = 0x00;
  897                 ecb->ecb_status.target_stat = 0x00;
  898 
  899                 if (xs->datalen) {
  900                         /*
  901                          * Map the DMA transfer.
  902                          */
  903 #ifdef TFS
  904                         if (flags & XS_CTL_DATA_UIO) {
  905                                 error = bus_dmamap_load_uio(sc->sc_dmat,
  906                                     ecb->dmamap_xfer, (struct uio *)xs->data,
  907                                     BUS_DMA_NOWAIT);
  908                         } else
  909 #endif /* TFS */
  910                         {
  911                                 error = bus_dmamap_load(sc->sc_dmat,
  912                                     ecb->dmamap_xfer, xs->data, xs->datalen,
  913                                     NULL, BUS_DMA_NOWAIT);
  914                         }
  915 
  916                         switch (error) {
  917                         case 0:
  918                                 break;
  919 
  920                         case ENOMEM:
  921                         case EAGAIN:
  922                                 xs->error = XS_RESOURCE_SHORTAGE;
  923                                 goto out_bad;
  924 
  925                         default:
  926                                 xs->error = XS_DRIVER_STUFFUP;
  927                                 printf("%s: error %d loading DMA map\n",
  928                                     sc->sc_dev.dv_xname, error);
  929  out_bad:
  930                                 ahb_free_ecb(sc, ecb);
  931                                 scsipi_done(xs);
  932                                 return;
  933                         }
  934 
  935                         bus_dmamap_sync(dmat, ecb->dmamap_xfer, 0,
  936                             ecb->dmamap_xfer->dm_mapsize,
  937                             (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
  938                             BUS_DMASYNC_PREWRITE);
  939 
  940                         /*
  941                          * Load the hardware scatter/gather map with the
  942                          * contents of the DMA map.
  943                          */
  944                         for (seg = 0; seg < ecb->dmamap_xfer->dm_nsegs; seg++) {
  945                                 ecb->ahb_dma[seg].seg_addr =
  946                                     ecb->dmamap_xfer->dm_segs[seg].ds_addr;
  947                                 ecb->ahb_dma[seg].seg_len =
  948                                     ecb->dmamap_xfer->dm_segs[seg].ds_len;
  949                         }
  950 
  951                         ecb->data_addr = sc->sc_dmamap_ecb->dm_segs[0].ds_addr +
  952                             AHB_ECB_OFF(ecb) +
  953                             offsetof(struct ahb_ecb, ahb_dma);
  954                         ecb->data_length = ecb->dmamap_xfer->dm_nsegs *
  955                             sizeof(struct ahb_dma_seg);
  956                         ecb->opt1 |= ECB_S_G;
  957                 } else {        /* No data xfer, use non S/G values */
  958                         ecb->data_addr = (physaddr)0;
  959                         ecb->data_length = 0;
  960                 }
  961                 ecb->link_addr = (physaddr)0;
  962 
  963                 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ecb,
  964                     AHB_ECB_OFF(ecb), sizeof(struct ahb_ecb),
  965                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  966 
  967                 s = splbio();
  968                 ahb_send_mbox(sc, OP_START_ECB, ecb);
  969                 splx(s);
  970 
  971                 if ((flags & XS_CTL_POLL) == 0)
  972                         return;
  973 
  974                 /*
  975                  * If we can't use interrupts, poll on completion
  976                  */
  977                 if (ahb_poll(sc, xs, ecb->timeout)) {
  978                         ahb_timeout(ecb);
  979                         if (ahb_poll(sc, xs, ecb->timeout))
  980                                 ahb_timeout(ecb);
  981                 }
  982                 return;
  983 
  984         case ADAPTER_REQ_GROW_RESOURCES:
  985                 /* XXX Not supported. */
  986                 return;
  987 
  988         case ADAPTER_REQ_SET_XFER_MODE:
  989                 /* XXX How do we do this? */
  990                 return;
  991         }
  992 }
  993 
  994 /*
  995  * Function to poll for command completion when in poll mode
  996  */
  997 int
  998 ahb_poll(sc, xs, count)
  999         struct ahb_softc *sc;
 1000         struct scsipi_xfer *xs;
 1001         int count;
 1002 {                               /* in msec  */
 1003         bus_space_tag_t iot = sc->sc_iot;
 1004         bus_space_handle_t ioh = sc->sc_ioh;
 1005 
 1006         while (count) {
 1007                 /*
 1008                  * If we had interrupts enabled, would we
 1009                  * have got an interrupt?
 1010                  */
 1011                 if (bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND)
 1012                         ahbintr(sc);
 1013                 if (xs->xs_status & XS_STS_DONE)
 1014                         return 0;
 1015                 delay(1000);
 1016                 count--;
 1017         }
 1018         return 1;
 1019 }
 1020 
 1021 void
 1022 ahb_timeout(arg)
 1023         void *arg;
 1024 {
 1025         struct ahb_ecb *ecb = arg;
 1026         struct scsipi_xfer *xs = ecb->xs;
 1027         struct scsipi_periph *periph = xs->xs_periph;
 1028         struct ahb_softc *sc =
 1029             (void *)periph->periph_channel->chan_adapter->adapt_dev;
 1030         int s;
 1031 
 1032         scsipi_printaddr(periph);
 1033         printf("timed out");
 1034 
 1035         s = splbio();
 1036 
 1037         if (ecb->flags & ECB_IMMED) {
 1038                 printf("\n");
 1039                 ecb->flags |= ECB_IMMED_FAIL;
 1040                 /* XXX Must reset! */
 1041         } else
 1042 
 1043         /*
 1044          * If it has been through before, then
 1045          * a previous abort has failed, don't
 1046          * try abort again
 1047          */
 1048         if (ecb->flags & ECB_ABORT) {
 1049                 /* abort timed out */
 1050                 printf(" AGAIN\n");
 1051                 /* XXX Must reset! */
 1052         } else {
 1053                 /* abort the operation that has timed out */
 1054                 printf("\n");
 1055                 ecb->xs->error = XS_TIMEOUT;
 1056                 ecb->timeout = AHB_ABORT_TIMEOUT;
 1057                 ecb->flags |= ECB_ABORT;
 1058                 ahb_send_mbox(sc, OP_ABORT_ECB, ecb);
 1059         }
 1060 
 1061         splx(s);
 1062 }

Cache object: 0db6f407a8a84e60196b9cf8541e0789


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