提交 92d161c3 编写于 作者: 提交者: James Bottomley

aic7xxx: add support for the SPI transport class

This is just a simplistic patch to export all of the
aic7xxx internal transport parameters via the SPI
transport class.  It doesn't actually alter the way the
driver works at all.
Signed-off-by: NJames Bottomley <James.Bottomley@SteelEye.com>
上级 7aaef27b
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
config SCSI_AIC7XXX config SCSI_AIC7XXX
tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)" tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
depends on (PCI || EISA) && SCSI depends on (PCI || EISA) && SCSI
select SCSI_SPI_ATTRS
---help--- ---help---
This driver supports all of Adaptec's Fast through Ultra 160 PCI This driver supports all of Adaptec's Fast through Ultra 160 PCI
based SCSI controllers as well as the aic7770 based EISA and VLB based SCSI controllers as well as the aic7770 based EISA and VLB
......
...@@ -122,6 +122,10 @@ ...@@ -122,6 +122,10 @@
#include "aic7xxx_osm.h" #include "aic7xxx_osm.h"
#include "aic7xxx_inline.h" #include "aic7xxx_inline.h"
#include <scsi/scsicam.h> #include <scsi/scsicam.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
static struct scsi_transport_template *ahc_linux_transport_template = NULL;
/* /*
* Include aiclib.c as part of our * Include aiclib.c as part of our
...@@ -1728,6 +1732,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ...@@ -1728,6 +1732,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc_linux_start_dv(ahc); ahc_linux_start_dv(ahc);
ahc_unlock(ahc, &s); ahc_unlock(ahc, &s);
host->transportt = ahc_linux_transport_template;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */ scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
scsi_scan_host(host); scsi_scan_host(host);
...@@ -4990,13 +4996,267 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) ...@@ -4990,13 +4996,267 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
static void ahc_linux_exit(void); static void ahc_linux_exit(void);
static void ahc_linux_get_period(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_period(starget) = tinfo->curr.period;
}
static void ahc_linux_set_period(struct scsi_target *starget, int period)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
unsigned int ppr_options = tinfo->curr.ppr_options;
unsigned long flags;
unsigned long offset = tinfo->curr.offset;
struct ahc_syncrate *syncrate;
if (offset == 0)
offset = MAX_OFFSET;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static void ahc_linux_get_offset(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_offset(starget) = tinfo->curr.offset;
}
static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
unsigned int ppr_options = 0;
unsigned int period = 0;
unsigned long flags;
struct ahc_syncrate *syncrate = NULL;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
if (offset != 0) {
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
period = tinfo->curr.period;
ppr_options = tinfo->curr.ppr_options;
}
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static void ahc_linux_get_width(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_width(starget) = tinfo->curr.width;
}
static void ahc_linux_set_width(struct scsi_target *starget, int width)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_devinfo devinfo;
unsigned long flags;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
ahc_lock(ahc, &flags);
ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static void ahc_linux_get_dt(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
}
static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
unsigned int ppr_options = tinfo->curr.ppr_options
& ~MSG_EXT_PPR_DT_REQ;
unsigned int period = tinfo->curr.period;
unsigned long flags;
struct ahc_syncrate *syncrate;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static void ahc_linux_get_qas(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
}
static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
unsigned int ppr_options = tinfo->curr.ppr_options
& ~MSG_EXT_PPR_QAS_REQ;
unsigned int period = tinfo->curr.period;
unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
unsigned long flags;
struct ahc_syncrate *syncrate;
if (qas)
ppr_options |= MSG_EXT_PPR_QAS_REQ;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static void ahc_linux_get_iu(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
}
static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
struct ahc_tmode_tstate *tstate;
struct ahc_initiator_tinfo *tinfo
= ahc_fetch_transinfo(ahc,
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
unsigned int ppr_options = tinfo->curr.ppr_options
& ~MSG_EXT_PPR_IU_REQ;
unsigned int period = tinfo->curr.period;
unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
unsigned long flags;
struct ahc_syncrate *syncrate;
if (iu)
ppr_options |= MSG_EXT_PPR_IU_REQ;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static struct spi_function_template ahc_linux_transport_functions = {
.get_offset = ahc_linux_get_offset,
.set_offset = ahc_linux_set_offset,
.show_offset = 1,
.get_period = ahc_linux_get_period,
.set_period = ahc_linux_set_period,
.show_period = 1,
.get_width = ahc_linux_get_width,
.set_width = ahc_linux_set_width,
.show_width = 1,
.get_dt = ahc_linux_get_dt,
.set_dt = ahc_linux_set_dt,
.show_dt = 1,
.get_iu = ahc_linux_get_iu,
.set_iu = ahc_linux_set_iu,
.show_iu = 1,
.get_qas = ahc_linux_get_qas,
.set_qas = ahc_linux_set_qas,
.show_qas = 1,
};
static int __init static int __init
ahc_linux_init(void) ahc_linux_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions);
if (!ahc_linux_transport_template)
return -ENODEV;
int rc = ahc_linux_detect(&aic7xxx_driver_template); int rc = ahc_linux_detect(&aic7xxx_driver_template);
if (rc) if (rc)
return rc; return rc;
spi_release_transport(ahc_linux_transport_template);
ahc_linux_exit(); ahc_linux_exit();
return -ENODEV; return -ENODEV;
#else #else
...@@ -5037,6 +5297,7 @@ ahc_linux_exit(void) ...@@ -5037,6 +5297,7 @@ ahc_linux_exit(void)
#endif #endif
ahc_linux_pci_exit(); ahc_linux_pci_exit();
ahc_linux_eisa_exit(); ahc_linux_eisa_exit();
spi_release_transport(ahc_linux_transport_template);
} }
module_init(ahc_linux_init); module_init(ahc_linux_init);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册