summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1994-08-19 00:01:08 +0000
committerphk <phk@FreeBSD.org>1994-08-19 00:01:08 +0000
commita8a9b8d89bccc8d87a7b579545c9c08e763fe17e (patch)
treee9961c05822a29ee65a755deb9cb5157ee9b41d4 /sys
parent3fcf3cf41df453b55f9b3061abf79f0f2c1ebb64 (diff)
downloadFreeBSD-src-a8a9b8d89bccc8d87a7b579545c9c08e763fe17e.zip
FreeBSD-src-a8a9b8d89bccc8d87a7b579545c9c08e763fe17e.tar.gz
Added my ProAudioSpectum SCSI driver for cards with the 5380 SCSI-chip.
This is the slowest and most stupid of our SCSI-drivers, but it is there and it works. It has been tested with CD-ROM and disk. It uses no interrupts, no DMA, just polled I/0. Transfer-rate is <= 100Kbyte/sec. If you set the jumpers on the board, you can change the unit-number and you will be able to have four of these co-exist in one computer, why one would do that is somewhat unclear though. If I ever get my hand on the docs for this, I will improve it of course, but for now we can install and access those CD-ROMs.
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/NOTES8
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/i386/conf/GENERICAH3
-rw-r--r--sys/i386/conf/LINT8
-rw-r--r--sys/i386/conf/NOTES8
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/isa/ic/ncr_5380.h130
-rw-r--r--sys/i386/isa/pas.c1011
8 files changed, 1168 insertions, 6 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 90c79b8..75ff641 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -4,7 +4,7 @@
#
# This kernel is NOT MEANT to be runnable!
#
-# $Id: LINT,v 1.70 1994/05/17 23:20:32 jkh Exp $
+# $Id: LINT,v 1.71 1994/05/18 16:23:25 jkh Exp $
#
machine "i386"
@@ -158,6 +158,12 @@ device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr
# Driver for Logitech and ATI inport bus mice
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device npx0 at isa? port "IO_NPX" irq 13 vector npxintr
+# Driver for ProAudioSpectrum SCSI, on cards with NCR 5380 chips.
+# The four units correspond to the HW-jumpers. No intr, No DMA, very slow.
+device pas0 at isa? port 0x1f88
+device pas1 at isa? port 0x1f84
+device pas2 at isa? port 0x1f8c
+device pas3 at isa? port 0x1e88
device pc0 at isa? port "IO_KBD" tty irq 1 vector pcrint
#only one of pc0 or sc0 allowed
#device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index b7a8604..1c744ee 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.34 1994/05/25 08:52:02 rgrimes Exp $
+# $Id: files.i386,v 1.35 1994/08/12 06:51:02 davidg Exp $
#
i386/i386/autoconf.c standard device-driver
i386/i386/cons.c standard
@@ -38,6 +38,7 @@ i386/isa/lpt.c optional lpt device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
i386/isa/npx.c optional npx device-driver
+i386/isa/pas.c optional pas device-driver
i386/isa/syscons.c optional sc device-driver
i386/isa/pccons.c optional pc device-driver
i386/isa/pcaudio.c optional pca device-driver
diff --git a/sys/i386/conf/GENERICAH b/sys/i386/conf/GENERICAH
index 720cd88..3818f1d 100644
--- a/sys/i386/conf/GENERICAH
+++ b/sys/i386/conf/GENERICAH
@@ -1,7 +1,7 @@
#
# GENERICAH -- Generic machine with WD/AHx family disks
#
-# $Id: GENERICAH,v 1.35 1994/07/28 05:53:43 davidg Exp $
+# $Id: GENERICAH,v 1.36 1994/08/09 08:17:08 davidg Exp $
#
machine "i386"
@@ -70,6 +70,7 @@ device cd0 #Only need one of these, the code dynamically grows
device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr
device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr
device mcd1 at isa? port 0x340 bio irq 11 vector mcdintr
+device pas0 at isa? port 0x1f88 bio
device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr
device npx0 at isa? port "IO_NPX" irq 13 vector npxintr
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index 90c79b8..75ff641 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -4,7 +4,7 @@
#
# This kernel is NOT MEANT to be runnable!
#
-# $Id: LINT,v 1.70 1994/05/17 23:20:32 jkh Exp $
+# $Id: LINT,v 1.71 1994/05/18 16:23:25 jkh Exp $
#
machine "i386"
@@ -158,6 +158,12 @@ device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr
# Driver for Logitech and ATI inport bus mice
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device npx0 at isa? port "IO_NPX" irq 13 vector npxintr
+# Driver for ProAudioSpectrum SCSI, on cards with NCR 5380 chips.
+# The four units correspond to the HW-jumpers. No intr, No DMA, very slow.
+device pas0 at isa? port 0x1f88
+device pas1 at isa? port 0x1f84
+device pas2 at isa? port 0x1f8c
+device pas3 at isa? port 0x1e88
device pc0 at isa? port "IO_KBD" tty irq 1 vector pcrint
#only one of pc0 or sc0 allowed
#device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 90c79b8..75ff641 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -4,7 +4,7 @@
#
# This kernel is NOT MEANT to be runnable!
#
-# $Id: LINT,v 1.70 1994/05/17 23:20:32 jkh Exp $
+# $Id: LINT,v 1.71 1994/05/18 16:23:25 jkh Exp $
#
machine "i386"
@@ -158,6 +158,12 @@ device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr
# Driver for Logitech and ATI inport bus mice
device mse0 at isa? port 0x23c tty irq 5 vector mseintr
device npx0 at isa? port "IO_NPX" irq 13 vector npxintr
+# Driver for ProAudioSpectrum SCSI, on cards with NCR 5380 chips.
+# The four units correspond to the HW-jumpers. No intr, No DMA, very slow.
+device pas0 at isa? port 0x1f88
+device pas1 at isa? port 0x1f84
+device pas2 at isa? port 0x1f8c
+device pas3 at isa? port 0x1e88
device pc0 at isa? port "IO_KBD" tty irq 1 vector pcrint
#only one of pc0 or sc0 allowed
#device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index b7a8604..1c744ee 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.34 1994/05/25 08:52:02 rgrimes Exp $
+# $Id: files.i386,v 1.35 1994/08/12 06:51:02 davidg Exp $
#
i386/i386/autoconf.c standard device-driver
i386/i386/cons.c standard
@@ -38,6 +38,7 @@ i386/isa/lpt.c optional lpt device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
i386/isa/npx.c optional npx device-driver
+i386/isa/pas.c optional pas device-driver
i386/isa/syscons.c optional sc device-driver
i386/isa/pccons.c optional pc device-driver
i386/isa/pcaudio.c optional pca device-driver
diff --git a/sys/i386/isa/ic/ncr_5380.h b/sys/i386/isa/ic/ncr_5380.h
new file mode 100644
index 0000000..1effe49
--- /dev/null
+++ b/sys/i386/isa/ic/ncr_5380.h
@@ -0,0 +1,130 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#ifndef _IC_NCR_5380_H_
+#define _IC_NCR_5380_H_
+
+/*
+ * Register map
+ */
+
+typedef struct {
+ volatile u_char sci_data; /* r: Current data */
+#define sci_odata sci_data /* w: Out data */
+
+ volatile u_char sci_icmd; /* rw:Initiator command */
+
+ volatile u_char sci_mode; /* rw:Mode */
+
+ volatile u_char sci_tcmd; /* rw:Target command */
+
+ volatile u_char sci_bus_csr;/* r: Bus Status */
+#define sci_sel_enb sci_bus_csr /* w: Select enable */
+
+ volatile u_char sci_csr; /* r: Status */
+#define sci_dma_send sci_csr /* w: Start dma send data */
+
+ volatile u_char sci_idata; /* r: Input data */
+#define sci_trecv sci_idata /* w: Start dma recv, target */
+
+ volatile u_char sci_iack; /* r: Interrupt Acknowledge */
+#define sci_irecv sci_iack /* w: Start dma recv, initiator */
+} sci_regmap_t;
+
+
+/*
+ * Initiator command register
+ */
+
+#define SCI_ICMD_DATA 0x01 /* rw:Assert data bus */
+#define SCI_ICMD_ATN 0x02 /* rw:Assert ATN signal */
+#define SCI_ICMD_SEL 0x04 /* rw:Assert SEL signal */
+#define SCI_ICMD_BSY 0x08 /* rw:Assert BSY signal */
+#define SCI_ICMD_ACK 0x10 /* rw:Assert ACK signal */
+#define SCI_ICMD_LST 0x20 /* r: Lost arbitration */
+#define SCI_ICMD_DIFF SCI_ICMD_LST /* w: Differential cable */
+#define SCI_ICMD_AIP 0x40 /* r: Arbitration in progress */
+#define SCI_ICMD_TEST SCI_ICMD_AIP /* w: Test mode */
+#define SCI_ICMD_RST 0x80 /* rw:Assert RST signal */
+
+
+/*
+ * Mode register
+ */
+
+#define SCI_MODE_ARB 0x01 /* rw: Start arbitration */
+#define SCI_MODE_DMA 0x02 /* rw: Enable DMA xfers */
+#define SCI_MODE_MONBSY 0x04 /* rw: Monitor BSY signal */
+#define SCI_MODE_DMA_IE 0x08 /* rw: Enable DMA complete interrupt */
+#define SCI_MODE_PERR_IE 0x10 /* rw: Interrupt on parity errors */
+#define SCI_MODE_PAR_CHK 0x20 /* rw: Check parity */
+#define SCI_MODE_TARGET 0x40 /* rw: Target mode (Initiator if 0) */
+#define SCI_MODE_BLOCKDMA 0x80 /* rw: Block-mode DMA handshake (MBZ) */
+
+
+/*
+ * Target command register
+ */
+
+#define SCI_TCMD_IO 0x01 /* rw: Assert I/O signal */
+#define SCI_TCMD_CD 0x02 /* rw: Assert C/D signal */
+#define SCI_TCMD_MSG 0x04 /* rw: Assert MSG signal */
+#define SCI_TCMD_PHASE_MASK 0x07 /* r: Mask for current bus phase */
+#define SCI_TCMD_REQ 0x08 /* rw: Assert REQ signal */
+#define SCI_TCMD_LAST_SENT 0x80 /* ro: Last byte was xferred
+ * (not on 5380/1) */
+
+#define SCI_PHASE(x) SCSI_PHASE(x)
+
+/*
+ * Current (SCSI) Bus status
+ */
+
+#define SCI_BUS_DBP 0x01 /* r: Data Bus parity */
+#define SCI_BUS_SEL 0x02 /* r: SEL signal */
+#define SCI_BUS_IO 0x04 /* r: I/O signal */
+#define SCI_BUS_CD 0x08 /* r: C/D signal */
+#define SCI_BUS_MSG 0x10 /* r: MSG signal */
+#define SCI_BUS_REQ 0x20 /* r: REQ signal */
+#define SCI_BUS_BSY 0x40 /* r: BSY signal */
+#define SCI_BUS_RST 0x80 /* r: RST signal */
+
+#define SCI_CUR_PHASE(x) SCSI_PHASE((x)>>2)
+
+/*
+ * Bus and Status register
+ */
+
+#define SCI_CSR_ACK 0x01 /* r: ACK signal */
+#define SCI_CSR_ATN 0x02 /* r: ATN signal */
+#define SCI_CSR_DISC 0x04 /* r: Disconnected (BSY==0) */
+#define SCI_CSR_PHASE_MATCH 0x08 /* r: Bus and SCI_TCMD match */
+#define SCI_CSR_INT 0x10 /* r: Interrupt request */
+#define SCI_CSR_PERR 0x20 /* r: Parity error */
+#define SCI_CSR_DREQ 0x40 /* r: DMA request */
+#define SCI_CSR_DONE 0x80 /* r: DMA count is zero */
+
+#endif /* _IC_NCR_5380_H_ */
diff --git a/sys/i386/isa/pas.c b/sys/i386/isa/pas.c
new file mode 100644
index 0000000..e0bbbc0
--- /dev/null
+++ b/sys/i386/isa/pas.c
@@ -0,0 +1,1011 @@
+/*-
+ * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
+ * Michael L. Finch, Bradley A. Grantham, and
+ * Lawrence A. Kesteloot
+ * Copyright (C) 1994 Poul-Henning Kamp
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Alice Group.
+ * 4. The names of the Alice Group or any of its members may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``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 ALICE GROUP 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.
+ *
+ * $Id: pas.c,v 1.8.2.1 1994/07/11 00:02:32 cgd Exp $
+ *
+ */
+
+/* Modified for use with the pc532 by Phil Nelson, Feb 94.
+ * Modified for use with MediaVision ProAudioSpectrum type adapters
+ * under FreeBSD by Poul-Henning Kamp,
+ */
+
+
+#include "pas.h"
+#if NPAS > 0
+#include "types.h"
+#include "param.h"
+#include "systm.h"
+#include "conf.h"
+#include "file.h"
+#include "buf.h"
+#include "stat.h"
+#include "uio.h"
+#include "ioctl.h"
+#include "cdio.h"
+#include "errno.h"
+#include "dkbad.h"
+#include "disklabel.h"
+#include "icu.h"
+#include "i386/isa/isa.h"
+#include "i386/isa/isa_device.h"
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+#include "ic/ncr_5380.h"
+
+/* What we need to debug the driver */
+
+#ifdef PAS_DEBUG
+static int pas_show_scsi_cmd(struct scsi_xfer *xs);
+#define HERE() printf("<%d>",__LINE__)
+#define ARGH() printf("[%d]",__LINE__)
+#else /* PAS_DEBUG */
+#define HERE() /**/
+#define ARGH() /**/
+#endif /* PAS_DEBUG */
+
+#define SCSI_PHASE_DATA_OUT 0x0
+#define SCSI_PHASE_DATA_IN 0x1
+#define SCSI_PHASE_CMD 0x2
+#define SCSI_PHASE_STATUS 0x3
+#define SCSI_PHASE_UNSPEC1 0x4
+#define SCSI_PHASE_UNSPEC2 0x5
+#define SCSI_PHASE_MESSAGE_OUT 0x6
+#define SCSI_PHASE_MESSAGE_IN 0x7
+
+#define SCSI_PHASE(x) ((x)&0x7)
+
+#define SCSI_RET_SUCCESS 0
+#define SCSI_RET_RETRY 1
+#define SCSI_RET_DEVICE_DOWN 2
+#define SCSI_RET_COMMAND_FAIL 3
+
+/* Our per device (card) structure */
+static
+struct pas_softc {
+ struct scsi_link sc_link;
+ int mv_unit;
+ u_short iobase;
+#define sci_data(ptr) (ptr->iobase+0x0)
+#define sci_icmd(ptr) (ptr->iobase+0x1)
+#define sci_mode(ptr) (ptr->iobase+0x2)
+#define sci_tcmd(ptr) (ptr->iobase+0x3)
+#define sci_bus_csr(ptr) (ptr->iobase+0x2000)
+#define sci_csr(ptr) (ptr->iobase+0x2001)
+#define sci_idata(ptr) (ptr->iobase+0x2002)
+#define sci_iack(ptr) (ptr->iobase+0x2003)
+#define sci_pdmadata(ptr) (ptr->iobase+0x4000)
+#define sci_pdmastat(ptr) (ptr->iobase+0x4001)
+} s_pas[NPAS];
+
+/* Our access to the 5380 chip */
+#define P_PAS struct pas_softc *
+#define R_PAS(ptr,foo) inb(foo(ptr))
+#define W_PAS(ptr,foo,val) outb(foo(ptr),val)
+#define M_PAS(ptr,foo,opr,arg) outb(foo(ptr),R_PAS(ptr,foo) opr arg)
+#define PSEUDO_DMA 0
+#if PSEUDO_DMA
+/*
+static int sci_pdma_out(P_PAS, int, int, u_char *);
+*/
+#define sci_pdma_out sci_data_out
+static int sci_pdma_in(P_PAS, int, int, u_char *);
+
+#else /* PSEUDO_DMA */
+#define sci_pdma_out sci_data_out
+#define sci_pdma_in sci_data_in
+#endif /* PSEUDO_DMA */
+
+
+
+static int pas_foo;
+#define SCI_CLR_INTR(ptr) {pas_foo += R_PAS(ptr,sci_iack);}
+#define SCI_PHASE_DISC 0 /* sort of ... */
+#define SCI_ACK(ptr,phase) {W_PAS(ptr,sci_tcmd,phase);}
+#define SCSI_TIMEOUT_VAL 10000000
+#define WAIT_FOR_NOT_REQ(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ( (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \
+ (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \
+ (R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_NOT_REQ-- pas.c:%d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+}
+#define WAIT_FOR_REQ(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ( ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \
+ ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \
+ ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_REQ) == 0) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_REQ-- pas.c:%d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+}
+#define WAIT_FOR_BSY(ptr) { \
+ int scsi_timeout = SCSI_TIMEOUT_VAL; \
+ while ( ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \
+ ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \
+ ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) && \
+ (--scsi_timeout) ); \
+ if (!scsi_timeout) { \
+ printf("scsi timeout--WAIT_FOR_BSY-- pas.c:%d.\n", __LINE__); \
+ goto scsi_timeout_error; \
+ } \
+}
+
+static u_int32 pas_adapter_info(int adapter_number);
+static void pas_minphys(struct buf *bp);
+static int32 pas_scsi_cmd(struct scsi_xfer *xs);
+
+static int pas_reset_target(int adapter, int target);
+static int pas_poll(int adapter, int timeout);
+static int pas_send_cmd(struct scsi_xfer *xs);
+static int scsi_req(P_PAS,int,int,u_char *,int,
+ u_char *, int , int *, int *);
+
+static int scsi_group0(int adapter, int id, int lun,
+ int opcode, int addr, int len,
+ int flags, caddr_t databuf, int datalen);
+
+static int sci_data_out(P_PAS, int, int, u_char *);
+static int sci_data_in(P_PAS, int, int, u_char *);
+
+extern int pasprobe(struct isa_device *dev);
+extern int pasattach(struct isa_device *dev);
+struct isa_driver pasdriver = { pasprobe, pasattach, "pas" };
+
+
+static
+struct scsi_adapter pas_adapter = {
+ pas_scsi_cmd, /* scsi_cmd() */
+ pas_minphys, /* scsi_minphys() */
+ 0, /* open_target_lu() */
+ 0, /* close_target_lu() */
+ pas_adapter_info, /* adapter_info() */
+"pas", /* name */
+ { 0, 0 } /* spare[2] */
+};
+
+static
+struct scsi_device pas_dev = {
+ NULL, /* Use default error handler. */
+ NULL, /* have a queue, served by this (?) */
+ NULL, /* have no async handler. */
+ NULL, /* Use default "done" routine. */
+ "pas",
+ 0,
+ { 0, 0 }
+};
+
+static char *mv_type[] = { "?" "PAS","PAS+","CDPC","PAS16C","PAS16D" };
+
+
+int
+pasprobe(struct isa_device *dev)
+{
+ int port = dev->id_iobase;
+ int base = port - 0x1c00;
+ int unit = dev->id_unit;
+ int i, j;
+
+ /* Tell the PAS16 we want to talk to, where to listen */
+ outb(0x9a01,0xbc + unit);
+ outb(0x9a01,base >> 2);
+
+ /* Various magic */
+ outb(base+0x4000,0x30);
+ outb(base+0x4001,0x01);
+ outb(base+0xbc00,0x01);
+
+ /* Killer one */
+ i = inb(base + 0x803);
+ if(i == 0xff) return 0;
+
+ /* killer two */
+ outb(base+0x803,i ^ 0xe0);
+ j = inb(base + 0x803);
+ outb(base+0x803,1);
+ if(i != j) return 0;
+
+ /* killer three */
+ if((0x03 & inb(base+0xec03)) != 0x03) return 0;
+
+ /* killer four */
+ for(i=0;i<4;i++) {
+ if(inb(port) != 0xff || inb(port+0x2000) != 0xff)
+ return 1;
+ }
+ return 0;
+}
+
+static u_int32
+pas_adapter_info(int adapter_number)
+{
+ return 1;
+}
+
+int
+pasattach(struct isa_device *dev)
+{
+ int i,j;
+ struct pas_softc *ppas;
+ i = inb(dev->id_iobase - 0x1c00 + 0xFC00) >> 5;
+ if(i >= (sizeof mv_type / sizeof *mv_type))
+ j=0;
+ else
+ j = i+1;
+ printf("pas%d: Type = %d <%s>\n",dev->id_unit,i,mv_type[j]);
+ ppas = s_pas + dev->id_unit;
+ ppas->sc_link.adapter_unit = dev->id_unit;
+ ppas->sc_link.adapter_targ = 7;
+ ppas->sc_link.adapter = &pas_adapter;
+ ppas->sc_link.device = &pas_dev;
+ ppas->iobase=dev->id_iobase;
+#ifdef STILL_NO_INTR
+/* As of yet we havn't bothered with interrupts, so don't bother */
+ j = inb(dev->id_iobase - 0x1c00 + 0xf002);
+ switch (dev->id_irq) {
+ case IRQ2: i=1; break;
+ case IRQ3: i=2; break;
+ case IRQ4: i=3; break;
+ case IRQ5: i=4; break;
+ case IRQ6: i=5; break;
+ case IRQ7: i=6; break;
+ case IRQ10: i=7; break;
+ case IRQ11: i=8; break;
+ case IRQ12: i=9; break;
+ case IRQ14: i=10; break;
+ case IRQ15: i=11; break;
+ default:
+ printf("Intr %d unknown\n",dev->id_irq);
+ panic("brag!");
+ }
+ printf("0xf002 irq%d code=%x, before %x,",dev->id_irq,i,j);
+ j &= 0x0f;
+ j |= (i << 4);
+ printf(" after= %x \n",j);
+ outb(dev->id_iobase - 0x1c00 + 0xf002,j);
+ outb(dev->id_iobase - 0x1c00 + 0x8003,0x4d);
+#endif /* STILL_NO_INTR */
+ scsi_attachdevs(&(ppas->sc_link));
+ return 1;
+}
+
+static void
+pas_minphys(struct buf *bp)
+{
+#define MIN_PHYS 65536 /*BARF!!!!*/
+ if (bp->b_bcount > MIN_PHYS) {
+ printf("Uh-oh... pas_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
+ bp->b_bcount = MIN_PHYS;
+ }
+#undef MIN_PHYS
+}
+
+static int32
+pas_scsi_cmd(struct scsi_xfer *xs)
+{
+ int flags, s, r;
+
+ flags = xs->flags;
+ if (xs->bp) flags |= (SCSI_NOSLEEP);
+ if ( flags & ITSDONE ) {
+ printf("Already done?");
+ xs->flags &= ~ITSDONE;
+ }
+ if ( ! ( flags & INUSE ) ) {
+ printf("Not in use?");
+ xs->flags |= INUSE;
+ }
+
+ if ( flags & SCSI_RESET ) {
+ printf("flags & SCSIRESET.\n");
+ if ( ! ( flags & SCSI_NOSLEEP ) ) {
+ s = splbio();
+ pas_reset_target(xs->sc_link->adapter_unit,
+ xs->sc_link->target);
+ splx(s);
+ return(SUCCESSFULLY_QUEUED);
+ } else {
+ pas_reset_target(xs->sc_link->adapter_unit, xs->sc_link->target);
+ if (pas_poll(xs->sc_link->adapter_unit, xs->timeout)) {
+ return (HAD_ERROR);
+ }
+ return (COMPLETE);
+ }
+ }
+ /*
+ * OK. Now that that's over with, let's pack up that
+ * SCSI puppy and send it off. If we can, we'll just
+ * queue and go; otherwise, we'll wait for the command
+ * to finish.
+ if ( ! ( flags & SCSI_NOSLEEP ) ) {
+ s = splbio();
+ pas_send_cmd(xs);
+ splx(s);
+ return(SUCCESSFULLY_QUEUED);
+ }
+ */
+
+ r = pas_send_cmd(xs);
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+ if (xs->flags&SCSI_NOMASK) {
+ return (r);
+ }
+ return SUCCESSFULLY_QUEUED;
+}
+
+#ifdef PAS_DEBUG
+static int
+pas_show_scsi_cmd(struct scsi_xfer *xs)
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if ( ! ( xs->flags & SCSI_RESET ) ) {
+ printf("pas(%d:%d:%d) ",
+ xs->sc_link->adapter_unit, xs->sc_link->target, xs->sc_link->lun);
+ printf("%d@%x, %d@%x <",xs->cmdlen,xs->cmd,xs->datalen,xs->data);
+ while (i < xs->cmdlen) {
+ if (i) printf(",");
+ printf("%x",b[i++]);
+ }
+ printf(">\n");
+ } else {
+ printf("pas(%d:%d:%d)-RESET-\n",
+ xs->sc_link->adapter_unit, xs->sc_link->target,
+ xs->sc_link->lun);
+ }
+ return 0;
+}
+#endif /* PAS_DEBUG */
+
+/*
+ * Actual chip control.
+ */
+
+extern void
+pasintr(int adapter)
+{
+ struct pas_softc *ppas = s_pas + adapter;
+ printf ("pasintr\n");
+ SCI_CLR_INTR(ppas);
+ W_PAS(ppas,sci_mode,0x00);
+}
+
+#if PHK
+extern int
+scsi_irq_intr(void)
+{
+
+/* if (R_PAS(ptr,sci_csr) != SCI_CSR_PHASE_MATCH)
+ printf("scsi_irq_intr called (not just phase match -- "
+ "csr = 0x%x, bus_csr = 0x%x).\n",
+ R_PAS(ptr,sci_csr), R_PAS(ptr,sci_bus_csr));
+ pas_intr(0); */
+ return 1;
+}
+#endif
+
+static int
+pas_reset_target(int adapter, int target)
+{
+ struct pas_softc *ppas = s_pas + adapter;
+
+ W_PAS(ppas,sci_icmd,SCI_ICMD_TEST);
+ W_PAS(ppas,sci_icmd,SCI_ICMD_TEST | SCI_ICMD_RST);
+ DELAY(2500);
+ W_PAS(ppas,sci_icmd,0);
+
+ W_PAS(ppas,sci_mode,0);
+ W_PAS(ppas,sci_tcmd,SCI_PHASE_DISC);
+ W_PAS(ppas,sci_sel_enb,0);
+
+ SCI_CLR_INTR(ppas);
+ SCI_CLR_INTR(ppas);
+ return 0;
+}
+
+static int
+pas_poll(int adapter, int timeout)
+{
+ return 0;
+}
+
+static int
+pas_send_cmd(struct scsi_xfer *xs)
+{
+ P_PAS ptr = s_pas + xs->sc_link->adapter_unit;
+ int s,sent,ret;
+ int sense;
+
+#ifdef PAS_DEBUG
+ pas_show_scsi_cmd(xs);
+#endif /* PAS_DEBUG */
+ s = splbio();
+ sense = scsi_req(ptr,
+ xs->sc_link->target, xs->sc_link->lun,
+ (u_char*)xs->cmd, xs->cmdlen, xs->data, xs->datalen,
+ &sent, &ret);
+ splx(s);
+#ifdef PAS_DEBUG
+HERE();
+ printf("sent=%d,ret=%d,sense=%x ",sent,ret,sense);
+#endif /* PAS_DEBUG */
+ switch (sense) {
+ case 0x00:
+ xs->error = XS_NOERROR;
+ xs->resid = sent;
+#ifdef PAS_DEBUG
+ printf("\n");
+#endif /* PAS_DEBUG */
+ return (COMPLETE);
+ case 0x02: /* Check condition */
+#ifdef PAS_DEBUG
+ printf("check cond. targ= %d.\n", xs->sc_link->target);
+#endif
+ spinwait(10);
+ s = splbio();
+ scsi_group0(xs->sc_link->adapter_unit,
+ xs->sc_link->target, xs->sc_link->lun,
+ 0x3, 0x0,
+ sizeof(struct scsi_sense_data),
+ 0, (caddr_t) &(xs->sense),
+ sizeof(struct scsi_sense_data));
+ splx(s);
+ xs->error = XS_SENSE;
+ return HAD_ERROR;
+ case 0x08: /* Busy */
+ARGH();
+ xs->error = XS_BUSY;
+ return HAD_ERROR;
+ default:
+ARGH();
+ xs->error = XS_DRIVER_STUFFUP;
+ return HAD_ERROR;
+ }
+}
+
+static int
+select_target(P_PAS ptr, u_char myid, u_char tid, int with_atn)
+{
+ register u_char bid, icmd;
+ int ret = SCSI_RET_RETRY;
+ if ((R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
+ (R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
+ (R_PAS(ptr,sci_bus_csr) & (SCI_BUS_BSY|SCI_BUS_SEL)))
+ return ret;
+
+ /* for our purposes.. */
+ myid = 1 << myid;
+ tid = 1 << tid;
+
+ W_PAS(ptr,sci_sel_enb,0); /* we don't want any interrupts. */
+ W_PAS(ptr,sci_tcmd,0); /* get into a harmless state */
+ W_PAS(ptr,sci_mode,0); /* get into a harmless state */
+
+ W_PAS(ptr,sci_odata,myid);
+ W_PAS(ptr,sci_mode,SCI_MODE_ARB);
+
+ /* AIP might not set if BSY went true after we checked */
+ for (bid = 0; bid < 20; bid++) /* 20usec circa */
+ if (R_PAS(ptr,sci_icmd) & SCI_ICMD_AIP)
+ break;
+ if ((R_PAS(ptr,sci_icmd) & SCI_ICMD_AIP) == 0) {
+ARGH();
+ goto lost;
+ }
+
+ spinwait(2 /* was 2 */); /* 2.2us arb delay */
+
+ if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) {
+printf ("lost 1\n");
+ goto lost;
+ }
+
+ M_PAS(ptr,sci_mode,&, ~SCI_MODE_PAR_CHK);
+ bid = R_PAS(ptr,sci_data);
+
+ if ((bid & ~myid) > myid) {
+printf ("lost 2\n");
+ goto lost;
+ }
+ if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) {
+printf ("lost 3\n");
+ goto lost;
+ }
+
+ /* Won arbitration, enter selection phase now */
+ icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+ icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
+ icmd |= SCI_ICMD_BSY;
+ W_PAS(ptr,sci_icmd,icmd);
+
+ if (R_PAS(ptr,sci_icmd) & SCI_ICMD_LST) {
+printf ("nosel\n");
+ goto nosel;
+ }
+
+ /* XXX a target that violates specs might still drive the bus XXX */
+ /* XXX should put our id out, and after the delay check nothi XXX */
+ /* XXX ng else is out there. XXX */
+
+ DELAY(0);
+
+ W_PAS(ptr,sci_tcmd,0);
+ W_PAS(ptr,sci_odata,myid|tid);
+ W_PAS(ptr,sci_sel_enb,0);
+
+ M_PAS(ptr,sci_mode, &, ~SCI_MODE_ARB); /* 2 deskew delays, too */
+ W_PAS(ptr,sci_mode,0);
+
+ icmd |= SCI_ICMD_DATA;
+ icmd &= ~(SCI_ICMD_BSY);
+
+ W_PAS(ptr,sci_icmd,icmd);
+
+ /* bus settle delay, 400ns */
+ DELAY(2); /* too much (was 2) ? */
+
+/* M_PAS(ptr,sci_mode, |, SCI_MODE_PAR_CHK); */
+
+ {
+ register int timeo = 2500;/* 250 msecs in 100 usecs chunks */
+ while ((R_PAS(ptr,sci_bus_csr) & SCI_BUS_BSY) == 0) {
+ if (--timeo > 0) {
+ DELAY(100);
+ } else {
+ARGH();
+ goto nodev;
+ }
+ }
+ }
+
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
+ W_PAS(ptr,sci_icmd,icmd);
+/* ptr->sci_sel_enb = myid;*/ /* looks like we should NOT have it */
+ return SCSI_RET_SUCCESS;
+nodev:
+ ret = SCSI_RET_DEVICE_DOWN;
+ W_PAS(ptr,sci_sel_enb,myid);
+nosel:
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
+ W_PAS(ptr,sci_icmd,icmd);
+lost:
+ W_PAS(ptr,sci_mode,0);
+
+ return ret;
+}
+
+static int
+sci_data_out(P_PAS ptr, int phase, int count, u_char *data)
+{
+ register unsigned char icmd;
+ register int cnt=0;
+
+#ifdef PAS_DEBUG
+ printf("out%d@%x ",count,data);
+#endif /* PAS_DEBUG */
+ /* ..checks.. */
+
+ icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+loop:
+ if (SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)) != phase)
+ return cnt;
+
+ WAIT_FOR_REQ(ptr);
+ icmd |= SCI_ICMD_DATA;
+ W_PAS(ptr,sci_icmd,icmd);
+ W_PAS(ptr,sci_odata, *data++);
+ icmd |= SCI_ICMD_ACK;
+ W_PAS(ptr,sci_icmd,icmd);
+
+ icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
+ WAIT_FOR_NOT_REQ(ptr);
+ W_PAS(ptr,sci_icmd,icmd);
+ ++cnt;
+ if (--count > 0)
+ goto loop;
+scsi_timeout_error:
+ return cnt;
+}
+
+static int
+sci_data_in(P_PAS ptr, int phase, int count, u_char *data)
+{
+ register unsigned char icmd;
+ register int cnt=0;
+
+#ifdef PAS_DEBUG
+ printf("in%d@%x ",count,data);
+#endif /* PAS_DEBUG */
+ /* ..checks.. */
+
+ icmd = R_PAS(ptr,sci_icmd) & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
+
+loop:
+ if (SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr)) != phase)
+ return cnt;
+
+ WAIT_FOR_REQ(ptr);
+ *data++ = R_PAS(ptr,sci_data);
+
+ icmd |= SCI_ICMD_ACK;
+ W_PAS(ptr,sci_icmd,icmd);
+
+ icmd &= ~SCI_ICMD_ACK;
+ WAIT_FOR_NOT_REQ(ptr);
+ W_PAS(ptr,sci_icmd,icmd);
+ ++cnt;
+ if (--count > 0)
+ goto loop;
+
+scsi_timeout_error:
+ return cnt;
+}
+
+#if PSEUDO_DMA
+
+static int
+sci_pdma_in(P_PAS ptr, int phase, int count, u_char *data)
+{
+ register unsigned char icmd;
+ register int cnt=0;
+
+#ifdef PAS_DEBUG
+ printf("in%d@%x ",count,data);
+#endif /* PAS_DEBUG */
+
+ WAIT_FOR_BSY(ptr);
+ M_PAS(ptr,sci_mode, |, SCI_MODE_DMA);
+ W_PAS(ptr,sci_dma_send, 0);
+ M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA);
+
+/*
+ while(R_PAS(ptr,sci_pdmastat) & 0x80) ;
+*/
+
+ for(; cnt < count; cnt++)
+ *data++ = R_PAS(ptr,sci_pdmadata);
+
+scsi_timeout_error:
+ M_PAS(ptr,sci_mode, &, ~SCI_MODE_DMA);
+ M_PAS(ptr,sci_icmd, &, ~SCI_ICMD_DATA);
+ return cnt;
+}
+#endif /* PSEUDO_DMA */
+
+static int
+cmd_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg)
+{
+ int xfer=0, phase;
+
+#ifdef PAS_DEBUG
+ printf("cmd_xfer called for 0x%x.\n", *data);
+#endif /* PAS_DEBUG */
+
+ W_PAS(ptr,sci_icmd,0);
+
+ while (1) {
+
+ WAIT_FOR_REQ(ptr);
+
+ phase = SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr));
+
+ switch (phase) {
+ case SCSI_PHASE_CMD:
+ SCI_ACK(ptr,SCSI_PHASE_CMD);
+ xfer += sci_data_out(ptr, SCSI_PHASE_CMD, maxlen, data);
+ return xfer;
+ case SCSI_PHASE_DATA_IN:
+ printf("Data in phase in cmd_xfer?\n");
+ return 0;
+ case SCSI_PHASE_DATA_OUT:
+ printf("Data out phase in cmd_xfer?\n");
+ return 0;
+ case SCSI_PHASE_STATUS:
+ SCI_ACK(ptr,SCSI_PHASE_STATUS);
+ printf("status in cmd_xfer.\n");
+ sci_data_in(ptr, SCSI_PHASE_STATUS, 1, status);
+ break;
+ case SCSI_PHASE_MESSAGE_IN:
+ SCI_ACK(ptr,SCSI_PHASE_MESSAGE_IN);
+ printf("msgin in cmd_xfer.\n");
+ sci_data_in(ptr, SCSI_PHASE_MESSAGE_IN, 1, msg);
+ break;
+ case SCSI_PHASE_MESSAGE_OUT:
+ SCI_ACK(ptr,SCSI_PHASE_MESSAGE_OUT);
+ sci_data_out(ptr, SCSI_PHASE_MESSAGE_OUT, 1, msg);
+ break;
+ default:
+ printf("Unexpected phase 0x%x in cmd_xfer()\n", phase);
+scsi_timeout_error:
+ return xfer;
+ break;
+ }
+ }
+}
+
+static int
+data_xfer(P_PAS ptr, int maxlen, u_char *data, u_char *status, u_char *msg)
+{
+ int retlen = 0, xfer, phase;
+
+ W_PAS(ptr,sci_icmd,0);
+
+ *status = 0;
+
+ while (1) {
+
+ WAIT_FOR_REQ(ptr);
+
+ phase = SCI_CUR_PHASE(R_PAS(ptr,sci_bus_csr));
+ switch (phase) {
+ case SCSI_PHASE_CMD:
+ printf("Command phase in data_xfer().\n");
+ return retlen;
+ case SCSI_PHASE_DATA_IN:
+ SCI_ACK(ptr,SCSI_PHASE_DATA_IN);
+ xfer = sci_pdma_in (ptr, SCSI_PHASE_DATA_IN, maxlen, data);
+ retlen += xfer;
+ maxlen -= xfer;
+ break;
+ case SCSI_PHASE_DATA_OUT:
+ SCI_ACK(ptr,SCSI_PHASE_DATA_OUT);
+ xfer = sci_pdma_out (ptr, SCSI_PHASE_DATA_OUT, maxlen, data);
+ retlen += xfer;
+ maxlen -= xfer;
+ break;
+ case SCSI_PHASE_STATUS:
+ SCI_ACK(ptr,SCSI_PHASE_STATUS);
+ sci_data_in(ptr, SCSI_PHASE_STATUS, 1, status);
+ break;
+ case SCSI_PHASE_MESSAGE_IN:
+ SCI_ACK(ptr,SCSI_PHASE_MESSAGE_IN);
+ sci_data_in(ptr, SCSI_PHASE_MESSAGE_IN, 1, msg);
+ if (*msg == 0) {
+ return retlen;
+ } else {
+ printf( "message 0x%x in data_xfer.\n", *msg);
+ }
+ break;
+ case SCSI_PHASE_MESSAGE_OUT:
+ SCI_ACK(ptr,SCSI_PHASE_MESSAGE_OUT);
+ sci_data_out(ptr, SCSI_PHASE_MESSAGE_OUT, 1, msg);
+ break;
+ default:
+ printf( "Unexpected phase 0x%x in data_xfer().\n",
+ phase);
+scsi_timeout_error:
+ return retlen;
+ break;
+ }
+ }
+}
+
+static int
+scsi_req(P_PAS ptr, int target, int lun, u_char *cmd, int cmdlen,
+ u_char *databuf, int datalen, int *sent, int *ret)
+{
+/* Returns 0 on success, -1 on internal error, or the status byte */
+ int cmd_bytes_sent, r;
+ u_char stat, msg, c;
+
+ *sent = 0;
+ if ( ( r = select_target(ptr, 7, target, 1) ) != SCSI_RET_SUCCESS) {
+ *ret = r;
+ SCI_CLR_INTR(ptr);
+ switch (r) {
+ case SCSI_RET_RETRY:
+ARGH();
+ return 0x08;
+ default:
+ printf("select_target(target %d, lun %d) failed(%d).\n",
+ target, lun, r);
+ case SCSI_RET_DEVICE_DOWN:
+ return -1;
+ }
+ }
+
+ c = 0x80 | lun;
+
+ if ((cmd_bytes_sent = cmd_xfer(ptr, cmdlen, cmd, &stat, &c))
+ != cmdlen) {
+ARGH();
+ SCI_CLR_INTR(ptr);
+ *ret = SCSI_RET_COMMAND_FAIL;
+ printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
+ cmd_bytes_sent, cmdlen);
+ return -1;
+ }
+
+ *sent=data_xfer(ptr, datalen, databuf, &stat, &msg);
+
+ *ret = 0;
+#ifdef PAS_DEBUG
+ printf("scsi_req,stat=0x%x ",stat);
+#endif /* PAS_DEBUG */
+ return stat;
+}
+
+static int
+scsi_group0(int adapter, int id, int lun,
+ int opcode, int addr, int len,
+ int flags, caddr_t databuf, int datalen)
+{
+ P_PAS ptr = s_pas + adapter;
+ unsigned char cmd[6];
+ int i,sent,ret;
+
+ cmd[0] = opcode; /* Operation code */
+ cmd[1] = (lun<<5) | ((addr>>16) & 0x1F); /* Lun & MSB of addr */
+ cmd[2] = (addr >> 8) & 0xFF; /* addr */
+ cmd[3] = addr & 0xFF; /* LSB of addr */
+ cmd[4] = len; /* Allocation length */
+ cmd[5] = flags; /* Link/Flag */
+
+ i = scsi_req(ptr, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
+
+ return i;
+}
+
+/* pseudo-dma action */
+
+#if 0 && PSEUDO_DMA
+
+static int pas_debug=1;
+#define W1 *byte_data = *data++
+#define W4 *long_data = *((long*)data)++
+
+int
+sci_pdma_out(ptr, phase, count, data)
+ P_PAS ptr;
+ int phase;
+ int count;
+ u_char *data;
+{
+ register volatile long *long_data = sci_4byte_addr;
+ register volatile u_char *byte_data = sci_1byte_addr;
+ register int len = count, i;
+
+pas_debug=1;
+
+ if (count < 128)
+ return sci_data_out(ptr, phase, count, data);
+
+ WAIT_FOR_BSY(ptr);
+ M_PAS(ptr,sci_mode, |, SCI_MODE_DMA);
+ M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA);
+ W_PAS(ptr,sci_dma_send,0);
+
+ while ( len >= 64 ) {
+ READY(1); W1; READY(1); W1; READY(1); W1; READY(1); W1;
+ READY(1);
+ W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4; W4;W4;W4;W4;
+ len -= 64;
+ }
+ while (len) {
+ READY(1);
+ W1;
+ len--;
+ }
+ i = TIMEOUT;
+ while ( ((R_PAS(ptr,sci_csr) & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
+ == SCI_CSR_PHASE_MATCH) && --i);
+ if (!i)
+ printf("pas.c:%d: timeout waiting for SCI_CSR_DREQ.\n", __LINE__);
+ *byte_data = 0;
+scsi_timeout_error:
+ M_PAS(ptr,sci_mode,&, ~SCI_MODE_DMA);
+ return count-len;
+}
+
+#undef W1
+#undef W4
+
+#define R4 *((long *)data)++ = *long_data
+#define R1 *data++ = *byte_data
+
+int
+sci_pdma_in(ptr, phase, count, data)
+ P_PAS ptr;
+ int phase;
+ int count;
+ u_char *data;
+{
+ register volatile long *long_data = sci_4byte_addr;
+ register volatile u_char *byte_data = sci_1byte_addr;
+ register int len = count, i;
+
+pas_debug=2;
+ if (count < 128)
+ return sci_data_in(ptr, phase, count, data);
+
+/* printf("Called sci_pdma_in(0x%x, 0x%x, %d, 0x%x.\n", ptr, phase, count, data); */
+
+ WAIT_FOR_BSY(ptr);
+ M_PAS(ptr,sci_mode, |, SCI_MODE_DMA);
+ M_PAS(ptr,sci_icmd, |, SCI_ICMD_DATA);
+ W_PAS(ptr,sci_irecv, 0);
+
+ while (len >= 1024) {
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 256 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 384 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 512 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 640 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 768 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 896 */
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /*1024 */
+ len -= 1024;
+ }
+ while (len >= 128) {
+ READY(0);
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4;
+ R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; R4;R4;R4;R4; /* 128 */
+ len -= 128;
+ }
+ while (len) {
+ READY(0);
+ R1;
+ len--;
+ }
+scsi_timeout_error:
+ M_PAS(ptr,sci_mode, &, ~SCI_MODE_DMA);
+ return count - len;
+}
+#undef R4
+#undef R1
+#endif
+#endif /* NPAS */
OpenPOWER on IntegriCloud