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: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Родитель
7aaef27baf
Коммит
92d161c373
|
@ -5,6 +5,7 @@
|
|||
config SCSI_AIC7XXX
|
||||
tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
|
||||
depends on (PCI || EISA) && SCSI
|
||||
select SCSI_SPI_ATTRS
|
||||
---help---
|
||||
This driver supports all of Adaptec's Fast through Ultra 160 PCI
|
||||
based SCSI controllers as well as the aic7770 based EISA and VLB
|
||||
|
|
|
@ -122,6 +122,10 @@
|
|||
#include "aic7xxx_osm.h"
|
||||
#include "aic7xxx_inline.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
|
||||
|
@ -1728,6 +1732,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
|
|||
ahc_linux_start_dv(ahc);
|
||||
ahc_unlock(ahc, &s);
|
||||
|
||||
host->transportt = ahc_linux_transport_template;
|
||||
|
||||
#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_scan_host(host);
|
||||
|
@ -4990,13 +4996,267 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
|
|||
|
||||
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
|
||||
ahc_linux_init(void)
|
||||
{
|
||||
#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);
|
||||
if (rc)
|
||||
return rc;
|
||||
spi_release_transport(ahc_linux_transport_template);
|
||||
ahc_linux_exit();
|
||||
return -ENODEV;
|
||||
#else
|
||||
|
@ -5037,6 +5297,7 @@ ahc_linux_exit(void)
|
|||
#endif
|
||||
ahc_linux_pci_exit();
|
||||
ahc_linux_eisa_exit();
|
||||
spi_release_transport(ahc_linux_transport_template);
|
||||
}
|
||||
|
||||
module_init(ahc_linux_init);
|
||||
|
|
Загрузка…
Ссылка в новой задаче