summaryrefslogtreecommitdiff
path: root/sys/arch/alpha/tc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/alpha/tc')
-rw-r--r--sys/arch/alpha/tc/cfb.c12
-rw-r--r--sys/arch/alpha/tc/cfbvar.h2
-rw-r--r--sys/arch/alpha/tc/esp.c1207
-rw-r--r--sys/arch/alpha/tc/espreg.h11
-rw-r--r--sys/arch/alpha/tc/espvar.h178
-rw-r--r--sys/arch/alpha/tc/ioasic.c14
-rw-r--r--sys/arch/alpha/tc/ioasicreg.h2
-rw-r--r--sys/arch/alpha/tc/mcclock_ioasic.c2
-rw-r--r--sys/arch/alpha/tc/scc.c540
-rw-r--r--sys/arch/alpha/tc/sccreg.h2
-rw-r--r--sys/arch/alpha/tc/sccvar.h6
-rw-r--r--sys/arch/alpha/tc/sfb.c12
-rw-r--r--sys/arch/alpha/tc/sfbvar.h2
-rw-r--r--sys/arch/alpha/tc/tc_3000_300.c20
-rw-r--r--sys/arch/alpha/tc/tc_3000_300.h2
-rw-r--r--sys/arch/alpha/tc/tc_3000_500.c20
-rw-r--r--sys/arch/alpha/tc/tc_3000_500.h2
-rw-r--r--sys/arch/alpha/tc/tc_bus_io.c6
-rw-r--r--sys/arch/alpha/tc/tc_bus_mem.c27
-rw-r--r--sys/arch/alpha/tc/tc_conf.h8
-rw-r--r--sys/arch/alpha/tc/tc_machdep.h13
-rw-r--r--sys/arch/alpha/tc/tcasic.c11
-rw-r--r--sys/arch/alpha/tc/tcds.c28
-rw-r--r--sys/arch/alpha/tc/tcds_dma.c162
-rw-r--r--sys/arch/alpha/tc/tcdsreg.h10
-rw-r--r--sys/arch/alpha/tc/tcdsvar.h16
26 files changed, 1344 insertions, 971 deletions
diff --git a/sys/arch/alpha/tc/cfb.c b/sys/arch/alpha/tc/cfb.c
index 3db8a4d2783..0f78f75e769 100644
--- a/sys/arch/alpha/tc/cfb.c
+++ b/sys/arch/alpha/tc/cfb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: cfb.c,v 1.2 1996/07/29 23:01:56 niklas Exp $ */
-/* $NetBSD: cfb.c,v 1.1 1996/05/01 23:25:03 cgd Exp $ */
+/* $OpenBSD: cfb.c,v 1.3 1996/10/30 22:41:01 niklas Exp $ */
+/* $NetBSD: cfb.c,v 1.5 1996/10/13 03:00:27 christos Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -57,7 +57,7 @@
int cfbmatch __P((struct device *, void *, void *));
void cfbattach __P((struct device *, struct device *, void *));
-int cfbprint __P((void *, char *));
+int cfbprint __P((void *, /* const */ char *));
struct cfattach cfb_ca = {
sizeof(struct cfb_softc), cfbmatch, cfbattach,
@@ -89,7 +89,6 @@ cfbmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct cfdata *cf = match;
struct tc_attach_args *ta = aux;
if (strncmp("PMAG-BA ", ta->ta_modname, TC_ROM_LLEN) != 0)
@@ -109,7 +108,7 @@ cfb_getdevconfig(dense_addr, dc)
int i;
dc->dc_vaddr = dense_addr;
- dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */
+ dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */
dc->dc_size = CFB_SIZE;
ramdacregp = (char *)dc->dc_vaddr + CFB_RAMDAC_OFFSET;
@@ -169,7 +168,6 @@ cfbattach(parent, self, aux)
struct wscons_attach_args waa;
struct wscons_odev_spec *wo;
int console;
- char *x;
console = 0; /* XXX */
if (console)
@@ -208,7 +206,7 @@ cfbattach(parent, self, aux)
int
cfbprint(aux, pnp)
void *aux;
- char *pnp;
+ /* const */ char *pnp;
{
if (pnp)
diff --git a/sys/arch/alpha/tc/cfbvar.h b/sys/arch/alpha/tc/cfbvar.h
index 8434cf92910..73a514ece37 100644
--- a/sys/arch/alpha/tc/cfbvar.h
+++ b/sys/arch/alpha/tc/cfbvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cfbvar.h,v 1.2 1996/07/29 23:01:58 niklas Exp $ */
+/* $OpenBSD: cfbvar.h,v 1.3 1996/10/30 22:41:03 niklas Exp $ */
/* $NetBSD: cfbvar.h,v 1.1 1996/05/01 23:25:04 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/esp.c b/sys/arch/alpha/tc/esp.c
index 5e6cfb9fb8d..cb18590130c 100644
--- a/sys/arch/alpha/tc/esp.c
+++ b/sys/arch/alpha/tc/esp.c
@@ -1,5 +1,38 @@
-/* $OpenBSD: esp.c,v 1.5 1996/10/18 16:12:01 niklas Exp $ */
-/* $NetBSD: esp.c,v 1.8.4.1 1996/06/05 00:39:03 cgd Exp $ */
+/* $OpenBSD: esp.c,v 1.6 1996/10/30 22:41:04 niklas Exp $ */
+/* $NetBSD: esp.c,v 1.22 1996/10/15 21:30:19 mycroft Exp $ */
+
+#ifdef __sparc__
+#define SPARC_DRIVER
+#endif
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. 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 Charles M. Hannum.
+ * 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.
+ */
/*
* Copyright (c) 1994 Peter Galbavy
@@ -17,7 +50,7 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Peter Galbavy
- * 4. The name of the author may not be used to endorse or promote products
+ * 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
@@ -66,7 +99,7 @@
#include <sparc/dev/espreg.h>
#include <sparc/dev/espvar.h>
#else
-#include <machine/autoconf.h>
+#include <machine/autoconf.h> /* badaddr() prototype */
#include <dev/tc/tcvar.h>
#include <alpha/tc/tcdsvar.h>
#include <alpha/tc/espreg.h>
@@ -76,33 +109,39 @@
int esp_debug = 0; /*ESP_SHOWPHASE|ESP_SHOWMISC|ESP_SHOWTRAC|ESP_SHOWCMDS;*/
/*static*/ void espattach __P((struct device *, struct device *, void *));
-/*static*/ int espmatch __P((struct device *, void *, void *));
/*static*/ int espprint __P((void *, char *));
+/*static*/ int espmatch __P((struct device *, void *, void *));
+/*static*/ u_int esp_adapter_info __P((struct esp_softc *));
/*static*/ void espreadregs __P((struct esp_softc *));
-/*static*/ void espselect __P((struct esp_softc *,
- u_char, u_char, u_char *, u_char));
+/*static*/ void esp_select __P((struct esp_softc *, struct esp_ecb *));
+/*static*/ int esp_reselect __P((struct esp_softc *, int));
/*static*/ void esp_scsi_reset __P((struct esp_softc *));
/*static*/ void esp_reset __P((struct esp_softc *));
/*static*/ void esp_init __P((struct esp_softc *, int));
/*static*/ int esp_scsi_cmd __P((struct scsi_xfer *));
-/*static*/ int esp_poll __P((struct esp_softc *, struct ecb *));
+/*static*/ int esp_poll __P((struct esp_softc *, struct scsi_xfer *, int));
/*static*/ void esp_sched __P((struct esp_softc *));
-/*static*/ void esp_done __P((struct ecb *));
+/*static*/ void esp_done __P((struct esp_softc *, struct esp_ecb *));
/*static*/ void esp_msgin __P((struct esp_softc *));
/*static*/ void esp_msgout __P((struct esp_softc *));
/*static*/ int espintr __P((struct esp_softc *));
/*static*/ void esp_timeout __P((void *arg));
-/*static*/ void esp_abort __P((struct esp_softc *, struct ecb *));
-int esp_cpb2stp __P((struct esp_softc *, int));
-int esp_stp2cpb __P((struct esp_softc *, int));
+/*static*/ void esp_abort __P((struct esp_softc *, struct esp_ecb *));
+/*static*/ void esp_dequeue __P((struct esp_softc *, struct esp_ecb *));
+void esp_sense __P((struct esp_softc *, struct esp_ecb *));
+void esp_free_ecb __P((struct esp_softc *, struct esp_ecb *, int));
+struct esp_ecb *esp_get_ecb __P((struct esp_softc *, int));
+static inline int esp_stp2cpb __P((struct esp_softc *, int));
+static inline int esp_cpb2stp __P((struct esp_softc *, int));
+static inline void esp_setsync __P((struct esp_softc *, struct esp_tinfo *));
/* Linkup to the rest of the kernel */
struct cfattach esp_ca = {
- sizeof(struct esp_softc), espmatch, espattach,
+ sizeof(struct esp_softc), espmatch, espattach
};
struct cfdriver esp_cd = {
- NULL, "esp", DV_DULL,
+ NULL, "esp", DV_DULL
};
struct scsi_adapter esp_switch = {
@@ -119,6 +158,9 @@ struct scsi_device esp_dev = {
NULL, /* Use default 'done' routine */
};
+/*
+ * XXX should go when new generic scsiprint finds its way here
+ */
int
espprint(aux, name)
void *aux;
@@ -170,7 +212,7 @@ espattach(parent, self, aux)
struct esp_softc *sc = (void *)self;
#ifdef SPARC_DRIVER
struct bootpath *bp;
- int dmachild = strncmp(parent->dv_xname, "espdma", 6) == 0;
+ int dmachild = strncmp(parent->dv_xname, "dma", 3) == 0;
#endif
#ifdef SPARC_DRIVER
@@ -256,6 +298,8 @@ espattach(parent, self, aux)
*/
if (sc->sc_dma)
sc->sc_dma->sc_esp = sc;
+ else
+ panic("espattach: no dma found");
}
#else
sc->sc_dma->sc_esp = sc; /* XXX */
@@ -276,7 +320,7 @@ espattach(parent, self, aux)
printf(": ESP100");
sc->sc_rev = ESP100;
} else {
- sc->sc_cfg2 = ESPCFG2_SCSI2 | ESPCFG2_FE;
+ sc->sc_cfg2 = ESPCFG2_SCSI2;
ESP_WRITE_REG(sc, ESP_CFG2, sc->sc_cfg2);
sc->sc_cfg3 = 0;
ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3);
@@ -286,6 +330,8 @@ espattach(parent, self, aux)
printf(": ESP100A");
sc->sc_rev = ESP100A;
} else {
+ /* ESPCFG2_FE enables > 64K transfers */
+ sc->sc_cfg2 |= ESPCFG2_FE;
sc->sc_cfg3 = 0;
ESP_WRITE_REG(sc, ESP_CFG3, sc->sc_cfg3);
printf(": ESP200");
@@ -318,14 +364,19 @@ espattach(parent, self, aux)
*/
switch (sc->sc_rev) {
case ESP100:
+ sc->sc_maxxfer = 64 * 1024;
sc->sc_minsync = 0; /* No synch on old chip? */
break;
case ESP100A:
+ sc->sc_maxxfer = 64 * 1024;
sc->sc_minsync = esp_cpb2stp(sc, 5); /* Min clocks/byte is 5 */
break;
case ESP200:
+ sc->sc_maxxfer = 16 * 1024 * 1024;
/* XXX - do actually set FAST* bits */
}
+#else
+ sc->sc_maxxfer = 64 * 1024;
#endif
sc->sc_ccf = FREQTOCCF(sc->sc_freq);
@@ -380,6 +431,7 @@ espattach(parent, self, aux)
/*
* fill in the prototype scsi_link.
*/
+ /* sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; */
sc->sc_link.adapter_softc = sc;
sc->sc_link.adapter_target = sc->sc_id;
sc->sc_link.adapter = &esp_switch;
@@ -410,7 +462,7 @@ espattach(parent, self, aux)
/*
* Now try to attach all the sub-devices
*/
- config_found(self, &sc->sc_link, espprint);
+ config_found(self, &sc->sc_link, /* scsiprint */ espprint); /* XXX */
#ifdef SPARC_DRIVER
bootpath_store(1, NULL);
@@ -425,7 +477,7 @@ espattach(parent, self, aux)
* After reset, registers are loaded with the defaults from the attach
* routine above.
*/
-void
+void
esp_reset(sc)
struct esp_softc *sc;
{
@@ -491,12 +543,13 @@ esp_init(sc, doreset)
struct esp_softc *sc;
int doreset;
{
- struct ecb *ecb;
+ struct esp_ecb *ecb;
int r;
ESP_TRACE(("[ESP_INIT(%d)] ", doreset));
- if (sc->sc_state == 0) { /* First time through */
+ if (sc->sc_state == 0) {
+ /* First time through; initialize. */
TAILQ_INIT(&sc->ready_list);
TAILQ_INIT(&sc->nexus_list);
TAILQ_INIT(&sc->free_list);
@@ -505,21 +558,21 @@ esp_init(sc, doreset)
bzero(ecb, sizeof(sc->sc_ecb));
for (r = 0; r < sizeof(sc->sc_ecb) / sizeof(*ecb); r++) {
TAILQ_INSERT_TAIL(&sc->free_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QFREE);
ecb++;
}
bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
} else {
- sc->sc_flags |= ESP_ABORTING;
- sc->sc_state = ESP_IDLE;
- if (sc->sc_nexus != NULL) {
- sc->sc_nexus->xs->error = XS_TIMEOUT;
- esp_done(sc->sc_nexus);
+ /* Cancel any active commands. */
+ sc->sc_state = ESP_CLEANING;
+ if ((ecb = sc->sc_nexus) != NULL) {
+ ecb->xs->error = XS_DRIVER_STUFFUP;
+ untimeout(esp_timeout, ecb);
+ esp_done(sc, ecb);
}
- sc->sc_nexus = NULL;
while ((ecb = sc->nexus_list.tqh_first) != NULL) {
- ecb->xs->error = XS_TIMEOUT;
- esp_done(ecb);
+ ecb->xs->error = XS_DRIVER_STUFFUP;
+ untimeout(esp_timeout, ecb);
+ esp_done(sc, ecb);
}
}
@@ -530,24 +583,24 @@ esp_init(sc, doreset)
sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
for (r = 0; r < 8; r++) {
- struct esp_tinfo *tp = &sc->sc_tinfo[r];
-
- tp->flags = (sc->sc_minsync ? T_NEGOTIATE : 0) |
- T_NEED_TO_RESET | (tp->flags & T_XXX);
- tp->period = sc->sc_minsync;
- tp->offset = 0;
+ struct esp_tinfo *ti = &sc->sc_tinfo[r];
+/* XXX - config flags per target: low bits: no reselect; high bits: no synch */
+ int fl = sc->sc_dev.dv_cfdata->cf_flags;
+
+ ti->flags = ((sc->sc_minsync && !(fl & (1<<(r+8))))
+ ? T_NEGOTIATE : 0) |
+ ((fl & (1<<r)) ? T_RSELECTOFF : 0) |
+ T_NEED_TO_RESET;
+ ti->period = sc->sc_minsync;
+ ti->offset = 0;
}
- sc->sc_flags &= ~ESP_ABORTING;
if (doreset) {
sc->sc_state = ESP_SBR;
ESPCMD(sc, ESPCMD_RSTSCSI);
- return;
+ } else {
+ sc->sc_state = ESP_IDLE;
}
-
- sc->sc_state = ESP_IDLE;
- esp_sched(sc);
- return;
}
/*
@@ -587,9 +640,20 @@ espreadregs(sc)
}
/*
+ * Convert chip register Clock Per Byte value to Synchronous Transfer Period.
+ */
+static inline int
+esp_cpb2stp(sc, cpb)
+ struct esp_softc *sc;
+ int cpb;
+{
+ return ((250 * cpb) / sc->sc_freq);
+}
+
+/*
* Convert Synchronous Transfer Period to chip register Clock Per Byte value.
*/
-int
+static inline int
esp_stp2cpb(sc, period)
struct esp_softc *sc;
int period;
@@ -602,15 +666,19 @@ esp_stp2cpb(sc, period)
return v;
}
-/*
- * Convert chip register Clock Per Byte value to Synchronous Transfer Period.
- */
-int
-esp_cpb2stp(sc, cpb)
+static inline void
+esp_setsync(sc, ti)
struct esp_softc *sc;
- int cpb;
+ struct esp_tinfo *ti;
{
- return ((250 * cpb) / sc->sc_freq);
+
+ if (ti->flags & T_SYNCMODE) {
+ ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset);
+ ESP_WRITE_REG(sc, ESP_SYNCTP, esp_stp2cpb(sc, ti->period));
+ } else {
+ ESP_WRITE_REG(sc, ESP_SYNCOFF, 0);
+ ESP_WRITE_REG(sc, ESP_SYNCTP, 0);
+ }
}
/*
@@ -621,38 +689,36 @@ esp_cpb2stp(sc, cpb)
* by DMA instead of programmed I/O soon.
*/
void
-espselect(sc, target, lun, cmd, clen)
+esp_select(sc, ecb)
struct esp_softc *sc;
- u_char target, lun;
- u_char *cmd;
- u_char clen;
+ struct esp_ecb *ecb;
{
+ struct scsi_link *sc_link = ecb->xs->sc_link;
+ int target = sc_link->target;
struct esp_tinfo *ti = &sc->sc_tinfo[target];
- int i;
+ u_char *cmd;
+ int clen;
- ESP_TRACE(("[espselect(t%d,l%d,cmd:%x)] ", target, lun, *(u_char *)cmd));
+ ESP_TRACE(("[esp_select(t%d,l%d,cmd:%x)] ", sc_link->target, sc_link->lun, ecb->cmd.opcode));
/* new state ESP_SELECTING */
sc->sc_state = ESP_SELECTING;
+ ESPCMD(sc, ESPCMD_FLUSH);
+
/*
* The docs say the target register is never reset, and I
* can't think of a better place to set it
*/
ESP_WRITE_REG(sc, ESP_SELID, target);
- if (ti->flags & T_SYNCMODE) {
- ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset);
- ESP_WRITE_REG(sc, ESP_SYNCTP, esp_stp2cpb(sc, ti->period));
- } else {
- ESP_WRITE_REG(sc, ESP_SYNCOFF, 0);
- ESP_WRITE_REG(sc, ESP_SYNCTP, 0);
- }
+ esp_setsync(sc, ti);
/*
* Who am I. This is where we tell the target that we are
* happy for it to disconnect etc.
*/
- ESP_WRITE_REG(sc, ESP_FIFO, MSG_IDENTIFY(lun, 1));
+ ESP_WRITE_REG(sc, ESP_FIFO,
+ MSG_IDENTIFY(sc_link->lun, (ti->flags & T_RSELECTOFF)?0:1));
if (ti->flags & T_NEGOTIATE) {
/* Arbitrate, select and stop after IDENTIFY message */
@@ -661,13 +727,60 @@ espselect(sc, target, lun, cmd, clen)
}
/* Now the command into the FIFO */
- for (i = 0; i < clen; i++)
+ cmd = (u_char *)&ecb->cmd;
+ clen = ecb->clen;
+ while (clen--)
ESP_WRITE_REG(sc, ESP_FIFO, *cmd++);
/* And get the targets attention */
ESPCMD(sc, ESPCMD_SELATN);
}
+void
+esp_free_ecb(sc, ecb, flags)
+ struct esp_softc *sc;
+ struct esp_ecb *ecb;
+ int flags;
+{
+ int s;
+
+ s = splbio();
+
+ ecb->flags = 0;
+ TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain);
+
+ /*
+ * If there were none, wake anybody waiting for one to come free,
+ * starting with queued entries.
+ */
+ if (ecb->chain.tqe_next == 0)
+ wakeup(&sc->free_list);
+
+ splx(s);
+}
+
+struct esp_ecb *
+esp_get_ecb(sc, flags)
+ struct esp_softc *sc;
+ int flags;
+{
+ struct esp_ecb *ecb;
+ int s;
+
+ s = splbio();
+
+ while ((ecb = sc->free_list.tqh_first) == NULL &&
+ (flags & SCSI_NOSLEEP) == 0)
+ tsleep(&sc->free_list, PRIBIO, "especb", 0);
+ if (ecb) {
+ TAILQ_REMOVE(&sc->free_list, ecb, chain);
+ ecb->flags |= ECB_ALLOC;
+ }
+
+ splx(s);
+ return ecb;
+}
+
/*
* DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
*/
@@ -677,73 +790,70 @@ espselect(sc, target, lun, cmd, clen)
* This function is called by the higher level SCSI-driver to queue/run
* SCSI-commands.
*/
-int
+int
esp_scsi_cmd(xs)
struct scsi_xfer *xs;
{
struct scsi_link *sc_link = xs->sc_link;
struct esp_softc *sc = sc_link->adapter_softc;
- struct ecb *ecb;
+ struct esp_ecb *ecb;
int s, flags;
-
+
ESP_TRACE(("[esp_scsi_cmd] "));
- ESP_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
+ ESP_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
sc_link->target));
flags = xs->flags;
-
- /* Get a esp command block */
- s = splbio();
- ecb = sc->free_list.tqh_first;
- if (ecb) {
- TAILQ_REMOVE(&sc->free_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QNONE);
- }
- splx(s);
-
- if (ecb == NULL) {
- ESP_MISC(("TRY_AGAIN_LATER"));
+ if ((ecb = esp_get_ecb(sc, flags)) == NULL) {
+ xs->error = XS_DRIVER_STUFFUP;
return TRY_AGAIN_LATER;
}
/* Initialize ecb */
ecb->xs = xs;
- bcopy(xs->cmd, &ecb->cmd, xs->cmdlen);
- ecb->clen = xs->cmdlen;
- ecb->daddr = xs->data;
- ecb->dleft = xs->datalen;
+ ecb->timeout = xs->timeout;
+
+ if (xs->flags & SCSI_RESET) {
+ ecb->flags |= ECB_RESET;
+ ecb->clen = 0;
+ ecb->dleft = 0;
+ } else {
+ bcopy(xs->cmd, &ecb->cmd, xs->cmdlen);
+ ecb->clen = xs->cmdlen;
+ ecb->daddr = xs->data;
+ ecb->dleft = xs->datalen;
+ }
ecb->stat = 0;
-
+
s = splbio();
- TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QREADY);
- timeout(esp_timeout, ecb, (xs->timeout*hz)/1000);
+ TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain);
if (sc->sc_state == ESP_IDLE)
esp_sched(sc);
splx(s);
- if (flags & SCSI_POLL) {
- /* Not allowed to use interrupts, use polling instead */
- return esp_poll(sc, ecb);
- }
-
- ESP_MISC(("SUCCESSFULLY_QUEUED"));
- return SUCCESSFULLY_QUEUED;
+ if ((flags & SCSI_POLL) == 0)
+ return SUCCESSFULLY_QUEUED;
+ /* Not allowed to use interrupts, use polling instead */
+ if (esp_poll(sc, xs, ecb->timeout)) {
+ esp_timeout(ecb);
+ if (esp_poll(sc, xs, ecb->timeout))
+ esp_timeout(ecb);
+ }
+ return COMPLETE;
}
/*
* Used when interrupt driven I/O isn't allowed, e.g. during boot.
*/
int
-esp_poll(sc, ecb)
+esp_poll(sc, xs, count)
struct esp_softc *sc;
- struct ecb *ecb;
+ struct scsi_xfer *xs;
+ int count;
{
- struct scsi_xfer *xs = ecb->xs;
- int count = xs->timeout * 100;
ESP_TRACE(("[esp_poll] "));
while (count) {
@@ -754,22 +864,16 @@ esp_poll(sc, ecb)
if (ESP_READ_REG(sc, ESP_STAT) & ESPSTAT_INT)
espintr(sc);
#endif
- if (xs->flags & ITSDONE)
- break;
- DELAY(10);
+ if ((xs->flags & ITSDONE) != 0)
+ return 0;
if (sc->sc_state == ESP_IDLE) {
ESP_TRACE(("[esp_poll: rescheduling] "));
esp_sched(sc);
}
+ DELAY(1000);
count--;
}
-
- if (count == 0) {
- ESP_MISC(("esp_poll: timeout"));
- esp_timeout((caddr_t)ecb);
- }
-
- return COMPLETE;
+ return 1;
}
@@ -787,46 +891,62 @@ void
esp_sched(sc)
struct esp_softc *sc;
{
+ struct esp_ecb *ecb;
struct scsi_link *sc_link;
- struct ecb *ecb;
- int t;
-
+ struct esp_tinfo *ti;
+
ESP_TRACE(("[esp_sched] "));
if (sc->sc_state != ESP_IDLE)
panic("esp_sched: not IDLE (state=%d)", sc->sc_state);
- if (sc->sc_flags & ESP_ABORTING)
- return;
-
/*
* Find first ecb in ready queue that is for a target/lunit
* combinations that is not busy.
*/
for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) {
sc_link = ecb->xs->sc_link;
- t = sc_link->target;
- if (!(sc->sc_tinfo[t].lubusy & (1 << sc_link->lun))) {
- struct esp_tinfo *ti = &sc->sc_tinfo[t];
-
- if ((ecb->flags & ECB_QBITS) != ECB_QREADY)
- panic("esp: busy entry on ready list");
+ ti = &sc->sc_tinfo[sc_link->target];
+ if ((ti->lubusy & (1 << sc_link->lun)) == 0) {
TAILQ_REMOVE(&sc->ready_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QNONE);
sc->sc_nexus = ecb;
- sc->sc_flags = 0;
- sc->sc_prevphase = INVALID_PHASE;
- sc->sc_dp = ecb->daddr;
- sc->sc_dleft = ecb->dleft;
- ti->lubusy |= (1<<sc_link->lun);
-/*XXX*/if (sc->sc_msgpriq) {
- printf("esp: message queue not empty: %x!\n", sc->sc_msgpriq);
-}
-/*XXX*/sc->sc_msgpriq = sc->sc_msgout = 0;
- espselect(sc, t, sc_link->lun,
- (u_char *)&ecb->cmd, ecb->clen);
+ esp_select(sc, ecb);
break;
} else
- ESP_MISC(("%d:%d busy\n", t, sc_link->lun));
+ ESP_MISC(("%d:%d busy\n",
+ sc_link->target, sc_link->lun));
+ }
+}
+
+void
+esp_sense(sc, ecb)
+ struct esp_softc *sc;
+ struct esp_ecb *ecb;
+{
+ struct scsi_xfer *xs = ecb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target];
+ struct scsi_sense *ss = (void *)&ecb->cmd;
+
+ ESP_MISC(("requesting sense "));
+ /* Next, setup a request sense command block */
+ bzero(ss, sizeof(*ss));
+ ss->opcode = REQUEST_SENSE;
+ ss->byte2 = sc_link->lun << 5;
+ ss->length = sizeof(struct scsi_sense_data);
+ ecb->clen = sizeof(*ss);
+ ecb->daddr = (char *)&xs->sense;
+ ecb->dleft = sizeof(struct scsi_sense_data);
+ ecb->flags |= ECB_SENSE;
+ ti->senses++;
+ if (ecb->flags & ECB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (ecb == sc->sc_nexus) {
+ esp_select(sc, ecb);
+ } else {
+ esp_dequeue(sc, ecb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
+ if (sc->sc_state == ESP_IDLE)
+ esp_sched(sc);
}
}
@@ -834,57 +954,34 @@ esp_sched(sc)
* POST PROCESSING OF SCSI_CMD (usually current)
*/
void
-esp_done(ecb)
- struct ecb *ecb;
+esp_done(sc, ecb)
+ struct esp_softc *sc;
+ struct esp_ecb *ecb;
{
struct scsi_xfer *xs = ecb->xs;
struct scsi_link *sc_link = xs->sc_link;
- struct esp_softc *sc = sc_link->adapter_softc;
struct esp_tinfo *ti = &sc->sc_tinfo[sc_link->target];
ESP_TRACE(("[esp_done(error:%x)] ", xs->error));
- untimeout(esp_timeout, ecb);
-
/*
- * Now, if we've come here with no error code, i.e. we've kept the
+ * Now, if we've come here with no error code, i.e. we've kept the
* initial XS_NOERROR, and the status code signals that we should
- * check sense, we'll need to set up a request sense cmd block and
- * push the command back into the ready queue *before* any other
+ * check sense, we'll need to set up a request sense cmd block and
+ * push the command back into the ready queue *before* any other
* commands for this target/lunit, else we lose the sense info.
* We don't support chk sense conditions for the request sense cmd.
*/
if (xs->error == XS_NOERROR) {
- if ((ecb->flags & ECB_ABORTED) != 0) {
- xs->error = XS_TIMEOUT;
- } else if ((ecb->flags & ECB_CHKSENSE) != 0) {
+ if ((ecb->flags & ECB_ABORT) != 0) {
+ xs->error = XS_DRIVER_STUFFUP;
+ } else if ((ecb->flags & ECB_SENSE) != 0) {
xs->error = XS_SENSE;
} else if ((ecb->stat & ST_MASK) == SCSI_CHECK) {
- struct scsi_sense *ss = (void *)&ecb->cmd;
- ESP_MISC(("requesting sense "));
/* First, save the return values */
xs->resid = ecb->dleft;
xs->status = ecb->stat;
- /* Next, setup a request sense command block */
- bzero(ss, sizeof(*ss));
- ss->opcode = REQUEST_SENSE;
- /*ss->byte2 = sc_link->lun << 5;*/
- ss->length = sizeof(struct scsi_sense_data);
- ecb->clen = sizeof(*ss);
- ecb->daddr = (char *)&xs->sense;
- ecb->dleft = sizeof(struct scsi_sense_data);
- ecb->flags |= ECB_CHKSENSE;
-/*XXX - must take off queue here */
- TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QREADY);
- ti->lubusy &= ~(1<<sc_link->lun);
- ti->senses++;
- timeout(esp_timeout, ecb, (xs->timeout*hz)/1000);
- if (sc->sc_nexus == ecb) {
- sc->sc_nexus = NULL;
- sc->sc_state = ESP_IDLE;
- esp_sched(sc);
- }
+ esp_sense(sc, ecb);
return;
} else {
xs->resid = ecb->dleft;
@@ -895,52 +992,43 @@ esp_done(ecb)
#ifdef ESP_DEBUG
if (esp_debug & ESP_SHOWMISC) {
- printf("err=0x%02x ",xs->error);
- if (xs->error == XS_SENSE) {
- printf("sense=%2x; ", xs->sense.error_code);
- if (xs->sense.error_code == 0x70)
- printf("extcode: %x; ", xs->sense.flags);
- }
- }
- if ((xs->resid || xs->error > XS_SENSE) && esp_debug & ESP_SHOWMISC) {
- if (xs->resid)
- printf("esp_done: resid=%d\n", xs->resid);
- if (xs->error)
- printf("esp_done: error=%d\n", xs->error);
+ if (xs->resid != 0)
+ printf("resid=%d ", xs->resid);
+ if (xs->error == XS_SENSE)
+ printf("sense=0x%02x\n", xs->sense.error_code);
+ else
+ printf("error=%d\n", xs->error);
}
#endif
/*
* Remove the ECB from whatever queue it's on.
*/
- switch (ecb->flags & ECB_QBITS) {
- case ECB_QNONE:
- if (ecb != sc->sc_nexus) {
- panic("%s: floating ecb", sc->sc_dev.dv_xname);
- }
+ if (ecb->flags & ECB_NEXUS)
+ ti->lubusy &= ~(1 << sc_link->lun);
+ if (ecb == sc->sc_nexus) {
+ sc->sc_nexus = NULL;
sc->sc_state = ESP_IDLE;
- ti->lubusy &= ~(1<<sc_link->lun);
esp_sched(sc);
- break;
- case ECB_QREADY:
- TAILQ_REMOVE(&sc->ready_list, ecb, chain);
- break;
- case ECB_QNEXUS:
- TAILQ_REMOVE(&sc->nexus_list, ecb, chain);
- ti->lubusy &= ~(1<<sc_link->lun);
- break;
- case ECB_QFREE:
- panic("%s: busy ecb on free list", sc->sc_dev.dv_xname);
- break;
- }
-
- /* Put it on the free list, and clear flags. */
- TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain);
- ecb->flags = ECB_QFREE;
-
+ } else
+ esp_dequeue(sc, ecb);
+
+ esp_free_ecb(sc, ecb, xs->flags);
ti->cmds++;
scsi_done(xs);
- return;
+}
+
+void
+esp_dequeue(sc, ecb)
+ struct esp_softc *sc;
+ struct esp_ecb *ecb;
+{
+
+ if (ecb->flags & ECB_NEXUS) {
+ TAILQ_REMOVE(&sc->nexus_list, ecb, chain);
+ } else {
+ TAILQ_REMOVE(&sc->ready_list, ecb, chain);
+ }
}
/*
@@ -953,12 +1041,83 @@ esp_done(ecb)
* else there will be an illegal command interrupt.
*/
#define esp_sched_msgout(m) \
- do { \
- ESP_MISC(("esp_sched_msgout %d ", m)); \
- ESPCMD(sc, ESPCMD_SETATN); \
- sc->sc_msgpriq |= (m); \
+ do { \
+ ESP_MISC(("esp_sched_msgout %d ", m)); \
+ ESPCMD(sc, ESPCMD_SETATN); \
+ sc->sc_flags |= ESP_ATN; \
+ sc->sc_msgpriq |= (m); \
} while (0)
+int
+esp_reselect(sc, message)
+ struct esp_softc *sc;
+ int message;
+{
+ u_char selid, target, lun;
+ struct esp_ecb *ecb;
+ struct scsi_link *sc_link;
+ struct esp_tinfo *ti;
+
+ /*
+ * The SCSI chip made a snapshot of the data bus while the reselection
+ * was being negotiated. This enables us to determine which target did
+ * the reselect.
+ */
+ selid = sc->sc_selid & ~(1 << sc->sc_id);
+ if (selid & (selid - 1)) {
+ printf("%s: reselect with invalid selid %02x; sending DEVICE RESET\n",
+ sc->sc_dev.dv_xname, selid);
+ goto reset;
+ }
+
+ /*
+ * Search wait queue for disconnected cmd
+ * The list should be short, so I haven't bothered with
+ * any more sophisticated structures than a simple
+ * singly linked list.
+ */
+ target = ffs(selid) - 1;
+ lun = message & 0x07;
+ for (ecb = sc->nexus_list.tqh_first; ecb != NULL;
+ ecb = ecb->chain.tqe_next) {
+ sc_link = ecb->xs->sc_link;
+ if (sc_link->target == target && sc_link->lun == lun)
+ break;
+ }
+ if (ecb == NULL) {
+ printf("%s: reselect from target %d lun %d with no nexus; sending ABORT\n",
+ sc->sc_dev.dv_xname, target, lun);
+ goto abort;
+ }
+
+ /* Make this nexus active again. */
+ TAILQ_REMOVE(&sc->nexus_list, ecb, chain);
+ sc->sc_state = ESP_CONNECTED;
+ sc->sc_nexus = ecb;
+ ti = &sc->sc_tinfo[target];
+ ti->lubusy |= (1 << lun);
+ esp_setsync(sc, ti);
+
+ if (ecb->flags & ECB_RESET)
+ esp_sched_msgout(SEND_DEV_RESET);
+ else if (ecb->flags & ECB_ABORT)
+ esp_sched_msgout(SEND_ABORT);
+
+ /* Do an implicit RESTORE POINTERS. */
+ sc->sc_dp = ecb->daddr;
+ sc->sc_dleft = ecb->dleft;
+
+ return (0);
+
+reset:
+ esp_sched_msgout(SEND_DEV_RESET);
+ return (1);
+
+abort:
+ esp_sched_msgout(SEND_ABORT);
+ return (1);
+}
+
#define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
#define ISEXTMSG(m) ((m) == 1)
@@ -974,7 +1133,7 @@ esp_msgin(sc)
register struct esp_softc *sc;
{
register int v;
-
+
ESP_TRACE(("[esp_msgin(curmsglen:%d)] ", sc->sc_imlen));
if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) == 0) {
@@ -1003,7 +1162,6 @@ esp_msgin(sc)
* Which target is reselecting us? (The ID bit really)
*/
sc->sc_selid = v;
- sc->sc_selid &= ~(1<<sc->sc_id);
ESP_MISC(("selid=0x%2x ", sc->sc_selid));
return;
}
@@ -1017,7 +1175,6 @@ esp_msgin(sc)
*/
if ((sc->sc_flags & ESP_DROP_MSGI)) {
- ESPCMD(sc, ESPCMD_SETATN);
ESPCMD(sc, ESPCMD_MSGOK);
printf("<dropping msg byte %x>",
sc->sc_imess[sc->sc_imlen]);
@@ -1029,7 +1186,7 @@ esp_msgin(sc)
sc->sc_flags |= ESP_DROP_MSGI;
} else {
sc->sc_imlen++;
- /*
+ /*
* This testing is suboptimal, but most
* messages will be of the one byte variety, so
* it should not effect performance
@@ -1055,209 +1212,159 @@ gotit:
* extended messages which total length is shorter than
* ESP_MAX_MSG_LEN. Longer messages will be amputated.
*/
- if (sc->sc_state == ESP_HASNEXUS) {
- struct ecb *ecb = sc->sc_nexus;
- struct esp_tinfo *ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
+ switch (sc->sc_state) {
+ struct esp_ecb *ecb;
+ struct scsi_link *sc_link;
+ struct esp_tinfo *ti;
+
+ case ESP_CONNECTED:
+ ecb = sc->sc_nexus;
+ ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
switch (sc->sc_imess[0]) {
case MSG_CMDCOMPLETE:
ESP_MSGS(("cmdcomplete "));
if (sc->sc_dleft < 0) {
- struct scsi_link *sc_link = ecb->xs->sc_link;
- printf("esp: %d extra bytes from %d:%d\n",
- -sc->sc_dleft,
- sc_link->target, sc_link->lun);
+ sc_link = ecb->xs->sc_link;
+ printf("%s: %d extra bytes from %d:%d\n",
+ sc->sc_dev.dv_xname, -sc->sc_dleft,
+ sc_link->target, sc_link->lun);
sc->sc_dleft = 0;
}
ecb->xs->resid = ecb->dleft = sc->sc_dleft;
- sc->sc_flags |= ESP_BUSFREE_OK;
+ sc->sc_state = ESP_CMDCOMPLETE;
break;
case MSG_MESSAGE_REJECT:
if (esp_debug & ESP_SHOWMSGS)
printf("%s: our msg rejected by target\n",
sc->sc_dev.dv_xname);
-#if 0 /* XXX - must remember last message */
-printf("<<target%d: MSG_MESSAGE_REJECT>>", ecb->xs->sc_link->target);
-ti->period = ti->offset = 0;
-sc->sc_flags &= ~ESP_SYNCHNEGO;
-ti->flags &= ~T_NEGOTIATE;
-#endif
- if (sc->sc_flags & ESP_SYNCHNEGO) {
- ti->period = ti->offset = 0;
+ switch (sc->sc_msgout) {
+ case SEND_SDTR:
sc->sc_flags &= ~ESP_SYNCHNEGO;
- ti->flags &= ~T_NEGOTIATE;
+ ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
+ esp_setsync(sc, ti);
+ break;
+ case SEND_INIT_DET_ERR:
+ goto abort;
}
- /* Not all targets understand INITIATOR_DETECTED_ERR */
- if (sc->sc_msgout == SEND_INIT_DET_ERR)
- esp_sched_msgout(SEND_ABORT);
break;
+
case MSG_NOOP:
ESP_MSGS(("noop "));
break;
+
case MSG_DISCONNECT:
ESP_MSGS(("disconnect "));
ti->dconns++;
- sc->sc_flags |= ESP_DISCON;
- sc->sc_flags |= ESP_BUSFREE_OK;
- break;
+ sc->sc_state = ESP_DISCONNECT;
+ if ((ecb->xs->sc_link->quirks & SDEV_AUTOSAVE) == 0)
+ break;
+ /*FALLTHROUGH*/
+
case MSG_SAVEDATAPOINTER:
ESP_MSGS(("save datapointer "));
- ecb->dleft = sc->sc_dleft;
ecb->daddr = sc->sc_dp;
+ ecb->dleft = sc->sc_dleft;
break;
+
case MSG_RESTOREPOINTERS:
ESP_MSGS(("restore datapointer "));
- if (!ecb) {
- esp_sched_msgout(SEND_ABORT);
- printf("%s: no DATAPOINTERs to restore\n",
- sc->sc_dev.dv_xname);
- break;
- }
sc->sc_dp = ecb->daddr;
sc->sc_dleft = ecb->dleft;
break;
- case MSG_PARITY_ERROR:
-printf("<<esp:target%d: MSG_PARITY_ERROR>>", ecb->xs->sc_link->target);
- break;
+
case MSG_EXTENDED:
ESP_MSGS(("extended(%x) ", sc->sc_imess[2]));
switch (sc->sc_imess[2]) {
case MSG_EXT_SDTR:
ESP_MSGS(("SDTR period %d, offset %d ",
sc->sc_imess[3], sc->sc_imess[4]));
- /*XXX*/if (ti->flags & T_XXX) {
- printf("%s:%d: rejecting SDTR\n",
- "esp", ecb->xs->sc_link->target);
- sc->sc_flags &= ~ESP_SYNCHNEGO;
- esp_sched_msgout(SEND_REJECT);
- break;
- }
+ if (sc->sc_imess[1] != 3)
+ goto reject;
ti->period = sc->sc_imess[3];
ti->offset = sc->sc_imess[4];
- if (sc->sc_minsync == 0) {
- /* We won't do synch */
- ti->offset = 0;
- esp_sched_msgout(SEND_SDTR);
- } else if (ti->offset == 0) {
- printf("%s:%d: async\n", "esp",
- ecb->xs->sc_link->target);
- ti->offset = 0;
- sc->sc_flags &= ~ESP_SYNCHNEGO;
- } else if (ti->period > 124) {
+ ti->flags &= ~T_NEGOTIATE;
+ if (sc->sc_minsync == 0 ||
+ ti->offset == 0 ||
+ ti->period > 124) {
printf("%s:%d: async\n", "esp",
ecb->xs->sc_link->target);
- ti->offset = 0;
- esp_sched_msgout(SEND_SDTR);
+ if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) {
+ /* target initiated negotiation */
+ ti->offset = 0;
+ ti->flags &= ~T_SYNCMODE;
+ esp_sched_msgout(SEND_SDTR);
+ } else {
+ /* we are async */
+ ti->flags &= ~T_SYNCMODE;
+ }
} else {
int r = 250/ti->period;
int s = (100*250)/ti->period - 100*r;
int p;
+
p = esp_stp2cpb(sc, ti->period);
ti->period = esp_cpb2stp(sc, p);
- if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) {
- /* Target initiated negotiation */
- sc->sc_flags |= ESP_SYNCHNEGO;
- if (ti->flags & T_SYNCMODE) {
- sc_print_addr(ecb->xs->sc_link);
#ifdef ESP_DEBUG
- printf("%s:%d: dropping out of sync mode\n");
+ sc_print_addr(ecb->xs->sc_link);
+ printf("max sync rate %d.%02dMb/s\n",
+ r, s);
#endif
- }
+ if ((sc->sc_flags&ESP_SYNCHNEGO) == 0) {
+ /* target initiated negotiation */
+ if (ti->period < sc->sc_minsync)
+ ti->period = sc->sc_minsync;
+ if (ti->offset > 15)
+ ti->offset = 15;
ti->flags &= ~T_SYNCMODE;
- ESP_WRITE_REG(sc,
- ESP_SYNCOFF, 0);
esp_sched_msgout(SEND_SDTR);
} else {
/* we are sync */
- sc->sc_flags &= ~ESP_SYNCHNEGO;
- ESP_WRITE_REG(sc,
- ESP_SYNCOFF, ti->offset);
- ESP_WRITE_REG(sc,
- ESP_SYNCTP, p);
ti->flags |= T_SYNCMODE;
- sc_print_addr(ecb->xs->sc_link);
-#ifdef ESP_DEBUG
- printf("max sync "
- "rate %d.%02dMb/s\n",
- r, s);
-#endif
}
}
- ti->flags &= ~T_NEGOTIATE;
- break;
- default: /* Extended messages we don't handle */
- ESPCMD(sc, ESPCMD_SETATN);
+ sc->sc_flags &= ~ESP_SYNCHNEGO;
+ esp_setsync(sc, ti);
break;
+
+ default:
+ printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n",
+ sc->sc_dev.dv_xname);
+ goto reject;
}
break;
+
default:
ESP_MSGS(("ident "));
- /* thanks for that ident... */
- if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
- ESP_MISC(("unknown "));
-printf("%s: unimplemented message: %d\n", sc->sc_dev.dv_xname, sc->sc_imess[0]);
- ESPCMD(sc, ESPCMD_SETATN);
- }
+ printf("%s: unrecognized MESSAGE; sending REJECT\n",
+ sc->sc_dev.dv_xname);
+ reject:
+ esp_sched_msgout(SEND_REJECT);
break;
}
- } else if (sc->sc_state == ESP_RESELECTED) {
- struct scsi_link *sc_link;
- struct ecb *ecb;
- struct esp_tinfo *ti;
- u_char lunit;
-
- if (MSG_ISIDENTIFY(sc->sc_imess[0])) { /* Identify? */
- ESP_MISC(("searching "));
- /*
- * Search wait queue for disconnected cmd
- * The list should be short, so I haven't bothered with
- * any more sophisticated structures than a simple
- * singly linked list.
- */
- lunit = sc->sc_imess[0] & 0x07;
- for (ecb = sc->nexus_list.tqh_first; ecb;
- ecb = ecb->chain.tqe_next) {
- sc_link = ecb->xs->sc_link;
- if (sc_link->lun == lunit &&
- sc->sc_selid == (1<<sc_link->target)) {
- TAILQ_REMOVE(&sc->nexus_list, ecb,
- chain);
- ECB_SETQ(ecb, ECB_QNONE);
- break;
- }
- }
+ break;
- if (!ecb) { /* Invalid reselection! */
- esp_sched_msgout(SEND_ABORT);
- printf("esp: invalid reselect (idbit=0x%2x)\n",
- sc->sc_selid);
- } else { /* Reestablish nexus */
- /*
- * Setup driver data structures and
- * do an implicit RESTORE POINTERS
- */
- ti = &sc->sc_tinfo[sc_link->target];
- sc->sc_nexus = ecb;
- sc->sc_dp = ecb->daddr;
- sc->sc_dleft = ecb->dleft;
- sc->sc_tinfo[sc_link->target].lubusy
- |= (1<<sc_link->lun);
- ESP_WRITE_REG(sc, ESP_SYNCOFF, ti->offset);
- ESP_WRITE_REG(sc, ESP_SYNCTP,
- esp_stp2cpb(sc, ti->period));
- ESP_MISC(("... found ecb"));
- sc->sc_state = ESP_HASNEXUS;
- }
- } else {
- printf("%s: bogus reselect (no IDENTIFY) %0x2x\n",
- sc->sc_dev.dv_xname, sc->sc_selid);
- esp_sched_msgout(SEND_DEV_RESET);
+ case ESP_RESELECTED:
+ if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
+ printf("%s: reselect without IDENTIFY; sending DEVICE RESET\n",
+ sc->sc_dev.dv_xname);
+ goto reset;
}
- } else { /* Neither ESP_HASNEXUS nor ESP_RESELECTED! */
- printf("%s: unexpected message in; will send DEV_RESET\n",
+
+ (void) esp_reselect(sc, sc->sc_imess[0]);
+ break;
+
+ default:
+ printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n",
sc->sc_dev.dv_xname);
+ reset:
esp_sched_msgout(SEND_DEV_RESET);
+ break;
+
+ abort:
+ esp_sched_msgout(SEND_ABORT);
+ break;
}
/* Ack last message byte */
@@ -1277,18 +1384,37 @@ esp_msgout(sc)
register struct esp_softc *sc;
{
struct esp_tinfo *ti;
- struct ecb *ecb;
+ struct esp_ecb *ecb;
+ size_t size;
ESP_TRACE(("[esp_msgout(priq:%x, prevphase:%x)]", sc->sc_msgpriq, sc->sc_prevphase));
- if (sc->sc_prevphase != MESSAGE_OUT_PHASE) {
+ if (sc->sc_flags & ESP_ATN) {
+ if (sc->sc_prevphase != MESSAGE_OUT_PHASE) {
+ new:
+ ESPCMD(sc, ESPCMD_FLUSH);
+ DELAY(1);
+ sc->sc_msgoutq = 0;
+ sc->sc_omlen = 0;
+ }
+ } else {
+ if (sc->sc_prevphase == MESSAGE_OUT_PHASE) {
+ esp_sched_msgout(sc->sc_msgoutq);
+ goto new;
+ } else {
+ printf("esp at line %d: unexpected MESSAGE OUT phase\n", __LINE__);
+ }
+ }
+
+ if (sc->sc_omlen == 0) {
/* Pick up highest priority message */
sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
+ sc->sc_msgoutq |= sc->sc_msgout;
+ sc->sc_msgpriq &= ~sc->sc_msgout;
sc->sc_omlen = 1; /* "Default" message len */
switch (sc->sc_msgout) {
case SEND_SDTR:
ecb = sc->sc_nexus;
- sc->sc_flags |= ESP_SYNCHNEGO;
ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
sc->sc_omess[0] = MSG_EXTENDED;
sc->sc_omess[1] = 3;
@@ -1296,17 +1422,21 @@ esp_msgout(sc)
sc->sc_omess[3] = ti->period;
sc->sc_omess[4] = ti->offset;
sc->sc_omlen = 5;
+ if ((sc->sc_flags & ESP_SYNCHNEGO) == 0) {
+ ti->flags |= T_SYNCMODE;
+ esp_setsync(sc, ti);
+ }
break;
case SEND_IDENTIFY:
- if (sc->sc_state != ESP_HASNEXUS) {
- printf("esp at line %d: no nexus", __LINE__);
+ if (sc->sc_state != ESP_CONNECTED) {
+ printf("esp at line %d: no nexus\n", __LINE__);
}
ecb = sc->sc_nexus;
sc->sc_omess[0] = MSG_IDENTIFY(ecb->xs->sc_link->lun,0);
break;
case SEND_DEV_RESET:
+ sc->sc_flags |= ESP_ABORTING;
sc->sc_omess[0] = MSG_BUS_DEV_RESET;
- sc->sc_flags |= ESP_BUSFREE_OK;
ecb = sc->sc_nexus;
ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
ti->flags &= ~T_SYNCMODE;
@@ -1316,8 +1446,8 @@ esp_msgout(sc)
sc->sc_omess[0] = MSG_PARITY_ERROR;
break;
case SEND_ABORT:
+ sc->sc_flags |= ESP_ABORTING;
sc->sc_omess[0] = MSG_ABORT;
- sc->sc_flags |= ESP_BUSFREE_OK;
break;
case SEND_INIT_DET_ERR:
sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
@@ -1326,6 +1456,8 @@ esp_msgout(sc)
sc->sc_omess[0] = MSG_MESSAGE_REJECT;
break;
default:
+ ESPCMD(sc, ESPCMD_RSTATN);
+ sc->sc_flags &= ~ESP_ATN;
sc->sc_omess[0] = MSG_NOOP;
break;
}
@@ -1334,16 +1466,24 @@ esp_msgout(sc)
#if 1
/* (re)send the message */
- DMA_START(sc->sc_dma, &sc->sc_omp, &sc->sc_omlen, 0);
+ size = min(sc->sc_omlen, sc->sc_maxxfer);
+ DMA_SETUP(sc->sc_dma, &sc->sc_omp, &sc->sc_omlen, 0, &size);
+ /* Program the SCSI counter */
+ ESP_WRITE_REG(sc, ESP_TCL, size);
+ ESP_WRITE_REG(sc, ESP_TCM, size >> 8);
+ if (sc->sc_cfg2 & ESPCFG2_FE) {
+ ESP_WRITE_REG(sc, ESP_TCH, size >> 16);
+ }
+ /* load the count in */
+ ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA);
+ ESPCMD(sc, ESPCMD_TRANS|ESPCMD_DMA);
+ DMA_GO(sc->sc_dma);
#else
{ int i;
- ESPCMD(sc, ESPCMD_FLUSH);
for (i = 0; i < sc->sc_omlen; i++)
ESP_WRITE_REG(sc, FIFO, sc->sc_omess[i]);
ESPCMD(sc, ESPCMD_TRANS);
-#if test_stuck_on_msgout
-printf("<<XXXmsgoutdoneXXX>>");
-#endif
+ sc->sc_omlen = 0;
}
#endif
}
@@ -1357,17 +1497,18 @@ printf("<<XXXmsgoutdoneXXX>>");
*
* Most of this needs verifying.
*/
-int
+int
espintr(sc)
register struct esp_softc *sc;
{
- register struct ecb *ecb;
+ register struct esp_ecb *ecb;
register struct scsi_link *sc_link;
struct esp_tinfo *ti;
int loop;
+ size_t size;
ESP_TRACE(("[espintr]"));
-
+
/*
* I have made some (maybe seriously flawed) assumptions here,
* but basic testing (uncomment the printf() below), show that
@@ -1387,7 +1528,7 @@ espintr(sc)
* This is a heuristic. It is 2 when at 20Mhz, 2 at 25Mhz and 1
* at 40Mhz. This needs testing.
*/
- for (loop = 0; ; loop++, DELAY(50/sc->sc_freq)) {
+ for (loop = 0; 1;loop++, DELAY(50/sc->sc_freq)) {
/* a feeling of deja-vu */
if (!DMA_ISINTR(sc->sc_dma))
return (loop != 0);
@@ -1439,9 +1580,7 @@ espintr(sc)
if (sc->sc_nexus)
panic("%s: nexus in reset state",
sc->sc_dev.dv_xname);
- sc->sc_state = ESP_IDLE;
- esp_sched(sc);
- return 1;
+ goto sched;
}
ecb = sc->sc_nexus;
@@ -1456,10 +1595,10 @@ espintr(sc)
ESPCMD(sc, ESPCMD_FLUSH);
DELAY(1);
}
- if (sc->sc_state == ESP_HASNEXUS ||
+ if (sc->sc_state == ESP_CONNECTED ||
sc->sc_state == ESP_SELECTING) {
ecb->xs->error = XS_DRIVER_STUFFUP;
- esp_done(ecb);
+ esp_done(sc, ecb);
}
return 1;
}
@@ -1486,14 +1625,30 @@ espintr(sc)
* again in case there is no more DMA queued, but a phase
* change is expected.
*/
- if (sc->sc_dma->sc_active && DMA_INTR(sc->sc_dma)) {
+ if (DMA_ISACTIVE(sc->sc_dma)) {
+ DMA_INTR(sc->sc_dma);
/* If DMA active here, then go back to work... */
- if (sc->sc_dma->sc_active)
+ if (DMA_ISACTIVE(sc->sc_dma))
return 1;
- if (!(sc->sc_espstat & ESPSTAT_TC))
- printf("%s: !TC\n", sc->sc_dev.dv_xname);
- continue;
+
+ if (sc->sc_dleft == 0 &&
+ (sc->sc_espstat & ESPSTAT_TC) == 0)
+ printf("%s: !TC [intr %x, stat %x, step %d]"
+ " prevphase %x, resid %x\n",
+ sc->sc_dev.dv_xname,
+ sc->sc_espintr,
+ sc->sc_espstat,
+ sc->sc_espstep,
+ sc->sc_prevphase,
+ ecb?ecb->dleft:-1);
+ }
+
+#if 0 /* Unreliable on some ESP revisions? */
+ if ((sc->sc_espstat & ESPSTAT_INT) == 0) {
+ printf("%s: spurious interrupt\n", sc->sc_dev.dv_xname);
+ return 1;
}
+#endif
/*
* check for less serious errors
@@ -1503,12 +1658,13 @@ espintr(sc)
sc->sc_dev.dv_xname);
if (sc->sc_prevphase == MESSAGE_IN_PHASE)
esp_sched_msgout(SEND_PARITY_ERROR);
- else
+ else
esp_sched_msgout(SEND_INIT_DET_ERR);
}
if (sc->sc_espintr & ESPINTR_DIS) {
- ESP_MISC(("<DISC [intr %x, stat %x, step %d]>", sc->sc_espintr, sc->sc_espstat, sc->sc_espstep));
+ ESP_MISC(("<DISC [intr %x, stat %x, step %d]>",
+ sc->sc_espintr,sc->sc_espstat,sc->sc_espstep));
if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) {
ESPCMD(sc, ESPCMD_FLUSH);
DELAY(1);
@@ -1518,38 +1674,59 @@ espintr(sc)
* 250mS of a disconnect. So here you are...
*/
ESPCMD(sc, ESPCMD_ENSEL);
- if (sc->sc_state != ESP_IDLE) {
+ switch (sc->sc_state) {
+ case ESP_RESELECTED:
+ goto sched;
+
+ case ESP_SELECTING:
+ ecb->xs->error = XS_SELTIMEOUT;
+ goto finish;
+
+ case ESP_CONNECTED:
if ((sc->sc_flags & ESP_SYNCHNEGO)) {
- printf("%s: sync nego not completed!\n",
- sc->sc_dev.dv_xname);
+#ifdef ESP_DEBUG
+ if (ecb)
+ sc_print_addr(ecb->xs->sc_link);
+ printf("sync nego not completed!\n");
+#endif
+ ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
+ sc->sc_flags &= ~ESP_SYNCHNEGO;
+ ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
}
- /*XXX*/sc->sc_msgpriq = sc->sc_msgout = 0;
/* it may be OK to disconnect */
- if (!(sc->sc_flags & ESP_BUSFREE_OK))
- ecb->xs->error = XS_TIMEOUT;
- else if (sc->sc_flags & ESP_DISCON) {
- TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain);
- ECB_SETQ(ecb, ECB_QNEXUS);
- sc->sc_nexus = NULL;
- sc->sc_flags &= ~ESP_DISCON;
- sc->sc_state = ESP_IDLE;
- esp_sched(sc);
- return 1;
+ if ((sc->sc_flags & ESP_ABORTING) == 0) {
+ /*
+ * Section 5.1.1 of the SCSI 2 spec
+ * suggests issuing a REQUEST SENSE
+ * following an unexpected disconnect.
+ * Some devices go into a contingent
+ * allegiance condition when
+ * disconnecting, and this is necessary
+ * to clean up their state.
+ */
+ printf("%s: unexpected disconnect; ",
+ sc->sc_dev.dv_xname);
+ if (ecb->flags & ECB_SENSE) {
+ printf("resetting\n");
+ goto reset;
+ }
+ printf("sending REQUEST SENSE\n");
+ esp_sense(sc, ecb);
+ goto out;
}
- esp_done(ecb);
- return 1;
- }
- printf("DISCONNECT in IDLE state!\n");
- }
+ ecb->xs->error = XS_DRIVER_STUFFUP;
+ goto finish;
+
+ case ESP_DISCONNECT:
+ TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain);
+ sc->sc_nexus = NULL;
+ goto sched;
- /* did a message go out OK ? This must be broken */
- if (sc->sc_prevphase == MESSAGE_OUT_PHASE &&
- sc->sc_phase != MESSAGE_OUT_PHASE) {
- /* we have sent it */
- sc->sc_msgpriq &= ~sc->sc_msgout;
- sc->sc_msgout = 0;
+ case ESP_CMDCOMPLETE:
+ goto finish;
+ }
}
switch (sc->sc_state) {
@@ -1572,7 +1749,7 @@ espintr(sc)
printf("<<RESELECT CONT'd>>");
#if XXXX
esp_msgin(sc);
- if (sc->sc_state != ESP_HASNEXUS) {
+ if (sc->sc_state != ESP_CONNECTED) {
/* IDENTIFY fail?! */
printf("%s: identify failed\n",
sc->sc_dev.dv_xname);
@@ -1585,6 +1762,8 @@ printf("<<RESELECT CONT'd>>");
case ESP_IDLE:
if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]");
case ESP_SELECTING:
+ sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0;
+ sc->sc_flags = 0;
if (sc->sc_espintr & ESPINTR_RESEL) {
/*
@@ -1598,8 +1777,6 @@ if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]");
ti = &sc->sc_tinfo[sc_link->target];
TAILQ_INSERT_HEAD(&sc->ready_list,
sc->sc_nexus, chain);
- ECB_SETQ(sc->sc_nexus, ECB_QREADY);
- ti->lubusy &= ~(1<<sc_link->lun);
ecb = sc->sc_nexus = NULL;
}
sc->sc_state = ESP_RESELECTED;
@@ -1608,19 +1785,23 @@ if (sc->sc_flags & ESP_ICCS) printf("[[esp: BUMMER]]");
* Things are seriously fucked up.
* Pull the brakes, i.e. reset
*/
- printf("%s: target didn't identify\n",
+ printf("%s: target didn't identify\n",
sc->sc_dev.dv_xname);
esp_init(sc, 1);
return 1;
}
if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) {
-printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF);
+ printf("%s: RESELECT: %d bytes in FIFO!\n",
+ sc->sc_dev.dv_xname,
+ ESP_READ_REG(sc, ESP_FFLAG) &
+ ESPFIFO_FF);
+ esp_init(sc, 1);
+ return 1;
}
sc->sc_selid = ESP_READ_REG(sc, ESP_FIFO);
- sc->sc_selid &= ~(1<<sc->sc_id);
ESP_MISC(("selid=0x%2x ", sc->sc_selid));
esp_msgin(sc); /* Handle identify message */
- if (sc->sc_state != ESP_HASNEXUS) {
+ if (sc->sc_state != ESP_CONNECTED) {
/* IDENTIFY fail?! */
printf("%s: identify failed\n",
sc->sc_dev.dv_xname);
@@ -1643,25 +1824,24 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
case 0:
printf("%s: select timeout/no disconnect\n",
sc->sc_dev.dv_xname);
- esp_abort(sc, ecb);
- return 1;
+ ecb->xs->error = XS_SELTIMEOUT;
+ goto finish;
case 1:
if ((ti->flags & T_NEGOTIATE) == 0) {
printf("%s: step 1 & !NEG\n",
sc->sc_dev.dv_xname);
- esp_abort(sc, ecb);
- return 1;
+ goto reset;
}
if (sc->sc_phase != MESSAGE_OUT_PHASE) {
printf("%s: !MSGOUT\n",
sc->sc_dev.dv_xname);
- esp_abort(sc, ecb);
- return 1;
+ goto reset;
}
/* Start negotiating */
ti->period = sc->sc_minsync;
ti->offset = 15;
- sc->sc_msgpriq = SEND_SDTR;
+ sc->sc_flags |= ESP_SYNCHNEGO;
+ esp_sched_msgout(SEND_SDTR);
break;
case 3:
/*
@@ -1686,7 +1866,7 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF,
sc->sc_espintr, sc->sc_espstat,
sc->sc_espstep);
- sc->sc_flags |= ESP_ABORTING;
+ ESPCMD(sc, ESPCMD_FLUSH);
esp_sched_msgout(SEND_ABORT);
return 1;
case 2:
@@ -1694,25 +1874,31 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
ESPCMD(sc, ESPCMD_FLUSH);
case 4:
/* So far, everything went fine */
- sc->sc_msgpriq = 0;
break;
}
#if 0
-/* Why set msgpriq? (and not raise ATN) */
if (ecb->xs->flags & SCSI_RESET)
- sc->sc_msgpriq = SEND_DEV_RESET;
+ esp_sched_msgout(SEND_DEV_RESET);
else if (ti->flags & T_NEGOTIATE)
- sc->sc_msgpriq =
- SEND_IDENTIFY | SEND_SDTR;
+ esp_sched_msgout(
+ SEND_IDENTIFY | SEND_SDTR);
else
- sc->sc_msgpriq = SEND_IDENTIFY;
+ esp_sched_msgout(SEND_IDENTIFY);
#endif
- sc->sc_state = ESP_HASNEXUS;
- /*???sc->sc_flags = 0; */
+
+ ecb->flags |= ECB_NEXUS;
+ ti->lubusy |= (1 << sc_link->lun);
+
sc->sc_prevphase = INVALID_PHASE; /* ?? */
+ /* Do an implicit RESTORE POINTERS. */
sc->sc_dp = ecb->daddr;
sc->sc_dleft = ecb->dleft;
- ti->lubusy |= (1<<sc_link->lun);
+
+ /* On our first connection, schedule a timeout. */
+ if ((ecb->xs->flags & SCSI_POLL) == 0)
+ timeout(esp_timeout, ecb, (ecb->timeout * hz) / 1000);
+
+ sc->sc_state = ESP_CONNECTED;
break;
} else {
printf("%s: unexpected status after select"
@@ -1722,7 +1908,7 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
sc->sc_espstep);
ESPCMD(sc, ESPCMD_FLUSH);
DELAY(1);
- esp_abort(sc, ecb);
+ goto reset;
}
if (sc->sc_state == ESP_IDLE) {
printf("%s: stray interrupt\n", sc->sc_dev.dv_xname);
@@ -1730,9 +1916,9 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
}
break;
- case ESP_HASNEXUS:
+ case ESP_CONNECTED:
if (sc->sc_flags & ESP_ICCS) {
- unsigned char msg;
+ u_char msg;
sc->sc_flags &= ~ESP_ICCS;
@@ -1744,22 +1930,16 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
sc->sc_espstep);
}
if ((ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) != 2) {
- printf("%s: ICCS: expected 2, got %d "
- ": [intr %x, stat %x, step %x]\n",
- sc->sc_dev.dv_xname,
- ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF,
- sc->sc_espintr, sc->sc_espstat,
- sc->sc_espstep);
- ESPCMD(sc, ESPCMD_FLUSH);
- esp_abort(sc, ecb);
- return 1;
+ int i = (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) - 2;
+ while (i--)
+ (void) ESP_READ_REG(sc, ESP_FIFO);
}
ecb->stat = ESP_READ_REG(sc, ESP_FIFO);
msg = ESP_READ_REG(sc, ESP_FIFO);
ESP_PHASE(("<stat:(%x,%x)>", ecb->stat, msg));
if (msg == MSG_CMDCOMPLETE) {
- sc->sc_flags |= ESP_BUSFREE_OK;
ecb->xs->resid = ecb->dleft = sc->sc_dleft;
+ sc->sc_state = ESP_CMDCOMPLETE;
} else
printf("%s: STATUS_PHASE: msg %d\n",
sc->sc_dev.dv_xname, msg);
@@ -1774,10 +1954,10 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
}
/*
- * Driver is now in state ESP_HASNEXUS, i.e. we
+ * Driver is now in state ESP_CONNECTED, i.e. we
* have a current command working the SCSI bus.
*/
- if (sc->sc_state != ESP_HASNEXUS || ecb == NULL) {
+ if (sc->sc_state != ESP_CONNECTED || ecb == NULL) {
panic("esp no nexus");
}
@@ -1833,31 +2013,39 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
case DATA_OUT_PHASE:
ESP_PHASE(("DATA_OUT_PHASE [%d] ", sc->sc_dleft));
ESPCMD(sc, ESPCMD_FLUSH);
- DMA_START(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, 0);
+ size = min(sc->sc_dleft, sc->sc_maxxfer);
+ DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft,
+ 0, &size);
sc->sc_prevphase = DATA_OUT_PHASE;
- return 1;
+ goto setup_xfer;
case DATA_IN_PHASE:
ESP_PHASE(("DATA_IN_PHASE "));
if (sc->sc_rev == ESP100)
ESPCMD(sc, ESPCMD_FLUSH);
-#if 0 /* Why is the fifo sometimes full after re-connect? */
- if (ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF) {
- static int xxx;
- if (xxx <= 3) {
- printf("%s: lost %d bytes from FIFO ",
- sc->sc_dev.dv_xname,
- ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF);
- printf(" previous phase %x\n",
- sc->sc_prevphase);
- if (xxx == 3)
- printf("(stopped logging)");
- ++xxx;
- }
- }
-#endif
- DMA_DRAIN(sc->sc_dma);
- DMA_START(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft, 1);
+ size = min(sc->sc_dleft, sc->sc_maxxfer);
+ DMA_SETUP(sc->sc_dma, &sc->sc_dp, &sc->sc_dleft,
+ 1, &size);
sc->sc_prevphase = DATA_IN_PHASE;
+ setup_xfer:
+ /* Program the SCSI counter */
+ ESP_WRITE_REG(sc, ESP_TCL, size);
+ ESP_WRITE_REG(sc, ESP_TCM, size >> 8);
+ if (sc->sc_cfg2 & ESPCFG2_FE) {
+ ESP_WRITE_REG(sc, ESP_TCH, size >> 16);
+ }
+ /* load the count in */
+ ESPCMD(sc, ESPCMD_NOP|ESPCMD_DMA);
+
+ /*
+ * Note that if `size' is 0, we've already transceived
+ * all the bytes we want but we're still in DATA PHASE.
+ * Apparently, the device needs padding. Also, a
+ * transfer size of 0 means "maximum" to the chip
+ * DMA logic.
+ */
+ ESPCMD(sc,
+ (size==0?ESPCMD_TRPAD:ESPCMD_TRANS)|ESPCMD_DMA);
+ DMA_GO(sc->sc_dma);
return 1;
case STATUS_PHASE:
ESP_PHASE(("STATUS_PHASE "));
@@ -1867,31 +2055,52 @@ printf("<RESELECT: %d bytes in FIFO>", ESP_READ_REG(sc, ESP_FFLAG) & ESPFIFO_FF)
break;
case INVALID_PHASE:
break;
- case BUSFREE_PHASE:
- if (sc->sc_flags & ESP_BUSFREE_OK) {
- /*It's fun the 1st time.. */
- sc->sc_flags &= ~ESP_BUSFREE_OK;
- }
- break;
default:
- panic("esp: bogus bus phase\n");
+ printf("%s: unexpected bus phase; resetting\n",
+ sc->sc_dev.dv_xname);
+ goto reset;
}
}
panic("esp: should not get here..");
+
+reset:
+ esp_init(sc, 1);
+ return 1;
+
+finish:
+ untimeout(esp_timeout, ecb);
+ esp_done(sc, ecb);
+ goto out;
+
+sched:
+ sc->sc_state = ESP_IDLE;
+ esp_sched(sc);
+ goto out;
+
+out:
+ return 1;
}
void
esp_abort(sc, ecb)
struct esp_softc *sc;
- struct ecb *ecb;
+ struct esp_ecb *ecb;
{
+
+ /* 2 secs for the abort */
+ ecb->timeout = ESP_ABORT_TIMEOUT;
+ ecb->flags |= ECB_ABORT;
+
if (ecb == sc->sc_nexus) {
-/*XXX*/sc->sc_tinfo[ecb->xs->sc_link->target].flags |= T_XXX;
- if (sc->sc_state == ESP_HASNEXUS) {
- sc->sc_flags |= ESP_ABORTING;
+ /*
+ * If we're still selecting, the message will be scheduled
+ * after selection is complete.
+ */
+ if (sc->sc_state == ESP_CONNECTED)
esp_sched_msgout(SEND_ABORT);
- }
} else {
+ esp_dequeue(sc, ecb);
+ TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
if (sc->sc_state == ESP_IDLE)
esp_sched(sc);
}
@@ -1901,58 +2110,36 @@ void
esp_timeout(arg)
void *arg;
{
- int s = splbio();
- struct ecb *ecb = (struct ecb *)arg;
- struct esp_softc *sc;
+ struct esp_ecb *ecb = arg;
struct scsi_xfer *xs = ecb->xs;
+ struct scsi_link *sc_link = xs->sc_link;
+ struct esp_softc *sc = sc_link->adapter_softc;
+ int s;
+
+ sc_print_addr(sc_link);
+ printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], "
+ "<state %d, nexus %p, phase(c %x, p %x), resid %x, msg(q %x,o %x) %s>",
+ sc->sc_dev.dv_xname,
+ ecb, ecb->flags, ecb->dleft, ecb->stat,
+ sc->sc_state, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
+ sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout,
+ DMA_ISACTIVE(sc->sc_dma) ? "DMA active" : "");
+#if ESP_DEBUG > 0
+ printf("TRACE: %s.", ecb->trace);
+#endif
- sc = xs->sc_link->adapter_softc;
- sc_print_addr(xs->sc_link);
-again:
- printf("timed out (ecb 0x%x (flags 0x%x, dleft %x), state %d, phase %d, msgpriq %x, msgout %x)",
- ecb, ecb->flags, ecb->dleft, sc->sc_state, sc->sc_phase,
- sc->sc_msgpriq, sc->sc_msgout);
+ s = splbio();
- if (ecb->flags == ECB_QFREE) {
- printf("note: ecb already on free list\n");
- splx(s);
- return;
- }
- if (ecb->flags & ECB_ABORTED) {
+ if (ecb->flags & ECB_ABORT) {
/* abort timed out */
printf(" AGAIN\n");
- xs->retries = 0;
esp_init(sc, 1);
} else {
/* abort the operation that has timed out */
printf("\n");
xs->error = XS_TIMEOUT;
- ecb->flags |= ECB_ABORTED;
-#if 0
-if (sc->sc_dma->sc_active) {
- int x = esp_debug; esp_debug=0x3ff;
- DMA_INTR(sc->sc_dma);
- esp_debug = x;
-}
-#endif
esp_abort(sc, ecb);
- /* 2 secs for the abort */
- if ((xs->flags & SCSI_POLL) == 0)
- timeout(esp_timeout, ecb, 2 * hz);
- else {
- int count = 200000;
- while (count) {
- if (DMA_ISINTR(sc->sc_dma)) {
- espintr(sc);
- }
- if (xs->flags & ITSDONE)
- break;
- DELAY(10);
- --count;
- }
- if (count == 0)
- goto again;
- }
}
+
splx(s);
}
diff --git a/sys/arch/alpha/tc/espreg.h b/sys/arch/alpha/tc/espreg.h
index d6602261f90..8492f1d5378 100644
--- a/sys/arch/alpha/tc/espreg.h
+++ b/sys/arch/alpha/tc/espreg.h
@@ -1,9 +1,8 @@
-/* $OpenBSD: espreg.h,v 1.3 1996/07/29 23:02:02 niklas Exp $ */
-/* $NetBSD: espreg.h,v 1.2 1995/12/20 00:40:25 cgd Exp $ */
+/* $OpenBSD: espreg.h,v 1.4 1996/10/30 22:41:06 niklas Exp $ */
+/* $NetBSD: espreg.h,v 1.3 1996/09/09 18:10:37 cgd Exp $ */
/*
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -132,10 +131,8 @@
#define ESP_TEST 0x0a /* WO - Test (Chip Test Only) */
#define ESP_CFG2 0x0b /* RW - Configuration #2 */
-#if 0
-#define ESPCFG2_RSVD 0xa0 /* reserved */
+#define ESPCFG2_RSVD 0xa0 /* reserved */
#define ESPCFG2_FE 0x40 /* Features Enable */
-#endif
#define ESPCFG2_DREQ 0x10 /* DREQ High Impedance */
#define ESPCFG2_SCSI2 0x08 /* SCSI-2 Enable */
#define ESPCFG2_BPA 0x04 /* Target Bad Parity Abort */
@@ -144,11 +141,9 @@
/* Config #3 only on 53C9X */
#define ESP_CFG3 0x0c /* RW - Configuration #3 */
-#if 0
#define ESPCFG3_RSVD 0xe0 /* reserved */
#define ESPCFG3_IDM 0x10 /* ID Message Res Check */
#define ESPCFG3_QTE 0x08 /* Queue Tag Enable */
#define ESPCFG3_CDB 0x04 /* CDB 10-bytes OK */
#define ESPCFG3_FSCSI 0x02 /* Fast SCSI */
#define ESPCFG3_FCLK 0x01 /* Fast Clock (>25Mhz) */
-#endif
diff --git a/sys/arch/alpha/tc/espvar.h b/sys/arch/alpha/tc/espvar.h
index 0564fcbdc1e..c21eb0d92c9 100644
--- a/sys/arch/alpha/tc/espvar.h
+++ b/sys/arch/alpha/tc/espvar.h
@@ -1,5 +1,9 @@
-/* $OpenBSD: espvar.h,v 1.4 1996/10/18 16:12:03 niklas Exp $ */
-/* $NetBSD: espvar.h,v 1.3 1995/12/20 00:40:26 cgd Exp $ */
+/* $OpenBSD: espvar.h,v 1.5 1996/10/30 22:41:07 niklas Exp $ */
+/* $NetBSD: espvar.h,v 1.10 1996/10/15 21:31:37 mycroft Exp $ */
+
+#if defined(__sparc__) && !defined(SPARC_DRIVER)
+#define SPARC_DRIVER
+#endif
/*
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
@@ -30,7 +34,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define ESP_DEBUG 0
+#define ESP_DEBUG 0
+
+#define ESP_ABORT_TIMEOUT 2000 /* time to wait for abort */
#define FREQTOCCF(freq) (((freq + 4) / 5))
@@ -40,7 +46,7 @@
#define ESP200 0x03
#define NCR53C94 0x04
-/*
+/*
* ECB. Holds additional information for each SCSI command Comments: We
* need a separate scsi command block because we may need to overwrite it
* with a request sense command. Basicly, we refrain from fiddling with
@@ -48,28 +54,41 @@
* We'll generally update: xs->{flags,resid,error,sense,status} and
* occasionally xs->retries.
*/
-struct ecb {
- TAILQ_ENTRY(ecb) chain;
+struct esp_ecb {
+ TAILQ_ENTRY(esp_ecb) chain;
struct scsi_xfer *xs; /* SCSI xfer ctrl block from above */
- int flags; /* Status */
-#define ECB_QNONE 0
-#define ECB_QFREE 1
-#define ECB_QREADY 2
-#define ECB_QNEXUS 3
-#define ECB_QBITS 0x07
-#define ECB_CHKSENSE 0x08
-#define ECB_ABORTED 0x10
-#define ECB_SETQ(e, q) do (e)->flags = ((e)->flags&~ECB_QBITS)|(q); while(0)
+ int flags;
+#define ECB_ALLOC 0x01
+#define ECB_NEXUS 0x02
+#define ECB_SENSE 0x04
+#define ECB_ABORT 0x40
+#define ECB_RESET 0x80
+ int timeout;
+
struct scsi_generic cmd; /* SCSI command block */
int clen;
char *daddr; /* Saved data pointer */
int dleft; /* Residue */
u_char stat; /* SCSI status byte */
+
+#if ESP_DEBUG > 0
+ char trace[1000];
+#endif
};
+#if ESP_DEBUG > 0
+#define ECB_TRACE(ecb, msg, a, b) do { \
+ const char *f = "[" msg "]"; \
+ int n = strlen((ecb)->trace); \
+ if (n < (sizeof((ecb)->trace)-100)) \
+ sprintf((ecb)->trace + n, f, a, b); \
+} while(0)
+#else
+#define ECB_TRACE(ecb, msg, a, b)
+#endif
-/*
- * Some info about each (possible) target on the SCSI bus. This should
- * probably have been a "per target+lunit" structure, but we'll leave it at
+/*
+ * Some info about each (possible) target on the SCSI bus. This should
+ * probably have been a "per target+lunit" structure, but we'll leave it at
* this for now. Is there a way to reliably hook it up to sc->fordriver??
*/
struct esp_tinfo {
@@ -84,8 +103,8 @@ struct esp_tinfo {
#define T_NEGOTIATE 0x02 /* (Re)Negotiate synchronous options */
#define T_BUSY 0x04 /* Target is busy, i.e. cmd in progress */
#define T_SYNCMODE 0x08 /* sync mode has been negotiated */
-#define T_XXX 0x10 /* Target is XXX */
-#define T_SYNCHNEGO 0x20 /* .. */
+#define T_SYNCHOFF 0x10 /* .. */
+#define T_RSELECTOFF 0x20 /* .. */
u_char period; /* Period suggestion */
u_char offset; /* Offset suggestion */
} tinfo_t;
@@ -106,15 +125,15 @@ struct esp_tinfo {
#ifdef ESP_DEBUG
extern int esp_debug;
-#define ESP_ECBS(str) do {if (esp_debug & ESP_SHOWECBS) printf str;} while (0)
-#define ESP_MISC(str) do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0)
-#define ESP_INTS(str) do {if (esp_debug & ESP_SHOWINTS) printf str;} while (0)
-#define ESP_TRACE(str) do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0)
-#define ESP_CMDS(str) do {if (esp_debug & ESP_SHOWCMDS) printf str;} while (0)
-#define ESP_START(str) do {if (esp_debug & ESP_SHOWSTART) printf str;}while (0)
-#define ESP_PHASE(str) do {if (esp_debug & ESP_SHOWPHASE) printf str;}while (0)
-#define ESP_DMA(str) do {if (esp_debug & ESP_SHOWDMA) printf str;} while (0)
-#define ESP_MSGS(str) do {if (esp_debug & ESP_SHOWMSGS) printf str;} while (0)
+#define ESP_ECBS(str) do {if (esp_debug & ESP_SHOWECBS) printf str;} while (0)
+#define ESP_MISC(str) do {if (esp_debug & ESP_SHOWMISC) printf str;} while (0)
+#define ESP_INTS(str) do {if (esp_debug & ESP_SHOWINTS) printf str;} while (0)
+#define ESP_TRACE(str) do {if (esp_debug & ESP_SHOWTRAC) printf str;} while (0)
+#define ESP_CMDS(str) do {if (esp_debug & ESP_SHOWCMDS) printf str;} while (0)
+#define ESP_START(str) do {if (esp_debug & ESP_SHOWSTART) printf str;}while (0)
+#define ESP_PHASE(str) do {if (esp_debug & ESP_SHOWPHASE) printf str;}while (0)
+#define ESP_DMA(str) do {if (esp_debug & ESP_SHOWDMA) printf str;}while (0)
+#define ESP_MSGS(str) do {if (esp_debug & ESP_SHOWMSGS) printf str;}while (0)
#else
#define ESP_ECBS(str)
#define ESP_MISC(str)
@@ -160,12 +179,12 @@ struct esp_softc {
u_char sc_espfflags;
/* Lists of command blocks */
- TAILQ_HEAD(ecb_list, ecb) free_list,
- ready_list,
- nexus_list;
+ TAILQ_HEAD(ecb_list, esp_ecb) free_list,
+ ready_list,
+ nexus_list;
- struct ecb *sc_nexus; /* current command */
- struct ecb sc_ecb[8]; /* one per target */
+ struct esp_ecb *sc_nexus; /* current command */
+ struct esp_ecb sc_ecb[16]; /* one per target */
struct esp_tinfo sc_tinfo[8];
/* Data about the current nexus (updated for every cmd switch) */
@@ -183,6 +202,7 @@ struct esp_softc {
/* Message stuff */
u_char sc_msgpriq; /* One or more messages to send (encoded) */
u_char sc_msgout; /* What message is on its way out? */
+ u_char sc_msgoutq; /* What messages have been sent so far? */
u_char sc_omess[ESP_MAX_MSG_LEN];
caddr_t sc_omp; /* Message pointer (for multibyte messages) */
size_t sc_omlen;
@@ -199,48 +219,39 @@ struct esp_softc {
int sc_id; /* our scsi id */
int sc_rev; /* esp revision */
int sc_minsync; /* minimum sync period / 4 */
+ int sc_maxxfer; /* maximum transfer size */
};
/* values for sc_state */
-#define ESP_IDLE 0x01 /* waiting for something to do */
-#define ESP_TMP_UNAVAIL 0x02 /* Don't accept SCSI commands */
-#define ESP_SELECTING 0x03 /* SCSI command is arbiting */
-#define ESP_RESELECTED 0x04 /* Has been reselected */
-#define ESP_HASNEXUS 0x05 /* Actively using the SCSI bus */
-#define ESP_CLEANING 0x06
-#define ESP_SBR 0x07 /* Expect a SCSI RST because we commanded it */
+#define ESP_IDLE 1 /* waiting for something to do */
+#define ESP_SELECTING 2 /* SCSI command is arbiting */
+#define ESP_RESELECTED 3 /* Has been reselected */
+#define ESP_CONNECTED 4 /* Actively using the SCSI bus */
+#define ESP_DISCONNECT 5 /* MSG_DISCONNECT received */
+#define ESP_CMDCOMPLETE 6 /* MSG_CMDCOMPLETE received */
+#define ESP_CLEANING 7
+#define ESP_SBR 8 /* Expect a SCSI RST because we commanded it */
/* values for sc_flags */
#define ESP_DROP_MSGI 0x01 /* Discard all msgs (parity err detected) */
-#define ESP_DOINGDMA 0x02 /* The FIFO data path is active! */
-#define ESP_BUSFREE_OK 0x04 /* Bus free phase is OK. */
+#define ESP_ABORTING 0x02 /* Bailing out */
+#define ESP_DOINGDMA 0x04 /* The FIFO data path is active! */
#define ESP_SYNCHNEGO 0x08 /* Synch negotiation in progress. */
-/*#define ESP_BLOCKED 0x10 * Don't schedule new scsi bus operations */
-#define ESP_DISCON 0x10 /* Target sent DISCONNECT msg */
-#define ESP_ABORTING 0x20 /* Bailing out */
-#define ESP_ICCS 0x40 /* Expect status phase results */
-#define ESP_WAITI 0x80 /* Waiting for non-DMA data to arrive */
+#define ESP_ICCS 0x10 /* Expect status phase results */
+#define ESP_WAITI 0x20 /* Waiting for non-DMA data to arrive */
+#define ESP_ATN 0x40 /* ATN asserted */
/* values for sc_msgout */
#define SEND_DEV_RESET 0x01
#define SEND_PARITY_ERROR 0x02
-#define SEND_ABORT 0x04
+#define SEND_INIT_DET_ERR 0x04
#define SEND_REJECT 0x08
-#define SEND_INIT_DET_ERR 0x10
-#define SEND_IDENTIFY 0x20
+#define SEND_IDENTIFY 0x10
+#define SEND_ABORT 0x20
#define SEND_SDTR 0x40
+#define SEND_WDTR 0x80
/* SCSI Status codes */
-#define ST_GOOD 0x00
-#define ST_CHKCOND 0x02
-#define ST_CONDMET 0x04
-#define ST_BUSY 0x08
-#define ST_INTERMED 0x10
-#define ST_INTERMED_CONDMET 0x14
-#define ST_RESERVATION_CONFLICT 0x18
-#define ST_CMD_TERM 0x22
-#define ST_QUEUE_FULL 0x28
-
#define ST_MASK 0x3e /* bit 0,6,7 is reserved */
/* phase bits */
@@ -263,8 +274,21 @@ struct esp_softc {
#define INVALID_PHASE 0x101 /* Re/Selection valid, but no REQ yet */
#define PSEUDO_PHASE 0x100 /* "pseudo" bit */
+/*
+ * Macros to read and write the chip's registers.
+ */
+#ifdef SPARC_DRIVER
+#define ESP_READ_REG(sc, reg) \
+ ((sc)->sc_reg[(reg) * 4])
+#define ESP_WRITE_REG(sc, reg, val) \
+ do { \
+ u_char v = (val); \
+ (sc)->sc_reg[(reg) * 4] = v; \
+ } while (0)
+#else /* ! SPARC_DRIVER */
#if 1
static __inline u_char ESP_READ_REG __P((struct esp_softc *, int));
+
static __inline u_char
ESP_READ_REG(sc, reg)
struct esp_softc *sc;
@@ -273,7 +297,7 @@ ESP_READ_REG(sc, reg)
u_char v;
v = sc->sc_reg[reg * 2] & 0xff;
- wbflush();
+ alpha_mb();
return v;
}
#else
@@ -284,8 +308,9 @@ ESP_READ_REG(sc, reg)
do { \
u_char v = (val); \
(sc)->sc_reg[(reg) * 2] = v; \
- wbflush(); \
+ alpha_mb(); \
} while (0)
+#endif /* SPARC_DRIVER */
#ifdef ESP_DEBUG
#define ESPCMD(sc, cmd) do { \
@@ -302,24 +327,13 @@ ESP_READ_REG(sc, reg)
((bp->val[0] == ca->ca_slot && bp->val[1] == ca->ca_offset) || \
(bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit))
+#ifndef SPARC_DRIVER
/* DMA macros for ESP */
-#ifdef SPARC_DRIVER
-#define DMA_ENINTR(r) ((r->enintr)(r))
-#define DMA_ISINTR(r) ((r->isintr)(r))
-#define DMA_RESET(r) ((r->reset)(r))
-#define DMA_START(a, b, c, d) ((a->start)(a, b, c, d))
-#define DMA_INTR(r) ((r->intr)(r))
-#define DMA_DRAIN(sc) if (sc->sc_rev < DMAREV_2) { \
- DMACSR(sc) |= D_DRAIN; \
- DMAWAIT1(sc); \
- }
-#else
-int tcds_dma_intr __P((struct tcds_slotconfig *));
-
-#define DMA_ENINTR(r) tcds_dma_enintr(r)
-#define DMA_ISINTR(r) tcds_dma_isintr(r)
-#define DMA_RESET(r) tcds_dma_reset(r)
-#define DMA_START(a, b, c, d) tcds_dma_start(a, b, c, d)
-#define DMA_INTR(r) tcds_dma_intr(r)
-#define DMA_DRAIN(sc)
+#define DMA_ISINTR(sc) tcds_dma_isintr(sc)
+#define DMA_RESET(sc) tcds_dma_reset(sc)
+#define DMA_INTR(sc) tcds_dma_intr(sc)
+#define DMA_SETUP(sc, addr, len, datain, dmasize) \
+ tcds_dma_setup(sc, addr, len, datain, dmasize)
+#define DMA_GO(sc) tcds_dma_go(sc)
+#define DMA_ISACTIVE(sc) tcds_dma_isactive(sc)
#endif
diff --git a/sys/arch/alpha/tc/ioasic.c b/sys/arch/alpha/tc/ioasic.c
index b6e09102e31..37e6d1bf17d 100644
--- a/sys/arch/alpha/tc/ioasic.c
+++ b/sys/arch/alpha/tc/ioasic.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ioasic.c,v 1.3 1996/07/29 23:02:06 niklas Exp $ */
-/* $NetBSD: ioasic.c,v 1.4.4.1 1996/06/05 00:39:05 cgd Exp $ */
+/* $OpenBSD: ioasic.c,v 1.4 1996/10/30 22:41:08 niklas Exp $ */
+/* $NetBSD: ioasic.c,v 1.9 1996/10/13 03:00:32 christos Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -54,7 +54,7 @@ struct ioasic_softc {
/* Definition of the driver for autoconfig. */
int ioasicmatch __P((struct device *, void *, void *));
void ioasicattach __P((struct device *, struct device *, void *));
-int ioasicprint(void *, char *);
+int ioasicprint(void *, /* const */ char *);
struct cfattach ioasic_ca = {
sizeof(struct ioasic_softc), ioasicmatch, ioasicattach,
@@ -190,7 +190,7 @@ ioasicattach(parent, self, aux)
int
ioasicprint(aux, pnp)
void *aux;
- char *pnp;
+ /* const */ char *pnp;
{
struct ioasicdev_attach_args *d = aux;
@@ -288,10 +288,10 @@ ioasic_intr(val)
void *val;
{
register struct ioasic_softc *sc = val;
- register int i, ifound;
+ register int ifound;
int gifound;
- u_int32_t sir, junk;
- volatile u_int32_t *sirp, *junkp;
+ u_int32_t sir;
+ volatile u_int32_t *sirp;
sirp = (volatile u_int32_t *)IOASIC_REG_INTR(sc->sc_base);
diff --git a/sys/arch/alpha/tc/ioasicreg.h b/sys/arch/alpha/tc/ioasicreg.h
index 370c0d47d14..2c09ef47776 100644
--- a/sys/arch/alpha/tc/ioasicreg.h
+++ b/sys/arch/alpha/tc/ioasicreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioasicreg.h,v 1.2 1996/07/29 23:02:07 niklas Exp $ */
+/* $OpenBSD: ioasicreg.h,v 1.3 1996/10/30 22:41:09 niklas Exp $ */
/* $NetBSD: ioasicreg.h,v 1.1 1995/12/20 00:43:22 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/mcclock_ioasic.c b/sys/arch/alpha/tc/mcclock_ioasic.c
index 6a01a25b5ee..235fff4e901 100644
--- a/sys/arch/alpha/tc/mcclock_ioasic.c
+++ b/sys/arch/alpha/tc/mcclock_ioasic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mcclock_ioasic.c,v 1.2 1996/07/29 23:02:09 niklas Exp $ */
+/* $OpenBSD: mcclock_ioasic.c,v 1.3 1996/10/30 22:41:10 niklas Exp $ */
/* $NetBSD: mcclock_ioasic.c,v 1.2 1996/04/17 22:22:58 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/scc.c b/sys/arch/alpha/tc/scc.c
index eeae075cba2..bfa713ad8d0 100644
--- a/sys/arch/alpha/tc/scc.c
+++ b/sys/arch/alpha/tc/scc.c
@@ -1,27 +1,27 @@
-/* $OpenBSD: scc.c,v 1.5 1996/07/29 23:02:11 niklas Exp $ */
-/* $NetBSD: scc.c,v 1.16.4.2 1996/06/03 19:44:41 cgd Exp $ */
+/* $OpenBSD: scc.c,v 1.6 1996/10/30 22:41:11 niklas Exp $ */
+/* $NetBSD: scc.c,v 1.26 1996/10/16 05:07:57 jonathan Exp $ */
-/*
+/*
* Copyright (c) 1991,1990,1989,1994,1995,1996 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
+ *
+ * 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.
*/
@@ -101,6 +101,7 @@
#include <pmax/dev/fbreg.h>
#endif
+#include <machine/autoconf.h> /* For the badaddr() proto */
#include <machine/rpb.h>
#include <dev/tc/tcvar.h>
@@ -112,14 +113,24 @@ extern void ttrstrt __P((void *));
#undef SCCDEV
#define SCCDEV 15 /* XXX */
-#define NSCCLINE (NSCC*2)
+/*
+ * rcons glass-tty console (as used on pmax) needs lk-201 ASCII input
+ * support from the tty drivers. This is ugly and broken and won't
+ * compile on Alphas.
+ */
+#ifdef pmax
+#define HAVE_RCONS
+extern int pending_remcons;
+#endif
+
+#define NSCCLINE (NSCC*2)
#define SCCUNIT(dev) (minor(dev) >> 1)
#define SCCLINE(dev) (minor(dev) & 0x1)
-struct tty *scc_tty[NSCCLINE];
-void (*sccDivertXInput)(); /* X windows keyboard input routine */
-void (*sccMouseEvent)(); /* X windows mouse motion event routine */
-void (*sccMouseButtons)(); /* X windows mouse buttons event routine */
+/* QVSS-compatible in-kernel X input event parser, pointer tracker */
+void (*sccDivertXInput) __P((int cc)); /* X windows keyboard input routine */
+void (*sccMouseEvent) __P((int)); /* X windows mouse motion event routine */
+void (*sccMouseButtons) __P((int)); /* X windows mouse buttons event routine */
#ifdef DEBUG
int debugChar;
#endif
@@ -134,13 +145,21 @@ struct scc_softc {
u_char wr5;
u_char wr14;
} scc_wreg[2];
+ struct tty *scc_tty[2];
int scc_softCAR;
+
+ int scc_flags[2];
+#define SCC_CHAN_NEEDSDELAY 0x01 /* sw must delay 1.6us between output*/
+#define SCC_CHAN_NOMODEM 0x02 /* don't touch modem ctl lines (may
+ be left floating or x-wired */
+#define SCC_CHAN_MODEM_CROSSED 0x04 /* modem lines wired to other channel*/
+#define SCC_CHAN_KBDLINE 0x08 /* XXX special-case keyboard lines */
};
/*
* BRG formula is:
* ClockFrequency
- * BRGconstant = --------------------------- - 2
+ * BRGconstant = --------------------------- - 2
* 2 * BaudRate * ClockDivider
*
* Speed selections with Pclk=7.3728Mhz, clock x16
@@ -159,9 +178,13 @@ struct speedtab sccspeedtab[] = {
{ 1800, 126, },
{ 2400, 94, },
{ 4800, 46, },
+ { 7200, 30, }, /* non-POSIX */
{ 9600, 22, },
+ { 14400, 14, }, /* non-POSIX */
{ 19200, 10, },
- { 38400, 4, },
+ { 28800, 6, }, /* non-POSIX */
+ { 38400, 4, }, /* non-POSIX */
+ { 57600, 2, }, /* non-POSIX */
{ -1, -1, },
};
@@ -174,9 +197,10 @@ struct speedtab sccspeedtab[] = {
#endif
/* Definition of the driver for autoconfig. */
-static int sccmatch(struct device *, void *, void *);
-static void sccattach(struct device *, struct device *, void *);
-
+static int sccmatch __P((struct device * parent, void *cfdata,
+ void *aux));
+static void sccattach __P((struct device *parent, struct device *self,
+ void *aux));
struct cfattach scc_ca = {
sizeof (struct scc_softc), sccmatch, sccattach,
};
@@ -185,12 +209,21 @@ struct cfdriver scc_cd = {
NULL, "scc", DV_TTY,
};
+int sccopen __P((dev_t, int, int, struct proc *));
+int sccclose __P((dev_t, int, int, struct proc *));
+int sccread __P((dev_t, struct uio *, int));
+int sccwrite __P((dev_t, struct uio *, int));
+struct tty *scctty __P((dev_t));
+int sccioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+void sccstop __P((struct tty *, int));
int sccGetc __P((dev_t));
void sccPutc __P((dev_t, int));
void sccPollc __P((dev_t, int));
int sccparam __P((struct tty *, struct termios *));
void sccstart __P((struct tty *));
int sccmctl __P((dev_t, int, int));
+static int cold_sccparam __P((struct tty *, struct termios *,
+ struct scc_softc *sc));
#ifdef SCC_DEBUG
static void rr __P((char *, scc_regmap_t *));
@@ -201,9 +234,97 @@ static void sccreset __P((struct scc_softc *));
int sccintr __P((void *));
void scc_alphaintr __P((int));
+
+/*
+ * console variables, for using serial console while still cold and
+ * autoconfig has not attached the scc device.
+ */
+extern int cold;
+scc_regmap_t *scc_cons_addr = 0;
+static struct scc_softc coldcons_softc;
+static struct consdev scccons = {
+ NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0
+};
+void scc_consinit __P((dev_t dev, scc_regmap_t *sccaddr));
+void scc_oconsinit __P((struct scc_softc *, dev_t));
+
+
+/*
+ * Set up a given unit as a serial console device.
+ * We need console output when cold, and before any device is configured.
+ * Should be callable when cold, to reset the chip and set parameters
+ * for a remote (serial) console or kgdb line.
+ * XXX
+ * As most DECstations only bring out one rs-232 lead from an SCC
+ * to the bulkhead, and use the other for mouse and keyboard, we
+ * only allow one unit per SCC to be console.
+ */
+void
+scc_consinit(dev, sccaddr)
+ dev_t dev;
+ scc_regmap_t *sccaddr;
+{
+ struct scc_softc *sc;
+ struct termios cterm;
+ struct tty ctty;
+ int s;
+
+ /* Save address in case we're cold. */
+ if (cold && scc_cons_addr == 0) {
+ scc_cons_addr = sccaddr;
+ sc = &coldcons_softc;
+ coldcons_softc.scc_pdma[0].p_addr = sccaddr;
+ coldcons_softc.scc_pdma[1].p_addr = sccaddr;
+ } else {
+ /* being called from sccattach() to reset console */
+ sc = scc_cd.cd_devs[SCCUNIT(dev)];
+ }
+
+ /* Reset chip. */
+ sccreset(sc);
+ /* XXX make sure sccreset() called only once for this chip? */
+
+ /* set console-line parameters */
+ s = spltty();
+ ctty.t_dev = dev;
+ scccons.cn_dev = dev;
+ cterm.c_cflag = CS8;
+#ifdef pmax
+ /* XXX -- why on pmax, not on Alpha? */
+ cterm.c_cflag |= CLOCAL;
+#endif
+ cterm.c_ospeed = cterm.c_ispeed = 9600;
+ (void) cold_sccparam(&ctty, &cterm, sc);
+ *cn_tab = scccons;
+ DELAY(1000);
+ splx(s);
+}
+
+void
+scc_oconsinit(sc, dev)
+ struct scc_softc *sc;
+ dev_t dev;
+{
+ struct termios cterm;
+ struct tty ctty;
+ int s;
+
+ s = spltty();
+ ctty.t_dev = dev;
+ cterm.c_cflag = CS8;
+#ifdef pmax
+ /* XXX -- why on pmax, not on Alpha? */
+ cterm.c_cflag |= CLOCAL;
+#endif
+ cterm.c_ospeed = cterm.c_ispeed = 9600;
+ (void) sccparam(&ctty, &cterm);
+ DELAY(1000);
+ splx(s);
+}
+
/*
* Test to see if device is present.
- * Return true if found and initialized ok.
+ * Return true if found.
*/
int
sccmatch(parent, cfdata, aux)
@@ -215,10 +336,16 @@ sccmatch(parent, cfdata, aux)
struct ioasicdev_attach_args *d = aux;
void *sccaddr;
- /* XXX BUS TYPE? */
+ if (parent->dv_cfdata->cf_driver != &ioasic_cd) {
+#ifdef DIAGNOSTIC
+ printf("Cannot attach scc on %s\n", parent->dv_xname);
+#endif
+ return (0);
+ }
/* Make sure that we're looking for this type of device. */
- if (strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN))
+ if ((strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN) != 0) &&
+ (strncmp(d->iada_modname, "scc", TC_ROM_LLEN)!= 0))
return (0);
/* XXX MATCH CFLOC */
@@ -236,6 +363,11 @@ sccmatch(parent, cfdata, aux)
return (1);
}
+#ifdef alpha
+/*
+ * Enable ioasic SCC interrupts and scc DMA engine interrupts.
+ * XXX does not really belong here.
+ */
void
scc_alphaintr(onoff)
int onoff;
@@ -257,14 +389,15 @@ scc_alphaintr(onoff)
IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2);
#endif
}
- wbflush();
+ tc_mb();
}
+#endif /* alpha */
void
sccattach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+ struct device *parent;
+ struct device *self;
+ void *aux;
{
struct scc_softc *sc = (struct scc_softc *)self;
struct ioasicdev_attach_args *d = aux;
@@ -272,9 +405,9 @@ sccattach(parent, self, aux)
struct tty *tp;
void *sccaddr;
int cntr;
- struct termios cterm;
- struct tty ctty;
- int s;
+ struct termios cterm;
+ struct tty ctty;
+ int s;
extern int cputype;
/* Get the address, and check it for validity. */
@@ -285,7 +418,7 @@ sccattach(parent, self, aux)
/* Register the interrupt handler. */
ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY,
- sccintr, (void *)(long)sc->sc_dv.dv_unit);
+ sccintr, (void *)sc);
/*
* For a remote console, wait a while for previous output to
@@ -305,68 +438,73 @@ sccattach(parent, self, aux)
/* init pseudo DMA structures */
for (cntr = 0; cntr < 2; cntr++) {
pdp->p_addr = (void *)sccaddr;
- tp = scc_tty[sc->sc_dv.dv_unit * 2 + cntr] = ttymalloc();
+ tp = sc->scc_tty[cntr] = ttymalloc();
if (cntr == 0)
tty_attach(tp);
pdp->p_arg = (long)tp;
- pdp->p_fcn = (void (*)())0;
+ pdp->p_fcn = (void (*)__P((struct tty*)))0;
tp->t_dev = (dev_t)((sc->sc_dv.dv_unit << 1) | cntr);
pdp++;
}
+ /* What's the warning here? Defaulting to softCAR on line 2? */
sc->scc_softCAR = 0x2; /* XXX */
- /* reset chip */
+ /* reset chip, initialize register-copies in softc */
sccreset(sc);
- /*
- * Special handling for consoles.
- */
- if (0 /* cn_tab.cn_screen */) {
- if (1 /* cn_tab.cn_kbdgetc == sccGetc */) {
- if (sc->sc_dv.dv_unit == 1) {
- s = spltty();
- ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);
- cterm.c_cflag = CS8;
- cterm.c_ospeed = cterm.c_ispeed = 4800;
- (void) sccparam(&ctty, &cterm);
- DELAY(10000);
+ /*
+ * Special handling for consoles.
+ */
+ if (0 /* cn_tab.cn_screen */) {
+ if (1 /* cn_tab.cn_kbdgetc == sccGetc */) {
+ if (sc->sc_dv.dv_unit == 1) {
+ s = spltty();
+ ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);
+ cterm.c_cflag = CS8;
+#ifdef pmax
+ /* XXX -- why on pmax, not on Alpha? */
+ cterm.c_cflag |= CLOCAL;
+#endif /* pmax */
+ cterm.c_ospeed = cterm.c_ispeed = 4800;
+ (void) sccparam(&ctty, &cterm);
+ DELAY(10000);
#ifdef notyet
- /*
- * For some reason doing this hangs the 3min
- * during booting. Fortunately the keyboard
- * works ok without it.
- */
- KBDReset(ctty.t_dev, sccPutc);
+ /*
+ * For some reason doing this hangs the 3min
+ * during booting. Fortunately the keyboard
+ * works ok without it.
+ */
+ KBDReset(ctty.t_dev, sccPutc);
#endif
- DELAY(10000);
- splx(s);
- } else if (sc->sc_dv.dv_unit == 0) {
- s = spltty();
- ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);
- cterm.c_cflag = CS8 | PARENB | PARODD;
- cterm.c_ospeed = cterm.c_ispeed = 4800;
- (void) sccparam(&ctty, &cterm);
+ DELAY(10000);
+ splx(s);
+ } else if (sc->sc_dv.dv_unit == 0) {
+ s = spltty();
+ ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);
+ cterm.c_cflag = CS8 | PARENB | PARODD;
+ cterm.c_ospeed = cterm.c_ispeed = 4800;
+ (void) sccparam(&ctty, &cterm);
#ifdef TK_NOTYET
- DELAY(10000);
- MouseInit(ctty.t_dev, sccPutc, sccGetc);
- DELAY(10000);
+ DELAY(10000);
+ MouseInit(ctty.t_dev, sccPutc, sccGetc);
+ DELAY(10000);
#endif
- splx(s);
- }
- }
- } else if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) {
- s = spltty();
- ctty.t_dev = makedev(SCCDEV,
- sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT);
- cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8;
- cterm.c_ospeed = cterm.c_ispeed = 9600;
- (void) sccparam(&ctty, &cterm);
- DELAY(1000);
+ splx(s);
+ }
+ }
+ } else if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) {
+ s = spltty();
+ ctty.t_dev = makedev(SCCDEV,
+ sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT);
+ cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8;
+ cterm.c_ospeed = cterm.c_ispeed = 9600;
+ (void) sccparam(&ctty, &cterm);
+ DELAY(1000);
#ifdef TK_NOTYET
- cn_tab.cn_disabled = 0;
+ cn_tab.cn_disabled = 0;
#endif
- splx(s);
- }
+ splx(s);
+ }
/*
* XXX
@@ -374,9 +512,6 @@ sccattach(parent, self, aux)
*/
if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) ||
(cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) {
- static struct consdev scccons = {
- NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0
- };
cn_tab = &scccons;
cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2);
@@ -475,9 +610,9 @@ sccopen(dev, flag, mode, p)
line = SCCLINE(dev);
if (sc->scc_pdma[line].p_addr == NULL)
return (ENXIO);
- tp = scc_tty[minor(dev)];
+ tp = sc->scc_tty[line];
if (tp == NULL) {
- tp = scc_tty[minor(dev)] = ttymalloc();
+ tp = sc->scc_tty[line] = ttymalloc();
tty_attach(tp);
}
tp->t_oproc = sccstart;
@@ -506,7 +641,7 @@ sccopen(dev, flag, mode, p)
(void) sccmctl(dev, DML_DTR, DMSET);
s = spltty();
while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
- !(tp->t_state & TS_CARR_ON)) {
+ !(tp->t_state & TS_CARR_ON)) {
tp->t_state |= TS_WOPEN;
if ((error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
ttopen, 0)) != 0)
@@ -529,8 +664,8 @@ sccclose(dev, flag, mode, p)
register struct tty *tp;
register int line;
- tp = scc_tty[minor(dev)];
line = SCCLINE(dev);
+ tp = sc->scc_tty[line];
if (sc->scc_wreg[line].wr5 & ZSWR5_BREAK) {
sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK;
ttyoutput(0, tp);
@@ -548,9 +683,11 @@ sccread(dev, uio, flag)
struct uio *uio;
int flag;
{
+ register struct scc_softc *sc;
register struct tty *tp;
- tp = scc_tty[minor(dev)];
+ sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/
+ tp = sc->scc_tty[SCCLINE(dev)];
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -560,9 +697,11 @@ sccwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
+ register struct scc_softc *sc;
register struct tty *tp;
- tp = scc_tty[minor(dev)];
+ sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/
+ tp = sc->scc_tty[SCCLINE(dev)];
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
@@ -570,9 +709,14 @@ struct tty *
scctty(dev)
dev_t dev;
{
- struct tty *tp = scc_tty[minor(dev)]; /* XXX */
+ register struct scc_softc *sc;
+ register struct tty *tp;
+ register int unit = SCCUNIT(dev);
- return (tp);
+ if ((unit >= scc_cd.cd_ndevs) || (sc = scc_cd.cd_devs[unit]) == 0)
+ return (0);
+ tp = sc->scc_tty[SCCLINE(dev)];
+ return (tp);
}
/*ARGSUSED*/
@@ -588,7 +732,9 @@ sccioctl(dev, cmd, data, flag, p)
register struct tty *tp;
int error, line;
- tp = scc_tty[minor(dev)];
+ line = SCCLINE(dev);
+ sc = scc_cd.cd_devs[SCCUNIT(dev)];
+ tp = sc->scc_tty[line];
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
@@ -596,8 +742,6 @@ sccioctl(dev, cmd, data, flag, p)
if (error >= 0)
return (error);
- line = SCCLINE(dev);
- sc = scc_cd.cd_devs[SCCUNIT(dev)];
switch (cmd) {
case TIOCSBRK:
@@ -640,32 +784,55 @@ sccioctl(dev, cmd, data, flag, p)
return (0);
}
+
+
+/*
+ * Set line parameters -- tty t_param entry point.
+ */
int
sccparam(tp, t)
register struct tty *tp;
register struct termios *t;
{
register struct scc_softc *sc;
+
+ /* Extract the softc and call cold_sccparam to do all the work. */
+ sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
+ return cold_sccparam(tp, t, sc);
+}
+
+
+/*
+ * Do what sccparam() (t_param entry point) does, but callable when cold.
+ */
+static int
+cold_sccparam(tp, t, sc)
+ register struct tty *tp;
+ register struct termios *t;
+ register struct scc_softc *sc;
+{
register scc_regmap_t *regs;
register int line;
register u_char value, wvalue;
register int cflag = t->c_cflag;
int ospeed;
- if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
- return (EINVAL);
+ /* Check arguments */
+ if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
+ return (EINVAL);
ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);
- if (ospeed < 0)
- return (EINVAL);
- /* and copy to tty */
- tp->t_ispeed = t->c_ispeed;
- tp->t_ospeed = t->c_ospeed;
- tp->t_cflag = cflag;
+ if (ospeed < 0)
+ return (EINVAL);
+ /* and copy to tty */
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = cflag;
/*
* Handle console specially.
*/
- if (0 /* cn_tab.cn_screen */) {
+#ifdef HAVE_RCONS
+ if (cn_tab->cn_getc == LKgetc) {
if (minor(tp->t_dev) == SCCKBD_PORT) {
cflag = CS8;
ospeed = ttspeedtab(4800, sccspeedtab);
@@ -673,7 +840,9 @@ sccparam(tp, t)
cflag = CS8 | PARENB | PARODD;
ospeed = ttspeedtab(4800, sccspeedtab);
}
- } else /* if (tp->t_dev == cn_tab.cn_dev) */ {
+ } else if (tp->t_dev == cn_tab->cn_dev)
+#endif /*HAVE_RCONS*/
+ {
cflag = CS8;
ospeed = ttspeedtab(9600, sccspeedtab);
}
@@ -682,10 +851,14 @@ sccparam(tp, t)
return (0);
}
- sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
line = SCCLINE(tp->t_dev);
regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
+ /*
+ * pmax driver used to reset the SCC here. That reset causes the
+ * other channel on the SCC to drop outpur chars: at least that's
+ * what CGD reports for the Alpha. It's a bug.
+ */
#if 0
/* reset line */
if (line == SCC_CHANNEL_A)
@@ -715,7 +888,7 @@ sccparam(tp, t)
SCC_WRITE_REG(regs, line, ZSWR_IVEC, 0xf0);
/* clear break, keep rts dtr */
- wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR | ZSWR5_RTS);
+ wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR|ZSWR5_RTS);
switch (cflag & CSIZE) {
case CS5:
value = ZSWR3_RX_5;
@@ -740,9 +913,14 @@ sccparam(tp, t)
sc->scc_wreg[line].wr5 = wvalue;
SCC_WRITE_REG(regs, line, SCC_WR5, wvalue);
+ /*
+ * XXX Does the SCC chip require us to refresh the WR5 register
+ * for the other channel after writing the other, or not?
+ */
#ifdef notdef
/* XXX */
- {int otherline = (line + 1) & 1;
+ {
+ int otherline = (line + 1) & 1;
SCC_WRITE_REG(regs, otherline, SCC_WR5, sc->scc_wreg[otherline].wr5);
}
#endif
@@ -757,11 +935,15 @@ sccparam(tp, t)
SCC_SET_TIMING_BASE(regs, line, ospeed);
value = sc->scc_wreg[line].wr14;
SCC_WRITE_REG(regs, line, SCC_WR14, value);
- if (SCCUNIT(tp->t_dev) != 1) {
- value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE;
- } else {
+
+#ifdef alpha
+ if (SCCUNIT(tp->t_dev) == 1) {
/* On unit one, on the flamingo, modem control is floating! */
value = ZSWR15_BREAK_IE;
+ } else
+#endif
+ {
+ value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE;
}
SCC_WRITE_REG(regs, line, SCC_WR15, value);
@@ -776,28 +958,32 @@ sccparam(tp, t)
value = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
SCC_WRITE_REG(regs, line, SCC_WR9, value);
SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1);
+ tc_mb();
+#ifdef alpha
scc_alphaintr(1); /* XXX XXX XXX */
+#endif /*alpha*/
return (0);
}
+
/*
* Check for interrupts from all devices.
*/
int
-sccintr(xxxunit)
- void *xxxunit;
+sccintr(xxxsc)
+ void *xxxsc;
{
- register int unit = (long)xxxunit;
+ register struct scc_softc *sc = (struct scc_softc *)xxxsc;
+ register int unit = (long)sc->sc_dv.dv_unit;
register scc_regmap_t *regs;
register struct tty *tp;
register struct pdma *dp;
- register struct scc_softc *sc;
register int cc, chan, rr1, rr2, rr3;
int overrun = 0;
- sc = scc_cd.cd_devs[unit];
+ rr1 = 0; /* shut up gcc -Wall */
regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
unit <<= 1;
for (;;) {
@@ -807,18 +993,21 @@ sccintr(xxxunit)
if (rr2 == 6) { /* strange, distinguished value */
SCC_READ_REG(regs, SCC_CHANNEL_A, ZSRR_IPEND, rr3);
if (rr3 == 0)
- return;
+ return 0; /* XXX */
}
SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, ZSWR0_CLR_INTR);
if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
SCC_CHANNEL_A : SCC_CHANNEL_B;
- tp = scc_tty[unit | chan];
+ tp = sc->scc_tty[chan];
dp = &sc->scc_pdma[chan];
if (dp->p_mem < dp->p_end) {
SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
- wbflush();
+#ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */
+ DELAY(2);
+#endif
+ tc_mb();
} else {
tp->t_state &= ~TS_BUSY;
if (tp->t_state & TS_FLUSH)
@@ -839,7 +1028,7 @@ sccintr(xxxunit)
cc = sc->scc_wreg[chan].wr1 & ~ZSWR1_TIE;
SCC_WRITE_REG(regs, chan, SCC_WR1, cc);
sc->scc_wreg[chan].wr1 = cc;
- wbflush();
+ tc_mb();
}
}
} else if (rr2 == SCC_RR2_A_RECV_DONE ||
@@ -849,7 +1038,7 @@ sccintr(xxxunit)
chan = SCC_CHANNEL_A;
else
chan = SCC_CHANNEL_B;
- tp = scc_tty[unit | chan];
+ tp = sc->scc_tty[chan];
SCC_READ_DATA(regs, chan, cc);
if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
rr2 == SCC_RR2_B_RECV_SPECIAL) {
@@ -865,12 +1054,12 @@ sccintr(xxxunit)
/*
* Keyboard needs special treatment.
*/
- if (tp == scc_tty[SCCKBD_PORT] /* && cn_tab.cn_screen */) {
+ if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) /* && cn_tab.cn_screen */) {
#ifdef KADB
if (cc == LK_DO) {
spl0();
kdbpanic();
- return;
+ return 0; /* XXX */
}
#endif
#ifdef DEBUG
@@ -887,40 +1076,11 @@ sccintr(xxxunit)
/*
* Now for mousey
*/
- } else if (tp == scc_tty[SCCMOUSE_PORT] && sccMouseButtons) {
-#if 0
- register MouseReport *mrp;
- static MouseReport currentRep;
-
- mrp = &currentRep;
- mrp->byteCount++;
- if (cc & MOUSE_START_FRAME) {
- /*
- * The first mouse report byte (button state).
- */
- mrp->state = cc;
- if (mrp->byteCount > 1)
- mrp->byteCount = 1;
- } else if (mrp->byteCount == 2) {
- /*
- * The second mouse report byte (delta x).
- */
- mrp->dx = cc;
- } else if (mrp->byteCount == 3) {
- /*
- * The final mouse report byte (delta y).
- */
- mrp->dy = cc;
- mrp->byteCount = 0;
- if (mrp->dx != 0 || mrp->dy != 0) {
- /*
- * If the mouse moved,
- * post a motion event.
- */
- (*sccMouseEvent)(mrp);
- }
- (*sccMouseButtons)(mrp);
- }
+ } else if (tp == scctty(makedev(SCCDEV, SCCMOUSE_PORT)) &&
+ sccMouseButtons) {
+#ifdef HAVE_RCONS
+ /*XXX*/
+ mouseInput(cc);
#endif
continue;
}
@@ -941,11 +1101,12 @@ sccintr(xxxunit)
(*linesw[tp->t_line].l_rint)(cc, tp);
} else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
- SCC_CHANNEL_A : SCC_CHANNEL_B;
+ SCC_CHANNEL_A : SCC_CHANNEL_B;
SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_STATUS);
scc_modem_intr(unit | chan);
}
}
+ return 0; /* XXX */
}
void
@@ -975,7 +1136,7 @@ sccstart(tp)
if (tp->t_outq.c_cc == 0)
goto out;
/* handle console specially */
- if (tp == scc_tty[SCCKBD_PORT] /* && cn_tab.cn_screen */) {
+ if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) /* && cn_tab.cn_screen */) {
while (tp->t_outq.c_cc > 0) {
cc = getc(&tp->t_outq) & 0x7f;
cnputc(cc);
@@ -993,21 +1154,8 @@ sccstart(tp)
}
goto out;
}
-#if 0
- if (tp->t_flags & (RAW|LITOUT))
- cc = ndqb(&tp->t_outq, 0);
- else {
- cc = ndqb(&tp->t_outq, 0200);
- if (cc == 0) {
- cc = getc(&tp->t_outq);
- timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6);
- tp->t_state |= TS_TIMEOUT;
- goto out;
- }
- }
-#else
cc = ndqb(&tp->t_outq, 0);
-#endif
+
tp->t_state |= TS_BUSY;
dp->p_end = dp->p_mem = tp->t_outq.c_cf;
dp->p_end += cc;
@@ -1030,8 +1178,11 @@ sccstart(tp)
panic("sccstart: No chars");
#endif
SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
+#ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */
+ DELAY(2);
+#endif
}
- wbflush();
+ tc_mb();
out:
splx(s);
}
@@ -1040,7 +1191,7 @@ out:
* Stop output on a line.
*/
/*ARGSUSED*/
-int
+void
sccstop(tp, flag)
register struct tty *tp;
int flag;
@@ -1058,8 +1209,6 @@ sccstop(tp, flag)
tp->t_state |= TS_FLUSH;
}
splx(s);
-
- return 0; /* XXX should be void */
}
int
@@ -1118,7 +1267,7 @@ sccmctl(dev, bits, how)
sc->scc_wreg[SCC_CHANNEL_A].wr5);
}
if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line)))
- scc_tty[minor(dev)]->t_state |= TS_CARR_ON;
+ sc->scc_tty[line]->t_state |= TS_CARR_ON;
(void) splx(s);
return (mbits);
}
@@ -1137,9 +1286,9 @@ scc_modem_intr(dev)
register u_char value;
int s;
- sc = scc_cd.cd_devs[SCCUNIT(dev)];
- tp = scc_tty[minor(dev)];
chan = SCCLINE(dev);
+ sc = scc_cd.cd_devs[SCCUNIT(dev)];
+ tp = sc->scc_tty[chan];
regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr;
if (chan == SCC_CHANNEL_A)
return;
@@ -1150,6 +1299,13 @@ scc_modem_intr(dev)
SCC_READ_REG_ZERO(regs, chan, value);
car = value & ZSRR0_DCD;
}
+
+ /*
+ * The pmax driver follows carrier-detect. The Alpha does not.
+ * XXX Why doesn't the Alpha driver follow carrier-detect?
+ * (in the Alpha driver, this is an "#ifdef notdef").
+ * Is it related to console handling?
+ */
#ifdef notdef
if (car) {
/* carrier present */
@@ -1171,15 +1327,25 @@ sccGetc(dev)
register scc_regmap_t *regs;
register int c, line;
register u_char value;
- struct scc_softc *sc;
int s;
line = SCCLINE(dev);
- sc = scc_cd.cd_devs[SCCUNIT(dev)];
- regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
+ if (cold && scc_cons_addr) {
+ regs = scc_cons_addr;
+ } else {
+ register struct scc_softc *sc;
+ sc = scc_cd.cd_devs[SCCUNIT(dev)];
+ regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
+ }
+
if (!regs)
return (0);
+#ifdef pmax
+ /*s = spltty(); */ /* XXX why different spls? */
+ s = splhigh();
+#else
s = splhigh();
+#endif
for (;;) {
SCC_READ_REG(regs, line, SCC_RR0, value);
if (value & ZSRR0_RX_READY) {
@@ -1212,13 +1378,21 @@ sccPutc(dev, c)
register scc_regmap_t *regs;
register int line;
register u_char value;
- struct scc_softc *sc;
int s;
+#ifdef pmax
+ s = spltty(); /* XXX why different spls? */
+#else
s = splhigh();
+#endif
line = SCCLINE(dev);
- sc = scc_cd.cd_devs[SCCUNIT(dev)];
- regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
+ if (cold && scc_cons_addr) {
+ regs = scc_cons_addr;
+ } else {
+ register struct scc_softc *sc;
+ sc = scc_cd.cd_devs[SCCUNIT(dev)];
+ regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
+ }
/*
* Wait for transmitter to be not busy.
@@ -1234,7 +1408,7 @@ sccPutc(dev, c)
* Send the char.
*/
SCC_WRITE_DATA(regs, line, c);
- wbflush();
+ tc_mb();
splx(s);
return;
@@ -1285,5 +1459,5 @@ rr(msg, regs)
printf("B: 0: %x 1: %x 2(state): %x 10: %x 15: %x\n",
r0, r1, r2, r10, r15);
}
-#endif
+#endif /* SCC_DEBUG */
#endif /* NSCC */
diff --git a/sys/arch/alpha/tc/sccreg.h b/sys/arch/alpha/tc/sccreg.h
index 2207605a58a..f51a1083921 100644
--- a/sys/arch/alpha/tc/sccreg.h
+++ b/sys/arch/alpha/tc/sccreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sccreg.h,v 1.2 1996/07/29 23:02:13 niklas Exp $ */
+/* $OpenBSD: sccreg.h,v 1.3 1996/10/30 22:41:12 niklas Exp $ */
/* $NetBSD: sccreg.h,v 1.2 1995/04/11 03:41:10 mycroft Exp $ */
/*
diff --git a/sys/arch/alpha/tc/sccvar.h b/sys/arch/alpha/tc/sccvar.h
index 5ffdb5baa11..c0c8285fb35 100644
--- a/sys/arch/alpha/tc/sccvar.h
+++ b/sys/arch/alpha/tc/sccvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sccvar.h,v 1.2 1996/07/29 23:02:15 niklas Exp $ */
-/* $NetBSD: sccvar.h,v 1.2 1995/08/03 00:52:23 cgd Exp $ */
+/* $OpenBSD: sccvar.h,v 1.3 1996/10/30 22:41:13 niklas Exp $ */
+/* $NetBSD: sccvar.h,v 1.3 1996/07/09 00:55:21 cgd Exp $ */
/*
* Copyright (c) 1991,1990,1989,1994,1995 Carnegie Mellon University
@@ -98,7 +98,7 @@ typedef struct {
#define scc_get_datum(d, v) \
do { (v) = ((d) >> 8) & 0xff; } while (0)
#define scc_set_datum(d, v) \
- do { (d) = (volatile unsigned int)(v) << 8; wbflush(); } while (0)
+ do { (d) = (volatile unsigned int)(v) << 8; alpha_mb(); } while (0)
/*
* Minor device numbers for scc. Weird because B channel comes first and
diff --git a/sys/arch/alpha/tc/sfb.c b/sys/arch/alpha/tc/sfb.c
index d593bc89fa1..1d6abccf59b 100644
--- a/sys/arch/alpha/tc/sfb.c
+++ b/sys/arch/alpha/tc/sfb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sfb.c,v 1.2 1996/07/29 23:02:16 niklas Exp $ */
-/* $NetBSD: sfb.c,v 1.1 1996/05/01 21:15:50 cgd Exp $ */
+/* $OpenBSD: sfb.c,v 1.3 1996/10/30 22:41:14 niklas Exp $ */
+/* $NetBSD: sfb.c,v 1.5 1996/10/13 03:00:35 christos Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -57,7 +57,7 @@
int sfbmatch __P((struct device *, void *, void *));
void sfbattach __P((struct device *, struct device *, void *));
-int sfbprint __P((void *, char *));
+int sfbprint __P((void *, /* const */ char *));
struct cfattach sfb_ca = {
sizeof(struct sfb_softc), sfbmatch, sfbattach,
@@ -92,7 +92,6 @@ sfbmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct cfdata *cf = match;
struct tc_attach_args *ta = aux;
if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
@@ -112,7 +111,7 @@ sfb_getdevconfig(dense_addr, dc)
int i;
dc->dc_vaddr = dense_addr;
- dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */
+ dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr); /* XXX */
dc->dc_size = SFB_SIZE;
regp = (char *)dc->dc_vaddr + SFB_ASIC_OFFSET;
@@ -209,7 +208,6 @@ sfbattach(parent, self, aux)
struct wscons_attach_args waa;
struct wscons_odev_spec *wo;
int console;
- char *x;
console = 0; /* XXX */
if (console)
@@ -253,7 +251,7 @@ sfbattach(parent, self, aux)
int
sfbprint(aux, pnp)
void *aux;
- char *pnp;
+ /* const */ char *pnp;
{
if (pnp)
diff --git a/sys/arch/alpha/tc/sfbvar.h b/sys/arch/alpha/tc/sfbvar.h
index a1fa2952d72..c1e46e511a2 100644
--- a/sys/arch/alpha/tc/sfbvar.h
+++ b/sys/arch/alpha/tc/sfbvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sfbvar.h,v 1.2 1996/07/29 23:02:18 niklas Exp $ */
+/* $OpenBSD: sfbvar.h,v 1.3 1996/10/30 22:41:15 niklas Exp $ */
/* $NetBSD: sfbvar.h,v 1.1 1996/05/01 21:15:51 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/tc_3000_300.c b/sys/arch/alpha/tc/tc_3000_300.c
index dc7c0b41fb9..890bfa6fc7f 100644
--- a/sys/arch/alpha/tc/tc_3000_300.c
+++ b/sys/arch/alpha/tc/tc_3000_300.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_3000_300.c,v 1.4 1996/07/29 23:02:19 niklas Exp $ */
-/* $NetBSD: tc_3000_300.c,v 1.7.4.1 1996/06/05 00:39:06 cgd Exp $ */
+/* $OpenBSD: tc_3000_300.c,v 1.5 1996/10/30 22:41:16 niklas Exp $ */
+/* $NetBSD: tc_3000_300.c,v 1.12 1996/10/13 03:00:37 christos Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,6 +29,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
@@ -46,12 +47,12 @@ void tc_3000_300_intr_setup __P((void));
void tc_3000_300_intr_establish __P((struct device *, void *,
tc_intrlevel_t, int (*)(void *), void *));
void tc_3000_300_intr_disestablish __P((struct device *, void *));
-void tc_3000_300_iointr __P((void *, int));
+void tc_3000_300_iointr __P((void *, unsigned long));
int tc_3000_300_intrnull __P((void *));
#define C(x) ((void *)(u_long)x)
-#define KV(x) (phystok0seg(x))
+#define KV(x) (ALPHA_PHYS_TO_K0SEG(x))
/*
* We have to read and modify the IOASIC registers directly, because
@@ -184,18 +185,19 @@ tc_3000_300_intrnull(val)
void
tc_3000_300_iointr(framep, vec)
void *framep;
- int vec;
+ unsigned long vec;
{
u_int32_t tcir, ioasicir, ioasicimr;
- int opt0intr, opt1intr, ifound;
+ int ifound;
#ifdef DIAGNOSTIC
int s;
if (vec != 0x800)
- panic("INVALID ASSUMPTION: vec %x, not 0x800", vec);
+ panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec);
s = splhigh();
- if (s != PSL_IPL_IO)
- panic("INVALID ASSUMPTION: IPL %d, not %d", s, PSL_IPL_IO);
+ if (s != ALPHA_PSL_IPL_IO)
+ panic("INVALID ASSUMPTION: IPL %d, not %d", s,
+ ALPHA_PSL_IPL_IO);
splx(s);
#endif
diff --git a/sys/arch/alpha/tc/tc_3000_300.h b/sys/arch/alpha/tc/tc_3000_300.h
index 8ef82e58802..475eefad00b 100644
--- a/sys/arch/alpha/tc/tc_3000_300.h
+++ b/sys/arch/alpha/tc/tc_3000_300.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tc_3000_300.h,v 1.3 1996/07/29 23:02:21 niklas Exp $ */
+/* $OpenBSD: tc_3000_300.h,v 1.4 1996/10/30 22:41:17 niklas Exp $ */
/* $NetBSD: tc_3000_300.h,v 1.2 1995/12/20 00:43:28 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/tc_3000_500.c b/sys/arch/alpha/tc/tc_3000_500.c
index ccda3b062bd..9e8133619b2 100644
--- a/sys/arch/alpha/tc/tc_3000_500.c
+++ b/sys/arch/alpha/tc/tc_3000_500.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_3000_500.c,v 1.4 1996/07/29 23:02:23 niklas Exp $ */
-/* $NetBSD: tc_3000_500.c,v 1.4.4.3 1996/06/13 18:35:35 cgd Exp $ */
+/* $OpenBSD: tc_3000_500.c,v 1.5 1996/10/30 22:41:18 niklas Exp $ */
+/* $NetBSD: tc_3000_500.c,v 1.11 1996/10/13 03:00:38 christos Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,6 +29,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
@@ -45,12 +46,12 @@ void tc_3000_500_intr_setup __P((void));
void tc_3000_500_intr_establish __P((struct device *, void *,
tc_intrlevel_t, int (*)(void *), void *));
void tc_3000_500_intr_disestablish __P((struct device *, void *));
-void tc_3000_500_iointr __P((void *, int));
+void tc_3000_500_iointr __P((void *, unsigned long));
int tc_3000_500_intrnull __P((void *));
#define C(x) ((void *)(u_long)x)
-#define KV(x) (phystok0seg(x))
+#define KV(x) (ALPHA_PHYS_TO_K0SEG(x))
struct tc_slotdesc tc_3000_500_slots[] = {
{ KV(0x100000000), C(TC_3000_500_DEV_OPT0), }, /* 0 - opt slot 0 */
@@ -175,7 +176,7 @@ tc_3000_500_intrnull(val)
void
tc_3000_500_iointr(framep, vec)
void *framep;
- int vec;
+ unsigned long vec;
{
u_int32_t ir;
int ifound;
@@ -183,10 +184,11 @@ tc_3000_500_iointr(framep, vec)
#ifdef DIAGNOSTIC
int s;
if (vec != 0x800)
- panic("INVALID ASSUMPTION: vec %x, not 0x800", vec);
+ panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec);
s = splhigh();
- if (s != PSL_IPL_IO)
- panic("INVALID ASSUMPTION: IPL %d, not %d", s, PSL_IPL_IO);
+ if (s != ALPHA_PSL_IPL_IO)
+ panic("INVALID ASSUMPTION: IPL %d, not %d", s,
+ ALPHA_PSL_IPL_IO);
splx(s);
#endif
@@ -248,6 +250,7 @@ tc_3000_500_iointr(framep, vec)
} while (ifound);
}
+#if 0
/*
* tc_3000_500_ioslot --
* Set the PBS bits for devices on the TC.
@@ -273,3 +276,4 @@ tc_3000_500_ioslot(slot, flags, set)
tc_mb();
splx(s);
}
+#endif
diff --git a/sys/arch/alpha/tc/tc_3000_500.h b/sys/arch/alpha/tc/tc_3000_500.h
index ea5a236e165..b9249b9a857 100644
--- a/sys/arch/alpha/tc/tc_3000_500.h
+++ b/sys/arch/alpha/tc/tc_3000_500.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tc_3000_500.h,v 1.3 1996/07/29 23:02:24 niklas Exp $ */
+/* $OpenBSD: tc_3000_500.h,v 1.4 1996/10/30 22:41:19 niklas Exp $ */
/* $NetBSD: tc_3000_500.h,v 1.2 1995/12/20 00:43:31 cgd Exp $ */
/*
diff --git a/sys/arch/alpha/tc/tc_bus_io.c b/sys/arch/alpha/tc/tc_bus_io.c
index e553611c1b4..731d237b820 100644
--- a/sys/arch/alpha/tc/tc_bus_io.c
+++ b/sys/arch/alpha/tc/tc_bus_io.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_bus_io.c,v 1.2 1996/07/29 23:02:26 niklas Exp $ */
-/* $NetBSD: tc_bus_io.c,v 1.1.4.1 1996/06/13 17:41:51 cgd Exp $ */
+/* $OpenBSD: tc_bus_io.c,v 1.3 1996/10/30 22:41:20 niklas Exp $ */
+/* $NetBSD: tc_bus_io.c,v 1.3 1996/07/09 00:55:31 cgd Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@@ -34,12 +34,14 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <vm/vm.h>
#include <machine/bus.h>
+#include <dev/tc/tcvar.h>
int tc_io_map __P((void *, bus_io_addr_t, bus_io_size_t,
bus_io_handle_t *));
diff --git a/sys/arch/alpha/tc/tc_bus_mem.c b/sys/arch/alpha/tc/tc_bus_mem.c
index b82678694fc..558dd764c0f 100644
--- a/sys/arch/alpha/tc/tc_bus_mem.c
+++ b/sys/arch/alpha/tc/tc_bus_mem.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_bus_mem.c,v 1.2 1996/07/29 23:02:27 niklas Exp $ */
-/* $NetBSD: tc_bus_mem.c,v 1.2.4.2 1996/06/13 17:42:51 cgd Exp $ */
+/* $OpenBSD: tc_bus_mem.c,v 1.3 1996/10/30 22:41:21 niklas Exp $ */
+/* $NetBSD: tc_bus_mem.c,v 1.7 1996/07/09 00:55:33 cgd Exp $ */
/*
* Copyright (c) 1996 Carnegie-Mellon University.
@@ -33,6 +33,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#include <sys/device.h>
@@ -105,9 +106,9 @@ tc_mem_map(v, memaddr, memsize, cacheable, memhp)
if (memaddr & 0x7)
panic("tc_mem_map needs 8 byte alignment");
if (cacheable)
- *memhp = phystok0seg(memaddr);
+ *memhp = ALPHA_PHYS_TO_K0SEG(memaddr);
else
- *memhp = phystok0seg(TC_DENSE_TO_SPARSE(memaddr));
+ *memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr));
return (0);
}
@@ -148,7 +149,7 @@ tc_mem_read_1(v, memh, off)
{
volatile u_int8_t *p;
- wbflush();
+ alpha_mb();
if ((memh & TC_SPACE_SPARSE) != 0)
panic("tc_mem_read_1 not implemented for sparse space");
@@ -165,7 +166,7 @@ tc_mem_read_2(v, memh, off)
{
volatile u_int16_t *p;
- wbflush();
+ alpha_mb();
if ((memh & TC_SPACE_SPARSE) != 0)
panic("tc_mem_read_2 not implemented for sparse space");
@@ -182,7 +183,7 @@ tc_mem_read_4(v, memh, off)
{
volatile u_int32_t *p;
- wbflush();
+ alpha_mb();
if ((memh & TC_SPACE_SPARSE) != 0)
/* Nothing special to do for 4-byte sparse space accesses */
@@ -200,7 +201,7 @@ tc_mem_read_8(v, memh, off)
{
volatile u_int64_t *p;
- wbflush();
+ alpha_mb();
if ((memh & TC_SPACE_SPARSE) != 0)
panic("tc_mem_read_8 not implemented for sparse space");
@@ -236,7 +237,7 @@ tc_mem_write_1(v, memh, off, val)
p = (u_int8_t *)(memh + off);
*p = val;
}
- wbflush();
+ alpha_mb();
}
void
@@ -266,7 +267,7 @@ tc_mem_write_2(v, memh, off, val)
p = (u_int16_t *)(memh + off);
*p = val;
}
- wbflush();
+ alpha_mb();
}
void
@@ -284,7 +285,7 @@ tc_mem_write_4(v, memh, off, val)
else
p = (u_int32_t *)(memh + off);
*p = val;
- wbflush();
+ alpha_mb();
}
void
@@ -301,7 +302,7 @@ tc_mem_write_8(v, memh, off, val)
p = (u_int64_t *)(memh + off);
*p = val;
- wbflush();
+ alpha_mb();
}
/* XXX DOES NOT BELONG */
@@ -310,5 +311,5 @@ tc_XXX_dmamap(addr)
void *addr;
{
- return (vtophys(addr));
+ return (vtophys((vm_offset_t)addr));
}
diff --git a/sys/arch/alpha/tc/tc_conf.h b/sys/arch/alpha/tc/tc_conf.h
index 948014a6e3f..479cea7eb6b 100644
--- a/sys/arch/alpha/tc/tc_conf.h
+++ b/sys/arch/alpha/tc/tc_conf.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_conf.h,v 1.2 1996/07/29 23:02:29 niklas Exp $ */
-/* $NetBSD: tc_conf.h,v 1.1 1995/12/20 00:43:32 cgd Exp $ */
+/* $OpenBSD: tc_conf.h,v 1.3 1996/10/30 22:41:22 niklas Exp $ */
+/* $NetBSD: tc_conf.h,v 1.2 1996/07/14 04:06:30 cgd Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
@@ -34,7 +34,7 @@
#ifdef DEC_3000_500
extern void tc_3000_500_intr_setup __P((void));
-extern void tc_3000_500_iointr __P((void *, int));
+extern void tc_3000_500_iointr __P((void *, unsigned long));
extern void tc_3000_500_intr_establish __P((struct device *, void *,
tc_intrlevel_t, int (*)(void *), void *));
@@ -48,7 +48,7 @@ extern struct tc_builtin tc_3000_500_builtins[];
#ifdef DEC_3000_300
extern void tc_3000_300_intr_setup __P((void));
-extern void tc_3000_300_iointr __P((void *, int));
+extern void tc_3000_300_iointr __P((void *, unsigned long));
extern void tc_3000_300_intr_establish __P((struct device *, void *,
tc_intrlevel_t, int (*)(void *), void *));
diff --git a/sys/arch/alpha/tc/tc_machdep.h b/sys/arch/alpha/tc/tc_machdep.h
index f5a55ec646b..842c8bc023a 100644
--- a/sys/arch/alpha/tc/tc_machdep.h
+++ b/sys/arch/alpha/tc/tc_machdep.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tc_machdep.h,v 1.2 1996/07/29 23:02:31 niklas Exp $ */
-/* $NetBSD: tc_machdep.h,v 1.1 1995/12/20 00:09:29 cgd Exp $ */
+/* $OpenBSD: tc_machdep.h,v 1.3 1996/10/30 22:41:23 niklas Exp $ */
+/* $NetBSD: tc_machdep.h,v 1.2 1996/07/09 00:55:35 cgd Exp $ */
/*
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -61,8 +61,8 @@
typedef u_int64_t tc_addr_t;
typedef int32_t tc_offset_t;
-#define tc_mb() wbflush()
-#define tc_wmb() wbflush()
+#define tc_mb() alpha_mb()
+#define tc_wmb() alpha_wmb()
/*
* A junk address to read from, to make sure writes are complete. See
@@ -73,7 +73,7 @@ typedef int32_t tc_offset_t;
do { \
volatile u_int32_t no_optimize; \
no_optimize = \
- *(volatile u_int32_t *)phystok0seg(0x00000001f0080220); \
+ *(volatile u_int32_t *)ALPHA_PHYS_TO_K0SEG(0x00000001f0080220); \
} while (0)
#define tc_badaddr(tcaddr) \
@@ -91,3 +91,6 @@ typedef int32_t tc_offset_t;
#define TC_PHYS_TO_UNCACHED(addr) \
(addr)
+
+void tc_bus_io_init __P((bus_chipset_tag_t bc, void *iov));;
+void tc_bus_mem_init __P((bus_chipset_tag_t bc, void *memv));;
diff --git a/sys/arch/alpha/tc/tcasic.c b/sys/arch/alpha/tc/tcasic.c
index c1f2223032f..6ea1615408c 100644
--- a/sys/arch/alpha/tc/tcasic.c
+++ b/sys/arch/alpha/tc/tcasic.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcasic.c,v 1.3 1996/07/29 23:02:32 niklas Exp $ */
-/* $NetBSD: tcasic.c,v 1.5 1996/05/17 23:58:43 cgd Exp $ */
+/* $OpenBSD: tcasic.c,v 1.4 1996/10/30 22:41:24 niklas Exp $ */
+/* $NetBSD: tcasic.c,v 1.10 1996/10/13 03:00:39 christos Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,6 +29,7 @@
*/
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
@@ -49,7 +50,7 @@ struct cfdriver tcasic_cd = {
NULL, "tcasic", DV_DULL,
};
-int tcasicprint __P((void *, char *));
+int tcasicprint __P((void *, /* const */ char *));
extern int cputype;
@@ -86,7 +87,7 @@ tcasicattach(parent, self, aux)
{
struct tcbus_attach_args tba;
void (*intr_setup) __P((void));
- void (*iointr) __P((void *, int));
+ void (*iointr) __P((void *, unsigned long));
struct alpha_bus_chipset bc;
printf("\n");
@@ -144,7 +145,7 @@ tcasicattach(parent, self, aux)
int
tcasicprint(aux, pnp)
void *aux;
- char *pnp;
+ /* const */ char *pnp;
{
/* only TCs can attach to tcasics; easy. */
diff --git a/sys/arch/alpha/tc/tcds.c b/sys/arch/alpha/tc/tcds.c
index dd8da7b9903..a3cb6ae6b1b 100644
--- a/sys/arch/alpha/tc/tcds.c
+++ b/sys/arch/alpha/tc/tcds.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcds.c,v 1.4 1996/07/29 23:02:34 niklas Exp $ */
-/* $NetBSD: tcds.c,v 1.9.4.2 1996/06/05 01:32:26 cgd Exp $ */
+/* $OpenBSD: tcds.c,v 1.5 1996/10/30 22:41:27 niklas Exp $ */
+/* $NetBSD: tcds.c,v 1.15 1996/10/13 03:00:41 christos Exp $ */
/*
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -58,7 +58,7 @@ struct tcds_softc {
/* Definition of the driver for autoconfig. */
int tcdsmatch __P((struct device *, void *, void *));
void tcdsattach __P((struct device *, struct device *, void *));
-int tcdsprint(void *, char *);
+int tcdsprint __P((void *, /* const */ char *));
struct cfattach tcds_ca = {
sizeof(struct tcds_softc), tcdsmatch, tcdsattach,
@@ -120,7 +120,7 @@ tcdsattach(parent, self, aux)
* not useful) bits set in it when the system boots. Clear it.
*/
*sc->sc_imer = 0;
- wbflush();
+ alpha_mb();
/* XXX Initial contents of CIR? */
@@ -204,7 +204,7 @@ tcdsattach(parent, self, aux)
int
tcdsprint(aux, pnp)
void *aux;
- char *pnp;
+ /* const */ char *pnp;
{
struct tc_attach_args *ta = aux;
@@ -279,10 +279,10 @@ tcds_scsi_reset(sc)
tcds_scsi_enable(sc, 0);
TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_resetbits);
- wbflush();
+ alpha_mb();
DELAY(1);
TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_resetbits);
- wbflush();
+ alpha_mb();
tcds_scsi_enable(sc, 1);
tcds_dma_enable(sc, 1);
@@ -298,7 +298,7 @@ tcds_scsi_enable(sc, on)
*sc->sc_tcds->sc_imer |= sc->sc_intrmaskbits;
else
*sc->sc_tcds->sc_imer &= ~sc->sc_intrmaskbits;
- wbflush();
+ alpha_mb();
}
void
@@ -312,7 +312,7 @@ tcds_dma_enable(sc, on)
TCDS_CIR_SET(*sc->sc_tcds->sc_cir, sc->sc_dmabits);
else
TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_dmabits);
- wbflush();
+ alpha_mb();
}
int
@@ -324,7 +324,7 @@ tcds_scsi_isintr(sc, clear)
if ((*sc->sc_tcds->sc_cir & sc->sc_intrbits) != 0) {
if (clear) {
TCDS_CIR_CLR(*sc->sc_tcds->sc_cir, sc->sc_intrbits);
- wbflush();
+ alpha_mb();
}
return (1);
} else
@@ -353,11 +353,11 @@ tcds_intr(val)
* Copy and clear (gag!) the interrupts.
*/
ir = *sc->sc_cir;
- wbflush();
+ alpha_mb();
TCDS_CIR_CLR(*sc->sc_cir, TCDS_CIR_ALLINTR);
- wbflush();
+ alpha_mb();
tc_syncbus();
- wbflush();
+ alpha_mb();
#ifdef EVCNT_COUNTERS
/* No interrupt counting via evcnt counters */
@@ -411,4 +411,6 @@ tcds_intr(val)
* This is wrong, but machine keeps dying.
*/
DELAY(1);
+
+ return (1);
}
diff --git a/sys/arch/alpha/tc/tcds_dma.c b/sys/arch/alpha/tc/tcds_dma.c
index c62f8ea7926..b7173fdc931 100644
--- a/sys/arch/alpha/tc/tcds_dma.c
+++ b/sys/arch/alpha/tc/tcds_dma.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcds_dma.c,v 1.3 1996/07/29 23:02:36 niklas Exp $ */
-/* $NetBSD: tcds_dma.c,v 1.6 1995/12/20 00:40:32 cgd Exp $ */
+/* $OpenBSD: tcds_dma.c,v 1.4 1996/10/30 22:41:28 niklas Exp $ */
+/* $NetBSD: tcds_dma.c,v 1.13 1996/10/13 03:00:43 christos Exp $ */
/*
* Copyright (c) 1994 Peter Galbavy. All rights reserved.
@@ -61,15 +61,6 @@ tcds_dma_reset(sc)
sc->sc_active = 0; /* and of course we aren't */
}
-
-void
-tcds_dma_enintr(sc)
- struct tcds_slotconfig *sc;
-{
-
- /* XXX */
-}
-
int
tcds_dma_isintr(sc)
struct tcds_slotconfig *sc;
@@ -85,79 +76,6 @@ tcds_dma_isintr(sc)
return x;
}
-#define ESPMAX (64 * 1024)
-#define DMAMAX(a) (0x02000 - ((a) & 0x1fff))
-
-/*
- * start a dma transfer or keep it going
- */
-void
-tcds_dma_start(sc, addr, len, datain)
- struct tcds_slotconfig *sc;
- caddr_t *addr;
- size_t *len;
- int datain; /* DMA into main memory */
-{
- u_int32_t dic;
- size_t size;
-
- sc->sc_dmaaddr = addr;
- sc->sc_dmalen = len;
- sc->sc_iswrite = datain;
-
- ESP_DMA(("tcds_dma %d: start %d@0x%lx,%d\n", sc->sc_slot, *sc->sc_dmalen, *sc->sc_dmaaddr, sc->sc_iswrite));
-
- /*
- * the rules say we cannot transfer more than the limit
- * of this DMA chip (64k) and we cannot cross a 8k boundary.
- */
- size = min(*sc->sc_dmalen, ESPMAX);
- size = min(size, DMAMAX((size_t) *sc->sc_dmaaddr));
- sc->sc_dmasize = size;
-
- ESP_DMA(("dma_start: dmasize = %d\n", sc->sc_dmasize));
-
- /* Load address, set/clear unaligned transfer and read/write bits. */
- /* XXX PICK AN ADDRESS TYPE, AND STICK TO IT! */
- if ((u_long)*addr > VM_MIN_KERNEL_ADDRESS) {
- *sc->sc_sda = vatopa((u_long)*addr) >> 2;
- } else {
- *sc->sc_sda = k0segtophys((u_long)*addr) >> 2;
- }
- wbflush();
- dic = *sc->sc_dic;
- dic &= ~TCDS_DIC_ADDRMASK;
- dic |= (vm_offset_t)*addr & TCDS_DIC_ADDRMASK;
- if (datain)
- dic |= TCDS_DIC_WRITE;
- else
- dic &= ~TCDS_DIC_WRITE;
- *sc->sc_dic = dic;
- wbflush();
-
- /* Program the SCSI counter */
- ESP_WRITE_REG(sc->sc_esp, ESP_TCL, size);
- ESP_WRITE_REG(sc->sc_esp, ESP_TCM, size >> 8);
- if (sc->sc_esp->sc_rev == ESP200) {
- ESP_WRITE_REG(sc->sc_esp, ESP_TCH, size >> 16);
- }
- /* load the count in */
- ESPCMD(sc->sc_esp, ESPCMD_NOP|ESPCMD_DMA);
-
- /*
- * Note that if `size' is 0, we've already transceived all
- * the bytes we want but we're still in the DATA PHASE.
- * Apparently, the device needs padding. Also, a transfer
- * size of 0 means "maximum" to the chip DMA logic.
- */
- ESPCMD(sc->sc_esp, (size==0?ESPCMD_TRPAD:ESPCMD_TRANS)|ESPCMD_DMA);
-
- sc->sc_active = 1;
-
- /* Start DMA */
- tcds_dma_enable(sc, 1);
-}
-
/*
* Pseudo (chained) interrupt from the esp driver to kick the
* current running DMA transfer. I am replying on espintr() to
@@ -246,7 +164,7 @@ tcds_dma_intr(sc)
#endif
ESP_DMA(("dud0 at 0x%lx dudmask 0x%x\n",
addr, dudmask));
- addr = (u_int32_t *)phystok0seg(addr);
+ addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr);
*addr = (*addr & ~dudmask) | (dud & dudmask);
}
dud = *sc->sc_dud1;
@@ -267,7 +185,7 @@ tcds_dma_intr(sc)
#endif
ESP_DMA(("dud1 at 0x%lx dudmask 0x%x\n",
addr, dudmask));
- addr = (u_int32_t *)phystok0seg(addr);
+ addr = (u_int32_t *)ALPHA_PHYS_TO_K0SEG((vm_offset_t)addr);
*addr = (*addr & ~dudmask) | (dud & dudmask);
}
/* XXX deal with saved residual byte? */
@@ -287,3 +205,75 @@ tcds_dma_intr(sc)
#endif
return 0;
}
+
+#define DMAMAX(a) (0x02000 - ((a) & 0x1fff))
+
+/*
+ * start a dma transfer or keep it going
+ */
+int
+tcds_dma_setup(sc, addr, len, datain, dmasize)
+ struct tcds_slotconfig *sc;
+ caddr_t *addr;
+ size_t *len, *dmasize;
+ int datain; /* DMA into main memory */
+{
+ u_int32_t dic;
+ size_t size;
+
+ sc->sc_dmaaddr = addr;
+ sc->sc_dmalen = len;
+ sc->sc_iswrite = datain;
+
+ ESP_DMA(("tcds_dma %d: start %d@0x%lx,%d\n", sc->sc_slot, *sc->sc_dmalen, *sc->sc_dmaaddr, sc->sc_iswrite));
+
+ /*
+ * the rules say we cannot transfer more than the limit
+ * of this DMA chip (64k) and we cannot cross a 8k boundary.
+ */
+
+ size = min(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
+ *dmasize = sc->sc_dmasize = size;
+
+ ESP_DMA(("dma_start: dmasize = %d\n", sc->sc_dmasize));
+
+ /* Load address, set/clear unaligned transfer and read/write bits. */
+ /* XXX PICK AN ADDRESS TYPE, AND STICK TO IT! */
+ if ((u_long)*addr > VM_MIN_KERNEL_ADDRESS) {
+ *sc->sc_sda = vatopa((u_long)*addr) >> 2;
+ } else {
+ *sc->sc_sda = ALPHA_K0SEG_TO_PHYS((u_long)*addr) >> 2;
+ }
+ alpha_mb();
+ dic = *sc->sc_dic;
+ dic &= ~TCDS_DIC_ADDRMASK;
+ dic |= (vm_offset_t)*addr & TCDS_DIC_ADDRMASK;
+ if (datain)
+ dic |= TCDS_DIC_WRITE;
+ else
+ dic &= ~TCDS_DIC_WRITE;
+ *sc->sc_dic = dic;
+ alpha_mb();
+
+ return (0);
+}
+
+void
+tcds_dma_go(sc)
+ struct tcds_slotconfig *sc;
+{
+
+ /* mark unit as DMA-active */
+ sc->sc_active = 1;
+
+ /* Start DMA */
+ tcds_dma_enable(sc, 1);
+}
+
+int
+tcds_dma_isactive(sc)
+ struct tcds_slotconfig *sc;
+{
+
+ return (sc->sc_active);
+}
diff --git a/sys/arch/alpha/tc/tcdsreg.h b/sys/arch/alpha/tc/tcdsreg.h
index beec02040ea..c8839b8cf7c 100644
--- a/sys/arch/alpha/tc/tcdsreg.h
+++ b/sys/arch/alpha/tc/tcdsreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcdsreg.h,v 1.2 1996/07/29 23:02:38 niklas Exp $ */
-/* $NetBSD: tcdsreg.h,v 1.1 1995/12/20 00:40:36 cgd Exp $ */
+/* $OpenBSD: tcdsreg.h,v 1.3 1996/10/30 22:41:29 niklas Exp $ */
+/* $NetBSD: tcdsreg.h,v 1.2 1996/07/09 00:55:42 cgd Exp $ */
/*
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
@@ -132,7 +132,7 @@ void tcds_scsi_reset __P((int));
/*
* XXX
- * Start of MACH #defines, minimal changes to port to NetBSD.
+ * Start of MACH #defines, minimal changes to port to {Net/Open}BSD.
*
* The following register is the SCSI control interrupt register. It
* starts, stops and resets scsi DMA. It takes over the SCSI funtions
@@ -209,7 +209,7 @@ void tcds_scsi_reset __P((int));
# define SCSI_DUDE_MASK01 0x2000000 /* Mask bit for byte[01] */
# define SCSI_DUDE_MASK10 0x4000000 /* Mask bit for byte[10] */
-#define SCSI_CIR phystok0seg(KN15AA_REG_SCSI_CIR)
-#define SCSI_IMER phystok0seg(KN15AA_REG_SCSI_IMER)
+#define SCSI_CIR ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_CIR)
+#define SCSI_IMER ALPHA_PHYS_TO_K0SEG(KN15AA_REG_SCSI_IMER)
#endif
diff --git a/sys/arch/alpha/tc/tcdsvar.h b/sys/arch/alpha/tc/tcdsvar.h
index 82dd5f57b50..a877de2dc7f 100644
--- a/sys/arch/alpha/tc/tcdsvar.h
+++ b/sys/arch/alpha/tc/tcdsvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: tcdsvar.h,v 1.3 1996/07/29 23:02:40 niklas Exp $ */
-/* $NetBSD: tcdsvar.h,v 1.3 1996/04/12 06:10:18 cgd Exp $ */
+/* $OpenBSD: tcdsvar.h,v 1.4 1996/10/30 22:41:31 niklas Exp $ */
+/* $NetBSD: tcdsvar.h,v 1.4 1996/09/09 18:10:39 cgd Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
@@ -91,16 +91,18 @@ void tcds_dma_enable __P((struct tcds_slotconfig *, int));
void tcds_scsi_enable __P((struct tcds_slotconfig *, int));
int tcds_scsi_isintr __P((struct tcds_slotconfig *, int));
void tcds_scsi_reset __P((struct tcds_slotconfig *));
+int tcds_scsi_iserr __P((struct tcds_slotconfig *));
/*
* TCDS DMA functions (used the the 53c94 driver)
*/
-void tcds_dma_reset __P((struct tcds_slotconfig *));
-void tcds_dma_enintr __P((struct tcds_slotconfig *));
int tcds_dma_isintr __P((struct tcds_slotconfig *));
-void tcds_dma_start __P((struct tcds_slotconfig *, caddr_t *,
- size_t *, int));
-int tcds_dmaintr __P((struct tcds_slotconfig *));
+void tcds_dma_reset __P((struct tcds_slotconfig *));
+int tcds_dma_intr __P((struct tcds_slotconfig *));
+int tcds_dma_setup __P((struct tcds_slotconfig *, caddr_t *, size_t *,
+ int, size_t *));
+void tcds_dma_go __P((struct tcds_slotconfig *));
+int tcds_dma_isactive __P((struct tcds_slotconfig *));
/*
* The TCDS (bus) cfdriver, so that subdevices can more