aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorpeter fuerst <post@pfrst.de>2007-02-12 09:20:15 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-02-16 10:22:11 -0500
commita5d8421b2f03e46f02cc02066b186fdbc0f590a6 (patch)
treefe517aae7d78c85af15c3a23810044544a576e52 /drivers/scsi
parent7de970e11fb832a56c897276967fb0e49f59b313 (diff)
[SCSI] wd33c93: Fast SCSI with WD33C93B
Attached are patches, which help to utilize more of the WD33C93B SCSI controller's capabilities. 1) Added/changed all the necessary code to enable Burst Mode DMA. Only Single Byte DMA was used before. 2) Added/changed all the necessary code to enable Fast-10 SCSI transfers. 3) The original driver inadvertently used a transfer period of 1000-800ns (the lowest possible transfer rate) for asynchronous data transfers, instead of the (configurable) default period intended for this purpose, if the target responded to a SDTR not with a Reject-message, but with a zero-SDTR. This issue was fixed. Moreover, in case of a Reject the driver used the default-period's initialization-value instead of its (maybe smaller) current value. The missing assignment was added. 4) The driver's commandline- and proc-file-interface was augmented to handle the new options properly. The WD33C93 manual, found at http://www.datasheet.in/datasheet-html/W/D/3/WD33C93B_WesternDigital.pdf.html, was very helpful. Signed-off-by: peter fuerst <post@pfrst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/wd33c93.c321
-rw-r--r--drivers/scsi/wd33c93.h6
2 files changed, 248 insertions, 79 deletions
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 835751600e93..fa4e08e508ad 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -69,6 +69,11 @@
69 * Added support for pre -A chips, which don't have advanced features 69 * Added support for pre -A chips, which don't have advanced features
70 * and will generate CSR_RESEL rather than CSR_RESEL_AM. 70 * and will generate CSR_RESEL rather than CSR_RESEL_AM.
71 * Richard Hirst <richard@sleepie.demon.co.uk> August 2000 71 * Richard Hirst <richard@sleepie.demon.co.uk> August 2000
72 *
73 * Added support for Burst Mode DMA and Fast SCSI. Enabled the use of
74 * default_sx_per for asynchronous data transfers. Added adjustment
75 * of transfer periods in sx_table to the actual input-clock.
76 * peter fuerst <post@pfrst.de> February 2007
72 */ 77 */
73 78
74#include <linux/module.h> 79#include <linux/module.h>
@@ -86,9 +91,11 @@
86 91
87#include "wd33c93.h" 92#include "wd33c93.h"
88 93
94#define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns
95
89 96
90#define WD33C93_VERSION "1.26" 97#define WD33C93_VERSION "1.26++"
91#define WD33C93_DATE "22/Feb/2003" 98#define WD33C93_DATE "10/Feb/2007"
92 99
93MODULE_AUTHOR("John Shifflett"); 100MODULE_AUTHOR("John Shifflett");
94MODULE_DESCRIPTION("Generic WD33C93 SCSI driver"); 101MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
@@ -122,6 +129,13 @@ MODULE_LICENSE("GPL");
122 * defines in wd33c93.h 129 * defines in wd33c93.h
123 * - clock:x -x = clock input in MHz for WD33c93 chip. Normal values 130 * - clock:x -x = clock input in MHz for WD33c93 chip. Normal values
124 * would be from 8 through 20. Default is 8. 131 * would be from 8 through 20. Default is 8.
132 * - burst:x -x = 1 to use Burst Mode (or Demand-Mode) DMA, x = 0 to use
133 * Single Byte DMA, which is the default. Argument is
134 * optional - if not present, same as "burst:1".
135 * - fast:x -x = 1 to enable Fast SCSI, which is only effective with
136 * input-clock divisor 4 (WD33C93_FS_16_20), x = 0 to disable
137 * it, which is the default. Argument is optional - if not
138 * present, same as "fast:1".
125 * - next -No argument. Used to separate blocks of keywords when 139 * - next -No argument. Used to separate blocks of keywords when
126 * there's more than one host adapter in the system. 140 * there's more than one host adapter in the system.
127 * 141 *
@@ -148,7 +162,7 @@ MODULE_LICENSE("GPL");
148 */ 162 */
149 163
150/* Normally, no defaults are specified */ 164/* Normally, no defaults are specified */
151static char *setup_args[] = { "", "", "", "", "", "", "", "", "" }; 165static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" };
152 166
153static char *setup_strings; 167static char *setup_strings;
154module_param(setup_strings, charp, 0); 168module_param(setup_strings, charp, 0);
@@ -298,20 +312,8 @@ read_1_byte(const wd33c93_regs regs)
298 return x; 312 return x;
299} 313}
300 314
301static struct sx_period sx_table[] = {
302 {1, 0x20},
303 {252, 0x20},
304 {376, 0x30},
305 {500, 0x40},
306 {624, 0x50},
307 {752, 0x60},
308 {876, 0x70},
309 {1000, 0x00},
310 {0, 0}
311};
312
313static int 315static int
314round_period(unsigned int period) 316round_period(unsigned int period, const struct sx_period *sx_table)
315{ 317{
316 int x; 318 int x;
317 319
@@ -324,17 +326,49 @@ round_period(unsigned int period)
324 return 7; 326 return 7;
325} 327}
326 328
329/*
330 * Calculate Synchronous Transfer Register value from SDTR code.
331 */
327static uchar 332static uchar
328calc_sync_xfer(unsigned int period, unsigned int offset) 333calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast,
334 const struct sx_period *sx_table)
329{ 335{
336 /* When doing Fast SCSI synchronous data transfers, the corresponding
337 * value in 'sx_table' is two times the actually used transfer period.
338 */
330 uchar result; 339 uchar result;
331 340
341 if (offset && fast) {
342 fast = STR_FSS;
343 period *= 2;
344 } else {
345 fast = 0;
346 }
332 period *= 4; /* convert SDTR code to ns */ 347 period *= 4; /* convert SDTR code to ns */
333 result = sx_table[round_period(period)].reg_value; 348 result = sx_table[round_period(period,sx_table)].reg_value;
334 result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF; 349 result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
350 result |= fast;
335 return result; 351 return result;
336} 352}
337 353
354/*
355 * Calculate SDTR code bytes [3],[4] from period and offset.
356 */
357static inline void
358calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
359 uchar msg[2])
360{
361 /* 'period' is a "normal"-mode value, like the ones in 'sx_table'. The
362 * actually used transfer period for Fast SCSI synchronous data
363 * transfers is half that value.
364 */
365 period /= 4;
366 if (offset && fast)
367 period /= 2;
368 msg[0] = period;
369 msg[1] = offset;
370}
371
338int 372int
339wd33c93_queuecommand(struct scsi_cmnd *cmd, 373wd33c93_queuecommand(struct scsi_cmnd *cmd,
340 void (*done)(struct scsi_cmnd *)) 374 void (*done)(struct scsi_cmnd *))
@@ -632,7 +666,7 @@ wd33c93_execute(struct Scsi_Host *instance)
632 write_wd33c93_count(regs, 666 write_wd33c93_count(regs,
633 cmd->SCp.this_residual); 667 cmd->SCp.this_residual);
634 write_wd33c93(regs, WD_CONTROL, 668 write_wd33c93(regs, WD_CONTROL,
635 CTRL_IDI | CTRL_EDI | CTRL_DMA); 669 CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
636 hostdata->dma = D_DMA_RUNNING; 670 hostdata->dma = D_DMA_RUNNING;
637 } 671 }
638 } else 672 } else
@@ -712,6 +746,8 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
712 cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + 746 cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
713 cmd->SCp.buffer->offset; 747 cmd->SCp.buffer->offset;
714 } 748 }
749 if (!cmd->SCp.this_residual) /* avoid bogus setups */
750 return;
715 751
716 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, 752 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
717 hostdata->sync_xfer[cmd->device->id]); 753 hostdata->sync_xfer[cmd->device->id]);
@@ -744,7 +780,7 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
744#ifdef PROC_STATISTICS 780#ifdef PROC_STATISTICS
745 hostdata->dma_cnt++; 781 hostdata->dma_cnt++;
746#endif 782#endif
747 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA); 783 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
748 write_wd33c93_count(regs, cmd->SCp.this_residual); 784 write_wd33c93_count(regs, cmd->SCp.this_residual);
749 785
750 if ((hostdata->level2 >= L2_DATA) || 786 if ((hostdata->level2 >= L2_DATA) ||
@@ -862,9 +898,6 @@ wd33c93_intr(struct Scsi_Host *instance)
862 hostdata->outgoing_msg[0] |= 0x40; 898 hostdata->outgoing_msg[0] |= 0x40;
863 899
864 if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) { 900 if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
865#ifdef SYNC_DEBUG
866 printk(" sending SDTR ");
867#endif
868 901
869 hostdata->sync_stat[cmd->device->id] = SS_WAITING; 902 hostdata->sync_stat[cmd->device->id] = SS_WAITING;
870 903
@@ -878,14 +911,20 @@ wd33c93_intr(struct Scsi_Host *instance)
878 hostdata->outgoing_msg[2] = 3; 911 hostdata->outgoing_msg[2] = 3;
879 hostdata->outgoing_msg[3] = EXTENDED_SDTR; 912 hostdata->outgoing_msg[3] = EXTENDED_SDTR;
880 if (hostdata->no_sync & (1 << cmd->device->id)) { 913 if (hostdata->no_sync & (1 << cmd->device->id)) {
881 hostdata->outgoing_msg[4] = 914 calc_sync_msg(hostdata->default_sx_per, 0,
882 hostdata->default_sx_per / 4; 915 0, hostdata->outgoing_msg + 4);
883 hostdata->outgoing_msg[5] = 0;
884 } else { 916 } else {
885 hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4; 917 calc_sync_msg(optimum_sx_per(hostdata),
886 hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; 918 OPTIMUM_SX_OFF,
919 hostdata->fast,
920 hostdata->outgoing_msg + 4);
887 } 921 }
888 hostdata->outgoing_len = 6; 922 hostdata->outgoing_len = 6;
923#ifdef SYNC_DEBUG
924 ucp = hostdata->outgoing_msg + 1;
925 printk(" sending SDTR %02x03%02x%02x%02x ",
926 ucp[0], ucp[2], ucp[3], ucp[4]);
927#endif
889 } else 928 } else
890 hostdata->outgoing_len = 1; 929 hostdata->outgoing_len = 1;
891 930
@@ -1001,8 +1040,13 @@ wd33c93_intr(struct Scsi_Host *instance)
1001#ifdef SYNC_DEBUG 1040#ifdef SYNC_DEBUG
1002 printk("-REJ-"); 1041 printk("-REJ-");
1003#endif 1042#endif
1004 if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) 1043 if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) {
1005 hostdata->sync_stat[cmd->device->id] = SS_SET; 1044 hostdata->sync_stat[cmd->device->id] = SS_SET;
1045 /* we want default_sx_per, not DEFAULT_SX_PER */
1046 hostdata->sync_xfer[cmd->device->id] =
1047 calc_sync_xfer(hostdata->default_sx_per
1048 / 4, 0, 0, hostdata->sx_table);
1049 }
1006 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK); 1050 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1007 hostdata->state = S_CONNECTED; 1051 hostdata->state = S_CONNECTED;
1008 break; 1052 break;
@@ -1022,7 +1066,10 @@ wd33c93_intr(struct Scsi_Host *instance)
1022 1066
1023 switch (ucp[2]) { /* what's the EXTENDED code? */ 1067 switch (ucp[2]) { /* what's the EXTENDED code? */
1024 case EXTENDED_SDTR: 1068 case EXTENDED_SDTR:
1025 id = calc_sync_xfer(ucp[3], ucp[4]); 1069 /* default to default async period */
1070 id = calc_sync_xfer(hostdata->
1071 default_sx_per / 4, 0,
1072 0, hostdata->sx_table);
1026 if (hostdata->sync_stat[cmd->device->id] != 1073 if (hostdata->sync_stat[cmd->device->id] !=
1027 SS_WAITING) { 1074 SS_WAITING) {
1028 1075
@@ -1041,20 +1088,22 @@ wd33c93_intr(struct Scsi_Host *instance)
1041 hostdata->outgoing_msg[1] = 3; 1088 hostdata->outgoing_msg[1] = 3;
1042 hostdata->outgoing_msg[2] = 1089 hostdata->outgoing_msg[2] =
1043 EXTENDED_SDTR; 1090 EXTENDED_SDTR;
1044 hostdata->outgoing_msg[3] = 1091 calc_sync_msg(hostdata->
1045 hostdata->default_sx_per / 1092 default_sx_per, 0,
1046 4; 1093 0, hostdata->outgoing_msg + 3);
1047 hostdata->outgoing_msg[4] = 0;
1048 hostdata->outgoing_len = 5; 1094 hostdata->outgoing_len = 5;
1049 hostdata->sync_xfer[cmd->device->id] =
1050 calc_sync_xfer(hostdata->
1051 default_sx_per
1052 / 4, 0);
1053 } else { 1095 } else {
1054 hostdata->sync_xfer[cmd->device->id] = id; 1096 if (ucp[4]) /* well, sync transfer */
1097 id = calc_sync_xfer(ucp[3], ucp[4],
1098 hostdata->fast,
1099 hostdata->sx_table);
1100 else if (ucp[3]) /* very unlikely... */
1101 id = calc_sync_xfer(ucp[3], ucp[4],
1102 0, hostdata->sx_table);
1055 } 1103 }
1104 hostdata->sync_xfer[cmd->device->id] = id;
1056#ifdef SYNC_DEBUG 1105#ifdef SYNC_DEBUG
1057 printk("sync_xfer=%02x", 1106 printk(" sync_xfer=%02x\n",
1058 hostdata->sync_xfer[cmd->device->id]); 1107 hostdata->sync_xfer[cmd->device->id]);
1059#endif 1108#endif
1060 hostdata->sync_stat[cmd->device->id] = 1109 hostdata->sync_stat[cmd->device->id] =
@@ -1486,7 +1535,7 @@ reset_wd33c93(struct Scsi_Host *instance)
1486 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); 1535 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1487 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, 1536 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
1488 calc_sync_xfer(hostdata->default_sx_per / 4, 1537 calc_sync_xfer(hostdata->default_sx_per / 4,
1489 DEFAULT_SX_OFF)); 1538 DEFAULT_SX_OFF, 0, hostdata->sx_table));
1490 write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET); 1539 write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
1491 1540
1492 1541
@@ -1512,6 +1561,9 @@ reset_wd33c93(struct Scsi_Host *instance)
1512 } else 1561 } else
1513 hostdata->chip = C_UNKNOWN_CHIP; 1562 hostdata->chip = C_UNKNOWN_CHIP;
1514 1563
1564 if (hostdata->chip != C_WD33C93B) /* Fast SCSI unavailable */
1565 hostdata->fast = 0;
1566
1515 write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); 1567 write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1516 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); 1568 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1517} 1569}
@@ -1533,7 +1585,8 @@ wd33c93_host_reset(struct scsi_cmnd * SCpnt)
1533 for (i = 0; i < 8; i++) { 1585 for (i = 0; i < 8; i++) {
1534 hostdata->busy[i] = 0; 1586 hostdata->busy[i] = 0;
1535 hostdata->sync_xfer[i] = 1587 hostdata->sync_xfer[i] =
1536 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); 1588 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1589 0, hostdata->sx_table);
1537 hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ 1590 hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
1538 } 1591 }
1539 hostdata->input_Q = NULL; 1592 hostdata->input_Q = NULL;
@@ -1782,6 +1835,98 @@ check_setup_args(char *key, int *flags, int *val, char *buf)
1782 return ++x; 1835 return ++x;
1783} 1836}
1784 1837
1838/*
1839 * Calculate internal data-transfer-clock cycle from input-clock
1840 * frequency (/MHz) and fill 'sx_table'.
1841 *
1842 * The original driver used to rely on a fixed sx_table, containing periods
1843 * for (only) the lower limits of the respective input-clock-frequency ranges
1844 * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with
1845 * this setting so far, it might be desirable to adjust the transfer periods
1846 * closer to the really attached, possibly 25% higher, input-clock, since
1847 * - the wd33c93 may really use a significant shorter period, than it has
1848 * negotiated (eg. thrashing the target, which expects 4/8MHz, with 5/10MHz
1849 * instead).
1850 * - the wd33c93 may ask the target for a lower transfer rate, than the target
1851 * is capable of (eg. negotiating for an assumed minimum of 252ns instead of
1852 * possible 200ns, which indeed shows up in tests as an approx. 10% lower
1853 * transfer rate).
1854 */
1855static inline unsigned int
1856round_4(unsigned int x)
1857{
1858 switch (x & 3) {
1859 case 1: --x;
1860 break;
1861 case 2: ++x;
1862 case 3: ++x;
1863 }
1864 return x;
1865}
1866
1867static void
1868calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
1869{
1870 unsigned int d, i;
1871 if (mhz < 11)
1872 d = 2; /* divisor for 8-10 MHz input-clock */
1873 else if (mhz < 16)
1874 d = 3; /* divisor for 12-15 MHz input-clock */
1875 else
1876 d = 4; /* divisor for 16-20 MHz input-clock */
1877
1878 d = (100000 * d) / 2 / mhz; /* 100 x DTCC / nanosec */
1879
1880 sx_table[0].period_ns = 1;
1881 sx_table[0].reg_value = 0x20;
1882 for (i = 1; i < 8; i++) {
1883 sx_table[i].period_ns = round_4((i+1)*d / 100);
1884 sx_table[i].reg_value = (i+1)*0x10;
1885 }
1886 sx_table[7].reg_value = 0;
1887 sx_table[8].period_ns = 0;
1888 sx_table[8].reg_value = 0;
1889}
1890
1891/*
1892 * check and, maybe, map an init- or "clock:"- argument.
1893 */
1894static uchar
1895set_clk_freq(int freq, int *mhz)
1896{
1897 int x = freq;
1898 if (WD33C93_FS_8_10 == freq)
1899 freq = 8;
1900 else if (WD33C93_FS_12_15 == freq)
1901 freq = 12;
1902 else if (WD33C93_FS_16_20 == freq)
1903 freq = 16;
1904 else if (freq > 7 && freq < 11)
1905 x = WD33C93_FS_8_10;
1906 else if (freq > 11 && freq < 16)
1907 x = WD33C93_FS_12_15;
1908 else if (freq > 15 && freq < 21)
1909 x = WD33C93_FS_16_20;
1910 else {
1911 /* Hmm, wouldn't it be safer to assume highest freq here? */
1912 x = WD33C93_FS_8_10;
1913 freq = 8;
1914 }
1915 *mhz = freq;
1916 return x;
1917}
1918
1919/*
1920 * to be used with the resync: fast: ... options
1921 */
1922static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
1923{
1924 int i;
1925 for (i = 0; i < 8; i++)
1926 if (mask & (1 << i))
1927 hd->sync_stat[i] = SS_UNSET;
1928}
1929
1785void 1930void
1786wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, 1931wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1787 dma_setup_t setup, dma_stop_t stop, int clock_freq) 1932 dma_setup_t setup, dma_stop_t stop, int clock_freq)
@@ -1798,7 +1943,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1798 hostdata = (struct WD33C93_hostdata *) instance->hostdata; 1943 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1799 1944
1800 hostdata->regs = regs; 1945 hostdata->regs = regs;
1801 hostdata->clock_freq = clock_freq; 1946 hostdata->clock_freq = set_clk_freq(clock_freq, &i);
1947 calc_sx_table(i, hostdata->sx_table);
1802 hostdata->dma_setup = setup; 1948 hostdata->dma_setup = setup;
1803 hostdata->dma_stop = stop; 1949 hostdata->dma_stop = stop;
1804 hostdata->dma_bounce_buffer = NULL; 1950 hostdata->dma_bounce_buffer = NULL;
@@ -1806,7 +1952,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1806 for (i = 0; i < 8; i++) { 1952 for (i = 0; i < 8; i++) {
1807 hostdata->busy[i] = 0; 1953 hostdata->busy[i] = 0;
1808 hostdata->sync_xfer[i] = 1954 hostdata->sync_xfer[i] =
1809 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); 1955 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1956 0, hostdata->sx_table);
1810 hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ 1957 hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
1811#ifdef PROC_STATISTICS 1958#ifdef PROC_STATISTICS
1812 hostdata->cmd_cnt[i] = 0; 1959 hostdata->cmd_cnt[i] = 0;
@@ -1828,6 +1975,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1828 hostdata->default_sx_per = DEFAULT_SX_PER; 1975 hostdata->default_sx_per = DEFAULT_SX_PER;
1829 hostdata->no_sync = 0xff; /* sync defaults to off */ 1976 hostdata->no_sync = 0xff; /* sync defaults to off */
1830 hostdata->no_dma = 0; /* default is DMA enabled */ 1977 hostdata->no_dma = 0; /* default is DMA enabled */
1978 hostdata->fast = 0; /* default is Fast SCSI transfers disabled */
1979 hostdata->dma_mode = CTRL_DMA; /* default is Single Byte DMA */
1831 1980
1832#ifdef PROC_INTERFACE 1981#ifdef PROC_INTERFACE
1833 hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | 1982 hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
@@ -1839,6 +1988,11 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1839#endif 1988#endif
1840#endif 1989#endif
1841 1990
1991 if (check_setup_args("clock", &flags, &val, buf)) {
1992 hostdata->clock_freq = set_clk_freq(val, &val);
1993 calc_sx_table(val, hostdata->sx_table);
1994 }
1995
1842 if (check_setup_args("nosync", &flags, &val, buf)) 1996 if (check_setup_args("nosync", &flags, &val, buf))
1843 hostdata->no_sync = val; 1997 hostdata->no_sync = val;
1844 1998
@@ -1847,7 +2001,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1847 2001
1848 if (check_setup_args("period", &flags, &val, buf)) 2002 if (check_setup_args("period", &flags, &val, buf))
1849 hostdata->default_sx_per = 2003 hostdata->default_sx_per =
1850 sx_table[round_period((unsigned int) val)].period_ns; 2004 hostdata->sx_table[round_period((unsigned int) val,
2005 hostdata->sx_table)].period_ns;
1851 2006
1852 if (check_setup_args("disconnect", &flags, &val, buf)) { 2007 if (check_setup_args("disconnect", &flags, &val, buf)) {
1853 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) 2008 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
@@ -1862,17 +2017,12 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1862 if (check_setup_args("debug", &flags, &val, buf)) 2017 if (check_setup_args("debug", &flags, &val, buf))
1863 hostdata->args = val & DB_MASK; 2018 hostdata->args = val & DB_MASK;
1864 2019
1865 if (check_setup_args("clock", &flags, &val, buf)) { 2020 if (check_setup_args("burst", &flags, &val, buf))
1866 if (val > 7 && val < 11) 2021 hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
1867 val = WD33C93_FS_8_10; 2022
1868 else if (val > 11 && val < 16) 2023 if (WD33C93_FS_16_20 == hostdata->clock_freq /* divisor 4 */
1869 val = WD33C93_FS_12_15; 2024 && check_setup_args("fast", &flags, &val, buf))
1870 else if (val > 15 && val < 21) 2025 hostdata->fast = !!val;
1871 val = WD33C93_FS_16_20;
1872 else
1873 val = WD33C93_FS_8_10;
1874 hostdata->clock_freq = val;
1875 }
1876 2026
1877 if ((i = check_setup_args("next", &flags, &val, buf))) { 2027 if ((i = check_setup_args("next", &flags, &val, buf))) {
1878 while (i) 2028 while (i)
@@ -1917,53 +2067,65 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
1917 char tbuf[128]; 2067 char tbuf[128];
1918 struct WD33C93_hostdata *hd; 2068 struct WD33C93_hostdata *hd;
1919 struct scsi_cmnd *cmd; 2069 struct scsi_cmnd *cmd;
1920 int x, i; 2070 int x;
1921 static int stop = 0; 2071 static int stop = 0;
1922 2072
1923 hd = (struct WD33C93_hostdata *) instance->hostdata; 2073 hd = (struct WD33C93_hostdata *) instance->hostdata;
1924 2074
1925/* If 'in' is TRUE we need to _read_ the proc file. We accept the following 2075/* If 'in' is TRUE we need to _read_ the proc file. We accept the following
1926 * keywords (same format as command-line, but only ONE per read): 2076 * keywords (same format as command-line, but arguments are not optional):
1927 * debug 2077 * debug
1928 * disconnect 2078 * disconnect
1929 * period 2079 * period
1930 * resync 2080 * resync
1931 * proc 2081 * proc
1932 * nodma 2082 * nodma
2083 * level2
2084 * burst
2085 * fast
2086 * nosync
1933 */ 2087 */
1934 2088
1935 if (in) { 2089 if (in) {
1936 buf[len] = '\0'; 2090 buf[len] = '\0';
1937 bp = buf; 2091 for (bp = buf; *bp; ) {
2092 while (',' == *bp || ' ' == *bp)
2093 ++bp;
1938 if (!strncmp(bp, "debug:", 6)) { 2094 if (!strncmp(bp, "debug:", 6)) {
1939 bp += 6; 2095 hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
1940 hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
1941 } else if (!strncmp(bp, "disconnect:", 11)) { 2096 } else if (!strncmp(bp, "disconnect:", 11)) {
1942 bp += 11; 2097 x = simple_strtoul(bp+11, &bp, 0);
1943 x = simple_strtoul(bp, NULL, 0);
1944 if (x < DIS_NEVER || x > DIS_ALWAYS) 2098 if (x < DIS_NEVER || x > DIS_ALWAYS)
1945 x = DIS_ADAPTIVE; 2099 x = DIS_ADAPTIVE;
1946 hd->disconnect = x; 2100 hd->disconnect = x;
1947 } else if (!strncmp(bp, "period:", 7)) { 2101 } else if (!strncmp(bp, "period:", 7)) {
1948 bp += 7; 2102 x = simple_strtoul(bp+7, &bp, 0);
1949 x = simple_strtoul(bp, NULL, 0);
1950 hd->default_sx_per = 2103 hd->default_sx_per =
1951 sx_table[round_period((unsigned int) x)].period_ns; 2104 hd->sx_table[round_period((unsigned int) x,
2105 hd->sx_table)].period_ns;
1952 } else if (!strncmp(bp, "resync:", 7)) { 2106 } else if (!strncmp(bp, "resync:", 7)) {
1953 bp += 7; 2107 set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
1954 x = simple_strtoul(bp, NULL, 0);
1955 for (i = 0; i < 7; i++)
1956 if (x & (1 << i))
1957 hd->sync_stat[i] = SS_UNSET;
1958 } else if (!strncmp(bp, "proc:", 5)) { 2108 } else if (!strncmp(bp, "proc:", 5)) {
1959 bp += 5; 2109 hd->proc = simple_strtoul(bp+5, &bp, 0);
1960 hd->proc = simple_strtoul(bp, NULL, 0);
1961 } else if (!strncmp(bp, "nodma:", 6)) { 2110 } else if (!strncmp(bp, "nodma:", 6)) {
1962 bp += 6; 2111 hd->no_dma = simple_strtoul(bp+6, &bp, 0);
1963 hd->no_dma = simple_strtoul(bp, NULL, 0);
1964 } else if (!strncmp(bp, "level2:", 7)) { 2112 } else if (!strncmp(bp, "level2:", 7)) {
1965 bp += 7; 2113 hd->level2 = simple_strtoul(bp+7, &bp, 0);
1966 hd->level2 = simple_strtoul(bp, NULL, 0); 2114 } else if (!strncmp(bp, "burst:", 6)) {
2115 hd->dma_mode =
2116 simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
2117 } else if (!strncmp(bp, "fast:", 5)) {
2118 x = !!simple_strtol(bp+5, &bp, 0);
2119 if (x != hd->fast)
2120 set_resync(hd, 0xff);
2121 hd->fast = x;
2122 } else if (!strncmp(bp, "nosync:", 7)) {
2123 x = simple_strtoul(bp+7, &bp, 0);
2124 set_resync(hd, x ^ hd->no_sync);
2125 hd->no_sync = x;
2126 } else {
2127 break; /* unknown keyword,syntax-error,... */
2128 }
1967 } 2129 }
1968 return len; 2130 return len;
1969 } 2131 }
@@ -1977,8 +2139,9 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off
1977 strcat(bp, tbuf); 2139 strcat(bp, tbuf);
1978 } 2140 }
1979 if (hd->proc & PR_INFO) { 2141 if (hd->proc & PR_INFO) {
1980 sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d", 2142 sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
1981 hd->clock_freq, hd->no_sync, hd->no_dma); 2143 " dma_mode=%02x fast=%d",
2144 hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
1982 strcat(bp, tbuf); 2145 strcat(bp, tbuf);
1983 strcat(bp, "\nsync_xfer[] = "); 2146 strcat(bp, "\nsync_xfer[] = ");
1984 for (x = 0; x < 7; x++) { 2147 for (x = 0; x < 7; x++) {
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index edcb0365cf0c..61ffb860dacc 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -155,6 +155,9 @@
155#define WD33C93_FS_12_15 OWNID_FS_12 155#define WD33C93_FS_12_15 OWNID_FS_12
156#define WD33C93_FS_16_20 OWNID_FS_16 156#define WD33C93_FS_16_20 OWNID_FS_16
157 157
158 /* pass input-clock explicitely. accepted mhz values are 8-10,12-20 */
159#define WD33C93_FS_MHZ(mhz) (mhz)
160
158 /* Control register */ 161 /* Control register */
159#define CTRL_HSP 0x01 162#define CTRL_HSP 0x01
160#define CTRL_HA 0x02 163#define CTRL_HA 0x02
@@ -253,6 +256,9 @@ struct WD33C93_hostdata {
253 uchar sync_stat[8]; /* status of sync negotiation per target */ 256 uchar sync_stat[8]; /* status of sync negotiation per target */
254 uchar no_sync; /* bitmask: don't do sync on these targets */ 257 uchar no_sync; /* bitmask: don't do sync on these targets */
255 uchar no_dma; /* set this flag to disable DMA */ 258 uchar no_dma; /* set this flag to disable DMA */
259 uchar dma_mode; /* DMA Burst Mode or Single Byte DMA */
260 uchar fast; /* set this flag to enable Fast SCSI */
261 struct sx_period sx_table[9]; /* transfer periods for actual DTC-setting */
256#ifdef PROC_INTERFACE 262#ifdef PROC_INTERFACE
257 uchar proc; /* bitmask: what's in proc output */ 263 uchar proc; /* bitmask: what's in proc output */
258#ifdef PROC_STATISTICS 264#ifdef PROC_STATISTICS