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/isa/uha_isa.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 /*      $OpenBSD: uha_isa.c,v 1.15 2022/04/06 18:59:29 naddy Exp $      */
    2 /*      $NetBSD: uha_isa.c,v 1.5 1996/10/21 22:41:21 thorpej Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1994, 1996 Charles M. Hannum.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Charles M. Hannum.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/device.h>
   36 #include <sys/kernel.h>
   37 #include <uvm/uvm_extern.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/intr.h>
   41 
   42 #include <scsi/scsi_all.h>
   43 #include <scsi/scsiconf.h>
   44 
   45 #include <dev/isa/isavar.h>
   46 #include <dev/isa/isadmavar.h>
   47 
   48 #include <dev/ic/uhareg.h>
   49 #include <dev/ic/uhavar.h>
   50 
   51 #define UHA_ISA_IOSIZE  16
   52 
   53 int     uha_isa_probe(struct device *, void *, void *);
   54 void    uha_isa_attach(struct device *, struct device *, void *);
   55 
   56 const struct cfattach uha_isa_ca = {
   57         sizeof(struct uha_softc), uha_isa_probe, uha_isa_attach
   58 };
   59 
   60 #define KVTOPHYS(x)     vtophys((vaddr_t)(x))
   61 
   62 int u14_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
   63 void u14_start_mbox(struct uha_softc *, struct uha_mscp *);
   64 int u14_poll(struct uha_softc *, struct scsi_xfer *, int);
   65 int u14_intr(void *);
   66 void u14_init(struct uha_softc *);
   67 
   68 /*
   69  * Check the slots looking for a board we recognise
   70  * If we find one, note its address (slot) and call
   71  * the actual probe routine to check it out.
   72  */
   73 int
   74 uha_isa_probe(struct device *parent, void *match, void *aux)
   75 {
   76         struct isa_attach_args *ia = aux;
   77         struct uha_softc sc;
   78         bus_space_tag_t iot = ia->ia_iot;
   79         bus_space_handle_t ioh;
   80         int rv;
   81 
   82         if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
   83                 return (0);
   84 
   85         rv = u14_find(iot, ioh, &sc);
   86 
   87         bus_space_unmap(iot, ioh, UHA_ISA_IOSIZE);
   88 
   89         if (rv) {
   90                 if (ia->ia_irq != -1 && ia->ia_irq != sc.sc_irq)
   91                         return (0);
   92                 if (ia->ia_drq != -1 && ia->ia_drq != sc.sc_drq)
   93                         return (0);
   94                 ia->ia_irq = sc.sc_irq;
   95                 ia->ia_drq = sc.sc_drq;
   96                 ia->ia_msize = 0;
   97                 ia->ia_iosize = UHA_ISA_IOSIZE;
   98         }
   99         return (rv);
  100 }
  101 
  102 /*
  103  * Attach all the sub-devices we can find
  104  */
  105 void
  106 uha_isa_attach(struct device *parent, struct device *self, void *aux)
  107 {
  108         struct isa_attach_args *ia = aux;
  109         struct uha_softc *sc = (void *)self;
  110         bus_space_tag_t iot = ia->ia_iot;
  111         bus_space_handle_t ioh;
  112         isa_chipset_tag_t ic = ia->ia_ic;
  113 
  114         printf("\n");
  115 
  116         if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
  117                 panic("uha_attach: bus_space_map failed!");
  118 
  119         sc->sc_iot = iot;
  120         sc->sc_ioh = ioh;
  121         if (!u14_find(iot, ioh, sc))
  122                 panic("uha_attach: u14_find failed!");
  123 
  124         if (sc->sc_drq != -1)
  125                 isadma_cascade(sc->sc_drq);
  126 
  127         sc->sc_ih = isa_intr_establish(ic, sc->sc_irq, IST_EDGE, IPL_BIO,
  128             u14_intr, sc, sc->sc_dev.dv_xname);
  129         if (sc->sc_ih == NULL) {
  130                 printf("%s: couldn't establish interrupt\n",
  131                     sc->sc_dev.dv_xname);
  132                 return;
  133         }
  134 
  135         /* Save function pointers for later use. */
  136         sc->start_mbox = u14_start_mbox;
  137         sc->poll = u14_poll;
  138         sc->init = u14_init;
  139 
  140         uha_attach(sc);
  141 }
  142 
  143 /*
  144  * Start the board, ready for normal operation
  145  */
  146 int
  147 u14_find(bus_space_tag_t iot, bus_space_handle_t ioh, struct uha_softc *sc)
  148 {
  149         u_int16_t model, config;
  150         int irq, drq;
  151         int resetcount = 4000;  /* 4 secs? */
  152 
  153         model = (bus_space_read_1(iot, ioh, U14_ID + 0) << 8) |
  154                 (bus_space_read_1(iot, ioh, U14_ID + 1) << 0);
  155         if ((model & 0xfff0) != 0x5640)
  156                 return (0);
  157 
  158         config = (bus_space_read_1(iot, ioh, U14_CONFIG + 0) << 8) |
  159                  (bus_space_read_1(iot, ioh, U14_CONFIG + 1) << 0);
  160 
  161         switch (model & 0x000f) {
  162         case 0x0000:
  163                 switch (config & U14_DMA_MASK) {
  164                 case U14_DMA_CH5:
  165                         drq = 5;
  166                         break;
  167                 case U14_DMA_CH6:
  168                         drq = 6;
  169                         break;
  170                 case U14_DMA_CH7:
  171                         drq = 7;
  172                         break;
  173                 default:
  174                         printf("u14_find: illegal drq setting %x\n",
  175                             config & U14_DMA_MASK);
  176                         return (0);
  177                 }
  178                 break;
  179         case 0x0001:
  180                 /* This is a 34f, and doesn't need an ISA DMA channel. */
  181                 drq = -1;
  182                 break;
  183         default:
  184                 printf("u14_find: unknown model %x\n", model);
  185                 return (0);
  186         }
  187 
  188         switch (config & U14_IRQ_MASK) {
  189         case U14_IRQ10:
  190                 irq = 10;
  191                 break;
  192         case U14_IRQ11:
  193                 irq = 11;
  194                 break;
  195         case U14_IRQ14:
  196                 irq = 14;
  197                 break;
  198         case U14_IRQ15:
  199                 irq = 15;
  200                 break;
  201         default:
  202                 printf("u14_find: illegal irq setting %x\n",
  203                     config & U14_IRQ_MASK);
  204                 return (0);
  205         }
  206 
  207         bus_space_write_1(iot, ioh, U14_LINT, UHA_ASRST);
  208 
  209         while (--resetcount) {
  210                 if (bus_space_read_1(iot, ioh, U14_LINT))
  211                         break;
  212                 delay(1000);    /* 1 mSec per loop */
  213         }
  214         if (!resetcount) {
  215                 printf("u14_find: board timed out during reset\n");
  216                 return (0);
  217         }
  218 
  219         /* if we want to fill in softc, do so now */
  220         if (sc != NULL) {
  221                 sc->sc_irq = irq;
  222                 sc->sc_drq = drq;
  223                 sc->sc_scsi_dev = config & U14_HOSTID_MASK;
  224         }
  225 
  226         return (1);
  227 }
  228 
  229 /*
  230  * Function to send a command out through a mailbox
  231  */
  232 void
  233 u14_start_mbox(struct uha_softc *sc, struct uha_mscp *mscp)
  234 {
  235         bus_space_tag_t iot = sc->sc_iot;
  236         bus_space_handle_t ioh = sc->sc_ioh;
  237         int spincount = 100000; /* 1s should be enough */
  238 
  239         while (--spincount) {
  240                 if ((bus_space_read_1(iot, ioh, U14_LINT) & U14_LDIP) == 0)
  241                         break;
  242                 delay(100);
  243         }
  244         if (!spincount)
  245                 panic("%s: uha_start_mbox, board not responding",
  246                     sc->sc_dev.dv_xname);
  247 
  248         bus_space_write_4(iot, ioh, U14_OGMPTR, KVTOPHYS(mscp));
  249         if (mscp->flags & MSCP_ABORT)
  250                 bus_space_write_1(iot, ioh, U14_LINT, U14_ABORT);
  251         else
  252                 bus_space_write_1(iot, ioh, U14_LINT, U14_OGMFULL);
  253 
  254         if ((mscp->xs->flags & SCSI_POLL) == 0)
  255                 timeout_add_msec(&mscp->xs->stimeout, mscp->timeout);
  256 }
  257 
  258 /*
  259  * Function to poll for command completion when in poll mode.
  260  *
  261  *      wait = timeout in msec
  262  */
  263 int
  264 u14_poll(struct uha_softc *sc, struct scsi_xfer *xs, int count)
  265 {
  266         bus_space_tag_t iot = sc->sc_iot;
  267         bus_space_handle_t ioh = sc->sc_ioh;
  268 
  269         while (count) {
  270                 /*
  271                  * If we had interrupts enabled, would we
  272                  * have got an interrupt?
  273                  */
  274                 if (bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP)
  275                         u14_intr(sc);
  276                 if (xs->flags & ITSDONE)
  277                         return (0);
  278                 delay(1000);
  279                 count--;
  280         }
  281         return (1);
  282 }
  283 
  284 /*
  285  * Catch an interrupt from the adaptor
  286  */
  287 int
  288 u14_intr(void *arg)
  289 {
  290         struct uha_softc *sc = arg;
  291         bus_space_tag_t iot = sc->sc_iot;
  292         bus_space_handle_t ioh = sc->sc_ioh;
  293         struct uha_mscp *mscp;
  294         u_char uhastat;
  295         u_long mboxval;
  296 
  297 #ifdef  UHADEBUG
  298         printf("%s: uhaintr ", sc->sc_dev.dv_xname);
  299 #endif /*UHADEBUG */
  300 
  301         if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
  302                 return (0);
  303 
  304         for (;;) {
  305                 /*
  306                  * First get all the information and then
  307                  * acknowledge the interrupt
  308                  */
  309                 uhastat = bus_space_read_1(iot, ioh, U14_SINT);
  310                 mboxval = bus_space_read_4(iot, ioh, U14_ICMPTR);
  311                 /* XXX Send an ABORT_ACK instead? */
  312                 bus_space_write_1(iot, ioh, U14_SINT, U14_ICM_ACK);
  313 
  314 #ifdef  UHADEBUG
  315                 printf("status = 0x%x ", uhastat);
  316 #endif /*UHADEBUG*/
  317 
  318                 /*
  319                  * Process the completed operation
  320                  */
  321                 mscp = uha_mscp_phys_kv(sc, mboxval);
  322                 if (!mscp) {
  323                         printf("%s: BAD MSCP RETURNED!\n",
  324                             sc->sc_dev.dv_xname);
  325                         continue;       /* whatever it was, it'll timeout */
  326                 }
  327 
  328                 timeout_del(&mscp->xs->stimeout);
  329                 uha_done(sc, mscp);
  330 
  331                 if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
  332                         return (1);
  333         }
  334 }
  335 
  336 void
  337 u14_init(struct uha_softc *sc)
  338 {
  339         bus_space_tag_t iot = sc->sc_iot;
  340         bus_space_handle_t ioh = sc->sc_ioh;
  341 
  342         /* make sure interrupts are enabled */
  343 #ifdef UHADEBUG
  344         printf("u14_init: lmask=%02x, smask=%02x\n",
  345             bus_space_read_1(iot, ioh, U14_LMASK),
  346             bus_space_read_1(iot, ioh, U14_SMASK));
  347 #endif
  348         bus_space_write_1(iot, ioh, U14_LMASK, 0xd1);   /* XXX */
  349         bus_space_write_1(iot, ioh, U14_SMASK, 0x91);   /* XXX */
  350 }

Cache object: fc28175a4e10a2db9cb03ca82caad5f0


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