diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2006-01-17 10:29:06 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-01-17 10:29:06 -0500 |
commit | ea9b395fe20ac74be788f415af2622ac8f0c35c7 (patch) | |
tree | d1653e1a4cbe360aa7132ea4e29ab92a02038224 /drivers/scsi/scsi_transport_spi.c | |
parent | 61420e147a706ee7c7a902008045547fb2a2a330 (diff) | |
parent | 1bc4ccfff8675adc3d96f91245eb7e2dc0043ca9 (diff) |
Merge branch 'upstream'
Diffstat (limited to 'drivers/scsi/scsi_transport_spi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_spi.c | 146 |
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 | ||
52 | struct spi_internal { | 53 | struct 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 */ |
381 | static ssize_t | 382 | static int period_to_str(char *buf, int period) |
382 | show_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 | |||
403 | static ssize_t | ||
404 | show_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 | } |
1048 | EXPORT_SYMBOL(spi_display_xfer_agreement); | 1055 | EXPORT_SYMBOL(spi_display_xfer_agreement); |
1049 | 1056 | ||
1057 | #ifdef CONFIG_SCSI_CONSTANTS | ||
1058 | static 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 | |||
1067 | static 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 | |||
1072 | static 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 | |||
1078 | static 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 | |||
1092 | int 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 | } | ||
1147 | EXPORT_SYMBOL(spi_print_msg); | ||
1148 | |||
1149 | #else /* ifndef CONFIG_SCSI_CONSTANTS */ | ||
1150 | |||
1151 | int 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 | } | ||
1175 | EXPORT_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) { \ |