Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys First cut at a esiop driver (enhanced siop). Doesn't imp...



details:   https://anonhg.NetBSD.org/src/rev/97174200cbc7
branches:  trunk
changeset: 525932:97174200cbc7
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Apr 21 22:52:05 2002 +0000

description:
First cut at a esiop driver (enhanced siop). Doesn't implement tagged queuing
yet.
If is restricted to SIOP which implement the load/store instruction, and
has 10 scratch registers (basically, 825 and newer, possibly 770).
It implements a different interface between host and script, using a real
ring for command starts, and improved support for reconnect which will allow
256 tag per device. It uses interrupt on the fly to signal complete command,
which allows several commands to be serviced per interrupt and doesn't require
the script to stop to signal command completion.

diffstat:

 sys/conf/files                  |     5 +-
 sys/dev/ic/esiop.c              |  1939 +++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/esiopvar.h           |   122 ++
 sys/dev/microcode/siop/Makefile |    11 +-
 sys/dev/microcode/siop/esiop.ss |   329 ++++++
 sys/dev/pci/esiop_pci.c         |    98 +
 6 files changed, 2499 insertions(+), 5 deletions(-)

diffs (truncated from 2548 to 300 lines):

diff -r e46fbd7869b1 -r 97174200cbc7 sys/conf/files
--- a/sys/conf/files    Sun Apr 21 22:40:10 2002 +0000
+++ b/sys/conf/files    Sun Apr 21 22:52:05 2002 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.517 2002/04/18 12:04:05 bouyer Exp $
+#      $NetBSD: files,v 1.518 2002/04/21 22:52:05 bouyer Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
@@ -359,6 +359,9 @@
 file   dev/ic/siop.c                   siop
 defflag        opt_siop.h                      SIOP_SYMLED
 
+device esiop: scsi,siop_common
+file   dev/ic/esiop.c                  esiop
+
 # UltraStor SCSI controllers
 #
 device uha: scsi
diff -r e46fbd7869b1 -r 97174200cbc7 sys/dev/ic/esiop.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/esiop.c        Sun Apr 21 22:52:05 2002 +0000
@@ -0,0 +1,1939 @@
+/*     $NetBSD: esiop.c,v 1.1 2002/04/21 22:52:05 bouyer Exp $ */
+
+/*
+ * Copyright (c) 2002 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Manuel Bouyer
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,     
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.1 2002/04/21 22:52:05 bouyer Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/kernel.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/endian.h>
+#include <machine/bus.h>
+
+#include <dev/microcode/siop/esiop.out>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsi_message.h>
+#include <dev/scsipi/scsipi_all.h>
+
+#include <dev/scsipi/scsiconf.h>
+
+#include <dev/ic/siopreg.h>
+#include <dev/ic/siopvar_common.h>
+#include <dev/ic/esiopvar.h>
+
+#include "opt_siop.h"
+
+#ifndef DEBUG
+#undef DEBUG
+#endif
+#undef SIOP_DEBUG
+#undef SIOP_DEBUG_DR
+#undef SIOP_DEBUG_INTR
+#undef SIOP_DEBUG_SCHED
+#undef DUMP_SCRIPT
+
+#define SIOP_STATS
+
+#ifndef SIOP_DEFAULT_TARGET
+#define SIOP_DEFAULT_TARGET 7
+#endif
+
+/* number of cmd descriptors per block */
+#define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct esiop_xfer))
+
+void   esiop_reset __P((struct esiop_softc *));
+void   esiop_checkdone __P((struct esiop_softc *));
+void   esiop_handle_reset __P((struct esiop_softc *));
+void   esiop_scsicmd_end __P((struct esiop_cmd *));
+void   esiop_unqueue __P((struct esiop_softc *, int, int));
+static void    esiop_start __P((struct esiop_softc *, struct esiop_cmd *));
+void   esiop_timeout __P((void *));
+int    esiop_scsicmd __P((struct scsipi_xfer *));
+void   esiop_scsipi_request __P((struct scsipi_channel *,
+                       scsipi_adapter_req_t, void *));
+void   esiop_dump_script __P((struct esiop_softc *));
+void   esiop_morecbd __P((struct esiop_softc *));
+void   siop_add_reselsw __P((struct esiop_softc *, int));
+void   esiop_update_scntl3 __P((struct esiop_softc *,
+                       struct siop_common_target *));
+struct esiop_cmd * esiop_cmd_find __P((struct esiop_softc *, int, u_int32_t));
+void   esiop_target_register __P((struct esiop_softc *, u_int32_t));
+
+static int nintr = 0;
+
+#ifdef SIOP_STATS
+static int esiop_stat_intr = 0;
+static int esiop_stat_intr_shortxfer = 0;
+static int esiop_stat_intr_sdp = 0;
+static int esiop_stat_intr_done = 0;
+static int esiop_stat_intr_xferdisc = 0;
+static int esiop_stat_intr_lunresel = 0;
+static int esiop_stat_intr_qfull = 0;
+void esiop_printstats __P((void));
+#define INCSTAT(x) x++
+#else
+#define INCSTAT(x) 
+#endif
+
+static __inline__ void esiop_script_sync __P((struct esiop_softc *, int));
+static __inline__ void
+esiop_script_sync(sc, ops)
+       struct esiop_softc *sc;
+       int ops;
+{
+       if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
+               bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
+                   PAGE_SIZE, ops);
+}
+
+static __inline__ u_int32_t esiop_script_read __P((struct esiop_softc *, u_int));
+static __inline__ u_int32_t
+esiop_script_read(sc, offset)
+       struct esiop_softc *sc;
+       u_int offset;
+{
+       if (sc->sc_c.features & SF_CHIP_RAM) {
+               return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
+                   offset * 4);
+       } else {
+               return le32toh(sc->sc_c.sc_script[offset]);
+       }
+}
+
+static __inline__ void esiop_script_write __P((struct esiop_softc *, u_int,
+       u_int32_t));
+static __inline__ void
+esiop_script_write(sc, offset, val)
+       struct esiop_softc *sc;
+       u_int offset;
+       u_int32_t val;
+{
+       if (sc->sc_c.features & SF_CHIP_RAM) {
+               bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
+                   offset * 4, val);
+       } else {
+               sc->sc_c.sc_script[offset] = htole32(val);
+       }
+}
+
+void
+esiop_attach(sc)
+       struct esiop_softc *sc;
+{
+       int error, i;
+       bus_dma_segment_t seg;
+       int rseg;
+
+       /*
+        * Allocate DMA-safe memory for the script and map it.
+        */
+       if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
+               error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, 
+                   PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
+               if (error) {
+                       printf("%s: unable to allocate script DMA memory, "
+                           "error = %d\n", sc->sc_c.sc_dev.dv_xname, error);
+                       return;
+               }
+               error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
+                   (caddr_t *)&sc->sc_c.sc_script,
+                   BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
+               if (error) {
+                       printf("%s: unable to map script DMA memory, "
+                           "error = %d\n", sc->sc_c.sc_dev.dv_xname, error);
+                       return;
+               }
+               error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1,
+                   PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_c.sc_scriptdma);
+               if (error) {
+                       printf("%s: unable to create script DMA map, "
+                           "error = %d\n", sc->sc_c.sc_dev.dv_xname, error);
+                       return;
+               }
+               error = bus_dmamap_load(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma,
+                   sc->sc_c.sc_script, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
+               if (error) {
+                       printf("%s: unable to load script DMA map, "
+                           "error = %d\n", sc->sc_c.sc_dev.dv_xname, error);
+                       return;
+               }
+               sc->sc_c.sc_scriptaddr =
+                   sc->sc_c.sc_scriptdma->dm_segs[0].ds_addr;
+               sc->sc_c.ram_size = PAGE_SIZE;
+       }
+       TAILQ_INIT(&sc->free_list);
+       TAILQ_INIT(&sc->cmds);
+       sc->sc_currschedslot = 0;
+#ifdef SIOP_DEBUG
+       printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
+           sc->sc_c.sc_dev.dv_xname, (int)sizeof(esiop_script),
+           (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
+#endif
+
+       sc->sc_c.sc_adapt.adapt_dev = &sc->sc_c.sc_dev;
+       sc->sc_c.sc_adapt.adapt_nchannels = 1;
+       sc->sc_c.sc_adapt.adapt_openings = 0;
+       sc->sc_c.sc_adapt.adapt_max_periph = 1 /* XXX ESIOP_NTAG - 1 */ ;
+       sc->sc_c.sc_adapt.adapt_ioctl = siop_ioctl;
+       sc->sc_c.sc_adapt.adapt_minphys = minphys;
+       sc->sc_c.sc_adapt.adapt_request = esiop_scsipi_request;
+
+       memset(&sc->sc_c.sc_chan, 0, sizeof(sc->sc_c.sc_chan));
+       sc->sc_c.sc_chan.chan_adapter = &sc->sc_c.sc_adapt;
+       sc->sc_c.sc_chan.chan_bustype = &scsi_bustype;
+       sc->sc_c.sc_chan.chan_channel = 0;
+       sc->sc_c.sc_chan.chan_flags = SCSIPI_CHAN_CANGROW;
+       sc->sc_c.sc_chan.chan_ntargets =
+           (sc->sc_c.features & SF_BUS_WIDE) ? 16 : 8;
+       sc->sc_c.sc_chan.chan_nluns = 8;
+       sc->sc_c.sc_chan.chan_id =
+           bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCID);
+       if (sc->sc_c.sc_chan.chan_id == 0 ||
+           sc->sc_c.sc_chan.chan_id >= sc->sc_c.sc_chan.chan_ntargets)
+               sc->sc_c.sc_chan.chan_id = SIOP_DEFAULT_TARGET;
+
+       for (i = 0; i < 16; i++)
+               sc->sc_c.targets[i] = NULL;
+
+       /* find min/max sync period for this chip */
+       sc->sc_c.maxsync = 0;
+       sc->sc_c.minsync = 255;
+       for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
+               if (sc->sc_c.clock_period != scf_period[i].clock)
+                       continue;
+               if (sc->sc_c.maxsync < scf_period[i].period)
+                       sc->sc_c.maxsync = scf_period[i].period;
+               if (sc->sc_c.minsync > scf_period[i].period)
+                       sc->sc_c.minsync = scf_period[i].period;
+       }
+       if (sc->sc_c.maxsync == 255 || sc->sc_c.minsync == 0)
+               panic("siop: can't find my sync parameters\n");
+       /* Do a bus reset, so that devices fall back to narrow/async */
+       siop_resetbus(&sc->sc_c);
+       /*
+        * siop_reset() will reset the chip, thus clearing pending interrupts
+        */
+       esiop_reset(sc);
+#ifdef DUMP_SCRIPT
+       esiop_dump_script(sc);
+#endif
+
+       config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint);
+}
+
+void
+esiop_reset(sc)
+       struct esiop_softc *sc;
+{
+       int i, j;
+       u_int32_t addr;
+       u_int32_t msgin_addr;
+
+       siop_common_reset(&sc->sc_c);
+
+       /*
+        * we copy the script at the beggining of RAM. Then there is 8 bytes
+        * for messages in.
+        */
+       sc->sc_free_offset = sizeof(esiop_script) / sizeof(esiop_script[0]);
+       msgin_addr =



Home | Main Index | Thread Index | Old Index