diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:32:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:32:28 -0500 |
commit | 5fc77247f7db01b6377a5ea6ab18c8ac60021045 (patch) | |
tree | d9f33f0e01b64a46ade3f45a3553b1a8ba8fc5b5 /drivers | |
parent | d43a338e395371733a80ec473b40baac5f74d768 (diff) | |
parent | 7c9d6f16f50d3aeb780e4f103a1ba8b35d9ae803 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6:
[SCSI] SCSI core: better initialization for sdev->scsi_level
[SCSI] scsi_proc.c: display sdev->scsi_level correctly
[SCSI] megaraid_sas: update version and author info
[SCSI] megaraid_sas: return sync cache call with success
[SCSI] megaraid_sas: replace pci_alloc_consitent with dma_alloc_coherent in ioctl path
[SCSI] megaraid_sas: add bios_param in scsi_host_template
[SCSI] megaraid_sas: do not process cmds if hw_crit_error is set
[SCSI] scsi_transport.h should include scsi_device.h
[SCSI] aic79xx: remove extra newline from info message
[SCSI] scsi_scan.c: handle bad inquiry responses
[SCSI] aic94xx: tie driver to the major number of the sequencer firmware
[SCSI] lpfc: add PCI error recovery support
[SCSI] megaraid: pci_module_init to pci_register_driver
[SCSI] tgt: fix the user/kernel ring buffer interface
[SCSI] sgiwd93: interfacing to wd33c93
[SCSI] wd33c93: Fast SCSI with WD33C93B
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 1 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_seq.c | 13 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_seq.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 97 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 12 | ||||
-rw-r--r-- | drivers/scsi/megaraid.c | 2 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 90 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 6 | ||||
-rw-r--r-- | drivers/scsi/scsi_proc.c | 5 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 14 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_tgt_if.c | 8 | ||||
-rw-r--r-- | drivers/scsi/sgiwd93.c | 5 | ||||
-rw-r--r-- | drivers/scsi/wd33c93.c | 321 | ||||
-rw-r--r-- | drivers/scsi/wd33c93.h | 6 |
15 files changed, 480 insertions, 103 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index c7fe478f4813..2be03e975d97 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -418,7 +418,6 @@ ahd_linux_info(struct Scsi_Host *host) | |||
418 | strcat(bp, " "); | 418 | strcat(bp, " "); |
419 | ahd_controller_info(ahd, ahd_info); | 419 | ahd_controller_info(ahd, ahd_info); |
420 | strcat(bp, ahd_info); | 420 | strcat(bp, ahd_info); |
421 | strcat(bp, "\n"); | ||
422 | 421 | ||
423 | return (bp); | 422 | return (bp); |
424 | } | 423 | } |
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index eae7a247bece..c750fbf7013b 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #define PAUSE_TRIES 1000 | 44 | #define PAUSE_TRIES 1000 |
45 | 45 | ||
46 | static const struct firmware *sequencer_fw; | 46 | static const struct firmware *sequencer_fw; |
47 | static const char *sequencer_version; | ||
48 | static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, | 47 | static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, |
49 | cseq_idle_loop, lseq_idle_loop; | 48 | cseq_idle_loop, lseq_idle_loop; |
50 | static u8 *cseq_code, *lseq_code; | 49 | static u8 *cseq_code, *lseq_code; |
@@ -1276,7 +1275,6 @@ static int asd_request_firmware(struct asd_ha_struct *asd_ha) | |||
1276 | header.csum = le32_to_cpu(hdr_ptr->csum); | 1275 | header.csum = le32_to_cpu(hdr_ptr->csum); |
1277 | header.major = le32_to_cpu(hdr_ptr->major); | 1276 | header.major = le32_to_cpu(hdr_ptr->major); |
1278 | header.minor = le32_to_cpu(hdr_ptr->minor); | 1277 | header.minor = le32_to_cpu(hdr_ptr->minor); |
1279 | sequencer_version = hdr_ptr->version; | ||
1280 | header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset); | 1278 | header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset); |
1281 | header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size); | 1279 | header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size); |
1282 | header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset); | 1280 | header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset); |
@@ -1303,6 +1301,16 @@ static int asd_request_firmware(struct asd_ha_struct *asd_ha) | |||
1303 | return -EINVAL; | 1301 | return -EINVAL; |
1304 | } | 1302 | } |
1305 | 1303 | ||
1304 | asd_printk("Found sequencer Firmware version %d.%d (%s)\n", | ||
1305 | header.major, header.minor, hdr_ptr->version); | ||
1306 | |||
1307 | if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) { | ||
1308 | asd_printk("Firmware Major Version Mismatch;" | ||
1309 | "driver requires version %d.X", | ||
1310 | SAS_RAZOR_SEQUENCER_FW_MAJOR); | ||
1311 | return -EINVAL; | ||
1312 | } | ||
1313 | |||
1306 | ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset]; | 1314 | ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset]; |
1307 | ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset]; | 1315 | ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset]; |
1308 | mode2_task = header.mode2_task; | 1316 | mode2_task = header.mode2_task; |
@@ -1335,7 +1343,6 @@ int asd_init_seqs(struct asd_ha_struct *asd_ha) | |||
1335 | return err; | 1343 | return err; |
1336 | } | 1344 | } |
1337 | 1345 | ||
1338 | asd_printk("using sequencer %s\n", sequencer_version); | ||
1339 | err = asd_seq_download_seqs(asd_ha); | 1346 | err = asd_seq_download_seqs(asd_ha); |
1340 | if (err) { | 1347 | if (err) { |
1341 | asd_printk("couldn't download sequencers for %s\n", | 1348 | asd_printk("couldn't download sequencers for %s\n", |
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h index 9437ff0ae3a4..2ea6a0d52208 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.h +++ b/drivers/scsi/aic94xx/aic94xx_seq.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define LSEQ_NUM_VECS 11 | 31 | #define LSEQ_NUM_VECS 11 |
32 | 32 | ||
33 | #define SAS_RAZOR_SEQUENCER_FW_FILE "aic94xx-seq.fw" | 33 | #define SAS_RAZOR_SEQUENCER_FW_FILE "aic94xx-seq.fw" |
34 | #define SAS_RAZOR_SEQUENCER_FW_MAJOR 1 | ||
34 | 35 | ||
35 | /* Note: All quantites in the sequencer file are little endian */ | 36 | /* Note: All quantites in the sequencer file are little endian */ |
36 | struct sequencer_file_header { | 37 | struct sequencer_file_header { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index afca45cdbcef..9d014e5a81c4 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -518,6 +518,10 @@ lpfc_handle_eratt(struct lpfc_hba * phba) | |||
518 | struct lpfc_sli *psli = &phba->sli; | 518 | struct lpfc_sli *psli = &phba->sli; |
519 | struct lpfc_sli_ring *pring; | 519 | struct lpfc_sli_ring *pring; |
520 | uint32_t event_data; | 520 | uint32_t event_data; |
521 | /* If the pci channel is offline, ignore possible errors, | ||
522 | * since we cannot communicate with the pci card anyway. */ | ||
523 | if (pci_channel_offline(phba->pcidev)) | ||
524 | return; | ||
521 | 525 | ||
522 | if (phba->work_hs & HS_FFER6 || | 526 | if (phba->work_hs & HS_FFER6 || |
523 | phba->work_hs & HS_FFER5) { | 527 | phba->work_hs & HS_FFER5) { |
@@ -1797,6 +1801,92 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1797 | pci_set_drvdata(pdev, NULL); | 1801 | pci_set_drvdata(pdev, NULL); |
1798 | } | 1802 | } |
1799 | 1803 | ||
1804 | /** | ||
1805 | * lpfc_io_error_detected - called when PCI error is detected | ||
1806 | * @pdev: Pointer to PCI device | ||
1807 | * @state: The current pci conneection state | ||
1808 | * | ||
1809 | * This function is called after a PCI bus error affecting | ||
1810 | * this device has been detected. | ||
1811 | */ | ||
1812 | static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | ||
1813 | pci_channel_state_t state) | ||
1814 | { | ||
1815 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
1816 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | ||
1817 | struct lpfc_sli *psli = &phba->sli; | ||
1818 | struct lpfc_sli_ring *pring; | ||
1819 | |||
1820 | if (state == pci_channel_io_perm_failure) { | ||
1821 | lpfc_pci_remove_one(pdev); | ||
1822 | return PCI_ERS_RESULT_DISCONNECT; | ||
1823 | } | ||
1824 | pci_disable_device(pdev); | ||
1825 | /* | ||
1826 | * There may be I/Os dropped by the firmware. | ||
1827 | * Error iocb (I/O) on txcmplq and let the SCSI layer | ||
1828 | * retry it after re-establishing link. | ||
1829 | */ | ||
1830 | pring = &psli->ring[psli->fcp_ring]; | ||
1831 | lpfc_sli_abort_iocb_ring(phba, pring); | ||
1832 | |||
1833 | /* Request a slot reset. */ | ||
1834 | return PCI_ERS_RESULT_NEED_RESET; | ||
1835 | } | ||
1836 | |||
1837 | /** | ||
1838 | * lpfc_io_slot_reset - called after the pci bus has been reset. | ||
1839 | * @pdev: Pointer to PCI device | ||
1840 | * | ||
1841 | * Restart the card from scratch, as if from a cold-boot. | ||
1842 | */ | ||
1843 | static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | ||
1844 | { | ||
1845 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
1846 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | ||
1847 | struct lpfc_sli *psli = &phba->sli; | ||
1848 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); | ||
1849 | |||
1850 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); | ||
1851 | if (pci_enable_device_bars(pdev, bars)) { | ||
1852 | printk(KERN_ERR "lpfc: Cannot re-enable " | ||
1853 | "PCI device after reset.\n"); | ||
1854 | return PCI_ERS_RESULT_DISCONNECT; | ||
1855 | } | ||
1856 | |||
1857 | pci_set_master(pdev); | ||
1858 | |||
1859 | /* Re-establishing Link */ | ||
1860 | spin_lock_irq(phba->host->host_lock); | ||
1861 | phba->fc_flag |= FC_ESTABLISH_LINK; | ||
1862 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
1863 | spin_unlock_irq(phba->host->host_lock); | ||
1864 | |||
1865 | |||
1866 | /* Take device offline; this will perform cleanup */ | ||
1867 | lpfc_offline(phba); | ||
1868 | lpfc_sli_brdrestart(phba); | ||
1869 | |||
1870 | return PCI_ERS_RESULT_RECOVERED; | ||
1871 | } | ||
1872 | |||
1873 | /** | ||
1874 | * lpfc_io_resume - called when traffic can start flowing again. | ||
1875 | * @pdev: Pointer to PCI device | ||
1876 | * | ||
1877 | * This callback is called when the error recovery driver tells us that | ||
1878 | * its OK to resume normal operation. | ||
1879 | */ | ||
1880 | static void lpfc_io_resume(struct pci_dev *pdev) | ||
1881 | { | ||
1882 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
1883 | struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; | ||
1884 | |||
1885 | if (lpfc_online(phba) == 0) { | ||
1886 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); | ||
1887 | } | ||
1888 | } | ||
1889 | |||
1800 | static struct pci_device_id lpfc_id_table[] = { | 1890 | static struct pci_device_id lpfc_id_table[] = { |
1801 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER, | 1891 | {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER, |
1802 | PCI_ANY_ID, PCI_ANY_ID, }, | 1892 | PCI_ANY_ID, PCI_ANY_ID, }, |
@@ -1857,11 +1947,18 @@ static struct pci_device_id lpfc_id_table[] = { | |||
1857 | 1947 | ||
1858 | MODULE_DEVICE_TABLE(pci, lpfc_id_table); | 1948 | MODULE_DEVICE_TABLE(pci, lpfc_id_table); |
1859 | 1949 | ||
1950 | static struct pci_error_handlers lpfc_err_handler = { | ||
1951 | .error_detected = lpfc_io_error_detected, | ||
1952 | .slot_reset = lpfc_io_slot_reset, | ||
1953 | .resume = lpfc_io_resume, | ||
1954 | }; | ||
1955 | |||
1860 | static struct pci_driver lpfc_driver = { | 1956 | static struct pci_driver lpfc_driver = { |
1861 | .name = LPFC_DRIVER_NAME, | 1957 | .name = LPFC_DRIVER_NAME, |
1862 | .id_table = lpfc_id_table, | 1958 | .id_table = lpfc_id_table, |
1863 | .probe = lpfc_pci_probe_one, | 1959 | .probe = lpfc_pci_probe_one, |
1864 | .remove = __devexit_p(lpfc_pci_remove_one), | 1960 | .remove = __devexit_p(lpfc_pci_remove_one), |
1961 | .err_handler = &lpfc_err_handler, | ||
1865 | }; | 1962 | }; |
1866 | 1963 | ||
1867 | static int __init | 1964 | static int __init |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a4128e19338a..9fb6960a8ada 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -2104,6 +2104,10 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) | |||
2104 | volatile uint32_t word0, ldata; | 2104 | volatile uint32_t word0, ldata; |
2105 | void __iomem *to_slim; | 2105 | void __iomem *to_slim; |
2106 | 2106 | ||
2107 | /* If the PCI channel is in offline state, do not post mbox. */ | ||
2108 | if (unlikely(pci_channel_offline(phba->pcidev))) | ||
2109 | return MBX_NOT_FINISHED; | ||
2110 | |||
2107 | psli = &phba->sli; | 2111 | psli = &phba->sli; |
2108 | 2112 | ||
2109 | spin_lock_irqsave(phba->host->host_lock, drvr_flag); | 2113 | spin_lock_irqsave(phba->host->host_lock, drvr_flag); |
@@ -2407,6 +2411,10 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
2407 | struct lpfc_iocbq *nextiocb; | 2411 | struct lpfc_iocbq *nextiocb; |
2408 | IOCB_t *iocb; | 2412 | IOCB_t *iocb; |
2409 | 2413 | ||
2414 | /* If the PCI channel is in offline state, do not post iocbs. */ | ||
2415 | if (unlikely(pci_channel_offline(phba->pcidev))) | ||
2416 | return IOCB_ERROR; | ||
2417 | |||
2410 | /* | 2418 | /* |
2411 | * We should never get an IOCB if we are in a < LINK_DOWN state | 2419 | * We should never get an IOCB if we are in a < LINK_DOWN state |
2412 | */ | 2420 | */ |
@@ -3154,6 +3162,10 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3154 | if (unlikely(!phba)) | 3162 | if (unlikely(!phba)) |
3155 | return IRQ_NONE; | 3163 | return IRQ_NONE; |
3156 | 3164 | ||
3165 | /* If the pci channel is offline, ignore all the interrupts. */ | ||
3166 | if (unlikely(pci_channel_offline(phba->pcidev))) | ||
3167 | return IRQ_NONE; | ||
3168 | |||
3157 | phba->sli.slistat.sli_intr++; | 3169 | phba->sli.slistat.sli_intr++; |
3158 | 3170 | ||
3159 | /* | 3171 | /* |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 808a1b8c4043..0aa3304f6b9b 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
@@ -5072,7 +5072,7 @@ static int __init megaraid_init(void) | |||
5072 | "megaraid: failed to create megaraid root\n"); | 5072 | "megaraid: failed to create megaraid root\n"); |
5073 | } | 5073 | } |
5074 | #endif | 5074 | #endif |
5075 | error = pci_module_init(&megaraid_pci_driver); | 5075 | error = pci_register_driver(&megaraid_pci_driver); |
5076 | if (error) { | 5076 | if (error) { |
5077 | #ifdef CONFIG_PROC_FS | 5077 | #ifdef CONFIG_PROC_FS |
5078 | remove_proc_entry("megaraid", &proc_root); | 5078 | remove_proc_entry("megaraid", &proc_root); |
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 15e24fcc84f3..7a812677ff8a 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -10,11 +10,13 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * FILE : megaraid_sas.c | 12 | * FILE : megaraid_sas.c |
13 | * Version : v00.00.03.05 | 13 | * Version : v00.00.03.10-rc1 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * Sreenivas Bagalkote <Sreenivas.Bagalkote@lsi.com> | 16 | * (email-id : megaraidlinux@lsi.com) |
17 | * Sumant Patro <Sumant.Patro@lsi.com> | 17 | * Sreenivas Bagalkote |
18 | * Sumant Patro | ||
19 | * Bo Yang | ||
18 | * | 20 | * |
19 | * List of supported controllers | 21 | * List of supported controllers |
20 | * | 22 | * |
@@ -35,6 +37,7 @@ | |||
35 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
36 | #include <linux/fs.h> | 38 | #include <linux/fs.h> |
37 | #include <linux/compat.h> | 39 | #include <linux/compat.h> |
40 | #include <linux/blkdev.h> | ||
38 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
39 | 42 | ||
40 | #include <scsi/scsi.h> | 43 | #include <scsi/scsi.h> |
@@ -841,6 +844,11 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
841 | 844 | ||
842 | instance = (struct megasas_instance *) | 845 | instance = (struct megasas_instance *) |
843 | scmd->device->host->hostdata; | 846 | scmd->device->host->hostdata; |
847 | |||
848 | /* Don't process if we have already declared adapter dead */ | ||
849 | if (instance->hw_crit_error) | ||
850 | return SCSI_MLQUEUE_HOST_BUSY; | ||
851 | |||
844 | scmd->scsi_done = done; | 852 | scmd->scsi_done = done; |
845 | scmd->result = 0; | 853 | scmd->result = 0; |
846 | 854 | ||
@@ -850,6 +858,18 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
850 | goto out_done; | 858 | goto out_done; |
851 | } | 859 | } |
852 | 860 | ||
861 | switch (scmd->cmnd[0]) { | ||
862 | case SYNCHRONIZE_CACHE: | ||
863 | /* | ||
864 | * FW takes care of flush cache on its own | ||
865 | * No need to send it down | ||
866 | */ | ||
867 | scmd->result = DID_OK << 16; | ||
868 | goto out_done; | ||
869 | default: | ||
870 | break; | ||
871 | } | ||
872 | |||
853 | cmd = megasas_get_cmd(instance); | 873 | cmd = megasas_get_cmd(instance); |
854 | if (!cmd) | 874 | if (!cmd) |
855 | return SCSI_MLQUEUE_HOST_BUSY; | 875 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -1010,6 +1030,49 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd) | |||
1010 | } | 1030 | } |
1011 | 1031 | ||
1012 | /** | 1032 | /** |
1033 | * megasas_bios_param - Returns disk geometry for a disk | ||
1034 | * @sdev: device handle | ||
1035 | * @bdev: block device | ||
1036 | * @capacity: drive capacity | ||
1037 | * @geom: geometry parameters | ||
1038 | */ | ||
1039 | static int | ||
1040 | megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, | ||
1041 | sector_t capacity, int geom[]) | ||
1042 | { | ||
1043 | int heads; | ||
1044 | int sectors; | ||
1045 | sector_t cylinders; | ||
1046 | unsigned long tmp; | ||
1047 | /* Default heads (64) & sectors (32) */ | ||
1048 | heads = 64; | ||
1049 | sectors = 32; | ||
1050 | |||
1051 | tmp = heads * sectors; | ||
1052 | cylinders = capacity; | ||
1053 | |||
1054 | sector_div(cylinders, tmp); | ||
1055 | |||
1056 | /* | ||
1057 | * Handle extended translation size for logical drives > 1Gb | ||
1058 | */ | ||
1059 | |||
1060 | if (capacity >= 0x200000) { | ||
1061 | heads = 255; | ||
1062 | sectors = 63; | ||
1063 | tmp = heads*sectors; | ||
1064 | cylinders = capacity; | ||
1065 | sector_div(cylinders, tmp); | ||
1066 | } | ||
1067 | |||
1068 | geom[0] = heads; | ||
1069 | geom[1] = sectors; | ||
1070 | geom[2] = cylinders; | ||
1071 | |||
1072 | return 0; | ||
1073 | } | ||
1074 | |||
1075 | /** | ||
1013 | * megasas_service_aen - Processes an event notification | 1076 | * megasas_service_aen - Processes an event notification |
1014 | * @instance: Adapter soft state | 1077 | * @instance: Adapter soft state |
1015 | * @cmd: AEN command completed by the ISR | 1078 | * @cmd: AEN command completed by the ISR |
@@ -1049,6 +1112,7 @@ static struct scsi_host_template megasas_template = { | |||
1049 | .eh_device_reset_handler = megasas_reset_device, | 1112 | .eh_device_reset_handler = megasas_reset_device, |
1050 | .eh_bus_reset_handler = megasas_reset_bus_host, | 1113 | .eh_bus_reset_handler = megasas_reset_bus_host, |
1051 | .eh_host_reset_handler = megasas_reset_bus_host, | 1114 | .eh_host_reset_handler = megasas_reset_bus_host, |
1115 | .bios_param = megasas_bios_param, | ||
1052 | .use_clustering = ENABLE_CLUSTERING, | 1116 | .use_clustering = ENABLE_CLUSTERING, |
1053 | }; | 1117 | }; |
1054 | 1118 | ||
@@ -1282,11 +1346,13 @@ megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status) | |||
1282 | if(instance->instancet->clear_intr(instance->reg_set)) | 1346 | if(instance->instancet->clear_intr(instance->reg_set)) |
1283 | return IRQ_NONE; | 1347 | return IRQ_NONE; |
1284 | 1348 | ||
1349 | if (instance->hw_crit_error) | ||
1350 | goto out_done; | ||
1285 | /* | 1351 | /* |
1286 | * Schedule the tasklet for cmd completion | 1352 | * Schedule the tasklet for cmd completion |
1287 | */ | 1353 | */ |
1288 | tasklet_schedule(&instance->isr_tasklet); | 1354 | tasklet_schedule(&instance->isr_tasklet); |
1289 | 1355 | out_done: | |
1290 | return IRQ_HANDLED; | 1356 | return IRQ_HANDLED; |
1291 | } | 1357 | } |
1292 | 1358 | ||
@@ -1741,6 +1807,10 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) | |||
1741 | struct megasas_cmd *cmd; | 1807 | struct megasas_cmd *cmd; |
1742 | struct megasas_instance *instance = (struct megasas_instance *)instance_addr; | 1808 | struct megasas_instance *instance = (struct megasas_instance *)instance_addr; |
1743 | 1809 | ||
1810 | /* If we have already declared adapter dead, donot complete cmds */ | ||
1811 | if (instance->hw_crit_error) | ||
1812 | return; | ||
1813 | |||
1744 | producer = *instance->producer; | 1814 | producer = *instance->producer; |
1745 | consumer = *instance->consumer; | 1815 | consumer = *instance->consumer; |
1746 | 1816 | ||
@@ -2655,9 +2725,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
2655 | * For each user buffer, create a mirror buffer and copy in | 2725 | * For each user buffer, create a mirror buffer and copy in |
2656 | */ | 2726 | */ |
2657 | for (i = 0; i < ioc->sge_count; i++) { | 2727 | for (i = 0; i < ioc->sge_count; i++) { |
2658 | kbuff_arr[i] = pci_alloc_consistent(instance->pdev, | 2728 | kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev, |
2659 | ioc->sgl[i].iov_len, | 2729 | ioc->sgl[i].iov_len, |
2660 | &buf_handle); | 2730 | &buf_handle, GFP_KERNEL); |
2661 | if (!kbuff_arr[i]) { | 2731 | if (!kbuff_arr[i]) { |
2662 | printk(KERN_DEBUG "megasas: Failed to alloc " | 2732 | printk(KERN_DEBUG "megasas: Failed to alloc " |
2663 | "kernel SGL buffer for IOCTL \n"); | 2733 | "kernel SGL buffer for IOCTL \n"); |
@@ -2684,8 +2754,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
2684 | } | 2754 | } |
2685 | 2755 | ||
2686 | if (ioc->sense_len) { | 2756 | if (ioc->sense_len) { |
2687 | sense = pci_alloc_consistent(instance->pdev, ioc->sense_len, | 2757 | sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, |
2688 | &sense_handle); | 2758 | &sense_handle, GFP_KERNEL); |
2689 | if (!sense) { | 2759 | if (!sense) { |
2690 | error = -ENOMEM; | 2760 | error = -ENOMEM; |
2691 | goto out; | 2761 | goto out; |
@@ -2744,12 +2814,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
2744 | 2814 | ||
2745 | out: | 2815 | out: |
2746 | if (sense) { | 2816 | if (sense) { |
2747 | pci_free_consistent(instance->pdev, ioc->sense_len, | 2817 | dma_free_coherent(&instance->pdev->dev, ioc->sense_len, |
2748 | sense, sense_handle); | 2818 | sense, sense_handle); |
2749 | } | 2819 | } |
2750 | 2820 | ||
2751 | for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { | 2821 | for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { |
2752 | pci_free_consistent(instance->pdev, | 2822 | dma_free_coherent(&instance->pdev->dev, |
2753 | kern_sge32[i].length, | 2823 | kern_sge32[i].length, |
2754 | kbuff_arr[i], kern_sge32[i].phys_addr); | 2824 | kbuff_arr[i], kern_sge32[i].phys_addr); |
2755 | } | 2825 | } |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index cacb3ad92527..e862992ee377 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -18,9 +18,9 @@ | |||
18 | /* | 18 | /* |
19 | * MegaRAID SAS Driver meta data | 19 | * MegaRAID SAS Driver meta data |
20 | */ | 20 | */ |
21 | #define MEGASAS_VERSION "00.00.03.05" | 21 | #define MEGASAS_VERSION "00.00.03.10-rc1" |
22 | #define MEGASAS_RELDATE "Oct 02, 2006" | 22 | #define MEGASAS_RELDATE "Feb 14, 2007" |
23 | #define MEGASAS_EXT_VERSION "Mon Oct 02 11:21:32 PDT 2006" | 23 | #define MEGASAS_EXT_VERSION "Wed Feb 14 10:14:25 PST 2007" |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Device IDs | 26 | * Device IDs |
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 69d6e9b198c4..bb6f051beda8 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -179,9 +179,8 @@ static int proc_print_scsidevice(struct device *dev, void *data) | |||
179 | seq_printf(s, "\n"); | 179 | seq_printf(s, "\n"); |
180 | 180 | ||
181 | seq_printf(s, " Type: %s ", scsi_device_type(sdev->type)); | 181 | seq_printf(s, " Type: %s ", scsi_device_type(sdev->type)); |
182 | seq_printf(s, " ANSI" | 182 | seq_printf(s, " ANSI SCSI revision: %02x", |
183 | " SCSI revision: %02x", (sdev->scsi_level - 1) ? | 183 | sdev->scsi_level - (sdev->scsi_level > 1)); |
184 | sdev->scsi_level - 1 : 1); | ||
185 | if (sdev->scsi_level == 2) | 184 | if (sdev->scsi_level == 2) |
186 | seq_printf(s, " CCS\n"); | 185 | seq_printf(s, " CCS\n"); |
187 | else | 186 | else |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d6fe756eb371..0949145304ea 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -385,6 +385,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
385 | INIT_LIST_HEAD(&starget->siblings); | 385 | INIT_LIST_HEAD(&starget->siblings); |
386 | INIT_LIST_HEAD(&starget->devices); | 386 | INIT_LIST_HEAD(&starget->devices); |
387 | starget->state = STARGET_RUNNING; | 387 | starget->state = STARGET_RUNNING; |
388 | starget->scsi_level = SCSI_2; | ||
388 | retry: | 389 | retry: |
389 | spin_lock_irqsave(shost->host_lock, flags); | 390 | spin_lock_irqsave(shost->host_lock, flags); |
390 | 391 | ||
@@ -654,6 +655,19 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
654 | * short INQUIRY), an abort here prevents any further use of the | 655 | * short INQUIRY), an abort here prevents any further use of the |
655 | * device, including spin up. | 656 | * device, including spin up. |
656 | * | 657 | * |
658 | * On the whole, the best approach seems to be to assume the first | ||
659 | * 36 bytes are valid no matter what the device says. That's | ||
660 | * better than copying < 36 bytes to the inquiry-result buffer | ||
661 | * and displaying garbage for the Vendor, Product, or Revision | ||
662 | * strings. | ||
663 | */ | ||
664 | if (sdev->inquiry_len < 36) { | ||
665 | printk(KERN_INFO "scsi scan: INQUIRY result too short (%d)," | ||
666 | " using 36\n", sdev->inquiry_len); | ||
667 | sdev->inquiry_len = 36; | ||
668 | } | ||
669 | |||
670 | /* | ||
657 | * Related to the above issue: | 671 | * Related to the above issue: |
658 | * | 672 | * |
659 | * XXX Devices (disk or all?) should be sent a TEST UNIT READY, | 673 | * XXX Devices (disk or all?) should be sent a TEST UNIT READY, |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 259c90cfa367..c275dcac3f18 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -922,7 +922,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) | |||
922 | snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, | 922 | snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, |
923 | "%d:%d:%d:%d", sdev->host->host_no, | 923 | "%d:%d:%d:%d", sdev->host->host_no, |
924 | sdev->channel, sdev->id, sdev->lun); | 924 | sdev->channel, sdev->id, sdev->lun); |
925 | sdev->scsi_level = SCSI_2; | 925 | sdev->scsi_level = starget->scsi_level; |
926 | transport_setup_device(&sdev->sdev_gendev); | 926 | transport_setup_device(&sdev->sdev_gendev); |
927 | spin_lock_irqsave(shost->host_lock, flags); | 927 | spin_lock_irqsave(shost->host_lock, flags); |
928 | list_add_tail(&sdev->same_target_siblings, &starget->devices); | 928 | list_add_tail(&sdev->same_target_siblings, &starget->devices); |
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index f2344ab8deff..0e08817fdecf 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c | |||
@@ -33,6 +33,14 @@ | |||
33 | 33 | ||
34 | #include "scsi_tgt_priv.h" | 34 | #include "scsi_tgt_priv.h" |
35 | 35 | ||
36 | #if TGT_RING_SIZE < PAGE_SIZE | ||
37 | # define TGT_RING_SIZE PAGE_SIZE | ||
38 | #endif | ||
39 | |||
40 | #define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT) | ||
41 | #define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event)) | ||
42 | #define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES) | ||
43 | |||
36 | struct tgt_ring { | 44 | struct tgt_ring { |
37 | u32 tr_idx; | 45 | u32 tr_idx; |
38 | unsigned long tr_pages[TGT_RING_PAGES]; | 46 | unsigned long tr_pages[TGT_RING_PAGES]; |
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index e81f97a35bc8..a15752b37990 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c | |||
@@ -244,9 +244,10 @@ static struct Scsi_Host * __init sgiwd93_setup_scsi( | |||
244 | regs.SASR = wdregs + 3; | 244 | regs.SASR = wdregs + 3; |
245 | regs.SCMD = wdregs + 7; | 245 | regs.SCMD = wdregs + 7; |
246 | 246 | ||
247 | wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_16_20); | 247 | wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20)); |
248 | 248 | ||
249 | hdata->wh.no_sync = 0; | 249 | if (hdata->wh.no_sync == 0xff) |
250 | hdata->wh.no_sync = 0; | ||
250 | 251 | ||
251 | if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { | 252 | if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) { |
252 | printk(KERN_WARNING "sgiwd93: Could not register irq %d " | 253 | printk(KERN_WARNING "sgiwd93: Could not register irq %d " |
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 835751600e93..fa4e08e508ad 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c | |||
@@ -69,6 +69,11 @@ | |||
69 | * Added support for pre -A chips, which don't have advanced features | 69 | * Added support for pre -A chips, which don't have advanced features |
70 | * and will generate CSR_RESEL rather than CSR_RESEL_AM. | 70 | * and will generate CSR_RESEL rather than CSR_RESEL_AM. |
71 | * Richard Hirst <richard@sleepie.demon.co.uk> August 2000 | 71 | * Richard Hirst <richard@sleepie.demon.co.uk> August 2000 |
72 | * | ||
73 | * Added support for Burst Mode DMA and Fast SCSI. Enabled the use of | ||
74 | * default_sx_per for asynchronous data transfers. Added adjustment | ||
75 | * of transfer periods in sx_table to the actual input-clock. | ||
76 | * peter fuerst <post@pfrst.de> February 2007 | ||
72 | */ | 77 | */ |
73 | 78 | ||
74 | #include <linux/module.h> | 79 | #include <linux/module.h> |
@@ -86,9 +91,11 @@ | |||
86 | 91 | ||
87 | #include "wd33c93.h" | 92 | #include "wd33c93.h" |
88 | 93 | ||
94 | #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns | ||
95 | |||
89 | 96 | ||
90 | #define WD33C93_VERSION "1.26" | 97 | #define WD33C93_VERSION "1.26++" |
91 | #define WD33C93_DATE "22/Feb/2003" | 98 | #define WD33C93_DATE "10/Feb/2007" |
92 | 99 | ||
93 | MODULE_AUTHOR("John Shifflett"); | 100 | MODULE_AUTHOR("John Shifflett"); |
94 | MODULE_DESCRIPTION("Generic WD33C93 SCSI driver"); | 101 | MODULE_DESCRIPTION("Generic WD33C93 SCSI driver"); |
@@ -122,6 +129,13 @@ MODULE_LICENSE("GPL"); | |||
122 | * defines in wd33c93.h | 129 | * defines in wd33c93.h |
123 | * - clock:x -x = clock input in MHz for WD33c93 chip. Normal values | 130 | * - clock:x -x = clock input in MHz for WD33c93 chip. Normal values |
124 | * would be from 8 through 20. Default is 8. | 131 | * would be from 8 through 20. Default is 8. |
132 | * - burst:x -x = 1 to use Burst Mode (or Demand-Mode) DMA, x = 0 to use | ||
133 | * Single Byte DMA, which is the default. Argument is | ||
134 | * optional - if not present, same as "burst:1". | ||
135 | * - fast:x -x = 1 to enable Fast SCSI, which is only effective with | ||
136 | * input-clock divisor 4 (WD33C93_FS_16_20), x = 0 to disable | ||
137 | * it, which is the default. Argument is optional - if not | ||
138 | * present, same as "fast:1". | ||
125 | * - next -No argument. Used to separate blocks of keywords when | 139 | * - next -No argument. Used to separate blocks of keywords when |
126 | * there's more than one host adapter in the system. | 140 | * there's more than one host adapter in the system. |
127 | * | 141 | * |
@@ -148,7 +162,7 @@ MODULE_LICENSE("GPL"); | |||
148 | */ | 162 | */ |
149 | 163 | ||
150 | /* Normally, no defaults are specified */ | 164 | /* Normally, no defaults are specified */ |
151 | static char *setup_args[] = { "", "", "", "", "", "", "", "", "" }; | 165 | static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" }; |
152 | 166 | ||
153 | static char *setup_strings; | 167 | static char *setup_strings; |
154 | module_param(setup_strings, charp, 0); | 168 | module_param(setup_strings, charp, 0); |
@@ -298,20 +312,8 @@ read_1_byte(const wd33c93_regs regs) | |||
298 | return x; | 312 | return x; |
299 | } | 313 | } |
300 | 314 | ||
301 | static struct sx_period sx_table[] = { | ||
302 | {1, 0x20}, | ||
303 | {252, 0x20}, | ||
304 | {376, 0x30}, | ||
305 | {500, 0x40}, | ||
306 | {624, 0x50}, | ||
307 | {752, 0x60}, | ||
308 | {876, 0x70}, | ||
309 | {1000, 0x00}, | ||
310 | {0, 0} | ||
311 | }; | ||
312 | |||
313 | static int | 315 | static int |
314 | round_period(unsigned int period) | 316 | round_period(unsigned int period, const struct sx_period *sx_table) |
315 | { | 317 | { |
316 | int x; | 318 | int x; |
317 | 319 | ||
@@ -324,17 +326,49 @@ round_period(unsigned int period) | |||
324 | return 7; | 326 | return 7; |
325 | } | 327 | } |
326 | 328 | ||
329 | /* | ||
330 | * Calculate Synchronous Transfer Register value from SDTR code. | ||
331 | */ | ||
327 | static uchar | 332 | static uchar |
328 | calc_sync_xfer(unsigned int period, unsigned int offset) | 333 | calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast, |
334 | const struct sx_period *sx_table) | ||
329 | { | 335 | { |
336 | /* When doing Fast SCSI synchronous data transfers, the corresponding | ||
337 | * value in 'sx_table' is two times the actually used transfer period. | ||
338 | */ | ||
330 | uchar result; | 339 | uchar result; |
331 | 340 | ||
341 | if (offset && fast) { | ||
342 | fast = STR_FSS; | ||
343 | period *= 2; | ||
344 | } else { | ||
345 | fast = 0; | ||
346 | } | ||
332 | period *= 4; /* convert SDTR code to ns */ | 347 | period *= 4; /* convert SDTR code to ns */ |
333 | result = sx_table[round_period(period)].reg_value; | 348 | result = sx_table[round_period(period,sx_table)].reg_value; |
334 | result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF; | 349 | result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF; |
350 | result |= fast; | ||
335 | return result; | 351 | return result; |
336 | } | 352 | } |
337 | 353 | ||
354 | /* | ||
355 | * Calculate SDTR code bytes [3],[4] from period and offset. | ||
356 | */ | ||
357 | static inline void | ||
358 | calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast, | ||
359 | uchar msg[2]) | ||
360 | { | ||
361 | /* 'period' is a "normal"-mode value, like the ones in 'sx_table'. The | ||
362 | * actually used transfer period for Fast SCSI synchronous data | ||
363 | * transfers is half that value. | ||
364 | */ | ||
365 | period /= 4; | ||
366 | if (offset && fast) | ||
367 | period /= 2; | ||
368 | msg[0] = period; | ||
369 | msg[1] = offset; | ||
370 | } | ||
371 | |||
338 | int | 372 | int |
339 | wd33c93_queuecommand(struct scsi_cmnd *cmd, | 373 | wd33c93_queuecommand(struct scsi_cmnd *cmd, |
340 | void (*done)(struct scsi_cmnd *)) | 374 | void (*done)(struct scsi_cmnd *)) |
@@ -632,7 +666,7 @@ wd33c93_execute(struct Scsi_Host *instance) | |||
632 | write_wd33c93_count(regs, | 666 | write_wd33c93_count(regs, |
633 | cmd->SCp.this_residual); | 667 | cmd->SCp.this_residual); |
634 | write_wd33c93(regs, WD_CONTROL, | 668 | write_wd33c93(regs, WD_CONTROL, |
635 | CTRL_IDI | CTRL_EDI | CTRL_DMA); | 669 | CTRL_IDI | CTRL_EDI | hostdata->dma_mode); |
636 | hostdata->dma = D_DMA_RUNNING; | 670 | hostdata->dma = D_DMA_RUNNING; |
637 | } | 671 | } |
638 | } else | 672 | } else |
@@ -712,6 +746,8 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd, | |||
712 | cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + | 746 | cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + |
713 | cmd->SCp.buffer->offset; | 747 | cmd->SCp.buffer->offset; |
714 | } | 748 | } |
749 | if (!cmd->SCp.this_residual) /* avoid bogus setups */ | ||
750 | return; | ||
715 | 751 | ||
716 | write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, | 752 | write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, |
717 | hostdata->sync_xfer[cmd->device->id]); | 753 | hostdata->sync_xfer[cmd->device->id]); |
@@ -744,7 +780,7 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd, | |||
744 | #ifdef PROC_STATISTICS | 780 | #ifdef PROC_STATISTICS |
745 | hostdata->dma_cnt++; | 781 | hostdata->dma_cnt++; |
746 | #endif | 782 | #endif |
747 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA); | 783 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode); |
748 | write_wd33c93_count(regs, cmd->SCp.this_residual); | 784 | write_wd33c93_count(regs, cmd->SCp.this_residual); |
749 | 785 | ||
750 | if ((hostdata->level2 >= L2_DATA) || | 786 | if ((hostdata->level2 >= L2_DATA) || |
@@ -862,9 +898,6 @@ wd33c93_intr(struct Scsi_Host *instance) | |||
862 | hostdata->outgoing_msg[0] |= 0x40; | 898 | hostdata->outgoing_msg[0] |= 0x40; |
863 | 899 | ||
864 | if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) { | 900 | if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) { |
865 | #ifdef SYNC_DEBUG | ||
866 | printk(" sending SDTR "); | ||
867 | #endif | ||
868 | 901 | ||
869 | hostdata->sync_stat[cmd->device->id] = SS_WAITING; | 902 | hostdata->sync_stat[cmd->device->id] = SS_WAITING; |
870 | 903 | ||
@@ -878,14 +911,20 @@ wd33c93_intr(struct Scsi_Host *instance) | |||
878 | hostdata->outgoing_msg[2] = 3; | 911 | hostdata->outgoing_msg[2] = 3; |
879 | hostdata->outgoing_msg[3] = EXTENDED_SDTR; | 912 | hostdata->outgoing_msg[3] = EXTENDED_SDTR; |
880 | if (hostdata->no_sync & (1 << cmd->device->id)) { | 913 | if (hostdata->no_sync & (1 << cmd->device->id)) { |
881 | hostdata->outgoing_msg[4] = | 914 | calc_sync_msg(hostdata->default_sx_per, 0, |
882 | hostdata->default_sx_per / 4; | 915 | 0, hostdata->outgoing_msg + 4); |
883 | hostdata->outgoing_msg[5] = 0; | ||
884 | } else { | 916 | } else { |
885 | hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4; | 917 | calc_sync_msg(optimum_sx_per(hostdata), |
886 | hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; | 918 | OPTIMUM_SX_OFF, |
919 | hostdata->fast, | ||
920 | hostdata->outgoing_msg + 4); | ||
887 | } | 921 | } |
888 | hostdata->outgoing_len = 6; | 922 | hostdata->outgoing_len = 6; |
923 | #ifdef SYNC_DEBUG | ||
924 | ucp = hostdata->outgoing_msg + 1; | ||
925 | printk(" sending SDTR %02x03%02x%02x%02x ", | ||
926 | ucp[0], ucp[2], ucp[3], ucp[4]); | ||
927 | #endif | ||
889 | } else | 928 | } else |
890 | hostdata->outgoing_len = 1; | 929 | hostdata->outgoing_len = 1; |
891 | 930 | ||
@@ -1001,8 +1040,13 @@ wd33c93_intr(struct Scsi_Host *instance) | |||
1001 | #ifdef SYNC_DEBUG | 1040 | #ifdef SYNC_DEBUG |
1002 | printk("-REJ-"); | 1041 | printk("-REJ-"); |
1003 | #endif | 1042 | #endif |
1004 | if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) | 1043 | if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) { |
1005 | hostdata->sync_stat[cmd->device->id] = SS_SET; | 1044 | hostdata->sync_stat[cmd->device->id] = SS_SET; |
1045 | /* we want default_sx_per, not DEFAULT_SX_PER */ | ||
1046 | hostdata->sync_xfer[cmd->device->id] = | ||
1047 | calc_sync_xfer(hostdata->default_sx_per | ||
1048 | / 4, 0, 0, hostdata->sx_table); | ||
1049 | } | ||
1006 | write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK); | 1050 | write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK); |
1007 | hostdata->state = S_CONNECTED; | 1051 | hostdata->state = S_CONNECTED; |
1008 | break; | 1052 | break; |
@@ -1022,7 +1066,10 @@ wd33c93_intr(struct Scsi_Host *instance) | |||
1022 | 1066 | ||
1023 | switch (ucp[2]) { /* what's the EXTENDED code? */ | 1067 | switch (ucp[2]) { /* what's the EXTENDED code? */ |
1024 | case EXTENDED_SDTR: | 1068 | case EXTENDED_SDTR: |
1025 | id = calc_sync_xfer(ucp[3], ucp[4]); | 1069 | /* default to default async period */ |
1070 | id = calc_sync_xfer(hostdata-> | ||
1071 | default_sx_per / 4, 0, | ||
1072 | 0, hostdata->sx_table); | ||
1026 | if (hostdata->sync_stat[cmd->device->id] != | 1073 | if (hostdata->sync_stat[cmd->device->id] != |
1027 | SS_WAITING) { | 1074 | SS_WAITING) { |
1028 | 1075 | ||
@@ -1041,20 +1088,22 @@ wd33c93_intr(struct Scsi_Host *instance) | |||
1041 | hostdata->outgoing_msg[1] = 3; | 1088 | hostdata->outgoing_msg[1] = 3; |
1042 | hostdata->outgoing_msg[2] = | 1089 | hostdata->outgoing_msg[2] = |
1043 | EXTENDED_SDTR; | 1090 | EXTENDED_SDTR; |
1044 | hostdata->outgoing_msg[3] = | 1091 | calc_sync_msg(hostdata-> |
1045 | hostdata->default_sx_per / | 1092 | default_sx_per, 0, |
1046 | 4; | 1093 | 0, hostdata->outgoing_msg + 3); |
1047 | hostdata->outgoing_msg[4] = 0; | ||
1048 | hostdata->outgoing_len = 5; | 1094 | hostdata->outgoing_len = 5; |
1049 | hostdata->sync_xfer[cmd->device->id] = | ||
1050 | calc_sync_xfer(hostdata-> | ||
1051 | default_sx_per | ||
1052 | / 4, 0); | ||
1053 | } else { | 1095 | } else { |
1054 | hostdata->sync_xfer[cmd->device->id] = id; | 1096 | if (ucp[4]) /* well, sync transfer */ |
1097 | id = calc_sync_xfer(ucp[3], ucp[4], | ||
1098 | hostdata->fast, | ||
1099 | hostdata->sx_table); | ||
1100 | else if (ucp[3]) /* very unlikely... */ | ||
1101 | id = calc_sync_xfer(ucp[3], ucp[4], | ||
1102 | 0, hostdata->sx_table); | ||
1055 | } | 1103 | } |
1104 | hostdata->sync_xfer[cmd->device->id] = id; | ||
1056 | #ifdef SYNC_DEBUG | 1105 | #ifdef SYNC_DEBUG |
1057 | printk("sync_xfer=%02x", | 1106 | printk(" sync_xfer=%02x\n", |
1058 | hostdata->sync_xfer[cmd->device->id]); | 1107 | hostdata->sync_xfer[cmd->device->id]); |
1059 | #endif | 1108 | #endif |
1060 | hostdata->sync_stat[cmd->device->id] = | 1109 | hostdata->sync_stat[cmd->device->id] = |
@@ -1486,7 +1535,7 @@ reset_wd33c93(struct Scsi_Host *instance) | |||
1486 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | 1535 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); |
1487 | write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, | 1536 | write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, |
1488 | calc_sync_xfer(hostdata->default_sx_per / 4, | 1537 | calc_sync_xfer(hostdata->default_sx_per / 4, |
1489 | DEFAULT_SX_OFF)); | 1538 | DEFAULT_SX_OFF, 0, hostdata->sx_table)); |
1490 | write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET); | 1539 | write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET); |
1491 | 1540 | ||
1492 | 1541 | ||
@@ -1512,6 +1561,9 @@ reset_wd33c93(struct Scsi_Host *instance) | |||
1512 | } else | 1561 | } else |
1513 | hostdata->chip = C_UNKNOWN_CHIP; | 1562 | hostdata->chip = C_UNKNOWN_CHIP; |
1514 | 1563 | ||
1564 | if (hostdata->chip != C_WD33C93B) /* Fast SCSI unavailable */ | ||
1565 | hostdata->fast = 0; | ||
1566 | |||
1515 | write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); | 1567 | write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); |
1516 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | 1568 | write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); |
1517 | } | 1569 | } |
@@ -1533,7 +1585,8 @@ wd33c93_host_reset(struct scsi_cmnd * SCpnt) | |||
1533 | for (i = 0; i < 8; i++) { | 1585 | for (i = 0; i < 8; i++) { |
1534 | hostdata->busy[i] = 0; | 1586 | hostdata->busy[i] = 0; |
1535 | hostdata->sync_xfer[i] = | 1587 | hostdata->sync_xfer[i] = |
1536 | calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); | 1588 | calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF, |
1589 | 0, hostdata->sx_table); | ||
1537 | hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ | 1590 | hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ |
1538 | } | 1591 | } |
1539 | hostdata->input_Q = NULL; | 1592 | hostdata->input_Q = NULL; |
@@ -1782,6 +1835,98 @@ check_setup_args(char *key, int *flags, int *val, char *buf) | |||
1782 | return ++x; | 1835 | return ++x; |
1783 | } | 1836 | } |
1784 | 1837 | ||
1838 | /* | ||
1839 | * Calculate internal data-transfer-clock cycle from input-clock | ||
1840 | * frequency (/MHz) and fill 'sx_table'. | ||
1841 | * | ||
1842 | * The original driver used to rely on a fixed sx_table, containing periods | ||
1843 | * for (only) the lower limits of the respective input-clock-frequency ranges | ||
1844 | * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with | ||
1845 | * this setting so far, it might be desirable to adjust the transfer periods | ||
1846 | * closer to the really attached, possibly 25% higher, input-clock, since | ||
1847 | * - the wd33c93 may really use a significant shorter period, than it has | ||
1848 | * negotiated (eg. thrashing the target, which expects 4/8MHz, with 5/10MHz | ||
1849 | * instead). | ||
1850 | * - the wd33c93 may ask the target for a lower transfer rate, than the target | ||
1851 | * is capable of (eg. negotiating for an assumed minimum of 252ns instead of | ||
1852 | * possible 200ns, which indeed shows up in tests as an approx. 10% lower | ||
1853 | * transfer rate). | ||
1854 | */ | ||
1855 | static inline unsigned int | ||
1856 | round_4(unsigned int x) | ||
1857 | { | ||
1858 | switch (x & 3) { | ||
1859 | case 1: --x; | ||
1860 | break; | ||
1861 | case 2: ++x; | ||
1862 | case 3: ++x; | ||
1863 | } | ||
1864 | return x; | ||
1865 | } | ||
1866 | |||
1867 | static void | ||
1868 | calc_sx_table(unsigned int mhz, struct sx_period sx_table[9]) | ||
1869 | { | ||
1870 | unsigned int d, i; | ||
1871 | if (mhz < 11) | ||
1872 | d = 2; /* divisor for 8-10 MHz input-clock */ | ||
1873 | else if (mhz < 16) | ||
1874 | d = 3; /* divisor for 12-15 MHz input-clock */ | ||
1875 | else | ||
1876 | d = 4; /* divisor for 16-20 MHz input-clock */ | ||
1877 | |||
1878 | d = (100000 * d) / 2 / mhz; /* 100 x DTCC / nanosec */ | ||
1879 | |||
1880 | sx_table[0].period_ns = 1; | ||
1881 | sx_table[0].reg_value = 0x20; | ||
1882 | for (i = 1; i < 8; i++) { | ||
1883 | sx_table[i].period_ns = round_4((i+1)*d / 100); | ||
1884 | sx_table[i].reg_value = (i+1)*0x10; | ||
1885 | } | ||
1886 | sx_table[7].reg_value = 0; | ||
1887 | sx_table[8].period_ns = 0; | ||
1888 | sx_table[8].reg_value = 0; | ||
1889 | } | ||
1890 | |||
1891 | /* | ||
1892 | * check and, maybe, map an init- or "clock:"- argument. | ||
1893 | */ | ||
1894 | static uchar | ||
1895 | set_clk_freq(int freq, int *mhz) | ||
1896 | { | ||
1897 | int x = freq; | ||
1898 | if (WD33C93_FS_8_10 == freq) | ||
1899 | freq = 8; | ||
1900 | else if (WD33C93_FS_12_15 == freq) | ||
1901 | freq = 12; | ||
1902 | else if (WD33C93_FS_16_20 == freq) | ||
1903 | freq = 16; | ||
1904 | else if (freq > 7 && freq < 11) | ||
1905 | x = WD33C93_FS_8_10; | ||
1906 | else if (freq > 11 && freq < 16) | ||
1907 | x = WD33C93_FS_12_15; | ||
1908 | else if (freq > 15 && freq < 21) | ||
1909 | x = WD33C93_FS_16_20; | ||
1910 | else { | ||
1911 | /* Hmm, wouldn't it be safer to assume highest freq here? */ | ||
1912 | x = WD33C93_FS_8_10; | ||
1913 | freq = 8; | ||
1914 | } | ||
1915 | *mhz = freq; | ||
1916 | return x; | ||
1917 | } | ||
1918 | |||
1919 | /* | ||
1920 | * to be used with the resync: fast: ... options | ||
1921 | */ | ||
1922 | static inline void set_resync ( struct WD33C93_hostdata *hd, int mask ) | ||
1923 | { | ||
1924 | int i; | ||
1925 | for (i = 0; i < 8; i++) | ||
1926 | if (mask & (1 << i)) | ||
1927 | hd->sync_stat[i] = SS_UNSET; | ||
1928 | } | ||
1929 | |||
1785 | void | 1930 | void |
1786 | wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | 1931 | wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, |
1787 | dma_setup_t setup, dma_stop_t stop, int clock_freq) | 1932 | dma_setup_t setup, dma_stop_t stop, int clock_freq) |
@@ -1798,7 +1943,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1798 | hostdata = (struct WD33C93_hostdata *) instance->hostdata; | 1943 | hostdata = (struct WD33C93_hostdata *) instance->hostdata; |
1799 | 1944 | ||
1800 | hostdata->regs = regs; | 1945 | hostdata->regs = regs; |
1801 | hostdata->clock_freq = clock_freq; | 1946 | hostdata->clock_freq = set_clk_freq(clock_freq, &i); |
1947 | calc_sx_table(i, hostdata->sx_table); | ||
1802 | hostdata->dma_setup = setup; | 1948 | hostdata->dma_setup = setup; |
1803 | hostdata->dma_stop = stop; | 1949 | hostdata->dma_stop = stop; |
1804 | hostdata->dma_bounce_buffer = NULL; | 1950 | hostdata->dma_bounce_buffer = NULL; |
@@ -1806,7 +1952,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1806 | for (i = 0; i < 8; i++) { | 1952 | for (i = 0; i < 8; i++) { |
1807 | hostdata->busy[i] = 0; | 1953 | hostdata->busy[i] = 0; |
1808 | hostdata->sync_xfer[i] = | 1954 | hostdata->sync_xfer[i] = |
1809 | calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); | 1955 | calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF, |
1956 | 0, hostdata->sx_table); | ||
1810 | hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ | 1957 | hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */ |
1811 | #ifdef PROC_STATISTICS | 1958 | #ifdef PROC_STATISTICS |
1812 | hostdata->cmd_cnt[i] = 0; | 1959 | hostdata->cmd_cnt[i] = 0; |
@@ -1828,6 +1975,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1828 | hostdata->default_sx_per = DEFAULT_SX_PER; | 1975 | hostdata->default_sx_per = DEFAULT_SX_PER; |
1829 | hostdata->no_sync = 0xff; /* sync defaults to off */ | 1976 | hostdata->no_sync = 0xff; /* sync defaults to off */ |
1830 | hostdata->no_dma = 0; /* default is DMA enabled */ | 1977 | hostdata->no_dma = 0; /* default is DMA enabled */ |
1978 | hostdata->fast = 0; /* default is Fast SCSI transfers disabled */ | ||
1979 | hostdata->dma_mode = CTRL_DMA; /* default is Single Byte DMA */ | ||
1831 | 1980 | ||
1832 | #ifdef PROC_INTERFACE | 1981 | #ifdef PROC_INTERFACE |
1833 | hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | | 1982 | hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | |
@@ -1839,6 +1988,11 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1839 | #endif | 1988 | #endif |
1840 | #endif | 1989 | #endif |
1841 | 1990 | ||
1991 | if (check_setup_args("clock", &flags, &val, buf)) { | ||
1992 | hostdata->clock_freq = set_clk_freq(val, &val); | ||
1993 | calc_sx_table(val, hostdata->sx_table); | ||
1994 | } | ||
1995 | |||
1842 | if (check_setup_args("nosync", &flags, &val, buf)) | 1996 | if (check_setup_args("nosync", &flags, &val, buf)) |
1843 | hostdata->no_sync = val; | 1997 | hostdata->no_sync = val; |
1844 | 1998 | ||
@@ -1847,7 +2001,8 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1847 | 2001 | ||
1848 | if (check_setup_args("period", &flags, &val, buf)) | 2002 | if (check_setup_args("period", &flags, &val, buf)) |
1849 | hostdata->default_sx_per = | 2003 | hostdata->default_sx_per = |
1850 | sx_table[round_period((unsigned int) val)].period_ns; | 2004 | hostdata->sx_table[round_period((unsigned int) val, |
2005 | hostdata->sx_table)].period_ns; | ||
1851 | 2006 | ||
1852 | if (check_setup_args("disconnect", &flags, &val, buf)) { | 2007 | if (check_setup_args("disconnect", &flags, &val, buf)) { |
1853 | if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) | 2008 | if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) |
@@ -1862,17 +2017,12 @@ wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, | |||
1862 | if (check_setup_args("debug", &flags, &val, buf)) | 2017 | if (check_setup_args("debug", &flags, &val, buf)) |
1863 | hostdata->args = val & DB_MASK; | 2018 | hostdata->args = val & DB_MASK; |
1864 | 2019 | ||
1865 | if (check_setup_args("clock", &flags, &val, buf)) { | 2020 | if (check_setup_args("burst", &flags, &val, buf)) |
1866 | if (val > 7 && val < 11) | 2021 | hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA; |
1867 | val = WD33C93_FS_8_10; | 2022 | |
1868 | else if (val > 11 && val < 16) | 2023 | if (WD33C93_FS_16_20 == hostdata->clock_freq /* divisor 4 */ |
1869 | val = WD33C93_FS_12_15; | 2024 | && check_setup_args("fast", &flags, &val, buf)) |
1870 | else if (val > 15 && val < 21) | 2025 | hostdata->fast = !!val; |
1871 | val = WD33C93_FS_16_20; | ||
1872 | else | ||
1873 | val = WD33C93_FS_8_10; | ||
1874 | hostdata->clock_freq = val; | ||
1875 | } | ||
1876 | 2026 | ||
1877 | if ((i = check_setup_args("next", &flags, &val, buf))) { | 2027 | if ((i = check_setup_args("next", &flags, &val, buf))) { |
1878 | while (i) | 2028 | while (i) |
@@ -1917,53 +2067,65 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off | |||
1917 | char tbuf[128]; | 2067 | char tbuf[128]; |
1918 | struct WD33C93_hostdata *hd; | 2068 | struct WD33C93_hostdata *hd; |
1919 | struct scsi_cmnd *cmd; | 2069 | struct scsi_cmnd *cmd; |
1920 | int x, i; | 2070 | int x; |
1921 | static int stop = 0; | 2071 | static int stop = 0; |
1922 | 2072 | ||
1923 | hd = (struct WD33C93_hostdata *) instance->hostdata; | 2073 | hd = (struct WD33C93_hostdata *) instance->hostdata; |
1924 | 2074 | ||
1925 | /* If 'in' is TRUE we need to _read_ the proc file. We accept the following | 2075 | /* If 'in' is TRUE we need to _read_ the proc file. We accept the following |
1926 | * keywords (same format as command-line, but only ONE per read): | 2076 | * keywords (same format as command-line, but arguments are not optional): |
1927 | * debug | 2077 | * debug |
1928 | * disconnect | 2078 | * disconnect |
1929 | * period | 2079 | * period |
1930 | * resync | 2080 | * resync |
1931 | * proc | 2081 | * proc |
1932 | * nodma | 2082 | * nodma |
2083 | * level2 | ||
2084 | * burst | ||
2085 | * fast | ||
2086 | * nosync | ||
1933 | */ | 2087 | */ |
1934 | 2088 | ||
1935 | if (in) { | 2089 | if (in) { |
1936 | buf[len] = '\0'; | 2090 | buf[len] = '\0'; |
1937 | bp = buf; | 2091 | for (bp = buf; *bp; ) { |
2092 | while (',' == *bp || ' ' == *bp) | ||
2093 | ++bp; | ||
1938 | if (!strncmp(bp, "debug:", 6)) { | 2094 | if (!strncmp(bp, "debug:", 6)) { |
1939 | bp += 6; | 2095 | hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK; |
1940 | hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK; | ||
1941 | } else if (!strncmp(bp, "disconnect:", 11)) { | 2096 | } else if (!strncmp(bp, "disconnect:", 11)) { |
1942 | bp += 11; | 2097 | x = simple_strtoul(bp+11, &bp, 0); |
1943 | x = simple_strtoul(bp, NULL, 0); | ||
1944 | if (x < DIS_NEVER || x > DIS_ALWAYS) | 2098 | if (x < DIS_NEVER || x > DIS_ALWAYS) |
1945 | x = DIS_ADAPTIVE; | 2099 | x = DIS_ADAPTIVE; |
1946 | hd->disconnect = x; | 2100 | hd->disconnect = x; |
1947 | } else if (!strncmp(bp, "period:", 7)) { | 2101 | } else if (!strncmp(bp, "period:", 7)) { |
1948 | bp += 7; | 2102 | x = simple_strtoul(bp+7, &bp, 0); |
1949 | x = simple_strtoul(bp, NULL, 0); | ||
1950 | hd->default_sx_per = | 2103 | hd->default_sx_per = |
1951 | sx_table[round_period((unsigned int) x)].period_ns; | 2104 | hd->sx_table[round_period((unsigned int) x, |
2105 | hd->sx_table)].period_ns; | ||
1952 | } else if (!strncmp(bp, "resync:", 7)) { | 2106 | } else if (!strncmp(bp, "resync:", 7)) { |
1953 | bp += 7; | 2107 | set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0)); |
1954 | x = simple_strtoul(bp, NULL, 0); | ||
1955 | for (i = 0; i < 7; i++) | ||
1956 | if (x & (1 << i)) | ||
1957 | hd->sync_stat[i] = SS_UNSET; | ||
1958 | } else if (!strncmp(bp, "proc:", 5)) { | 2108 | } else if (!strncmp(bp, "proc:", 5)) { |
1959 | bp += 5; | 2109 | hd->proc = simple_strtoul(bp+5, &bp, 0); |
1960 | hd->proc = simple_strtoul(bp, NULL, 0); | ||
1961 | } else if (!strncmp(bp, "nodma:", 6)) { | 2110 | } else if (!strncmp(bp, "nodma:", 6)) { |
1962 | bp += 6; | 2111 | hd->no_dma = simple_strtoul(bp+6, &bp, 0); |
1963 | hd->no_dma = simple_strtoul(bp, NULL, 0); | ||
1964 | } else if (!strncmp(bp, "level2:", 7)) { | 2112 | } else if (!strncmp(bp, "level2:", 7)) { |
1965 | bp += 7; | 2113 | hd->level2 = simple_strtoul(bp+7, &bp, 0); |
1966 | hd->level2 = simple_strtoul(bp, NULL, 0); | 2114 | } else if (!strncmp(bp, "burst:", 6)) { |
2115 | hd->dma_mode = | ||
2116 | simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA; | ||
2117 | } else if (!strncmp(bp, "fast:", 5)) { | ||
2118 | x = !!simple_strtol(bp+5, &bp, 0); | ||
2119 | if (x != hd->fast) | ||
2120 | set_resync(hd, 0xff); | ||
2121 | hd->fast = x; | ||
2122 | } else if (!strncmp(bp, "nosync:", 7)) { | ||
2123 | x = simple_strtoul(bp+7, &bp, 0); | ||
2124 | set_resync(hd, x ^ hd->no_sync); | ||
2125 | hd->no_sync = x; | ||
2126 | } else { | ||
2127 | break; /* unknown keyword,syntax-error,... */ | ||
2128 | } | ||
1967 | } | 2129 | } |
1968 | return len; | 2130 | return len; |
1969 | } | 2131 | } |
@@ -1977,8 +2139,9 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off | |||
1977 | strcat(bp, tbuf); | 2139 | strcat(bp, tbuf); |
1978 | } | 2140 | } |
1979 | if (hd->proc & PR_INFO) { | 2141 | if (hd->proc & PR_INFO) { |
1980 | sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d", | 2142 | sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d" |
1981 | hd->clock_freq, hd->no_sync, hd->no_dma); | 2143 | " dma_mode=%02x fast=%d", |
2144 | hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast); | ||
1982 | strcat(bp, tbuf); | 2145 | strcat(bp, tbuf); |
1983 | strcat(bp, "\nsync_xfer[] = "); | 2146 | strcat(bp, "\nsync_xfer[] = "); |
1984 | for (x = 0; x < 7; x++) { | 2147 | for (x = 0; x < 7; x++) { |
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h index edcb0365cf0c..61ffb860dacc 100644 --- a/drivers/scsi/wd33c93.h +++ b/drivers/scsi/wd33c93.h | |||
@@ -155,6 +155,9 @@ | |||
155 | #define WD33C93_FS_12_15 OWNID_FS_12 | 155 | #define WD33C93_FS_12_15 OWNID_FS_12 |
156 | #define WD33C93_FS_16_20 OWNID_FS_16 | 156 | #define WD33C93_FS_16_20 OWNID_FS_16 |
157 | 157 | ||
158 | /* pass input-clock explicitely. accepted mhz values are 8-10,12-20 */ | ||
159 | #define WD33C93_FS_MHZ(mhz) (mhz) | ||
160 | |||
158 | /* Control register */ | 161 | /* Control register */ |
159 | #define CTRL_HSP 0x01 | 162 | #define CTRL_HSP 0x01 |
160 | #define CTRL_HA 0x02 | 163 | #define CTRL_HA 0x02 |
@@ -253,6 +256,9 @@ struct WD33C93_hostdata { | |||
253 | uchar sync_stat[8]; /* status of sync negotiation per target */ | 256 | uchar sync_stat[8]; /* status of sync negotiation per target */ |
254 | uchar no_sync; /* bitmask: don't do sync on these targets */ | 257 | uchar no_sync; /* bitmask: don't do sync on these targets */ |
255 | uchar no_dma; /* set this flag to disable DMA */ | 258 | uchar no_dma; /* set this flag to disable DMA */ |
259 | uchar dma_mode; /* DMA Burst Mode or Single Byte DMA */ | ||
260 | uchar fast; /* set this flag to enable Fast SCSI */ | ||
261 | struct sx_period sx_table[9]; /* transfer periods for actual DTC-setting */ | ||
256 | #ifdef PROC_INTERFACE | 262 | #ifdef PROC_INTERFACE |
257 | uchar proc; /* bitmask: what's in proc output */ | 263 | uchar proc; /* bitmask: what's in proc output */ |
258 | #ifdef PROC_STATISTICS | 264 | #ifdef PROC_STATISTICS |