aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);