diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-08-30 21:22:26 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-08-30 21:22:26 +0000 |
commit | a09b456942fab69b475d9e9e5c6b9d7e517bd06b (patch) | |
tree | f3eabb0c11c4e5516569b58e209138605851b686 /sys/arch | |
parent | 25aec09563340fddf243450ef5287b5908a15f9b (diff) |
Add support for ISP2200 SBus FC cards.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/dev/isp_sbus.c | 123 |
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); } |