Source-Changes-HG archive

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

[src/trunk]: src/sys Add MI NCR/Symbios 53c700 SCSI driver.



details:   https://anonhg.NetBSD.org/src/rev/0bc7c1212d88
branches:  trunk
changeset: 545283:0bc7c1212d88
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Sun Apr 06 09:48:41 2003 +0000

description:
Add MI NCR/Symbios 53c700 SCSI driver.
This "oosiop" driver was originally written by Shuichiro URATA
for arc port, and then it was modified by me to make it work
also on hp700.

This driver has been tested on my NEC Express5800/240 with 53c700-66
for several months, and also tested on HP9000 735/125 with 53c700
(though current hp700 port has been broken since SA merge).
Both sync transfer and disconnect/reselect work fine,
but tagged queuing is not implemented yet.

diffstat:

 sys/conf/files                   |     6 +-
 sys/dev/ic/oosiop.c              |  1325 ++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/oosiopreg.h           |   327 +++++++++
 sys/dev/ic/oosiopvar.h           |   157 ++++
 sys/dev/microcode/siop/oosiop.ss |   303 +++-----
 5 files changed, 1919 insertions(+), 199 deletions(-)

diffs (truncated from 2183 to 300 lines):

diff -r 215874d2fedb -r 0bc7c1212d88 sys/conf/files
--- a/sys/conf/files    Sun Apr 06 07:22:13 2003 +0000
+++ b/sys/conf/files    Sun Apr 06 09:48:41 2003 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files,v 1.604 2003/03/16 11:50:27 jdolecek Exp $
+#      $NetBSD: files,v 1.605 2003/04/06 09:48:41 tsutsui Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
 
@@ -385,6 +385,10 @@
 attach lfmport at lfmiop
 file   dev/ic/lfmiop.c                 lfmiop
 
+# Symbios/NCR 53c700 SCSI controllers
+device oosiop: scsi
+file   dev/ic/oosiop.c                 oosiop
+
 # Symbios/NCR 53c710 SCSI controllers
 #
 device osiop: scsi
diff -r 215874d2fedb -r 0bc7c1212d88 sys/dev/ic/oosiop.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/oosiop.c       Sun Apr 06 09:48:41 2003 +0000
@@ -0,0 +1,1325 @@
+/*     $NetBSD: oosiop.c,v 1.1 2003/04/06 09:48:43 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
+ *
+ * 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. 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.
+ */
+
+/*
+ * NCR53C700 SCSI I/O processor (OOSIOP) driver
+ *
+ * TODO:
+ *   - More better error handling.
+ *   - Implement tagged queuing.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsi_message.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <dev/ic/oosiopreg.h>
+#include <dev/ic/oosiopvar.h>
+#include <dev/microcode/siop/oosiop.out>
+
+static int     oosiop_alloc_cb(struct oosiop_softc *, int);
+
+static __inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
+static __inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
+                        int);
+static __inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
+                        bus_addr_t);
+static __inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
+                        bus_size_t, bus_addr_t);
+
+static void    oosiop_load_script(struct oosiop_softc *);
+static void    oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
+static void    oosiop_setup_dma(struct oosiop_softc *);
+static void    oosiop_flush_fifo(struct oosiop_softc *);
+static void    oosiop_clear_fifo(struct oosiop_softc *);
+static void    oosiop_phasemismatch(struct oosiop_softc *);
+static void    oosiop_setup_syncxfer(struct oosiop_softc *);
+static void    oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
+static void    oosiop_minphys(struct buf *);
+static void    oosiop_scsipi_request(struct scsipi_channel *,
+                   scsipi_adapter_req_t, void *);
+static void    oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
+static void    oosiop_timeout(void *);
+static void    oosiop_reset(struct oosiop_softc *);
+static void    oosiop_reset_bus(struct oosiop_softc *);
+static void    oosiop_scriptintr(struct oosiop_softc *);
+static void    oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
+
+/* Trap interrupt code for unexpected data I/O */
+#define        DATAIN_TRAP     0xdead0001
+#define        DATAOUT_TRAP    0xdead0002
+
+/* Possible TP and SCF conbination */
+static const struct {
+       u_int8_t        tp;
+       u_int8_t        scf;
+} synctbl[] = {
+       {0, 1},         /* SCLK /  4.0 */
+       {1, 1},         /* SCLK /  5.0 */
+       {2, 1},         /* SCLK /  6.0 */
+       {3, 1},         /* SCLK /  7.0 */
+       {1, 2},         /* SCLK /  7.5 */
+       {4, 1},         /* SCLK /  8.0 */
+       {5, 1},         /* SCLK /  9.0 */
+       {6, 1},         /* SCLK / 10.0 */
+       {3, 2},         /* SCLK / 10.5 */
+       {7, 1},         /* SCLK / 11.0 */
+       {4, 2},         /* SCLK / 12.0 */
+       {5, 2},         /* SCLK / 13.5 */
+       {3, 3},         /* SCLK / 14.0 */
+       {6, 2},         /* SCLK / 15.0 */
+       {4, 3},         /* SCLK / 16.0 */
+       {7, 2},         /* SCLK / 16.5 */
+       {5, 3},         /* SCLK / 18.0 */
+       {6, 3},         /* SCLK / 20.0 */
+       {7, 3}          /* SCLK / 22.0 */
+};
+#define        NSYNCTBL        (sizeof(synctbl) / sizeof(synctbl[0]))
+
+#define        oosiop_period(sc, tp, scf)                                      \
+           (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
+
+void
+oosiop_attach(struct oosiop_softc *sc)
+{
+       bus_size_t scrsize;
+       bus_dma_segment_t seg;
+       struct oosiop_cb *cb;
+       int err, i, nseg;
+
+       /*
+        * Allocate DMA-safe memory for the script and map it.
+        */
+       scrsize = sizeof(oosiop_script);
+       err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
+           &nseg, BUS_DMA_NOWAIT);
+       if (err) {
+               printf(": failed to allocate script memory, err=%d\n", err);
+               return;
+       }
+       err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
+           (caddr_t *)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+       if (err) {
+               printf(": failed to map script memory, err=%d\n", err);
+               return;
+       }
+       err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
+           BUS_DMA_NOWAIT, &sc->sc_scrdma);
+       if (err) {
+               printf(": failed to create script map, err=%d\n", err);
+               return;
+       }
+       err = bus_dmamap_load(sc->sc_dmat, sc->sc_scrdma, sc->sc_scr, scrsize,
+           NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+       if (err) {
+               printf(": failed to load script map, err=%d\n", err);
+               return;
+       }
+       sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
+
+       /* Initialize command block array */
+       TAILQ_INIT(&sc->sc_free_cb);
+       TAILQ_INIT(&sc->sc_cbq);
+       if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
+               return;
+
+       /* Use first cb to reselection msgin buffer */
+       cb = TAILQ_FIRST(&sc->sc_free_cb);
+       sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
+           offsetof(struct oosiop_xfer, msgin[0]);
+
+       for (i = 0; i < OOSIOP_NTGT; i++) {
+               sc->sc_tgt[i].nexus = NULL;
+               sc->sc_tgt[i].flags = 0;
+       }
+
+       /* Setup asynchronous clock divisor parameters */
+       if (sc->sc_freq <= 25000000) {
+               sc->sc_ccf = 10;
+               sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
+       } else if (sc->sc_freq <= 37500000) {
+               sc->sc_ccf = 15;
+               sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
+       } else if (sc->sc_freq <= 50000000) {
+               sc->sc_ccf = 20;
+               sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
+       } else {
+               sc->sc_ccf = 30;
+               sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
+       }
+
+       if (sc->sc_chip == OOSIOP_700)
+               sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
+       else
+               sc->sc_minperiod = oosiop_period(sc, 4, 10);
+
+       if (sc->sc_minperiod < 25)
+               sc->sc_minperiod = 25;  /* limit to 10MB/s */
+
+       printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
+           sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
+           oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
+           sc->sc_freq / 1000000, sc->sc_id);
+       /*
+        * Reset all
+        */
+       oosiop_reset(sc);
+       oosiop_reset_bus(sc);
+
+       /*
+        * Start SCRIPTS processor
+        */
+       oosiop_load_script(sc);
+       sc->sc_active = 0;
+       oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
+
+       /*
+        * Fill in the scsipi_adapter.
+        */
+       sc->sc_adapter.adapt_dev = &sc->sc_dev;
+       sc->sc_adapter.adapt_nchannels = 1;
+       sc->sc_adapter.adapt_openings = OOSIOP_NCB;
+       sc->sc_adapter.adapt_max_periph = 1;
+       sc->sc_adapter.adapt_ioctl = NULL;
+       sc->sc_adapter.adapt_minphys = oosiop_minphys;
+       sc->sc_adapter.adapt_request = oosiop_scsipi_request;
+
+       /*
+        * Fill in the scsipi_channel.
+        */
+       sc->sc_channel.chan_adapter = &sc->sc_adapter;
+       sc->sc_channel.chan_bustype = &scsi_bustype;
+       sc->sc_channel.chan_channel = 0;
+       sc->sc_channel.chan_ntargets = OOSIOP_NTGT;
+       sc->sc_channel.chan_nluns = 8;
+       sc->sc_channel.chan_id = sc->sc_id;
+
+       /*
+        * Now try to attach all the sub devices.
+        */
+       config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
+}
+
+static int
+oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
+{
+       struct oosiop_cb *cb;
+       struct oosiop_xfer *xfer;
+       bus_size_t xfersize;
+       bus_dma_segment_t seg;
+       int i, s, err, nseg;
+
+       /*
+        * Allocate oosiop_cb.
+        */
+       cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT|M_ZERO);
+       if (cb == NULL) {
+               printf(": failed to allocate cb memory\n");
+               return (ENOMEM);
+       }
+
+       /*
+        * Allocate DMA-safe memory for the oosiop_xfer and map it.
+        */
+       xfersize = sizeof(struct oosiop_xfer) * ncb;
+       err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
+           &nseg, BUS_DMA_NOWAIT);
+       if (err) {
+               printf(": failed to allocate xfer block memory, err=%d\n", err);
+               return (err);
+       }
+       err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
+           (caddr_t *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+       if (err) {
+               printf(": failed to map xfer block memory, err=%d\n", err);
+               return (err);



Home | Main Index | Thread Index | Old Index