X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_transport_spi.c;h=46da6fe10ad54d1d25dc1784071365d8fe288287;hb=29552b1462799afbe02af035b243e97579d63350;hp=718a2bc4ed5e6fcbe777637661bdc08769691c5e;hpb=fecb4a0c87c2bcaee1f3cf800126eef752a07ed3;p=powerpc.git diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 718a2bc4ed..46da6fe10a 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -18,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -378,9 +379,7 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate); /* Translate the period into ns according to the current spec * for SDTR/PPR messages */ -static ssize_t -show_spi_transport_period_helper(struct class_device *cdev, char *buf, - int period) +static int period_to_str(char *buf, int period) { int len, picosec; @@ -398,6 +397,14 @@ show_spi_transport_period_helper(struct class_device *cdev, char *buf, len = sprint_frac(buf, picosec, 1000); } + return len; +} + +static ssize_t +show_spi_transport_period_helper(struct class_device *cdev, char *buf, + int period) +{ + int len = period_to_str(buf, period); buf[len++] = '\n'; buf[len] = '\0'; return len; @@ -812,12 +819,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) return; - /* see if the device has an echo buffer. If it does we can - * do the SPI pattern write tests */ - - len = 0; - if (scsi_device_dt(sdev)) - len = spi_dv_device_get_echo_buffer(sdev, buffer); + /* len == -1 is the signal that we need to ascertain the + * presence of an echo buffer before trying to use it. len == + * 0 means we don't have an echo buffer */ + len = -1; retry: @@ -840,11 +845,23 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) if (spi_min_period(starget) == 8) DV_SET(pcomp_en, 1); } + /* Do the read only INQUIRY tests */ + spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, + spi_dv_device_compare_inquiry); + /* See if we actually managed to negotiate and sustain DT */ + if (i->f->get_dt) + i->f->get_dt(starget); + + /* see if the device has an echo buffer. If it does we can do + * the SPI pattern write tests. Because of some broken + * devices, we *only* try this on a device that has actually + * negotiated DT */ + + if (len == -1 && spi_dt(starget)) + len = spi_dv_device_get_echo_buffer(sdev, buffer); - if (len == 0) { + if (len <= 0) { starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n"); - spi_dv_retrain(sdev, buffer, buffer + len, - spi_dv_device_compare_inquiry); return; } @@ -1031,12 +1048,133 @@ void spi_display_xfer_agreement(struct scsi_target *starget) tp->hold_mcs ? " HMCS" : "", tmp, tp->offset); } else { - dev_info(&starget->dev, "%sasynchronous.\n", + dev_info(&starget->dev, "%sasynchronous\n", tp->width ? "wide " : ""); } } EXPORT_SYMBOL(spi_display_xfer_agreement); +#ifdef CONFIG_SCSI_CONSTANTS +static const char * const one_byte_msgs[] = { +/* 0x00 */ "Command Complete", NULL, "Save Pointers", +/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", +/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error", +/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag", +/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", +/* 0x0f */ "Initiate Recovery", "Release Recovery" +}; + +static const char * const two_byte_msgs[] = { +/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag", +/* 0x23 */ "Ignore Wide Residue" +}; + +static const char * const extended_msgs[] = { +/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request", +/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request", +/* 0x04 */ "Parallel Protocol Request" +}; + +void print_nego(const unsigned char *msg, int per, int off, int width) +{ + if (per) { + char buf[20]; + period_to_str(buf, msg[per]); + printk("period = %s ns ", buf); + } + + if (off) + printk("offset = %d ", msg[off]); + if (width) + printk("width = %d ", 8 << msg[width]); +} + +int spi_print_msg(const unsigned char *msg) +{ + int len = 0, i; + if (msg[0] == EXTENDED_MESSAGE) { + len = 3 + msg[1]; + if (msg[2] < ARRAY_SIZE(extended_msgs)) + printk ("%s ", extended_msgs[msg[2]]); + else + printk ("Extended Message, reserved code (0x%02x) ", + (int) msg[2]); + switch (msg[2]) { + case EXTENDED_MODIFY_DATA_POINTER: + printk("pointer = %d", (int) (msg[3] << 24) | + (msg[4] << 16) | (msg[5] << 8) | msg[6]); + break; + case EXTENDED_SDTR: + print_nego(msg, 3, 4, 0); + break; + case EXTENDED_WDTR: + print_nego(msg, 0, 0, 3); + break; + case EXTENDED_PPR: + print_nego(msg, 3, 5, 6); + break; + default: + for (i = 2; i < len; ++i) + printk("%02x ", msg[i]); + } + /* Identify */ + } else if (msg[0] & 0x80) { + printk("Identify disconnect %sallowed %s %d ", + (msg[0] & 0x40) ? "" : "not ", + (msg[0] & 0x20) ? "target routine" : "lun", + msg[0] & 0x7); + len = 1; + /* Normal One byte */ + } else if (msg[0] < 0x1f) { + if (msg[0] < ARRAY_SIZE(one_byte_msgs)) + printk(one_byte_msgs[msg[0]]); + else + printk("reserved (%02x) ", msg[0]); + len = 1; + /* Two byte */ + } else if (msg[0] <= 0x2f) { + if ((msg[0] - 0x20) < ARRAY_SIZE(two_byte_msgs)) + printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], + msg[1]); + else + printk("reserved two byte (%02x %02x) ", + msg[0], msg[1]); + len = 2; + } else + printk("reserved"); + return len; +} +EXPORT_SYMBOL(spi_print_msg); + +#else /* ifndef CONFIG_SCSI_CONSTANTS */ + +int spi_print_msg(const unsigned char *msg) +{ + int len = 0, i; + + if (msg[0] == EXTENDED_MESSAGE) { + len = 3 + msg[1]; + for (i = 0; i < len; ++i) + printk("%02x ", msg[i]); + /* Identify */ + } else if (msg[0] & 0x80) { + printk("%02x ", msg[0]); + len = 1; + /* Normal One byte */ + } else if (msg[0] < 0x1f) { + printk("%02x ", msg[0]); + len = 1; + /* Two byte */ + } else if (msg[0] <= 0x2f) { + printk("%02x %02x", msg[0], msg[1]); + len = 2; + } else + printk("%02x ", msg[0]); + return len; +} +EXPORT_SYMBOL(spi_print_msg); +#endif /* ! CONFIG_SCSI_CONSTANTS */ + #define SETUP_ATTRIBUTE(field) \ i->private_attrs[count] = class_device_attr_##field; \ if (!i->f->set_##field) { \