aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx
diff options
context:
space:
mode:
author <jejb@titanic.il.steeleye.com>2005-04-17 19:03:20 -0400
committerJames Bottomley <jejb@titanic>2005-04-18 14:52:27 -0400
commitcb624029cab62e5415287d15b2ec907b8f322ff5 (patch)
tree9ab51220f3ad2a63632b69c5d3662f2c9a771a09 /drivers/scsi/aic7xxx
parent92d161c373b45be158b73a162bedebb5293a73d3 (diff)
aic7xxx: convert to SPI transport class Domain Validation
Now that we export all the parameters, this is easy to do. It also means that we can dump about 2000 lines of code that were dedicated to doing this internally. Additionally, this removes all the aic7xxx driver abuse of SCSI timers which were embedded in the DV routines. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c1681
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h40
2 files changed, 10 insertions, 1711 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 6b6ee0a52a46..d74b99dab7ec 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -275,39 +275,6 @@ static adapter_tag_info_t aic7xxx_tag_info[] =
275}; 275};
276 276
277/* 277/*
278 * DV option:
279 *
280 * positive value = DV Enabled
281 * zero = DV Disabled
282 * negative value = DV Default for adapter type/seeprom
283 */
284#ifdef CONFIG_AIC7XXX_DV_SETTING
285#define AIC7XXX_CONFIGED_DV CONFIG_AIC7XXX_DV_SETTING
286#else
287#define AIC7XXX_CONFIGED_DV -1
288#endif
289
290static int8_t aic7xxx_dv_settings[] =
291{
292 AIC7XXX_CONFIGED_DV,
293 AIC7XXX_CONFIGED_DV,
294 AIC7XXX_CONFIGED_DV,
295 AIC7XXX_CONFIGED_DV,
296 AIC7XXX_CONFIGED_DV,
297 AIC7XXX_CONFIGED_DV,
298 AIC7XXX_CONFIGED_DV,
299 AIC7XXX_CONFIGED_DV,
300 AIC7XXX_CONFIGED_DV,
301 AIC7XXX_CONFIGED_DV,
302 AIC7XXX_CONFIGED_DV,
303 AIC7XXX_CONFIGED_DV,
304 AIC7XXX_CONFIGED_DV,
305 AIC7XXX_CONFIGED_DV,
306 AIC7XXX_CONFIGED_DV,
307 AIC7XXX_CONFIGED_DV
308};
309
310/*
311 * There should be a specific return value for this in scsi.h, but 278 * There should be a specific return value for this in scsi.h, but
312 * it seems that most drivers ignore it. 279 * it seems that most drivers ignore it.
313 */ 280 */
@@ -454,7 +421,6 @@ MODULE_PARM_DESC(aic7xxx,
454" tag_info:<tag_str> Set per-target tag depth\n" 421" tag_info:<tag_str> Set per-target tag depth\n"
455" global_tag_depth:<int> Global tag depth for every target\n" 422" global_tag_depth:<int> Global tag depth for every target\n"
456" on every bus\n" 423" on every bus\n"
457" dv:<dv_settings> Set per-controller Domain Validation Setting.\n"
458" seltime:<int> Selection Timeout\n" 424" seltime:<int> Selection Timeout\n"
459" (0/256ms,1/128ms,2/64ms,3/32ms)\n" 425" (0/256ms,1/128ms,2/64ms,3/32ms)\n"
460"\n" 426"\n"
@@ -471,7 +437,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *,
471 struct scb *); 437 struct scb *);
472static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, 438static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
473 Scsi_Cmnd *cmd); 439 Scsi_Cmnd *cmd);
474static void ahc_linux_filter_inquiry(struct ahc_softc*, struct ahc_devinfo*);
475static void ahc_linux_sem_timeout(u_long arg); 440static void ahc_linux_sem_timeout(u_long arg);
476static void ahc_linux_freeze_simq(struct ahc_softc *ahc); 441static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
477static void ahc_linux_release_simq(u_long arg); 442static void ahc_linux_release_simq(u_long arg);
@@ -480,49 +445,8 @@ static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
480static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); 445static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
481static void ahc_linux_size_nseg(void); 446static void ahc_linux_size_nseg(void);
482static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); 447static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
483static void ahc_linux_start_dv(struct ahc_softc *ahc);
484static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd);
485static int ahc_linux_dv_thread(void *data);
486static void ahc_linux_kill_dv_thread(struct ahc_softc *ahc);
487static void ahc_linux_dv_target(struct ahc_softc *ahc, u_int target);
488static void ahc_linux_dv_transition(struct ahc_softc *ahc,
489 struct scsi_cmnd *cmd,
490 struct ahc_devinfo *devinfo,
491 struct ahc_linux_target *targ);
492static void ahc_linux_dv_fill_cmd(struct ahc_softc *ahc,
493 struct scsi_cmnd *cmd,
494 struct ahc_devinfo *devinfo);
495static void ahc_linux_dv_inq(struct ahc_softc *ahc,
496 struct scsi_cmnd *cmd,
497 struct ahc_devinfo *devinfo,
498 struct ahc_linux_target *targ,
499 u_int request_length);
500static void ahc_linux_dv_tur(struct ahc_softc *ahc,
501 struct scsi_cmnd *cmd,
502 struct ahc_devinfo *devinfo);
503static void ahc_linux_dv_rebd(struct ahc_softc *ahc,
504 struct scsi_cmnd *cmd,
505 struct ahc_devinfo *devinfo,
506 struct ahc_linux_target *targ);
507static void ahc_linux_dv_web(struct ahc_softc *ahc,
508 struct scsi_cmnd *cmd,
509 struct ahc_devinfo *devinfo,
510 struct ahc_linux_target *targ);
511static void ahc_linux_dv_reb(struct ahc_softc *ahc,
512 struct scsi_cmnd *cmd,
513 struct ahc_devinfo *devinfo,
514 struct ahc_linux_target *targ);
515static void ahc_linux_dv_su(struct ahc_softc *ahc,
516 struct scsi_cmnd *cmd,
517 struct ahc_devinfo *devinfo,
518 struct ahc_linux_target *targ);
519static int ahc_linux_fallback(struct ahc_softc *ahc,
520 struct ahc_devinfo *devinfo);
521static void ahc_linux_dv_complete(Scsi_Cmnd *cmd);
522static void ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ);
523static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc, 448static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
524 struct ahc_devinfo *devinfo); 449 struct ahc_devinfo *devinfo);
525static u_int ahc_linux_user_dv_setting(struct ahc_softc *ahc);
526static void ahc_linux_device_queue_depth(struct ahc_softc *ahc, 450static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
527 struct ahc_linux_device *dev); 451 struct ahc_linux_device *dev);
528static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*, 452static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*,
@@ -538,7 +462,6 @@ static void ahc_linux_run_device_queue(struct ahc_softc*,
538 struct ahc_linux_device*); 462 struct ahc_linux_device*);
539static void ahc_linux_setup_tag_info_global(char *p); 463static void ahc_linux_setup_tag_info_global(char *p);
540static aic_option_callback_t ahc_linux_setup_tag_info; 464static aic_option_callback_t ahc_linux_setup_tag_info;
541static aic_option_callback_t ahc_linux_setup_dv;
542static int aic7xxx_setup(char *s); 465static int aic7xxx_setup(char *s);
543static int ahc_linux_next_unit(void); 466static int ahc_linux_next_unit(void);
544static void ahc_runq_tasklet(unsigned long data); 467static void ahc_runq_tasklet(unsigned long data);
@@ -667,8 +590,7 @@ ahc_linux_next_device_to_run(struct ahc_softc *ahc)
667{ 590{
668 591
669 if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 592 if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
670 || (ahc->platform_data->qfrozen != 0 593 || (ahc->platform_data->qfrozen != 0))
671 && AHC_DV_SIMQ_FROZEN(ahc) == 0))
672 return (NULL); 594 return (NULL);
673 return (TAILQ_FIRST(&ahc->platform_data->device_runq)); 595 return (TAILQ_FIRST(&ahc->platform_data->device_runq));
674} 596}
@@ -966,8 +888,7 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
966 * DV commands through so long as we are only frozen to 888 * DV commands through so long as we are only frozen to
967 * perform DV. 889 * perform DV.
968 */ 890 */
969 if (ahc->platform_data->qfrozen != 0 891 if (ahc->platform_data->qfrozen != 0) {
970 && AHC_DV_CMD(cmd) == 0) {
971 892
972 ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); 893 ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
973 ahc_linux_queue_cmd_complete(ahc, cmd); 894 ahc_linux_queue_cmd_complete(ahc, cmd);
@@ -1034,6 +955,11 @@ ahc_linux_slave_configure(Scsi_Device *device)
1034 ahc_linux_device_queue_depth(ahc, dev); 955 ahc_linux_device_queue_depth(ahc, dev);
1035 } 956 }
1036 ahc_midlayer_entrypoint_unlock(ahc, &flags); 957 ahc_midlayer_entrypoint_unlock(ahc, &flags);
958
959 /* Initial Domain Validation */
960 if (!spi_initial_dv(device->sdev_target))
961 spi_dv_device(device);
962
1037 return (0); 963 return (0);
1038} 964}
1039 965
@@ -1549,18 +1475,6 @@ ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
1549 } 1475 }
1550} 1476}
1551 1477
1552static void
1553ahc_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
1554{
1555
1556 if ((instance >= 0)
1557 && (instance < NUM_ELEMENTS(aic7xxx_dv_settings))) {
1558 aic7xxx_dv_settings[instance] = value;
1559 if (bootverbose)
1560 printf("dv[%d] = %d\n", instance, value);
1561 }
1562}
1563
1564/* 1478/*
1565 * Handle Linux boot parameters. This routine allows for assigning a value 1479 * Handle Linux boot parameters. This routine allows for assigning a value
1566 * to a parameter with a ':' between the parameter and the value. 1480 * to a parameter with a ':' between the parameter and the value.
@@ -1620,9 +1534,6 @@ aic7xxx_setup(char *s)
1620 } else if (strncmp(p, "tag_info", n) == 0) { 1534 } else if (strncmp(p, "tag_info", n) == 0) {
1621 s = aic_parse_brace_option("tag_info", p + n, end, 1535 s = aic_parse_brace_option("tag_info", p + n, end,
1622 2, ahc_linux_setup_tag_info, 0); 1536 2, ahc_linux_setup_tag_info, 0);
1623 } else if (strncmp(p, "dv", n) == 0) {
1624 s = aic_parse_brace_option("dv", p + n, end, 1,
1625 ahc_linux_setup_dv, 0);
1626 } else if (p[n] == ':') { 1537 } else if (p[n] == ':') {
1627 *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); 1538 *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
1628 } else if (strncmp(p, "verbose", n) == 0) { 1539 } else if (strncmp(p, "verbose", n) == 0) {
@@ -1645,7 +1556,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
1645 struct Scsi_Host *host; 1556 struct Scsi_Host *host;
1646 char *new_name; 1557 char *new_name;
1647 u_long s; 1558 u_long s;
1648 u_int targ_offset;
1649 1559
1650 template->name = ahc->description; 1560 template->name = ahc->description;
1651 host = scsi_host_alloc(template, sizeof(struct ahc_softc *)); 1561 host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
@@ -1681,55 +1591,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
1681 scsi_set_pci_device(host, ahc->dev_softc); 1591 scsi_set_pci_device(host, ahc->dev_softc);
1682#endif 1592#endif
1683 ahc_linux_initialize_scsi_bus(ahc); 1593 ahc_linux_initialize_scsi_bus(ahc);
1684 ahc_unlock(ahc, &s);
1685 ahc->platform_data->dv_pid = kernel_thread(ahc_linux_dv_thread, ahc, 0);
1686 ahc_lock(ahc, &s);
1687 if (ahc->platform_data->dv_pid < 0) {
1688 printf("%s: Failed to create DV thread, error= %d\n",
1689 ahc_name(ahc), ahc->platform_data->dv_pid);
1690 return (-ahc->platform_data->dv_pid);
1691 }
1692 /*
1693 * Initially allocate *all* of our linux target objects
1694 * so that the DV thread will scan them all in parallel
1695 * just after driver initialization. Any device that
1696 * does not exist will have its target object destroyed
1697 * by the selection timeout handler. In the case of a
1698 * device that appears after the initial DV scan, async
1699 * negotiation will occur for the first command, and DV
1700 * will comence should that first command be successful.
1701 */
1702 for (targ_offset = 0;
1703 targ_offset < host->max_id * (host->max_channel + 1);
1704 targ_offset++) {
1705 u_int channel;
1706 u_int target;
1707
1708 channel = 0;
1709 target = targ_offset;
1710 if (target > 7
1711 && (ahc->features & AHC_TWIN) != 0) {
1712 channel = 1;
1713 target &= 0x7;
1714 }
1715 /*
1716 * Skip our own ID. Some Compaq/HP storage devices
1717 * have enclosure management devices that respond to
1718 * single bit selection (i.e. selecting ourselves).
1719 * It is expected that either an external application
1720 * or a modified kernel will be used to probe this
1721 * ID if it is appropriate. To accommodate these
1722 * installations, ahc_linux_alloc_target() will allocate
1723 * for our ID if asked to do so.
1724 */
1725 if ((channel == 0 && target == ahc->our_id)
1726 || (channel == 1 && target == ahc->our_id_b))
1727 continue;
1728
1729 ahc_linux_alloc_target(ahc, channel, target);
1730 }
1731 ahc_intr_enable(ahc, TRUE); 1594 ahc_intr_enable(ahc, TRUE);
1732 ahc_linux_start_dv(ahc);
1733 ahc_unlock(ahc, &s); 1595 ahc_unlock(ahc, &s);
1734 1596
1735 host->transportt = ahc_linux_transport_template; 1597 host->transportt = ahc_linux_transport_template;
@@ -1866,8 +1728,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
1866 ahc->platform_data->completeq_timer.function = 1728 ahc->platform_data->completeq_timer.function =
1867 (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue; 1729 (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
1868 init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); 1730 init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
1869 init_MUTEX_LOCKED(&ahc->platform_data->dv_sem);
1870 init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem);
1871 tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet, 1731 tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
1872 (unsigned long)ahc); 1732 (unsigned long)ahc);
1873 ahc->seltime = (aic7xxx_seltime & 0x3) << 4; 1733 ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
@@ -1887,7 +1747,6 @@ ahc_platform_free(struct ahc_softc *ahc)
1887 1747
1888 if (ahc->platform_data != NULL) { 1748 if (ahc->platform_data != NULL) {
1889 del_timer_sync(&ahc->platform_data->completeq_timer); 1749 del_timer_sync(&ahc->platform_data->completeq_timer);
1890 ahc_linux_kill_dv_thread(ahc);
1891 tasklet_kill(&ahc->platform_data->runq_tasklet); 1750 tasklet_kill(&ahc->platform_data->runq_tasklet);
1892 if (ahc->platform_data->host != NULL) { 1751 if (ahc->platform_data->host != NULL) {
1893#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1752#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -2126,1331 +1985,6 @@ ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
2126 ahc_unlock(ahc, &flags); 1985 ahc_unlock(ahc, &flags);
2127} 1986}
2128 1987
2129static void
2130ahc_linux_start_dv(struct ahc_softc *ahc)
2131{
2132
2133 /*
2134 * Freeze the simq and signal ahc_linux_queue to not let any
2135 * more commands through.
2136 */
2137 if ((ahc->platform_data->flags & AHC_DV_ACTIVE) == 0) {
2138#ifdef AHC_DEBUG
2139 if (ahc_debug & AHC_SHOW_DV)
2140 printf("%s: Waking DV thread\n", ahc_name(ahc));
2141#endif
2142
2143 ahc->platform_data->flags |= AHC_DV_ACTIVE;
2144 ahc_linux_freeze_simq(ahc);
2145
2146 /* Wake up the DV kthread */
2147 up(&ahc->platform_data->dv_sem);
2148 }
2149}
2150
2151static void
2152ahc_linux_kill_dv_thread(struct ahc_softc *ahc)
2153{
2154 u_long s;
2155
2156 ahc_lock(ahc, &s);
2157 if (ahc->platform_data->dv_pid != 0) {
2158 ahc->platform_data->flags |= AHC_DV_SHUTDOWN;
2159 ahc_unlock(ahc, &s);
2160 up(&ahc->platform_data->dv_sem);
2161
2162 /*
2163 * Use the eh_sem as an indicator that the
2164 * dv thread is exiting. Note that the dv
2165 * thread must still return after performing
2166 * the up on our semaphore before it has
2167 * completely exited this module. Unfortunately,
2168 * there seems to be no easy way to wait for the
2169 * exit of a thread for which you are not the
2170 * parent (dv threads are parented by init).
2171 * Cross your fingers...
2172 */
2173 down(&ahc->platform_data->eh_sem);
2174
2175 /*
2176 * Mark the dv thread as already dead. This
2177 * avoids attempting to kill it a second time.
2178 * This is necessary because we must kill the
2179 * DV thread before calling ahc_free() in the
2180 * module shutdown case to avoid bogus locking
2181 * in the SCSI mid-layer, but we ahc_free() is
2182 * called without killing the DV thread in the
2183 * instance detach case, so ahc_platform_free()
2184 * calls us again to verify that the DV thread
2185 * is dead.
2186 */
2187 ahc->platform_data->dv_pid = 0;
2188 } else {
2189 ahc_unlock(ahc, &s);
2190 }
2191}
2192
2193static int
2194ahc_linux_dv_thread(void *data)
2195{
2196 struct ahc_softc *ahc;
2197 int target;
2198 u_long s;
2199
2200 ahc = (struct ahc_softc *)data;
2201
2202#ifdef AHC_DEBUG
2203 if (ahc_debug & AHC_SHOW_DV)
2204 printf("Launching DV Thread\n");
2205#endif
2206
2207 /*
2208 * Complete thread creation.
2209 */
2210 lock_kernel();
2211#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2212 /*
2213 * Don't care about any signals.
2214 */
2215 siginitsetinv(&current->blocked, 0);
2216
2217 daemonize();
2218 sprintf(current->comm, "ahc_dv_%d", ahc->unit);
2219#else
2220 daemonize("ahc_dv_%d", ahc->unit);
2221 current->flags |= PF_FREEZE;
2222#endif
2223 unlock_kernel();
2224
2225 while (1) {
2226 /*
2227 * Use down_interruptible() rather than down() to
2228 * avoid inclusion in the load average.
2229 */
2230 down_interruptible(&ahc->platform_data->dv_sem);
2231
2232 /* Check to see if we've been signaled to exit */
2233 ahc_lock(ahc, &s);
2234 if ((ahc->platform_data->flags & AHC_DV_SHUTDOWN) != 0) {
2235 ahc_unlock(ahc, &s);
2236 break;
2237 }
2238 ahc_unlock(ahc, &s);
2239
2240#ifdef AHC_DEBUG
2241 if (ahc_debug & AHC_SHOW_DV)
2242 printf("%s: Beginning Domain Validation\n",
2243 ahc_name(ahc));
2244#endif
2245
2246 /*
2247 * Wait for any pending commands to drain before proceeding.
2248 */
2249 ahc_lock(ahc, &s);
2250 while (LIST_FIRST(&ahc->pending_scbs) != NULL) {
2251 ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY;
2252 ahc_unlock(ahc, &s);
2253 down_interruptible(&ahc->platform_data->dv_sem);
2254 ahc_lock(ahc, &s);
2255 }
2256
2257 /*
2258 * Wait for the SIMQ to be released so that DV is the
2259 * only reason the queue is frozen.
2260 */
2261 while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
2262 ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
2263 ahc_unlock(ahc, &s);
2264 down_interruptible(&ahc->platform_data->dv_sem);
2265 ahc_lock(ahc, &s);
2266 }
2267 ahc_unlock(ahc, &s);
2268
2269 for (target = 0; target < AHC_NUM_TARGETS; target++)
2270 ahc_linux_dv_target(ahc, target);
2271
2272 ahc_lock(ahc, &s);
2273 ahc->platform_data->flags &= ~AHC_DV_ACTIVE;
2274 ahc_unlock(ahc, &s);
2275
2276 /*
2277 * Release the SIMQ so that normal commands are
2278 * allowed to continue on the bus.
2279 */
2280 ahc_linux_release_simq((u_long)ahc);
2281 }
2282 up(&ahc->platform_data->eh_sem);
2283 return (0);
2284}
2285
2286#define AHC_LINUX_DV_INQ_SHORT_LEN 36
2287#define AHC_LINUX_DV_INQ_LEN 256
2288#define AHC_LINUX_DV_TIMEOUT (HZ / 4)
2289
2290#define AHC_SET_DV_STATE(ahc, targ, newstate) \
2291 ahc_set_dv_state(ahc, targ, newstate, __LINE__)
2292
2293static __inline void
2294ahc_set_dv_state(struct ahc_softc *ahc, struct ahc_linux_target *targ,
2295 ahc_dv_state newstate, u_int line)
2296{
2297 ahc_dv_state oldstate;
2298
2299 oldstate = targ->dv_state;
2300#ifdef AHC_DEBUG
2301 if (ahc_debug & AHC_SHOW_DV)
2302 printf("%s:%d: Going from state %d to state %d\n",
2303 ahc_name(ahc), line, oldstate, newstate);
2304#endif
2305
2306 if (oldstate == newstate)
2307 targ->dv_state_retry++;
2308 else
2309 targ->dv_state_retry = 0;
2310 targ->dv_state = newstate;
2311}
2312
2313static void
2314ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
2315{
2316 struct ahc_devinfo devinfo;
2317 struct ahc_linux_target *targ;
2318 struct scsi_cmnd *cmd;
2319 struct scsi_device *scsi_dev;
2320 struct scsi_sense_data *sense;
2321 uint8_t *buffer;
2322 u_long s;
2323 u_int timeout;
2324 int echo_size;
2325
2326 sense = NULL;
2327 buffer = NULL;
2328 echo_size = 0;
2329 ahc_lock(ahc, &s);
2330 targ = ahc->platform_data->targets[target_offset];
2331 if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) {
2332 ahc_unlock(ahc, &s);
2333 return;
2334 }
2335 ahc_compile_devinfo(&devinfo,
2336 targ->channel == 0 ? ahc->our_id : ahc->our_id_b,
2337 targ->target, /*lun*/0, targ->channel + 'A',
2338 ROLE_INITIATOR);
2339#ifdef AHC_DEBUG
2340 if (ahc_debug & AHC_SHOW_DV) {
2341 ahc_print_devinfo(ahc, &devinfo);
2342 printf("Performing DV\n");
2343 }
2344#endif
2345
2346 ahc_unlock(ahc, &s);
2347
2348 cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
2349 scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK);
2350 scsi_dev->host = ahc->platform_data->host;
2351 scsi_dev->id = devinfo.target;
2352 scsi_dev->lun = devinfo.lun;
2353 scsi_dev->channel = devinfo.channel - 'A';
2354 ahc->platform_data->dv_scsi_dev = scsi_dev;
2355
2356 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_SHORT_ASYNC);
2357
2358 while (targ->dv_state != AHC_DV_STATE_EXIT) {
2359 timeout = AHC_LINUX_DV_TIMEOUT;
2360 switch (targ->dv_state) {
2361 case AHC_DV_STATE_INQ_SHORT_ASYNC:
2362 case AHC_DV_STATE_INQ_ASYNC:
2363 case AHC_DV_STATE_INQ_ASYNC_VERIFY:
2364 /*
2365 * Set things to async narrow to reduce the
2366 * chance that the INQ will fail.
2367 */
2368 ahc_lock(ahc, &s);
2369 ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
2370 AHC_TRANS_GOAL, /*paused*/FALSE);
2371 ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
2372 AHC_TRANS_GOAL, /*paused*/FALSE);
2373 ahc_unlock(ahc, &s);
2374 timeout = 10 * HZ;
2375 targ->flags &= ~AHC_INQ_VALID;
2376 /* FALLTHROUGH */
2377 case AHC_DV_STATE_INQ_VERIFY:
2378 {
2379 u_int inq_len;
2380
2381 if (targ->dv_state == AHC_DV_STATE_INQ_SHORT_ASYNC)
2382 inq_len = AHC_LINUX_DV_INQ_SHORT_LEN;
2383 else
2384 inq_len = targ->inq_data->additional_length + 5;
2385 ahc_linux_dv_inq(ahc, cmd, &devinfo, targ, inq_len);
2386 break;
2387 }
2388 case AHC_DV_STATE_TUR:
2389 case AHC_DV_STATE_BUSY:
2390 timeout = 5 * HZ;
2391 ahc_linux_dv_tur(ahc, cmd, &devinfo);
2392 break;
2393 case AHC_DV_STATE_REBD:
2394 ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ);
2395 break;
2396 case AHC_DV_STATE_WEB:
2397 ahc_linux_dv_web(ahc, cmd, &devinfo, targ);
2398 break;
2399
2400 case AHC_DV_STATE_REB:
2401 ahc_linux_dv_reb(ahc, cmd, &devinfo, targ);
2402 break;
2403
2404 case AHC_DV_STATE_SU:
2405 ahc_linux_dv_su(ahc, cmd, &devinfo, targ);
2406 timeout = 50 * HZ;
2407 break;
2408
2409 default:
2410 ahc_print_devinfo(ahc, &devinfo);
2411 printf("Unknown DV state %d\n", targ->dv_state);
2412 goto out;
2413 }
2414
2415 /* Queue the command and wait for it to complete */
2416 /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
2417 init_timer(&cmd->eh_timeout);
2418#ifdef AHC_DEBUG
2419 if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
2420 /*
2421 * All of the printfs during negotiation
2422 * really slow down the negotiation.
2423 * Add a bit of time just to be safe.
2424 */
2425 timeout += HZ;
2426#endif
2427 scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout);
2428 /*
2429 * In 2.5.X, it is assumed that all calls from the
2430 * "midlayer" (which we are emulating) will have the
2431 * ahc host lock held. For other kernels, the
2432 * io_request_lock must be held.
2433 */
2434#if AHC_SCSI_HAS_HOST_LOCK != 0
2435 ahc_lock(ahc, &s);
2436#else
2437 spin_lock_irqsave(&io_request_lock, s);
2438#endif
2439 ahc_linux_queue(cmd, ahc_linux_dv_complete);
2440#if AHC_SCSI_HAS_HOST_LOCK != 0
2441 ahc_unlock(ahc, &s);
2442#else
2443 spin_unlock_irqrestore(&io_request_lock, s);
2444#endif
2445 down_interruptible(&ahc->platform_data->dv_cmd_sem);
2446 /*
2447 * Wait for the SIMQ to be released so that DV is the
2448 * only reason the queue is frozen.
2449 */
2450 ahc_lock(ahc, &s);
2451 while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
2452 ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
2453 ahc_unlock(ahc, &s);
2454 down_interruptible(&ahc->platform_data->dv_sem);
2455 ahc_lock(ahc, &s);
2456 }
2457 ahc_unlock(ahc, &s);
2458
2459 ahc_linux_dv_transition(ahc, cmd, &devinfo, targ);
2460 }
2461
2462out:
2463 if ((targ->flags & AHC_INQ_VALID) != 0
2464 && ahc_linux_get_device(ahc, devinfo.channel - 'A',
2465 devinfo.target, devinfo.lun,
2466 /*alloc*/FALSE) == NULL) {
2467 /*
2468 * The DV state machine failed to configure this device.
2469 * This is normal if DV is disabled. Since we have inquiry
2470 * data, filter it and use the "optimistic" negotiation
2471 * parameters found in the inquiry string.
2472 */
2473 ahc_linux_filter_inquiry(ahc, &devinfo);
2474 if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) {
2475 ahc_print_devinfo(ahc, &devinfo);
2476 printf("DV failed to configure device. "
2477 "Please file a bug report against "
2478 "this driver.\n");
2479 }
2480 }
2481
2482 if (cmd != NULL)
2483 free(cmd, M_DEVBUF);
2484
2485 if (ahc->platform_data->dv_scsi_dev != NULL) {
2486 free(ahc->platform_data->dv_scsi_dev, M_DEVBUF);
2487 ahc->platform_data->dv_scsi_dev = NULL;
2488 }
2489
2490 ahc_lock(ahc, &s);
2491 if (targ->dv_buffer != NULL) {
2492 free(targ->dv_buffer, M_DEVBUF);
2493 targ->dv_buffer = NULL;
2494 }
2495 if (targ->dv_buffer1 != NULL) {
2496 free(targ->dv_buffer1, M_DEVBUF);
2497 targ->dv_buffer1 = NULL;
2498 }
2499 targ->flags &= ~AHC_DV_REQUIRED;
2500 if (targ->refcount == 0)
2501 ahc_linux_free_target(ahc, targ);
2502 ahc_unlock(ahc, &s);
2503}
2504
2505static void
2506ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
2507 struct ahc_devinfo *devinfo,
2508 struct ahc_linux_target *targ)
2509{
2510 u_int32_t status;
2511
2512 status = aic_error_action(cmd, targ->inq_data,
2513 ahc_cmd_get_transaction_status(cmd),
2514 ahc_cmd_get_scsi_status(cmd));
2515
2516#ifdef AHC_DEBUG
2517 if (ahc_debug & AHC_SHOW_DV) {
2518 ahc_print_devinfo(ahc, devinfo);
2519 printf("Entering ahc_linux_dv_transition, state= %d, "
2520 "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
2521 status, cmd->result);
2522 }
2523#endif
2524
2525 switch (targ->dv_state) {
2526 case AHC_DV_STATE_INQ_SHORT_ASYNC:
2527 case AHC_DV_STATE_INQ_ASYNC:
2528 switch (status & SS_MASK) {
2529 case SS_NOP:
2530 {
2531 AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1);
2532 break;
2533 }
2534 case SS_INQ_REFRESH:
2535 AHC_SET_DV_STATE(ahc, targ,
2536 AHC_DV_STATE_INQ_SHORT_ASYNC);
2537 break;
2538 case SS_TUR:
2539 case SS_RETRY:
2540 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2541 if (ahc_cmd_get_transaction_status(cmd)
2542 == CAM_REQUEUE_REQ)
2543 targ->dv_state_retry--;
2544 if ((status & SS_ERRMASK) == EBUSY)
2545 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
2546 if (targ->dv_state_retry < 10)
2547 break;
2548 /* FALLTHROUGH */
2549 default:
2550 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2551#ifdef AHC_DEBUG
2552 if (ahc_debug & AHC_SHOW_DV) {
2553 ahc_print_devinfo(ahc, devinfo);
2554 printf("Failed DV inquiry, skipping\n");
2555 }
2556#endif
2557 break;
2558 }
2559 break;
2560 case AHC_DV_STATE_INQ_ASYNC_VERIFY:
2561 switch (status & SS_MASK) {
2562 case SS_NOP:
2563 {
2564 u_int xportflags;
2565 u_int spi3data;
2566
2567 if (memcmp(targ->inq_data, targ->dv_buffer,
2568 AHC_LINUX_DV_INQ_LEN) != 0) {
2569 /*
2570 * Inquiry data must have changed.
2571 * Try from the top again.
2572 */
2573 AHC_SET_DV_STATE(ahc, targ,
2574 AHC_DV_STATE_INQ_SHORT_ASYNC);
2575 break;
2576 }
2577
2578 AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1);
2579 targ->flags |= AHC_INQ_VALID;
2580 if (ahc_linux_user_dv_setting(ahc) == 0)
2581 break;
2582
2583 xportflags = targ->inq_data->flags;
2584 if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
2585 break;
2586
2587 spi3data = targ->inq_data->spi3data;
2588 switch (spi3data & SID_SPI_CLOCK_DT_ST) {
2589 default:
2590 case SID_SPI_CLOCK_ST:
2591 /* Assume only basic DV is supported. */
2592 targ->flags |= AHC_BASIC_DV;
2593 break;
2594 case SID_SPI_CLOCK_DT:
2595 case SID_SPI_CLOCK_DT_ST:
2596 targ->flags |= AHC_ENHANCED_DV;
2597 break;
2598 }
2599 break;
2600 }
2601 case SS_INQ_REFRESH:
2602 AHC_SET_DV_STATE(ahc, targ,
2603 AHC_DV_STATE_INQ_SHORT_ASYNC);
2604 break;
2605 case SS_TUR:
2606 case SS_RETRY:
2607 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2608 if (ahc_cmd_get_transaction_status(cmd)
2609 == CAM_REQUEUE_REQ)
2610 targ->dv_state_retry--;
2611
2612 if ((status & SS_ERRMASK) == EBUSY)
2613 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
2614 if (targ->dv_state_retry < 10)
2615 break;
2616 /* FALLTHROUGH */
2617 default:
2618 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2619#ifdef AHC_DEBUG
2620 if (ahc_debug & AHC_SHOW_DV) {
2621 ahc_print_devinfo(ahc, devinfo);
2622 printf("Failed DV inquiry, skipping\n");
2623 }
2624#endif
2625 break;
2626 }
2627 break;
2628 case AHC_DV_STATE_INQ_VERIFY:
2629 switch (status & SS_MASK) {
2630 case SS_NOP:
2631 {
2632
2633 if (memcmp(targ->inq_data, targ->dv_buffer,
2634 AHC_LINUX_DV_INQ_LEN) == 0) {
2635 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2636 break;
2637 }
2638#ifdef AHC_DEBUG
2639 if (ahc_debug & AHC_SHOW_DV) {
2640 int i;
2641
2642 ahc_print_devinfo(ahc, devinfo);
2643 printf("Inquiry buffer mismatch:");
2644 for (i = 0; i < AHC_LINUX_DV_INQ_LEN; i++) {
2645 if ((i & 0xF) == 0)
2646 printf("\n ");
2647 printf("0x%x:0x0%x ",
2648 ((uint8_t *)targ->inq_data)[i],
2649 targ->dv_buffer[i]);
2650 }
2651 printf("\n");
2652 }
2653#endif
2654
2655 if (ahc_linux_fallback(ahc, devinfo) != 0) {
2656 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2657 break;
2658 }
2659 /*
2660 * Do not count "falling back"
2661 * against our retries.
2662 */
2663 targ->dv_state_retry = 0;
2664 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2665 break;
2666 }
2667 case SS_INQ_REFRESH:
2668 AHC_SET_DV_STATE(ahc, targ,
2669 AHC_DV_STATE_INQ_SHORT_ASYNC);
2670 break;
2671 case SS_TUR:
2672 case SS_RETRY:
2673 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2674 if (ahc_cmd_get_transaction_status(cmd)
2675 == CAM_REQUEUE_REQ) {
2676 targ->dv_state_retry--;
2677 } else if ((status & SSQ_FALLBACK) != 0) {
2678 if (ahc_linux_fallback(ahc, devinfo) != 0) {
2679 AHC_SET_DV_STATE(ahc, targ,
2680 AHC_DV_STATE_EXIT);
2681 break;
2682 }
2683 /*
2684 * Do not count "falling back"
2685 * against our retries.
2686 */
2687 targ->dv_state_retry = 0;
2688 } else if ((status & SS_ERRMASK) == EBUSY)
2689 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
2690 if (targ->dv_state_retry < 10)
2691 break;
2692 /* FALLTHROUGH */
2693 default:
2694 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2695#ifdef AHC_DEBUG
2696 if (ahc_debug & AHC_SHOW_DV) {
2697 ahc_print_devinfo(ahc, devinfo);
2698 printf("Failed DV inquiry, skipping\n");
2699 }
2700#endif
2701 break;
2702 }
2703 break;
2704
2705 case AHC_DV_STATE_TUR:
2706 switch (status & SS_MASK) {
2707 case SS_NOP:
2708 if ((targ->flags & AHC_BASIC_DV) != 0) {
2709 ahc_linux_filter_inquiry(ahc, devinfo);
2710 AHC_SET_DV_STATE(ahc, targ,
2711 AHC_DV_STATE_INQ_VERIFY);
2712 } else if ((targ->flags & AHC_ENHANCED_DV) != 0) {
2713 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD);
2714 } else {
2715 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2716 }
2717 break;
2718 case SS_RETRY:
2719 case SS_TUR:
2720 if ((status & SS_ERRMASK) == EBUSY) {
2721 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
2722 break;
2723 }
2724 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2725 if (ahc_cmd_get_transaction_status(cmd)
2726 == CAM_REQUEUE_REQ) {
2727 targ->dv_state_retry--;
2728 } else if ((status & SSQ_FALLBACK) != 0) {
2729 if (ahc_linux_fallback(ahc, devinfo) != 0) {
2730 AHC_SET_DV_STATE(ahc, targ,
2731 AHC_DV_STATE_EXIT);
2732 break;
2733 }
2734 /*
2735 * Do not count "falling back"
2736 * against our retries.
2737 */
2738 targ->dv_state_retry = 0;
2739 }
2740 if (targ->dv_state_retry >= 10) {
2741#ifdef AHC_DEBUG
2742 if (ahc_debug & AHC_SHOW_DV) {
2743 ahc_print_devinfo(ahc, devinfo);
2744 printf("DV TUR reties exhausted\n");
2745 }
2746#endif
2747 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2748 break;
2749 }
2750 if (status & SSQ_DELAY)
2751 ssleep(1);
2752
2753 break;
2754 case SS_START:
2755 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU);
2756 break;
2757 case SS_INQ_REFRESH:
2758 AHC_SET_DV_STATE(ahc, targ,
2759 AHC_DV_STATE_INQ_SHORT_ASYNC);
2760 break;
2761 default:
2762 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2763 break;
2764 }
2765 break;
2766
2767 case AHC_DV_STATE_REBD:
2768 switch (status & SS_MASK) {
2769 case SS_NOP:
2770 {
2771 uint32_t echo_size;
2772
2773 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB);
2774 echo_size = scsi_3btoul(&targ->dv_buffer[1]);
2775 echo_size &= 0x1FFF;
2776#ifdef AHC_DEBUG
2777 if (ahc_debug & AHC_SHOW_DV) {
2778 ahc_print_devinfo(ahc, devinfo);
2779 printf("Echo buffer size= %d\n", echo_size);
2780 }
2781#endif
2782 if (echo_size == 0) {
2783 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2784 break;
2785 }
2786
2787 /* Generate the buffer pattern */
2788 targ->dv_echo_size = echo_size;
2789 ahc_linux_generate_dv_pattern(targ);
2790 /*
2791 * Setup initial negotiation values.
2792 */
2793 ahc_linux_filter_inquiry(ahc, devinfo);
2794 break;
2795 }
2796 case SS_INQ_REFRESH:
2797 AHC_SET_DV_STATE(ahc, targ,
2798 AHC_DV_STATE_INQ_SHORT_ASYNC);
2799 break;
2800 case SS_RETRY:
2801 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2802 if (ahc_cmd_get_transaction_status(cmd)
2803 == CAM_REQUEUE_REQ)
2804 targ->dv_state_retry--;
2805 if (targ->dv_state_retry <= 10)
2806 break;
2807#ifdef AHC_DEBUG
2808 if (ahc_debug & AHC_SHOW_DV) {
2809 ahc_print_devinfo(ahc, devinfo);
2810 printf("DV REBD reties exhausted\n");
2811 }
2812#endif
2813 /* FALLTHROUGH */
2814 case SS_FATAL:
2815 default:
2816 /*
2817 * Setup initial negotiation values
2818 * and try level 1 DV.
2819 */
2820 ahc_linux_filter_inquiry(ahc, devinfo);
2821 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY);
2822 targ->dv_echo_size = 0;
2823 break;
2824 }
2825 break;
2826
2827 case AHC_DV_STATE_WEB:
2828 switch (status & SS_MASK) {
2829 case SS_NOP:
2830 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB);
2831 break;
2832 case SS_INQ_REFRESH:
2833 AHC_SET_DV_STATE(ahc, targ,
2834 AHC_DV_STATE_INQ_SHORT_ASYNC);
2835 break;
2836 case SS_RETRY:
2837 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2838 if (ahc_cmd_get_transaction_status(cmd)
2839 == CAM_REQUEUE_REQ) {
2840 targ->dv_state_retry--;
2841 } else if ((status & SSQ_FALLBACK) != 0) {
2842 if (ahc_linux_fallback(ahc, devinfo) != 0) {
2843 AHC_SET_DV_STATE(ahc, targ,
2844 AHC_DV_STATE_EXIT);
2845 break;
2846 }
2847 /*
2848 * Do not count "falling back"
2849 * against our retries.
2850 */
2851 targ->dv_state_retry = 0;
2852 }
2853 if (targ->dv_state_retry <= 10)
2854 break;
2855 /* FALLTHROUGH */
2856#ifdef AHC_DEBUG
2857 if (ahc_debug & AHC_SHOW_DV) {
2858 ahc_print_devinfo(ahc, devinfo);
2859 printf("DV WEB reties exhausted\n");
2860 }
2861#endif
2862 default:
2863 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2864 break;
2865 }
2866 break;
2867
2868 case AHC_DV_STATE_REB:
2869 switch (status & SS_MASK) {
2870 case SS_NOP:
2871 if (memcmp(targ->dv_buffer, targ->dv_buffer1,
2872 targ->dv_echo_size) != 0) {
2873 if (ahc_linux_fallback(ahc, devinfo) != 0)
2874 AHC_SET_DV_STATE(ahc, targ,
2875 AHC_DV_STATE_EXIT);
2876 else
2877 AHC_SET_DV_STATE(ahc, targ,
2878 AHC_DV_STATE_WEB);
2879 break;
2880 }
2881
2882 if (targ->dv_buffer != NULL) {
2883 free(targ->dv_buffer, M_DEVBUF);
2884 targ->dv_buffer = NULL;
2885 }
2886 if (targ->dv_buffer1 != NULL) {
2887 free(targ->dv_buffer1, M_DEVBUF);
2888 targ->dv_buffer1 = NULL;
2889 }
2890 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2891 break;
2892 case SS_INQ_REFRESH:
2893 AHC_SET_DV_STATE(ahc, targ,
2894 AHC_DV_STATE_INQ_SHORT_ASYNC);
2895 break;
2896 case SS_RETRY:
2897 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2898 if (ahc_cmd_get_transaction_status(cmd)
2899 == CAM_REQUEUE_REQ) {
2900 targ->dv_state_retry--;
2901 } else if ((status & SSQ_FALLBACK) != 0) {
2902 if (ahc_linux_fallback(ahc, devinfo) != 0) {
2903 AHC_SET_DV_STATE(ahc, targ,
2904 AHC_DV_STATE_EXIT);
2905 break;
2906 }
2907 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB);
2908 }
2909 if (targ->dv_state_retry <= 10) {
2910 if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
2911 msleep(ahc->our_id*1000/10);
2912 break;
2913 }
2914#ifdef AHC_DEBUG
2915 if (ahc_debug & AHC_SHOW_DV) {
2916 ahc_print_devinfo(ahc, devinfo);
2917 printf("DV REB reties exhausted\n");
2918 }
2919#endif
2920 /* FALLTHROUGH */
2921 default:
2922 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2923 break;
2924 }
2925 break;
2926
2927 case AHC_DV_STATE_SU:
2928 switch (status & SS_MASK) {
2929 case SS_NOP:
2930 case SS_INQ_REFRESH:
2931 AHC_SET_DV_STATE(ahc, targ,
2932 AHC_DV_STATE_INQ_SHORT_ASYNC);
2933 break;
2934 default:
2935 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2936 break;
2937 }
2938 break;
2939
2940 case AHC_DV_STATE_BUSY:
2941 switch (status & SS_MASK) {
2942 case SS_NOP:
2943 case SS_INQ_REFRESH:
2944 AHC_SET_DV_STATE(ahc, targ,
2945 AHC_DV_STATE_INQ_SHORT_ASYNC);
2946 break;
2947 case SS_TUR:
2948 case SS_RETRY:
2949 AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
2950 if (ahc_cmd_get_transaction_status(cmd)
2951 == CAM_REQUEUE_REQ) {
2952 targ->dv_state_retry--;
2953 } else if (targ->dv_state_retry < 60) {
2954 if ((status & SSQ_DELAY) != 0)
2955 ssleep(1);
2956 } else {
2957#ifdef AHC_DEBUG
2958 if (ahc_debug & AHC_SHOW_DV) {
2959 ahc_print_devinfo(ahc, devinfo);
2960 printf("DV BUSY reties exhausted\n");
2961 }
2962#endif
2963 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2964 }
2965 break;
2966 default:
2967 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2968 break;
2969 }
2970 break;
2971
2972 default:
2973 printf("%s: Invalid DV completion state %d\n", ahc_name(ahc),
2974 targ->dv_state);
2975 AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
2976 break;
2977 }
2978}
2979
2980static void
2981ahc_linux_dv_fill_cmd(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
2982 struct ahc_devinfo *devinfo)
2983{
2984 memset(cmd, 0, sizeof(struct scsi_cmnd));
2985 cmd->device = ahc->platform_data->dv_scsi_dev;
2986 cmd->scsi_done = ahc_linux_dv_complete;
2987}
2988
2989/*
2990 * Synthesize an inquiry command. On the return trip, it'll be
2991 * sniffed and the device transfer settings set for us.
2992 */
2993static void
2994ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
2995 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ,
2996 u_int request_length)
2997{
2998
2999#ifdef AHC_DEBUG
3000 if (ahc_debug & AHC_SHOW_DV) {
3001 ahc_print_devinfo(ahc, devinfo);
3002 printf("Sending INQ\n");
3003 }
3004#endif
3005 if (targ->inq_data == NULL)
3006 targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN,
3007 M_DEVBUF, M_WAITOK);
3008 if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC) {
3009 if (targ->dv_buffer != NULL)
3010 free(targ->dv_buffer, M_DEVBUF);
3011 targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN,
3012 M_DEVBUF, M_WAITOK);
3013 }
3014
3015 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3016 cmd->sc_data_direction = DMA_FROM_DEVICE;
3017 cmd->cmd_len = 6;
3018 cmd->cmnd[0] = INQUIRY;
3019 cmd->cmnd[4] = request_length;
3020 cmd->request_bufflen = request_length;
3021 if (targ->dv_state > AHC_DV_STATE_INQ_ASYNC)
3022 cmd->request_buffer = targ->dv_buffer;
3023 else
3024 cmd->request_buffer = targ->inq_data;
3025 memset(cmd->request_buffer, 0, AHC_LINUX_DV_INQ_LEN);
3026}
3027
3028static void
3029ahc_linux_dv_tur(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
3030 struct ahc_devinfo *devinfo)
3031{
3032
3033#ifdef AHC_DEBUG
3034 if (ahc_debug & AHC_SHOW_DV) {
3035 ahc_print_devinfo(ahc, devinfo);
3036 printf("Sending TUR\n");
3037 }
3038#endif
3039 /* Do a TUR to clear out any non-fatal transitional state */
3040 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3041 cmd->sc_data_direction = DMA_NONE;
3042 cmd->cmd_len = 6;
3043 cmd->cmnd[0] = TEST_UNIT_READY;
3044}
3045
3046#define AHC_REBD_LEN 4
3047
3048static void
3049ahc_linux_dv_rebd(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
3050 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
3051{
3052
3053#ifdef AHC_DEBUG
3054 if (ahc_debug & AHC_SHOW_DV) {
3055 ahc_print_devinfo(ahc, devinfo);
3056 printf("Sending REBD\n");
3057 }
3058#endif
3059 if (targ->dv_buffer != NULL)
3060 free(targ->dv_buffer, M_DEVBUF);
3061 targ->dv_buffer = malloc(AHC_REBD_LEN, M_DEVBUF, M_WAITOK);
3062 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3063 cmd->sc_data_direction = DMA_FROM_DEVICE;
3064 cmd->cmd_len = 10;
3065 cmd->cmnd[0] = READ_BUFFER;
3066 cmd->cmnd[1] = 0x0b;
3067 scsi_ulto3b(AHC_REBD_LEN, &cmd->cmnd[6]);
3068 cmd->request_bufflen = AHC_REBD_LEN;
3069 cmd->underflow = cmd->request_bufflen;
3070 cmd->request_buffer = targ->dv_buffer;
3071}
3072
3073static void
3074ahc_linux_dv_web(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
3075 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
3076{
3077
3078#ifdef AHC_DEBUG
3079 if (ahc_debug & AHC_SHOW_DV) {
3080 ahc_print_devinfo(ahc, devinfo);
3081 printf("Sending WEB\n");
3082 }
3083#endif
3084 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3085 cmd->sc_data_direction = DMA_TO_DEVICE;
3086 cmd->cmd_len = 10;
3087 cmd->cmnd[0] = WRITE_BUFFER;
3088 cmd->cmnd[1] = 0x0a;
3089 scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
3090 cmd->request_bufflen = targ->dv_echo_size;
3091 cmd->underflow = cmd->request_bufflen;
3092 cmd->request_buffer = targ->dv_buffer;
3093}
3094
3095static void
3096ahc_linux_dv_reb(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
3097 struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
3098{
3099
3100#ifdef AHC_DEBUG
3101 if (ahc_debug & AHC_SHOW_DV) {
3102 ahc_print_devinfo(ahc, devinfo);
3103 printf("Sending REB\n");
3104 }
3105#endif
3106 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3107 cmd->sc_data_direction = DMA_FROM_DEVICE;
3108 cmd->cmd_len = 10;
3109 cmd->cmnd[0] = READ_BUFFER;
3110 cmd->cmnd[1] = 0x0a;
3111 scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
3112 cmd->request_bufflen = targ->dv_echo_size;
3113 cmd->underflow = cmd->request_bufflen;
3114 cmd->request_buffer = targ->dv_buffer1;
3115}
3116
3117static void
3118ahc_linux_dv_su(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
3119 struct ahc_devinfo *devinfo,
3120 struct ahc_linux_target *targ)
3121{
3122 u_int le;
3123
3124 le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
3125
3126#ifdef AHC_DEBUG
3127 if (ahc_debug & AHC_SHOW_DV) {
3128 ahc_print_devinfo(ahc, devinfo);
3129 printf("Sending SU\n");
3130 }
3131#endif
3132 ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
3133 cmd->sc_data_direction = DMA_NONE;
3134 cmd->cmd_len = 6;
3135 cmd->cmnd[0] = START_STOP_UNIT;
3136 cmd->cmnd[4] = le | SSS_START;
3137}
3138
3139static int
3140ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3141{
3142 struct ahc_linux_target *targ;
3143 struct ahc_initiator_tinfo *tinfo;
3144 struct ahc_transinfo *goal;
3145 struct ahc_tmode_tstate *tstate;
3146 struct ahc_syncrate *syncrate;
3147 u_long s;
3148 u_int width;
3149 u_int period;
3150 u_int offset;
3151 u_int ppr_options;
3152 u_int cur_speed;
3153 u_int wide_speed;
3154 u_int narrow_speed;
3155 u_int fallback_speed;
3156
3157#ifdef AHC_DEBUG
3158 if (ahc_debug & AHC_SHOW_DV) {
3159 ahc_print_devinfo(ahc, devinfo);
3160 printf("Trying to fallback\n");
3161 }
3162#endif
3163 ahc_lock(ahc, &s);
3164 targ = ahc->platform_data->targets[devinfo->target_offset];
3165 tinfo = ahc_fetch_transinfo(ahc, devinfo->channel,
3166 devinfo->our_scsiid,
3167 devinfo->target, &tstate);
3168 goal = &tinfo->goal;
3169 width = goal->width;
3170 period = goal->period;
3171 offset = goal->offset;
3172 ppr_options = goal->ppr_options;
3173 if (offset == 0)
3174 period = AHC_ASYNC_XFER_PERIOD;
3175 if (targ->dv_next_narrow_period == 0)
3176 targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2);
3177 if (targ->dv_next_wide_period == 0)
3178 targ->dv_next_wide_period = period;
3179 if (targ->dv_max_width == 0)
3180 targ->dv_max_width = width;
3181 if (targ->dv_max_ppr_options == 0)
3182 targ->dv_max_ppr_options = ppr_options;
3183 if (targ->dv_last_ppr_options == 0)
3184 targ->dv_last_ppr_options = ppr_options;
3185
3186 cur_speed = aic_calc_speed(width, period, offset, AHC_SYNCRATE_MIN);
3187 wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
3188 targ->dv_next_wide_period,
3189 MAX_OFFSET,
3190 AHC_SYNCRATE_MIN);
3191 narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
3192 targ->dv_next_narrow_period,
3193 MAX_OFFSET,
3194 AHC_SYNCRATE_MIN);
3195 fallback_speed = aic_calc_speed(width, period+1, offset,
3196 AHC_SYNCRATE_MIN);
3197#ifdef AHC_DEBUG
3198 if (ahc_debug & AHC_SHOW_DV) {
3199 printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
3200 "fallback_speed= %d\n", cur_speed, wide_speed,
3201 narrow_speed, fallback_speed);
3202 }
3203#endif
3204
3205 if (cur_speed > 160000) {
3206 /*
3207 * Paced/DT/IU_REQ only transfer speeds. All we
3208 * can do is fallback in terms of syncrate.
3209 */
3210 period++;
3211 } else if (cur_speed > 80000) {
3212 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3213 /*
3214 * Try without IU_REQ as it may be confusing
3215 * an expander.
3216 */
3217 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
3218 } else {
3219 /*
3220 * Paced/DT only transfer speeds. All we
3221 * can do is fallback in terms of syncrate.
3222 */
3223 period++;
3224 ppr_options = targ->dv_max_ppr_options;
3225 }
3226 } else if (cur_speed > 3300) {
3227
3228 /*
3229 * In this range we the following
3230 * options ordered from highest to
3231 * lowest desireability:
3232 *
3233 * o Wide/DT
3234 * o Wide/non-DT
3235 * o Narrow at a potentally higher sync rate.
3236 *
3237 * All modes are tested with and without IU_REQ
3238 * set since using IUs may confuse an expander.
3239 */
3240 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3241
3242 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
3243 } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
3244 /*
3245 * Try going non-DT.
3246 */
3247 ppr_options = targ->dv_max_ppr_options;
3248 ppr_options &= ~MSG_EXT_PPR_DT_REQ;
3249 } else if (targ->dv_last_ppr_options != 0) {
3250 /*
3251 * Try without QAS or any other PPR options.
3252 * We may need a non-PPR message to work with
3253 * an expander. We look at the "last PPR options"
3254 * so we will perform this fallback even if the
3255 * target responded to our PPR negotiation with
3256 * no option bits set.
3257 */
3258 ppr_options = 0;
3259 } else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
3260 /*
3261 * If the next narrow speed is greater than
3262 * the next wide speed, fallback to narrow.
3263 * Otherwise fallback to the next DT/Wide setting.
3264 * The narrow async speed will always be smaller
3265 * than the wide async speed, so handle this case
3266 * specifically.
3267 */
3268 ppr_options = targ->dv_max_ppr_options;
3269 if (narrow_speed > fallback_speed
3270 || period >= AHC_ASYNC_XFER_PERIOD) {
3271 targ->dv_next_wide_period = period+1;
3272 width = MSG_EXT_WDTR_BUS_8_BIT;
3273 period = targ->dv_next_narrow_period;
3274 } else {
3275 period++;
3276 }
3277 } else if ((ahc->features & AHC_WIDE) != 0
3278 && targ->dv_max_width != 0
3279 && wide_speed >= fallback_speed
3280 && (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD
3281 || period >= AHC_ASYNC_XFER_PERIOD)) {
3282
3283 /*
3284 * We are narrow. Try falling back
3285 * to the next wide speed with
3286 * all supported ppr options set.
3287 */
3288 targ->dv_next_narrow_period = period+1;
3289 width = MSG_EXT_WDTR_BUS_16_BIT;
3290 period = targ->dv_next_wide_period;
3291 ppr_options = targ->dv_max_ppr_options;
3292 } else {
3293 /* Only narrow fallback is allowed. */
3294 period++;
3295 ppr_options = targ->dv_max_ppr_options;
3296 }
3297 } else {
3298 ahc_unlock(ahc, &s);
3299 return (-1);
3300 }
3301 offset = MAX_OFFSET;
3302 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
3303 AHC_SYNCRATE_DT);
3304 ahc_set_width(ahc, devinfo, width, AHC_TRANS_GOAL, FALSE);
3305 if (period == 0) {
3306 period = 0;
3307 offset = 0;
3308 ppr_options = 0;
3309 if (width == MSG_EXT_WDTR_BUS_8_BIT)
3310 targ->dv_next_narrow_period = AHC_ASYNC_XFER_PERIOD;
3311 else
3312 targ->dv_next_wide_period = AHC_ASYNC_XFER_PERIOD;
3313 }
3314 ahc_set_syncrate(ahc, devinfo, syncrate, period, offset,
3315 ppr_options, AHC_TRANS_GOAL, FALSE);
3316 targ->dv_last_ppr_options = ppr_options;
3317 ahc_unlock(ahc, &s);
3318 return (0);
3319}
3320
3321static void
3322ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
3323{
3324 struct ahc_softc *ahc;
3325 struct scb *scb;
3326 u_long flags;
3327
3328 ahc = *((struct ahc_softc **)cmd->device->host->hostdata);
3329 ahc_lock(ahc, &flags);
3330
3331#ifdef AHC_DEBUG
3332 if (ahc_debug & AHC_SHOW_DV) {
3333 printf("%s: Timeout while doing DV command %x.\n",
3334 ahc_name(ahc), cmd->cmnd[0]);
3335 ahc_dump_card_state(ahc);
3336 }
3337#endif
3338
3339 /*
3340 * Guard against "done race". No action is
3341 * required if we just completed.
3342 */
3343 if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
3344 ahc_unlock(ahc, &flags);
3345 return;
3346 }
3347
3348 /*
3349 * Command has not completed. Mark this
3350 * SCB as having failing status prior to
3351 * resetting the bus, so we get the correct
3352 * error code.
3353 */
3354 if ((scb->flags & SCB_SENSE) != 0)
3355 ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
3356 else
3357 ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
3358 ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate*/TRUE);
3359
3360 /*
3361 * Add a minimal bus settle delay for devices that are slow to
3362 * respond after bus resets.
3363 */
3364 ahc_linux_freeze_simq(ahc);
3365 init_timer(&ahc->platform_data->reset_timer);
3366 ahc->platform_data->reset_timer.data = (u_long)ahc;
3367 ahc->platform_data->reset_timer.expires = jiffies + HZ / 2;
3368 ahc->platform_data->reset_timer.function =
3369 (ahc_linux_callback_t *)ahc_linux_release_simq;
3370 add_timer(&ahc->platform_data->reset_timer);
3371 if (ahc_linux_next_device_to_run(ahc) != NULL)
3372 ahc_schedule_runq(ahc);
3373 ahc_linux_run_complete_queue(ahc);
3374 ahc_unlock(ahc, &flags);
3375}
3376
3377static void
3378ahc_linux_dv_complete(struct scsi_cmnd *cmd)
3379{
3380 struct ahc_softc *ahc;
3381
3382 ahc = *((struct ahc_softc **)cmd->device->host->hostdata);
3383
3384 /* Delete the DV timer before it goes off! */
3385 scsi_delete_timer(cmd);
3386
3387#ifdef AHC_DEBUG
3388 if (ahc_debug & AHC_SHOW_DV)
3389 printf("%s:%d:%d: Command completed, status= 0x%x\n",
3390 ahc_name(ahc), cmd->device->channel,
3391 cmd->device->id, cmd->result);
3392#endif
3393
3394 /* Wake up the state machine */
3395 up(&ahc->platform_data->dv_cmd_sem);
3396}
3397
3398static void
3399ahc_linux_generate_dv_pattern(struct ahc_linux_target *targ)
3400{
3401 uint16_t b;
3402 u_int i;
3403 u_int j;
3404
3405 if (targ->dv_buffer != NULL)
3406 free(targ->dv_buffer, M_DEVBUF);
3407 targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
3408 if (targ->dv_buffer1 != NULL)
3409 free(targ->dv_buffer1, M_DEVBUF);
3410 targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
3411
3412 i = 0;
3413 b = 0x0001;
3414 for (j = 0 ; i < targ->dv_echo_size; j++) {
3415 if (j < 32) {
3416 /*
3417 * 32bytes of sequential numbers.
3418 */
3419 targ->dv_buffer[i++] = j & 0xff;
3420 } else if (j < 48) {
3421 /*
3422 * 32bytes of repeating 0x0000, 0xffff.
3423 */
3424 targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00;
3425 } else if (j < 64) {
3426 /*
3427 * 32bytes of repeating 0x5555, 0xaaaa.
3428 */
3429 targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55;
3430 } else {
3431 /*
3432 * Remaining buffer is filled with a repeating
3433 * patter of:
3434 *
3435 * 0xffff
3436 * ~0x0001 << shifted once in each loop.
3437 */
3438 if (j & 0x02) {
3439 if (j & 0x01) {
3440 targ->dv_buffer[i++] = ~(b >> 8) & 0xff;
3441 b <<= 1;
3442 if (b == 0x0000)
3443 b = 0x0001;
3444 } else {
3445 targ->dv_buffer[i++] = (~b & 0xff);
3446 }
3447 } else {
3448 targ->dv_buffer[i++] = 0xff;
3449 }
3450 }
3451 }
3452}
3453
3454static u_int 1988static u_int
3455ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) 1989ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3456{ 1990{
@@ -3482,48 +2016,6 @@ ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3482 return (tags); 2016 return (tags);
3483} 2017}
3484 2018
3485static u_int
3486ahc_linux_user_dv_setting(struct ahc_softc *ahc)
3487{
3488 static int warned_user;
3489 int dv;
3490
3491 if (ahc->unit >= NUM_ELEMENTS(aic7xxx_dv_settings)) {
3492 if (warned_user == 0) {
3493
3494 printf(KERN_WARNING
3495"aic7xxx: WARNING: Insufficient dv settings instances\n"
3496"aic7xxx: for installed controllers. Using defaults\n"
3497"aic7xxx: Please update the aic7xxx_dv_settings array\n"
3498"aic7xxx: in the aic7xxx_osm.c source file.\n");
3499 warned_user++;
3500 }
3501 dv = -1;
3502 } else {
3503
3504 dv = aic7xxx_dv_settings[ahc->unit];
3505 }
3506
3507 if (dv < 0) {
3508 u_long s;
3509
3510 /*
3511 * Apply the default.
3512 */
3513 /*
3514 * XXX - Enable DV on non-U160 controllers once it
3515 * has been tested there.
3516 */
3517 ahc_lock(ahc, &s);
3518 dv = (ahc->features & AHC_DT);
3519 if (ahc->seep_config != 0
3520 && ahc->seep_config->signature >= CFSIGNATURE2)
3521 dv = (ahc->seep_config->adapter_control & CFENABLEDV);
3522 ahc_unlock(ahc, &s);
3523 }
3524 return (dv);
3525}
3526
3527/* 2019/*
3528 * Determines the queue depth for a given device. 2020 * Determines the queue depth for a given device.
3529 */ 2021 */
@@ -3574,8 +2066,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
3574 * Schedule us to run later. The only reason we are not 2066 * Schedule us to run later. The only reason we are not
3575 * running is because the whole controller Q is frozen. 2067 * running is because the whole controller Q is frozen.
3576 */ 2068 */
3577 if (ahc->platform_data->qfrozen != 0 2069 if (ahc->platform_data->qfrozen != 0) {
3578 && AHC_DV_SIMQ_FROZEN(ahc) == 0) {
3579 TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, 2070 TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
3580 dev, links); 2071 dev, links);
3581 dev->flags |= AHC_DEV_ON_RUN_LIST; 2072 dev->flags |= AHC_DEV_ON_RUN_LIST;
@@ -3616,9 +2107,6 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
3616 if ((ahc->user_discenable & mask) != 0) 2107 if ((ahc->user_discenable & mask) != 0)
3617 hscb->control |= DISCENB; 2108 hscb->control |= DISCENB;
3618 2109
3619 if (AHC_DV_CMD(cmd) != 0)
3620 scb->flags |= SCB_SILENT;
3621
3622 if ((tstate->auto_negotiate & mask) != 0) { 2110 if ((tstate->auto_negotiate & mask) != 0) {
3623 scb->flags |= SCB_AUTO_NEGOTIATE; 2111 scb->flags |= SCB_AUTO_NEGOTIATE;
3624 scb->hscb->control |= MK_MESSAGE; 2112 scb->hscb->control |= MK_MESSAGE;
@@ -3811,7 +2299,6 @@ ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
3811 targ->channel = channel; 2299 targ->channel = channel;
3812 targ->target = target; 2300 targ->target = target;
3813 targ->ahc = ahc; 2301 targ->ahc = ahc;
3814 targ->flags = AHC_DV_REQUIRED;
3815 ahc->platform_data->targets[target_offset] = targ; 2302 ahc->platform_data->targets[target_offset] = targ;
3816 return (targ); 2303 return (targ);
3817} 2304}
@@ -3850,10 +2337,6 @@ ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
3850 ahc->platform_data->targets[target_offset] = NULL; 2337 ahc->platform_data->targets[target_offset] = NULL;
3851 if (targ->inq_data != NULL) 2338 if (targ->inq_data != NULL)
3852 free(targ->inq_data, M_DEVBUF); 2339 free(targ->inq_data, M_DEVBUF);
3853 if (targ->dv_buffer != NULL)
3854 free(targ->dv_buffer, M_DEVBUF);
3855 if (targ->dv_buffer1 != NULL)
3856 free(targ->dv_buffer1, M_DEVBUF);
3857 free(targ, M_DEVBUF); 2340 free(targ, M_DEVBUF);
3858} 2341}
3859 2342
@@ -3900,8 +2383,7 @@ __ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
3900 targ->devices[dev->lun] = NULL; 2383 targ->devices[dev->lun] = NULL;
3901 free(dev, M_DEVBUF); 2384 free(dev, M_DEVBUF);
3902 targ->refcount--; 2385 targ->refcount--;
3903 if (targ->refcount == 0 2386 if (targ->refcount == 0)
3904 && (targ->flags & AHC_DV_REQUIRED) == 0)
3905 ahc_linux_free_target(ahc, targ); 2387 ahc_linux_free_target(ahc, targ);
3906} 2388}
3907 2389
@@ -4105,16 +2587,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
4105 ahc_linux_handle_scsi_status(ahc, dev, scb); 2587 ahc_linux_handle_scsi_status(ahc, dev, scb);
4106 } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) { 2588 } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
4107 dev->flags |= AHC_DEV_UNCONFIGURED; 2589 dev->flags |= AHC_DEV_UNCONFIGURED;
4108 if (AHC_DV_CMD(cmd) == FALSE)
4109 dev->target->flags &= ~AHC_DV_REQUIRED;
4110 } 2590 }
4111 /*
4112 * Start DV for devices that require it assuming the first command
4113 * sent does not result in a selection timeout.
4114 */
4115 if (ahc_get_transaction_status(scb) != CAM_SEL_TIMEOUT
4116 && (dev->target->flags & AHC_DV_REQUIRED) != 0)
4117 ahc_linux_start_dv(ahc);
4118 2591
4119 if (dev->openings == 1 2592 if (dev->openings == 1
4120 && ahc_get_transaction_status(scb) == CAM_REQ_CMP 2593 && ahc_get_transaction_status(scb) == CAM_REQ_CMP
@@ -4158,13 +2631,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
4158 2631
4159 ahc_free_scb(ahc, scb); 2632 ahc_free_scb(ahc, scb);
4160 ahc_linux_queue_cmd_complete(ahc, cmd); 2633 ahc_linux_queue_cmd_complete(ahc, cmd);
4161
4162 if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0
4163 && LIST_FIRST(&ahc->pending_scbs) == NULL) {
4164 ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY;
4165 up(&ahc->platform_data->dv_sem);
4166 }
4167
4168} 2634}
4169 2635
4170static void 2636static void
@@ -4341,7 +2807,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
4341 * full error information available when making 2807 * full error information available when making
4342 * state change decisions. 2808 * state change decisions.
4343 */ 2809 */
4344 if (AHC_DV_CMD(cmd) == FALSE) { 2810 {
4345 u_int new_status; 2811 u_int new_status;
4346 2812
4347 switch (ahc_cmd_get_transaction_status(cmd)) { 2813 switch (ahc_cmd_get_transaction_status(cmd)) {
@@ -4432,115 +2898,6 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
4432} 2898}
4433 2899
4434static void 2900static void
4435ahc_linux_filter_inquiry(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
4436{
4437 struct scsi_inquiry_data *sid;
4438 struct ahc_initiator_tinfo *tinfo;
4439 struct ahc_transinfo *user;
4440 struct ahc_transinfo *goal;
4441 struct ahc_transinfo *curr;
4442 struct ahc_tmode_tstate *tstate;
4443 struct ahc_syncrate *syncrate;
4444 struct ahc_linux_device *dev;
4445 u_int maxsync;
4446 u_int width;
4447 u_int period;
4448 u_int offset;
4449 u_int ppr_options;
4450 u_int trans_version;
4451 u_int prot_version;
4452
4453 /*
4454 * Determine if this lun actually exists. If so,
4455 * hold on to its corresponding device structure.
4456 * If not, make sure we release the device and
4457 * don't bother processing the rest of this inquiry
4458 * command.
4459 */
4460 dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
4461 devinfo->target, devinfo->lun,
4462 /*alloc*/TRUE);
4463
4464 sid = (struct scsi_inquiry_data *)dev->target->inq_data;
4465 if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
4466
4467 dev->flags &= ~AHC_DEV_UNCONFIGURED;
4468 } else {
4469 dev->flags |= AHC_DEV_UNCONFIGURED;
4470 return;
4471 }
4472
4473 /*
4474 * Update our notion of this device's transfer
4475 * negotiation capabilities.
4476 */
4477 tinfo = ahc_fetch_transinfo(ahc, devinfo->channel,
4478 devinfo->our_scsiid,
4479 devinfo->target, &tstate);
4480 user = &tinfo->user;
4481 goal = &tinfo->goal;
4482 curr = &tinfo->curr;
4483 width = user->width;
4484 period = user->period;
4485 offset = user->offset;
4486 ppr_options = user->ppr_options;
4487 trans_version = user->transport_version;
4488 prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid));
4489
4490 /*
4491 * Only attempt SPI3/4 once we've verified that
4492 * the device claims to support SPI3/4 features.
4493 */
4494 if (prot_version < SCSI_REV_2)
4495 trans_version = SID_ANSI_REV(sid);
4496 else
4497 trans_version = SCSI_REV_2;
4498
4499 if ((sid->flags & SID_WBus16) == 0)
4500 width = MSG_EXT_WDTR_BUS_8_BIT;
4501 if ((sid->flags & SID_Sync) == 0) {
4502 period = 0;
4503 offset = 0;
4504 ppr_options = 0;
4505 }
4506 if ((sid->spi3data & SID_SPI_QAS) == 0)
4507 ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
4508 if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
4509 ppr_options &= MSG_EXT_PPR_QAS_REQ;
4510 if ((sid->spi3data & SID_SPI_IUS) == 0)
4511 ppr_options &= (MSG_EXT_PPR_DT_REQ
4512 | MSG_EXT_PPR_QAS_REQ);
4513
4514 if (prot_version > SCSI_REV_2
4515 && ppr_options != 0)
4516 trans_version = user->transport_version;
4517
4518 ahc_validate_width(ahc, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN);
4519 if ((ahc->features & AHC_ULTRA2) != 0)
4520 maxsync = AHC_SYNCRATE_DT;
4521 else if ((ahc->features & AHC_ULTRA) != 0)
4522 maxsync = AHC_SYNCRATE_ULTRA;
4523 else
4524 maxsync = AHC_SYNCRATE_FAST;
4525
4526 syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, maxsync);
4527 ahc_validate_offset(ahc, /*tinfo limit*/NULL, syncrate,
4528 &offset, width, ROLE_UNKNOWN);
4529 if (offset == 0 || period == 0) {
4530 period = 0;
4531 offset = 0;
4532 ppr_options = 0;
4533 }
4534 /* Apply our filtered user settings. */
4535 curr->transport_version = trans_version;
4536 curr->protocol_version = prot_version;
4537 ahc_set_width(ahc, devinfo, width, AHC_TRANS_GOAL, /*paused*/FALSE);
4538 ahc_set_syncrate(ahc, devinfo, syncrate, period,
4539 offset, ppr_options, AHC_TRANS_GOAL,
4540 /*paused*/FALSE);
4541}
4542
4543static void
4544ahc_linux_sem_timeout(u_long arg) 2901ahc_linux_sem_timeout(u_long arg)
4545{ 2902{
4546 struct ahc_softc *ahc; 2903 struct ahc_softc *ahc;
@@ -4585,11 +2942,6 @@ ahc_linux_release_simq(u_long arg)
4585 ahc->platform_data->qfrozen--; 2942 ahc->platform_data->qfrozen--;
4586 if (ahc->platform_data->qfrozen == 0) 2943 if (ahc->platform_data->qfrozen == 0)
4587 unblock_reqs = 1; 2944 unblock_reqs = 1;
4588 if (AHC_DV_SIMQ_FROZEN(ahc)
4589 && ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) {
4590 ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE;
4591 up(&ahc->platform_data->dv_sem);
4592 }
4593 ahc_schedule_runq(ahc); 2945 ahc_schedule_runq(ahc);
4594 ahc_unlock(ahc, &s); 2946 ahc_unlock(ahc, &s);
4595 /* 2947 /*
@@ -5274,19 +3626,6 @@ ahc_linux_init(void)
5274static void 3626static void
5275ahc_linux_exit(void) 3627ahc_linux_exit(void)
5276{ 3628{
5277 struct ahc_softc *ahc;
5278
5279 /*
5280 * Shutdown DV threads before going into the SCSI mid-layer.
5281 * This avoids situations where the mid-layer locks the entire
5282 * kernel so that waiting for our DV threads to exit leads
5283 * to deadlock.
5284 */
5285 TAILQ_FOREACH(ahc, &ahc_tailq, links) {
5286
5287 ahc_linux_kill_dv_thread(ahc);
5288 }
5289
5290#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 3629#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
5291 /* 3630 /*
5292 * In 2.4 we have to unregister from the PCI core _after_ 3631 * In 2.4 we have to unregister from the PCI core _after_
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index db3bd6321dd4..c401537067b6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -424,27 +424,9 @@ struct ahc_linux_device {
424}; 424};
425 425
426typedef enum { 426typedef enum {
427 AHC_DV_REQUIRED = 0x01,
428 AHC_INQ_VALID = 0x02, 427 AHC_INQ_VALID = 0x02,
429 AHC_BASIC_DV = 0x04,
430 AHC_ENHANCED_DV = 0x08
431} ahc_linux_targ_flags; 428} ahc_linux_targ_flags;
432 429
433/* DV States */
434typedef enum {
435 AHC_DV_STATE_EXIT = 0,
436 AHC_DV_STATE_INQ_SHORT_ASYNC,
437 AHC_DV_STATE_INQ_ASYNC,
438 AHC_DV_STATE_INQ_ASYNC_VERIFY,
439 AHC_DV_STATE_TUR,
440 AHC_DV_STATE_REBD,
441 AHC_DV_STATE_INQ_VERIFY,
442 AHC_DV_STATE_WEB,
443 AHC_DV_STATE_REB,
444 AHC_DV_STATE_SU,
445 AHC_DV_STATE_BUSY
446} ahc_dv_state;
447
448struct ahc_linux_target { 430struct ahc_linux_target {
449 struct ahc_linux_device *devices[AHC_NUM_LUNS]; 431 struct ahc_linux_device *devices[AHC_NUM_LUNS];
450 int channel; 432 int channel;
@@ -454,19 +436,6 @@ struct ahc_linux_target {
454 struct ahc_softc *ahc; 436 struct ahc_softc *ahc;
455 ahc_linux_targ_flags flags; 437 ahc_linux_targ_flags flags;
456 struct scsi_inquiry_data *inq_data; 438 struct scsi_inquiry_data *inq_data;
457 /*
458 * The next "fallback" period to use for narrow/wide transfers.
459 */
460 uint8_t dv_next_narrow_period;
461 uint8_t dv_next_wide_period;
462 uint8_t dv_max_width;
463 uint8_t dv_max_ppr_options;
464 uint8_t dv_last_ppr_options;
465 u_int dv_echo_size;
466 ahc_dv_state dv_state;
467 u_int dv_state_retry;
468 char *dv_buffer;
469 char *dv_buffer1;
470}; 439};
471 440
472/********************* Definitions Required by the Core ***********************/ 441/********************* Definitions Required by the Core ***********************/
@@ -511,10 +480,6 @@ struct scb_platform_data {
511 * this driver. 480 * this driver.
512 */ 481 */
513typedef enum { 482typedef enum {
514 AHC_DV_WAIT_SIMQ_EMPTY = 0x01,
515 AHC_DV_WAIT_SIMQ_RELEASE = 0x02,
516 AHC_DV_ACTIVE = 0x04,
517 AHC_DV_SHUTDOWN = 0x08,
518 AHC_RUN_CMPLT_Q_TIMER = 0x10 483 AHC_RUN_CMPLT_Q_TIMER = 0x10
519} ahc_linux_softc_flags; 484} ahc_linux_softc_flags;
520 485
@@ -937,11 +902,6 @@ int ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
937#endif 902#endif
938 903
939/*************************** Domain Validation ********************************/ 904/*************************** Domain Validation ********************************/
940#define AHC_DV_CMD(cmd) ((cmd)->scsi_done == ahc_linux_dv_complete)
941#define AHC_DV_SIMQ_FROZEN(ahc) \
942 ((((ahc)->platform_data->flags & AHC_DV_ACTIVE) != 0) \
943 && (ahc)->platform_data->qfrozen == 1)
944
945/*********************** Transaction Access Wrappers *************************/ 905/*********************** Transaction Access Wrappers *************************/
946static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); 906static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
947static __inline void ahc_set_transaction_status(struct scb *, uint32_t); 907static __inline void ahc_set_transaction_status(struct scb *, uint32_t);