aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx1
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c261
2 files changed, 262 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 8398e0dd4810..ac8de03c9fa2 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -5,6 +5,7 @@
5config SCSI_AIC7XXX 5config SCSI_AIC7XXX
6 tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)" 6 tristate "Adaptec AIC7xxx Fast -> U160 support (New Driver)"
7 depends on (PCI || EISA) && SCSI 7 depends on (PCI || EISA) && SCSI
8 select SCSI_SPI_ATTRS
8 ---help--- 9 ---help---
9 This driver supports all of Adaptec's Fast through Ultra 160 PCI 10 This driver supports all of Adaptec's Fast through Ultra 160 PCI
10 based SCSI controllers as well as the aic7770 based EISA and VLB 11 based SCSI controllers as well as the aic7770 based EISA and VLB
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 35d6de5a4c9d..6b6ee0a52a46 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -122,6 +122,10 @@
122#include "aic7xxx_osm.h" 122#include "aic7xxx_osm.h"
123#include "aic7xxx_inline.h" 123#include "aic7xxx_inline.h"
124#include <scsi/scsicam.h> 124#include <scsi/scsicam.h>
125#include <scsi/scsi_transport.h>
126#include <scsi/scsi_transport_spi.h>
127
128static struct scsi_transport_template *ahc_linux_transport_template = NULL;
125 129
126/* 130/*
127 * Include aiclib.c as part of our 131 * Include aiclib.c as part of our
@@ -1728,6 +1732,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
1728 ahc_linux_start_dv(ahc); 1732 ahc_linux_start_dv(ahc);
1729 ahc_unlock(ahc, &s); 1733 ahc_unlock(ahc, &s);
1730 1734
1735 host->transportt = ahc_linux_transport_template;
1736
1731#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1737#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1732 scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */ 1738 scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
1733 scsi_scan_host(host); 1739 scsi_scan_host(host);
@@ -4990,13 +4996,267 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
4990 4996
4991static void ahc_linux_exit(void); 4997static void ahc_linux_exit(void);
4992 4998
4999static void ahc_linux_get_period(struct scsi_target *starget)
5000{
5001 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5002 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5003 struct ahc_tmode_tstate *tstate;
5004 struct ahc_initiator_tinfo *tinfo
5005 = ahc_fetch_transinfo(ahc,
5006 starget->channel + 'A',
5007 shost->this_id, starget->id, &tstate);
5008 spi_period(starget) = tinfo->curr.period;
5009}
5010
5011static void ahc_linux_set_period(struct scsi_target *starget, int period)
5012{
5013 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5014 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5015 struct ahc_tmode_tstate *tstate;
5016 struct ahc_initiator_tinfo *tinfo
5017 = ahc_fetch_transinfo(ahc,
5018 starget->channel + 'A',
5019 shost->this_id, starget->id, &tstate);
5020 struct ahc_devinfo devinfo;
5021 unsigned int ppr_options = tinfo->curr.ppr_options;
5022 unsigned long flags;
5023 unsigned long offset = tinfo->curr.offset;
5024 struct ahc_syncrate *syncrate;
5025
5026 if (offset == 0)
5027 offset = MAX_OFFSET;
5028
5029 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5030 starget->channel + 'A', ROLE_INITIATOR);
5031 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
5032 ahc_lock(ahc, &flags);
5033 ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
5034 ppr_options, AHC_TRANS_GOAL, FALSE);
5035 ahc_unlock(ahc, &flags);
5036}
5037
5038static void ahc_linux_get_offset(struct scsi_target *starget)
5039{
5040 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5041 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5042 struct ahc_tmode_tstate *tstate;
5043 struct ahc_initiator_tinfo *tinfo
5044 = ahc_fetch_transinfo(ahc,
5045 starget->channel + 'A',
5046 shost->this_id, starget->id, &tstate);
5047 spi_offset(starget) = tinfo->curr.offset;
5048}
5049
5050static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
5051{
5052 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5053 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5054 struct ahc_tmode_tstate *tstate;
5055 struct ahc_initiator_tinfo *tinfo
5056 = ahc_fetch_transinfo(ahc,
5057 starget->channel + 'A',
5058 shost->this_id, starget->id, &tstate);
5059 struct ahc_devinfo devinfo;
5060 unsigned int ppr_options = 0;
5061 unsigned int period = 0;
5062 unsigned long flags;
5063 struct ahc_syncrate *syncrate = NULL;
5064
5065 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5066 starget->channel + 'A', ROLE_INITIATOR);
5067 if (offset != 0) {
5068 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
5069 period = tinfo->curr.period;
5070 ppr_options = tinfo->curr.ppr_options;
5071 }
5072 ahc_lock(ahc, &flags);
5073 ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
5074 ppr_options, AHC_TRANS_GOAL, FALSE);
5075 ahc_unlock(ahc, &flags);
5076}
5077
5078static void ahc_linux_get_width(struct scsi_target *starget)
5079{
5080 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5081 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5082 struct ahc_tmode_tstate *tstate;
5083 struct ahc_initiator_tinfo *tinfo
5084 = ahc_fetch_transinfo(ahc,
5085 starget->channel + 'A',
5086 shost->this_id, starget->id, &tstate);
5087 spi_width(starget) = tinfo->curr.width;
5088}
5089
5090static void ahc_linux_set_width(struct scsi_target *starget, int width)
5091{
5092 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5093 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5094 struct ahc_devinfo devinfo;
5095 unsigned long flags;
5096
5097 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5098 starget->channel + 'A', ROLE_INITIATOR);
5099 ahc_lock(ahc, &flags);
5100 ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
5101 ahc_unlock(ahc, &flags);
5102}
5103
5104static void ahc_linux_get_dt(struct scsi_target *starget)
5105{
5106 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5107 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5108 struct ahc_tmode_tstate *tstate;
5109 struct ahc_initiator_tinfo *tinfo
5110 = ahc_fetch_transinfo(ahc,
5111 starget->channel + 'A',
5112 shost->this_id, starget->id, &tstate);
5113 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
5114}
5115
5116static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
5117{
5118 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5119 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5120 struct ahc_tmode_tstate *tstate;
5121 struct ahc_initiator_tinfo *tinfo
5122 = ahc_fetch_transinfo(ahc,
5123 starget->channel + 'A',
5124 shost->this_id, starget->id, &tstate);
5125 struct ahc_devinfo devinfo;
5126 unsigned int ppr_options = tinfo->curr.ppr_options
5127 & ~MSG_EXT_PPR_DT_REQ;
5128 unsigned int period = tinfo->curr.period;
5129 unsigned long flags;
5130 struct ahc_syncrate *syncrate;
5131
5132 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5133 starget->channel + 'A', ROLE_INITIATOR);
5134 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
5135 dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
5136 ahc_lock(ahc, &flags);
5137 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
5138 ppr_options, AHC_TRANS_GOAL, FALSE);
5139 ahc_unlock(ahc, &flags);
5140}
5141
5142static void ahc_linux_get_qas(struct scsi_target *starget)
5143{
5144 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5145 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5146 struct ahc_tmode_tstate *tstate;
5147 struct ahc_initiator_tinfo *tinfo
5148 = ahc_fetch_transinfo(ahc,
5149 starget->channel + 'A',
5150 shost->this_id, starget->id, &tstate);
5151 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
5152}
5153
5154static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
5155{
5156 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5157 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5158 struct ahc_tmode_tstate *tstate;
5159 struct ahc_initiator_tinfo *tinfo
5160 = ahc_fetch_transinfo(ahc,
5161 starget->channel + 'A',
5162 shost->this_id, starget->id, &tstate);
5163 struct ahc_devinfo devinfo;
5164 unsigned int ppr_options = tinfo->curr.ppr_options
5165 & ~MSG_EXT_PPR_QAS_REQ;
5166 unsigned int period = tinfo->curr.period;
5167 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
5168 unsigned long flags;
5169 struct ahc_syncrate *syncrate;
5170
5171 if (qas)
5172 ppr_options |= MSG_EXT_PPR_QAS_REQ;
5173
5174 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5175 starget->channel + 'A', ROLE_INITIATOR);
5176 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
5177 dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
5178 ahc_lock(ahc, &flags);
5179 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
5180 ppr_options, AHC_TRANS_GOAL, FALSE);
5181 ahc_unlock(ahc, &flags);
5182}
5183
5184static void ahc_linux_get_iu(struct scsi_target *starget)
5185{
5186 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5187 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5188 struct ahc_tmode_tstate *tstate;
5189 struct ahc_initiator_tinfo *tinfo
5190 = ahc_fetch_transinfo(ahc,
5191 starget->channel + 'A',
5192 shost->this_id, starget->id, &tstate);
5193 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
5194}
5195
5196static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
5197{
5198 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
5199 struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
5200 struct ahc_tmode_tstate *tstate;
5201 struct ahc_initiator_tinfo *tinfo
5202 = ahc_fetch_transinfo(ahc,
5203 starget->channel + 'A',
5204 shost->this_id, starget->id, &tstate);
5205 struct ahc_devinfo devinfo;
5206 unsigned int ppr_options = tinfo->curr.ppr_options
5207 & ~MSG_EXT_PPR_IU_REQ;
5208 unsigned int period = tinfo->curr.period;
5209 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
5210 unsigned long flags;
5211 struct ahc_syncrate *syncrate;
5212
5213 if (iu)
5214 ppr_options |= MSG_EXT_PPR_IU_REQ;
5215
5216 ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
5217 starget->channel + 'A', ROLE_INITIATOR);
5218 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
5219 dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
5220 ahc_lock(ahc, &flags);
5221 ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
5222 ppr_options, AHC_TRANS_GOAL, FALSE);
5223 ahc_unlock(ahc, &flags);
5224}
5225
5226static struct spi_function_template ahc_linux_transport_functions = {
5227 .get_offset = ahc_linux_get_offset,
5228 .set_offset = ahc_linux_set_offset,
5229 .show_offset = 1,
5230 .get_period = ahc_linux_get_period,
5231 .set_period = ahc_linux_set_period,
5232 .show_period = 1,
5233 .get_width = ahc_linux_get_width,
5234 .set_width = ahc_linux_set_width,
5235 .show_width = 1,
5236 .get_dt = ahc_linux_get_dt,
5237 .set_dt = ahc_linux_set_dt,
5238 .show_dt = 1,
5239 .get_iu = ahc_linux_get_iu,
5240 .set_iu = ahc_linux_set_iu,
5241 .show_iu = 1,
5242 .get_qas = ahc_linux_get_qas,
5243 .set_qas = ahc_linux_set_qas,
5244 .show_qas = 1,
5245};
5246
5247
5248
4993static int __init 5249static int __init
4994ahc_linux_init(void) 5250ahc_linux_init(void)
4995{ 5251{
4996#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 5252#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
5253 ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions);
5254 if (!ahc_linux_transport_template)
5255 return -ENODEV;
4997 int rc = ahc_linux_detect(&aic7xxx_driver_template); 5256 int rc = ahc_linux_detect(&aic7xxx_driver_template);
4998 if (rc) 5257 if (rc)
4999 return rc; 5258 return rc;
5259 spi_release_transport(ahc_linux_transport_template);
5000 ahc_linux_exit(); 5260 ahc_linux_exit();
5001 return -ENODEV; 5261 return -ENODEV;
5002#else 5262#else
@@ -5037,6 +5297,7 @@ ahc_linux_exit(void)
5037#endif 5297#endif
5038 ahc_linux_pci_exit(); 5298 ahc_linux_pci_exit();
5039 ahc_linux_eisa_exit(); 5299 ahc_linux_eisa_exit();
5300 spi_release_transport(ahc_linux_transport_template);
5040} 5301}
5041 5302
5042module_init(ahc_linux_init); 5303module_init(ahc_linux_init);