diff options
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r-- | drivers/scsi/aic7xxx/Kconfig.aic7xxx | 1 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 261 |
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 @@ | |||
5 | config SCSI_AIC7XXX | 5 | config 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 | |||
128 | static 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 | ||
4991 | static void ahc_linux_exit(void); | 4997 | static void ahc_linux_exit(void); |
4992 | 4998 | ||
4999 | static 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 | |||
5011 | static 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 | |||
5038 | static 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 | |||
5050 | static 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 | |||
5078 | static 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 | |||
5090 | static 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 | |||
5104 | static 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 | |||
5116 | static 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 | |||
5142 | static 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 | |||
5154 | static 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 | |||
5184 | static 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 | |||
5196 | static 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 | |||
5226 | static 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 | |||
4993 | static int __init | 5249 | static int __init |
4994 | ahc_linux_init(void) | 5250 | ahc_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 | ||
5042 | module_init(ahc_linux_init); | 5303 | module_init(ahc_linux_init); |