GIT 293d6dcdb3cdfc9c57e243a2f2180121855922be git+ssh://master.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#ALL commit 591d8c124db81ce4193276b08ebe8cc2841e58a2 Author: Alan Date: Mon Jan 8 16:11:07 2007 +0000 sata_sis: Support for PATA supports This is quick rework of the patch Uwe proposed but using Kconfig not ifdefs and user selection to sort out PATA support. Instead of ifdefs and requiring the user to select both drivers the SATA driver selects the PATA one. For neatness I've also moved the extern into the function that uses it. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 5bfb12b6e4589fe9f30e4d79ffefd5ff92fda5f4 Author: Tejun Heo Date: Tue Jan 2 20:20:07 2007 +0900 libata: implement HDIO_GET_IDENTITY 'hdparm -I' doesn't work with ATAPI devices and sg_sat is not widely spread yet leaving no easy way to access ATAPI IDENTIFY data. Implement HDIO_GET_IDENTITY such that at least 'hdparm -i' works. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 8c10e0b6fd93e4e640dfd9d9791e5447642b16f9 Author: Alan Date: Wed Jan 24 11:42:38 2007 +0000 libata: trivial stuff Readability/typos etc Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 98c6bc6090e8142735420bba2f5fd0bf26710189 Author: Tejun Heo Date: Sat Jan 20 13:12:46 2007 +0900 sata_promise: kill qc->nsect Merge order left qc->nsect usage in sata_promise dangling. Kill it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit f5037cafa4ed74dd836be7754f2406a5b40265ac Author: Andrew Morton Date: Wed Jan 10 17:20:34 2007 -0800 libata piix3 support warning fix Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit 1a1a3d3ec31bdc1a50f0b9d221ade736ea50d92a Author: Alan Date: Wed Jan 10 17:13:38 2007 +0000 libata: PIIX3 support This I believe completes the PIIX range of support for libata This adds the table entries needed for the PIIX3, both a new PCI identifier and a new mode list. It also fixes an erroneous access to PCI configuration 0x48 on non UDMA capable chips. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 68bc71643afca085ac88a61916d63d92d5e38a51 Author: Mikael Pettersson Date: Sat Jan 13 21:32:30 2007 +0100 sata_promise: handle ATAPI_NODATA ourselves This patch extends sata_promise to handle ATAPI_NODATA commands internally. However, commands destined to ATA_DFLAG_CDB_INTR devices are excluded from this and continue to be returned to libata. Concrete changes: - pdc_atapi_dma_pkt() is renamed to pdc_atapi_pkt(), and is extended to set up correct headers for NODATA packets - pdc_qc_prep() calls pdc_atapi_pkt() for ATAPI_NODATA - pdc_host_intr() handles ATAPI_NODATA - pdc_qc_issue_prot() sends ATAPI_NODATA packets via the chip's packet mechanism, except for CDB_INTR devices Tested on first- and second-generation chips, SATAPI and PATAPI, with no observable regressions. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik commit f9f0ccf0b55304fd691b5e0ca266d282fdc45879 Author: Mikael Pettersson Date: Sat Jan 13 21:31:05 2007 +0100 sata_promise: issue ATAPI commands as normal packets This patch (against libata #upstream + the ATAPI cleanup patch) reimplements sata_promise's ATAPI support to format ATAPI DMA commands as normal packets, and to issue them via the hardware's normal packet machinery. It turns out that the only reason for issuing ATAPI DMA commands via the pdc_issue_atapi_pkt_cmd() procedure was to perform two interrupt-fiddling steps for ATA_DFLAG_CDB_INTR devices. But these steps aren't needed because sata_promise sets ATA_FLAG_PIO_POLLING, which disables DMA for those devices. The remaining steps can easily be done in ATA taskfile packets. Concrete changes: - pdc_atapi_dma_pkt() is extended to program all packet setup steps, and not just contain the CDB; the sequence of steps exactly mirrors what pdc_issue_atapi_pkt_cmd() did - pdc_atapi_dma_pkt() needed more parameters: simplify it by just passing 'qc' and having it extract the data it needs - pdc_issue_atai_pkt_cmd() and its two helper procedures pdc_wait_for_drq() and pdc_wait_on_busy() are removed Tested on first- and second-generation chips, SATAPI and PATAPI, with no observable regressions. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik commit e73a58d33ed70248cce56e1e271848d667cdbecc Author: Mikael Pettersson Date: Wed Jan 10 09:32:34 2007 +0100 sata_promise: ATAPI cleanup Here's a cleanup for yesterday's sata_promise ATAPI patch: - add and use a symbolic constant for the altstatus register - check return status from ata_busy_wait() - add missing newline in a warning printk() - update comment in pdc_issue_atapi_pkt_cmd() to clarify that the maybe-wait-for-INT issue cannot occur in the current driver, but may occur if the driver starts issuing ATAPI non-DMA commands as PDC packets Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik commit 02ca0fafd4c6c155f83ab92f945bd9b8a50a82f1 Author: Tejun Heo Date: Wed Jan 3 17:32:45 2007 +0900 sata_inic162x: finally, driver for initio 162x SATA controllers, take #2 Driver for Initio 162x SATA controllers. ATA r/w, ATAPI r, hotplug and suspend/resume work. ATAPI w (recording, that is) broken. Feel free to fix it, but be warned, this controller is weird. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 5feb2b16983cd6fb79829e5cb6d2def65aa7b161 Author: Tejun Heo Date: Wed Jan 3 17:30:39 2007 +0900 libata: kill qc->nsect and cursect libata used two separate sets of variables to record request size and current offset for ATA and ATAPI. This is confusing and fragile. This patch replaces qc->nsect/cursect with qc->nbytes/curbytes and kills them. Also, ata_pio_sector() is updated to use bytes for qc->cursg_ofs instead of sectors. The field used to be used in bytes for ATAPI and in sectors for ATA. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 934b0a234b3634295d6d7e236e6960a9b0195bde Author: Jeff Garzik Date: Tue Jan 9 06:28:24 2007 -0500 [libata] sata_vsc: build fix after PCI MSI feature addition Signed-off-by: Jeff Garzik commit 953dad28032c7483a04e6909031a80cffcd83668 Author: Dan Wolstenholme Date: Tue Jan 9 05:59:21 2007 -0500 [libata] sata_vsc: support PCI MSI Signed-off-by: Jeff Garzik commit 297ff8f4cf00a4f8161c2bf39e5e6527b21f196c Author: Tejun Heo Date: Tue Dec 26 19:39:50 2006 +0900 libata: handle pci_enable_device() failure while resuming Handle pci_enable_device() failure while resuming. This patch kills the "ignoring return value of 'pci_enable_device'" warning message and propagates __must_check through ata_pci_device_do_resume(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 8a431bdd5600187ac05944b0ea26221eec0df8b1 Author: Tejun Heo Date: Tue Jan 2 20:19:40 2007 +0900 libata: use ata_id_c_string() There were several places where ATA ID strings are manually terminated and in some places possibly unterminated strings were passed to string functions which don't limit length like strstr(). This patch converts all of them over to ata_id_c_string(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 475e966f594af205bd3d6d0e1f1d8336be315048 Author: Tejun Heo Date: Tue Jan 2 20:18:49 2007 +0900 libata: straighten out ATA_ID_* constants * Kill _OFS suffixes in ATA_ID_{SERNO|FW_REV|PROD}_OFS for consistency with other ATA_ID_* constants. * Kill ATA_SERNO_LEN * Add and use ATA_ID_SERNO_LEN, ATA_ID_FW_REV_LEN and ATA_ID_PROD_LEN. This change also makes ata_device_blacklisted() use proper length for fwrev. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 10485420c9bbc4cea3a06717ba0680fa1f402d9a Author: Robert Hancock Date: Wed Jan 3 18:13:57 2007 -0600 sata_nv: add suspend/resume support v3 (Resubmit) Thoughts from Jeff & company on merging the patch below into libata-dev? This has been in the -mm tree for over a month now, I haven't heard any complaints about regressions.. Signed-off-by: Jeff Garzik commit c12bcda229062a662598fe4b912ed69f5d71865d Author: Adrian Bunk Date: Thu Jan 4 00:09:36 2007 +0100 drivers/ata/: make 4 functions static This patch makes the following needlessly global functions static: - libata-core.c: ata_qc_complete_internal() - libata-scsi.c: ata_scsi_qc_new() - libata-scsi.c: ata_dump_status() - libata-scsi.c: ata_to_sense_error() Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik commit c3948690920d200ac48fd19f96a507bac663db23 Author: Alan Date: Mon Jan 8 12:07:25 2007 +0000 ahci: Remove jmicron fixup The AHCI set up is handled properly along with the other bits in the JMICRON quirk. Remove the code whacking it in ahci.c as its un-needed and also blindly fiddles with bits it doesn't own. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit d219252b7768fe1a2ef42327d9cfc7f59b7bf734 Author: Alan Date: Mon Jan 8 12:10:05 2007 +0000 libata-sff: Don't try and activate channels which are not in use An ATA controller in native mode may have one or more channels disabled and not assigned resources. In that case the existing code crashes trying to access I/O ports 0-7. Add the neccessary check. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit bdc49fc2b44755c3bc362752d0686d13ed66c95e Author: Alan Date: Mon Jan 8 17:11:13 2007 +0000 sata_via: PATA support Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik commit 3af1597042c7f5810ef4683797d0289ec27a1a1c Author: Jakub W. Jozwicki J Date: Tue Jan 9 09:01:19 2007 +0900 pata_sis: implement laptop list and add ASUS A6K/A6U In ASUS A6K/A6U hdd is connected to SiS 96x via 40c cable, however it is short cable and is UDMA66 capable. tj: fixed if () conditionals ah: fixed infinite loop Signed-off-by: Jakub W. Jozwicki Cc: Andreas Henriksson Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit cf6e925837f8151e160c7d77161a749bde7b6884 Author: J J Date: Tue Jan 9 02:26:30 2007 +0900 ata_piix: add ICH7 on Acer 3682WLMi to laptop list In Acer Aspire hdd is connected to ICH7 via 40c cable, however it is short cable and it is UDMA66 capable. Signed-off-by: J J Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 1314a0b605a50368e261dfe1c04a39af240a56a7 Author: Conke Hu Date: Tue Jan 9 05:32:51 2007 -0500 Add pci class code for SATA & AHCI, and replace some magic numbers. Signed-off-by: Conke Hu Signed-off-by: Jeff Garzik commit 74b303d97b193da9f1eea92fb85709289fefe2d9 Author: Mikael Pettersson Date: Tue Jan 9 10:51:46 2007 +0100 sata_promise: ATAPI support This patch adds ATAPI support to the sata_promise driver. This has been tested on both first- and second-generation chips (20378 and 20575), and with both SATAPI and PATAPI devices. CD-writing works. SATAPI DMA works on second-generation chips, but on first-generation chips SATAPI is limited to PIO due to what appears to be HW limitations. PATAPI DMA works on both first- and second-generation chips, but requires the separate PATA support patch before it can be used on TX2plus chips. The functional changes to the driver are: - remove ATA_FLAG_NO_ATAPI from PDC_COMMON_FLAGS - add ->check_atapi_dma() operation to enable DMA for bulk data transfers but force PIO for other ATAPI commands; this filter is from Promise's driver and largely matches pata_pdc207x.c - use a more restrictive ->check_atapi_dma() on first-generation chips to force SATAPI to always use PIO - add handling of ATAPI protocols to pdc_qc_prep(), pdc_host_intr(), and pdc_qc_issue_prot(): ATAPI_DMA is handled by the driver while non-DMA protocols are handed over to libata generic code - add pdc_issue_atapi_pkt_cmd() to handle the initial steps in issuing ATAPI DMA commands before sending the actual CDB; this procedure was ported from Promise's driver Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik commit 3af36db23828c0de89676f2ef2852b5d8a51d8b9 Author: Mikael Pettersson Date: Tue Jan 9 10:50:27 2007 +0100 sata_promise: TX2plus PATA support This patch implements a simple way of setting up per-port flags on the SATA+PATA Promise TX2plus chips, which is a prerequisite for supporting the PATA port on those chips. It is based on the observation that ap->flags isn't really used until after ->port_start() has been invoked. So it places the "exceptional" per-port flags array in the driver's private host structure, and uses it in ->port_start() to finalise the port's flags. This patch obsoletes the #promise-sata-pata branch included in the #all branch. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik commit 6ded093e0caf618e91dc512ef7ee501202ff5e3b Author: Arjan van de Ven Date: Tue Dec 19 13:05:53 2006 -0800 [PATCH] user of the jiffies rounding patch: ATA subsystem This patch introduces users of the round_jiffies() function: ATA subsystem This delayed work is of the "about once a second" variety and can be rounded to coincide with other wakers. Signed-off-by: Arjan van de Ven Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit ca672a20983c44738ec928bc137285693d7aa6bd Author: Alan Cox Date: Fri Dec 15 13:08:50 2006 -0800 [PATCH] pci: Move PCI_VDEVICE from libata to core Updated diff which doesn't move the comment as per Jeff's request and corrects the docs as per report on l/k Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit 3ea34e2aa729616129cd4b0233c3ed64db6b8127 Author: Jeff Garzik Date: Mon Dec 11 11:14:06 2006 -0500 [libata] trim trailing whitespace Most of these contributed by that mysterious figger known as A.C. Signed-off-by: Jeff Garzik commit bf9ef8fbc5290b06010b0c478bd72dac93dba5e6 Author: Sylvain Munaut Date: Fri Dec 8 00:14:16 2006 +0100 [PATCH] libata: Add support for the MPC52xx ATA controller This patch adds initial libata support for the Freescale MPC5200 integrated IDE controller. Signed-off-by: Sylvain Munaut Signed-off-by: Jeff Garzik commit 25c838d0640b8fc347d47ba1ba0dce6f555c4035 Author: Alan Date: Thu Dec 7 08:59:14 2006 -0800 [PATCH] pata_it8213: Add new driver for the IT8213 card Add a driver for the IT8213 which is a single channel ICH-ish PATA controller. As it is very different to the IT8211/2 it gets its own driver. There is a legacy drivers/ide driver also available and I'll post that once I get time to test it all out (probably early January). If anyone else needs the drivers/ide driver and wants to do the merge for drivers/ide (Bart ??) then I'll forward it. [akpm@osdl.org: add PCI ID, constify needed_pio[]] Signed-off-by: Alan Cox Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit 2aecfd507f713b08bfc04ed52dab0fcdb66f0db4 Author: Uwe Koziolek Date: Mon Dec 4 01:34:42 2006 +0100 [PATCH] sata_sis: support SiS966/966L The SiS966/966L has different PCI-IDs for native mode and AHCI mode. The SiS966 supports four SATA ports only in native mode. Added additional PCI-ID 0x0183 for SiS965/965L. this patch is based on the code from David Wang from SiS Corporation published on SiS Website. Signed-off-by: Uwe Koziolek Signed-off-by: Jeff Garzik commit 03ee5b1cdd09ed1ee2e75d0bc647fc5db66b9d07 Author: Tejun Heo Date: Fri Jan 26 20:10:25 2007 +0900 libata: fix ata_eh_suspend() return value ata_eh_suspend() was returning 0 regardless of failure. This bug has potential to lose data on suspend. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik commit 514efa0aa0ec1a7a8b501e63075d0ddb831f26ad Author: Fiodor Suietov Date: Tue Dec 19 12:33:20 2006 -0800 [PATCH] libata: wrong sizeof for BUFFER I have reproduced the AE_AML_BUFFER_LIMIT exception mentioned in basing on the SSDT ASL code and libata ata_acpi_push_id() code. There is an oversight in ata_acpi_push_id() causing the exception. The following update fixes it: Signed-off-by: Fiodor Suietov Cc: Jeff Garzik Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik commit 35e5ce75c8ed97e28edf75b55d39471acefe5062 Author: Kristen Carlson Accardi Date: Fri Nov 10 16:14:47 2006 -0800 [PATCH] libata: change order of _SDD/_GTF execution (resend #3) Make the sdd call come before gtf. _SDD is used to provide input to the _GTF file, so it should be executed first. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jeff Garzik (cherry picked from 89d74215e1e5b79ea084385b5c83d0e33cf2d655 commit) commit 0fef014f90551cbc87fb7010ebbc3f57fe7ebab6 Author: Kristen Carlson Accardi Date: Thu Sep 28 11:29:12 2006 -0700 [PATCH] libata: ACPI _SDD support _SDD (Set Device Data) is an ACPI method that is used to tell the firmware what the identify data is of the device that is attached to the port. It is an optional method, and it's ok for it to be missing. Because of this, we always return success from the routine that calls this method, even if the execution fails. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jeff Garzik (cherry picked from 39aa79e0a1f5f2e28aa341f035940746a98b45b1 commit) commit 0ec3be1061aeed2368746f76b48d09368c2ad08c Author: Kristen Carlson Accardi Date: Thu Sep 28 11:29:01 2006 -0700 [PATCH] libata: ACPI and _GTF support _GTF is an acpi method that is used to reinitialize the drive. It returns a task file containing ata commands that are sent back to the drive to restore it to boot up defaults. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jeff Garzik (cherry picked from 9c69cab24b51a89664f4c0dfaf8a436d32117624 commit) commit a718728f9e40ec79c0879ec6509a54fee214f5b2 Author: Tejun Heo Date: Sat Jan 27 11:04:26 2007 +0900 ahci: port_no should be used when clearing IRQ in ahci_thaw() ap->id is logcial port ID which is unique among all ATA ports and doesn't have anything to do with hardware port index. ap->port_no is the hardware port index and thus should be used when clearing IRQ mask in ahci_thaw(). This problem has been spotted by Jeff Garzik . Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik Documentation/kernel-parameters.txt | 5 drivers/ata/Kconfig | 48 ++ drivers/ata/Makefile | 5 drivers/ata/ahci.c | 22 - drivers/ata/ata_piix.c | 23 + drivers/ata/libata-acpi.c | 698 ++++++++++++++++++++++++++++++ drivers/ata/libata-core.c | 99 ++-- drivers/ata/libata-eh.c | 9 drivers/ata/libata-scsi.c | 95 +++- drivers/ata/libata-sff.c | 24 + drivers/ata/libata.h | 15 + drivers/ata/pata_ali.c | 8 drivers/ata/pata_cs5520.c | 2 drivers/ata/pata_cs5530.c | 8 drivers/ata/pata_hpt366.c | 20 - drivers/ata/pata_hpt37x.c | 23 - drivers/ata/pata_hpt3x3.c | 2 drivers/ata/pata_it8213.c | 354 +++++++++++++++ drivers/ata/pata_it821x.c | 20 - drivers/ata/pata_jmicron.c | 2 drivers/ata/pata_marvell.c | 4 drivers/ata/pata_mpc52xx.c | 563 ++++++++++++++++++++++++ drivers/ata/pata_pdc202xx_old.c | 5 drivers/ata/pata_serverworks.c | 19 - drivers/ata/pata_sil680.c | 2 drivers/ata/pata_sis.c | 36 +- drivers/ata/pata_via.c | 10 drivers/ata/pata_winbond.c | 16 - drivers/ata/sata_inic162x.c | 809 +++++++++++++++++++++++++++++++++++ drivers/ata/sata_nv.c | 239 +++++++--- drivers/ata/sata_promise.c | 226 +++++++++- drivers/ata/sata_qstor.c | 2 drivers/ata/sata_sil.c | 10 drivers/ata/sata_sil24.c | 5 drivers/ata/sata_sis.c | 105 +++-- drivers/ata/sata_via.c | 110 ++++- drivers/ata/sata_vsc.c | 44 ++ drivers/pci/quirks.c | 2 include/linux/ata.h | 11 include/linux/libata.h | 19 - include/linux/pci_ids.h | 3 41 files changed, 3381 insertions(+), 341 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 25d2985..179ac52 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -48,6 +48,7 @@ parameter is applicable: ISAPNP ISA PnP code is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. + LIBATA Libata driver is enabled LP Printer support is enabled. LOOP Loopback device support is enabled. M68k M68k architecture is enabled. @@ -1026,6 +1027,10 @@ and is between 256 and 4096 characters. emulation library even if a 387 maths coprocessor is present. + noacpi [LIBATA] Disables use of ACPI in libata suspend/resume + when set. + Format: + noaliencache [MM, NUMA] Disables the allcoation of alien caches in the slab allocator. Saves per-node memory, but will impact performance on real NUMA hardware. diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 1c94b43..f15db5b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -116,11 +116,14 @@ config SATA_SIL24 If unsure, say N. config SATA_SIS - tristate "SiS 964/180 SATA support" + tristate "SiS 964/965/966/180 SATA support" depends on PCI + select PATA_SIS help - This option enables support for SiS Serial ATA 964/180. - + This option enables support for SiS Serial ATA on + SiS 964/965/966/180 and Parallel ATA on SiS 180. + The PATA support for SiS 180 requires additionally to + enable the PATA_SIS driver in the config. If unsure, say N. config SATA_ULI @@ -147,11 +150,30 @@ config SATA_VITESSE If unsure, say N. +config SATA_INIC162X + tristate "Initio 162x SATA support (HIGHLY EXPERIMENTAL)" + depends on PCI && EXPERIMENTAL + help + This option enables support for Initio 162x Serial ATA. + config SATA_INTEL_COMBINED bool depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX) default y +config SATA_ACPI + bool + depends on ACPI && PCI + default y + help + This option adds support for SATA-related ACPI objects. + These ACPI objects add the ability to retrieve taskfiles + from the ACPI BIOS and write them to the disk controller. + These objects may be related to performance, security, + power management, or other areas. + You can disable this at kernel boot time by using the + option libata.noacpi=1 + config PATA_ALI tristate "ALi PATA support (Experimental)" depends on PCI && EXPERIMENTAL @@ -296,7 +318,7 @@ config PATA_ISAPNP If unsure, say N. config PATA_IT821X - tristate "IT821x PATA support (Experimental)" + tristate "IT8211/2 PATA support (Experimental)" depends on PCI && EXPERIMENTAL help This option enables support for the ITE 8211 and 8212 @@ -305,6 +327,15 @@ config PATA_IT821X If unsure, say N. +config PATA_IT8213 + tristate "IT8213 PATA support (Experimental)" + depends on PCI && EXPERIMENTAL + help + This option enables support for the ITE 821 PATA + controllers via the new ATA layer. + + If unsure, say N. + config PATA_JMICRON tristate "JMicron PATA support" depends on PCI @@ -341,6 +372,15 @@ config PATA_MARVELL If unsure, say N. +config PATA_MPC52xx + tristate "Freescale MPC52xx SoC internal IDE" + depends on PPC_MPC52xx + help + This option enables support for integrated IDE controller + of the Freescale MPC52xx SoC. + + If unsure, say N. + config PATA_MPIIX tristate "Intel PATA MPIIX support" depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index bc3d81a..74298af 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SATA_SX4) += sata_sx4.o obj-$(CONFIG_SATA_NV) += sata_nv.o obj-$(CONFIG_SATA_ULI) += sata_uli.o obj-$(CONFIG_SATA_MV) += sata_mv.o +obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o obj-$(CONFIG_PDC_ADMA) += pdc_adma.o obj-$(CONFIG_PATA_ALI) += pata_ali.o @@ -33,11 +34,13 @@ obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o obj-$(CONFIG_PATA_IT821X) += pata_it821x.o +obj-$(CONFIG_PATA_IT8213) += pata_it8213.o obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o obj-$(CONFIG_PATA_OPTI) += pata_opti.o obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o +obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o @@ -63,4 +66,4 @@ # Should be last libata driver obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o - +libata-$(CONFIG_SATA_ACPI) += libata-acpi.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 28a82e3..a6144f5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -431,7 +431,7 @@ static const struct pci_device_id ahci_p /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - 0x010601, 0xffffff, board_ahci }, + PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, { } /* terminate list */ }; @@ -1282,7 +1282,7 @@ static void ahci_thaw(struct ata_port *a /* clear IRQ */ tmp = readl(port_mmio + PORT_IRQ_STAT); writel(tmp, port_mmio + PORT_IRQ_STAT); - writel(1 << ap->id, mmio + HOST_IRQ_STAT); + writel(1 << ap->port_no, mmio + HOST_IRQ_STAT); /* turn IRQ back on */ writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); @@ -1397,7 +1397,9 @@ static int ahci_pci_device_resume(struct void __iomem *mmio = host->mmio_base; int rc; - ata_pci_device_do_resume(pdev); + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { rc = ahci_reset_controller(mmio, pdev); @@ -1619,11 +1621,11 @@ static void ahci_print_info(struct ata_p speed_s = "?"; pci_read_config_word(pdev, 0x0a, &cc); - if (cc == 0x0101) + if (cc == PCI_CLASS_STORAGE_IDE) scc_s = "IDE"; - else if (cc == 0x0106) + else if (cc == PCI_CLASS_STORAGE_SATA) scc_s = "SATA"; - else if (cc == 0x0104) + else if (cc == PCI_CLASS_STORAGE_RAID) scc_s = "RAID"; else scc_s = "unknown"; @@ -1685,13 +1687,9 @@ static int ahci_init_one (struct pci_dev if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - /* JMicron-specific fixup: make sure we're in AHCI mode */ - /* This is protected from races with ata_jmicron by the pci probe - locking */ if (pdev->vendor == PCI_VENDOR_ID_JMICRON) { - /* AHCI enable, AHCI on function 0 */ - pci_write_config_byte(pdev, 0x41, 0xa1); - /* Function 1 is the PATA controller */ + /* Function 1 is the PATA controller except on the 368, where + we are not AHCI anyway */ if (PCI_FUNC(pdev->devfn)) return -ENODEV; } diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 47701b2..f15ef88 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -118,7 +118,7 @@ enum { PIIX_80C_SEC = (1 << 7) | (1 << 6), /* controller IDs */ - piix_pata_33 = 0, /* PIIX3 or 4 at 33Mhz */ + piix_pata_33 = 0, /* PIIX4 at 33Mhz */ ich_pata_33 = 1, /* ICH up to UDMA 33 only */ ich_pata_66 = 2, /* ICH up to 66 Mhz */ ich_pata_100 = 3, /* ICH up to UDMA 100 */ @@ -128,6 +128,7 @@ enum { ich6_sata_ahci = 7, ich6m_sata_ahci = 8, ich8_sata_ahci = 9, + piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -165,6 +166,8 @@ static unsigned int in_module_init = 1; static const struct pci_device_id piix_pci_tbl[] = { #ifdef ATA_ENABLE_PATA + /* Intel PIIX3 for the 430HX etc */ + { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma }, /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, @@ -441,7 +444,7 @@ static const struct piix_map_db *piix_ma }; static struct ata_port_info piix_port_info[] = { - /* piix_pata_33: 0: PIIX3 or 4 at 33MHz */ + /* piix_pata_33: 0: PIIX4 at 33MHz */ { .sht = &piix_sht, .flags = PIIX_PATA_FLAGS, @@ -543,6 +546,14 @@ static struct ata_port_info piix_port_in .port_ops = &piix_sata_ops, }, + /* piix_pata_mwdma: 10: PIIX3 MWDMA only */ + { + .sht = &piix_sht, + .flags = PIIX_PATA_FLAGS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .port_ops = &piix_pata_ops, + }, }; static struct pci_bits piix_enable_bits[] = { @@ -569,6 +580,7 @@ struct ich_laptop { static const struct ich_laptop ich_laptop[] = { /* devid, subvendor, subdev */ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ + { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ /* end marker */ { 0, } }; @@ -632,7 +644,7 @@ static int piix_pata_prereset(struct ata if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) return -ENOENT; - + ap->cbl = ATA_CBL_PATA40; return ata_std_prereset(ap); } @@ -776,7 +788,7 @@ static void do_pata_set_dmamode (struct u16 master_data; u8 speed = adev->dma_mode; int devid = adev->devno + 2 * ap->port_no; - u8 udma_enable; + u8 udma_enable = 0; static const /* ISP RTC */ u8 timings[][2] = { { 0, 0 }, @@ -786,7 +798,8 @@ static void do_pata_set_dmamode (struct { 2, 3 }, }; pci_read_config_word(dev, master_port, &master_data); - pci_read_config_byte(dev, 0x48, &udma_enable); + if (ap->udma_mask) + pci_read_config_byte(dev, 0x48, &udma_enable); if (speed >= XFER_UDMA_0) { unsigned int udma = adev->dma_mode - XFER_UDMA_0; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c new file mode 100644 index 0000000..b4e8be5 --- /dev/null +++ b/drivers/ata/libata-acpi.c @@ -0,0 +1,698 @@ +/* + * libata-acpi.c + * Provides ACPI support for PATA/SATA. + * + * Copyright (C) 2006 Intel Corp. + * Copyright (C) 2006 Randy Dunlap + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "libata.h" + +#include +#include +#include +#include +#include +#include +#include + +#define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff) +#define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */ +#define NO_PORT_MULT 0xffff +#define SATA_ADR_RSVD 0xffffffff + +#define REGS_PER_GTF 7 +struct taskfile_array { + u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ +}; + + +/** + * sata_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev + * + * This function is somewhat SATA-specific. Or at least the + * PATA & SATA versions of this function are different, + * so it's not entirely generic code. + * + * Returns 0 on success, <0 on error. + */ +static int sata_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) +{ + struct pci_dev *pci_dev; + acpi_integer addr; + + pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */ + /* Please refer to the ACPI spec for the syntax of _ADR. */ + addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); + *pcidevfn = addr; + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); + if (!*handle) + return -ENODEV; + return 0; +} + +/** + * pata_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev + * + * The PATA and SATA versions of this function are different. + * + * Returns 0 on success, <0 on error. + */ +static int pata_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) +{ + unsigned int bus, devnum, func; + acpi_integer addr; + acpi_handle dev_handle, parent_handle; + struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; + acpi_status status; + struct acpi_device_info *dinfo = NULL; + int ret = -ENODEV; + struct pci_dev *pdev = to_pci_dev(dev); + + bus = pdev->bus->number; + devnum = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + + dev_handle = DEVICE_ACPI_HANDLE(dev); + parent_handle = DEVICE_ACPI_HANDLE(dev->parent); + + status = acpi_get_object_info(parent_handle, &buffer); + if (ACPI_FAILURE(status)) + goto err; + + dinfo = buffer.pointer; + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == bus) { + /* ACPI spec for _ADR for PCI bus: */ + addr = (acpi_integer)(devnum << 16 | func); + *pcidevfn = addr; + *handle = dev_handle; + } else { + goto err; + } + + if (!*handle) + goto err; + ret = 0; +err: + kfree(dinfo); + return ret; +} + +struct walk_info { /* can be trimmed some */ + struct device *dev; + struct acpi_device *adev; + acpi_handle handle; + acpi_integer pcidevfn; + unsigned int drivenum; + acpi_handle obj_handle; + struct ata_port *ataport; + struct ata_device *atadev; + u32 sata_adr; + int status; + char basepath[ACPI_PATHNAME_MAX]; + int basepath_len; +}; + +static acpi_status get_devices(acpi_handle handle, + u32 level, void *context, void **return_value) +{ + acpi_status status; + struct walk_info *winfo = context; + struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL}; + char *pathname; + struct acpi_buffer buffer; + struct acpi_device_info *dinfo; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf); + if (status) + goto ret; + pathname = namebuf.pointer; + + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + status = acpi_get_object_info(handle, &buffer); + if (ACPI_FAILURE(status)) + goto out2; + + dinfo = buffer.pointer; + + /* find full device path name for pcidevfn */ + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == winfo->pcidevfn) { + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + ":%s: matches pcidevfn (0x%llx)\n", + pathname, winfo->pcidevfn); + strlcpy(winfo->basepath, pathname, + sizeof(winfo->basepath)); + winfo->basepath_len = strlen(pathname); + goto out; + } + + /* if basepath is not yet known, ignore this object */ + if (!winfo->basepath_len) + goto out; + + /* if this object is in scope of basepath, maybe use it */ + if (strncmp(pathname, winfo->basepath, + winfo->basepath_len) == 0) { + if (!(dinfo->valid & ACPI_VALID_ADR)) + goto out; + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "GOT ONE: (%s) root_port = 0x%llx," + " port_num = 0x%llx\n", pathname, + SATA_ROOT_PORT(dinfo->address), + SATA_PORT_NUMBER(dinfo->address)); + /* heuristics: */ + if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT) + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, + KERN_DEBUG, "warning: don't" + " know how to handle SATA port" + " multiplier\n"); + if (SATA_ROOT_PORT(dinfo->address) == + winfo->ataport->port_no && + SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) { + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, + KERN_DEBUG, + "THIS ^^^^^ is the requested" + " SATA drive (handle = 0x%p)\n", + handle); + winfo->sata_adr = dinfo->address; + winfo->obj_handle = handle; + } + } +out: + kfree(dinfo); +out2: + kfree(pathname); + +ret: + return status; +} + +/* Get the SATA drive _ADR object. */ +static int get_sata_adr(struct device *dev, acpi_handle handle, + acpi_integer pcidevfn, unsigned int drive, + struct ata_port *ap, + struct ata_device *atadev, u32 *dev_adr) +{ + acpi_status status; + struct walk_info *winfo; + int err = -ENOMEM; + + winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL); + if (!winfo) + goto out; + + winfo->dev = dev; + winfo->atadev = atadev; + winfo->ataport = ap; + if (acpi_bus_get_device(handle, &winfo->adev) < 0) + if (ata_msg_probe(ap)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "acpi_bus_get_device failed\n"); + winfo->handle = handle; + winfo->pcidevfn = pcidevfn; + winfo->drivenum = drive; + + status = acpi_get_devices(NULL, get_devices, winfo, NULL); + if (ACPI_FAILURE(status)) { + if (ata_msg_probe(ap)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "%s: acpi_get_devices failed\n", + __FUNCTION__); + err = -ENODEV; + } else { + *dev_adr = winfo->sata_adr; + atadev->obj_handle = winfo->obj_handle; + err = 0; + } + kfree(winfo); +out: + return err; +} + +/** + * do_drive_get_GTF - get the drive bootup default taskfile settings + * @ap: the ata_port for the drive + * @ix: target ata_device (drive) index + * @gtf_length: number of bytes of _GTF data returned at @gtf_address + * @gtf_address: buffer containing _GTF taskfile arrays + * + * This applies to both PATA and SATA drives. + * + * The _GTF method has no input parameters. + * It returns a variable number of register set values (registers + * hex 1F1..1F7, taskfiles). + * The is not known in advance, so have ACPI-CA + * allocate the buffer as needed and return it, then free it later. + * + * The returned @gtf_length and @gtf_address are only valid if the + * function return value is 0. + */ +static int do_drive_get_GTF(struct ata_port *ap, int ix, + unsigned int *gtf_length, unsigned long *gtf_address, + unsigned long *obj_loc) +{ + acpi_status status; + acpi_handle dev_handle = NULL; + acpi_handle chan_handle, drive_handle; + acpi_integer pcidevfn = 0; + u32 dev_adr; + struct acpi_buffer output; + union acpi_object *out_obj; + struct device *dev = ap->host->dev; + struct ata_device *atadev = &ap->device[ix]; + int err = -ENODEV; + + *gtf_length = 0; + *gtf_address = 0UL; + *obj_loc = 0UL; + + if (noacpi) + return 0; + + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: ENTER: ap->id: %d, port#: %d\n", + __FUNCTION__, ap->id, ap->port_no); + + if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, "%s: ERR: " + "ata_dev_present: %d, PORT_DISABLED: %lu\n", + __FUNCTION__, ata_dev_enabled(atadev), + ap->flags & ATA_FLAG_DISABLED); + goto out; + } + + /* Don't continue if device has no _ADR method. + * _GTF is intended for known motherboard devices. */ + if (!(ap->cbl == ATA_CBL_SATA)) { + err = pata_get_dev_handle(dev, &dev_handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: pata_get_dev_handle failed (%d)\n", + __FUNCTION__, err); + goto out; + } + } else { + err = sata_get_dev_handle(dev, &dev_handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: sata_get_dev_handle failed (%d\n", + __FUNCTION__, err); + goto out; + } + } + + /* Get this drive's _ADR info. if not already known. */ + if (!atadev->obj_handle) { + if (!(ap->cbl == ATA_CBL_SATA)) { + /* get child objects of dev_handle == channel objects, + * + _their_ children == drive objects */ + /* channel is ap->port_no */ + chan_handle = acpi_get_child(dev_handle, + ap->port_no); + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: chan adr=%d: chan_handle=0x%p\n", + __FUNCTION__, ap->port_no, + chan_handle); + if (!chan_handle) { + err = -ENODEV; + goto out; + } + /* TBD: could also check ACPI object VALID bits */ + drive_handle = acpi_get_child(chan_handle, ix); + if (!drive_handle) { + err = -ENODEV; + goto out; + } + dev_adr = ix; + atadev->obj_handle = drive_handle; + } else { /* for SATA mode */ + dev_adr = SATA_ADR_RSVD; + err = get_sata_adr(dev, dev_handle, pcidevfn, 0, + ap, atadev, &dev_adr); + } + if (err < 0 || dev_adr == SATA_ADR_RSVD || + !atadev->obj_handle) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: get_sata/pata_adr failed: " + "err=%d, dev_adr=%u, obj_handle=0x%p\n", + __FUNCTION__, err, dev_adr, + atadev->obj_handle); + goto out; + } + } + + /* Setting up output buffer */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTF has no input parameters */ + err = -EIO; + status = acpi_evaluate_object(atadev->obj_handle, "_GTF", + NULL, &output); + if (ACPI_FAILURE(status)) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: Run _GTF error: status = 0x%x\n", + __FUNCTION__, status); + goto out; + } + + if (!output.length || !output.pointer) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " + "length or ptr is NULL (0x%llx, 0x%p)\n", + __FUNCTION__, + (unsigned long long)output.length, + output.pointer); + kfree(output.pointer); + goto out; + } + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + kfree(output.pointer); + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, "%s: Run _GTF: " + "error: expected object type of " + " ACPI_TYPE_BUFFER, got 0x%x\n", + __FUNCTION__, out_obj->type); + err = -ENOENT; + goto out; + } + + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length % REGS_PER_GTF) { + if (ata_msg_drv(ap)) + ata_dev_printk(atadev, KERN_ERR, + "%s: unexpected GTF length (%d) or addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + out_obj->buffer.pointer); + err = -ENOENT; + goto out; + } + + *gtf_length = out_obj->buffer.length; + *gtf_address = (unsigned long)out_obj->buffer.pointer; + *obj_loc = (unsigned long)out_obj; + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, "%s: returning " + "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", + __FUNCTION__, *gtf_length, *gtf_address, *obj_loc); + err = 0; +out: + return err; +} + +/** + * taskfile_load_raw - send taskfile registers to host controller + * @ap: Port to which output is sent + * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) + * + * Outputs ATA taskfile to standard ATA host controller using MMIO + * or PIO as indicated by the ATA_FLAG_MMIO flag. + * Writes the control, feature, nsect, lbal, lbam, and lbah registers. + * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect, + * hob_lbal, hob_lbam, and hob_lbah. + * + * This function waits for idle (!BUSY and !DRQ) after writing + * registers. If the control register has a new value, this + * function also waits for idle after writing control and before + * writing the remaining registers. + * + * LOCKING: TBD: + * Inherited from caller. + */ +static void taskfile_load_raw(struct ata_port *ap, + struct ata_device *atadev, + const struct taskfile_array *gtf) +{ + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: " + "%02x %02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, + gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], + gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); + + if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0) + && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0) + && (gtf->tfa[6] == 0)) + return; + + if (ap->ops->qc_issue) { + struct ata_taskfile tf; + unsigned int err; + + ata_tf_init(atadev, &tf); + + /* convert gtf to tf */ + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ + tf.protocol = atadev->class == ATA_DEV_ATAPI ? + ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA; + tf.feature = gtf->tfa[0]; /* 0x1f1 */ + tf.nsect = gtf->tfa[1]; /* 0x1f2 */ + tf.lbal = gtf->tfa[2]; /* 0x1f3 */ + tf.lbam = gtf->tfa[3]; /* 0x1f4 */ + tf.lbah = gtf->tfa[4]; /* 0x1f5 */ + tf.device = gtf->tfa[5]; /* 0x1f6 */ + tf.command = gtf->tfa[6]; /* 0x1f7 */ + + err = ata_exec_internal(atadev, &tf, NULL, DMA_NONE, NULL, 0); + if (err && ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_ERR, + "%s: ata_exec_internal failed: %u\n", + __FUNCTION__, err); + } else + if (ata_msg_warn(ap)) + ata_dev_printk(atadev, KERN_WARNING, + "%s: SATA driver is missing qc_issue function" + " entry points\n", + __FUNCTION__); +} + +/** + * do_drive_set_taskfiles - write the drive taskfile settings from _GTF + * @ap: the ata_port for the drive + * @atadev: target ata_device + * @gtf_length: total number of bytes of _GTF taskfiles + * @gtf_address: location of _GTF taskfile arrays + * + * This applies to both PATA and SATA drives. + * + * Write {gtf_address, length gtf_length} in groups of + * REGS_PER_GTF bytes. + */ +static int do_drive_set_taskfiles(struct ata_port *ap, + struct ata_device *atadev, unsigned int gtf_length, + unsigned long gtf_address) +{ + int err = -ENODEV; + int gtf_count = gtf_length / REGS_PER_GTF; + int ix; + struct taskfile_array *gtf; + + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: ENTER: ap->id: %d, port#: %d\n", + __FUNCTION__, ap->id, ap->port_no); + + if (noacpi || !(ap->cbl == ATA_CBL_SATA)) + return 0; + + if (!ata_dev_enabled(atadev) || (ap->flags & ATA_FLAG_DISABLED)) + goto out; + if (!gtf_count) /* shouldn't be here */ + goto out; + + if (gtf_length % REGS_PER_GTF) { + if (ata_msg_drv(ap)) + ata_dev_printk(atadev, KERN_ERR, + "%s: unexpected GTF length (%d)\n", + __FUNCTION__, gtf_length); + goto out; + } + + for (ix = 0; ix < gtf_count; ix++) { + gtf = (struct taskfile_array *) + (gtf_address + ix * REGS_PER_GTF); + + /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ + taskfile_load_raw(ap, atadev, gtf); + } + + err = 0; +out: + return err; +} + +/** + * ata_acpi_exec_tfs - get then write drive taskfile settings + * @ap: the ata_port for the drive + * + * This applies to both PATA and SATA drives. + */ +int ata_acpi_exec_tfs(struct ata_port *ap) +{ + int ix; + int ret =0; + unsigned int gtf_length; + unsigned long gtf_address; + unsigned long obj_loc; + + if (noacpi) + return 0; + + for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { + if (!ata_dev_enabled(&ap->device[ix])) + continue; + + ret = do_drive_get_GTF(ap, ix, + >f_length, >f_address, &obj_loc); + if (ret < 0) { + if (ata_msg_probe(ap)) + ata_port_printk(ap, KERN_DEBUG, + "%s: get_GTF error (%d)\n", + __FUNCTION__, ret); + break; + } + + ret = do_drive_set_taskfiles(ap, &ap->device[ix], + gtf_length, gtf_address); + kfree((void *)obj_loc); + if (ret < 0) { + if (ata_msg_probe(ap)) + ata_port_printk(ap, KERN_DEBUG, + "%s: set_taskfiles error (%d)\n", + __FUNCTION__, ret); + break; + } + } + + return ret; +} + +/** + * ata_acpi_push_id - send Identify data to drive + * @ap: the ata_port for the drive + * @ix: drive index + * + * _SDD ACPI object: for SATA mode only + * Must be after Identify (Packet) Device -- uses its data + * ATM this function never returns a failure. It is an optional + * method and if it fails for whatever reason, we should still + * just keep going. + */ +int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) +{ + acpi_handle handle; + acpi_integer pcidevfn; + int err; + struct device *dev = ap->host->dev; + struct ata_device *atadev = &ap->device[ix]; + u32 dev_adr; + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[1]; + + if (noacpi) + return 0; + + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: ap->id: %d, ix = %d, port#: %d\n", + __FUNCTION__, ap->id, ix, ap->port_no); + + /* Don't continue if not a SATA device. */ + if (!(ap->cbl == ATA_CBL_SATA)) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: Not a SATA device\n", __FUNCTION__); + goto out; + } + + /* Don't continue if device has no _ADR method. + * _SDD is intended for known motherboard devices. */ + err = sata_get_dev_handle(dev, &handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: sata_get_dev_handle failed (%d\n", + __FUNCTION__, err); + goto out; + } + + /* Get this drive's _ADR info, if not already known */ + if (!atadev->obj_handle) { + dev_adr = SATA_ADR_RSVD; + err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, + &dev_adr); + if (err < 0 || dev_adr == SATA_ADR_RSVD || + !atadev->obj_handle) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "%s: get_sata_adr failed: " + "err=%d, dev_adr=%u, obj_handle=0x%p\n", + __FUNCTION__, err, dev_adr, + atadev->obj_handle); + goto out; + } + } + + /* Give the drive Identify data to the drive via the _SDD method */ + /* _SDD: set up input parameters */ + input.count = 1; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = sizeof(atadev->id[0]) * ATA_ID_WORDS; + in_params[0].buffer.pointer = (u8 *)atadev->id; + /* Output buffer: _SDD has no output */ + + /* It's OK for _SDD to be missing too. */ + swap_buf_le16(atadev->id, ATA_ID_WORDS); + status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL); + swap_buf_le16(atadev->id, ATA_ID_WORDS); + + err = ACPI_FAILURE(status) ? -EIO : 0; + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(atadev, KERN_DEBUG, + "ata%u(%u): %s _SDD error: status = 0x%x\n", + ap->id, ap->device->devno, + __FUNCTION__, status); + } + + /* always return success */ +out: + return 0; +} + + diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a388a8d..5ffc4c5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -90,6 +90,10 @@ static int ata_probe_timeout = ATA_TMOUT module_param(ata_probe_timeout, int, 0444); MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)"); +int noacpi; +module_param(noacpi, int, 0444); +MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set"); + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Library module for ATA devices"); MODULE_LICENSE("GPL"); @@ -1156,7 +1160,7 @@ void ata_port_flush_task(struct ata_port ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__); } -void ata_qc_complete_internal(struct ata_queued_cmd *qc) +static void ata_qc_complete_internal(struct ata_queued_cmd *qc) { struct completion *waiting = qc->private_data; @@ -1249,7 +1253,7 @@ unsigned ata_exec_internal_sg(struct ata buflen += sg[i].length; ata_sg_init(qc, sg, n_elem); - qc->nsect = buflen / ATA_SECT_SIZE; + qc->nbytes = buflen; } qc->private_data = &wait; @@ -1291,7 +1295,7 @@ unsigned ata_exec_internal_sg(struct ata if (ap->ops->post_internal_cmd) ap->ops->post_internal_cmd(qc); - if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) { + if ((qc->flags & ATA_QCFLAG_FAILED) && !qc->err_mask) { if (ata_msg_warn(ap)) ata_dev_printk(dev, KERN_WARNING, "zero err_mask for failed " @@ -1620,6 +1624,16 @@ int ata_dev_configure(struct ata_device ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", __FUNCTION__, ap->id, dev->devno); + /* set _SDD */ + rc = ata_acpi_push_id(ap, dev->devno); + if (rc) { + ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", + rc); + } + + /* retrieve and execute the ATA task file of _GTF */ + ata_acpi_exec_tfs(ap); + /* print device capabilities */ if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, @@ -2492,7 +2506,7 @@ int ata_set_mode(struct ata_port *ap, st for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; - /* don't udpate suspended devices' xfer mode */ + /* don't update suspended devices' xfer mode */ if (!ata_dev_ready(dev)) continue; @@ -3186,7 +3200,8 @@ static int ata_dev_same_device(struct at const u16 *new_id) { const u16 *old_id = dev->id; - unsigned char model[2][41], serial[2][21]; + unsigned char model[2][ATA_ID_PROD_LEN + 1]; + unsigned char serial[2][ATA_ID_SERNO_LEN + 1]; u64 new_n_sectors; if (dev->class != new_class) { @@ -3195,10 +3210,10 @@ static int ata_dev_same_device(struct at return 0; } - ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); - ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); - ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); - ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1])); + ata_id_c_string(old_id, model[0], ATA_ID_PROD, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0])); + ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1])); new_n_sectors = ata_id_n_sectors(new_id); if (strcmp(model[0], model[1])) { @@ -3323,37 +3338,20 @@ static const struct ata_blacklist_entry { } }; -static int ata_strim(char *s, size_t len) -{ - len = strnlen(s, len); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - return len; -} - unsigned long ata_device_blacklisted(const struct ata_device *dev) { - unsigned char model_num[40]; - unsigned char model_rev[16]; - unsigned int nlen, rlen; + unsigned char model_num[ATA_ID_PROD_LEN + 1]; + unsigned char model_rev[ATA_ID_FW_REV_LEN + 1]; const struct ata_blacklist_entry *ad = ata_device_blacklist; - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, - sizeof(model_rev)); - nlen = ata_strim(model_num, sizeof(model_num)); - rlen = ata_strim(model_rev, sizeof(model_rev)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); + ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev)); while (ad->model_num) { - if (!strncmp(ad->model_num, model_num, nlen)) { + if (!strcmp(ad->model_num, model_num)) { if (ad->model_rev == NULL) return ad->horkage; - if (!strncmp(ad->model_rev, model_rev, rlen)) + if (!strcmp(ad->model_rev, model_rev)) return ad->horkage; } ad++; @@ -4021,11 +4019,11 @@ static void ata_pio_sector(struct ata_qu unsigned int offset; unsigned char *buf; - if (qc->cursect == (qc->nsect - 1)) + if (qc->curbytes == qc->nbytes - ATA_SECT_SIZE) ap->hsm_task_state = HSM_ST_LAST; page = sg[qc->cursg].page; - offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE; + offset = sg[qc->cursg].offset + qc->cursg_ofs; /* get the current page and offset */ page = nth_page(page, (offset >> PAGE_SHIFT)); @@ -4050,10 +4048,10 @@ static void ata_pio_sector(struct ata_qu ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); } - qc->cursect++; - qc->cursg_ofs++; + qc->curbytes += ATA_SECT_SIZE; + qc->cursg_ofs += ATA_SECT_SIZE; - if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) { + if (qc->cursg_ofs == (&sg[qc->cursg])->length) { qc->cursg++; qc->cursg_ofs = 0; } @@ -4078,7 +4076,8 @@ static void ata_pio_sectors(struct ata_q WARN_ON(qc->dev->multi_count == 0); - nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count); + nsect = min((qc->nbytes - qc->curbytes) / ATA_SECT_SIZE, + qc->dev->multi_count); while (nsect--) ata_pio_sector(qc); } else @@ -5769,7 +5768,7 @@ int ata_device_add(const struct ata_prob int rc; DPRINTK("ENTER\n"); - + if (ent->irq == 0) { dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n"); return 0; @@ -6211,12 +6210,22 @@ void ata_pci_device_do_suspend(struct pc } } -void ata_pci_device_do_resume(struct pci_dev *pdev) +int ata_pci_device_do_resume(struct pci_dev *pdev) { + int rc; + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_device(pdev); + + rc = pci_enable_device(pdev); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + pci_set_master(pdev); + return 0; } int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) @@ -6236,10 +6245,12 @@ int ata_pci_device_suspend(struct pci_de int ata_pci_device_resume(struct pci_dev *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; - ata_pci_device_do_resume(pdev); - ata_host_resume(host); - return 0; + rc = ata_pci_device_do_resume(pdev); + if (rc == 0) + ata_host_resume(host); + return rc; } #endif /* CONFIG_PCI */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 56cf59b..52c85af 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1443,15 +1443,10 @@ static void ata_eh_report(struct ata_por }; struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; - unsigned int nbytes; if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) continue; - nbytes = qc->nbytes; - if (!nbytes) - nbytes = qc->nsect << 9; - ata_dev_printk(qc->dev, KERN_ERR, "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " "tag %d cdb 0x%x data %u %s\n " @@ -1461,7 +1456,7 @@ static void ata_eh_report(struct ata_por cmd->lbal, cmd->lbam, cmd->lbah, cmd->hob_feature, cmd->hob_nsect, cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, - cmd->device, qc->tag, qc->cdb[0], nbytes, + cmd->device, qc->tag, qc->cdb[0], qc->nbytes, dma_str[qc->dma_dir], res->command, res->feature, res->nsect, res->lbal, res->lbam, res->lbah, @@ -1796,7 +1791,7 @@ static int ata_eh_suspend(struct ata_por *r_failed_dev = dev; DPRINTK("EXIT\n"); - return 0; + return rc; } /** diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7cc5a4a..a39d100 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -149,6 +149,45 @@ int ata_std_bios_param(struct scsi_devic } /** + * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl + * @sdev: SCSI device to get identify data for + * @arg: User buffer area for identify data + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ +static int ata_get_identity(struct scsi_device *sdev, void __user *arg) +{ + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *dev = ata_scsi_find_dev(ap, sdev); + u16 __user *dst = arg; + char buf[40]; + + if (!dev) + return -ENOMSG; + + if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16))) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN); + if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN)) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN); + if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN)) + return -EFAULT; + + ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN); + if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN)) + return -EFAULT; + + return 0; +} + +/** * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl * @scsidev: Device to which we are issuing command * @arg: User provided data for issuing command @@ -159,7 +198,6 @@ int ata_std_bios_param(struct scsi_devic * RETURNS: * Zero on success, negative errno on error. */ - int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) { int rc = 0; @@ -320,6 +358,9 @@ int ata_scsi_ioctl(struct scsi_device *s return -EINVAL; return 0; + case HDIO_GET_IDENTITY: + return ata_get_identity(scsidev, arg); + case HDIO_DRIVE_CMD: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; @@ -358,9 +399,9 @@ int ata_scsi_ioctl(struct scsi_device *s * RETURNS: * Command allocated, or %NULL if none available. */ -struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)) +static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, + struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { struct ata_queued_cmd *qc; @@ -396,7 +437,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(s * LOCKING: * inherited from caller */ -void ata_dump_status(unsigned id, struct ata_taskfile *tf) +static void ata_dump_status(unsigned id, struct ata_taskfile *tf) { u8 stat = tf->command, err = tf->feature; @@ -571,8 +612,8 @@ int ata_scsi_device_resume(struct scsi_d * LOCKING: * spin_lock_irqsave(host lock) */ -void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, - u8 *ascq, int verbose) +static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, + u8 *asc, u8 *ascq, int verbose) { int i; @@ -1321,7 +1362,7 @@ static unsigned int ata_scsi_rw_xlat(str goto nothing_to_do; qc->flags |= ATA_QCFLAG_IO; - qc->nsect = n_block; + qc->nbytes = n_block * ATA_SECT_SIZE; rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, qc->tag); @@ -1660,8 +1701,8 @@ unsigned int ata_scsiop_inq_std(struct a if (buflen > 35) { memcpy(&rbuf[8], "ATA ", 8); - ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16); - ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4); + ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); + ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); if (rbuf[32] == 0 || rbuf[32] == ' ') memcpy(&rbuf[32], "n/a ", 4); } @@ -1730,13 +1771,13 @@ unsigned int ata_scsiop_inq_80(struct at 0, 0x80, /* this page code */ 0, - ATA_SERNO_LEN, /* page len */ + ATA_ID_SERNO_LEN, /* page len */ }; memcpy(rbuf, hdr, sizeof(hdr)); - if (buflen > (ATA_SERNO_LEN + 4 - 1)) + if (buflen > (ATA_ID_SERNO_LEN + 4 - 1)) ata_id_string(args->id, (unsigned char *) &rbuf[4], - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); + ATA_ID_SERNO, ATA_ID_SERNO_LEN); return 0; } @@ -1761,19 +1802,18 @@ unsigned int ata_scsiop_inq_83(struct at { int num; const int sat_model_serial_desc_len = 68; - const int ata_model_byte_len = 40; rbuf[1] = 0x83; /* this page code */ num = 4; - if (buflen > (ATA_SERNO_LEN + num + 3)) { + if (buflen > (ATA_ID_SERNO_LEN + num + 3)) { /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ rbuf[num + 0] = 2; - rbuf[num + 3] = ATA_SERNO_LEN; + rbuf[num + 3] = ATA_ID_SERNO_LEN; num += 4; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); - num += ATA_SERNO_LEN; + ATA_ID_SERNO, ATA_ID_SERNO_LEN); + num += ATA_ID_SERNO_LEN; } if (buflen > (sat_model_serial_desc_len + num + 3)) { /* SAT defined lu model and serial numbers descriptor */ @@ -1785,11 +1825,11 @@ unsigned int ata_scsiop_inq_83(struct at memcpy(rbuf + num, "ATA ", 8); num += 8; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_PROD_OFS, ata_model_byte_len); - num += ata_model_byte_len; + ATA_ID_PROD, ATA_ID_PROD_LEN); + num += ATA_ID_PROD_LEN; ata_id_string(args->id, (unsigned char *) rbuf + num, - ATA_ID_SERNO_OFS, ATA_SERNO_LEN); - num += ATA_SERNO_LEN; + ATA_ID_SERNO, ATA_ID_SERNO_LEN); + num += ATA_ID_SERNO_LEN; } rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ return 0; @@ -1917,15 +1957,15 @@ static unsigned int ata_msense_rw_recove */ static int ata_dev_supports_fua(u16 *id) { - unsigned char model[41], fw[9]; + unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1]; if (!libata_fua) return 0; if (!ata_id_has_fua(id)) return 0; - ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model)); - ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw)); + ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); + ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw)); if (strcmp(model, "Maxtor")) return 1; @@ -2623,7 +2663,7 @@ static unsigned int ata_scsi_pass_thru(s * TODO: find out if we need to do more here to * cover scatter/gather case. */ - qc->nsect = scmd->request_bufflen / ATA_SECT_SIZE; + qc->nbytes = scmd->request_bufflen; /* request result TF */ qc->flags |= ATA_QCFLAG_RESULT_TF; @@ -3021,7 +3061,8 @@ void ata_scsi_hotplug(struct work_struct for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; if (ata_dev_enabled(dev) && !dev->sdev) { - queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, + round_jiffies_relative(HZ)); break; } } diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 12c88c5..9bbc874 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -775,7 +775,7 @@ void ata_bmdma_drive_eh(struct ata_port * really a timeout event, adjust error mask and * cancel frozen state. */ - if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) { + if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { qc->err_mask = AC_ERR_HOST_BUS; thaw = 1; } @@ -832,6 +832,21 @@ void ata_bmdma_post_internal_cmd(struct } #ifdef CONFIG_PCI + +static int ata_resources_present(struct pci_dev *pdev, int port) +{ + int i; + + /* Check the PCI resources for this channel are enabled */ + port = port * 2; + for (i = 0; i < 2; i ++) { + if (pci_resource_start(pdev, port + i) == 0 || + pci_resource_len(pdev, port + i) == 0) + return 0; + } + return 1; +} + /** * ata_pci_init_native_mode - Initialize native-mode driver * @pdev: pci device to be initialized @@ -863,6 +878,13 @@ ata_pci_init_native_mode(struct pci_dev probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; + + /* Discard disabled ports. Some controllers show their + unused channels this way */ + if (ata_resources_present(pdev, 0) == 0) + ports &= ~ATA_PORT_PRIMARY; + if (ata_resources_present(pdev, 1) == 0) + ports &= ~ATA_PORT_SECONDARY; if (ports & ATA_PORT_PRIMARY) { probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 81ae41d..d91ac92 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -48,6 +48,7 @@ extern struct workqueue_struct *ata_aux_ extern int atapi_enabled; extern int atapi_dmadir; extern int libata_fua; +extern int noacpi; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, @@ -88,6 +89,20 @@ extern void ata_port_init(struct ata_por extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port); +/* libata-acpi.c */ +#ifdef CONFIG_SATA_ACPI +extern int ata_acpi_exec_tfs(struct ata_port *ap); +extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix); +#else +static inline int ata_acpi_exec_tfs(struct ata_port *ap) +{ + return 0; +} +static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) +{ + return 0; +} +#endif /* libata-scsi.c */ extern struct scsi_transport_template ata_scsi_transport_template; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index c5d61d1..fde5ce9 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -153,11 +153,11 @@ static void ali_early_error_handler(stru static unsigned long ali_20_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) { - char model_num[40]; + char model_num[ATA_ID_PROD_LEN + 1]; /* No DMA on anything but a disk for now */ if (adev->class != ATA_DEV_ATA) mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); + ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num)); if (strstr(model_num, "WDC")) return mask &= ~ATA_MASK_UDMA; return ata_pci_default_filter(ap, adev, mask); @@ -504,7 +504,7 @@ static struct ata_port_operations ali_c5 * Perform the setup on the device that must be done both at boot * and at resume time. */ - + static void ali_init_chipset(struct pci_dev *pdev) { u8 rev, tmp; @@ -655,7 +655,7 @@ static int ali_init_one(struct pci_dev * port_info[0] = port_info[1] = &info_c5; ali_init_chipset(pdev); - + isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (isa_bridge && rev >= 0x20 && rev < 0xC2) { /* Are we paired with a UDMA capable chip */ diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 9f165a8..476b879 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -305,7 +305,7 @@ static void __devexit cs5520_remove_one( * Do any reconfiguration work needed by a resume from RAM. We need * to restore DMA mode support on BIOSen which disabled it */ - + static int cs5520_reinit_one(struct pci_dev *pdev) { u8 pcicfg; diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index b1ca207..611d90f 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -247,7 +247,7 @@ static int cs5530_is_palmax(void) * Perform the chip initialisation work that is shared between both * setup and resume paths */ - + static int cs5530_init_chip(void) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL; @@ -357,11 +357,11 @@ static int cs5530_init_one(struct pci_de .port_ops = &cs5530_port_ops }; static struct ata_port_info *port_info[2] = { &info, &info }; - + /* Chip initialisation */ if (cs5530_init_chip()) return -ENODEV; - + if (cs5530_is_palmax()) port_info[1] = &info_palmax_secondary; @@ -376,7 +376,7 @@ static int cs5530_reinit_one(struct pci_ BUG(); return ata_pci_device_resume(pdev); } - + static const struct pci_device_id cs5530[] = { { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 2663599..2202c7e 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -151,23 +151,13 @@ static const char *bad_ata66_3[] = { static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) { - unsigned char model_num[40]; - char *s; - unsigned int len; + unsigned char model_num[ATA_ID_PROD_LEN + 1]; int i = 0; - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - while(list[i] != NULL) { - if (!strncmp(list[i], s, len)) { + while (list[i] != NULL) { + if (!strcmp(list[i], model_num)) { printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", modestr, list[i]); return 1; @@ -232,7 +222,7 @@ static int hpt36x_pre_reset(struct ata_p if (!pci_test_config_bits(pdev, &hpt36x_enable_bits[ap->port_no])) return -ENOENT; - + pci_read_config_byte(pdev, 0x5A, &ata66); if (ata66 & (1 << ap->port_no)) ap->cbl = ATA_CBL_PATA40; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index dfb3060..9e1eb47 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -349,24 +349,13 @@ static u32 hpt37x_find_mode(struct ata_p static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) { - unsigned char model_num[40]; - char *s; - unsigned int len; + unsigned char model_num[ATA_ID_PROD_LEN + 1]; int i = 0; - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - while(list[i] != NULL) { - if (!strncmp(list[i], s, len)) { + while (list[i] != NULL) { + if (!strcmp(list[i], model_num)) { printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", modestr, list[i]); return 1; @@ -459,7 +448,7 @@ static int hpt37x_pre_reset(struct ata_p }; if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) return -ENOENT; - + pci_read_config_byte(pdev, 0x5B, &scr2); pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); /* Cable register now active */ @@ -504,7 +493,7 @@ static int hpt374_pre_reset(struct ata_p if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) return -ENOENT; - + /* Do the extra channel work */ pci_read_config_word(pdev, 0x52, &mcr3); pci_read_config_word(pdev, 0x56, &mcr6); diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index 5f1d385..5caf167 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -164,7 +164,7 @@ static struct ata_port_operations hpt3x3 * * Perform the setup required at boot and on resume. */ - + static void hpt3x3_init_chipset(struct pci_dev *dev) { u16 cmd; diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c new file mode 100644 index 0000000..7e9a416 --- /dev/null +++ b/drivers/ata/pata_it8213.c @@ -0,0 +1,354 @@ +/* + * pata_it8213.c - iTE Tech. Inc. IT8213 PATA driver + * + * The IT8213 is a very Intel ICH like device for timing purposes, having + * a similar register layout and the same split clock arrangement. Cable + * detection is different, and it does not have slave channels or all the + * clutter of later ICH/SATA setups. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pata_it8213" +#define DRV_VERSION "0.0.2" + +/** + * it8213_pre_reset - check for 40/80 pin + * @ap: Port + * + * Perform cable detection for the 8213 ATA interface. This is + * different to the PIIX arrangement + */ + +static int it8213_pre_reset(struct ata_port *ap) +{ + static const struct pci_bits it8213_enable_bits[] = { + { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ + }; + + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u8 tmp; + + if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no])) + return -ENOENT; + + pci_read_config_byte(pdev, 0x42, &tmp); + if (tmp & 2) /* The initial docs are incorrect */ + ap->cbl = ATA_CBL_PATA40; + else + ap->cbl = ATA_CBL_PATA80; + return ata_std_prereset(ap); +} + +/** + * it8213_probe_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * LOCKING: + * None (inherited from caller). + */ + +static void it8213_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset); +} + +/** + * it8213_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * + * Set PIO mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev) +{ + unsigned int pio = adev->pio_mode - XFER_PIO_0; + struct pci_dev *dev = to_pci_dev(ap->host->dev); + unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; + u16 idetm_data; + int control = 0; + + /* + * See Intel Document 298600-004 for the timing programing rules + * for PIIX/ICH. The 8213 is a clone so very similar + */ + + static const /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + if (pio > 2) + control |= 1; /* TIME1 enable */ + if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ + control |= 2; /* IORDY enable */ + /* Bit 2 is set for ATAPI on the IT8213 - reverse of ICH/PIIX */ + if (adev->class != ATA_DEV_ATA) + control |= 4; + + pci_read_config_word(dev, idetm_port, &idetm_data); + + /* Enable PPE, IE and TIME as appropriate */ + + if (adev->devno == 0) { + idetm_data &= 0xCCF0; + idetm_data |= control; + idetm_data |= (timings[pio][0] << 12) | + (timings[pio][1] << 8); + } else { + u8 slave_data; + + idetm_data &= 0xCC0F; + idetm_data |= (control << 4); + + /* Slave timing in seperate register */ + pci_read_config_byte(dev, 0x44, &slave_data); + slave_data &= 0xF0; + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << 4; + pci_write_config_byte(dev, 0x44, slave_data); + } + + idetm_data |= 0x4000; /* Ensure SITRE is enabled */ + pci_write_config_word(dev, idetm_port, idetm_data); +} + +/** + * it8213_set_dmamode - Initialize host controller PATA DMA timings + * @ap: Port whose timings we are configuring + * @adev: Device to program + * + * Set UDMA/MWDMA mode for device, in host controller PCI config space. + * This device is basically an ICH alike. + * + * LOCKING: + * None (inherited from caller). + */ + +static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev) +{ + struct pci_dev *dev = to_pci_dev(ap->host->dev); + u16 master_data; + u8 speed = adev->dma_mode; + int devid = adev->devno; + u8 udma_enable; + + static const /* ISP RTC */ + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pci_read_config_word(dev, 0x40, &master_data); + pci_read_config_byte(dev, 0x48, &udma_enable); + + if (speed >= XFER_UDMA_0) { + unsigned int udma = adev->dma_mode - XFER_UDMA_0; + u16 udma_timing; + u16 ideconf; + int u_clock, u_speed; + + /* Clocks follow the PIIX style */ + u_speed = min(2 - (udma & 1), udma); + if (udma == 5) + u_clock = 0x1000; /* 100Mhz */ + else if (udma > 2) + u_clock = 1; /* 66Mhz */ + else + u_clock = 0; /* 33Mhz */ + + udma_enable |= (1 << devid); + + /* Load the UDMA mode number */ + pci_read_config_word(dev, 0x4A, &udma_timing); + udma_timing &= ~(3 << (4 * devid)); + udma_timing |= (udma & 3) << (4 * devid); + pci_write_config_word(dev, 0x4A, udma_timing); + + /* Load the clock selection */ + pci_read_config_word(dev, 0x54, &ideconf); + ideconf &= ~(0x1001 << devid); + ideconf |= u_clock << devid; + pci_write_config_word(dev, 0x54, ideconf); + } else { + /* + * MWDMA is driven by the PIO timings. We must also enable + * IORDY unconditionally along with TIME1. PPE has already + * been set when the PIO timing was set. + */ + unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; + unsigned int control; + u8 slave_data; + static const unsigned int needed_pio[3] = { + XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 + }; + int pio = needed_pio[mwdma] - XFER_PIO_0; + + control = 3; /* IORDY|TIME1 */ + + /* If the drive MWDMA is faster than it can do PIO then + we must force PIO into PIO0 */ + + if (adev->pio_mode < needed_pio[mwdma]) + /* Enable DMA timing only */ + control |= 8; /* PIO cycles in PIO0 */ + + if (devid) { /* Slave */ + master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ + master_data |= control << 4; + pci_read_config_byte(dev, 0x44, &slave_data); + slave_data &= (0x0F + 0xE1 * ap->port_no); + /* Load the matching timing */ + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); + pci_write_config_byte(dev, 0x44, slave_data); + } else { /* Master */ + master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY + and master timing bits */ + master_data |= control; + master_data |= + (timings[pio][0] << 12) | + (timings[pio][1] << 8); + } + udma_enable &= ~(1 << devid); + pci_write_config_word(dev, 0x40, master_data); + } + pci_write_config_byte(dev, 0x48, udma_enable); +} + +static struct scsi_host_template it8213_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, + .resume = ata_scsi_device_resume, + .suspend = ata_scsi_device_suspend, +}; + +static const struct ata_port_operations it8213_ops = { + .port_disable = ata_port_disable, + .set_piomode = it8213_set_piomode, + .set_dmamode = it8213_set_dmamode, + .mode_filter = ata_pci_default_filter, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = it8213_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + + +/** + * it8213_init_one - Register 8213 ATA PCI device with kernel services + * @pdev: PCI device to register + * @ent: Entry in it8213_pci_tbl matching with @pdev + * + * Called from kernel PCI layer. + * + * LOCKING: + * Inherited from PCI layer (may sleep). + * + * RETURNS: + * Zero on success, or -ERRNO value. + */ + +static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + static struct ata_port_info info = { + .sht = &it8213_sht, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x1f, /* UDMA 100 */ + .port_ops = &it8213_ops, + }; + static struct ata_port_info *port_info[2] = { &info, &info }; + + if (!printed_version++) + dev_printk(KERN_DEBUG, &pdev->dev, + "version " DRV_VERSION "\n"); + + /* Current IT8213 stuff is single port */ + return ata_pci_init_one(pdev, port_info, 1); +} + +static const struct pci_device_id it8213_pci_tbl[] = { + { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8213), }, + + { } /* terminate list */ +}; + +static struct pci_driver it8213_pci_driver = { + .name = DRV_NAME, + .id_table = it8213_pci_tbl, + .probe = it8213_init_one, + .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = ata_pci_device_resume, +}; + +static int __init it8213_init(void) +{ + return pci_register_driver(&it8213_pci_driver); +} + +static void __exit it8213_exit(void) +{ + pci_unregister_driver(&it8213_pci_driver); +} + +module_init(it8213_init); +module_exit(it8213_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("SCSI low-level driver for the ITE 8213"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index e8afd48..171fbd2 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -531,23 +531,9 @@ static int it821x_smart_set_mode(struct static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev) { - unsigned char model_num[40]; - char *s; - unsigned int len; - - /* This block ought to be a library routine as it is in several - drivers now */ - - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } + unsigned char model_num[ATA_ID_PROD_LEN + 1]; + + ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num)); if (adev->max_sectors > 255) adev->max_sectors = 255; diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 2d661cb..efb1b6d 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -229,7 +229,7 @@ static int jmicron_init_one (struct pci_ static int jmicron_reinit_one(struct pci_dev *pdev) { u32 reg; - + switch(pdev->device) { case PCI_DEVICE_ID_JMICRON_JMB368: break; diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 1c810ea..af93533 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -45,10 +45,10 @@ static int marvell_pre_reset(struct ata_ for(i = 0; i <= 0x0F; i++) printk("%02X:%02X ", i, readb(barp + i)); printk("\n"); - + devices = readl(barp + 0x0C); pci_iounmap(pdev, barp); - + if ((pdev->device == 0x6145) && (ap->port_no == 0) && (!(devices & 0x10))) /* PATA enable ? */ return -ENOENT; diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c new file mode 100644 index 0000000..8b7019a --- /dev/null +++ b/drivers/ata/pata_mpc52xx.c @@ -0,0 +1,563 @@ +/* + * drivers/ata/pata_mpc52xx.c + * + * libata driver for the Freescale MPC52xx on-chip IDE interface + * + * Copyright (C) 2006 Sylvain Munaut + * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define DRV_NAME "mpc52xx_ata" +#define DRV_VERSION "0.1.0" + + +/* Private structures used by the driver */ +struct mpc52xx_ata_timings { + u32 pio1; + u32 pio2; +}; + +struct mpc52xx_ata_priv { + unsigned int ipb_period; + struct mpc52xx_ata __iomem * ata_regs; + int ata_irq; + struct mpc52xx_ata_timings timings[2]; + int csel; +}; + + +/* ATAPI-4 PIO specs (in ns) */ +static const int ataspec_t0[5] = {600, 383, 240, 180, 120}; +static const int ataspec_t1[5] = { 70, 50, 30, 30, 25}; +static const int ataspec_t2_8[5] = {290, 290, 290, 80, 70}; +static const int ataspec_t2_16[5] = {165, 125, 100, 80, 70}; +static const int ataspec_t2i[5] = { 0, 0, 0, 70, 25}; +static const int ataspec_t4[5] = { 30, 20, 15, 10, 10}; +static const int ataspec_ta[5] = { 35, 35, 35, 35, 35}; + +#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c))) + + +/* Bit definitions inside the registers */ +#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */ +#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */ +#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */ +#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */ + +#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */ +#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */ +#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */ +#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */ + +#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */ + +#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */ +#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */ +#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */ +#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */ +#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */ +#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */ +#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */ + + +/* Structure of the hardware registers */ +struct mpc52xx_ata { + + /* Host interface registers */ + u32 config; /* ATA + 0x00 Host configuration */ + u32 host_status; /* ATA + 0x04 Host controller status */ + u32 pio1; /* ATA + 0x08 PIO Timing 1 */ + u32 pio2; /* ATA + 0x0c PIO Timing 2 */ + u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */ + u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */ + u32 udma1; /* ATA + 0x18 UDMA Timing 1 */ + u32 udma2; /* ATA + 0x1c UDMA Timing 2 */ + u32 udma3; /* ATA + 0x20 UDMA Timing 3 */ + u32 udma4; /* ATA + 0x24 UDMA Timing 4 */ + u32 udma5; /* ATA + 0x28 UDMA Timing 5 */ + u32 share_cnt; /* ATA + 0x2c ATA share counter */ + u32 reserved0[3]; + + /* FIFO registers */ + u32 fifo_data; /* ATA + 0x3c */ + u8 fifo_status_frame; /* ATA + 0x40 */ + u8 fifo_status; /* ATA + 0x41 */ + u16 reserved7[1]; + u8 fifo_control; /* ATA + 0x44 */ + u8 reserved8[5]; + u16 fifo_alarm; /* ATA + 0x4a */ + u16 reserved9; + u16 fifo_rdp; /* ATA + 0x4e */ + u16 reserved10; + u16 fifo_wrp; /* ATA + 0x52 */ + u16 reserved11; + u16 fifo_lfrdp; /* ATA + 0x56 */ + u16 reserved12; + u16 fifo_lfwrp; /* ATA + 0x5a */ + + /* Drive TaskFile registers */ + u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */ + u8 reserved13[3]; + u16 tf_data; /* ATA + 0x60 TASKFILE Data */ + u16 reserved14; + u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */ + u8 reserved15[3]; + u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */ + u8 reserved16[3]; + u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */ + u8 reserved17[3]; + u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */ + u8 reserved18[3]; + u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */ + u8 reserved19[3]; + u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */ + u8 reserved20[3]; + u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */ + u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */ + u8 reserved21[2]; +}; + + +/* ======================================================================== */ +/* Aux fns */ +/* ======================================================================== */ + + +/* MPC52xx low level hw control */ + +static int +mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio) +{ + struct mpc52xx_ata_timings *timing = &priv->timings[dev]; + unsigned int ipb_period = priv->ipb_period; + unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta; + + if ((pio<0) || (pio>4)) + return -EINVAL; + + t0 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]); + t1 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t1[pio]); + t2_8 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_8[pio]); + t2_16 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_16[pio]); + t2i = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2i[pio]); + t4 = CALC_CLKCYC(ipb_period, 1000 * ataspec_t4[pio]); + ta = CALC_CLKCYC(ipb_period, 1000 * ataspec_ta[pio]); + + timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i); + timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8); + + return 0; +} + +static void +mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device) +{ + struct mpc52xx_ata __iomem *regs = priv->ata_regs; + struct mpc52xx_ata_timings *timing = &priv->timings[device]; + + out_be32(®s->pio1, timing->pio1); + out_be32(®s->pio2, timing->pio2); + out_be32(®s->mdma1, 0); + out_be32(®s->mdma2, 0); + out_be32(®s->udma1, 0); + out_be32(®s->udma2, 0); + out_be32(®s->udma3, 0); + out_be32(®s->udma4, 0); + out_be32(®s->udma5, 0); + + priv->csel = device; +} + +static int +mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv) +{ + struct mpc52xx_ata __iomem *regs = priv->ata_regs; + int tslot; + + /* Clear share_cnt (all sample code do this ...) */ + out_be32(®s->share_cnt, 0); + + /* Configure and reset host */ + out_be32(®s->config, + MPC52xx_ATA_HOSTCONF_IE | + MPC52xx_ATA_HOSTCONF_IORDY | + MPC52xx_ATA_HOSTCONF_SMR | + MPC52xx_ATA_HOSTCONF_FR); + + udelay(10); + + out_be32(®s->config, + MPC52xx_ATA_HOSTCONF_IE | + MPC52xx_ATA_HOSTCONF_IORDY); + + /* Set the time slot to 1us */ + tslot = CALC_CLKCYC(priv->ipb_period, 1000000); + out_be32(®s->share_cnt, tslot << 16 ); + + /* Init timings to PIO0 */ + memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings)); + + mpc52xx_ata_compute_pio_timings(priv, 0, 0); + mpc52xx_ata_compute_pio_timings(priv, 1, 0); + + mpc52xx_ata_apply_timings(priv, 0); + + return 0; +} + + +/* ======================================================================== */ +/* libata driver */ +/* ======================================================================== */ + +static void +mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + struct mpc52xx_ata_priv *priv = ap->host->private_data; + int pio, rv; + + pio = adev->pio_mode - XFER_PIO_0; + + rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio); + + if (rv) { + printk(KERN_ERR DRV_NAME + ": Trying to select invalid PIO mode %d\n", pio); + return; + } + + mpc52xx_ata_apply_timings(priv, adev->devno); +} +static void +mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device) +{ + struct mpc52xx_ata_priv *priv = ap->host->private_data; + + if (device != priv->csel) + mpc52xx_ata_apply_timings(priv, device); + + ata_std_dev_select(ap,device); +} + +static void +mpc52xx_ata_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL, + ata_std_postreset); +} + + + +static struct scsi_host_template mpc52xx_ata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations mpc52xx_ata_port_ops = { + .port_disable = ata_port_disable, + .set_piomode = mpc52xx_ata_set_piomode, + .dev_select = mpc52xx_ata_dev_select, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = mpc52xx_ata_error_handler, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_mmio_data_xfer, + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + +static struct ata_probe_ent mpc52xx_ata_probe_ent = { + .port_ops = &mpc52xx_ata_port_ops, + .sht = &mpc52xx_ata_sht, + .n_ports = 1, + .pio_mask = 0x1f, /* Up to PIO4 */ + .mwdma_mask = 0x00, /* No MWDMA */ + .udma_mask = 0x00, /* No UDMA */ + .port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_MMIO, + .irq_flags = 0, +}; + +static int __devinit +mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv) +{ + struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent; + struct ata_ioports *aio = &ae->port[0]; + int rv; + + INIT_LIST_HEAD(&ae->node); + ae->dev = dev; + ae->irq = priv->ata_irq; + + aio->cmd_addr = 0; /* Don't have a classic reg block */ + aio->altstatus_addr = (unsigned long)&priv->ata_regs->tf_control; + aio->ctl_addr = (unsigned long)&priv->ata_regs->tf_control; + aio->data_addr = (unsigned long)&priv->ata_regs->tf_data; + aio->error_addr = (unsigned long)&priv->ata_regs->tf_features; + aio->feature_addr = (unsigned long)&priv->ata_regs->tf_features; + aio->nsect_addr = (unsigned long)&priv->ata_regs->tf_sec_count; + aio->lbal_addr = (unsigned long)&priv->ata_regs->tf_sec_num; + aio->lbam_addr = (unsigned long)&priv->ata_regs->tf_cyl_low; + aio->lbah_addr = (unsigned long)&priv->ata_regs->tf_cyl_high; + aio->device_addr = (unsigned long)&priv->ata_regs->tf_dev_head; + aio->status_addr = (unsigned long)&priv->ata_regs->tf_command; + aio->command_addr = (unsigned long)&priv->ata_regs->tf_command; + + ae->private_data = priv; + + rv = ata_device_add(ae); + + return rv ? 0 : -EINVAL; +} + +static struct mpc52xx_ata_priv * +mpc52xx_ata_remove_one(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct mpc52xx_ata_priv *priv = host->private_data; + + ata_host_remove(host); + + return priv; +} + + +/* ======================================================================== */ +/* OF Platform driver */ +/* ======================================================================== */ + +static int __devinit +mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) +{ + unsigned int ipb_freq; + struct resource res_mem; + int ata_irq = NO_IRQ; + struct mpc52xx_ata __iomem *ata_regs = NULL; + struct mpc52xx_ata_priv *priv = NULL; + int rv; + + /* Get ipb frequency */ + ipb_freq = mpc52xx_find_ipb_freq(op->node); + if (!ipb_freq) { + printk(KERN_ERR DRV_NAME ": " + "Unable to find IPB Bus frequency\n" ); + return -ENODEV; + } + + /* Get IRQ and register */ + rv = of_address_to_resource(op->node, 0, &res_mem); + if (rv) { + printk(KERN_ERR DRV_NAME ": " + "Error while parsing device node resource\n" ); + return rv; + } + + ata_irq = irq_of_parse_and_map(op->node, 0); + if (ata_irq == NO_IRQ) { + printk(KERN_ERR DRV_NAME ": " + "Error while mapping the irq\n"); + return -EINVAL; + } + + /* Request mem region */ + if (!request_mem_region(res_mem.start, + sizeof(struct mpc52xx_ata), DRV_NAME)) { + printk(KERN_ERR DRV_NAME ": " + "Error while requesting mem region\n"); + irq_dispose_mapping(ata_irq); + return -EBUSY; + } + + /* Remap registers */ + ata_regs = ioremap(res_mem.start, sizeof(struct mpc52xx_ata)); + if (!ata_regs) { + printk(KERN_ERR DRV_NAME ": " + "Error while mapping register set\n"); + rv = -ENOMEM; + goto err; + } + + /* Prepare our private structure */ + priv = kmalloc(sizeof(struct mpc52xx_ata_priv), GFP_ATOMIC); + if (!priv) { + printk(KERN_ERR DRV_NAME ": " + "Error while allocating private structure\n"); + rv = -ENOMEM; + goto err; + } + + priv->ipb_period = 1000000000 / (ipb_freq / 1000); + priv->ata_regs = ata_regs; + priv->ata_irq = ata_irq; + priv->csel = -1; + + /* Init the hw */ + rv = mpc52xx_ata_hw_init(priv); + if (rv) { + printk(KERN_ERR DRV_NAME ": Error during HW init\n"); + goto err; + } + + /* Register ourselves to libata */ + rv = mpc52xx_ata_init_one(&op->dev, priv); + if (rv) { + printk(KERN_ERR DRV_NAME ": " + "Error while registering to ATA layer\n"); + return rv; + } + + /* Done */ + return 0; + + /* Error path */ +err: + kfree(priv); + + if (ata_regs) + iounmap(ata_regs); + + release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata)); + + irq_dispose_mapping(ata_irq); + + return rv; +} + +static int +mpc52xx_ata_remove(struct of_device *op) +{ + struct mpc52xx_ata_priv *priv; + struct resource res_mem; + int rv; + + /* Unregister */ + priv = mpc52xx_ata_remove_one(&op->dev); + + /* Free everything */ + iounmap(priv->ata_regs); + + rv = of_address_to_resource(op->node, 0, &res_mem); + if (rv) { + printk(KERN_ERR DRV_NAME ": " + "Error while parsing device node resource\n"); + printk(KERN_ERR DRV_NAME ": " + "Zone may not be properly released\n"); + } else + release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata)); + + irq_dispose_mapping(priv->ata_irq); + + kfree(priv); + + return 0; +} + + +#ifdef CONFIG_PM + +static int +mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) +{ + return 0; /* FIXME : What to do here ? */ +} + +static int +mpc52xx_ata_resume(struct of_device *op) +{ + return 0; /* FIXME : What to do here ? */ +} + +#endif + + +static struct of_device_id mpc52xx_ata_of_match[] = { + { + .compatible = "mpc5200-ata", + }, + { + .compatible = "mpc52xx-ata", + }, + {}, +}; + + +static struct of_platform_driver mpc52xx_ata_of_platform_driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + .match_table = mpc52xx_ata_of_match, + .probe = mpc52xx_ata_probe, + .remove = mpc52xx_ata_remove, +#ifdef CONFIG_PM + .suspend = mpc52xx_ata_suspend, + .resume = mpc52xx_ata_resume, +#endif + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + + +/* ======================================================================== */ +/* Module */ +/* ======================================================================== */ + +static int __init +mpc52xx_ata_init(void) +{ + printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n"); + return of_register_platform_driver(&mpc52xx_ata_of_platform_driver); +} + +static void __exit +mpc52xx_ata_exit(void) +{ + of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver); +} + +module_init(mpc52xx_ata_init); +module_exit(mpc52xx_ata_exit); + +MODULE_AUTHOR("Sylvain Munaut "); +MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match); +MODULE_VERSION(DRV_VERSION); + diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index ad691b9..ba982ba 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -189,10 +189,7 @@ static void pdc2026x_bmdma_start(struct /* Cases the state machine will not complete correctly without help */ if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) { - if (tf->flags & ATA_TFLAG_LBA48) - len = qc->nsect * 512; - else - len = qc->nbytes; + len = qc->nbytes; if (tf->flags & ATA_TFLAG_WRITE) len |= 0x06000000; diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index f02b6a3..4b8c235 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -218,25 +218,18 @@ static unsigned long serverworks_osb4_fi static unsigned long serverworks_csb_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) { const char *p; - char model_num[40]; - int len, i; + char model_num[ATA_ID_PROD_LEN + 1]; + int i; /* Disk, UDMA */ if (adev->class != ATA_DEV_ATA) return ata_pci_default_filter(ap, adev, mask); /* Actually do need to check */ - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - /* Precuationary - why not do this in the libata core ?? */ + ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - len = strlen(model_num); - while ((len > 0) && (model_num[len - 1] == ' ')) { - len--; - model_num[len] = 0; - } - - for(i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { - if (!strncmp(p, model_num, len)) + for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { + if (!strcmp(p, model_num)) mask &= ~(0x1F << ATA_SHIFT_UDMA); } return ata_pci_default_filter(ap, adev, mask); @@ -559,7 +552,7 @@ static int serverworks_reinit_one(struct { /* Force master latency timer to 64 PCI clocks */ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); - + switch (pdev->device) { case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 32cf0bf..ae07f63 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -270,7 +270,7 @@ static struct ata_port_operations sil680 * is powered up on boot and when we resume in case we resumed from RAM. * Returns the final clock settings. */ - + static u8 sil680_init_chip(struct pci_dev *pdev) { u32 class_rev = 0; diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 916cedb..6746f3f 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -43,6 +43,34 @@ struct sis_chipset { up code later */ }; +struct sis_laptop { + u16 device; + u16 subvendor; + u16 subdevice; +}; + +static const struct sis_laptop sis_laptop[] = { + /* devid, subvendor, subdev */ + { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ + /* end marker */ + { 0, } +}; + +static int sis_short_ata40(struct pci_dev *dev) +{ + const struct sis_laptop *lap = &sis_laptop[0]; + + while (lap->device) { + if (lap->device == dev->device && + lap->subvendor == dev->subsystem_vendor && + lap->subdevice == dev->subsystem_device) + return 1; + lap++; + } + + return 0; +} + /** * sis_port_base - return PCI configuration base for dev * @adev: device @@ -79,7 +107,7 @@ static int sis_133_pre_reset(struct ata_ /* The top bit of this register is the cable detect bit */ pci_read_config_word(pdev, 0x50 + 2 * ap->port_no, &tmp); - if (tmp & 0x8000) + if ((tmp & 0x8000) && !sis_short_ata40(pdev)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; @@ -127,7 +155,7 @@ static int sis_66_pre_reset(struct ata_p /* Older chips keep cable detect in bits 4/5 of reg 0x48 */ pci_read_config_byte(pdev, 0x48, &tmp); tmp >>= ap->port_no; - if (tmp & 0x10) + if ((tmp & 0x10) && !sis_short_ata40(pdev)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; @@ -768,6 +796,8 @@ static struct ata_port_info sis_info133_ .port_ops = &sis_133_early_ops, }; +/* Privately shared with the SiS180 SATA driver, not for use elsewhere */ +EXPORT_SYMBOL_GPL(sis_info133); static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis) { @@ -847,7 +877,7 @@ static int sis_init_one (struct pci_dev struct sis_chipset *chipset = NULL; static struct sis_chipset sis_chipsets[] = { - + { 0x0968, &sis_info133 }, { 0x0966, &sis_info133 }, { 0x0965, &sis_info133 }, diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index f0d4f7e..707df8e 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -389,11 +389,11 @@ static struct ata_port_operations via_po static void via_config_fifo(struct pci_dev *pdev, unsigned int flags) { u8 enable; - + /* 0x40 low bits indicate enabled channels */ pci_read_config_byte(pdev, 0x40 , &enable); enable &= 3; - + if (flags & VIA_SET_FIFO) { static const u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; u8 fifo; @@ -514,7 +514,7 @@ static int via_init_one(struct pci_dev * /* Initialise the FIFO for the enabled channels. */ via_config_fifo(pdev, config->flags); - + /* Clock set up */ switch(config->flags & VIA_UDMA) { case VIA_UDMA_NONE: @@ -573,7 +573,7 @@ static int via_reinit_one(struct pci_dev u32 timing; struct ata_host *host = dev_get_drvdata(&pdev->dev); const struct via_isa_bridge *config = host->private_data; - + via_config_fifo(pdev, config->flags); if ((config->flags & VIA_UDMA) == VIA_UDMA_66) { @@ -588,7 +588,7 @@ static int via_reinit_one(struct pci_dev timing &= ~0x80008; pci_write_config_dword(pdev, 0x50, timing); } - return ata_pci_device_resume(pdev); + return ata_pci_device_resume(pdev); } static const struct pci_device_id via[] = { diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 5d1f518..022da95 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -5,7 +5,7 @@ * Support for the Winbond 83759A when operating in advanced mode. * Multichip mode is not currently supported. */ - + #include #include #include @@ -69,7 +69,7 @@ static void winbond_set_piomode(struct a int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); reg = winbond_readcfg(winbond->config, 0x81); - + /* Get the timing data in cycles */ if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); @@ -80,9 +80,9 @@ static void winbond_set_piomode(struct a recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F; timing = (active << 4) | recovery; winbond_writecfg(winbond->config, timing, reg); - + /* Load the setup timing */ - + reg = 0x35; if (adev->class != ATA_DEV_ATA) reg |= 0x08; /* FIFO off */ @@ -194,13 +194,13 @@ static __init int winbond_init_one(unsig winbond_writecfg(port, 0x85, reg); reg = winbond_readcfg(port, 0x81); - + if (!(reg & 0x03)) /* Disabled */ return 0; for (i = 0; i < 2 ; i ++) { - if (reg & (1 << i)) { + if (reg & (1 << i)) { /* * Fill in a probe structure first of all */ @@ -217,7 +217,7 @@ static __init int winbond_init_one(unsig ae.pio_mask = 0x1F; ae.sht = &winbond_sht; - + ae.n_ports = 1; ae.irq = 14 + i; ae.irq_flags = 0; @@ -257,7 +257,7 @@ static __init int winbond_init(void) int ct = 0; int i; - + if (probe_winbond == 0) return -ENODEV; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c new file mode 100644 index 0000000..b67817e --- /dev/null +++ b/drivers/ata/sata_inic162x.c @@ -0,0 +1,809 @@ +/* + * sata_inic162x.c - Driver for Initio 162x SATA controllers + * + * Copyright 2006 SUSE Linux Products GmbH + * Copyright 2006 Tejun Heo + * + * This file is released under GPL v2. + * + * This controller is eccentric and easily locks up if something isn't + * right. Documentation is available at initio's website but it only + * documents registers (not programming model). + * + * - ATA disks work. + * - Hotplug works. + * - ATAPI read works but burning doesn't. This thing is really + * peculiar about ATAPI and I couldn't figure out how ATAPI PIO and + * ATAPI DMA WRITE should be programmed. If you've got a clue, be + * my guest. + * - Both STR and STD work. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "sata_inic162x" +#define DRV_VERSION "0.1" + +enum { + MMIO_BAR = 5, + + NR_PORTS = 2, + + HOST_CTL = 0x7c, + HOST_STAT = 0x7e, + HOST_IRQ_STAT = 0xbc, + HOST_IRQ_MASK = 0xbe, + + PORT_SIZE = 0x40, + + /* registers for ATA TF operation */ + PORT_TF = 0x00, + PORT_ALT_STAT = 0x08, + PORT_IRQ_STAT = 0x09, + PORT_IRQ_MASK = 0x0a, + PORT_PRD_CTL = 0x0b, + PORT_PRD_ADDR = 0x0c, + PORT_PRD_XFERLEN = 0x10, + + /* IDMA register */ + PORT_IDMA_CTL = 0x14, + + PORT_SCR = 0x20, + + /* HOST_CTL bits */ + HCTL_IRQOFF = (1 << 8), /* global IRQ off */ + HCTL_PWRDWN = (1 << 13), /* power down PHYs */ + HCTL_SOFTRST = (1 << 13), /* global reset (no phy reset) */ + HCTL_RPGSEL = (1 << 15), /* register page select */ + + HCTL_KNOWN_BITS = HCTL_IRQOFF | HCTL_PWRDWN | HCTL_SOFTRST | + HCTL_RPGSEL, + + /* HOST_IRQ_(STAT|MASK) bits */ + HIRQ_PORT0 = (1 << 0), + HIRQ_PORT1 = (1 << 1), + HIRQ_SOFT = (1 << 14), + HIRQ_GLOBAL = (1 << 15), /* STAT only */ + + /* PORT_IRQ_(STAT|MASK) bits */ + PIRQ_OFFLINE = (1 << 0), /* device unplugged */ + PIRQ_ONLINE = (1 << 1), /* device plugged */ + PIRQ_COMPLETE = (1 << 2), /* completion interrupt */ + PIRQ_FATAL = (1 << 3), /* fatal error */ + PIRQ_ATA = (1 << 4), /* ATA interrupt */ + PIRQ_REPLY = (1 << 5), /* reply FIFO not empty */ + PIRQ_PENDING = (1 << 7), /* port IRQ pending (STAT only) */ + + PIRQ_ERR = PIRQ_OFFLINE | PIRQ_ONLINE | PIRQ_FATAL, + + PIRQ_MASK_DMA_READ = PIRQ_REPLY | PIRQ_ATA, + PIRQ_MASK_OTHER = PIRQ_REPLY | PIRQ_COMPLETE, + PIRQ_MASK_FREEZE = 0xff, + + /* PORT_PRD_CTL bits */ + PRD_CTL_START = (1 << 0), + PRD_CTL_WR = (1 << 3), + PRD_CTL_DMAEN = (1 << 7), /* DMA enable */ + + /* PORT_IDMA_CTL bits */ + IDMA_CTL_RST_ATA = (1 << 2), /* hardreset ATA bus */ + IDMA_CTL_RST_IDMA = (1 << 5), /* reset IDMA machinary */ + IDMA_CTL_GO = (1 << 7), /* IDMA mode go */ + IDMA_CTL_ATA_NIEN = (1 << 8), /* ATA IRQ disable */ +}; + +struct inic_host_priv { + u16 cached_hctl; +}; + +struct inic_port_priv { + u8 dfl_prdctl; + u8 cached_prdctl; + u8 cached_pirq_mask; +}; + +static int inic_slave_config(struct scsi_device *sdev) +{ + /* This controller is braindamaged. dma_boundary is 0xffff + * like others but it will lock up the whole machine HARD if + * 65536 byte PRD entry is fed. Reduce maximum segment size. + */ + blk_queue_max_segment_size(sdev->request_queue, 65536 - 512); + + return ata_scsi_slave_config(sdev); +} + +static struct scsi_host_template inic_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = inic_slave_config, + .slave_destroy = ata_scsi_slave_destroy, + .bios_param = ata_std_bios_param, + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, +}; + +static const int scr_map[] = { + [SCR_STATUS] = 0, + [SCR_ERROR] = 1, + [SCR_CONTROL] = 2, +}; + +static void __iomem * inic_port_base(struct ata_port *ap) +{ + return ap->host->mmio_base + ap->port_no * PORT_SIZE; +} + +static void __inic_set_pirq_mask(struct ata_port *ap, u8 mask) +{ + void __iomem *port_base = inic_port_base(ap); + struct inic_port_priv *pp = ap->private_data; + + writeb(mask, port_base + PORT_IRQ_MASK); + pp->cached_pirq_mask = mask; +} + +static void inic_set_pirq_mask(struct ata_port *ap, u8 mask) +{ + struct inic_port_priv *pp = ap->private_data; + + if (pp->cached_pirq_mask != mask) + __inic_set_pirq_mask(ap, mask); +} + +static void inic_reset_port(void __iomem *port_base) +{ + void __iomem *idma_ctl = port_base + PORT_IDMA_CTL; + u16 ctl; + + ctl = readw(idma_ctl); + ctl &= ~(IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN | IDMA_CTL_GO); + + /* mask IRQ and assert reset */ + writew(ctl | IDMA_CTL_RST_IDMA | IDMA_CTL_ATA_NIEN, idma_ctl); + readw(idma_ctl); /* flush */ + + /* give it some time */ + msleep(1); + + /* release reset */ + writew(ctl | IDMA_CTL_ATA_NIEN, idma_ctl); + + /* clear irq */ + writeb(0xff, port_base + PORT_IRQ_STAT); + + /* reenable ATA IRQ, turn off IDMA mode */ + writew(ctl, idma_ctl); +} + +static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg) +{ + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; + void __iomem *addr; + u32 val; + + if (unlikely(sc_reg >= ARRAY_SIZE(scr_map))) + return 0xffffffffU; + + addr = scr_addr + scr_map[sc_reg] * 4; + val = readl(scr_addr + scr_map[sc_reg] * 4); + + /* this controller has stuck DIAG.N, ignore it */ + if (sc_reg == SCR_ERROR) + val &= ~SERR_PHYRDY_CHG; + return val; +} + +static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) +{ + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; + void __iomem *addr; + + if (unlikely(sc_reg >= ARRAY_SIZE(scr_map))) + return; + + addr = scr_addr + scr_map[sc_reg] * 4; + writel(val, scr_addr + scr_map[sc_reg] * 4); +} + +/* + * In TF mode, inic162x is very similar to SFF device. TF registers + * function the same. DMA engine behaves similary using the same PRD + * format as BMDMA but different command register, interrupt and event + * notification methods are used. The following inic_bmdma_*() + * functions do the impedance matching. + */ +static void inic_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct inic_port_priv *pp = ap->private_data; + void __iomem *port_base = inic_port_base(ap); + int rw = qc->tf.flags & ATA_TFLAG_WRITE; + + /* make sure device sees PRD table writes */ + wmb(); + + /* load transfer length */ + writel(qc->nbytes, port_base + PORT_PRD_XFERLEN); + + /* turn on DMA and specify data direction */ + pp->cached_prdctl = pp->dfl_prdctl | PRD_CTL_DMAEN; + if (!rw) + pp->cached_prdctl |= PRD_CTL_WR; + writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL); + + /* issue r/w command */ + ap->ops->exec_command(ap, &qc->tf); +} + +static void inic_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct inic_port_priv *pp = ap->private_data; + void __iomem *port_base = inic_port_base(ap); + + /* start host DMA transaction */ + pp->cached_prdctl |= PRD_CTL_START; + writeb(pp->cached_prdctl, port_base + PORT_PRD_CTL); +} + +static void inic_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct inic_port_priv *pp = ap->private_data; + void __iomem *port_base = inic_port_base(ap); + + /* stop DMA engine */ + writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL); +} + +static u8 inic_bmdma_status(struct ata_port *ap) +{ + /* event is already verified by the interrupt handler */ + return ATA_DMA_INTR; +} + +static void inic_irq_clear(struct ata_port *ap) +{ + /* noop */ +} + +static void inic_host_intr(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + struct ata_eh_info *ehi = &ap->eh_info; + u8 irq_stat; + + /* fetch and clear irq */ + irq_stat = readb(port_base + PORT_IRQ_STAT); + writeb(irq_stat, port_base + PORT_IRQ_STAT); + + if (likely(!(irq_stat & PIRQ_ERR))) { + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); + + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { + ata_chk_status(ap); /* clear ATA interrupt */ + return; + } + + if (likely(ata_host_intr(ap, qc))) + return; + + ata_chk_status(ap); /* clear ATA interrupt */ + ata_port_printk(ap, KERN_WARNING, "unhandled " + "interrupt, irq_stat=%x\n", irq_stat); + return; + } + + /* error */ + ata_ehi_push_desc(ehi, "irq_stat=0x%x", irq_stat); + + if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) { + ata_ehi_hotplugged(ehi); + ata_port_freeze(ap); + } else + ata_port_abort(ap); +} + +static irqreturn_t inic_interrupt(int irq, void *dev_instance) +{ + struct ata_host *host = dev_instance; + void __iomem *mmio_base = host->mmio_base; + u16 host_irq_stat; + int i, handled = 0;; + + host_irq_stat = readw(mmio_base + HOST_IRQ_STAT); + + if (unlikely(!(host_irq_stat & HIRQ_GLOBAL))) + goto out; + + spin_lock(&host->lock); + + for (i = 0; i < NR_PORTS; i++) { + struct ata_port *ap = host->ports[i]; + + if (!(host_irq_stat & (HIRQ_PORT0 << i))) + continue; + + if (likely(ap && !(ap->flags & ATA_FLAG_DISABLED))) { + inic_host_intr(ap); + handled++; + } else { + if (ata_ratelimit()) + dev_printk(KERN_ERR, host->dev, "interrupt " + "from disabled port %d (0x%x)\n", + i, host_irq_stat); + } + } + + spin_unlock(&host->lock); + + out: + return IRQ_RETVAL(handled); +} + +static unsigned int inic_qc_issue(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + /* ATA IRQ doesn't wait for DMA transfer completion and vice + * versa. Mask IRQ selectively to detect command completion. + * Without it, ATA DMA read command can cause data corruption. + * + * Something similar might be needed for ATAPI writes. I + * tried a lot of combinations but couldn't find the solution. + */ + if (qc->tf.protocol == ATA_PROT_DMA && + !(qc->tf.flags & ATA_TFLAG_WRITE)) + inic_set_pirq_mask(ap, PIRQ_MASK_DMA_READ); + else + inic_set_pirq_mask(ap, PIRQ_MASK_OTHER); + + /* Issuing a command to yet uninitialized port locks up the + * controller. Most of the time, this happens for the first + * command after reset which are ATA and ATAPI IDENTIFYs. + * Fast fail if stat is 0x7f or 0xff for those commands. + */ + if (unlikely(qc->tf.command == ATA_CMD_ID_ATA || + qc->tf.command == ATA_CMD_ID_ATAPI)) { + u8 stat = ata_chk_status(ap); + if (stat == 0x7f || stat == 0xff) + return AC_ERR_HSM; + } + + return ata_qc_issue_prot(qc); +} + +static void inic_freeze(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + + __inic_set_pirq_mask(ap, PIRQ_MASK_FREEZE); + + ata_chk_status(ap); + writeb(0xff, port_base + PORT_IRQ_STAT); + + readb(port_base + PORT_IRQ_STAT); /* flush */ +} + +static void inic_thaw(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + + ata_chk_status(ap); + writeb(0xff, port_base + PORT_IRQ_STAT); + + __inic_set_pirq_mask(ap, PIRQ_MASK_OTHER); + + readb(port_base + PORT_IRQ_STAT); /* flush */ +} + +/* + * SRST and SControl hardreset don't give valid signature on this + * controller. Only controller specific hardreset mechanism works. + */ +static int inic_hardreset(struct ata_port *ap, unsigned int *class) +{ + void __iomem *port_base = inic_port_base(ap); + void __iomem *idma_ctl = port_base + PORT_IDMA_CTL; + const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context); + u16 val; + int rc; + + /* hammer it into sane state */ + inic_reset_port(port_base); + + if (ata_port_offline(ap)) { + *class = ATA_DEV_NONE; + return 0; + } + + val = readw(idma_ctl); + writew(val | IDMA_CTL_RST_ATA, idma_ctl); + readw(idma_ctl); /* flush */ + msleep(1); + writew(val & ~IDMA_CTL_RST_ATA, idma_ctl); + + rc = sata_phy_resume(ap, timing); + if (rc) { + ata_port_printk(ap, KERN_WARNING, "failed to resume " + "link for reset (errno=%d)\n", rc); + return rc; + } + + msleep(150); + + *class = ATA_DEV_NONE; + if (ata_port_online(ap)) { + struct ata_taskfile tf; + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + ata_port_printk(ap, KERN_WARNING, + "device busy after hardreset\n"); + return -EIO; + } + + ata_tf_read(ap, &tf); + *class = ata_dev_classify(&tf); + if (*class == ATA_DEV_UNKNOWN) + *class = ATA_DEV_NONE; + } + + return 0; +} + +static void inic_error_handler(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + struct inic_port_priv *pp = ap->private_data; + unsigned long flags; + + /* reset PIO HSM and stop DMA engine */ + inic_reset_port(port_base); + + spin_lock_irqsave(ap->lock, flags); + ap->hsm_task_state = HSM_ST_IDLE; + writeb(pp->dfl_prdctl, port_base + PORT_PRD_CTL); + spin_unlock_irqrestore(ap->lock, flags); + + /* PIO and DMA engines have been stopped, perform recovery */ + ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset, + ata_std_postreset); +} + +static void inic_post_internal_cmd(struct ata_queued_cmd *qc) +{ + /* make DMA engine forget about the failed command */ + if (qc->err_mask) + inic_reset_port(inic_port_base(qc->ap)); +} + +static void inic_dev_config(struct ata_port *ap, struct ata_device *dev) +{ + /* inic can only handle upto LBA28 max sectors */ + if (dev->max_sectors > ATA_MAX_SECTORS) + dev->max_sectors = ATA_MAX_SECTORS; +} + +static void init_port(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + + /* Setup PRD address */ + writel(ap->prd_dma, port_base + PORT_PRD_ADDR); +} + +static int inic_port_resume(struct ata_port *ap) +{ + init_port(ap); + return 0; +} + +static int inic_port_start(struct ata_port *ap) +{ + void __iomem *port_base = inic_port_base(ap); + struct inic_port_priv *pp; + u8 tmp; + int rc; + + /* alloc and initialize private data */ + pp = kzalloc(sizeof(*pp), GFP_KERNEL); + if (!pp) + return -ENOMEM; + ap->private_data = pp; + + /* default PRD_CTL value, DMAEN, WR and START off */ + tmp = readb(port_base + PORT_PRD_CTL); + tmp &= ~(PRD_CTL_DMAEN | PRD_CTL_WR | PRD_CTL_START); + pp->dfl_prdctl = tmp; + + /* Alloc resources */ + rc = ata_port_start(ap); + if (rc) { + kfree(pp); + return rc; + } + + init_port(ap); + + return 0; +} + +static void inic_port_stop(struct ata_port *ap) +{ + ata_port_stop(ap); + kfree(ap->private_data); +} + +static struct ata_port_operations inic_port_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .scr_read = inic_scr_read, + .scr_write = inic_scr_write, + + .bmdma_setup = inic_bmdma_setup, + .bmdma_start = inic_bmdma_start, + .bmdma_stop = inic_bmdma_stop, + .bmdma_status = inic_bmdma_status, + + .irq_handler = inic_interrupt, + .irq_clear = inic_irq_clear, + + .qc_prep = ata_qc_prep, + .qc_issue = inic_qc_issue, + .data_xfer = ata_pio_data_xfer, + + .freeze = inic_freeze, + .thaw = inic_thaw, + .error_handler = inic_error_handler, + .post_internal_cmd = inic_post_internal_cmd, + .dev_config = inic_dev_config, + + .port_resume = inic_port_resume, + + .port_start = inic_port_start, + .port_stop = inic_port_stop, + .host_stop = ata_pci_host_stop +}; + +static struct ata_port_info inic_port_info = { + .sht = &inic_sht, + /* For some reason, ATA_PROT_ATAPI is broken on this + * controller, and no, PIO_POLLING does't fix it. It somehow + * manages to report the wrong ireason and ignoring ireason + * results in machine lock up. Tell libata to always prefer + * DMA. + */ + .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &inic_port_ops +}; + +static int init_controller(void __iomem *mmio_base, u16 hctl) +{ + int i; + u16 val; + + hctl &= ~HCTL_KNOWN_BITS; + + /* Soft reset whole controller. Spec says reset duration is 3 + * PCI clocks, be generous and give it 10ms. + */ + writew(hctl | HCTL_SOFTRST, mmio_base + HOST_CTL); + readw(mmio_base + HOST_CTL); /* flush */ + + for (i = 0; i < 10; i++) { + msleep(1); + val = readw(mmio_base + HOST_CTL); + if (!(val & HCTL_SOFTRST)) + break; + } + + if (val & HCTL_SOFTRST) + return -EIO; + + /* mask all interrupts and reset ports */ + for (i = 0; i < NR_PORTS; i++) { + void __iomem *port_base = mmio_base + i * PORT_SIZE; + + writeb(0xff, port_base + PORT_IRQ_MASK); + inic_reset_port(port_base); + } + + /* port IRQ is masked now, unmask global IRQ */ + writew(hctl & ~HCTL_IRQOFF, mmio_base + HOST_CTL); + val = readw(mmio_base + HOST_IRQ_MASK); + val &= ~(HIRQ_PORT0 | HIRQ_PORT1); + writew(val, mmio_base + HOST_IRQ_MASK); + + return 0; +} + +static int inic_pci_device_resume(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct inic_host_priv *hpriv = host->private_data; + void __iomem *mmio_base = host->mmio_base; + int rc; + + ata_pci_device_do_resume(pdev); + + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { + printk("XXX\n"); + rc = init_controller(mmio_base, hpriv->cached_hctl); + if (rc) + return rc; + } + + ata_host_resume(host); + + return 0; +} + +static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_port_info *pinfo = &inic_port_info; + struct ata_probe_ent *probe_ent; + struct inic_host_priv *hpriv; + void __iomem *mmio_base; + int i, rc; + + if (!printed_version++) + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + rc = -ENOMEM; + mmio_base = pci_iomap(pdev, MMIO_BAR, 0); + if (!mmio_base) + goto err_out_regions; + + /* Set dma_mask. This devices doesn't support 64bit addressing. */ + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); + goto err_out_map; + } + + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); + goto err_out_map; + } + + rc = -ENOMEM; + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) + goto err_out_map; + + hpriv = kzalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) + goto err_out_ent; + + probe_ent->dev = &pdev->dev; + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->sht = pinfo->sht; + probe_ent->port_flags = pinfo->flags; + probe_ent->pio_mask = pinfo->pio_mask; + probe_ent->mwdma_mask = pinfo->mwdma_mask; + probe_ent->udma_mask = pinfo->udma_mask; + probe_ent->port_ops = pinfo->port_ops; + probe_ent->n_ports = NR_PORTS; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + + probe_ent->mmio_base = mmio_base; + + for (i = 0; i < NR_PORTS; i++) { + struct ata_ioports *port = &probe_ent->port[i]; + unsigned long port_base = + (unsigned long)mmio_base + i * PORT_SIZE; + + port->cmd_addr = pci_resource_start(pdev, 2 * i); + port->altstatus_addr = + port->ctl_addr = + pci_resource_start(pdev, 2 * i + 1) | ATA_PCI_CTL_OFS; + port->scr_addr = port_base + PORT_SCR; + + ata_std_ports(port); + } + + probe_ent->private_data = hpriv; + hpriv->cached_hctl = readw(mmio_base + HOST_CTL); + + rc = init_controller(mmio_base, hpriv->cached_hctl); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to initialize controller\n"); + goto err_out_hpriv; + } + + pci_set_master(pdev); + + rc = -ENODEV; + if (!ata_device_add(probe_ent)) + goto err_out_hpriv; + + kfree(probe_ent); + + return 0; + + err_out_hpriv: + kfree(hpriv); + err_out_ent: + kfree(probe_ent); + err_out_map: + pci_iounmap(pdev, mmio_base); + err_out_regions: + pci_release_regions(pdev); + err_out: + pci_disable_device(pdev); + return rc; +} + +static const struct pci_device_id inic_pci_tbl[] = { + { PCI_VDEVICE(INIT, 0x1622), }, + { }, +}; + +static struct pci_driver inic_pci_driver = { + .name = DRV_NAME, + .id_table = inic_pci_tbl, + .suspend = ata_pci_device_suspend, + .resume = inic_pci_device_resume, + .probe = inic_init_one, + .remove = ata_pci_remove_one, +}; + +static int __init inic_init(void) +{ + return pci_register_driver(&inic_pci_driver); +} + +static void __exit inic_exit(void) +{ + pci_unregister_driver(&inic_pci_driver); +} + +MODULE_AUTHOR("Tejun Heo"); +MODULE_DESCRIPTION("low-level driver for Initio 162x SATA"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, inic_pci_tbl); +MODULE_VERSION(DRV_VERSION); + +module_init(inic_init); +module_exit(inic_exit); diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index f7a963e..246df22 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -49,7 +49,7 @@ #include #include #define DRV_NAME "sata_nv" -#define DRV_VERSION "3.2" +#define DRV_VERSION "3.3" #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL @@ -213,12 +213,21 @@ struct nv_adma_port_priv { dma_addr_t cpb_dma; struct nv_adma_prd *aprd; dma_addr_t aprd_dma; + void __iomem * ctl_block; + void __iomem * gen_block; + void __iomem * notifier_clear_block; u8 flags; }; +struct nv_host_priv { + unsigned long type; +}; + #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static void nv_remove_one (struct pci_dev *pdev); +static int nv_pci_device_resume(struct pci_dev *pdev); static void nv_ck804_host_stop(struct ata_host *host); static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance); static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance); @@ -239,6 +248,8 @@ static irqreturn_t nv_adma_interrupt(int static void nv_adma_irq_clear(struct ata_port *ap); static int nv_adma_port_start(struct ata_port *ap); static void nv_adma_port_stop(struct ata_port *ap); +static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); +static int nv_adma_port_resume(struct ata_port *ap); static void nv_adma_error_handler(struct ata_port *ap); static void nv_adma_host_stop(struct ata_host *host); static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc); @@ -284,7 +295,9 @@ static struct pci_driver nv_pci_driver = .name = DRV_NAME, .id_table = nv_pci_tbl, .probe = nv_init_one, - .remove = ata_pci_remove_one, + .suspend = ata_pci_device_suspend, + .resume = nv_pci_device_resume, + .remove = nv_remove_one, }; static struct scsi_host_template nv_sht = { @@ -303,6 +316,8 @@ static struct scsi_host_template nv_sht .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, }; static struct scsi_host_template nv_adma_sht = { @@ -321,6 +336,8 @@ static struct scsi_host_template nv_adma .slave_configure = nv_adma_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, }; static const struct ata_port_operations nv_generic_ops = { @@ -429,6 +446,8 @@ static const struct ata_port_operations .scr_write = nv_scr_write, .port_start = nv_adma_port_start, .port_stop = nv_adma_port_stop, + .port_suspend = nv_adma_port_suspend, + .port_resume = nv_adma_port_resume, .host_stop = nv_adma_host_stop, }; @@ -467,6 +486,7 @@ static struct ata_port_info nv_port_info { .sht = &nv_adma_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_HRST_TO_RESUME | ATA_FLAG_MMIO | ATA_FLAG_NCQ, .pio_mask = NV_PIO_MASK, .mwdma_mask = NV_MWDMA_MASK, @@ -483,32 +503,10 @@ MODULE_VERSION(DRV_VERSION); static int adma_enabled = 1; -static inline void __iomem *__nv_adma_ctl_block(void __iomem *mmio, - unsigned int port_no) -{ - mmio += NV_ADMA_PORT + port_no * NV_ADMA_PORT_SIZE; - return mmio; -} - -static inline void __iomem *nv_adma_ctl_block(struct ata_port *ap) -{ - return __nv_adma_ctl_block(ap->host->mmio_base, ap->port_no); -} - -static inline void __iomem *nv_adma_gen_block(struct ata_port *ap) -{ - return (ap->host->mmio_base + NV_ADMA_GEN); -} - -static inline void __iomem *nv_adma_notifier_clear_block(struct ata_port *ap) -{ - return (nv_adma_gen_block(ap) + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no)); -} - static void nv_adma_register_mode(struct ata_port *ap) { - void __iomem *mmio = nv_adma_ctl_block(ap); struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = pp->ctl_block; u16 tmp; if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) @@ -522,13 +520,13 @@ static void nv_adma_register_mode(struct static void nv_adma_mode(struct ata_port *ap) { - void __iomem *mmio = nv_adma_ctl_block(ap); struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = pp->ctl_block; u16 tmp; if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) return; - + WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); tmp = readw(mmio + NV_ADMA_CTL); @@ -568,7 +566,7 @@ static int nv_adma_slave_config(struct s /* Subtract 1 since an extra entry may be needed for padding, see libata-scsi.c */ sg_tablesize = LIBATA_MAX_PRD - 1; - + /* Since the legacy DMA engine is in use, we need to disable ADMA on the port. */ adma_enable = 0; @@ -580,7 +578,7 @@ static int nv_adma_slave_config(struct s sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; adma_enable = 1; } - + pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg); if(ap->port_no == 1) @@ -589,7 +587,7 @@ static int nv_adma_slave_config(struct s else config_mask = NV_MCP_SATA_CFG_20_PORT0_EN | NV_MCP_SATA_CFG_20_PORT0_PWB_EN; - + if(adma_enable) { new_reg = current_reg | config_mask; pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE; @@ -598,10 +596,10 @@ static int nv_adma_slave_config(struct s new_reg = current_reg & ~config_mask; pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE; } - + if(current_reg != new_reg) pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); - + blk_queue_bounce_limit(sdev->request_queue, bounce_limit); blk_queue_segment_boundary(sdev->request_queue, segment_boundary); blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); @@ -684,7 +682,7 @@ static void nv_adma_check_cpb(struct ata For NCQ commands the current status may have nothing to do with the command just completed. */ if(qc->tf.protocol != ATA_PROT_NCQ) - ata_status = readb(nv_adma_ctl_block(ap) + (ATA_REG_STATUS * 4)); + ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4)); if(have_err || force_err) ata_status |= ATA_ERR; @@ -735,7 +733,7 @@ static irqreturn_t nv_adma_interrupt(int if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = nv_adma_ctl_block(ap); + void __iomem *mmio = pp->ctl_block; u16 status; u32 gen_ctl; int have_global_err = 0; @@ -758,7 +756,7 @@ static irqreturn_t nv_adma_interrupt(int notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); notifier_clears[i] = notifier | notifier_error; - gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); + gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier && !notifier_error) @@ -812,14 +810,14 @@ static irqreturn_t nv_adma_interrupt(int handled++; /* irq handled if we got here */ } } - + if(notifier_clears[0] || notifier_clears[1]) { /* Note: Both notifier clear registers must be written if either is set, even if one is zero, according to NVIDIA. */ - writel(notifier_clears[0], - nv_adma_notifier_clear_block(host->ports[0])); - writel(notifier_clears[1], - nv_adma_notifier_clear_block(host->ports[1])); + struct nv_adma_port_priv *pp = host->ports[0]->private_data; + writel(notifier_clears[0], pp->notifier_clear_block); + pp = host->ports[1]->private_data; + writel(notifier_clears[1], pp->notifier_clear_block); } spin_unlock(&host->lock); @@ -829,7 +827,8 @@ static irqreturn_t nv_adma_interrupt(int static void nv_adma_irq_clear(struct ata_port *ap) { - void __iomem *mmio = nv_adma_ctl_block(ap); + struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = pp->ctl_block; u16 status = readw(mmio + NV_ADMA_STAT); u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); @@ -838,7 +837,7 @@ static void nv_adma_irq_clear(struct ata /* clear ADMA status */ writew(status, mmio + NV_ADMA_STAT); writel(notifier | notifier_error, - nv_adma_notifier_clear_block(ap)); + pp->notifier_clear_block); /** clear legacy status */ outb(inb(dma_stat_addr), dma_stat_addr); @@ -920,7 +919,7 @@ static int nv_adma_port_start(struct ata int rc; void *mem; dma_addr_t mem_dma; - void __iomem *mmio = nv_adma_ctl_block(ap); + void __iomem *mmio; u16 tmp; VPRINTK("ENTER\n"); @@ -935,6 +934,13 @@ static int nv_adma_port_start(struct ata goto err_out; } + mmio = ap->host->mmio_base + NV_ADMA_PORT + + ap->port_no * NV_ADMA_PORT_SIZE; + pp->ctl_block = mmio; + pp->gen_block = ap->host->mmio_base + NV_ADMA_GEN; + pp->notifier_clear_block = pp->gen_block + + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); + mem = dma_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); @@ -975,9 +981,9 @@ static int nv_adma_port_start(struct ata /* clear CPB fetch count */ writew(0, mmio + NV_ADMA_CPB_COUNT); - /* clear GO for register mode */ + /* clear GO for register mode, enable interrupt */ tmp = readw(mmio + NV_ADMA_CTL); - writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); + writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); tmp = readw(mmio + NV_ADMA_CTL); writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); @@ -999,7 +1005,7 @@ static void nv_adma_port_stop(struct ata { struct device *dev = ap->host->dev; struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = nv_adma_ctl_block(ap); + void __iomem *mmio = pp->ctl_block; VPRINTK("ENTER\n"); @@ -1011,6 +1017,55 @@ static void nv_adma_port_stop(struct ata ata_port_stop(ap); } +static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg) +{ + struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = pp->ctl_block; + + /* Go to register mode - clears GO */ + nv_adma_register_mode(ap); + + /* clear CPB fetch count */ + writew(0, mmio + NV_ADMA_CPB_COUNT); + + /* disable interrupt, shut down port */ + writew(0, mmio + NV_ADMA_CTL); + + return 0; +} + +static int nv_adma_port_resume(struct ata_port *ap) +{ + struct nv_adma_port_priv *pp = ap->private_data; + void __iomem *mmio = pp->ctl_block; + u16 tmp; + + /* set CPB block location */ + writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW); + writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH); + + /* clear any outstanding interrupt conditions */ + writew(0xffff, mmio + NV_ADMA_STAT); + + /* initialize port variables */ + pp->flags |= NV_ADMA_PORT_REGISTER_MODE; + + /* clear CPB fetch count */ + writew(0, mmio + NV_ADMA_CPB_COUNT); + + /* clear GO for register mode, enable interrupt */ + tmp = readw(mmio + NV_ADMA_CTL); + writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); + + tmp = readw(mmio + NV_ADMA_CTL); + writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + udelay(1); + writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL); + readl( mmio + NV_ADMA_CTL ); /* flush posted write */ + + return 0; +} static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port) { @@ -1056,15 +1111,6 @@ static int nv_adma_host_init(struct ata_ for (i = 0; i < probe_ent->n_ports; i++) nv_adma_setup_port(probe_ent, i); - for (i = 0; i < probe_ent->n_ports; i++) { - void __iomem *mmio = __nv_adma_ctl_block(probe_ent->mmio_base, i); - u16 tmp; - - /* enable interrupt, clear reset if not already clear */ - tmp = readw(mmio + NV_ADMA_CTL); - writew(tmp | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); - } - return 0; } @@ -1118,8 +1164,6 @@ static void nv_adma_qc_prep(struct ata_q NV_CPB_CTL_APRD_VALID | NV_CPB_CTL_IEN; - VPRINTK("qc->flags = 0x%lx\n", qc->flags); - if (!(qc->flags & ATA_QCFLAG_DMAMAP) || (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { nv_adma_register_mode(qc->ap); @@ -1137,6 +1181,8 @@ static void nv_adma_qc_prep(struct ata_q if (qc->tf.protocol == ATA_PROT_NCQ) ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA; + VPRINTK("qc->flags = 0x%lx\n", qc->flags); + nv_adma_tf_to_cpb(&qc->tf, cpb->tf); nv_adma_fill_sg(qc, cpb); @@ -1150,7 +1196,7 @@ static void nv_adma_qc_prep(struct ata_q static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) { struct nv_adma_port_priv *pp = qc->ap->private_data; - void __iomem *mmio = nv_adma_ctl_block(qc->ap); + void __iomem *mmio = pp->ctl_block; VPRINTK("ENTER\n"); @@ -1335,13 +1381,13 @@ static void nv_adma_error_handler(struct { struct nv_adma_port_priv *pp = ap->private_data; if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) { - void __iomem *mmio = nv_adma_ctl_block(ap); + void __iomem *mmio = pp->ctl_block; int i; u16 tmp; u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); - u32 gen_ctl = readl(nv_adma_gen_block(ap) + NV_ADMA_GEN_CTL); + u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); u32 status = readw(mmio + NV_ADMA_STAT); ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X " @@ -1386,6 +1432,7 @@ static int nv_init_one (struct pci_dev * static int printed_version = 0; struct ata_port_info *ppi[2]; struct ata_probe_ent *probe_ent; + struct nv_host_priv *hpriv; int pci_dev_busy = 0; int rc; u32 bar; @@ -1400,7 +1447,7 @@ static int nv_init_one (struct pci_dev * if (pci_resource_start(pdev, bar) == 0) return -ENODEV; - if ( !printed_version++) + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); rc = pci_enable_device(pdev); @@ -1432,6 +1479,10 @@ static int nv_init_one (struct pci_dev * rc = -ENOMEM; + hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) + goto err_out_regions; + ppi[0] = ppi[1] = &nv_port_info[type]; probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) @@ -1442,6 +1493,8 @@ static int nv_init_one (struct pci_dev * rc = -EIO; goto err_out_free_ent; } + probe_ent->private_data = hpriv; + hpriv->type = type; base = (unsigned long)probe_ent->mmio_base; @@ -1486,6 +1539,60 @@ err_out: return rc; } +static void nv_remove_one (struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct nv_host_priv *hpriv = host->private_data; + + ata_pci_remove_one(pdev); + kfree(hpriv); +} + +static int nv_pci_device_resume(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct nv_host_priv *hpriv = host->private_data; + + ata_pci_device_do_resume(pdev); + + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { + if(hpriv->type >= CK804) { + u8 regval; + + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); + regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); + } + if(hpriv->type == ADMA) { + u32 tmp32; + struct nv_adma_port_priv *pp; + /* enable/disable ADMA on the ports appropriately */ + pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); + + pp = host->ports[0]->private_data; + if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + else + tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN | + NV_MCP_SATA_CFG_20_PORT0_PWB_EN); + pp = host->ports[1]->private_data; + if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) + tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN | + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + else + tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN | + NV_MCP_SATA_CFG_20_PORT1_PWB_EN); + + pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32); + } + } + + ata_host_resume(host); + + return 0; +} + static void nv_ck804_host_stop(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -1502,18 +1609,8 @@ static void nv_ck804_host_stop(struct at static void nv_adma_host_stop(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); - int i; u32 tmp32; - for (i = 0; i < host->n_ports; i++) { - void __iomem *mmio = __nv_adma_ctl_block(host->mmio_base, i); - u16 tmp; - - /* disable interrupt */ - tmp = readw(mmio + NV_ADMA_CTL); - writew(tmp & ~NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL); - } - /* disable ADMA on the ports */ pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32); tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN | diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index f055874..32ae03e 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -39,6 +39,7 @@ #include #include #include #include +#include #include #include #include @@ -50,6 +51,15 @@ #define DRV_VERSION "1.05" enum { + /* register offsets */ + PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */ + PDC_SECTOR_COUNT = 0x08, /* Sector count reg (per port) */ + PDC_SECTOR_NUMBER = 0x0C, /* Sector number reg (per port) */ + PDC_CYLINDER_LOW = 0x10, /* Cylinder low reg (per port) */ + PDC_CYLINDER_HIGH = 0x14, /* Cylinder high reg (per port) */ + PDC_DEVICE = 0x18, /* Device/Head reg (per port) */ + PDC_COMMAND = 0x1C, /* Command/status reg (per port) */ + PDC_ALTSTATUS = 0x38, /* Alternate-status/device-control reg (per port) */ PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ PDC_FLASH_CTL = 0x44, /* Flash control register */ @@ -71,13 +81,23 @@ enum { PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ + /* Sequence counter control registers bit definitions */ + PDC_SEQCNTRL_INT_MASK = (1 << 5), /* Sequence Interrupt Mask */ + + /* Feature register values */ + PDC_FEATURE_ATAPI_PIO = 0x00, /* ATAPI data xfer by PIO */ + PDC_FEATURE_ATAPI_DMA = 0x01, /* ATAPI data xfer by DMA */ + + /* Device/Head register values */ + PDC_DEVICE_SATA = 0xE0, /* Device/Head value for SATA devices */ + /* PDC_CTLSTAT bit definitions */ PDC_DMA_ENABLE = (1 << 7), PDC_IRQ_DISABLE = (1 << 10), PDC_RESET = (1 << 11), /* HDMA reset */ PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, /* hp->flags bits */ @@ -92,6 +112,7 @@ struct pdc_port_priv { struct pdc_host_priv { unsigned long flags; + unsigned long port_flags[ATA_MAX_PORTS]; }; static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -105,6 +126,8 @@ static void pdc_pata_phy_reset(struct at static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); +static int pdc_check_atapi_dma(struct ata_queued_cmd *qc); +static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc); static void pdc_irq_clear(struct ata_port *ap); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static void pdc_host_stop(struct ata_host *host); @@ -139,6 +162,34 @@ static const struct ata_port_operations .check_status = ata_check_status, .exec_command = pdc_exec_command_mmio, .dev_select = ata_std_dev_select, + .check_atapi_dma = pdc_check_atapi_dma, + + .qc_prep = pdc_qc_prep, + .qc_issue = pdc_qc_issue_prot, + .freeze = pdc_freeze, + .thaw = pdc_thaw, + .error_handler = pdc_error_handler, + .post_internal_cmd = pdc_post_internal_cmd, + .data_xfer = ata_mmio_data_xfer, + .irq_handler = pdc_interrupt, + .irq_clear = pdc_irq_clear, + + .scr_read = pdc_sata_scr_read, + .scr_write = pdc_sata_scr_write, + .port_start = pdc_port_start, + .port_stop = pdc_port_stop, + .host_stop = pdc_host_stop, +}; + +/* First-generation chips need a more restrictive ->check_atapi_dma op */ +static const struct ata_port_operations pdc_old_sata_ops = { + .port_disable = ata_port_disable, + .tf_load = pdc_tf_load_mmio, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = pdc_exec_command_mmio, + .dev_select = ata_std_dev_select, + .check_atapi_dma = pdc_old_check_atapi_dma, .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, @@ -164,6 +215,7 @@ static const struct ata_port_operations .check_status = ata_check_status, .exec_command = pdc_exec_command_mmio, .dev_select = ata_std_dev_select, + .check_atapi_dma = pdc_check_atapi_dma, .phy_reset = pdc_pata_phy_reset, @@ -183,11 +235,11 @@ static const struct ata_port_info pdc_po /* board_2037x */ { .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .flags = PDC_COMMON_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_sata_ops, + .port_ops = &pdc_old_sata_ops, }, /* board_20319 */ @@ -197,7 +249,7 @@ static const struct ata_port_info pdc_po .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_sata_ops, + .port_ops = &pdc_old_sata_ops, }, /* board_20619 */ @@ -213,7 +265,7 @@ static const struct ata_port_info pdc_po /* board_2057x */ { .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .flags = PDC_COMMON_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -271,6 +323,11 @@ static int pdc_port_start(struct ata_por struct pdc_port_priv *pp; int rc; + /* fix up port flags and cable type for SATA+PATA chips */ + ap->flags |= hp->port_flags[ap->port_no]; + if (ap->flags & ATA_FLAG_SATA) + ap->cbl = ATA_CBL_SATA; + rc = ata_port_start(ap); if (rc) return rc; @@ -377,7 +434,7 @@ static void pdc_pata_phy_reset(struct at static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) { - if (sc_reg > SCR_CONTROL) + if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA) return 0xffffffffU; return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); } @@ -386,11 +443,95 @@ static u32 pdc_sata_scr_read (struct ata static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) { - if (sc_reg > SCR_CONTROL) + if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA) return; writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); } +static void pdc_atapi_pkt(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + dma_addr_t sg_table = ap->prd_dma; + unsigned int cdb_len = qc->dev->cdb_len; + u8 *cdb = qc->cdb; + struct pdc_port_priv *pp = ap->private_data; + u8 *buf = pp->pkt; + u32 *buf32 = (u32 *) buf; + unsigned int dev_sel, feature, nbytes; + + /* set control bits (byte 0), zero delay seq id (byte 3), + * and seq id (byte 2) + */ + switch (qc->tf.protocol) { + case ATA_PROT_ATAPI_DMA: + if (!(qc->tf.flags & ATA_TFLAG_WRITE)) + buf32[0] = cpu_to_le32(PDC_PKT_READ); + else + buf32[0] = 0; + break; + case ATA_PROT_ATAPI_NODATA: + buf32[0] = cpu_to_le32(PDC_PKT_NODATA); + break; + default: + BUG(); + break; + } + buf32[1] = cpu_to_le32(sg_table); /* S/G table addr */ + buf32[2] = 0; /* no next-packet */ + + /* select drive */ + if (sata_scr_valid(ap)) { + dev_sel = PDC_DEVICE_SATA; + } else { + dev_sel = ATA_DEVICE_OBS; + if (qc->dev->devno != 0) + dev_sel |= ATA_DEV1; + } + buf[12] = (1 << 5) | ATA_REG_DEVICE; + buf[13] = dev_sel; + buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY; + buf[15] = dev_sel; /* once more, waiting for BSY to clear */ + + buf[16] = (1 << 5) | ATA_REG_NSECT; + buf[17] = 0x00; + buf[18] = (1 << 5) | ATA_REG_LBAL; + buf[19] = 0x00; + + /* set feature and byte counter registers */ + if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) { + feature = PDC_FEATURE_ATAPI_PIO; + /* set byte counter register to real transfer byte count */ + nbytes = qc->nbytes; + if (nbytes > 0xffff) + nbytes = 0xffff; + } else { + feature = PDC_FEATURE_ATAPI_DMA; + /* set byte counter register to 0 */ + nbytes = 0; + } + buf[20] = (1 << 5) | ATA_REG_FEATURE; + buf[21] = feature; + buf[22] = (1 << 5) | ATA_REG_BYTEL; + buf[23] = nbytes & 0xFF; + buf[24] = (1 << 5) | ATA_REG_BYTEH; + buf[25] = (nbytes >> 8) & 0xFF; + + /* send ATAPI packet command 0xA0 */ + buf[26] = (1 << 5) | ATA_REG_CMD; + buf[27] = ATA_CMD_PACKET; + + /* select drive and check DRQ */ + buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY; + buf[29] = dev_sel; + + /* we can represent cdb lengths 2/4/6/8/10/12/14/16 */ + BUG_ON(cdb_len & ~0x1E); + + /* append the CDB as the final part */ + buf[30] = (((cdb_len >> 1) & 7) << 5) | ATA_REG_DATA | PDC_LAST_REG; + memcpy(buf+31, cdb, cdb_len); +} + static void pdc_qc_prep(struct ata_queued_cmd *qc) { struct pdc_port_priv *pp = qc->ap->private_data; @@ -415,6 +556,17 @@ static void pdc_qc_prep(struct ata_queue pdc_pkt_footer(&qc->tf, pp->pkt, i); break; + case ATA_PROT_ATAPI: + ata_qc_prep(qc); + break; + + case ATA_PROT_ATAPI_DMA: + ata_qc_prep(qc); + /*FALLTHROUGH*/ + case ATA_PROT_ATAPI_NODATA: + pdc_atapi_pkt(qc); + break; + default: break; } @@ -528,6 +680,8 @@ static inline unsigned int pdc_host_intr switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: + case ATA_PROT_ATAPI_DMA: + case ATA_PROT_ATAPI_NODATA: qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); ata_qc_complete(qc); handled = 1; @@ -627,15 +781,16 @@ static inline void pdc_packet_start(stru static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { + case ATA_PROT_ATAPI_NODATA: + if (qc->dev->flags & ATA_DFLAG_CDB_INTR) + break; + /*FALLTHROUGH*/ + case ATA_PROT_ATAPI_DMA: case ATA_PROT_DMA: case ATA_PROT_NODATA: pdc_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: - BUG(); - break; - default: break; } @@ -658,6 +813,42 @@ static void pdc_exec_command_mmio(struct ata_exec_command(ap, tf); } +static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) +{ + u8 *scsicmd = qc->scsicmd->cmnd; + int pio = 1; /* atapi dma off by default */ + + /* Whitelist commands that may use DMA. */ + switch (scsicmd[0]) { + case WRITE_12: + case WRITE_10: + case WRITE_6: + case READ_12: + case READ_10: + case READ_6: + case 0xad: /* READ_DVD_STRUCTURE */ + case 0xbe: /* READ_CD */ + pio = 0; + } + /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */ + if (scsicmd[0] == WRITE_10) { + unsigned int lba; + lba = (scsicmd[2] << 24) | (scsicmd[3] << 16) | (scsicmd[4] << 8) | scsicmd[5]; + if (lba >= 0xFFFF4FA2) + pio = 1; + } + return pio; +} + +static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + /* First generation chips cannot use ATAPI DMA on SATA ports */ + if (sata_scr_valid(ap)) + return 1; + return pdc_check_atapi_dma(qc); +} static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) { @@ -740,6 +931,7 @@ static int pdc_ata_init_one (struct pci_ unsigned int board_idx = (unsigned int) ent->driver_data; int pci_dev_busy = 0; int rc; + u8 tmp; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -820,7 +1012,17 @@ static int pdc_ata_init_one (struct pci_ hp->flags |= PDC_FLAG_GEN_II; /* Fall through */ case board_2037x: - probe_ent->n_ports = 2; + /* TX2plus boards also have a PATA port */ + tmp = readb(mmio_base + PDC_FLASH_CTL+1); + if (!(tmp & 0x80)) { + probe_ent->n_ports = 3; + pdc_ata_setup_port(&probe_ent->port[2], base + 0x300); + hp->port_flags[2] = ATA_FLAG_SLAVE_POSS; + printk(KERN_INFO DRV_NAME " PATA port found\n"); + } else + probe_ent->n_ports = 2; + hp->port_flags[0] = ATA_FLAG_SATA; + hp->port_flags[1] = ATA_FLAG_SATA; break; case board_20619: probe_ent->n_ports = 4; diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 710909d..0292a79 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -325,7 +325,7 @@ static void qs_qc_prep(struct ata_queued /* host control block (HCB) */ buf[ 0] = QS_HCB_HDR; buf[ 1] = hflags; - *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); + *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nbytes); *(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem); addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; *(__le64 *)(&buf[16]) = cpu_to_le64(addr); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 7808d03..1f3fdcf 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -541,9 +541,9 @@ static void sil_dev_config(struct ata_po { int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; unsigned int n, quirks = 0; - unsigned char model_num[41]; + unsigned char model_num[ATA_ID_PROD_LEN + 1]; - ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); for (n = 0; sil_blacklist[n].product; n++) if (!strcmp(sil_blacklist[n].product, model_num)) { @@ -710,8 +710,12 @@ #ifdef CONFIG_PM static int sil_pci_device_resume(struct pci_dev *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; + + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; - ata_pci_device_do_resume(pdev); sil_init_controller(pdev, host->n_ports, host->ports[0]->flags, host->mmio_base); ata_host_resume(host); diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 5aa288d..da982ed 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1200,8 +1200,11 @@ static int sil24_pci_device_resume(struc { struct ata_host *host = dev_get_drvdata(&pdev->dev); struct sil24_host_priv *hpriv = host->private_data; + int rc; - ata_pci_device_do_resume(pdev); + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL); diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 9c25a1e..a915822 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -42,7 +42,7 @@ #include #include #define DRV_NAME "sata_sis" -#define DRV_VERSION "0.6" +#define DRV_VERSION "0.7" enum { sis_180 = 0, @@ -67,9 +67,12 @@ static u32 sis_scr_read (struct ata_port static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static const struct pci_device_id sis_pci_tbl[] = { - { PCI_VDEVICE(SI, 0x180), sis_180 }, - { PCI_VDEVICE(SI, 0x181), sis_180 }, - { PCI_VDEVICE(SI, 0x182), sis_180 }, + { PCI_VDEVICE(SI, 0x0180), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */ + { PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */ + { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/966L */ + { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L */ { } /* terminate list */ }; @@ -135,31 +138,42 @@ static struct ata_port_info sis_port_inf .port_ops = &sis_ops, }; - MODULE_AUTHOR("Uwe Koziolek"); MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sis_pci_tbl); MODULE_VERSION(DRV_VERSION); -static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device) +static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg) { + struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); + u8 pmr; - if (port_no) { - if (device == 0x182) - addr += SIS182_SATA1_OFS; - else - addr += SIS180_SATA1_OFS; + if (ap->port_no) { + switch (pdev->device) { + case 0x0180: + case 0x0181: + pci_read_config_byte(pdev, SIS_PMR, &pmr); + if ((pmr & SIS_PMR_COMBINED) == 0) + addr += SIS180_SATA1_OFS; + break; + + case 0x0182: + case 0x0183: + case 0x1182: + case 0x1183: + addr += SIS182_SATA1_OFS; + break; + } } - return addr; } static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); + unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); u32 val, val2 = 0; u8 pmr; @@ -170,26 +184,28 @@ static u32 sis_scr_cfg_read (struct ata_ pci_read_config_dword(pdev, cfg_addr, &val); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) || + (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED)) pci_read_config_dword(pdev, cfg_addr+0x10, &val2); return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */ } -static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) +static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device); + unsigned int cfg_addr = get_scr_cfg_addr(ap, sc_reg); u8 pmr; - if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ + if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ return; pci_read_config_byte(pdev, SIS_PMR, &pmr); pci_write_config_dword(pdev, cfg_addr, val); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) || + (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED)) pci_write_config_dword(pdev, cfg_addr+0x10, val); } @@ -209,7 +225,8 @@ static u32 sis_scr_read (struct ata_port val = inl(ap->ioaddr.scr_addr + (sc_reg * 4)); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) || + (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED)) val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); return (val | val2) & 0xfffffffb; @@ -229,13 +246,17 @@ static void sis_scr_write (struct ata_po sis_scr_cfg_write(ap, sc_reg, val); else { outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); - if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) + if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) || + (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED)) outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10); } } static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { + /* Provided by the PATA driver */ + extern struct ata_port_info sis_info133; + static int printed_version; struct ata_probe_ent *probe_ent = NULL; int rc; @@ -243,7 +264,7 @@ static int sis_init_one (struct pci_dev struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi }; int pci_dev_busy = 0; u8 pmr; - u8 port2_start; + u8 port2_start = 0x20; if (!printed_version++) dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); @@ -282,28 +303,53 @@ static int sis_init_one (struct pci_dev } pci_read_config_byte(pdev, SIS_PMR, &pmr); - if (ent->device != 0x182) { + switch (ent->device) { + case 0x0180: + case 0x0181: + + /* The PATA-handling is provided by pata_sis */ + switch (pmr & 0x30) { + case 0x10: + ppi[1] = &sis_info133; + break; + + case 0x30: + ppi[0] = &sis_info133; + break; + } if ((pmr & SIS_PMR_COMBINED) == 0) { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181/964 chipset in SATA mode\n"); port2_start = 64; - } - else { + } else { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 180/181 chipset in combined mode\n"); port2_start=0; pi.flags |= ATA_FLAG_SLAVE_POSS; } - } - else { + break; + + case 0x0182: + case 0x0183: pci_read_config_dword ( pdev, 0x6C, &val); if (val & (1L << 31)) { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965 chipset\n"); pi.flags |= ATA_FLAG_SLAVE_POSS; - } - else + } else { dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 182/965L chipset\n"); - port2_start = 0x20; + } + break; + + case 0x1182: + case 0x1183: + pci_read_config_dword(pdev, 0x64, &val); + if (val & 0x10000000) { + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966L SATA controller\n"); + } else { + dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966 SATA controller\n"); + pi.flags |= ATA_FLAG_SLAVE_POSS; + } + break; } probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); @@ -350,4 +396,3 @@ static void __exit sis_exit(void) module_init(sis_init); module_exit(sis_exit); - diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index d3d5c0d..e95acfa 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -59,11 +59,14 @@ enum { SATA_INT_GATE = 0x41, /* SATA interrupt gating */ SATA_NATIVE_MODE = 0x42, /* Native mode enable */ SATA_PATA_SHARING = 0x49, /* PATA/SATA sharing func ctrl */ - + PATA_UDMA_TIMING = 0xB3, /* PATA timing for DMA/ cable detect */ + PATA_PIO_TIMING = 0xAB, /* PATA timing register */ + PORT0 = (1 << 1), PORT1 = (1 << 0), ALL_PORTS = PORT0 | PORT1, - N_PORTS = 2, + PATA_PORT = 2, /* PATA is port 2 */ + N_PORTS = 3, NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), @@ -76,6 +79,11 @@ static u32 svia_scr_read (struct ata_por static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void svia_noop_freeze(struct ata_port *ap); static void vt6420_error_handler(struct ata_port *ap); +static void vt6421_sata_error_handler(struct ata_port *ap); +static void vt6421_pata_error_handler(struct ata_port *ap); +static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev); +static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); +static int vt6421_port_start(struct ata_port *ap); static const struct pci_device_id svia_pci_tbl[] = { { PCI_VDEVICE(VIA, 0x5337), vt6420 }, @@ -142,8 +150,11 @@ static const struct ata_port_operations .host_stop = ata_host_stop, }; -static const struct ata_port_operations vt6421_sata_ops = { +static const struct ata_port_operations vt6421_pata_ops = { .port_disable = ata_port_disable, + + .set_piomode = vt6421_set_pio_mode, + .set_dmamode = vt6421_set_dma_mode, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -162,7 +173,38 @@ static const struct ata_port_operations .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = vt6421_pata_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + + .irq_handler = ata_interrupt, + .irq_clear = ata_bmdma_irq_clear, + + .port_start = vt6421_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_host_stop, +}; + +static const struct ata_port_operations vt6421_sata_ops = { + .port_disable = ata_port_disable, + + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .data_xfer = ata_pio_data_xfer, + + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = vt6421_sata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt, @@ -171,7 +213,7 @@ static const struct ata_port_operations .scr_read = svia_scr_read, .scr_write = svia_scr_write, - .port_start = ata_port_start, + .port_start = vt6421_port_start, .port_stop = ata_port_stop, .host_stop = ata_host_stop, }; @@ -289,6 +331,61 @@ static void vt6420_error_handler(struct NULL, ata_std_postreset); } +static int vt6421_pata_prereset(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u8 tmp; + + pci_read_config_byte(pdev, PATA_UDMA_TIMING, &tmp); + if (tmp & 0x10) + ap->cbl = ATA_CBL_PATA40; + else + ap->cbl = ATA_CBL_PATA80; + return 0; +} + +static void vt6421_pata_error_handler(struct ata_port *ap) +{ + return ata_bmdma_drive_eh(ap, vt6421_pata_prereset, ata_std_softreset, + NULL, ata_std_postreset); +} + +static int vt6421_sata_prereset(struct ata_port *ap) +{ + ap->cbl = ATA_CBL_SATA; + return 0; +} + +static void vt6421_sata_error_handler(struct ata_port *ap) +{ + return ata_bmdma_drive_eh(ap, vt6421_sata_prereset, ata_std_softreset, + NULL, ata_std_postreset); +} + +static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + static const u8 pio_bits[] = { 0xA8, 0x65, 0x65, 0x31, 0x20 }; + pci_write_config_byte(pdev, PATA_PIO_TIMING, pio_bits[adev->pio_mode - XFER_PIO_0]); +} + +static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev) +{ + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + static const u8 udma_bits[] = { 0xEE, 0xE8, 0xE6, 0xE4, 0xE2, 0xE1, 0xE0, 0xE0 }; + pci_write_config_byte(pdev, PATA_UDMA_TIMING, udma_bits[adev->pio_mode - XFER_UDMA_0]); +} + +static int vt6421_port_start(struct ata_port *ap) +{ + if (ap->port_no == PATA_PORT) { + ap->ops = &vt6421_pata_ops; + ap->mwdma_mask = 0; + ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST; + } + return ata_port_start(ap); +} + static const unsigned int svia_bar_sizes[] = { 8, 4, 8, 4, 16, 256 }; @@ -330,7 +427,7 @@ static struct ata_probe_ent *vt6420_init { struct ata_probe_ent *probe_ent; struct ata_port_info *ppi[2]; - + ppi[0] = ppi[1] = &vt6420_port_info; probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) @@ -511,4 +608,3 @@ static void __exit svia_exit(void) module_init(svia_init); module_exit(svia_exit); - diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 0fa1b89..8d1683e 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -94,8 +94,14 @@ enum { VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \ VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \ VSC_SATA_INT_PHY_CHANGE), + + /* Host private flags (hp_flags) */ + VSC_SATA_HP_FLAG_MSI = (1 << 0), }; +struct vsc_sata_host_priv { + u32 hp_flags; +}; #define is_vsc_sata_int_err(port_idx, int_status) \ (int_status & (VSC_SATA_INT_ERROR << (8 * port_idx))) @@ -118,6 +124,20 @@ static void vsc_sata_scr_write (struct a } +static void vsc_sata_host_stop(struct ata_host *host) +{ + struct vsc_sata_host_priv *hpriv = host->private_data; + struct pci_dev *pdev = to_pci_dev(host->dev); + + if (hpriv->hp_flags & VSC_SATA_HP_FLAG_MSI) + pci_disable_msi(pdev); + else + pci_intx(pdev, 0); + kfree (hpriv); + ata_pci_host_stop(host); +} + + static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl) { void __iomem *mask_addr; @@ -312,7 +332,7 @@ static const struct ata_port_operations .scr_write = vsc_sata_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = ata_pci_host_stop, + .host_stop = vsc_sata_host_stop, }; static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) @@ -341,6 +361,7 @@ static int __devinit vsc_sata_init_one ( { static int printed_version; struct ata_probe_ent *probe_ent = NULL; + struct vsc_sata_host_priv *hpriv; unsigned long base; int pci_dev_busy = 0; void __iomem *mmio_base; @@ -382,6 +403,7 @@ static int __devinit vsc_sata_init_one ( rc = -ENOMEM; goto err_out_regions; } + memset(probe_ent, 0, sizeof(*probe_ent)); probe_ent->dev = pci_dev_to_dev(pdev); INIT_LIST_HEAD(&probe_ent->node); @@ -393,19 +415,33 @@ static int __devinit vsc_sata_init_one ( } base = (unsigned long) mmio_base; + hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) { + rc = -ENOMEM; + goto err_out_iounmap; + } + memset(hpriv, 0, sizeof(*hpriv)); + /* * Due to a bug in the chip, the default cache line size can't be used */ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80); + if (pci_enable_msi(pdev) == 0) { + hpriv->hp_flags |= VSC_SATA_HP_FLAG_MSI; + pci_intx(pdev, 0); + } + else + probe_ent->irq_flags = IRQF_SHARED; + probe_ent->sht = &vsc_sata_sht; probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; probe_ent->port_ops = &vsc_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; - probe_ent->irq_flags = IRQF_SHARED; probe_ent->mmio_base = mmio_base; + probe_ent->private_data = hpriv; /* We don't care much about the PIO/UDMA masks, but the core won't like us * if we don't fill these @@ -432,10 +468,12 @@ static int __devinit vsc_sata_init_one ( /* FIXME: check ata_device_add return value */ ata_device_add(probe_ent); - kfree(probe_ent); + kfree(probe_ent); return 0; +err_out_iounmap: + pci_iounmap(pdev, mmio_base); err_out_free_ent: kfree(probe_ent); err_out_regions: diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ef882a8..2c2c285 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -862,7 +862,7 @@ static void __devinit quirk_sb600_sata(s pci_write_config_byte(pdev, 0xa, 6); pci_write_config_byte(pdev, 0x40, tmp); - pdev->class = 0x010601; + pdev->class = PCI_CLASS_STORAGE_SATA_AHCI; } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_sb600_sata); diff --git a/include/linux/ata.h b/include/linux/ata.h index 1df9416..3a50739 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -44,9 +44,9 @@ enum { ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */ ATA_ID_WORDS = 256, - ATA_ID_SERNO_OFS = 10, - ATA_ID_FW_REV_OFS = 23, - ATA_ID_PROD_OFS = 27, + ATA_ID_SERNO = 10, + ATA_ID_FW_REV = 23, + ATA_ID_PROD = 27, ATA_ID_OLD_PIO_MODES = 51, ATA_ID_FIELD_VALID = 53, ATA_ID_MWDMA_MODES = 63, @@ -58,8 +58,11 @@ enum { ATA_ID_MAJOR_VER = 80, ATA_ID_PIO4 = (1 << 1), + ATA_ID_SERNO_LEN = 20, + ATA_ID_FW_REV_LEN = 8, + ATA_ID_PROD_LEN = 40, + ATA_PCI_CTL_OFS = 2, - ATA_SERNO_LEN = 20, ATA_UDMA0 = (1 << 0), ATA_UDMA1 = ATA_UDMA0 | (1 << 1), ATA_UDMA2 = ATA_UDMA1 | (1 << 2), diff --git a/include/linux/libata.h b/include/linux/libata.h index 22aa69e..9dad9ab 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -35,6 +35,7 @@ #include #include #include #include +#include /* * Define if arch has non-standard setup. This is a _PCI_ standard @@ -109,10 +110,6 @@ static inline u32 ata_msg_init(int dval, #define ATA_TAG_POISON 0xfafbfcfdU /* move to PCI layer? */ -#define PCI_VDEVICE(vendor, device) \ - PCI_VENDOR_ID_##vendor, (device), \ - PCI_ANY_ID, PCI_ANY_ID, 0, 0 - static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) { return &pdev->dev; @@ -308,7 +305,7 @@ enum { * most devices. */ ATA_SPINUP_WAIT = 8000, - + /* Horkage types. May be set by libata or controller on drives (some horkage may be drive/controller pair dependant */ @@ -431,9 +428,6 @@ struct ata_queued_cmd { unsigned int pad_len; - unsigned int nsect; - unsigned int cursect; - unsigned int nbytes; unsigned int curbytes; @@ -503,6 +497,10 @@ struct ata_device { /* error history */ struct ata_ering ering; unsigned int horkage; /* List of broken features */ +#ifdef CONFIG_SATA_ACPI + /* ACPI objects info */ + acpi_handle obj_handle; +#endif }; /* Offset into struct ata_device. Fields above it are maintained @@ -720,7 +718,7 @@ extern int ata_pci_init_one (struct pci_ unsigned int n_ports); extern void ata_pci_remove_one (struct pci_dev *pdev); extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg); -extern void ata_pci_device_do_resume(struct pci_dev *pdev); +extern int __must_check ata_pci_device_do_resume(struct pci_dev *pdev); extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); extern int ata_pci_device_resume(struct pci_dev *pdev); extern int ata_pci_clear_simplex(struct pci_dev *pdev); @@ -1147,8 +1145,7 @@ static inline void ata_qc_reinit(struct qc->dma_dir = DMA_NONE; qc->__sg = NULL; qc->flags = 0; - qc->cursect = qc->cursg = qc->cursg_ofs = 0; - qc->nsect = 0; + qc->cursg = qc->cursg_ofs = 0; qc->nbytes = qc->curbytes = 0; qc->n_elem = 0; qc->err_mask = 0; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f7a416c..9918190 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -15,6 +15,8 @@ #define PCI_CLASS_STORAGE_IDE 0x0101 #define PCI_CLASS_STORAGE_FLOPPY 0x0102 #define PCI_CLASS_STORAGE_IPI 0x0103 #define PCI_CLASS_STORAGE_RAID 0x0104 +#define PCI_CLASS_STORAGE_SATA 0x0106 +#define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 #define PCI_CLASS_STORAGE_SAS 0x0107 #define PCI_CLASS_STORAGE_OTHER 0x0180 @@ -1626,6 +1628,7 @@ #define PCI_VENDOR_ID_ROCKWELL 0x127A #define PCI_VENDOR_ID_ITE 0x1283 #define PCI_DEVICE_ID_ITE_8211 0x8211 #define PCI_DEVICE_ID_ITE_8212 0x8212 +#define PCI_DEVICE_ID_ITE_8213 0x8213 #define PCI_DEVICE_ID_ITE_8872 0x8872 #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886