diff options
Diffstat (limited to 'drivers/ieee1394/sbp2.c')
-rw-r--r-- | drivers/ieee1394/sbp2.c | 355 |
1 files changed, 178 insertions, 177 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 5b9d03e93514..14b0c35ee9a4 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -1707,26 +1707,184 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) | |||
1707 | return 0; | 1707 | return 0; |
1708 | } | 1708 | } |
1709 | 1709 | ||
1710 | static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, | ||
1711 | struct sbp2scsi_host_info *hi, | ||
1712 | struct sbp2_command_info *command, | ||
1713 | unsigned int scsi_use_sg, | ||
1714 | struct scatterlist *sgpnt, | ||
1715 | u32 orb_direction, | ||
1716 | enum dma_data_direction dma_dir) | ||
1717 | { | ||
1718 | command->dma_dir = dma_dir; | ||
1719 | orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1720 | orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1721 | |||
1722 | /* Special case if only one element (and less than 64KB in size) */ | ||
1723 | if ((scsi_use_sg == 1) && | ||
1724 | (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) { | ||
1725 | |||
1726 | SBP2_DEBUG("Only one s/g element"); | ||
1727 | command->dma_size = sgpnt[0].length; | ||
1728 | command->dma_type = CMD_DMA_PAGE; | ||
1729 | command->cmd_dma = pci_map_page(hi->host->pdev, | ||
1730 | sgpnt[0].page, | ||
1731 | sgpnt[0].offset, | ||
1732 | command->dma_size, | ||
1733 | command->dma_dir); | ||
1734 | SBP2_DMA_ALLOC("single page scatter element"); | ||
1735 | |||
1736 | orb->data_descriptor_lo = command->cmd_dma; | ||
1737 | orb->misc |= ORB_SET_DATA_SIZE(command->dma_size); | ||
1738 | |||
1739 | } else { | ||
1740 | struct sbp2_unrestricted_page_table *sg_element = | ||
1741 | &command->scatter_gather_element[0]; | ||
1742 | u32 sg_count, sg_len; | ||
1743 | dma_addr_t sg_addr; | ||
1744 | int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, | ||
1745 | dma_dir); | ||
1746 | |||
1747 | SBP2_DMA_ALLOC("scatter list"); | ||
1748 | |||
1749 | command->dma_size = scsi_use_sg; | ||
1750 | command->sge_buffer = sgpnt; | ||
1751 | |||
1752 | /* use page tables (s/g) */ | ||
1753 | orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | ||
1754 | orb->data_descriptor_lo = command->sge_dma; | ||
1755 | |||
1756 | /* | ||
1757 | * Loop through and fill out our sbp-2 page tables | ||
1758 | * (and split up anything too large) | ||
1759 | */ | ||
1760 | for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) { | ||
1761 | sg_len = sg_dma_len(sgpnt); | ||
1762 | sg_addr = sg_dma_address(sgpnt); | ||
1763 | while (sg_len) { | ||
1764 | sg_element[sg_count].segment_base_lo = sg_addr; | ||
1765 | if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1766 | sg_element[sg_count].length_segment_base_hi = | ||
1767 | PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | ||
1768 | sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1769 | sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1770 | } else { | ||
1771 | sg_element[sg_count].length_segment_base_hi = | ||
1772 | PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | ||
1773 | sg_len = 0; | ||
1774 | } | ||
1775 | sg_count++; | ||
1776 | } | ||
1777 | } | ||
1778 | |||
1779 | /* Number of page table (s/g) elements */ | ||
1780 | orb->misc |= ORB_SET_DATA_SIZE(sg_count); | ||
1781 | |||
1782 | sbp2util_packet_dump(sg_element, | ||
1783 | (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | ||
1784 | "sbp2 s/g list", command->sge_dma); | ||
1785 | |||
1786 | /* Byte swap page tables if necessary */ | ||
1787 | sbp2util_cpu_to_be32_buffer(sg_element, | ||
1788 | (sizeof(struct sbp2_unrestricted_page_table)) * | ||
1789 | sg_count); | ||
1790 | } | ||
1791 | } | ||
1792 | |||
1793 | static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb, | ||
1794 | struct sbp2scsi_host_info *hi, | ||
1795 | struct sbp2_command_info *command, | ||
1796 | struct scatterlist *sgpnt, | ||
1797 | u32 orb_direction, | ||
1798 | unsigned int scsi_request_bufflen, | ||
1799 | void *scsi_request_buffer, | ||
1800 | enum dma_data_direction dma_dir) | ||
1801 | { | ||
1802 | command->dma_dir = dma_dir; | ||
1803 | command->dma_size = scsi_request_bufflen; | ||
1804 | command->dma_type = CMD_DMA_SINGLE; | ||
1805 | command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer, | ||
1806 | command->dma_size, command->dma_dir); | ||
1807 | orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1808 | orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1809 | |||
1810 | SBP2_DMA_ALLOC("single bulk"); | ||
1811 | |||
1812 | /* | ||
1813 | * Handle case where we get a command w/o s/g enabled (but | ||
1814 | * check for transfers larger than 64K) | ||
1815 | */ | ||
1816 | if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1817 | |||
1818 | orb->data_descriptor_lo = command->cmd_dma; | ||
1819 | orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen); | ||
1820 | |||
1821 | } else { | ||
1822 | struct sbp2_unrestricted_page_table *sg_element = | ||
1823 | &command->scatter_gather_element[0]; | ||
1824 | u32 sg_count, sg_len; | ||
1825 | dma_addr_t sg_addr; | ||
1826 | |||
1827 | /* | ||
1828 | * Need to turn this into page tables, since the | ||
1829 | * buffer is too large. | ||
1830 | */ | ||
1831 | orb->data_descriptor_lo = command->sge_dma; | ||
1832 | |||
1833 | /* Use page tables (s/g) */ | ||
1834 | orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | ||
1835 | |||
1836 | /* | ||
1837 | * fill out our sbp-2 page tables (and split up | ||
1838 | * the large buffer) | ||
1839 | */ | ||
1840 | sg_count = 0; | ||
1841 | sg_len = scsi_request_bufflen; | ||
1842 | sg_addr = command->cmd_dma; | ||
1843 | while (sg_len) { | ||
1844 | sg_element[sg_count].segment_base_lo = sg_addr; | ||
1845 | if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1846 | sg_element[sg_count].length_segment_base_hi = | ||
1847 | PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | ||
1848 | sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1849 | sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1850 | } else { | ||
1851 | sg_element[sg_count].length_segment_base_hi = | ||
1852 | PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | ||
1853 | sg_len = 0; | ||
1854 | } | ||
1855 | sg_count++; | ||
1856 | } | ||
1857 | |||
1858 | /* Number of page table (s/g) elements */ | ||
1859 | orb->misc |= ORB_SET_DATA_SIZE(sg_count); | ||
1860 | |||
1861 | sbp2util_packet_dump(sg_element, | ||
1862 | (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | ||
1863 | "sbp2 s/g list", command->sge_dma); | ||
1864 | |||
1865 | /* Byte swap page tables if necessary */ | ||
1866 | sbp2util_cpu_to_be32_buffer(sg_element, | ||
1867 | (sizeof(struct sbp2_unrestricted_page_table)) * | ||
1868 | sg_count); | ||
1869 | } | ||
1870 | } | ||
1871 | |||
1710 | /* | 1872 | /* |
1711 | * This function is called to create the actual command orb and s/g list | 1873 | * This function is called to create the actual command orb and s/g list |
1712 | * out of the scsi command itself. | 1874 | * out of the scsi command itself. |
1713 | */ | 1875 | */ |
1714 | static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, | 1876 | static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, |
1715 | struct sbp2_command_info *command, | 1877 | struct sbp2_command_info *command, |
1716 | unchar *scsi_cmd, | 1878 | unchar *scsi_cmd, |
1717 | unsigned int scsi_use_sg, | 1879 | unsigned int scsi_use_sg, |
1718 | unsigned int scsi_request_bufflen, | 1880 | unsigned int scsi_request_bufflen, |
1719 | void *scsi_request_buffer, | 1881 | void *scsi_request_buffer, |
1720 | enum dma_data_direction dma_dir) | 1882 | enum dma_data_direction dma_dir) |
1721 | { | 1883 | { |
1722 | struct sbp2scsi_host_info *hi = scsi_id->hi; | 1884 | struct sbp2scsi_host_info *hi = scsi_id->hi; |
1723 | struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer; | 1885 | struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer; |
1724 | struct sbp2_command_orb *command_orb = &command->command_orb; | 1886 | struct sbp2_command_orb *command_orb = &command->command_orb; |
1725 | struct sbp2_unrestricted_page_table *scatter_gather_element = | 1887 | u32 orb_direction; |
1726 | &command->scatter_gather_element[0]; | ||
1727 | u32 sg_count, sg_len, orb_direction; | ||
1728 | dma_addr_t sg_addr; | ||
1729 | int i; | ||
1730 | 1888 | ||
1731 | /* | 1889 | /* |
1732 | * Set-up our command ORB.. | 1890 | * Set-up our command ORB.. |
@@ -1753,186 +1911,29 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, | |||
1753 | orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; | 1911 | orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; |
1754 | } | 1912 | } |
1755 | 1913 | ||
1756 | /* | 1914 | /* Set-up our pagetable stuff */ |
1757 | * Set-up our pagetable stuff... unfortunately, this has become | ||
1758 | * messier than I'd like. Need to clean this up a bit. ;-) | ||
1759 | */ | ||
1760 | if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) { | 1915 | if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) { |
1761 | |||
1762 | SBP2_DEBUG("No data transfer"); | 1916 | SBP2_DEBUG("No data transfer"); |
1763 | |||
1764 | /* | ||
1765 | * Handle no data transfer | ||
1766 | */ | ||
1767 | command_orb->data_descriptor_hi = 0x0; | 1917 | command_orb->data_descriptor_hi = 0x0; |
1768 | command_orb->data_descriptor_lo = 0x0; | 1918 | command_orb->data_descriptor_lo = 0x0; |
1769 | command_orb->misc |= ORB_SET_DIRECTION(1); | 1919 | command_orb->misc |= ORB_SET_DIRECTION(1); |
1770 | |||
1771 | } else if (scsi_use_sg) { | 1920 | } else if (scsi_use_sg) { |
1772 | |||
1773 | SBP2_DEBUG("Use scatter/gather"); | 1921 | SBP2_DEBUG("Use scatter/gather"); |
1774 | 1922 | sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg, | |
1775 | /* | 1923 | sgpnt, orb_direction, dma_dir); |
1776 | * Special case if only one element (and less than 64KB in size) | ||
1777 | */ | ||
1778 | if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) { | ||
1779 | |||
1780 | SBP2_DEBUG("Only one s/g element"); | ||
1781 | command->dma_dir = dma_dir; | ||
1782 | command->dma_size = sgpnt[0].length; | ||
1783 | command->dma_type = CMD_DMA_PAGE; | ||
1784 | command->cmd_dma = pci_map_page(hi->host->pdev, | ||
1785 | sgpnt[0].page, | ||
1786 | sgpnt[0].offset, | ||
1787 | command->dma_size, | ||
1788 | command->dma_dir); | ||
1789 | SBP2_DMA_ALLOC("single page scatter element"); | ||
1790 | |||
1791 | command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1792 | command_orb->data_descriptor_lo = command->cmd_dma; | ||
1793 | command_orb->misc |= ORB_SET_DATA_SIZE(command->dma_size); | ||
1794 | command_orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1795 | |||
1796 | } else { | ||
1797 | int count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, dma_dir); | ||
1798 | SBP2_DMA_ALLOC("scatter list"); | ||
1799 | |||
1800 | command->dma_size = scsi_use_sg; | ||
1801 | command->dma_dir = dma_dir; | ||
1802 | command->sge_buffer = sgpnt; | ||
1803 | |||
1804 | /* use page tables (s/g) */ | ||
1805 | command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | ||
1806 | command_orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1807 | command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1808 | command_orb->data_descriptor_lo = command->sge_dma; | ||
1809 | |||
1810 | /* | ||
1811 | * Loop through and fill out our sbp-2 page tables | ||
1812 | * (and split up anything too large) | ||
1813 | */ | ||
1814 | for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) { | ||
1815 | sg_len = sg_dma_len(sgpnt); | ||
1816 | sg_addr = sg_dma_address(sgpnt); | ||
1817 | while (sg_len) { | ||
1818 | scatter_gather_element[sg_count].segment_base_lo = sg_addr; | ||
1819 | if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1820 | scatter_gather_element[sg_count].length_segment_base_hi = | ||
1821 | PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | ||
1822 | sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1823 | sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1824 | } else { | ||
1825 | scatter_gather_element[sg_count].length_segment_base_hi = | ||
1826 | PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | ||
1827 | sg_len = 0; | ||
1828 | } | ||
1829 | sg_count++; | ||
1830 | } | ||
1831 | } | ||
1832 | |||
1833 | /* Number of page table (s/g) elements */ | ||
1834 | command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); | ||
1835 | |||
1836 | sbp2util_packet_dump(scatter_gather_element, | ||
1837 | (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | ||
1838 | "sbp2 s/g list", command->sge_dma); | ||
1839 | |||
1840 | /* | ||
1841 | * Byte swap page tables if necessary | ||
1842 | */ | ||
1843 | sbp2util_cpu_to_be32_buffer(scatter_gather_element, | ||
1844 | (sizeof(struct sbp2_unrestricted_page_table)) * | ||
1845 | sg_count); | ||
1846 | |||
1847 | } | ||
1848 | |||
1849 | } else { | 1924 | } else { |
1850 | |||
1851 | SBP2_DEBUG("No scatter/gather"); | 1925 | SBP2_DEBUG("No scatter/gather"); |
1852 | 1926 | sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt, | |
1853 | command->dma_dir = dma_dir; | 1927 | orb_direction, scsi_request_bufflen, |
1854 | command->dma_size = scsi_request_bufflen; | 1928 | scsi_request_buffer, dma_dir); |
1855 | command->dma_type = CMD_DMA_SINGLE; | ||
1856 | command->cmd_dma = | ||
1857 | pci_map_single(hi->host->pdev, scsi_request_buffer, | ||
1858 | command->dma_size, command->dma_dir); | ||
1859 | SBP2_DMA_ALLOC("single bulk"); | ||
1860 | |||
1861 | /* | ||
1862 | * Handle case where we get a command w/o s/g enabled (but | ||
1863 | * check for transfers larger than 64K) | ||
1864 | */ | ||
1865 | if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1866 | |||
1867 | command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1868 | command_orb->data_descriptor_lo = command->cmd_dma; | ||
1869 | command_orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen); | ||
1870 | command_orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1871 | |||
1872 | } else { | ||
1873 | /* | ||
1874 | * Need to turn this into page tables, since the | ||
1875 | * buffer is too large. | ||
1876 | */ | ||
1877 | command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | ||
1878 | command_orb->data_descriptor_lo = command->sge_dma; | ||
1879 | |||
1880 | /* Use page tables (s/g) */ | ||
1881 | command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | ||
1882 | command_orb->misc |= ORB_SET_DIRECTION(orb_direction); | ||
1883 | |||
1884 | /* | ||
1885 | * fill out our sbp-2 page tables (and split up | ||
1886 | * the large buffer) | ||
1887 | */ | ||
1888 | sg_count = 0; | ||
1889 | sg_len = scsi_request_bufflen; | ||
1890 | sg_addr = command->cmd_dma; | ||
1891 | while (sg_len) { | ||
1892 | scatter_gather_element[sg_count].segment_base_lo = sg_addr; | ||
1893 | if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | ||
1894 | scatter_gather_element[sg_count].length_segment_base_hi = | ||
1895 | PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | ||
1896 | sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1897 | sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | ||
1898 | } else { | ||
1899 | scatter_gather_element[sg_count].length_segment_base_hi = | ||
1900 | PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | ||
1901 | sg_len = 0; | ||
1902 | } | ||
1903 | sg_count++; | ||
1904 | } | ||
1905 | |||
1906 | /* Number of page table (s/g) elements */ | ||
1907 | command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); | ||
1908 | |||
1909 | sbp2util_packet_dump(scatter_gather_element, | ||
1910 | (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | ||
1911 | "sbp2 s/g list", command->sge_dma); | ||
1912 | |||
1913 | /* | ||
1914 | * Byte swap page tables if necessary | ||
1915 | */ | ||
1916 | sbp2util_cpu_to_be32_buffer(scatter_gather_element, | ||
1917 | (sizeof(struct sbp2_unrestricted_page_table)) * | ||
1918 | sg_count); | ||
1919 | |||
1920 | } | ||
1921 | |||
1922 | } | 1929 | } |
1923 | 1930 | ||
1924 | /* | 1931 | /* Byte swap command ORB if necessary */ |
1925 | * Byte swap command ORB if necessary | ||
1926 | */ | ||
1927 | sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb)); | 1932 | sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb)); |
1928 | 1933 | ||
1929 | /* | 1934 | /* Put our scsi command in the command ORB */ |
1930 | * Put our scsi command in the command ORB | ||
1931 | */ | ||
1932 | memset(command_orb->cdb, 0, 12); | 1935 | memset(command_orb->cdb, 0, 12); |
1933 | memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); | 1936 | memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); |
1934 | |||
1935 | return 0; | ||
1936 | } | 1937 | } |
1937 | 1938 | ||
1938 | /* | 1939 | /* |