root/dev/eisa/cac_eisa.c

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

DEFINITIONS

This source file includes following definitions.
  1. cac_eisa_match
  2. cac_eisa_attach
  3. cac_eisa_l0_fifo_full
  4. cac_eisa_l0_submit
  5. cac_eisa_l0_completed
  6. cac_eisa_l0_intr_pending
  7. cac_eisa_l0_intr_enable

    1 /*      $OpenBSD: cac_eisa.c,v 1.2 2001/11/05 17:25:58 art Exp $        */
    2 /*      $NetBSD: cac_eisa.c,v 1.1 2000/09/01 12:15:20 ad Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Andrew Doran.
   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  * Copyright (c) 2000 Jonathan Lemon
   42  * Copyright (c) 1999 by Matthew N. Dodd <winter@jurai.net>
   43  * All Rights Reserved.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions, and the following disclaimer,
   50  *    without modification, immediately at the beginning of the file.
   51  * 2. The name of the author may not be used to endorse or promote products
   52  *    derived from this software without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   57  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   58  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   64  * SUCH DAMAGE.
   65  */
   66 
   67 /*
   68  * EISA front-end for cac(4) driver.
   69  */
   70 
   71 #include <sys/types.h>
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/device.h>
   75 
   76 #include <machine/bus.h>
   77 #include <machine/intr.h>
   78 
   79 #include <dev/eisa/eisavar.h>
   80 #include <dev/eisa/eisadevs.h>
   81 
   82 #include <scsi/scsi_all.h>
   83 #include <scsi/scsi_disk.h>
   84 #include <scsi/scsiconf.h>
   85 
   86 #include <dev/ic/cacreg.h>
   87 #include <dev/ic/cacvar.h>
   88 
   89 #define CAC_EISA_SLOT_OFFSET            0x0c88
   90 #define CAC_EISA_IOSIZE                 0x0017
   91 #define CAC_EISA_IOCONF                 0x38
   92 
   93 int     cac_eisa_match(struct device *, void *, void *);
   94 void    cac_eisa_attach(struct device *, struct device *, void *);
   95 
   96 struct  cac_ccb *cac_eisa_l0_completed(struct cac_softc *);
   97 int     cac_eisa_l0_fifo_full(struct cac_softc *);
   98 void    cac_eisa_l0_intr_enable(struct cac_softc *, int);
   99 int     cac_eisa_l0_intr_pending(struct cac_softc *);
  100 void    cac_eisa_l0_submit(struct cac_softc *, struct cac_ccb *);
  101 
  102 struct cfattach cac_eisa_ca = {
  103         sizeof(struct cac_softc), cac_eisa_match, cac_eisa_attach
  104 };
  105 
  106 static const
  107 struct cac_linkage cac_eisa_l0 = {
  108         cac_eisa_l0_completed,
  109         cac_eisa_l0_fifo_full,
  110         cac_eisa_l0_intr_enable,
  111         cac_eisa_l0_intr_pending,
  112         cac_eisa_l0_submit
  113 };
  114 
  115 static const
  116 struct cac_eisa_type {
  117         const char      *ct_prodstr;
  118         const char      *ct_typestr;
  119         const struct    cac_linkage *ct_linkage;
  120 } cac_eisa_type[] = {
  121         { "CPQ4001",    "IDA",          &cac_eisa_l0 },
  122         { "CPQ4002",    "IDA-2",        &cac_eisa_l0 },
  123         { "CPQ4010",    "IEAS",         &cac_eisa_l0 },
  124         { "CPQ4020",    "SMART",        &cac_eisa_l0 },
  125         { "CPQ4030",    "SMART-2/E",    &cac_l0 },
  126 };
  127 
  128 int
  129 cac_eisa_match(parent, match, aux)
  130         struct device *parent;
  131         void *match, *aux;
  132 {
  133         struct eisa_attach_args *ea;
  134         int i;
  135 
  136         ea = aux;
  137 
  138         for (i = 0; i < sizeof(cac_eisa_type) / sizeof(cac_eisa_type[0]); i++)
  139                 if (strcmp(ea->ea_idstring, cac_eisa_type[i].ct_prodstr) == 0)
  140                         return (1);
  141 
  142         return (0);
  143 }
  144 
  145 void
  146 cac_eisa_attach(parent, self, aux)
  147         struct device *parent;
  148         struct device *self;
  149         void *aux;
  150 {
  151         struct eisa_attach_args *ea;
  152         bus_space_handle_t ioh;
  153         eisa_chipset_tag_t ec;
  154         eisa_intr_handle_t ih;
  155         struct cac_softc *sc;
  156         bus_space_tag_t iot;
  157         const char *intrstr;
  158         int irq, i;
  159         
  160         ea = aux;
  161         sc = (struct cac_softc *)self;
  162         iot = ea->ea_iot;
  163         ec = ea->ea_ec;
  164         
  165         if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
  166             CAC_EISA_SLOT_OFFSET, CAC_EISA_IOSIZE, 0, &ioh)) {
  167                 printf(": can't map i/o space\n");
  168                 return;
  169         }
  170 
  171         sc->sc_iot = iot;
  172         sc->sc_ioh = ioh;
  173         sc->sc_dmat = ea->ea_dmat;
  174 
  175         /* 
  176          * Map and establish the interrupt.
  177          */
  178         switch (bus_space_read_1(iot, ioh, CAC_EISA_IOCONF) & 0xf0) {
  179         case 0x20:
  180                 irq = 10;
  181                 break;
  182         case 0x10:
  183                 irq = 11;
  184                 break;
  185         case 0x40:
  186                 irq = 14;
  187                 break;
  188         case 0x80:
  189                 irq = 15;
  190                 break;
  191         default:
  192                 printf(": controller on invalid IRQ\n");
  193                 return;
  194         }
  195 
  196         if (eisa_intr_map(ec, irq, &ih)) {
  197                 printf(": can't map interrupt (%d)\n", irq);
  198                 return;
  199         }
  200         
  201         intrstr = eisa_intr_string(ec, ih);
  202         if ((sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
  203             cac_intr, sc, sc->sc_dv.dv_xname)) == NULL) {
  204                 printf(": can't establish interrupt");
  205                 if (intrstr != NULL)
  206                         printf(" at %s", intrstr);
  207                 printf("\n");
  208                 return;
  209         }
  210 
  211         /*
  212          * Print board type and attach to the bus-independent code.
  213          */
  214         for (i = 0; i < sizeof(cac_eisa_type) / sizeof(cac_eisa_type[0]); i++)
  215                 if (strcmp(ea->ea_idstring, cac_eisa_type[i].ct_prodstr) == 0)
  216                         break;
  217 
  218         printf(" %s: Compaq %s\n", intrstr, cac_eisa_type[i].ct_typestr);
  219         sc->sc_cl = cac_eisa_type[i].ct_linkage;
  220         cac_init(sc, 0);
  221 }
  222 
  223 /*
  224  * Linkage specific to EISA boards.
  225  */
  226 
  227 int
  228 cac_eisa_l0_fifo_full(struct cac_softc *sc)
  229 {
  230 
  231         return ((cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
  232             CAC_EISA_CHANNEL_CLEAR) == 0);
  233 }
  234 
  235 void
  236 cac_eisa_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb)
  237 {
  238         u_int16_t size;
  239 
  240         /*
  241          * On these boards, `ccb_hdr.size' is actually for control flags.
  242          * Set it to zero and pass the value by means of an I/O port.
  243          */
  244         size = letoh16(ccb->ccb_hdr.size) << 2;
  245         ccb->ccb_hdr.size = 0;
  246 
  247         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, (caddr_t)ccb - sc->sc_ccbs,
  248             sizeof(struct cac_ccb), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
  249 
  250         cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL, CAC_EISA_CHANNEL_CLEAR);
  251         cac_outl(sc, CAC_EISAREG_LIST_ADDR, ccb->ccb_paddr);
  252         cac_outw(sc, CAC_EISAREG_LIST_LEN, size);
  253         cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL, CAC_EISA_CHANNEL_BUSY);
  254 }
  255 
  256 struct cac_ccb *
  257 cac_eisa_l0_completed(struct cac_softc *sc)
  258 {
  259         struct cac_ccb *ccb;
  260         u_int32_t off;
  261         u_int8_t status;
  262 
  263         if ((cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
  264             CAC_EISA_CHANNEL_BUSY) == 0)
  265                 return (NULL);
  266 
  267         cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL, CAC_EISA_CHANNEL_BUSY);
  268         off = cac_inl(sc, CAC_EISAREG_COMPLETE_ADDR);
  269         status = cac_inb(sc, CAC_EISAREG_LIST_STATUS);
  270         cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL, CAC_EISA_CHANNEL_CLEAR);
  271 
  272         if (off == 0)
  273                 return (NULL);
  274 
  275         off = (off & ~3) - sc->sc_ccbs_paddr;
  276         ccb = (struct cac_ccb *)(sc->sc_ccbs + off);
  277 
  278         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, off, sizeof(struct cac_ccb),
  279             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
  280 
  281         ccb->ccb_req.error = status;
  282         return (ccb);
  283 }
  284 
  285 int
  286 cac_eisa_l0_intr_pending(struct cac_softc *sc)
  287 {
  288 
  289         return (cac_inb(sc, CAC_EISAREG_SYSTEM_DOORBELL) &
  290             CAC_EISA_CHANNEL_BUSY);
  291 }
  292 
  293 void
  294 cac_eisa_l0_intr_enable(struct cac_softc *sc, int state)
  295 {
  296 
  297         if (state) {
  298                 cac_outb(sc, CAC_EISAREG_SYSTEM_DOORBELL,
  299                     ~CAC_EISA_CHANNEL_CLEAR);
  300                 cac_outb(sc, CAC_EISAREG_LOCAL_DOORBELL,
  301                     CAC_EISA_CHANNEL_BUSY);
  302                 cac_outb(sc, CAC_EISAREG_INTR_MASK, CAC_INTR_ENABLE);
  303                 cac_outb(sc, CAC_EISAREG_SYSTEM_MASK, CAC_INTR_ENABLE);
  304         } else
  305                 cac_outb(sc, CAC_EISAREG_SYSTEM_MASK, CAC_INTR_DISABLE);
  306 }

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