diff options
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 144 |
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 | |||
| 51 | static struct ata_device * | 51 | static struct ata_device * |
| 52 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); | 52 | ata_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 | |||
| 64 | static 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 | |||
| 75 | static 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 | |||
| 84 | static 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 | ||
| 55 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, | 94 | static 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, | |||
| 1583 | static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, | 1622 | static 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 | ||
| 1614 | static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) | 1649 | static 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 | ||
| 1639 | static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) | 1668 | static 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 | ||
| 1732 | invalid_fld: | 1794 | invalid_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 | */ |
| 2158 | static unsigned int | 2220 | static unsigned int |
| 2159 | ata_scsi_pass_thru(struct ata_queued_cmd *qc, u8 *scsicmd) | 2221 | ata_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; |
