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/podulebus/hcsc.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: hcsc.c,v 1.12 2002/10/02 16:52:23 thorpej Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2001 Ben Harris
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Mark Brinicombe of Causality Limited.
   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  * Copyright (c) 1996, 1997 Matthias Pfaller.
   41  * All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  * 3. All advertising materials mentioning features or use of this software
   52  *    must display the following acknowledgement:
   53  *      This product includes software developed by Matthias Pfaller.
   54  * 4. The name of the author may not be used to endorse or promote products
   55  *    derived from this software without specific prior written permission
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   60  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   62  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   63  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   64  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   66  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   67  */
   68 
   69 /*
   70  * HCCS 8-bit SCSI driver using the generic NCR5380 driver
   71  *
   72  * Andy Armstrong gives some details of the HCCS SCSI cards at
   73  * <URL:http://www.armlinux.org/~webmail/linux-arm/1997-08/msg00042.html>.
   74  */
   75 
   76 #include <sys/cdefs.h>
   77 __KERNEL_RCSID(0, "$NetBSD: hcsc.c,v 1.12 2002/10/02 16:52:23 thorpej Exp $");
   78 
   79 #include <sys/param.h>
   80 
   81 #include <sys/systm.h>
   82 #include <sys/kernel.h>
   83 #include <sys/device.h>
   84 #include <sys/buf.h>
   85 #include <dev/scsipi/scsi_all.h>
   86 #include <dev/scsipi/scsipi_all.h>
   87 #include <dev/scsipi/scsiconf.h>
   88 
   89 #include <dev/ic/ncr5380reg.h>
   90 #include <dev/ic/ncr5380var.h>
   91 
   92 #include <machine/bootconfig.h>
   93 
   94 #include <dev/podulebus/podulebus.h>
   95 #include <dev/podulebus/podules.h>
   96 #include <dev/podulebus/powerromreg.h>
   97 
   98 #include <dev/podulebus/hcscreg.h>
   99 
  100 void hcsc_attach (struct device *, struct device *, void *);
  101 int  hcsc_match  (struct device *, struct cfdata *, void *);
  102 
  103 static int hcsc_pdma_in(struct ncr5380_softc *, int, int, u_char *);
  104 static int hcsc_pdma_out(struct ncr5380_softc *, int, int, u_char *);
  105 
  106 
  107 /*
  108  * HCCS 8-bit SCSI softc structure.
  109  *
  110  * Contains the generic ncr5380 device node, podule information and
  111  * global information required by the driver.
  112  */
  113 
  114 struct hcsc_softc {
  115         struct ncr5380_softc    sc_ncr5380;
  116         bus_space_tag_t         sc_pdmat;
  117         bus_space_handle_t      sc_pdmah;
  118         void            *sc_ih;
  119         struct evcnt    sc_intrcnt;
  120 };
  121 
  122 CFATTACH_DECL(hcsc, sizeof(struct hcsc_softc),
  123     hcsc_match, hcsc_attach, NULL, NULL);
  124 
  125 /*
  126  * Card probe function
  127  *
  128  * Just match the manufacturer and podule ID's
  129  */
  130 
  131 int
  132 hcsc_match(struct device *parent, struct cfdata *cf, void *aux)
  133 {
  134         struct podulebus_attach_args *pa = aux;
  135 
  136         /* Normal ROM */
  137         if (pa->pa_product == PODULE_HCCS_IDESCSI &&
  138             strncmp(pa->pa_descr, "SCSI", 4) == 0)
  139                 return 1;
  140         /* PowerROM */
  141         if (pa->pa_product == PODULE_ALSYSTEMS_SCSI &&
  142             podulebus_initloader(pa) == 0 &&
  143             podloader_callloader(pa, 0, 0) == PRID_HCCS_SCSI1)
  144                 return 1;
  145         return 0;
  146 }
  147 
  148 /*
  149  * Card attach function
  150  *
  151  */
  152 
  153 void
  154 hcsc_attach(struct device *parent, struct device *self, void *aux)
  155 {
  156         struct hcsc_softc *sc = (struct hcsc_softc *)self;
  157         struct podulebus_attach_args *pa = aux;
  158 #ifndef NCR5380_USE_BUS_SPACE
  159         u_char *iobase;
  160 #endif
  161         char hi_option[sizeof(sc->sc_ncr5380.sc_dev.dv_xname) + 8];
  162 
  163         sc->sc_ncr5380.sc_min_dma_len = 0;
  164         sc->sc_ncr5380.sc_no_disconnect = 0;
  165         sc->sc_ncr5380.sc_parity_disable = 0;
  166 
  167         sc->sc_ncr5380.sc_dma_alloc = NULL;
  168         sc->sc_ncr5380.sc_dma_free = NULL;
  169         sc->sc_ncr5380.sc_dma_poll = NULL;
  170         sc->sc_ncr5380.sc_dma_setup = NULL;
  171         sc->sc_ncr5380.sc_dma_start = NULL;
  172         sc->sc_ncr5380.sc_dma_eop = NULL;
  173         sc->sc_ncr5380.sc_dma_stop = NULL;
  174         sc->sc_ncr5380.sc_intr_on = NULL;
  175         sc->sc_ncr5380.sc_intr_off = NULL;
  176 
  177 #ifdef NCR5380_USE_BUS_SPACE
  178         sc->sc_ncr5380.sc_regt = pa->pa_fast_t;
  179         bus_space_map(sc->sc_ncr5380.sc_regt,
  180             pa->pa_fast_base + HCSC_DP8490_OFFSET, 8, 0,
  181             &sc->sc_ncr5380.sc_regh);
  182         sc->sc_ncr5380.sci_r0 = 0;
  183         sc->sc_ncr5380.sci_r1 = 1;
  184         sc->sc_ncr5380.sci_r2 = 2;
  185         sc->sc_ncr5380.sci_r3 = 3;
  186         sc->sc_ncr5380.sci_r4 = 4;
  187         sc->sc_ncr5380.sci_r5 = 5;
  188         sc->sc_ncr5380.sci_r6 = 6;
  189         sc->sc_ncr5380.sci_r7 = 7;
  190 #else
  191         iobase = (u_char *)pa->pa_fast_base + HCSC_DP8490_OFFSET;
  192         sc->sc_ncr5380.sci_r0 = iobase + 0;
  193         sc->sc_ncr5380.sci_r1 = iobase + 4;
  194         sc->sc_ncr5380.sci_r2 = iobase + 8;
  195         sc->sc_ncr5380.sci_r3 = iobase + 12;
  196         sc->sc_ncr5380.sci_r4 = iobase + 16;
  197         sc->sc_ncr5380.sci_r5 = iobase + 20;
  198         sc->sc_ncr5380.sci_r6 = iobase + 24;
  199         sc->sc_ncr5380.sci_r7 = iobase + 28;
  200 #endif
  201         sc->sc_pdmat = pa->pa_mod_t;
  202         bus_space_map(sc->sc_pdmat, pa->pa_mod_base + HCSC_PDMA_OFFSET, 1, 0,
  203             &sc->sc_pdmah);
  204 
  205         sc->sc_ncr5380.sc_rev = NCR_VARIANT_DP8490;
  206 
  207         sc->sc_ncr5380.sc_pio_in = hcsc_pdma_in;
  208         sc->sc_ncr5380.sc_pio_out = hcsc_pdma_out;
  209 
  210         /* Provide an override for the host id */
  211         sc->sc_ncr5380.sc_channel.chan_id = 7;
  212         sprintf(hi_option, "%s.hostid", sc->sc_ncr5380.sc_dev.dv_xname);
  213         (void)get_bootconf_option(boot_args, hi_option,
  214             BOOTOPT_TYPE_INT, &sc->sc_ncr5380.sc_channel.chan_id);
  215         sc->sc_ncr5380.sc_adapter.adapt_minphys = minphys;
  216 
  217         printf(": host ID %d\n", sc->sc_ncr5380.sc_channel.chan_id);
  218 
  219         evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
  220             self->dv_xname, "intr");
  221         sc->sc_ih = podulebus_irq_establish(pa->pa_ih, IPL_BIO, ncr5380_intr,
  222             sc, &sc->sc_intrcnt);
  223 
  224         ncr5380_attach(&sc->sc_ncr5380);
  225 }
  226 
  227 #ifndef HCSC_TSIZE_OUT
  228 #define HCSC_TSIZE_OUT  512
  229 #endif
  230 
  231 #ifndef HCSC_TSIZE_IN
  232 #define HCSC_TSIZE_IN   512
  233 #endif
  234 
  235 #define TIMEOUT 1000000
  236 
  237 static __inline int
  238 hcsc_ready(struct ncr5380_softc *sc)
  239 {
  240         int i;
  241 
  242         for (i = TIMEOUT; i > 0; i--) {
  243                 if ((NCR5380_READ(sc,sci_csr) &
  244                     (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH)) ==
  245                     (SCI_CSR_DREQ | SCI_CSR_PHASE_MATCH))
  246                         return(1);
  247 
  248                 if ((NCR5380_READ(sc, sci_csr) & SCI_CSR_PHASE_MATCH) == 0 ||
  249                     SCI_BUSY(sc) == 0)
  250                         return(0);
  251         }
  252         printf("%s: ready timeout\n", sc->sc_dev.dv_xname);
  253         return(0);
  254 }
  255 
  256 
  257 
  258 /* Return zero on success. */
  259 static __inline void hcsc_wait_not_req(struct ncr5380_softc *sc)
  260 {
  261         int timo;
  262         for (timo = TIMEOUT; timo; timo--) {
  263                 if ((NCR5380_READ(sc, sci_bus_csr) & SCI_BUS_REQ) == 0 ||
  264                     (NCR5380_READ(sc, sci_csr) & SCI_CSR_PHASE_MATCH) == 0 ||
  265                     SCI_BUSY(sc) == 0) {
  266                         return;
  267                 }
  268         }
  269         printf("%s: pdma not_req timeout\n", sc->sc_dev.dv_xname);
  270 }
  271 
  272 static int
  273 hcsc_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen,
  274     u_char *data)
  275 {
  276         struct hcsc_softc *sc = (void *)ncr_sc;
  277         bus_space_tag_t pdmat = sc->sc_pdmat;
  278         bus_space_handle_t pdmah = sc->sc_pdmah;
  279         int s, resid, len;
  280 
  281         s = splbio();
  282 
  283         NCR5380_WRITE(ncr_sc, sci_mode,
  284             NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
  285         NCR5380_WRITE(ncr_sc, sci_irecv, 0);
  286 
  287         resid = datalen;
  288         while (resid > 0) {
  289                 len = min(resid, HCSC_TSIZE_IN);
  290                 if (hcsc_ready(ncr_sc) == 0)
  291                         goto interrupt;
  292                 bus_space_read_multi_1(pdmat, pdmah, 0, data, len);
  293                 data += len;
  294                 resid -= len;
  295         }
  296 
  297         hcsc_wait_not_req(ncr_sc);
  298 
  299 interrupt:
  300         SCI_CLR_INTR(ncr_sc);
  301         NCR5380_WRITE(ncr_sc, sci_mode,
  302             NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
  303         splx(s);
  304         return datalen - resid;
  305 }
  306 
  307 static int
  308 hcsc_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen,
  309     u_char *data)
  310 {
  311         struct hcsc_softc *sc = (void *)ncr_sc;
  312         bus_space_tag_t pdmat = sc->sc_pdmat;
  313         bus_space_handle_t pdmah = sc->sc_pdmah;
  314         int i, s, icmd, resid;
  315 
  316         s = splbio();
  317         icmd = NCR5380_READ(ncr_sc, sci_icmd) & SCI_ICMD_RMASK;
  318         NCR5380_WRITE(ncr_sc, sci_icmd, icmd | SCI_ICMD_DATA);
  319         NCR5380_WRITE(ncr_sc, sci_mode,
  320             NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
  321         NCR5380_WRITE(ncr_sc, sci_dma_send, 0);
  322 
  323         resid = datalen;
  324         if (hcsc_ready(ncr_sc) == 0)
  325                 goto interrupt;
  326 
  327         if (resid > HCSC_TSIZE_OUT) {
  328                 /*
  329                  * Because of the chips DMA prefetch, phase changes
  330                  * etc, won't be detected until we have written at
  331                  * least one byte more. We pre-write 4 bytes so
  332                  * subsequent transfers will be aligned to a 4 byte
  333                  * boundary. Assuming disconects will only occur on
  334                  * block boundaries, we then correct for the pre-write
  335                  * when and if we get a phase change. If the chip had
  336                  * DMA byte counting hardware, the assumption would not
  337                  * be necessary.
  338                  */
  339                 bus_space_write_multi_1(pdmat, pdmah, 0, data, 4);
  340                 data += 4;
  341                 resid -= 4;
  342                 
  343                 for (; resid >= HCSC_TSIZE_OUT; resid -= HCSC_TSIZE_OUT) {
  344                         if (hcsc_ready(ncr_sc) == 0) {
  345                                 resid += 4; /* Overshot */
  346                                 goto interrupt;
  347                         }
  348                         bus_space_write_multi_1(pdmat, pdmah, 0, data,
  349                             HCSC_TSIZE_OUT);
  350                         data += HCSC_TSIZE_OUT;
  351                 }
  352                 if (hcsc_ready(ncr_sc) == 0) {
  353                         resid += 4; /* Overshot */
  354                         goto interrupt;
  355                 }
  356         }
  357 
  358         if (resid) {
  359                 bus_space_write_multi_1(pdmat, pdmah, 0, data, resid);
  360                 resid = 0;
  361         }
  362         for (i = TIMEOUT; i > 0; i--) {
  363                 if ((NCR5380_READ(ncr_sc, sci_csr)
  364                     & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
  365                     != SCI_CSR_DREQ)
  366                         break;
  367         }
  368         if (i != 0)
  369                 bus_space_write_1(pdmat, pdmah, 0, 0);
  370         else
  371                 printf("%s: timeout waiting for final SCI_DSR_DREQ.\n",
  372                         ncr_sc->sc_dev.dv_xname);
  373 
  374         hcsc_wait_not_req(ncr_sc);
  375 interrupt:
  376         SCI_CLR_INTR(ncr_sc);
  377         NCR5380_WRITE(ncr_sc, sci_mode,
  378             NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
  379         NCR5380_WRITE(ncr_sc, sci_icmd, icmd);
  380         splx(s);
  381         return(datalen - resid);
  382 }

Cache object: 1179e4a73e75bdefc86f1b0c6a1beaa6


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