summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2002-09-16 00:53:13 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2002-09-16 00:53:13 +0000
commit5c887e3b8f5771d2cd3d6f139c092e87d57f5546 (patch)
treea2872203708b1f27f48b0f7051bdb165b72cb001 /sys/dev/ic
parentdc3f896569f53d964a5e3ae960063e5aec5125b6 (diff)
Resync siop with NetBSD. Make strong effort to minimize
differences, undoing whitespace, spelling, etc. changes and adopting the NetBSD code instead of equivalent home grown code for PPR negotiation, etc. siop.c 1.21 -> 1.64 siop_common.c 1.12 -> 1.30 siopreg.h 1.7 -> 1.13 siopvar.h 1.13 -> 1.18 siopvar_common.h 1.10 -> 1.21 ncr53cxxx.c 1.5 -> 1.10 siop.ss 1.12 -> 1.17 siop_pci.c 1.8 -> 1.11 siop_pci_common.c 1.6 -> 1.17 siop_pci_common.h 1.2 -> 1.4 Many fixes, add 1010-66 support, restructure things to prepare for addition of esiop, osiop and oosiop drivers. tested on various archs by art@, millert@, wilfried@, jason@, Dan Weeks. ok deraadt@.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/siop.c1359
-rw-r--r--sys/dev/ic/siop_common.c849
-rw-r--r--sys/dev/ic/siopreg.h230
-rw-r--r--sys/dev/ic/siopvar.h138
-rw-r--r--sys/dev/ic/siopvar_common.h240
5 files changed, 1584 insertions, 1232 deletions
diff --git a/sys/dev/ic/siop.c b/sys/dev/ic/siop.c
index fae73c66490..539cfd137d0 100644
--- a/sys/dev/ic/siop.c
+++ b/sys/dev/ic/siop.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: siop.c,v 1.21 2002/07/20 11:22:27 art Exp $ */
-/* $NetBSD: siop.c,v 1.39 2001/02/11 18:04:49 bouyer Exp $ */
+/* $OpenBSD: siop.c,v 1.22 2002/09/16 00:53:12 krw Exp $ */
+/* $NetBSD: siop.c,v 1.64 2002/07/26 01:00:43 wiz Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -14,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Manuel Bouyer
+ * This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -50,8 +50,8 @@
#include <scsi/scsiconf.h>
#include <dev/ic/siopreg.h>
-#include <dev/ic/siopvar.h>
#include <dev/ic/siopvar_common.h>
+#include <dev/ic/siopvar.h>
#ifndef DEBUG
#undef DEBUG
@@ -71,7 +71,7 @@
/* number of cmd descriptors per block */
#define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer))
-/* number of scheduler slots (needs to match script) */
+/* Number of scheduler slot (needs to match script) */
#define SIOP_NSLOTS 40
void siop_reset(struct siop_softc *);
@@ -82,10 +82,10 @@ void siop_start(struct siop_softc *);
void siop_timeout(void *);
int siop_scsicmd(struct scsi_xfer *);
void siop_dump_script(struct siop_softc *);
-int siop_morecbd(struct siop_softc *);
+void siop_morecbd(struct siop_softc *);
struct siop_lunsw *siop_get_lunsw(struct siop_softc *);
void siop_add_reselsw(struct siop_softc *, int);
-void siop_update_scntl3(struct siop_softc *, struct siop_target *);
+void siop_update_scntl3(struct siop_softc *, struct siop_common_target *);
struct cfdriver siop_cd = {
NULL, "siop", DV_DULL
@@ -125,9 +125,9 @@ siop_script_sync(sc, ops)
struct siop_softc *sc;
int ops;
{
- if ((sc->features & SF_CHIP_RAM) == 0)
- bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma,
- 0, PAGE_SIZE, ops);
+ if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
+ bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
+ PAGE_SIZE, ops);
}
static __inline__ u_int32_t siop_script_read(struct siop_softc *, u_int);
@@ -136,10 +136,11 @@ siop_script_read(sc, offset)
struct siop_softc *sc;
u_int offset;
{
- if (sc->features & SF_CHIP_RAM) {
- return bus_space_read_4(sc->sc_ramt, sc->sc_ramh, offset * 4);
+ if (sc->sc_c.features & SF_CHIP_RAM) {
+ return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
+ offset * 4);
} else {
- return letoh32(sc->sc_script[offset]);
+ return letoh32(sc->sc_c.sc_script[offset]);
}
}
@@ -151,10 +152,11 @@ siop_script_write(sc, offset, val)
u_int offset;
u_int32_t val;
{
- if (sc->features & SF_CHIP_RAM) {
- bus_space_write_4(sc->sc_ramt, sc->sc_ramh, offset * 4, val);
+ if (sc->sc_c.features & SF_CHIP_RAM) {
+ bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
+ offset * 4, val);
} else {
- sc->sc_script[offset] = htole32(val);
+ sc->sc_c.sc_script[offset] = htole32(val);
}
}
@@ -162,104 +164,29 @@ void
siop_attach(sc)
struct siop_softc *sc;
{
- int error, i;
- bus_dma_segment_t seg;
- int rseg;
+ if (siop_common_attach(&sc->sc_c) != 0)
+ return;
- /*
- * Allocate DMA-safe memory for the script and map it.
- */
- if ((sc->features & SF_CHIP_RAM) == 0) {
- error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE,
- PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
- if (error) {
- printf("%s: unable to allocate script DMA memory, "
- "error = %d\n", sc->sc_dev.dv_xname, error);
- return;
- }
- error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, PAGE_SIZE,
- (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
- if (error) {
- printf("%s: unable to map script DMA memory, "
- "error = %d\n", sc->sc_dev.dv_xname, error);
- return;
- }
- error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
- PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_scriptdma);
- if (error) {
- printf("%s: unable to create script DMA map, "
- "error = %d\n", sc->sc_dev.dv_xname, error);
- return;
- }
- error = bus_dmamap_load(sc->sc_dmat, sc->sc_scriptdma,
- sc->sc_script, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
- if (error) {
- printf("%s: unable to load script DMA map, "
- "error = %d\n", sc->sc_dev.dv_xname, error);
- return;
- }
- sc->sc_scriptaddr = sc->sc_scriptdma->dm_segs[0].ds_addr;
- sc->ram_size = PAGE_SIZE;
- }
TAILQ_INIT(&sc->free_list);
TAILQ_INIT(&sc->ready_list);
TAILQ_INIT(&sc->urgent_list);
TAILQ_INIT(&sc->cmds);
TAILQ_INIT(&sc->lunsw_list);
sc->sc_currschedslot = 0;
-#ifdef SIOP_DEBUG
- printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
- sc->sc_dev.dv_xname, (int)sizeof(siop_script),
- (u_int32_t)sc->sc_scriptaddr, sc->sc_script);
-#endif
+ sc->sc_c.sc_link.adapter = &siop_adapter;
+ sc->sc_c.sc_link.device = &siop_dev;
+
/* Start with one page worth of commands */
siop_morecbd(sc);
- /*
- * sc->sc_link is the template for all device sc_link's
- * for devices attached to this adapter. It is passed to
- * the upper layers in config_found().
- */
- sc->sc_link.adapter_softc = sc;
- sc->sc_link.openings = SIOP_OPENINGS;
- sc->sc_link.adapter_buswidth =
- (sc->features & SF_BUS_WIDE) ? 16 : 8;
- sc->sc_link.adapter_target = bus_space_read_1(sc->sc_rt,
- sc->sc_rh, SIOP_SCID);
- if (sc->sc_link.adapter_target == 0 ||
- sc->sc_link.adapter_target >=
- sc->sc_link.adapter_buswidth)
- sc->sc_link.adapter_target = SIOP_DEFAULT_TARGET;
- sc->sc_link.adapter = &siop_adapter;
- sc->sc_link.device = &siop_dev;
- sc->sc_link.flags = 0;
- sc->sc_link.quirks = 0;
- if ((sc->features & SF_BUS_WIDE) == 0)
- sc->sc_link.quirks |= SDEV_NOWIDE;
-
- for (i = 0; i < 16; i++)
- sc->targets[i] = NULL;
-
- /* find min_dt_sync and min_st_sync for this chip */
- sc->min_dt_sync = 0;
- for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)
- if (period_factor[i].scf[sc->scf_index].dt_scf != 0) {
- sc->min_dt_sync = period_factor[i].factor;
- break;
- }
-
- sc->min_st_sync = 0;
- for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)
- if (period_factor[i].scf[sc->scf_index].st_scf != 0) {
- sc->min_st_sync = period_factor[i].factor;
- break;
- }
-
- if (sc->min_st_sync == 0)
- panic("%s: can't find minimum allowed sync period factor\n", sc->sc_dev.dv_xname);
+#ifdef SIOP_DEBUG
+ printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
+ sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script),
+ (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
+#endif
/* Do a bus reset, so that devices fall back to narrow/async */
- siop_resetbus(sc);
+ siop_resetbus(&sc->sc_c);
/*
* siop_reset() will reset the chip, thus clearing pending interrupts
*/
@@ -268,7 +195,7 @@ siop_attach(sc)
siop_dump_script(sc);
#endif
- config_found((struct device*)sc, &sc->sc_link, scsiprint);
+ config_found((struct device*)sc, &sc->sc_c.sc_link, scsiprint);
}
void
@@ -278,78 +205,114 @@ siop_reset(sc)
int i, j;
struct siop_lunsw *lunsw;
- siop_common_reset(sc);
+ siop_common_reset(&sc->sc_c);
/* copy and patch the script */
- if (sc->features & SF_CHIP_RAM) {
- bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh, 0,
+ if (sc->sc_c.features & SF_CHIP_RAM) {
+ bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
for (j = 0; j <
(sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
j++) {
- bus_space_write_4(sc->sc_ramt, sc->sc_ramh,
+ bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
E_abs_msgin_Used[j] * 4,
- sc->sc_scriptaddr + Ent_msgin_space);
+ sc->sc_c.sc_scriptaddr + Ent_msgin_space);
+ }
+ if (sc->sc_c.features & SF_CHIP_LED0) {
+ bus_space_write_region_4(sc->sc_c.sc_ramt,
+ sc->sc_c.sc_ramh,
+ Ent_led_on1, siop_led_on,
+ sizeof(siop_led_on) / sizeof(siop_led_on[0]));
+ bus_space_write_region_4(sc->sc_c.sc_ramt,
+ sc->sc_c.sc_ramh,
+ Ent_led_on2, siop_led_on,
+ sizeof(siop_led_on) / sizeof(siop_led_on[0]));
+ bus_space_write_region_4(sc->sc_c.sc_ramt,
+ sc->sc_c.sc_ramh,
+ Ent_led_off, siop_led_off,
+ sizeof(siop_led_off) / sizeof(siop_led_off[0]));
}
} else {
for (j = 0;
j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
- sc->sc_script[j] = htole32(siop_script[j]);
+ sc->sc_c.sc_script[j] = htole32(siop_script[j]);
}
for (j = 0; j <
(sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
j++) {
- sc->sc_script[E_abs_msgin_Used[j]] =
- htole32(sc->sc_scriptaddr + Ent_msgin_space);
+ sc->sc_c.sc_script[E_abs_msgin_Used[j]] =
+ htole32(sc->sc_c.sc_scriptaddr + Ent_msgin_space);
+ }
+ if (sc->sc_c.features & SF_CHIP_LED0) {
+ for (j = 0; j < (sizeof(siop_led_on) /
+ sizeof(siop_led_on[0])); j++)
+ sc->sc_c.sc_script[
+ Ent_led_on1 / sizeof(siop_led_on[0]) + j
+ ] = htole32(siop_led_on[j]);
+ for (j = 0; j < (sizeof(siop_led_on) /
+ sizeof(siop_led_on[0])); j++)
+ sc->sc_c.sc_script[
+ Ent_led_on2 / sizeof(siop_led_on[0]) + j
+ ] = htole32(siop_led_on[j]);
+ for (j = 0; j < (sizeof(siop_led_off) /
+ sizeof(siop_led_off[0])); j++)
+ sc->sc_c.sc_script[
+ Ent_led_off / sizeof(siop_led_off[0]) + j
+ ] = htole32(siop_led_off[j]);
}
}
sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);
- sc->script_free_hi = sc->ram_size / 4;
+ sc->script_free_hi = sc->sc_c.ram_size / 4;
/* free used and unused lun switches */
while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {
#ifdef SIOP_DEBUG
printf("%s: free lunsw at offset %d\n",
- sc->sc_dev.dv_xname, lunsw->lunsw_off);
+ sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off);
#endif
TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
free(lunsw, M_DEVBUF);
}
TAILQ_INIT(&sc->lunsw_list);
/* restore reselect switch */
- for (i = 0; i < sc->sc_link.adapter_buswidth; i++) {
- if (sc->targets[i] == NULL)
+ for (i = 0; i < sc->sc_c.sc_link.adapter_buswidth; i++) {
+ struct siop_target *target;
+ if (sc->sc_c.targets[i] == NULL)
continue;
#ifdef SIOP_DEBUG
printf("%s: restore sw for target %d\n",
- sc->sc_dev.dv_xname, i);
+ sc->sc_c.sc_dev.dv_xname, i);
#endif
- free(sc->targets[i]->lunsw, M_DEVBUF);
- sc->targets[i]->lunsw = siop_get_lunsw(sc);
- if (sc->targets[i]->lunsw == NULL) {
+ target = (struct siop_target *)sc->sc_c.targets[i];
+ free(target->lunsw, M_DEVBUF);
+ target->lunsw = siop_get_lunsw(sc);
+ if (target->lunsw == NULL) {
printf("%s: can't alloc lunsw for target %d\n",
- sc->sc_dev.dv_xname, i);
+ sc->sc_c.sc_dev.dv_xname, i);
break;
}
siop_add_reselsw(sc, i);
}
/* start script */
- siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
- sc->sc_scriptaddr + Ent_reselect);
+ if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
+ bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
+ PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ }
+ bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
+ sc->sc_c.sc_scriptaddr + Ent_reselect);
}
#if 0
#define CALL_SCRIPT(ent) do {\
printf ("start script DSA 0x%lx DSP 0x%lx\n", \
- siop_cmd->dsa, \
- sc->sc_scriptaddr + ent); \
-bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \
+ siop_cmd->cmd_c.dsa, \
+ sc->sc_c.sc_scriptaddr + ent); \
+bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
} while (0)
#else
#define CALL_SCRIPT(ent) do {\
-bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \
+bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
} while (0)
#endif
@@ -362,8 +325,8 @@ siop_intr(v)
struct siop_cmd *siop_cmd;
struct siop_lun *siop_lun;
struct scsi_xfer *xs;
- int istat, sist = 0, sstat1 = 0, dstat = 0;
- u_int32_t irqcode = 0;
+ int istat, sist, sstat1, dstat;
+ u_int32_t irqcode;
int need_reset = 0;
int offset, target, lun, tag;
bus_addr_t dsa;
@@ -371,16 +334,23 @@ siop_intr(v)
int freetarget = 0;
int restart = 0;
- istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
+ istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
return 0;
INCSTAT(siop_stat_intr);
if (istat & ISTAT_INTF) {
printf("INTRF\n");
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_INTF);
+ bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_ISTAT, ISTAT_INTF);
+ }
+ if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
+ (ISTAT_DIP | ISTAT_ABRT)) {
+ /* clear abort */
+ bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_ISTAT, 0);
}
/* use DSA to find the current siop_cmd */
- dsa = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA);
+ dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA);
for (cbdp = TAILQ_FIRST(&sc->cmds); cbdp != NULL;
cbdp = TAILQ_NEXT(cbdp, next)) {
if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&
@@ -396,17 +366,18 @@ siop_intr(v)
siop_cmd = NULL;
}
if (siop_cmd) {
- xs = siop_cmd->xs;
- siop_target = siop_cmd->siop_target;
- target = siop_cmd->xs->sc_link->target;
- lun = siop_cmd->xs->sc_link->lun;
- tag = siop_cmd->tag;
+ xs = siop_cmd->cmd_c.xs;
+ siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target;
+ target = siop_cmd->cmd_c.xs->sc_link->target;
+ lun = siop_cmd->cmd_c.xs->sc_link->lun;
+ tag = siop_cmd->cmd_c.tag;
siop_lun = siop_target->siop_lun[lun];
#ifdef DIAGNOSTIC
- if (siop_cmd->status != CMDST_ACTIVE &&
- siop_cmd->status != CMDST_SENSE_ACTIVE) {
- printf("siop_cmd (lun %d) not active (%d)\n",
- lun, siop_cmd->status);
+ if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
+ siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
+ printf("siop_cmd (lun %d) for DSA 0x%x "
+ "not active (%d)\n", lun, (u_int)dsa,
+ siop_cmd->cmd_c.status);
xs = NULL;
siop_target = NULL;
target = -1;
@@ -429,44 +400,55 @@ siop_intr(v)
siop_lun = NULL;
}
if (istat & ISTAT_DIP) {
- dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);
+ dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSTAT);
+ if (dstat & DSTAT_ABRT) {
+ /* was probably generated by a bus reset IOCTL */
+ if ((dstat & DSTAT_DFE) == 0)
+ siop_clearfifo(&sc->sc_c);
+ goto reset;
+ }
if (dstat & DSTAT_SSI) {
printf("single step dsp 0x%08x dsa 0x08%x\n",
- (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- sc->sc_scriptaddr),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
+ (int)(bus_space_read_4(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_DSP) -
+ sc->sc_c.sc_scriptaddr),
+ bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSA));
if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
(istat & ISTAT_SIP) == 0) {
- bus_space_write_1(sc->sc_rt, sc->sc_rh,
- SIOP_DCNTL, bus_space_read_1(sc->sc_rt,
- sc->sc_rh, SIOP_DCNTL) | DCNTL_STD);
+ bus_space_write_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_DCNTL,
+ bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
}
return 1;
}
+
if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
- printf("DMA IRQ:");
- if (dstat & DSTAT_IID)
- printf("Illegal instruction");
- if (dstat & DSTAT_ABRT)
- printf(" abort");
- if (dstat & DSTAT_BF)
- printf(" bus fault");
- if (dstat & DSTAT_MDPE)
- printf(" parity");
- if (dstat & DSTAT_DFE)
- printf(" dma fifo empty");
- printf(", DSP=0x%x DSA=0x%x: ",
- (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- sc->sc_scriptaddr),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
- if (siop_cmd)
- printf("last msg_in=0x%x status=0x%x\n",
- siop_cmd->siop_tables.msg_in[0],
- letoh32(siop_cmd->siop_tables.status));
- else
- printf("%s: current DSA invalid\n",
- sc->sc_dev.dv_xname);
- need_reset = 1;
+ printf("DMA IRQ:");
+ if (dstat & DSTAT_IID)
+ printf(" Illegal instruction");
+ if (dstat & DSTAT_BF)
+ printf(" bus fault");
+ if (dstat & DSTAT_MDPE)
+ printf(" parity");
+ if (dstat & DSTAT_DFE)
+ printf(" dma fifo empty");
+ else
+ siop_clearfifo(&sc->sc_c);
+ printf(", DSP=0x%x DSA=0x%x: ",
+ (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSP) - sc->sc_c.sc_scriptaddr),
+ bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
+ if (siop_cmd)
+ printf("last msg_in=0x%x status=0x%x\n",
+ siop_cmd->cmd_tables->msg_in[0],
+ letoh32(siop_cmd->cmd_tables->status));
+ else
+ printf("%s: current DSA invalid\n",
+ sc->sc_c.sc_dev.dv_xname);
+ need_reset = 1;
}
}
if (istat & ISTAT_SIP) {
@@ -476,15 +458,19 @@ siop_intr(v)
* Can't read sist0 & sist1 independantly, or we have to
* insert delay
*/
- sist = bus_space_read_2(sc->sc_rt, sc->sc_rh, SIOP_SIST0);
- sstat1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1);
+ sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_SIST0);
+ sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_SSTAT1);
#ifdef SIOP_DEBUG_INTR
printf("scsi interrupt, sist=0x%x sstat1=0x%x "
"DSA=0x%x DSP=0x%lx\n", sist,
- bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
- (u_long)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- sc->sc_scriptaddr));
+ bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_SSTAT1),
+ bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
+ (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSP) -
+ sc->sc_c.sc_scriptaddr));
#endif
if (sist & SIST0_RST) {
siop_handle_reset(sc);
@@ -496,49 +482,50 @@ siop_intr(v)
if (siop_cmd)
sc_print_addr(xs->sc_link);
else
- printf("%s:", sc->sc_dev.dv_xname);
+ printf("%s:", sc->sc_c.sc_dev.dv_xname);
printf("scsi gross error\n");
goto reset;
}
if ((sist & SIST0_MA) && need_reset == 0) {
if (siop_cmd) {
int scratcha0;
- dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh,
- SIOP_DSTAT);
+ dstat = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_DSTAT);
/*
* first restore DSA, in case we were in a S/G
* operation.
*/
- bus_space_write_4(sc->sc_rt, sc->sc_rh,
- SIOP_DSA, siop_cmd->dsa);
- scratcha0 = bus_space_read_1(sc->sc_rt,
- sc->sc_rh, SIOP_SCRATCHA);
+ bus_space_write_4(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh,
+ SIOP_DSA, siop_cmd->cmd_c.dsa);
+ scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SCRATCHA);
switch (sstat1 & SSTAT1_PHASE_MASK) {
case SSTAT1_PHASE_STATUS:
/*
- * Previous phase may have aborted for any reason
- * (for example, the target has less data to
+ * previous phase may be aborted for any reason
+ * ( for example, the target has less data to
* transfer than requested). Just go to status
* and the command should terminate.
*/
INCSTAT(siop_stat_intr_shortxfer);
if ((dstat & DSTAT_DFE) == 0)
- siop_clearfifo(sc);
+ siop_clearfifo(&sc->sc_c);
/* no table to flush here */
CALL_SCRIPT(Ent_status);
return 1;
case SSTAT1_PHASE_MSGIN:
/*
- * Target may be ready to disconnect.
+ * target may be ready to disconnect
* Save data pointers just in case.
*/
INCSTAT(siop_stat_intr_xferdisc);
if (scratcha0 & A_flag_data)
- siop_sdp(siop_cmd);
+ siop_sdp(&siop_cmd->cmd_c);
else if ((dstat & DSTAT_DFE) == 0)
- siop_clearfifo(sc);
- bus_space_write_1(sc->sc_rt, sc->sc_rh,
- SIOP_SCRATCHA,
+ siop_clearfifo(&sc->sc_c);
+ bus_space_write_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SCRATCHA,
scratcha0 & ~A_flag_data);
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD |
@@ -547,11 +534,11 @@ siop_intr(v)
return 1;
}
printf("%s: unexpected phase mismatch %d\n",
- sc->sc_dev.dv_xname,
+ sc->sc_c.sc_dev.dv_xname,
sstat1 & SSTAT1_PHASE_MASK);
} else {
printf("%s: phase mismatch without command\n",
- sc->sc_dev.dv_xname);
+ sc->sc_c.sc_dev.dv_xname);
}
need_reset = 1;
}
@@ -560,20 +547,20 @@ siop_intr(v)
if (siop_cmd)
sc_print_addr(xs->sc_link);
else
- printf("%s:", sc->sc_dev.dv_xname);
+ printf("%s:", sc->sc_c.sc_dev.dv_xname);
printf("parity error\n");
goto reset;
}
if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
/* selection time out, assume there's no device here */
if (siop_cmd) {
- siop_cmd->status = CMDST_DONE;
+ siop_cmd->cmd_c.status = CMDST_DONE;
xs->error = XS_SELTIMEOUT;
freetarget = 1;
goto end;
} else {
printf("%s: selection timeout without "
- "command\n", sc->sc_dev.dv_xname);
+ "command\n", sc->sc_c.sc_dev.dv_xname);
need_reset = 1;
}
}
@@ -583,43 +570,45 @@ siop_intr(v)
* a fatal condition this way. Attempt to get sense.
*/
if (siop_cmd) {
- siop_cmd->siop_tables.status =
+ siop_cmd->cmd_tables->status =
htole32(SCSI_CHECK);
goto end;
}
printf("%s: unexpected disconnect without "
- "command\n", sc->sc_dev.dv_xname);
+ "command\n", sc->sc_c.sc_dev.dv_xname);
goto reset;
}
if (sist & (SIST1_SBMC << 8)) {
/* SCSI bus mode change */
- if (siop_modechange(sc) == 0 || need_reset == 1)
+ if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
goto reset;
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
/*
- * We have a script interrupt. It will
+ * we have a script interrupt, it will
* restart the script.
*/
goto scintr;
}
/*
- * Else we have to restart the script ourself, at the
+ * else we have to restart it ourselve, at the
* interrupted instruction.
*/
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
- bus_space_read_4(sc->sc_rt, sc->sc_rh,
+ bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSP,
+ bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_DSP) - 8);
return 1;
}
- /* Else it's an unhandled exception (for now). */
+ /* Else it's an unhandled exeption (for now). */
printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
- "DSA=0x%x DSP=0x%x\n", sc->sc_dev.dv_xname, sist,
- bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
- bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
- (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
- sc->sc_scriptaddr));
+ "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, sist,
+ bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_SSTAT1),
+ bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
+ (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSP) - sc->sc_c.sc_scriptaddr));
if (siop_cmd) {
- siop_cmd->status = CMDST_DONE;
+ siop_cmd->cmd_c.status = CMDST_DONE;
xs->error = XS_SELTIMEOUT;
goto end;
}
@@ -628,14 +617,14 @@ siop_intr(v)
if (need_reset) {
reset:
/* fatal error, reset the bus */
- siop_resetbus(sc);
+ siop_resetbus(&sc->sc_c);
/* no table to flush here */
return 1;
}
scintr:
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
- irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,
+ irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_DSPS);
#ifdef SIOP_DEBUG_INTR
printf("script interrupt 0x%x\n", irqcode);
@@ -646,25 +635,25 @@ scintr:
*/
if ((irqcode & 0x80) == 0) {
if (siop_cmd == NULL) {
- printf("%s: script interrupt (0x%x) with "
- "invalid DSA !!!\n", sc->sc_dev.dv_xname,
- irqcode);
+ printf(
+ "%s: script interrupt (0x%x) with invalid DSA !!!\n",
+ sc->sc_c.sc_dev.dv_xname, irqcode);
goto reset;
}
- if (siop_cmd->status != CMDST_ACTIVE &&
- siop_cmd->status != CMDST_SENSE_ACTIVE) {
+ if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
+ siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
printf("%s: command with invalid status "
"(IRQ code 0x%x current status %d) !\n",
- sc->sc_dev.dv_xname,
- irqcode, siop_cmd->status);
+ sc->sc_c.sc_dev.dv_xname,
+ irqcode, siop_cmd->cmd_c.status);
xs = NULL;
}
}
switch(irqcode) {
case A_int_err:
printf("error, DSP=0x%x\n",
- (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh,
- SIOP_DSP) - sc->sc_scriptaddr));
+ (int)(bus_space_read_4(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
if (xs) {
xs->error = XS_SELTIMEOUT;
goto end;
@@ -673,89 +662,98 @@ scintr:
}
case A_int_reseltarg:
printf("%s: reselect with invalid target\n",
- sc->sc_dev.dv_xname);
+ sc->sc_c.sc_dev.dv_xname);
goto reset;
case A_int_resellun:
INCSTAT(siop_stat_intr_lunresel);
- target = bus_space_read_1(sc->sc_rt, sc->sc_rh,
- SIOP_SCRATCHA) & 0xf;
- lun = bus_space_read_1(sc->sc_rt, sc->sc_rh,
+ target = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf;
+ lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_SCRATCHA + 1);
- tag = bus_space_read_1(sc->sc_rt, sc->sc_rh,
+ tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_SCRATCHA + 2);
- siop_target = sc->targets[target];
+ siop_target =
+ (struct siop_target *)sc->sc_c.targets[target];
if (siop_target == NULL) {
- printf("%s: reselect with invalid "
- "target %d\n", sc->sc_dev.dv_xname, target);
+ printf("%s: reselect with invalid target %d\n",
+ sc->sc_c.sc_dev.dv_xname, target);
goto reset;
}
siop_lun = siop_target->siop_lun[lun];
if (siop_lun == NULL) {
printf("%s: target %d reselect with invalid "
- "lun %d\n", sc->sc_dev.dv_xname,
+ "lun %d\n", sc->sc_c.sc_dev.dv_xname,
target, lun);
goto reset;
}
if (siop_lun->siop_tag[tag].active == NULL) {
printf("%s: target %d lun %d tag %d reselect "
- "without command\n", sc->sc_dev.dv_xname,
+ "without command\n",
+ sc->sc_c.sc_dev.dv_xname,
target, lun, tag);
goto reset;
}
siop_cmd = siop_lun->siop_tag[tag].active;
- bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
- siop_cmd->dsa + sizeof(struct siop_xfer_common) +
+ bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_DSP, siop_cmd->cmd_c.dsa +
+ sizeof(struct siop_common_xfer) +
Ent_ldsa_reload_dsa);
siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
return 1;
case A_int_reseltag:
printf("%s: reselect with invalid tag\n",
- sc->sc_dev.dv_xname);
+ sc->sc_c.sc_dev.dv_xname);
goto reset;
case A_int_msgin:
{
- int msgin = bus_space_read_1(sc->sc_rt, sc->sc_rh,
- SIOP_SFBR);
+ int msgin = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SFBR);
if (msgin == MSG_MESSAGE_REJECT) {
int msg, extmsg;
- if (siop_cmd->siop_tables.msg_out[0] & 0x80) {
+ if (siop_cmd->cmd_tables->msg_out[0] & 0x80) {
/*
- * Message was part of an identify +
+ * message was part of a identify +
* something else. Identify shouldn't
* have been rejected.
*/
- msg = siop_cmd->siop_tables.msg_out[1];
+ msg =
+ siop_cmd->cmd_tables->msg_out[1];
extmsg =
- siop_cmd->siop_tables.msg_out[3];
+ siop_cmd->cmd_tables->msg_out[3];
} else {
- msg = siop_cmd->siop_tables.msg_out[0];
+ msg = siop_cmd->cmd_tables->msg_out[0];
extmsg =
- siop_cmd->siop_tables.msg_out[2];
+ siop_cmd->cmd_tables->msg_out[2];
}
if (msg == MSG_MESSAGE_REJECT) {
- /* MSG_REJECT for a MSG_REJECT! */
+ /* MSG_REJECT for a MSG_REJECT !*/
if (xs)
sc_print_addr(xs->sc_link);
else
printf("%s: ",
- sc->sc_dev.dv_xname);
+ sc->sc_c.sc_dev.dv_xname);
printf("our reject message was "
"rejected\n");
goto reset;
}
if (msg == MSG_EXTENDED &&
extmsg == MSG_EXT_WDTR) {
- if ((siop_target->flags & TARF_SYNC)
- == 0) {
- siop_target->status = TARST_OK;
- siop_print_info(sc, target);
+ /* WDTR rejected, initiate sync */
+ if ((siop_target->target_c.flags &
+ TARF_SYNC) == 0) {
+ siop_target->target_c.status =
+ TARST_OK;
+ siop_update_xfer_mode(&sc->sc_c,
+ target);
/* no table to flush here */
CALL_SCRIPT(Ent_msgin_ack);
return 1;
}
- siop_target->status = TARST_SYNC_NEG;
- siop_sdtr_msg(siop_cmd, 0,
- sc->min_st_sync, sc->maxoff);
+ siop_target->target_c.status =
+ TARST_SYNC_NEG;
+ siop_sdtr_msg(&siop_cmd->cmd_c, 0,
+ sc->sc_c.st_minsync,
+ sc->sc_c.maxoff);
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
@@ -763,8 +761,12 @@ scintr:
return 1;
} else if (msg == MSG_EXTENDED &&
extmsg == MSG_EXT_SDTR) {
- siop_target->status = TARST_OK;
- siop_print_info(sc, target);
+ /* sync rejected */
+ siop_target->target_c.offset = 0;
+ siop_target->target_c.period = 0;
+ siop_target->target_c.status = TARST_OK;
+ siop_update_xfer_mode(&sc->sc_c,
+ target);
/* no table to flush here */
CALL_SCRIPT(Ent_msgin_ack);
return 1;
@@ -780,7 +782,8 @@ scintr:
if (xs)
sc_print_addr(xs->sc_link);
else
- printf("%s: ", sc->sc_dev.dv_xname);
+ printf("%s: ",
+ sc->sc_c.sc_dev.dv_xname);
if (msg == MSG_EXTENDED) {
printf("scsi message reject, extended "
"message sent was 0x%x\n", extmsg);
@@ -795,11 +798,11 @@ scintr:
if (xs)
sc_print_addr(xs->sc_link);
else
- printf("%s: ", sc->sc_dev.dv_xname);
+ printf("%s: ", sc->sc_c.sc_dev.dv_xname);
printf("unhandled message 0x%x\n",
- siop_cmd->siop_tables.msg_in[0]);
- siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
- siop_cmd->siop_tables.t_msgout.count= htole32(1);
+ siop_cmd->cmd_tables->msg_in[0]);
+ siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
+ siop_cmd->cmd_tables->t_msgout.count= htole32(1);
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_send_msgout);
@@ -808,136 +811,159 @@ scintr:
case A_int_extmsgin:
#ifdef SIOP_DEBUG_INTR
printf("extended message: msg 0x%x len %d\n",
- siop_cmd->siop_tables.msg_in[2],
- siop_cmd->siop_tables.msg_in[1]);
+ siop_cmd->cmd_tables->msg_in[2],
+ siop_cmd->cmd_tables->msg_in[1]);
#endif
- if (siop_cmd->siop_tables.msg_in[1] > 6)
+ if (siop_cmd->cmd_tables->msg_in[1] >
+ sizeof(siop_cmd->cmd_tables->msg_in) - 2)
printf("%s: extended message too big (%d)\n",
- sc->sc_dev.dv_xname,
- siop_cmd->siop_tables.msg_in[1]);
- siop_cmd->siop_tables.t_extmsgdata.count =
- htole32(siop_cmd->siop_tables.msg_in[1] - 1);
+ sc->sc_c.sc_dev.dv_xname,
+ siop_cmd->cmd_tables->msg_in[1]);
+ siop_cmd->cmd_tables->t_extmsgdata.count =
+ htole32(siop_cmd->cmd_tables->msg_in[1] - 1);
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_get_extmsgdata);
return 1;
case A_int_extmsgdata:
- {
#ifdef SIOP_DEBUG_INTR
{
int i;
printf("extended message: 0x%x, data:",
- siop_cmd->siop_tables.msg_in[2]);
- for (i = 3; i < 2 + siop_cmd->siop_tables.msg_in[1];
+ siop_cmd->cmd_tables->msg_in[2]);
+ for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1];
i++)
printf(" 0x%x",
- siop_cmd->siop_tables.msg_in[i]);
+ siop_cmd->cmd_tables->msg_in[i]);
printf("\n");
}
#endif
- int neg_action = SIOP_NEG_NOP;
- const char *neg_name = "";
-
- switch (siop_cmd->siop_tables.msg_in[2]) {
- case MSG_EXT_WDTR:
- neg_action = siop_wdtr_neg(siop_cmd);
- neg_name = "wdtr";
- break;
- case MSG_EXT_SDTR:
- neg_action = siop_sdtr_neg(siop_cmd);
- neg_name = "sdtr";
- break;
- case MSG_EXT_PPR:
- neg_action = siop_ppr_neg(siop_cmd);
- neg_name = "ppr";
- break;
- default:
- neg_action = SIOP_NEG_MSGREJ;
- break;
+ if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
+ switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
+ case SIOP_NEG_MSGOUT:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return(1);
+ case SIOP_NEG_ACK:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ CALL_SCRIPT(Ent_msgin_ack);
+ return(1);
+ default:
+ panic("invalid retval from "
+ "siop_wdtr_neg()");
+ }
+ return(1);
}
-
- switch (neg_action) {
- case SIOP_NEG_NOP:
- break;
- case SIOP_NEG_MSGOUT:
- siop_update_scntl3(sc, siop_cmd->siop_target);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_send_msgout);
- break;
- case SIOP_NEG_ACK:
- siop_update_scntl3(sc, siop_cmd->siop_target);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_msgin_ack);
- break;
- case SIOP_NEG_MSGREJ:
- siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
- siop_cmd->siop_tables.t_msgout.count = htole32(1);
- siop_table_sync(siop_cmd,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- CALL_SCRIPT(Ent_send_msgout);
- break;
- default:
- panic("invalid return value from siop_%s_neg(): 0x%x", neg_name, neg_action);
+ if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
+ switch (siop_sdtr_neg(&siop_cmd->cmd_c)) {
+ case SIOP_NEG_MSGOUT:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return(1);
+ case SIOP_NEG_ACK:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ CALL_SCRIPT(Ent_msgin_ack);
+ return(1);
+ default:
+ panic("invalid retval from "
+ "siop_wdtr_neg()");
+ }
+ return(1);
}
-
- return (1);
- }
-
+ if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
+ switch (siop_ppr_neg(&siop_cmd->cmd_c)) {
+ case SIOP_NEG_MSGOUT:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return(1);
+ case SIOP_NEG_ACK:
+ siop_update_scntl3(sc,
+ siop_cmd->cmd_c.siop_target);
+ CALL_SCRIPT(Ent_msgin_ack);
+ return(1);
+ default:
+ panic("invalid retval from "
+ "siop_wdtr_neg()");
+ }
+ return(1);
+ }
+ /* send a message reject */
+ siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
+ siop_cmd->cmd_tables->t_msgout.count = htole32(1);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ CALL_SCRIPT(Ent_send_msgout);
+ return 1;
case A_int_disc:
INCSTAT(siop_stat_intr_sdp);
- offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,
- SIOP_SCRATCHA + 1);
+ offset = bus_space_read_1(sc->sc_c.sc_rt,
+ sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
#ifdef SIOP_DEBUG_DR
printf("disconnect offset %d\n", offset);
#endif
if (offset > SIOP_NSG) {
printf("%s: bad offset for disconnect (%d)\n",
- sc->sc_dev.dv_xname, offset);
+ sc->sc_c.sc_dev.dv_xname, offset);
goto reset;
}
/*
* offset == SIOP_NSG may be a valid condition if
* we get a sdp when the xfer is done.
- * Don't call memmove in this case.
+ * Don't call bcopy in this case.
*/
if (offset < SIOP_NSG) {
- bcopy(&siop_cmd->siop_tables.data[offset],
- &siop_cmd->siop_tables.data[0],
- (SIOP_NSG - offset) * sizeof(struct scr_table));
+ bcopy(&siop_cmd->cmd_tables->data[offset],
+ &siop_cmd->cmd_tables->data[0],
+ (SIOP_NSG - offset) * sizeof(scr_table_t));
siop_table_sync(siop_cmd,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
- CALL_SCRIPT(Ent_script_sched);
/* check if we can put some command in scheduler */
siop_start(sc);
+ CALL_SCRIPT(Ent_script_sched);
return 1;
case A_int_resfail:
printf("reselect failed\n");
+ /* check if we can put some command in scheduler */
+ siop_start(sc);
CALL_SCRIPT(Ent_script_sched);
return 1;
case A_int_done:
if (xs == NULL) {
printf("%s: done without command, DSA=0x%lx\n",
- sc->sc_dev.dv_xname, (u_long)siop_cmd->dsa);
- siop_cmd->status = CMDST_FREE;
+ sc->sc_c.sc_dev.dv_xname,
+ (u_long)siop_cmd->cmd_c.dsa);
+ siop_cmd->cmd_c.status = CMDST_FREE;
siop_start(sc);
CALL_SCRIPT(Ent_script_sched);
return 1;
}
#ifdef SIOP_DEBUG_INTR
printf("done, DSA=0x%lx target id 0x%x last msg "
- "in=0x%x status=0x%x\n", (u_long)siop_cmd->dsa,
- letoh32(siop_cmd->siop_tables.id),
- siop_cmd->siop_tables.msg_in[0],
- letoh32(siop_cmd->siop_tables.status));
+ "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa,
+ letoh32(siop_cmd->cmd_tables->id),
+ siop_cmd->cmd_tables->msg_in[0],
+ letoh32(siop_cmd->cmd_tables->status));
#endif
INCSTAT(siop_stat_intr_done);
- if (siop_cmd->status == CMDST_SENSE_ACTIVE)
- siop_cmd->status = CMDST_SENSE_DONE;
+ if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
+ siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
else
- siop_cmd->status = CMDST_DONE;
+ siop_cmd->cmd_c.status = CMDST_DONE;
goto end;
default:
printf("unknown irqcode %x\n", irqcode);
@@ -954,29 +980,25 @@ scintr:
printf("%s: siop_intr() - we should not be here!\n"
" istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n"
" need_reset = %x, irqcode = %x, siop_cmd %s\n",
- sc->sc_dev.dv_xname,
+ sc->sc_c.sc_dev.dv_xname,
istat, dstat, sist, sstat1, need_reset, irqcode,
(siop_cmd == NULL) ? "== NULL" : "!= NULL");
goto reset; /* Where we should have gone in the first place! */
end:
/*
- * Restart the script now if command completed properly.
- * Otherwise wait for siop_scsicmd_end(), it may need to put
- * a cmd at the front of the queue.
+ * restart the script now if command completed properly
+ * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
+ * queue
*/
- if (letoh32(siop_cmd->siop_tables.status) == SCSI_OK &&
- TAILQ_FIRST(&sc->urgent_list) != NULL)
+ xs->status = letoh32(siop_cmd->cmd_tables->status);
+ if (xs->status == SCSI_OK)
CALL_SCRIPT(Ent_script_sched);
else
restart = 1;
- siop_scsicmd_end(siop_cmd);
siop_lun->siop_tag[tag].active = NULL;
- if (siop_cmd->status == CMDST_FREE) {
- TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
- siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
- if (freetarget && siop_target->status == TARST_PROBING)
- siop_del_dev(sc, target, lun);
- }
+ siop_scsicmd_end(siop_cmd);
+ if (freetarget && siop_target->target_c.status == TARST_PROBING)
+ siop_del_dev(sc, target, lun);
siop_start(sc);
if (restart)
CALL_SCRIPT(Ent_script_sched);
@@ -987,30 +1009,35 @@ void
siop_scsicmd_end(siop_cmd)
struct siop_cmd *siop_cmd;
{
- struct scsi_xfer *xs = siop_cmd->xs;
- struct siop_softc *sc = siop_cmd->siop_sc;
+ struct scsi_xfer *xs = siop_cmd->cmd_c.xs;
+ struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
+ struct siop_lun *siop_lun =
+ ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun];
+
+ /*
+ * If the command is re-queued (SENSE, QUEUE_FULL) it
+ * must get a new timeout, so delete existing timeout now.
+ */
+ timeout_del(&siop_cmd->cmd_c.xs->stimeout);
- switch(letoh32(siop_cmd->siop_tables.status)) {
+ switch(xs->status) {
case SCSI_OK:
- xs->error = (siop_cmd->status == CMDST_DONE) ?
+ xs->error = (siop_cmd->cmd_c.status == CMDST_DONE) ?
XS_NOERROR : XS_SENSE;
break;
case SCSI_BUSY:
xs->error = XS_BUSY;
break;
case SCSI_CHECK:
- if (siop_cmd->status == CMDST_SENSE_DONE) {
+ if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
/* request sense on a request sense ? */
printf("request sense failed\n");
xs->error = XS_DRIVER_STUFFUP;
} else {
- siop_cmd->status = CMDST_SENSE;
+ siop_cmd->cmd_c.status = CMDST_SENSE;
}
break;
case SCSI_QUEUE_FULL:
- {
- struct siop_lun *siop_lun = siop_cmd->siop_target->siop_lun[
- xs->sc_link->lun];
/*
* Device didn't queue the command. We have to retry
* it. We insert it into the urgent list, hoping to
@@ -1021,17 +1048,16 @@ siop_scsicmd_end(siop_cmd)
*/
INCSTAT(siop_stat_intr_qfull);
#ifdef SIOP_DEBUG
- printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_dev.dv_xname,
+ printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname,
xs->sc_link->target,
- xs->sc_link->lun, siop_cmd->tag);
+ xs->sc_link->lun, siop_cmd->cmd_c.tag);
#endif
- timeout_del(&xs->stimeout);
siop_lun->lun_flags |= SIOP_LUNF_FULL;
- siop_cmd->status = CMDST_READY;
- siop_setuptables(siop_cmd);
+ siop_cmd->cmd_c.status = CMDST_READY;
+ siop_setuptables(&siop_cmd->cmd_c);
+ siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
return;
- }
case SCSI_SIOP_NOCHECK:
/*
* don't check status, xs->error is already valid
@@ -1047,66 +1073,68 @@ siop_scsicmd_end(siop_cmd)
default:
xs->error = XS_DRIVER_STUFFUP;
}
- if (siop_cmd->status != CMDST_SENSE_DONE &&
+ if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE &&
xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,
- 0, siop_cmd->dmamap_data->dm_mapsize,
+ bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,
+ siop_cmd->cmd_c.dmamap_data->dm_mapsize,
(xs->flags & SCSI_DATA_IN) ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
+ bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
}
- bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
- if (siop_cmd->status == CMDST_SENSE) {
+ bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd);
+ if (siop_cmd->cmd_c.status == CMDST_SENSE) {
/* issue a request sense for this target */
int error;
- siop_cmd->rs_cmd.opcode = REQUEST_SENSE;
- siop_cmd->rs_cmd.byte2 = xs->sc_link->lun << 5;
- siop_cmd->rs_cmd.unused[0] = siop_cmd->rs_cmd.unused[1] = 0;
- siop_cmd->rs_cmd.length = sizeof(struct scsi_sense_data);
- siop_cmd->rs_cmd.control = 0;
- siop_cmd->flags &= ~CMDFL_TAG;
- error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
- &siop_cmd->rs_cmd, sizeof(struct scsi_sense),
+ siop_cmd->cmd_c.rs_cmd.opcode = REQUEST_SENSE;
+ siop_cmd->cmd_c.rs_cmd.byte2 = xs->sc_link->lun << 5;
+ siop_cmd->cmd_c.rs_cmd.unused[0] = siop_cmd->cmd_c.rs_cmd.unused[1] = 0;
+ siop_cmd->cmd_c.rs_cmd.length = sizeof(struct scsi_sense_data);
+ siop_cmd->cmd_c.rs_cmd.control = 0;
+ siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
+ error = bus_dmamap_load(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd,
+ &siop_cmd->cmd_c.rs_cmd, sizeof(struct scsi_sense),
NULL, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to load cmd DMA map "
"(for SENSE): %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
goto out;
}
- error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
+ error = bus_dmamap_load(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
&xs->sense, sizeof(struct scsi_sense_data),
NULL, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to load data DMA map "
"(for SENSE): %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
- bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
+ bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd);
goto out;
}
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,
- 0, siop_cmd->dmamap_data->dm_mapsize,
+ bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
+ 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
BUS_DMASYNC_PREREAD);
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd,
- 0, siop_cmd->dmamap_cmd->dm_mapsize,
+ bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd,
+ 0, siop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
BUS_DMASYNC_PREWRITE);
- siop_setuptables(siop_cmd);
+ siop_setuptables(&siop_cmd->cmd_c);
+ siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* arrange for the cmd to be handled now */
TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);
return;
- } else if (siop_cmd->status == CMDST_SENSE_DONE) {
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,
- 0, siop_cmd->dmamap_data->dm_mapsize,
+ } else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
+ bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
+ 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
+ bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
}
out:
- timeout_del(&siop_cmd->xs->stimeout);
- siop_cmd->status = CMDST_FREE;
+ siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
xs->flags |= ITSDONE;
+ siop_cmd->cmd_c.status = CMDST_FREE;
+ TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
xs->resid = 0;
scsi_done(xs);
}
@@ -1119,34 +1147,35 @@ int
siop_handle_qtag_reject(siop_cmd)
struct siop_cmd *siop_cmd;
{
- struct siop_softc *sc = siop_cmd->siop_sc;
- int target = siop_cmd->xs->sc_link->target;
- int lun = siop_cmd->xs->sc_link->lun;
- int tag = siop_cmd->siop_tables.msg_out[2];
- struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];
+ struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
+ int target = siop_cmd->cmd_c.xs->sc_link->target;
+ int lun = siop_cmd->cmd_c.xs->sc_link->lun;
+ int tag = siop_cmd->cmd_tables->msg_out[2];
+ struct siop_lun *siop_lun =
+ ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
#ifdef SIOP_DEBUG
printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
- sc->sc_dev.dv_xname, target, lun, tag, siop_cmd->tag,
- siop_cmd->status);
+ sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag,
+ siop_cmd->cmd_c.status);
#endif
if (siop_lun->siop_tag[0].active != NULL) {
printf("%s: untagged command already running for target %d "
- "lun %d (status %d)\n", sc->sc_dev.dv_xname, target, lun,
- siop_lun->siop_tag[0].active->status);
+ "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
+ target, lun, siop_lun->siop_tag[0].active->cmd_c.status);
return -1;
}
/* clear tag slot */
siop_lun->siop_tag[tag].active = NULL;
/* add command to non-tagged slot */
siop_lun->siop_tag[0].active = siop_cmd;
- siop_cmd->tag = 0;
+ siop_cmd->cmd_c.tag = 0;
/* adjust reselect script if there is one */
if (siop_lun->siop_tag[0].reseloff > 0) {
siop_script_write(sc,
siop_lun->siop_tag[0].reseloff + 1,
- siop_cmd->dsa + sizeof(struct siop_xfer_common) +
+ siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) +
Ent_ldsa_reload_dsa);
siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
}
@@ -1154,9 +1183,9 @@ siop_handle_qtag_reject(siop_cmd)
}
/*
- * Handle a bus reset: reset chip, unqueue all active commands, free all
- * target structs and report losage to upper layer.
- * As the upper layer may requeue immediately we have to first store
+ * handle a bus reset: reset chip, unqueue all active commands, free all
+ * target struct and report loosage to upper layer.
+ * As the upper layer may requeue immediatly we have to first store
* all active commands in a temporary queue.
*/
void
@@ -1168,49 +1197,59 @@ siop_handle_reset(sc)
struct siop_lun *siop_lun;
int target, lun, tag;
/*
- * SCSI bus reset. Reset the chip and restart
- * the queue. Need to clean up all active commands.
+ * scsi bus reset. reset the chip and restart
+ * the queue. Need to clean up all active commands
*/
- printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);
+ printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
/* stop, reset and restart the chip */
siop_reset(sc);
TAILQ_INIT(&reset_list);
/*
* Process all commands: first commmands being executed
*/
- for (target = 0; target < sc->sc_link.adapter_buswidth;
+ for (target = 0; target < sc->sc_c.sc_link.adapter_buswidth;
target++) {
- if (sc->targets[target] == NULL)
+ if (sc->sc_c.targets[target] == NULL)
continue;
for (lun = 0; lun < 8; lun++) {
- siop_lun = sc->targets[target]->siop_lun[lun];
+ struct siop_target *siop_target =
+ (struct siop_target *)sc->sc_c.targets[target];
+ siop_lun = siop_target->siop_lun[lun];
if (siop_lun == NULL)
continue;
siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
for (tag = 0; tag <
- ((sc->targets[target]->flags & TARF_TAG) ?
+ ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
SIOP_NTAG : 1);
tag++) {
siop_cmd = siop_lun->siop_tag[tag].active;
if (siop_cmd == NULL)
continue;
- printf("cmd %p (target %d:%d) in reset list\n",
- siop_cmd, target, lun);
- TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
+ sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
+ printf("command with tag id %d reset\n", tag);
+ siop_cmd->cmd_c.xs->error =
+ (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
+ XS_TIMEOUT : XS_RESET;
+ siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
siop_lun->siop_tag[tag].active = NULL;
+ siop_cmd->cmd_c.status = CMDST_DONE;
+ siop_scsicmd_end(siop_cmd);
}
}
- sc->targets[target]->status = TARST_ASYNC;
- sc->targets[target]->flags = 0;
+ sc->sc_c.targets[target]->status = TARST_ASYNC;
+ sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE;
+ sc->sc_c.targets[target]->period =
+ sc->sc_c.targets[target]->offset = 0;
+ siop_update_xfer_mode(&sc->sc_c, target);
}
/* Next commands from the urgent list */
for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
siop_cmd = next_siop_cmd) {
next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
- siop_cmd->flags &= ~CMDFL_TAG;
+ siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
printf("cmd %p (target %d:%d) in reset list (wait)\n",
- siop_cmd, siop_cmd->xs->sc_link->target,
- siop_cmd->xs->sc_link->lun);
+ siop_cmd, siop_cmd->cmd_c.xs->sc_link->target,
+ siop_cmd->cmd_c.xs->sc_link->lun);
TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
}
@@ -1218,10 +1257,10 @@ siop_handle_reset(sc)
for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
siop_cmd = next_siop_cmd) {
next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
- siop_cmd->flags &= ~CMDFL_TAG;
+ siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
printf("cmd %p (target %d:%d) in reset list (wait)\n",
- siop_cmd, siop_cmd->xs->sc_link->target,
- siop_cmd->xs->sc_link->lun);
+ siop_cmd, siop_cmd->cmd_c.xs->sc_link->target,
+ siop_cmd->cmd_c.xs->sc_link->lun);
TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
}
@@ -1229,16 +1268,16 @@ siop_handle_reset(sc)
for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
siop_cmd = next_siop_cmd) {
next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
- siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?
+ siop_cmd->cmd_c.xs->error = (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
XS_TIMEOUT : XS_RESET;
- siop_cmd->siop_tables.status = htole32(SCSI_SIOP_NOCHECK);
+ siop_cmd->cmd_tables->status = htole32(SCSI_SIOP_NOCHECK);
printf("cmd %p (status %d) about to be processed\n", siop_cmd,
- siop_cmd->status);
- if (siop_cmd->status == CMDST_SENSE ||
- siop_cmd->status == CMDST_SENSE_ACTIVE)
- siop_cmd->status = CMDST_SENSE_DONE;
+ siop_cmd->cmd_c.status);
+ if (siop_cmd->cmd_c.status == CMDST_SENSE ||
+ siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
+ siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
else
- siop_cmd->status = CMDST_DONE;
+ siop_cmd->cmd_c.status = CMDST_DONE;
TAILQ_REMOVE(&reset_list, siop_cmd, next);
siop_scsicmd_end(siop_cmd);
TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
@@ -1251,113 +1290,127 @@ siop_scsicmd(xs)
{
struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
struct siop_cmd *siop_cmd;
+ struct siop_target *siop_target;
int s, error, i, j;
const int target = xs->sc_link->target;
const int lun = xs->sc_link->lun;
s = splbio();
#ifdef SIOP_DEBUG_SCHED
- printf("starting cmd 0x%02x for %d:%d\n", xs->cmd->opcode, target, lun);
+ printf("starting cmd for %d:%d\n", target, lun);
#endif
siop_cmd = TAILQ_FIRST(&sc->free_list);
- if (siop_cmd != NULL) {
- TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
- } else {
+ if (siop_cmd == NULL) {
xs->error = XS_DRIVER_STUFFUP;
splx(s);
return(TRY_AGAIN_LATER);
}
+ TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
/* Always reset xs->stimeout, lest we timeout_del() with trash */
timeout_set(&xs->stimeout, siop_timeout, siop_cmd);
#ifdef DIAGNOSTIC
- if (siop_cmd->status != CMDST_FREE)
+ if (siop_cmd->cmd_c.status != CMDST_FREE)
panic("siop_scsicmd: new cmd not free");
#endif
- if (sc->targets[target] == NULL) {
+ siop_target = (struct siop_target*)sc->sc_c.targets[target];
+ if (siop_target == NULL) {
#ifdef SIOP_DEBUG
printf("%s: alloc siop_target for target %d\n",
- sc->sc_dev.dv_xname, target);
+ sc->sc_c.sc_dev.dv_xname, target);
#endif
- sc->targets[target] =
- malloc(sizeof(struct siop_target), M_DEVBUF, M_NOWAIT);
- if (sc->targets[target] == NULL) {
- printf("%s: can't malloc memory for target %d\n",
- sc->sc_dev.dv_xname, target);
+ sc->sc_c.targets[target] =
+ malloc(sizeof(struct siop_target),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_c.targets[target] == NULL) {
+ printf("%s: can't malloc memory for "
+ "target %d\n", sc->sc_c.sc_dev.dv_xname,
+ target);
xs->error = XS_DRIVER_STUFFUP;
splx(s);
return(TRY_AGAIN_LATER);
}
- sc->targets[target]->status = TARST_PROBING;
- sc->targets[target]->flags = 0;
- sc->targets[target]->id = sc->clock_div << 24; /* scntl3 */
- sc->targets[target]->id |= target << 16; /* id */
- /* sc->targets[target]->id |= 0x0 << 8; scxfer is 0 */
+ siop_target =
+ (struct siop_target*)sc->sc_c.targets[target];
+ siop_target->target_c.status = TARST_PROBING;
+ siop_target->target_c.flags = 0;
+ siop_target->target_c.id =
+ sc->sc_c.clock_div << 24; /* scntl3 */
+ siop_target->target_c.id |= target << 16; /* id */
+ /* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
/* get a lun switch script */
- sc->targets[target]->lunsw = siop_get_lunsw(sc);
- if (sc->targets[target]->lunsw == NULL) {
+ siop_target->lunsw = siop_get_lunsw(sc);
+ if (siop_target->lunsw == NULL) {
printf("%s: can't alloc lunsw for target %d\n",
- sc->sc_dev.dv_xname, target);
+ sc->sc_c.sc_dev.dv_xname, target);
xs->error = XS_DRIVER_STUFFUP;
splx(s);
return(TRY_AGAIN_LATER);
}
for (i=0; i < 8; i++)
- sc->targets[target]->siop_lun[i] = NULL;
+ siop_target->siop_lun[i] = NULL;
siop_add_reselsw(sc, target);
}
-
- if (sc->targets[target]->siop_lun[lun] == NULL) {
- sc->targets[target]->siop_lun[lun] =
- malloc(sizeof(struct siop_lun), M_DEVBUF, M_NOWAIT);
- if (sc->targets[target]->siop_lun[lun] == NULL) {
- printf("%s: can't alloc siop_lun for target %d "
- "lun %d\n", sc->sc_dev.dv_xname, target, lun);
+ if (siop_target->siop_lun[lun] == NULL) {
+ siop_target->siop_lun[lun] =
+ malloc(sizeof(struct siop_lun), M_DEVBUF,
+ M_NOWAIT);
+ if (siop_target->siop_lun[lun] == NULL) {
+ printf("%s: can't alloc siop_lun for "
+ "target %d lun %d\n",
+ sc->sc_c.sc_dev.dv_xname, target, lun);
xs->error = XS_DRIVER_STUFFUP;
splx(s);
return(TRY_AGAIN_LATER);
}
- memset(sc->targets[target]->siop_lun[lun], 0,
- sizeof(struct siop_lun));
+ bzero(siop_target->siop_lun[lun], sizeof(struct siop_lun));
}
- siop_cmd->siop_target = sc->targets[target];
- siop_cmd->xs = xs;
- siop_cmd->flags = 0;
- siop_cmd->status = CMDST_READY;
+ siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
+ siop_cmd->cmd_c.xs = xs;
+ siop_cmd->cmd_c.flags = 0;
+ siop_cmd->cmd_c.status = CMDST_READY;
/* load the DMA maps */
- error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
+ error = bus_dmamap_load(sc->sc_c.sc_dmat,
+ siop_cmd->cmd_c.dmamap_cmd,
xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to load cmd DMA map: %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
splx(s);
return(TRY_AGAIN_LATER);
}
if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
- error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
- xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load(sc->sc_c.sc_dmat,
+ siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
+ NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
+ ((xs->flags & SCSI_DATA_IN) ?
+ BUS_DMA_READ : BUS_DMA_WRITE));
if (error) {
printf("%s: unable to load cmd DMA map: %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
xs->error = XS_DRIVER_STUFFUP;
- bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
+ bus_dmamap_unload(sc->sc_c.sc_dmat,
+ siop_cmd->cmd_c.dmamap_cmd);
splx(s);
return(TRY_AGAIN_LATER);
}
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data,
- 0, siop_cmd->dmamap_data->dm_mapsize,
+ bus_dmamap_sync(sc->sc_c.sc_dmat,
+ siop_cmd->cmd_c.dmamap_data, 0,
+ siop_cmd->cmd_c.dmamap_data->dm_mapsize,
(xs->flags & SCSI_DATA_IN) ?
BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd,
- 0, siop_cmd->dmamap_cmd->dm_mapsize,
+ bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd, 0,
+ siop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
BUS_DMASYNC_PREWRITE);
- siop_setuptables(siop_cmd);
+ siop_setuptables(&siop_cmd->cmd_c);
+ siop_table_sync(siop_cmd,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
@@ -1373,16 +1426,23 @@ siop_scsicmd(xs)
if (error != SID_QUAL_BAD_LU) {
/*
* Allocate enough commands to hold at least max openings
- * worth of commands. Do this statically now because
+ * worth of commands. Do this statically now 'cuz
* a) We can't rely on the upper layers to ask for more
* b) Doing it dynamically in siop_startcmd may cause
* calls to bus_dma* functions in interrupt context
*/
for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB)
siop_morecbd(sc);
- if (sc->targets[target]->status == TARST_PROBING)
- sc->targets[target]->status = TARST_ASYNC;
+ if (sc->sc_c.targets[target]->status == TARST_PROBING)
+ sc->sc_c.targets[target]->status = TARST_ASYNC;
+
+ /* Set TARF_DT here because if it is turned off during PPR, it must STAY off! */
+ if ((lun == 0) &&
+ (((struct scsi_inquiry_data *)xs->data)->flags2 & SID_CLOCKING) &&
+ (sc->sc_c.features & SF_BUS_ULTRA3))
+ sc->sc_c.targets[target]->flags |= TARF_DT;
/* Can't do lun 0 here, because flags not set yet */
+ /* But have to do other lun's here because they never go through TARST_ASYNC */
if (lun > 0)
siop_add_dev(sc, target, lun);
}
@@ -1412,6 +1472,7 @@ siop_start(sc)
{
struct siop_cmd *siop_cmd, *next_siop_cmd;
struct siop_lun *siop_lun;
+ struct siop_xfer *siop_xfer;
u_int32_t dsa;
int timeout;
int target, lun, tag, slot;
@@ -1425,7 +1486,7 @@ siop_start(sc)
/*
* The queue management here is a bit tricky: the script always looks
- * at the slots from first to last, so if we always use the first
+ * at the slot from first to last, so if we always use the first
* free slot commands can stay at the tail of the queue ~forever.
* The algorithm used here is to restart from the head when we know
* that the queue is empty, and only add commands after the last one.
@@ -1453,13 +1514,14 @@ again:
for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {
next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
#ifdef DIAGNOSTIC
- if (siop_cmd->status != CMDST_READY &&
- siop_cmd->status != CMDST_SENSE)
+ if (siop_cmd->cmd_c.status != CMDST_READY &&
+ siop_cmd->cmd_c.status != CMDST_SENSE)
panic("siop: non-ready cmd in ready list");
#endif
- target = siop_cmd->xs->sc_link->target;
- lun = siop_cmd->xs->sc_link->lun;
- siop_lun = sc->targets[target]->siop_lun[lun];
+ target = siop_cmd->cmd_c.xs->sc_link->target;
+ lun = siop_cmd->cmd_c.xs->sc_link->lun;
+ siop_lun =
+ ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
/* if non-tagged command active, wait */
if (siop_lun->siop_tag[0].active != NULL)
continue;
@@ -1468,10 +1530,10 @@ again:
* command, unless it's a request sense
*/
if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&
- siop_cmd->status == CMDST_READY)
+ siop_cmd->cmd_c.status == CMDST_READY)
continue;
/* find a free tag if needed */
- if (siop_cmd->flags & CMDFL_TAG) {
+ if (siop_cmd->cmd_c.flags & CMDFL_TAG) {
for (tag = 1; tag < SIOP_NTAG; tag++) {
if (siop_lun->siop_tag[tag].active == NULL)
break;
@@ -1481,12 +1543,12 @@ again:
} else {
tag = 0;
}
- siop_cmd->tag = tag;
+ siop_cmd->cmd_c.tag = tag;
/*
* find a free scheduler slot and load it. If it's a request
* sense we need to use slot 0.
*/
- if (siop_cmd->status != CMDST_SENSE) {
+ if (siop_cmd->cmd_c.status != CMDST_SENSE) {
for (; slot < SIOP_NSLOTS; slot++) {
/*
* If cmd if 0x80000000 the slot is free
@@ -1509,35 +1571,35 @@ again:
#ifdef SIOP_DEBUG_SCHED
printf("using slot %d for DSA 0x%lx\n", slot,
- (u_long)siop_cmd->dsa);
+ (u_long)siop_cmd->cmd_c.dsa);
#endif
/* Ok, we can add the tag message */
if (tag > 0) {
#ifdef DIAGNOSTIC
int msgcount =
- letoh32(siop_cmd->siop_tables.t_msgout.count);
+ letoh32(siop_cmd->cmd_tables->t_msgout.count);
if (msgcount != 1)
printf("%s:%d:%d: tag %d with msgcount %d\n",
- sc->sc_dev.dv_xname, target, lun, tag,
+ sc->sc_c.sc_dev.dv_xname, target, lun, tag,
msgcount);
#endif
- if (siop_cmd->xs->bp != NULL &&
- (siop_cmd->xs->bp->b_flags & B_ASYNC))
- siop_cmd->siop_tables.msg_out[1] =
+ if (siop_cmd->cmd_c.xs->bp != NULL &&
+ (siop_cmd->cmd_c.xs->bp->b_flags & B_ASYNC))
+ siop_cmd->cmd_tables->msg_out[1] =
MSG_SIMPLE_Q_TAG;
else
- siop_cmd->siop_tables.msg_out[1] =
+ siop_cmd->cmd_tables->msg_out[1] =
MSG_ORDERED_Q_TAG;
- siop_cmd->siop_tables.msg_out[2] = tag;
- siop_cmd->siop_tables.t_msgout.count = htole32(3);
+ siop_cmd->cmd_tables->msg_out[2] = tag;
+ siop_cmd->cmd_tables->t_msgout.count = htole32(3);
}
/* note that we started a new command */
newcmd = 1;
/* mark command as active */
- if (siop_cmd->status == CMDST_READY) {
- siop_cmd->status = CMDST_ACTIVE;
- } else if (siop_cmd->status == CMDST_SENSE) {
- siop_cmd->status = CMDST_SENSE_ACTIVE;
+ if (siop_cmd->cmd_c.status == CMDST_READY) {
+ siop_cmd->cmd_c.status = CMDST_ACTIVE;
+ } else if (siop_cmd->cmd_c.status == CMDST_SENSE) {
+ siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE;
} else
panic("siop_start: bad status");
if (doingready)
@@ -1546,31 +1608,31 @@ again:
TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
siop_lun->siop_tag[tag].active = siop_cmd;
/* patch scripts with DSA addr */
- dsa = siop_cmd->dsa;
+ dsa = siop_cmd->cmd_c.dsa;
/* first reselect switch, if we have an entry */
if (siop_lun->siop_tag[tag].reseloff > 0)
siop_script_write(sc,
siop_lun->siop_tag[tag].reseloff + 1,
- dsa + sizeof(struct siop_xfer_common) +
+ dsa + sizeof(struct siop_common_xfer) +
Ent_ldsa_reload_dsa);
/* CMD script: MOVE MEMORY addr */
- siop_cmd->siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
- htole32(sc->sc_scriptaddr + Ent_script_sched_slot0 +
- slot * 8);
+ siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables;
+ siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
+ htole32(sc->sc_c.sc_scriptaddr + Ent_script_sched_slot0 + slot * 8);
siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
/* scheduler slot: JUMP ldsa_select */
siop_script_write(sc,
(Ent_script_sched_slot0 / 4) + slot * 2 + 1,
- dsa + sizeof(struct siop_xfer_common) + Ent_ldsa_select);
+ dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select);
/* handle timeout */
- if (siop_cmd->status == CMDST_ACTIVE) {
- if ((siop_cmd->xs->flags & SCSI_POLL) == 0) {
+ if (siop_cmd->cmd_c.status == CMDST_ACTIVE) {
+ if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL) == 0) {
/* start expire timer */
- timeout = (u_int64_t) siop_cmd->xs->timeout *
+ timeout = (u_int64_t) siop_cmd->cmd_c.xs->timeout *
(u_int64_t)hz / 1000;
if (timeout == 0)
timeout = 1;
- timeout_add(&siop_cmd->xs->stimeout, timeout);
+ timeout_add(&siop_cmd->cmd_c.xs->stimeout, timeout);
}
}
/*
@@ -1598,7 +1660,8 @@ end:
/* make sure SCRIPT processor will read valid data */
siop_script_sync(sc,BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/* Signal script it has some work to do */
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);
+ bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_ISTAT, ISTAT_SIGP);
/* and wait for IRQ */
return;
}
@@ -1608,24 +1671,24 @@ siop_timeout(v)
void *v;
{
struct siop_cmd *siop_cmd = v;
- struct siop_softc *sc = siop_cmd->siop_sc;
+ struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
int s;
- sc_print_addr(siop_cmd->xs->sc_link);
- printf("timeout on SCSI command 0x%x\n", siop_cmd->xs->cmd->opcode);
+ sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
+ printf("timeout on SCSI command 0x%x\n", siop_cmd->cmd_c.xs->cmd->opcode);
s = splbio();
/* reset the scsi bus */
- siop_resetbus(sc);
+ siop_resetbus(&sc->sc_c);
/* deactivate callout */
- timeout_del(&siop_cmd->xs->stimeout);
+ timeout_del(&siop_cmd->cmd_c.xs->stimeout);
/*
- * Mark command as being timed out and just return. The bus
- * reset will generate an interrupt, which will be handled
- * in siop_intr().
+ * mark command has being timed out and just return;
+ * the bus reset will generate an interrupt,
+ * it will be handled in siop_intr()
*/
- siop_cmd->flags |= CMDFL_TIMEOUT;
+ siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
splx(s);
return;
@@ -1638,23 +1701,26 @@ siop_dump_script(sc)
int i;
for (i = 0; i < PAGE_SIZE / 4; i += 2) {
printf("0x%04x: 0x%08x 0x%08x", i * 4,
- letoh32(sc->sc_script[i]), letoh32(sc->sc_script[i+1]));
- if ((letoh32(sc->sc_script[i]) & 0xe0000000) == 0xc0000000) {
+ letoh32(sc->sc_c.sc_script[i]),
+ letoh32(sc->sc_c.sc_script[i+1]));
+ if ((letoh32(sc->sc_c.sc_script[i]) & 0xe0000000) ==
+ 0xc0000000) {
i++;
- printf(" 0x%08x", letoh32(sc->sc_script[i+1]));
+ printf(" 0x%08x", letoh32(sc->sc_c.sc_script[i+1]));
}
printf("\n");
}
}
-int
+void
siop_morecbd(sc)
struct siop_softc *sc;
{
- int error, i, j;
+ int error, i, j, s;
bus_dma_segment_t seg;
int rseg;
struct siop_cbd *newcbd;
+ struct siop_xfer *xfer;
bus_addr_t dsa;
u_int32_t *scr;
@@ -1662,96 +1728,100 @@ siop_morecbd(sc)
newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT);
if (newcbd == NULL) {
printf("%s: can't allocate memory for command descriptors "
- "head\n", sc->sc_dev.dv_xname);
- return ENOMEM;
+ "head\n", sc->sc_c.sc_dev.dv_xname);
+ return;
}
- memset(newcbd, 0, sizeof(struct siop_cbd));
+ bzero(newcbd, sizeof(struct siop_cbd));
/* allocate cmd list */
- newcbd->cmds =
- malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB, M_DEVBUF, M_NOWAIT);
+ newcbd->cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB,
+ M_DEVBUF, M_NOWAIT);
if (newcbd->cmds == NULL) {
printf("%s: can't allocate memory for command descriptors\n",
- sc->sc_dev.dv_xname);
- error = ENOMEM;
+ sc->sc_c.sc_dev.dv_xname);
goto bad3;
}
- memset(newcbd->cmds, 0, sizeof(struct siop_cmd) * SIOP_NCMDPB);
- error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &seg,
+ bzero(newcbd->cmds, sizeof(struct siop_cmd) * SIOP_NCMDPB);
+ error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &seg,
1, &rseg, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to allocate cbd DMA memory, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad2;
}
- error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, PAGE_SIZE,
+ error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
(caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
if (error) {
printf("%s: unable to map cbd DMA memory, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad2;
}
- error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
+ error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
BUS_DMA_NOWAIT, &newcbd->xferdma);
if (error) {
printf("%s: unable to create cbd DMA map, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad1;
}
- error = bus_dmamap_load(sc->sc_dmat, newcbd->xferdma, newcbd->xfers,
+ error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, newcbd->xfers,
PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
if (error) {
printf("%s: unable to load cbd DMA map, error = %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad0;
}
#ifdef DEBUG
- printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_dev.dv_xname,
+ printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
(unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
#endif
-
for (i = 0; i < SIOP_NCMDPB; i++) {
- error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SIOP_NSG,
+ error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
- &newcbd->cmds[i].dmamap_data);
+ &newcbd->cmds[i].cmd_c.dmamap_data);
if (error) {
printf("%s: unable to create data DMA map for cbd: "
"error %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad0;
}
- error = bus_dmamap_create(sc->sc_dmat,
+ error = bus_dmamap_create(sc->sc_c.sc_dmat,
sizeof(struct scsi_generic), 1,
sizeof(struct scsi_generic), 0,
BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
- &newcbd->cmds[i].dmamap_cmd);
+ &newcbd->cmds[i].cmd_c.dmamap_cmd);
if (error) {
printf("%s: unable to create cmd DMA map for cbd %d\n",
- sc->sc_dev.dv_xname, error);
+ sc->sc_c.sc_dev.dv_xname, error);
goto bad0;
}
- newcbd->cmds[i].siop_sc = sc;
+ }
+
+ /* Use two loops since bailing out above releases allocated memory */
+ for (i = 0; i < SIOP_NCMDPB; i++) {
+ newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
newcbd->cmds[i].siop_cbdp = newcbd;
- newcbd->cmds[i].siop_xfer = &newcbd->xfers[i];
- memset(newcbd->cmds[i].siop_xfer, 0,
- sizeof(struct siop_xfer));
- newcbd->cmds[i].dsa = newcbd->xferdma->dm_segs[0].ds_addr +
+ xfer = &newcbd->xfers[i];
+ newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
+ bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer));
+ dsa = newcbd->xferdma->dm_segs[0].ds_addr +
i * sizeof(struct siop_xfer);
- dsa = newcbd->cmds[i].dsa;
- newcbd->cmds[i].status = CMDST_FREE;
- newcbd->cmds[i].siop_tables.t_msgout.count= htole32(1);
- newcbd->cmds[i].siop_tables.t_msgout.addr = htole32(dsa);
- newcbd->cmds[i].siop_tables.t_msgin.count= htole32(1);
- newcbd->cmds[i].siop_tables.t_msgin.addr = htole32(dsa + 16);
- newcbd->cmds[i].siop_tables.t_extmsgin.count= htole32(2);
- newcbd->cmds[i].siop_tables.t_extmsgin.addr = htole32(dsa + 17);
- newcbd->cmds[i].siop_tables.t_extmsgdata.addr =
- htole32(dsa + 19);
- newcbd->cmds[i].siop_tables.t_status.count= htole32(1);
- newcbd->cmds[i].siop_tables.t_status.addr = htole32(dsa + 32);
-
+ newcbd->cmds[i].cmd_c.dsa = dsa;
+ newcbd->cmds[i].cmd_c.status = CMDST_FREE;
+ xfer->siop_tables.t_msgout.count= htole32(1);
+ xfer->siop_tables.t_msgout.addr = htole32(dsa);
+ xfer->siop_tables.t_msgin.count= htole32(1);
+ xfer->siop_tables.t_msgin.addr = htole32(dsa +
+ offsetof(struct siop_common_xfer, msg_in));
+ xfer->siop_tables.t_extmsgin.count= htole32(2);
+ xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
+ offsetof(struct siop_common_xfer, msg_in) + 1);
+ xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
+ offsetof(struct siop_common_xfer, msg_in) + 3);
+ xfer->siop_tables.t_status.count= htole32(1);
+ xfer->siop_tables.t_status.addr = htole32(dsa +
+ offsetof(struct siop_common_xfer, status));
/* The select/reselect script */
- scr = &newcbd->cmds[i].siop_xfer->resel[0];
+ scr = &xfer->resel[0];
for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
scr[j] = htole32(load_dsa[j]);
/*
@@ -1767,35 +1837,41 @@ siop_morecbd(sc)
scr[Ent_rdsa3 / 4] =
htole32(0x78130000 | ((dsa & 0xff000000) >> 16));
scr[E_ldsa_abs_reselected_Used[0]] =
- htole32(sc->sc_scriptaddr + Ent_reselected);
+ htole32(sc->sc_c.sc_scriptaddr + Ent_reselected);
scr[E_ldsa_abs_reselect_Used[0]] =
- htole32(sc->sc_scriptaddr + Ent_reselect);
+ htole32(sc->sc_c.sc_scriptaddr + Ent_reselect);
scr[E_ldsa_abs_selected_Used[0]] =
- htole32(sc->sc_scriptaddr + Ent_selected);
+ htole32(sc->sc_c.sc_scriptaddr + Ent_selected);
scr[E_ldsa_abs_data_Used[0]] =
- htole32(dsa + sizeof(struct siop_xfer_common) +
+ htole32(dsa + sizeof(struct siop_common_xfer) +
Ent_ldsa_data);
/* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
scr[Ent_ldsa_data / 4] = htole32(0x80000000);
+ s = splbio();
TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
+ splx(s);
#ifdef SIOP_DEBUG
printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
- letoh32(newcbd->cmds[i].siop_tables.t_msgin.addr),
- letoh32(newcbd->cmds[i].siop_tables.t_msgout.addr),
- letoh32(newcbd->cmds[i].siop_tables.t_status.addr));
+ letoh32(newcbd->cmds[i].cmd_tables->t_msgin.addr),
+ letoh32(newcbd->cmds[i].cmd_tables->t_msgout.addr),
+ letoh32(newcbd->cmds[i].cmd_tables->t_status.addr));
#endif
}
+ s = splbio();
TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
- return 0;
+ sc->sc_c.sc_link.openings += SIOP_NCMDPB;
+ splx(s);
+ return;
bad0:
- bus_dmamap_destroy(sc->sc_dmat, newcbd->xferdma);
+ bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
+ bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
bad1:
- bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
bad2:
free(newcbd->cmds, M_DEVBUF);
bad3:
free(newcbd, M_DEVBUF);
- return error;
+ return;
}
struct siop_lunsw *
@@ -1820,31 +1896,29 @@ siop_get_lunsw(sc)
lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT);
if (lunsw == NULL)
return NULL;
- memset(lunsw, 0, sizeof(struct siop_lunsw));
+ bzero(lunsw, sizeof(struct siop_lunsw));
#ifdef SIOP_DEBUG
printf("allocating lunsw at offset %d\n", sc->script_free_lo);
#endif
- if (sc->features & SF_CHIP_RAM) {
- bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh,
+ if (sc->sc_c.features & SF_CHIP_RAM) {
+ bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
sc->script_free_lo * 4, lun_switch,
sizeof(lun_switch) / sizeof(lun_switch[0]));
- bus_space_write_4(sc->sc_ramt, sc->sc_ramh,
+ bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
(sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
- sc->sc_scriptaddr + Ent_lunsw_return);
+ sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
} else {
for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
i++)
- sc->sc_script[sc->script_free_lo + i] =
+ sc->sc_c.sc_script[sc->script_free_lo + i] =
htole32(lun_switch[i]);
- sc->sc_script[sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
- htole32(sc->sc_scriptaddr + Ent_lunsw_return);
+ sc->sc_c.sc_script[
+ sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
+ htole32(sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
}
lunsw->lunsw_off = sc->script_free_lo;
lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
sc->script_free_lo += lunsw->lunsw_size;
- if (sc->script_free_lo > 1024)
- printf("%s: script_free_lo (%d) > 1024\n", sc->sc_dev.dv_xname,
- sc->script_free_lo);
siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
return lunsw;
}
@@ -1855,25 +1929,28 @@ siop_add_reselsw(sc, target)
int target;
{
int i;
+ struct siop_target *siop_target;
struct siop_lun *siop_lun;
+
+ siop_target = (struct siop_target *)sc->sc_c.targets[target];
/*
* add an entry to resel switch
*/
siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
for (i = 0; i < 15; i++) {
- sc->targets[target]->reseloff = Ent_resel_targ0 / 4 + i * 2;
- if ((siop_script_read(sc, sc->targets[target]->reseloff) & 0xff)
+ siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2;
+ if ((siop_script_read(sc, siop_target->reseloff) & 0xff)
== 0xff) { /* it's free */
#ifdef SIOP_DEBUG
printf("siop: target %d slot %d offset %d\n",
- target, i, sc->targets[target]->reseloff);
+ target, i, siop_target->reseloff);
#endif
/* JUMP abs_foo, IF target | 0x80; */
- siop_script_write(sc, sc->targets[target]->reseloff,
+ siop_script_write(sc, siop_target->reseloff,
0x800c0080 | target);
- siop_script_write(sc, sc->targets[target]->reseloff + 1,
- sc->sc_scriptaddr +
- sc->targets[target]->lunsw->lunsw_off * 4 +
+ siop_script_write(sc, siop_target->reseloff + 1,
+ sc->sc_c.sc_scriptaddr +
+ siop_target->lunsw->lunsw_off * 4 +
Ent_lun_switch_entry);
break;
}
@@ -1883,7 +1960,7 @@ siop_add_reselsw(sc, target)
sc->sc_ntargets++;
for (i = 0; i < 8; i++) {
- siop_lun = sc->targets[target]->siop_lun[i];
+ siop_lun = siop_target->siop_lun[i];
if (siop_lun == NULL)
continue;
if (siop_lun->reseloff > 0) {
@@ -1891,33 +1968,24 @@ siop_add_reselsw(sc, target)
siop_add_dev(sc, target, i);
}
}
- siop_update_scntl3(sc, sc->targets[target]);
+ siop_update_scntl3(sc, sc->sc_c.targets[target]);
siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
}
void
-siop_update_scntl3(sc, siop_target)
+siop_update_scntl3(sc, _siop_target)
struct siop_softc *sc;
- struct siop_target *siop_target;
+ struct siop_common_target *_siop_target;
{
+ struct siop_target *siop_target = (struct siop_target *)_siop_target;
/* MOVE target->id >> 24 TO SCNTL3 */
siop_script_write(sc,
siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
- 0x78030000 | ((siop_target->id >> 16) & 0x0000ff00));
+ 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00));
/* MOVE target->id >> 8 TO SXFER */
siop_script_write(sc,
siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
- 0x78050000 | (siop_target->id & 0x0000ff00));
- /* If DT, change null op ('MOVE 0xff TO SFBR') to 'MOVE n TO SCNTL4' */
- if (siop_target->flags & TARF_ISDT)
- siop_script_write(sc,
- siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 4,
- 0x78bc0000 | ((siop_target->id << 8) & 0x0000ff00));
- else
- siop_script_write(sc,
- siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 4,
- 0x7808ff00);
-
+ 0x78050000 | (siop_target->target_c.id & 0x0000ff00));
siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
}
@@ -1928,50 +1996,52 @@ siop_add_dev(sc, target, lun)
int lun;
{
struct siop_lunsw *lunsw;
- struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];
+ struct siop_target *siop_target =
+ (struct siop_target *)sc->sc_c.targets[target];
+ struct siop_lun *siop_lun = siop_target->siop_lun[lun];
int i, ntargets;
if (siop_lun->reseloff > 0)
return;
- lunsw = sc->targets[target]->lunsw;
+ lunsw = siop_target->lunsw;
if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
/*
- * Can't extend this slot. Probably not worth trying to deal
- * with this case.
+ * can't extend this slot. Probably not worth trying to deal
+ * with this case
*/
#ifdef DEBUG
printf("%s:%d:%d: can't allocate a lun sw slot\n",
- sc->sc_dev.dv_xname, target, lun);
+ sc->sc_c.sc_dev.dv_xname, target, lun);
#endif
return;
}
/* count how many free targets we still have to probe */
- ntargets = (sc->sc_link.adapter_buswidth - 1) - 1 - sc->sc_ntargets;
+ ntargets = (sc->sc_c.sc_link.adapter_buswidth - 1) - 1 - sc->sc_ntargets;
/*
- * We need 8 bytes for the lun sw additional entry, and
+ * we need 8 bytes for the lun sw additionnal entry, and
* eventually sizeof(tag_switch) for the tag switch entry.
* Keep enough free space for the free targets that could be
* probed later.
*/
if (sc->script_free_lo + 2 +
(ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
- ((sc->targets[target]->flags & TARF_TAG) ?
+ ((siop_target->target_c.flags & TARF_TAG) ?
sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
sc->script_free_hi)) {
/*
- * Not enough space, but probably not worth dealing with it.
+ * not enough space, probably not worth dealing with it.
* We can hold 13 tagged-queuing capable devices in the 4k RAM.
*/
#ifdef DEBUG
printf("%s:%d:%d: not enough memory for a lun sw slot\n",
- sc->sc_dev.dv_xname, target, lun);
+ sc->sc_c.sc_dev.dv_xname, target, lun);
#endif
return;
}
#ifdef SIOP_DEBUG
printf("%s:%d:%d: allocate lun sw entry\n",
- sc->sc_dev.dv_xname, target, lun);
+ sc->sc_c.sc_dev.dv_xname, target, lun);
#endif
/* INT int_resellun */
siop_script_write(sc, sc->script_free_lo, 0x98080000);
@@ -1983,25 +2053,26 @@ siop_add_dev(sc, target, lun)
siop_lun->reseloff = sc->script_free_lo - 2;
lunsw->lunsw_size += 2;
sc->script_free_lo += 2;
- if (sc->targets[target]->flags & TARF_TAG) {
+ if (siop_target->target_c.flags & TARF_TAG) {
/* we need a tag switch */
sc->script_free_hi -=
sizeof(tag_switch) / sizeof(tag_switch[0]);
- if (sc->features & SF_CHIP_RAM) {
- bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh,
+ if (sc->sc_c.features & SF_CHIP_RAM) {
+ bus_space_write_region_4(sc->sc_c.sc_ramt,
+ sc->sc_c.sc_ramh,
sc->script_free_hi * 4, tag_switch,
sizeof(tag_switch) / sizeof(tag_switch[0]));
} else {
for(i = 0;
i < sizeof(tag_switch) / sizeof(tag_switch[0]);
i++) {
- sc->sc_script[sc->script_free_hi + i] =
+ sc->sc_c.sc_script[sc->script_free_hi + i] =
htole32(tag_switch[i]);
}
}
siop_script_write(sc,
siop_lun->reseloff + 1,
- sc->sc_scriptaddr + sc->script_free_hi * 4 +
+ sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 +
Ent_tag_switch_entry);
for (i = 0; i < SIOP_NTAG; i++) {
@@ -2011,7 +2082,7 @@ siop_add_dev(sc, target, lun)
} else {
/* non-tag case; just work with the lun switch */
siop_lun->siop_tag[0].reseloff =
- sc->targets[target]->siop_lun[lun]->reseloff;
+ siop_target->siop_lun[lun]->reseloff;
}
siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
}
@@ -2023,34 +2094,36 @@ siop_del_dev(sc, target, lun)
int lun;
{
int i;
+ struct siop_target *siop_target;
#ifdef SIOP_DEBUG
printf("%s:%d:%d: free lun sw entry\n",
- sc->sc_dev.dv_xname, target, lun);
+ sc->sc_c.sc_dev.dv_xname, target, lun);
#endif
- if (sc->targets[target] == NULL)
+ if (sc->sc_c.targets[target] == NULL)
return;
- free(sc->targets[target]->siop_lun[lun], M_DEVBUF);
- sc->targets[target]->siop_lun[lun] = NULL;
+ siop_target = (struct siop_target *)sc->sc_c.targets[target];
+ free(siop_target->siop_lun[lun], M_DEVBUF);
+ siop_target->siop_lun[lun] = NULL;
/* XXX compact sw entry too ? */
/* check if we can free the whole target */
for (i = 0; i < 8; i++) {
- if (sc->targets[target]->siop_lun[i] != NULL)
+ if (siop_target->siop_lun[i] != NULL)
return;
}
#ifdef SIOP_DEBUG
printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
- sc->sc_dev.dv_xname, target, lun,
- sc->targets[target]->lunsw->lunsw_off);
+ sc->sc_c.sc_dev.dv_xname, target, lun,
+ siop_target->lunsw->lunsw_off);
#endif
/*
* nothing here, free the target struct and resel
* switch entry
*/
- siop_script_write(sc, sc->targets[target]->reseloff, 0x800c00ff);
+ siop_script_write(sc, siop_target->reseloff, 0x800c00ff);
siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
- TAILQ_INSERT_TAIL(&sc->lunsw_list, sc->targets[target]->lunsw, next);
- free(sc->targets[target], M_DEVBUF);
- sc->targets[target] = NULL;
+ TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next);
+ free(sc->sc_c.targets[target], M_DEVBUF);
+ sc->sc_c.targets[target] = NULL;
sc->sc_ntargets--;
}
diff --git a/sys/dev/ic/siop_common.c b/sys/dev/ic/siop_common.c
index 3a217253507..0144b30fa98 100644
--- a/sys/dev/ic/siop_common.c
+++ b/sys/dev/ic/siop_common.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: siop_common.c,v 1.13 2002/03/14 01:26:55 millert Exp $ */
-/* $NetBSD: siop_common.c,v 1.12 2001/02/11 18:04:50 bouyer Exp $ */
+/* $OpenBSD: siop_common.c,v 1.14 2002/09/16 00:53:12 krw Exp $ */
+/* $NetBSD: siop_common.c,v 1.30 2002/08/29 18:23:52 bouyer Exp $ */
/*
- * Copyright (c) 2000 Manuel Bouyer.
+ * Copyright (c) 2000, 2002 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Manuel Bouyer
+ * This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -49,17 +49,108 @@
#include <scsi/scsiconf.h>
#include <dev/ic/siopreg.h>
-#include <dev/ic/siopvar.h>
#include <dev/ic/siopvar_common.h>
+#include <dev/ic/siopvar.h>
#undef DEBUG
#undef DEBUG_DR
+#undef DEBUG_NEG
+
+int
+siop_common_attach(sc)
+ struct siop_common_softc *sc;
+{
+ int error, i;
+ bus_dma_segment_t seg;
+ int rseg;
-int siop_find_lun0_quirks(struct siop_softc *, u_int8_t, u_int16_t);
+ /*
+ * Allocate DMA-safe memory for the script and map it.
+ */
+ if ((sc->features & SF_CHIP_RAM) == 0) {
+ error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE,
+ PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
+ if (error) {
+ printf("%s: unable to allocate script DMA memory, "
+ "error = %d\n", sc->sc_dev.dv_xname, error);
+ return error;
+ }
+ error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, PAGE_SIZE,
+ (caddr_t *)&sc->sc_script,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
+ if (error) {
+ printf("%s: unable to map script DMA memory, "
+ "error = %d\n", sc->sc_dev.dv_xname, error);
+ return error;
+ }
+ error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,
+ PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_scriptdma);
+ if (error) {
+ printf("%s: unable to create script DMA map, "
+ "error = %d\n", sc->sc_dev.dv_xname, error);
+ return error;
+ }
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_scriptdma,
+ sc->sc_script, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
+ if (error) {
+ printf("%s: unable to load script DMA map, "
+ "error = %d\n", sc->sc_dev.dv_xname, error);
+ return error;
+ }
+ sc->sc_scriptaddr =
+ sc->sc_scriptdma->dm_segs[0].ds_addr;
+ sc->ram_size = PAGE_SIZE;
+ }
+
+ /*
+ * sc->sc_link is the template for all device sc_link's
+ * for devices attached to this adapter. It is passed to
+ * the upper layers in config_found().
+ */
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_buswidth =
+ (sc->features & SF_BUS_WIDE) ? 16 : 8;
+ sc->sc_link.adapter_target =
+ bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCID);
+ if (sc->sc_link.adapter_target == 0 ||
+ sc->sc_link.adapter_target >=
+ sc->sc_link.adapter_buswidth)
+ sc->sc_link.adapter_target = SIOP_DEFAULT_TARGET;
+
+ for (i = 0; i < 16; i++)
+ sc->targets[i] = NULL;
+
+ /* find min/max sync period for this chip */
+ sc->st_maxsync = 0;
+ sc->dt_maxsync = 0;
+ sc->st_minsync = 255;
+ sc->dt_minsync = 255;
+ for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
+ if (sc->clock_period != scf_period[i].clock)
+ continue;
+ if (sc->st_maxsync < scf_period[i].period)
+ sc->st_maxsync = scf_period[i].period;
+ if (sc->st_minsync > scf_period[i].period)
+ sc->st_minsync = scf_period[i].period;
+ }
+ if (sc->st_maxsync == 255 || sc->st_minsync == 0)
+ panic("siop: can't find my sync parameters\n");
+ for (i = 0; i < sizeof(dt_scf_period) / sizeof(dt_scf_period[0]); i++) {
+ if (sc->clock_period != dt_scf_period[i].clock)
+ continue;
+ if (sc->dt_maxsync < dt_scf_period[i].period)
+ sc->dt_maxsync = dt_scf_period[i].period;
+ if (sc->dt_minsync > dt_scf_period[i].period)
+ sc->dt_minsync = dt_scf_period[i].period;
+ }
+ if (sc->dt_maxsync == 255 || sc->dt_minsync == 0)
+ panic("siop: can't find my sync parameters\n");
+ return 0;
+}
void
siop_common_reset(sc)
- struct siop_softc *sc;
+ struct siop_common_softc *sc;
{
u_int32_t stest3;
@@ -73,8 +164,6 @@ siop_common_reset(sc)
SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, sc->clock_div);
- if (sc->features & SF_CHIP_C10)
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER, 0);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DIEN, 0xff);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN0,
@@ -97,7 +186,7 @@ siop_common_reset(sc)
stest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1,
STEST1_DBLEN);
- if ((sc->features & (SF_CHIP_QUAD | SF_CHIP_C10)) == SF_CHIP_QUAD) {
+ if (sc->features & SF_CHIP_QUAD) {
/* wait for PPL to lock */
while ((bus_space_read_1(sc->sc_rt, sc->sc_rh,
SIOP_STEST4) & STEST4_LOCK) == 0)
@@ -119,205 +208,133 @@ siop_common_reset(sc)
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5,
bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5) |
CTEST5_DFS);
-
- sc->sc_reset(sc);
-}
-
-int
-siop_find_lun0_quirks(sc, bus, target)
- struct siop_softc *sc;
- u_int8_t bus;
- u_int16_t target;
-{
- struct scsi_link *sc_link;
- struct device *dev;
-
- for (dev = TAILQ_FIRST(&alldevs); dev != NULL; dev = TAILQ_NEXT(dev, dv_list))
- if (dev->dv_parent == (struct device *)sc) {
- sc_link = ((struct scsibus_softc *)dev)->sc_link[target][0];
- if ((sc_link != NULL) && (sc_link->scsibus == bus))
- return sc_link->quirks;
- }
+ if (sc->features & SF_CHIP_LED0) {
+ /* Set GPIO0 as output if software LED control is required */
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_GPCNTL,
+ bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_GPCNTL) & 0xfe);
+ }
+ if (sc->features & SF_BUS_ULTRA3) {
+ /* reset SCNTL4 */
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4, 0);
+ }
+ sc->mode = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &
+ STEST4_MODE_MASK;
- /* If we can't find a quirks entry, assume the worst */
- return (SDEV_NOTAGS | SDEV_NOWIDE | SDEV_NOSYNC);
+ /*
+ * initialise the RAM. Without this we may get scsi gross errors on
+ * the 1010
+ */
+ if (sc->features & SF_CHIP_RAM)
+ bus_space_set_region_4(sc->sc_ramt, sc->sc_ramh,
+ 0, 0, sc->ram_size / 4);
+ sc->sc_reset(sc);
}
/* prepare tables before sending a cmd */
void
siop_setuptables(siop_cmd)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
{
int i;
- struct siop_softc *sc = siop_cmd->siop_sc;
+ struct siop_common_softc *sc = siop_cmd->siop_sc;
struct scsi_xfer *xs = siop_cmd->xs;
int target = xs->sc_link->target;
int lun = xs->sc_link->lun;
+ int msgoffset = 1;
int *targ_flags = &sc->targets[target]->flags;
int quirks;
- siop_cmd->siop_tables.id = htole32(sc->targets[target]->id);
- memset(siop_cmd->siop_tables.msg_out, 0, 8);
- if (siop_cmd->status != CMDST_SENSE)
- siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 1);
+ siop_cmd->siop_tables->id = htole32(sc->targets[target]->id);
+ memset(siop_cmd->siop_tables->msg_out, 0,
+ sizeof(siop_cmd->siop_tables->msg_out));
+ /* request sense doesn't disconnect */
+ if (siop_cmd->status == CMDST_SENSE)
+ siop_cmd->siop_tables->msg_out[0] = MSG_IDENTIFY(lun, 0);
+ else if ((sc->features & SF_CHIP_GEBUG) &&
+ (sc->targets[target]->flags & TARF_ISWIDE) == 0)
+ /*
+ * 1010 bug: it seems that the 1010 has problems with reselect
+ * when not in wide mode (generate false SCSI gross error).
+ * The FreeBSD sym driver has comments about it but their
+ * workaround (disable SCSI gross error reporting) doesn't
+ * work with my adapter. So disable disconnect when not
+ * wide.
+ */
+ siop_cmd->siop_tables->msg_out[0] = MSG_IDENTIFY(lun, 0);
else
- siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 0);
- siop_cmd->siop_tables.t_msgout.count= htole32(1);
+ siop_cmd->siop_tables->msg_out[0] = MSG_IDENTIFY(lun, 1);
+ siop_cmd->siop_tables->t_msgout.count= htole32(msgoffset);
if (sc->targets[target]->status == TARST_ASYNC) {
- *targ_flags = 0;
- if (lun == 0)
- quirks = xs->sc_link->quirks;
- else
- quirks = siop_find_lun0_quirks(sc, xs->sc_link->scsibus, target);
+ *targ_flags &= TARF_DT; /* Save TARF_DT 'cuz we don't set it here */
+ quirks = xs->sc_link->quirks;
- if ((quirks & SDEV_NOTAGS) == 0) {
+ if ((quirks & SDEV_NOTAGS) == 0)
*targ_flags |= TARF_TAG;
- xs->sc_link->openings += SIOP_NTAG - SIOP_OPENINGS;
- }
- if ((quirks & SDEV_NOWIDE) == 0)
+ if (((quirks & SDEV_NOWIDE) == 0) &&
+ (sc->features & SF_BUS_WIDE))
*targ_flags |= TARF_WIDE;
if ((quirks & SDEV_NOSYNC) == 0)
*targ_flags |= TARF_SYNC;
+ if ((sc->features & SF_CHIP_GEBUG) &&
+ (*targ_flags & TARF_WIDE) == 0)
+ /*
+ * 1010 workaround: can't do disconnect if not wide,
+ * so can't do tag
+ */
+ *targ_flags &= ~TARF_TAG;
+
/* Safe to call siop_add_dev() multiple times */
- siop_add_dev(sc, target, 0);
+ siop_add_dev((struct siop_softc *)sc, target, lun);
- if ((sc->features & SF_CHIP_C10)
- && (*targ_flags & TARF_WIDE)
- && (xs->sc_link->inquiry_flags2 & (SID_CLOCKING | SID_QAS | SID_IUS))) {
+ if ((*targ_flags & TARF_DT) &&
+ (sc->mode == STEST4_MODE_LVD)) {
sc->targets[target]->status = TARST_PPR_NEG;
- siop_ppr_msg(siop_cmd, 1,
- (sc->min_dt_sync == 0) ? sc->min_st_sync : sc->min_dt_sync,
- sc->maxoff);
+ siop_ppr_msg(siop_cmd, msgoffset, sc->dt_minsync,
+ sc->maxoff);
} else if (*targ_flags & TARF_WIDE) {
sc->targets[target]->status = TARST_WIDE_NEG;
- siop_wdtr_msg(siop_cmd, 1, MSG_EXT_WDTR_BUS_16_BIT);
+ siop_wdtr_msg(siop_cmd, msgoffset,
+ MSG_EXT_WDTR_BUS_16_BIT);
} else if (*targ_flags & TARF_SYNC) {
sc->targets[target]->status = TARST_SYNC_NEG;
- siop_sdtr_msg(siop_cmd, 1, sc->min_st_sync, sc->maxoff);
+ siop_sdtr_msg(siop_cmd, msgoffset, sc->st_minsync,
+ (sc->maxoff > 31) ? 31 : sc->maxoff);
} else {
sc->targets[target]->status = TARST_OK;
- siop_print_info(sc, target);
+ siop_update_xfer_mode(sc, target);
}
} else if (sc->targets[target]->status == TARST_OK &&
(*targ_flags & TARF_TAG) &&
siop_cmd->status != CMDST_SENSE) {
siop_cmd->flags |= CMDFL_TAG;
}
- siop_cmd->siop_tables.status =
+ siop_cmd->siop_tables->status =
htole32(SCSI_SIOP_NOSTATUS); /* set invalid status */
- siop_cmd->siop_tables.cmd.count =
+ siop_cmd->siop_tables->cmd.count =
htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_len);
- siop_cmd->siop_tables.cmd.addr =
+ siop_cmd->siop_tables->cmd.addr =
htole32(siop_cmd->dmamap_cmd->dm_segs[0].ds_addr);
if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) ||
siop_cmd->status == CMDST_SENSE) {
for (i = 0; i < siop_cmd->dmamap_data->dm_nsegs; i++) {
- siop_cmd->siop_tables.data[i].count =
+ siop_cmd->siop_tables->data[i].count =
htole32(siop_cmd->dmamap_data->dm_segs[i].ds_len);
- siop_cmd->siop_tables.data[i].addr =
+ siop_cmd->siop_tables->data[i].addr =
htole32(siop_cmd->dmamap_data->dm_segs[i].ds_addr);
}
}
- siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-}
-
-int
-siop_ppr_neg(siop_cmd)
- struct siop_cmd *siop_cmd;
-{
- struct siop_softc *sc = siop_cmd->siop_sc;
- struct siop_target *siop_target = siop_cmd->siop_target;
- int target = siop_cmd->xs->sc_link->target;
- struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
- int offset, sync, protocol, scf;
-
- sync = tables->msg_in[3];
- offset = tables->msg_in[5];
- protocol = tables->msg_in[7];
-
-#ifdef DEBUG
- printf("%s: siop_ppr_neg: sync = %x, offset = %x, protocol = %x\n",
- sc->sc_dev.dv_xname, sync, offset, protocol);
-#endif
- /*
- * Process protocol bits first, because finding the correct scf
- * via siop_period_factor_to_scf() requires the TARF_ISDT flag
- * to be correctly set.
- */
- if (protocol & MSG_EXT_PPR_PROT_IUS)
- siop_target->flags |= TARF_ISIUS;
-
- if (protocol & MSG_EXT_PPR_PROT_DT) {
- siop_target->flags |= TARF_ISDT;
- sc->targets[target]->id |= SCNTL4_ULTRA3;
- }
-
- if (protocol & MSG_EXT_PPR_PROT_QAS)
- siop_target->flags |= TARF_ISQAS;
-
- scf = siop_period_factor_to_scf(sc, sync, siop_target->flags);
-
- if ((offset > sc->maxoff) ||
- (scf == 0) ||
- ((siop_target->flags & TARF_ISDT) && (offset == 1))) {
- tables->t_msgout.count= htole32(1);
- tables->msg_out[0] = MSG_MESSAGE_REJECT;
- return (SIOP_NEG_MSGOUT);
- }
-
- siop_target->id |= scf << (24 + SCNTL3_SCF_SHIFT);
-
- if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
- siop_target->id |= SCNTL3_ULTRA << 24;
-
- siop_target->id |= (offset & 0xff) << 8;
-
- if (tables->msg_in[6] == MSG_EXT_WDTR_BUS_16_BIT) {
- siop_target->flags |= TARF_ISWIDE;
- sc->targets[target]->id |= (SCNTL3_EWS << 24);
- }
-
-#ifdef DEBUG
- printf("%s: siop_ppr_neg: id now 0x%x, flags is now 0x%x\n",
- sc->sc_dev.dv_xname, siop_target->id, siop_target->flags);
-#endif
- tables->id = htole32(siop_target->id);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
- (siop_target->id >> 24) & 0xff);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
- (siop_target->id >> 8) & 0xff);
- /* Only cards with SCNTL4 can cause PPR negotiations, so ... */
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4,
- (siop_target->id & 0xff));
-
- siop_target->status = TARST_OK;
- siop_print_info(sc, target);
-
- return (SIOP_NEG_ACK);
}
int
siop_wdtr_neg(siop_cmd)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
{
- struct siop_softc *sc = siop_cmd->siop_sc;
- struct siop_target *siop_target = siop_cmd->siop_target;
+ struct siop_common_softc *sc = siop_cmd->siop_sc;
+ struct siop_common_target *siop_target = siop_cmd->siop_target;
int target = siop_cmd->xs->sc_link->target;
- struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
-
- /* revert to narrow async until told otherwise */
- sc->targets[target]->id &= 0x07ff0000; /* Keep SCNTL3.CCF and id */
- sc->targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT | TARF_ISQAS | TARF_ISIUS);
-
- tables->id = htole32(sc->targets[target]->id);
-
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
- (sc->targets[target]->id >> 24) & 0xff);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER, 0);
- if (sc->features & SF_CHIP_C10)
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4, 0);
+ struct siop_common_xfer *tables = siop_cmd->siop_tables;
if (siop_target->status == TARST_WIDE_NEG) {
/* we initiated wide negotiation */
@@ -332,18 +349,19 @@ siop_wdtr_neg(siop_cmd)
sc->targets[target]->id |= (SCNTL3_EWS << 24);
break;
}
- /* FALLTHROUGH */
+ /* FALLTHROUH */
default:
/*
- * We got more than we can handle, which shouldn't
- * happen. Reject, and stay async.
+ * hum, we got more than what we can handle, shouldn't
+ * happen. Reject, and stay async
*/
siop_target->flags &= ~TARF_ISWIDE;
siop_target->status = TARST_OK;
+ siop_target->offset = siop_target->period = 0;
+ siop_update_xfer_mode(sc, target);
printf("%s: rejecting invalid wide negotiation from "
"target %d (%d)\n", sc->sc_dev.dv_xname, target,
tables->msg_in[3]);
- siop_print_info(sc, target);
tables->t_msgout.count= htole32(1);
tables->msg_out[0] = MSG_MESSAGE_REJECT;
return SIOP_NEG_MSGOUT;
@@ -355,11 +373,12 @@ siop_wdtr_neg(siop_cmd)
/* we now need to do sync */
if (siop_target->flags & TARF_SYNC) {
siop_target->status = TARST_SYNC_NEG;
- siop_sdtr_msg(siop_cmd, 0, sc->min_st_sync, sc->maxoff);
+ siop_sdtr_msg(siop_cmd, 0, sc->st_minsync,
+ (sc->maxoff > 31) ? 31 : sc->maxoff);
return SIOP_NEG_MSGOUT;
} else {
siop_target->status = TARST_OK;
- siop_print_info(sc, target);
+ siop_update_xfer_mode(sc, target);
return SIOP_NEG_ACK;
}
} else {
@@ -376,12 +395,12 @@ siop_wdtr_neg(siop_cmd)
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
(sc->targets[target]->id >> 24) & 0xff);
/*
- * Don't schedule a sync neg, target should initiate it.
+ * we did reset wide parameters, so fall back to async,
+ * but don't schedule a sync neg, target should initiate it
*/
- if (siop_target->status != TARST_PROBING) {
- siop_target->status = TARST_OK;
- siop_print_info(sc, target);
- }
+ siop_target->status = TARST_OK;
+ siop_target->offset = siop_target->period = 0;
+ siop_update_xfer_mode(sc, target);
siop_wdtr_msg(siop_cmd, 0, (siop_target->flags & TARF_ISWIDE) ?
MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT);
return SIOP_NEG_MSGOUT;
@@ -389,76 +408,238 @@ siop_wdtr_neg(siop_cmd)
}
int
+siop_ppr_neg(siop_cmd)
+ struct siop_common_cmd *siop_cmd;
+{
+ struct siop_common_softc *sc = siop_cmd->siop_sc;
+ struct siop_common_target *siop_target = siop_cmd->siop_target;
+ int target = siop_cmd->xs->sc_link->target;
+ struct siop_common_xfer *tables = siop_cmd->siop_tables;
+ int sync, offset, options, scf = 0;
+ int i;
+
+#ifdef DEBUG_NEG
+ printf("%s: anserw on ppr negotiation:", sc->sc_dev.dv_xname);
+ for (i = 0; i < 8; i++)
+ printf(" 0x%x", tables->msg_in[i]);
+ printf("\n");
+#endif
+
+ if (siop_target->status == TARST_PPR_NEG) {
+ /* we initiated PPR negotiation */
+ sync = tables->msg_in[3];
+ offset = tables->msg_in[5];
+ options = tables->msg_in[7];
+ if (options != MSG_EXT_PPR_PROT_DT) {
+ /* should't happen */
+ printf("%s: ppr negotiation for target %d: "
+ "no DT option\n", sc->sc_dev.dv_xname, target);
+ siop_target->status = TARST_ASYNC;
+ siop_target->flags &= ~(TARF_DT | TARF_ISDT);
+ siop_target->offset = 0;
+ siop_target->period = 0;
+ goto reject;
+ }
+
+ if (offset > sc->maxoff || sync < sc->dt_minsync ||
+ sync > sc->dt_maxsync) {
+ printf("%s: ppr negotiation for target %d: "
+ "offset (%d) or sync (%d) out of range\n",
+ sc->sc_dev.dv_xname, target, offset, sync);
+ /* should not happen */
+ siop_target->status = TARST_ASYNC;
+ siop_target->flags &= ~(TARF_DT | TARF_ISDT);
+ siop_target->offset = 0;
+ siop_target->period = 0;
+ goto reject;
+ } else {
+ for (i = 0; i <
+ sizeof(dt_scf_period) / sizeof(dt_scf_period[0]);
+ i++) {
+ if (sc->clock_period != dt_scf_period[i].clock)
+ continue;
+ if (dt_scf_period[i].period == sync) {
+ /* ok, found it. we now are sync. */
+ siop_target->offset = offset;
+ siop_target->period = sync;
+ scf = dt_scf_period[i].scf;
+ siop_target->flags |= TARF_ISDT;
+ }
+ }
+ if ((siop_target->flags & TARF_ISDT) == 0) {
+ printf("%s: ppr negotiation for target %d: "
+ "sync (%d) incompatible with adapter\n",
+ sc->sc_dev.dv_xname, target, sync);
+ /*
+ * we didn't find it in our table, do async
+ * send reject msg, start SDTR/WDTR neg
+ */
+ siop_target->status = TARST_ASYNC;
+ siop_target->flags &= ~(TARF_DT | TARF_ISDT);
+ siop_target->offset = 0;
+ siop_target->period = 0;
+ goto reject;
+ }
+ }
+ if (tables->msg_in[6] != 1) {
+ printf("%s: ppr negotiation for target %d: "
+ "transfer width (%d) incompatible with dt\n",
+ sc->sc_dev.dv_xname, target, tables->msg_in[6]);
+ /* DT mode can only be done with wide transfers */
+ siop_target->status = TARST_ASYNC;
+ siop_target->flags &= ~(TARF_DT | TARF_ISDT);
+ siop_target->offset = 0;
+ siop_target->period = 0;
+ goto reject;
+ }
+ siop_target->flags |= TARF_ISWIDE;
+ sc->targets[target]->id |= (SCNTL3_EWS << 24);
+ sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);
+ sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id |=
+ (siop_target->offset & SXFER_MO_MASK) << 8;
+ sc->targets[target]->id &= ~0xff;
+ sc->targets[target]->id |= SCNTL4_U3EN;
+ siop_target->status = TARST_OK;
+ siop_update_xfer_mode(sc, target);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3,
+ (sc->targets[target]->id >> 24) & 0xff);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
+ (sc->targets[target]->id >> 8) & 0xff);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL4,
+ sc->targets[target]->id & 0xff);
+ return SIOP_NEG_ACK;
+ } else {
+ /* target initiated PPR negotiation, shouldn't happen */
+ printf("%s: rejecting invalid PPR negotiation from "
+ "target %d\n", sc->sc_dev.dv_xname, target);
+reject:
+ tables->t_msgout.count= htole32(1);
+ tables->msg_out[0] = MSG_MESSAGE_REJECT;
+ return SIOP_NEG_MSGOUT;
+ }
+}
+
+int
siop_sdtr_neg(siop_cmd)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
{
- struct siop_softc *sc = siop_cmd->siop_sc;
- struct siop_target *siop_target = siop_cmd->siop_target;
+ struct siop_common_softc *sc = siop_cmd->siop_sc;
+ struct siop_common_target *siop_target = siop_cmd->siop_target;
int target = siop_cmd->xs->sc_link->target;
- int sync, offset, scf;
+ int sync, maxoffset, offset, i;
int send_msgout = 0;
- struct siop_xfer_common *tables = &siop_cmd->siop_xfer->tables;
+ struct siop_common_xfer *tables = siop_cmd->siop_tables;
+
+ /* limit to Ultra/2 parameters, need PPR for Ultra/3 */
+ maxoffset = (sc->maxoff > 31) ? 31 : sc->maxoff;
sync = tables->msg_in[3];
offset = tables->msg_in[4];
- /* revert to async until told otherwise */
- sc->targets[target]->id &= 0x0fff0000; /* Keep SCNTL3.EWS, SCNTL3.CCF and id */
- sc->targets[target]->flags &= ~(TARF_ISDT | TARF_ISQAS | TARF_ISIUS);
-
if (siop_target->status == TARST_SYNC_NEG) {
/* we initiated sync negotiation */
+ siop_target->status = TARST_OK;
#ifdef DEBUG
- printf("%s: sdtr for target %d: sync %d offset %d\n",
- sc->sc_dev.dv_xname, target, sync, offset);
+ printf("sdtr: sync %d offset %d\n", sync, offset);
#endif
- scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);
- if (offset > sc->maxoff || scf == 0)
+ if (offset > maxoffset || sync < sc->st_minsync ||
+ sync > sc->st_maxsync)
goto reject;
- sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);
- if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
- sc->targets[target]->id |= SCNTL3_ULTRA << 24;
- sc->targets[target]->id |= (offset & 0xff) << 8;
- goto end;
+ for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]);
+ i++) {
+ if (sc->clock_period != scf_period[i].clock)
+ continue;
+ if (scf_period[i].period == sync) {
+ /* ok, found it. we now are sync. */
+ siop_target->offset = offset;
+ siop_target->period = sync;
+ sc->targets[target]->id &=
+ ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id |= scf_period[i].scf
+ << (24 + SCNTL3_SCF_SHIFT);
+ if (sync < 25 && /* Ultra */
+ (sc->features & SF_BUS_ULTRA3) == 0)
+ sc->targets[target]->id |=
+ SCNTL3_ULTRA << 24;
+ else
+ sc->targets[target]->id &=
+ ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &=
+ ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id |=
+ (offset & SXFER_MO_MASK) << 8;
+ sc->targets[target]->id &= ~0xff; /* scntl4 */
+ goto end;
+ }
+ }
/*
- * We didn't find it in our table, so stay async and send reject
- * msg.
+ * we didn't find it in our table, do async and send reject
+ * msg
*/
reject:
send_msgout = 1;
tables->t_msgout.count= htole32(1);
tables->msg_out[0] = MSG_MESSAGE_REJECT;
+ sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id &= ~0xff; /* scntl4 */
+ siop_target->offset = siop_target->period = 0;
} else { /* target initiated sync neg */
#ifdef DEBUG
- printf("%s: target initiated sdtr for target %d: sync %d offset %d\n",
- sc->sc_dev.dv_xname, target, sync, offset);
printf("sdtr (target): sync %d offset %d\n", sync, offset);
#endif
- if (sync < sc->min_st_sync)
- sync = sc->min_st_sync;
- scf = siop_period_factor_to_scf(sc, sync, sc->targets[target]->flags);
- if ((sc->targets[target]->flags & TARF_SYNC) == 0
- || offset == 0
- || scf == 0) {
+ if (offset == 0 || sync > sc->st_maxsync) { /* async */
goto async;
}
- if ((offset > 31) && ((sc->targets[target]->flags & TARF_ISDT) == 0))
- offset = 31;
- if (offset > sc->maxoff)
- offset = sc->maxoff;
-
- sc->targets[target]->id |= scf << (24 + SCNTL3_SCF_SHIFT);
- if (((sc->features & SF_CHIP_C10) == 0) && (sync < 25))
- sc->targets[target]->id |= SCNTL3_ULTRA << 24;
- sc->targets[target]->id |= (offset & 0xff) << 8;
- siop_sdtr_msg(siop_cmd, 0, sync, offset);
- send_msgout = 1;
- goto end;
+ if (offset > maxoffset)
+ offset = maxoffset;
+ if (sync < sc->st_minsync)
+ sync = sc->st_minsync;
+ /* look for sync period */
+ for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]);
+ i++) {
+ if (sc->clock_period != scf_period[i].clock)
+ continue;
+ if (scf_period[i].period == sync) {
+ /* ok, found it. we now are sync. */
+ siop_target->offset = offset;
+ siop_target->period = sync;
+ sc->targets[target]->id &=
+ ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id |= scf_period[i].scf
+ << (24 + SCNTL3_SCF_SHIFT);
+ if (sync < 25 && /* Ultra */
+ (sc->features & SF_BUS_ULTRA3) == 0)
+ sc->targets[target]->id |=
+ SCNTL3_ULTRA << 24;
+ else
+ sc->targets[target]->id &=
+ ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &=
+ ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id |=
+ (offset & SXFER_MO_MASK) << 8;
+ sc->targets[target]->id &= ~0xff; /* scntl4 */
+ siop_sdtr_msg(siop_cmd, 0, sync, offset);
+ send_msgout = 1;
+ goto end;
+ }
+ }
async:
+ siop_target->offset = siop_target->period = 0;
+ sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24);
+ sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24);
+ sc->targets[target]->id &= ~(SXFER_MO_MASK << 8);
+ sc->targets[target]->id &= ~0xff; /* scntl4 */
siop_sdtr_msg(siop_cmd, 0, 0, 0);
send_msgout = 1;
}
end:
+ if (siop_target->status == TARST_OK)
+ siop_update_xfer_mode(sc, target);
#ifdef DEBUG
printf("id now 0x%x\n", sc->targets[target]->id);
#endif
@@ -467,12 +648,6 @@ end:
(sc->targets[target]->id >> 24) & 0xff);
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SXFER,
(sc->targets[target]->id >> 8) & 0xff);
-
- if (siop_target->status != TARST_PROBING) {
- siop_target->status = TARST_OK;
- siop_print_info(sc, target);
- }
-
if (send_msgout) {
return SIOP_NEG_MSGOUT;
} else {
@@ -481,72 +656,52 @@ end:
}
void
-siop_ppr_msg(siop_cmd, offset, ssync, soff)
- struct siop_cmd *siop_cmd;
- int offset, ssync, soff;
-{
- struct siop_softc *sc = siop_cmd->siop_sc;
- u_int8_t protocol;
-
- siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
- siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_PPR_LEN;
- siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_PPR;
- siop_cmd->siop_tables.msg_out[offset + 3] = ssync;
- siop_cmd->siop_tables.msg_out[offset + 4] = 0; /* RESERVED */
- siop_cmd->siop_tables.msg_out[offset + 5] = soff;
- siop_cmd->siop_tables.msg_out[offset + 6] = MSG_EXT_WDTR_BUS_16_BIT;
-
- protocol = 0;
- if (sc->min_dt_sync != 0)
- protocol |= MSG_EXT_PPR_PROT_DT;
-
- /* XXX - need tests for chip's capability to do QAS & IUS
- *
- * if (test for QAS support)
- * protocol |= MSG_EXT_PPR_PROT_QAS;
- * if (test for IUS support)
- * protocol |= MSG_EXT_PPR_PROT_IUS;
- */
-
- siop_cmd->siop_tables.msg_out[offset + 7] = protocol;
-
- siop_cmd->siop_tables.t_msgout.count =
- htole32(offset + MSG_EXT_PPR_LEN + 2);
-}
-
-void
siop_sdtr_msg(siop_cmd, offset, ssync, soff)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
int offset;
int ssync, soff;
{
- siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
- siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_SDTR_LEN;
- siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_SDTR;
- siop_cmd->siop_tables.msg_out[offset + 3] = ssync;
-
- if ((soff > 31) && ((siop_cmd->siop_target->flags & TARF_ISDT) == 0))
- soff = 31;
-
- siop_cmd->siop_tables.msg_out[offset + 4] = soff;
- siop_cmd->siop_tables.t_msgout.count =
+ siop_cmd->siop_tables->msg_out[offset + 0] = MSG_EXTENDED;
+ siop_cmd->siop_tables->msg_out[offset + 1] = MSG_EXT_SDTR_LEN;
+ siop_cmd->siop_tables->msg_out[offset + 2] = MSG_EXT_SDTR;
+ siop_cmd->siop_tables->msg_out[offset + 3] = ssync;
+ siop_cmd->siop_tables->msg_out[offset + 4] = soff;
+ siop_cmd->siop_tables->t_msgout.count =
htole32(offset + MSG_EXT_SDTR_LEN + 2);
}
void
siop_wdtr_msg(siop_cmd, offset, wide)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
int offset;
{
- siop_cmd->siop_tables.msg_out[offset + 0] = MSG_EXTENDED;
- siop_cmd->siop_tables.msg_out[offset + 1] = MSG_EXT_WDTR_LEN;
- siop_cmd->siop_tables.msg_out[offset + 2] = MSG_EXT_WDTR;
- siop_cmd->siop_tables.msg_out[offset + 3] = wide;
- siop_cmd->siop_tables.t_msgout.count =
+ siop_cmd->siop_tables->msg_out[offset + 0] = MSG_EXTENDED;
+ siop_cmd->siop_tables->msg_out[offset + 1] = MSG_EXT_WDTR_LEN;
+ siop_cmd->siop_tables->msg_out[offset + 2] = MSG_EXT_WDTR;
+ siop_cmd->siop_tables->msg_out[offset + 3] = wide;
+ siop_cmd->siop_tables->t_msgout.count =
htole32(offset + MSG_EXT_WDTR_LEN + 2);
}
void
+siop_ppr_msg(siop_cmd, offset, ssync, soff)
+ struct siop_common_cmd *siop_cmd;
+ int offset;
+ int ssync, soff;
+{
+ siop_cmd->siop_tables->msg_out[offset + 0] = MSG_EXTENDED;
+ siop_cmd->siop_tables->msg_out[offset + 1] = MSG_EXT_PPR_LEN;
+ siop_cmd->siop_tables->msg_out[offset + 2] = MSG_EXT_PPR;
+ siop_cmd->siop_tables->msg_out[offset + 3] = ssync;
+ siop_cmd->siop_tables->msg_out[offset + 4] = 0; /* reserved */
+ siop_cmd->siop_tables->msg_out[offset + 5] = soff;
+ siop_cmd->siop_tables->msg_out[offset + 6] = 1; /* wide */
+ siop_cmd->siop_tables->msg_out[offset + 7] = MSG_EXT_PPR_PROT_DT;
+ siop_cmd->siop_tables->t_msgout.count =
+ htole32(offset + MSG_EXT_PPR_LEN + 2);
+}
+
+void
siop_minphys(bp)
struct buf *bp;
{
@@ -555,12 +710,12 @@ siop_minphys(bp)
void
siop_sdp(siop_cmd)
- struct siop_cmd *siop_cmd;
+ struct siop_common_cmd *siop_cmd;
{
/* save data pointer. Handle async only for now */
int offset, dbc, sstat;
- struct siop_softc *sc = siop_cmd->siop_sc;
- struct scr_table *table; /* table to patch */
+ struct siop_common_softc *sc = siop_cmd->siop_sc;
+ scr_table_t *table; /* table to patch */
if ((siop_cmd->xs->flags & (SCSI_DATA_OUT | SCSI_DATA_IN))
== 0)
@@ -571,21 +726,23 @@ siop_sdp(siop_cmd)
sc->sc_dev.dv_xname, offset);
return;
}
- table = &siop_cmd->siop_xfer->tables.data[offset];
+ table = &siop_cmd->siop_tables->data[offset];
#ifdef DEBUG_DR
printf("sdp: offset %d count=%d addr=0x%x ", offset,
table->count, table->addr);
#endif
dbc = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DBC) & 0x00ffffff;
if (siop_cmd->xs->flags & SCSI_DATA_OUT) {
- /* need to account for stale data in FIFO */
- if (sc->features & SF_CHIP_C10)
- dbc += bus_space_read_2(sc->sc_rt, sc->sc_rh, SIOP_DFBC);
- else {
- int dfifo = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DFIFO);
+ if (sc->features & SF_CHIP_DFBC) {
+ dbc +=
+ bus_space_read_2(sc->sc_rt, sc->sc_rh, SIOP_DFBC);
+ } else {
+ /* need to account stale data in FIFO */
+ int dfifo =
+ bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DFIFO);
if (sc->features & SF_CHIP_FIFO) {
dfifo |= (bus_space_read_1(sc->sc_rt, sc->sc_rh,
- SIOP_CTEST5) & CTEST5_BOMASK) << 8;
+ SIOP_CTEST5) & CTEST5_BOMASK) << 8;
dbc += (dfifo - (dbc & 0x3ff)) & 0x3ff;
} else {
dbc += (dfifo - (dbc & 0x7f)) & 0x7f;
@@ -594,17 +751,16 @@ siop_sdp(siop_cmd)
sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT0);
if (sstat & SSTAT0_OLF)
dbc++;
- if ((sc->features & SF_CHIP_C10) == 0)
- if (sstat & SSTAT0_ORF)
- dbc++;
+ if ((sstat & SSTAT0_ORF) && (sc->features & SF_CHIP_DFBC) == 0)
+ dbc++;
if (siop_cmd->siop_target->flags & TARF_ISWIDE) {
sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh,
SIOP_SSTAT2);
if (sstat & SSTAT2_OLF1)
dbc++;
- if ((sc->features & SF_CHIP_C10) == 0)
- if (sstat & SSTAT2_ORF1)
- dbc++;
+ if ((sstat & SSTAT2_ORF1) &&
+ (sc->features & SF_CHIP_DFBC) == 0)
+ dbc++;
}
/* clear the FIFO */
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,
@@ -621,13 +777,13 @@ siop_sdp(siop_cmd)
void
siop_clearfifo(sc)
- struct siop_softc *sc;
+ struct siop_common_softc *sc;
{
int timeout = 0;
int ctest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3);
-#ifdef SIOP_DEBUG_INTR
- printf("DMA fifo not empty!\n");
+#ifdef DEBUG_INTR
+ printf("DMA fifo not empty !\n");
#endif
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3,
ctest3 | CTEST3_CLF);
@@ -646,15 +802,15 @@ siop_clearfifo(sc)
int
siop_modechange(sc)
- struct siop_softc *sc;
+ struct siop_common_softc *sc;
{
int retry;
- int sist0, sist1, stest2, stest4;
+ int sist0, sist1, stest2;
for (retry = 0; retry < 5; retry++) {
/*
- * Datasheet says to wait 100ms and re-read SIST1,
+ * datasheet says to wait 100ms and re-read SIST1,
* to check that DIFFSENSE is stable.
- * We may delay() 5 times for 100ms at interrupt time;
+ * We may delay() 5 times for 100ms at interrupt time;
* hopefully this will not happen often.
*/
delay(100000);
@@ -662,21 +818,15 @@ siop_modechange(sc)
sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1);
if (sist1 & SIEN1_SBMC)
continue; /* we got an irq again */
- stest4 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &
+ sc->mode = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &
STEST4_MODE_MASK;
stest2 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2);
- switch(stest4) {
+ switch(sc->mode) {
case STEST4_MODE_DIF:
- if (sc->features & SF_CHIP_C10) {
- printf("%s: invalid SCSI mode 0x%x\n",
- sc->sc_dev.dv_xname, stest4);
- return 0;
- } else {
- printf("%s: switching to differential mode\n",
- sc->sc_dev.dv_xname);
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
- stest2 | STEST2_DIF);
- }
+ printf("%s: switching to differential mode\n",
+ sc->sc_dev.dv_xname);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
+ stest2 | STEST2_DIF);
break;
case STEST4_MODE_SE:
printf("%s: switching to single-ended mode\n",
@@ -692,11 +842,9 @@ siop_modechange(sc)
break;
default:
printf("%s: invalid SCSI mode 0x%x\n",
- sc->sc_dev.dv_xname, stest4);
+ sc->sc_dev.dv_xname, sc->mode);
return 0;
}
- bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST0,
- stest4 >> 2);
return 1;
}
printf("%s: timeout waiting for DIFFSENSE to stabilise\n",
@@ -706,7 +854,7 @@ siop_modechange(sc)
void
siop_resetbus(sc)
- struct siop_softc *sc;
+ struct siop_common_softc *sc;
{
int scntl1;
scntl1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1);
@@ -717,77 +865,60 @@ siop_resetbus(sc)
bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1);
}
-/*
- * siop_print_info: print the current negotiated wide/sync xfer values for
- * a particular target. This function is called whenever
- * a wide/sync negotiation completes, i.e. whenever
- * target->status is set to TARST_OK.
- */
void
-siop_print_info(sc, target)
- struct siop_softc *sc;
+siop_update_xfer_mode(sc, target)
+ struct siop_common_softc *sc;
int target;
{
- struct siop_target *siop_target;
- u_int8_t scf, offset;
- int scf_index, factors, i;
+ struct siop_common_target *siop_target;
siop_target = sc->targets[target];
- printf("%s: target %d now using %s%s%s%s%d bit ",
+ printf("%s: target %d now using %s%s%d bit ",
sc->sc_dev.dv_xname, target,
(siop_target->flags & TARF_TAG) ? "tagged " : "",
(siop_target->flags & TARF_ISDT) ? "DT " : "",
- (siop_target->flags & TARF_ISQAS) ? "QAS " : "",
- (siop_target->flags & TARF_ISIUS) ? "IUS " : "",
(siop_target->flags & TARF_ISWIDE) ? 16 : 8);
- offset = ((siop_target->id >> 8) & 0xff) >> SXFER_MO_SHIFT;
-
- if (offset == 0)
+ if (siop_target->offset == 0)
printf("async ");
- else {
- factors = sizeof(period_factor) / sizeof(period_factor[0]);
-
- scf = ((siop_target->id >> 24) & SCNTL3_SCF_MASK) >> SCNTL3_SCF_SHIFT;
- scf_index = sc->scf_index;
-
- for (i = 0; i < factors; i++)
- if (siop_target->flags & TARF_ISDT) {
- if (period_factor[i].scf[scf_index].dt_scf == scf)
- break;
- }
- else if (period_factor[i].scf[scf_index].st_scf == scf)
- break;
-
- if (i >= factors)
- printf("?? ");
- else
- printf("%s ", period_factor[i].rate);
-
- printf("MHz %d REQ/ACK offset ", offset);
+ else {
+ switch (siop_target->period) {
+ case 9: /* 12.5ns cycle */
+ printf("80.0");
+ break;
+ case 10: /* 25 ns cycle */
+ printf("40.0");
+ break;
+ case 12: /* 48 ns cycle */
+ printf("20.0");
+ break;
+ case 18: /* 72 ns cycle */
+ printf("13.3");
+ break;
+ case 25: /* 100 ns cycle */
+ printf("10.0");
+ break;
+ case 37: /* 118 ns cycle */
+ printf("6.67");
+ break;
+ case 50: /* 200 ns cycle */
+ printf("5.0");
+ break;
+ case 75: /* 300 ns cycle */
+ printf("3.33");
+ break;
+ default:
+ printf("??");
+ break;
+ }
+ printf(" MHz %d REQ/ACK offset ", siop_target->offset);
}
printf("xfers\n");
-}
-
-int
-siop_period_factor_to_scf(sc, pf, flags)
- struct siop_softc *sc;
- int pf, flags;
-{
- const int scf_index = sc->scf_index;
- int i;
-
- const int factors = sizeof(period_factor) / sizeof(period_factor[0]);
-
- for (i = 0; i < factors; i++)
- if (period_factor[i].factor == pf) {
- if (flags & TARF_ISDT)
- return (period_factor[i].scf[scf_index].dt_scf);
- else
- return (period_factor[i].scf[scf_index].st_scf);
- }
- return (0);
+ if ((sc->features & SF_CHIP_GEBUG) &&
+ (siop_target->flags & TARF_ISWIDE) == 0)
+ /* 1010 workaround: can't do disconnect if not wide, so can't do tag */
+ siop_target->flags &= ~TARF_TAG;
}
diff --git a/sys/dev/ic/siopreg.h b/sys/dev/ic/siopreg.h
index cfaa758e086..cc22b87231b 100644
--- a/sys/dev/ic/siopreg.h
+++ b/sys/dev/ic/siopreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: siopreg.h,v 1.4 2001/06/25 23:14:40 krw Exp $ */
-/* $NetBSD: siopreg.h,v 1.7 2000/10/06 16:35:13 bouyer Exp $ */
+/* $OpenBSD: siopreg.h,v 1.5 2002/09/16 00:53:12 krw Exp $ */
+/* $NetBSD: siopreg.h,v 1.13 2002/08/29 16:43:23 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -14,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Manuel Bouyer
+ * This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -74,49 +74,35 @@
#define SCNTL3_CCF_SHIFT 0
#define SCNTL3_CCF_MASK 0x07
-#define SIOP_CLOCKS_SUPPORTED 3 /* 3 supported clocks: 25, 12.5, 6.25 ns */
-
-struct period_factor {
- int factor; /* transfer period factor from sdtr/ppr */
- char *rate; /* string describing transfer rate */
- struct {
- int st_scf;
- int dt_scf;
- } scf[SIOP_CLOCKS_SUPPORTED];
- /* scf value to use in SCNTL3[6:4]
- * 0 == SCLK/3
- * 1 == SCLK/1
- * 2 == SCLK/1.5
- * 3 == SCLK/2
- * 4 == SCLK/3
- * 5 == SCLK/4
- * 6 == SCLK/6
- * 7 == SCLK/8
- *
- * One entry for each different clock
- * supported, showing appropriate scf
- * for the period_factor requested. A
- * value of 0 indicates the rate is
- * not supported.
- *
- * scf[0] == scf for a 25ns cycle
- * scf[1] == scf for a 12.5 ns cycle
- * scf[2] == scf for a 6.25 ns cycle
- *
- * min sync = first non zero in column
- * max sync = last non zero in column
- */
+/* periods for various SCF values, assume transfer period of 4 */
+struct scf_period {
+ int clock; /* clock period (ns * 10) */
+ int period; /* scsi period, as set in the SDTR message */
+ int scf; /* scf value to use */
};
-static const struct period_factor period_factor[] __attribute__((__unused__)) = {
- {0x09, "80", {{0,0},{0,0},{0,1}}},
- {0x0a, "40", {{0,0},{0,0},{1,3}}},
- {0x0c, "20", {{0,0},{1,0},{3,5}}},
- {0x12, "13.3", {{0,0},{2,0},{4,6}}},
- {0x19, "10", {{1,0},{3,0},{5,7}}},
- {0x25, "6.67", {{2,0},{4,0},{6,0}}},
- {0x32, "5", {{3,0},{5,0},{7,0}}},
- {0x4b, "3.33", {{4,0},{6,0},{0,0}}},
+static const struct scf_period scf_period[] __attribute__((__unused__)) = {
+ {250, 25, 1}, /* 10.0 Mhz */
+ {250, 37, 2}, /* 6.67 Mhz */
+ {250, 50, 3}, /* 5.00 Mhz */
+ {250, 75, 4}, /* 3.33 Mhz */
+ {125, 12, 1}, /* 20.0 Mhz */
+ {125, 18, 2}, /* 13.3 Mhz */
+ {125, 25, 3}, /* 10.0 Mhz */
+ {125, 37, 4}, /* 6.67 Mhz */
+ {125, 50, 5}, /* 5.0 Mhz */
+ { 62, 10, 1}, /* 40.0 Mhz */
+ { 62, 12, 3}, /* 20.0 Mhz */
+ { 62, 18, 4}, /* 13.3 Mhz */
+ { 62, 25, 5}, /* 10.0 Mhz */
+};
+
+static const struct scf_period dt_scf_period[] __attribute__((__unused__)) = {
+ { 62, 9, 1}, /* 80.0 Mhz */
+ { 62, 10, 3}, /* 40.0 Mhz */
+ { 62, 12, 5}, /* 20.0 Mhz */
+ { 62, 18, 6}, /* 13.3 Mhz */
+ { 62, 25, 7}, /* 10.0 Mhz */
};
#define SIOP_SCID 0x04 /* SCSI chip ID R/W */
@@ -129,9 +115,9 @@ static const struct period_factor period_factor[] __attribute__((__unused__)) =
#define SXFER_TP_SHIFT 5
#define SXFER_TP_MASK 0xe0
#define SXFER_MO_SHIFT 0
-#define SXFER_MO_MASK 0x1f
+#define SXFER_MO_MASK 0x3f
-#define SIOP_SDID 0x06 /* SCSI destination ID, R/W */
+#define SIOP_SDID 0x06 /* SCSI destiation ID, R/W */
#define SDID_ENCID_SHIFT 0
#define SDID_ENCID_MASK 0x07
@@ -354,6 +340,8 @@ static const struct period_factor period_factor[] __attribute__((__unused__)) =
#define SIOP_STEST0 0x4C /* SCSI test 0, RO */
#define SIOP_STEST1 0x4D /* SCSI test 1, RO, RW on 875 */
+#define STEST1_DOGE 0x20 /* 1010 only */
+#define STEST1_DIGE 0x10 /* 1010 only */
#define STEST1_DBLEN 0x08 /* 875-only */
#define STEST1_DBLSEL 0x04 /* 875-only */
@@ -397,8 +385,150 @@ static const struct period_factor period_factor[] __attribute__((__unused__)) =
#define SIOP_SCRATCHJ 0x7c /* Scratch register J, R/W, 875-only */
-#define SIOP_SCNTL4 0xbc
-#define SCNTL4_ULTRA3 0x80
-#define SCNTL4_AIP 0x40
+#define SIOP_SCNTL4 0xBC /* SCSI control 4, R/W, 1010-only */
+#define SCNTL4_XCLKS_ST 0x01
+#define SCNTL4_XCLKS_DT 0x02
+#define SCNTL4_XCLKH_ST 0x04
+#define SCNTL4_XCLKH_DT 0x08
+#define SCNTL4_AIPEN 0x40
+#define SCNTL4_U3EN 0x80
+
+#define SIOP_DFBC 0xf0 /* DMA fifo byte count, RO */
+
+#define SIOP_AIPCNTL0 0xbe /* AIP Control 0, 1010-only */
+#define AIPCNTL0_ERRLIVE 0x04 /* AIP error status, live */
+#define AIPCNTL0_ERR 0x02 /* AIP error status, latched */
+#define AIPCNTL0_PARITYERRs 0x01 /* Parity error */
+
+#define SIOP_AIPCNTL1 0xbf /* AIP Control 1, 1010-only */
+#define AIPCNTL1_DIS 0x08 /* disable AIP generation, 1010-66 only */
+#define AIPCNTL1_RSETERR 0x04 /* reset AIP error 1010-66 only */
+#define AIPCNTL1_FB 0x02 /* force bad AIP value 1010-66 only */
+#define AIPCNTL1_RSET 0x01 /* reset AIP sequence value 1010-66 only */
+
+/*
+ * Non-volatile configuration settings stored in the EEPROM. There
+ * are at least two known formats: Symbios Logic format and Tekram format.
+ */
+
+#define SIOP_NVRAM_SYM_SIZE 368
+#define SIOP_NVRAM_SYM_ADDRESS 0x100
+
+struct nvram_symbios {
+ /* Header (6 bytes) */
+ u_int16_t type; /* 0x0000 */
+ u_int16_t byte_count; /* excluding header/trailer */
+ u_int16_t checksum;
+
+ /* Adapter configuration (20 bytes) */
+ u_int8_t v_major;
+ u_int8_t v_minor;
+ u_int32_t boot_crc;
+ u_int16_t flags;
+#define NVRAM_SYM_F_SCAM_ENABLE 0x0001
+#define NVRAM_SYM_F_PARITY_ENABLE 0x0002
+#define NVRAM_SYM_F_VERBOSE_MESSAGES 0x0004
+#define NVRAM_SYM_F_CHS_MAPPING 0x0008
+ u_int16_t flags1;
+#define NVRAM_SYM_F1_SCAN_HI_LO 0x0001
+ u_int16_t term_state;
+#define NVRAM_SYM_TERM_CANT_PROGRAM 0
+#define NVRAM_SYM_TERM_ENABLED 1
+#define NVRAM_SYM_TERM_DISABLED 2
+ u_int16_t rmvbl_flags;
+#define NVRAM_SYM_RMVBL_NO_SUPPORT 0
+#define NVRAM_SYM_RMVBL_BOOT_DEVICE 1
+#define NVRAM_SYM_RMVBL_MEDIA_INSTALLED 2
+ u_int8_t host_id;
+ u_int8_t num_hba;
+ u_int8_t num_devices;
+ u_int8_t max_scam_devices;
+ u_int8_t num_valid_scam_devices;
+ u_int8_t rsvd;
+
+ /* Boot order (14 bytes x 4) */
+ struct nvram_symbios_host {
+ u_int16_t type; /* 4 - 8xx */
+ u_int16_t device_id; /* PCI device ID */
+ u_int16_t vendor_id; /* PCI vendor ID */
+ u_int8_t bus_nr; /* PCI bus number */
+ u_int8_t device_fn; /* PCI device/func # << 3 */
+ u_int16_t word8;
+ u_int16_t flags;
+#define NVRAM_SYM_HOST_F_SCAN_AT_BOOT 0x0001
+ u_int16_t io_port; /* PCI I/O address */
+ } __attribute__((__packed__)) host[4];
+
+ /* Targets (8 bytes x 16) */
+ struct nvram_symbios_target {
+ u_int8_t flags;
+#define NVRAM_SYM_TARG_F_DISCONNECT_EN 0x0001
+#define NVRAM_SYM_TARG_F_SCAN_AT_BOOT 0x0002
+#define NVRAM_SYM_TARG_F_SCAN_LUNS 0x0004
+#define NVRAM_SYM_TARG_F_TQ_EN 0x0008
+ u_int8_t rsvd;
+ u_int8_t bus_width;
+ u_int8_t sync_offset; /* 8, 16, etc. */
+ u_int16_t sync_period; /* 4 * factor */
+ u_int16_t timeout;
+ } __attribute__((__packed__)) target[16];
+
+ /* SCAM table (8 bytes x 4) */
+ struct nvram_symbios_scam {
+ u_int16_t id;
+ u_int16_t method;
+#define NVRAM_SYM_SCAM_DEFAULT_METHOD 0
+#define NVRAM_SYM_SCAM_DONT_ASSIGN 1
+#define NVRAM_SYM_SCAM_SET_SPECIFIC_ID 2
+#define NVRAM_SYM_SCAM_USE_ORDER_GIVEN 3
+ u_int16_t status;
+#define NVRAM_SYM_SCAM_UNKNOWN 0
+#define NVRAM_SYM_SCAM_DEVICE_NOT_FOUND 1
+#define NVRAM_SYM_SCAM_ID_NOT_SET 2
+#define NVRAM_SYM_SCAM_ID_VALID 3
+ u_int8_t target_id;
+ u_int8_t rsvd;
+ } __attribute__((__packed__)) scam[4];
+
+ u_int8_t spare_devices[15 * 8];
+ u_int8_t trailer[6]; /* 0xfe 0xfe 0x00 0x00 0x00 0x00 */
+} __attribute__((__packed__));
+
+#define SIOP_NVRAM_TEK_SIZE 64
+#define SIOP_NVRAM_TEK_93c46_ADDRESS 0
+#define SIOP_NVRAM_TEK_24c16_ADDRESS 0x40
+
+static const u_int8_t tekram_sync_table[16] __attribute__((__unused__)) = {
+ 25, 31, 37, 43,
+ 50, 62, 75, 125,
+ 12, 15, 18, 21,
+ 6, 7, 9, 10,
+};
-#define SIOP_DFBC 0xf0 /* DMA FIFO byte count, RO, C10-only */
+struct nvram_tekram {
+ struct nvram_tekram_target {
+ u_int8_t flags;
+#define NVRAM_TEK_TARG_F_PARITY_CHECK 0x01
+#define NVRAM_TEK_TARG_F_SYNC_NEGO 0x02
+#define NVRAM_TEK_TARG_F_DISCONNECT_EN 0x04
+#define NVRAM_TEK_TARG_F_START_CMD 0x08
+#define NVRAM_TEK_TARG_F_TQ_EN 0x10
+#define NVRAM_TEK_TARG_F_WIDE_NEGO 0x20
+ u_int8_t sync_index;
+ u_int16_t word2;
+ } __attribute__((__packed__)) target[16];
+ u_int8_t host_id;
+ u_int8_t flags;
+#define NVRAM_TEK_F_MORE_THAN_2_DRIVES 0x01
+#define NVRAM_TEK_F_DRIVES_SUP_1G 0x02
+#define NVRAM_TEK_F_RESET_ON_POWER_ON 0x04
+#define NVRAM_TEK_F_ACTIVE_NEGATION 0x08
+#define NVRAM_TEK_F_IMMEDIATE_SEEK 0x10
+#define NVRAM_TEK_F_SCAN_LUNS 0x20
+#define NVRAM_TEK_F_REMOVABLE_FLAGS 0xc0 /* 0 dis, 1 boot, 2 all */
+ u_int8_t boot_delay_index;
+ u_int8_t max_tags_index;
+ u_int16_t flags1;
+#define NVRAM_TEK_F_F2_F6_ENABLED 0x0001
+ u_int16_t spare[29];
+} __attribute__((__packed__));
diff --git a/sys/dev/ic/siopvar.h b/sys/dev/ic/siopvar.h
index 57579d7d69e..7cbde2ef2b8 100644
--- a/sys/dev/ic/siopvar.h
+++ b/sys/dev/ic/siopvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: siopvar.h,v 1.5 2002/03/14 01:26:55 millert Exp $ */
-/* $NetBSD: siopvar.h,v 1.13 2000/10/23 23:18:11 bouyer Exp $ */
+/* $OpenBSD: siopvar.h,v 1.6 2002/09/16 00:53:12 krw Exp $ */
+/* $NetBSD: siopvar.h,v 1.18 2002/04/23 20:41:15 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -14,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Manuel Bouyer
+ * This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -33,32 +33,96 @@
/* structure and definitions for the siop driver */
+/* Number of tag */
+#define SIOP_NTAG 16
+
+/*
+ * xfer description of the script: tables and reselect script
+ * In struct siop_common_cmd siop_xfer will point to this.
+ */
+struct siop_xfer {
+ struct siop_common_xfer siop_tables;
+ /* u_int32_t resel[sizeof(load_dsa) / sizeof(load_dsa[0])]; */
+ u_int32_t resel[25];
+} __attribute__((__packed__));
+
+/*
+ * This decribes a command handled by the SCSI controller
+ * These are chained in either a free list or a active list
+ * We have one queue per target
+ */
+
+struct siop_cmd {
+ TAILQ_ENTRY (siop_cmd) next;
+ struct siop_common_cmd cmd_c;
+ struct siop_cbd *siop_cbdp; /* pointer to our siop_cbd */
+ int reselslot;
+};
+#define cmd_tables cmd_c.siop_tables
+
+/* command block descriptors: an array of siop_cmd + an array of siop_xfer */
+struct siop_cbd {
+ TAILQ_ENTRY (siop_cbd) next;
+ struct siop_cmd *cmds;
+ struct siop_xfer *xfers;
+ bus_dmamap_t xferdma; /* DMA map for this block of xfers */
+};
+
+/* per-tag struct */
+struct siop_tag {
+ struct siop_cmd *active; /* active command */
+ u_int reseloff;
+};
+
+/* per lun struct */
+struct siop_lun {
+ struct siop_tag siop_tag[SIOP_NTAG]; /* tag array */
+ int lun_flags;
+#define SIOP_LUNF_FULL 0x01 /* queue full message */
+ u_int reseloff;
+};
+
+/*
+ * per target struct; siop_common_cmd->target and siop_common_softc->targets[]
+ * will point to this
+ */
+struct siop_target {
+ struct siop_common_target target_c;
+ struct siop_lun *siop_lun[8]; /* per-lun state */
+ u_int reseloff;
+ struct siop_lunsw *lunsw;
+};
+
+struct siop_lunsw {
+ TAILQ_ENTRY (siop_lunsw) next;
+ u_int32_t lunsw_off; /* offset of this lun sw, from sc_scriptaddr*/
+ u_int32_t lunsw_size; /* size of this lun sw */
+};
+
+static __inline__ void siop_table_sync(struct siop_cmd *, int);
+static __inline__ void
+siop_table_sync(siop_cmd, ops)
+ struct siop_cmd *siop_cmd;
+ int ops;
+{
+ struct siop_common_softc *sc = siop_cmd->cmd_c.siop_sc;
+ bus_addr_t offset;
+
+ offset = siop_cmd->cmd_c.dsa -
+ siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
+ bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
+ sizeof(struct siop_xfer), ops);
+}
+
+
TAILQ_HEAD(cmd_list, siop_cmd);
TAILQ_HEAD(cbd_list, siop_cbd);
TAILQ_HEAD(lunsw_list, siop_lunsw);
+
/* Driver internal state */
struct siop_softc {
- struct device sc_dev;
- struct scsi_link sc_link; /* link to upper level */
- int features; /* chip's features */
- int ram_size;
- int maxburst;
- int maxoff;
- int clock_div; /* async. clock divider (scntl3) */
- int min_dt_sync; /* minimum acceptable double transition sync */
- int min_st_sync; /* minimum acceptable single transition sync */
- int scf_index; /* clock id == index into period_factor[].scf */
- bus_space_tag_t sc_rt; /* bus_space registers tag */
- bus_space_handle_t sc_rh; /* bus_space registers handle */
- bus_addr_t sc_raddr; /* register adresses */
- bus_space_tag_t sc_ramt; /* bus_space ram tag */
- bus_space_handle_t sc_ramh; /* bus_space ram handle */
- bus_dma_tag_t sc_dmat; /* bus DMA tag */
- void (*sc_reset)(struct siop_softc*); /* reset callback */
- bus_dmamap_t sc_scriptdma; /* DMA map for script */
- bus_addr_t sc_scriptaddr; /* on-board ram or physical adress */
- u_int32_t *sc_script; /* script location in memory */
+ struct siop_common_softc sc_c;
int sc_currschedslot; /* current scheduler slot */
struct cbd_list cmds; /* list of command block descriptors */
struct cmd_list free_list; /* cmd descr free list */
@@ -67,34 +131,14 @@ struct siop_softc {
struct lunsw_list lunsw_list; /* lunsw free list */
u_int32_t script_free_lo; /* free ram offset from sc_scriptaddr */
u_int32_t script_free_hi; /* free ram offset from sc_scriptaddr */
- struct siop_target *targets[16]; /* per-target states */
int sc_ntargets; /* number of known targets */
u_int32_t sc_flags;
};
+
/* defs for sc_flags */
-/* none for now */
-
-/* features */
-#define SF_BUS_WIDE 0x00000001 /* wide bus */
-#define SF_BUS_ULTRA 0x00000002 /* Ultra (20Mhz) bus */
-#define SF_BUS_ULTRA2 0x00000004 /* Ultra2 (40Mhz) bus */
-#define SF_BUS_DIFF 0x00000008 /* differential bus */
-
-#define SF_CHIP_LED0 0x00000100 /* led on GPIO0 */
-#define SF_CHIP_DBLR 0x00000200 /* clock doubler */
-#define SF_CHIP_QUAD 0x00000400 /* clock quadrupler */
-#define SF_CHIP_FIFO 0x00000800 /* large fifo */
-#define SF_CHIP_PF 0x00001000 /* Intructions prefetch */
-#define SF_CHIP_RAM 0x00002000 /* on-board RAM */
-#define SF_CHIP_LS 0x00004000 /* load/store instruction */
-#define SF_CHIP_10REGS 0x00008000 /* 10 scratch registers */
-#define SF_CHIP_C10 0x00010000 /* 1010 or variant */
-
-#define SF_PCI_RL 0x01000000 /* PCI read line */
-#define SF_PCI_RM 0x02000000 /* PCI read multiple */
-#define SF_PCI_BOF 0x04000000 /* PCI burst opcode fetch */
-#define SF_PCI_CLS 0x08000000 /* PCI cache line size */
-#define SF_PCI_WRI 0x10000000 /* PCI write and invalidate */
+#define SCF_CHAN_NOSLOT 0x0001 /* channel out of sheduler slot */
void siop_attach(struct siop_softc *);
int siop_intr(void *);
+void siop_add_dev(struct siop_softc *, int, int);
+void siop_del_dev(struct siop_softc *, int, int);
diff --git a/sys/dev/ic/siopvar_common.h b/sys/dev/ic/siopvar_common.h
index 93929a00cc5..ef4be6fad3d 100644
--- a/sys/dev/ic/siopvar_common.h
+++ b/sys/dev/ic/siopvar_common.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: siopvar_common.h,v 1.10 2002/03/14 01:26:55 millert Exp $ */
-/* $NetBSD: siopvar_common.h,v 1.10 2001/01/26 21:58:56 bouyer Exp $ */
+/* $OpenBSD: siopvar_common.h,v 1.11 2002/09/16 00:53:12 krw Exp $ */
+/* $NetBSD: siopvar_common.h,v 1.21 2002/05/04 18:43:22 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -14,7 +14,7 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by Manuel Bouyer
+ * This product includes software developed by Manuel Bouyer.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
@@ -38,83 +38,56 @@
#endif
/* tables used by SCRIPT */
-struct scr_table {
+typedef struct scr_table {
u_int32_t count;
u_int32_t addr;
-} __attribute__((__packed__));
+} scr_table_t __attribute__((__packed__));
/* Number of scatter/gather entries */
#define SIOP_NSG (MAXPHYS/NBPG + 1) /* XXX NBPG */
-/* Number of tags, also number of openings if tags are used */
-#define SIOP_NTAG 16
-
-/* Number of openings if tags are not used */
-#define SIOP_OPENINGS 2
-
/*
* This structure interfaces the SCRIPT with the driver; it describes a full
* transfer.
+ * If you change something here, don't forget to update offsets in {s,es}iop.ss
*/
-struct siop_xfer_common {
- u_int8_t msg_out[16]; /* 0 */
- u_int8_t msg_in[16]; /* 16 */
- u_int32_t status; /* 32 */
- u_int32_t pad1; /* 36 */
- u_int32_t id; /* 40 */
- u_int32_t pad2; /* 44 */
- struct scr_table t_msgin; /* 48 */
- struct scr_table t_extmsgin; /* 56 */
- struct scr_table t_extmsgdata; /* 64 */
- struct scr_table t_msgout; /* 72 */
- struct scr_table cmd; /* 80 */
- struct scr_table t_status; /* 88 */
- struct scr_table data[SIOP_NSG]; /* 96 */
+struct siop_common_xfer {
+ u_int8_t msg_out[16]; /* 0 */
+ u_int8_t msg_in[16]; /* 16 */
+ u_int32_t status; /* 32 */
+ u_int32_t pad1; /* 36 */
+ u_int32_t id; /* 40 */
+ u_int32_t pad2; /* 44 */
+ scr_table_t t_msgin; /* 48 */
+ scr_table_t t_extmsgin; /* 56 */
+ scr_table_t t_extmsgdata; /* 64 */
+ scr_table_t t_msgout; /* 72 */
+ scr_table_t cmd; /* 80 */
+ scr_table_t t_status; /* 88 */
+ scr_table_t data[SIOP_NSG]; /* 96 */
} __attribute__((__packed__));
-/* status can hold the SCSI_* status values, and 2 additional values: */
+/* status can hold the SCSI_* status values, and 2 additionnal values: */
#define SCSI_SIOP_NOCHECK 0xfe /* don't check the scsi status */
#define SCSI_SIOP_NOSTATUS 0xff /* device didn't report status */
-/* xfer description of the script: tables and reselect script */
-struct siop_xfer {
- struct siop_xfer_common tables;
- /* u_int32_t resel[sizeof(load_dsa) / sizeof(load_dsa[0])]; */
- u_int32_t resel[25];
-} __attribute__((__packed__));
-
/*
- * This describes a command handled by the SCSI controller.
- * These are chained in either a free list or a active list.
- * We have one queue per target.
+ * This decribes a command handled by the SCSI controller
*/
-struct siop_cmd {
- TAILQ_ENTRY (siop_cmd) next;
- struct siop_softc *siop_sc; /* points back to our adapter */
- struct siop_target *siop_target; /* pointer to our target def */
+struct siop_common_cmd {
+ struct siop_common_softc *siop_sc; /* points back to our adapter */
+ struct siop_common_target *siop_target; /* pointer to our target def */
struct scsi_xfer *xs; /* xfer from the upper level */
- struct siop_xfer *siop_xfer; /* tables dealing with this xfer */
-#define siop_tables siop_xfer->tables
- struct siop_cbd *siop_cbdp; /* pointer to our siop_cbd */
+ struct siop_common_xfer *siop_tables; /* tables for this cmd */
+ struct scsi_sense rs_cmd; /* request sense command buffer */
bus_addr_t dsa; /* DSA value to load */
bus_dmamap_t dmamap_cmd;
bus_dmamap_t dmamap_data;
- struct scsi_sense rs_cmd; /* request sense command buffer */
int status;
int flags;
- int reselslot; /* the reselect slot used */
int tag; /* tag used for tagged command queuing */
};
-/* command block descriptors: an array of siop_cmd + an array of siop_xfer */
-
-struct siop_cbd {
- TAILQ_ENTRY (siop_cbd) next;
- struct siop_cmd *cmds;
- struct siop_xfer *xfers;
- bus_dmamap_t xferdma; /* DMA map for this block of xfers */
-};
-
/* status defs */
#define CMDST_FREE 0 /* cmd slot is free */
#define CMDST_READY 1 /* cmd slot is waiting for processing */
@@ -127,34 +100,13 @@ struct siop_cbd {
#define CMDFL_TIMEOUT 0x0001 /* cmd timed out */
#define CMDFL_TAG 0x0002 /* tagged cmd */
-/* per-tag struct */
-struct siop_tag {
- struct siop_cmd *active; /* active command */
- u_int reseloff; /* XXX */
-};
-
-/* per lun struct */
-struct siop_lun {
- struct siop_tag siop_tag[SIOP_NTAG]; /* tag array */
- int lun_flags; /* per-lun flags, see below */
- u_int reseloff; /* XXX */
-};
-
-#define SIOP_LUNF_FULL 0x01 /* queue full message */
-
/* per-target struct */
-struct siop_target {
+struct siop_common_target {
int status; /* target status, see below */
int flags; /* target flags, see below */
- u_int32_t id; /* for SELECT FROM
- * 31-24 == SCNTL3
- * 23-16 == SCSI id
- * 15- 8 == SXFER
- * 7- 0 == SCNTL4
- */
- struct siop_lun *siop_lun[8]; /* per-lun state */
- u_int reseloff; /* XXX */
- struct siop_lunsw *lunsw; /* XXX */
+ u_int32_t id; /* for SELECT FROM */
+ int period;
+ int offset;
};
/* target status */
@@ -162,67 +114,89 @@ struct siop_target {
#define TARST_ASYNC 1 /* target needs sync/wide negotiation */
#define TARST_WIDE_NEG 2 /* target is doing wide negotiation */
#define TARST_SYNC_NEG 3 /* target is doing sync negotiation */
-#define TARST_PPR_NEG 4 /* target is doing PPR (Parallel Protocol Request) */
+#define TARST_PPR_NEG 4 /* target is doing sync negotiation */
#define TARST_OK 5 /* sync/wide agreement is valid */
/* target flags */
-#define TARF_SYNC 0x01 /* target can do sync xfers */
-#define TARF_WIDE 0x02 /* target can do wide xfers */
-#define TARF_TAG 0x04 /* target can do taggged queuing */
-#define TARF_PPR 0x08 /* target can do PPR negotiation */
-
-#define TARF_ISWIDE 0x10 /* target is using wide xfers */
-#define TARF_ISIUS 0x20 /* target is using IUS */
-#define TARF_ISDT 0x40 /* target is using DT */
-#define TARF_ISQAS 0x80 /* target is using QAS */
-
-struct siop_lunsw {
- TAILQ_ENTRY (siop_lunsw) next;
- u_int32_t lunsw_off; /* offset of this lun sw, from sc_scriptaddr*/
- u_int32_t lunsw_size; /* size of this lun sw */
+#define TARF_SYNC 0x01 /* target can do sync */
+#define TARF_WIDE 0x02 /* target can do wide */
+#define TARF_TAG 0x04 /* target can do tags */
+#define TARF_DT 0x08 /* target can do DT clocking */
+#define TARF_ISWIDE 0x10 /* target is wide */
+#define TARF_ISDT 0x20 /* target is doing DT clocking */
+
+/* Driver internal state */
+struct siop_common_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link; /* link to upper level */
+ int features; /* chip's features */
+ int ram_size;
+ int maxburst;
+ int maxoff;
+ int clock_div; /* async. clock divider (scntl3) */
+ int clock_period; /* clock period (ns * 10) */
+ int st_minsync; /* min and max sync period, */
+ int dt_minsync;
+ int st_maxsync; /* as sent in or PPR messages */
+ int dt_maxsync;
+ int mode; /* current SE/LVD/HVD mode */
+ bus_space_tag_t sc_rt; /* bus_space registers tag */
+ bus_space_handle_t sc_rh; /* bus_space registers handle */
+ bus_addr_t sc_raddr; /* register adresses */
+ bus_space_tag_t sc_ramt; /* bus_space ram tag */
+ bus_space_handle_t sc_ramh; /* bus_space ram handle */
+ bus_dma_tag_t sc_dmat; /* bus DMA tag */
+ void (*sc_reset)(struct siop_common_softc*); /* reset callback */
+ bus_dmamap_t sc_scriptdma; /* DMA map for script */
+ bus_addr_t sc_scriptaddr; /* on-board ram or physical adress */
+ u_int32_t *sc_script; /* script location in memory */
+ struct siop_common_target *targets[16]; /* per-target states */
};
-static __inline__ void siop_table_sync(struct siop_cmd *, int);
-static __inline__ void
-siop_table_sync(siop_cmd, ops)
- struct siop_cmd *siop_cmd;
- int ops;
-{
- struct siop_softc *sc = siop_cmd->siop_sc;
- bus_addr_t offset;
-
- offset = siop_cmd->dsa -
- siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
- bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
- sizeof(struct siop_xfer), ops);
-}
-
-void siop_common_reset(struct siop_softc *);
-void siop_setuptables(struct siop_cmd *);
-int siop_modechange(struct siop_softc *);
-
-int siop_wdtr_neg(struct siop_cmd *);
-int siop_sdtr_neg(struct siop_cmd *);
-int siop_ppr_neg(struct siop_cmd *);
-void siop_sdtr_msg(struct siop_cmd *, int, int, int);
-void siop_wdtr_msg(struct siop_cmd *, int, int);
-void siop_ppr_msg(struct siop_cmd *, int, int, int);
-
-/* actions to take at return of siop_<xxx>_neg() */
+/* features */
+#define SF_BUS_WIDE 0x00000001 /* wide bus */
+#define SF_BUS_ULTRA 0x00000002 /* Ultra (20Mhz) bus */
+#define SF_BUS_ULTRA2 0x00000004 /* Ultra2 (40Mhz) bus */
+#define SF_BUS_ULTRA3 0x00000008 /* Ultra3 (80Mhz) bus */
+#define SF_BUS_DIFF 0x00000010 /* differential bus */
+
+#define SF_CHIP_LED0 0x00000100 /* led on GPIO0 */
+#define SF_CHIP_LEDC 0x00000200 /* led on GPIO0 with hardware control */
+#define SF_CHIP_DBLR 0x00000400 /* clock doubler or quadrupler */
+#define SF_CHIP_QUAD 0x00000800 /* clock quadrupler, with PPL */
+#define SF_CHIP_FIFO 0x00001000 /* large fifo */
+#define SF_CHIP_PF 0x00002000 /* Intructions prefetch */
+#define SF_CHIP_RAM 0x00004000 /* on-board RAM */
+#define SF_CHIP_LS 0x00008000 /* load/store instruction */
+#define SF_CHIP_10REGS 0x00010000 /* 10 scratch registers */
+#define SF_CHIP_DFBC 0x00020000 /* Use DFBC register */
+#define SF_CHIP_DT 0x00040000 /* DT clocking */
+#define SF_CHIP_GEBUG 0x00080000 /* SCSI gross error bug */
+
+#define SF_PCI_RL 0x01000000 /* PCI read line */
+#define SF_PCI_RM 0x02000000 /* PCI read multiple */
+#define SF_PCI_BOF 0x04000000 /* PCI burst opcode fetch */
+#define SF_PCI_CLS 0x08000000 /* PCI cache line size */
+#define SF_PCI_WRI 0x10000000 /* PCI write and invalidate */
+
+int siop_common_attach(struct siop_common_softc *);
+void siop_common_reset(struct siop_common_softc *);
+void siop_setuptables(struct siop_common_cmd *);
+int siop_modechange(struct siop_common_softc *);
+
+int siop_wdtr_neg(struct siop_common_cmd *);
+int siop_sdtr_neg(struct siop_common_cmd *);
+int siop_ppr_neg(struct siop_common_cmd *);
+void siop_sdtr_msg(struct siop_common_cmd *, int, int, int);
+void siop_wdtr_msg(struct siop_common_cmd *, int, int);
+void siop_ppr_msg(struct siop_common_cmd *, int, int, int);
+void siop_update_xfer_mode(struct siop_common_softc *, int);
+/* actions to take at return of siop_wdtr_neg() and siop_sdtr_neg() */
#define SIOP_NEG_NOP 0x0
#define SIOP_NEG_MSGOUT 0x1
#define SIOP_NEG_ACK 0x2
-#define SIOP_NEG_MSGREJ 0x3
-void siop_print_info(struct siop_softc *, int);
void siop_minphys(struct buf *);
-void siop_sdp(struct siop_cmd *);
-void siop_clearfifo(struct siop_softc *);
-void siop_resetbus(struct siop_softc *);
-
-int siop_period_factor_to_scf(struct siop_softc *, int, int);
-int siop_scf_to_period_factor(struct siop_softc *, int, int);
-
-/* XXXX should be callbacks */
-void siop_add_dev(struct siop_softc *, int, int);
-void siop_del_dev(struct siop_softc *, int, int);
+void siop_sdp(struct siop_common_cmd *);
+void siop_clearfifo(struct siop_common_softc *);
+void siop_resetbus(struct siop_common_softc *);