aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-scsi.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dougg@torque.net>2005-10-28 15:58:28 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-28 15:58:28 -0400
commit00ac37f508689da281586c7ef304f26b5138d8a6 (patch)
tree409c2367a5630d860fa0d30b60c1fc6ea9ad659f /drivers/scsi/libata-scsi.c
parenta21a84a375ea3783cf9a53730d643c4db24371bc (diff)
[libata scsi] MODE SELECT, strengthen mode sense
- move default mode pages to the front of libata-scsi.c so various functions can access them - partial annotation of these pages, point out divergence from sat-r06 - replace various mode page magic numbers with defines - strengthen MODE SENSE command decoding: handle DBD bit in cdb, yield block descriptor (per sat-r06) and handle mode sub pages Signed-off-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r--drivers/scsi/libata-scsi.c144
1 files changed, 103 insertions, 41 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index b761bd1b9717..89a04b1a5a0e 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -51,6 +51,45 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scs
51static struct ata_device * 51static struct ata_device *
52ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); 52ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
53 53
54#define RW_RECOVERY_MPAGE 0x1
55#define RW_RECOVERY_MPAGE_LEN 12
56#define CACHE_MPAGE 0x8
57#define CACHE_MPAGE_LEN 20
58#define CONTROL_MPAGE 0xa
59#define CONTROL_MPAGE_LEN 12
60#define ALL_MPAGES 0x3f
61#define ALL_SUB_MPAGES 0xff
62
63
64static const u8 def_rw_recovery_mpage[] = {
65 RW_RECOVERY_MPAGE,
66 RW_RECOVERY_MPAGE_LEN - 2,
67 (1 << 7) | /* AWRE, sat-r06 say it shall be 0 */
68 (1 << 6), /* ARRE (auto read reallocation) */
69 0, /* read retry count */
70 0, 0, 0, 0,
71 0, /* write retry count */
72 0, 0, 0
73};
74
75static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = {
76 CACHE_MPAGE,
77 CACHE_MPAGE_LEN - 2,
78 0, /* contains WCE, needs to be 0 for logic */
79 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, /* contains DRA, needs to be 0 for logic */
81 0, 0, 0, 0, 0, 0, 0
82};
83
84static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
85 CONTROL_MPAGE,
86 CONTROL_MPAGE_LEN - 2,
87 2, /* DSENSE=0, GLTSD=1 */
88 0, /* [QAM+QERR may be 1, see 05-359r1] */
89 0, 0, 0, 0, 0xff, 0xff,
90 0, 30 /* extended self test time, see 05-359r1 */
91};
92
54 93
55static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, 94static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
56 void (*done)(struct scsi_cmnd *)) 95 void (*done)(struct scsi_cmnd *))
@@ -1583,13 +1622,9 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
1583static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, 1622static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
1584 const u8 *last) 1623 const u8 *last)
1585{ 1624{
1586 u8 page[] = { 1625 u8 page[CACHE_MPAGE_LEN];
1587 0x8, /* page code */
1588 0x12, /* page length */
1589 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 zeroes */
1590 0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */
1591 };
1592 1626
1627 memcpy(page, def_cache_mpage, sizeof(page));
1593 if (ata_id_wcache_enabled(id)) 1628 if (ata_id_wcache_enabled(id))
1594 page[2] |= (1 << 2); /* write cache enable */ 1629 page[2] |= (1 << 2); /* write cache enable */
1595 if (!ata_id_rahead_enabled(id)) 1630 if (!ata_id_rahead_enabled(id))
@@ -1613,15 +1648,9 @@ static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
1613 1648
1614static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) 1649static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
1615{ 1650{
1616 const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30}; 1651 ata_msense_push(ptr_io, last, def_control_mpage,
1617 1652 sizeof(def_control_mpage));
1618 /* byte 2: set the descriptor format sense data bit (bit 2) 1653 return sizeof(def_control_mpage);
1619 * since we need to support returning this format for SAT
1620 * commands and any SCSI commands against a 48b LBA device.
1621 */
1622
1623 ata_msense_push(ptr_io, last, page, sizeof(page));
1624 return sizeof(page);
1625} 1654}
1626 1655
1627/** 1656/**
@@ -1638,15 +1667,10 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
1638 1667
1639static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) 1668static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
1640{ 1669{
1641 const u8 page[] = {
1642 0x1, /* page code */
1643 0xa, /* page length */
1644 (1 << 7) | (1 << 6), /* note auto r/w reallocation */
1645 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
1646 };
1647 1670
1648 ata_msense_push(ptr_io, last, page, sizeof(page)); 1671 ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
1649 return sizeof(page); 1672 sizeof(def_rw_recovery_mpage));
1673 return sizeof(def_rw_recovery_mpage);
1650} 1674}
1651 1675
1652/** 1676/**
@@ -1655,7 +1679,9 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
1655 * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. 1679 * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
1656 * @buflen: Response buffer length. 1680 * @buflen: Response buffer length.
1657 * 1681 *
1658 * Simulate MODE SENSE commands. 1682 * Simulate MODE SENSE commands. Assume this is invoked for direct
1683 * access devices (e.g. disks) only. There should be no block
1684 * descriptor for other device types.
1659 * 1685 *
1660 * LOCKING: 1686 * LOCKING:
1661 * spin_lock_irqsave(host_set lock) 1687 * spin_lock_irqsave(host_set lock)
@@ -1665,15 +1691,22 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
1665 unsigned int buflen) 1691 unsigned int buflen)
1666{ 1692{
1667 u8 *scsicmd = args->cmd->cmnd, *p, *last; 1693 u8 *scsicmd = args->cmd->cmnd, *p, *last;
1668 unsigned int page_control, six_byte, output_len; 1694 const u8 sat_blk_desc[] = {
1695 0, 0, 0, 0, /* number of blocks: sat unspecified */
1696 0,
1697 0, 0x2, 0x0 /* block length: 512 bytes */
1698 };
1699 u8 pg, spg;
1700 unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
1669 1701
1670 VPRINTK("ENTER\n"); 1702 VPRINTK("ENTER\n");
1671 1703
1672 six_byte = (scsicmd[0] == MODE_SENSE); 1704 six_byte = (scsicmd[0] == MODE_SENSE);
1673 1705 ebd = !(scsicmd[1] & 0x8); /* dbd bit inverted == edb */
1674 /* we only support saved and current values (which we treat 1706 /*
1675 * in the same manner) 1707 * LLBA bit in msense(10) ignored (compliant)
1676 */ 1708 */
1709
1677 page_control = scsicmd[2] >> 6; 1710 page_control = scsicmd[2] >> 6;
1678 switch (page_control) { 1711 switch (page_control) {
1679 case 0: /* current */ 1712 case 0: /* current */
@@ -1686,29 +1719,42 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
1686 goto invalid_fld; 1719 goto invalid_fld;
1687 } 1720 }
1688 1721
1689 if (six_byte) 1722 if (six_byte) {
1690 output_len = 4; 1723 output_len = 4 + (ebd ? 8 : 0);
1691 else 1724 alloc_len = scsicmd[4];
1692 output_len = 8; 1725 } else {
1726 output_len = 8 + (ebd ? 8 : 0);
1727 alloc_len = (scsicmd[7] << 8) + scsicmd[8];
1728 }
1729 minlen = (alloc_len < buflen) ? alloc_len : buflen;
1693 1730
1694 p = rbuf + output_len; 1731 p = rbuf + output_len;
1695 last = rbuf + buflen - 1; 1732 last = rbuf + minlen - 1;
1696 1733
1697 switch(scsicmd[2] & 0x3f) { 1734 pg = scsicmd[2] & 0x3f;
1698 case 0x01: /* r/w error recovery */ 1735 spg = scsicmd[3];
1736 /*
1737 * No mode subpages supported (yet) but asking for _all_
1738 * subpages may be valid
1739 */
1740 if (spg && (spg != ALL_SUB_MPAGES))
1741 goto invalid_fld;
1742
1743 switch(pg) {
1744 case RW_RECOVERY_MPAGE:
1699 output_len += ata_msense_rw_recovery(&p, last); 1745 output_len += ata_msense_rw_recovery(&p, last);
1700 break; 1746 break;
1701 1747
1702 case 0x08: /* caching */ 1748 case CACHE_MPAGE:
1703 output_len += ata_msense_caching(args->id, &p, last); 1749 output_len += ata_msense_caching(args->id, &p, last);
1704 break; 1750 break;
1705 1751
1706 case 0x0a: { /* control mode */ 1752 case CONTROL_MPAGE: {
1707 output_len += ata_msense_ctl_mode(&p, last); 1753 output_len += ata_msense_ctl_mode(&p, last);
1708 break; 1754 break;
1709 } 1755 }
1710 1756
1711 case 0x3f: /* all pages */ 1757 case ALL_MPAGES:
1712 output_len += ata_msense_rw_recovery(&p, last); 1758 output_len += ata_msense_rw_recovery(&p, last);
1713 output_len += ata_msense_caching(args->id, &p, last); 1759 output_len += ata_msense_caching(args->id, &p, last);
1714 output_len += ata_msense_ctl_mode(&p, last); 1760 output_len += ata_msense_ctl_mode(&p, last);
@@ -1718,15 +1764,31 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
1718 goto invalid_fld; 1764 goto invalid_fld;
1719 } 1765 }
1720 1766
1767 if (minlen < 1)
1768 return 0;
1721 if (six_byte) { 1769 if (six_byte) {
1722 output_len--; 1770 output_len--;
1723 rbuf[0] = output_len; 1771 rbuf[0] = output_len;
1772 if (ebd) {
1773 if (minlen > 3)
1774 rbuf[3] = sizeof(sat_blk_desc);
1775 if (minlen > 11)
1776 memcpy(rbuf + 4, sat_blk_desc,
1777 sizeof(sat_blk_desc));
1778 }
1724 } else { 1779 } else {
1725 output_len -= 2; 1780 output_len -= 2;
1726 rbuf[0] = output_len >> 8; 1781 rbuf[0] = output_len >> 8;
1727 rbuf[1] = output_len; 1782 if (minlen > 1)
1783 rbuf[1] = output_len;
1784 if (ebd) {
1785 if (minlen > 7)
1786 rbuf[7] = sizeof(sat_blk_desc);
1787 if (minlen > 15)
1788 memcpy(rbuf + 8, sat_blk_desc,
1789 sizeof(sat_blk_desc));
1790 }
1728 } 1791 }
1729
1730 return 0; 1792 return 0;
1731 1793
1732invalid_fld: 1794invalid_fld:
@@ -2156,7 +2218,7 @@ ata_scsi_map_proto(u8 byte1)
2156 * Zero on success, non-zero on failure. 2218 * Zero on success, non-zero on failure.
2157 */ 2219 */
2158static unsigned int 2220static unsigned int
2159ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd) 2221ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
2160{ 2222{
2161 struct ata_taskfile *tf = &(qc->tf); 2223 struct ata_taskfile *tf = &(qc->tf);
2162 struct scsi_cmnd *cmd = qc->scsicmd; 2224 struct scsi_cmnd *cmd = qc->scsicmd;