root/dev/isa/uha_isa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uha_isa_probe
  2. uha_isa_attach
  3. u14_find
  4. u14_start_mbox
  5. u14_poll
  6. u14_intr
  7. u14_init

    1 /*      $OpenBSD: uha_isa.c,v 1.8 2007/04/10 17:47:55 miod 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/types.h>
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/device.h>
   37 #include <sys/kernel.h>
   38 #include <sys/proc.h>
   39 #include <sys/user.h>
   40 
   41 #include <machine/bus.h>
   42 #include <machine/intr.h>
   43 
   44 #include <scsi/scsi_all.h>
   45 #include <scsi/scsiconf.h>
   46 
   47 #include <dev/isa/isavar.h>
   48 #include <dev/isa/isadmavar.h>
   49 
   50 #include <dev/ic/uhareg.h>
   51 #include <dev/ic/uhavar.h>
   52 
   53 #define UHA_ISA_IOSIZE  16
   54 
   55 #ifndef DDB
   56 #define Debugger() panic("should call debugger here (uha_isa.c)")
   57 #endif
   58 
   59 int     uha_isa_probe(struct device *, void *, void *);
   60 void    uha_isa_attach(struct device *, struct device *, void *);
   61 
   62 struct cfattach uha_isa_ca = {
   63         sizeof(struct uha_softc), uha_isa_probe, uha_isa_attach
   64 };
   65 
   66 #define KVTOPHYS(x)     vtophys((vaddr_t)(x))
   67 
   68 int u14_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
   69 void u14_start_mbox(struct uha_softc *, struct uha_mscp *);
   70 int u14_poll(struct uha_softc *, struct scsi_xfer *, int);
   71 int u14_intr(void *);
   72 void u14_init(struct uha_softc *);
   73 
   74 /*
   75  * Check the slots looking for a board we recognise
   76  * If we find one, note its address (slot) and call
   77  * the actual probe routine to check it out.
   78  */
   79 int
   80 uha_isa_probe(parent, match, aux)
   81         struct device *parent;
   82         void *match, *aux;
   83 {
   84         struct isa_attach_args *ia = aux;
   85         struct uha_softc sc;
   86         bus_space_tag_t iot = ia->ia_iot;
   87         bus_space_handle_t ioh;
   88         int rv;
   89 
   90         if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
   91                 return (0);
   92 
   93         rv = u14_find(iot, ioh, &sc);
   94 
   95         bus_space_unmap(iot, ioh, UHA_ISA_IOSIZE);
   96 
   97         if (rv) {
   98                 if (ia->ia_irq != -1 && ia->ia_irq != sc.sc_irq)
   99                         return (0);
  100                 if (ia->ia_drq != -1 && ia->ia_drq != sc.sc_drq)
  101                         return (0);
  102                 ia->ia_irq = sc.sc_irq;
  103                 ia->ia_drq = sc.sc_drq;
  104                 ia->ia_msize = 0;
  105                 ia->ia_iosize = UHA_ISA_IOSIZE;
  106         }
  107         return (rv);
  108 }
  109 
  110 /*
  111  * Attach all the sub-devices we can find
  112  */
  113 void
  114 uha_isa_attach(parent, self, aux)
  115         struct device *parent, *self;
  116         void *aux;
  117 {
  118         struct isa_attach_args *ia = aux;
  119         struct uha_softc *sc = (void *)self;
  120         bus_space_tag_t iot = ia->ia_iot;
  121         bus_space_handle_t ioh;
  122         isa_chipset_tag_t ic = ia->ia_ic;
  123 
  124         printf("\n");
  125 
  126         if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
  127                 panic("uha_attach: bus_space_map failed!");
  128 
  129         sc->sc_iot = iot;
  130         sc->sc_ioh = ioh;
  131         if (!u14_find(iot, ioh, sc))
  132                 panic("uha_attach: u14_find failed!");
  133 
  134         if (sc->sc_drq != -1)
  135                 isadma_cascade(sc->sc_drq);
  136 
  137         sc->sc_ih = isa_intr_establish(ic, sc->sc_irq, IST_EDGE, IPL_BIO,
  138             u14_intr, sc, sc->sc_dev.dv_xname);
  139         if (sc->sc_ih == NULL) {
  140                 printf("%s: couldn't establish interrupt\n",
  141                     sc->sc_dev.dv_xname);
  142                 return;
  143         }
  144 
  145         /* Save function pointers for later use. */
  146         sc->start_mbox = u14_start_mbox;
  147         sc->poll = u14_poll;
  148         sc->init = u14_init;
  149 
  150         uha_attach(sc);
  151 }
  152 
  153 /*
  154  * Start the board, ready for normal operation
  155  */
  156 int
  157 u14_find(iot, ioh, sc)
  158         bus_space_tag_t iot;
  159         bus_space_handle_t ioh;
  160         struct uha_softc *sc;
  161 {
  162         u_int16_t model, config;
  163         int irq, drq;
  164         int resetcount = 4000;  /* 4 secs? */
  165 
  166         model = (bus_space_read_1(iot, ioh, U14_ID + 0) << 8) |
  167                 (bus_space_read_1(iot, ioh, U14_ID + 1) << 0);
  168         if ((model & 0xfff0) != 0x5640)
  169                 return (0);
  170 
  171         config = (bus_space_read_1(iot, ioh, U14_CONFIG + 0) << 8) |
  172                  (bus_space_read_1(iot, ioh, U14_CONFIG + 1) << 0);
  173 
  174         switch (model & 0x000f) {
  175         case 0x0000:
  176                 switch (config & U14_DMA_MASK) {
  177                 case U14_DMA_CH5:
  178                         drq = 5;
  179                         break;
  180                 case U14_DMA_CH6:
  181                         drq = 6;
  182                         break;
  183                 case U14_DMA_CH7:
  184                         drq = 7;
  185                         break;
  186                 default:
  187                         printf("u14_find: illegal drq setting %x\n",
  188                             config & U14_DMA_MASK);
  189                         return (0);
  190                 }
  191                 break;
  192         case 0x0001:
  193                 /* This is a 34f, and doesn't need an ISA DMA channel. */
  194                 drq = -1;
  195                 break;
  196         default:
  197                 printf("u14_find: unknown model %x\n", model);
  198                 return (0);
  199         }
  200 
  201         switch (config & U14_IRQ_MASK) {
  202         case U14_IRQ10:
  203                 irq = 10;
  204                 break;
  205         case U14_IRQ11:
  206                 irq = 11;
  207                 break;
  208         case U14_IRQ14:
  209                 irq = 14;
  210                 break;
  211         case U14_IRQ15:
  212                 irq = 15;
  213                 break;
  214         default:
  215                 printf("u14_find: illegal irq setting %x\n",
  216                     config & U14_IRQ_MASK);
  217                 return (0);
  218         }
  219 
  220         bus_space_write_1(iot, ioh, U14_LINT, UHA_ASRST);
  221 
  222         while (--resetcount) {
  223                 if (bus_space_read_1(iot, ioh, U14_LINT))
  224                         break;
  225                 delay(1000);    /* 1 mSec per loop */
  226         }
  227         if (!resetcount) {
  228                 printf("u14_find: board timed out during reset\n");
  229                 return (0);
  230         }
  231 
  232         /* if we want to fill in softc, do so now */
  233         if (sc != NULL) {
  234                 sc->sc_irq = irq;
  235                 sc->sc_drq = drq;
  236                 sc->sc_scsi_dev = config & U14_HOSTID_MASK;
  237         }
  238 
  239         return (1);
  240 }
  241 
  242 /*
  243  * Function to send a command out through a mailbox
  244  */
  245 void
  246 u14_start_mbox(sc, mscp)
  247         struct uha_softc *sc;
  248         struct uha_mscp *mscp;
  249 {
  250         bus_space_tag_t iot = sc->sc_iot;
  251         bus_space_handle_t ioh = sc->sc_ioh;
  252         int spincount = 100000; /* 1s should be enough */
  253 
  254         while (--spincount) {
  255                 if ((bus_space_read_1(iot, ioh, U14_LINT) & U14_LDIP) == 0)
  256                         break;
  257                 delay(100);
  258         }
  259         if (!spincount) {
  260                 printf("%s: uha_start_mbox, board not responding\n",
  261                     sc->sc_dev.dv_xname);
  262                 Debugger();
  263         }
  264 
  265         bus_space_write_4(iot, ioh, U14_OGMPTR, KVTOPHYS(mscp));
  266         if (mscp->flags & MSCP_ABORT)
  267                 bus_space_write_1(iot, ioh, U14_LINT, U14_ABORT);
  268         else
  269                 bus_space_write_1(iot, ioh, U14_LINT, U14_OGMFULL);
  270 
  271         if ((mscp->xs->flags & SCSI_POLL) == 0)
  272                 timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
  273 }
  274 
  275 /*
  276  * Function to poll for command completion when in poll mode.
  277  *
  278  *      wait = timeout in msec
  279  */
  280 int
  281 u14_poll(sc, xs, count)
  282         struct uha_softc *sc;
  283         struct scsi_xfer *xs;
  284         int count;
  285 {
  286         bus_space_tag_t iot = sc->sc_iot;
  287         bus_space_handle_t ioh = sc->sc_ioh;
  288 
  289         while (count) {
  290                 /*
  291                  * If we had interrupts enabled, would we
  292                  * have got an interrupt?
  293                  */
  294                 if (bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP)
  295                         u14_intr(sc);
  296                 if (xs->flags & ITSDONE)
  297                         return (0);
  298                 delay(1000);
  299                 count--;
  300         }
  301         return (1);
  302 }
  303 
  304 /*
  305  * Catch an interrupt from the adaptor
  306  */
  307 int
  308 u14_intr(arg)
  309         void *arg;
  310 {
  311         struct uha_softc *sc = arg;
  312         bus_space_tag_t iot = sc->sc_iot;
  313         bus_space_handle_t ioh = sc->sc_ioh;
  314         struct uha_mscp *mscp;
  315         u_char uhastat;
  316         u_long mboxval;
  317 
  318 #ifdef  UHADEBUG
  319         printf("%s: uhaintr ", sc->sc_dev.dv_xname);
  320 #endif /*UHADEBUG */
  321 
  322         if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
  323                 return (0);
  324 
  325         for (;;) {
  326                 /*
  327                  * First get all the information and then
  328                  * acknowledge the interrupt
  329                  */
  330                 uhastat = bus_space_read_1(iot, ioh, U14_SINT);
  331                 mboxval = bus_space_read_4(iot, ioh, U14_ICMPTR);
  332                 /* XXX Send an ABORT_ACK instead? */
  333                 bus_space_write_1(iot, ioh, U14_SINT, U14_ICM_ACK);
  334 
  335 #ifdef  UHADEBUG
  336                 printf("status = 0x%x ", uhastat);
  337 #endif /*UHADEBUG*/
  338 
  339                 /*
  340                  * Process the completed operation
  341                  */
  342                 mscp = uha_mscp_phys_kv(sc, mboxval);
  343                 if (!mscp) {
  344                         printf("%s: BAD MSCP RETURNED!\n",
  345                             sc->sc_dev.dv_xname);
  346                         continue;       /* whatever it was, it'll timeout */
  347                 }
  348 
  349                 timeout_del(&mscp->xs->stimeout);
  350                 uha_done(sc, mscp);
  351 
  352                 if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
  353                         return (1);
  354         }
  355 }
  356 
  357 void
  358 u14_init(sc)
  359         struct uha_softc *sc;
  360 {
  361         bus_space_tag_t iot = sc->sc_iot;
  362         bus_space_handle_t ioh = sc->sc_ioh;
  363 
  364         /* make sure interrupts are enabled */
  365 #ifdef UHADEBUG
  366         printf("u14_init: lmask=%02x, smask=%02x\n",
  367             bus_space_read_1(iot, ioh, U14_LMASK),
  368             bus_space_read_1(iot, ioh, U14_SMASK));
  369 #endif
  370         bus_space_write_1(iot, ioh, U14_LMASK, 0xd1);   /* XXX */
  371         bus_space_write_1(iot, ioh, U14_SMASK, 0x91);   /* XXX */
  372 }

/* [<][>][^][v][top][bottom][index][help] */