summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-08-30 21:22:26 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-08-30 21:22:26 +0000
commita09b456942fab69b475d9e9e5c6b9d7e517bd06b (patch)
treef3eabb0c11c4e5516569b58e209138605851b686 /sys/arch
parent25aec09563340fddf243450ef5287b5908a15f9b (diff)
Add support for ISP2200 SBus FC cards.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc/dev/isp_sbus.c123
1 files changed, 120 insertions, 3 deletions
diff --git a/sys/arch/sparc/dev/isp_sbus.c b/sys/arch/sparc/dev/isp_sbus.c
index 97acb49f4a1..bd5b062d6b2 100644
--- a/sys/arch/sparc/dev/isp_sbus.c
+++ b/sys/arch/sparc/dev/isp_sbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp_sbus.c,v 1.28 2009/06/24 11:38:40 deraadt Exp $ */
+/* $OpenBSD: isp_sbus.c,v 1.29 2009/08/30 21:22:25 kettenis Exp $ */
/*
* SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
*
@@ -46,6 +46,7 @@
#ifndef ISP_NOFIRMWARE
#define ISP_FIRMWARE_1000
+#define ISP_FIRMWARE_2200
#endif
#if defined(ISP_FIRMWARE_1000)
@@ -54,6 +55,13 @@
#define ISP_1000_RISC_CODE NULL
#endif
+#if defined(ISP_FIRMWARE_2200)
+#define ISP_2200_RISC_CODE (u_int16_t *) isp_2200_risc_code
+#include <dev/microcode/isp/asm_2200.h>
+#else
+#define ISP_2200_RISC_CODE NULL
+#endif
+
#define ISP_SBUSIFY_ISPHDR(isp, hdrp) \
ISP_SWAP8((hdrp)->rqs_entry_count, (hdrp)->rqs_entry_type); \
ISP_SWAP8((hdrp)->rqs_flags, (hdrp)->rqs_seqno);
@@ -65,8 +73,12 @@
static int
isp_sbus_rd_isr(struct ispsoftc *, u_int32_t *, u_int16_t *, u_int16_t *);
+static int
+isp_sbus_rd_isr_2200(struct ispsoftc *, u_int32_t *, u_int16_t *, u_int16_t *);
static u_int32_t isp_sbus_rd_reg(struct ispsoftc *, int);
static void isp_sbus_wr_reg(struct ispsoftc *, int, u_int32_t);
+static u_int32_t isp_sbus_rd_reg_2200(struct ispsoftc *, int);
+static void isp_sbus_wr_reg_2200(struct ispsoftc *, int, u_int32_t);
static int isp_sbus_mbxdma(struct ispsoftc *);
static int isp_sbus_dmasetup(struct ispsoftc *, struct scsi_xfer *,
ispreq_t *, u_int32_t *, u_int32_t);
@@ -84,10 +96,23 @@ static struct ispmdvec mdvec = {
NULL,
NULL,
NULL,
- (u_int16_t *) ISP_1000_RISC_CODE,
+ ISP_1000_RISC_CODE,
BIU_BURST_ENABLE|BIU_SBUS_CONF1_FIFO_32
};
+static struct ispmdvec mdvec_2200 = {
+ isp_sbus_rd_isr_2200,
+ isp_sbus_rd_reg_2200,
+ isp_sbus_wr_reg_2200,
+ isp_sbus_mbxdma,
+ isp_sbus_dmasetup,
+ isp_sbus_dmateardown,
+ NULL,
+ NULL,
+ NULL,
+ ISP_2200_RISC_CODE
+};
+
struct isp_sbussoftc {
struct ispsoftc sbus_isp;
sdparam sbus_dev;
@@ -122,7 +147,9 @@ isp_match(struct device *parent, void *cfarg, void *aux)
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);
+ strcmp("SUNW,qlc", ra->ra_name) == 0 ||
+ strcmp("QLGC,isp", ra->ra_name) == 0 ||
+ strcmp("QLGC,qla", ra->ra_name) == 0);
if (rv == 0)
return (rv);
#ifdef DEBUG
@@ -148,6 +175,7 @@ isp_sbus_attach(struct device *parent, struct device *self, void *aux)
struct bootpath *bp;
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self;
struct ispsoftc *isp = &sbc->sbus_isp;
+ volatile u_int16_t *fpga_reg;
if (ca->ca_ra.ra_nintr != 1) {
printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
@@ -221,6 +249,35 @@ isp_sbus_attach(struct device *parent, struct device *self, void *aux)
sbc->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
+ if (strcmp("SUNW,qlc", ca->ca_ra.ra_name) == 0 ||
+ strcmp("QLGC,qla", ca->ca_ra.ra_name) == 0) {
+ isp->isp_mdvec = &mdvec_2200;
+ isp->isp_bustype = ISP_BT_PCI;
+ isp->isp_type = ISP_HA_FC_2200;
+ isp->isp_param = malloc(sizeof(fcparam), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (isp->isp_param == NULL) {
+ printf("%s: no mem for sdparam table\n",
+ self->dv_xname);
+ return;
+ }
+ sbc->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] =
+ 0x100 + BIU_REGS_OFF;
+ sbc->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
+ 0x100 + PCI_MBOX_REGS2100_OFF;
+ sbc->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] =
+ 0x100 + PCI_SXP_REGS_OFF;
+ sbc->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] =
+ 0x100 + PCI_RISC_REGS_OFF;
+ sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
+ 0x100 + DMA_REGS_OFF;
+
+ fpga_reg = mapiodev(&ca->ca_ra.ra_reg[1], 0,
+ ca->ca_ra.ra_reg[1].rr_len);
+ fpga_reg[0x80] &= ~htole16(0x700);
+ fpga_reg[0x80] |= htole16(0x300);
+ }
+
/* Establish interrupt channel */
sbc->sbus_ih.ih_fun = (void *) isp_sbus_intr;
sbc->sbus_ih.ih_arg = sbc;
@@ -312,6 +369,28 @@ isp_sbus_rd_isr(struct ispsoftc *isp, u_int32_t *isrp,
return (1);
}
+static int
+isp_sbus_rd_isr_2200(struct ispsoftc *isp, u_int32_t *isrp,
+ u_int16_t *semap, u_int16_t *mbp)
+{
+ struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
+ volatile u_int16_t isr, sema;
+
+ isr = letoh16(BXR2(pcs, IspVirt2Off(isp, BIU_ISR)));
+ sema = letoh16(BXR2(pcs, IspVirt2Off(isp, BIU_SEMA)));
+ isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
+ isr &= INT_PENDING_MASK(isp);
+ sema &= BIU_SEMA_LOCK;
+ if (isr == 0 && sema == 0) {
+ return (0);
+ }
+ *isrp = isr;
+ if ((*semap = sema) != 0) {
+ *mbp = letoh16(BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0)));
+ }
+ return (1);
+}
+
static u_int32_t
isp_sbus_rd_reg(struct ispsoftc *isp, int regoff)
{
@@ -330,6 +409,23 @@ isp_sbus_wr_reg(struct ispsoftc *isp, int regoff, u_int32_t val)
sbc->sbus_reg[offset >> 1] = val;
}
+static u_int32_t
+isp_sbus_rd_reg_2200(struct ispsoftc *isp, int regoff)
+{
+ struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
+ int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
+ offset += (regoff & 0xff);
+ return ((u_int16_t) letoh16(sbc->sbus_reg[offset >> 1]));
+}
+
+static void
+isp_sbus_wr_reg_2200(struct ispsoftc *isp, int regoff, u_int32_t val)
+{
+ struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
+ int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
+ offset += (regoff & 0xff);
+ sbc->sbus_reg[offset >> 1] = htole16(val);
+}
static int
isp_sbus_mbxdma(struct ispsoftc *isp)
@@ -384,6 +480,27 @@ isp_sbus_mbxdma(struct ispsoftc *isp)
printf("%s: can't mapin result queue\n", isp->isp_name);
return (1);
}
+
+ if (IS_FC(isp)) {
+ /*
+ * Allocate and map the FC scratch area.
+ */
+ len = ISP2100_SCRLEN;
+ FCPARAM(isp)->isp_scratch = malloc(len, M_DEVBUF, M_NOWAIT);
+ if (FCPARAM(isp)->isp_scratch == 0) {
+ printf("%s: cannot allocate FC scratch area\n",
+ isp->isp_name);
+ return (1);
+ }
+ FCPARAM(isp)->isp_scdma = (u_int32_t)
+ kdvma_mapin((caddr_t)FCPARAM(isp)->isp_scratch, len, 0);
+ if (FCPARAM(isp)->isp_scdma == 0) {
+ printf("%s: can't mapin FC scratch area\n",
+ isp->isp_name);
+ return (1);
+ }
+ }
+
return (0);
}