aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_spi.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-01-17 10:29:06 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-01-17 10:29:06 -0500
commitea9b395fe20ac74be788f415af2622ac8f0c35c7 (patch)
treed1653e1a4cbe360aa7132ea4e29ab92a02038224 /drivers/scsi/scsi_transport_spi.c
parent61420e147a706ee7c7a902008045547fb2a2a330 (diff)
parent1bc4ccfff8675adc3d96f91245eb7e2dc0043ca9 (diff)
Merge branch 'upstream'
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r--drivers/scsi/scsi_transport_spi.c146
1 files changed, 137 insertions, 9 deletions
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 38a53b5f9e9a..7ee95eb83dda 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -18,12 +18,13 @@
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21#include <linux/config.h>
21#include <linux/ctype.h> 22#include <linux/ctype.h>
22#include <linux/init.h> 23#include <linux/init.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/workqueue.h> 25#include <linux/workqueue.h>
25#include <linux/blkdev.h> 26#include <linux/blkdev.h>
26#include <asm/semaphore.h> 27#include <linux/mutex.h>
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
28#include "scsi_priv.h" 29#include "scsi_priv.h"
29#include <scsi/scsi_device.h> 30#include <scsi/scsi_device.h>
@@ -47,7 +48,7 @@
47 48
48/* Private data accessors (keep these out of the header file) */ 49/* Private data accessors (keep these out of the header file) */
49#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending) 50#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
50#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem) 51#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
51 52
52struct spi_internal { 53struct spi_internal {
53 struct scsi_transport_template t; 54 struct scsi_transport_template t;
@@ -241,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
241 spi_hold_mcs(starget) = 0; 242 spi_hold_mcs(starget) = 0;
242 spi_dv_pending(starget) = 0; 243 spi_dv_pending(starget) = 0;
243 spi_initial_dv(starget) = 0; 244 spi_initial_dv(starget) = 0;
244 init_MUTEX(&spi_dv_sem(starget)); 245 mutex_init(&spi_dv_mutex(starget));
245 246
246 return 0; 247 return 0;
247} 248}
@@ -378,9 +379,7 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
378 379
379/* Translate the period into ns according to the current spec 380/* Translate the period into ns according to the current spec
380 * for SDTR/PPR messages */ 381 * for SDTR/PPR messages */
381static ssize_t 382static int period_to_str(char *buf, int period)
382show_spi_transport_period_helper(struct class_device *cdev, char *buf,
383 int period)
384{ 383{
385 int len, picosec; 384 int len, picosec;
386 385
@@ -398,6 +397,14 @@ show_spi_transport_period_helper(struct class_device *cdev, char *buf,
398 len = sprint_frac(buf, picosec, 1000); 397 len = sprint_frac(buf, picosec, 1000);
399 } 398 }
400 399
400 return len;
401}
402
403static ssize_t
404show_spi_transport_period_helper(struct class_device *cdev, char *buf,
405 int period)
406{
407 int len = period_to_str(buf, period);
401 buf[len++] = '\n'; 408 buf[len++] = '\n';
402 buf[len] = '\0'; 409 buf[len] = '\0';
403 return len; 410 return len;
@@ -908,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev)
908 scsi_target_quiesce(starget); 915 scsi_target_quiesce(starget);
909 916
910 spi_dv_pending(starget) = 1; 917 spi_dv_pending(starget) = 1;
911 down(&spi_dv_sem(starget)); 918 mutex_lock(&spi_dv_mutex(starget));
912 919
913 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n"); 920 starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");
914 921
@@ -916,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev)
916 923
917 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n"); 924 starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");
918 925
919 up(&spi_dv_sem(starget)); 926 mutex_unlock(&spi_dv_mutex(starget));
920 spi_dv_pending(starget) = 0; 927 spi_dv_pending(starget) = 0;
921 928
922 scsi_target_resume(starget); 929 scsi_target_resume(starget);
@@ -1041,12 +1048,133 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
1041 tp->hold_mcs ? " HMCS" : "", 1048 tp->hold_mcs ? " HMCS" : "",
1042 tmp, tp->offset); 1049 tmp, tp->offset);
1043 } else { 1050 } else {
1044 dev_info(&starget->dev, "%sasynchronous.\n", 1051 dev_info(&starget->dev, "%sasynchronous\n",
1045 tp->width ? "wide " : ""); 1052 tp->width ? "wide " : "");
1046 } 1053 }
1047} 1054}
1048EXPORT_SYMBOL(spi_display_xfer_agreement); 1055EXPORT_SYMBOL(spi_display_xfer_agreement);
1049 1056
1057#ifdef CONFIG_SCSI_CONSTANTS
1058static const char * const one_byte_msgs[] = {
1059/* 0x00 */ "Command Complete", NULL, "Save Pointers",
1060/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error",
1061/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
1062/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
1063/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue",
1064/* 0x0f */ "Initiate Recovery", "Release Recovery"
1065};
1066
1067static const char * const two_byte_msgs[] = {
1068/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag",
1069/* 0x23 */ "Ignore Wide Residue"
1070};
1071
1072static const char * const extended_msgs[] = {
1073/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
1074/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request",
1075/* 0x04 */ "Parallel Protocol Request"
1076};
1077
1078static void print_nego(const unsigned char *msg, int per, int off, int width)
1079{
1080 if (per) {
1081 char buf[20];
1082 period_to_str(buf, msg[per]);
1083 printk("period = %s ns ", buf);
1084 }
1085
1086 if (off)
1087 printk("offset = %d ", msg[off]);
1088 if (width)
1089 printk("width = %d ", 8 << msg[width]);
1090}
1091
1092int spi_print_msg(const unsigned char *msg)
1093{
1094 int len = 0, i;
1095 if (msg[0] == EXTENDED_MESSAGE) {
1096 len = 3 + msg[1];
1097 if (msg[2] < ARRAY_SIZE(extended_msgs))
1098 printk ("%s ", extended_msgs[msg[2]]);
1099 else
1100 printk ("Extended Message, reserved code (0x%02x) ",
1101 (int) msg[2]);
1102 switch (msg[2]) {
1103 case EXTENDED_MODIFY_DATA_POINTER:
1104 printk("pointer = %d", (int) (msg[3] << 24) |
1105 (msg[4] << 16) | (msg[5] << 8) | msg[6]);
1106 break;
1107 case EXTENDED_SDTR:
1108 print_nego(msg, 3, 4, 0);
1109 break;
1110 case EXTENDED_WDTR:
1111 print_nego(msg, 0, 0, 3);
1112 break;
1113 case EXTENDED_PPR:
1114 print_nego(msg, 3, 5, 6);
1115 break;
1116 default:
1117 for (i = 2; i < len; ++i)
1118 printk("%02x ", msg[i]);
1119 }
1120 /* Identify */
1121 } else if (msg[0] & 0x80) {
1122 printk("Identify disconnect %sallowed %s %d ",
1123 (msg[0] & 0x40) ? "" : "not ",
1124 (msg[0] & 0x20) ? "target routine" : "lun",
1125 msg[0] & 0x7);
1126 len = 1;
1127 /* Normal One byte */
1128 } else if (msg[0] < 0x1f) {
1129 if (msg[0] < ARRAY_SIZE(one_byte_msgs))
1130 printk(one_byte_msgs[msg[0]]);
1131 else
1132 printk("reserved (%02x) ", msg[0]);
1133 len = 1;
1134 /* Two byte */
1135 } else if (msg[0] <= 0x2f) {
1136 if ((msg[0] - 0x20) < ARRAY_SIZE(two_byte_msgs))
1137 printk("%s %02x ", two_byte_msgs[msg[0] - 0x20],
1138 msg[1]);
1139 else
1140 printk("reserved two byte (%02x %02x) ",
1141 msg[0], msg[1]);
1142 len = 2;
1143 } else
1144 printk("reserved");
1145 return len;
1146}
1147EXPORT_SYMBOL(spi_print_msg);
1148
1149#else /* ifndef CONFIG_SCSI_CONSTANTS */
1150
1151int spi_print_msg(const unsigned char *msg)
1152{
1153 int len = 0, i;
1154
1155 if (msg[0] == EXTENDED_MESSAGE) {
1156 len = 3 + msg[1];
1157 for (i = 0; i < len; ++i)
1158 printk("%02x ", msg[i]);
1159 /* Identify */
1160 } else if (msg[0] & 0x80) {
1161 printk("%02x ", msg[0]);
1162 len = 1;
1163 /* Normal One byte */
1164 } else if (msg[0] < 0x1f) {
1165 printk("%02x ", msg[0]);
1166 len = 1;
1167 /* Two byte */
1168 } else if (msg[0] <= 0x2f) {
1169 printk("%02x %02x", msg[0], msg[1]);
1170 len = 2;
1171 } else
1172 printk("%02x ", msg[0]);
1173 return len;
1174}
1175EXPORT_SYMBOL(spi_print_msg);
1176#endif /* ! CONFIG_SCSI_CONSTANTS */
1177
1050#define SETUP_ATTRIBUTE(field) \ 1178#define SETUP_ATTRIBUTE(field) \
1051 i->private_attrs[count] = class_device_attr_##field; \ 1179 i->private_attrs[count] = class_device_attr_##field; \
1052 if (!i->f->set_##field) { \ 1180 if (!i->f->set_##field) { \