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>

authored by and committed by James Bottomley 92d161c3 7aaef27b

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