aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx/aic7xxx_osm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx_osm.c')
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c261
1 files changed, 261 insertions, 0 deletions
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);