1999-08-28 01:08:13 +00:00
|
|
|
/* $FreeBSD$ */
|
1998-04-22 18:12:29 +00:00
|
|
|
/*
|
|
|
|
* PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
|
|
|
|
* FreeBSD Version.
|
|
|
|
*
|
2001-03-02 06:28:55 +00:00
|
|
|
* Copyright (c) 1997, 1998, 1999, 2000, 2001 by Matthew Jacob
|
1998-04-22 18:12:29 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice immediately at the beginning of the file, without modification,
|
|
|
|
* this list of conditions, and the following disclaimer.
|
2000-09-21 20:16:04 +00:00
|
|
|
* 2. The name of the author may not be used to endorse or promote products
|
|
|
|
* derived from this software without specific prior written permission.
|
1998-04-22 18:12:29 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
1998-09-15 10:06:23 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/bus.h>
|
1998-04-22 18:12:29 +00:00
|
|
|
|
|
|
|
#include <pci/pcireg.h>
|
|
|
|
#include <pci/pcivar.h>
|
|
|
|
|
1998-09-15 10:06:23 +00:00
|
|
|
#include <machine/bus_memio.h>
|
|
|
|
#include <machine/bus_pio.h>
|
|
|
|
#include <machine/bus.h>
|
2000-02-11 19:45:17 +00:00
|
|
|
#include <machine/resource.h>
|
|
|
|
#include <sys/rman.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
|
|
|
|
#include <dev/isp/isp_freebsd.h>
|
1999-03-17 05:07:18 +00:00
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int);
|
|
|
|
static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t);
|
|
|
|
static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int);
|
|
|
|
static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t);
|
|
|
|
static int
|
|
|
|
isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
|
|
|
|
static int
|
|
|
|
isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
|
|
|
|
static int isp_pci_mbxdma(struct ispsoftc *);
|
|
|
|
static int
|
|
|
|
isp_pci_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *, u_int16_t);
|
1998-09-15 10:06:23 +00:00
|
|
|
static void
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_dmateardown(struct ispsoftc *, XS_T *, u_int16_t);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
static void isp_pci_reset1(struct ispsoftc *);
|
|
|
|
static void isp_pci_dumpregs(struct ispsoftc *, const char *);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-10-30 19:35:11 +00:00
|
|
|
#ifndef ISP_CODE_ORG
|
|
|
|
#define ISP_CODE_ORG 0x1000
|
|
|
|
#endif
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
static struct ispmdvec mdvec = {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_isr,
|
1998-04-22 18:12:29 +00:00
|
|
|
isp_pci_rd_reg,
|
|
|
|
isp_pci_wr_reg,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
1998-09-15 10:06:23 +00:00
|
|
|
isp_pci_dmateardown,
|
1998-04-22 18:12:29 +00:00
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
|
|
|
isp_pci_dumpregs,
|
2000-06-18 05:18:55 +00:00
|
|
|
NULL,
|
2000-08-01 05:16:49 +00:00
|
|
|
BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
|
1998-04-22 18:12:29 +00:00
|
|
|
};
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
static struct ispmdvec mdvec_1080 = {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_isr,
|
1999-03-17 05:07:18 +00:00
|
|
|
isp_pci_rd_reg_1080,
|
|
|
|
isp_pci_wr_reg_1080,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
|
|
|
isp_pci_dmateardown,
|
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
|
|
|
isp_pci_dumpregs,
|
2000-06-18 05:18:55 +00:00
|
|
|
NULL,
|
2000-08-01 05:16:49 +00:00
|
|
|
BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
|
1999-03-17 05:07:18 +00:00
|
|
|
};
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static struct ispmdvec mdvec_12160 = {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_isr,
|
2000-02-11 19:45:17 +00:00
|
|
|
isp_pci_rd_reg_1080,
|
|
|
|
isp_pci_wr_reg_1080,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
|
|
|
isp_pci_dmateardown,
|
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
|
|
|
isp_pci_dumpregs,
|
2000-06-18 05:18:55 +00:00
|
|
|
NULL,
|
2000-08-01 05:16:49 +00:00
|
|
|
BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
|
2000-02-11 19:45:17 +00:00
|
|
|
};
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
static struct ispmdvec mdvec_2100 = {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_isr,
|
1998-04-22 18:12:29 +00:00
|
|
|
isp_pci_rd_reg,
|
|
|
|
isp_pci_wr_reg,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
1998-09-15 10:06:23 +00:00
|
|
|
isp_pci_dmateardown,
|
1998-04-22 18:12:29 +00:00
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_pci_dumpregs
|
1998-04-22 18:12:29 +00:00
|
|
|
};
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
|
|
|
|
static struct ispmdvec mdvec_2200 = {
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_isr,
|
|
|
|
isp_pci_rd_reg,
|
|
|
|
isp_pci_wr_reg,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
|
|
|
isp_pci_dmateardown,
|
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
|
|
|
isp_pci_dumpregs
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct ispmdvec mdvec_2300 = {
|
|
|
|
isp_pci_rd_isr_2300,
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
isp_pci_rd_reg,
|
|
|
|
isp_pci_wr_reg,
|
|
|
|
isp_pci_mbxdma,
|
|
|
|
isp_pci_dmasetup,
|
|
|
|
isp_pci_dmateardown,
|
|
|
|
NULL,
|
|
|
|
isp_pci_reset1,
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_pci_dumpregs
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
};
|
1999-02-09 01:12:52 +00:00
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
#ifndef PCIM_CMD_INVEN
|
1998-09-15 10:06:23 +00:00
|
|
|
#define PCIM_CMD_INVEN 0x10
|
1998-04-22 18:12:29 +00:00
|
|
|
#endif
|
|
|
|
#ifndef PCIM_CMD_BUSMASTEREN
|
1998-09-15 10:06:23 +00:00
|
|
|
#define PCIM_CMD_BUSMASTEREN 0x0004
|
1998-04-22 18:12:29 +00:00
|
|
|
#endif
|
1999-02-09 01:12:52 +00:00
|
|
|
#ifndef PCIM_CMD_PERRESPEN
|
|
|
|
#define PCIM_CMD_PERRESPEN 0x0040
|
|
|
|
#endif
|
|
|
|
#ifndef PCIM_CMD_SEREN
|
|
|
|
#define PCIM_CMD_SEREN 0x0100
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PCIR_COMMAND
|
|
|
|
#define PCIR_COMMAND 0x04
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PCIR_CACHELNSZ
|
|
|
|
#define PCIR_CACHELNSZ 0x0c
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PCIR_LATTIMER
|
|
|
|
#define PCIR_LATTIMER 0x0d
|
|
|
|
#endif
|
|
|
|
|
1999-04-04 01:14:02 +00:00
|
|
|
#ifndef PCIR_ROMADDR
|
|
|
|
#define PCIR_ROMADDR 0x30
|
|
|
|
#endif
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
#ifndef PCI_VENDOR_QLOGIC
|
2000-06-18 05:18:55 +00:00
|
|
|
#define PCI_VENDOR_QLOGIC 0x1077
|
1998-04-22 18:12:29 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP1020
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
|
|
|
|
#endif
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP1080
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080
|
|
|
|
#endif
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP12160
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP12160 0x1216
|
|
|
|
#endif
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP1240
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240
|
|
|
|
#endif
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-12-16 05:42:02 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP1280
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP1280 0x1280
|
|
|
|
#endif
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP2100
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
|
|
|
|
#endif
|
|
|
|
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP2200
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
|
|
|
|
#endif
|
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP2300
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP2300 0x2300
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef PCI_PRODUCT_QLOGIC_ISP2312
|
|
|
|
#define PCI_PRODUCT_QLOGIC_ISP2312 0x2312
|
|
|
|
#endif
|
|
|
|
|
2000-06-18 05:18:55 +00:00
|
|
|
#define PCI_QLOGIC_ISP1020 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
|
1999-03-17 05:07:18 +00:00
|
|
|
|
|
|
|
#define PCI_QLOGIC_ISP1080 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
#define PCI_QLOGIC_ISP12160 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
#define PCI_QLOGIC_ISP1240 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
1999-12-16 05:42:02 +00:00
|
|
|
#define PCI_QLOGIC_ISP1280 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
#define PCI_QLOGIC_ISP2100 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
#define PCI_QLOGIC_ISP2200 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
#define PCI_QLOGIC_ISP2300 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
|
|
|
#define PCI_QLOGIC_ISP2312 \
|
|
|
|
((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
|
|
|
|
|
2000-09-07 20:27:40 +00:00
|
|
|
/*
|
|
|
|
* Odd case for some AMI raid cards... We need to *not* attach to this.
|
|
|
|
*/
|
|
|
|
#define AMI_RAID_SUBVENDOR_ID 0x101e
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
#define IO_MAP_REG 0x10
|
|
|
|
#define MEM_MAP_REG 0x14
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-02-09 01:12:52 +00:00
|
|
|
#define PCI_DFLT_LTNCY 0x40
|
|
|
|
#define PCI_DFLT_LNSZ 0x10
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static int isp_pci_probe (device_t);
|
|
|
|
static int isp_pci_attach (device_t);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
|
|
|
struct isp_pcisoftc {
|
1998-09-15 10:06:23 +00:00
|
|
|
struct ispsoftc pci_isp;
|
2000-02-11 19:45:17 +00:00
|
|
|
device_t pci_dev;
|
|
|
|
struct resource * pci_reg;
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_space_tag_t pci_st;
|
|
|
|
bus_space_handle_t pci_sh;
|
2000-02-11 19:45:17 +00:00
|
|
|
void * ih;
|
1999-03-17 05:07:18 +00:00
|
|
|
int16_t pci_poff[_NREG_BLKS];
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_dma_tag_t parent_dmat;
|
|
|
|
bus_dma_tag_t cntrol_dmat;
|
|
|
|
bus_dmamap_t cntrol_dmap;
|
1999-10-17 19:03:11 +00:00
|
|
|
bus_dmamap_t *dmaps;
|
1998-04-22 18:12:29 +00:00
|
|
|
};
|
2000-06-18 05:18:55 +00:00
|
|
|
ispfwfunc *isp_get_firmware_p = NULL;
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static device_method_t isp_pci_methods[] = {
|
|
|
|
/* Device interface */
|
|
|
|
DEVMETHOD(device_probe, isp_pci_probe),
|
|
|
|
DEVMETHOD(device_attach, isp_pci_attach),
|
|
|
|
{ 0, 0 }
|
1998-04-22 18:12:29 +00:00
|
|
|
};
|
2001-08-31 21:39:04 +00:00
|
|
|
static void isp_pci_intr(void *);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static driver_t isp_pci_driver = {
|
|
|
|
"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
|
|
|
|
};
|
|
|
|
static devclass_t isp_devclass;
|
|
|
|
DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0);
|
2000-06-18 05:18:55 +00:00
|
|
|
MODULE_VERSION(isp, 1);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static int
|
|
|
|
isp_pci_probe(device_t dev)
|
1999-03-17 05:07:18 +00:00
|
|
|
{
|
2000-02-11 19:45:17 +00:00
|
|
|
switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) {
|
2000-06-18 05:18:55 +00:00
|
|
|
case PCI_QLOGIC_ISP1020:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter");
|
1999-03-17 05:07:18 +00:00
|
|
|
break;
|
|
|
|
case PCI_QLOGIC_ISP1080:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter");
|
1999-05-11 04:53:57 +00:00
|
|
|
break;
|
|
|
|
case PCI_QLOGIC_ISP1240:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter");
|
1998-04-22 18:12:29 +00:00
|
|
|
break;
|
1999-12-16 05:42:02 +00:00
|
|
|
case PCI_QLOGIC_ISP1280:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter");
|
|
|
|
break;
|
|
|
|
case PCI_QLOGIC_ISP12160:
|
2000-09-07 20:27:40 +00:00
|
|
|
if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) {
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter");
|
1999-12-16 05:42:02 +00:00
|
|
|
break;
|
1998-04-22 18:12:29 +00:00
|
|
|
case PCI_QLOGIC_ISP2100:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter");
|
1998-04-22 18:12:29 +00:00
|
|
|
break;
|
1999-07-05 20:24:46 +00:00
|
|
|
case PCI_QLOGIC_ISP2200:
|
2000-02-11 19:45:17 +00:00
|
|
|
device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter");
|
1999-07-05 20:24:46 +00:00
|
|
|
break;
|
2001-08-31 21:39:04 +00:00
|
|
|
case PCI_QLOGIC_ISP2300:
|
|
|
|
device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter");
|
|
|
|
break;
|
|
|
|
case PCI_QLOGIC_ISP2312:
|
|
|
|
device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter");
|
|
|
|
break;
|
1998-04-22 18:12:29 +00:00
|
|
|
default:
|
2000-02-11 19:45:17 +00:00
|
|
|
return (ENXIO);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2000-08-01 05:16:49 +00:00
|
|
|
if (device_get_unit(dev) == 0 && bootverbose) {
|
|
|
|
printf("Qlogic ISP Driver, FreeBSD Version %d.%d, "
|
1999-10-17 19:03:11 +00:00
|
|
|
"Core Version %d.%d\n",
|
1998-09-15 10:06:23 +00:00
|
|
|
ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
|
|
|
|
ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2000-06-18 05:18:55 +00:00
|
|
|
/*
|
|
|
|
* XXXX: Here is where we might load the f/w module
|
|
|
|
* XXXX: (or increase a reference count to it).
|
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
return (0);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
static int
|
|
|
|
isp_pci_attach(device_t dev)
|
1998-04-22 18:12:29 +00:00
|
|
|
{
|
2000-02-11 19:45:17 +00:00
|
|
|
struct resource *regs, *irq;
|
2001-03-01 02:21:36 +00:00
|
|
|
int tval, rtp, rgd, iqd, m1, m2, isp_debug, role;
|
2000-02-11 19:45:17 +00:00
|
|
|
u_int32_t data, cmd, linesz, psize, basetype;
|
1998-04-22 18:12:29 +00:00
|
|
|
struct isp_pcisoftc *pcs;
|
2000-10-25 04:40:49 +00:00
|
|
|
struct ispsoftc *isp = NULL;
|
1999-05-11 04:53:57 +00:00
|
|
|
struct ispmdvec *mdvp;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
bus_size_t lim;
|
2001-06-15 00:13:18 +00:00
|
|
|
const char *sptr;
|
2000-10-25 04:40:49 +00:00
|
|
|
int locksetup = 0;
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-07-06 01:24:20 +00:00
|
|
|
/*
|
|
|
|
* Figure out if we're supposed to skip this one.
|
2001-02-11 03:53:23 +00:00
|
|
|
* If we are, we actually go to ISP_ROLE_NONE.
|
1999-07-06 01:24:20 +00:00
|
|
|
*/
|
2001-03-01 02:21:36 +00:00
|
|
|
|
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"disable", &tval) == 0 && tval) {
|
|
|
|
device_printf(dev, "device is disabled\n");
|
|
|
|
/* but return 0 so the !$)$)*!$*) unit isn't reused */
|
|
|
|
return (0);
|
2001-02-11 03:53:23 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
|
|
|
|
role = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"role", &role) == 0 &&
|
|
|
|
((role & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) == 0)) {
|
|
|
|
device_printf(dev, "setting role to 0x%x\n", role);
|
|
|
|
} else {
|
2001-02-11 03:53:23 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
2001-03-01 02:21:36 +00:00
|
|
|
role = ISP_ROLE_INITIATOR|ISP_ROLE_TARGET;
|
2001-02-11 03:53:23 +00:00
|
|
|
#else
|
2001-03-01 02:21:36 +00:00
|
|
|
role = ISP_DEFAULT_ROLES;
|
2001-02-11 03:53:23 +00:00
|
|
|
#endif
|
1999-07-06 01:24:20 +00:00
|
|
|
}
|
|
|
|
|
2000-12-08 21:51:06 +00:00
|
|
|
pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT | M_ZERO);
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pcs == NULL) {
|
|
|
|
device_printf(dev, "cannot allocate softc\n");
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
|
|
|
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
/*
|
|
|
|
* Figure out which we should try first - memory mapping or i/o mapping?
|
|
|
|
*/
|
2000-06-18 05:18:55 +00:00
|
|
|
#ifdef __alpha__
|
2000-02-11 19:45:17 +00:00
|
|
|
m1 = PCIM_CMD_MEMEN;
|
|
|
|
m2 = PCIM_CMD_PORTEN;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
#else
|
2000-02-11 19:45:17 +00:00
|
|
|
m1 = PCIM_CMD_PORTEN;
|
|
|
|
m2 = PCIM_CMD_MEMEN;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
#endif
|
2001-03-01 02:21:36 +00:00
|
|
|
|
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"prefer_iomap", &tval) == 0 && tval != 0) {
|
|
|
|
m1 = PCIM_CMD_PORTEN;
|
|
|
|
m2 = PCIM_CMD_MEMEN;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"prefer_memmap", &tval) == 0 && tval != 0) {
|
|
|
|
m1 = PCIM_CMD_MEMEN;
|
|
|
|
m2 = PCIM_CMD_PORTEN;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
|
|
|
|
1999-04-04 01:14:02 +00:00
|
|
|
linesz = PCI_DFLT_LNSZ;
|
2000-02-11 19:45:17 +00:00
|
|
|
irq = regs = NULL;
|
|
|
|
rgd = rtp = iqd = 0;
|
|
|
|
|
|
|
|
cmd = pci_read_config(dev, PCIR_COMMAND, 1);
|
|
|
|
if (cmd & m1) {
|
|
|
|
rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
|
|
|
|
rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
|
|
|
|
regs = bus_alloc_resource(dev, rtp, &rgd, 0, ~0, 1, RF_ACTIVE);
|
1999-02-09 01:12:52 +00:00
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (regs == NULL && (cmd & m2)) {
|
|
|
|
rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
|
|
|
|
rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
|
|
|
|
regs = bus_alloc_resource(dev, rtp, &rgd, 0, ~0, 1, RF_ACTIVE);
|
|
|
|
}
|
|
|
|
if (regs == NULL) {
|
|
|
|
device_printf(dev, "unable to map any ports\n");
|
|
|
|
goto bad;
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (bootverbose)
|
2000-12-05 07:38:41 +00:00
|
|
|
device_printf(dev, "using %s space register mapping\n",
|
2000-02-11 19:45:17 +00:00
|
|
|
(rgd == IO_MAP_REG)? "I/O" : "Memory");
|
|
|
|
pcs->pci_dev = dev;
|
|
|
|
pcs->pci_reg = regs;
|
|
|
|
pcs->pci_st = rman_get_bustag(regs);
|
|
|
|
pcs->pci_sh = rman_get_bushandle(regs);
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
|
|
|
|
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
|
|
|
|
pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
|
|
|
|
pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
|
|
|
|
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
|
1999-05-11 04:53:57 +00:00
|
|
|
mdvp = &mdvec;
|
|
|
|
basetype = ISP_HA_SCSI_UNKNOWN;
|
|
|
|
psize = sizeof (sdparam);
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
lim = BUS_SPACE_MAXSIZE_32BIT;
|
2000-06-18 05:18:55 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP1020) {
|
1999-05-11 04:53:57 +00:00
|
|
|
mdvp = &mdvec;
|
|
|
|
basetype = ISP_HA_SCSI_UNKNOWN;
|
|
|
|
psize = sizeof (sdparam);
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
lim = BUS_SPACE_MAXSIZE_24BIT;
|
1999-03-17 05:07:18 +00:00
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP1080) {
|
1999-05-11 04:53:57 +00:00
|
|
|
mdvp = &mdvec_1080;
|
|
|
|
basetype = ISP_HA_SCSI_1080;
|
|
|
|
psize = sizeof (sdparam);
|
|
|
|
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
ISP1080_DMA_REGS_OFF;
|
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP1240) {
|
1999-05-11 04:53:57 +00:00
|
|
|
mdvp = &mdvec_1080;
|
1999-12-16 05:42:02 +00:00
|
|
|
basetype = ISP_HA_SCSI_1240;
|
|
|
|
psize = 2 * sizeof (sdparam);
|
|
|
|
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
ISP1080_DMA_REGS_OFF;
|
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP1280) {
|
1999-12-16 05:42:02 +00:00
|
|
|
mdvp = &mdvec_1080;
|
|
|
|
basetype = ISP_HA_SCSI_1280;
|
1999-05-11 04:53:57 +00:00
|
|
|
psize = 2 * sizeof (sdparam);
|
1999-03-17 05:07:18 +00:00
|
|
|
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
ISP1080_DMA_REGS_OFF;
|
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP12160) {
|
|
|
|
mdvp = &mdvec_12160;
|
|
|
|
basetype = ISP_HA_SCSI_12160;
|
|
|
|
psize = 2 * sizeof (sdparam);
|
|
|
|
pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
ISP1080_DMA_REGS_OFF;
|
|
|
|
}
|
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP2100) {
|
1999-05-11 04:53:57 +00:00
|
|
|
mdvp = &mdvec_2100;
|
|
|
|
basetype = ISP_HA_FC_2100;
|
|
|
|
psize = sizeof (fcparam);
|
1999-03-17 05:07:18 +00:00
|
|
|
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
PCI_MBOX_REGS2100_OFF;
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_revid(dev) < 3) {
|
1999-04-04 01:14:02 +00:00
|
|
|
/*
|
|
|
|
* XXX: Need to get the actual revision
|
|
|
|
* XXX: number of the 2100 FB. At any rate,
|
|
|
|
* XXX: lower cache line size for early revision
|
|
|
|
* XXX; boards.
|
|
|
|
*/
|
|
|
|
linesz = 1;
|
|
|
|
}
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP2200) {
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
mdvp = &mdvec_2200;
|
|
|
|
basetype = ISP_HA_FC_2200;
|
|
|
|
psize = sizeof (fcparam);
|
|
|
|
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
PCI_MBOX_REGS2100_OFF;
|
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300 ||
|
|
|
|
pci_get_devid(dev) == PCI_QLOGIC_ISP2312) {
|
|
|
|
mdvp = &mdvec_2300;
|
|
|
|
basetype = ISP_HA_FC_2300;
|
|
|
|
psize = sizeof (fcparam);
|
|
|
|
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
|
|
|
|
PCI_MBOX_REGS2300_OFF;
|
|
|
|
}
|
1999-05-11 04:53:57 +00:00
|
|
|
isp = &pcs->pci_isp;
|
2000-12-08 21:51:06 +00:00
|
|
|
isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
|
1999-05-11 04:53:57 +00:00
|
|
|
if (isp->isp_param == NULL) {
|
2000-02-11 19:45:17 +00:00
|
|
|
device_printf(dev, "cannot allocate parameter data\n");
|
|
|
|
goto bad;
|
1999-05-11 04:53:57 +00:00
|
|
|
}
|
|
|
|
isp->isp_mdvec = mdvp;
|
|
|
|
isp->isp_type = basetype;
|
2000-02-11 19:45:17 +00:00
|
|
|
isp->isp_revision = pci_get_revid(dev);
|
2001-02-11 03:53:23 +00:00
|
|
|
isp->isp_role = role;
|
2001-03-01 02:21:36 +00:00
|
|
|
isp->isp_dev = dev;
|
1998-04-22 18:12:29 +00:00
|
|
|
|
2000-06-18 05:18:55 +00:00
|
|
|
/*
|
|
|
|
* Try and find firmware for this device.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (isp_get_firmware_p) {
|
|
|
|
int device = (int) pci_get_device(dev);
|
|
|
|
#ifdef ISP_TARGET_MODE
|
|
|
|
(*isp_get_firmware_p)(0, 1, device, &mdvp->dv_ispfw);
|
|
|
|
#else
|
|
|
|
(*isp_get_firmware_p)(0, 0, device, &mdvp->dv_ispfw);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1999-02-09 01:12:52 +00:00
|
|
|
/*
|
|
|
|
* Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER
|
|
|
|
* are set.
|
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN |
|
|
|
|
PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN;
|
|
|
|
pci_write_config(dev, PCIR_COMMAND, cmd, 1);
|
1999-04-04 01:14:02 +00:00
|
|
|
|
1999-02-09 01:12:52 +00:00
|
|
|
/*
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
* Make sure the Cache Line Size register is set sensibly.
|
1999-02-09 01:12:52 +00:00
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
data = pci_read_config(dev, PCIR_CACHELNSZ, 1);
|
1999-04-04 01:14:02 +00:00
|
|
|
if (data != linesz) {
|
1999-02-09 01:12:52 +00:00
|
|
|
data = PCI_DFLT_LNSZ;
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(isp, ISP_LOGCONFIG, "set PCI line size to %d", data);
|
2000-02-11 19:45:17 +00:00
|
|
|
pci_write_config(dev, PCIR_CACHELNSZ, data, 1);
|
1999-02-09 01:12:52 +00:00
|
|
|
}
|
1999-04-04 01:14:02 +00:00
|
|
|
|
1999-02-09 01:12:52 +00:00
|
|
|
/*
|
|
|
|
* Make sure the Latency Timer is sane.
|
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
data = pci_read_config(dev, PCIR_LATTIMER, 1);
|
1999-02-09 01:12:52 +00:00
|
|
|
if (data < PCI_DFLT_LTNCY) {
|
|
|
|
data = PCI_DFLT_LTNCY;
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(isp, ISP_LOGCONFIG, "set PCI latency to %d", data);
|
2000-02-11 19:45:17 +00:00
|
|
|
pci_write_config(dev, PCIR_LATTIMER, data, 1);
|
1999-02-09 01:12:52 +00:00
|
|
|
}
|
1999-04-04 01:14:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure we've disabled the ROM.
|
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
data = pci_read_config(dev, PCIR_ROMADDR, 4);
|
1999-04-04 01:14:02 +00:00
|
|
|
data &= ~1;
|
2000-02-11 19:45:17 +00:00
|
|
|
pci_write_config(dev, PCIR_ROMADDR, data, 4);
|
2000-07-18 06:40:22 +00:00
|
|
|
|
1999-02-09 01:12:52 +00:00
|
|
|
|
1999-08-16 01:52:21 +00:00
|
|
|
if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
|
|
|
|
255, lim, 0, &pcs->parent_dmat) != 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
device_printf(dev, "could not create master dma tag\n");
|
2000-02-11 19:45:17 +00:00
|
|
|
free(isp->isp_param, M_DEVBUF);
|
1998-09-15 10:06:23 +00:00
|
|
|
free(pcs, M_DEVBUF);
|
2000-02-11 19:45:17 +00:00
|
|
|
return (ENXIO);
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
|
|
|
|
iqd = 0;
|
|
|
|
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0,
|
|
|
|
1, RF_ACTIVE | RF_SHAREABLE);
|
|
|
|
if (irq == NULL) {
|
|
|
|
device_printf(dev, "could not allocate interrupt\n");
|
|
|
|
goto bad;
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
|
2001-03-01 02:21:36 +00:00
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"fwload_disable", &tval) == 0 && tval != 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_NORELOAD;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"ignore_nvram", &tval) == 0 && tval != 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_NONVRAM;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
tval = 0;
|
|
|
|
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"fullduplex", &tval) == 0 && tval != 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
|
|
|
|
sptr = 0;
|
|
|
|
if (resource_string_value(device_get_name(dev), device_get_unit(dev),
|
2001-07-04 18:51:58 +00:00
|
|
|
"topology", (const char **) &sptr) == 0 && sptr != 0) {
|
2001-03-01 02:21:36 +00:00
|
|
|
if (strcmp(sptr, "lport") == 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_LPORT;
|
|
|
|
} else if (strcmp(sptr, "nport") == 0) {
|
2000-02-11 19:45:17 +00:00
|
|
|
isp->isp_confopts |= ISP_CFG_NPORT;
|
2001-03-01 02:21:36 +00:00
|
|
|
} else if (strcmp(sptr, "lport-only") == 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_LPORT_ONLY;
|
|
|
|
} else if (strcmp(sptr, "nport-only") == 0) {
|
|
|
|
isp->isp_confopts |= ISP_CFG_NPORT_ONLY;
|
|
|
|
}
|
2000-02-11 19:45:17 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
|
1999-11-21 02:56:17 +00:00
|
|
|
/*
|
2001-03-01 02:21:36 +00:00
|
|
|
* Because the resource_*_value functions can neither return
|
|
|
|
* 64 bit integer values, nor can they be directly coerced
|
|
|
|
* to interpret the right hand side of the assignment as
|
|
|
|
* you want them to interpret it, we have to force WWN
|
|
|
|
* hint replacement to specify WWN strings with a leading
|
|
|
|
* 'w' (e..g w50000000aaaa0001). Sigh.
|
1999-11-21 02:56:17 +00:00
|
|
|
*/
|
2001-03-01 02:21:36 +00:00
|
|
|
sptr = 0;
|
|
|
|
tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
|
2001-07-04 18:51:58 +00:00
|
|
|
"portwwn", (const char **) &sptr);
|
2001-03-01 02:21:36 +00:00
|
|
|
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
|
|
|
|
char *eptr = 0;
|
|
|
|
isp->isp_osinfo.default_port_wwn = strtouq(sptr, &eptr, 16);
|
|
|
|
if (eptr < sptr + 16 || isp->isp_osinfo.default_port_wwn == 0) {
|
|
|
|
device_printf(dev, "mangled portwwn hint '%s'\n", sptr);
|
|
|
|
isp->isp_osinfo.default_port_wwn = 0;
|
|
|
|
} else {
|
|
|
|
isp->isp_confopts |= ISP_CFG_OWNWWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isp->isp_osinfo.default_port_wwn == 0) {
|
|
|
|
isp->isp_osinfo.default_port_wwn = 0x400000007F000009ull;
|
|
|
|
}
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
|
2001-03-01 02:21:36 +00:00
|
|
|
sptr = 0;
|
|
|
|
tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
|
2001-07-04 18:51:58 +00:00
|
|
|
"nodewwn", (const char **) &sptr);
|
2001-03-01 02:21:36 +00:00
|
|
|
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
|
|
|
|
char *eptr = 0;
|
|
|
|
isp->isp_osinfo.default_node_wwn = strtouq(sptr, &eptr, 16);
|
|
|
|
if (eptr < sptr + 16 || isp->isp_osinfo.default_node_wwn == 0) {
|
|
|
|
device_printf(dev, "mangled nodewwn hint '%s'\n", sptr);
|
|
|
|
isp->isp_osinfo.default_node_wwn = 0;
|
|
|
|
} else {
|
|
|
|
isp->isp_confopts |= ISP_CFG_OWNWWN;
|
1999-11-21 02:56:17 +00:00
|
|
|
}
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
}
|
2001-03-01 02:21:36 +00:00
|
|
|
if (isp->isp_osinfo.default_node_wwn == 0) {
|
|
|
|
isp->isp_osinfo.default_node_wwn = 0x400000007F000009ull;
|
|
|
|
}
|
|
|
|
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_debug = 0;
|
2001-03-01 02:21:36 +00:00
|
|
|
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
|
|
"debug", &isp_debug);
|
2000-12-29 19:10:16 +00:00
|
|
|
|
|
|
|
/* Make sure the lock is set up. */
|
|
|
|
mtx_init(&isp->isp_osinfo.lock, "isp", MTX_DEF);
|
|
|
|
locksetup++;
|
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
#ifdef ISP_SMPLOCK
|
|
|
|
#define INTR_FLAGS INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY
|
2000-12-29 19:10:16 +00:00
|
|
|
#else
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
#define INTR_FLAGS INTR_TYPE_CAM | INTR_ENTROPY
|
|
|
|
#endif
|
|
|
|
if (bus_setup_intr(dev, irq, INTR_FLAGS, isp_pci_intr, isp, &pcs->ih)) {
|
2000-02-11 19:45:17 +00:00
|
|
|
device_printf(dev, "could not setup interrupt\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2000-08-01 05:16:49 +00:00
|
|
|
/*
|
|
|
|
* Set up logging levels.
|
|
|
|
*/
|
|
|
|
if (isp_debug) {
|
|
|
|
isp->isp_dblev = isp_debug;
|
|
|
|
} else {
|
|
|
|
isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
|
|
|
|
}
|
|
|
|
if (bootverbose)
|
2000-12-05 07:38:41 +00:00
|
|
|
isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
|
2000-08-01 05:16:49 +00:00
|
|
|
|
2000-07-18 06:40:22 +00:00
|
|
|
/*
|
|
|
|
* Make sure we're in reset state.
|
|
|
|
*/
|
2000-10-25 04:40:49 +00:00
|
|
|
ISP_LOCK(isp);
|
1998-04-22 18:12:29 +00:00
|
|
|
isp_reset(isp);
|
|
|
|
if (isp->isp_state != ISP_RESETSTATE) {
|
2000-10-25 04:40:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2000-02-11 19:45:17 +00:00
|
|
|
goto bad;
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
isp_init(isp);
|
2001-02-11 03:53:23 +00:00
|
|
|
if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
|
|
|
|
isp_uninit(isp);
|
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
goto bad;
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
isp_attach(isp);
|
2001-02-11 03:53:23 +00:00
|
|
|
if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
|
|
|
|
isp_uninit(isp);
|
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
goto bad;
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2000-06-18 05:18:55 +00:00
|
|
|
/*
|
|
|
|
* XXXX: Here is where we might unload the f/w module
|
|
|
|
* XXXX: (or decrease the reference count to it).
|
|
|
|
*/
|
2000-10-25 04:40:49 +00:00
|
|
|
ISP_UNLOCK(isp);
|
2000-02-11 19:45:17 +00:00
|
|
|
return (0);
|
|
|
|
|
|
|
|
bad:
|
|
|
|
|
|
|
|
if (pcs && pcs->ih) {
|
|
|
|
(void) bus_teardown_intr(dev, irq, pcs->ih);
|
|
|
|
}
|
|
|
|
|
2000-10-25 04:40:49 +00:00
|
|
|
if (locksetup && isp) {
|
|
|
|
mtx_destroy(&isp->isp_osinfo.lock);
|
|
|
|
}
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
if (irq) {
|
|
|
|
(void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
|
|
|
|
}
|
2000-10-25 04:40:49 +00:00
|
|
|
|
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
if (regs) {
|
|
|
|
(void) bus_release_resource(dev, rtp, rgd, regs);
|
|
|
|
}
|
2000-10-25 04:40:49 +00:00
|
|
|
|
2000-02-11 19:45:17 +00:00
|
|
|
if (pcs) {
|
|
|
|
if (pcs->pci_isp.isp_param)
|
|
|
|
free(pcs->pci_isp.isp_param, M_DEVBUF);
|
|
|
|
free(pcs, M_DEVBUF);
|
|
|
|
}
|
2000-10-25 04:40:49 +00:00
|
|
|
|
2000-06-18 05:18:55 +00:00
|
|
|
/*
|
|
|
|
* XXXX: Here is where we might unload the f/w module
|
|
|
|
* XXXX: (or decrease the reference count to it).
|
|
|
|
*/
|
2000-02-11 19:45:17 +00:00
|
|
|
return (ENXIO);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
|
2000-12-29 19:10:16 +00:00
|
|
|
static void
|
|
|
|
isp_pci_intr(void *arg)
|
|
|
|
{
|
|
|
|
struct ispsoftc *isp = arg;
|
2001-08-31 21:39:04 +00:00
|
|
|
u_int16_t isr, sema, mbox;
|
|
|
|
|
2000-12-29 19:10:16 +00:00
|
|
|
ISP_LOCK(isp);
|
2001-08-31 21:39:04 +00:00
|
|
|
isp->isp_intcnt++;
|
|
|
|
if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
|
|
|
|
isp->isp_intbogus++;
|
|
|
|
} else {
|
|
|
|
isp_intr(isp, isr, sema, mbox);
|
|
|
|
}
|
2000-12-29 19:10:16 +00:00
|
|
|
ISP_UNLOCK(isp);
|
|
|
|
}
|
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
|
|
|
|
#define IspVirt2Off(a, x) \
|
|
|
|
(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
|
|
|
|
_BLK_REG_SHFT] + ((x) & 0xff))
|
|
|
|
|
|
|
|
#define BXR2(pcs, off) \
|
|
|
|
bus_space_read_2(pcs->pci_st, pcs->pci_sh, off)
|
|
|
|
#define BXW2(pcs, off, v) \
|
|
|
|
bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v)
|
|
|
|
|
|
|
|
|
|
|
|
static INLINE int
|
|
|
|
isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp)
|
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
|
|
|
u_int16_t val0, val1;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
val0 = BXR2(pcs, IspVirt2Off(isp, off));
|
|
|
|
val1 = BXR2(pcs, IspVirt2Off(isp, off));
|
|
|
|
} while (val0 != val1 && ++i < 1000);
|
|
|
|
if (val0 != val1) {
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
*rp = val0;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp,
|
|
|
|
u_int16_t *semap, u_int16_t *mbp)
|
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
|
|
|
u_int16_t isr, sema;
|
|
|
|
|
|
|
|
if (IS_2100(isp)) {
|
|
|
|
if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR));
|
|
|
|
sema = 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) {
|
|
|
|
if (IS_2100(isp)) {
|
|
|
|
if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp,
|
|
|
|
u_int16_t *semap, u_int16_t *mbox0p)
|
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
|
|
|
u_int32_t r2hisr;
|
|
|
|
|
|
|
|
r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
|
|
|
|
IspVirt2Off(pcs, BIU_R2HSTSLO));
|
|
|
|
isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
|
|
|
|
if ((r2hisr & BIU_R2HST_INTR) == 0) {
|
|
|
|
*isrp = 0;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
switch (r2hisr & BIU_R2HST_ISTAT_MASK) {
|
|
|
|
case ISPR2HST_ROM_MBX_OK:
|
|
|
|
case ISPR2HST_ROM_MBX_FAIL:
|
|
|
|
case ISPR2HST_MBX_OK:
|
|
|
|
case ISPR2HST_MBX_FAIL:
|
|
|
|
case ISPR2HST_ASYNC_EVENT:
|
|
|
|
case ISPR2HST_FPOST:
|
|
|
|
case ISPR2HST_FPOST_CTIO:
|
|
|
|
*isrp = r2hisr & 0xffff;
|
|
|
|
*mbox0p = (r2hisr >> 16);
|
|
|
|
*semap = 1;
|
|
|
|
return (1);
|
|
|
|
case ISPR2HST_RSPQ_UPDATE:
|
|
|
|
*isrp = r2hisr & 0xffff;
|
|
|
|
*mbox0p = 0;
|
|
|
|
*semap = 0;
|
|
|
|
return (1);
|
|
|
|
default:
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
static u_int16_t
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_reg(struct ispsoftc *isp, int regoff)
|
1999-03-17 05:07:18 +00:00
|
|
|
{
|
|
|
|
u_int16_t rv;
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
2001-08-31 21:39:04 +00:00
|
|
|
int oldconf = 0;
|
1998-04-22 18:12:29 +00:00
|
|
|
|
1999-03-17 05:07:18 +00:00
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
|
|
|
/*
|
|
|
|
* We will assume that someone has paused the RISC processor.
|
|
|
|
*/
|
2001-08-31 21:39:04 +00:00
|
|
|
oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
|
|
|
oldconf | BIU_PCI_CONF1_SXP);
|
1999-03-17 05:07:18 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
rv = BXR2(pcs, IspVirt2Off(isp, regoff));
|
1999-03-17 05:07:18 +00:00
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
|
1999-03-17 05:07:18 +00:00
|
|
|
}
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
|
1999-03-17 05:07:18 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
2001-08-31 21:39:04 +00:00
|
|
|
int oldconf = 0;
|
1999-03-17 05:07:18 +00:00
|
|
|
|
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
|
|
|
/*
|
|
|
|
* We will assume that someone has paused the RISC processor.
|
|
|
|
*/
|
2001-08-31 21:39:04 +00:00
|
|
|
oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
|
|
|
oldconf | BIU_PCI_CONF1_SXP);
|
1999-03-17 05:07:18 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, regoff), val);
|
1999-03-17 05:07:18 +00:00
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
|
1999-03-17 05:07:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
static u_int16_t
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff)
|
1998-04-22 18:12:29 +00:00
|
|
|
{
|
1999-12-16 05:42:02 +00:00
|
|
|
u_int16_t rv, oc = 0;
|
1998-04-22 18:12:29 +00:00
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
1999-03-17 05:07:18 +00:00
|
|
|
|
1999-12-16 05:42:02 +00:00
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
|
|
|
|
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
|
|
|
|
u_int16_t tc;
|
1998-04-22 18:12:29 +00:00
|
|
|
/*
|
|
|
|
* We will assume that someone has paused the RISC processor.
|
|
|
|
*/
|
2001-08-31 21:39:04 +00:00
|
|
|
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
1999-12-16 05:42:02 +00:00
|
|
|
tc = oc & ~BIU_PCI1080_CONF1_DMA;
|
|
|
|
if (regoff & SXP_BANK1_SELECT)
|
|
|
|
tc |= BIU_PCI1080_CONF1_SXP1;
|
|
|
|
else
|
|
|
|
tc |= BIU_PCI1080_CONF1_SXP0;
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
|
1999-03-17 05:07:18 +00:00
|
|
|
} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
|
2001-08-31 21:39:04 +00:00
|
|
|
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
|
|
|
oc | BIU_PCI1080_CONF1_DMA);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
rv = BXR2(pcs, IspVirt2Off(isp, regoff));
|
1999-12-16 05:42:02 +00:00
|
|
|
if (oc) {
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
return (rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-08-31 21:39:04 +00:00
|
|
|
isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val)
|
1998-04-22 18:12:29 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
2001-08-31 21:39:04 +00:00
|
|
|
int oc = 0;
|
1999-03-17 05:07:18 +00:00
|
|
|
|
1999-12-16 05:42:02 +00:00
|
|
|
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
|
|
|
|
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
|
|
|
|
u_int16_t tc;
|
1998-04-22 18:12:29 +00:00
|
|
|
/*
|
|
|
|
* We will assume that someone has paused the RISC processor.
|
|
|
|
*/
|
2001-08-31 21:39:04 +00:00
|
|
|
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
1999-12-16 05:42:02 +00:00
|
|
|
tc = oc & ~BIU_PCI1080_CONF1_DMA;
|
|
|
|
if (regoff & SXP_BANK1_SELECT)
|
|
|
|
tc |= BIU_PCI1080_CONF1_SXP1;
|
|
|
|
else
|
|
|
|
tc |= BIU_PCI1080_CONF1_SXP0;
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
|
1999-03-17 05:07:18 +00:00
|
|
|
} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
|
2001-08-31 21:39:04 +00:00
|
|
|
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
|
|
|
oc | BIU_PCI1080_CONF1_DMA);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, regoff), val);
|
1999-12-16 05:42:02 +00:00
|
|
|
if (oc) {
|
2001-08-31 21:39:04 +00:00
|
|
|
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
static void isp_map_rquest(void *, bus_dma_segment_t *, int, int);
|
|
|
|
static void isp_map_result(void *, bus_dma_segment_t *, int, int);
|
|
|
|
static void isp_map_fcscrt(void *, bus_dma_segment_t *, int, int);
|
1998-09-15 10:06:23 +00:00
|
|
|
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
struct imush {
|
|
|
|
struct ispsoftc *isp;
|
|
|
|
int error;
|
|
|
|
};
|
|
|
|
|
1998-09-15 10:06:23 +00:00
|
|
|
static void
|
1998-12-28 19:24:23 +00:00
|
|
|
isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
struct imush *imushp = (struct imush *) arg;
|
|
|
|
if (error) {
|
|
|
|
imushp->error = error;
|
|
|
|
} else {
|
|
|
|
imushp->isp->isp_rquest_dma = segs->ds_addr;
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-12-28 19:24:23 +00:00
|
|
|
isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
struct imush *imushp = (struct imush *) arg;
|
|
|
|
if (error) {
|
|
|
|
imushp->error = error;
|
|
|
|
} else {
|
|
|
|
imushp->isp->isp_result_dma = segs->ds_addr;
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-12-28 19:24:23 +00:00
|
|
|
isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
struct imush *imushp = (struct imush *) arg;
|
|
|
|
if (error) {
|
|
|
|
imushp->error = error;
|
|
|
|
} else {
|
|
|
|
fcparam *fcp = imushp->isp->isp_param;
|
|
|
|
fcp->isp_scdma = segs->ds_addr;
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
1998-12-28 19:24:23 +00:00
|
|
|
isp_pci_mbxdma(struct ispsoftc *isp)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
|
|
|
|
caddr_t base;
|
|
|
|
u_int32_t len;
|
|
|
|
int i, error;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
bus_size_t lim;
|
|
|
|
struct imush im;
|
|
|
|
|
|
|
|
|
1999-10-17 19:03:11 +00:00
|
|
|
/*
|
|
|
|
* Already been here? If so, leave...
|
|
|
|
*/
|
|
|
|
if (isp->isp_rquest) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2000-08-01 05:16:49 +00:00
|
|
|
len = sizeof (XS_T **) * isp->isp_maxcmds;
|
2000-12-08 21:51:06 +00:00
|
|
|
isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
|
1999-10-17 19:03:11 +00:00
|
|
|
if (isp->isp_xflist == NULL) {
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
|
1999-10-17 19:03:11 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
|
|
|
|
pci->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
|
|
|
|
if (pci->dmaps == NULL) {
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR, "can't alloc dma maps");
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
1999-12-16 05:42:02 +00:00
|
|
|
if (IS_FC(isp) || IS_ULTRA2(isp))
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
lim = BUS_SPACE_MAXADDR + 1;
|
|
|
|
else
|
|
|
|
lim = BUS_SPACE_MAXADDR_24BIT + 1;
|
1998-09-15 10:06:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate and map the request, result queues, plus FC scratch area.
|
|
|
|
*/
|
2000-08-01 05:16:49 +00:00
|
|
|
len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
|
|
|
|
len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (IS_FC(isp)) {
|
1998-09-15 10:06:23 +00:00
|
|
|
len += ISP2100_SCRLEN;
|
|
|
|
}
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim,
|
|
|
|
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1,
|
|
|
|
BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"cannot create a dma tag for control spaces");
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
1998-09-15 10:06:23 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base,
|
|
|
|
BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
2001-01-09 02:12:42 +00:00
|
|
|
"cannot allocate %d bytes of CCB memory", len);
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
1998-09-15 10:06:23 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
isp->isp_rquest = base;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
im.isp = isp;
|
|
|
|
im.error = 0;
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest,
|
2000-08-01 05:16:49 +00:00
|
|
|
ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)), isp_map_rquest, &im, 0);
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (im.error) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"error %d loading dma map for DMA request queue", im.error);
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
|
|
|
isp->isp_rquest = NULL;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
return (1);
|
|
|
|
}
|
2000-08-01 05:16:49 +00:00
|
|
|
isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
im.error = 0;
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result,
|
2000-08-01 05:16:49 +00:00
|
|
|
ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)), isp_map_result, &im, 0);
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (im.error) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"error %d loading dma map for DMA result queue", im.error);
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
|
|
|
isp->isp_rquest = NULL;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
return (1);
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
|
1999-10-17 19:03:11 +00:00
|
|
|
for (i = 0; i < isp->isp_maxcmds; i++) {
|
1998-09-15 10:06:23 +00:00
|
|
|
error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]);
|
|
|
|
if (error) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"error %d creating per-cmd DMA maps", error);
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
|
|
|
isp->isp_rquest = NULL;
|
1998-09-15 10:06:23 +00:00
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
}
|
1999-10-17 19:03:11 +00:00
|
|
|
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
if (IS_FC(isp)) {
|
1999-03-25 22:53:56 +00:00
|
|
|
fcparam *fcp = (fcparam *) isp->isp_param;
|
|
|
|
fcp->isp_scratch = base +
|
2000-08-01 05:16:49 +00:00
|
|
|
ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)) +
|
|
|
|
ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
im.error = 0;
|
1999-03-25 22:53:56 +00:00
|
|
|
bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap,
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0);
|
|
|
|
if (im.error) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"error %d loading FC scratch area", im.error);
|
1999-10-17 19:03:11 +00:00
|
|
|
free(isp->isp_xflist, M_DEVBUF);
|
|
|
|
free(pci->dmaps, M_DEVBUF);
|
|
|
|
isp->isp_rquest = NULL;
|
Remove pre-CAM code. Add in getenv_int calls for variables isp_mem_map,
isp_io_map, isp_no_fwload, isp_fwload, isp_no_nvram, isp_fcduplex
which are all bitmaps of isp instances that should or shouldn't
map memory space, I/O space, not load f/w, load f/w, ignore nvram,
not ignore nvarm, set full duplex mode. Also have an isp_seed value
that we can use to generate a pseudo seed for a synthetic WWN.
Other minor cosmetic cleanup. Add in support for the Qlogic ISP
2200. Very important change where we actually check now to see
whether we were successful in mapping request and response queues
(and fibre channel scratch space).
1999-07-02 23:18:03 +00:00
|
|
|
return (1);
|
|
|
|
}
|
1999-03-25 22:53:56 +00:00
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
struct ispsoftc *isp;
|
2000-01-03 23:50:13 +00:00
|
|
|
void *cmd_token;
|
|
|
|
void *rq;
|
1999-11-21 02:56:17 +00:00
|
|
|
u_int16_t *iptrp;
|
|
|
|
u_int16_t optr;
|
1998-09-15 10:06:23 +00:00
|
|
|
u_int error;
|
|
|
|
} mush_t;
|
|
|
|
|
1998-09-17 21:11:21 +00:00
|
|
|
#define MUSHERR_NOQENTRIES -2
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
|
|
|
/*
|
|
|
|
* We need to handle DMA for target mode differently from initiator mode.
|
|
|
|
*
|
|
|
|
* DMA mapping and construction and submission of CTIO Request Entries
|
|
|
|
* and rendevous for completion are very tightly coupled because we start
|
|
|
|
* out by knowing (per platform) how much data we have to move, but we
|
|
|
|
* don't know, up front, how many DMA mapping segments will have to be used
|
|
|
|
* cover that data, so we don't know how many CTIO Request Entries we
|
|
|
|
* will end up using. Further, for performance reasons we may want to
|
|
|
|
* (on the last CTIO for Fibre Channel), send status too (if all went well).
|
|
|
|
*
|
|
|
|
* The standard vector still goes through isp_pci_dmasetup, but the callback
|
|
|
|
* for the DMA mapping routines comes here instead with the whole transfer
|
|
|
|
* mapped and a pointer to a partially filled in already allocated request
|
|
|
|
* queue entry. We finish the job.
|
|
|
|
*/
|
2001-04-04 21:53:59 +00:00
|
|
|
static void tdma_mk(void *, bus_dma_segment_t *, int, int);
|
|
|
|
static void tdma_mkfc(void *, bus_dma_segment_t *, int, int);
|
|
|
|
|
|
|
|
#define STATUS_WITH_DATA 1
|
2000-01-03 23:50:13 +00:00
|
|
|
|
|
|
|
static void
|
2000-07-18 06:40:22 +00:00
|
|
|
tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
2000-01-03 23:50:13 +00:00
|
|
|
{
|
|
|
|
mush_t *mp;
|
|
|
|
struct ccb_scsiio *csio;
|
|
|
|
struct isp_pcisoftc *pci;
|
|
|
|
bus_dmamap_t *dp;
|
2000-07-18 06:40:22 +00:00
|
|
|
u_int8_t scsi_status;
|
2000-01-03 23:50:13 +00:00
|
|
|
ct_entry_t *cto;
|
2001-03-02 06:28:55 +00:00
|
|
|
u_int16_t handle;
|
|
|
|
u_int32_t totxfr, sflags;
|
2000-07-18 06:40:22 +00:00
|
|
|
int nctios, send_status;
|
|
|
|
int32_t resid;
|
2001-04-04 21:53:59 +00:00
|
|
|
int i, j;
|
2000-01-03 23:50:13 +00:00
|
|
|
|
|
|
|
mp = (mush_t *) arg;
|
|
|
|
if (error) {
|
|
|
|
mp->error = error;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
csio = mp->cmd_token;
|
|
|
|
cto = mp->rq;
|
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
cto->ct_xfrlen = 0;
|
|
|
|
cto->ct_seg_count = 0;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
|
|
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
if (nseg == 0) {
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_header.rqs_seqno = 1;
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-04-04 21:53:59 +00:00
|
|
|
"CTIO[%x] lun%d iid%d tag %x flgs %x sts %x ssts %x res %d",
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_fwhandle, csio->ccb_h.target_lun, cto->ct_iid,
|
2001-04-04 21:53:59 +00:00
|
|
|
cto->ct_tag_val, cto->ct_flags, cto->ct_status,
|
|
|
|
cto->ct_scsi_status, cto->ct_resid);
|
|
|
|
ISP_TDQE(mp->isp, "tdma_mk[no data]", *mp->iptrp, cto);
|
2000-07-18 06:40:22 +00:00
|
|
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
2000-01-15 01:54:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-07-18 06:40:22 +00:00
|
|
|
nctios = nseg / ISP_RQDSEG;
|
|
|
|
if (nseg % ISP_RQDSEG) {
|
|
|
|
nctios++;
|
|
|
|
}
|
|
|
|
|
2001-04-04 21:53:59 +00:00
|
|
|
/*
|
|
|
|
* Check to see that we don't overflow.
|
|
|
|
*/
|
|
|
|
for (i = 0, j = *mp->iptrp; i < nctios; i++) {
|
|
|
|
j = ISP_NXT_QENTRY(j, RQUEST_QUEUE_LEN(isp));
|
|
|
|
if (j == mp->optr) {
|
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"Request Queue Overflow [tdma_mk]");
|
|
|
|
mp->error = MUSHERR_NOQENTRIES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
/*
|
2001-03-02 06:28:55 +00:00
|
|
|
* Save syshandle, and potentially any SCSI status, which we'll
|
|
|
|
* reinsert on the last CTIO we're going to send.
|
2000-01-03 23:50:13 +00:00
|
|
|
*/
|
2001-03-02 06:28:55 +00:00
|
|
|
handle = cto->ct_syshandle;
|
|
|
|
cto->ct_syshandle = 0;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_header.rqs_seqno = 0;
|
|
|
|
send_status = (cto->ct_flags & CT_SENDSTATUS) != 0;
|
2000-01-03 23:50:13 +00:00
|
|
|
|
2000-07-18 06:40:22 +00:00
|
|
|
if (send_status) {
|
|
|
|
sflags = cto->ct_flags & (CT_SENDSTATUS | CT_CCINCR);
|
|
|
|
cto->ct_flags &= ~(CT_SENDSTATUS | CT_CCINCR);
|
|
|
|
/*
|
|
|
|
* Preserve residual.
|
|
|
|
*/
|
|
|
|
resid = cto->ct_resid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save actual SCSI status.
|
|
|
|
*/
|
|
|
|
scsi_status = cto->ct_scsi_status;
|
|
|
|
|
2001-04-04 21:53:59 +00:00
|
|
|
#ifndef STATUS_WITH_DATA
|
|
|
|
sflags |= CT_NO_DATA;
|
2000-07-18 06:40:22 +00:00
|
|
|
/*
|
|
|
|
* We can't do a status at the same time as a data CTIO, so
|
|
|
|
* we need to synthesize an extra CTIO at this level.
|
|
|
|
*/
|
2000-01-15 01:54:36 +00:00
|
|
|
nctios++;
|
2001-03-21 00:49:37 +00:00
|
|
|
#endif
|
2000-07-18 06:40:22 +00:00
|
|
|
} else {
|
|
|
|
sflags = scsi_status = resid = 0;
|
2000-01-15 01:54:36 +00:00
|
|
|
}
|
|
|
|
|
2000-07-18 06:40:22 +00:00
|
|
|
totxfr = cto->ct_resid = 0;
|
|
|
|
cto->ct_scsi_status = 0;
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
pci = (struct isp_pcisoftc *)mp->isp;
|
2000-07-04 01:01:15 +00:00
|
|
|
dp = &pci->dmaps[isp_handle_index(handle)];
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
|
|
|
|
} else {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (nctios--) {
|
2000-07-18 06:40:22 +00:00
|
|
|
int seglim;
|
2000-01-03 23:50:13 +00:00
|
|
|
|
|
|
|
seglim = nseg;
|
2000-07-18 06:40:22 +00:00
|
|
|
if (seglim) {
|
|
|
|
int seg;
|
|
|
|
|
|
|
|
if (seglim > ISP_RQDSEG)
|
|
|
|
seglim = ISP_RQDSEG;
|
|
|
|
|
|
|
|
for (seg = 0; seg < seglim; seg++, nseg--) {
|
|
|
|
/*
|
|
|
|
* Unlike normal initiator commands, we don't
|
|
|
|
* do any swizzling here.
|
|
|
|
*/
|
|
|
|
cto->ct_dataseg[seg].ds_count = dm_segs->ds_len;
|
|
|
|
cto->ct_dataseg[seg].ds_base = dm_segs->ds_addr;
|
|
|
|
cto->ct_xfrlen += dm_segs->ds_len;
|
|
|
|
totxfr += dm_segs->ds_len;
|
|
|
|
dm_segs++;
|
|
|
|
}
|
|
|
|
cto->ct_seg_count = seg;
|
2000-01-03 23:50:13 +00:00
|
|
|
} else {
|
2000-07-18 06:40:22 +00:00
|
|
|
/*
|
|
|
|
* This case should only happen when we're sending an
|
|
|
|
* extra CTIO with final status.
|
|
|
|
*/
|
|
|
|
if (send_status == 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"tdma_mk ran out of segments");
|
2000-07-18 06:40:22 +00:00
|
|
|
mp->error = EINVAL;
|
|
|
|
return;
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
}
|
|
|
|
|
2000-07-18 06:40:22 +00:00
|
|
|
/*
|
|
|
|
* At this point, the fields ct_lun, ct_iid, ct_tagval,
|
|
|
|
* ct_tagtype, and ct_timeout have been carried over
|
|
|
|
* unchanged from what our caller had set.
|
|
|
|
*
|
|
|
|
* The dataseg fields and the seg_count fields we just got
|
|
|
|
* through setting. The data direction we've preserved all
|
|
|
|
* along and only clear it if we're now sending status.
|
|
|
|
*/
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
if (nctios == 0) {
|
|
|
|
/*
|
2000-07-18 06:40:22 +00:00
|
|
|
* We're the last in a sequence of CTIOs, so mark
|
|
|
|
* this CTIO and save the handle to the CCB such that
|
|
|
|
* when this CTIO completes we can free dma resources
|
|
|
|
* and do whatever else we need to do to finish the
|
2001-04-04 21:53:59 +00:00
|
|
|
* rest of the command. We *don't* give this to the
|
|
|
|
* firmware to work on- the caller will do that.
|
2000-01-03 23:50:13 +00:00
|
|
|
*/
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_syshandle = handle;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_header.rqs_seqno = 1;
|
|
|
|
|
|
|
|
if (send_status) {
|
|
|
|
cto->ct_scsi_status = scsi_status;
|
2001-03-21 00:49:37 +00:00
|
|
|
cto->ct_flags |= sflags;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_resid = resid;
|
|
|
|
}
|
2000-08-01 05:16:49 +00:00
|
|
|
if (send_status) {
|
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-04-04 21:53:59 +00:00
|
|
|
"CTIO[%x] lun%d iid %d tag %x ct_flags %x "
|
2001-03-02 06:28:55 +00:00
|
|
|
"scsi status %x resid %d",
|
|
|
|
cto->ct_fwhandle, csio->ccb_h.target_lun,
|
2001-04-04 21:53:59 +00:00
|
|
|
cto->ct_iid, cto->ct_tag_val, cto->ct_flags,
|
2000-01-04 03:41:40 +00:00
|
|
|
cto->ct_scsi_status, cto->ct_resid);
|
2000-08-01 05:16:49 +00:00
|
|
|
} else {
|
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-04-04 21:53:59 +00:00
|
|
|
"CTIO[%x] lun%d iid%d tag %x ct_flags 0x%x",
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_fwhandle, csio->ccb_h.target_lun,
|
2001-04-04 21:53:59 +00:00
|
|
|
cto->ct_iid, cto->ct_tag_val,
|
|
|
|
cto->ct_flags);
|
2000-01-04 03:41:40 +00:00
|
|
|
}
|
2000-07-18 06:40:22 +00:00
|
|
|
ISP_TDQE(mp->isp, "last tdma_mk", *mp->iptrp, cto);
|
|
|
|
ISP_SWIZ_CTIO(mp->isp, cto, cto);
|
2000-01-03 23:50:13 +00:00
|
|
|
} else {
|
2000-07-18 06:40:22 +00:00
|
|
|
ct_entry_t *octo = cto;
|
|
|
|
|
|
|
|
/*
|
2001-03-02 06:28:55 +00:00
|
|
|
* Make sure syshandle fields are clean
|
2000-07-18 06:40:22 +00:00
|
|
|
*/
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_syshandle = 0;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_header.rqs_seqno = 0;
|
2000-07-18 06:40:22 +00:00
|
|
|
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-03-02 06:28:55 +00:00
|
|
|
"CTIO[%x] lun%d for ID%d ct_flags 0x%x",
|
|
|
|
cto->ct_fwhandle, csio->ccb_h.target_lun,
|
|
|
|
cto->ct_iid, cto->ct_flags);
|
2000-07-18 06:40:22 +00:00
|
|
|
ISP_TDQE(mp->isp, "tdma_mk", *mp->iptrp, cto);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a new CTIO
|
|
|
|
*/
|
2000-01-03 23:50:13 +00:00
|
|
|
cto = (ct_entry_t *)
|
|
|
|
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
2001-04-04 21:53:59 +00:00
|
|
|
j = *mp->iptrp;
|
2000-07-18 06:40:22 +00:00
|
|
|
*mp->iptrp =
|
2000-08-01 05:16:49 +00:00
|
|
|
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp));
|
2000-01-03 23:50:13 +00:00
|
|
|
if (*mp->iptrp == mp->optr) {
|
2001-03-02 06:28:55 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG0,
|
2000-12-05 07:38:41 +00:00
|
|
|
"Queue Overflow in tdma_mk");
|
2000-01-03 23:50:13 +00:00
|
|
|
mp->error = MUSHERR_NOQENTRIES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Fill in the new CTIO with info from the old one.
|
|
|
|
*/
|
|
|
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_fwhandle = octo->ct_fwhandle;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_header.rqs_flags = 0;
|
|
|
|
cto->ct_lun = octo->ct_lun;
|
|
|
|
cto->ct_iid = octo->ct_iid;
|
|
|
|
cto->ct_reserved2 = octo->ct_reserved2;
|
|
|
|
cto->ct_tgt = octo->ct_tgt;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_flags = octo->ct_flags;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_status = 0;
|
|
|
|
cto->ct_scsi_status = 0;
|
|
|
|
cto->ct_tag_val = octo->ct_tag_val;
|
|
|
|
cto->ct_tag_type = octo->ct_tag_type;
|
|
|
|
cto->ct_xfrlen = 0;
|
|
|
|
cto->ct_resid = 0;
|
|
|
|
cto->ct_timeout = octo->ct_timeout;
|
|
|
|
cto->ct_seg_count = 0;
|
2000-07-18 06:40:22 +00:00
|
|
|
MEMZERO(cto->ct_dataseg, sizeof(cto->ct_dataseg));
|
|
|
|
/*
|
2001-04-04 21:53:59 +00:00
|
|
|
* Now swizzle the old one for the consumption
|
|
|
|
* of the chip and give it to the firmware to
|
|
|
|
* work on while we do the next.
|
2000-07-18 06:40:22 +00:00
|
|
|
*/
|
|
|
|
ISP_SWIZ_CTIO(mp->isp, octo, octo);
|
2001-04-04 21:53:59 +00:00
|
|
|
ISP_ADD_REQUEST(mp->isp, j);
|
2000-01-03 23:50:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-07-18 06:40:22 +00:00
|
|
|
tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
2000-01-03 23:50:13 +00:00
|
|
|
{
|
|
|
|
mush_t *mp;
|
|
|
|
struct ccb_scsiio *csio;
|
|
|
|
struct isp_pcisoftc *pci;
|
|
|
|
bus_dmamap_t *dp;
|
|
|
|
ct2_entry_t *cto;
|
2001-03-02 06:28:55 +00:00
|
|
|
u_int16_t scsi_status, send_status, send_sense, handle;
|
|
|
|
u_int32_t totxfr, datalen;
|
2000-01-15 01:54:36 +00:00
|
|
|
u_int8_t sense[QLTM_SENSELEN];
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
int nctios, j;
|
2000-01-03 23:50:13 +00:00
|
|
|
|
|
|
|
mp = (mush_t *) arg;
|
|
|
|
if (error) {
|
|
|
|
mp->error = error;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
csio = mp->cmd_token;
|
|
|
|
cto = mp->rq;
|
|
|
|
|
|
|
|
if (nseg == 0) {
|
|
|
|
if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE1) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"dma2_tgt_fc, a status CTIO2 without MODE1 "
|
|
|
|
"set (0x%x)", cto->ct_flags);
|
2000-01-15 01:54:36 +00:00
|
|
|
mp->error = EINVAL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
2000-07-18 06:40:22 +00:00
|
|
|
cto->ct_header.rqs_seqno = 1;
|
2001-03-02 06:28:55 +00:00
|
|
|
/* ct_syshandle contains the handle set by caller */
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* We preserve ct_lun, ct_iid, ct_rxid. We set the data
|
|
|
|
* flags to NO DATA and clear relative offset flags.
|
|
|
|
* We preserve the ct_resid and the response area.
|
|
|
|
*/
|
|
|
|
cto->ct_flags |= CT2_NO_DATA;
|
2000-07-18 06:40:22 +00:00
|
|
|
if (cto->ct_resid > 0)
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER;
|
2000-07-18 06:40:22 +00:00
|
|
|
else if (cto->ct_resid < 0)
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
cto->rsp.m1.ct_scsi_status |= CT2_DATA_OVER;
|
2000-01-15 01:54:36 +00:00
|
|
|
cto->ct_seg_count = 0;
|
|
|
|
cto->ct_reloff = 0;
|
|
|
|
ISP_TDQE(mp->isp, "dma2_tgt_fc[no data]", *mp->iptrp, cto);
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-03-02 06:28:55 +00:00
|
|
|
"CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x ssts "
|
2000-08-01 05:16:49 +00:00
|
|
|
"0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun,
|
|
|
|
cto->ct_iid, cto->ct_flags, cto->ct_status,
|
|
|
|
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
2000-01-15 01:54:36 +00:00
|
|
|
ISP_SWIZ_CTIO2(isp, cto, cto);
|
2000-01-03 23:50:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
if ((cto->ct_flags & CT2_FLAG_MMASK) != CT2_FLAG_MODE0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"dma2_tgt_fc, a data CTIO2 without MODE0 set "
|
|
|
|
"(0x%x)", cto->ct_flags);
|
2000-01-15 01:54:36 +00:00
|
|
|
mp->error = EINVAL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nctios = nseg / ISP_RQDSEG_T2;
|
|
|
|
if (nseg % ISP_RQDSEG_T2) {
|
|
|
|
nctios++;
|
|
|
|
}
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
/*
|
2000-01-15 01:54:36 +00:00
|
|
|
* Save the handle, status, reloff, and residual. We'll reinsert the
|
|
|
|
* handle into the last CTIO2 we're going to send, and reinsert status
|
|
|
|
* and residual (and possibly sense data) if that's to be sent as well.
|
|
|
|
*
|
|
|
|
* We preserve ct_reloff and adjust it for each data CTIO2 we send past
|
|
|
|
* the first one. This is needed so that the FCP DATA IUs being sent
|
|
|
|
* out have the correct offset (they can arrive at the other end out
|
|
|
|
* of order).
|
2000-01-03 23:50:13 +00:00
|
|
|
*/
|
2000-01-15 01:54:36 +00:00
|
|
|
|
2001-03-02 06:28:55 +00:00
|
|
|
handle = cto->ct_syshandle;
|
|
|
|
cto->ct_syshandle = 0;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
send_status = (cto->ct_flags & CT2_SENDSTATUS) != 0;
|
2000-01-15 01:54:36 +00:00
|
|
|
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
if (send_status) {
|
|
|
|
cto->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR);
|
2000-01-15 01:54:36 +00:00
|
|
|
|
|
|
|
/*
|
2000-07-18 06:40:22 +00:00
|
|
|
* Preserve residual, which is actually the total count.
|
2000-01-15 01:54:36 +00:00
|
|
|
*/
|
2000-07-18 06:40:22 +00:00
|
|
|
datalen = cto->ct_resid;
|
2000-01-15 01:54:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Save actual SCSI status. We'll reinsert the
|
|
|
|
* CT2_SNSLEN_VALID later if appropriate.
|
|
|
|
*/
|
|
|
|
scsi_status = cto->rsp.m0.ct_scsi_status & 0xff;
|
|
|
|
send_sense = cto->rsp.m0.ct_scsi_status & CT2_SNSLEN_VALID;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're sending status and have a CHECK CONDTION and
|
|
|
|
* have sense data, we send one more CTIO2 with just the
|
|
|
|
* status and sense data. The upper layers have stashed
|
|
|
|
* the sense data in the dataseg structure for us.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((scsi_status & 0xf) == SCSI_STATUS_CHECK_COND &&
|
|
|
|
send_sense) {
|
|
|
|
bcopy(cto->rsp.m0.ct_dataseg, sense, QLTM_SENSELEN);
|
|
|
|
nctios++;
|
|
|
|
}
|
|
|
|
} else {
|
2000-07-18 06:40:22 +00:00
|
|
|
scsi_status = send_sense = datalen = 0;
|
2000-01-15 01:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
totxfr = cto->ct_resid = 0;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->rsp.m0.ct_scsi_status = 0;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
MEMZERO(&cto->rsp, sizeof (cto->rsp));
|
2000-01-03 23:50:13 +00:00
|
|
|
|
|
|
|
pci = (struct isp_pcisoftc *)mp->isp;
|
2000-07-04 01:01:15 +00:00
|
|
|
dp = &pci->dmaps[isp_handle_index(handle)];
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
|
|
|
|
} else {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (nctios--) {
|
|
|
|
int seg, seglim;
|
|
|
|
|
|
|
|
seglim = nseg;
|
2000-01-15 01:54:36 +00:00
|
|
|
if (seglim) {
|
|
|
|
if (seglim > ISP_RQDSEG_T2)
|
|
|
|
seglim = ISP_RQDSEG_T2;
|
|
|
|
|
|
|
|
for (seg = 0; seg < seglim; seg++) {
|
|
|
|
cto->rsp.m0.ct_dataseg[seg].ds_base =
|
|
|
|
dm_segs->ds_addr;
|
|
|
|
cto->rsp.m0.ct_dataseg[seg].ds_count =
|
|
|
|
dm_segs->ds_len;
|
|
|
|
cto->rsp.m0.ct_xfrlen += dm_segs->ds_len;
|
|
|
|
totxfr += dm_segs->ds_len;
|
|
|
|
dm_segs++;
|
|
|
|
}
|
|
|
|
cto->ct_seg_count = seg;
|
2000-01-03 23:50:13 +00:00
|
|
|
} else {
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* This case should only happen when we're sending a
|
|
|
|
* synthesized MODE1 final status with sense data.
|
|
|
|
*/
|
|
|
|
if (send_sense == 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"dma2_tgt_fc ran out of segments, "
|
|
|
|
"no SENSE DATA");
|
2000-01-15 01:54:36 +00:00
|
|
|
mp->error = EINVAL;
|
|
|
|
return;
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
}
|
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* At this point, the fields ct_lun, ct_iid, ct_rxid,
|
|
|
|
* ct_timeout have been carried over unchanged from what
|
|
|
|
* our caller had set.
|
|
|
|
*
|
|
|
|
* The field ct_reloff is either what the caller set, or
|
|
|
|
* what we've added to below.
|
|
|
|
*
|
|
|
|
* The dataseg fields and the seg_count fields we just got
|
|
|
|
* through setting. The data direction we've preserved all
|
|
|
|
* along and only clear it if we're sending a MODE1 status
|
|
|
|
* as the last CTIO.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
if (nctios == 0) {
|
2000-01-15 01:54:36 +00:00
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
/*
|
2000-01-15 01:54:36 +00:00
|
|
|
* We're the last in a sequence of CTIO2s, so mark this
|
|
|
|
* CTIO2 and save the handle to the CCB such that when
|
|
|
|
* this CTIO2 completes we can free dma resources and
|
2000-01-03 23:50:13 +00:00
|
|
|
* do whatever else we need to do to finish the rest
|
|
|
|
* of the command.
|
|
|
|
*/
|
2000-01-15 01:54:36 +00:00
|
|
|
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_syshandle = handle;
|
2000-01-15 01:54:36 +00:00
|
|
|
cto->ct_header.rqs_seqno = 1;
|
|
|
|
|
|
|
|
if (send_status) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
/*
|
|
|
|
* Get 'real' residual and set flags based
|
|
|
|
* on it.
|
|
|
|
*/
|
|
|
|
cto->ct_resid = datalen - totxfr;
|
2000-01-15 01:54:36 +00:00
|
|
|
if (send_sense) {
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
MEMCPY(cto->rsp.m1.ct_resp, sense,
|
2000-01-15 01:54:36 +00:00
|
|
|
QLTM_SENSELEN);
|
|
|
|
cto->rsp.m1.ct_senselen =
|
|
|
|
QLTM_SENSELEN;
|
|
|
|
scsi_status |= CT2_SNSLEN_VALID;
|
|
|
|
cto->rsp.m1.ct_scsi_status =
|
|
|
|
scsi_status;
|
|
|
|
cto->ct_flags &= CT2_FLAG_MMASK;
|
|
|
|
cto->ct_flags |= CT2_FLAG_MODE1 |
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
CT2_NO_DATA | CT2_SENDSTATUS |
|
|
|
|
CT2_CCINCR;
|
|
|
|
if (cto->ct_resid > 0)
|
|
|
|
cto->rsp.m1.ct_scsi_status |=
|
|
|
|
CT2_DATA_UNDER;
|
|
|
|
else if (cto->ct_resid < 0)
|
|
|
|
cto->rsp.m1.ct_scsi_status |=
|
|
|
|
CT2_DATA_OVER;
|
2000-01-15 01:54:36 +00:00
|
|
|
} else {
|
|
|
|
cto->rsp.m0.ct_scsi_status =
|
|
|
|
scsi_status;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
cto->ct_flags |=
|
|
|
|
CT2_SENDSTATUS | CT2_CCINCR;
|
|
|
|
if (cto->ct_resid > 0)
|
|
|
|
cto->rsp.m0.ct_scsi_status |=
|
|
|
|
CT2_DATA_UNDER;
|
|
|
|
else if (cto->ct_resid < 0)
|
|
|
|
cto->rsp.m0.ct_scsi_status |=
|
|
|
|
CT2_DATA_OVER;
|
2000-01-15 01:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
ISP_TDQE(mp->isp, "last dma2_tgt_fc", *mp->iptrp, cto);
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-03-02 06:28:55 +00:00
|
|
|
"CTIO2[%x] lun %d->iid%d flgs 0x%x sts 0x%x"
|
2000-08-01 05:16:49 +00:00
|
|
|
" ssts 0x%x res %d", cto->ct_rxid,
|
|
|
|
csio->ccb_h.target_lun, (int) cto->ct_iid,
|
|
|
|
cto->ct_flags, cto->ct_status,
|
|
|
|
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
|
2000-01-15 01:54:36 +00:00
|
|
|
ISP_SWIZ_CTIO2(isp, cto, cto);
|
2000-01-03 23:50:13 +00:00
|
|
|
} else {
|
|
|
|
ct2_entry_t *octo = cto;
|
2000-01-15 01:54:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure handle fields are clean
|
|
|
|
*/
|
2001-03-02 06:28:55 +00:00
|
|
|
cto->ct_syshandle = 0;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_header.rqs_seqno = 0;
|
2000-01-15 01:54:36 +00:00
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
ISP_TDQE(mp->isp, "dma2_tgt_fc", *mp->iptrp, cto);
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGTDEBUG1,
|
2001-03-02 06:28:55 +00:00
|
|
|
"CTIO2[%x] lun %d->iid%d flgs 0x%x",
|
2000-08-01 05:16:49 +00:00
|
|
|
cto->ct_rxid, csio->ccb_h.target_lun,
|
|
|
|
(int) cto->ct_iid, cto->ct_flags);
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* Get a new CTIO2
|
|
|
|
*/
|
2000-01-03 23:50:13 +00:00
|
|
|
cto = (ct2_entry_t *)
|
|
|
|
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
j = *mp->iptrp;
|
2000-01-03 23:50:13 +00:00
|
|
|
*mp->iptrp =
|
2000-08-01 05:16:49 +00:00
|
|
|
ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp));
|
2000-01-03 23:50:13 +00:00
|
|
|
if (*mp->iptrp == mp->optr) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGWARN,
|
|
|
|
"Queue Overflow in dma2_tgt_fc");
|
2000-01-03 23:50:13 +00:00
|
|
|
mp->error = MUSHERR_NOQENTRIES;
|
|
|
|
return;
|
|
|
|
}
|
2000-01-15 01:54:36 +00:00
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
/*
|
2000-01-15 01:54:36 +00:00
|
|
|
* Fill in the new CTIO2 with info from the old one.
|
2000-01-03 23:50:13 +00:00
|
|
|
*/
|
|
|
|
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
|
|
|
|
cto->ct_header.rqs_entry_count = 1;
|
|
|
|
cto->ct_header.rqs_flags = 0;
|
2001-03-02 06:28:55 +00:00
|
|
|
/* ct_header.rqs_seqno && ct_syshandle done later */
|
|
|
|
cto->ct_fwhandle = octo->ct_fwhandle;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_lun = octo->ct_lun;
|
|
|
|
cto->ct_iid = octo->ct_iid;
|
|
|
|
cto->ct_rxid = octo->ct_rxid;
|
2000-01-15 01:54:36 +00:00
|
|
|
cto->ct_flags = octo->ct_flags;
|
2000-01-03 23:50:13 +00:00
|
|
|
cto->ct_status = 0;
|
|
|
|
cto->ct_resid = 0;
|
|
|
|
cto->ct_timeout = octo->ct_timeout;
|
|
|
|
cto->ct_seg_count = 0;
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* Adjust the new relative offset by the amount which
|
|
|
|
* is recorded in the data segment of the old CTIO2 we
|
|
|
|
* just finished filling out.
|
|
|
|
*/
|
|
|
|
cto->ct_reloff += octo->rsp.m0.ct_xfrlen;
|
Spring MegaChange #1.
----
Make a device for each ISP- really usable only with devfs and add an ioctl
entry point (this can be used to (re)set debug levels, reset the HBA,
rescan the fabric, issue lips, etc).
----
Add in a kernel thread for Fibre Channel cards. The purpose of this
thread is to be woken up to clean up after Fibre Channel events
block things. Basically, any FC event that casts doubt on the
location or identify of FC devices blocks the queues. When, and
if, we get the PORT DATABASE CHANGED or NAME SERVER DATABASE CHANGED
async event, we activate the kthread which will then, in full thread
context, re-evaluate the local loop and/or the fabric. When it's
satisfied that things are stable, it can then release the blocked
queues and let commands flow again.
The prior mechanism was a lazy evaluation. That is, the next command
to come down the pipe after change events would pay the full price
for re-evaluation. And if this was done off of a softcall, it really
could hang up the system.
These changes brings the FreeBSD port more in line with the Solaris,
Linux and NetBSD ports. It also, more importantly, gets us being
more proactive about topology changes which could then be reflected
upwards to CAM so that the periph driver can be informed sooner
rather than later when things arrive or depart.
---
Add in the (correct) usage of locking macros- we now have lock transition
macros which allow us to transition from holding the CAM lock (Giant)
and grabbing the softc lock and vice versa. Switch over to having this
HBA do real locking. Some folks claim this won't be a win. They're right.
But you have to start somewhere, and this will begin to teach us how
to DTRT for HBAs, etc.
--
Start putting in prototype 2300 support. Add back in LIP
and Loop Reset as async events that each platform will handle.
Add in another int_bogus instrumentation point.
Do some more substantial target mode cleanups.
MFC after: 8 weeks
2001-05-28 21:20:43 +00:00
|
|
|
MEMZERO(&cto->rsp, sizeof (cto->rsp));
|
|
|
|
ISP_SWIZ_CTIO2(isp, octo, octo);
|
|
|
|
ISP_ADD_REQUEST(mp->isp, j);
|
2000-01-03 23:50:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-08-31 21:39:04 +00:00
|
|
|
static void dma2(void *, bus_dma_segment_t *, int, int);
|
2000-01-03 23:50:13 +00:00
|
|
|
|
1998-09-15 10:06:23 +00:00
|
|
|
static void
|
1998-12-28 19:24:23 +00:00
|
|
|
dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
|
|
|
mush_t *mp;
|
2000-01-03 23:50:13 +00:00
|
|
|
struct ccb_scsiio *csio;
|
1998-09-15 10:06:23 +00:00
|
|
|
struct isp_pcisoftc *pci;
|
|
|
|
bus_dmamap_t *dp;
|
|
|
|
bus_dma_segment_t *eseg;
|
|
|
|
ispreq_t *rq;
|
|
|
|
ispcontreq_t *crq;
|
2000-01-03 23:50:13 +00:00
|
|
|
int seglim, datalen;
|
1998-09-15 10:06:23 +00:00
|
|
|
|
|
|
|
mp = (mush_t *) arg;
|
|
|
|
if (error) {
|
|
|
|
mp->error = error;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nseg < 1) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
|
1998-09-15 10:06:23 +00:00
|
|
|
mp->error = EFAULT;
|
|
|
|
return;
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
csio = mp->cmd_token;
|
1998-09-15 10:06:23 +00:00
|
|
|
rq = mp->rq;
|
2000-01-03 23:50:13 +00:00
|
|
|
pci = (struct isp_pcisoftc *)mp->isp;
|
2000-07-04 01:01:15 +00:00
|
|
|
dp = &pci->dmaps[isp_handle_index(rq->req_handle)];
|
1999-10-17 19:03:11 +00:00
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
|
|
|
|
} else {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
|
|
|
|
}
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
datalen = XS_XFRLEN(csio);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We're passed an initial partially filled in entry that
|
|
|
|
* has most fields filled in except for data transfer
|
|
|
|
* related values.
|
|
|
|
*
|
|
|
|
* Our job is to fill in the initial request queue entry and
|
|
|
|
* then to start allocating and filling in continuation entries
|
|
|
|
* until we've covered the entire transfer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (IS_FC(mp->isp)) {
|
1998-09-15 10:06:23 +00:00
|
|
|
seglim = ISP_RQDSEG_T2;
|
|
|
|
((ispreqt2_t *)rq)->req_totalcnt = datalen;
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_IN;
|
|
|
|
} else {
|
|
|
|
((ispreqt2_t *)rq)->req_flags |= REQFLAG_DATA_OUT;
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
} else {
|
2000-02-15 00:50:01 +00:00
|
|
|
if (csio->cdb_len > 12) {
|
|
|
|
seglim = 0;
|
|
|
|
} else {
|
|
|
|
seglim = ISP_RQDSEG;
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
|
|
|
rq->req_flags |= REQFLAG_DATA_IN;
|
|
|
|
} else {
|
|
|
|
rq->req_flags |= REQFLAG_DATA_OUT;
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
eseg = dm_segs + nseg;
|
|
|
|
|
|
|
|
while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
|
2000-01-03 23:50:13 +00:00
|
|
|
if (IS_FC(mp->isp)) {
|
1998-09-15 10:06:23 +00:00
|
|
|
ispreqt2_t *rq2 = (ispreqt2_t *)rq;
|
|
|
|
rq2->req_dataseg[rq2->req_seg_count].ds_base =
|
|
|
|
dm_segs->ds_addr;
|
|
|
|
rq2->req_dataseg[rq2->req_seg_count].ds_count =
|
|
|
|
dm_segs->ds_len;
|
|
|
|
} else {
|
|
|
|
rq->req_dataseg[rq->req_seg_count].ds_base =
|
|
|
|
dm_segs->ds_addr;
|
|
|
|
rq->req_dataseg[rq->req_seg_count].ds_count =
|
|
|
|
dm_segs->ds_len;
|
|
|
|
}
|
|
|
|
datalen -= dm_segs->ds_len;
|
|
|
|
#if 0
|
2000-01-03 23:50:13 +00:00
|
|
|
if (IS_FC(mp->isp)) {
|
1998-09-15 10:06:23 +00:00
|
|
|
ispreqt2_t *rq2 = (ispreqt2_t *)rq;
|
2001-03-01 02:21:36 +00:00
|
|
|
device_printf(mp->isp->isp_dev,
|
|
|
|
"seg0[%d] cnt 0x%x paddr 0x%08x\n",
|
|
|
|
rq->req_seg_count,
|
1998-09-15 10:06:23 +00:00
|
|
|
rq2->req_dataseg[rq2->req_seg_count].ds_count,
|
|
|
|
rq2->req_dataseg[rq2->req_seg_count].ds_base);
|
|
|
|
} else {
|
2001-03-01 02:21:36 +00:00
|
|
|
device_printf(mp->isp->isp_dev,
|
|
|
|
"seg0[%d] cnt 0x%x paddr 0x%08x\n",
|
|
|
|
rq->req_seg_count,
|
1998-09-15 10:06:23 +00:00
|
|
|
rq->req_dataseg[rq->req_seg_count].ds_count,
|
|
|
|
rq->req_dataseg[rq->req_seg_count].ds_base);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
rq->req_seg_count++;
|
|
|
|
dm_segs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (datalen > 0 && dm_segs != eseg) {
|
2000-01-03 23:50:13 +00:00
|
|
|
crq = (ispcontreq_t *)
|
|
|
|
ISP_QUEUE_ENTRY(mp->isp->isp_rquest, *mp->iptrp);
|
2000-08-01 05:16:49 +00:00
|
|
|
*mp->iptrp = ISP_NXT_QENTRY(*mp->iptrp, RQUEST_QUEUE_LEN(isp));
|
2000-01-03 23:50:13 +00:00
|
|
|
if (*mp->iptrp == mp->optr) {
|
2001-03-01 02:21:36 +00:00
|
|
|
isp_prt(mp->isp,
|
|
|
|
ISP_LOGDEBUG0, "Request Queue Overflow++");
|
1998-09-17 21:11:21 +00:00
|
|
|
mp->error = MUSHERR_NOQENTRIES;
|
1998-09-15 10:06:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
rq->req_header.rqs_entry_count++;
|
|
|
|
bzero((void *)crq, sizeof (*crq));
|
|
|
|
crq->req_header.rqs_entry_count = 1;
|
|
|
|
crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
|
|
|
|
|
|
|
|
seglim = 0;
|
|
|
|
while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
|
|
|
|
crq->req_dataseg[seglim].ds_base =
|
|
|
|
dm_segs->ds_addr;
|
|
|
|
crq->req_dataseg[seglim].ds_count =
|
|
|
|
dm_segs->ds_len;
|
|
|
|
#if 0
|
2001-03-01 02:21:36 +00:00
|
|
|
device_printf(mp->isp->isp_dev,
|
|
|
|
"seg%d[%d] cnt 0x%x paddr 0x%08x\n",
|
|
|
|
rq->req_header.rqs_entry_count-1,
|
1998-09-15 10:06:23 +00:00
|
|
|
seglim, crq->req_dataseg[seglim].ds_count,
|
|
|
|
crq->req_dataseg[seglim].ds_base);
|
|
|
|
#endif
|
|
|
|
rq->req_seg_count++;
|
|
|
|
dm_segs++;
|
|
|
|
seglim++;
|
|
|
|
datalen -= dm_segs->ds_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2000-01-03 23:50:13 +00:00
|
|
|
isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
1999-11-21 02:56:17 +00:00
|
|
|
u_int16_t *iptrp, u_int16_t optr)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
|
1999-08-16 19:52:29 +00:00
|
|
|
bus_dmamap_t *dp = NULL;
|
1998-09-15 10:06:23 +00:00
|
|
|
mush_t mush, *mp;
|
2001-08-31 21:39:04 +00:00
|
|
|
void (*eptr)(void *, bus_dma_segment_t *, int, int);
|
1998-09-15 10:06:23 +00:00
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
|
|
|
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
|
|
|
if (IS_FC(isp)) {
|
2000-07-18 06:40:22 +00:00
|
|
|
eptr = tdma_mkfc;
|
2000-01-03 23:50:13 +00:00
|
|
|
} else {
|
2000-07-18 06:40:22 +00:00
|
|
|
eptr = tdma_mk;
|
2000-01-03 23:50:13 +00:00
|
|
|
}
|
2000-07-18 06:40:22 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
|
|
|
(csio->dxfer_len == 0)) {
|
2000-01-15 01:54:36 +00:00
|
|
|
mp = &mush;
|
|
|
|
mp->isp = isp;
|
|
|
|
mp->cmd_token = csio;
|
2001-04-04 21:53:59 +00:00
|
|
|
mp->rq = rq; /* really a ct_entry_t or ct2_entry_t */
|
2000-01-15 01:54:36 +00:00
|
|
|
mp->iptrp = iptrp;
|
|
|
|
mp->optr = optr;
|
|
|
|
mp->error = 0;
|
|
|
|
(*eptr)(mp, NULL, 0, 0);
|
|
|
|
goto exit;
|
|
|
|
}
|
2000-01-03 23:50:13 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
eptr = dma2;
|
1998-09-15 10:06:23 +00:00
|
|
|
|
2000-01-15 01:54:36 +00:00
|
|
|
/*
|
|
|
|
* NB: if we need to do request queue entry swizzling,
|
|
|
|
* NB: this is where it would need to be done for cmds
|
|
|
|
* NB: that move no data. For commands that move data,
|
|
|
|
* NB: swizzling would take place in those functions.
|
|
|
|
*/
|
2000-07-18 06:40:22 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE ||
|
|
|
|
(csio->dxfer_len == 0)) {
|
2000-01-15 01:54:36 +00:00
|
|
|
rq->req_seg_count = 1;
|
|
|
|
return (CMD_QUEUED);
|
|
|
|
}
|
1998-09-15 10:06:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do a virtual grapevine step to collect info for
|
1998-09-17 21:11:21 +00:00
|
|
|
* the callback dma allocation that we have to use...
|
1998-09-15 10:06:23 +00:00
|
|
|
*/
|
|
|
|
mp = &mush;
|
|
|
|
mp->isp = isp;
|
2000-01-03 23:50:13 +00:00
|
|
|
mp->cmd_token = csio;
|
1998-09-15 10:06:23 +00:00
|
|
|
mp->rq = rq;
|
|
|
|
mp->iptrp = iptrp;
|
|
|
|
mp->optr = optr;
|
|
|
|
mp->error = 0;
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
|
|
|
|
if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
|
1998-09-17 21:11:21 +00:00
|
|
|
int error, s;
|
2000-07-04 01:01:15 +00:00
|
|
|
dp = &pci->dmaps[isp_handle_index(rq->req_handle)];
|
1998-09-15 10:06:23 +00:00
|
|
|
s = splsoftvm();
|
|
|
|
error = bus_dmamap_load(pci->parent_dmat, *dp,
|
2000-01-03 23:50:13 +00:00
|
|
|
csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
|
1998-09-15 10:06:23 +00:00
|
|
|
if (error == EINPROGRESS) {
|
|
|
|
bus_dmamap_unload(pci->parent_dmat, *dp);
|
|
|
|
mp->error = EINVAL;
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"deferred dma allocation not supported");
|
1998-09-15 10:06:23 +00:00
|
|
|
} else if (error && mp->error == 0) {
|
1999-08-16 19:52:29 +00:00
|
|
|
#ifdef DIAGNOSTIC
|
2001-03-01 02:21:36 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"error %d in dma mapping code", error);
|
1999-08-16 19:52:29 +00:00
|
|
|
#endif
|
1998-09-15 10:06:23 +00:00
|
|
|
mp->error = error;
|
|
|
|
}
|
1998-09-17 21:11:21 +00:00
|
|
|
splx(s);
|
1998-09-15 10:06:23 +00:00
|
|
|
} else {
|
|
|
|
/* Pointer to physical buffer */
|
1999-03-17 05:07:18 +00:00
|
|
|
struct bus_dma_segment seg;
|
1998-09-15 10:06:23 +00:00
|
|
|
seg.ds_addr = (bus_addr_t)csio->data_ptr;
|
|
|
|
seg.ds_len = csio->dxfer_len;
|
2000-01-03 23:50:13 +00:00
|
|
|
(*eptr)(mp, &seg, 1, 0);
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
struct bus_dma_segment *segs;
|
|
|
|
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"Physical segment pointers unsupported");
|
1998-09-15 10:06:23 +00:00
|
|
|
mp->error = EINVAL;
|
2000-01-03 23:50:13 +00:00
|
|
|
} else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) {
|
2000-12-05 07:38:41 +00:00
|
|
|
isp_prt(isp, ISP_LOGERR,
|
|
|
|
"Virtual segment addresses unsupported");
|
1998-09-15 10:06:23 +00:00
|
|
|
mp->error = EINVAL;
|
|
|
|
} else {
|
|
|
|
/* Just use the segments provided */
|
|
|
|
segs = (struct bus_dma_segment *) csio->data_ptr;
|
2000-01-03 23:50:13 +00:00
|
|
|
(*eptr)(mp, segs, csio->sglist_cnt, 0);
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-15 07:06:44 +00:00
|
|
|
#ifdef ISP_TARGET_MODE
|
2000-01-15 01:54:36 +00:00
|
|
|
exit:
|
2000-01-15 07:06:44 +00:00
|
|
|
#endif
|
1998-09-15 10:06:23 +00:00
|
|
|
if (mp->error) {
|
1998-09-17 21:11:21 +00:00
|
|
|
int retval = CMD_COMPLETE;
|
|
|
|
if (mp->error == MUSHERR_NOQENTRIES) {
|
|
|
|
retval = CMD_EAGAIN;
|
|
|
|
} else if (mp->error == EFBIG) {
|
1999-08-16 19:52:29 +00:00
|
|
|
XS_SETERR(csio, CAM_REQ_TOO_BIG);
|
1998-09-15 10:06:23 +00:00
|
|
|
} else if (mp->error == EINVAL) {
|
1999-08-16 19:52:29 +00:00
|
|
|
XS_SETERR(csio, CAM_REQ_INVALID);
|
1998-09-15 10:06:23 +00:00
|
|
|
} else {
|
1999-08-16 19:52:29 +00:00
|
|
|
XS_SETERR(csio, CAM_UNREC_HBA_ERROR);
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
1998-09-17 21:11:21 +00:00
|
|
|
return (retval);
|
|
|
|
} else {
|
1999-08-16 19:52:29 +00:00
|
|
|
/*
|
|
|
|
* Check to see if we weren't cancelled while sleeping on
|
|
|
|
* getting DMA resources...
|
|
|
|
*/
|
2000-01-03 23:50:13 +00:00
|
|
|
if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
|
1999-08-16 19:52:29 +00:00
|
|
|
if (dp) {
|
|
|
|
bus_dmamap_unload(pci->parent_dmat, *dp);
|
|
|
|
}
|
|
|
|
return (CMD_COMPLETE);
|
|
|
|
}
|
1998-09-17 21:11:21 +00:00
|
|
|
return (CMD_QUEUED);
|
1998-09-15 10:06:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2001-03-04 18:42:51 +00:00
|
|
|
isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle)
|
1998-09-15 10:06:23 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
|
2000-07-04 01:01:15 +00:00
|
|
|
bus_dmamap_t *dp = &pci->dmaps[isp_handle_index(handle)];
|
1999-10-17 19:03:11 +00:00
|
|
|
if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
|
1998-09-15 10:06:23 +00:00
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD);
|
|
|
|
} else {
|
|
|
|
bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE);
|
|
|
|
}
|
|
|
|
bus_dmamap_unload(pci->parent_dmat, *dp);
|
|
|
|
}
|
|
|
|
|
1998-04-22 18:12:29 +00:00
|
|
|
|
|
|
|
static void
|
1998-12-28 19:24:23 +00:00
|
|
|
isp_pci_reset1(struct ispsoftc *isp)
|
1998-04-22 18:12:29 +00:00
|
|
|
{
|
|
|
|
/* Make sure the BIOS is disabled */
|
|
|
|
isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
|
2000-07-04 01:01:15 +00:00
|
|
|
/* and enable interrupts */
|
|
|
|
ENABLE_INTS(isp);
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-08-01 05:16:49 +00:00
|
|
|
isp_pci_dumpregs(struct ispsoftc *isp, const char *msg)
|
1998-04-22 18:12:29 +00:00
|
|
|
{
|
|
|
|
struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
|
2000-08-01 05:16:49 +00:00
|
|
|
if (msg)
|
2001-03-01 02:21:36 +00:00
|
|
|
printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg);
|
|
|
|
else
|
|
|
|
printf("%s:\n", device_get_nameunit(isp->isp_dev));
|
2000-08-01 05:16:49 +00:00
|
|
|
if (IS_SCSI(isp))
|
|
|
|
printf(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1));
|
|
|
|
else
|
|
|
|
printf(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR));
|
|
|
|
printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR),
|
|
|
|
ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
|
|
|
|
printf("risc_hccr=%x\n", ISP_READ(isp, HCCR));
|
|
|
|
|
|
|
|
|
|
|
|
if (IS_SCSI(isp)) {
|
|
|
|
ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
|
|
|
|
printf(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n",
|
|
|
|
ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS),
|
|
|
|
ISP_READ(isp, CDMA_FIFO_STS));
|
|
|
|
printf(" ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n",
|
|
|
|
ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS),
|
|
|
|
ISP_READ(isp, DDMA_FIFO_STS));
|
|
|
|
printf(" sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n",
|
|
|
|
ISP_READ(isp, SXP_INTERRUPT),
|
|
|
|
ISP_READ(isp, SXP_GROSS_ERR),
|
|
|
|
ISP_READ(isp, SXP_PINS_CTRL));
|
|
|
|
ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
|
|
|
|
}
|
|
|
|
printf(" mbox regs: %x %x %x %x %x\n",
|
|
|
|
ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1),
|
|
|
|
ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3),
|
|
|
|
ISP_READ(isp, OUTMAILBOX4));
|
|
|
|
printf(" PCI Status Command/Status=%x\n",
|
2000-02-11 19:45:17 +00:00
|
|
|
pci_read_config(pci->pci_dev, PCIR_COMMAND, 1));
|
1998-04-22 18:12:29 +00:00
|
|
|
}
|