summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev/isp_sbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sparc/dev/isp_sbus.c')
-rw-r--r--sys/arch/sparc/dev/isp_sbus.c227
1 files changed, 127 insertions, 100 deletions
diff --git a/sys/arch/sparc/dev/isp_sbus.c b/sys/arch/sparc/dev/isp_sbus.c
index 70c30a1958f..58d9e86f9e8 100644
--- a/sys/arch/sparc/dev/isp_sbus.c
+++ b/sys/arch/sparc/dev/isp_sbus.c
@@ -1,10 +1,9 @@
-/* $OpenBSD: isp_sbus.c,v 1.4 1999/01/11 05:11:56 millert Exp $ */
-/* $NetBSD: isp_sbus.c,v 1.8 1997/08/27 11:24:19 bouyer Exp $ */
-
+/* $OpenBSD: isp_sbus.c,v 1.5 1999/03/17 05:20:24 mjacob Exp $ */
+/* release_03_16_99A */
/*
* SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
*
- * Copyright (c) 1997 by Matthew Jacob
+ * Copyright (c) 1997 by Matthew Jacob
* NASA AMES Research Center
* All rights reserved.
*
@@ -31,35 +30,31 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
+#include <sys/device.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/queue.h>
-#include <sys/device.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
#include <machine/autoconf.h>
-#include <sparc/cpu.h>
-#include <sparc/sparc/cpuvar.h>
-#include <sparc/dev/sbusvar.h>
-
-#include <dev/ic/ispreg.h>
-#include <dev/ic/ispvar.h>
-#include <dev/microcode/isp/asm_sbus.h>
+#include <machine/cpu.h>
#include <machine/param.h>
#include <machine/vmparam.h>
+#include <sparc/sparc/cpuvar.h>
+#include <dev/ic/isp_openbsd.h>
+#include <dev/microcode/isp/asm_sbus.h>
static u_int16_t isp_sbus_rd_reg __P((struct ispsoftc *, int));
static void isp_sbus_wr_reg __P((struct ispsoftc *, int, u_int16_t));
static int isp_sbus_mbxdma __P((struct ispsoftc *));
-static int isp_sbus_dmasetup __P((struct ispsoftc *, struct scsipi_xfer *,
+static int isp_sbus_dmasetup __P((struct ispsoftc *, struct scsi_xfer *,
ispreq_t *, u_int8_t *, u_int8_t));
-static void isp_sbus_dmateardown __P((struct ispsoftc *, struct scsipi_xfer *,
+static void isp_sbus_dmateardown __P((struct ispsoftc *, struct scsi_xfer *,
u_int32_t));
static struct ispmdvec mdvec = {
@@ -75,57 +70,75 @@ static struct ispmdvec mdvec = {
ISP_CODE_LENGTH,
ISP_CODE_ORG,
ISP_CODE_VERSION,
- 0,
+ BIU_BURST_ENABLE,
0
};
struct isp_sbussoftc {
- struct ispsoftc sbus_isp;
- sdparam sbus_dev;
+ struct ispsoftc sbus_isp;
+ sdparam sbus_dev;
struct intrhand sbus_ih;
volatile u_char *sbus_reg;
- int sbus_node;
- int sbus_pri;
- vm_offset_t sbus_kdma_allocs[MAXISPREQUEST];
+ int sbus_node;
+ int sbus_pri;
+ struct ispmdvec sbus_mdvec;
+ vm_offset_t sbus_kdma_allocs[MAXISPREQUEST];
+ int16_t sbus_poff[_NREG_BLKS];
};
static int isp_match __P((struct device *, void *, void *));
static void isp_sbus_attach __P((struct device *, struct device *, void *));
struct cfattach isp_sbus_ca = {
- sizeof (struct isp_sbussoftc), isp_match, isp_sbus_attach
+ sizeof (struct isp_sbussoftc), isp_match, isp_sbus_attach
};
static int
-isp_match(parent, vcf, aux)
+isp_match(parent, cfarg, aux)
struct device *parent;
- void *vcf, *aux;
+ void *cfarg;
+ void *aux;
{
- struct cfdata *cf = vcf;
- struct confargs *ca = aux;
- register struct romaux *ra = &ca->ca_ra;
-
- if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
- strcmp("SUNW,isp", ra->ra_name) &&
- strcmp("QLGC,isp", ra->ra_name)) {
- return (0);
+ int rv;
+ struct cfdata *cf = cfarg;
+#ifdef DEBUG
+ static int oneshot = 1;
+#endif
+ struct confargs *ca = aux;
+ register struct romaux *ra = &ca->ca_ra;
+
+ rv = (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0 ||
+ strcmp("PTI,ptisp", ra->ra_name) == 0 ||
+ strcmp("ptisp", ra->ra_name) == 0 ||
+ strcmp("SUNW,isp", ra->ra_name) == 0 ||
+ strcmp("QLGC,isp", ra->ra_name) == 0);
+ if (rv == 0)
+ return (rv);
+#ifdef DEBUG
+ if (rv && oneshot) {
+ oneshot = 0;
+ printf("Qlogic ISP Driver, NetBSD (sbus) Platform Version "
+ "%d.%d Core Version %d.%d\n",
+ ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
+ ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
}
- if (ca->ca_bustype == BUS_SBUS) {
- if (!sbus_testdma((struct sbus_softc *)parent, ca))
- return (0);
+#endif
+ if (ca->ca_bustype == BUS_SBUS)
return (1);
- }
ra->ra_len = NBPG;
return (probeget(ra->ra_vaddr, 1) != -1);
}
-static void
+static void
isp_sbus_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
+ int freq;
struct confargs *ca = aux;
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self;
+ struct ispsoftc *isp = &sbc->sbus_isp;
+ ISP_LOCKVAL_DECL;
if (ca->ca_ra.ra_nintr != 1) {
printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
@@ -133,66 +146,90 @@ isp_sbus_attach(parent, self, aux)
}
sbc->sbus_pri = ca->ca_ra.ra_intr[0].int_pri;
- printf(" pri %d\n", sbc->sbus_pri);
+ sbc->sbus_mdvec = mdvec;
if (ca->ca_ra.ra_vaddr) {
sbc->sbus_reg = (volatile u_char *) ca->ca_ra.ra_vaddr;
} else {
sbc->sbus_reg = (volatile u_char *)
- mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
+ mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
}
sbc->sbus_node = ca->ca_ra.ra_node;
- sbc->sbus_isp.isp_mdvec = &mdvec;
- sbc->sbus_isp.isp_type = ISP_HA_SCSI_UNKNOWN;
- sbc->sbus_isp.isp_param = &sbc->sbus_dev;
- bzero(sbc->sbus_isp.isp_param, sizeof (sdparam));
- isp_reset(&sbc->sbus_isp);
- if (sbc->sbus_isp.isp_state != ISP_RESETSTATE) {
- return;
+ freq = getpropint(ca->ca_ra.ra_node, "clock-frequency", 0);
+ if (freq) {
+ /*
+ * Convert from HZ to MHz, rounding up.
+ */
+ freq = (freq + 500000)/1000000;
+#if 0
+ printf("%s: %d MHz\n", self->dv_xname, freq);
+#endif
}
- isp_init(&sbc->sbus_isp);
- if (sbc->sbus_isp.isp_state != ISP_INITSTATE) {
- isp_uninit(&sbc->sbus_isp);
- return;
+ sbc->sbus_mdvec.dv_clock = freq;
+
+ /*
+ * XXX: Now figure out what the proper burst sizes, etc., to use.
+ */
+ sbc->sbus_mdvec.dv_conf1 |= BIU_SBUS_CONF1_FIFO_8;
+
+ /*
+ * Some early versions of the PTI SBus adapter
+ * would fail in trying to download (via poking)
+ * FW. We give up on them.
+ */
+ if (strcmp("PTI,ptisp", ca->ca_ra.ra_name) == 0 ||
+ strcmp("ptisp", ca->ca_ra.ra_name) == 0) {
+ sbc->sbus_mdvec.dv_fwlen = 0;
}
+
+ isp->isp_mdvec = &sbc->sbus_mdvec;
+ isp->isp_bustype = ISP_BT_SBUS;
+ isp->isp_type = ISP_HA_SCSI_UNKNOWN;
+ isp->isp_param = &sbc->sbus_dev;
+ bzero(isp->isp_param, sizeof (sdparam));
+
+ sbc->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
+ sbc->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
+ sbc->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF;
+ sbc->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
+ sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
+
+ /* Establish interrupt channel */
sbc->sbus_ih.ih_fun = (void *) isp_intr;
sbc->sbus_ih.ih_arg = sbc;
intr_establish(sbc->sbus_pri, &sbc->sbus_ih);
+ ISP_LOCK(isp);
+ isp_reset(isp);
+ if (isp->isp_state != ISP_RESETSTATE) {
+ ISP_UNLOCK(isp);
+ return;
+ }
+ isp_init(isp);
+ if (isp->isp_state != ISP_INITSTATE) {
+ isp_uninit(isp);
+ ISP_UNLOCK(isp);
+ return;
+ }
/*
- * Do Generic attach now.
+ * do generic attach.
*/
- isp_attach(&sbc->sbus_isp);
- if (sbc->sbus_isp.isp_state != ISP_RUNSTATE) {
- isp_uninit(&sbc->sbus_isp);
+ isp_attach(isp);
+ if (isp->isp_state != ISP_RUNSTATE) {
+ isp_uninit(isp);
}
+ ISP_UNLOCK(isp);
}
-#define SBUS_BIU_REGS_OFF 0x00
-#define SBUS_MBOX_REGS_OFF 0x80
-#define SBUS_SXP_REGS_OFF 0x200
-#define SBUS_RISC_REGS_OFF 0x400
-
static u_int16_t
isp_sbus_rd_reg(isp, regoff)
struct ispsoftc *isp;
int regoff;
{
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
-
- int offset;
- if ((regoff & BIU_BLOCK) != 0) {
- offset = SBUS_BIU_REGS_OFF;
- } else if ((regoff & MBOX_BLOCK) != 0) {
- offset = SBUS_MBOX_REGS_OFF;
- } else if ((regoff & SXP_BLOCK) != 0) {
- offset = SBUS_SXP_REGS_OFF;
- } else {
- offset = SBUS_RISC_REGS_OFF;
- }
- regoff &= 0xff;
- offset += regoff;
+ int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
+ offset += (regoff & 0xff);
return (*((u_int16_t *) &sbc->sbus_reg[offset]));
}
@@ -203,22 +240,12 @@ isp_sbus_wr_reg (isp, regoff, val)
u_int16_t val;
{
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
- int offset;
-
- if ((regoff & BIU_BLOCK) != 0) {
- offset = SBUS_BIU_REGS_OFF;
- } else if ((regoff & MBOX_BLOCK) != 0) {
- offset = SBUS_MBOX_REGS_OFF;
- } else if ((regoff & SXP_BLOCK) != 0) {
- offset = SBUS_SXP_REGS_OFF;
- } else {
- offset = SBUS_RISC_REGS_OFF;
- }
- regoff &= 0xff;
- offset += regoff;
+ int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
+ offset += (regoff & 0xff);
*((u_int16_t *) &sbc->sbus_reg[offset]) = val;
}
+
static int
isp_sbus_mbxdma(isp)
struct ispsoftc *isp;
@@ -234,7 +261,7 @@ isp_sbus_mbxdma(isp)
/*
* Allocate and map the request queue.
*/
- len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
+ len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
isp->isp_rquest = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT);
if (isp->isp_rquest == 0)
return (1);
@@ -246,7 +273,7 @@ isp_sbus_mbxdma(isp)
/*
* Allocate and map the result queue.
*/
- len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
+ len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
isp->isp_result = (volatile caddr_t)malloc(len, M_DEVBUF, M_NOWAIT);
if (isp->isp_result == 0)
return (1);
@@ -268,7 +295,7 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr)
struct scsi_xfer *xs;
ispreq_t *rq;
u_int8_t *iptrp;
- u_int8_t optr;
+ u_int8_t optr;
{
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
vm_offset_t kdvma;
@@ -276,12 +303,12 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr)
if (xs->datalen == 0) {
rq->req_seg_count = 1;
- return (0);
+ return (CMD_QUEUED);
}
- if (rq->req_handle > RQUEST_QUEUE_LEN(isp) ||
+ if (rq->req_handle > RQUEST_QUEUE_LEN ||
rq->req_handle < 1) {
- panic("%s: bad handle (%d) in isp_sbus_dmasetup",
+ panic("%s: bad handle (%d) in isp_sbus_dmasetup\n",
isp->isp_name, rq->req_handle);
/* NOTREACHED */
}
@@ -289,14 +316,15 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr)
kdvma = (vm_offset_t)
kdvma_mapin((caddr_t)xs->data, xs->datalen, dosleep);
if (kdvma == (vm_offset_t) 0) {
- return (1);
+ XS_SETERR(xs, HBA_BOTCH);
+ return (CMD_COMPLETE);
}
} else {
kdvma = (vm_offset_t) xs->data;
}
if (sbc->sbus_kdma_allocs[rq->req_handle - 1] != (vm_offset_t) 0) {
- panic("%s: kdma handle already allocated", isp->isp_name);
+ panic("%s: kdma handle already allocated\n", isp->isp_name);
/* NOTREACHED */
}
sbc->sbus_kdma_allocs[rq->req_handle - 1] = kdvma;
@@ -308,7 +336,7 @@ isp_sbus_dmasetup(isp, xs, rq, iptrp, optr)
rq->req_dataseg[0].ds_count = xs->datalen;
rq->req_dataseg[0].ds_base = (u_int32_t) kdvma;
rq->req_seg_count = 1;
- return (0);
+ return (CMD_QUEUED);
}
static void
@@ -323,14 +351,13 @@ isp_sbus_dmateardown(isp, xs, handle)
if (xs->flags & SCSI_DATA_IN) {
cpuinfo.cache_flush(xs->data, xs->datalen - xs->resid);
}
-
- if (handle >= RQUEST_QUEUE_LEN(isp)) {
- panic("%s: bad handle (%d) in isp_sbus_dmateardown",
+ if (handle >= RQUEST_QUEUE_LEN) {
+ panic("%s: bad handle (%d) in isp_sbus_dmateardown\n",
isp->isp_name, handle);
/* NOTREACHED */
}
if (sbc->sbus_kdma_allocs[handle] == (vm_offset_t) 0) {
- panic("%s: kdma handle not already allocated", isp->isp_name);
+ panic("%s: kdma handle not already allocated\n", isp->isp_name);
/* NOTREACHED */
}
kdvma = sbc->sbus_kdma_allocs[handle];