diff options
Diffstat (limited to 'drivers/scsi/sata_nv.c')
-rw-r--r-- | drivers/scsi/sata_nv.c | 535 |
1 files changed, 285 insertions, 250 deletions
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 9f553081b5e8..5cc42c6054eb 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -44,7 +44,7 @@ #include <linux/libata.h> #define DRV_NAME "sata_nv" -#define DRV_VERSION "0.8" +#define DRV_VERSION "2.0" enum { NV_PORTS = 2, @@ -54,40 +54,25 @@ enum { NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT1_SCR_REG_OFFSET = 0x40, + /* INT_STATUS/ENABLE */ NV_INT_STATUS = 0x10, - NV_INT_STATUS_CK804 = 0x440, - NV_INT_STATUS_PDEV_INT = 0x01, - NV_INT_STATUS_PDEV_PM = 0x02, - NV_INT_STATUS_PDEV_ADDED = 0x04, - NV_INT_STATUS_PDEV_REMOVED = 0x08, - NV_INT_STATUS_SDEV_INT = 0x10, - NV_INT_STATUS_SDEV_PM = 0x20, - NV_INT_STATUS_SDEV_ADDED = 0x40, - NV_INT_STATUS_SDEV_REMOVED = 0x80, - NV_INT_STATUS_PDEV_HOTPLUG = (NV_INT_STATUS_PDEV_ADDED | - NV_INT_STATUS_PDEV_REMOVED), - NV_INT_STATUS_SDEV_HOTPLUG = (NV_INT_STATUS_SDEV_ADDED | - NV_INT_STATUS_SDEV_REMOVED), - NV_INT_STATUS_HOTPLUG = (NV_INT_STATUS_PDEV_HOTPLUG | - NV_INT_STATUS_SDEV_HOTPLUG), - NV_INT_ENABLE = 0x11, + NV_INT_STATUS_CK804 = 0x440, NV_INT_ENABLE_CK804 = 0x441, - NV_INT_ENABLE_PDEV_MASK = 0x01, - NV_INT_ENABLE_PDEV_PM = 0x02, - NV_INT_ENABLE_PDEV_ADDED = 0x04, - NV_INT_ENABLE_PDEV_REMOVED = 0x08, - NV_INT_ENABLE_SDEV_MASK = 0x10, - NV_INT_ENABLE_SDEV_PM = 0x20, - NV_INT_ENABLE_SDEV_ADDED = 0x40, - NV_INT_ENABLE_SDEV_REMOVED = 0x80, - NV_INT_ENABLE_PDEV_HOTPLUG = (NV_INT_ENABLE_PDEV_ADDED | - NV_INT_ENABLE_PDEV_REMOVED), - NV_INT_ENABLE_SDEV_HOTPLUG = (NV_INT_ENABLE_SDEV_ADDED | - NV_INT_ENABLE_SDEV_REMOVED), - NV_INT_ENABLE_HOTPLUG = (NV_INT_ENABLE_PDEV_HOTPLUG | - NV_INT_ENABLE_SDEV_HOTPLUG), + /* INT_STATUS/ENABLE bits */ + NV_INT_DEV = 0x01, + NV_INT_PM = 0x02, + NV_INT_ADDED = 0x04, + NV_INT_REMOVED = 0x08, + + NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ + + NV_INT_ALL = 0x0f, + NV_INT_MASK = NV_INT_DEV | + NV_INT_ADDED | NV_INT_REMOVED, + + /* INT_CONFIG */ NV_INT_CONFIG = 0x12, NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI @@ -97,23 +82,27 @@ enum { }; static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs); +static void nv_ck804_host_stop(struct ata_host_set *host_set); +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static void nv_host_stop (struct ata_host_set *host_set); -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug(struct ata_host_set *host_set); -static int nv_check_hotplug(struct ata_host_set *host_set); -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent); -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set); -static int nv_check_hotplug_ck804(struct ata_host_set *host_set); + +static void nv_nf2_freeze(struct ata_port *ap); +static void nv_nf2_thaw(struct ata_port *ap); +static void nv_ck804_freeze(struct ata_port *ap); +static void nv_ck804_thaw(struct ata_port *ap); +static void nv_error_handler(struct ata_port *ap); enum nv_host_type { GENERIC, NFORCE2, - NFORCE3, + NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */ CK804 }; @@ -140,6 +129,16 @@ static const struct pci_device_id nv_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, + { PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC }, { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, @@ -149,46 +148,6 @@ static const struct pci_device_id nv_pci_tbl[] = { { 0, } /* terminate list */ }; -struct nv_host_desc -{ - enum nv_host_type host_type; - void (*enable_hotplug)(struct ata_probe_ent *probe_ent); - void (*disable_hotplug)(struct ata_host_set *host_set); - int (*check_hotplug)(struct ata_host_set *host_set); - -}; -static struct nv_host_desc nv_device_tbl[] = { - { - .host_type = GENERIC, - .enable_hotplug = NULL, - .disable_hotplug= NULL, - .check_hotplug = NULL, - }, - { - .host_type = NFORCE2, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, - }, - { - .host_type = NFORCE3, - .enable_hotplug = nv_enable_hotplug, - .disable_hotplug= nv_disable_hotplug, - .check_hotplug = nv_check_hotplug, - }, - { .host_type = CK804, - .enable_hotplug = nv_enable_hotplug_ck804, - .disable_hotplug= nv_disable_hotplug_ck804, - .check_hotplug = nv_check_hotplug_ck804, - }, -}; - -struct nv_host -{ - struct nv_host_desc *host_desc; - unsigned long host_flags; -}; - static struct pci_driver nv_pci_driver = { .name = DRV_NAME, .id_table = nv_pci_tbl, @@ -210,51 +169,119 @@ static struct scsi_host_template nv_sht = { .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 const struct ata_port_operations nv_ops = { +static const struct ata_port_operations nv_generic_ops = { .port_disable = ata_port_disable, .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, - .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, - .irq_handler = nv_interrupt, + .freeze = ata_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_generic_interrupt, .irq_clear = ata_bmdma_irq_clear, .scr_read = nv_scr_read, .scr_write = nv_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = nv_host_stop, + .host_stop = ata_pci_host_stop, }; -/* FIXME: The hardware provides the necessary SATA PHY controls - * to support ATA_FLAG_SATA_RESET. However, it is currently - * necessary to disable that flag, to solve misdetection problems. - * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. - * - * This problem really needs to be investigated further. But in the - * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. - */ -static struct ata_port_info nv_port_info = { - .sht = &nv_sht, - .host_flags = ATA_FLAG_SATA | - /* ATA_FLAG_SATA_RESET | */ - ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY, - .pio_mask = NV_PIO_MASK, - .mwdma_mask = NV_MWDMA_MASK, - .udma_mask = NV_UDMA_MASK, - .port_ops = &nv_ops, +static const struct ata_port_operations nv_nf2_ops = { + .port_disable = ata_port_disable, + .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, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .freeze = nv_nf2_freeze, + .thaw = nv_nf2_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_nf2_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = ata_pci_host_stop, +}; + +static const struct ata_port_operations nv_ck804_ops = { + .port_disable = ata_port_disable, + .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, + .bmdma_setup = ata_bmdma_setup, + .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, + .error_handler = nv_error_handler, + .post_internal_cmd = ata_bmdma_post_internal_cmd, + .data_xfer = ata_pio_data_xfer, + .irq_handler = nv_ck804_interrupt, + .irq_clear = ata_bmdma_irq_clear, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, + .host_stop = nv_ck804_host_stop, +}; + +static struct ata_port_info nv_port_info[] = { + /* generic */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_generic_ops, + }, + /* nforce2/3 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_nf2_ops, + }, + /* ck804 */ + { + .sht = &nv_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .pio_mask = NV_PIO_MASK, + .mwdma_mask = NV_MWDMA_MASK, + .udma_mask = NV_UDMA_MASK, + .port_ops = &nv_ck804_ops, + }, }; MODULE_AUTHOR("NVIDIA"); @@ -263,11 +290,10 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, nv_pci_tbl); MODULE_VERSION(DRV_VERSION); -static irqreturn_t nv_interrupt (int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) { struct ata_host_set *host_set = dev_instance; - struct nv_host *host = host_set->private_data; unsigned int i; unsigned int handled = 0; unsigned long flags; @@ -279,11 +305,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); else // No request pending? Clear interrupt status @@ -293,14 +319,88 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, } - if (host->host_desc->check_hotplug) - handled += host->host_desc->check_hotplug(host_set); - spin_unlock_irqrestore(&host_set->lock, flags); return IRQ_RETVAL(handled); } +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); + int handled; + + /* freeze if hotplugged */ + if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { + ata_port_freeze(ap); + return 1; + } + + /* bail out if not our interrupt */ + if (!(irq_stat & NV_INT_DEV)) + return 0; + + /* DEV interrupt w/ no active qc? */ + if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { + ata_check_status(ap); + return 1; + } + + /* handle interrupt */ + handled = ata_host_intr(ap, qc); + if (unlikely(!handled)) { + /* spurious, clear it */ + ata_check_status(ap); + } + + return 1; +} + +static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat) +{ + int i, handled = 0; + + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; + + if (ap && !(ap->flags & ATA_FLAG_DISABLED)) + handled += nv_host_intr(ap, irq_stat); + + irq_stat >>= NV_INT_PORT_SHIFT; + } + + return IRQ_RETVAL(handled); +} + +static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + u8 irq_stat; + irqreturn_t ret; + + spin_lock(&host_set->lock); + irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock(&host_set->lock); + + return ret; +} + +static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, + struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + u8 irq_stat; + irqreturn_t ret; + + spin_lock(&host_set->lock); + irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804); + ret = nv_do_interrupt(host_set, irq_stat); + spin_unlock(&host_set->lock); + + return ret; +} + static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) @@ -317,23 +417,74 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void nv_host_stop (struct ata_host_set *host_set) +static void nv_nf2_freeze(struct ata_port *ap) { - struct nv_host *host = host_set->private_data; + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; - // Disable hotplug event interrupts. - if (host->host_desc->disable_hotplug) - host->host_desc->disable_hotplug(host_set); + mask = inb(scr_addr + NV_INT_ENABLE); + mask &= ~(NV_INT_ALL << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} - kfree(host); +static void nv_nf2_thaw(struct ata_port *ap) +{ + unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; - ata_pci_host_stop(host_set); + outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS); + + mask = inb(scr_addr + NV_INT_ENABLE); + mask |= (NV_INT_MASK << shift); + outb(mask, scr_addr + NV_INT_ENABLE); +} + +static void nv_ck804_freeze(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask &= ~(NV_INT_ALL << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static void nv_ck804_thaw(struct ata_port *ap) +{ + void __iomem *mmio_base = ap->host_set->mmio_base; + int shift = ap->port_no * NV_INT_PORT_SHIFT; + u8 mask; + + writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804); + + mask = readb(mmio_base + NV_INT_ENABLE_CK804); + mask |= (NV_INT_MASK << shift); + writeb(mask, mmio_base + NV_INT_ENABLE_CK804); +} + +static int nv_hardreset(struct ata_port *ap, unsigned int *class) +{ + unsigned int dummy; + + /* SATA hardreset fails to retrieve proper device signature on + * some controllers. Don't classify on hardreset. For more + * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + */ + return sata_std_hardreset(ap, &dummy); +} + +static void nv_error_handler(struct ata_port *ap) +{ + ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, + nv_hardreset, ata_std_postreset); } static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version = 0; - struct nv_host *host; struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; int pci_dev_busy = 0; @@ -370,24 +521,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = -ENOMEM; - ppi = &nv_port_info; + ppi = &nv_port_info[ent->driver_data]; probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) goto err_out_regions; - host = kmalloc(sizeof(struct nv_host), GFP_KERNEL); - if (!host) - goto err_out_free_ent; - - memset(host, 0, sizeof(struct nv_host)); - host->host_desc = &nv_device_tbl[ent->driver_data]; - - probe_ent->private_data = host; - probe_ent->mmio_base = pci_iomap(pdev, 5, 0); if (!probe_ent->mmio_base) { rc = -EIO; - goto err_out_free_host; + goto err_out_free_ent; } base = (unsigned long)probe_ent->mmio_base; @@ -395,24 +537,27 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET; probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET; + /* enable SATA space for CK804 */ + if (ent->driver_data == CK804) { + u8 regval; + + pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); + regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; + pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); + } + pci_set_master(pdev); rc = ata_device_add(probe_ent); if (rc != NV_PORTS) goto err_out_iounmap; - // Enable hotplug event interrupts. - if (host->host_desc->enable_hotplug) - host->host_desc->enable_hotplug(probe_ent); - kfree(probe_ent); return 0; err_out_iounmap: pci_iounmap(pdev, probe_ent->mmio_base); -err_out_free_host: - kfree(host); err_out_free_ent: kfree(probe_ent); err_out_regions: @@ -424,127 +569,17 @@ err_out: return rc; } -static void nv_enable_hotplug(struct ata_probe_ent *probe_ent) -{ - u8 intr_mask; - - outb(NV_INT_STATUS_HOTPLUG, - probe_ent->port[0].scr_addr + NV_INT_STATUS); - - intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE); -} - -static void nv_disable_hotplug(struct ata_host_set *host_set) -{ - u8 intr_mask; - - intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE); -} - -static int nv_check_hotplug(struct ata_host_set *host_set) -{ - u8 intr_status; - - intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - // Clear interrupt status. - outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; -} - -static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent) -{ - struct pci_dev *pdev = to_pci_dev(probe_ent->dev); - u8 intr_mask; - u8 regval; - - pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); - regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN; - pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); - - writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804); - - intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804); - intr_mask |= NV_INT_ENABLE_HOTPLUG; - - writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804); -} - -static void nv_disable_hotplug_ck804(struct ata_host_set *host_set) +static void nv_ck804_host_stop(struct ata_host_set *host_set) { struct pci_dev *pdev = to_pci_dev(host_set->dev); - u8 intr_mask; u8 regval; - intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804); - - intr_mask &= ~(NV_INT_ENABLE_HOTPLUG); - - writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804); - + /* disable SATA space for CK804 */ pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val); regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN; pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval); -} - -static int nv_check_hotplug_ck804(struct ata_host_set *host_set) -{ - u8 intr_status; - intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804); - - // Clear interrupt status. - writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804); - - if (intr_status & NV_INT_STATUS_HOTPLUG) { - if (intr_status & NV_INT_STATUS_PDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Primary device added\n"); - - if (intr_status & NV_INT_STATUS_PDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Primary device removed\n"); - - if (intr_status & NV_INT_STATUS_SDEV_ADDED) - printk(KERN_WARNING "nv_sata: " - "Secondary device added\n"); - - if (intr_status & NV_INT_STATUS_SDEV_REMOVED) - printk(KERN_WARNING "nv_sata: " - "Secondary device removed\n"); - - return 1; - } - - return 0; + ata_pci_host_stop(host_set); } static int __init nv_init(void) |