Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (119 commits)
  [libata] struct pci_dev related cleanups
  libata: use ata_exec_internal() for PMP register access
  libata: implement ATA_PFLAG_RESETTING
  libata: add @timeout to ata_exec_internal[_sg]()
  ahci: fix notification handling
  ahci: clean up PORT_IRQ_BAD_PMP enabling
  ahci: kill leftover from enabling NCQ over PMP
  libata: wrap schedule_timeout_uninterruptible() in loop
  libata: skip suppress reporting if ATA_EHI_QUIET
  libata: clear ehi description after initial host report
  pata_jmicron: match vendor and class code only
  libata: add ST9160821AS / 3.ALD to NCQ blacklist
  pata_acpi: ACPI driver support
  libata-core: Expose gtm methods for driver use
  libata: add HDT722516DLA380 to NCQ blacklist
  libata: blacklist NCQ on Seagate Barracuda ST380817AS
  [libata] Turn on ACPI by default
  libata_scsi: Fix ATAPI transfer lengths
  libata: correct handling of SRST reset sequences
  libata: Integrate ACPI-based PATA/SATA hotplug - version 5
  ...
This commit is contained in:
Linus Torvalds 2007-10-12 16:16:41 -07:00
Родитель 8bd0983e05 2855568b1e
Коммит ab9c232286
82 изменённых файлов: 7872 добавлений и 2070 удалений

Просмотреть файл

@ -865,6 +865,10 @@ and is between 256 and 4096 characters. It is defined in the file
lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip lasi= [HW,SCSI] PARISC LASI driver for the 53c700 chip
Format: addr:<io>,irq:<irq> Format: addr:<io>,irq:<irq>
libata.noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
when set.
Format: <int>
load_ramdisk= [RAM] List of ramdisks to load from floppy load_ramdisk= [RAM] List of ramdisks to load from floppy
See Documentation/ramdisk.txt. See Documentation/ramdisk.txt.
@ -1085,10 +1089,6 @@ and is between 256 and 4096 characters. It is defined in the file
emulation library even if a 387 maths coprocessor emulation library even if a 387 maths coprocessor
is present. is present.
noacpi [LIBATA] Disables use of ACPI in libata suspend/resume
when set.
Format: <int>
noaliencache [MM, NUMA, SLAB] Disables the allocation of alien noaliencache [MM, NUMA, SLAB] Disables the allocation of alien
caches in the slab allocator. Saves per-node memory, caches in the slab allocator. Saves per-node memory,
but will impact performance. but will impact performance.

Просмотреть файл

@ -173,6 +173,15 @@ config SATA_INIC162X
help help
This option enables support for Initio 162x Serial ATA. This option enables support for Initio 162x Serial ATA.
config PATA_ACPI
tristate "ACPI firmware driver for PATA"
depends on ATA_ACPI
help
This option enables an ACPI method driver which drives
motherboard PATA controller interfaces through the ACPI
firmware in the BIOS. This driver can sometimes handle
otherwise unsupported hardware.
config PATA_ALI config PATA_ALI
tristate "ALi PATA support (Experimental)" tristate "ALi PATA support (Experimental)"
depends on PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
@ -192,16 +201,25 @@ config PATA_AMD
If unsure, say N. If unsure, say N.
config PATA_ARTOP config PATA_ARTOP
tristate "ARTOP 6210/6260 PATA support (Experimental)" tristate "ARTOP 6210/6260 PATA support"
depends on PCI && EXPERIMENTAL depends on PCI
help help
This option enables support for ARTOP PATA controllers. This option enables support for ARTOP PATA controllers.
If unsure, say N. If unsure, say N.
config PATA_AT32
tristate "Atmel AVR32 PATA support (Experimental)"
depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL
help
This option enables support for the IDE devices on the
Atmel AT32AP platform.
If unsure, say N.
config PATA_ATIIXP config PATA_ATIIXP
tristate "ATI PATA support (Experimental)" tristate "ATI PATA support"
depends on PCI && EXPERIMENTAL depends on PCI
help help
This option enables support for the ATI ATA interfaces This option enables support for the ATI ATA interfaces
found on the many ATI chipsets. found on the many ATI chipsets.
@ -219,8 +237,8 @@ config PATA_CMD640_PCI
If unsure, say N. If unsure, say N.
config PATA_CMD64X config PATA_CMD64X
tristate "CMD64x PATA support (Very Experimental)" tristate "CMD64x PATA support"
depends on PCI&& EXPERIMENTAL depends on PCI
help help
This option enables support for the CMD64x series chips This option enables support for the CMD64x series chips
except for the CMD640. except for the CMD640.
@ -282,8 +300,8 @@ config ATA_GENERIC
If unsure, say N. If unsure, say N.
config PATA_HPT366 config PATA_HPT366
tristate "HPT 366/368 PATA support (Experimental)" tristate "HPT 366/368 PATA support"
depends on PCI && EXPERIMENTAL depends on PCI
help help
This option enables support for the HPT 366 and 368 This option enables support for the HPT 366 and 368
PATA controllers via the new ATA layer. PATA controllers via the new ATA layer.
@ -432,6 +450,15 @@ config PATA_NS87410
If unsure, say N. If unsure, say N.
config PATA_NS87415
tristate "Nat Semi NS87415 PATA support (Experimental)"
depends on PCI && EXPERIMENTAL
help
This option enables support for the National Semiconductor
NS87415 PCI-IDE controller.
If unsure, say N.
config PATA_OPTI config PATA_OPTI
tristate "OPTI621/6215 PATA support (Very Experimental)" tristate "OPTI621/6215 PATA support (Very Experimental)"
depends on PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
@ -596,4 +623,20 @@ config PATA_SCC
If unsure, say N. If unsure, say N.
config PATA_BF54X
tristate "Blackfin 54x ATAPI support"
depends on BF542 || BF548 || BF549
help
This option enables support for the built-in ATAPI controller on
Blackfin 54x family chips.
If unsure, say N.
config PATA_BF54X_DMA
bool "DMA mode"
depends on PATA_BF54X
default y
help
Enable DMA mode for Blackfin ATAPI controller.
endif # ATA endif # ATA

Просмотреть файл

@ -21,6 +21,7 @@ obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
obj-$(CONFIG_PATA_ALI) += pata_ali.o obj-$(CONFIG_PATA_ALI) += pata_ali.o
obj-$(CONFIG_PATA_AMD) += pata_amd.o obj-$(CONFIG_PATA_AMD) += pata_amd.o
obj-$(CONFIG_PATA_ARTOP) += pata_artop.o obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
obj-$(CONFIG_PATA_AT32) += pata_at32.o
obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o
obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
@ -39,6 +40,7 @@ obj-$(CONFIG_PATA_IT8213) += pata_it8213.o
obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o
obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o
obj-$(CONFIG_PATA_OPTI) += pata_opti.o obj-$(CONFIG_PATA_OPTI) += pata_opti.o
obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
@ -61,12 +63,16 @@ obj-$(CONFIG_PATA_SIS) += pata_sis.o
obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o
obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
# Should be last but two libata driver
obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
# Should be last but one libata driver # Should be last but one libata driver
obj-$(CONFIG_ATA_GENERIC) += ata_generic.o obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver # Should be last libata driver
obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o libata-objs := libata-core.o libata-scsi.o libata-sff.o libata-eh.o \
libata-pmp.o
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o

Просмотреть файл

@ -46,7 +46,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "ahci" #define DRV_NAME "ahci"
#define DRV_VERSION "2.3" #define DRV_VERSION "3.0"
enum { enum {
@ -77,11 +77,10 @@ enum {
RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
board_ahci = 0, board_ahci = 0,
board_ahci_pi = 1, board_ahci_vt8251 = 1,
board_ahci_vt8251 = 2, board_ahci_ign_iferr = 2,
board_ahci_ign_iferr = 3, board_ahci_sb600 = 3,
board_ahci_sb600 = 4, board_ahci_mv = 4,
board_ahci_mv = 5,
/* global controller registers */ /* global controller registers */
HOST_CAP = 0x00, /* host capabilities */ HOST_CAP = 0x00, /* host capabilities */
@ -97,6 +96,7 @@ enum {
/* HOST_CAP bits */ /* HOST_CAP bits */
HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_SSC = (1 << 14), /* Slumber capable */
HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
HOST_CAP_CLO = (1 << 24), /* Command List Override support */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */
HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
HOST_CAP_SNTF = (1 << 29), /* SNotification register */ HOST_CAP_SNTF = (1 << 29), /* SNotification register */
@ -144,7 +144,8 @@ enum {
PORT_IRQ_IF_ERR | PORT_IRQ_IF_ERR |
PORT_IRQ_CONNECT | PORT_IRQ_CONNECT |
PORT_IRQ_PHYRDY | PORT_IRQ_PHYRDY |
PORT_IRQ_UNK_FIS, PORT_IRQ_UNK_FIS |
PORT_IRQ_BAD_PMP,
PORT_IRQ_ERROR = PORT_IRQ_FREEZE | PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
PORT_IRQ_TF_ERR | PORT_IRQ_TF_ERR |
PORT_IRQ_HBUS_DATA_ERR, PORT_IRQ_HBUS_DATA_ERR,
@ -154,6 +155,7 @@ enum {
/* PORT_CMD bits */ /* PORT_CMD bits */
PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
PORT_CMD_PMP = (1 << 17), /* PMP attached */
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
@ -167,19 +169,22 @@ enum {
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
/* hpriv->flags bits */
AHCI_HFLAG_NO_NCQ = (1 << 0),
AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
/* ap->flags bits */ /* ap->flags bits */
AHCI_FLAG_NO_NCQ = (1 << 24), AHCI_FLAG_NO_HOTPLUG = (1 << 24), /* ignore PxSERR.DIAG.N */
AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 25), /* ignore IRQ_IF_ERR */
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_SKIP_D2H_BSY | ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
ATA_FLAG_ACPI_SATA, AHCI_LFLAG_COMMON = ATA_LFLAG_SKIP_D2H_BSY,
}; };
struct ahci_cmd_hdr { struct ahci_cmd_hdr {
@ -198,6 +203,7 @@ struct ahci_sg {
}; };
struct ahci_host_priv { struct ahci_host_priv {
unsigned int flags; /* AHCI_HFLAG_* */
u32 cap; /* cap to use */ u32 cap; /* cap to use */
u32 port_map; /* port map to use */ u32 port_map; /* port map to use */
u32 saved_cap; /* saved initial cap */ u32 saved_cap; /* saved initial cap */
@ -205,6 +211,7 @@ struct ahci_host_priv {
}; };
struct ahci_port_priv { struct ahci_port_priv {
struct ata_link *active_link;
struct ahci_cmd_hdr *cmd_slot; struct ahci_cmd_hdr *cmd_slot;
dma_addr_t cmd_slot_dma; dma_addr_t cmd_slot_dma;
void *cmd_tbl; void *cmd_tbl;
@ -215,6 +222,7 @@ struct ahci_port_priv {
unsigned int ncq_saw_d2h:1; unsigned int ncq_saw_d2h:1;
unsigned int ncq_saw_dmas:1; unsigned int ncq_saw_dmas:1;
unsigned int ncq_saw_sdb:1; unsigned int ncq_saw_sdb:1;
u32 intr_mask; /* interrupts to enable */
}; };
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
@ -229,6 +237,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap); static u8 ahci_check_status(struct ata_port *ap);
static void ahci_freeze(struct ata_port *ap); static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap); static void ahci_thaw(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap); static void ahci_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap); static void ahci_vt8251_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
@ -262,20 +272,17 @@ static struct scsi_host_template ahci_sht = {
}; };
static const struct ata_port_operations ahci_ops = { static const struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status, .check_status = ahci_check_status,
.check_altstatus = ahci_check_status, .check_altstatus = ahci_check_status,
.dev_select = ata_noop_dev_select, .dev_select = ata_noop_dev_select,
.tf_read = ahci_tf_read, .tf_read = ahci_tf_read,
.qc_defer = sata_pmp_qc_defer_cmd_switch,
.qc_prep = ahci_qc_prep, .qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue, .qc_issue = ahci_qc_issue,
.irq_clear = ahci_irq_clear, .irq_clear = ahci_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
.scr_read = ahci_scr_read, .scr_read = ahci_scr_read,
.scr_write = ahci_scr_write, .scr_write = ahci_scr_write,
@ -286,6 +293,9 @@ static const struct ata_port_operations ahci_ops = {
.error_handler = ahci_error_handler, .error_handler = ahci_error_handler,
.post_internal_cmd = ahci_post_internal_cmd, .post_internal_cmd = ahci_post_internal_cmd,
.pmp_attach = ahci_pmp_attach,
.pmp_detach = ahci_pmp_detach,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.port_suspend = ahci_port_suspend, .port_suspend = ahci_port_suspend,
.port_resume = ahci_port_resume, .port_resume = ahci_port_resume,
@ -296,20 +306,17 @@ static const struct ata_port_operations ahci_ops = {
}; };
static const struct ata_port_operations ahci_vt8251_ops = { static const struct ata_port_operations ahci_vt8251_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status, .check_status = ahci_check_status,
.check_altstatus = ahci_check_status, .check_altstatus = ahci_check_status,
.dev_select = ata_noop_dev_select, .dev_select = ata_noop_dev_select,
.tf_read = ahci_tf_read, .tf_read = ahci_tf_read,
.qc_defer = sata_pmp_qc_defer_cmd_switch,
.qc_prep = ahci_qc_prep, .qc_prep = ahci_qc_prep,
.qc_issue = ahci_qc_issue, .qc_issue = ahci_qc_issue,
.irq_clear = ahci_irq_clear, .irq_clear = ahci_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
.scr_read = ahci_scr_read, .scr_read = ahci_scr_read,
.scr_write = ahci_scr_write, .scr_write = ahci_scr_write,
@ -320,6 +327,9 @@ static const struct ata_port_operations ahci_vt8251_ops = {
.error_handler = ahci_vt8251_error_handler, .error_handler = ahci_vt8251_error_handler,
.post_internal_cmd = ahci_post_internal_cmd, .post_internal_cmd = ahci_post_internal_cmd,
.pmp_attach = ahci_pmp_attach,
.pmp_detach = ahci_pmp_detach,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.port_suspend = ahci_port_suspend, .port_suspend = ahci_port_suspend,
.port_resume = ahci_port_resume, .port_resume = ahci_port_resume,
@ -329,53 +339,52 @@ static const struct ata_port_operations ahci_vt8251_ops = {
.port_stop = ahci_port_stop, .port_stop = ahci_port_stop,
}; };
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
static const struct ata_port_info ahci_port_info[] = { static const struct ata_port_info ahci_port_info[] = {
/* board_ahci */ /* board_ahci */
{ {
.flags = AHCI_FLAG_COMMON, .flags = AHCI_FLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */ .link_flags = AHCI_LFLAG_COMMON,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_pi */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
}, },
/* board_ahci_vt8251 */ /* board_ahci_vt8251 */
{ {
.flags = AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
AHCI_FLAG_NO_NCQ, .flags = AHCI_FLAG_COMMON,
.link_flags = AHCI_LFLAG_COMMON | ATA_LFLAG_HRST_TO_RESUME,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops, .port_ops = &ahci_vt8251_ops,
}, },
/* board_ahci_ign_iferr */ /* board_ahci_ign_iferr */
{ {
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR, AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR),
.flags = AHCI_FLAG_COMMON,
.link_flags = AHCI_LFLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
}, },
/* board_ahci_sb600 */ /* board_ahci_sb600 */
{ {
.flags = AHCI_FLAG_COMMON | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL |
AHCI_FLAG_IGN_SERR_INTERNAL | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_PMP),
AHCI_FLAG_32BIT_ONLY, .flags = AHCI_FLAG_COMMON,
.link_flags = AHCI_LFLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
}, },
/* board_ahci_mv */ /* board_ahci_mv */
{ {
.sht = &ahci_sht, AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
AHCI_HFLAG_MV_PATA),
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI | .link_flags = AHCI_LFLAG_COMMON,
AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
AHCI_FLAG_MV_PATA,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops, .port_ops = &ahci_ops,
@ -394,23 +403,25 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */
{ PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */
{ PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */ { PCI_VDEVICE(INTEL, 0x27c6), board_ahci }, /* ICH7-M DH */
{ PCI_VDEVICE(INTEL, 0x2821), board_ahci_pi }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2821), board_ahci }, /* ICH8 */
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci_pi }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* ICH8 */
{ PCI_VDEVICE(INTEL, 0x2824), board_ahci_pi }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */
{ PCI_VDEVICE(INTEL, 0x2829), board_ahci_pi }, /* ICH8M */ { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */
{ PCI_VDEVICE(INTEL, 0x282a), board_ahci_pi }, /* ICH8M */ { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */
{ PCI_VDEVICE(INTEL, 0x2922), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x2923), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x2924), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x2925), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x2927), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x2929), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x292a), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x292b), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x292c), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x292c), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x292f), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x294d), board_ahci_pi }, /* ICH9 */ { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */
{ PCI_VDEVICE(INTEL, 0x294e), board_ahci_pi }, /* ICH9M */ { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@ -474,6 +485,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ab8), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0ab9), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0aba), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abb), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abc), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
/* SiS */ /* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
@ -524,7 +543,6 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
/** /**
* ahci_save_initial_config - Save and fixup initial config values * ahci_save_initial_config - Save and fixup initial config values
* @pdev: target PCI device * @pdev: target PCI device
* @pi: associated ATA port info
* @hpriv: host private area to store config values * @hpriv: host private area to store config values
* *
* Some registers containing configuration info might be setup by * Some registers containing configuration info might be setup by
@ -538,7 +556,6 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
* None. * None.
*/ */
static void ahci_save_initial_config(struct pci_dev *pdev, static void ahci_save_initial_config(struct pci_dev *pdev,
const struct ata_port_info *pi,
struct ahci_host_priv *hpriv) struct ahci_host_priv *hpriv)
{ {
void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
@ -552,26 +569,22 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
/* some chips have errata preventing 64bit use */ /* some chips have errata preventing 64bit use */
if ((cap & HOST_CAP_64) && (pi->flags & AHCI_FLAG_32BIT_ONLY)) { if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
dev_printk(KERN_INFO, &pdev->dev, dev_printk(KERN_INFO, &pdev->dev,
"controller can't do 64bit DMA, forcing 32bit\n"); "controller can't do 64bit DMA, forcing 32bit\n");
cap &= ~HOST_CAP_64; cap &= ~HOST_CAP_64;
} }
if ((cap & HOST_CAP_NCQ) && (pi->flags & AHCI_FLAG_NO_NCQ)) { if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
dev_printk(KERN_INFO, &pdev->dev, dev_printk(KERN_INFO, &pdev->dev,
"controller can't do NCQ, turning off CAP_NCQ\n"); "controller can't do NCQ, turning off CAP_NCQ\n");
cap &= ~HOST_CAP_NCQ; cap &= ~HOST_CAP_NCQ;
} }
/* fixup zero port_map */ if ((cap && HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
if (!port_map) { dev_printk(KERN_INFO, &pdev->dev,
port_map = (1 << ahci_nr_ports(cap)) - 1; "controller can't do PMP, turning off CAP_PMP\n");
dev_printk(KERN_WARNING, &pdev->dev, cap &= ~HOST_CAP_PMP;
"PORTS_IMPL is zero, forcing 0x%x\n", port_map);
/* write the fixed up value to the PI register */
hpriv->saved_port_map = port_map;
} }
/* /*
@ -579,7 +592,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
* is asserted through the standard AHCI port * is asserted through the standard AHCI port
* presence register, as bit 4 (counting from 0) * presence register, as bit 4 (counting from 0)
*/ */
if (pi->flags & AHCI_FLAG_MV_PATA) { if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
dev_printk(KERN_ERR, &pdev->dev, dev_printk(KERN_ERR, &pdev->dev,
"MV_AHCI HACK: port_map %x -> %x\n", "MV_AHCI HACK: port_map %x -> %x\n",
hpriv->port_map, hpriv->port_map,
@ -589,7 +602,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
} }
/* cross check port_map and cap.n_ports */ /* cross check port_map and cap.n_ports */
if (pi->flags & AHCI_FLAG_HONOR_PI) { if (port_map) {
u32 tmp_port_map = port_map; u32 tmp_port_map = port_map;
int n_ports = ahci_nr_ports(cap); int n_ports = ahci_nr_ports(cap);
@ -600,17 +613,26 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
} }
} }
/* Whine if inconsistent. No need to update cap. /* If n_ports and port_map are inconsistent, whine and
* port_map is used to determine number of ports. * clear port_map and let it be generated from n_ports.
*/ */
if (n_ports || tmp_port_map) if (n_ports || tmp_port_map) {
dev_printk(KERN_WARNING, &pdev->dev, dev_printk(KERN_WARNING, &pdev->dev,
"nr_ports (%u) and implemented port map " "nr_ports (%u) and implemented port map "
"(0x%x) don't match\n", "(0x%x) don't match, using nr_ports\n",
ahci_nr_ports(cap), port_map); ahci_nr_ports(cap), port_map);
} else { port_map = 0;
/* fabricate port_map from cap.nr_ports */ }
}
/* fabricate port_map from cap.nr_ports */
if (!port_map) {
port_map = (1 << ahci_nr_ports(cap)) - 1; port_map = (1 << ahci_nr_ports(cap)) - 1;
dev_printk(KERN_WARNING, &pdev->dev,
"forcing PORTS_IMPL to 0x%x\n", port_map);
/* write the fixed up value to the PI register */
hpriv->saved_port_map = port_map;
} }
/* record values to use during operation */ /* record values to use during operation */
@ -836,8 +858,14 @@ static int ahci_reset_controller(struct ata_host *host)
void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
u32 tmp; u32 tmp;
/* global controller reset */ /* we must be in AHCI mode, before using anything
* AHCI-specific, such as HOST_RESET.
*/
tmp = readl(mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL);
if (!(tmp & HOST_AHCI_EN))
writel(tmp | HOST_AHCI_EN, mmio + HOST_CTL);
/* global controller reset */
if ((tmp & HOST_RESET) == 0) { if ((tmp & HOST_RESET) == 0) {
writel(tmp | HOST_RESET, mmio + HOST_CTL); writel(tmp | HOST_RESET, mmio + HOST_CTL);
readl(mmio + HOST_CTL); /* flush */ readl(mmio + HOST_CTL); /* flush */
@ -904,13 +932,14 @@ static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
static void ahci_init_controller(struct ata_host *host) static void ahci_init_controller(struct ata_host *host)
{ {
struct ahci_host_priv *hpriv = host->private_data;
struct pci_dev *pdev = to_pci_dev(host->dev); struct pci_dev *pdev = to_pci_dev(host->dev);
void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
int i; int i;
void __iomem *port_mmio; void __iomem *port_mmio;
u32 tmp; u32 tmp;
if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) { if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
port_mmio = __ahci_port_base(host, 4); port_mmio = __ahci_port_base(host, 4);
writel(0, port_mmio + PORT_IRQ_MASK); writel(0, port_mmio + PORT_IRQ_MASK);
@ -1042,9 +1071,10 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
return 0; return 0;
} }
static int ahci_do_softreset(struct ata_port *ap, unsigned int *class, static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
int pmp, unsigned long deadline) int pmp, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
const char *reason = NULL; const char *reason = NULL;
unsigned long now, msecs; unsigned long now, msecs;
struct ata_taskfile tf; struct ata_taskfile tf;
@ -1052,7 +1082,7 @@ static int ahci_do_softreset(struct ata_port *ap, unsigned int *class,
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (ata_port_offline(ap)) { if (ata_link_offline(link)) {
DPRINTK("PHY reports no device\n"); DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
return 0; return 0;
@ -1061,10 +1091,10 @@ static int ahci_do_softreset(struct ata_port *ap, unsigned int *class,
/* prepare for SRST (AHCI-1.1 10.4.1) */ /* prepare for SRST (AHCI-1.1 10.4.1) */
rc = ahci_kick_engine(ap, 1); rc = ahci_kick_engine(ap, 1);
if (rc) if (rc)
ata_port_printk(ap, KERN_WARNING, ata_link_printk(link, KERN_WARNING,
"failed to reset engine (errno=%d)", rc); "failed to reset engine (errno=%d)", rc);
ata_tf_init(ap->device, &tf); ata_tf_init(link->device, &tf);
/* issue the first D2H Register FIS */ /* issue the first D2H Register FIS */
msecs = 0; msecs = 0;
@ -1109,19 +1139,25 @@ static int ahci_do_softreset(struct ata_port *ap, unsigned int *class,
return 0; return 0;
fail: fail:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
return rc; return rc;
} }
static int ahci_softreset(struct ata_port *ap, unsigned int *class, static int ahci_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
return ahci_do_softreset(ap, class, 0, deadline); int pmp = 0;
if (link->ap->flags & ATA_FLAG_PMP)
pmp = SATA_PMP_CTRL_PORT;
return ahci_do_softreset(link, class, pmp, deadline);
} }
static int ahci_hardreset(struct ata_port *ap, unsigned int *class, static int ahci_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf; struct ata_taskfile tf;
@ -1132,26 +1168,27 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class,
ahci_stop_engine(ap); ahci_stop_engine(ap);
/* clear D2H reception area to properly wait for D2H FIS */ /* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf); ata_tf_init(link->device, &tf);
tf.command = 0x80; tf.command = 0x80;
ata_tf_to_fis(&tf, 0, 0, d2h_fis); ata_tf_to_fis(&tf, 0, 0, d2h_fis);
rc = sata_std_hardreset(ap, class, deadline); rc = sata_std_hardreset(link, class, deadline);
ahci_start_engine(ap); ahci_start_engine(ap);
if (rc == 0 && ata_port_online(ap)) if (rc == 0 && ata_link_online(link))
*class = ahci_dev_classify(ap); *class = ahci_dev_classify(ap);
if (*class == ATA_DEV_UNKNOWN) if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN)
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
return rc; return rc;
} }
static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class, static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
u32 serror; u32 serror;
int rc; int rc;
@ -1159,7 +1196,7 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class,
ahci_stop_engine(ap); ahci_stop_engine(ap);
rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context), rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
deadline); deadline);
/* vt8251 needs SError cleared for the port to operate */ /* vt8251 needs SError cleared for the port to operate */
@ -1176,12 +1213,13 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class,
return rc ?: -EAGAIN; return rc ?: -EAGAIN;
} }
static void ahci_postreset(struct ata_port *ap, unsigned int *class) static void ahci_postreset(struct ata_link *link, unsigned int *class)
{ {
struct ata_port *ap = link->ap;
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
u32 new_tmp, tmp; u32 new_tmp, tmp;
ata_std_postreset(ap, class); ata_std_postreset(link, class);
/* Make sure port's ATAPI bit is set appropriately */ /* Make sure port's ATAPI bit is set appropriately */
new_tmp = tmp = readl(port_mmio + PORT_CMD); new_tmp = tmp = readl(port_mmio + PORT_CMD);
@ -1195,6 +1233,12 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class)
} }
} }
static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
return ahci_do_softreset(link, class, link->pmp, deadline);
}
static u8 ahci_check_status(struct ata_port *ap) static u8 ahci_check_status(struct ata_port *ap)
{ {
void __iomem *mmio = ap->ioaddr.cmd_addr; void __iomem *mmio = ap->ioaddr.cmd_addr;
@ -1253,7 +1297,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
*/ */
cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
ata_tf_to_fis(&qc->tf, 0, 1, cmd_tbl); ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
if (is_atapi) { if (is_atapi) {
memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
@ -1266,7 +1310,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
/* /*
* Fill in command slot information. * Fill in command slot information.
*/ */
opts = cmd_fis_len | n_elem << 16; opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
if (qc->tf.flags & ATA_TFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE; opts |= AHCI_CMD_WRITE;
if (is_atapi) if (is_atapi)
@ -1277,66 +1321,87 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
{ {
struct ahci_host_priv *hpriv = ap->host->private_data;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *host_ehi = &ap->link.eh_info;
unsigned int err_mask = 0, action = 0; struct ata_link *link = NULL;
struct ata_queued_cmd *qc; struct ata_queued_cmd *active_qc;
struct ata_eh_info *active_ehi;
u32 serror; u32 serror;
ata_ehi_clear_desc(ehi); /* determine active link */
ata_port_for_each_link(link, ap)
if (ata_link_active(link))
break;
if (!link)
link = &ap->link;
active_qc = ata_qc_from_tag(ap, link->active_tag);
active_ehi = &link->eh_info;
/* record irq stat */
ata_ehi_clear_desc(host_ehi);
ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
/* AHCI needs SError cleared; otherwise, it might lock up */ /* AHCI needs SError cleared; otherwise, it might lock up */
ahci_scr_read(ap, SCR_ERROR, &serror); ahci_scr_read(ap, SCR_ERROR, &serror);
ahci_scr_write(ap, SCR_ERROR, serror); ahci_scr_write(ap, SCR_ERROR, serror);
host_ehi->serror |= serror;
/* analyze @irq_stat */
ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
/* some controllers set IRQ_IF_ERR on device errors, ignore it */ /* some controllers set IRQ_IF_ERR on device errors, ignore it */
if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
irq_stat &= ~PORT_IRQ_IF_ERR; irq_stat &= ~PORT_IRQ_IF_ERR;
if (irq_stat & PORT_IRQ_TF_ERR) { if (irq_stat & PORT_IRQ_TF_ERR) {
err_mask |= AC_ERR_DEV; /* If qc is active, charge it; otherwise, the active
if (ap->flags & AHCI_FLAG_IGN_SERR_INTERNAL) * link. There's no active qc on NCQ errors. It will
serror &= ~SERR_INTERNAL; * be determined by EH by reading log page 10h.
} */
if (active_qc)
active_qc->err_mask |= AC_ERR_DEV;
else
active_ehi->err_mask |= AC_ERR_DEV;
if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
err_mask |= AC_ERR_HOST_BUS; host_ehi->serror &= ~SERR_INTERNAL;
action |= ATA_EH_SOFTRESET;
}
if (irq_stat & PORT_IRQ_IF_ERR) {
err_mask |= AC_ERR_ATA_BUS;
action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(ehi, "interface fatal error");
}
if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, "%s", irq_stat & PORT_IRQ_CONNECT ?
"connection status changed" : "PHY RDY changed");
} }
if (irq_stat & PORT_IRQ_UNK_FIS) { if (irq_stat & PORT_IRQ_UNK_FIS) {
u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
err_mask |= AC_ERR_HSM; active_ehi->err_mask |= AC_ERR_HSM;
action |= ATA_EH_SOFTRESET; active_ehi->action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(ehi, "unknown FIS %08x %08x %08x %08x", ata_ehi_push_desc(active_ehi,
"unknown FIS %08x %08x %08x %08x" ,
unk[0], unk[1], unk[2], unk[3]); unk[0], unk[1], unk[2], unk[3]);
} }
/* okay, let's hand over to EH */ if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
ehi->serror |= serror; active_ehi->err_mask |= AC_ERR_HSM;
ehi->action |= action; active_ehi->action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(active_ehi, "incorrect PMP");
}
qc = ata_qc_from_tag(ap, ap->active_tag); if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
if (qc) host_ehi->err_mask |= AC_ERR_HOST_BUS;
qc->err_mask |= err_mask; host_ehi->action |= ATA_EH_SOFTRESET;
else ata_ehi_push_desc(host_ehi, "host bus error");
ehi->err_mask |= err_mask; }
if (irq_stat & PORT_IRQ_IF_ERR) {
host_ehi->err_mask |= AC_ERR_ATA_BUS;
host_ehi->action |= ATA_EH_SOFTRESET;
ata_ehi_push_desc(host_ehi, "interface fatal error");
}
if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
ata_ehi_hotplugged(host_ehi);
ata_ehi_push_desc(host_ehi, "%s",
irq_stat & PORT_IRQ_CONNECT ?
"connection status changed" : "PHY RDY changed");
}
/* okay, let's hand over to EH */
if (irq_stat & PORT_IRQ_FREEZE) if (irq_stat & PORT_IRQ_FREEZE)
ata_port_freeze(ap); ata_port_freeze(ap);
@ -1347,25 +1412,64 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
static void ahci_port_intr(struct ata_port *ap) static void ahci_port_intr(struct ata_port *ap)
{ {
void __iomem *port_mmio = ap->ioaddr.cmd_addr; void __iomem *port_mmio = ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
struct ahci_host_priv *hpriv = ap->host->private_data;
int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING);
u32 status, qc_active; u32 status, qc_active;
int rc, known_irq = 0; int rc, known_irq = 0;
status = readl(port_mmio + PORT_IRQ_STAT); status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT);
/* ignore BAD_PMP while resetting */
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;
if (unlikely(status & PORT_IRQ_ERROR)) { if (unlikely(status & PORT_IRQ_ERROR)) {
ahci_error_intr(ap, status); ahci_error_intr(ap, status);
return; return;
} }
if (ap->sactive) if (status & PORT_IRQ_SDB_FIS) {
/* If SNotification is available, leave notification
* handling to sata_async_notification(). If not,
* emulate it by snooping SDB FIS RX area.
*
* Snooping FIS RX area is probably cheaper than
* poking SNotification but some constrollers which
* implement SNotification, ICH9 for example, don't
* store AN SDB FIS into receive area.
*/
if (hpriv->cap & HOST_CAP_SNTF)
sata_async_notification(ap);
else {
/* If the 'N' bit in word 0 of the FIS is set,
* we just received asynchronous notification.
* Tell libata about it.
*/
const __le32 *f = pp->rx_fis + RX_FIS_SDB;
u32 f0 = le32_to_cpu(f[0]);
if (f0 & (1 << 15))
sata_async_notification(ap);
}
}
/* pp->active_link is valid iff any command is in flight */
if (ap->qc_active && pp->active_link->sactive)
qc_active = readl(port_mmio + PORT_SCR_ACT); qc_active = readl(port_mmio + PORT_SCR_ACT);
else else
qc_active = readl(port_mmio + PORT_CMD_ISSUE); qc_active = readl(port_mmio + PORT_CMD_ISSUE);
rc = ata_qc_complete_multiple(ap, qc_active, NULL); rc = ata_qc_complete_multiple(ap, qc_active, NULL);
/* If resetting, spurious or invalid completions are expected,
* return unconditionally.
*/
if (resetting)
return;
if (rc > 0) if (rc > 0)
return; return;
if (rc < 0) { if (rc < 0) {
@ -1380,7 +1484,7 @@ static void ahci_port_intr(struct ata_port *ap)
/* if !NCQ, ignore. No modern ATA device has broken HSM /* if !NCQ, ignore. No modern ATA device has broken HSM
* implementation for non-NCQ commands. * implementation for non-NCQ commands.
*/ */
if (!ap->sactive) if (!ap->link.sactive)
return; return;
if (status & PORT_IRQ_D2H_REG_FIS) { if (status & PORT_IRQ_D2H_REG_FIS) {
@ -1433,7 +1537,7 @@ static void ahci_port_intr(struct ata_port *ap)
if (!known_irq) if (!known_irq)
ata_port_printk(ap, KERN_INFO, "spurious interrupt " ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n", "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n",
status, ap->active_tag, ap->sactive); status, ap->link.active_tag, ap->link.sactive);
} }
static void ahci_irq_clear(struct ata_port *ap) static void ahci_irq_clear(struct ata_port *ap)
@ -1498,6 +1602,13 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
struct ahci_port_priv *pp = ap->private_data;
/* Keep track of the currently active link. It will be used
* in completion path to determine whether NCQ phase is in
* progress.
*/
pp->active_link = qc->dev->link;
if (qc->tf.protocol == ATA_PROT_NCQ) if (qc->tf.protocol == ATA_PROT_NCQ)
writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
@ -1520,6 +1631,7 @@ static void ahci_thaw(struct ata_port *ap)
void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
u32 tmp; u32 tmp;
struct ahci_port_priv *pp = ap->private_data;
/* clear IRQ */ /* clear IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT); tmp = readl(port_mmio + PORT_IRQ_STAT);
@ -1527,7 +1639,7 @@ static void ahci_thaw(struct ata_port *ap)
writel(1 << ap->port_no, mmio + HOST_IRQ_STAT); writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
/* turn IRQ back on */ /* turn IRQ back on */
writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
} }
static void ahci_error_handler(struct ata_port *ap) static void ahci_error_handler(struct ata_port *ap)
@ -1539,8 +1651,10 @@ static void ahci_error_handler(struct ata_port *ap)
} }
/* perform recovery */ /* perform recovery */
ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_hardreset, sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset,
ahci_postreset); ahci_hardreset, ahci_postreset,
sata_pmp_std_prereset, ahci_pmp_softreset,
sata_pmp_std_hardreset, sata_pmp_std_postreset);
} }
static void ahci_vt8251_error_handler(struct ata_port *ap) static void ahci_vt8251_error_handler(struct ata_port *ap)
@ -1565,11 +1679,44 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
ahci_kick_engine(ap, 1); ahci_kick_engine(ap, 1);
} }
static void ahci_pmp_attach(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
struct ahci_port_priv *pp = ap->private_data;
u32 cmd;
cmd = readl(port_mmio + PORT_CMD);
cmd |= PORT_CMD_PMP;
writel(cmd, port_mmio + PORT_CMD);
pp->intr_mask |= PORT_IRQ_BAD_PMP;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
static void ahci_pmp_detach(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
struct ahci_port_priv *pp = ap->private_data;
u32 cmd;
cmd = readl(port_mmio + PORT_CMD);
cmd &= ~PORT_CMD_PMP;
writel(cmd, port_mmio + PORT_CMD);
pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
static int ahci_port_resume(struct ata_port *ap) static int ahci_port_resume(struct ata_port *ap)
{ {
ahci_power_up(ap); ahci_power_up(ap);
ahci_start_port(ap); ahci_start_port(ap);
if (ap->nr_pmp_links)
ahci_pmp_attach(ap);
else
ahci_pmp_detach(ap);
return 0; return 0;
} }
@ -1681,6 +1828,12 @@ static int ahci_port_start(struct ata_port *ap)
pp->cmd_tbl = mem; pp->cmd_tbl = mem;
pp->cmd_tbl_dma = mem_dma; pp->cmd_tbl_dma = mem_dma;
/*
* Save off initial list of interrupts to be enabled.
* This could be changed later
*/
pp->intr_mask = DEF_PORT_IRQ;
ap->private_data = pp; ap->private_data = pp;
/* engage engines, captain */ /* engage engines, captain */
@ -1830,20 +1983,24 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
return rc; return rc;
if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
if (!hpriv) if (!hpriv)
return -ENOMEM; return -ENOMEM;
hpriv->flags |= (unsigned long)pi.private_data;
if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);
/* save initial config */ /* save initial config */
ahci_save_initial_config(pdev, &pi, hpriv); ahci_save_initial_config(pdev, hpriv);
/* prepare host */ /* prepare host */
if (hpriv->cap & HOST_CAP_NCQ) if (hpriv->cap & HOST_CAP_NCQ)
pi.flags |= ATA_FLAG_NCQ; pi.flags |= ATA_FLAG_NCQ;
if (hpriv->cap & HOST_CAP_PMP)
pi.flags |= ATA_FLAG_PMP;
host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
if (!host) if (!host)
return -ENOMEM; return -ENOMEM;
@ -1854,6 +2011,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_port *ap = host->ports[i]; struct ata_port *ap = host->ports[i];
void __iomem *port_mmio = ahci_port_base(ap); void __iomem *port_mmio = ahci_port_base(ap);
ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
ata_port_pbar_desc(ap, AHCI_PCI_BAR,
0x100 + ap->port_no * 0x80, "port");
/* standard SATA port setup */ /* standard SATA port setup */
if (hpriv->port_map & (1 << i)) if (hpriv->port_map & (1 << i))
ap->ioaddr.cmd_addr = port_mmio; ap->ioaddr.cmd_addr = port_mmio;

Просмотреть файл

@ -34,7 +34,7 @@
/** /**
* generic_set_mode - mode setting * generic_set_mode - mode setting
* @ap: interface to set up * @link: link to set up
* @unused: returned device on error * @unused: returned device on error
* *
* Use a non standard set_mode function. We don't want to be tuned. * Use a non standard set_mode function. We don't want to be tuned.
@ -43,24 +43,24 @@
* and respect them. * and respect them.
*/ */
static int generic_set_mode(struct ata_port *ap, struct ata_device **unused) static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
struct ata_port *ap = link->ap;
int dma_enabled = 0; int dma_enabled = 0;
int i; struct ata_device *dev;
/* Bits 5 and 6 indicate if DMA is active on master/slave */ /* Bits 5 and 6 indicate if DMA is active on master/slave */
if (ap->ioaddr.bmdma_addr) if (ap->ioaddr.bmdma_addr)
dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_link_for_each_dev(dev, link) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->dma_mode = XFER_MW_DMA_0; dev->dma_mode = XFER_MW_DMA_0;
/* We do need the right mode information for DMA or PIO /* We do need the right mode information for DMA or PIO
and this comes from the current configuration flags */ and this comes from the current configuration flags */
if (dma_enabled & (1 << (5 + i))) { if (dma_enabled & (1 << (5 + dev->devno))) {
ata_id_to_dma_mode(dev, XFER_MW_DMA_0); ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
dev->flags &= ~ATA_DFLAG_PIO; dev->flags &= ~ATA_DFLAG_PIO;
} else { } else {
@ -95,7 +95,6 @@ static struct scsi_host_template generic_sht = {
static struct ata_port_operations generic_port_ops = { static struct ata_port_operations generic_port_ops = {
.set_mode = generic_set_mode, .set_mode = generic_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -121,9 +120,8 @@ static struct ata_port_operations generic_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int all_generic_ide; /* Set to claim all devices */ static int all_generic_ide; /* Set to claim all devices */

Просмотреть файл

@ -123,7 +123,6 @@ enum {
ich_pata_33 = 1, /* ICH up to UDMA 33 only */ ich_pata_33 = 1, /* ICH up to UDMA 33 only */
ich_pata_66 = 2, /* ICH up to 66 Mhz */ ich_pata_66 = 2, /* ICH up to 66 Mhz */
ich_pata_100 = 3, /* ICH up to UDMA 100 */ ich_pata_100 = 3, /* ICH up to UDMA 100 */
ich_pata_133 = 4, /* ICH up to UDMA 133 */
ich5_sata = 5, ich5_sata = 5,
ich6_sata = 6, ich6_sata = 6,
ich6_sata_ahci = 7, ich6_sata_ahci = 7,
@ -199,7 +198,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
{ 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* Intel ICH5 */ /* Intel ICH5 */
{ 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* C-ICH (i810E2) */ /* C-ICH (i810E2) */
{ 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* ESB (855GME/875P + 6300ESB) UDMA 100 */ /* ESB (855GME/875P + 6300ESB) UDMA 100 */
@ -207,7 +206,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* ICH6 (and 6) (i915) UDMA 100 */ /* ICH6 (and 6) (i915) UDMA 100 */
{ 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* ICH7/7-R (i945, i975) UDMA 100*/ /* ICH7/7-R (i945, i975) UDMA 100*/
{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* ICH8 Mobile PATA Controller */ /* ICH8 Mobile PATA Controller */
{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
@ -290,7 +289,6 @@ static struct scsi_host_template piix_sht = {
}; };
static const struct ata_port_operations piix_pata_ops = { static const struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode, .set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode, .set_dmamode = piix_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -318,13 +316,11 @@ static const struct ata_port_operations piix_pata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations ich_pata_ops = { static const struct ata_port_operations ich_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode, .set_piomode = piix_set_piomode,
.set_dmamode = ich_set_dmamode, .set_dmamode = ich_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -352,14 +348,11 @@ static const struct ata_port_operations ich_pata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations piix_sata_ops = { static const struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -382,7 +375,6 @@ static const struct ata_port_operations piix_sata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -445,15 +437,15 @@ static const struct piix_map_db ich8_map_db = {
}; };
static const struct piix_map_db tolapai_map_db = { static const struct piix_map_db tolapai_map_db = {
.mask = 0x3, .mask = 0x3,
.port_enable = 0x3, .port_enable = 0x3,
.map = { .map = {
/* PM PS SM SS MAP */ /* PM PS SM SS MAP */
{ P0, NA, P1, NA }, /* 00b */ { P0, NA, P1, NA }, /* 00b */
{ RV, RV, RV, RV }, /* 01b */ { RV, RV, RV, RV }, /* 01b */
{ RV, RV, RV, RV }, /* 10b */ { RV, RV, RV, RV }, /* 10b */
{ RV, RV, RV, RV }, { RV, RV, RV, RV },
}, },
}; };
static const struct piix_map_db *piix_map_db_table[] = { static const struct piix_map_db *piix_map_db_table[] = {
@ -466,7 +458,7 @@ static const struct piix_map_db *piix_map_db_table[] = {
}; };
static struct ata_port_info piix_port_info[] = { static struct ata_port_info piix_port_info[] = {
/* piix_pata_33: 0: PIIX4 at 33MHz */ [piix_pata_33] = /* PIIX4 at 33MHz */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS, .flags = PIIX_PATA_FLAGS,
@ -476,7 +468,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_pata_ops, .port_ops = &piix_pata_ops,
}, },
/* ich_pata_33: 1 ICH0 - ICH at 33Mhz*/ [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS, .flags = PIIX_PATA_FLAGS,
@ -485,7 +477,8 @@ static struct ata_port_info piix_port_info[] = {
.udma_mask = ATA_UDMA2, /* UDMA33 */ .udma_mask = ATA_UDMA2, /* UDMA33 */
.port_ops = &ich_pata_ops, .port_ops = &ich_pata_ops,
}, },
/* ich_pata_66: 2 ICH controllers up to 66MHz */
[ich_pata_66] = /* ICH controllers up to 66MHz */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS, .flags = PIIX_PATA_FLAGS,
@ -495,7 +488,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &ich_pata_ops, .port_ops = &ich_pata_ops,
}, },
/* ich_pata_100: 3 */ [ich_pata_100] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
@ -505,17 +498,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &ich_pata_ops, .port_ops = &ich_pata_ops,
}, },
/* ich_pata_133: 4 ICH with full UDMA6 */ [ich5_sata] =
{
.sht = &piix_sht,
.flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
.pio_mask = 0x1f, /* pio 0-4 */
.mwdma_mask = 0x06, /* Check: maybe 0x07 */
.udma_mask = ATA_UDMA6, /* UDMA133 */
.port_ops = &ich_pata_ops,
},
/* ich5_sata: 5 */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS, .flags = PIIX_SATA_FLAGS,
@ -525,7 +508,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
/* ich6_sata: 6 */ [ich6_sata] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
@ -535,7 +518,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
/* ich6_sata_ahci: 7 */ [ich6_sata_ahci] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@ -546,7 +529,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
/* ich6m_sata_ahci: 8 */ [ich6m_sata_ahci] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@ -557,7 +540,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
/* ich8_sata_ahci: 9 */ [ich8_sata_ahci] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@ -568,7 +551,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops, .port_ops = &piix_sata_ops,
}, },
/* piix_pata_mwdma: 10: PIIX3 MWDMA only */ [piix_pata_mwdma] = /* PIIX3 MWDMA only */
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_PATA_FLAGS, .flags = PIIX_PATA_FLAGS,
@ -577,7 +560,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_pata_ops, .port_ops = &piix_pata_ops,
}, },
/* tolapai_sata_ahci: 11: */ [tolapai_sata_ahci] =
{ {
.sht = &piix_sht, .sht = &piix_sht,
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
@ -615,6 +598,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
/* end marker */ /* end marker */
{ 0, } { 0, }
@ -657,19 +641,20 @@ static int ich_pata_cable_detect(struct ata_port *ap)
/** /**
* piix_pata_prereset - prereset for PATA host controller * piix_pata_prereset - prereset for PATA host controller
* @ap: Target port * @link: Target link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* LOCKING: * LOCKING:
* None (inherited from caller). * None (inherited from caller).
*/ */
static int piix_pata_prereset(struct ata_port *ap, unsigned long deadline) static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
static void piix_pata_error_handler(struct ata_port *ap) static void piix_pata_error_handler(struct ata_port *ap)

Просмотреть файл

@ -14,6 +14,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <scsi/scsi_device.h>
#include "libata.h" #include "libata.h"
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
@ -40,11 +41,40 @@ static int is_pci_dev(struct device *dev)
return (dev->bus == &pci_bus_type); return (dev->bus == &pci_bus_type);
} }
static void ata_acpi_associate_sata_port(struct ata_port *ap) /**
* ata_acpi_associate_sata_port - associate SATA port with ACPI objects
* @ap: target SATA port
*
* Look up ACPI objects associated with @ap and initialize acpi_handle
* fields of @ap, the port and devices accordingly.
*
* LOCKING:
* EH context.
*
* RETURNS:
* 0 on success, -errno on failure.
*/
void ata_acpi_associate_sata_port(struct ata_port *ap)
{ {
acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));
ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); if (!ap->nr_pmp_links) {
acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
ap->link.device->acpi_handle =
acpi_get_child(ap->host->acpi_handle, adr);
} else {
struct ata_link *link;
ap->link.device->acpi_handle = NULL;
ata_port_for_each_link(link, ap) {
acpi_integer adr = SATA_ADR(ap->port_no, link->pmp);
link->device->acpi_handle =
acpi_get_child(ap->host->acpi_handle, adr);
}
}
} }
static void ata_acpi_associate_ide_port(struct ata_port *ap) static void ata_acpi_associate_ide_port(struct ata_port *ap)
@ -60,12 +90,53 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
max_devices++; max_devices++;
for (i = 0; i < max_devices; i++) { for (i = 0; i < max_devices; i++) {
struct ata_device *dev = &ap->device[i]; struct ata_device *dev = &ap->link.device[i];
dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
} }
} }
static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
u32 event)
{
char event_string[12];
char *envp[] = { event_string, NULL };
struct ata_eh_info *ehi = &ap->link.eh_info;
if (event == 0 || event == 1) {
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "ACPI event");
ata_ehi_hotplugged(ehi);
ata_port_freeze(ap);
spin_unlock_irqrestore(ap->lock, flags);
}
if (kobj) {
sprintf(event_string, "BAY_EVENT=%d", event);
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
}
}
static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_device *dev = data;
struct kobject *kobj = NULL;
if (dev->sdev)
kobj = &dev->sdev->sdev_gendev.kobj;
ata_acpi_handle_hotplug (dev->link->ap, kobj, event);
}
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event);
}
/** /**
* ata_acpi_associate - associate ATA host with ACPI objects * ata_acpi_associate - associate ATA host with ACPI objects
* @host: target ATA host * @host: target ATA host
@ -81,7 +152,7 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
*/ */
void ata_acpi_associate(struct ata_host *host) void ata_acpi_associate(struct ata_host *host)
{ {
int i; int i, j;
if (!is_pci_dev(host->dev) || libata_noacpi) if (!is_pci_dev(host->dev) || libata_noacpi)
return; return;
@ -97,6 +168,22 @@ void ata_acpi_associate(struct ata_host *host)
ata_acpi_associate_sata_port(ap); ata_acpi_associate_sata_port(ap);
else else
ata_acpi_associate_ide_port(ap); ata_acpi_associate_ide_port(ap);
if (ap->acpi_handle)
acpi_install_notify_handler (ap->acpi_handle,
ACPI_SYSTEM_NOTIFY,
ata_acpi_ap_notify,
ap);
for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
struct ata_device *dev = &ap->link.device[j];
if (dev->acpi_handle)
acpi_install_notify_handler (dev->acpi_handle,
ACPI_SYSTEM_NOTIFY,
ata_acpi_dev_notify,
dev);
}
} }
} }
@ -113,7 +200,7 @@ void ata_acpi_associate(struct ata_host *host)
* RETURNS: * RETURNS:
* 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
*/ */
static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
{ {
struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
union acpi_object *out_obj; union acpi_object *out_obj;
@ -157,6 +244,8 @@ static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(ata_acpi_gtm);
/** /**
* ata_acpi_stm - execute _STM * ata_acpi_stm - execute _STM
* @ap: target ATA port * @ap: target ATA port
@ -170,7 +259,7 @@ static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
* RETURNS: * RETURNS:
* 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
*/ */
static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
{ {
acpi_status status; acpi_status status;
struct acpi_object_list input; struct acpi_object_list input;
@ -182,10 +271,10 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
/* Buffers for id may need byteswapping ? */ /* Buffers for id may need byteswapping ? */
in_params[1].type = ACPI_TYPE_BUFFER; in_params[1].type = ACPI_TYPE_BUFFER;
in_params[1].buffer.length = 512; in_params[1].buffer.length = 512;
in_params[1].buffer.pointer = (u8 *)ap->device[0].id; in_params[1].buffer.pointer = (u8 *)ap->link.device[0].id;
in_params[2].type = ACPI_TYPE_BUFFER; in_params[2].type = ACPI_TYPE_BUFFER;
in_params[2].buffer.length = 512; in_params[2].buffer.length = 512;
in_params[2].buffer.pointer = (u8 *)ap->device[1].id; in_params[2].buffer.pointer = (u8 *)ap->link.device[1].id;
input.count = 3; input.count = 3;
input.pointer = in_params; input.pointer = in_params;
@ -202,6 +291,8 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ata_acpi_stm);
/** /**
* ata_dev_get_GTF - get the drive bootup default taskfile settings * ata_dev_get_GTF - get the drive bootup default taskfile settings
* @dev: target ATA device * @dev: target ATA device
@ -226,7 +317,7 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
void **ptr_to_free) void **ptr_to_free)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
acpi_status status; acpi_status status;
struct acpi_buffer output; struct acpi_buffer output;
union acpi_object *out_obj; union acpi_object *out_obj;
@ -295,6 +386,44 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
return rc; return rc;
} }
/**
* ata_acpi_cbl_80wire - Check for 80 wire cable
* @ap: Port to check
*
* Return 1 if the ACPI mode data for this port indicates the BIOS selected
* an 80wire mode.
*/
int ata_acpi_cbl_80wire(struct ata_port *ap)
{
struct ata_acpi_gtm gtm;
int valid = 0;
/* No _GTM data, no information */
if (ata_acpi_gtm(ap, &gtm) < 0)
return 0;
/* Split timing, DMA enabled */
if ((gtm.flags & 0x11) == 0x11 && gtm.drive[0].dma < 55)
valid |= 1;
if ((gtm.flags & 0x14) == 0x14 && gtm.drive[1].dma < 55)
valid |= 2;
/* Shared timing, DMA enabled */
if ((gtm.flags & 0x11) == 0x01 && gtm.drive[0].dma < 55)
valid |= 1;
if ((gtm.flags & 0x14) == 0x04 && gtm.drive[0].dma < 55)
valid |= 2;
/* Drive check */
if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))
return 1;
if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))
return 1;
return 0;
}
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
/** /**
* taskfile_load_raw - send taskfile registers to host controller * taskfile_load_raw - send taskfile registers to host controller
* @dev: target ATA device * @dev: target ATA device
@ -320,7 +449,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
static int taskfile_load_raw(struct ata_device *dev, static int taskfile_load_raw(struct ata_device *dev,
const struct ata_acpi_gtf *gtf) const struct ata_acpi_gtf *gtf)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
struct ata_taskfile tf, rtf; struct ata_taskfile tf, rtf;
unsigned int err_mask; unsigned int err_mask;
@ -349,7 +478,7 @@ static int taskfile_load_raw(struct ata_device *dev,
tf.lbal, tf.lbam, tf.lbah, tf.device); tf.lbal, tf.lbam, tf.lbah, tf.device);
rtf = tf; rtf = tf;
err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0); err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0);
if (err_mask) { if (err_mask) {
ata_dev_printk(dev, KERN_ERR, ata_dev_printk(dev, KERN_ERR,
"ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed " "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
@ -424,7 +553,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev)
*/ */
static int ata_acpi_push_id(struct ata_device *dev) static int ata_acpi_push_id(struct ata_device *dev)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
int err; int err;
acpi_status status; acpi_status status;
struct acpi_object_list input; struct acpi_object_list input;
@ -508,7 +637,7 @@ int ata_acpi_on_suspend(struct ata_port *ap)
*/ */
void ata_acpi_on_resume(struct ata_port *ap) void ata_acpi_on_resume(struct ata_port *ap)
{ {
int i; struct ata_device *dev;
if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) { if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) {
BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
@ -518,8 +647,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
} }
/* schedule _GTF */ /* schedule _GTF */
for (i = 0; i < ATA_MAX_DEVICES; i++) ata_link_for_each_dev(dev, &ap->link)
ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING; dev->flags |= ATA_DFLAG_ACPI_PENDING;
} }
/** /**
@ -538,8 +667,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
*/ */
int ata_acpi_on_devcfg(struct ata_device *dev) int ata_acpi_on_devcfg(struct ata_device *dev)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
struct ata_eh_context *ehc = &ap->eh_context; struct ata_eh_context *ehc = &ap->link.eh_context;
int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
int rc; int rc;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1191
drivers/ata/libata-pmp.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -71,11 +71,10 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
#define ALL_SUB_MPAGES 0xff #define ALL_SUB_MPAGES 0xff
static const u8 def_rw_recovery_mpage[] = { static const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = {
RW_RECOVERY_MPAGE, RW_RECOVERY_MPAGE,
RW_RECOVERY_MPAGE_LEN - 2, RW_RECOVERY_MPAGE_LEN - 2,
(1 << 7) | /* AWRE, sat-r06 say it shall be 0 */ (1 << 7), /* AWRE */
(1 << 6), /* ARRE (auto read reallocation) */
0, /* read retry count */ 0, /* read retry count */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* write retry count */ 0, /* write retry count */
@ -450,13 +449,8 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
qc->scsicmd = cmd; qc->scsicmd = cmd;
qc->scsidone = done; qc->scsidone = done;
if (cmd->use_sg) { qc->__sg = scsi_sglist(cmd);
qc->__sg = (struct scatterlist *) cmd->request_buffer; qc->n_elem = scsi_sg_count(cmd);
qc->n_elem = cmd->use_sg;
} else if (cmd->request_bufflen) {
qc->__sg = &qc->sgent;
qc->n_elem = 1;
}
} else { } else {
cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
done(cmd); done(cmd);
@ -755,6 +749,13 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
{ {
sdev->use_10_for_rw = 1; sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1; sdev->use_10_for_ms = 1;
/* Schedule policy is determined by ->qc_defer() callback and
* it needs to see every deferred qc. Set dev_blocked to 1 to
* prevent SCSI midlayer from automatically deferring
* requests.
*/
sdev->max_device_blocked = 1;
} }
static void ata_scsi_dev_config(struct scsi_device *sdev, static void ata_scsi_dev_config(struct scsi_device *sdev,
@ -943,6 +944,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
goto invalid_fld; /* LOEJ bit set not supported */ goto invalid_fld; /* LOEJ bit set not supported */
if (((cdb[4] >> 4) & 0xf) != 0) if (((cdb[4] >> 4) & 0xf) != 0)
goto invalid_fld; /* power conditions not supported */ goto invalid_fld; /* power conditions not supported */
if (qc->dev->horkage & ATA_HORKAGE_SKIP_PM) {
/* the device lacks PM support, finish without doing anything */
scmd->result = SAM_STAT_GOOD;
return 1;
}
if (cdb[4] & 0x1) { if (cdb[4] & 0x1) {
tf->nsect = 1; /* 1 sector, lba=0 */ tf->nsect = 1; /* 1 sector, lba=0 */
@ -1368,14 +1376,14 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
case ATA_CMD_SET_FEATURES: case ATA_CMD_SET_FEATURES:
if ((qc->tf.feature == SETFEATURES_WC_ON) || if ((qc->tf.feature == SETFEATURES_WC_ON) ||
(qc->tf.feature == SETFEATURES_WC_OFF)) { (qc->tf.feature == SETFEATURES_WC_OFF)) {
ap->eh_info.action |= ATA_EH_REVALIDATE; ap->link.eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap); ata_port_schedule_eh(ap);
} }
break; break;
case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
case ATA_CMD_SET_MULTI: /* multi_count changed */ case ATA_CMD_SET_MULTI: /* multi_count changed */
ap->eh_info.action |= ATA_EH_REVALIDATE; ap->link.eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap); ata_port_schedule_eh(ap);
break; break;
} }
@ -1421,37 +1429,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
ata_qc_free(qc); ata_qc_free(qc);
} }
/**
* ata_scmd_need_defer - Check whether we need to defer scmd
* @dev: ATA device to which the command is addressed
* @is_io: Is the command IO (and thus possibly NCQ)?
*
* NCQ and non-NCQ commands cannot run together. As upper layer
* only knows the queue depth, we are responsible for maintaining
* exclusion. This function checks whether a new command can be
* issued to @dev.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*
* RETURNS:
* 1 if deferring is needed, 0 otherwise.
*/
static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
{
struct ata_port *ap = dev->ap;
int is_ncq = is_io && ata_ncq_enabled(dev);
if (is_ncq) {
if (!ata_tag_valid(ap->active_tag))
return 0;
} else {
if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
return 0;
}
return 1;
}
/** /**
* ata_scsi_translate - Translate then issue SCSI command to ATA device * ata_scsi_translate - Translate then issue SCSI command to ATA device
* @dev: ATA device to which the command is addressed * @dev: ATA device to which the command is addressed
@ -1483,14 +1460,12 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *), void (*done)(struct scsi_cmnd *),
ata_xlat_func_t xlat_func) ata_xlat_func_t xlat_func)
{ {
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
int is_io = xlat_func == ata_scsi_rw_xlat; int rc;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
if (unlikely(ata_scmd_need_defer(dev, is_io)))
goto defer;
qc = ata_scsi_qc_new(dev, cmd, done); qc = ata_scsi_qc_new(dev, cmd, done);
if (!qc) if (!qc)
goto err_mem; goto err_mem;
@ -1498,17 +1473,13 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
/* data is present; dma-map it */ /* data is present; dma-map it */
if (cmd->sc_data_direction == DMA_FROM_DEVICE || if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
cmd->sc_data_direction == DMA_TO_DEVICE) { cmd->sc_data_direction == DMA_TO_DEVICE) {
if (unlikely(cmd->request_bufflen < 1)) { if (unlikely(scsi_bufflen(cmd) < 1)) {
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
"WARNING: zero len r/w req\n"); "WARNING: zero len r/w req\n");
goto err_did; goto err_did;
} }
if (cmd->use_sg) ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd));
ata_sg_init(qc, cmd->request_buffer, cmd->use_sg);
else
ata_sg_init_one(qc, cmd->request_buffer,
cmd->request_bufflen);
qc->dma_dir = cmd->sc_data_direction; qc->dma_dir = cmd->sc_data_direction;
} }
@ -1518,6 +1489,11 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
if (xlat_func(qc)) if (xlat_func(qc))
goto early_finish; goto early_finish;
if (ap->ops->qc_defer) {
if ((rc = ap->ops->qc_defer(qc)))
goto defer;
}
/* select device, send command to hardware */ /* select device, send command to hardware */
ata_qc_issue(qc); ata_qc_issue(qc);
@ -1539,8 +1515,12 @@ err_mem:
return 0; return 0;
defer: defer:
ata_qc_free(qc);
DPRINTK("EXIT - defer\n"); DPRINTK("EXIT - defer\n");
return SCSI_MLQUEUE_DEVICE_BUSY; if (rc == ATA_DEFER_LINK)
return SCSI_MLQUEUE_DEVICE_BUSY;
else
return SCSI_MLQUEUE_HOST_BUSY;
} }
/** /**
@ -1562,15 +1542,14 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
u8 *buf; u8 *buf;
unsigned int buflen; unsigned int buflen;
if (cmd->use_sg) { struct scatterlist *sg = scsi_sglist(cmd);
struct scatterlist *sg;
sg = (struct scatterlist *) cmd->request_buffer; if (sg) {
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
buflen = sg->length; buflen = sg->length;
} else { } else {
buf = cmd->request_buffer; buf = NULL;
buflen = cmd->request_bufflen; buflen = 0;
} }
*buf_out = buf; *buf_out = buf;
@ -1590,12 +1569,9 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf) static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
{ {
if (cmd->use_sg) { struct scatterlist *sg = scsi_sglist(cmd);
struct scatterlist *sg; if (sg)
sg = (struct scatterlist *) cmd->request_buffer;
kunmap_atomic(buf - sg->offset, KM_IRQ0); kunmap_atomic(buf - sg->offset, KM_IRQ0);
}
} }
/** /**
@ -1816,6 +1792,62 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
return 0; return 0;
} }
/**
* ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
*
* Yields SAT-specified ATA VPD page.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
u8 pbuf[60];
struct ata_taskfile tf;
unsigned int i;
if (!buflen)
return 0;
memset(&pbuf, 0, sizeof(pbuf));
memset(&tf, 0, sizeof(tf));
pbuf[1] = 0x89; /* our page code */
pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
pbuf[3] = (0x238 & 0xff);
memcpy(&pbuf[8], "linux ", 8);
memcpy(&pbuf[16], "libata ", 16);
memcpy(&pbuf[32], DRV_VERSION, 4);
ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
/* we don't store the ATA device signature, so we fake it */
tf.command = ATA_DRDY; /* really, this is Status reg */
tf.lbal = 0x1;
tf.nsect = 0x1;
ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */
pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
pbuf[56] = ATA_CMD_ID_ATA;
i = min(buflen, 60U);
memcpy(rbuf, &pbuf[0], i);
buflen -= i;
if (!buflen)
return 0;
memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
return 0;
}
/** /**
* ata_scsiop_noop - Command handler that simply returns success. * ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
@ -2273,8 +2305,8 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_PKT_DMA; qc->tf.feature |= ATAPI_PKT_DMA;
} else { } else {
qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = (8 * 1024) & 0xff; qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
qc->tf.lbah = (8 * 1024) >> 8; qc->tf.lbah = 0;
} }
qc->nbytes = SCSI_SENSE_BUFFERSIZE; qc->nbytes = SCSI_SENSE_BUFFERSIZE;
@ -2383,6 +2415,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev; struct ata_device *dev = qc->dev;
int using_pio = (dev->flags & ATA_DFLAG_PIO); int using_pio = (dev->flags & ATA_DFLAG_PIO);
int nodata = (scmd->sc_data_direction == DMA_NONE); int nodata = (scmd->sc_data_direction == DMA_NONE);
unsigned int nbytes;
memset(qc->cdb, 0, dev->cdb_len); memset(qc->cdb, 0, dev->cdb_len);
memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len); memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
@ -2396,20 +2429,26 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
} }
qc->tf.command = ATA_CMD_PACKET; qc->tf.command = ATA_CMD_PACKET;
qc->nbytes = scmd->request_bufflen; qc->nbytes = scsi_bufflen(scmd);
/* check whether ATAPI DMA is safe */ /* check whether ATAPI DMA is safe */
if (!using_pio && ata_check_atapi_dma(qc)) if (!using_pio && ata_check_atapi_dma(qc))
using_pio = 1; using_pio = 1;
/* Some controller variants snoop this value for Packet transfers
to do state machine and FIFO management. Thus we want to set it
properly, and for DMA where it is effectively meaningless */
nbytes = min(qc->nbytes, (unsigned int)63 * 1024);
qc->tf.lbam = (nbytes & 0xFF);
qc->tf.lbah = (nbytes >> 8);
if (using_pio || nodata) { if (using_pio || nodata) {
/* no data, or PIO data xfer */ /* no data, or PIO data xfer */
if (nodata) if (nodata)
qc->tf.protocol = ATA_PROT_ATAPI_NODATA; qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
else else
qc->tf.protocol = ATA_PROT_ATAPI; qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = (8 * 1024) & 0xff;
qc->tf.lbah = (8 * 1024) >> 8;
} else { } else {
/* DMA data xfer */ /* DMA data xfer */
qc->tf.protocol = ATA_PROT_ATAPI_DMA; qc->tf.protocol = ATA_PROT_ATAPI_DMA;
@ -2420,24 +2459,42 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_DMADIR; qc->tf.feature |= ATAPI_DMADIR;
} }
/* FIXME: We need to translate 0x05 READ_BLOCK_LIMITS to a MODE_SENSE
as ATAPI tape drives don't get this right otherwise */
return 0; return 0;
} }
static struct ata_device * ata_find_dev(struct ata_port *ap, int id) static struct ata_device * ata_find_dev(struct ata_port *ap, int devno)
{ {
if (likely(id < ATA_MAX_DEVICES)) if (ap->nr_pmp_links == 0) {
return &ap->device[id]; if (likely(devno < ata_link_max_devices(&ap->link)))
return &ap->link.device[devno];
} else {
if (likely(devno < ap->nr_pmp_links))
return &ap->pmp_link[devno].device[0];
}
return NULL; return NULL;
} }
static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap, static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev) const struct scsi_device *scsidev)
{ {
/* skip commands not addressed to targets we simulate */ int devno;
if (unlikely(scsidev->channel || scsidev->lun))
return NULL;
return ata_find_dev(ap, scsidev->id); /* skip commands not addressed to targets we simulate */
if (ap->nr_pmp_links == 0) {
if (unlikely(scsidev->channel || scsidev->lun))
return NULL;
devno = scsidev->id;
} else {
if (unlikely(scsidev->id || scsidev->lun))
return NULL;
devno = scsidev->channel;
}
return ata_find_dev(ap, devno);
} }
/** /**
@ -2458,7 +2515,7 @@ static int ata_scsi_dev_enabled(struct ata_device *dev)
if (unlikely(!ata_dev_enabled(dev))) if (unlikely(!ata_dev_enabled(dev)))
return 0; return 0;
if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) { if (!atapi_enabled || (dev->link->ap->flags & ATA_FLAG_NO_ATAPI)) {
if (unlikely(dev->class == ATA_DEV_ATAPI)) { if (unlikely(dev->class == ATA_DEV_ATAPI)) {
ata_dev_printk(dev, KERN_WARNING, ata_dev_printk(dev, KERN_WARNING,
"WARNING: ATAPI is %s, device ignored.\n", "WARNING: ATAPI is %s, device ignored.\n",
@ -2631,7 +2688,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
case ATA_CMD_WRITE_LONG_ONCE: case ATA_CMD_WRITE_LONG_ONCE:
if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
goto invalid_fld; goto invalid_fld;
qc->sect_size = scmd->request_bufflen; qc->sect_size = scsi_bufflen(scmd);
} }
/* /*
@ -2661,7 +2718,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
* TODO: find out if we need to do more here to * TODO: find out if we need to do more here to
* cover scatter/gather case. * cover scatter/gather case.
*/ */
qc->nbytes = scmd->request_bufflen; qc->nbytes = scsi_bufflen(scmd);
/* request result TF */ /* request result TF */
qc->flags |= ATA_QCFLAG_RESULT_TF; qc->flags |= ATA_QCFLAG_RESULT_TF;
@ -2746,28 +2803,48 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
void (*done)(struct scsi_cmnd *), void (*done)(struct scsi_cmnd *),
struct ata_device *dev) struct ata_device *dev)
{ {
u8 scsi_op = scmd->cmnd[0];
ata_xlat_func_t xlat_func;
int rc = 0; int rc = 0;
if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len)) { if (dev->class == ATA_DEV_ATA) {
DPRINTK("bad CDB len=%u, max=%u\n", if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len))
scmd->cmd_len, dev->cdb_len); goto bad_cdb_len;
scmd->result = DID_ERROR << 16;
done(scmd); xlat_func = ata_get_xlat_func(dev, scsi_op);
return 0; } else {
if (unlikely(!scmd->cmd_len))
goto bad_cdb_len;
xlat_func = NULL;
if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
/* relay SCSI command to ATAPI device */
if (unlikely(scmd->cmd_len > dev->cdb_len))
goto bad_cdb_len;
xlat_func = atapi_xlat;
} else {
/* ATA_16 passthru, treat as an ATA command */
if (unlikely(scmd->cmd_len > 16))
goto bad_cdb_len;
xlat_func = ata_get_xlat_func(dev, scsi_op);
}
} }
if (dev->class == ATA_DEV_ATA) { if (xlat_func)
ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, rc = ata_scsi_translate(dev, scmd, done, xlat_func);
scmd->cmnd[0]); else
ata_scsi_simulate(dev, scmd, done);
if (xlat_func)
rc = ata_scsi_translate(dev, scmd, done, xlat_func);
else
ata_scsi_simulate(dev, scmd, done);
} else
rc = ata_scsi_translate(dev, scmd, done, atapi_xlat);
return rc; return rc;
bad_cdb_len:
DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",
scmd->cmd_len, scsi_op, dev->cdb_len);
scmd->result = DID_ERROR << 16;
done(scmd);
return 0;
} }
/** /**
@ -2835,6 +2912,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
{ {
struct ata_scsi_args args; struct ata_scsi_args args;
const u8 *scsicmd = cmd->cmnd; const u8 *scsicmd = cmd->cmnd;
u8 tmp8;
args.dev = dev; args.dev = dev;
args.id = dev->id; args.id = dev->id;
@ -2842,15 +2920,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
args.done = done; args.done = done;
switch(scsicmd[0]) { switch(scsicmd[0]) {
/* no-op's, complete with success */ /* TODO: worth improving? */
case SYNCHRONIZE_CACHE: case FORMAT_UNIT:
case REZERO_UNIT: ata_scsi_invalid_field(cmd, done);
case SEEK_6:
case SEEK_10:
case TEST_UNIT_READY:
case FORMAT_UNIT: /* FIXME: correct? */
case SEND_DIAGNOSTIC: /* FIXME: correct? */
ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
break; break;
case INQUIRY: case INQUIRY:
@ -2858,14 +2930,23 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
ata_scsi_invalid_field(cmd, done); ata_scsi_invalid_field(cmd, done);
else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */ else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
else if (scsicmd[2] == 0x00) else switch (scsicmd[2]) {
case 0x00:
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
else if (scsicmd[2] == 0x80) break;
case 0x80:
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
else if (scsicmd[2] == 0x83) break;
case 0x83:
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83); ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
else break;
case 0x89:
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
break;
default:
ata_scsi_invalid_field(cmd, done); ata_scsi_invalid_field(cmd, done);
break;
}
break; break;
case MODE_SENSE: case MODE_SENSE:
@ -2893,8 +2974,33 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns); ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
break; break;
/* mandatory commands we haven't implemented yet */
case REQUEST_SENSE: case REQUEST_SENSE:
ata_scsi_set_sense(cmd, 0, 0, 0);
cmd->result = (DRIVER_SENSE << 24);
done(cmd);
break;
/* if we reach this, then writeback caching is disabled,
* turning this into a no-op.
*/
case SYNCHRONIZE_CACHE:
/* fall through */
/* no-op's, complete with success */
case REZERO_UNIT:
case SEEK_6:
case SEEK_10:
case TEST_UNIT_READY:
ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
break;
case SEND_DIAGNOSTIC:
tmp8 = scsicmd[1] & ~(1 << 3);
if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
else
ata_scsi_invalid_field(cmd, done);
break;
/* all other commands */ /* all other commands */
default: default:
@ -2928,6 +3034,13 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
shost->max_channel = 1; shost->max_channel = 1;
shost->max_cmd_len = 16; shost->max_cmd_len = 16;
/* Schedule policy is determined by ->qc_defer()
* callback and it needs to see every deferred qc.
* Set host_blocked to 1 to prevent SCSI midlayer from
* automatically deferring requests.
*/
shost->max_host_blocked = 1;
rc = scsi_add_host(ap->scsi_host, ap->host->dev); rc = scsi_add_host(ap->scsi_host, ap->host->dev);
if (rc) if (rc)
goto err_add; goto err_add;
@ -2951,25 +3064,32 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
{ {
int tries = 5; int tries = 5;
struct ata_device *last_failed_dev = NULL; struct ata_device *last_failed_dev = NULL;
struct ata_link *link;
struct ata_device *dev; struct ata_device *dev;
unsigned int i;
if (ap->flags & ATA_FLAG_DISABLED) if (ap->flags & ATA_FLAG_DISABLED)
return; return;
repeat: repeat:
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_port_for_each_link(link, ap) {
struct scsi_device *sdev; ata_link_for_each_dev(dev, link) {
struct scsi_device *sdev;
int channel = 0, id = 0;
dev = &ap->device[i]; if (!ata_dev_enabled(dev) || dev->sdev)
continue;
if (!ata_dev_enabled(dev) || dev->sdev) if (ata_is_host_link(link))
continue; id = dev->devno;
else
channel = link->pmp;
sdev = __scsi_add_device(ap->scsi_host, 0, i, 0, NULL); sdev = __scsi_add_device(ap->scsi_host, channel, id, 0,
if (!IS_ERR(sdev)) { NULL);
dev->sdev = sdev; if (!IS_ERR(sdev)) {
scsi_device_put(sdev); dev->sdev = sdev;
scsi_device_put(sdev);
}
} }
} }
@ -2977,12 +3097,14 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
* failure occurred, scan would have failed silently. Check * failure occurred, scan would have failed silently. Check
* whether all devices are attached. * whether all devices are attached.
*/ */
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_port_for_each_link(link, ap) {
dev = &ap->device[i]; ata_link_for_each_dev(dev, link) {
if (ata_dev_enabled(dev) && !dev->sdev) if (ata_dev_enabled(dev) && !dev->sdev)
break; goto exit_loop;
}
} }
if (i == ATA_MAX_DEVICES) exit_loop:
if (!link)
return; return;
/* we're missing some SCSI devices */ /* we're missing some SCSI devices */
@ -3049,7 +3171,7 @@ int ata_scsi_offline_dev(struct ata_device *dev)
*/ */
static void ata_scsi_remove_dev(struct ata_device *dev) static void ata_scsi_remove_dev(struct ata_device *dev)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
struct scsi_device *sdev; struct scsi_device *sdev;
unsigned long flags; unsigned long flags;
@ -3096,6 +3218,43 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
} }
} }
static void ata_scsi_handle_link_detach(struct ata_link *link)
{
struct ata_port *ap = link->ap;
struct ata_device *dev;
ata_link_for_each_dev(dev, link) {
unsigned long flags;
if (!(dev->flags & ATA_DFLAG_DETACHED))
continue;
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_DETACHED;
spin_unlock_irqrestore(ap->lock, flags);
ata_scsi_remove_dev(dev);
}
}
/**
* ata_scsi_media_change_notify - send media change event
* @atadev: Pointer to the disk device with media change event
*
* Tell the block layer to send a media change notification
* event.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
void ata_scsi_media_change_notify(struct ata_device *dev)
{
#ifdef OTHER_AN_PATCHES_HAVE_BEEN_APPLIED
if (dev->sdev)
scsi_device_event_notify(dev->sdev, SDEV_MEDIA_CHANGE);
#endif
}
/** /**
* ata_scsi_hotplug - SCSI part of hotplug * ata_scsi_hotplug - SCSI part of hotplug
* @work: Pointer to ATA port to perform SCSI hotplug on * @work: Pointer to ATA port to perform SCSI hotplug on
@ -3121,20 +3280,14 @@ void ata_scsi_hotplug(struct work_struct *work)
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
/* unplug detached devices */ /* Unplug detached devices. We cannot use link iterator here
for (i = 0; i < ATA_MAX_DEVICES; i++) { * because PMP links have to be scanned even if PMP is
struct ata_device *dev = &ap->device[i]; * currently not attached. Iterate manually.
unsigned long flags; */
ata_scsi_handle_link_detach(&ap->link);
if (!(dev->flags & ATA_DFLAG_DETACHED)) if (ap->pmp_link)
continue; for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
ata_scsi_handle_link_detach(&ap->pmp_link[i]);
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_DETACHED;
spin_unlock_irqrestore(ap->lock, flags);
ata_scsi_remove_dev(dev);
}
/* scan for new ones */ /* scan for new ones */
ata_scsi_scan_host(ap, 0); ata_scsi_scan_host(ap, 0);
@ -3163,27 +3316,42 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
{ {
struct ata_port *ap = ata_shost_to_port(shost); struct ata_port *ap = ata_shost_to_port(shost);
unsigned long flags; unsigned long flags;
int rc = 0; int devno, rc = 0;
if (!ap->ops->error_handler) if (!ap->ops->error_handler)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if ((channel != SCAN_WILD_CARD && channel != 0) || if (lun != SCAN_WILD_CARD && lun)
(lun != SCAN_WILD_CARD && lun != 0))
return -EINVAL; return -EINVAL;
if (ap->nr_pmp_links == 0) {
if (channel != SCAN_WILD_CARD && channel)
return -EINVAL;
devno = id;
} else {
if (id != SCAN_WILD_CARD && id)
return -EINVAL;
devno = channel;
}
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
if (id == SCAN_WILD_CARD) { if (devno == SCAN_WILD_CARD) {
ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1; struct ata_link *link;
ap->eh_info.action |= ATA_EH_SOFTRESET;
ata_port_for_each_link(link, ap) {
struct ata_eh_info *ehi = &link->eh_info;
ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
ehi->action |= ATA_EH_SOFTRESET;
}
} else { } else {
struct ata_device *dev = ata_find_dev(ap, id); struct ata_device *dev = ata_find_dev(ap, devno);
if (dev) { if (dev) {
ap->eh_info.probe_mask |= 1 << dev->devno; struct ata_eh_info *ehi = &dev->link->eh_info;
ap->eh_info.action |= ATA_EH_SOFTRESET; ehi->probe_mask |= 1 << dev->devno;
ap->eh_info.flags |= ATA_EHI_RESUME_LINK; ehi->action |= ATA_EH_SOFTRESET;
ehi->flags |= ATA_EHI_RESUME_LINK;
} else } else
rc = -EINVAL; rc = -EINVAL;
} }
@ -3214,24 +3382,26 @@ void ata_scsi_dev_rescan(struct work_struct *work)
{ {
struct ata_port *ap = struct ata_port *ap =
container_of(work, struct ata_port, scsi_rescan_task); container_of(work, struct ata_port, scsi_rescan_task);
struct ata_link *link;
struct ata_device *dev;
unsigned long flags; unsigned long flags;
unsigned int i;
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_port_for_each_link(link, ap) {
struct ata_device *dev = &ap->device[i]; ata_link_for_each_dev(dev, link) {
struct scsi_device *sdev = dev->sdev; struct scsi_device *sdev = dev->sdev;
if (!ata_dev_enabled(dev) || !sdev) if (!ata_dev_enabled(dev) || !sdev)
continue; continue;
if (scsi_device_get(sdev)) if (scsi_device_get(sdev))
continue; continue;
spin_unlock_irqrestore(ap->lock, flags); spin_unlock_irqrestore(ap->lock, flags);
scsi_rescan_device(&(sdev->sdev_gendev)); scsi_rescan_device(&(sdev->sdev_gendev));
scsi_device_put(sdev); scsi_device_put(sdev);
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
}
} }
spin_unlock_irqrestore(ap->lock, flags); spin_unlock_irqrestore(ap->lock, flags);
@ -3359,7 +3529,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
{ {
ata_scsi_sdev_config(sdev); ata_scsi_sdev_config(sdev);
ata_scsi_dev_config(sdev, ap->device); ata_scsi_dev_config(sdev, ap->link.device);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ata_sas_slave_configure); EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
@ -3382,8 +3552,8 @@ int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
ata_scsi_dump_cdb(ap, cmd); ata_scsi_dump_cdb(ap, cmd);
if (likely(ata_scsi_dev_enabled(ap->device))) if (likely(ata_scsi_dev_enabled(ap->link.device)))
rc = __ata_scsi_queuecmd(cmd, done, ap->device); rc = __ata_scsi_queuecmd(cmd, done, ap->link.device);
else { else {
cmd->result = (DID_BAD_TARGET << 16); cmd->result = (DID_BAD_TARGET << 16);
done(cmd); done(cmd);

Просмотреть файл

@ -64,46 +64,6 @@ u8 ata_irq_on(struct ata_port *ap)
return tmp; return tmp;
} }
u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; }
/**
* ata_irq_ack - Acknowledge a device interrupt.
* @ap: Port on which interrupts are enabled.
*
* Wait up to 10 ms for legacy IDE device to become idle (BUSY
* or BUSY+DRQ clear). Obtain dma status and port status from
* device. Clear the interrupt. Return port status.
*
* LOCKING:
*/
u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
u8 host_stat = 0, post_stat = 0, status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
if (ap->ioaddr.bmdma_addr) {
/* get controller status; clear intr, err bits */
host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
return status;
}
u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq) { return 0; }
/** /**
* ata_tf_load - send taskfile registers to host controller * ata_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent * @ap: Port to which output is sent
@ -445,7 +405,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
unsigned long flags; unsigned long flags;
int thaw = 0; int thaw = 0;
qc = __ata_qc_from_tag(ap, ap->active_tag); qc = __ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
qc = NULL; qc = NULL;
@ -500,7 +460,7 @@ void ata_bmdma_error_handler(struct ata_port *ap)
ata_reset_fn_t hardreset; ata_reset_fn_t hardreset;
hardreset = NULL; hardreset = NULL;
if (sata_scr_valid(ap)) if (sata_scr_valid(&ap->link))
hardreset = sata_std_hardreset; hardreset = sata_std_hardreset;
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
@ -607,6 +567,9 @@ int ata_pci_init_bmdma(struct ata_host *host)
if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) && if ((!(ap->flags & ATA_FLAG_IGN_SIMPLEX)) &&
(ioread8(bmdma + 2) & 0x80)) (ioread8(bmdma + 2) & 0x80))
host->flags |= ATA_HOST_SIMPLEX; host->flags |= ATA_HOST_SIMPLEX;
ata_port_desc(ap, "bmdma 0x%llx",
(unsigned long long)pci_resource_start(pdev, 4) + 8 * i);
} }
return 0; return 0;
@ -674,6 +637,10 @@ int ata_pci_init_sff_host(struct ata_host *host)
((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS); ((unsigned long)iomap[base + 1] | ATA_PCI_CTL_OFS);
ata_std_ports(&ap->ioaddr); ata_std_ports(&ap->ioaddr);
ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
(unsigned long long)pci_resource_start(pdev, base),
(unsigned long long)pci_resource_start(pdev, base + 1));
mask |= 1 << i; mask |= 1 << i;
} }
@ -844,24 +811,30 @@ int ata_pci_init_one(struct pci_dev *pdev,
IRQF_SHARED, DRV_NAME, host); IRQF_SHARED, DRV_NAME, host);
if (rc) if (rc)
goto err_out; goto err_out;
host->irq = pdev->irq;
ata_port_desc(host->ports[0], "irq %d", pdev->irq);
ata_port_desc(host->ports[1], "irq %d", pdev->irq);
} else { } else {
if (!ata_port_is_dummy(host->ports[0])) { if (!ata_port_is_dummy(host->ports[0])) {
host->irq = ATA_PRIMARY_IRQ(pdev); rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
rc = devm_request_irq(dev, host->irq,
pi->port_ops->irq_handler, pi->port_ops->irq_handler,
IRQF_SHARED, DRV_NAME, host); IRQF_SHARED, DRV_NAME, host);
if (rc) if (rc)
goto err_out; goto err_out;
ata_port_desc(host->ports[0], "irq %d",
ATA_PRIMARY_IRQ(pdev));
} }
if (!ata_port_is_dummy(host->ports[1])) { if (!ata_port_is_dummy(host->ports[1])) {
host->irq2 = ATA_SECONDARY_IRQ(pdev); rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
rc = devm_request_irq(dev, host->irq2,
pi->port_ops->irq_handler, pi->port_ops->irq_handler,
IRQF_SHARED, DRV_NAME, host); IRQF_SHARED, DRV_NAME, host);
if (rc) if (rc)
goto err_out; goto err_out;
ata_port_desc(host->ports[1], "irq %d",
ATA_SECONDARY_IRQ(pdev));
} }
} }
@ -909,7 +882,7 @@ unsigned long ata_pci_default_filter(struct ata_device *adev, unsigned long xfer
/* Filter out DMA modes if the device has been configured by /* Filter out DMA modes if the device has been configured by
the BIOS as PIO only */ the BIOS as PIO only */
if (adev->ap->ioaddr.bmdma_addr == 0) if (adev->link->ap->ioaddr.bmdma_addr == 0)
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
return xfer_mask; return xfer_mask;
} }

Просмотреть файл

@ -29,6 +29,7 @@
#define __LIBATA_H__ #define __LIBATA_H__
#define DRV_NAME "libata" #define DRV_NAME "libata"
#define DRV_VERSION "3.00" /* must be exactly four chars */
struct ata_scsi_args { struct ata_scsi_args {
struct ata_device *dev; struct ata_device *dev;
@ -56,6 +57,7 @@ extern unsigned int ata_print_id;
extern struct workqueue_struct *ata_aux_wq; extern struct workqueue_struct *ata_aux_wq;
extern int atapi_enabled; extern int atapi_enabled;
extern int atapi_dmadir; extern int atapi_dmadir;
extern int atapi_passthru16;
extern int libata_fua; extern int libata_fua;
extern int libata_noacpi; extern int libata_noacpi;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
@ -67,21 +69,23 @@ extern void ata_dev_disable(struct ata_device *dev);
extern void ata_port_flush_task(struct ata_port *ap); extern void ata_port_flush_task(struct ata_port *ap);
extern unsigned ata_exec_internal(struct ata_device *dev, extern unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb, struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen); int dma_dir, void *buf, unsigned int buflen,
unsigned long timeout);
extern unsigned ata_exec_internal_sg(struct ata_device *dev, extern unsigned ata_exec_internal_sg(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb, struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, struct scatterlist *sg, int dma_dir, struct scatterlist *sg,
unsigned int n_elem); unsigned int n_elem, unsigned long timeout);
extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
unsigned int flags, u16 *id); unsigned int flags, u16 *id);
extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags); extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags);
extern int ata_dev_configure(struct ata_device *dev); extern int ata_dev_configure(struct ata_device *dev);
extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_down_spd_limit(struct ata_link *link);
extern int sata_set_spd_needed(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_link *link);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
extern void ata_sg_clean(struct ata_queued_cmd *qc); extern void ata_sg_clean(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc);
extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc);
@ -92,17 +96,21 @@ extern void ata_dev_select(struct ata_port *ap, unsigned int device,
extern void swap_buf_le16(u16 *buf, unsigned int buf_words); extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
extern int ata_flush_cache(struct ata_device *dev); extern int ata_flush_cache(struct ata_device *dev);
extern void ata_dev_init(struct ata_device *dev); extern void ata_dev_init(struct ata_device *dev);
extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
extern int sata_link_init_spd(struct ata_link *link);
extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct ata_port *ata_port_alloc(struct ata_host *host); extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */ /* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
extern void ata_acpi_associate(struct ata_host *host); extern void ata_acpi_associate(struct ata_host *host);
extern int ata_acpi_on_suspend(struct ata_port *ap); extern int ata_acpi_on_suspend(struct ata_port *ap);
extern void ata_acpi_on_resume(struct ata_port *ap); extern void ata_acpi_on_resume(struct ata_port *ap);
extern int ata_acpi_on_devcfg(struct ata_device *adev); extern int ata_acpi_on_devcfg(struct ata_device *adev);
#else #else
static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
static inline void ata_acpi_associate(struct ata_host *host) { } static inline void ata_acpi_associate(struct ata_host *host) { }
static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
static inline void ata_acpi_on_resume(struct ata_port *ap) { } static inline void ata_acpi_on_resume(struct ata_port *ap) { }
@ -114,6 +122,7 @@ extern int ata_scsi_add_hosts(struct ata_host *host,
struct scsi_host_template *sht); struct scsi_host_template *sht);
extern void ata_scsi_scan_host(struct ata_port *ap, int sync); extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
extern int ata_scsi_offline_dev(struct ata_device *dev); extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_media_change_notify(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_scsi_hotplug(struct work_struct *work);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen); unsigned int buflen);
@ -147,12 +156,32 @@ extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work); extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap); extern int ata_bus_probe(struct ata_port *ap);
/* libata-pmp.c */
extern int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *val);
extern int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val);
extern int sata_pmp_attach(struct ata_device *dev);
/* libata-eh.c */ /* libata-eh.c */
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_port_wait_eh(struct ata_port *ap);
extern void ata_eh_fastdrain_timerfn(unsigned long arg); extern void ata_eh_fastdrain_timerfn(unsigned long arg);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
extern void ata_eh_detach_dev(struct ata_device *dev);
extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action);
extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
unsigned int action);
extern void ata_eh_autopsy(struct ata_port *ap);
extern void ata_eh_report(struct ata_port *ap);
extern int ata_eh_reset(struct ata_link *link, int classify,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset,
struct ata_link **r_failed_disk);
extern void ata_eh_finish(struct ata_port *ap);
/* libata-sff.c */ /* libata-sff.c */
extern u8 ata_irq_on(struct ata_port *ap); extern u8 ata_irq_on(struct ata_port *ap);

395
drivers/ata/pata_acpi.c Normal file
Просмотреть файл

@ -0,0 +1,395 @@
/*
* ACPI PATA driver
*
* (c) 2007 Red Hat <alan@redhat.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <acpi/acpi_bus.h>
#include <acpi/acnames.h>
#include <acpi/acnamesp.h>
#include <acpi/acparser.h>
#include <acpi/acexcep.h>
#include <acpi/acmacros.h>
#include <acpi/actypes.h>
#include <linux/libata.h>
#include <linux/ata.h>
#define DRV_NAME "pata_acpi"
#define DRV_VERSION "0.2.3"
struct pata_acpi {
struct ata_acpi_gtm gtm;
void *last;
unsigned long mask[2];
};
/**
* pacpi_pre_reset - check for 40/80 pin
* @ap: Port
* @deadline: deadline jiffies for the operation
*
* Perform the PATA port setup we need.
*/
static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
{
struct ata_port *ap = link->ap;
struct pata_acpi *acpi = ap->private_data;
if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
return -ENODEV;
return ata_std_prereset(link, deadline);
}
/**
* pacpi_cable_detect - cable type detection
* @ap: port to detect
*
* Perform device specific cable detection
*/
static int pacpi_cable_detect(struct ata_port *ap)
{
struct pata_acpi *acpi = ap->private_data;
if ((acpi->mask[0] | acpi->mask[1]) & (0xF8 << ATA_SHIFT_UDMA))
return ATA_CBL_PATA80;
else
return ATA_CBL_PATA40;
}
/**
* pacpi_error_handler - Setup and error handler
* @ap: Port to handle
*
* LOCKING:
* None (inherited from caller).
*/
static void pacpi_error_handler(struct ata_port *ap)
{
return ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset,
NULL, ata_std_postreset);
}
/* Welcome to ACPI, bring a bucket */
static const unsigned int pio_cycle[7] = {
600, 383, 240, 180, 120, 100, 80
};
static const unsigned int mwdma_cycle[5] = {
480, 150, 120, 100, 80
};
static const unsigned int udma_cycle[7] = {
120, 80, 60, 45, 30, 20, 15
};
/**
* pacpi_discover_modes - filter non ACPI modes
* @adev: ATA device
* @mask: proposed modes
*
* Try the modes available and see which ones the ACPI method will
* set up sensibly. From this we get a mask of ACPI modes we can use
*/
static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
{
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
int i;
u32 t;
unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
struct ata_acpi_gtm probe;
probe = acpi->gtm;
/* We always use the 0 slot for crap hardware */
if (!(probe.flags & 0x10))
unit = 0;
ata_acpi_gtm(ap, &probe);
/* Start by scanning for PIO modes */
for (i = 0; i < 7; i++) {
t = probe.drive[unit].pio;
if (t <= pio_cycle[i]) {
mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
break;
}
}
/* See if we have MWDMA or UDMA data. We don't bother with MWDMA
if UDMA is availabe as this means the BIOS set UDMA and our
error changedown if it works is UDMA to PIO anyway */
if (probe.flags & (1 << (2 * unit))) {
/* MWDMA */
for (i = 0; i < 5; i++) {
t = probe.drive[unit].dma;
if (t <= mwdma_cycle[i]) {
mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
break;
}
}
} else {
/* UDMA */
for (i = 0; i < 7; i++) {
t = probe.drive[unit].dma;
if (t <= udma_cycle[i]) {
mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
break;
}
}
}
if (mask & (0xF8 << ATA_SHIFT_UDMA))
ap->cbl = ATA_CBL_PATA80;
return mask;
}
/**
* pacpi_mode_filter - mode filter for ACPI
* @adev: device
* @mask: mask of valid modes
*
* Filter the valid mode list according to our own specific rules, in
* this case the list of discovered valid modes obtained by ACPI probing
*/
static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
{
struct pata_acpi *acpi = adev->link->ap->private_data;
return ata_pci_default_filter(adev, mask & acpi->mask[adev->devno]);
}
/**
* pacpi_set_piomode - set initial PIO mode data
* @ap: ATA interface
* @adev: ATA device
*/
static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
if(!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
ata_acpi_stm(ap, &acpi->gtm);
/* See what mode we actually got */
ata_acpi_gtm(ap, &acpi->gtm);
}
/**
* pacpi_set_dmamode - set initial DMA mode data
* @ap: ATA interface
* @adev: ATA device
*/
static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
int unit = adev->devno;
struct pata_acpi *acpi = ap->private_data;
if(!(acpi->gtm.flags & 0x10))
unit = 0;
/* Now stuff the nS values into the structure */
if (adev->dma_mode >= XFER_UDMA_0) {
acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
acpi->gtm.flags |= (1 << (2 * unit));
} else {
acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
acpi->gtm.flags &= ~(1 << (2 * unit));
}
ata_acpi_stm(ap, &acpi->gtm);
/* See what mode we actually got */
ata_acpi_gtm(ap, &acpi->gtm);
}
/**
* pacpi_qc_issue_prot - command issue
* @qc: command pending
*
* Called when the libata layer is about to issue a command. We wrap
* this interface so that we can load the correct ATA timings if
* neccessary.
*/
static unsigned int pacpi_qc_issue_prot(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ata_device *adev = qc->dev;
struct pata_acpi *acpi = ap->private_data;
if (acpi->gtm.flags & 0x10)
return ata_qc_issue_prot(qc);
if (adev != acpi->last) {
pacpi_set_piomode(ap, adev);
if (adev->dma_mode)
pacpi_set_dmamode(ap, adev);
acpi->last = adev;
}
return ata_qc_issue_prot(qc);
}
/**
* pacpi_port_start - port setup
* @ap: ATA port being set up
*
* Use the port_start hook to maintain private control structures
*/
static int pacpi_port_start(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct pata_acpi *acpi;
int ret;
if (ap->acpi_handle == NULL)
return -ENODEV;
acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL);
if (ap->private_data == NULL)
return -ENOMEM;
acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
ret = ata_sff_port_start(ap);
if (ret < 0)
return ret;
return ret;
}
static struct scsi_host_template pacpi_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 = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
/* Use standard CHS mapping rules */
.bios_param = ata_std_bios_param,
};
static const struct ata_port_operations pacpi_ops = {
.set_piomode = pacpi_set_piomode,
.set_dmamode = pacpi_set_dmamode,
.mode_filter = pacpi_mode_filter,
/* Task file is PCI ATA format, use helpers */
.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 = pacpi_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = pacpi_cable_detect,
/* BMDMA handling is PCI ATA format, use helpers */
.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 = pacpi_qc_issue_prot,
.data_xfer = ata_data_xfer,
/* Timeout handling */
.irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on,
/* Generic PATA PCI ATA helpers */
.port_start = pacpi_port_start,
};
/**
* pacpi_init_one - Register ACPI ATA PCI device with kernel services
* @pdev: PCI device to register
* @ent: Entry in pacpi_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 pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &pacpi_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x7f,
.port_ops = &pacpi_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
return ata_pci_init_one(pdev, ppi);
}
static const struct pci_device_id pacpi_pci_tbl[] = {
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
{ } /* terminate list */
};
static struct pci_driver pacpi_pci_driver = {
.name = DRV_NAME,
.id_table = pacpi_pci_tbl,
.probe = pacpi_init_one,
.remove = ata_pci_remove_one,
.suspend = ata_pci_device_suspend,
.resume = ata_pci_device_resume,
};
static int __init pacpi_init(void)
{
return pci_register_driver(&pacpi_pci_driver);
}
static void __exit pacpi_exit(void)
{
pci_unregister_driver(&pacpi_pci_driver);
}
module_init(pacpi_init);
module_exit(pacpi_exit);
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pacpi_pci_tbl);
MODULE_VERSION(DRV_VERSION);

Просмотреть файл

@ -305,7 +305,6 @@ static struct scsi_host_template ali_sht = {
*/ */
static struct ata_port_operations ali_early_port_ops = { static struct ata_port_operations ali_early_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = ali_set_piomode, .set_piomode = ali_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -327,9 +326,8 @@ static struct ata_port_operations ali_early_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
@ -337,8 +335,6 @@ static struct ata_port_operations ali_early_port_ops = {
* detect * detect
*/ */
static struct ata_port_operations ali_20_port_ops = { static struct ata_port_operations ali_20_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = ali_set_piomode, .set_piomode = ali_set_piomode,
.set_dmamode = ali_set_dmamode, .set_dmamode = ali_set_dmamode,
.mode_filter = ali_20_filter, .mode_filter = ali_20_filter,
@ -369,16 +365,14 @@ static struct ata_port_operations ali_20_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
* Port operations for DMA capable ALi with cable detect * Port operations for DMA capable ALi with cable detect
*/ */
static struct ata_port_operations ali_c2_port_ops = { static struct ata_port_operations ali_c2_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = ali_set_piomode, .set_piomode = ali_set_piomode,
.set_dmamode = ali_set_dmamode, .set_dmamode = ali_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -408,16 +402,14 @@ static struct ata_port_operations ali_c2_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
* Port operations for DMA capable ALi with cable detect and LBA48 * Port operations for DMA capable ALi with cable detect and LBA48
*/ */
static struct ata_port_operations ali_c5_port_ops = { static struct ata_port_operations ali_c5_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = ali_set_piomode, .set_piomode = ali_set_piomode,
.set_dmamode = ali_set_dmamode, .set_dmamode = ali_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -446,9 +438,8 @@ static struct ata_port_operations ali_c5_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -119,27 +119,28 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
} }
/** /**
* amd_probe_init - perform reset handling * amd_pre_reset - perform reset handling
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Reset sequence checking enable bits to see which ports are * Reset sequence checking enable bits to see which ports are
* active. * active.
*/ */
static int amd_pre_reset(struct ata_port *ap, unsigned long deadline) static int amd_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits amd_enable_bits[] = { static const struct pci_bits amd_enable_bits[] = {
{ 0x40, 1, 0x02, 0x02 }, { 0x40, 1, 0x02, 0x02 },
{ 0x40, 1, 0x01, 0x01 } { 0x40, 1, 0x01, 0x01 }
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
static void amd_error_handler(struct ata_port *ap) static void amd_error_handler(struct ata_port *ap)
@ -221,25 +222,26 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
/** /**
* nv_probe_init - cable detection * nv_probe_init - cable detection
* @ap: ATA port * @lin: ATA link
* *
* Perform cable detection. The BIOS stores this in PCI config * Perform cable detection. The BIOS stores this in PCI config
* space for us. * space for us.
*/ */
static int nv_pre_reset(struct ata_port *ap, unsigned long deadline) static int nv_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits nv_enable_bits[] = { static const struct pci_bits nv_enable_bits[] = {
{ 0x50, 1, 0x02, 0x02 }, { 0x50, 1, 0x02, 0x02 },
{ 0x50, 1, 0x01, 0x01 } { 0x50, 1, 0x01, 0x01 }
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &nv_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
static void nv_error_handler(struct ata_port *ap) static void nv_error_handler(struct ata_port *ap)
@ -268,6 +270,9 @@ static int nv_cable_detect(struct ata_port *ap)
pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma); pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400) if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
cbl = ATA_CBL_PATA80; cbl = ATA_CBL_PATA80;
/* And a triple check across suspend/resume with ACPI around */
if (ata_acpi_cbl_80wire(ap))
cbl = ATA_CBL_PATA80;
return cbl; return cbl;
} }
@ -327,7 +332,6 @@ static struct scsi_host_template amd_sht = {
}; };
static struct ata_port_operations amd33_port_ops = { static struct ata_port_operations amd33_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = amd33_set_piomode, .set_piomode = amd33_set_piomode,
.set_dmamode = amd33_set_dmamode, .set_dmamode = amd33_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -356,13 +360,11 @@ static struct ata_port_operations amd33_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations amd66_port_ops = { static struct ata_port_operations amd66_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = amd66_set_piomode, .set_piomode = amd66_set_piomode,
.set_dmamode = amd66_set_dmamode, .set_dmamode = amd66_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -391,13 +393,11 @@ static struct ata_port_operations amd66_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations amd100_port_ops = { static struct ata_port_operations amd100_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = amd100_set_piomode, .set_piomode = amd100_set_piomode,
.set_dmamode = amd100_set_dmamode, .set_dmamode = amd100_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -426,13 +426,11 @@ static struct ata_port_operations amd100_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations amd133_port_ops = { static struct ata_port_operations amd133_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = amd133_set_piomode, .set_piomode = amd133_set_piomode,
.set_dmamode = amd133_set_dmamode, .set_dmamode = amd133_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -461,13 +459,11 @@ static struct ata_port_operations amd133_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations nv100_port_ops = { static struct ata_port_operations nv100_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = nv100_set_piomode, .set_piomode = nv100_set_piomode,
.set_dmamode = nv100_set_dmamode, .set_dmamode = nv100_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -496,13 +492,11 @@ static struct ata_port_operations nv100_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations nv133_port_ops = { static struct ata_port_operations nv133_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = nv133_set_piomode, .set_piomode = nv133_set_piomode,
.set_dmamode = nv133_set_dmamode, .set_dmamode = nv133_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -531,9 +525,8 @@ static struct ata_port_operations nv133_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)

Просмотреть файл

@ -40,8 +40,9 @@
static int clock = 0; static int clock = 0;
static int artop6210_pre_reset(struct ata_port *ap, unsigned long deadline) static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
const struct pci_bits artop_enable_bits[] = { const struct pci_bits artop_enable_bits[] = {
{ 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
@ -51,7 +52,7 @@ static int artop6210_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -71,27 +72,28 @@ static void artop6210_error_handler(struct ata_port *ap)
/** /**
* artop6260_pre_reset - check for 40/80 pin * artop6260_pre_reset - check for 40/80 pin
* @ap: Port * @link: link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* The ARTOP hardware reports the cable detect bits in register 0x49. * The ARTOP hardware reports the cable detect bits in register 0x49.
* Nothing complicated needed here. * Nothing complicated needed here.
*/ */
static int artop6260_pre_reset(struct ata_port *ap, unsigned long deadline) static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits artop_enable_bits[] = { static const struct pci_bits artop_enable_bits[] = {
{ 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */
{ 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */ { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
/* Odd numbered device ids are the units with enable bits (the -R cards) */ /* Odd numbered device ids are the units with enable bits (the -R cards) */
if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -330,7 +332,6 @@ static struct scsi_host_template artop_sht = {
}; };
static const struct ata_port_operations artop6210_ops = { static const struct ata_port_operations artop6210_ops = {
.port_disable = ata_port_disable,
.set_piomode = artop6210_set_piomode, .set_piomode = artop6210_set_piomode,
.set_dmamode = artop6210_set_dmamode, .set_dmamode = artop6210_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -359,13 +360,11 @@ static const struct ata_port_operations artop6210_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations artop6260_ops = { static const struct ata_port_operations artop6260_ops = {
.port_disable = ata_port_disable,
.set_piomode = artop6260_set_piomode, .set_piomode = artop6260_set_piomode,
.set_dmamode = artop6260_set_dmamode, .set_dmamode = artop6260_set_dmamode,
@ -392,9 +391,8 @@ static const struct ata_port_operations artop6260_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

441
drivers/ata/pata_at32.c Normal file
Просмотреть файл

@ -0,0 +1,441 @@
/*
* AVR32 SMC/CFC PATA Driver
*
* Copyright (C) 2007 Atmel Norway
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <scsi/scsi_host.h>
#include <linux/ata.h>
#include <linux/libata.h>
#include <linux/err.h>
#include <linux/io.h>
#include <asm/arch/board.h>
#include <asm/arch/smc.h>
#define DRV_NAME "pata_at32"
#define DRV_VERSION "0.0.2"
/*
* CompactFlash controller memory layout relative to the base address:
*
* Attribute memory: 0000 0000 -> 003f ffff
* Common memory: 0040 0000 -> 007f ffff
* I/O memory: 0080 0000 -> 00bf ffff
* True IDE Mode: 00c0 0000 -> 00df ffff
* Alt IDE Mode: 00e0 0000 -> 00ff ffff
*
* Only True IDE and Alt True IDE mode are needed for this driver.
*
* True IDE mode => CS0 = 0, CS1 = 1 (cmd, error, stat, etc)
* Alt True IDE mode => CS0 = 1, CS1 = 0 (ctl, alt_stat)
*/
#define CF_IDE_OFFSET 0x00c00000
#define CF_ALT_IDE_OFFSET 0x00e00000
#define CF_RES_SIZE 2048
/*
* Define DEBUG_BUS if you are doing debugging of your own EBI -> PATA
* adaptor with a logic analyzer or similar.
*/
#undef DEBUG_BUS
/*
* ATA PIO modes
*
* Name | Mb/s | Min cycle time | Mask
* --------+-------+----------------+--------
* Mode 0 | 3.3 | 600 ns | 0x01
* Mode 1 | 5.2 | 383 ns | 0x03
* Mode 2 | 8.3 | 240 ns | 0x07
* Mode 3 | 11.1 | 180 ns | 0x0f
* Mode 4 | 16.7 | 120 ns | 0x1f
*/
#define PIO_MASK (0x1f)
/*
* Struct containing private information about device.
*/
struct at32_ide_info {
unsigned int irq;
struct resource res_ide;
struct resource res_alt;
void __iomem *ide_addr;
void __iomem *alt_addr;
unsigned int cs;
struct smc_config smc;
};
/*
* Setup SMC for the given ATA timing.
*/
static int pata_at32_setup_timing(struct device *dev,
struct at32_ide_info *info,
const struct ata_timing *timing)
{
/* These two values are found through testing */
const int min_recover = 25;
const int ncs_hold = 15;
struct smc_config *smc = &info->smc;
int active;
int recover;
/* Total cycle time */
smc->read_cycle = timing->cyc8b;
/* DIOR <= CFIOR timings */
smc->nrd_setup = timing->setup;
smc->nrd_pulse = timing->act8b;
/* Compute recover, extend total cycle if needed */
active = smc->nrd_setup + smc->nrd_pulse;
recover = smc->read_cycle - active;
if (recover < min_recover) {
smc->read_cycle = active + min_recover;
recover = min_recover;
}
/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
smc->ncs_read_setup = 0;
smc->ncs_read_pulse = active + ncs_hold;
/* Write timings same as read timings */
smc->write_cycle = smc->read_cycle;
smc->nwe_setup = smc->nrd_setup;
smc->nwe_pulse = smc->nrd_pulse;
smc->ncs_write_setup = smc->ncs_read_setup;
smc->ncs_write_pulse = smc->ncs_read_pulse;
/* Do some debugging output */
dev_dbg(dev, "SMC: C=%d S=%d P=%d R=%d NCSS=%d NCSP=%d NCSR=%d\n",
smc->read_cycle, smc->nrd_setup, smc->nrd_pulse,
recover, smc->ncs_read_setup, smc->ncs_read_pulse,
smc->read_cycle - smc->ncs_read_pulse);
/* Finally, configure the SMC */
return smc_set_configuration(info->cs, smc);
}
/*
* Procedures for libATA.
*/
static void pata_at32_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
struct ata_timing timing;
struct at32_ide_info *info = ap->host->private_data;
int ret;
/* Compute ATA timing */
ret = ata_timing_compute(adev, adev->pio_mode, &timing, 1000, 0);
if (ret) {
dev_warn(ap->dev, "Failed to compute ATA timing %d\n", ret);
return;
}
/* Setup SMC to ATA timing */
ret = pata_at32_setup_timing(ap->dev, info, &timing);
if (ret) {
dev_warn(ap->dev, "Failed to setup ATA timing %d\n", ret);
return;
}
}
static void pata_at32_irq_clear(struct ata_port *ap)
{
/* No DMA controller yet */
}
static struct scsi_host_template at32_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 = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
static struct ata_port_operations at32_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = pata_at32_set_piomode,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
.dev_select = ata_std_dev_select,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
.irq_clear = pata_at32_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_sff_port_start,
};
static int __init pata_at32_init_one(struct device *dev,
struct at32_ide_info *info)
{
struct ata_host *host;
struct ata_port *ap;
host = ata_host_alloc(dev, 1);
if (!host)
return -ENOMEM;
ap = host->ports[0];
/* Setup ATA bindings */
ap->ops = &at32_port_ops;
ap->pio_mask = PIO_MASK;
ap->flags = ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS
| ATA_FLAG_PIO_POLLING;
/*
* Since all 8-bit taskfile transfers has to go on the lower
* byte of the data bus and there is a bug in the SMC that
* makes it impossible to alter the bus width during runtime,
* we need to hardwire the address signals as follows:
*
* A_IDE(2:0) <= A_EBI(3:1)
*
* This makes all addresses on the EBI even, thus all data
* will be on the lower byte of the data bus. All addresses
* used by libATA need to be altered according to this.
*/
ap->ioaddr.altstatus_addr = info->alt_addr + (0x06 << 1);
ap->ioaddr.ctl_addr = info->alt_addr + (0x06 << 1);
ap->ioaddr.data_addr = info->ide_addr + (ATA_REG_DATA << 1);
ap->ioaddr.error_addr = info->ide_addr + (ATA_REG_ERR << 1);
ap->ioaddr.feature_addr = info->ide_addr + (ATA_REG_FEATURE << 1);
ap->ioaddr.nsect_addr = info->ide_addr + (ATA_REG_NSECT << 1);
ap->ioaddr.lbal_addr = info->ide_addr + (ATA_REG_LBAL << 1);
ap->ioaddr.lbam_addr = info->ide_addr + (ATA_REG_LBAM << 1);
ap->ioaddr.lbah_addr = info->ide_addr + (ATA_REG_LBAH << 1);
ap->ioaddr.device_addr = info->ide_addr + (ATA_REG_DEVICE << 1);
ap->ioaddr.status_addr = info->ide_addr + (ATA_REG_STATUS << 1);
ap->ioaddr.command_addr = info->ide_addr + (ATA_REG_CMD << 1);
/* Set info as private data of ATA host */
host->private_data = info;
/* Register ATA device and return */
return ata_host_activate(host, info->irq, ata_interrupt,
IRQF_SHARED | IRQF_TRIGGER_RISING,
&at32_sht);
}
/*
* This function may come in handy for people analyzing their own
* EBI -> PATA adaptors.
*/
#ifdef DEBUG_BUS
static void __init pata_at32_debug_bus(struct device *dev,
struct at32_ide_info *info)
{
const int d1 = 0xff;
const int d2 = 0x00;
int i;
/* Write 8-bit values (registers) */
iowrite8(d1, info->alt_addr + (0x06 << 1));
iowrite8(d2, info->alt_addr + (0x06 << 1));
for (i = 0; i < 8; i++) {
iowrite8(d1, info->ide_addr + (i << 1));
iowrite8(d2, info->ide_addr + (i << 1));
}
/* Write 16 bit values (data) */
iowrite16(d1, info->ide_addr);
iowrite16(d1 << 8, info->ide_addr);
iowrite16(d1, info->ide_addr);
iowrite16(d1 << 8, info->ide_addr);
}
#endif
static int __init pata_at32_probe(struct platform_device *pdev)
{
const struct ata_timing initial_timing =
{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
struct device *dev = &pdev->dev;
struct at32_ide_info *info;
struct ide_platform_data *board = pdev->dev.platform_data;
struct resource *res;
int irq;
int ret;
if (!board)
return -ENXIO;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
/* Retrive IRQ */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
/* Setup struct containing private infomation */
info = kzalloc(sizeof(struct at32_ide_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(struct at32_ide_info));
info->irq = irq;
info->cs = board->cs;
/* Request memory resources */
info->res_ide.start = res->start + CF_IDE_OFFSET;
info->res_ide.end = info->res_ide.start + CF_RES_SIZE - 1;
info->res_ide.name = "ide";
info->res_ide.flags = IORESOURCE_MEM;
ret = request_resource(res, &info->res_ide);
if (ret)
goto err_req_res_ide;
info->res_alt.start = res->start + CF_ALT_IDE_OFFSET;
info->res_alt.end = info->res_alt.start + CF_RES_SIZE - 1;
info->res_alt.name = "alt";
info->res_alt.flags = IORESOURCE_MEM;
ret = request_resource(res, &info->res_alt);
if (ret)
goto err_req_res_alt;
/* Setup non-timing elements of SMC */
info->smc.bus_width = 2; /* 16 bit data bus */
info->smc.nrd_controlled = 1; /* Sample data on rising edge of NRD */
info->smc.nwe_controlled = 0; /* Drive data on falling edge of NCS */
info->smc.nwait_mode = 3; /* NWAIT is in READY mode */
info->smc.byte_write = 0; /* Byte select access type */
info->smc.tdf_mode = 0; /* TDF optimization disabled */
info->smc.tdf_cycles = 0; /* No TDF wait cycles */
/* Setup ATA timing */
ret = pata_at32_setup_timing(dev, info, &initial_timing);
if (ret)
goto err_setup_timing;
/* Setup ATA addresses */
ret = -ENOMEM;
info->ide_addr = devm_ioremap(dev, info->res_ide.start, 16);
info->alt_addr = devm_ioremap(dev, info->res_alt.start, 16);
if (!info->ide_addr || !info->alt_addr)
goto err_ioremap;
#ifdef DEBUG_BUS
pata_at32_debug_bus(dev, info);
#endif
/* Register ATA device */
ret = pata_at32_init_one(dev, info);
if (ret)
goto err_ata_device;
return 0;
err_ata_device:
err_ioremap:
err_setup_timing:
release_resource(&info->res_alt);
err_req_res_alt:
release_resource(&info->res_ide);
err_req_res_ide:
kfree(info);
return ret;
}
static int __exit pata_at32_remove(struct platform_device *pdev)
{
struct ata_host *host = platform_get_drvdata(pdev);
struct at32_ide_info *info;
if (!host)
return 0;
info = host->private_data;
ata_host_detach(host);
if (!info)
return 0;
release_resource(&info->res_ide);
release_resource(&info->res_alt);
kfree(info);
return 0;
}
static struct platform_driver pata_at32_driver = {
.remove = __exit_p(pata_at32_remove),
.driver = {
.name = "at32_ide",
.owner = THIS_MODULE,
},
};
static int __init pata_at32_init(void)
{
return platform_driver_probe(&pata_at32_driver, pata_at32_probe);
}
static void __exit pata_at32_exit(void)
{
platform_driver_unregister(&pata_at32_driver);
}
module_init(pata_at32_init);
module_exit(pata_at32_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AVR32 SMC/CFC PATA Driver");
MODULE_AUTHOR("Kristoffer Nyborg Gregertsen <kngregertsen@norway.atmel.com>");
MODULE_VERSION(DRV_VERSION);

Просмотреть файл

@ -33,8 +33,9 @@ enum {
ATIIXP_IDE_UDMA_MODE = 0x56 ATIIXP_IDE_UDMA_MODE = 0x56
}; };
static int atiixp_pre_reset(struct ata_port *ap, unsigned long deadline) static int atiixp_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
static const struct pci_bits atiixp_enable_bits[] = { static const struct pci_bits atiixp_enable_bits[] = {
{ 0x48, 1, 0x01, 0x00 }, { 0x48, 1, 0x01, 0x00 },
{ 0x48, 1, 0x08, 0x00 } { 0x48, 1, 0x08, 0x00 }
@ -44,7 +45,7 @@ static int atiixp_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
static void atiixp_error_handler(struct ata_port *ap) static void atiixp_error_handler(struct ata_port *ap)
@ -172,6 +173,9 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* *
* When DMA begins we need to ensure that the UDMA control * When DMA begins we need to ensure that the UDMA control
* register for the channel is correctly set. * register for the channel is correctly set.
*
* Note: The host lock held by the libata layer protects
* us from two channels both trying to set DMA bits at once
*/ */
static void atiixp_bmdma_start(struct ata_queued_cmd *qc) static void atiixp_bmdma_start(struct ata_queued_cmd *qc)
@ -198,6 +202,9 @@ static void atiixp_bmdma_start(struct ata_queued_cmd *qc)
* *
* DMA has completed. Clear the UDMA flag as the next operations will * DMA has completed. Clear the UDMA flag as the next operations will
* be PIO ones not UDMA data transfer. * be PIO ones not UDMA data transfer.
*
* Note: The host lock held by the libata layer protects
* us from two channels both trying to set DMA bits at once
*/ */
static void atiixp_bmdma_stop(struct ata_queued_cmd *qc) static void atiixp_bmdma_stop(struct ata_queued_cmd *qc)
@ -232,7 +239,6 @@ static struct scsi_host_template atiixp_sht = {
}; };
static struct ata_port_operations atiixp_port_ops = { static struct ata_port_operations atiixp_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = atiixp_set_piomode, .set_piomode = atiixp_set_piomode,
.set_dmamode = atiixp_set_dmamode, .set_dmamode = atiixp_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -261,9 +267,8 @@ static struct ata_port_operations atiixp_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)

1627
drivers/ata/pata_bf54x.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -153,7 +153,7 @@ static int cmd640_port_start(struct ata_port *ap)
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct cmd640_reg *timing; struct cmd640_reg *timing;
int ret = ata_port_start(ap); int ret = ata_sff_port_start(ap);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -184,7 +184,6 @@ static struct scsi_host_template cmd640_sht = {
}; };
static struct ata_port_operations cmd640_port_ops = { static struct ata_port_operations cmd640_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cmd640_set_piomode, .set_piomode = cmd640_set_piomode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -213,7 +212,6 @@ static struct ata_port_operations cmd640_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = cmd640_port_start, .port_start = cmd640_port_start,
}; };

Просмотреть файл

@ -31,7 +31,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "pata_cmd64x" #define DRV_NAME "pata_cmd64x"
#define DRV_VERSION "0.2.4" #define DRV_VERSION "0.2.5"
/* /*
* CMD64x specific registers definition. * CMD64x specific registers definition.
@ -88,14 +88,15 @@ static int cmd648_cable_detect(struct ata_port *ap)
} }
/** /**
* cmd64x_set_piomode - set initial PIO mode data * cmd64x_set_piomode - set PIO and MWDMA timing
* @ap: ATA interface * @ap: ATA interface
* @adev: ATA device * @adev: ATA device
* @mode: mode
* *
* Called to do the PIO mode setup. * Called to do the PIO and MWDMA mode setup.
*/ */
static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev) static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 mode)
{ {
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct ata_timing t; struct ata_timing t;
@ -117,8 +118,9 @@ static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
int arttim = arttim_port[ap->port_no][adev->devno]; int arttim = arttim_port[ap->port_no][adev->devno];
int drwtim = drwtim_port[ap->port_no][adev->devno]; int drwtim = drwtim_port[ap->port_no][adev->devno];
/* ata_timing_compute is smart and will produce timings for MWDMA
if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) { that don't violate the drives PIO capabilities. */
if (ata_timing_compute(adev, mode, &t, T, 0) < 0) {
printk(KERN_ERR DRV_NAME ": mode computation failed.\n"); printk(KERN_ERR DRV_NAME ": mode computation failed.\n");
return; return;
} }
@ -167,6 +169,20 @@ static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, drwtim, (t.active << 4) | t.recover); pci_write_config_byte(pdev, drwtim, (t.active << 4) | t.recover);
} }
/**
* cmd64x_set_piomode - set initial PIO mode data
* @ap: ATA interface
* @adev: ATA device
*
* Used when configuring the devices ot set the PIO timings. All the
* actual work is done by the PIO/MWDMA setting helper
*/
static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
cmd64x_set_timing(ap, adev, adev->pio_mode);
}
/** /**
* cmd64x_set_dmamode - set initial DMA mode data * cmd64x_set_dmamode - set initial DMA mode data
* @ap: ATA interface * @ap: ATA interface
@ -180,9 +196,6 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
static const u8 udma_data[] = { static const u8 udma_data[] = {
0x30, 0x20, 0x10, 0x20, 0x10, 0x00 0x30, 0x20, 0x10, 0x20, 0x10, 0x00
}; };
static const u8 mwdma_data[] = {
0x30, 0x20, 0x10
};
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u8 regU, regD; u8 regU, regD;
@ -208,8 +221,10 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
regU |= 1 << adev->devno; /* UDMA on */ regU |= 1 << adev->devno; /* UDMA on */
if (adev->dma_mode > 2) /* 15nS timing */ if (adev->dma_mode > 2) /* 15nS timing */
regU |= 4 << adev->devno; regU |= 4 << adev->devno;
} else } else {
regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift; regU &= ~ (1 << adev->devno); /* UDMA off */
cmd64x_set_timing(ap, adev, adev->dma_mode);
}
regD |= 0x20 << adev->devno; regD |= 0x20 << adev->devno;
@ -269,7 +284,6 @@ static struct scsi_host_template cmd64x_sht = {
}; };
static struct ata_port_operations cmd64x_port_ops = { static struct ata_port_operations cmd64x_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cmd64x_set_piomode, .set_piomode = cmd64x_set_piomode,
.set_dmamode = cmd64x_set_dmamode, .set_dmamode = cmd64x_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -298,13 +312,11 @@ static struct ata_port_operations cmd64x_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static struct ata_port_operations cmd646r1_port_ops = { static struct ata_port_operations cmd646r1_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cmd64x_set_piomode, .set_piomode = cmd64x_set_piomode,
.set_dmamode = cmd64x_set_dmamode, .set_dmamode = cmd64x_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -333,13 +345,11 @@ static struct ata_port_operations cmd646r1_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static struct ata_port_operations cmd648_port_ops = { static struct ata_port_operations cmd648_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cmd64x_set_piomode, .set_piomode = cmd64x_set_piomode,
.set_dmamode = cmd64x_set_dmamode, .set_dmamode = cmd64x_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -368,7 +378,6 @@ static struct ata_port_operations cmd648_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };

Просмотреть файл

@ -158,7 +158,6 @@ static struct scsi_host_template cs5520_sht = {
}; };
static struct ata_port_operations cs5520_port_ops = { static struct ata_port_operations cs5520_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cs5520_set_piomode, .set_piomode = cs5520_set_piomode,
.set_dmamode = cs5520_set_dmamode, .set_dmamode = cs5520_set_dmamode,
@ -184,13 +183,14 @@ static struct ata_port_operations cs5520_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
static const unsigned int cmd_port[] = { 0x1F0, 0x170 };
static const unsigned int ctl_port[] = { 0x3F6, 0x376 };
struct ata_port_info pi = { struct ata_port_info pi = {
.flags = ATA_FLAG_SLAVE_POSS, .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, .pio_mask = 0x1f,
@ -244,10 +244,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
} }
/* Map IO ports and initialize host accordingly */ /* Map IO ports and initialize host accordingly */
iomap[0] = devm_ioport_map(&pdev->dev, 0x1F0, 8); iomap[0] = devm_ioport_map(&pdev->dev, cmd_port[0], 8);
iomap[1] = devm_ioport_map(&pdev->dev, 0x3F6, 1); iomap[1] = devm_ioport_map(&pdev->dev, ctl_port[0], 1);
iomap[2] = devm_ioport_map(&pdev->dev, 0x170, 8); iomap[2] = devm_ioport_map(&pdev->dev, cmd_port[1], 8);
iomap[3] = devm_ioport_map(&pdev->dev, 0x376, 1); iomap[3] = devm_ioport_map(&pdev->dev, ctl_port[1], 1);
iomap[4] = pcim_iomap(pdev, 2, 0); iomap[4] = pcim_iomap(pdev, 2, 0);
if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4]) if (!iomap[0] || !iomap[1] || !iomap[2] || !iomap[3] || !iomap[4])
@ -260,6 +260,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
ioaddr->bmdma_addr = iomap[4]; ioaddr->bmdma_addr = iomap[4];
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_desc(host->ports[0],
"cmd 0x%x ctl 0x%x", cmd_port[0], ctl_port[0]);
ata_port_pbar_desc(host->ports[0], 4, 0, "bmdma");
ioaddr = &host->ports[1]->ioaddr; ioaddr = &host->ports[1]->ioaddr;
ioaddr->cmd_addr = iomap[2]; ioaddr->cmd_addr = iomap[2];
ioaddr->ctl_addr = iomap[3]; ioaddr->ctl_addr = iomap[3];
@ -267,6 +271,10 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
ioaddr->bmdma_addr = iomap[4] + 8; ioaddr->bmdma_addr = iomap[4] + 8;
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_desc(host->ports[1],
"cmd 0x%x ctl 0x%x", cmd_port[1], ctl_port[1]);
ata_port_pbar_desc(host->ports[1], 4, 8, "bmdma");
/* activate the host */ /* activate the host */
pci_set_master(pdev); pci_set_master(pdev);
rc = ata_host_start(host); rc = ata_host_start(host);
@ -285,33 +293,12 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
if (rc) if (rc)
return rc; return rc;
if (i == 0) ata_port_desc(ap, "irq %d", irq[i]);
host->irq = irq[0];
else
host->irq2 = irq[1];
} }
return ata_host_register(host, &cs5520_sht); return ata_host_register(host, &cs5520_sht);
} }
/**
* cs5520_remove_one - device unload
* @pdev: PCI device being removed
*
* Handle an unplug/unload event for a PCI device. Unload the
* PCI driver but do not use the default handler as we manage
* resources ourself and *MUST NOT* disable the device as it has
* other functions.
*/
static void __devexit cs5520_remove_one(struct pci_dev *pdev)
{
struct device *dev = pci_dev_to_dev(pdev);
struct ata_host *host = dev_get_drvdata(dev);
ata_host_detach(host);
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
/** /**
* cs5520_reinit_one - device resume * cs5520_reinit_one - device resume
@ -368,7 +355,7 @@ static struct pci_driver cs5520_pci_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.id_table = pata_cs5520, .id_table = pata_cs5520,
.probe = cs5520_init_one, .probe = cs5520_init_one,
.remove = cs5520_remove_one, .remove = ata_pci_remove_one,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = cs5520_pci_device_suspend, .suspend = cs5520_pci_device_suspend,
.resume = cs5520_reinit_one, .resume = cs5520_reinit_one,

Просмотреть файл

@ -179,7 +179,6 @@ static struct scsi_host_template cs5530_sht = {
}; };
static struct ata_port_operations cs5530_port_ops = { static struct ata_port_operations cs5530_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cs5530_set_piomode, .set_piomode = cs5530_set_piomode,
.set_dmamode = cs5530_set_dmamode, .set_dmamode = cs5530_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -209,9 +208,8 @@ static struct ata_port_operations cs5530_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct dmi_system_id palmax_dmi_table[] = { static const struct dmi_system_id palmax_dmi_table[] = {

Просмотреть файл

@ -176,7 +176,6 @@ static struct scsi_host_template cs5535_sht = {
}; };
static struct ata_port_operations cs5535_port_ops = { static struct ata_port_operations cs5535_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cs5535_set_piomode, .set_piomode = cs5535_set_piomode,
.set_dmamode = cs5535_set_dmamode, .set_dmamode = cs5535_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -206,9 +205,8 @@ static struct ata_port_operations cs5535_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -128,7 +128,6 @@ static struct scsi_host_template cy82c693_sht = {
}; };
static struct ata_port_operations cy82c693_port_ops = { static struct ata_port_operations cy82c693_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = cy82c693_set_piomode, .set_piomode = cy82c693_set_piomode,
.set_dmamode = cy82c693_set_dmamode, .set_dmamode = cy82c693_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -158,9 +157,8 @@ static struct ata_port_operations cy82c693_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id)

Просмотреть файл

@ -26,25 +26,26 @@
/** /**
* efar_pre_reset - Enable bits * efar_pre_reset - Enable bits
* @ap: Port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform cable detection for the EFAR ATA interface. This is * Perform cable detection for the EFAR ATA interface. This is
* different to the PIIX arrangement * different to the PIIX arrangement
*/ */
static int efar_pre_reset(struct ata_port *ap, unsigned long deadline) static int efar_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits efar_enable_bits[] = { static const struct pci_bits efar_enable_bits[] = {
{ 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
{ 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -250,7 +251,6 @@ static struct scsi_host_template efar_sht = {
}; };
static const struct ata_port_operations efar_ops = { static const struct ata_port_operations efar_ops = {
.port_disable = ata_port_disable,
.set_piomode = efar_set_piomode, .set_piomode = efar_set_piomode,
.set_dmamode = efar_set_dmamode, .set_dmamode = efar_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -278,9 +278,8 @@ static const struct ata_port_operations efar_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -312,7 +312,6 @@ static struct scsi_host_template hpt36x_sht = {
*/ */
static struct ata_port_operations hpt366_port_ops = { static struct ata_port_operations hpt366_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt366_set_piomode, .set_piomode = hpt366_set_piomode,
.set_dmamode = hpt366_set_dmamode, .set_dmamode = hpt366_set_dmamode,
.mode_filter = hpt366_filter, .mode_filter = hpt366_filter,
@ -342,9 +341,8 @@ static struct ata_port_operations hpt366_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -304,15 +304,16 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
/** /**
* hpt37x_pre_reset - reset the hpt37x bus * hpt37x_pre_reset - reset the hpt37x bus
* @ap: ATA port to reset * @link: ATA link to reset
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform the initial reset handling for the 370/372 and 374 func 0 * Perform the initial reset handling for the 370/372 and 374 func 0
*/ */
static int hpt37x_pre_reset(struct ata_port *ap, unsigned long deadline) static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
u8 scr2, ata66; u8 scr2, ata66;
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits hpt37x_enable_bits[] = { static const struct pci_bits hpt37x_enable_bits[] = {
{ 0x50, 1, 0x04, 0x04 }, { 0x50, 1, 0x04, 0x04 },
@ -337,7 +338,7 @@ static int hpt37x_pre_reset(struct ata_port *ap, unsigned long deadline)
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100); udelay(100);
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -352,7 +353,7 @@ static void hpt37x_error_handler(struct ata_port *ap)
ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
} }
static int hpt374_pre_reset(struct ata_port *ap, unsigned long deadline) static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits hpt37x_enable_bits[] = { static const struct pci_bits hpt37x_enable_bits[] = {
{ 0x50, 1, 0x04, 0x04 }, { 0x50, 1, 0x04, 0x04 },
@ -360,6 +361,7 @@ static int hpt374_pre_reset(struct ata_port *ap, unsigned long deadline)
}; };
u16 mcr3, mcr6; u16 mcr3, mcr6;
u8 ata66; u8 ata66;
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))
@ -387,7 +389,7 @@ static int hpt374_pre_reset(struct ata_port *ap, unsigned long deadline)
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100); udelay(100);
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -642,7 +644,6 @@ static struct scsi_host_template hpt37x_sht = {
*/ */
static struct ata_port_operations hpt370_port_ops = { static struct ata_port_operations hpt370_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt370_set_piomode, .set_piomode = hpt370_set_piomode,
.set_dmamode = hpt370_set_dmamode, .set_dmamode = hpt370_set_dmamode,
.mode_filter = hpt370_filter, .mode_filter = hpt370_filter,
@ -671,9 +672,8 @@ static struct ata_port_operations hpt370_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
@ -681,7 +681,6 @@ static struct ata_port_operations hpt370_port_ops = {
*/ */
static struct ata_port_operations hpt370a_port_ops = { static struct ata_port_operations hpt370a_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt370_set_piomode, .set_piomode = hpt370_set_piomode,
.set_dmamode = hpt370_set_dmamode, .set_dmamode = hpt370_set_dmamode,
.mode_filter = hpt370a_filter, .mode_filter = hpt370a_filter,
@ -710,9 +709,8 @@ static struct ata_port_operations hpt370a_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
@ -721,7 +719,6 @@ static struct ata_port_operations hpt370a_port_ops = {
*/ */
static struct ata_port_operations hpt372_port_ops = { static struct ata_port_operations hpt372_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt372_set_piomode, .set_piomode = hpt372_set_piomode,
.set_dmamode = hpt372_set_dmamode, .set_dmamode = hpt372_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -750,9 +747,8 @@ static struct ata_port_operations hpt372_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/* /*
@ -761,7 +757,6 @@ static struct ata_port_operations hpt372_port_ops = {
*/ */
static struct ata_port_operations hpt374_port_ops = { static struct ata_port_operations hpt374_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt372_set_piomode, .set_piomode = hpt372_set_piomode,
.set_dmamode = hpt372_set_dmamode, .set_dmamode = hpt372_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -790,9 +785,8 @@ static struct ata_port_operations hpt374_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -141,21 +141,22 @@ static int hpt3x2n_cable_detect(struct ata_port *ap)
/** /**
* hpt3x2n_pre_reset - reset the hpt3x2n bus * hpt3x2n_pre_reset - reset the hpt3x2n bus
* @ap: ATA port to reset * @link: ATA link to reset
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform the initial reset handling for the 3x2n series controllers. * Perform the initial reset handling for the 3x2n series controllers.
* Reset the hardware and state machine, * Reset the hardware and state machine,
*/ */
static int hpt3xn_pre_reset(struct ata_port *ap, unsigned long deadline) static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
/* Reset the state machine */ /* Reset the state machine */
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
udelay(100); udelay(100);
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -360,7 +361,6 @@ static struct scsi_host_template hpt3x2n_sht = {
*/ */
static struct ata_port_operations hpt3x2n_port_ops = { static struct ata_port_operations hpt3x2n_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt3x2n_set_piomode, .set_piomode = hpt3x2n_set_piomode,
.set_dmamode = hpt3x2n_set_dmamode, .set_dmamode = hpt3x2n_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -390,9 +390,8 @@ static struct ata_port_operations hpt3x2n_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -120,7 +120,6 @@ static struct scsi_host_template hpt3x3_sht = {
}; };
static struct ata_port_operations hpt3x3_port_ops = { static struct ata_port_operations hpt3x3_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt3x3_set_piomode, .set_piomode = hpt3x3_set_piomode,
#if defined(CONFIG_PATA_HPT3X3_DMA) #if defined(CONFIG_PATA_HPT3X3_DMA)
.set_dmamode = hpt3x3_set_dmamode, .set_dmamode = hpt3x3_set_dmamode,
@ -153,9 +152,8 @@ static struct ata_port_operations hpt3x3_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**
@ -239,7 +237,8 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
base = host->iomap[4]; /* Bus mastering base */ base = host->iomap[4]; /* Bus mastering base */
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_ioports *ioaddr = &host->ports[i]->ioaddr; struct ata_port *ap = host->ports[i];
struct ata_ioports *ioaddr = &ap->ioaddr;
ioaddr->cmd_addr = base + offset_cmd[i]; ioaddr->cmd_addr = base + offset_cmd[i];
ioaddr->altstatus_addr = ioaddr->altstatus_addr =
@ -247,6 +246,9 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
ioaddr->scr_addr = NULL; ioaddr->scr_addr = NULL;
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ioaddr->bmdma_addr = base + 8 * i; ioaddr->bmdma_addr = base + 8 * i;
ata_port_pbar_desc(ap, 4, -1, "ioport");
ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd");
} }
pci_set_master(pdev); pci_set_master(pdev);
return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,

Просмотреть файл

@ -70,6 +70,8 @@ struct pata_icside_info {
unsigned int mwdma_mask; unsigned int mwdma_mask;
unsigned int nr_ports; unsigned int nr_ports;
const struct portinfo *port[2]; const struct portinfo *port[2];
unsigned long raw_base;
unsigned long raw_ioc_base;
}; };
#define ICS_TYPE_A3IN 0 #define ICS_TYPE_A3IN 0
@ -357,26 +359,7 @@ static void pata_icside_error_handler(struct ata_port *ap)
pata_icside_postreset); pata_icside_postreset);
} }
static u8 pata_icside_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
u8 status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: drv_stat 0x%X\n",
__FUNCTION__, status);
return status;
}
static struct ata_port_operations pata_icside_port_ops = { static struct ata_port_operations pata_icside_port_ops = {
.port_disable = ata_port_disable,
.set_dmamode = pata_icside_set_dmamode, .set_dmamode = pata_icside_set_dmamode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -403,7 +386,6 @@ static struct ata_port_operations pata_icside_port_ops = {
.irq_clear = ata_dummy_noret, .irq_clear = ata_dummy_noret,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = pata_icside_irq_ack,
.port_start = pata_icside_port_start, .port_start = pata_icside_port_start,
@ -412,9 +394,10 @@ static struct ata_port_operations pata_icside_port_ops = {
}; };
static void __devinit static void __devinit
pata_icside_setup_ioaddr(struct ata_ioports *ioaddr, void __iomem *base, pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,
const struct portinfo *info) const struct portinfo *info)
{ {
struct ata_ioports *ioaddr = &ap->ioaddr;
void __iomem *cmd = base + info->dataoffset; void __iomem *cmd = base + info->dataoffset;
ioaddr->cmd_addr = cmd; ioaddr->cmd_addr = cmd;
@ -431,6 +414,13 @@ pata_icside_setup_ioaddr(struct ata_ioports *ioaddr, void __iomem *base,
ioaddr->ctl_addr = base + info->ctrloffset; ioaddr->ctl_addr = base + info->ctrloffset;
ioaddr->altstatus_addr = ioaddr->ctl_addr; ioaddr->altstatus_addr = ioaddr->ctl_addr;
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
info->raw_base + info->dataoffset,
info->raw_base + info->ctrloffset);
if (info->raw_ioc_base)
ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);
} }
static int __devinit pata_icside_register_v5(struct pata_icside_info *info) static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
@ -451,6 +441,8 @@ static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
info->nr_ports = 1; info->nr_ports = 1;
info->port[0] = &pata_icside_portinfo_v5; info->port[0] = &pata_icside_portinfo_v5;
info->raw_base = ecard_resource_start(ec, ECARD_RES_MEMC);
return 0; return 0;
} }
@ -491,6 +483,9 @@ static int __devinit pata_icside_register_v6(struct pata_icside_info *info)
info->port[0] = &pata_icside_portinfo_v6_1; info->port[0] = &pata_icside_portinfo_v6_1;
info->port[1] = &pata_icside_portinfo_v6_2; info->port[1] = &pata_icside_portinfo_v6_2;
info->raw_base = ecard_resource_start(ec, ECARD_RES_EASI);
info->raw_ioc_base = ecard_resource_start(ec, ECARD_RES_IOCFAST);
return icside_dma_init(info); return icside_dma_init(info);
} }
@ -527,7 +522,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
ap->flags |= ATA_FLAG_SLAVE_POSS; ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ops = &pata_icside_port_ops; ap->ops = &pata_icside_port_ops;
pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]); pata_icside_setup_ioaddr(ap, info->base, info->port[i]);
} }
return ata_host_activate(host, ec->irq, ata_interrupt, 0, return ata_host_activate(host, ec->irq, ata_interrupt, 0,

Просмотреть файл

@ -38,7 +38,6 @@ static struct scsi_host_template isapnp_sht = {
}; };
static struct ata_port_operations isapnp_port_ops = { static struct ata_port_operations isapnp_port_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -58,9 +57,8 @@ static struct ata_port_operations isapnp_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**
@ -112,6 +110,10 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
ata_std_ports(&ap->ioaddr); ata_std_ports(&ap->ioaddr);
ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
(unsigned long long)pnp_port_start(idev, 0),
(unsigned long long)pnp_port_start(idev, 1));
/* activate */ /* activate */
return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0, return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0,
&isapnp_sht); &isapnp_sht);

Просмотреть файл

@ -23,23 +23,24 @@
/** /**
* it8213_pre_reset - check for 40/80 pin * it8213_pre_reset - check for 40/80 pin
* @ap: Port * @link: link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Filter out ports by the enable bits before doing the normal reset * Filter out ports by the enable bits before doing the normal reset
* and probe. * and probe.
*/ */
static int it8213_pre_reset(struct ata_port *ap, unsigned long deadline) static int it8213_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits it8213_enable_bits[] = { static const struct pci_bits it8213_enable_bits[] = {
{ 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &it8213_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -260,7 +261,6 @@ static struct scsi_host_template it8213_sht = {
}; };
static const struct ata_port_operations it8213_ops = { static const struct ata_port_operations it8213_ops = {
.port_disable = ata_port_disable,
.set_piomode = it8213_set_piomode, .set_piomode = it8213_set_piomode,
.set_dmamode = it8213_set_dmamode, .set_dmamode = it8213_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -288,9 +288,8 @@ static const struct ata_port_operations it8213_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -391,7 +391,7 @@ static void it821x_passthru_dev_select(struct ata_port *ap,
{ {
struct it821x_dev *itdev = ap->private_data; struct it821x_dev *itdev = ap->private_data;
if (itdev && device != itdev->last_device) { if (itdev && device != itdev->last_device) {
struct ata_device *adev = &ap->device[device]; struct ata_device *adev = &ap->link.device[device];
it821x_program(ap, adev, itdev->pio[adev->devno]); it821x_program(ap, adev, itdev->pio[adev->devno]);
itdev->last_device = device; itdev->last_device = device;
} }
@ -450,7 +450,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
/** /**
* it821x_smart_set_mode - mode setting * it821x_smart_set_mode - mode setting
* @ap: interface to set up * @link: interface to set up
* @unused: device that failed (error only) * @unused: device that failed (error only)
* *
* Use a non standard set_mode function. We don't want to be tuned. * Use a non standard set_mode function. We don't want to be tuned.
@ -459,12 +459,11 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
* and respect them. * and respect them.
*/ */
static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused) static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
int i; struct ata_device *dev;
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_link_for_each_dev(dev, link) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
@ -564,7 +563,7 @@ static int it821x_port_start(struct ata_port *ap)
struct it821x_dev *itdev; struct it821x_dev *itdev;
u8 conf; u8 conf;
int ret = ata_port_start(ap); int ret = ata_sff_port_start(ap);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -621,7 +620,6 @@ static struct scsi_host_template it821x_sht = {
static struct ata_port_operations it821x_smart_port_ops = { static struct ata_port_operations it821x_smart_port_ops = {
.set_mode = it821x_smart_set_mode, .set_mode = it821x_smart_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -651,13 +649,11 @@ static struct ata_port_operations it821x_smart_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = it821x_port_start, .port_start = it821x_port_start,
}; };
static struct ata_port_operations it821x_passthru_port_ops = { static struct ata_port_operations it821x_passthru_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = it821x_passthru_set_piomode, .set_piomode = it821x_passthru_set_piomode,
.set_dmamode = it821x_passthru_set_dmamode, .set_dmamode = it821x_passthru_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -688,7 +684,6 @@ static struct ata_port_operations it821x_passthru_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = it821x_port_start, .port_start = it821x_port_start,
}; };

Просмотреть файл

@ -26,12 +26,11 @@
#define DRV_NAME "pata_ixp4xx_cf" #define DRV_NAME "pata_ixp4xx_cf"
#define DRV_VERSION "0.2" #define DRV_VERSION "0.2"
static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error) static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
{ {
int i; struct ata_device *dev;
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_link_for_each_dev(dev, link) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
@ -49,7 +48,7 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int i; unsigned int i;
unsigned int words = buflen >> 1; unsigned int words = buflen >> 1;
u16 *buf16 = (u16 *) buf; u16 *buf16 = (u16 *) buf;
struct ata_port *ap = adev->ap; struct ata_port *ap = adev->link->ap;
void __iomem *mmio = ap->ioaddr.data_addr; void __iomem *mmio = ap->ioaddr.data_addr;
struct ixp4xx_pata_data *data = ap->host->dev->platform_data; struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
@ -108,7 +107,6 @@ static struct ata_port_operations ixp4xx_port_ops = {
.set_mode = ixp4xx_set_mode, .set_mode = ixp4xx_set_mode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
@ -128,14 +126,17 @@ static struct ata_port_operations ixp4xx_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_dummy_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static void ixp4xx_setup_port(struct ata_ioports *ioaddr, static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
struct ixp4xx_pata_data *data) struct ixp4xx_pata_data *data,
unsigned long raw_cs0, unsigned long raw_cs1)
{ {
unsigned long raw_cmd = raw_cs0;
unsigned long raw_ctl = raw_cs1 + 0x06;
ioaddr->cmd_addr = data->cs0; ioaddr->cmd_addr = data->cs0;
ioaddr->altstatus_addr = data->cs1 + 0x06; ioaddr->altstatus_addr = data->cs1 + 0x06;
ioaddr->ctl_addr = data->cs1 + 0x06; ioaddr->ctl_addr = data->cs1 + 0x06;
@ -161,7 +162,12 @@ static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
*(unsigned long *)&ioaddr->device_addr ^= 0x03; *(unsigned long *)&ioaddr->device_addr ^= 0x03;
*(unsigned long *)&ioaddr->status_addr ^= 0x03; *(unsigned long *)&ioaddr->status_addr ^= 0x03;
*(unsigned long *)&ioaddr->command_addr ^= 0x03; *(unsigned long *)&ioaddr->command_addr ^= 0x03;
raw_cmd ^= 0x03;
raw_ctl ^= 0x03;
#endif #endif
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", raw_cmd, raw_ctl);
} }
static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
@ -206,7 +212,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
ap->pio_mask = 0x1f; /* PIO4 */ ap->pio_mask = 0x1f; /* PIO4 */
ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
ixp4xx_setup_port(&ap->ioaddr, data); ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");

Просмотреть файл

@ -29,7 +29,7 @@ typedef enum {
/** /**
* jmicron_pre_reset - check for 40/80 pin * jmicron_pre_reset - check for 40/80 pin
* @ap: Port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform the PATA port setup we need. * Perform the PATA port setup we need.
@ -39,9 +39,9 @@ typedef enum {
* and setup here. We assume that has been done by init_one and the * and setup here. We assume that has been done by init_one and the
* BIOS. * BIOS.
*/ */
static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline)
static int jmicron_pre_reset(struct ata_port *ap, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 control; u32 control;
u32 control5; u32 control5;
@ -103,7 +103,7 @@ static int jmicron_pre_reset(struct ata_port *ap, unsigned long deadline)
ap->cbl = ATA_CBL_SATA; ap->cbl = ATA_CBL_SATA;
break; break;
} }
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -141,8 +141,6 @@ static struct scsi_host_template jmicron_sht = {
}; };
static const struct ata_port_operations jmicron_ops = { static const struct ata_port_operations jmicron_ops = {
.port_disable = ata_port_disable,
/* Task file is PCI ATA format, use helpers */ /* Task file is PCI ATA format, use helpers */
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -168,7 +166,6 @@ static const struct ata_port_operations jmicron_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
/* Generic PATA PCI ATA helpers */ /* Generic PATA PCI ATA helpers */
.port_start = ata_port_start, .port_start = ata_port_start,
@ -207,17 +204,8 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
} }
static const struct pci_device_id jmicron_pci_tbl[] = { static const struct pci_device_id jmicron_pci_tbl[] = {
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 361 }, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 363 },
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 365 },
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 366 },
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368,
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 368 },
{ } /* terminate list */ { } /* terminate list */
}; };

Просмотреть файл

@ -96,7 +96,7 @@ static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
/** /**
* legacy_set_mode - mode setting * legacy_set_mode - mode setting
* @ap: IDE interface * @link: IDE link
* @unused: Device that failed when error is returned * @unused: Device that failed when error is returned
* *
* Use a non standard set_mode function. We don't want to be tuned. * Use a non standard set_mode function. We don't want to be tuned.
@ -107,12 +107,11 @@ static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
* expand on this as per hdparm in the base kernel. * expand on this as per hdparm in the base kernel.
*/ */
static int legacy_set_mode(struct ata_port *ap, struct ata_device **unused) static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
int i; struct ata_device *dev;
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_link_for_each_dev(dev, link) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
@ -151,7 +150,6 @@ static struct scsi_host_template legacy_sht = {
*/ */
static struct ata_port_operations simple_port_ops = { static struct ata_port_operations simple_port_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -172,7 +170,6 @@ static struct ata_port_operations simple_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -180,7 +177,6 @@ static struct ata_port_operations simple_port_ops = {
static struct ata_port_operations legacy_port_ops = { static struct ata_port_operations legacy_port_ops = {
.set_mode = legacy_set_mode, .set_mode = legacy_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -201,7 +197,6 @@ static struct ata_port_operations legacy_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -256,7 +251,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{ {
struct ata_port *ap = adev->ap; struct ata_port *ap = adev->link->ap;
int slop = buflen & 3; int slop = buflen & 3;
unsigned long flags; unsigned long flags;
@ -296,7 +291,6 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig
static struct ata_port_operations pdc20230_port_ops = { static struct ata_port_operations pdc20230_port_ops = {
.set_piomode = pdc20230_set_piomode, .set_piomode = pdc20230_set_piomode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -317,7 +311,6 @@ static struct ata_port_operations pdc20230_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -352,7 +345,6 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
static struct ata_port_operations ht6560a_port_ops = { static struct ata_port_operations ht6560a_port_ops = {
.set_piomode = ht6560a_set_piomode, .set_piomode = ht6560a_set_piomode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -373,7 +365,6 @@ static struct ata_port_operations ht6560a_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -419,7 +410,6 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
static struct ata_port_operations ht6560b_port_ops = { static struct ata_port_operations ht6560b_port_ops = {
.set_piomode = ht6560b_set_piomode, .set_piomode = ht6560b_set_piomode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -440,7 +430,6 @@ static struct ata_port_operations ht6560b_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -541,7 +530,6 @@ static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev
static struct ata_port_operations opti82c611a_port_ops = { static struct ata_port_operations opti82c611a_port_ops = {
.set_piomode = opti82c611a_set_piomode, .set_piomode = opti82c611a_set_piomode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -562,7 +550,6 @@ static struct ata_port_operations opti82c611a_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -675,7 +662,6 @@ static unsigned int opti82c46x_qc_issue_prot(struct ata_queued_cmd *qc)
static struct ata_port_operations opti82c46x_port_ops = { static struct ata_port_operations opti82c46x_port_ops = {
.set_piomode = opti82c46x_set_piomode, .set_piomode = opti82c46x_set_piomode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -696,7 +682,6 @@ static struct ata_port_operations opti82c46x_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
@ -814,6 +799,8 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
ata_std_ports(&ap->ioaddr); ata_std_ports(&ap->ioaddr);
ap->private_data = ld; ap->private_data = ld;
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, ctrl);
ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht); ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
if (ret) if (ret)
goto fail; goto fail;

Просмотреть файл

@ -24,14 +24,15 @@
/** /**
* marvell_pre_reset - check for 40/80 pin * marvell_pre_reset - check for 40/80 pin
* @ap: Port * @link: link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform the PATA port setup we need. * Perform the PATA port setup we need.
*/ */
static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline) static int marvell_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
u32 devices; u32 devices;
void __iomem *barp; void __iomem *barp;
@ -54,7 +55,7 @@ static int marvell_pre_reset(struct ata_port *ap, unsigned long deadline)
(!(devices & 0x10))) /* PATA enable ? */ (!(devices & 0x10))) /* PATA enable ? */
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
static int marvell_cable_detect(struct ata_port *ap) static int marvell_cable_detect(struct ata_port *ap)
@ -110,8 +111,6 @@ static struct scsi_host_template marvell_sht = {
}; };
static const struct ata_port_operations marvell_ops = { static const struct ata_port_operations marvell_ops = {
.port_disable = ata_port_disable,
/* Task file is PCI ATA format, use helpers */ /* Task file is PCI ATA format, use helpers */
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -138,10 +137,9 @@ static const struct ata_port_operations marvell_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
/* Generic PATA PCI ATA helpers */ /* Generic PATA PCI ATA helpers */
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -283,7 +283,6 @@ static struct scsi_host_template mpc52xx_ata_sht = {
}; };
static struct ata_port_operations mpc52xx_ata_port_ops = { static struct ata_port_operations mpc52xx_ata_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = mpc52xx_ata_set_piomode, .set_piomode = mpc52xx_ata_set_piomode,
.dev_select = mpc52xx_ata_dev_select, .dev_select = mpc52xx_ata_dev_select,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -299,12 +298,12 @@ static struct ata_port_operations mpc52xx_ata_port_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static int __devinit static int __devinit
mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv) mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,
unsigned long raw_ata_regs)
{ {
struct ata_host *host; struct ata_host *host;
struct ata_port *ap; struct ata_port *ap;
@ -338,6 +337,8 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
aio->status_addr = &priv->ata_regs->tf_command; aio->status_addr = &priv->ata_regs->tf_command;
aio->command_addr = &priv->ata_regs->tf_command; aio->command_addr = &priv->ata_regs->tf_command;
ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs);
/* activate host */ /* activate host */
return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0, return ata_host_activate(host, priv->ata_irq, ata_interrupt, 0,
&mpc52xx_ata_sht); &mpc52xx_ata_sht);
@ -434,7 +435,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
} }
/* Register ourselves to libata */ /* Register ourselves to libata */
rv = mpc52xx_ata_init_one(&op->dev, priv); rv = mpc52xx_ata_init_one(&op->dev, priv, res_mem.start);
if (rv) { if (rv) {
printk(KERN_ERR DRV_NAME ": " printk(KERN_ERR DRV_NAME ": "
"Error while registering to ATA layer\n"); "Error while registering to ATA layer\n");

Просмотреть файл

@ -46,15 +46,16 @@ enum {
SECONDARY = (1 << 14) SECONDARY = (1 << 14)
}; };
static int mpiix_pre_reset(struct ata_port *ap, unsigned long deadline) static int mpiix_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 }; static const struct pci_bits mpiix_enable_bits = { 0x6D, 1, 0x80, 0x80 };
if (!pci_test_config_bits(pdev, &mpiix_enable_bits)) if (!pci_test_config_bits(pdev, &mpiix_enable_bits))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -168,7 +169,6 @@ static struct scsi_host_template mpiix_sht = {
}; };
static struct ata_port_operations mpiix_port_ops = { static struct ata_port_operations mpiix_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = mpiix_set_piomode, .set_piomode = mpiix_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -189,9 +189,8 @@ static struct ata_port_operations mpiix_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@ -202,7 +201,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
struct ata_port *ap; struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr; void __iomem *cmd_addr, *ctl_addr;
u16 idetim; u16 idetim;
int irq; int cmd, ctl, irq;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");
@ -210,6 +209,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
host = ata_host_alloc(&dev->dev, 1); host = ata_host_alloc(&dev->dev, 1);
if (!host) if (!host)
return -ENOMEM; return -ENOMEM;
ap = host->ports[0];
/* MPIIX has many functions which can be turned on or off according /* MPIIX has many functions which can be turned on or off according
to other devices present. Make sure IDE is enabled before we try to other devices present. Make sure IDE is enabled before we try
@ -221,25 +221,28 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* See if it's primary or secondary channel... */ /* See if it's primary or secondary channel... */
if (!(idetim & SECONDARY)) { if (!(idetim & SECONDARY)) {
cmd = 0x1F0;
ctl = 0x3F6;
irq = 14; irq = 14;
cmd_addr = devm_ioport_map(&dev->dev, 0x1F0, 8);
ctl_addr = devm_ioport_map(&dev->dev, 0x3F6, 1);
} else { } else {
cmd = 0x170;
ctl = 0x376;
irq = 15; irq = 15;
cmd_addr = devm_ioport_map(&dev->dev, 0x170, 8);
ctl_addr = devm_ioport_map(&dev->dev, 0x376, 1);
} }
cmd_addr = devm_ioport_map(&dev->dev, cmd, 8);
ctl_addr = devm_ioport_map(&dev->dev, ctl, 1);
if (!cmd_addr || !ctl_addr) if (!cmd_addr || !ctl_addr)
return -ENOMEM; return -ENOMEM;
ata_port_desc(ap, "cmd 0x%x ctl 0x%x", cmd, ctl);
/* We do our own plumbing to avoid leaking special cases for whacko /* We do our own plumbing to avoid leaking special cases for whacko
ancient hardware into the core code. There are two issues to ancient hardware into the core code. There are two issues to
worry about. #1 The chip is a bridge so if in legacy mode and worry about. #1 The chip is a bridge so if in legacy mode and
without BARs set fools the setup. #2 If you pci_disable_device without BARs set fools the setup. #2 If you pci_disable_device
the MPIIX your box goes castors up */ the MPIIX your box goes castors up */
ap = host->ports[0];
ap->ops = &mpiix_port_ops; ap->ops = &mpiix_port_ops;
ap->pio_mask = 0x1F; ap->pio_mask = 0x1F;
ap->flags |= ATA_FLAG_SLAVE_POSS; ap->flags |= ATA_FLAG_SLAVE_POSS;

Просмотреть файл

@ -40,8 +40,6 @@ static struct scsi_host_template netcell_sht = {
}; };
static const struct ata_port_operations netcell_ops = { static const struct ata_port_operations netcell_ops = {
.port_disable = ata_port_disable,
/* Task file is PCI ATA format, use helpers */ /* Task file is PCI ATA format, use helpers */
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -68,10 +66,9 @@ static const struct ata_port_operations netcell_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
/* Generic PATA PCI ATA helpers */ /* Generic PATA PCI ATA helpers */
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -32,14 +32,15 @@
/** /**
* ns87410_pre_reset - probe begin * ns87410_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Check enabled ports * Check enabled ports
*/ */
static int ns87410_pre_reset(struct ata_port *ap, unsigned long deadline) static int ns87410_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits ns87410_enable_bits[] = { static const struct pci_bits ns87410_enable_bits[] = {
{ 0x43, 1, 0x08, 0x08 }, { 0x43, 1, 0x08, 0x08 },
@ -49,7 +50,7 @@ static int ns87410_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -161,7 +162,6 @@ static struct scsi_host_template ns87410_sht = {
}; };
static struct ata_port_operations ns87410_port_ops = { static struct ata_port_operations ns87410_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = ns87410_set_piomode, .set_piomode = ns87410_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -184,9 +184,8 @@ static struct ata_port_operations ns87410_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)

467
drivers/ata/pata_ns87415.c Normal file
Просмотреть файл

@ -0,0 +1,467 @@
/*
* pata_ns87415.c - NS87415 (non PARISC) PATA
*
* (C) 2005 Red Hat <alan@redhat.com>
*
* This is a fairly generic MWDMA controller. It has some limitations
* as it requires timing reloads on PIO/DMA transitions but it is otherwise
* fairly well designed.
*
* This driver assumes the firmware has left the chip in a valid ST506
* compliant state, either legacy IRQ 14/15 or native INTA shared. You
* may need to add platform code if your system fails to do this.
*
* The same cell appears in the 87560 controller used by some PARISC
* systems. This has its own special mountain of errata.
*
* TODO:
* Test PARISC SuperIO
* Get someone to test on SPARC
* Implement lazy pio/dma switching for better performance
* 8bit shared timing.
* See if we need to kill the FIFO for ATAPI
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <linux/ata.h>
#define DRV_NAME "pata_ns87415"
#define DRV_VERSION "0.0.1"
/**
* ns87415_set_mode - Initialize host controller mode timings
* @ap: Port whose timings we are configuring
* @adev: Device whose timings we are configuring
* @mode: Mode to set
*
* Program the mode registers for this controller, channel and
* device. Because the chip is quite an old design we have to do this
* for PIO/DMA switches.
*
* LOCKING:
* None (inherited from caller).
*/
static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mode)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
int unit = 2 * ap->port_no + adev->devno;
int timing = 0x44 + 2 * unit;
unsigned long T = 1000000000 / 33333; /* PCI clocks */
struct ata_timing t;
u16 clocking;
u8 iordy;
u8 status;
/* Timing register format is 17 - low nybble read timing with
the high nybble being 16 - x for recovery time in PCI clocks */
ata_timing_compute(adev, adev->pio_mode, &t, T, 0);
clocking = 17 - FIT(t.active, 2, 17);
clocking |= (16 - FIT(t.recover, 1, 16)) << 4;
/* Use the same timing for read and write bytes */
clocking |= (clocking << 8);
pci_write_config_word(dev, timing, clocking);
/* Set the IORDY enable versus DMA enable on or off properly */
pci_read_config_byte(dev, 0x42, &iordy);
iordy &= ~(1 << (4 + unit));
if (mode >= XFER_MW_DMA_0 || !ata_pio_need_iordy(adev))
iordy |= (1 << (4 + unit));
/* Paranoia: We shouldn't ever get here with busy write buffers
but if so wait */
pci_read_config_byte(dev, 0x43, &status);
while (status & 0x03) {
udelay(1);
pci_read_config_byte(dev, 0x43, &status);
}
/* Flip the IORDY/DMA bits now we are sure the write buffers are
clear */
pci_write_config_byte(dev, 0x42, iordy);
/* TODO: Set byte 54 command timing to the best 8bit
mode shared by all four devices */
}
/**
* ns87415_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Device to program
*
* Set PIO mode for device, in host controller PCI config space.
*
* LOCKING:
* None (inherited from caller).
*/
static void ns87415_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
ns87415_set_mode(ap, adev, adev->pio_mode);
}
/**
* ns87415_bmdma_setup - Set up DMA
* @qc: Command block
*
* Set up for bus masterng DMA. We have to do this ourselves
* rather than use the helper due to a chip erratum
*/
static void ns87415_bmdma_setup(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 dmactl;
/* load PRD table addr. */
mb(); /* make sure PRD table writes are visible to controller */
iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
/* specify data direction, triple-check start bit is clear */
dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
/* Due to an erratum we need to write these bits to the wrong
place - which does save us an I/O bizarrely */
dmactl |= ATA_DMA_INTR | ATA_DMA_ERR;
if (!rw)
dmactl |= ATA_DMA_WR;
iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
/* issue r/w command */
ap->ops->exec_command(ap, &qc->tf);
}
/**
* ns87415_bmdma_start - Begin DMA transfer
* @qc: Command block
*
* Switch the timings for the chip and set up for a DMA transfer
* before the DMA burst begins.
*
* FIXME: We should do lazy switching on bmdma_start versus
* ata_pio_data_xfer for better performance.
*/
static void ns87415_bmdma_start(struct ata_queued_cmd *qc)
{
ns87415_set_mode(qc->ap, qc->dev, qc->dev->dma_mode);
ata_bmdma_start(qc);
}
/**
* ns87415_bmdma_stop - End DMA transfer
* @qc: Command block
*
* End DMA mode and switch the controller back into PIO mode
*/
static void ns87415_bmdma_stop(struct ata_queued_cmd *qc)
{
ata_bmdma_stop(qc);
ns87415_set_mode(qc->ap, qc->dev, qc->dev->pio_mode);
}
/**
* ns87415_bmdma_irq_clear - Clear interrupt
* @ap: Channel to clear
*
* Erratum: Due to a chip bug regisers 02 and 0A bit 1 and 2 (the
* error bits) are reset by writing to register 00 or 08.
*/
static void ns87415_bmdma_irq_clear(struct ata_port *ap)
{
void __iomem *mmio = ap->ioaddr.bmdma_addr;
if (!mmio)
return;
iowrite8((ioread8(mmio + ATA_DMA_CMD) | ATA_DMA_INTR | ATA_DMA_ERR),
mmio + ATA_DMA_CMD);
}
/**
* ns87415_check_atapi_dma - ATAPI DMA filter
* @qc: Command block
*
* Disable ATAPI DMA (for now). We may be able to do DMA if we
* kill the prefetching. This isn't clear.
*/
static int ns87415_check_atapi_dma(struct ata_queued_cmd *qc)
{
return -EOPNOTSUPP;
}
#if defined(CONFIG_SUPERIO)
/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
* Unfortunately, it's built-in on all Astro-based PA-RISC workstations
* which use the integrated NS87514 cell for CD-ROM support.
* i.e we have to support for CD-ROM installs.
* See drivers/parisc/superio.c for more gory details.
*
* Workarounds taken from drivers/ide/pci/ns87415.c
*/
#include <asm/superio.h>
/**
* ns87560_read_buggy - workaround buggy Super I/O chip
* @port: Port to read
*
* Work around chipset problems in the 87560 SuperIO chip
*/
static u8 ns87560_read_buggy(void __iomem *port)
{
u8 tmp;
int retries = SUPERIO_IDE_MAX_RETRIES;
do {
tmp = ioread8(port);
if (tmp != 0)
return tmp;
udelay(50);
} while(retries-- > 0);
return tmp;
}
/**
* ns87560_check_status
* @ap: channel to check
*
* Return the status of the channel working around the
* 87560 flaws.
*/
static u8 ns87560_check_status(struct ata_port *ap)
{
return ns87560_read_buggy(ap->ioaddr.status_addr);
}
/**
* ns87560_tf_read - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf. Work around the 87560 bugs.
*
* LOCKING:
* Inherited from caller.
*/
void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
tf->command = ns87560_check_status(ap);
tf->feature = ioread8(ioaddr->error_addr);
tf->nsect = ioread8(ioaddr->nsect_addr);
tf->lbal = ioread8(ioaddr->lbal_addr);
tf->lbam = ioread8(ioaddr->lbam_addr);
tf->lbah = ioread8(ioaddr->lbah_addr);
tf->device = ns87560_read_buggy(ioaddr->device_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
tf->hob_feature = ioread8(ioaddr->error_addr);
tf->hob_nsect = ioread8(ioaddr->nsect_addr);
tf->hob_lbal = ioread8(ioaddr->lbal_addr);
tf->hob_lbam = ioread8(ioaddr->lbam_addr);
tf->hob_lbah = ioread8(ioaddr->lbah_addr);
iowrite8(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
}
}
/**
* ns87560_bmdma_status
* @ap: channel to check
*
* Return the DMA status of the channel working around the
* 87560 flaws.
*/
static u8 ns87560_bmdma_status(struct ata_port *ap)
{
return ns87560_read_buggy(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
static const struct ata_port_operations ns87560_pata_ops = {
.set_piomode = ns87415_set_piomode,
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
.tf_read = ns87560_tf_read,
.check_status = ns87560_check_status,
.check_atapi_dma = ns87415_check_atapi_dma,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
.bmdma_setup = ns87415_bmdma_setup,
.bmdma_start = ns87415_bmdma_start,
.bmdma_stop = ns87415_bmdma_stop,
.bmdma_status = ns87560_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
.irq_handler = ata_interrupt,
.irq_clear = ns87415_bmdma_irq_clear,
.irq_on = ata_irq_on,
.port_start = ata_sff_port_start,
};
#endif /* 87560 SuperIO Support */
static const struct ata_port_operations ns87415_pata_ops = {
.set_piomode = ns87415_set_piomode,
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.check_atapi_dma = ns87415_check_atapi_dma,
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
.bmdma_setup = ns87415_bmdma_setup,
.bmdma_start = ns87415_bmdma_start,
.bmdma_stop = ns87415_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
.irq_handler = ata_interrupt,
.irq_clear = ns87415_bmdma_irq_clear,
.irq_on = ata_irq_on,
.port_start = ata_sff_port_start,
};
static struct scsi_host_template ns87415_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 = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
};
/**
* ns87415_init_one - Register 87415 ATA PCI device with kernel services
* @pdev: PCI device to register
* @ent: Entry in ns87415_pci_tbl matching with @pdev
*
* Called from kernel PCI layer. We probe for combined mode (sigh),
* and then hand over control to libata, for it to do the rest.
*
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
* Zero on success, or -ERRNO value.
*/
static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
static const struct ata_port_info info = {
.sht = &ns87415_sht,
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.port_ops = &ns87415_pata_ops,
};
const struct ata_port_info *ppi[] = { &info, NULL };
#if defined(CONFIG_SUPERIO)
static const struct ata_port_info info87560 = {
.sht = &ns87415_sht,
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.port_ops = &ns87560_pata_ops,
};
if (PCI_SLOT(pdev->devfn) == 0x0E)
ppi[0] = &info87560;
#endif
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
"version " DRV_VERSION "\n");
/* Select 512 byte sectors */
pci_write_config_byte(pdev, 0x55, 0xEE);
/* Select PIO0 8bit clocking */
pci_write_config_byte(pdev, 0x54, 0xB7);
return ata_pci_init_one(pdev, ppi);
}
static const struct pci_device_id ns87415_pci_tbl[] = {
{ PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87415), },
{ } /* terminate list */
};
static struct pci_driver ns87415_pci_driver = {
.name = DRV_NAME,
.id_table = ns87415_pci_tbl,
.probe = ns87415_init_one,
.remove = ata_pci_remove_one,
#ifdef CONFIG_PM
.suspend = ata_pci_device_suspend,
.resume = ata_pci_device_resume,
#endif
};
static int __init ns87415_init(void)
{
return pci_register_driver(&ns87415_pci_driver);
}
static void __exit ns87415_exit(void)
{
pci_unregister_driver(&ns87415_pci_driver);
}
module_init(ns87415_init);
module_exit(ns87415_exit);
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("ATA low-level driver for NS87415 controllers");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
MODULE_VERSION(DRV_VERSION);

Просмотреть файл

@ -29,14 +29,15 @@
/** /**
* oldpiix_pre_reset - probe begin * oldpiix_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int oldpiix_pre_reset(struct ata_port *ap, unsigned long deadline) static int oldpiix_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits oldpiix_enable_bits[] = { static const struct pci_bits oldpiix_enable_bits[] = {
{ 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */
@ -46,7 +47,7 @@ static int oldpiix_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -237,7 +238,6 @@ static struct scsi_host_template oldpiix_sht = {
}; };
static const struct ata_port_operations oldpiix_pata_ops = { static const struct ata_port_operations oldpiix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = oldpiix_set_piomode, .set_piomode = oldpiix_set_piomode,
.set_dmamode = oldpiix_set_dmamode, .set_dmamode = oldpiix_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -265,9 +265,8 @@ static const struct ata_port_operations oldpiix_pata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -46,14 +46,15 @@ enum {
/** /**
* opti_pre_reset - probe begin * opti_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int opti_pre_reset(struct ata_port *ap, unsigned long deadline) static int opti_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits opti_enable_bits[] = { static const struct pci_bits opti_enable_bits[] = {
{ 0x45, 1, 0x80, 0x00 }, { 0x45, 1, 0x80, 0x00 },
@ -63,7 +64,7 @@ static int opti_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -182,7 +183,6 @@ static struct scsi_host_template opti_sht = {
}; };
static struct ata_port_operations opti_port_ops = { static struct ata_port_operations opti_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = opti_set_piomode, .set_piomode = opti_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -209,9 +209,8 @@ static struct ata_port_operations opti_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)

Просмотреть файл

@ -47,14 +47,15 @@ static int pci_clock; /* 0 = 33 1 = 25 */
/** /**
* optidma_pre_reset - probe begin * optidma_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int optidma_pre_reset(struct ata_port *ap, unsigned long deadline) static int optidma_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
static const struct pci_bits optidma_enable_bits = { static const struct pci_bits optidma_enable_bits = {
0x40, 1, 0x08, 0x00 0x40, 1, 0x08, 0x00
@ -63,7 +64,7 @@ static int optidma_pre_reset(struct ata_port *ap, unsigned long deadline)
if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits)) if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -323,25 +324,26 @@ static u8 optidma_make_bits43(struct ata_device *adev)
/** /**
* optidma_set_mode - mode setup * optidma_set_mode - mode setup
* @ap: port to set up * @link: link to set up
* *
* Use the standard setup to tune the chipset and then finalise the * Use the standard setup to tune the chipset and then finalise the
* configuration by writing the nibble of extra bits of data into * configuration by writing the nibble of extra bits of data into
* the chip. * the chip.
*/ */
static int optidma_set_mode(struct ata_port *ap, struct ata_device **r_failed) static int optidma_set_mode(struct ata_link *link, struct ata_device **r_failed)
{ {
struct ata_port *ap = link->ap;
u8 r; u8 r;
int nybble = 4 * ap->port_no; int nybble = 4 * ap->port_no;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int rc = ata_do_set_mode(ap, r_failed); int rc = ata_do_set_mode(link, r_failed);
if (rc == 0) { if (rc == 0) {
pci_read_config_byte(pdev, 0x43, &r); pci_read_config_byte(pdev, 0x43, &r);
r &= (0x0F << nybble); r &= (0x0F << nybble);
r |= (optidma_make_bits43(&ap->device[0]) + r |= (optidma_make_bits43(&link->device[0]) +
(optidma_make_bits43(&ap->device[0]) << 2)) << nybble; (optidma_make_bits43(&link->device[0]) << 2)) << nybble;
pci_write_config_byte(pdev, 0x43, r); pci_write_config_byte(pdev, 0x43, r);
} }
return rc; return rc;
@ -366,7 +368,6 @@ static struct scsi_host_template optidma_sht = {
}; };
static struct ata_port_operations optidma_port_ops = { static struct ata_port_operations optidma_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = optidma_set_pio_mode, .set_piomode = optidma_set_pio_mode,
.set_dmamode = optidma_set_dma_mode, .set_dmamode = optidma_set_dma_mode,
@ -396,13 +397,11 @@ static struct ata_port_operations optidma_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations optiplus_port_ops = { static struct ata_port_operations optiplus_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = optiplus_set_pio_mode, .set_piomode = optiplus_set_pio_mode,
.set_dmamode = optiplus_set_dma_mode, .set_dmamode = optiplus_set_dma_mode,
@ -432,9 +431,8 @@ static struct ata_port_operations optiplus_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -56,7 +56,7 @@ struct ata_pcmcia_info {
/** /**
* pcmcia_set_mode - PCMCIA specific mode setup * pcmcia_set_mode - PCMCIA specific mode setup
* @ap: Port * @link: link
* @r_failed_dev: Return pointer for failed device * @r_failed_dev: Return pointer for failed device
* *
* Perform the tuning and setup of the devices and timings, which * Perform the tuning and setup of the devices and timings, which
@ -65,13 +65,13 @@ struct ata_pcmcia_info {
* decode, which alas is embarrassingly common in the PC world * decode, which alas is embarrassingly common in the PC world
*/ */
static int pcmcia_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
{ {
struct ata_device *master = &ap->device[0]; struct ata_device *master = &link->device[0];
struct ata_device *slave = &ap->device[1]; struct ata_device *slave = &link->device[1];
if (!ata_dev_enabled(master) || !ata_dev_enabled(slave)) if (!ata_dev_enabled(master) || !ata_dev_enabled(slave))
return ata_do_set_mode(ap, r_failed_dev); return ata_do_set_mode(link, r_failed_dev);
if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV, if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV,
ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0)
@ -84,7 +84,7 @@ static int pcmcia_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev
ata_dev_disable(slave); ata_dev_disable(slave);
} }
} }
return ata_do_set_mode(ap, r_failed_dev); return ata_do_set_mode(link, r_failed_dev);
} }
static struct scsi_host_template pcmcia_sht = { static struct scsi_host_template pcmcia_sht = {
@ -107,7 +107,6 @@ static struct scsi_host_template pcmcia_sht = {
static struct ata_port_operations pcmcia_port_ops = { static struct ata_port_operations pcmcia_port_ops = {
.set_mode = pcmcia_set_mode, .set_mode = pcmcia_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -127,7 +126,6 @@ static struct ata_port_operations pcmcia_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_sff_port_start, .port_start = ata_sff_port_start,
}; };
@ -304,6 +302,8 @@ next_entry:
ap->ioaddr.ctl_addr = ctl_addr; ap->ioaddr.ctl_addr = ctl_addr;
ata_std_ports(&ap->ioaddr); ata_std_ports(&ap->ioaddr);
ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
/* activate */ /* activate */
ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt, ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
IRQF_SHARED, &pcmcia_sht); IRQF_SHARED, &pcmcia_sht);

Просмотреть файл

@ -69,7 +69,7 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc); static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long mask); static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long mask);
static int pdc2027x_cable_detect(struct ata_port *ap); static int pdc2027x_cable_detect(struct ata_port *ap);
static int pdc2027x_set_mode(struct ata_port *ap, struct ata_device **r_failed); static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed);
/* /*
* ATA Timing Tables based on 133MHz controller clock. * ATA Timing Tables based on 133MHz controller clock.
@ -147,7 +147,6 @@ static struct scsi_host_template pdc2027x_sht = {
}; };
static struct ata_port_operations pdc2027x_pata100_ops = { static struct ata_port_operations pdc2027x_pata100_ops = {
.port_disable = ata_port_disable,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -173,13 +172,11 @@ static struct ata_port_operations pdc2027x_pata100_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations pdc2027x_pata133_ops = { static struct ata_port_operations pdc2027x_pata133_ops = {
.port_disable = ata_port_disable,
.set_piomode = pdc2027x_set_piomode, .set_piomode = pdc2027x_set_piomode,
.set_dmamode = pdc2027x_set_dmamode, .set_dmamode = pdc2027x_set_dmamode,
.set_mode = pdc2027x_set_mode, .set_mode = pdc2027x_set_mode,
@ -208,9 +205,8 @@ static struct ata_port_operations pdc2027x_pata133_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_info pdc2027x_port_info[] = { static struct ata_port_info pdc2027x_port_info[] = {
@ -277,7 +273,7 @@ static int pdc2027x_cable_detect(struct ata_port *ap)
u32 cgcr; u32 cgcr;
/* check cable detect results */ /* check cable detect results */
cgcr = readl(port_mmio(ap, PDC_GLOBAL_CTL)); cgcr = ioread32(port_mmio(ap, PDC_GLOBAL_CTL));
if (cgcr & (1 << 26)) if (cgcr & (1 << 26))
goto cbl40; goto cbl40;
@ -295,12 +291,12 @@ cbl40:
*/ */
static inline int pdc2027x_port_enabled(struct ata_port *ap) static inline int pdc2027x_port_enabled(struct ata_port *ap)
{ {
return readb(port_mmio(ap, PDC_ATA_CTL)) & 0x02; return ioread8(port_mmio(ap, PDC_ATA_CTL)) & 0x02;
} }
/** /**
* pdc2027x_prereset - prereset for PATA host controller * pdc2027x_prereset - prereset for PATA host controller
* @ap: Target port * @link: Target link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Probeinit including cable detection. * Probeinit including cable detection.
@ -309,12 +305,12 @@ static inline int pdc2027x_port_enabled(struct ata_port *ap)
* None (inherited from caller). * None (inherited from caller).
*/ */
static int pdc2027x_prereset(struct ata_port *ap, unsigned long deadline) static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline)
{ {
/* Check whether port enabled */ /* Check whether port enabled */
if (!pdc2027x_port_enabled(ap)) if (!pdc2027x_port_enabled(link->ap))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -387,16 +383,16 @@ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev)
/* Set the PIO timing registers using value table for 133MHz */ /* Set the PIO timing registers using value table for 133MHz */
PDPRINTK("Set pio regs... \n"); PDPRINTK("Set pio regs... \n");
ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0));
ctcr0 &= 0xffff0000; ctcr0 &= 0xffff0000;
ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 |
(pdc2027x_pio_timing_tbl[pio].value1 << 8); (pdc2027x_pio_timing_tbl[pio].value1 << 8);
writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0));
ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1));
ctcr1 &= 0x00ffffff; ctcr1 &= 0x00ffffff;
ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24);
writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1));
PDPRINTK("Set pio regs done\n"); PDPRINTK("Set pio regs done\n");
@ -430,18 +426,18 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* If tHOLD is '1', the hardware will add half clock for data hold time. * If tHOLD is '1', the hardware will add half clock for data hold time.
* This code segment seems to be no effect. tHOLD will be overwritten below. * This code segment seems to be no effect. tHOLD will be overwritten below.
*/ */
ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1));
writel(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); iowrite32(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1));
} }
PDPRINTK("Set udma regs... \n"); PDPRINTK("Set udma regs... \n");
ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); ctcr1 = ioread32(dev_mmio(ap, adev, PDC_CTCR1));
ctcr1 &= 0xff000000; ctcr1 &= 0xff000000;
ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 |
(pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) |
(pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16);
writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); iowrite32(ctcr1, dev_mmio(ap, adev, PDC_CTCR1));
PDPRINTK("Set udma regs done\n"); PDPRINTK("Set udma regs done\n");
@ -453,13 +449,13 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
unsigned int mdma_mode = dma_mode & 0x07; unsigned int mdma_mode = dma_mode & 0x07;
PDPRINTK("Set mdma regs... \n"); PDPRINTK("Set mdma regs... \n");
ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); ctcr0 = ioread32(dev_mmio(ap, adev, PDC_CTCR0));
ctcr0 &= 0x0000ffff; ctcr0 &= 0x0000ffff;
ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) |
(pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24);
writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); iowrite32(ctcr0, dev_mmio(ap, adev, PDC_CTCR0));
PDPRINTK("Set mdma regs done\n"); PDPRINTK("Set mdma regs done\n");
PDPRINTK("Set to mdma mode[%u] \n", mdma_mode); PDPRINTK("Set to mdma mode[%u] \n", mdma_mode);
@ -470,24 +466,24 @@ static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
/** /**
* pdc2027x_set_mode - Set the timing registers back to correct values. * pdc2027x_set_mode - Set the timing registers back to correct values.
* @ap: Port to configure * @link: link to configure
* @r_failed: Returned device for failure * @r_failed: Returned device for failure
* *
* The pdc2027x hardware will look at "SET FEATURES" and change the timing registers * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers
* automatically. The values set by the hardware might be incorrect, under 133Mhz PLL. * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL.
* This function overwrites the possibly incorrect values set by the hardware to be correct. * This function overwrites the possibly incorrect values set by the hardware to be correct.
*/ */
static int pdc2027x_set_mode(struct ata_port *ap, struct ata_device **r_failed) static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed)
{ {
int i; struct ata_port *ap = link->ap;
struct ata_device *dev;
int rc;
i = ata_do_set_mode(ap, r_failed); rc = ata_do_set_mode(link, r_failed);
if (i < 0) if (rc < 0)
return i; return rc;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
ata_link_for_each_dev(dev, link) {
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
pdc2027x_set_piomode(ap, dev); pdc2027x_set_piomode(ap, dev);
@ -496,9 +492,9 @@ static int pdc2027x_set_mode(struct ata_port *ap, struct ata_device **r_failed)
* Enable prefetch if the device support PIO only. * Enable prefetch if the device support PIO only.
*/ */
if (dev->xfer_shift == ATA_SHIFT_PIO) { if (dev->xfer_shift == ATA_SHIFT_PIO) {
u32 ctcr1 = readl(dev_mmio(ap, dev, PDC_CTCR1)); u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1));
ctcr1 |= (1 << 25); ctcr1 |= (1 << 25);
writel(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1));
PDPRINTK("Turn on prefetch\n"); PDPRINTK("Turn on prefetch\n");
} else { } else {
@ -563,14 +559,12 @@ static long pdc_read_counter(struct ata_host *host)
u32 bccrl, bccrh, bccrlv, bccrhv; u32 bccrl, bccrh, bccrlv, bccrhv;
retry: retry:
bccrl = readl(mmio_base + PDC_BYTE_COUNT) & 0x7fff; bccrl = ioread32(mmio_base + PDC_BYTE_COUNT) & 0x7fff;
bccrh = readl(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff; bccrh = ioread32(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff;
rmb();
/* Read the counter values again for verification */ /* Read the counter values again for verification */
bccrlv = readl(mmio_base + PDC_BYTE_COUNT) & 0x7fff; bccrlv = ioread32(mmio_base + PDC_BYTE_COUNT) & 0x7fff;
bccrhv = readl(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff; bccrhv = ioread32(mmio_base + PDC_BYTE_COUNT + 0x100) & 0x7fff;
rmb();
counter = (bccrh << 15) | bccrl; counter = (bccrh << 15) | bccrl;
@ -619,7 +613,7 @@ static void pdc_adjust_pll(struct ata_host *host, long pll_clock, unsigned int b
/* Show the current clock value of PLL control register /* Show the current clock value of PLL control register
* (maybe already configured by the firmware) * (maybe already configured by the firmware)
*/ */
pll_ctl = readw(mmio_base + PDC_PLL_CTL); pll_ctl = ioread16(mmio_base + PDC_PLL_CTL);
PDPRINTK("pll_ctl[%X]\n", pll_ctl); PDPRINTK("pll_ctl[%X]\n", pll_ctl);
#endif #endif
@ -659,8 +653,8 @@ static void pdc_adjust_pll(struct ata_host *host, long pll_clock, unsigned int b
PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl); PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl);
writew(pll_ctl, mmio_base + PDC_PLL_CTL); iowrite16(pll_ctl, mmio_base + PDC_PLL_CTL);
readw(mmio_base + PDC_PLL_CTL); /* flush */ ioread16(mmio_base + PDC_PLL_CTL); /* flush */
/* Wait the PLL circuit to be stable */ /* Wait the PLL circuit to be stable */
mdelay(30); mdelay(30);
@ -670,7 +664,7 @@ static void pdc_adjust_pll(struct ata_host *host, long pll_clock, unsigned int b
* Show the current clock value of PLL control register * Show the current clock value of PLL control register
* (maybe configured by the firmware) * (maybe configured by the firmware)
*/ */
pll_ctl = readw(mmio_base + PDC_PLL_CTL); pll_ctl = ioread16(mmio_base + PDC_PLL_CTL);
PDPRINTK("pll_ctl[%X]\n", pll_ctl); PDPRINTK("pll_ctl[%X]\n", pll_ctl);
#endif #endif
@ -693,10 +687,10 @@ static long pdc_detect_pll_input_clock(struct ata_host *host)
long pll_clock, usec_elapsed; long pll_clock, usec_elapsed;
/* Start the test mode */ /* Start the test mode */
scr = readl(mmio_base + PDC_SYS_CTL); scr = ioread32(mmio_base + PDC_SYS_CTL);
PDPRINTK("scr[%X]\n", scr); PDPRINTK("scr[%X]\n", scr);
writel(scr | (0x01 << 14), mmio_base + PDC_SYS_CTL); iowrite32(scr | (0x01 << 14), mmio_base + PDC_SYS_CTL);
readl(mmio_base + PDC_SYS_CTL); /* flush */ ioread32(mmio_base + PDC_SYS_CTL); /* flush */
/* Read current counter value */ /* Read current counter value */
start_count = pdc_read_counter(host); start_count = pdc_read_counter(host);
@ -710,10 +704,10 @@ static long pdc_detect_pll_input_clock(struct ata_host *host)
do_gettimeofday(&end_time); do_gettimeofday(&end_time);
/* Stop the test mode */ /* Stop the test mode */
scr = readl(mmio_base + PDC_SYS_CTL); scr = ioread32(mmio_base + PDC_SYS_CTL);
PDPRINTK("scr[%X]\n", scr); PDPRINTK("scr[%X]\n", scr);
writel(scr & ~(0x01 << 14), mmio_base + PDC_SYS_CTL); iowrite32(scr & ~(0x01 << 14), mmio_base + PDC_SYS_CTL);
readl(mmio_base + PDC_SYS_CTL); /* flush */ ioread32(mmio_base + PDC_SYS_CTL); /* flush */
/* calculate the input clock in Hz */ /* calculate the input clock in Hz */
usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 + usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
@ -745,9 +739,6 @@ static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)
*/ */
pll_clock = pdc_detect_pll_input_clock(host); pll_clock = pdc_detect_pll_input_clock(host);
if (pll_clock < 0) /* counter overflow? Try again. */
pll_clock = pdc_detect_pll_input_clock(host);
dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000); dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);
/* Adjust PLL control register */ /* Adjust PLL control register */
@ -791,12 +782,14 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)
static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version; static int printed_version;
static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 };
static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 };
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
const struct ata_port_info *ppi[] = const struct ata_port_info *ppi[] =
{ &pdc2027x_port_info[board_idx], NULL }; { &pdc2027x_port_info[board_idx], NULL };
struct ata_host *host; struct ata_host *host;
void __iomem *mmio_base; void __iomem *mmio_base;
int rc; int i, rc;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@ -826,10 +819,15 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de
mmio_base = host->iomap[PDC_MMIO_BAR]; mmio_base = host->iomap[PDC_MMIO_BAR];
pdc_ata_setup_port(&host->ports[0]->ioaddr, mmio_base + 0x17c0); for (i = 0; i < 2; i++) {
host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x1000; struct ata_port *ap = host->ports[i];
pdc_ata_setup_port(&host->ports[1]->ioaddr, mmio_base + 0x15c0);
host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x1008; pdc_ata_setup_port(&ap->ioaddr, mmio_base + cmd_offset[i]);
ap->ioaddr.bmdma_addr = mmio_base + bmdma_offset[i];
ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, PDC_MMIO_BAR, cmd_offset[i], "cmd");
}
//pci_enable_intx(pdev); //pci_enable_intx(pdev);

Просмотреть файл

@ -9,7 +9,7 @@
* First cut with LBA48/ATAPI * First cut with LBA48/ATAPI
* *
* TODO: * TODO:
* Channel interlock/reset on both required * Channel interlock/reset on both required ?
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
@ -22,7 +22,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "pata_pdc202xx_old" #define DRV_NAME "pata_pdc202xx_old"
#define DRV_VERSION "0.4.2" #define DRV_VERSION "0.4.3"
static int pdc2026x_cable_detect(struct ata_port *ap) static int pdc2026x_cable_detect(struct ata_port *ap)
{ {
@ -106,9 +106,9 @@ static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{ 0x20, 0x01 } { 0x20, 0x01 }
}; };
static u8 mdma_timing[3][2] = { static u8 mdma_timing[3][2] = {
{ 0x60, 0x03 },
{ 0x60, 0x04 },
{ 0xe0, 0x0f }, { 0xe0, 0x0f },
{ 0x60, 0x04 },
{ 0x60, 0x03 },
}; };
u8 r_bp, r_cp; u8 r_bp, r_cp;
@ -139,6 +139,9 @@ static void pdc202xx_set_dmamode(struct ata_port *ap, struct ata_device *adev)
* *
* In UDMA3 or higher we have to clock switch for the duration of the * In UDMA3 or higher we have to clock switch for the duration of the
* DMA transfer sequence. * DMA transfer sequence.
*
* Note: The host lock held by the libata layer protects
* us from two channels both trying to set DMA bits at once
*/ */
static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
@ -187,6 +190,9 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
* *
* After a DMA completes we need to put the clock back to 33MHz for * After a DMA completes we need to put the clock back to 33MHz for
* PIO timings. * PIO timings.
*
* Note: The host lock held by the libata layer protects
* us from two channels both trying to set DMA bits at once
*/ */
static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
@ -206,7 +212,6 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
iowrite32(0, atapi_reg); iowrite32(0, atapi_reg);
iowrite8(ioread8(clock) & ~sel66, clock); iowrite8(ioread8(clock) & ~sel66, clock);
} }
/* Check we keep host level locking here */
/* Flip back to 33Mhz for PIO */ /* Flip back to 33Mhz for PIO */
if (adev->dma_mode >= XFER_UDMA_2) if (adev->dma_mode >= XFER_UDMA_2)
iowrite8(ioread8(clock) & ~sel66, clock); iowrite8(ioread8(clock) & ~sel66, clock);
@ -247,7 +252,6 @@ static struct scsi_host_template pdc202xx_sht = {
}; };
static struct ata_port_operations pdc2024x_port_ops = { static struct ata_port_operations pdc2024x_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = pdc202xx_set_piomode, .set_piomode = pdc202xx_set_piomode,
.set_dmamode = pdc202xx_set_dmamode, .set_dmamode = pdc202xx_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -275,13 +279,11 @@ static struct ata_port_operations pdc2024x_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations pdc2026x_port_ops = { static struct ata_port_operations pdc2026x_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = pdc202xx_set_piomode, .set_piomode = pdc202xx_set_piomode,
.set_dmamode = pdc202xx_set_dmamode, .set_dmamode = pdc202xx_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -310,9 +312,8 @@ static struct ata_port_operations pdc2026x_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)

Просмотреть файл

@ -30,13 +30,11 @@ static int pio_mask = 1;
* Provide our own set_mode() as we don't want to change anything that has * Provide our own set_mode() as we don't want to change anything that has
* already been configured.. * already been configured..
*/ */
static int pata_platform_set_mode(struct ata_port *ap, struct ata_device **unused) static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
int i; struct ata_device *dev;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
ata_link_for_each_dev(dev, link) {
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = dev->xfer_mode = XFER_PIO_0; dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
@ -71,7 +69,6 @@ static struct scsi_host_template pata_platform_sht = {
static struct ata_port_operations pata_platform_port_ops = { static struct ata_port_operations pata_platform_port_ops = {
.set_mode = pata_platform_set_mode, .set_mode = pata_platform_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -91,7 +88,6 @@ static struct ata_port_operations pata_platform_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_dummy_ret0, .port_start = ata_dummy_ret0,
}; };
@ -209,9 +205,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
pp_info = (struct pata_platform_info *)(pdev->dev.platform_data); pp_info = pdev->dev.platform_data;
pata_platform_setup_port(&ap->ioaddr, pp_info); pata_platform_setup_port(&ap->ioaddr, pp_info);
ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
(unsigned long long)io_res->start,
(unsigned long long)ctl_res->start);
/* activate */ /* activate */
return ata_host_activate(host, platform_get_irq(pdev, 0), return ata_host_activate(host, platform_get_irq(pdev, 0),
ata_interrupt, pp_info ? pp_info->irq_flags ata_interrupt, pp_info ? pp_info->irq_flags

Просмотреть файл

@ -126,7 +126,7 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{ {
struct ata_port *ap = adev->ap; struct ata_port *ap = adev->link->ap;
int slop = buflen & 3; int slop = buflen & 3;
if (ata_id_has_dword_io(adev->id)) { if (ata_id_has_dword_io(adev->id)) {
@ -170,7 +170,6 @@ static struct scsi_host_template qdi_sht = {
}; };
static struct ata_port_operations qdi6500_port_ops = { static struct ata_port_operations qdi6500_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = qdi6500_set_piomode, .set_piomode = qdi6500_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -192,13 +191,11 @@ static struct ata_port_operations qdi6500_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations qdi6580_port_ops = { static struct ata_port_operations qdi6580_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = qdi6580_set_piomode, .set_piomode = qdi6580_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -220,9 +217,8 @@ static struct ata_port_operations qdi6580_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**
@ -238,6 +234,7 @@ static struct ata_port_operations qdi6580_port_ops = {
static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast) static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast)
{ {
unsigned long ctl = io + 0x206;
struct platform_device *pdev; struct platform_device *pdev;
struct ata_host *host; struct ata_host *host;
struct ata_port *ap; struct ata_port *ap;
@ -254,7 +251,7 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
ret = -ENOMEM; ret = -ENOMEM;
io_addr = devm_ioport_map(&pdev->dev, io, 8); io_addr = devm_ioport_map(&pdev->dev, io, 8);
ctl_addr = devm_ioport_map(&pdev->dev, io + 0x206, 1); ctl_addr = devm_ioport_map(&pdev->dev, ctl, 1);
if (!io_addr || !ctl_addr) if (!io_addr || !ctl_addr)
goto fail; goto fail;
@ -279,6 +276,8 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i
ap->ioaddr.ctl_addr = ctl_addr; ap->ioaddr.ctl_addr = ctl_addr;
ata_std_ports(&ap->ioaddr); ata_std_ports(&ap->ioaddr);
ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl);
/* /*
* Hook in a private data structure per channel * Hook in a private data structure per channel
*/ */

Просмотреть файл

@ -203,7 +203,6 @@ static struct scsi_host_template radisys_sht = {
}; };
static const struct ata_port_operations radisys_pata_ops = { static const struct ata_port_operations radisys_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = radisys_set_piomode, .set_piomode = radisys_set_piomode,
.set_dmamode = radisys_set_dmamode, .set_dmamode = radisys_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -231,9 +230,8 @@ static const struct ata_port_operations radisys_pata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };

Просмотреть файл

@ -26,7 +26,7 @@
/** /**
* rz1000_set_mode - mode setting function * rz1000_set_mode - mode setting function
* @ap: ATA interface * @link: ATA link
* @unused: returned device on set_mode failure * @unused: returned device on set_mode failure
* *
* Use a non standard set_mode function. We don't want to be tuned. We * Use a non standard set_mode function. We don't want to be tuned. We
@ -34,12 +34,11 @@
* whacked out. * whacked out.
*/ */
static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused) static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
int i; struct ata_device *dev;
for (i = 0; i < ATA_MAX_DEVICES; i++) { ata_link_for_each_dev(dev, link) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) { if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
@ -74,7 +73,6 @@ static struct scsi_host_template rz1000_sht = {
static struct ata_port_operations rz1000_port_ops = { static struct ata_port_operations rz1000_port_ops = {
.set_mode = rz1000_set_mode, .set_mode = rz1000_set_mode,
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -100,9 +98,8 @@ static struct ata_port_operations rz1000_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int rz1000_fifo_disable(struct pci_dev *pdev) static int rz1000_fifo_disable(struct pci_dev *pdev)

Просмотреть файл

@ -197,7 +197,6 @@ static struct scsi_host_template sc1200_sht = {
}; };
static struct ata_port_operations sc1200_port_ops = { static struct ata_port_operations sc1200_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = sc1200_set_piomode, .set_piomode = sc1200_set_piomode,
.set_dmamode = sc1200_set_dmamode, .set_dmamode = sc1200_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -227,9 +226,8 @@ static struct ata_port_operations sc1200_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -603,16 +603,17 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
* Note: Original code is ata_std_softreset(). * Note: Original code is ata_std_softreset().
*/ */
static int scc_std_softreset (struct ata_port *ap, unsigned int *classes, static int scc_std_softreset(struct ata_link *link, unsigned int *classes,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
unsigned int devmask = 0, err_mask; unsigned int devmask = 0, err_mask;
u8 err; u8 err;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (ata_port_offline(ap)) { if (ata_link_offline(link)) {
classes[0] = ATA_DEV_NONE; classes[0] = ATA_DEV_NONE;
goto out; goto out;
} }
@ -636,9 +637,11 @@ static int scc_std_softreset (struct ata_port *ap, unsigned int *classes,
} }
/* determine by signature whether we have ATA or ATAPI devices */ /* determine by signature whether we have ATA or ATAPI devices */
classes[0] = ata_dev_try_classify(ap, 0, &err); classes[0] = ata_dev_try_classify(&ap->link.device[0],
devmask & (1 << 0), &err);
if (slave_possible && err != 0x81) if (slave_possible && err != 0x81)
classes[1] = ata_dev_try_classify(ap, 1, &err); classes[1] = ata_dev_try_classify(&ap->link.device[1],
devmask & (1 << 1), &err);
out: out:
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]); DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
@ -701,7 +704,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME); printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT); out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
/* TBD: SW reset */ /* TBD: SW reset */
scc_std_softreset(ap, &classes, deadline); scc_std_softreset(&ap->link, &classes, deadline);
continue; continue;
} }
@ -740,7 +743,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
void __iomem *mmio = ap->ioaddr.bmdma_addr; void __iomem *mmio = ap->ioaddr.bmdma_addr;
u8 host_stat = in_be32(mmio + SCC_DMA_STATUS); u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
u32 int_status = in_be32(mmio + SCC_DMA_INTST); u32 int_status = in_be32(mmio + SCC_DMA_INTST);
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
static int retry = 0; static int retry = 0;
/* return if IOS_SS is cleared */ /* return if IOS_SS is cleared */
@ -785,7 +788,7 @@ static u8 scc_bmdma_status (struct ata_port *ap)
static void scc_data_xfer (struct ata_device *adev, unsigned char *buf, static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data) unsigned int buflen, int write_data)
{ {
struct ata_port *ap = adev->ap; struct ata_port *ap = adev->link->ap;
unsigned int words = buflen >> 1; unsigned int words = buflen >> 1;
unsigned int i; unsigned int i;
u16 *buf16 = (u16 *) buf; u16 *buf16 = (u16 *) buf;
@ -838,38 +841,6 @@ static u8 scc_irq_on (struct ata_port *ap)
return tmp; return tmp;
} }
/**
* scc_irq_ack - Acknowledge a device interrupt.
* @ap: Port on which interrupts are enabled.
*
* Note: Original code is ata_irq_ack().
*/
static u8 scc_irq_ack (struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
u8 host_stat, post_stat, status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
/* get controller status; clear intr, err bits */
host_stat = in_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS);
out_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS,
host_stat | ATA_DMA_INTR | ATA_DMA_ERR);
post_stat = in_be32(ap->ioaddr.bmdma_addr + SCC_DMA_STATUS);
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
return status;
}
/** /**
* scc_bmdma_freeze - Freeze BMDMA controller port * scc_bmdma_freeze - Freeze BMDMA controller port
* @ap: port to freeze * @ap: port to freeze
@ -901,10 +872,10 @@ static void scc_bmdma_freeze (struct ata_port *ap)
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
*/ */
static int scc_pata_prereset(struct ata_port *ap, unsigned long deadline) static int scc_pata_prereset(struct ata_link *link, unsigned long deadline)
{ {
ap->cbl = ATA_CBL_PATA80; link->ap->cbl = ATA_CBL_PATA80;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
/** /**
@ -915,8 +886,10 @@ static int scc_pata_prereset(struct ata_port *ap, unsigned long deadline)
* Note: Original code is ata_std_postreset(). * Note: Original code is ata_std_postreset().
*/ */
static void scc_std_postreset (struct ata_port *ap, unsigned int *classes) static void scc_std_postreset(struct ata_link *link, unsigned int *classes)
{ {
struct ata_port *ap = link->ap;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
/* is double-select really necessary? */ /* is double-select really necessary? */
@ -1020,7 +993,6 @@ static struct scsi_host_template scc_sht = {
}; };
static const struct ata_port_operations scc_pata_ops = { static const struct ata_port_operations scc_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = scc_set_piomode, .set_piomode = scc_set_piomode,
.set_dmamode = scc_set_dmamode, .set_dmamode = scc_set_dmamode,
.mode_filter = scc_mode_filter, .mode_filter = scc_mode_filter,
@ -1047,7 +1019,6 @@ static const struct ata_port_operations scc_pata_ops = {
.irq_clear = scc_bmdma_irq_clear, .irq_clear = scc_bmdma_irq_clear,
.irq_on = scc_irq_on, .irq_on = scc_irq_on,
.irq_ack = scc_irq_ack,
.port_start = scc_port_start, .port_start = scc_port_start,
.port_stop = scc_port_stop, .port_stop = scc_port_stop,
@ -1193,6 +1164,9 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
host->iomap = pcim_iomap_table(pdev); host->iomap = pcim_iomap_table(pdev);
ata_port_pbar_desc(host->ports[0], SCC_CTRL_BAR, -1, "ctrl");
ata_port_pbar_desc(host->ports[0], SCC_BMID_BAR, -1, "bmid");
rc = scc_host_init(host); rc = scc_host_init(host);
if (rc) if (rc)
return rc; return rc;

Просмотреть файл

@ -318,7 +318,6 @@ static struct scsi_host_template serverworks_sht = {
}; };
static struct ata_port_operations serverworks_osb4_port_ops = { static struct ata_port_operations serverworks_osb4_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = serverworks_set_piomode, .set_piomode = serverworks_set_piomode,
.set_dmamode = serverworks_set_dmamode, .set_dmamode = serverworks_set_dmamode,
.mode_filter = serverworks_osb4_filter, .mode_filter = serverworks_osb4_filter,
@ -348,13 +347,11 @@ static struct ata_port_operations serverworks_osb4_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations serverworks_csb_port_ops = { static struct ata_port_operations serverworks_csb_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = serverworks_set_piomode, .set_piomode = serverworks_set_piomode,
.set_dmamode = serverworks_set_dmamode, .set_dmamode = serverworks_set_dmamode,
.mode_filter = serverworks_csb_filter, .mode_filter = serverworks_csb_filter,
@ -384,9 +381,8 @@ static struct ata_port_operations serverworks_csb_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int serverworks_fixup_osb4(struct pci_dev *pdev) static int serverworks_fixup_osb4(struct pci_dev *pdev)

Просмотреть файл

@ -95,15 +95,16 @@ static int sil680_cable_detect(struct ata_port *ap) {
/** /**
* sil680_bus_reset - reset the SIL680 bus * sil680_bus_reset - reset the SIL680 bus
* @ap: ATA port to reset * @link: ATA link to reset
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Perform the SIL680 housekeeping when doing an ATA bus reset * Perform the SIL680 housekeeping when doing an ATA bus reset
*/ */
static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes, static int sil680_bus_reset(struct ata_link *link, unsigned int *classes,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long addr = sil680_selreg(ap, 0); unsigned long addr = sil680_selreg(ap, 0);
u8 reset; u8 reset;
@ -112,7 +113,7 @@ static int sil680_bus_reset(struct ata_port *ap,unsigned int *classes,
pci_write_config_byte(pdev, addr, reset | 0x03); pci_write_config_byte(pdev, addr, reset | 0x03);
udelay(25); udelay(25);
pci_write_config_byte(pdev, addr, reset); pci_write_config_byte(pdev, addr, reset);
return ata_std_softreset(ap, classes, deadline); return ata_std_softreset(link, classes, deadline);
} }
static void sil680_error_handler(struct ata_port *ap) static void sil680_error_handler(struct ata_port *ap)
@ -237,7 +238,6 @@ static struct scsi_host_template sil680_sht = {
}; };
static struct ata_port_operations sil680_port_ops = { static struct ata_port_operations sil680_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = sil680_set_piomode, .set_piomode = sil680_set_piomode,
.set_dmamode = sil680_set_dmamode, .set_dmamode = sil680_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -266,9 +266,8 @@ static struct ata_port_operations sil680_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -84,7 +84,7 @@ static int sis_short_ata40(struct pci_dev *dev)
static int sis_old_port_base(struct ata_device *adev) static int sis_old_port_base(struct ata_device *adev)
{ {
return 0x40 + (4 * adev->ap->port_no) + (2 * adev->devno); return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);
} }
/** /**
@ -133,19 +133,20 @@ static int sis_66_cable_detect(struct ata_port *ap)
/** /**
* sis_pre_reset - probe begin * sis_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int sis_pre_reset(struct ata_port *ap, unsigned long deadline) static int sis_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits sis_enable_bits[] = { static const struct pci_bits sis_enable_bits[] = {
{ 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */
{ 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
@ -154,7 +155,7 @@ static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
/* Clear the FIFO settings. We can't enable the FIFO until /* Clear the FIFO settings. We can't enable the FIFO until
we know we are poking at a disk */ we know we are poking at a disk */
pci_write_config_byte(pdev, 0x4B, 0); pci_write_config_byte(pdev, 0x4B, 0);
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
@ -530,7 +531,6 @@ static struct scsi_host_template sis_sht = {
}; };
static const struct ata_port_operations sis_133_ops = { static const struct ata_port_operations sis_133_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_133_set_piomode, .set_piomode = sis_133_set_piomode,
.set_dmamode = sis_133_set_dmamode, .set_dmamode = sis_133_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -558,13 +558,11 @@ static const struct ata_port_operations sis_133_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations sis_133_for_sata_ops = { static const struct ata_port_operations sis_133_for_sata_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_133_set_piomode, .set_piomode = sis_133_set_piomode,
.set_dmamode = sis_133_set_dmamode, .set_dmamode = sis_133_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -592,13 +590,11 @@ static const struct ata_port_operations sis_133_for_sata_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations sis_133_early_ops = { static const struct ata_port_operations sis_133_early_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_100_set_piomode, .set_piomode = sis_100_set_piomode,
.set_dmamode = sis_133_early_set_dmamode, .set_dmamode = sis_133_early_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -626,13 +622,11 @@ static const struct ata_port_operations sis_133_early_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations sis_100_ops = { static const struct ata_port_operations sis_100_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_100_set_piomode, .set_piomode = sis_100_set_piomode,
.set_dmamode = sis_100_set_dmamode, .set_dmamode = sis_100_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -660,13 +654,11 @@ static const struct ata_port_operations sis_100_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations sis_66_ops = { static const struct ata_port_operations sis_66_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_old_set_piomode, .set_piomode = sis_old_set_piomode,
.set_dmamode = sis_66_set_dmamode, .set_dmamode = sis_66_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -694,13 +686,11 @@ static const struct ata_port_operations sis_66_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_operations sis_old_ops = { static const struct ata_port_operations sis_old_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_old_set_piomode, .set_piomode = sis_old_set_piomode,
.set_dmamode = sis_old_set_dmamode, .set_dmamode = sis_old_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -728,9 +718,8 @@ static const struct ata_port_operations sis_old_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static const struct ata_port_info sis_info = { static const struct ata_port_info sis_info = {

Просмотреть файл

@ -43,23 +43,24 @@ enum {
/** /**
* sl82c105_pre_reset - probe begin * sl82c105_pre_reset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int sl82c105_pre_reset(struct ata_port *ap, unsigned long deadline) static int sl82c105_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits sl82c105_enable_bits[] = { static const struct pci_bits sl82c105_enable_bits[] = {
{ 0x40, 1, 0x01, 0x01 }, { 0x40, 1, 0x01, 0x01 },
{ 0x40, 1, 0x10, 0x10 } { 0x40, 1, 0x10, 0x10 }
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no])) if (ap->port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
@ -224,7 +225,6 @@ static struct scsi_host_template sl82c105_sht = {
}; };
static struct ata_port_operations sl82c105_port_ops = { static struct ata_port_operations sl82c105_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = sl82c105_set_piomode, .set_piomode = sl82c105_set_piomode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -253,9 +253,8 @@ static struct ata_port_operations sl82c105_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -47,25 +47,26 @@
/** /**
* triflex_prereset - probe begin * triflex_prereset - probe begin
* @ap: ATA port * @link: ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* Set up cable type and use generic probe init * Set up cable type and use generic probe init
*/ */
static int triflex_prereset(struct ata_port *ap, unsigned long deadline) static int triflex_prereset(struct ata_link *link, unsigned long deadline)
{ {
static const struct pci_bits triflex_enable_bits[] = { static const struct pci_bits triflex_enable_bits[] = {
{ 0x80, 1, 0x01, 0x01 }, { 0x80, 1, 0x01, 0x01 },
{ 0x80, 1, 0x02, 0x02 } { 0x80, 1, 0x02, 0x02 }
}; };
struct ata_port *ap = link->ap;
struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pci_dev *pdev = to_pci_dev(ap->host->dev);
if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no])) if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
return -ENOENT; return -ENOENT;
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
@ -197,7 +198,6 @@ static struct scsi_host_template triflex_sht = {
}; };
static struct ata_port_operations triflex_port_ops = { static struct ata_port_operations triflex_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = triflex_set_piomode, .set_piomode = triflex_set_piomode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -226,9 +226,8 @@ static struct ata_port_operations triflex_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)

Просмотреть файл

@ -184,11 +184,15 @@ static int via_cable_detect(struct ata_port *ap) {
two drives */ two drives */
if (ata66 & (0x10100000 >> (16 * ap->port_no))) if (ata66 & (0x10100000 >> (16 * ap->port_no)))
return ATA_CBL_PATA80; return ATA_CBL_PATA80;
/* Check with ACPI so we can spot BIOS reported SATA bridges */
if (ata_acpi_cbl_80wire(ap))
return ATA_CBL_PATA80;
return ATA_CBL_PATA40; return ATA_CBL_PATA40;
} }
static int via_pre_reset(struct ata_port *ap, unsigned long deadline) static int via_pre_reset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
const struct via_isa_bridge *config = ap->host->private_data; const struct via_isa_bridge *config = ap->host->private_data;
if (!(config->flags & VIA_NO_ENABLES)) { if (!(config->flags & VIA_NO_ENABLES)) {
@ -201,7 +205,7 @@ static int via_pre_reset(struct ata_port *ap, unsigned long deadline)
return -ENOENT; return -ENOENT;
} }
return ata_std_prereset(ap, deadline); return ata_std_prereset(link, deadline);
} }
@ -344,7 +348,6 @@ static struct scsi_host_template via_sht = {
}; };
static struct ata_port_operations via_port_ops = { static struct ata_port_operations via_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = via_set_piomode, .set_piomode = via_set_piomode,
.set_dmamode = via_set_dmamode, .set_dmamode = via_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -374,13 +377,11 @@ static struct ata_port_operations via_port_ops = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
static struct ata_port_operations via_port_ops_noirq = { static struct ata_port_operations via_port_ops_noirq = {
.port_disable = ata_port_disable,
.set_piomode = via_set_piomode, .set_piomode = via_set_piomode,
.set_dmamode = via_set_dmamode, .set_dmamode = via_set_dmamode,
.mode_filter = ata_pci_default_filter, .mode_filter = ata_pci_default_filter,
@ -410,9 +411,8 @@ static struct ata_port_operations via_port_ops_noirq = {
.irq_handler = ata_interrupt, .irq_handler = ata_interrupt,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**

Просмотреть файл

@ -94,7 +94,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
{ {
struct ata_port *ap = adev->ap; struct ata_port *ap = adev->link->ap;
int slop = buflen & 3; int slop = buflen & 3;
if (ata_id_has_dword_io(adev->id)) { if (ata_id_has_dword_io(adev->id)) {
@ -138,7 +138,6 @@ static struct scsi_host_template winbond_sht = {
}; };
static struct ata_port_operations winbond_port_ops = { static struct ata_port_operations winbond_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = winbond_set_piomode, .set_piomode = winbond_set_piomode,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
@ -160,9 +159,8 @@ static struct ata_port_operations winbond_port_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_sff_port_start,
}; };
/** /**
@ -199,6 +197,7 @@ static __init int winbond_init_one(unsigned long port)
for (i = 0; i < 2 ; i ++) { for (i = 0; i < 2 ; i ++) {
unsigned long cmd_port = 0x1F0 - (0x80 * i); unsigned long cmd_port = 0x1F0 - (0x80 * i);
unsigned long ctl_port = cmd_port + 0x206;
struct ata_host *host; struct ata_host *host;
struct ata_port *ap; struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr; void __iomem *cmd_addr, *ctl_addr;
@ -214,14 +213,16 @@ static __init int winbond_init_one(unsigned long port)
host = ata_host_alloc(&pdev->dev, 1); host = ata_host_alloc(&pdev->dev, 1);
if (!host) if (!host)
goto err_unregister; goto err_unregister;
ap = host->ports[0];
rc = -ENOMEM; rc = -ENOMEM;
cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8); cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8);
ctl_addr = devm_ioport_map(&pdev->dev, cmd_port + 0x0206, 1); ctl_addr = devm_ioport_map(&pdev->dev, ctl_port, 1);
if (!cmd_addr || !ctl_addr) if (!cmd_addr || !ctl_addr)
goto err_unregister; goto err_unregister;
ap = host->ports[0]; ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port);
ap->ops = &winbond_port_ops; ap->ops = &winbond_port_ops;
ap->pio_mask = 0x1F; ap->pio_mask = 0x1F;
ap->flags |= ATA_FLAG_SLAVE_POSS; ap->flags |= ATA_FLAG_SLAVE_POSS;

Просмотреть файл

@ -92,6 +92,8 @@ enum {
/* CPB bits */ /* CPB bits */
cDONE = (1 << 0), cDONE = (1 << 0),
cATERR = (1 << 3),
cVLD = (1 << 0), cVLD = (1 << 0),
cDAT = (1 << 2), cDAT = (1 << 2),
cIEN = (1 << 3), cIEN = (1 << 3),
@ -131,14 +133,15 @@ static int adma_ata_init_one (struct pci_dev *pdev,
static int adma_port_start(struct ata_port *ap); static int adma_port_start(struct ata_port *ap);
static void adma_host_stop(struct ata_host *host); static void adma_host_stop(struct ata_host *host);
static void adma_port_stop(struct ata_port *ap); static void adma_port_stop(struct ata_port *ap);
static void adma_phy_reset(struct ata_port *ap);
static void adma_qc_prep(struct ata_queued_cmd *qc); static void adma_qc_prep(struct ata_queued_cmd *qc);
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc); static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
static int adma_check_atapi_dma(struct ata_queued_cmd *qc); static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
static void adma_bmdma_stop(struct ata_queued_cmd *qc); static void adma_bmdma_stop(struct ata_queued_cmd *qc);
static u8 adma_bmdma_status(struct ata_port *ap); static u8 adma_bmdma_status(struct ata_port *ap);
static void adma_irq_clear(struct ata_port *ap); static void adma_irq_clear(struct ata_port *ap);
static void adma_eng_timeout(struct ata_port *ap); static void adma_freeze(struct ata_port *ap);
static void adma_thaw(struct ata_port *ap);
static void adma_error_handler(struct ata_port *ap);
static struct scsi_host_template adma_ata_sht = { static struct scsi_host_template adma_ata_sht = {
.module = THIS_MODULE, .module = THIS_MODULE,
@ -159,21 +162,20 @@ static struct scsi_host_template adma_ata_sht = {
}; };
static const struct ata_port_operations adma_ata_ops = { static const struct ata_port_operations adma_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
.check_status = ata_check_status, .check_status = ata_check_status,
.dev_select = ata_std_dev_select, .dev_select = ata_std_dev_select,
.phy_reset = adma_phy_reset,
.check_atapi_dma = adma_check_atapi_dma, .check_atapi_dma = adma_check_atapi_dma,
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.qc_prep = adma_qc_prep, .qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue, .qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout, .freeze = adma_freeze,
.thaw = adma_thaw,
.error_handler = adma_error_handler,
.irq_clear = adma_irq_clear, .irq_clear = adma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = adma_port_start, .port_start = adma_port_start,
.port_stop = adma_port_stop, .port_stop = adma_port_stop,
.host_stop = adma_host_stop, .host_stop = adma_host_stop,
@ -184,7 +186,7 @@ static const struct ata_port_operations adma_ata_ops = {
static struct ata_port_info adma_port_info[] = { static struct ata_port_info adma_port_info[] = {
/* board_1841_idx */ /* board_1841_idx */
{ {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | .flags = ATA_FLAG_SLAVE_POSS |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING, ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */ .pio_mask = 0x10, /* pio4 */
@ -273,24 +275,42 @@ static inline void adma_enter_reg_mode(struct ata_port *ap)
readb(chan + ADMA_STATUS); /* flush */ readb(chan + ADMA_STATUS); /* flush */
} }
static void adma_phy_reset(struct ata_port *ap) static void adma_freeze(struct ata_port *ap)
{ {
struct adma_port_priv *pp = ap->private_data; void __iomem *chan = ADMA_PORT_REGS(ap);
pp->state = adma_state_idle; /* mask/clear ATA interrupts */
adma_reinit_engine(ap); writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
ata_port_probe(ap); ata_check_status(ap);
ata_bus_reset(ap);
/* reset ADMA to idle state */
writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
udelay(2);
writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
udelay(2);
} }
static void adma_eng_timeout(struct ata_port *ap) static void adma_thaw(struct ata_port *ap)
{ {
adma_reinit_engine(ap);
}
static int adma_prereset(struct ata_link *link, unsigned long deadline)
{
struct ata_port *ap = link->ap;
struct adma_port_priv *pp = ap->private_data; struct adma_port_priv *pp = ap->private_data;
if (pp->state != adma_state_idle) /* healthy paranoia */ if (pp->state != adma_state_idle) /* healthy paranoia */
pp->state = adma_state_mmio; pp->state = adma_state_mmio;
adma_reinit_engine(ap); adma_reinit_engine(ap);
ata_eng_timeout(ap);
return ata_std_prereset(link, deadline);
}
static void adma_error_handler(struct ata_port *ap)
{
ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
ata_std_postreset);
} }
static int adma_fill_sg(struct ata_queued_cmd *qc) static int adma_fill_sg(struct ata_queued_cmd *qc)
@ -464,14 +484,33 @@ static inline unsigned int adma_intr_pkt(struct ata_host *host)
pp = ap->private_data; pp = ap->private_data;
if (!pp || pp->state != adma_state_pkt) if (!pp || pp->state != adma_state_pkt)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
if ((status & (aPERR | aPSD | aUIRQ))) if (status & aPERR)
qc->err_mask |= AC_ERR_HOST_BUS;
else if ((status & (aPSD | aUIRQ)))
qc->err_mask |= AC_ERR_OTHER; qc->err_mask |= AC_ERR_OTHER;
if (pp->pkt[0] & cATERR)
qc->err_mask |= AC_ERR_DEV;
else if (pp->pkt[0] != cDONE) else if (pp->pkt[0] != cDONE)
qc->err_mask |= AC_ERR_OTHER; qc->err_mask |= AC_ERR_OTHER;
ata_qc_complete(qc); if (!qc->err_mask)
ata_qc_complete(qc);
else {
struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi,
"ADMA-status 0x%02X", status);
ata_ehi_push_desc(ehi,
"pkt[0] 0x%02X", pp->pkt[0]);
if (qc->err_mask == AC_ERR_DEV)
ata_port_abort(ap);
else
ata_port_freeze(ap);
}
} }
} }
return handled; return handled;
@ -489,7 +528,7 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
struct adma_port_priv *pp = ap->private_data; struct adma_port_priv *pp = ap->private_data;
if (!pp || pp->state != adma_state_mmio) if (!pp || pp->state != adma_state_mmio)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */ /* check main status, clearing INTRQ */
@ -502,7 +541,20 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
/* complete taskfile transaction */ /* complete taskfile transaction */
pp->state = adma_state_idle; pp->state = adma_state_idle;
qc->err_mask |= ac_err_mask(status); qc->err_mask |= ac_err_mask(status);
ata_qc_complete(qc); if (!qc->err_mask)
ata_qc_complete(qc);
else {
struct ata_eh_info *ehi =
&ap->link.eh_info;
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi,
"status 0x%02X", status);
if (qc->err_mask == AC_ERR_DEV)
ata_port_abort(ap);
else
ata_port_freeze(ap);
}
handled = 1; handled = 1;
} }
} }
@ -652,9 +704,16 @@ static int adma_ata_init_one(struct pci_dev *pdev,
if (rc) if (rc)
return rc; return rc;
for (port_no = 0; port_no < ADMA_PORTS; ++port_no) for (port_no = 0; port_no < ADMA_PORTS; ++port_no) {
adma_ata_setup_port(&host->ports[port_no]->ioaddr, struct ata_port *ap = host->ports[port_no];
ADMA_ATA_REGS(mmio_base, port_no)); void __iomem *port_base = ADMA_ATA_REGS(mmio_base, port_no);
unsigned int offset = port_base - mmio_base;
adma_ata_setup_port(&ap->ioaddr, port_base);
ata_port_pbar_desc(ap, ADMA_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, ADMA_MMIO_BAR, offset, "port");
}
/* initialize adapter */ /* initialize adapter */
adma_host_init(host, board_idx); adma_host_init(host, board_idx);

Просмотреть файл

@ -285,7 +285,7 @@ static void inic_irq_clear(struct ata_port *ap)
static void inic_host_intr(struct ata_port *ap) static void inic_host_intr(struct ata_port *ap)
{ {
void __iomem *port_base = inic_port_base(ap); void __iomem *port_base = inic_port_base(ap);
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
u8 irq_stat; u8 irq_stat;
/* fetch and clear irq */ /* fetch and clear irq */
@ -293,7 +293,8 @@ static void inic_host_intr(struct ata_port *ap)
writeb(irq_stat, port_base + PORT_IRQ_STAT); writeb(irq_stat, port_base + PORT_IRQ_STAT);
if (likely(!(irq_stat & PIRQ_ERR))) { if (likely(!(irq_stat & PIRQ_ERR))) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct ata_queued_cmd *qc =
ata_qc_from_tag(ap, ap->link.active_tag);
if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
ata_chk_status(ap); /* clear ATA interrupt */ ata_chk_status(ap); /* clear ATA interrupt */
@ -416,12 +417,13 @@ static void inic_thaw(struct ata_port *ap)
* SRST and SControl hardreset don't give valid signature on this * SRST and SControl hardreset don't give valid signature on this
* controller. Only controller specific hardreset mechanism works. * controller. Only controller specific hardreset mechanism works.
*/ */
static int inic_hardreset(struct ata_port *ap, unsigned int *class, static int inic_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
void __iomem *port_base = inic_port_base(ap); void __iomem *port_base = inic_port_base(ap);
void __iomem *idma_ctl = port_base + PORT_IDMA_CTL; void __iomem *idma_ctl = port_base + PORT_IDMA_CTL;
const unsigned long *timing = sata_ehc_deb_timing(&ap->eh_context); const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
u16 val; u16 val;
int rc; int rc;
@ -434,15 +436,15 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class,
msleep(1); msleep(1);
writew(val & ~IDMA_CTL_RST_ATA, idma_ctl); writew(val & ~IDMA_CTL_RST_ATA, idma_ctl);
rc = sata_phy_resume(ap, timing, deadline); rc = sata_link_resume(link, timing, deadline);
if (rc) { if (rc) {
ata_port_printk(ap, KERN_WARNING, "failed to resume " ata_link_printk(link, KERN_WARNING, "failed to resume "
"link after reset (errno=%d)\n", rc); "link after reset (errno=%d)\n", rc);
return rc; return rc;
} }
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
if (ata_port_online(ap)) { if (ata_link_online(link)) {
struct ata_taskfile tf; struct ata_taskfile tf;
/* wait a while before checking status */ /* wait a while before checking status */
@ -451,7 +453,7 @@ static int inic_hardreset(struct ata_port *ap, unsigned int *class,
rc = ata_wait_ready(ap, deadline); rc = ata_wait_ready(ap, deadline);
/* link occupied, -ENODEV too is an error */ /* link occupied, -ENODEV too is an error */
if (rc) { if (rc) {
ata_port_printk(ap, KERN_WARNING, "device not ready " ata_link_printk(link, KERN_WARNING, "device not ready "
"after hardreset (errno=%d)\n", rc); "after hardreset (errno=%d)\n", rc);
return rc; return rc;
} }
@ -550,7 +552,6 @@ static int inic_port_start(struct ata_port *ap)
} }
static struct ata_port_operations inic_port_ops = { static struct ata_port_operations inic_port_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -567,7 +568,6 @@ static struct ata_port_operations inic_port_ops = {
.irq_clear = inic_irq_clear, .irq_clear = inic_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = inic_qc_issue, .qc_issue = inic_qc_issue,
@ -693,16 +693,24 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = iomap = pcim_iomap_table(pdev); host->iomap = iomap = pcim_iomap_table(pdev);
for (i = 0; i < NR_PORTS; i++) { for (i = 0; i < NR_PORTS; i++) {
struct ata_ioports *port = &host->ports[i]->ioaddr; struct ata_port *ap = host->ports[i];
void __iomem *port_base = iomap[MMIO_BAR] + i * PORT_SIZE; struct ata_ioports *port = &ap->ioaddr;
unsigned int offset = i * PORT_SIZE;
port->cmd_addr = iomap[2 * i]; port->cmd_addr = iomap[2 * i];
port->altstatus_addr = port->altstatus_addr =
port->ctl_addr = (void __iomem *) port->ctl_addr = (void __iomem *)
((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS); ((unsigned long)iomap[2 * i + 1] | ATA_PCI_CTL_OFS);
port->scr_addr = port_base + PORT_SCR; port->scr_addr = iomap[MMIO_BAR] + offset + PORT_SCR;
ata_std_ports(port); ata_std_ports(port);
ata_port_pbar_desc(ap, MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, MMIO_BAR, offset, "port");
ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
(unsigned long long)pci_resource_start(pdev, 2 * i),
(unsigned long long)pci_resource_start(pdev, (2 * i + 1)) |
ATA_PCI_CTL_OFS);
} }
hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL); hpriv->cached_hctl = readw(iomap[MMIO_BAR] + HOST_CTL);

Просмотреть файл

@ -483,8 +483,6 @@ static struct scsi_host_template mv6_sht = {
}; };
static const struct ata_port_operations mv5_ops = { static const struct ata_port_operations mv5_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -499,7 +497,6 @@ static const struct ata_port_operations mv5_ops = {
.irq_clear = mv_irq_clear, .irq_clear = mv_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.error_handler = mv_error_handler, .error_handler = mv_error_handler,
.post_internal_cmd = mv_post_int_cmd, .post_internal_cmd = mv_post_int_cmd,
@ -514,8 +511,6 @@ static const struct ata_port_operations mv5_ops = {
}; };
static const struct ata_port_operations mv6_ops = { static const struct ata_port_operations mv6_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -530,7 +525,6 @@ static const struct ata_port_operations mv6_ops = {
.irq_clear = mv_irq_clear, .irq_clear = mv_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.error_handler = mv_error_handler, .error_handler = mv_error_handler,
.post_internal_cmd = mv_post_int_cmd, .post_internal_cmd = mv_post_int_cmd,
@ -545,8 +539,6 @@ static const struct ata_port_operations mv6_ops = {
}; };
static const struct ata_port_operations mv_iie_ops = { static const struct ata_port_operations mv_iie_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -561,7 +553,6 @@ static const struct ata_port_operations mv_iie_ops = {
.irq_clear = mv_irq_clear, .irq_clear = mv_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.error_handler = mv_error_handler, .error_handler = mv_error_handler,
.post_internal_cmd = mv_post_int_cmd, .post_internal_cmd = mv_post_int_cmd,
@ -1415,7 +1406,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
struct mv_host_priv *hpriv = ap->host->private_data; struct mv_host_priv *hpriv = ap->host->private_data;
unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN); unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
unsigned int action = 0, err_mask = 0; unsigned int action = 0, err_mask = 0;
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
@ -1423,8 +1414,8 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
/* just a guess: do we need to do this? should we /* just a guess: do we need to do this? should we
* expand this, and do it in all cases? * expand this, and do it in all cases?
*/ */
sata_scr_read(ap, SCR_ERROR, &serr); sata_scr_read(&ap->link, SCR_ERROR, &serr);
sata_scr_write_flush(ap, SCR_ERROR, serr); sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
} }
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@ -1468,8 +1459,8 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
} }
if (edma_err_cause & EDMA_ERR_SERR) { if (edma_err_cause & EDMA_ERR_SERR) {
sata_scr_read(ap, SCR_ERROR, &serr); sata_scr_read(&ap->link, SCR_ERROR, &serr);
sata_scr_write_flush(ap, SCR_ERROR, serr); sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
err_mask = AC_ERR_ATA_BUS; err_mask = AC_ERR_ATA_BUS;
action |= ATA_EH_HARDRESET; action |= ATA_EH_HARDRESET;
} }
@ -1508,7 +1499,7 @@ static void mv_intr_pio(struct ata_port *ap)
return; return;
/* get active ATA command */ /* get active ATA command */
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (unlikely(!qc)) /* no active tag */ if (unlikely(!qc)) /* no active tag */
return; return;
if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */ if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */
@ -1543,7 +1534,7 @@ static void mv_intr_edma(struct ata_port *ap)
/* 50xx: get active ATA command */ /* 50xx: get active ATA command */
if (IS_GEN_I(hpriv)) if (IS_GEN_I(hpriv))
tag = ap->active_tag; tag = ap->link.active_tag;
/* Gen II/IIE: get active ATA command via tag, to enable /* Gen II/IIE: get active ATA command via tag, to enable
* support for queueing. this works transparently for * support for queueing. this works transparently for
@ -1646,7 +1637,7 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
if (unlikely(have_err_bits)) { if (unlikely(have_err_bits)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
continue; continue;
@ -1687,15 +1678,15 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
ap = host->ports[i]; ap = host->ports[i];
if (!ata_port_offline(ap)) { if (!ata_link_offline(&ap->link)) {
ehi = &ap->eh_info; ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
if (!printed++) if (!printed++)
ata_ehi_push_desc(ehi, ata_ehi_push_desc(ehi,
"PCI err cause 0x%08x", err_cause); "PCI err cause 0x%08x", err_cause);
err_mask = AC_ERR_HOST_BUS; err_mask = AC_ERR_HOST_BUS;
ehi->action = ATA_EH_HARDRESET; ehi->action = ATA_EH_HARDRESET;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc) if (qc)
qc->err_mask |= err_mask; qc->err_mask |= err_mask;
else else
@ -2198,14 +2189,14 @@ static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
/* Issue COMRESET via SControl */ /* Issue COMRESET via SControl */
comreset_retry: comreset_retry:
sata_scr_write_flush(ap, SCR_CONTROL, 0x301); sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x301);
msleep(1); msleep(1);
sata_scr_write_flush(ap, SCR_CONTROL, 0x300); sata_scr_write_flush(&ap->link, SCR_CONTROL, 0x300);
msleep(20); msleep(20);
do { do {
sata_scr_read(ap, SCR_STATUS, &sstatus); sata_scr_read(&ap->link, SCR_STATUS, &sstatus);
if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
break; break;
@ -2230,7 +2221,7 @@ comreset_retry:
} }
#endif #endif
if (ata_port_offline(ap)) { if (ata_link_offline(&ap->link)) {
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
return; return;
} }
@ -2257,7 +2248,7 @@ comreset_retry:
*/ */
/* finally, read device signature from TF registers */ /* finally, read device signature from TF registers */
*class = ata_dev_try_classify(ap, 0, NULL); *class = ata_dev_try_classify(ap->link.device, 1, NULL);
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
@ -2266,10 +2257,11 @@ comreset_retry:
VPRINTK("EXIT\n"); VPRINTK("EXIT\n");
} }
static int mv_prereset(struct ata_port *ap, unsigned long deadline) static int mv_prereset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct mv_port_priv *pp = ap->private_data; struct mv_port_priv *pp = ap->private_data;
struct ata_eh_context *ehc = &ap->eh_context; struct ata_eh_context *ehc = &link->eh_context;
int rc; int rc;
rc = mv_stop_dma(ap); rc = mv_stop_dma(ap);
@ -2285,7 +2277,7 @@ static int mv_prereset(struct ata_port *ap, unsigned long deadline)
if (ehc->i.action & ATA_EH_HARDRESET) if (ehc->i.action & ATA_EH_HARDRESET)
return 0; return 0;
if (ata_port_online(ap)) if (ata_link_online(link))
rc = ata_wait_ready(ap, deadline); rc = ata_wait_ready(ap, deadline);
else else
rc = -ENODEV; rc = -ENODEV;
@ -2293,9 +2285,10 @@ static int mv_prereset(struct ata_port *ap, unsigned long deadline)
return rc; return rc;
} }
static int mv_hardreset(struct ata_port *ap, unsigned int *class, static int mv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
struct mv_host_priv *hpriv = ap->host->private_data; struct mv_host_priv *hpriv = ap->host->private_data;
void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
@ -2308,16 +2301,17 @@ static int mv_hardreset(struct ata_port *ap, unsigned int *class,
return 0; return 0;
} }
static void mv_postreset(struct ata_port *ap, unsigned int *classes) static void mv_postreset(struct ata_link *link, unsigned int *classes)
{ {
struct ata_port *ap = link->ap;
u32 serr; u32 serr;
/* print link status */ /* print link status */
sata_print_link_status(ap); sata_print_link_status(link);
/* clear SError */ /* clear SError */
sata_scr_read(ap, SCR_ERROR, &serr); sata_scr_read(link, SCR_ERROR, &serr);
sata_scr_write_flush(ap, SCR_ERROR, serr); sata_scr_write_flush(link, SCR_ERROR, serr);
/* bail out if no device is present */ /* bail out if no device is present */
if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
@ -2590,8 +2584,14 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
} }
for (port = 0; port < host->n_ports; port++) { for (port = 0; port < host->n_ports; port++) {
struct ata_port *ap = host->ports[port];
void __iomem *port_mmio = mv_port_base(mmio, port); void __iomem *port_mmio = mv_port_base(mmio, port);
mv_port_init(&host->ports[port]->ioaddr, port_mmio); unsigned int offset = port_mmio - mmio;
mv_port_init(&ap->ioaddr, port_mmio);
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
} }
for (hc = 0; hc < n_hc; hc++) { for (hc = 0; hc < n_hc; hc++) {

Просмотреть файл

@ -340,7 +340,6 @@ static struct scsi_host_template nv_adma_sht = {
}; };
static const struct ata_port_operations nv_generic_ops = { static const struct ata_port_operations nv_generic_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
@ -359,14 +358,12 @@ static const struct ata_port_operations nv_generic_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = nv_scr_read, .scr_read = nv_scr_read,
.scr_write = nv_scr_write, .scr_write = nv_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations nv_nf2_ops = { static const struct ata_port_operations nv_nf2_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
@ -385,14 +382,12 @@ static const struct ata_port_operations nv_nf2_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = nv_scr_read, .scr_read = nv_scr_read,
.scr_write = nv_scr_write, .scr_write = nv_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations nv_ck804_ops = { static const struct ata_port_operations nv_ck804_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
@ -411,7 +406,6 @@ static const struct ata_port_operations nv_ck804_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = nv_scr_read, .scr_read = nv_scr_read,
.scr_write = nv_scr_write, .scr_write = nv_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
@ -419,7 +413,6 @@ static const struct ata_port_operations nv_ck804_ops = {
}; };
static const struct ata_port_operations nv_adma_ops = { static const struct ata_port_operations nv_adma_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = nv_adma_tf_read, .tf_read = nv_adma_tf_read,
.check_atapi_dma = nv_adma_check_atapi_dma, .check_atapi_dma = nv_adma_check_atapi_dma,
@ -430,6 +423,7 @@ static const struct ata_port_operations nv_adma_ops = {
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop, .bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status, .bmdma_status = ata_bmdma_status,
.qc_defer = ata_std_qc_defer,
.qc_prep = nv_adma_qc_prep, .qc_prep = nv_adma_qc_prep,
.qc_issue = nv_adma_qc_issue, .qc_issue = nv_adma_qc_issue,
.freeze = nv_adma_freeze, .freeze = nv_adma_freeze,
@ -439,7 +433,6 @@ static const struct ata_port_operations nv_adma_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = nv_adma_irq_clear, .irq_clear = nv_adma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = nv_scr_read, .scr_read = nv_scr_read,
.scr_write = nv_scr_write, .scr_write = nv_scr_write,
.port_start = nv_adma_port_start, .port_start = nv_adma_port_start,
@ -455,8 +448,8 @@ static const struct ata_port_info nv_port_info[] = {
/* generic */ /* generic */
{ {
.sht = &nv_sht, .sht = &nv_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
ATA_FLAG_HRST_TO_RESUME, .link_flags = ATA_LFLAG_HRST_TO_RESUME,
.pio_mask = NV_PIO_MASK, .pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK, .mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK, .udma_mask = NV_UDMA_MASK,
@ -466,8 +459,8 @@ static const struct ata_port_info nv_port_info[] = {
/* nforce2/3 */ /* nforce2/3 */
{ {
.sht = &nv_sht, .sht = &nv_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
ATA_FLAG_HRST_TO_RESUME, .link_flags = ATA_LFLAG_HRST_TO_RESUME,
.pio_mask = NV_PIO_MASK, .pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK, .mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK, .udma_mask = NV_UDMA_MASK,
@ -477,8 +470,8 @@ static const struct ata_port_info nv_port_info[] = {
/* ck804 */ /* ck804 */
{ {
.sht = &nv_sht, .sht = &nv_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
ATA_FLAG_HRST_TO_RESUME, .link_flags = ATA_LFLAG_HRST_TO_RESUME,
.pio_mask = NV_PIO_MASK, .pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK, .mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK, .udma_mask = NV_UDMA_MASK,
@ -489,8 +482,8 @@ static const struct ata_port_info nv_port_info[] = {
{ {
.sht = &nv_adma_sht, .sht = &nv_adma_sht,
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_HRST_TO_RESUME |
ATA_FLAG_MMIO | ATA_FLAG_NCQ, ATA_FLAG_MMIO | ATA_FLAG_NCQ,
.link_flags = ATA_LFLAG_HRST_TO_RESUME,
.pio_mask = NV_PIO_MASK, .pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK, .mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK, .udma_mask = NV_UDMA_MASK,
@ -594,7 +587,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
/* Not a proper libata device, ignore */ /* Not a proper libata device, ignore */
return rc; return rc;
if (ap->device[sdev->id].class == ATA_DEV_ATAPI) { if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
/* /*
* NVIDIA reports that ADMA mode does not support ATAPI commands. * NVIDIA reports that ADMA mode does not support ATAPI commands.
* Therefore ATAPI commands are sent through the legacy interface. * Therefore ATAPI commands are sent through the legacy interface.
@ -711,7 +704,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
flags & (NV_CPB_RESP_ATA_ERR | flags & (NV_CPB_RESP_ATA_ERR |
NV_CPB_RESP_CMD_ERR | NV_CPB_RESP_CMD_ERR |
NV_CPB_RESP_CPB_ERR)))) { NV_CPB_RESP_CPB_ERR)))) {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
int freeze = 0; int freeze = 0;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
@ -747,7 +740,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
DPRINTK("Completing qc from tag %d\n",cpb_num); DPRINTK("Completing qc from tag %d\n",cpb_num);
ata_qc_complete(qc); ata_qc_complete(qc);
} else { } else {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
/* Notifier bits set without a command may indicate the drive /* Notifier bits set without a command may indicate the drive
is misbehaving. Raise host state machine violation on this is misbehaving. Raise host state machine violation on this
condition. */ condition. */
@ -764,7 +757,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
static int nv_host_intr(struct ata_port *ap, u8 irq_stat) static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
{ {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
/* freeze if hotplugged */ /* freeze if hotplugged */
if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
@ -817,7 +810,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
>> (NV_INT_PORT_SHIFT * i); >> (NV_INT_PORT_SHIFT * i);
if(ata_tag_valid(ap->active_tag)) if(ata_tag_valid(ap->link.active_tag))
/** NV_INT_DEV indication seems unreliable at times /** NV_INT_DEV indication seems unreliable at times
at least in ADMA mode. Force it on always when a at least in ADMA mode. Force it on always when a
command is active, to prevent losing interrupts. */ command is active, to prevent losing interrupts. */
@ -852,7 +845,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
NV_ADMA_STAT_HOTUNPLUG | NV_ADMA_STAT_HOTUNPLUG |
NV_ADMA_STAT_TIMEOUT | NV_ADMA_STAT_TIMEOUT |
NV_ADMA_STAT_SERROR))) { NV_ADMA_STAT_SERROR))) {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
__ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status ); __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status );
@ -879,10 +872,10 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
u32 check_commands; u32 check_commands;
int pos, error = 0; int pos, error = 0;
if(ata_tag_valid(ap->active_tag)) if(ata_tag_valid(ap->link.active_tag))
check_commands = 1 << ap->active_tag; check_commands = 1 << ap->link.active_tag;
else else
check_commands = ap->sactive; check_commands = ap->link.sactive;
/** Check CPBs for completed commands */ /** Check CPBs for completed commands */
while ((pos = ffs(check_commands)) && !error) { while ((pos = ffs(check_commands)) && !error) {
@ -1333,7 +1326,7 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
!(ap->flags & ATA_FLAG_DISABLED)) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += ata_host_intr(ap, qc); handled += ata_host_intr(ap, qc);
else else
@ -1459,7 +1452,7 @@ static void nv_ck804_thaw(struct ata_port *ap)
writeb(mask, mmio_base + NV_INT_ENABLE_CK804); writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
} }
static int nv_hardreset(struct ata_port *ap, unsigned int *class, static int nv_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
unsigned int dummy; unsigned int dummy;
@ -1468,7 +1461,7 @@ static int nv_hardreset(struct ata_port *ap, unsigned int *class,
* some controllers. Don't classify on hardreset. For more * some controllers. Don't classify on hardreset. For more
* info, see http://bugme.osdl.org/show_bug.cgi?id=3352 * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
*/ */
return sata_std_hardreset(ap, &dummy, deadline); return sata_std_hardreset(link, &dummy, deadline);
} }
static void nv_error_handler(struct ata_port *ap) static void nv_error_handler(struct ata_port *ap)
@ -1485,7 +1478,7 @@ static void nv_adma_error_handler(struct ata_port *ap)
int i; int i;
u16 tmp; u16 tmp;
if(ata_tag_valid(ap->active_tag) || ap->sactive) { if(ata_tag_valid(ap->link.active_tag) || ap->link.sactive) {
u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL); u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
@ -1501,8 +1494,8 @@ static void nv_adma_error_handler(struct ata_port *ap)
for( i=0;i<NV_ADMA_MAX_CPBS;i++) { for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
struct nv_adma_cpb *cpb = &pp->cpb[i]; struct nv_adma_cpb *cpb = &pp->cpb[i];
if( (ata_tag_valid(ap->active_tag) && i == ap->active_tag) || if( (ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||
ap->sactive & (1 << i) ) ap->link.sactive & (1 << i) )
ata_port_printk(ap, KERN_ERR, ata_port_printk(ap, KERN_ERR,
"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n", "CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
i, cpb->ctl_flags, cpb->resp_flags); i, cpb->ctl_flags, cpb->resp_flags);

Просмотреть файл

@ -167,7 +167,6 @@ static struct scsi_host_template pdc_ata_sht = {
}; };
static const struct ata_port_operations pdc_sata_ops = { static const struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -185,7 +184,6 @@ static const struct ata_port_operations pdc_sata_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = pdc_irq_clear, .irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = pdc_sata_scr_read, .scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write, .scr_write = pdc_sata_scr_write,
@ -194,7 +192,6 @@ static const struct ata_port_operations pdc_sata_ops = {
/* First-generation chips need a more restrictive ->check_atapi_dma op */ /* First-generation chips need a more restrictive ->check_atapi_dma op */
static const struct ata_port_operations pdc_old_sata_ops = { static const struct ata_port_operations pdc_old_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -212,7 +209,6 @@ static const struct ata_port_operations pdc_old_sata_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = pdc_irq_clear, .irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = pdc_sata_scr_read, .scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write, .scr_write = pdc_sata_scr_write,
@ -220,7 +216,6 @@ static const struct ata_port_operations pdc_old_sata_ops = {
}; };
static const struct ata_port_operations pdc_pata_ops = { static const struct ata_port_operations pdc_pata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -238,7 +233,6 @@ static const struct ata_port_operations pdc_pata_ops = {
.data_xfer = ata_data_xfer, .data_xfer = ata_data_xfer,
.irq_clear = pdc_irq_clear, .irq_clear = pdc_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = pdc_common_port_start, .port_start = pdc_common_port_start,
}; };
@ -475,7 +469,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
buf32[2] = 0; /* no next-packet */ buf32[2] = 0; /* no next-packet */
/* select drive */ /* select drive */
if (sata_scr_valid(ap)) { if (sata_scr_valid(&ap->link)) {
dev_sel = PDC_DEVICE_SATA; dev_sel = PDC_DEVICE_SATA;
} else { } else {
dev_sel = ATA_DEVICE_OBS; dev_sel = ATA_DEVICE_OBS;
@ -626,7 +620,7 @@ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
u32 port_status, u32 err_mask) u32 port_status, u32 err_mask)
{ {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
unsigned int ac_err_mask = 0; unsigned int ac_err_mask = 0;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
@ -643,7 +637,7 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
| PDC_PCI_SYS_ERR | PDC1_PCI_PARITY_ERR)) | PDC_PCI_SYS_ERR | PDC1_PCI_PARITY_ERR))
ac_err_mask |= AC_ERR_HOST_BUS; ac_err_mask |= AC_ERR_HOST_BUS;
if (sata_scr_valid(ap)) { if (sata_scr_valid(&ap->link)) {
u32 serror; u32 serror;
pdc_sata_scr_read(ap, SCR_ERROR, &serror); pdc_sata_scr_read(ap, SCR_ERROR, &serror);
@ -773,7 +767,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
tmp = hotplug_status & (0x11 << ata_no); tmp = hotplug_status & (0x11 << ata_no);
if (tmp && ap && if (tmp && ap &&
!(ap->flags & ATA_FLAG_DISABLED)) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
ata_ehi_hotplugged(ehi); ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp); ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
@ -788,7 +782,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
!(ap->flags & ATA_FLAG_DISABLED)) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc_host_intr(ap, qc); handled += pdc_host_intr(ap, qc);
} }
@ -1009,10 +1003,15 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
pdc_ata_setup_port(host->ports[i], unsigned int port_offset = 0x200 + ata_no * 0x80;
base + 0x200 + ata_no * 0x80, unsigned int scr_offset = 0x400 + ata_no * 0x100;
base + 0x400 + ata_no * 0x100);
pdc_ata_setup_port(ap, base + port_offset, base + scr_offset);
ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, PDC_MMIO_BAR, port_offset, "port");
} }
/* initialize adapter */ /* initialize adapter */

Просмотреть файл

@ -145,7 +145,6 @@ static struct scsi_host_template qs_ata_sht = {
}; };
static const struct ata_port_operations qs_ata_ops = { static const struct ata_port_operations qs_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -159,7 +158,6 @@ static const struct ata_port_operations qs_ata_ops = {
.eng_timeout = qs_eng_timeout, .eng_timeout = qs_eng_timeout,
.irq_clear = qs_irq_clear, .irq_clear = qs_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = qs_scr_read, .scr_read = qs_scr_read,
.scr_write = qs_scr_write, .scr_write = qs_scr_write,
.port_start = qs_port_start, .port_start = qs_port_start,
@ -404,7 +402,7 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host)
struct qs_port_priv *pp = ap->private_data; struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_pkt) if (!pp || pp->state != qs_state_pkt)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
switch (sHST) { switch (sHST) {
case 0: /* successful CPB */ case 0: /* successful CPB */
@ -437,7 +435,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host)
struct qs_port_priv *pp = ap->private_data; struct qs_port_priv *pp = ap->private_data;
if (!pp || pp->state != qs_state_mmio) if (!pp || pp->state != qs_state_mmio)
continue; continue;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
/* check main status, clearing INTRQ */ /* check main status, clearing INTRQ */
@ -637,9 +635,14 @@ static int qs_ata_init_one(struct pci_dev *pdev,
return rc; return rc;
for (port_no = 0; port_no < host->n_ports; ++port_no) { for (port_no = 0; port_no < host->n_ports; ++port_no) {
void __iomem *chan = struct ata_port *ap = host->ports[port_no];
host->iomap[QS_MMIO_BAR] + (port_no * 0x4000); unsigned int offset = port_no * 0x4000;
qs_ata_setup_port(&host->ports[port_no]->ioaddr, chan); void __iomem *chan = host->iomap[QS_MMIO_BAR] + offset;
qs_ata_setup_port(&ap->ioaddr, chan);
ata_port_pbar_desc(ap, QS_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, QS_MMIO_BAR, offset, "port");
} }
/* initialize adapter */ /* initialize adapter */

Просмотреть файл

@ -59,7 +59,8 @@ enum {
SIL_FLAG_MOD15WRITE = (1 << 30), SIL_FLAG_MOD15WRITE = (1 << 30),
SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME, ATA_FLAG_MMIO,
SIL_DFL_LINK_FLAGS = ATA_LFLAG_HRST_TO_RESUME,
/* /*
* Controller IDs * Controller IDs
@ -117,7 +118,7 @@ static int sil_pci_device_resume(struct pci_dev *pdev);
static void sil_dev_config(struct ata_device *dev); static void sil_dev_config(struct ata_device *dev);
static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int sil_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int sil_set_mode (struct ata_port *ap, struct ata_device **r_failed); static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed);
static void sil_freeze(struct ata_port *ap); static void sil_freeze(struct ata_port *ap);
static void sil_thaw(struct ata_port *ap); static void sil_thaw(struct ata_port *ap);
@ -185,7 +186,6 @@ static struct scsi_host_template sil_sht = {
}; };
static const struct ata_port_operations sil_ops = { static const struct ata_port_operations sil_ops = {
.port_disable = ata_port_disable,
.dev_config = sil_dev_config, .dev_config = sil_dev_config,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
@ -206,7 +206,6 @@ static const struct ata_port_operations sil_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd, .post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = sil_scr_read, .scr_read = sil_scr_read,
.scr_write = sil_scr_write, .scr_write = sil_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
@ -216,6 +215,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3112 */ /* sil_3112 */
{ {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
.link_flags = SIL_DFL_LINK_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, .udma_mask = ATA_UDMA5,
@ -225,6 +225,7 @@ static const struct ata_port_info sil_port_info[] = {
{ {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE |
SIL_FLAG_NO_SATA_IRQ, SIL_FLAG_NO_SATA_IRQ,
.link_flags = SIL_DFL_LINK_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, .udma_mask = ATA_UDMA5,
@ -233,6 +234,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3512 */ /* sil_3512 */
{ {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.link_flags = SIL_DFL_LINK_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, .udma_mask = ATA_UDMA5,
@ -241,6 +243,7 @@ static const struct ata_port_info sil_port_info[] = {
/* sil_3114 */ /* sil_3114 */
{ {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.link_flags = SIL_DFL_LINK_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, .udma_mask = ATA_UDMA5,
@ -290,35 +293,33 @@ static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
/** /**
* sil_set_mode - wrap set_mode functions * sil_set_mode - wrap set_mode functions
* @ap: port to set up * @link: link to set up
* @r_failed: returned device when we fail * @r_failed: returned device when we fail
* *
* Wrap the libata method for device setup as after the setup we need * Wrap the libata method for device setup as after the setup we need
* to inspect the results and do some configuration work * to inspect the results and do some configuration work
*/ */
static int sil_set_mode (struct ata_port *ap, struct ata_device **r_failed) static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed)
{ {
struct ata_host *host = ap->host; struct ata_port *ap = link->ap;
struct ata_device *dev; void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR];
void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR];
void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode; void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode;
u32 tmp, dev_mode[2]; struct ata_device *dev;
unsigned int i; u32 tmp, dev_mode[2] = { };
int rc; int rc;
rc = ata_do_set_mode(ap, r_failed); rc = ata_do_set_mode(link, r_failed);
if (rc) if (rc)
return rc; return rc;
for (i = 0; i < 2; i++) { ata_link_for_each_dev(dev, link) {
dev = &ap->device[i];
if (!ata_dev_enabled(dev)) if (!ata_dev_enabled(dev))
dev_mode[i] = 0; /* PIO0/1/2 */ dev_mode[dev->devno] = 0; /* PIO0/1/2 */
else if (dev->flags & ATA_DFLAG_PIO) else if (dev->flags & ATA_DFLAG_PIO)
dev_mode[i] = 1; /* PIO3/4 */ dev_mode[dev->devno] = 1; /* PIO3/4 */
else else
dev_mode[i] = 3; /* UDMA */ dev_mode[dev->devno] = 3; /* UDMA */
/* value 2 indicates MDMA */ /* value 2 indicates MDMA */
} }
@ -374,8 +375,8 @@ static int sil_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
static void sil_host_intr(struct ata_port *ap, u32 bmdma2) static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
{ {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
u8 status; u8 status;
if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
@ -394,8 +395,8 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
* repeat probing needlessly. * repeat probing needlessly.
*/ */
if (!(ap->pflags & ATA_PFLAG_FROZEN)) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
ata_ehi_hotplugged(&ap->eh_info); ata_ehi_hotplugged(&ap->link.eh_info);
ap->eh_info.serror |= serror; ap->link.eh_info.serror |= serror;
} }
goto freeze; goto freeze;
@ -562,8 +563,8 @@ static void sil_thaw(struct ata_port *ap)
*/ */
static void sil_dev_config(struct ata_device *dev) static void sil_dev_config(struct ata_device *dev)
{ {
struct ata_port *ap = dev->ap; struct ata_port *ap = dev->link->ap;
int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; int print_info = ap->link.eh_context.i.flags & ATA_EHI_PRINTINFO;
unsigned int n, quirks = 0; unsigned int n, quirks = 0;
unsigned char model_num[ATA_ID_PROD_LEN + 1]; unsigned char model_num[ATA_ID_PROD_LEN + 1];
@ -686,7 +687,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
mmio_base = host->iomap[SIL_MMIO_BAR]; mmio_base = host->iomap[SIL_MMIO_BAR];
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_ioports *ioaddr = &host->ports[i]->ioaddr; struct ata_port *ap = host->ports[i];
struct ata_ioports *ioaddr = &ap->ioaddr;
ioaddr->cmd_addr = mmio_base + sil_port[i].tf; ioaddr->cmd_addr = mmio_base + sil_port[i].tf;
ioaddr->altstatus_addr = ioaddr->altstatus_addr =
@ -694,6 +696,9 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma;
ioaddr->scr_addr = mmio_base + sil_port[i].scr; ioaddr->scr_addr = mmio_base + sil_port[i].scr;
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf");
} }
/* initialize and activate */ /* initialize and activate */

Просмотреть файл

@ -30,7 +30,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#define DRV_NAME "sata_sil24" #define DRV_NAME "sata_sil24"
#define DRV_VERSION "1.0" #define DRV_VERSION "1.1"
/* /*
* Port request block (PRB) 32 bytes * Port request block (PRB) 32 bytes
@ -168,7 +168,7 @@ enum {
DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | DEF_PORT_IRQ = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG | PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
PORT_IRQ_UNK_FIS, PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_NOTIFY,
/* bits[27:16] are unmasked (raw) */ /* bits[27:16] are unmasked (raw) */
PORT_IRQ_RAW_SHIFT = 16, PORT_IRQ_RAW_SHIFT = 16,
@ -237,8 +237,9 @@ enum {
/* host flags */ /* host flags */
SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY | ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
ATA_FLAG_ACPI_SATA, ATA_FLAG_AN | ATA_FLAG_PMP,
SIL24_COMMON_LFLAGS = ATA_LFLAG_SKIP_D2H_BSY,
SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
IRQ_STAT_4PORTS = 0xf, IRQ_STAT_4PORTS = 0xf,
@ -322,6 +323,7 @@ struct sil24_port_priv {
union sil24_cmd_block *cmd_block; /* 32 cmd blocks */ union sil24_cmd_block *cmd_block; /* 32 cmd blocks */
dma_addr_t cmd_block_dma; /* DMA base addr for them */ dma_addr_t cmd_block_dma; /* DMA base addr for them */
struct ata_taskfile tf; /* Cached taskfile registers */ struct ata_taskfile tf; /* Cached taskfile registers */
int do_port_rst;
}; };
static void sil24_dev_config(struct ata_device *dev); static void sil24_dev_config(struct ata_device *dev);
@ -329,9 +331,12 @@ static u8 sil24_check_status(struct ata_port *ap);
static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val); static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val); static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static int sil24_qc_defer(struct ata_queued_cmd *qc);
static void sil24_qc_prep(struct ata_queued_cmd *qc); static void sil24_qc_prep(struct ata_queued_cmd *qc);
static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
static void sil24_irq_clear(struct ata_port *ap); static void sil24_irq_clear(struct ata_port *ap);
static void sil24_pmp_attach(struct ata_port *ap);
static void sil24_pmp_detach(struct ata_port *ap);
static void sil24_freeze(struct ata_port *ap); static void sil24_freeze(struct ata_port *ap);
static void sil24_thaw(struct ata_port *ap); static void sil24_thaw(struct ata_port *ap);
static void sil24_error_handler(struct ata_port *ap); static void sil24_error_handler(struct ata_port *ap);
@ -340,6 +345,7 @@ static int sil24_port_start(struct ata_port *ap);
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int sil24_pci_device_resume(struct pci_dev *pdev); static int sil24_pci_device_resume(struct pci_dev *pdev);
static int sil24_port_resume(struct ata_port *ap);
#endif #endif
static const struct pci_device_id sil24_pci_tbl[] = { static const struct pci_device_id sil24_pci_tbl[] = {
@ -384,8 +390,6 @@ static struct scsi_host_template sil24_sht = {
}; };
static const struct ata_port_operations sil24_ops = { static const struct ata_port_operations sil24_ops = {
.port_disable = ata_port_disable,
.dev_config = sil24_dev_config, .dev_config = sil24_dev_config,
.check_status = sil24_check_status, .check_status = sil24_check_status,
@ -394,22 +398,28 @@ static const struct ata_port_operations sil24_ops = {
.tf_read = sil24_tf_read, .tf_read = sil24_tf_read,
.qc_defer = sil24_qc_defer,
.qc_prep = sil24_qc_prep, .qc_prep = sil24_qc_prep,
.qc_issue = sil24_qc_issue, .qc_issue = sil24_qc_issue,
.irq_clear = sil24_irq_clear, .irq_clear = sil24_irq_clear,
.irq_on = ata_dummy_irq_on,
.irq_ack = ata_dummy_irq_ack,
.scr_read = sil24_scr_read, .scr_read = sil24_scr_read,
.scr_write = sil24_scr_write, .scr_write = sil24_scr_write,
.pmp_attach = sil24_pmp_attach,
.pmp_detach = sil24_pmp_detach,
.freeze = sil24_freeze, .freeze = sil24_freeze,
.thaw = sil24_thaw, .thaw = sil24_thaw,
.error_handler = sil24_error_handler, .error_handler = sil24_error_handler,
.post_internal_cmd = sil24_post_internal_cmd, .post_internal_cmd = sil24_post_internal_cmd,
.port_start = sil24_port_start, .port_start = sil24_port_start,
#ifdef CONFIG_PM
.port_resume = sil24_port_resume,
#endif
}; };
/* /*
@ -424,6 +434,7 @@ static const struct ata_port_info sil24_port_info[] = {
{ {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
SIL24_FLAG_PCIX_IRQ_WOC, SIL24_FLAG_PCIX_IRQ_WOC,
.link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */ .udma_mask = ATA_UDMA5, /* udma0-5 */
@ -432,6 +443,7 @@ static const struct ata_port_info sil24_port_info[] = {
/* sil_3132 */ /* sil_3132 */
{ {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
.link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */ .udma_mask = ATA_UDMA5, /* udma0-5 */
@ -440,6 +452,7 @@ static const struct ata_port_info sil24_port_info[] = {
/* sil_3131/sil_3531 */ /* sil_3131/sil_3531 */
{ {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
.link_flags = SIL24_COMMON_LFLAGS,
.pio_mask = 0x1f, /* pio0-4 */ .pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5, /* udma0-5 */ .udma_mask = ATA_UDMA5, /* udma0-5 */
@ -456,7 +469,7 @@ static int sil24_tag(int tag)
static void sil24_dev_config(struct ata_device *dev) static void sil24_dev_config(struct ata_device *dev)
{ {
void __iomem *port = dev->ap->ioaddr.cmd_addr; void __iomem *port = dev->link->ap->ioaddr.cmd_addr;
if (dev->cdb_len == 16) if (dev->cdb_len == 16)
writel(PORT_CS_CDB16, port + PORT_CTRL_STAT); writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
@ -520,19 +533,78 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
*tf = pp->tf; *tf = pp->tf;
} }
static void sil24_config_port(struct ata_port *ap)
{
void __iomem *port = ap->ioaddr.cmd_addr;
/* configure IRQ WoC */
if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH);
writel(0x8000, port + PORT_HSHK_ERR_THRESH);
writel(0x0000, port + PORT_DECODE_ERR_CNT);
writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* always use 64bit activation */
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
/* clear port multiplier enable and resume bits */
writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
}
static void sil24_config_pmp(struct ata_port *ap, int attached)
{
void __iomem *port = ap->ioaddr.cmd_addr;
if (attached)
writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT);
else
writel(PORT_CS_PMP_EN, port + PORT_CTRL_CLR);
}
static void sil24_clear_pmp(struct ata_port *ap)
{
void __iomem *port = ap->ioaddr.cmd_addr;
int i;
writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
void __iomem *pmp_base = port + PORT_PMP + i * PORT_PMP_SIZE;
writel(0, pmp_base + PORT_PMP_STATUS);
writel(0, pmp_base + PORT_PMP_QACTIVE);
}
}
static int sil24_init_port(struct ata_port *ap) static int sil24_init_port(struct ata_port *ap)
{ {
void __iomem *port = ap->ioaddr.cmd_addr; void __iomem *port = ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
u32 tmp; u32 tmp;
/* clear PMP error status */
if (ap->nr_pmp_links)
sil24_clear_pmp(ap);
writel(PORT_CS_INIT, port + PORT_CTRL_STAT); writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
ata_wait_register(port + PORT_CTRL_STAT, ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_INIT, PORT_CS_INIT, 10, 100); PORT_CS_INIT, PORT_CS_INIT, 10, 100);
tmp = ata_wait_register(port + PORT_CTRL_STAT, tmp = ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_RDY, 0, 10, 100); PORT_CS_RDY, 0, 10, 100);
if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
pp->do_port_rst = 1;
ap->link.eh_context.i.action |= ATA_EH_HARDRESET;
return -EIO; return -EIO;
}
return 0; return 0;
} }
@ -583,9 +655,10 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
return rc; return rc;
} }
static int sil24_do_softreset(struct ata_port *ap, unsigned int *class, static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
int pmp, unsigned long deadline) int pmp, unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
unsigned long timeout_msec = 0; unsigned long timeout_msec = 0;
struct ata_taskfile tf; struct ata_taskfile tf;
const char *reason; const char *reason;
@ -593,7 +666,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
if (ata_port_offline(ap)) { if (ata_link_offline(link)) {
DPRINTK("PHY reports no device\n"); DPRINTK("PHY reports no device\n");
*class = ATA_DEV_NONE; *class = ATA_DEV_NONE;
goto out; goto out;
@ -609,7 +682,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
if (time_after(deadline, jiffies)) if (time_after(deadline, jiffies))
timeout_msec = jiffies_to_msecs(deadline - jiffies); timeout_msec = jiffies_to_msecs(deadline - jiffies);
ata_tf_init(ap->device, &tf); /* doesn't really matter */ ata_tf_init(link->device, &tf); /* doesn't really matter */
rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST, rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST,
timeout_msec); timeout_msec);
if (rc == -EBUSY) { if (rc == -EBUSY) {
@ -631,29 +704,54 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
return 0; return 0;
err: err:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
return -EIO; return -EIO;
} }
static int sil24_softreset(struct ata_port *ap, unsigned int *class, static int sil24_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
return sil24_do_softreset(ap, class, 0, deadline); return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline);
} }
static int sil24_hardreset(struct ata_port *ap, unsigned int *class, static int sil24_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline) unsigned long deadline)
{ {
struct ata_port *ap = link->ap;
void __iomem *port = ap->ioaddr.cmd_addr; void __iomem *port = ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
int did_port_rst = 0;
const char *reason; const char *reason;
int tout_msec, rc; int tout_msec, rc;
u32 tmp; u32 tmp;
retry:
/* Sometimes, DEV_RST is not enough to recover the controller.
* This happens often after PM DMA CS errata.
*/
if (pp->do_port_rst) {
ata_port_printk(ap, KERN_WARNING, "controller in dubious "
"state, performing PORT_RST\n");
writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);
msleep(10);
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_RDY, 0,
10, 5000);
/* restore port configuration */
sil24_config_port(ap);
sil24_config_pmp(ap, ap->nr_pmp_links);
pp->do_port_rst = 0;
did_port_rst = 1;
}
/* sil24 does the right thing(tm) without any protection */ /* sil24 does the right thing(tm) without any protection */
sata_set_spd(ap); sata_set_spd(link);
tout_msec = 100; tout_msec = 100;
if (ata_port_online(ap)) if (ata_link_online(link))
tout_msec = 5000; tout_msec = 5000;
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
@ -663,14 +761,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
/* SStatus oscillates between zero and valid status after /* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it. * DEV_RST, debounce it.
*/ */
rc = sata_phy_debounce(ap, sata_deb_timing_long, deadline); rc = sata_link_debounce(link, sata_deb_timing_long, deadline);
if (rc) { if (rc) {
reason = "PHY debouncing failed"; reason = "PHY debouncing failed";
goto err; goto err;
} }
if (tmp & PORT_CS_DEV_RST) { if (tmp & PORT_CS_DEV_RST) {
if (ata_port_offline(ap)) if (ata_link_offline(link))
return 0; return 0;
reason = "link not ready"; reason = "link not ready";
goto err; goto err;
@ -685,7 +783,12 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
return -EAGAIN; return -EAGAIN;
err: err:
ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); if (!did_port_rst) {
pp->do_port_rst = 1;
goto retry;
}
ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason);
return -EIO; return -EIO;
} }
@ -705,6 +808,38 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
} }
} }
static int sil24_qc_defer(struct ata_queued_cmd *qc)
{
struct ata_link *link = qc->dev->link;
struct ata_port *ap = link->ap;
u8 prot = qc->tf.protocol;
int is_atapi = (prot == ATA_PROT_ATAPI ||
prot == ATA_PROT_ATAPI_NODATA ||
prot == ATA_PROT_ATAPI_DMA);
/* ATAPI commands completing with CHECK_SENSE cause various
* weird problems if other commands are active. PMP DMA CS
* errata doesn't cover all and HSM violation occurs even with
* only one other device active. Always run an ATAPI command
* by itself.
*/
if (unlikely(ap->excl_link)) {
if (link == ap->excl_link) {
if (ap->nr_active_links)
return ATA_DEFER_PORT;
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
} else
return ATA_DEFER_PORT;
} else if (unlikely(is_atapi)) {
ap->excl_link = link;
if (ap->nr_active_links)
return ATA_DEFER_PORT;
qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
}
return ata_std_qc_defer(qc);
}
static void sil24_qc_prep(struct ata_queued_cmd *qc) static void sil24_qc_prep(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
@ -748,7 +883,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
} }
prb->ctrl = cpu_to_le16(ctrl); prb->ctrl = cpu_to_le16(ctrl);
ata_tf_to_fis(&qc->tf, 0, 1, prb->fis); ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, prb->fis);
if (qc->flags & ATA_QCFLAG_DMAMAP) if (qc->flags & ATA_QCFLAG_DMAMAP)
sil24_fill_sg(qc, sge); sil24_fill_sg(qc, sge);
@ -777,6 +912,39 @@ static void sil24_irq_clear(struct ata_port *ap)
/* unused */ /* unused */
} }
static void sil24_pmp_attach(struct ata_port *ap)
{
sil24_config_pmp(ap, 1);
sil24_init_port(ap);
}
static void sil24_pmp_detach(struct ata_port *ap)
{
sil24_init_port(ap);
sil24_config_pmp(ap, 0);
}
static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
return sil24_do_softreset(link, class, link->pmp, deadline);
}
static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline)
{
int rc;
rc = sil24_init_port(link->ap);
if (rc) {
ata_link_printk(link, KERN_ERR,
"hardreset failed (port not ready)\n");
return rc;
}
return sata_pmp_std_hardreset(link, class, deadline);
}
static void sil24_freeze(struct ata_port *ap) static void sil24_freeze(struct ata_port *ap)
{ {
void __iomem *port = ap->ioaddr.cmd_addr; void __iomem *port = ap->ioaddr.cmd_addr;
@ -804,8 +972,10 @@ static void sil24_error_intr(struct ata_port *ap)
{ {
void __iomem *port = ap->ioaddr.cmd_addr; void __iomem *port = ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data; struct sil24_port_priv *pp = ap->private_data;
struct ata_eh_info *ehi = &ap->eh_info; struct ata_queued_cmd *qc = NULL;
int freeze = 0; struct ata_link *link;
struct ata_eh_info *ehi;
int abort = 0, freeze = 0;
u32 irq_stat; u32 irq_stat;
/* on error, we need to clear IRQ explicitly */ /* on error, we need to clear IRQ explicitly */
@ -813,10 +983,17 @@ static void sil24_error_intr(struct ata_port *ap)
writel(irq_stat, port + PORT_IRQ_STAT); writel(irq_stat, port + PORT_IRQ_STAT);
/* first, analyze and record host port events */ /* first, analyze and record host port events */
link = &ap->link;
ehi = &link->eh_info;
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
if (irq_stat & PORT_IRQ_SDB_NOTIFY) {
ata_ehi_push_desc(ehi, "SDB notify");
sata_async_notification(ap);
}
if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) { if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
ata_ehi_hotplugged(ehi); ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, "%s", ata_ehi_push_desc(ehi, "%s",
@ -836,8 +1013,44 @@ static void sil24_error_intr(struct ata_port *ap)
if (irq_stat & PORT_IRQ_ERROR) { if (irq_stat & PORT_IRQ_ERROR) {
struct sil24_cerr_info *ci = NULL; struct sil24_cerr_info *ci = NULL;
unsigned int err_mask = 0, action = 0; unsigned int err_mask = 0, action = 0;
struct ata_queued_cmd *qc; u32 context, cerr;
u32 cerr; int pmp;
abort = 1;
/* DMA Context Switch Failure in Port Multiplier Mode
* errata. If we have active commands to 3 or more
* devices, any error condition on active devices can
* corrupt DMA context switching.
*/
if (ap->nr_active_links >= 3) {
ehi->err_mask |= AC_ERR_OTHER;
ehi->action |= ATA_EH_HARDRESET;
ata_ehi_push_desc(ehi, "PMP DMA CS errata");
pp->do_port_rst = 1;
freeze = 1;
}
/* find out the offending link and qc */
if (ap->nr_pmp_links) {
context = readl(port + PORT_CONTEXT);
pmp = (context >> 5) & 0xf;
if (pmp < ap->nr_pmp_links) {
link = &ap->pmp_link[pmp];
ehi = &link->eh_info;
qc = ata_qc_from_tag(ap, link->active_tag);
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "irq_stat 0x%08x",
irq_stat);
} else {
err_mask |= AC_ERR_HSM;
action |= ATA_EH_HARDRESET;
freeze = 1;
}
} else
qc = ata_qc_from_tag(ap, link->active_tag);
/* analyze CMD_ERR */ /* analyze CMD_ERR */
cerr = readl(port + PORT_CMD_ERR); cerr = readl(port + PORT_CMD_ERR);
@ -856,7 +1069,6 @@ static void sil24_error_intr(struct ata_port *ap)
} }
/* record error info */ /* record error info */
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc) { if (qc) {
sil24_read_tf(ap, qc->tag, &pp->tf); sil24_read_tf(ap, qc->tag, &pp->tf);
qc->err_mask |= err_mask; qc->err_mask |= err_mask;
@ -864,13 +1076,21 @@ static void sil24_error_intr(struct ata_port *ap)
ehi->err_mask |= err_mask; ehi->err_mask |= err_mask;
ehi->action |= action; ehi->action |= action;
/* if PMP, resume */
if (ap->nr_pmp_links)
writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
} }
/* freeze or abort */ /* freeze or abort */
if (freeze) if (freeze)
ata_port_freeze(ap); ata_port_freeze(ap);
else else if (abort) {
ata_port_abort(ap); if (qc)
ata_link_abort(qc->dev->link);
else
ata_port_abort(ap);
}
} }
static void sil24_finish_qc(struct ata_queued_cmd *qc) static void sil24_finish_qc(struct ata_queued_cmd *qc)
@ -910,7 +1130,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
if (rc > 0) if (rc > 0)
return; return;
if (rc < 0) { if (rc < 0) {
struct ata_eh_info *ehi = &ap->eh_info; struct ata_eh_info *ehi = &ap->link.eh_info;
ehi->err_mask |= AC_ERR_HSM; ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_SOFTRESET; ehi->action |= ATA_EH_SOFTRESET;
ata_port_freeze(ap); ata_port_freeze(ap);
@ -921,7 +1141,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit())
ata_port_printk(ap, KERN_INFO, "spurious interrupt " ata_port_printk(ap, KERN_INFO, "spurious interrupt "
"(slot_stat 0x%x active_tag %d sactive 0x%x)\n", "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
slot_stat, ap->active_tag, ap->sactive); slot_stat, ap->link.active_tag, ap->link.sactive);
} }
static irqreturn_t sil24_interrupt(int irq, void *dev_instance) static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
@ -963,16 +1183,18 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
static void sil24_error_handler(struct ata_port *ap) static void sil24_error_handler(struct ata_port *ap)
{ {
struct ata_eh_context *ehc = &ap->eh_context; struct sil24_port_priv *pp = ap->private_data;
if (sil24_init_port(ap)) { if (sil24_init_port(ap))
ata_eh_freeze_port(ap); ata_eh_freeze_port(ap);
ehc->i.action |= ATA_EH_HARDRESET;
}
/* perform recovery */ /* perform recovery */
ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset, sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
ata_std_postreset); ata_std_postreset, sata_pmp_std_prereset,
sil24_pmp_softreset, sil24_pmp_hardreset,
sata_pmp_std_postreset);
pp->do_port_rst = 0;
} }
static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
@ -980,8 +1202,8 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
/* make DMA engine forget about the failed command */ /* make DMA engine forget about the failed command */
if (qc->flags & ATA_QCFLAG_FAILED) if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap))
sil24_init_port(ap); ata_eh_freeze_port(ap);
} }
static int sil24_port_start(struct ata_port *ap) static int sil24_port_start(struct ata_port *ap)
@ -1019,7 +1241,6 @@ static int sil24_port_start(struct ata_port *ap)
static void sil24_init_controller(struct ata_host *host) static void sil24_init_controller(struct ata_host *host)
{ {
void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
u32 tmp; u32 tmp;
int i; int i;
@ -1031,7 +1252,8 @@ static void sil24_init_controller(struct ata_host *host)
/* init ports */ /* init ports */
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
void __iomem *port = port_base + i * PORT_REGS_SIZE; struct ata_port *ap = host->ports[i];
void __iomem *port = ap->ioaddr.cmd_addr;
/* Initial PHY setting */ /* Initial PHY setting */
writel(0x20c, port + PORT_PHY_CFG); writel(0x20c, port + PORT_PHY_CFG);
@ -1048,26 +1270,8 @@ static void sil24_init_controller(struct ata_host *host)
"failed to clear port RST\n"); "failed to clear port RST\n");
} }
/* Configure IRQ WoC */ /* configure port */
if (host->ports[0]->flags & SIL24_FLAG_PCIX_IRQ_WOC) sil24_config_port(ap);
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH);
writel(0x8000, port + PORT_HSHK_ERR_THRESH);
writel(0x0000, port + PORT_DECODE_ERR_CNT);
writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* Always use 64bit activation */
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
/* Clear port multiplier enable and resume bits */
writel(PORT_CS_PMP_EN | PORT_CS_PMP_RESUME,
port + PORT_CTRL_CLR);
} }
/* Turn on interrupts */ /* Turn on interrupts */
@ -1118,12 +1322,15 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = iomap; host->iomap = iomap;
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE; struct ata_port *ap = host->ports[i];
size_t offset = ap->port_no * PORT_REGS_SIZE;
void __iomem *port = iomap[SIL24_PORT_BAR] + offset;
host->ports[i]->ioaddr.cmd_addr = port; host->ports[i]->ioaddr.cmd_addr = port;
host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL; host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
ata_std_ports(&host->ports[i]->ioaddr); ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port");
} }
/* configure and activate the device */ /* configure and activate the device */
@ -1179,6 +1386,12 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
return 0; return 0;
} }
static int sil24_port_resume(struct ata_port *ap)
{
sil24_config_pmp(ap, ap->nr_pmp_links);
return 0;
}
#endif #endif
static int __init sil24_init(void) static int __init sil24_init(void)

Просмотреть файл

@ -104,7 +104,6 @@ static struct scsi_host_template sis_sht = {
}; };
static const struct ata_port_operations sis_ops = { static const struct ata_port_operations sis_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -123,7 +122,6 @@ static const struct ata_port_operations sis_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd, .post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = sis_scr_read, .scr_read = sis_scr_read,
.scr_write = sis_scr_write, .scr_write = sis_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,

Просмотреть файл

@ -329,7 +329,6 @@ static struct scsi_host_template k2_sata_sht = {
static const struct ata_port_operations k2_sata_ops = { static const struct ata_port_operations k2_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = k2_sata_tf_load, .tf_load = k2_sata_tf_load,
.tf_read = k2_sata_tf_read, .tf_read = k2_sata_tf_read,
.check_status = k2_stat_check_status, .check_status = k2_stat_check_status,
@ -349,7 +348,6 @@ static const struct ata_port_operations k2_sata_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd, .post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = k2_sata_scr_read, .scr_read = k2_sata_scr_read,
.scr_write = k2_sata_scr_write, .scr_write = k2_sata_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
@ -445,9 +443,15 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* different controllers have different number of ports - currently 4 or 8 */ /* different controllers have different number of ports - currently 4 or 8 */
/* All ports are on the same function. Multi-function device is no /* All ports are on the same function. Multi-function device is no
* longer available. This should not be seen in any system. */ * longer available. This should not be seen in any system. */
for (i = 0; i < host->n_ports; i++) for (i = 0; i < host->n_ports; i++) {
k2_sata_setup_port(&host->ports[i]->ioaddr, struct ata_port *ap = host->ports[i];
mmio_base + i * K2_SATA_PORT_OFFSET); unsigned int offset = i * K2_SATA_PORT_OFFSET;
k2_sata_setup_port(&ap->ioaddr, mmio_base + offset);
ata_port_pbar_desc(ap, 5, -1, "mmio");
ata_port_pbar_desc(ap, 5, offset, "port");
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)

Просмотреть файл

@ -254,7 +254,6 @@ static struct scsi_host_template pdc_sata_sht = {
}; };
static const struct ata_port_operations pdc_20621_ops = { static const struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio, .tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -267,7 +266,6 @@ static const struct ata_port_operations pdc_20621_ops = {
.eng_timeout = pdc_eng_timeout, .eng_timeout = pdc_eng_timeout,
.irq_clear = pdc20621_irq_clear, .irq_clear = pdc20621_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = pdc_port_start, .port_start = pdc_port_start,
}; };
@ -854,7 +852,7 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance)
!(ap->flags & ATA_FLAG_DISABLED)) { !(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled += pdc20621_host_intr(ap, qc, (i > 4), handled += pdc20621_host_intr(ap, qc, (i > 4),
mmio_base); mmio_base);
@ -881,7 +879,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
case ATA_PROT_DMA: case ATA_PROT_DMA:
@ -1383,9 +1381,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
const struct ata_port_info *ppi[] = const struct ata_port_info *ppi[] =
{ &pdc_port_info[ent->driver_data], NULL }; { &pdc_port_info[ent->driver_data], NULL };
struct ata_host *host; struct ata_host *host;
void __iomem *base;
struct pdc_host_priv *hpriv; struct pdc_host_priv *hpriv;
int rc; int i, rc;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@ -1411,11 +1408,17 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return rc; return rc;
host->iomap = pcim_iomap_table(pdev); host->iomap = pcim_iomap_table(pdev);
base = host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS; for (i = 0; i < 4; i++) {
pdc_sata_setup_port(&host->ports[0]->ioaddr, base + 0x200); struct ata_port *ap = host->ports[i];
pdc_sata_setup_port(&host->ports[1]->ioaddr, base + 0x280); void __iomem *base = host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
pdc_sata_setup_port(&host->ports[2]->ioaddr, base + 0x300); unsigned int offset = 0x200 + i * 0x80;
pdc_sata_setup_port(&host->ports[3]->ioaddr, base + 0x380);
pdc_sata_setup_port(&ap->ioaddr, base + offset);
ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, PDC_DIMM_BAR, -1, "dimm");
ata_port_pbar_desc(ap, PDC_MMIO_BAR, offset, "port");
}
/* configure and activate */ /* configure and activate */
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);

Просмотреть файл

@ -94,8 +94,6 @@ static struct scsi_host_template uli_sht = {
}; };
static const struct ata_port_operations uli_ops = { static const struct ata_port_operations uli_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -117,7 +115,6 @@ static const struct ata_port_operations uli_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = uli_scr_read, .scr_read = uli_scr_read,
.scr_write = uli_scr_write, .scr_write = uli_scr_write,
@ -242,6 +239,12 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4; hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_desc(host->ports[2],
"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
(unsigned long long)pci_resource_start(pdev, 0) + 8,
((unsigned long long)pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4,
(unsigned long long)pci_resource_start(pdev, 4) + 16);
ioaddr = &host->ports[3]->ioaddr; ioaddr = &host->ports[3]->ioaddr;
ioaddr->cmd_addr = iomap[2] + 8; ioaddr->cmd_addr = iomap[2] + 8;
ioaddr->altstatus_addr = ioaddr->altstatus_addr =
@ -250,6 +253,13 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
ioaddr->bmdma_addr = iomap[4] + 24; ioaddr->bmdma_addr = iomap[4] + 24;
hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5; hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_desc(host->ports[2],
"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
(unsigned long long)pci_resource_start(pdev, 2) + 9,
((unsigned long long)pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4,
(unsigned long long)pci_resource_start(pdev, 4) + 24);
break; break;
case uli_5289: case uli_5289:

Просмотреть файл

@ -57,7 +57,6 @@ enum {
SATA_CHAN_ENAB = 0x40, /* SATA channel enable */ SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
SATA_INT_GATE = 0x41, /* SATA interrupt gating */ SATA_INT_GATE = 0x41, /* SATA interrupt gating */
SATA_NATIVE_MODE = 0x42, /* Native mode enable */ 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_UDMA_TIMING = 0xB3, /* PATA timing for DMA/ cable detect */
PATA_PIO_TIMING = 0xAB, /* PATA timing register */ PATA_PIO_TIMING = 0xAB, /* PATA timing register */
@ -68,7 +67,6 @@ enum {
NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */ SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */
SATA_2DEV = (1 << 5), /* SATA is master/slave */
}; };
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
@ -122,8 +120,6 @@ static struct scsi_host_template svia_sht = {
}; };
static const struct ata_port_operations vt6420_sata_ops = { static const struct ata_port_operations vt6420_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -146,14 +142,11 @@ static const struct ata_port_operations vt6420_sata_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations vt6421_pata_ops = { static const struct ata_port_operations vt6421_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = vt6421_set_pio_mode, .set_piomode = vt6421_set_pio_mode,
.set_dmamode = vt6421_set_dma_mode, .set_dmamode = vt6421_set_dma_mode,
@ -180,14 +173,11 @@ static const struct ata_port_operations vt6421_pata_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.port_start = ata_port_start, .port_start = ata_port_start,
}; };
static const struct ata_port_operations vt6421_sata_ops = { static const struct ata_port_operations vt6421_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load, .tf_load = ata_tf_load,
.tf_read = ata_tf_read, .tf_read = ata_tf_read,
.check_status = ata_check_status, .check_status = ata_check_status,
@ -211,7 +201,6 @@ static const struct ata_port_operations vt6421_sata_ops = {
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = svia_scr_read, .scr_read = svia_scr_read,
.scr_write = svia_scr_write, .scr_write = svia_scr_write,
@ -276,7 +265,7 @@ static void svia_noop_freeze(struct ata_port *ap)
/** /**
* vt6420_prereset - prereset for vt6420 * vt6420_prereset - prereset for vt6420
* @ap: target ATA port * @link: target ATA link
* @deadline: deadline jiffies for the operation * @deadline: deadline jiffies for the operation
* *
* SCR registers on vt6420 are pieces of shit and may hang the * SCR registers on vt6420 are pieces of shit and may hang the
@ -294,9 +283,10 @@ static void svia_noop_freeze(struct ata_port *ap)
* RETURNS: * RETURNS:
* 0 on success, -errno otherwise. * 0 on success, -errno otherwise.
*/ */
static int vt6420_prereset(struct ata_port *ap, unsigned long deadline) static int vt6420_prereset(struct ata_link *link, unsigned long deadline)
{ {
struct ata_eh_context *ehc = &ap->eh_context; struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &ap->link.eh_context;
unsigned long timeout = jiffies + (HZ * 5); unsigned long timeout = jiffies + (HZ * 5);
u32 sstatus, scontrol; u32 sstatus, scontrol;
int online; int online;
@ -407,6 +397,9 @@ static void vt6421_init_addrs(struct ata_port *ap)
ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no); ioaddr->scr_addr = vt6421_scr_addr(iomap[5], ap->port_no);
ata_std_ports(ioaddr); ata_std_ports(ioaddr);
ata_port_pbar_desc(ap, ap->port_no, -1, "port");
ata_port_pbar_desc(ap, 4, ap->port_no * 8, "bmdma");
} }
static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
@ -513,7 +506,6 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_host *host; struct ata_host *host;
int board_id = (int) ent->driver_data; int board_id = (int) ent->driver_data;
const int *bar_sizes; const int *bar_sizes;
u8 tmp8;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@ -522,19 +514,10 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
return rc; return rc;
if (board_id == vt6420) { if (board_id == vt6420)
pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
if (tmp8 & SATA_2DEV) {
dev_printk(KERN_ERR, &pdev->dev,
"SATA master/slave not supported (0x%x)\n",
(int) tmp8);
return -EIO;
}
bar_sizes = &svia_bar_sizes[0]; bar_sizes = &svia_bar_sizes[0];
} else { else
bar_sizes = &vt6421_bar_sizes[0]; bar_sizes = &vt6421_bar_sizes[0];
}
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) || if ((pci_resource_start(pdev, i) == 0) ||

Просмотреть файл

@ -240,7 +240,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap)
return; return;
} }
qc = ata_qc_from_tag(ap, ap->active_tag); qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING))) if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
handled = ata_host_intr(ap, qc); handled = ata_host_intr(ap, qc);
@ -317,7 +317,6 @@ static struct scsi_host_template vsc_sata_sht = {
static const struct ata_port_operations vsc_sata_ops = { static const struct ata_port_operations vsc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = vsc_sata_tf_load, .tf_load = vsc_sata_tf_load,
.tf_read = vsc_sata_tf_read, .tf_read = vsc_sata_tf_read,
.exec_command = ata_exec_command, .exec_command = ata_exec_command,
@ -336,7 +335,6 @@ static const struct ata_port_operations vsc_sata_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd, .post_internal_cmd = ata_bmdma_post_internal_cmd,
.irq_clear = ata_bmdma_irq_clear, .irq_clear = ata_bmdma_irq_clear,
.irq_on = ata_irq_on, .irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
.scr_read = vsc_sata_scr_read, .scr_read = vsc_sata_scr_read,
.scr_write = vsc_sata_scr_write, .scr_write = vsc_sata_scr_write,
.port_start = ata_port_start, .port_start = ata_port_start,
@ -408,9 +406,15 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
mmio_base = host->iomap[VSC_MMIO_BAR]; mmio_base = host->iomap[VSC_MMIO_BAR];
for (i = 0; i < host->n_ports; i++) for (i = 0; i < host->n_ports; i++) {
vsc_sata_setup_port(&host->ports[i]->ioaddr, struct ata_port *ap = host->ports[i];
mmio_base + (i + 1) * VSC_SATA_PORT_OFFSET); unsigned int offset = (i + 1) * VSC_SATA_PORT_OFFSET;
vsc_sata_setup_port(&ap->ioaddr, mmio_base + offset);
ata_port_pbar_desc(ap, VSC_MMIO_BAR, -1, "mmio");
ata_port_pbar_desc(ap, VSC_MMIO_BAR, offset, "port");
}
/* /*
* Use 32 bit DMA mask, because 64 bit address support is poor. * Use 32 bit DMA mask, because 64 bit address support is poor.

Просмотреть файл

@ -3829,18 +3829,18 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg,
/** /**
* ipr_sata_reset - Reset the SATA port * ipr_sata_reset - Reset the SATA port
* @ap: SATA port to reset * @link: SATA link to reset
* @classes: class of the attached device * @classes: class of the attached device
* *
* This function issues a SATA phy reset to the affected ATA port. * This function issues a SATA phy reset to the affected ATA link.
* *
* Return value: * Return value:
* 0 on success / non-zero on failure * 0 on success / non-zero on failure
**/ **/
static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes, static int ipr_sata_reset(struct ata_link *link, unsigned int *classes,
unsigned long deadline) unsigned long deadline)
{ {
struct ipr_sata_port *sata_port = ap->private_data; struct ipr_sata_port *sata_port = link->ap->private_data;
struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg;
struct ipr_resource_entry *res; struct ipr_resource_entry *res;
unsigned long lock_flags = 0; unsigned long lock_flags = 0;
@ -4981,22 +4981,22 @@ static void ipr_ata_phy_reset(struct ata_port *ap)
rc = ipr_device_reset(ioa_cfg, res); rc = ipr_device_reset(ioa_cfg, res);
if (rc) { if (rc) {
ap->ops->port_disable(ap); ata_port_disable(ap);
goto out_unlock; goto out_unlock;
} }
switch(res->cfgte.proto) { switch(res->cfgte.proto) {
case IPR_PROTO_SATA: case IPR_PROTO_SATA:
case IPR_PROTO_SAS_STP: case IPR_PROTO_SAS_STP:
ap->device[0].class = ATA_DEV_ATA; ap->link.device[0].class = ATA_DEV_ATA;
break; break;
case IPR_PROTO_SATA_ATAPI: case IPR_PROTO_SATA_ATAPI:
case IPR_PROTO_SAS_STP_ATAPI: case IPR_PROTO_SAS_STP_ATAPI:
ap->device[0].class = ATA_DEV_ATAPI; ap->link.device[0].class = ATA_DEV_ATAPI;
break; break;
default: default:
ap->device[0].class = ATA_DEV_UNKNOWN; ap->link.device[0].class = ATA_DEV_UNKNOWN;
ap->ops->port_disable(ap); ata_port_disable(ap);
break; break;
}; };
@ -5262,7 +5262,6 @@ static u8 ipr_ata_check_altstatus(struct ata_port *ap)
} }
static struct ata_port_operations ipr_sata_ops = { static struct ata_port_operations ipr_sata_ops = {
.port_disable = ata_port_disable,
.check_status = ipr_ata_check_status, .check_status = ipr_ata_check_status,
.check_altstatus = ipr_ata_check_altstatus, .check_altstatus = ipr_ata_check_altstatus,
.dev_select = ata_noop_dev_select, .dev_select = ata_noop_dev_select,

Просмотреть файл

@ -249,17 +249,17 @@ static void sas_ata_phy_reset(struct ata_port *ap)
switch (dev->sata_dev.command_set) { switch (dev->sata_dev.command_set) {
case ATA_COMMAND_SET: case ATA_COMMAND_SET:
SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__); SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__);
ap->device[0].class = ATA_DEV_ATA; ap->link.device[0].class = ATA_DEV_ATA;
break; break;
case ATAPI_COMMAND_SET: case ATAPI_COMMAND_SET:
SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__); SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__);
ap->device[0].class = ATA_DEV_ATAPI; ap->link.device[0].class = ATA_DEV_ATAPI;
break; break;
default: default:
SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
__FUNCTION__, __FUNCTION__,
dev->sata_dev.command_set); dev->sata_dev.command_set);
ap->device[0].class = ATA_DEV_UNKNOWN; ap->link.device[0].class = ATA_DEV_UNKNOWN;
break; break;
} }
@ -317,7 +317,7 @@ static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
dev->sata_dev.serror = val; dev->sata_dev.serror = val;
break; break;
case SCR_ACTIVE: case SCR_ACTIVE:
dev->sata_dev.ap->sactive = val; dev->sata_dev.ap->link.sactive = val;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -342,7 +342,7 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
*val = dev->sata_dev.serror; *val = dev->sata_dev.serror;
return 0; return 0;
case SCR_ACTIVE: case SCR_ACTIVE:
*val = dev->sata_dev.ap->sactive; *val = dev->sata_dev.ap->link.sactive;
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
@ -350,7 +350,6 @@ static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in,
} }
static struct ata_port_operations sas_sata_ops = { static struct ata_port_operations sas_sata_ops = {
.port_disable = ata_port_disable,
.check_status = sas_ata_check_status, .check_status = sas_ata_check_status,
.check_altstatus = sas_ata_check_status, .check_altstatus = sas_ata_check_status,
.dev_select = ata_noop_dev_select, .dev_select = ata_noop_dev_select,

Просмотреть файл

@ -1,12 +1,7 @@
#ifndef __ASM_GENERIC_LIBATA_PORTMAP_H #ifndef __ASM_GENERIC_LIBATA_PORTMAP_H
#define __ASM_GENERIC_LIBATA_PORTMAP_H #define __ASM_GENERIC_LIBATA_PORTMAP_H
#define ATA_PRIMARY_CMD 0x1F0
#define ATA_PRIMARY_CTL 0x3F6
#define ATA_PRIMARY_IRQ(dev) 14 #define ATA_PRIMARY_IRQ(dev) 14
#define ATA_SECONDARY_CMD 0x170
#define ATA_SECONDARY_CTL 0x376
#define ATA_SECONDARY_IRQ(dev) 15 #define ATA_SECONDARY_IRQ(dev) 15
#endif #endif

Просмотреть файл

@ -230,6 +230,12 @@ enum {
SETFEATURES_SPINUP = 0x07, /* Spin-up drive */ SETFEATURES_SPINUP = 0x07, /* Spin-up drive */
SETFEATURES_SATA_ENABLE = 0x10, /* Enable use of SATA feature */
SETFEATURES_SATA_DISABLE = 0x90, /* Disable use of SATA feature */
/* SETFEATURE Sector counts for SATA features */
SATA_AN = 0x05, /* Asynchronous Notification */
/* ATAPI stuff */ /* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0), ATAPI_PKT_DMA = (1 << 0),
ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: ATAPI_DMADIR = (1 << 2), /* ATAPI data dir:
@ -281,6 +287,15 @@ enum {
SERR_PROTOCOL = (1 << 10), /* protocol violation */ SERR_PROTOCOL = (1 << 10), /* protocol violation */
SERR_INTERNAL = (1 << 11), /* host internal error */ SERR_INTERNAL = (1 << 11), /* host internal error */
SERR_PHYRDY_CHG = (1 << 16), /* PHY RDY changed */ SERR_PHYRDY_CHG = (1 << 16), /* PHY RDY changed */
SERR_PHY_INT_ERR = (1 << 17), /* PHY internal error */
SERR_COMM_WAKE = (1 << 18), /* Comm wake */
SERR_10B_8B_ERR = (1 << 19), /* 10b to 8b decode error */
SERR_DISPARITY = (1 << 20), /* Disparity */
SERR_CRC = (1 << 21), /* CRC error */
SERR_HANDSHAKE = (1 << 22), /* Handshake error */
SERR_LINK_SEQ_ERR = (1 << 23), /* Link sequence error */
SERR_TRANS_ST_ERROR = (1 << 24), /* Transport state trans. error */
SERR_UNRECOG_FIS = (1 << 25), /* Unrecognized FIS */
SERR_DEV_XCHG = (1 << 26), /* device exchanged */ SERR_DEV_XCHG = (1 << 26), /* device exchanged */
/* struct ata_taskfile flags */ /* struct ata_taskfile flags */
@ -341,24 +356,17 @@ struct ata_taskfile {
}; };
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
#define ata_id_hpa_enabled(id) ((id)[85] & (1 << 10))
#define ata_id_has_fua(id) ((id)[84] & (1 << 6))
#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
#define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13))
#define ata_id_has_lba48(id) ((id)[83] & (1 << 10))
#define ata_id_has_hpa(id) ((id)[82] & (1 << 10))
#define ata_id_has_wcache(id) ((id)[82] & (1 << 5))
#define ata_id_has_pm(id) ((id)[82] & (1 << 3))
#define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_lba(id) ((id)[49] & (1 << 9))
#define ata_id_has_dma(id) ((id)[49] & (1 << 8)) #define ata_id_has_dma(id) ((id)[49] & (1 << 8))
#define ata_id_has_ncq(id) ((id)[76] & (1 << 8)) #define ata_id_has_ncq(id) ((id)[76] & (1 << 8))
#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1) #define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
#define ata_id_removeable(id) ((id)[0] & (1 << 7)) #define ata_id_removeable(id) ((id)[0] & (1 << 7))
#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0)) #define ata_id_has_dword_io(id) ((id)[48] & (1 << 0))
#define ata_id_has_atapi_AN(id) \
( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
((id)[78] & (1 << 5)) )
#define ata_id_iordy_disable(id) ((id)[49] & (1 << 10)) #define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
#define ata_id_has_iordy(id) ((id)[49] & (1 << 9)) #define ata_id_has_iordy(id) ((id)[49] & (1 << 11))
#define ata_id_u32(id,n) \ #define ata_id_u32(id,n) \
(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)])) (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
#define ata_id_u64(id,n) \ #define ata_id_u64(id,n) \
@ -369,6 +377,90 @@ struct ata_taskfile {
#define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20) #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
static inline int ata_id_has_fua(const u16 *id)
{
if ((id[84] & 0xC000) != 0x4000)
return 0;
return id[84] & (1 << 6);
}
static inline int ata_id_has_flush(const u16 *id)
{
if ((id[83] & 0xC000) != 0x4000)
return 0;
return id[83] & (1 << 12);
}
static inline int ata_id_has_flush_ext(const u16 *id)
{
if ((id[83] & 0xC000) != 0x4000)
return 0;
return id[83] & (1 << 13);
}
static inline int ata_id_has_lba48(const u16 *id)
{
if ((id[83] & 0xC000) != 0x4000)
return 0;
return id[83] & (1 << 10);
}
static inline int ata_id_hpa_enabled(const u16 *id)
{
/* Yes children, word 83 valid bits cover word 82 data */
if ((id[83] & 0xC000) != 0x4000)
return 0;
/* And 87 covers 85-87 */
if ((id[87] & 0xC000) != 0x4000)
return 0;
/* Check command sets enabled as well as supported */
if ((id[85] & ( 1 << 10)) == 0)
return 0;
return id[82] & (1 << 10);
}
static inline int ata_id_has_wcache(const u16 *id)
{
/* Yes children, word 83 valid bits cover word 82 data */
if ((id[83] & 0xC000) != 0x4000)
return 0;
return id[82] & (1 << 5);
}
static inline int ata_id_has_pm(const u16 *id)
{
if ((id[83] & 0xC000) != 0x4000)
return 0;
return id[82] & (1 << 3);
}
static inline int ata_id_rahead_enabled(const u16 *id)
{
if ((id[87] & 0xC000) != 0x4000)
return 0;
return id[85] & (1 << 6);
}
static inline int ata_id_wcache_enabled(const u16 *id)
{
if ((id[87] & 0xC000) != 0x4000)
return 0;
return id[85] & (1 << 5);
}
/**
* ata_id_major_version - get ATA level of drive
* @id: Identify data
*
* Caveats:
* ATA-1 considers identify optional
* ATA-2 introduces mandatory identify
* ATA-3 introduces word 80 and accurate reporting
*
* The practical impact of this is that ata_id_major_version cannot
* reliably report on drives below ATA3.
*/
static inline unsigned int ata_id_major_version(const u16 *id) static inline unsigned int ata_id_major_version(const u16 *id)
{ {
unsigned int mver; unsigned int mver;

Просмотреть файл

@ -28,7 +28,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#include <linux/io.h> #include <linux/io.h>
@ -107,12 +106,6 @@ static inline u32 ata_msg_init(int dval, int default_msg_enable_bits)
/* defines only for the constants which don't work well as enums */ /* defines only for the constants which don't work well as enums */
#define ATA_TAG_POISON 0xfafbfcfdU #define ATA_TAG_POISON 0xfafbfcfdU
/* move to PCI layer? */
static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
{
return &pdev->dev;
}
enum { enum {
/* various global constants */ /* various global constants */
LIBATA_MAX_PRD = ATA_MAX_PRD / 2, LIBATA_MAX_PRD = ATA_MAX_PRD / 2,
@ -139,11 +132,12 @@ enum {
ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */ ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_AN = (1 << 7), /* AN configured */
ATA_DFLAG_CFG_MASK = (1 << 12) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ ATA_DFLAG_PIO = (1 << 12), /* device limited to PIO mode */
ATA_DFLAG_NCQ_OFF = (1 << 9), /* device limited to non-NCQ mode */ ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */
ATA_DFLAG_SPUNDOWN = (1 << 10), /* XXX: for spindown_compat */ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */
ATA_DFLAG_INIT_MASK = (1 << 16) - 1, ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
ATA_DFLAG_DETACH = (1 << 16), ATA_DFLAG_DETACH = (1 << 16),
@ -154,7 +148,22 @@ enum {
ATA_DEV_ATA_UNSUP = 2, /* ATA device (unsupported) */ ATA_DEV_ATA_UNSUP = 2, /* ATA device (unsupported) */
ATA_DEV_ATAPI = 3, /* ATAPI device */ ATA_DEV_ATAPI = 3, /* ATAPI device */
ATA_DEV_ATAPI_UNSUP = 4, /* ATAPI device (unsupported) */ ATA_DEV_ATAPI_UNSUP = 4, /* ATAPI device (unsupported) */
ATA_DEV_NONE = 5, /* no device */ ATA_DEV_PMP = 5, /* SATA port multiplier */
ATA_DEV_PMP_UNSUP = 6, /* SATA port multiplier (unsupported) */
ATA_DEV_SEMB = 7, /* SEMB */
ATA_DEV_SEMB_UNSUP = 8, /* SEMB (unsupported) */
ATA_DEV_NONE = 9, /* no device */
/* struct ata_link flags */
ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
ATA_LFLAG_SKIP_D2H_BSY = (1 << 1), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_LFLAG_NO_SRST = (1 << 2), /* avoid softreset */
ATA_LFLAG_ASSUME_ATA = (1 << 3), /* assume ATA class */
ATA_LFLAG_ASSUME_SEMB = (1 << 4), /* assume SEMB class */
ATA_LFLAG_ASSUME_CLASS = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */
ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */
/* struct ata_port flags */ /* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
@ -170,13 +179,12 @@ enum {
ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD
* doesn't handle PIO interrupts */ * doesn't handle PIO interrupts */
ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */
ATA_FLAG_HRST_TO_RESUME = (1 << 11), /* hardreset to resume phy */
ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13), ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
ATA_FLAG_AN = (1 << 18), /* controller supports AN */
ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
/* The following flag belongs to ap->pflags but is kept in /* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be * ap->flags because it's referenced in many LLDs and will be
@ -195,6 +203,7 @@ enum {
ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */ ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */
ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */ ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */
ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */ ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */
ATA_PFLAG_RESETTING = (1 << 8), /* reset in progress */
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
@ -207,6 +216,7 @@ enum {
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */
ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */ ATA_QCFLAG_FAILED = (1 << 16), /* cmd failed and is owned by EH */
ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */ ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */
@ -263,6 +273,10 @@ enum {
/* ering size */ /* ering size */
ATA_ERING_SIZE = 32, ATA_ERING_SIZE = 32,
/* return values for ->qc_defer */
ATA_DEFER_LINK = 1,
ATA_DEFER_PORT = 2,
/* desc_len for ata_eh_info and context */ /* desc_len for ata_eh_info and context */
ATA_EH_DESC_LEN = 80, ATA_EH_DESC_LEN = 80,
@ -270,6 +284,7 @@ enum {
ATA_EH_REVALIDATE = (1 << 0), ATA_EH_REVALIDATE = (1 << 0),
ATA_EH_SOFTRESET = (1 << 1), ATA_EH_SOFTRESET = (1 << 1),
ATA_EH_HARDRESET = (1 << 2), ATA_EH_HARDRESET = (1 << 2),
ATA_EH_ENABLE_LINK = (1 << 3),
ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
@ -289,12 +304,16 @@ enum {
ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET, ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
/* max repeat if error condition is still set after ->error_handler */ /* max tries if error condition is still set after ->error_handler */
ATA_EH_MAX_REPEAT = 5, ATA_EH_MAX_TRIES = 5,
/* how hard are we gonna try to probe/recover devices */ /* how hard are we gonna try to probe/recover devices */
ATA_PROBE_MAX_TRIES = 3, ATA_PROBE_MAX_TRIES = 3,
ATA_EH_DEV_TRIES = 3, ATA_EH_DEV_TRIES = 3,
ATA_EH_PMP_TRIES = 5,
ATA_EH_PMP_LINK_TRIES = 3,
SATA_PMP_SCR_TIMEOUT = 250,
/* Horkage types. May be set by libata or controller on drives /* Horkage types. May be set by libata or controller on drives
(some horkage may be drive/controller pair dependant */ (some horkage may be drive/controller pair dependant */
@ -304,6 +323,14 @@ enum {
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */ ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */ ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */
ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */ ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */
ATA_HORKAGE_SKIP_PM = (1 << 5), /* Skip PM operations */
ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
ATA_DMA_MASK_ATA = (1 << 0), /* DMA on ATA Disk */
ATA_DMA_MASK_ATAPI = (1 << 1), /* DMA on ATAPI */
ATA_DMA_MASK_CFA = (1 << 2), /* DMA on CF Card */
}; };
enum hsm_task_states { enum hsm_task_states {
@ -333,14 +360,15 @@ enum ata_completion_errors {
struct scsi_device; struct scsi_device;
struct ata_port_operations; struct ata_port_operations;
struct ata_port; struct ata_port;
struct ata_link;
struct ata_queued_cmd; struct ata_queued_cmd;
/* typedefs */ /* typedefs */
typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc); typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
typedef int (*ata_prereset_fn_t)(struct ata_port *ap, unsigned long deadline); typedef int (*ata_prereset_fn_t)(struct ata_link *link, unsigned long deadline);
typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes, typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes,
unsigned long deadline); unsigned long deadline);
typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes); typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
struct ata_ioports { struct ata_ioports {
void __iomem *cmd_addr; void __iomem *cmd_addr;
@ -363,8 +391,6 @@ struct ata_ioports {
struct ata_host { struct ata_host {
spinlock_t lock; spinlock_t lock;
struct device *dev; struct device *dev;
unsigned long irq;
unsigned long irq2;
void __iomem * const *iomap; void __iomem * const *iomap;
unsigned int n_ports; unsigned int n_ports;
void *private_data; void *private_data;
@ -436,7 +462,7 @@ struct ata_ering {
}; };
struct ata_device { struct ata_device {
struct ata_port *ap; struct ata_link *link;
unsigned int devno; /* 0 or 1 */ unsigned int devno; /* 0 or 1 */
unsigned long flags; /* ATA_DFLAG_xxx */ unsigned long flags; /* ATA_DFLAG_xxx */
unsigned int horkage; /* List of broken features */ unsigned int horkage; /* List of broken features */
@ -447,7 +473,12 @@ struct ata_device {
/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
u64 n_sectors; /* size of device, if ATA */ u64 n_sectors; /* size of device, if ATA */
unsigned int class; /* ATA_DEV_xxx */ unsigned int class; /* ATA_DEV_xxx */
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
union {
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
};
u8 pio_mode; u8 pio_mode;
u8 dma_mode; u8 dma_mode;
u8 xfer_mode; u8 xfer_mode;
@ -510,6 +541,27 @@ struct ata_acpi_gtm {
u32 flags; u32 flags;
} __packed; } __packed;
struct ata_link {
struct ata_port *ap;
int pmp; /* port multiplier port # */
unsigned int active_tag; /* active tag on this link */
u32 sactive; /* active NCQ commands */
unsigned int flags; /* ATA_LFLAG_xxx */
unsigned int hw_sata_spd_limit;
unsigned int sata_spd_limit;
unsigned int sata_spd; /* current SATA PHY speed */
/* record runtime error info, protected by host_set lock */
struct ata_eh_info eh_info;
/* EH context */
struct ata_eh_context eh_context;
struct ata_device device[ATA_MAX_DEVICES];
};
struct ata_port { struct ata_port {
struct Scsi_Host *scsi_host; /* our co-allocated scsi host */ struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
const struct ata_port_operations *ops; const struct ata_port_operations *ops;
@ -533,23 +585,17 @@ struct ata_port {
unsigned int mwdma_mask; unsigned int mwdma_mask;
unsigned int udma_mask; unsigned int udma_mask;
unsigned int cbl; /* cable type; ATA_CBL_xxx */ unsigned int cbl; /* cable type; ATA_CBL_xxx */
unsigned int hw_sata_spd_limit;
unsigned int sata_spd_limit; /* SATA PHY speed limit */
unsigned int sata_spd; /* current SATA PHY speed */
/* record runtime error info, protected by host lock */
struct ata_eh_info eh_info;
/* EH context owned by EH */
struct ata_eh_context eh_context;
struct ata_device device[ATA_MAX_DEVICES];
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE]; struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
unsigned long qc_allocated; unsigned long qc_allocated;
unsigned int qc_active; unsigned int qc_active;
int nr_active_links; /* #links with active qcs */
unsigned int active_tag; struct ata_link link; /* host default link */
u32 sactive;
int nr_pmp_links; /* nr of available PMP links */
struct ata_link *pmp_link; /* array of PMP links */
struct ata_link *excl_link; /* for PMP qc exclusion */
struct ata_port_stats stats; struct ata_port_stats stats;
struct ata_host *host; struct ata_host *host;
@ -565,6 +611,7 @@ struct ata_port {
u32 msg_enable; u32 msg_enable;
struct list_head eh_done_q; struct list_head eh_done_q;
wait_queue_head_t eh_wait_q; wait_queue_head_t eh_wait_q;
int eh_tries;
pm_message_t pm_mesg; pm_message_t pm_mesg;
int *pm_result; int *pm_result;
@ -582,8 +629,6 @@ struct ata_port {
}; };
struct ata_port_operations { struct ata_port_operations {
void (*port_disable) (struct ata_port *);
void (*dev_config) (struct ata_device *); void (*dev_config) (struct ata_device *);
void (*set_piomode) (struct ata_port *, struct ata_device *); void (*set_piomode) (struct ata_port *, struct ata_device *);
@ -599,7 +644,7 @@ struct ata_port_operations {
void (*dev_select)(struct ata_port *ap, unsigned int device); void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap); /* obsolete */ void (*phy_reset) (struct ata_port *ap); /* obsolete */
int (*set_mode) (struct ata_port *ap, struct ata_device **r_failed_dev); int (*set_mode) (struct ata_link *link, struct ata_device **r_failed_dev);
int (*cable_detect) (struct ata_port *ap); int (*cable_detect) (struct ata_port *ap);
@ -610,9 +655,14 @@ struct ata_port_operations {
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
int (*qc_defer) (struct ata_queued_cmd *qc);
void (*qc_prep) (struct ata_queued_cmd *qc); void (*qc_prep) (struct ata_queued_cmd *qc);
unsigned int (*qc_issue) (struct ata_queued_cmd *qc); unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
/* port multiplier */
void (*pmp_attach) (struct ata_port *ap);
void (*pmp_detach) (struct ata_port *ap);
/* Error handlers. ->error_handler overrides ->eng_timeout and /* Error handlers. ->error_handler overrides ->eng_timeout and
* indicates that new-style EH is in place. * indicates that new-style EH is in place.
*/ */
@ -626,7 +676,6 @@ struct ata_port_operations {
irq_handler_t irq_handler; irq_handler_t irq_handler;
void (*irq_clear) (struct ata_port *); void (*irq_clear) (struct ata_port *);
u8 (*irq_on) (struct ata_port *); u8 (*irq_on) (struct ata_port *);
u8 (*irq_ack) (struct ata_port *ap, unsigned int chk_drq);
int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val); int (*scr_read) (struct ata_port *ap, unsigned int sc_reg, u32 *val);
int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val); int (*scr_write) (struct ata_port *ap, unsigned int sc_reg, u32 val);
@ -646,6 +695,7 @@ struct ata_port_operations {
struct ata_port_info { struct ata_port_info {
struct scsi_host_template *sht; struct scsi_host_template *sht;
unsigned long flags; unsigned long flags;
unsigned long link_flags;
unsigned long pio_mask; unsigned long pio_mask;
unsigned long mwdma_mask; unsigned long mwdma_mask;
unsigned long udma_mask; unsigned long udma_mask;
@ -689,38 +739,27 @@ static inline int ata_port_is_dummy(struct ata_port *ap)
return ap->ops == &ata_dummy_port_ops; return ap->ops == &ata_dummy_port_ops;
} }
extern void sata_print_link_status(struct ata_port *ap); extern void sata_print_link_status(struct ata_link *link);
extern void ata_port_probe(struct ata_port *); extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap); extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap); extern void sata_phy_reset(struct ata_port *ap);
extern void ata_bus_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap);
extern int sata_set_spd(struct ata_port *ap); extern int sata_set_spd(struct ata_link *link);
extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param, extern int sata_link_debounce(struct ata_link *link,
const unsigned long *params, unsigned long deadline);
extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
unsigned long deadline);
extern int ata_std_prereset(struct ata_link *link, unsigned long deadline);
extern int ata_std_softreset(struct ata_link *link, unsigned int *classes,
unsigned long deadline); unsigned long deadline);
extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param, extern int sata_link_hardreset(struct ata_link *link,
unsigned long deadline); const unsigned long *timing, unsigned long deadline);
extern int ata_std_prereset(struct ata_port *ap, unsigned long deadline); extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes,
unsigned long deadline);
extern int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing,
unsigned long deadline);
extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class,
unsigned long deadline); unsigned long deadline);
extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
extern void ata_port_disable(struct ata_port *); extern void ata_port_disable(struct ata_port *);
extern void ata_std_ports(struct ata_ioports *ioaddr); extern void ata_std_ports(struct ata_ioports *ioaddr);
#ifdef CONFIG_PCI
extern int ata_pci_init_one (struct pci_dev *pdev,
const struct ata_port_info * const * ppi);
extern void ata_pci_remove_one (struct pci_dev *pdev);
#ifdef CONFIG_PM
extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
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);
#endif
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports); extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
extern struct ata_host *ata_host_alloc_pinfo(struct device *dev, extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
const struct ata_port_info * const * ppi, int n_ports); const struct ata_port_info * const * ppi, int n_ports);
@ -746,12 +785,12 @@ extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
struct ata_port *ap); struct ata_port *ap);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
extern int sata_scr_valid(struct ata_port *ap); extern int sata_scr_valid(struct ata_link *link);
extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); extern int sata_scr_read(struct ata_link *link, int reg, u32 *val);
extern int sata_scr_write(struct ata_port *ap, int reg, u32 val); extern int sata_scr_write(struct ata_link *link, int reg, u32 val);
extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val); extern int sata_scr_write_flush(struct ata_link *link, int reg, u32 val);
extern int ata_port_online(struct ata_port *ap); extern int ata_link_online(struct ata_link *link);
extern int ata_port_offline(struct ata_port *ap); extern int ata_link_offline(struct ata_link *link);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
extern void ata_host_resume(struct ata_host *host); extern void ata_host_resume(struct ata_host *host);
@ -765,7 +804,8 @@ extern void ata_port_queue_task(struct ata_port *ap, work_func_t fn,
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
unsigned long interval_msec, unsigned long interval_msec,
unsigned long timeout_msec); unsigned long timeout_msec);
extern unsigned int ata_dev_try_classify(struct ata_port *, unsigned int, u8 *); extern unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
u8 *r_err);
/* /*
* Default driver ops implementations * Default driver ops implementations
@ -787,6 +827,7 @@ extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data); unsigned int buflen, int write_data);
extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data); unsigned int buflen, int write_data);
extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
@ -830,11 +871,8 @@ extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
int queue_depth); int queue_depth);
extern struct ata_device *ata_dev_pair(struct ata_device *adev); extern struct ata_device *ata_dev_pair(struct ata_device *adev);
extern int ata_do_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
extern u8 ata_irq_on(struct ata_port *ap); extern u8 ata_irq_on(struct ata_port *ap);
extern u8 ata_dummy_irq_on(struct ata_port *ap);
extern u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq);
extern u8 ata_dummy_irq_ack(struct ata_port *ap, unsigned int chk_drq);
extern int ata_cable_40wire(struct ata_port *ap); extern int ata_cable_40wire(struct ata_port *ap);
extern int ata_cable_80wire(struct ata_port *ap); extern int ata_cable_80wire(struct ata_port *ap);
@ -869,8 +907,29 @@ enum {
ATA_TIMING_CYCLE | ATA_TIMING_UDMA, ATA_TIMING_CYCLE | ATA_TIMING_UDMA,
}; };
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
extern int ata_acpi_cbl_80wire(struct ata_port *ap);
int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm);
int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *stm);
#else
static inline int ata_acpi_cbl_80wire(struct ata_port *ap) { return 0; }
#endif
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct pci_dev;
extern int ata_pci_init_one (struct pci_dev *pdev,
const struct ata_port_info * const * ppi);
extern void ata_pci_remove_one (struct pci_dev *pdev);
#ifdef CONFIG_PM
extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg);
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);
#endif
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
struct pci_bits { struct pci_bits {
unsigned int reg; /* PCI config register to read */ unsigned int reg; /* PCI config register to read */
unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */ unsigned int width; /* 1 (8 bit), 2 (16 bit), 4 (32 bit) */
@ -887,14 +946,30 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit
extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long); extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
/*
* PMP
*/
extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
extern int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline);
extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class);
extern void sata_pmp_do_eh(struct ata_port *ap,
ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset);
/* /*
* EH * EH
*/ */
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
extern void ata_port_schedule_eh(struct ata_port *ap); extern void ata_port_schedule_eh(struct ata_port *ap);
extern int ata_link_abort(struct ata_link *link);
extern int ata_port_abort(struct ata_port *ap); extern int ata_port_abort(struct ata_port *ap);
extern int ata_port_freeze(struct ata_port *ap); extern int ata_port_freeze(struct ata_port *ap);
extern int sata_async_notification(struct ata_port *ap);
extern void ata_eh_freeze_port(struct ata_port *ap); extern void ata_eh_freeze_port(struct ata_port *ap);
extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_thaw_port(struct ata_port *ap);
@ -912,14 +987,25 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
#define ata_port_printk(ap, lv, fmt, args...) \ #define ata_port_printk(ap, lv, fmt, args...) \
printk(lv"ata%u: "fmt, (ap)->print_id , ##args) printk(lv"ata%u: "fmt, (ap)->print_id , ##args)
#define ata_link_printk(link, lv, fmt, args...) do { \
if ((link)->ap->nr_pmp_links) \
printk(lv"ata%u.%02u: "fmt, (link)->ap->print_id, \
(link)->pmp , ##args); \
else \
printk(lv"ata%u: "fmt, (link)->ap->print_id , ##args); \
} while(0)
#define ata_dev_printk(dev, lv, fmt, args...) \ #define ata_dev_printk(dev, lv, fmt, args...) \
printk(lv"ata%u.%02u: "fmt, (dev)->ap->print_id, (dev)->devno , ##args) printk(lv"ata%u.%02u: "fmt, (dev)->link->ap->print_id, \
(dev)->link->pmp + (dev)->devno , ##args)
/* /*
* ata_eh_info helpers * ata_eh_info helpers
*/ */
extern void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); extern void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...); __attribute__ ((format (printf, 2, 3)));
extern void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
extern void ata_ehi_clear_desc(struct ata_eh_info *ehi); extern void ata_ehi_clear_desc(struct ata_eh_info *ehi);
static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi) static inline void ata_ehi_schedule_probe(struct ata_eh_info *ehi)
@ -933,9 +1019,20 @@ static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
{ {
ata_ehi_schedule_probe(ehi); ata_ehi_schedule_probe(ehi);
ehi->flags |= ATA_EHI_HOTPLUGGED; ehi->flags |= ATA_EHI_HOTPLUGGED;
ehi->action |= ATA_EH_ENABLE_LINK;
ehi->err_mask |= AC_ERR_ATA_BUS; ehi->err_mask |= AC_ERR_ATA_BUS;
} }
/*
* port description helpers
*/
extern void ata_port_desc(struct ata_port *ap, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#ifdef CONFIG_PCI
extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
const char *name);
#endif
/* /*
* qc helpers * qc helpers
*/ */
@ -991,12 +1088,14 @@ static inline unsigned int ata_tag_internal(unsigned int tag)
*/ */
static inline unsigned int ata_class_enabled(unsigned int class) static inline unsigned int ata_class_enabled(unsigned int class)
{ {
return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI ||
class == ATA_DEV_PMP || class == ATA_DEV_SEMB;
} }
static inline unsigned int ata_class_disabled(unsigned int class) static inline unsigned int ata_class_disabled(unsigned int class)
{ {
return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP; return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP ||
class == ATA_DEV_PMP_UNSUP || class == ATA_DEV_SEMB_UNSUP;
} }
static inline unsigned int ata_class_absent(unsigned int class) static inline unsigned int ata_class_absent(unsigned int class)
@ -1020,15 +1119,62 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev)
} }
/* /*
* port helpers * link helpers
*/ */
static inline int ata_port_max_devices(const struct ata_port *ap) static inline int ata_is_host_link(const struct ata_link *link)
{ {
if (ap->flags & ATA_FLAG_SLAVE_POSS) return link == &link->ap->link;
}
static inline int ata_link_max_devices(const struct ata_link *link)
{
if (ata_is_host_link(link) && link->ap->flags & ATA_FLAG_SLAVE_POSS)
return 2; return 2;
return 1; return 1;
} }
static inline int ata_link_active(struct ata_link *link)
{
return ata_tag_valid(link->active_tag) || link->sactive;
}
static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
{
if (ap->nr_pmp_links)
return ap->pmp_link;
return &ap->link;
}
static inline struct ata_link *ata_port_next_link(struct ata_link *link)
{
struct ata_port *ap = link->ap;
if (link == &ap->link) {
if (!ap->nr_pmp_links)
return NULL;
return ap->pmp_link;
}
if (++link - ap->pmp_link < ap->nr_pmp_links)
return link;
return NULL;
}
#define __ata_port_for_each_link(lk, ap) \
for ((lk) = &(ap)->link; (lk); (lk) = ata_port_next_link(lk))
#define ata_port_for_each_link(link, ap) \
for ((link) = ata_port_first_link(ap); (link); \
(link) = ata_port_next_link(link))
#define ata_link_for_each_dev(dev, link) \
for ((dev) = (link)->device; \
(dev) < (link)->device + ata_link_max_devices(link) || ((dev) = NULL); \
(dev)++)
#define ata_link_for_each_dev_reverse(dev, link) \
for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \
(dev) >= (link)->device || ((dev) = NULL); (dev)--)
static inline u8 ata_chk_status(struct ata_port *ap) static inline u8 ata_chk_status(struct ata_port *ap)
{ {
@ -1110,9 +1256,11 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
{ {
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
#ifdef ATA_DEBUG
if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
DPRINTK("ATA: abnormal status 0x%X on port 0x%p\n", ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n",
status, ap->ioaddr.status_addr); status);
#endif
return status; return status;
} }
@ -1149,7 +1297,7 @@ static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
{ {
memset(tf, 0, sizeof(*tf)); memset(tf, 0, sizeof(*tf));
tf->ctl = dev->ap->ctl; tf->ctl = dev->link->ap->ctl;
if (dev->devno == 0) if (dev->devno == 0)
tf->device = ATA_DEVICE_OBS; tf->device = ATA_DEVICE_OBS;
else else