* [RFC] convert fusion to SPI transport class and use generic DV
@ 2005-06-09 13:35 James Bottomley
0 siblings, 0 replies; only message in thread
From: James Bottomley @ 2005-06-09 13:35 UTC (permalink / raw)
To: SCSI Mailing List
This code is more posted as an illustration of how to do things than an
actual patch for submission. However, I've tested this and it does
actually work:
ioc1: 53C1030: Capabilities={Initiator,Target}
scsi5 : ioc1: LSI53C1030, FwRev=01032700h, Ports=1, MaxQ=255, IRQ=56
Vendor: HP 36.4G Model: ST336607LW Rev: HPC3
Type: Direct-Access ANSI SCSI revision: 03
target5:0:1: Beginning Domain Validation
target5:0:1: Ending Domain Validation
target5:0:1: FAST-160 WIDE SCSI 320.0 MB/s DT IU QAS (6.25 ns, offset 127)
jejb@titanic> ls /sys/class/spi_transport/target5\:0\:1/
device@ iu max_width offset period rd_strm rti wr_flow
dt max_offset min_period pcomp_en qas revalidate width
James
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -9,6 +9,7 @@ config FUSION_SPI
tristate "Fusion MPT ScsiHost drivers for SPI"
depends on PCI && SCSI
select FUSION
+ select SCSI_SPI_ATTRS
---help---
SCSI HOST support for a parallel SCSI host adapters.
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2507,7 +2507,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
/* 4. Renegotiate to all devices, if SCSI
*/
if (ioc->bus_type == SCSI) {
- dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
+ printk("writeSDP1: ALL_IDS USE_NVRAM\n");
mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
}
@@ -2766,7 +2766,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
}
}
- mptscsih_setTargetNegoParms(hd, vdev, data_56);
+ //mptscsih_setTargetNegoParms(hd, vdev, data_56);
} else {
/* Initial Inquiry may not request enough data bytes to
* obtain byte 57. DV will; if target doesn't return
@@ -2777,7 +2777,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
*/
data_56 = data[56];
vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
- mptscsih_setTargetNegoParms(hd, vdev, data_56);
+ //mptscsih_setTargetNegoParms(hd, vdev, data_56);
}
}
}
@@ -2806,6 +2806,8 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOS
target->negoFlags = pspi_data->noQas;
+ printk("HERE\n");
+
/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
* support. If available, default QAS to off and allow enabling.
* If not available, default QAS to on, turn off for non-disks.
@@ -3105,6 +3107,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
u8 negoFlags;
u8 maxwidth, maxoffset, maxfactor;
+ printk("HERE2\n");
+
if (ioc->spi_data.sdp1length == 0)
return 0;
@@ -3204,8 +3208,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
return -EAGAIN;
}
- ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
- hd->ioc->name, mf, id, requested, configuration));
+ printk(MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
+ hd->ioc->name, mf, id, requested, configuration);
/* Set the request and the data pointers.
@@ -4228,12 +4232,12 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, in
if ((pTarget != NULL) && (!pTarget->raidVolume)) {
if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
pTarget->negoFlags |= hd->ioc->spi_data.noQas;
- dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
+ printk("writeSDP1: id=%d flags=0\n", id);
mptscsih_writeSDP1(hd, 0, ii, 0);
}
} else {
if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
- dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
+ printk("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id);
mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
}
}
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -67,7 +67,7 @@
* capabilities.
*/
-#define MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+#undef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* SCSI driver setup structure. Settings can be overridden
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -62,6 +62,8 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -98,6 +100,8 @@ static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+static struct scsi_transport_template *mptspi_transport_template = NULL;
+
static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
@@ -115,6 +119,48 @@ static struct device_attribute *mptspi_d
NULL,
};
+static int mptspi_target_alloc(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+ static void mptspi_write_offset(struct scsi_target *, int);
+ static void mptspi_write_width(struct scsi_target *, int);
+
+ if (hd == NULL)
+ return -ENODEV;
+
+ if (hd->ioc->spi_data.nvram &&
+ hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) {
+ u32 nvram = hd->ioc->spi_data.nvram[starget->id];
+ spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+ spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+ } else {
+ spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor;
+ spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth;
+ }
+ spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset;
+
+ spi_offset(starget) = 0;
+ mptspi_write_width(starget, 0);
+
+ return 0;
+}
+
+static int mptspi_slave_configure(struct scsi_device *sdev)
+{
+ int ret = mptscsih_slave_configure(sdev);
+
+ if (ret)
+ return ret;
+
+ if (!spi_initial_dv(sdev->sdev_target)) {
+ spi_dv_device(sdev);
+ spi_display_xfer_agreement(sdev->sdev_target);
+ }
+
+ return 0;
+}
+
static struct scsi_host_template mptspi_driver_template = {
.proc_name = "mptspi",
.proc_info = mptscsih_proc_info,
@@ -122,8 +168,9 @@ static struct scsi_host_template mptspi_
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.slave_alloc = mptscsih_slave_alloc,
- .slave_configure = mptscsih_slave_configure,
+ .slave_configure = mptspi_slave_configure,
.slave_destroy = mptscsih_slave_destroy,
+ .target_alloc = mptspi_target_alloc,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_bus_reset_handler = mptscsih_bus_reset,
@@ -138,6 +185,325 @@ static struct scsi_host_template mptspi_
.sdev_attrs = mptspi_dev_attrs,
};
+static int mptspi_read_page0(struct scsi_target *starget,
+ struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+ struct _MPT_ADAPTER *ioc = hd->ioc;
+ struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0;
+ dma_addr_t pg0_dma;
+ int size;
+ struct _x_config_parms cfg;
+ struct _CONFIG_PAGE_HEADER hdr;
+ int err = -EBUSY;
+
+ size = ioc->spi_data.sdp0length * 4;
+ /*
+ if (ioc->spi_data.sdp0length & 1)
+ size += size + 4;
+ size += 2048;
+ */
+
+ pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL);
+ if (pg0 == NULL) {
+ dev_printk(KERN_ERR, &starget->dev, "dma_alloc_coherent for parameters failed\n");
+ return -EINVAL;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ hdr.PageVersion = ioc->spi_data.sdp0version;
+ hdr.PageLength = ioc->spi_data.sdp0length;
+ hdr.PageNumber = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.hdr = &hdr;
+ cfg.physAddr = pg0_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+ cfg.dir = 0;
+ cfg.pageAddr = (starget->channel << 8) | starget->id;
+
+ if (mpt_config(ioc, &cfg)) {
+ dev_printk(KERN_ERR, &starget->dev, "mpt_config failed\n");
+ goto out_free;
+ }
+ err = 0;
+ memcpy(pass_pg0, pg0, size);
+
+ out_free:
+ dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma);
+ return err;
+}
+
+static void mptspi_read_parameters(struct scsi_target *starget)
+{
+ int nego;
+ struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0;
+
+ mptspi_read_page0(starget, &pg0);
+
+ nego = le32_to_cpu(pg0.NegotiatedParameters);
+
+ spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;
+ spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;
+ spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;
+ //spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;
+ spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;
+ spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;
+ spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;
+ spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;
+ spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;
+ spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;
+ spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;
+}
+
+static int mptspi_write_page1(struct scsi_target *starget,
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata;
+ struct _MPT_ADAPTER *ioc = hd->ioc;
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;
+ dma_addr_t pg1_dma;
+ int size;
+ struct _x_config_parms cfg;
+ struct _CONFIG_PAGE_HEADER hdr;
+ int err = -EBUSY;
+
+ size = ioc->spi_data.sdp1length * 4;
+
+ pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);
+ if (pg1 == NULL) {
+ dev_printk(KERN_ERR, &starget->dev, "dma_alloc_coherent for parameters failed\n");
+ return -EINVAL;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+
+ hdr.PageVersion = ioc->spi_data.sdp1version;
+ hdr.PageLength = ioc->spi_data.sdp1length;
+ hdr.PageNumber = 1;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.hdr = &hdr;
+ cfg.physAddr = pg1_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ cfg.dir = 1;
+ cfg.pageAddr = (starget->channel << 8) | starget->id;
+
+ memcpy(pg1, pass_pg1, size);
+
+ pg1->Header.PageVersion = hdr.PageVersion;
+ pg1->Header.PageLength = hdr.PageLength;
+ pg1->Header.PageNumber = hdr.PageNumber;
+ pg1->Header.PageType = hdr.PageType;
+
+ if (mpt_config(ioc, &cfg)) {
+ dev_printk(KERN_ERR, &starget->dev, "mpt_config failed\n");
+ goto out_free;
+ }
+ err = 0;
+
+ out_free:
+ dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);
+ return err;
+}
+
+static u32 mptspi_getRP(struct scsi_target *starget)
+{
+ u32 nego = 0;
+
+ nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;
+ nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;
+ nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;
+ //nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;
+ nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;
+ nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;
+ nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;
+ nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;
+
+ nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;
+ nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;
+ nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
+
+ return nego;
+}
+
+static void mptspi_write_offset(struct scsi_target *starget, int offset)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ if (offset < 0)
+ offset = 0;
+
+ if (offset > 255)
+ offset = 255;
+
+ if (spi_offset(starget) == -1)
+ mptspi_read_parameters(starget);
+
+ spi_offset(starget) = offset;
+
+ nego = mptspi_getRP(starget);
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_period(struct scsi_target *starget, int period)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ if (period < 8)
+ period = 8;
+
+ if (period > 255)
+ period = 255;
+
+ if (spi_period(starget) == -1)
+ mptspi_read_parameters(starget);
+
+ if (period == 8) {
+ spi_iu(starget) = 1;
+ spi_dt(starget) = 1;
+ } else if (period == 9) {
+ spi_dt(starget) = 1;
+ }
+
+ spi_period(starget) = period;
+
+ nego = mptspi_getRP(starget);
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_dt(struct scsi_target *starget, int dt)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ if (spi_period(starget) == -1)
+ mptspi_read_parameters(starget);
+
+ if (!dt && spi_period(starget) < 10)
+ spi_period(starget) = 10;
+
+ spi_dt(starget) = dt;
+
+ nego = mptspi_getRP(starget);
+
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_iu(struct scsi_target *starget, int iu)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ if (spi_period(starget) == -1)
+ mptspi_read_parameters(starget);
+
+ if (!iu && spi_period(starget) < 9)
+ spi_period(starget) = 9;
+
+ spi_iu(starget) = iu;
+
+ nego = mptspi_getRP(starget);
+
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_qas(struct scsi_target *starget, int qas)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ spi_qas(starget) = qas;
+
+ nego = mptspi_getRP(starget);
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static void mptspi_write_width(struct scsi_target *starget, int width)
+{
+ struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
+ u32 nego;
+
+ if (!width) {
+ spi_dt(starget) = 0;
+ if (spi_period(starget) < 10)
+ spi_period(starget) = 10;
+ }
+
+ spi_width(starget) = width;
+
+ nego = mptspi_getRP(starget);
+
+ pg1.RequestedParameters = cpu_to_le32(nego);
+ pg1.Reserved = 0;
+ pg1.Configuration = 0;
+
+ mptspi_write_page1(starget, &pg1);
+}
+
+static struct spi_function_template mptspi_transport_functions = {
+ .get_offset = mptspi_read_parameters,
+ .set_offset = mptspi_write_offset,
+ .show_offset = 1,
+ .get_period = mptspi_read_parameters,
+ .set_period = mptspi_write_period,
+ .show_period = 1,
+ .get_width = mptspi_read_parameters,
+ .set_width = mptspi_write_width,
+ .show_width = 1,
+ .get_iu = mptspi_read_parameters,
+ .set_iu = mptspi_write_iu,
+ .show_iu = 1,
+ .get_dt = mptspi_read_parameters,
+ .set_dt = mptspi_write_dt,
+ .show_dt = 1,
+ .get_qas = mptspi_read_parameters,
+ .set_qas = mptspi_write_qas,
+ .show_qas = 1,
+ .get_wr_flow = mptspi_read_parameters,
+ .show_wr_flow = 1,
+ .get_rd_strm = mptspi_read_parameters,
+ .show_rd_strm = 1,
+ .get_rti = mptspi_read_parameters,
+ .show_rti = 1,
+ .get_pcomp_en = mptspi_read_parameters,
+ .show_pcomp_en = 1,
+};
+
/****************************************************************************
* Supported hardware
@@ -382,7 +748,6 @@ mptspi_probe(struct pci_dev *pdev, const
mpt_saf_te,
mpt_pq_filter));
#endif
-
ioc->spi_data.forceDv = 0;
ioc->spi_data.noQas = 0;
@@ -398,6 +763,11 @@ mptspi_probe(struct pci_dev *pdev, const
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
+ /* Some versions of the firmware don't support page 0; without
+ * that we can't get the parameters */
+ if (hd->ioc->spi_data.sdp0length != 0)
+ sh->transportt = mptspi_transport_template;
+
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
@@ -441,6 +811,10 @@ mptspi_init(void)
show_mptmod_ver(my_NAME, my_VERSION);
+ mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions);
+ if (!mptspi_transport_template)
+ return -ENODEV;
+
mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-06-09 13:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-09 13:35 [RFC] convert fusion to SPI transport class and use generic DV James Bottomley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox